sim-card
/
qemu
Archived
10
0
Fork 0

microblaze: Catch illegal insns and privilege violations.

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 <edgar.iglesias@gmail.com>
This commit is contained in:
Edgar E. Iglesias 2009-09-03 11:12:30 +02:00
parent cedb936bfc
commit 1567a00568
2 changed files with 111 additions and 1 deletions

View File

@ -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)}

View File

@ -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;