Changeset View
Standalone View
sys/dev/hyperv/vmbus/hv_hv.c
Show All 30 Lines | |||||
*/ | */ | ||||
#include <sys/cdefs.h> | #include <sys/cdefs.h> | ||||
__FBSDID("$FreeBSD$"); | __FBSDID("$FreeBSD$"); | ||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#include <sys/kernel.h> | #include <sys/kernel.h> | ||||
#include <sys/malloc.h> | #include <sys/malloc.h> | ||||
#include <sys/pcpu.h> | #include <sys/pcpu.h> | ||||
#include <sys/proc.h> | |||||
#include <sys/timetc.h> | #include <sys/timetc.h> | ||||
#include <machine/bus.h> | #include <machine/bus.h> | ||||
#include <machine/md_var.h> | #include <machine/md_var.h> | ||||
#include <vm/vm.h> | #include <vm/vm.h> | ||||
#include <vm/vm_param.h> | #include <vm/vm_param.h> | ||||
#include <vm/pmap.h> | #include <vm/pmap.h> | ||||
Show All 25 Lines | |||||
static u_int | static u_int | ||||
hv_get_timecount(struct timecounter *tc) | hv_get_timecount(struct timecounter *tc) | ||||
{ | { | ||||
u_int now = rdmsr(HV_X64_MSR_TIME_REF_COUNT); | u_int now = rdmsr(HV_X64_MSR_TIME_REF_COUNT); | ||||
return (now); | return (now); | ||||
} | } | ||||
static void | |||||
hv_idle_hook(sbintime_t sbt) | |||||
{ | |||||
rdmsr(HV_X64_MSR_GUEST_IDLE); | |||||
} | |||||
/** | /** | ||||
* @brief Invoke the specified hypercall | * @brief Invoke the specified hypercall | ||||
*/ | */ | ||||
static uint64_t | static uint64_t | ||||
hv_vmbus_do_hypercall(uint64_t control, void* input, void* output) | hv_vmbus_do_hypercall(uint64_t control, void* input, void* output) | ||||
{ | { | ||||
#ifdef __x86_64__ | #ifdef __x86_64__ | ||||
uint64_t hv_status = 0; | uint64_t hv_status = 0; | ||||
▲ Show 20 Lines • Show All 79 Lines • ▼ Show 20 Lines | hv_vmbus_init(void) | ||||
hypercall_msr.as_uint64_t = rdmsr(HV_X64_MSR_HYPERCALL); | hypercall_msr.as_uint64_t = rdmsr(HV_X64_MSR_HYPERCALL); | ||||
if (!hypercall_msr.u.enable) | if (!hypercall_msr.u.enable) | ||||
goto cleanup; | goto cleanup; | ||||
hv_vmbus_g_context.hypercall_page = virt_addr; | hv_vmbus_g_context.hypercall_page = virt_addr; | ||||
hv_et_init(); | hv_et_init(); | ||||
return (0); | return (0); | ||||
cleanup: | cleanup: | ||||
if (virt_addr != NULL) { | if (virt_addr != NULL) { | ||||
if (hypercall_msr.u.enable) { | if (hypercall_msr.u.enable) { | ||||
hypercall_msr.as_uint64_t = 0; | hypercall_msr.as_uint64_t = 0; | ||||
wrmsr(HV_X64_MSR_HYPERCALL, | wrmsr(HV_X64_MSR_HYPERCALL, | ||||
hypercall_msr.as_uint64_t); | hypercall_msr.as_uint64_t); | ||||
▲ Show 20 Lines • Show All 320 Lines • ▼ Show 20 Lines | |||||
hyperv_init(void *dummy __unused) | hyperv_init(void *dummy __unused) | ||||
{ | { | ||||
if (!hyperv_identify()) | if (!hyperv_identify()) | ||||
return; | return; | ||||
if (hyperv_features & HV_FEATURE_MSR_TIME_REFCNT) { | if (hyperv_features & HV_FEATURE_MSR_TIME_REFCNT) { | ||||
/* Register virtual timecount */ | /* Register virtual timecount */ | ||||
tc_init(&hv_timecounter); | tc_init(&hv_timecounter); | ||||
} | |||||
if (hyperv_features & HV_FEATURE_MSR_GUEST_IDLE) { | |||||
sepherosa_gmail.com: Hmm, we should make the test more stringent:
if ((hyperv_features &… | |||||
cpu_idle_hook = hv_idle_hook; | |||||
sepherosa_gmail.comUnsubmitted Not Done Inline ActionsWell, does it really work for you? acpi_cpu will override cpu_idle_hook unconditionally later. sepherosa_gmail.com: Well, does it really work for you? acpi_cpu will override cpu_idle_hook unconditionally later. | |||||
howard0su_gmail.comAuthorUnsubmitted Not Done Inline ActionsI set the breakpoint in DDB to make sure it works. I believe acpi_cpu is earlier. howard0su_gmail.com: I set the breakpoint in DDB to make sure it works. I believe acpi_cpu is earlier. | |||||
sepherosa_gmail.comUnsubmitted Not Done Inline ActionsI added a log in hyperv_init() and acpi_cpu_startup(), see the last line in the two log chunks. ... I think you were adding the ddb brkptr to the MSR idle routing; the MSR version would be triggered before the ACPI cpu overrides, but it does not mean ACPI cpu takes over the idle hook earlier. sepherosa_gmail.com: I added a log in hyperv_init() and acpi_cpu_startup(), see the last line in the two log chunks. | |||||
} | } | ||||
} | } | ||||
SYSINIT(hyperv_initialize, SI_SUB_HYPERVISOR, SI_ORDER_FIRST, hyperv_init, | SYSINIT(hyperv_initialize, SI_SUB_HYPERVISOR, SI_ORDER_FIRST, hyperv_init, | ||||
NULL); | NULL); |
Hmm, we should make the test more stringent: