#include <sys/cdefs.h>
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/x86_archext.h>
#include <machine/specialreg.h>
#include <machine/vmm.h>
#include "vmcb.h"
#include "svm.h"
struct vmcb_segment *
vmcb_segptr(struct vmcb *vmcb, int type)
{
struct vmcb_state *state = &vmcb->state;
switch (type) {
case VM_REG_GUEST_CS:
return (&state->cs);
case VM_REG_GUEST_DS:
return (&state->ds);
case VM_REG_GUEST_ES:
return (&state->es);
case VM_REG_GUEST_FS:
return (&state->fs);
case VM_REG_GUEST_GS:
return (&state->gs);
case VM_REG_GUEST_SS:
return (&state->ss);
case VM_REG_GUEST_GDTR:
return (&state->gdt);
case VM_REG_GUEST_IDTR:
return (&state->idt);
case VM_REG_GUEST_LDTR:
return (&state->ldt);
case VM_REG_GUEST_TR:
return (&state->tr);
default:
panic("unexpected seg %d", type);
}
}
uint64_t *
vmcb_regptr(struct vmcb *vmcb, int ident, uint32_t *dirtyp)
{
struct vmcb_state *state;
uint64_t *res = NULL;
uint32_t dirty = VMCB_CACHE_NONE;
state = &vmcb->state;
switch (ident) {
case VM_REG_GUEST_CR2:
res = &state->cr2;
dirty = VMCB_CACHE_CR2;
break;
case VM_REG_GUEST_CR3:
res = &state->cr3;
dirty = VMCB_CACHE_CR;
break;
case VM_REG_GUEST_CR4:
res = &state->cr4;
dirty = VMCB_CACHE_CR;
break;
case VM_REG_GUEST_DR6:
res = &state->dr6;
dirty = VMCB_CACHE_DR;
break;
case VM_REG_GUEST_DR7:
res = &state->dr7;
dirty = VMCB_CACHE_DR;
break;
case VM_REG_GUEST_EFER:
res = &state->efer;
dirty = VMCB_CACHE_CR;
break;
case VM_REG_GUEST_RAX:
res = &state->rax;
break;
case VM_REG_GUEST_RFLAGS:
res = &state->rflags;
break;
case VM_REG_GUEST_RIP:
res = &state->rip;
break;
case VM_REG_GUEST_RSP:
res = &state->rsp;
break;
default:
panic("unexpected register %d", ident);
break;
}
ASSERT(res != NULL);
if (dirtyp != NULL) {
*dirtyp |= dirty;
}
return (res);
}
uint64_t *
vmcb_msr_ptr(struct vmcb *vmcb, uint32_t msr, uint32_t *dirtyp)
{
uint64_t *res = NULL;
uint32_t dirty = 0;
struct vmcb_state *state = &vmcb->state;
switch (msr) {
case MSR_EFER:
res = &state->efer;
dirty = VMCB_CACHE_CR;
break;
case MSR_GSBASE:
res = &state->gs.base;
dirty = VMCB_CACHE_SEG;
break;
case MSR_FSBASE:
res = &state->fs.base;
dirty = VMCB_CACHE_SEG;
break;
case MSR_KGSBASE:
res = &state->kernelgsbase;
break;
case MSR_STAR:
res = &state->star;
break;
case MSR_LSTAR:
res = &state->lstar;
break;
case MSR_CSTAR:
res = &state->cstar;
break;
case MSR_SF_MASK:
res = &state->sfmask;
break;
case MSR_SYSENTER_CS_MSR:
res = &state->sysenter_cs;
break;
case MSR_SYSENTER_ESP_MSR:
res = &state->sysenter_esp;
break;
case MSR_SYSENTER_EIP_MSR:
res = &state->sysenter_eip;
break;
case MSR_PAT:
res = &state->g_pat;
dirty = VMCB_CACHE_NP;
break;
case MSR_DEBUGCTL:
res = &state->dbgctl;
dirty = VMCB_CACHE_LBR;
break;
case MSR_LBR_FROM:
res = &state->br_from;
dirty = VMCB_CACHE_LBR;
break;
case MSR_LBR_TO:
res = &state->br_to;
dirty = VMCB_CACHE_LBR;
break;
case MSR_LEX_FROM:
res = &state->int_from;
dirty = VMCB_CACHE_LBR;
break;
case MSR_LEX_TO:
res = &state->int_to;
dirty = VMCB_CACHE_LBR;
break;
}
if (res != NULL && dirtyp != NULL) {
*dirtyp = dirty;
}
return (res);
}