Skip to content

Commit

Permalink
PCI: host-generic: Fix NULL pointer dereference on 32-bit CAM systems
Browse files Browse the repository at this point in the history
CAM (legacy) host drivers also need to refer to pci_ecam_add_bus and
pci_ecam_remove_bus functions to get mapped resources on 32-bit systems.
This is because 32-bit systems have separate iomap resources per bus
segment and pci_ecam_add_bus is the one that sets that up. Move the
pci_ecam_ops for CAM mode to ecam.c so we can refer the static functions.

This fixes :

[    1.356001] pci-host-generic 30000000.pci: host bridge /soc/pci@30000000 ranges:
[    1.365324] pci-host-generic 30000000.pci:      MEM 0x0040000000..0x004fffffff -> 0x0040000000
[    1.375556] pci-host-generic 30000000.pci:      MEM 0x0050000000..0x006fffffff -> 0x0050000000
[    1.386132] pci-host-generic 30000000.pci: ECAM at [mem 0x30000000-0x30ffffff] for [bus 00-ff]
[    1.399490] pci-host-generic 30000000.pci: PCI host bridge to bus 0000:00
[    1.407073] pci_bus 0000:00: root bus resource [bus 00-ff]
[    1.413648] pci_bus 0000:00: root bus resource [mem 0x40000000-0x4fffffff]
[    1.421718] pci_bus 0000:00: root bus resource [mem 0x50000000-0x6fffffff pref]
[    1.430647] Unable to handle kernel NULL pointer dereference at virtual address 00000800
[    1.439441] Oops [#1]
[    1.442152] CPU: 0 PID: 1 Comm: swapper Not tainted 6.9.7+ torvalds#43
[    1.448753] Hardware name: Digilent Nexys-Video-A7 RV32 (DT)
[    1.454968] epc : pci_generic_config_read+0x40/0xb0
[    1.460652]  ra : pci_generic_config_read+0x2c/0xb0
[    1.466322] epc : c038db9c ra : c038db88 sp : c1c3bc20
[    1.472095]  gp : c18726d0 tp : c1c5c000 t0 : 0000006e
[    1.477859]  t1 : 00000063 t2 : 00000000 s0 : c1c3bc30
[    1.483604]  s1 : 00000004 a0 : 00000800 a1 : 00000800
[    1.489348]  a2 : 00000000 a3 : 00000008 a4 : c1d15800
[    1.495090]  a5 : 00000002 a6 : 0000008a a7 : c1809ec0
[    1.500844]  s2 : c1c3bc38 s3 : 0000ea60 s4 : 00000008
[    1.506600]  s5 : c1ce4a00 s6 : 00000006 s7 : c11c7460
[    1.512353]  s8 : 00000008 s9 : c0800108 s10: 00000000
[    1.518095]  s11: 00000000 t3 : 3ffff7ff t4 : 00000000
[    1.523833]  t5 : 00000001 t6 : 00000000
[    1.528252] status: 00000100 badaddr: 00000800 cause: 0000000d
[    1.534729] [<c038db9c>] pci_generic_config_read+0x40/0xb0
[    1.541096] [<c038da04>] pci_bus_read_config_dword+0x50/0xb0
[    1.547623] [<c0391e94>] pci_bus_generic_read_dev_vendor_id+0x3c/0x1ec
[    1.555010] [<c039245c>] pci_scan_single_device+0xa4/0x11c
[    1.561273] [<c0392570>] pci_scan_slot+0x9c/0x23c
[    1.566716] [<c039388c>] pci_scan_child_bus_extend+0x58/0x2f4
[    1.573275] [<c0393db0>] pci_scan_root_bus_bridge+0x64/0xe8
[    1.579650] [<c0393e54>] pci_host_probe+0x20/0xc8
[    1.585104] [<c03bc6f4>] pci_host_common_probe+0x144/0x1e4
[    1.591396] [<c042ec20>] platform_probe+0x54/0x9c
[    1.596957] [<c042b5c8>] really_probe+0xbc/0x418
[    1.602367] [<c042bb0c>] __driver_probe_device+0x70/0xfc
[    1.608507] [<c042bbe0>] driver_probe_device+0x48/0xf0
[    1.614487] [<c042be98>] __driver_attach+0xbc/0x264
[    1.620190] [<c0428d04>] bus_for_each_dev+0x84/0xf8
[    1.625868] [<c042aeec>] driver_attach+0x28/0x38
[    1.631269] [<c042a510>] bus_add_driver+0x140/0x278
[    1.636956] [<c042cf48>] driver_register+0x70/0x15c
[    1.642666] [<c042e8f8>] __platform_driver_register+0x28/0x38
[    1.649332] [<c081b694>] gen_pci_driver_init+0x24/0x34
[    1.655241] [<c0801424>] do_one_initcall+0x88/0x164
[    1.660943] [<c0801768>] kernel_init_freeable+0x1dc/0x264
[    1.667199] [<c0699f34>] kernel_init+0x28/0x138
[    1.672578] [<c06a0b5c>] ret_from_fork+0x14/0x24
[    1.678399] Code: 0463 0605 0793 0010 8663 04f4 0793 0020 8663 02f4 (2503) 0005
[    1.686462] ---[ end trace 0000000000000000 ]---
[    1.691591] Kernel panic - not syncing: Fatal exception

Signed-off-by: Steffen Persvold <spersvold@gmail.com>
  • Loading branch information
spersvold authored and intel-lab-lkp committed Aug 20, 2024
1 parent 79b01ef commit e1bb29b
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 10 deletions.
11 changes: 1 addition & 10 deletions drivers/pci/controller/pci-host-generic.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,6 @@
#include <linux/pci-ecam.h>
#include <linux/platform_device.h>

static const struct pci_ecam_ops gen_pci_cfg_cam_bus_ops = {
.bus_shift = 16,
.pci_ops = {
.map_bus = pci_ecam_map_bus,
.read = pci_generic_config_read,
.write = pci_generic_config_write,
}
};

static bool pci_dw_valid_device(struct pci_bus *bus, unsigned int devfn)
{
struct pci_config_window *cfg = bus->sysdata;
Expand Down Expand Up @@ -58,7 +49,7 @@ static const struct pci_ecam_ops pci_dw_ecam_bus_ops = {

static const struct of_device_id gen_pci_of_match[] = {
{ .compatible = "pci-host-cam-generic",
.data = &gen_pci_cfg_cam_bus_ops },
.data = &pci_generic_cam_ops },

{ .compatible = "pci-host-ecam-generic",
.data = &pci_generic_ecam_ops },
Expand Down
13 changes: 13 additions & 0 deletions drivers/pci/ecam.c
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,19 @@ const struct pci_ecam_ops pci_generic_ecam_ops = {
};
EXPORT_SYMBOL_GPL(pci_generic_ecam_ops);

/* CAM ops */
const struct pci_ecam_ops pci_generic_cam_ops = {
.bus_shift = 16,
.pci_ops = {
.add_bus = pci_ecam_add_bus,
.remove_bus = pci_ecam_remove_bus,
.map_bus = pci_ecam_map_bus,
.read = pci_generic_config_read,
.write = pci_generic_config_write,
}
};
EXPORT_SYMBOL_GPL(pci_generic_cam_ops);

#if defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS)
/* ECAM ops for 32-bit access only (non-compliant) */
const struct pci_ecam_ops pci_32b_ops = {
Expand Down
3 changes: 3 additions & 0 deletions include/linux/pci-ecam.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ void __iomem *pci_ecam_map_bus(struct pci_bus *bus, unsigned int devfn,
/* default ECAM ops */
extern const struct pci_ecam_ops pci_generic_ecam_ops;

/* default CAM ops */
extern const struct pci_ecam_ops pci_generic_cam_ops;

#if defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS)
extern const struct pci_ecam_ops pci_32b_ops; /* 32-bit accesses only */
extern const struct pci_ecam_ops pci_32b_read_ops; /* 32-bit read only */
Expand Down

0 comments on commit e1bb29b

Please sign in to comment.