diff options
Diffstat (limited to 'drivers/hv/hv.c')
| -rw-r--r-- | drivers/hv/hv.c | 72 | 
1 files changed, 36 insertions, 36 deletions
diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c index 3648f8f0f36..1c5481da6e4 100644 --- a/drivers/hv/hv.c +++ b/drivers/hv/hv.c @@ -27,6 +27,7 @@  #include <linux/vmalloc.h>  #include <linux/hyperv.h>  #include <linux/version.h> +#include <linux/interrupt.h>  #include <asm/hyperv.h>  #include "hyperv_vmbus.h" @@ -34,13 +35,16 @@  struct hv_context hv_context = {  	.synic_initialized	= false,  	.hypercall_page		= NULL, -	.signal_event_param	= NULL, -	.signal_event_buffer	= NULL,  };  /*   * query_hypervisor_info - Get version info of the windows hypervisor   */ +unsigned int host_info_eax; +unsigned int host_info_ebx; +unsigned int host_info_ecx; +unsigned int host_info_edx; +  static int query_hypervisor_info(void)  {  	unsigned int eax; @@ -70,13 +74,10 @@ static int query_hypervisor_info(void)  		edx = 0;  		op = HVCPUID_VERSION;  		cpuid(op, &eax, &ebx, &ecx, &edx); -		pr_info("Hyper-V Host OS Build:%d-%d.%d-%d-%d.%d\n", -			    eax, -			    ebx >> 16, -			    ebx & 0xFFFF, -			    ecx, -			    edx >> 24, -			    edx & 0xFFFFFF); +		host_info_eax = eax; +		host_info_ebx = ebx; +		host_info_ecx = ecx; +		host_info_edx = edx;  	}  	return max_leaf;  } @@ -137,6 +138,10 @@ int hv_init(void)  	memset(hv_context.synic_event_page, 0, sizeof(void *) * NR_CPUS);  	memset(hv_context.synic_message_page, 0,  	       sizeof(void *) * NR_CPUS); +	memset(hv_context.vp_index, 0, +	       sizeof(int) * NR_CPUS); +	memset(hv_context.event_dpc, 0, +	       sizeof(void *) * NR_CPUS);  	max_leaf = query_hypervisor_info(); @@ -168,24 +173,6 @@ int hv_init(void)  	hv_context.hypercall_page = virtaddr; -	/* Setup the global signal event param for the signal event hypercall */ -	hv_context.signal_event_buffer = -			kmalloc(sizeof(struct hv_input_signal_event_buffer), -				GFP_KERNEL); -	if (!hv_context.signal_event_buffer) -		goto cleanup; - -	hv_context.signal_event_param = -		(struct hv_input_signal_event *) -			(ALIGN((unsigned long) -				  hv_context.signal_event_buffer, -				  HV_HYPERCALL_PARAM_ALIGN)); -	hv_context.signal_event_param->connectionid.asu32 = 0; -	hv_context.signal_event_param->connectionid.u.id = -						VMBUS_EVENT_CONNECTION_ID; -	hv_context.signal_event_param->flag_number = 0; -	hv_context.signal_event_param->rsvdz = 0; -  	return 0;  cleanup: @@ -213,10 +200,6 @@ void hv_cleanup(void)  	/* Reset our OS id */  	wrmsrl(HV_X64_MSR_GUEST_OS_ID, 0); -	kfree(hv_context.signal_event_buffer); -	hv_context.signal_event_buffer = NULL; -	hv_context.signal_event_param = NULL; -  	if (hv_context.hypercall_page) {  		hypercall_msr.as_uint64 = 0;  		wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64); @@ -273,13 +256,12 @@ int hv_post_message(union hv_connection_id connection_id,   *   * This involves a hypercall.   */ -u16 hv_signal_event(void) +u16 hv_signal_event(void *con_id)  {  	u16 status; -	status = do_hypercall(HVCALL_SIGNAL_EVENT, -			       hv_context.signal_event_param, -			       NULL) & 0xFFFF; +	status = (do_hypercall(HVCALL_SIGNAL_EVENT, con_id, NULL) & 0xFFFF); +  	return status;  } @@ -297,6 +279,7 @@ void hv_synic_init(void *irqarg)  	union hv_synic_siefp siefp;  	union hv_synic_sint shared_sint;  	union hv_synic_scontrol sctrl; +	u64 vp_index;  	u32 irq_vector = *((u32 *)(irqarg));  	int cpu = smp_processor_id(); @@ -307,6 +290,15 @@ void hv_synic_init(void *irqarg)  	/* Check the version */  	rdmsrl(HV_X64_MSR_SVERSION, version); +	hv_context.event_dpc[cpu] = (struct tasklet_struct *) +					kmalloc(sizeof(struct tasklet_struct), +						GFP_ATOMIC); +	if (hv_context.event_dpc[cpu] == NULL) { +		pr_err("Unable to allocate event dpc\n"); +		goto cleanup; +	} +	tasklet_init(hv_context.event_dpc[cpu], vmbus_on_event, cpu); +  	hv_context.synic_message_page[cpu] =  		(void *)get_zeroed_page(GFP_ATOMIC); @@ -345,7 +337,7 @@ void hv_synic_init(void *irqarg)  	shared_sint.as_uint64 = 0;  	shared_sint.vector = irq_vector; /* HV_SHARED_SINT_IDT_VECTOR + 0x20; */  	shared_sint.masked = false; -	shared_sint.auto_eoi = false; +	shared_sint.auto_eoi = true;  	wrmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, shared_sint.as_uint64); @@ -356,6 +348,14 @@ void hv_synic_init(void *irqarg)  	wrmsrl(HV_X64_MSR_SCONTROL, sctrl.as_uint64);  	hv_context.synic_initialized = true; + +	/* +	 * Setup the mapping between Hyper-V's notion +	 * of cpuid and Linux' notion of cpuid. +	 * This array will be indexed using Linux cpuid. +	 */ +	rdmsrl(HV_X64_MSR_VP_INDEX, vp_index); +	hv_context.vp_index[cpu] = (u32)vp_index;  	return;  cleanup:  |