ISACaller: fix syscall emulation
authorJacob Lifshay <programmerjake@gmail.com>
Fri, 1 Dec 2023 07:15:45 +0000 (23:15 -0800)
committerJacob Lifshay <programmerjake@gmail.com>
Fri, 1 Dec 2023 07:24:45 +0000 (23:24 -0800)
there were two bugs fixed:
1. sc emulation was missing a `return`, so it tried to run sc
   again after running sc and rfid, giving the wrong CIA and
   MSR values.
2. the code to replace and restore the instruction with rfid
   had the wrong endian on the load, so it was corrupting the
   instruction for the next time it was used. I just deleted
   the save/replace/restore code since it isn't needed anymore.

I then changed the syscall tests to ensure both the
bugs above don't happen again.

src/openpower/decoder/isa/caller.py
src/openpower/decoder/isa/test_syscall.py

index 735252c78f75d54fad9adb522e540c2fdef84ddf..409fedfb21740407a885b1397182f3ebc8838a36 100644 (file)
@@ -2011,8 +2011,6 @@ class ISACaller(ISACallerHelper, ISAFPHelpers, StepLoop):
         # 2. Call the HDL implementation which invokes trap.
         # 3. Reroute the guest system call to host system call.
         # 4. Force return from the interrupt as if we had guest OS.
-        #    "executing" rfid requires putting 0x4c000024 temporarily
-        #    into the program at the PC. TODO investigate and remove
         if ((asmop in ("sc", "scv")) and
                 (self.syscall is not None) and
                 not syscall_emu_active):
@@ -2030,10 +2028,8 @@ class ISACaller(ISACallerHelper, ISAFPHelpers, StepLoop):
             self.gpr.write(3, result, False, self.namespace["XLEN"])
 
             # Return from interrupt
-            backup = self.imem.ld(pc, 4, False, True, instr_fetch=True)
-            self.imem.st(pc, 0x4c000024, width=4, swap=True)
             yield from self.call("rfid", syscall_emu_active=True)
-            self.imem.st(pc, backup, width=4, swap=True)
+            return
         elif ((name in ("rfid", "hrfid")) and syscall_emu_active):
             asmop = "rfid"
 
index 2bbd27da74222248b45b23946c1b27756e12e9ee..580bdbcd60845149ed8271a7922090156a676803 100644 (file)
@@ -62,14 +62,15 @@ class SyscallTestCase(FHDLTestCase):
         MSR[52:58] = SRR1[52:58]
         MSR[60:64] = SRR1[60:64]
 
-        self.assertEqual(sim.spr['SRR0'], 8)    # PC to return to: CIA+4
+        self.assertEqual(sim.spr['SRR0'], 4)    # PC to return to: CIA+4
         self.assertEqual(sim.spr['SRR1'], SRR1) # MSR to restore after sc return
 
-        # FIXME this is currently hardcoded to the same way as in test_trap.py.
-        # However, I'd have expected 0x9000000000002903, not 0x9000000000000001.
-        MSR = SelectableInt(0x9000000000000001, 64)
+        MSR = SelectableInt(0x9000000000002903, 64)
         self.assertEqual(sim.msr, MSR)          # MSR changed to this by sc/trap
 
+        # we need to actually return to right after the sc
+        self.assertEqual(sim.pc.CIA, 4)
+
         print("SYSCALL SRR1", hex(int(SRR1)), hex(int(sim.spr['SRR1'])))
         print("SYSCALL MSR", hex(int(MSR)), hex(int(sim.msr)), hex(DEFAULT_MSR))
         return sim
@@ -80,6 +81,8 @@ class SyscallTestCase(FHDLTestCase):
         initial_regs[0] = 20 # getpid
         with Program(lst, bigendian=False) as program:
             sim = self.run_tst_program(program, initial_regs)
+            self.assertEqual(hex(sim.imem.ld(0, width=8, swap=False)),
+                             "0x44000002", "insn wasn't restored correctly")
             self.assertEqual(sim.gpr(3), os.getpid())
 
     def test_sc_getuid(self):