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