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