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: > > 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]? Works for me. > > +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. > > + > > +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. > > +{ > > + 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. > > + 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