New paravirtual PCI front-end for Hyper-V VMs
Subsystems (13)
v2 cover New paravirtual PCI front-end for Hyper-V VMs
From: Jake Oshins <[email protected]>
The patch series updates the one sent about a month ago in three ways. It integrated with other IRQ domain work done in linux-next in that time, it distributes interrupts to multiple virtual processors in the guest VM, and it incorporates feedback from Thomas Gleixner and others.
These patches change the IRQ domain code so that an IRQ domain can match on both bus type and on the PCI domain. The IRQ domain match code is modified so that IRQ domains can have a "rank," allowing for a default one which matches every x86 PC and more specific ones that replace the default.
The next step is to make it possible to implement an IRQ domain in a module, by exporting a few functions. This seems to make sense here, rather than linking it into the kernel, because pulling it into the kernel would involve pulling a lot of other Hyper-V-related code into the kernel, since the IRQ domain implementation has to send messages to and receive messages from the hypervisor, and those facilities are currently built as modules.
After that, a couple of new Hyper-V-related facilities are exported from hv_vmbus.ko, so that the PCI front end can correlate Linux CPUs with virtual processor IDs and to make hypercalls.
The last patch is a new front-end driver that exposes new root PCI buses that (virtually) contain devices being passed through into the VM.
Jake Oshins (12):
kernel:irq: Change signature of irq_domain_ops match() method, adding
*bus_data
kernel:irq: Change signature of irq_find_matching_host() kernel:irq: Allow for ranked matches on IRQ domains drivers:pci: Add IRQ domain lookup by PCI domain drivers:hv: Export a function that maps Linux CPU num onto Hyper-V
proc num
drivers:hv: Export do_hypercall()
drivers:x86:pci: Make it possible to implement a PCI MSI IRQ Domain in
a module.
drivers:pci:msi: Store PCI domain (segment) as part of IRQ domain kernel:irq: Implement msi match function
kernel:irq: Return a higher ranked match when the IRQ domain matches a
specific PCI domain
drivers:hv: Define the channel type for Hyper-V PCI Express
pass-through
drivers:pci:hv: New paravirtual PCI front-end for Hyper-V VMs
MAINTAINERS | 1 + arch/powerpc/platforms/512x/mpc5121_ads_cpld.c | 2 +- arch/powerpc/platforms/cell/interrupt.c | 2 +- arch/powerpc/platforms/embedded6xx/flipper-pic.c | 3 +- arch/powerpc/platforms/powermac/pic.c | 3 +- arch/powerpc/platforms/powernv/opal-irqchip.c | 2 +- arch/powerpc/platforms/ps3/interrupt.c | 2 +- arch/powerpc/sysdev/ehv_pic.c | 3 +- arch/powerpc/sysdev/i8259.c | 2 +- arch/powerpc/sysdev/ipic.c | 2 +- arch/powerpc/sysdev/mpic.c | 2 +- arch/powerpc/sysdev/qe_lib/qe_ic.c | 2 +- arch/powerpc/sysdev/xics/xics-common.c | 2 +- arch/x86/include/asm/msi.h | 4 + arch/x86/kernel/apic/msi.c | 5 +- arch/x86/kernel/apic/vector.c | 2 + drivers/hv/hv.c | 3 +- drivers/hv/vmbus_drv.c | 17 + drivers/irqchip/irq-gic-v3-its-pci-msi.c | 2 +- drivers/irqchip/irq-gic-v3-its-platform-msi.c | 2 +- drivers/of/irq.c | 2 +- drivers/pci/Kconfig | 7 + drivers/pci/host/Makefile | 1 + drivers/pci/host/hv_pcifront.c | 2244 ++++++++++++++++++++++ drivers/pci/msi.c | 2 + drivers/pci/of.c | 2 +- drivers/pci/probe.c | 11 + include/linux/hyperv.h | 14 + include/linux/irqdomain.h | 9 +- include/linux/msi.h | 4 + kernel/irq/chip.c | 1 + kernel/irq/irqdomain.c | 48 +- kernel/irq/msi.c | 24 + 33 files changed, 2394 insertions(+), 38 deletions(-) create mode 100644 drivers/pci/host/hv_pcifront.c
Signature · 1 line
1.9.1
PATCH v2 1/12 kernel:irq: Change signature of irq_domain_ops match() method, adding *bus_data
From: Jake Oshins <[email protected]>
The current irq_domain_ops allows an IRQ domain to match on bus type, but not a specific PCI bus heirarchy. This patch introduces a bus_data parameter, intended to allow a more specific match. This patch does nothing more than introduce that parameter and change all the implementations' signatures.
--- arch/powerpc/platforms/512x/mpc5121_ads_cpld.c | 2 +- arch/powerpc/platforms/cell/interrupt.c | 2 +- arch/powerpc/platforms/embedded6xx/flipper-pic.c | 3 ++- arch/powerpc/platforms/powermac/pic.c | 3 ++- arch/powerpc/platforms/powernv/opal-irqchip.c | 2 +- arch/powerpc/platforms/ps3/interrupt.c | 2 +- arch/powerpc/sysdev/ehv_pic.c | 3 ++- arch/powerpc/sysdev/i8259.c | 2 +- arch/powerpc/sysdev/ipic.c | 2 +- arch/powerpc/sysdev/mpic.c | 2 +- arch/powerpc/sysdev/qe_lib/qe_ic.c | 2 +- arch/powerpc/sysdev/xics/xics-common.c | 2 +- include/linux/irqdomain.h | 2 +- kernel/irq/irqdomain.c | 2 +- 14 files changed, 17 insertions(+), 14 deletions(-)
arch/powerpc/platforms/512x/mpc5121_ads_cpld.c +1 -1
@@ -124,7 +124,7 @@ cpld_pic_cascade(unsigned int irq, struct irq_desc *desc)static int cpld_pic_host_match (struct irq_domain *h,struct device_node *node, -enum irq_domain_bus_token bus_token) +enum irq_domain_bus_token bus_token,void *bus_data) {return cpld_pic_node == node; }
arch/powerpc/platforms/cell/interrupt.c +1 -1
@@ -223,7 +223,7 @@ void iic_request_IPIs(void)static int iic_host_match (struct irq_domain *h,struct device_node *node, -enum irq_domain_bus_token bus_token) +enum irq_domain_bus_token bus_token,void *bus_data) {return of_device_is_compatible (node,"IBM,CBEA-Internal-Interrupt-Controller" );
arch/powerpc/platforms/embedded6xx/flipper-pic.c +2 -1
@@ -109,7 +109,8 @@ static int flipper_pic_map(struct irq_domain *h, unsigned int virq, }static int flipper_pic_match (struct irq_domain *h,struct device_node *np, -enum irq_domain_bus_token bus_token) +enum irq_domain_bus_token bus_token, +void *bus_data) {return 1 ; }
arch/powerpc/platforms/powermac/pic.c +2 -1
@@ -269,7 +269,8 @@ static struct irqaction gatwick_cascade_action = { };static int pmac_pic_host_match (struct irq_domain *h,struct device_node *node, -enum irq_domain_bus_token bus_token) +enum irq_domain_bus_token bus_token, +void *bus_data) {/* We match all, we don't always have a node anyway */ return 1 ;
arch/powerpc/platforms/powernv/opal-irqchip.c +1 -1
@@ -135,7 +135,7 @@ static void opal_handle_irq_work(struct irq_work *work) }static int opal_event_match (struct irq_domain *h,struct device_node *node, -enum irq_domain_bus_token bus_token) +enum irq_domain_bus_token bus_token,void *bus_data) {return h->of_node == node; }
arch/powerpc/platforms/ps3/interrupt.c +1 -1
@@ -679,7 +679,7 @@ static int ps3_host_map(struct irq_domain *h, unsigned int virq, }static int ps3_host_match (struct irq_domain *h,struct device_node *np, -enum irq_domain_bus_token bus_token) +enum irq_domain_bus_token bus_token,void *bus_data) {/* Match all */ return 1 ;
arch/powerpc/sysdev/ehv_pic.c +2 -1
@@ -178,7 +178,8 @@ unsigned int ehv_pic_get_irq(void) }static int ehv_pic_host_match (struct irq_domain *h,struct device_node *node, -enum irq_domain_bus_token bus_token) +enum irq_domain_bus_token bus_token, +void *bus_data) {/* Exact match, unless ehv_pic node is NULL */ return h->of_node ==NULL || h->of_node == node;
arch/powerpc/sysdev/i8259.c +1 -1
@@ -163,7 +163,7 @@ static struct resource pic_edgectrl_iores = { };static int i8259_host_match (struct irq_domain *h,struct device_node *node, -enum irq_domain_bus_token bus_token) +enum irq_domain_bus_token bus_token,void *bus_data) {return h->of_node ==NULL || h->of_node == node; }
arch/powerpc/sysdev/ipic.c +1 -1
@@ -672,7 +672,7 @@ static struct irq_chip ipic_edge_irq_chip = { };static int ipic_host_match (struct irq_domain *h,struct device_node *node, -enum irq_domain_bus_token bus_token) +enum irq_domain_bus_token bus_token,void *bus_data) {/* Exact match, unless ipic node is NULL */ return h->of_node ==NULL || h->of_node == node;
arch/powerpc/sysdev/mpic.c +1 -1
@@ -1008,7 +1008,7 @@ static struct irq_chip mpic_irq_ht_chip = {static int mpic_host_match (struct irq_domain *h,struct device_node *node, -enum irq_domain_bus_token bus_token) +enum irq_domain_bus_token bus_token,void *bus_data) {/* Exact match, unless mpic node is NULL */ return h->of_node ==NULL || h->of_node == node;
arch/powerpc/sysdev/qe_lib/qe_ic.c +1 -1
@@ -245,7 +245,7 @@ static struct irq_chip qe_ic_irq_chip = { };static int qe_ic_host_match (struct irq_domain *h,struct device_node *node, -enum irq_domain_bus_token bus_token) +enum irq_domain_bus_token bus_token,void *bus_data) {/* Exact match, unless qe_ic node is NULL */ return h->of_node ==NULL || h->of_node == node;
arch/powerpc/sysdev/xics/xics-common.c +1 -1
@@ -299,7 +299,7 @@ int xics_get_irq_server(unsigned int virq, const struct cpumask *cpumask,#endif /* CONFIG_SMP */ static int xics_host_match (struct irq_domain *h,struct device_node *node, -enum irq_domain_bus_token bus_token) +enum irq_domain_bus_token bus_token,void *bus_data) {struct ics *ics;
include/linux/irqdomain.h +1 -1
@@ -76,7 +76,7 @@ enum irq_domain_bus_token {*/ struct irq_domain_ops {int (*match)(struct irq_domain *d,struct device_node *node, -enum irq_domain_bus_token bus_token); +enum irq_domain_bus_token bus_token,void *bus_data);int (*map)(struct irq_domain *d,unsigned int virq,irq_hw_number_t hw);void (*unmap)(struct irq_domain *d,unsigned int virq); int (*xlate)(struct irq_domain *d, struct device_node *node,
kernel/irq/irqdomain.c +1 -1
@@ -209,7 +209,7 @@ struct irq_domain *irq_find_matching_host(struct device_node *node,mutex_lock (&irq_domain_mutex);list_for_each_entry (h, &irq_domain_list, link) {if (h->ops->match) - rc = h->ops->match (h, node, bus_token); + rc = h->ops->match (h, node, bus_token,NULL );else rc = ((h->of_node != NULL) && (h->of_node == node) && ((bus_token == DOMAIN_BUS_ANY) ||
Signature · 1 line
1.9.1
PATCH v2 2/12 kernel:irq: Change signature of irq_find_matching_host()
In reply to [email protected]From: Jake Oshins <[email protected]>
In order to use the facility introduced in the last patch (the ability to match on both bus type and something that identifies the specific bus of that type,) irq_find_matching_host() needs to take that bus-specific parameter.
--- drivers/irqchip/irq-gic-v3-its-pci-msi.c | 2 +- drivers/irqchip/irq-gic-v3-its-platform-msi.c | 2 +- drivers/of/irq.c | 2 +- drivers/pci/of.c | 2 +- include/linux/irqdomain.h | 5 +++-- kernel/irq/irqdomain.c | 6 ++++-- 6 files changed, 11 insertions(+), 8 deletions(-)
drivers/irqchip/irq-gic-v3-its-pci-msi.c +1 -1
@@ -118,7 +118,7 @@ static int __init its_pci_msi_init(void)if (!of_property_read_bool (np,"msi-controller" ))continue ; - parent =irq_find_matching_host (np,DOMAIN_BUS_NEXUS ); + parent =irq_find_matching_host (np,DOMAIN_BUS_NEXUS ,NULL );if (!parent || !msi_get_domain_info (parent)) {pr_err ("%s: unable to locate ITS domain\n" , np->full_name);
drivers/irqchip/irq-gic-v3-its-platform-msi.c +1 -1
@@ -71,7 +71,7 @@ static int __init its_pmsi_init(void)if (!of_property_read_bool (np,"msi-controller" ))continue ; - parent =irq_find_matching_host (np,DOMAIN_BUS_NEXUS ); + parent =irq_find_matching_host (np,DOMAIN_BUS_NEXUS ,NULL );if (!parent || !msi_get_domain_info (parent)) {pr_err ("%s: unable to locate ITS domain\n" , np->full_name);
drivers/of/irq.c +1 -1
@@ -593,7 +593,7 @@ void of_msi_configure(struct device *dev, struct device_node *np)if (!msi_np)return ; - d =irq_find_matching_host (msi_np,DOMAIN_BUS_PLATFORM_MSI ); + d =irq_find_matching_host (msi_np,DOMAIN_BUS_PLATFORM_MSI ,NULL );if (!d) d =irq_find_host (msi_np);dev_set_msi_domain (dev, d);
drivers/pci/of.c +1 -1
@@ -80,7 +80,7 @@ struct irq_domain *pci_host_bridge_of_msi_domain(struct pci_bus *bus)if (!np) np = bus->dev.of_node; - d =irq_find_matching_host (np,DOMAIN_BUS_PCI_MSI ); + d =irq_find_matching_host (np,DOMAIN_BUS_PCI_MSI ,NULL );if (d)return d;
include/linux/irqdomain.h +3 -2
@@ -178,12 +178,13 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node,const struct irq_domain_ops *ops, void *host_data);extern struct irq_domain *irq_find_matching_host (struct device_node *node, -enum irq_domain_bus_token bus_token); +enum irq_domain_bus_token bus_token, +void *bus_data);extern void irq_set_default_host (struct irq_domain *host);static inline struct irq_domain *irq_find_host (struct device_node *node) { -return irq_find_matching_host (node,DOMAIN_BUS_ANY ); +return irq_find_matching_host (node,DOMAIN_BUS_ANY ,NULL ); }/**
kernel/irq/irqdomain.c +4 -2
@@ -190,9 +190,11 @@ EXPORT_SYMBOL_GPL(irq_domain_add_legacy);* irq_find_matching_host() - Locates a domain for a given device node * @node: device-tree node of the interrupt controller * @bus_token: domain-specific data +* @bus_data: bus-specific data */ struct irq_domain *irq_find_matching_host (struct device_node *node, -enum irq_domain_bus_token bus_token) +enum irq_domain_bus_token bus_token, +void *bus_data) {struct irq_domain *h, *found =NULL ;int rc;
@@ -209,7 +211,7 @@ struct irq_domain *irq_find_matching_host(struct device_node *node,mutex_lock (&irq_domain_mutex);list_for_each_entry (h, &irq_domain_list, link) {if (h->ops->match) - rc = h->ops->match (h, node, bus_token,NULL ); + rc = h->ops->match (h, node, bus_token, bus_data);else rc = ((h->of_node != NULL) && (h->of_node == node) && ((bus_token == DOMAIN_BUS_ANY) ||
Signature · 1 line
1.9.1
PATCH v2 3/12 kernel:irq: Allow for ranked matches on IRQ domains
In reply to [email protected]From: Jake Oshins <[email protected]>
The existing IRQ domain match code cycles through all the IRQ domains looking for the first one to return a non-zero value from its match() function. There's even a comment that says "this isn't a problem so far..."
This patch changes the semantics on the match() function so that the value returned is a ranking, where zero means "no match." The function now runs the list of IRQ domains twice, finding the highest ranked matches on the first pass and returning the first one of those (to preserve existing behavior, where there might have been multiple matches) on the second pass.
This allows for a situation where a default IRQ domain (specifically the one for message-signaled interrupts on x86 PCs) is always present, but where it can be overriden by an IRQ domain implementation that is targeted at specific PCIe root complexes.
--- include/linux/irqdomain.h | 2 +- kernel/irq/irqdomain.c | 44 ++++++++++++++++++++++++++++++-------------- 2 files changed, 31 insertions(+), 15 deletions(-)
include/linux/irqdomain.h +1 -1
@@ -62,7 +62,7 @@ enum irq_domain_bus_token {/** * struct irq_domain_ops - Methods for irq_domain objects * @match: Match an interrupt controller device node to a host, returns -* 1 on a match +* a ranking (non-zero) on a match * @map: Create or update a mapping between a virtual irq number and a hw * irq number. This is called only once for a given mapping. * @unmap: Dispose of such a mapping
kernel/irq/irqdomain.c +30 -14
60 lines not on this page · raw message
Signature · 1 line
1.9.1
PATCH v2 4/12 drivers:pci: Add IRQ domain lookup by PCI domain
In reply to [email protected]From: Jake Oshins <[email protected]>
The PCI driver currently looks up IRQ domains for root PCI buses by walking up the Open Firmware tree looking for any that cover this particular PCI root. Since x86 PCs don't implement Open Firmware, this patch offers an alternative lookup by the PCI domain ID (known as "segment" in the PCI and ACPI specs.)
I could have tried to build a (fake) Open Firmware tree and leverage the old code, but I rejected that possibility both because it would have required changes in lots of other places and because most distributions don't even compile in the OF infrastructure when targeting PCs.
--- drivers/pci/probe.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
drivers/pci/probe.c +11 -0
@@ -12,6 +12,7 @@#include <linux/module.h> #include <linux/cpumask.h> #include <linux/pci-aspm.h> +#include <linux/irqdomain.h> #include <asm-generic/pci-bridge.h> #include "pci.h"
@@ -663,12 +664,22 @@ static void pci_set_bus_speed(struct pci_bus *bus)static struct irq_domain *pci_host_bridge_msi_domain (struct pci_bus *bus) {struct irq_domain *d; +int pci_domain;/* * Any firmware interface that can resolve the msi_domain * should be called from here. */ d =pci_host_bridge_of_msi_domain (bus); +if (d) +return d; + +/* +* If firmware couldn't help find, it try looking it up by PCI +* domain/segment. +*/ + pci_domain =pci_domain_nr (bus); + d =irq_find_matching_host (NULL ,DOMAIN_BUS_PCI_MSI , &pci_domain);return d; }
Signature · 1 line
1.9.1
Bjorn Helgaas
maintainerRe: [PATCH v2 04/12] drivers:pci: Add IRQ domain lookup by PCI domain
Hi Jake,
I don't know how this will be morphed after Marc's comments, but when you repost this series, please take a look at the existing change history, e.g., with "git log --oneline drivers/pci/probe.c", and make your subject lines follow the existing conventions. In this case, they look like:
PCI: Make pci_msi_setup_pci_dev() non-static for use by arch code
PCI: Set MPS to match upstream bridge
PCI: Move MPS configuration check to pci_configure_device()
PCI: Add pci_scan_root_bus_msi()
PCI: Tolerate hierarchies with no Root Port
...
Bjorn
Quoted 55 lines · On Fri, Sep 11, 2015 at 12:01:03AM +0000, [email protected] wrote:
From: Jake Oshins <[email protected]>
The PCI driver currently looks up IRQ domains for root PCI buses by walking up the Open Firmware tree looking for any that cover this particular PCI root. Since x86 PCs don't implement Open Firmware, this patch offers an alternative lookup by the PCI domain ID (known as "segment" in the PCI and ACPI specs.)
I could have tried to build a (fake) Open Firmware tree and leverage the old code, but I rejected that possibility both because it would have required changes in lots of other places and because most distributions don't even compile in the OF infrastructure when targeting PCs.
Signed-off-by Jake Oshins <[email protected]>--- drivers/pci/probe.c | 11 +++++++++++ 1 file changed, 11 insertions(+)drivers/pci/probe.c +11
-0@@ -12,6 +12,7 @@#include <linux/module.h> #include <linux/cpumask.h> #include <linux/pci-aspm.h> +#include <linux/irqdomain.h> #include <asm-generic/pci-bridge.h> #include "pci.h" @@ -663,12 +664,22 @@ static void pci_set_bus_speed(struct pci_bus *bus)static struct irq_domain *pci_host_bridge_msi_domain (struct pci_bus *bus) {struct irq_domain *d; +int pci_domain;/* * Any firmware interface that can resolve the msi_domain * should be called from here. */ d =pci_host_bridge_of_msi_domain (bus); +if (d) +return d; + +/* +* If firmware couldn't help find, it try looking it up by PCI +* domain/segment. +*/ + pci_domain =pci_domain_nr (bus); + d =irq_find_matching_host (NULL ,DOMAIN_BUS_PCI_MSI , &pci_domain);return d; }Signature · 1 line
1.9.1
PATCH v2 9/11 kernel:irq: Implement msi match function
In reply to [email protected]From: Jake Oshins <[email protected]>
Previous patches in this series introduced the concept of ranked matches of IRQ domains, where a default implementation ranks low and a specific implementation might rank higher, overriding the default.
This patch supplies a match function for use by any IRQ domain derived from the default MSI IRQ domain. It returns a rank of '1' when the IRQ domain does not ask for a match based on PCI domain and a rank of '2' if the IRQ domain does set the flag indicating that it wants a more specific match.
At this point in the patch series, there is no implementation of an MSI IRQ domain which asks for a more specific match. That's found in the final patch, introducing a new driver.
--- include/linux/msi.h | 2 ++ kernel/irq/msi.c | 24 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+)
include/linux/msi.h +2 -0
@@ -259,6 +259,8 @@ enum {MSI_FLAG_MULTI_PCI_MSI = (1 <<3 ),/* Support PCI MSIX interrupts */ MSI_FLAG_PCI_MSIX = (1 <<4 ), +/* Require exact match for PCI domain */ + MSI_FLAG_PCI_DOMAIN_MATCH = (1 << 5), }; int msi_domain_set_affinity(struct irq_data *data, const struct cpumask *mask,
kernel/irq/msi.c +24 -0
@@ -141,11 +141,35 @@ static void msi_domain_free(struct irq_domain *domain, unsigned int virq,irq_domain_free_irqs_top (domain, virq, nr_irqs); } +/* +* Return a higher rank for exact matches against PCI domain (segment) +* so that generic MSI IRQ domains can be overridden by more specific +* implementations. +*/ +static int msi_domain_match (struct irq_domain *d,struct device_node *node, +enum irq_domain_bus_token bus_token, +void *bus_data) +{ +struct msi_domain_info *info = d->host_data; + +if (bus_token != d->bus_token) +return 0 ; + +if (bus_token ==DOMAIN_BUS_PCI_MSI ) { +if (!(info->flags &MSI_FLAG_PCI_DOMAIN_MATCH )) +return 1 ; +if (bus_data && (info->pci_domain == *(int *)bus_data)) +return 2 ; + } +return 0 ; +} +static const struct irq_domain_ops msi_domain_ops = { .alloc = msi_domain_alloc, .free = msi_domain_free, .activate = msi_domain_activate, .deactivate = msi_domain_deactivate, + .match = msi_domain_match, };#ifdef GENERIC_MSI_DOMAIN_OPS
Signature · 1 line
1.9.1
PATCH v2 5/12 drivers:hv: Export a function that maps Linux CPU num onto Hyper-V proc num
In reply to [email protected]From: Jake Oshins <[email protected]>
This patch exposes the mapping between Linux CPU number and Hyper-V virtual processor number. This is necessary because the hypervisor needs to know which virtual processors to target when making a mapping in the Interrupt Redirection Table in the I/O MMU.
--- drivers/hv/vmbus_drv.c | 17 +++++++++++++++++ include/linux/hyperv.h | 2 ++ 2 files changed, 19 insertions(+)
drivers/hv/vmbus_drv.c +17 -0
@@ -1191,6 +1191,23 @@ int vmbus_allocate_mmio(struct resource **new, struct hv_device *device_obj, }EXPORT_SYMBOL_GPL (vmbus_allocate_mmio); +/** +* vmbus_cpu_number_to_vp_number() - Map CPU to VP. +* @cpu_number: CPU number in Linux terms +* +* This function returns the mapping between the Linux processor +* number and the hypervisor's virtual processor number, useful +* in making hypercalls and such that talk about specific +* processors. +* +* Return: Virtual processor number in Hyper-V terms +*/ +int vmbus_cpu_number_to_vp_number (int cpu_number) +{ +return hv_context.vp_index[cpu_number]; +} +EXPORT_SYMBOL_GPL (vmbus_cpu_number_to_vp_number); +static int vmbus_acpi_add (struct acpi_device *device) {acpi_status result;
include/linux/hyperv.h +2 -0
@@ -982,6 +982,8 @@ int vmbus_allocate_mmio(struct resource **new, struct hv_device *device_obj, resource_size_t size, resource_size_t align, bool fb_overlap_ok); +int vmbus_cpu_number_to_vp_number (int cpu_number); +/** * VMBUS_DEVICE - macro used to describe a specific hyperv vmbus device *
Signature · 1 line
1.9.1
PATCH v2 10/11 drivers:hv: Define the channel type for Hyper-V PCI Express pass-through
In reply to [email protected]From: Jake Oshins <[email protected]>
This defines the channel type for PCI front-ends in Hyper-V VMs.
--- include/linux/hyperv.h | 11 +++++++++++ 1 file changed, 11 insertions(+)
include/linux/hyperv.h +11 -0
@@ -1140,6 +1140,17 @@ u64 do_hypercall(u64 control, void *input, void *output); }/* +* PCI Express Pass Through +* {44C4F61D-4444-4400-9D52-802E27EDE19F} +*/ + +#define HV_PCIE_GUID \ + .guid = { \ + 0x1D, 0xF6, 0xC4, 0x44, 0x44, 0x44, 0x00, 0x44, \ + 0x9D, 0x52, 0x80, 0x2E, 0x27, 0xED, 0xE1, 0x9F \ + } + +/* * Common header for Hyper-V ICs */
Signature · 1 line
1.9.1
PATCH v2 11/11 drivers:pci:hv: New paravirtual PCI front-end for Hyper-V VMs
In reply to [email protected]From: Jake Oshins <[email protected]>
This patch introduces a new driver which exposes a root PCI bus whenever a PCI Express device is passed through to a guest VM under Hyper-V. The device can be single- or multi-function. The interrupts for the devices are managed by an IRQ domain, implemented within the driver.
This version incorporates feedback from Thomas Gleixner, Dan Carpenter and Paul Bolle.
--- MAINTAINERS | 1 + drivers/pci/Kconfig | 7 + drivers/pci/host/Makefile | 1 + drivers/pci/host/hv_pcifront.c | 2244 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 2253 insertions(+) create mode 100644 drivers/pci/host/hv_pcifront.c
MAINTAINERS +1 -0
@@ -5011,6 +5011,7 @@ F: arch/x86/kernel/cpu/mshyperv.c F: drivers/hid/hid-hyperv.c F: drivers/hv/ F: drivers/input/serio/hyperv-keyboard.c +F: drivers/pci/host/hv_pcifront.c F: drivers/net/hyperv/ F: drivers/scsi/storvsc_drv.c F: drivers/video/fbdev/hyperv_fb.c
drivers/pci/Kconfig +7 -0
@@ -118,4 +118,11 @@ config PCI_LABEL def_bool y if (DMI || ACPI) select NLS +config HYPERV_VPCI + tristate "Hyper-V PCI Frontend" + depends on PCI && X86 && HYPERV && PCI_MSI && PCI_MSI_IRQ_DOMAIN + help + The PCI device frontend driver allows the kernel to import arbitrary + PCI devices from a PCI backend to support PCI driver domains. + source "drivers/pci/host/Kconfig"
drivers/pci/host/Makefile +1 -0
@@ -2,6 +2,7 @@ obj-$(CONFIG_PCIE_DW) += pcie-designware.o obj-$(CONFIG_PCI_DRA7XX) += pci-dra7xx.o obj-$(CONFIG_PCI_EXYNOS) += pci-exynos.o obj-$(CONFIG_PCI_IMX6) += pci-imx6.o +obj-$(CONFIG_HYPERV_VPCI) += hv_pcifront.o obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o obj-$(CONFIG_PCI_TEGRA) += pci-tegra.o obj-$(CONFIG_PCI_RCAR_GEN2) += pci-rcar-gen2.o
drivers/pci/host/hv_pcifront.c new file +2244 -0
2,244 lines not on this page · raw message
Signature · 1 line
1.9.1
PATCH v2 6/12 drivers:hv: Export do_hypercall()
In reply to [email protected]From: Jake Oshins <[email protected]>
This patch exposes the function that hv_vmbus.ko uses to make hypercalls. This is necessary for retargeting an interrupt when it is given a new affinity.
--- drivers/hv/hv.c | 3 ++- include/linux/hyperv.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-)
drivers/hv/hv.c +2 -1
@@ -91,7 +91,7 @@ static int query_hypervisor_info(void)/* * do_hypercall- Invoke the specified hypercall */ -static u64 do_hypercall (u64 control,void *input,void *output) +u64 do_hypercall (u64 control,void *input,void *output) {u64 input_address = (input) ?virt_to_phys (input) :0 ;u64 output_address = (output) ?virt_to_phys (output) :0 ;
@@ -132,6 +132,7 @@ static u64 do_hypercall(u64 control, void *input, void *output)return hv_status_lo | ((u64 )hv_status_hi <<32 );#endif /* !x86_64 */ } +EXPORT_SYMBOL_GPL (do_hypercall);#ifdef CONFIG_X86_64 static cycle_t read_hv_clock_tsc (struct clocksource *arg)
include/linux/hyperv.h +1 -0
@@ -983,6 +983,7 @@ int vmbus_allocate_mmio(struct resource **new, struct hv_device *device_obj, bool fb_overlap_ok);int vmbus_cpu_number_to_vp_number (int cpu_number); +u64 do_hypercall (u64 control,void *input,void *output);/** * VMBUS_DEVICE - macro used to describe a specific hyperv vmbus device
Signature · 1 line
1.9.1
RE: [PATCH v2 06/12] drivers:hv: Export do_hypercall()
Quoted 29 lines
-----Original Message-----
From: [email protected] [mailto:[email protected]]
Sent: Thursday, September 10, 2015 5:01 PM
To: [email protected]; KY Srinivasan <[email protected]>; linux- [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]
Cc: Jake Oshins <[email protected]>
Subject: [PATCH v2 06/12] drivers:hv: Exportdo_hypercall()From: Jake Oshins <[email protected]>
This patch exposes the function that hv_vmbus.ko uses to make hypercalls. This
is necessary for retargeting an interrupt when it is given a new affinity.Signed-off-by Jake Oshins <[email protected]>--- drivers/hv/hv.c | 3 ++- include/linux/hyperv.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-)drivers/hv/hv.c +0
-0
drivers/hv/hv.c static int query_hypervisor_info(void) · line 94
Quoted 5 lines
drivers/hv/hv.c +1
-1@@ -91,7 +91,7 @@ static int query_hypervisor_info(void)/* * do_hypercall- Invoke the specified hypercall */ -static u64 do_hypercall (u64 control,void *input,void *output) +u64 do_hypercall (u64 control,void *input,void *output)
do_hypercall() is not an appropriate name for a function to be exported. I plan to take the base vmbus patches through Greg's tree and if it is ok with you, I will change the name of this function.
Regards,
K. Y
RE: [PATCH v2 06/12] drivers:hv: Export do_hypercall()
Quoted 13 lines
drivers/hv/hv.c static int query_hypervisor_info(void) · line 94
Quoted 7 lines
---
drivers/hv/hv.c +1
-1@@ -91,7 +91,7 @@ static int query_hypervisor_info(void)/* * do_hypercall- Invoke the specified hypercall */ -static u64 do_hypercall (u64 control,void *input,void *output) +u64 do_hypercall (u64 control,void *input,void *output)
do_hypercall()is not an appropriate name for a function to be exported. I plan to take the base
vmbus patches through Greg's tree and if it is ok with you, I will change the name of this function.
Quoted 3 lines
Regards,
K. Y
Of course. Thanks.
-- Jake Oshins
PATCH v2 7/12 drivers:x86:pci: Make it possible to implement a PCI MSI IRQ Domain in a module.
In reply to [email protected]From: Jake Oshins <[email protected]>
The Linux kernel already has the concept of IRQ domain, wherein a component can expose a set of IRQs which are managed by a particular interrupt controller chip or other subsystem. The PCI driver exposes the notion of an IRQ domain for Message-Signaled Interrupts (MSI) from PCI Express devices. This patch exposes the functions which are necessary for making an MSI IRQ domain within a module.
The same goal could be accomplished by building an MSI IRQ domain for Hyper-V into the kernel itself, but this would have required pulling in a lot of other code which currently exists in modules, and it seemed cleaner to avoid that.
--- arch/x86/include/asm/msi.h | 4 ++++ arch/x86/kernel/apic/msi.c | 5 +++-- arch/x86/kernel/apic/vector.c | 2 ++ drivers/pci/msi.c | 2 ++ kernel/irq/chip.c | 1 + 5 files changed, 12 insertions(+), 2 deletions(-)
arch/x86/include/asm/msi.h +4 -0
@@ -1,7 +1,11 @@#ifndef _ASM_X86_MSI_H#define _ASM_X86_MSI_H#include <asm/hw_irq.h> +#include <asm/irqdomain.h> typedef struct irq_alloc_info msi_alloc_info_t ; +int pci_msi_prepare (struct irq_domain *domain,struct device *dev,int nvec, +msi_alloc_info_t *arg); +#endif /* _ASM_X86_MSI_H */
arch/x86/kernel/apic/msi.c +3 -2
@@ -96,8 +96,8 @@ static irq_hw_number_t pci_msi_get_hwirq(struct msi_domain_info *info,return arg->msi_hwirq; } -static int pci_msi_prepare (struct irq_domain *domain,struct device *dev, -int nvec,msi_alloc_info_t *arg) +int pci_msi_prepare (struct irq_domain *domain,struct device *dev,int nvec, +msi_alloc_info_t *arg) {struct pci_dev *pdev =to_pci_dev (dev);struct msi_desc *desc =first_pci_msi_entry (pdev);
@@ -113,6 +113,7 @@ static int pci_msi_prepare(struct irq_domain *domain, struct device *dev,return 0 ; } +EXPORT_SYMBOL_GPL (pci_msi_prepare);static void pci_msi_set_desc (msi_alloc_info_t *arg,struct msi_desc *desc) {
arch/x86/kernel/apic/vector.c +2 -0
@@ -29,6 +29,7 @@ struct apic_chip_data { };struct irq_domain *x86_vector_domain; +EXPORT_SYMBOL_GPL (x86_vector_domain);static DEFINE_RAW_SPINLOCK (vector_lock);static cpumask_var_t vector_cpumask;static struct irq_chip lapic_controller;
@@ -66,6 +67,7 @@ struct irq_cfg *irqd_cfg(struct irq_data *irq_data)return data ? &data->cfg :NULL ; } +EXPORT_SYMBOL_GPL (irqd_cfg);struct irq_cfg *irq_cfg (unsigned int irq) {
drivers/pci/msi.c +2 -0
@@ -1119,6 +1119,7 @@ struct pci_dev *msi_desc_to_pci_dev(struct msi_desc *desc) {return to_pci_dev (desc->dev); } +EXPORT_SYMBOL (msi_desc_to_pci_dev);void *msi_desc_to_pci_sysdata (struct msi_desc *desc) {
@@ -1274,6 +1275,7 @@ struct irq_domain *pci_msi_create_irq_domain(struct device_node *node, domain->bus_token =DOMAIN_BUS_PCI_MSI ;return domain; } +EXPORT_SYMBOL_GPL (pci_msi_create_irq_domain);/** * pci_msi_domain_alloc_irqs - Allocate interrupts for @dev in @domain
kernel/irq/chip.c +1 -0
@@ -935,6 +935,7 @@ void irq_chip_ack_parent(struct irq_data *data) data = data->parent_data; data->chip->irq_ack (data); } +EXPORT_SYMBOL_GPL (irq_chip_ack_parent);/** * irq_chip_mask_parent - Mask the parent interrupt
Signature · 1 line
1.9.1
PATCH v2 8/12 drivers:pci:msi: Store PCI domain (segment) as part of IRQ domain
In reply to [email protected]From: Jake Oshins <[email protected]>
In order to allow an MSI IRQ domain to be specific to a PCI domain, add a field to the struct that tracks the PCI domain.
--- include/linux/msi.h | 2 ++ 1 file changed, 2 insertions(+)
include/linux/msi.h +2 -0
@@ -227,6 +227,7 @@ struct msi_domain_ops {* @handler_data: Optional: associated interrupt flow handler data * @handler_name: Optional: associated interrupt flow handler name * @data: Optional: domain specific data +* @pci_domain: Associated PCI domain (segment) */ struct msi_domain_info {u32 flags;
@@ -237,6 +238,7 @@ struct msi_domain_info {void *handler_data;const char *handler_name;void *data; +int pci_domain; };/* Flags for msi_domain_info */
Signature · 1 line
1.9.1
Hi Jake,
In the future, please CC me on anything that touches irqdomains, along with Jiang Liu as we both co-maintain this piece of code.
Quoted 11 lines · On 11/09/15 01:00, [email protected] wrote:
From: Jake Oshins <[email protected]>
The patch series updates the one sent about a month ago in three ways. It integrated with other IRQ domain work done in linux-next in that time, it distributes interrupts to multiple virtual processors in the guest VM, and it incorporates feedback from Thomas Gleixner and others.
These patches change the IRQ domain code so that an IRQ domain can match on both bus type and on the PCI domain. The IRQ domain match code is modified so that IRQ domains can have a "rank," allowing for a default one which matches every x86 PC and more specific ones that replace the default.
I'm not really fond of this approach. We already have a way to match an IRQ domain, and that's the device node. It looks to me that you're going through a lot of pain inventing a new infrastructure to avoid divorcing the two. If you could lookup your PCI IRQ domain directly based some (non-DT) identifier, and then possibly fallback to the default one, would that help?
If so, here's the deal: I have been working on a patch series that addresses the above for unrelated reasons (ACPI support on arm64). It has been posted twice already:
http://lists.infradead.org/pipermail/linux-arm-kernel/2015-July/358768.html
and the latest version is there:
https://git.kernel.org/cgit/linux/kernel/git/maz/arm-platforms.git/log/?h=irq/gsi-irq-domain-v3
I have the feeling that you could replace a lot of your patches with this infrastructure.
Thoughts?
M.
Signature · 1 line
Jazz is not dead. It just smells funny...
Quoted 11 lines
-----Original Message-----
From: Marc Zyngier [mailto:[email protected]]
Sent: Monday, September 14, 2015 8:01 AM
To: Jake Oshins <[email protected]>; [email protected]; KY Srinivasan <[email protected]>; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; Jiang Liu <[email protected]>
Subject: Re: [PATCH v2 00/12] New paravirtual PCI front-end for Hyper-V VMs
Quoted 5 lines
Hi Jake,
In the future, please CC me on anything that touches irqdomains, along with Jiang Liu as we both co-maintain this piece of code.
Absolutely. Sorry for that omission.
Quoted 34 lines · On 11/09/15 01:00, [email protected] wrote:
Quoted 8 lines
From: Jake Oshins <[email protected]>
The patch series updates the one sent about a month ago in three ways. It integrated with other IRQ domain work done in linux-next in that time, it distributes interrupts to multiple virtual processors in the guest VM, and it incorporates feedback from Thomas Gleixner and others.
These patches change the IRQ domain code so that an IRQ domain can
match on both
Quoted 1 line
bus type and on the PCI domain. The IRQ domain match code is modified
so that
Quoted 1 line
IRQ domains can have a "rank," allowing for a default one which matches
every
Quoted 1 line
x86 PC and more specific ones that replace the default.
I'm not really fond of this approach. We already have a way to match an IRQ domain, and that's the device node. It looks to me that you're going through a lot of pain inventing a new infrastructure to avoid divorcing the two. If you could lookup your PCI IRQ domain directly based some (non-DT) identifier, and then possibly fallback to the default one, would that help?
If so, here's the deal: I have been working on a patch series that addresses the above for unrelated reasons (ACPI support on arm64). It has been posted twice already:
http://lists.infradead.org/pipermail/linux-arm-kernel/2015-July/358768.html
and the latest version is there:
https://git.kernel.org/cgit/linux/kernel/git/maz/arm-
platforms.git/log/?h=irq/gsi-irq-domain-v3
Quoted 7 lines
I have the feeling that you could replace a lot of your patches with this infrastructure.
Thoughts?
M.--
First, thank you so much for reviewing this. I've read the patch series above, but I'm sure that I might have misinterpreted it. It seems to merge the DT and ACPI GSI infrastructure, which I think is a great idea. I'm not sure, however, that it would, as it stands, provide what I need here. Please do tell me if I'm wrong.
The series above allows you to supply different IRQ domains for separate parts of the ACPI GSI space, which is fine for IRQs which are actually defined by ACPI. Message-signaled interrupts (MSI), however, aren't defined by ACPI. ACPI only talks about the routing of interrupts with pins and traces (or ones which have equivalent mechanisms like the INTx# protocol in PCI Express.)
What the older DT layer code allowed was for the PCI driver to look up an IRQ domain by walking up the device tree looking for a node that claimed to be an IRQ domain. The match() function on the IRQ domain allowed it to say that it supported interrupts on PCI buses.
What's not clear to me is how I would create an IRQ domain that matches not on ACPI GSI ranges (because ACPI doesn't talk about MSI) and not just on generic PCI buses. I need to be able to ask for an IRQ domain "from my parent" which doesn't really exist without the OF device tree or "for a specific PCI bus domain." That second one is what I was trying to enable.
Is there a way to do that with the infrastructure that you're introducing?
Thanks again,
Jake Oshins
Quoted 86 lines · Jake Oshins
Quoted 11 lines
-----Original Message-----
From: Marc Zyngier [mailto:[email protected]]
Sent: Monday, September 14, 2015 8:01 AM
To: Jake Oshins <[email protected]>; [email protected]; KY Srinivasan <[email protected]>; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; Jiang Liu <[email protected]>
Subject: Re: [PATCH v2 00/12] New paravirtual PCI front-end for Hyper-V VMsQuoted 5 lines
Hi Jake,
In the future, please CC me on anything that touches irqdomains, along with Jiang Liu as we both co-maintain this piece of code.
Absolutely. Sorry for that omission.
Quoted 34 lines · On 11/09/15 01:00, [email protected] wrote:
Quoted 8 lines
From: Jake Oshins <[email protected]>
The patch series updates the one sent about a month ago in three ways. It integrated with other IRQ domain work done in linux-next in that time, it distributes interrupts to multiple virtual processors in the guest VM, and it incorporates feedback from Thomas Gleixner and others.
These patches change the IRQ domain code so that an IRQ domain can
match on both
Quoted 1 line
bus type and on the PCI domain. The IRQ domain match code is modified
so that
Quoted 1 line
IRQ domains can have a "rank," allowing for a default one which matches
every
Quoted 1 line
x86 PC and more specific ones that replace the default.
I'm not really fond of this approach. We already have a way to match an IRQ domain, and that's the device node. It looks to me that you're going through a lot of pain inventing a new infrastructure to avoid divorcing the two. If you could lookup your PCI IRQ domain directly based some (non-DT) identifier, and then possibly fallback to the default one, would that help?
If so, here's the deal: I have been working on a patch series that addresses the above for unrelated reasons (ACPI support on arm64). It has been posted twice already:
http://lists.infradead.org/pipermail/linux-arm-kernel/2015-July/358768.html
and the latest version is there:
https://git.kernel.org/cgit/linux/kernel/git/maz/arm-
platforms.git/log/?h=irq/gsi-irq-domain-v3Quoted 7 lines
I have the feeling that you could replace a lot of your patches with this infrastructure.
Thoughts?
M.--
First, thank you so much for reviewing this. I've read the patch series above, but I'm sure that I might have misinterpreted it. It seems to merge the DT and ACPI GSI infrastructure, which I think is a great idea. I'm not sure, however, that it would, as it stands, provide what I need here. Please do tell me if I'm wrong.
The series above allows you to supply different IRQ domains for separate parts of the ACPI GSI space, which is fine for IRQs which are actually defined by ACPI. Message-signaled interrupts (MSI), however, aren't defined by ACPI. ACPI only talks about the routing of interrupts with pins and traces (or ones which have equivalent mechanisms like the INTx# protocol in PCI Express.)
What the older DT layer code allowed was for the PCI driver to look up an IRQ domain by walking up the device tree looking for a node that claimed to be an IRQ domain. The
match()function on the IRQ domain allowed it to say that it supported interrupts on PCI buses.What's not clear to me is how I would create an IRQ domain that matches not on ACPI GSI ranges (because ACPI doesn't talk about MSI) and not just on generic PCI buses. I need to be able to ask for an IRQ domain "from my parent" which doesn't really exist without the OF device tree or "for a specific PCI bus domain." That second one is what I was trying to enable.
Quoted 2 lines
Is there a way to do that with the infrastructure that you're introducing?
The ACPI/GSI stuff is a red herring, and is completely unrelated to the problem you're trying to solve. What I think is of interest to you is contained in the first three patches.
In your 4th patch, you have the following code:
+ pci_domain = pci_domain_nr(bus);
+ d = irq_find_matching_host(NULL, DOMAIN_BUS_PCI_MSI, &pci_domain);
which really feels like you're trying to create a namespace that is parallel to the one defined by the device_node parameter. What I'm trying to do is to be able to replace the device_node by something more generic (at the moment, you can either pass a device_node or some token that the irqdomain subsystem generates for you - see patch #7 for an example).
You could pass this token to pci_msi_create_irq_domain (which obviously needs some repainting not to take a device_node), store it in your bus structure, and perform the lookup based on this value. Or store the actual domain there, whatever.
What I want to do is really to make this device_node pointer for systems that do not have a DT node to pass there, which is exactly your case (by the look of it, the bus number is your identifier of choice, but I suspect a pointer to an internal structure would be better suited).
M.
Signature · 1 line
Jazz is not dead. It just smells funny...
Quoted 39 lines
-----Original Message-----
From: Marc Zyngier [mailto:[email protected]]
Sent: Tuesday, September 15, 2015 2:57 AM
To: Jake Oshins <[email protected]>; [email protected]; KY Srinivasan <[email protected]>; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; Jiang Liu <[email protected]>
Subject: Re: [PATCH v2 00/12] New paravirtual PCI front-end for Hyper-V VMsQuoted 3 lines
Is there a way to do that with the infrastructure that you're introducing?
The ACPI/GSI stuff is a red herring, and is completely unrelated to the problem you're trying to solve. What I think is of interest to you is contained in the first three patches.
In your 4th patch, you have the following code:
(quoted diff) +2
-0+ pci_domain = pci_domain_nr(bus); + d = irq_find_matching_host(NULL, DOMAIN_BUS_PCI_MSI,
&pci_domain);which really feels like you're trying to create a namespace that is parallel to the one defined by the
device_nodeparameter. What I'm trying to do is to be able to replace thedevice_nodeby something more generic (at the moment, you can either pass adevice_nodeor some token that the irqdomain subsystem generates for you - see patch #7 for an example).You could pass this token to
pci_msi_create_irq_domain(which obviously needs some repainting not to take adevice_node), store it in your bus structure, and perform the lookup based on this value. Or store the actual domain there, whatever.
Quoted 7 lines
What I want to do is really to make this
device_nodepointer for systems that do not have a DT node to pass there, which is exactly your case (by the look of it, the bus number is your identifier of choice, but I suspect a pointer to an internal structure would be better suited).M.--
Got it. I'll rebase on your changes and send this series again, using the strategy that you outline here. I may wait a little while until your patches make it into linux-next.
Thanks again,
Jake Oshins