Model Linx EBSTATE and firmwareless direct-kernel boot in QEMU#31
Model Linx EBSTATE and firmwareless direct-kernel boot in QEMU#31zhoubot wants to merge 4 commits into
Conversation
…base The recovered my.patch is treated as the authoritative latest Linx QEMU line. This commit captures the full applied tree on the old upstream base that best matches the patch, including target/linx, linux-user/linx, the older linx-softmmu and linx-linux-user target surfaces, and the supporting core-file changes. Constraint: The recovered patch references an unrecoverable LinxInit firmware blob and internal submodule URLs, so this commit keeps the source tree coherent while making minimal local build adaptations for missing firmware-at-configure and Darwin host gating Rejected: Keep the newer partial forward-port as master | it does not represent the authoritative latest implementation from my.patch Confidence: medium Scope-risk: broad Reversibility: clean Directive: Treat this branch as the source of truth for the recovered latest Linx QEMU line; do not mix it with the newer partial linx64-softmmu line without an explicit port plan Tested: linx-linux-user configure reaches target generation on Darwin after local host-policy relaxations Not-tested: successful full build of qemu-linx or qemu-system-linx from this branch
The previous commit captured the applied latest tree from my.patch, but also included transient files from local configure probing under build-user. Remove those generated artifacts so the branch contains only intended source content. Confidence: high Scope-risk: narrow Reversibility: clean Tested: branch status clean aside from expected source changes before commit
* Sync QEMU firmware and CI submodule baselines Advance the vendored ROM and libvirt-ci gitlinks together so the emulator tree points at one consistent set of external firmware and CI snapshots. Constraint: This repository tracks ROM and CI dependencies as gitlink snapshots rather than in-tree copies Rejected: Leave the existing mixed submodule revisions in place | makes emulator state harder to reproduce Confidence: medium Scope-risk: narrow Directive: Treat these gitlink bumps as a coordinated baseline update and validate firmware-dependent flows before bisecting emulator regressions across them Tested: git diff --check Not-tested: QEMU build, firmware boot, or CI execution * Stabilize the recovered Linx64 QEMU branch for clean rebuilds Preserve the recovered v7.0.0-based Linx implementation while making the branch reproducible from a fresh configure/build and aligning boot/reset handling with the recovered firmwareless lane. Constraint: Recovered patch line is authoritative and must stay on the v7.0.0 compatibility base Rejected: Rebase the recovered implementation onto current upstream master | much larger integration surface with no validation benefit for this lane Confidence: medium Scope-risk: moderate Reversibility: clean Directive: Keep linx64-softmmu single-target shims in sync with target/linx header expectations before changing Meson target wiring Tested: Fresh ../configure --target-list=linx64-softmmu --disable-werror, full ninja build, qemu-system-linx64-unsigned --version Not-tested: Guest boot/runtime smoke beyond binary startup --------- Co-authored-by: RuoyuZhou <ruoyu.zhou@hisilicon.com>
The staged work extends CSR naming and live block-state handling, adds firmwareless direct-kernel boot seeding plus low-page debug hooks, and broadens decode, translate, execute, and bring-up device behavior around the current Linux runtime lane. Constraint: The current runtime lane depends on ACR1 EBSTATE visibility and firmwareless boot instead of a Linx firmware blob Rejected: Split direct-boot hooks from EBSTATE and translate/execute work | the user asked to package the current cohesive worktree state Confidence: medium Scope-risk: broad Directive: Keep the ACR1 0x1f40..0x1f5f window as live architectural block state; emulator-only spill data belongs in hidden extension slots Tested: git diff --check Not-tested: qemu build, runtime smoke, TSVC and full-OS gates Co-authored-by: OmX <omx@oh-my-codex.dev>
There was a problem hiding this comment.
Code Review
This pull request introduces the new 'linx' target architecture, including custom CPU, memory, and interrupt controller (LXIC) models, along with support for atomic block execution, custom debugging tools, and low-precision softfloat types. While the implementation is comprehensive, several critical issues must be addressed. These include a potential out-of-bounds memory read in loader.c due to integer underflow, a potential NULL pointer dereference in linx_hart.c, a missing break statement in tcg-accel-ops-mttcg.c, and a regression in configure that breaks non-Linux compilation. Additionally, several portability issues with format specifiers, GDB syntax errors, and code style violations should be resolved.
| if (rom->data && rom->datasize > 0x5c - rom->addr + 7) { | ||
| size_t off = 0x5c - rom->addr; | ||
| uint8_t *p = rom->data + off; | ||
| error_report("LINX_ROM_LOW[%s] src_5c=%02x %02x %02x %02x %02x %02x %02x %02x", | ||
| rom->name, | ||
| p[0], p[1], p[2], p[3], | ||
| p[4], p[5], p[6], p[7]); | ||
| } |
There was a problem hiding this comment.
If rom->addr is greater than 0x5c (for example, 0x60), the expression 0x5c - rom->addr will underflow to a very large unsigned value. This causes rom->datasize > 0x5c - rom->addr + 7 to evaluate to true, and subsequently rom->data + off will point to an out-of-bounds memory location (before rom->data), leading to an out-of-bounds read and potential crash. Add a check to ensure rom->addr <= 0x5c before performing the subtraction.
if (rom->data && rom->addr <= 0x5c && rom->datasize > 0x5c - rom->addr + 7) {
size_t off = 0x5c - rom->addr;
uint8_t *p = rom->data + off;
error_report("LINX_ROM_LOW[%s] src_5c=%02x %02x %02x %02x %02x %02x %02x %02x",
rom->name,
p[0], p[1], p[2], p[3],
p[4], p[5], p[6], p[7]);
}| printf("cpu %d: linx_debug max insn (%lu) reach on %lu\n", | ||
| cpu->cpu_index, cpu->max_insn_count, cpu->insn_count); |
There was a problem hiding this comment.
Using %lu to print uint64_t variables (cpu->max_insn_count and cpu->insn_count) is non-portable and will cause compilation warnings or errors on 32-bit platforms or 64-bit Windows where long is 32-bit. Use PRIu64 instead. Also, consider using qemu_log instead of printf to avoid polluting stdout.
qemu_log("cpu %d: linx_debug max insn (%" PRIu64 ") reach on %" PRIu64 "\n",
cpu->cpu_index, cpu->max_insn_count, cpu->insn_count);| case EXCP_ATOMIC_BLK: | ||
| qemu_mutex_unlock_iothread(); | ||
| cpu_exec_multi_steps_atomic(cpu); | ||
| qemu_mutex_lock_iothread(); |
There was a problem hiding this comment.
There is a missing break statement at the end of case EXCP_ATOMIC_BLK:, which causes execution to fall through to default:. While default currently only contains a break, this is extremely fragile and violates coding standards.
| qemu_mutex_lock_iothread(); | |
| qemu_mutex_lock_iothread(); | |
| break; |
|
|
||
| if [ "$linux_user" != no ]; then | ||
| if [ "$targetos" = linux ] && [ -d $source_path/linux-user/include/host/$cpu ]; then | ||
| if [ -d $source_path/linux-user/include/host/$cpu ]; then |
There was a problem hiding this comment.
Removing [ "$targetos" = linux ] allows linux-user to be enabled on non-Linux hosts (such as macOS or BSD) if the directory $source_path/linux-user/include/host/$cpu exists. Since linux-user relies on Linux-specific system calls and headers, this will cause compilation failures on non-Linux platforms.
| if [ -d $source_path/linux-user/include/host/$cpu ]; then | |
| if [ "$targetos" = linux ] && [ -d $source_path/linux-user/include/host/$cpu ]; then |
| offset = offset % VIRT_LXIC_DOMAIN_STRIDE; | ||
|
|
||
| if (dom < 0 || dom >= VIRT_LXIC_DOMAIN_NUM) { | ||
| qemu_log("Error offset: %lx, error domain: %x\n", offset, dom); |
There was a problem hiding this comment.
Using %lx to print hwaddr (which is uint64_t) is non-portable and will fail to compile on 32-bit hosts where hwaddr is unsigned long long. Use HWADDR_PRIx instead. Also, use qemu_log_mask(LOG_GUEST_ERROR, ...) instead of bare qemu_log for guest errors.
qemu_log_mask(LOG_GUEST_ERROR, "Error offset: %" HWADDR_PRIx ", error domain: %x\n", offset, dom);|
|
||
| # Load QEMU-specific sub-commands and settings | ||
| source scripts/qemu-gdb.py | ||
| qemu.gdbinit No newline at end of file |
| [submodule "dtc"] | ||
| path = dtc | ||
| url = https://gitlab.com/qemu-project/dtc.git | ||
| url = ssh://git@szv-y.codehub.huawei.com:2222/qemu/dtc.git |
| ctl->page[i].threshold = 0; | ||
| for (j = 0; j < CTL_PENDING_WORD; j++) | ||
| ctl->page[i].pending[j] = 0; | ||
| for (j = 0; j < CTL_ENABLE_WORD; j++) | ||
| ctl->page[i].enable[j] = 0xFFFFFFFF; | ||
| for (j = 0; j < CTL_TYPE_WORD; j++) |
There was a problem hiding this comment.
QEMU coding style requires braces {} for all blocks, even single-line ones.
for (j = 0; j < CTL_PENDING_WORD; j++) {
ctl->page[i].pending[j] = 0;
}
for (j = 0; j < CTL_ENABLE_WORD; j++) {
ctl->page[i].enable[j] = 0xFFFFFFFF;
}
for (j = 0; j < CTL_TYPE_WORD; j++) {
ctl->page[i].type[j] = 0x11111111;
}| int i; | ||
| uint32_t start_addr_hi32 = start_addr >> 32; | ||
| uint32_t kernel_entry_hi32 = kernel_entry >> 32; | ||
|
|
||
| /* reset vector */ | ||
| /* a0->lxlcid, a1->fdt_laddr, a2->kernel_entry */ |
There was a problem hiding this comment.
Assigning start_addr and kernel_entry (which are 64-bit hwaddr/uint64_t values) directly to elements of the uint32_t array reset_vec will cause implicit truncation compiler warnings. Cast them to uint32_t explicitly.
(uint32_t)start_addr, /* start: .dword */
start_addr_hi32,
fdt_load_addr, /* fdt_laddr: .dword */
0x00000000,
(uint32_t)kernel_entry, /* kernel_entry: .dword */
kernel_entry_hi32,| #define QEMU_CPU_H | ||
|
|
||
| #include "hw/qdev-core.h" | ||
| #include "hw/core/cpu.h" |
Summary
Testing
git diff --checkNot tested