Skip to content

Commit

Permalink
handle CONFIG_IO_STRICT_DEVMEM better
Browse files Browse the repository at this point in the history
  • Loading branch information
algrant-arm committed Jul 14, 2022
1 parent 6c298c1 commit 9365240
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 7 deletions.
18 changes: 15 additions & 3 deletions coresight-tools/csscan.py
Original file line number Diff line number Diff line change
Expand Up @@ -740,6 +740,7 @@ def __init__(self, td, offset, width, e):
self.width = width # entry width in bytes
self.descriptor = e # the 4-byte or 8-byte table entry (device offset, power req)
self.device = None # may be populated later
self.is_inaccessible = False # set to True if we can't create a device for it

def __str__(self):
s = "0x%x[0x%03x]: " % (self.table.base_address, self.offset)
Expand Down Expand Up @@ -837,13 +838,18 @@ def map(self, addr, write=False):
sorting that out.
The caller is also responsible for releasing the mapping when finished with.
If the kernel is built with CONFIG_IO_STRICT_DEVMEM, this mmap() may fail
with EPERM if the area is already registered to the kernel.
"""
try:
if write:
prot = (mmap.PROT_READ|mmap.PROT_WRITE)
else:
prot = mmap.PROT_READ
m = mmap.mmap(self.fno, self.page_size, mmap.MAP_SHARED, prot, offset=addr)
except PermissionError:
raise
except EnvironmentError as e:
print("** failed to map 0x%x size 0x%x on fileno %d (currently %u mappings): %s" % (addr, self.page_size, self.fno, self.n_mappings, e))
raise
Expand Down Expand Up @@ -946,7 +952,7 @@ def affinity_group(self, id):
def list_table(self, td, include_empty=False, recurse=True):
"""
Iterate (perhaps recursively) over a ROM Table, returning
table entries which contain device objects.
ROMTableEntry objects which contain device objects.
We assume ROM tables all have the same format. They may have a
vendor part number, and DEVARCH is not set, but the CIDR device class
Expand Down Expand Up @@ -988,6 +994,7 @@ def list_table(self, td, include_empty=False, recurse=True):
# ROM table points back to itself - shouldn't happen
continue
if e.device_address() in o_exclusions:
e.is_inaccessible = True
yield e
continue
# We don't want to fault when we encounter the same device in multiple
Expand All @@ -1004,7 +1011,12 @@ def list_table(self, td, include_empty=False, recurse=True):
# we aren't otherwise interested in devices. A ROM Table entry doesn't
# indicate that it points to a sub-table as opposed to some other device -
# we have to map the device and find out if it's another table.
d = self.create_device_at(e.device_address(), rom_table_entry=e)
try:
d = self.create_device_at(e.device_address(), rom_table_entry=e)
except PermissionError:
e.is_inaccessible = True
yield e
continue
e.device = d
# Fix up device affinity - in the absence of anywhere better.
# We could either do this using DEVAFF or heuristically.
Expand Down Expand Up @@ -2431,7 +2443,7 @@ def scan_rom(c, table_addr, recurse=True, detect_topology=False, detect_topology
devices = []
ts = []
for e in c.list_table(table, recurse=recurse):
assert e.device is not None or e.device_address() in o_exclusions
assert e.device is not None or e.is_inaccessible
if e.device is not None:
if e.device.is_coresight():
devices.append(e.device)
Expand Down
5 changes: 3 additions & 2 deletions coresight-tools/discovery.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,11 @@ This is a summary of the procedure if you haven't got a manufacturer datasheet o
* run the `csscan.py --topology` or `cstopology` tools to discover the CoreSight system topology and build a complete topology description.
* convert the topology description into any required formats, e.g. Linux device tree or ACPI tables.

Hints and tips
### Hints and tips

* Some devices have two or more separate CoreSight subsystems - one for the application cores and one for the management cores (usually Cortex-Ms). For self-hosted trace, the management subsystem can be mostly ignored, although it may share (and manage) a global CoreSight timestamp generator with the application trace subsystem.
* Access to the top-level ROM Table might cause lockups, or it may be necessary to use a workaround such as connecting an external JTAG device to cause on-chip logic to power-on the main debug subsystem. Vendor assistance may be needed.
* Individual devices might be powered-off or security-protected. In this case, even though the devices are listed in the ROM table, access to the device may lock up the system. If the devices relate to system management areas encountered during discovery, the discovery should be repeated with these areas excluded (some trial and error might be necessary). If they are devices needed for self-hosted trace, it may be necessary to ask the vendor how to enable access.
* A variety of IP, such as graphics units, DSPs etc. can generate trace, either in standard formats (e.g. MIPI STP) or custom formats - discovery of unknown types of trace source is normal. There is a risk of multiple trace sources using the same trace source identifier and being funnelled together, resulting in a corrupt trace stream. As it might not be known how to disable trace sources or set the 7-bit trace source identifier, it might be necessary to use an input port on a funnel to block trace from unknown sources.
* A variety of IP, such as graphics units, DSPs etc. can generate trace, either in standard formats (e.g. MIPI STP) or custom formats - discovery of unknown types of trace source is normal. Also, it is not guaranteed that all trace sources are discoverable via the system ROM table. There is a risk of multiple trace sources using the same trace source identifier and being funnelled together, resulting in a corrupt trace stream. As it might not be known how to disable trace sources or set the 7-bit trace source identifier, it might be necessary to use an input port on a funnel to block trace from unknown sources.
* Some chip families have a variety of different parts with different numbers of cores, and may exhibit chip-to-chip variation in device addresses (e.g. because all the parts are produced from the same die and different physical cores have been fused out). It's still unclear how chip-to-chip variation is best dealt with in system descriptions. It may be possible to rerun cslist on each chip to find physical addresses, without having to rerun the more invasive topology discovery procedure, if topology is described in terms of logical devices. Or the vendor may provide an alternative procedure for finding out which physical cores are enabled, which can be used to customise the system description file.
* Once CoreSight devices are discovered and registered with the Linux kernel, if the kernel is built with CONFIG_IO_STRICT_DEVMEM it will not permit userspace to map these addresses via /dev/mem, so tools such as `csscan.py` cannot be used to investigate them.
8 changes: 6 additions & 2 deletions coresight-tools/iommap.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

from __future__ import print_function

import os, ctypes, struct
import os, ctypes, struct, errno

# We support going via the syscall directly, as an alternative to using libc mmap().
# The rationale for this is now unclear, so disable it by default.
Expand Down Expand Up @@ -57,7 +57,7 @@ def get_syscall_numbers(fns):
if use_syscall:
[SYS_mmap, SYS_munmap] = get_syscall_numbers(["mmap", "munmap"])

libc = ctypes.CDLL(None)
libc = ctypes.CDLL(None, use_errno=True)
syscall = libc.syscall
libc_mmap = libc.mmap
libc_mmap.restype = ctypes.c_void_p
Expand All @@ -83,6 +83,10 @@ def __init__(self, fno, size, flags=MAP_SHARED, prot=(PROT_WRITE|PROT_READ), off
else:
self.addr = libc_mmap(0, size, prot, flags, fno, offset)
if (self.addr & 0xfff) == 0xfff:
# Mapping failed. Possible reasons:
# - CONFIG_IO_STRICT_DEVMEM and area is forbidden
if ctypes.get_errno() == errno.EPERM:
raise PermissionError
raise EnvironmentError

def close(self):
Expand Down

0 comments on commit 9365240

Please sign in to comment.