aboutsummaryrefslogtreecommitdiffstats
path: root/xen/arch/x86/traps.c
diff options
context:
space:
mode:
authorOlaf Hering <olaf@aepfle.de>2013-05-07 16:41:24 +0200
committerJan Beulich <jbeulich@suse.com>2013-05-07 16:41:24 +0200
commit013e34f5a61725012467f17650597d351fc0ca99 (patch)
tree594b4e26937725656d6b6ff45b307bb770eaaae1 /xen/arch/x86/traps.c
parentda3ef0f81250b5a680001610028ff35ee94741bc (diff)
downloadxen-013e34f5a61725012467f17650597d351fc0ca99.tar.gz
xen-013e34f5a61725012467f17650597d351fc0ca99.tar.bz2
xen-013e34f5a61725012467f17650597d351fc0ca99.zip
x86: handle paged gfn in wrmsr_hypervisor_regs
If xenpaging is started very early for a guest the gfn for the hypercall page may be paged-out already. This leads to a guest crash: ... (XEN) HVM10: Allocated Xen hypercall page at 169ff000 (XEN) traps.c:654:d10 Bad GMFN 169ff (MFN 3e900000000) to MSR 40000000 (XEN) HVM10: Detected Xen v4.3 (XEN) io.c:201:d10 MMIO emulation failed @ 0008:c2c2c2c2: 18 7c 55 6d 03 83 ff ff 10 7c (XEN) hvm.c:1253:d10 Triple fault on VCPU0 - invoking HVM shutdown action 1. (XEN) HVM11: HVM Loader ... Update return codes of wrmsr_hypervisor_regs, update callers to deal with the new return codes: 0: not handled 1: handled -EAGAIN: retry Currently wrmsr_hypervisor_regs will not return the following error, it will be added in a separate patch: -EINVAL: error during handling Also update the gdprintk to handle a page value of NULL to avoid printing a bogus MFN value. Update also computing of MSR value in gdprintk, the idx was always zero. Signed-off-by: Olaf Hering <olaf@aepfle.de> Acked-by: Keir Fraser <keir@xen.org>
Diffstat (limited to 'xen/arch/x86/traps.c')
-rw-r--r--xen/arch/x86/traps.c14
1 files changed, 11 insertions, 3 deletions
diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c
index fbbe31d6fc..f630f8318d 100644
--- a/xen/arch/x86/traps.c
+++ b/xen/arch/x86/traps.c
@@ -634,6 +634,7 @@ int wrmsr_hypervisor_regs(uint32_t idx, uint64_t val)
unsigned long gmfn = val >> 12;
unsigned int idx = val & 0xfff;
struct page_info *page;
+ p2m_type_t t;
if ( idx > 0 )
{
@@ -643,15 +644,22 @@ int wrmsr_hypervisor_regs(uint32_t idx, uint64_t val)
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;
}
@@ -2490,7 +2498,7 @@ static int emulate_privileged_op(struct cpu_user_regs *regs)
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);