[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] Experimental results for VGA passthrough
On Mon, Jun 8, 2009 at 2:51 PM, Beng Heng, Ng<bengheng@xxxxxxxxxxxxxx> wrote: > The patch was mostly originally from XCI, and subsequently the Xen 3.4 > testing branch. > > Note that this does not include HID passthrough. It only demonstrates > VGA passthrough. > > Also, you need to specify the following in your DomU configuration. > vga_passthrough=1 > intel=1 What does intel=1 do? > dom0_input="0" (can ignore for now, since I did not include dom0 driver) > > I've only tried it for HVM guests. But it should work for PV too. I've > got good results on Windows DomU. On Linux, there was an error that says > the guest is trying to access unintialised BAR. > > - Beng Heng > > Andrew Lyon wrote: >> On Mon, Jun 8, 2009 at 6:36 AM, Beng Heng, Ng <bengheng@xxxxxxxxxxxxxx> >> wrote: >>> Certainly. I tried this on Xen 3.4.1 rc1 pre, changeset 19645. Most of >>> these stuff are from Jean and his team. Hopefully more people can update >>> their results. >>> >>> - Beng Heng >>> >>> Jun Koi wrote: >>>> Hi Beng, >>>> >>>> Would you please send the patch you applied on top of Xen to the list? >>>> I think many people are interested in that. >>>> >>>> Thanks, >>>> Jun >>>> >>>> >>>> >>> >>> diff -rupN --ignore-blank-lines-X diffignore >>> a/linux-2.6.18-xen.hg/drivers/xen/pciback/controller.c >>> b/linux-2.6.18-xen.hg/drivers/xen/pciback/controller.c >>> --- a/linux-2.6.18-xen.hg/drivers/xen/pciback/controller.c 2009-06-07 >>> 20:48:21.000000000 -0400 >>> +++ b/linux-2.6.18-xen.hg/drivers/xen/pciback/controller.c 2009-06-07 >>> 19:04:11.000000000 -0400 >>> @@ -208,7 +208,7 @@ void pciback_release_pci_dev(struct pcib >>> } >>> >>> spin_unlock_irqrestore(&dev_data->lock, flags); >>> - pcistub_put_pci_dev(found_dev); >>> + pcistub_put_pci_dev(found_dev, 0); >>> } >>> >>> int pciback_init_devices(struct pciback_device *pdev) >>> @@ -396,7 +396,7 @@ void pciback_release_devices(struct pcib >>> list_for_each_entry_safe(dev_entry, d, >>> &cntrl_entry->dev_list, list) { >>> list_del(&dev_entry->list); >>> - pcistub_put_pci_dev(dev_entry->dev); >>> + pcistub_put_pci_dev(dev_entry->dev, 0); >>> kfree(dev_entry); >>> } >>> list_del(&cntrl_entry->list); >>> diff -rupN --ignore-blank-lines-X diffignore >>> a/linux-2.6.18-xen.hg/drivers/xen/pciback/passthrough.c >>> b/linux-2.6.18-xen.hg/drivers/xen/pciback/passthrough.c >>> --- a/linux-2.6.18-xen.hg/drivers/xen/pciback/passthrough.c 2009-06-07 >>> 20:48:21.000000000 -0400 >>> +++ b/linux-2.6.18-xen.hg/drivers/xen/pciback/passthrough.c 2009-06-07 >>> 19:04:11.000000000 -0400 >>> @@ -88,7 +88,7 @@ void pciback_release_pci_dev(struct pcib >>> spin_unlock_irqrestore(&dev_data->lock, flags); >>> >>> if (found_dev) >>> - pcistub_put_pci_dev(found_dev); >>> + pcistub_put_pci_dev(found_dev, 1); >>> } >>> >>> int pciback_init_devices(struct pciback_device *pdev) >>> @@ -157,7 +157,7 @@ void pciback_release_devices(struct pcib >>> >>> list_for_each_entry_safe(dev_entry, t, &dev_data->dev_list, list) { >>> list_del(&dev_entry->list); >>> - pcistub_put_pci_dev(dev_entry->dev); >>> + pcistub_put_pci_dev(dev_entry->dev, 1); >>> kfree(dev_entry); >>> } >>> >>> diff -rupN --ignore-blank-lines-X diffignore >>> a/linux-2.6.18-xen.hg/drivers/xen/pciback/pciback.h >>> b/linux-2.6.18-xen.hg/drivers/xen/pciback/pciback.h >>> --- a/linux-2.6.18-xen.hg/drivers/xen/pciback/pciback.h 2009-06-07 >>> 20:48:21.000000000 -0400 >>> +++ b/linux-2.6.18-xen.hg/drivers/xen/pciback/pciback.h 2009-06-07 >>> 19:04:11.000000000 -0400 >>> @@ -25,6 +25,14 @@ struct pci_dev_entry { >>> #define _PCIB_op_pending (1) >>> #define PCIB_op_pending (1<<(_PCIB_op_pending)) >>> >>> +#define PCIBACK_TYPE_UNKNOWN 0 >>> +#define PCIBACK_TYPE_PCIe_ENDPOINT 1 >>> +#define PCIBACK_TYPE_PCIe_BRIDGE 2 >>> +#define PCIBACK_TYPE_PCI_BRIDGE 3 >>> +#define PCIBACK_TYPE_PCI 4 >>> + >>> +#define DEV_CLASS_PCI_PCI_BRIDGE 0x0604 >>> + >>> struct pciback_device { >>> void *pci_dev_data; >>> spinlock_t dev_lock; >>> @@ -48,6 +56,13 @@ struct pciback_dev_data { >>> struct list_head config_fields; >>> int permissive; >>> int warned_on_write; >>> + u32 dev_type; >>> + int no_flr; >>> + int exp_flr_offset; >>> + int af_flr_offset; >>> + int use_sbr; >>> + int use_d3r; >>> + u8 *cfg_space; /* saved config space for device */ >>> }; >>> >>> /* Get/Put PCI Devices that are hidden from the PCI Backend Domain */ >>> @@ -56,11 +71,25 @@ struct pci_dev *pcistub_get_pci_dev_by_s >>> int slot, int func); >>> struct pci_dev *pcistub_get_pci_dev(struct pciback_device *pdev, >>> struct pci_dev *dev); >>> -void pcistub_put_pci_dev(struct pci_dev *dev); >>> +void pcistub_put_pci_dev(struct pci_dev *dev, int do_flr); >>> + >>> +/* Reference/unreference PCI Devices and stubs without changing the state >>> */ >>> +struct pci_dev *pcistub_ref_pci_dev(struct pci_dev *dev); >>> +void pcistub_unref_pci_dev(struct pci_dev *dev); >>> + >>> +/* Store/reload config space for devices */ >>> +void pciback_store_config_space(struct pci_dev *dev); >>> +void pciback_reload_config_space(struct pci_dev *dev); >>> >>> /* Ensure a device is turned off or reset */ >>> void pciback_reset_device(struct pci_dev *pdev); >>> >>> +/* Do a function level reset (or approximage functionality) for device */ >>> +void pciback_flr_device(struct pci_dev *dev); >>> + >>> +/* Helper to classify the device type */ >>> +void pciback_classify_device(struct pci_dev *dev); >>> + >>> /* Access a virtual configuration space for a PCI device */ >>> int pciback_config_init(void); >>> int pciback_config_init_dev(struct pci_dev *dev); >>> @@ -102,6 +131,10 @@ void pciback_release_devices(struct pcib >>> irqreturn_t pciback_handle_event(int irq, void *dev_id, struct pt_regs >>> *regs); >>> void pciback_do_op(void *data); >>> >>> +/* Parse and load device specific module parameters */ >>> +int pciback_parse_device_params(const char *device_args, int type, >>> + int (*add_func) (int domain, int >>> bus, int slot, int func, int type)); >>> + >>> int pciback_xenbus_register(void); >>> void pciback_xenbus_unregister(void); >>> >>> diff -rupN --ignore-blank-lines-X diffignore >>> a/linux-2.6.18-xen.hg/drivers/xen/pciback/pciback_ops.c >>> b/linux-2.6.18-xen.hg/drivers/xen/pciback/pciback_ops.c >>> --- a/linux-2.6.18-xen.hg/drivers/xen/pciback/pciback_ops.c 2009-06-07 >>> 20:48:21.000000000 -0400 >>> +++ b/linux-2.6.18-xen.hg/drivers/xen/pciback/pciback_ops.c 2009-06-07 >>> 19:04:11.000000000 -0400 >>> @@ -5,20 +5,189 @@ >>> */ >>> #include <linux/module.h> >>> #include <linux/wait.h> >>> +#include <linux/delay.h> /* For mdelay function */ >>> #include <asm/bitops.h> >>> #include <xen/evtchn.h> >>> #include "pciback.h" >>> >>> +#define PCIBACK_VENDOR_INTEL 0x8086 >>> +#define PCIBACK_CLASS_ID_USB 0x0c03 >>> +#define PCIBACK_CLASS_ID_VGA 0x0300 >>> +#define PCIBACK_USB_FLRCTRL 0x4 >>> + >>> +#define PCIBACK_IGFX_CAP09_OFFSET 0xa4 >>> +#define PCIBACK_IGFX_CAP13_OFFSET 0xa4 >>> + >>> +#define PCIBACK_IGFX_MEDIARST 0x0d >>> +#define PCIBACK_IGFX_MEDIARST_OFFSET 0xc0 >>> + >>> int verbose_request = 0; >>> module_param(verbose_request, int, 0644); >>> >>> +struct pcistub_sbr_entry { >>> + struct list_head dev_list; >>> + struct pci_dev *dev; >>> +}; >>> + >>> +struct pcistub_sbr_list { >>> + struct list_head dev_list; >>> + struct pci_dev *bridge; >>> + struct pci_dev *dev; >>> + int find_all; >>> + int err; >>> +}; >>> + >>> +/* Used to store the config state so it can be restored after >>> + * resets. >>> + */ >>> +void pciback_store_config_space(struct pci_dev *dev) >>> +{ >>> + struct pciback_dev_data *dev_data = pci_get_drvdata(dev); >>> + u32 *ptr = (u32*)dev_data->cfg_space; >>> + int i, count = dev->cfg_size/sizeof(u32); >>> + >>> + for (i = 0; i < count; i += sizeof(u32), ptr++) >>> + pci_read_config_dword(dev, i, ptr); >>> +} >>> + >>> +/* Used to reload the config state after resets. >>> + */ >>> +void pciback_reload_config_space(struct pci_dev *dev) >>> +{ >>> + struct pciback_dev_data *dev_data = pci_get_drvdata(dev); >>> + u32 *ptr = (u32*)dev_data->cfg_space; >>> + int i, val, count = dev->cfg_size/sizeof(u32); >>> + >>> + for (i = 0; i < count; i += sizeof(u32), ptr++) { >>> + pci_read_config_dword(dev, i, &val); >>> + if (val != *ptr) >>> + pci_write_config_dword(dev, i, *ptr); >>> + } >>> +} >>> + >>> +static void pciback_walk_bus_cb(struct pci_dev *dev, void *userdata) >>> +{ >>> + struct pcistub_sbr_list *list = (struct pcistub_sbr_list*)userdata; >>> + struct pcistub_sbr_entry *entry; >>> + struct pci_dev *dev_tmp; >>> + >>> + if (list->err != 0) >>> + return; >>> + >>> + /* For PCIe endpoints we are only looking for co-assigned functions >>> */ >>> + if (!list->find_all && >>> + (dev->bus->number != list->dev->bus->number || >>> + PCI_SLOT(dev->devfn) != PCI_SLOT(list->dev->devfn))) >>> + return; >>> + >>> + dev_tmp = pcistub_ref_pci_dev(dev); >>> + if (dev_tmp == NULL) { >>> + /* not controlled by pciback, fail */ >>> + list->err = ENXIO; >>> + return; >>> + } >>> + >>> + entry = kzalloc(sizeof(*entry), GFP_ATOMIC); >>> + if (entry == NULL) { >>> + pcistub_unref_pci_dev(dev_tmp); >>> + list->err = ENOMEM; >>> + return; >>> + } >>> + >>> + entry->dev = dev_tmp; >>> + list_add_tail(&entry->dev_list, &list->dev_list); >>> +} >>> + >>> +static void pciback_cleanup_sbr_list(struct pcistub_sbr_list *list) >>> +{ >>> + struct pcistub_sbr_entry *entry; >>> + >>> + list_for_each_entry(entry, &list->dev_list, dev_list) { >>> + pcistub_unref_pci_dev(entry->dev); >>> + kfree(entry); >>> + } >>> +} >>> + >>> +/* Routine to find all devices and bridges that need to be reset >>> + * during a secondary bus reset. For PCIe this is simply all the >>> + * functions on the particular device. For PCI this is all devices >>> + * and bridges below the topmost PCI/PCI-X bridge. Note for PCI, >>> + * there is at least one something->PCI/PCI-X bridge to find since >>> + * the device is not on the host bus 0 and is on a PCI bus. >>> + */ >>> +static int pciback_get_sbr_list(struct pci_dev *dev, >>> + struct pcistub_sbr_list *list, int pcie_endpoint) >>> +{ >>> + struct pci_dev *bridge = dev->bus->self; >>> + struct pci_dev *last = NULL; >>> + int exp_pos; >>> + u16 exp_caps = 0; >>> + >>> + list->err = 0; >>> + list->dev = dev; >>> + INIT_LIST_HEAD(&list->dev_list); >>> + >>> + if (!pcie_endpoint) { >>> + while (bridge) { >>> + /* Looking for the uppermost PCI/PCI-X bridge. If >>> it is not PCIe then >>> + * this is a PCI/PCI-X bridge. If it is PCIe then >>> except the PCIe to >>> + * PCI/PCI-X type 7, the rest of the bridge types >>> are PCIe so the last >>> + * bridge encountered was the topmost PCI/PCI-X >>> bridge. >>> + */ >>> + exp_pos = pci_find_capability(bridge, >>> PCI_CAP_ID_EXP); >>> + if (exp_pos != 0) { >>> + pci_read_config_word(bridge, exp_pos + >>> PCI_EXP_FLAGS, &exp_caps); >>> + if (((exp_caps & PCI_EXP_FLAGS_TYPE) >> 4) >>> != PCI_EXP_TYPE_PCI_BRIDGE) >>> + break; /* don't want it in the list >>> if it is a PCIe bridge */ >>> + } >>> + last = bridge; >>> + bridge = last->bus->self; >>> + } >>> + list->bridge = last; >>> + list->find_all = 1; /* find all devices/bridges below the >>> topmost */ >>> + } >>> + else { >>> + if (bridge) { >>> + /* For PCIe, SBR logic is limited to PCIe endpoints >>> behind a root/switch >>> + * port. >>> + */ >>> + exp_pos = pci_find_capability(bridge, >>> PCI_CAP_ID_EXP); >>> + if (likely(exp_pos != 0)) { >>> + pci_read_config_word(bridge, exp_pos + >>> PCI_EXP_FLAGS, &exp_caps); >>> + exp_caps = ((exp_caps & PCI_EXP_FLAGS_TYPE) >>> >> 4); >>> + if (exp_caps == PCI_EXP_TYPE_ROOT_PORT || >>> + exp_caps == PCI_EXP_TYPE_UPSTREAM || >>> + exp_caps == PCI_EXP_TYPE_DOWNSTREAM) >>> + last = bridge; >>> + } >>> + } >>> + list->bridge = last; >>> + list->find_all = 0; /* find just functions on this slot */ >>> + } >>> + >>> + /* Sanity check, there may not be any appropriate bridge to reset */ >>> + if (!list->bridge) { >>> + dev_dbg(&dev->dev, "No appropriate bridge to reset\n"); >>> + return ENXIO; >>> + } >>> + >>> + pci_walk_bus(list->bridge->subordinate, pciback_walk_bus_cb, list); >>> + >>> + if (list->err) { >>> + pciback_cleanup_sbr_list(list); >>> + return list->err; >>> + } >>> + >>> + return 0; >>> +} >>> + >>> /* Ensure a device is "turned off" and ready to be exported. >>> * (Also see pciback_config_reset to ensure virtual configuration space is >>> * ready to be re-exported) >>> */ >>> void pciback_reset_device(struct pci_dev *dev) >>> { >>> - u16 cmd; >>> + u16 cmd = 0; >>> >>> /* Disable devices (but not bridges) */ >>> if (dev->hdr_type == PCI_HEADER_TYPE_NORMAL) { >>> @@ -38,6 +207,425 @@ void pciback_reset_device(struct pci_dev >>> } >>> } >>> } >>> + >>> +/* Do a PCIe type function level reset for a single function on this >>> + * device. >>> + */ >>> +static void pciback_do_pcie_flr(struct pci_dev *dev, int exp_pos) >>> +{ >>> + u16 status = 0; >>> + >>> + dev_dbg(&dev->dev, "doing PCIe FLR\n"); >>> + >>> + pci_block_user_cfg_access(dev); >>> + >>> + /* Wait for Transaction Pending bit clean */ >>> + msleep(100); >>> + pci_read_config_word(dev, exp_pos + PCI_EXP_DEVSTA, &status); >>> + if (status & PCI_EXP_DEVSTA_TRPND) { >>> + dev_dbg(&dev->dev, "Busy after 100ms while trying to reset; >>> sleeping for 1 second\n"); >>> + ssleep(1); >>> + pci_read_config_word(dev, exp_pos + PCI_EXP_DEVSTA, >>> &status); >>> + if (status & PCI_EXP_DEVSTA_TRPND) >>> + dev_warn(&dev->dev, "Still busy after 1s; >>> proceeding with reset anyway\n"); >>> + } >>> + >>> + pci_write_config_word(dev, exp_pos + PCI_EXP_DEVCTL, >>> PCI_EXP_DEVCTL_BCR_FLR); >>> + mdelay(200); >>> + >>> + pciback_reload_config_space(dev); >>> + >>> + pci_unblock_user_cfg_access(dev); >>> +} >>> + >>> +/* Do a PCI type function level reset for a single function on this >>> + * device. This uses the Advanced Features Capability extensions to >>> + * the PCI spec. >>> + */ >>> +static void pciback_do_pci_flr(struct pci_dev *dev, int af_pos, int >>> clear_cmd) >>> +{ >>> + u8 status = 0; >>> + >>> + dev_dbg(&dev->dev, "doing PCI FLR\n"); >>> + >>> + pci_block_user_cfg_access(dev); >>> + >>> + /* Clear the command register to prevent new transactions */ >>> + if (clear_cmd) >>> + pci_write_config_word(dev, PCI_COMMAND, 0); >>> + >>> + /* Wait for Transaction Pending bit clean */ >>> + msleep(100); >>> + pci_read_config_byte(dev, af_pos + PCI_AF_STA, &status); >>> + if (status & PCI_AF_STA_TP) { >>> + dev_dbg(&dev->dev, "Busy after 100ms while trying to reset; >>> sleeping for 1 second\n"); >>> + ssleep(1); >>> + pci_read_config_byte(dev, af_pos + PCI_AF_STA, &status); >>> + if (status & PCI_AF_STA_TP) >>> + dev_warn(&dev->dev, "Still busy after 1s; >>> proceeding with reset anyway\n"); >>> + } >>> + >>> + pci_write_config_byte(dev, af_pos + PCI_AF_CTRL, PCI_AF_CTRL_FLR); >>> + mdelay(200); >>> + >>> + pciback_reload_config_space(dev); >>> + >>> + pci_unblock_user_cfg_access(dev); >>> +} >>> + >>> +/* Vendor specific resets. These can be set in the vendor specific >>> + * capabilities structures. Currently only the Intel USB and iGFX >>> + * reset is supported. >>> + */ >>> +static int pciback_do_vendor_specific_reset(struct pci_dev *dev) >>> +{ >>> + struct pci_dev *gmch; >>> + int vendor_pos, i; >>> + u32 reg32 = 0; >>> + u16 device_id, cmd; >>> + u8 reg8 = 0; >>> + >>> + dev_dbg(&dev->dev, "doing vendor specific resets\n"); >>> + >>> + if (dev->vendor != PCIBACK_VENDOR_INTEL) >>> + return -ENXIO; >>> + >>> + if ((dev->class >> 8) == PCIBACK_CLASS_ID_VGA) { >>> + if (dev->bus->number != 0 || dev->devfn != PCI_DEVFN(2,0)) >>> + return -ENXIO; >>> + >>> + /* Locate the GMCH (north bridge) and test for specific >>> Intel devices */ >>> + gmch = pci_get_bus_and_slot(0, PCI_DEVFN(0,0)); >>> + if (!gmch) >>> + return -ENXIO; >>> + >>> + device_id = gmch->device; >>> + pci_dev_put(gmch); >>> + >>> + if (device_id != PCI_DEVICE_ID_INTEL_GMCHGM45) >>> + return -ENXIO; >>> + >>> + /* Correct device and platform, assume vendor specific >>> offset */ >>> + pci_read_config_dword(dev, PCIBACK_IGFX_CAP09_OFFSET, >>> ®32); >>> + if ((reg32 & 0x000000FF) != PCI_CAP_ID_VNDR || >>> + ((reg32 >> 16) & 0x000000FF) != 0x06 || >>> + ((reg32 >> 24) & 0x000000F0) != 0x20) >>> + return -ENXIO; >>> + >>> + vendor_pos = PCIBACK_IGFX_CAP09_OFFSET; >>> + } else if ((dev->class >> 8) == PCIBACK_CLASS_ID_USB) { >>> + vendor_pos = pci_find_capability(dev, PCI_CAP_ID_VNDR); >>> + if (vendor_pos == 0) >>> + return -ENXIO; >>> + } >>> + else >>> + return -ENXIO; >>> + >>> + if ((dev->class >> 8) == PCIBACK_CLASS_ID_VGA) { >>> + pci_write_config_byte(dev, PCIBACK_IGFX_MEDIARST_OFFSET, >>> PCIBACK_IGFX_MEDIARST); >>> + for (i = 0; i <= 10; i++) { >>> + msleep(100); >>> + pci_read_config_byte(dev, >>> PCIBACK_IGFX_MEDIARST_OFFSET, ®8); >>> + if ((reg8 & 0x01) == 0) >>> + break; >>> + if (i == 10) { >>> + dev_warn(&dev->dev, "media not reset after >>> 1s; skipping FLR\n"); >>> + goto out; >>> + } >>> + } >>> + >>> + /* This specific reset will hang if the command register >>> does not have >>> + * memory space access enabled */ >>> + pci_read_config_word(dev, PCI_COMMAND, &cmd); >>> + pci_write_config_word(dev, PCI_COMMAND, (cmd | >>> PCI_COMMAND_MEMORY)); >>> + /* The rest is the same as a PCI AF FLR - use the same >>> routine */ >>> + pciback_do_pci_flr(dev, vendor_pos, 0); >>> + pci_write_config_word(dev, PCI_COMMAND, cmd); >>> + } else { >>> + pci_block_user_cfg_access(dev); >>> + >>> + pci_write_config_byte(dev, vendor_pos + >>> PCIBACK_USB_FLRCTRL, 1); >>> + mdelay(200); >>> + >>> + pciback_reload_config_space(dev); >>> + >>> + pci_unblock_user_cfg_access(dev); >>> + } >>> + >>> +out: >>> + return 0; >>> +} >>> + >>> +/* Use a D0-D3-D0 device state transition to reset the device. This >>> + * is a good enough reset for some devices (like NICs). >>> + */ >>> +static int pciback_do_dstate_transition_reset(struct pci_dev *dev) >>> +{ >>> + int pm_pos; >>> + u32 pm_ctl = 0; >>> + >>> + pm_pos = pci_find_capability(dev, PCI_CAP_ID_PM); >>> + if (pm_pos == 0) >>> + return -ENXIO; >>> + >>> + dev_dbg(&dev->dev, "doing Dstate transition reset\n"); >>> + >>> + /* No_Soft_Reset - When set 1, this bit indicates that devices >>> + * transitioning from D3hot to D0 because of PowerState commands >>> + * do not perform an internal reset. >>> + */ >>> + pci_read_config_dword(dev, pm_pos + PCI_PM_CTRL, &pm_ctl); >>> + if (pm_ctl & PCI_PM_CTRL_NO_SOFT_RESET) >>> + return -ENXIO; >>> + >>> + pci_block_user_cfg_access(dev); >>> + >>> + pm_ctl &= ~PCI_PM_CTRL_STATE_MASK; >>> + pm_ctl |= PCI_PM_CTRL_D3HOT; >>> + pci_write_config_word(dev, pm_pos + PCI_PM_CTRL, pm_ctl); >>> + mdelay(10); >>> + >>> + pm_ctl &= ~PCI_PM_CTRL_STATE_MASK; >>> + pm_ctl |= PCI_PM_CTRL_D0; >>> + pci_write_config_word(dev, pm_pos + PCI_PM_CTRL, pm_ctl); >>> + mdelay(10); >>> + >>> + pciback_reload_config_space(dev); >>> + >>> + pci_unblock_user_cfg_access(dev); >>> + >>> + return 0; >>> +} >>> + >>> +/* Do a secondary bus reset on a bridge. This is only done if all >>> + * co-assignment rules are satisfied and if it was explicitly >>> + * requested via pciback parameters. >>> + */ >>> +static int pciback_do_secondary_bus_reset(struct pci_dev *dev, u32 >>> dev_type) >>> +{ >>> + struct pcistub_sbr_list sbr_list; >>> + struct pcistub_sbr_entry *entry; >>> + u16 pci_bctl = 0; >>> + int err = 0; >>> + >>> + /* Call helper to get the device list needed for the device type. */ >>> + err = pciback_get_sbr_list(dev, &sbr_list, >>> + (dev_type == PCIBACK_TYPE_PCIe_ENDPOINT ? 1 : 0)); >>> + if (err) { >>> + dev_warn(&dev->dev, >>> + "secondary bus reset failed for device - all >>> functions need to be co-assigned - err: %d\n", err); >>> + return err; >>> + } >>> + >>> + pci_block_user_cfg_access(dev); >>> + >>> + /* Reset the secondary bus and restore the PCI space for all the >>> devfn found above. >>> + */ >>> + pci_read_config_word(sbr_list.bridge, PCI_BRIDGE_CONTROL, >>> &pci_bctl); >>> + pci_write_config_word(sbr_list.bridge, PCI_BRIDGE_CONTROL, pci_bctl >>> | PCI_BRIDGE_CTL_BUS_RESET); >>> + msleep(200); >>> + pci_write_config_word(sbr_list.bridge, PCI_BRIDGE_CONTROL, >>> pci_bctl); >>> + msleep(200); >>> + >>> + list_for_each_entry(entry, &sbr_list.dev_list, dev_list) { >>> + pciback_reload_config_space(entry->dev); >>> + } >>> + >>> + pci_unblock_user_cfg_access(dev); >>> + >>> + pciback_cleanup_sbr_list(&sbr_list); >>> + >>> + return 0; >>> +} >>> + >>> +/* This function is used to do a function level reset on a singe >>> + * device/function. FLRs must be done on devices before they are >>> + * unassigned from one domain and passed through to another. The >>> + * preferred method is to do an actual FLR on the device but the >>> + * functionality may not be present or exposed. In the later case >>> + * we attempt to locate the capability even though it is not >>> + * chained into the capabilities list. >>> + * >>> + * In some cases, there is no way to perform the actual FLR so we >>> + * fall back to some alternate methods (which are not as effective >>> + * or useful). >>> + */ >>> +void pciback_flr_device(struct pci_dev *dev) >>> +{ >>> + struct pciback_dev_data *dev_data = pci_get_drvdata(dev); >>> + int err = 0; >>> + >>> + if (dev_data->no_flr) { >>> + dev_dbg(&dev->dev, "FLR disabled for device\n"); >>> + return; >>> + } >>> + dev_dbg(&dev->dev, "FLR invoked for device\n"); >>> + >>> + do { >>> + /* First, always try to do an FLR */ >>> + if (dev_data->dev_type == PCIBACK_TYPE_PCIe_ENDPOINT && >>> + dev_data->exp_flr_offset != 0) { >>> + pciback_do_pcie_flr(dev, dev_data->exp_flr_offset); >>> + break; >>> + } >>> + if (dev_data->dev_type == PCIBACK_TYPE_PCI && >>> + dev_data->af_flr_offset != 0) { >>> + pciback_do_pci_flr(dev, dev_data->af_flr_offset, 1); >>> + break; >>> + } >>> + >>> + /* Next for integrated devices on the host bus 0, try some >>> other methods */ >>> + if (dev->bus->number == 0) { >>> + err = pciback_do_vendor_specific_reset(dev); >>> + if (err && dev_data->use_d3r) >>> + err = >>> pciback_do_dstate_transition_reset(dev); >>> + if (err) >>> + dev_warn(&dev->dev, "FLR functionality not >>> supported; " >>> + "attempts to use vendor FLR >>> or D-states unsuccessful\n"); >>> + break; >>> + } >>> + >>> + /* Else attempt a secondary bus reset if all conditions are >>> met */ >>> + if (dev_data->use_sbr) { >>> + err = pciback_do_secondary_bus_reset(dev, >>> dev_data->dev_type); >>> + if (err) >>> + dev_warn(&dev->dev, "FLR functionality not >>> supported; " >>> + "attempts to use secondary >>> bus reset unsuccessful;\n"); >>> + break; >>> + } >>> + >>> + err = -ENODEV; >>> + } while (0); >>> + >>> + if (err) >>> + dev_warn(&dev->dev, "FLR not performed for device\n"); >>> +} >>> + >>> +/* Helper used to location the FLR capabilities for a PCIe device. >>> + * When the capability cannot be found in the chain but is present, >>> + * special logic is used to attempt to locate functionality. >>> + * >>> + * returns: the offset to the capability, zero if not found. >>> + */ >>> +static int pciback_find_pcie_flr_caps(struct pci_dev *dev) >>> +{ >>> + int exp_pos; >>> + u32 cap = 0; >>> + >>> + /* First look for the PCIe FLR capabilities using the capabilities >>> list */ >>> + exp_pos = pci_find_capability(dev, PCI_CAP_ID_EXP); >>> + if (exp_pos) { >>> + pci_read_config_dword(dev, exp_pos + PCI_EXP_DEVCAP, &cap); >>> + if (cap & PCI_EXP_DEVCAP_FLR) { >>> + return exp_pos; >>> + } >>> + } >>> + >>> + return 0; >>> +} >>> + >>> +/* Helper used to location the AF FLR capabilities for a PCI device. >>> + * When the capability cannot be found in the chain but is present, >>> + * special logic is used to attempt to locate functionality. >>> + * >>> + * returns: the offset to the capability, zero if not found. >>> + */ >>> +static int pciback_find_pci_flr_caps(struct pci_dev *dev) >>> +{ >>> + struct pci_dev *gmch; >>> + int af_pos; >>> + u16 device_id; >>> + u8 cap = 0, reg8 = 0; >>> + >>> + /* First look for the PCI AF capabilities for FLR using the >>> capabilities list. This >>> + * is only used on the devices on the root/host bus (integrated >>> devices). >>> + */ >>> + if (dev->bus->number != 0) >>> + return 0; >>> + >>> + af_pos = pci_find_capability(dev, PCI_CAP_ID_AF); >>> + if (af_pos) { >>> + pci_read_config_byte(dev, af_pos + PCI_AF_DEVCAP, &cap); >>> + if (cap & PCI_AF_CAP_FLR) { >>> + return af_pos; >>> + } >>> + } >>> + >>> + /* Next look for the unchained AF capabilities for FLR using >>> specific >>> + * logic. Currently only the graphics device on the Intel Q45 etc >>> + * systems has special logic for locating the hidden FLR caps. >>> + */ >>> + do { >>> + if (dev->bus->number != 0 || dev->devfn != PCI_DEVFN(2,0) || >>> + dev->vendor != PCIBACK_VENDOR_INTEL || (dev->class >>> >> 8) != PCIBACK_CLASS_ID_VGA) >>> + break; >>> + >>> + /* Locate the GMCH (north bridge) and test for specific >>> Intel devices */ >>> + gmch = pci_get_bus_and_slot(0, PCI_DEVFN(0,0)); >>> + if (!gmch) >>> + break; >>> + >>> + device_id = gmch->device; >>> + pci_dev_put(gmch); >>> + >>> + if (device_id != PCI_DEVICE_ID_INTEL_GMCHQ45 && >>> + device_id != PCI_DEVICE_ID_INTEL_GMCHG45 && >>> + device_id != PCI_DEVICE_ID_INTEL_GMCHG41) >>> + break; >>> + >>> + /* Correct device and platform, assume AF offset */ >>> + af_pos = PCIBACK_IGFX_CAP13_OFFSET; >>> + pci_read_config_byte(dev, af_pos + PCI_AF_LENFLD, ®8); >>> + if (reg8 == PCI_AF_LENGTH) { >>> + pci_read_config_byte(dev, af_pos + PCI_AF_DEVCAP, >>> &cap); >>> + if (cap & PCI_AF_CAP_FLR) { >>> + return af_pos; >>> + } >>> + } >>> + } while (0); >>> + >>> + /* Else not found */ >>> + return 0; >>> +} >>> + >>> +/* Classify the device, specifically determine if it is PCIe/PCI >>> + * and whether it is a PCIe endpoint, bridge, or other PCI device. >>> + */ >>> +void pciback_classify_device(struct pci_dev *dev) >>> +{ >>> + struct pciback_dev_data *dev_data; >>> + int exp_pos; >>> + u16 exp_caps = 0; >>> + >>> + dev_data = pci_get_drvdata(dev); >>> + dev_data->dev_type = PCIBACK_TYPE_UNKNOWN; >>> + >>> + exp_pos = pci_find_capability(dev, PCI_CAP_ID_EXP); >>> + >>> + if ((dev->class >> 8) != DEV_CLASS_PCI_PCI_BRIDGE) { >>> + if (exp_pos != 0) { >>> + dev_data->dev_type = PCIBACK_TYPE_PCIe_ENDPOINT; >>> + dev_data->exp_flr_offset = >>> pciback_find_pcie_flr_caps(dev); >>> + } else { >>> + dev_data->dev_type = PCIBACK_TYPE_PCI; >>> + dev_data->af_flr_offset = >>> pciback_find_pci_flr_caps(dev); >>> + } >>> + goto classify_done; >>> + } >>> + >>> + if (exp_pos == 0) { >>> + dev_data->dev_type = PCIBACK_TYPE_PCI_BRIDGE; >>> + goto classify_done; >>> + } >>> + >>> + pci_read_config_word(dev, exp_pos + PCI_EXP_FLAGS, &exp_caps); >>> + dev_data->dev_type = (((exp_caps & PCI_EXP_FLAGS_TYPE) >> 4) == >>> PCI_EXP_TYPE_PCI_BRIDGE) ? PCIBACK_TYPE_PCI_BRIDGE : >>> PCIBACK_TYPE_PCIe_BRIDGE; >>> + >>> +classify_done: >>> + >>> + return; >>> +} >>> + >>> extern wait_queue_head_t aer_wait_queue; >>> extern struct workqueue_struct *pciback_wq; >>> /* >>> @@ -132,3 +720,51 @@ irqreturn_t pciback_handle_event(int irq >>> >>> return IRQ_HANDLED; >>> } >>> + >>> +/* Helper routine used to parse command line parameters passed to the >>> + * pciback module from the boot loader. These params all have the form >>> + * of a list of one or more devices, e.g.: >>> + * (XXXX:XX:XX.X)(XXXX:XX:XX.X) >>> + * Which is: (domain/segment:bus:dev.func) >>> + */ >>> +int pciback_parse_device_params(const char *device_args, int type, >>> + int (*add_func) (int domain, int bus, int slot, int >>> func, int type)) >>> +{ >>> + int pos = 0; >>> + int err = 0; >>> + int domain, bus, slot, func; >>> + int parsed; >>> + >>> + if (device_args && *device_args) { >>> + do { >>> + parsed = 0; >>> + >>> + err = sscanf(device_args + pos, >>> + " (%x:%x:%x.%x) %n", >>> + &domain, &bus, &slot, &func, &parsed); >>> + if (err != 4) { >>> + domain = 0; >>> + err = sscanf(device_args + pos, >>> + " (%x:%x.%x) %n", >>> + &bus, &slot, &func, &parsed); >>> + if (err != 3) >>> + goto parse_error; >>> + } >>> + >>> + err = add_func(domain, bus, slot, func, type); >>> + if (err) >>> + goto out; >>> + >>> + /* if parsed<=0, we've reached the end of the >>> string */ >>> + pos += parsed; >>> + } while (parsed > 0 && device_args[pos]); >>> + } >>> + >>> +out: >>> + return err; >>> + >>> +parse_error: >>> + printk(KERN_ERR "pciback: Error parsing device parameters \"%s\" at >>> \"%s\"\n", >>> + device_args, device_args + pos); >>> + return -EINVAL; >>> +} >>> diff -rupN --ignore-blank-lines-X diffignore >>> a/linux-2.6.18-xen.hg/drivers/xen/pciback/pci_stub.c >>> b/linux-2.6.18-xen.hg/drivers/xen/pciback/pci_stub.c >>> --- a/linux-2.6.18-xen.hg/drivers/xen/pciback/pci_stub.c 2009-06-07 >>> 20:48:21.000000000 -0400 >>> +++ b/linux-2.6.18-xen.hg/drivers/xen/pciback/pci_stub.c 2009-06-07 >>> 19:04:11.000000000 -0400 >>> @@ -24,10 +24,28 @@ wait_queue_head_t aer_wait_queue; >>> * We want to avoid in middle of AER ops, pciback devices is being removed >>> */ >>> static DECLARE_RWSEM(pcistub_sem); >>> -module_param_named(hide, pci_devs_to_hide, charp, 0444); >>> +module_param_named(hide, pci_devs_to_hide, charp, S_IRUGO); >>> + >>> +static char *pci_devs_use_sbr = NULL; >>> +module_param_named(sbr, pci_devs_use_sbr, charp, S_IRUGO); >>> + >>> +static char *pci_devs_use_d3r = NULL; >>> +module_param_named(d3r, pci_devs_use_d3r, charp, S_IRUGO); >>> + >>> +static char *pci_devs_no_flr = NULL; >>> +module_param_named(noflr, pci_devs_no_flr, charp, S_IRUGO); >>> + >>> +/* Device id list holding different device type listings >>> + * for hiding devices and reset logic. >>> + */ >>> +#define PCIBACK_ID_TYPE_HIDE 1 >>> +#define PCIBACK_ID_TYPE_SBR 2 >>> +#define PCIBACK_ID_TYPE_D3R 3 >>> +#define PCIBACK_ID_TYPE_NOFLR 4 >>> >>> struct pcistub_device_id { >>> struct list_head slot_list; >>> + int type; >>> int domain; >>> unsigned char bus; >>> unsigned int devfn; >>> @@ -56,6 +74,8 @@ static LIST_HEAD(pcistub_devices); >>> static int initialize_devices = 0; >>> static LIST_HEAD(seized_devices); >>> >>> +static int disable_all_flr = 0; >>> + >>> static struct pcistub_device *pcistub_device_alloc(struct pci_dev *dev) >>> { >>> struct pcistub_device *psdev; >>> @@ -78,6 +98,23 @@ static struct pcistub_device *pcistub_de >>> return psdev; >>> } >>> >>> +static struct pciback_dev_data *pcistub_dev_data_alloc(struct pci_dev *dev) >>> +{ >>> + struct pciback_dev_data *dev_data; >>> + >>> + dev_dbg(&dev->dev, "pcistub_dev_data_alloc\n"); >>> + >>> + dev_data = kzalloc(sizeof(*dev_data) + dev->cfg_size, GFP_ATOMIC); >>> + if (!dev_data) >>> + return NULL; >>> + >>> + pci_set_drvdata(dev, dev_data); >>> + >>> + dev_data->cfg_space = (u8*)(dev_data) + sizeof(*dev_data); >>> + >>> + return dev_data; >>> +} >>> + >>> /* Don't call this directly as it's called by pcistub_device_put */ >>> static void pcistub_device_release(struct kref *kref) >>> { >>> @@ -200,7 +237,7 @@ struct pci_dev *pcistub_get_pci_dev(stru >>> return found_dev; >>> } >>> >>> -void pcistub_put_pci_dev(struct pci_dev *dev) >>> +void pcistub_put_pci_dev(struct pci_dev *dev, int do_flr) >>> { >>> struct pcistub_device *psdev, *found_psdev = NULL; >>> unsigned long flags; >>> @@ -220,6 +257,13 @@ void pcistub_put_pci_dev(struct pci_dev >>> * pcistub and pciback when AER is in processing >>> */ >>> down_write(&pcistub_sem); >>> + >>> + /* For pass-through devices, do an FLR (or approximate) for the >>> device >>> + * before it is put back and ready for the next domain >>> + */ >>> + if (!disable_all_flr && do_flr) >>> + pciback_flr_device(dev); >>> + >>> /* Cleanup our device >>> * (so it's ready for the next domain) >>> */ >>> @@ -235,6 +279,43 @@ void pcistub_put_pci_dev(struct pci_dev >>> up_write(&pcistub_sem); >>> } >>> >>> +struct pci_dev *pcistub_ref_pci_dev(struct pci_dev *dev) >>> +{ >>> + struct pcistub_device *psdev; >>> + struct pci_dev *found_dev = NULL; >>> + unsigned long flags; >>> + >>> + spin_lock_irqsave(&pcistub_devices_lock, flags); >>> + >>> + list_for_each_entry(psdev, &pcistub_devices, dev_list) { >>> + if (psdev->dev == dev) { >>> + pcistub_device_get(psdev); /* just a ref count */ >>> + found_dev = psdev->dev; >>> + break; >>> + } >>> + } >>> + >>> + spin_unlock_irqrestore(&pcistub_devices_lock, flags); >>> + return found_dev; >>> +} >>> + >>> +void pcistub_unref_pci_dev(struct pci_dev *dev) >>> +{ >>> + struct pcistub_device *psdev; >>> + unsigned long flags; >>> + >>> + spin_lock_irqsave(&pcistub_devices_lock, flags); >>> + >>> + list_for_each_entry(psdev, &pcistub_devices, dev_list) { >>> + if (psdev->dev == dev) { >>> + pcistub_device_get(psdev); /* just an unref count */ >>> + break; >>> + } >>> + } >>> + >>> + spin_unlock_irqrestore(&pcistub_devices_lock, flags); >>> +} >>> + >>> static int __devinit pcistub_match_one(struct pci_dev *dev, >>> struct pcistub_device_id *pdev_id) >>> { >>> @@ -255,7 +336,7 @@ static int __devinit pcistub_match_one(s >>> return 0; >>> } >>> >>> -static int __devinit pcistub_match(struct pci_dev *dev) >>> +static int __devinit pcistub_match(struct pci_dev *dev, int type) >>> { >>> struct pcistub_device_id *pdev_id; >>> unsigned long flags; >>> @@ -263,6 +344,8 @@ static int __devinit pcistub_match(struc >>> >>> spin_lock_irqsave(&device_ids_lock, flags); >>> list_for_each_entry(pdev_id, &pcistub_device_ids, slot_list) { >>> + if (pdev_id->type != type) >>> + continue; >>> if (pcistub_match_one(dev, pdev_id)) { >>> found = 1; >>> break; >>> @@ -285,12 +368,11 @@ static int __devinit pcistub_init_device >>> * would need to be called somewhere to free the memory allocated >>> * here and then to call kfree(pci_get_drvdata(psdev->dev)). >>> */ >>> - dev_data = kzalloc(sizeof(*dev_data), GFP_ATOMIC); >>> + dev_data = pcistub_dev_data_alloc(dev); >>> if (!dev_data) { >>> err = -ENOMEM; >>> goto out; >>> } >>> - pci_set_drvdata(dev, dev_data); >>> >>> dev_dbg(&dev->dev, "initializing config\n"); >>> >>> @@ -317,6 +399,22 @@ static int __devinit pcistub_init_device >>> dev_dbg(&dev->dev, "reset device\n"); >>> pciback_reset_device(dev); >>> >>> + /* Classify the device so we know if it is PCI/PCIe and if it is >>> + * a bridge - this information is used for FLR logic. Also store >>> + * values if SBR/D3R reset logic was requested. >>> + */ >>> + pciback_classify_device(dev); >>> + dev_data->no_flr = pcistub_match(dev, PCIBACK_ID_TYPE_NOFLR); >>> + if (!dev_data->no_flr) { >>> + dev_data->use_sbr = pcistub_match(dev, PCIBACK_ID_TYPE_SBR); >>> + dev_data->use_d3r = pcistub_match(dev, PCIBACK_ID_TYPE_D3R); >>> + } >>> + >>> + /* Store the config space here where the device is off and ready to >>> be >>> + * exported before any FLRs or other resets are done >>> + */ >>> + pciback_store_config_space(dev); >>> + >>> return 0; >>> >>> config_release: >>> @@ -414,7 +512,7 @@ static int __devinit pcistub_probe(struc >>> >>> dev_dbg(&dev->dev, "probing...\n"); >>> >>> - if (pcistub_match(dev)) { >>> + if (pcistub_match(dev, PCIBACK_ID_TYPE_HIDE)) { >>> >>> if (dev->hdr_type != PCI_HEADER_TYPE_NORMAL >>> && dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) { >>> @@ -851,7 +949,7 @@ static inline int str_to_quirk(const cha >>> return -EINVAL; >>> } >>> >>> -static int pcistub_device_id_add(int domain, int bus, int slot, int func) >>> +static int pcistub_device_id_add(int domain, int bus, int slot, int func, >>> int type) >>> { >>> struct pcistub_device_id *pci_dev_id; >>> unsigned long flags; >>> @@ -860,12 +958,13 @@ static int pcistub_device_id_add(int dom >>> if (!pci_dev_id) >>> return -ENOMEM; >>> >>> + pci_dev_id->type = type; >>> pci_dev_id->domain = domain; >>> pci_dev_id->bus = bus; >>> pci_dev_id->devfn = PCI_DEVFN(slot, func); >>> >>> - pr_debug("pciback: wants to seize %04x:%02x:%02x.%01x\n", >>> - domain, bus, slot, func); >>> + pr_debug("pciback: adding device ID type: %d for >>> %04x:%02x:%02x.%01x\n", >>> + type, domain, bus, slot, func); >>> >>> spin_lock_irqsave(&device_ids_lock, flags); >>> list_add_tail(&pci_dev_id->slot_list, &pcistub_device_ids); >>> @@ -874,7 +973,7 @@ static int pcistub_device_id_add(int dom >>> return 0; >>> } >>> >>> -static int pcistub_device_id_remove(int domain, int bus, int slot, int >>> func) >>> +static int pcistub_device_id_remove(int domain, int bus, int slot, int >>> func, int type) >>> { >>> struct pcistub_device_id *pci_dev_id, *t; >>> int devfn = PCI_DEVFN(slot, func); >>> @@ -884,7 +983,7 @@ static int pcistub_device_id_remove(int >>> spin_lock_irqsave(&device_ids_lock, flags); >>> list_for_each_entry_safe(pci_dev_id, t, &pcistub_device_ids, >>> slot_list) { >>> >>> - if (pci_dev_id->domain == domain >>> + if (pci_dev_id->type == type && pci_dev_id->domain == domain >>> && pci_dev_id->bus == bus && pci_dev_id->devfn == devfn) >>> { >>> /* Don't break; here because it's possible the same >>> * slot could be in the list more than once >>> @@ -939,6 +1038,32 @@ static int pcistub_reg_add(int domain, i >>> return err; >>> } >>> >>> +static int pcistub_device_do_flr(int domain, int bus, int slot, int func) >>> +{ >>> + int err = 0; >>> + struct pcistub_device *psdev; >>> + struct pci_dev *dev; >>> + >>> + psdev = pcistub_device_find(domain, bus, slot, func); >>> + if (!psdev || !psdev->dev) { >>> + err = -ENODEV; >>> + goto out; >>> + } >>> + dev = psdev->dev; >>> + >>> + /* Do an FLR (or approximate) for the device on demand and >>> + * reload config >>> + */ >>> + if (!disable_all_flr) { >>> + pciback_flr_device(dev); >>> + } >>> + else >>> + dev_dbg(&dev->dev, "FLR disabled for all devices\n"); >>> + >>> +out: >>> + return err; >>> +} >>> + >>> static ssize_t pcistub_slot_add(struct device_driver *drv, const char *buf, >>> size_t count) >>> { >>> @@ -949,7 +1074,7 @@ static ssize_t pcistub_slot_add(struct d >>> if (err) >>> goto out; >>> >>> - err = pcistub_device_id_add(domain, bus, slot, func); >>> + err = pcistub_device_id_add(domain, bus, slot, func, >>> PCIBACK_ID_TYPE_HIDE); >>> >>> out: >>> if (!err) >>> @@ -969,7 +1094,7 @@ static ssize_t pcistub_slot_remove(struc >>> if (err) >>> goto out; >>> >>> - err = pcistub_device_id_remove(domain, bus, slot, func); >>> + err = pcistub_device_id_remove(domain, bus, slot, func, >>> PCIBACK_ID_TYPE_HIDE); >>> >>> out: >>> if (!err) >>> @@ -987,6 +1112,10 @@ static ssize_t pcistub_slot_show(struct >>> >>> spin_lock_irqsave(&device_ids_lock, flags); >>> list_for_each_entry(pci_dev_id, &pcistub_device_ids, slot_list) { >>> + /* only want devices set for hide, not reset entries */ >>> + if (pci_dev_id->type != PCIBACK_ID_TYPE_HIDE) >>> + continue; >>> + >>> if (count >= PAGE_SIZE) >>> break; >>> >>> @@ -1068,7 +1197,7 @@ static ssize_t pcistub_quirk_show(struct >>> >>> DRIVER_ATTR(quirks, S_IRUSR | S_IWUSR, pcistub_quirk_show, >>> pcistub_quirk_add); >>> >>> -static ssize_t permissive_add(struct device_driver *drv, const char *buf, >>> +static ssize_t pcistub_permissive_add(struct device_driver *drv, const >>> char *buf, >>> size_t count) >>> { >>> int domain, bus, slot, func; >>> @@ -1109,7 +1238,7 @@ static ssize_t permissive_add(struct dev >>> return err; >>> } >>> >>> -static ssize_t permissive_show(struct device_driver *drv, char *buf) >>> +static ssize_t pcistub_permissive_show(struct device_driver *drv, char >>> *buf) >>> { >>> struct pcistub_device *psdev; >>> struct pciback_dev_data *dev_data; >>> @@ -1132,7 +1261,68 @@ static ssize_t permissive_show(struct de >>> return count; >>> } >>> >>> -DRIVER_ATTR(permissive, S_IRUSR | S_IWUSR, permissive_show, >>> permissive_add); >>> +DRIVER_ATTR(permissive, S_IRUSR | S_IWUSR, pcistub_permissive_show, >>> pcistub_permissive_add); >>> + >>> +static ssize_t pcistub_do_flr(struct device_driver *drv, const char *buf, >>> + size_t count) >>> +{ >>> + int domain, bus, slot, func; >>> + int err; >>> + >>> + err = str_to_slot(buf, &domain, &bus, &slot, &func); >>> + if (err) >>> + goto out; >>> + >>> + err = pcistub_device_do_flr(domain, bus, slot, func); >>> + >>> +out: >>> + if (!err) >>> + err = count; >>> + return err; >>> +} >>> + >>> +DRIVER_ATTR(do_flr, S_IWUSR, NULL, pcistub_do_flr); >>> + >>> +static ssize_t pcistub_resets(struct device_driver *drv, const char *buf, >>> + size_t count) >>> +{ >>> + int domain, bus, slot, func; >>> + int type, err = 0; >>> + >>> + /* string begins with reset type specifier sbr=|dr3=|noflr= */ >>> + if (!strncmp(buf, "sbr=", 4)) { >>> + type = PCIBACK_ID_TYPE_SBR; >>> + buf += 4; >>> + } else if (!strncmp(buf, "d3r=", 4)) { >>> + type = PCIBACK_ID_TYPE_D3R; >>> + buf += 4; >>> + } else if (!strncmp(buf, "noflr=", 6)) { >>> + type = PCIBACK_ID_TYPE_NOFLR; >>> + buf += 6; >>> + } else { >>> + err = -EINVAL; >>> + goto out; >>> + } >>> + >>> + /* check special wildcard noflr */ >>> + if (type == PCIBACK_ID_TYPE_NOFLR && !strncmp(buf, "(*)", 3)) { >>> + disable_all_flr = 1; >>> + goto out; >>> + } >>> + >>> + err = str_to_slot(buf, &domain, &bus, &slot, &func); >>> + if (err) >>> + goto out; >>> + >>> + err = pcistub_device_id_add(domain, bus, slot, func, type); >>> + >>> +out: >>> + if (!err) >>> + err = count; >>> + return err; >>> +} >>> + >>> +DRIVER_ATTR(resets, S_IWUSR, NULL, pcistub_resets); >>> >>> #ifdef CONFIG_PCI_MSI >>> >>> @@ -1158,6 +1348,8 @@ static void pcistub_exit(void) >>> driver_remove_file(&pciback_pci_driver.driver, &driver_attr_slots); >>> driver_remove_file(&pciback_pci_driver.driver, &driver_attr_quirks); >>> driver_remove_file(&pciback_pci_driver.driver, >>> &driver_attr_permissive); >>> + driver_remove_file(&pciback_pci_driver.driver, &driver_attr_do_flr); >>> + driver_remove_file(&pciback_pci_driver.driver, &driver_attr_resets); >>> >>> pci_unregister_driver(&pciback_pci_driver); >>> WARN_ON(unregister_msi_get_owner(pciback_get_owner)); >>> @@ -1165,35 +1357,27 @@ static void pcistub_exit(void) >>> >>> static int __init pcistub_init(void) >>> { >>> - int pos = 0; >>> int err = 0; >>> - int domain, bus, slot, func; >>> - int parsed; >>> >>> - if (pci_devs_to_hide && *pci_devs_to_hide) { >>> - do { >>> - parsed = 0; >>> - >>> - err = sscanf(pci_devs_to_hide + pos, >>> - " (%x:%x:%x.%x) %n", >>> - &domain, &bus, &slot, &func, &parsed); >>> - if (err != 4) { >>> - domain = 0; >>> - err = sscanf(pci_devs_to_hide + pos, >>> - " (%x:%x.%x) %n", >>> - &bus, &slot, &func, &parsed); >>> - if (err != 3) >>> - goto parse_error; >>> - } >>> + /* Parse device lists for hide, sbr, and d3r */ >>> + err = pciback_parse_device_params(pci_devs_to_hide, >>> PCIBACK_ID_TYPE_HIDE, pcistub_device_id_add); >>> + if (err) >>> + goto out; >>> >>> - err = pcistub_device_id_add(domain, bus, slot, >>> func); >>> - if (err) >>> - goto out; >>> + err = pciback_parse_device_params(pci_devs_use_sbr, >>> PCIBACK_ID_TYPE_SBR, pcistub_device_id_add); >>> + if (err) >>> + goto out; >>> >>> - /* if parsed<=0, we've reached the end of the >>> string */ >>> - pos += parsed; >>> - } while (parsed > 0 && pci_devs_to_hide[pos]); >>> - } >>> + err = pciback_parse_device_params(pci_devs_use_d3r, >>> PCIBACK_ID_TYPE_D3R, pcistub_device_id_add); >>> + if (err) >>> + goto out; >>> + >>> + if (pci_devs_no_flr && *pci_devs_no_flr && >>> !strncmp(pci_devs_no_flr, "(*)", 3)) >>> + disable_all_flr = 1; /* check special wildcard noflr */ >>> + else >>> + err = pciback_parse_device_params(pci_devs_no_flr, >>> PCIBACK_ID_TYPE_NOFLR, pcistub_device_id_add); >>> + if (err) >>> + goto out; >>> >>> /* If we're the first PCI Device Driver to register, we're the >>> * first one to get offered PCI devices as they become >>> @@ -1217,6 +1401,12 @@ static int __init pcistub_init(void) >>> if (!err) >>> err = driver_create_file(&pciback_pci_driver.driver, >>> &driver_attr_permissive); >>> + if (!err) >>> + err = driver_create_file(&pciback_pci_driver.driver, >>> + &driver_attr_do_flr); >>> + if (!err) >>> + err = driver_create_file(&pciback_pci_driver.driver, >>> + &driver_attr_resets); >>> >>> if (!err) >>> err = register_msi_get_owner(pciback_get_owner); >>> @@ -1225,11 +1415,6 @@ static int __init pcistub_init(void) >>> >>> out: >>> return err; >>> - >>> - parse_error: >>> - printk(KERN_ERR "pciback: Error parsing pci_devs_to_hide at >>> \"%s\"\n", >>> - pci_devs_to_hide + pos); >>> - return -EINVAL; >>> } >>> >>> #ifndef MODULE >>> diff -rupN --ignore-blank-lines-X diffignore >>> a/linux-2.6.18-xen.hg/drivers/xen/pciback/slot.c >>> b/linux-2.6.18-xen.hg/drivers/xen/pciback/slot.c >>> --- a/linux-2.6.18-xen.hg/drivers/xen/pciback/slot.c 2009-06-07 >>> 20:48:21.000000000 -0400 >>> +++ b/linux-2.6.18-xen.hg/drivers/xen/pciback/slot.c 2009-06-07 >>> 19:04:11.000000000 -0400 >>> @@ -109,7 +109,7 @@ void pciback_release_pci_dev(struct pcib >>> spin_unlock_irqrestore(&slot_dev->lock, flags); >>> >>> if (found_dev) >>> - pcistub_put_pci_dev(found_dev); >>> + pcistub_put_pci_dev(found_dev, 0); >>> } >>> >>> int pciback_init_devices(struct pciback_device *pdev) >>> @@ -149,7 +149,7 @@ void pciback_release_devices(struct pcib >>> for (slot = 0; slot < PCI_SLOT_MAX; slot++) { >>> dev = slot_dev->slots[bus][slot]; >>> if (dev != NULL) >>> - pcistub_put_pci_dev(dev); >>> + pcistub_put_pci_dev(dev, 0); >>> } >>> >>> kfree(slot_dev); >>> diff -rupN --ignore-blank-lines-X diffignore >>> a/linux-2.6.18-xen.hg/drivers/xen/pciback/vpci.c >>> b/linux-2.6.18-xen.hg/drivers/xen/pciback/vpci.c >>> --- a/linux-2.6.18-xen.hg/drivers/xen/pciback/vpci.c 2009-06-07 >>> 20:48:21.000000000 -0400 >>> +++ b/linux-2.6.18-xen.hg/drivers/xen/pciback/vpci.c 2009-06-07 >>> 19:04:11.000000000 -0400 >>> @@ -162,7 +162,7 @@ void pciback_release_pci_dev(struct pcib >>> spin_unlock_irqrestore(&vpci_dev->lock, flags); >>> >>> if (found_dev) >>> - pcistub_put_pci_dev(found_dev); >>> + pcistub_put_pci_dev(found_dev, 0); >>> } >>> >>> int pciback_init_devices(struct pciback_device *pdev) >>> @@ -202,7 +202,7 @@ void pciback_release_devices(struct pcib >>> list_for_each_entry_safe(e, tmp, &vpci_dev->dev_list[slot], >>> list) { >>> list_del(&e->list); >>> - pcistub_put_pci_dev(e->dev); >>> + pcistub_put_pci_dev(e->dev, 0); >>> kfree(e); >>> } >>> } >>> diff -rupN --ignore-blank-lines-X diffignore >>> a/linux-2.6.18-xen.hg/include/linux/pci_ids.h >>> b/linux-2.6.18-xen.hg/include/linux/pci_ids.h >>> --- a/linux-2.6.18-xen.hg/include/linux/pci_ids.h 2009-06-07 >>> 20:48:23.000000000 -0400 >>> +++ b/linux-2.6.18-xen.hg/include/linux/pci_ids.h 2009-06-07 >>> 19:04:11.000000000 -0400 >>> @@ -2259,6 +2259,14 @@ >>> #define PCI_DEVICE_ID_INTEL_IXP2800 0x9004 >>> #define PCI_DEVICE_ID_INTEL_S21152BB 0xb152 >>> >>> +#define PCI_DEVICE_ID_INTEL_GMCHQ45 0x2e10 >>> +#define PCI_DEVICE_ID_INTEL_GMCHG45 0x2e20 >>> +#define PCI_DEVICE_ID_INTEL_MCHP45 0x2e20 >>> +#define PCI_DEVICE_ID_INTEL_GMCHG41 0x2e30 >>> +#define PCI_DEVICE_ID_INTEL_GMCHGM45 0x2a40 >>> + >>> +#define PCI_DEVICE_ID_INTEL_GMCHG41 0x2e30 >>> + >>> #define PCI_VENDOR_ID_SCALEMP 0x8686 >>> #define PCI_DEVICE_ID_SCALEMP_VSMP_CTL 0x1010 >>> >>> diff -rupN --ignore-blank-lines-X diffignore >>> a/linux-2.6.18-xen.hg/include/linux/pci_regs.h >>> b/linux-2.6.18-xen.hg/include/linux/pci_regs.h >>> --- a/linux-2.6.18-xen.hg/include/linux/pci_regs.h 2009-06-07 >>> 20:48:23.000000000 -0400 >>> +++ b/linux-2.6.18-xen.hg/include/linux/pci_regs.h 2009-06-07 >>> 19:04:11.000000000 -0400 >>> @@ -201,6 +201,7 @@ >>> #define PCI_CAP_ID_SHPC 0x0C /* PCI Standard Hot-Plug Controller >>> */ >>> #define PCI_CAP_ID_EXP 0x10 /* PCI Express */ >>> #define PCI_CAP_ID_MSIX 0x11 /* MSI-X */ >>> +#define PCI_CAP_ID_AF 0x13 /* Advanced Features Capability */ >>> #define PCI_CAP_LIST_NEXT 1 /* Next capability in the list */ >>> #define PCI_CAP_FLAGS 2 /* Capability defined flags (16 >>> bits) */ >>> #define PCI_CAP_SIZEOF 4 >>> @@ -229,6 +230,11 @@ >>> #define PCI_PM_CTRL_DATA_SEL_MASK 0x1e00 /* Data select (??) */ >>> #define PCI_PM_CTRL_DATA_SCALE_MASK 0x6000 /* Data scale (??) */ >>> #define PCI_PM_CTRL_PME_STATUS 0x8000 /* PME pin status */ >>> +#define PCI_PM_CTRL_DATA_DSTATE_MASK 0x3 /* D0 - D3 */ >>> +#define PCI_PM_CTRL_D0 0x0 >>> +#define PCI_PM_CTRL_D1 0x1 >>> +#define PCI_PM_CTRL_D2 0x2 >>> +#define PCI_PM_CTRL_D3HOT 0x3 >>> #define PCI_PM_PPB_EXTENSIONS 6 /* PPB support extensions (??) */ >>> #define PCI_PM_PPB_B2_B3 0x40 /* Stop clock when in D3hot (??) */ >>> #define PCI_PM_BPCC_ENABLE 0x80 /* Bus power/clock control enable >>> (??) */ >>> @@ -346,6 +352,7 @@ >>> #define PCI_EXP_DEVCAP_PWR_IND 0x4000 /* Power Indicator Present >>> */ >>> #define PCI_EXP_DEVCAP_PWR_VAL 0x3fc0000 /* Slot Power Limit Value >>> */ >>> #define PCI_EXP_DEVCAP_PWR_SCL 0xc000000 /* Slot Power Limit Scale >>> */ >>> +#define PCI_EXP_DEVCAP_FLR 0x10000000 /* Function Level Reset */ >>> #define PCI_EXP_DEVCTL 8 /* Device Control */ >>> #define PCI_EXP_DEVCTL_CERE 0x0001 /* Correctable Error Reporting En. >>> */ >>> #define PCI_EXP_DEVCTL_NFERE 0x0002 /* Non-Fatal Error Reporting Enable >>> */ >>> @@ -358,6 +365,7 @@ >>> #define PCI_EXP_DEVCTL_AUX_PME 0x0400 /* Auxiliary Power PM >>> Enable */ >>> #define PCI_EXP_DEVCTL_NOSNOOP_EN 0x0800 /* Enable No Snoop */ >>> #define PCI_EXP_DEVCTL_READRQ 0x7000 /* Max_Read_Request_Size */ >>> +#define PCI_EXP_DEVCTL_BCR_FLR 0x8000 /* Bridge Configuration Retry / >>> FLR */ >>> #define PCI_EXP_DEVSTA 10 /* Device Status */ >>> #define PCI_EXP_DEVSTA_CED 0x01 /* Correctable Error Detected */ >>> #define PCI_EXP_DEVSTA_NFED 0x02 /* Non-Fatal Error Detected */ >>> @@ -482,6 +490,17 @@ >>> #define PCI_ARI_CTRL_ACS 0x0002 /* ACS Function Groups Enable */ >>> #define PCI_ARI_CTRL_FG(x) (((x) >> 4) & 7) /* Function Group */ >>> >>> +/* Advanced Features Capability */ >>> +#define PCI_AF_LENFLD 0x02 /* Device length offset */ >>> +#define PCI_AF_LENGTH 0x06 >>> +#define PCI_AF_DEVCAP 0x03 /* Device capabilities offset */ >>> +#define PCI_AF_CAP_TP 0x01 >>> +#define PCI_AF_CAP_FLR 0x02 >>> +#define PCI_AF_CTRL 0x04 /* Device CTRL offset */ >>> +#define PCI_AF_CTRL_FLR 0x01 >>> +#define PCI_AF_STA 0x05 /* Device STATUS offset */ >>> +#define PCI_AF_STA_TP 0x01 >>> + >>> /* Single Root I/O Virtualization */ >>> #define PCI_SRIOV_CAP 0x04 /* SR-IOV Capabilities */ >>> #define PCI_SRIOV_CAP_VFM 0x01 /* VF Migration Capable */ >>> diff -rupN --ignore-blank-lines-X diffignore >>> a/tools/firmware/hvmloader/hvmloader.c >>> b/tools/firmware/hvmloader/hvmloader.c >>> --- a/tools/firmware/hvmloader/hvmloader.c 2009-06-07 >>> 20:44:47.000000000 -0400 >>> +++ b/tools/firmware/hvmloader/hvmloader.c 2009-06-07 >>> 19:04:11.000000000 -0400 >>> @@ -673,6 +673,7 @@ int main(void) >>> break; >>> default: >>> printf("No emulated VGA adaptor ...\n"); >>> + vgabios_sz = round_option_rom((*(uint8_t >>> *)(VGABIOS_PHYSICAL_ADDRESS+2)) * 512); >>> break; >>> } >>> >>> diff -rupN --ignore-blank-lines-X diffignore a/tools/ioemu-remote/console.h >>> b/tools/ioemu-remote/console.h >>> --- a/tools/ioemu-remote/console.h 2009-06-07 21:14:47.000000000 -0400 >>> +++ b/tools/ioemu-remote/console.h 2009-06-07 19:04:11.000000000 -0400 >>> @@ -290,6 +290,9 @@ void vga_hw_update(void); >>> void vga_hw_invalidate(void); >>> void vga_hw_screen_dump(const char *filename); >>> >>> +void unset_vga_acc(void); >>> +void set_vga_acc(void); >>> + >>> int is_graphic_console(void); >>> int is_fixedsize_console(void); >>> CharDriverState *text_console_init(const char *p); >>> @@ -341,4 +344,9 @@ const char *readline_get_history(unsigne >>> void readline_start(const char *prompt, int is_password, >>> ReadLineFunc *readline_func, void *opaque); >>> >>> +/* intel.c */ >>> +int intel_enter(void); >>> +int intel_leave(void); >>> +void intel_display_init(DisplayState *ds); >>> + >>> #endif >>> diff -rupN --ignore-blank-lines-X diffignore >>> a/tools/ioemu-remote/hw/pass-through.c >>> b/tools/ioemu-remote/hw/pass-through.c >>> --- a/tools/ioemu-remote/hw/pass-through.c 2009-06-07 >>> 21:14:48.000000000 -0400 >>> +++ b/tools/ioemu-remote/hw/pass-through.c 2009-06-07 >>> 19:04:11.000000000 -0400 >>> @@ -90,6 +90,8 @@ >>> #include "qemu-xen.h" >>> #include <unistd.h> >>> >>> +extern int vga_passthrough; >>> + >>> struct php_dev { >>> struct pt_dev *pt_dev; >>> uint8_t valid; >>> @@ -1573,10 +1575,11 @@ static int pt_dev_is_virtfn(struct pci_d >>> >>> static int pt_register_regions(struct pt_dev *assigned_device) >>> { >>> - int i = 0; >>> + int i = 0, ret = 0; >>> uint32_t bar_data = 0; >>> struct pci_dev *pci_dev = assigned_device->pci_dev; >>> PCIDevice *d = &assigned_device->dev; >>> + uint16_t class, vendor_id; >>> >>> /* Register PIO/MMIO BARs */ >>> for ( i = 0; i < PCI_BAR_ENTRIES; i++ ) >>> @@ -1632,6 +1635,25 @@ static int pt_register_regions(struct pt >>> (uint32_t)(pci_dev->rom_size), >>> (uint32_t)(pci_dev->rom_base_addr)); >>> } >>> >>> + /* Map legacy ioport and iomem, for specific devices */ >>> + vendor_id = pci_read_word(pci_dev, 0x00); >>> + class = pci_read_word(pci_dev, 0x0a); >>> + >>> + PT_LOG("Real device vendor_id=0x%x class=0x%x\n", vendor_id, class); >>> + if ( vga_passthrough && class == 0x0300 ) >>> + { >>> + PT_LOG("add an intel graphic card\n"); >>> + >>> + ret = xc_domain_ioport_mapping(xc_handle, domid, 0x3B0, 0x3B0, >>> 0xb, DPCI_ADD_MAPPING); >>> + ret = xc_domain_ioport_mapping(xc_handle, domid, 0x3C0, 0x3C0, 32, >>> DPCI_ADD_MAPPING); >>> + ret |= xc_domain_memory_mapping(xc_handle, domid, 0xa0, 0xa0, 32, >>> DPCI_ADD_MAPPING); >>> + if ( ret != 0 ) >>> + { >>> + PT_LOG("legacy mapping failed!\n"); >>> + return ret; >>> + } >>> + } >>> + >>> return 0; >>> } >>> >>> @@ -1640,6 +1662,7 @@ static void pt_unregister_regions(struct >>> int i, type, ret; >>> uint32_t e_size; >>> PCIDevice *d = (PCIDevice*)assigned_device; >>> + uint16_t class, vendor_id; >>> >>> for ( i = 0; i < PCI_NUM_REGIONS; i++ ) >>> { >>> @@ -1681,6 +1704,24 @@ static void pt_unregister_regions(struct >>> >>> } >>> >>> + /* unmap legacy ioport and iomem, for specific devices */ >>> + vendor_id = pci_read_word(assigned_device->pci_dev, 0x00); >>> + class = pci_read_word(assigned_device->pci_dev, 0x0a); >>> + >>> + PT_LOG("Real device vendor_id=0x%x class=0x%x\n", vendor_id, class); >>> + if ( vga_passthrough && class == 0x0300 ) >>> + { >>> + PT_LOG("remove an intel graphic card\n"); >>> + >>> + ret = xc_domain_ioport_mapping(xc_handle, domid, 0x3B0, 0x3B0, >>> 0xb, DPCI_REMOVE_MAPPING); >>> + ret = xc_domain_ioport_mapping(xc_handle, domid, 0x3C0, 0x3C0, 32, >>> DPCI_REMOVE_MAPPING); >>> + ret |= xc_domain_memory_mapping(xc_handle, domid, 0xa0, 0xa0, 32, >>> DPCI_REMOVE_MAPPING); >>> + if ( ret != 0 ) >>> + { >>> + PT_LOG("legacy unmapping failed !\n"); >>> + } >>> + } >>> + >>> } >>> >>> static uint8_t find_cap_offset(struct pci_dev *pci_dev, uint8_t cap) >>> @@ -3759,7 +3800,7 @@ static struct pt_dev * register_real_dev >>> struct pci_config_cf8 machine_bdf; >>> char *key, *val; >>> int msi_translate, power_mgmt; >>> - >>> + >>> PT_LOG("Assigning real physical device %02x:%02x.%x ...\n", >>> r_bus, r_dev, r_func); >>> >>> @@ -3931,7 +3972,7 @@ static struct pt_dev * register_real_dev >>> } >>> >>> out: >>> - PT_LOG("Real physical device %02x:%02x.%x registered successfuly!\n" >>> + PT_LOG("Real physical device %02x:%02x.%x registered successfully!\n" >>> "IRQ type = %s\n", r_bus, r_dev, r_func, >>> assigned_device->msi_trans_en? "MSI-INTx":"INTx"); >>> >>> @@ -4113,3 +4154,47 @@ err: >>> return status; >>> } >>> >>> +u8 pt_pci_host_read_byte(int bus, int dev, int fn, u32 addr) >>> +{ >>> + struct pci_dev *pci_dev; >>> + u8 val; >>> + >>> + pci_dev = pci_get_dev(dpci_infos.pci_access, 0, bus, dev, fn); >>> + if (!pci_dev) >>> + return 0; >>> + >>> + val = pci_read_byte(pci_dev, addr); >>> + pci_free_dev(pci_dev); >>> + >>> + return val; >>> +} >>> + >>> +u16 pt_pci_host_read_word(int bus, int dev, int fn, u32 addr) >>> +{ >>> + struct pci_dev *pci_dev; >>> + u16 val; >>> + >>> + pci_dev = pci_get_dev(dpci_infos.pci_access, 0, bus, dev, fn); >>> + if (!pci_dev) >>> + return 0; >>> + >>> + val = pci_read_word(pci_dev, addr); >>> + pci_free_dev(pci_dev); >>> + >>> + return val; >>> +} >>> + >>> +u32 pt_pci_host_read_long(int bus, int dev, int fn, u32 addr) >>> +{ >>> + struct pci_dev *pci_dev; >>> + u32 val; >>> + >>> + pci_dev = pci_get_dev(dpci_infos.pci_access, 0, bus, dev, fn); >>> + if (!pci_dev) >>> + return 0; >>> + >>> + val = pci_read_long(pci_dev, addr); >>> + pci_free_dev(pci_dev); >>> + >>> + return val; >>> +} >>> diff -rupN --ignore-blank-lines-X diffignore a/tools/ioemu-remote/hw/pc.c >>> b/tools/ioemu-remote/hw/pc.c >>> --- a/tools/ioemu-remote/hw/pc.c 2009-06-07 21:14:47.000000000 -0400 >>> +++ b/tools/ioemu-remote/hw/pc.c 2009-06-07 19:04:11.000000000 -0400 >>> @@ -65,6 +65,8 @@ void tpm_tis_init(SetIRQFunc *set_irq, v >>> extern uint8_t *acpi_tables; >>> extern size_t acpi_tables_len; >>> >>> +extern int vga_passthrough; >>> + >>> static fdctrl_t *floppy_controller; >>> static RTCState *rtc_state; >>> static PITState *pit; >>> @@ -984,6 +986,7 @@ vga_bios_error: >>> >>> register_ioport_write(0xf0, 1, 1, ioportF0_write, NULL); >>> >>> + if (!vga_passthrough) { >>> if (cirrus_vga_enabled) { >>> if (pci_enabled) { >>> pci_cirrus_vga_init(pci_bus, >>> @@ -1010,6 +1013,7 @@ vga_bios_error: >>> vga_ram_addr, vga_ram_size); >>> } >>> } >>> + } >>> >>> #ifdef CONFIG_PASSTHROUGH >>> /* Pass-through Initialization >>> diff -rupN --ignore-blank-lines-X diffignore a/tools/ioemu-remote/hw/pci.c >>> b/tools/ioemu-remote/hw/pci.c >>> --- a/tools/ioemu-remote/hw/pci.c 2009-06-07 21:14:47.000000000 -0400 >>> +++ b/tools/ioemu-remote/hw/pci.c 2009-06-07 19:04:11.000000000 -0400 >>> @@ -28,11 +28,14 @@ >>> #include "virtio-net.h" >>> #include "sysemu.h" >>> >>> +#include "pass-through.h" >>> #include "exec-all.h" >>> #include "qemu-xen.h" >>> >>> //#define DEBUG_PCI >>> >>> +extern int vga_passthrough; >>> + >>> struct PCIBus { >>> int bus_num; >>> int devfn_min; >>> @@ -611,7 +614,24 @@ uint32_t pci_data_read(void *opaque, uin >>> goto the_end; >>> } >>> config_addr = addr & 0xff; >>> - val = pci_dev->config_read(pci_dev, config_addr, len); >>> + if (vga_passthrough && pci_dev->devfn == 0x00) //Host Bridge >>> + { >>> + val = pci_dev->config_read(pci_dev, config_addr, len); >>> + >>> + if (config_addr == 0x52) // GMCH >>> + val = pt_pci_host_read_word(0, 0, 0, 0x52); >>> + if (config_addr == 0x02) // Device ID >>> + { >>> + if (len == 2) >>> + val = pt_pci_host_read_word(0, 0, 0, 0x00); >>> + else if (len == 4) >>> + val = pt_pci_host_read_long(0, 0, 0, 0x00); >>> + } >>> + } else if (vga_passthrough && pci_dev->devfn == 0x10 && // intel >>> graphic card >>> + config_addr == 0xfc) // OpRegion address >>> + val = 0; // force to fall back to SMI mode >>> + else >>> + val = pci_dev->config_read(pci_dev, config_addr, len); >>> #if defined(DEBUG_PCI) >>> printf("pci_config_read: %s: addr=%02x val=%08x len=%d\n", >>> pci_dev->name, config_addr, val, len); >>> diff -rupN --ignore-blank-lines-X diffignore a/tools/ioemu-remote/hw/vga.c >>> b/tools/ioemu-remote/hw/vga.c >>> --- a/tools/ioemu-remote/hw/vga.c 2009-06-07 21:14:47.000000000 -0400 >>> +++ b/tools/ioemu-remote/hw/vga.c 2009-06-07 19:04:11.000000000 -0400 >>> @@ -34,9 +34,9 @@ >>> >>> #include "qemu-timer.h" >>> >>> -//#define DEBUG_VGA >>> -//#define DEBUG_VGA_MEM >>> -//#define DEBUG_VGA_REG >>> +#define DEBUG_VGA >>> +#define DEBUG_VGA_MEM >>> +#define DEBUG_VGA_REG >>> >>> //#define DEBUG_BOCHS_VBE >>> >>> @@ -161,6 +161,18 @@ static uint8_t expand4to8[16]; >>> static void vga_bios_init(VGAState *s); >>> static void vga_screen_dump(void *opaque, const char *filename); >>> >>> +static VGAState *xen_vga_state; >>> + >>> +void set_vga_acc(void) >>> +{ >>> + set_vram_mapping(xen_vga_state, xen_vga_state->lfb_addr, >>> xen_vga_state->lfb_end); >>> +} >>> + >>> +void unset_vga_acc(void) >>> +{ >>> + unset_vram_mapping(xen_vga_state); >>> +} >>> + >>> static void vga_dumb_update_retrace_info(VGAState *s) >>> { >>> (void) s; >>> @@ -2473,8 +2485,6 @@ static void vga_bios_init(VGAState *s) >>> } >>> >>> >>> -static VGAState *xen_vga_state; >>> - >>> /* Allocate video memory in the GPFN space */ >>> void xen_vga_populate_vram(uint64_t vram_addr, uint32_t vga_ram_size) >>> { >>> diff -rupN --ignore-blank-lines-X diffignore a/tools/ioemu-remote/intel.c >>> b/tools/ioemu-remote/intel.c >>> --- a/tools/ioemu-remote/intel.c 1969-12-31 19:00:00.000000000 -0500 >>> +++ b/tools/ioemu-remote/intel.c 2009-06-07 19:04:11.000000000 -0400 >>> @@ -0,0 +1,494 @@ >>> +#include <stdio.h> >>> +#include <stdlib.h> >>> +#include <stdint.h> >>> +#include <sys/mman.h> >>> +#include <sys/types.h> >>> +#include <sys/stat.h> >>> +#include <fcntl.h> >>> +#include <assert.h> >>> +#include <signal.h> >>> +#include <pci/pci.h> >>> + >>> +#include "qemu-common.h" >>> +#include "console.h" >>> +#include "sysemu.h" >>> + >>> +#define INTEL_DEBUG(format, args...) \ >>> + fprintf (stderr, "intel.c:%d:%s " format , __LINE__, __func__, ## args) >>> + >>> +#define TileW 128 >>> +#define TileH 8 >>> + >>> +#define REG_DR_DSPASURF 0x7019C >>> +#define REG_DR_DSPACNTR 0x70180 >>> +#define REG_DR_DSPASTRIDE 0x70188 >>> +#define REG_DR_PIPEACONF 0x70008 >>> + >>> +#define REG_DR_DSPBSURF 0x7119C >>> +#define REG_DR_DSPBCNTR 0x71180 >>> +#define REG_DR_DSPBSTRIDE 0x71188 >>> +#define REG_DR_PIPEBCONF 0x71008 >>> + >>> +#define REG_DE_PIPEASRC 0x6001c >>> + >>> +extern int vga_passthrough; >>> +uint32_t guest_framebuffer; >>> + >>> +static int display = 0; >>> + >>> +static int mmio_fd = -1; >>> +static int mem_fd = -1; >>> +static uint8_t *intel_mem = NULL; >>> +static uint8_t *intel_mmio = NULL; >>> +static int intel_force_full_update = 0; >>> +static int intel_have_focus; >>> +static int IntelPitch = 16; >>> +static int IntelX = 1280; >>> +static int IntelY = 1024; >>> +static DisplayState *lds = NULL; >>> +static uint8_t *old_data = NULL; >>> +static uint32_t intel_fb_base, intel_mmio_base; >>> +static uint32_t map_s, map_d, map_size; >>> +static int refresh; >>> + >>> +static void set_data_mappings(void); >>> +static void unset_data_mappings(int mapping); >>> +static void set_data_pointer(void); >>> +static void intel_resize(DisplayState *ds); >>> + >>> +static inline unsigned int intel_get_reg(unsigned int reg) >>> +{ >>> + return *(unsigned int*)(intel_mmio + reg); >>> +} >>> + >>> +static inline int is_linear(void) >>> +{ >>> + unsigned int *dspacntr = (unsigned int *)(intel_mmio + >>> REG_DR_DSPACNTR); >>> + if (((*dspacntr) & (1 << 10)) == 0) >>> + return 1; >>> + else >>> + return 0; >>> +} >>> + >>> +static inline unsigned int intel_get_pitch(void) >>> +{ >>> + unsigned int *dspastride = (unsigned int *)(intel_mmio + >>> REG_DR_DSPASTRIDE); >>> + return *dspastride; >>> +} >>> + >>> +static inline unsigned int intel_get_offset(DisplaySurface *ds, int x, int >>> y) >>> +{ >>> + return (y * ds->width + x) * 4; >>> +} >>> + >>> +static void intel_update_linear(DisplaySurface *ds, int x, int y, int w, >>> int h) >>> +{ >>> + int i, bpp = ds->pf.depth / 8; >>> + unsigned char *s, *d; >>> + s = ds->data; >>> + d = (unsigned char *)(intel_mem + intel_get_reg(REG_DR_DSPASURF)); >>> + s += (ds->linesize * y) + bpp * x; >>> + d += (ds->linesize * y) + bpp * x; >>> + for (i = 0; i < h; i++) { >>> + memcpy(d, s, w * bpp); >>> + s += ds->linesize; >>> + d += ds->linesize; >>> + } >>> +} >>> + >>> +static void intel_force_linear(int linesize) >>> +{ >>> + unsigned int *dspacntr = (unsigned int *)(intel_mmio + >>> REG_DR_DSPACNTR); >>> + unsigned int *pipeaconf = (unsigned int *)(intel_mmio + >>> REG_DR_PIPEACONF); >>> + unsigned int *dspasurf = (unsigned int *)(intel_mmio + >>> REG_DR_DSPASURF); >>> + unsigned int *dspastride = (unsigned int *)(intel_mmio + >>> REG_DR_DSPASTRIDE); >>> + >>> + unsigned int *dspbcntr = (unsigned int *)(intel_mmio + >>> REG_DR_DSPBCNTR); >>> + unsigned int *pipebconf = (unsigned int *)(intel_mmio + >>> REG_DR_PIPEBCONF); >>> + unsigned int *dspbsurf = (unsigned int *)(intel_mmio + >>> REG_DR_DSPBSURF); >>> + unsigned int *dspbstride = (unsigned int *)(intel_mmio + >>> REG_DR_DSPBSTRIDE); >>> + >>> + unsigned int surfa = 0, surfb = 0, pipea = 0, pipeb = 0; >>> + char pipebenabled = !!(*pipebconf & (1 << 30)); >>> + >>> + >>> + INTEL_DEBUG("DSPASURF CTRL: 0x%x\n", intel_get_reg(REG_DR_DSPACNTR)); >>> + >>> + /* Disable surface */ >>> + pipea = *pipeaconf & (0x3 << 18); >>> + *pipeaconf &= ~(0x3 << 18); >>> + *dspacntr |= (1 << 31); >>> + /* Address of the surface to map to */ >>> + surfa = *dspasurf; >>> + *dspasurf = 0x00000000; >>> + *dspacntr &= ~(1 << 31); >>> + *dspasurf = 0x00000000; >>> + *pipeaconf |= pipea; >>> + >>> + if (pipebenabled) { >>> + INTEL_DEBUG("PIPEBCONF enabled.\n"); >>> + >>> + /* Disable surface */ >>> + pipeb = *pipebconf & (0x3 << 18); >>> + *pipebconf &= ~(0x3 << 18); >>> + *dspbcntr |= (1 << 31); >>> + /* Address of the surface to map to */ >>> + surfb = *dspbsurf; >>> + *dspbsurf = 0x00000000; >>> + *dspbcntr &= ~(1 << 31); >>> + *dspbsurf = 0x00000000; >>> + *pipebconf |= pipeb; >>> + } >>> + >>> + usleep(20000); >>> + >>> + *pipeaconf &= ~(0x3 << 18); >>> + /* Enable surface linear mode */ >>> + *dspacntr &= ~(1 << 10); >>> + if (linesize) *dspastride = linesize; >>> + *dspasurf = surfa; >>> + *dspacntr |= (1 << 31); >>> + *pipeaconf |= pipea; >>> + >>> + if (pipebenabled) { >>> + *pipebconf &= ~(0x3 << 18); >>> + /* Enable surface linear mode */ >>> + *dspbcntr &= ~(1 << 10); >>> + if (linesize) *dspbstride = linesize; >>> + *dspbsurf = surfb; >>> + *dspbcntr |= (1 << 31); >>> + *pipebconf |= pipeb; >>> + } >>> + >>> + usleep(20000); >>> +} >>> + >>> +static void intel_update(DisplayState *ds, int x, int y, int w, int h) >>> +{ >>> + if (intel_have_focus && !old_data && !map_size) >>> + intel_update_linear(ds->surface, x, y, w, h); >>> +} >>> + >>> +static void set_fb_mapping(void) >>> +{ >>> + DisplaySurface *surf = lds->surface; >>> + int rc; >>> + unsigned long nr_pfn; >>> + >>> + unset_vga_acc(); >>> + fprintf(stderr, "set_fb_mapping: %x %x\n", (intel_fb_base + >>> intel_get_reg(REG_DR_DSPASURF)), guest_framebuffer); >>> + nr_pfn = (surf->linesize * surf->height) >> TARGET_PAGE_BITS; >>> + >>> + rc = xc_domain_memory_mapping(xc_handle, >>> + domid, >>> + (guest_framebuffer >> TARGET_PAGE_BITS), >>> + ((intel_fb_base + intel_get_reg(REG_DR_DSPASURF)) >> >>> TARGET_PAGE_BITS), >>> + nr_pfn, >>> + DPCI_ADD_MAPPING); >>> + if (rc) { >>> + fprintf(stderr, "xc_domain_memory_mapping failed %d\n", rc); >>> + return; >>> + } >>> + map_s = ((intel_fb_base + intel_get_reg(REG_DR_DSPASURF)) >> >>> TARGET_PAGE_BITS); >>> + map_d = (guest_framebuffer >> TARGET_PAGE_BITS); >>> + map_size = nr_pfn; >>> +} >>> + >>> +static void unset_fb_mapping(void) >>> +{ >>> + int rc; >>> + >>> + fprintf(stderr, "unset_fb_mapping: %x %x\n", map_d, map_s); >>> + >>> + rc = xc_domain_memory_mapping(xc_handle, >>> + domid, >>> + map_d, >>> + map_s, >>> + map_size, >>> + DPCI_REMOVE_MAPPING); >>> + if (rc) { >>> + fprintf(stderr, "xc_domain_memory_mapping failed %d\n", rc); >>> + return; >>> + } >>> + >>> + set_vga_acc(); >>> + map_s = 0; >>> + map_d = 0; >>> + map_size = 0; >>> +} >>> + >>> +static void intel_setdata(DisplayState *ds) >>> +{ >>> + if (map_size) >>> + unset_fb_mapping(); >>> + set_fb_mapping(); >>> +} >>> + >>> +static void intel_resize_shared(DisplayState *ds, int w, int h, int depth, >>> int linesize, void *pixels) >>> +{ >>> + DisplaySurface *surf = ds->surface; >>> + >>> + if (!intel_have_focus) { >>> + surf->width = w; >>> + surf->height = h; >>> + intel_resize(ds); >>> + return; >>> + } >>> + if (depth == 32 && w == IntelX && h == IntelY) >>> + surf->flags = QEMU_ALLOCATED_FLAG; >>> + else >>> + surf->flags &= ~QEMU_ALLOCATED_FLAG; >>> + if (surf->flags & QEMU_ALLOCATED_FLAG) { >>> + surf->width = w; >>> + surf->height = h; >>> + surf->pf.depth = 32; >>> + surf->linesize = linesize; >>> + /* adjust linesize */ >>> + intel_force_linear(linesize); >>> + set_data_mappings(); >>> + if (refresh) { >>> + memcpy(surf->data, pixels, surf->linesize * surf->height); >>> + refresh = 0; >>> + } >>> + surf->data = pixels; >>> + intel_setdata(ds); >>> + } else { >>> + surf->width = w; >>> + surf->height = h; >>> + intel_resize(ds); >>> + } >>> +} >>> + >>> +static void intel_resize(DisplayState *ds) >>> +{ >>> + DisplaySurface *surf = ds->surface; >>> + int old_linesize = surf->linesize; >>> + >>> + if (surf->pf.depth == 32 && surf->width == IntelX && surf->height == >>> IntelY) >>> + surf->flags = QEMU_ALLOCATED_FLAG; >>> + else >>> + surf->flags &= ~QEMU_ALLOCATED_FLAG; >>> + >>> + if (is_buffer_shared(surf)) >>> + { >>> + INTEL_DEBUG("intel_resize_shared: enable shared buffer, linesize >>> %d\n", >>> + surf->linesize); >>> + intel_force_linear(surf->linesize); >>> + set_data_mappings(); >>> + if (refresh) >>> + { >>> + // Pixels doesn't exist anymore ?? >>> + //memcpy(surf->data, pixels, surf->linesize * surf->height); >>> + refresh = 0; >>> + } >>> + intel_setdata(ds); >>> + return; >>> + } >>> + >>> + INTEL_DEBUG("intel_resize: no shared buffer, linesize=%d\n", >>> surf->linesize); >>> + surf->linesize = intel_get_pitch(); >>> + if (map_size) { >>> + unset_fb_mapping(); >>> + unset_data_mappings(1); >>> + } >>> + if (intel_have_focus && !is_linear()) { >>> + intel_force_linear(0); >>> + } >>> + surf->flags &= ~QEMU_ALLOCATED_FLAG; >>> + if (intel_have_focus && !old_data && >>> + surf->width * surf->height <= IntelX * IntelY) >>> + set_data_mappings(); >>> + else if (intel_have_focus && old_data && >>> + surf->width * surf->height > IntelX * IntelY) >>> + unset_data_mappings(0); >>> + if (!old_data) { >>> + qemu_free(surf->data); >>> + surf->data = qemu_mallocz(surf->height * surf->linesize); >>> + } else { >>> + INTEL_DEBUG("intel_resize: set_data_pointer\n"); >>> + set_data_pointer(); >>> + } >>> + if (intel_have_focus) >>> + memset((unsigned char *)(intel_mem + >>> intel_get_reg(REG_DR_DSPASURF)), 0x0, IntelX * IntelY); >>> + if (refresh) { >>> + if (old_data) { >>> + unsigned char *s, *d; >>> + int i; >>> + s = old_data; >>> + d = surf->data; >>> + for (i = 0; i < surf->height; i++) { >>> + memcpy(d, s, surf->width * 4); >>> + s += old_linesize; >>> + d += surf->linesize; >>> + } >>> + } >>> + refresh = 0; >>> + } >>> +} >>> + >>> +static void intel_refresh(DisplayState *ds) >>> +{ >>> + vga_hw_update(); >>> +} >>> + >>> +static void intel_init_mapping(void) >>> +{ >>> + struct pci_access *pci_bus; >>> + struct pci_dev *pci_dev; >>> + >>> + mmio_fd = open("/dev/mem", O_RDWR); >>> + if (mmio_fd == -1) >>> + { >>> + perror("open"); >>> + exit(1); >>> + } >>> + mem_fd = open("/dev/mem", O_RDWR); >>> + if (mem_fd == -1) >>> + { >>> + perror("open"); >>> + exit(1); >>> + } >>> + >>> + pci_bus = pci_alloc(); >>> + pci_init(pci_bus); >>> + pci_dev = pci_get_dev(pci_bus, 0, 0, 2, 0); >>> + pci_fill_info(pci_dev, PCI_FILL_BASES); >>> + intel_fb_base = pci_dev->base_addr[2] & 0xfffff000; >>> + intel_mmio_base = pci_dev->base_addr[0] & 0xfffff000; >>> + pci_free_dev(pci_dev); >>> + pci_cleanup(pci_bus); >>> + >>> + INTEL_DEBUG("Map intel main mem 0x%x\n", intel_fb_base); >>> + intel_mem = mmap(NULL, 0x10000000, PROT_READ | PROT_WRITE, MAP_SHARED, >>> + mem_fd, intel_fb_base); >>> + if (intel_mem == MAP_FAILED) >>> + { >>> + perror("mmap"); >>> + exit(1); >>> + } >>> + >>> + INTEL_DEBUG("Map intel mmio 0x%x\n", intel_mmio_base); >>> + intel_mmio = mmap(NULL, 4 * 1024 * 1024, PROT_READ | PROT_WRITE, >>> MAP_SHARED, >>> + mmio_fd, intel_mmio_base); >>> + if (intel_mem == MAP_FAILED) >>> + { >>> + perror("mmap"); >>> + exit(1); >>> + } >>> +} >>> + >>> +static void set_data_pointer(void) >>> +{ >>> + DisplaySurface *surf = lds->surface; >>> + >>> + surf->data = (unsigned char *)(intel_mem + >>> intel_get_reg(REG_DR_DSPASURF)); >>> + surf->data = surf->data + >>> + surf->linesize * ((IntelY - surf->height) / 2) + >>> + 4 * ((IntelX - surf->width) / 2); >>> +} >>> + >>> +static void set_data_mappings(void) >>> +{ >>> + INTEL_DEBUG("set_data_mappings\n"); >>> + if (!old_data) >>> + old_data = lds->surface->data; >>> + set_data_pointer(); >>> +} >>> + >>> +static void unset_data_mappings(int mapping) >>> +{ >>> + DisplaySurface *surf = lds->surface; >>> + if (!old_data) >>> + return; >>> + if (mapping) { >>> + uint8_t * buffer_pointer = surf->data; >>> + surf->data = old_data; >>> + old_data = NULL; >>> + surf->data = realloc(surf->data, surf->linesize * surf->height); >>> + memcpy(surf->data, >>> + (unsigned char *)(intel_mem + >>> intel_get_reg(REG_DR_DSPASURF)), >>> + surf->linesize * surf->height); >>> + memcpy(buffer_pointer, >>> + surf->data, >>> + surf->linesize * surf->height); >>> + } else { >>> + uint8_t * buffer_pointer = surf->data; >>> + surf->data = old_data; >>> + old_data = NULL; >>> + surf->data = realloc(surf->data, surf->linesize * surf->height); >>> + memcpy(surf->data, >>> + buffer_pointer, >>> + surf->linesize * surf->height); >>> + } >>> + INTEL_DEBUG("unset_data_mappings %d: success\n", mapping); >>> +} >>> + >>> +static int intel_getfocus(void) >>> +{ >>> + return intel_have_focus; >>> +} >>> + >>> +static void intel_focus(int focus) >>> +{ >>> + if (intel_have_focus == focus) >>> + return; >>> + >>> + INTEL_DEBUG("intel_focus %d\n", focus); >>> + intel_have_focus = focus; >>> + if (focus) { >>> + if (!is_linear()) { >>> + IntelPitch = intel_get_reg(REG_DR_DSPASTRIDE); >>> + IntelX = ((intel_get_reg(REG_DE_PIPEASRC) >> 16) & 0xfff) + 1; >>> + IntelY = (intel_get_reg(REG_DE_PIPEASRC) & 0xfff) + 1; >>> + INTEL_DEBUG("Resolution is %dx%d\n", IntelX, IntelY); >>> + } >>> + refresh = 1; >>> + lds->listeners->dpy_resize = intel_resize; >>> + lds->listeners->dpy_setdata = intel_setdata; >>> + vga_hw_invalidate(); >>> + } else { >>> + if (map_size) { >>> + unset_fb_mapping(); >>> + unset_data_mappings(1); >>> + } else if (old_data) { >>> + unset_data_mappings(0); >>> + } >>> + lds->listeners->dpy_resize = NULL; >>> + lds->listeners->dpy_setdata = NULL; >>> + lds->surface->flags &= ~QEMU_ALLOCATED_FLAG; >>> + } >>> +} >>> + >>> +int intel_enter(void) >>> +{ >>> + intel_focus(1); >>> + return 1; >>> +} >>> + >>> +int intel_leave(void) >>> +{ >>> + intel_focus(0); >>> + return 1; >>> +} >>> + >>> +void intel_display_init(DisplayState *ds) >>> +{ >>> + DisplaySurface *surf = ds->surface; >>> + >>> + INTEL_DEBUG("\n"); >>> + >>> + intel_init_mapping(); >>> + >>> + INTEL_DEBUG("Frambuffer is at 0x%x\n", intel_get_reg(REG_DR_DSPASURF)); >>> + >>> + surf->flags = 0; >>> + surf->width = 640; >>> + surf->height = 480; >>> + surf->pf.depth = 32; >>> + intel_resize(ds); >>> + lds = ds; >>> + >>> + ds->listeners->dpy_update = intel_update; >>> + ds->listeners->dpy_resize = intel_resize; >>> + ds->listeners->dpy_refresh = intel_refresh; >>> +} >>> \ No newline at end of file >>> diff -rupN --ignore-blank-lines-X diffignore a/tools/ioemu-remote/vl.c >>> b/tools/ioemu-remote/vl.c >>> --- a/tools/ioemu-remote/vl.c 2009-06-07 21:14:47.000000000 -0400 >>> +++ b/tools/ioemu-remote/vl.c 2009-06-07 19:29:12.000000000 -0400 >>> @@ -233,6 +233,9 @@ CharDriverState *virtcon_hds[MAX_VIRTIO_ >>> #ifdef TARGET_I386 >>> int win2k_install_hack = 0; >>> int rtc_td_hack = 0; >>> +int vga_passthrough = 0; >>> +const char *dom0_input = NULL; >>> +int intel = 0; >>> #endif >>> int usb_enabled = 0; >>> int smp_cpus = 1; >>> @@ -4039,6 +4042,9 @@ static void help(int exitcode) >>> "-disable-opengl disable OpenGL rendering, using SDL" >>> #endif >>> #endif >>> + "-vga_passthrough enable graphics card passthrough\n" >>> + "-dom0-input enable dom0 controlling qemu\n" >>> + "-intel use intel gfx\n" >>> "-portrait rotate graphical output 90 deg left (only PXA >>> LCD)\n" >>> "-vga [std|cirrus|vmware|none]\n" >>> " select video card type\n" >>> @@ -4275,6 +4281,9 @@ enum { >>> QEMU_OPTION_domainname, >>> QEMU_OPTION_acpi, >>> QEMU_OPTION_vcpus, >>> + QEMU_OPTION_vga_passthrough, >>> + QEMU_OPTION_dom0_input, >>> + QEMU_OPTION_intel, >>> >>> /* Debug/Expert options: */ >>> QEMU_OPTION_serial, >>> @@ -4448,6 +4457,9 @@ static const QEMUOption qemu_options[] = >>> { "pciemulation", HAS_ARG, QEMU_OPTION_pci_emulation }, >>> { "vncunused", 0, QEMU_OPTION_vncunused }, >>> { "vcpus", HAS_ARG, QEMU_OPTION_vcpus }, >>> + { "vga_passthrough", 0, QEMU_OPTION_vga_passthrough }, >>> + { "dom0-input", HAS_ARG, QEMU_OPTION_dom0_input }, >>> + { "intel", 0, QEMU_OPTION_intel }, >>> #if defined(CONFIG_XEN) && !defined(CONFIG_DM) >>> { "xen-domid", HAS_ARG, QEMU_OPTION_xen_domid }, >>> { "xen-create", 0, QEMU_OPTION_xen_create }, >>> @@ -5281,6 +5293,15 @@ int main(int argc, char **argv, char **e >>> case QEMU_OPTION_disable_opengl: >>> opengl_enabled = 0; >>> break; >>> + case QEMU_OPTION_vga_passthrough: >>> + vga_passthrough = 1; >>> + break; >>> + case QEMU_OPTION_dom0_input: >>> + dom0_input = optarg; >>> + break; >>> + case QEMU_OPTION_intel: >>> + intel = 1; >>> + break; >>> case QEMU_OPTION_direct_pci: >>> direct_pci = optarg; >>> break; >>> @@ -5876,6 +5897,14 @@ int main(int argc, char **argv, char **e >>> fprintf(stderr, "fatal: -nographic can't be used with >>> -curses\n"); >>> exit(1); >>> } >>> + >>> +#ifdef CONFIG_DM >>> + if(vga_passthrough) >>> + fprintf(stderr, "Replace if initializing dom0_driver\n" ); >>> +#else >>> + dumb_display_init(ds); >>> +#endif >>> + >>> } else { >>> #if defined(CONFIG_CURSES) >>> if (curses) { >>> diff -rupN --ignore-blank-lines-X diffignore >>> a/tools/ioemu-remote/xen-hooks.mak b/tools/ioemu-remote/xen-hooks.mak >>> --- a/tools/ioemu-remote/xen-hooks.mak 2009-06-07 21:14:47.000000000 -0400 >>> +++ b/tools/ioemu-remote/xen-hooks.mak 2009-06-07 19:04:12.000000000 -0400 >>> @@ -35,6 +35,7 @@ OBJS += exec-dm.o >>> OBJS += pci_emulation.o >>> OBJS += helper2.o >>> OBJS += battery_mgmt.o >>> +OBJS += intel.o >>> >>> ifdef CONFIG_STUBDOM >>> CPPFLAGS += $(TARGET_CPPFLAGS) -DNEED_CPU_H \ >>> diff -rupN --ignore-blank-lines-X diffignore a/tools/libxc/xc_hvm_build.c >>> b/tools/libxc/xc_hvm_build.c >>> --- a/tools/libxc/xc_hvm_build.c 2009-06-07 20:44:47.000000000 -0400 >>> +++ b/tools/libxc/xc_hvm_build.c 2009-06-07 19:04:12.000000000 -0400 >>> @@ -1,7 +1,3 @@ >>> -/****************************************************************************** >>> - * xc_hvm_build.c >>> - */ >>> - >>> #include <stddef.h> >>> #include <inttypes.h> >>> #include <stdlib.h> >>> @@ -66,6 +62,82 @@ static void build_hvm_info(void *hvm_inf >>> hvm_info->checksum = -sum; >>> } >>> >>> +static int init_vgabios(int xc_handle, >>> + uint32_t dom, >>> + unsigned char *buffer, >>> + uint32_t bios_size) >>> +{ >>> + char *va_bios = NULL; >>> + uint32_t va_size = 0; >>> + >>> + va_size = bios_size + bios_size % XC_PAGE_SIZE; >>> + va_bios = xc_map_foreign_range(xc_handle, dom, va_size, >>> + PROT_READ | PROT_WRITE, 0xC0); >>> + if (!va_bios) >>> + { >>> + IPRINTF("Unable to map vga bios!\n"); >>> + return -1; >>> + } >>> + >>> + if ( buffer != NULL) >>> + memcpy(va_bios, buffer, bios_size); >>> + else >>> + memset(va_bios, 0, bios_size); >>> + >>> + munmap(va_bios, va_size); >>> + return 0; >>> +} >>> + >>> +static int setup_vga_pt(int xc_handle, >>> + uint32_t dom) >>> +{ >>> + int rc = 0; >>> + unsigned char *bios = NULL; >>> + int bios_size = 0; >>> + char *c = NULL; >>> + char checksum = 0; >>> + >>> + IPRINTF("Setting up vga passthrough.\n"); >>> + >>> + /* Allocated 64K for the vga bios */ >>> + if (!(bios = malloc(64 * 1024))) { >>> + IPRINTF("Error allocating memory for vga bios.\n"); >>> + return -1; >>> + } >>> + >>> +#ifdef __linux__ >>> + bios_size = xc_get_vgabios(bios, 64 * 1024); >>> +#else >>> + bios_size = 0; >>> +#endif /* __linux__ */ >>> + >>> + if (bios_size == 0) >>> + { >>> + IPRINTF("vga bios size is 0!\n"); >>> + rc = -1; >>> + goto error; >>> + } >>> + >>> + /* Adjust the bios checksum */ >>> + for ( c = (char*)bios; c < ((char*)bios + bios_size); c++ ) >>> + checksum += *c; >>> + if (checksum) >>> + bios[bios_size - 1] -= checksum; >>> + init_vgabios(xc_handle, dom, bios, bios_size); >>> + >>> +error: >>> + free(bios); >>> + >>> + if( rc == -1 ) { >>> + IPRINTF("Error setting up vga passthrough.\n"); >>> + } >>> + else { >>> + IPRINTF("Success setting up vga passthrough.\n"); >>> + } >>> + >>> + return rc; >>> +} >>> + >>> static int loadelfimage( >>> struct elf_binary *elf, int xch, uint32_t dom, unsigned long *parray) >>> { >>> @@ -381,7 +453,8 @@ int xc_hvm_build_target_mem(int xc_handl >>> uint32_t domid, >>> int memsize, >>> int target, >>> - const char *image_name) >>> + const char *image_name, >>> + int vga_pt_enabled) >>> { >>> char *image; >>> int sts; >>> @@ -392,6 +465,12 @@ int xc_hvm_build_target_mem(int xc_handl >>> return -1; >>> >>> sts = xc_hvm_build_internal(xc_handle, domid, memsize, target, image, >>> image_size); >>> + if ( vga_pt_enabled ) { >>> + sts |= setup_vga_pt(xc_handle, domid); >>> + } else { >>> + sts |= init_vgabios(xc_handle, domid, NULL, 0x800); >>> + } >>> + >>> >>> free(image); >>> >>> diff -rupN --ignore-blank-lines-X diffignore a/tools/libxc/xc_linux.c >>> b/tools/libxc/xc_linux.c >>> --- a/tools/libxc/xc_linux.c 2009-06-07 20:44:47.000000000 -0400 >>> +++ b/tools/libxc/xc_linux.c 2009-06-07 19:04:12.000000000 -0400 >>> @@ -562,6 +562,57 @@ int xc_gnttab_set_max_grants(int xcg_han >>> return 0; >>> } >>> >>> +int xc_get_vgabios(unsigned char *buf, >>> + int len) >>> +{ >>> + int mem; >>> + uint32_t start, size = 0; >>> + uint16_t magic = 0; >>> + >>> + start = 0xC0000; >>> + if (len < size) >>> + return 0; >>> + if ((mem = open("/dev/mem", O_RDONLY)) < 0) >>> + return 0; >>> + >>> + /* >>> + ** Check if it a real bios extension. >>> + ** The magic number is 0xAA55. >>> + */ >>> + if (start != lseek(mem, start, SEEK_SET)) >>> + goto out; >>> + if (read(mem, &magic, 2) != 2) >>> + goto out; >>> + if (magic != 0xAA55) >>> + goto out; >>> + >>> + /* Find the size of the rom extension */ >>> + if (start != lseek(mem, start, SEEK_SET)) >>> + goto out; >>> + if (lseek(mem, 2, SEEK_CUR) != (start + 2)) >>> + goto out; >>> + if (read(mem, &size, 1) != 1) >>> + goto out; >>> + /* This size is in 512K */ >>> + size *= 512; >>> + >>> + /* >>> + ** Set the file to the begining of the rombios, >>> + ** to start the copy. >>> + */ >>> + if (start != lseek(mem, start, SEEK_SET)) >>> + { >>> + size = 0; >>> + goto out; >>> + } >>> + if (size != read(mem, buf, size)) >>> + size = 0; >>> + >>> +out: >>> + close(mem); >>> + return size; >>> +} >>> + >>> /* >>> * Local variables: >>> * mode: C >>> diff -rupN --ignore-blank-lines-X diffignore a/tools/libxc/xenctrl.h >>> b/tools/libxc/xenctrl.h >>> --- a/tools/libxc/xenctrl.h 2009-06-07 20:44:47.000000000 -0400 >>> +++ b/tools/libxc/xenctrl.h 2009-06-07 19:04:12.000000000 -0400 >>> @@ -145,6 +145,10 @@ int xc_waitdomain( >>> int *status, >>> int options); >>> >>> +int xc_get_vgabios( >>> + unsigned char *bios, >>> + int len); >>> + >>> #endif /* __linux__ */ >>> >>> /* >>> diff -rupN --ignore-blank-lines-X diffignore a/tools/libxc/xenguest.h >>> b/tools/libxc/xenguest.h >>> --- a/tools/libxc/xenguest.h 2009-06-07 20:44:47.000000000 -0400 >>> +++ b/tools/libxc/xenguest.h 2009-06-07 19:04:12.000000000 -0400 >>> @@ -134,7 +134,8 @@ int xc_hvm_build_target_mem(int xc_handl >>> uint32_t domid, >>> int memsize, >>> int target, >>> - const char *image_name); >>> + const char *image_name, >>> + int vga_pt_enabled); >>> >>> int xc_hvm_build_mem(int xc_handle, >>> uint32_t domid, >>> diff -rupN --ignore-blank-lines-X diffignore >>> a/tools/python/xen/lowlevel/xc/xc.c b/tools/python/xen/lowlevel/xc/xc.c >>> --- a/tools/python/xen/lowlevel/xc/xc.c 2009-06-07 20:44:47.000000000 -0400 >>> +++ b/tools/python/xen/lowlevel/xc/xc.c 2009-06-07 19:04:12.000000000 -0400 >>> @@ -890,21 +890,21 @@ static PyObject *pyxc_hvm_build(XcObject >>> int i; >>> #endif >>> char *image; >>> - int memsize, target=-1, vcpus = 1, acpi = 0, apic = 1; >>> + int memsize, target=-1, vcpus = 1, acpi = 0, apic = 1, vga_pt = 0; >>> >>> static char *kwd_list[] = { "domid", >>> "memsize", "image", "target", "vcpus", >>> "acpi", >>> - "apic", NULL }; >>> - if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iis|iiii", kwd_list, >>> + "apic", "vga_pt", NULL }; >>> + if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iis|iiiii", kwd_list, >>> &dom, &memsize, &image, &target, >>> &vcpus, >>> - &acpi, &apic) ) >>> + &acpi, &apic, &vga_pt) ) >>> return NULL; >>> >>> if ( target == -1 ) >>> target = memsize; >>> >>> if ( xc_hvm_build_target_mem(self->xc_handle, dom, memsize, >>> - target, image) != 0 ) >>> + target, image, vga_pt) != 0 ) >>> return pyxc_error_to_exception(); >>> >>> #if !defined(__ia64__) >>> diff -rupN --ignore-blank-lines-X diffignore >>> a/tools/python/xen/xend/image.py b/tools/python/xen/xend/image.py >>> --- a/tools/python/xen/xend/image.py 2009-06-07 20:44:47.000000000 -0400 >>> +++ b/tools/python/xen/xend/image.py 2009-06-07 19:04:12.000000000 -0400 >>> @@ -279,6 +279,9 @@ class ImageHandler: >>> vnc_config = {} >>> has_vnc = int(vmConfig['platform'].get('vnc', 0)) != 0 >>> has_sdl = int(vmConfig['platform'].get('sdl', 0)) != 0 >>> + has_vga_passthrough = >>> int(vmConfig['platform'].get('vga_passthrough', 0)) != 0 >>> + has_intel = int(vmConfig['platform'].get('intel', 0)) != 0 >>> + >>> opengl = 1 >>> keymap = vmConfig['platform'].get("keymap") >>> for dev_uuid in vmConfig['console_refs']: >>> @@ -302,7 +305,7 @@ class ImageHandler: >>> ret.append("-k") >>> ret.append(keymap) >>> >>> - if has_vnc: >>> + if has_vnc and not has_vga_passthrough: >>> if not vnc_config: >>> for key in ('vncunused', 'vnclisten', 'vncdisplay', >>> 'vncpasswd'): >>> @@ -353,6 +356,15 @@ class ImageHandler: >>> >>> if int(vmConfig['platform'].get('monitor', 0)) != 0: >>> ret = ret + ['-monitor', 'vc'] >>> + >>> + if has_vga_passthrough: >>> + ret.append('-vga_passthrough') >>> + dom0_input = str(vmConfig['platform'].get('dom0_input')) >>> + ret = ret + ['-dom0-input', dom0_input] >>> + >>> + if has_intel: >>> + ret.append('-intel') >>> + >>> return ret >>> >>> def getDeviceModelArgs(self, restore = False): >>> @@ -754,7 +766,9 @@ class HVMImageHandler(ImageHandler): >>> self.apic = int(vmConfig['platform'].get('apic', 0)) >>> self.acpi = int(vmConfig['platform'].get('acpi', 0)) >>> self.guest_os_type = vmConfig['platform'].get('guest_os_type') >>> - >>> + self.vga_pt = int(vmConfig['platform'].get('vga_passthrough', 0)) >>> + self.dom0_input = str(vmConfig['platform'].get('dom0_input')) >>> + self.intel = int(vmConfig['platform'].get('intel', 0)) >>> >>> # Return a list of cmd line args to the device models based on the >>> # xm config file >>> @@ -869,6 +883,7 @@ class HVMImageHandler(ImageHandler): >>> log.debug("vcpus = %d", self.vm.getVCpuCount()) >>> log.debug("acpi = %d", self.acpi) >>> log.debug("apic = %d", self.apic) >>> + log.debug("vga_pt = %d", self.vga_pt) >>> >>> rc = xc.hvm_build(domid = self.vm.getDomid(), >>> image = self.loader, >>> @@ -876,7 +891,8 @@ class HVMImageHandler(ImageHandler): >>> target = mem_mb, >>> vcpus = self.vm.getVCpuCount(), >>> acpi = self.acpi, >>> - apic = self.apic) >>> + apic = self.apic, >>> + vga_pt = self.vga_pt) >>> rc['notes'] = { 'SUSPEND_CANCEL': 1 } >>> >>> rc['store_mfn'] = xc.hvm_get_param(self.vm.getDomid(), >>> diff -rupN --ignore-blank-lines-X diffignore >>> a/tools/python/xen/xend/XendConfig.py b/tools/python/xen/xend/XendConfig.py >>> --- a/tools/python/xen/xend/XendConfig.py 2009-06-07 >>> 20:44:47.000000000 -0400 >>> +++ b/tools/python/xen/xend/XendConfig.py 2009-06-07 >>> 19:04:12.000000000 -0400 >>> @@ -171,6 +171,9 @@ XENAPI_PLATFORM_CFG_TYPES = { >>> 'pci_msitranslate': int, >>> 'pci_power_mgmt': int, >>> 'xen_platform_pci': int, >>> + 'vga_passthrough': int, >>> + 'dom0_input': str, >>> + 'intel': int, >>> } >>> >>> # Xen API console 'other_config' keys. >>> diff -rupN --ignore-blank-lines-X diffignore >>> a/tools/python/xen/xm/create.py b/tools/python/xen/xm/create.py >>> --- a/tools/python/xen/xm/create.py 2009-06-07 20:44:47.000000000 -0400 >>> +++ b/tools/python/xen/xm/create.py 2009-06-07 19:04:12.000000000 -0400 >>> @@ -618,6 +618,18 @@ gopts.var('xen_platform_pci', val='0|1', >>> fn=set_int, default=1, >>> use="Is xen_platform_pci used?") >>> >>> +gopts.var('vga_passthrough', val='0|1', >>> + fn=set_int, default=None, >>> + use="Enable the passthrough for the graphic card.") >>> + >>> +gopts.var('dom0_input', val='DOM0_INPUT', >>> + fn=set_value, default=None, >>> + use="Input arguments for dom0 driver") >>> + >>> +gopts.var('intel', val='INTEL', >>> + fn=set_int, default=None, >>> + use="Use Intel GFX.") >>> + >>> def err(msg): >>> """Print an error to stderr and exit. >>> """ >>> @@ -932,7 +944,8 @@ def configure_hvm(config_image, vals): >>> 'acpi', 'apic', 'usb', 'usbdevice', 'keymap', 'pci', 'hpet', >>> 'guest_os_type', 'hap', 'opengl', 'cpuid', 'cpuid_check', >>> 'viridian', 'xen_extended_power_mgmt', 'pci_msitranslate', >>> - 'vpt_align', 'pci_power_mgmt', 'xen_platform_pci' ] >>> + 'vpt_align', 'pci_power_mgmt', 'xen_platform_pci', >>> + 'vga_passthrough', 'dom0_input', 'intel' ] >>> >>> for a in args: >>> if a in vals.__dict__ and vals.__dict__[a] is not None: >>> >>> _______________________________________________ >>> Xen-devel mailing list >>> Xen-devel@xxxxxxxxxxxxxxxxxxx >>> http://lists.xensource.com/xen-devel >>> >>> >> >> Where did this patch come from? I plan to try using a ati card with a >> windows domU this week but first I need to port this patch to 2.6.29, >> before I start I want to make sure I am working with the latest >> version of the patch. >> >> Andy >> >> _______________________________________________ >> Xen-devel mailing list >> Xen-devel@xxxxxxxxxxxxxxxxxxx >> http://lists.xensource.com/xen-devel > > _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |