Message ID | 1570129355-16005-4-git-send-email-mikelley@microsoft.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Enable Linux guests on Hyper-V on ARM64 | expand |
On 2019-10-03 20:12, Michael Kelley wrote: > Add ARM64-specific code to allocate memory with HV_HYP_PAGE_SIZE > size and alignment. These are for use when pages need to be shared > with Hyper-V. Separate functions are needed as the page size used > by Hyper-V may not be the same as the guest page size. Free > operations are rarely done, so no attempt is made to combine > freed pages into larger chunks. > > This code is built only when CONFIG_HYPERV is enabled. > > Signed-off-by: Michael Kelley <mikelley@microsoft.com> > --- > arch/arm64/hyperv/hv_init.c | 68 > ++++++++++++++++++++++++++++++++++++++++++ > include/asm-generic/mshyperv.h | 5 ++++ > 2 files changed, 73 insertions(+) > > diff --git a/arch/arm64/hyperv/hv_init.c > b/arch/arm64/hyperv/hv_init.c > index 6808bc8..9c294f6 100644 > --- a/arch/arm64/hyperv/hv_init.c > +++ b/arch/arm64/hyperv/hv_init.c > @@ -15,10 +15,78 @@ > #include <linux/export.h> > #include <linux/mm.h> > #include <linux/hyperv.h> > +#include <linux/spinlock.h> > +#include <linux/list.h> > +#include <linux/string.h> > #include <asm-generic/bug.h> > #include <asm/hyperv-tlfs.h> > #include <asm/mshyperv.h> > > + > +/* > + * Functions for allocating and freeing memory with size and > + * alignment HV_HYP_PAGE_SIZE. These functions are needed because > + * the guest page size may not be the same as the Hyper-V page > + * size. And while kalloc() could allocate the memory, it does not > + * guarantee the required alignment. So a separate small memory > + * allocator is needed. The free function is rarely used, so it > + * does not try to combine freed pages into larger chunks. Is this still needed now that kmalloc has alignment guarantees (see 59bb47985c1d)? M.
From: Marc Zyngier <maz@kernel.org> Sent: Thursday, November 7, 2019 6:20 AM > > +/* > > + * Functions for allocating and freeing memory with size and > > + * alignment HV_HYP_PAGE_SIZE. These functions are needed because > > + * the guest page size may not be the same as the Hyper-V page > > + * size. And while kalloc() could allocate the memory, it does not > > + * guarantee the required alignment. So a separate small memory > > + * allocator is needed. The free function is rarely used, so it > > + * does not try to combine freed pages into larger chunks. > > Is this still needed now that kmalloc has alignment guarantees > (see 59bb47985c1d)? > The new kmalloc alignment guarantee is good news, and at least for now would allow these implementations to collapse to just kmalloc/kzalloc/kfree calls. My inclination is to keep the function calls as wrappers, since ISA neutral Hyper-V drivers are starting to use them, and future work on memory encryption in virtual environments may require special handling of pages like these that are shared between the host and guest. But they probably can be moved into the ISA neutral Hyper-V drivers instead of per arch. Michael
diff --git a/arch/arm64/hyperv/hv_init.c b/arch/arm64/hyperv/hv_init.c index 6808bc8..9c294f6 100644 --- a/arch/arm64/hyperv/hv_init.c +++ b/arch/arm64/hyperv/hv_init.c @@ -15,10 +15,78 @@ #include <linux/export.h> #include <linux/mm.h> #include <linux/hyperv.h> +#include <linux/spinlock.h> +#include <linux/list.h> +#include <linux/string.h> #include <asm-generic/bug.h> #include <asm/hyperv-tlfs.h> #include <asm/mshyperv.h> + +/* + * Functions for allocating and freeing memory with size and + * alignment HV_HYP_PAGE_SIZE. These functions are needed because + * the guest page size may not be the same as the Hyper-V page + * size. And while kalloc() could allocate the memory, it does not + * guarantee the required alignment. So a separate small memory + * allocator is needed. The free function is rarely used, so it + * does not try to combine freed pages into larger chunks. + * + * These functions are used by arm64 specific code as well as + * arch independent Hyper-V drivers. + */ + +static DEFINE_SPINLOCK(free_list_lock); +static struct list_head free_list = LIST_HEAD_INIT(free_list); + +void *hv_alloc_hyperv_page(void) +{ + int i; + struct list_head *hv_page; + unsigned long addr; + + BUILD_BUG_ON(HV_HYP_PAGE_SIZE > PAGE_SIZE); + + spin_lock(&free_list_lock); + if (list_empty(&free_list)) { + spin_unlock(&free_list_lock); + addr = __get_free_page(GFP_KERNEL); + spin_lock(&free_list_lock); + for (i = 0; i < PAGE_SIZE; i += HV_HYP_PAGE_SIZE) + list_add_tail((struct list_head *)(addr + i), + &free_list); + } + hv_page = free_list.next; + list_del(hv_page); + spin_unlock(&free_list_lock); + + return hv_page; +} +EXPORT_SYMBOL_GPL(hv_alloc_hyperv_page); + +void *hv_alloc_hyperv_zeroed_page(void) +{ + void *memp; + + memp = hv_alloc_hyperv_page(); + memset(memp, 0, HV_HYP_PAGE_SIZE); + + return memp; +} +EXPORT_SYMBOL_GPL(hv_alloc_hyperv_zeroed_page); + + +void hv_free_hyperv_page(unsigned long addr) +{ + if (!addr) + return; + spin_lock(&free_list_lock); + list_add((struct list_head *)addr, &free_list); + spin_unlock(&free_list_lock); +} +EXPORT_SYMBOL_GPL(hv_free_hyperv_page); + + /* * hv_do_hypercall- Invoke the specified hypercall */ diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h index 18d8e2d..f9f3b66 100644 --- a/include/asm-generic/mshyperv.h +++ b/include/asm-generic/mshyperv.h @@ -99,6 +99,11 @@ static inline void vmbus_signal_eom(struct hv_message *msg, u32 old_msg_type) void hv_setup_crash_handler(void (*handler)(struct pt_regs *regs)); void hv_remove_crash_handler(void); +void *hv_alloc_hyperv_page(void); +void *hv_alloc_hyperv_zeroed_page(void); +void hv_free_hyperv_page(unsigned long addr); + + #if IS_ENABLED(CONFIG_HYPERV) /* * Hypervisor's notion of virtual processor ID is different from
Add ARM64-specific code to allocate memory with HV_HYP_PAGE_SIZE size and alignment. These are for use when pages need to be shared with Hyper-V. Separate functions are needed as the page size used by Hyper-V may not be the same as the guest page size. Free operations are rarely done, so no attempt is made to combine freed pages into larger chunks. This code is built only when CONFIG_HYPERV is enabled. Signed-off-by: Michael Kelley <mikelley@microsoft.com> --- arch/arm64/hyperv/hv_init.c | 68 ++++++++++++++++++++++++++++++++++++++++++ include/asm-generic/mshyperv.h | 5 ++++ 2 files changed, 73 insertions(+)