aboutsummaryrefslogtreecommitdiffstats
path: root/xen/arch/x86/hvm
diff options
context:
space:
mode:
authorSuravee Suthikulpanit <suravee.suthikulpanit@amd.com>2013-08-13 14:22:14 +0200
committerJan Beulich <jbeulich@suse.com>2013-08-13 14:22:14 +0200
commit85fc517ec3055e8e8d9c9e36e15a81e630237252 (patch)
tree9b268fb99f72f77824deb9e5573329fc06d441c8 /xen/arch/x86/hvm
parent73f18583dd824f0e49f65149ef603600ce31b8ee (diff)
downloadxen-85fc517ec3055e8e8d9c9e36e15a81e630237252.tar.gz
xen-85fc517ec3055e8e8d9c9e36e15a81e630237252.tar.bz2
xen-85fc517ec3055e8e8d9c9e36e15a81e630237252.zip
x86/AMD: Fix nested svm crash due to assertion in __virt_to_maddr
Fix assertion in __virt_to_maddr when starting nested SVM guest in debug mode. Investigation has shown that svm_vmsave/svm_vmload make use of __pa() with invalid address. Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com> Reviewed-by: Tim Deegan <tim@xen.org>
Diffstat (limited to 'xen/arch/x86/hvm')
-rw-r--r--xen/arch/x86/hvm/svm/svm.c52
1 files changed, 43 insertions, 9 deletions
diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c
index 4cc4b15315..a20540b1d1 100644
--- a/xen/arch/x86/hvm/svm/svm.c
+++ b/xen/arch/x86/hvm/svm/svm.c
@@ -1795,6 +1795,32 @@ svm_vmexit_do_vmrun(struct cpu_user_regs *regs,
return;
}
+static struct page_info *
+nsvm_get_nvmcb_page(struct vcpu *v, uint64_t vmcbaddr)
+{
+ p2m_type_t p2mt;
+ struct page_info *page;
+ struct nestedvcpu *nv = &vcpu_nestedhvm(v);
+
+ if ( !nestedsvm_vmcb_map(v, vmcbaddr) )
+ return NULL;
+
+ /* Need to translate L1-GPA to MPA */
+ page = get_page_from_gfn(v->domain,
+ nv->nv_vvmcxaddr >> PAGE_SHIFT,
+ &p2mt, P2M_ALLOC | P2M_UNSHARE);
+ if ( !page )
+ return NULL;
+
+ if ( !p2m_is_ram(p2mt) || p2m_is_readonly(p2mt) )
+ {
+ put_page(page);
+ return NULL;
+ }
+
+ return page;
+}
+
static void
svm_vmexit_do_vmload(struct vmcb_struct *vmcb,
struct cpu_user_regs *regs,
@@ -1802,7 +1828,7 @@ svm_vmexit_do_vmload(struct vmcb_struct *vmcb,
{
int ret;
unsigned int inst_len;
- struct nestedvcpu *nv = &vcpu_nestedhvm(v);
+ struct page_info *page;
if ( (inst_len = __get_instruction_length(v, INSTR_VMLOAD)) == 0 )
return;
@@ -1813,13 +1839,18 @@ svm_vmexit_do_vmload(struct vmcb_struct *vmcb,
goto inject;
}
- if (!nestedsvm_vmcb_map(v, vmcbaddr)) {
- gdprintk(XENLOG_ERR, "VMLOAD: mapping vmcb failed, injecting #UD\n");
+ page = nsvm_get_nvmcb_page(v, vmcbaddr);
+ if ( !page )
+ {
+ gdprintk(XENLOG_ERR,
+ "VMLOAD: mapping failed, injecting #UD\n");
ret = TRAP_invalid_op;
goto inject;
}
- svm_vmload(nv->nv_vvmcx);
+ svm_vmload_pa(page_to_maddr(page));
+ put_page(page);
+
/* State in L1 VMCB is stale now */
v->arch.hvm_svm.vmcb_in_sync = 0;
@@ -1838,7 +1869,7 @@ svm_vmexit_do_vmsave(struct vmcb_struct *vmcb,
{
int ret;
unsigned int inst_len;
- struct nestedvcpu *nv = &vcpu_nestedhvm(v);
+ struct page_info *page;
if ( (inst_len = __get_instruction_length(v, INSTR_VMSAVE)) == 0 )
return;
@@ -1849,14 +1880,17 @@ svm_vmexit_do_vmsave(struct vmcb_struct *vmcb,
goto inject;
}
- if (!nestedsvm_vmcb_map(v, vmcbaddr)) {
- gdprintk(XENLOG_ERR, "VMSAVE: mapping vmcb failed, injecting #UD\n");
+ page = nsvm_get_nvmcb_page(v, vmcbaddr);
+ if ( !page )
+ {
+ gdprintk(XENLOG_ERR,
+ "VMSAVE: mapping vmcb failed, injecting #UD\n");
ret = TRAP_invalid_op;
goto inject;
}
- svm_vmsave(nv->nv_vvmcx);
-
+ svm_vmsave_pa(page_to_maddr(page));
+ put_page(page);
__update_guest_eip(regs, inst_len);
return;