|  | /* | 
|  | * Copyright 2017, Data61 | 
|  | * Commonwealth Scientific and Industrial Research Organisation (CSIRO) | 
|  | * ABN 41 687 119 230. | 
|  | * | 
|  | * This software may be distributed and modified according to the terms of | 
|  | * the GNU General Public License version 2. Note that NO WARRANTY is provided. | 
|  | * See "LICENSE_GPLv2.txt" for details. | 
|  | * | 
|  | * @TAG(DATA61_GPL) | 
|  | */ | 
|  |  | 
|  | /*handling msr read & write exceptions*/ | 
|  |  | 
|  | #include <stdio.h> | 
|  | #include <stdlib.h> | 
|  |  | 
|  | #include <sel4/sel4.h> | 
|  |  | 
|  | #include "vmm/debug.h" | 
|  | #include "vmm/vmm.h" | 
|  | #include "vmm/processor/msr.h" | 
|  |  | 
|  | int vmm_rdmsr_handler(vmm_vcpu_t *vcpu) { | 
|  |  | 
|  | int ret = 0; | 
|  | unsigned int msr_no = vmm_read_user_context(&vcpu->guest_state, USER_CONTEXT_ECX); | 
|  | uint64_t data = 0; | 
|  |  | 
|  | DPRINTF(4, "rdmsr ecx 0x%x\n", msr_no); | 
|  |  | 
|  | // src reference: Linux kernel 3.11 kvm arch/x86/kvm/x86.c | 
|  | switch (msr_no) { | 
|  | case MSR_IA32_PLATFORM_ID: | 
|  | case MSR_IA32_EBL_CR_POWERON: | 
|  | case MSR_IA32_DEBUGCTLMSR: | 
|  | case MSR_IA32_LASTBRANCHFROMIP: | 
|  | case MSR_IA32_LASTBRANCHTOIP: | 
|  | case MSR_IA32_LASTINTFROMIP: | 
|  | case MSR_IA32_LASTINTTOIP: | 
|  | case MSR_IA32_MISC_ENABLE: | 
|  | data = 0; | 
|  | break; | 
|  |  | 
|  | case MSR_IA32_UCODE_REV: | 
|  | data = 0x100000000ULL; | 
|  | break; | 
|  |  | 
|  | case MSR_P6_PERFCTR0: | 
|  | case MSR_P6_PERFCTR1: | 
|  | case MSR_P6_EVNTSEL0: | 
|  | case MSR_P6_EVNTSEL1: | 
|  | case MSR_IA32_PERF_GLOBAL_STATUS_SET: | 
|  | /* performance counters not supported. */ | 
|  | data = 0; | 
|  | break; | 
|  |  | 
|  | case 0xcd: /* fsb frequency */ | 
|  | data = 3; | 
|  | break; | 
|  |  | 
|  | case MSR_EBC_FREQUENCY_ID: | 
|  | data = 1 << 24; | 
|  | break; | 
|  |  | 
|  | case MSR_IA32_APICBASE: | 
|  | data = vmm_lapic_get_base_msr(vcpu); | 
|  | break; | 
|  |  | 
|  | default: | 
|  | DPRINTF(1, "rdmsr WARNING unsupported msr_no 0x%x\n", msr_no); | 
|  | // generate a GP fault | 
|  | vmm_inject_exception(vcpu, 13, 1, 0); | 
|  | return 0; | 
|  |  | 
|  | } | 
|  |  | 
|  | if (!ret) { | 
|  | vmm_set_user_context(&vcpu->guest_state, USER_CONTEXT_EAX, (uint32_t)(data & 0xffffffff)); | 
|  | vmm_set_user_context(&vcpu->guest_state, USER_CONTEXT_EDX, (uint32_t)(data >> 32)); | 
|  | vmm_guest_exit_next_instruction(&vcpu->guest_state, vcpu->guest_vcpu); | 
|  | } | 
|  |  | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | int vmm_wrmsr_handler(vmm_vcpu_t *vcpu) { | 
|  |  | 
|  | int ret = 0; | 
|  |  | 
|  | unsigned int msr_no = vmm_read_user_context(&vcpu->guest_state, USER_CONTEXT_ECX); | 
|  | unsigned int val_high = vmm_read_user_context(&vcpu->guest_state, USER_CONTEXT_EDX); | 
|  | unsigned int val_low = vmm_read_user_context(&vcpu->guest_state, USER_CONTEXT_EAX); | 
|  |  | 
|  | DPRINTF(4, "wrmsr ecx 0x%x   value: 0x%x  0x%x\n", msr_no, val_high, val_low); | 
|  |  | 
|  | // src reference: Linux kernel 3.11 kvm arch/x86/kvm/x86.c | 
|  | switch (msr_no) { | 
|  | case MSR_IA32_UCODE_REV: | 
|  | case MSR_IA32_UCODE_WRITE: | 
|  | break; | 
|  |  | 
|  | case MSR_P6_PERFCTR0: | 
|  | case MSR_P6_PERFCTR1: | 
|  | case MSR_P6_EVNTSEL0: | 
|  | case MSR_P6_EVNTSEL1: | 
|  | case MSR_IA32_PERF_GLOBAL_STATUS_SET: | 
|  | /* performance counters not supported. */ | 
|  | break; | 
|  |  | 
|  | case MSR_IA32_APICBASE: | 
|  | vmm_lapic_set_base_msr(vcpu, val_low); | 
|  | break; | 
|  |  | 
|  | default: | 
|  | DPRINTF(1, "wrmsr WARNING unsupported msr_no 0x%x\n", msr_no); | 
|  | // generate a GP fault | 
|  | vmm_inject_exception(vcpu, 13, 1, 0); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | if (!ret) | 
|  | vmm_guest_exit_next_instruction(&vcpu->guest_state, vcpu->guest_vcpu); | 
|  |  | 
|  | return ret; | 
|  | } |