SVM patch to add 64bit hv support.

This patch only modifies svm files.
Tested with c/s 9015 with 32bit hv using UP Dom0, with UP linux and
winxpsp1 unmodified guests.
Tested with c/s 9015 with 64bit hv using UP Dom0, with 32bit and 64bit
UP linux and 32bit winxpsp1.

Signed-off-by: Tom Woller <thomas.woller@amd.com>
This commit is contained in:
kaf24@firebug.cl.cam.ac.uk committed 2006-02-28 22:57:38 +01:00
1 parent cc12ca26b5
commit 10a6fd541c
6 files changed
+203 -221

No files matched your search

+6 -12
View File
@@ -86,7 +86,7 @@ static inline unsigned long DECODE_GPR_VALUE(struct vmcb_struct *vmcb,
case 0x7:
value = regs->edi;
break;
#if X86_64
#if __x86_64__
case 0x8:
value = regs->r8;
break;
@@ -318,20 +318,14 @@ unsigned long get_effective_addr_sib(struct vmcb_struct *vmcb,
/* Get the register/mode number of src register in ModRM register. */
unsigned int decode_dest_reg(u8 m)
unsigned int decode_dest_reg(u8 prefix, u8 m)
{
#if __x86_64__
ASSERT(0); /* Need to adjust for REX prefix if applicable */
#endif
return (m >> 3) & 7;
return DECODE_MODRM_REG(prefix, m);
}
unsigned int decode_src_reg(u8 m)
unsigned int decode_src_reg(u8 prefix, u8 m)
{
#if __x86_64__
ASSERT(0); /* Need to adjust for REX prefix if applicable */
#endif
return m & 7;
return DECODE_MODRM_RM(prefix, m);
}
@@ -431,7 +425,7 @@ static const u8 *opc_bytes[INSTR_MAX_COUNT] =
* The caller can either pass a NULL pointer to the guest_eip_buf, or a pointer
* to enough bytes to satisfy the instruction including prefix bytes.
*/
unsigned int __get_instruction_length_from_list(struct vmcb_struct *vmcb,
int __get_instruction_length_from_list(struct vmcb_struct *vmcb,
enum instruction_index *list, unsigned int list_count,
u8 *guest_eip_buf, enum instruction_index *match)
{
+159 -165
View File
@@ -164,7 +164,7 @@ void asidpool_retire( struct vmcb_struct *vmcb, int core )
}
static inline void svm_inject_exception(struct vmcb_struct *vmcb,
int trap, int error_code)
int trap, int ev, int error_code)
{
eventinj_t event;
@@ -172,7 +172,7 @@ static inline void svm_inject_exception(struct vmcb_struct *vmcb,
event.fields.v = 1;
event.fields.type = EVENTTYPE_EXCEPTION;
event.fields.vector = trap;
event.fields.ev = 1;
event.fields.ev = ev;
event.fields.errorcode = error_code;
ASSERT(vmcb->eventinj.fields.v == 0);
@@ -237,109 +237,62 @@ void svm_load_cpu_guest_regs(struct vcpu *v, struct cpu_user_regs *regs)
}
#ifdef __x86_64__
static struct svm_msr_state percpu_msr[NR_CPUS];
static u32 msr_data_index[VMX_MSR_COUNT] =
{
MSR_LSTAR, MSR_STAR, MSR_CSTAR,
MSR_SYSCALL_MASK, MSR_EFER,
};
void svm_save_segments(struct vcpu *v)
{
rdmsrl(MSR_SHADOW_GS_BASE, v->arch.hvm_svm.msr_content.shadow_gs);
}
/*
* To avoid MSR save/restore at every VM exit/entry time, we restore
* the x86_64 specific MSRs at domain switch time. Since those MSRs are
* are not modified once set for generic domains, we don't save them,
* but simply reset them to the values set at percpu_traps_init().
*/
void svm_load_msrs(void)
{
struct svm_msr_state *host_state = &percpu_msr[smp_processor_id()];
int i;
while ( host_state->flags )
{
i = find_first_set_bit(host_state->flags);
wrmsrl(msr_data_index[i], host_state->msr_items[i]);
clear_bit(i, &host_state->flags);
}
}
static void svm_save_init_msrs(void)
void svm_restore_msrs(struct vcpu *v)
{
struct svm_msr_state *host_state = &percpu_msr[smp_processor_id()];
int i;
for ( i = 0; i < SVM_MSR_COUNT; i++ )
rdmsrl(msr_data_index[i], host_state->msr_items[i]);
}
#define CASE_READ_MSR(address) \
case MSR_ ## address: \
msr_content = msr->msr_items[SVM_INDEX_MSR_ ## address]; \
break
#define CASE_WRITE_MSR(address) \
case MSR_ ## address: \
msr->msr_items[SVM_INDEX_MSR_ ## address] = msr_content; \
if (!test_bit(SVM_INDEX_MSR_ ## address, &msr->flags)) \
{ \
set_bit(SVM_INDEX_MSR_ ## address, &msr->flags); \
} \
break
#define IS_CANO_ADDRESS(add) 1
static inline int long_mode_do_msr_read(struct cpu_user_regs *regs)
{
u64 msr_content = 0;
struct vcpu *vc = current;
struct svm_msr_state *msr = &vc->arch.hvm_svm.msr_content;
// struct svm_msr_state *msr = &vc->arch.hvm_svm.msr_content;
struct vmcb_struct *vmcb = vc->arch.hvm_svm.vmcb;
switch (regs->ecx)
{
case MSR_EFER:
msr_content = msr->msr_items[SVM_INDEX_MSR_EFER];
HVM_DBG_LOG(DBG_LEVEL_2, "EFER msr_content %llx\n",
(unsigned long long)msr_content);
if (test_bit(SVM_CPU_STATE_LME_ENABLED, &vc->arch.hvm_svm.cpu_state))
msr_content |= 1 << _EFER_LME;
if (SVM_LONG_GUEST(vc))
msr_content |= 1 << _EFER_LMA;
// msr_content = msr->msr_items[SVM_INDEX_MSR_EFER];
msr_content = vmcb->efer;
msr_content &= ~EFER_SVME;
break;
case MSR_FS_BASE:
if (!(SVM_LONG_GUEST(vc)))
/* XXX should it be GP fault */
domain_crash_synchronous();
msr_content = vmcb->fs.base;
break;
case MSR_GS_BASE:
if (!(SVM_LONG_GUEST(vc)))
domain_crash_synchronous();
msr_content = vmcb->gs.base;
break;
case MSR_SHADOW_GS_BASE:
msr_content = msr->shadow_gs;
msr_content = vmcb->kerngsbase;
break;
CASE_READ_MSR(STAR);
CASE_READ_MSR(LSTAR);
CASE_READ_MSR(CSTAR);
CASE_READ_MSR(SYSCALL_MASK);
case MSR_STAR:
msr_content = vmcb->star;
break;
case MSR_LSTAR:
msr_content = vmcb->lstar;
break;
case MSR_CSTAR:
msr_content = vmcb->cstar;
break;
case MSR_SYSCALL_MASK:
msr_content = vmcb->sfmask;
break;
default:
return 0;
}
@@ -356,8 +309,6 @@ static inline int long_mode_do_msr_write(struct cpu_user_regs *regs)
{
u64 msr_content = regs->eax | ((u64)regs->edx << 32);
struct vcpu *vc = current;
struct svm_msr_state *msr = &vc->arch.hvm_svm.msr_content;
struct svm_msr_state *host_state = &percpu_msr[smp_processor_id()];
struct vmcb_struct *vmcb = vc->arch.hvm_svm.vmcb;
HVM_DBG_LOG(DBG_LEVEL_1, "mode_do_msr_write msr %lx msr_content %lx\n",
@@ -373,26 +324,20 @@ static inline int long_mode_do_msr_write(struct cpu_user_regs *regs)
|| !test_bit(SVM_CPU_STATE_PAE_ENABLED,
&vc->arch.hvm_svm.cpu_state))
{
svm_inject_exception(vmcb, TRAP_gp_fault, 0);
svm_inject_exception(vmcb, TRAP_gp_fault, 1, 0);
}
}
if (msr_content & EFER_LME)
set_bit(SVM_CPU_STATE_LME_ENABLED, &vc->arch.hvm_svm.cpu_state);
/* We have already recorded that we want LME, so it will be set
* next time CR0 gets updated. So we clear that bit and continue.
*/
if ((msr_content ^ vmcb->efer) & EFER_LME)
msr_content &= ~EFER_LME;
/* No update for LME/LMA since it have no effect */
msr->msr_items[SVM_INDEX_MSR_EFER] = msr_content;
if (msr_content & ~(EFER_LME | EFER_LMA))
{
msr->msr_items[SVM_INDEX_MSR_EFER] = msr_content;
if (!test_bit(SVM_INDEX_MSR_EFER, &msr->flags))
{
rdmsrl(MSR_EFER, host_state->msr_items[SVM_INDEX_MSR_EFER]);
set_bit(SVM_INDEX_MSR_EFER, &host_state->flags);
set_bit(SVM_INDEX_MSR_EFER, &msr->flags);
wrmsrl(MSR_EFER, msr_content);
}
}
vmcb->efer = msr_content | EFER_SVME;
break;
case MSR_FS_BASE:
@@ -403,63 +348,42 @@ static inline int long_mode_do_msr_write(struct cpu_user_regs *regs)
if (!IS_CANO_ADDRESS(msr_content))
{
HVM_DBG_LOG(DBG_LEVEL_1, "Not cano address of msr write\n");
svm_inject_exception(vmcb, TRAP_gp_fault, 0);
svm_inject_exception(vmcb, TRAP_gp_fault, 1, 0);
}
if (regs->ecx == MSR_FS_BASE)
vmcb->fs.base = msr_content;
vmcb->fs.base = msr_content;
else
vmcb->gs.base = msr_content;
vmcb->gs.base = msr_content;
break;
case MSR_SHADOW_GS_BASE:
if (!(SVM_LONG_GUEST(vc)))
domain_crash_synchronous();
vmcb->kerngsbase = msr_content;
break;
case MSR_STAR:
vmcb->star = msr_content;
break;
case MSR_LSTAR:
vmcb->lstar = msr_content;
break;
case MSR_CSTAR:
vmcb->cstar = msr_content;
break;
case MSR_SYSCALL_MASK:
vmcb->sfmask = msr_content;
break;
vc->arch.hvm_svm.msr_content.shadow_gs = msr_content;
wrmsrl(MSR_SHADOW_GS_BASE, msr_content);
break;
CASE_WRITE_MSR(STAR);
CASE_WRITE_MSR(LSTAR);
CASE_WRITE_MSR(CSTAR);
CASE_WRITE_MSR(SYSCALL_MASK);
default:
return 0;
}
return 1;
}
void
svm_restore_msrs(struct vcpu *v)
{
int i = 0;
struct svm_msr_state *guest_state;
struct svm_msr_state *host_state;
unsigned long guest_flags;
guest_state = &v->arch.hvm_svm.msr_content;;
host_state = &percpu_msr[smp_processor_id()];
wrmsrl(MSR_SHADOW_GS_BASE, guest_state->shadow_gs);
guest_flags = guest_state->flags;
if (!guest_flags)
return;
while (guest_flags){
i = find_first_set_bit(guest_flags);
HVM_DBG_LOG(DBG_LEVEL_2,
"restore guest's index %d msr %lx with %lx\n",
i, (unsigned long) msr_data_index[i], (unsigned long) guest_state->msr_items[i]);
set_bit(i, &host_state->flags);
wrmsrl(msr_data_index[i], guest_state->msr_items[i]);
clear_bit(i, &guest_flags);
}
}
#else
#define svm_save_init_msrs() ((void)0)
static inline int long_mode_do_msr_read(struct cpu_user_regs *regs)
{
return 0;
@@ -497,11 +421,30 @@ int svm_instruction_length(struct vcpu *v)
{
struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
unsigned long cr0 = vmcb->cr0, eflags = vmcb->rflags, mode;
mode = (eflags & X86_EFLAGS_VM) || !(cr0 & X86_CR0_PE) ? 2 : 4;
/* check which operating mode the guest is running */
if( vmcb->efer & EFER_LMA )
mode = vmcb->cs.attributes.fields.l ? 8 : 4;
else
mode = (eflags & X86_EFLAGS_VM) || !(cr0 & X86_CR0_PE) ? 2 : 4;
return svm_instrlen(guest_cpu_user_regs(), mode);
}
unsigned long svm_get_ctrl_reg(struct vcpu *v, unsigned int num)
{
switch ( num )
{
case 0:
return v->arch.hvm_svm.cpu_shadow_cr0;
case 2:
return v->arch.hvm_svm.cpu_cr2;
case 3:
return v->arch.hvm_svm.cpu_cr3;
default:
BUG();
}
return 0; /* dummy */
}
int start_svm(void)
{
u32 eax, ecx, edx;
@@ -519,8 +462,6 @@ int start_svm(void)
asidpool_init(smp_processor_id());
printk("AMD SVM Extension is enabled for cpu %d.\n", smp_processor_id());
svm_save_init_msrs();
/* Setup HVM interfaces */
hvm_funcs.disable = stop_svm;
@@ -542,6 +483,7 @@ int start_svm(void)
hvm_funcs.realmode = svm_realmode;
hvm_funcs.paging_enabled = svm_paging_enabled;
hvm_funcs.instruction_length = svm_instruction_length;
hvm_funcs.get_guest_ctrl_reg = svm_get_ctrl_reg;
hvm_enabled = 1;
@@ -631,8 +573,17 @@ void save_svm_cpu_user_regs(struct vcpu *v, struct cpu_user_regs *ctxt)
}
#if defined (__x86_64__)
void svm_store_cpu_user_regs(struct cpu_user_regs *regs, struct vcpu *c )
void svm_store_cpu_user_regs(struct cpu_user_regs *regs, struct vcpu *v )
{
struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
regs->rip = vmcb->rip;
regs->rsp = vmcb->rsp;
regs->rflags = vmcb->rflags;
regs->cs = vmcb->cs.sel;
regs->ds = vmcb->ds.sel;
regs->es = vmcb->es.sel;
regs->ss = vmcb->ss.sel;
}
#elif defined (__i386__)
void svm_store_cpu_user_regs(struct cpu_user_regs *regs, struct vcpu *v)
@@ -882,9 +833,9 @@ static int svm_do_page_fault(unsigned long va, struct cpu_user_regs *regs)
/* No support for APIC */
if (!hvm_apic_support(v->domain) && gpa >= 0xFEC00000)
{
unsigned long inst_len;
inst_len = svm_instruction_length(v);
if (inst_len == (unsigned long)-1)
int inst_len;
inst_len = svm_instruction_length(v);
if (inst_len == -1)
{
printf("%s: INST_LEN - Unable to decode properly.\n", __func__);
domain_crash_synchronous();
@@ -937,6 +888,14 @@ static void svm_do_general_protection_fault(struct vcpu *v,
eip = vmcb->rip;
error_code = vmcb->exitinfo1;
if (vmcb->idtr.limit == 0) {
printf("Huh? We got a GP Fault with an invalid IDTR!\n");
svm_dump_vmcb(__func__, vmcb);
svm_dump_regs(__func__, regs);
svm_dump_inst(vmcb->rip);
__hvm_bug(regs);
}
HVM_DBG_LOG(DBG_LEVEL_1,
"svm_general_protection_fault: eip = %lx, erro_code = %lx",
eip, error_code);
@@ -949,7 +908,7 @@ static void svm_do_general_protection_fault(struct vcpu *v,
/* Reflect it back into the guest */
svm_inject_exception(vmcb, TRAP_gp_fault, error_code);
svm_inject_exception(vmcb, TRAP_gp_fault, 1, error_code);
}
/* Reserved bits: [31:14], [12:1] */
@@ -961,7 +920,7 @@ static void svm_vmexit_do_cpuid(struct vmcb_struct *vmcb, unsigned long input,
unsigned int eax, ebx, ecx, edx;
unsigned long eip;
struct vcpu *v = current;
unsigned int inst_len;
int inst_len;
ASSERT(vmcb);
@@ -978,8 +937,10 @@ static void svm_vmexit_do_cpuid(struct vmcb_struct *vmcb, unsigned long input,
if (input == 1)
{
#ifndef __x86_64__
if ( hvm_apic_support(v->domain) &&
!vlapic_global_enabled((VLAPIC(v))) )
#endif
clear_bit(X86_FEATURE_APIC, &edx);
#if CONFIG_PAGING_LEVELS < 3
@@ -1019,6 +980,7 @@ static void svm_vmexit_do_cpuid(struct vmcb_struct *vmcb, unsigned long input,
eip, input, eax, ebx, ecx, edx);
inst_len = __get_instruction_length(vmcb, INSTR_CPUID, NULL);
ASSERT(inst_len > 0);
__update_guest_eip(vmcb, inst_len);
}
@@ -1111,9 +1073,11 @@ static void svm_dr_access (struct vcpu *v, unsigned int reg, unsigned int type,
unsigned long *reg_p = 0;
unsigned int gpreg = 0;
unsigned long eip;
unsigned int inst_len;
int inst_len;
int index;
struct vmcb_struct *vmcb;
u8 buffer[MAX_INST_LEN];
u8 prefix = 0;
vmcb = v->arch.hvm_svm.vmcb;
@@ -1121,13 +1085,15 @@ static void svm_dr_access (struct vcpu *v, unsigned int reg, unsigned int type,
eip = vmcb->rip;
inst_copy_from_guest(buffer, svm_rip2pointer(vmcb), sizeof(buffer));
index = skip_prefix_bytes(buffer, sizeof(buffer));
ASSERT(buffer[index+0] == 0x0f && (buffer[index+1] & 0xFD) == 0x21);
ASSERT(buffer[0] == 0x0f && (buffer[1] & 0xFD) == 0x21);
if (index > 0 && (buffer[index-1] & 0xF0) == 0x40)
prefix = buffer[index-1];
gpreg = decode_src_reg(buffer[2]);
#if DEBUG
ASSERT(reg == decode_dest_reg(buffer[2]));
#endif
gpreg = decode_src_reg(prefix, buffer[index + 2]);
ASSERT(reg == decode_dest_reg(prefix, buffer[index + 2]));
HVM_DBG_LOG(DBG_LEVEL_1, "svm_dr_access : eip=%lx, reg=%d, gpreg = %x",
eip, reg, gpreg);
@@ -1148,6 +1114,7 @@ static void svm_dr_access (struct vcpu *v, unsigned int reg, unsigned int type,
__hvm_bug(regs);
break;
}
ASSERT(inst_len > 0);
__update_guest_eip(vmcb, inst_len);
}
@@ -1405,7 +1372,7 @@ static int svm_set_cr0(unsigned long value)
&v->arch.hvm_svm.cpu_state))
{
HVM_DBG_LOG(DBG_LEVEL_1, "Enable paging before PAE enable\n");
svm_inject_exception(vmcb, TRAP_gp_fault, 0);
svm_inject_exception(vmcb, TRAP_gp_fault, 1, 0);
}
if (test_bit(SVM_CPU_STATE_LME_ENABLED, &v->arch.hvm_svm.cpu_state))
@@ -1468,7 +1435,7 @@ static int svm_set_cr0(unsigned long value)
*/
if ((value & X86_CR0_PE) == 0) {
if (value & X86_CR0_PG) {
svm_inject_exception(vmcb, TRAP_gp_fault, 0);
svm_inject_exception(vmcb, TRAP_gp_fault, 1, 0);
return 0;
}
@@ -1503,7 +1470,7 @@ static void mov_from_cr(int cr, int gp, struct cpu_user_regs *regs)
value = (unsigned long) v->arch.hvm_svm.cpu_cr3;
break;
case 4:
value = vmcb->cr4;
value = (unsigned long) v->arch.hvm_svm.cpu_shadow_cr4;
break;
case 8:
#if 0
@@ -1602,12 +1569,19 @@ static int mov_to_cr(int gpreg, int cr, struct cpu_user_regs *regs)
case 4:
/* CR4 */
if (value & X86_CR4_PAE)
__hvm_bug(regs); /* not implemented */
if (value & X86_CR4_PAE) {
set_bit(SVM_CPU_STATE_PAE_ENABLED, &v->arch.hvm_svm.cpu_state);
} else {
if (test_bit(SVM_CPU_STATE_LMA_ENABLED,
&v->arch.hvm_svm.cpu_state)) {
svm_inject_exception(vmcb, TRAP_gp_fault, 1, 0);
}
clear_bit(SVM_CPU_STATE_PAE_ENABLED, &v->arch.hvm_svm.cpu_state);
}
old_cr = vmcb->cr4;
vmcb->cr4 = value;
old_cr = v->arch.hvm_svm.cpu_shadow_cr4;
v->arch.hvm_svm.cpu_shadow_cr4 = value;
vmcb->cr4 = value | SVM_CR4_HOST_MASK;
/*
* Writing to CR4 to modify the PSE, PGE, or PAE flag invalidates
@@ -1636,10 +1610,12 @@ static int svm_cr_access(struct vcpu *v, unsigned int cr, unsigned int type,
struct cpu_user_regs *regs)
{
struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
unsigned int inst_len = 0;
int inst_len = 0;
int index;
unsigned int gpreg;
unsigned long value;
u8 buffer[6];
u8 buffer[MAX_INST_LEN];
u8 prefix = 0;
int result = 1;
enum instruction_index list_a[] = {INSTR_MOV2CR, INSTR_CLTS, INSTR_LMSW};
enum instruction_index list_b[] = {INSTR_MOVCR2, INSTR_SMSW};
@@ -1648,29 +1624,41 @@ static int svm_cr_access(struct vcpu *v, unsigned int cr, unsigned int type,
ASSERT(vmcb);
inst_copy_from_guest(buffer, svm_rip2pointer(vmcb), sizeof(buffer));
/* get index to first actual instruction byte - as we will need to know where the
* prefix lives later on
*/
index = skip_prefix_bytes(buffer, sizeof(buffer));
if (type == TYPE_MOV_TO_CR)
{
inst_len = __get_instruction_length_from_list(vmcb, list_a,
ARR_SIZE(list_a), buffer, &match);
ARR_SIZE(list_a), &buffer[index], &match);
}
else
{
inst_len = __get_instruction_length_from_list(vmcb, list_b,
ARR_SIZE(list_b), buffer, &match);
ARR_SIZE(list_b), &buffer[index], &match);
}
ASSERT(inst_len > 0);
inst_len += index;
/* Check for REX prefix - it's ALWAYS the last byte of any prefix bytes */
if (index > 0 && (buffer[index-1] & 0xF0) == 0x40)
prefix = buffer[index-1];
HVM_DBG_LOG(DBG_LEVEL_1, "eip = %lx", (unsigned long) vmcb->rip);
switch (match)
{
case INSTR_MOV2CR:
gpreg = decode_src_reg(buffer[2]);
gpreg = decode_src_reg(prefix, buffer[index+2]);
result = mov_to_cr(gpreg, cr, regs);
break;
case INSTR_MOVCR2:
gpreg = decode_src_reg(buffer[2]);
gpreg = decode_src_reg(prefix, buffer[index+2]);
mov_from_cr(cr, gpreg, regs);
break;
@@ -1686,7 +1674,7 @@ static int svm_cr_access(struct vcpu *v, unsigned int cr, unsigned int type,
if (svm_dbg_on)
svm_dump_inst(svm_rip2pointer(vmcb));
gpreg = decode_src_reg(buffer[2]);
gpreg = decode_src_reg(prefix, buffer[index+2]);
value = get_reg(gpreg, regs, vmcb) & 0xF;
if (svm_dbg_on)
@@ -1704,7 +1692,7 @@ static int svm_cr_access(struct vcpu *v, unsigned int cr, unsigned int type,
case INSTR_SMSW:
svm_dump_inst(svm_rip2pointer(vmcb));
value = v->arch.hvm_svm.cpu_shadow_cr0;
gpreg = decode_src_reg(buffer[2]);
gpreg = decode_src_reg(prefix, buffer[index+2]);
set_reg(gpreg, value, regs, vmcb);
if (svm_dbg_on)
@@ -1727,7 +1715,7 @@ static int svm_cr_access(struct vcpu *v, unsigned int cr, unsigned int type,
static inline void svm_do_msr_access(struct vcpu *v, struct cpu_user_regs *regs)
{
struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
unsigned int inst_len;
int inst_len;
int64_t tsc_sum;
ASSERT(vmcb);
@@ -1868,7 +1856,7 @@ void svm_handle_invlpg(const short invlpga, struct cpu_user_regs *regs)
struct vcpu *v = current;
u8 opcode[MAX_INST_SIZE], prefix, length = MAX_INST_SIZE;
unsigned long g_vaddr;
unsigned int inst_len;
int inst_len;
struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
ASSERT(vmcb);
@@ -1885,6 +1873,7 @@ void svm_handle_invlpg(const short invlpga, struct cpu_user_regs *regs)
if (invlpga)
{
inst_len = __get_instruction_length(vmcb, INSTR_INVLPGA, opcode);
ASSERT(inst_len > 0);
__update_guest_eip(vmcb, inst_len);
/*
@@ -1898,6 +1887,7 @@ void svm_handle_invlpg(const short invlpga, struct cpu_user_regs *regs)
/* What about multiple prefix codes? */
prefix = (is_prefix(opcode[0])?opcode[0]:0);
inst_len = __get_instruction_length(vmcb, INSTR_INVLPG, opcode);
ASSERT(inst_len > 0);
inst_len--;
length -= inst_len;
@@ -1949,7 +1939,10 @@ static int svm_do_vmmcall_reset_to_realmode(struct vcpu *v,
v->arch.hvm_svm.cpu_shadow_cr0 = X86_CR0_ET;
vmcb->cr2 = 0;
vmcb->cr4 = 0;
vmcb->efer = EFER_SVME;
vmcb->cr4 = SVM_CR4_HOST_MASK;
v->arch.hvm_svm.cpu_shadow_cr4 = 0;
/* This will jump to ROMBIOS */
vmcb->rip = 0xFFF0;
@@ -2019,12 +2012,13 @@ static int svm_do_vmmcall_reset_to_realmode(struct vcpu *v,
static int svm_do_vmmcall(struct vcpu *v, struct cpu_user_regs *regs)
{
struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
unsigned int inst_len;
int inst_len;
ASSERT(vmcb);
ASSERT(regs);
inst_len = __get_instruction_length(vmcb, INSTR_VMCALL, NULL);
ASSERT(inst_len > 0);
/* VMMCALL sanity check */
if (vmcb->cpl > get_vmmcall_cpl(regs->edi))
@@ -2478,7 +2472,7 @@ asmlinkage void svm_vmexit_handler(struct cpu_user_regs regs)
{
v->arch.hvm_svm.injecting_event = 1;
/* Inject #PG using Interruption-Information Fields */
svm_inject_exception(vmcb, TRAP_page_fault, regs.error_code);
svm_inject_exception(vmcb, TRAP_page_fault, 1, regs.error_code);
v->arch.hvm_svm.cpu_cr2 = va;
vmcb->cr2 = va;
+10 -16
View File
@@ -190,7 +190,6 @@ static int construct_init_vmcb_guest(struct arch_svm_struct *arch_svm,
unsigned long eflags;
unsigned long shadow_cr;
struct vmcb_struct *vmcb = arch_svm->vmcb;
struct Xgt_desc_struct desc;
/* Allows IRQs to be shares */
vmcb->vintr.fields.intr_masking = 1;
@@ -224,9 +223,9 @@ static int construct_init_vmcb_guest(struct arch_svm_struct *arch_svm,
vmcb->fs.base = 0;
vmcb->gs.base = 0;
__asm__ __volatile__ ("sidt (%0) \n" :: "a"(&desc) : "memory");
vmcb->idtr.base = desc.address;
vmcb->idtr.limit = desc.size;
/* Guest Interrupt descriptor table */
vmcb->idtr.base = 0;
vmcb->idtr.limit = 0;
/* Set up segment attributes */
attrib.bytes = 0;
@@ -248,15 +247,11 @@ static int construct_init_vmcb_guest(struct arch_svm_struct *arch_svm,
attrib.fields.type = 0xb; /* type=0xb -> executable/readable, accessed */
vmcb->cs.attributes = attrib;
/* Global descriptor table */
//NMERGE7500 - can probably remove access to gdtr
vmcb->gdtr.base = regs->edx;
regs->edx = 0;
ASSERT(regs->eax <= 0xFFFF); /* Make sure we're in the limit */
vmcb->gdtr.limit = regs->eax;
regs->eax = 0;
/* Guest Global descriptor table */
vmcb->gdtr.base = 0;
vmcb->gdtr.limit = 0;
/* Local Descriptor Table */
/* Guest Local Descriptor Table */
attrib.fields.s = 0; /* not code or data segement */
attrib.fields.type = 0x2; /* LDT */
attrib.fields.db = 0; /* 16-bit */
@@ -279,11 +274,10 @@ static int construct_init_vmcb_guest(struct arch_svm_struct *arch_svm,
/* CR3 is set in svm_final_setup_guest */
__asm__ __volatile__ ("mov %%cr4,%0" : "=r" (crn) :);
shadow_cr = crn;
vmcb->cr4 = shadow_cr;
arch_svm->cpu_shadow_cr4 = crn & ~(X86_CR4_PGE | X86_CR4_PSE);
vmcb->cr4 = crn | SVM_CR4_HOST_MASK;
//MERGE7500 - should write a 0 instead to rsp?
vmcb->rsp = regs->esp;
vmcb->rsp = 0;
vmcb->rip = regs->eip;
eflags = regs->eflags & ~HVM_EFLAGS_RESERVED_0; /* clear 0s */
-4
View File
@@ -107,8 +107,6 @@ ENTRY(svm_asm_do_launch)
movq %rax, VMCB_rax(%rcx)
movq VCPU_svm_hsa_pa(%rbx), %rax
VMSAVE
/* XXX FPU SAVE */
/* XXX DO TSC OFFSET */
movq VCPU_svm_vmcb_pa(%rbx), %rax
popq %r15
@@ -137,9 +135,7 @@ ENTRY(svm_asm_do_launch)
VMSAVE
/* rax is the only register we're allowed to touch here... */
/* XXX FPU SAVE */
GET_CURRENT(%rax)
/* XXX DO TSC OFFSET */
movq VCPU_svm_hsa_pa(%rax), %rax
VMLOAD
+17 -6
View File
@@ -83,15 +83,15 @@ extern unsigned long get_effective_addr_sib(struct vmcb_struct *vmcb,
struct cpu_user_regs *regs, const u8 prefix, const u8 *operand,
u8 *size);
extern OPERATING_MODE get_operating_mode (struct vmcb_struct *vmcb);
extern unsigned int decode_dest_reg(u8 modrm);
extern unsigned int decode_src_reg(u8 modrm);
extern unsigned int decode_dest_reg(u8 prefix, u8 modrm);
extern unsigned int decode_src_reg(u8 prefix, u8 modrm);
extern unsigned long svm_rip2pointer(struct vmcb_struct *vmcb);
extern unsigned int __get_instruction_length_from_list(struct vmcb_struct *vmcb,
extern int __get_instruction_length_from_list(struct vmcb_struct *vmcb,
enum instruction_index *list, unsigned int list_count,
u8 *guest_eip_buf, enum instruction_index *match);
static inline unsigned int __get_instruction_length(struct vmcb_struct *vmcb,
static inline int __get_instruction_length(struct vmcb_struct *vmcb,
enum instruction_index instr, u8 *guest_eip_buf)
{
return __get_instruction_length_from_list(vmcb, &instr, 1, guest_eip_buf,
@@ -138,9 +138,20 @@ static inline unsigned int is_prefix(u8 opc)
}
static void inline __update_guest_eip(struct vmcb_struct *vmcb,
unsigned long inst_len)
static inline int skip_prefix_bytes(u8 *buf, size_t size)
{
int index;
for (index = 0; index < size && is_prefix(buf[index]); index ++)
/* do nothing */ ;
return index;
}
static void inline __update_guest_eip(struct vmcb_struct *vmcb,
int inst_len)
{
ASSERT(inst_len > 0);
vmcb->rip += inst_len;
}
+11 -18
View File
@@ -269,21 +269,6 @@ enum {
#define SVM_LONG_GUEST(ed) \
(test_bit(SVM_CPU_STATE_LMA_ENABLED, &ed->arch.hvm_svm.cpu_state))
enum {
SVM_INDEX_MSR_LSTAR = 0,
SVM_INDEX_MSR_STAR,
SVM_INDEX_MSR_CSTAR,
SVM_INDEX_MSR_SYSCALL_MASK,
SVM_INDEX_MSR_EFER,
SVM_MSR_COUNT,
};
struct svm_msr_state {
unsigned long flags;
unsigned long msr_items[SVM_MSR_COUNT];
unsigned long shadow_gs;
};
/*
* Attribute for segment selector. This is a copy of bit 40:47 & 52:55 of the
@@ -449,7 +434,7 @@ struct vmcb_struct {
struct arch_svm_struct {
struct vmcb_struct *vmcb;
void *host_save_area;
void *host_save_area;
u64 host_save_pa;
u64 vmcb_pa;
u32 *iopm;
@@ -461,11 +446,11 @@ struct arch_svm_struct {
u32 asid_core;
unsigned long flags; /* VMCB flags */
unsigned long cpu_shadow_cr0; /* copy of guest read shadow CR0 */
unsigned long cpu_shadow_cr0; /* Guest value for CR0 */
unsigned long cpu_shadow_cr4; /* Guest value for CR4 */
unsigned long cpu_cr2;
unsigned long cpu_cr3;
unsigned long cpu_state;
struct svm_msr_state msr_content;
struct timer hlt_timer; /* hlt ins emulation wakeup timer */
};
@@ -487,6 +472,14 @@ enum {
#define VMCB_EFLAGS_RESERVED_0 0xffc08028 /* bitmap for 0 */
#define VMCB_EFLAGS_RESERVED_1 0x00000002 /* bitmap for 1 */
/* These bits in the CR4 are owned by the host */
#ifdef __i386__
#define SVM_CR4_HOST_MASK (0)
#else
#define SVM_CR4_HOST_MASK (X86_CR4_PAE)
#endif
#endif /* ASM_X86_HVM_SVM_VMCS_H__ */
/*
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.