kernel: Create CPU topology tree
This commit is contained in:
parent
5cbf227236
commit
343c489689
@ -39,6 +39,15 @@ typedef enum cpu_topology_level {
|
||||
CPU_TOPOLOGY_LEVELS
|
||||
} cpu_topology_level;
|
||||
|
||||
typedef struct cpu_topology_node {
|
||||
cpu_topology_level level;
|
||||
|
||||
int id;
|
||||
|
||||
cpu_topology_node** children;
|
||||
int children_count;
|
||||
} cpu_topology_node;
|
||||
|
||||
|
||||
/* CPU local data structure */
|
||||
|
||||
@ -93,6 +102,9 @@ bigtime_t cpu_get_active_time(int32 cpu);
|
||||
cpu_ent *get_cpu_struct(void);
|
||||
extern inline cpu_ent *get_cpu_struct(void) { return &gCPU[smp_get_current_cpu()]; }
|
||||
|
||||
status_t cpu_build_topology_tree(void);
|
||||
cpu_topology_node* get_cpu_topology(void);
|
||||
|
||||
void _user_clear_caches(void *address, size_t length, uint32 flags);
|
||||
bool _user_cpu_enabled(int32 cpu);
|
||||
status_t _user_set_cpu_enabled(int32 cpu, bool enabled);
|
||||
|
@ -21,7 +21,9 @@
|
||||
|
||||
/* global per-cpu structure */
|
||||
cpu_ent gCPU[MAX_BOOT_CPUS];
|
||||
|
||||
uint32 gCPUCacheLevelCount;
|
||||
static cpu_topology_node sCPUTopology;
|
||||
|
||||
static spinlock sSetCpuLock;
|
||||
|
||||
@ -88,6 +90,115 @@ clear_caches(void *address, size_t length, uint32 flags)
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
cpu_create_topology_node(cpu_topology_node* node, int32* maxID, int32 id)
|
||||
{
|
||||
cpu_topology_level level = static_cast<cpu_topology_level>(node->level - 1);
|
||||
ASSERT(level >= 0);
|
||||
|
||||
cpu_topology_node* newNode = new(std::nothrow) cpu_topology_node;
|
||||
if (newNode == NULL)
|
||||
return B_NO_MEMORY;
|
||||
node->children[id] = newNode;
|
||||
|
||||
newNode->level = level;
|
||||
if (level != CPU_TOPOLOGY_SMT) {
|
||||
newNode->children_count = maxID[level - 1];
|
||||
newNode->children
|
||||
= new(std::nothrow) cpu_topology_node*[maxID[level - 1]];
|
||||
if (newNode->children == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
memset(newNode->children, 0,
|
||||
maxID[level - 1] * sizeof(cpu_topology_node*));
|
||||
} else {
|
||||
newNode->children_count = 0;
|
||||
newNode->children = NULL;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cpu_rebuild_topology_tree(cpu_topology_node* node, int32* lastID)
|
||||
{
|
||||
if (node->children == NULL)
|
||||
return;
|
||||
|
||||
int32 count = 0;
|
||||
for (int32 i = 0; i < node->children_count; i++) {
|
||||
if (node->children[i] == NULL)
|
||||
continue;
|
||||
|
||||
if (count != i)
|
||||
node->children[count] = node->children[i];
|
||||
|
||||
if (node->children[count]->level != CPU_TOPOLOGY_SMT)
|
||||
node->children[count]->id = lastID[node->children[count]->level]++;
|
||||
|
||||
cpu_rebuild_topology_tree(node->children[count], lastID);
|
||||
count++;
|
||||
}
|
||||
node->children_count = count;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
cpu_build_topology_tree(void)
|
||||
{
|
||||
sCPUTopology.level = CPU_TOPOLOGY_LEVELS;
|
||||
|
||||
int32 maxID[CPU_TOPOLOGY_LEVELS];
|
||||
memset(&maxID, 0, sizeof(maxID));
|
||||
|
||||
const int32 kCPUCount = smp_get_num_cpus();
|
||||
for (int32 i = 0; i < kCPUCount; i++) {
|
||||
for (int32 j = 0; j < CPU_TOPOLOGY_LEVELS; j++)
|
||||
maxID[j] = max_c(maxID[j], gCPU[i].topology_id[j]);
|
||||
}
|
||||
|
||||
for (int32 j = 0; j < CPU_TOPOLOGY_LEVELS; j++)
|
||||
maxID[j]++;
|
||||
|
||||
sCPUTopology.children_count = maxID[CPU_TOPOLOGY_LEVELS - 1];
|
||||
sCPUTopology.children
|
||||
= new(std::nothrow) cpu_topology_node*[maxID[CPU_TOPOLOGY_LEVELS - 1]];
|
||||
if (sCPUTopology.children == NULL)
|
||||
return B_NO_MEMORY;
|
||||
memset(sCPUTopology.children, 0,
|
||||
maxID[CPU_TOPOLOGY_LEVELS - 1] * sizeof(cpu_topology_node*));
|
||||
|
||||
for (int32 i = 0; i < kCPUCount; i++) {
|
||||
cpu_topology_node* node = &sCPUTopology;
|
||||
for (int32 j = CPU_TOPOLOGY_LEVELS - 1; j >= 0; j--) {
|
||||
int32 id = gCPU[i].topology_id[j];
|
||||
if (node->children[id] == NULL) {
|
||||
status_t result = cpu_create_topology_node(node, maxID, id);
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
}
|
||||
|
||||
node = node->children[id];
|
||||
}
|
||||
|
||||
ASSERT(node->level == CPU_TOPOLOGY_SMT);
|
||||
node->id = i;
|
||||
}
|
||||
|
||||
int32 lastID[CPU_TOPOLOGY_LEVELS];
|
||||
memset(&lastID, 0, sizeof(lastID));
|
||||
cpu_rebuild_topology_tree(&sCPUTopology, lastID);
|
||||
}
|
||||
|
||||
|
||||
cpu_topology_node*
|
||||
get_cpu_topology(void)
|
||||
{
|
||||
return &sCPUTopology;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
|
@ -165,6 +165,7 @@ _start(kernel_args *bootKernelArgs, int currentCPU)
|
||||
|
||||
TRACE("init SMP\n");
|
||||
smp_init(&sKernelArgs);
|
||||
cpu_build_topology_tree();
|
||||
TRACE("init timer\n");
|
||||
timer_init(&sKernelArgs);
|
||||
TRACE("init real time clock\n");
|
||||
|
Loading…
Reference in New Issue
Block a user