diff --git a/tee_blackbox/guest/0001-add-poll-method-for-nfs.patch b/tee_blackbox/guest/0001-add-poll-method-for-nfs.patch new file mode 100644 index 0000000000000000000000000000000000000000..723546248109ec352812f9b67a0599a0f7663cf1 --- /dev/null +++ b/tee_blackbox/guest/0001-add-poll-method-for-nfs.patch @@ -0,0 +1,474 @@ +From eb37321c89af45b19b1ba2dd918a63030558b1f1 Mon Sep 17 00:00:00 2001 +From: zeus <1435901016@qq.com> +Date: Fri, 3 Jan 2025 11:44:44 +0800 +Subject: [PATCH] add poll method for nfs + +--- + drivers/char/Makefile | 1 + + drivers/char/poll_cq_kthread.c | 324 ++++++++++++++++++ + drivers/char/poll_cq_kthread.h | 17 + + drivers/infiniband/core/cq.c | 31 ++ + .../infiniband/core/ib_core_poll_kthread.h | 22 ++ + 5 files changed, 395 insertions(+) + create mode 100644 drivers/char/poll_cq_kthread.c + create mode 100644 drivers/char/poll_cq_kthread.h + create mode 100644 drivers/infiniband/core/ib_core_poll_kthread.h + +diff --git a/drivers/char/Makefile b/drivers/char/Makefile +index 109af71c5416..d7d5065430df 100644 +--- a/drivers/char/Makefile ++++ b/drivers/char/Makefile +@@ -46,3 +46,4 @@ obj-$(CONFIG_PS3_FLASH) += ps3flash.o + obj-$(CONFIG_XILLYBUS_CLASS) += xillybus/ + obj-$(CONFIG_POWERNV_OP_PANEL) += powernv-op-panel.o + obj-$(CONFIG_ADI) += adi.o ++obj-m += poll_cq_kthread.o +diff --git a/drivers/char/poll_cq_kthread.c b/drivers/char/poll_cq_kthread.c +new file mode 100644 +index 000000000000..88f36e7e4fba +--- /dev/null ++++ b/drivers/char/poll_cq_kthread.c +@@ -0,0 +1,324 @@ ++#include ++#include ++ ++#include ++#include ++ ++#include ++#include ++ ++#include "./poll_cq_kthread.h" ++#include "../infiniband/core/ib_core_poll_kthread.h" ++ ++#define INVALID_IB_POLL_CORE -1 ++/* A lock for concurrent access. */ ++static DEFINE_SPINLOCK(polling_kthread_spinlock); ++int debug_cq_poll_stat = 0; ++unsigned int poll_core; ++ ++struct task_struct *poll_cq_thread; ++struct task_struct *waker_polling_thread; ++ ++extern struct polling_kthread ib_cq_polling_kthread; ++ ++LIST_HEAD(global_ib_cq_poll_list); ++/* A lock for concurrent access. */ ++spinlock_t cq_list_lock; ++ ++void add_cq_to_poll_list(void *cq) ++{ ++ cq_poll_node_t *cq_node; ++ ++ cq_node = (cq_poll_node_t *)kmalloc(sizeof(cq_poll_node_t), GFP_ATOMIC); ++ ++ spin_lock_irq(&cq_list_lock); ++ cq_node->cq = cq; ++ cq_node->time_used_ns = 0; ++ cq_node->poll_cq_cnt = 0; ++ cq_node->max_time_ns = 0; ++ list_add_tail(&cq_node->list, &global_ib_cq_poll_list); ++ spin_unlock_irq(&cq_list_lock); ++} ++ ++void del_cq_from_poll_list(void *del_cq) ++{ ++ cq_poll_node_t *poll_node_entry, *poll_node_next; ++ void *curr_cq; ++ void *cq = del_cq; ++ ++ spin_lock_irq(&cq_list_lock); ++ list_for_each_entry_safe(poll_node_entry, poll_node_next, ++ &global_ib_cq_poll_list, list) { ++ curr_cq = poll_node_entry->cq; ++ if (!curr_cq) { ++ WARN_ONCE(1, "del_cq_from_poll_list: got NULL CQ 0x%p\n", ++ curr_cq); ++ list_del(&poll_node_entry->list); ++ kfree(poll_node_entry); ++ continue; ++ } ++ if (curr_cq == cq) { ++ list_del(&poll_node_entry->list); ++ kfree(poll_node_entry); ++ break; ++ } ++ } ++ spin_unlock_irq(&cq_list_lock); ++} ++ ++void clear_cq_poll_list(void) ++{ ++ cq_poll_node_t *entry, *next; ++ ++ spin_lock_irq(&cq_list_lock); ++ list_for_each_entry_safe(entry, next, &global_ib_cq_poll_list, list) { ++ list_del(&entry->list); ++ kfree(entry); ++ } ++ spin_unlock_irq(&cq_list_lock); ++ ++ INIT_LIST_HEAD(&global_ib_cq_poll_list); ++} ++ ++/* Obtain the timestamp through the register */ ++static unsigned long get_timestamp_ns(void) ++{ ++ unsigned long val, freq; ++ asm volatile("mrs %0, cntvct_el0" : "=r"(val)); ++ asm volatile("mrs %0, cntfrq_el0" : "=r"(freq)); ++ ++ /* should never happen */ ++ if (freq == 0) ++ return 0; ++ ++ return 1000000000 / freq * val; ++} ++ ++void cq_polling(void *data) ++{ ++ void *cq; ++ int completed = 0; ++ static unsigned long start_time_stamp, end_time_stamp, time_interval; ++ cq_poll_node_t *poll_node_entry, *poll_node_next; ++ ++ spin_lock_irq(&cq_list_lock); ++ list_for_each_entry_safe(poll_node_entry, poll_node_next, ++ &global_ib_cq_poll_list, list) { ++ cq = poll_node_entry->cq; ++ if (!cq) { ++ WARN_ONCE(1, "got NULL CQ 0x%p in poll list\n", cq); ++ continue; ++ } ++ start_time_stamp = get_timestamp_ns(); ++ completed = ib_poll_cq_thread(cq); ++ end_time_stamp = get_timestamp_ns(); ++ if (debug_cq_poll_stat && completed) { ++ time_interval = end_time_stamp - start_time_stamp; ++ poll_node_entry->time_used_ns += time_interval; ++ poll_node_entry->poll_cq_cnt++; ++ if (poll_node_entry->max_time_ns < time_interval) { ++ poll_node_entry->max_time_ns = time_interval; ++ } ++ } ++ } ++ spin_unlock_irq(&cq_list_lock); ++} ++ ++void wakeup_and_poll(struct task_struct *awakened_thread) ++{ ++ wake_up_process(awakened_thread); ++ ++ cq_polling(NULL); ++} ++ ++int polling_thread(void *data) ++{ ++ while(1) { ++ if (ib_cq_polling_kthread.use_polling_kthread) { ++ wakeup_and_poll(waker_polling_thread); ++ } ++ ++ set_current_state(TASK_INTERRUPTIBLE); ++ if (unlikely(kthread_should_stop())) { ++ set_current_state(TASK_RUNNING); ++ break; ++ } ++ schedule(); ++ } ++ ++ return 0; ++} ++ ++int polling_awaken_thread(void *data) ++{ ++ while(1) { ++ if (ib_cq_polling_kthread.use_polling_kthread) { ++ wakeup_and_poll(poll_cq_thread); ++ } ++ ++ set_current_state(TASK_INTERRUPTIBLE); ++ if (unlikely(kthread_should_stop())) { ++ set_current_state(TASK_RUNNING); ++ break; ++ } ++ schedule(); ++ } ++ ++ return 0; ++} ++ ++/* sysfs ui */ ++ ++static ssize_t ib_core_poll_cpu_show(struct kobject *kobj, ++ struct kobj_attribute *attr, char *buf) ++{ ++ int ret; ++ ++ if (ib_cq_polling_kthread.use_polling_kthread) { ++ ret = sprintf(buf, "Current polling core is: %u\n", poll_core); ++ } else { ++ ret = sprintf(buf, "Current polling thread is down\n"); ++ } ++ ++ return ret; ++} ++ ++static ssize_t ib_core_poll_cpu_store(struct kobject *kobj, ++ struct kobj_attribute *attr, const char *buf, ++ size_t count) ++{ ++ int input_poll_core; ++ unsigned int max_nr_cores = num_possible_cpus(); ++ ++ spin_lock(&polling_kthread_spinlock); ++ if (sscanf(buf, "%d", &input_poll_core) < 0) { ++ pr_err("Invalid input, input format: e.g. 8\n"); ++ goto err_inval; ++ } ++ if (input_poll_core == INVALID_IB_POLL_CORE) { ++ ib_cq_polling_kthread.use_polling_kthread = 0; ++ clear_cq_poll_list(); ++ goto out; ++ } ++ if (input_poll_core < 0 || input_poll_core >= max_nr_cores) { ++ pr_err("Invalid CPU core ID. Valid range is 0 to %u.\n", max_nr_cores - 1); ++ goto err_inval; ++ } ++ ib_cq_polling_kthread.use_polling_kthread = 1; ++ poll_core = (unsigned int)input_poll_core; ++ set_cpus_allowed_ptr(poll_cq_thread, cpumask_of(poll_core)); ++ set_cpus_allowed_ptr(waker_polling_thread, cpumask_of(poll_core)); ++ wake_up_process(waker_polling_thread); ++ ++out: ++ spin_unlock(&polling_kthread_spinlock); ++ return count; ++ ++err_inval: ++ spin_unlock(&polling_kthread_spinlock); ++ return -EINVAL; ++} ++ ++static ssize_t ib_core_poll_stat_show(struct kobject *kobj, ++ struct kobj_attribute *attr, char *buf) ++{ ++ int ret; ++ unsigned long avg_poll_time; ++ cq_poll_node_t *poll_node_entry, *poll_node_next; ++ ++ ret = sprintf(buf, "kthread polled cqes cnt: %lu\n", ++ ib_cq_polling_kthread.g_polling_cnt); ++ ++ spin_lock_irq(&cq_list_lock); ++ printk("cq\t\tpoll cnt\tavg poll time(ns)\tmax poll time(ns)\n"); ++ list_for_each_entry_safe(poll_node_entry, poll_node_next, ++ &global_ib_cq_poll_list, list) { ++ avg_poll_time = poll_node_entry->time_used_ns / poll_node_entry->poll_cq_cnt; ++ printk("%p\t%lu\t\t%lu\t\t\t%lu", poll_node_entry->cq, ++ poll_node_entry->poll_cq_cnt, avg_poll_time, ++ poll_node_entry->max_time_ns); ++ } ++ spin_unlock_irq(&cq_list_lock); ++ ++ return ret; ++} ++ ++static ssize_t ib_core_poll_stat_store(struct kobject *kobj, ++ struct kobj_attribute *attr, const char *buf, ++ size_t count) ++{ ++ int input_debug_cq_poll_stat; ++ ++ if (sscanf(buf, "%d", &input_debug_cq_poll_stat) < 0) { ++ pr_err("Invalid input, input format: <0/1> for on/off\n"); ++ return -EINVAL; ++ } ++ debug_cq_poll_stat = input_debug_cq_poll_stat; ++ ib_cq_polling_kthread.debug_cq_poll_stat = input_debug_cq_poll_stat; ++ ++ return count; ++} ++ ++static struct kobj_attribute ib_core_poll_cpu_attr = __ATTR_RW(ib_core_poll_cpu); ++static struct kobj_attribute ib_core_poll_stat_attr = __ATTR_RW(ib_core_poll_stat); ++ ++static int __init mod_poll_cq_kthread_init(void) ++{ ++ int ret; ++ ++ ret = sysfs_create_file(kernel_kobj, &ib_core_poll_cpu_attr.attr); ++ if (ret) { ++ return ret; ++ } ++ ret = sysfs_create_file(kernel_kobj, &ib_core_poll_stat_attr.attr); ++ if (ret) { ++ return ret; ++ } ++ ++ /* init poll thread */ ++ if (!poll_cq_thread) ++ poll_cq_thread = kthread_create(polling_thread, NULL, "polling_thread"); ++ if (IS_ERR(poll_cq_thread)) { ++ ret = PTR_ERR(poll_cq_thread); ++ poll_cq_thread = NULL; ++ goto out; ++ } ++ if (!waker_polling_thread) ++ waker_polling_thread = kthread_create(polling_awaken_thread, ++ NULL, "polling_awaken_thread"); ++ if (IS_ERR(waker_polling_thread)) { ++ ret = PTR_ERR(waker_polling_thread); ++ waker_polling_thread = NULL; ++ goto out; ++ } ++ ib_cq_polling_kthread.add_to_poll_list = add_cq_to_poll_list; ++ ib_cq_polling_kthread.del_from_poll_list = del_cq_from_poll_list; ++ ++out: ++ return 0; ++} ++late_initcall(mod_poll_cq_kthread_init); ++ ++static void mod_poll_cq_kthread_exit(void) ++{ ++ if (poll_cq_thread) { ++ kthread_stop(poll_cq_thread); ++ } ++ if (waker_polling_thread) { ++ kthread_stop(waker_polling_thread); ++ } ++ printk("kthread stopped"); ++ if (ib_cq_polling_kthread.use_polling_kthread) { ++ ib_cq_polling_kthread.use_polling_kthread = 0; ++ ib_cq_polling_kthread.debug_cq_poll_stat = 0; ++ clear_cq_poll_list(); ++ } ++ ++ sysfs_remove_file(kernel_kobj, &ib_core_poll_cpu_attr.attr); ++ sysfs_remove_file(kernel_kobj, &ib_core_poll_stat_attr.attr); ++} ++module_exit(mod_poll_cq_kthread_exit); ++ ++MODULE_DESCRIPTION("cq polling kthread init and config"); ++MODULE_LICENSE("GPL v2"); ++MODULE_AUTHOR("Chen Haotian "); +\ No newline at end of file +diff --git a/drivers/char/poll_cq_kthread.h b/drivers/char/poll_cq_kthread.h +new file mode 100644 +index 000000000000..df5b6e161819 +--- /dev/null ++++ b/drivers/char/poll_cq_kthread.h +@@ -0,0 +1,17 @@ ++#ifndef __POLL_CQ_KTHREAD_H ++#define __POLL_CQ_KTHREAD_H ++ ++typedef struct cq_poll_node ++{ ++ struct list_head list; ++ void *cq; ++ unsigned long time_used_ns; ++ unsigned long poll_cq_cnt; ++ unsigned long max_time_ns; ++} cq_poll_node_t; ++ ++void add_cq_to_poll_list(void *cq); ++void del_cq_from_poll_list(void *del_cq); ++void clear_cq_poll_list(void); ++ ++#endif /* __POLL_CQ_KTHREAD_H */ +\ No newline at end of file +diff --git a/drivers/infiniband/core/cq.c b/drivers/infiniband/core/cq.c +index a70876a0a231..56eaee1bd472 100644 +--- a/drivers/infiniband/core/cq.c ++++ b/drivers/infiniband/core/cq.c +@@ -7,6 +7,7 @@ + #include + + #include "core_priv.h" ++#include "./ib_core_poll_kthread.h" + + #include + /* Max size for shared CQ, may require tuning */ +@@ -195,6 +196,28 @@ static void ib_cq_completion_workqueue(struct ib_cq *cq, void *private) + queue_work(cq->comp_wq, &cq->work); + } + ++struct polling_kthread ib_cq_polling_kthread = { ++ .use_polling_kthread = 0, ++ .debug_cq_poll_stat = 0, ++ .g_polling_cnt = 0, ++}; ++EXPORT_SYMBOL(ib_cq_polling_kthread); ++ ++int ib_poll_cq_thread(void *data) { ++ int completed; ++ struct ib_wc wcs[IB_POLL_BATCH]; ++ struct ib_cq *cq = (struct ib_cq *)data; ++ ++ memcpy(wcs, cq->wc, sizeof(wcs)); ++ completed = __ib_process_cq(cq, IB_POLL_BUDGET_WORKQUEUE, wcs, ++ IB_POLL_BATCH); ++ if (ib_cq_polling_kthread.debug_cq_poll_stat) { ++ ib_cq_polling_kthread.g_polling_cnt += completed; ++ } ++ return completed; ++} ++EXPORT_SYMBOL(ib_poll_cq_thread); ++ + /** + * __ib_alloc_cq - allocate a completion queue + * @dev: device to allocate the CQ for +@@ -243,6 +266,10 @@ struct ib_cq *__ib_alloc_cq(struct ib_device *dev, void *private, int nr_cqe, + + rdma_dim_init(cq); + ++ if (ib_cq_polling_kthread.use_polling_kthread) { ++ cq->poll_ctx = IB_POLL_DIRECT; ++ ib_cq_polling_kthread.add_to_poll_list(cq); ++ } + switch (cq->poll_ctx) { + case IB_POLL_DIRECT: + cq->comp_handler = ib_cq_completion_direct; +@@ -338,6 +365,10 @@ void ib_free_cq(struct ib_cq *cq) + WARN_ON_ONCE(1); + } + ++ if (ib_cq_polling_kthread.use_polling_kthread) { ++ ib_cq_polling_kthread.del_from_poll_list(cq); ++ } ++ + rdma_dim_destroy(cq); + trace_cq_free(cq); + ret = cq->device->ops.destroy_cq(cq, NULL); +diff --git a/drivers/infiniband/core/ib_core_poll_kthread.h b/drivers/infiniband/core/ib_core_poll_kthread.h +new file mode 100644 +index 000000000000..45f6854ddde9 +--- /dev/null ++++ b/drivers/infiniband/core/ib_core_poll_kthread.h +@@ -0,0 +1,22 @@ ++#ifndef __IB_CORE_POLL_KTHREAD_H ++#define __IB_CORE_POLL_KTHREAD_H ++ ++struct polling_kthread ++{ ++ /* configs */ ++ int use_polling_kthread; ++ int debug_cq_poll_stat; ++ ++ /* vars */ ++ unsigned long g_polling_cnt; ++ ++ /* ops */ ++ void (*add_to_poll_list)(void *new_entry); ++ void (*del_from_poll_list)(void *deleted_entry); ++}; ++ ++extern struct polling_kthread ib_cq_polling_kthread; ++ ++int ib_poll_cq_thread(void *data); ++ ++#endif /* __IB_CORE_POLL_KTHREAD_H */ +-- +2.34.1 + diff --git a/tee_blackbox/guest/0001-improve-nfs-workqueue-bind-method.patch b/tee_blackbox/guest/0001-improve-nfs-workqueue-bind-method.patch new file mode 100644 index 0000000000000000000000000000000000000000..e103e5f2684d3593bfa7586421d09f6446e92f68 --- /dev/null +++ b/tee_blackbox/guest/0001-improve-nfs-workqueue-bind-method.patch @@ -0,0 +1,73 @@ +From 9cd63793447bfaa054253f815fd73942f40e2140 Mon Sep 17 00:00:00 2001 +From: zeus <1435901016@qq.com> +Date: Thu, 2 Jan 2025 17:28:28 +0800 +Subject: [PATCH 1/3] improve nfs workqueue bind method + +--- + fs/nfs/inode.c | 8 +++++++- + net/sunrpc/sched.c | 13 +++++++++++-- + 2 files changed, 18 insertions(+), 3 deletions(-) + +diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c +index 56bbf59bda3c..37267c6655a0 100644 +--- a/fs/nfs/inode.c ++++ b/fs/nfs/inode.c +@@ -41,6 +41,7 @@ + #include + #include + #include ++#include + + #include "nfs4_fs.h" + #include "callback.h" +@@ -2411,7 +2412,12 @@ static int nfsiod_start(void) + { + struct workqueue_struct *wq; + dprintk("RPC: creating workqueue nfsiod\n"); +- wq = alloc_workqueue("nfsiod", WQ_MEM_RECLAIM | WQ_UNBOUND, 0); ++ if (virtcca_cvm_domain()) { ++ wq = alloc_workqueue("nfsiod", WQ_MEM_RECLAIM, 0); ++ } else { ++ wq = alloc_workqueue("nfsiod", WQ_MEM_RECLAIM | WQ_UNBOUND, 0); ++ } ++ + if (wq == NULL) + return -ENOMEM; + nfsiod_workqueue = wq; +diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c +index cef623ea1506..fcecf9127cbe 100644 +--- a/net/sunrpc/sched.c ++++ b/net/sunrpc/sched.c +@@ -21,6 +21,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -1282,11 +1283,19 @@ static int rpciod_start(void) + /* + * Create the rpciod thread and wait for it to start. + */ +- wq = alloc_workqueue("rpciod", WQ_MEM_RECLAIM | WQ_UNBOUND, 0); ++ if (virtcca_cvm_domain()) { ++ wq = alloc_workqueue("rpciod", WQ_MEM_RECLAIM, 0); ++ } else { ++ wq = alloc_workqueue("rpciod", WQ_MEM_RECLAIM | WQ_UNBOUND, 0); ++ } + if (!wq) + goto out_failed; + rpciod_workqueue = wq; +- wq = alloc_workqueue("xprtiod", WQ_UNBOUND | WQ_MEM_RECLAIM, 0); ++ if (virtcca_cvm_domain()) { ++ wq = alloc_workqueue("xprtiod", WQ_MEM_RECLAIM | WQ_HIGHPRI, 0); ++ } else { ++ wq = alloc_workqueue("xprtiod", WQ_UNBOUND | WQ_MEM_RECLAIM, 0); ++ } + if (!wq) + goto free_rpciod; + xprtiod_workqueue = wq; +-- +2.34.1 + diff --git a/tee_blackbox/guest/0002-improve-virtio-get-queue-method.patch b/tee_blackbox/guest/0002-improve-virtio-get-queue-method.patch new file mode 100644 index 0000000000000000000000000000000000000000..2403fedd4bebe19f6d94cb3f1499bd0286f32259 --- /dev/null +++ b/tee_blackbox/guest/0002-improve-virtio-get-queue-method.patch @@ -0,0 +1,33 @@ +From 4befe4f49165c14a926d845e6982a8d76b808958 Mon Sep 17 00:00:00 2001 +From: zeus <1435901016@qq.com> +Date: Thu, 2 Jan 2025 17:30:56 +0800 +Subject: [PATCH 2/3] improve virtio get queue method + +--- + net/core/dev.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/net/core/dev.c b/net/core/dev.c +index 75e94b327b31..130e9f015885 100644 +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -154,6 +154,7 @@ + #include + #include + #include ++#include + + #include "dev.h" + #include "net-sysfs.h" +@@ -4231,7 +4232,7 @@ u16 netdev_pick_tx(struct net_device *dev, struct sk_buff *skb, + queue_index >= dev->real_num_tx_queues) { + int new_index = get_xps_queue(dev, sb_dev, skb); + +- if (new_index < 0) ++ if (new_index < 0 || virtcca_cvm_domain()) + new_index = skb_tx_hash(dev, sb_dev, skb); + + if (queue_index != new_index && sk && +-- +2.34.1 + diff --git a/tee_blackbox/guest/0003-add-ipi-direct-inject-method.patch b/tee_blackbox/guest/0003-add-ipi-direct-inject-method.patch new file mode 100644 index 0000000000000000000000000000000000000000..0fbbf4ea1a2ccd11676a572dd5230db9f205af21 --- /dev/null +++ b/tee_blackbox/guest/0003-add-ipi-direct-inject-method.patch @@ -0,0 +1,238 @@ +From 9892ec4a129df0af5dcf43d1f5fa6b6a786f88f1 Mon Sep 17 00:00:00 2001 +From: zeus <1435901016@qq.com> +Date: Fri, 3 Jan 2025 10:47:14 +0800 +Subject: [PATCH 3/3] add ipi direct inject method + +--- + arch/arm64/include/asm/virtcca_cvm_guest.h | 4 ++ + arch/arm64/kernel/smp.c | 13 ++++++- + arch/arm64/kernel/virtcca_cvm_guest.c | 42 +++++++++++++++++++++ + include/linux/virtcca_cvm_domain.h | 44 ++++++++++++++++++++++ + kernel/sched/idle.c | 25 ++++++++++++ + 5 files changed, 126 insertions(+), 2 deletions(-) + +diff --git a/arch/arm64/include/asm/virtcca_cvm_guest.h b/arch/arm64/include/asm/virtcca_cvm_guest.h +index c1ac1a9cd537..40d428645288 100644 +--- a/arch/arm64/include/asm/virtcca_cvm_guest.h ++++ b/arch/arm64/include/asm/virtcca_cvm_guest.h +@@ -20,6 +20,10 @@ extern void virtcca_cvm_tsi_init(void); + + extern void swiotlb_unmap_notify(unsigned long paddr, unsigned long size); + ++extern struct cpumask cvm_spin_cpumask; ++DECLARE_PER_CPU(unsigned int, cvm_unpark_idle_notify); ++DECLARE_PER_CPU(unsigned int, cvm_park_idle_state); ++ + #else + + static inline int set_cvm_memory_encrypted(unsigned long addr, int numpages) +diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c +index 50f6576f1b31..14723b9be741 100644 +--- a/arch/arm64/kernel/smp.c ++++ b/arch/arm64/kernel/smp.c +@@ -34,6 +34,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -832,7 +833,11 @@ void arch_send_call_function_ipi_mask(const struct cpumask *mask) + + void arch_send_call_function_single_ipi(int cpu) + { +- smp_cross_call(cpumask_of(cpu), IPI_CALL_FUNC); ++ if (cvm_spin_cpumask_test_cpu(cpu) && cvm_get_park_idle_state(cpu)) { ++ cvm_set_unpark_idle_notify(cpu, 1); ++ } else { ++ smp_cross_call(cpumask_of(cpu), IPI_CALL_FUNC); ++ } + } + + #ifdef CONFIG_ARM64_ACPI_PARKING_PROTOCOL +@@ -1027,7 +1032,11 @@ void __init set_smp_ipi_range(int ipi_base, int n) + + void arch_smp_send_reschedule(int cpu) + { +- smp_cross_call(cpumask_of(cpu), IPI_RESCHEDULE); ++ if (cvm_spin_cpumask_test_cpu(cpu) && cvm_get_park_idle_state(cpu)) { ++ cvm_set_unpark_idle_notify(cpu, 1); ++ } else { ++ smp_cross_call(cpumask_of(cpu), IPI_RESCHEDULE); ++ } + } + + #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST +diff --git a/arch/arm64/kernel/virtcca_cvm_guest.c b/arch/arm64/kernel/virtcca_cvm_guest.c +index e5368d3e1bfe..6d612a10dcbe 100644 +--- a/arch/arm64/kernel/virtcca_cvm_guest.c ++++ b/arch/arm64/kernel/virtcca_cvm_guest.c +@@ -8,6 +8,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -154,3 +155,44 @@ void swiotlb_unmap_notify(unsigned long paddr, unsigned long size) + + arm_smccc_1_1_smc(SMC_TSI_SEC_MEM_UNMAP, paddr, size, &res); + } ++ ++struct cpumask cvm_spin_cpumask; ++DEFINE_PER_CPU(unsigned int, cvm_unpark_idle_notify); ++DEFINE_PER_CPU(unsigned int, cvm_park_idle_state); ++ ++static ssize_t soft_ipi_passthrough_store(struct kobject *kobj, ++ struct kobj_attribute *attr, ++ const char *buf, size_t count) ++{ ++ if (cpumask_parse(buf, &cvm_spin_cpumask) < 0) { ++ return -EINVAL; ++ } ++ ++ return count; ++} ++ ++static ssize_t soft_ipi_passthrough_show(struct kobject *kobj, ++ struct kobj_attribute *attr, char *buf) ++{ ++ int ret; ++ ++ ret = scnprintf(buf, PAGE_SIZE, "%*pb\n", cpumask_pr_args(&cvm_spin_cpumask)); ++ ++ return ret; ++} ++ ++static struct kobj_attribute soft_ipi_passthrough_attr = __ATTR_RW(soft_ipi_passthrough); ++ ++static int __init soft_ipi_passthrough_init(void) ++{ ++ unsigned int cpu; ++ unsigned int max_nr_cpus = num_possible_cpus(); ++ ++ cpumask_clear(&cvm_spin_cpumask); ++ for (cpu = 0; cpu < max_nr_cpus; cpu++) { ++ cvm_set_unpark_idle_notify(cpu, 0); ++ } ++ ++ return sysfs_create_file(kernel_kobj, &soft_ipi_passthrough_attr.attr); ++} ++late_initcall(soft_ipi_passthrough_init); +diff --git a/include/linux/virtcca_cvm_domain.h b/include/linux/virtcca_cvm_domain.h +index 41b2d15082ab..1209e907cac2 100644 +--- a/include/linux/virtcca_cvm_domain.h ++++ b/include/linux/virtcca_cvm_domain.h +@@ -16,6 +16,31 @@ static inline bool virtcca_cvm_domain(void) + + extern void enable_swiotlb_for_cvm_dev(struct device *dev, bool enable); + ++static inline bool cvm_spin_cpumask_test_cpu(int cpu) ++{ ++ return cpumask_test_cpu(cpu, &cvm_spin_cpumask); ++} ++ ++static inline int cvm_get_park_idle_state(int cpu) ++{ ++ return per_cpu(cvm_park_idle_state, cpu); ++} ++ ++static inline void cvm_set_park_idle_state(int cpu, int val) ++{ ++ per_cpu(cvm_park_idle_state, cpu) = val; ++} ++ ++static inline int cvm_get_unpark_idle_notify(int cpu) ++{ ++ return per_cpu(cvm_unpark_idle_notify, cpu); ++} ++ ++static inline void cvm_set_unpark_idle_notify(int cpu, int val) ++{ ++ per_cpu(cvm_unpark_idle_notify, cpu) = val; ++} ++ + #else + static inline bool virtcca_cvm_domain(void) + { +@@ -24,6 +49,25 @@ static inline bool virtcca_cvm_domain(void) + + static inline void enable_swiotlb_for_cvm_dev(struct device *dev, bool enable) {} + ++static inline bool cvm_spin_cpumask_test_cpu(int cpu) ++{ ++ return false; ++} ++ ++static inline int cvm_get_park_idle_state(int cpu) ++{ ++ return 0; ++} ++ ++static inline void cvm_set_park_idle_state(int cpu, int val) {} ++ ++static inline int cvm_get_unpark_idle_notify(int cpu) ++{ ++ return 0; ++} ++ ++static inline void cvm_set_unpark_idle_notify(int cpu, int val) {} ++ + #endif + + #endif /* __VIRTCCA_CVM_DOMAIN_H */ +diff --git a/kernel/sched/idle.c b/kernel/sched/idle.c +index 5007b25c5bc6..6d241f417ef1 100644 +--- a/kernel/sched/idle.c ++++ b/kernel/sched/idle.c +@@ -7,6 +7,8 @@ + * tasks which are handled in sched/fair.c ) + */ + ++#include ++ + /* Linker adds these: start and end of __cpuidle functions */ + extern char __cpuidle_text_start[], __cpuidle_text_end[]; + +@@ -229,6 +231,25 @@ static void cpuidle_idle_call(void) + local_irq_enable(); + } + ++static noinline int cvm_cpu_idle_poll(void) ++{ ++ unsigned int cpu = smp_processor_id(); ++ ++ if (!virtcca_cvm_domain() || !cvm_spin_cpumask_test_cpu(cpu)) { ++ return 0; ++ } ++ trace_cpu_idle(0, smp_processor_id()); ++ local_irq_enable(); ++ ++ cvm_set_park_idle_state(cpu, 1); ++ while (!tif_need_resched() && !cvm_get_unpark_idle_notify(cpu)) { ++ cpu_relax(); ++ } ++ cvm_set_unpark_idle_notify(cpu, 0); ++ trace_cpu_idle(PWR_EVENT_EXIT, smp_processor_id()); ++ ++ return 1; ++} + /* + * Generic idle loop implementation + * +@@ -269,6 +290,10 @@ static void do_idle(void) + arch_cpu_idle_enter(); + rcu_nocb_flush_deferred_wakeup(); + ++ if (cvm_cpu_idle_poll()) { ++ arch_cpu_idle_exit(); ++ break; ++ } + /* + * In poll mode we reenable interrupts and spin. Also if we + * detected in the wakeup from idle path that the tick +-- +2.34.1 + diff --git a/tee_blackbox/host/0001-cvm-dynamic-wfx-config.patch b/tee_blackbox/host/0001-cvm-dynamic-wfx-config.patch new file mode 100644 index 0000000000000000000000000000000000000000..9f2ed72cae7de4fc55bd8ee8a9dd38bef86650b3 --- /dev/null +++ b/tee_blackbox/host/0001-cvm-dynamic-wfx-config.patch @@ -0,0 +1,72 @@ +From 5217335794b63a7bfbbdce0621873fa46c4c30d9 Mon Sep 17 00:00:00 2001 +From: zeus <1435901016@qq.com> +Date: Fri, 3 Jan 2025 11:41:51 +0800 +Subject: [PATCH] cvm dynamic wfx config + +--- + arch/arm64/kvm/virtcca_cvm.c | 38 ++++++++++++++++++++++++++++++++++-- + 1 file changed, 36 insertions(+), 2 deletions(-) + +diff --git a/arch/arm64/kvm/virtcca_cvm.c b/arch/arm64/kvm/virtcca_cvm.c +index 43f61e5be40b..6636a71932a5 100644 +--- a/arch/arm64/kvm/virtcca_cvm.c ++++ b/arch/arm64/kvm/virtcca_cvm.c +@@ -726,6 +726,38 @@ static int tmi_check_version(void) + return 0; + } + ++struct cpumask cvm_wfx_no_trap_mask; ++static ssize_t cvm_wfx_trap_config_store(struct kobject *kobj, ++ struct kobj_attribute *attr, ++ const char *buf, size_t count) ++{ ++ if (cpumask_parse(buf, &cvm_wfx_no_trap_mask) < 0) { ++ return -EINVAL; ++ } ++ ++ return count; ++} ++ ++static ssize_t cvm_wfx_trap_config_show(struct kobject *kobj, ++ struct kobj_attribute *attr, char *buf) ++{ ++ int ret; ++ ++ ret = scnprintf(buf, PAGE_SIZE, "%*pb\n", cpumask_pr_args(&cvm_wfx_no_trap_mask)); ++ ++ return ret; ++} ++ ++static struct kobj_attribute cvm_wfx_trap_config_attr = __ATTR_RW(cvm_wfx_trap_config); ++ ++static int __init cvm_wfx_trap_config_init(void) ++{ ++ cpumask_clear(&cvm_wfx_no_trap_mask); ++ ++ return sysfs_create_file(kernel_kobj, &cvm_wfx_trap_config_attr.attr); ++} ++late_initcall(cvm_wfx_trap_config_init); ++ + int kvm_tec_enter(struct kvm_vcpu *vcpu) + { + struct tmi_tec_run *run; +@@ -742,12 +774,14 @@ int kvm_tec_enter(struct kvm_vcpu *vcpu) + + run = tec->tec_run; + /* set/clear TWI TWE flags */ +- if (vcpu->arch.hcr_el2 & HCR_TWI) ++ if (vcpu->arch.hcr_el2 & HCR_TWI && ++ !cpumask_test_cpu(vcpu->vcpu_id, &cvm_wfx_no_trap_mask)) + run->tec_entry.flags |= TEC_ENTRY_FLAG_TRAP_WFI; + else + run->tec_entry.flags &= ~TEC_ENTRY_FLAG_TRAP_WFI; + +- if (vcpu->arch.hcr_el2 & HCR_TWE) ++ if (vcpu->arch.hcr_el2 & HCR_TWE && ++ !cpumask_test_cpu(vcpu->vcpu_id, &cvm_wfx_no_trap_mask)) + run->tec_entry.flags |= TEC_ENTRY_FLAG_TRAP_WFE; + else + run->tec_entry.flags &= ~TEC_ENTRY_FLAG_TRAP_WFE; +-- +2.34.1 +