From 6f6b0c3ba0f308bccb5a83fa70ae1200592f13ce Mon Sep 17 00:00:00 2001 From: GUI <39894654+GuEe-GUI@users.noreply.github.com> Date: Tue, 28 May 2024 14:08:33 +0800 Subject: [PATCH] [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 <2991707448@qq.com> --- components/drivers/core/SConscript | 2 +- components/drivers/core/numa.c | 171 ++++++++++++++++++ .../drivers/include/drivers/core/numa.h | 25 +++ components/drivers/include/rtdevice.h | 1 + 4 files changed, 198 insertions(+), 1 deletion(-) create mode 100644 components/drivers/core/numa.c create mode 100644 components/drivers/include/drivers/core/numa.h 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 +#include + +#define DBG_TAG "rtdm.numa" +#define DBG_LVL DBG_INFO +#include + +#include + +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 +#include + +#include + +/* 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