qemu-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-commits] [COMMIT 1567a00] microblaze: Catch illegal insns and priv


From: Anthony Liguori
Subject: [Qemu-commits] [COMMIT 1567a00] microblaze: Catch illegal insns and privilegeviolations.
Date: Thu, 03 Sep 2009 09:20:56 -0000

From: Edgar E. Iglesias <address@hidden>

Raise illegal instruction exceptions when executing instructions that
require units not available on the particulare microblaze configuration.

Also trap priviliege violations made by userspace.

Signed-off-by: Edgar E. Iglesias <address@hidden>

diff --git a/target-microblaze/microblaze-decode.h 
b/target-microblaze/microblaze-decode.h
index 2c975d6..602027d 100644
--- a/target-microblaze/microblaze-decode.h
+++ b/target-microblaze/microblaze-decode.h
@@ -41,6 +41,7 @@
 #define DEC_BARREL  {B8(00010001), B8(00110111)}
 #define DEC_MUL     {B8(00010000), B8(00110111)}
 #define DEC_DIV     {B8(00010010), B8(00110111)}
+#define DEC_FPU     {B8(00111111), B8(00010110)}
 
 #define DEC_LD      {B8(00110000), B8(00110100)}
 #define DEC_ST      {B8(00110100), B8(00110100)}
diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index 9c8631d..16b282f 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -231,6 +231,13 @@ static void dec_pattern(DisasContext *dc)
     unsigned int mode;
     int l1;
 
+    if ((dc->tb_flags & MSR_EE_FLAG)
+          && !(dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
+          && !((dc->env->pvr.regs[2] & PVR2_USE_PCMP_INSTR))) {
+        tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
+        t_gen_raise_exception(dc, EXCP_HW_EXCP);
+    }
+
     mode = dc->opcode & 3;
     switch (mode) {
         case 0:
@@ -358,6 +365,7 @@ static void dec_msr(DisasContext *dc)
 {
     TCGv t0, t1;
     unsigned int sr, to, rn;
+    int mem_index = cpu_mmu_index(dc->env);
 
     sr = dc->imm & ((1 << 14) - 1);
     to = dc->imm & (1 << 14);
@@ -371,6 +379,19 @@ static void dec_msr(DisasContext *dc)
 
         LOG_DIS("msr%s r%d imm=%x\n", clr ? "clr" : "set",
                 dc->rd, dc->imm);
+
+        if (!(dc->env->pvr.regs[2] & PVR2_USE_MSR_INSTR)) {
+            /* nop??? */
+            return;
+        }
+
+        if ((dc->tb_flags & MSR_EE_FLAG)
+            && mem_index == MMU_USER_IDX && (dc->imm != 4 && dc->imm != 0)) {
+            tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN);
+            t_gen_raise_exception(dc, EXCP_HW_EXCP);
+            return;
+        }
+
         if (dc->rd)
             msr_read(dc, cpu_R[dc->rd]);
 
@@ -392,6 +413,15 @@ static void dec_msr(DisasContext *dc)
         return;
     }
 
+    if (to) {
+        if ((dc->tb_flags & MSR_EE_FLAG)
+             && mem_index == MMU_USER_IDX) {
+            tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN);
+            t_gen_raise_exception(dc, EXCP_HW_EXCP);
+            return;
+        }
+    }
+
 #if !defined(CONFIG_USER_ONLY)
     /* Catch read/writes to the mmu block.  */
     if ((sr & ~0xff) == 0x1000) {
@@ -518,6 +548,14 @@ static void dec_mul(DisasContext *dc)
     TCGv d[2];
     unsigned int subcode;
 
+    if ((dc->tb_flags & MSR_EE_FLAG)
+         && !(dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
+         && !(dc->env->pvr.regs[0] & PVR0_USE_HW_MUL_MASK)) {
+        tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
+        t_gen_raise_exception(dc, EXCP_HW_EXCP);
+        return;
+    }
+
     subcode = dc->imm & 3;
     d[0] = tcg_temp_new();
     d[1] = tcg_temp_new();
@@ -528,6 +566,12 @@ static void dec_mul(DisasContext *dc)
         goto done;
     }
 
+    /* mulh, mulhsu and mulhu are not available if C_USE_HW_MUL is < 2.  */
+    if (subcode >= 1 && subcode <= 3
+        && !((dc->env->pvr.regs[2] & PVR2_USE_MUL64_MASK))) {
+        /* nop??? */
+    }
+
     switch (subcode) {
         case 0:
             LOG_DIS("mul r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
@@ -562,6 +606,12 @@ static void dec_div(DisasContext *dc)
     u = dc->imm & 2; 
     LOG_DIS("div\n");
 
+    if (!(dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
+          && !((dc->env->pvr.regs[0] & PVR0_USE_DIV_MASK))) {
+        tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
+        t_gen_raise_exception(dc, EXCP_HW_EXCP);
+    }
+
     /* FIXME: support div by zero exceptions.  */
     if (u)
         gen_helper_divu(cpu_R[dc->rd], *(dec_alu_op_b(dc)), cpu_R[dc->ra]);
@@ -576,6 +626,14 @@ static void dec_barrel(DisasContext *dc)
     TCGv t0;
     unsigned int s, t;
 
+    if ((dc->tb_flags & MSR_EE_FLAG)
+          && !(dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
+          && !(dc->env->pvr.regs[0] & PVR0_USE_BARREL_MASK)) {
+        tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
+        t_gen_raise_exception(dc, EXCP_HW_EXCP);
+        return;
+    }
+
     s = dc->imm & (1 << 10);
     t = dc->imm & (1 << 9);
 
@@ -601,6 +659,7 @@ static void dec_bit(DisasContext *dc)
 {
     TCGv t0, t1;
     unsigned int op;
+    int mem_index = cpu_mmu_index(dc->env);
 
     op = dc->ir & ((1 << 8) - 1);
     switch (op) {
@@ -653,10 +712,22 @@ static void dec_bit(DisasContext *dc)
         case 0x64:
             /* wdc.  */
             LOG_DIS("wdc r%d\n", dc->ra);
+            if ((dc->tb_flags & MSR_EE_FLAG)
+                 && mem_index == MMU_USER_IDX) {
+                tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN);
+                t_gen_raise_exception(dc, EXCP_HW_EXCP);
+                return;
+            }
             break;
         case 0x68:
             /* wic.  */
             LOG_DIS("wic r%d\n", dc->ra);
+            if ((dc->tb_flags & MSR_EE_FLAG)
+                 && mem_index == MMU_USER_IDX) {
+                tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN);
+                t_gen_raise_exception(dc, EXCP_HW_EXCP);
+                return;
+            }
             break;
         default:
             cpu_abort(dc->env, "unknown bit oc=%x op=%x rd=%d ra=%d rb=%d\n",
@@ -966,6 +1037,7 @@ static inline void do_rte(DisasContext *dc)
 static void dec_rts(DisasContext *dc)
 {
     unsigned int b_bit, i_bit, e_bit;
+    int mem_index = cpu_mmu_index(dc->env);
 
     i_bit = dc->ir & (1 << 21);
     b_bit = dc->ir & (1 << 22);
@@ -978,12 +1050,27 @@ static void dec_rts(DisasContext *dc)
 
     if (i_bit) {
         LOG_DIS("rtid ir=%x\n", dc->ir);
+        if ((dc->tb_flags & MSR_EE_FLAG)
+             && mem_index == MMU_USER_IDX) {
+            tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN);
+            t_gen_raise_exception(dc, EXCP_HW_EXCP);
+        }
         dc->tb_flags |= DRTI_FLAG;
     } else if (b_bit) {
         LOG_DIS("rtbd ir=%x\n", dc->ir);
+        if ((dc->tb_flags & MSR_EE_FLAG)
+             && mem_index == MMU_USER_IDX) {
+            tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN);
+            t_gen_raise_exception(dc, EXCP_HW_EXCP);
+        }
         dc->tb_flags |= DRTB_FLAG;
     } else if (e_bit) {
         LOG_DIS("rted ir=%x\n", dc->ir);
+        if ((dc->tb_flags & MSR_EE_FLAG)
+             && mem_index == MMU_USER_IDX) {
+            tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN);
+            t_gen_raise_exception(dc, EXCP_HW_EXCP);
+        }
         dc->tb_flags |= DRTE_FLAG;
     } else
         LOG_DIS("rts ir=%x\n", dc->ir);
@@ -992,6 +1079,20 @@ static void dec_rts(DisasContext *dc)
     tcg_gen_add_tl(env_btarget, cpu_R[dc->ra], *(dec_alu_op_b(dc)));
 }
 
+static void dec_fpu(DisasContext *dc)
+{
+    if ((dc->tb_flags & MSR_EE_FLAG)
+          && !(dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
+          && !((dc->env->pvr.regs[2] & PVR2_USE_FPU_MASK))) {
+        tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
+        t_gen_raise_exception(dc, EXCP_HW_EXCP);
+        return;
+    }
+
+    qemu_log ("unimplemented FPU insn pc=%x opc=%x\n", dc->pc, dc->opcode);
+    dc->abort_at_next_insn = 1;
+}
+
 static void dec_null(DisasContext *dc)
 {
     qemu_log ("unknown insn pc=%x opc=%x\n", dc->pc, dc->opcode);
@@ -1018,6 +1119,7 @@ static struct decoder_info {
     {DEC_BR, dec_br},
     {DEC_BCC, dec_bcc},
     {DEC_RTS, dec_rts},
+    {DEC_FPU, dec_fpu},
     {DEC_MUL, dec_mul},
     {DEC_DIV, dec_div},
     {DEC_MSR, dec_msr},
@@ -1038,6 +1140,14 @@ static inline void decode(DisasContext *dc)
     if (dc->ir)
         dc->nr_nops = 0;
     else {
+        if ((dc->tb_flags & MSR_EE_FLAG)
+              && !(dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
+              && !(dc->env->pvr.regs[2] & PVR2_OPCODE_0x0_ILL_MASK)) {
+            tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
+            t_gen_raise_exception(dc, EXCP_HW_EXCP);
+            return;
+        }
+
         LOG_DIS("nr_nops=%d\t", dc->nr_nops);
         dc->nr_nops++;
         if (dc->nr_nops > 4)
@@ -1061,7 +1171,6 @@ static inline void decode(DisasContext *dc)
     }
 }
 
-
 static void check_breakpoint(CPUState *env, DisasContext *dc)
 {
     CPUBreakpoint *bp;




reply via email to

[Prev in Thread] Current Thread [Next in Thread]