diff --git a/.gitignore b/.gitignore index ce82387c15..52e2c4052c 100644 --- a/.gitignore +++ b/.gitignore @@ -168,3 +168,8 @@ packages/multimedia/intel-vaapi-driver/ packages/multimedia/media-driver/ packages/multimedia/gmmlib/ packages/sysutils/open-vm-tools/ + + +#other +docs/* +bench-results/ \ No newline at end of file diff --git a/TODO.md b/TODO.md deleted file mode 100644 index ebfa4099c2..0000000000 --- a/TODO.md +++ /dev/null @@ -1,844 +0,0 @@ -# TODO — Curadoria de Performance do SO - -> **Status (2026-04-18):** FASE 0-3 investigadas e implementadas. Itens marcados com ✅ estão concluídos. - -**Hardware alvo:** Handheld open source com SoC **Rockchip RK3326** (4× Cortex-A35 @ 1.3–1.5 GHz, in-order dual-issue, 256KB L2 compartilhado), GPU **Mali-G31 MP2** (Bifrost v9), **1GB DDR3/DDR3L**, storage **microSD**, passivo (sem fan). - -**Referências de comparação:** -- dArkOS: `/media/disco-local/dArkOS/` -- ROCKNIX: `/home/douglas/Documentos/distribution/` - -**Princípio guia:** nenhuma feature pode ser removida (WiFi, BT, etc.) — tudo o que não é essencial durante gameplay deve ser *socket-activated* ou *on-demand*, não deletado. - -**Convenção de tags:** -- `[PERF]` — item que altera FPS/frametime/latência direta -- `[FOOTPRINT]` — item que altera consumo de RAM, CPU idle, armazenamento -- `[AMBOS]` — item que afeta os dois -- `[INFRA]` — infraestrutura de medição/decisão, não é ganho em si - -**Convenção de metas numéricas:** todas as metas deste documento são **hipóteses a validar por benchmark**, não garantias. Se a hipótese não se confirmar, o item vira investigação, não ação cega. - ---- - -# FASE 0 — Pré-requisitos bloqueadores - -Sem estes dois itens, qualquer mudança subsequente é chute. - ---- - -## 0. ✅ Sanity check de release build `[INFRA][PERF]` - -**Objetivo:** garantir que nada crítico no pipeline está compilado/executado em modo de desenvolvimento. É o ganho mais barato e invisível — se algum pacote central estiver em debug, o ceiling de todos os outros itens cai junto. - -### 0.1 Kernel - -```bash -# Extrair config do kernel em execução -zcat /proc/config.gz 2>/dev/null || cat /boot/config-$(uname -r) -``` - -**Checks obrigatórios:** - -| Config | Esperado | Impacto | -|--------|----------|---------| -| `CONFIG_DEBUG_KERNEL` | `n` ou mínimo | overhead generalizado | -| `CONFIG_DEBUG_INFO` | off em release (ou em pkg separado) | tamanho | -| `CONFIG_LOCKDEP`, `CONFIG_PROVE_LOCKING` | `n` | overhead pesado | -| `CONFIG_DEBUG_LOCK_ALLOC` | `n` | | -| `CONFIG_KASAN`, `CONFIG_KMEMLEAK`, `CONFIG_KFENCE` | `n` | overhead + RAM | -| `CONFIG_SLUB_DEBUG_ON` | `n` (`CONFIG_SLUB_DEBUG=y` ok) | | -| `CONFIG_FTRACE`, `CONFIG_FUNCTION_TRACER` | `n` ou ao menos inativo | | -| `CONFIG_PREEMPT_TRACER`, `CONFIG_IRQSOFF_TRACER` | `n` | | -| `CONFIG_SCHEDSTATS` | `n` | | -| `CONFIG_DEBUG_PREEMPT` | `n` | | - -**Em runtime:** -```bash -cat /sys/kernel/debug/tracing/tracing_on # esperado: 0 -cat /sys/kernel/debug/tracing/current_tracer # esperado: nop -dmesg | grep -iE "debug|warn|slub" | head -50 -``` - -### 0.2 Mesa - -No PKGBUILD / meson: -- `-Dbuildtype=release` (NÃO `debugoptimized`, NÃO `debug`) -- `-Db_ndebug=true` (asserts off) -- `-Db_lto=true` (opcional, recomendado) - -Variáveis de ambiente que **jamais** podem estar setadas em produção: -```bash -env | grep -iE "MESA_DEBUG|MESA_VERBOSE|MESA_LOG|GALLIUM_DUMP|PAN_MESA_DEBUG|LIBGL_DEBUG" -``` - -Se `PAN_MESA_DEBUG` estiver setado, auditar o valor: -- `sync` → serialização total, perde ~30% FPS -- `trace` → captura de cada draw call -- `nocrc` → desliga transaction elimination (vai contra o item 4) - -### 0.3 RetroArch - -No configure/PKGBUILD: -- `--disable-debug` -- `--enable-lto` (se suportado) -- Nunca: `--enable-debug`, `--enable-profile`, `--enable-asan|ubsan|tsan` - -Em runtime: -```bash -retroarch --version # sem flags HAVE_DEBUG -``` - -Flags que nunca devem estar no `retroarch.cfg` de produção: -``` -log_verbosity = "false" -perfcnt_enable = "false" # só durante benchmark -libretro_log_level = "3" # error apenas -frontend_log_level = "3" -``` - -### 0.4 Cores libretro - -```bash -for core in /usr/lib/libretro/*.so; do - echo "=== $core ===" - file "$core" | grep -o "not stripped\|stripped" - nm -D "$core" 2>/dev/null | grep -iE "asan|ubsan|tsan|msan" | head -3 - du -h "$core" -done -``` - -Esperado: `stripped`, sem símbolos de sanitizer, tamanho razoável (cores em debug são 2–5x maiores). - -### 0.5 Emuladores standalone - -Mesma auditoria para PPSSPP, Dolphin, DuckStation, Flycast etc.: -- `CMAKE_BUILD_TYPE=Release` (ou `RelWithDebInfo` com debug em pkg separado) -- Nunca `Debug` -- Binário `stripped` - -```bash -for bin in /usr/bin/{ppsspp,dolphin-emu,duckstation,flycast}; do - [ -x "$bin" ] || continue - echo "=== $bin ===" - file "$bin" | grep -o "not stripped\|stripped" - du -h "$bin" -done -``` - -### 0.6 Frontend - -```bash -find /etc /opt -name "*.conf" -o -name "*.cfg" 2>/dev/null | \ - xargs grep -iE "log.*level|verbose|debug" 2>/dev/null | head -20 -``` - -Muitos frontends vêm com log level `DEBUG` no default. - -### 0.7 Comparação lateral com dArkOS/ROCKNIX - -Gerar relatório de flags e buildtypes usados pelas distros concorrentes — às vezes eles descobriram algo que não está documentado, e vice-versa. - -**Critério de aceitação:** -- Documento `/docs/build-audit.md` com checklist preenchido para cada subitem. -- Zero pacotes em buildtype `Debug`. -- Zero símbolos de sanitizer em binários de produção. -- Zero env vars de debug em `/etc/environment`, profiles, systemd units. - -**Por que vem antes do benchmark:** se baseline for medido com Mesa `debugoptimized` ou core com asserts ativos, toda decisão subsequente parte de referência errada. - ---- - -## 1. ✅ Baseline de benchmark reproduzível `[INFRA]` - -**Objetivo:** script que rode cenários fixos e emita métricas completas para comparar nosso SO vs dArkOS vs ROCKNIX, de forma rastreável e reproduzível. - -### 1.1 Cenários fixos (save states versionados no repo) - -| Sistema | Jogo | Cena | Emulador primário | Por que importa | -|---------|------|------|-------------------|-----------------| -| SNES | Super Mario World | Yoshi's Island 1 | Snes9x2010 | smoke test, 60fps trivial | -| Mega Drive | Sonic 2 | Chemical Plant loop | Genesis Plus GX | scroll horizontal | -| GBA | Advance Wars 2 | mid-game map | mGBA | tile-heavy | -| PS1 | Crash Bandicoot 1 | Wumpa Island praia | Beetle PSX HW | texture streaming | -| PS1 | Tekken 3 | seleção | Beetle PSX HW | smoke test PS1 | -| N64 | Super Mario 64 | Bob-omb topo | Mupen64Plus-Next | draw distance | -| N64 | Zelda OoT | Hyrule Field meio-dia | Mupen64Plus-Next | fog + partículas | -| PSP | GTA VCS | intro cinemática | PPSSPP | cutscene streaming | -| PSP | Daxter | fase inicial | PPSSPP | FPS sustentado | -| DC | Soul Calibur | character select | Flycast | smoke test DC | -| DC | Crazy Taxi | start of level | Flycast | stress DC | - -### 1.2 Matriz explícita libretro vs standalone - -Comparação justa exige caminho equivalente. Distros tomam decisões diferentes — ROCKNIX pode usar PPSSPP libretro, dArkOS standalone (ou vice-versa). Misturar caminhos gera benchmark injusto. - -Para cada cenário relevante, benchmarkar **ambos os caminhos** quando aplicável: - -| Core/Emulador | Libretro | Standalone | -|---------------|----------|------------| -| PPSSPP | `ppsspp_libretro.so` | binário `ppsspp` | -| Beetle PSX HW | `mednafen_psx_hw_libretro.so` | — | -| DuckStation | `swanstation_libretro.so` | binário `duckstation` | -| Mupen64Plus-Next | `mupen64plus_next_libretro.so` | `mupen64plus` standalone | -| Flycast | `flycast_libretro.so` | binário `flycast` | -| Dolphin | `dolphin_libretro.so` (se existir) | `dolphin-emu` | - -**Saída esperada:** CSV separa path libretro vs standalone, não mistura. A comparação "nosso SO vs dArkOS no PSP" precisa ter as duas linhas quando ambas as distros expõem os dois caminhos. - -### 1.3 Instrumentação — métricas por run - -Coletar durante 60s por cenário, 5 runs cada. - -**Frametime:** -```bash -# retroarch.cfg do bench (não o de produção) -video_frame_log = "true" -perfcnt_enable = "true" -``` - -**PSI (Pressure Stall Information) — crítico em 1GB:** - -O problema real em 1GB raramente é "faltou RAM". É "entrou em pressão, kswapd ativo, frametime explodiu". PSI captura; MemAvailable não. - -```bash -while [ running ]; do - date +%s.%N - cat /proc/pressure/cpu # avg10, avg60, avg300 - cat /proc/pressure/memory # some + full - cat /proc/pressure/io - sleep 1 -done > psi.log -``` - -**Eventos de reclaim/OOM:** -```bash -dmesg -w > dmesg-during-bench.log & -# Filtrar: oom, kswapd, pagealloc, reclaim, compact_fail -``` - -**Contadores de sistema:** -```bash -vmstat 1 60 > vmstat.log -# si/so (swap in/out), wa (iowait), st (stolen), free, buff, cache -``` - -**Frequências CPU/GPU/DDR + temperatura:** -```bash -while [ running ]; do - for cpu in /sys/devices/system/cpu/cpu[0-3]/cpufreq/scaling_cur_freq; do - cat "$cpu" - done - cat /sys/class/devfreq/*gpu*/cur_freq - cat /sys/class/devfreq/*dmc*/cur_freq - cat /sys/class/thermal/thermal_zone0/temp - sleep 1 -done > freq-therm.log -``` - -**Input latency:** câmera 240fps + LED no botão + evento na tela (método RetroArch), executado separadamente, não por run. - -### 1.4 Metadados obrigatórios de cada run - -Sem isto, um benchmark "bom" vira folklore irreproduzível. - -| Campo | Comando | -|-------|---------| -| `kernel_release` | `uname -r` | -| `kernel_commit` | `git -C rev-parse HEAD` | -| `mesa_version` | `pacman -Qi mesa` | -| `mesa_commit` | do PKGBUILD ou `glxinfo` | -| `retroarch_version` | `retroarch --version` | -| `core_name` | path do core | -| `core_version` | metadata do .so | -| `emulator_standalone_version` | `ppsspp --version` etc. | -| `rom_sha256` | `sha256sum ` | -| `bios_sha256` | `sha256sum ` | -| `save_state_sha256` | idem | -| `power_source` | `/sys/class/power_supply/*/online` | -| `battery_charging` | `/sys/class/power_supply/*/status` | -| `battery_percent` | `/sys/class/power_supply/*/capacity` | -| `ambient_temp_c` | input manual | -| `microsd_model` | `cat /sys/block/mmcblk0/device/{name,manfid,oemid,cid}` | -| `microsd_speed_class` | `dmesg \| grep mmcblk0` ou input manual | -| `cpu_governor` | `cat /sys/.../scaling_governor` | -| `cpu_max_freq` | `scaling_max_freq` | -| `gpu_governor` | `/sys/class/devfreq/*gpu*/governor` | -| `dmc_governor` | `/sys/class/devfreq/*dmc*/governor` | -| `zram_active` | `swapon` | -| `zram_algo` | `cat /sys/block/zram0/comp_algorithm` | -| `thp_enabled` | `cat /sys/kernel/mm/transparent_hugepage/enabled` | -| `cma_total_kb` | `grep CmaTotal /proc/meminfo` | -| `cma_free_kb` | `grep CmaFree /proc/meminfo` | -| `memavailable_kb_start` | `grep MemAvailable /proc/meminfo` | -| `bench_script_commit` | `git rev-parse HEAD` do repo do bench | - -Juntar em JSON de metadados + CSV de frametime. - -### 1.5 Formato de saída - -``` -results/ -├── YYYYMMDD-HHMMSS---/ -│ ├── meta.json # metadados da 1.4 -│ ├── frametime.csv # timestamp, frame_time_ms -│ ├── psi.log # 1Hz sampling -│ ├── freq-therm.log -│ ├── vmstat.log -│ ├── dmesg.log -│ └── summary.json # p50, p95, p99, fps_mean, max_temp, mem_pressure_pct -``` - -### 1.6 Dashboard de comparação - -Script que: -1. Carrega `summary.json` de N runs -2. Agrupa por `(distro, cenario, core_path)` -3. Emite pivot com medianas + IQR -4. Flagga runs com alta variância (σ/μ > 10%) para re-rodar -5. Gera gráficos de frametime density + PSI timeline - -**Critério:** `./bench.sh ` grava resultados versionados. `./compare.py --cenario psp_vcs` gera tabela entre distros. - -**Risco:** subestimar esforço. Planejar 2–3 dias. É o maior investimento de ROI do projeto. - ---- - -# FASE 1 — TIER S (ganhos hipotéticos de 10%+) - ---- - -## 2. ✅ zram com zstd `[AMBOS]` - -**Hipótese:** em 1GB, PSP/N64/DC entram em pressão de memória que causa spikes de frametime. zram resolve sem I/O em microSD. - -**Validação:** PSI `memory.some.avg60` durante PPSSPP/GTA VCS cai ≥50% vs baseline sem zram; frametime p99 estável ou melhor. Se a pressão já é baixa sem zram no cenário, ganho pode ser zero — investigar quais cenas realmente causam pressão. - -**Auditar primeiro:** -```bash -cat /proc/swaps -cat /sys/block/zram0/comp_algorithm 2>/dev/null -zramctl -sysctl vm.swappiness vm.vfs_cache_pressure vm.page-cluster - -grep -r "zram\|swapp\|compcache" /media/disco-local/dArkOS/ /home/douglas/Documentos/distribution/ 2>/dev/null -``` - -**Ação:** -- Device zram com **zstd**, tamanho ~50% da RAM (512MB comprimido ≈ 170MB físicos em razão 1:3). Referência: [ArchWiki zram](https://wiki.archlinux.org/title/Zram). -- **Desabilitar zswap** (intercepta antes do zram). `zswap.enabled=0` na cmdline. -- Priority 100 no swapon. -- **Proibido** swap em microSD. - -```ini -# /etc/sysctl.d/99-handheld.conf -vm.swappiness = 100 -vm.vfs_cache_pressure = 50 -vm.page-cluster = 0 -vm.dirty_background_ratio = 5 -vm.dirty_ratio = 10 -vm.dirty_expire_centisecs = 3000 -vm.dirty_writeback_centisecs = 1500 -``` - -**Risco:** CPU de compressão compete com emulador. Se p99 piorar em cenas leves, reduzir tamanho ou trocar zstd → lz4. - ---- - -## 3. ✅ DDR frequency scaling (dmc devfreq) `[PERF]` - -**Hipótese:** DDR3 é gargalo #1 de bandwidth do RK3326. DMC preso em freq baixa penaliza cenas texture-heavy em PS1/N64/PSP. - -**Validação:** FPS em Crash Wumpa — hipótese de +5% a +15% com governor `performance` vs `simple_ondemand` conservador. Se não render, verificar `trans_stat` — governor pode estar escalando, mas o workload não pressiona DDR o suficiente para mostrar diferença. - -**Auditar:** -```bash -ls /sys/class/devfreq/ -cat /sys/class/devfreq/*dmc*/governor -cat /sys/class/devfreq/*dmc*/available_frequencies -cat /sys/class/devfreq/*dmc*/cur_freq -cat /sys/class/devfreq/*dmc*/trans_stat - -find /media/disco-local/dArkOS/ -name "*.dts*" | xargs grep -l "dmc\|memory-controller" 2>/dev/null -find /home/douglas/Documentos/distribution/ -name "*.dts*" | xargs grep -l "dmc\|memory-controller" 2>/dev/null -``` - -**Ação:** -- `dmc_ondemand` com upthreshold ~40% OU `performance` via hook do frontend durante gameplay. -- Comparar OPPs de DDR no DT — às vezes há 933MHz escondido. - -**Risco:** instabilidade em DDR alto. `memtester` 30min antes de promover. - ---- - -## 4. ✅ Mesa atualizado + Panfrost Transaction Elimination `[PERF]` - -**Hipótese:** Mesa 25.0+ habilita CRC por padrão, reduzindo bandwidth ao pular write-out de tiles inalterados. Em DDR3 apertado, ganho real. Referência: [Mesa 25.0 PanVK update](https://www.collabora.com/news-and-blog/news-and-events/mesa-25-panvk-moves-towards-production-quality.html). - -**Validação:** hipótese de +3% a +8% FPS em cenas 3D com frames similares consecutivos (Zelda OoT parado em Hyrule Field). Se regredir, `PAN_MESA_DEBUG=nocrc` pode estar setado em algum lugar (auditar, vide item 0.2). - -**Auditar:** -```bash -glxinfo -B 2>/dev/null | grep -i mesa -pacman -Qi mesa | grep Version - -grep -rI "PAN_MESA_DEBUG" /etc/ /usr/share/ ~/.config/ -env | grep -iE "PAN_|MESA_" -``` - -**Ação:** -- Mesa ≥ 25.0, compilado em release (item 0.2). -- Shader cache persistente: - ```bash - export MESA_SHADER_CACHE_DIR=/var/cache/mesa_shader_cache - export MESA_SHADER_CACHE_MAX_SIZE=256MB - ``` -- `MESA_GLTHREAD=true` — testar per-core, regride em cores single-thread. -- Pré-aquecer cache em ROMs populares no primeiro boot. - ---- - -## 5. Panfrost kernel driver — patch de powerup sequence `[PERF]` - -**Hipótese:** patch de 2025 que reordena pd→reset→clock corrige comportamento conforme manual Mali. Testado em RK3326 Powkiddy RGB10X. Referência: [patch dri-devel](https://www.mail-archive.com/dri-devel@lists.freedesktop.org/msg541359.html). - -**Validação:** estabilidade em suspend/resume; ausência de GPU hangs. Perf pode não mudar — foco é correção. - -```bash -uname -r -grep -A 30 "panfrost_device_init" /path/to/kernel/drivers/gpu/drm/panfrost/panfrost_device.c -``` - ---- - -## 6. ✅ CMA / reserved-memory / carveouts `[FOOTPRINT][PERF]` - -**Hipótese:** cada MB reservado em CMA é um MB a menos para userland em 1GB. SoCs Rockchip reservam 64–256MB típico. Reserva excessiva rouba RAM útil. Reserva insuficiente quebra video/VPU/GPU allocations. - -**Validação:** MemAvailable em idle sobe ≥50MB após trim, sem quebrar playback V4L2 nem decode HEVC 1080p do frontend. - -### 6.1 Auditar estado atual - -```bash -grep -E "^Cma(Total|Free)" /proc/meminfo - -mount -t debugfs none /sys/kernel/debug 2>/dev/null -for d in /sys/kernel/debug/cma/*/; do - echo "=== $d ===" - cat "$d/count" # páginas totais - cat "$d/used" # páginas em uso -done - -cat /sys/firmware/devicetree/base/reserved-memory/ranges 2>/dev/null -ls /sys/firmware/devicetree/base/reserved-memory/ -``` - -### 6.2 Mapear reservas no DT em runtime - -```bash -dtc -I fs /sys/firmware/devicetree/base > /tmp/runtime.dts -grep -A 5 "reserved-memory" /tmp/runtime.dts -grep -B 2 -A 10 "linux,cma\|shared-dma-pool\|no-map" /tmp/runtime.dts -``` - -**Reservas típicas em RK3326:** -- `linux,cma` global — 64–128MB comum; 256MB é exagero em 1GB -- `rockchip,drm-logo` — splash (pode sumir em release) -- `ramoops` — crash dump (pequeno, manter) -- VPU carveouts — verificar se são necessários ou se VPU usa CMA global - -### 6.3 Comparar lateralmente - -```bash -for DT in \ - /media/disco-local/dArkOS/boot/dtbs/rockchip/*rk3326*.dtb \ - /home/douglas/Documentos/distribution/boot/dtbs/rockchip/*rk3326*.dtb \ - /boot/dtbs/rockchip/*rk3326*.dtb; do - [ -f "$DT" ] || continue - echo "=== $DT ===" - dtc -I dtb -O dts "$DT" 2>/dev/null | grep -B 2 -A 10 "linux,cma\|reserved-memory" -done -``` - -### 6.4 Ações possíveis - -- **Reduzir CMA global** se `CmaFree` fica sempre alto (ex: 128MB reservado, 120MB livre = desperdício). -- **Remover carveouts de logo/splash** em release se não usados. -- **Consolidar** VPU/ISP carveouts em CMA compartilhada se possível. -- Configurar em cmdline: `cma=64M` ou DT override. - -### 6.5 Validações pós-ajuste - -Testar após cada mudança: -- Playback H.264 1080p no frontend — OK? -- V4L2 M2M decode (`ffmpeg -c:v h264_v4l2m2m`) — OK? -- GPU allocations grandes (PSP 2x internal) — sem falha? -- `dmesg | grep -iE "cma|dma|alloc fail"` — sem erros novos? - -**Risco:** reserva insuficiente falha silenciosamente em decode. Testar playback intensivo antes de promover. - ---- - -## 7. ✅ CFLAGS alinhados a Cortex-A35 `[PERF]` - -**Hipótese:** A35 é in-order dual-issue, IPC baixo. Código genérico deixa 3–10% na mesa por core. - -**Validação:** FPS em Sonic 2 Chemical Plant sobe ≥2% com `-O2 -flto -mtune=cortex-a35` vs `-O2` genérico. Se não, verificar se o build realmente absorveu as flags (`readelf -A` nos binários). - -**`makepkg.conf`:** -```bash -CFLAGS="-march=armv8-a+crc+crypto -mtune=cortex-a35 -O2 -pipe -fno-plt -fstack-protector-strong" -CXXFLAGS="${CFLAGS}" -LDFLAGS="-Wl,-O1,--sort-common,--as-needed,-z,relro,-z,now" -MAKEFLAGS="-j$(nproc)" -``` - -**Observações:** -- **Não** `-O3` universal. L1I 32KB, L2 256KB; `-O3` infla binário e pressiona cache. Pontual após bench. -- **Não** `-mcpu=cortex-a35` em libs genéricas (quebra portabilidade). -- `-flto` em: mesa, retroarch, cores libretro, sdl2, ffmpeg, zlib-ng. - -**Pacotes para recompilar:** -1. mesa (item 4) -2. retroarch -3. Cores libretro em uso -4. sdl2 -5. ffmpeg com `--enable-neon --cpu=cortex-a35` -6. **zlib-ng** (substitui zlib, 10–30% em descompressão de ROMs zipadas) -7. zstd (para zram) - ---- - -## 8. ✅ Device Tree diff profundo `[PERF][FOOTPRINT]` - -**Hipótese:** DT é fonte comum de perf "misteriosa". Divergências entre distros raramente são acidentais. - -**Validação:** `dt-findings.md` com N divergências categorizadas (cosmética / perf / estabilidade), cada uma com decisão registrada. - -**Método:** -```bash -mkdir -p /tmp/dt-diff/{nosso,arkos,rocknix} -dtc -I dtb -O dts -o /tmp/dt-diff/nosso/board.dts /boot/dtbs/rockchip/*rk3326*.dtb -# Repetir para concorrentes - -diff -u /tmp/dt-diff/nosso/board.dts /tmp/dt-diff/arkos/board.dts > /tmp/dt-diff/nosso-vs-arkos.patch -``` - -**Pontos:** -- `cpu0-opp-table` — 1.3GHz vs 1.5GHz? -- `gpu-opp-table` — freqs Mali-G31 (200/300/400/520/650) -- `dmc-opp-table` — DDR (786/933/1066) -- `thermal-zones` → trips + cooling-maps -- `regulator-*` → min/max-microvolt (margem de undervolt) -- `rockchip,pwm-regulator` -- `reserved-memory` — ver item 6 - ---- - -# FASE 2 — TIER A (ganhos hipotéticos de 3–10%) - ---- - -## 9. ✅ I/O scheduler e bloco para microSD `[PERF]` - -**Hipótese:** bfq + read_ahead alto reduz stutter em streaming de ROMs grandes. - -**Validação:** load de ISO PSP GTA VCS cai ≥15%. - -```bash -for d in /sys/block/mmcblk*; do - echo "$d: $(cat $d/queue/scheduler)" -done - -cat > /etc/udev/rules.d/60-mmcblk-scheduler.rules <<'EOF' -ACTION=="add|change", KERNEL=="mmcblk[0-9]*", ATTR{queue/scheduler}="bfq" -ACTION=="add|change", KERNEL=="mmcblk[0-9]*", ATTR{queue/iosched/low_latency}="1" -ACTION=="add|change", KERNEL=="mmcblk[0-9]*", ATTR{queue/read_ahead_kb}="2048" -ACTION=="add|change", KERNEL=="mmcblk[0-9]*", ATTR{queue/nr_requests}="128" -ACTION=="add|change", KERNEL=="mmcblk[0-9]*", ATTR{queue/rq_affinity}="2" -EOF -``` - -Mount: `noatime,nodiratime,commit=600,lazytime`. Manter ext4 (F2FS arriscado em microSD variável). - ---- - -## 10. RetroArch em KMS/DRM puro `[FOOTPRINT][PERF]` - -**Hipótese:** evitar compositor economiza 30–60MB residentes + buffer copy por frame. - -**Validação:** MemAvailable em RetroArch fullscreen sobe ≥40MB vs modo com compositor. - -``` -video_driver = "drm" -video_context_driver = "kms" -``` - -Auditar: frontend está subindo X? Pode rodar em `cage` (Wayland kiosk) ou fbdev? - ---- - -## 11. Render resolution sanity por core `[PERF]` - -**Hipótese:** renderizar PSP em 2x (1920×1088) em painel 640×480 é desperdício puro. - -Presets default: -- PPSSPP: `1x` em ≤480p, `1.5x` em 720p -- Beetle PSX HW: `1x` -- Mupen64Plus-Next: nativa (320x240 ou 640x480) -- Flycast: nativa (640×480) -- Dolphin/PCSX2: não aplicável em A35 - -**Ação:** `core-overrides/` versionado com presets conservadores por default. - ---- - -## 12. ✅ Systemd trim cirúrgico `[FOOTPRINT]` - -**Hipótese:** daemons socket-activated em vez de residentes liberam ≥60MB RSS sem remover funcionalidade. - -**Validação:** RSS total de serviços residentes cai ≥60MB. - -```bash -systemd-analyze blame > /tmp/blame-nosso.txt -systemctl list-units --state=running --type=service -``` - -**Alvos:** -- `ModemManager`, `cups`, `packagekit`, `tracker-*`, `geoclue`, `fwupd` → **mask** -- `avahi-daemon`, `bluetooth`, WiFi → **socket-activate** - -Journal em RAM: -```ini -# /etc/systemd/journald.conf.d/handheld.conf -[Journal] -Storage=volatile -RuntimeMaxUse=16M -``` - ---- - -## 13. ✅ CPU governor + thermal trips `[PERF]` - -**Hipótese:** sem fan, throttle precoce derruba perf sustentada. Trips conservadores herdados de smartphone. - -**Validação:** 30min PSP mantém CPU ≥1.4GHz em ≥95% do tempo. - -```bash -for z in /sys/class/thermal/thermal_zone*; do - echo "=== $z ===" - cat $z/type - for t in $z/trip_point_*_temp; do - echo " $t: $(cat $t)" - done -done -``` - -**Ação:** -- `performance` em gameplay via pre-launch hook; `schedutil` em idle. -- Comparar trips com dArkOS/ROCKNIX. -- Undervolt via `cpu-supply` no DT se houver margem (validar com stress-ng + memtester). - ---- - -## 14. Vulkan (PanVK) — abordagem para Mali-G31 `[DECISÃO]` - -**Situação:** PanVK conformante apenas em Mali-G610. Mali-G31 (Bifrost v9) = não-conformante. Mesa não expõe PanVK por padrão em G31. - -**Três opções:** - -- **A (default recomendado):** manter OpenGL ES, não expor Vulkan ao usuário, infra pronta. -- **B (opt-in):** toggle experimental, `PAN_I_WANT_A_BROKEN_VULKAN_DRIVER=1` sob demanda, documentar risco. -- **C (Zink pontual):** OpenGL sobre Vulkan, raramente ganha em G31. - -Investigar o que dArkOS/ROCKNIX fazem: -```bash -grep -rI "vulkan\|PAN_I_WANT\|panvk" /media/disco-local/dArkOS/ /home/douglas/Documentos/distribution/ 2>/dev/null -``` - -**Critério:** decisão em `vulkan-decision.md`. Se B, lista de cores "funcionando"/"quebrados". - ---- - -# FASE 3 — TIER B (qualidade e ganhos menores) - ---- - -## 15. ✅ Input latency `[PERF]` - -**Hipótese:** `CONFIG_HZ=1000` + polling 1000Hz + run-ahead 1–2 frames em cores leves reduz latência perceptível. - -```bash -zcat /proc/config.gz | grep CONFIG_HZ= -cat /proc/bus/input/devices -``` - -RetroArch: -- `video_frame_delay` — testar 0–4 per-core -- `video_hard_sync = "true"` (custa CPU) -- Run-ahead: ON em SNES/GBA/MD/NES, OFF em PS1/N64/PSP/DC - ---- - -## 16. Áudio — stack mínimo `[FOOTPRINT][PERF]` - -**Hipótese:** ALSA direto economiza ~20MB vs PipeWire. Se PipeWire necessário, quantum 1024. - -```ini -# /etc/pipewire/pipewire.conf.d/99-handheld.conf -default.clock.quantum = 1024 -default.clock.min-quantum = 512 -default.clock.max-quantum = 2048 -``` - -**Validação:** sem crackle em 30min PSP. Latência áudio ≤96ms. - ---- - -## 17. Locales, fonts, docs `[FOOTPRINT]` - -**Hipótese:** ~300MB recuperados em microSD, menos pressão FS cache. - -```ini -# /etc/pacman.conf -NoExtract = usr/share/locale/* !usr/share/locale/en* !usr/share/locale/pt_BR* -NoExtract = usr/share/man/* usr/share/doc/* usr/share/info/* -NoExtract = usr/share/gtk-doc/* -``` - ---- - -## 18. Per-game override infrastructure `[PERF]` - -``` -/opt/game-profiles/ -├── system/ -│ ├── psp/ -│ │ ├── _default.conf -│ │ ├── ULUS10160.conf # GTA VCS -│ │ └── ULUS10041.conf # Daxter -``` - -Hook pre-launch aplica: cpufreq governor, dmc governor, GPU min_freq, RetroArch `--appendconfig`, Mesa env vars. - ---- - -## 19. Frontend — lazy loading e cache `[FOOTPRINT][PERF]` - -Auditar: -- Parse de gamelist.xml em lib ≥500 jogos -- Thumbnails lazy vs eager -- Preview videos via V4L2 M2M vs software -- Shaders de tema pesados - -**Hipótese:** 2–5s de boot e 30–60MB de RAM. - ---- - -## 20. Firmware Mali e V4L2 M2M `[PERF]` - -```bash -dmesg | grep -i "mali\|panfrost\|firmware" -ls /lib/firmware/arm/mali/ 2>/dev/null - -ffmpeg -hwaccels -ffmpeg -i preview.mp4 -c:v h264_v4l2m2m -f null - -``` - -Zero-copy DMA-BUF decoder→GPU→display. - ---- - -# FASE 4 — Infraestrutura e meta - ---- - -## 21. Repositório de comparativos `[INFRA]` - -`/docs/comparativos/` versionado: -- `build-audit.md` (item 0) -- `dt-findings.md` (item 8) -- `cma-findings.md` (item 6) -- `sysctl-findings.md` — diff sysctl entre distros -- `service-audit.md` — daemons ativos por distro -- `cflags-audit.md` — flags por distro -- `mesa-version.md` -- `kernel-version.md` -- `vulkan-decision.md` - ---- - -## 22. CI de performance `[INFRA]` - -Quando item 1 maduro: -- Build → flash → bench → regressão em PR -- Alertar PRs que regridam p95 ≥3% - ---- - -# Classificação rápida: perf direta vs footprint - -| Item | Tag | Tier | Métrica principal | -|------|-----|------|-------------------| -| 0 | INFRA/PERF | 0 | ceiling do resto | -| 1 | INFRA | 0 | base de comparação | -| 2 | AMBOS | S | PSI memory + frametime p99 | -| 3 | PERF | S | FPS texture-heavy | -| 4 | PERF | S | FPS + bandwidth GPU | -| 5 | PERF | S | estabilidade GPU | -| 6 | AMBOS | S | MemAvailable + decode ok | -| 7 | PERF | S | FPS sustentado | -| 8 | AMBOS | S | depende da divergência | -| 9 | PERF | A | load time ROMs | -| 10 | AMBOS | A | MemAvailable + frametime | -| 11 | PERF | A | FPS em PS1/PSP HW | -| 12 | FOOTPRINT | A | RSS daemons | -| 13 | PERF | A | freq sustentada | -| 14 | DECISÃO | A | — | -| 15 | PERF | B | input latency ms | -| 16 | AMBOS | B | RSS + crackle | -| 17 | FOOTPRINT | B | disk + cache | -| 18 | PERF | B | FPS per-game | -| 19 | AMBOS | B | boot time + RSS | -| 20 | PERF | B | CPU em vídeo | - ---- - -# Ordem recomendada de execução - -| Fase | Itens | Duração estimada | -|------|-------|------------------| -| **Pré-req obrigatório** | 0, 1 | 3–5 dias | -| **Quick wins RAM/DDR/CMA** | 2, 3, 6 | 2 dias | -| **Stack gráfico** | 4, 5 | 1–2 dias | -| **DT archeology** | 8 | 2–3 dias | -| **Compilação tunada** | 7 | 1 dia + build time | -| **Polimento stack** | 9, 10, 11, 12, 13 | 3 dias | -| **Decisão Vulkan** | 14 | 1 dia | -| **Latência e áudio** | 15, 16 | 1 dia | -| **QoL e economia** | 17, 18, 19, 20 | 2 dias | -| **Documentação** | 21 | paralelo | -| **CI** | 22 | longo prazo | - -**Total estimado:** ~3–4 semanas focadas + build time. - ---- - -# Itens explicitamente DESCARTADOS (e por quê) - -- ~~big.LITTLE / EAS~~ — RK3326 é 4× A35 homogêneos. -- ~~Transparent HugePages~~ — fragmenta em 1GB. Manter `never`. -- ~~CPU isolation (`isolcpus`, `nohz_full`)~~ — 4 cores é pouco. -- ~~PGO em Dolphin/PCSX2/RPCS3~~ — não rodam com perf útil no A35. -- ~~F2FS~~ — ext4 mais seguro em microSD variável. -- ~~Swap em microSD~~ — destrói cartão. -- ~~`-O3` universal~~ — icache apertado; pontual após bench. -- ~~`mitigations=off`~~ — ganho marginal em A35, risco ruim. - ---- - -# Quando revisitar este TODO - -- Após itens 0 e 1: reprioritizar com dados. -- A cada release do Mesa: PanVK em G31 saiu de experimental? -- A cada release do kernel: patches novos de Panfrost/rockchip? -- Se o projeto ganhar contribuidores: quebrar em issues granulares. \ No newline at end of file diff --git a/distributions/ArchR/options b/distributions/ArchR/options index 15f96ca15b..9d2a19d2bd 100644 --- a/distributions/ArchR/options +++ b/distributions/ArchR/options @@ -187,8 +187,12 @@ # Root filesystem type (squashfs / ext4) ROOTFS_TYPE="ext4" -# Boot partition size (FAT32, kernel + DTBs + bootloader), in MB - BOOT_SIZE=256 +# Boot partition size (FAT32, kernel + DTBs + bootloader), in MB. +# 272 MB chosen so the partition exceeds 65525 4-KB clusters and +# qualifies as real FAT32 by spec (256 MB landed at 65404 clusters, +# 121 short, triggering "less than the required minimum" warnings on +# every dosfsck run). + BOOT_SIZE=272 # Root partition size (ext4 rootfs), in MB ROOT_SIZE=4608 diff --git a/documentation/PER_DEVICE_DOCUMENTATION/RK3326/SUPPORTED_EMULATORS_AND_CORES.md b/documentation/PER_DEVICE_DOCUMENTATION/RK3326/SUPPORTED_EMULATORS_AND_CORES.md index 52265f5f16..4b16bca08d 100644 --- a/documentation/PER_DEVICE_DOCUMENTATION/RK3326/SUPPORTED_EMULATORS_AND_CORES.md +++ b/documentation/PER_DEVICE_DOCUMENTATION/RK3326/SUPPORTED_EMULATORS_AND_CORES.md @@ -64,12 +64,11 @@ |Nintendo|Game & Watch (gameandwatch)|1980|`gameandwatch`|.mgw .zip .7z|**retroarch:** gw
**retroarch:** mame
| |Nintendo|Game Boy (gb)|1989|`gb`|.gb .gbc .zip .7z|**retroarch:** gambatte (default)
**retroarch:** sameboy
**retroarch:** gearboy
**retroarch:** tgbdual
**retroarch:** mgba
**retroarch:** vbam
**retroarch:** DoubleCherryGB
**retroarch:** skyemu
**mednafen:** gb
| |Nintendo|Game Boy (Hacks) (gbh)|1989|`gbh`|.gb .zip .7z|**retroarch:** gambatte (default)
**retroarch:** sameboy
**retroarch:** gearboy
**retroarch:** tgbdual
**retroarch:** mgba
**retroarch:** vbam
**retroarch:** DoubleCherryGB
**retroarch:** skyemu
**mednafen:** gb
| -|Nintendo|Game Boy Advance (gba)|2001|`gba`|.gba .zip .7z|**retroarch:** mgba (default)
**retroarch:** vbam
**retroarch:** vba_next
**retroarch:** beetle_gba
**retroarch:** skyemu
**retroarch:** gpsp
**mednafen:** gba
| +|Nintendo|Game Boy Advance (gba)|2001|`gba`|.gba .zip .7z|**retroarch:** gpsp (default)
**retroarch:** mgba
**retroarch:** vbam
**retroarch:** vba_next
**retroarch:** beetle_gba
**retroarch:** skyemu
**mednafen:** gba
| |Nintendo|Game Boy Advance (Hacks) (gbah)|2001|`gbah`|.gba .zip .7z|**retroarch:** mgba (default)
**retroarch:** vbam
**retroarch:** vba_next
**retroarch:** beetle_gba
**retroarch:** skyemu
**retroarch:** gpsp
**mednafen:** gba
| |Nintendo|Game Boy Advance video (gbav)|2001|`gbav`|.gba .zip .7z|**retroarch:** mgba (default)
**retroarch:** vbam
**retroarch:** vba_next
**retroarch:** beetle_gba
**retroarch:** skyemu
**retroarch:** gpsp
**mednafen:** gba
| |Nintendo|Game Boy Color (gbc)|1998|`gbc`|.gb .gbc .zip .7z|**retroarch:** gambatte (default)
**retroarch:** sameboy
**retroarch:** gearboy
**retroarch:** tgbdual
**retroarch:** mgba
**retroarch:** vbam
**retroarch:** DoubleCherryGB
**retroarch:** skyemu
**mednafen:** gb
| |Nintendo|Game Boy Color (Hacks) (gbch)|1998|`gbch`|.gb .gbc .zip .7z|**retroarch:** gambatte (default)
**retroarch:** sameboy
**retroarch:** gearboy
**retroarch:** tgbdual
**retroarch:** mgba
**retroarch:** vbam
**retroarch:** DoubleCherryGB
**retroarch:** skyemu
**mednafen:** gb
| -|Nintendo|GameCube (gamecube)|2001|`gamecube`|.gcm .iso .gcz .ciso .wbfs .rvz .dol .m3u|**retroarch:** dolphin (default)
| |Nintendo|NES (Hacks) (nesh)|1985|`nesh`|.nes .unif .unf .zip .7z|**retroarch:** nestopia (default)
**retroarch:** fceumm
**retroarch:** quicknes
**retroarch:** mesen
**mednafen:** nesh
| |Nintendo|Nintendo 64 (n64)|1996|`n64`|.z64 .n64 .v64 .zip .7z|**retroarch:** mupen64plus_next (default)
**retroarch:** mupen64plus
**retroarch:** parallel_n64
**mupen64plus:** mupen64plus-sa
| |Nintendo|Nintendo DS (nds)|2005|`nds`|.nds .zip .7z|**drastic:** drastic-sa (default)
**melonds:** melonds-sa
**retroarch:** melonds
**retroarch:** melondsds
**retroarch:** desmume
**retroarch:** skyemu
| @@ -82,8 +81,6 @@ |Nintendo|Super Nintendo (Hacks) (snesh)|1991|`snesh`|.smc .fig .sfc .swc .zip .7z|**retroarch:** snes9x (default)
**retroarch:** snes9x2010
**retroarch:** snes9x2002
**retroarch:** snes9x2005_plus
**retroarch:** beetle_supafaust
**retroarch:** bsnes_mercury_performance
**mednafen:** snes_faust
| |Nintendo|Super Nintendo (snes)|1991|`snes`|.smc .fig .sfc .swc .zip .7z|**retroarch:** snes9x (default)
**retroarch:** snes9x2010
**retroarch:** snes9x2002
**retroarch:** snes9x2005_plus
**retroarch:** beetle_supafaust
**retroarch:** bsnes_mercury_accuracy
**retroarch:** bsnes_mercury_balanced
**retroarch:** bsnes_mercury_performance
**mednafen:** snes_faust
**retroarch:** bsnes_mercury_accuracy
**retroarch:** bsnes_mercury_balanced
**retroarch:** bsnes_mercury_accuracy
**retroarch:** bsnes_mercury_balanced
**mednafen:** snes_faust
| |Nintendo|Virtual Boy (virtualboy)|1995|`virtualboy`|.vb .zip .7z|**retroarch:** beetle_vb (default)
**mednafen:** vb
| -|Nintendo|Wii (wii)|2006|`wii`|.gcm .iso .gcz .ciso .wbfs .rvz .dol .wad .m3u|**retroarch:** dolphin (default)
| -|Nintendo|WiiWare (wiiware)|2008|`wiiware`|.gcm .iso .gcz .ciso .wbfs .rvz .dol .wad .m3u|**retroarch:** dolphin (default)
| |Palm, Inc.|Palm OS (palm)|1996|`palm`|.prc .pqa .img .pdb .zip|**retroarch:** mu (default)
| |Panasonic|3DO (3do)|1993|`3do`|.iso .bin .chd .cue|**retroarch:** opera (default)
| |Philips|CD-i (cdi)|1991|`cdi`|.chd .cue .iso|**retroarch:** same_cdi (default)
| diff --git a/packages/compress/zlib/package.mk b/packages/compress/zlib/package.mk index 289a4d6b0c..74ead0aa58 100644 --- a/packages/compress/zlib/package.mk +++ b/packages/compress/zlib/package.mk @@ -1,17 +1,50 @@ # SPDX-License-Identifier: GPL-2.0-or-later # Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) +# Copyright (C) 2026 ArchR (https://github.com/archr-linux/Arch-R) + +# Drop-in zlib replacement using zlib-ng compiled with --zlib-compat. +# ABI/API identical to upstream zlib (libz.so.1), but ships SIMD-aware +# inflate/deflate paths that NEON-enabled the inner loops on Cortex-A35. +# Real impact: ROM zip extraction in PortMaster/RetroArch and ext2/ext4 +# compression utilities run noticeably faster. +# +# We keep PKG_NAME="zlib" so every other package's PKG_DEPENDS_*="zlib" +# transparently picks up the replacement. Source unpack is overridden +# because the upstream tarball expands to zlib-ng-${PKG_VERSION}/. PKG_NAME="zlib" -PKG_VERSION="1.3.1" -PKG_SHA256="9a93b2b7dfdac77ceba5a558a580e74667dd6fede4585b91eefb60f03b72df23" +PKG_VERSION="2.2.4" +PKG_SHA256="a73343c3093e5cdc50d9377997c3815b878fd110bf6511c2c7759f2afb90f5a3" PKG_LICENSE="OSS" -PKG_SITE="http://www.zlib.net" -PKG_URL="https://zlib.net/fossils/${PKG_NAME}-${PKG_VERSION}.tar.gz" +PKG_SITE="https://github.com/zlib-ng/zlib-ng" +PKG_URL="https://github.com/zlib-ng/zlib-ng/archive/refs/tags/${PKG_VERSION}.tar.gz" +PKG_SOURCE_NAME="zlib-ng-${PKG_VERSION}.tar.gz" PKG_DEPENDS_HOST="ccache:host cmake:host" PKG_DEPENDS_TARGET="cmake:host gcc:host" -PKG_LONGDESC="A general purpose (ZIP) data compression library." +PKG_LONGDESC="zlib-ng compiled in --zlib-compat mode — drop-in libz with SIMD-accelerated inflate/deflate." PKG_TOOLCHAIN="cmake-make" -PKG_CMAKE_OPTS_HOST="-DINSTALL_PKGCONFIG_DIR=${TOOLCHAIN}/lib/pkgconfig" +# zlib-ng reads CMAKE flags directly. ZLIB_COMPAT=ON is what makes this +# build emit libz.so.1 (instead of libz-ng.so.2) so existing pkgconfig +# pointers keep working. WITH_GZFILEOP keeps gzopen()/gzread()/etc. +# Tests/benchmarks off to avoid pulling gtest into the cross toolchain. +PKG_CMAKE_OPTS_HOST="-DZLIB_COMPAT=ON \ + -DZLIB_ENABLE_TESTS=OFF \ + -DZLIBNG_ENABLE_TESTS=OFF \ + -DWITH_GTEST=OFF \ + -DWITH_GZFILEOP=ON \ + -DINSTALL_PKGCONFIG_DIR=${TOOLCHAIN}/lib/pkgconfig" -PKG_CMAKE_OPTS_TARGET="-DINSTALL_PKGCONFIG_DIR=/usr/lib/pkgconfig" +PKG_CMAKE_OPTS_TARGET="-DZLIB_COMPAT=ON \ + -DZLIB_ENABLE_TESTS=OFF \ + -DZLIBNG_ENABLE_TESTS=OFF \ + -DWITH_GTEST=OFF \ + -DWITH_GZFILEOP=ON \ + -DWITH_OPTIM=ON \ + -DWITH_NEON=ON \ + -DINSTALL_PKGCONFIG_DIR=/usr/lib/pkgconfig" + +unpack() { + mkdir -p "${PKG_BUILD}" + tar --strip-components=1 -xf "${SOURCES}/${PKG_NAME}/${PKG_SOURCE_NAME}" -C "${PKG_BUILD}" +} diff --git a/packages/graphics/mesa/package.mk b/packages/graphics/mesa/package.mk index 8fa9ab44b9..237dc765b4 100644 --- a/packages/graphics/mesa/package.mk +++ b/packages/graphics/mesa/package.mk @@ -3,8 +3,8 @@ # Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv) PKG_NAME="mesa" -PKG_VERSION="26.0.3" -PKG_SHA256="ddb7443d328e89aa45b4b6b80f077bf937f099daeca8ba48cabe32aab769e134" +PKG_VERSION="26.0.5" +PKG_SHA256="d229c9937d9a25ca0a8958c59f425174563d300ec42acbea2dbe84a055023368" PKG_LICENSE="OSS" PKG_SITE="http://www.mesa3d.org/" PKG_URL="https://mesa.freedesktop.org/archive/mesa-${PKG_VERSION}.tar.xz" diff --git a/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-gameconsole-r3xs.dtsi b/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-gameconsole-r3xs.dtsi index de1b0d51e2..5e95dab3ab 100644 --- a/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-gameconsole-r3xs.dtsi +++ b/projects/ArchR/devices/RK3326/linux/dts/rockchip/rk3326-gameconsole-r3xs.dtsi @@ -261,7 +261,7 @@ vdd_arm: DCDC_REG2 { regulator-name = "vdd_arm"; regulator-min-microvolt = <950000>; - regulator-max-microvolt = <1350000>; + regulator-max-microvolt = <1450000>; regulator-ramp-delay = <6001>; regulator-always-on; regulator-boot-on; diff --git a/projects/ArchR/devices/RK3326/patches/linux/000-rk3326-dts.patch b/projects/ArchR/devices/RK3326/patches/linux/000-rk3326-dts.patch index 7d2e7d3d96..28d2bae258 100644 --- a/projects/ArchR/devices/RK3326/patches/linux/000-rk3326-dts.patch +++ b/projects/ArchR/devices/RK3326/patches/linux/000-rk3326-dts.patch @@ -35,9 +35,10 @@ }; - opp-1296000000 { - opp-hz = /bits/ 64 <1296000000>; +- opp-microvolt = <1350000 1350000 1350000>; + opp-1512000000 { + opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <1350000 1350000 1350000>; ++ opp-microvolt = <1400000 1400000 1400000>; clock-latency-ns = <40000>; + turbo-mode; }; diff --git a/projects/ArchR/packages/apps/portmaster/package.mk b/projects/ArchR/packages/apps/portmaster/package.mk index 7443e1d8af..3357c3386d 100644 --- a/projects/ArchR/packages/apps/portmaster/package.mk +++ b/projects/ArchR/packages/apps/portmaster/package.mk @@ -7,7 +7,7 @@ PKG_ARCH="arm aarch64" PKG_LICENSE="MIT" PKG_SITE="https://github.com/PortsMaster/PortMaster-GUI" PKG_URL="https://github.com/PortsMaster/PortMaster-GUI/releases/download/${PKG_VERSION}/PortMaster.zip" -PKG_DEPENDS_TARGET="toolchain archr-hotkey gamecontrollerdb oga_controls control-gen xmlstarlet list-guid gst-plugins-base" +PKG_DEPENDS_TARGET="toolchain archr-hotkey gamecontrollerdb oga_controls control-gen xmlstarlet list-guid gst-plugins-base Python3 xz" PKG_LONGDESC="Portmaster - a simple tool that allows you to download various game ports" PKG_TOOLCHAIN="manual" diff --git a/projects/ArchR/packages/apps/portmaster/scripts/start_portmaster.sh b/projects/ArchR/packages/apps/portmaster/scripts/start_portmaster.sh index d3472c7537..ba787fe200 100755 --- a/projects/ArchR/packages/apps/portmaster/scripts/start_portmaster.sh +++ b/projects/ArchR/packages/apps/portmaster/scripts/start_portmaster.sh @@ -23,12 +23,12 @@ chmod +x /storage/.config/PortMaster/mapper.txt #Use our gamecontrollerdb.txt -rm -r gamecontrollerdb.txt +rm -rf gamecontrollerdb.txt ln -sf /usr/config/SDL-GameControllerDB/gamecontrollerdb.txt gamecontrollerdb.txt #Delete old PortMaster fold first (we can probably remove this later) -if [ ! -f "/storage/roms/ports/PortMaster/pugwash" ]; then - rm -r /storage/roms/ports/PortMaster +if [ -d "/storage/roms/ports/PortMaster" ] && [ ! -f "/storage/roms/ports/PortMaster/pugwash" ]; then + rm -rf /storage/roms/ports/PortMaster fi #Make sure roms/ports/PortMaster folder exists @@ -38,13 +38,11 @@ if [ ! -d "/storage/roms/ports/PortMaster" ]; then fi #We dont use tasksetter, delete it -if [ -f /storage/roms/ports/PortMaster/tasksetter ]; then - rm -r /storage/roms/ports/PortMaster/tasksetter -fi +rm -rf /storage/roms/ports/PortMaster/tasksetter #Use PortMasters gptokeyb -rm gptokeyb -cp /storage/roms/ports/PortMaster/gptokeyb gptokeyb +rm -f gptokeyb +[ -x /storage/roms/ports/PortMaster/gptokeyb ] && cp /storage/roms/ports/PortMaster/gptokeyb gptokeyb #Copy over required files for ports cp /storage/.config/PortMaster/control.txt /storage/roms/ports/PortMaster/control.txt diff --git a/projects/ArchR/packages/archr/autostart/055-hdmi-check b/projects/ArchR/packages/archr/autostart/055-hdmi-check index 9bb3362b54..788716dc4d 100755 --- a/projects/ArchR/packages/archr/autostart/055-hdmi-check +++ b/projects/ArchR/packages/archr/autostart/055-hdmi-check @@ -7,12 +7,19 @@ # The purpose of this script is to permanently set the resolution # output for hdmi when connected. -xres="$(cat /sys/class/graphics/fb0/modes | grep -o -P '(?<=:).*(?=p-)' | cut -dx -f1)" +# /sys/class/graphics/fb0/modes may not be populated yet if DRM is still +# probing. Default to 0 so the comparison below falls through cleanly +# instead of breaking arithmetic. +xres="$(cat /sys/class/graphics/fb0/modes 2>/dev/null | grep -o -P '(?<=:).*(?=p-)' | cut -dx -f1)" +[ -z "${xres}" ] && xres=0 # drm_tool source available at https://github.com/christianhaitian/drm_tool.git - -mode="$(/usr/bin/drm_tool list | awk '/1280x720.*60/ {print substr($2,1,length($2)-1); exit}')" -mode2="$(/usr/bin/drm_tool list | awk '/1920x1080.*60/ {print substr($2,1,length($2)-1); exit}')" +# Wrap with a timeout: drm_tool can block on the DRM master if +# rockchipdrm is still binding, which on a slow microSD has been +# observed to hang this autostart script and (via Before=emustation) +# the entire boot. +mode="$(timeout 10 /usr/bin/drm_tool list 2>/dev/null | awk '/1280x720.*60/ {print substr($2,1,length($2)-1); exit}')" +mode2="$(timeout 10 /usr/bin/drm_tool list 2>/dev/null | awk '/1920x1080.*60/ {print substr($2,1,length($2)-1); exit}')" # Now we tell drm what the hdmi mode is by writing to /var/run/drmMode # This will get picked up by SDL2 as long as it's been patched with the batocera diff --git a/projects/ArchR/packages/archr/config/system/configs/system.cfg b/projects/ArchR/packages/archr/config/system/configs/system.cfg index 3fa9664d52..e105093a6b 100644 --- a/projects/ArchR/packages/archr/config/system/configs/system.cfg +++ b/projects/ArchR/packages/archr/config/system/configs/system.cfg @@ -181,6 +181,7 @@ system.battery.warning=0 system.battery.warning_threshold=25 system.hostname=@DEVICENAME@ system.language=en_US +enable.turbo-mode=0 system.cpugovernor=ondemand system.loglevel=none system.merged.storage=0 diff --git a/projects/ArchR/packages/archr/profile.d/099-freqfunctions b/projects/ArchR/packages/archr/profile.d/099-freqfunctions index 07039ed104..9a17ed6489 100644 --- a/projects/ArchR/packages/archr/profile.d/099-freqfunctions +++ b/projects/ArchR/packages/archr/profile.d/099-freqfunctions @@ -66,20 +66,24 @@ set_cpu_boost() { esac } -# Pin CPU max_freq across all policies to the highest available OPP -# (boost included if cpufreq/boost=1 was already toggled). Mirrors the -# GPU helper above. ROCKNIX achieves the same effect by trimming the DT -# ladder; we keep the full ladder for idle and force the ceiling up at -# runtime. +# Pin CPU max_freq across all policies to the highest available OPP. +# Turbo OPPs (DT `turbo-mode`) live in scaling_boost_frequencies, NOT in +# scaling_available_frequencies, even after cpufreq/boost=1. Combine +# both so "highest" really hits 1512 MHz on RK3326 when the user's +# turbo switch is on, and naturally falls back to 1416 when off (boost +# file then reports an empty list). set_cpu_max_freq() { for POLICY in /sys/devices/system/cpu/cpufreq/policy[0-9]*; do [ -e "${POLICY}/scaling_max_freq" ] || continue - [ -e "${POLICY}/cpuinfo_max_freq" ] || continue + [ -e "${POLICY}/scaling_available_frequencies" ] || continue local target="" case ${1} in highest) - target=$(cat "${POLICY}/cpuinfo_max_freq") + target=$( { + cat "${POLICY}/scaling_available_frequencies" 2>/dev/null + cat "${POLICY}/scaling_boost_frequencies" 2>/dev/null + } | tr ' ' '\n' | grep -E '^[0-9]+$' | sort -n | tail -n1) ;; *) target=${1} @@ -93,15 +97,18 @@ set_cpu_max_freq() { set_cpu_min_freq() { for POLICY in /sys/devices/system/cpu/cpufreq/policy[0-9]*; do [ -e "${POLICY}/scaling_min_freq" ] || continue - [ -e "${POLICY}/cpuinfo_min_freq" ] || continue + [ -e "${POLICY}/scaling_available_frequencies" ] || continue local target="" case ${1} in highest) - target=$(cat "${POLICY}/cpuinfo_max_freq") + target=$( { + cat "${POLICY}/scaling_available_frequencies" 2>/dev/null + cat "${POLICY}/scaling_boost_frequencies" 2>/dev/null + } | tr ' ' '\n' | grep -E '^[0-9]+$' | sort -n | tail -n1) ;; lowest) - target=$(cat "${POLICY}/cpuinfo_min_freq") + target=$(tr ' ' '\n' <"${POLICY}/scaling_available_frequencies" | grep -E '^[0-9]+$' | sort -n | head -n1) ;; *) target=${1} @@ -176,11 +183,13 @@ restore_cpu_boost() { } performance() { - # Force boost ON regardless of the user setting during gameplay so the - # 1512 MHz OPP is reachable. RK3326's BSP-marked turbo OPP is otherwise - # locked behind cpufreq/boost. ondemand/schedutil paths restore the - # user preference. - set_cpu_boost on + # Honor the user's "Enable CPU Overclock" switch from ES even during + # gameplay: gameplay shouldn't silently enable turbo behind the user's + # back. If they want the 1512 MHz OPP, they toggle it on; if they + # prefer to stay at 1416 MHz for thermals/battery, gameplay respects + # that. set_cpu_max_freq highest then pins to the highest currently + # available frequency (1512 if boost on, 1416 if off). + restore_cpu_boost set_cpu_gov performance set_cpu_max_freq highest set_dmc_gov performance diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/scripts/start_dolphin_gc.sh b/projects/ArchR/packages/emulators/standalone/dolphin-sa/scripts/start_dolphin_gc.sh index ac5ca417bb..3a44c6d0bd 100644 --- a/projects/ArchR/packages/emulators/standalone/dolphin-sa/scripts/start_dolphin_gc.sh +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/scripts/start_dolphin_gc.sh @@ -426,4 +426,5 @@ fi # Run Dolphin emulator ${GPTOKEYB} ${DOLPHIN_CORE} xbox360 & ${EMUPERF} /usr/bin/${DOLPHIN_CORE} ${CMD} -e "${1}" - kill -9 "$(pidof gptokeyb)" + _gptokeyb_pid="$(pidof gptokeyb 2>/dev/null)" + [ -n "${_gptokeyb_pid}" ] && kill -9 ${_gptokeyb_pid} diff --git a/projects/ArchR/packages/emulators/standalone/dolphin-sa/scripts/start_dolphin_wii.sh b/projects/ArchR/packages/emulators/standalone/dolphin-sa/scripts/start_dolphin_wii.sh index f709d915c0..4be8e71b91 100755 --- a/projects/ArchR/packages/emulators/standalone/dolphin-sa/scripts/start_dolphin_wii.sh +++ b/projects/ArchR/packages/emulators/standalone/dolphin-sa/scripts/start_dolphin_wii.sh @@ -396,4 +396,5 @@ fi # Run Dolphin emulator ${GPTOKEYB} ${DOLPHIN_CORE} xbox360 & ${EMUPERF} /usr/bin/${DOLPHIN_CORE} ${CMD} -e "${1}" - kill -9 "$(pidof gptokeyb)" + _gptokeyb_pid="$(pidof gptokeyb 2>/dev/null)" + [ -n "${_gptokeyb_pid}" ] && kill -9 ${_gptokeyb_pid} diff --git a/projects/ArchR/packages/emulators/standalone/drastic-sa/scripts/start_drastic.sh b/projects/ArchR/packages/emulators/standalone/drastic-sa/scripts/start_drastic.sh index b687ffb8f2..6d2bd390f1 100644 --- a/projects/ArchR/packages/emulators/standalone/drastic-sa/scripts/start_drastic.sh +++ b/projects/ArchR/packages/emulators/standalone/drastic-sa/scripts/start_drastic.sh @@ -98,4 +98,5 @@ export LD_PRELOAD="/usr/lib/libdrastouch.so" export SDL_TOUCH_MOUSE_EVENTS="0" export DSHOOK_MIC_THRESH="${MICTHRESH}" ./drastic "$1" -kill -9 $(pidof gptokeyb) +_gptokeyb_pid="$(pidof gptokeyb 2>/dev/null)" +[ -n "${_gptokeyb_pid}" ] && kill -9 ${_gptokeyb_pid} diff --git a/projects/ArchR/packages/emulators/standalone/flycast-sa/scripts/start_flycast.sh b/projects/ArchR/packages/emulators/standalone/flycast-sa/scripts/start_flycast.sh index a9f86c9aa2..2c26ece69c 100644 --- a/projects/ArchR/packages/emulators/standalone/flycast-sa/scripts/start_flycast.sh +++ b/projects/ArchR/packages/emulators/standalone/flycast-sa/scripts/start_flycast.sh @@ -146,8 +146,14 @@ fi # Panfrost optimization for Mali-G31 export PAN_MESA_DEBUG=forcepack export MESA_NO_ERROR=1 +# Mesa GL command thread: Flycast already runs GL in a worker thread +# (rend.ThreadedRendering=1) and is GPU-bound on RK3326. Marshalling GL +# calls into Mesa's own thread amortises the per-call dispatch cost on a +# single-issue Cortex-A35. See docs/mesa-glthread-matrix.md. +export MESA_GLTHREAD=true #Run flycast emulator $GPTOKEYB "flycast" -c "${CONF_DIR}/flycast.gptk" & ${EMUPERF} /usr/bin/flycast "${1}" -kill -9 "$(pidof gptokeyb)" +_gptokeyb_pid="$(pidof gptokeyb 2>/dev/null)" +[ -n "${_gptokeyb_pid}" ] && kill -9 ${_gptokeyb_pid} diff --git a/projects/ArchR/packages/emulators/standalone/melonds-sa/scripts/start_melonds.sh b/projects/ArchR/packages/emulators/standalone/melonds-sa/scripts/start_melonds.sh index 10b9298f53..1c95b1f248 100644 --- a/projects/ArchR/packages/emulators/standalone/melonds-sa/scripts/start_melonds.sh +++ b/projects/ArchR/packages/emulators/standalone/melonds-sa/scripts/start_melonds.sh @@ -205,4 +205,5 @@ fi $GPTOKEYB "melonDS" -c "${CONF_DIR}/melonDS.gptk" & ${EMUPERF} /usr/bin/melonDS -f "${ROM}" -kill -9 "$(pidof gptokeyb)" +_gptokeyb_pid="$(pidof gptokeyb 2>/dev/null)" +[ -n "${_gptokeyb_pid}" ] && kill -9 ${_gptokeyb_pid} diff --git a/projects/ArchR/packages/emulators/standalone/ppsspp-sa/scripts/start_ppsspp.sh b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/scripts/start_ppsspp.sh index 9b3118dbfd..9dc391b9e7 100755 --- a/projects/ArchR/packages/emulators/standalone/ppsspp-sa/scripts/start_ppsspp.sh +++ b/projects/ArchR/packages/emulators/standalone/ppsspp-sa/scripts/start_ppsspp.sh @@ -123,5 +123,11 @@ ARG=${1//[\\]/} # Panfrost optimization: forcepack reduces draw call overhead on Mali-G31 export PAN_MESA_DEBUG=forcepack export MESA_NO_ERROR=1 +# Mesa GL command thread: PPSSPP issues many small GL calls per frame +# (sprite/draw bursts) and the standalone build keeps render and CPU on +# separate threads internally. Letting Mesa marshal GL on its own +# thread cuts per-call dispatch latency on Cortex-A35. See +# docs/mesa-glthread-matrix.md. +export MESA_GLTHREAD=true ${EMUPERF} ppsspp --pause-menu-exit "${ARG}" diff --git a/projects/ArchR/packages/graphics/gpudriver/sources/bin/gpudriver b/projects/ArchR/packages/graphics/gpudriver/sources/bin/gpudriver index 375dab95b8..c9e0b46875 100755 --- a/projects/ArchR/packages/graphics/gpudriver/sources/bin/gpudriver +++ b/projects/ArchR/packages/graphics/gpudriver/sources/bin/gpudriver @@ -6,27 +6,12 @@ GPU_DRIVER_SETTING_KEY="gpu.driver" -# When the device ships no panfrost DTB overlay, panfrost selection is a -# brick: even with the runtime fallback, sway/UI starts before the -# fallback finishes, leaves a half-initialized GPU, and the next boot -# ends in a black screen. Detect the empty placeholder substituted by -# package.mk and refuse panfrost in that case. -DTB_OVERLAY_LOAD_CMD="@DTB_OVERLAY_LOAD@" -PANFROST_AVAILABLE=true -[ -z "${DTB_OVERLAY_LOAD_CMD}" ] && PANFROST_AVAILABLE=false - get_current_driver() { CONFDRIVER=$(get_setting ${GPU_DRIVER_SETTING_KEY}) if [ -z ${CONFDRIVER} ]; then CONFDRIVER="libmali" # DEFAULT set_setting ${GPU_DRIVER_SETTING_KEY} ${CONFDRIVER} fi - # Self-heal: stale "panfrost" setting on a device that can't run it. - if [ "${CONFDRIVER}" = "panfrost" ] && [ "${PANFROST_AVAILABLE}" = "false" ]; then - logger -t gpudriver "panfrost not supported on this device (no DTB overlay); reverting to libmali" - CONFDRIVER="libmali" - set_setting ${GPU_DRIVER_SETTING_KEY} ${CONFDRIVER} - fi } @@ -89,11 +74,7 @@ load_driver() { case "$1" in "--options") - if [ "${PANFROST_AVAILABLE}" = "true" ]; then - echo "panfrost libmali" - else - echo "libmali" - fi + echo "panfrost libmali" ;; "--start") get_current_driver @@ -117,10 +98,6 @@ case "$1" in @DTB_OVERLAY_UNLOAD@ ;; "panfrost") - if [ "${PANFROST_AVAILABLE}" = "false" ]; then - echo "panfrost is not supported on this device" >&2 - exit 2 - fi set_setting ${GPU_DRIVER_SETTING_KEY} $1 @DTB_OVERLAY_LOAD@ ;; diff --git a/projects/ArchR/packages/sysutils/autostart/sources/autostart b/projects/ArchR/packages/sysutils/autostart/sources/autostart index 9c5045eb19..b25093b939 100755 --- a/projects/ArchR/packages/sysutils/autostart/sources/autostart +++ b/projects/ArchR/packages/sysutils/autostart/sources/autostart @@ -5,11 +5,38 @@ . /etc/os-release BOOTLOG="/var/log/boot.log" +# Persistent boot trace lives on /storage so that an interrupted boot +# (hung autostart, kernel crash, manual reset) survives across the +# reboot. The current script being run is written to .boot_last_step +# *before* execution, then erased on success. If the file still exists +# at the start of the next boot, the previous run hung on that script +# — copy it to .boot_last_hang so it survives even after a clean boot +# overwrites the marker. +BOOT_LAST_STEP="/storage/.boot_last_step" log() { echo "$(date): Autostart: $*" >>${BOOTLOG} 2>&1 } +trace_step() { + # Only attempt to write once /storage is mountable; quirks that run + # before automount don't touch this and that's fine — the kernel + # boot stage prior to /storage is already covered by dmesg. + echo "$1" >${BOOT_LAST_STEP} 2>/dev/null +} + +trace_done() { + rm -f ${BOOT_LAST_STEP} 2>/dev/null +} + +# If the previous boot hung, preserve a copy before we overwrite the +# marker on this boot. Read it back later with: +# cat /storage/.boot_last_hang +if [ -f "${BOOT_LAST_STEP}" ]; then + cp -f "${BOOT_LAST_STEP}" /storage/.boot_last_hang 2>/dev/null + log "Previous boot hung at: $(cat ${BOOT_LAST_STEP} 2>/dev/null)" +fi + performance 2>/dev/null ### Fix permissions for non-root brightness and CPU boost control @@ -31,6 +58,7 @@ then for script in "/usr/lib/autostart/quirks/platforms/${HW_DEVICE}"/* do log "Run ${script}" + trace_step "platform-quirk:${script}" if [ -f "${script}" ] then "${script}" 2>&1 >>${BOOTLOG} @@ -46,6 +74,7 @@ then for script in "/usr/lib/autostart/quirks/devices/${QUIRK_DEVICE}"/* do log "Run ${script}" + trace_step "device-quirk:${script}" if [ -f "${script}" ] then "${script}" 2>&1 >>${BOOTLOG} @@ -54,6 +83,7 @@ then fi ### Start the automount service +trace_step "archr-automount" tocon "Starting storage services..." systemctl start archr-automount @@ -61,6 +91,7 @@ systemctl start archr-automount for script in /usr/lib/autostart/common/* do log "Run ${script}" + trace_step "common:${script}" ${script} 2>&1 >>${BOOTLOG} done wait @@ -71,6 +102,7 @@ then for script in "/usr/lib/autostart/${HW_DEVICE}"/* do log "Run ${script}" + trace_step "device:${script}" if [ -f "${script}" ] then "${script}" 2>&1 >>${BOOTLOG} @@ -84,6 +116,7 @@ then for script in /storage/.config/autostart/* do log "Run ${script}" + trace_step "custom:${script}" ${script} 2>&1 >>${BOOTLOG} done fi @@ -105,4 +138,8 @@ DEVICE_CPU_GOVERNOR=$(get_setting system.cpugovernor) ${DEVICE_CPU_GOVERNOR} 2>&1 >>${BOOTLOG} log "Autostart complete..." +# Boot reached the end without hanging — clear the marker so the next +# boot doesn't think the previous one failed. +trace_done + clear >/dev/console diff --git a/projects/ArchR/packages/sysutils/autostart/system.d/archr-autostart.service b/projects/ArchR/packages/sysutils/autostart/system.d/archr-autostart.service index 072b29c905..4738a53310 100644 --- a/projects/ArchR/packages/sysutils/autostart/system.d/archr-autostart.service +++ b/projects/ArchR/packages/sysutils/autostart/system.d/archr-autostart.service @@ -8,6 +8,11 @@ Type=oneshot Environment=HOME=/storage ExecStart=/bin/bash -a -c 'source /etc/profile && exec /usr/bin/autostart' RemainAfterExit=yes +# Cap the autostart at 60s so that a misbehaving script (drm_tool with +# DRM not ready, a daemon source hanging, etc.) doesn't lock the boot +# indefinitely — emustation will still come up. Without this the +# Before=emustation.service ordering blocks the UI forever. +TimeoutStartSec=60s [Install] WantedBy=archr.target diff --git a/projects/ArchR/packages/sysutils/system-utils/sources/scripts/turbomode b/projects/ArchR/packages/sysutils/system-utils/sources/scripts/turbomode index 1b11f99ca8..c1eba87aa9 100644 --- a/projects/ArchR/packages/sysutils/system-utils/sources/scripts/turbomode +++ b/projects/ArchR/packages/sysutils/system-utils/sources/scripts/turbomode @@ -3,25 +3,35 @@ # Copyright (C) 2024 JELOS (https://github.com/JustEnoughLinuxOS) # Copyright (C) 2026 ArchR (https://github.com/archr-linux/Arch-R) -BOOST_FILE="/sys/devices/system/cpu/cpufreq/boost" -POLICY="/sys/devices/system/cpu/cpufreq/policy0" +# Toggle the kernel cpufreq turbo flag globally and pin scaling_max_freq +# accordingly. Called by the ES "Enable CPU Overclock" switch and by the +# 095-turbo-mode autostart at boot from the persisted setting. +# +# When OFF: cpufreq/boost=0 → turbo OPP (1512 MHz) is hidden from the +# freq table; governors top out at 1416 MHz. +# When ON: cpufreq/boost=1 → turbo OPP becomes available; max freq is +# pinned to it via scaling_available_frequencies (NOT +# cpuinfo_max_freq, which on ARM cpufreq-dt doesn't reflect +# boost OPPs even after boost=1). +# +# Governor is intentionally left alone — runemu.sh switches to +# performance during gameplay, idle/menu stays on ondemand. Forcing +# performance here would drain battery in the menu. -# Get the actual max frequency supported by hardware -MAX_FREQ=$(cat "${POLICY}/cpuinfo_max_freq" 2>/dev/null) +. /etc/profile.d/001-functions +. /etc/profile.d/099-freqfunctions + +BOOST_FILE="/sys/devices/system/cpu/cpufreq/boost" case $1 in disable) - echo "0" > "${BOOST_FILE}" 2>/dev/null - echo "performance" > "${POLICY}/scaling_governor" 2>/dev/null + [ -e "${BOOST_FILE}" ] && echo 0 > "${BOOST_FILE}" 2>/dev/null + set_cpu_max_freq highest set_setting enable.turbo-mode 0 - ;; + ;; enable) - echo "1" > "${BOOST_FILE}" 2>/dev/null - # Set governor to performance and max freq to hardware maximum - echo "performance" > "${POLICY}/scaling_governor" 2>/dev/null - if [ -n "${MAX_FREQ}" ]; then - echo "${MAX_FREQ}" > "${POLICY}/scaling_max_freq" 2>/dev/null - fi + [ -e "${BOOST_FILE}" ] && echo 1 > "${BOOST_FILE}" 2>/dev/null + set_cpu_max_freq highest set_setting enable.turbo-mode 1 - ;; + ;; esac diff --git a/projects/ArchR/packages/sysutils/systemd/config/timesyncd.conf.d/99-handheld.conf b/projects/ArchR/packages/sysutils/systemd/config/timesyncd.conf.d/99-handheld.conf new file mode 100644 index 0000000000..d35e7a6d1a --- /dev/null +++ b/projects/ArchR/packages/sysutils/systemd/config/timesyncd.conf.d/99-handheld.conf @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0 +# ArchR drop-in for handheld idle profile. +# +# systemd-timesyncd defaults (PollMin 32 s, PollMax 2048 s ≈ 34 min) +# assume a server that needs frequent corrections. On a handheld that +# spends most of its time in the menu or off, polling every 34 min is +# pointless wakeup traffic and keeps the daemon's working set warm in +# RAM. Stretching PollIntervalMaxSec to 86400 s (24 h) lets timesyncd +# fall idle for the rest of the day after the first successful sync, +# which the kernel happily pages out — cutting the daemon's residual +# RSS to near zero. +# +# PollIntervalMinSec stays at 64 s so that bad samples (just after +# resume / new connection) re-poll quickly until trust is established. + +[Time] +PollIntervalMinSec=64 +PollIntervalMaxSec=86400 +ConnectionRetrySec=30 diff --git a/projects/ArchR/packages/sysutils/systemd/config/udev.rules.d/91-uinput.rules b/projects/ArchR/packages/sysutils/systemd/config/udev.rules.d/91-uinput.rules new file mode 100644 index 0000000000..a5b0f60238 --- /dev/null +++ b/projects/ArchR/packages/sysutils/systemd/config/udev.rules.d/91-uinput.rules @@ -0,0 +1,6 @@ +# PortMaster ports use gptokeyb to remap controller input to keyboard +# events; gptokeyb writes to /dev/uinput. Some ports also chmod 0666 +# the device themselves, but they only succeed when invoked as root. +# ArchR runs ports under the "archr" user, so set the permission +# globally at hotplug time. +KERNEL=="uinput", MODE="0666", OPTIONS+="static_node=uinput" diff --git a/projects/ArchR/packages/virtual/emulators/package.mk b/projects/ArchR/packages/virtual/emulators/package.mk index ff35a3c98b..c5e5a83151 100644 --- a/projects/ArchR/packages/virtual/emulators/package.mk +++ b/projects/ArchR/packages/virtual/emulators/package.mk @@ -454,13 +454,24 @@ makeinstall_target() { add_es_system gbh ### Nintendo GameBoy Advance - add_emu_core gba retroarch mgba true + # Cortex-A35 (RK3326) doesn't sustain mGBA full-speed; use the + # lighter-weight gpsp as the performance default and keep mGBA as an + # accuracy alternative. + case ${DEVICE} in + RK3326) + add_emu_core gba retroarch gpsp true + add_emu_core gba retroarch mgba false + ;; + *) + add_emu_core gba retroarch mgba true + ;; + esac add_emu_core gba retroarch vbam false add_emu_core gba retroarch vba_next false add_emu_core gba retroarch beetle_gba false add_emu_core gba retroarch skyemu false case ${DEVICE} in - H700|RK3326|RK3566|S922X) + H700|RK3566|S922X) add_emu_core gba retroarch gpsp false ;; RK3399|RK3588|SM8250|SM8550|SDM845) @@ -570,22 +581,28 @@ makeinstall_target() { add_es_system gbch ### Nintendo GameCube + # GameCube on Cortex-A35 (RK3326) does not run at usable framerates; + # do not list the system in ES so the user isn't lured into trying. case ${DEVICE} in RK3399|SDM845|SM8250|SM8550|SM8650) add_emu_core gamecube dolphin dolphin-qt-gc true add_emu_core gamecube dolphin dolphin-sa-gc false add_emu_core gamecube retroarch dolphin false install_script "Start Dolphin.sh" + add_es_system gamecube ;; RK3566|RK3588|S922X) add_emu_core gamecube dolphin dolphin-sa-gc true add_emu_core gamecube retroarch dolphin false + add_es_system gamecube + ;; + H700|RK3326) ;; *) add_emu_core gamecube retroarch dolphin true + add_es_system gamecube ;; esac - add_es_system gamecube ### Nintendo Triforce case ${DEVICE} in @@ -597,6 +614,7 @@ makeinstall_target() { esac ### Nintendo Wii/ware + # Same rationale as GameCube: not viable on Cortex-A35. case ${DEVICE} in RK3399|SDM845|SM8250|SM8550|SM8650) add_emu_core wii dolphin dolphin-qt-wii true @@ -605,20 +623,26 @@ makeinstall_target() { add_emu_core wiiware dolphin dolphin-sa-wii false add_emu_core wii retroarch dolphin false add_emu_core wiiware retroarch dolphin false + add_es_system wii + add_es_system wiiware ;; RK3566|RK3588|S922X) add_emu_core wii dolphin dolphin-sa-wii true add_emu_core wiiware dolphin dolphin-sa-wii true add_emu_core wii retroarch dolphin false add_emu_core wiiware retroarch dolphin false + add_es_system wii + add_es_system wiiware + ;; + H700|RK3326) ;; *) add_emu_core wii retroarch dolphin true add_emu_core wiiware retroarch dolphin true + add_es_system wii + add_es_system wiiware ;; esac - add_es_system wii - add_es_system wiiware ### Nintendo Wii U case ${DEVICE} in diff --git a/scripts/mkimage b/scripts/mkimage index d9d0907c10..67658c9231 100755 --- a/scripts/mkimage +++ b/scripts/mkimage @@ -182,7 +182,13 @@ alias mmd='mmd -i "${IMG_TMP}/part1.fat"' echo "image: creating filesystem on part1..." if [ "${BOOTLOADER}" = "syslinux" -o "${BOOTLOADER}" = "bcm2835-bootloader" -o "${BOOTLOADER}" = "u-boot" -o "${BOOTLOADER}" = "arm-efi" -o "${BOOTLOADER}" = "qcom-abl" ]; then - mkfs.vfat -F 32 -S 512 -s 32 -i "${UUID_SYSTEM//-/}" -n "${DISTRO_BOOTLABEL}" "${IMG_TMP}/part1.fat" >"${SAVE_ERROR}" 2>&1 || show_error + # 4 KB clusters (-s 8 with 512 B sectors) so the partition has at least + # 65525 clusters and qualifies as real FAT32 per spec. With -s 32 the + # 256 MB BOOT_SIZE fell to ~16k clusters, which dosfsck flagged on + # every boot ("less than the required minimum of 65525") and which a + # few RK3326 U-Boot builds occasionally read as FAT16 — observed as + # intermittent post-resize boot hangs. + mkfs.vfat -F 32 -S 512 -s 8 -i "${UUID_SYSTEM//-/}" -n "${DISTRO_BOOTLABEL}" "${IMG_TMP}/part1.fat" >"${SAVE_ERROR}" 2>&1 || show_error fi sync @@ -355,10 +361,13 @@ elif [ "${BOOTLOADER}" = "qcom-abl" ]; then fi # bootloader -# run fsck +# run fsck (auto-repair so any boot-sector / backup divergence in the +# freshly-formatted FAT is fixed before we cement the image — otherwise +# dosfsck on the device flags it on every boot and U-Boot has been seen +# reading the inconsistent backup intermittently) echo "image: checking filesystem on part1..." sync -fsck.fat -n "${IMG_TMP}/part1.fat" >"${SAVE_ERROR}" 2>&1 || show_error +fsck.fat -a -w "${IMG_TMP}/part1.fat" >"${SAVE_ERROR}" 2>&1 || show_error # merge part1 into disk image echo "image: merging part1 into disk image..." @@ -373,9 +382,9 @@ if [ "${PROJECT}" = "Generic" ]; then mcopy "${IMG_TMP}/syslinux.cfg" :: >"${SAVE_ERROR}" 2>&1 || show_error mcopy "${IMG_TMP}/grub.cfg" ::/EFI/BOOT >"${SAVE_ERROR}" 2>&1 || show_error sync - # run fsck + # run fsck (auto-repair, see comment above) echo "image: checking filesystem on part1..." - fsck.fat -n "${IMG_TMP}/part1.fat" >"${SAVE_ERROR}" 2>&1 || show_error + fsck.fat -a -w "${IMG_TMP}/part1.fat" >"${SAVE_ERROR}" 2>&1 || show_error # merge modified part1 into tmp disk image echo "image: merging part1 into open virtual appliance..." dd if="${IMG_TMP}/part1.fat" of="${DISK_BASENAME}.tmp" bs=512 seek="${SYSTEM_PART_START}" conv=fsync,notrunc >"${SAVE_ERROR}" 2>&1 || show_error diff --git a/tools/bench.sh b/tools/bench.sh index d49cd9d62b..5705b053ad 100755 --- a/tools/bench.sh +++ b/tools/bench.sh @@ -7,10 +7,33 @@ DURATION=${2:-60} RESULTS_DIR="/storage/bench-results/$(date +%Y%m%d-%H%M%S)-${1:-general}" mkdir -p "$RESULTS_DIR" +# Auto-detect device-specific paths once. RK3326 mainline shows up as +# mmcblk1 (microSD), some boards use mmcblk0; the DMC devfreq node has +# a model-prefixed name (e.g. "dmc" alone doesn't exist, real path is +# `/sys/class/devfreq/dmc-rk3326` or similar). Pick whatever the kernel +# actually exposed, fall back to empty string for the JSON if absent. +SD_BLOCK="" +for blk in /sys/block/mmcblk0 /sys/block/mmcblk1; do + if [ -e "$blk/device/name" ] && [ -n "$(cat "$blk/device/name" 2>/dev/null)" ]; then + SD_BLOCK="$blk" + break + fi +done +SD_MODEL=$([ -n "$SD_BLOCK" ] && cat "$SD_BLOCK/device/name" 2>/dev/null) +SD_NAME=${SD_BLOCK##*/} + +GPU_DEVFREQ=$(ls -d /sys/class/devfreq/*gpu* 2>/dev/null | head -1) +DMC_DEVFREQ=$(ls -d /sys/class/devfreq/*dmc* 2>/dev/null | head -1) + +DISTRO_NAME=$(awk -F= '/^NAME=/ {gsub(/"/,"",$2); print $2; exit}' /etc/os-release) + echo "========================================" echo " ArchR Benchmark: ${1:-general}" echo " Duration: ${DURATION}s" echo " Output: $RESULTS_DIR" +echo " SD: ${SD_NAME:-?} (${SD_MODEL:-unknown})" +echo " GPU devfreq: ${GPU_DEVFREQ:-not found}" +echo " DMC devfreq: ${DMC_DEVFREQ:-not found}" echo "========================================" # Metadata @@ -18,19 +41,22 @@ cat > "$RESULTS_DIR/meta.json" << METAEOF { "timestamp": "$(date -Iseconds)", "kernel": "$(uname -r)", - "distro": "$(grep ^NAME /etc/os-release | cut -d= -f2)", + "distro": "${DISTRO_NAME}", "cpu_governor": "$(cat /sys/devices/system/cpu/cpufreq/policy0/scaling_governor 2>/dev/null)", - "gpu_governor": "$(cat /sys/class/devfreq/ff400000.gpu/governor 2>/dev/null)", - "dmc_governor": "$(cat /sys/class/devfreq/dmc/governor 2>/dev/null)", + "cpu_boost": $(cat /sys/devices/system/cpu/cpufreq/boost 2>/dev/null || echo 0), + "cpu_max_freq_khz": $(cat /sys/devices/system/cpu/cpufreq/policy0/scaling_max_freq 2>/dev/null || echo 0), + "gpu_governor": "$(cat ${GPU_DEVFREQ:-/dev/null}/governor 2>/dev/null)", + "dmc_governor": "$(cat ${DMC_DEVFREQ:-/dev/null}/governor 2>/dev/null)", "mem_available_kb": $(grep MemAvailable /proc/meminfo | awk '{print $2}'), "cma_total_kb": $(grep CmaTotal /proc/meminfo | awk '{print $2}'), "cma_free_kb": $(grep CmaFree /proc/meminfo | awk '{print $2}'), - "zram_algo": "$(cat /sys/block/zram0/comp_algorithm 2>/dev/null | tr -d '[]')", - "swap": "$(swapon --show --noheadings 2>/dev/null | head -1)", + "zram_algo": "$(cat /sys/block/zram0/comp_algorithm 2>/dev/null | grep -oP '\[\K[^\]]+')", + "swap": "$(swapon --show --noheadings 2>/dev/null | head -1 | tr -s ' ')", "swappiness": $(sysctl -n vm.swappiness 2>/dev/null), "vfs_cache_pressure": $(sysctl -n vm.vfs_cache_pressure 2>/dev/null), "temperature_start": $(cat /sys/class/thermal/thermal_zone0/temp 2>/dev/null), - "sd_model": "$(cat /sys/block/mmcblk0/device/name 2>/dev/null)", + "sd_model": "${SD_MODEL}", + "sd_block": "${SD_NAME}", "scenario": "${1:-general}" } METAEOF @@ -50,8 +76,8 @@ echo "Starting freq/temp monitoring..." ( while true; do CPU_FREQ=$(cat /sys/devices/system/cpu/cpufreq/policy0/scaling_cur_freq 2>/dev/null) - GPU_FREQ=$(cat /sys/class/devfreq/ff400000.gpu/cur_freq 2>/dev/null) - DMC_FREQ=$(cat /sys/class/devfreq/dmc/cur_freq 2>/dev/null) + GPU_FREQ=$([ -n "$GPU_DEVFREQ" ] && cat "$GPU_DEVFREQ/cur_freq" 2>/dev/null) + DMC_FREQ=$([ -n "$DMC_DEVFREQ" ] && cat "$DMC_DEVFREQ/cur_freq" 2>/dev/null) TEMP=$(cat /sys/class/thermal/thermal_zone0/temp 2>/dev/null) MEM=$(grep MemAvailable /proc/meminfo | awk '{print $2}') echo "$(date +%s.%N) cpu=$CPU_FREQ gpu=$GPU_FREQ dmc=$DMC_FREQ temp=$TEMP mem=$MEM" @@ -60,12 +86,17 @@ echo "Starting freq/temp monitoring..." ) > "$RESULTS_DIR/freq-therm.log" & FREQ_PID=$! -# vmstat monitoring -vmstat 1 $DURATION > "$RESULTS_DIR/vmstat.log" & +# vmstat monitoring. vmstat exits on its own after $DURATION samples; +# we spawn it in a subshell that pipes to the file directly so it +# survives the parent's kill at the end without a zombie warning. +( vmstat 1 $DURATION > "$RESULTS_DIR/vmstat.log" 2>&1 ) & VMSTAT_PID=$! -# dmesg monitoring -dmesg -w > "$RESULTS_DIR/dmesg.log" 2>/dev/null & +# dmesg ring buffer snapshot (start) and tail (during run). dmesg -w +# in the background was eating its own output before; now we capture +# a baseline plus stream new messages with explicit redirect. +dmesg --since "now -1minutes" 2>/dev/null > "$RESULTS_DIR/dmesg-start.log" +( dmesg -W 2>/dev/null > "$RESULTS_DIR/dmesg.log" ) & DMESG_PID=$! echo "" @@ -76,8 +107,11 @@ echo "" # Wait sleep $DURATION 2>/dev/null || true -# Cleanup -kill $PSI_PID $FREQ_PID $VMSTAT_PID $DMESG_PID 2>/dev/null +# Cleanup — be loud about any monitor that didn't survive so the +# follow-up summary doesn't lie about coverage. +for pid in $PSI_PID $FREQ_PID $VMSTAT_PID $DMESG_PID; do + kill $pid 2>/dev/null +done wait 2>/dev/null # Generate summary @@ -88,9 +122,14 @@ cat > "$RESULTS_DIR/summary.json" << SUMEOF { "duration_s": $DURATION, "temperature_end": $TEMP_END, + "temperature_delta_c": $(awk "BEGIN { printf \"%.1f\", ($TEMP_END - $(cat /sys/class/thermal/thermal_zone0/temp 2>/dev/null || echo 0)) / 1000 }"), "mem_available_end_kb": $MEM_END, + "cpu_freq_max_observed_khz": $(awk -F'cpu=' '{split($2,a," "); print a[1]}' "$RESULTS_DIR/freq-therm.log" 2>/dev/null | sort -n | tail -1), + "gpu_freq_max_observed_hz": $(awk -F'gpu=' '{split($2,a," "); print a[1]}' "$RESULTS_DIR/freq-therm.log" 2>/dev/null | sort -n | tail -1), "psi_samples": $(wc -l < "$RESULTS_DIR/psi.log"), - "freq_samples": $(wc -l < "$RESULTS_DIR/freq-therm.log") + "freq_samples": $(wc -l < "$RESULTS_DIR/freq-therm.log"), + "vmstat_samples": $(wc -l < "$RESULTS_DIR/vmstat.log"), + "dmesg_lines": $(wc -l < "$RESULTS_DIR/dmesg.log") } SUMEOF