diff options
author | neel <neel@FreeBSD.org> | 2014-09-20 02:35:21 +0000 |
---|---|---|
committer | neel <neel@FreeBSD.org> | 2014-09-20 02:35:21 +0000 |
commit | 46721cc2c7d83b96c9c48ed0f7a7fa51d989cfaf (patch) | |
tree | 3ad2fde5e753649653c89f4a1d4cb530ee5c3775 /usr.sbin | |
parent | f3617deb72cbf326e4637a92017022bd0df02a58 (diff) | |
download | FreeBSD-src-46721cc2c7d83b96c9c48ed0f7a7fa51d989cfaf.zip FreeBSD-src-46721cc2c7d83b96c9c48ed0f7a7fa51d989cfaf.tar.gz |
Restructure the MSR handling so it is entirely handled by processor-specific
code. There are only a handful of MSRs common between the two so there isn't
too much duplicate functionality.
The VT-x code has the following types of MSRs:
- MSRs that are unconditionally saved/restored on every guest/host context
switch (e.g., MSR_GSBASE).
- MSRs that are restored to guest values on entry to vmx_run() and saved
before returning. This is an optimization for MSRs that are not used in
host kernel context (e.g., MSR_KGSBASE).
- MSRs that are emulated and every access by the guest causes a trap into
the hypervisor (e.g., MSR_IA32_MISC_ENABLE).
Reviewed by: grehan
Diffstat (limited to 'usr.sbin')
-rw-r--r-- | usr.sbin/bhyve/bhyverun.c | 6 | ||||
-rw-r--r-- | usr.sbin/bhyve/xmsr.c | 71 | ||||
-rw-r--r-- | usr.sbin/bhyve/xmsr.h | 1 |
3 files changed, 68 insertions, 10 deletions
diff --git a/usr.sbin/bhyve/bhyverun.c b/usr.sbin/bhyve/bhyverun.c index 7dcf6d0..b2b36bb 100644 --- a/usr.sbin/bhyve/bhyverun.c +++ b/usr.sbin/bhyve/bhyverun.c @@ -803,6 +803,12 @@ main(int argc, char *argv[]) exit(1); } + error = init_msr(); + if (error) { + fprintf(stderr, "init_msr error %d", error); + exit(1); + } + init_mem(); init_inout(); pci_irq_init(ctx); diff --git a/usr.sbin/bhyve/xmsr.c b/usr.sbin/bhyve/xmsr.c index 63522bf..c0ab7c5 100644 --- a/usr.sbin/bhyve/xmsr.c +++ b/usr.sbin/bhyve/xmsr.c @@ -31,33 +31,84 @@ __FBSDID("$FreeBSD$"); #include <sys/types.h> +#include <machine/cpufunc.h> #include <machine/vmm.h> +#include <machine/specialreg.h> + #include <vmmapi.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> #include "xmsr.h" +static int cpu_vendor_intel, cpu_vendor_amd; + int emulate_wrmsr(struct vmctx *ctx, int vcpu, uint32_t code, uint64_t val) { - switch (code) { - case 0xd04: /* Sandy Bridge uncore PMC MSRs */ - case 0xc24: - return (0); - case 0x79: - return (0); /* IA32_BIOS_UPDT_TRIG MSR */ - default: - break; + if (cpu_vendor_intel) { + switch (code) { + case 0xd04: /* Sandy Bridge uncore PMCs */ + case 0xc24: + return (0); + case MSR_BIOS_UPDT_TRIG: + return (0); + case MSR_BIOS_SIGN: + return (0); + default: + break; + } } return (-1); } int -emulate_rdmsr(struct vmctx *ctx, int vcpu, uint32_t code, uint64_t *val) +emulate_rdmsr(struct vmctx *ctx, int vcpu, uint32_t num, uint64_t *val) { + int error = 0; - return (-1); + if (cpu_vendor_intel) { + switch (num) { + case MSR_BIOS_SIGN: + case MSR_IA32_PLATFORM_ID: + case MSR_PKG_ENERGY_STATUS: + case MSR_PP0_ENERGY_STATUS: + case MSR_PP1_ENERGY_STATUS: + case MSR_DRAM_ENERGY_STATUS: + *val = 0; + break; + default: + error = -1; + break; + } + } + return (error); +} + +int +init_msr(void) +{ + int error; + u_int regs[4]; + char cpu_vendor[13]; + + do_cpuid(0, regs); + ((u_int *)&cpu_vendor)[0] = regs[1]; + ((u_int *)&cpu_vendor)[1] = regs[3]; + ((u_int *)&cpu_vendor)[2] = regs[2]; + cpu_vendor[12] = '\0'; + + error = 0; + if (strcmp(cpu_vendor, "AuthenticAMD") == 0) { + cpu_vendor_amd = 1; + } else if (strcmp(cpu_vendor, "GenuineIntel") == 0) { + cpu_vendor_intel = 1; + } else { + fprintf(stderr, "Unknown cpu vendor \"%s\"\n", cpu_vendor); + error = -1; + } + return (error); } diff --git a/usr.sbin/bhyve/xmsr.h b/usr.sbin/bhyve/xmsr.h index b097cf8..bcf65b7 100644 --- a/usr.sbin/bhyve/xmsr.h +++ b/usr.sbin/bhyve/xmsr.h @@ -29,6 +29,7 @@ #ifndef _XMSR_H_ #define _XMSR_H_ +int init_msr(void); int emulate_wrmsr(struct vmctx *ctx, int vcpu, uint32_t code, uint64_t val); int emulate_rdmsr(struct vmctx *ctx, int vcpu, uint32_t code, uint64_t *val); |