2 * This file is part of the Palacios Virtual Machine Monitor developed
3 * by the V3VEE Project with funding from the United States National
4 * Science Foundation and the Department of Energy.
6 * The V3VEE Project is a joint project between Northwestern University
7 * and the University of New Mexico. You can find out more at
10 * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu>
11 * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org>
12 * All rights reserved.
14 * Author: Jack Lange <jarusl@cs.northwestern.edu>
15 * Patrick G. Bridges <bridges@cs.unm.edu>
17 * This is free software. You are permitted to use,
18 * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
21 #include <palacios/vmm.h>
22 #include <palacios/vmm_time.h>
23 #include <palacios/vm_guest.h>
26 // Functions for handling exits on the TSC when fully virtualizing
27 // the timestamp counter.
29 #define TSC_AUX_MSR 0xC0000103
31 int v3_handle_rdtscp(struct guest_info *info);
32 int v3_handle_rdtsc(struct guest_info *info);
37 struct v3_msr tsc_aux; // Auxilliary MSR for RDTSCP
44 * Handle full virtualization of the time stamp counter. As noted
45 * above, we don't store the actual value of the TSC, only the guest's
46 * offset from monotonic guest's time. If the guest writes to the TSC, we
47 * handle this by changing that offset.
49 * Possible TODO: Proper hooking of TSC read/writes?
52 static int rdtsc(struct guest_info * info) {
53 uint64_t tscval = v3_get_guest_tsc(&info->time_state);
55 info->vm_regs.rdx = tscval >> 32;
56 info->vm_regs.rax = tscval & 0xffffffffLL;
61 int v3_handle_rdtsc(struct guest_info * info) {
64 info->vm_regs.rax &= 0x00000000ffffffffLL;
65 info->vm_regs.rdx &= 0x00000000ffffffffLL;
72 int v3_rdtscp(struct guest_info * info) {
74 /* First get the MSR value that we need. It's safe to futz with
75 * ra/c/dx here since they're modified by this instruction anyway. */
76 info->vm_regs.rcx = TSC_AUX_MSR;
77 ret = v3_handle_msr_read(info);
83 info->vm_regs.rcx = info->vm_regs.rax;
85 /* Now do the TSC half of the instruction */
96 int v3_handle_rdtscp(struct guest_info * info) {
97 PrintDebug("Handling virtual RDTSCP call.\n");
101 info->vm_regs.rax &= 0x00000000ffffffffLL;
102 info->vm_regs.rcx &= 0x00000000ffffffffLL;
103 info->vm_regs.rdx &= 0x00000000ffffffffLL;
113 static int tsc_aux_msr_read_hook(struct guest_info *info, uint_t msr_num,
114 struct v3_msr *msr_val, void *priv) {
115 struct vm_time * time_state = &(info->time_state);
117 V3_ASSERT(msr_num == TSC_AUX_MSR);
119 msr_val->lo = time_state->tsc_aux.lo;
120 msr_val->hi = time_state->tsc_aux.hi;
126 static int tsc_aux_msr_write_hook(struct guest_info *info, uint_t msr_num,
127 struct v3_msr msr_val, void *priv) {
128 struct vm_time * time_state = &(info->time_state);
130 V3_ASSERT(msr_num == TSC_AUX_MSR);
132 time_state->tsc_aux.lo = msr_val.lo;
133 time_state->tsc_aux.hi = msr_val.hi;
139 static int tsc_msr_read_hook(struct guest_info *info, uint_t msr_num,
140 struct v3_msr *msr_val, void *priv) {
141 uint64_t time = v3_get_guest_tsc(&info->time_state);
143 V3_ASSERT(msr_num == TSC_MSR);
145 msr_val->hi = time >> 32;
146 msr_val->lo = time & 0xffffffffLL;
152 static int tsc_msr_write_hook(struct guest_info *info, uint_t msr_num,
153 struct v3_msr msr_val, void *priv) {
154 struct vm_time * time_state = &(info->time_state);
155 uint64_t guest_time, new_tsc;
157 V3_ASSERT(msr_num == TSC_MSR);
159 new_tsc = (((uint64_t)msr_val.hi) << 32) | (uint64_t)msr_val.lo;
160 guest_time = v3_get_guest_time(time_state);
161 time_state->tsc_guest_offset = (sint64_t)new_tsc - (sint64_t)guest_time;
167 static int deinit() {
168 v3_unhook_msr(vm, TSC_MSR);
169 v3_unhook_msr(vm, TSC_AUX_MSR);
175 time_state->tsc_aux.lo = 0;
176 time_state->tsc_aux.hi = 0;
180 PrintDebug("Installing TSC MSR hook.\n");
181 ret = v3_hook_msr(vm, TSC_MSR,
182 tsc_msr_read_hook, tsc_msr_write_hook, NULL);
188 PrintDebug("Installing TSC_AUX MSR hook.\n");
189 ret = v3_hook_msr(vm, TSC_AUX_MSR, tsc_aux_msr_read_hook,
190 tsc_aux_msr_write_hook, NULL);