aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Waterman <andrew@sifive.com>2019-11-13 05:22:18 -0800
committerGitHub <noreply@github.com>2019-11-13 05:22:18 -0800
commit2704790df5d16868571bacf4c521df4bac87f452 (patch)
tree5b80d59e0eb989d491f2c7db46a1a960e8236e67
parentff81dea8593c6e51b45e7bed230a2cafd56e4caf (diff)
parent86857aa3511d0a3bb1d28f8a6213013382545f77 (diff)
downloadspike-2704790df5d16868571bacf4c521df4bac87f452.zip
spike-2704790df5d16868571bacf4c521df4bac87f452.tar.gz
spike-2704790df5d16868571bacf4c521df4bac87f452.tar.bz2
Merge pull request #356 from riscv/priv-flag
Add --priv command-line option to set which privilege modes are available
-rw-r--r--ChangeLog.md1
-rw-r--r--config.h.in3
-rwxr-xr-xconfigure19
-rw-r--r--riscv/decode.h3
-rw-r--r--riscv/insns/sret.h1
-rw-r--r--riscv/processor.cc76
-rw-r--r--riscv/processor.h9
-rw-r--r--riscv/riscv.ac6
-rw-r--r--riscv/sim.cc7
-rw-r--r--riscv/sim.h3
-rw-r--r--spike_main/spike-dasm.cc2
-rw-r--r--spike_main/spike-log-parser.cc2
-rw-r--r--spike_main/spike.cc5
13 files changed, 106 insertions, 31 deletions
diff --git a/ChangeLog.md b/ChangeLog.md
index 9d456c2..2be2d4a 100644
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -3,6 +3,7 @@ Version 1.0.1-dev
- Preliminary support for a subset of the Vector Extension, v0.7.1.
- Support S-mode vectored interrupts (i.e. `stvec[0]` is now writable).
- Added support for dynamic linking of libraries containing MMIO devices.
+- Added `--priv` flag to control which privilege modes are available.
- When the commit log is enabled at configure time (`--enable-commitlog`),
it must also be enabled at runtime with the `--log-commits` option.
- Several debug-related additions and changes:
diff --git a/config.h.in b/config.h.in
index e82156d..4f7f39f 100644
--- a/config.h.in
+++ b/config.h.in
@@ -6,6 +6,9 @@
/* Default value for --isa switch */
#undef DEFAULT_ISA
+/* Default value for --priv switch */
+#undef DEFAULT_PRIV
+
/* Default value for --vector switch */
#undef DEFAULT_VARCH
diff --git a/configure b/configure
index bf8dd50..7c46e7b 100755
--- a/configure
+++ b/configure
@@ -702,6 +702,7 @@ enable_option_checking
enable_stow
enable_optional_subprojects
with_isa
+with_priv
with_varch
enable_commitlog
enable_histogram
@@ -1360,6 +1361,7 @@ Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
--without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
--with-isa=RV64IMAFDC Sets the default RISC-V ISA
+ --with-priv=MSU Sets the default RISC-V privilege modes supported
--with-varch=v128:e32:s128
Sets the default vector config
@@ -4620,6 +4622,23 @@ fi
+# Check whether --with-priv was given.
+if test "${with_priv+set}" = set; then :
+ withval=$with_priv;
+cat >>confdefs.h <<_ACEOF
+#define DEFAULT_PRIV "$withval"
+_ACEOF
+
+else
+
+cat >>confdefs.h <<_ACEOF
+#define DEFAULT_PRIV "MSU"
+_ACEOF
+
+fi
+
+
+
# Check whether --with-varch was given.
if test "${with_varch+set}" = set; then :
withval=$with_varch;
diff --git a/riscv/decode.h b/riscv/decode.h
index a756607..f8ac020 100644
--- a/riscv/decode.h
+++ b/riscv/decode.h
@@ -292,8 +292,9 @@ inline freg_t f128_negate(freg_t a)
if (!STATE.serialized) return PC_SERIALIZE_BEFORE; \
STATE.serialized = false; \
unsigned csr_priv = get_field((which), 0x300); \
+ bool mode_unsupported = csr_priv == PRV_S && !P.supports_extension('S'); \
unsigned csr_read_only = get_field((which), 0xC00) == 3; \
- if (((write) && csr_read_only) || STATE.prv < csr_priv) \
+ if (((write) && csr_read_only) || STATE.prv < csr_priv || mode_unsupported) \
throw trap_illegal_instruction(0); \
(which); })
diff --git a/riscv/insns/sret.h b/riscv/insns/sret.h
index ae841de..be837a3 100644
--- a/riscv/insns/sret.h
+++ b/riscv/insns/sret.h
@@ -1,3 +1,4 @@
+require_extension('S');
require_privilege(get_field(STATE.mstatus, MSTATUS_TSR) ? PRV_M : PRV_S);
set_pc_and_serialize(p->get_state()->sepc);
reg_t s = STATE.mstatus;
diff --git a/riscv/processor.cc b/riscv/processor.cc
index 59fa062..9b8050c 100644
--- a/riscv/processor.cc
+++ b/riscv/processor.cc
@@ -20,14 +20,15 @@
#undef STATE
#define STATE state
-processor_t::processor_t(const char* isa, const char* varch, simif_t* sim,
- uint32_t id, bool halt_on_reset)
+processor_t::processor_t(const char* isa, const char* priv, const char* varch,
+ simif_t* sim, uint32_t id, bool halt_on_reset)
: debug(false), halt_request(false), sim(sim), ext(NULL), id(id),
histogram_enabled(false), log_commits_enabled(false),
halt_on_reset(halt_on_reset), last_pc(1), executions(1)
{
VU.p = this;
parse_isa_string(isa);
+ parse_priv_string(priv);
parse_varch_string(varch);
register_base_instructions();
mmu = new mmu_t(sim, this);
@@ -61,6 +62,12 @@ static void bad_isa_string(const char* isa)
abort();
}
+static void bad_priv_string(const char* priv)
+{
+ fprintf(stderr, "error: bad --priv option %s\n", priv);
+ abort();
+}
+
static void bad_varch_string(const char* varch)
{
fprintf(stderr, "error: bad --varch option %s\n", varch);
@@ -121,11 +128,35 @@ void processor_t::parse_varch_string(const char* s)
VU.SLEN = slen;
}
-void processor_t::parse_isa_string(const char* str)
+static std::string strtolower(const char* str)
{
- std::string lowercase, tmp;
+ std::string res;
for (const char *r = str; *r; r++)
- lowercase += std::tolower(*r);
+ res += std::tolower(*r);
+ return res;
+}
+
+void processor_t::parse_priv_string(const char* str)
+{
+ std::string lowercase = strtolower(str);
+ bool user = false, supervisor = false;
+
+ if (lowercase == "m")
+ ;
+ else if (lowercase == "mu")
+ user = true;
+ else if (lowercase == "msu")
+ user = supervisor = true;
+ else
+ bad_priv_string(str);
+
+ max_isa |= reg_t(user) << ('u' - 'a');
+ max_isa |= reg_t(supervisor) << ('s' - 'a');
+}
+
+void processor_t::parse_isa_string(const char* str)
+{
+ std::string lowercase = strtolower(str), tmp;
const char* p = lowercase.c_str();
const char* all_subsets = "imafdqc"
@@ -135,10 +166,10 @@ void processor_t::parse_isa_string(const char* str)
"";
max_xlen = 64;
- state.misa = reg_t(2) << 62;
+ max_isa = reg_t(2) << 62;
if (strncmp(p, "rv32", 4) == 0)
- max_xlen = 32, state.misa = reg_t(1) << 30, p += 4;
+ max_xlen = 32, max_isa = reg_t(1) << 30, p += 4;
else if (strncmp(p, "rv64", 4) == 0)
p += 4;
else if (strncmp(p, "rv", 2) == 0)
@@ -154,11 +185,9 @@ void processor_t::parse_isa_string(const char* str)
}
isa_string = "rv" + std::to_string(max_xlen) + p;
- state.misa |= 1L << ('s' - 'a'); // advertise support for supervisor mode
- state.misa |= 1L << ('u' - 'a'); // advertise support for user mode
while (*p) {
- state.misa |= 1L << (*p - 'a');
+ max_isa |= 1L << (*p - 'a');
if (auto next = strchr(all_subsets, *p)) {
all_subsets = next + 1;
@@ -179,8 +208,6 @@ void processor_t::parse_isa_string(const char* str)
if (supports_extension('Q') && !supports_extension('D'))
bad_isa_string(str);
-
- max_isa = state.misa;
}
void state_t::reset(reg_t max_isa)
@@ -349,7 +376,7 @@ reg_t processor_t::legalize_privilege(reg_t prv)
if (!supports_extension('U'))
return PRV_M;
- if (prv == PRV_H || !supports_extension('S'))
+ if (prv == PRV_H || (prv == PRV_S && !supports_extension('S')))
return PRV_U;
return prv;
@@ -461,8 +488,9 @@ int processor_t::paddr_bits()
void processor_t::set_csr(int which, reg_t val)
{
val = zext_xlen(val);
- reg_t delegable_ints = MIP_SSIP | MIP_STIP | MIP_SEIP
- | ((ext != NULL) << IRQ_COP);
+ reg_t supervisor_ints = supports_extension('S') ? MIP_SSIP | MIP_STIP | MIP_SEIP : 0;
+ reg_t coprocessor_ints = (ext != NULL) << IRQ_COP;
+ reg_t delegable_ints = supervisor_ints | coprocessor_ints;
reg_t all_ints = delegable_ints | MIP_MSIP | MIP_MTIP;
if (which >= CSR_PMPADDR0 && which < CSR_PMPADDR0 + state.n_pmp) {
@@ -507,10 +535,14 @@ void processor_t::set_csr(int which, reg_t val)
(MSTATUS_MPP | MSTATUS_MPRV | MSTATUS_SUM | MSTATUS_MXR))
mmu->flush_tlb();
+ bool has_fs = supports_extension('S') || supports_extension('F')
+ || supports_extension('V');
+
reg_t mask = MSTATUS_SIE | MSTATUS_SPIE | MSTATUS_MIE | MSTATUS_MPIE
- | MSTATUS_FS | MSTATUS_MPRV | MSTATUS_SUM
+ | MSTATUS_MPRV | MSTATUS_SUM
| MSTATUS_MXR | MSTATUS_TW | MSTATUS_TVM
| MSTATUS_TSR | MSTATUS_UXL | MSTATUS_SXL |
+ (has_fs ? MSTATUS_FS : 0) |
(ext ? MSTATUS_XS : 0);
reg_t requested_mpp = legalize_privilege(get_field(val, MSTATUS_MPP));
@@ -534,7 +566,7 @@ void processor_t::set_csr(int which, reg_t val)
break;
}
case CSR_MIP: {
- reg_t mask = MIP_SSIP | MIP_STIP;
+ reg_t mask = supervisor_ints & (MIP_SSIP | MIP_STIP);
state.mip = (state.mip & ~mask) | (val & mask);
break;
}
@@ -809,8 +841,14 @@ reg_t processor_t::get_csr(int which)
case CSR_MVENDORID: return 0;
case CSR_MHARTID: return id;
case CSR_MTVEC: return state.mtvec;
- case CSR_MEDELEG: return state.medeleg;
- case CSR_MIDELEG: return state.mideleg;
+ case CSR_MEDELEG:
+ if (!supports_extension('S'))
+ break;
+ return state.medeleg;
+ case CSR_MIDELEG:
+ if (!supports_extension('S'))
+ break;
+ return state.mideleg;
case CSR_TSELECT: return state.tselect;
case CSR_TDATA1:
if (state.tselect < state.num_triggers) {
diff --git a/riscv/processor.h b/riscv/processor.h
index 3e72282..bcf36c5 100644
--- a/riscv/processor.h
+++ b/riscv/processor.h
@@ -297,8 +297,8 @@ static int cto(reg_t val)
class processor_t : public abstract_device_t
{
public:
- processor_t(const char* isa, const char* varch, simif_t* sim, uint32_t id,
- bool halt_on_reset=false);
+ processor_t(const char* isa, const char* priv, const char* varch,
+ simif_t* sim, uint32_t id, bool halt_on_reset=false);
~processor_t();
void set_debug(bool value);
@@ -465,8 +465,9 @@ private:
friend class clint_t;
friend class extension_t;
- void parse_varch_string(const char* isa);
- void parse_isa_string(const char* isa);
+ void parse_varch_string(const char*);
+ void parse_priv_string(const char*);
+ void parse_isa_string(const char*);
void build_opcode_map();
void register_base_instructions();
insn_func_t decode_insn(insn_t insn);
diff --git a/riscv/riscv.ac b/riscv/riscv.ac
index 40cf706..747c3e3 100644
--- a/riscv/riscv.ac
+++ b/riscv/riscv.ac
@@ -6,6 +6,12 @@ AC_ARG_WITH(isa,
AC_DEFINE_UNQUOTED([DEFAULT_ISA], "$withval", [Default value for --isa switch]),
AC_DEFINE_UNQUOTED([DEFAULT_ISA], "RV64IMAFDC", [Default value for --isa switch]))
+AC_ARG_WITH(priv,
+ [AS_HELP_STRING([--with-priv=MSU],
+ [Sets the default RISC-V privilege modes supported])],
+ AC_DEFINE_UNQUOTED([DEFAULT_PRIV], "$withval", [Default value for --priv switch]),
+ AC_DEFINE_UNQUOTED([DEFAULT_PRIV], "MSU", [Default value for --priv switch]))
+
AC_ARG_WITH(varch,
[AS_HELP_STRING([--with-varch=v128:e32:s128],
[Sets the default vector config])],
diff --git a/riscv/sim.cc b/riscv/sim.cc
index eca7057..7d6f3c1 100644
--- a/riscv/sim.cc
+++ b/riscv/sim.cc
@@ -25,7 +25,8 @@ static void handle_signal(int sig)
signal(sig, &handle_signal);
}
-sim_t::sim_t(const char* isa, const char* varch, size_t nprocs, bool halted,
+sim_t::sim_t(const char* isa, const char* priv, const char* varch,
+ size_t nprocs, bool halted,
reg_t start_pc, std::vector<std::pair<reg_t, mem_t*>> mems,
std::vector<std::pair<reg_t, abstract_device_t*>> plugin_devices,
const std::vector<std::string>& args,
@@ -51,7 +52,7 @@ sim_t::sim_t(const char* isa, const char* varch, size_t nprocs, bool halted,
if (hartids.size() == 0) {
for (size_t i = 0; i < procs.size(); i++) {
- procs[i] = new processor_t(isa, varch, this, i, halted);
+ procs[i] = new processor_t(isa, priv, varch, this, i, halted);
}
}
else {
@@ -60,7 +61,7 @@ sim_t::sim_t(const char* isa, const char* varch, size_t nprocs, bool halted,
exit(1);
}
for (size_t i = 0; i < procs.size(); i++) {
- procs[i] = new processor_t(isa, varch, this, hartids[i], halted);
+ procs[i] = new processor_t(isa, priv, varch, this, hartids[i], halted);
}
}
diff --git a/riscv/sim.h b/riscv/sim.h
index 0720ce4..3b7e25c 100644
--- a/riscv/sim.h
+++ b/riscv/sim.h
@@ -21,7 +21,8 @@ class remote_bitbang_t;
class sim_t : public htif_t, public simif_t
{
public:
- sim_t(const char* isa, const char* varch, size_t _nprocs, bool halted,
+ sim_t(const char* isa, const char* priv, const char* varch, size_t _nprocs,
+ bool halted,
reg_t start_pc, std::vector<std::pair<reg_t, mem_t*>> mems,
std::vector<std::pair<reg_t, abstract_device_t*>> plugin_devices,
const std::vector<std::string>& args, const std::vector<int> hartids,
diff --git a/spike_main/spike-dasm.cc b/spike_main/spike-dasm.cc
index 044f220..4ec9d35 100644
--- a/spike_main/spike-dasm.cc
+++ b/spike_main/spike-dasm.cc
@@ -25,7 +25,7 @@ int main(int argc, char** argv)
parser.option(0, "isa", 1, [&](const char* s){isa = s;});
parser.parse(argv);
- processor_t p(isa, DEFAULT_VARCH, 0, 0);
+ processor_t p(isa, DEFAULT_PRIV, DEFAULT_VARCH, 0, 0);
if (extension)
p.register_extension(extension());
diff --git a/spike_main/spike-log-parser.cc b/spike_main/spike-log-parser.cc
index fd07f53..5de6220 100644
--- a/spike_main/spike-log-parser.cc
+++ b/spike_main/spike-log-parser.cc
@@ -27,7 +27,7 @@ int main(int argc, char** argv)
parser.option(0, "isa", 1, [&](const char* s){isa = s;});
parser.parse(argv);
- processor_t p(isa, DEFAULT_VARCH, 0, 0);
+ processor_t p(isa, DEFAULT_PRIV, DEFAULT_VARCH, 0, 0);
if (extension) {
p.register_extension(extension());
}
diff --git a/spike_main/spike.cc b/spike_main/spike.cc
index 19f877b..4656a0a 100644
--- a/spike_main/spike.cc
+++ b/spike_main/spike.cc
@@ -29,6 +29,7 @@ static void help(int exit_code = 1)
fprintf(stderr, " -h, --help Print this help message\n");
fprintf(stderr, " -H Start halted, allowing a debugger to connect\n");
fprintf(stderr, " --isa=<name> RISC-V ISA string [default %s]\n", DEFAULT_ISA);
+ fprintf(stderr, " --priv=<m|mu|msu> RISC-V privilege modes supported [default %s]\n", DEFAULT_PRIV);
fprintf(stderr, " --varch=<name> RISC-V Vector uArch string [default %s]\n", DEFAULT_VARCH);
fprintf(stderr, " --pc=<address> Override ELF entry point\n");
fprintf(stderr, " --hartids=<a,b,...> Explicitly specify hartids, default is 0,1,...\n");
@@ -119,6 +120,7 @@ int main(int argc, char** argv)
bool log_commits = false;
std::function<extension_t*()> extension;
const char* isa = DEFAULT_ISA;
+ const char* priv = DEFAULT_PRIV;
const char* varch = DEFAULT_VARCH;
uint16_t rbb_port = 0;
bool use_rbb = false;
@@ -207,6 +209,7 @@ int main(int argc, char** argv)
parser.option(0, "l2", 1, [&](const char* s){l2.reset(cache_sim_t::construct(s, "L2$"));});
parser.option(0, "log-cache-miss", 0, [&](const char* s){log_cache = true;});
parser.option(0, "isa", 1, [&](const char* s){isa = s;});
+ parser.option(0, "priv", 1, [&](const char* s){priv = s;});
parser.option(0, "varch", 1, [&](const char* s){varch = s;});
parser.option(0, "device", 1, device_parser);
parser.option(0, "extension", 1, [&](const char* s){extension = find_extension(s);});
@@ -245,7 +248,7 @@ int main(int argc, char** argv)
if (!*argv1)
help();
- sim_t s(isa, varch, nprocs, halted, start_pc, mems, plugin_devices, htif_args,
+ sim_t s(isa, priv, varch, nprocs, halted, start_pc, mems, plugin_devices, htif_args,
std::move(hartids), dm_config);
std::unique_ptr<remote_bitbang_t> remote_bitbang((remote_bitbang_t *) NULL);
std::unique_ptr<jtag_dtm_t> jtag_dtm(