Skip to content

linx: support clean qemu-user glibc execution#32

Open
touzicongbupianren wants to merge 3 commits into
LinxISA:qemu-my-patch-v7.0.0from
touzicongbupianren:lihan-qemu-user-glibc-pr
Open

linx: support clean qemu-user glibc execution#32
touzicongbupianren wants to merge 3 commits into
LinxISA:qemu-my-patch-v7.0.0from
touzicongbupianren:lihan-qemu-user-glibc-pr

Conversation

@touzicongbupianren

Copy link
Copy Markdown

This PR improves Linx qemu-user execution enough to run a dynamically linked glibc printf program.

Changes:

  • Remove temporary qemu-user TB diagnostics that polluted guest stdout.
  • Align Linx linux-user syscall handling with a7 syscall number and QEMU restart/sigreturn conventions.
  • Add/adjust Linx linux-user headers needed by glibc.
  • Complete several Linx block translation fixes required by dynamic glibc execution.

Validation:

  • Rebuilt qemu-linx with build-user.
  • Ran dynamic Linx glibc printf under qemu-linx.
  • stdout is exactly:
    Hello from Linx glibc printf: value=42 status=ok
  • stderr is empty.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request cleans up debug variables, updates syscall register mappings to xA7, replaces target-specific signal constants with generic QEMU ones, and implements several new instructions including long immediate arithmetic and store pair immediate operations. Additionally, it fixes conditional select operand ordering and adds setret padding detection. Feedback highlights two critical issues: first, regenerating exceptions on -QEMU_ERESTARTSYS in cpu_loop.c without rewinding env->pc can bypass signal handlers and corrupt state; second, speculative read-ahead in has_head_setret_padding can cross page boundaries and trigger spurious page faults, requiring a boundary guard.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +74 to 83
if (ret == -QEMU_ERESTARTSYS) {
/*
* Regenerate the exception so that cpu_exec can exit before
* executing the instruction.
*/
cs->exception_index = LINX_EXCP_SCALL;
} else {
if (ret != -TARGET_QEMU_ESIGRETURN)
if (ret != -QEMU_ESIGRETURN)
env->gpr[xA0] = ret;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

Regenerating the exception on -QEMU_ERESTARTSYS without rewinding env->pc is incorrect and leads to severe bugs. When a signal is pending, cpu_exec will exit immediately and process_pending_signals will set up the signal frame and modify env->pc to point to the signal handler. However, because cs->exception_index is still set to LINX_EXCP_SCALL, the loop will immediately execute case LINX_EXCP_SCALL again, overwriting env->pc with env->next_bpc. This completely bypasses the signal handler and corrupts the execution state.

Instead, we should rewind env->pc to the original syscall instruction (which is 4 bytes before env->next_bpc) and let the normal QEMU signal delivery mechanism handle the restart without regenerating the exception, matching the standard behavior of other QEMU targets like RISC-V.

            if (ret == -QEMU_ERESTARTSYS) {
                env->pc -= 4;
            } else {
                if (ret != -QEMU_ESIGRETURN)
                    env->gpr[xA0] = ret;
            }

Comment thread target/linx/translate.c
Comment on lines +957 to +964
static bool has_head_setret_padding(DisasContext *ctx, int head_size)
{
CPULINXState *env = ctx->cs->env_ptr;
uint16_t pad = cpu_lduw_code(env, ctx->base.pc_next + head_size);
uint32_t next = cpu_ldl_code(env, ctx->base.pc_next + head_size + 2);

return pad == 0xfffe && is_blk_setret_32(next);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Speculative read-ahead using cpu_lduw_code and cpu_ldl_code can cross page boundaries if the current instruction is near the end of a page. If the next page is not mapped or not executable, this will trigger a spurious translation-time page fault (SIGSEGV), causing valid guest programs to crash. We should add a guard to ensure we do not perform the lookahead if it crosses a page boundary.

static bool has_head_setret_padding(DisasContext *ctx, int head_size)
{
    target_ulong pc = ctx->base.pc_next + head_size;
    if ((pc & TARGET_PAGE_MASK) != ((pc + 5) & TARGET_PAGE_MASK)) {
        return false;
    }
    CPULINXState *env = ctx->cs->env_ptr;
    uint16_t pad = cpu_lduw_code(env, pc);
    uint32_t next = cpu_ldl_code(env, pc + 2);

    return pad == 0xfffe && is_blk_setret_32(next);
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant