Fix paddr_bits computation prior to VM setup
[riscv-isa-sim.git] / riscv / htif.cc
index 438d86274cdc5dd9069682fe86490fcefa2fb108..6e8fee9e462127e07f8ff8ac8ec962b3dd067974 100644 (file)
@@ -1,5 +1,9 @@
+// See LICENSE for license details.
+
 #include "htif.h"
 #include "sim.h"
+#include "mmu.h"
+#include "encoding.h"
 #include <unistd.h>
 #include <stdexcept>
 #include <stdlib.h>
@@ -13,9 +17,14 @@ htif_isasim_t::htif_isasim_t(sim_t* _sim, const std::vector<std::string>& args)
 {
 }
 
-void htif_isasim_t::tick()
+bool htif_isasim_t::tick()
 {
+  if (done())
+    return false;
+
   do tick_once(); while (reset);
+
+  return true;
 }
 
 void htif_isasim_t::tick_once()
@@ -38,17 +47,30 @@ void htif_isasim_t::tick_once()
       send(&ack, sizeof(ack));
 
       uint64_t buf[hdr.data_size];
-      for (size_t i = 0; i < hdr.data_size; i++)
-        buf[i] = sim->mmu->load_uint64((hdr.addr+i)*HTIF_DATA_ALIGN);
+      for (size_t i = 0; i < hdr.data_size; i++) {
+        reg_t addr = (hdr.addr + i) * HTIF_DATA_ALIGN;
+        try {
+          buf[i] = sim->debug_mmu->load_uint64(addr);
+        } catch (trap_load_access_fault& e) {
+          fprintf(stderr, "HTIF: attempt to read from illegal address 0x%" PRIx64 "\n", addr);
+          exit(-1);
+        }
+      }
       send(buf, hdr.data_size * sizeof(buf[0]));
       break;
     }
     case HTIF_CMD_WRITE_MEM:
     {
       const uint64_t* buf = (const uint64_t*)p.get_payload();
-      for (size_t i = 0; i < hdr.data_size; i++)
-        sim->mmu->store_uint64((hdr.addr+i)*HTIF_DATA_ALIGN, buf[i]);
-
+      for (size_t i = 0; i < hdr.data_size; i++) {
+        reg_t addr = (hdr.addr + i) * HTIF_DATA_ALIGN;
+        try {
+          sim->debug_mmu->store_uint64(addr, buf[i]);
+        } catch (trap_store_access_fault& e) {
+          fprintf(stderr, "HTIF: attempt to write to illegal address 0x%" PRIx64 "\n", addr);
+          exit(-1);
+        }
+      }
       packet_header_t ack(HTIF_CMD_ACK, seqno, 0, 0);
       send(&ack, sizeof(ack));
       break;
@@ -56,42 +78,34 @@ void htif_isasim_t::tick_once()
     case HTIF_CMD_READ_CONTROL_REG:
     case HTIF_CMD_WRITE_CONTROL_REG:
     {
+      assert(hdr.data_size == 1);
       reg_t coreid = hdr.addr >> 20;
       reg_t regno = hdr.addr & ((1<<20)-1);
-      assert(hdr.data_size == 1);
+      uint64_t old_val, new_val = 0 /* shut up gcc */;
 
       packet_header_t ack(HTIF_CMD_ACK, seqno, 1, 0);
       send(&ack, sizeof(ack));
 
-      if (coreid == 0xFFFFF) // system control register space
+      processor_t* proc = sim->get_core(coreid);
+      bool write = hdr.cmd == HTIF_CMD_WRITE_CONTROL_REG;
+      if (write)
+        memcpy(&new_val, p.get_payload(), sizeof(new_val));
+
+      switch (regno)
       {
-        uint64_t scr = sim->get_scr(regno);
-        send(&scr, sizeof(scr));
-        break;
+        case CSR_MRESET:
+          old_val = !proc->running();
+          if (write)
+          {
+            reset = reset & (new_val & 1);
+            proc->reset(new_val & 1);
+          }
+          break;
+        default:
+          abort();
       }
 
-      assert(coreid < sim->num_cores());
-      uint64_t old_val = sim->procs[coreid]->get_pcr(regno);
       send(&old_val, sizeof(old_val));
-
-      if (regno == PCR_TOHOST)
-          sim->procs[coreid]->tohost = 0;
-
-      if (hdr.cmd == HTIF_CMD_WRITE_CONTROL_REG)
-      {
-        uint64_t new_val;
-        memcpy(&new_val, p.get_payload(), sizeof(new_val));
-        if (regno == PCR_RESET)
-        {
-          if (reset && !(new_val & 1))
-            reset = false;
-          sim->procs[coreid]->reset(new_val & 1);
-        }
-        else if (regno == PCR_FROMHOST && old_val != 0)
-          ; // ignore host writes to fromhost if target hasn't yet consumed
-        else
-          sim->procs[coreid]->set_pcr(regno, new_val);
-      }
       break;
     }
     default:
@@ -104,8 +118,5 @@ bool htif_isasim_t::done()
 {
   if (reset)
     return false;
-  for (size_t i = 0; i < sim->num_cores(); i++)
-    if (sim->procs[i]->running())
-      return false;
-  return true;
+  return !sim->running();
 }