Merge "Add trap handlers to exception tests"
diff --git a/tests/kelvin_isa/BUILD b/tests/kelvin_isa/BUILD
index b606fad..004da08 100644
--- a/tests/kelvin_isa/BUILD
+++ b/tests/kelvin_isa/BUILD
@@ -51,20 +51,6 @@
 )
 
 kelvin_test(
-    name = "mret_fault",
-    srcs = [
-        "mret_fault.cc",
-    ],
-    hw_test_size = "small",
-    deps = [
-        ":kelvin_test",
-    ],
-    iss = False,
-    expect_success = False,
-    tags = ["intentional_failure"],
-)
-
-kelvin_test(
     name = "instr_fault",
     srcs = [
         "instr_fault.cc",
@@ -74,8 +60,7 @@
         ":kelvin_test",
     ],
     iss = False,
-    expect_success = False,
-    tags = ["intentional_failure"],
+    tags = ["exceptions"],
 )
 
 kelvin_test(
@@ -88,8 +73,7 @@
         ":kelvin_test",
     ],
     iss = False,
-    expect_success = False,
-    tags = ["intentional_failure"],
+    tags = ["exceptions"],
 )
 
 kelvin_test(
@@ -102,8 +86,7 @@
         ":kelvin_test",
     ],
     iss = False,
-    expect_success = False,
-    tags = ["intentional_failure"],
+    tags = ["exceptions"],
 )
 
 kelvin_test(
@@ -116,8 +99,7 @@
         ":kelvin_test",
     ],
     iss = False,
-    expect_success = False,
-    tags = ["intentional_failure"],
+    tags = ["exceptions"],
 )
 
 kelvin_test(
@@ -130,8 +112,7 @@
         ":kelvin_test",
     ],
     iss = False,
-    expect_success = False,
-    tags = ["intentional_failure"],
+    tags = ["exceptions"],
 )
 
 kelvin_test(
@@ -144,8 +125,7 @@
         ":kelvin_test",
     ],
     iss = False,
-    expect_success = False,
-    tags = ["intentional_failure"],
+    tags = ["exceptions"],
 )
 
 kelvin_test(
@@ -158,8 +138,7 @@
         ":kelvin_test",
     ],
     iss = False,
-    expect_success = False,
-    tags = ["intentional_failure"],
+    tags = ["exceptions"],
 )
 
 kelvin_test(
@@ -172,8 +151,9 @@
         ":kelvin_test",
     ],
     iss = False,
-    # This passes on core_sim, but should fail on core_mini_sim.
-    # expect_success = False,
+    # This fails on core_sim, but should pass on core_mini_sim.
+    expect_success = False,
+    tags = ["exceptions"],
 )
 
 kelvin_test(
@@ -186,8 +166,7 @@
         ":kelvin_test",
     ],
     iss = False,
