RISC-V Patches for 4.0-rc0, Part 2

This patch set contains three major sources of bug fixes:
 
 * Jim has added support for GDB XML files, as well as fixing access to
   CSRs via the GDB stub.
 * Alistair has rebased a large set of fixes from Michael that were still
   in his patch queue.  These fix bugs all over our tree, including:
     * Logging of PMP errors.
     * User ABI cleanups and fixes, most notably on RVE guests.
     * Fixes for interrupt emulation fidelity.
     * Improvements to the emulation fidelity of the sifive_u machine.
 * Bin Meng has improved the emulation fidelity of the SiFive UART, which
   now supports both TX and RX interrupts (as well as setting the correct
   interrupt line).
 -----BEGIN PGP SIGNATURE-----
 
 iQJHBAABCAAxFiEEAM520YNJYN/OiG3470yhUCzLq0EFAlyQ46MTHHBhbG1lckBk
 YWJiZWx0LmNvbQAKCRDvTKFQLMurQT7CEACDhwOw5Xmp5OBUrZWBUG84nURt8yNG
 WJ4hPfyc765xVJ8FHPlRR5s1mAIF9232LfV/sBnAtlNnl1pRbyckPuOFxLUjPpjK
 DLY83z3zJgVhsTCa7oBGd2WSJG6YQ+uSS/g8MomtVUjU34qZliF0nX5HeLUmj/EY
 2AAge+vYUj7+5aQh5pveRaC4F7aZ4hukowPsDTknUo8EpAR25DTtHIjfxxdo4ONQ
 8gWxGsg/QpaJPyIw4fw5yBn1D49hq8+3VNaBNv+Lajq6BLl/esIIrCawvp90EGUx
 QeIm7Sws1vVaeOIYmrjLjChRveS4xxV7fjScZZ4IlhMqY0yQU7nNfcRkefsS0EoE
 0TKEQxkNMLfJcB7SEL6FtbnPTfzz4nyouA9D4feZaLh6cgRXj77LyoO54kKRxugX
 m1+VOd0VT34VM1QaXIy6fYXod6GdXw5mAnSQsfIAKSk9/0fOzeafMBj5gAZuf7jI
 YWEKwXZOmENXehTXRvVDQh2A4j5tBXP9T2K3iSVktcxjc7/3a4vQAJZMudpYmLSx
 sKYTBSF2bQ379fZUoEU6B+7AwBSf7VT/WqOqf2GC/IJ/dmpxzZY7bq4G9lqodhGl
 zYgVOqAVJHjfEHSXaMICvAb+/mK6EGIw77xvHUZ3RPFWjaTrMHBifogzQMQ5+ZWD
 V3JBczHO9VrviA==
 =365E
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/palmer/tags/riscv-for-master-4.0-rc0-2' into staging

RISC-V Patches for 4.0-rc0, Part 2

This patch set contains three major sources of bug fixes:

* Jim has added support for GDB XML files, as well as fixing access to
  CSRs via the GDB stub.
* Alistair has rebased a large set of fixes from Michael that were still
  in his patch queue.  These fix bugs all over our tree, including:
    * Logging of PMP errors.
    * User ABI cleanups and fixes, most notably on RVE guests.
    * Fixes for interrupt emulation fidelity.
    * Improvements to the emulation fidelity of the sifive_u machine.
* Bin Meng has improved the emulation fidelity of the SiFive UART, which
  now supports both TX and RX interrupts (as well as setting the correct
  interrupt line).

# gpg: Signature made Tue 19 Mar 2019 12:42:11 GMT
# gpg:                using RSA key 00CE76D1834960DFCE886DF8EF4CA1502CCBAB41
# gpg:                issuer "palmer@dabbelt.com"
# gpg: Good signature from "Palmer Dabbelt <palmer@dabbelt.com>" [unknown]
# gpg:                 aka "Palmer Dabbelt <palmer@sifive.com>" [unknown]
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: 00CE 76D1 8349 60DF CE88  6DF8 EF4C A150 2CCB AB41

* remotes/palmer/tags/riscv-for-master-4.0-rc0-2:
  riscv: sifive_u: Correct UART0's IRQ in the device tree
  riscv: sifive_uart: Generate TX interrupt
  target/riscv: Remove unused struct
  riscv: sifive_u: Allow up to 4 CPUs to be created
  RISC-V: Update load reservation comment in do_interrupt
  RISC-V: Convert trap debugging to trace events
  RISC-V: Add support for vectored interrupts
  RISC-V: Change local interrupts from edge to level
  RISC-V: linux-user support for RVE ABI
  elf: Add RISC-V PSABI ELF header defines
  RISC-V: Remove unnecessary disassembler constraints
  RISC-V: Allow interrupt controllers to claim interrupts
  RISC-V: Replace __builtin_popcount with ctpop8 in PLIC
  riscv: pmp: Log pmp access errors as guest errors
  RISC-V: Add hooks to use the gdb xml files.
  RISC-V: Add debug support for accessing CSRs.
  RISC-V: Fixes to CSR_* register macros.
  RISC-V: Add 64-bit gdb xml files.
  RISC-V: Add 32-bit gdb xml files.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2019-03-19 12:55:02 +00:00
commit b98a66201d
23 changed files with 1267 additions and 291 deletions

View File

@ -186,6 +186,7 @@ trace-events-subdirs += target/hppa
trace-events-subdirs += target/i386
trace-events-subdirs += target/mips
trace-events-subdirs += target/ppc
trace-events-subdirs += target/riscv
trace-events-subdirs += target/s390x
trace-events-subdirs += target/sparc
trace-events-subdirs += ui

2
configure vendored
View File

@ -7514,12 +7514,14 @@ case "$target_name" in
TARGET_BASE_ARCH=riscv
TARGET_ABI_DIR=riscv
mttcg=yes
gdb_xml_files="riscv-32bit-cpu.xml riscv-32bit-fpu.xml riscv-32bit-csr.xml"
target_compiler=$cross_cc_riscv32
;;
riscv64)
TARGET_BASE_ARCH=riscv
TARGET_ABI_DIR=riscv
mttcg=yes
gdb_xml_files="riscv-64bit-cpu.xml riscv-64bit-fpu.xml riscv-64bit-csr.xml"
target_compiler=$cross_cc_riscv64
;;
sh4|sh4eb)

View File

