From: Vitaly Kuznetsov <vkuznets@redhat.com>
To: Wei Liu <wei.liu@kernel.org>,
Linux on Hyper-V List <linux-hyperv@vger.kernel.org>
Cc: virtualization@lists.linux-foundation.org,
Linux Kernel List <linux-kernel@vger.kernel.org>,
Michael Kelley <mikelley@microsoft.com>,
Vineeth Pillai <viremana@linux.microsoft.com>,
Sunil Muthuswamy <sunilmut@microsoft.com>,
Nuno Das Neves <nunodasneves@linux.microsoft.com>,
Wei Liu <wei.liu@kernel.org>,
"K. Y. Srinivasan" <kys@microsoft.com>,
Haiyang Zhang <haiyangz@microsoft.com>,
Stephen Hemminger <sthemmin@microsoft.com>,
Thomas Gleixner <tglx@linutronix.de>,
Ingo Molnar <mingo@redhat.com>, Borislav Petkov <bp@alien8.de>,
"maintainer:X86 ARCHITECTURE (32-BIT AND 64-BIT)"
<x86@kernel.org>, "H. Peter Anvin" <hpa@zytor.com>
Subject: Re: [PATCH v2 17/17] x86/hyperv: handle IO-APIC when running as root
Date: Thu, 12 Nov 2020 17:56:41 +0100 [thread overview]
Message-ID: <87v9eawm2e.fsf@vitty.brq.redhat.com> (raw)
In-Reply-To: <20201105165814.29233-18-wei.liu@kernel.org>
Wei Liu <wei.liu@kernel.org> writes:
> Just like MSI/MSI-X, IO-APIC interrupts are remapped by Microsoft
> Hypervisor when Linux runs as the root partition. Implement an IRQ chip
> to handle mapping and unmapping of IO-APIC interrupts.
>
> Use custom functions for mapping and unmapping ACPI GSIs. They will
> issue Microsoft Hypervisor specific hypercalls on top of the native
> routines.
>
> Signed-off-by: Sunil Muthuswamy <sunilmut@microsoft.com>
> Co-Developed-by: Sunil Muthuswamy <sunilmut@microsoft.com>
> Signed-off-by: Wei Liu <wei.liu@kernel.org>
> ---
> arch/x86/hyperv/hv_init.c | 13 +++
> arch/x86/hyperv/irqdomain.c | 226 ++++++++++++++++++++++++++++++++++++
> 2 files changed, 239 insertions(+)
>
> diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c
> index a46b817b5b2a..2c2189832da7 100644
> --- a/arch/x86/hyperv/hv_init.c
> +++ b/arch/x86/hyperv/hv_init.c
> @@ -267,10 +267,23 @@ static int hv_cpu_die(unsigned int cpu)
> return 0;
> }
>
> +int hv_acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity);
> +void hv_acpi_unregister_gsi(u32 gsi);
> +
> +extern int (*native_acpi_register_gsi)(struct device *dev, u32 gsi, int trigger, int polarity);
> +extern void (*native_acpi_unregister_gsi)(u32 gsi);
> +
> static int __init hv_pci_init(void)
> {
> int gen2vm = efi_enabled(EFI_BOOT);
>
> + if (hv_root_partition) {
> + native_acpi_register_gsi = __acpi_register_gsi;
> + native_acpi_unregister_gsi = __acpi_unregister_gsi;
> + __acpi_register_gsi = hv_acpi_register_gsi;
> + __acpi_unregister_gsi = hv_acpi_unregister_gsi;
> + }
> +
> /*
> * For Generation-2 VM, we exit from pci_arch_init() by returning 0.
> * The purpose is to suppress the harmless warning:
> diff --git a/arch/x86/hyperv/irqdomain.c b/arch/x86/hyperv/irqdomain.c
> index 80109e3cbf8f..ae9a728589a4 100644
> --- a/arch/x86/hyperv/irqdomain.c
> +++ b/arch/x86/hyperv/irqdomain.c
> @@ -9,6 +9,8 @@
> #include <linux/pci.h>
> #include <linux/irq.h>
> #include <asm/mshyperv.h>
> +#include <asm/apic.h>
> +#include <asm/io_apic.h>
>
> struct rid_data {
> struct pci_dev *bridge;
> @@ -328,3 +330,227 @@ struct irq_domain * __init hv_create_pci_msi_domain(void)
> return d;
> }
>
> +/* Copied from io_apic.c */
> +union entry_union {
> + struct { u32 w1, w2; };
> + struct IO_APIC_route_entry entry;
> +};
> +
> +static int hv_unmap_ioapic_interrupt(int gsi)
> +{
> + union hv_device_id device_id;
> + int ioapic, ioapic_id;
> + u8 ioapic_pin;
> + struct IO_APIC_route_entry ire;
> + union entry_union eu;
> + struct hv_interrupt_entry entry;
> +
> + ioapic = mp_find_ioapic(gsi);
> + ioapic_pin = mp_find_ioapic_pin(ioapic, gsi);
> + ioapic_id = mpc_ioapic_id(ioapic);
> + ire = ioapic_read_entry(ioapic, ioapic_pin);
> +
> + eu.entry = ire;
> +
> + /*
> + * Polarity may have been set by us, but Hyper-V expects the exact same
> + * entry. See the mapping routine.
> + */
> + eu.entry.polarity = 0;
> +
> + memset(&entry, 0, sizeof(entry));
> + entry.source = HV_INTERRUPT_SOURCE_IOAPIC;
> + entry.ioapic_rte.low_uint32 = eu.w1;
> + entry.ioapic_rte.high_uint32 = eu.w2;
> +
> + device_id.as_uint64 = 0;
> + device_id.device_type = HV_DEVICE_TYPE_IOAPIC;
> + device_id.ioapic.ioapic_id = (u8)ioapic_id;
> +
> + return hv_unmap_interrupt(device_id.as_uint64, &entry) & HV_HYPERCALL_RESULT_MASK;
> +}
> +
> +static int hv_map_ioapic_interrupt(int ioapic_id, int trigger, int vcpu, int vector,
> + struct hv_interrupt_entry *out_entry)
> +{
> + unsigned long flags;
> + struct hv_input_map_device_interrupt *input;
> + struct hv_output_map_device_interrupt *output;
> + union hv_device_id device_id;
> + struct hv_device_interrupt_descriptor *intr_desc;
> + u16 status;
> +
> + device_id.as_uint64 = 0;
> + device_id.device_type = HV_DEVICE_TYPE_IOAPIC;
> + device_id.ioapic.ioapic_id = (u8)ioapic_id;
> +
> + local_irq_save(flags);
> + input = *this_cpu_ptr(hyperv_pcpu_input_arg);
> + output = *this_cpu_ptr(hyperv_pcpu_output_arg);
> + memset(input, 0, sizeof(*input));
> + intr_desc = &input->interrupt_descriptor;
> + input->partition_id = hv_current_partition_id;
> + input->device_id = device_id.as_uint64;
> + intr_desc->interrupt_type = HV_X64_INTERRUPT_TYPE_FIXED;
> + intr_desc->target.vector = vector;
> + intr_desc->vector_count = 1;
> +
> + if (trigger)
> + intr_desc->trigger_mode = HV_INTERRUPT_TRIGGER_MODE_LEVEL;
> + else
> + intr_desc->trigger_mode = HV_INTERRUPT_TRIGGER_MODE_EDGE;
> +
> + __set_bit(vcpu, (unsigned long *)&intr_desc->target.vp_mask);
> +
> + status = hv_do_rep_hypercall(HVCALL_MAP_DEVICE_INTERRUPT, 0, 0, input, output) &
> + HV_HYPERCALL_RESULT_MASK;
> + local_irq_restore(flags);
> +
> + *out_entry = output->interrupt_entry;
> +
> + return status;
> +}
> +
> +static unsigned int hv_ioapic_startup_irq(struct irq_data *data)
> +{
> + u16 status;
> + struct IO_APIC_route_entry ire;
> + u32 vector;
> + struct irq_cfg *cfg;
> + int ioapic;
> + u8 ioapic_pin;
> + int ioapic_id;
> + int gsi;
> + union entry_union eu;
> + struct cpumask *affinity;
> + int cpu, vcpu;
> + struct hv_interrupt_entry entry;
> + struct mp_chip_data *mp_data = data->chip_data;
> +
> + gsi = data->irq;
> + cfg = irqd_cfg(data);
> + affinity = irq_data_get_effective_affinity_mask(data);
> + cpu = cpumask_first_and(affinity, cpu_online_mask);
> + vcpu = hv_cpu_number_to_vp_number(cpu);
> +
> + vector = cfg->vector;
> +
> + ioapic = mp_find_ioapic(gsi);
> + ioapic_pin = mp_find_ioapic_pin(ioapic, gsi);
> + ioapic_id = mpc_ioapic_id(ioapic);
> + ire = ioapic_read_entry(ioapic, ioapic_pin);
> +
> + /*
> + * Always try unmapping. We do not have visibility into which whether
> + * an IO-APIC has been mapped or not. We can't use chip_data because it
> + * already points to mp_data.
> + *
> + * We don't use retarget interrupt hypercalls here because Hyper-V
> + * doens't allow root to change the vector or specify VPs outside of
> + * the set that is initially used during mapping.
> + */
> + status = hv_unmap_ioapic_interrupt(gsi);
> +
> + if (!(status == HV_STATUS_SUCCESS || status == HV_STATUS_INVALID_PARAMETER)) {
> + pr_debug("%s: unexpected unmap status %d\n", __func__, status);
> + return -1;
Nit: the function returns 'unsigned int' but I see other 'irq_startup'
routines return negative values too, however, they tend to returd
'-ESOMETHING' so maybe -EFAULT here?
> + }
> +
> + status = hv_map_ioapic_interrupt(ioapic_id, ire.trigger, vcpu, vector, &entry);
> +
> + if (status != HV_STATUS_SUCCESS) {
> + pr_err("%s: map hypercall failed, status %d\n", __func__, status);
> + return -1;
and here.
> + }
> +
> + /* Update the entry in mp_chip_data. It is used in other places. */
> + mp_data->entry = *(struct IO_APIC_route_entry *)&entry.ioapic_rte;
> +
> + /* Sync polarity -- Hyper-V's returned polarity is always 0... */
> + mp_data->entry.polarity = ire.polarity;
> +
> + eu.w1 = entry.ioapic_rte.low_uint32;
> + eu.w2 = entry.ioapic_rte.high_uint32;
> + ioapic_write_entry(ioapic, ioapic_pin, eu.entry);
> +
> + return 0;
> +}
> +
> +static void hv_ioapic_mask_irq(struct irq_data *data)
> +{
> + mask_ioapic_irq(data);
> +}
> +
> +static void hv_ioapic_unmask_irq(struct irq_data *data)
> +{
> + unmask_ioapic_irq(data);
> +}
> +
> +static int hv_ioapic_set_affinity(struct irq_data *data,
> + const struct cpumask *mask, bool force)
> +{
> + /*
> + * We only update the affinity mask here. Programming the hardware is
> + * done in irq_startup.
> + */
> + return ioapic_set_affinity(data, mask, force);
> +}
> +
> +void hv_ioapic_ack_level(struct irq_data *irq_data)
> +{
> + /*
> + * Per email exchange with Hyper-V team, all is needed is write to
> + * LAPIC's EOI register. They don't support directed EOI to IO-APIC.
> + * Hyper-V handles it for us.
> + */
> + apic_ack_irq(irq_data);
> +}
> +
> +struct irq_chip hv_ioapic_chip __read_mostly = {
> + .name = "HV-IO-APIC",
> + .irq_startup = hv_ioapic_startup_irq,
> + .irq_mask = hv_ioapic_mask_irq,
> + .irq_unmask = hv_ioapic_unmask_irq,
> + .irq_ack = irq_chip_ack_parent,
> + .irq_eoi = hv_ioapic_ack_level,
> + .irq_set_affinity = hv_ioapic_set_affinity,
> + .irq_retrigger = irq_chip_retrigger_hierarchy,
> + .irq_get_irqchip_state = ioapic_irq_get_chip_state,
> + .flags = IRQCHIP_SKIP_SET_WAKE,
> +};
> +
> +
> +int (*native_acpi_register_gsi)(struct device *dev, u32 gsi, int trigger, int polarity);
> +void (*native_acpi_unregister_gsi)(u32 gsi);
> +
> +int hv_acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)
> +{
> + int irq = gsi;
> +
> +#ifdef CONFIG_X86_IO_APIC
> + irq = native_acpi_register_gsi(dev, gsi, trigger, polarity);
> + if (irq < 0) {
> + pr_err("native_acpi_register_gsi failed %d\n", irq);
> + return irq;
> + }
> +
> + if (trigger) {
> + irq_set_status_flags(irq, IRQ_LEVEL);
> + irq_set_chip_and_handler_name(irq, &hv_ioapic_chip,
> + handle_fasteoi_irq, "ioapic-fasteoi");
> + } else {
> + irq_clear_status_flags(irq, IRQ_LEVEL);
> + irq_set_chip_and_handler_name(irq, &hv_ioapic_chip,
> + handle_edge_irq, "ioapic-edge");
> + }
> +#endif
> + return irq;
> +}
> +
> +void hv_acpi_unregister_gsi(u32 gsi)
> +{
> +#ifdef CONFIG_X86_IO_APIC
> + (void)hv_unmap_ioapic_interrupt(gsi);
> + native_acpi_unregister_gsi(gsi);
> +#endif
> +}
--
Vitaly
WARNING: multiple messages have this Message-ID (diff)
From: Vitaly Kuznetsov <vkuznets@redhat.com>
To: Wei Liu <wei.liu@kernel.org>,
Linux on Hyper-V List <linux-hyperv@vger.kernel.org>
Cc: Wei Liu <wei.liu@kernel.org>,
Stephen Hemminger <sthemmin@microsoft.com>,
Haiyang Zhang <haiyangz@microsoft.com>,
"maintainer:X86 ARCHITECTURE \(32-BIT AND 64-BIT\)"
<x86@kernel.org>,
Linux Kernel List <linux-kernel@vger.kernel.org>,
Michael Kelley <mikelley@microsoft.com>,
Ingo Molnar <mingo@redhat.com>, Borislav Petkov <bp@alien8.de>,
"H. Peter Anvin" <hpa@zytor.com>,
Nuno Das Neves <nunodasneves@linux.microsoft.com>,
Sunil Muthuswamy <sunilmut@microsoft.com>,
virtualization@lists.linux-foundation.org,
Vineeth Pillai <viremana@linux.microsoft.com>,
Thomas Gleixner <tglx@linutronix.de>
Subject: Re: [PATCH v2 17/17] x86/hyperv: handle IO-APIC when running as root
Date: Thu, 12 Nov 2020 17:56:41 +0100 [thread overview]
Message-ID: <87v9eawm2e.fsf@vitty.brq.redhat.com> (raw)
In-Reply-To: <20201105165814.29233-18-wei.liu@kernel.org>
Wei Liu <wei.liu@kernel.org> writes:
> Just like MSI/MSI-X, IO-APIC interrupts are remapped by Microsoft
> Hypervisor when Linux runs as the root partition. Implement an IRQ chip
> to handle mapping and unmapping of IO-APIC interrupts.
>
> Use custom functions for mapping and unmapping ACPI GSIs. They will
> issue Microsoft Hypervisor specific hypercalls on top of the native
> routines.
>
> Signed-off-by: Sunil Muthuswamy <sunilmut@microsoft.com>
> Co-Developed-by: Sunil Muthuswamy <sunilmut@microsoft.com>
> Signed-off-by: Wei Liu <wei.liu@kernel.org>
> ---
> arch/x86/hyperv/hv_init.c | 13 +++
> arch/x86/hyperv/irqdomain.c | 226 ++++++++++++++++++++++++++++++++++++
> 2 files changed, 239 insertions(+)
>
> diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c
> index a46b817b5b2a..2c2189832da7 100644
> --- a/arch/x86/hyperv/hv_init.c
> +++ b/arch/x86/hyperv/hv_init.c
> @@ -267,10 +267,23 @@ static int hv_cpu_die(unsigned int cpu)
> return 0;
> }
>
> +int hv_acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity);
> +void hv_acpi_unregister_gsi(u32 gsi);
> +
> +extern int (*native_acpi_register_gsi)(struct device *dev, u32 gsi, int trigger, int polarity);
> +extern void (*native_acpi_unregister_gsi)(u32 gsi);
> +
> static int __init hv_pci_init(void)
> {
> int gen2vm = efi_enabled(EFI_BOOT);
>
> + if (hv_root_partition) {
> + native_acpi_register_gsi = __acpi_register_gsi;
> + native_acpi_unregister_gsi = __acpi_unregister_gsi;
> + __acpi_register_gsi = hv_acpi_register_gsi;
> + __acpi_unregister_gsi = hv_acpi_unregister_gsi;
> + }
> +
> /*
> * For Generation-2 VM, we exit from pci_arch_init() by returning 0.
> * The purpose is to suppress the harmless warning:
> diff --git a/arch/x86/hyperv/irqdomain.c b/arch/x86/hyperv/irqdomain.c
> index 80109e3cbf8f..ae9a728589a4 100644
> --- a/arch/x86/hyperv/irqdomain.c
> +++ b/arch/x86/hyperv/irqdomain.c
> @@ -9,6 +9,8 @@
> #include <linux/pci.h>
> #include <linux/irq.h>
> #include <asm/mshyperv.h>
> +#include <asm/apic.h>
> +#include <asm/io_apic.h>
>
> struct rid_data {
> struct pci_dev *bridge;
> @@ -328,3 +330,227 @@ struct irq_domain * __init hv_create_pci_msi_domain(void)
> return d;
> }
>
> +/* Copied from io_apic.c */
> +union entry_union {
> + struct { u32 w1, w2; };
> + struct IO_APIC_route_entry entry;
> +};
> +
> +static int hv_unmap_ioapic_interrupt(int gsi)
> +{
> + union hv_device_id device_id;
> + int ioapic, ioapic_id;
> + u8 ioapic_pin;
> + struct IO_APIC_route_entry ire;
> + union entry_union eu;
> + struct hv_interrupt_entry entry;
> +
> + ioapic = mp_find_ioapic(gsi);
> + ioapic_pin = mp_find_ioapic_pin(ioapic, gsi);
> + ioapic_id = mpc_ioapic_id(ioapic);
> + ire = ioapic_read_entry(ioapic, ioapic_pin);
> +
> + eu.entry = ire;
> +
> + /*
> + * Polarity may have been set by us, but Hyper-V expects the exact same
> + * entry. See the mapping routine.
> + */
> + eu.entry.polarity = 0;
> +
> + memset(&entry, 0, sizeof(entry));
> + entry.source = HV_INTERRUPT_SOURCE_IOAPIC;
> + entry.ioapic_rte.low_uint32 = eu.w1;
> + entry.ioapic_rte.high_uint32 = eu.w2;
> +
> + device_id.as_uint64 = 0;
> + device_id.device_type = HV_DEVICE_TYPE_IOAPIC;
> + device_id.ioapic.ioapic_id = (u8)ioapic_id;
> +
> + return hv_unmap_interrupt(device_id.as_uint64, &entry) & HV_HYPERCALL_RESULT_MASK;
> +}
> +
> +static int hv_map_ioapic_interrupt(int ioapic_id, int trigger, int vcpu, int vector,
> + struct hv_interrupt_entry *out_entry)
> +{
> + unsigned long flags;
> + struct hv_input_map_device_interrupt *input;
> + struct hv_output_map_device_interrupt *output;
> + union hv_device_id device_id;
> + struct hv_device_interrupt_descriptor *intr_desc;
> + u16 status;
> +
> + device_id.as_uint64 = 0;
> + device_id.device_type = HV_DEVICE_TYPE_IOAPIC;
> + device_id.ioapic.ioapic_id = (u8)ioapic_id;
> +
> + local_irq_save(flags);
> + input = *this_cpu_ptr(hyperv_pcpu_input_arg);
> + output = *this_cpu_ptr(hyperv_pcpu_output_arg);
> + memset(input, 0, sizeof(*input));
> + intr_desc = &input->interrupt_descriptor;
> + input->partition_id = hv_current_partition_id;
> + input->device_id = device_id.as_uint64;
> + intr_desc->interrupt_type = HV_X64_INTERRUPT_TYPE_FIXED;
> + intr_desc->target.vector = vector;
> + intr_desc->vector_count = 1;
> +
> + if (trigger)
> + intr_desc->trigger_mode = HV_INTERRUPT_TRIGGER_MODE_LEVEL;
> + else
> + intr_desc->trigger_mode = HV_INTERRUPT_TRIGGER_MODE_EDGE;
> +
> + __set_bit(vcpu, (unsigned long *)&intr_desc->target.vp_mask);
> +
> + status = hv_do_rep_hypercall(HVCALL_MAP_DEVICE_INTERRUPT, 0, 0, input, output) &
> + HV_HYPERCALL_RESULT_MASK;
> + local_irq_restore(flags);
> +
> + *out_entry = output->interrupt_entry;
> +
> + return status;
> +}
> +
> +static unsigned int hv_ioapic_startup_irq(struct irq_data *data)
> +{
> + u16 status;
> + struct IO_APIC_route_entry ire;
> + u32 vector;
> + struct irq_cfg *cfg;
> + int ioapic;
> + u8 ioapic_pin;
> + int ioapic_id;
> + int gsi;
> + union entry_union eu;
> + struct cpumask *affinity;
> + int cpu, vcpu;
> + struct hv_interrupt_entry entry;
> + struct mp_chip_data *mp_data = data->chip_data;
> +
> + gsi = data->irq;
> + cfg = irqd_cfg(data);
> + affinity = irq_data_get_effective_affinity_mask(data);
> + cpu = cpumask_first_and(affinity, cpu_online_mask);
> + vcpu = hv_cpu_number_to_vp_number(cpu);
> +
> + vector = cfg->vector;
> +
> + ioapic = mp_find_ioapic(gsi);
> + ioapic_pin = mp_find_ioapic_pin(ioapic, gsi);
> + ioapic_id = mpc_ioapic_id(ioapic);
> + ire = ioapic_read_entry(ioapic, ioapic_pin);
> +
> + /*
> + * Always try unmapping. We do not have visibility into which whether
> + * an IO-APIC has been mapped or not. We can't use chip_data because it
> + * already points to mp_data.
> + *
> + * We don't use retarget interrupt hypercalls here because Hyper-V
> + * doens't allow root to change the vector or specify VPs outside of
> + * the set that is initially used during mapping.
> + */
> + status = hv_unmap_ioapic_interrupt(gsi);
> +
> + if (!(status == HV_STATUS_SUCCESS || status == HV_STATUS_INVALID_PARAMETER)) {
> + pr_debug("%s: unexpected unmap status %d\n", __func__, status);
> + return -1;
Nit: the function returns 'unsigned int' but I see other 'irq_startup'
routines return negative values too, however, they tend to returd
'-ESOMETHING' so maybe -EFAULT here?
> + }
> +
> + status = hv_map_ioapic_interrupt(ioapic_id, ire.trigger, vcpu, vector, &entry);
> +
> + if (status != HV_STATUS_SUCCESS) {
> + pr_err("%s: map hypercall failed, status %d\n", __func__, status);
> + return -1;
and here.
> + }
> +
> + /* Update the entry in mp_chip_data. It is used in other places. */
> + mp_data->entry = *(struct IO_APIC_route_entry *)&entry.ioapic_rte;
> +
> + /* Sync polarity -- Hyper-V's returned polarity is always 0... */
> + mp_data->entry.polarity = ire.polarity;
> +
> + eu.w1 = entry.ioapic_rte.low_uint32;
> + eu.w2 = entry.ioapic_rte.high_uint32;
> + ioapic_write_entry(ioapic, ioapic_pin, eu.entry);
> +
> + return 0;
> +}
> +
> +static void hv_ioapic_mask_irq(struct irq_data *data)
> +{
> + mask_ioapic_irq(data);
> +}
> +
> +static void hv_ioapic_unmask_irq(struct irq_data *data)
> +{
> + unmask_ioapic_irq(data);
> +}
> +
> +static int hv_ioapic_set_affinity(struct irq_data *data,
> + const struct cpumask *mask, bool force)
> +{
> + /*
> + * We only update the affinity mask here. Programming the hardware is
> + * done in irq_startup.
> + */
> + return ioapic_set_affinity(data, mask, force);
> +}
> +
> +void hv_ioapic_ack_level(struct irq_data *irq_data)
> +{
> + /*
> + * Per email exchange with Hyper-V team, all is needed is write to
> + * LAPIC's EOI register. They don't support directed EOI to IO-APIC.
> + * Hyper-V handles it for us.
> + */
> + apic_ack_irq(irq_data);
> +}
> +
> +struct irq_chip hv_ioapic_chip __read_mostly = {
> + .name = "HV-IO-APIC",
> + .irq_startup = hv_ioapic_startup_irq,
> + .irq_mask = hv_ioapic_mask_irq,
> + .irq_unmask = hv_ioapic_unmask_irq,
> + .irq_ack = irq_chip_ack_parent,
> + .irq_eoi = hv_ioapic_ack_level,
> + .irq_set_affinity = hv_ioapic_set_affinity,
> + .irq_retrigger = irq_chip_retrigger_hierarchy,
> + .irq_get_irqchip_state = ioapic_irq_get_chip_state,
> + .flags = IRQCHIP_SKIP_SET_WAKE,
> +};
> +
> +
> +int (*native_acpi_register_gsi)(struct device *dev, u32 gsi, int trigger, int polarity);
> +void (*native_acpi_unregister_gsi)(u32 gsi);
> +
> +int hv_acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)
> +{
> + int irq = gsi;
> +
> +#ifdef CONFIG_X86_IO_APIC
> + irq = native_acpi_register_gsi(dev, gsi, trigger, polarity);
> + if (irq < 0) {
> + pr_err("native_acpi_register_gsi failed %d\n", irq);
> + return irq;
> + }
> +
> + if (trigger) {
> + irq_set_status_flags(irq, IRQ_LEVEL);
> + irq_set_chip_and_handler_name(irq, &hv_ioapic_chip,
> + handle_fasteoi_irq, "ioapic-fasteoi");
> + } else {
> + irq_clear_status_flags(irq, IRQ_LEVEL);
> + irq_set_chip_and_handler_name(irq, &hv_ioapic_chip,
> + handle_edge_irq, "ioapic-edge");
> + }
> +#endif
> + return irq;
> +}
> +
> +void hv_acpi_unregister_gsi(u32 gsi)
> +{
> +#ifdef CONFIG_X86_IO_APIC
> + (void)hv_unmap_ioapic_interrupt(gsi);
> + native_acpi_unregister_gsi(gsi);
> +#endif
> +}
--
Vitaly
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
next prev parent reply other threads:[~2020-11-12 16:56 UTC|newest]
Thread overview: 88+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-11-05 16:57 [PATCH v2 00/17] Introducing Linux root partition support for Microsoft Hypervisor Wei Liu
2020-11-05 16:57 ` [PATCH v2 01/17] asm-generic/hyperv: change HV_CPU_POWER_MANAGEMENT to HV_CPU_MANAGEMENT Wei Liu
2020-11-12 15:14 ` Vitaly Kuznetsov
2020-11-12 15:14 ` Vitaly Kuznetsov
2020-11-05 16:57 ` [PATCH v2 02/17] x86/hyperv: detect if Linux is the root partition Wei Liu
2020-11-05 19:16 ` kernel test robot
2020-11-05 19:16 ` kernel test robot
2020-11-05 19:16 ` kernel test robot
2020-11-12 11:42 ` Wei Liu
2020-11-12 11:42 ` Wei Liu
2020-11-12 11:46 ` Wei Liu
2020-11-12 11:46 ` Wei Liu
2020-11-12 12:22 ` Wei Liu
2020-11-12 12:22 ` Wei Liu
2020-11-05 20:23 ` kernel test robot
2020-11-05 20:23 ` kernel test robot
2020-11-05 20:23 ` kernel test robot
2020-11-12 15:16 ` Vitaly Kuznetsov
2020-11-12 15:16 ` Vitaly Kuznetsov
2020-11-12 15:51 ` Wei Liu
2020-11-05 16:58 ` [PATCH v2 03/17] Drivers: hv: vmbus: skip VMBus initialization if Linux is root Wei Liu
2020-11-12 15:24 ` Vitaly Kuznetsov
2020-11-12 15:24 ` Vitaly Kuznetsov
2020-11-13 14:51 ` Wei Liu
2020-11-05 16:58 ` [PATCH v2 04/17] iommu/hyperv: don't setup IRQ remapping when running as root Wei Liu
2020-11-05 16:58 ` Wei Liu
2020-11-12 15:27 ` Vitaly Kuznetsov
2020-11-12 15:27 ` Vitaly Kuznetsov
2020-11-12 15:27 ` Vitaly Kuznetsov
2020-11-13 14:53 ` Wei Liu
2020-11-13 14:53 ` Wei Liu
2020-11-05 16:58 ` [PATCH v2 05/17] clocksource/hyperv: use MSR-based access if " Wei Liu
2020-11-12 9:56 ` Daniel Lezcano
2020-11-12 9:56 ` Daniel Lezcano
2020-11-12 11:24 ` Wei Liu
2020-11-12 11:40 ` Daniel Lezcano
2020-11-12 11:40 ` Daniel Lezcano
2020-11-12 11:42 ` Wei Liu
2020-11-12 15:30 ` Vitaly Kuznetsov
2020-11-12 15:30 ` Vitaly Kuznetsov
2020-11-12 15:52 ` Wei Liu
2020-11-05 16:58 ` [PATCH v2 06/17] x86/hyperv: allocate output arg pages if required Wei Liu
2020-11-12 15:35 ` Vitaly Kuznetsov
2020-11-12 15:35 ` Vitaly Kuznetsov
2020-11-13 15:05 ` Wei Liu
2020-11-05 16:58 ` [PATCH v2 07/17] x86/hyperv: extract partition ID from Microsoft Hypervisor if necessary Wei Liu
2020-11-05 20:07 ` kernel test robot
2020-11-05 20:07 ` kernel test robot
2020-11-05 20:07 ` kernel test robot
2020-11-12 11:54 ` Wei Liu
2020-11-12 11:54 ` Wei Liu
2020-11-05 20:20 ` kernel test robot
2020-11-05 20:20 ` kernel test robot
2020-11-05 20:20 ` kernel test robot
2020-11-12 15:44 ` Vitaly Kuznetsov
2020-11-12 15:44 ` Vitaly Kuznetsov
2020-11-13 15:21 ` Wei Liu
2020-11-05 16:58 ` [PATCH v2 08/17] x86/hyperv: handling hypercall page setup for root Wei Liu
2020-11-12 15:51 ` Vitaly Kuznetsov
2020-11-12 15:51 ` Vitaly Kuznetsov
2020-11-13 15:33 ` Wei Liu
2020-11-13 16:09 ` Wei Liu
2020-11-13 16:16 ` Vitaly Kuznetsov
2020-11-13 16:16 ` Vitaly Kuznetsov
2020-11-05 16:58 ` [PATCH v2 09/17] x86/hyperv: provide a bunch of helper functions Wei Liu
2020-11-12 15:57 ` Vitaly Kuznetsov
2020-11-12 15:57 ` Vitaly Kuznetsov
2020-11-13 15:51 ` Wei Liu
2020-11-13 16:13 ` Vitaly Kuznetsov
2020-11-13 16:13 ` Vitaly Kuznetsov
2020-11-16 11:41 ` Wei Liu
2020-11-05 16:58 ` [PATCH v2 10/17] x86/hyperv: implement and use hv_smp_prepare_cpus Wei Liu
2020-11-12 16:44 ` Vitaly Kuznetsov
2020-11-12 16:44 ` Vitaly Kuznetsov
2020-11-13 15:56 ` Wei Liu
2020-11-05 16:58 ` [PATCH v2 11/17] asm-generic/hyperv: update hv_msi_entry Wei Liu
2020-11-05 16:58 ` [PATCH v2 12/17] asm-generic/hyperv: update hv_interrupt_entry Wei Liu
2020-11-05 16:58 ` [PATCH v2 13/17] asm-generic/hyperv: introduce hv_device_id and auxiliary structures Wei Liu
2020-11-05 16:58 ` [PATCH v2 14/17] asm-generic/hyperv: import data structures for mapping device interrupts Wei Liu
2020-11-05 16:58 ` [PATCH v2 15/17] x86/hyperv: implement an MSI domain for root partition Wei Liu
2020-11-12 13:50 ` Wei Liu
2020-11-05 16:58 ` [PATCH v2 16/17] x86/ioapic: export a few functions and data structures via io_apic.h Wei Liu
2020-11-12 11:39 ` Wei Liu
2020-11-05 16:58 ` [PATCH v2 17/17] x86/hyperv: handle IO-APIC when running as root Wei Liu
2020-11-12 16:56 ` Vitaly Kuznetsov [this message]
2020-11-12 16:56 ` Vitaly Kuznetsov
2020-11-13 16:01 ` Wei Liu
2020-11-13 16:04 ` Wei Liu
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87v9eawm2e.fsf@vitty.brq.redhat.com \
--to=vkuznets@redhat.com \
--cc=bp@alien8.de \
--cc=haiyangz@microsoft.com \
--cc=hpa@zytor.com \
--cc=kys@microsoft.com \
--cc=linux-hyperv@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mikelley@microsoft.com \
--cc=mingo@redhat.com \
--cc=nunodasneves@linux.microsoft.com \
--cc=sthemmin@microsoft.com \
--cc=sunilmut@microsoft.com \
--cc=tglx@linutronix.de \
--cc=viremana@linux.microsoft.com \
--cc=virtualization@lists.linux-foundation.org \
--cc=wei.liu@kernel.org \
--cc=x86@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.