Loading arch/arm64/configs/vendor/genericarmv8-64_defconfig +1 −0 Original line number Diff line number Diff line Loading @@ -335,6 +335,7 @@ CONFIG_HAVEN_DRIVERS=y CONFIG_HH_MSGQ=y CONFIG_HH_RM_DRV=y CONFIG_HH_DBL=y CONFIG_HH_MEM_NOTIFIER=y CONFIG_VIRTIO_PCI=y CONFIG_VIRTIO_BALLOON=y CONFIG_VIRTIO_MMIO=y Loading arch/arm64/configs/vendor/lahaina_GKI.config +1 −0 Original line number Diff line number Diff line Loading @@ -146,6 +146,7 @@ CONFIG_VIRT_DRIVERS=y CONFIG_HAVEN_DRIVERS=y CONFIG_HH_MSGQ=m CONFIG_HH_RM_DRV=m CONFIG_HH_MEM_NOTIFIER=m CONFIG_HH_DBL=m CONFIG_HVC_HAVEN=m # CONFIG_HVC_HAVEN_CONSOLE is not set Loading drivers/virt/haven/Kconfig +12 −0 Original line number Diff line number Diff line Loading @@ -78,4 +78,16 @@ config HH_IRQ_LEND supports sharing these interrupts. The follows RM recommended protocol. config HH_MEM_NOTIFIER tristate "Haven Memory Resource Notification Framework" depends on HH_RM_DRV help The Haven Resource Manager allows for different memory resources to be transferred across virtual machines with different notification labels assigned to each resource to aid in distinguishing them. Enabling the Haven Memory Resource Notification Framework provides an interface for clients to transmit memory resources between virtual machines, and register callbacks that get invoked only when notifications pertaining to their memory resources arrive. endif drivers/virt/haven/Makefile +1 −0 Original line number Diff line number Diff line Loading @@ -5,3 +5,4 @@ obj-$(CONFIG_HH_RM_DRV) += hh_rm_drv.o hh_rm_drv-y := hh_rm_core.o hh_rm_iface.o obj-$(CONFIG_HH_DBL) += hh_dbl.o obj-$(CONFIG_HH_IRQ_LEND) += hh_irq_lend.o obj-$(CONFIG_HH_MEM_NOTIFIER) += hh_mem_notifier.o drivers/virt/haven/hh_mem_notifier.c 0 → 100644 +151 −0 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2020, The Linux Foundation. All rights reserved. * */ #include <linux/haven/hh_mem_notifier.h> #include <linux/list.h> #include <linux/module.h> #include <linux/mutex.h> #include <linux/notifier.h> #include <linux/slab.h> struct mem_notifier_entry { hh_mem_notifier_handler handler; void *data; }; static DEFINE_MUTEX(mem_notifier_entries_lock); static struct mem_notifier_entry mem_notifier_entries[HH_MEM_NOTIFIER_TAG_MAX]; static bool hh_mem_notifier_tag_valid(enum hh_mem_notifier_tag tag) { return tag >= 0 && tag < HH_MEM_NOTIFIER_TAG_MAX; } /** * hh_mem_notifier_register: Bind a callback and arbitrary data to a particular * notification tag. The callback will be invoked when * the Haven MEM_SHARED and MEM_RELEASED notifications * involving the tag that was registered with arrive * at the VM. * @tag: The tag for which the caller would like to receive MEM_SHARED and * MEM_RELEASED notifications for * @handler: The handler that will be invoked when a MEM_SHARED or MEM_RELEASED * notification pertaining to @tag arrives at the VM. The handler will * also be invoked with a pointer to caller specific data, as well as * the original MEM_SHARED/MEM_RELEASED payload from the resource * manager. * @data: The data that should be passed to @handler when it is invoked * * On success, the function will return a cookie. Otherwise, the function will * return an error, and thus, callers should use IS_ERR() to check for any * errors. The cookie must be used when unregistering the handler from the * tag. */ void *hh_mem_notifier_register(enum hh_mem_notifier_tag tag, hh_mem_notifier_handler handler, void *data) { struct mem_notifier_entry *entry; if (!hh_mem_notifier_tag_valid(tag) || !handler) return ERR_PTR(-EINVAL); mutex_lock(&mem_notifier_entries_lock); entry = &mem_notifier_entries[tag]; if (entry->handler) { mutex_unlock(&mem_notifier_entries_lock); return ERR_PTR(-EEXIST); } entry->handler = handler; entry->data = data; mutex_unlock(&mem_notifier_entries_lock); return entry; } EXPORT_SYMBOL(hh_mem_notifier_register); /** * hh_mem_notifier_unregister: Unregister for memory notifier notifications * with respect to a particular tag. * @cookie: The cookie returned by hh_mem_notifier_register * * On success, the function will unbind the handler specified in * hh_mem_notifier_register from the tag, preventing the handler from being * invoked when subsequent MEM_SHARED/MEM_RELEASED notifications pertaining * to the tag arrive. */ void hh_mem_notifier_unregister(void *cookie) { struct mem_notifier_entry *entry = cookie; if (!cookie) return; mutex_lock(&mem_notifier_entries_lock); entry->handler = NULL; entry->data = NULL; mutex_unlock(&mem_notifier_entries_lock); } EXPORT_SYMBOL(hh_mem_notifier_unregister); static enum hh_mem_notifier_tag hh_mem_notifier_get_tag(unsigned long action, void *msg) { return action == HH_RM_NOTIF_MEM_SHARED ? ((struct hh_rm_notif_mem_shared_payload *)msg)->mem_info_tag : ((struct hh_rm_notif_mem_released_payload *)msg)->mem_info_tag; } static int hh_mem_notifier_call(struct notifier_block *nb, unsigned long action, void *msg) { struct mem_notifier_entry *entry; enum hh_mem_notifier_tag tag; hh_mem_notifier_handler handler = NULL; void *data; if ((action != HH_RM_NOTIF_MEM_SHARED) && (action != HH_RM_NOTIF_MEM_RELEASED)) return NOTIFY_DONE; tag = hh_mem_notifier_get_tag(action, msg); if (!hh_mem_notifier_tag_valid(tag)) return NOTIFY_DONE; mutex_lock(&mem_notifier_entries_lock); entry = &mem_notifier_entries[tag]; handler = entry->handler; data = entry->data; mutex_unlock(&mem_notifier_entries_lock); if (handler) handler(tag, action, data, msg); return NOTIFY_OK; } static struct notifier_block hh_mem_notifier_blk = { .notifier_call = hh_mem_notifier_call, }; static int __init hh_mem_notifier_init(void) { int ret = hh_rm_register_notifier(&hh_mem_notifier_blk); if (ret) pr_err("%s: registration with RM notifier failed rc: %d\n", __func__, ret); return ret; } module_init(hh_mem_notifier_init); static void __exit hh_mem_notifier_exit(void) { hh_rm_unregister_notifier(&hh_mem_notifier_blk); } module_exit(hh_mem_notifier_exit); MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("Qualcomm Technologies, Inc. Haven Memory Notifier"); Loading
arch/arm64/configs/vendor/genericarmv8-64_defconfig +1 −0 Original line number Diff line number Diff line Loading @@ -335,6 +335,7 @@ CONFIG_HAVEN_DRIVERS=y CONFIG_HH_MSGQ=y CONFIG_HH_RM_DRV=y CONFIG_HH_DBL=y CONFIG_HH_MEM_NOTIFIER=y CONFIG_VIRTIO_PCI=y CONFIG_VIRTIO_BALLOON=y CONFIG_VIRTIO_MMIO=y Loading
arch/arm64/configs/vendor/lahaina_GKI.config +1 −0 Original line number Diff line number Diff line Loading @@ -146,6 +146,7 @@ CONFIG_VIRT_DRIVERS=y CONFIG_HAVEN_DRIVERS=y CONFIG_HH_MSGQ=m CONFIG_HH_RM_DRV=m CONFIG_HH_MEM_NOTIFIER=m CONFIG_HH_DBL=m CONFIG_HVC_HAVEN=m # CONFIG_HVC_HAVEN_CONSOLE is not set Loading
drivers/virt/haven/Kconfig +12 −0 Original line number Diff line number Diff line Loading @@ -78,4 +78,16 @@ config HH_IRQ_LEND supports sharing these interrupts. The follows RM recommended protocol. config HH_MEM_NOTIFIER tristate "Haven Memory Resource Notification Framework" depends on HH_RM_DRV help The Haven Resource Manager allows for different memory resources to be transferred across virtual machines with different notification labels assigned to each resource to aid in distinguishing them. Enabling the Haven Memory Resource Notification Framework provides an interface for clients to transmit memory resources between virtual machines, and register callbacks that get invoked only when notifications pertaining to their memory resources arrive. endif
drivers/virt/haven/Makefile +1 −0 Original line number Diff line number Diff line Loading @@ -5,3 +5,4 @@ obj-$(CONFIG_HH_RM_DRV) += hh_rm_drv.o hh_rm_drv-y := hh_rm_core.o hh_rm_iface.o obj-$(CONFIG_HH_DBL) += hh_dbl.o obj-$(CONFIG_HH_IRQ_LEND) += hh_irq_lend.o obj-$(CONFIG_HH_MEM_NOTIFIER) += hh_mem_notifier.o
drivers/virt/haven/hh_mem_notifier.c 0 → 100644 +151 −0 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2020, The Linux Foundation. All rights reserved. * */ #include <linux/haven/hh_mem_notifier.h> #include <linux/list.h> #include <linux/module.h> #include <linux/mutex.h> #include <linux/notifier.h> #include <linux/slab.h> struct mem_notifier_entry { hh_mem_notifier_handler handler; void *data; }; static DEFINE_MUTEX(mem_notifier_entries_lock); static struct mem_notifier_entry mem_notifier_entries[HH_MEM_NOTIFIER_TAG_MAX]; static bool hh_mem_notifier_tag_valid(enum hh_mem_notifier_tag tag) { return tag >= 0 && tag < HH_MEM_NOTIFIER_TAG_MAX; } /** * hh_mem_notifier_register: Bind a callback and arbitrary data to a particular * notification tag. The callback will be invoked when * the Haven MEM_SHARED and MEM_RELEASED notifications * involving the tag that was registered with arrive * at the VM. * @tag: The tag for which the caller would like to receive MEM_SHARED and * MEM_RELEASED notifications for * @handler: The handler that will be invoked when a MEM_SHARED or MEM_RELEASED * notification pertaining to @tag arrives at the VM. The handler will * also be invoked with a pointer to caller specific data, as well as * the original MEM_SHARED/MEM_RELEASED payload from the resource * manager. * @data: The data that should be passed to @handler when it is invoked * * On success, the function will return a cookie. Otherwise, the function will * return an error, and thus, callers should use IS_ERR() to check for any * errors. The cookie must be used when unregistering the handler from the * tag. */ void *hh_mem_notifier_register(enum hh_mem_notifier_tag tag, hh_mem_notifier_handler handler, void *data) { struct mem_notifier_entry *entry; if (!hh_mem_notifier_tag_valid(tag) || !handler) return ERR_PTR(-EINVAL); mutex_lock(&mem_notifier_entries_lock); entry = &mem_notifier_entries[tag]; if (entry->handler) { mutex_unlock(&mem_notifier_entries_lock); return ERR_PTR(-EEXIST); } entry->handler = handler; entry->data = data; mutex_unlock(&mem_notifier_entries_lock); return entry; } EXPORT_SYMBOL(hh_mem_notifier_register); /** * hh_mem_notifier_unregister: Unregister for memory notifier notifications * with respect to a particular tag. * @cookie: The cookie returned by hh_mem_notifier_register * * On success, the function will unbind the handler specified in * hh_mem_notifier_register from the tag, preventing the handler from being * invoked when subsequent MEM_SHARED/MEM_RELEASED notifications pertaining * to the tag arrive. */ void hh_mem_notifier_unregister(void *cookie) { struct mem_notifier_entry *entry = cookie; if (!cookie) return; mutex_lock(&mem_notifier_entries_lock); entry->handler = NULL; entry->data = NULL; mutex_unlock(&mem_notifier_entries_lock); } EXPORT_SYMBOL(hh_mem_notifier_unregister); static enum hh_mem_notifier_tag hh_mem_notifier_get_tag(unsigned long action, void *msg) { return action == HH_RM_NOTIF_MEM_SHARED ? ((struct hh_rm_notif_mem_shared_payload *)msg)->mem_info_tag : ((struct hh_rm_notif_mem_released_payload *)msg)->mem_info_tag; } static int hh_mem_notifier_call(struct notifier_block *nb, unsigned long action, void *msg) { struct mem_notifier_entry *entry; enum hh_mem_notifier_tag tag; hh_mem_notifier_handler handler = NULL; void *data; if ((action != HH_RM_NOTIF_MEM_SHARED) && (action != HH_RM_NOTIF_MEM_RELEASED)) return NOTIFY_DONE; tag = hh_mem_notifier_get_tag(action, msg); if (!hh_mem_notifier_tag_valid(tag)) return NOTIFY_DONE; mutex_lock(&mem_notifier_entries_lock); entry = &mem_notifier_entries[tag]; handler = entry->handler; data = entry->data; mutex_unlock(&mem_notifier_entries_lock); if (handler) handler(tag, action, data, msg); return NOTIFY_OK; } static struct notifier_block hh_mem_notifier_blk = { .notifier_call = hh_mem_notifier_call, }; static int __init hh_mem_notifier_init(void) { int ret = hh_rm_register_notifier(&hh_mem_notifier_blk); if (ret) pr_err("%s: registration with RM notifier failed rc: %d\n", __func__, ret); return ret; } module_init(hh_mem_notifier_init); static void __exit hh_mem_notifier_exit(void) { hh_rm_unregister_notifier(&hh_mem_notifier_blk); } module_exit(hh_mem_notifier_exit); MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("Qualcomm Technologies, Inc. Haven Memory Notifier");