struct jailhouse_irqchip irqchips[1];
__u8 pio_bitmap[0x2000];
struct jailhouse_pci_device pci_devices[13];
+ struct jailhouse_pci_capability pci_caps[27];
} __attribute__((packed)) config = {
.header = {
.hypervisor_memory = {
.num_irqchips = ARRAY_SIZE(config.irqchips),
.pio_bitmap_size = ARRAY_SIZE(config.pio_bitmap),
.num_pci_devices = ARRAY_SIZE(config.pci_devices),
+ .num_pci_caps = ARRAY_SIZE(config.pci_caps),
},
},
},
.pci_devices = {
+ /* PCIDevice: 00:00.0 */
{
.type = JAILHOUSE_PCI_TYPE_DEVICE,
- .domain = 0x0000,
- .bus = 0x00,
- .devfn = 0x00,
+ .domain = 0x0,
+ .bus = 0x0,
+ .devfn = 0x0,
+ .caps_start = 0,
+ .num_caps = 1,
},
+ /* PCIDevice: 00:01.0 */
{
.type = JAILHOUSE_PCI_TYPE_BRIDGE,
- .domain = 0x0000,
- .bus = 0x00,
- .devfn = 0x08,
+ .domain = 0x0,
+ .bus = 0x0,
+ .devfn = 0x8,
+ .caps_start = 1,
+ .num_caps = 4,
},
+ /* PCIDevice: 00:02.0 */
{
.type = JAILHOUSE_PCI_TYPE_DEVICE,
- .domain = 0x0000,
- .bus = 0x00,
+ .domain = 0x0,
+ .bus = 0x0,
.devfn = 0x10,
+ .caps_start = 5,
+ .num_caps = 3,
},
+ /* PCIDevice: 00:03.0 */
{
.type = JAILHOUSE_PCI_TYPE_DEVICE,
- .domain = 0x0000,
- .bus = 0x00,
+ .domain = 0x0,
+ .bus = 0x0,
.devfn = 0x18,
+ .caps_start = 8,
+ .num_caps = 3,
},
+ /* PCIDevice: 00:14.0 */
{
.type = JAILHOUSE_PCI_TYPE_DEVICE,
- .domain = 0x0000,
- .bus = 0x00,
+ .domain = 0x0,
+ .bus = 0x0,
.devfn = 0xa0,
+ .caps_start = 11,
+ .num_caps = 2,
},
+ /* PCIDevice: 00:16.0 */
{
.type = JAILHOUSE_PCI_TYPE_DEVICE,
- .domain = 0x0000,
- .bus = 0x00,
+ .domain = 0x0,
+ .bus = 0x0,
.devfn = 0xb0,
+ .caps_start = 13,
+ .num_caps = 2,
},
+ /* PCIDevice: 00:19.0 */
{
.type = JAILHOUSE_PCI_TYPE_DEVICE,
- .domain = 0x0000,
- .bus = 0x00,
+ .domain = 0x0,
+ .bus = 0x0,
.devfn = 0xc8,
+ .caps_start = 15,
+ .num_caps = 3,
},
+ /* PCIDevice: 00:1a.0 */
{
.type = JAILHOUSE_PCI_TYPE_DEVICE,
- .domain = 0x0000,
- .bus = 0x00,
+ .domain = 0x0,
+ .bus = 0x0,
.devfn = 0xd0,
+ .caps_start = 18,
+ .num_caps = 3,
},
+ /* PCIDevice: 00:1b.0 */
{
.type = JAILHOUSE_PCI_TYPE_DEVICE,
- .domain = 0x0000,
- .bus = 0x00,
+ .domain = 0x0,
+ .bus = 0x0,
.devfn = 0xd8,
+ .caps_start = 21,
+ .num_caps = 3,
},
+ /* PCIDevice: 00:1d.0 */
{
.type = JAILHOUSE_PCI_TYPE_DEVICE,
- .domain = 0x0000,
- .bus = 0x00,
+ .domain = 0x0,
+ .bus = 0x0,
.devfn = 0xe8,
+ .caps_start = 18,
+ .num_caps = 3,
},
+ /* PCIDevice: 00:1f.0 */
{
.type = JAILHOUSE_PCI_TYPE_DEVICE,
- .domain = 0x0000,
- .bus = 0x00,
+ .domain = 0x0,
+ .bus = 0x0,
.devfn = 0xf8,
+ .caps_start = 0,
+ .num_caps = 1,
},
+ /* PCIDevice: 00:1f.2 */
{
.type = JAILHOUSE_PCI_TYPE_DEVICE,
- .domain = 0x0000,
- .bus = 0x00,
+ .domain = 0x0,
+ .bus = 0x0,
.devfn = 0xfa,
+ .caps_start = 24,
+ .num_caps = 3,
},
+ /* PCIDevice: 00:1f.3 */
{
.type = JAILHOUSE_PCI_TYPE_DEVICE,
- .domain = 0x0000,
- .bus = 0x00,
+ .domain = 0x0,
+ .bus = 0x0,
.devfn = 0xfb,
+ .caps_start = 0,
+ .num_caps = 0,
+ },
+ },
+
+ .pci_caps = {
+ /* PCIDevice: 00:00.0 */
+ /* PCIDevice: 00:1f.0 */
+ {
+ .id = 0x9,
+ .start = 0xe0,
+ .len = 2,
+ .flags = 0,
+ },
+ /* PCIDevice: 00:01.0 */
+ {
+ .id = 0xd,
+ .start = 0x88,
+ .len = 2,
+ .flags = 0,
+ },
+ {
+ .id = 0x1,
+ .start = 0x80,
+ .len = 8,
+ .flags = JAILHOUSE_PCICAPS_WRITE,
+ },
+ {
+ .id = 0x5,
+ .start = 0x90,
+ .len = 10,
+ .flags = JAILHOUSE_PCICAPS_WRITE,
+ },
+ {
+ .id = 0x10,
+ .start = 0xa0,
+ .len = 2,
+ .flags = 0,
+ },
+ /* PCIDevice: 00:02.0 */
+ {
+ .id = 0x5,
+ .start = 0x90,
+ .len = 10,
+ .flags = JAILHOUSE_PCICAPS_WRITE,
+ },
+ {
+ .id = 0x1,
+ .start = 0xd0,
+ .len = 8,
+ .flags = JAILHOUSE_PCICAPS_WRITE,
+ },
+ {
+ .id = 0x13,
+ .start = 0xa4,
+ .len = 2,
+ .flags = 0,
+ },
+ /* PCIDevice: 00:03.0 */
+ {
+ .id = 0x1,
+ .start = 0x50,
+ .len = 8,
+ .flags = JAILHOUSE_PCICAPS_WRITE,
+ },
+ {
+ .id = 0x5,
+ .start = 0x60,
+ .len = 10,
+ .flags = JAILHOUSE_PCICAPS_WRITE,
+ },
+ {
+ .id = 0x10,
+ .start = 0x70,
+ .len = 2,
+ .flags = 0,
+ },
+ /* PCIDevice: 00:14.0 */
+ {
+ .id = 0x1,
+ .start = 0x70,
+ .len = 8,
+ .flags = JAILHOUSE_PCICAPS_WRITE,
+ },
+ {
+ .id = 0x5,
+ .start = 0x80,
+ .len = 14,
+ .flags = JAILHOUSE_PCICAPS_WRITE,
+ },
+ /* PCIDevice: 00:16.0 */
+ {
+ .id = 0x1,
+ .start = 0x50,
+ .len = 8,
+ .flags = JAILHOUSE_PCICAPS_WRITE,
+ },
+ {
+ .id = 0x5,
+ .start = 0x8c,
+ .len = 14,
+ .flags = JAILHOUSE_PCICAPS_WRITE,
+ },
+ /* PCIDevice: 00:19.0 */
+ {
+ .id = 0x1,
+ .start = 0xc8,
+ .len = 8,
+ .flags = JAILHOUSE_PCICAPS_WRITE,
+ },
+ {
+ .id = 0x5,
+ .start = 0xd0,
+ .len = 14,
+ .flags = JAILHOUSE_PCICAPS_WRITE,
+ },
+ {
+ .id = 0x13,
+ .start = 0xe0,
+ .len = 2,
+ .flags = 0,
+ },
+ /* PCIDevice: 00:1a.0 */
+ /* PCIDevice: 00:1d.0 */
+ {
+ .id = 0x1,
+ .start = 0x50,
+ .len = 8,
+ .flags = JAILHOUSE_PCICAPS_WRITE,
+ },
+ {
+ .id = 0xa,
+ .start = 0x58,
+ .len = 2,
+ .flags = 0,
+ },
+ {
+ .id = 0x13,
+ .start = 0x98,
+ .len = 2,
+ .flags = 0,
+ },
+ /* PCIDevice: 00:1b.0 */
+ {
+ .id = 0x1,
+ .start = 0x50,
+ .len = 8,
+ .flags = JAILHOUSE_PCICAPS_WRITE,
+ },
+ {
+ .id = 0x5,
+ .start = 0x60,
+ .len = 14,
+ .flags = JAILHOUSE_PCICAPS_WRITE,
+ },
+ {
+ .id = 0x10,
+ .start = 0x70,
+ .len = 2,
+ .flags = 0,
+ },
+ /* PCIDevice: 00:1f.2 */
+ {
+ .id = 0x5,
+ .start = 0x80,
+ .len = 10,
+ .flags = JAILHOUSE_PCICAPS_WRITE,
+ },
+ {
+ .id = 0x1,
+ .start = 0x70,
+ .len = 8,
+ .flags = JAILHOUSE_PCICAPS_WRITE,
+ },
+ {
+ .id = 0x12,
+ .start = 0xa8,
+ .len = 2,
+ .flags = 0,
},
},
};
struct jailhouse_memory mem_regions[3];
__u8 pio_bitmap[0x2000];
struct jailhouse_pci_device pci_devices[1];
+ struct jailhouse_pci_capability pci_caps[1];
} __attribute__((packed)) config = {
.cell = {
.name = "pci-demo",
.num_irqchips = 0,
.pio_bitmap_size = ARRAY_SIZE(config.pio_bitmap),
.num_pci_devices = ARRAY_SIZE(config.pci_devices),
+ .num_pci_caps = ARRAY_SIZE(config.pci_caps),
},
.cpus = {
.domain = 0x0000,
.bus = 0x00,
.devfn = 0xd8,
+ .caps_start = 0,
+ .num_caps = 1,
+ },
+ },
+
+ .pci_caps = {
+ { /* Intel HDA @00:1b.0 */
+ .id = 0x5,
+ .start = 0x50,
+ .len = 14,
+ .flags = JAILHOUSE_PCICAPS_WRITE,
},
},
};
struct jailhouse_irqchip irqchips[1];
__u8 pio_bitmap[0x2000];
struct jailhouse_pci_device pci_devices[9];
+ struct jailhouse_pci_capability pci_caps[3];
} __attribute__((packed)) config = {
.header = {
.hypervisor_memory = {
.num_irqchips = ARRAY_SIZE(config.irqchips),
.pio_bitmap_size = ARRAY_SIZE(config.pio_bitmap),
.num_pci_devices = ARRAY_SIZE(config.pci_devices),
+ .num_pci_caps = ARRAY_SIZE(config.pci_caps),
},
},
.domain = 0x0000,
.bus = 0x00,
.devfn = 0x18,
+ .caps_start = 0, /* for q35 */
+ .num_caps = 1,
},
{ /* 440fx: virtio-9p-pci */
.type = JAILHOUSE_PCI_TYPE_DEVICE,
.domain = 0x0000,
.bus = 0x00,
.devfn = 0x20,
+ .caps_start = 0,
+ .num_caps = 1,
},
{ /* q35: ISA bridge */
.type = JAILHOUSE_PCI_TYPE_DEVICE,
.domain = 0x0000,
.bus = 0x00,
.devfn = 0xfa,
+ .caps_start = 2,
+ .num_caps = 2,
},
{ /* q35: SMBus */
.type = JAILHOUSE_PCI_TYPE_DEVICE,
.devfn = 0xfb,
},
},
+
+ .pci_caps = {
+ { /* virtio-9p-pci */
+ .id = 0x11,
+ .start = 0x40,
+ .len = 12,
+ .flags = JAILHOUSE_PCICAPS_WRITE,
+ },
+ { /* AHCI */
+ .id = 0x12,
+ .start = 0xa8,
+ .len = 2,
+ .flags = 0,
+ },
+ {
+ .id = 0x5,
+ .start = 0x50,
+ .len = 14,
+ .flags = JAILHOUSE_PCICAPS_WRITE,
+ },
+ },
};
__u32 num_irqchips;
__u32 pio_bitmap_size;
__u32 num_pci_devices;
+ __u32 num_pci_caps;
} __attribute__((packed));
#define JAILHOUSE_MEM_READ 0x0001
__u16 domain;
__u8 bus;
__u8 devfn;
+ __u16 caps_start;
+ __u16 num_caps;
+} __attribute__((packed));
+
+#define JAILHOUSE_PCICAPS_WRITE 0x0001
+
+struct jailhouse_pci_capability {
+ __u16 id;
+ __u16 start;
+ __u16 len;
+ __u16 flags;
} __attribute__((packed));
struct jailhouse_system {
cell->num_memory_regions * sizeof(struct jailhouse_memory) +
cell->num_irqchips * sizeof(struct jailhouse_irqchip) +
cell->pio_bitmap_size +
- cell->num_pci_devices * sizeof(struct jailhouse_pci_device);
+ cell->num_pci_devices * sizeof(struct jailhouse_pci_device) +
+ cell->num_pci_caps * sizeof(struct jailhouse_pci_capability);
}
static inline __u32
cell->pio_bitmap_size);
}
+static inline const struct jailhouse_pci_capability *
+jailhouse_cell_pci_caps(const struct jailhouse_cell_desc *cell)
+{
+ return (const struct jailhouse_pci_capability *)
+ ((void *)jailhouse_cell_pci_devices(cell) +
+ cell->num_pci_devices * sizeof(struct jailhouse_pci_device));
+}
+
#endif /* !_JAILHOUSE_CELL_CONFIG_H */
inputs = {'files': set(), 'files_opt': set(), 'dirs': set()}
+class PCICapability:
+ def __init__(self, id, start, len, flags):
+ self.id = id
+ self.start = start
+ self.len = len
+ self.flags = flags
+ self.comments = []
+
+ def __eq__(self, other):
+ return self.id == other.id and self.start == other.start and \
+ self.len == other.len and self.flags == other.flags
+
+ RD = '0'
+ RW = 'JAILHOUSE_PCICAPS_WRITE'
+
+ @staticmethod
+ def parse_pcicaps(dir):
+ caps = []
+ f = input_open(dir + '/config', 'rb')
+ f.seek(0x06)
+ (status,) = struct.unpack('<H', f.read(2))
+ # capability list supported?
+ if (status & (1 << 4)) == 0:
+ f.close()
+ return caps
+ # walk capability list
+ f.seek(0x34)
+ (next,) = struct.unpack('B', f.read(1))
+ while next != 0:
+ cap = next
+ f.seek(cap)
+ (id, next) = struct.unpack('<BB', f.read(2))
+ if id == 0x01: # Power Management
+ # this cap can be handed out completely
+ len = 8
+ flags = PCICapability.RW
+ elif id == 0x05: # MSI
+ # access will be moderated by hypervisor
+ len = 10
+ (msgctl,) = struct.unpack('<H', f.read(2))
+ if (msgctl & (1 << 7)) != 0: # 64-bit support
+ len += 4
+ if (msgctl & (1 << 8)) != 0: # per-vector masking support
+ len += 10
+ flags = PCICapability.RW
+ elif id == 0x11: # MSI-X
+ # access will be moderated by hypervisor
+ len = 12
+ flags = PCICapability.RW
+ else:
+ # unknown/unhandled cap, mark its existence
+ len = 2
+ flags = PCICapability.RD
+ caps.append(PCICapability(id, cap, len, flags))
+ return caps
+
+
class PCIDevice:
- def __init__(self, type, domain, bus, dev, fn):
+ def __init__(self, type, domain, bus, dev, fn, caps):
self.type = type
self.domain = domain
self.bus = bus
self.dev = dev
self.fn = fn
+ self.caps = caps
+ self.caps_start = 0
+ self.num_caps = 0
def __str__(self):
return 'PCIDevice: %02x:%02x.%x' % (self.bus, self.dev, self.fn)
@staticmethod
def parse_pcidevice_sysfsdir(basedir, dir):
- dclass = input_readline(basedir + '/' + dir + '/class')
+ dpath = basedir + '/' + dir
+ dclass = input_readline(dpath + '/class')
if re.match(r'0x0604..', dclass):
type = 'JAILHOUSE_PCI_TYPE_BRIDGE'
else:
domain = int(a[0], 16)
bus = int(a[1], 16)
df = a[2].split('.')
- return PCIDevice(type, domain, bus, int(df[0], 16), int(df[1], 16))
+ caps = PCICapability.parse_pcicaps(dpath)
+ return PCIDevice(type, domain, bus, int(df[0], 16), int(df[1], 16),
+ caps)
class MemRegion:
def parse_pcidevices():
devices = []
+ caps = []
basedir = '/sys/bus/pci/devices'
- list = input_listdir(basedir, ['*/class'])
+ list = input_listdir(basedir, ['*/class', '*/config'])
for dir in list:
d = PCIDevice.parse_pcidevice_sysfsdir(basedir, dir)
if d is not None:
+ if len(d.caps) > 0:
+ duplicate = False
+ # look for duplicate capability patterns
+ for d2 in devices:
+ if d2.caps == d.caps:
+ # reused existing capability list, but record all users
+ d2.caps[0].comments.append(str(d))
+ d.caps_start = d2.caps_start
+ d.num_caps = d2.num_caps
+ duplicate = True
+ break
+ if not duplicate:
+ d.caps[0].comments.append(str(d))
+ d.caps_start = len(caps)
+ d.num_caps = len(d.caps)
+ caps.extend(d.caps)
devices.append(d)
- return devices
+ return (devices, caps)
def kmg_multiply(value, kmg):
return pm_timer_base
-pcidevices = parse_pcidevices()
+(pcidevices, pcicaps) = parse_pcidevices()
product = [input_readline('/sys/class/dmi/id/sys_vendor',
True).rstrip(),
confmem=confmem,
product=product,
pcidevices=pcidevices,
+ pcicaps=pcicaps,
cpucount=cpucount,
ioapic_id=ioapic_id,
pm_timer_base=pm_timer_base))
struct jailhouse_irqchip irqchips[1];
__u8 pio_bitmap[0x2000];
struct jailhouse_pci_device pci_devices[${len(pcidevices)}];
+ struct jailhouse_pci_capability pci_caps[${len(pcicaps)}];
} __attribute__((packed)) config = {
.header = {
.hypervisor_memory = {
.num_irqchips = ARRAY_SIZE(config.irqchips),
.pio_bitmap_size = ARRAY_SIZE(config.pio_bitmap),
.num_pci_devices = ARRAY_SIZE(config.pci_devices),
+ .num_pci_caps = ARRAY_SIZE(config.pci_caps),
},
},
.domain = ${hex(d.domain)},
.bus = ${hex(d.bus)},
.devfn = ${hex(d.devfn())},
+ .caps_start = ${d.caps_start},
+ .num_caps = ${d.num_caps},
+ },
+ % endfor
+ },
+
+ .pci_caps = {
+ % for c in pcicaps:
+ % for comment in c.comments:
+ /* ${comment} */
+ % endfor
+ {
+ .id = ${hex(c.id)},
+ .start = ${hex(c.start)},
+ .len = ${c.len},
+ .flags = ${c.flags},
},
% endfor
},