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 --- |