]>
Commit | Line | Data |
---|---|---|
39236c6e A |
1 | from xnu import * |
2 | from misc import DoReadMsr64, DoWriteMsr64 | |
3 | ||
4 | ###################################### | |
5 | # Globals | |
6 | ###################################### | |
7 | lapic_base_addr = 0xfee00000 | |
8 | ioapic_base_addr = 0xfec00000 | |
9 | ioapic_index_off = 0x0 | |
10 | ioapic_data_off = 0x10 | |
11 | ||
12 | ||
13 | ###################################### | |
14 | # LAPIC Helper functions | |
15 | ###################################### | |
16 | def IsArchX86_64(): | |
17 | """ Determines if target machine is x86_64 | |
18 | Returns: | |
19 | True if running on x86_64, False otherwise | |
20 | """ | |
21 | return kern.arch == "x86_64" | |
22 | ||
23 | ||
24 | @static_var('x2apic_enabled', -1) | |
25 | def IsX2ApicEnabled(): | |
26 | """ Reads the APIC configuration MSR to determine if APIC is operating | |
27 | in x2APIC mode. The MSR is read the first time this function is | |
28 | called, and the answer is remembered for all subsequent calls. | |
29 | Returns: | |
30 | True if APIC is x2APIC mode | |
31 | False if not | |
32 | """ | |
33 | apic_cfg_msr = 0x1b | |
34 | apic_cfg_msr_x2en_mask = 0xc00 | |
35 | if IsX2ApicEnabled.x2apic_enabled < 0: | |
36 | if (int(DoReadMsr64(apic_cfg_msr, xnudefines.lcpu_self)) & apic_cfg_msr_x2en_mask == | |
37 | apic_cfg_msr_x2en_mask): | |
38 | IsX2ApicEnabled.x2apic_enabled = 1 | |
39 | else: | |
40 | IsX2ApicEnabled.x2apic_enabled = 0 | |
41 | return IsX2ApicEnabled.x2apic_enabled == 1 | |
42 | ||
43 | def DoLapicRead32(offset, cpu): | |
44 | """ Read the specified 32-bit LAPIC register | |
45 | Params: | |
46 | offset: int - index of LAPIC register to read | |
47 | cpu: int - cpu ID | |
48 | Returns: | |
49 | The 32-bit LAPIC register value | |
50 | """ | |
51 | if IsX2ApicEnabled(): | |
52 | return DoReadMsr64(offset >> 4, cpu) | |
53 | else: | |
54 | return ReadPhysInt(lapic_base_addr + offset, 32, cpu) | |
55 | ||
56 | def DoLapicWrite32(offset, val, cpu): | |
57 | """ Write the specified 32-bit LAPIC register | |
58 | Params: | |
59 | offset: int - index of LAPIC register to write | |
60 | val: int - write value | |
61 | cpu: int - cpu ID | |
62 | Returns: | |
63 | True if success, False if error | |
64 | """ | |
65 | if IsX2ApicEnabled(): | |
66 | return DoWriteMsr64(offset >> 4, cpu, val) | |
67 | else: | |
68 | return WritePhysInt(lapic_base_addr + offset, val, 32) | |
69 | ||
70 | ###################################### | |
71 | # LAPIC Register Print functions | |
72 | ###################################### | |
73 | def GetLapicVersionFields(reg_val): | |
74 | """ Helper function for DoLapicDump that prints the fields of the | |
75 | version register. | |
76 | Params: | |
77 | reg_val: int - the value of the version register to print | |
78 | Returns: | |
79 | string showing the fields | |
80 | """ | |
81 | lvt_num = (reg_val >> 16) + 1 | |
82 | version = reg_val & 0xff | |
83 | return "[VERSION={:d} MaxLVT={:d}]".format(lvt_num, version) | |
84 | ||
85 | def GetLapicSpuriousVectorFields(reg_val): | |
86 | """ Helper function for DoLapicDump that prints the fields of the | |
87 | spurious vector register. | |
88 | Params: | |
89 | reg_val: int - the value of the spurious vector registre to print | |
90 | Returns: | |
91 | string showing the fields | |
92 | """ | |
93 | vector = reg_val & 0xff | |
94 | enabled = (reg_val & 0x100) >> 8 | |
95 | return "[VEC={:3d} ENABLED={:d}]".format(vector, enabled) | |
96 | ||
97 | def GetLapicIcrHiFields(reg_val): | |
98 | """ Helper function for DoLapicDump that prints the fields of the | |
99 | upper 32-bits of the Interrupt Control Register (ICR). | |
100 | Params: | |
101 | reg_val: int - the value of the ICR to show | |
102 | Returns: | |
103 | string showing the fields | |
104 | """ | |
105 | dest = reg_val >> 24 | |
106 | return "[DEST={:d}]".format(dest) | |
107 | ||
108 | def GetLapicTimerDivideFields(reg_val): | |
109 | """ Helper function for DoLapicDump that prints the fields of the | |
110 | timer divide register. | |
111 | Params: | |
112 | reg_val: int - the value of the timer divide register | |
113 | Returns: | |
114 | string showing the fields | |
115 | """ | |
116 | divide_val = ((reg_val & 0x8) >> 1) | (reg_val & 0x3) | |
117 | if divide_val == 0x7: | |
118 | divide_by = 1 | |
119 | else: | |
120 | divide_by = 2 << divide_val | |
121 | return "[Divide by {:d}]".format(divide_by) | |
122 | ||
123 | def GetApicFields(reg_val): | |
124 | """ Helper function for DoLapicDump and DoIoapicDump that prints the | |
125 | fields of the APIC register. | |
126 | Params: | |
127 | reg_val: int - the value of the APIC register to print | |
128 | Returns: | |
129 | string showing the fields | |
130 | """ | |
131 | vector = reg_val & 0xff | |
132 | tsc_deadline = reg_val & 0x40000 | |
133 | periodic = reg_val & 0x20000 | |
134 | masked = reg_val & 0x10000 | |
135 | trigger = reg_val & 0x8000 | |
136 | polarity = reg_val & 0x2000 | |
137 | pending = reg_val & 0x1000 | |
138 | ||
139 | ret_str = "[VEC={:3d} MASK={:3s} TRIG={:5s} POL={:4s} PEND={:3s}".format( | |
140 | vector, | |
141 | "no" if masked == 0 else "yes", | |
142 | "edge" if trigger == 0 else "level", | |
143 | "low" if polarity == 0 else "high", | |
144 | "no" if pending == 0 else "yes") | |
145 | if not periodic == 0: | |
146 | ret_str += " PERIODIC" | |
147 | if not tsc_deadline == 0: | |
148 | ret_str += " TSC_DEADLINE" | |
149 | ret_str += "]" | |
150 | return ret_str | |
151 | ||
152 | def DoLapicDump(): | |
153 | """ Prints all LAPIC registers | |
154 | """ | |
155 | print "LAPIC operating mode: {:s}".format( | |
156 | "x2APIC" if IsX2ApicEnabled() else "xAPIC") | |
157 | # LAPIC register offset, register name, field formatting function | |
158 | lapic_dump_table = [ | |
159 | (0x020, "ID", None), | |
160 | (0x030, "VERSION", GetLapicVersionFields), | |
161 | (0x080, "TASK PRIORITY", None), | |
162 | (0x0A0, "PROCESSOR PRIORITY", None), | |
163 | (0x0D0, "LOGICAL DEST", None), | |
164 | (0x0E0, "DEST FORMAT", None), | |
165 | (0x0F0, "SPURIOUS VECTOR", GetLapicSpuriousVectorFields), | |
166 | (0x100, "ISR[031:000]", None), | |
167 | (0x110, "ISR[063:032]", None), | |
168 | (0x120, "ISR[095:064]", None), | |
169 | (0x130, "ISR[127:096]", None), | |
170 | (0x140, "ISR[159:128]", None), | |
171 | (0x150, "ISR[191:160]", None), | |
172 | (0x160, "ISR[223:192]", None), | |
173 | (0x170, "ISR[225:224]", None), | |
174 | (0x180, "TMR[031:000]", None), | |
175 | (0x190, "TMR[063:032]", None), | |
176 | (0x1A0, "TMR[095:064]", None), | |
177 | (0x1B0, "TMR[127:096]", None), | |
178 | (0x1C0, "TMR[159:128]", None), | |
179 | (0x1D0, "TMR[191:160]", None), | |
180 | (0x1E0, "TMR[223:192]", None), | |
181 | (0x1F0, "TMR[225:224]", None), | |
182 | (0x200, "IRR[031:000]", None), | |
183 | (0x210, "IRR[063:032]", None), | |
184 | (0x220, "IRR[095:064]", None), | |
185 | (0x230, "IRR[127:096]", None), | |
186 | (0x240, "IRR[159:128]", None), | |
187 | (0x250, "IRR[191:160]", None), | |
188 | (0x260, "IRR[223:192]", None), | |
189 | (0x270, "IRR[225:224]", None), | |
190 | (0x280, "ERROR STATUS", None), | |
191 | (0x300, "Interrupt Command LO", GetApicFields), | |
192 | (0x310, "Interrupt Command HI", GetLapicIcrHiFields), | |
193 | (0x320, "LVT Timer", GetApicFields), | |
194 | (0x350, "LVT LINT0", GetApicFields), | |
195 | (0x360, "LVT LINT1", GetApicFields), | |
196 | (0x370, "LVT Error", GetApicFields), | |
197 | (0x340, "LVT PerfMon", GetApicFields), | |
198 | (0x330, "LVT Thermal", GetApicFields), | |
199 | (0x3e0, "Timer Divide", GetLapicTimerDivideFields), | |
200 | (0x380, "Timer Init Count", None), | |
201 | (0x390, "Timer Cur Count", None)] | |
202 | for reg in lapic_dump_table: | |
203 | reg_val = DoLapicRead32(reg[0], xnudefines.lcpu_self) | |
204 | if reg[2] == None: | |
205 | print "LAPIC[{:#05x}] {:21s}: {:#010x}".format(reg[0], reg[1], reg_val) | |
206 | else: | |
207 | print "LAPIC[{:#05x}] {:21s}: {:#010x} {:s}".format(reg[0], reg[1], | |
208 | reg_val, reg[2](reg_val)) | |
209 | ||
210 | ###################################### | |
211 | # IOAPIC Helper functions | |
212 | ###################################### | |
213 | def DoIoApicRead(offset): | |
214 | """ Read the specified IOAPIC register | |
215 | Params: | |
216 | offset: int - index of IOAPIC register to read | |
217 | Returns: | |
218 | int 32-bit read value | |
219 | """ | |
220 | WritePhysInt(ioapic_base_addr + ioapic_index_off, offset, 8) | |
221 | return ReadPhysInt(ioapic_base_addr + ioapic_data_off, 32) | |
222 | ||
223 | def DoIoApicWrite(offset, val): | |
224 | """ Write the specified IOAPIC register | |
225 | Params: | |
226 | offset: int - index of IOAPIC register to write | |
227 | Returns: | |
228 | True if success, False if error | |
229 | """ | |
230 | WritePhysInt(ioapic_base_addr + ioapic_index_off, offset, 8) | |
231 | return WritePhysInt(ioapic_base_addr + ioapic_data_off, val, 32) | |
232 | ||
233 | def DoIoApicDump(): | |
234 | """ Prints all IOAPIC registers | |
235 | """ | |
236 | # Show IOAPIC ID register | |
237 | ioapic_id = DoIoApicRead(0) | |
238 | print "IOAPIC[0x00] {:9s}: {:#010x}".format("ID", ioapic_id) | |
239 | # Show IOAPIC Version register | |
240 | ioapic_ver = DoIoApicRead(1) | |
241 | maxredir = ((ioapic_ver >> 16) & 0xff) + 1 | |
242 | print "IOAPIC[0x01] {:9s}: {:#010x}".format("VERSION", ioapic_ver) +\ | |
243 | " [MAXREDIR={:02d} PRQ={:d} VERSION={:#04x}]".format( | |
244 | maxredir, | |
245 | ioapic_ver >> 15 & 0x1, | |
246 | ioapic_ver & 0xff) | |
247 | # Show IOAPIC redirect regsiters | |
248 | for redir in range(maxredir): | |
249 | redir_val_lo = DoIoApicRead(0x10 + redir * 2) | |
250 | redir_val_hi = DoIoApicRead(0x10 + (redir * 2) + 1) | |
251 | print "IOAPIC[{:#04x}] IOREDIR{:02d}: {:#08x}{:08x} {:s}".format( | |
252 | 0x10 + (redir * 2), | |
253 | redir, | |
254 | redir_val_hi, | |
255 | redir_val_lo, | |
256 | GetApicFields(redir_val_lo)) | |
257 | ||
258 | ###################################### | |
259 | # LLDB commands | |
260 | ###################################### | |
261 | @lldb_command('lapic_read32') | |
262 | def LapicRead32(cmd_args=None): | |
263 | """ Read the LAPIC register at the specified offset. The CPU can | |
264 | be optionally specified | |
265 | Syntax: lapic_read32 <offset> [lcpu] | |
266 | """ | |
267 | if cmd_args == None or len(cmd_args) < 1: | |
268 | print LapicRead32.__doc__ | |
269 | return | |
270 | if not IsArchX86_64(): | |
271 | print "lapic_read32 not supported on this architecture." | |
272 | return | |
273 | ||
274 | lcpu = xnudefines.lcpu_self | |
275 | if len(cmd_args) > 1: | |
276 | lcpu = ArgumentStringToInt(cmd_args[1]) | |
277 | ||
278 | offset = ArgumentStringToInt(cmd_args[0]) | |
279 | read_val = DoLapicRead32(offset, lcpu) | |
280 | print "LAPIC[{:#05x}]: {:#010x}".format(offset, read_val) | |
281 | ||
282 | @lldb_command('lapic_write32') | |
283 | def LapicWrite32(cmd_args=None): | |
284 | """ Write the LAPIC register at the specified offset. The CPU can | |
285 | be optionally specified. Prints an error message if there was a | |
286 | failure. Prints nothing upon success. | |
287 | Syntax: lapic_write32 <offset> <val> [lcpu] | |
288 | """ | |
289 | if cmd_args == None or len(cmd_args) < 2: | |
290 | print LapicWrite32.__doc__ | |
291 | return | |
292 | if not IsArchX86_64(): | |
293 | print "lapic_write32 not supported on this architecture." | |
294 | return | |
295 | offset = ArgumentStringToInt(cmd_args[0]) | |
296 | write_val = ArgumentStringToInt(cmd_args[1]) | |
297 | lcpu = xnudefines.lcpu_self | |
298 | if len(cmd_args) > 2: | |
299 | lcpu = ArgumentStringToInt(cmd_args[2]) | |
300 | if not DoLapicWrite32(offset, write_val, lcpu): | |
301 | print "lapic_write32 FAILED" | |
302 | ||
303 | @lldb_command('lapic_dump') | |
304 | def LapicDump(cmd_args=None): | |
305 | """ Prints all LAPIC entries | |
306 | """ | |
307 | if not IsArchX86_64(): | |
308 | print "lapic_dump not supported on this architecture." | |
309 | return | |
310 | DoLapicDump() | |
311 | ||
312 | @lldb_command('ioapic_read32') | |
313 | def IoApicRead32(cmd_args=None): | |
314 | """ Read the IOAPIC register at the specified offset. | |
315 | Syntax: ioapic_read32 <offset> | |
316 | """ | |
317 | if cmd_args == None or len(cmd_args) < 1: | |
318 | print IoApicRead32.__doc__ | |
319 | return | |
320 | if not IsArchX86_64(): | |
321 | print "ioapic_read32 not supported on this architecture." | |
322 | return | |
323 | ||
324 | offset = ArgumentStringToInt(cmd_args[0]) | |
325 | read_val = DoIoApicRead(offset) | |
326 | print "IOAPIC[{:#04x}]: {:#010x}".format(offset, read_val) | |
327 | ||
328 | @lldb_command('ioapic_write32') | |
329 | def IoApicWrite32(cmd_args=None): | |
330 | """ Write the IOAPIC register at the specified offset. | |
331 | Syntax: ioapic_write32 <offset> <val> | |
332 | """ | |
333 | if cmd_args == None or len(cmd_args) < 2: | |
334 | print IoApicWrite32.__doc__ | |
335 | return | |
336 | if not IsArchX86_64(): | |
337 | print "ioapic_write32 not supported on this architecture." | |
338 | return | |
339 | ||
340 | offset = ArgumentStringToInt(cmd_args[0]) | |
341 | write_val = ArgumentStringToInt(cmd_args[1]) | |
342 | if not DoIoApicWrite(offset, write_val): | |
343 | print "ioapic_write32 FAILED" | |
344 | return | |
345 | ||
346 | @lldb_command('ioapic_dump') | |
347 | def IoApicDump(cmd_args=None): | |
348 | """ Prints all IOAPIC entries | |
349 | """ | |
350 | if not IsArchX86_64(): | |
351 | print "ioapic_dump not supported on this architecture." | |
352 | return | |
353 | DoIoApicDump() | |
354 |