On Fri, Jan 08, 2021 at 12:15:08PM +0000, Quentin Perret wrote: > 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@xxxxxxxxxx> > + */ > + > +#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]? > + > +extern void clear_page(void *to); Stick this in a header? > + > +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? > +{ > + 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. 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). > + 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; Will