Changeset View
Changeset View
Standalone View
Standalone View
head/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c
Show First 20 Lines • Show All 171 Lines • ▼ Show 20 Lines | hv_vmbus_isr(struct trapframe *frame) | ||||
page_addr = hv_vmbus_g_context.syn_ic_event_page[cpu]; | page_addr = hv_vmbus_g_context.syn_ic_event_page[cpu]; | ||||
event = (hv_vmbus_synic_event_flags*) | event = (hv_vmbus_synic_event_flags*) | ||||
page_addr + HV_VMBUS_MESSAGE_SINT; | page_addr + HV_VMBUS_MESSAGE_SINT; | ||||
if ((hv_vmbus_protocal_version == HV_VMBUS_VERSION_WS2008) || | if ((hv_vmbus_protocal_version == HV_VMBUS_VERSION_WS2008) || | ||||
(hv_vmbus_protocal_version == HV_VMBUS_VERSION_WIN7)) { | (hv_vmbus_protocal_version == HV_VMBUS_VERSION_WIN7)) { | ||||
/* Since we are a child, we only need to check bit 0 */ | /* Since we are a child, we only need to check bit 0 */ | ||||
if (synch_test_and_clear_bit(0, &event->flags32[0])) { | if (synch_test_and_clear_bit(0, &event->flags32[0])) { | ||||
swi_sched(hv_vmbus_g_context.event_swintr[cpu], 0); | hv_vmbus_on_events(cpu); | ||||
} | } | ||||
} else { | } else { | ||||
/* | /* | ||||
* On host with Win8 or above, we can directly look at | * On host with Win8 or above, we can directly look at | ||||
* the event page. If bit n is set, we have an interrupt | * the event page. If bit n is set, we have an interrupt | ||||
* on the channel with id n. | * on the channel with id n. | ||||
* Directly schedule the event software interrupt on | * Directly schedule the event software interrupt on | ||||
* current cpu. | * current cpu. | ||||
*/ | */ | ||||
swi_sched(hv_vmbus_g_context.event_swintr[cpu], 0); | hv_vmbus_on_events(cpu); | ||||
} | } | ||||
/* Check if there are actual msgs to be process */ | /* Check if there are actual msgs to be process */ | ||||
page_addr = hv_vmbus_g_context.syn_ic_msg_page[cpu]; | page_addr = hv_vmbus_g_context.syn_ic_msg_page[cpu]; | ||||
msg = (hv_vmbus_message*) page_addr + HV_VMBUS_MESSAGE_SINT; | msg = (hv_vmbus_message*) page_addr + HV_VMBUS_MESSAGE_SINT; | ||||
/* we call eventtimer process the message */ | /* we call eventtimer process the message */ | ||||
if (msg->header.message_type == HV_MESSAGE_TIMER_EXPIRED) { | if (msg->header.message_type == HV_MESSAGE_TIMER_EXPIRED) { | ||||
Show All 21 Lines | hv_vmbus_isr(struct trapframe *frame) | ||||
if (msg->header.message_type != HV_MESSAGE_TYPE_NONE) { | if (msg->header.message_type != HV_MESSAGE_TYPE_NONE) { | ||||
swi_sched(hv_vmbus_g_context.msg_swintr[cpu], 0); | swi_sched(hv_vmbus_g_context.msg_swintr[cpu], 0); | ||||
} | } | ||||
return (FILTER_HANDLED); | return (FILTER_HANDLED); | ||||
} | } | ||||
uint32_t hv_vmbus_swintr_event_cpu[MAXCPU]; | |||||
u_long *hv_vmbus_intr_cpu[MAXCPU]; | u_long *hv_vmbus_intr_cpu[MAXCPU]; | ||||
void | void | ||||
hv_vector_handler(struct trapframe *trap_frame) | hv_vector_handler(struct trapframe *trap_frame) | ||||
{ | { | ||||
int cpu; | int cpu; | ||||
/* | /* | ||||
▲ Show 20 Lines • Show All 230 Lines • ▼ Show 20 Lines | |||||
* - setup the vmbus root device | * - setup the vmbus root device | ||||
* - retrieve the channel offers | * - retrieve the channel offers | ||||
*/ | */ | ||||
static int | static int | ||||
vmbus_bus_init(void) | vmbus_bus_init(void) | ||||
{ | { | ||||
int i, j, n, ret; | int i, j, n, ret; | ||||
char buf[MAXCOMLEN + 1]; | char buf[MAXCOMLEN + 1]; | ||||
cpuset_t cpu_mask; | |||||
if (vmbus_inited) | if (vmbus_inited) | ||||
return (0); | return (0); | ||||
vmbus_inited = 1; | vmbus_inited = 1; | ||||
ret = hv_vmbus_init(); | ret = hv_vmbus_init(); | ||||
Show All 20 Lines | printf("VMBUS: vmbus callback vector %d\n", | ||||
hv_vmbus_g_context.hv_cb_vector); | hv_vmbus_g_context.hv_cb_vector); | ||||
/* | /* | ||||
* Notify the hypervisor of our vector. | * Notify the hypervisor of our vector. | ||||
*/ | */ | ||||
setup_args.vector = hv_vmbus_g_context.hv_cb_vector; | setup_args.vector = hv_vmbus_g_context.hv_cb_vector; | ||||
CPU_FOREACH(j) { | CPU_FOREACH(j) { | ||||
hv_vmbus_swintr_event_cpu[j] = 0; | |||||
hv_vmbus_g_context.hv_event_intr_event[j] = NULL; | |||||
hv_vmbus_g_context.hv_msg_intr_event[j] = NULL; | hv_vmbus_g_context.hv_msg_intr_event[j] = NULL; | ||||
hv_vmbus_g_context.event_swintr[j] = NULL; | |||||
hv_vmbus_g_context.msg_swintr[j] = NULL; | hv_vmbus_g_context.msg_swintr[j] = NULL; | ||||
snprintf(buf, sizeof(buf), "cpu%d:hyperv", j); | snprintf(buf, sizeof(buf), "cpu%d:hyperv", j); | ||||
intrcnt_add(buf, &hv_vmbus_intr_cpu[j]); | intrcnt_add(buf, &hv_vmbus_intr_cpu[j]); | ||||
for (i = 0; i < 2; i++) | for (i = 0; i < 2; i++) | ||||
setup_args.page_buffers[2 * j + i] = NULL; | setup_args.page_buffers[2 * j + i] = NULL; | ||||
} | } | ||||
/* | /* | ||||
* Per cpu setup. | * Per cpu setup. | ||||
*/ | */ | ||||
CPU_FOREACH(j) { | CPU_FOREACH(j) { | ||||
/* | /* | ||||
* Setup taskqueue to handle events | |||||
*/ | |||||
hv_vmbus_g_context.hv_event_queue[j] = taskqueue_create_fast("hyperv event", M_WAITOK, | |||||
taskqueue_thread_enqueue, &hv_vmbus_g_context.hv_event_queue[j]); | |||||
if (hv_vmbus_g_context.hv_event_queue[j] == NULL) { | |||||
if (bootverbose) | |||||
printf("VMBUS: failed to setup taskqueue\n"); | |||||
goto cleanup1; | |||||
} | |||||
CPU_SETOF(j, &cpu_mask); | |||||
taskqueue_start_threads_cpuset(&hv_vmbus_g_context.hv_event_queue[j], 1, PI_NET, &cpu_mask, | |||||
"hvevent%d", j); | |||||
/* | |||||
* Setup software interrupt thread and handler for msg handling. | * Setup software interrupt thread and handler for msg handling. | ||||
*/ | */ | ||||
ret = swi_add(&hv_vmbus_g_context.hv_msg_intr_event[j], | ret = swi_add(&hv_vmbus_g_context.hv_msg_intr_event[j], | ||||
"hv_msg", vmbus_msg_swintr, (void *)(long)j, SWI_CLOCK, 0, | "hv_msg", vmbus_msg_swintr, (void *)(long)j, SWI_CLOCK, 0, | ||||
&hv_vmbus_g_context.msg_swintr[j]); | &hv_vmbus_g_context.msg_swintr[j]); | ||||
if (ret) { | if (ret) { | ||||
if(bootverbose) | if(bootverbose) | ||||
printf("VMBUS: failed to setup msg swi for " | printf("VMBUS: failed to setup msg swi for " | ||||
"cpu %d\n", j); | "cpu %d\n", j); | ||||
goto cleanup1; | goto cleanup1; | ||||
} | } | ||||
/* | /* | ||||
* Bind the swi thread to the cpu. | * Bind the swi thread to the cpu. | ||||
*/ | */ | ||||
ret = intr_event_bind(hv_vmbus_g_context.hv_msg_intr_event[j], | ret = intr_event_bind(hv_vmbus_g_context.hv_msg_intr_event[j], | ||||
j); | j); | ||||
if (ret) { | if (ret) { | ||||
if(bootverbose) | if(bootverbose) | ||||
printf("VMBUS: failed to bind msg swi thread " | printf("VMBUS: failed to bind msg swi thread " | ||||
"to cpu %d\n", j); | "to cpu %d\n", j); | ||||
goto cleanup1; | goto cleanup1; | ||||
} | } | ||||
/* | /* | ||||
* Setup software interrupt thread and handler for | |||||
* event handling. | |||||
*/ | |||||
ret = swi_add(&hv_vmbus_g_context.hv_event_intr_event[j], | |||||
"hv_event", hv_vmbus_on_events, (void *)(long)j, | |||||
SWI_CLOCK, 0, &hv_vmbus_g_context.event_swintr[j]); | |||||
if (ret) { | |||||
if(bootverbose) | |||||
printf("VMBUS: failed to setup event swi for " | |||||
"cpu %d\n", j); | |||||
goto cleanup1; | |||||
} | |||||
/* | |||||
* Prepare the per cpu msg and event pages to be called on each cpu. | * Prepare the per cpu msg and event pages to be called on each cpu. | ||||
*/ | */ | ||||
for(i = 0; i < 2; i++) { | for(i = 0; i < 2; i++) { | ||||
setup_args.page_buffers[2 * j + i] = | setup_args.page_buffers[2 * j + i] = | ||||
malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT | M_ZERO); | malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT | M_ZERO); | ||||
if (setup_args.page_buffers[2 * j + i] == NULL) { | if (setup_args.page_buffers[2 * j + i] == NULL) { | ||||
KASSERT(setup_args.page_buffers[2 * j + i] != NULL, | KASSERT(setup_args.page_buffers[2 * j + i] != NULL, | ||||
("Error VMBUS: malloc failed!")); | ("Error VMBUS: malloc failed!")); | ||||
Show All 26 Lines | vmbus_bus_init(void) | ||||
for (n = 0; n < 2 * MAXCPU; n++) | for (n = 0; n < 2 * MAXCPU; n++) | ||||
if (setup_args.page_buffers[n] != NULL) | if (setup_args.page_buffers[n] != NULL) | ||||
free(setup_args.page_buffers[n], M_DEVBUF); | free(setup_args.page_buffers[n], M_DEVBUF); | ||||
/* | /* | ||||
* remove swi and vmbus callback vector; | * remove swi and vmbus callback vector; | ||||
*/ | */ | ||||
CPU_FOREACH(j) { | CPU_FOREACH(j) { | ||||
if (hv_vmbus_g_context.hv_event_queue[j] != NULL) | |||||
taskqueue_free(hv_vmbus_g_context.hv_event_queue[j]); | |||||
if (hv_vmbus_g_context.msg_swintr[j] != NULL) | if (hv_vmbus_g_context.msg_swintr[j] != NULL) | ||||
swi_remove(hv_vmbus_g_context.msg_swintr[j]); | swi_remove(hv_vmbus_g_context.msg_swintr[j]); | ||||
if (hv_vmbus_g_context.event_swintr[j] != NULL) | |||||
swi_remove(hv_vmbus_g_context.event_swintr[j]); | |||||
hv_vmbus_g_context.hv_msg_intr_event[j] = NULL; | hv_vmbus_g_context.hv_msg_intr_event[j] = NULL; | ||||
hv_vmbus_g_context.hv_event_intr_event[j] = NULL; | |||||
} | } | ||||
vmbus_vector_free(hv_vmbus_g_context.hv_cb_vector); | vmbus_vector_free(hv_vmbus_g_context.hv_cb_vector); | ||||
cleanup: | cleanup: | ||||
hv_vmbus_cleanup(); | hv_vmbus_cleanup(); | ||||
return (ret); | return (ret); | ||||
▲ Show 20 Lines • Show All 48 Lines • ▼ Show 20 Lines | for(i = 0; i < 2 * MAXCPU; i++) { | ||||
if (setup_args.page_buffers[i] != 0) | if (setup_args.page_buffers[i] != 0) | ||||
free(setup_args.page_buffers[i], M_DEVBUF); | free(setup_args.page_buffers[i], M_DEVBUF); | ||||
} | } | ||||
hv_vmbus_cleanup(); | hv_vmbus_cleanup(); | ||||
/* remove swi */ | /* remove swi */ | ||||
CPU_FOREACH(i) { | CPU_FOREACH(i) { | ||||
if (hv_vmbus_g_context.hv_event_queue[i] != NULL) | |||||
taskqueue_free(hv_vmbus_g_context.hv_event_queue[i]); | |||||
if (hv_vmbus_g_context.msg_swintr[i] != NULL) | if (hv_vmbus_g_context.msg_swintr[i] != NULL) | ||||
swi_remove(hv_vmbus_g_context.msg_swintr[i]); | swi_remove(hv_vmbus_g_context.msg_swintr[i]); | ||||
if (hv_vmbus_g_context.event_swintr[i] != NULL) | |||||
swi_remove(hv_vmbus_g_context.event_swintr[i]); | |||||
hv_vmbus_g_context.hv_msg_intr_event[i] = NULL; | hv_vmbus_g_context.hv_msg_intr_event[i] = NULL; | ||||
hv_vmbus_g_context.hv_event_intr_event[i] = NULL; | |||||
} | } | ||||
vmbus_vector_free(hv_vmbus_g_context.hv_cb_vector); | vmbus_vector_free(hv_vmbus_g_context.hv_cb_vector); | ||||
return; | return; | ||||
} | } | ||||
static void | static void | ||||
▲ Show 20 Lines • Show All 72 Lines • Show Last 20 Lines |