自定义配置
自定义 BWMON 调节器
你可以根据功耗和性能需求,从 kernel_platform/kernel/arch/arm64/boot/dts/qcom/sc7280.dtsi 文件中自定义 bwmon_opp_table 以进行 LLCC 和 DDR 投票。
该表包含 DDR 和 LLCC 的频率级别,每个级别根据流量转换为 LLCC 和 DDR 投票。
例如,以下 DTSI 条目根据 CPU 流量在 LLCC 到 DDR 之间投票,对应于 200 MHz,因为 800000 / w(其中 w = 4)等于 200,000。
llcc_bwmon_opp_table: opp-table {
compatible = "operating-points-v2";
opp-0 {
opp-peak-kBps = <800000>;
};
};
以下 DTSI 条目根据 CPU 和 LLCC 之间的 CPU 流量在 LLCC 上投票,对应于 150 MHz,因为 2400000 / w(其中 w = 16)等于 150,000:
cpu_bwmon_opp_table: opp-table {
compatible = "operating-points-v2";
opp-0 {
opp-peak-kBps = <2400000>;
};
};
在此示例中,w 表示你可以在一个周期内写入的字节数。
- 对于 DDR,此值为 4。每个通道可以在每个周期执行两个事务(DDR 内存),每个事务为 2 字节。
- 对于 LLCC,此值为 16。
自定义 Perflock
你可以运行 Perflock API,使用不同的调优参数执行用例,并调试 Perflock 问题。
Perflock API
要从用户空间软件中使用 Perflock API,请按照以下步骤操作:
- 在源文件中包含动态链接头文件:#include <dlfcn.h>。
- 使用 dlopen 加载库(libqti-perfd-client.so)。使用系统属性
ro.vendor.extension_library。 - 使用 dlsym 加载 perf_lock_acq() 和 perf_lock_rel() 符号。
- 声明一个整数变量以存储 perf_lock_acq() 的返回值。
- 使用所需的资源操作码和值对定义 perf_lock_opts。
- 使用指定的优化选项调用 perf_lock_acq() 以获取锁。
- 使用 perf_lock_rel() 释放锁。
- 在清理时使用 dlclose 卸载库。
以下示例代码显示了 Perflock API 的使用:
#include <dlfcn.h>
static void *qcopt_handle;
static int (*perf_lock_acq)(int handle, int duration, int list[], int numArgs);
static int (*perf_lock_rel)(int handle);
static int perf_lock_handle;
char opt_lib_path[PATH_MAX] = {0};
if (property_get("ro.vendor.extension_library", opt_lib_path, NULL) != 0) {
if ((qcopt_handle = dlopen(opt_lib_path, RTLD_NOW)) == NULL) {
error_out();
} else {
perf_lock_acq = (int (*)(int, int, int *, int))dlsym(qcopt_handle, "perf_lock_acq");
perf_lock_rel = (int (*)(int))dlsym(qcopt_handle, "perf_lock_rel");
}
}
int perf_lock_opts[2] = {MPCTLV3_MIN_ONLINE_CPU_CLUSTER_BIG, 0x2};
perf_lock_handle = perf_lock_acq(perf_lock_handle, 0, perf_lock_opts, 2);
:
:
// Code requiring perflock
:
:
:
perf_lock_rel(perf_lock_handle);
这个示例代码展示了如何动态加载 libqti-perfd-client.so 库并使用 perf_lock_acq 和 perf_lock_rel 函数来获取和释放性能锁。
Perflock 本地测试
Perflock 本地测试是一种工具,用于评估特定组合的 Perflock 操作码的有效性。
此工具位于 /usr/bin/ 目录下。
你可以将此工具作为一个用例来试验不同的 <资源, 操作码> 调优参数。一旦确认了所需的性能改进,可以将 Perflock 代码集成到你的软件中。
以下代码显示了语法:
perflock_native_test --acq <handle> <duration> <resource opcode, value, resource opcode, value,...>
以下是一些如何使用该工具的示例:
示例 1, 要为 Silver 集群获取 Perflock,并将最低频率设置为 1958400 KHz,持续 30 秒,运行以下命令:
perflock_native_test --acq 0 30000 0x44008100,1958400
示例 2, 要验证 Silver 集群的最低频率,运行以下命令:
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq
示例 3, 要从 syslog 验证 Perflock 日志,运行以下命令:
cat /var/log/syslog
示例日志输出:
perflock_native_test: ANDR-PERFLOCK-TESTERANDR-PERFLOCK-TESTER: initialize() 60: NRP: lib name libqti-perfd-client.so
perflock_native_test: ANDR-PERFLOCK-TESTERANDR-PERFLOCK-TESTER: main() 502: NRP: resource_list[0] = 44008100 //银核最低频率操作码
perflock_native_test: ANDR-PERFLOCK-TESTERANDR-PERFLOCK-TESTER: main() 502: NRP: resource_list[1] = 7a6 // 银核最低频率十六进制值
Debug Perflock
以下是一些用于调试 Perflock 问题的日志机制示例:
示例 1, 要验证 PerfHAL 服务是否可用,运行以下命令:
ls /usr/bin | grep perf
示例 2, 要验证 PerfHAL 服务的运行状态,运行以下命令:
systemctl status perf-hal
示例 3,要在 /var/log/syslog 中启用 Perflock 日志和追踪,运行以下命令:
echo debug.trace.perf=1 >> /etc/build.prop
echo vendor.debug.trace.perf=1 >> /etc/build.prop
reboot
自定义内存
你可以使用 kswapd 管理虚拟内存,使用水印调节系统内存,并通过内存切割定义特定子系统的内存区域。
Kswapd
kswapd 是一个管理虚拟内存的内核线程。当系统内存不足时,kswapd 被激活,通过识别文件缓存中使用频率较低的页面并将其移动到交换空间(ZRAM)来回收内存。
kswapd 执行以下操作:
- 监控系统的内存使用情况。
- 在后台执行交换活动,以保持最佳的自由内存水平。
Watermark
watermark是在内存参数上设置的阈值或限制,有助于调节系统内存的分配和利用率。
参数 | 描述 |
---|---|
/proc/sys/vm/min_free_kbytes |
|
/proc/sys/vm/watermark_scale_factor |
|
/proc/sys/vm/watermark_boost_factor |
|
有关更多信息,请参阅 内核文档。
内存切割
内存切割指的是内核无法访问的特定内存区域,称为 no-map 区域。这些区域为特定子系统(如调制解调器、相机、aDSP、cDSP 和 TrustZone)专用,并且对 Linux 内核不可访问。
这些内存切割在源代码 arch/arm64/boot/dts/qcom/qcm6490.dtsi 文件中定义。
它们属于 reserved-memory 节点,可以配置。
以下代码显示了 cDSP、相机、调制解调器和 TrustZone 子系统的 no-map 区域:
reserved-memory {
cdsp_secure_heap_mem: cdsp-secure-heap@81800000 {
reg = <0x0 0x81800000 0x0 0x1e00000>;
no-map;
};
camera_mem: camera@84300000 {
reg = <0x0 0x84300000 0x0 0x500000>;
no-map;
};
adsp_mem: adsp@86100000 {
reg = <0x0 0x86100000 0x0 0x2800000>;
no-map;
};
cdsp_mem: cdsp@88900000 {
reg = <0x0 0x88900000 0x0 0x1e00000>;
no-map;
};
mpss_mem: mpss@8b800000 {
reg = <0x0 0x8b800000 0x0 0xf600000>;
no-map;
};
tz_stat_mem: tz-stat@c0000000 {
reg = <0x0 0xc0000000 0x0 0x100000>;
no-map;
};
tags_mem: tags@c0100000 {
reg = <0x0 0xc0100000 0x0 0x1200000>;
no-map;
};
你可以根据产品需求调整保留内存切割区域。这可能涉及删除调制解调器切割区域或减少 TrustZone 应用内存切割区域的大小。
例如,以下代码片段展示了如何禁用调制解调器内存切割以进行内存优化:
reserved-memory {
mpss_mem: mpss@8b800000 {
reg = <0x0 0x8b800000 0x0 0xf600000>;
no-map;
status = "disabled";
};
在此代码中:
- 0x8b800000 是调制解调器区域的基地址。
- 0xf600000 是调制解调器区域的大小,即 246 MB。
- 添加 status = “disabled” 使该区域可供 Linux 内核使用。
以下示例代码片段展示了如何将 TrustZone 受信任应用内存切割大小从 28 MB(0x1c00000)减少到 20 MB(0x1400000):
Before | After |
---|---|
reserved memory { trusted_apps_mem: trusted_apps@c1800000 { reg = <0x0 0xc1800000 0x0 0x1c00000>; no-map; }; | reserved memory { trusted_apps_mem: trusted_apps@c1800000 { reg = <0x0 0xc1800000 0x0 0x1400000>; no-map; }; |