Skip to content

Commit b6c23a5

Browse files
committed
TPMI: Improve read speed
When reading a 64-bit registers (actually all of them are 64-bit) - avoid opening the 'mem_dump' file twice. Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
1 parent 896a90c commit b6c23a5

2 files changed

Lines changed: 117 additions & 61 deletions

File tree

pepclibs/TPMI.py

Lines changed: 101 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1354,48 +1354,6 @@ def _adjust_ufs_offset(self, addr: str, instance: int, cluster: int, offset: int
13541354
# subtract 16 bytes to get the correct offset within the cluster.
13551355
return offset + coffset - _UFS_HEADER_SIZE
13561356

1357-
def _read(self,
1358-
fname: str,
1359-
addr: str,
1360-
instance: int,
1361-
cluster: int,
1362-
regname: str,
1363-
offset: int,
1364-
mdmap: _MDMapType) -> int:
1365-
"""
1366-
Read a TPMI register value from the TPMI debugfs 'mem_dump' file.
1367-
1368-
Args:
1369-
fname: Name of the TPMI feature.
1370-
addr: TPMI device PCI address.
1371-
instance: The instance number of the TPMI feature.
1372-
cluster: The cluster number.
1373-
regname: The name of the register to read.
1374-
offset: The offset of the register within the feature.
1375-
mdmap: The memory dump map (mdmap) for the TPMI feature.
1376-
1377-
Returns:
1378-
The integer value of the TPMI register.
1379-
"""
1380-
1381-
self._validate_instance_offset(fname, addr, instance, regname, offset, mdmap)
1382-
1383-
path = self._get_debugfs_feature_path(addr, fname)
1384-
path = path / "mem_dump"
1385-
1386-
if cluster > 0:
1387-
offset = self._adjust_ufs_offset(addr, instance, cluster, offset)
1388-
1389-
with self._pman.open(path, "r") as fobj:
1390-
fobj.seek(mdmap[instance][offset])
1391-
val = fobj.read(8)
1392-
1393-
_LOG.debug("Read 0x%s: feature '%s', register '%s', offset '%#x', file: %s, file offset %d",
1394-
val, fname, regname, offset, path, mdmap[instance][offset])
1395-
1396-
what = f"value of register '{regname}' (offset '{offset:#x}') of TPMI feature '{fname}'"
1397-
return Trivial.str_to_int(val, base=16, what=what)
1398-
13991357
def _get_bfdict(self, fname: str, regname: str, bfname: str) -> BFDictTypedDict:
14001358
"""
14011359
Retrieve the bit field definition for a specified TPMI register.
@@ -1455,6 +1413,99 @@ def _set_bitfield(self, regval: int, bitval: int, fname: str, regname: str, bfna
14551413
regval ^= regval & bfdict["bitmask"]
14561414
return regval | (bitval << bfdict["bitshift"])
14571415

1416+
def _read32(self,
1417+
fname: str,
1418+
addr: str,
1419+
instance: int,
1420+
cluster: int,
1421+
regname: str,
1422+
offset: int,
1423+
mdmap: _MDMapType) -> int:
1424+
"""
1425+
Read a 32-bit TPMI register value from the TPMI debugfs 'mem_dump' file.
1426+
1427+
Args:
1428+
fname: Name of the TPMI feature.
1429+
addr: TPMI device PCI address.
1430+
instance: The instance number of the TPMI feature.
1431+
cluster: The cluster number.
1432+
regname: The name of the register to read.
1433+
offset: The offset of the register within the feature.
1434+
mdmap: The memory dump map (mdmap) for the TPMI feature.
1435+
1436+
Returns:
1437+
The integer value of the TPMI register.
1438+
"""
1439+
1440+
self._validate_instance_offset(fname, addr, instance, regname, offset, mdmap)
1441+
1442+
path = self._get_debugfs_feature_path(addr, fname)
1443+
path = path / "mem_dump"
1444+
1445+
if cluster > 0:
1446+
offset = self._adjust_ufs_offset(addr, instance, cluster, offset)
1447+
1448+
with self._pman.open(path, "r") as fobj:
1449+
fobj.seek(mdmap[instance][offset])
1450+
val = fobj.read(8)
1451+
1452+
what = f"value of '{fname}' register '{regname}' (offset '{offset:#x}')"
1453+
return Trivial.str_to_int(val, base=16, what=what)
1454+
1455+
def _read64(self,
1456+
fname: str,
1457+
addr: str,
1458+
instance: int,
1459+
cluster: int,
1460+
regname: str,
1461+
offset: int,
1462+
mdmap: _MDMapType) -> int:
1463+
"""
1464+
Read a 64-bit TPMI register value from the TPMI debugfs 'mem_dump' file.
1465+
1466+
Args:
1467+
fname: Name of the TPMI feature.
1468+
addr: TPMI device PCI address.
1469+
instance: The instance number of the TPMI feature.
1470+
cluster: The cluster number.
1471+
regname: The name of the register to read.
1472+
offset: The offset of the register within the feature.
1473+
mdmap: The memory dump map (mdmap) for the TPMI feature.
1474+
1475+
Returns:
1476+
The integer value of the TPMI register.
1477+
"""
1478+
1479+
self._validate_instance_offset(fname, addr, instance, regname, offset, mdmap)
1480+
1481+
path = self._get_debugfs_feature_path(addr, fname)
1482+
path = path / "mem_dump"
1483+
1484+
if cluster > 0:
1485+
offset = self._adjust_ufs_offset(addr, instance, cluster, offset)
1486+
1487+
file_offset0 = mdmap[instance][offset]
1488+
file_offset1 = mdmap[instance][offset + 4]
1489+
read_len = file_offset1 - file_offset0 + 8
1490+
1491+
if read_len < 16:
1492+
raise Error(f"BUG: invalid read length '{read_len}' for 64-bit register '{regname}' "
1493+
f"(offset '{offset:#x}') of TPMI feature '{fname}'")
1494+
1495+
with self._pman.open(path, "r") as fobj:
1496+
fobj.seek(file_offset0)
1497+
val_str = fobj.read(read_len)
1498+
1499+
# The 'val_str' contains two 32-bit hex values, 8 characters each. The first value at the
1500+
# beginning, and the second value at the end.
1501+
what = f"lower 32 bits of '{fname}' register '{regname}' (offset '{offset:#x}')"
1502+
val_low = Trivial.str_to_int(val_str[:8], base=16, what=what)
1503+
what = f"upper 32 bits of '{fname}' register '{regname}' (offset '{offset + 4:#x}')"
1504+
val_high = Trivial.str_to_int(val_str[-8:], base=16, what=what)
1505+
val = val_low + (val_high << 32)
1506+
1507+
return val
1508+
14581509
def _read_register(self,
14591510
fname: str,
14601511
addr: str,
@@ -1485,15 +1536,15 @@ def _read_register(self,
14851536
width = regdict["width"]
14861537

14871538
if not mdmap:
1488-
_mdmap = self._get_mdmap(fname, addr)
1489-
else:
1490-
_mdmap = mdmap
1539+
mdmap = self._get_mdmap(fname, addr)
14911540

1492-
# TODO: Make one read operation for 64-bit registers.
1493-
val = self._read(fname, addr, instance, cluster, regname, offset, _mdmap)
1494-
if width > 32:
1495-
val_high = self._read(fname, addr, instance, cluster, regname, offset + 4, _mdmap) << 32
1496-
val += val_high
1541+
if width == 32:
1542+
val = self._read32(fname, addr, instance, cluster, regname, offset, mdmap)
1543+
elif width == 64:
1544+
val = self._read64(fname, addr, instance, cluster, regname, offset, mdmap)
1545+
else:
1546+
raise Error(f"Unsupported TPMI register width '{width}' for register '{regname}' "
1547+
f"in feature '{fname}'{self._pman.hostmsg}")
14971548

14981549
if bfname:
14991550
val = self._get_bitfield(val, fname, regname, bfname)

tests/test_uncore_freq.py

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -641,6 +641,10 @@ def test_freq_cross_mechanisms(params: _TestParamsTypedDict):
641641
params: The test parameters.
642642
"""
643643

644+
if common.is_emulated(params["pman"]):
645+
pytest.skip("The cross-mechanism uncore frequency test is not supported on emulated "
646+
"environments")
647+
644648
all_dies = params["cpuinfo"].get_all_dies()
645649

646650
uncfreq_objs: tuple[_UncoreFreqObjType, _UncoreFreqObjType]
@@ -666,26 +670,27 @@ def test_freq_cross_mechanisms(params: _TestParamsTypedDict):
666670

667671
# Set min and max frequencies to known values using the first mechanism.
668672
uncfreq_obj0.set_min_freq_dies(min_freq, {package: [die]})
673+
uncfreq_obj0.set_min_freq_dies(min_freq, {package: [die]})
669674
uncfreq_obj0.set_max_freq_dies(max_freq, {package: [die]})
670675

671-
# Set the min uncore frequency to the middle value using the first mechanism.
672-
uncfreq_obj0.set_min_freq_dies(mid_freq, {package: [die]})
676+
# Set the min uncore frequency to the middle value using the second mechanism.
677+
uncfreq_obj1 = uncfreq_objs[1]
678+
uncfreq_obj1.set_min_freq_dies(mid_freq, {package: [die]})
673679

674-
uncfreq_obj1 = uncfreq_objs[0]
675-
# Read the min uncore frequency using the second mechanism and check it.
676-
rd_pkg, rd_die, rd_freq = next(uncfreq_obj1.get_min_freq_dies({package: [die]}))
680+
# Read the min uncore frequency using the first mechanism and check it.
681+
rd_pkg, rd_die, rd_freq = next(uncfreq_obj0.get_min_freq_dies({package: [die]}))
677682
assert rd_pkg == package and rd_die == die, \
678683
f"Expected package {package} and die {die}, but got package {rd_pkg} " \
679684
f"and die {rd_die}"
680685
assert rd_freq == mid_freq, \
681686
f"Set min. uncore frequency to {mid_freq} for ({package}, {die}) via " \
682-
f"{uncfreq_obj0.mname} but got {rd_freq} via {uncfreq_obj1.mname}"
687+
f"{uncfreq_obj1.mname} but got {rd_freq} via {uncfreq_obj0.mname}"
683688

684-
# Set the min uncore frequency to the original value using the second mechanism.
685-
uncfreq_obj1.set_min_freq_dies(min_freq, {package: [die]})
689+
# Set the min uncore frequency to the original value using the first mechanism.
690+
uncfreq_obj0.set_min_freq_dies(min_freq, {package: [die]})
686691

687-
# Verify that the original value is restored using the first mechanism.
688-
_, _, rd_freq = next(uncfreq_obj0.get_min_freq_dies({package: [die]}))
692+
# Verify that the original value is restored using the second mechanism.
693+
_, _, rd_freq = next(uncfreq_obj1.get_min_freq_dies({package: [die]}))
689694
assert rd_freq == min_freq, \
690695
f"Set min. uncore frequency to {min_freq} for ({package}, {die}) via " \
691-
f"{uncfreq_obj1.mname} but got {rd_freq} via {uncfreq_obj0.mname}"
696+
f"{uncfreq_obj0.mname} but got {rd_freq} via {uncfreq_obj1.mname}"

0 commit comments

Comments
 (0)