[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH RFC 3/7] xen/arm: Enable the compilation of mem_access and mem_event on ARM.
This patch sets up the infrastructure to support mem_access and mem_event on ARM and turns on compilation. We define the required XSM functions, handling of domctl copyback, and the required p2m types and stub-functions in this patch. Signed-off-by: Tamas K Lengyel <tamas.lengyel@xxxxxxxxxxxx> --- xen/arch/arm/domctl.c | 36 ++++++++++++++-- xen/arch/arm/mm.c | 18 ++++++-- xen/arch/arm/p2m.c | 5 +++ xen/common/mem_access.c | 6 +-- xen/common/mem_event.c | 15 +++++-- xen/include/asm-arm/p2m.h | 100 ++++++++++++++++++++++++++++++++++--------- xen/include/xen/mem_access.h | 19 -------- xen/include/xen/mem_event.h | 53 +++-------------------- xen/include/xen/sched.h | 1 - xen/include/xsm/dummy.h | 24 +++++------ xen/include/xsm/xsm.h | 25 +++++------ xen/xsm/dummy.c | 4 +- 12 files changed, 178 insertions(+), 128 deletions(-) diff --git a/xen/arch/arm/domctl.c b/xen/arch/arm/domctl.c index 45974e7..bb0b8d3 100644 --- a/xen/arch/arm/domctl.c +++ b/xen/arch/arm/domctl.c @@ -11,10 +11,17 @@ #include <xen/sched.h> #include <xen/hypercall.h> #include <public/domctl.h> +#include <asm/guest_access.h> +#include <xen/mem_event.h> +#include <public/mem_event.h> long arch_do_domctl(struct xen_domctl *domctl, struct domain *d, XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl) { + + long ret; + bool_t copyback = 0; + switch ( domctl->cmd ) { case XEN_DOMCTL_cacheflush: @@ -23,17 +30,38 @@ long arch_do_domctl(struct xen_domctl *domctl, struct domain *d, unsigned long e = s + domctl->u.cacheflush.nr_pfns; if ( domctl->u.cacheflush.nr_pfns > (1U<<MAX_ORDER) ) - return -EINVAL; + { + ret = -EINVAL; + break; + } if ( e < s ) - return -EINVAL; + { + ret = -EINVAL; + break; + } - return p2m_cache_flush(d, s, e); + ret = p2m_cache_flush(d, s, e); } + break; + + case XEN_DOMCTL_mem_event_op: + { + ret = mem_event_domctl(d, &domctl->u.mem_event_op, + guest_handle_cast(u_domctl, void)); + copyback = 1; + } + break; default: - return subarch_do_domctl(domctl, d, u_domctl); + ret = subarch_do_domctl(domctl, d, u_domctl); + break; } + + if ( copyback && __copy_to_guest(u_domctl, domctl, 1) ) + ret = -EFAULT; + + return ret; } void arch_get_info_guest(struct vcpu *v, vcpu_guest_context_u c) diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c index 0a243b0..cd04dec 100644 --- a/xen/arch/arm/mm.c +++ b/xen/arch/arm/mm.c @@ -35,6 +35,9 @@ #include <asm/current.h> #include <asm/flushtlb.h> #include <public/memory.h> +#include <xen/mem_event.h> +#include <xen/mem_access.h> +#include <xen/hypercall.h> #include <xen/sched.h> #include <xen/vmap.h> #include <xsm/xsm.h> @@ -1111,18 +1114,27 @@ int xenmem_add_to_physmap_one( long arch_memory_op(int op, XEN_GUEST_HANDLE_PARAM(void) arg) { - switch ( op ) + + long rc; + + switch ( op & MEMOP_CMD_MASK ) { /* XXX: memsharing not working yet */ case XENMEM_get_sharing_shared_pages: case XENMEM_get_sharing_freed_pages: return 0; + case XENMEM_access_op: + { + rc = mem_access_memop(op, guest_handle_cast(arg, xen_mem_access_op_t)); + break; + } default: - return -ENOSYS; + rc = -ENOSYS; + break; } - return 0; + return rc; } struct domain *page_get_owner_and_reference(struct page_info *page) diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c index 143199b..0ca0d2f 100644 --- a/xen/arch/arm/p2m.c +++ b/xen/arch/arm/p2m.c @@ -10,6 +10,9 @@ #include <asm/event.h> #include <asm/hardirq.h> #include <asm/page.h> +#include <xen/mem_event.h> +#include <public/mem_event.h> +#include <xen/mem_access.h> /* First level P2M is 2 consecutive pages */ #define P2M_FIRST_ORDER 1 @@ -999,6 +1002,8 @@ int p2m_init(struct domain *d) p2m->max_mapped_gfn = 0; p2m->lowest_mapped_gfn = ULONG_MAX; + p2m->default_access = p2m_access_rwx; + err: spin_unlock(&p2m->lock); diff --git a/xen/common/mem_access.c b/xen/common/mem_access.c index 84acdf9..6bb9cf4 100644 --- a/xen/common/mem_access.c +++ b/xen/common/mem_access.c @@ -29,8 +29,6 @@ #include <xen/mem_event.h> #include <xsm/xsm.h> -#ifdef CONFIG_X86 - int mem_access_memop(unsigned long cmd, XEN_GUEST_HANDLE_PARAM(xen_mem_access_op_t) arg) { @@ -45,9 +43,11 @@ int mem_access_memop(unsigned long cmd, if ( rc ) return rc; +#ifdef CONFIG_X86 rc = -EINVAL; if ( !is_hvm_domain(d) ) goto out; +#endif rc = xsm_mem_event_op(XSM_DM_PRIV, d, XENMEM_access_op); if ( rc ) @@ -125,8 +125,6 @@ int mem_access_send_req(struct domain *d, mem_event_request_t *req) return 0; } -#endif /* CONFIG_X86 */ - /* * Local variables: * mode: C diff --git a/xen/common/mem_event.c b/xen/common/mem_event.c index a94ddf6..2a91928 100644 --- a/xen/common/mem_event.c +++ b/xen/common/mem_event.c @@ -20,16 +20,19 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifdef CONFIG_X86 - +#include <xen/sched.h> #include <asm/domain.h> #include <xen/event.h> #include <xen/wait.h> #include <asm/p2m.h> #include <xen/mem_event.h> #include <xen/mem_access.h> + +#ifdef CONFIG_X86 #include <asm/mem_paging.h> #include <asm/mem_sharing.h> +#endif + #include <xsm/xsm.h> /* for public/io/ring.h macros */ @@ -427,6 +430,7 @@ static void mem_access_notification(struct vcpu *v, unsigned int port) p2m_mem_access_resume(v->domain); } +#ifdef CONFIG_X86 /* Registered with Xen-bound event channel for incoming notifications. */ static void mem_paging_notification(struct vcpu *v, unsigned int port) { @@ -470,6 +474,7 @@ int do_mem_event_op(int op, uint32_t domain, void *arg) rcu_unlock_domain(d); return ret; } +#endif /* Clean up on domain destruction */ void mem_event_cleanup(struct domain *d) @@ -538,6 +543,8 @@ int mem_event_domctl(struct domain *d, xen_domctl_mem_event_op_t *mec, { case XEN_DOMCTL_MEM_EVENT_OP_ACCESS_ENABLE: { + +#ifdef CONFIG_X86 rc = -ENODEV; /* Only HAP is supported */ if ( !hap_enabled(d) ) @@ -546,6 +553,7 @@ int mem_event_domctl(struct domain *d, xen_domctl_mem_event_op_t *mec, /* Currently only EPT is supported */ if ( !cpu_has_vmx ) break; +#endif rc = mem_event_enable(d, mec, med, _VPF_mem_access, HVM_PARAM_ACCESS_RING_PFN, @@ -567,6 +575,7 @@ int mem_event_domctl(struct domain *d, xen_domctl_mem_event_op_t *mec, } break; +#ifdef CONFIG_X86 case XEN_DOMCTL_MEM_EVENT_OP_PAGING: { struct mem_event_domain *med = &d->mem_event->paging; @@ -656,6 +665,7 @@ int mem_event_domctl(struct domain *d, xen_domctl_mem_event_op_t *mec, } } break; +#endif default: rc = -ENOSYS; @@ -695,7 +705,6 @@ void mem_event_vcpu_unpause(struct vcpu *v) vcpu_unpause(v); } -#endif /* * Local variables: diff --git a/xen/include/asm-arm/p2m.h b/xen/include/asm-arm/p2m.h index 06c93a0..f3d1f33 100644 --- a/xen/include/asm-arm/p2m.h +++ b/xen/include/asm-arm/p2m.h @@ -2,9 +2,55 @@ #define _XEN_P2M_H #include <xen/mm.h> +#include <public/memory.h> +#include <public/mem_event.h> struct domain; +/* List of possible type for each page in the p2m entry. + * The number of available bit per page in the pte for this purpose is 4 bits. + * So it's possible to only have 16 fields. If we run out of value in the + * future, it's possible to use higher value for pseudo-type and don't store + * them in the p2m entry. + */ +typedef enum { + p2m_invalid = 0, /* Nothing mapped here */ + p2m_ram_rw, /* Normal read/write guest RAM */ + p2m_ram_ro, /* Read-only; writes are silently dropped */ + p2m_mmio_direct, /* Read/write mapping of genuine MMIO area */ + p2m_map_foreign, /* Ram pages from foreign domain */ + p2m_grant_map_rw, /* Read/write grant mapping */ + p2m_grant_map_ro, /* Read-only grant mapping */ + /* The types below are only used to decide the page attribute in the P2M */ + p2m_iommu_map_rw, /* Read/write iommu mapping */ + p2m_iommu_map_ro, /* Read-only iommu mapping */ + p2m_max_real_type, /* Types after this won't be store in the p2m */ +} p2m_type_t; + +/* + * Additional access types, which are used to further restrict + * the permissions given by the p2m_type_t memory type. Violations + * caused by p2m_access_t restrictions are sent to the mem_event + * interface. + * + * The access permissions are soft state: when any ambigious change of page + * type or use occurs, or when pages are flushed, swapped, or at any other + * convenient type, the access permissions can get reset to the p2m_domain + * default. + */ +typedef enum { + p2m_access_n = 0, /* No access permissions allowed */ + p2m_access_r = 1, + p2m_access_w = 2, + p2m_access_rw = 3, + p2m_access_x = 4, + p2m_access_rx = 5, + p2m_access_wx = 6, + p2m_access_rwx = 7 + + /* NOTE: Assumed to be only 4 bits right now */ +} p2m_access_t; + /* Per-p2m-table state */ struct p2m_domain { /* Lock that protects updates to the p2m */ @@ -38,27 +84,17 @@ struct p2m_domain { * at each p2m tree level. */ unsigned long shattered[4]; } stats; -}; -/* List of possible type for each page in the p2m entry. - * The number of available bit per page in the pte for this purpose is 4 bits. - * So it's possible to only have 16 fields. If we run out of value in the - * future, it's possible to use higher value for pseudo-type and don't store - * them in the p2m entry. - */ -typedef enum { - p2m_invalid = 0, /* Nothing mapped here */ - p2m_ram_rw, /* Normal read/write guest RAM */ - p2m_ram_ro, /* Read-only; writes are silently dropped */ - p2m_mmio_direct, /* Read/write mapping of genuine MMIO area */ - p2m_map_foreign, /* Ram pages from foreign domain */ - p2m_grant_map_rw, /* Read/write grant mapping */ - p2m_grant_map_ro, /* Read-only grant mapping */ - /* The types below are only used to decide the page attribute in the P2M */ - p2m_iommu_map_rw, /* Read/write iommu mapping */ - p2m_iommu_map_ro, /* Read-only iommu mapping */ - p2m_max_real_type, /* Types after this won't be store in the p2m */ -} p2m_type_t; + /* Default P2M access type for each page in the the domain: new pages, + * swapped in pages, cleared pages, and pages that are ambiquously + * retyped get this access type. See definition of p2m_access_t. */ + p2m_access_t default_access; + + /* If true, and an access fault comes in and there is no mem_event listener, + * pause domain. Otherwise, remove access restrictions. */ + bool_t access_required; + +}; #define p2m_is_foreign(_t) ((_t) == p2m_map_foreign) #define p2m_is_ram(_t) ((_t) == p2m_ram_rw || (_t) == p2m_ram_ro) @@ -195,6 +231,30 @@ static inline int get_page_and_type(struct page_info *page, return rc; } +/* get host p2m table */ +#define p2m_get_hostp2m(d) (&((d)->arch.p2m)) + +/* Resumes the running of the VCPU, restarting the last instruction */ +static inline void p2m_mem_access_resume(struct domain *d) {} + +/* Set access type for a region of pfns. + * If start_pfn == -1ul, sets the default access type */ +static inline +long p2m_set_mem_access(struct domain *d, unsigned long start_pfn, uint32_t nr, + uint32_t start, uint32_t mask, xenmem_access_t access) +{ + return -ENOSYS; +} + +/* Get access type for a pfn + * If pfn == -1ul, gets the default access type */ +static inline +int p2m_get_mem_access(struct domain *d, unsigned long pfn, + xenmem_access_t *access) +{ + return -ENOSYS; +} + #endif /* _XEN_P2M_H */ /* diff --git a/xen/include/xen/mem_access.h b/xen/include/xen/mem_access.h index ded5441..5c7c5fd 100644 --- a/xen/include/xen/mem_access.h +++ b/xen/include/xen/mem_access.h @@ -23,29 +23,10 @@ #ifndef _XEN_ASM_MEM_ACCESS_H #define _XEN_ASM_MEM_ACCESS_H -#ifdef CONFIG_X86 - int mem_access_memop(unsigned long cmd, XEN_GUEST_HANDLE_PARAM(xen_mem_access_op_t) arg); int mem_access_send_req(struct domain *d, mem_event_request_t *req); -#else - -static inline -int mem_access_memop(unsigned long cmd, - XEN_GUEST_HANDLE_PARAM(xen_mem_access_op_t) arg) -{ - return -ENOSYS; -} - -static inline -int mem_access_send_req(struct domain *d, mem_event_request_t *req) -{ - return -ENOSYS; -} - -#endif /* CONFIG_X86 */ - #endif /* _XEN_ASM_MEM_ACCESS_H */ /* diff --git a/xen/include/xen/mem_event.h b/xen/include/xen/mem_event.h index a28d453..e2a9d4d 100644 --- a/xen/include/xen/mem_event.h +++ b/xen/include/xen/mem_event.h @@ -24,8 +24,6 @@ #ifndef __MEM_EVENT_H__ #define __MEM_EVENT_H__ -#ifdef CONFIG_X86 - /* Clean up on domain destruction */ void mem_event_cleanup(struct domain *d); @@ -67,66 +65,25 @@ void mem_event_put_request(struct domain *d, struct mem_event_domain *med, int mem_event_get_response(struct domain *d, struct mem_event_domain *med, mem_event_response_t *rsp); -int do_mem_event_op(int op, uint32_t domain, void *arg); int mem_event_domctl(struct domain *d, xen_domctl_mem_event_op_t *mec, XEN_GUEST_HANDLE_PARAM(void) u_domctl); void mem_event_vcpu_pause(struct vcpu *v); void mem_event_vcpu_unpause(struct vcpu *v); -#else - -static inline void mem_event_cleanup(struct domain *d) {} - -static inline bool_t mem_event_check_ring(struct mem_event_domain *med) -{ - return 0; -} - -static inline int mem_event_claim_slot(struct domain *d, - struct mem_event_domain *med) -{ - return -ENOSYS; -} - -static inline int mem_event_claim_slot_nosleep(struct domain *d, - struct mem_event_domain *med) -{ - return -ENOSYS; -} - -static inline -void mem_event_cancel_slot(struct domain *d, struct mem_event_domain *med) -{} - -static inline -void mem_event_put_request(struct domain *d, struct mem_event_domain *med, - mem_event_request_t *req) -{} +#ifdef CONFIG_X86 -static inline -int mem_event_get_response(struct domain *d, struct mem_event_domain *med, - mem_event_response_t *rsp) -{ - return -ENOSYS; -} +int do_mem_event_op(int op, uint32_t domain, void *arg); -static inline int do_mem_event_op(int op, uint32_t domain, void *arg) -{ - return -ENOSYS; -} +#else static inline -int mem_event_domctl(struct domain *d, xen_domctl_mem_event_op_t *mec, - XEN_GUEST_HANDLE_PARAM(void) u_domctl) +int do_mem_event_op(int op, uint32_t domain, void *arg) { return -ENOSYS; } -static inline void mem_event_vcpu_pause(struct vcpu *v) {} -static inline void mem_event_vcpu_unpause(struct vcpu *v) {} - -#endif /* CONFIG_X86 */ +#endif #endif /* __MEM_EVENT_H__ */ diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h index 4575dda..2365fad 100644 --- a/xen/include/xen/sched.h +++ b/xen/include/xen/sched.h @@ -1,4 +1,3 @@ - #ifndef __SCHED_H__ #define __SCHED_H__ diff --git a/xen/include/xsm/dummy.h b/xen/include/xsm/dummy.h index c5aa316..61677ea 100644 --- a/xen/include/xsm/dummy.h +++ b/xen/include/xsm/dummy.h @@ -507,6 +507,18 @@ static XSM_INLINE int xsm_hvm_param_nested(XSM_DEFAULT_ARG struct domain *d) return xsm_default_action(action, current->domain, d); } +static XSM_INLINE int xsm_mem_event_control(XSM_DEFAULT_ARG struct domain *d, int mode, int op) +{ + XSM_ASSERT_ACTION(XSM_PRIV); + return xsm_default_action(action, current->domain, d); +} + +static XSM_INLINE int xsm_mem_event_op(XSM_DEFAULT_ARG struct domain *d, int op) +{ + XSM_ASSERT_ACTION(XSM_DM_PRIV); + return xsm_default_action(action, current->domain, d); +} + #ifdef CONFIG_X86 static XSM_INLINE int xsm_do_mca(XSM_DEFAULT_VOID) { @@ -550,18 +562,6 @@ static XSM_INLINE int xsm_hvm_ioreq_server(XSM_DEFAULT_ARG struct domain *d, int return xsm_default_action(action, current->domain, d); } -static XSM_INLINE int xsm_mem_event_control(XSM_DEFAULT_ARG struct domain *d, int mode, int op) -{ - XSM_ASSERT_ACTION(XSM_PRIV); - return xsm_default_action(action, current->domain, d); -} - -static XSM_INLINE int xsm_mem_event_op(XSM_DEFAULT_ARG struct domain *d, int op) -{ - XSM_ASSERT_ACTION(XSM_DM_PRIV); - return xsm_default_action(action, current->domain, d); -} - static XSM_INLINE int xsm_mem_sharing_op(XSM_DEFAULT_ARG struct domain *d, struct domain *cd, int op) { XSM_ASSERT_ACTION(XSM_DM_PRIV); diff --git a/xen/include/xsm/xsm.h b/xen/include/xsm/xsm.h index a85045d..64289cd 100644 --- a/xen/include/xsm/xsm.h +++ b/xen/include/xsm/xsm.h @@ -140,6 +140,9 @@ struct xsm_operations { int (*hvm_control) (struct domain *d, unsigned long op); int (*hvm_param_nested) (struct domain *d); + int (*mem_event_control) (struct domain *d, int mode, int op); + int (*mem_event_op) (struct domain *d, int op); + #ifdef CONFIG_X86 int (*do_mca) (void); int (*shadow_control) (struct domain *d, uint32_t op); @@ -148,8 +151,6 @@ struct xsm_operations { int (*hvm_set_pci_link_route) (struct domain *d); int (*hvm_inject_msi) (struct domain *d); int (*hvm_ioreq_server) (struct domain *d, int op); - int (*mem_event_control) (struct domain *d, int mode, int op); - int (*mem_event_op) (struct domain *d, int op); int (*mem_sharing_op) (struct domain *d, struct domain *cd, int op); int (*apic) (struct domain *d, int cmd); int (*memtype) (uint32_t access); @@ -534,6 +535,16 @@ static inline int xsm_hvm_param_nested (xsm_default_t def, struct domain *d) return xsm_ops->hvm_param_nested(d); } +static inline int xsm_mem_event_control (xsm_default_t def, struct domain *d, int mode, int op) +{ + return xsm_ops->mem_event_control(d, mode, op); +} + +static inline int xsm_mem_event_op (xsm_default_t def, struct domain *d, int op) +{ + return xsm_ops->mem_event_op(d, op); +} + #ifdef CONFIG_X86 static inline int xsm_do_mca(xsm_default_t def) { @@ -570,16 +581,6 @@ static inline int xsm_hvm_ioreq_server (xsm_default_t def, struct domain *d, int return xsm_ops->hvm_ioreq_server(d, op); } -static inline int xsm_mem_event_control (xsm_default_t def, struct domain *d, int mode, int op) -{ - return xsm_ops->mem_event_control(d, mode, op); -} - -static inline int xsm_mem_event_op (xsm_default_t def, struct domain *d, int op) -{ - return xsm_ops->mem_event_op(d, op); -} - static inline int xsm_mem_sharing_op (xsm_default_t def, struct domain *d, struct domain *cd, int op) { return xsm_ops->mem_sharing_op(d, cd, op); diff --git a/xen/xsm/dummy.c b/xen/xsm/dummy.c index c95c803..9df9d81 100644 --- a/xen/xsm/dummy.c +++ b/xen/xsm/dummy.c @@ -116,6 +116,8 @@ void xsm_fixup_ops (struct xsm_operations *ops) set_to_dummy_if_null(ops, add_to_physmap); set_to_dummy_if_null(ops, remove_from_physmap); set_to_dummy_if_null(ops, map_gmfn_foreign); + set_to_dummy_if_null(ops, mem_event_control); + set_to_dummy_if_null(ops, mem_event_op); #ifdef CONFIG_X86 set_to_dummy_if_null(ops, do_mca); @@ -125,8 +127,6 @@ void xsm_fixup_ops (struct xsm_operations *ops) set_to_dummy_if_null(ops, hvm_set_pci_link_route); set_to_dummy_if_null(ops, hvm_inject_msi); set_to_dummy_if_null(ops, hvm_ioreq_server); - set_to_dummy_if_null(ops, mem_event_control); - set_to_dummy_if_null(ops, mem_event_op); set_to_dummy_if_null(ops, mem_sharing_op); set_to_dummy_if_null(ops, apic); set_to_dummy_if_null(ops, platform_op); -- 2.0.1 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |