1#include <console/panic.h>
2#include <global.h>
3#include <linker/symbols.h>
4#include <mem/alloc.h>
5#include <mem/nofail.h>
6#include <smp/core.h>
7#include <smp/domain.h>
8#include <smp/percpu.h>
9#include <smp/perdomain.h>
10#include <smp/pertopo.h>
11
12/* TODO: memory locality with valloc_from_domain aligned */
13void percpu_obj_init(void) {
14 struct percpu_descriptor *d;
15 linker_section_for_each_object(d, percpu_desc) {
16 d->percpu_ptrs = nofail_vnews(d->percpu_ptrs, global.core_count);
17
18 size_t cpu;
19 for_each_cpu_id(cpu) {
20 d->percpu_ptrs[cpu] =
21 nofail(valloc_aligned(d->size, d->align, ALLOC_ZERO));
22
23 if (d->constructor)
24 d->constructor(d->percpu_ptrs[cpu], cpu);
25 }
26 }
27}
28
29void perdomain_obj_init(void) {
30 struct perdomain_descriptor *d;
31 linker_section_for_each_object(d, perdomain_desc) {
32 d->perdomain_ptrs =
33 nofail_vnews(d->perdomain_ptrs, global.domain_count);
34
35 size_t id;
36 domain_for_each_domain_id(id) {
37 d->perdomain_ptrs[id] =
38 nofail(valloc_aligned(d->size, d->align, ALLOC_ZERO));
39
40 if (d->constructor)
41 d->constructor(d->perdomain_ptrs[id], id);
42 }
43 }
44}
45
46void pertopo_obj_init(void) {
47 struct pertopo_descriptor *d;
48 linker_section_for_each_object(d, pertopo_desc) {
49 d->pertopo_ptrs =
50 nofail_vnews(d->pertopo_ptrs, global.topology.count[d->level]);
51 size_t n;
52 topology_for_each_id(n, d->level) {
53 d->pertopo_ptrs[n] =
54 nofail(valloc_aligned(d->size, d->align, ALLOC_ZERO));
55
56 if (d->constructor)
57 d->constructor(d->pertopo_ptrs[n], n);
58 }
59 }
60}
61
62size_t pertopo_node_local(struct pertopo_descriptor *desc,
63 enum topology_caller c) {
64 enum topology_level l = desc->level;
65 enforce(topology_contract_verify(
66 (struct topology_contract){.caller = c, .scope = l}));
67
68 struct core *self = smp_core_raw();
69 for (struct topology_node *n = self->topo_node; n; n = n->parent_node) {
70 if (n->level == l)
71 return n->id;
72 }
73
74 return SIZE_MAX;
75}
76
77void **percpu_alloc_array(size_t size) {
78 size_t count = global.core_count;
79 void **ret = nofail_vnews(ret, count, ALLOC_ZERO);
80 for (size_t i = 0; i < count; i++)
81 ret[i] = nofail(valloc_from_domain(domain_for_cpu(i), size));
82
83 return ret;
84}
85
86void **perdomain_alloc_array(size_t size) {
87 size_t count = global.domain_count;
88 void **ret = nofail_vnews(ret, count, ALLOC_ZERO);
89 for (size_t i = 0; i < count; i++)
90 ret[i] = nofail(valloc_from_domain(i, size));
91
92 return ret;
93}
94