static int svm_msr_write_intercept(unsigned int msr, uint64_t msr_content)
{
- int ret;
+ int ret, result = X86EMUL_OKAY;
struct vcpu *v = current;
struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
int sync = 0;
if ( wrmsr_viridian_regs(msr, msr_content) )
break;
- wrmsr_hypervisor_regs(msr, msr_content);
+ switch ( wrmsr_hypervisor_regs(msr, msr_content) )
+ {
+ case -EAGAIN:
+ result = X86EMUL_RETRY;
+ break;
+ case 0:
+ case 1:
+ break;
+ default:
+ goto gpf;
+ }
break;
}
if ( sync )
svm_vmload(vmcb);
- return X86EMUL_OKAY;
+ return result;
gpf:
hvm_inject_hw_exception(TRAP_gp_fault, 0);
case HNDL_unhandled:
if ( (vmx_write_guest_msr(msr, msr_content) != 0) &&
!is_last_branch_msr(msr) )
- wrmsr_hypervisor_regs(msr, msr_content);
+ switch ( wrmsr_hypervisor_regs(msr, msr_content) )
+ {
+ case -EAGAIN:
+ return X86EMUL_RETRY;
+ case 0:
+ case 1:
+ break;
+ default:
+ goto gp_fault;
+ }
break;
case HNDL_exception_raised:
return X86EMUL_EXCEPTION;
unsigned long gmfn = val >> 12;
unsigned int idx = val & 0xfff;
struct page_info *page;
+ p2m_type_t t;
if ( idx > 0 )
{
return 0;
}
- page = get_page_from_gfn(d, gmfn, NULL, P2M_ALLOC);
+ page = get_page_from_gfn(d, gmfn, &t, P2M_ALLOC);
if ( !page || !get_page_type(page, PGT_writable_page) )
{
if ( page )
put_page(page);
+
+ if ( p2m_is_paging(t) )
+ {
+ p2m_mem_paging_populate(d, gmfn);
+ return -EAGAIN;
+ }
+
gdprintk(XENLOG_WARNING,
"Bad GMFN %lx (MFN %lx) to MSR %08x\n",
- gmfn, page_to_mfn(page), base + idx);
+ gmfn, page ? page_to_mfn(page) : -1UL, base);
return 0;
}
goto fail;
break;
default:
- if ( wrmsr_hypervisor_regs(regs->ecx, msr_content) )
+ if ( wrmsr_hypervisor_regs(regs->ecx, msr_content) == 1 )
break;
rc = vmce_wrmsr(regs->ecx, msr_content);