FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

pci/multikernel: virtualize assigned config access · multikernel/linux@f45edca · GitHub

forked from torvalds/linux

Commit f45edca

Browse files
committed
pci/multikernel: virtualize assigned config access
Filter root PCI config access in arch/x86/multikernel. Synthesize assigned VF identity and restore BARs with a PCI header fixup. Remove multikernel branches from drivers/pci/probe.c. Signed-off-by: Nikolay Nikolaev <nicknickolaev@gmail.com>
1 parent 1e1918e commit f45edca

4 files changed

Lines changed: 71 additions & 30 deletions

File tree

‎arch/x86/multikernel/pci.c‎

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,47 @@ struct mk_mmcfg_snapshot {
2121
size_t count;
2222
};
2323

24+
static struct pci_ops mk_pci_native_ops;
25+
26+
static bool mk_pci_identity_read(struct pci_bus *bus, unsigned int devfn,
27+
int where, int size, u32 *value)
28+
{
29+
u16 vendor, device;
30+
u32 identity;
31+
u32 mask;
32+
33+
if (where < PCI_VENDOR_ID || where + size > PCI_COMMAND ||
34+
!mk_pci_get_assigned_identity(bus, devfn, &vendor, &device))
35+
return false;
36+
37+
identity = vendor | (u32)device << 16;
38+
mask = size == sizeof(identity) ? ~0U : (1U << (size * 8)) - 1;
39+
*value = (identity >> (where * 8)) & mask;
40+
return true;
41+
}
42+
43+
static int mk_pci_read(struct pci_bus *bus, unsigned int devfn, int where,
44+
int size, u32 *value)
45+
{
46+
if (!mk_pci_should_probe(bus, devfn, &mk_pci_native_ops)) {
47+
*value = ~0U;
48+
return PCIBIOS_DEVICE_NOT_FOUND;
49+
}
50+
if (mk_pci_identity_read(bus, devfn, where, size, value))
51+
return PCIBIOS_SUCCESSFUL;
52+
53+
return mk_pci_native_ops.read(bus, devfn, where, size, value);
54+
}
55+
56+
static int mk_pci_write(struct pci_bus *bus, unsigned int devfn, int where,
57+
int size, u32 value)
58+
{
59+
if (!mk_pci_should_probe(bus, devfn, &mk_pci_native_ops))
60+
return PCIBIOS_DEVICE_NOT_FOUND;
61+
62+
return mk_pci_native_ops.write(bus, devfn, where, size, value);
63+
}
64+
2465
#ifdef CONFIG_PCI_MMCONFIG
2566
static int mk_mmcfg_snapshot_region(const struct pci_mmcfg_region *region,
2667
void *data)
@@ -98,6 +139,9 @@ static int __init x86_multikernel_pci_arch_init(void)
98139

99140
raw_pci_ops = &pci_mmcfg;
100141
raw_pci_ext_ops = &pci_mmcfg;
142+
mk_pci_native_ops = pci_root_ops;
143+
pci_root_ops.read = mk_pci_read;
144+
pci_root_ops.write = mk_pci_write;
101145
pr_notice("Multikernel selected ECAM for PCI config access\n");
102146

103147
return 0;

‎drivers/pci/probe.c‎

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,6 @@
2222
#include <linux/irqdomain.h>
2323
#include <linux/pm_runtime.h>
2424
#include <linux/bitfield.h>
25-
#ifdef CONFIG_MULTIKERNEL
26-
#include <linux/multikernel.h>
27-
#endif
2825
#include "pci.h"
2926

3027
#define CARDBUS_LATENCY_TIMER 176 /* secondary latency timer */
@@ -2625,14 +2622,6 @@ static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn)
26252622
struct pci_dev *dev;
26262623
u32 l;
26272624

2628-
/*
2629-
* For multikernel spawns, check if we should even probe this location
2630-
* BEFORE any config space access. This prevents hardware conflicts
2631-
* when the host kernel is also using PCI devices.
2632-
*/
2633-
if (IS_ENABLED(CONFIG_MULTIKERNEL) && !mk_pci_should_probe(bus, devfn))
2634-
return NULL;
2635-
26362625
/*
26372626
* Create pwrctrl device (if required) for the PCI device to handle the
26382627
* power state. If the pwrctrl device is created, then skip scanning

‎include/linux/multikernel.h‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
#include <linux/genalloc.h>
1616
#include <linux/sizes.h>
1717
struct pci_bus;
18-
struct pci_dev;
18+
struct pci_ops;
1919

2020
/**
2121
* Multikernel IPI interface
@@ -873,10 +873,10 @@ void __init mk_register_cpus_from_kho(void);
873873
*
874874
* Returns: true if probing should proceed, false to skip entirely
875875
*/
876-
bool mk_pci_should_probe(struct pci_bus *bus, int devfn);
876+
bool mk_pci_should_probe(struct pci_bus *bus, int devfn,
877+
const struct pci_ops *ops);
877878
bool mk_pci_get_assigned_identity(struct pci_bus *bus, int devfn,
878879
u16 *vendor, u16 *device);
879-
void mk_pci_restore_resources(struct pci_dev *dev);
880880