@ -87,33 +87,10 @@ typedef enum {
typedef enum {
rvc_end,
rvc_simm_6,
rvc_imm_6,
rvc_imm_7,
rvc_imm_8,
rvc_imm_9,
rvc_imm_10,
rvc_imm_12,
rvc_imm_18,
rvc_imm_nz,
rvc_imm_x2,
rvc_imm_x4,
rvc_imm_x8,
rvc_imm_x16,
rvc_rd_b3,
rvc_rs1_b3,
rvc_rs2_b3,
rvc_rd_eq_rs1,
rvc_rd_eq_ra,
rvc_rd_eq_sp,
rvc_rd_eq_x0,
rvc_rs1_eq_sp,
rvc_rs1_eq_x0,
rvc_rs2_eq_x0,
rvc_rd_ne_x0_x2,
rvc_rd_ne_x0,
rvc_rs1_ne_x0,
rvc_rs2_ne_x0,
rvc_rs2_eq_rs1,
rvc_rs1_eq_ra,
rvc_imm_eq_zero,
@ -2522,111 +2499,16 @@ static bool check_constraints(rv_decode *dec, const rvc_constraint *c)
uint8_t rd = dec->rd, rs1 = dec->rs1, rs2 = dec->rs2;
while (*c != rvc_end) {
switch (*c) {
case rvc_simm_6:
if (!(imm >= -32 && imm < 32)) {
return false;
}
break;
case rvc_imm_6:
if (!(imm <= 63)) {
return false;
}
break;
case rvc_imm_7:
if (!(imm <= 127)) {
return false;
}
break;
case rvc_imm_8:
if (!(imm <= 255)) {
return false;
}
break;
case rvc_imm_9:
if (!(imm <= 511)) {
return false;
}
break;
case rvc_imm_10:
if (!(imm <= 1023)) {
return false;
}
break;
case rvc_imm_12:
if (!(imm <= 4095)) {
return false;
}
break;
case rvc_imm_18:
if (!(imm <= 262143)) {
return false;
}
break;
case rvc_imm_nz:
if (!(imm != 0)) {
return false;
}
break;
case rvc_imm_x2:
if (!((imm & 0b1) == 0)) {
return false;
}
break;
case rvc_imm_x4:
if (!((imm & 0b11) == 0)) {
return false;
}
break;
case rvc_imm_x8:
if (!((imm & 0b111) == 0)) {
return false;
}
break;
case rvc_imm_x16:
if (!((imm & 0b1111) == 0)) {
return false;
}
break;
case rvc_rd_b3:
if (!(rd >= 8 && rd <= 15)) {
return false;
}
break;
case rvc_rs1_b3:
if (!(rs1 >= 8 && rs1 <= 15)) {
return false;
}
break;
case rvc_rs2_b3:
if (!(rs2 >= 8 && rs2 <= 15)) {
return false;
}
break;
case rvc_rd_eq_rs1:
if (!(rd == rs1)) {
return false;
}
break;
case rvc_rd_eq_ra:
if (!(rd == 1)) {
return false;
}
break;
case rvc_rd_eq_sp:
if (!(rd == 2)) {
return false;
}
break;
case rvc_rd_eq_x0:
if (!(rd == 0)) {
return false;
}
break;
case rvc_rs1_eq_sp:
if (!(rs1 == 2)) {
return false;
}
break;
case rvc_rs1_eq_x0:
if (!(rs1 == 0)) {
return false;
@ -2637,26 +2519,6 @@ static bool check_constraints(rv_decode *dec, const rvc_constraint *c)
return false;
}
break;
case rvc_rd_ne_x0_x2:
if (!(rd != 0 && rd != 2)) {
return false;
}
break;
case rvc_rd_ne_x0:
if (!(rd != 0)) {
return false;
}
break;
case rvc_rs1_ne_x0:
if (!(rs1 != 0)) {
return false;
}
break;
case rvc_rs2_ne_x0:
if (!(rs2 != 0)) {
return false;
}
break;
case rvc_rs2_eq_rs1:
if (!(rs2 == rs1)) {
return false;

View File

@ -0,0 +1,47 @@
<?xml version="1.0"?>
<!-- Copyright (C) 2018-2019 Free Software Foundation, Inc.
Copying and distribution of this file, with or without modification,
are permitted in any medium without royalty provided the copyright
notice and this notice are preserved. -->
<!-- Register numbers are hard-coded in order to maintain backward
compatibility with older versions of tools that didn't use xml
register descriptions. -->
<!DOCTYPE feature SYSTEM "gdb-target.dtd">
<feature name="org.gnu.gdb.riscv.cpu">
<reg name="zero" bitsize="32" type="int" regnum="0"/>
<reg name="ra" bitsize="32" type="code_ptr"/>
<reg name="sp" bitsize="32" type="data_ptr"/>
<reg name="gp" bitsize="32" type="data_ptr"/>
<reg name="tp" bitsize="32" type="data_ptr"/>
<reg name="t0" bitsize="32" type="int"/>
<reg name="t1" bitsize="32" type="int"/>
<reg name="t2" bitsize="32" type="int"/>
<reg name="fp" bitsize="32" type="data_ptr"/>
<reg name="s1" bitsize="32" type="int"/>
<reg name="a0" bitsize="32" type="int"/>
<reg name="a1" bitsize="32" type="int"/>
<reg name="a2" bitsize="32" type="int"/>
<reg name="a3" bitsize="32" type="int"/>
<reg name="a4" bitsize="32" type="int"/>
<reg name="a5" bitsize="32" type="int"/>
<reg name="a6" bitsize="32" type="int"/>
<reg name="a7" bitsize="32" type="int"/>
<reg name="s2" bitsize="32" type="int"/>
<reg name="s3" bitsize="32" type="int"/>
<reg name="s4" bitsize="32" type="int"/>
<reg name="s5" bitsize="32" type="int"/>
<reg name="s6" bitsize="32" type="int"/>
<reg name="s7" bitsize="32" type="int"/>
<reg name="s8" bitsize="32" type="int"/>
<reg name="s9" bitsize="32" type="int"/>
<reg name="s10" bitsize="32" type="int"/>
<reg name="s11" bitsize="32" type="int"/>
<reg name="t3" bitsize="32" type="int"/>
<reg name="t4" bitsize="32" type="int"/>
<reg name="t5" bitsize="32" type="int"/>
<reg name="t6" bitsize="32" type="int"/>
<reg name="pc" bitsize="32" type="code_ptr"/>
</feature>

250
gdb-xml/riscv-32bit-csr.xml Normal file
View File

@ -0,0 +1,250 @@
<?xml version="1.0"?>
<!-- Copyright (C) 2018-2019 Free Software Foundation, Inc.
Copying and distribution of this file, with or without modification,
are permitted in any medium without royalty provided the copyright
notice and this notice are preserved. -->
<!DOCTYPE feature SYSTEM "gdb-target.dtd">
<feature name="org.gnu.gdb.riscv.csr">
<reg name="ustatus" bitsize="32"/>
<reg name="uie" bitsize="32"/>
<reg name="utvec" bitsize="32"/>
<reg name="uscratch" bitsize="32"/>
<reg name="uepc" bitsize="32"/>
<reg name="ucause" bitsize="32"/>
<reg name="utval" bitsize="32"/>
<reg name="uip" bitsize="32"/>
<reg name="fflags" bitsize="32"/>
<reg name="frm" bitsize="32"/>
<reg name="fcsr" bitsize="32"/>
<reg name="cycle" bitsize="32"/>
<reg name="time" bitsize="32"/>
<reg name="instret" bitsize="32"/>
<reg name="hpmcounter3" bitsize="32"/>
<reg name="hpmcounter4" bitsize="32"/>
<reg name="hpmcounter5" bitsize="32"/>
<reg name="hpmcounter6" bitsize="32"/>
<reg name="hpmcounter7" bitsize="32"/>
<reg name="hpmcounter8" bitsize="32"/>
<reg name="hpmcounter9" bitsize="32"/>
<reg name="hpmcounter10" bitsize="32"/>
<reg name="hpmcounter11" bitsize="32"/>
<reg name="hpmcounter12" bitsize="32"/>
<reg name="hpmcounter13" bitsize="32"/>
<reg name="hpmcounter14" bitsize="32"/>
<reg name="hpmcounter15" bitsize="32"/>
<reg name="hpmcounter16" bitsize="32"/>
<reg name="hpmcounter17" bitsize="32"/>
<reg name="hpmcounter18" bitsize="32"/>
<reg name="hpmcounter19" bitsize="32"/>
<reg name="hpmcounter20" bitsize="32"/>
<reg name="hpmcounter21" bitsize="32"/>
<reg name="hpmcounter22" bitsize="32"/>
<reg name="hpmcounter23" bitsize="32"/>
<reg name="hpmcounter24" bitsize="32"/>
<reg name="hpmcounter25" bitsize="32"/>
<reg name="hpmcounter26" bitsize="32"/>
<reg name="hpmcounter27" bitsize="32"/>
<reg name="hpmcounter28" bitsize="32"/>
<reg name="hpmcounter29" bitsize="32"/>
<reg name="hpmcounter30" bitsize="32"/>
<reg name="hpmcounter31" bitsize="32"/>
<reg name="cycleh" bitsize="32"/>
<reg name="timeh" bitsize="32"/>
<reg name="instreth" bitsize="32"/>
<reg name="hpmcounter3h" bitsize="32"/>
<reg name="hpmcounter4h" bitsize="32"/>
<reg name="hpmcounter5h" bitsize="32"/>
<reg name="hpmcounter6h" bitsize="32"/>
<reg name="hpmcounter7h" bitsize="32"/>
<reg name="hpmcounter8h" bitsize="32"/>
<reg name="hpmcounter9h" bitsize="32"/>
<reg name="hpmcounter10h" bitsize="32"/>
<reg name="hpmcounter11h" bitsize="32"/>
<reg name="hpmcounter12h" bitsize="32"/>
<reg name="hpmcounter13h" bitsize="32"/>
<reg name="hpmcounter14h" bitsize="32"/>
<reg name="hpmcounter15h" bitsize="32"/>
<reg name="hpmcounter16h" bitsize="32"/>
<reg name="hpmcounter17h" bitsize="32"/>
<reg name="hpmcounter18h" bitsize="32"/>
<reg name="hpmcounter19h" bitsize="32"/>
<reg name="hpmcounter20h" bitsize="32"/>
<reg name="hpmcounter21h" bitsize="32"/>
<reg name="hpmcounter22h" bitsize="32"/>
<reg name="hpmcounter23h" bitsize="32"/>
<reg name="hpmcounter24h" bitsize="32"/>
<reg name="hpmcounter25h" bitsize="32"/>
<reg name="hpmcounter26h" bitsize="32"/>
<reg name="hpmcounter27h" bitsize="32"/>
<reg name="hpmcounter28h" bitsize="32"/>
<reg name="hpmcounter29h" bitsize="32"/>
<reg name="hpmcounter30h" bitsize="32"/>
<reg name="hpmcounter31h" bitsize="32"/>
<reg name="sstatus" bitsize="32"/>
<reg name="sedeleg" bitsize="32"/>
<reg name="sideleg" bitsize="32"/>
<reg name="sie" bitsize="32"/>
<reg name="stvec" bitsize="32"/>
<reg name="scounteren" bitsize="32"/>
<reg name="sscratch" bitsize="32"/>
<reg name="sepc" bitsize="32"/>
<reg name="scause" bitsize="32"/>
<reg name="stval" bitsize="32"/>
<reg name="sip" bitsize="32"/>
<reg name="satp" bitsize="32"/>
<reg name="mvendorid" bitsize="32"/>
<reg name="marchid" bitsize="32"/>
<reg name="mimpid" bitsize="32"/>
<reg name="mhartid" bitsize="32"/>
<reg name="mstatus" bitsize="32"/>
<reg name="misa" bitsize="32"/>
<reg name="medeleg" bitsize="32"/>
<reg name="mideleg" bitsize="32"/>
<reg name="mie" bitsize="32"/>
<reg name="mtvec" bitsize="32"/>
<reg name="mcounteren" bitsize="32"/>
<reg name="mscratch" bitsize="32"/>
<reg name="mepc" bitsize="32"/>
<reg name="mcause" bitsize="32"/>
<reg name="mtval" bitsize="32"/>
<reg name="mip" bitsize="32"/>
<reg name="pmpcfg0" bitsize="32"/>
<reg name="pmpcfg1" bitsize="32"/>
<reg name="pmpcfg2" bitsize="32"/>
<reg name="pmpcfg3" bitsize="32"/>
<reg name="pmpaddr0" bitsize="32"/>
<reg name="pmpaddr1" bitsize="32"/>
<reg name="pmpaddr2" bitsize="32"/>
<reg name="pmpaddr3" bitsize="32"/>
<reg name="pmpaddr4" bitsize="32"/>
<reg name="pmpaddr5" bitsize="32"/>
<reg name="pmpaddr6" bitsize="32"/>
<reg name="pmpaddr7" bitsize="32"/>
<reg name="pmpaddr8" bitsize="32"/>
<reg name="pmpaddr9" bitsize="32"/>
<reg name="pmpaddr10" bitsize="32"/>
<reg name="pmpaddr11" bitsize="32"/>
<reg name="pmpaddr12" bitsize="32"/>
<reg name="pmpaddr13" bitsize="32"/>
<reg name="pmpaddr14" bitsize="32"/>
<reg name="pmpaddr15" bitsize="32"/>
<reg name="mcycle" bitsize="32"/>
<reg name="minstret" bitsize="32"/>
<reg name="mhpmcounter3" bitsize="32"/>
<reg name="mhpmcounter4" bitsize="32"/>
<reg name="mhpmcounter5" bitsize="32"/>
<reg name="mhpmcounter6" bitsize="32"/>
<reg name="mhpmcounter7" bitsize="32"/>
<reg name="mhpmcounter8" bitsize="32"/>
<reg name="mhpmcounter9" bitsize="32"/>
<reg name="mhpmcounter10" bitsize="32"/>
<reg name="mhpmcounter11" bitsize="32"/>
<reg name="mhpmcounter12" bitsize="32"/>
<reg name="mhpmcounter13" bitsize="32"/>
<reg name="mhpmcounter14" bitsize="32"/>
<reg name="mhpmcounter15" bitsize="32"/>
<reg name="mhpmcounter16" bitsize="32"/>
<reg name="mhpmcounter17" bitsize="32"/>
<reg name="mhpmcounter18" bitsize="32"/>
<reg name="mhpmcounter19" bitsize="32"/>
<reg name="mhpmcounter20" bitsize="32"/>
<reg name="mhpmcounter21" bitsize="32"/>
<reg name="mhpmcounter22" bitsize="32"/>
<reg name="mhpmcounter23" bitsize="32"/>
<reg name="mhpmcounter24" bitsize="32"/>
<reg name="mhpmcounter25" bitsize="32"/>
<reg name="mhpmcounter26" bitsize="32"/>
<reg name="mhpmcounter27" bitsize="32"/>
<reg name="mhpmcounter28" bitsize="32"/>
<reg name="mhpmcounter29" bitsize="32"/>
<reg name="mhpmcounter30" bitsize="32"/>
<reg name="mhpmcounter31" bitsize="32"/>
<reg name="mcycleh" bitsize="32"/>
<reg name="minstreth" bitsize="32"/>
<reg name="mhpmcounter3h" bitsize="32"/>
<reg name="mhpmcounter4h" bitsize="32"/>
<reg name="mhpmcounter5h" bitsize="32"/>
<reg name="mhpmcounter6h" bitsize="32"/>
<reg name="mhpmcounter7h" bitsize="32"/>
<reg name="mhpmcounter8h" bitsize="32"/>
<reg name="mhpmcounter9h" bitsize="32"/>
<reg name="mhpmcounter10h" bitsize="32"/>
<reg name="mhpmcounter11h" bitsize="32"/>
<reg name="mhpmcounter12h" bitsize="32"/>
<reg name="mhpmcounter13h" bitsize="32"/>
<reg name="mhpmcounter14h" bitsize="32"/>
<reg name="mhpmcounter15h" bitsize="32"/>
<reg name="mhpmcounter16h" bitsize="32"/>
<reg name="mhpmcounter17h" bitsize="32"/>
<reg name="mhpmcounter18h" bitsize="32"/>
<reg name="mhpmcounter19h" bitsize="32"/>
<reg name="mhpmcounter20h" bitsize="32"/>
<reg name="mhpmcounter21h" bitsize="32"/>
<reg name="mhpmcounter22h" bitsize="32"/>
<reg name="mhpmcounter23h" bitsize="32"/>
<reg name="mhpmcounter24h" bitsize="32"/>
<reg name="mhpmcounter25h" bitsize="32"/>
<reg name="mhpmcounter26h" bitsize="32"/>
<reg name="mhpmcounter27h" bitsize="32"/>
<reg name="mhpmcounter28h" bitsize="32"/>
<reg name="mhpmcounter29h" bitsize="32"/>
<reg name="mhpmcounter30h" bitsize="32"/>
<reg name="mhpmcounter31h" bitsize="32"/>
<reg name="mhpmevent3" bitsize="32"/>
<reg name="mhpmevent4" bitsize="32"/>
<reg name="mhpmevent5" bitsize="32"/>
<reg name="mhpmevent6" bitsize="32"/>
<reg name="mhpmevent7" bitsize="32"/>
<reg name="mhpmevent8" bitsize="32"/>
<reg name="mhpmevent9" bitsize="32"/>
<reg name="mhpmevent10" bitsize="32"/>
<reg name="mhpmevent11" bitsize="32"/>
<reg name="mhpmevent12" bitsize="32"/>
<reg name="mhpmevent13" bitsize="32"/>
<reg name="mhpmevent14" bitsize="32"/>
<reg name="mhpmevent15" bitsize="32"/>
<reg name="mhpmevent16" bitsize="32"/>
<reg name="mhpmevent17" bitsize="32"/>
<reg name="mhpmevent18" bitsize="32"/>
<reg name="mhpmevent19" bitsize="32"/>
<reg name="mhpmevent20" bitsize="32"/>
<reg name="mhpmevent21" bitsize="32"/>
<reg name="mhpmevent22" bitsize="32"/>
<reg name="mhpmevent23" bitsize="32"/>
<reg name="mhpmevent24" bitsize="32"/>
<reg name="mhpmevent25" bitsize="32"/>
<reg name="mhpmevent26" bitsize="32"/>
<reg name="mhpmevent27" bitsize="32"/>
<reg name="mhpmevent28" bitsize="32"/>
<reg name="mhpmevent29" bitsize="32"/>
<reg name="mhpmevent30" bitsize="32"/>
<reg name="mhpmevent31" bitsize="32"/>
<reg name="tselect" bitsize="32"/>
<reg name="tdata1" bitsize="32"/>
<reg name="tdata2" bitsize="32"/>
<reg name="tdata3" bitsize="32"/>
<reg name="dcsr" bitsize="32"/>
<reg name="dpc" bitsize="32"/>
<reg name="dscratch" bitsize="32"/>
<reg name="hstatus" bitsize="32"/>
<reg name="hedeleg" bitsize="32"/>
<reg name="hideleg" bitsize="32"/>
<reg name="hie" bitsize="32"/>
<reg name="htvec" bitsize="32"/>
<reg name="hscratch" bitsize="32"/>
<reg name="hepc" bitsize="32"/>
<reg name="hcause" bitsize="32"/>
<reg name="hbadaddr" bitsize="32"/>
<reg name="hip" bitsize="32"/>
<reg name="mbase" bitsize="32"/>
<reg name="mbound" bitsize="32"/>
<reg name="mibase" bitsize="32"/>
<reg name="mibound" bitsize="32"/>
<reg name="mdbase" bitsize="32"/>
<reg name="mdbound" bitsize="32"/>
<reg name="mucounteren" bitsize="32"/>
<reg name="mscounteren" bitsize="32"/>
<reg name="mhcounteren" bitsize="32"/>
</feature>

View File

@ -0,0 +1,50 @@
<?xml version="1.0"?>
<!-- Copyright (C) 2018-2019 Free Software Foundation, Inc.
Copying and distribution of this file, with or without modification,
are permitted in any medium without royalty provided the copyright
notice and this notice are preserved. -->
<!-- Register numbers are hard-coded in order to maintain backward
compatibility with older versions of tools that didn't use xml
register descriptions. -->
<!DOCTYPE feature SYSTEM "gdb-target.dtd">
<feature name="org.gnu.gdb.riscv.fpu">
<reg name="ft0" bitsize="32" type="ieee_single" regnum="33"/>
<reg name="ft1" bitsize="32" type="ieee_single"/>
<reg name="ft2" bitsize="32" type="ieee_single"/>
<reg name="ft3" bitsize="32" type="ieee_single"/>
<reg name="ft4" bitsize="32" type="ieee_single"/>
<reg name="ft5" bitsize="32" type="ieee_single"/>
<reg name="ft6" bitsize="32" type="ieee_single"/>
<reg name="ft7" bitsize="32" type="ieee_single"/>
<reg name="fs0" bitsize="32" type="ieee_single"/>
<reg name="fs1" bitsize="32" type="ieee_single"/>
<reg name="fa0" bitsize="32" type="ieee_single"/>
<reg name="fa1" bitsize="32" type="ieee_single"/>
<reg name="fa2" bitsize="32" type="ieee_single"/>
<reg name="fa3" bitsize="32" type="ieee_single"/>
<reg name="fa4" bitsize="32" type="ieee_single"/>
<reg name="fa5" bitsize="32" type="ieee_single"/>
<reg name="fa6" bitsize="32" type="ieee_single"/>
<reg name="fa7" bitsize="32" type="ieee_single"/>
<reg name="fs2" bitsize="32" type="ieee_single"/>
<reg name="fs3" bitsize="32" type="ieee_single"/>
<reg name="fs4" bitsize="32" type="ieee_single"/>
<reg name="fs5" bitsize="32" type="ieee_single"/>
<reg name="fs6" bitsize="32" type="ieee_single"/>
<reg name="fs7" bitsize="32" type="ieee_single"/>
<reg name="fs8" bitsize="32" type="ieee_single"/>
<reg name="fs9" bitsize="32" type="ieee_single"/>
<reg name="fs10" bitsize="32" type="ieee_single"/>
<reg name="fs11" bitsize="32" type="ieee_single"/>
<reg name="ft8" bitsize="32" type="ieee_single"/>
<reg name="ft9" bitsize="32" type="ieee_single"/>
<reg name="ft10" bitsize="32" type="ieee_single"/>
<reg name="ft11" bitsize="32" type="ieee_single"/>
<reg name="fflags" bitsize="32" type="int" regnum="66"/>
<reg name="frm" bitsize="32" type="int" regnum="67"/>
<reg name="fcsr" bitsize="32" type="int" regnum="68"/>
</feature>

View File

@ -0,0 +1,47 @@
<?xml version="1.0"?>
<!-- Copyright (C) 2018-2019 Free Software Foundation, Inc.
Copying and distribution of this file, with or without modification,
are permitted in any medium without royalty provided the copyright
notice and this notice are preserved. -->
<!-- Register numbers are hard-coded in order to maintain backward
compatibility with older versions of tools that didn't use xml
register descriptions. -->
<!DOCTYPE feature SYSTEM "gdb-target.dtd">
<feature name="org.gnu.gdb.riscv.cpu">
<reg name="zero" bitsize="64" type="int" regnum="0"/>
<reg name="ra" bitsize="64" type="code_ptr"/>
<reg name="sp" bitsize="64" type="data_ptr"/>
<reg name="gp" bitsize="64" type="data_ptr"/>
<reg name="tp" bitsize="64" type="data_ptr"/>
<reg name="t0" bitsize="64" type="int"/>
<reg name="t1" bitsize="64" type="int"/>
<reg name="t2" bitsize="64" type="int"/>
<reg name="fp" bitsize="64" type="data_ptr"/>
<reg name="s1" bitsize="64" type="int"/>
<reg name="a0" bitsize="64" type="int"/>
<reg name="a1" bitsize="64" type="int"/>
<reg name="a2" bitsize="64" type="int"/>
<reg name="a3" bitsize="64" type="int"/>
<reg name="a4" bitsize="64" type="int"/>
<reg name="a5" bitsize="64" type="int"/>
<reg name="a6" bitsize="64" type="int"/>
<reg name="a7" bitsize="64" type="int"/>
<reg name="s2" bitsize="64" type="int"/>
<reg name="s3" bitsize="64" type="int"/>
<reg name="s4" bitsize="64" type="int"/>
<reg name="s5" bitsize="64" type="int"/>
<reg name="s6" bitsize="64" type="int"/>
<reg name="s7" bitsize="64" type="int"/>
<reg name="s8" bitsize="64" type="int"/>
<reg name="s9" bitsize="64" type="int"/>
<reg name="s10" bitsize="64" type="int"/>
<reg name="s11" bitsize="64" type="int"/>
<reg name="t3" bitsize="64" type="int"/>
<reg name="t4" bitsize="64" type="int"/>
<reg name="t5" bitsize="64" type="int"/>
<reg name="t6" bitsize="64" type="int"/>
<reg name="pc" bitsize="64" type="code_ptr"/>
</feature>

250
gdb-xml/riscv-64bit-csr.xml Normal file
View File

@ -0,0 +1,250 @@
<?xml version="1.0"?>
<!-- Copyright (C) 2018-2019 Free Software Foundation, Inc.
Copying and distribution of this file, with or without modification,
are permitted in any medium without royalty provided the copyright
notice and this notice are preserved. -->
<!DOCTYPE feature SYSTEM "gdb-target.dtd">
<feature name="org.gnu.gdb.riscv.csr">
<reg name="ustatus" bitsize="64"/>
<reg name="uie" bitsize="64"/>
<reg name="utvec" bitsize="64"/>
<reg name="uscratch" bitsize="64"/>
<reg name="uepc" bitsize="64"/>
<reg name="ucause" bitsize="64"/>
<reg name="utval" bitsize="64"/>
<reg name="uip" bitsize="64"/>
<reg name="fflags" bitsize="64"/>
<reg name="frm" bitsize="64"/>
<reg name="fcsr" bitsize="64"/>
<reg name="cycle" bitsize="64"/>
<reg name="time" bitsize="64"/>
<reg name="instret" bitsize="64"/>
<reg name="hpmcounter3" bitsize="64"/>
<reg name="hpmcounter4" bitsize="64"/>
<reg name="hpmcounter5" bitsize="64"/>
<reg name="hpmcounter6" bitsize="64"/>
<reg name="hpmcounter7" bitsize="64"/>
<reg name="hpmcounter8" bitsize="64"/>
<reg name="hpmcounter9" bitsize="64"/>
<reg name="hpmcounter10" bitsize="64"/>
<reg name="hpmcounter11" bitsize="64"/>
<reg name="hpmcounter12" bitsize="64"/>
<reg name="hpmcounter13" bitsize="64"/>
<reg name="hpmcounter14" bitsize="64"/>
<reg name="hpmcounter15" bitsize="64"/>
<reg name="hpmcounter16" bitsize="64"/>
<reg name="hpmcounter17" bitsize="64"/>
<reg name="hpmcounter18" bitsize="64"/>
<reg name="hpmcounter19" bitsize="64"/>
<reg name="hpmcounter20" bitsize="64"/>
<reg name="hpmcounter21" bitsize="64"/>
<reg name="hpmcounter22" bitsize="64"/>
<reg name="hpmcounter23" bitsize="64"/>
<reg name="hpmcounter24" bitsize="64"/>
<reg name="hpmcounter25" bitsize="64"/>
<reg name="hpmcounter26" bitsize="64"/>
<reg name="hpmcounter27" bitsize="64"/>
<reg name="hpmcounter28" bitsize="64"/>
<reg name="hpmcounter29" bitsize="64"/>
<reg name="hpmcounter30" bitsize="64"/>
<reg name="hpmcounter31" bitsize="64"/>
<reg name="cycleh" bitsize="64"/>
<reg name="timeh" bitsize="64"/>
<reg name="instreth" bitsize="64"/>
<reg name="hpmcounter3h" bitsize="64"/>
<reg name="hpmcounter4h" bitsize="64"/>
<reg name="hpmcounter5h" bitsize="64"/>
<reg name="hpmcounter6h" bitsize="64"/>
<reg name="hpmcounter7h" bitsize="64"/>
<reg name="hpmcounter8h" bitsize="64"/>
<reg name="hpmcounter9h" bitsize="64"/>
<reg name="hpmcounter10h" bitsize="64"/>
<reg name="hpmcounter11h" bitsize="64"/>
<reg name="hpmcounter12h" bitsize="64"/>
<reg name="hpmcounter13h" bitsize="64"/>
<reg name="hpmcounter14h" bitsize="64"/>
<reg name="hpmcounter15h" bitsize="64"/>
<reg name="hpmcounter16h" bitsize="64"/>
<reg name="hpmcounter17h" bitsize="64"/>
<reg name="hpmcounter18h" bitsize="64"/>
<reg name="hpmcounter19h" bitsize="64"/>
<reg name="hpmcounter20h" bitsize="64"/>
<reg name="hpmcounter21h" bitsize="64"/>
<reg name="hpmcounter22h" bitsize="64"/>
<reg name="hpmcounter23h" bitsize="64"/>
<reg name="hpmcounter24h" bitsize="64"/>
<reg name="hpmcounter25h" bitsize="64"/>
<reg name="hpmcounter26h" bitsize="64"/>
<reg name="hpmcounter27h" bitsize="64"/>
<reg name="hpmcounter28h" bitsize="64"/>
<reg name="hpmcounter29h" bitsize="64"/>
<reg name="hpmcounter30h" bitsize="64"/>
<reg name="hpmcounter31h" bitsize="64"/>
<reg name="sstatus" bitsize="64"/>
<reg name="sedeleg" bitsize="64"/>
<reg name="sideleg" bitsize="64"/>
<reg name="sie" bitsize="64"/>
<reg name="stvec" bitsize="64"/>
<reg name="scounteren" bitsize="64"/>
<reg name="sscratch" bitsize="64"/>
<reg name="sepc" bitsize="64"/>
<reg name="scause" bitsize="64"/>
<reg name="stval" bitsize="64"/>
<reg name="sip" bitsize="64"/>
<reg name="satp" bitsize="64"/>
<reg name="mvendorid" bitsize="64"/>
<reg name="marchid" bitsize="64"/>
<reg name="mimpid" bitsize="64"/>
<reg name="mhartid" bitsize="64"/>
<reg name="mstatus" bitsize="64"/>
<reg name="misa" bitsize="64"/>
<reg name="medeleg" bitsize="64"/>
<reg name="mideleg" bitsize="64"/>
<reg name="mie" bitsize="64"/>
<reg name="mtvec" bitsize="64"/>
<reg name="mcounteren" bitsize="64"/>
<reg name="mscratch" bitsize="64"/>
<reg name="mepc" bitsize="64"/>
<reg name="mcause" bitsize="64"/>
<reg name="mtval" bitsize="64"/>
<reg name="mip" bitsize="64"/>
<reg name="pmpcfg0" bitsize="64"/>
<reg name="pmpcfg1" bitsize="64"/>
<reg name="pmpcfg2" bitsize="64"/>
<reg name="pmpcfg3" bitsize="64"/>
<reg name="pmpaddr0" bitsize="64"/>
<reg name="pmpaddr1" bitsize="64"/>
<reg name="pmpaddr2" bitsize="64"/>
<reg name="pmpaddr3" bitsize="64"/>
<reg name="pmpaddr4" bitsize="64"/>
<reg name="pmpaddr5" bitsize="64"/>
<reg name="pmpaddr6" bitsize="64"/>
<reg name="pmpaddr7" bitsize="64"/>
<reg name="pmpaddr8" bitsize="64"/>
<reg name="pmpaddr9" bitsize="64"/>
<reg name="pmpaddr10" bitsize="64"/>
<reg name="pmpaddr11" bitsize="64"/>
<reg name="pmpaddr12" bitsize="64"/>
<reg name="pmpaddr13" bitsize="64"/>
<reg name="pmpaddr14" bitsize="64"/>
<reg name="pmpaddr15" bitsize="64"/>
<reg name="mcycle" bitsize="64"/>
<reg name="minstret" bitsize="64"/>
<reg name="mhpmcounter3" bitsize="64"/>
<reg name="mhpmcounter4" bitsize="64"/>
<reg name="mhpmcounter5" bitsize="64"/>
<reg name="mhpmcounter6" bitsize="64"/>
<reg name="mhpmcounter7" bitsize="64"/>
<reg name="mhpmcounter8" bitsize="64"/>
<reg name="mhpmcounter9" bitsize="64"/>
<reg name="mhpmcounter10" bitsize="64"/>
<reg name="mhpmcounter11" bitsize="64"/>
<reg name="mhpmcounter12" bitsize="64"/>
<reg name="mhpmcounter13" bitsize="64"/>
<reg name="mhpmcounter14" bitsize="64"/>
<reg name="mhpmcounter15" bitsize="64"/>
<reg name="mhpmcounter16" bitsize="64"/>
<reg name="mhpmcounter17" bitsize="64"/>
<reg name="mhpmcounter18" bitsize="64"/>
<reg name="mhpmcounter19" bitsize="64"/>
<reg name="mhpmcounter20" bitsize="64"/>
<reg name="mhpmcounter21" bitsize="64"/>
<reg name="mhpmcounter22" bitsize="64"/>
<reg name="mhpmcounter23" bitsize="64"/>
<reg name="mhpmcounter24" bitsize="64"/>
<reg name="mhpmcounter25" bitsize="64"/>
<reg name="mhpmcounter26" bitsize="64"/>
<reg name="mhpmcounter27" bitsize="64"/>
<reg name="mhpmcounter28" bitsize="64"/>
<reg name="mhpmcounter29" bitsize="64"/>
<reg name="mhpmcounter30" bitsize="64"/>
<reg name="mhpmcounter31" bitsize="64"/>
<reg name="mcycleh" bitsize="64"/>
<reg name="minstreth" bitsize="64"/>
<reg name="mhpmcounter3h" bitsize="64"/>
<reg name="mhpmcounter4h" bitsize="64"/>
<reg name="mhpmcounter5h" bitsize="64"/>
<reg name="mhpmcounter6h" bitsize="64"/>
<reg name="mhpmcounter7h" bitsize="64"/>
<reg name="mhpmcounter8h" bitsize="64"/>
<reg name="mhpmcounter9h" bitsize="64"/>
<reg name="mhpmcounter10h" bitsize="64"/>
<reg name="mhpmcounter11h" bitsize="64"/>
<reg name="mhpmcounter12h" bitsize="64"/>
<reg name="mhpmcounter13h" bitsize="64"/>
<reg name="mhpmcounter14h" bitsize="64"/>
<reg name="mhpmcounter15h" bitsize="64"/>
<reg name="mhpmcounter16h" bitsize="64"/>
<reg name="mhpmcounter17h" bitsize="64"/>
<reg name="mhpmcounter18h" bitsize="64"/>
<reg name="mhpmcounter19h" bitsize="64"/>
<reg name="mhpmcounter20h" bitsize="64"/>
<reg name="mhpmcounter21h" bitsize="64"/>
<reg name="mhpmcounter22h" bitsize="64"/>
<reg name="mhpmcounter23h" bitsize="64"/>
<reg name="mhpmcounter24h" bitsize="64"/>
<reg name="mhpmcounter25h" bitsize="64"/>
<reg name="mhpmcounter26h" bitsize="64"/>
<reg name="mhpmcounter27h" bitsize="64"/>
<reg name="mhpmcounter28h" bitsize="64"/>
<reg name="mhpmcounter29h" bitsize="64"/>
<reg name="mhpmcounter30h" bitsize="64"/>
<reg name="mhpmcounter31h" bitsize="64"/>
<reg name="mhpmevent3" bitsize="64"/>
<reg name="mhpmevent4" bitsize="64"/>
<reg name="mhpmevent5" bitsize="64"/>
<reg name="mhpmevent6" bitsize="64"/>
<reg name="mhpmevent7" bitsize="64"/>
<reg name="mhpmevent8" bitsize="64"/>
<reg name="mhpmevent9" bitsize="64"/>
<reg name="mhpmevent10" bitsize="64"/>
<reg name="mhpmevent11" bitsize="64"/>
<reg name="mhpmevent12" bitsize="64"/>
<reg name="mhpmevent13" bitsize="64"/>
<reg name="mhpmevent14" bitsize="64"/>
<reg name="mhpmevent15" bitsize="64"/>
<reg name="mhpmevent16" bitsize="64"/>
<reg name="mhpmevent17" bitsize="64"/>
<reg name="mhpmevent18" bitsize="64"/>
<reg name="mhpmevent19" bitsize="64"/>
<reg name="mhpmevent20" bitsize="64"/>
<reg name="mhpmevent21" bitsize="64"/>
<reg name="mhpmevent22" bitsize="64"/>
<reg name="mhpmevent23" bitsize="64"/>
<reg name="mhpmevent24" bitsize="64"/>
<reg name="mhpmevent25" bitsize="64"/>
<reg name="mhpmevent26" bitsize="64"/>
<reg name="mhpmevent27" bitsize="64"/>
<reg name="mhpmevent28" bitsize="64"/>
<reg name="mhpmevent29" bitsize="64"/>
<reg name="mhpmevent30" bitsize="64"/>
<reg name="mhpmevent31" bitsize="64"/>
<reg name="tselect" bitsize="64"/>
<reg name="tdata1" bitsize="64"/>
<reg name="tdata2" bitsize="64"/>
<reg name="tdata3" bitsize="64"/>
<reg name="dcsr" bitsize="64"/>
<reg name="dpc" bitsize="64"/>
<reg name="dscratch" bitsize="64"/>
<reg name="hstatus" bitsize="64"/>
<reg name="hedeleg" bitsize="64"/>
<reg name="hideleg" bitsize="64"/>
<reg name="hie" bitsize="64"/>
<reg name="htvec" bitsize="64"/>
<reg name="hscratch" bitsize="64"/>
<reg name="hepc" bitsize="64"/>
<reg name="hcause" bitsize="64"/>
<reg name="hbadaddr" bitsize="64"/>
<reg name="hip" bitsize="64"/>
<reg name="mbase" bitsize="64"/>
<reg name="mbound" bitsize="64"/>
<reg name="mibase" bitsize="64"/>
<reg name="mibound" bitsize="64"/>
<reg name="mdbase" bitsize="64"/>
<reg name="mdbound" bitsize="64"/>
<reg name="mucounteren" bitsize="64"/>
<reg name="mscounteren" bitsize="64"/>
<reg name="mhcounteren" bitsize="64"/>
</feature>

View File

@ -0,0 +1,56 @@
<?xml version="1.0"?>
<!-- Copyright (C) 2018-2019 Free Software Foundation, Inc.
Copying and distribution of this file, with or without modification,
are permitted in any medium without royalty provided the copyright
notice and this notice are preserved. -->
<!-- Register numbers are hard-coded in order to maintain backward
compatibility with older versions of tools that didn't use xml
register descriptions. -->
<!DOCTYPE feature SYSTEM "gdb-target.dtd">
<feature name="org.gnu.gdb.riscv.fpu">
<union id="riscv_double">
<field name="float" type="ieee_single"/>
<field name="double" type="ieee_double"/>
</union>
<reg name="ft0" bitsize="64" type="riscv_double" regnum="33"/>
<reg name="ft1" bitsize="64" type="riscv_double"/>
<reg name="ft2" bitsize="64" type="riscv_double"/>
<reg name="ft3" bitsize="64" type="riscv_double"/>
<reg name="ft4" bitsize="64" type="riscv_double"/>
<reg name="ft5" bitsize="64" type="riscv_double"/>
<reg name="ft6" bitsize="64" type="riscv_double"/>
<reg name="ft7" bitsize="64" type="riscv_double"/>
<reg name="fs0" bitsize="64" type="riscv_double"/>
<reg name="fs1" bitsize="64" type="riscv_double"/>
<reg name="fa0" bitsize="64" type="riscv_double"/>
<reg name="fa1" bitsize="64" type="riscv_double"/>
<reg name="fa2" bitsize="64" type="riscv_double"/>
<reg name="fa3" bitsize="64" type="riscv_double"/>
<reg name="fa4" bitsize="64" type="riscv_double"/>
<reg name="fa5" bitsize="64" type="riscv_double"/>
<reg name="fa6" bitsize="64" type="riscv_double"/>
<reg name="fa7" bitsize="64" type="riscv_double"/>
<reg name="fs2" bitsize="64" type="riscv_double"/>
<reg name="fs3" bitsize="64" type="riscv_double"/>
<reg name="fs4" bitsize="64" type="riscv_double"/>
<reg name="fs5" bitsize="64" type="riscv_double"/>
<reg name="fs6" bitsize="64" type="riscv_double"/>
<reg name="fs7" bitsize="64" type="riscv_double"/>
<reg name="fs8" bitsize="64" type="riscv_double"/>
<reg name="fs9" bitsize="64" type="riscv_double"/>
<reg name="fs10" bitsize="64" type="riscv_double"/>
<reg name="fs11" bitsize="64" type="riscv_double"/>
<reg name="ft8" bitsize="64" type="riscv_double"/>
<reg name="ft9" bitsize="64" type="riscv_double"/>
<reg name="ft10" bitsize="64" type="riscv_double"/>
<reg name="ft11" bitsize="64" type="riscv_double"/>
<reg name="fflags" bitsize="32" type="int" regnum="66"/>
<reg name="frm" bitsize="32" type="int" regnum="67"/>
<reg name="fcsr" bitsize="32" type="int" regnum="68"/>
</feature>

View File

@ -23,6 +23,7 @@
#include "qemu/error-report.h"
#include "hw/sysbus.h"
#include "target/riscv/cpu.h"
#include "sysemu/sysemu.h"
#include "hw/riscv/sifive_plic.h"
#define RISCV_DEBUG_PLIC 0
@ -383,7 +384,7 @@ static void parse_hart_config(SiFivePLICState *plic)
p = plic->hart_config;
while ((c = *p++)) {
if (c == ',') {
addrid += __builtin_popcount(modes);
addrid += ctpop8(modes);
modes = 0;
hartid++;
} else {
@ -397,7 +398,7 @@ static void parse_hart_config(SiFivePLICState *plic)
}
}
if (modes) {
addrid += __builtin_popcount(modes);
addrid += ctpop8(modes);
}
hartid++;
@ -431,6 +432,7 @@ static void sifive_plic_irq_request(void *opaque, int irq, int level)
static void sifive_plic_realize(DeviceState *dev, Error **errp)
{
SiFivePLICState *plic = SIFIVE_PLIC(dev);
int i;
memory_region_init_io(&plic->mmio, OBJECT(dev), &sifive_plic_ops, plic,
TYPE_SIFIVE_PLIC, plic->aperture_size);
@ -443,6 +445,19 @@ static void sifive_plic_realize(DeviceState *dev, Error **errp)
plic->enable = g_new0(uint32_t, plic->bitfield_words * plic->num_addrs);
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &plic->mmio);
qdev_init_gpio_in(dev, sifive_plic_irq_request, plic->num_sources);
/* We can't allow the supervisor to control SEIP as this would allow the
* supervisor to clear a pending external interrupt which will result in
* lost a interrupt in the case a PLIC is attached. The SEIP bit must be
* hardware controlled when a PLIC is attached.
*/
for (i = 0; i < smp_cpus; i++) {
RISCVCPU *cpu = RISCV_CPU(qemu_get_cpu(i));
if (riscv_cpu_claim_interrupts(cpu, MIP_SEIP) < 0) {
error_report("SEIP already claimed");
exit(1);
}
}
}
static void sifive_plic_class_init(ObjectClass *klass, void *data)

View File

@ -244,7 +244,7 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap,
qemu_fdt_setprop_cell(fdt, nodename, "clock-frequency",
SIFIVE_U_CLOCK_FREQ / 2);
qemu_fdt_setprop_cells(fdt, nodename, "interrupt-parent", plic_phandle);
qemu_fdt_setprop_cells(fdt, nodename, "interrupts", 1);
qemu_fdt_setprop_cells(fdt, nodename, "interrupts", SIFIVE_U_UART0_IRQ);
qemu_fdt_add_subnode(fdt, "/chosen");
qemu_fdt_setprop_string(fdt, "/chosen", "stdout-path", nodename);
@ -398,7 +398,10 @@ static void riscv_sifive_u_machine_init(MachineClass *mc)
{
mc->desc = "RISC-V Board compatible with SiFive U SDK";
mc->init = riscv_sifive_u_init;
mc->max_cpus = 1;
/* The real hardware has 5 CPUs, but one of them is a small embedded power
* management CPU.
*/
mc->max_cpus = 4;
}
DEFINE_MACHINE("sifive_u", riscv_sifive_u_machine_init)

View File

@ -51,7 +51,8 @@ static uint64_t uart_ip(SiFiveUARTState *s)
static void update_irq(SiFiveUARTState *s)
{
int cond = 0;
if ((s->ie & SIFIVE_UART_IE_RXWM) && s->rx_fifo_len) {
if ((s->ie & SIFIVE_UART_IE_TXWM) ||
((s->ie & SIFIVE_UART_IE_RXWM) && s->rx_fifo_len)) {
cond = 1;
}
if (cond) {
@ -108,6 +109,7 @@ uart_write(void *opaque, hwaddr addr,
switch (addr) {
case SIFIVE_UART_TXFIFO:
qemu_chr_fe_write(&s->chr, &ch, 1);
update_irq(s);
return;
case SIFIVE_UART_IE:
s->ie = val64;

View File

@ -1393,6 +1393,16 @@ typedef struct {
#define R_RISCV_SET16 55
#define R_RISCV_SET32 56
/* RISC-V ELF Flags. */
#define EF_RISCV_RVC 0x0001
#define EF_RISCV_FLOAT_ABI 0x0006
#define EF_RISCV_FLOAT_ABI_SOFT 0x0000
#define EF_RISCV_FLOAT_ABI_SINGLE 0x0002
#define EF_RISCV_FLOAT_ABI_DOUBLE 0x0004
#define EF_RISCV_FLOAT_ABI_QUAD 0x0006
#define EF_RISCV_RVE 0x0008
#define EF_RISCV_TSO 0x0010
typedef struct elf32_rel {
Elf32_Addr r_offset;
Elf32_Word r_info;

View File

@ -18,8 +18,10 @@
*/
#include "qemu/osdep.h"
#include "qemu/error-report.h"
#include "qemu.h"
#include "cpu_loop-common.h"
#include "elf.h"
void cpu_loop(CPURISCVState *env)
{
@ -53,7 +55,8 @@ void cpu_loop(CPURISCVState *env)
ret = 0;
} else {
ret = do_syscall(env,
env->gpr[xA7],
env->gpr[(env->elf_flags & EF_RISCV_RVE)
? xT0 : xA7],
env->gpr[xA0],
env->gpr[xA1],
env->gpr[xA2],
@ -113,6 +116,16 @@ void cpu_loop(CPURISCVState *env)
void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs)
{
CPUState *cpu = ENV_GET_CPU(env);
TaskState *ts = cpu->opaque;
struct image_info *info = ts->info;
env->pc = regs->sepc;
env->gpr[xSP] = regs->sp;
env->elf_flags = info->elf_flags;
if ((env->misa & RVE) && !(env->elf_flags & EF_RISCV_RVE)) {
error_report("Incompatible ELF: RVE cpu requires RVE ABI binary");
exit(EXIT_FAILURE);
}
}

View File

@ -80,12 +80,6 @@ const char * const riscv_intr_names[] = {
"reserved"
};
typedef struct RISCVCPUInfo {
const int bit_widths;
const char *name;
void (*initfn)(Object *obj);
} RISCVCPUInfo;
static void set_misa(CPURISCVState *env, target_ulong misa)
{
env->misa_mask = env->misa = misa;
@ -311,6 +305,8 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
return;
}
riscv_cpu_register_gdb_regs_for_features(cs);
qemu_init_vcpu(cs);
cpu_reset(cs);
@ -351,7 +347,12 @@ static void riscv_cpu_class_init(ObjectClass *c, void *data)
cc->synchronize_from_tb = riscv_cpu_synchronize_from_tb;
cc->gdb_read_register = riscv_cpu_gdb_read_register;
cc->gdb_write_register = riscv_cpu_gdb_write_register;
cc->gdb_num_core_regs = 65;
cc->gdb_num_core_regs = 33;
#if defined(TARGET_RISCV32)
cc->gdb_core_xml_file = "riscv-32bit-cpu.xml";
#elif defined(TARGET_RISCV64)
cc->gdb_core_xml_file = "riscv-64bit-cpu.xml";
#endif
cc->gdb_stop_before_watchpoint = true;
cc->disas_set_info = riscv_cpu_disas_set_info;
#ifdef CONFIG_USER_ONLY

View File

@ -123,6 +123,10 @@ struct CPURISCVState {
uint32_t features;
#ifdef CONFIG_USER_ONLY
uint32_t elf_flags;
#endif
#ifndef CONFIG_USER_ONLY
target_ulong priv;
target_ulong resetvec;
@ -140,6 +144,7 @@ struct CPURISCVState {
* mip is 32-bits to allow atomic_read on 32-bit hosts.
*/
uint32_t mip;
uint32_t miclaim;
target_ulong mie;
target_ulong mideleg;
@ -172,6 +177,9 @@ struct CPURISCVState {
/* physical memory protection */
pmp_table_t pmp_state;
/* True if in debugger mode. */
bool debugger;
#endif
float_status fp_status;
@ -263,6 +271,7 @@ void riscv_cpu_list(FILE *f, fprintf_function cpu_fprintf);
#define cpu_mmu_index riscv_cpu_mmu_index
#ifndef CONFIG_USER_ONLY
int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint32_t interrupts);
uint32_t riscv_cpu_update_mip(RISCVCPU *cpu, uint32_t mask, uint32_t value);
#define BOOL_TO_MASK(x) (-!!(x)) /* helper for riscv_cpu_update_mip value */
#endif
@ -293,6 +302,8 @@ static inline void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
int riscv_csrrw(CPURISCVState *env, int csrno, target_ulong *ret_value,
target_ulong new_value, target_ulong write_mask);
int riscv_csrrw_debug(CPURISCVState *env, int csrno, target_ulong *ret_value,
target_ulong new_value, target_ulong write_mask);
static inline void riscv_csr_write(CPURISCVState *env, int csrno,
target_ulong val)
@ -325,6 +336,8 @@ typedef struct {
void riscv_get_csr_ops(int csrno, riscv_csr_operations *ops);
void riscv_set_csr_ops(int csrno, riscv_csr_operations *ops);
void riscv_cpu_register_gdb_regs_for_features(CPUState *cs);
#include "exec/cpu-all.h"
#endif /* RISCV_CPU_H */

View File

@ -135,16 +135,22 @@
/* Legacy Counter Setup (priv v1.9.1) */
#define CSR_MUCOUNTEREN 0x320
#define CSR_MSCOUNTEREN 0x321
#define CSR_MHCOUNTEREN 0x322
/* Machine Trap Handling */
#define CSR_MSCRATCH 0x340
#define CSR_MEPC 0x341
#define CSR_MCAUSE 0x342
#define CSR_MBADADDR 0x343
#define CSR_MTVAL 0x343
#define CSR_MIP 0x344
/* Legacy Machine Trap Handling (priv v1.9.1) */
#define CSR_MBADADDR 0x343
/* Supervisor Trap Setup */
#define CSR_SSTATUS 0x100
#define CSR_SEDELEG 0x102
#define CSR_SIDELEG 0x103
#define CSR_SIE 0x104
#define CSR_STVEC 0x105
#define CSR_SCOUNTEREN 0x106
@ -153,9 +159,12 @@
#define CSR_SSCRATCH 0x140
#define CSR_SEPC 0x141
#define CSR_SCAUSE 0x142
#define CSR_SBADADDR 0x143
#define CSR_STVAL 0x143
#define CSR_SIP 0x144
/* Legacy Supervisor Trap Handling (priv v1.9.1) */
#define CSR_SBADADDR 0x143
/* Supervisor Protection and Translation */
#define CSR_SPTBR 0x180
#define CSR_SATP 0x180
@ -282,6 +291,28 @@
#define CSR_MHPMCOUNTER30H 0xb9e
#define CSR_MHPMCOUNTER31H 0xb9f
/* Legacy Hypervisor Trap Setup (priv v1.9.1) */
#define CSR_HSTATUS 0x200
#define CSR_HEDELEG 0x202
#define CSR_HIDELEG 0x203
#define CSR_HIE 0x204
#define CSR_HTVEC 0x205
/* Legacy Hypervisor Trap Handling (priv v1.9.1) */
#define CSR_HSCRATCH 0x240
#define CSR_HEPC 0x241
#define CSR_HCAUSE 0x242
#define CSR_HBADADDR 0x243
#define CSR_HIP 0x244
/* Legacy Machine Protection and Translation (priv v1.9.1) */
#define CSR_MBASE 0x380
#define CSR_MBOUND 0x381
#define CSR_MIBASE 0x382
#define CSR_MIBOUND 0x383
#define CSR_MDBASE 0x384
#define CSR_MDBOUND 0x385
/* mstatus CSR bits */
#define MSTATUS_UIE 0x00000001
#define MSTATUS_SIE 0x00000002

View File

@ -22,8 +22,7 @@
#include "cpu.h"
#include "exec/exec-all.h"
#include "tcg-op.h"
#define RISCV_DEBUG_INTERRUPT 0
#include "trace.h"
int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch)
{
@ -72,6 +71,17 @@ bool riscv_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
#if !defined(CONFIG_USER_ONLY)
int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint32_t interrupts)
{
CPURISCVState *env = &cpu->env;
if (env->miclaim & interrupts) {
return -1;
} else {
env->miclaim |= interrupts;
return 0;
}
}
/* iothread_mutex must be held */
uint32_t riscv_cpu_update_mip(RISCVCPU *cpu, uint32_t mask, uint32_t value)
{
@ -84,9 +94,9 @@ uint32_t riscv_cpu_update_mip(RISCVCPU *cpu, uint32_t mask, uint32_t value)
cmp = atomic_cmpxchg(&env->mip, old, new);
} while (old != cmp);
if (new && !old) {
if (new) {
cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
} else if (!new && old) {
} else {
cpu_reset_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
}
@ -443,121 +453,85 @@ void riscv_cpu_do_interrupt(CPUState *cs)
RISCVCPU *cpu = RISCV_CPU(cs);
CPURISCVState *env = &cpu->env;
if (RISCV_DEBUG_INTERRUPT) {
int log_cause = cs->exception_index & RISCV_EXCP_INT_MASK;
if (cs->exception_index & RISCV_EXCP_INT_FLAG) {
qemu_log_mask(LOG_TRACE, "core "
TARGET_FMT_ld ": trap %s, epc 0x" TARGET_FMT_lx "\n",
env->mhartid, riscv_intr_names[log_cause], env->pc);
} else {
qemu_log_mask(LOG_TRACE, "core "
TARGET_FMT_ld ": intr %s, epc 0x" TARGET_FMT_lx "\n",
env->mhartid, riscv_excp_names[log_cause], env->pc);
/* cs->exception is 32-bits wide unlike mcause which is XLEN-bits wide
* so we mask off the MSB and separate into trap type and cause.
*/
bool async = !!(cs->exception_index & RISCV_EXCP_INT_FLAG);
target_ulong cause = cs->exception_index & RISCV_EXCP_INT_MASK;
target_ulong deleg = async ? env->mideleg : env->medeleg;
target_ulong tval = 0;
static const int ecall_cause_map[] = {
[PRV_U] = RISCV_EXCP_U_ECALL,
[PRV_S] = RISCV_EXCP_S_ECALL,
[PRV_H] = RISCV_EXCP_H_ECALL,
[PRV_M] = RISCV_EXCP_M_ECALL
};
if (!async) {
/* set tval to badaddr for traps with address information */
switch (cause) {
case RISCV_EXCP_INST_ADDR_MIS:
case RISCV_EXCP_INST_ACCESS_FAULT:
case RISCV_EXCP_LOAD_ADDR_MIS:
case RISCV_EXCP_STORE_AMO_ADDR_MIS:
case RISCV_EXCP_LOAD_ACCESS_FAULT:
case RISCV_EXCP_STORE_AMO_ACCESS_FAULT:
case RISCV_EXCP_INST_PAGE_FAULT:
case RISCV_EXCP_LOAD_PAGE_FAULT:
case RISCV_EXCP_STORE_PAGE_FAULT:
tval = env->badaddr;
break;
default:
break;
}
/* ecall is dispatched as one cause so translate based on mode */
if (cause == RISCV_EXCP_U_ECALL) {
assert(env->priv <= 3);
cause = ecall_cause_map[env->priv];
}
}
target_ulong fixed_cause = 0;
if (cs->exception_index & (RISCV_EXCP_INT_FLAG)) {
/* hacky for now. the MSB (bit 63) indicates interrupt but cs->exception
index is only 32 bits wide */
fixed_cause = cs->exception_index & RISCV_EXCP_INT_MASK;
fixed_cause |= ((target_ulong)1) << (TARGET_LONG_BITS - 1);
} else {
/* fixup User ECALL -> correct priv ECALL */
if (cs->exception_index == RISCV_EXCP_U_ECALL) {
switch (env->priv) {
case PRV_U:
fixed_cause = RISCV_EXCP_U_ECALL;
break;
case PRV_S:
fixed_cause = RISCV_EXCP_S_ECALL;
break;
case PRV_H:
fixed_cause = RISCV_EXCP_H_ECALL;
break;
case PRV_M:
fixed_cause = RISCV_EXCP_M_ECALL;
break;
}
} else {
fixed_cause = cs->exception_index;
}
}
trace_riscv_trap(env->mhartid, async, cause, env->pc, tval, cause < 16 ?
(async ? riscv_intr_names : riscv_excp_names)[cause] : "(unknown)");
target_ulong backup_epc = env->pc;
target_ulong bit = fixed_cause;
target_ulong deleg = env->medeleg;
int hasbadaddr =
(fixed_cause == RISCV_EXCP_INST_ADDR_MIS) ||
(fixed_cause == RISCV_EXCP_INST_ACCESS_FAULT) ||
(fixed_cause == RISCV_EXCP_LOAD_ADDR_MIS) ||
(fixed_cause == RISCV_EXCP_STORE_AMO_ADDR_MIS) ||
(fixed_cause == RISCV_EXCP_LOAD_ACCESS_FAULT) ||
(fixed_cause == RISCV_EXCP_STORE_AMO_ACCESS_FAULT) ||
(fixed_cause == RISCV_EXCP_INST_PAGE_FAULT) ||
(fixed_cause == RISCV_EXCP_LOAD_PAGE_FAULT) ||
(fixed_cause == RISCV_EXCP_STORE_PAGE_FAULT);
if (bit & ((target_ulong)1 << (TARGET_LONG_BITS - 1))) {
deleg = env->mideleg;
bit &= ~((target_ulong)1 << (TARGET_LONG_BITS - 1));
}
if (env->priv <= PRV_S && bit < 64 && ((deleg >> bit) & 1)) {
if (env->priv <= PRV_S &&
cause < TARGET_LONG_BITS && ((deleg >> cause) & 1)) {
/* handle the trap in S-mode */
/* No need to check STVEC for misaligned - lower 2 bits cannot be set */
env->pc = env->stvec;
env->scause = fixed_cause;
env->sepc = backup_epc;
if (hasbadaddr) {
if (RISCV_DEBUG_INTERRUPT) {
qemu_log_mask(LOG_TRACE, "core " TARGET_FMT_ld ": badaddr 0x"
TARGET_FMT_lx "\n", env->mhartid, env->badaddr);
}
env->sbadaddr = env->badaddr;
} else {
/* otherwise we must clear sbadaddr/stval
* todo: support populating stval on illegal instructions */
env->sbadaddr = 0;
}
target_ulong s = env->mstatus;
s = set_field(s, MSTATUS_SPIE, env->priv_ver >= PRIV_VERSION_1_10_0 ?
get_field(s, MSTATUS_SIE) : get_field(s, MSTATUS_UIE << env->priv));
s = set_field(s, MSTATUS_SPP, env->priv);
s = set_field(s, MSTATUS_SIE, 0);
env->mstatus = s;
env->scause = cause | ~(((target_ulong)-1) >> async);
env->sepc = env->pc;
env->sbadaddr = tval;
env->pc = (env->stvec >> 2 << 2) +
((async && (env->stvec & 3) == 1) ? cause * 4 : 0);
riscv_cpu_set_mode(env, PRV_S);
} else {
/* No need to check MTVEC for misaligned - lower 2 bits cannot be set */
env->pc = env->mtvec;
env->mepc = backup_epc;
env->mcause = fixed_cause;
if (hasbadaddr) {
if (RISCV_DEBUG_INTERRUPT) {
qemu_log_mask(LOG_TRACE, "core " TARGET_FMT_ld ": badaddr 0x"
TARGET_FMT_lx "\n", env->mhartid, env->badaddr);
}
env->mbadaddr = env->badaddr;
} else {
/* otherwise we must clear mbadaddr/mtval
* todo: support populating mtval on illegal instructions */
env->mbadaddr = 0;
}
/* handle the trap in M-mode */
target_ulong s = env->mstatus;
s = set_field(s, MSTATUS_MPIE, env->priv_ver >= PRIV_VERSION_1_10_0 ?
get_field(s, MSTATUS_MIE) : get_field(s, MSTATUS_UIE << env->priv));
s = set_field(s, MSTATUS_MPP, env->priv);
s = set_field(s, MSTATUS_MIE, 0);
env->mstatus = s;
env->mcause = cause | ~(((target_ulong)-1) >> async);
env->mepc = env->pc;
env->mbadaddr = tval;
env->pc = (env->mtvec >> 2 << 2) +
((async && (env->mtvec & 3) == 1) ? cause * 4 : 0);
riscv_cpu_set_mode(env, PRV_M);
}
/* TODO yield load reservation */
/* NOTE: it is not necessary to yield load reservations here. It is only
* necessary for an SC from "another hart" to cause a load reservation
* to be yielded. Refer to the memory consistency model section of the
* RISC-V ISA Specification.
*/
#endif
cs->exception_index = EXCP_NONE; /* mark handled to qemu */
}

View File

@ -10,4 +10,5 @@
#define xA4 14
#define xA5 15
#define xA6 16
#define xA7 17 /* syscall number goes here */
#define xA7 17 /* syscall number for RVI ABI */
#define xT0 5 /* syscall number for RVE ABI */

View File

@ -46,7 +46,7 @@ void riscv_set_csr_ops(int csrno, riscv_csr_operations *ops)
static int fs(CPURISCVState *env, int csrno)
{
#if !defined(CONFIG_USER_ONLY)
if (!(env->mstatus & MSTATUS_FS)) {
if (!env->debugger && !(env->mstatus & MSTATUS_FS)) {
return -1;
}
#endif
@ -92,7 +92,7 @@ static int pmp(CPURISCVState *env, int csrno)
static int read_fflags(CPURISCVState *env, int csrno, target_ulong *val)
{
#if !defined(CONFIG_USER_ONLY)
if (!(env->mstatus & MSTATUS_FS)) {
if (!env->debugger && !(env->mstatus & MSTATUS_FS)) {
return -1;
}
#endif
@ -103,7 +103,7 @@ static int read_fflags(CPURISCVState *env, int csrno, target_ulong *val)
static int write_fflags(CPURISCVState *env, int csrno, target_ulong val)
{
#if !defined(CONFIG_USER_ONLY)
if (!(env->mstatus & MSTATUS_FS)) {
if (!env->debugger && !(env->mstatus & MSTATUS_FS)) {
return -1;
}
env->mstatus |= MSTATUS_FS;
@ -115,7 +115,7 @@ static int write_fflags(CPURISCVState *env, int csrno, target_ulong val)
static int read_frm(CPURISCVState *env, int csrno, target_ulong *val)
{
#if !defined(CONFIG_USER_ONLY)
if (!(env->mstatus & MSTATUS_FS)) {
if (!env->debugger && !(env->mstatus & MSTATUS_FS)) {
return -1;
}
#endif
@ -126,7 +126,7 @@ static int read_frm(CPURISCVState *env, int csrno, target_ulong *val)
static int write_frm(CPURISCVState *env, int csrno, target_ulong val)
{
#if !defined(CONFIG_USER_ONLY)
if (!(env->mstatus & MSTATUS_FS)) {
if (!env->debugger && !(env->mstatus & MSTATUS_FS)) {
return -1;
}
env->mstatus |= MSTATUS_FS;
@ -138,7 +138,7 @@ static int write_frm(CPURISCVState *env, int csrno, target_ulong val)
static int read_fcsr(CPURISCVState *env, int csrno, target_ulong *val)
{
#if !defined(CONFIG_USER_ONLY)
if (!(env->mstatus & MSTATUS_FS)) {
if (!env->debugger && !(env->mstatus & MSTATUS_FS)) {
return -1;
}
#endif
@ -150,7 +150,7 @@ static int read_fcsr(CPURISCVState *env, int csrno, target_ulong *val)
static int write_fcsr(CPURISCVState *env, int csrno, target_ulong val)
{
#if !defined(CONFIG_USER_ONLY)
if (!(env->mstatus & MSTATUS_FS)) {
if (!env->debugger && !(env->mstatus & MSTATUS_FS)) {
return -1;
}
env->mstatus |= MSTATUS_FS;
@ -435,10 +435,10 @@ static int read_mtvec(CPURISCVState *env, int csrno, target_ulong *val)
static int write_mtvec(CPURISCVState *env, int csrno, target_ulong val)
{
/* bits [1:0] encode mode; 0 = direct, 1 = vectored, 2 >= reserved */
if ((val & 3) == 0) {
env->mtvec = val >> 2 << 2;
if ((val & 3) < 2) {
env->mtvec = val;
} else {
qemu_log_mask(LOG_UNIMP, "CSR_MTVEC: vectored traps not supported");
qemu_log_mask(LOG_UNIMP, "CSR_MTVEC: reserved mode not supported\n");
}
return 0;
}
@ -550,16 +550,10 @@ static int rmw_mip(CPURISCVState *env, int csrno, target_ulong *ret_value,
target_ulong new_value, target_ulong write_mask)
{
RISCVCPU *cpu = riscv_env_get_cpu(env);
target_ulong mask = write_mask & delegable_ints;
/* Allow software control of delegable interrupts not claimed by hardware */
target_ulong mask = write_mask & delegable_ints & ~env->miclaim;
uint32_t old_mip;
/* We can't allow the supervisor to control SEIP as this would allow the
* supervisor to clear a pending external interrupt which will result in
* lost a interrupt in the case a PLIC is attached. The SEIP bit must be
* hardware controlled when a PLIC is attached. This should be an option
* for CPUs with software-delegated Supervisor External Interrupts. */
mask &= ~MIP_SEIP;
if (mask) {
qemu_mutex_lock_iothread();
old_mip = riscv_cpu_update_mip(cpu, mask, (new_value & mask));
@ -613,10 +607,10 @@ static int read_stvec(CPURISCVState *env, int csrno, target_ulong *val)
static int write_stvec(CPURISCVState *env, int csrno, target_ulong val)
{
/* bits [1:0] encode mode; 0 = direct, 1 = vectored, 2 >= reserved */
if ((val & 3) == 0) {
env->stvec = val >> 2 << 2;
if ((val & 3) < 2) {
env->stvec = val;
} else {
qemu_log_mask(LOG_UNIMP, "CSR_STVEC: vectored traps not supported");
qemu_log_mask(LOG_UNIMP, "CSR_STVEC: reserved mode not supported\n");
}
return 0;
}
@ -827,6 +821,24 @@ int riscv_csrrw(CPURISCVState *env, int csrno, target_ulong *ret_value,
return 0;
}
/*
* Debugger support. If not in user mode, set env->debugger before the
* riscv_csrrw call and clear it after the call.
*/
int riscv_csrrw_debug(CPURISCVState *env, int csrno, target_ulong *ret_value,
target_ulong new_value, target_ulong write_mask)
{
int ret;
#if !defined(CONFIG_USER_ONLY)
env->debugger = true;
#endif
ret = riscv_csrrw(env, csrno, ret_value, new_value, write_mask);
#if !defined(CONFIG_USER_ONLY)
env->debugger = false;
#endif
return ret;
}
/* Control and Status Register function table */
static riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
/* User Floating-Point CSRs */

View File

@ -21,6 +21,255 @@
#include "exec/gdbstub.h"
#include "cpu.h"
/*
* The GDB CSR xml files list them in documentation order, not numerical order,
* and are missing entries for unnamed CSRs. So we need to map the gdb numbers
* to the hardware numbers.
*/
static int csr_register_map[] = {
CSR_USTATUS,
CSR_UIE,
CSR_UTVEC,
CSR_USCRATCH,
CSR_UEPC,
CSR_UCAUSE,
CSR_UTVAL,
CSR_UIP,
CSR_FFLAGS,
CSR_FRM,
CSR_FCSR,
CSR_CYCLE,
CSR_TIME,
CSR_INSTRET,
CSR_HPMCOUNTER3,
CSR_HPMCOUNTER4,
CSR_HPMCOUNTER5,
CSR_HPMCOUNTER6,
CSR_HPMCOUNTER7,
CSR_HPMCOUNTER8,
CSR_HPMCOUNTER9,
CSR_HPMCOUNTER10,
CSR_HPMCOUNTER11,
CSR_HPMCOUNTER12,
CSR_HPMCOUNTER13,
CSR_HPMCOUNTER14,
CSR_HPMCOUNTER15,
CSR_HPMCOUNTER16,
CSR_HPMCOUNTER17,
CSR_HPMCOUNTER18,
CSR_HPMCOUNTER19,
CSR_HPMCOUNTER20,
CSR_HPMCOUNTER21,
CSR_HPMCOUNTER22,
CSR_HPMCOUNTER23,
CSR_HPMCOUNTER24,
CSR_HPMCOUNTER25,
CSR_HPMCOUNTER26,
CSR_HPMCOUNTER27,
CSR_HPMCOUNTER28,
CSR_HPMCOUNTER29,
CSR_HPMCOUNTER30,
CSR_HPMCOUNTER31,
CSR_CYCLEH,
CSR_TIMEH,
CSR_INSTRETH,
CSR_HPMCOUNTER3H,
CSR_HPMCOUNTER4H,
CSR_HPMCOUNTER5H,
CSR_HPMCOUNTER6H,
CSR_HPMCOUNTER7H,
CSR_HPMCOUNTER8H,
CSR_HPMCOUNTER9H,
CSR_HPMCOUNTER10H,
CSR_HPMCOUNTER11H,
CSR_HPMCOUNTER12H,
CSR_HPMCOUNTER13H,
CSR_HPMCOUNTER14H,
CSR_HPMCOUNTER15H,
CSR_HPMCOUNTER16H,
CSR_HPMCOUNTER17H,
CSR_HPMCOUNTER18H,
CSR_HPMCOUNTER19H,
CSR_HPMCOUNTER20H,
CSR_HPMCOUNTER21H,
CSR_HPMCOUNTER22H,
CSR_HPMCOUNTER23H,
CSR_HPMCOUNTER24H,
CSR_HPMCOUNTER25H,
CSR_HPMCOUNTER26H,
CSR_HPMCOUNTER27H,
CSR_HPMCOUNTER28H,
CSR_HPMCOUNTER29H,
CSR_HPMCOUNTER30H,
CSR_HPMCOUNTER31H,
CSR_SSTATUS,
CSR_SEDELEG,
CSR_SIDELEG,
CSR_SIE,
CSR_STVEC,
CSR_SCOUNTEREN,
CSR_SSCRATCH,
CSR_SEPC,
CSR_SCAUSE,
CSR_STVAL,
CSR_SIP,
CSR_SATP,
CSR_MVENDORID,
CSR_MARCHID,
CSR_MIMPID,
CSR_MHARTID,
CSR_MSTATUS,
CSR_MISA,
CSR_MEDELEG,
CSR_MIDELEG,
CSR_MIE,
CSR_MTVEC,
CSR_MCOUNTEREN,
CSR_MSCRATCH,
CSR_MEPC,
CSR_MCAUSE,
CSR_MTVAL,
CSR_MIP,
CSR_PMPCFG0,
CSR_PMPCFG1,
CSR_PMPCFG2,
CSR_PMPCFG3,
CSR_PMPADDR0,
CSR_PMPADDR1,
CSR_PMPADDR2,
CSR_PMPADDR3,
CSR_PMPADDR4,
CSR_PMPADDR5,
CSR_PMPADDR6,
CSR_PMPADDR7,
CSR_PMPADDR8,
CSR_PMPADDR9,
CSR_PMPADDR10,
CSR_PMPADDR11,
CSR_PMPADDR12,
CSR_PMPADDR13,
CSR_PMPADDR14,
CSR_PMPADDR15,
CSR_MCYCLE,
CSR_MINSTRET,
CSR_MHPMCOUNTER3,
CSR_MHPMCOUNTER4,
CSR_MHPMCOUNTER5,
CSR_MHPMCOUNTER6,
CSR_MHPMCOUNTER7,
CSR_MHPMCOUNTER8,
CSR_MHPMCOUNTER9,
CSR_MHPMCOUNTER10,
CSR_MHPMCOUNTER11,
CSR_MHPMCOUNTER12,
CSR_MHPMCOUNTER13,
CSR_MHPMCOUNTER14,
CSR_MHPMCOUNTER15,
CSR_MHPMCOUNTER16,
CSR_MHPMCOUNTER17,
CSR_MHPMCOUNTER18,
CSR_MHPMCOUNTER19,
CSR_MHPMCOUNTER20,
CSR_MHPMCOUNTER21,
CSR_MHPMCOUNTER22,
CSR_MHPMCOUNTER23,
CSR_MHPMCOUNTER24,
CSR_MHPMCOUNTER25,
CSR_MHPMCOUNTER26,
CSR_MHPMCOUNTER27,
CSR_MHPMCOUNTER28,
CSR_MHPMCOUNTER29,
CSR_MHPMCOUNTER30,
CSR_MHPMCOUNTER31,
CSR_MCYCLEH,
CSR_MINSTRETH,
CSR_MHPMCOUNTER3H,
CSR_MHPMCOUNTER4H,
CSR_MHPMCOUNTER5H,
CSR_MHPMCOUNTER6H,
CSR_MHPMCOUNTER7H,
CSR_MHPMCOUNTER8H,
CSR_MHPMCOUNTER9H,
CSR_MHPMCOUNTER10H,
CSR_MHPMCOUNTER11H,
CSR_MHPMCOUNTER12H,
CSR_MHPMCOUNTER13H,
CSR_MHPMCOUNTER14H,
CSR_MHPMCOUNTER15H,
CSR_MHPMCOUNTER16H,
CSR_MHPMCOUNTER17H,
CSR_MHPMCOUNTER18H,
CSR_MHPMCOUNTER19H,
CSR_MHPMCOUNTER20H,
CSR_MHPMCOUNTER21H,
CSR_MHPMCOUNTER22H,
CSR_MHPMCOUNTER23H,
CSR_MHPMCOUNTER24H,
CSR_MHPMCOUNTER25H,
CSR_MHPMCOUNTER26H,
CSR_MHPMCOUNTER27H,
CSR_MHPMCOUNTER28H,
CSR_MHPMCOUNTER29H,
CSR_MHPMCOUNTER30H,
CSR_MHPMCOUNTER31H,
CSR_MHPMEVENT3,
CSR_MHPMEVENT4,
CSR_MHPMEVENT5,
CSR_MHPMEVENT6,
CSR_MHPMEVENT7,
CSR_MHPMEVENT8,
CSR_MHPMEVENT9,
CSR_MHPMEVENT10,
CSR_MHPMEVENT11,
CSR_MHPMEVENT12,
CSR_MHPMEVENT13,
CSR_MHPMEVENT14,
CSR_MHPMEVENT15,
CSR_MHPMEVENT16,
CSR_MHPMEVENT17,
CSR_MHPMEVENT18,
CSR_MHPMEVENT19,
CSR_MHPMEVENT20,
CSR_MHPMEVENT21,
CSR_MHPMEVENT22,
CSR_MHPMEVENT23,
CSR_MHPMEVENT24,
CSR_MHPMEVENT25,
CSR_MHPMEVENT26,
CSR_MHPMEVENT27,
CSR_MHPMEVENT28,
CSR_MHPMEVENT29,
CSR_MHPMEVENT30,
CSR_MHPMEVENT31,
CSR_TSELECT,
CSR_TDATA1,
CSR_TDATA2,
CSR_TDATA3,
CSR_DCSR,
CSR_DPC,
CSR_DSCRATCH,
CSR_HSTATUS,
CSR_HEDELEG,
CSR_HIDELEG,
CSR_HIE,
CSR_HTVEC,
CSR_HSCRATCH,
CSR_HEPC,
CSR_HCAUSE,
CSR_HBADADDR,
CSR_HIP,
CSR_MBASE,
CSR_MBOUND,
CSR_MIBASE,
CSR_MIBOUND,
CSR_MDBASE,
CSR_MDBOUND,
CSR_MUCOUNTEREN,
CSR_MSCOUNTEREN,
CSR_MHCOUNTEREN,
};
int riscv_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
{
RISCVCPU *cpu = RISCV_CPU(cs);
@ -30,13 +279,6 @@ int riscv_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
return gdb_get_regl(mem_buf, env->gpr[n]);
} else if (n == 32) {
return gdb_get_regl(mem_buf, env->pc);
} else if (n < 65) {
return gdb_get_reg64(mem_buf, env->fpr[n - 33]);
} else if (n < 4096 + 65) {
target_ulong val = 0;
if (riscv_csrrw(env, n - 65, &val, 0, 0) == 0) {
return gdb_get_regl(mem_buf, val);
}
}
return 0;
}
@ -55,14 +297,100 @@ int riscv_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
} else if (n == 32) {
env->pc = ldtul_p(mem_buf);
return sizeof(target_ulong);
} else if (n < 65) {
env->fpr[n - 33] = ldq_p(mem_buf); /* always 64-bit */
}
return 0;
}
static int riscv_gdb_get_fpu(CPURISCVState *env, uint8_t *mem_buf, int n)
{
if (n < 32) {
return gdb_get_reg64(mem_buf, env->fpr[n]);
/* there is hole between ft11 and fflags in fpu.xml */
} else if (n < 36 && n > 32) {
target_ulong val = 0;
int result;
/*
* CSR_FFLAGS is at index 8 in csr_register, and gdb says it is FP
* register 33, so we recalculate the map index.
* This also works for CSR_FRM and CSR_FCSR.
*/
result = riscv_csrrw_debug(env, n - 33 + 8, &val, 0, 0);
if (result == 0) {
return gdb_get_regl(mem_buf, val);
}
}
return 0;
}
static int riscv_gdb_set_fpu(CPURISCVState *env, uint8_t *mem_buf, int n)
{
if (n < 32) {
env->fpr[n] = ldq_p(mem_buf); /* always 64-bit */
return sizeof(uint64_t);
} else if (n < 4096 + 65) {
/* there is hole between ft11 and fflags in fpu.xml */
} else if (n < 36 && n > 32) {
target_ulong val = ldtul_p(mem_buf);
if (riscv_csrrw(env, n - 65, NULL, val, -1) == 0) {
int result;
/*
* CSR_FFLAGS is at index 8 in csr_register, and gdb says it is FP
* register 33, so we recalculate the map index.
* This also works for CSR_FRM and CSR_FCSR.
*/
result = riscv_csrrw_debug(env, n - 33 + 8, NULL, val, -1);
if (result == 0) {
return sizeof(target_ulong);
}
}
return 0;
}
static int riscv_gdb_get_csr(CPURISCVState *env, uint8_t *mem_buf, int n)
{
if (n < ARRAY_SIZE(csr_register_map)) {
target_ulong val = 0;
int result;
result = riscv_csrrw_debug(env, csr_register_map[n], &val, 0, 0);
if (result == 0) {
return gdb_get_regl(mem_buf, val);
}
}
return 0;
}
static int riscv_gdb_set_csr(CPURISCVState *env, uint8_t *mem_buf, int n)
{
if (n < ARRAY_SIZE(csr_register_map)) {
target_ulong val = ldtul_p(mem_buf);
int result;
result = riscv_csrrw_debug(env, csr_register_map[n], NULL, val, -1);
if (result == 0) {
return sizeof(target_ulong);
}
}
return 0;
}
void riscv_cpu_register_gdb_regs_for_features(CPUState *cs)
{
RISCVCPU *cpu = RISCV_CPU(cs);
CPURISCVState *env = &cpu->env;
#if defined(TARGET_RISCV32)
if (env->misa & RVF) {
gdb_register_coprocessor(cs, riscv_gdb_get_fpu, riscv_gdb_set_fpu,
36, "riscv-32bit-fpu.xml", 0);
}
gdb_register_coprocessor(cs, riscv_gdb_get_csr, riscv_gdb_set_csr,
4096, "riscv-32bit-csr.xml", 0);
#elif defined(TARGET_RISCV64)
if (env->misa & RVF) {
gdb_register_coprocessor(cs, riscv_gdb_get_fpu, riscv_gdb_set_fpu,
36, "riscv-64bit-fpu.xml", 0);
}
gdb_register_coprocessor(cs, riscv_gdb_get_csr, riscv_gdb_set_csr,
4096, "riscv-64bit-csr.xml", 0);
#endif
}

View File

@ -113,10 +113,11 @@ static void pmp_write_cfg(CPURISCVState *env, uint32_t pmp_index, uint8_t val)
env->pmp_state.pmp[pmp_index].cfg_reg = val;
pmp_update_rule(env, pmp_index);
} else {
PMP_DEBUG("ignoring write - locked");
qemu_log_mask(LOG_GUEST_ERROR, "ignoring pmpcfg write - locked\n");
}
} else {
PMP_DEBUG("ignoring write - out of bounds");
qemu_log_mask(LOG_GUEST_ERROR,
"ignoring pmpcfg write - out of bounds\n");
}
}
@ -249,7 +250,8 @@ bool pmp_hart_has_privs(CPURISCVState *env, target_ulong addr,
/* partially inside */
if ((s + e) == 1) {
PMP_DEBUG("pmp violation - access is partially inside");
qemu_log_mask(LOG_GUEST_ERROR,
"pmp violation - access is partially inside\n");
ret = 0;
break;
}
@ -306,7 +308,8 @@ void pmpcfg_csr_write(CPURISCVState *env, uint32_t reg_index,
env->mhartid, reg_index, val);
if ((reg_index & 1) && (sizeof(target_ulong) == 8)) {
PMP_DEBUG("ignoring write - incorrect address");
qemu_log_mask(LOG_GUEST_ERROR,
"ignoring pmpcfg write - incorrect address\n");
return;
}
@ -353,10 +356,12 @@ void pmpaddr_csr_write(CPURISCVState *env, uint32_t addr_index,
env->pmp_state.pmp[addr_index].addr_reg = val;
pmp_update_rule(env, addr_index);
} else {
PMP_DEBUG("ignoring write - locked");
qemu_log_mask(LOG_GUEST_ERROR,
"ignoring pmpaddr write - locked\n");
}
} else {
PMP_DEBUG("ignoring write - out of bounds");
qemu_log_mask(LOG_GUEST_ERROR,
"ignoring pmpaddr write - out of bounds\n");
}
}
@ -372,7 +377,8 @@ target_ulong pmpaddr_csr_read(CPURISCVState *env, uint32_t addr_index)
if (addr_index < MAX_RISCV_PMPS) {
return env->pmp_state.pmp[addr_index].addr_reg;
} else {
PMP_DEBUG("ignoring read - out of bounds");
qemu_log_mask(LOG_GUEST_ERROR,
"ignoring pmpaddr read - out of bounds\n");
return 0;
}
}

View File

@ -0,0 +1,2 @@
# target/riscv/cpu_helper.c
riscv_trap(uint64_t hartid, bool async, uint64_t cause, uint64_t epc, uint64_t tval, const char *desc) "hart:%"PRId64", async:%d, cause:%"PRId64", epc:0x%"PRIx64", tval:0x%"PRIx64", desc=%s"