-    expect_success = False,
-    tags = ["intentional_failure"],
+    tags = ["exceptions"],
 )
 
 kelvin_test(
diff --git a/tests/kelvin_isa/illegal.cc b/tests/kelvin_isa/illegal.cc
index 418ee00..b476450 100644
--- a/tests/kelvin_isa/illegal.cc
+++ b/tests/kelvin_isa/illegal.cc
@@ -14,7 +14,28 @@
 
 #include <cstdint>
 
+extern "C" {
+void isr_wrapper(void);
+__attribute__((naked)) void isr_wrapper(void) {
+  asm volatile(
+      "csrr t0, mepc \n"
+      "addi t0, t0, 4 \n"
+      "csrw mepc, t0 \n"
+      "csrr t0, mcause \n"
+      "li t1, 2 \n"
+      "beq t0, t1, 0f \n"
+      "csrr t0, mtval \n"
+      "la t1, 0x02007043 \n"
+      "beq t0, t1, 0f \n"
+      "ebreak \n"
+      "0: mpause \n"
+  );
+}
+
+}  // extern "C"
+
 int main(int argc, char** argv) {
+  asm volatile("csrw mtvec, %0" :: "rK"((uint32_t)(&isr_wrapper)));
   asm volatile(".word 0x02007043"); // fmadd.d f0, f0, f0, f0
 
   return 0;
diff --git a/tests/kelvin_isa/instr_align_0.cc b/tests/kelvin_isa/instr_align_0.cc
index 303e279..375b48d 100644
--- a/tests/kelvin_isa/instr_align_0.cc
+++ b/tests/kelvin_isa/instr_align_0.cc
@@ -14,9 +14,27 @@
 
 #include <cstdint>
 
+extern "C" {
+void isr_wrapper(void);
+__attribute__((naked)) void isr_wrapper(void) {
+  asm volatile(
+      "csrr t0, mepc \n"
+      "addi t0, t0, 4 \n"
+      "csrw mepc, t0 \n"
+      "csrr t0, mcause \n"
+      "li t1, 0 \n"
+      "beq t0, t1, 0f \n"
+      "ebreak \n"
+      "0: mpause \n"
+  );
+}
+
+}  // extern "C"
+
 int main(int argc, char** argv) {
   // Instruction address misaligned
-  asm volatile("la ra, 0x3; jalr ra,ra");
+  asm volatile("csrw mtvec, %0" :: "rK"((uint32_t)(&isr_wrapper)));
+  asm volatile("la ra, 0x3; nop; nop; nop; nop; jalr ra,ra");
 
   return 0;
 }
diff --git a/tests/kelvin_isa/instr_align_1.cc b/tests/kelvin_isa/instr_align_1.cc
index 1ee81d1..a99c8f7 100644
--- a/tests/kelvin_isa/instr_align_1.cc
+++ b/tests/kelvin_isa/instr_align_1.cc
@@ -14,9 +14,28 @@
 
 #include <cstdint>
 
+extern "C" {
+void isr_wrapper(void);
+__attribute__((naked)) void isr_wrapper(void) {
+  asm volatile(
+      "csrr t0, mepc \n"
+      "addi t0, t0, 4 \n"
+      "csrw mepc, t0 \n"
+      "csrr t0, mcause \n"
+      "li t1, 0 \n"
+      "beq t0, t1, 0f \n"
+      "ebreak \n"
+      "0: mpause \n"
+  );
+}
+
+}  // extern "C"
+
 int main(int argc, char** argv) {
   // Instruction address misaligned
-  asm volatile("jal x0, .+2");
+  // // TODO(atv): Make multiple versions of this for slot utilization purposes.
+  asm volatile("csrw mtvec, %0" :: "rK"((uint32_t)(&isr_wrapper)));
+  asm volatile("nop; jal x0, .+2");
 
   return 0;
 }
diff --git a/tests/kelvin_isa/instr_align_2.cc b/tests/kelvin_isa/instr_align_2.cc
index 21aa0b7..a6a9507 100644
--- a/tests/kelvin_isa/instr_align_2.cc
+++ b/tests/kelvin_isa/instr_align_2.cc
@@ -14,8 +14,26 @@
 
 #include <cstdint>
 
+extern "C" {
+void isr_wrapper(void);
+__attribute__((naked)) void isr_wrapper(void) {
+  asm volatile(
+      "csrr t0, mepc \n"
+      "addi t0, t0, 4 \n"
+      "csrw mepc, t0 \n"
+      "csrr t0, mcause \n"
+      "li t1, 0 \n"
+      "beq t0, t1, 0f \n"
+      "ebreak \n"
+      "0: mpause \n"
+  );
+}
+
+}  // extern "C"
+
 int main(int argc, char** argv) {
   // Instruction address misaligned
+  asm volatile("csrw mtvec, %0" :: "rK"((uint32_t)(&isr_wrapper)));
   asm volatile("beqz x0, .+2");
 
   return 0;
diff --git a/tests/kelvin_isa/instr_fault.cc b/tests/kelvin_isa/instr_fault.cc
index c3e974f..f7981b2 100644
--- a/tests/kelvin_isa/instr_fault.cc
+++ b/tests/kelvin_isa/instr_fault.cc
@@ -12,7 +12,27 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+#include <cstdint>
+
+extern "C" {
+void isr_wrapper(void);
+__attribute__((naked)) void isr_wrapper(void) {
+  asm volatile(
+      "csrr t0, mepc \n"
+      "addi t0, t0, 4 \n"
+      "csrw mepc, t0 \n"
+      "csrr t0, mcause \n"
+      "li t1, 1 \n"
+      "beq t0, t1, 0f \n"
+      "ebreak \n"
+      "0: mpause \n"
+  );
+}
+
+}  // extern "C"
+   //
 int main(int argc, char** argv) {
+  asm volatile("csrw mtvec, %0" :: "rK"((uint32_t)(&isr_wrapper)));
   asm volatile("la ra, 0x40000000; jalr ra, ra");
 
   return 0;
diff --git a/tests/kelvin_isa/load_fault_0.cc b/tests/kelvin_isa/load_fault_0.cc
index c3e974f..1a60889 100644
--- a/tests/kelvin_isa/load_fault_0.cc
+++ b/tests/kelvin_isa/load_fault_0.cc
@@ -12,8 +12,28 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-int main(int argc, char** argv) {
-  asm volatile("la ra, 0x40000000; jalr ra, ra");
+#include <cstdint>
 
+extern "C" {
+void isr_wrapper(void);
+__attribute__((naked)) void isr_wrapper(void) {
+  asm volatile(
+      "csrr t0, mepc \n"
+      "addi t0, t0, 4 \n"
+      "csrw mepc, t0 \n"
+      "csrr t0, mcause \n"
+      "li t1, 1 \n"
+      "beq t0, t1, 0f \n"
+      "ebreak \n"
+      "0: mpause \n"
+  );
+}
+
+}  // extern "C"
+
+int main(int argc, char** argv) {
+  asm volatile("csrw mtvec, %0" :: "rK"((uint32_t)(&isr_wrapper)));
+  asm volatile("la ra, 0x40000000; jalr ra, ra");
+  asm volatile("ebreak");
   return 0;
 }
diff --git a/tests/kelvin_isa/load_fault_1.cc b/tests/kelvin_isa/load_fault_1.cc
index 78f7beb..48a93cb 100644
--- a/tests/kelvin_isa/load_fault_1.cc
+++ b/tests/kelvin_isa/load_fault_1.cc
@@ -14,10 +14,32 @@
 
 #include <cstdint>
 
+extern "C" {
+void isr_wrapper(void);
+__attribute__((naked)) void isr_wrapper(void) {
+  asm volatile(
+      "csrr t0, mepc \n"
+      "addi t0, t0, 4 \n"
+      "csrw mepc, t0 \n"
+      "csrr t0, mcause \n"
+      "li t1, 5 \n"
+      "bne t0, t1, 0f \n"
+      "csrr t0, mtval \n"
+      "la t1, 0xA0000000 \n"
+      "bne t0, t1, 0f \n"
+      "mpause \n"
+      "0: ebreak \n"
+  );
+}
+
+}  // extern "C"
+
 int main(int argc, char** argv) {
+  asm volatile("csrw mtvec, %0" :: "rK"((uint32_t)(&isr_wrapper)));
   volatile uint32_t* load_bad_addr = (uint32_t*)0xA0000000;
   volatile uint32_t foo = *load_bad_addr;
   (void)foo;
+  asm volatile("ebreak");
 
   return 0;
 }
diff --git a/tests/kelvin_isa/mret_fault.cc b/tests/kelvin_isa/mret_fault.cc
deleted file mode 100644
index 3a16b5e..0000000
--- a/tests/kelvin_isa/mret_fault.cc
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright 2025 Google LLC
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include <cstdint>
-
-extern "C" {
-
-void isr_wrapper(void);
-__attribute__((naked)) void isr_wrapper() {
-  asm volatile(
-      "csrr t0, mepc \n"
-      "addi t0, t0, 2 \n"
-      "csrw mepc, t0 \n"
-      "mret \n");
-}
-void bad_isr(void);
-__attribute__((naked)) void bad_isr() { asm volatile("ebreak \n"); }
-
-__attribute__((naked, aligned(256))) void isr_vector_table() {
-  asm volatile(
-      "j isr_wrapper \n"
-      "j bad_isr \n"
-      "j bad_isr \n"
-      "j bad_isr \n"
-      "j bad_isr \n"
-      "j bad_isr \n"
-      "j bad_isr \n"
-      "j bad_isr \n"
-      "j bad_isr \n"
-      "j bad_isr \n"
-      "j bad_isr \n"
-      "j bad_isr \n"
-      "j bad_isr \n"
-      "j bad_isr \n"
-      "j bad_isr \n"
-      "j bad_isr \n"
-      "j bad_isr \n"
-      "j bad_isr \n"
-      "j bad_isr \n"
-      "j bad_isr \n"
-      "j bad_isr \n"
-      "j bad_isr \n"
-      "j bad_isr \n"
-      "j bad_isr \n"
-      "j bad_isr \n"
-      "j bad_isr \n"
-      "j bad_isr \n"
-      "j bad_isr \n"
-      "j bad_isr \n"
-      "j bad_isr \n"
-      "j bad_isr \n"
-      "j bad_isr \n");
-}
-
-int main(int argc, char** argv) {
-  asm volatile("csrw mtvec, %0" ::"rK"((uint32_t)(&isr_vector_table)));
-  asm volatile("ecall");
-  return 0;
-}
-
-}  // extern "C"
\ No newline at end of file
diff --git a/tests/kelvin_isa/store_fault_0.cc b/tests/kelvin_isa/store_fault_0.cc
index 68c5094..04051f7 100644
--- a/tests/kelvin_isa/store_fault_0.cc
+++ b/tests/kelvin_isa/store_fault_0.cc
@@ -14,10 +14,32 @@
 
 #include <cstdint>
 
+extern "C" {
+void isr_wrapper(void);
+__attribute__((naked)) void isr_wrapper(void) {
+  asm volatile(
+      "csrr t0, mepc \n"
+      "addi t0, t0, 4 \n"
+      "csrw mepc, t0 \n"
+      "csrr t0, mcause \n"
+      "li t1, 7 \n"
+      "beq t0, t1, 0f \n"
+      "csrr t0, mtval \n"
+      "li t1, 0x4 \n"
+      "beq t0, t1, 0f \n"
+      "ebreak \n"
+      "0: mpause \n"
+  );
+}
+
+}  // extern "C"
+
 int main(int argc, char** argv) {
   // Store Fault (internal)
+  asm volatile("csrw mtvec, %0" :: "rK"((uint32_t)(&isr_wrapper)));
   volatile uint32_t* store_bad_addr = (uint32_t*)4L;
   *store_bad_addr = 0xdeadbeef;
+  asm volatile("ebreak");
 
   return 0;
 }
diff --git a/tests/kelvin_isa/store_fault_1.cc b/tests/kelvin_isa/store_fault_1.cc
index bb5d2fc..e646ccd 100644
--- a/tests/kelvin_isa/store_fault_1.cc
+++ b/tests/kelvin_isa/store_fault_1.cc
@@ -14,8 +14,29 @@
 
 #include <cstdint>
 
+extern "C" {
+void isr_wrapper(void);
+__attribute__((naked)) void isr_wrapper(void) {
+  asm volatile(
+      "csrr t0, mepc \n"
+      "addi t0, t0, 4 \n"
+      "csrw mepc, t0 \n"
+      "csrr t0, mcause \n"
+      "li t1, 7 \n"
+      "beq t0, t1, 0f \n"
+      "csrr t0, mtval \n"
+      "li t1, 0xA0000000 \n"
+      "beq t0, t1, 0f \n"
+      "ebreak \n"
+      "0: mpause \n"
+  );
+}
+
+}  // extern "C"
+
 int main(int argc, char** argv) {
   // Store Fault (external)
+  asm volatile("csrw mtvec, %0" :: "rK"((uint32_t)(&isr_wrapper)));
   volatile uint32_t* store_bad_addr = (uint32_t*)0xA0000000;
   *store_bad_addr = 0xdeadbeef;
 
diff --git a/tests/riscv-tests/BUILD b/tests/riscv-tests/BUILD
index b224702..d152f21 100644
--- a/tests/riscv-tests/BUILD
+++ b/tests/riscv-tests/BUILD
@@ -223,6 +223,25 @@
     ],
 )
 
+# kelvin_test(
+#     name = "rv32mi_illegal",
+#     srcs = [
+#         "@riscv-tests//:isa/rv64mi/illegal.S",
+#     ],
+#     copts = [
+#         "-Itests/riscv-tests",
+#         "-Iexternal/riscv-tests/isa/macros/scalar",
+#         "-Wno-variadic-macros",
+#     ],
+#     defines = [
+#         "RVTEST_RV64M=RVTEST_RV32M",
+#     ],
+#     hw_test_size = "small",
+#     deps = [
+#         ":riscv_tests_base",
+#     ],
+# )
+
 kelvin_test(
     name = "rv32mi_csr",
     srcs = [