From: Peter Dinda Date: Wed, 9 Jul 2008 00:44:38 +0000 (+0000) Subject: Fixes to PCI scanning and configuration storage X-Git-Tag: reaches-user-mode-on-qemu-and-both-amd-boxes-nested-paging-faults~13 X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=commitdiff_plain;h=c1e082c26ab3f0b7cc183a7709f90ef4c3f7ad3d Fixes to PCI scanning and configuration storage Plus it now knows about bridges --- diff --git a/palacios/src/geekos/kthread.c b/palacios/src/geekos/kthread.c index 1a67775..0cba546 100644 --- a/palacios/src/geekos/kthread.c +++ b/palacios/src/geekos/kthread.c @@ -1,7 +1,7 @@ /* * Kernel threads * Copyright (c) 2001,2003 David H. Hovemeyer - * $Revision: 1.3 $ + * $Revision: 1.4 $ * * This is free software. You are permitted to use, * redistribute, and modify it as specified in the file "COPYING". @@ -561,7 +561,7 @@ void Schedule(void) * it was called from. */ - SerialPrint("Switch_To_Thread() in Schedule()\n"); + //SerialPrint("Switch_To_Thread() in Schedule()\n"); Switch_To_Thread(runnable); } diff --git a/palacios/src/geekos/pci.c b/palacios/src/geekos/pci.c index 3657bcf..c276552 100644 --- a/palacios/src/geekos/pci.c +++ b/palacios/src/geekos/pci.c @@ -10,28 +10,124 @@ struct pci_device_config { - ushort_t device_id; ushort_t vendor_id; - ushort_t status; + ushort_t device_id; ushort_t command; - uchar_t class_code; - uchar_t subclass; - ushort_t revision; - uchar_t BIST; - uchar_t header_type; - uchar_t latency_time; + ushort_t status; + uchar_t revision; + uchar_t class_code[3]; // in order: programming interface, subclass, class code + +#define PROG_INTERFACE(x) ((x)[0]) +#define SUBCLASS(x) ((x)[1]) +#define CLASSCODE(x) ((x)[2]) + + uchar_t cache_line_size; - uint_t BAR[6]; - uint_t cardbus_cis_pointer; - ushort_t subsystem_id; - ushort_t subsystem_vendor_id; - uint_t expansion_rom_address; - uint_t reserved[2]; - uchar_t max_latency; - uchar_t min_grant; - uchar_t intr_pin; - uchar_t intr_line; -} __attribute__((__packed__)) ; + uchar_t latency_time; + uchar_t header_type; // bits 6-0: 00: other, 01: pci-pci bridge, 02: pci-cardbus; bit 7: 1=multifunction + +#define HEADER_TYPE(x) ((x)&0x7f) + +#define PCI_DEVICE 0x0 +#define PCI_PCI_BRIDGE 0x1 +#define PCI_CARDBUS_BRIDGE 0x2 + +#define MULTIFUNCTION(x) ((x)&0x80) + +#define IS_DEVICE(x) (HEADER_TYPE(x)==0x0) +#define IS_PCI_PCI_BRIDGE(x) (HEADER_TYPE(x)==0x1) +#define IS_PCI_CARDBUS_BRIDGE(x) (HEADER_TYPE(x)==0x2) + + uchar_t BIST; + + union { + + // header = 00 (Device) + struct { + uint_t BAR[6]; + +#define IS_IO_ADDR(x) ((x)&0x1) +#define IS_MEM_ADDR(x) (!((x)&0x1)) +#define GET_IO_ADDR(x) (((uint_t)(x))&0xfffffffc) +#define GET_MEM_ADDR(x) (((uint_t)(x))&0xfffffff0) +#define GET_MEM_TYPE(x) (((x)&0x6)>>2) +#define GET_MEM_PREFETCHABLE(x) ((x)&0x8) + + uint_t cardbus_cis_pointer; + ushort_t subsystem_vendor_id; + ushort_t subsystem_id; + uint_t expansion_rom_address; + uchar_t cap_ptr; // capabilities list offset in config space + uchar_t reserved[7]; + uchar_t intr_line; // 00=none, 01=IRQ1, etc. + uchar_t intr_pin; // 00=none, otherwise INTA# to INTD# + uchar_t min_grant; // min busmaster time - units of 250ns + uchar_t max_latency; // units of 250ns - busmasters + uint_t device_data[48]; + } __attribute__((__packed__)) pci_device_config; + + // header = 01 (pci-pci bridge) + struct { + uint_t BAR[2]; + uchar_t primary_bus; // the one closer to the processor + uchar_t secondary_bus; // the one further away + uchar_t subordinate_bus; + uchar_t secondary_lat_timer; + uchar_t io_base; + uchar_t io_limit; + ushort_t secondary_status; + ushort_t memory_base; + ushort_t memory_limit; + ushort_t prefetchable_memory_base; + ushort_t prefetchable_memory_limit; + uint_t prefetchable_memory_base_upper; // for 64 bit? + uint_t prefetchable_memory_limit_upper; + ushort_t io_base_upper; // upper 16 + ushort_t io_limit_upper; + uint_t reserved; + uint_t expansion_rom_address; + uchar_t intr_line; + uchar_t intr_pin; + ushort_t bridge_ctl; + uint_t device_data[48]; + } __attribute__((__packed__)) pci_pci_bridge_config; + + + // header = 02 (pci-cardbus bridge) + struct { + uint_t cardbus_base_addr; + uchar_t cap_ptr; + uchar_t reserved; + ushort_t secondary_status; + uchar_t pci_bus; + uchar_t cardbus_bus; + uchar_t subordinate_bus; + uchar_t cardbus_lat_timer; + uint_t memory_base0; + uint_t memory_limit0; + uint_t memory_base1; + uint_t memory_limit1; + ushort_t io_base0; + ushort_t io_base0_upper; + ushort_t io_limit0; + ushort_t io_limit0_upper; + ushort_t io_base1; + ushort_t io_base1_upper; + ushort_t io_limit1; + ushort_t io_limit1_upper; + uchar_t intr_line; + uchar_t intr_pin; + ushort_t bridge_ctl; + ushort_t subsystem_vendor_id; + ushort_t subsystem_device_id; + uint_t legacy_16bit_base_addr; + uint_t reserved2[14]; + uint_t device_data[32]; + } __attribute__((__packed__)) pci_cardbus_bridge_config; + + } __attribute__((__packed__)) u; + +}; struct pci_bus { uint_t number; @@ -195,39 +291,179 @@ static struct pci *ScanPCI() return thepci; } -static void PrintPCIDevice(struct pci_device *thedev) +static void PrintPCIShared(struct pci_device *thedev) { - PrintBoth(" PCI Device: \n"); PrintBoth(" Slot: %u\n",thedev->number); - PrintBoth(" device_id: 0x%x\n", (uint_t) thedev->config.device_id); PrintBoth(" vendor_id: 0x%x\n", (uint_t) thedev->config.vendor_id); - PrintBoth(" status: 0x%x\n", (uint_t) thedev->config.status); + PrintBoth(" device_id: 0x%x\n", (uint_t) thedev->config.device_id); PrintBoth(" command: 0x%x\n", (uint_t) thedev->config.command); - PrintBoth(" class_code: 0x%x\n", (uint_t) thedev->config.class_code); - PrintBoth(" subclass: 0x%x\n", (uint_t) thedev->config.subclass); + PrintBoth(" status: 0x%x\n", (uint_t) thedev->config.status); PrintBoth(" revision: 0x%x\n", (uint_t) thedev->config.revision); - PrintBoth(" BIST: 0x%x\n", (uint_t) thedev->config.BIST); - PrintBoth(" header_type: 0x%x\n", (uint_t) thedev->config.header_type); - PrintBoth(" latency_time: 0x%x\n", (uint_t) thedev->config.latency_time); + PrintBoth(" class_code: 0x%x%x%x (prog_interface 0x%x, subclass 0x%x, classcode 0x%x)\n", + (uint_t) thedev->config.class_code[0], + (uint_t) thedev->config.class_code[1], + (uint_t) thedev->config.class_code[2], + (uint_t) PROG_INTERFACE(thedev->config.class_code), + (uint_t) SUBCLASS(thedev->config.class_code), + (uint_t) CLASSCODE(thedev->config.class_code) + ); PrintBoth(" cache_line_size: 0x%x\n", (uint_t) thedev->config.cache_line_size); - PrintBoth(" BAR[0]: 0x%x\n", (uint_t) thedev->config.BAR[0]); - PrintBoth(" BAR[1]: 0x%x\n", (uint_t) thedev->config.BAR[1]); - PrintBoth(" BAR[2]: 0x%x\n", (uint_t) thedev->config.BAR[2]); - PrintBoth(" BAR[3]: 0x%x\n", (uint_t) thedev->config.BAR[3]); - PrintBoth(" BAR[4]: 0x%x\n", (uint_t) thedev->config.BAR[4]); - PrintBoth(" BAR[5]: 0x%x\n", (uint_t) thedev->config.BAR[5]); - PrintBoth(" cardbus_cis_ptr: 0x%x\n", (uint_t) thedev->config.cardbus_cis_pointer); - PrintBoth(" subsystem_id: 0x%x\n", (uint_t) thedev->config.subsystem_id); - PrintBoth(" subsystem_vendor: 0x%x\n", (uint_t) thedev->config.subsystem_vendor_id); - PrintBoth(" exp_rom_address: 0x%x\n", (uint_t) thedev->config.expansion_rom_address); - PrintBoth(" reserved[0]: 0x%x\n", (uint_t) thedev->config.reserved[0]); - PrintBoth(" reserved[1]: 0x%x\n", (uint_t) thedev->config.reserved[1]); - PrintBoth(" max_latency: 0x%x\n", (uint_t) thedev->config.max_latency); - PrintBoth(" min_grant: 0x%x\n", (uint_t) thedev->config.min_grant); - PrintBoth(" intr_pin: 0x%x\n", (uint_t) thedev->config.intr_pin); - PrintBoth(" intr_line: 0x%x\n", (uint_t) thedev->config.intr_line); + PrintBoth(" latency_time: 0x%x\n", (uint_t) thedev->config.latency_time); + PrintBoth(" header_type: 0x%x (%s%s)\n", (uint_t) thedev->config.header_type, + HEADER_TYPE(thedev->config.header_type)==PCI_DEVICE ? "PCI Device" : + HEADER_TYPE(thedev->config.header_type)==PCI_PCI_BRIDGE ? "PCI-PCI Bridge" : + HEADER_TYPE(thedev->config.header_type)==PCI_CARDBUS_BRIDGE ? "PCI-Cardbus Bridge" : "UNKNOWN", + MULTIFUNCTION(thedev->config.header_type) ? " Multifunction" : "" + ); + PrintBoth(" BIST: 0x%x\n", (uint_t) thedev->config.BIST); } +static void PrintPCIDevice(struct pci_device *thedev) +{ + int i; + + PrintBoth(" PCI Device:\n"); + PrintPCIShared(thedev); + for (i=0;i<6;i++) { + PrintBoth(" BAR[%d]: 0x%x (", i, (uint_t) thedev->config.u.pci_device_config.BAR[i]); + if (IS_IO_ADDR(thedev->config.u.pci_device_config.BAR[i])) { + PrintBoth("IO Address 0x%x)\n", GET_IO_ADDR(thedev->config.u.pci_device_config.BAR[i])); + } else if (IS_MEM_ADDR(thedev->config.u.pci_device_config.BAR[i])) { + PrintBoth("Memory Address 0x%x type=0x%x%s\n", + GET_MEM_ADDR(thedev->config.u.pci_device_config.BAR[i]), + GET_MEM_TYPE(thedev->config.u.pci_device_config.BAR[i]), + GET_MEM_PREFETCHABLE(thedev->config.u.pci_device_config.BAR[i]) ? " prefetchable)" : ")"); + } else { + PrintBoth("UNKNOWN)\n"); + } + } + PrintBoth(" cardbus_cis_ptr: 0x%x\n", (uint_t) thedev->config.u.pci_device_config.cardbus_cis_pointer); + PrintBoth(" subsystem_vendor: 0x%x\n", (uint_t) thedev->config.u.pci_device_config.subsystem_vendor_id); + PrintBoth(" subsystem_id: 0x%x\n", (uint_t) thedev->config.u.pci_device_config.subsystem_id); + PrintBoth(" exp_rom_address: 0x%x\n", (uint_t) thedev->config.u.pci_device_config.expansion_rom_address); + PrintBoth(" cap ptr 0x%x\n", (uint_t) thedev->config.u.pci_device_config.cap_ptr); + for (i=0;i<7;i++) { + PrintBoth(" reserved[%d]: 0x%x\n", i, (uint_t) thedev->config.u.pci_device_config.reserved[i]); + } + PrintBoth(" intr_line: 0x%x\n", (uint_t) thedev->config.u.pci_device_config.intr_line); + PrintBoth(" intr_pin: 0x%x\n", (uint_t) thedev->config.u.pci_device_config.intr_pin); + PrintBoth(" min_grant: 0x%x\n", (uint_t) thedev->config.u.pci_device_config.min_grant); + PrintBoth(" max_latency: 0x%x\n", (uint_t) thedev->config.u.pci_device_config.max_latency); + for (i=0;i<48;i++) { + PrintBoth(" device_data[%d]: 0x%x\n", i, (uint_t) thedev->config.u.pci_device_config.device_data[i]); + } +} + +static void PrintPCIPCIBridge(struct pci_device *thedev) +{ + int i; + + PrintBoth(" PCI-PCI Bridge:\n"); + PrintPCIShared(thedev); + for (i=0;i<2;i++) { + PrintBoth(" BAR[%d]: 0x%x (", i, (uint_t) thedev->config.u.pci_pci_bridge_config.BAR[i]); + if (IS_IO_ADDR(thedev->config.u.pci_pci_bridge_config.BAR[i])) { + PrintBoth("IO Address 0x%x)\n", GET_IO_ADDR(thedev->config.u.pci_pci_bridge_config.BAR[i])); + } else if (IS_MEM_ADDR(thedev->config.u.pci_pci_bridge_config.BAR[i])) { + PrintBoth("Memory Address 0x%x type=0x%x%s\n", + GET_MEM_ADDR(thedev->config.u.pci_pci_bridge_config.BAR[i]), + GET_MEM_TYPE(thedev->config.u.pci_pci_bridge_config.BAR[i]), + GET_MEM_PREFETCHABLE(thedev->config.u.pci_pci_bridge_config.BAR[i]) ? " prefetchable)" : ")"); + } else { + PrintBoth("UNKNOWN)\n"); + } + } + PrintBoth(" primary_bus: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.primary_bus); + PrintBoth(" secondary_bus: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.secondary_bus); + PrintBoth(" subordinate_bus: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.subordinate_bus); + PrintBoth(" second_lat_timer: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.secondary_lat_timer); + PrintBoth(" io_base: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.io_base); + PrintBoth(" io_limit: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.io_limit); + PrintBoth(" secondary_status: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.secondary_status); + PrintBoth(" memory_base: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.memory_base); + PrintBoth(" memory_limit: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.memory_limit); + PrintBoth(" prefetch_base: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.prefetchable_memory_base); + PrintBoth(" prefetch_limit: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.prefetchable_memory_limit); + PrintBoth(" prefetch_base_up: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.prefetchable_memory_base_upper); + PrintBoth(" prefetch_limit_u: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.prefetchable_memory_limit_upper); + PrintBoth(" memory_limit: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.memory_limit); + PrintBoth(" memory_limit: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.memory_limit); + PrintBoth(" io_base_up: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.io_base_upper); + PrintBoth(" io_limit_up: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.io_limit_upper); + PrintBoth(" reserved: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.reserved); + PrintBoth(" exp_rom_address: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.expansion_rom_address); + PrintBoth(" intr_line: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.intr_line); + PrintBoth(" intr_pin: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.intr_pin); + for (i=0;i<48;i++) { + PrintBoth(" device_data[%d]: 0x%x\n", i, (uint_t) thedev->config.u.pci_pci_bridge_config.device_data[i]); + } +} + +static void PrintPCICardbusBridge(struct pci_device *thedev) +{ + int i; + + PrintBoth(" PCI-Cardbus Bridge:\n"); + PrintPCIShared(thedev); + PrintBoth(" cardbus_base_add: 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.cardbus_base_addr); + PrintBoth(" cap_ptr: 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.cap_ptr); + PrintBoth(" reserved: 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.reserved); + PrintBoth(" secondary_status 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.secondary_status); + PrintBoth(" pci_bus: 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.pci_bus); + PrintBoth(" cardbus_bus: 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.cardbus_bus); + PrintBoth(" subordinate_bus: 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.subordinate_bus); + PrintBoth(" cardbus_lat_time: 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.cardbus_lat_timer); + PrintBoth(" memory_base0 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.memory_base0); + PrintBoth(" memory_limit0 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.memory_limit0); + PrintBoth(" memory_base1 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.memory_base1); + PrintBoth(" memory_limit1 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.memory_limit1); + PrintBoth(" io_base0 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.io_base0); + PrintBoth(" io_base0_up 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.io_base0_upper); + PrintBoth(" io_limit0 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.io_limit0); + PrintBoth(" io_limit0_up 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.io_limit0_upper); + PrintBoth(" io_base1 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.io_base1); + PrintBoth(" io_base1_up 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.io_base1_upper); + PrintBoth(" io_limit1 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.io_limit1); + PrintBoth(" io_limit1_up 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.io_limit1_upper); + PrintBoth(" intr_line: 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.intr_line); + PrintBoth(" intr_pin: 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.intr_pin); + PrintBoth(" bridge_ctl: 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.bridge_ctl); + PrintBoth(" subsys_vend_id: 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.subsystem_vendor_id); + PrintBoth(" subsys_dev_id: 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.subsystem_device_id); + PrintBoth(" legacy16_base: 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.legacy_16bit_base_addr); + for (i=0;i<14;i++) { + PrintBoth(" reserved2[%d]: 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.reserved2[i]); + } + for (i=0;i<48;i++) { + PrintBoth(" device_data[%d]: 0x%x\n", i, (uint_t) thedev->config.u.pci_cardbus_bridge_config.device_data[i]); + } +} + +static void PrintPCIUnknown(struct pci_device *thedev) +{ + PrintBoth(" PCI Unknown Element\n"); + PrintPCIShared(thedev); +} + +static void PrintPCIElement(struct pci_device *thedev) +{ + switch (HEADER_TYPE(thedev->config.header_type)) { + case PCI_DEVICE: + PrintPCIDevice(thedev); + break; + case PCI_PCI_BRIDGE: + PrintPCIPCIBridge(thedev); + break; + case PCI_CARDBUS_BRIDGE: + PrintPCICardbusBridge(thedev); + break; + default: + PrintPCIUnknown(thedev); + break; + } +} + + static void PrintPCIBus(struct pci_bus *thebus) { struct pci_device *thedev; @@ -238,7 +474,7 @@ static void PrintPCIBus(struct pci_bus *thebus) thedev=thebus->device_list; while (thedev) { - PrintPCIDevice(thedev); + PrintPCIElement(thedev); thedev=thedev->next; } }