/* hardware assisted paging bits */
extern int opt_hap_enabled;
+static void inline __update_guest_eip(
+ struct vmcb_struct *vmcb, unsigned int inst_len)
+{
+ if ( unlikely((inst_len == 0) || (inst_len > 15)) )
+ {
+ gdprintk(XENLOG_ERR, "Bad instruction length %u\n", inst_len);
+ domain_crash(current->domain);
+ return;
+ }
+
+ vmcb->rip += inst_len;
+ vmcb->rflags &= ~X86_EFLAGS_RF;
+
+ current->arch.hvm_svm.vmcb->interrupt_shadow = 0;
+}
+
static void svm_inject_exception(struct vcpu *v, int trap,
int ev, int error_code)
{
((uint64_t)eax << 32) | ebx, ((uint64_t)ecx << 32) | edx);
inst_len = __get_instruction_length(v, INSTR_CPUID, NULL);
- ASSERT(inst_len > 0);
__update_guest_eip(vmcb, inst_len);
}
v, list_b, 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 */
BUG();
}
- ASSERT(inst_len);
-
__update_guest_eip(vmcb, inst_len);
return result;
static void svm_vmexit_do_hlt(struct vmcb_struct *vmcb)
{
- __update_guest_eip(vmcb, 1);
+ struct vcpu *curr = current;
+ unsigned int inst_len;
+
+ inst_len = __get_instruction_length(curr, INSTR_HLT, NULL);
+ __update_guest_eip(vmcb, inst_len);
/* Check for interrupt not handled or new interrupt. */
if ( (vmcb->rflags & X86_EFLAGS_IF) &&
return;
}
- HVMTRACE_1D(HLT, current, /*int pending=*/ 0);
+ HVMTRACE_1D(HLT, curr, /*int pending=*/ 0);
hvm_hlt(vmcb->rflags);
}
* Unknown how many bytes the invlpg instruction will take. Use the
* maximum instruction length here
*/
- if (inst_copy_from_guest(opcode, svm_rip2pointer(v), length) < length)
+ if ( inst_copy_from_guest(opcode, svm_rip2pointer(v), length) < length )
{
gdprintk(XENLOG_ERR, "Error reading memory %d bytes\n", length);
- domain_crash(v->domain);
- return;
+ goto crash;
}
if (invlpga)
{
inst_len = __get_instruction_length(v, INSTR_INVLPGA, opcode);
- ASSERT(inst_len > 0);
__update_guest_eip(vmcb, inst_len);
/*
/* What about multiple prefix codes? */
prefix = (is_prefix(opcode[0])?opcode[0]:0);
inst_len = __get_instruction_length(v, INSTR_INVLPG, opcode);
- ASSERT(inst_len > 0);
+ if ( inst_len <= 0 )
+ {
+ gdprintk(XENLOG_ERR, "Error getting invlpg instr len\n");
+ goto crash;
+ }
inst_len--;
length -= inst_len;
paging_invlpg(v, g_vaddr);
/* signal invplg to ASID handler */
svm_asid_g_invlpg (v, g_vaddr);
+ return;
+
+ crash:
+ domain_crash(v->domain);
}
case VMEXIT_VMMCALL:
inst_len = __get_instruction_length(v, INSTR_VMCALL, NULL);
- ASSERT(inst_len > 0);
HVMTRACE_1D(VMMCALL, v, regs->eax);
rc = hvm_do_hypercall(regs);
if ( rc != HVM_HCALL_preempted )