Re: [RFC PATCH v2 10/26] KVM: arm64: Introduce an early Hyp page allocator
From: Quentin Perret <hidden>
Date: 2021-02-02 09:46:08
Also in:
kvmarm, linux-devicetree, lkml
On Monday 01 Feb 2021 at 19:00:08 (+0000), Will Deacon wrote:
On Fri, Jan 08, 2021 at 12:15:08PM +0000, Quentin Perret wrote:quoted
diff --git a/arch/arm64/kvm/hyp/nvhe/early_alloc.c b/arch/arm64/kvm/hyp/nvhe/early_alloc.c new file mode 100644 index 000000000000..de4c45662970 --- /dev/null +++ b/arch/arm64/kvm/hyp/nvhe/early_alloc.c@@ -0,0 +1,60 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2020 Google LLC + * Author: Quentin Perret <qperret@google.com> + */ + +#include <asm/kvm_pgtable.h> + +#include <nvhe/memory.h> + +struct kvm_pgtable_mm_ops hyp_early_alloc_mm_ops; +s64 __ro_after_init hyp_physvirt_offset; + +static unsigned long base; +static unsigned long end; +static unsigned long cur; + +unsigned long hyp_early_alloc_nr_pages(void) +{ + return (cur - base) >> PAGE_SHIFT; +}nit: but I find this function name confusing (it's returning the number of _allocated_ pages, not the number of _free_ pages!). How about something like hyp_early_alloc_size() to match hyp_s1_pgtable_size() which you add later? [and move the shift out to the caller]?
Works for me.
quoted
+extern void clear_page(void *to);Stick this in a header?
Right, that, or perhaps just use asm/page.h directly -- I _think_ that should work fine assuming with have the correct symbol aliasing in place.
quoted
+ +void *hyp_early_alloc_contig(unsigned int nr_pages)I think order might make more sense, or do you need to allocate non-power-of-2 batches of pages?
Indeed, I allocate page-aligned blobs of arbitrary size (e.g. divide_memory_pool() in patch 16), so I prefer it that way.
quoted
+{ + unsigned long ret = cur, i, p; + + if (!nr_pages) + return NULL; + + cur += nr_pages << PAGE_SHIFT; + if (cur > end) {This would mean that concurrent hyp_early_alloc_nr_pages() would transiently give the wrong answer. Might be worth sticking the locking expectations with the function prototypes.
This is only called from a single CPU from a non-preemptible section, so that is not a problem. But yes, I'll stick a comment.
That said, maybe it would be better to write this check as: if (end - cur < (nr_pages << PAGE_SHIFT)) as that also removes the need to worry about overflow if nr_pages is huge (which would be a bug in the hypervisor, which we would then catch here).
Sounds good.
quoted
+ cur = ret; + return NULL; + } + + for (i = 0; i < nr_pages; i++) { + p = ret + (i << PAGE_SHIFT); + clear_page((void *)(p)); + } + + return (void *)ret; +} + +void *hyp_early_alloc_page(void *arg) +{ + return hyp_early_alloc_contig(1); +} + +void hyp_early_alloc_init(unsigned long virt, unsigned long size) +{ + base = virt; + end = virt + size; + cur = virt;nit: base = cur = virt;
Ack. Thanks for the review, Quentin _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel