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