]> git.saurik.com Git - apple/xnu.git/blob - tools/lldbmacros/apic.py
xnu-4570.71.2.tar.gz
[apple/xnu.git] / tools / lldbmacros / apic.py
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