[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v4 14/39] arm/p2m: Add HVMOP_altp2m_set_domain_state
The HVMOP_altp2m_set_domain_state allows to activate altp2m on a specific domain. This commit adopts the x86 HVMOP_altp2m_set_domain_state implementation. Signed-off-by: Sergej Proskurin <proskurin@xxxxxxxxxxxxx> --- Cc: Stefano Stabellini <sstabellini@xxxxxxxxxx> Cc: Julien Grall <julien.grall@xxxxxxx> --- v2: Dynamically allocate memory for altp2m views only when needed. Move altp2m related helpers to altp2m.c. p2m_flush_tlb is made publicly accessible. v3: Cosmetic fixes. Removed call to "p2m_alloc_table" in "altp2m_init_helper" as the entire p2m allocation is now done within the function "p2m_init_one". The same applies to the call of the function "p2m_flush_tlb" from "p2m_init_one". Removed the "altp2m_enabled" check in HVMOP_altp2m_set_domain_state case as it has been moved in front of the switch statement in "do_altp2m_op". Changed the order of setting the new altp2m state (depending on setting/resetting the state) in HVMOP_altp2m_set_domain_state case. Removed the call to altp2m_vcpu_reset from altp2m_vcpu_initialize, as the p2midx is set right after the call to 0, representing the default view. Moved the define "vcpu_altp2m" from domain.h to altp2m.h to avoid defining altp2m-related functionality in multiple files. Also renamed "vcpu_altp2m" to "altp2m_vcpu". Declared the function "p2m_flush_tlb" as static, as it is not called from altp2m.h anymore. Exported the function "altp2m_get_altp2m" in altp2m.h. Exchanged the check "altp2m_vttbr[idx] == INVALID_VTTBR" for "altp2m_p2m[idx] == NULL" in "altp2m_init_by_id". Set the field p2m->access_required to false by default. v4: Removed unnecessary initialization in "altp2m_init_helper". Move the field "active_vcpus" in "struct p2m_domain" out of this commit. Set "d->arch.altp2m_active" to the provided new state only once instead of for each vCPU. Move the definition of the macro INVALID_ALTP2M to a common place in a separate commit. ARM supports an external-only interface to the altp2m subsystem, i.e., the guest does not have access to the altp2m subsystem. Thus, we remove the check for the current vcpu in the function altp2m_vcpu_initialize; there is no scenario in which a guest is allowed to initialize the altp2m subsystem for itself. Cosmetic fixes. --- xen/arch/arm/altp2m.c | 97 ++++++++++++++++++++++++++++++++++++++++++++ xen/arch/arm/hvm.c | 30 +++++++++++++- xen/include/asm-arm/altp2m.h | 10 +++++ xen/include/asm-arm/domain.h | 3 ++ 4 files changed, 139 insertions(+), 1 deletion(-) diff --git a/xen/arch/arm/altp2m.c b/xen/arch/arm/altp2m.c index 9c06055a94..43e95c5681 100644 --- a/xen/arch/arm/altp2m.c +++ b/xen/arch/arm/altp2m.c @@ -20,6 +20,103 @@ #include <asm/p2m.h> #include <asm/altp2m.h> +struct p2m_domain *altp2m_get_altp2m(struct vcpu *v) +{ + unsigned int idx = v->arch.ap2m_idx; + + if ( idx == INVALID_ALTP2M ) + return NULL; + + BUG_ON(idx >= MAX_ALTP2M); + + return v->domain->arch.altp2m_p2m[idx]; +} + +static void altp2m_vcpu_reset(struct vcpu *v) +{ + v->arch.ap2m_idx = INVALID_ALTP2M; +} + +void altp2m_vcpu_initialize(struct vcpu *v) +{ + /* + * ARM supports an external-only interface to the altp2m subsystem, i.e., + * the guest does not have access to the altp2m subsystem. Thus, we can + * simply pause the vcpu, as there is no scenario in which we initialize + * altp2m on the current vcpu. That is, the vcpu must be paused every time + * we initialize altp2m. + */ + vcpu_pause(v); + + v->arch.ap2m_idx = 0; + atomic_inc(&altp2m_get_altp2m(v)->active_vcpus); + + vcpu_unpause(v); +} + +void altp2m_vcpu_destroy(struct vcpu *v) +{ + struct p2m_domain *p2m; + + if ( v != current ) + vcpu_pause(v); + + if ( (p2m = altp2m_get_altp2m(v)) ) + atomic_dec(&p2m->active_vcpus); + + altp2m_vcpu_reset(v); + + if ( v != current ) + vcpu_unpause(v); +} + +static int altp2m_init_helper(struct domain *d, unsigned int idx) +{ + int rc; + struct p2m_domain *p2m = d->arch.altp2m_p2m[idx]; + + ASSERT(p2m == NULL); + + /* Allocate a new, zeroed altp2m view. */ + p2m = xzalloc(struct p2m_domain); + if ( p2m == NULL) + return -ENOMEM; + + p2m->p2m_class = p2m_alternate; + + /* Initialize the new altp2m view. */ + rc = p2m_init_one(d, p2m); + if ( rc ) + goto err; + + d->arch.altp2m_p2m[idx] = p2m; + + return rc; + +err: + xfree(p2m); + d->arch.altp2m_p2m[idx] = NULL; + + return rc; +} + +int altp2m_init_by_id(struct domain *d, unsigned int idx) +{ + int rc = -EINVAL; + + if ( idx >= MAX_ALTP2M ) + return rc; + + altp2m_lock(d); + + if ( d->arch.altp2m_p2m[idx] == NULL ) + rc = altp2m_init_helper(d, idx); + + altp2m_unlock(d); + + return rc; +} + int altp2m_init(struct domain *d) { spin_lock_init(&d->arch.altp2m_lock); diff --git a/xen/arch/arm/hvm.c b/xen/arch/arm/hvm.c index 43b8352cb7..ec8e259797 100644 --- a/xen/arch/arm/hvm.c +++ b/xen/arch/arm/hvm.c @@ -90,8 +90,36 @@ static int do_altp2m_op(XEN_GUEST_HANDLE_PARAM(void) arg) break; case HVMOP_altp2m_set_domain_state: - rc = -EOPNOTSUPP; + { + struct vcpu *v; + bool ostate, nstate; + + ostate = d->arch.altp2m_active; + nstate = !!a.u.domain_state.state; + + /* If the alternate p2m state has changed, handle appropriately */ + if ( (nstate != ostate) && + (ostate || !(rc = altp2m_init_by_id(d, 0))) ) + { + d->arch.altp2m_active = nstate; + + for_each_vcpu( d, v ) + { + if ( !ostate ) + altp2m_vcpu_initialize(v); + else + altp2m_vcpu_destroy(v); + } + + /* + * The altp2m_active state has been deactivated. It is now safe to + * flush all altp2m views -- including altp2m[0]. + */ + if ( ostate ) + altp2m_flush_complete(d); + } break; + } case HVMOP_altp2m_vcpu_enable_notify: rc = -EOPNOTSUPP; diff --git a/xen/include/asm-arm/altp2m.h b/xen/include/asm-arm/altp2m.h index e116cce25f..2ef88cec35 100644 --- a/xen/include/asm-arm/altp2m.h +++ b/xen/include/asm-arm/altp2m.h @@ -43,6 +43,16 @@ static inline uint16_t altp2m_vcpu_idx(const struct vcpu *v) int altp2m_init(struct domain *d); void altp2m_teardown(struct domain *d); +void altp2m_vcpu_initialize(struct vcpu *v); +void altp2m_vcpu_destroy(struct vcpu *v); + +/* Get current alternate p2m table. */ +struct p2m_domain *altp2m_get_altp2m(struct vcpu *v); + +/* Make a specific alternate p2m valid. */ +int altp2m_init_by_id(struct domain *d, + unsigned int idx); + /* Flush all the alternate p2m's for a domain. */ void altp2m_flush_complete(struct domain *d); diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h index 668f398dbf..fc16cb81fd 100644 --- a/xen/include/asm-arm/domain.h +++ b/xen/include/asm-arm/domain.h @@ -293,6 +293,9 @@ struct arch_vcpu struct vtimer phys_timer; struct vtimer virt_timer; bool_t vtimer_initialized; + + /* Alternate p2m index */ + uint16_t ap2m_idx; } __cacheline_aligned; void vcpu_show_execution_state(struct vcpu *); -- 2.13.3 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx https://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |