xref: /openbmc/qemu/target/riscv/cpu.c (revision 0602847289feed9c5abd25ebe5604596c9d4bdbe)
1dc5bd18fSMichael Clark /*
2dc5bd18fSMichael Clark  * QEMU RISC-V CPU
3dc5bd18fSMichael Clark  *
4dc5bd18fSMichael Clark  * Copyright (c) 2016-2017 Sagar Karandikar, sagark@eecs.berkeley.edu
5dc5bd18fSMichael Clark  * Copyright (c) 2017-2018 SiFive, Inc.
6dc5bd18fSMichael Clark  *
7dc5bd18fSMichael Clark  * This program is free software; you can redistribute it and/or modify it
8dc5bd18fSMichael Clark  * under the terms and conditions of the GNU General Public License,
9dc5bd18fSMichael Clark  * version 2 or later, as published by the Free Software Foundation.
10dc5bd18fSMichael Clark  *
11dc5bd18fSMichael Clark  * This program is distributed in the hope it will be useful, but WITHOUT
12dc5bd18fSMichael Clark  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13dc5bd18fSMichael Clark  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
14dc5bd18fSMichael Clark  * more details.
15dc5bd18fSMichael Clark  *
16dc5bd18fSMichael Clark  * You should have received a copy of the GNU General Public License along with
17dc5bd18fSMichael Clark  * this program.  If not, see <http://www.gnu.org/licenses/>.
18dc5bd18fSMichael Clark  */
19dc5bd18fSMichael Clark 
20dc5bd18fSMichael Clark #include "qemu/osdep.h"
210442428aSMarkus Armbruster #include "qemu/qemu-print.h"
22856dfd8aSMarkus Armbruster #include "qemu/ctype.h"
23dc5bd18fSMichael Clark #include "qemu/log.h"
24dc5bd18fSMichael Clark #include "cpu.h"
2595bd8daaSChristoph Müllner #include "cpu_vendorid.h"
2614664483SAtish Patra #include "pmu.h"
27f7697f0eSYifei Jiang #include "internals.h"
2843888c2fSAtish Patra #include "time_helper.h"
29dc5bd18fSMichael Clark #include "exec/exec-all.h"
30dc5bd18fSMichael Clark #include "qapi/error.h"
316f23aaebSAlexandre Ghiti #include "qapi/visitor.h"
32b55d7d34SAlistair Francis #include "qemu/error-report.h"
33c4e95030SAlistair Francis #include "hw/qdev-properties.h"
34dc5bd18fSMichael Clark #include "migration/vmstate.h"
35135b03cbSAlex Bennée #include "fpu/softfloat-helpers.h"
36ad40be27SYifei Jiang #include "sysemu/kvm.h"
37eddabb6bSDaniel Henrique Barboza #include "sysemu/tcg.h"
38ad40be27SYifei Jiang #include "kvm_riscv.h"
390489d5bdSAnton Johansson #include "tcg/tcg.h"
40dc5bd18fSMichael Clark 
41dc5bd18fSMichael Clark /* RISC-V CPU definitions */
420e2c3770STsukasa OI static const char riscv_single_letter_exts[] = "IEMAFDQCPVH";
43dc5bd18fSMichael Clark 
44a775398bSAtish Patra struct isa_ext_data {
45a775398bSAtish Patra     const char *name;
469a1f054dSAnup Patel     int min_version;
479a1f054dSAnup Patel     int ext_enable_offset;
48a775398bSAtish Patra };
49a775398bSAtish Patra 
50ccc84a75SDaniel Henrique Barboza #define ISA_EXT_DATA_ENTRY(_name, _min_ver, _prop) \
51ccc84a75SDaniel Henrique Barboza     {#_name, _min_ver, offsetof(struct RISCVCPUConfig, _prop)}
529a1f054dSAnup Patel 
533b57254dSWeiwei Li /*
54b227f6a8SIvan Klokov  * From vector_helper.c
55b227f6a8SIvan Klokov  * Note that vector data is stored in host-endian 64-bit chunks,
56b227f6a8SIvan Klokov  * so addressing bytes needs a host-endian fixup.
57b227f6a8SIvan Klokov  */
58b227f6a8SIvan Klokov #if HOST_BIG_ENDIAN
59b227f6a8SIvan Klokov #define BYTE(x)   ((x) ^ 7)
60b227f6a8SIvan Klokov #else
61b227f6a8SIvan Klokov #define BYTE(x)   (x)
62b227f6a8SIvan Klokov #endif
63b227f6a8SIvan Klokov 
64b227f6a8SIvan Klokov /*
659a1f054dSAnup Patel  * Here are the ordering rules of extension naming defined by RISC-V
669a1f054dSAnup Patel  * specification :
679a1f054dSAnup Patel  * 1. All extensions should be separated from other multi-letter extensions
689a1f054dSAnup Patel  *    by an underscore.
699a1f054dSAnup Patel  * 2. The first letter following the 'Z' conventionally indicates the most
709a1f054dSAnup Patel  *    closely related alphabetical extension category, IMAFDQLCBKJTPVH.
719a1f054dSAnup Patel  *    If multiple 'Z' extensions are named, they should be ordered first
729a1f054dSAnup Patel  *    by category, then alphabetically within a category.
739a1f054dSAnup Patel  * 3. Standard supervisor-level extensions (starts with 'S') should be
749a1f054dSAnup Patel  *    listed after standard unprivileged extensions.  If multiple
759a1f054dSAnup Patel  *    supervisor-level extensions are listed, they should be ordered
769a1f054dSAnup Patel  *    alphabetically.
779a1f054dSAnup Patel  * 4. Non-standard extensions (starts with 'X') must be listed after all
789a1f054dSAnup Patel  *    standard extensions. They must be separated from other multi-letter
799a1f054dSAnup Patel  *    extensions by an underscore.
806508272aSDaniel Henrique Barboza  *
816508272aSDaniel Henrique Barboza  * Single letter extensions are checked in riscv_cpu_validate_misa_priv()
826508272aSDaniel Henrique Barboza  * instead.
839a1f054dSAnup Patel  */
849a1f054dSAnup Patel static const struct isa_ext_data isa_edata_arr[] = {
85ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(zicbom, PRIV_VERSION_1_12_0, ext_icbom),
86ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(zicboz, PRIV_VERSION_1_12_0, ext_icboz),
87ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(zicond, PRIV_VERSION_1_12_0, ext_zicond),
88ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(zicsr, PRIV_VERSION_1_10_0, ext_icsr),
89ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(zifencei, PRIV_VERSION_1_10_0, ext_ifencei),
90ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(zihintpause, PRIV_VERSION_1_10_0, ext_zihintpause),
9150f94649SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(zmmul, PRIV_VERSION_1_12_0, ext_zmmul),
92ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(zawrs, PRIV_VERSION_1_12_0, ext_zawrs),
93a47842d1SChristoph Müllner     ISA_EXT_DATA_ENTRY(zfa, PRIV_VERSION_1_12_0, ext_zfa),
94889caa44SWeiwei Li     ISA_EXT_DATA_ENTRY(zfbfmin, PRIV_VERSION_1_12_0, ext_zfbfmin),
95ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(zfh, PRIV_VERSION_1_11_0, ext_zfh),
96ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(zfhmin, PRIV_VERSION_1_11_0, ext_zfhmin),
97ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(zfinx, PRIV_VERSION_1_12_0, ext_zfinx),
98ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(zdinx, PRIV_VERSION_1_12_0, ext_zdinx),
99ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(zca, PRIV_VERSION_1_12_0, ext_zca),
100ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(zcb, PRIV_VERSION_1_12_0, ext_zcb),
101ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(zcf, PRIV_VERSION_1_12_0, ext_zcf),
102ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(zcd, PRIV_VERSION_1_12_0, ext_zcd),
103ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(zce, PRIV_VERSION_1_12_0, ext_zce),
104ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(zcmp, PRIV_VERSION_1_12_0, ext_zcmp),
105ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(zcmt, PRIV_VERSION_1_12_0, ext_zcmt),
106ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(zba, PRIV_VERSION_1_12_0, ext_zba),
107ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(zbb, PRIV_VERSION_1_12_0, ext_zbb),
108ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(zbc, PRIV_VERSION_1_12_0, ext_zbc),
109ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(zbkb, PRIV_VERSION_1_12_0, ext_zbkb),
110ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(zbkc, PRIV_VERSION_1_12_0, ext_zbkc),
111ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(zbkx, PRIV_VERSION_1_12_0, ext_zbkx),
112ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(zbs, PRIV_VERSION_1_12_0, ext_zbs),
113ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(zk, PRIV_VERSION_1_12_0, ext_zk),
114ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(zkn, PRIV_VERSION_1_12_0, ext_zkn),
115ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(zknd, PRIV_VERSION_1_12_0, ext_zknd),
116ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(zkne, PRIV_VERSION_1_12_0, ext_zkne),
117ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(zknh, PRIV_VERSION_1_12_0, ext_zknh),
118ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(zkr, PRIV_VERSION_1_12_0, ext_zkr),
119ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(zks, PRIV_VERSION_1_12_0, ext_zks),
120ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(zksed, PRIV_VERSION_1_12_0, ext_zksed),
121ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(zksh, PRIV_VERSION_1_12_0, ext_zksh),
122ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(zkt, PRIV_VERSION_1_12_0, ext_zkt),
123*06028472SDickon Hood     ISA_EXT_DATA_ENTRY(zvbb, PRIV_VERSION_1_12_0, ext_zvbb),
124e13c7d3bSLawrence Hunter     ISA_EXT_DATA_ENTRY(zvbc, PRIV_VERSION_1_12_0, ext_zvbc),
125ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(zve32f, PRIV_VERSION_1_10_0, ext_zve32f),
126ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(zve64f, PRIV_VERSION_1_10_0, ext_zve64f),
127ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(zve64d, PRIV_VERSION_1_10_0, ext_zve64d),
128889caa44SWeiwei Li     ISA_EXT_DATA_ENTRY(zvfbfmin, PRIV_VERSION_1_12_0, ext_zvfbfmin),
129889caa44SWeiwei Li     ISA_EXT_DATA_ENTRY(zvfbfwma, PRIV_VERSION_1_12_0, ext_zvfbfwma),
130ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(zvfh, PRIV_VERSION_1_12_0, ext_zvfh),
131ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(zvfhmin, PRIV_VERSION_1_12_0, ext_zvfhmin),
132ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(zhinx, PRIV_VERSION_1_12_0, ext_zhinx),
133ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(zhinxmin, PRIV_VERSION_1_12_0, ext_zhinxmin),
134ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(smaia, PRIV_VERSION_1_12_0, ext_smaia),
13503d7bbfdSDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(smepmp, PRIV_VERSION_1_12_0, epmp),
1363594e3e5SMayuresh Chitale     ISA_EXT_DATA_ENTRY(smstateen, PRIV_VERSION_1_12_0, ext_smstateen),
137ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(ssaia, PRIV_VERSION_1_12_0, ext_ssaia),
138ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(sscofpmf, PRIV_VERSION_1_12_0, ext_sscofpmf),
139ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(sstc, PRIV_VERSION_1_12_0, ext_sstc),
140ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(svadu, PRIV_VERSION_1_12_0, ext_svadu),
141ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(svinval, PRIV_VERSION_1_12_0, ext_svinval),
142ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(svnapot, PRIV_VERSION_1_12_0, ext_svnapot),
143ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(svpbmt, PRIV_VERSION_1_12_0, ext_svpbmt),
144ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(xtheadba, PRIV_VERSION_1_11_0, ext_xtheadba),
145ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(xtheadbb, PRIV_VERSION_1_11_0, ext_xtheadbb),
146ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(xtheadbs, PRIV_VERSION_1_11_0, ext_xtheadbs),
147ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(xtheadcmo, PRIV_VERSION_1_11_0, ext_xtheadcmo),
148ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(xtheadcondmov, PRIV_VERSION_1_11_0, ext_xtheadcondmov),
149ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(xtheadfmemidx, PRIV_VERSION_1_11_0, ext_xtheadfmemidx),
150ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(xtheadfmv, PRIV_VERSION_1_11_0, ext_xtheadfmv),
151ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(xtheadmac, PRIV_VERSION_1_11_0, ext_xtheadmac),
152ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(xtheadmemidx, PRIV_VERSION_1_11_0, ext_xtheadmemidx),
153ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(xtheadmempair, PRIV_VERSION_1_11_0, ext_xtheadmempair),
154ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(xtheadsync, PRIV_VERSION_1_11_0, ext_xtheadsync),
155ccc84a75SDaniel Henrique Barboza     ISA_EXT_DATA_ENTRY(xventanacondops, PRIV_VERSION_1_12_0, ext_XVentanaCondOps),
1569a1f054dSAnup Patel };
1579a1f054dSAnup Patel 
1589a1f054dSAnup Patel static bool isa_ext_is_enabled(RISCVCPU *cpu,
1599a1f054dSAnup Patel                                const struct isa_ext_data *edata)
1609a1f054dSAnup Patel {
1619a1f054dSAnup Patel     bool *ext_enabled = (void *)&cpu->cfg + edata->ext_enable_offset;
1629a1f054dSAnup Patel 
1639a1f054dSAnup Patel     return *ext_enabled;
1649a1f054dSAnup Patel }
1659a1f054dSAnup Patel 
1669a1f054dSAnup Patel static void isa_ext_update_enabled(RISCVCPU *cpu,
1679a1f054dSAnup Patel                                    const struct isa_ext_data *edata, bool en)
1689a1f054dSAnup Patel {
1699a1f054dSAnup Patel     bool *ext_enabled = (void *)&cpu->cfg + edata->ext_enable_offset;
1709a1f054dSAnup Patel 
1719a1f054dSAnup Patel     *ext_enabled = en;
1729a1f054dSAnup Patel }
1739a1f054dSAnup Patel 
174dc5bd18fSMichael Clark const char * const riscv_int_regnames[] = {
175a9f37afaSAtish Patra     "x0/zero", "x1/ra",  "x2/sp",  "x3/gp",  "x4/tp",  "x5/t0",   "x6/t1",
176a9f37afaSAtish Patra     "x7/t2",   "x8/s0",  "x9/s1",  "x10/a0", "x11/a1", "x12/a2",  "x13/a3",
177a9f37afaSAtish Patra     "x14/a4",  "x15/a5", "x16/a6", "x17/a7", "x18/s2", "x19/s3",  "x20/s4",
178a9f37afaSAtish Patra     "x21/s5",  "x22/s6", "x23/s7", "x24/s8", "x25/s9", "x26/s10", "x27/s11",
179a9f37afaSAtish Patra     "x28/t3",  "x29/t4", "x30/t5", "x31/t6"
180dc5bd18fSMichael Clark };
181dc5bd18fSMichael Clark 
1822b547084SFrédéric Pétrot const char * const riscv_int_regnamesh[] = {
1832b547084SFrédéric Pétrot     "x0h/zeroh", "x1h/rah",  "x2h/sph",   "x3h/gph",   "x4h/tph",  "x5h/t0h",
1842b547084SFrédéric Pétrot     "x6h/t1h",   "x7h/t2h",  "x8h/s0h",   "x9h/s1h",   "x10h/a0h", "x11h/a1h",
1852b547084SFrédéric Pétrot     "x12h/a2h",  "x13h/a3h", "x14h/a4h",  "x15h/a5h",  "x16h/a6h", "x17h/a7h",
1862b547084SFrédéric Pétrot     "x18h/s2h",  "x19h/s3h", "x20h/s4h",  "x21h/s5h",  "x22h/s6h", "x23h/s7h",
1872b547084SFrédéric Pétrot     "x24h/s8h",  "x25h/s9h", "x26h/s10h", "x27h/s11h", "x28h/t3h", "x29h/t4h",
1882b547084SFrédéric Pétrot     "x30h/t5h",  "x31h/t6h"
1892b547084SFrédéric Pétrot };
1902b547084SFrédéric Pétrot 
191dc5bd18fSMichael Clark const char * const riscv_fpr_regnames[] = {
192a9f37afaSAtish Patra     "f0/ft0",   "f1/ft1",  "f2/ft2",   "f3/ft3",   "f4/ft4",  "f5/ft5",
193a9f37afaSAtish Patra     "f6/ft6",   "f7/ft7",  "f8/fs0",   "f9/fs1",   "f10/fa0", "f11/fa1",
194a9f37afaSAtish Patra     "f12/fa2",  "f13/fa3", "f14/fa4",  "f15/fa5",  "f16/fa6", "f17/fa7",
195a9f37afaSAtish Patra     "f18/fs2",  "f19/fs3", "f20/fs4",  "f21/fs5",  "f22/fs6", "f23/fs7",
196a9f37afaSAtish Patra     "f24/fs8",  "f25/fs9", "f26/fs10", "f27/fs11", "f28/ft8", "f29/ft9",
197a9f37afaSAtish Patra     "f30/ft10", "f31/ft11"
198dc5bd18fSMichael Clark };
199dc5bd18fSMichael Clark 
200b227f6a8SIvan Klokov const char * const riscv_rvv_regnames[] = {
201b227f6a8SIvan Klokov   "v0",  "v1",  "v2",  "v3",  "v4",  "v5",  "v6",
202b227f6a8SIvan Klokov   "v7",  "v8",  "v9",  "v10", "v11", "v12", "v13",
203b227f6a8SIvan Klokov   "v14", "v15", "v16", "v17", "v18", "v19", "v20",
204b227f6a8SIvan Klokov   "v21", "v22", "v23", "v24", "v25", "v26", "v27",
205b227f6a8SIvan Klokov   "v28", "v29", "v30", "v31"
206b227f6a8SIvan Klokov };
207b227f6a8SIvan Klokov 
2089a575d33SBin Meng static const char * const riscv_excp_names[] = {
209dc5bd18fSMichael Clark     "misaligned_fetch",
210dc5bd18fSMichael Clark     "fault_fetch",
211dc5bd18fSMichael Clark     "illegal_instruction",
212dc5bd18fSMichael Clark     "breakpoint",
213dc5bd18fSMichael Clark     "misaligned_load",
214dc5bd18fSMichael Clark     "fault_load",
215dc5bd18fSMichael Clark     "misaligned_store",
216dc5bd18fSMichael Clark     "fault_store",
217dc5bd18fSMichael Clark     "user_ecall",
218dc5bd18fSMichael Clark     "supervisor_ecall",
219dc5bd18fSMichael Clark     "hypervisor_ecall",
220dc5bd18fSMichael Clark     "machine_ecall",
221dc5bd18fSMichael Clark     "exec_page_fault",
222dc5bd18fSMichael Clark     "load_page_fault",
223dc5bd18fSMichael Clark     "reserved",
224fd990e86SPalmer Dabbelt     "store_page_fault",
225ab67a1d0SAlistair Francis     "reserved",
226ab67a1d0SAlistair Francis     "reserved",
227ab67a1d0SAlistair Francis     "reserved",
228ab67a1d0SAlistair Francis     "reserved",
229ab67a1d0SAlistair Francis     "guest_exec_page_fault",
230ab67a1d0SAlistair Francis     "guest_load_page_fault",
231ab67a1d0SAlistair Francis     "reserved",
232fd990e86SPalmer Dabbelt     "guest_store_page_fault",
233dc5bd18fSMichael Clark };
234dc5bd18fSMichael Clark 
2359a575d33SBin Meng static const char * const riscv_intr_names[] = {
236dc5bd18fSMichael Clark     "u_software",
237dc5bd18fSMichael Clark     "s_software",
238205377f8SAlistair Francis     "vs_software",
239dc5bd18fSMichael Clark     "m_software",
240dc5bd18fSMichael Clark     "u_timer",
241dc5bd18fSMichael Clark     "s_timer",
242205377f8SAlistair Francis     "vs_timer",
243dc5bd18fSMichael Clark     "m_timer",
244dc5bd18fSMichael Clark     "u_external",
2456cfcf775SEmmanuel Blot     "s_external",
246205377f8SAlistair Francis     "vs_external",
247dc5bd18fSMichael Clark     "m_external",
248426f0348SMichael Clark     "reserved",
249426f0348SMichael Clark     "reserved",
250426f0348SMichael Clark     "reserved",
251426f0348SMichael Clark     "reserved"
252dc5bd18fSMichael Clark };
253dc5bd18fSMichael Clark 
254dd8f244fSDaniel Henrique Barboza static void riscv_cpu_add_user_properties(Object *obj);
25526b2bc58SAlistair Francis 
256c51a3f5dSYifei Jiang const char *riscv_cpu_get_trap_name(target_ulong cause, bool async)
257c51a3f5dSYifei Jiang {
258c51a3f5dSYifei Jiang     if (async) {
259c51a3f5dSYifei Jiang         return (cause < ARRAY_SIZE(riscv_intr_names)) ?
260c51a3f5dSYifei Jiang                riscv_intr_names[cause] : "(unknown)";
261c51a3f5dSYifei Jiang     } else {
262c51a3f5dSYifei Jiang         return (cause < ARRAY_SIZE(riscv_excp_names)) ?
263c51a3f5dSYifei Jiang                riscv_excp_names[cause] : "(unknown)";
264c51a3f5dSYifei Jiang     }
265c51a3f5dSYifei Jiang }
266c51a3f5dSYifei Jiang 
267e91a7227SRichard Henderson static void set_misa(CPURISCVState *env, RISCVMXL mxl, uint32_t ext)
268dc5bd18fSMichael Clark {
269e91a7227SRichard Henderson     env->misa_mxl_max = env->misa_mxl = mxl;
270e91a7227SRichard Henderson     env->misa_ext_mask = env->misa_ext = ext;
271dc5bd18fSMichael Clark }
272dc5bd18fSMichael Clark 
2736f23aaebSAlexandre Ghiti #ifndef CONFIG_USER_ONLY
2746f23aaebSAlexandre Ghiti static uint8_t satp_mode_from_str(const char *satp_mode_str)
2756f23aaebSAlexandre Ghiti {
2766f23aaebSAlexandre Ghiti     if (!strncmp(satp_mode_str, "mbare", 5)) {
2776f23aaebSAlexandre Ghiti         return VM_1_10_MBARE;
2786f23aaebSAlexandre Ghiti     }
2796f23aaebSAlexandre Ghiti 
2806f23aaebSAlexandre Ghiti     if (!strncmp(satp_mode_str, "sv32", 4)) {
2816f23aaebSAlexandre Ghiti         return VM_1_10_SV32;
2826f23aaebSAlexandre Ghiti     }
2836f23aaebSAlexandre Ghiti 
2846f23aaebSAlexandre Ghiti     if (!strncmp(satp_mode_str, "sv39", 4)) {
2856f23aaebSAlexandre Ghiti         return VM_1_10_SV39;
2866f23aaebSAlexandre Ghiti     }
2876f23aaebSAlexandre Ghiti 
2886f23aaebSAlexandre Ghiti     if (!strncmp(satp_mode_str, "sv48", 4)) {
2896f23aaebSAlexandre Ghiti         return VM_1_10_SV48;
2906f23aaebSAlexandre Ghiti     }
2916f23aaebSAlexandre Ghiti 
2926f23aaebSAlexandre Ghiti     if (!strncmp(satp_mode_str, "sv57", 4)) {
2936f23aaebSAlexandre Ghiti         return VM_1_10_SV57;
2946f23aaebSAlexandre Ghiti     }
2956f23aaebSAlexandre Ghiti 
2966f23aaebSAlexandre Ghiti     if (!strncmp(satp_mode_str, "sv64", 4)) {
2976f23aaebSAlexandre Ghiti         return VM_1_10_SV64;
2986f23aaebSAlexandre Ghiti     }
2996f23aaebSAlexandre Ghiti 
3006f23aaebSAlexandre Ghiti     g_assert_not_reached();
3016f23aaebSAlexandre Ghiti }
3026f23aaebSAlexandre Ghiti 
3036f23aaebSAlexandre Ghiti uint8_t satp_mode_max_from_map(uint32_t map)
3046f23aaebSAlexandre Ghiti {
3056f23aaebSAlexandre Ghiti     /* map here has at least one bit set, so no problem with clz */
3066f23aaebSAlexandre Ghiti     return 31 - __builtin_clz(map);
3076f23aaebSAlexandre Ghiti }
3086f23aaebSAlexandre Ghiti 
3096f23aaebSAlexandre Ghiti const char *satp_mode_str(uint8_t satp_mode, bool is_32_bit)
3106f23aaebSAlexandre Ghiti {
3116f23aaebSAlexandre Ghiti     if (is_32_bit) {
3126f23aaebSAlexandre Ghiti         switch (satp_mode) {
3136f23aaebSAlexandre Ghiti         case VM_1_10_SV32:
3146f23aaebSAlexandre Ghiti             return "sv32";
3156f23aaebSAlexandre Ghiti         case VM_1_10_MBARE:
3166f23aaebSAlexandre Ghiti             return "none";
3176f23aaebSAlexandre Ghiti         }
3186f23aaebSAlexandre Ghiti     } else {
3196f23aaebSAlexandre Ghiti         switch (satp_mode) {
3206f23aaebSAlexandre Ghiti         case VM_1_10_SV64:
3216f23aaebSAlexandre Ghiti             return "sv64";
3226f23aaebSAlexandre Ghiti         case VM_1_10_SV57:
3236f23aaebSAlexandre Ghiti             return "sv57";
3246f23aaebSAlexandre Ghiti         case VM_1_10_SV48:
3256f23aaebSAlexandre Ghiti             return "sv48";
3266f23aaebSAlexandre Ghiti         case VM_1_10_SV39:
3276f23aaebSAlexandre Ghiti             return "sv39";
3286f23aaebSAlexandre Ghiti         case VM_1_10_MBARE:
3296f23aaebSAlexandre Ghiti             return "none";
3306f23aaebSAlexandre Ghiti         }
3316f23aaebSAlexandre Ghiti     }
3326f23aaebSAlexandre Ghiti 
3336f23aaebSAlexandre Ghiti     g_assert_not_reached();
3346f23aaebSAlexandre Ghiti }
3356f23aaebSAlexandre Ghiti 
3366df3747aSAlexandre Ghiti static void set_satp_mode_max_supported(RISCVCPU *cpu,
3376df3747aSAlexandre Ghiti                                         uint8_t satp_mode)
3386f23aaebSAlexandre Ghiti {
3396f23aaebSAlexandre Ghiti     bool rv32 = riscv_cpu_mxl(&cpu->env) == MXL_RV32;
3406df3747aSAlexandre Ghiti     const bool *valid_vm = rv32 ? valid_vm_1_10_32 : valid_vm_1_10_64;
3416f23aaebSAlexandre Ghiti 
3426df3747aSAlexandre Ghiti     for (int i = 0; i <= satp_mode; ++i) {
3436df3747aSAlexandre Ghiti         if (valid_vm[i]) {
3446df3747aSAlexandre Ghiti             cpu->cfg.satp_mode.supported |= (1 << i);
3456f23aaebSAlexandre Ghiti         }
3466f23aaebSAlexandre Ghiti     }
3476df3747aSAlexandre Ghiti }
3486df3747aSAlexandre Ghiti 
3496df3747aSAlexandre Ghiti /* Set the satp mode to the max supported */
3506df3747aSAlexandre Ghiti static void set_satp_mode_default_map(RISCVCPU *cpu)
3516df3747aSAlexandre Ghiti {
3526df3747aSAlexandre Ghiti     cpu->cfg.satp_mode.map = cpu->cfg.satp_mode.supported;
3536df3747aSAlexandre Ghiti }
3546f23aaebSAlexandre Ghiti #endif
3556f23aaebSAlexandre Ghiti 
356dc5bd18fSMichael Clark static void riscv_any_cpu_init(Object *obj)
357dc5bd18fSMichael Clark {
3587f0bdfb5SDaniel Henrique Barboza     RISCVCPU *cpu = RISCV_CPU(obj);
3597f0bdfb5SDaniel Henrique Barboza     CPURISCVState *env = &cpu->env;
3603820602fSAlistair Francis #if defined(TARGET_RISCV32)
361e91a7227SRichard Henderson     set_misa(env, MXL_RV32, RVI | RVM | RVA | RVF | RVD | RVC | RVU);
3623820602fSAlistair Francis #elif defined(TARGET_RISCV64)
363e91a7227SRichard Henderson     set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | RVC | RVU);
3643820602fSAlistair Francis #endif
3656df3747aSAlexandre Ghiti 
3666df3747aSAlexandre Ghiti #ifndef CONFIG_USER_ONLY
3676df3747aSAlexandre Ghiti     set_satp_mode_max_supported(RISCV_CPU(obj),
3686df3747aSAlexandre Ghiti         riscv_cpu_mxl(&RISCV_CPU(obj)->env) == MXL_RV32 ?
3696df3747aSAlexandre Ghiti         VM_1_10_SV32 : VM_1_10_SV57);
3706df3747aSAlexandre Ghiti #endif
3716df3747aSAlexandre Ghiti 
372b9a2b98eSDaniel Henrique Barboza     env->priv_ver = PRIV_VERSION_LATEST;
3737f0bdfb5SDaniel Henrique Barboza 
3747f0bdfb5SDaniel Henrique Barboza     /* inherited from parent obj via riscv_cpu_init() */
3757f0bdfb5SDaniel Henrique Barboza     cpu->cfg.ext_ifencei = true;
3767f0bdfb5SDaniel Henrique Barboza     cpu->cfg.ext_icsr = true;
3777f0bdfb5SDaniel Henrique Barboza     cpu->cfg.mmu = true;
3787f0bdfb5SDaniel Henrique Barboza     cpu->cfg.pmp = true;
379dc5bd18fSMichael Clark }
380dc5bd18fSMichael Clark 
381094b072cSAlistair Francis #if defined(TARGET_RISCV64)
382094b072cSAlistair Francis static void rv64_base_cpu_init(Object *obj)
3838903bf6eSAlistair Francis {
3848903bf6eSAlistair Francis     CPURISCVState *env = &RISCV_CPU(obj)->env;
385b55d7d34SAlistair Francis     /* We set this in the realise function */
386e91a7227SRichard Henderson     set_misa(env, MXL_RV64, 0);
387dd8f244fSDaniel Henrique Barboza     riscv_cpu_add_user_properties(obj);
38818800095SAnup Patel     /* Set latest version of privileged specification */
389b9a2b98eSDaniel Henrique Barboza     env->priv_ver = PRIV_VERSION_LATEST;
3906df3747aSAlexandre Ghiti #ifndef CONFIG_USER_ONLY
3916df3747aSAlexandre Ghiti     set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV57);
3926df3747aSAlexandre Ghiti #endif
3938903bf6eSAlistair Francis }
3948903bf6eSAlistair Francis 
395114baacaSAlistair Francis static void rv64_sifive_u_cpu_init(Object *obj)
396dc5bd18fSMichael Clark {
3977f0bdfb5SDaniel Henrique Barboza     RISCVCPU *cpu = RISCV_CPU(obj);
3987f0bdfb5SDaniel Henrique Barboza     CPURISCVState *env = &cpu->env;
399e91a7227SRichard Henderson     set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
4008c6eeb50SDaniel Henrique Barboza     env->priv_ver = PRIV_VERSION_1_10_0;
4016df3747aSAlexandre Ghiti #ifndef CONFIG_USER_ONLY
4026df3747aSAlexandre Ghiti     set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV39);
4036df3747aSAlexandre Ghiti #endif
4047f0bdfb5SDaniel Henrique Barboza 
4057f0bdfb5SDaniel Henrique Barboza     /* inherited from parent obj via riscv_cpu_init() */
4067f0bdfb5SDaniel Henrique Barboza     cpu->cfg.ext_ifencei = true;
4077f0bdfb5SDaniel Henrique Barboza     cpu->cfg.ext_icsr = true;
4087f0bdfb5SDaniel Henrique Barboza     cpu->cfg.mmu = true;
4097f0bdfb5SDaniel Henrique Barboza     cpu->cfg.pmp = true;
410dc5bd18fSMichael Clark }
411dc5bd18fSMichael Clark 
412114baacaSAlistair Francis static void rv64_sifive_e_cpu_init(Object *obj)
413d8e72bd1SBin Meng {
414d8e72bd1SBin Meng     CPURISCVState *env = &RISCV_CPU(obj)->env;
41526b2bc58SAlistair Francis     RISCVCPU *cpu = RISCV_CPU(obj);
41626b2bc58SAlistair Francis 
417e91a7227SRichard Henderson     set_misa(env, MXL_RV64, RVI | RVM | RVA | RVC | RVU);
4188c6eeb50SDaniel Henrique Barboza     env->priv_ver = PRIV_VERSION_1_10_0;
4196df3747aSAlexandre Ghiti #ifndef CONFIG_USER_ONLY
4206df3747aSAlexandre Ghiti     set_satp_mode_max_supported(cpu, VM_1_10_MBARE);
4216df3747aSAlexandre Ghiti #endif
4227f0bdfb5SDaniel Henrique Barboza 
4237f0bdfb5SDaniel Henrique Barboza     /* inherited from parent obj via riscv_cpu_init() */
4247f0bdfb5SDaniel Henrique Barboza     cpu->cfg.ext_ifencei = true;
4257f0bdfb5SDaniel Henrique Barboza     cpu->cfg.ext_icsr = true;
4267f0bdfb5SDaniel Henrique Barboza     cpu->cfg.pmp = true;
427d8e72bd1SBin Meng }
428332dab68SFrédéric Pétrot 
42995bd8daaSChristoph Müllner static void rv64_thead_c906_cpu_init(Object *obj)
43095bd8daaSChristoph Müllner {
43195bd8daaSChristoph Müllner     CPURISCVState *env = &RISCV_CPU(obj)->env;
43295bd8daaSChristoph Müllner     RISCVCPU *cpu = RISCV_CPU(obj);
43395bd8daaSChristoph Müllner 
4344f13abcbSDaniel Henrique Barboza     set_misa(env, MXL_RV64, RVG | RVC | RVS | RVU);
4358c6eeb50SDaniel Henrique Barboza     env->priv_ver = PRIV_VERSION_1_11_0;
43695bd8daaSChristoph Müllner 
437a47842d1SChristoph Müllner     cpu->cfg.ext_zfa = true;
43895bd8daaSChristoph Müllner     cpu->cfg.ext_zfh = true;
43995bd8daaSChristoph Müllner     cpu->cfg.mmu = true;
44095bd8daaSChristoph Müllner     cpu->cfg.ext_xtheadba = true;
44195bd8daaSChristoph Müllner     cpu->cfg.ext_xtheadbb = true;
44295bd8daaSChristoph Müllner     cpu->cfg.ext_xtheadbs = true;
44395bd8daaSChristoph Müllner     cpu->cfg.ext_xtheadcmo = true;
44495bd8daaSChristoph Müllner     cpu->cfg.ext_xtheadcondmov = true;
44595bd8daaSChristoph Müllner     cpu->cfg.ext_xtheadfmemidx = true;
44695bd8daaSChristoph Müllner     cpu->cfg.ext_xtheadmac = true;
44795bd8daaSChristoph Müllner     cpu->cfg.ext_xtheadmemidx = true;
44895bd8daaSChristoph Müllner     cpu->cfg.ext_xtheadmempair = true;
44995bd8daaSChristoph Müllner     cpu->cfg.ext_xtheadsync = true;
45095bd8daaSChristoph Müllner 
45195bd8daaSChristoph Müllner     cpu->cfg.mvendorid = THEAD_VENDOR_ID;
4526df3747aSAlexandre Ghiti #ifndef CONFIG_USER_ONLY
4536df3747aSAlexandre Ghiti     set_satp_mode_max_supported(cpu, VM_1_10_SV39);
4546df3747aSAlexandre Ghiti #endif
4557f0bdfb5SDaniel Henrique Barboza 
4567f0bdfb5SDaniel Henrique Barboza     /* inherited from parent obj via riscv_cpu_init() */
4577f0bdfb5SDaniel Henrique Barboza     cpu->cfg.pmp = true;
45895bd8daaSChristoph Müllner }
45995bd8daaSChristoph Müllner 
460e1d084a8SRahul Pathak static void rv64_veyron_v1_cpu_init(Object *obj)
461e1d084a8SRahul Pathak {
462e1d084a8SRahul Pathak     CPURISCVState *env = &RISCV_CPU(obj)->env;
463e1d084a8SRahul Pathak     RISCVCPU *cpu = RISCV_CPU(obj);
464e1d084a8SRahul Pathak 
465e1d084a8SRahul Pathak     set_misa(env, MXL_RV64, RVG | RVC | RVS | RVU | RVH);
466e1d084a8SRahul Pathak     env->priv_ver = PRIV_VERSION_1_12_0;
467e1d084a8SRahul Pathak 
468e1d084a8SRahul Pathak     /* Enable ISA extensions */
469e1d084a8SRahul Pathak     cpu->cfg.mmu = true;
470029f5feeSDaniel Henrique Barboza     cpu->cfg.ext_ifencei = true;
471029f5feeSDaniel Henrique Barboza     cpu->cfg.ext_icsr = true;
472029f5feeSDaniel Henrique Barboza     cpu->cfg.pmp = true;
473e1d084a8SRahul Pathak     cpu->cfg.ext_icbom = true;
474e1d084a8SRahul Pathak     cpu->cfg.cbom_blocksize = 64;
475e1d084a8SRahul Pathak     cpu->cfg.cboz_blocksize = 64;
476e1d084a8SRahul Pathak     cpu->cfg.ext_icboz = true;
477e1d084a8SRahul Pathak     cpu->cfg.ext_smaia = true;
478e1d084a8SRahul Pathak     cpu->cfg.ext_ssaia = true;
479e1d084a8SRahul Pathak     cpu->cfg.ext_sscofpmf = true;
480e1d084a8SRahul Pathak     cpu->cfg.ext_sstc = true;
481e1d084a8SRahul Pathak     cpu->cfg.ext_svinval = true;
482e1d084a8SRahul Pathak     cpu->cfg.ext_svnapot = true;
483e1d084a8SRahul Pathak     cpu->cfg.ext_svpbmt = true;
484e1d084a8SRahul Pathak     cpu->cfg.ext_smstateen = true;
485e1d084a8SRahul Pathak     cpu->cfg.ext_zba = true;
486e1d084a8SRahul Pathak     cpu->cfg.ext_zbb = true;
487e1d084a8SRahul Pathak     cpu->cfg.ext_zbc = true;
488e1d084a8SRahul Pathak     cpu->cfg.ext_zbs = true;
489e1d084a8SRahul Pathak     cpu->cfg.ext_XVentanaCondOps = true;
490e1d084a8SRahul Pathak 
491e1d084a8SRahul Pathak     cpu->cfg.mvendorid = VEYRON_V1_MVENDORID;
492e1d084a8SRahul Pathak     cpu->cfg.marchid = VEYRON_V1_MARCHID;
493e1d084a8SRahul Pathak     cpu->cfg.mimpid = VEYRON_V1_MIMPID;
494e1d084a8SRahul Pathak 
495e1d084a8SRahul Pathak #ifndef CONFIG_USER_ONLY
496e1d084a8SRahul Pathak     set_satp_mode_max_supported(cpu, VM_1_10_SV48);
497e1d084a8SRahul Pathak #endif
498e1d084a8SRahul Pathak }
499e1d084a8SRahul Pathak 
500332dab68SFrédéric Pétrot static void rv128_base_cpu_init(Object *obj)
501332dab68SFrédéric Pétrot {
502332dab68SFrédéric Pétrot     if (qemu_tcg_mttcg_enabled()) {
503332dab68SFrédéric Pétrot         /* Missing 128-bit aligned atomics */
504332dab68SFrédéric Pétrot         error_report("128-bit RISC-V currently does not work with Multi "
505332dab68SFrédéric Pétrot                      "Threaded TCG. Please use: -accel tcg,thread=single");
506332dab68SFrédéric Pétrot         exit(EXIT_FAILURE);
507332dab68SFrédéric Pétrot     }
508332dab68SFrédéric Pétrot     CPURISCVState *env = &RISCV_CPU(obj)->env;
509332dab68SFrédéric Pétrot     /* We set this in the realise function */
510332dab68SFrédéric Pétrot     set_misa(env, MXL_RV128, 0);
511dd8f244fSDaniel Henrique Barboza     riscv_cpu_add_user_properties(obj);
51218800095SAnup Patel     /* Set latest version of privileged specification */
513b9a2b98eSDaniel Henrique Barboza     env->priv_ver = PRIV_VERSION_LATEST;
5146df3747aSAlexandre Ghiti #ifndef CONFIG_USER_ONLY
5156df3747aSAlexandre Ghiti     set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV57);
5166df3747aSAlexandre Ghiti #endif
517332dab68SFrédéric Pétrot }
518114baacaSAlistair Francis #else
519094b072cSAlistair Francis static void rv32_base_cpu_init(Object *obj)
520094b072cSAlistair Francis {
521094b072cSAlistair Francis     CPURISCVState *env = &RISCV_CPU(obj)->env;
522094b072cSAlistair Francis     /* We set this in the realise function */
523e91a7227SRichard Henderson     set_misa(env, MXL_RV32, 0);
524dd8f244fSDaniel Henrique Barboza     riscv_cpu_add_user_properties(obj);
52518800095SAnup Patel     /* Set latest version of privileged specification */
526b9a2b98eSDaniel Henrique Barboza     env->priv_ver = PRIV_VERSION_LATEST;
5276df3747aSAlexandre Ghiti #ifndef CONFIG_USER_ONLY
5286df3747aSAlexandre Ghiti     set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV32);
5296df3747aSAlexandre Ghiti #endif
530094b072cSAlistair Francis }
531094b072cSAlistair Francis 
532114baacaSAlistair Francis static void rv32_sifive_u_cpu_init(Object *obj)
533114baacaSAlistair Francis {
5347f0bdfb5SDaniel Henrique Barboza     RISCVCPU *cpu = RISCV_CPU(obj);
5357f0bdfb5SDaniel Henrique Barboza     CPURISCVState *env = &cpu->env;
536e91a7227SRichard Henderson     set_misa(env, MXL_RV32, RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
5378c6eeb50SDaniel Henrique Barboza     env->priv_ver = PRIV_VERSION_1_10_0;
5386df3747aSAlexandre Ghiti #ifndef CONFIG_USER_ONLY
5396df3747aSAlexandre Ghiti     set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV32);
5406df3747aSAlexandre Ghiti #endif
5417f0bdfb5SDaniel Henrique Barboza 
5427f0bdfb5SDaniel Henrique Barboza     /* inherited from parent obj via riscv_cpu_init() */
5437f0bdfb5SDaniel Henrique Barboza     cpu->cfg.ext_ifencei = true;
5447f0bdfb5SDaniel Henrique Barboza     cpu->cfg.ext_icsr = true;
5457f0bdfb5SDaniel Henrique Barboza     cpu->cfg.mmu = true;
5467f0bdfb5SDaniel Henrique Barboza     cpu->cfg.pmp = true;
547114baacaSAlistair Francis }
548d8e72bd1SBin Meng 
549114baacaSAlistair Francis static void rv32_sifive_e_cpu_init(Object *obj)
550114baacaSAlistair Francis {
551114baacaSAlistair Francis     CPURISCVState *env = &RISCV_CPU(obj)->env;
55226b2bc58SAlistair Francis     RISCVCPU *cpu = RISCV_CPU(obj);
55326b2bc58SAlistair Francis 
554e91a7227SRichard Henderson     set_misa(env, MXL_RV32, RVI | RVM | RVA | RVC | RVU);
5558c6eeb50SDaniel Henrique Barboza     env->priv_ver = PRIV_VERSION_1_10_0;
5566df3747aSAlexandre Ghiti #ifndef CONFIG_USER_ONLY
5576df3747aSAlexandre Ghiti     set_satp_mode_max_supported(cpu, VM_1_10_MBARE);
5586df3747aSAlexandre Ghiti #endif
5597f0bdfb5SDaniel Henrique Barboza 
5607f0bdfb5SDaniel Henrique Barboza     /* inherited from parent obj via riscv_cpu_init() */
5617f0bdfb5SDaniel Henrique Barboza     cpu->cfg.ext_ifencei = true;
5627f0bdfb5SDaniel Henrique Barboza     cpu->cfg.ext_icsr = true;
5637f0bdfb5SDaniel Henrique Barboza     cpu->cfg.pmp = true;
564114baacaSAlistair Francis }
5654c56793fSBin Meng 
566e8905c6cSBin Meng static void rv32_ibex_cpu_init(Object *obj)
56736b80ad9SAlistair Francis {
56836b80ad9SAlistair Francis     CPURISCVState *env = &RISCV_CPU(obj)->env;
56926b2bc58SAlistair Francis     RISCVCPU *cpu = RISCV_CPU(obj);
57026b2bc58SAlistair Francis 
571e91a7227SRichard Henderson     set_misa(env, MXL_RV32, RVI | RVM | RVC | RVU);
5728c6eeb50SDaniel Henrique Barboza     env->priv_ver = PRIV_VERSION_1_11_0;
5736df3747aSAlexandre Ghiti #ifndef CONFIG_USER_ONLY
5746df3747aSAlexandre Ghiti     set_satp_mode_max_supported(cpu, VM_1_10_MBARE);
5756df3747aSAlexandre Ghiti #endif
57626b2bc58SAlistair Francis     cpu->cfg.epmp = true;
5777f0bdfb5SDaniel Henrique Barboza 
5787f0bdfb5SDaniel Henrique Barboza     /* inherited from parent obj via riscv_cpu_init() */
5797f0bdfb5SDaniel Henrique Barboza     cpu->cfg.ext_ifencei = true;
5807f0bdfb5SDaniel Henrique Barboza     cpu->cfg.ext_icsr = true;
5817f0bdfb5SDaniel Henrique Barboza     cpu->cfg.pmp = true;
58236b80ad9SAlistair Francis }
58336b80ad9SAlistair Francis 
5842fdd2c09SBin Meng static void rv32_imafcu_nommu_cpu_init(Object *obj)
585d784733bSCorey Wharton {
586d784733bSCorey Wharton     CPURISCVState *env = &RISCV_CPU(obj)->env;
58726b2bc58SAlistair Francis     RISCVCPU *cpu = RISCV_CPU(obj);
58826b2bc58SAlistair Francis 
589e91a7227SRichard Henderson     set_misa(env, MXL_RV32, RVI | RVM | RVA | RVF | RVC | RVU);
5908c6eeb50SDaniel Henrique Barboza     env->priv_ver = PRIV_VERSION_1_10_0;
5916df3747aSAlexandre Ghiti #ifndef CONFIG_USER_ONLY
5926df3747aSAlexandre Ghiti     set_satp_mode_max_supported(cpu, VM_1_10_MBARE);
5936df3747aSAlexandre Ghiti #endif
5947f0bdfb5SDaniel Henrique Barboza 
5957f0bdfb5SDaniel Henrique Barboza     /* inherited from parent obj via riscv_cpu_init() */
5967f0bdfb5SDaniel Henrique Barboza     cpu->cfg.ext_ifencei = true;
5977f0bdfb5SDaniel Henrique Barboza     cpu->cfg.ext_icsr = true;
5987f0bdfb5SDaniel Henrique Barboza     cpu->cfg.pmp = true;
599d784733bSCorey Wharton }
600eab15862SMichael Clark #endif
601dc5bd18fSMichael Clark 
60210f1ca27SYifei Jiang #if defined(CONFIG_KVM)
60310f1ca27SYifei Jiang static void riscv_host_cpu_init(Object *obj)
60410f1ca27SYifei Jiang {
60510f1ca27SYifei Jiang     CPURISCVState *env = &RISCV_CPU(obj)->env;
60610f1ca27SYifei Jiang #if defined(TARGET_RISCV32)
60710f1ca27SYifei Jiang     set_misa(env, MXL_RV32, 0);
60810f1ca27SYifei Jiang #elif defined(TARGET_RISCV64)
60910f1ca27SYifei Jiang     set_misa(env, MXL_RV64, 0);
61010f1ca27SYifei Jiang #endif
611dd8f244fSDaniel Henrique Barboza     riscv_cpu_add_user_properties(obj);
61210f1ca27SYifei Jiang }
6139638cbdeSPhilippe Mathieu-Daudé #endif /* CONFIG_KVM */
61410f1ca27SYifei Jiang 
615dc5bd18fSMichael Clark static ObjectClass *riscv_cpu_class_by_name(const char *cpu_model)
616dc5bd18fSMichael Clark {
617dc5bd18fSMichael Clark     ObjectClass *oc;
618dc5bd18fSMichael Clark     char *typename;
619dc5bd18fSMichael Clark     char **cpuname;
620dc5bd18fSMichael Clark 
621dc5bd18fSMichael Clark     cpuname = g_strsplit(cpu_model, ",", 1);
622dc5bd18fSMichael Clark     typename = g_strdup_printf(RISCV_CPU_TYPE_NAME("%s"), cpuname[0]);
623dc5bd18fSMichael Clark     oc = object_class_by_name(typename);
624dc5bd18fSMichael Clark     g_strfreev(cpuname);
625dc5bd18fSMichael Clark     g_free(typename);
626dc5bd18fSMichael Clark     if (!oc || !object_class_dynamic_cast(oc, TYPE_RISCV_CPU) ||
627dc5bd18fSMichael Clark         object_class_is_abstract(oc)) {
628dc5bd18fSMichael Clark         return NULL;
629dc5bd18fSMichael Clark     }
630dc5bd18fSMichael Clark     return oc;
631dc5bd18fSMichael Clark }
632dc5bd18fSMichael Clark 
63390c84c56SMarkus Armbruster static void riscv_cpu_dump_state(CPUState *cs, FILE *f, int flags)
634dc5bd18fSMichael Clark {
635dc5bd18fSMichael Clark     RISCVCPU *cpu = RISCV_CPU(cs);
636dc5bd18fSMichael Clark     CPURISCVState *env = &cpu->env;
637b227f6a8SIvan Klokov     int i, j;
638b227f6a8SIvan Klokov     uint8_t *p;
639dc5bd18fSMichael Clark 
640df30e652SAlistair Francis #if !defined(CONFIG_USER_ONLY)
641df30e652SAlistair Francis     if (riscv_has_ext(env, RVH)) {
64238256529SWeiwei Li         qemu_fprintf(f, " %s %d\n", "V      =  ", env->virt_enabled);
643df30e652SAlistair Francis     }
644df30e652SAlistair Francis #endif
64590c84c56SMarkus Armbruster     qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "pc      ", env->pc);
646dc5bd18fSMichael Clark #ifndef CONFIG_USER_ONLY
647665b90d8SRichard Henderson     {
648665b90d8SRichard Henderson         static const int dump_csrs[] = {
649665b90d8SRichard Henderson             CSR_MHARTID,
650665b90d8SRichard Henderson             CSR_MSTATUS,
651665b90d8SRichard Henderson             CSR_MSTATUSH,
652bc7dca13SBin Meng             /*
653bc7dca13SBin Meng              * CSR_SSTATUS is intentionally omitted here as its value
654bc7dca13SBin Meng              * can be figured out by looking at CSR_MSTATUS
655bc7dca13SBin Meng              */
656665b90d8SRichard Henderson             CSR_HSTATUS,
657665b90d8SRichard Henderson             CSR_VSSTATUS,
658665b90d8SRichard Henderson             CSR_MIP,
659665b90d8SRichard Henderson             CSR_MIE,
660665b90d8SRichard Henderson             CSR_MIDELEG,
661665b90d8SRichard Henderson             CSR_HIDELEG,
662665b90d8SRichard Henderson             CSR_MEDELEG,
663665b90d8SRichard Henderson             CSR_HEDELEG,
664665b90d8SRichard Henderson             CSR_MTVEC,
665665b90d8SRichard Henderson             CSR_STVEC,
666665b90d8SRichard Henderson             CSR_VSTVEC,
667665b90d8SRichard Henderson             CSR_MEPC,
668665b90d8SRichard Henderson             CSR_SEPC,
669665b90d8SRichard Henderson             CSR_VSEPC,
670665b90d8SRichard Henderson             CSR_MCAUSE,
671665b90d8SRichard Henderson             CSR_SCAUSE,
672665b90d8SRichard Henderson             CSR_VSCAUSE,
673665b90d8SRichard Henderson             CSR_MTVAL,
674665b90d8SRichard Henderson             CSR_STVAL,
675665b90d8SRichard Henderson             CSR_HTVAL,
676665b90d8SRichard Henderson             CSR_MTVAL2,
677665b90d8SRichard Henderson             CSR_MSCRATCH,
678665b90d8SRichard Henderson             CSR_SSCRATCH,
679665b90d8SRichard Henderson             CSR_SATP,
680bd5594caSAlexey Baturo             CSR_MMTE,
681bd5594caSAlexey Baturo             CSR_UPMBASE,
682bd5594caSAlexey Baturo             CSR_UPMMASK,
683bd5594caSAlexey Baturo             CSR_SPMBASE,
684bd5594caSAlexey Baturo             CSR_SPMMASK,
685bd5594caSAlexey Baturo             CSR_MPMBASE,
686bd5594caSAlexey Baturo             CSR_MPMMASK,
687665b90d8SRichard Henderson         };
688665b90d8SRichard Henderson 
689665b90d8SRichard Henderson         for (int i = 0; i < ARRAY_SIZE(dump_csrs); ++i) {
690665b90d8SRichard Henderson             int csrno = dump_csrs[i];
691665b90d8SRichard Henderson             target_ulong val = 0;
692665b90d8SRichard Henderson             RISCVException res = riscv_csrrw_debug(env, csrno, &val, 0, 0);
693665b90d8SRichard Henderson 
694665b90d8SRichard Henderson             /*
695665b90d8SRichard Henderson              * Rely on the smode, hmode, etc, predicates within csr.c
696665b90d8SRichard Henderson              * to do the filtering of the registers that are present.
697665b90d8SRichard Henderson              */
698665b90d8SRichard Henderson             if (res == RISCV_EXCP_NONE) {
699665b90d8SRichard Henderson                 qemu_fprintf(f, " %-8s " TARGET_FMT_lx "\n",
700665b90d8SRichard Henderson                              csr_ops[csrno].name, val);
7015c5a47f1SAlistair Francis             }
702df30e652SAlistair Francis         }
703df30e652SAlistair Francis     }
704dc5bd18fSMichael Clark #endif
705dc5bd18fSMichael Clark 
706dc5bd18fSMichael Clark     for (i = 0; i < 32; i++) {
707e573a7f3STravis Geiselbrecht         qemu_fprintf(f, " %-8s " TARGET_FMT_lx,
708dc5bd18fSMichael Clark                      riscv_int_regnames[i], env->gpr[i]);
709dc5bd18fSMichael Clark         if ((i & 3) == 3) {
71090c84c56SMarkus Armbruster             qemu_fprintf(f, "\n");
711dc5bd18fSMichael Clark         }
712dc5bd18fSMichael Clark     }
71386ea1880SRichard Henderson     if (flags & CPU_DUMP_FPU) {
714dc5bd18fSMichael Clark         for (i = 0; i < 32; i++) {
715e573a7f3STravis Geiselbrecht             qemu_fprintf(f, " %-8s %016" PRIx64,
716dc5bd18fSMichael Clark                          riscv_fpr_regnames[i], env->fpr[i]);
717dc5bd18fSMichael Clark             if ((i & 3) == 3) {
71890c84c56SMarkus Armbruster                 qemu_fprintf(f, "\n");
719dc5bd18fSMichael Clark             }
720dc5bd18fSMichael Clark         }
721dc5bd18fSMichael Clark     }
722b227f6a8SIvan Klokov     if (riscv_has_ext(env, RVV) && (flags & CPU_DUMP_VPU)) {
723b227f6a8SIvan Klokov         static const int dump_rvv_csrs[] = {
724b227f6a8SIvan Klokov                     CSR_VSTART,
725b227f6a8SIvan Klokov                     CSR_VXSAT,
726b227f6a8SIvan Klokov                     CSR_VXRM,
727b227f6a8SIvan Klokov                     CSR_VCSR,
728b227f6a8SIvan Klokov                     CSR_VL,
729b227f6a8SIvan Klokov                     CSR_VTYPE,
730b227f6a8SIvan Klokov                     CSR_VLENB,
731b227f6a8SIvan Klokov                 };
732b227f6a8SIvan Klokov         for (int i = 0; i < ARRAY_SIZE(dump_rvv_csrs); ++i) {
733b227f6a8SIvan Klokov             int csrno = dump_rvv_csrs[i];
734b227f6a8SIvan Klokov             target_ulong val = 0;
735b227f6a8SIvan Klokov             RISCVException res = riscv_csrrw_debug(env, csrno, &val, 0, 0);
736b227f6a8SIvan Klokov 
737b227f6a8SIvan Klokov             /*
738b227f6a8SIvan Klokov              * Rely on the smode, hmode, etc, predicates within csr.c
739b227f6a8SIvan Klokov              * to do the filtering of the registers that are present.
740b227f6a8SIvan Klokov              */
741b227f6a8SIvan Klokov             if (res == RISCV_EXCP_NONE) {
742b227f6a8SIvan Klokov                 qemu_fprintf(f, " %-8s " TARGET_FMT_lx "\n",
743b227f6a8SIvan Klokov                              csr_ops[csrno].name, val);
744b227f6a8SIvan Klokov             }
745b227f6a8SIvan Klokov         }
746b227f6a8SIvan Klokov         uint16_t vlenb = cpu->cfg.vlen >> 3;
747b227f6a8SIvan Klokov 
748b227f6a8SIvan Klokov         for (i = 0; i < 32; i++) {
749b227f6a8SIvan Klokov             qemu_fprintf(f, " %-8s ", riscv_rvv_regnames[i]);
750b227f6a8SIvan Klokov             p = (uint8_t *)env->vreg;
751b227f6a8SIvan Klokov             for (j = vlenb - 1 ; j >= 0; j--) {
752b227f6a8SIvan Klokov                 qemu_fprintf(f, "%02x", *(p + i * vlenb + BYTE(j)));
753b227f6a8SIvan Klokov             }
754b227f6a8SIvan Klokov             qemu_fprintf(f, "\n");
755b227f6a8SIvan Klokov         }
756b227f6a8SIvan Klokov     }
75786ea1880SRichard Henderson }
758dc5bd18fSMichael Clark 
759dc5bd18fSMichael Clark static void riscv_cpu_set_pc(CPUState *cs, vaddr value)
760dc5bd18fSMichael Clark {
761dc5bd18fSMichael Clark     RISCVCPU *cpu = RISCV_CPU(cs);
762dc5bd18fSMichael Clark     CPURISCVState *env = &cpu->env;
763bf9e776eSLIU Zhiwei 
764bf9e776eSLIU Zhiwei     if (env->xl == MXL_RV32) {
765bf9e776eSLIU Zhiwei         env->pc = (int32_t)value;
766bf9e776eSLIU Zhiwei     } else {
767dc5bd18fSMichael Clark         env->pc = value;
768dc5bd18fSMichael Clark     }
769bf9e776eSLIU Zhiwei }
770dc5bd18fSMichael Clark 
771e4fdf9dfSRichard Henderson static vaddr riscv_cpu_get_pc(CPUState *cs)
772e4fdf9dfSRichard Henderson {
773e4fdf9dfSRichard Henderson     RISCVCPU *cpu = RISCV_CPU(cs);
774e4fdf9dfSRichard Henderson     CPURISCVState *env = &cpu->env;
775e4fdf9dfSRichard Henderson 
776e4fdf9dfSRichard Henderson     /* Match cpu_get_tb_cpu_state. */
777e4fdf9dfSRichard Henderson     if (env->xl == MXL_RV32) {
778e4fdf9dfSRichard Henderson         return env->pc & UINT32_MAX;
779e4fdf9dfSRichard Henderson     }
780e4fdf9dfSRichard Henderson     return env->pc;
781e4fdf9dfSRichard Henderson }
782e4fdf9dfSRichard Henderson 
78304a37d4cSRichard Henderson static void riscv_cpu_synchronize_from_tb(CPUState *cs,
78404a37d4cSRichard Henderson                                           const TranslationBlock *tb)
785dc5bd18fSMichael Clark {
786356c13f9SWeiwei Li     if (!(tb_cflags(tb) & CF_PCREL)) {
787dc5bd18fSMichael Clark         RISCVCPU *cpu = RISCV_CPU(cs);
788dc5bd18fSMichael Clark         CPURISCVState *env = &cpu->env;
789bf9e776eSLIU Zhiwei         RISCVMXL xl = FIELD_EX32(tb->flags, TB_FLAGS, XL);
790bf9e776eSLIU Zhiwei 
7910489d5bdSAnton Johansson         tcg_debug_assert(!(cs->tcg_cflags & CF_PCREL));
7920489d5bdSAnton Johansson 
793bf9e776eSLIU Zhiwei         if (xl == MXL_RV32) {
7940489d5bdSAnton Johansson             env->pc = (int32_t) tb->pc;
795bf9e776eSLIU Zhiwei         } else {
7960489d5bdSAnton Johansson             env->pc = tb->pc;
797dc5bd18fSMichael Clark         }
798bf9e776eSLIU Zhiwei     }
799356c13f9SWeiwei Li }
800dc5bd18fSMichael Clark 
801dc5bd18fSMichael Clark static bool riscv_cpu_has_work(CPUState *cs)
802dc5bd18fSMichael Clark {
803dc5bd18fSMichael Clark #ifndef CONFIG_USER_ONLY
804dc5bd18fSMichael Clark     RISCVCPU *cpu = RISCV_CPU(cs);
805dc5bd18fSMichael Clark     CPURISCVState *env = &cpu->env;
806dc5bd18fSMichael Clark     /*
807dc5bd18fSMichael Clark      * Definition of the WFI instruction requires it to ignore the privilege
808dc5bd18fSMichael Clark      * mode and delegation registers, but respect individual enables
809dc5bd18fSMichael Clark      */
8108f42415fSAndrew Bresticker     return riscv_cpu_all_pending(env) != 0;
811dc5bd18fSMichael Clark #else
812dc5bd18fSMichael Clark     return true;
813dc5bd18fSMichael Clark #endif
814dc5bd18fSMichael Clark }
815dc5bd18fSMichael Clark 
816ad1e84f5SRichard Henderson static void riscv_restore_state_to_opc(CPUState *cs,
817ad1e84f5SRichard Henderson                                        const TranslationBlock *tb,
818ad1e84f5SRichard Henderson                                        const uint64_t *data)
819dc5bd18fSMichael Clark {
820ad1e84f5SRichard Henderson     RISCVCPU *cpu = RISCV_CPU(cs);
821ad1e84f5SRichard Henderson     CPURISCVState *env = &cpu->env;
822bf9e776eSLIU Zhiwei     RISCVMXL xl = FIELD_EX32(tb->flags, TB_FLAGS, XL);
823356c13f9SWeiwei Li     target_ulong pc;
824356c13f9SWeiwei Li 
825356c13f9SWeiwei Li     if (tb_cflags(tb) & CF_PCREL) {
826356c13f9SWeiwei Li         pc = (env->pc & TARGET_PAGE_MASK) | data[0];
827356c13f9SWeiwei Li     } else {
828356c13f9SWeiwei Li         pc = data[0];
829356c13f9SWeiwei Li     }
830ad1e84f5SRichard Henderson 
831bf9e776eSLIU Zhiwei     if (xl == MXL_RV32) {
832356c13f9SWeiwei Li         env->pc = (int32_t)pc;
833bf9e776eSLIU Zhiwei     } else {
834356c13f9SWeiwei Li         env->pc = pc;
835dc5bd18fSMichael Clark     }
83662cf0245SAnup Patel     env->bins = data[1];
837bf9e776eSLIU Zhiwei }
838dc5bd18fSMichael Clark 
8394fa485a7SPeter Maydell static void riscv_cpu_reset_hold(Object *obj)
840dc5bd18fSMichael Clark {
84143dc93afSAnup Patel #ifndef CONFIG_USER_ONLY
84243dc93afSAnup Patel     uint8_t iprio;
84343dc93afSAnup Patel     int i, irq, rdzero;
84443dc93afSAnup Patel #endif
8454fa485a7SPeter Maydell     CPUState *cs = CPU(obj);
846dc5bd18fSMichael Clark     RISCVCPU *cpu = RISCV_CPU(cs);
847dc5bd18fSMichael Clark     RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(cpu);
848dc5bd18fSMichael Clark     CPURISCVState *env = &cpu->env;
849dc5bd18fSMichael Clark 
8504fa485a7SPeter Maydell     if (mcc->parent_phases.hold) {
8514fa485a7SPeter Maydell         mcc->parent_phases.hold(obj);
8524fa485a7SPeter Maydell     }
853dc5bd18fSMichael Clark #ifndef CONFIG_USER_ONLY
854e91a7227SRichard Henderson     env->misa_mxl = env->misa_mxl_max;
855dc5bd18fSMichael Clark     env->priv = PRV_M;
856dc5bd18fSMichael Clark     env->mstatus &= ~(MSTATUS_MIE | MSTATUS_MPRV);
85792371bd9SRichard Henderson     if (env->misa_mxl > MXL_RV32) {
85892371bd9SRichard Henderson         /*
85992371bd9SRichard Henderson          * The reset status of SXL/UXL is undefined, but mstatus is WARL
86092371bd9SRichard Henderson          * and we must ensure that the value after init is valid for read.
86192371bd9SRichard Henderson          */
86292371bd9SRichard Henderson         env->mstatus = set_field(env->mstatus, MSTATUS64_SXL, env->misa_mxl);
86392371bd9SRichard Henderson         env->mstatus = set_field(env->mstatus, MSTATUS64_UXL, env->misa_mxl);
8645a2ae235SLIU Zhiwei         if (riscv_has_ext(env, RVH)) {
8655a2ae235SLIU Zhiwei             env->vsstatus = set_field(env->vsstatus,
8665a2ae235SLIU Zhiwei                                       MSTATUS64_SXL, env->misa_mxl);
8675a2ae235SLIU Zhiwei             env->vsstatus = set_field(env->vsstatus,
8685a2ae235SLIU Zhiwei                                       MSTATUS64_UXL, env->misa_mxl);
8695a2ae235SLIU Zhiwei             env->mstatus_hs = set_field(env->mstatus_hs,
8705a2ae235SLIU Zhiwei                                         MSTATUS64_SXL, env->misa_mxl);
8715a2ae235SLIU Zhiwei             env->mstatus_hs = set_field(env->mstatus_hs,
8725a2ae235SLIU Zhiwei                                         MSTATUS64_UXL, env->misa_mxl);
8735a2ae235SLIU Zhiwei         }
87492371bd9SRichard Henderson     }
875dc5bd18fSMichael Clark     env->mcause = 0;
876881df35dSAnup Patel     env->miclaim = MIP_SGEIP;
877dc5bd18fSMichael Clark     env->pc = env->resetvec;
87862cf0245SAnup Patel     env->bins = 0;
879ec352d0cSGeorg Kotheimer     env->two_stage_lookup = false;
88043dc93afSAnup Patel 
8810af3f115SWeiwei Li     env->menvcfg = (cpu->cfg.ext_svpbmt ? MENVCFG_PBMTE : 0) |
8820af3f115SWeiwei Li                    (cpu->cfg.ext_svadu ? MENVCFG_HADE : 0);
8830af3f115SWeiwei Li     env->henvcfg = (cpu->cfg.ext_svpbmt ? HENVCFG_PBMTE : 0) |
8840af3f115SWeiwei Li                    (cpu->cfg.ext_svadu ? HENVCFG_HADE : 0);
8857a6613daSWeiwei Li 
88643dc93afSAnup Patel     /* Initialized default priorities of local interrupts. */
88743dc93afSAnup Patel     for (i = 0; i < ARRAY_SIZE(env->miprio); i++) {
88843dc93afSAnup Patel         iprio = riscv_cpu_default_priority(i);
88943dc93afSAnup Patel         env->miprio[i] = (i == IRQ_M_EXT) ? 0 : iprio;
89043dc93afSAnup Patel         env->siprio[i] = (i == IRQ_S_EXT) ? 0 : iprio;
89143dc93afSAnup Patel         env->hviprio[i] = 0;
89243dc93afSAnup Patel     }
89343dc93afSAnup Patel     i = 0;
89443dc93afSAnup Patel     while (!riscv_cpu_hviprio_index2irq(i, &irq, &rdzero)) {
89543dc93afSAnup Patel         if (!rdzero) {
89643dc93afSAnup Patel             env->hviprio[irq] = env->miprio[irq];
89743dc93afSAnup Patel         }
89843dc93afSAnup Patel         i++;
89943dc93afSAnup Patel     }
9004bbe8033SAlexey Baturo     /* mmte is supposed to have pm.current hardwired to 1 */
90142967f40SLIU Zhiwei     env->mmte |= (EXT_STATUS_INITIAL | MMTE_M_PM_CURRENT);
902dc5bd18fSMichael Clark #endif
903440544e1SLIU Zhiwei     env->xl = riscv_cpu_mxl(env);
90440bfa5f6SLIU Zhiwei     riscv_cpu_update_mask(env);
905330d2ae3SAlistair Francis     cs->exception_index = RISCV_EXCP_NONE;
906c13b169fSJoel Sing     env->load_res = -1;
907dc5bd18fSMichael Clark     set_default_nan_mode(1, &env->fp_status);
908ad40be27SYifei Jiang 
909ad40be27SYifei Jiang #ifndef CONFIG_USER_ONLY
910cdfb2905SDaniel Henrique Barboza     if (cpu->cfg.debug) {
911b6092544SBin Meng         riscv_trigger_init(env);
912b6092544SBin Meng     }
913b6092544SBin Meng 
914ad40be27SYifei Jiang     if (kvm_enabled()) {
915ad40be27SYifei Jiang         kvm_riscv_reset_vcpu(cpu);
916ad40be27SYifei Jiang     }
917ad40be27SYifei Jiang #endif
918dc5bd18fSMichael Clark }
919dc5bd18fSMichael Clark 
920dc5bd18fSMichael Clark static void riscv_cpu_disas_set_info(CPUState *s, disassemble_info *info)
921dc5bd18fSMichael Clark {
9225c5a47f1SAlistair Francis     RISCVCPU *cpu = RISCV_CPU(s);
92394692c3aSLIU Zhiwei     CPURISCVState *env = &cpu->env;
924454c2201SWeiwei Li     info->target_info = &cpu->cfg;
925db23e5d9SRichard Henderson 
92694692c3aSLIU Zhiwei     switch (env->xl) {
927db23e5d9SRichard Henderson     case MXL_RV32:
928dc5bd18fSMichael Clark         info->print_insn = print_insn_riscv32;
929db23e5d9SRichard Henderson         break;
930db23e5d9SRichard Henderson     case MXL_RV64:
931dc5bd18fSMichael Clark         info->print_insn = print_insn_riscv64;
932db23e5d9SRichard Henderson         break;
933332dab68SFrédéric Pétrot     case MXL_RV128:
934332dab68SFrédéric Pétrot         info->print_insn = print_insn_riscv128;
935332dab68SFrédéric Pétrot         break;
936db23e5d9SRichard Henderson     default:
937db23e5d9SRichard Henderson         g_assert_not_reached();
9385c5a47f1SAlistair Francis     }
939dc5bd18fSMichael Clark }
940dc5bd18fSMichael Clark 
941d63be184SDaniel Henrique Barboza static void riscv_cpu_validate_v(CPURISCVState *env, RISCVCPUConfig *cfg,
942d63be184SDaniel Henrique Barboza                                  Error **errp)
943d63be184SDaniel Henrique Barboza {
944d63be184SDaniel Henrique Barboza     int vext_version = VEXT_VERSION_1_00_0;
945d63be184SDaniel Henrique Barboza 
946d63be184SDaniel Henrique Barboza     if (!is_power_of_2(cfg->vlen)) {
947d63be184SDaniel Henrique Barboza         error_setg(errp, "Vector extension VLEN must be power of 2");
948d63be184SDaniel Henrique Barboza         return;
949d63be184SDaniel Henrique Barboza     }
950d63be184SDaniel Henrique Barboza     if (cfg->vlen > RV_VLEN_MAX || cfg->vlen < 128) {
951d63be184SDaniel Henrique Barboza         error_setg(errp,
952d63be184SDaniel Henrique Barboza                    "Vector extension implementation only supports VLEN "
953d63be184SDaniel Henrique Barboza                    "in the range [128, %d]", RV_VLEN_MAX);
954d63be184SDaniel Henrique Barboza         return;
955d63be184SDaniel Henrique Barboza     }
956d63be184SDaniel Henrique Barboza     if (!is_power_of_2(cfg->elen)) {
957d63be184SDaniel Henrique Barboza         error_setg(errp, "Vector extension ELEN must be power of 2");
958d63be184SDaniel Henrique Barboza         return;
959d63be184SDaniel Henrique Barboza     }
960d63be184SDaniel Henrique Barboza     if (cfg->elen > 64 || cfg->elen < 8) {
961d63be184SDaniel Henrique Barboza         error_setg(errp,
962d63be184SDaniel Henrique Barboza                    "Vector extension implementation only supports ELEN "
963d63be184SDaniel Henrique Barboza                    "in the range [8, 64]");
964d63be184SDaniel Henrique Barboza         return;
965d63be184SDaniel Henrique Barboza     }
966d63be184SDaniel Henrique Barboza     if (cfg->vext_spec) {
967d63be184SDaniel Henrique Barboza         if (!g_strcmp0(cfg->vext_spec, "v1.0")) {
968d63be184SDaniel Henrique Barboza             vext_version = VEXT_VERSION_1_00_0;
969d63be184SDaniel Henrique Barboza         } else {
970d63be184SDaniel Henrique Barboza             error_setg(errp, "Unsupported vector spec version '%s'",
971d63be184SDaniel Henrique Barboza                        cfg->vext_spec);
972d63be184SDaniel Henrique Barboza             return;
973d63be184SDaniel Henrique Barboza         }
974d63be184SDaniel Henrique Barboza     } else {
975d63be184SDaniel Henrique Barboza         qemu_log("vector version is not specified, "
976d63be184SDaniel Henrique Barboza                  "use the default value v1.0\n");
977d63be184SDaniel Henrique Barboza     }
9782238c9d1SDaniel Henrique Barboza     env->vext_ver = vext_version;
979d63be184SDaniel Henrique Barboza }
980d63be184SDaniel Henrique Barboza 
981bd305595SDaniel Henrique Barboza static void riscv_cpu_validate_priv_spec(RISCVCPU *cpu, Error **errp)
982bd305595SDaniel Henrique Barboza {
983bd305595SDaniel Henrique Barboza     CPURISCVState *env = &cpu->env;
984bd305595SDaniel Henrique Barboza     int priv_version = -1;
985bd305595SDaniel Henrique Barboza 
986bd305595SDaniel Henrique Barboza     if (cpu->cfg.priv_spec) {
987bd305595SDaniel Henrique Barboza         if (!g_strcmp0(cpu->cfg.priv_spec, "v1.12.0")) {
988bd305595SDaniel Henrique Barboza             priv_version = PRIV_VERSION_1_12_0;
989bd305595SDaniel Henrique Barboza         } else if (!g_strcmp0(cpu->cfg.priv_spec, "v1.11.0")) {
990bd305595SDaniel Henrique Barboza             priv_version = PRIV_VERSION_1_11_0;
991bd305595SDaniel Henrique Barboza         } else if (!g_strcmp0(cpu->cfg.priv_spec, "v1.10.0")) {
992bd305595SDaniel Henrique Barboza             priv_version = PRIV_VERSION_1_10_0;
993bd305595SDaniel Henrique Barboza         } else {
994bd305595SDaniel Henrique Barboza             error_setg(errp,
995bd305595SDaniel Henrique Barboza                        "Unsupported privilege spec version '%s'",
996bd305595SDaniel Henrique Barboza                        cpu->cfg.priv_spec);
997bd305595SDaniel Henrique Barboza             return;
998bd305595SDaniel Henrique Barboza         }
999bd305595SDaniel Henrique Barboza 
1000bd305595SDaniel Henrique Barboza         env->priv_ver = priv_version;
1001bd305595SDaniel Henrique Barboza     }
1002bd305595SDaniel Henrique Barboza }
1003bd305595SDaniel Henrique Barboza 
1004bd305595SDaniel Henrique Barboza static void riscv_cpu_disable_priv_spec_isa_exts(RISCVCPU *cpu)
1005bd305595SDaniel Henrique Barboza {
1006bd305595SDaniel Henrique Barboza     CPURISCVState *env = &cpu->env;
1007bd305595SDaniel Henrique Barboza     int i;
1008bd305595SDaniel Henrique Barboza 
1009bd305595SDaniel Henrique Barboza     /* Force disable extensions if priv spec version does not match */
1010bd305595SDaniel Henrique Barboza     for (i = 0; i < ARRAY_SIZE(isa_edata_arr); i++) {
1011bd305595SDaniel Henrique Barboza         if (isa_ext_is_enabled(cpu, &isa_edata_arr[i]) &&
1012bd305595SDaniel Henrique Barboza             (env->priv_ver < isa_edata_arr[i].min_version)) {
1013bd305595SDaniel Henrique Barboza             isa_ext_update_enabled(cpu, &isa_edata_arr[i], false);
1014bd305595SDaniel Henrique Barboza #ifndef CONFIG_USER_ONLY
1015bd305595SDaniel Henrique Barboza             warn_report("disabling %s extension for hart 0x" TARGET_FMT_lx
1016bd305595SDaniel Henrique Barboza                         " because privilege spec version does not match",
1017bd305595SDaniel Henrique Barboza                         isa_edata_arr[i].name, env->mhartid);
1018bd305595SDaniel Henrique Barboza #else
1019bd305595SDaniel Henrique Barboza             warn_report("disabling %s extension because "
1020bd305595SDaniel Henrique Barboza                         "privilege spec version does not match",
1021bd305595SDaniel Henrique Barboza                         isa_edata_arr[i].name);
1022bd305595SDaniel Henrique Barboza #endif
1023bd305595SDaniel Henrique Barboza         }
1024bd305595SDaniel Henrique Barboza     }
1025bd305595SDaniel Henrique Barboza }
1026bd305595SDaniel Henrique Barboza 
1027f5664064SDaniel Henrique Barboza static void riscv_cpu_validate_misa_mxl(RISCVCPU *cpu, Error **errp)
1028f5664064SDaniel Henrique Barboza {
1029f5664064SDaniel Henrique Barboza     RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(cpu);
1030f5664064SDaniel Henrique Barboza     CPUClass *cc = CPU_CLASS(mcc);
1031f5664064SDaniel Henrique Barboza     CPURISCVState *env = &cpu->env;
1032f5664064SDaniel Henrique Barboza 
1033f5664064SDaniel Henrique Barboza     /* Validate that MISA_MXL is set properly. */
1034f5664064SDaniel Henrique Barboza     switch (env->misa_mxl_max) {
1035f5664064SDaniel Henrique Barboza #ifdef TARGET_RISCV64
1036f5664064SDaniel Henrique Barboza     case MXL_RV64:
1037f5664064SDaniel Henrique Barboza     case MXL_RV128:
1038f5664064SDaniel Henrique Barboza         cc->gdb_core_xml_file = "riscv-64bit-cpu.xml";
1039f5664064SDaniel Henrique Barboza         break;
1040f5664064SDaniel Henrique Barboza #endif
1041f5664064SDaniel Henrique Barboza     case MXL_RV32:
1042f5664064SDaniel Henrique Barboza         cc->gdb_core_xml_file = "riscv-32bit-cpu.xml";
1043f5664064SDaniel Henrique Barboza         break;
1044f5664064SDaniel Henrique Barboza     default:
1045f5664064SDaniel Henrique Barboza         g_assert_not_reached();
1046f5664064SDaniel Henrique Barboza     }
1047f5664064SDaniel Henrique Barboza 
1048f5664064SDaniel Henrique Barboza     if (env->misa_mxl_max != env->misa_mxl) {
1049f5664064SDaniel Henrique Barboza         error_setg(errp, "misa_mxl_max must be equal to misa_mxl");
1050f5664064SDaniel Henrique Barboza         return;
1051f5664064SDaniel Henrique Barboza     }
1052f5664064SDaniel Henrique Barboza }
1053f5664064SDaniel Henrique Barboza 
10545da9514eSHou Weiying /*
10555ab10952SDaniel Henrique Barboza  * Check consistency between chosen extensions while setting
10561ffa805cSDaniel Henrique Barboza  * cpu->cfg accordingly.
10575da9514eSHou Weiying  */
1058faf3b5d8SDaniel Henrique Barboza void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp)
10595ab10952SDaniel Henrique Barboza {
10605ab10952SDaniel Henrique Barboza     CPURISCVState *env = &cpu->env;
1061d63be184SDaniel Henrique Barboza     Error *local_err = NULL;
1062e91a7227SRichard Henderson 
1063b55d7d34SAlistair Francis     /* Do some ISA extension error checking */
10644f13abcbSDaniel Henrique Barboza     if (riscv_has_ext(env, RVG) &&
10654f13abcbSDaniel Henrique Barboza         !(riscv_has_ext(env, RVI) && riscv_has_ext(env, RVM) &&
10664f13abcbSDaniel Henrique Barboza           riscv_has_ext(env, RVA) && riscv_has_ext(env, RVF) &&
10674b33598fSDaniel Henrique Barboza           riscv_has_ext(env, RVD) &&
10689f6b7da5STsukasa OI           cpu->cfg.ext_icsr && cpu->cfg.ext_ifencei)) {
10699f6b7da5STsukasa OI         warn_report("Setting G will also set IMAFD_Zicsr_Zifencei");
10709f6b7da5STsukasa OI         cpu->cfg.ext_icsr = true;
10719f6b7da5STsukasa OI         cpu->cfg.ext_ifencei = true;
10721ffa805cSDaniel Henrique Barboza 
10731ffa805cSDaniel Henrique Barboza         env->misa_ext |= RVI | RVM | RVA | RVF | RVD;
1074faf3b5d8SDaniel Henrique Barboza         env->misa_ext_mask |= RVI | RVM | RVA | RVF | RVD;
1075b55d7d34SAlistair Francis     }
1076b55d7d34SAlistair Francis 
1077427d8e7dSDaniel Henrique Barboza     if (riscv_has_ext(env, RVI) && riscv_has_ext(env, RVE)) {
1078bb06941fSWeiwei Li         error_setg(errp,
1079bb06941fSWeiwei Li                    "I and E extensions are incompatible");
1080bb06941fSWeiwei Li         return;
1081bb06941fSWeiwei Li     }
1082bb06941fSWeiwei Li 
1083427d8e7dSDaniel Henrique Barboza     if (!riscv_has_ext(env, RVI) && !riscv_has_ext(env, RVE)) {
1084bb06941fSWeiwei Li         error_setg(errp,
1085bb06941fSWeiwei Li                    "Either I or E extension must be set");
1086bb06941fSWeiwei Li         return;
1087bb06941fSWeiwei Li     }
1088bb06941fSWeiwei Li 
1089e17801e1SDaniel Henrique Barboza     if (riscv_has_ext(env, RVS) && !riscv_has_ext(env, RVU)) {
10900b572c81SWeiwei Li         error_setg(errp,
10910b572c81SWeiwei Li                    "Setting S extension without U extension is illegal");
10920b572c81SWeiwei Li         return;
10930b572c81SWeiwei Li     }
10940b572c81SWeiwei Li 
1095b5c042e8SDaniel Henrique Barboza     if (riscv_has_ext(env, RVH) && !riscv_has_ext(env, RVI)) {
1096756b0374SWeiwei Li         error_setg(errp,
1097756b0374SWeiwei Li                    "H depends on an I base integer ISA with 32 x registers");
1098756b0374SWeiwei Li         return;
1099756b0374SWeiwei Li     }
1100756b0374SWeiwei Li 
1101b5c042e8SDaniel Henrique Barboza     if (riscv_has_ext(env, RVH) && !riscv_has_ext(env, RVS)) {
110262a09b9bSWeiwei Li         error_setg(errp, "H extension implicitly requires S-mode");
110362a09b9bSWeiwei Li         return;
110462a09b9bSWeiwei Li     }
110562a09b9bSWeiwei Li 
11064b33598fSDaniel Henrique Barboza     if (riscv_has_ext(env, RVF) && !cpu->cfg.ext_icsr) {
11071086504cSTsukasa OI         error_setg(errp, "F extension requires Zicsr");
11081086504cSTsukasa OI         return;
11091086504cSTsukasa OI     }
11101086504cSTsukasa OI 
11114c759943SDaniel Henrique Barboza     if ((cpu->cfg.ext_zawrs) && !riscv_has_ext(env, RVA)) {
1112260b594dSChristoph Muellner         error_setg(errp, "Zawrs extension requires A extension");
1113260b594dSChristoph Muellner         return;
1114260b594dSChristoph Muellner     }
1115260b594dSChristoph Muellner 
1116a47842d1SChristoph Müllner     if (cpu->cfg.ext_zfa && !riscv_has_ext(env, RVF)) {
1117a47842d1SChristoph Müllner         error_setg(errp, "Zfa extension requires F extension");
1118a47842d1SChristoph Müllner         return;
1119a47842d1SChristoph Müllner     }
1120a47842d1SChristoph Müllner 
11211d2cb5a8SWeiwei Li     if (cpu->cfg.ext_zfh) {
11221d2cb5a8SWeiwei Li         cpu->cfg.ext_zfhmin = true;
11231d2cb5a8SWeiwei Li     }
11241d2cb5a8SWeiwei Li 
11254b33598fSDaniel Henrique Barboza     if (cpu->cfg.ext_zfhmin && !riscv_has_ext(env, RVF)) {
11261086504cSTsukasa OI         error_setg(errp, "Zfh/Zfhmin extensions require F extension");
11271086504cSTsukasa OI         return;
11281086504cSTsukasa OI     }
11291086504cSTsukasa OI 
11304556fdaaSWeiwei Li     if (cpu->cfg.ext_zfbfmin && !riscv_has_ext(env, RVF)) {
11314556fdaaSWeiwei Li         error_setg(errp, "Zfbfmin extension depends on F extension");
11324556fdaaSWeiwei Li         return;
11334556fdaaSWeiwei Li     }
11344556fdaaSWeiwei Li 
11354b33598fSDaniel Henrique Barboza     if (riscv_has_ext(env, RVD) && !riscv_has_ext(env, RVF)) {
11361086504cSTsukasa OI         error_setg(errp, "D extension requires F extension");
11371086504cSTsukasa OI         return;
11381086504cSTsukasa OI     }
11391086504cSTsukasa OI 
11403e7674fdSDaniel Henrique Barboza     if (riscv_has_ext(env, RVV)) {
1141d63be184SDaniel Henrique Barboza         riscv_cpu_validate_v(env, &cpu->cfg, &local_err);
1142d63be184SDaniel Henrique Barboza         if (local_err != NULL) {
1143d63be184SDaniel Henrique Barboza             error_propagate(errp, local_err);
1144d63be184SDaniel Henrique Barboza             return;
1145d63be184SDaniel Henrique Barboza         }
1146d63be184SDaniel Henrique Barboza 
1147d63be184SDaniel Henrique Barboza         /* The V vector extension depends on the Zve64d extension */
1148e7f0a803SWeiwei Li         cpu->cfg.ext_zve64d = true;
1149e7f0a803SWeiwei Li     }
1150e7f0a803SWeiwei Li 
1151e7f0a803SWeiwei Li     /* The Zve64d extension depends on the Zve64f extension */
1152e7f0a803SWeiwei Li     if (cpu->cfg.ext_zve64d) {
1153e7f0a803SWeiwei Li         cpu->cfg.ext_zve64f = true;
1154e7f0a803SWeiwei Li     }
1155e7f0a803SWeiwei Li 
1156e7f0a803SWeiwei Li     /* The Zve64f extension depends on the Zve32f extension */
1157e7f0a803SWeiwei Li     if (cpu->cfg.ext_zve64f) {
1158e7f0a803SWeiwei Li         cpu->cfg.ext_zve32f = true;
1159e7f0a803SWeiwei Li     }
1160e7f0a803SWeiwei Li 
1161ffffd954SDaniel Henrique Barboza     if (cpu->cfg.ext_zve64d && !riscv_has_ext(env, RVD)) {
1162e7f0a803SWeiwei Li         error_setg(errp, "Zve64d/V extensions require D extension");
11631086504cSTsukasa OI         return;
11641086504cSTsukasa OI     }
11651086504cSTsukasa OI 
11664b33598fSDaniel Henrique Barboza     if (cpu->cfg.ext_zve32f && !riscv_has_ext(env, RVF)) {
1167bc573816STsukasa OI         error_setg(errp, "Zve32f/Zve64f extensions require F extension");
1168bc573816STsukasa OI         return;
1169bc573816STsukasa OI     }
1170bc573816STsukasa OI 
11712e60f9ecSWeiwei Li     if (cpu->cfg.ext_zvfh) {
11722e60f9ecSWeiwei Li         cpu->cfg.ext_zvfhmin = true;
11732e60f9ecSWeiwei Li     }
11742e60f9ecSWeiwei Li 
11752e60f9ecSWeiwei Li     if (cpu->cfg.ext_zvfhmin && !cpu->cfg.ext_zve32f) {
11762e60f9ecSWeiwei Li         error_setg(errp, "Zvfh/Zvfhmin extensions require Zve32f extension");
11772e60f9ecSWeiwei Li         return;
11782e60f9ecSWeiwei Li     }
11792e60f9ecSWeiwei Li 
11802e60f9ecSWeiwei Li     if (cpu->cfg.ext_zvfh && !cpu->cfg.ext_zfhmin) {
11812e60f9ecSWeiwei Li         error_setg(errp, "Zvfh extensions requires Zfhmin extension");
11822e60f9ecSWeiwei Li         return;
11832e60f9ecSWeiwei Li     }
11842e60f9ecSWeiwei Li 
11854556fdaaSWeiwei Li     if (cpu->cfg.ext_zvfbfmin && !cpu->cfg.ext_zfbfmin) {
11864556fdaaSWeiwei Li         error_setg(errp, "Zvfbfmin extension depends on Zfbfmin extension");
11874556fdaaSWeiwei Li         return;
11884556fdaaSWeiwei Li     }
11894556fdaaSWeiwei Li 
11904556fdaaSWeiwei Li     if (cpu->cfg.ext_zvfbfmin && !cpu->cfg.ext_zve32f) {
11914556fdaaSWeiwei Li         error_setg(errp, "Zvfbfmin extension depends on Zve32f extension");
11924556fdaaSWeiwei Li         return;
11934556fdaaSWeiwei Li     }
11944556fdaaSWeiwei Li 
11954556fdaaSWeiwei Li     if (cpu->cfg.ext_zvfbfwma && !cpu->cfg.ext_zvfbfmin) {
11964556fdaaSWeiwei Li         error_setg(errp, "Zvfbfwma extension depends on Zvfbfmin extension");
11974556fdaaSWeiwei Li         return;
11984556fdaaSWeiwei Li     }
11994556fdaaSWeiwei Li 
1200bc573816STsukasa OI     /* Set the ISA extensions, checks should have happened above */
1201a0d805f0SWeiwei Li     if (cpu->cfg.ext_zhinx) {
1202a0d805f0SWeiwei Li         cpu->cfg.ext_zhinxmin = true;
1203a0d805f0SWeiwei Li     }
1204a0d805f0SWeiwei Li 
12059ba63f94SWeiwei Li     if ((cpu->cfg.ext_zdinx || cpu->cfg.ext_zhinxmin) && !cpu->cfg.ext_zfinx) {
12069ba63f94SWeiwei Li         error_setg(errp, "Zdinx/Zhinx/Zhinxmin extensions require Zfinx");
12079ba63f94SWeiwei Li         return;
120889ffdcecSWeiwei Li     }
120989ffdcecSWeiwei Li 
1210bc573816STsukasa OI     if (cpu->cfg.ext_zfinx) {
1211bc573816STsukasa OI         if (!cpu->cfg.ext_icsr) {
12121086504cSTsukasa OI             error_setg(errp, "Zfinx extension requires Zicsr");
12131086504cSTsukasa OI             return;
12141086504cSTsukasa OI         }
12154b33598fSDaniel Henrique Barboza         if (riscv_has_ext(env, RVF)) {
1216bc573816STsukasa OI             error_setg(errp,
1217bc573816STsukasa OI                        "Zfinx cannot be supported together with F extension");
1218bc573816STsukasa OI             return;
1219bc573816STsukasa OI         }
1220bc573816STsukasa OI     }
12211086504cSTsukasa OI 
122200d312bdSWeiwei Li     if (cpu->cfg.ext_zce) {
122300d312bdSWeiwei Li         cpu->cfg.ext_zca = true;
122400d312bdSWeiwei Li         cpu->cfg.ext_zcb = true;
122500d312bdSWeiwei Li         cpu->cfg.ext_zcmp = true;
122600d312bdSWeiwei Li         cpu->cfg.ext_zcmt = true;
12274b33598fSDaniel Henrique Barboza         if (riscv_has_ext(env, RVF) && env->misa_mxl_max == MXL_RV32) {
122800d312bdSWeiwei Li             cpu->cfg.ext_zcf = true;
122900d312bdSWeiwei Li         }
123000d312bdSWeiwei Li     }
123100d312bdSWeiwei Li 
123255ea4739SDaniel Henrique Barboza     /* zca, zcd and zcf has a PRIV 1.12.0 restriction */
123355ea4739SDaniel Henrique Barboza     if (riscv_has_ext(env, RVC) && env->priv_ver >= PRIV_VERSION_1_12_0) {
12342288a5ceSWeiwei Li         cpu->cfg.ext_zca = true;
12354b33598fSDaniel Henrique Barboza         if (riscv_has_ext(env, RVF) && env->misa_mxl_max == MXL_RV32) {
12362288a5ceSWeiwei Li             cpu->cfg.ext_zcf = true;
12372288a5ceSWeiwei Li         }
1238ffffd954SDaniel Henrique Barboza         if (riscv_has_ext(env, RVD)) {
12392288a5ceSWeiwei Li             cpu->cfg.ext_zcd = true;
12402288a5ceSWeiwei Li         }
12412288a5ceSWeiwei Li     }
12422288a5ceSWeiwei Li 
12432288a5ceSWeiwei Li     if (env->misa_mxl_max != MXL_RV32 && cpu->cfg.ext_zcf) {
12442288a5ceSWeiwei Li         error_setg(errp, "Zcf extension is only relevant to RV32");
12452288a5ceSWeiwei Li         return;
12462288a5ceSWeiwei Li     }
12472288a5ceSWeiwei Li 
12484b33598fSDaniel Henrique Barboza     if (!riscv_has_ext(env, RVF) && cpu->cfg.ext_zcf) {
12492288a5ceSWeiwei Li         error_setg(errp, "Zcf extension requires F extension");
12502288a5ceSWeiwei Li         return;
12512288a5ceSWeiwei Li     }
12522288a5ceSWeiwei Li 
1253ffffd954SDaniel Henrique Barboza     if (!riscv_has_ext(env, RVD) && cpu->cfg.ext_zcd) {
12542288a5ceSWeiwei Li         error_setg(errp, "Zcd extension requires D extension");
12552288a5ceSWeiwei Li         return;
12562288a5ceSWeiwei Li     }
12572288a5ceSWeiwei Li 
12582288a5ceSWeiwei Li     if ((cpu->cfg.ext_zcf || cpu->cfg.ext_zcd || cpu->cfg.ext_zcb ||
12592288a5ceSWeiwei Li          cpu->cfg.ext_zcmp || cpu->cfg.ext_zcmt) && !cpu->cfg.ext_zca) {
12602288a5ceSWeiwei Li         error_setg(errp, "Zcf/Zcd/Zcb/Zcmp/Zcmt extensions require Zca "
12612288a5ceSWeiwei Li                          "extension");
12622288a5ceSWeiwei Li         return;
12632288a5ceSWeiwei Li     }
12642288a5ceSWeiwei Li 
12652288a5ceSWeiwei Li     if (cpu->cfg.ext_zcd && (cpu->cfg.ext_zcmp || cpu->cfg.ext_zcmt)) {
12662288a5ceSWeiwei Li         error_setg(errp, "Zcmp/Zcmt extensions are incompatible with "
12672288a5ceSWeiwei Li                          "Zcd extension");
12682288a5ceSWeiwei Li         return;
12692288a5ceSWeiwei Li     }
12702288a5ceSWeiwei Li 
12712288a5ceSWeiwei Li     if (cpu->cfg.ext_zcmt && !cpu->cfg.ext_icsr) {
12722288a5ceSWeiwei Li         error_setg(errp, "Zcmt extension requires Zicsr extension");
12732288a5ceSWeiwei Li         return;
12742288a5ceSWeiwei Li     }
12752288a5ceSWeiwei Li 
1276*06028472SDickon Hood     /*
1277*06028472SDickon Hood      * In principle Zve*x would also suffice here, were they supported
1278*06028472SDickon Hood      * in qemu
1279*06028472SDickon Hood      */
1280*06028472SDickon Hood     if (cpu->cfg.ext_zvbb && !cpu->cfg.ext_zve32f) {
1281*06028472SDickon Hood         error_setg(errp,
1282*06028472SDickon Hood                    "Vector crypto extensions require V or Zve* extensions");
1283*06028472SDickon Hood         return;
1284*06028472SDickon Hood     }
1285*06028472SDickon Hood 
1286e13c7d3bSLawrence Hunter     if (cpu->cfg.ext_zvbc && !cpu->cfg.ext_zve64f) {
1287e13c7d3bSLawrence Hunter         error_setg(errp, "Zvbc extension requires V or Zve64{f,d} extensions");
1288e13c7d3bSLawrence Hunter         return;
1289e13c7d3bSLawrence Hunter     }
1290e13c7d3bSLawrence Hunter 
1291eef82872SWeiwei Li     if (cpu->cfg.ext_zk) {
1292eef82872SWeiwei Li         cpu->cfg.ext_zkn = true;
1293eef82872SWeiwei Li         cpu->cfg.ext_zkr = true;
1294eef82872SWeiwei Li         cpu->cfg.ext_zkt = true;
1295eef82872SWeiwei Li     }
1296eef82872SWeiwei Li 
1297eef82872SWeiwei Li     if (cpu->cfg.ext_zkn) {
1298eef82872SWeiwei Li         cpu->cfg.ext_zbkb = true;
1299eef82872SWeiwei Li         cpu->cfg.ext_zbkc = true;
1300eef82872SWeiwei Li         cpu->cfg.ext_zbkx = true;
1301eef82872SWeiwei Li         cpu->cfg.ext_zkne = true;
1302eef82872SWeiwei Li         cpu->cfg.ext_zknd = true;
1303eef82872SWeiwei Li         cpu->cfg.ext_zknh = true;
1304eef82872SWeiwei Li     }
1305eef82872SWeiwei Li 
1306eef82872SWeiwei Li     if (cpu->cfg.ext_zks) {
1307eef82872SWeiwei Li         cpu->cfg.ext_zbkb = true;
1308eef82872SWeiwei Li         cpu->cfg.ext_zbkc = true;
1309eef82872SWeiwei Li         cpu->cfg.ext_zbkx = true;
1310eef82872SWeiwei Li         cpu->cfg.ext_zksed = true;
1311eef82872SWeiwei Li         cpu->cfg.ext_zksh = true;
1312eef82872SWeiwei Li     }
1313bd305595SDaniel Henrique Barboza 
1314bd305595SDaniel Henrique Barboza     /*
1315bd305595SDaniel Henrique Barboza      * Disable isa extensions based on priv spec after we
1316bd305595SDaniel Henrique Barboza      * validated and set everything we need.
1317bd305595SDaniel Henrique Barboza      */
1318bd305595SDaniel Henrique Barboza     riscv_cpu_disable_priv_spec_isa_exts(cpu);
1319b55d7d34SAlistair Francis }
1320b55d7d34SAlistair Francis 
13216f23aaebSAlexandre Ghiti #ifndef CONFIG_USER_ONLY
13226f23aaebSAlexandre Ghiti static void riscv_cpu_satp_mode_finalize(RISCVCPU *cpu, Error **errp)
13236f23aaebSAlexandre Ghiti {
13246f23aaebSAlexandre Ghiti     bool rv32 = riscv_cpu_mxl(&cpu->env) == MXL_RV32;
13256df3747aSAlexandre Ghiti     uint8_t satp_mode_map_max;
13266df3747aSAlexandre Ghiti     uint8_t satp_mode_supported_max =
13276df3747aSAlexandre Ghiti                         satp_mode_max_from_map(cpu->cfg.satp_mode.supported);
13286f23aaebSAlexandre Ghiti 
13296f23aaebSAlexandre Ghiti     if (cpu->cfg.satp_mode.map == 0) {
13306f23aaebSAlexandre Ghiti         if (cpu->cfg.satp_mode.init == 0) {
13316f23aaebSAlexandre Ghiti             /* If unset by the user, we fallback to the default satp mode. */
13326f23aaebSAlexandre Ghiti             set_satp_mode_default_map(cpu);
13336f23aaebSAlexandre Ghiti         } else {
13346f23aaebSAlexandre Ghiti             /*
13356f23aaebSAlexandre Ghiti              * Find the lowest level that was disabled and then enable the
13366f23aaebSAlexandre Ghiti              * first valid level below which can be found in
13376f23aaebSAlexandre Ghiti              * valid_vm_1_10_32/64.
13386f23aaebSAlexandre Ghiti              */
13396f23aaebSAlexandre Ghiti             for (int i = 1; i < 16; ++i) {
13406df3747aSAlexandre Ghiti                 if ((cpu->cfg.satp_mode.init & (1 << i)) &&
13416df3747aSAlexandre Ghiti                     (cpu->cfg.satp_mode.supported & (1 << i))) {
13426f23aaebSAlexandre Ghiti                     for (int j = i - 1; j >= 0; --j) {
13436df3747aSAlexandre Ghiti                         if (cpu->cfg.satp_mode.supported & (1 << j)) {
13446f23aaebSAlexandre Ghiti                             cpu->cfg.satp_mode.map |= (1 << j);
13456f23aaebSAlexandre Ghiti                             break;
13466f23aaebSAlexandre Ghiti                         }
13476f23aaebSAlexandre Ghiti                     }
13486f23aaebSAlexandre Ghiti                     break;
13496f23aaebSAlexandre Ghiti                 }
13506f23aaebSAlexandre Ghiti             }
13516f23aaebSAlexandre Ghiti         }
13526f23aaebSAlexandre Ghiti     }
13536f23aaebSAlexandre Ghiti 
13546df3747aSAlexandre Ghiti     satp_mode_map_max = satp_mode_max_from_map(cpu->cfg.satp_mode.map);
13556df3747aSAlexandre Ghiti 
13566df3747aSAlexandre Ghiti     /* Make sure the user asked for a supported configuration (HW and qemu) */
13576df3747aSAlexandre Ghiti     if (satp_mode_map_max > satp_mode_supported_max) {
13586df3747aSAlexandre Ghiti         error_setg(errp, "satp_mode %s is higher than hw max capability %s",
13596df3747aSAlexandre Ghiti                    satp_mode_str(satp_mode_map_max, rv32),
13606df3747aSAlexandre Ghiti                    satp_mode_str(satp_mode_supported_max, rv32));
13616f23aaebSAlexandre Ghiti         return;
13626f23aaebSAlexandre Ghiti     }
13636f23aaebSAlexandre Ghiti 
13646f23aaebSAlexandre Ghiti     /*
13656f23aaebSAlexandre Ghiti      * Make sure the user did not ask for an invalid configuration as per
13666f23aaebSAlexandre Ghiti      * the specification.
13676f23aaebSAlexandre Ghiti      */
13686f23aaebSAlexandre Ghiti     if (!rv32) {
13696df3747aSAlexandre Ghiti         for (int i = satp_mode_map_max - 1; i >= 0; --i) {
13706f23aaebSAlexandre Ghiti             if (!(cpu->cfg.satp_mode.map & (1 << i)) &&
13716f23aaebSAlexandre Ghiti                 (cpu->cfg.satp_mode.init & (1 << i)) &&
13726df3747aSAlexandre Ghiti                 (cpu->cfg.satp_mode.supported & (1 << i))) {
13736f23aaebSAlexandre Ghiti                 error_setg(errp, "cannot disable %s satp mode if %s "
13746f23aaebSAlexandre Ghiti                            "is enabled", satp_mode_str(i, false),
13756df3747aSAlexandre Ghiti                            satp_mode_str(satp_mode_map_max, false));
13766f23aaebSAlexandre Ghiti                 return;
13776f23aaebSAlexandre Ghiti             }
13786f23aaebSAlexandre Ghiti         }
13796f23aaebSAlexandre Ghiti     }
13806f23aaebSAlexandre Ghiti 
13816f23aaebSAlexandre Ghiti     /* Finally expand the map so that all valid modes are set */
13826df3747aSAlexandre Ghiti     for (int i = satp_mode_map_max - 1; i >= 0; --i) {
13836df3747aSAlexandre Ghiti         if (cpu->cfg.satp_mode.supported & (1 << i)) {
13846f23aaebSAlexandre Ghiti             cpu->cfg.satp_mode.map |= (1 << i);
13856f23aaebSAlexandre Ghiti         }
13866f23aaebSAlexandre Ghiti     }
13876f23aaebSAlexandre Ghiti }
13886f23aaebSAlexandre Ghiti #endif
13896f23aaebSAlexandre Ghiti 
13906f23aaebSAlexandre Ghiti static void riscv_cpu_finalize_features(RISCVCPU *cpu, Error **errp)
13916f23aaebSAlexandre Ghiti {
13926f23aaebSAlexandre Ghiti #ifndef CONFIG_USER_ONLY
13936f23aaebSAlexandre Ghiti     Error *local_err = NULL;
13946f23aaebSAlexandre Ghiti 
13956f23aaebSAlexandre Ghiti     riscv_cpu_satp_mode_finalize(cpu, &local_err);
13966f23aaebSAlexandre Ghiti     if (local_err != NULL) {
13976f23aaebSAlexandre Ghiti         error_propagate(errp, local_err);
13986f23aaebSAlexandre Ghiti         return;
13996f23aaebSAlexandre Ghiti     }
14006f23aaebSAlexandre Ghiti #endif
14016f23aaebSAlexandre Ghiti }
14026f23aaebSAlexandre Ghiti 
14036508272aSDaniel Henrique Barboza static void riscv_cpu_validate_misa_priv(CPURISCVState *env, Error **errp)
14046508272aSDaniel Henrique Barboza {
14056508272aSDaniel Henrique Barboza     if (riscv_has_ext(env, RVH) && env->priv_ver < PRIV_VERSION_1_12_0) {
14066508272aSDaniel Henrique Barboza         error_setg(errp, "H extension requires priv spec 1.12.0");
14076508272aSDaniel Henrique Barboza         return;
14086508272aSDaniel Henrique Barboza     }
14096508272aSDaniel Henrique Barboza }
14106508272aSDaniel Henrique Barboza 
1411eddabb6bSDaniel Henrique Barboza static void riscv_cpu_realize_tcg(DeviceState *dev, Error **errp)
14125ab10952SDaniel Henrique Barboza {
14135ab10952SDaniel Henrique Barboza     RISCVCPU *cpu = RISCV_CPU(dev);
14145ab10952SDaniel Henrique Barboza     CPURISCVState *env = &cpu->env;
14155ab10952SDaniel Henrique Barboza     Error *local_err = NULL;
14165ab10952SDaniel Henrique Barboza 
1417782ee711SDaniel Henrique Barboza     if (object_dynamic_cast(OBJECT(dev), TYPE_RISCV_CPU_HOST)) {
1418782ee711SDaniel Henrique Barboza         error_setg(errp, "'host' CPU is not compatible with TCG acceleration");
1419782ee711SDaniel Henrique Barboza         return;
1420782ee711SDaniel Henrique Barboza     }
1421782ee711SDaniel Henrique Barboza 
1422f5664064SDaniel Henrique Barboza     riscv_cpu_validate_misa_mxl(cpu, &local_err);
1423f5664064SDaniel Henrique Barboza     if (local_err != NULL) {
1424f5664064SDaniel Henrique Barboza         error_propagate(errp, local_err);
1425f5664064SDaniel Henrique Barboza         return;
1426f5664064SDaniel Henrique Barboza     }
1427f5664064SDaniel Henrique Barboza 
1428bd305595SDaniel Henrique Barboza     riscv_cpu_validate_priv_spec(cpu, &local_err);
1429bd305595SDaniel Henrique Barboza     if (local_err != NULL) {
1430bd305595SDaniel Henrique Barboza         error_propagate(errp, local_err);
14315ab10952SDaniel Henrique Barboza         return;
14325ab10952SDaniel Henrique Barboza     }
14335ab10952SDaniel Henrique Barboza 
14346508272aSDaniel Henrique Barboza     riscv_cpu_validate_misa_priv(env, &local_err);
14356508272aSDaniel Henrique Barboza     if (local_err != NULL) {
14366508272aSDaniel Henrique Barboza         error_propagate(errp, local_err);
14376508272aSDaniel Henrique Barboza         return;
14386508272aSDaniel Henrique Barboza     }
14396508272aSDaniel Henrique Barboza 
14406a3ffda2SDaniel Henrique Barboza     if (cpu->cfg.epmp && !cpu->cfg.pmp) {
14415ab10952SDaniel Henrique Barboza         /*
14425ab10952SDaniel Henrique Barboza          * Enhanced PMP should only be available
14435ab10952SDaniel Henrique Barboza          * on harts with PMP support
14445ab10952SDaniel Henrique Barboza          */
144509631441SDaniel Henrique Barboza         error_setg(errp, "Invalid configuration: EPMP requires PMP support");
144609631441SDaniel Henrique Barboza         return;
14475ab10952SDaniel Henrique Barboza     }
14485ab10952SDaniel Henrique Barboza 
14495ab10952SDaniel Henrique Barboza     riscv_cpu_validate_set_extensions(cpu, &local_err);
14505ab10952SDaniel Henrique Barboza     if (local_err != NULL) {
14515ab10952SDaniel Henrique Barboza         error_propagate(errp, local_err);
14525ab10952SDaniel Henrique Barboza         return;
14535ab10952SDaniel Henrique Barboza     }
14545ab10952SDaniel Henrique Barboza 
145514664483SAtish Patra #ifndef CONFIG_USER_ONLY
1456eddabb6bSDaniel Henrique Barboza     CPU(dev)->tcg_cflags |= CF_PCREL;
1457356c13f9SWeiwei Li 
1458e2fa85f4SDaniel Henrique Barboza     if (cpu->cfg.ext_sstc) {
1459e2fa85f4SDaniel Henrique Barboza         riscv_timer_init(cpu);
1460e2fa85f4SDaniel Henrique Barboza     }
1461e2fa85f4SDaniel Henrique Barboza 
146214664483SAtish Patra     if (cpu->cfg.pmu_num) {
146314664483SAtish Patra         if (!riscv_pmu_init(cpu, cpu->cfg.pmu_num) && cpu->cfg.ext_sscofpmf) {
146414664483SAtish Patra             cpu->pmu_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
146514664483SAtish Patra                                           riscv_pmu_timer_cb, cpu);
146614664483SAtish Patra         }
146714664483SAtish Patra      }
146814664483SAtish Patra #endif
1469eddabb6bSDaniel Henrique Barboza }
1470eddabb6bSDaniel Henrique Barboza 
1471eddabb6bSDaniel Henrique Barboza static void riscv_cpu_realize(DeviceState *dev, Error **errp)
1472eddabb6bSDaniel Henrique Barboza {
1473eddabb6bSDaniel Henrique Barboza     CPUState *cs = CPU(dev);
1474eddabb6bSDaniel Henrique Barboza     RISCVCPU *cpu = RISCV_CPU(dev);
1475eddabb6bSDaniel Henrique Barboza     RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(dev);
1476eddabb6bSDaniel Henrique Barboza     Error *local_err = NULL;
1477eddabb6bSDaniel Henrique Barboza 
1478eddabb6bSDaniel Henrique Barboza     cpu_exec_realizefn(cs, &local_err);
1479eddabb6bSDaniel Henrique Barboza     if (local_err != NULL) {
1480eddabb6bSDaniel Henrique Barboza         error_propagate(errp, local_err);
1481eddabb6bSDaniel Henrique Barboza         return;
1482eddabb6bSDaniel Henrique Barboza     }
1483eddabb6bSDaniel Henrique Barboza 
1484eddabb6bSDaniel Henrique Barboza     if (tcg_enabled()) {
1485eddabb6bSDaniel Henrique Barboza         riscv_cpu_realize_tcg(dev, &local_err);
1486eddabb6bSDaniel Henrique Barboza         if (local_err != NULL) {
1487eddabb6bSDaniel Henrique Barboza             error_propagate(errp, local_err);
1488eddabb6bSDaniel Henrique Barboza             return;
1489eddabb6bSDaniel Henrique Barboza         }
1490eddabb6bSDaniel Henrique Barboza     }
149114664483SAtish Patra 
14926f23aaebSAlexandre Ghiti     riscv_cpu_finalize_features(cpu, &local_err);
14936f23aaebSAlexandre Ghiti     if (local_err != NULL) {
14946f23aaebSAlexandre Ghiti         error_propagate(errp, local_err);
14956f23aaebSAlexandre Ghiti         return;
14966f23aaebSAlexandre Ghiti     }
14976f23aaebSAlexandre Ghiti 
14985371f5cdSJim Wilson     riscv_cpu_register_gdb_regs_for_features(cs);
14995371f5cdSJim Wilson 
1500dc5bd18fSMichael Clark     qemu_init_vcpu(cs);
1501dc5bd18fSMichael Clark     cpu_reset(cs);
1502dc5bd18fSMichael Clark 
1503dc5bd18fSMichael Clark     mcc->parent_realize(dev, errp);
1504dc5bd18fSMichael Clark }
1505dc5bd18fSMichael Clark 
15060f0b70eeSAlistair Francis #ifndef CONFIG_USER_ONLY
15076f23aaebSAlexandre Ghiti static void cpu_riscv_get_satp(Object *obj, Visitor *v, const char *name,
15086f23aaebSAlexandre Ghiti                                void *opaque, Error **errp)
15096f23aaebSAlexandre Ghiti {
15106f23aaebSAlexandre Ghiti     RISCVSATPMap *satp_map = opaque;
15116f23aaebSAlexandre Ghiti     uint8_t satp = satp_mode_from_str(name);
15126f23aaebSAlexandre Ghiti     bool value;
15136f23aaebSAlexandre Ghiti 
15146f23aaebSAlexandre Ghiti     value = satp_map->map & (1 << satp);
15156f23aaebSAlexandre Ghiti 
15166f23aaebSAlexandre Ghiti     visit_type_bool(v, name, &value, errp);
15176f23aaebSAlexandre Ghiti }
15186f23aaebSAlexandre Ghiti 
15196f23aaebSAlexandre Ghiti static void cpu_riscv_set_satp(Object *obj, Visitor *v, const char *name,
15206f23aaebSAlexandre Ghiti                                void *opaque, Error **errp)
15216f23aaebSAlexandre Ghiti {
15226f23aaebSAlexandre Ghiti     RISCVSATPMap *satp_map = opaque;
15236f23aaebSAlexandre Ghiti     uint8_t satp = satp_mode_from_str(name);
15246f23aaebSAlexandre Ghiti     bool value;
15256f23aaebSAlexandre Ghiti 
15266f23aaebSAlexandre Ghiti     if (!visit_type_bool(v, name, &value, errp)) {
15276f23aaebSAlexandre Ghiti         return;
15286f23aaebSAlexandre Ghiti     }
15296f23aaebSAlexandre Ghiti 
15306f23aaebSAlexandre Ghiti     satp_map->map = deposit32(satp_map->map, satp, 1, value);
15316f23aaebSAlexandre Ghiti     satp_map->init |= 1 << satp;
15326f23aaebSAlexandre Ghiti }
15336f23aaebSAlexandre Ghiti 
15346f23aaebSAlexandre Ghiti static void riscv_add_satp_mode_properties(Object *obj)
15356f23aaebSAlexandre Ghiti {
15366f23aaebSAlexandre Ghiti     RISCVCPU *cpu = RISCV_CPU(obj);
15376f23aaebSAlexandre Ghiti 
15386f23aaebSAlexandre Ghiti     if (cpu->env.misa_mxl == MXL_RV32) {
15396f23aaebSAlexandre Ghiti         object_property_add(obj, "sv32", "bool", cpu_riscv_get_satp,
15406f23aaebSAlexandre Ghiti                             cpu_riscv_set_satp, NULL, &cpu->cfg.satp_mode);
15416f23aaebSAlexandre Ghiti     } else {
15426f23aaebSAlexandre Ghiti         object_property_add(obj, "sv39", "bool", cpu_riscv_get_satp,
15436f23aaebSAlexandre Ghiti                             cpu_riscv_set_satp, NULL, &cpu->cfg.satp_mode);
15446f23aaebSAlexandre Ghiti         object_property_add(obj, "sv48", "bool", cpu_riscv_get_satp,
15456f23aaebSAlexandre Ghiti                             cpu_riscv_set_satp, NULL, &cpu->cfg.satp_mode);
15466f23aaebSAlexandre Ghiti         object_property_add(obj, "sv57", "bool", cpu_riscv_get_satp,
15476f23aaebSAlexandre Ghiti                             cpu_riscv_set_satp, NULL, &cpu->cfg.satp_mode);
15486f23aaebSAlexandre Ghiti         object_property_add(obj, "sv64", "bool", cpu_riscv_get_satp,
15496f23aaebSAlexandre Ghiti                             cpu_riscv_set_satp, NULL, &cpu->cfg.satp_mode);
15506f23aaebSAlexandre Ghiti     }
15516f23aaebSAlexandre Ghiti }
15526f23aaebSAlexandre Ghiti 
15530f0b70eeSAlistair Francis static void riscv_cpu_set_irq(void *opaque, int irq, int level)
15540f0b70eeSAlistair Francis {
15550f0b70eeSAlistair Francis     RISCVCPU *cpu = RISCV_CPU(opaque);
1556cd032fe7SAnup Patel     CPURISCVState *env = &cpu->env;
15570f0b70eeSAlistair Francis 
1558cd032fe7SAnup Patel     if (irq < IRQ_LOCAL_MAX) {
15590f0b70eeSAlistair Francis         switch (irq) {
15600f0b70eeSAlistair Francis         case IRQ_U_SOFT:
15610f0b70eeSAlistair Francis         case IRQ_S_SOFT:
15620f0b70eeSAlistair Francis         case IRQ_VS_SOFT:
15630f0b70eeSAlistair Francis         case IRQ_M_SOFT:
15640f0b70eeSAlistair Francis         case IRQ_U_TIMER:
15650f0b70eeSAlistair Francis         case IRQ_S_TIMER:
15660f0b70eeSAlistair Francis         case IRQ_VS_TIMER:
15670f0b70eeSAlistair Francis         case IRQ_M_TIMER:
15680f0b70eeSAlistair Francis         case IRQ_U_EXT:
15690f0b70eeSAlistair Francis         case IRQ_VS_EXT:
15700f0b70eeSAlistair Francis         case IRQ_M_EXT:
15712b650fbbSYifei Jiang             if (kvm_enabled()) {
15722b650fbbSYifei Jiang                 kvm_riscv_set_irq(cpu, irq, level);
15732b650fbbSYifei Jiang             } else {
1574bbb9fc25SWeiwei Li                 riscv_cpu_update_mip(env, 1 << irq, BOOL_TO_MASK(level));
15752b650fbbSYifei Jiang             }
15760f0b70eeSAlistair Francis              break;
157733fe584fSAlistair Francis         case IRQ_S_EXT:
157833fe584fSAlistair Francis             if (kvm_enabled()) {
157933fe584fSAlistair Francis                 kvm_riscv_set_irq(cpu, irq, level);
158033fe584fSAlistair Francis             } else {
158133fe584fSAlistair Francis                 env->external_seip = level;
1582bbb9fc25SWeiwei Li                 riscv_cpu_update_mip(env, 1 << irq,
158333fe584fSAlistair Francis                                      BOOL_TO_MASK(level | env->software_seip));
158433fe584fSAlistair Francis             }
158533fe584fSAlistair Francis             break;
15860f0b70eeSAlistair Francis         default:
15870f0b70eeSAlistair Francis             g_assert_not_reached();
15880f0b70eeSAlistair Francis         }
1589cd032fe7SAnup Patel     } else if (irq < (IRQ_LOCAL_MAX + IRQ_LOCAL_GUEST_MAX)) {
1590cd032fe7SAnup Patel         /* Require H-extension for handling guest local interrupts */
1591cd032fe7SAnup Patel         if (!riscv_has_ext(env, RVH)) {
1592cd032fe7SAnup Patel             g_assert_not_reached();
1593cd032fe7SAnup Patel         }
1594cd032fe7SAnup Patel 
1595cd032fe7SAnup Patel         /* Compute bit position in HGEIP CSR */
1596cd032fe7SAnup Patel         irq = irq - IRQ_LOCAL_MAX + 1;
1597cd032fe7SAnup Patel         if (env->geilen < irq) {
1598cd032fe7SAnup Patel             g_assert_not_reached();
1599cd032fe7SAnup Patel         }
1600cd032fe7SAnup Patel 
1601cd032fe7SAnup Patel         /* Update HGEIP CSR */
1602cd032fe7SAnup Patel         env->hgeip &= ~((target_ulong)1 << irq);
1603cd032fe7SAnup Patel         if (level) {
1604cd032fe7SAnup Patel             env->hgeip |= (target_ulong)1 << irq;
1605cd032fe7SAnup Patel         }
1606cd032fe7SAnup Patel 
1607cd032fe7SAnup Patel         /* Update mip.SGEIP bit */
1608bbb9fc25SWeiwei Li         riscv_cpu_update_mip(env, MIP_SGEIP,
1609cd032fe7SAnup Patel                              BOOL_TO_MASK(!!(env->hgeie & env->hgeip)));
1610cd032fe7SAnup Patel     } else {
1611cd032fe7SAnup Patel         g_assert_not_reached();
1612cd032fe7SAnup Patel     }
16130f0b70eeSAlistair Francis }
16140f0b70eeSAlistair Francis #endif /* CONFIG_USER_ONLY */
16150f0b70eeSAlistair Francis 
1616dc5bd18fSMichael Clark static void riscv_cpu_init(Object *obj)
1617dc5bd18fSMichael Clark {
1618dc5bd18fSMichael Clark     RISCVCPU *cpu = RISCV_CPU(obj);
1619dc5bd18fSMichael Clark 
16207506ed90SRichard Henderson     cpu_set_cpustate_pointers(cpu);
16210f0b70eeSAlistair Francis 
16220f0b70eeSAlistair Francis #ifndef CONFIG_USER_ONLY
1623cd032fe7SAnup Patel     qdev_init_gpio_in(DEVICE(cpu), riscv_cpu_set_irq,
1624cd032fe7SAnup Patel                       IRQ_LOCAL_MAX + IRQ_LOCAL_GUEST_MAX);
16250f0b70eeSAlistair Francis #endif /* CONFIG_USER_ONLY */
1626dc5bd18fSMichael Clark }
1627dc5bd18fSMichael Clark 
1628b3df64c8SDaniel Henrique Barboza typedef struct RISCVCPUMisaExtConfig {
1629b3df64c8SDaniel Henrique Barboza     const char *name;
1630b3df64c8SDaniel Henrique Barboza     const char *description;
1631b3df64c8SDaniel Henrique Barboza     target_ulong misa_bit;
1632b3df64c8SDaniel Henrique Barboza     bool enabled;
1633b3df64c8SDaniel Henrique Barboza } RISCVCPUMisaExtConfig;
1634b3df64c8SDaniel Henrique Barboza 
1635b3df64c8SDaniel Henrique Barboza static void cpu_set_misa_ext_cfg(Object *obj, Visitor *v, const char *name,
1636b3df64c8SDaniel Henrique Barboza                                  void *opaque, Error **errp)
1637b3df64c8SDaniel Henrique Barboza {
1638b3df64c8SDaniel Henrique Barboza     const RISCVCPUMisaExtConfig *misa_ext_cfg = opaque;
1639b3df64c8SDaniel Henrique Barboza     target_ulong misa_bit = misa_ext_cfg->misa_bit;
1640b3df64c8SDaniel Henrique Barboza     RISCVCPU *cpu = RISCV_CPU(obj);
1641b3df64c8SDaniel Henrique Barboza     CPURISCVState *env = &cpu->env;
1642b3df64c8SDaniel Henrique Barboza     bool value;
1643b3df64c8SDaniel Henrique Barboza 
1644b3df64c8SDaniel Henrique Barboza     if (!visit_type_bool(v, name, &value, errp)) {
1645b3df64c8SDaniel Henrique Barboza         return;
1646b3df64c8SDaniel Henrique Barboza     }
1647b3df64c8SDaniel Henrique Barboza 
1648b3df64c8SDaniel Henrique Barboza     if (value) {
1649b3df64c8SDaniel Henrique Barboza         env->misa_ext |= misa_bit;
1650b3df64c8SDaniel Henrique Barboza         env->misa_ext_mask |= misa_bit;
1651b3df64c8SDaniel Henrique Barboza     } else {
1652b3df64c8SDaniel Henrique Barboza         env->misa_ext &= ~misa_bit;
1653b3df64c8SDaniel Henrique Barboza         env->misa_ext_mask &= ~misa_bit;
1654b3df64c8SDaniel Henrique Barboza     }
1655b3df64c8SDaniel Henrique Barboza }
1656b3df64c8SDaniel Henrique Barboza 
1657b3df64c8SDaniel Henrique Barboza static void cpu_get_misa_ext_cfg(Object *obj, Visitor *v, const char *name,
1658b3df64c8SDaniel Henrique Barboza                                  void *opaque, Error **errp)
1659b3df64c8SDaniel Henrique Barboza {
1660b3df64c8SDaniel Henrique Barboza     const RISCVCPUMisaExtConfig *misa_ext_cfg = opaque;
1661b3df64c8SDaniel Henrique Barboza     target_ulong misa_bit = misa_ext_cfg->misa_bit;
1662b3df64c8SDaniel Henrique Barboza     RISCVCPU *cpu = RISCV_CPU(obj);
1663b3df64c8SDaniel Henrique Barboza     CPURISCVState *env = &cpu->env;
1664b3df64c8SDaniel Henrique Barboza     bool value;
1665b3df64c8SDaniel Henrique Barboza 
1666b3df64c8SDaniel Henrique Barboza     value = env->misa_ext & misa_bit;
1667b3df64c8SDaniel Henrique Barboza 
1668b3df64c8SDaniel Henrique Barboza     visit_type_bool(v, name, &value, errp);
1669b3df64c8SDaniel Henrique Barboza }
1670b3df64c8SDaniel Henrique Barboza 
1671ed7e6182SDaniel Henrique Barboza typedef struct misa_ext_info {
1672ed7e6182SDaniel Henrique Barboza     const char *name;
1673ed7e6182SDaniel Henrique Barboza     const char *description;
1674ed7e6182SDaniel Henrique Barboza } MISAExtInfo;
1675ed7e6182SDaniel Henrique Barboza 
1676ed7e6182SDaniel Henrique Barboza #define MISA_INFO_IDX(_bit) \
1677ed7e6182SDaniel Henrique Barboza     __builtin_ctz(_bit)
1678ed7e6182SDaniel Henrique Barboza 
1679ed7e6182SDaniel Henrique Barboza #define MISA_EXT_INFO(_bit, _propname, _descr) \
1680ed7e6182SDaniel Henrique Barboza     [MISA_INFO_IDX(_bit)] = {.name = _propname, .description = _descr}
1681ed7e6182SDaniel Henrique Barboza 
1682ed7e6182SDaniel Henrique Barboza static const MISAExtInfo misa_ext_info_arr[] = {
1683ed7e6182SDaniel Henrique Barboza     MISA_EXT_INFO(RVA, "a", "Atomic instructions"),
1684ed7e6182SDaniel Henrique Barboza     MISA_EXT_INFO(RVC, "c", "Compressed instructions"),
1685ed7e6182SDaniel Henrique Barboza     MISA_EXT_INFO(RVD, "d", "Double-precision float point"),
1686ed7e6182SDaniel Henrique Barboza     MISA_EXT_INFO(RVF, "f", "Single-precision float point"),
1687ed7e6182SDaniel Henrique Barboza     MISA_EXT_INFO(RVI, "i", "Base integer instruction set"),
1688ed7e6182SDaniel Henrique Barboza     MISA_EXT_INFO(RVE, "e", "Base integer instruction set (embedded)"),
1689ed7e6182SDaniel Henrique Barboza     MISA_EXT_INFO(RVM, "m", "Integer multiplication and division"),
1690ed7e6182SDaniel Henrique Barboza     MISA_EXT_INFO(RVS, "s", "Supervisor-level instructions"),
1691ed7e6182SDaniel Henrique Barboza     MISA_EXT_INFO(RVU, "u", "User-level instructions"),
1692ed7e6182SDaniel Henrique Barboza     MISA_EXT_INFO(RVH, "h", "Hypervisor"),
1693ed7e6182SDaniel Henrique Barboza     MISA_EXT_INFO(RVJ, "x-j", "Dynamic translated languages"),
1694ed7e6182SDaniel Henrique Barboza     MISA_EXT_INFO(RVV, "v", "Vector operations"),
1695ed7e6182SDaniel Henrique Barboza     MISA_EXT_INFO(RVG, "g", "General purpose (IMAFD_Zicsr_Zifencei)"),
1696ed7e6182SDaniel Henrique Barboza };
1697ed7e6182SDaniel Henrique Barboza 
1698ed7e6182SDaniel Henrique Barboza static int riscv_validate_misa_info_idx(uint32_t bit)
1699ed7e6182SDaniel Henrique Barboza {
1700ed7e6182SDaniel Henrique Barboza     int idx;
1701ed7e6182SDaniel Henrique Barboza 
1702ed7e6182SDaniel Henrique Barboza     /*
1703ed7e6182SDaniel Henrique Barboza      * Our lowest valid input (RVA) is 1 and
1704ed7e6182SDaniel Henrique Barboza      * __builtin_ctz() is UB with zero.
1705ed7e6182SDaniel Henrique Barboza      */
1706ed7e6182SDaniel Henrique Barboza     g_assert(bit != 0);
1707ed7e6182SDaniel Henrique Barboza     idx = MISA_INFO_IDX(bit);
1708ed7e6182SDaniel Henrique Barboza 
1709ed7e6182SDaniel Henrique Barboza     g_assert(idx < ARRAY_SIZE(misa_ext_info_arr));
1710ed7e6182SDaniel Henrique Barboza     return idx;
1711ed7e6182SDaniel Henrique Barboza }
1712ed7e6182SDaniel Henrique Barboza 
1713ed7e6182SDaniel Henrique Barboza const char *riscv_get_misa_ext_name(uint32_t bit)
1714ed7e6182SDaniel Henrique Barboza {
1715ed7e6182SDaniel Henrique Barboza     int idx = riscv_validate_misa_info_idx(bit);
1716ed7e6182SDaniel Henrique Barboza     const char *val = misa_ext_info_arr[idx].name;
1717ed7e6182SDaniel Henrique Barboza 
1718ed7e6182SDaniel Henrique Barboza     g_assert(val != NULL);
1719ed7e6182SDaniel Henrique Barboza     return val;
1720ed7e6182SDaniel Henrique Barboza }
1721ed7e6182SDaniel Henrique Barboza 
1722ed7e6182SDaniel Henrique Barboza const char *riscv_get_misa_ext_description(uint32_t bit)
1723ed7e6182SDaniel Henrique Barboza {
1724ed7e6182SDaniel Henrique Barboza     int idx = riscv_validate_misa_info_idx(bit);
1725ed7e6182SDaniel Henrique Barboza     const char *val = misa_ext_info_arr[idx].description;
1726ed7e6182SDaniel Henrique Barboza 
1727ed7e6182SDaniel Henrique Barboza     g_assert(val != NULL);
1728ed7e6182SDaniel Henrique Barboza     return val;
1729ed7e6182SDaniel Henrique Barboza }
1730ed7e6182SDaniel Henrique Barboza 
1731ed7e6182SDaniel Henrique Barboza #define MISA_CFG(_bit, _enabled) \
1732ed7e6182SDaniel Henrique Barboza     {.misa_bit = _bit, .enabled = _enabled}
1733ed7e6182SDaniel Henrique Barboza 
1734ed7e6182SDaniel Henrique Barboza static RISCVCPUMisaExtConfig misa_ext_cfgs[] = {
1735ed7e6182SDaniel Henrique Barboza     MISA_CFG(RVA, true),
1736ed7e6182SDaniel Henrique Barboza     MISA_CFG(RVC, true),
1737ed7e6182SDaniel Henrique Barboza     MISA_CFG(RVD, true),
1738ed7e6182SDaniel Henrique Barboza     MISA_CFG(RVF, true),
1739ed7e6182SDaniel Henrique Barboza     MISA_CFG(RVI, true),
1740ed7e6182SDaniel Henrique Barboza     MISA_CFG(RVE, false),
1741ed7e6182SDaniel Henrique Barboza     MISA_CFG(RVM, true),
1742ed7e6182SDaniel Henrique Barboza     MISA_CFG(RVS, true),
1743ed7e6182SDaniel Henrique Barboza     MISA_CFG(RVU, true),
1744ed7e6182SDaniel Henrique Barboza     MISA_CFG(RVH, true),
1745ed7e6182SDaniel Henrique Barboza     MISA_CFG(RVJ, false),
1746ed7e6182SDaniel Henrique Barboza     MISA_CFG(RVV, false),
1747ed7e6182SDaniel Henrique Barboza     MISA_CFG(RVG, false),
17484c759943SDaniel Henrique Barboza };
1749b3df64c8SDaniel Henrique Barboza 
1750b3df64c8SDaniel Henrique Barboza static void riscv_cpu_add_misa_properties(Object *cpu_obj)
1751b3df64c8SDaniel Henrique Barboza {
1752b3df64c8SDaniel Henrique Barboza     int i;
1753b3df64c8SDaniel Henrique Barboza 
1754b3df64c8SDaniel Henrique Barboza     for (i = 0; i < ARRAY_SIZE(misa_ext_cfgs); i++) {
1755ed7e6182SDaniel Henrique Barboza         RISCVCPUMisaExtConfig *misa_cfg = &misa_ext_cfgs[i];
1756ed7e6182SDaniel Henrique Barboza         int bit = misa_cfg->misa_bit;
1757ed7e6182SDaniel Henrique Barboza 
1758ed7e6182SDaniel Henrique Barboza         misa_cfg->name = riscv_get_misa_ext_name(bit);
1759ed7e6182SDaniel Henrique Barboza         misa_cfg->description = riscv_get_misa_ext_description(bit);
1760b3df64c8SDaniel Henrique Barboza 
176192becce5SDaniel Henrique Barboza         /* Check if KVM already created the property */
176292becce5SDaniel Henrique Barboza         if (object_property_find(cpu_obj, misa_cfg->name)) {
176392becce5SDaniel Henrique Barboza             continue;
176492becce5SDaniel Henrique Barboza         }
176592becce5SDaniel Henrique Barboza 
1766b3df64c8SDaniel Henrique Barboza         object_property_add(cpu_obj, misa_cfg->name, "bool",
1767b3df64c8SDaniel Henrique Barboza                             cpu_get_misa_ext_cfg,
1768b3df64c8SDaniel Henrique Barboza                             cpu_set_misa_ext_cfg,
1769b3df64c8SDaniel Henrique Barboza                             NULL, (void *)misa_cfg);
1770b3df64c8SDaniel Henrique Barboza         object_property_set_description(cpu_obj, misa_cfg->name,
1771b3df64c8SDaniel Henrique Barboza                                         misa_cfg->description);
1772b3df64c8SDaniel Henrique Barboza         object_property_set_bool(cpu_obj, misa_cfg->name,
1773b3df64c8SDaniel Henrique Barboza                                  misa_cfg->enabled, NULL);
1774b3df64c8SDaniel Henrique Barboza     }
1775b3df64c8SDaniel Henrique Barboza }
1776b3df64c8SDaniel Henrique Barboza 
177726b2bc58SAlistair Francis static Property riscv_cpu_extensions[] = {
17789d3d60b7SAlistair Francis     /* Defaults for standard extensions */
177918d6d89eSAtish Patra     DEFINE_PROP_UINT8("pmu-num", RISCVCPU, cfg.pmu_num, 16),
178014664483SAtish Patra     DEFINE_PROP_BOOL("sscofpmf", RISCVCPU, cfg.ext_sscofpmf, false),
17819d3d60b7SAlistair Francis     DEFINE_PROP_BOOL("Zifencei", RISCVCPU, cfg.ext_ifencei, true),
17829d3d60b7SAlistair Francis     DEFINE_PROP_BOOL("Zicsr", RISCVCPU, cfg.ext_icsr, true),
17834696f0abSDao Lu     DEFINE_PROP_BOOL("Zihintpause", RISCVCPU, cfg.ext_zihintpause, true),
1784260b594dSChristoph Muellner     DEFINE_PROP_BOOL("Zawrs", RISCVCPU, cfg.ext_zawrs, true),
1785a47842d1SChristoph Müllner     DEFINE_PROP_BOOL("Zfa", RISCVCPU, cfg.ext_zfa, true),
178613fb8c7bSFrank Chang     DEFINE_PROP_BOOL("Zfh", RISCVCPU, cfg.ext_zfh, false),
1787e5237730SFrank Chang     DEFINE_PROP_BOOL("Zfhmin", RISCVCPU, cfg.ext_zfhmin, false),
17882fc1b44dSFrank Chang     DEFINE_PROP_BOOL("Zve32f", RISCVCPU, cfg.ext_zve32f, false),
1789bfefe406SFrank Chang     DEFINE_PROP_BOOL("Zve64f", RISCVCPU, cfg.ext_zve64f, false),
1790058d9d30SWeiwei Li     DEFINE_PROP_BOOL("Zve64d", RISCVCPU, cfg.ext_zve64d, false),
17919d3d60b7SAlistair Francis     DEFINE_PROP_BOOL("mmu", RISCVCPU, cfg.mmu, true),
17929d3d60b7SAlistair Francis     DEFINE_PROP_BOOL("pmp", RISCVCPU, cfg.pmp, true),
179343888c2fSAtish Patra     DEFINE_PROP_BOOL("sstc", RISCVCPU, cfg.ext_sstc, true),
17949d3d60b7SAlistair Francis 
17959d3d60b7SAlistair Francis     DEFINE_PROP_STRING("priv_spec", RISCVCPU, cfg.priv_spec),
17969ec6622dSFrank Chang     DEFINE_PROP_STRING("vext_spec", RISCVCPU, cfg.vext_spec),
17979ec6622dSFrank Chang     DEFINE_PROP_UINT16("vlen", RISCVCPU, cfg.vlen, 128),
17989ec6622dSFrank Chang     DEFINE_PROP_UINT16("elen", RISCVCPU, cfg.elen, 64),
17999d3d60b7SAlistair Francis 
18003594e3e5SMayuresh Chitale     DEFINE_PROP_BOOL("smstateen", RISCVCPU, cfg.ext_smstateen, false),
180162108f05SWeiwei Li     DEFINE_PROP_BOOL("svadu", RISCVCPU, cfg.ext_svadu, true),
1802c5d77dddSWeiwei Li     DEFINE_PROP_BOOL("svinval", RISCVCPU, cfg.ext_svinval, false),
18032bacb224SWeiwei Li     DEFINE_PROP_BOOL("svnapot", RISCVCPU, cfg.ext_svnapot, false),
1804bbce8ba8SWeiwei Li     DEFINE_PROP_BOOL("svpbmt", RISCVCPU, cfg.ext_svpbmt, false),
18052bacb224SWeiwei Li 
18060643c12eSVineet Gupta     DEFINE_PROP_BOOL("zba", RISCVCPU, cfg.ext_zba, true),
18070643c12eSVineet Gupta     DEFINE_PROP_BOOL("zbb", RISCVCPU, cfg.ext_zbb, true),
18080643c12eSVineet Gupta     DEFINE_PROP_BOOL("zbc", RISCVCPU, cfg.ext_zbc, true),
1809cf7ed971SWeiwei Li     DEFINE_PROP_BOOL("zbkb", RISCVCPU, cfg.ext_zbkb, false),
1810cf7ed971SWeiwei Li     DEFINE_PROP_BOOL("zbkc", RISCVCPU, cfg.ext_zbkc, false),
1811cf7ed971SWeiwei Li     DEFINE_PROP_BOOL("zbkx", RISCVCPU, cfg.ext_zbkx, false),
18120643c12eSVineet Gupta     DEFINE_PROP_BOOL("zbs", RISCVCPU, cfg.ext_zbs, true),
1813cf7ed971SWeiwei Li     DEFINE_PROP_BOOL("zk", RISCVCPU, cfg.ext_zk, false),
1814cf7ed971SWeiwei Li     DEFINE_PROP_BOOL("zkn", RISCVCPU, cfg.ext_zkn, false),
1815cf7ed971SWeiwei Li     DEFINE_PROP_BOOL("zknd", RISCVCPU, cfg.ext_zknd, false),
1816cf7ed971SWeiwei Li     DEFINE_PROP_BOOL("zkne", RISCVCPU, cfg.ext_zkne, false),
1817cf7ed971SWeiwei Li     DEFINE_PROP_BOOL("zknh", RISCVCPU, cfg.ext_zknh, false),
1818cf7ed971SWeiwei Li     DEFINE_PROP_BOOL("zkr", RISCVCPU, cfg.ext_zkr, false),
1819cf7ed971SWeiwei Li     DEFINE_PROP_BOOL("zks", RISCVCPU, cfg.ext_zks, false),
1820cf7ed971SWeiwei Li     DEFINE_PROP_BOOL("zksed", RISCVCPU, cfg.ext_zksed, false),
1821cf7ed971SWeiwei Li     DEFINE_PROP_BOOL("zksh", RISCVCPU, cfg.ext_zksh, false),
1822cf7ed971SWeiwei Li     DEFINE_PROP_BOOL("zkt", RISCVCPU, cfg.ext_zkt, false),
1823dfdb46a3SPhilipp Tomsich 
18246b1accefSWeiwei Li     DEFINE_PROP_BOOL("zdinx", RISCVCPU, cfg.ext_zdinx, false),
18256b1accefSWeiwei Li     DEFINE_PROP_BOOL("zfinx", RISCVCPU, cfg.ext_zfinx, false),
18266b1accefSWeiwei Li     DEFINE_PROP_BOOL("zhinx", RISCVCPU, cfg.ext_zhinx, false),
18276b1accefSWeiwei Li     DEFINE_PROP_BOOL("zhinxmin", RISCVCPU, cfg.ext_zhinxmin, false),
18286b1accefSWeiwei Li 
1829e05da09bSChristoph Muellner     DEFINE_PROP_BOOL("zicbom", RISCVCPU, cfg.ext_icbom, true),
1830e05da09bSChristoph Muellner     DEFINE_PROP_UINT16("cbom_blocksize", RISCVCPU, cfg.cbom_blocksize, 64),
1831a939c500SChristoph Muellner     DEFINE_PROP_BOOL("zicboz", RISCVCPU, cfg.ext_icboz, true),
1832a939c500SChristoph Muellner     DEFINE_PROP_UINT16("cboz_blocksize", RISCVCPU, cfg.cboz_blocksize, 64),
1833a939c500SChristoph Muellner 
18346d00ffadSWeiwei Li     DEFINE_PROP_BOOL("zmmul", RISCVCPU, cfg.ext_zmmul, false),
18356d00ffadSWeiwei Li 
18366672e29dSWeiwei Li     DEFINE_PROP_BOOL("zca", RISCVCPU, cfg.ext_zca, false),
18376672e29dSWeiwei Li     DEFINE_PROP_BOOL("zcb", RISCVCPU, cfg.ext_zcb, false),
18386672e29dSWeiwei Li     DEFINE_PROP_BOOL("zcd", RISCVCPU, cfg.ext_zcd, false),
18396672e29dSWeiwei Li     DEFINE_PROP_BOOL("zce", RISCVCPU, cfg.ext_zce, false),
18406672e29dSWeiwei Li     DEFINE_PROP_BOOL("zcf", RISCVCPU, cfg.ext_zcf, false),
18416672e29dSWeiwei Li     DEFINE_PROP_BOOL("zcmp", RISCVCPU, cfg.ext_zcmp, false),
18426672e29dSWeiwei Li     DEFINE_PROP_BOOL("zcmt", RISCVCPU, cfg.ext_zcmt, false),
18436672e29dSWeiwei Li 
18440d429bd2SPhilipp Tomsich     /* Vendor-specific custom extensions */
1845c9410a68SChristoph Müllner     DEFINE_PROP_BOOL("xtheadba", RISCVCPU, cfg.ext_xtheadba, false),
1846426c0491SChristoph Müllner     DEFINE_PROP_BOOL("xtheadbb", RISCVCPU, cfg.ext_xtheadbb, false),
1847fa134585SChristoph Müllner     DEFINE_PROP_BOOL("xtheadbs", RISCVCPU, cfg.ext_xtheadbs, false),
184849a7f3aaSChristoph Müllner     DEFINE_PROP_BOOL("xtheadcmo", RISCVCPU, cfg.ext_xtheadcmo, false),
184932909338SChristoph Müllner     DEFINE_PROP_BOOL("xtheadcondmov", RISCVCPU, cfg.ext_xtheadcondmov, false),
1850d4d90115SChristoph Müllner     DEFINE_PROP_BOOL("xtheadfmemidx", RISCVCPU, cfg.ext_xtheadfmemidx, false),
1851578086baSChristoph Müllner     DEFINE_PROP_BOOL("xtheadfmv", RISCVCPU, cfg.ext_xtheadfmv, false),
1852b8a5832bSChristoph Müllner     DEFINE_PROP_BOOL("xtheadmac", RISCVCPU, cfg.ext_xtheadmac, false),
185345f9df86SChristoph Müllner     DEFINE_PROP_BOOL("xtheadmemidx", RISCVCPU, cfg.ext_xtheadmemidx, false),
1854af99aa72SChristoph Müllner     DEFINE_PROP_BOOL("xtheadmempair", RISCVCPU, cfg.ext_xtheadmempair, false),
1855134c3ffaSChristoph Müllner     DEFINE_PROP_BOOL("xtheadsync", RISCVCPU, cfg.ext_xtheadsync, false),
18560d429bd2SPhilipp Tomsich     DEFINE_PROP_BOOL("xventanacondops", RISCVCPU, cfg.ext_XVentanaCondOps, false),
18570d429bd2SPhilipp Tomsich 
1858dfdb46a3SPhilipp Tomsich     /* These are experimental so mark with 'x-' */
1859b8e1f32cSWeiwei Li     DEFINE_PROP_BOOL("x-zicond", RISCVCPU, cfg.ext_zicond, false),
1860d364c0abSWeiwei Li 
1861a44da25aSAlistair Francis     /* ePMP 0.9.3 */
18625da9514eSHou Weiying     DEFINE_PROP_BOOL("x-epmp", RISCVCPU, cfg.epmp, false),
1863dc9acc9cSAnup Patel     DEFINE_PROP_BOOL("x-smaia", RISCVCPU, cfg.ext_smaia, false),
1864dc9acc9cSAnup Patel     DEFINE_PROP_BOOL("x-ssaia", RISCVCPU, cfg.ext_ssaia, false),
18655da9514eSHou Weiying 
1866058d9d30SWeiwei Li     DEFINE_PROP_BOOL("x-zvfh", RISCVCPU, cfg.ext_zvfh, false),
1867058d9d30SWeiwei Li     DEFINE_PROP_BOOL("x-zvfhmin", RISCVCPU, cfg.ext_zvfhmin, false),
1868058d9d30SWeiwei Li 
1869889caa44SWeiwei Li     DEFINE_PROP_BOOL("x-zfbfmin", RISCVCPU, cfg.ext_zfbfmin, false),
1870889caa44SWeiwei Li     DEFINE_PROP_BOOL("x-zvfbfmin", RISCVCPU, cfg.ext_zvfbfmin, false),
1871889caa44SWeiwei Li     DEFINE_PROP_BOOL("x-zvfbfwma", RISCVCPU, cfg.ext_zvfbfwma, false),
1872889caa44SWeiwei Li 
1873e13c7d3bSLawrence Hunter     /* Vector cryptography extensions */
1874*06028472SDickon Hood     DEFINE_PROP_BOOL("x-zvbb", RISCVCPU, cfg.ext_zvbb, false),
1875e13c7d3bSLawrence Hunter     DEFINE_PROP_BOOL("x-zvbc", RISCVCPU, cfg.ext_zvbc, false),
1876e13c7d3bSLawrence Hunter 
187726b2bc58SAlistair Francis     DEFINE_PROP_END_OF_LIST(),
187826b2bc58SAlistair Francis };
187926b2bc58SAlistair Francis 
188056f0e992SDaniel Henrique Barboza 
188156f0e992SDaniel Henrique Barboza #ifndef CONFIG_USER_ONLY
188256f0e992SDaniel Henrique Barboza static void cpu_set_cfg_unavailable(Object *obj, Visitor *v,
188356f0e992SDaniel Henrique Barboza                                     const char *name,
188456f0e992SDaniel Henrique Barboza                                     void *opaque, Error **errp)
188556f0e992SDaniel Henrique Barboza {
188656f0e992SDaniel Henrique Barboza     const char *propname = opaque;
188756f0e992SDaniel Henrique Barboza     bool value;
188856f0e992SDaniel Henrique Barboza 
188956f0e992SDaniel Henrique Barboza     if (!visit_type_bool(v, name, &value, errp)) {
189056f0e992SDaniel Henrique Barboza         return;
189156f0e992SDaniel Henrique Barboza     }
189256f0e992SDaniel Henrique Barboza 
189356f0e992SDaniel Henrique Barboza     if (value) {
189456f0e992SDaniel Henrique Barboza         error_setg(errp, "extension %s is not available with KVM",
189556f0e992SDaniel Henrique Barboza                    propname);
189656f0e992SDaniel Henrique Barboza     }
189756f0e992SDaniel Henrique Barboza }
189856f0e992SDaniel Henrique Barboza #endif
189956f0e992SDaniel Henrique Barboza 
1900c66ffcd5SDaniel Henrique Barboza /*
1901dd8f244fSDaniel Henrique Barboza  * Add CPU properties with user-facing flags.
1902dd8f244fSDaniel Henrique Barboza  *
1903dd8f244fSDaniel Henrique Barboza  * This will overwrite existing env->misa_ext values with the
1904dd8f244fSDaniel Henrique Barboza  * defaults set via riscv_cpu_add_misa_properties().
1905c66ffcd5SDaniel Henrique Barboza  */
1906dd8f244fSDaniel Henrique Barboza static void riscv_cpu_add_user_properties(Object *obj)
190726b2bc58SAlistair Francis {
190826b2bc58SAlistair Francis     Property *prop;
1909c01756a7SAlexandre Ghiti     DeviceState *dev = DEVICE(obj);
191026b2bc58SAlistair Francis 
1911492265aeSDaniel Henrique Barboza #ifndef CONFIG_USER_ONLY
1912b71f9dcaSDaniel Henrique Barboza     riscv_add_satp_mode_properties(obj);
1913b71f9dcaSDaniel Henrique Barboza 
1914492265aeSDaniel Henrique Barboza     if (kvm_enabled()) {
1915492265aeSDaniel Henrique Barboza         kvm_riscv_init_user_properties(obj);
1916492265aeSDaniel Henrique Barboza     }
1917492265aeSDaniel Henrique Barboza #endif
1918492265aeSDaniel Henrique Barboza 
1919b3df64c8SDaniel Henrique Barboza     riscv_cpu_add_misa_properties(obj);
1920b3df64c8SDaniel Henrique Barboza 
192126b2bc58SAlistair Francis     for (prop = riscv_cpu_extensions; prop && prop->name; prop++) {
1922f7a69fa6SDaniel Henrique Barboza #ifndef CONFIG_USER_ONLY
1923f7a69fa6SDaniel Henrique Barboza         if (kvm_enabled()) {
1924f7a69fa6SDaniel Henrique Barboza             /* Check if KVM created the property already */
1925f7a69fa6SDaniel Henrique Barboza             if (object_property_find(obj, prop->name)) {
1926f7a69fa6SDaniel Henrique Barboza                 continue;
1927f7a69fa6SDaniel Henrique Barboza             }
192856f0e992SDaniel Henrique Barboza 
192956f0e992SDaniel Henrique Barboza             /*
193056f0e992SDaniel Henrique Barboza              * Set the default to disabled for every extension
193156f0e992SDaniel Henrique Barboza              * unknown to KVM and error out if the user attempts
193256f0e992SDaniel Henrique Barboza              * to enable any of them.
193356f0e992SDaniel Henrique Barboza              *
193456f0e992SDaniel Henrique Barboza              * We're giving a pass for non-bool properties since they're
193556f0e992SDaniel Henrique Barboza              * not related to the availability of extensions and can be
193656f0e992SDaniel Henrique Barboza              * safely ignored as is.
193756f0e992SDaniel Henrique Barboza              */
193856f0e992SDaniel Henrique Barboza             if (prop->info == &qdev_prop_bool) {
193956f0e992SDaniel Henrique Barboza                 object_property_add(obj, prop->name, "bool",
194056f0e992SDaniel Henrique Barboza                                     NULL, cpu_set_cfg_unavailable,
194156f0e992SDaniel Henrique Barboza                                     NULL, (void *)prop->name);
194256f0e992SDaniel Henrique Barboza                 continue;
194356f0e992SDaniel Henrique Barboza             }
1944f7a69fa6SDaniel Henrique Barboza         }
1945f7a69fa6SDaniel Henrique Barboza #endif
194626b2bc58SAlistair Francis         qdev_property_add_static(dev, prop);
194726b2bc58SAlistair Francis     }
194826b2bc58SAlistair Francis }
194926b2bc58SAlistair Francis 
195026b2bc58SAlistair Francis static Property riscv_cpu_properties[] = {
195126b2bc58SAlistair Francis     DEFINE_PROP_BOOL("debug", RISCVCPU, cfg.debug, true),
195226b2bc58SAlistair Francis 
1953277b210dSAlistair Francis #ifndef CONFIG_USER_ONLY
1954277b210dSAlistair Francis     DEFINE_PROP_UINT64("resetvec", RISCVCPU, env.resetvec, DEFAULT_RSTVEC),
1955277b210dSAlistair Francis #endif
1956a4a9a443STsukasa OI 
1957a4a9a443STsukasa OI     DEFINE_PROP_BOOL("short-isa-string", RISCVCPU, cfg.short_isa_string, false),
1958b8312675SeopXD 
1959b8312675SeopXD     DEFINE_PROP_BOOL("rvv_ta_all_1s", RISCVCPU, cfg.rvv_ta_all_1s, false),
19601ad3f9bdSeopXD     DEFINE_PROP_BOOL("rvv_ma_all_1s", RISCVCPU, cfg.rvv_ma_all_1s, false),
196154bd9b6eSDaniel Henrique Barboza 
196254bd9b6eSDaniel Henrique Barboza     /*
196354bd9b6eSDaniel Henrique Barboza      * write_misa() is marked as experimental for now so mark
196454bd9b6eSDaniel Henrique Barboza      * it with -x and default to 'false'.
196554bd9b6eSDaniel Henrique Barboza      */
196654bd9b6eSDaniel Henrique Barboza     DEFINE_PROP_BOOL("x-misa-w", RISCVCPU, cfg.misa_w, false),
1967c4e95030SAlistair Francis     DEFINE_PROP_END_OF_LIST(),
1968c4e95030SAlistair Francis };
1969c4e95030SAlistair Francis 
1970edf64786SSylvain Pelissier static gchar *riscv_gdb_arch_name(CPUState *cs)
1971edf64786SSylvain Pelissier {
1972edf64786SSylvain Pelissier     RISCVCPU *cpu = RISCV_CPU(cs);
1973edf64786SSylvain Pelissier     CPURISCVState *env = &cpu->env;
1974edf64786SSylvain Pelissier 
1975db23e5d9SRichard Henderson     switch (riscv_cpu_mxl(env)) {
1976db23e5d9SRichard Henderson     case MXL_RV32:
1977edf64786SSylvain Pelissier         return g_strdup("riscv:rv32");
1978db23e5d9SRichard Henderson     case MXL_RV64:
1979332dab68SFrédéric Pétrot     case MXL_RV128:
1980edf64786SSylvain Pelissier         return g_strdup("riscv:rv64");
1981db23e5d9SRichard Henderson     default:
1982db23e5d9SRichard Henderson         g_assert_not_reached();
1983edf64786SSylvain Pelissier     }
1984edf64786SSylvain Pelissier }
1985edf64786SSylvain Pelissier 
1986b93777e1SBin Meng static const char *riscv_gdb_get_dynamic_xml(CPUState *cs, const char *xmlname)
1987b93777e1SBin Meng {
1988b93777e1SBin Meng     RISCVCPU *cpu = RISCV_CPU(cs);
1989b93777e1SBin Meng 
1990b93777e1SBin Meng     if (strcmp(xmlname, "riscv-csr.xml") == 0) {
1991b93777e1SBin Meng         return cpu->dyn_csr_xml;
1992719d3561SHsiangkai Wang     } else if (strcmp(xmlname, "riscv-vector.xml") == 0) {
1993719d3561SHsiangkai Wang         return cpu->dyn_vreg_xml;
1994b93777e1SBin Meng     }
1995b93777e1SBin Meng 
1996b93777e1SBin Meng     return NULL;
1997b93777e1SBin Meng }
1998b93777e1SBin Meng 
19998b80bd28SPhilippe Mathieu-Daudé #ifndef CONFIG_USER_ONLY
2000f1bd6f8eSMayuresh Chitale static int64_t riscv_get_arch_id(CPUState *cs)
2001f1bd6f8eSMayuresh Chitale {
2002f1bd6f8eSMayuresh Chitale     RISCVCPU *cpu = RISCV_CPU(cs);
2003f1bd6f8eSMayuresh Chitale 
2004f1bd6f8eSMayuresh Chitale     return cpu->env.mhartid;
2005f1bd6f8eSMayuresh Chitale }
2006f1bd6f8eSMayuresh Chitale 
20078b80bd28SPhilippe Mathieu-Daudé #include "hw/core/sysemu-cpu-ops.h"
20088b80bd28SPhilippe Mathieu-Daudé 
20098b80bd28SPhilippe Mathieu-Daudé static const struct SysemuCPUOps riscv_sysemu_ops = {
201008928c6dSPhilippe Mathieu-Daudé     .get_phys_page_debug = riscv_cpu_get_phys_page_debug,
2011715e3c1aSPhilippe Mathieu-Daudé     .write_elf64_note = riscv_cpu_write_elf64_note,
2012715e3c1aSPhilippe Mathieu-Daudé     .write_elf32_note = riscv_cpu_write_elf32_note,
2013feece4d0SPhilippe Mathieu-Daudé     .legacy_vmsd = &vmstate_riscv_cpu,
20148b80bd28SPhilippe Mathieu-Daudé };
20158b80bd28SPhilippe Mathieu-Daudé #endif
20168b80bd28SPhilippe Mathieu-Daudé 
201778271684SClaudio Fontana #include "hw/core/tcg-cpu-ops.h"
201878271684SClaudio Fontana 
201911906557SRichard Henderson static const struct TCGCPUOps riscv_tcg_ops = {
202078271684SClaudio Fontana     .initialize = riscv_translate_init,
202178271684SClaudio Fontana     .synchronize_from_tb = riscv_cpu_synchronize_from_tb,
2022ad1e84f5SRichard Henderson     .restore_state_to_opc = riscv_restore_state_to_opc,
202378271684SClaudio Fontana 
202478271684SClaudio Fontana #ifndef CONFIG_USER_ONLY
2025263e2ab2SRichard Henderson     .tlb_fill = riscv_cpu_tlb_fill,
202617b3c353SPhilippe Mathieu-Daudé     .cpu_exec_interrupt = riscv_cpu_exec_interrupt,
202778271684SClaudio Fontana     .do_interrupt = riscv_cpu_do_interrupt,
202878271684SClaudio Fontana     .do_transaction_failed = riscv_cpu_do_transaction_failed,
202978271684SClaudio Fontana     .do_unaligned_access = riscv_cpu_do_unaligned_access,
2030b5f6379dSBin Meng     .debug_excp_handler = riscv_cpu_debug_excp_handler,
2031b5f6379dSBin Meng     .debug_check_breakpoint = riscv_cpu_debug_check_breakpoint,
2032b5f6379dSBin Meng     .debug_check_watchpoint = riscv_cpu_debug_check_watchpoint,
203378271684SClaudio Fontana #endif /* !CONFIG_USER_ONLY */
203478271684SClaudio Fontana };
203578271684SClaudio Fontana 
20361e341500SDaniel Henrique Barboza static bool riscv_cpu_is_dynamic(Object *cpu_obj)
20371e341500SDaniel Henrique Barboza {
20381e341500SDaniel Henrique Barboza     return object_dynamic_cast(cpu_obj, TYPE_RISCV_DYNAMIC_CPU) != NULL;
20391e341500SDaniel Henrique Barboza }
20401e341500SDaniel Henrique Barboza 
20411e341500SDaniel Henrique Barboza static void cpu_set_mvendorid(Object *obj, Visitor *v, const char *name,
20421e341500SDaniel Henrique Barboza                               void *opaque, Error **errp)
20431e341500SDaniel Henrique Barboza {
20441e341500SDaniel Henrique Barboza     bool dynamic_cpu = riscv_cpu_is_dynamic(obj);
20451e341500SDaniel Henrique Barboza     RISCVCPU *cpu = RISCV_CPU(obj);
20461e341500SDaniel Henrique Barboza     uint32_t prev_val = cpu->cfg.mvendorid;
20471e341500SDaniel Henrique Barboza     uint32_t value;
20481e341500SDaniel Henrique Barboza 
20491e341500SDaniel Henrique Barboza     if (!visit_type_uint32(v, name, &value, errp)) {
20501e341500SDaniel Henrique Barboza         return;
20511e341500SDaniel Henrique Barboza     }
20521e341500SDaniel Henrique Barboza 
20531e341500SDaniel Henrique Barboza     if (!dynamic_cpu && prev_val != value) {
20541e341500SDaniel Henrique Barboza         error_setg(errp, "Unable to change %s mvendorid (0x%x)",
20551e341500SDaniel Henrique Barboza                    object_get_typename(obj), prev_val);
20561e341500SDaniel Henrique Barboza         return;
20571e341500SDaniel Henrique Barboza     }
20581e341500SDaniel Henrique Barboza 
20591e341500SDaniel Henrique Barboza     cpu->cfg.mvendorid = value;
20601e341500SDaniel Henrique Barboza }
20611e341500SDaniel Henrique Barboza 
20621e341500SDaniel Henrique Barboza static void cpu_get_mvendorid(Object *obj, Visitor *v, const char *name,
20631e341500SDaniel Henrique Barboza                               void *opaque, Error **errp)
20641e341500SDaniel Henrique Barboza {
20651e341500SDaniel Henrique Barboza     bool value = RISCV_CPU(obj)->cfg.mvendorid;
20661e341500SDaniel Henrique Barboza 
20671e341500SDaniel Henrique Barboza     visit_type_bool(v, name, &value, errp);
20681e341500SDaniel Henrique Barboza }
20691e341500SDaniel Henrique Barboza 
2070a1863ad3SDaniel Henrique Barboza static void cpu_set_mimpid(Object *obj, Visitor *v, const char *name,
2071a1863ad3SDaniel Henrique Barboza                            void *opaque, Error **errp)
2072a1863ad3SDaniel Henrique Barboza {
2073a1863ad3SDaniel Henrique Barboza     bool dynamic_cpu = riscv_cpu_is_dynamic(obj);
2074a1863ad3SDaniel Henrique Barboza     RISCVCPU *cpu = RISCV_CPU(obj);
2075a1863ad3SDaniel Henrique Barboza     uint64_t prev_val = cpu->cfg.mimpid;
2076a1863ad3SDaniel Henrique Barboza     uint64_t value;
2077a1863ad3SDaniel Henrique Barboza 
2078a1863ad3SDaniel Henrique Barboza     if (!visit_type_uint64(v, name, &value, errp)) {
2079a1863ad3SDaniel Henrique Barboza         return;
2080a1863ad3SDaniel Henrique Barboza     }
2081a1863ad3SDaniel Henrique Barboza 
2082a1863ad3SDaniel Henrique Barboza     if (!dynamic_cpu && prev_val != value) {
2083a1863ad3SDaniel Henrique Barboza         error_setg(errp, "Unable to change %s mimpid (0x%" PRIu64 ")",
2084a1863ad3SDaniel Henrique Barboza                    object_get_typename(obj), prev_val);
2085a1863ad3SDaniel Henrique Barboza         return;
2086a1863ad3SDaniel Henrique Barboza     }
2087a1863ad3SDaniel Henrique Barboza 
2088a1863ad3SDaniel Henrique Barboza     cpu->cfg.mimpid = value;
2089a1863ad3SDaniel Henrique Barboza }
2090a1863ad3SDaniel Henrique Barboza 
2091a1863ad3SDaniel Henrique Barboza static void cpu_get_mimpid(Object *obj, Visitor *v, const char *name,
2092a1863ad3SDaniel Henrique Barboza                            void *opaque, Error **errp)
2093a1863ad3SDaniel Henrique Barboza {
2094a1863ad3SDaniel Henrique Barboza     bool value = RISCV_CPU(obj)->cfg.mimpid;
2095a1863ad3SDaniel Henrique Barboza 
2096a1863ad3SDaniel Henrique Barboza     visit_type_bool(v, name, &value, errp);
2097a1863ad3SDaniel Henrique Barboza }
2098a1863ad3SDaniel Henrique Barboza 
2099d6a427e2SDaniel Henrique Barboza static void cpu_set_marchid(Object *obj, Visitor *v, const char *name,
2100d6a427e2SDaniel Henrique Barboza                             void *opaque, Error **errp)
2101d6a427e2SDaniel Henrique Barboza {
2102d6a427e2SDaniel Henrique Barboza     bool dynamic_cpu = riscv_cpu_is_dynamic(obj);
2103d6a427e2SDaniel Henrique Barboza     RISCVCPU *cpu = RISCV_CPU(obj);
2104d6a427e2SDaniel Henrique Barboza     uint64_t prev_val = cpu->cfg.marchid;
2105d6a427e2SDaniel Henrique Barboza     uint64_t value, invalid_val;
2106d6a427e2SDaniel Henrique Barboza     uint32_t mxlen = 0;
2107d6a427e2SDaniel Henrique Barboza 
2108d6a427e2SDaniel Henrique Barboza     if (!visit_type_uint64(v, name, &value, errp)) {
2109d6a427e2SDaniel Henrique Barboza         return;
2110d6a427e2SDaniel Henrique Barboza     }
2111d6a427e2SDaniel Henrique Barboza 
2112d6a427e2SDaniel Henrique Barboza     if (!dynamic_cpu && prev_val != value) {
2113d6a427e2SDaniel Henrique Barboza         error_setg(errp, "Unable to change %s marchid (0x%" PRIu64 ")",
2114d6a427e2SDaniel Henrique Barboza                    object_get_typename(obj), prev_val);
2115d6a427e2SDaniel Henrique Barboza         return;
2116d6a427e2SDaniel Henrique Barboza     }
2117d6a427e2SDaniel Henrique Barboza 
2118d6a427e2SDaniel Henrique Barboza     switch (riscv_cpu_mxl(&cpu->env)) {
2119d6a427e2SDaniel Henrique Barboza     case MXL_RV32:
2120d6a427e2SDaniel Henrique Barboza         mxlen = 32;
2121d6a427e2SDaniel Henrique Barboza         break;
2122d6a427e2SDaniel Henrique Barboza     case MXL_RV64:
2123d6a427e2SDaniel Henrique Barboza     case MXL_RV128:
2124d6a427e2SDaniel Henrique Barboza         mxlen = 64;
2125d6a427e2SDaniel Henrique Barboza         break;
2126d6a427e2SDaniel Henrique Barboza     default:
2127d6a427e2SDaniel Henrique Barboza         g_assert_not_reached();
2128d6a427e2SDaniel Henrique Barboza     }
2129d6a427e2SDaniel Henrique Barboza 
2130d6a427e2SDaniel Henrique Barboza     invalid_val = 1LL << (mxlen - 1);
2131d6a427e2SDaniel Henrique Barboza 
2132d6a427e2SDaniel Henrique Barboza     if (value == invalid_val) {
2133d6a427e2SDaniel Henrique Barboza         error_setg(errp, "Unable to set marchid with MSB (%u) bit set "
2134d6a427e2SDaniel Henrique Barboza                          "and the remaining bits zero", mxlen);
2135d6a427e2SDaniel Henrique Barboza         return;
2136d6a427e2SDaniel Henrique Barboza     }
2137d6a427e2SDaniel Henrique Barboza 
2138d6a427e2SDaniel Henrique Barboza     cpu->cfg.marchid = value;
2139d6a427e2SDaniel Henrique Barboza }
2140d6a427e2SDaniel Henrique Barboza 
2141d6a427e2SDaniel Henrique Barboza static void cpu_get_marchid(Object *obj, Visitor *v, const char *name,
2142d6a427e2SDaniel Henrique Barboza                            void *opaque, Error **errp)
2143d6a427e2SDaniel Henrique Barboza {
2144d6a427e2SDaniel Henrique Barboza     bool value = RISCV_CPU(obj)->cfg.marchid;
2145d6a427e2SDaniel Henrique Barboza 
2146d6a427e2SDaniel Henrique Barboza     visit_type_bool(v, name, &value, errp);
2147d6a427e2SDaniel Henrique Barboza }
2148d6a427e2SDaniel Henrique Barboza 
2149dc5bd18fSMichael Clark static void riscv_cpu_class_init(ObjectClass *c, void *data)
2150dc5bd18fSMichael Clark {
2151dc5bd18fSMichael Clark     RISCVCPUClass *mcc = RISCV_CPU_CLASS(c);
2152dc5bd18fSMichael Clark     CPUClass *cc = CPU_CLASS(c);
2153dc5bd18fSMichael Clark     DeviceClass *dc = DEVICE_CLASS(c);
21544fa485a7SPeter Maydell     ResettableClass *rc = RESETTABLE_CLASS(c);
2155dc5bd18fSMichael Clark 
215641fbbba7SMao Zhongyi     device_class_set_parent_realize(dc, riscv_cpu_realize,
215741fbbba7SMao Zhongyi                                     &mcc->parent_realize);
2158dc5bd18fSMichael Clark 
21594fa485a7SPeter Maydell     resettable_class_set_parent_phases(rc, NULL, riscv_cpu_reset_hold, NULL,
21604fa485a7SPeter Maydell                                        &mcc->parent_phases);
2161dc5bd18fSMichael Clark 
2162dc5bd18fSMichael Clark     cc->class_by_name = riscv_cpu_class_by_name;
2163dc5bd18fSMichael Clark     cc->has_work = riscv_cpu_has_work;
2164dc5bd18fSMichael Clark     cc->dump_state = riscv_cpu_dump_state;
2165dc5bd18fSMichael Clark     cc->set_pc = riscv_cpu_set_pc;
2166e4fdf9dfSRichard Henderson     cc->get_pc = riscv_cpu_get_pc;
2167dc5bd18fSMichael Clark     cc->gdb_read_register = riscv_cpu_gdb_read_register;
2168dc5bd18fSMichael Clark     cc->gdb_write_register = riscv_cpu_gdb_write_register;
21695371f5cdSJim Wilson     cc->gdb_num_core_regs = 33;
2170dc5bd18fSMichael Clark     cc->gdb_stop_before_watchpoint = true;
2171dc5bd18fSMichael Clark     cc->disas_set_info = riscv_cpu_disas_set_info;
21728a4ca3c1SRichard Henderson #ifndef CONFIG_USER_ONLY
21738b80bd28SPhilippe Mathieu-Daudé     cc->sysemu_ops = &riscv_sysemu_ops;
2174f1bd6f8eSMayuresh Chitale     cc->get_arch_id = riscv_get_arch_id;
2175dc5bd18fSMichael Clark #endif
2176edf64786SSylvain Pelissier     cc->gdb_arch_name = riscv_gdb_arch_name;
2177b93777e1SBin Meng     cc->gdb_get_dynamic_xml = riscv_gdb_get_dynamic_xml;
217878271684SClaudio Fontana     cc->tcg_ops = &riscv_tcg_ops;
21796a3d2e7cSClaudio Fontana 
21801e341500SDaniel Henrique Barboza     object_class_property_add(c, "mvendorid", "uint32", cpu_get_mvendorid,
21811e341500SDaniel Henrique Barboza                               cpu_set_mvendorid, NULL, NULL);
21821e341500SDaniel Henrique Barboza 
2183a1863ad3SDaniel Henrique Barboza     object_class_property_add(c, "mimpid", "uint64", cpu_get_mimpid,
2184a1863ad3SDaniel Henrique Barboza                               cpu_set_mimpid, NULL, NULL);
2185a1863ad3SDaniel Henrique Barboza 
2186d6a427e2SDaniel Henrique Barboza     object_class_property_add(c, "marchid", "uint64", cpu_get_marchid,
2187d6a427e2SDaniel Henrique Barboza                               cpu_set_marchid, NULL, NULL);
2188d6a427e2SDaniel Henrique Barboza 
21894f67d30bSMarc-André Lureau     device_class_set_props(dc, riscv_cpu_properties);
2190dc5bd18fSMichael Clark }
2191dc5bd18fSMichael Clark 
2192246f8796SWeiwei Li static void riscv_isa_string_ext(RISCVCPU *cpu, char **isa_str,
2193246f8796SWeiwei Li                                  int max_str_len)
2194a775398bSAtish Patra {
2195a775398bSAtish Patra     char *old = *isa_str;
2196a775398bSAtish Patra     char *new = *isa_str;
2197a775398bSAtish Patra     int i;
2198a775398bSAtish Patra 
2199a775398bSAtish Patra     for (i = 0; i < ARRAY_SIZE(isa_edata_arr); i++) {
220063c7eedcSDaniel Henrique Barboza         if (isa_ext_is_enabled(cpu, &isa_edata_arr[i])) {
2201a775398bSAtish Patra             new = g_strconcat(old, "_", isa_edata_arr[i].name, NULL);
2202a775398bSAtish Patra             g_free(old);
2203a775398bSAtish Patra             old = new;
2204a775398bSAtish Patra         }
2205a775398bSAtish Patra     }
2206a775398bSAtish Patra 
2207a775398bSAtish Patra     *isa_str = new;
2208a775398bSAtish Patra }
2209a775398bSAtish Patra 
2210dc5bd18fSMichael Clark char *riscv_isa_string(RISCVCPU *cpu)
2211dc5bd18fSMichael Clark {
2212dc5bd18fSMichael Clark     int i;
22130e2c3770STsukasa OI     const size_t maxlen = sizeof("rv128") + sizeof(riscv_single_letter_exts);
2214d1fd31f8SMichael Clark     char *isa_str = g_new(char, maxlen);
2215d1fd31f8SMichael Clark     char *p = isa_str + snprintf(isa_str, maxlen, "rv%d", TARGET_LONG_BITS);
22160e2c3770STsukasa OI     for (i = 0; i < sizeof(riscv_single_letter_exts) - 1; i++) {
22170e2c3770STsukasa OI         if (cpu->env.misa_ext & RV(riscv_single_letter_exts[i])) {
22180e2c3770STsukasa OI             *p++ = qemu_tolower(riscv_single_letter_exts[i]);
2219dc5bd18fSMichael Clark         }
2220dc5bd18fSMichael Clark     }
2221d1fd31f8SMichael Clark     *p = '\0';
2222a4a9a443STsukasa OI     if (!cpu->cfg.short_isa_string) {
2223a775398bSAtish Patra         riscv_isa_string_ext(cpu, &isa_str, maxlen);
2224a4a9a443STsukasa OI     }
2225d1fd31f8SMichael Clark     return isa_str;
2226dc5bd18fSMichael Clark }
2227dc5bd18fSMichael Clark 
2228eab15862SMichael Clark static gint riscv_cpu_list_compare(gconstpointer a, gconstpointer b)
2229eab15862SMichael Clark {
2230eab15862SMichael Clark     ObjectClass *class_a = (ObjectClass *)a;
2231eab15862SMichael Clark     ObjectClass *class_b = (ObjectClass *)b;
2232eab15862SMichael Clark     const char *name_a, *name_b;
2233eab15862SMichael Clark 
2234eab15862SMichael Clark     name_a = object_class_get_name(class_a);
2235eab15862SMichael Clark     name_b = object_class_get_name(class_b);
2236eab15862SMichael Clark     return strcmp(name_a, name_b);
2237eab15862SMichael Clark }
2238eab15862SMichael Clark 
2239eab15862SMichael Clark static void riscv_cpu_list_entry(gpointer data, gpointer user_data)
2240eab15862SMichael Clark {
2241eab15862SMichael Clark     const char *typename = object_class_get_name(OBJECT_CLASS(data));
2242eab15862SMichael Clark     int len = strlen(typename) - strlen(RISCV_CPU_TYPE_SUFFIX);
2243eab15862SMichael Clark 
22440442428aSMarkus Armbruster     qemu_printf("%.*s\n", len, typename);
2245eab15862SMichael Clark }
2246eab15862SMichael Clark 
22470442428aSMarkus Armbruster void riscv_cpu_list(void)
2248dc5bd18fSMichael Clark {
2249eab15862SMichael Clark     GSList *list;
2250dc5bd18fSMichael Clark 
2251eab15862SMichael Clark     list = object_class_get_list(TYPE_RISCV_CPU, false);
2252eab15862SMichael Clark     list = g_slist_sort(list, riscv_cpu_list_compare);
22530442428aSMarkus Armbruster     g_slist_foreach(list, riscv_cpu_list_entry, NULL);
2254eab15862SMichael Clark     g_slist_free(list);
2255dc5bd18fSMichael Clark }
2256dc5bd18fSMichael Clark 
2257eab15862SMichael Clark #define DEFINE_CPU(type_name, initfn)      \
2258eab15862SMichael Clark     {                                      \
2259eab15862SMichael Clark         .name = type_name,                 \
2260eab15862SMichael Clark         .parent = TYPE_RISCV_CPU,          \
2261eab15862SMichael Clark         .instance_init = initfn            \
2262eab15862SMichael Clark     }
2263eab15862SMichael Clark 
22649e1a30d3SDaniel Henrique Barboza #define DEFINE_DYNAMIC_CPU(type_name, initfn) \
22659e1a30d3SDaniel Henrique Barboza     {                                         \
22669e1a30d3SDaniel Henrique Barboza         .name = type_name,                    \
22679e1a30d3SDaniel Henrique Barboza         .parent = TYPE_RISCV_DYNAMIC_CPU,     \
22689e1a30d3SDaniel Henrique Barboza         .instance_init = initfn               \
22699e1a30d3SDaniel Henrique Barboza     }
22709e1a30d3SDaniel Henrique Barboza 
2271eab15862SMichael Clark static const TypeInfo riscv_cpu_type_infos[] = {
2272dc5bd18fSMichael Clark     {
2273eab15862SMichael Clark         .name = TYPE_RISCV_CPU,
2274eab15862SMichael Clark         .parent = TYPE_CPU,
2275eab15862SMichael Clark         .instance_size = sizeof(RISCVCPU),
22765de5b99bSRichard Henderson         .instance_align = __alignof__(RISCVCPU),
2277eab15862SMichael Clark         .instance_init = riscv_cpu_init,
2278eab15862SMichael Clark         .abstract = true,
2279eab15862SMichael Clark         .class_size = sizeof(RISCVCPUClass),
2280eab15862SMichael Clark         .class_init = riscv_cpu_class_init,
2281eab15862SMichael Clark     },
22829e1a30d3SDaniel Henrique Barboza     {
22839e1a30d3SDaniel Henrique Barboza         .name = TYPE_RISCV_DYNAMIC_CPU,
22849e1a30d3SDaniel Henrique Barboza         .parent = TYPE_RISCV_CPU,
22859e1a30d3SDaniel Henrique Barboza         .abstract = true,
22869e1a30d3SDaniel Henrique Barboza     },
22879e1a30d3SDaniel Henrique Barboza     DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_ANY,      riscv_any_cpu_init),
228810f1ca27SYifei Jiang #if defined(CONFIG_KVM)
228910f1ca27SYifei Jiang     DEFINE_CPU(TYPE_RISCV_CPU_HOST,             riscv_host_cpu_init),
229010f1ca27SYifei Jiang #endif
2291eab15862SMichael Clark #if defined(TARGET_RISCV32)
22929e1a30d3SDaniel Henrique Barboza     DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_BASE32,   rv32_base_cpu_init),
2293e8905c6cSBin Meng     DEFINE_CPU(TYPE_RISCV_CPU_IBEX,             rv32_ibex_cpu_init),
2294114baacaSAlistair Francis     DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E31,       rv32_sifive_e_cpu_init),
22952fdd2c09SBin Meng     DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E34,       rv32_imafcu_nommu_cpu_init),
2296114baacaSAlistair Francis     DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_U34,       rv32_sifive_u_cpu_init),
2297eab15862SMichael Clark #elif defined(TARGET_RISCV64)
22989e1a30d3SDaniel Henrique Barboza     DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_BASE64,   rv64_base_cpu_init),
2299114baacaSAlistair Francis     DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E51,       rv64_sifive_e_cpu_init),
2300114baacaSAlistair Francis     DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_U54,       rv64_sifive_u_cpu_init),
23016ddc7069SVijai Kumar K     DEFINE_CPU(TYPE_RISCV_CPU_SHAKTI_C,         rv64_sifive_u_cpu_init),
230295bd8daaSChristoph Müllner     DEFINE_CPU(TYPE_RISCV_CPU_THEAD_C906,       rv64_thead_c906_cpu_init),
2303e1d084a8SRahul Pathak     DEFINE_CPU(TYPE_RISCV_CPU_VEYRON_V1,        rv64_veyron_v1_cpu_init),
23049e1a30d3SDaniel Henrique Barboza     DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_BASE128,  rv128_base_cpu_init),
2305eab15862SMichael Clark #endif
2306eab15862SMichael Clark };
2307dc5bd18fSMichael Clark 
2308eab15862SMichael Clark DEFINE_TYPES(riscv_cpu_type_infos)
2309