Simon Horman
2009-Jun-17 08:07 UTC
[Xen-devel] [rfc 0/8] xen-qemu: multi-function VT-d device pass-through
This series of patches cleans up various aspects of the PCI pass-through code. This is working towards multi-function pass-through devices in guests. But most of these changes are useful in their own right, so I am posting this batch without the rest of the multi-function changes. This series of patches extends VT-d pass-through to allow multi-function devices to appear in guests as multi-function devices. The interface for this is a new extension to BDF notation that can be used in configuration files for boot-time (static) assignment and on the xm command like with pci-attach and pci-detach for hot-plug and hot-unplug respectively. If the existing BDF notation, which only specifies a single function, is used then the existing single-function pass-through scheme is used. That is, when a function is passed-through its will appear as function zero of a vslot in the guest. For example, the following physical to virtual mapping may occur. The critical part is the treatment of the function numbers which will always be consistent. That is, the virtual function number is always zero. Physical | Virtual -----------+-------- 00:1d.0 | 00:06.0 00:1d.1 | 00:07.0 00:1d.7 | 00:08.0 If the new extensions to BDF notation are used, thereby specifying multiple functions of a device, then a multi-function scheme is used. Two such schemes are proposed: 1. Identity mapping, whereby physical function numbers are identity mapped into virtual functions. For example the following physical to virtual mapping may occur. Again, the treatment of the function numbers is critical and will always be consistent. That is it is the virtual function number is always the same as the physical function number. It is also important that both the physical and virtual device numbers are the same. Physical | Virtual -----------+-------- 00:1d.0 | 00:07.0 00:1d.1 | 00:07.1 00:1d.7 | 00:07.7 2. Least mapping, whereby the lowest available virtual function is used. The example above would become: Physical | Virtual -----------+-------- 00:1d.0 | 00:07.0 00:1d.1 | 00:07.1 00:1d.7 | 00:07.2 Unlike identity mapping, this scheme is dependant on the order that functions are supplied. So if the order in the above example was reversed, then the result would be: Physical | Virtual -----------+-------- 00:1d.7 | 00:07.0 00:1d.1 | 00:07.1 00:1d.0 | 00:07.1 As physical function 0 need not be present, this scheme allows multiple virtual multi-function devices to be formed from functions of the same physical multi-function device. It is not known if this scheme violates hardware restrictions. This scheme is activated by applying the last patch in this series. There is no mechanism to switch schemes at this time. Least mapping was proposed by Masaki Kanno. The above multi-function mappings will occur when the following extension to the BDF notation is used. In the case of unplug the VSLOT and OPT must be omitted. Existing: SEQ:BUS:DEV.FUNC[@VSLOT][,OPT...] New: SEQ:BUS:DEV.FUNC0-FUNCN[@VSLOT][,OPT...] SEQ:BUS:DEV.FUNC0,FUNCM,FUNCN[@VSLOT][,OPT...] SEQ:BUS:DEV.*[@VSLOT][,OPT...] This notation is expanded into more conventional parameters which are passed to qemu-xen. E.g: 0000:00:1d.0-2 becomes: 0000:00:1d.0 0000:00:1d.1 0000:00:1d.2 0000:00:1d.0,3,5,7 becomes: 0000:00:0d.0 0000:00:0d.3 0000:00:0d.5 0000:00:0d.7 For a device that has functions 0, 1, 2, 3, 5 and 7, 0000:00:1d.* becomes: 0000:00:1d.00 0000:00:1d.01 0000:00:1d.02 0000:00:1d.03 0000:00:1d.05 0000:00:1d.07 Limitation: * This scheme does not allow for the physical and virtual function to be specified.. Bugs: * Suspended domains with PCI pass-through devices may not be restored correctly because the vslot field is no longer honoured after these patches. This needs further investigation. I will post a document that includes a fuller description of this code as a follow-up. This patch series applies against: http://xenbits.xensource.com/git-http/staging/qemu-xen-unstable.git/ commit e0bb6b8df60863bca0163a1688baf4854e931e55 Author: Ian Jackson <ian.jackson@eu.citrix.com> Date: Mon Jun 8 17:45:42 2009 +0100 Subject: stdvga + videoram config option Please apply the patches in order, many of the patches in this series depend on previous patches in the series to function correctly. There are both xen and xen-qemu patch series relating to this change. Where they depend on each other this is noted in the patch''s comment. Only applying one series will break pass-through. I will be taking a holiday from the 24th June - 8th July. I will not be able to make any fixes or answer email during that time. _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Simon Horman
2009-Jun-17 08:07 UTC
[Xen-devel] [rfc 1/8] qemu-xen: pass-through: Read the interrupt pin from hardware
Preparation for multi-fucntion devices in guests. Up until now guests have only seen devices with one function, so it is both safe and sensible to always use INTA. But if if multiple functions appear, it makes sense to use the interrupt pin specified by the hardware. Cc: Dexuan Cui <dexuan.cui@intel.com> Cc: Masaki Kanno <kanno.masaki@jp.fujitsu.com> Cc: Yuji Shimada <shimada-yxb@necst.nec.co.jp> Signed-off-by: Simon Horman <horms@verge.net.au> Index: ioemu-remote/hw/pass-through.c ==================================================================--- ioemu-remote.orig/hw/pass-through.c 2009-06-15 11:25:38.000000000 +1000 +++ ioemu-remote/hw/pass-through.c 2009-06-15 11:25:40.000000000 +1000 @@ -2296,8 +2296,7 @@ static int pt_init_pci_config(struct pt_ if (ret < 0 && ptdev->machine_irq != 0) { uint8_t e_device = PCI_SLOT(ptdev->dev.devfn); - /* fix virtual interrupt pin to INTA# */ - uint8_t e_intx = 0; + uint8_t e_intx = pci_intx(ptdev); ret = xc_domain_bind_pt_pci_irq(xc_handle, domid, ptdev->machine_irq, 0, e_device, e_intx); @@ -3580,7 +3579,6 @@ static int pt_msgctrl_reg_write(struct p uint16_t writable_mask = 0; uint16_t throughable_mask = 0; uint16_t old_ctrl = cfg_entry->data; - uint8_t e_device, e_intx; PCIDevice *pd = (PCIDevice *)ptdev; uint16_t val; @@ -4106,7 +4104,7 @@ static struct pt_dev * register_real_dev { e_device = PCI_SLOT(assigned_device->dev.devfn); /* fix virtual interrupt pin to INTA# */ - e_intx = 0; + e_intx = pci_intx(assigned_device); rc = xc_domain_bind_pt_pci_irq(xc_handle, domid, machine_irq, 0, e_device, e_intx); @@ -4164,8 +4162,7 @@ static int unregister_real_device(int sl /* Unbind interrupt */ e_device = PCI_SLOT(assigned_device->dev.devfn); - /* fix virtual interrupt pin to INTA# */ - e_intx = 0; + e_intx = pci_intx(assigned_device); machine_irq = assigned_device->machine_irq; if ( assigned_device->msi_trans_en == 0 && machine_irq ) { @@ -4258,3 +4255,60 @@ int pt_init(PCIBus *e_bus) return 0; } +/* The PCI Local Bus Specification, Rev. 3.0, + * Section 6.2.4 Miscellaneous Registers, pp 223 + * outlines 5 valid values for the intertupt pin (intx). + * 0: For devices (or device functions) that don''t use an interrupt in + * 1: INTA# + * 2: INTB# + * 3: INTC# + * 4: INTD# + * + * Xen uses the following 4 values for intx + * 0: INTA# + * 1: INTB# + * 2: INTC# + * 3: INTD# + * + * Observing that these list of values are not the same, pci_read_intx() + * uses the following mapping from hw to xen values. + * This seems to reflect the current usage within Xen. + * + * PCI hardware | Xen | Notes + * ----------------+-----+---------------------------------------------------- + * 0 | 0 | No interrupt + * 1 | 0 | INTA# + * 2 | 1 | INTB# + * 3 | 2 | INTC# + * 4 | 3 | INTD# + * any other value | 0 | This should never happen, log error message + */ +static uint8_t pci_read_intx(struct pt_dev *ptdev) +{ + uint8_t r_val = pci_read_byte(ptdev->pci_dev, PCI_INTERRUPT_PIN); + + PT_LOG("intx=%i\n", r_val); + if (r_val < 1 || r_val > 4) + { + PT_LOG("Interrupt pin read from hardware is out of range: " + "value=%i, acceptable range is 1 - 4\n", r_val); + r_val = 0; + } + else + { + r_val -= 1; + } + + return r_val; +} + +/* + * For virtual function 0, always use INTA#, + * otherwise use the hardware value + */ +uint8_t pci_intx(struct pt_dev *ptdev) +{ + if (!PCI_FUNC(ptdev->dev.devfn)) + return 0; + return pci_read_intx(ptdev); +} Index: ioemu-remote/hw/pt-msi.c ==================================================================--- ioemu-remote.orig/hw/pt-msi.c 2009-06-15 11:25:38.000000000 +1000 +++ ioemu-remote/hw/pt-msi.c 2009-06-15 11:25:40.000000000 +1000 @@ -153,8 +153,7 @@ void pt_msi_disable(struct pt_dev *dev) msi_set_enable(dev, 0); e_device = PCI_SLOT(dev->dev.devfn); - /* fix virtual interrupt pin to INTA# */ - e_intx = 0; + e_intx = pci_intx(dev); if (dev->msi_trans_en) { @@ -224,7 +223,7 @@ int pt_enable_msi_translate(struct pt_de e_device = PCI_SLOT(dev->dev.devfn); /* fix virtual interrupt pin to INTA# */ - e_intx = 0; + e_intx = pci_intx(dev); if (xc_domain_bind_pt_irq(xc_handle, domid, dev->msi->pirq, PT_IRQ_TYPE_MSI_TRANSLATE, 0, @@ -253,8 +252,7 @@ void pt_disable_msi_translate(struct pt_ msi_set_enable(dev, 0); e_device = PCI_SLOT(dev->dev.devfn); - /* fix virtual interrupt pin to INTA# */ - e_intx = 0; + e_intx = pci_intx(dev); if (xc_domain_unbind_pt_irq(xc_handle, domid, dev->msi->pirq, PT_IRQ_TYPE_MSI_TRANSLATE, 0, Index: ioemu-remote/hw/pass-through.h ==================================================================--- ioemu-remote.orig/hw/pass-through.h 2009-06-15 11:25:38.000000000 +1000 +++ ioemu-remote/hw/pass-through.h 2009-06-15 11:25:40.000000000 +1000 @@ -402,5 +402,7 @@ static inline pciaddr_t pt_pci_base_addr return base & PCI_ADDR_MEM_MASK; } +uint8_t pci_intx(struct pt_dev *ptdev); + #endif /* __PASSTHROUGH_H__ */ -- _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Simon Horman
2009-Jun-17 08:07 UTC
[Xen-devel] [rfc 2/8] qemu-xen: pass-through: Read the PCI type bit from hardware
Preparation for multi-fucntion devices in guests. When scanning the PCI bus a guest* will only look for functions 2-7 if the multifunction bit is set. Cc: Dexuan Cui <dexuan.cui@intel.com> Cc: Masaki Kanno <kanno.masaki@jp.fujitsu.com> Signed-off-by: Simon Horman <horms@verge.net.au> Index: ioemu-remote/hw/pass-through.c ==================================================================--- ioemu-remote.orig/hw/pass-through.c 2009-06-09 21:43:27.000000000 +1000 +++ ioemu-remote/hw/pass-through.c 2009-06-09 21:52:13.000000000 +1000 @@ -145,6 +145,8 @@ static uint32_t pt_msgdata_reg_init(stru struct pt_reg_info_tbl *reg, uint32_t real_offset); static uint32_t pt_msixctrl_reg_init(struct pt_dev *ptdev, struct pt_reg_info_tbl *reg, uint32_t real_offset); +static uint32_t pt_header_type_reg_init(struct pt_dev *ptdev, + struct pt_reg_info_tbl *reg, uint32_t real_offset); static uint8_t pt_reg_grp_size_init(struct pt_dev *ptdev, struct pt_reg_grp_info_tbl *grp_reg, uint32_t base_offset); static uint8_t pt_pm_size_init(struct pt_dev *ptdev, @@ -324,7 +326,7 @@ static struct pt_reg_info_tbl pt_emu_reg .init_val = 0x00, .ro_mask = 0x00, .emu_mask = 0xFF, - .init = pt_common_reg_init, + .init = pt_header_type_reg_init, .u.b.read = pt_byte_reg_read, .u.b.write = pt_byte_reg_write, .u.b.restore = pt_byte_reg_restore, @@ -2999,6 +3001,13 @@ static uint8_t pt_pcie_size_init(struct return pcie_size; } +/* read PCI_HEADER_TYPE */ +static uint32_t pt_header_type_reg_init(struct pt_dev *ptdev, + struct pt_reg_info_tbl *reg, uint32_t real_offset) +{ + return reg->init_val | 0x80; +} + /* read byte size emulate register */ static int pt_byte_reg_read(struct pt_dev *ptdev, struct pt_reg_tbl *cfg_entry, -- _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Simon Horman
2009-Jun-17 08:07 UTC
[Xen-devel] [rfc 3/8] qemu-xen: pass-through: use devfn instead of slots as the unit for pass-through
This is part of support for multi-function PCI devices in guests Instead of reading a slot number from xend, read a devfn. This and subsequent other changes will allow xend to ask for more than one function to be inserted into a single slot - by specifying which function of the slot should be used. This is a minimal patch for this change. A subsequent patch that has a lot of noise to rename slot to devfn follows. This patch breaks compatibility with xend and corresponding patches to xend are required. Cc: Dexuan Cui <dexuan.cui@intel.com> Cc: Masaki Kanno <kanno.masaki@jp.fujitsu.com> Signed-off-by: Simon Horman <horms@verge.net.au> --- * co-dependent with xend patch "xend: pass-through: use devfn instead of slots as the unit for pass-through" Changes Thu, 21 May 2009 12:09:30 +1000 * __insert_to_pci_slot() should operate on a vdevfn not a vslot when it automatically allocating a vslot Thu, 28 May 2009 22:36:54 +1000 * Up-port to 16a3f599db2afcd87137294f8c497597ddcccde1 Index: ioemu-remote/hw/pass-through.c ==================================================================--- ioemu-remote.orig/hw/pass-through.c 2009-06-15 11:25:44.000000000 +1000 +++ ioemu-remote/hw/pass-through.c 2009-06-15 11:25:45.000000000 +1000 @@ -103,7 +103,7 @@ struct php_dev { }; struct dpci_infos { - struct php_dev php_devs[NR_PCI_DEV]; + struct php_dev php_devs[NR_PCI_DEVFN]; PCIBus *e_bus; struct pci_access *pci_access; @@ -859,7 +859,7 @@ static int parse_bdf(char **str, int *se } else { - *vslot = AUTO_PHP_SLOT; + *vslot = AUTO_PHP_DEVFN; *opt = token; } @@ -903,30 +903,30 @@ static int pci_slot_match(int bus, int d } /* Insert a new pass-through device into a specific pci slot. - * input dom:bus:dev.func@slot, chose free one if slot == AUTO_PHP_SLOT + * input dom:bus:dev.func@slot, chose free one if slot == AUTO_PHP_DEVFN * return -2: requested slot not available * -1: no free slots * >=0: the new hotplug slot */ -static int __insert_to_pci_slot(int bus, int dev, int func, int slot, +static int __insert_to_pci_slot(int bus, int dev, int func, int devfn, char *opt) { PCIBus *e_bus = dpci_infos.e_bus; + int slot; - /* preferred virt pci slot */ - if ( slot != AUTO_PHP_SLOT) + /* preferred virt pci devfn */ + if ( devfn != AUTO_PHP_DEVFN ) { - if ( !test_pci_slot(slot) && - !pci_devfn_in_use(e_bus, PCI_DEVFN(slot, 0)) ) + if ( !test_pci_slot(devfn) && !pci_devfn_in_use(e_bus, devfn) ) goto found; return -2; } - /* slot == 0, pick up a free one */ + /* pick a free slot */ for ( slot = 0; slot < NR_PCI_DEV; slot++ ) { - if ( !test_pci_slot(slot) && - !pci_devfn_in_use(e_bus, PCI_DEVFN(slot, 0)) ) + devfn = PCI_DEVFN(slot, 0); + if ( !test_pci_slot(devfn) && !pci_devfn_in_use(e_bus, devfn) ) goto found; } @@ -934,12 +934,12 @@ static int __insert_to_pci_slot(int bus, return -1; found: - dpci_infos.php_devs[slot].valid = 1; - dpci_infos.php_devs[slot].r_bus = bus; - dpci_infos.php_devs[slot].r_dev = dev; - dpci_infos.php_devs[slot].r_func = func; - dpci_infos.php_devs[slot].opt = opt; - return slot; + dpci_infos.php_devs[devfn].valid = 1; + dpci_infos.php_devs[devfn].r_bus = bus; + dpci_infos.php_devs[devfn].r_dev = dev; + dpci_infos.php_devs[devfn].r_func = func; + dpci_infos.php_devs[devfn].opt = opt; + return devfn; } /* Insert a new pass-through device into a specific pci slot. @@ -966,7 +966,7 @@ int insert_to_pci_slot(char *bdf_slt) */ int test_pci_slot(int slot) { - if ( slot < 0 || slot >= NR_PCI_DEV ) + if ( slot < 0 || slot >= NR_PCI_DEVFN ) return -1; if ( dpci_infos.php_devs[slot].valid ) @@ -987,7 +987,7 @@ int bdf_to_slot(char *bdf_str) } /* locate the virtual pci slot for this VTd device */ - for ( i = 0; i < NR_PCI_DEV; i++ ) + for ( i = 0; i < NR_PCI_DEVFN; i++ ) { if ( pci_slot_match(bus, dev, func, i) ) return i; @@ -4037,7 +4037,7 @@ static struct pt_dev * register_real_dev /* Register device */ assigned_device = (struct pt_dev *) pci_register_device(e_bus, e_dev_name, - sizeof(struct pt_dev), PCI_DEVFN(e_slot, 0), + sizeof(struct pt_dev), e_slot, pt_pci_read_config, pt_pci_write_config); if ( assigned_device == NULL ) { Index: ioemu-remote/hw/pci.h ==================================================================--- ioemu-remote.orig/hw/pci.h 2009-06-15 11:25:38.000000000 +1000 +++ ioemu-remote/hw/pci.h 2009-06-15 11:25:45.000000000 +1000 @@ -255,8 +255,11 @@ void pci_info(void); PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid, uint16_t did, pci_map_irq_fn map_irq, const char *name); -#define NR_PCI_DEV 32 -#define AUTO_PHP_SLOT NR_PCI_DEV +#define NR_PCI_FUNC 8 +#define NR_PCI_DEV 32 +#define NR_PCI_DEVFN (NR_PCI_FUNC * NR_PCI_DEV) +#define AUTO_PHP_SLOT NR_PCI_DEV +#define AUTO_PHP_DEVFN NR_PCI_DEVFN int insert_to_pci_slot(char*); int test_pci_slot(int); Index: ioemu-remote/hw/piix4acpi.c ==================================================================--- ioemu-remote.orig/hw/piix4acpi.c 2009-06-15 11:25:38.000000000 +1000 +++ ioemu-remote/hw/piix4acpi.c 2009-06-15 11:25:45.000000000 +1000 @@ -33,6 +33,8 @@ #include <xen/hvm/ioreq.h> #include <xen/hvm/params.h> +#include <pci/header.h> + /* PM1a_CNT bits, as defined in the ACPI specification. */ #define SCI_EN (1 << 0) #define GBL_RLS (1 << 2) @@ -276,7 +278,7 @@ static void acpi_php_writeb(void *opaque hotplug_slots->plug_slot = 0; /* power off the slot */ - power_off_php_slot(slot); + power_off_php_slot(PCI_DEVFN(slot, 0)); /* signal the CP ACPI hot remove done. */ xenstore_record_dm_state("pci-removed"); @@ -459,17 +461,32 @@ static void acpi_sci_intr(GPEState *s) } } -void acpi_php_del(int slot) +void acpi_php_del(int devfn) { GPEState *s = &gpe_state; + int slot, func; + + slot = PCI_SLOT(devfn); + func = PCI_FUNC(devfn); - if ( test_pci_slot(slot) < 0 ) { - fprintf(logfile, "hot remove: pci slot %d " - "is not used by a hotplug device.\n", slot); + if ( test_pci_slot(devfn) < 0 ) { + fprintf(logfile, "hot remove: pci slot 0x%02x, function 0x%x " + "is not used by a hotplug device.\n", slot, func); return; } + /* ACPI PHP can only work on slots + * So only remove zero-functions - + * which will remove all other fucntions of the same device in the + * guest. + */ + if ( func ) { + fprintf(logfile, "hot remove: Attempt to remove non-zero function " + "slot=0x%02x func=0x%0x.\n", slot, func); + return; + } + /* update the php controller status */ php_slots.plug_evt = PHP_EVT_REMOVE; php_slots.plug_slot = slot; @@ -478,18 +495,19 @@ void acpi_php_del(int slot) acpi_sci_intr(s); } -void acpi_php_add(int slot) +void acpi_php_add(int devfn) { GPEState *s = &gpe_state; char ret_str[30]; + int slot, func; - if ( slot < 0 ) { - fprintf(logfile, "hot add pci slot %d exceed.\n", slot); + if ( devfn < 0 ) { + fprintf(logfile, "hot add pci devfn %d exceed.\n", devfn); - if ( slot == -1 ) - sprintf(ret_str, "no free hotplug slots"); - else if ( slot == -2 ) - sprintf(ret_str, "wrong bdf or vslot"); + if ( devfn == -1 ) + sprintf(ret_str, "no free hotplug devfn"); + else if ( devfn == -2 ) + sprintf(ret_str, "wrong bdf or vdevfn"); if ( strlen(ret_str) > 0 ) xenstore_record_dm("parameter", ret_str); @@ -497,25 +515,40 @@ void acpi_php_add(int slot) return; } - /* update the php controller status */ - php_slots.plug_evt = PHP_EVT_ADD; - php_slots.plug_slot = slot; + /* ACPI PHP can only work on slots + * For function 0 we do a full hot-add. + * For other functions we just register the device with the hypervisor. + * Assuming that function 0 is added after non-zero functions, + * its ACPI PHP event will cause all previously registered functions + * to be added to the guest. + */ - /* update the slot status as present */ - php_slots.status[slot] = 0xf; + slot = PCI_SLOT(devfn); + func = PCI_FUNC(devfn); - /* power on the slot */ - power_on_php_slot(slot); + if ( !func ) + { + /* update the php controller status */ + php_slots.plug_evt = PHP_EVT_ADD; + php_slots.plug_slot = slot; + + /* update the slot status as present */ + php_slots.status[slot] = 0xf; + } + + /* power on the function */ + power_on_php_slot(devfn); /* tell Control panel which slot for the new pass-throgh dev */ - sprintf(ret_str, "0x%02x", slot); + sprintf(ret_str, "0x%02x", devfn); xenstore_record_dm("parameter", ret_str); /* signal the CP ACPI hot insert done */ xenstore_record_dm_state("pci-inserted"); /* generate a SCI interrupt */ - acpi_sci_intr(s); + if ( !func ) + acpi_sci_intr(s); } #endif /* CONFIG_PASSTHROUGH */ -- _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Simon Horman
2009-Jun-17 08:07 UTC
[Xen-devel] [rfc 4/8] qemu-xen: pass-through: rename slot to devfn
This is the noisy companion to the previous patch "qemu-xen: pass-through: use devfn instead of slots as the unit for pass-through". It just renames slot to devfn in various places. Cc: Dexuan Cui <dexuan.cui@intel.com> Cc: Masaki Kanno <kanno.masaki@jp.fujitsu.com> Signed-off-by: Simon Horman <horms@verge.net.au> --- Changes Thu, 21 May 2009 13:09:53 +1000 * Rediff for recent canges made to "qemu-xen: pass-through: use devfn instead of slots as the unit for pass-through" Index: ioemu-remote/hw/pass-through.c ==================================================================--- ioemu-remote.orig/hw/pass-through.c 2009-06-15 11:25:45.000000000 +1000 +++ ioemu-remote/hw/pass-through.c 2009-06-15 11:25:50.000000000 +1000 @@ -831,7 +831,7 @@ static int token_value(char *token) } static int parse_bdf(char **str, int *seg, int *bus, int *dev, int *func, - char **opt, int *vslot) + char **opt, int *vdevfn) { char *token, *endptr; const char *delim = ":."; @@ -855,11 +855,11 @@ static int parse_bdf(char **str, int *se if (*opt) { *(*opt)++ = ''\0''; - *vslot = token_value(*opt); + *vdevfn = token_value(*opt); } else { - *vslot = AUTO_PHP_DEVFN; + *vdevfn = AUTO_PHP_DEVFN; *opt = token; } @@ -892,24 +892,24 @@ static int get_next_keyval(char **option return 0; } -static int pci_slot_match(int bus, int dev, int func, int slot) +static int pci_devfn_match(int bus, int dev, int func, int devfn) { - if (test_pci_slot(slot) == 1 && - dpci_infos.php_devs[slot].r_bus == bus && - dpci_infos.php_devs[slot].r_dev == dev && - dpci_infos.php_devs[slot].r_func == func ) + if (test_pci_devfn(devfn) == 1 && + dpci_infos.php_devs[devfn].r_bus == bus && + dpci_infos.php_devs[devfn].r_dev == dev && + dpci_infos.php_devs[devfn].r_func == func ) return 1; return 0; } -/* Insert a new pass-through device into a specific pci slot. - * input dom:bus:dev.func@slot, chose free one if slot == AUTO_PHP_DEVFN - * return -2: requested slot not available - * -1: no free slots - * >=0: the new hotplug slot +/* Insert a new pass-through device into a specific pci devfn. + * input dom:bus:dev.func@devfn, chose free one if devfn == AUTO_PHP_DEVFN + * return -2: requested devfn not available + * -1: no free devfns + * >=0: the new hotplug devfn */ -static int __insert_to_pci_slot(int bus, int dev, int func, int devfn, - char *opt) +static int __insert_to_pci_devfn(int bus, int dev, int func, int devfn, + char *opt) { PCIBus *e_bus = dpci_infos.e_bus; int slot; @@ -917,7 +917,7 @@ static int __insert_to_pci_slot(int bus, /* preferred virt pci devfn */ if ( devfn != AUTO_PHP_DEVFN ) { - if ( !test_pci_slot(devfn) && !pci_devfn_in_use(e_bus, devfn) ) + if ( !test_pci_devfn(devfn) && !pci_devfn_in_use(e_bus, devfn) ) goto found; return -2; } @@ -926,7 +926,7 @@ static int __insert_to_pci_slot(int bus, for ( slot = 0; slot < NR_PCI_DEV; slot++ ) { devfn = PCI_DEVFN(slot, 0); - if ( !test_pci_slot(devfn) && !pci_devfn_in_use(e_bus, devfn) ) + if ( !test_pci_devfn(devfn) && !pci_devfn_in_use(e_bus, devfn) ) goto found; } @@ -942,54 +942,54 @@ found: return devfn; } -/* Insert a new pass-through device into a specific pci slot. - * input dom:bus:dev.func@slot +/* Insert a new pass-through device into a specific pci devfn. + * input dom:bus:dev.func@devfn */ -int insert_to_pci_slot(char *bdf_slt) +int insert_to_pci_devfn(char *bdf_slt) { - int seg, bus, dev, func, slot; + int seg, bus, dev, func, devfn; char *opt; - if ( !parse_bdf(&bdf_slt, &seg, &bus, &dev, &func, &opt, &slot) ) + if ( !parse_bdf(&bdf_slt, &seg, &bus, &dev, &func, &opt, &devfn) ) { return -1; } - return __insert_to_pci_slot(bus, dev, func, slot, opt); + return __insert_to_pci_devfn(bus, dev, func, devfn, opt); } -/* Test if a pci slot has a PHP device +/* Test if a pci devfn has a PHP device * 1: present * 0: not present - * -1: invalid pci slot input + * -1: invalid pci devfn input */ -int test_pci_slot(int slot) +int test_pci_devfn(int devfn) { - if ( slot < 0 || slot >= NR_PCI_DEVFN ) + if ( devfn < 0 || devfn >= NR_PCI_DEVFN ) return -1; - if ( dpci_infos.php_devs[slot].valid ) + if ( dpci_infos.php_devs[devfn].valid ) return 1; return 0; } -/* find the pci slot for pass-through dev with specified BDF */ -int bdf_to_slot(char *bdf_str) +/* find the pci devfn for pass-through dev with specified BDF */ +int bdf_to_devfn(char *bdf_str) { - int seg, bus, dev, func, slot, i; + int seg, bus, dev, func, devfn, i; char *opt; - if ( !parse_bdf(&bdf_str, &seg, &bus, &dev, &func, &opt, &slot)) + if ( !parse_bdf(&bdf_str, &seg, &bus, &dev, &func, &opt, &devfn)) { return -1; } - /* locate the virtual pci slot for this VTd device */ + /* locate the virtual pci devfn for this VTd device */ for ( i = 0; i < NR_PCI_DEVFN; i++ ) { - if ( pci_slot_match(bus, dev, func, i) ) + if ( pci_devfn_match(bus, dev, func, i) ) return i; } @@ -3960,7 +3960,7 @@ static int pt_pmcsr_reg_restore(struct p } static struct pt_dev * register_real_device(PCIBus *e_bus, - const char *e_dev_name, int e_slot, uint8_t r_bus, uint8_t r_dev, + const char *e_dev_name, int e_devfn, uint8_t r_bus, uint8_t r_dev, uint8_t r_func, uint32_t machine_irq, struct pci_access *pci_access, char *opt) { @@ -4037,7 +4037,7 @@ static struct pt_dev * register_real_dev /* Register device */ assigned_device = (struct pt_dev *) pci_register_device(e_bus, e_dev_name, - sizeof(struct pt_dev), e_slot, + sizeof(struct pt_dev), e_devfn, pt_pci_read_config, pt_pci_write_config); if ( assigned_device == NULL ) { @@ -4045,7 +4045,7 @@ static struct pt_dev * register_real_dev return NULL; } - dpci_infos.php_devs[e_slot].pt_dev = assigned_device; + dpci_infos.php_devs[e_devfn].pt_dev = assigned_device; assigned_device->pci_dev = pci_dev; assigned_device->msi_trans_cap = msi_translate; @@ -4145,7 +4145,7 @@ out: return assigned_device; } -static int unregister_real_device(int slot) +static int unregister_real_device(int devfn) { struct php_dev *php_dev; struct pci_dev *pci_dev; @@ -4155,10 +4155,10 @@ static int unregister_real_device(int sl uint32_t bdf = 0; int rc = -1; - if ( test_pci_slot(slot) != 1 ) + if ( test_pci_devfn(devfn) != 1 ) return -1; - php_dev = &dpci_infos.php_devs[slot]; + php_dev = &dpci_infos.php_devs[devfn]; assigned_device = php_dev->pt_dev; if ( !assigned_device ) @@ -4209,7 +4209,7 @@ static int unregister_real_device(int sl pt_iomul_free(assigned_device); - /* mark this slot as free */ + /* mark this devfn as free */ php_dev->valid = 0; php_dev->pt_dev = NULL; qemu_free(assigned_device); @@ -4217,14 +4217,14 @@ static int unregister_real_device(int sl return 0; } -int power_on_php_slot(int slot) +int power_on_php_devfn(int devfn) { - struct php_dev *php_dev = &dpci_infos.php_devs[slot]; + struct php_dev *php_dev = &dpci_infos.php_devs[devfn]; struct pt_dev *pt_dev; pt_dev register_real_device(dpci_infos.e_bus, "DIRECT PCI", - slot, + devfn, php_dev->r_bus, php_dev->r_dev, php_dev->r_func, @@ -4238,9 +4238,9 @@ int power_on_php_slot(int slot) } -int power_off_php_slot(int php_slot) +int power_off_php_devfn(int php_devfn) { - return unregister_real_device(php_slot); + return unregister_real_device(php_devfn); } int pt_init(PCIBus *e_bus) Index: ioemu-remote/hw/pci.h ==================================================================--- ioemu-remote.orig/hw/pci.h 2009-06-15 11:25:45.000000000 +1000 +++ ioemu-remote/hw/pci.h 2009-06-15 11:25:50.000000000 +1000 @@ -261,11 +261,11 @@ PCIBus *pci_bridge_init(PCIBus *bus, int #define AUTO_PHP_SLOT NR_PCI_DEV #define AUTO_PHP_DEVFN NR_PCI_DEVFN -int insert_to_pci_slot(char*); -int test_pci_slot(int); -int bdf_to_slot(char*); -int power_on_php_slot(int); -int power_off_php_slot(int); +int insert_to_pci_devfn(char *bdf_devfn); +int test_pci_devfn(int devfn); +int bdf_to_devfn(char *bdf_str); +int power_on_php_devfn(int devfn); +int power_off_php_devfn(int devfn); /* pci_emulation.c */ #include "hw/pci_emulation.h" Index: ioemu-remote/xen-vl-extra.c ==================================================================--- ioemu-remote.orig/xen-vl-extra.c 2009-06-15 11:25:37.000000000 +1000 +++ ioemu-remote/xen-vl-extra.c 2009-06-15 11:25:50.000000000 +1000 @@ -102,31 +102,31 @@ struct qemu_alarm_timer; #ifdef CONFIG_PASSTHROUGH void do_pci_del(char *devname) { - int pci_slot; + int devfn; char *devname_cpy; devname_cpy = strdup(devname); if (!devname_cpy) return; - pci_slot = bdf_to_slot(devname); + devfn = bdf_to_devfn(devname); - if (pci_slot < 0) + if (devfn < 0) fprintf(logfile, "Device \"%s\" is not used by a hotplug device.\n", devname_cpy); else - acpi_php_del(pci_slot); + acpi_php_del(devfn); free(devname_cpy); } void do_pci_add(char *devname) { - int pci_slot; + int devfn; - pci_slot = insert_to_pci_slot(devname); + devfn = insert_to_pci_devfn(devname); - acpi_php_add(pci_slot); + acpi_php_add(devfn); } int pci_emulation_add(char *config_text) Index: ioemu-remote/hw/piix4acpi.c ==================================================================--- ioemu-remote.orig/hw/piix4acpi.c 2009-06-15 11:25:45.000000000 +1000 +++ ioemu-remote/hw/piix4acpi.c 2009-06-15 11:25:50.000000000 +1000 @@ -278,7 +278,7 @@ static void acpi_php_writeb(void *opaque hotplug_slots->plug_slot = 0; /* power off the slot */ - power_off_php_slot(PCI_DEVFN(slot, 0)); + power_off_php_devfn(PCI_DEVFN(slot, 0)); /* signal the CP ACPI hot remove done. */ xenstore_record_dm_state("pci-removed"); @@ -318,7 +318,7 @@ static void php_slots_init(void) /* update the pci slot status */ for ( i = 0; i < NR_PCI_DEV; i++ ) { - if ( test_pci_slot(i) ) + if ( test_pci_devfn(i) ) php_slots.status[i] = 0xf; } @@ -469,7 +469,7 @@ void acpi_php_del(int devfn) slot = PCI_SLOT(devfn); func = PCI_FUNC(devfn); - if ( test_pci_slot(devfn) < 0 ) { + if ( test_pci_devfn(devfn) < 0 ) { fprintf(logfile, "hot remove: pci slot 0x%02x, function 0x%x " "is not used by a hotplug device.\n", slot, func); @@ -537,7 +537,7 @@ void acpi_php_add(int devfn) } /* power on the function */ - power_on_php_slot(devfn); + power_on_php_devfn(devfn); /* tell Control panel which slot for the new pass-throgh dev */ sprintf(ret_str, "0x%02x", devfn); -- _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Simon Horman
2009-Jun-17 08:07 UTC
[Xen-devel] [rfc 5/8] qemu-xen: pass-through: Add AUTO_PHP_DEVFN_MULTI
Up until now there has been a signle magic value that xend can pass to qemu-xen to signify that qemu-xen should choose a devfn for a pass-through function. When supporting multi-function devices in guests, it is useful for xend to be able to sepcify if a function is to appear in a guest as a single-function deveice, or as part of a multi-function device. By adding AUTO_PHP_DEVFN_MULTI to suplement the existing AUTO_PHP_DEVFN, this patch achieves that goal. This patch does not break compatibility with xend as the value chosen for AUTO_PHP_DEVFN_MULTI could never validly be sent by xend up until now. However, there is a companion change to xend in order to make use of this feature. Cc: Dexuan Cui <dexuan.cui@intel.com> Cc: Masaki Kanno <kanno.masaki@jp.fujitsu.com> Signed-off-by: Simon Horman <horms@verge.net.au> Index: ioemu-remote/hw/pass-through.c ==================================================================--- ioemu-remote.orig/hw/pass-through.c 2009-06-15 11:25:50.000000000 +1000 +++ ioemu-remote/hw/pass-through.c 2009-06-15 11:25:53.000000000 +1000 @@ -859,7 +859,7 @@ static int parse_bdf(char **str, int *se } else { - *vdevfn = AUTO_PHP_DEVFN; + *vdevfn = AUTO_PHP_SLOT; *opt = token; } @@ -902,8 +902,32 @@ static int pci_devfn_match(int bus, int return 0; } +static int find_free_vslot(void) +{ + PCIBus *e_bus = dpci_infos.e_bus; + int slot, func, devfn; + + for ( slot = 0; slot < NR_PCI_DEV; slot++ ) + { + for ( func = 0; func < NR_PCI_FUNC; func++ ) + { + devfn = PCI_DEVFN(slot, func); + if ( test_pci_devfn(devfn) || pci_devfn_in_use(e_bus, devfn) ) + { + break; + } + } + if (func == NR_PCI_FUNC) + return slot; + } + + /* not found */ + return -1; +} + + /* Insert a new pass-through device into a specific pci devfn. - * input dom:bus:dev.func@devfn, chose free one if devfn == AUTO_PHP_DEVFN + * input dom:bus:dev.func@devfn, chose free one if devfn & AUTO_PHP_SLOT * return -2: requested devfn not available * -1: no free devfns * >=0: the new hotplug devfn @@ -912,28 +936,23 @@ static int __insert_to_pci_devfn(int bus char *opt) { PCIBus *e_bus = dpci_infos.e_bus; - int slot; + int vslot; - /* preferred virt pci devfn */ - if ( devfn != AUTO_PHP_DEVFN ) + if ( devfn & AUTO_PHP_SLOT ) { - if ( !test_pci_devfn(devfn) && !pci_devfn_in_use(e_bus, devfn) ) - goto found; - return -2; + vslot = find_free_vslot(); + if (vslot < 0) + return -1; + /* The vfunc is provided in the devfn paramter */ + devfn = PCI_DEVFN(vslot, PCI_FUNC(devfn)); } - - /* pick a free slot */ - for ( slot = 0; slot < NR_PCI_DEV; slot++ ) + else { - devfn = PCI_DEVFN(slot, 0); - if ( !test_pci_devfn(devfn) && !pci_devfn_in_use(e_bus, devfn) ) - goto found; + /* Prefered devfn */ + if ( test_pci_devfn(devfn) || pci_devfn_in_use(e_bus, devfn) ) + return -2; } - /* not found */ - return -1; - -found: dpci_infos.php_devs[devfn].valid = 1; dpci_infos.php_devs[devfn].r_bus = bus; dpci_infos.php_devs[devfn].r_dev = dev; Index: ioemu-remote/hw/pci.h ==================================================================--- ioemu-remote.orig/hw/pci.h 2009-06-15 11:25:50.000000000 +1000 +++ ioemu-remote/hw/pci.h 2009-06-15 11:25:53.000000000 +1000 @@ -255,11 +255,10 @@ void pci_info(void); PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid, uint16_t did, pci_map_irq_fn map_irq, const char *name); -#define NR_PCI_FUNC 8 -#define NR_PCI_DEV 32 -#define NR_PCI_DEVFN (NR_PCI_FUNC * NR_PCI_DEV) -#define AUTO_PHP_SLOT NR_PCI_DEV -#define AUTO_PHP_DEVFN NR_PCI_DEVFN +#define NR_PCI_FUNC 8 +#define NR_PCI_DEV 32 +#define NR_PCI_DEVFN (NR_PCI_FUNC * NR_PCI_DEV) +#define AUTO_PHP_SLOT 0x100 int insert_to_pci_devfn(char *bdf_devfn); int test_pci_devfn(int devfn); -- _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Simon Horman
2009-Jun-17 08:07 UTC
[Xen-devel] [rfc 6/8] qemu-xen: pass-through: multi-function PCI in ACPI
This changes the interface beween qemu-xen and the ACPI portion of hvmlader. As such it breaks compatibility with older hvmloaders and a companion patch to hvmloader is needed. There is a subsequent "noise" companion to this change which changes slot to devfn as appropriate. Cc: Dexuan Cui <dexuan.cui@intel.com> Cc: Masaki Kanno <kanno.masaki@jp.fujitsu.com> Signed-off-by: Simon Horman <horms@verge.net.au> --- This patch is co-dependent on "hvmloader: multi-function PCI hot-plug" Index: ioemu-remote/hw/piix4acpi.c ==================================================================--- ioemu-remote.orig/hw/piix4acpi.c 2009-04-06 14:56:00.000000000 +1000 +++ ioemu-remote/hw/piix4acpi.c 2009-04-06 15:01:49.000000000 +1000 @@ -56,8 +56,9 @@ /* The bit in GPE0_STS/EN to notify the pci hotplug event */ #define ACPI_PHP_GPE_BIT 3 -typedef struct AcpiDeviceState AcpiDeviceState; -AcpiDeviceState *acpi_device_table; +#define NR_PHP_SLOT_REG (NR_PCI_DEVFN/2) +#define DEVFN_TO_PHP_SLOT_REG(devfn) (devfn >> 1) +#define PHP_SLOT_REG_TO_DEVFN(reg, hilo) ((reg << 1) | hilo) typedef struct PCIAcpiState { PCIDevice dev; @@ -77,17 +78,46 @@ typedef struct GPEState { static GPEState gpe_state; typedef struct PHPSlots { - uint8_t status[NR_PCI_DEV]; /* Apaptor stats */ - uint8_t plug_evt; /* PHP_EVT_ADD or PHP_EVT_REMOVE - * PSTA in ASL */ - uint8_t plug_slot; /* Slot number - * PSTB in ASL */ + uint8_t status[NR_PHP_SLOT_REG]; /* Apaptor n stats | Adaptor n+1 status */ + uint8_t plug_evt; /* PHP_EVT_ADD or PHP_EVT_REMOVE + * PSTA in ASL */ + uint8_t plug_slot; /* Slot number + * PSTB in ASL */ } PHPSlots; static PHPSlots php_slots; int s3_shutdown_flag; static qemu_irq sci_irq; +static void php_reg_set(PHPSlots *hotplug_slots, int devfn, uint8_t val) +{ + uint8_t *reg = &(hotplug_slots->status[DEVFN_TO_PHP_SLOT_REG(devfn)]); + + /* Value may only use a nibble */ + val &= 0xf; + + if (devfn & 0x1) + *reg = (*reg & 0x0f) | (val << 4); + else + *reg = (*reg & 0xf0) | val; +} + + +static uint8_t php_reg_get(PHPSlots *hotplug_slots, int devfn) +{ + uint8_t reg = hotplug_slots->status[DEVFN_TO_PHP_SLOT_REG(devfn)]; + uint8_t val; + + if (devfn & 0x1) + val = (reg & 0xf0) >> 4; + else + val = reg & 0x0f; + + return val; +} + +typedef struct AcpiDeviceState AcpiDeviceState; +AcpiDeviceState *acpi_device_table; static void piix4acpi_save(QEMUFile *f, void *opaque) { PCIAcpiState *s = opaque; @@ -225,8 +255,8 @@ static void acpi_dbg_writel(void *opaque * ACPI_PHP_IO_ADDR + : * 0 - the hotplug event * 1 - the slot that has a hotplug event - * 2 - 1st php slot ctr/sts reg - * 3 - 2nd php slot ctr/sts reg + * 2 - 1st php slot ctr/sts reg|2nd php slot ctr/sts reg + * 3 - 3rd php slot ctr/sts reg|4th php slot ctr/sts reg * ... */ static uint32_t acpi_php_readb(void *opaque, uint32_t addr) @@ -248,7 +278,7 @@ static uint32_t acpi_php_readb(void *opa val = hotplug_slots->status[num]; } - fprintf(logfile, "ACPI PCI hotplug: read addr=0x%x, val=0x%x.\n", + fprintf(logfile, "ACPI PCI hotplug: read addr=0x%x, val=0x%02x.\n", addr, val); return val; @@ -257,9 +287,9 @@ static uint32_t acpi_php_readb(void *opa static void acpi_php_writeb(void *opaque, uint32_t addr, uint32_t val) { PHPSlots *hotplug_slots = opaque; - int slot; + int devfn, num, func, i; - fprintf(logfile, "ACPI PCI hotplug: write addr=0x%x, val=0x%x.\n", + fprintf(logfile, "ACPI PCI hotplug: write addr=0x%x, val=0x%02x.\n", addr, val); switch (addr) @@ -268,17 +298,39 @@ static void acpi_php_writeb(void *opaque case ACPI_PHP_IO_ADDR + 1: break; default: - slot = addr - ACPI_PHP_IO_ADDR - 2; - if ( val == 0x1 ) { /* Eject command */ - /* make _STA of the slot 0 */ - hotplug_slots->status[slot] = 0; + num = addr - ACPI_PHP_IO_ADDR - 2; + if ( val == 0x01 || val == 0x10 ) { /* Eject command */ + if ( val == 0x01 ) + devfn = PHP_SLOT_REG_TO_DEVFN(num, 0); + else + devfn = PHP_SLOT_REG_TO_DEVFN(num, 1); + + fprintf(logfile, "ACPI PCI hotplug: write devfn=0x%02x.\n", + devfn); + + if (hotplug_slots->plug_evt != PHP_EVT_REMOVE || + hotplug_slots->plug_slot != devfn ) + { + fprintf(logfile, "ACPI PCI hotplug: not expecting " + "devfn 0x%02x to be removed. Expected event 0x%x " + "for devfn 0x%02x\n", devfn, + hotplug_slots->plug_evt, hotplug_slots->plug_slot); + return; + } /* clear the hotplug event */ hotplug_slots->plug_evt = 0; - hotplug_slots->plug_slot = 0; - /* power off the slot */ - power_off_php_devfn(PCI_DEVFN(slot, 0)); + for ( func = NR_PCI_FUNC - 1; func >= 0; func-- ) + { + i = PCI_DEVFN(PCI_SLOT(devfn), func); + + /* make _STA of the slot 0 */ + php_reg_set(hotplug_slots, i, 0); + + /* power off the slot */ + power_off_php_devfn(i); + } /* signal the CP ACPI hot remove done. */ xenstore_record_dm_state("pci-removed"); @@ -290,7 +342,7 @@ static void pcislots_save(QEMUFile* f, v { PHPSlots *hotplug_slots = opaque; int i; - for ( i = 0; i < NR_PCI_DEV; i++ ) { + for ( i = 0; i < NR_PHP_SLOT_REG; i++ ) { qemu_put_8s( f, &hotplug_slots->status[i]); } qemu_put_8s(f, &hotplug_slots->plug_evt); @@ -303,7 +355,7 @@ static int pcislots_load(QEMUFile* f, vo int i; if (version_id != 1) return -EINVAL; - for ( i = 0; i < NR_PCI_DEV; i++ ) { + for ( i = 0; i < NR_PHP_SLOT_REG; i++ ) { qemu_get_8s( f, &hotplug_slots->status[i]); } qemu_get_8s(f, &hotplug_slots->plug_evt); @@ -317,15 +369,15 @@ static void php_slots_init(void) memset(&php_slots, 0, sizeof(PHPSlots)); /* update the pci slot status */ - for ( i = 0; i < NR_PCI_DEV; i++ ) { + for ( i = 0; i < NR_PCI_DEVFN; i++ ) { if ( test_pci_devfn(i) ) - php_slots.status[i] = 0xf; + php_reg_set(&php_slots, i, 0xf); } /* ACPI PCI hotplug controller */ - register_ioport_read(ACPI_PHP_IO_ADDR, NR_PCI_DEV + 2, 1, + register_ioport_read(ACPI_PHP_IO_ADDR, NR_PHP_SLOT_REG + 2, 1, acpi_php_readb, &php_slots); - register_ioport_write(ACPI_PHP_IO_ADDR, NR_PCI_DEV + 2, 1, + register_ioport_write(ACPI_PHP_IO_ADDR, NR_PHP_SLOT_REG + 2, 1, acpi_php_writeb, &php_slots); register_savevm("pcislots", 0, 1, pcislots_save, pcislots_load, &php_slots); @@ -489,7 +541,7 @@ void acpi_php_del(int devfn) /* update the php controller status */ php_slots.plug_evt = PHP_EVT_REMOVE; - php_slots.plug_slot = slot; + php_slots.plug_slot = devfn; /* generate a SCI interrupt */ acpi_sci_intr(s); @@ -530,12 +582,12 @@ void acpi_php_add(int devfn) { /* update the php controller status */ php_slots.plug_evt = PHP_EVT_ADD; - php_slots.plug_slot = slot; - - /* update the slot status as present */ - php_slots.status[slot] = 0xf; + php_slots.plug_slot = devfn; } + /* update the slot status as present */ + php_reg_set(&php_slots, devfn, 0xf); + /* power on the function */ power_on_php_devfn(devfn); -- _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Simon Horman
2009-Jun-17 08:07 UTC
[Xen-devel] [rfc 7/8] qemu-xen: pass-through: multi-function PCI in ACPI: rename slot to devfn
This is a companion to the previous patch "qemu-xen: pass-through: multi-function PCI in ACPI". It does not make any functional changes, rather it just renames slot to devfn as appropriate. Cc: Dexuan Cui <dexuan.cui@intel.com> Cc: Masaki Kanno <kanno.masaki@jp.fujitsu.com> Signed-off-by: Simon Horman <horms@verge.net.au> Index: ioemu-remote/hw/piix4acpi.c ==================================================================--- ioemu-remote.orig/hw/piix4acpi.c 2009-06-15 11:25:56.000000000 +1000 +++ ioemu-remote/hw/piix4acpi.c 2009-06-15 11:25:57.000000000 +1000 @@ -77,21 +77,21 @@ typedef struct GPEState { static GPEState gpe_state; -typedef struct PHPSlots { +typedef struct PHPDevFn { uint8_t status[NR_PHP_SLOT_REG]; /* Apaptor n stats | Adaptor n+1 status */ uint8_t plug_evt; /* PHP_EVT_ADD or PHP_EVT_REMOVE * PSTA in ASL */ - uint8_t plug_slot; /* Slot number + uint8_t plug_devfn; /* DevFn number * PSTB in ASL */ -} PHPSlots; +} PHPDevFn; -static PHPSlots php_slots; +static PHPDevFn php_devfn; int s3_shutdown_flag; static qemu_irq sci_irq; -static void php_reg_set(PHPSlots *hotplug_slots, int devfn, uint8_t val) +static void php_reg_set(PHPDevFn *hotplug_devfn, int devfn, uint8_t val) { - uint8_t *reg = &(hotplug_slots->status[DEVFN_TO_PHP_SLOT_REG(devfn)]); + uint8_t *reg = &(hotplug_devfn->status[DEVFN_TO_PHP_SLOT_REG(devfn)]); /* Value may only use a nibble */ val &= 0xf; @@ -103,9 +103,9 @@ static void php_reg_set(PHPSlots *hotplu } -static uint8_t php_reg_get(PHPSlots *hotplug_slots, int devfn) +static uint8_t php_reg_get(PHPDevFn *hotplug_devfn, int devfn) { - uint8_t reg = hotplug_slots->status[DEVFN_TO_PHP_SLOT_REG(devfn)]; + uint8_t reg = hotplug_devfn->status[DEVFN_TO_PHP_SLOT_REG(devfn)]; uint8_t val; if (devfn & 0x1) @@ -254,28 +254,28 @@ static void acpi_dbg_writel(void *opaque * simple PCI hotplug controller IO * ACPI_PHP_IO_ADDR + : * 0 - the hotplug event - * 1 - the slot that has a hotplug event - * 2 - 1st php slot ctr/sts reg|2nd php slot ctr/sts reg - * 3 - 3rd php slot ctr/sts reg|4th php slot ctr/sts reg + * 1 - the devfn that has a hotplug event + * 2 - 1st php devfn ctr/sts reg|2nd php devfn ctr/sts reg + * 3 - 3rd php devfn ctr/sts reg|4th php devfn ctr/sts reg * ... */ static uint32_t acpi_php_readb(void *opaque, uint32_t addr) { - PHPSlots *hotplug_slots = opaque; + PHPDevFn *hotplug_devfn = opaque; int num; uint32_t val; switch (addr) { case ACPI_PHP_IO_ADDR: - val = hotplug_slots->plug_evt; + val = hotplug_devfn->plug_evt; break; case ACPI_PHP_IO_ADDR + 1: - val = hotplug_slots->plug_slot; + val = hotplug_devfn->plug_devfn; break; default: num = addr - ACPI_PHP_IO_ADDR - 2; - val = hotplug_slots->status[num]; + val = hotplug_devfn->status[num]; } fprintf(logfile, "ACPI PCI hotplug: read addr=0x%x, val=0x%02x.\n", @@ -286,7 +286,7 @@ static uint32_t acpi_php_readb(void *opa static void acpi_php_writeb(void *opaque, uint32_t addr, uint32_t val) { - PHPSlots *hotplug_slots = opaque; + PHPDevFn *hotplug_devfn = opaque; int devfn, num, func, i; fprintf(logfile, "ACPI PCI hotplug: write addr=0x%x, val=0x%02x.\n", @@ -308,25 +308,25 @@ static void acpi_php_writeb(void *opaque fprintf(logfile, "ACPI PCI hotplug: write devfn=0x%02x.\n", devfn); - if (hotplug_slots->plug_evt != PHP_EVT_REMOVE || - hotplug_slots->plug_slot != devfn ) + if (hotplug_devfn->plug_evt != PHP_EVT_REMOVE || + hotplug_devfn->plug_devfn!= devfn ) { fprintf(logfile, "ACPI PCI hotplug: not expecting " "devfn 0x%02x to be removed. Expected event 0x%x " "for devfn 0x%02x\n", devfn, - hotplug_slots->plug_evt, hotplug_slots->plug_slot); + hotplug_devfn->plug_evt, hotplug_devfn->plug_devfn); return; } /* clear the hotplug event */ - hotplug_slots->plug_evt = 0; + hotplug_devfn->plug_evt = 0; for ( func = NR_PCI_FUNC - 1; func >= 0; func-- ) { i = PCI_DEVFN(PCI_SLOT(devfn), func); - /* make _STA of the slot 0 */ - php_reg_set(hotplug_slots, i, 0); + /* make _STA of the devfn 0 */ + php_reg_set(hotplug_devfn, i, 0); /* power off the slot */ power_off_php_devfn(i); @@ -338,49 +338,49 @@ static void acpi_php_writeb(void *opaque } } -static void pcislots_save(QEMUFile* f, void* opaque) +static void pci_devfn_save(QEMUFile* f, void* opaque) { - PHPSlots *hotplug_slots = opaque; + PHPDevFn *hotplug_devfn = opaque; int i; for ( i = 0; i < NR_PHP_SLOT_REG; i++ ) { - qemu_put_8s( f, &hotplug_slots->status[i]); + qemu_put_8s( f, &hotplug_devfn->status[i]); } - qemu_put_8s(f, &hotplug_slots->plug_evt); - qemu_put_8s(f, &hotplug_slots->plug_slot); + qemu_put_8s(f, &hotplug_devfn->plug_evt); + qemu_put_8s(f, &hotplug_devfn->plug_devfn); } -static int pcislots_load(QEMUFile* f, void* opaque, int version_id) +static int pci_devfn_load(QEMUFile* f, void* opaque, int version_id) { - PHPSlots *hotplug_slots = opaque; + PHPDevFn *hotplug_devfn = opaque; int i; if (version_id != 1) return -EINVAL; for ( i = 0; i < NR_PHP_SLOT_REG; i++ ) { - qemu_get_8s( f, &hotplug_slots->status[i]); + qemu_get_8s( f, &hotplug_devfn->status[i]); } - qemu_get_8s(f, &hotplug_slots->plug_evt); - qemu_get_8s(f, &hotplug_slots->plug_slot); + qemu_get_8s(f, &hotplug_devfn->plug_evt); + qemu_get_8s(f, &hotplug_devfn->plug_devfn); return 0; } -static void php_slots_init(void) +static void php_devfn_init(void) { int i; - memset(&php_slots, 0, sizeof(PHPSlots)); + memset(&php_devfn, 0, sizeof(PHPDevFn)); - /* update the pci slot status */ + /* update the pci devfn status */ for ( i = 0; i < NR_PCI_DEVFN; i++ ) { if ( test_pci_devfn(i) ) - php_reg_set(&php_slots, i, 0xf); + php_reg_set(&php_devfn, i, 0xf); } /* ACPI PCI hotplug controller */ register_ioport_read(ACPI_PHP_IO_ADDR, NR_PHP_SLOT_REG + 2, 1, - acpi_php_readb, &php_slots); + acpi_php_readb, &php_devfn); register_ioport_write(ACPI_PHP_IO_ADDR, NR_PHP_SLOT_REG + 2, 1, - acpi_php_writeb, &php_slots); - register_savevm("pcislots", 0, 1, pcislots_save, pcislots_load, - &php_slots); + acpi_php_writeb, &php_devfn); + register_savevm("pci_devfn", 0, 1, pci_devfn_save, pci_devfn_load, + &php_devfn); } /* GPEx_STS occupy 1st half of the block, while GPEx_EN 2nd half */ @@ -540,8 +540,8 @@ void acpi_php_del(int devfn) } /* update the php controller status */ - php_slots.plug_evt = PHP_EVT_REMOVE; - php_slots.plug_slot = devfn; + php_devfn.plug_evt = PHP_EVT_REMOVE; + php_devfn.plug_devfn = devfn; /* generate a SCI interrupt */ acpi_sci_intr(s); @@ -581,17 +581,17 @@ void acpi_php_add(int devfn) if ( !func ) { /* update the php controller status */ - php_slots.plug_evt = PHP_EVT_ADD; - php_slots.plug_slot = devfn; + php_devfn.plug_evt = PHP_EVT_ADD; + php_devfn.plug_devfn = devfn; } - /* update the slot status as present */ - php_reg_set(&php_slots, devfn, 0xf); + /* update the devfn status as present */ + php_reg_set(&php_devfn, devfn, 0xf); /* power on the function */ power_on_php_devfn(devfn); - /* tell Control panel which slot for the new pass-throgh dev */ + /* tell Control panel which devfn for the new pass-throgh dev */ sprintf(ret_str, "0x%02x", devfn); xenstore_record_dm("parameter", ret_str); @@ -651,7 +651,7 @@ i2c_bus *piix4_pm_init(PCIBus *bus, int #ifdef CONFIG_PASSTHROUGH gpe_acpi_init(); - php_slots_init(); + php_devfn_init(); register_ioport_write(ACPI_DBG_IO_ADDR, 4, 4, acpi_dbg_writel, d); #endif @@ -661,7 +661,7 @@ i2c_bus *piix4_pm_init(PCIBus *bus, int } void qemu_system_hot_add_init() { } -void qemu_system_device_hot_add(int bus, int slot, int state) { +void qemu_system_device_hot_add(int bus, int devfn, int state) { fputs("qemu-upstream PCI hotplug not supported in qemu-dm\n",stderr); exit(-1); } -- _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Simon Horman
2009-Jun-17 08:07 UTC
[Xen-devel] [rfc 8/8] qemu-xen: pass-through: rename vslot to vdevfn and vslots to vdevfns
This is a noisy patch that makes no functional changes. It renames vslot to vdevfn and vslots to vdevfns. This breaks compatibility with xend and as a xenstore entry has been renamed. A companion patch for that code will be posted separately. Cc: Dexuan Cui <dexuan.cui@intel.com> Cc: Masaki Kanno <kanno.masaki@jp.fujitsu.com> Signed-off-by: Simon Horman <horms@verge.net.au> --- Co-Dependent on "xend: pass-through: rename vslot to vdevfn and vslots to vdevfns" Index: ioemu-remote/qemu-xen.h ==================================================================--- ioemu-remote.orig/qemu-xen.h 2009-06-15 11:26:01.000000000 +1000 +++ ioemu-remote/qemu-xen.h 2009-06-15 11:26:10.000000000 +1000 @@ -71,7 +71,7 @@ void xenstore_record_dm_state(const char void xenstore_check_new_media_present(int timeout); void xenstore_write_vncport(int vnc_display); void xenstore_read_vncpasswd(int domid, char *pwbuf, size_t pwbuflen); -void xenstore_write_vslots(char *vslots); +void xenstore_write_vdevfns(char *vdevfns); int xenstore_domain_has_devtype_danger(struct xs_handle *handle, const char *devtype); Index: ioemu-remote/xenstore.c ==================================================================--- ioemu-remote.orig/xenstore.c 2009-06-15 11:26:01.000000000 +1000 +++ ioemu-remote/xenstore.c 2009-06-15 11:26:10.000000000 +1000 @@ -971,18 +971,18 @@ void xenstore_write_vncport(int display) free(buf); } -void xenstore_write_vslots(char *vslots) +void xenstore_write_vdevfns(char *vdevfns) { char *path = NULL; int pci_devid = 0; if (pasprintf(&path, - "/local/domain/0/backend/pci/%u/%u/vslots", domid, pci_devid) == -1) { - fprintf(logfile, "out of memory when updating vslots.\n"); + "/local/domain/0/backend/pci/%u/%u/vdevfns", domid, pci_devid) == -1) { + fprintf(logfile, "out of memory when updating vdevfns.\n"); goto out; } - if (!xs_write(xsh, XBT_NULL, path, vslots, strlen(vslots))) - fprintf(logfile, "error updating vslots \n"); + if (!xs_write(xsh, XBT_NULL, path, vdevfns, strlen(vdevfns))) + fprintf(logfile, "error updating vdevfns \n"); out: free(path); -- _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel