1%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2% Copyright (c) 2009, ETH Zurich. 3% All rights reserved. 4% 5% This file is distributed under the terms in the attached LICENSE file. 6% If you do not find this file, copies can be found by writing to: 7% ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group. 8%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 9 10% :-include("data.pl"). 11% :-include("boardlayout.pl"). 12% test data which are manually created, but can be figured out at runtime 13% :-include("testdata.pl"). 14 15:- dynamic interrupt_override/4. 16:- dynamic iommu_enabled/2. 17 18% 1. find list of core IDs which are closest to device add(bus, dev, fun) 19% -> that means that the HT-network has to be represented. With this information 20% we can ask this kind of information 21 22cores_close_to_pci_device(Bus, _, _, CoreIDs) :- 23 rootbridge(Addr,childbus(CLow,CHigh),_), 24 Bus >= CLow, 25 Bus =< CHigh, 26 rootcomplex_addr(Name, Addr), 27 ht_link(CPU,Name), 28 findall(X,core(X,CPU),CoreIDs). 29 30% 2. find memory region closest to core ID 31% -> this can also be queried if we have the whole connection between cores 32% memory and rootcomplexes represented 33 34ram_closest_to(CoreID,RetBase,RetLimit) :- 35 corename(CoreID,_,apic(ApicID)), 36 cpu_affinity(ApicID, _, ProxDomain), 37 memory_affinity(AffinityBase, AffinitySize, ProxDomain), 38 AffinityLimit is AffinityBase + AffinitySize, 39 memory_region(MemBase, _, MemSize, MemType, _), 40 mem_region_type(MemType, ram), 41 MemLimit is MemBase + MemSize, 42 MemBase < AffinityLimit, 43 MemLimit > AffinityBase, 44 ( AffinityBase < MemBase -> 45 RetBase is MemBase 46 ; 47 RetBase is AffinityBase), 48 ( AffinityLimit < MemLimit -> 49 RetLimit is AffinityLimit 50 ; 51 RetLimit is MemLimit). 52 53% The above returns one range, this will return all the ranges by using findall. 54ram_findall(CoreID, List) :- 55 findall(range(Base,Limit), ram_closest_to(CoreID, Base, Limit), List). 56 57% this is the version which only gives local address range whithout checking 58% whether it is actually RAM. This is sufficient, if ram_set_affinity is called, 59% because that will only allocate RAM anyway 60 61local_memory_affinity(CoreID, L) :- 62 is_predicate(cpu_affinity/3), 63 is_predicate(memory_affinity/3), 64 findall(range(Base,Limit), 65 ( 66 cpu_affinity(CoreID,_,ProxDomain), 67 memory_affinity(Base,Size,ProxDomain), 68 Limit is Base + Size 69 ), 70 L). 71 72extractbase(range(X,_),X). 73extractlimit(range(_,X),X). 74 75local_memory_affinity(CoreID, Base, Limit) :- 76 local_memory_affinity(CoreID, L), 77 ( not L=[] -> 78 maplist(extractbase, L, Bases), 79 maplist(extractlimit, L, Limits), 80 min(Bases, Base), 81 max(Limits, Limit) 82 ; 83 Base=0, 84 Limit=0 85 ). 86 87% 3. find core ID list which share same L2/L3 cache 88% -> till now it looks like the only way to know that is from data sheets. 89 90% cores_with_cache_sharing(Level,CoreIDs) :- 91% findall([C1,C2],cache_share(C1,C2,Level),CoreIDs). 92 93 94% 4. find core IDs which do _not_ share caches 95 96%cns(CPL) :- 97% core(X,_),core(Y,_),not X =:= Y,not cache_share(X,Y,_),not cache_share(Y,X,_), 98% CPL = [X,Y]. 99% 100%cores_no_cache_sharing(CoreIDs) :- 101% findall(X,cns(X),CoreIDs). 102 103% 5. find core IDs which are not on the same CPU 104 105%cores_on_different_cpus(CoreIDs) :- 106% core(X,N1), 107% core(Y,N2), 108% not N1 =:= N2, 109% CoreIDs = [X,Y]. 110 111 112% 6. get a sorted list of all available APIC IDs 113 114get_apic_id_list(L) :- 115 ( is_predicate(apic/3) -> 116 findall(ID, apic(_, ID, 1), TmpL), sort(TmpL, L); 117 L = [] 118 ). 119 120% get a sorted list of all available core ids 121get_core_id_list(L) :- 122 ( is_predicate(corename/3) -> 123 findall(ID, corename(ID, _, _), TmpL), sort(TmpL, L); 124 L = [] 125 ). 126 127get_core_info(ProxDomain, CoreID, Arch, ApicID) :- 128 ( is_predicate(cpu_affinity/3) -> 129 corename(CoreID,Arch,apic(ApicID)), 130 cpu_affinity(ApicID, _, ProxDomain) 131 ; 132 corename(CoreID,Arch,apic(ApicID)), 133 ProxDomain = 0 134 ). 135 136arm_mpids(L) :- 137 findall(mpid(MPID), arm_core(MPID,_), L). 138 139 140% this function gets the system RAM size 141get_system_ram_size(RetBase,RetLimit) :- 142 findall(range(MemBase, MemLimit), ( 143 mem_region_type(MemType, ram), 144 memory_region(MemBase, _, MemSize, MemType, _), 145 MemLimit is MemBase + MemSize 146 ), List), 147 maplist(extractbase, List, Bases), 148 maplist(extractlimit, List, Limits), 149 min(Bases, RetBase), 150 max(Limits, RetLimit). 151 152 153extractbasenode(range(X,_,_),X). 154extractlimitnode(range(_,X,_),X). 155 156 157get_node_ram_size(ProxDomain,RetBase,RetLimit) :- 158 is_predicate(memory_affinity/3), 159 findall(range(MemBase, MemLimit, ProxDomain), ( 160 memory_affinity(MemBase,MemSize,ProxDomain), 161 MemLimit is MemBase + MemSize 162 ), List), 163 maplist(extractbasenode, List, Bases), 164 maplist(extractlimitnode, List, Limits), 165 min(Bases, RetBase), 166 max(Limits, RetLimit). 167 168get_node_info(ProxDomain, RetBase, RetLimit) :- 169 ( is_predicate(memory_affinity/3) -> 170 get_node_ram_size(ProxDomain, RetBase, RetLimit) 171 ; 172 get_system_ram_size(RetBase, RetLimit), 173 ProxDomain = 0 174 ). 175 176% obtains the number of available nodes 177available_nr_nodes(Nnodes) :- 178 get_system_topology(Nnodes, _, _, _). 179 180% get the system locality information 181get_system_locality(Ldistances) :- 182 ( is_predicate(node_distance/3) -> 183 findall(node_distance(I, J, E), node_distance(I, J, E), TmpL), sort(TmpL, Ldistances); 184 Ldistances = [] 185 ). 186 187% get the system NUMA topology 188get_system_topology(Nnodes,Ncores, Lnodes, Lcores, Llocalities) :- 189 findall(node(ProxDomain, RetBase, RetLimit), ( 190 (is_predicate(memory_affinity/3) -> 191 memory_affinity(_,_,ProxDomain) 192 ; 193 ProxDomain = 0 194 ), 195 get_node_info(ProxDomain, RetBase, RetLimit) 196 ), TmpN), sort(TmpN, Lnodes), 197 findall(cpu(NODE,ID,APIC,ARCH), get_core_info(NODE, ID, ARCH, APIC), TmpL), sort(TmpL, Lcores), 198 get_system_locality(Llocalities), 199 length(Lnodes, Nnodes), 200 length(Lcores, Ncores). 201 202% 7. find the available number of cores 203 204available_nr_cores(Nr) :- 205 get_core_id_list(L), 206 length(L, Nr). 207 208% 8. figure out whether all the available cores found by pci/acpi are added to the 209% skb 210 211is_pci_done(Status) :- 212 ( is_predicate(pci_discovery_done/0) -> 213 Status=yes; 214 Status=no 215 ). 216 217% 9. Figure out if boot time perfmon domain is finished 218 219is_boot_perfmon_done(Status) :- 220 ( is_predicate(boot_perfmon_done/0) -> 221 Status=yes; 222 Status=no 223 ). 224 225 226get_cache_size(Level, Type, Size):- 227 ( is_predicate(cache/8), cache(_, _, Level, Type, Size, _, _, _) -> 228 true; 229 Size is 32768 230 ). 231 232 233 234 235%10. Figure out whether the datagatherer is done 236 237is_datagatherer_done(Status) :- 238 ( is_predicate(datagatherer_done/0) -> 239 Status=yes; 240 Status=no 241 ). 242 243