riscvarchive / riscv-qemu

QEMU with RISC-V (RV64G, RV32G) Emulation Support
385 stars 154 forks source link

Don't generate exceptions for CSR access in gdbstub.c #127

Open michaeljclark opened 6 years ago

michaeljclark commented 6 years ago

Currently the csr_read_helper and csr_write_helper TCG CSR helper function in target/riscv/op_helper.c are the only way to access CSR and they can generate illegal instruction exceptions. i.e. call longjump. We are calling these in gdbstub.c but we really shouldn't be calling functions with this behaviour as a longjmp called outside of a setjump context has undefined behaviour.

The csr_read_helper and csr_write_helper need to be split into front-end wrappers and back-end access functions, with the back-end functions indicating the presence of a CSR (which can be used both for debug access to CSRs and by the front-end helpers used by TCG). This is required because we can't call helpers that may call longjump from the GDB interface in target/riscv/gdbstub.c

Currently CSR read and write is implemented in the helpers that are called directly by TCG:

We need to split the helpers into wrappers and create generic CSR access functions that don't generate exceptions, rather indicate presence via their return code. The helpers will then call the CSR access functions, and generate exceptions based on precense. e.g. a return code of -1 can indicate an illegal access. gdbstub.c can could return -1 or (0xffffffff for RV32 or 0xffffffffffffffff for RV64). In the GDB stub we have no way to indicate whether a CSR register exists as the entire 12-bit range is defined, however we can return -1 as a sentinel. The access functions however can distinguish illegal accesses (return -1) from successful accesses (return 0) for CSRs that are fully present or hardwired to zero.

We could add these two methods, perhaps with interfaces in target/riscv/cpu.h and implementation in target/riscv/csr.c