[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v2 25/25] arm/altp2m: Add test of xc_altp2m_change_gfn.
This commit extends xen-access by a simple test of the functionality provided by "xc_altp2m_change_gfn". The idea is to dynamically remap a trapping gfn to another mfn, which holds the same content as the original mfn. Signed-off-by: Sergej Proskurin <proskurin@xxxxxxxxxxxxx> --- Cc: Razvan Cojocaru <rcojocaru@xxxxxxxxxxxxxxx> Cc: Tamas K Lengyel <tamas@xxxxxxxxxxxxx> Cc: Ian Jackson <ian.jackson@xxxxxxxxxxxxx> Cc: Wei Liu <wei.liu2@xxxxxxxxxx> --- tools/tests/xen-access/xen-access.c | 135 +++++++++++++++++++++++++++++++++++- 1 file changed, 132 insertions(+), 3 deletions(-) diff --git a/tools/tests/xen-access/xen-access.c b/tools/tests/xen-access/xen-access.c index eafd7d6..39b7ddf 100644 --- a/tools/tests/xen-access/xen-access.c +++ b/tools/tests/xen-access/xen-access.c @@ -38,6 +38,7 @@ #include <sys/mman.h> #include <sys/poll.h> +#define XC_WANT_COMPAT_MAP_FOREIGN_API #include <xenctrl.h> #include <xenevtchn.h> #include <xen/vm_event.h> @@ -49,6 +50,8 @@ #define START_PFN 0ULL #endif +#define INVALID_GFN ~(0UL) + #define DPRINTF(a, b...) fprintf(stderr, a, ## b) #define ERROR(a, b...) fprintf(stderr, a "\n", ## b) #define PERROR(a, b...) fprintf(stderr, a ": %s\n", ## b, strerror(errno)) @@ -72,9 +75,14 @@ typedef struct xenaccess { xen_pfn_t max_gpfn; vm_event_t vm_event; + + unsigned int ap2m_idx; + xen_pfn_t gfn_old; + xen_pfn_t gfn_new; } xenaccess_t; static int interrupted; +static int gfn_changed = 0; bool evtchn_bind = 0, evtchn_open = 0, mem_access_enable = 0; static void close_handler(int sig) @@ -82,6 +90,94 @@ static void close_handler(int sig) interrupted = sig; } +static int copy_gfn(xc_interface *xch, domid_t domain_id, + xen_pfn_t dst_gfn, xen_pfn_t src_gfn) +{ + void *src_vaddr = NULL; + void *dst_vaddr = NULL; + + src_vaddr = xc_map_foreign_range(xch, domain_id, XC_PAGE_SIZE, + PROT_READ, src_gfn); + if ( src_vaddr == MAP_FAILED || src_vaddr == NULL) + { + return -1; + } + + dst_vaddr = xc_map_foreign_range(xch, domain_id, XC_PAGE_SIZE, + PROT_WRITE, dst_gfn); + if ( dst_vaddr == MAP_FAILED || dst_vaddr == NULL) + { + return -1; + } + + memcpy(dst_vaddr, src_vaddr, XC_PAGE_SIZE); + + munmap(src_vaddr, XC_PAGE_SIZE); + munmap(dst_vaddr, XC_PAGE_SIZE); + + return 0; +} + +/* + * This function allocates and populates a page in the guest's physmap that is + * subsequently filled with contents of the trapping address. Finally, through + * the invocation of xc_altp2m_change_gfn, the altp2m subsystem changes the gfn + * to mfn mapping of the target altp2m view. + */ +static int xenaccess_change_gfn(xc_interface *xch, + domid_t domain_id, + unsigned int ap2m_idx, + xen_pfn_t gfn_old, + xen_pfn_t *gfn_new) +{ + int rc; + + /* + * We perform this function only once as it is intended to be used for + * testing and demonstration purposes. Thus, we signalize that further + * altp2m-related traps will not change trapping gfn's. + */ + gfn_changed = 1; + + rc = xc_domain_increase_reservation_exact(xch, domain_id, 1, 0, 0, gfn_new); + if ( rc < 0 ) + return -1; + + rc = xc_domain_populate_physmap_exact(xch, domain_id, 1, 0, 0, gfn_new); + if ( rc < 0 ) + return -1; + + /* Copy content of the old gfn into the newly allocated gfn */ + rc = copy_gfn(xch, domain_id, *gfn_new, gfn_old); + if ( rc < 0 ) + return -1; + + xc_altp2m_change_gfn(xch, domain_id, ap2m_idx, gfn_old, *gfn_new); + + return 0; +} + +static int xenaccess_reset_gfn(xc_interface *xch, + domid_t domain_id, + unsigned int ap2m_idx, + xen_pfn_t gfn_old, + xen_pfn_t gfn_new) +{ + int rc; + + /* Reset previous state */ + xc_altp2m_change_gfn(xch, domain_id, ap2m_idx, gfn_old, INVALID_GFN); + + /* Invalidate the new gfn */ + xc_altp2m_change_gfn(xch, domain_id, ap2m_idx, gfn_new, INVALID_GFN); + + rc = xc_domain_decrease_reservation_exact(xch, domain_id, 1, 0, &gfn_new); + if ( rc < 0 ) + return -1; + + return 0; +} + int xc_wait_for_event_or_timeout(xc_interface *xch, xenevtchn_handle *xce, unsigned long ms) { struct pollfd fd = { .fd = xenevtchn_fd(xce), .events = POLLIN | POLLERR }; @@ -227,6 +323,10 @@ xenaccess_t *xenaccess_init(xc_interface **xch_r, domid_t domain_id) } mem_access_enable = 1; + xenaccess->ap2m_idx = ~(0); + xenaccess->gfn_old = INVALID_GFN; + xenaccess->gfn_new = INVALID_GFN; + /* Open event channel */ xenaccess->vm_event.xce_handle = xenevtchn_open(NULL, 0); if ( xenaccess->vm_event.xce_handle == NULL ) @@ -662,10 +762,27 @@ int main(int argc, char *argv[]) if ( altp2m && req.flags & VM_EVENT_FLAG_ALTERNATE_P2M) { - DPRINTF("\tSwitching back to default view!\n"); - rsp.flags |= (VM_EVENT_FLAG_ALTERNATE_P2M | VM_EVENT_FLAG_TOGGLE_SINGLESTEP); - rsp.altp2m_idx = 0; + + if ( !gfn_changed ) + { + /* Store trapping gfn and ap2m index for cleanup. */ + xenaccess->gfn_old = req.u.mem_access.gfn; + xenaccess->ap2m_idx = req.altp2m_idx; + + /* Note that this function is called only once. */ + xenaccess_change_gfn(xenaccess->xc_handle, domain_id, req.altp2m_idx, + xenaccess->gfn_old, &xenaccess->gfn_new); + + /* Do not change the currently active altp2m view, yet. */ + rsp.altp2m_idx = req.altp2m_idx; + } + else + { + DPRINTF("\tSwitching back to default view!\n"); + + rsp.altp2m_idx = 0; + } } else if ( default_access != after_first_access ) { @@ -783,6 +900,18 @@ exit: for ( vcpu_id = 0; vcpu_id<XEN_LEGACY_MAX_VCPUS; vcpu_id++) rc = control_singlestep(xch, domain_id, vcpu_id, 0); #endif + + /* Reset changed gfn. */ + if ( xenaccess->gfn_new != INVALID_GFN ) + { + rc = xenaccess_reset_gfn(xenaccess->xc_handle, xenaccess->vm_event.domain_id, + xenaccess->ap2m_idx, xenaccess->gfn_old, xenaccess->gfn_new); + if ( rc != 0 ) + { + ERROR("Error resetting the remapped gfn"); + return rc; + } + } } /* Tear down domain xenaccess */ -- 2.9.0 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx https://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |