Deleted Added
full compact
hyperv.c (256425) hyperv.c (282212)
1/*-
2 * Copyright (c) 2009-2012 Microsoft Corp.
3 * Copyright (c) 2012 NetApp Inc.
4 * Copyright (c) 2012 Citrix Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions

--- 16 unchanged lines hidden (view full) ---

25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/**
30 * Implements low-level interactions with Hypver-V/Azure
31 */
32#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2009-2012 Microsoft Corp.
3 * Copyright (c) 2012 NetApp Inc.
4 * Copyright (c) 2012 Citrix Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions

--- 16 unchanged lines hidden (view full) ---

25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/**
30 * Implements low-level interactions with Hypver-V/Azure
31 */
32#include <sys/cdefs.h>
33__FBSDID("$FreeBSD: head/sys/dev/hyperv/vmbus/hv_hv.c 256425 2013-10-13 02:41:30Z gibbs $");
33__FBSDID("$FreeBSD: head/sys/dev/hyperv/vmbus/hv_hv.c 282212 2015-04-29 10:12:34Z whu $");
34
35#include <sys/param.h>
36#include <sys/malloc.h>
37#include <sys/pcpu.h>
38#include <sys/timetc.h>
39#include <machine/bus.h>
40#include <vm/vm.h>
41#include <vm/vm_param.h>

--- 20 unchanged lines hidden (view full) ---

62}
63
64/**
65 * Globals
66 */
67hv_vmbus_context hv_vmbus_g_context = {
68 .syn_ic_initialized = FALSE,
69 .hypercall_page = NULL,
34
35#include <sys/param.h>
36#include <sys/malloc.h>
37#include <sys/pcpu.h>
38#include <sys/timetc.h>
39#include <machine/bus.h>
40#include <vm/vm.h>
41#include <vm/vm_param.h>

--- 20 unchanged lines hidden (view full) ---

62}
63
64/**
65 * Globals
66 */
67hv_vmbus_context hv_vmbus_g_context = {
68 .syn_ic_initialized = FALSE,
69 .hypercall_page = NULL,
70 .signal_event_param = NULL,
71 .signal_event_buffer = NULL,
72};
73
74static struct timecounter hv_timecounter = {
75 hv_get_timecount, 0, ~0u, HV_NANOSECONDS_PER_SEC/100, "Hyper-V", HV_NANOSECONDS_PER_SEC/100
76};
77
78static u_int
79hv_get_timecount(struct timecounter *tc)

--- 171 unchanged lines hidden (view full) ---

251 hypercall_msr.as_uint64_t = 0;
252 hypercall_msr.as_uint64_t = rdmsr(HV_X64_MSR_HYPERCALL);
253
254 if (!hypercall_msr.u.enable)
255 goto cleanup;
256
257 hv_vmbus_g_context.hypercall_page = virt_addr;
258
70};
71
72static struct timecounter hv_timecounter = {
73 hv_get_timecount, 0, ~0u, HV_NANOSECONDS_PER_SEC/100, "Hyper-V", HV_NANOSECONDS_PER_SEC/100
74};
75
76static u_int
77hv_get_timecount(struct timecounter *tc)

--- 171 unchanged lines hidden (view full) ---

249 hypercall_msr.as_uint64_t = 0;
250 hypercall_msr.as_uint64_t = rdmsr(HV_X64_MSR_HYPERCALL);
251
252 if (!hypercall_msr.u.enable)
253 goto cleanup;
254
255 hv_vmbus_g_context.hypercall_page = virt_addr;
256
259 /*
260 * Setup the global signal event param for the signal event hypercall
261 */
262 hv_vmbus_g_context.signal_event_buffer =
263 malloc(sizeof(hv_vmbus_input_signal_event_buffer), M_DEVBUF,
264 M_ZERO | M_NOWAIT);
265 KASSERT(hv_vmbus_g_context.signal_event_buffer != NULL,
266 ("Error VMBUS: Failed to allocate signal_event_buffer\n"));
267 if (hv_vmbus_g_context.signal_event_buffer == NULL)
268 goto cleanup;
269
270 hv_vmbus_g_context.signal_event_param =
271 (hv_vmbus_input_signal_event*)
272 (HV_ALIGN_UP((unsigned long)
273 hv_vmbus_g_context.signal_event_buffer,
274 HV_HYPERCALL_PARAM_ALIGN));
275 hv_vmbus_g_context.signal_event_param->connection_id.as_uint32_t = 0;
276 hv_vmbus_g_context.signal_event_param->connection_id.u.id =
277 HV_VMBUS_EVENT_CONNECTION_ID;
278 hv_vmbus_g_context.signal_event_param->flag_number = 0;
279 hv_vmbus_g_context.signal_event_param->rsvd_z = 0;
280
281 tc_init(&hv_timecounter); /* register virtual timecount */
282
283 return (0);
284
285 cleanup:
286 if (virt_addr != NULL) {
287 if (hypercall_msr.u.enable) {
288 hypercall_msr.as_uint64_t = 0;

--- 9 unchanged lines hidden (view full) ---

298/**
299 * @brief Cleanup routine, called normally during driver unloading or exiting
300 */
301void
302hv_vmbus_cleanup(void)
303{
304 hv_vmbus_x64_msr_hypercall_contents hypercall_msr;
305
257 tc_init(&hv_timecounter); /* register virtual timecount */
258
259 return (0);
260
261 cleanup:
262 if (virt_addr != NULL) {
263 if (hypercall_msr.u.enable) {
264 hypercall_msr.as_uint64_t = 0;

--- 9 unchanged lines hidden (view full) ---

274/**
275 * @brief Cleanup routine, called normally during driver unloading or exiting
276 */
277void
278hv_vmbus_cleanup(void)
279{
280 hv_vmbus_x64_msr_hypercall_contents hypercall_msr;
281
306 if (hv_vmbus_g_context.signal_event_buffer != NULL) {
307 free(hv_vmbus_g_context.signal_event_buffer, M_DEVBUF);
308 hv_vmbus_g_context.signal_event_buffer = NULL;
309 hv_vmbus_g_context.signal_event_param = NULL;
310 }
311
312 if (hv_vmbus_g_context.guest_id == HV_FREEBSD_GUEST_ID) {
313 if (hv_vmbus_g_context.hypercall_page != NULL) {
314 hypercall_msr.as_uint64_t = 0;
315 wrmsr(HV_X64_MSR_HYPERCALL,
316 hypercall_msr.as_uint64_t);
317 free(hv_vmbus_g_context.hypercall_page, M_DEVBUF);
318 hv_vmbus_g_context.hypercall_page = NULL;
319 }

--- 45 unchanged lines hidden (view full) ---

365 return (status);
366}
367
368/**
369 * @brief Signal an event on the specified connection using the hypervisor
370 * event IPC. (This involves a hypercall.)
371 */
372hv_vmbus_status
282 if (hv_vmbus_g_context.guest_id == HV_FREEBSD_GUEST_ID) {
283 if (hv_vmbus_g_context.hypercall_page != NULL) {
284 hypercall_msr.as_uint64_t = 0;
285 wrmsr(HV_X64_MSR_HYPERCALL,
286 hypercall_msr.as_uint64_t);
287 free(hv_vmbus_g_context.hypercall_page, M_DEVBUF);
288 hv_vmbus_g_context.hypercall_page = NULL;
289 }

--- 45 unchanged lines hidden (view full) ---

335 return (status);
336}
337
338/**
339 * @brief Signal an event on the specified connection using the hypervisor
340 * event IPC. (This involves a hypercall.)
341 */
342hv_vmbus_status
373hv_vmbus_signal_event()
343hv_vmbus_signal_event(void *con_id)
374{
375 hv_vmbus_status status;
376
377 status = hv_vmbus_do_hypercall(
378 HV_CALL_SIGNAL_EVENT,
344{
345 hv_vmbus_status status;
346
347 status = hv_vmbus_do_hypercall(
348 HV_CALL_SIGNAL_EVENT,
379 hv_vmbus_g_context.signal_event_param,
349 con_id,
380 0) & 0xFFFF;
381
382 return (status);
383}
384
385/**
386 * @brief hv_vmbus_synic_init
387 */
388void
389hv_vmbus_synic_init(void *arg)
390
391{
392 int cpu;
350 0) & 0xFFFF;
351
352 return (status);
353}
354
355/**
356 * @brief hv_vmbus_synic_init
357 */
358void
359hv_vmbus_synic_init(void *arg)
360
361{
362 int cpu;
363 uint64_t hv_vcpu_index;
393 hv_vmbus_synic_simp simp;
394 hv_vmbus_synic_siefp siefp;
395 hv_vmbus_synic_scontrol sctrl;
396 hv_vmbus_synic_sint shared_sint;
397 uint64_t version;
398 hv_setup_args* setup_args = (hv_setup_args *)arg;
399
400 cpu = PCPU_GET(cpuid);
401
402 if (hv_vmbus_g_context.hypercall_page == NULL)
403 return;
404
405 /*
364 hv_vmbus_synic_simp simp;
365 hv_vmbus_synic_siefp siefp;
366 hv_vmbus_synic_scontrol sctrl;
367 hv_vmbus_synic_sint shared_sint;
368 uint64_t version;
369 hv_setup_args* setup_args = (hv_setup_args *)arg;
370
371 cpu = PCPU_GET(cpuid);
372
373 if (hv_vmbus_g_context.hypercall_page == NULL)
374 return;
375
376 /*
406 * KYS: Looks like we can only initialize on cpu0; don't we support
407 * SMP guests?
408 *
409 * TODO: Need to add SMP support for FreeBSD V9
410 */
411
412 if (cpu != 0)
413 return;
414
415 /*
416 * TODO: Check the version
417 */
418 version = rdmsr(HV_X64_MSR_SVERSION);
377 * TODO: Check the version
378 */
379 version = rdmsr(HV_X64_MSR_SVERSION);
419
420
380
421 hv_vmbus_g_context.syn_ic_msg_page[cpu] = setup_args->page_buffers[0];
422 hv_vmbus_g_context.syn_ic_event_page[cpu] = setup_args->page_buffers[1];
381 hv_vmbus_g_context.syn_ic_msg_page[cpu] =
382 setup_args->page_buffers[2 * cpu];
383 hv_vmbus_g_context.syn_ic_event_page[cpu] =
384 setup_args->page_buffers[2 * cpu + 1];
423
424 /*
425 * Setup the Synic's message page
426 */
427
428 simp.as_uint64_t = rdmsr(HV_X64_MSR_SIMP);
429 simp.u.simp_enabled = 1;
430 simp.u.base_simp_gpa = ((hv_get_phys_addr(

--- 7 unchanged lines hidden (view full) ---

438 siefp.as_uint64_t = rdmsr(HV_X64_MSR_SIEFP);
439 siefp.u.siefp_enabled = 1;
440 siefp.u.base_siefp_gpa = ((hv_get_phys_addr(
441 hv_vmbus_g_context.syn_ic_event_page[cpu])) >> PAGE_SHIFT);
442
443 wrmsr(HV_X64_MSR_SIEFP, siefp.as_uint64_t);
444
445 /*HV_SHARED_SINT_IDT_VECTOR + 0x20; */
385
386 /*
387 * Setup the Synic's message page
388 */
389
390 simp.as_uint64_t = rdmsr(HV_X64_MSR_SIMP);
391 simp.u.simp_enabled = 1;
392 simp.u.base_simp_gpa = ((hv_get_phys_addr(

--- 7 unchanged lines hidden (view full) ---

400 siefp.as_uint64_t = rdmsr(HV_X64_MSR_SIEFP);
401 siefp.u.siefp_enabled = 1;
402 siefp.u.base_siefp_gpa = ((hv_get_phys_addr(
403 hv_vmbus_g_context.syn_ic_event_page[cpu])) >> PAGE_SHIFT);
404
405 wrmsr(HV_X64_MSR_SIEFP, siefp.as_uint64_t);
406
407 /*HV_SHARED_SINT_IDT_VECTOR + 0x20; */
408 shared_sint.as_uint64_t = 0;
446 shared_sint.u.vector = setup_args->vector;
447 shared_sint.u.masked = FALSE;
409 shared_sint.u.vector = setup_args->vector;
410 shared_sint.u.masked = FALSE;
448 shared_sint.u.auto_eoi = FALSE;
411 shared_sint.u.auto_eoi = TRUE;
449
450 wrmsr(HV_X64_MSR_SINT0 + HV_VMBUS_MESSAGE_SINT,
451 shared_sint.as_uint64_t);
452
453 /* Enable the global synic bit */
454 sctrl.as_uint64_t = rdmsr(HV_X64_MSR_SCONTROL);
455 sctrl.u.enable = 1;
456
457 wrmsr(HV_X64_MSR_SCONTROL, sctrl.as_uint64_t);
458
459 hv_vmbus_g_context.syn_ic_initialized = TRUE;
460
412
413 wrmsr(HV_X64_MSR_SINT0 + HV_VMBUS_MESSAGE_SINT,
414 shared_sint.as_uint64_t);
415
416 /* Enable the global synic bit */
417 sctrl.as_uint64_t = rdmsr(HV_X64_MSR_SCONTROL);
418 sctrl.u.enable = 1;
419
420 wrmsr(HV_X64_MSR_SCONTROL, sctrl.as_uint64_t);
421
422 hv_vmbus_g_context.syn_ic_initialized = TRUE;
423
424 /*
425 * Set up the cpuid mapping from Hyper-V to FreeBSD.
426 * The array is indexed using FreeBSD cpuid.
427 */
428 hv_vcpu_index = rdmsr(HV_X64_MSR_VP_INDEX);
429 hv_vmbus_g_context.hv_vcpu_index[cpu] = (uint32_t)hv_vcpu_index;
430
461 return;
462}
463
464/**
465 * @brief Cleanup routine for hv_vmbus_synic_init()
466 */
467void hv_vmbus_synic_cleanup(void *arg)
468{
469 hv_vmbus_synic_sint shared_sint;
470 hv_vmbus_synic_simp simp;
471 hv_vmbus_synic_siefp siefp;
431 return;
432}
433
434/**
435 * @brief Cleanup routine for hv_vmbus_synic_init()
436 */
437void hv_vmbus_synic_cleanup(void *arg)
438{
439 hv_vmbus_synic_sint shared_sint;
440 hv_vmbus_synic_simp simp;
441 hv_vmbus_synic_siefp siefp;
472 int cpu = PCPU_GET(cpuid);
473
474 if (!hv_vmbus_g_context.syn_ic_initialized)
475 return;
476
442
443 if (!hv_vmbus_g_context.syn_ic_initialized)
444 return;
445
477 if (cpu != 0)
478 return; /* TODO: XXXKYS: SMP? */
479
480 shared_sint.as_uint64_t = rdmsr(
481 HV_X64_MSR_SINT0 + HV_VMBUS_MESSAGE_SINT);
482
483 shared_sint.u.masked = 1;
484
485 /*
486 * Disable the interrupt
487 */

--- 17 unchanged lines hidden ---
446 shared_sint.as_uint64_t = rdmsr(
447 HV_X64_MSR_SINT0 + HV_VMBUS_MESSAGE_SINT);
448
449 shared_sint.u.masked = 1;
450
451 /*
452 * Disable the interrupt
453 */

--- 17 unchanged lines hidden ---