Commit 626b901f authored by Michael Kelley's avatar Michael Kelley Committed by Wei Liu

Drivers: hv: vmbus: Add parsing of VMbus interrupt in ACPI DSDT

On ARM64, Hyper-V now specifies the interrupt to be used by VMbus
in the ACPI DSDT.  This information is not used on x86 because the
interrupt vector must be hardcoded.  But update the generic
VMbus driver to do the parsing and pass the information to the
architecture specific code that sets up the Linux IRQ.  Update
consumers of the interrupt to get it from an architecture specific
function.
Signed-off-by: default avatarMichael Kelley <mikelley@microsoft.com>
Link: https://lore.kernel.org/r/1597434304-40631-1-git-send-email-mikelley@microsoft.comSigned-off-by: default avatarWei Liu <wei.liu@kernel.org>
parent 1f3aed01
...@@ -54,6 +54,7 @@ typedef int (*hyperv_fill_flush_list_func)( ...@@ -54,6 +54,7 @@ typedef int (*hyperv_fill_flush_list_func)(
#define hv_enable_vdso_clocksource() \ #define hv_enable_vdso_clocksource() \
vclocks_set_used(VDSO_CLOCKMODE_HVCLOCK); vclocks_set_used(VDSO_CLOCKMODE_HVCLOCK);
#define hv_get_raw_timer() rdtsc_ordered() #define hv_get_raw_timer() rdtsc_ordered()
#define hv_get_vector() HYPERVISOR_CALLBACK_VECTOR
/* /*
* Reference to pv_ops must be inline so objtool * Reference to pv_ops must be inline so objtool
......
...@@ -55,9 +55,14 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_hyperv_callback) ...@@ -55,9 +55,14 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_hyperv_callback)
set_irq_regs(old_regs); set_irq_regs(old_regs);
} }
void hv_setup_vmbus_irq(void (*handler)(void)) int hv_setup_vmbus_irq(int irq, void (*handler)(void))
{ {
/*
* The 'irq' argument is ignored on x86/x64 because a hard-coded
* interrupt vector is used for Hyper-V interrupts.
*/
vmbus_handler = handler; vmbus_handler = handler;
return 0;
} }
void hv_remove_vmbus_irq(void) void hv_remove_vmbus_irq(void)
......
...@@ -180,7 +180,7 @@ void hv_synic_enable_regs(unsigned int cpu) ...@@ -180,7 +180,7 @@ void hv_synic_enable_regs(unsigned int cpu)
/* Setup the shared SINT. */ /* Setup the shared SINT. */
hv_get_synint_state(VMBUS_MESSAGE_SINT, shared_sint.as_uint64); hv_get_synint_state(VMBUS_MESSAGE_SINT, shared_sint.as_uint64);
shared_sint.vector = HYPERVISOR_CALLBACK_VECTOR; shared_sint.vector = hv_get_vector();
shared_sint.masked = false; shared_sint.masked = false;
shared_sint.auto_eoi = hv_recommend_using_aeoi(); shared_sint.auto_eoi = hv_recommend_using_aeoi();
hv_set_synint_state(VMBUS_MESSAGE_SINT, shared_sint.as_uint64); hv_set_synint_state(VMBUS_MESSAGE_SINT, shared_sint.as_uint64);
......
...@@ -48,6 +48,10 @@ static int hyperv_cpuhp_online; ...@@ -48,6 +48,10 @@ static int hyperv_cpuhp_online;
static void *hv_panic_page; static void *hv_panic_page;
/* Values parsed from ACPI DSDT */
static int vmbus_irq;
int vmbus_interrupt;
/* /*
* Boolean to control whether to report panic messages over Hyper-V. * Boolean to control whether to report panic messages over Hyper-V.
* *
...@@ -1347,7 +1351,7 @@ static void vmbus_isr(void) ...@@ -1347,7 +1351,7 @@ static void vmbus_isr(void)
tasklet_schedule(&hv_cpu->msg_dpc); tasklet_schedule(&hv_cpu->msg_dpc);
} }
add_interrupt_randomness(HYPERVISOR_CALLBACK_VECTOR, 0); add_interrupt_randomness(hv_get_vector(), 0);
} }
/* /*
...@@ -1430,7 +1434,9 @@ static int vmbus_bus_init(void) ...@@ -1430,7 +1434,9 @@ static int vmbus_bus_init(void)
if (ret) if (ret)
return ret; return ret;
hv_setup_vmbus_irq(vmbus_isr); ret = hv_setup_vmbus_irq(vmbus_irq, vmbus_isr);
if (ret)
goto err_setup;
ret = hv_synic_alloc(); ret = hv_synic_alloc();
if (ret) if (ret)
...@@ -1505,7 +1511,7 @@ static int vmbus_bus_init(void) ...@@ -1505,7 +1511,7 @@ static int vmbus_bus_init(void)
hv_synic_free(); hv_synic_free();
err_alloc: err_alloc:
hv_remove_vmbus_irq(); hv_remove_vmbus_irq();
err_setup:
bus_unregister(&hv_bus); bus_unregister(&hv_bus);
unregister_sysctl_table(hv_ctl_table_hdr); unregister_sysctl_table(hv_ctl_table_hdr);
hv_ctl_table_hdr = NULL; hv_ctl_table_hdr = NULL;
...@@ -2070,6 +2076,7 @@ static acpi_status vmbus_walk_resources(struct acpi_resource *res, void *ctx) ...@@ -2070,6 +2076,7 @@ static acpi_status vmbus_walk_resources(struct acpi_resource *res, void *ctx)
struct resource *new_res; struct resource *new_res;
struct resource **old_res = &hyperv_mmio; struct resource **old_res = &hyperv_mmio;
struct resource **prev_res = NULL; struct resource **prev_res = NULL;
struct resource r;
switch (res->type) { switch (res->type) {
...@@ -2088,6 +2095,23 @@ static acpi_status vmbus_walk_resources(struct acpi_resource *res, void *ctx) ...@@ -2088,6 +2095,23 @@ static acpi_status vmbus_walk_resources(struct acpi_resource *res, void *ctx)
end = res->data.address64.address.maximum; end = res->data.address64.address.maximum;
break; break;
/*
* The IRQ information is needed only on ARM64, which Hyper-V
* sets up in the extended format. IRQ information is present
* on x86/x64 in the non-extended format but it is not used by
* Linux. So don't bother checking for the non-extended format.
*/
case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
if (!acpi_dev_resource_interrupt(res, 0, &r)) {
pr_err("Unable to parse Hyper-V ACPI interrupt\n");
return AE_ERROR;
}
/* ARM64 INTID for VMbus */
vmbus_interrupt = res->data.extended_irq.interrupts[0];
/* Linux IRQ number */
vmbus_irq = r.start;
return AE_OK;
default: default:
/* Unused resource type */ /* Unused resource type */
return AE_OK; return AE_OK;
......
...@@ -89,7 +89,7 @@ static inline void vmbus_signal_eom(struct hv_message *msg, u32 old_msg_type) ...@@ -89,7 +89,7 @@ static inline void vmbus_signal_eom(struct hv_message *msg, u32 old_msg_type)
} }
} }
void hv_setup_vmbus_irq(void (*handler)(void)); int hv_setup_vmbus_irq(int irq, void (*handler)(void));
void hv_remove_vmbus_irq(void); void hv_remove_vmbus_irq(void);
void hv_enable_vmbus_irq(void); void hv_enable_vmbus_irq(void);
void hv_disable_vmbus_irq(void); void hv_disable_vmbus_irq(void);
...@@ -99,6 +99,8 @@ void hv_remove_kexec_handler(void); ...@@ -99,6 +99,8 @@ void hv_remove_kexec_handler(void);
void hv_setup_crash_handler(void (*handler)(struct pt_regs *regs)); void hv_setup_crash_handler(void (*handler)(struct pt_regs *regs));
void hv_remove_crash_handler(void); void hv_remove_crash_handler(void);
extern int vmbus_interrupt;
#if IS_ENABLED(CONFIG_HYPERV) #if IS_ENABLED(CONFIG_HYPERV)
/* /*
* Hypervisor's notion of virtual processor ID is different from * Hypervisor's notion of virtual processor ID is different from
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment