Add an option to ignore accesses by the guest to unimplemented MSRs.

Also, ignore a couple of SandyBridge uncore PMC MSRs that Centos 6.4 writes
to during boot.

Reviewed by:	grehan
This commit is contained in:
neel 2013-12-19 22:27:28 +00:00
parent 86d162fb60
commit 5dab6f9ed3
4 changed files with 58 additions and 14 deletions

View File

@ -32,7 +32,7 @@
.Nd "run a guest operating system inside a virtual machine"
.Sh SYNOPSIS
.Nm
.Op Fl aehAHPW
.Op Fl aehwAHPW
.Op Fl c Ar numcpus
.Op Fl g Ar gdbport
.Op Fl p Ar pinnedcpu
@ -229,6 +229,8 @@ Force
.Nm
to exit when a guest issues an access to an I/O port that is not emulated.
This is intended for debug purposes.
.It Fl w
Ignore accesses to unimplemented Model Specific Registers (MSRs). This is intended for debug purposes.
.It Fl h
Print help message and exit.
.It Ar vmname

View File

@ -87,6 +87,7 @@ static int guest_vmexit_on_hlt, guest_vmexit_on_pause, disable_x2apic;
static int virtio_msix = 1;
static int strictio;
static int strictmsr = 1;
static int acpi;
@ -122,7 +123,7 @@ usage(int code)
{
fprintf(stderr,
"Usage: %s [-aehAHIPW] [-g <gdb port>] [-s <pci>] [-S <pci>]\n"
"Usage: %s [-aehwAHIPW] [-g <gdb port>] [-s <pci>] [-S <pci>]\n"
" %*s [-c vcpus] [-p pincpu] [-m mem] [-l <lpc>] <vm>\n"
" -a: local apic is in XAPIC mode (default is X2APIC)\n"
" -A: create an ACPI table\n"
@ -137,7 +138,8 @@ usage(int code)
" -s: <slot,driver,configinfo> PCI slot config\n"
" -S: <slot,driver,configinfo> legacy PCI slot config\n"
" -l: LPC device configuration\n"
" -m: memory size in MB\n",
" -m: memory size in MB\n"
" -w: ignore unimplemented MSRs\n",
progname, (int)strlen(progname), "");
exit(code);
@ -310,20 +312,43 @@ vmexit_inout(struct vmctx *ctx, struct vm_exit *vme, int *pvcpu)
static int
vmexit_rdmsr(struct vmctx *ctx, struct vm_exit *vme, int *pvcpu)
{
fprintf(stderr, "vm exit rdmsr 0x%x, cpu %d\n", vme->u.msr.code,
*pvcpu);
return (VMEXIT_ABORT);
uint64_t val;
uint32_t eax, edx;
int error;
val = 0;
error = emulate_rdmsr(ctx, *pvcpu, vme->u.msr.code, &val);
if (error != 0) {
fprintf(stderr, "rdmsr to register %#x on vcpu %d\n",
vme->u.msr.code, *pvcpu);
if (strictmsr)
return (VMEXIT_ABORT);
}
eax = val;
error = vm_set_register(ctx, *pvcpu, VM_REG_GUEST_RAX, eax);
assert(error == 0);
edx = val >> 32;
error = vm_set_register(ctx, *pvcpu, VM_REG_GUEST_RDX, edx);
assert(error == 0);
return (VMEXIT_CONTINUE);
}
static int
vmexit_wrmsr(struct vmctx *ctx, struct vm_exit *vme, int *pvcpu)
{
int newcpu;
int retval = VMEXIT_CONTINUE;
int error;
newcpu = emulate_wrmsr(ctx, *pvcpu, vme->u.msr.code,vme->u.msr.wval);
return (retval);
error = emulate_wrmsr(ctx, *pvcpu, vme->u.msr.code, vme->u.msr.wval);
if (error != 0) {
fprintf(stderr, "wrmsr to register %#x(%#lx) on vcpu %d\n",
vme->u.msr.code, vme->u.msr.wval, *pvcpu);
if (strictmsr)
return (VMEXIT_ABORT);
}
return (VMEXIT_CONTINUE);
}
static int
@ -577,7 +602,7 @@ main(int argc, char *argv[])
guest_ncpus = 1;
memsize = 256 * MB;
while ((c = getopt(argc, argv, "abehAHIPWp:g:c:s:S:m:l:")) != -1) {
while ((c = getopt(argc, argv, "abehwAHIPWp:g:c:s:S:m:l:")) != -1) {
switch (c) {
case 'a':
disable_x2apic = 1;
@ -636,6 +661,9 @@ main(int argc, char *argv[])
case 'e':
strictio = 1;
break;
case 'w':
strictmsr = 0;
break;
case 'W':
virtio_msix = 0;
break;

View File

@ -43,6 +43,19 @@ int
emulate_wrmsr(struct vmctx *ctx, int vcpu, uint32_t code, uint64_t val)
{
printf("Unknown WRMSR code %x, val %lx, cpu %d\n", code, val, vcpu);
exit(1);
switch (code) {
case 0xd04: /* Sandy Bridge uncore PMC MSRs */
case 0xc24:
return (0);
default:
break;
}
return (-1);
}
int
emulate_rdmsr(struct vmctx *ctx, int vcpu, uint32_t code, uint64_t *val)
{
return (-1);
}

View File

@ -30,5 +30,6 @@
#define _XMSR_H_
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);
#endif