| 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 */ |
| 13 | void 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 | |
| 29 | void 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 | |
| 46 | void 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 | |
| 62 | size_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 | |
| 77 | void **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 | |
| 86 | void **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 | |