From 4d9310e39728a87c86eb48492da7546f61189633 Mon Sep 17 00:00:00 2001 From: Stefano Stabellini Date: Mon, 6 Aug 2012 15:27:09 +0100 Subject: xen: missing includes Changes in v2: - remove pvclock hack; - remove include linux/types.h from xen/interface/xen.h. v3: - Compile under IA64 Signed-off-by: Stefano Stabellini Signed-off-by: Konrad Rzeszutek Wilk --- drivers/xen/grant-table.c | 1 + drivers/xen/xenbus/xenbus_probe_frontend.c | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers/xen') diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c index 0bfc1ef1125..1d0d95e5b44 100644 --- a/drivers/xen/grant-table.c +++ b/drivers/xen/grant-table.c @@ -47,6 +47,7 @@ #include #include #include +#include #include #include diff --git a/drivers/xen/xenbus/xenbus_probe_frontend.c b/drivers/xen/xenbus/xenbus_probe_frontend.c index a31b54d4883..3159a37d966 100644 --- a/drivers/xen/xenbus/xenbus_probe_frontend.c +++ b/drivers/xen/xenbus/xenbus_probe_frontend.c @@ -21,6 +21,7 @@ #include #include #include +#include #include -- cgit v1.2.3-70-g09d2 From b8b0f559c7b1dcf5503817e518c81c9a18ee45e0 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Tue, 21 Aug 2012 14:49:34 -0400 Subject: xen/apic/xenbus/swiotlb/pcifront/grant/tmem: Make functions or variables static. There is no need for those functions/variables to be visible. Make them static and also fix the compile warnings of this sort: drivers/xen/.c: warning: symbol '' was not declared. Should it be static? Some of them just require including the header file that declares the functions. Signed-off-by: Konrad Rzeszutek Wilk --- arch/x86/xen/apic.c | 3 ++- arch/x86/xen/enlighten.c | 2 ++ arch/x86/xen/pci-swiotlb-xen.c | 1 + arch/x86/xen/platform-pci-unplug.c | 1 + drivers/pci/xen-pcifront.c | 2 +- drivers/xen/gntdev.c | 2 +- drivers/xen/grant-table.c | 13 ++++++------- drivers/xen/swiotlb-xen.c | 2 +- drivers/xen/tmem.c | 1 + drivers/xen/xenbus/xenbus_dev_backend.c | 2 +- drivers/xen/xenbus/xenbus_probe.c | 4 ++-- 11 files changed, 19 insertions(+), 14 deletions(-) (limited to 'drivers/xen') diff --git a/arch/x86/xen/apic.c b/arch/x86/xen/apic.c index ec57bd3818a..7005ced5d1a 100644 --- a/arch/x86/xen/apic.c +++ b/arch/x86/xen/apic.c @@ -6,8 +6,9 @@ #include #include +#include "xen-ops.h" -unsigned int xen_io_apic_read(unsigned apic, unsigned reg) +static unsigned int xen_io_apic_read(unsigned apic, unsigned reg) { struct physdev_apic apic_op; int ret; diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index ff962d4b821..cb1b1914dbd 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -79,6 +79,8 @@ #include "smp.h" #include "multicalls.h" +#include + EXPORT_SYMBOL_GPL(hypercall_page); DEFINE_PER_CPU(struct vcpu_info *, xen_vcpu); diff --git a/arch/x86/xen/pci-swiotlb-xen.c b/arch/x86/xen/pci-swiotlb-xen.c index 967633ad98c..2d58b3ff4fa 100644 --- a/arch/x86/xen/pci-swiotlb-xen.c +++ b/arch/x86/xen/pci-swiotlb-xen.c @@ -8,6 +8,7 @@ #include #include +#include int xen_swiotlb __read_mostly; static struct dma_map_ops xen_swiotlb_dma_ops = { diff --git a/arch/x86/xen/platform-pci-unplug.c b/arch/x86/xen/platform-pci-unplug.c index ffcf2615640..0a7852483ff 100644 --- a/arch/x86/xen/platform-pci-unplug.c +++ b/arch/x86/xen/platform-pci-unplug.c @@ -24,6 +24,7 @@ #include #include +#include "xen-ops.h" #define XEN_PLATFORM_ERR_MAGIC -1 #define XEN_PLATFORM_ERR_PROTOCOL -2 diff --git a/drivers/pci/xen-pcifront.c b/drivers/pci/xen-pcifront.c index d6cc62cb4cf..a4d901def8f 100644 --- a/drivers/pci/xen-pcifront.c +++ b/drivers/pci/xen-pcifront.c @@ -236,7 +236,7 @@ static int pcifront_bus_write(struct pci_bus *bus, unsigned int devfn, return errno_to_pcibios_err(do_pci_op(pdev, &op)); } -struct pci_ops pcifront_bus_ops = { +static struct pci_ops pcifront_bus_ops = { .read = pcifront_bus_read, .write = pcifront_bus_write, }; diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c index 1ffd03bf8e1..163b7e985ed 100644 --- a/drivers/xen/gntdev.c +++ b/drivers/xen/gntdev.c @@ -445,7 +445,7 @@ static void mn_release(struct mmu_notifier *mn, spin_unlock(&priv->lock); } -struct mmu_notifier_ops gntdev_mmu_ops = { +static struct mmu_notifier_ops gntdev_mmu_ops = { .release = mn_release, .invalidate_page = mn_invl_page, .invalidate_range_start = mn_invl_range_start, diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c index 1d0d95e5b44..eea81cf8a2a 100644 --- a/drivers/xen/grant-table.c +++ b/drivers/xen/grant-table.c @@ -286,10 +286,9 @@ int gnttab_grant_foreign_access(domid_t domid, unsigned long frame, } EXPORT_SYMBOL_GPL(gnttab_grant_foreign_access); -void gnttab_update_subpage_entry_v2(grant_ref_t ref, domid_t domid, - unsigned long frame, int flags, - unsigned page_off, - unsigned length) +static void gnttab_update_subpage_entry_v2(grant_ref_t ref, domid_t domid, + unsigned long frame, int flags, + unsigned page_off, unsigned length) { gnttab_shared.v2[ref].sub_page.frame = frame; gnttab_shared.v2[ref].sub_page.page_off = page_off; @@ -346,9 +345,9 @@ bool gnttab_subpage_grants_available(void) } EXPORT_SYMBOL_GPL(gnttab_subpage_grants_available); -void gnttab_update_trans_entry_v2(grant_ref_t ref, domid_t domid, - int flags, domid_t trans_domid, - grant_ref_t trans_gref) +static void gnttab_update_trans_entry_v2(grant_ref_t ref, domid_t domid, + int flags, domid_t trans_domid, + grant_ref_t trans_gref) { gnttab_shared.v2[ref].transitive.trans_domid = trans_domid; gnttab_shared.v2[ref].transitive.gref = trans_gref; diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c index 1afb4fba11b..a52f3ae05d9 100644 --- a/drivers/xen/swiotlb-xen.c +++ b/drivers/xen/swiotlb-xen.c @@ -52,7 +52,7 @@ static unsigned long xen_io_tlb_nslabs; * Quick lookup value of the bus address of the IOTLB. */ -u64 start_dma_addr; +static u64 start_dma_addr; static dma_addr_t xen_phys_to_bus(phys_addr_t paddr) { diff --git a/drivers/xen/tmem.c b/drivers/xen/tmem.c index 89f264c6742..144564e5eb2 100644 --- a/drivers/xen/tmem.c +++ b/drivers/xen/tmem.c @@ -21,6 +21,7 @@ #include #include #include +#include #define TMEM_CONTROL 0 #define TMEM_NEW_POOL 1 diff --git a/drivers/xen/xenbus/xenbus_dev_backend.c b/drivers/xen/xenbus/xenbus_dev_backend.c index be738c43104..d7300080076 100644 --- a/drivers/xen/xenbus/xenbus_dev_backend.c +++ b/drivers/xen/xenbus/xenbus_dev_backend.c @@ -107,7 +107,7 @@ static int xenbus_backend_mmap(struct file *file, struct vm_area_struct *vma) return 0; } -const struct file_operations xenbus_backend_fops = { +static const struct file_operations xenbus_backend_fops = { .open = xenbus_backend_open, .mmap = xenbus_backend_mmap, .unlocked_ioctl = xenbus_backend_ioctl, diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c index b793723e724..91d3d6544a7 100644 --- a/drivers/xen/xenbus/xenbus_probe.c +++ b/drivers/xen/xenbus/xenbus_probe.c @@ -324,8 +324,8 @@ static int cmp_dev(struct device *dev, void *data) return 0; } -struct xenbus_device *xenbus_device_find(const char *nodename, - struct bus_type *bus) +static struct xenbus_device *xenbus_device_find(const char *nodename, + struct bus_type *bus) { struct xb_find_info info = { .dev = NULL, .nodename = nodename }; -- cgit v1.2.3-70-g09d2 From 5c13f8067745efc15f6ad0158b58d57c44104c25 Mon Sep 17 00:00:00 2001 From: Daniel De Graaf Date: Thu, 16 Aug 2012 16:40:26 -0400 Subject: xen/sysfs: Use XENVER_guest_handle to query UUID This hypercall has been present since Xen 3.1, and is the preferred method for a domain to obtain its UUID. Fall back to the xenstore method if using an older version of Xen (which returns -ENOSYS). Signed-off-by: Daniel De Graaf Signed-off-by: Konrad Rzeszutek Wilk --- drivers/xen/sys-hypervisor.c | 13 ++++++++++++- include/xen/interface/version.h | 3 +++ 2 files changed, 15 insertions(+), 1 deletion(-) (limited to 'drivers/xen') diff --git a/drivers/xen/sys-hypervisor.c b/drivers/xen/sys-hypervisor.c index fdb6d229c9b..5e5ad7e2885 100644 --- a/drivers/xen/sys-hypervisor.c +++ b/drivers/xen/sys-hypervisor.c @@ -114,7 +114,7 @@ static void xen_sysfs_version_destroy(void) /* UUID */ -static ssize_t uuid_show(struct hyp_sysfs_attr *attr, char *buffer) +static ssize_t uuid_show_fallback(struct hyp_sysfs_attr *attr, char *buffer) { char *vm, *val; int ret; @@ -135,6 +135,17 @@ static ssize_t uuid_show(struct hyp_sysfs_attr *attr, char *buffer) return ret; } +static ssize_t uuid_show(struct hyp_sysfs_attr *attr, char *buffer) +{ + xen_domain_handle_t uuid; + int ret; + ret = HYPERVISOR_xen_version(XENVER_guest_handle, uuid); + if (ret) + return uuid_show_fallback(attr, buffer); + ret = sprintf(buffer, "%pU\n", uuid); + return ret; +} + HYPERVISOR_ATTR_RO(uuid); static int __init xen_sysfs_uuid_init(void) diff --git a/include/xen/interface/version.h b/include/xen/interface/version.h index e8b6519d47e..dd58cf5ea3e 100644 --- a/include/xen/interface/version.h +++ b/include/xen/interface/version.h @@ -60,4 +60,7 @@ struct xen_feature_info { /* arg == NULL; returns host memory page size. */ #define XENVER_pagesize 7 +/* arg == xen_domain_handle_t. */ +#define XENVER_guest_handle 8 + #endif /* __XEN_PUBLIC_VERSION_H__ */ -- cgit v1.2.3-70-g09d2 From b5e579232d635b79a3da052964cb357ccda8d9ea Mon Sep 17 00:00:00 2001 From: Stefano Stabellini Date: Wed, 22 Aug 2012 17:20:11 +0100 Subject: xen/events: fix unmask_evtchn for PV on HVM guests When unmask_evtchn is called, if we already have an event pending, we just set evtchn_pending_sel waiting for local_irq_enable to be called. That is because PV guests set the irq_enable pvops to xen_irq_enable_direct in xen_setup_vcpu_info_placement: xen_irq_enable_direct is implemented in assembly in arch/x86/xen/xen-asm.S and call xen_force_evtchn_callback if XEN_vcpu_info_pending is set. However HVM guests (and ARM guests) do not change or do not have the irq_enable pvop, so evtchn_unmask cannot work properly for them. Considering that having the pending_irq bit set when unmask_evtchn is called is not very common, and it is simpler to keep the native_irq_enable implementation for HVM guests (and ARM guests), the best thing to do is just use the EVTCHNOP_unmask hypercall (Xen re-injects pending events in response). Signed-off-by: Stefano Stabellini Signed-off-by: Konrad Rzeszutek Wilk --- drivers/xen/events.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'drivers/xen') diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 7595581d032..36bf17dc7bf 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c @@ -373,11 +373,22 @@ static void unmask_evtchn(int port) { struct shared_info *s = HYPERVISOR_shared_info; unsigned int cpu = get_cpu(); + int do_hypercall = 0, evtchn_pending = 0; BUG_ON(!irqs_disabled()); - /* Slow path (hypercall) if this is a non-local port. */ - if (unlikely(cpu != cpu_from_evtchn(port))) { + if (unlikely((cpu != cpu_from_evtchn(port)))) + do_hypercall = 1; + else + evtchn_pending = sync_test_bit(port, &s->evtchn_pending[0]); + + if (unlikely(evtchn_pending && xen_hvm_domain())) + do_hypercall = 1; + + /* Slow path (hypercall) if this is a non-local port or if this is + * an hvm domain and an event is pending (hvm domains don't have + * their own implementation of irq_enable). */ + if (do_hypercall) { struct evtchn_unmask unmask = { .port = port }; (void)HYPERVISOR_event_channel_op(EVTCHNOP_unmask, &unmask); } else { @@ -390,7 +401,7 @@ static void unmask_evtchn(int port) * 'hw_resend_irq'. Just like a real IO-APIC we 'lose * the interrupt edge' if the channel is masked. */ - if (sync_test_bit(port, &s->evtchn_pending[0]) && + if (evtchn_pending && !sync_test_and_set_bit(port / BITS_PER_LONG, &vcpu_info->evtchn_pending_sel)) vcpu_info->evtchn_upcall_pending = 1; -- cgit v1.2.3-70-g09d2 From a8636c0b2e57d4f31f71aa306b1ee701db3f3c85 Mon Sep 17 00:00:00 2001 From: Stefano Stabellini Date: Wed, 22 Aug 2012 17:20:15 +0100 Subject: xen: clear IRQ_NOAUTOEN and IRQ_NOREQUEST Reset the IRQ_NOAUTOEN and IRQ_NOREQUEST flags that are enabled by default on ARM. If IRQ_NOAUTOEN is set, __setup_irq doesn't call irq_startup, that is responsible for calling irq_unmask at startup time. As a result event channels remain masked. Signed-off-by: Stefano Stabellini Acked-by: Konrad Rzeszutek Wilk Signed-off-by: Konrad Rzeszutek Wilk --- drivers/xen/events.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/xen') diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 36bf17dc7bf..c60d1629c91 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c @@ -842,6 +842,7 @@ int bind_evtchn_to_irq(unsigned int evtchn) struct irq_info *info = info_for_irq(irq); WARN_ON(info == NULL || info->type != IRQT_EVTCHN); } + irq_clear_status_flags(irq, IRQ_NOREQUEST|IRQ_NOAUTOEN); out: mutex_unlock(&irq_mapping_update_lock); -- cgit v1.2.3-70-g09d2 From 1a1d43318aeb74d679372c0b65029957be274529 Mon Sep 17 00:00:00 2001 From: Stefano Stabellini Date: Wed, 22 Aug 2012 17:20:16 +0100 Subject: xen: allow privcmd for HVM guests This patch removes the "return -ENOSYS" for auto_translated_physmap guests from privcmd_mmap, thus it allows ARM guests to issue privcmd mmap calls. However privcmd mmap calls are still going to fail for HVM and hybrid guests on x86 because the xen_remap_domain_mfn_range implementation is currently PV only. Changes in v2: - better commit message; - return -EINVAL from xen_remap_domain_mfn_range if auto_translated_physmap. Signed-off-by: Stefano Stabellini Acked-by: Konrad Rzeszutek Wilk Signed-off-by: Konrad Rzeszutek Wilk --- arch/x86/xen/mmu.c | 3 +++ drivers/xen/privcmd.c | 4 ---- 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers/xen') diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index 3a73785631c..885a22354a9 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c @@ -2310,6 +2310,9 @@ int xen_remap_domain_mfn_range(struct vm_area_struct *vma, unsigned long range; int err = 0; + if (xen_feature(XENFEAT_auto_translated_physmap)) + return -EINVAL; + prot = __pgprot(pgprot_val(prot) | _PAGE_IOMAP); BUG_ON(!((vma->vm_flags & (VM_PFNMAP | VM_RESERVED | VM_IO)) == diff --git a/drivers/xen/privcmd.c b/drivers/xen/privcmd.c index ccee0f16bcf..85226cbeca2 100644 --- a/drivers/xen/privcmd.c +++ b/drivers/xen/privcmd.c @@ -380,10 +380,6 @@ static struct vm_operations_struct privcmd_vm_ops = { static int privcmd_mmap(struct file *file, struct vm_area_struct *vma) { - /* Unsupported for auto-translate guests. */ - if (xen_feature(XENFEAT_auto_translated_physmap)) - return -ENOSYS; - /* DONTCOPY is essential for Xen because copy_page_range doesn't know * how to recreate these mappings */ vma->vm_flags |= VM_RESERVED | VM_IO | VM_DONTCOPY | VM_PFNMAP; -- cgit v1.2.3-70-g09d2 From a8752fd9a4106c5efe324109df133692d5fcbffc Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Mon, 13 Aug 2012 13:26:11 -0400 Subject: xen/swiotlb: Remove functions not needed anymore. Sparse warns us off: drivers/xen/swiotlb-xen.c:506:1: warning: symbol 'xen_swiotlb_map_sg' was not declared. Should it be static? drivers/xen/swiotlb-xen.c:534:1: warning: symbol 'xen_swiotlb_unmap_sg' was not declared. Should it be static? and it looks like we do not need this function at all. Signed-off-by: Konrad Rzeszutek Wilk --- drivers/xen/swiotlb-xen.c | 16 ---------------- include/xen/swiotlb-xen.h | 9 --------- 2 files changed, 25 deletions(-) (limited to 'drivers/xen') diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c index a52f3ae05d9..29e8cd48180 100644 --- a/drivers/xen/swiotlb-xen.c +++ b/drivers/xen/swiotlb-xen.c @@ -466,14 +466,6 @@ xen_swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl, } EXPORT_SYMBOL_GPL(xen_swiotlb_map_sg_attrs); -int -xen_swiotlb_map_sg(struct device *hwdev, struct scatterlist *sgl, int nelems, - enum dma_data_direction dir) -{ - return xen_swiotlb_map_sg_attrs(hwdev, sgl, nelems, dir, NULL); -} -EXPORT_SYMBOL_GPL(xen_swiotlb_map_sg); - /* * Unmap a set of streaming mode DMA translations. Again, cpu read rules * concerning calls here are the same as for swiotlb_unmap_page() above. @@ -494,14 +486,6 @@ xen_swiotlb_unmap_sg_attrs(struct device *hwdev, struct scatterlist *sgl, } EXPORT_SYMBOL_GPL(xen_swiotlb_unmap_sg_attrs); -void -xen_swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sgl, int nelems, - enum dma_data_direction dir) -{ - return xen_swiotlb_unmap_sg_attrs(hwdev, sgl, nelems, dir, NULL); -} -EXPORT_SYMBOL_GPL(xen_swiotlb_unmap_sg); - /* * Make physical memory consistent for a set of streaming mode DMA translations * after a transfer. diff --git a/include/xen/swiotlb-xen.h b/include/xen/swiotlb-xen.h index 4f4d449f00f..c050b6b9de3 100644 --- a/include/xen/swiotlb-xen.h +++ b/include/xen/swiotlb-xen.h @@ -23,15 +23,6 @@ extern dma_addr_t xen_swiotlb_map_page(struct device *dev, struct page *page, extern void xen_swiotlb_unmap_page(struct device *hwdev, dma_addr_t dev_addr, size_t size, enum dma_data_direction dir, struct dma_attrs *attrs); -/* -extern int -xen_swiotlb_map_sg(struct device *hwdev, struct scatterlist *sg, int nents, - enum dma_data_direction dir); - -extern void -xen_swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sg, int nents, - enum dma_data_direction dir); -*/ extern int xen_swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl, int nelems, enum dma_data_direction dir, -- cgit v1.2.3-70-g09d2 From c59687f8466df36633d937cc298aad465d704990 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Wed, 5 Sep 2012 15:13:48 +0200 Subject: cpuidle / ACPI : remove power from acpi_processor_cx structure Remove the unused power field from struct struct acpi_processor_cx. [rjw: Modified changelog.] Signed-off-by: Daniel Lezcano Acked-by: Konrad Rzeszutek Wilk Signed-off-by: Rafael J. Wysocki --- drivers/acpi/processor_idle.c | 2 -- drivers/xen/xen-acpi-processor.c | 1 - include/acpi/processor.h | 1 - 3 files changed, 4 deletions(-) (limited to 'drivers/xen') diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index ad3730b4038..de896242d14 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -483,8 +483,6 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr) if (obj->type != ACPI_TYPE_INTEGER) continue; - cx.power = obj->integer.value; - current_count++; memcpy(&(pr->power.states[current_count]), &cx, sizeof(cx)); diff --git a/drivers/xen/xen-acpi-processor.c b/drivers/xen/xen-acpi-processor.c index b590ee067fc..316df65163c 100644 --- a/drivers/xen/xen-acpi-processor.c +++ b/drivers/xen/xen-acpi-processor.c @@ -98,7 +98,6 @@ static int push_cxx_to_hypervisor(struct acpi_processor *_pr) dst_cx->type = cx->type; dst_cx->latency = cx->latency; - dst_cx->power = cx->power; dst_cx->dpcnt = 0; set_xen_guest_handle(dst_cx->dp, NULL); diff --git a/include/acpi/processor.h b/include/acpi/processor.h index 64ec644808b..db427fa8cf8 100644 --- a/include/acpi/processor.h +++ b/include/acpi/processor.h @@ -59,7 +59,6 @@ struct acpi_processor_cx { u8 entry_method; u8 index; u32 latency; - u32 power; u8 bm_sts_skip; char desc[ACPI_CX_DESC_LEN]; }; -- cgit v1.2.3-70-g09d2 From ceb90fa0a8008059ecbbf9114cb89dc71a730bb6 Mon Sep 17 00:00:00 2001 From: Andres Lagar-Cavilla Date: Fri, 31 Aug 2012 09:59:30 -0400 Subject: xen/privcmd: add PRIVCMD_MMAPBATCH_V2 ioctl PRIVCMD_MMAPBATCH_V2 extends PRIVCMD_MMAPBATCH with an additional field for reporting the error code for every frame that could not be mapped. libxc prefers PRIVCMD_MMAPBATCH_V2 over PRIVCMD_MMAPBATCH. Also expand PRIVCMD_MMAPBATCH to return appropriate error-encoding top nibble in the mfn array. Signed-off-by: David Vrabel Signed-off-by: Andres Lagar-Cavilla Signed-off-by: Konrad Rzeszutek Wilk --- drivers/xen/privcmd.c | 130 ++++++++++++++++++++++++++++++++++++++------------ include/xen/privcmd.h | 24 +++++++++- 2 files changed, 123 insertions(+), 31 deletions(-) (limited to 'drivers/xen') diff --git a/drivers/xen/privcmd.c b/drivers/xen/privcmd.c index 85226cbeca2..92a285b1b96 100644 --- a/drivers/xen/privcmd.c +++ b/drivers/xen/privcmd.c @@ -76,7 +76,7 @@ static void free_page_list(struct list_head *pages) */ static int gather_array(struct list_head *pagelist, unsigned nelem, size_t size, - void __user *data) + const void __user *data) { unsigned pageidx; void *pagedata; @@ -246,61 +246,117 @@ struct mmap_batch_state { domid_t domain; unsigned long va; struct vm_area_struct *vma; - int err; - - xen_pfn_t __user *user; + /* A tristate: + * 0 for no errors + * 1 if at least one error has happened (and no + * -ENOENT errors have happened) + * -ENOENT if at least 1 -ENOENT has happened. + */ + int global_error; + /* An array for individual errors */ + int *err; + + /* User-space mfn array to store errors in the second pass for V1. */ + xen_pfn_t __user *user_mfn; }; static int mmap_batch_fn(void *data, void *state) { xen_pfn_t *mfnp = data; struct mmap_batch_state *st = state; + int ret; - if (xen_remap_domain_mfn_range(st->vma, st->va & PAGE_MASK, *mfnp, 1, - st->vma->vm_page_prot, st->domain) < 0) { - *mfnp |= 0xf0000000U; - st->err++; + ret = xen_remap_domain_mfn_range(st->vma, st->va & PAGE_MASK, *mfnp, 1, + st->vma->vm_page_prot, st->domain); + + /* Store error code for second pass. */ + *(st->err++) = ret; + + /* And see if it affects the global_error. */ + if (ret < 0) { + if (ret == -ENOENT) + st->global_error = -ENOENT; + else { + /* Record that at least one error has happened. */ + if (st->global_error == 0) + st->global_error = 1; + } } st->va += PAGE_SIZE; return 0; } -static int mmap_return_errors(void *data, void *state) +static int mmap_return_errors_v1(void *data, void *state) { xen_pfn_t *mfnp = data; struct mmap_batch_state *st = state; - - return put_user(*mfnp, st->user++); + int err = *(st->err++); + + /* + * V1 encodes the error codes in the 32bit top nibble of the + * mfn (with its known limitations vis-a-vis 64 bit callers). + */ + *mfnp |= (err == -ENOENT) ? + PRIVCMD_MMAPBATCH_PAGED_ERROR : + PRIVCMD_MMAPBATCH_MFN_ERROR; + return __put_user(*mfnp, st->user_mfn++); } static struct vm_operations_struct privcmd_vm_ops; -static long privcmd_ioctl_mmap_batch(void __user *udata) +static long privcmd_ioctl_mmap_batch(void __user *udata, int version) { int ret; - struct privcmd_mmapbatch m; + struct privcmd_mmapbatch_v2 m; struct mm_struct *mm = current->mm; struct vm_area_struct *vma; unsigned long nr_pages; LIST_HEAD(pagelist); + int *err_array = NULL; struct mmap_batch_state state; if (!xen_initial_domain()) return -EPERM; - if (copy_from_user(&m, udata, sizeof(m))) - return -EFAULT; + switch (version) { + case 1: + if (copy_from_user(&m, udata, sizeof(struct privcmd_mmapbatch))) + return -EFAULT; + /* Returns per-frame error in m.arr. */ + m.err = NULL; + if (!access_ok(VERIFY_WRITE, m.arr, m.num * sizeof(*m.arr))) + return -EFAULT; + break; + case 2: + if (copy_from_user(&m, udata, sizeof(struct privcmd_mmapbatch_v2))) + return -EFAULT; + /* Returns per-frame error code in m.err. */ + if (!access_ok(VERIFY_WRITE, m.err, m.num * (sizeof(*m.err)))) + return -EFAULT; + break; + default: + return -EINVAL; + } nr_pages = m.num; if ((m.num <= 0) || (nr_pages > (LONG_MAX >> PAGE_SHIFT))) return -EINVAL; - ret = gather_array(&pagelist, m.num, sizeof(xen_pfn_t), - m.arr); + ret = gather_array(&pagelist, m.num, sizeof(xen_pfn_t), m.arr); + + if (ret) + goto out; + if (list_empty(&pagelist)) { + ret = -EINVAL; + goto out; + } - if (ret || list_empty(&pagelist)) + err_array = kcalloc(m.num, sizeof(int), GFP_KERNEL); + if (err_array == NULL) { + ret = -ENOMEM; goto out; + } down_write(&mm->mmap_sem); @@ -315,24 +371,34 @@ static long privcmd_ioctl_mmap_batch(void __user *udata) goto out; } - state.domain = m.dom; - state.vma = vma; - state.va = m.addr; - state.err = 0; + state.domain = m.dom; + state.vma = vma; + state.va = m.addr; + state.global_error = 0; + state.err = err_array; - ret = traverse_pages(m.num, sizeof(xen_pfn_t), - &pagelist, mmap_batch_fn, &state); + /* mmap_batch_fn guarantees ret == 0 */ + BUG_ON(traverse_pages(m.num, sizeof(xen_pfn_t), + &pagelist, mmap_batch_fn, &state)); up_write(&mm->mmap_sem); - if (state.err > 0) { - state.user = m.arr; + if (state.global_error && (version == 1)) { + /* Write back errors in second pass. */ + state.user_mfn = (xen_pfn_t *)m.arr; + state.err = err_array; ret = traverse_pages(m.num, sizeof(xen_pfn_t), - &pagelist, - mmap_return_errors, &state); - } + &pagelist, mmap_return_errors_v1, &state); + } else + ret = __copy_to_user(m.err, err_array, m.num * sizeof(int)); + + /* If we have not had any EFAULT-like global errors then set the global + * error to -ENOENT if necessary. */ + if ((ret == 0) && (state.global_error == -ENOENT)) + ret = -ENOENT; out: + kfree(err_array); free_page_list(&pagelist); return ret; @@ -354,7 +420,11 @@ static long privcmd_ioctl(struct file *file, break; case IOCTL_PRIVCMD_MMAPBATCH: - ret = privcmd_ioctl_mmap_batch(udata); + ret = privcmd_ioctl_mmap_batch(udata, 1); + break; + + case IOCTL_PRIVCMD_MMAPBATCH_V2: + ret = privcmd_ioctl_mmap_batch(udata, 2); break; default: diff --git a/include/xen/privcmd.h b/include/xen/privcmd.h index 45c1aa14b83..a85316811d7 100644 --- a/include/xen/privcmd.h +++ b/include/xen/privcmd.h @@ -58,13 +58,33 @@ struct privcmd_mmapbatch { int num; /* number of pages to populate */ domid_t dom; /* target domain */ __u64 addr; /* virtual address */ - xen_pfn_t __user *arr; /* array of mfns - top nibble set on err */ + xen_pfn_t __user *arr; /* array of mfns - or'd with + PRIVCMD_MMAPBATCH_*_ERROR on err */ +}; + +#define PRIVCMD_MMAPBATCH_MFN_ERROR 0xf0000000U +#define PRIVCMD_MMAPBATCH_PAGED_ERROR 0x80000000U + +struct privcmd_mmapbatch_v2 { + unsigned int num; /* number of pages to populate */ + domid_t dom; /* target domain */ + __u64 addr; /* virtual address */ + const xen_pfn_t __user *arr; /* array of mfns */ + int __user *err; /* array of error codes */ }; /* * @cmd: IOCTL_PRIVCMD_HYPERCALL * @arg: &privcmd_hypercall_t * Return: Value returned from execution of the specified hypercall. + * + * @cmd: IOCTL_PRIVCMD_MMAPBATCH_V2 + * @arg: &struct privcmd_mmapbatch_v2 + * Return: 0 on success (i.e., arg->err contains valid error codes for + * each frame). On an error other than a failed frame remap, -1 is + * returned and errno is set to EINVAL, EFAULT etc. As an exception, + * if the operation was otherwise successful but any frame failed with + * -ENOENT, then -1 is returned and errno is set to ENOENT. */ #define IOCTL_PRIVCMD_HYPERCALL \ _IOC(_IOC_NONE, 'P', 0, sizeof(struct privcmd_hypercall)) @@ -72,5 +92,7 @@ struct privcmd_mmapbatch { _IOC(_IOC_NONE, 'P', 2, sizeof(struct privcmd_mmap)) #define IOCTL_PRIVCMD_MMAPBATCH \ _IOC(_IOC_NONE, 'P', 3, sizeof(struct privcmd_mmapbatch)) +#define IOCTL_PRIVCMD_MMAPBATCH_V2 \ + _IOC(_IOC_NONE, 'P', 4, sizeof(struct privcmd_mmapbatch_v2)) #endif /* __LINUX_PUBLIC_PRIVCMD_H__ */ -- cgit v1.2.3-70-g09d2 From 1714df7f2cee6a741c3ed24231ec5db25b90633a Mon Sep 17 00:00:00 2001 From: Andres Lagar-Cavilla Date: Thu, 6 Sep 2012 13:24:39 -0400 Subject: xen/privcmd: Fix mmap batch ioctl error status copy back. Copy back of per-slot error codes is only necessary for V2. V1 does not provide an error array, so copyback will unconditionally set the global rc to EFAULT. Only copyback for V2. Signed-off-by: Andres Lagar-Cavilla Signed-off-by: Konrad Rzeszutek Wilk --- drivers/xen/privcmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/xen') diff --git a/drivers/xen/privcmd.c b/drivers/xen/privcmd.c index 92a285b1b96..3b162c65620 100644 --- a/drivers/xen/privcmd.c +++ b/drivers/xen/privcmd.c @@ -389,7 +389,7 @@ static long privcmd_ioctl_mmap_batch(void __user *udata, int version) state.err = err_array; ret = traverse_pages(m.num, sizeof(xen_pfn_t), &pagelist, mmap_return_errors_v1, &state); - } else + } else if (version == 2) ret = __copy_to_user(m.err, err_array, m.num * sizeof(int)); /* If we have not had any EFAULT-like global errors then set the global -- cgit v1.2.3-70-g09d2 From 1d3520357df99baf4ad89f86268ac96cd38092d9 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 7 Sep 2012 09:33:17 -0700 Subject: make drivers with pci error handlers const Covers the rest of the uses of pci error handler. Signed-off-by: Stephen Hemminger Signed-off-by: Bjorn Helgaas --- drivers/block/nvme.c | 2 +- drivers/infiniband/hw/qib/qib.h | 2 +- drivers/infiniband/hw/qib/qib_pcie.c | 2 +- drivers/media/dvb/ngene/ngene-cards.c | 2 +- drivers/tty/serial/8250/8250_pci.c | 2 +- drivers/tty/serial/jsm/jsm_driver.c | 2 +- drivers/xen/xen-pciback/pci_stub.c | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/xen') diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index 38a2d063188..c95ca0f8ff8 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -1675,7 +1675,7 @@ static void __devexit nvme_remove(struct pci_dev *pdev) #define nvme_suspend NULL #define nvme_resume NULL -static struct pci_error_handlers nvme_err_handler = { +static const struct pci_error_handlers nvme_err_handler = { .error_detected = nvme_error_detected, .mmio_enabled = nvme_dump_registers, .link_reset = nvme_link_reset, diff --git a/drivers/infiniband/hw/qib/qib.h b/drivers/infiniband/hw/qib/qib.h index 7b1b8669002..4d11575c201 100644 --- a/drivers/infiniband/hw/qib/qib.h +++ b/drivers/infiniband/hw/qib/qib.h @@ -87,7 +87,7 @@ struct qlogic_ib_stats { }; extern struct qlogic_ib_stats qib_stats; -extern struct pci_error_handlers qib_pci_err_handler; +extern const struct pci_error_handlers qib_pci_err_handler; extern struct pci_driver qib_driver; #define QIB_CHIP_SWVERSION QIB_CHIP_VERS_MAJ diff --git a/drivers/infiniband/hw/qib/qib_pcie.c b/drivers/infiniband/hw/qib/qib_pcie.c index 062c301ebf5..8fd03a8c735 100644 --- a/drivers/infiniband/hw/qib/qib_pcie.c +++ b/drivers/infiniband/hw/qib/qib_pcie.c @@ -753,7 +753,7 @@ qib_pci_resume(struct pci_dev *pdev) qib_init(dd, 1); /* same as re-init after reset */ } -struct pci_error_handlers qib_pci_err_handler = { +const struct pci_error_handlers qib_pci_err_handler = { .error_detected = qib_pci_error_detected, .mmio_enabled = qib_pci_mmio_enabled, .link_reset = qib_pci_link_reset, diff --git a/drivers/media/dvb/ngene/ngene-cards.c b/drivers/media/dvb/ngene/ngene-cards.c index 72ee8de0226..0a497be97af 100644 --- a/drivers/media/dvb/ngene/ngene-cards.c +++ b/drivers/media/dvb/ngene/ngene-cards.c @@ -524,7 +524,7 @@ static void ngene_resume(struct pci_dev *dev) printk(KERN_INFO DEVICE_NAME ": resume\n"); } -static struct pci_error_handlers ngene_errors = { +static const struct pci_error_handlers ngene_errors = { .error_detected = ngene_error_detected, .link_reset = ngene_link_reset, .slot_reset = ngene_slot_reset, diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index 28e7c7cce89..452278efef2 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -4236,7 +4236,7 @@ static void serial8250_io_resume(struct pci_dev *dev) pciserial_resume_ports(priv); } -static struct pci_error_handlers serial8250_err_handler = { +static const struct pci_error_handlers serial8250_err_handler = { .error_detected = serial8250_io_error_detected, .slot_reset = serial8250_io_slot_reset, .resume = serial8250_io_resume, diff --git a/drivers/tty/serial/jsm/jsm_driver.c b/drivers/tty/serial/jsm/jsm_driver.c index 7545fe1b992..5ab3c3b595e 100644 --- a/drivers/tty/serial/jsm/jsm_driver.c +++ b/drivers/tty/serial/jsm/jsm_driver.c @@ -54,7 +54,7 @@ static pci_ers_result_t jsm_io_error_detected(struct pci_dev *pdev, static pci_ers_result_t jsm_io_slot_reset(struct pci_dev *pdev); static void jsm_io_resume(struct pci_dev *pdev); -static struct pci_error_handlers jsm_err_handler = { +static const struct pci_error_handlers jsm_err_handler = { .error_detected = jsm_io_error_detected, .slot_reset = jsm_io_slot_reset, .resume = jsm_io_resume, diff --git a/drivers/xen/xen-pciback/pci_stub.c b/drivers/xen/xen-pciback/pci_stub.c index 097e536e867..0f1539edbd0 100644 --- a/drivers/xen/xen-pciback/pci_stub.c +++ b/drivers/xen/xen-pciback/pci_stub.c @@ -871,7 +871,7 @@ end: } /*add xen_pcibk AER handling*/ -static struct pci_error_handlers xen_pcibk_error_handler = { +static const struct pci_error_handlers xen_pcibk_error_handler = { .error_detected = xen_pcibk_error_detected, .mmio_enabled = xen_pcibk_mmio_enabled, .slot_reset = xen_pcibk_slot_reset, -- cgit v1.2.3-70-g09d2 From 9d2be9287107695708e6aae5105a8a518a6cb4d0 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 8 Sep 2012 12:57:35 +0300 Subject: xen/privcmd: return -EFAULT on error __copy_to_user() returns the number of bytes remaining to be copied but we want to return a negative error code here. Acked-by: Andres Lagar-Cavilla Signed-off-by: Dan Carpenter Signed-off-by: Konrad Rzeszutek Wilk --- drivers/xen/privcmd.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/xen') diff --git a/drivers/xen/privcmd.c b/drivers/xen/privcmd.c index 3b162c65620..ef6389580b8 100644 --- a/drivers/xen/privcmd.c +++ b/drivers/xen/privcmd.c @@ -389,8 +389,11 @@ static long privcmd_ioctl_mmap_batch(void __user *udata, int version) state.err = err_array; ret = traverse_pages(m.num, sizeof(xen_pfn_t), &pagelist, mmap_return_errors_v1, &state); - } else if (version == 2) + } else if (version == 2) { ret = __copy_to_user(m.err, err_array, m.num * sizeof(int)); + if (ret) + ret = -EFAULT; + } /* If we have not had any EFAULT-like global errors then set the global * error to -ENOENT if necessary. */ -- cgit v1.2.3-70-g09d2 From ecc635f90adfe1b7cd5fd354f49edfbf24aa4e3e Mon Sep 17 00:00:00 2001 From: Stefano Stabellini Date: Fri, 14 Sep 2012 12:13:12 +0100 Subject: xen/arm: compile and run xenbus bind_evtchn_to_irqhandler can legitimately return 0 (irq 0): it is not an error. If Linux is running as an HVM domain and is running as Dom0, use xenstored_local_init to initialize the xenstore page and event channel. Changes in v4: - do not xs_reset_watches on dom0. Changes in v2: - refactor xenbus_init. Signed-off-by: Stefano Stabellini [v5: Fixed case switch indentations] Signed-off-by: Konrad Rzeszutek Wilk --- drivers/xen/xenbus/xenbus_comms.c | 2 +- drivers/xen/xenbus/xenbus_probe.c | 52 ++++++++++++++++++++++++++++----------- drivers/xen/xenbus/xenbus_xs.c | 3 ++- 3 files changed, 41 insertions(+), 16 deletions(-) (limited to 'drivers/xen') diff --git a/drivers/xen/xenbus/xenbus_comms.c b/drivers/xen/xenbus/xenbus_comms.c index 52fe7ad0766..c5aa55c5d37 100644 --- a/drivers/xen/xenbus/xenbus_comms.c +++ b/drivers/xen/xenbus/xenbus_comms.c @@ -224,7 +224,7 @@ int xb_init_comms(void) int err; err = bind_evtchn_to_irqhandler(xen_store_evtchn, wake_waiting, 0, "xenbus", &xb_waitq); - if (err <= 0) { + if (err < 0) { printk(KERN_ERR "XENBUS request irq failed %i\n", err); return err; } diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c index 91d3d6544a7..038b71dbf03 100644 --- a/drivers/xen/xenbus/xenbus_probe.c +++ b/drivers/xen/xenbus/xenbus_probe.c @@ -719,17 +719,47 @@ static int __init xenstored_local_init(void) return err; } +enum xenstore_init { + UNKNOWN, + PV, + HVM, + LOCAL, +}; static int __init xenbus_init(void) { int err = 0; + enum xenstore_init usage = UNKNOWN; + uint64_t v = 0; if (!xen_domain()) return -ENODEV; xenbus_ring_ops_init(); - if (xen_hvm_domain()) { - uint64_t v = 0; + if (xen_pv_domain()) + usage = PV; + if (xen_hvm_domain()) + usage = HVM; + if (xen_hvm_domain() && xen_initial_domain()) + usage = LOCAL; + if (xen_pv_domain() && !xen_start_info->store_evtchn) + usage = LOCAL; + if (xen_pv_domain() && xen_start_info->store_evtchn) + xenstored_ready = 1; + + switch (usage) { + case LOCAL: + err = xenstored_local_init(); + if (err) + goto out_error; + xen_store_interface = mfn_to_virt(xen_store_mfn); + break; + case PV: + xen_store_evtchn = xen_start_info->store_evtchn; + xen_store_mfn = xen_start_info->store_mfn; + xen_store_interface = mfn_to_virt(xen_store_mfn); + break; + case HVM: err = hvm_get_parameter(HVM_PARAM_STORE_EVTCHN, &v); if (err) goto out_error; @@ -738,18 +768,12 @@ static int __init xenbus_init(void) if (err) goto out_error; xen_store_mfn = (unsigned long)v; - xen_store_interface = ioremap(xen_store_mfn << PAGE_SHIFT, PAGE_SIZE); - } else { - xen_store_evtchn = xen_start_info->store_evtchn; - xen_store_mfn = xen_start_info->store_mfn; - if (xen_store_evtchn) - xenstored_ready = 1; - else { - err = xenstored_local_init(); - if (err) - goto out_error; - } - xen_store_interface = mfn_to_virt(xen_store_mfn); + xen_store_interface = + ioremap(xen_store_mfn << PAGE_SHIFT, PAGE_SIZE); + break; + default: + pr_warn("Xenstore state unknown\n"); + break; } /* Initialize the interface to xenstore. */ diff --git a/drivers/xen/xenbus/xenbus_xs.c b/drivers/xen/xenbus/xenbus_xs.c index bce15cf4a8d..131dec04794 100644 --- a/drivers/xen/xenbus/xenbus_xs.c +++ b/drivers/xen/xenbus/xenbus_xs.c @@ -44,6 +44,7 @@ #include #include #include +#include #include #include #include "xenbus_comms.h" @@ -622,7 +623,7 @@ static void xs_reset_watches(void) { int err, supported = 0; - if (!xen_hvm_domain()) + if (!xen_hvm_domain() || xen_initial_domain()) return; err = xenbus_scanf(XBT_NIL, "control", -- cgit v1.2.3-70-g09d2 From 1cef36a529f44dbb3612ee0deeb0b5563de36163 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Thu, 23 Aug 2012 13:55:26 -0400 Subject: xen/swiotlb: Move the nr_tbl determination in its own function. Moving the function out of the way to prepare for the late SWIOTLB init. Acked-by: Stefano Stabellini Signed-off-by: Konrad Rzeszutek Wilk --- drivers/xen/swiotlb-xen.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'drivers/xen') diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c index 1afb4fba11b..a2aad6ec240 100644 --- a/drivers/xen/swiotlb-xen.c +++ b/drivers/xen/swiotlb-xen.c @@ -144,25 +144,26 @@ xen_swiotlb_fixup(void *buf, size_t size, unsigned long nslabs) } while (i < nslabs); return 0; } +static unsigned long xen_set_nslabs(unsigned long nr_tbl) +{ + if (!nr_tbl) { + xen_io_tlb_nslabs = (64 * 1024 * 1024 >> IO_TLB_SHIFT); + xen_io_tlb_nslabs = ALIGN(xen_io_tlb_nslabs, IO_TLB_SEGSIZE); + } else + xen_io_tlb_nslabs = nr_tbl; + return xen_io_tlb_nslabs << IO_TLB_SHIFT; +} void __init xen_swiotlb_init(int verbose) { unsigned long bytes; int rc = -ENOMEM; - unsigned long nr_tbl; char *m = NULL; unsigned int repeat = 3; - nr_tbl = swiotlb_nr_tbl(); - if (nr_tbl) - xen_io_tlb_nslabs = nr_tbl; - else { - xen_io_tlb_nslabs = (64 * 1024 * 1024 >> IO_TLB_SHIFT); - xen_io_tlb_nslabs = ALIGN(xen_io_tlb_nslabs, IO_TLB_SEGSIZE); - } + xen_io_tlb_nslabs = swiotlb_nr_tbl(); retry: - bytes = xen_io_tlb_nslabs << IO_TLB_SHIFT; - + bytes = xen_set_nslabs(xen_io_tlb_nslabs); /* * Get IO TLB memory from any location. */ -- cgit v1.2.3-70-g09d2 From 5bab7864b1167f9a72d375f6854027db436a1cc1 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Thu, 23 Aug 2012 14:03:55 -0400 Subject: xen/swiotlb: Move the error strings to its own function. That way we can more easily reuse those errors when using the late SWIOTLB init. Acked-by: Stefano Stabellini Signed-off-by: Konrad Rzeszutek Wilk --- drivers/xen/swiotlb-xen.c | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) (limited to 'drivers/xen') diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c index a2aad6ec240..701b1035fa6 100644 --- a/drivers/xen/swiotlb-xen.c +++ b/drivers/xen/swiotlb-xen.c @@ -154,11 +154,33 @@ static unsigned long xen_set_nslabs(unsigned long nr_tbl) return xen_io_tlb_nslabs << IO_TLB_SHIFT; } + +enum xen_swiotlb_err { + XEN_SWIOTLB_UNKNOWN = 0, + XEN_SWIOTLB_ENOMEM, + XEN_SWIOTLB_EFIXUP +}; + +static const char *xen_swiotlb_error(enum xen_swiotlb_err err) +{ + switch (err) { + case XEN_SWIOTLB_ENOMEM: + return "Cannot allocate Xen-SWIOTLB buffer\n"; + case XEN_SWIOTLB_EFIXUP: + return "Failed to get contiguous memory for DMA from Xen!\n"\ + "You either: don't have the permissions, do not have"\ + " enough free memory under 4GB, or the hypervisor memory"\ + " is too fragmented!"; + default: + break; + } + return ""; +} void __init xen_swiotlb_init(int verbose) { unsigned long bytes; int rc = -ENOMEM; - char *m = NULL; + enum xen_swiotlb_err m_ret = XEN_SWIOTLB_UNKNOWN; unsigned int repeat = 3; xen_io_tlb_nslabs = swiotlb_nr_tbl(); @@ -169,7 +191,7 @@ retry: */ xen_io_tlb_start = alloc_bootmem_pages(PAGE_ALIGN(bytes)); if (!xen_io_tlb_start) { - m = "Cannot allocate Xen-SWIOTLB buffer!\n"; + m_ret = XEN_SWIOTLB_ENOMEM; goto error; } xen_io_tlb_end = xen_io_tlb_start + bytes; @@ -181,10 +203,7 @@ retry: xen_io_tlb_nslabs); if (rc) { free_bootmem(__pa(xen_io_tlb_start), PAGE_ALIGN(bytes)); - m = "Failed to get contiguous memory for DMA from Xen!\n"\ - "You either: don't have the permissions, do not have"\ - " enough free memory under 4GB, or the hypervisor memory"\ - "is too fragmented!"; + m_ret = XEN_SWIOTLB_EFIXUP; goto error; } start_dma_addr = xen_virt_to_bus(xen_io_tlb_start); @@ -199,8 +218,8 @@ error: (xen_io_tlb_nslabs << IO_TLB_SHIFT) >> 20); goto retry; } - xen_raw_printk("%s (rc:%d)", m, rc); - panic("%s (rc:%d)", m, rc); + xen_raw_printk("%s (rc:%d)", xen_swiotlb_error(m_ret), rc); + panic("%s (rc:%d)", xen_swiotlb_error(m_ret), rc); } void * -- cgit v1.2.3-70-g09d2 From b82776005369899c1c7ca2e4b2414bb64b538d2c Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Thu, 23 Aug 2012 14:36:15 -0400 Subject: xen/swiotlb: Use the swiotlb_late_init_with_tbl to init Xen-SWIOTLB late when PV PCI is used. With this patch we provide the functionality to initialize the Xen-SWIOTLB late in the bootup cycle - specifically for Xen PCI-frontend. We still will work if the user had supplied 'iommu=soft' on the Linux command line. Note: We cannot depend on after_bootmem to automatically determine whether this is early or not. This is because when PCI IOMMUs are initialized it is after after_bootmem but before a lot of "other" subsystems are initialized. CC: FUJITA Tomonori [v1: Fix smatch warnings] [v2: Added check for xen_swiotlb] [v3: Rebased with new xen-swiotlb changes] [v4: squashed xen/swiotlb: Depending on after_bootmem is not correct in] Reviewed-by: Stefano Stabellini Signed-off-by: Konrad Rzeszutek Wilk --- arch/x86/include/asm/xen/swiotlb-xen.h | 2 ++ arch/x86/xen/pci-swiotlb-xen.c | 24 +++++++++++++++-- drivers/xen/swiotlb-xen.c | 48 +++++++++++++++++++++++++++------- include/xen/swiotlb-xen.h | 2 +- 4 files changed, 63 insertions(+), 13 deletions(-) (limited to 'drivers/xen') diff --git a/arch/x86/include/asm/xen/swiotlb-xen.h b/arch/x86/include/asm/xen/swiotlb-xen.h index 1be1ab7d6a4..ee52fcac6f7 100644 --- a/arch/x86/include/asm/xen/swiotlb-xen.h +++ b/arch/x86/include/asm/xen/swiotlb-xen.h @@ -5,10 +5,12 @@ extern int xen_swiotlb; extern int __init pci_xen_swiotlb_detect(void); extern void __init pci_xen_swiotlb_init(void); +extern int pci_xen_swiotlb_init_late(void); #else #define xen_swiotlb (0) static inline int __init pci_xen_swiotlb_detect(void) { return 0; } static inline void __init pci_xen_swiotlb_init(void) { } +static inline int pci_xen_swiotlb_init_late(void) { return -ENXIO; } #endif #endif /* _ASM_X86_SWIOTLB_XEN_H */ diff --git a/arch/x86/xen/pci-swiotlb-xen.c b/arch/x86/xen/pci-swiotlb-xen.c index 1c1722761ee..b152640d838 100644 --- a/arch/x86/xen/pci-swiotlb-xen.c +++ b/arch/x86/xen/pci-swiotlb-xen.c @@ -12,7 +12,7 @@ #include #include #endif - +#include int xen_swiotlb __read_mostly; static struct dma_map_ops xen_swiotlb_dma_ops = { @@ -69,13 +69,33 @@ int __init pci_xen_swiotlb_detect(void) void __init pci_xen_swiotlb_init(void) { if (xen_swiotlb) { - xen_swiotlb_init(1); + xen_swiotlb_init(1, true /* early */); dma_ops = &xen_swiotlb_dma_ops; /* Make sure ACS will be enabled */ pci_request_acs(); } } + +int pci_xen_swiotlb_init_late(void) +{ + int rc; + + if (xen_swiotlb) + return 0; + + rc = xen_swiotlb_init(1, false /* late */); + if (rc) + return rc; + + dma_ops = &xen_swiotlb_dma_ops; + /* Make sure ACS will be enabled */ + pci_request_acs(); + + return 0; +} +EXPORT_SYMBOL_GPL(pci_xen_swiotlb_init_late); + IOMMU_INIT_FINISH(pci_xen_swiotlb_detect, 0, pci_xen_swiotlb_init, diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c index 701b1035fa6..7461edb5118 100644 --- a/drivers/xen/swiotlb-xen.c +++ b/drivers/xen/swiotlb-xen.c @@ -176,9 +176,9 @@ static const char *xen_swiotlb_error(enum xen_swiotlb_err err) } return ""; } -void __init xen_swiotlb_init(int verbose) +int __ref xen_swiotlb_init(int verbose, bool early) { - unsigned long bytes; + unsigned long bytes, order; int rc = -ENOMEM; enum xen_swiotlb_err m_ret = XEN_SWIOTLB_UNKNOWN; unsigned int repeat = 3; @@ -186,10 +186,28 @@ void __init xen_swiotlb_init(int verbose) xen_io_tlb_nslabs = swiotlb_nr_tbl(); retry: bytes = xen_set_nslabs(xen_io_tlb_nslabs); + order = get_order(xen_io_tlb_nslabs << IO_TLB_SHIFT); /* * Get IO TLB memory from any location. */ - xen_io_tlb_start = alloc_bootmem_pages(PAGE_ALIGN(bytes)); + if (early) + xen_io_tlb_start = alloc_bootmem_pages(PAGE_ALIGN(bytes)); + else { +#define SLABS_PER_PAGE (1 << (PAGE_SHIFT - IO_TLB_SHIFT)) +#define IO_TLB_MIN_SLABS ((1<<20) >> IO_TLB_SHIFT) + while ((SLABS_PER_PAGE << order) > IO_TLB_MIN_SLABS) { + xen_io_tlb_start = (void *)__get_free_pages(__GFP_NOWARN, order); + if (xen_io_tlb_start) + break; + order--; + } + if (order != get_order(bytes)) { + pr_warn("Warning: only able to allocate %ld MB " + "for software IO TLB\n", (PAGE_SIZE << order) >> 20); + xen_io_tlb_nslabs = SLABS_PER_PAGE << order; + bytes = xen_io_tlb_nslabs << IO_TLB_SHIFT; + } + } if (!xen_io_tlb_start) { m_ret = XEN_SWIOTLB_ENOMEM; goto error; @@ -202,14 +220,21 @@ retry: bytes, xen_io_tlb_nslabs); if (rc) { - free_bootmem(__pa(xen_io_tlb_start), PAGE_ALIGN(bytes)); + if (early) + free_bootmem(__pa(xen_io_tlb_start), PAGE_ALIGN(bytes)); + else { + free_pages((unsigned long)xen_io_tlb_start, order); + xen_io_tlb_start = NULL; + } m_ret = XEN_SWIOTLB_EFIXUP; goto error; } start_dma_addr = xen_virt_to_bus(xen_io_tlb_start); - swiotlb_init_with_tbl(xen_io_tlb_start, xen_io_tlb_nslabs, verbose); - - return; + if (early) + swiotlb_init_with_tbl(xen_io_tlb_start, xen_io_tlb_nslabs, verbose); + else + rc = swiotlb_late_init_with_tbl(xen_io_tlb_start, xen_io_tlb_nslabs); + return rc; error: if (repeat--) { xen_io_tlb_nslabs = max(1024UL, /* Min is 2MB */ @@ -218,10 +243,13 @@ error: (xen_io_tlb_nslabs << IO_TLB_SHIFT) >> 20); goto retry; } - xen_raw_printk("%s (rc:%d)", xen_swiotlb_error(m_ret), rc); - panic("%s (rc:%d)", xen_swiotlb_error(m_ret), rc); + pr_err("%s (rc:%d)", xen_swiotlb_error(m_ret), rc); + if (early) + panic("%s (rc:%d)", xen_swiotlb_error(m_ret), rc); + else + free_pages((unsigned long)xen_io_tlb_start, order); + return rc; } - void * xen_swiotlb_alloc_coherent(struct device *hwdev, size_t size, dma_addr_t *dma_handle, gfp_t flags, diff --git a/include/xen/swiotlb-xen.h b/include/xen/swiotlb-xen.h index 4f4d449f00f..289ee509bda 100644 --- a/include/xen/swiotlb-xen.h +++ b/include/xen/swiotlb-xen.h @@ -3,7 +3,7 @@ #include -extern void xen_swiotlb_init(int verbose); +extern int xen_swiotlb_init(int verbose, bool early); extern void *xen_swiotlb_alloc_coherent(struct device *hwdev, size_t size, -- cgit v1.2.3-70-g09d2 From c468bdee28a1cb61d9b7a8ce9859d17dee43b7d7 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Mon, 17 Sep 2012 10:20:09 -0400 Subject: xen/swiotlb: For early initialization, return zero on success. If everything is setup properly we would return -ENOMEM since rc by default is set to that value. Lets not do that and return a proper return code. Note: The reason the early code needs this special treatment is that it SWIOTLB library call does not return anything (and had it failed it would call panic()) - but our function does. Acked-by: Stefano Stabellini Signed-off-by: Konrad Rzeszutek Wilk --- drivers/xen/swiotlb-xen.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/xen') diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c index 7461edb5118..b70f2d19ab9 100644 --- a/drivers/xen/swiotlb-xen.c +++ b/drivers/xen/swiotlb-xen.c @@ -230,9 +230,10 @@ retry: goto error; } start_dma_addr = xen_virt_to_bus(xen_io_tlb_start); - if (early) + if (early) { swiotlb_init_with_tbl(xen_io_tlb_start, xen_io_tlb_nslabs, verbose); - else + rc = 0; + } else rc = swiotlb_late_init_with_tbl(xen_io_tlb_start, xen_io_tlb_nslabs); return rc; error: -- cgit v1.2.3-70-g09d2 From e815f45e6e5fe40ca3049987eab80d89d5781f03 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Mon, 13 Aug 2012 13:26:11 -0400 Subject: xen/swiotlb: Remove functions not needed anymore. Sparse warns us off: drivers/xen/swiotlb-xen.c:506:1: warning: symbol 'xen_swiotlb_map_sg' was not declared. Should it be static? drivers/xen/swiotlb-xen.c:534:1: warning: symbol 'xen_swiotlb_unmap_sg' was not declared. Should it be static? and it looks like we do not need this function at all. Acked-by: Stefano Stabellini Signed-off-by: Konrad Rzeszutek Wilk --- drivers/xen/swiotlb-xen.c | 16 ---------------- include/xen/swiotlb-xen.h | 9 --------- 2 files changed, 25 deletions(-) (limited to 'drivers/xen') diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c index b70f2d19ab9..ab4c66c19c1 100644 --- a/drivers/xen/swiotlb-xen.c +++ b/drivers/xen/swiotlb-xen.c @@ -515,14 +515,6 @@ xen_swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl, } EXPORT_SYMBOL_GPL(xen_swiotlb_map_sg_attrs); -int -xen_swiotlb_map_sg(struct device *hwdev, struct scatterlist *sgl, int nelems, - enum dma_data_direction dir) -{ - return xen_swiotlb_map_sg_attrs(hwdev, sgl, nelems, dir, NULL); -} -EXPORT_SYMBOL_GPL(xen_swiotlb_map_sg); - /* * Unmap a set of streaming mode DMA translations. Again, cpu read rules * concerning calls here are the same as for swiotlb_unmap_page() above. @@ -543,14 +535,6 @@ xen_swiotlb_unmap_sg_attrs(struct device *hwdev, struct scatterlist *sgl, } EXPORT_SYMBOL_GPL(xen_swiotlb_unmap_sg_attrs); -void -xen_swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sgl, int nelems, - enum dma_data_direction dir) -{ - return xen_swiotlb_unmap_sg_attrs(hwdev, sgl, nelems, dir, NULL); -} -EXPORT_SYMBOL_GPL(xen_swiotlb_unmap_sg); - /* * Make physical memory consistent for a set of streaming mode DMA translations * after a transfer. diff --git a/include/xen/swiotlb-xen.h b/include/xen/swiotlb-xen.h index 289ee509bda..de8bcc641c4 100644 --- a/include/xen/swiotlb-xen.h +++ b/include/xen/swiotlb-xen.h @@ -23,15 +23,6 @@ extern dma_addr_t xen_swiotlb_map_page(struct device *dev, struct page *page, extern void xen_swiotlb_unmap_page(struct device *hwdev, dma_addr_t dev_addr, size_t size, enum dma_data_direction dir, struct dma_attrs *attrs); -/* -extern int -xen_swiotlb_map_sg(struct device *hwdev, struct scatterlist *sg, int nents, - enum dma_data_direction dir); - -extern void -xen_swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sg, int nents, - enum dma_data_direction dir); -*/ extern int xen_swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl, int nelems, enum dma_data_direction dir, -- cgit v1.2.3-70-g09d2 From c3cb4709809e655a4ba5a716086c8bc5bbbbccdb Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Tue, 18 Sep 2012 12:29:03 +0100 Subject: xen-pciback: support wild cards in slot specifications Particularly for hiding sets of SR-IOV devices, specifying them all individually is rather cumbersome. Therefore, allow function and slot numbers to be replaced by a wildcard character ('*'). Unfortunately this gets complicated by the in-kernel sscanf() implementation not being really standard conformant - matching of plain text tails cannot be checked by the caller (a patch to overcome this will be sent shortly, and a follow-up patch for simplifying the code is planned to be sent when that fixed went upstream). Signed-off-by: Jan Beulich Signed-off-by: Konrad Rzeszutek Wilk --- drivers/xen/xen-pciback/pci_stub.c | 89 +++++++++++++++++++++++++++++++++++--- 1 file changed, 82 insertions(+), 7 deletions(-) (limited to 'drivers/xen') diff --git a/drivers/xen/xen-pciback/pci_stub.c b/drivers/xen/xen-pciback/pci_stub.c index 03342728bf2..20e1c42c1c4 100644 --- a/drivers/xen/xen-pciback/pci_stub.c +++ b/drivers/xen/xen-pciback/pci_stub.c @@ -897,17 +897,41 @@ static inline int str_to_slot(const char *buf, int *domain, int *bus, int *slot, int *func) { int err; + char wc = '*'; err = sscanf(buf, " %x:%x:%x.%x", domain, bus, slot, func); - if (err == 4) + switch (err) { + case 3: + *func = -1; + err = sscanf(buf, " %x:%x:%x.%c", domain, bus, slot, &wc); + break; + case 2: + *slot = *func = -1; + err = sscanf(buf, " %x:%x:*.%c", domain, bus, &wc); + if (err >= 2) + ++err; + break; + } + if (err == 4 && wc == '*') return 0; else if (err < 0) return -EINVAL; /* try again without domain */ *domain = 0; + wc = '*'; err = sscanf(buf, " %x:%x.%x", bus, slot, func); - if (err == 3) + switch (err) { + case 2: + *func = -1; + err = sscanf(buf, " %x:%x.%c", bus, slot, &wc); + break; + case 1: + *slot = *func = -1; + err = sscanf(buf, " %x:*.%c", bus, &wc) + 1; + break; + } + if (err == 3 && wc == '*') return 0; return -EINVAL; @@ -930,6 +954,19 @@ static int pcistub_device_id_add(int domain, int bus, int slot, int func) { struct pcistub_device_id *pci_dev_id; unsigned long flags; + int rc = 0; + + if (slot < 0) { + for (slot = 0; !rc && slot < 32; ++slot) + rc = pcistub_device_id_add(domain, bus, slot, func); + return rc; + } + + if (func < 0) { + for (func = 0; !rc && func < 8; ++func) + rc = pcistub_device_id_add(domain, bus, slot, func); + return rc; + } pci_dev_id = kmalloc(sizeof(*pci_dev_id), GFP_KERNEL); if (!pci_dev_id) @@ -952,15 +989,15 @@ static int pcistub_device_id_add(int domain, int bus, int slot, int func) static int pcistub_device_id_remove(int domain, int bus, int slot, int func) { struct pcistub_device_id *pci_dev_id, *t; - int devfn = PCI_DEVFN(slot, func); int err = -ENOENT; unsigned long flags; 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 - && pci_dev_id->bus == bus && pci_dev_id->devfn == devfn) { + if (pci_dev_id->domain == domain && pci_dev_id->bus == bus + && (slot < 0 || PCI_SLOT(pci_dev_id->devfn) == slot) + && (func < 0 || PCI_FUNC(pci_dev_id->devfn) == func)) { /* Don't break; here because it's possible the same * slot could be in the list more than once */ @@ -1216,6 +1253,10 @@ static ssize_t permissive_add(struct device_driver *drv, const char *buf, err = str_to_slot(buf, &domain, &bus, &slot, &func); if (err) goto out; + if (slot < 0 || func < 0) { + err = -EINVAL; + goto out; + } psdev = pcistub_device_find(domain, bus, slot, func); if (!psdev) { err = -ENODEV; @@ -1297,17 +1338,51 @@ static int __init pcistub_init(void) if (pci_devs_to_hide && *pci_devs_to_hide) { do { + char wc = '*'; + parsed = 0; err = sscanf(pci_devs_to_hide + pos, " (%x:%x:%x.%x) %n", &domain, &bus, &slot, &func, &parsed); - if (err != 4) { + switch (err) { + case 3: + func = -1; + err = sscanf(pci_devs_to_hide + pos, + " (%x:%x:%x.%c) %n", + &domain, &bus, &slot, &wc, + &parsed); + break; + case 2: + slot = func = -1; + err = sscanf(pci_devs_to_hide + pos, + " (%x:%x:*.%c) %n", + &domain, &bus, &wc, &parsed) + 1; + break; + } + + if (err != 4 || wc != '*') { domain = 0; + wc = '*'; err = sscanf(pci_devs_to_hide + pos, " (%x:%x.%x) %n", &bus, &slot, &func, &parsed); - if (err != 3) + switch (err) { + case 2: + func = -1; + err = sscanf(pci_devs_to_hide + pos, + " (%x:%x.%c) %n", + &bus, &slot, &wc, + &parsed); + break; + case 1: + slot = func = -1; + err = sscanf(pci_devs_to_hide + pos, + " (%x:*.%c) %n", + &bus, &wc, &parsed) + 1; + break; + } + if (err != 3 || wc != '*') goto parse_error; } -- cgit v1.2.3-70-g09d2 From 9fa5780beea1274d498a224822397100022da7d4 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Tue, 18 Sep 2012 12:23:02 +0100 Subject: USB EHCI/Xen: propagate controller reset information to hypervisor Just like for the in-tree early console debug port driver, the hypervisor - when using a debug port based console - also needs to be told about controller resets, so it can suppress using and then re-initialize the debug port accordingly. Other than the in-tree driver, the hypervisor driver actually cares about doing this only for the device where the debug is port actually in use, i.e. it needs to be told the coordinates of the device being reset (quite obviously, leveraging the addition done for that would likely benefit the in-tree driver too). Signed-off-by: Jan Beulich Acked-by: Konrad Rzeszutek Wilk Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/early/ehci-dbgp.c | 17 +++++++++++---- drivers/usb/host/ehci-hcd.c | 4 ++-- drivers/usb/host/ehci-hub.c | 4 ++-- drivers/xen/Makefile | 2 +- drivers/xen/dbgp.c | 48 +++++++++++++++++++++++++++++++++++++++++ include/linux/usb/ehci_def.h | 29 +++++++++++++++++++------ include/xen/interface/physdev.h | 16 ++++++++++++++ 7 files changed, 105 insertions(+), 15 deletions(-) create mode 100644 drivers/xen/dbgp.c (limited to 'drivers/xen') diff --git a/drivers/usb/early/ehci-dbgp.c b/drivers/usb/early/ehci-dbgp.c index 89dcf155d57..e426ad626d7 100644 --- a/drivers/usb/early/ehci-dbgp.c +++ b/drivers/usb/early/ehci-dbgp.c @@ -491,7 +491,7 @@ static int ehci_wait_for_port(int port); * Return -ENODEV for any general failure * Return -EIO if wait for port fails */ -int dbgp_external_startup(void) +static int _dbgp_external_startup(void) { int devnum; struct usb_debug_descriptor dbgp_desc; @@ -613,6 +613,11 @@ err: goto try_again; return -ENODEV; } + +int dbgp_external_startup(struct usb_hcd *hcd) +{ + return xen_dbgp_external_startup(hcd) ?: _dbgp_external_startup(); +} EXPORT_SYMBOL_GPL(dbgp_external_startup); static int ehci_reset_port(int port) @@ -804,7 +809,7 @@ try_next_port: dbgp_ehci_status("ehci skip - already configured"); } - ret = dbgp_external_startup(); + ret = _dbgp_external_startup(); if (ret == -EIO) goto next_debug_port; @@ -934,7 +939,7 @@ static void early_dbgp_write(struct console *con, const char *str, u32 n) ctrl = readl(&ehci_debug->control); if (!(ctrl & DBGP_ENABLED)) { dbgp_not_safe = 1; - dbgp_external_startup(); + _dbgp_external_startup(); } else { cmd |= CMD_RUN; writel(cmd, &ehci_regs->command); @@ -974,10 +979,14 @@ struct console early_dbgp_console = { .index = -1, }; -int dbgp_reset_prep(void) +int dbgp_reset_prep(struct usb_hcd *hcd) { + int ret = xen_dbgp_reset_prep(hcd); u32 ctrl; + if (ret) + return ret; + dbgp_not_safe = 1; if (!ehci_debug) return 0; diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index b05c6865b61..6bf6c42481e 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -228,7 +228,7 @@ static int ehci_reset (struct ehci_hcd *ehci) /* If the EHCI debug controller is active, special care must be * taken before and after a host controller reset */ - if (ehci->debug && !dbgp_reset_prep()) + if (ehci->debug && !dbgp_reset_prep(ehci_to_hcd(ehci))) ehci->debug = NULL; command |= CMD_RESET; @@ -251,7 +251,7 @@ static int ehci_reset (struct ehci_hcd *ehci) tdi_reset (ehci); if (ehci->debug) - dbgp_external_startup(); + dbgp_external_startup(ehci_to_hcd(ehci)); ehci->port_c_suspend = ehci->suspended_ports = ehci->resuming_ports = 0; diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index c7880223738..914ce9370e7 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -353,10 +353,10 @@ static int ehci_bus_resume (struct usb_hcd *hcd) goto shutdown; if (unlikely(ehci->debug)) { - if (!dbgp_reset_prep()) + if (!dbgp_reset_prep(hcd)) ehci->debug = NULL; else - dbgp_external_startup(); + dbgp_external_startup(hcd); } /* Ideally and we've got a real resume here, and no port's power diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile index d80bea5535a..a4a3cab2f45 100644 --- a/drivers/xen/Makefile +++ b/drivers/xen/Makefile @@ -18,7 +18,7 @@ obj-$(CONFIG_XEN_PVHVM) += platform-pci.o obj-$(CONFIG_XEN_TMEM) += tmem.o obj-$(CONFIG_SWIOTLB_XEN) += swiotlb-xen.o obj-$(CONFIG_XEN_DOM0) += pcpu.o -obj-$(CONFIG_XEN_DOM0) += pci.o acpi.o +obj-$(CONFIG_XEN_DOM0) += pci.o dbgp.o acpi.o obj-$(CONFIG_XEN_MCE_LOG) += mcelog.o obj-$(CONFIG_XEN_PCIDEV_BACKEND) += xen-pciback/ obj-$(CONFIG_XEN_PRIVCMD) += xen-privcmd.o diff --git a/drivers/xen/dbgp.c b/drivers/xen/dbgp.c new file mode 100644 index 00000000000..42569c77ccc --- /dev/null +++ b/drivers/xen/dbgp.c @@ -0,0 +1,48 @@ +#include +#include +#include +#include +#include +#include +#include + +static int xen_dbgp_op(struct usb_hcd *hcd, int op) +{ + const struct device *ctrlr = hcd_to_bus(hcd)->controller; + struct physdev_dbgp_op dbgp; + + if (!xen_initial_domain()) + return 0; + + dbgp.op = op; + +#ifdef CONFIG_PCI + if (ctrlr->bus == &pci_bus_type) { + const struct pci_dev *pdev = to_pci_dev(ctrlr); + + dbgp.u.pci.seg = pci_domain_nr(pdev->bus); + dbgp.u.pci.bus = pdev->bus->number; + dbgp.u.pci.devfn = pdev->devfn; + dbgp.bus = PHYSDEVOP_DBGP_BUS_PCI; + } else +#endif + dbgp.bus = PHYSDEVOP_DBGP_BUS_UNKNOWN; + + return HYPERVISOR_physdev_op(PHYSDEVOP_dbgp_op, &dbgp); +} + +int xen_dbgp_reset_prep(struct usb_hcd *hcd) +{ + return xen_dbgp_op(hcd, PHYSDEVOP_DBGP_RESET_PREPARE); +} + +int xen_dbgp_external_startup(struct usb_hcd *hcd) +{ + return xen_dbgp_op(hcd, PHYSDEVOP_DBGP_RESET_DONE); +} + +#ifndef CONFIG_EARLY_PRINTK_DBGP +#include +EXPORT_SYMBOL_GPL(xen_dbgp_reset_prep); +EXPORT_SYMBOL_GPL(xen_dbgp_external_startup); +#endif diff --git a/include/linux/usb/ehci_def.h b/include/linux/usb/ehci_def.h index de4b9ed5d5d..9a446302b65 100644 --- a/include/linux/usb/ehci_def.h +++ b/include/linux/usb/ehci_def.h @@ -221,18 +221,35 @@ extern int __init early_dbgp_init(char *s); extern struct console early_dbgp_console; #endif /* CONFIG_EARLY_PRINTK_DBGP */ +struct usb_hcd; + +#ifdef CONFIG_XEN_DOM0 +extern int xen_dbgp_reset_prep(struct usb_hcd *); +extern int xen_dbgp_external_startup(struct usb_hcd *); +#else +static inline int xen_dbgp_reset_prep(struct usb_hcd *hcd) +{ + return 1; /* Shouldn't this be 0? */ +} + +static inline int xen_dbgp_external_startup(struct usb_hcd *hcd) +{ + return -1; +} +#endif + #ifdef CONFIG_EARLY_PRINTK_DBGP /* Call backs from ehci host driver to ehci debug driver */ -extern int dbgp_external_startup(void); -extern int dbgp_reset_prep(void); +extern int dbgp_external_startup(struct usb_hcd *); +extern int dbgp_reset_prep(struct usb_hcd *hcd); #else -static inline int dbgp_reset_prep(void) +static inline int dbgp_reset_prep(struct usb_hcd *hcd) { - return 1; + return xen_dbgp_reset_prep(hcd); } -static inline int dbgp_external_startup(void) +static inline int dbgp_external_startup(struct usb_hcd *hcd) { - return -1; + return xen_dbgp_external_startup(hcd); } #endif diff --git a/include/xen/interface/physdev.h b/include/xen/interface/physdev.h index 9ce788d8cf4..bfa1d50fe15 100644 --- a/include/xen/interface/physdev.h +++ b/include/xen/interface/physdev.h @@ -258,6 +258,22 @@ struct physdev_pci_device { uint8_t devfn; }; +#define PHYSDEVOP_DBGP_RESET_PREPARE 1 +#define PHYSDEVOP_DBGP_RESET_DONE 2 + +#define PHYSDEVOP_DBGP_BUS_UNKNOWN 0 +#define PHYSDEVOP_DBGP_BUS_PCI 1 + +#define PHYSDEVOP_dbgp_op 29 +struct physdev_dbgp_op { + /* IN */ + uint8_t op; + uint8_t bus; + union { + struct physdev_pci_device pci; + } u; +}; + /* * Notify that some PIRQ-bound event channels have been unmasked. * ** This command is obsolete since interface version 0x00030202 and is ** -- cgit v1.2.3-70-g09d2 From 9a11f4513c2e308e0025a55b465d377438606445 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Tue, 7 Feb 2012 16:29:19 -0800 Subject: userns: Convert xenfs to use kuid and kgid where appropriate Cc: Ian Campbell Cc: Konrad Rzeszutek Wilk Acked-by: Serge Hallyn Signed-off-by: Eric W. Biederman --- drivers/xen/xenfs/super.c | 3 ++- init/Kconfig | 2 -- 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/xen') diff --git a/drivers/xen/xenfs/super.c b/drivers/xen/xenfs/super.c index a84b53c0143..459b9ac45cf 100644 --- a/drivers/xen/xenfs/super.c +++ b/drivers/xen/xenfs/super.c @@ -30,7 +30,8 @@ static struct inode *xenfs_make_inode(struct super_block *sb, int mode) if (ret) { ret->i_mode = mode; - ret->i_uid = ret->i_gid = 0; + ret->i_uid = GLOBAL_ROOT_UID; + ret->i_gid = GLOBAL_ROOT_GID; ret->i_blocks = 0; ret->i_atime = ret->i_mtime = ret->i_ctime = CURRENT_TIME; } diff --git a/init/Kconfig b/init/Kconfig index 7ee6e19632d..485c60ae2ae 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -932,8 +932,6 @@ config UIDGID_CONVERTED depends on NET_9P = n # Filesystems - depends on XENFS = n - depends on 9P_FS = n depends on ADFS_FS = n depends on AFFS_FS = n -- cgit v1.2.3-70-g09d2 From c571898ffc24a1768e1b2dabeac0fc7dd4c14601 Mon Sep 17 00:00:00 2001 From: Andres Lagar-Cavilla Date: Fri, 14 Sep 2012 14:26:59 +0000 Subject: xen/gndev: Xen backend support for paged out grant targets V4. Since Xen-4.2, hvm domains may have portions of their memory paged out. When a foreign domain (such as dom0) attempts to map these frames, the map will initially fail. The hypervisor returns a suitable errno, and kicks an asynchronous page-in operation carried out by a helper. The foreign domain is expected to retry the mapping operation until it eventually succeeds. The foreign domain is not put to sleep because itself could be the one running the pager assist (typical scenario for dom0). This patch adds support for this mechanism for backend drivers using grant mapping and copying operations. Specifically, this covers the blkback and gntdev drivers (which map foreign grants), and the netback driver (which copies foreign grants). * Add a retry method for grants that fail with GNTST_eagain (i.e. because the target foreign frame is paged out). * Insert hooks with appropriate wrappers in the aforementioned drivers. The retry loop is only invoked if the grant operation status is GNTST_eagain. It guarantees to leave a new status code different from GNTST_eagain. Any other status code results in identical code execution as before. The retry loop performs 256 attempts with increasing time intervals through a 32 second period. It uses msleep to yield while waiting for the next retry. V2 after feedback from David Vrabel: * Explicit MAX_DELAY instead of wrap-around delay into zero * Abstract GNTST_eagain check into core grant table code for netback module. V3 after feedback from Ian Campbell: * Add placeholder in array of grant table error descriptions for unrelated error code we jump over. * Eliminate single map and retry macro in favor of a generic batch flavor. * Some renaming. * Bury most implementation in grant_table.c, cleaner interface. V4 rebased on top of sync of Xen grant table interface headers. Signed-off-by: Andres Lagar-Cavilla Acked-by: Ian Campbell [v5: Fixed whitespace issues] Signed-off-by: Konrad Rzeszutek Wilk --- drivers/net/xen-netback/netback.c | 11 +++----- drivers/xen/grant-table.c | 53 ++++++++++++++++++++++++++++++++++++++ drivers/xen/xenbus/xenbus_client.c | 6 ++--- include/xen/grant_table.h | 12 +++++++++ 4 files changed, 70 insertions(+), 12 deletions(-) (limited to 'drivers/xen') diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index 682633bfe00..05593d88202 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c @@ -635,9 +635,7 @@ static void xen_netbk_rx_action(struct xen_netbk *netbk) return; BUG_ON(npo.copy_prod > ARRAY_SIZE(netbk->grant_copy_op)); - ret = HYPERVISOR_grant_table_op(GNTTABOP_copy, &netbk->grant_copy_op, - npo.copy_prod); - BUG_ON(ret != 0); + gnttab_batch_copy(netbk->grant_copy_op, npo.copy_prod); while ((skb = __skb_dequeue(&rxq)) != NULL) { sco = (struct skb_cb_overlay *)skb->cb; @@ -1460,18 +1458,15 @@ static void xen_netbk_tx_submit(struct xen_netbk *netbk) static void xen_netbk_tx_action(struct xen_netbk *netbk) { unsigned nr_gops; - int ret; nr_gops = xen_netbk_tx_build_gops(netbk); if (nr_gops == 0) return; - ret = HYPERVISOR_grant_table_op(GNTTABOP_copy, - netbk->tx_copy_ops, nr_gops); - BUG_ON(ret); - xen_netbk_tx_submit(netbk); + gnttab_batch_copy(netbk->tx_copy_ops, nr_gops); + xen_netbk_tx_submit(netbk); } static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx) diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c index eea81cf8a2a..3a567b15600 100644 --- a/drivers/xen/grant-table.c +++ b/drivers/xen/grant-table.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -823,6 +824,52 @@ unsigned int gnttab_max_grant_frames(void) } EXPORT_SYMBOL_GPL(gnttab_max_grant_frames); +/* Handling of paged out grant targets (GNTST_eagain) */ +#define MAX_DELAY 256 +static inline void +gnttab_retry_eagain_gop(unsigned int cmd, void *gop, int16_t *status, + const char *func) +{ + unsigned delay = 1; + + do { + BUG_ON(HYPERVISOR_grant_table_op(cmd, gop, 1)); + if (*status == GNTST_eagain) + msleep(delay++); + } while ((*status == GNTST_eagain) && (delay < MAX_DELAY)); + + if (delay >= MAX_DELAY) { + printk(KERN_ERR "%s: %s eagain grant\n", func, current->comm); + *status = GNTST_bad_page; + } +} + +void gnttab_batch_map(struct gnttab_map_grant_ref *batch, unsigned count) +{ + struct gnttab_map_grant_ref *op; + + if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, batch, count)) + BUG(); + for (op = batch; op < batch + count; op++) + if (op->status == GNTST_eagain) + gnttab_retry_eagain_gop(GNTTABOP_map_grant_ref, op, + &op->status, __func__); +} +EXPORT_SYMBOL_GPL(gnttab_batch_map); + +void gnttab_batch_copy(struct gnttab_copy *batch, unsigned count) +{ + struct gnttab_copy *op; + + if (HYPERVISOR_grant_table_op(GNTTABOP_copy, batch, count)) + BUG(); + for (op = batch; op < batch + count; op++) + if (op->status == GNTST_eagain) + gnttab_retry_eagain_gop(GNTTABOP_copy, op, + &op->status, __func__); +} +EXPORT_SYMBOL_GPL(gnttab_batch_copy); + int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops, struct gnttab_map_grant_ref *kmap_ops, struct page **pages, unsigned int count) @@ -836,6 +883,12 @@ int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops, if (ret) return ret; + /* Retry eagain maps */ + for (i = 0; i < count; i++) + if (map_ops[i].status == GNTST_eagain) + gnttab_retry_eagain_gop(GNTTABOP_map_grant_ref, map_ops + i, + &map_ops[i].status, __func__); + if (xen_feature(XENFEAT_auto_translated_physmap)) return ret; diff --git a/drivers/xen/xenbus/xenbus_client.c b/drivers/xen/xenbus/xenbus_client.c index b3e146edb51..bcf3ba4a6ec 100644 --- a/drivers/xen/xenbus/xenbus_client.c +++ b/drivers/xen/xenbus/xenbus_client.c @@ -490,8 +490,7 @@ static int xenbus_map_ring_valloc_pv(struct xenbus_device *dev, op.host_addr = arbitrary_virt_to_machine(pte).maddr; - if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1)) - BUG(); + gnttab_batch_map(&op, 1); if (op.status != GNTST_okay) { free_vm_area(area); @@ -572,8 +571,7 @@ int xenbus_map_ring(struct xenbus_device *dev, int gnt_ref, gnttab_set_map_op(&op, (unsigned long)vaddr, GNTMAP_host_map, gnt_ref, dev->otherend_id); - if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1)) - BUG(); + gnttab_batch_map(&op, 1); if (op.status != GNTST_okay) { xenbus_dev_fatal(dev, op.status, diff --git a/include/xen/grant_table.h b/include/xen/grant_table.h index 11e27c3af3c..ba0d77529a2 100644 --- a/include/xen/grant_table.h +++ b/include/xen/grant_table.h @@ -189,4 +189,16 @@ int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops, int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops, struct page **pages, unsigned int count, bool clear_pte); +/* Perform a batch of grant map/copy operations. Retry every batch slot + * for which the hypervisor returns GNTST_eagain. This is typically due + * to paged out target frames. + * + * Will retry for 1, 2, ... 255 ms, i.e. 256 times during 32 seconds. + * + * Return value in each iand every status field of the batch guaranteed + * to not be GNTST_eagain. + */ +void gnttab_batch_map(struct gnttab_map_grant_ref *batch, unsigned count); +void gnttab_batch_copy(struct gnttab_copy *batch, unsigned count); + #endif /* __ASM_GNTTAB_H__ */ -- cgit v1.2.3-70-g09d2 From e6aa70a0d5511296ea3d5fd1f5e2203ff6898107 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Mon, 24 Sep 2012 15:55:37 +0100 Subject: xen-pciback: properly clean up after calling pcistub_device_find() As the function calls pcistub_device_get() before returning non-NULL, its callers need to take care of calling pcistub_device_put() on (mostly, but not exclusively) error paths. Otoh, the function already guarantees that the 'dev' member is non-NULL upon successful return, so callers do not need to check for this a second time. Signed-off-by: Jan Beulich Signed-off-by: Konrad Rzeszutek Wilk --- drivers/xen/xen-pciback/pci_stub.c | 46 +++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 23 deletions(-) (limited to 'drivers/xen') diff --git a/drivers/xen/xen-pciback/pci_stub.c b/drivers/xen/xen-pciback/pci_stub.c index 20e1c42c1c4..acec6faff88 100644 --- a/drivers/xen/xen-pciback/pci_stub.c +++ b/drivers/xen/xen-pciback/pci_stub.c @@ -681,14 +681,14 @@ static pci_ers_result_t xen_pcibk_slot_reset(struct pci_dev *dev) dev_err(&dev->dev, DRV_NAME " device is not connected or owned" " by HVM, kill it\n"); kill_domain_by_device(psdev); - goto release; + goto end; } if (!test_bit(_XEN_PCIB_AERHANDLER, (unsigned long *)&psdev->pdev->sh_info->flags)) { dev_err(&dev->dev, "guest with no AER driver should have been killed\n"); - goto release; + goto end; } result = common_process(psdev, 1, XEN_PCI_OP_aer_slotreset, result); @@ -698,9 +698,9 @@ static pci_ers_result_t xen_pcibk_slot_reset(struct pci_dev *dev) "No AER slot_reset service or disconnected!\n"); kill_domain_by_device(psdev); } -release: - pcistub_device_put(psdev); end: + if (psdev) + pcistub_device_put(psdev); up_write(&pcistub_sem); return result; @@ -739,14 +739,14 @@ static pci_ers_result_t xen_pcibk_mmio_enabled(struct pci_dev *dev) dev_err(&dev->dev, DRV_NAME " device is not connected or owned" " by HVM, kill it\n"); kill_domain_by_device(psdev); - goto release; + goto end; } if (!test_bit(_XEN_PCIB_AERHANDLER, (unsigned long *)&psdev->pdev->sh_info->flags)) { dev_err(&dev->dev, "guest with no AER driver should have been killed\n"); - goto release; + goto end; } result = common_process(psdev, 1, XEN_PCI_OP_aer_mmio, result); @@ -756,9 +756,9 @@ static pci_ers_result_t xen_pcibk_mmio_enabled(struct pci_dev *dev) "No AER mmio_enabled service or disconnected!\n"); kill_domain_by_device(psdev); } -release: - pcistub_device_put(psdev); end: + if (psdev) + pcistub_device_put(psdev); up_write(&pcistub_sem); return result; } @@ -797,7 +797,7 @@ static pci_ers_result_t xen_pcibk_error_detected(struct pci_dev *dev, dev_err(&dev->dev, DRV_NAME " device is not connected or owned" " by HVM, kill it\n"); kill_domain_by_device(psdev); - goto release; + goto end; } /*Guest owns the device yet no aer handler regiested, kill guest*/ @@ -805,7 +805,7 @@ static pci_ers_result_t xen_pcibk_error_detected(struct pci_dev *dev, (unsigned long *)&psdev->pdev->sh_info->flags)) { dev_dbg(&dev->dev, "guest may have no aer driver, kill it\n"); kill_domain_by_device(psdev); - goto release; + goto end; } result = common_process(psdev, error, XEN_PCI_OP_aer_detected, result); @@ -815,9 +815,9 @@ static pci_ers_result_t xen_pcibk_error_detected(struct pci_dev *dev, "No AER error_detected service or disconnected!\n"); kill_domain_by_device(psdev); } -release: - pcistub_device_put(psdev); end: + if (psdev) + pcistub_device_put(psdev); up_write(&pcistub_sem); return result; } @@ -851,7 +851,7 @@ static void xen_pcibk_error_resume(struct pci_dev *dev) dev_err(&dev->dev, DRV_NAME " device is not connected or owned" " by HVM, kill it\n"); kill_domain_by_device(psdev); - goto release; + goto end; } if (!test_bit(_XEN_PCIB_AERHANDLER, @@ -859,13 +859,13 @@ static void xen_pcibk_error_resume(struct pci_dev *dev) dev_err(&dev->dev, "guest with no AER driver should have been killed\n"); kill_domain_by_device(psdev); - goto release; + goto end; } common_process(psdev, 1, XEN_PCI_OP_aer_resume, PCI_ERS_RESULT_RECOVERED); -release: - pcistub_device_put(psdev); end: + if (psdev) + pcistub_device_put(psdev); up_write(&pcistub_sem); return; } @@ -1024,7 +1024,7 @@ static int pcistub_reg_add(int domain, int bus, int slot, int func, int reg, struct config_field *field; psdev = pcistub_device_find(domain, bus, slot, func); - if (!psdev || !psdev->dev) { + if (!psdev) { err = -ENODEV; goto out; } @@ -1048,6 +1048,8 @@ static int pcistub_reg_add(int domain, int bus, int slot, int func, int reg, if (err) kfree(field); out: + if (psdev) + pcistub_device_put(psdev); return err; } @@ -1152,10 +1154,9 @@ static ssize_t pcistub_irq_handler_switch(struct device_driver *drv, err = str_to_slot(buf, &domain, &bus, &slot, &func); if (err) - goto out; + return err; psdev = pcistub_device_find(domain, bus, slot, func); - if (!psdev) goto out; @@ -1171,6 +1172,8 @@ static ssize_t pcistub_irq_handler_switch(struct device_driver *drv, if (dev_data->isr_on) dev_data->ack_intr = 1; out: + if (psdev) + pcistub_device_put(psdev); if (!err) err = count; return err; @@ -1262,10 +1265,7 @@ static ssize_t permissive_add(struct device_driver *drv, const char *buf, err = -ENODEV; goto out; } - if (!psdev->dev) { - err = -ENODEV; - goto release; - } + dev_data = pci_get_drvdata(psdev->dev); /* the driver data for a device should never be null at this point */ if (!dev_data) { -- cgit v1.2.3-70-g09d2 From c341ca45ce56143804ef5a8f4db753e554e640b4 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Tue, 25 Sep 2012 16:48:24 -0400 Subject: xen/pciback: Restore the PCI config space after an FLR. When we do an FLR, or D0->D3_hot we may lose the BARs as the device has turned itself off (and on). This means the device cannot function unless the pci_restore_state is called - which it is when the PCI device is unbound from the Xen PCI backend driver. For PV guests it ends up calling pci_enable_device / pci_enable_msi[x] which does the proper steps That however is not happening if a HVM guest is run as QEMU deals with PCI configuration space. QEMU also requires that the device be "parked" under the ownership of a pci-stub driver to guarantee that the PCI device is not being used. Hence we follow the same incantation as pci_reset_function does - by doing an FLR, then restoring the PCI configuration space. The result of this patch is that when you run lspci, you get now this: - Region 0: [virtual] Memory at fe8c0000 (32-bit, non-prefetchable) [size=128K] - Region 1: [virtual] Memory at fe800000 (32-bit, non-prefetchable) [size=512K] + Region 0: Memory at fe8c0000 (32-bit, non-prefetchable) [size=128K] + Region 1: Memory at fe800000 (32-bit, non-prefetchable) [size=512K] Region 2: I/O ports at c000 [size=32] - Region 3: [virtual] Memory at fe8e0000 (32-bit, non-prefetchable) [size=16K] + Region 3: Memory at fe8e0000 (32-bit, non-prefetchable) [size=16K] The [virtual] means that lspci read those entries from SysFS but when it read them from the device it got a different value (0xfffffff). CC: stable@vger.kernel.org #only for 3.5, 3.6 Signed-off-by: Konrad Rzeszutek Wilk --- drivers/xen/xen-pciback/pci_stub.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/xen') diff --git a/drivers/xen/xen-pciback/pci_stub.c b/drivers/xen/xen-pciback/pci_stub.c index acec6faff88..e5a0c13e2ad 100644 --- a/drivers/xen/xen-pciback/pci_stub.c +++ b/drivers/xen/xen-pciback/pci_stub.c @@ -362,6 +362,7 @@ static int __devinit pcistub_init_device(struct pci_dev *dev) else { dev_dbg(&dev->dev, "reseting (FLR, D3, etc) the device\n"); __pci_reset_function_locked(dev); + pci_restore_state(dev); } /* Now disable the device (this also ensures some private device * data is setup before we export) -- cgit v1.2.3-70-g09d2