From: Marc Zyngier <maz@kernel.org>
To: Kalesh Singh <kaleshsingh@google.com>
Cc: will@kernel.org, qperret@google.com, tabba@google.com,
surenb@google.com, kernel-team@android.com,
James Morse <james.morse@arm.com>,
Alexandru Elisei <alexandru.elisei@arm.com>,
Suzuki K Poulose <suzuki.poulose@arm.com>,
Catalin Marinas <catalin.marinas@arm.com>,
Mark Rutland <mark.rutland@arm.com>,
Ard Biesheuvel <ardb@kernel.org>,
Zenghui Yu <yuzenghui@huawei.com>,
Nick Desaulniers <ndesaulniers@google.com>,
Masahiro Yamada <masahiroy@kernel.org>,
Changbin Du <changbin.du@intel.com>,
linux-arm-kernel@lists.infradead.org,
kvmarm@lists.cs.columbia.edu, linux-kernel@vger.kernel.org
Subject: Re: [PATCH v7 2/6] KVM: arm64: Introduce pkvm_alloc_private_va_range()
Date: Mon, 11 Apr 2022 08:01:25 +0100 [thread overview]
Message-ID: <87a6cscddm.wl-maz@kernel.org> (raw)
In-Reply-To: <20220408200349.1529080-3-kaleshsingh@google.com>
On Fri, 08 Apr 2022 21:03:25 +0100,
Kalesh Singh <kaleshsingh@google.com> wrote:
>
> pkvm_hyp_alloc_private_va_range() can be used to reserve private VA ranges
> in the pKVM nVHE hypervisor. Allocations are aligned based on the order of
> the requested size.
>
> This will be used to implement stack guard pages for pKVM nVHE hypervisor
> (in a subsequent patch in the series).
>
> Credits to Quentin Perret <qperret@google.com> for the idea of moving
> private VA allocation out of __pkvm_create_private_mapping()
>
> Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
> Tested-by: Fuad Tabba <tabba@google.com>
> Reviewed-by: Fuad Tabba <tabba@google.com>
> ---
>
> Changes in v7:
> - Add Fuad's Reviewed-by and Tested-by tags.
>
> Changes in v6:
> - Update kernel-doc for pkvm_alloc_private_va_range() and add
> return description, per Stephen
> - Update pkvm_alloc_private_va_range() to return an int error code,
> per Stephen
> - Update __pkvm_create_private_mapping to return an in error code,
> per Quentin
> - Update callers of __pkvm_create_private_mapping() to handle new
> return value and params.
>
> Changes in v5:
> - Align private allocations based on the order of their size, per Marc
>
> Changes in v4:
> - Handle null ptr in pkvm_alloc_private_va_range() and replace
> IS_ERR_OR_NULL checks in callers with IS_ERR checks, per Fuad
> - Fix kernel-doc comments format, per Fuad
> - Format __pkvm_create_private_mapping() prototype args (< 80 col), per Fuad
>
> Changes in v3:
> - Handle null ptr in IS_ERR_OR_NULL checks, per Mark
>
> Changes in v2:
> - Allow specifying an alignment for the private VA allocations, per Marc
>
>
> arch/arm64/kvm/hyp/include/nvhe/mm.h | 6 ++-
> arch/arm64/kvm/hyp/nvhe/hyp-main.c | 18 ++++++-
> arch/arm64/kvm/hyp/nvhe/mm.c | 78 ++++++++++++++++++----------
> 3 files changed, 72 insertions(+), 30 deletions(-)
>
> diff --git a/arch/arm64/kvm/hyp/include/nvhe/mm.h b/arch/arm64/kvm/hyp/include/nvhe/mm.h
> index 2d08510c6cc1..42d8eb9bfe72 100644
> --- a/arch/arm64/kvm/hyp/include/nvhe/mm.h
> +++ b/arch/arm64/kvm/hyp/include/nvhe/mm.h
> @@ -19,8 +19,10 @@ int hyp_back_vmemmap(phys_addr_t phys, unsigned long size, phys_addr_t back);
> int pkvm_cpu_set_vector(enum arm64_hyp_spectre_vector slot);
> int pkvm_create_mappings(void *from, void *to, enum kvm_pgtable_prot prot);
> int pkvm_create_mappings_locked(void *from, void *to, enum kvm_pgtable_prot prot);
> -unsigned long __pkvm_create_private_mapping(phys_addr_t phys, size_t size,
> - enum kvm_pgtable_prot prot);
> +int __pkvm_create_private_mapping(phys_addr_t phys, size_t size,
> + enum kvm_pgtable_prot prot,
> + unsigned long *haddr);
> +int pkvm_alloc_private_va_range(size_t size, unsigned long *haddr);
>
> static inline void hyp_vmemmap_range(phys_addr_t phys, unsigned long size,
> unsigned long *start, unsigned long *end)
> diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
> index 5e2197db0d32..3cea4b6ac23e 100644
> --- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
> +++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
> @@ -160,7 +160,23 @@ static void handle___pkvm_create_private_mapping(struct kvm_cpu_context *host_ct
> DECLARE_REG(size_t, size, host_ctxt, 2);
> DECLARE_REG(enum kvm_pgtable_prot, prot, host_ctxt, 3);
>
> - cpu_reg(host_ctxt, 1) = __pkvm_create_private_mapping(phys, size, prot);
> + /*
> + * __pkvm_create_private_mapping() populates a pointer with the
> + * hypervisor start address of the allocation.
> + *
> + * However, handle___pkvm_create_private_mapping() hypercall crosses the
> + * EL1/EL2 boundary so the pointer would not be valid in this context.
> + *
> + * Instead pass the allocation address as the return value (or return
> + * ERR_PTR() on failure).
> + */
> + unsigned long haddr;
> + int err = __pkvm_create_private_mapping(phys, size, prot, &haddr);
> +
> + if (err)
> + haddr = (unsigned long)ERR_PTR(err);
> +
> + cpu_reg(host_ctxt, 1) = haddr;
> }
>
> static void handle___pkvm_prot_finalize(struct kvm_cpu_context *host_ctxt)
> diff --git a/arch/arm64/kvm/hyp/nvhe/mm.c b/arch/arm64/kvm/hyp/nvhe/mm.c
> index cdbe8e246418..670f11349070 100644
> --- a/arch/arm64/kvm/hyp/nvhe/mm.c
> +++ b/arch/arm64/kvm/hyp/nvhe/mm.c
> @@ -37,36 +37,60 @@ static int __pkvm_create_mappings(unsigned long start, unsigned long size,
> return err;
> }
>
> -unsigned long __pkvm_create_private_mapping(phys_addr_t phys, size_t size,
> - enum kvm_pgtable_prot prot)
> +/**
> + * pkvm_alloc_private_va_range - Allocates a private VA range.
> + * @size: The size of the VA range to reserve.
> + * @haddr: The hypervisor virtual start address of the allocation.
> + *
> + * The private virtual address (VA) range is allocated above __io_map_base
> + * and aligned based on the order of @size.
> + *
> + * Return: 0 on success or negative error code on failure.
> + */
> +int pkvm_alloc_private_va_range(size_t size, unsigned long *haddr)
> {
> - unsigned long addr;
> - int err;
> + unsigned long base, addr;
> + int ret = 0;
>
> hyp_spin_lock(&pkvm_pgd_lock);
>
> - size = PAGE_ALIGN(size + offset_in_page(phys));
> - addr = __io_map_base;
> - __io_map_base += size;
> + /* Align the allocation based on the order of its size */
> + addr = ALIGN(__io_map_base, PAGE_SIZE << get_order(size));
>
> - /* Are we overflowing on the vmemmap ? */
> - if (__io_map_base > __hyp_vmemmap) {
> - __io_map_base -= size;
> - addr = (unsigned long)ERR_PTR(-ENOMEM);
> - goto out;
> - }
> + /* The allocated size is always a multiple of PAGE_SIZE */
> + base = addr + PAGE_ALIGN(size);
>
> - err = kvm_pgtable_hyp_map(&pkvm_pgtable, addr, size, phys, prot);
> - if (err) {
> - addr = (unsigned long)ERR_PTR(err);
> - goto out;
> + /* Are we overflowing on the vmemmap ? */
> + if (!addr || base > __hyp_vmemmap)
> + ret = -ENOMEM;
> + else {
> + __io_map_base = base;
> + *haddr = addr;
> }
>
> - addr = addr + offset_in_page(phys);
> -out:
> hyp_spin_unlock(&pkvm_pgd_lock);
>
> - return addr;
> + return ret;
> +}
> +
> +int __pkvm_create_private_mapping(phys_addr_t phys, size_t size,
> + enum kvm_pgtable_prot prot,
> + unsigned long *haddr)
> +{
> + unsigned long addr;
> + int err;
> +
> + size += offset_in_page(phys);
I have the same comment as for the previous patch. Keep the ALIGN()
here in order to make the code readable (it is just an add+and on a
slow path).
> + err = pkvm_alloc_private_va_range(size, &addr);
> + if (err)
> + return err;
> +
> + err = __pkvm_create_mappings(addr, size, phys, prot);
> + if (err)
> + return err;
> +
> + *haddr = addr + offset_in_page(phys);
> + return err;
> }
>
> int pkvm_create_mappings_locked(void *from, void *to, enum kvm_pgtable_prot prot)
> @@ -146,7 +170,8 @@ int pkvm_cpu_set_vector(enum arm64_hyp_spectre_vector slot)
> int hyp_map_vectors(void)
> {
> phys_addr_t phys;
> - void *bp_base;
> + unsigned long bp_base;
> + int ret;
>
> if (!kvm_system_needs_idmapped_vectors()) {
> __hyp_bp_vect_base = __bp_harden_hyp_vecs;
> @@ -154,13 +179,12 @@ int hyp_map_vectors(void)
> }
>
> phys = __hyp_pa(__bp_harden_hyp_vecs);
> - bp_base = (void *)__pkvm_create_private_mapping(phys,
> - __BP_HARDEN_HYP_VECS_SZ,
> - PAGE_HYP_EXEC);
> - if (IS_ERR_OR_NULL(bp_base))
> - return PTR_ERR(bp_base);
> + ret = __pkvm_create_private_mapping(phys, __BP_HARDEN_HYP_VECS_SZ,
> + PAGE_HYP_EXEC, &bp_base);
> + if (ret)
> + return ret;
>
> - __hyp_bp_vect_base = bp_base;
> + __hyp_bp_vect_base = (void *)bp_base;
>
> return 0;
> }
Thanks,
M.
--
Without deviation from the norm, progress is not possible.
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
next prev parent reply other threads:[~2022-04-11 7:08 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-04-08 20:03 [PATCH v7 0/6] KVM: arm64: Hypervisor stack enhancements Kalesh Singh
2022-04-08 20:03 ` [PATCH v7 1/6] KVM: arm64: Introduce hyp_alloc_private_va_range() Kalesh Singh
2022-04-11 6:52 ` Marc Zyngier
2022-04-19 2:21 ` Kalesh Singh
2022-04-08 20:03 ` [PATCH v7 2/6] KVM: arm64: Introduce pkvm_alloc_private_va_range() Kalesh Singh
2022-04-11 7:01 ` Marc Zyngier [this message]
2022-04-08 20:03 ` [PATCH v7 3/6] KVM: arm64: Add guard pages for KVM nVHE hypervisor stack Kalesh Singh
2022-04-18 10:01 ` Marc Zyngier
2022-04-19 2:25 ` Kalesh Singh
2022-04-08 20:03 ` [PATCH v7 4/6] KVM: arm64: Add guard pages for pKVM (protected nVHE) " Kalesh Singh
2022-04-08 20:03 ` [PATCH v7 5/6] KVM: arm64: Detect and handle hypervisor stack overflows Kalesh Singh
2022-04-18 10:09 ` Marc Zyngier
2022-04-19 2:41 ` Kalesh Singh
2022-04-20 21:51 ` Kalesh Singh
2022-04-08 20:03 ` [PATCH v7 6/6] KVM: arm64: Symbolize the nVHE HYP addresses Kalesh Singh
2022-04-18 10:16 ` Marc Zyngier
2022-04-19 2:42 ` Kalesh Singh
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87a6cscddm.wl-maz@kernel.org \
--to=maz@kernel.org \
--cc=alexandru.elisei@arm.com \
--cc=ardb@kernel.org \
--cc=catalin.marinas@arm.com \
--cc=changbin.du@intel.com \
--cc=james.morse@arm.com \
--cc=kaleshsingh@google.com \
--cc=kernel-team@android.com \
--cc=kvmarm@lists.cs.columbia.edu \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mark.rutland@arm.com \
--cc=masahiroy@kernel.org \
--cc=ndesaulniers@google.com \
--cc=qperret@google.com \
--cc=surenb@google.com \
--cc=suzuki.poulose@arm.com \
--cc=tabba@google.com \
--cc=will@kernel.org \
--cc=yuzenghui@huawei.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).