Brian May <b...@debian.org> writes: > It appears that we need an extra patch to get the fix for xsa97 working > properly. See the linked Ubuntu bug report. > > https://bugs.launchpad.net/ubuntu/+source/xen/+bug/1515145 > > Just wondering if you included this in version 4.1.6.1-1+deb7u2 by any > chance?
Looks like it wasn't included. So guessing this will have exactly the same problem too. I attempted to apply to patch to 4.1.6.1-1+deb7u1, but unfortunately it fails to build. gcc -O2 -fomit-frame-pointer -m64 -fno-strict-aliasing -std=gnu99 -Wall -Wstrict-prototypes -Wno-unused-value -Wdeclaration-after-statement -Wno-unused-but-set-variable -Wno-unused-local-typedefs -DNDEBUG -nostdinc -fno-builtin -fno-common -Wredundant-decls -iwithprefix include -Werror -Wno-pointer-arith -pipe -I/<<PKGBUILDDIR>>/debian/build/build-hypervisor_i386_amd64/xen/include -I/<<PKGBUILDDIR>>/debian/build/build-hypervisor_i386_amd64/xen/include/asm-x86/mach-generic -I/<<PKGBUILDDIR>>/debian/build/build-hypervisor_i386_amd64/xen/include/asm-x86/mach-default -msoft-float -fno-stack-protector -fno-exceptions -mno-red-zone -fpic -fno-asynchronous-unwind-tables -DGCC_HAS_VISIBILITY_ATTRIBUTE -g -D__XEN__ -MMD -MF .p2m.o.d -c p2m.c -o p2m.o p2m.c: In function 'p2m_set_mem_access': p2m.c:3198:9: error: passing argument 1 of '_gfn_to_mfn_type' from incompatible pointer type [-Werror] In file included from p2m.c:30:0: /<<PKGBUILDDIR>>/debian/build/build-hypervisor_i386_amd64/xen/include/asm/p2m.h:365:21: note: expected 'struct p2m_domain *' but argument is of type 'struct domain *' cc1: all warnings being treated as errors If I apply the patch to 4.1.6.1-1+deb7u2 it still has the same build error. -- Brian May <b...@debian.org>
>From 1b4dab6f51957169ddae6bd7cdb44c40f0b48c00 Mon Sep 17 00:00:00 2001 Message-Id: <1b4dab6f51957169ddae6bd7cdb44c40f0b48c00.1459495982.git.h...@univention.de> From: Tim Deegan <tim.dee...@citrix.com> Date: Thu, 2 Jun 2011 13:16:52 +0100 Subject: [PATCH 1/2] x86/mm/p2m: Move p2m code in HVMOP_[gs]et_mem_access into p2m.c Organization: Univention GmbH, Bremen, Germany To: xen-de...@lists.xen.org It uses p2m internals like the p2m lock and function pointers so belongs behind the p2m interface. Signed-off-by: Tim Deegan <tim.dee...@citrix.com> [Backported to Xen 4.1.x] Includes f488040222f34df97deb2470f14cef7fb9599810 to fix i386 build Signed-off-by: Philipp Hahn <h...@univention.de> --- xen/arch/x86/hvm/hvm.c | 103 +++++----------------------------------------- xen/arch/x86/mm/p2m.c | 95 ++++++++++++++++++++++++++++++++++++++++++ xen/include/asm-x86/p2m.h | 18 +++++++++ 3 files changed, 116 insertions(+), 93 deletions(-) diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c index 7d3a36c..a2266fc 100644 --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -3711,21 +3711,6 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg) { struct xen_hvm_set_mem_access a; struct domain *d; - struct p2m_domain *p2m; - unsigned long pfn; - - p2m_access_t memaccess[] = { - p2m_access_n, - p2m_access_r, - p2m_access_w, - p2m_access_rw, - p2m_access_x, - p2m_access_rx, - p2m_access_wx, - p2m_access_rwx, - p2m_access_rx2rw, - 0, /* HVMMEM_access_default -- will get set below */ - }; if ( copy_from_guest(&a, arg, 1) ) return -EFAULT; @@ -3735,19 +3720,8 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg) return rc; rc = -EINVAL; - if ( !is_hvm_domain(d) || a.hvmmem_access >= ARRAY_SIZE(memaccess) ) - goto param_fail5; - - p2m = p2m_get_hostp2m(d); - memaccess[HVMMEM_access_default] = p2m->default_access; - - /* If request to set default access */ - if ( a.first_pfn == ~0ull ) - { - rc = 0; - p2m->default_access = memaccess[a.hvmmem_access]; + if ( !is_hvm_domain(d) ) goto param_fail5; - } rc = -EINVAL; if ( (a.first_pfn > domain_get_maximum_gpfn(d)) || @@ -3755,33 +3729,7 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg) ((a.first_pfn + a.nr - 1) > domain_get_maximum_gpfn(d)) ) goto param_fail5; - for ( pfn = a.first_pfn; a.nr; ++pfn ) - { - p2m_type_t t; - mfn_t mfn; - int success; - - mfn = gfn_to_mfn_unshare(p2m, pfn, &t, 0); - - p2m_lock(p2m); - success = p2m->set_entry(p2m, pfn, mfn, 0, t, memaccess[a.hvmmem_access]); - p2m_unlock(p2m); - if ( !success ) - goto param_fail5; - - /* Check for continuation if it's not the last interation. */ - if ( --a.nr && hypercall_preempt_check() ) - { - a.first_pfn = pfn + 1; - if ( copy_to_guest(arg, &a, 1) ) - rc = -EFAULT; - else - rc = -EAGAIN; - goto param_fail5; - } - } - - rc = 0; + rc = p2m_set_mem_access(d, a.first_pfn, a.nr, a.hvmmem_access); param_fail5: rcu_unlock_domain(d); @@ -3792,23 +3740,7 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg) { struct xen_hvm_get_mem_access a; struct domain *d; - struct p2m_domain *p2m; - p2m_type_t t; - p2m_access_t ac; - mfn_t mfn; - - /* Interface access to internal p2m accesses */ - hvmmem_access_t memaccess[] = { - HVMMEM_access_n, - HVMMEM_access_r, - HVMMEM_access_w, - HVMMEM_access_rw, - HVMMEM_access_x, - HVMMEM_access_rx, - HVMMEM_access_wx, - HVMMEM_access_rwx, - HVMMEM_access_rx2rw - }; + hvmmem_access_t access; if ( copy_from_guest(&a, arg, 1) ) return -EFAULT; @@ -3821,30 +3753,15 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg) if ( !is_hvm_domain(d) ) goto param_fail6; - p2m = p2m_get_hostp2m(d); - - if ( a.pfn == ~0ull ) - { - a.hvmmem_access = memaccess[p2m->default_access]; - } - else { - rc = -EINVAL; - if ( (a.pfn > domain_get_maximum_gpfn(d)) ) - goto param_fail6; - - rc = -ESRCH; - mfn = p2m->get_entry(p2m, a.pfn, &t, &ac, p2m_query); + rc = -EINVAL; + if ( (a.pfn > domain_get_maximum_gpfn(d)) && a.pfn != ~0ull ) + goto param_fail6; - if ( mfn_x(mfn) == INVALID_MFN ) - goto param_fail6; - - rc = -ERANGE; - if ( ac >= ARRAY_SIZE(memaccess) ) - goto param_fail6; - - a.hvmmem_access = memaccess[ac]; - } + rc = p2m_get_mem_access(d, a.pfn, &access); + if ( rc != 0 ) + goto param_fail6; + a.hvmmem_access = access; rc = copy_to_guest(arg, &a, 1) ? -EFAULT : 0; param_fail6: diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c index 09f5b43..14ef0fe 100644 --- a/xen/arch/x86/mm/p2m.c +++ b/xen/arch/x86/mm/p2m.c @@ -3150,6 +3150,101 @@ void p2m_mem_access_resume(struct p2m_domain *p2m) * was available */ mem_event_unpause_vcpus(d); } + + +/* Set access type for a region of pfns. + * If start_pfn == -1ul, sets the default access type */ +int p2m_set_mem_access(struct domain *d, unsigned long start_pfn, + uint32_t nr, hvmmem_access_t access) +{ + struct p2m_domain *p2m = p2m_get_hostp2m(d); + unsigned long pfn; + p2m_access_t a; + p2m_type_t t; + mfn_t mfn; + int rc = 0; + + /* N.B. _not_ static: initializer depends on p2m->default_access */ + p2m_access_t memaccess[] = { + p2m_access_n, + p2m_access_r, + p2m_access_w, + p2m_access_rw, + p2m_access_x, + p2m_access_rx, + p2m_access_wx, + p2m_access_rwx, + p2m_access_rx2rw, + p2m->default_access, + }; + + if ( access >= HVMMEM_access_default || access < 0 ) + return -EINVAL; + + a = memaccess[access]; + + /* If request to set default access */ + if ( start_pfn == ~0ull ) + { + p2m->default_access = a; + return 0; + } + + p2m_lock(p2m); + for ( pfn = start_pfn; pfn < start_pfn + nr; pfn++ ) + { + mfn = gfn_to_mfn_query(d, pfn, &t); + if ( p2m->set_entry(p2m, pfn, mfn, 0, t, a) == 0 ) + { + rc = -ENOMEM; + break; + } + } + p2m_unlock(p2m); + return rc; +} + +/* Get access type for a pfn + * If pfn == -1ul, gets the default access type */ +int p2m_get_mem_access(struct domain *d, unsigned long pfn, + hvmmem_access_t *access) +{ + struct p2m_domain *p2m = p2m_get_hostp2m(d); + p2m_type_t t; + p2m_access_t a; + mfn_t mfn; + + static const hvmmem_access_t memaccess[] = { + HVMMEM_access_n, + HVMMEM_access_r, + HVMMEM_access_w, + HVMMEM_access_rw, + HVMMEM_access_x, + HVMMEM_access_rx, + HVMMEM_access_wx, + HVMMEM_access_rwx, + HVMMEM_access_rx2rw + }; + + /* If request to get default access */ + if ( pfn == ~0ull ) + { + *access = memaccess[p2m->default_access]; + return 0; + } + + mfn = p2m->get_entry(p2m, pfn, &t, &a, p2m_query); + if ( mfn_x(mfn) == INVALID_MFN ) + return -ESRCH; + + if ( a >= ARRAY_SIZE(memaccess) || a < 0 ) + return -ERANGE; + + *access = memaccess[a]; + return 0; +} + + #endif /* __x86_64__ */ /* diff --git a/xen/include/asm-x86/p2m.h b/xen/include/asm-x86/p2m.h index aa8bbfc..5672e7a 100644 --- a/xen/include/asm-x86/p2m.h +++ b/xen/include/asm-x86/p2m.h @@ -564,11 +564,29 @@ void p2m_mem_access_check(paddr_t gpa, bool_t gla_valid, unsigned long gla, bool_t access_r, bool_t access_w, bool_t access_x); /* Resumes the running of the VCPU, restarting the last instruction */ void p2m_mem_access_resume(struct p2m_domain *p2m); + +/* Set access type for a region of pfns. + * If start_pfn == -1ul, sets the default access type */ +int p2m_set_mem_access(struct domain *d, unsigned long start_pfn, + uint32_t nr, hvmmem_access_t access); + +/* Get access type for a pfn + * If pfn == -1ul, gets the default access type */ +int p2m_get_mem_access(struct domain *d, unsigned long pfn, + hvmmem_access_t *access); + #else static inline void p2m_mem_access_check(paddr_t gpa, bool_t gla_valid, unsigned long gla, bool_t access_r, bool_t access_w, bool_t access_x) { } +static inline int p2m_set_mem_access(struct domain *d, + unsigned long start_pfn, + uint32_t nr, hvmmem_access_t access) +{ return -EINVAL; } +static inline int p2m_get_mem_access(struct domain *d, unsigned long pfn, + hvmmem_access_t *access) +{ return -EINVAL; } #endif struct page_info *p2m_alloc_ptp(struct p2m_domain *p2m, unsigned long type); -- 2.1.4