|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH 2/2] xen/arm: Support runstate crossing pages
Hi,
> On 12 Jun 2020, at 13:14, Julien Grall <julien@xxxxxxx> wrote:
>
> Hi,
>
> On 11/06/2020 12:58, Bertrand Marquis wrote:
>> Add support for runstate area register with the structure crossing pages
>
> Well, this has always been supported until your previous patch. In general,
> we try to not break thing in a middle of the series so we can still bisect it.
>
> I think this patch can be simplified a lot by mapping the two page
> contiguously (see my previous answer). With that it would be feasible to fold
> this patch in #1.
I will dig into switching to something using vmap.
Worst case scenario we would consume 8k * 128 vCPU which is still 1M but should
be acceptable as it could simplify greatly the code.
>
>> The code is storing up to 2 pages reference during the hypercall.
>> During a context switch, the code is computing where the
>> state_entry_time is and is breaking the memcpy in 2 parts when it is
>> required.
>> Signed-off-by: Bertrand Marquis <bertrand.marquis@xxxxxxx>
>> ---
>> xen/arch/arm/domain.c | 101 +++++++++++++++++++++++++----------
>> xen/include/asm-arm/domain.h | 5 +-
>> 2 files changed, 76 insertions(+), 30 deletions(-)
>> diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
>> index 739059234f..d847cb00f2 100644
>> --- a/xen/arch/arm/domain.c
>> +++ b/xen/arch/arm/domain.c
>> @@ -280,11 +280,16 @@ void arch_cleanup_runstate_guest(struct vcpu *v)
>> {
>> spin_lock(&v->arch.runstate_guest.lock);
>> - /* cleanup previous page if any */
>> - if ( v->arch.runstate_guest.page )
>> + /* cleanup previous pages if any */
>> + if ( v->arch.runstate_guest.page[0] )
>> {
>> - put_page_and_type(v->arch.runstate_guest.page);
>> - v->arch.runstate_guest.page = NULL;
>> + put_page_and_type(v->arch.runstate_guest.page[0]);
>> + v->arch.runstate_guest.page[0] = NULL;
>> + if ( v->arch.runstate_guest.page[1] )
>> + {
>> + put_page_and_type(v->arch.runstate_guest.page[1]);
>> + v->arch.runstate_guest.page[1] = NULL;
>> + }
>
> I think this can be moved outside of the first if.
Agree
>
>> v->arch.runstate_guest.offset = 0;
>> }
>> @@ -294,26 +299,25 @@ void arch_cleanup_runstate_guest(struct vcpu *v)
>> int arch_setup_runstate_guest(struct vcpu *v,
>> struct vcpu_register_runstate_memory_area area)
>> {
>> - struct page_info *page;
>> + struct page_info *page[2] = {NULL,NULL};
>
> I don't think you need the temporary variable. You can directly update
> page[0] as it is protected by the lock. The nice benefits is you could take
> advantage of a common helper to cleanup and reduce the complexity of the code.
Would make sense yes (and remove the unlock everywhere).
I will try that, thanks for the hint.
>
>> unsigned offset;
>> spin_lock(&v->arch.runstate_guest.lock);
>> - /* cleanup previous page if any */
>> - if ( v->arch.runstate_guest.page )
>> + /* cleanup previous pages if any */
>> + if ( v->arch.runstate_guest.page[0] )
>> {
>> - put_page_and_type(v->arch.runstate_guest.page);
>> - v->arch.runstate_guest.page = NULL;
>> + put_page_and_type(v->arch.runstate_guest.page[0]);
>> + v->arch.runstate_guest.page[0] = NULL;
>> + if ( v->arch.runstate_guest.page[1] )
>> + {
>> + put_page_and_type(v->arch.runstate_guest.page[1]);
>> + v->arch.runstate_guest.page[1] = NULL;
>> + }
>> v->arch.runstate_guest.offset = 0;
>> }
>> offset = ((vaddr_t)area.addr.v) & ~PAGE_MASK;
>> - if ( offset > (PAGE_SIZE - sizeof(struct vcpu_runstate_info)) )
>> - {
>> - spin_unlock(&v->arch.runstate_guest.lock);
>> - gprintk(XENLOG_DEBUG, "Runstate is crossing pages\n");
>> - return -EINVAL;
>> - }
>> /* provided address must be aligned to a 64bit */
>> if ( offset % alignof(struct vcpu_runstate_info) )
>> @@ -323,15 +327,30 @@ int arch_setup_runstate_guest(struct vcpu *v,
>> return -EINVAL;
>> }
>> - page = get_page_from_gva(v, (vaddr_t)area.addr.v, GV2M_WRITE);
>> - if ( !page )
>> + page[0] = get_page_from_gva(v, (vaddr_t)area.addr.v, GV2M_WRITE);
>> + if ( !page[0] )
>> {
>> spin_unlock(&v->arch.runstate_guest.lock);
>> gprintk(XENLOG_DEBUG, "Runstate pointer is not mapped\n");
>> return -EINVAL;
>> }
>> - v->arch.runstate_guest.page = page;
>> + if ( offset > (PAGE_SIZE - sizeof(struct vcpu_runstate_info)) )
>> + {
>> + /* guest area is crossing pages */
>> + page[1] = get_page_from_gva(v, (vaddr_t)area.addr.v + PAGE_SIZE,
>> + GV2M_WRITE);
>> + if ( !page[1] )
>> + {
>> + put_page_and_type(v->arch.runstate_guest.page[0]);
> v->arch.runstate_guest.page[0] would be NULL as you set it afterwards. So you
> want to set v->arch.runstate_guest.page[0] beforehand.
Nice catch, should have been page[0] alone.
Thanks
Bertrand
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |