[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH 2/2 for-4.12] xen: implement VCPUOP_register_runstate_phys_memory_area
From: Andrii Anisov <andrii_anisov@xxxxxxxx> VCPUOP_register_runstate_phys_memory_area is implemented via runstate area mapping. Signed-off-by: Andrii Anisov <andrii_anisov@xxxxxxxx> --- xen/arch/arm/domain.c | 22 ++++++++++- xen/arch/x86/domain.c | 34 ++++++++++++++-- xen/common/domain.c | 92 ++++++++++++++++++++++++++++++++++++++++++-- xen/include/asm-arm/domain.h | 2 + xen/include/xen/domain.h | 5 +++ 5 files changed, 148 insertions(+), 7 deletions(-) diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c index ec9bdbd..afc2d48 100644 --- a/xen/arch/arm/domain.c +++ b/xen/arch/arm/domain.c @@ -275,7 +275,7 @@ static void ctxt_switch_to(struct vcpu *n) } /* Update per-VCPU guest runstate shared memory area (if registered). */ -static void update_runstate_area(struct vcpu *v) +void update_runstate_area(struct vcpu *v) { if ( guest_handle_is_null(runstate_guest(v)) ) return; @@ -305,6 +305,26 @@ static void update_runstate_area(struct vcpu *v) 1); } } + else if ( v->runstate_guest_type == RUNSTATE_PADDR ) + { + if ( VM_ASSIST(v->domain, runstate_update_flag) ) + { + runstate_guest(v).p->state_entry_time |= XEN_RUNSTATE_UPDATE; + smp_wmb(); + v->runstate.state_entry_time |= XEN_RUNSTATE_UPDATE; + } + + memcpy(runstate_guest(v).p, &v->runstate, sizeof(v->runstate)); + + if ( VM_ASSIST(v->domain, runstate_update_flag) ) + { + runstate_guest(v).p->state_entry_time &= ~XEN_RUNSTATE_UPDATE; + smp_wmb(); + v->runstate.state_entry_time &= ~XEN_RUNSTATE_UPDATE; + } + } + else + { /* No actions required */ } } static void schedule_tail(struct vcpu *prev) diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index 2acffba..6598bbb 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -1605,7 +1605,7 @@ void paravirt_ctxt_switch_to(struct vcpu *v) /* Update per-VCPU guest runstate shared memory area (if registered). */ bool update_runstate_area(struct vcpu *v) { - bool rc; + bool rc = true; struct guest_memory_policy policy = { .nested_guest_mode = false }; void __user *guest_handle = NULL; @@ -1648,9 +1648,37 @@ bool update_runstate_area(struct vcpu *v) (void *)(&v->runstate.state_entry_time + 1) - 1, 1); } } - else + else if ( v->runstate_guest_type == RUNSTATE_PADDR ) { - rc = true; + if ( VM_ASSIST(v->domain, runstate_update_flag) ) + { + v->runstate.state_entry_time |= XEN_RUNSTATE_UPDATE; + if ( has_32bit_shinfo((v)->domain) ) + v->runstate_guest.compat.p->state_entry_time |= XEN_RUNSTATE_UPDATE; + else + runstate_guest(v).p->state_entry_time |= XEN_RUNSTATE_UPDATE; + smp_wmb(); + } + + if ( has_32bit_shinfo(v->domain) ) + { + struct compat_vcpu_runstate_info info; + + XLAT_vcpu_runstate_info(&info, &v->runstate); + memcpy(v->runstate_guest.compat.p, &info, sizeof(info)); + } + else + memcpy(runstate_guest(v).p, &v->runstate, sizeof(v->runstate)); + + if ( VM_ASSIST(v->domain, runstate_update_flag) ) + { + v->runstate.state_entry_time &= ~XEN_RUNSTATE_UPDATE; + if ( has_32bit_shinfo((v)->domain) ) + v->runstate_guest.compat.p->state_entry_time &= ~XEN_RUNSTATE_UPDATE; + else + runstate_guest(v).p->state_entry_time &= ~XEN_RUNSTATE_UPDATE; + smp_wmb(); + } } update_guest_memory_policy(v, &policy); diff --git a/xen/common/domain.c b/xen/common/domain.c index 2c83ede..cb9c788 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -738,7 +738,14 @@ int domain_kill(struct domain *d) if ( cpupool_move_domain(d, cpupool0) ) return -ERESTART; for_each_vcpu ( d, v ) + { + if ( v->runstate_guest_type == RUNSTATE_VADDR ) + set_xen_guest_handle(runstate_guest(v), NULL); + else + unmap_runstate_area(v); + unmap_vcpu_info(v); + } d->is_dying = DOMDYING_dead; /* Mem event cleanup has to go here because the rings * have to be put before we call put_domain. */ @@ -1192,7 +1199,11 @@ int domain_soft_reset(struct domain *d) for_each_vcpu ( d, v ) { - set_xen_guest_handle(runstate_guest(v), NULL); + if ( v->runstate_guest_type == RUNSTATE_VADDR ) + set_xen_guest_handle(runstate_guest(v), NULL); + else + unmap_runstate_area(v); + unmap_vcpu_info(v); } @@ -1333,6 +1344,65 @@ void unmap_vcpu_info(struct vcpu *v) put_page_and_type(mfn_to_page(mfn)); } +int map_runstate_area(struct vcpu *v, + struct vcpu_register_runstate_memory_area *area) +{ + unsigned long offset = area->addr.p & ~PAGE_MASK; + gfn_t gfn = gaddr_to_gfn(area->addr.p); + struct domain *d = v->domain; + void *mapping; + struct page_info *page; + size_t size = sizeof (struct vcpu_runstate_info ); + + ASSERT(v->runstate_guest_type == RUNSTATE_PADDR ); + + if ( offset > (PAGE_SIZE - size) ) + return -EINVAL; + + page = get_page_from_gfn(d, gfn_x(gfn), NULL, P2M_ALLOC); + if ( !page ) + return -EINVAL; + + if ( !get_page_type(page, PGT_writable_page) ) + { + put_page(page); + return -EINVAL; + } + + mapping = __map_domain_page_global(page); + + if ( mapping == NULL ) + { + put_page_and_type(page); + return -ENOMEM; + } + + runstate_guest(v).p = mapping + offset; + + return 0; +} + +void unmap_runstate_area(struct vcpu *v) +{ + mfn_t mfn; + + if ( v->runstate_guest_type != RUNSTATE_PADDR ) + return; + + if ( guest_handle_is_null(runstate_guest(v)) ) + return; + + mfn = _mfn(virt_to_mfn(runstate_guest(v).p)); + + unmap_domain_page_global((void *) + ((unsigned long)runstate_guest(v).p & + PAGE_MASK)); + + v->runstate_guest_type = RUNSTATE_NONE; + runstate_guest(v).p = NULL; + put_page_and_type(mfn_to_page(mfn)); +} + int default_initialise_vcpu(struct vcpu *v, XEN_GUEST_HANDLE_PARAM(void) arg) { struct vcpu_guest_context *ctxt; @@ -1532,13 +1602,29 @@ long do_vcpu_op(int cmd, unsigned int vcpuid, XEN_GUEST_HANDLE_PARAM(void) arg) vcpu_runstate_get(v, &runstate); __copy_to_guest(runstate_guest(v), &runstate, 1); } - break; } case VCPUOP_register_runstate_phys_memory_area: { - rc = -ENOSYS; + struct vcpu_register_runstate_memory_area area; + + rc = -EFAULT; + if ( copy_from_guest(&area, arg, 1) ) + break; + + unmap_runstate_area(v); + v->runstate_guest_type = RUNSTATE_PADDR; + rc = map_runstate_area(v, &area); + + if ( rc ) + { + v->runstate_guest_type = RUNSTATE_NONE; + break; + } + + update_runstate_area(v); + break; } diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h index 312fec8..3fb6ea2 100644 --- a/xen/include/asm-arm/domain.h +++ b/xen/include/asm-arm/domain.h @@ -217,6 +217,8 @@ void vcpu_show_execution_state(struct vcpu *); void vcpu_show_registers(const struct vcpu *); void vcpu_switch_to_aarch64_mode(struct vcpu *); +void update_runstate_area(struct vcpu *); + /* * Due to the restriction of GICv3, the number of vCPUs in AFF0 is * limited to 16, thus only the first 4 bits of AFF0 are legal. We will diff --git a/xen/include/xen/domain.h b/xen/include/xen/domain.h index d1bfc82..090a54d 100644 --- a/xen/include/xen/domain.h +++ b/xen/include/xen/domain.h @@ -118,4 +118,9 @@ struct vnuma_info { void vnuma_destroy(struct vnuma_info *vnuma); +struct vcpu_register_runstate_memory_area; +int map_runstate_area(struct vcpu *v, + struct vcpu_register_runstate_memory_area *area); +void unmap_runstate_area(struct vcpu *v); + #endif /* __XEN_DOMAIN_H__ */ -- 2.7.4 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |