foss-for-synopsys-dwc-arc-processors / qemu

QEMU port for ARCv2 Processors
Other
12 stars 9 forks source link

ILINK register is accessible from userspace #154

Open kokas-a opened 1 year ago

kokas-a commented 1 year ago

Hi,

ARCv2 documentation contains the following: "The ILINK register is not accessible in user mode. Illegal accesses from user mode to ILINK raise a Privilege Violation exception". But QEMU allows ILINK access form user mode.

Examples are based on Zephyr. The following is executed in userspace:

    uint32_t rd_ilink = 0;

    __asm__ volatile("mov %%[ilink], 0xaaaaaaaa\n"::);

    __asm__ volatile("mov %0, %%[ilink]\n": "=r"(rd_ilink) : );

    printf("Ilink was set in %s to 0x%x but we got no crashes\n",
           k_is_user_context() ? "UserSpace!" : "privileged mode." , rd_ilink);

Expected behavior - raising exception

*** Booting Zephyr OS build v3.3.0-rc3-59-gf1b662ae17b5 ***
Hello World from UserSpace! (nsim)
E: ***** Exception vector: 0x7, cause code: 0x0, parameter 0x0
E: Address 0xe6
E: EV_PrivilegeV
E: Privilege violation
E:  r0: 0x1  r1: 0x2  r2: 0x600  r3: 0x857c
E:  r4: 0x0  r5: 0x0  r6: 0x176  r7: 0x0
E:  r8: 0x0  r9: 0x0 r10: 0x0 r11: 0x0
E: r12: 0x43 r13: 0x0  pc: 0xe6
E:  blink: 0xb6 status32: 0x80182282
E: lp_end: 0x0 lp_start: 0x0 lp_count: 0x0
E: >>> ZEPHYR FATAL ERROR 0: CPU exception on CPU 0
E: Current thread: 0x80000000 (unknown)
E: Halting system

Current behavior - continuing execution

*** Booting Zephyr OS build v3.3.0-rc3-59-gf1b662ae17b5 ***
Hello World from UserSpace! (qemu_arc)
Ilink was set in UserSpace! to 0xaaaaaaaa but we got no crashes

How to reproduce

Download example and run it on recent version of qemu

qemu-system-arc -cpu archs -m 8M -nographic -no-reboot -monitor none -global cpu.firq=false -global cpu.num-irqlevels=15 -global cpu.num-irq=25 -global cpu.ext-irq=20 -global cpu.freq_hz=10000000 -global cpu.timer0=true -global cpu.timer1=true -global cpu.has-mpu=true -global cpu.mpu-numreg=16 -net none -pidfile qemu.pid -chardev stdio,id=con,mux=on -serial chardev:con -mon chardev=con,mode=readline -icount shift=6,align=off,sleep=off -rtc clock=vm -kernel <PATH_TO_ZEPHYR_ELF> 

Routine that contains example code with ILINK access is user_function()

zephyr_user_ilink.zip

shahab-vahedi commented 1 year ago

For what it's worth, auxiliary registers suffer the same. I re-iterate what has been submitted on a now-private repo:

At the moment, in user mode, most auxiliary registers are readable/writable;  while
according to PRM (section 4.2.3.2 Privileged Registers), only these should be accessible:

    PC
    STATS32
    LP_START
    LP_END

I consider this ...

The fix should look like this:

op_helper.c
-----------

target_ulong
arc_status_regs_get(const struct arc_aux_reg_detail *aux_reg_detail,
                    void *data)
{
    ...
    case AUX_ID_erstatus:
        if (is_user_mode(env)) {
            arc_raise_exception(env, GETPC(), EXCP_PRIVILEGEV);
        }
        reg = pack_status32(&env->stat_er);
        break;
    ...
}
shahab-vahedi commented 1 year ago

ilink is a GPR. In case of a GPR, every instructions that uses it, should take care of it. This requires adaptation to the decoder to insert the checking routine in place if one of the operands is ilink. By "checking routine" I mean the tcg code to check against status32.u, and raise an exception if indeed it is set. Something like seti and clri do.