提交 484125f3 编写于 作者: K Keith Busch 提交者: Yang Yingliang

PCI/AER: Refactor error injection fallbacks

mainline inclusion
from mainline-v4.20-rc1
commit e51cd9ce5dd3b10f9e67a30a4dc00fc1fa80c673
category: bugfix
bugzilla: NA
CVE: NA

-------------------------------------------------

Move the bus ops fallback into separate functions.  No functional change
here.

[wangxiongfeng]

We came across the following Oops.

[ 7365.854051] Internal error: Oops: 96000004 [#1] SMP
[ 7365.858907] Process bash (pid: 110038, stack limit = 0x00000000c3909a30)
[ 7365.865580] CPU: 42 PID: 110038 Comm: bash Tainted: G           O      4.19.36-vhulk1907.1.0.h628.eulerosv2r8.aarch64 #1
[ 7365.876398] Hardware name: Huawei TaiShan 2280 V2/BC82AMDD, BIOS 1.05 09/18/2019
[ 7365.883758] pstate: 60400089 (nZCv daIf +PAN -UAO)
[ 7365.888529] pc : aer_inj_read_config+0xc4/0x1a0 [aer_inject]
[ 7365.894163] lr :           (null)
[ 7365.897462] sp : ffff000036ad37c0
[ 7365.900761] x29: ffff000036ad37c0 x28: 0000000000000001
[ 7365.906049] x27: 0000000000000001 x26: 0000000000000004
[ 7365.911338] x25: ffff000000a29000 x24: ffff000036ad3864
[ 7365.916625] x23: 0000000000000000 x22: 0000000000000000
[ 7365.921912] x21: 0000000000000080 x20: ffffa02fd7c34800
[ 7365.927201] x19: ffff000000a29020 x18: ffffffffffffffff
[ 7365.932488] x17: 0000000000000000 x16: 0000000000000000
[ 7365.937775] x15: ffff0000091d9708 x14: 6963702f302e3030
[ 7365.943064] x13: 0000000000000040 x12: 0000000000000228
[ 7365.948352] x11: 0000000000000000 x10: 0000000000000000
[ 7365.953639] x9 : 0000000000000000 x8 : ffff802fd8998000
[ 7365.958926] x7 : ffff8027df40f200 x6 : 0000000000000001
[ 7365.964213] x5 : ffff000000a26128 x4 : ffff000036ad3864
[ 7365.969501] x3 : 0000000000000004 x2 : 0000000000000000
[ 7365.974788] x1 : 0000000000000000 x0 : 0000000000000000
[ 7365.980076] Call trace:
[ 7365.982514]  aer_inj_read_config+0xc4/0x1a0 [aer_inject]
[ 7365.987805]  pci_bus_read_config_dword+0xb0/0x120
[ 7365.992488]  pci_bus_generic_read_dev_vendor_id+0xcc/0x2e0
[ 7365.997949]  pci_bus_read_dev_vendor_id+0x58/0x98
[ 7366.002631]  pci_scan_single_device+0x8c/0x110
[ 7366.007054]  pci_scan_slot+0x40/0x110
[ 7366.010700]  pci_scan_child_bus_extend+0x60/0x358
[ 7366.015383]  pci_scan_child_bus+0x24/0x30
[ 7366.019375]  pci_scan_bridge_extend+0x278/0x518
[ 7366.023886]  pci_scan_child_bus_extend+0x158/0x358
[ 7366.028654]  pci_scan_child_bus+0x24/0x30
[ 7366.032646]  pci_scan_bridge_extend+0x278/0x518
[ 7366.037155]  pci_scan_child_bus_extend+0x158/0x358
[ 7366.041923]  pci_rescan_bus+0x24/0x48
[ 7366.045568]  bus_rescan_store+0x8c/0xb0
[ 7366.049389]  bus_attr_store+0x40/0x58
[ 7366.053036]  sysfs_kf_write+0x58/0x80
[ 7366.056682]  kernfs_fop_write+0xe8/0x1f0
[ 7366.060588]  __vfs_write+0x60/0x190
[ 7366.064061]  vfs_write+0xac/0x1c0
[ 7366.067361]  ksys_write+0x6c/0xd8
[ 7366.070661]  __arm64_sys_write+0x24/0x30
[ 7366.074568]  el0_svc_common+0x78/0x130
[ 7366.078301]  el0_svc_handler+0x38/0x78
[ 7366.082033]  el0_svc+0x8/0xc
[ 7366.084902] Code: f9007280 2a1603e1 aa1803e4 2a1a03e3 (f9400c05)

When we use 'aer-inject' to inject AER error into a PCI device. The
'pci_ops' of the 'pci_bus' of the device is changed to
'aer_inj_pci_ops'. When we remove the device and rescan the PCI tree,
the 'pci_ops' of the newly allocced 'pci_bus' is also assign as
'aer_inj_pci_ops'. When we access the configuration space under the
newly allocced 'pci_bus' and the register we want to access is not an AER
register, kernel will try to find the original 'pci_ops',rather than
'aer_inj_pci_ops, and call 'pci_ops->write/read'.
For the newly allocced 'pci_bus', we can not find the original
'pci_ops', so an Oops happened. This patch add a check for 'pci_ops'
before we access its member.
Signed-off-by: NKeith Busch <keith.busch@intel.com>
Signed-off-by: NBjorn Helgaas <bhelgaas@google.com>
Signed-off-by: NXiongfeng Wang <wangxiongfeng2@huawei.com>
Reviewed-by: NHanjun Guo <guohanjun@huawei.com>
Signed-off-by: NYang Yingliang <yangyingliang@huawei.com>
上级 932cefbd
......@@ -175,14 +175,48 @@ static u32 *find_pci_config_dword(struct aer_error *err, int where,
return target;
}
static int aer_inj_read(struct pci_bus *bus, unsigned int devfn, int where,
int size, u32 *val)
{
struct pci_ops *ops, *my_ops;
int rv;
ops = __find_pci_bus_ops(bus);
if (!ops)
return -1;
my_ops = bus->ops;
bus->ops = ops;
rv = ops->read(bus, devfn, where, size, val);
bus->ops = my_ops;
return rv;
}
static int aer_inj_write(struct pci_bus *bus, unsigned int devfn, int where,
int size, u32 val)
{
struct pci_ops *ops, *my_ops;
int rv;
ops = __find_pci_bus_ops(bus);
if (!ops)
return -1;
my_ops = bus->ops;
bus->ops = ops;
rv = ops->write(bus, devfn, where, size, val);
bus->ops = my_ops;
return rv;
}
static int aer_inj_read_config(struct pci_bus *bus, unsigned int devfn,
int where, int size, u32 *val)
{
u32 *sim;
struct aer_error *err;
unsigned long flags;
struct pci_ops *ops;
struct pci_ops *my_ops;
int domain;
int rv;
......@@ -203,18 +237,7 @@ static int aer_inj_read_config(struct pci_bus *bus, unsigned int devfn,
return 0;
}
out:
ops = __find_pci_bus_ops(bus);
/*
* pci_lock must already be held, so we can directly
* manipulate bus->ops. Many config access functions,
* including pci_generic_config_read() require the original
* bus->ops be installed to function, so temporarily put them
* back.
*/
my_ops = bus->ops;
bus->ops = ops;
rv = ops->read(bus, devfn, where, size, val);
bus->ops = my_ops;
rv = aer_inj_read(bus, devfn, where, size, val);
spin_unlock_irqrestore(&inject_lock, flags);
return rv;
}
......@@ -226,8 +249,6 @@ static int aer_inj_write_config(struct pci_bus *bus, unsigned int devfn,
struct aer_error *err;
unsigned long flags;
int rw1cs;
struct pci_ops *ops;
struct pci_ops *my_ops;
int domain;
int rv;
......@@ -251,18 +272,7 @@ static int aer_inj_write_config(struct pci_bus *bus, unsigned int devfn,
return 0;
}
out:
ops = __find_pci_bus_ops(bus);
/*
* pci_lock must already be held, so we can directly
* manipulate bus->ops. Many config access functions,
* including pci_generic_config_write() require the original
* bus->ops be installed to function, so temporarily put them
* back.
*/
my_ops = bus->ops;
bus->ops = ops;
rv = ops->write(bus, devfn, where, size, val);
bus->ops = my_ops;
rv = aer_inj_write(bus, devfn, where, size, val);
spin_unlock_irqrestore(&inject_lock, flags);
return rv;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册