[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>
This commit is contained in:
GUI 2024-05-28 14:08:33 +08:00 committed by GitHub
parent 952f2c43f8
commit 6f6b0c3ba0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 198 additions and 1 deletions

View File

@ -8,7 +8,7 @@ if GetDepend(['RT_USING_DEV_BUS']) or GetDepend(['RT_USING_DM']):
src = src + ['bus.c'] src = src + ['bus.c']
if GetDepend(['RT_USING_DM']): 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']): if GetDepend(['RT_USING_DFS']):
src += ['mnt.c']; src += ['mnt.c'];

View File

@ -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 */

View File

@ -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__ */

View File

@ -41,6 +41,7 @@ extern "C" {
#ifdef RT_USING_DM #ifdef RT_USING_DM
#include "drivers/core/dm.h" #include "drivers/core/dm.h"
#include "drivers/core/numa.h"
#include "drivers/platform.h" #include "drivers/platform.h"
#ifdef RT_USING_OFW #ifdef RT_USING_OFW