881881
/**
882882
* mk_platform_device_allowed() - Check if a platform device is allowed by DTB allowlist

‎kernel/multikernel/pci.c‎

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@
1212

1313
#include "internal.h"
1414

15-
static struct mk_pci_device *mk_pci_find_assigned(struct pci_bus *bus,
16-
int devfn)
15+
static struct mk_pci_device *mk_pci_find_assigned(struct pci_bus *bus, int devfn)
1716
{
1817
struct mk_pci_device *device;
1918
u16 domain = pci_domain_nr(bus);
@@ -52,13 +51,10 @@ bool mk_pci_get_assigned_identity(struct pci_bus *bus, int devfn,
5251

5352
*vendor = device->vendor;
5453
*device_id = device->device;
55-
pr_notice("MK_SECONDARY_ASSIGNED_PCI_IDENTITY bdf=%04x:%02x:%02x.%x vendor=%04x device=%04x\n",
56-
device->domain, device->bus, device->slot, device->func,
57-
*vendor, *device_id);
5854
return true;
5955
}
6056

61-
void mk_pci_restore_resources(struct pci_dev *dev)
57+
static void mk_pci_restore_resources(struct pci_dev *dev)
6258
{
6359
struct mk_pci_device *device;
6460
int i;
@@ -75,23 +71,33 @@ void mk_pci_restore_resources(struct pci_dev *dev)
7571
}
7672
pr_info("Restored PCI BAR resources for %s\n", pci_name(dev));
7773
}
78-
EXPORT_SYMBOL_GPL(mk_pci_restore_resources);
7974

80-
static bool mk_pci_bridge_reaches_assigned(struct pci_bus *bus, int devfn)
75+
DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, mk_pci_restore_resources);
76+
77+
static bool mk_pci_bridge_reaches_assigned(struct pci_bus *bus, int devfn,
78+
const struct pci_ops *ops)
8179
{
8280
struct mk_pci_device *device;
8381
u16 domain = pci_domain_nr(bus);
8482
u8 secondary_bus = 0;
8583
u8 subordinate_bus = 0;
8684
u8 hdr_type;
85+
u32 value;
8786

88-
if (pci_bus_read_config_byte(bus, devfn, PCI_HEADER_TYPE, &hdr_type) ||
89-
(hdr_type & PCI_HEADER_TYPE_MASK) != PCI_HEADER_TYPE_BRIDGE)
87+
if (ops->read(bus, devfn, PCI_HEADER_TYPE, sizeof(hdr_type), &value))
88+
return false;
89+
hdr_type = value;
90+
if ((hdr_type & PCI_HEADER_TYPE_MASK) != PCI_HEADER_TYPE_BRIDGE)
9091
return false;
9192

92-
pci_bus_read_config_byte(bus, devfn, PCI_SECONDARY_BUS, &secondary_bus);
93-
pci_bus_read_config_byte(bus, devfn, PCI_SUBORDINATE_BUS,
94-
&subordinate_bus);
93+
if (ops->read(bus, devfn, PCI_SECONDARY_BUS, sizeof(secondary_bus),
94+
&value))
95+
return false;
96+
secondary_bus = value;
97+
if (ops->read(bus, devfn, PCI_SUBORDINATE_BUS,
98+
sizeof(subordinate_bus), &value))
99+
return false;
100+
subordinate_bus = value;
95101
if (!secondary_bus || subordinate_bus < secondary_bus)
96102
return false;
97103

@@ -108,18 +114,20 @@ static bool mk_pci_bridge_reaches_assigned(struct pci_bus *bus, int devfn)
108114
* mk_pci_should_probe - Check whether PCI probing may access a location
109115
* @bus: PCI bus
110116
* @devfn: device/function number
117+
* @ops: unfiltered config-space operations used to identify bridge paths
111118
*
112119
* Exact assigned functions and bridges leading to downstream assignments are
113120
* visible. Other functions are rejected before their config space is read.
114121
*
115122
* Returns: true if probing should proceed, false to skip entirely.
116123
*/
117-
bool mk_pci_should_probe(struct pci_bus *bus, int devfn)
124+
bool mk_pci_should_probe(struct pci_bus *bus, int devfn,
125+
const struct pci_ops *ops)
118126
{
119127
struct mk_pci_device *device;
120128
u16 domain = pci_domain_nr(bus);
121129

122-
if (!root_instance || !root_instance->dtb_data)
130+
if (!ops || !root_instance || !root_instance->dtb_data)
123131
return true;
124132
if (!root_instance->pci_devices_valid ||
125133
!root_instance->pci_device_count)
@@ -129,7 +137,7 @@ bool mk_pci_should_probe(struct pci_bus *bus, int devfn)
129137

130138
list_for_each_entry(device, &root_instance->pci_devices, list) {
131139
if (device->domain == domain && device->bus > bus->number)
132-
return mk_pci_bridge_reaches_assigned(bus, devfn);
140+
return mk_pci_bridge_reaches_assigned(bus, devfn, ops);
133141
}
134142

135143
return false;

0 commit comments

Comments
 (0)

Back | FazBrowse Home | New Git URL