From patchwork Fri May 24 18:12:54 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrii Anisov X-Patchwork-Id: 10960273 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 87040112C for ; Fri, 24 May 2019 18:14:33 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 766D328917 for ; Fri, 24 May 2019 18:14:33 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 69C4F2896F; Fri, 24 May 2019 18:14:33 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.0 required=2.0 tests=BAYES_00,DKIM_ADSP_CUSTOM_MED, DKIM_INVALID,DKIM_SIGNED,FREEMAIL_FROM,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 990AD28A22 for ; Fri, 24 May 2019 18:14:32 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1hUEgj-00076W-4O; Fri, 24 May 2019 18:13:05 +0000 Received: from us1-rack-dfw2.inumbo.com ([104.130.134.6]) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1hUEgi-00076P-BI for xen-devel@lists.xenproject.org; Fri, 24 May 2019 18:13:04 +0000 X-Inumbo-ID: 9101c14b-7e4f-11e9-8980-bc764e045a96 Received: from mail-lf1-x143.google.com (unknown [2a00:1450:4864:20::143]) by us1-rack-dfw2.inumbo.com (Halon) with ESMTPS id 9101c14b-7e4f-11e9-8980-bc764e045a96; Fri, 24 May 2019 18:13:02 +0000 (UTC) Received: by mail-lf1-x143.google.com with SMTP id y10so7815863lfl.3 for ; Fri, 24 May 2019 11:13:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id; bh=1VhFGqpRzYi36j0UdsAC5u3jd3GfJ2G+kRwRwEcdc1s=; b=SSg6jnrLlQg9Gdu8xPp7SwIaxEFRHE7ImaNawJ5oAhJRpxWRJlQhI00kwWOKIeWjrt Kdi9NcTTvPZCP8CJT8u22+/c2Bp14cqS1ICaKH7r9vj9aqJ5eLJE6ChPA5aaGO1WTItF MrKg+jrSR6RcDFILMRHPcLlmo0UJaGxTTfWJ1IlmmpBxqR4Dps60lTqEoIJ2iSQpMbAK Rs5DWzkeXkUYCgs+k4yKdSk65ok+b0bvNuyZbIOyOF5wO2wnZn4ngEB8s/Tx94Dul9ly gcz/6jh52tBFNJlT7dOVKriWNqlLWaRRXYjXQdAK182csUZ0zwPjZhK//MhBT5/TzqS6 Lixw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=1VhFGqpRzYi36j0UdsAC5u3jd3GfJ2G+kRwRwEcdc1s=; b=GVct12bcM2boDKmOV78TGujtmTdfpCX5k2YD7tLtbDNZyQS3ebIjeM2U81k/TQx/sG fIWcFF5HYs9+0bFvb9vPMAetONjuzcZ2IUBoCtAm7AUbtk/EEkGk26F/XgAnQd0cH3pe JUIk6pHN+7tCRehsg0QZALIT3sDoUxCu3bhInM6UHEPejXHY+R23jnZBXVttRgcg0DSD lIK6UJVNCCOr8mJJL/ABjCkB5jNfJqRu3OnSm/HlcVyevHWxSbBVvCL0P3K3oPUFMrL3 mDFetAiqCZEmtVjl5De6eD9vI8nlulAGD9CtEgl9+ODZ7nr9zAOK4mUBo59B4LkuKoot Z1eQ== X-Gm-Message-State: APjAAAUumn5QXsS3FhpI0xotCG8kJYHjpoXT+i1YVWyJyI2mteTz+Nxx KeWGCikVm3yNxXfemF6El/k= X-Google-Smtp-Source: APXvYqwQXezgNJ4ZHOtmb0vBiUcYIaKn7Eo0PNkuaif5t0zFk9vUMaqukHqO1WLc3yl+xqZbqJg5uQ== X-Received: by 2002:a19:6b04:: with SMTP id d4mr23648108lfa.57.1558721580500; Fri, 24 May 2019 11:13:00 -0700 (PDT) Received: from aanisov-work.kyiv.epam.com (ll-22.209.223.85.sovam.net.ua. [85.223.209.22]) by smtp.gmail.com with ESMTPSA id m25sm629438ljj.92.2019.05.24.11.12.58 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 24 May 2019 11:12:59 -0700 (PDT) From: Andrii Anisov To: Date: Fri, 24 May 2019 21:12:54 +0300 Message-Id: <1558721577-13958-1-git-send-email-andrii.anisov@gmail.com> X-Mailer: git-send-email 2.7.4 Subject: [Xen-devel] [PATCH RFC 2] [DO NOT APPLY] introduce VCPUOP_register_runstate_phys_memory_area hypercall X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Stefano Stabellini , Andrii Anisov , Konrad Rzeszutek Wilk , George Dunlap , Andrew Cooper , Ian Jackson , Tim Deegan , Julien Grall , Jan Beulich , xen-devel@lists.xenproject.org, Wei Liu MIME-Version: 1.0 Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" X-Virus-Scanned: ClamAV using ClamSMTP From: Andrii Anisov An RFC version of the runstate registration with phys address. Runstate area access is implemented with mapping on each update once for all accesses. Signed-off-by: Andrii Anisov --- xen/arch/arm/domain.c | 63 ++++++++++++++++++++++++++--- xen/common/domain.c | 101 ++++++++++++++++++++++++++++++++++++++++++++-- xen/include/public/vcpu.h | 15 +++++++ xen/include/xen/sched.h | 28 +++++++++---- 4 files changed, 190 insertions(+), 17 deletions(-) diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c index a9f7ff5..04c4cff 100644 --- a/xen/arch/arm/domain.c +++ b/xen/arch/arm/domain.c @@ -274,17 +274,15 @@ static void ctxt_switch_to(struct vcpu *n) virt_timer_restore(n); } -/* Update per-VCPU guest runstate shared memory area (if registered). */ -static void update_runstate_area(struct vcpu *v) +static void update_runstate_by_gvaddr(struct vcpu *v) { void __user *guest_handle = NULL; - if ( guest_handle_is_null(runstate_guest(v)) ) - return; + ASSERT(!guest_handle_is_null(runstate_guest_virt(v))); if ( VM_ASSIST(v->domain, runstate_update_flag) ) { - guest_handle = &v->runstate_guest.p->state_entry_time + 1; + guest_handle = &v->runstate_guest.virt.p->state_entry_time + 1; guest_handle--; v->runstate.state_entry_time |= XEN_RUNSTATE_UPDATE; __raw_copy_to_guest(guest_handle, @@ -292,7 +290,7 @@ static void update_runstate_area(struct vcpu *v) smp_wmb(); } - __copy_to_guest(runstate_guest(v), &v->runstate, 1); + __copy_to_guest(runstate_guest_virt(v), &v->runstate, 1); if ( guest_handle ) { @@ -303,6 +301,58 @@ static void update_runstate_area(struct vcpu *v) } } +extern int map_runstate_area(struct vcpu *v, struct vcpu_runstate_info **area); +extern void unmap_runstate_area(struct vcpu_runstate_info *area); + +static void update_runstate_by_gpaddr(struct vcpu *v) +{ + struct vcpu_runstate_info *runstate; + + if ( map_runstate_area(v, &runstate) ) + return; + + if ( VM_ASSIST(v->domain, runstate_update_flag) ) + { + runstate->state_entry_time |= XEN_RUNSTATE_UPDATE; + smp_wmb(); + v->runstate.state_entry_time |= XEN_RUNSTATE_UPDATE; + } + + memcpy(runstate, &v->runstate, sizeof(v->runstate)); + + if ( VM_ASSIST(v->domain, runstate_update_flag) ) + { + runstate->state_entry_time &= ~XEN_RUNSTATE_UPDATE; + smp_wmb(); + v->runstate.state_entry_time &= ~XEN_RUNSTATE_UPDATE; + } + + unmap_runstate_area(runstate); +} + +/* Update per-VCPU guest runstate shared memory area (if registered). */ +static void update_runstate_area(struct vcpu *v) +{ + if ( xchg(&v->runstate_in_use, 1) ) + return; + + switch ( v->runstate_guest_type ) + { + case RUNSTATE_NONE: + break; + + case RUNSTATE_VADDR: + update_runstate_by_gvaddr(v); + break; + + case RUNSTATE_PADDR: + update_runstate_by_gpaddr(v); + break; + } + + xchg(&v->runstate_in_use, 0); +} + static void schedule_tail(struct vcpu *prev) { ctxt_switch_from(prev); @@ -998,6 +1048,7 @@ long do_arm_vcpu_op(int cmd, unsigned int vcpuid, XEN_GUEST_HANDLE_PARAM(void) a { case VCPUOP_register_vcpu_info: case VCPUOP_register_runstate_memory_area: + case VCPUOP_register_runstate_phys_memory_area: return do_vcpu_op(cmd, vcpuid, arg); default: return -EINVAL; diff --git a/xen/common/domain.c b/xen/common/domain.c index 32bca8d..f167a68 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -700,6 +700,68 @@ int rcu_lock_live_remote_domain_by_id(domid_t dom, struct domain **d) return 0; } +void unmap_runstate_area(struct vcpu_runstate_info *area) +{ + mfn_t mfn; + + ASSERT(area != NULL); + + mfn = _mfn(domain_page_map_to_mfn(area)); + + unmap_domain_page_global((void *) + ((unsigned long)area & + PAGE_MASK)); + + put_page_and_type(mfn_to_page(mfn)); +} + +int map_runstate_area(struct vcpu *v, struct vcpu_runstate_info **area) +{ + unsigned long offset = v->runstate_guest.phys & ~PAGE_MASK; + gfn_t gfn = gaddr_to_gfn(v->runstate_guest.phys); + struct domain *d = v->domain; + void *mapping; + struct page_info *page; + size_t size = sizeof(struct vcpu_runstate_info); + + 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; + } + + *area = mapping + offset; + + return 0; +} + +static void discard_runstate_area(struct vcpu *v) +{ + v->runstate_guest_type = RUNSTATE_NONE; +} + +static void discard_runstate_area_locked(struct vcpu *v) +{ + while ( xchg(&v->runstate_in_use, 1) ); + discard_runstate_area(v); + xchg(&v->runstate_in_use, 0); +} + int domain_kill(struct domain *d) { int rc = 0; @@ -738,7 +800,10 @@ int domain_kill(struct domain *d) if ( cpupool_move_domain(d, cpupool0) ) return -ERESTART; for_each_vcpu ( d, v ) + { + discard_runstate_area_locked(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 +1257,7 @@ int domain_soft_reset(struct domain *d) for_each_vcpu ( d, v ) { - set_xen_guest_handle(runstate_guest(v), NULL); + discard_runstate_area_locked(v); unmap_vcpu_info(v); } @@ -1520,18 +1585,46 @@ long do_vcpu_op(int cmd, unsigned int vcpuid, XEN_GUEST_HANDLE_PARAM(void) arg) break; rc = 0; - runstate_guest(v) = area.addr.h; + + while( xchg(&v->runstate_in_use, 1) == 0); + + discard_runstate_area(v); + + runstate_guest_virt(v) = area.addr.h; + v->runstate_guest_type = RUNSTATE_VADDR; if ( v == current ) { - __copy_to_guest(runstate_guest(v), &v->runstate, 1); + __copy_to_guest(runstate_guest_virt(v), &v->runstate, 1); } else { vcpu_runstate_get(v, &runstate); - __copy_to_guest(runstate_guest(v), &runstate, 1); + __copy_to_guest(runstate_guest_virt(v), &runstate, 1); } + xchg(&v->runstate_in_use, 0); + + break; + } + + case VCPUOP_register_runstate_phys_memory_area: + { + struct vcpu_register_runstate_memory_area area; + + rc = -EFAULT; + if ( copy_from_guest(&area, arg, 1) ) + break; + + while( xchg(&v->runstate_in_use, 1) == 0); + + discard_runstate_area(v); + v->runstate_guest.phys = area.addr.p; + v->runstate_guest_type = RUNSTATE_PADDR; + + xchg(&v->runstate_in_use, 0); + rc = 0; + break; } diff --git a/xen/include/public/vcpu.h b/xen/include/public/vcpu.h index 3623af9..d7da4a3 100644 --- a/xen/include/public/vcpu.h +++ b/xen/include/public/vcpu.h @@ -235,6 +235,21 @@ struct vcpu_register_time_memory_area { typedef struct vcpu_register_time_memory_area vcpu_register_time_memory_area_t; DEFINE_XEN_GUEST_HANDLE(vcpu_register_time_memory_area_t); +/* + * Register a shared memory area from which the guest may obtain its own + * runstate information without needing to execute a hypercall. + * Notes: + * 1. The registered address must be guest's physical address. + * 2. The registered runstate area should not cross page boundary. + * 3. Only one shared area may be registered per VCPU. The shared area is + * updated by the hypervisor each time the VCPU is scheduled. Thus + * runstate.state will always be RUNSTATE_running and + * runstate.state_entry_time will indicate the system time at which the + * VCPU was last scheduled to run. + * @extra_arg == pointer to vcpu_register_runstate_memory_area structure. + */ +#define VCPUOP_register_runstate_phys_memory_area 14 + #endif /* __XEN_PUBLIC_VCPU_H__ */ /* diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h index edee52d..8ac597b 100644 --- a/xen/include/xen/sched.h +++ b/xen/include/xen/sched.h @@ -163,17 +163,31 @@ struct vcpu void *sched_priv; /* scheduler-specific data */ struct vcpu_runstate_info runstate; + + enum { + RUNSTATE_NONE = 0, + RUNSTATE_PADDR = 1, + RUNSTATE_VADDR = 2, + } runstate_guest_type; + + unsigned long runstate_in_use; + + union + { #ifndef CONFIG_COMPAT -# define runstate_guest(v) ((v)->runstate_guest) - XEN_GUEST_HANDLE(vcpu_runstate_info_t) runstate_guest; /* guest address */ +# define runstate_guest_virt(v) ((v)->runstate_guest.virt) + XEN_GUEST_HANDLE(vcpu_runstate_info_t) virt; /* guest address */ #else -# define runstate_guest(v) ((v)->runstate_guest.native) - union { - XEN_GUEST_HANDLE(vcpu_runstate_info_t) native; - XEN_GUEST_HANDLE(vcpu_runstate_info_compat_t) compat; - } runstate_guest; /* guest address */ +# define runstate_guest_virt(v) ((v)->runstate_guest.virt.native) + union { + XEN_GUEST_HANDLE(vcpu_runstate_info_t) native; + XEN_GUEST_HANDLE(vcpu_runstate_info_compat_t) compat; + } virt; /* guest address */ #endif + paddr_t phys; + } runstate_guest; + /* last time when vCPU is scheduled out */ uint64_t last_run_time;