3f55414718
- Upstream or pending upstream patches from Jan 25587-fix-off-by-one-parsing-error.patch 25616-x86-MCi_CTL-default.patch 25617-vtd-qinval-addr.patch 25688-x86-nr_irqs_gsi.patch - bnc#773393 - VUL-0: CVE-2012-3433: xen: HVM guest destroy p2m teardown host DoS vulnerability CVE-2012-3433-xsa11.patch - bnc#773401 - VUL-1: CVE-2012-3432: xen: HVM guest user mode MMIO emulation DoS 25682-x86-inconsistent-io-state.patch - bnc#762484 - VUL-1: CVE-2012-2625: xen: pv bootloader doesn't check the size of the bzip2 or lzma compressed kernel, leading to denial of service 25589-pygrub-size-limits.patch - Make it build with latest TeXLive 2012 with new package layout OBS-URL: https://build.opensuse.org/package/show/Virtualization/xen?expand=0&rev=196
364 lines
16 KiB
Diff
364 lines
16 KiB
Diff
# HG changeset patch
|
|
# Parent 4a0a6a1cd56a8f3d242f323fb5161c2d1f52dccb
|
|
xenpaging: add need_populate and paged_no_mfn checks
|
|
|
|
There is currently a mix of p2mt checks for the various paging types.
|
|
Some mean the p2mt needs to be populated, others mean a gfn without mfn.
|
|
|
|
Add a new p2m_do_populate() helper which covers the p2m_ram_paged and
|
|
p2m_ram_paging_out types. If a gfn is not in these states anymore another
|
|
populate request for the pager is not needed. This avoids a call to
|
|
p2m_mem_paging_populate() which in turn reduces the pressure on the ring
|
|
buffer because no temporary slot needs to be claimed. As such, this helper is
|
|
an optimization.
|
|
|
|
Modify the existing p2m_is_paged() helper which now covers also
|
|
p2m_ram_paging_in_start in addition to the current p2m_ram_paged type. A gfn
|
|
in these two states is not backed by a mfn.
|
|
|
|
Signed-off-by: Olaf Hering <olaf@aepfle.de>
|
|
|
|
---
|
|
xen/arch/x86/hvm/emulate.c | 3 +
|
|
xen/arch/x86/hvm/hvm.c | 17 ++++++----
|
|
xen/arch/x86/mm.c | 63 ++++++++++++---------------------------
|
|
xen/arch/x86/mm/guest_walk.c | 3 +
|
|
xen/arch/x86/mm/hap/guest_walk.c | 6 ++-
|
|
xen/arch/x86/mm/hap/p2m-ept.c | 3 -
|
|
xen/arch/x86/mm/p2m.c | 4 +-
|
|
xen/common/grant_table.c | 3 +
|
|
xen/include/asm-x86/p2m.h | 9 ++++-
|
|
9 files changed, 51 insertions(+), 60 deletions(-)
|
|
|
|
Index: xen-4.1.3-testing/xen/arch/x86/hvm/emulate.c
|
|
===================================================================
|
|
--- xen-4.1.3-testing.orig/xen/arch/x86/hvm/emulate.c
|
|
+++ xen-4.1.3-testing/xen/arch/x86/hvm/emulate.c
|
|
@@ -66,7 +66,8 @@ static int hvmemul_do_io(
|
|
ram_mfn = gfn_to_mfn_unshare(p2m, ram_gfn, &p2mt, 0);
|
|
if ( p2m_is_paging(p2mt) )
|
|
{
|
|
- p2m_mem_paging_populate(p2m, ram_gfn);
|
|
+ if ( p2m_do_populate(p2mt) )
|
|
+ p2m_mem_paging_populate(p2m, ram_gfn);
|
|
return X86EMUL_RETRY;
|
|
}
|
|
if ( p2m_is_shared(p2mt) )
|
|
Index: xen-4.1.3-testing/xen/arch/x86/hvm/hvm.c
|
|
===================================================================
|
|
--- xen-4.1.3-testing.orig/xen/arch/x86/hvm/hvm.c
|
|
+++ xen-4.1.3-testing/xen/arch/x86/hvm/hvm.c
|
|
@@ -393,7 +393,8 @@ static int hvm_set_ioreq_page(
|
|
return -EINVAL;
|
|
if ( p2m_is_paging(p2mt) )
|
|
{
|
|
- p2m_mem_paging_populate(p2m, gmfn);
|
|
+ if ( p2m_do_populate(p2mt) )
|
|
+ p2m_mem_paging_populate(p2m, gmfn);
|
|
return -ENOENT;
|
|
}
|
|
if ( p2m_is_shared(p2mt) )
|
|
@@ -1207,7 +1208,7 @@ bool_t hvm_hap_nested_page_fault(unsigne
|
|
|
|
#ifdef __x86_64__
|
|
/* Check if the page has been paged out */
|
|
- if ( p2m_is_paged(p2mt) || (p2mt == p2m_ram_paging_out) )
|
|
+ if ( p2m_do_populate(p2mt) )
|
|
p2m_mem_paging_populate(p2m, gfn);
|
|
|
|
/* Mem sharing: unshare the page and try again */
|
|
@@ -1695,7 +1696,8 @@ static void *__hvm_map_guest_frame(unsig
|
|
return NULL;
|
|
if ( p2m_is_paging(p2mt) )
|
|
{
|
|
- p2m_mem_paging_populate(p2m, gfn);
|
|
+ if ( p2m_do_populate(p2mt) )
|
|
+ p2m_mem_paging_populate(p2m, gfn);
|
|
return NULL;
|
|
}
|
|
|
|
@@ -2153,7 +2155,8 @@ static enum hvm_copy_result __hvm_copy(
|
|
|
|
if ( p2m_is_paging(p2mt) )
|
|
{
|
|
- p2m_mem_paging_populate(p2m, gfn);
|
|
+ if ( p2m_do_populate(p2mt) )
|
|
+ p2m_mem_paging_populate(p2m, gfn);
|
|
return HVMCOPY_gfn_paged_out;
|
|
}
|
|
if ( p2m_is_shared(p2mt) )
|
|
@@ -2241,7 +2244,8 @@ static enum hvm_copy_result __hvm_clear(
|
|
|
|
if ( p2m_is_paging(p2mt) )
|
|
{
|
|
- p2m_mem_paging_populate(p2m, gfn);
|
|
+ if ( p2m_do_populate(p2mt) )
|
|
+ p2m_mem_paging_populate(p2m, gfn);
|
|
return HVMCOPY_gfn_paged_out;
|
|
}
|
|
if ( p2m_is_shared(p2mt) )
|
|
@@ -3630,7 +3634,8 @@ long do_hvm_op(unsigned long op, XEN_GUE
|
|
mfn_t mfn = gfn_to_mfn(p2m, pfn, &t);
|
|
if ( p2m_is_paging(t) )
|
|
{
|
|
- p2m_mem_paging_populate(p2m, pfn);
|
|
+ if ( p2m_do_populate(t) )
|
|
+ p2m_mem_paging_populate(p2m, pfn);
|
|
|
|
rc = -EINVAL;
|
|
goto param_fail3;
|
|
@@ -3727,7 +3732,8 @@ long do_hvm_op(unsigned long op, XEN_GUE
|
|
mfn = gfn_to_mfn_unshare(p2m, pfn, &t, 0);
|
|
if ( p2m_is_paging(t) )
|
|
{
|
|
- p2m_mem_paging_populate(p2m, pfn);
|
|
+ if ( p2m_do_populate(t) )
|
|
+ p2m_mem_paging_populate(p2m, pfn);
|
|
|
|
rc = -EINVAL;
|
|
goto param_fail4;
|
|
Index: xen-4.1.3-testing/xen/arch/x86/mm.c
|
|
===================================================================
|
|
--- xen-4.1.3-testing.orig/xen/arch/x86/mm.c
|
|
+++ xen-4.1.3-testing/xen/arch/x86/mm.c
|
|
@@ -3467,9 +3467,10 @@ int do_mmu_update(
|
|
if ( !p2m_is_valid(p2mt) )
|
|
mfn = INVALID_MFN;
|
|
|
|
- if ( p2m_is_paged(p2mt) )
|
|
+ if ( p2m_is_paging(p2mt) )
|
|
{
|
|
- p2m_mem_paging_populate(p2m_get_hostp2m(pg_owner), gmfn);
|
|
+ if ( p2m_do_populate(p2mt) )
|
|
+ p2m_mem_paging_populate(p2m_get_hostp2m(pg_owner), gmfn);
|
|
|
|
rc = -ENOENT;
|
|
break;
|
|
@@ -3494,24 +3495,18 @@ int do_mmu_update(
|
|
{
|
|
l1_pgentry_t l1e = l1e_from_intpte(req.val);
|
|
p2m_type_t l1e_p2mt;
|
|
- unsigned long l1emfn = mfn_x(
|
|
gfn_to_mfn(p2m_get_hostp2m(pg_owner),
|
|
- l1e_get_pfn(l1e), &l1e_p2mt));
|
|
+ l1e_get_pfn(l1e), &l1e_p2mt);
|
|
|
|
- if ( p2m_is_paged(l1e_p2mt) )
|
|
+#ifdef __x86_64__
|
|
+ if ( p2m_is_paging(l1e_p2mt) )
|
|
{
|
|
- p2m_mem_paging_populate(p2m_get_hostp2m(pg_owner),
|
|
+ if ( p2m_do_populate(l1e_p2mt) )
|
|
+ p2m_mem_paging_populate(p2m_get_hostp2m(pg_owner),
|
|
l1e_get_pfn(l1e));
|
|
rc = -ENOENT;
|
|
break;
|
|
}
|
|
- else if ( p2m_ram_paging_in_start == l1e_p2mt &&
|
|
- !mfn_valid(l1emfn) )
|
|
- {
|
|
- rc = -ENOENT;
|
|
- break;
|
|
- }
|
|
-#ifdef __x86_64__
|
|
/* XXX: Ugly: pull all the checks into a separate function.
|
|
* Don't want to do it now, not to interfere with mem_paging
|
|
* patches */
|
|
@@ -3538,22 +3533,16 @@ int do_mmu_update(
|
|
{
|
|
l2_pgentry_t l2e = l2e_from_intpte(req.val);
|
|
p2m_type_t l2e_p2mt;
|
|
- unsigned long l2emfn = mfn_x(
|
|
- gfn_to_mfn(p2m_get_hostp2m(pg_owner), l2e_get_pfn(l2e), &l2e_p2mt));
|
|
+ gfn_to_mfn(p2m_get_hostp2m(pg_owner), l2e_get_pfn(l2e), &l2e_p2mt);
|
|
|
|
- if ( p2m_is_paged(l2e_p2mt) )
|
|
+ if ( p2m_is_paging(l2e_p2mt) )
|
|
{
|
|
- p2m_mem_paging_populate(p2m_get_hostp2m(pg_owner),
|
|
+ if ( p2m_do_populate(l2e_p2mt) )
|
|
+ p2m_mem_paging_populate(p2m_get_hostp2m(pg_owner),
|
|
l2e_get_pfn(l2e));
|
|
rc = -ENOENT;
|
|
break;
|
|
}
|
|
- else if ( p2m_ram_paging_in_start == l2e_p2mt &&
|
|
- !mfn_valid(l2emfn) )
|
|
- {
|
|
- rc = -ENOENT;
|
|
- break;
|
|
- }
|
|
else if ( p2m_ram_shared == l2e_p2mt )
|
|
{
|
|
MEM_LOG("Unexpected attempt to map shared page.\n");
|
|
@@ -3569,22 +3558,16 @@ int do_mmu_update(
|
|
{
|
|
l3_pgentry_t l3e = l3e_from_intpte(req.val);
|
|
p2m_type_t l3e_p2mt;
|
|
- unsigned long l3emfn = mfn_x(
|
|
- gfn_to_mfn(p2m_get_hostp2m(pg_owner), l3e_get_pfn(l3e), &l3e_p2mt));
|
|
+ gfn_to_mfn(p2m_get_hostp2m(pg_owner), l3e_get_pfn(l3e), &l3e_p2mt);
|
|
|
|
- if ( p2m_is_paged(l3e_p2mt) )
|
|
+ if ( p2m_is_paging(l3e_p2mt) )
|
|
{
|
|
- p2m_mem_paging_populate(p2m_get_hostp2m(pg_owner),
|
|
+ if ( p2m_do_populate(l3e_p2mt) )
|
|
+ p2m_mem_paging_populate(p2m_get_hostp2m(pg_owner),
|
|
l3e_get_pfn(l3e));
|
|
rc = -ENOENT;
|
|
break;
|
|
}
|
|
- else if ( p2m_ram_paging_in_start == l3e_p2mt &&
|
|
- !mfn_valid(l3emfn) )
|
|
- {
|
|
- rc = -ENOENT;
|
|
- break;
|
|
- }
|
|
else if ( p2m_ram_shared == l3e_p2mt )
|
|
{
|
|
MEM_LOG("Unexpected attempt to map shared page.\n");
|
|
@@ -3600,23 +3583,17 @@ int do_mmu_update(
|
|
{
|
|
l4_pgentry_t l4e = l4e_from_intpte(req.val);
|
|
p2m_type_t l4e_p2mt;
|
|
- unsigned long l4emfn = mfn_x(
|
|
gfn_to_mfn(p2m_get_hostp2m(pg_owner),
|
|
- l4e_get_pfn(l4e), &l4e_p2mt));
|
|
+ l4e_get_pfn(l4e), &l4e_p2mt);
|
|
|
|
- if ( p2m_is_paged(l4e_p2mt) )
|
|
+ if ( p2m_is_paging(l4e_p2mt) )
|
|
{
|
|
- p2m_mem_paging_populate(p2m_get_hostp2m(pg_owner),
|
|
+ if ( p2m_do_populate(l4e_p2mt) )
|
|
+ p2m_mem_paging_populate(p2m_get_hostp2m(pg_owner),
|
|
l4e_get_pfn(l4e));
|
|
rc = -ENOENT;
|
|
break;
|
|
}
|
|
- else if ( p2m_ram_paging_in_start == l4e_p2mt &&
|
|
- !mfn_valid(l4emfn) )
|
|
- {
|
|
- rc = -ENOENT;
|
|
- break;
|
|
- }
|
|
else if ( p2m_ram_shared == l4e_p2mt )
|
|
{
|
|
MEM_LOG("Unexpected attempt to map shared page.\n");
|
|
Index: xen-4.1.3-testing/xen/arch/x86/mm/guest_walk.c
|
|
===================================================================
|
|
--- xen-4.1.3-testing.orig/xen/arch/x86/mm/guest_walk.c
|
|
+++ xen-4.1.3-testing/xen/arch/x86/mm/guest_walk.c
|
|
@@ -96,7 +96,8 @@ static inline void *map_domain_gfn(struc
|
|
*mfn = gfn_to_mfn_unshare(p2m, gfn_x(gfn), p2mt, 0);
|
|
if ( p2m_is_paging(*p2mt) )
|
|
{
|
|
- p2m_mem_paging_populate(p2m, gfn_x(gfn));
|
|
+ if ( p2m_do_populate(*p2mt) )
|
|
+ p2m_mem_paging_populate(p2m, gfn_x(gfn));
|
|
|
|
*rc = _PAGE_PAGED;
|
|
return NULL;
|
|
Index: xen-4.1.3-testing/xen/arch/x86/mm/hap/guest_walk.c
|
|
===================================================================
|
|
--- xen-4.1.3-testing.orig/xen/arch/x86/mm/hap/guest_walk.c
|
|
+++ xen-4.1.3-testing/xen/arch/x86/mm/hap/guest_walk.c
|
|
@@ -50,7 +50,8 @@ unsigned long hap_gva_to_gfn(GUEST_PAGIN
|
|
top_mfn = gfn_to_mfn_unshare(p2m, cr3 >> PAGE_SHIFT, &p2mt, 0);
|
|
if ( p2m_is_paging(p2mt) )
|
|
{
|
|
- p2m_mem_paging_populate(p2m, cr3 >> PAGE_SHIFT);
|
|
+ if ( p2m_do_populate(p2mt) )
|
|
+ p2m_mem_paging_populate(p2m, cr3 >> PAGE_SHIFT);
|
|
|
|
pfec[0] = PFEC_page_paged;
|
|
return INVALID_GFN;
|
|
@@ -82,7 +83,8 @@ unsigned long hap_gva_to_gfn(GUEST_PAGIN
|
|
gfn_to_mfn_unshare(p2m, gfn_x(gfn), &p2mt, 0);
|
|
if ( p2m_is_paging(p2mt) )
|
|
{
|
|
- p2m_mem_paging_populate(p2m, gfn_x(gfn));
|
|
+ if ( p2m_do_populate(p2mt) )
|
|
+ p2m_mem_paging_populate(p2m, gfn_x(gfn));
|
|
|
|
pfec[0] = PFEC_page_paged;
|
|
return INVALID_GFN;
|
|
Index: xen-4.1.3-testing/xen/arch/x86/mm/hap/p2m-ept.c
|
|
===================================================================
|
|
--- xen-4.1.3-testing.orig/xen/arch/x86/mm/hap/p2m-ept.c
|
|
+++ xen-4.1.3-testing/xen/arch/x86/mm/hap/p2m-ept.c
|
|
@@ -377,8 +377,7 @@ ept_set_entry(struct p2m_domain *p2m, un
|
|
* the intermediate tables will be freed below after the ept flush */
|
|
old_entry = *ept_entry;
|
|
|
|
- if ( mfn_valid(mfn_x(mfn)) || direct_mmio || p2m_is_paged(p2mt) ||
|
|
- (p2mt == p2m_ram_paging_in_start) )
|
|
+ if ( mfn_valid(mfn_x(mfn)) || direct_mmio || p2m_is_paged(p2mt) )
|
|
{
|
|
/* Construct the new entry, and then write it once */
|
|
new_entry.emt = epte_get_entry_emt(p2m->domain, gfn, mfn, &ipat,
|
|
Index: xen-4.1.3-testing/xen/arch/x86/mm/p2m.c
|
|
===================================================================
|
|
--- xen-4.1.3-testing.orig/xen/arch/x86/mm/p2m.c
|
|
+++ xen-4.1.3-testing/xen/arch/x86/mm/p2m.c
|
|
@@ -3051,7 +3051,7 @@ void p2m_mem_paging_populate(struct p2m_
|
|
p2m_lock(p2m);
|
|
mfn = p2m->get_entry(p2m, gfn, &p2mt, &a, p2m_query);
|
|
/* Allow only nominated or evicted pages to enter page-in path */
|
|
- if ( p2mt == p2m_ram_paging_out || p2mt == p2m_ram_paged )
|
|
+ if ( p2m_do_populate(p2mt) )
|
|
{
|
|
/* Evict will fail now, tag this request for pager */
|
|
if ( p2mt == p2m_ram_paging_out )
|
|
@@ -3069,7 +3069,7 @@ void p2m_mem_paging_populate(struct p2m_
|
|
req.flags |= MEM_EVENT_FLAG_VCPU_PAUSED;
|
|
}
|
|
/* No need to inform pager if the gfn is not in the page-out path */
|
|
- else if ( p2mt != p2m_ram_paging_out && p2mt != p2m_ram_paged )
|
|
+ else if ( !p2m_do_populate(p2mt) )
|
|
{
|
|
/* gfn is already on its way back and vcpu is not paused */
|
|
mem_event_put_req_producers(&d->mem_event->paging);
|
|
Index: xen-4.1.3-testing/xen/common/grant_table.c
|
|
===================================================================
|
|
--- xen-4.1.3-testing.orig/xen/common/grant_table.c
|
|
+++ xen-4.1.3-testing/xen/common/grant_table.c
|
|
@@ -158,7 +158,8 @@ static int __get_paged_frame(unsigned lo
|
|
*frame = mfn_x(mfn);
|
|
if ( p2m_is_paging(p2mt) )
|
|
{
|
|
- p2m_mem_paging_populate(p2m, gfn);
|
|
+ if ( p2m_do_populate(p2mt) )
|
|
+ p2m_mem_paging_populate(p2m, gfn);
|
|
rc = GNTST_eagain;
|
|
}
|
|
} else {
|
|
Index: xen-4.1.3-testing/xen/include/asm-x86/p2m.h
|
|
===================================================================
|
|
--- xen-4.1.3-testing.orig/xen/include/asm-x86/p2m.h
|
|
+++ xen-4.1.3-testing/xen/include/asm-x86/p2m.h
|
|
@@ -159,7 +159,11 @@ typedef enum {
|
|
| p2m_to_mask(p2m_ram_paging_in_start) \
|
|
| p2m_to_mask(p2m_ram_paging_in))
|
|
|
|
-#define P2M_PAGED_TYPES (p2m_to_mask(p2m_ram_paged))
|
|
+#define P2M_POPULATE_TYPES (p2m_to_mask(p2m_ram_paged) \
|
|
+ | p2m_to_mask(p2m_ram_paging_out) )
|
|
+
|
|
+#define P2M_PAGED_NO_MFN_TYPES (p2m_to_mask(p2m_ram_paged) \
|
|
+ | p2m_to_mask(p2m_ram_paging_in_start) )
|
|
|
|
/* Shared types */
|
|
/* XXX: Sharable types could include p2m_ram_ro too, but we would need to
|
|
@@ -181,7 +185,8 @@ typedef enum {
|
|
#define p2m_has_emt(_t) (p2m_to_mask(_t) & (P2M_RAM_TYPES | p2m_to_mask(p2m_mmio_direct)))
|
|
#define p2m_is_pageable(_t) (p2m_to_mask(_t) & P2M_PAGEABLE_TYPES)
|
|
#define p2m_is_paging(_t) (p2m_to_mask(_t) & P2M_PAGING_TYPES)
|
|
-#define p2m_is_paged(_t) (p2m_to_mask(_t) & P2M_PAGED_TYPES)
|
|
+#define p2m_is_paged(_t) (p2m_to_mask(_t) & P2M_PAGED_NO_MFN_TYPES)
|
|
+#define p2m_do_populate(_t) (p2m_to_mask(_t) & P2M_POPULATE_TYPES)
|
|
#define p2m_is_sharable(_t) (p2m_to_mask(_t) & P2M_SHARABLE_TYPES)
|
|
#define p2m_is_shared(_t) (p2m_to_mask(_t) & P2M_SHARED_TYPES)
|
|
#define p2m_is_broken(_t) (p2m_to_mask(_t) & P2M_BROKEN_TYPES)
|