debuggers.hg
changeset 22716:76e07538870e
mem_access: HVMOPs for setting mem access
* Creates HVMOPs for setting and getting memory access. The hypercalls
can set individual pages or the default access for new/refreshed
pages.
* Added functions to libxc to access these hypercalls.
Signed-off-by: Joe Epstein <jepstein98@gmail.com>
Reviewed-by: Ian Campbell <ian.campbell@citrix.com>
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
Acked-by: Keir Fraser <keir@xen.org>
Acked-by: Tim Deegan <Tim.Deegan@citrix.com>
* Creates HVMOPs for setting and getting memory access. The hypercalls
can set individual pages or the default access for new/refreshed
pages.
* Added functions to libxc to access these hypercalls.
Signed-off-by: Joe Epstein <jepstein98@gmail.com>
Reviewed-by: Ian Campbell <ian.campbell@citrix.com>
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
Acked-by: Keir Fraser <keir@xen.org>
Acked-by: Tim Deegan <Tim.Deegan@citrix.com>
author | Joe Epstein <jepstein98@gmail.com> |
---|---|
date | Fri Jan 07 11:54:45 2011 +0000 (2011-01-07) |
parents | 8af5bab1bf43 |
children | d9dca2bfe6b2 |
files | tools/libxc/Makefile tools/libxc/xc_domain.c tools/libxc/xc_mem_access.c tools/libxc/xc_misc.c tools/libxc/xenctrl.h xen/arch/ia64/vmx/vmx_hypercall.c xen/arch/x86/hvm/hvm.c xen/arch/x86/mm/mem_sharing.c xen/arch/x86/mm/p2m.c xen/include/public/hvm/hvm_op.h |
line diff
1.1 --- a/tools/libxc/Makefile Fri Jan 07 11:54:42 2011 +0000 1.2 +++ b/tools/libxc/Makefile Fri Jan 07 11:54:45 2011 +0000 1.3 @@ -28,6 +28,7 @@ CTRL_SRCS-y += xc_resume.c 1.4 CTRL_SRCS-y += xc_tmem.c 1.5 CTRL_SRCS-y += xc_mem_event.c 1.6 CTRL_SRCS-y += xc_mem_paging.c 1.7 +CTRL_SRCS-y += xc_mem_access.c 1.8 CTRL_SRCS-y += xc_memshr.c 1.9 CTRL_SRCS-y += xc_hcall_buf.c 1.10 CTRL_SRCS-y += xc_foreign_memory.c
2.1 --- a/tools/libxc/xc_domain.c Fri Jan 07 11:54:42 2011 +0000 2.2 +++ b/tools/libxc/xc_domain.c Fri Jan 07 11:54:45 2011 +0000 2.3 @@ -1442,6 +1442,17 @@ int xc_domain_debug_control(xc_interface 2.4 return do_domctl(xc, &domctl); 2.5 } 2.6 2.7 +int xc_domain_set_access_required(xc_interface *xch, 2.8 + uint32_t domid, 2.9 + unsigned int required) 2.10 +{ 2.11 + DECLARE_DOMCTL; 2.12 + 2.13 + domctl.cmd = XEN_DOMCTL_set_access_required; 2.14 + domctl.domain = domid; 2.15 + domctl.u.access_required.access_required = required; 2.16 + return do_domctl(xch, &domctl); 2.17 +} 2.18 2.19 /* 2.20 * Local variables:
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/tools/libxc/xc_mem_access.c Fri Jan 07 11:54:45 2011 +0000 3.3 @@ -0,0 +1,42 @@ 3.4 +/****************************************************************************** 3.5 + * 3.6 + * tools/libxc/xc_mem_access.c 3.7 + * 3.8 + * Interface to low-level memory access mode functionality 3.9 + * 3.10 + * Copyright (c) 2011 Virtuata, Inc. 3.11 + * 3.12 + * This library is free software; you can redistribute it and/or 3.13 + * modify it under the terms of the GNU Lesser General Public 3.14 + * License as published by the Free Software Foundation; either 3.15 + * version 2.1 of the License, or (at your option) any later version. 3.16 + * 3.17 + * This library is distributed in the hope that it will be useful, 3.18 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 3.19 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 3.20 + * Lesser General Public License for more details. 3.21 + * 3.22 + * You should have received a copy of the GNU Lesser General Public 3.23 + * License along with this library; if not, write to the Free Software 3.24 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 3.25 + */ 3.26 + 3.27 +#include "xc_private.h" 3.28 + 3.29 + 3.30 +int xc_mem_access_resume(xc_interface *xch, domid_t domain_id, unsigned long gfn) 3.31 +{ 3.32 + return xc_mem_event_control(xch, domain_id, 3.33 + XEN_DOMCTL_MEM_EVENT_OP_ACCESS_RESUME, 3.34 + XEN_DOMCTL_MEM_EVENT_OP_ACCESS, NULL, NULL, 3.35 + gfn); 3.36 +} 3.37 + 3.38 +/* 3.39 + * Local variables: 3.40 + * mode: C 3.41 + * c-set-style: "BSD" 3.42 + * c-basic-offset: 4 3.43 + * indent-tabs-mode: nil 3.44 + * End: 3.45 + */
4.1 --- a/tools/libxc/xc_misc.c Fri Jan 07 11:54:42 2011 +0000 4.2 +++ b/tools/libxc/xc_misc.c Fri Jan 07 11:54:45 2011 +0000 4.3 @@ -511,6 +511,66 @@ int xc_hvm_set_mem_type( 4.4 return rc; 4.5 } 4.6 4.7 +int xc_hvm_set_mem_access( 4.8 + xc_interface *xch, domid_t dom, hvmmem_access_t mem_access, uint64_t first_pfn, uint64_t nr) 4.9 +{ 4.10 + DECLARE_HYPERCALL; 4.11 + DECLARE_HYPERCALL_BUFFER(struct xen_hvm_set_mem_access, arg); 4.12 + int rc; 4.13 + 4.14 + arg = xc_hypercall_buffer_alloc(xch, arg, sizeof(*arg)); 4.15 + if ( arg == NULL ) 4.16 + { 4.17 + PERROR("Could not allocate memory for xc_hvm_set_mem_access hypercall"); 4.18 + return -1; 4.19 + } 4.20 + 4.21 + arg->domid = dom; 4.22 + arg->hvmmem_access = mem_access; 4.23 + arg->first_pfn = first_pfn; 4.24 + arg->nr = nr; 4.25 + 4.26 + hypercall.op = __HYPERVISOR_hvm_op; 4.27 + hypercall.arg[0] = HVMOP_set_mem_access; 4.28 + hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg); 4.29 + 4.30 + rc = do_xen_hypercall(xch, &hypercall); 4.31 + 4.32 + xc_hypercall_buffer_free(xch, arg); 4.33 + 4.34 + return rc; 4.35 +} 4.36 + 4.37 +int xc_hvm_get_mem_access( 4.38 + xc_interface *xch, domid_t dom, uint64_t pfn, hvmmem_access_t* mem_access) 4.39 +{ 4.40 + DECLARE_HYPERCALL; 4.41 + DECLARE_HYPERCALL_BUFFER(struct xen_hvm_get_mem_access, arg); 4.42 + int rc; 4.43 + 4.44 + arg = xc_hypercall_buffer_alloc(xch, arg, sizeof(*arg)); 4.45 + if ( arg == NULL ) 4.46 + { 4.47 + PERROR("Could not allocate memory for xc_hvm_get_mem_access hypercall"); 4.48 + return -1; 4.49 + } 4.50 + 4.51 + arg->domid = dom; 4.52 + arg->pfn = pfn; 4.53 + 4.54 + hypercall.op = __HYPERVISOR_hvm_op; 4.55 + hypercall.arg[0] = HVMOP_get_mem_access; 4.56 + hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg); 4.57 + 4.58 + rc = do_xen_hypercall(xch, &hypercall); 4.59 + 4.60 + if ( !rc ) 4.61 + *mem_access = arg->hvmmem_access; 4.62 + 4.63 + xc_hypercall_buffer_free(xch, arg); 4.64 + 4.65 + return rc; 4.66 +} 4.67 4.68 /* 4.69 * Local variables:
5.1 --- a/tools/libxc/xenctrl.h Fri Jan 07 11:54:42 2011 +0000 5.2 +++ b/tools/libxc/xenctrl.h Fri Jan 07 11:54:45 2011 +0000 5.3 @@ -701,6 +701,19 @@ int xc_domain_setdebugging(xc_interface 5.4 uint32_t domid, 5.5 unsigned int enable); 5.6 5.7 +/** 5.8 + * This function sets or clears the requirement that an access memory 5.9 + * event listener is required on the domain. 5.10 + * 5.11 + * @parm xch a handle to an open hypervisor interface 5.12 + * @parm domid the domain id to send trigger 5.13 + * @parm enable true to require a listener 5.14 + * return 0 on success, -1 on failure 5.15 + */ 5.16 +int xc_domain_set_access_required(xc_interface *xch, 5.17 + uint32_t domid, 5.18 + unsigned int required); 5.19 + 5.20 /* 5.21 * CPUPOOL MANAGEMENT FUNCTIONS 5.22 */ 5.23 @@ -1398,6 +1411,19 @@ int xc_hvm_modified_memory( 5.24 int xc_hvm_set_mem_type( 5.25 xc_interface *xch, domid_t dom, hvmmem_type_t memtype, uint64_t first_pfn, uint64_t nr); 5.26 5.27 +/* 5.28 + * Set a range of memory to a specific access. 5.29 + * Allowed types are HVMMEM_access_default, HVMMEM_access_n, any combination of 5.30 + * HVM_access_ + (rwx), and HVM_access_rx2rw 5.31 + */ 5.32 +int xc_hvm_set_mem_access( 5.33 + xc_interface *xch, domid_t dom, hvmmem_access_t memaccess, uint64_t first_pfn, uint64_t nr); 5.34 + 5.35 +/* 5.36 + * Gets the mem access for the given page (returned in memacess on success) 5.37 + */ 5.38 +int xc_hvm_get_mem_access( 5.39 + xc_interface *xch, domid_t dom, uint64_t pfn, hvmmem_access_t* memaccess); 5.40 5.41 /* 5.42 * LOGGING AND ERROR REPORTING 5.43 @@ -1704,6 +1730,8 @@ int xc_mem_paging_evict(xc_interface *xc 5.44 int xc_mem_paging_prep(xc_interface *xch, domid_t domain_id, unsigned long gfn); 5.45 int xc_mem_paging_resume(xc_interface *xch, domid_t domain_id, 5.46 unsigned long gfn); 5.47 +int xc_mem_access_resume(xc_interface *xch, domid_t domain_id, 5.48 + unsigned long gfn); 5.49 5.50 /** 5.51 * memshr operations
6.1 --- a/xen/arch/ia64/vmx/vmx_hypercall.c Fri Jan 07 11:54:42 2011 +0000 6.2 +++ b/xen/arch/ia64/vmx/vmx_hypercall.c Fri Jan 07 11:54:45 2011 +0000 6.3 @@ -218,6 +218,9 @@ do_hvm_op(unsigned long op, XEN_GUEST_HA 6.4 } 6.5 6.6 case HVMOP_set_mem_type: 6.7 + case HVMOP_set_mem_access: 6.8 + case HVMOP_get_mem_access: 6.9 + 6.10 rc = -ENOSYS; 6.11 break; 6.12
7.1 --- a/xen/arch/x86/hvm/hvm.c Fri Jan 07 11:54:42 2011 +0000 7.2 +++ b/xen/arch/x86/hvm/hvm.c Fri Jan 07 11:54:45 2011 +0000 7.3 @@ -3464,6 +3464,149 @@ long do_hvm_op(unsigned long op, XEN_GUE 7.4 break; 7.5 } 7.6 7.7 + case HVMOP_set_mem_access: 7.8 + { 7.9 + struct xen_hvm_set_mem_access a; 7.10 + struct domain *d; 7.11 + struct p2m_domain *p2m; 7.12 + unsigned long pfn; 7.13 + 7.14 + p2m_access_t memaccess[] = { 7.15 + p2m_access_n, 7.16 + p2m_access_r, 7.17 + p2m_access_w, 7.18 + p2m_access_rw, 7.19 + p2m_access_x, 7.20 + p2m_access_rx, 7.21 + p2m_access_wx, 7.22 + p2m_access_rwx, 7.23 + p2m_access_rx2rw, 7.24 + 0, /* HVMMEM_access_default -- will get set below */ 7.25 + }; 7.26 + 7.27 + if ( copy_from_guest(&a, arg, 1) ) 7.28 + return -EFAULT; 7.29 + 7.30 + if ( current->domain->domain_id == a.domid ) 7.31 + return -EPERM; 7.32 + 7.33 + rc = rcu_lock_target_domain_by_id(a.domid, &d); 7.34 + if ( rc != 0 ) 7.35 + return rc; 7.36 + 7.37 + rc = -EINVAL; 7.38 + if ( !is_hvm_domain(d) ) 7.39 + goto param_fail5; 7.40 + 7.41 + p2m = p2m_get_hostp2m(d); 7.42 + memaccess[HVMMEM_access_default] = p2m->default_access; 7.43 + 7.44 + /* If request to set default access */ 7.45 + if ( a.first_pfn == ~0ull ) 7.46 + { 7.47 + rc = 0; 7.48 + p2m->default_access = memaccess[a.hvmmem_access]; 7.49 + goto param_fail5; 7.50 + } 7.51 + 7.52 + rc = -EINVAL; 7.53 + if ( (a.first_pfn > domain_get_maximum_gpfn(d)) || 7.54 + ((a.first_pfn + a.nr - 1) < a.first_pfn) || 7.55 + ((a.first_pfn + a.nr - 1) > domain_get_maximum_gpfn(d)) ) 7.56 + goto param_fail5; 7.57 + 7.58 + if ( a.hvmmem_access >= ARRAY_SIZE(memaccess) ) 7.59 + goto param_fail5; 7.60 + 7.61 + for ( pfn = a.first_pfn; pfn < a.first_pfn + a.nr; pfn++ ) 7.62 + { 7.63 + p2m_type_t t; 7.64 + mfn_t mfn; 7.65 + int success; 7.66 + 7.67 + mfn = gfn_to_mfn_unshare(p2m, pfn, &t, 0); 7.68 + 7.69 + p2m_lock(p2m); 7.70 + success = p2m->set_entry(p2m, pfn, mfn, 0, t, memaccess[a.hvmmem_access]); 7.71 + p2m_unlock(p2m); 7.72 + if ( !success ) 7.73 + goto param_fail5; 7.74 + } 7.75 + 7.76 + rc = 0; 7.77 + 7.78 + param_fail5: 7.79 + rcu_unlock_domain(d); 7.80 + break; 7.81 + } 7.82 + 7.83 + case HVMOP_get_mem_access: 7.84 + { 7.85 + struct xen_hvm_get_mem_access a; 7.86 + struct domain *d; 7.87 + struct p2m_domain *p2m; 7.88 + p2m_type_t t; 7.89 + p2m_access_t ac; 7.90 + mfn_t mfn; 7.91 + 7.92 + /* Interface access to internal p2m accesses */ 7.93 + hvmmem_access_t memaccess[] = { 7.94 + HVMMEM_access_n, 7.95 + HVMMEM_access_r, 7.96 + HVMMEM_access_w, 7.97 + HVMMEM_access_rw, 7.98 + HVMMEM_access_x, 7.99 + HVMMEM_access_rx, 7.100 + HVMMEM_access_wx, 7.101 + HVMMEM_access_rwx, 7.102 + HVMMEM_access_rx2rw 7.103 + }; 7.104 + 7.105 + if ( copy_from_guest(&a, arg, 1) ) 7.106 + return -EFAULT; 7.107 + 7.108 + if ( current->domain->domain_id == a.domid ) 7.109 + return -EPERM; 7.110 + 7.111 + rc = rcu_lock_target_domain_by_id(a.domid, &d); 7.112 + if ( rc != 0 ) 7.113 + return rc; 7.114 + 7.115 + rc = -EINVAL; 7.116 + if ( !is_hvm_domain(d) ) 7.117 + goto param_fail6; 7.118 + 7.119 + p2m = p2m_get_hostp2m(d); 7.120 + 7.121 + if ( a.pfn == ~0ull ) 7.122 + { 7.123 + a.hvmmem_access = memaccess[p2m->default_access]; 7.124 + } 7.125 + else { 7.126 + rc = -EINVAL; 7.127 + if ( (a.pfn > domain_get_maximum_gpfn(d)) ) 7.128 + goto param_fail6; 7.129 + 7.130 + rc = -ESRCH; 7.131 + mfn = p2m->get_entry(p2m, a.pfn, &t, &ac, p2m_query); 7.132 + 7.133 + if ( mfn_x(mfn) == INVALID_MFN ) 7.134 + goto param_fail6; 7.135 + 7.136 + rc = -ERANGE; 7.137 + if ( ac >= ARRAY_SIZE(memaccess) ) 7.138 + goto param_fail6; 7.139 + 7.140 + a.hvmmem_access = memaccess[ac]; 7.141 + } 7.142 + 7.143 + rc = copy_to_guest(arg, &a, 1) ? -EFAULT : 0; 7.144 + 7.145 + param_fail6: 7.146 + rcu_unlock_domain(d); 7.147 + break; 7.148 + } 7.149 + 7.150 case HVMOP_pagetable_dying: 7.151 { 7.152 struct xen_hvm_pagetable_dying a; 7.153 @@ -3478,12 +3621,12 @@ long do_hvm_op(unsigned long op, XEN_GUE 7.154 7.155 rc = -EINVAL; 7.156 if ( !is_hvm_domain(d) || !paging_mode_shadow(d) ) 7.157 - goto param_fail5; 7.158 + goto param_fail7; 7.159 7.160 rc = 0; 7.161 pagetable_dying(d, a.gpa); 7.162 7.163 - param_fail5: 7.164 + param_fail7: 7.165 rcu_unlock_domain(d); 7.166 break; 7.167 }
8.1 --- a/xen/arch/x86/mm/mem_sharing.c Fri Jan 07 11:54:42 2011 +0000 8.2 +++ b/xen/arch/x86/mm/mem_sharing.c Fri Jan 07 11:54:45 2011 +0000 8.3 @@ -304,6 +304,8 @@ static struct page_info* mem_sharing_all 8.4 if(page != NULL) return page; 8.5 8.6 memset(&req, 0, sizeof(req)); 8.7 + req.type = MEM_EVENT_TYPE_SHARED; 8.8 + 8.9 if(must_succeed) 8.10 { 8.11 /* We do not support 'must_succeed' any more. External operations such
9.1 --- a/xen/arch/x86/mm/p2m.c Fri Jan 07 11:54:42 2011 +0000 9.2 +++ b/xen/arch/x86/mm/p2m.c Fri Jan 07 11:54:45 2011 +0000 9.3 @@ -2781,6 +2781,7 @@ void p2m_mem_paging_populate(struct p2m_ 9.4 return; 9.5 9.6 memset(&req, 0, sizeof(req)); 9.7 + req.type = MEM_EVENT_TYPE_PAGING; 9.8 9.9 /* Fix p2m mapping */ 9.10 /* XXX: It seems inefficient to have this here, as it's only needed
10.1 --- a/xen/include/public/hvm/hvm_op.h Fri Jan 07 11:54:42 2011 +0000 10.2 +++ b/xen/include/public/hvm/hvm_op.h Fri Jan 07 11:54:45 2011 +0000 10.3 @@ -158,4 +158,46 @@ struct xen_hvm_xentrace { 10.4 typedef struct xen_hvm_xentrace xen_hvm_xentrace_t; 10.5 DEFINE_XEN_GUEST_HANDLE(xen_hvm_xentrace_t); 10.6 10.7 +#define HVMOP_set_mem_access 12 10.8 +typedef enum { 10.9 + HVMMEM_access_n, 10.10 + HVMMEM_access_r, 10.11 + HVMMEM_access_w, 10.12 + HVMMEM_access_rw, 10.13 + HVMMEM_access_x, 10.14 + HVMMEM_access_rx, 10.15 + HVMMEM_access_wx, 10.16 + HVMMEM_access_rwx, 10.17 + HVMMEM_access_rx2rw, /* Page starts off as read-execute, but automatically change 10.18 + * to read-write on a write */ 10.19 + HVMMEM_access_default /* Take the domain default */ 10.20 +} hvmmem_access_t; 10.21 +/* Notify that a region of memory is to have specific access types */ 10.22 +struct xen_hvm_set_mem_access { 10.23 + /* Domain to be updated. */ 10.24 + domid_t domid; 10.25 + uint16_t pad[3]; /* align next field on 8-byte boundary */ 10.26 + /* Memory type */ 10.27 + uint64_t hvmmem_access; /* hvm_access_t */ 10.28 + /* First pfn, or ~0ull to set the default access for new pages */ 10.29 + uint64_t first_pfn; 10.30 + /* Number of pages, ignored on setting default access */ 10.31 + uint64_t nr; 10.32 +}; 10.33 +typedef struct xen_hvm_set_mem_access xen_hvm_set_mem_access_t; 10.34 +DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_mem_access_t); 10.35 + 10.36 +#define HVMOP_get_mem_access 13 10.37 +/* Get the specific access type for that region of memory */ 10.38 +struct xen_hvm_get_mem_access { 10.39 + /* Domain to be queried. */ 10.40 + domid_t domid; 10.41 + uint16_t pad[3]; /* align next field on 8-byte boundary */ 10.42 + /* Memory type: OUT */ 10.43 + uint64_t hvmmem_access; /* hvm_access_t */ 10.44 + /* pfn, or ~0ull for default access for new pages. IN */ 10.45 + uint64_t pfn; 10.46 +}; 10.47 +typedef struct xen_hvm_get_mem_access xen_hvm_get_mem_access_t; 10.48 +DEFINE_XEN_GUEST_HANDLE(xen_hvm_get_mem_access_t); 10.49 #endif /* __XEN_PUBLIC_HVM_HVM_OP_H__ */