xref: /xnu-8796.121.2/tools/lldbmacros/pci.py (revision c54f35ca767986246321eb901baf8f5ff7923f6a)
1*c54f35caSApple OSS Distributionsfrom __future__ import absolute_import, print_function
2*c54f35caSApple OSS Distributions
3*c54f35caSApple OSS Distributionsfrom builtins import range
4*c54f35caSApple OSS Distributions
5*c54f35caSApple OSS Distributionsfrom xnu import *
6*c54f35caSApple OSS Distributions
7*c54f35caSApple OSS Distributions######################################
8*c54f35caSApple OSS Distributions# Helper functions
9*c54f35caSApple OSS Distributions######################################
10*c54f35caSApple OSS Distributionsdef GetMemMappedPciCfgAddrFromRegistry():
11*c54f35caSApple OSS Distributions    """ Retrieve the base address of the memory mapped PCI config space. It is
12*c54f35caSApple OSS Distributions        found in registry entry AppleACPIPlatformExpert, property acpi-mmcfg-seg0.
13*c54f35caSApple OSS Distributions        Returns:
14*c54f35caSApple OSS Distributions            int base address of memory mapped PCI config space
15*c54f35caSApple OSS Distributions    """
16*c54f35caSApple OSS Distributions    kgm_pci_cfg_base_default = 0xe0000000
17*c54f35caSApple OSS Distributions    acpi_pe_obj = FindRegistryObjectRecurse(kern.globals.gRegistryRoot,
18*c54f35caSApple OSS Distributions        "AppleACPIPlatformExpert")
19*c54f35caSApple OSS Distributions    if acpi_pe_obj is None:
20*c54f35caSApple OSS Distributions        print("Could not find AppleACPIPlatformExpert in registry, \
21*c54f35caSApple OSS Distributions        using default base address for memory mapped PCI config space")
22*c54f35caSApple OSS Distributions        return kgm_pci_cfg_base_default
23*c54f35caSApple OSS Distributions    entry = kern.GetValueFromAddress(int(acpi_pe_obj), 'IOService *')
24*c54f35caSApple OSS Distributions    acpi_mmcfg_seg_prop = LookupKeyInPropTable(entry.fPropertyTable, "acpi-mmcfg-seg0")
25*c54f35caSApple OSS Distributions    if acpi_mmcfg_seg_prop is None:
26*c54f35caSApple OSS Distributions        print("Could not find acpi-mmcfg-seg0 property, \
27*c54f35caSApple OSS Distributions        using default base address for memory mapped PCI config space")
28*c54f35caSApple OSS Distributions        return kgm_pci_cfg_base_default
29*c54f35caSApple OSS Distributions    else:
30*c54f35caSApple OSS Distributions        return int(GetNumber(acpi_mmcfg_seg_prop))
31*c54f35caSApple OSS Distributions
32*c54f35caSApple OSS Distributions@static_var('kgm_pci_cfg_base', -1)
33*c54f35caSApple OSS Distributionsdef GetMemMappedPciCfgAddrBase():
34*c54f35caSApple OSS Distributions    """ Returns the base address of the memory mapped PCI config space. The address
35*c54f35caSApple OSS Distributions        is retrieved once from the registry, and is remembered for all subsequent
36*c54f35caSApple OSS Distributions        calls to this function
37*c54f35caSApple OSS Distributions        Returns:
38*c54f35caSApple OSS Distributions            int base address of memory mapped PCI config space
39*c54f35caSApple OSS Distributions    """
40*c54f35caSApple OSS Distributions    if GetMemMappedPciCfgAddrBase.kgm_pci_cfg_base == -1:
41*c54f35caSApple OSS Distributions        # Retrieve the base address from the registry if it hasn't been
42*c54f35caSApple OSS Distributions        # initialized yet
43*c54f35caSApple OSS Distributions        GetMemMappedPciCfgAddrBase.kgm_pci_cfg_base = GetMemMappedPciCfgAddrFromRegistry()
44*c54f35caSApple OSS Distributions    return GetMemMappedPciCfgAddrBase.kgm_pci_cfg_base
45*c54f35caSApple OSS Distributions
46*c54f35caSApple OSS Distributionsdef MakeMemMappedPciCfgAddr(bus, dev, func, offs):
47*c54f35caSApple OSS Distributions    """ Construct the memory address for the PCI config register specified by the
48*c54f35caSApple OSS Distributions        bus, device, function, and offset
49*c54f35caSApple OSS Distributions        Params:
50*c54f35caSApple OSS Distributions            bus, dev, func, offs: int - bus, device, function, and offset that specifies
51*c54f35caSApple OSS Distributions            the PCI config space register
52*c54f35caSApple OSS Distributions        Returns:
53*c54f35caSApple OSS Distributions            int - the physical memory address that maps to the PCI config space register
54*c54f35caSApple OSS Distributions    """
55*c54f35caSApple OSS Distributions    return GetMemMappedPciCfgAddrBase() | (bus << 20) | (dev << 15) | (func << 12) | offs
56*c54f35caSApple OSS Distributions
57*c54f35caSApple OSS Distributionsdef DoPciCfgRead(bits, bus, dev, func, offs):
58*c54f35caSApple OSS Distributions    """ Helper function that performs PCI config space read
59*c54f35caSApple OSS Distributions        Params:
60*c54f35caSApple OSS Distributions            bits: int - bit width of access: 8, 16, or 32 bits
61*c54f35caSApple OSS Distributions            bus, dev, func, offs: int - PCI config bus, device, function and offset
62*c54f35caSApple OSS Distributions        Returns:
63*c54f35caSApple OSS Distributions            int - the value read from PCI config space
64*c54f35caSApple OSS Distributions    """
65*c54f35caSApple OSS Distributions    phys_addr = MakeMemMappedPciCfgAddr(bus, dev, func, offs)
66*c54f35caSApple OSS Distributions    return ReadPhysInt(phys_addr, bits)
67*c54f35caSApple OSS Distributions
68*c54f35caSApple OSS Distributionsdef DoPciCfgWrite(bits, bus, dev, func, offs, val):
69*c54f35caSApple OSS Distributions    """ Helper function that performs PCI config space write
70*c54f35caSApple OSS Distributions        Params:
71*c54f35caSApple OSS Distributions            bits: int - bit width of access: 8, 16, or 32 bits
72*c54f35caSApple OSS Distributions            bus, dev, func, offs: int - PCI config bus, device, function and offset
73*c54f35caSApple OSS Distributions        Returns:
74*c54f35caSApple OSS Distributions            boolean - True upon success, False otherwise
75*c54f35caSApple OSS Distributions    """
76*c54f35caSApple OSS Distributions    phys_addr = MakeMemMappedPciCfgAddr(bus, dev, func, offs)
77*c54f35caSApple OSS Distributions    return WritePhysInt(phys_addr, val, bits)
78*c54f35caSApple OSS Distributions
79*c54f35caSApple OSS Distributionsdef ShowPciCfgBytes(bus, dev, func, offset):
80*c54f35caSApple OSS Distributions    """ Prints 16 bytes of PCI config space starting at specified offset
81*c54f35caSApple OSS Distributions        Params:
82*c54f35caSApple OSS Distributions            bus, dev, func, offset: int - bus, dev, function, and offset of the
83*c54f35caSApple OSS Distributions            PCI config space register
84*c54f35caSApple OSS Distributions    """
85*c54f35caSApple OSS Distributions    # Print mem-mapped address at beginning of each 16-byte line
86*c54f35caSApple OSS Distributions    phys_addr = MakeMemMappedPciCfgAddr(bus, dev, func, offset)
87*c54f35caSApple OSS Distributions    read_vals = [DoPciCfgRead(32, bus, dev, func, offset + byte)
88*c54f35caSApple OSS Distributions                    for byte in range(0, 16, 4)]
89*c54f35caSApple OSS Distributions    # It would be nicer to have a shorter format that we could loop
90*c54f35caSApple OSS Distributions    # over, but each call to print results in a newline which
91*c54f35caSApple OSS Distributions    # would prevent us from printing all 16 bytes on one line.
92*c54f35caSApple OSS Distributions    bytes_fmt = "{:08x}:" + "{:02x} " * 16
93*c54f35caSApple OSS Distributions    print(bytes_fmt.format(
94*c54f35caSApple OSS Distributions        phys_addr,
95*c54f35caSApple OSS Distributions        read_vals[0] & 0xff, (read_vals[0] >> 8) & 0xff,
96*c54f35caSApple OSS Distributions        (read_vals[0] >> 16) & 0xff, (read_vals[0] >> 24) & 0xff,
97*c54f35caSApple OSS Distributions        read_vals[1] & 0xff, (read_vals[1] >> 8) & 0xff,
98*c54f35caSApple OSS Distributions        (read_vals[1] >> 16) & 0xff, (read_vals[1] >> 24) & 0xff,
99*c54f35caSApple OSS Distributions        read_vals[2] & 0xff, (read_vals[2] >> 8) & 0xff,
100*c54f35caSApple OSS Distributions        (read_vals[2] >> 16) & 0xff, (read_vals[2] >> 24) & 0xff,
101*c54f35caSApple OSS Distributions        read_vals[3] & 0xff, (read_vals[3] >> 8) & 0xff,
102*c54f35caSApple OSS Distributions        (read_vals[3] >> 16) & 0xff, (read_vals[3] >> 24) & 0xff))
103*c54f35caSApple OSS Distributions
104*c54f35caSApple OSS Distributionsdef DoPciCfgDump(bus, dev, func):
105*c54f35caSApple OSS Distributions    """ Dumps PCI config space of the PCI device specified by bus, dev, function
106*c54f35caSApple OSS Distributions        Params:
107*c54f35caSApple OSS Distributions            bus, dev, func: int - bus, dev, function of PCI config space to dump
108*c54f35caSApple OSS Distributions    """
109*c54f35caSApple OSS Distributions    # Check for a valid PCI device
110*c54f35caSApple OSS Distributions    vendor_id = DoPciCfgRead(16, bus, dev, func, 0)
111*c54f35caSApple OSS Distributions    if (vendor_id == 0xbad10ad) or not (vendor_id > 0 and vendor_id < 0xffff):
112*c54f35caSApple OSS Distributions        return
113*c54f35caSApple OSS Distributions    # Show the standard PCI config space
114*c54f35caSApple OSS Distributions    print("address: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n")
115*c54f35caSApple OSS Distributions    print("--------------------------------------------------------")
116*c54f35caSApple OSS Distributions    for offset in range(0, 256, 16):
117*c54f35caSApple OSS Distributions        ShowPciCfgBytes(bus, dev, func, offset)
118*c54f35caSApple OSS Distributions    # Check for PCIE extended capability config space
119*c54f35caSApple OSS Distributions    if DoPciCfgRead(8, bus, dev, func, 256) < 0xff:
120*c54f35caSApple OSS Distributions        print(" \n")
121*c54f35caSApple OSS Distributions        for offset in range(256, 4096, 16):
122*c54f35caSApple OSS Distributions            ShowPciCfgBytes(bus, dev, func, offset)
123*c54f35caSApple OSS Distributions
124*c54f35caSApple OSS Distributionsdef DoPciCfgScan(max_bus, dump):
125*c54f35caSApple OSS Distributions    """ Do a PCI config scan starting at bus 0 up to specified max bus
126*c54f35caSApple OSS Distributions        Params:
127*c54f35caSApple OSS Distributions            max_bus: int - maximum bus to scan
128*c54f35caSApple OSS Distributions            dump: bool - if True, dump the config space of each scanned device
129*c54f35caSApple OSS Distributions                         if False, print basic information of each scanned device
130*c54f35caSApple OSS Distributions    """
131*c54f35caSApple OSS Distributions    max_dev  = 32
132*c54f35caSApple OSS Distributions    max_func = 8
133*c54f35caSApple OSS Distributions    bdfs = ({'bus':bus, 'dev':dev, 'func':func}
134*c54f35caSApple OSS Distributions            for bus in range(max_bus)
135*c54f35caSApple OSS Distributions            for dev in range(max_dev)
136*c54f35caSApple OSS Distributions            for func in range(max_func))
137*c54f35caSApple OSS Distributions    fmt_string = "{:03x}:" * 3 + " " + \
138*c54f35caSApple OSS Distributions        "{:02x}" * 2 + "   " + \
139*c54f35caSApple OSS Distributions        "{:02x}" * 2 + "    {:02x} | " + \
140*c54f35caSApple OSS Distributions        "{:02x}" * 3
141*c54f35caSApple OSS Distributions    for bdf in bdfs:
142*c54f35caSApple OSS Distributions        bus = bdf['bus']
143*c54f35caSApple OSS Distributions        dev = bdf['dev']
144*c54f35caSApple OSS Distributions        func = bdf['func']
145*c54f35caSApple OSS Distributions        vend_dev_id = DoPciCfgRead(32, bus, dev, func, 0)
146*c54f35caSApple OSS Distributions        if not (vend_dev_id > 0 and vend_dev_id < 0xffffffff):
147*c54f35caSApple OSS Distributions            continue
148*c54f35caSApple OSS Distributions        if dump == False:
149*c54f35caSApple OSS Distributions            class_rev_id = DoPciCfgRead(32, bus, dev, func, 8)
150*c54f35caSApple OSS Distributions            print(fmt_string.format(
151*c54f35caSApple OSS Distributions                bus, dev, func,
152*c54f35caSApple OSS Distributions                (vend_dev_id >> 8) & 0xff, vend_dev_id & 0xff,
153*c54f35caSApple OSS Distributions                (vend_dev_id >> 24) & 0xff, (vend_dev_id >> 16) & 0xff,
154*c54f35caSApple OSS Distributions                class_rev_id & 0xff, (class_rev_id >> 24) & 0xff,
155*c54f35caSApple OSS Distributions                (class_rev_id >> 16) & 0xff, (class_rev_id >> 8) & 0xff))
156*c54f35caSApple OSS Distributions        else:
157*c54f35caSApple OSS Distributions            print("{:03x}:{:03x}:{:03x}".format(bus, dev, func))
158*c54f35caSApple OSS Distributions            DoPciCfgDump(bus, dev, func)
159*c54f35caSApple OSS Distributions
160*c54f35caSApple OSS Distributions######################################
161*c54f35caSApple OSS Distributions# LLDB commands
162*c54f35caSApple OSS Distributions######################################
163*c54f35caSApple OSS Distributions@lldb_command('pci_cfg_read')
164*c54f35caSApple OSS Distributionsdef PciCfgRead(cmd_args=None):
165*c54f35caSApple OSS Distributions    """ Read PCI config space at the specified bus, device, function, and offset
166*c54f35caSApple OSS Distributions        Syntax: pci_cfg_read <bits> <bus> <device> <function> <offset>
167*c54f35caSApple OSS Distributions            bits: 8, 16, 32
168*c54f35caSApple OSS Distributions    """
169*c54f35caSApple OSS Distributions    if cmd_args == None or len(cmd_args) < 5:
170*c54f35caSApple OSS Distributions        print(PciCfgRead.__doc__)
171*c54f35caSApple OSS Distributions        return
172*c54f35caSApple OSS Distributions
173*c54f35caSApple OSS Distributions    bits = ArgumentStringToInt(cmd_args[0])
174*c54f35caSApple OSS Distributions    bus  = ArgumentStringToInt(cmd_args[1])
175*c54f35caSApple OSS Distributions    dev  = ArgumentStringToInt(cmd_args[2])
176*c54f35caSApple OSS Distributions    func = ArgumentStringToInt(cmd_args[3])
177*c54f35caSApple OSS Distributions    offs = ArgumentStringToInt(cmd_args[4])
178*c54f35caSApple OSS Distributions
179*c54f35caSApple OSS Distributions    read_val = DoPciCfgRead(bits, bus, dev, func, offs)
180*c54f35caSApple OSS Distributions    if read_val == 0xbad10ad:
181*c54f35caSApple OSS Distributions        print("ERROR: Failed to read PCI config space")
182*c54f35caSApple OSS Distributions        return
183*c54f35caSApple OSS Distributions
184*c54f35caSApple OSS Distributions    format_for_bits = {8:"{:#04x}", 16:"{:#06x}", 32:"{:#010x}"}
185*c54f35caSApple OSS Distributions    phys_addr = MakeMemMappedPciCfgAddr(bus, dev, func, offs)
186*c54f35caSApple OSS Distributions    fmt_string = "{:08x}: " + format_for_bits[bits]
187*c54f35caSApple OSS Distributions    print(fmt_string.format(phys_addr, read_val))
188*c54f35caSApple OSS Distributions
189*c54f35caSApple OSS Distributionslldb_alias('pci_cfg_read8', 'pci_cfg_read 8')
190*c54f35caSApple OSS Distributionslldb_alias('pci_cfg_read16', 'pci_cfg_read 16')
191*c54f35caSApple OSS Distributionslldb_alias('pci_cfg_read32', 'pci_cfg_read 32')
192*c54f35caSApple OSS Distributions
193*c54f35caSApple OSS Distributions@lldb_command('pci_cfg_write')
194*c54f35caSApple OSS Distributionsdef PciCfgWrite(cmd_args=None):
195*c54f35caSApple OSS Distributions    """ Write PCI config space at the specified bus, device, function, and offset
196*c54f35caSApple OSS Distributions        Syntax: pci_cfg_write <bits> <bus> <device> <function> <offset> <write val>
197*c54f35caSApple OSS Distributions            bits: 8, 16, 32
198*c54f35caSApple OSS Distributions
199*c54f35caSApple OSS Distributions        Prints an error message if there was a problem
200*c54f35caSApple OSS Distributions        Prints nothing upon success.
201*c54f35caSApple OSS Distributions    """
202*c54f35caSApple OSS Distributions    if cmd_args == None or len(cmd_args) < 6:
203*c54f35caSApple OSS Distributions        print(PciCfgWrite.__doc__)
204*c54f35caSApple OSS Distributions        return
205*c54f35caSApple OSS Distributions
206*c54f35caSApple OSS Distributions    bits = ArgumentStringToInt(cmd_args[0])
207*c54f35caSApple OSS Distributions    bus  = ArgumentStringToInt(cmd_args[1])
208*c54f35caSApple OSS Distributions    dev  = ArgumentStringToInt(cmd_args[2])
209*c54f35caSApple OSS Distributions    func = ArgumentStringToInt(cmd_args[3])
210*c54f35caSApple OSS Distributions    offs = ArgumentStringToInt(cmd_args[4])
211*c54f35caSApple OSS Distributions    write_val = ArgumentStringToInt(cmd_args[5])
212*c54f35caSApple OSS Distributions
213*c54f35caSApple OSS Distributions    if DoPciCfgWrite(bits, bus, dev, func, offs, write_val) == False:
214*c54f35caSApple OSS Distributions        print("ERROR: Failed to write PCI config space")
215*c54f35caSApple OSS Distributions
216*c54f35caSApple OSS Distributionslldb_alias('pci_cfg_write8', 'pci_cfg_write 8')
217*c54f35caSApple OSS Distributionslldb_alias('pci_cfg_write16', 'pci_cfg_write 16')
218*c54f35caSApple OSS Distributionslldb_alias('pci_cfg_write32', 'pci_cfg_write 32')
219*c54f35caSApple OSS Distributions
220*c54f35caSApple OSS Distributions@lldb_command('pci_cfg_dump')
221*c54f35caSApple OSS Distributionsdef PciCfgDump(cmd_args=None):
222*c54f35caSApple OSS Distributions    """ Dump PCI config space for specified bus, device, and function
223*c54f35caSApple OSS Distributions        If an invalid/inaccessible PCI device is specified, nothing will
224*c54f35caSApple OSS Distributions        be printed out.
225*c54f35caSApple OSS Distributions        Syntax: pci_cfg_dump <bus> <dev> <fuction>
226*c54f35caSApple OSS Distributions    """
227*c54f35caSApple OSS Distributions    if cmd_args == None or len(cmd_args) < 3:
228*c54f35caSApple OSS Distributions        print(PciCfgDump.__doc__)
229*c54f35caSApple OSS Distributions        return
230*c54f35caSApple OSS Distributions
231*c54f35caSApple OSS Distributions    bus  = ArgumentStringToInt(cmd_args[0])
232*c54f35caSApple OSS Distributions    dev  = ArgumentStringToInt(cmd_args[1])
233*c54f35caSApple OSS Distributions    func = ArgumentStringToInt(cmd_args[2])
234*c54f35caSApple OSS Distributions
235*c54f35caSApple OSS Distributions    DoPciCfgDump(bus, dev, func)
236*c54f35caSApple OSS Distributions
237*c54f35caSApple OSS Distributions@lldb_command('pci_cfg_scan')
238*c54f35caSApple OSS Distributionsdef PciCfgScan(cmd_args=None):
239*c54f35caSApple OSS Distributions    """ Scan for pci devices. The maximum bus number to be scanned defaults to 8,
240*c54f35caSApple OSS Distributions        but can be specified as an argument
241*c54f35caSApple OSS Distributions        Syntax: pci_cfg_scan [max bus number]
242*c54f35caSApple OSS Distributions    """
243*c54f35caSApple OSS Distributions    if cmd_args == None or len(cmd_args) == 0:
244*c54f35caSApple OSS Distributions        max_bus = 8
245*c54f35caSApple OSS Distributions    elif len(cmd_args) == 1:
246*c54f35caSApple OSS Distributions        max_bus = ArgumentStringToInt(cmd_args[0])
247*c54f35caSApple OSS Distributions    else:
248*c54f35caSApple OSS Distributions        print(PciCfgScan.__doc__)
249*c54f35caSApple OSS Distributions        return
250*c54f35caSApple OSS Distributions
251*c54f35caSApple OSS Distributions    print("bus:dev:fcn: vendor device rev | class")
252*c54f35caSApple OSS Distributions    print("--------------------------------------")
253*c54f35caSApple OSS Distributions    DoPciCfgScan(max_bus, False)
254*c54f35caSApple OSS Distributions
255*c54f35caSApple OSS Distributions@lldb_command('pci_cfg_dump_all')
256*c54f35caSApple OSS Distributionsdef PciCfgDumpAll(cmd_args=None):
257*c54f35caSApple OSS Distributions    """ Dump config space for all scanned PCI devices. The maximum bus number to
258*c54f35caSApple OSS Distributions        be scanned defaults to 8, but can be specified as an argument
259*c54f35caSApple OSS Distributions        Syntax: pci_cfg_dump_all [max bus number]
260*c54f35caSApple OSS Distributions    """
261*c54f35caSApple OSS Distributions    if cmd_args == None or len(cmd_args) == 0:
262*c54f35caSApple OSS Distributions        max_bus = 8
263*c54f35caSApple OSS Distributions    elif len(cmd_args) == 1:
264*c54f35caSApple OSS Distributions        max_bus = ArgumentStringToInt(cmd_args[0])
265*c54f35caSApple OSS Distributions    else:
266*c54f35caSApple OSS Distributions        print(PciCfgDumpAll.__doc__)
267*c54f35caSApple OSS Distributions        return
268*c54f35caSApple OSS Distributions
269*c54f35caSApple OSS Distributions    DoPciCfgScan(max_bus, True)
270