summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGUI <[email protected]>2024-05-28 14:08:33 +0800
committerGitHub <[email protected]>2024-05-28 14:08:33 +0800
commit6f6b0c3ba0f308bccb5a83fa70ae1200592f13ce (patch)
tree5cada9d72246e42c3fd9a1ee3e3c1e5d8f46c60e
parent952f2c43f8a10f815f34307c7d184af8f08011ba (diff)
[DM/feature] Simple NUMA (Non-Uniform Memory Access) (#9000)
For some CPU memory access devices, that the drivers will find memory and CPU affinity to config device. Signed-off-by: GuEe-GUI <[email protected]>
-rw-r--r--components/drivers/core/SConscript2
-rw-r--r--components/drivers/core/numa.c171
-rw-r--r--components/drivers/include/drivers/core/numa.h25
-rw-r--r--components/drivers/include/rtdevice.h1
4 files changed, 198 insertions, 1 deletions
diff --git a/components/drivers/core/SConscript b/components/drivers/core/SConscript
index 99b39436b2..e1f003549f 100644
--- a/components/drivers/core/SConscript
+++ b/components/drivers/core/SConscript
@@ -8,7 +8,7 @@ if GetDepend(['RT_USING_DEV_BUS']) or GetDepend(['RT_USING_DM']):
src = src + ['bus.c']
if GetDepend(['RT_USING_DM']):
- src = src + ['dm.c', 'driver.c', 'platform.c']
+ src = src + ['dm.c', 'driver.c', 'numa.c', 'platform.c']
if GetDepend(['RT_USING_DFS']):
src += ['mnt.c'];
diff --git a/components/drivers/core/numa.c b/components/drivers/core/numa.c
new file mode 100644
index 0000000000..5a2e7907ef
--- /dev/null
+++ b/components/drivers/core/numa.c
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2023-09-24 GuEe-GUI the first version
+ */
+
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#define DBG_TAG "rtdm.numa"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
+#include <drivers/pic.h>
+
+struct numa_memory
+{
+ rt_list_t list;
+
+ int nid;
+ rt_uint64_t start;
+ rt_uint64_t end;
+
+ union
+ {
+ void *ofw_node;
+ };
+};
+
+static rt_bool_t numa_enabled = RT_FALSE;
+static int cpu_numa_map[RT_CPUS_NR] rt_section(".bss.noclean.numa");
+static rt_list_t numa_memory_nodes rt_section(".bss.noclean.numa");
+
+int rt_numa_cpu_id(int cpuid)
+{
+ if (!numa_enabled)
+ {
+ return -RT_ENOSYS;
+ }
+
+ return cpuid < RT_ARRAY_SIZE(cpu_numa_map) ? cpu_numa_map[cpuid] : -RT_EINVAL;
+}
+
+int rt_numa_device_id(struct rt_device *dev)
+{
+ rt_uint32_t nid = (rt_uint32_t)-RT_ENOSYS;
+
+ if (!numa_enabled)
+ {
+ return nid;
+ }
+
+ return rt_dm_dev_prop_read_u32(dev, "numa-node-id", &nid) ? : (int)nid;
+}
+
+rt_err_t rt_numa_memory_affinity(rt_uint64_t phy_addr, rt_bitmap_t *out_affinity)
+{
+ struct numa_memory *nm;
+
+ if (!out_affinity)
+ {
+ return -RT_EINVAL;
+ }
+
+ if (!numa_enabled)
+ {
+ /* Default to CPU#0 */
+ RT_IRQ_AFFINITY_SET(out_affinity, 0);
+
+ return RT_EOK;
+ }
+
+ rt_memset(out_affinity, 0, sizeof(*out_affinity) * RT_BITMAP_LEN(RT_CPUS_NR));
+
+ rt_list_for_each_entry(nm, &numa_memory_nodes, list)
+ {
+ if (phy_addr >= nm->start && phy_addr < nm->end)
+ {
+ for (int i = 0; i < RT_ARRAY_SIZE(cpu_numa_map); ++i)
+ {
+ if (cpu_numa_map[i] == nm->nid)
+ {
+ RT_IRQ_AFFINITY_SET(out_affinity, i);
+ }
+ }
+
+ return RT_EOK;
+ }
+ }
+
+ return -RT_EEMPTY;
+}
+
+#ifdef RT_USING_OFW
+static int numa_ofw_init(void)
+{
+ int i = 0;
+ rt_uint32_t nid;
+ const char *numa_conf;
+ struct rt_ofw_node *np = RT_NULL;
+
+ numa_conf = rt_ofw_bootargs_select("numa=", 0);
+
+ if (!numa_conf || rt_strcmp(numa_conf, "on"))
+ {
+ return (int)RT_EOK;
+ }
+
+ numa_enabled = RT_TRUE;
+
+ for (int i = 0; i < RT_ARRAY_SIZE(cpu_numa_map); ++i)
+ {
+ cpu_numa_map[i] = -RT_ENOSYS;
+ }
+
+ rt_list_init(&numa_memory_nodes);
+
+ rt_ofw_foreach_cpu_node(np)
+ {
+ rt_ofw_prop_read_u32(np, "numa-node-id", (rt_uint32_t *)&cpu_numa_map[i]);
+
+ if (++i >= RT_CPUS_NR)
+ {
+ break;
+ }
+ }
+
+ rt_ofw_foreach_node_by_type(np, "memory")
+ {
+ if (!rt_ofw_prop_read_u32(np, "numa-node-id", &nid))
+ {
+ int mem_nr = rt_ofw_get_address_count(np);
+
+ for (i = 0; i < mem_nr; ++i)
+ {
+ rt_uint64_t addr, size;
+ struct numa_memory *nm;
+
+ if (rt_ofw_get_address(np, i, &addr, &size))
+ {
+ continue;
+ }
+
+ nm = rt_malloc(sizeof(*nm));
+
+ if (!nm)
+ {
+ LOG_E("No memory to record NUMA[%d] memory[%p, %p] info",
+ nid, addr, addr + size);
+
+ return (int)-RT_ENOMEM;
+ }
+
+ nm->start = addr;
+ nm->end = addr + size;
+ nm->ofw_node = np;
+
+ rt_list_init(&nm->list);
+ rt_list_insert_before(&numa_memory_nodes, &nm->list);
+ }
+ }
+ }
+
+ return 0;
+}
+INIT_CORE_EXPORT(numa_ofw_init);
+#endif /* RT_USING_OFW */
diff --git a/components/drivers/include/drivers/core/numa.h b/components/drivers/include/drivers/core/numa.h
new file mode 100644
index 0000000000..e4d35981fb
--- /dev/null
+++ b/components/drivers/include/drivers/core/numa.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2023-09-24 GuEe-GUI the first version
+ */
+
+#ifndef __RT_DM_NUMA_H__
+#define __RT_DM_NUMA_H__
+
+#include <rthw.h>
+#include <rtthread.h>
+
+#include <bitmap.h>
+
+/* NUMA: Non-Uniform Memory Access */
+
+int rt_numa_cpu_id(int cpuid);
+int rt_numa_device_id(struct rt_device *dev);
+rt_err_t rt_numa_memory_affinity(rt_uint64_t phy_addr, rt_bitmap_t *out_affinity);
+
+#endif /* __RT_DM_NUMA_H__ */
diff --git a/components/drivers/include/rtdevice.h b/components/drivers/include/rtdevice.h
index afb5bb2533..863e9d8503 100644
--- a/components/drivers/include/rtdevice.h
+++ b/components/drivers/include/rtdevice.h
@@ -41,6 +41,7 @@ extern "C" {
#ifdef RT_USING_DM
#include "drivers/core/dm.h"
+#include "drivers/core/numa.h"
#include "drivers/platform.h"
#ifdef RT_USING_OFW