From: Haimin Zhang tcs_kernel@tencent.com
stable inclusion from stable-v5.10.110 commit 8d3f4ad43054619379ccc697cfcbdb2c266800d8 category: bugfix bugzilla: 186606, https://gitee.com/src-openeuler/kernel/issues/I53SSV CVE: CVE-2022-1353
--------------------------------
[ Upstream commit 9a564bccb78a76740ea9d75a259942df8143d02c ]
Add __GFP_ZERO flag for compose_sadb_supported in function pfkey_register to initialize the buffer of supp_skb to fix a kernel-info-leak issue. 1) Function pfkey_register calls compose_sadb_supported to request a sk_buff. 2) compose_sadb_supported calls alloc_sbk to allocate a sk_buff, but it doesn't zero it. 3) If auth_len is greater 0, then compose_sadb_supported treats the memory as a struct sadb_supported and begins to initialize. But it just initializes the field sadb_supported_len and field sadb_supported_exttype without field sadb_supported_reserved.
Reported-by: TCS Robot tcs_robot@tencent.com Signed-off-by: Haimin Zhang tcs_kernel@tencent.com Signed-off-by: Steffen Klassert steffen.klassert@secunet.com Signed-off-by: Sasha Levin sashal@kernel.org Signed-off-by: Xu Jia xujia39@huawei.com Reviewed-by: Wei Yongjun weiyongjun1@huawei.com Reviewed-by: Wang Weiyang wangweiyang2@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- net/key/af_key.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/key/af_key.c b/net/key/af_key.c index ef9b4ac03e7b..b95684b8903e 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -1703,7 +1703,7 @@ static int pfkey_register(struct sock *sk, struct sk_buff *skb, const struct sad
xfrm_probe_algs();
- supp_skb = compose_sadb_supported(hdr, GFP_KERNEL); + supp_skb = compose_sadb_supported(hdr, GFP_KERNEL | __GFP_ZERO); if (!supp_skb) { if (hdr->sadb_msg_satype != SADB_SATYPE_UNSPEC) pfk->registered &= ~(1<<hdr->sadb_msg_satype);
From: Sean V Kelley sean.v.kelley@intel.com
mainline inclusion from mainline-v5.11-rc1 commit 50cc18fcd305 category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I51U4T CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
------------------------------------------------------------------------
If an OS has not been granted AER control via _OSC, it should not make changes to PCI_ERR_ROOT_COMMAND and PCI_ERR_ROOT_STATUS related registers. Per section 4.5.1 of the System Firmware Intermediary (SFI) _OSC and DPC Updates ECN [1], this bit also covers these aspects of the PCI Express Advanced Error Reporting. Based on the above and earlier discussion [2], make the following changes:
Add a check for the native case (i.e., AER control via _OSC)
Note that the previous "clear, reset, enable" order suggests that the reset might cause errors that we should ignore. After this commit, those errors (if any) will remain logged in the PCI_ERR_ROOT_STATUS register.
[1] System Firmware Intermediary (SFI) _OSC and DPC Updates ECN, Feb 24, 2020, affecting PCI Firmware Specification, Rev. 3.2 https://members.pcisig.com/wg/PCI-SIG/document/14076 [2] https://lore.kernel.org/linux-pci/20201020162820.GA370938@bjorn-Precision-55...
Link: https://lore.kernel.org/r/20201121001036.8560-2-sean.v.kelley@intel.com Tested-by: Jonathan Cameron Jonathan.Cameron@huawei.com # non-native/no RCEC Signed-off-by: Sean V Kelley sean.v.kelley@intel.com Signed-off-by: Bjorn Helgaas bhelgaas@google.com Signed-off-by: Jiefeng Ou oujiefeng@h-partners.com Reviewed-by: Jay Fang f.fangjian@huawei.com Reviewed-by: Xiongfeng Wang wangxiongfeng2@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/pci/pcie/aer.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-)
diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c index 65dff5f3457a..6fe2d4ef0635 100644 --- a/drivers/pci/pcie/aer.c +++ b/drivers/pci/pcie/aer.c @@ -1361,23 +1361,26 @@ static pci_ers_result_t aer_root_reset(struct pci_dev *dev) u32 reg32; int rc;
- - /* Disable Root's interrupt in response to error messages */ - pci_read_config_dword(dev, aer + PCI_ERR_ROOT_COMMAND, ®32); - reg32 &= ~ROOT_PORT_INTR_ON_MESG_MASK; - pci_write_config_dword(dev, aer + PCI_ERR_ROOT_COMMAND, reg32); + if (pcie_aer_is_native(dev)) { + /* Disable Root's interrupt in response to error messages */ + pci_read_config_dword(dev, aer + PCI_ERR_ROOT_COMMAND, ®32); + reg32 &= ~ROOT_PORT_INTR_ON_MESG_MASK; + pci_write_config_dword(dev, aer + PCI_ERR_ROOT_COMMAND, reg32); + }
rc = pci_bus_error_reset(dev); - pci_info(dev, "Root Port link has been reset\n"); + pci_info(dev, "Root Port link has been reset (%d)\n", rc);
- /* Clear Root Error Status */ - pci_read_config_dword(dev, aer + PCI_ERR_ROOT_STATUS, ®32); - pci_write_config_dword(dev, aer + PCI_ERR_ROOT_STATUS, reg32); + if (pcie_aer_is_native(dev)) { + /* Clear Root Error Status */ + pci_read_config_dword(dev, aer + PCI_ERR_ROOT_STATUS, ®32); + pci_write_config_dword(dev, aer + PCI_ERR_ROOT_STATUS, reg32);
- /* Enable Root Port's interrupt in response to error messages */ - pci_read_config_dword(dev, aer + PCI_ERR_ROOT_COMMAND, ®32); - reg32 |= ROOT_PORT_INTR_ON_MESG_MASK; - pci_write_config_dword(dev, aer + PCI_ERR_ROOT_COMMAND, reg32); + /* Enable Root Port's interrupt in response to error messages */ + pci_read_config_dword(dev, aer + PCI_ERR_ROOT_COMMAND, ®32); + reg32 |= ROOT_PORT_INTR_ON_MESG_MASK; + pci_write_config_dword(dev, aer + PCI_ERR_ROOT_COMMAND, reg32); + }
return rc ? PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_RECOVERED; }
From: Qiuxu Zhuo qiuxu.zhuo@intel.com
mainline inclusion from mainline-v5.11-rc1 commit c9d659b60770 category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I51U4T CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
--------------------------------------------------------------------------
If a Root Complex Integrated Endpoint (RCiEP) is implemented, it may signal errors through a Root Complex Event Collector (RCEC). Each RCiEP must be associated with no more than one RCEC.
For an RCEC (which is technically not a Bridge), error messages "received" from associated RCiEPs must be enabled for "transmission" in order to cause a System Error via the Root Control register or (when the Advanced Error Reporting Capability is present) reporting via the Root Error Command register and logging in the Root Error Status register and Error Source Identification register.
Given the commonality with Root Ports and the need to also support AER and PME services for RCECs, extend the Root Port driver to support RCEC devices by adding the RCEC Class ID to the driver structure.
Co-developed-by: Sean V Kelley sean.v.kelley@intel.com Link: https://lore.kernel.org/r/20201121001036.8560-3-sean.v.kelley@intel.com Tested-by: Jonathan Cameron Jonathan.Cameron@huawei.com # non-native/no RCEC Signed-off-by: Sean V Kelley sean.v.kelley@intel.com Signed-off-by: Qiuxu Zhuo qiuxu.zhuo@intel.com Signed-off-by: Bjorn Helgaas bhelgaas@google.com Signed-off-by: Jiefeng Ou oujiefeng@h-partners.com Reviewed-by: Jonathan Cameron Jonathan.Cameron@huawei.com Reviewed-by: Kuppuswamy Sathyanarayanan sathyanarayanan.kuppuswamy@linux.intel.com Reviewed-by: Jay Fang f.fangjian@huawei.com Reviewed-by: Xiongfeng Wang wangxiongfeng2@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/pci/pcie/portdrv_pci.c | 5 ++++- include/linux/pci_ids.h | 1 + include/uapi/linux/pci_regs.h | 7 +++++++ 3 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c index d4559cf88f79..26259630fd10 100644 --- a/drivers/pci/pcie/portdrv_pci.c +++ b/drivers/pci/pcie/portdrv_pci.c @@ -106,7 +106,8 @@ static int pcie_portdrv_probe(struct pci_dev *dev, if (!pci_is_pcie(dev) || ((pci_pcie_type(dev) != PCI_EXP_TYPE_ROOT_PORT) && (pci_pcie_type(dev) != PCI_EXP_TYPE_UPSTREAM) && - (pci_pcie_type(dev) != PCI_EXP_TYPE_DOWNSTREAM))) + (pci_pcie_type(dev) != PCI_EXP_TYPE_DOWNSTREAM) && + (pci_pcie_type(dev) != PCI_EXP_TYPE_RC_EC))) return -ENODEV;
status = pcie_port_device_register(dev); @@ -195,6 +196,8 @@ static const struct pci_device_id port_pci_ids[] = { { PCI_DEVICE_CLASS(((PCI_CLASS_BRIDGE_PCI << 8) | 0x00), ~0) }, /* subtractive decode PCI-to-PCI bridge, class type is 060401h */ { PCI_DEVICE_CLASS(((PCI_CLASS_BRIDGE_PCI << 8) | 0x01), ~0) }, + /* handle any Root Complex Event Collector */ + { PCI_DEVICE_CLASS(((PCI_CLASS_SYSTEM_RCEC << 8) | 0x00), ~0) }, { }, };
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index f8da3669b6b0..a1069c76e9bc 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -81,6 +81,7 @@ #define PCI_CLASS_SYSTEM_RTC 0x0803 #define PCI_CLASS_SYSTEM_PCI_HOTPLUG 0x0804 #define PCI_CLASS_SYSTEM_SDHCI 0x0805 +#define PCI_CLASS_SYSTEM_RCEC 0x0807 #define PCI_CLASS_SYSTEM_OTHER 0x0880
#define PCI_BASE_CLASS_INPUT 0x09 diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h index 142b184eca8b..7e0d526dd96f 100644 --- a/include/uapi/linux/pci_regs.h +++ b/include/uapi/linux/pci_regs.h @@ -837,6 +837,13 @@ #define PCI_PWR_CAP_BUDGET(x) ((x) & 1) /* Included in system budget */ #define PCI_EXT_CAP_PWR_SIZEOF 16
+/* Root Complex Event Collector Endpoint Association */ +#define PCI_RCEC_RCIEP_BITMAP 4 /* Associated Bitmap for RCiEPs */ +#define PCI_RCEC_BUSN 8 /* RCEC Associated Bus Numbers */ +#define PCI_RCEC_BUSN_REG_VER 0x02 /* Least version with BUSN present */ +#define PCI_RCEC_BUSN_NEXT(x) (((x) >> 8) & 0xff) +#define PCI_RCEC_BUSN_LAST(x) (((x) >> 16) & 0xff) + /* Vendor-Specific (VSEC, PCI_EXT_CAP_ID_VNDR) */ #define PCI_VNDR_HEADER 4 /* Vendor-Specific Header */ #define PCI_VNDR_HEADER_ID(x) ((x) & 0xffff)
From: Sean V Kelley sean.v.kelley@intel.com
mainline inclusion from mainline-v5.11-rc1 commit 90655631988f category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I51U4T CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
--------------------------------------------------------------------------
Extend support for Root Complex Event Collectors by decoding and caching the RCEC Endpoint Association Extended Capabilities when enumerating. Use that cached information for later error source reporting. See PCIe r5.0, sec 7.9.10.
Co-developed-by: Qiuxu Zhuo qiuxu.zhuo@intel.com Link: https://lore.kernel.org/r/20201121001036.8560-4-sean.v.kelley@intel.com Tested-by: Jonathan Cameron Jonathan.Cameron@huawei.com # non-native/no RCEC Signed-off-by: Qiuxu Zhuo qiuxu.zhuo@intel.com Signed-off-by: Sean V Kelley sean.v.kelley@intel.com Signed-off-by: Bjorn Helgaas bhelgaas@google.com Signed-off-by: Jiefeng Ou oujiefeng@h-partners.com Reviewed-by: Jonathan Cameron Jonathan.Cameron@huawei.com Reviewed-by: Jay Fang f.fangjian@huawei.com Reviewed-by: Xiongfeng Wang wangxiongfeng2@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/pci/pci.h | 17 +++++++++++ drivers/pci/pcie/Makefile | 2 +- drivers/pci/pcie/rcec.c | 59 +++++++++++++++++++++++++++++++++++++++ drivers/pci/probe.c | 2 ++ include/linux/pci.h | 4 +++ 5 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 drivers/pci/pcie/rcec.c
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 9a4e34814005..b32330f69326 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -459,6 +459,15 @@ int aer_get_device_error_info(struct pci_dev *dev, struct aer_err_info *info); void aer_print_error(struct pci_dev *dev, struct aer_err_info *info); #endif /* CONFIG_PCIEAER */
+#ifdef CONFIG_PCIEPORTBUS +/* Cached RCEC Endpoint Association */ +struct rcec_ea { + u8 nextbusn; + u8 lastbusn; + u32 bitmap; +}; +#endif + #ifdef CONFIG_PCIE_DPC void pci_save_dpc_state(struct pci_dev *dev); void pci_restore_dpc_state(struct pci_dev *dev); @@ -473,6 +482,14 @@ static inline void pci_dpc_init(struct pci_dev *pdev) {} static inline bool pci_dpc_recovered(struct pci_dev *pdev) { return false; } #endif
+#ifdef CONFIG_PCIEPORTBUS +void pci_rcec_init(struct pci_dev *dev); +void pci_rcec_exit(struct pci_dev *dev); +#else +static inline void pci_rcec_init(struct pci_dev *dev) {} +static inline void pci_rcec_exit(struct pci_dev *dev) {} +#endif + #ifdef CONFIG_PCI_ATS /* Address Translation Service */ void pci_ats_init(struct pci_dev *dev); diff --git a/drivers/pci/pcie/Makefile b/drivers/pci/pcie/Makefile index 9a7085668466..b2980db88cc0 100644 --- a/drivers/pci/pcie/Makefile +++ b/drivers/pci/pcie/Makefile @@ -2,7 +2,7 @@ # # Makefile for PCI Express features and port driver
-pcieportdrv-y := portdrv_core.o portdrv_pci.o err.o +pcieportdrv-y := portdrv_core.o portdrv_pci.o err.o rcec.o
obj-$(CONFIG_PCIEPORTBUS) += pcieportdrv.o
diff --git a/drivers/pci/pcie/rcec.c b/drivers/pci/pcie/rcec.c new file mode 100644 index 000000000000..038e9d706d5f --- /dev/null +++ b/drivers/pci/pcie/rcec.c @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Root Complex Event Collector Support + * + * Authors: + * Sean V Kelley sean.v.kelley@intel.com + * Qiuxu Zhuo qiuxu.zhuo@intel.com + * + * Copyright (C) 2020 Intel Corp. + */ + +#include <linux/kernel.h> +#include <linux/pci.h> +#include <linux/pci_regs.h> + +#include "../pci.h" + +void pci_rcec_init(struct pci_dev *dev) +{ + struct rcec_ea *rcec_ea; + u32 rcec, hdr, busn; + u8 ver; + + /* Only for Root Complex Event Collectors */ + if (pci_pcie_type(dev) != PCI_EXP_TYPE_RC_EC) + return; + + rcec = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_RCEC); + if (!rcec) + return; + + rcec_ea = kzalloc(sizeof(*rcec_ea), GFP_KERNEL); + if (!rcec_ea) + return; + + pci_read_config_dword(dev, rcec + PCI_RCEC_RCIEP_BITMAP, + &rcec_ea->bitmap); + + /* Check whether RCEC BUSN register is present */ + pci_read_config_dword(dev, rcec, &hdr); + ver = PCI_EXT_CAP_VER(hdr); + if (ver >= PCI_RCEC_BUSN_REG_VER) { + pci_read_config_dword(dev, rcec + PCI_RCEC_BUSN, &busn); + rcec_ea->nextbusn = PCI_RCEC_BUSN_NEXT(busn); + rcec_ea->lastbusn = PCI_RCEC_BUSN_LAST(busn); + } else { + /* Avoid later ver check by setting nextbusn */ + rcec_ea->nextbusn = 0xff; + rcec_ea->lastbusn = 0x00; + } + + dev->rcec_ea = rcec_ea; +} + +void pci_rcec_exit(struct pci_dev *dev) +{ + kfree(dev->rcec_ea); + dev->rcec_ea = NULL; +} diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 6a54bdcd5631..5a926c883a89 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -2222,6 +2222,7 @@ static void pci_configure_device(struct pci_dev *dev) static void pci_release_capabilities(struct pci_dev *dev) { pci_aer_exit(dev); + pci_rcec_exit(dev); pci_vpd_release(dev); pci_iov_release(dev); pci_free_cap_save_buffers(dev); @@ -2422,6 +2423,7 @@ static void pci_init_capabilities(struct pci_dev *dev) pci_ptm_init(dev); /* Precision Time Measurement */ pci_aer_init(dev); /* Advanced Error Reporting */ pci_dpc_init(dev); /* Downstream Port Containment */ + pci_rcec_init(dev); /* Root Complex Event Collector */
pcie_report_downtraining(dev);
diff --git a/include/linux/pci.h b/include/linux/pci.h index ff6236a3dd6b..9f8b44ffabff 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -307,6 +307,7 @@ struct pcie_link_state; struct pci_vpd; struct pci_sriov; struct pci_p2pdma; +struct rcec_ea;
/* The pci_dev structure describes PCI devices */ struct pci_dev { @@ -329,6 +330,9 @@ struct pci_dev { #ifdef CONFIG_PCIEAER u16 aer_cap; /* AER capability offset */ struct aer_stats *aer_stats; /* AER stats for this device */ +#endif +#ifdef CONFIG_PCIEPORTBUS + struct rcec_ea *rcec_ea; /* RCEC cached endpoint association */ #endif u8 pcie_cap; /* PCIe capability offset */ u8 msi_cap; /* MSI capability offset */
From: Sean V Kelley sean.v.kelley@intel.com
mainline inclusion from mainline-v5.11-rc1 commit 8f1bbfbc3596 category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I51U4T CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
--------------------------------------------------------------------------
reset_link() appears to be misnamed. The point is to reset any devices below a given bridge, so rename it to reset_subordinates() to make it clear that we are passing a bridge with the intent to reset the devices below it.
Link: https://lore.kernel.org/r/20201121001036.8560-5-sean.v.kelley@intel.com Tested-by: Jonathan Cameron Jonathan.Cameron@huawei.com # non-native/no RCEC Signed-off-by: Sean V Kelley sean.v.kelley@intel.com Signed-off-by: Bjorn Helgaas bhelgaas@google.com Signed-off-by: Jiefeng Ou oujiefeng@h-partners.com Reviewed-by: Kuppuswamy Sathyanarayanan sathyanarayanan.kuppuswamy@linux.intel.com Acked-by: Jonathan Cameron Jonathan.Cameron@huawei.com Reviewed-by: Jay Fang f.fangjian@huawei.com Reviewed-by: Xiongfeng Wang wangxiongfeng2@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/pci/pci.h | 4 ++-- drivers/pci/pcie/err.c | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index b32330f69326..693983e1de5f 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -585,8 +585,8 @@ static inline int pci_dev_specific_disable_acs_redir(struct pci_dev *dev)
/* PCI error reporting and recovery */ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev, - pci_channel_state_t state, - pci_ers_result_t (*reset_link)(struct pci_dev *pdev)); + pci_channel_state_t state, + pci_ers_result_t (*reset_subordinates)(struct pci_dev *pdev));
bool pcie_wait_for_link(struct pci_dev *pdev, bool active); #ifdef CONFIG_PCIEASPM diff --git a/drivers/pci/pcie/err.c b/drivers/pci/pcie/err.c index c543f419d8f9..db149c6ce4fb 100644 --- a/drivers/pci/pcie/err.c +++ b/drivers/pci/pcie/err.c @@ -147,8 +147,8 @@ static int report_resume(struct pci_dev *dev, void *data) }
pci_ers_result_t pcie_do_recovery(struct pci_dev *dev, - pci_channel_state_t state, - pci_ers_result_t (*reset_link)(struct pci_dev *pdev)) + pci_channel_state_t state, + pci_ers_result_t (*reset_subordinates)(struct pci_dev *pdev)) { pci_ers_result_t status = PCI_ERS_RESULT_CAN_RECOVER; struct pci_bus *bus; @@ -165,9 +165,9 @@ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev, pci_dbg(dev, "broadcast error_detected message\n"); if (state == pci_channel_io_frozen) { pci_walk_bus(bus, report_frozen_detected, &status); - status = reset_link(dev); + status = reset_subordinates(dev); if (status != PCI_ERS_RESULT_RECOVERED) { - pci_warn(dev, "link reset failed\n"); + pci_warn(dev, "subordinate device reset failed\n"); goto failed; } } else {
From: Sean V Kelley sean.v.kelley@intel.com
mainline inclusion from mainline-v5.11-rc1 commit 5d69dcc9f839 category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I51U4T CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
--------------------------------------------------------------------------
Use pci_upstream_bridge() in place of dev->bus->self. No functional change intended.
Link: https://lore.kernel.org/r/20201121001036.8560-6-sean.v.kelley@intel.com Tested-by: Jonathan Cameron Jonathan.Cameron@huawei.com # non-native/no RCEC Signed-off-by: Sean V Kelley sean.v.kelley@intel.com Signed-off-by: Bjorn Helgaas bhelgaas@google.com Signed-off-by: Jiefeng Ou oujiefeng@h-partners.com Reviewed-by: Kuppuswamy Sathyanarayanan sathyanarayanan.kuppuswamy@linux.intel.com Acked-by: Jonathan Cameron Jonathan.Cameron@huawei.com Reviewed-by: Jay Fang f.fangjian@huawei.com Reviewed-by: Xiongfeng Wang wangxiongfeng2@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/pci/pcie/err.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/pci/pcie/err.c b/drivers/pci/pcie/err.c index db149c6ce4fb..05f61da5ed9d 100644 --- a/drivers/pci/pcie/err.c +++ b/drivers/pci/pcie/err.c @@ -159,7 +159,7 @@ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev, */ if (!(pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT || pci_pcie_type(dev) == PCI_EXP_TYPE_DOWNSTREAM)) - dev = dev->bus->self; + dev = pci_upstream_bridge(dev); bus = dev->subordinate;
pci_dbg(dev, "broadcast error_detected message\n");
From: Sean V Kelley sean.v.kelley@intel.com
mainline inclusion from mainline-v5.11-rc1 commit 480ef7cb9fce category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I51U4T CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
--------------------------------------------------------------------------
Instead of calling pci_pcie_type(dev) twice, call it once and save the result. No functional change intended.
Link: https://lore.kernel.org/r/20201121001036.8560-7-sean.v.kelley@intel.com Tested-by: Jonathan Cameron Jonathan.Cameron@huawei.com # non-native/no RCEC Signed-off-by: Sean V Kelley sean.v.kelley@intel.com Signed-off-by: Bjorn Helgaas bhelgaas@google.com Signed-off-by: Jiefeng Ou oujiefeng@h-partners.com Acked-by: Jonathan Cameron Jonathan.Cameron@huawei.com Reviewed-by: Jay Fang f.fangjian@huawei.com Reviewed-by: Xiongfeng Wang wangxiongfeng2@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/pci/pcie/aer.c | 5 +++-- drivers/pci/pcie/err.c | 5 +++-- drivers/pci/pcie/portdrv_pci.c | 9 +++++---- 3 files changed, 11 insertions(+), 8 deletions(-)
diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c index 6fe2d4ef0635..0ba0b47ae751 100644 --- a/drivers/pci/pcie/aer.c +++ b/drivers/pci/pcie/aer.c @@ -1034,6 +1034,7 @@ EXPORT_SYMBOL_GPL(aer_recover_queue); */ int aer_get_device_error_info(struct pci_dev *dev, struct aer_err_info *info) { + int type = pci_pcie_type(dev); int aer = dev->aer_cap; int temp;
@@ -1052,8 +1053,8 @@ int aer_get_device_error_info(struct pci_dev *dev, struct aer_err_info *info) &info->mask); if (!(info->status & ~info->mask)) return 0; - } else if (pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT || - pci_pcie_type(dev) == PCI_EXP_TYPE_DOWNSTREAM || + } else if (type == PCI_EXP_TYPE_ROOT_PORT || + type == PCI_EXP_TYPE_DOWNSTREAM || info->severity == AER_NONFATAL) {
/* Link is still healthy for IO reads */ diff --git a/drivers/pci/pcie/err.c b/drivers/pci/pcie/err.c index 05f61da5ed9d..7a5af873d8bc 100644 --- a/drivers/pci/pcie/err.c +++ b/drivers/pci/pcie/err.c @@ -150,6 +150,7 @@ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev, pci_channel_state_t state, pci_ers_result_t (*reset_subordinates)(struct pci_dev *pdev)) { + int type = pci_pcie_type(dev); pci_ers_result_t status = PCI_ERS_RESULT_CAN_RECOVER; struct pci_bus *bus;
@@ -157,8 +158,8 @@ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev, * Error recovery runs on all subordinates of the first downstream port. * If the downstream port detected the error, it is cleared at the end. */ - if (!(pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT || - pci_pcie_type(dev) == PCI_EXP_TYPE_DOWNSTREAM)) + if (!(type == PCI_EXP_TYPE_ROOT_PORT || + type == PCI_EXP_TYPE_DOWNSTREAM)) dev = pci_upstream_bridge(dev); bus = dev->subordinate;
diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c index 26259630fd10..aac1a6828b4f 100644 --- a/drivers/pci/pcie/portdrv_pci.c +++ b/drivers/pci/pcie/portdrv_pci.c @@ -101,13 +101,14 @@ static const struct dev_pm_ops pcie_portdrv_pm_ops = { static int pcie_portdrv_probe(struct pci_dev *dev, const struct pci_device_id *id) { + int type = pci_pcie_type(dev); int status;
if (!pci_is_pcie(dev) || - ((pci_pcie_type(dev) != PCI_EXP_TYPE_ROOT_PORT) && - (pci_pcie_type(dev) != PCI_EXP_TYPE_UPSTREAM) && - (pci_pcie_type(dev) != PCI_EXP_TYPE_DOWNSTREAM) && - (pci_pcie_type(dev) != PCI_EXP_TYPE_RC_EC))) + ((type != PCI_EXP_TYPE_ROOT_PORT) && + (type != PCI_EXP_TYPE_UPSTREAM) && + (type != PCI_EXP_TYPE_DOWNSTREAM) && + (type != PCI_EXP_TYPE_RC_EC))) return -ENODEV;
status = pcie_port_device_register(dev);
From: Sean V Kelley sean.v.kelley@intel.com
mainline inclusion from mainline-v5.11-rc1 commit 0791721d8007 category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I51U4T CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
--------------------------------------------------------------------------
pcie_do_recovery() may be called with "dev" being either a bridge (Root Port or Switch Downstream Port) or an Endpoint. The bulk of the function deals with the bridge, so if we start with an Endpoint, we reset "dev" to be the bridge leading to it.
For clarity, replace "dev" in the body of the function with "bridge". No functional change intended.
Link: https://lore.kernel.org/r/20201121001036.8560-8-sean.v.kelley@intel.com Tested-by: Jonathan Cameron Jonathan.Cameron@huawei.com # non-native/no RCEC Signed-off-by: Sean V Kelley sean.v.kelley@intel.com Signed-off-by: Bjorn Helgaas bhelgaas@google.com Signed-off-by: Jiefeng Ou oujiefeng@h-partners.com Reviewed-by: Kuppuswamy Sathyanarayanan sathyanarayanan.kuppuswamy@linux.intel.com Acked-by: Jonathan Cameron Jonathan.Cameron@huawei.com Reviewed-by: Jay Fang f.fangjian@huawei.com Reviewed-by: Xiongfeng Wang wangxiongfeng2@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/pci/pcie/err.c | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-)
diff --git a/drivers/pci/pcie/err.c b/drivers/pci/pcie/err.c index 7a5af873d8bc..46a5b84f8842 100644 --- a/drivers/pci/pcie/err.c +++ b/drivers/pci/pcie/err.c @@ -151,24 +151,27 @@ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev, pci_ers_result_t (*reset_subordinates)(struct pci_dev *pdev)) { int type = pci_pcie_type(dev); - pci_ers_result_t status = PCI_ERS_RESULT_CAN_RECOVER; + struct pci_dev *bridge; struct pci_bus *bus; + pci_ers_result_t status = PCI_ERS_RESULT_CAN_RECOVER;
/* - * Error recovery runs on all subordinates of the first downstream port. - * If the downstream port detected the error, it is cleared at the end. + * Error recovery runs on all subordinates of the bridge. If the + * bridge detected the error, it is cleared at the end. */ if (!(type == PCI_EXP_TYPE_ROOT_PORT || type == PCI_EXP_TYPE_DOWNSTREAM)) - dev = pci_upstream_bridge(dev); - bus = dev->subordinate; + bridge = pci_upstream_bridge(dev); + else + bridge = dev;
- pci_dbg(dev, "broadcast error_detected message\n"); + bus = bridge->subordinate; + pci_dbg(bridge, "broadcast error_detected message\n"); if (state == pci_channel_io_frozen) { pci_walk_bus(bus, report_frozen_detected, &status); - status = reset_subordinates(dev); + status = reset_subordinates(bridge); if (status != PCI_ERS_RESULT_RECOVERED) { - pci_warn(dev, "subordinate device reset failed\n"); + pci_warn(bridge, "subordinate device reset failed\n"); goto failed; } } else { @@ -177,7 +180,7 @@ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev,
if (status == PCI_ERS_RESULT_CAN_RECOVER) { status = PCI_ERS_RESULT_RECOVERED; - pci_dbg(dev, "broadcast mmio_enabled message\n"); + pci_dbg(bridge, "broadcast mmio_enabled message\n"); pci_walk_bus(bus, report_mmio_enabled, &status); }
@@ -188,27 +191,27 @@ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev, * drivers' slot_reset callbacks? */ status = PCI_ERS_RESULT_RECOVERED; - pci_dbg(dev, "broadcast slot_reset message\n"); + pci_dbg(bridge, "broadcast slot_reset message\n"); pci_walk_bus(bus, report_slot_reset, &status); }
if (status != PCI_ERS_RESULT_RECOVERED) goto failed;
- pci_dbg(dev, "broadcast resume message\n"); + pci_dbg(bridge, "broadcast resume message\n"); pci_walk_bus(bus, report_resume, &status);
- if (pcie_aer_is_native(dev)) - pcie_clear_device_status(dev); - pci_aer_clear_nonfatal_status(dev); - pci_info(dev, "device recovery successful\n"); + if (pcie_aer_is_native(bridge)) + pcie_clear_device_status(bridge); + pci_aer_clear_nonfatal_status(bridge); + pci_info(bridge, "device recovery successful\n"); return status;
failed: - pci_uevent_ers(dev, PCI_ERS_RESULT_DISCONNECT); + pci_uevent_ers(bridge, PCI_ERS_RESULT_DISCONNECT);
/* TODO: Should kernel panic here? */ - pci_info(dev, "device recovery failed\n"); + pci_info(bridge, "device recovery failed\n");
return status; }
From: Sean V Kelley sean.v.kelley@intel.com
mainline inclusion from mainline-v5.11-rc1 commit 3d7d8fc78f4b category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I51U4T CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
--------------------------------------------------------------------------
Reverse the sense of the Root Port/Downstream Port conditional for clarity. No functional change intended.
Link: https://lore.kernel.org/r/20201121001036.8560-9-sean.v.kelley@intel.com Tested-by: Jonathan Cameron Jonathan.Cameron@huawei.com # non-native/no RCEC Signed-off-by: Sean V Kelley sean.v.kelley@intel.com Signed-off-by: Bjorn Helgaas bhelgaas@google.com Signed-off-by: Jiefeng Ou oujiefeng@h-partners.com Reviewed-by: Kuppuswamy Sathyanarayanan sathyanarayanan.kuppuswamy@linux.intel.com Acked-by: Jonathan Cameron Jonathan.Cameron@huawei.com Reviewed-by: Jay Fang f.fangjian@huawei.com Reviewed-by: Xiongfeng Wang wangxiongfeng2@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/pci/pcie/err.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/pci/pcie/err.c b/drivers/pci/pcie/err.c index 46a5b84f8842..931e75f2549d 100644 --- a/drivers/pci/pcie/err.c +++ b/drivers/pci/pcie/err.c @@ -159,11 +159,11 @@ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev, * Error recovery runs on all subordinates of the bridge. If the * bridge detected the error, it is cleared at the end. */ - if (!(type == PCI_EXP_TYPE_ROOT_PORT || - type == PCI_EXP_TYPE_DOWNSTREAM)) - bridge = pci_upstream_bridge(dev); - else + if (type == PCI_EXP_TYPE_ROOT_PORT || + type == PCI_EXP_TYPE_DOWNSTREAM) bridge = dev; + else + bridge = pci_upstream_bridge(dev);
bus = bridge->subordinate; pci_dbg(bridge, "broadcast error_detected message\n");
From: Sean V Kelley sean.v.kelley@intel.com
mainline inclusion from mainline-v5.11-rc1 commit 05e9ae19ab83 category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I51U4T CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
--------------------------------------------------------------------------
Consolidate subordinate bus checks with pci_walk_bus() into pci_walk_bridge() for walking below potentially AER affected bridges.
Link: https://lore.kernel.org/r/20201121001036.8560-10-sean.v.kelley@intel.com Tested-by: Jonathan Cameron Jonathan.Cameron@huawei.com # non-native/no RCEC Signed-off-by: Sean V Kelley sean.v.kelley@intel.com Signed-off-by: Bjorn Helgaas bhelgaas@google.com Signed-off-by: Jiefeng Ou oujiefeng@h-partners.com Reviewed-by: Jay Fang f.fangjian@huawei.com Reviewed-by: Xiongfeng Wang wangxiongfeng2@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/pci/pcie/err.c | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-)
diff --git a/drivers/pci/pcie/err.c b/drivers/pci/pcie/err.c index 931e75f2549d..8b53aecdb43d 100644 --- a/drivers/pci/pcie/err.c +++ b/drivers/pci/pcie/err.c @@ -146,13 +146,30 @@ static int report_resume(struct pci_dev *dev, void *data) return 0; }
+/** + * pci_walk_bridge - walk bridges potentially AER affected + * @bridge: bridge which may be a Port + * @cb: callback to be called for each device found + * @userdata: arbitrary pointer to be passed to callback + * + * If the device provided is a bridge, walk the subordinate bus, including + * any bridged devices on buses under this bus. Call the provided callback + * on each device found. + */ +static void pci_walk_bridge(struct pci_dev *bridge, + int (*cb)(struct pci_dev *, void *), + void *userdata) +{ + if (bridge->subordinate) + pci_walk_bus(bridge->subordinate, cb, userdata); +} + pci_ers_result_t pcie_do_recovery(struct pci_dev *dev, pci_channel_state_t state, pci_ers_result_t (*reset_subordinates)(struct pci_dev *pdev)) { int type = pci_pcie_type(dev); struct pci_dev *bridge; - struct pci_bus *bus; pci_ers_result_t status = PCI_ERS_RESULT_CAN_RECOVER;
/* @@ -165,23 +182,22 @@ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev, else bridge = pci_upstream_bridge(dev);
- bus = bridge->subordinate; pci_dbg(bridge, "broadcast error_detected message\n"); if (state == pci_channel_io_frozen) { - pci_walk_bus(bus, report_frozen_detected, &status); + pci_walk_bridge(bridge, report_frozen_detected, &status); status = reset_subordinates(bridge); if (status != PCI_ERS_RESULT_RECOVERED) { pci_warn(bridge, "subordinate device reset failed\n"); goto failed; } } else { - pci_walk_bus(bus, report_normal_detected, &status); + pci_walk_bridge(bridge, report_normal_detected, &status); }
if (status == PCI_ERS_RESULT_CAN_RECOVER) { status = PCI_ERS_RESULT_RECOVERED; pci_dbg(bridge, "broadcast mmio_enabled message\n"); - pci_walk_bus(bus, report_mmio_enabled, &status); + pci_walk_bridge(bridge, report_mmio_enabled, &status); }
if (status == PCI_ERS_RESULT_NEED_RESET) { @@ -192,14 +208,14 @@ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev, */ status = PCI_ERS_RESULT_RECOVERED; pci_dbg(bridge, "broadcast slot_reset message\n"); - pci_walk_bus(bus, report_slot_reset, &status); + pci_walk_bridge(bridge, report_slot_reset, &status); }
if (status != PCI_ERS_RESULT_RECOVERED) goto failed;
pci_dbg(bridge, "broadcast resume message\n"); - pci_walk_bus(bus, report_resume, &status); + pci_walk_bridge(bridge, report_resume, &status);
if (pcie_aer_is_native(bridge)) pcie_clear_device_status(bridge);
From: Sean V Kelley sean.v.kelley@intel.com
mainline inclusion from mainline-v5.11-rc1 commit aa344bc8b727 category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I51U4T CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
--------------------------------------------------------------------------
In some cases a bridge may not exist as the hardware controlling may be handled only by firmware and so is not visible to the OS. This scenario is also possible in future use cases involving non-native use of RCECs by firmware. In this scenario, we expect the platform to retain control of the bridge and to clear error status itself.
Clear error status only when the OS has native control of AER.
Signed-off-by: Sean V Kelley sean.v.kelley@intel.com Signed-off-by: Bjorn Helgaas bhelgaas@google.com Signed-off-by: Jiefeng Ou oujiefeng@h-partners.com Reviewed-by: Jay Fang f.fangjian@huawei.com Reviewed-by: Xiongfeng Wang wangxiongfeng2@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/pci/pcie/err.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/drivers/pci/pcie/err.c b/drivers/pci/pcie/err.c index 8b53aecdb43d..45a0ce95632a 100644 --- a/drivers/pci/pcie/err.c +++ b/drivers/pci/pcie/err.c @@ -171,6 +171,7 @@ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev, int type = pci_pcie_type(dev); struct pci_dev *bridge; pci_ers_result_t status = PCI_ERS_RESULT_CAN_RECOVER; + struct pci_host_bridge *host = pci_find_host_bridge(dev->bus);
/* * Error recovery runs on all subordinates of the bridge. If the @@ -217,9 +218,17 @@ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev, pci_dbg(bridge, "broadcast resume message\n"); pci_walk_bridge(bridge, report_resume, &status);
- if (pcie_aer_is_native(bridge)) + /* + * If we have native control of AER, clear error status in the Root + * Port or Downstream Port that signaled the error. If the + * platform retained control of AER, it is responsible for clearing + * this status. In that case, the signaling device may not even be + * visible to the OS. + */ + if (host->native_aer || pcie_ports_native) { pcie_clear_device_status(bridge); - pci_aer_clear_nonfatal_status(bridge); + pci_aer_clear_nonfatal_status(bridge); + } pci_info(bridge, "device recovery successful\n"); return status;
From: Sean V Kelley sean.v.kelley@intel.com
mainline inclusion from mainline-v5.11-rc1 commit a175102b0a82 category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I51U4T CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------------
A Root Complex Event Collector (RCEC) collects and signals AER errors that were detected by Root Complex Integrated Endpoints (RCiEPs), but it may also signal errors it detects itself. This is analogous to errors detected and signaled by a Root Port.
Update the AER service driver to claim RCECs in addition to Root Ports. Add support for handling RCEC-detected AER errors. This does not include handling RCiEP-detected errors that are signaled by the RCEC.
Note that we expect these errors only from the native AER and APEI paths, not from DPC or EDR.
[bhelgaas: split from combined RCEC/RCiEP patch, commit log] Signed-off-by: Sean V Kelley sean.v.kelley@intel.com Signed-off-by: Bjorn Helgaas bhelgaas@google.com Signed-off-by: Jiefeng Ou oujiefeng@h-partners.com Reviewed-by: Jay Fang f.fangjian@huawei.com Reviewed-by: Xiongfeng Wang wangxiongfeng2@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/pci/pcie/aer.c | 58 +++++++++++++++++++++++++++++------------- drivers/pci/pcie/err.c | 19 +++++++++++--- 2 files changed, 56 insertions(+), 21 deletions(-)
diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c index 0ba0b47ae751..84a785fa272c 100644 --- a/drivers/pci/pcie/aer.c +++ b/drivers/pci/pcie/aer.c @@ -300,7 +300,8 @@ int pci_aer_raw_clear_status(struct pci_dev *dev) return -EIO;
port_type = pci_pcie_type(dev); - if (port_type == PCI_EXP_TYPE_ROOT_PORT) { + if (port_type == PCI_EXP_TYPE_ROOT_PORT || + port_type == PCI_EXP_TYPE_RC_EC) { pci_read_config_dword(dev, aer + PCI_ERR_ROOT_STATUS, &status); pci_write_config_dword(dev, aer + PCI_ERR_ROOT_STATUS, status); } @@ -595,7 +596,8 @@ static umode_t aer_stats_attrs_are_visible(struct kobject *kobj, if ((a == &dev_attr_aer_rootport_total_err_cor.attr || a == &dev_attr_aer_rootport_total_err_fatal.attr || a == &dev_attr_aer_rootport_total_err_nonfatal.attr) && - pci_pcie_type(pdev) != PCI_EXP_TYPE_ROOT_PORT) + ((pci_pcie_type(pdev) != PCI_EXP_TYPE_ROOT_PORT) && + (pci_pcie_type(pdev) != PCI_EXP_TYPE_RC_EC))) return 0;
return a->mode; @@ -1206,6 +1208,7 @@ static int set_device_error_reporting(struct pci_dev *dev, void *data) int type = pci_pcie_type(dev);
if ((type == PCI_EXP_TYPE_ROOT_PORT) || + (type == PCI_EXP_TYPE_RC_EC) || (type == PCI_EXP_TYPE_UPSTREAM) || (type == PCI_EXP_TYPE_DOWNSTREAM)) { if (enable) @@ -1330,6 +1333,11 @@ static int aer_probe(struct pcie_device *dev) struct device *device = &dev->device; struct pci_dev *port = dev->port;
+ /* Limit to Root Ports or Root Complex Event Collectors */ + if ((pci_pcie_type(port) != PCI_EXP_TYPE_RC_EC) && + (pci_pcie_type(port) != PCI_EXP_TYPE_ROOT_PORT)) + return -ENODEV; + rpc = devm_kzalloc(device, sizeof(struct aer_rpc), GFP_KERNEL); if (!rpc) return -ENOMEM; @@ -1351,36 +1359,52 @@ static int aer_probe(struct pcie_device *dev) }
/** - * aer_root_reset - reset link on Root Port - * @dev: pointer to Root Port's pci_dev data structure + * aer_root_reset - reset Root Port hierarchy or RCEC + * @dev: pointer to Root Port or RCEC * - * Invoked by Port Bus driver when performing link reset at Root Port. + * Invoked by Port Bus driver when performing reset. */ static pci_ers_result_t aer_root_reset(struct pci_dev *dev) { - int aer = dev->aer_cap; + int type = pci_pcie_type(dev); + struct pci_dev *root; + int aer; + struct pci_host_bridge *host = pci_find_host_bridge(dev->bus); u32 reg32; int rc;
- if (pcie_aer_is_native(dev)) { + root = dev; /* device with Root Error registers */ + aer = root->aer_cap; + + if ((host->native_aer || pcie_ports_native) && aer) { /* Disable Root's interrupt in response to error messages */ - pci_read_config_dword(dev, aer + PCI_ERR_ROOT_COMMAND, ®32); + pci_read_config_dword(root, aer + PCI_ERR_ROOT_COMMAND, ®32); reg32 &= ~ROOT_PORT_INTR_ON_MESG_MASK; - pci_write_config_dword(dev, aer + PCI_ERR_ROOT_COMMAND, reg32); + pci_write_config_dword(root, aer + PCI_ERR_ROOT_COMMAND, reg32); }
- rc = pci_bus_error_reset(dev); - pci_info(dev, "Root Port link has been reset (%d)\n", rc); + if (type == PCI_EXP_TYPE_RC_EC) { + if (pcie_has_flr(dev)) { + rc = pcie_flr(dev); + pci_info(dev, "has been reset (%d)\n", rc); + } else { + pci_info(dev, "not reset (no FLR support)\n"); + rc = -ENOTTY; + } + } else { + rc = pci_bus_error_reset(dev); + pci_info(dev, "Root Port link has been reset (%d)\n", rc); + }
- if (pcie_aer_is_native(dev)) { + if ((host->native_aer || pcie_ports_native) && aer) { /* Clear Root Error Status */ - pci_read_config_dword(dev, aer + PCI_ERR_ROOT_STATUS, ®32); - pci_write_config_dword(dev, aer + PCI_ERR_ROOT_STATUS, reg32); + pci_read_config_dword(root, aer + PCI_ERR_ROOT_STATUS, ®32); + pci_write_config_dword(root, aer + PCI_ERR_ROOT_STATUS, reg32);
/* Enable Root Port's interrupt in response to error messages */ - pci_read_config_dword(dev, aer + PCI_ERR_ROOT_COMMAND, ®32); + pci_read_config_dword(root, aer + PCI_ERR_ROOT_COMMAND, ®32); reg32 |= ROOT_PORT_INTR_ON_MESG_MASK; - pci_write_config_dword(dev, aer + PCI_ERR_ROOT_COMMAND, reg32); + pci_write_config_dword(root, aer + PCI_ERR_ROOT_COMMAND, reg32); }
return rc ? PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_RECOVERED; @@ -1388,7 +1412,7 @@ static pci_ers_result_t aer_root_reset(struct pci_dev *dev)
static struct pcie_port_service_driver aerdriver = { .name = "aer", - .port_type = PCI_EXP_TYPE_ROOT_PORT, + .port_type = PCIE_ANY_PORT, .service = PCIE_PORT_SERVICE_AER,
.probe = aer_probe, diff --git a/drivers/pci/pcie/err.c b/drivers/pci/pcie/err.c index 45a0ce95632a..87a2dc8d17f8 100644 --- a/drivers/pci/pcie/err.c +++ b/drivers/pci/pcie/err.c @@ -148,13 +148,16 @@ static int report_resume(struct pci_dev *dev, void *data)
/** * pci_walk_bridge - walk bridges potentially AER affected - * @bridge: bridge which may be a Port + * @bridge: bridge which may be a Port or an RCEC * @cb: callback to be called for each device found * @userdata: arbitrary pointer to be passed to callback * * If the device provided is a bridge, walk the subordinate bus, including * any bridged devices on buses under this bus. Call the provided callback * on each device found. + * + * If the device provided has no subordinate bus, e.g., an RCEC, call the + * callback on the device itself. */ static void pci_walk_bridge(struct pci_dev *bridge, int (*cb)(struct pci_dev *, void *), @@ -162,6 +165,8 @@ static void pci_walk_bridge(struct pci_dev *bridge, { if (bridge->subordinate) pci_walk_bus(bridge->subordinate, cb, userdata); + else + cb(bridge, userdata); }
pci_ers_result_t pcie_do_recovery(struct pci_dev *dev, @@ -174,11 +179,17 @@ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev, struct pci_host_bridge *host = pci_find_host_bridge(dev->bus);
/* - * Error recovery runs on all subordinates of the bridge. If the - * bridge detected the error, it is cleared at the end. + * If the error was detected by a Root Port, Downstream Port, or + * RCEC, recovery runs on the device itself. For Ports, that also + * includes any subordinate devices. + * + * If it was detected by another device (Endpoint, etc), recovery + * runs on the device and anything else under the same Port, i.e., + * everything under "bridge". */ if (type == PCI_EXP_TYPE_ROOT_PORT || - type == PCI_EXP_TYPE_DOWNSTREAM) + type == PCI_EXP_TYPE_DOWNSTREAM || + type == PCI_EXP_TYPE_RC_EC) bridge = dev; else bridge = pci_upstream_bridge(dev);
From: Sean V Kelley sean.v.kelley@intel.com
mainline inclusion from mainline-v5.11-rc1 commit 507b460f8144 category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I51U4T CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
--------------------------------------------------------------------------
A Root Complex Event Collector terminates error and PME messages from associated RCiEPs.
Use the RCEC Endpoint Association Extended Capability to identify associated RCiEPs. Link the associated RCiEPs as the RCECs are enumerated.
Co-developed-by: Qiuxu Zhuo qiuxu.zhuo@intel.com Link: https://lore.kernel.org/r/20201121001036.8560-12-sean.v.kelley@intel.com Tested-by: Jonathan Cameron Jonathan.Cameron@huawei.com # non-native/no RCEC Signed-off-by: Qiuxu Zhuo qiuxu.zhuo@intel.com Signed-off-by: Sean V Kelley sean.v.kelley@intel.com Signed-off-by: Bjorn Helgaas bhelgaas@google.com Signed-off-by: Jiefeng Ou oujiefeng@h-partners.com Reviewed-by: Jonathan Cameron Jonathan.Cameron@huawei.com Reviewed-by: Jay Fang f.fangjian@huawei.com Reviewed-by: Xiongfeng Wang wangxiongfeng2@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/pci/pci.h | 2 + drivers/pci/pcie/portdrv_pci.c | 3 ++ drivers/pci/pcie/rcec.c | 94 ++++++++++++++++++++++++++++++++++ include/linux/pci.h | 1 + 4 files changed, 100 insertions(+)
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 693983e1de5f..c9d263cd3c94 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -485,9 +485,11 @@ static inline bool pci_dpc_recovered(struct pci_dev *pdev) { return false; } #ifdef CONFIG_PCIEPORTBUS void pci_rcec_init(struct pci_dev *dev); void pci_rcec_exit(struct pci_dev *dev); +void pcie_link_rcec(struct pci_dev *rcec); #else static inline void pci_rcec_init(struct pci_dev *dev) {} static inline void pci_rcec_exit(struct pci_dev *dev) {} +static inline void pcie_link_rcec(struct pci_dev *rcec) {} #endif
#ifdef CONFIG_PCI_ATS diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c index aac1a6828b4f..8bd4992a4f32 100644 --- a/drivers/pci/pcie/portdrv_pci.c +++ b/drivers/pci/pcie/portdrv_pci.c @@ -111,6 +111,9 @@ static int pcie_portdrv_probe(struct pci_dev *dev, (type != PCI_EXP_TYPE_RC_EC))) return -ENODEV;
+ if (type == PCI_EXP_TYPE_RC_EC) + pcie_link_rcec(dev); + status = pcie_port_device_register(dev); if (status) return status; diff --git a/drivers/pci/pcie/rcec.c b/drivers/pci/pcie/rcec.c index 038e9d706d5f..cdec277cbd62 100644 --- a/drivers/pci/pcie/rcec.c +++ b/drivers/pci/pcie/rcec.c @@ -15,6 +15,100 @@
#include "../pci.h"
+struct walk_rcec_data { + struct pci_dev *rcec; + int (*user_callback)(struct pci_dev *dev, void *data); + void *user_data; +}; + +static bool rcec_assoc_rciep(struct pci_dev *rcec, struct pci_dev *rciep) +{ + unsigned long bitmap = rcec->rcec_ea->bitmap; + unsigned int devn; + + /* An RCiEP found on a different bus in range */ + if (rcec->bus->number != rciep->bus->number) + return true; + + /* Same bus, so check bitmap */ + for_each_set_bit(devn, &bitmap, 32) + if (devn == rciep->devfn) + return true; + + return false; +} + +static int link_rcec_helper(struct pci_dev *dev, void *data) +{ + struct walk_rcec_data *rcec_data = data; + struct pci_dev *rcec = rcec_data->rcec; + + if ((pci_pcie_type(dev) == PCI_EXP_TYPE_RC_END) && + rcec_assoc_rciep(rcec, dev)) { + dev->rcec = rcec; + pci_dbg(dev, "PME & error events signaled via %s\n", + pci_name(rcec)); + } + + return 0; +} + +static void walk_rcec(int (*cb)(struct pci_dev *dev, void *data), + void *userdata) +{ + struct walk_rcec_data *rcec_data = userdata; + struct pci_dev *rcec = rcec_data->rcec; + u8 nextbusn, lastbusn; + struct pci_bus *bus; + unsigned int bnr; + + if (!rcec->rcec_ea) + return; + + /* Walk own bus for bitmap based association */ + pci_walk_bus(rcec->bus, cb, rcec_data); + + nextbusn = rcec->rcec_ea->nextbusn; + lastbusn = rcec->rcec_ea->lastbusn; + + /* All RCiEP devices are on the same bus as the RCEC */ + if (nextbusn == 0xff && lastbusn == 0x00) + return; + + for (bnr = nextbusn; bnr <= lastbusn; bnr++) { + /* No association indicated (PCIe 5.0-1, 7.9.10.3) */ + if (bnr == rcec->bus->number) + continue; + + bus = pci_find_bus(pci_domain_nr(rcec->bus), bnr); + if (!bus) + continue; + + /* Find RCiEP devices on the given bus ranges */ + pci_walk_bus(bus, cb, rcec_data); + } +} + +/** + * pcie_link_rcec - Link RCiEP devices associated with RCEC. + * @rcec: RCEC whose RCiEP devices should be linked. + * + * Link the given RCEC to each RCiEP device found. + */ +void pcie_link_rcec(struct pci_dev *rcec) +{ + struct walk_rcec_data rcec_data; + + if (!rcec->rcec_ea) + return; + + rcec_data.rcec = rcec; + rcec_data.user_callback = NULL; + rcec_data.user_data = NULL; + + walk_rcec(link_rcec_helper, &rcec_data); +} + void pci_rcec_init(struct pci_dev *dev) { struct rcec_ea *rcec_ea; diff --git a/include/linux/pci.h b/include/linux/pci.h index 9f8b44ffabff..7d4e6c223970 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -333,6 +333,7 @@ struct pci_dev { #endif #ifdef CONFIG_PCIEPORTBUS struct rcec_ea *rcec_ea; /* RCEC cached endpoint association */ + struct pci_dev *rcec; /* Associated RCEC device */ #endif u8 pcie_cap; /* PCIe capability offset */ u8 msi_cap; /* MSI capability offset */
From: Qiuxu Zhuo qiuxu.zhuo@intel.com
mainline inclusion from mainline-v5.11-rc1 commit 579086225502 category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I51U4T CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
-----------------------------------------------------------------------------
Add support for handling AER errors detected by Root Complex Integrated Endpoints (RCiEPs). These errors are signaled to software natively via a Root Complex Event Collector (RCEC) or non-natively via ACPI APEI if the platform retains control of AER or uses a non-standard RCEC-like device.
When recovering from RCiEP errors, the Root Error Command and Status registers are in the AER Capability of an associated RCEC (if any), not in a Root Port. In the non-native case, the platform is responsible for those registers and we can't touch them.
[bhelgaas: commit log, etc] Co-developed-by: Sean V Kelley sean.v.kelley@intel.com Link: https://lore.kernel.org/r/20201121001036.8560-13-sean.v.kelley@intel.com Signed-off-by: Sean V Kelley sean.v.kelley@intel.com Signed-off-by: Qiuxu Zhuo qiuxu.zhuo@intel.com Signed-off-by: Bjorn Helgaas bhelgaas@google.com Signed-off-by: Jiefeng Ou oujiefeng@h-partners.com Reviewed-by: Jay Fang f.fangjian@huawei.com Reviewed-by: Xiongfeng Wang wangxiongfeng2@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/pci/pcie/aer.c | 24 +++++++++++++++++++----- drivers/pci/pcie/err.c | 15 ++++++++------- 2 files changed, 27 insertions(+), 12 deletions(-)
diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c index 84a785fa272c..e682df536be5 100644 --- a/drivers/pci/pcie/aer.c +++ b/drivers/pci/pcie/aer.c @@ -1359,8 +1359,8 @@ static int aer_probe(struct pcie_device *dev) }
/** - * aer_root_reset - reset Root Port hierarchy or RCEC - * @dev: pointer to Root Port or RCEC + * aer_root_reset - reset Root Port hierarchy, RCEC, or RCiEP + * @dev: pointer to Root Port, RCEC, or RCiEP * * Invoked by Port Bus driver when performing reset. */ @@ -1373,8 +1373,22 @@ static pci_ers_result_t aer_root_reset(struct pci_dev *dev) u32 reg32; int rc;
- root = dev; /* device with Root Error registers */ - aer = root->aer_cap; + /* + * Only Root Ports and RCECs have AER Root Command and Root Status + * registers. If "dev" is an RCiEP, the relevant registers are in + * the RCEC. + */ + if (type == PCI_EXP_TYPE_RC_END) + root = dev->rcec; + else + root = dev; + + /* + * If the platform retained control of AER, an RCiEP may not have + * an RCEC visible to us, so dev->rcec ("root") may be NULL. In + * that case, firmware is responsible for these registers. + */ + aer = root ? root->aer_cap : 0;
if ((host->native_aer || pcie_ports_native) && aer) { /* Disable Root's interrupt in response to error messages */ @@ -1383,7 +1397,7 @@ static pci_ers_result_t aer_root_reset(struct pci_dev *dev) pci_write_config_dword(root, aer + PCI_ERR_ROOT_COMMAND, reg32); }
- if (type == PCI_EXP_TYPE_RC_EC) { + if (type == PCI_EXP_TYPE_RC_EC || type == PCI_EXP_TYPE_RC_END) { if (pcie_has_flr(dev)) { rc = pcie_flr(dev); pci_info(dev, "has been reset (%d)\n", rc); diff --git a/drivers/pci/pcie/err.c b/drivers/pci/pcie/err.c index 87a2dc8d17f8..510f31f0ef6d 100644 --- a/drivers/pci/pcie/err.c +++ b/drivers/pci/pcie/err.c @@ -148,7 +148,7 @@ static int report_resume(struct pci_dev *dev, void *data)
/** * pci_walk_bridge - walk bridges potentially AER affected - * @bridge: bridge which may be a Port or an RCEC + * @bridge: bridge which may be a Port, an RCEC, or an RCiEP * @cb: callback to be called for each device found * @userdata: arbitrary pointer to be passed to callback * @@ -156,8 +156,8 @@ static int report_resume(struct pci_dev *dev, void *data) * any bridged devices on buses under this bus. Call the provided callback * on each device found. * - * If the device provided has no subordinate bus, e.g., an RCEC, call the - * callback on the device itself. + * If the device provided has no subordinate bus, e.g., an RCEC or RCiEP, + * call the callback on the device itself. */ static void pci_walk_bridge(struct pci_dev *bridge, int (*cb)(struct pci_dev *, void *), @@ -179,9 +179,9 @@ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev, struct pci_host_bridge *host = pci_find_host_bridge(dev->bus);
/* - * If the error was detected by a Root Port, Downstream Port, or - * RCEC, recovery runs on the device itself. For Ports, that also - * includes any subordinate devices. + * If the error was detected by a Root Port, Downstream Port, RCEC, + * or RCiEP, recovery runs on the device itself. For Ports, that + * also includes any subordinate devices. * * If it was detected by another device (Endpoint, etc), recovery * runs on the device and anything else under the same Port, i.e., @@ -189,7 +189,8 @@ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev, */ if (type == PCI_EXP_TYPE_ROOT_PORT || type == PCI_EXP_TYPE_DOWNSTREAM || - type == PCI_EXP_TYPE_RC_EC) + type == PCI_EXP_TYPE_RC_EC || + type == PCI_EXP_TYPE_RC_END) bridge = dev; else bridge = pci_upstream_bridge(dev);
From: Sean V Kelley sean.v.kelley@intel.com
mainline inclusion from mainline-v5.11-rc1 commit af113553d961 category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I51U4T CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
--------------------------------------------------------------------------
Root Complex Event Collectors (RCEC) appear as peers to Root Ports and also have the AER capability. In addition, actions need to be taken for associated RCiEPs. In such cases the RCECs will need to be walked in order to find and act upon their respective RCiEPs.
Extend the existing ability to link the RCECs with a walking function pcie_walk_rcec(). Add RCEC support to the current AER service driver and attach the AER service driver to the RCEC device.
Co-developed-by: Qiuxu Zhuo qiuxu.zhuo@intel.com Link: https://lore.kernel.org/r/20201121001036.8560-14-sean.v.kelley@intel.com Tested-by: Jonathan Cameron Jonathan.Cameron@huawei.com # non-native/no RCEC Signed-off-by: Qiuxu Zhuo qiuxu.zhuo@intel.com Signed-off-by: Sean V Kelley sean.v.kelley@intel.com Signed-off-by: Bjorn Helgaas bhelgaas@google.com Signed-off-by: Jiefeng Ou oujiefeng@h-partners.com Reviewed-by: Jonathan Cameron Jonathan.Cameron@huawei.com Reviewed-by: Kuppuswamy Sathyanarayanan sathyanarayanan.kuppuswamy@linux.intel.com Reviewed-by: Jay Fang f.fangjian@huawei.com Reviewed-by: Xiongfeng Wang wangxiongfeng2@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/pci/pci.h | 6 ++++++ drivers/pci/pcie/aer.c | 15 +++++++++++---- drivers/pci/pcie/rcec.c | 37 +++++++++++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 4 deletions(-)
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index c9d263cd3c94..b85bb3dc4216 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -486,10 +486,16 @@ static inline bool pci_dpc_recovered(struct pci_dev *pdev) { return false; } void pci_rcec_init(struct pci_dev *dev); void pci_rcec_exit(struct pci_dev *dev); void pcie_link_rcec(struct pci_dev *rcec); +void pcie_walk_rcec(struct pci_dev *rcec, + int (*cb)(struct pci_dev *, void *), + void *userdata); #else static inline void pci_rcec_init(struct pci_dev *dev) {} static inline void pci_rcec_exit(struct pci_dev *dev) {} static inline void pcie_link_rcec(struct pci_dev *rcec) {} +static inline void pcie_walk_rcec(struct pci_dev *rcec, + int (*cb)(struct pci_dev *, void *), + void *userdata) {} #endif
#ifdef CONFIG_PCI_ATS diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c index e682df536be5..77b0f2c45bc0 100644 --- a/drivers/pci/pcie/aer.c +++ b/drivers/pci/pcie/aer.c @@ -918,7 +918,10 @@ static bool find_source_device(struct pci_dev *parent, if (result) return true;
- pci_walk_bus(parent->subordinate, find_device_iter, e_info); + if (pci_pcie_type(parent) == PCI_EXP_TYPE_RC_EC) + pcie_walk_rcec(parent, find_device_iter, e_info); + else + pci_walk_bus(parent->subordinate, find_device_iter, e_info);
if (!e_info->error_dev_num) { pci_info(parent, "can't find device of ID%04x\n", e_info->id); @@ -1056,6 +1059,7 @@ int aer_get_device_error_info(struct pci_dev *dev, struct aer_err_info *info) if (!(info->status & ~info->mask)) return 0; } else if (type == PCI_EXP_TYPE_ROOT_PORT || + type == PCI_EXP_TYPE_RC_EC || type == PCI_EXP_TYPE_DOWNSTREAM || info->severity == AER_NONFATAL) {
@@ -1233,9 +1237,12 @@ static void set_downstream_devices_error_reporting(struct pci_dev *dev, { set_device_error_reporting(dev, &enable);
- if (!dev->subordinate) - return; - pci_walk_bus(dev->subordinate, set_device_error_reporting, &enable); + if (pci_pcie_type(dev) == PCI_EXP_TYPE_RC_EC) + pcie_walk_rcec(dev, set_device_error_reporting, &enable); + else if (dev->subordinate) + pci_walk_bus(dev->subordinate, set_device_error_reporting, + &enable); + }
/** diff --git a/drivers/pci/pcie/rcec.c b/drivers/pci/pcie/rcec.c index cdec277cbd62..2c5c552994e4 100644 --- a/drivers/pci/pcie/rcec.c +++ b/drivers/pci/pcie/rcec.c @@ -53,6 +53,18 @@ static int link_rcec_helper(struct pci_dev *dev, void *data) return 0; }
+static int walk_rcec_helper(struct pci_dev *dev, void *data) +{ + struct walk_rcec_data *rcec_data = data; + struct pci_dev *rcec = rcec_data->rcec; + + if ((pci_pcie_type(dev) == PCI_EXP_TYPE_RC_END) && + rcec_assoc_rciep(rcec, dev)) + rcec_data->user_callback(dev, rcec_data->user_data); + + return 0; +} + static void walk_rcec(int (*cb)(struct pci_dev *dev, void *data), void *userdata) { @@ -109,6 +121,31 @@ void pcie_link_rcec(struct pci_dev *rcec) walk_rcec(link_rcec_helper, &rcec_data); }
+/** + * pcie_walk_rcec - Walk RCiEP devices associating with RCEC and call callback. + * @rcec: RCEC whose RCiEP devices should be walked + * @cb: Callback to be called for each RCiEP device found + * @userdata: Arbitrary pointer to be passed to callback + * + * Walk the given RCEC. Call the callback on each RCiEP found. + * + * If @cb returns anything other than 0, break out. + */ +void pcie_walk_rcec(struct pci_dev *rcec, int (*cb)(struct pci_dev *, void *), + void *userdata) +{ + struct walk_rcec_data rcec_data; + + if (!rcec->rcec_ea) + return; + + rcec_data.rcec = rcec; + rcec_data.user_callback = cb; + rcec_data.user_data = userdata; + + walk_rcec(walk_rcec_helper, &rcec_data); +} + void pci_rcec_init(struct pci_dev *dev) { struct rcec_ea *rcec_ea;
From: Sean V Kelley sean.v.kelley@intel.com
mainline inclusion from mainline-v5.11-rc1 commit 9a2f604f4497 category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I51U4T CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
--------------------------------------------------------------------------
Root Complex Event Collectors (RCEC) appear as peers of Root Ports and also have the PME capability. As with AER, there is a need to be able to walk the RCiEPs associated with their RCEC for purposes of acting upon them with callbacks.
Add RCEC support through the use of pcie_walk_rcec() to the current PME service driver and attach the PME service driver to the RCEC device.
Co-developed-by: Qiuxu Zhuo qiuxu.zhuo@intel.com Link: https://lore.kernel.org/r/20201121001036.8560-15-sean.v.kelley@intel.com Tested-by: Jonathan Cameron Jonathan.Cameron@huawei.com # non-native/no RCEC Signed-off-by: Qiuxu Zhuo qiuxu.zhuo@intel.com Signed-off-by: Sean V Kelley sean.v.kelley@intel.com Signed-off-by: Bjorn Helgaas bhelgaas@google.com Signed-off-by: Jiefeng Ou oujiefeng@h-partners.com Reviewed-by: Jay Fang f.fangjian@huawei.com Reviewed-by: Xiongfeng Wang wangxiongfeng2@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/pci/pcie/pme.c | 16 ++++++++++++---- drivers/pci/pcie/portdrv_core.c | 9 +++------ 2 files changed, 15 insertions(+), 10 deletions(-)
diff --git a/drivers/pci/pcie/pme.c b/drivers/pci/pcie/pme.c index 6a32970bb731..3fc08488d65f 100644 --- a/drivers/pci/pcie/pme.c +++ b/drivers/pci/pcie/pme.c @@ -310,7 +310,10 @@ static int pcie_pme_can_wakeup(struct pci_dev *dev, void *ign) static void pcie_pme_mark_devices(struct pci_dev *port) { pcie_pme_can_wakeup(port, NULL); - if (port->subordinate) + + if (pci_pcie_type(port) == PCI_EXP_TYPE_RC_EC) + pcie_walk_rcec(port, pcie_pme_can_wakeup, NULL); + else if (port->subordinate) pci_walk_bus(port->subordinate, pcie_pme_can_wakeup, NULL); }
@@ -320,10 +323,16 @@ static void pcie_pme_mark_devices(struct pci_dev *port) */ static int pcie_pme_probe(struct pcie_device *srv) { - struct pci_dev *port; + struct pci_dev *port = srv->port; struct pcie_pme_service_data *data; + int type = pci_pcie_type(port); int ret;
+ /* Limit to Root Ports or Root Complex Event Collectors */ + if (type != PCI_EXP_TYPE_RC_EC && + type != PCI_EXP_TYPE_ROOT_PORT) + return -ENODEV; + data = kzalloc(sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM; @@ -333,7 +342,6 @@ static int pcie_pme_probe(struct pcie_device *srv) data->srv = srv; set_service_data(srv, data);
- port = srv->port; pcie_pme_interrupt_enable(port, false); pcie_clear_root_pme_status(port);
@@ -445,7 +453,7 @@ static void pcie_pme_remove(struct pcie_device *srv)
static struct pcie_port_service_driver pcie_pme_driver = { .name = "pcie_pme", - .port_type = PCI_EXP_TYPE_ROOT_PORT, + .port_type = PCIE_ANY_PORT, .service = PCIE_PORT_SERVICE_PME,
.probe = pcie_pme_probe, diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c index 3779b264dbec..3ee63968deaa 100644 --- a/drivers/pci/pcie/portdrv_core.c +++ b/drivers/pci/pcie/portdrv_core.c @@ -233,12 +233,9 @@ static int get_port_device_capability(struct pci_dev *dev) } #endif
- /* - * Root ports are capable of generating PME too. Root Complex - * Event Collectors can also generate PMEs, but we don't handle - * those yet. - */ - if (pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT && + /* Root Ports and Root Complex Event Collectors may generate PMEs */ + if ((pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT || + pci_pcie_type(dev) == PCI_EXP_TYPE_RC_EC) && (pcie_ports_native || host->native_pme)) { services |= PCIE_PORT_SERVICE_PME;
From: Qiuxu Zhuo qiuxu.zhuo@intel.com
mainline inclusion from mainline-v5.11-rc1 commit d292dd0eb3ac category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I51U4T CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
--------------------------------------------------------------------------
Root Complex Event Collectors (RCEC) appear as peers to Root Ports and may also have the AER capability.
Add RCEC support to the AER error injection driver.
Co-developed-by: Sean V Kelley sean.v.kelley@intel.com Link: https://lore.kernel.org/r/20201121001036.8560-16-sean.v.kelley@intel.com Tested-by: Jonathan Cameron Jonathan.Cameron@huawei.com # non-native/no RCEC Signed-off-by: Qiuxu Zhuo qiuxu.zhuo@intel.com Signed-off-by: Sean V Kelley sean.v.kelley@intel.com Signed-off-by: Bjorn Helgaas bhelgaas@google.com Signed-off-by: Jiefeng Ou oujiefeng@h-partners.com Reviewed-by: Kuppuswamy Sathyanarayanan sathyanarayanan.kuppuswamy@linux.intel.com Reviewed-by: Jay Fang f.fangjian@huawei.com Reviewed-by: Xiongfeng Wang wangxiongfeng2@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/pci/pcie/aer_inject.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/pci/pcie/aer_inject.c b/drivers/pci/pcie/aer_inject.c index 4dc1d95f085b..ba11a0eed2be 100644 --- a/drivers/pci/pcie/aer_inject.c +++ b/drivers/pci/pcie/aer_inject.c @@ -341,8 +341,11 @@ static int aer_inject(struct aer_error_inj *einj) if (!dev) return -ENODEV; rpdev = pcie_find_root_port(dev); + /* If Root Port not found, try to find an RCEC */ + if (!rpdev) + rpdev = dev->rcec; if (!rpdev) { - pci_err(dev, "Root port not found\n"); + pci_err(dev, "Neither Root Port nor RCEC found\n"); ret = -ENODEV; goto out_put; }
From: Qiuxu Zhuo qiuxu.zhuo@intel.com
mainline inclusion from mainline-v5.13-rc1 commit d9b7eae8e342 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I51U4T CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
--------------------------------------------------------------------------
rcec_assoc_rciep() used "rciep->devfn" (a single byte encoding both the device and function number) as the device number to check whether the corresponding bit was set in the RCEC's Association Bitmap for RCiEPs.
But per PCIe r5.0, sec 7.9.10.2, "Association Bitmap for RCiEPs", the 32-bit bitmap contains one bit per device. That bit applies to all functions of the device.
Fix rcec_assoc_rciep() to convert the value of "rciep->devfn" to a device number to ensure that RCiEP devices are correctly associated with the RCEC.
Reported-and-tested-by: Wen Jin wen.jin@intel.com Fixes: 507b460f8144 ("PCI/ERR: Add pcie_link_rcec() to associate RCiEPs") Link: https://lore.kernel.org/r/20210222011717.43266-1-qiuxu.zhuo@intel.com Signed-off-by: Qiuxu Zhuo qiuxu.zhuo@intel.com Signed-off-by: Bjorn Helgaas bhelgaas@google.com Signed-off-by: Jiefeng Ou oujiefeng@h-partners.com Reviewed-by: Sean V Kelley sean.v.kelley@intel.com Reviewed-by: Jay Fang f.fangjian@huawei.com Reviewed-by: Xiongfeng Wang wangxiongfeng2@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/pci/pcie/rcec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/pci/pcie/rcec.c b/drivers/pci/pcie/rcec.c index 2c5c552994e4..d0bcd141ac9c 100644 --- a/drivers/pci/pcie/rcec.c +++ b/drivers/pci/pcie/rcec.c @@ -32,7 +32,7 @@ static bool rcec_assoc_rciep(struct pci_dev *rcec, struct pci_dev *rciep)
/* Same bus, so check bitmap */ for_each_set_bit(devn, &bitmap, 32) - if (devn == rciep->devfn) + if (devn == PCI_SLOT(rciep->devfn)) return true;
return false;
From: Jiefeng Ou oujiefeng@h-partners.com
driver inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I51U4T
--------------------------------------------------------------------------
Fix kabi change in struct pci_dev since the following patches: - commit 8eb7b6ca203f ("PCI/ERR: Cache RCEC EA Capability offset in pci_init_capabilities()") - commit 1345ecf47242 ("PCI/ERR: Add pcie_link_rcec() to associate RCiEPs")
Signed-off-by: Jiefeng Ou oujiefeng@h-partners.com Reviewed-by: Xiongfeng Wang wangxiongfeng2@huawei.com Reviewed-by: Jay Fang f.fangjian@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- include/linux/pci.h | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-)
diff --git a/include/linux/pci.h b/include/linux/pci.h index 7d4e6c223970..aee7a7563fc2 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -330,10 +330,6 @@ struct pci_dev { #ifdef CONFIG_PCIEAER u16 aer_cap; /* AER capability offset */ struct aer_stats *aer_stats; /* AER stats for this device */ -#endif -#ifdef CONFIG_PCIEPORTBUS - struct rcec_ea *rcec_ea; /* RCEC cached endpoint association */ - struct pci_dev *rcec; /* Associated RCEC device */ #endif u8 pcie_cap; /* PCIe capability offset */ u8 msi_cap; /* MSI capability offset */ @@ -516,8 +512,18 @@ struct pci_dev { unsigned long slot_being_removed_rescanned; struct pci_dev *rpdev; /* root port pci_dev */
+#ifndef __GENKSYMS__ +#ifdef CONFIG_PCIEPORTBUS + struct rcec_ea *rcec_ea; /* RCEC cached endpoint association */ + struct pci_dev *rcec; /* Associated RCEC device */ +#else + KABI_RESERVE(1) + KABI_RESERVE(2) +#endif +#else KABI_RESERVE(1) KABI_RESERVE(2) +#endif KABI_RESERVE(3) KABI_RESERVE(4) KABI_RESERVE(5)
From: yanghui yanghui.def@bytedance.com
mainline inclusion from mainline-v5.15-rc1 commit 276aeee1c5fc00df700f0782060beae126600472 category: bugfix bugzilla: 181417 https://gitee.com/openeuler/kernel/issues/I53CSV backport: openEuler-22.03-LTS
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
-------------------------------
Servers happened below panic:
Kernel version:5.4.56 BUG: unable to handle page fault for address: 0000000000002c48 RIP: 0010:__next_zones_zonelist+0x1d/0x40 Call Trace: __alloc_pages_nodemask+0x277/0x310 alloc_page_interleave+0x13/0x70 handle_mm_fault+0xf99/0x1390 __do_page_fault+0x288/0x500 do_page_fault+0x30/0x110 page_fault+0x3e/0x50
The reason for the panic is that MAX_NUMNODES is passed in the third parameter in __alloc_pages_nodemask(preferred_nid). So access to zonelist->zoneref->zone_idx in __next_zones_zonelist will cause a panic.
In offset_il_node(), first_node() returns nid from pol->v.nodes, after this other threads may chang pol->v.nodes before next_node(). This race condition will let next_node return MAX_NUMNODES. So put pol->nodes in a local variable.
The race condition is between offset_il_node and cpuset_change_task_nodemask:
CPU0: CPU1: alloc_pages_vma() interleave_nid(pol,) offset_il_node(pol,) first_node(pol->v.nodes) cpuset_change_task_nodemask //nodes==0xc mpol_rebind_task mpol_rebind_policy mpol_rebind_nodemask(pol,nodes) //nodes==0x3 next_node(nid, pol->v.nodes)//return MAX_NUMNODES
Link: https://lkml.kernel.org/r/20210906034658.48721-1-yanghui.def@bytedance.com Signed-off-by: yanghui yanghui.def@bytedance.com Reviewed-by: Muchun Song songmuchun@bytedance.com Cc: stable@vger.kernel.org Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org (cherry picked from commit 276aeee1c5fc00df700f0782060beae126600472) conflicts: mm/mempolicy.c Signed-off-by: Yongqiang Liu liuyongqiang13@huawei.com Reviewed-by: Kefeng Wang wangkefeng.wang@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- mm/mempolicy.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-)
diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 746383b54605..5ce39dbc84e1 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -2014,17 +2014,26 @@ unsigned int mempolicy_slab_node(void) */ static unsigned offset_il_node(struct mempolicy *pol, unsigned long n) { - unsigned nnodes = nodes_weight(pol->v.nodes); - unsigned target; + nodemask_t nodemask = pol->v.nodes; + unsigned int target, nnodes; int i; int nid; + /* + * The barrier will stabilize the nodemask in a register or on + * the stack so that it will stop changing under the code. + * + * Between first_node() and next_node(), pol->nodes could be changed + * by other threads. So we put pol->nodes in a local stack. + */ + barrier();
+ nnodes = nodes_weight(nodemask); if (!nnodes) return numa_node_id(); target = (unsigned int)n % nnodes; - nid = first_node(pol->v.nodes); + nid = first_node(nodemask); for (i = 0; i < target; i++) - nid = next_node(nid, pol->v.nodes); + nid = next_node(nid, nodemask); return nid; }
From: Juergen Gross jgross@suse.com
mainline inclusion from mainline-v5.13-rc1 commit 8d0968cc6b8ffd8496c2ebffdfdc801f949a85e5 category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I5319J
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
--------------------------------
Currently CSD lock debugging can be switched on and off via a kernel config option only. Unfortunately there is at least one problem with CSD lock handling pending for about 2 years now, which has been seen in different environments (mostly when running virtualized under KVM or Xen, at least once on bare metal). Multiple attempts to catch this issue have finally led to introduction of CSD lock debug code, but this code is not in use in most distros as it has some impact on performance.
In order to be able to ship kernels with CONFIG_CSD_LOCK_WAIT_DEBUG enabled even for production use, add a boot parameter for switching the debug functionality on. This will reduce any performance impact of the debug coding to a bare minimum when not being used.
Signed-off-by: Juergen Gross jgross@suse.com [ Minor edits. ] Signed-off-by: Ingo Molnar mingo@kernel.org Link: https://lore.kernel.org/r/20210301101336.7797-2-jgross@suse.com (cherry picked from commit 8d0968cc6b8ffd8496c2ebffdfdc801f949a85e5)
conflicts: kernel/smp.c
Signed-off-by: Chen Zhongjin chenzhongjin@huawei.com Reviewed-by: Kuohai Xu xukuohai@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- .../admin-guide/kernel-parameters.txt | 6 ++++ kernel/smp.c | 34 +++++++++++++++++-- 2 files changed, 38 insertions(+), 2 deletions(-)
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index b5524464f1cb..74c25228aec4 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -800,6 +800,12 @@ cs89x0_media= [HW,NET] Format: { rj45 | aui | bnc }
+ csdlock_debug= [KNL] Enable debug add-ons of cross-CPU function call + handling. When switched on, additional debug data is + printed to the console in case a hanging CPU is + detected, and that CPU is pinged again in order to try + to resolve the hang situation. + dasd= [HW,NET] See header of drivers/s390/block/dasd_devmap.c.
diff --git a/kernel/smp.c b/kernel/smp.c index a5a87a51e726..b04ab01eb9e0 100644 --- a/kernel/smp.c +++ b/kernel/smp.c @@ -24,6 +24,7 @@ #include <linux/sched/clock.h> #include <linux/nmi.h> #include <linux/sched/debug.h> +#include <linux/jump_label.h>
#include "smpboot.h" #include "sched/smp.h" @@ -102,6 +103,20 @@ void __init call_function_init(void)
#ifdef CONFIG_CSD_LOCK_WAIT_DEBUG
+static DEFINE_STATIC_KEY_FALSE(csdlock_debug_enabled); + +static int __init csdlock_debug(char *str) +{ + unsigned int val = 0; + + get_option(&str, &val); + if (val) + static_branch_enable(&csdlock_debug_enabled); + + return 0; +} +early_param("csdlock_debug", csdlock_debug); + static DEFINE_PER_CPU(call_single_data_t *, cur_csd); static DEFINE_PER_CPU(smp_call_func_t, cur_csd_func); static DEFINE_PER_CPU(void *, cur_csd_info); @@ -110,7 +125,7 @@ static DEFINE_PER_CPU(void *, cur_csd_info); static atomic_t csd_bug_count = ATOMIC_INIT(0);
/* Record current CSD work for current CPU, NULL to erase. */ -static void csd_lock_record(struct __call_single_data *csd) +static void __csd_lock_record(struct __call_single_data *csd) { if (!csd) { smp_mb(); /* NULL cur_csd after unlock. */ @@ -125,6 +140,12 @@ static void csd_lock_record(struct __call_single_data *csd) /* Or before unlock, as the case may be. */ }
+static __always_inline void csd_lock_record(struct __call_single_data *csd) +{ + if (static_branch_unlikely(&csdlock_debug_enabled)) + __csd_lock_record(csd); +} + static __always_inline int csd_lock_wait_getcpu(struct __call_single_data *csd) { unsigned int csd_type; @@ -204,7 +225,7 @@ static __always_inline bool csd_lock_wait_toolong(struct __call_single_data *csd * previous function call. For multi-cpu calls its even more interesting * as we'll have to ensure no other cpu is observing our csd. */ -static __always_inline void csd_lock_wait(struct __call_single_data *csd) +static void __csd_lock_wait(struct __call_single_data *csd) { int bug_id = 0; u64 ts0, ts1; @@ -218,6 +239,15 @@ static __always_inline void csd_lock_wait(struct __call_single_data *csd) smp_acquire__after_ctrl_dep(); }
+static __always_inline void csd_lock_wait(struct __call_single_data *csd) +{ + if (static_branch_unlikely(&csdlock_debug_enabled)) { + __csd_lock_wait(csd); + return; + } + + smp_cond_load_acquire(&csd->node.u_flags, !(VAL & CSD_FLAG_LOCK)); +} #else static void csd_lock_record(struct __call_single_data *csd) {
From: Greg Kroah-Hartman gregkh@linuxfoundation.org
mainline inclusion from mainline-v5.17-rc2 commit 38ea1eac7d88072bbffb630e2b3db83ca649b826 bugzilla: 186289, https://gitee.com/src-openeuler/kernel/issues/I4VNWC CVE: CVE-2022-25375 backport: openEuler-22.03-LTS
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
--------------------------------
Check the size of the RNDIS_MSG_SET command given to us before attempting to respond to an invalid message size.
Reported-by: Szymon Heidrich szymon.heidrich@gmail.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Lijun Fang fanglijun3@huawei.com Reviewed-by: Xiu Jianfeng xiujianfeng@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/usb/gadget/function/rndis.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/drivers/usb/gadget/function/rndis.c b/drivers/usb/gadget/function/rndis.c index 9ea94215e113..60d89339a563 100644 --- a/drivers/usb/gadget/function/rndis.c +++ b/drivers/usb/gadget/function/rndis.c @@ -655,14 +655,17 @@ static int rndis_set_response(struct rndis_params *params, rndis_set_cmplt_type *resp; rndis_resp_t *r;
+ BufLength = le32_to_cpu(buf->InformationBufferLength); + BufOffset = le32_to_cpu(buf->InformationBufferOffset); + if ((BufLength > RNDIS_MAX_TOTAL_SIZE) || + (BufOffset + 8 >= RNDIS_MAX_TOTAL_SIZE)) + return -EINVAL; + r = rndis_add_response(params, sizeof(rndis_set_cmplt_type)); if (!r) return -ENOMEM; resp = (rndis_set_cmplt_type *)r->buf;
- BufLength = le32_to_cpu(buf->InformationBufferLength); - BufOffset = le32_to_cpu(buf->InformationBufferOffset); - #ifdef VERBOSE_DEBUG pr_debug("%s: Length: %d\n", __func__, BufLength); pr_debug("%s: Offset: %d\n", __func__, BufOffset);
From: Hangyu Hua hbh25y@gmail.com
mainline inclusion from mainline-v5.17-rc1 commit 501e38a5531efbd77d5c73c0ba838a889bfc1d74 category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/I4U74M CVE: CVE-2022-24958
--------------------------------
dev->config and dev->hs_config and dev->dev need to be cleaned if dev_config fails to avoid UAF.
Acked-by: Alan Stern stern@rowland.harvard.edu Signed-off-by: Hangyu Hua hbh25y@gmail.com Link: https://lore.kernel.org/r/20211231172138.7993-3-hbh25y@gmail.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Yuan Can yuancan@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/usb/gadget/legacy/inode.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c index 217d2b66fa51..523d05e5dca5 100644 --- a/drivers/usb/gadget/legacy/inode.c +++ b/drivers/usb/gadget/legacy/inode.c @@ -1876,8 +1876,8 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
value = usb_gadget_probe_driver(&gadgetfs_driver); if (value != 0) { - kfree (dev->buf); - dev->buf = NULL; + spin_lock_irq(&dev->lock); + goto fail; } else { /* at this point "good" hardware has for the first time * let the USB the host see us. alternatively, if users @@ -1894,6 +1894,9 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr) return value;
fail: + dev->config = NULL; + dev->hs_config = NULL; + dev->dev = NULL; spin_unlock_irq (&dev->lock); pr_debug ("%s: %s fail %zd, %p\n", shortname, __func__, value, dev); kfree (dev->buf);
From: Hangyu Hua hbh25y@gmail.com
mainline inclusion from mainline-v5.17-rc1 commit 89f3594d0de58e8a57d92d497dea9fee3d4b9cda category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/I4U74M CVE: CVE-2022-24958
--------------------------------
dev->buf does not need to be released if it already exists before executing dev_config.
Acked-by: Alan Stern stern@rowland.harvard.edu Signed-off-by: Hangyu Hua hbh25y@gmail.com Link: https://lore.kernel.org/r/20211231172138.7993-2-hbh25y@gmail.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Yuan Can yuancan@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/usb/gadget/legacy/inode.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c index 523d05e5dca5..454860d52ce7 100644 --- a/drivers/usb/gadget/legacy/inode.c +++ b/drivers/usb/gadget/legacy/inode.c @@ -1828,8 +1828,9 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr) spin_lock_irq (&dev->lock); value = -EINVAL; if (dev->buf) { + spin_unlock_irq(&dev->lock); kfree(kbuf); - goto fail; + return value; } dev->buf = kbuf;
From: Szymon Heidrich szymon.heidrich@gmail.com
mainline inclusion from mainline-v5.17-rc4 commit 75e5b4849b81e19e9efe1654b30d7f3151c33c2c category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/I4VNW2 CVE: CVE-2022-25258
--------------------------------
Stall the control endpoint in case provided index exceeds array size of MAX_CONFIG_INTERFACES or when the retrieved function pointer is null.
Signed-off-by: Szymon Heidrich szymon.heidrich@gmail.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Yuan Can yuancan@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/usb/gadget/composite.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 8bec0cbf844e..a980799900e7 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -1944,6 +1944,9 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) if (w_index != 0x5 || (w_value >> 8)) break; interface = w_value & 0xFF; + if (interface >= MAX_CONFIG_INTERFACES || + !os_desc_cfg->interface[interface]) + break; buf[6] = w_index; count = count_ext_prop(os_desc_cfg, interface);
From: Peter Zijlstra peterz@infradead.org
mainline inclusion from mainline-v5.17-rc5 commit b1e8206582f9d680cff7d04828708c8b6ab32957 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I53LXG?from=project-issue CVE: NA
--------------------------------
Where commit 4ef0c5c6b5ba ("kernel/sched: Fix sched_fork() access an invalid sched_task_group") fixed a fork race vs cgroup, it opened up a race vs syscalls by not placing the task on the runqueue before it gets exposed through the pidhash.
Commit 13765de8148f ("sched/fair: Fix fault in reweight_entity") is trying to fix a single instance of this, instead fix the whole class of issues, effectively reverting this commit.
Fixes: 4ef0c5c6b5ba ("kernel/sched: Fix sched_fork() access an invalid sched_task_group") Reported-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Peter Zijlstra (Intel) peterz@infradead.org Tested-by: Tadeusz Struk tadeusz.struk@linaro.org Tested-by: Zhang Qiao zhangqiao22@huawei.com Tested-by: Dietmar Eggemann dietmar.eggemann@arm.com Link: https://lkml.kernel.org/r/YgoeCbwj5mbCR0qA@hirez.programming.kicks-ass.net Signed-off-by: Zucheng Zheng zhengzucheng@huawei.com Reviewed-by: Zhang Qiao zhangqiao22@huawei.com Reviewed-by: Chen Hui judy.chenhui@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- include/linux/sched/task.h | 4 ++-- kernel/fork.c | 13 ++++++++++++- kernel/sched/core.c | 23 ++++++++++++++++------- 3 files changed, 30 insertions(+), 10 deletions(-)
diff --git a/include/linux/sched/task.h b/include/linux/sched/task.h index fa75f325dad5..cea4bdfd0f05 100644 --- a/include/linux/sched/task.h +++ b/include/linux/sched/task.h @@ -55,8 +55,8 @@ extern asmlinkage void schedule_tail(struct task_struct *prev); extern void init_idle(struct task_struct *idle, int cpu);
extern int sched_fork(unsigned long clone_flags, struct task_struct *p); -extern void sched_post_fork(struct task_struct *p, - struct kernel_clone_args *kargs); +extern void sched_cgroup_fork(struct task_struct *p, struct kernel_clone_args *kargs); +extern void sched_post_fork(struct task_struct *p); extern void sched_dead(struct task_struct *p);
void __noreturn do_task_dead(void); diff --git a/kernel/fork.c b/kernel/fork.c index bf27ee90ad23..f3e3f53893bb 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -2233,6 +2233,17 @@ static __latent_entropy struct task_struct *copy_process( if (retval) goto bad_fork_put_pidfd;
+ /* + * Now that the cgroups are pinned, re-clone the parent cgroup and put + * the new task on the correct runqueue. All this *before* the task + * becomes visible. + * + * This isn't part of ->can_fork() because while the re-cloning is + * cgroup specific, it unconditionally needs to place the task on a + * runqueue. + */ + sched_cgroup_fork(p, args); + /* * From this point on we must avoid any synchronous user-space * communication until we take the tasklist-lock. In particular, we do @@ -2341,7 +2352,7 @@ static __latent_entropy struct task_struct *copy_process( write_unlock_irq(&tasklist_lock);
proc_fork_connector(p); - sched_post_fork(p, args); + sched_post_fork(p); cgroup_post_fork(p, args); perf_event_fork(p);
diff --git a/kernel/sched/core.c b/kernel/sched/core.c index a8358ddba7ef..56be8d1c7f69 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -3307,6 +3307,7 @@ int sched_fork(unsigned long clone_flags, struct task_struct *p)
init_entity_runnable_average(&p->se);
+ #ifdef CONFIG_SCHED_INFO if (likely(sched_info_on())) memset(&p->sched_info, 0, sizeof(p->sched_info)); @@ -3322,18 +3323,23 @@ int sched_fork(unsigned long clone_flags, struct task_struct *p) return 0; }
-void sched_post_fork(struct task_struct *p, struct kernel_clone_args *kargs) +void sched_cgroup_fork(struct task_struct *p, struct kernel_clone_args *kargs) { unsigned long flags; -#ifdef CONFIG_CGROUP_SCHED - struct task_group *tg; -#endif
+ /* + * Because we're not yet on the pid-hash, p->pi_lock isn't strictly + * required yet, but lockdep gets upset if rules are violated. + */ raw_spin_lock_irqsave(&p->pi_lock, flags); #ifdef CONFIG_CGROUP_SCHED - tg = container_of(kargs->cset->subsys[cpu_cgrp_id], - struct task_group, css); - p->sched_task_group = autogroup_task_group(p, tg); + if (1) { + struct task_group *tg; + tg = container_of(kargs->cset->subsys[cpu_cgrp_id], + struct task_group, css); + tg = autogroup_task_group(p, tg); + p->sched_task_group = tg; + } #endif rseq_migrate(p); /* @@ -3344,7 +3350,10 @@ void sched_post_fork(struct task_struct *p, struct kernel_clone_args *kargs) if (p->sched_class->task_fork) p->sched_class->task_fork(p); raw_spin_unlock_irqrestore(&p->pi_lock, flags); +}
+void sched_post_fork(struct task_struct *p) +{ uclamp_post_fork(p); }
From: Pablo Neira Ayuso pablo@netfilter.org
mainline inclusion from mainline-v5.18-rc1 commit 4c905f6740a365464e91467aa50916555b28213d category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/I50WAZ CVE: CVE-2022-1016
-------------------------------------------------
Initialize registers to avoid stack leak into userspace.
Fixes: 96518518cc41 ("netfilter: add nftables") Signed-off-by: Pablo Neira Ayuso pablo@netfilter.org
conflict: net/netfilter/nf_tables_core.c
Signed-off-by: Lu Wei luwei32@huawei.com Reviewed-by: Wei Yongjun weiyongjun1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- net/netfilter/nf_tables_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/netfilter/nf_tables_core.c b/net/netfilter/nf_tables_core.c index dbc2e945c98e..a61b5bf5aa0f 100644 --- a/net/netfilter/nf_tables_core.c +++ b/net/netfilter/nf_tables_core.c @@ -162,7 +162,7 @@ nft_do_chain(struct nft_pktinfo *pkt, void *priv) struct nft_rule *const *rules; const struct nft_rule *rule; const struct nft_expr *expr, *last; - struct nft_regs regs; + struct nft_regs regs = {}; unsigned int stackptr = 0; struct nft_jumpstack jumpstack[NFT_JUMP_STACK_SIZE]; bool genbit = READ_ONCE(net->nft.gencursor);
From: Xiang Chen chenxiang66@hisilicon.com
mainline inclusion from mainline-v5.17-rc1 commit 286ce4c65fbdf5eb9d4d5f4e4997c4e32bf1b073 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I53P0K CVE: NA
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/dr...
--------------------------------
Add a file operation for "cnt" file under bist directory, so users can only read "cnt" or clear "cnt" to zero, but cannot randomly modify.
Link: https://lore.kernel.org/r/1645703489-87194-6-git-send-email-john.garry@huawe... Signed-off-by: Xiang Chen chenxiang66@hisilicon.com Signed-off-by: Qi Liu liuqi115@huawei.com Signed-off-by: John Garry john.garry@huawei.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Fujai Ninifuijia1@hisilicon.com Reviewed-by: Jason Yan yanaijie@huawei.com Reviewed-by: Qi Liu liuqi115@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 52 +++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 2 deletions(-)
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index 16d00dbe094d..b896d60e20ac 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -3956,6 +3956,54 @@ static const struct file_operations debugfs_bist_phy_v3_hw_fops = { .owner = THIS_MODULE, };
+static ssize_t debugfs_bist_cnt_v3_hw_write(struct file *filp, + const char __user *buf, + size_t count, loff_t *ppos) +{ + struct seq_file *m = filp->private_data; + struct hisi_hba *hisi_hba = m->private; + unsigned int cnt; + int val; + + if (hisi_hba->debugfs_bist_enable) + return -EPERM; + + val = kstrtouint_from_user(buf, count, 0, &cnt); + if (val) + return val; + + if (cnt) + return -EINVAL; + + hisi_hba->debugfs_bist_cnt = 0; + return count; +} + +static int debugfs_bist_cnt_v3_hw_show(struct seq_file *s, void *p) +{ + struct hisi_hba *hisi_hba = s->private; + + seq_printf(s, "%u\n", hisi_hba->debugfs_bist_cnt); + + return 0; +} + +static int debugfs_bist_cnt_v3_hw_open(struct inode *inode, + struct file *filp) +{ + return single_open(filp, debugfs_bist_cnt_v3_hw_show, + inode->i_private); +} + +static const struct file_operations debugfs_bist_cnt_v3_hw_ops = { + .open = debugfs_bist_cnt_v3_hw_open, + .read = seq_read, + .write = debugfs_bist_cnt_v3_hw_write, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + static const struct { int value; char *name; @@ -4593,8 +4641,8 @@ static void debugfs_bist_init_v3_hw(struct hisi_hba *hisi_hba) debugfs_create_file("phy_id", 0600, hisi_hba->debugfs_bist_dentry, hisi_hba, &debugfs_bist_phy_v3_hw_fops);
- debugfs_create_u32("cnt", 0600, hisi_hba->debugfs_bist_dentry, - &hisi_hba->debugfs_bist_cnt); + debugfs_create_file("cnt", 0600, hisi_hba->debugfs_bist_dentry, + hisi_hba, &debugfs_bist_cnt_v3_hw_ops);
debugfs_create_file("loopback_mode", 0600, hisi_hba->debugfs_bist_dentry,