[Qemu-devel] [PATCH] x86: enforce DPL checking on task gate switches invoked through IDT

2012-08-17 Thread Alex ZUEPKE
Hi,

x86 software emulation (non-KVM mode) does not check privilege levels on
task gate switches ... so one can invoke a kernel's double fault handler
from user space -- very bad.

Expected behaviour (testcase works with any linux distribution + gcc):
  $ cat test.c
int main(void)
{
  __asm__ volatile ("int $8");
}
  $ gcc test.c
  $ ./a.out
  Segmentation fault
  $
... and not a kernel panic (double fault)

Forgive me for sending this patch as attachment, I'm not used to git.

Best Regards,
Alex
 x86 software emulation (non-KVM mode) does not check privilege
 levels on task gate switches ... so one can invoke a kernel's
 double fault handler from user space.
 
 Signed-off-by: Alex Zuepke 
diff --git a/target-i386/seg_helper.c b/target-i386/seg_helper.c
index 5fff8d5..23c5542 100644
--- a/target-i386/seg_helper.c
+++ b/target-i386/seg_helper.c
@@ -578,12 +578,17 @@ static void do_interrupt_protected(CPUX86State *env, int intno, int is_int,
 e2 = cpu_ldl_kernel(env, ptr + 4);
 /* check gate type */
 type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;
+dpl = (e2 >> DESC_DPL_SHIFT) & 3;
+cpl = env->hflags & HF_CPL_MASK;
 switch (type) {
 case 5: /* task gate */
 /* must do that check here to return the correct error code */
 if (!(e2 & DESC_P_MASK)) {
 raise_exception_err(env, EXCP0B_NOSEG, intno * 8 + 2);
 }
+/* check privilege if software int */
+if (is_int && dpl < cpl)
+raise_exception_err(env, EXCP0D_GPF, intno * 8 + 2);
 switch_tss(env, intno * 8, e1, e2, SWITCH_TSS_CALL, old_eip);
 if (has_error_code) {
 int type;
@@ -616,8 +621,6 @@ static void do_interrupt_protected(CPUX86State *env, int intno, int is_int,
 raise_exception_err(env, EXCP0D_GPF, intno * 8 + 2);
 break;
 }
-dpl = (e2 >> DESC_DPL_SHIFT) & 3;
-cpl = env->hflags & HF_CPL_MASK;
 /* check privilege if software int */
 if (is_int && dpl < cpl) {
 raise_exception_err(env, EXCP0D_GPF, intno * 8 + 2);


[Qemu-devel] [PATCH] x86: enforce DPL checking on task gate switches invoked through IDT

2012-08-17 Thread Alex ZUEPKE
Hi,

x86 software emulation (non-KVM mode) does not check privilege levels on
task gate switches ... so one can invoke a kernel's double fault handler
from user space -- very bad.

Expected behaviour (testcase works with any linux distribution + gcc):
  $ cat test.c
int main(void)
{
  __asm__ volatile ("int $8");
}
  $ gcc test.c
  $ ./a.out
  Segmentation fault
  $
... and not a kernel panic (double fault)


Best Regards,
Alex

---
 x86 software emulation (non-KVM mode) does not check privilege
 levels on task gate switches ... so one can invoke a kernel's
 double fault handler from user space.
 
 Signed-off-by: Alex Zuepke 
diff --git a/target-i386/seg_helper.c b/target-i386/seg_helper.c
index 5fff8d5..23c5542 100644
--- a/target-i386/seg_helper.c
+++ b/target-i386/seg_helper.c
@@ -578,12 +578,17 @@ static void do_interrupt_protected(CPUX86State *env, int 
intno, int is_int,
 e2 = cpu_ldl_kernel(env, ptr + 4);
 /* check gate type */
 type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;
+dpl = (e2 >> DESC_DPL_SHIFT) & 3;
+cpl = env->hflags & HF_CPL_MASK;
 switch (type) {
 case 5: /* task gate */
 /* must do that check here to return the correct error code */
 if (!(e2 & DESC_P_MASK)) {
 raise_exception_err(env, EXCP0B_NOSEG, intno * 8 + 2);
 }
+/* check privilege if software int */
+if (is_int && dpl < cpl)
+raise_exception_err(env, EXCP0D_GPF, intno * 8 + 2);
 switch_tss(env, intno * 8, e1, e2, SWITCH_TSS_CALL, old_eip);
 if (has_error_code) {
 int type;
@@ -616,8 +621,6 @@ static void do_interrupt_protected(CPUX86State *env, int 
intno, int is_int,
 raise_exception_err(env, EXCP0D_GPF, intno * 8 + 2);
 break;
 }
-dpl = (e2 >> DESC_DPL_SHIFT) & 3;
-cpl = env->hflags & HF_CPL_MASK;
 /* check privilege if software int */
 if (is_int && dpl < cpl) {
 raise_exception_err(env, EXCP0D_GPF, intno * 8 + 2);




Re: [Qemu-devel] [PATCH] x86: enforce DPL checking on task gate switches invoked through IDT

2012-08-27 Thread Alex ZUEPKE
Ping, no response so far ...


Thanks,
Alex

Alex ZUEPKE wrote:
> Hi,
> 
> x86 software emulation (non-KVM mode) does not check privilege levels on
> task gate switches ... so one can invoke a kernel's double fault handler
> from user space -- very bad.
> 
> Expected behaviour (testcase works with any linux distribution + gcc):
>   $ cat test.c
> int main(void)
> {
>   __asm__ volatile ("int $8");
> }
>   $ gcc test.c
>   $ ./a.out
>   Segmentation fault
>   $
> ... and not a kernel panic (double fault)
> 
> 
> Best Regards,
> Alex
> 
> ---
>  x86 software emulation (non-KVM mode) does not check privilege
>  levels on task gate switches ... so one can invoke a kernel's
>  double fault handler from user space.
>  
>  Signed-off-by: Alex Zuepke 
> diff --git a/target-i386/seg_helper.c b/target-i386/seg_helper.c
> index 5fff8d5..23c5542 100644
> --- a/target-i386/seg_helper.c
> +++ b/target-i386/seg_helper.c
> @@ -578,12 +578,17 @@ static void do_interrupt_protected(CPUX86State *env, 
> int intno, int is_int,
>  e2 = cpu_ldl_kernel(env, ptr + 4);
>  /* check gate type */
>  type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;
> +dpl = (e2 >> DESC_DPL_SHIFT) & 3;
> +cpl = env->hflags & HF_CPL_MASK;
>  switch (type) {
>  case 5: /* task gate */
>  /* must do that check here to return the correct error code */
>  if (!(e2 & DESC_P_MASK)) {
>  raise_exception_err(env, EXCP0B_NOSEG, intno * 8 + 2);
>  }
> +/* check privilege if software int */
> +if (is_int && dpl < cpl)
> +raise_exception_err(env, EXCP0D_GPF, intno * 8 + 2);
>  switch_tss(env, intno * 8, e1, e2, SWITCH_TSS_CALL, old_eip);
>  if (has_error_code) {
>  int type;
> @@ -616,8 +621,6 @@ static void do_interrupt_protected(CPUX86State *env, int 
> intno, int is_int,
>  raise_exception_err(env, EXCP0D_GPF, intno * 8 + 2);
>  break;
>  }
> -dpl = (e2 >> DESC_DPL_SHIFT) & 3;
> -cpl = env->hflags & HF_CPL_MASK;
>  /* check privilege if software int */
>  if (is_int && dpl < cpl) {
>  raise_exception_err(env, EXCP0D_GPF, intno * 8 + 2);
> 
> 



[Qemu-devel] [PATCH 1/1] x86: enforce DPL checking on task gate switches

2014-05-14 Thread Alex Zuepke
x86 software emulation (non-KVM mode) does not check privilege levels on task 
gate switches.
An "int $8" in user mode panics any OS kernel by a forbidden direct call into 
the double fault handler.

This testcase crashes a Linux kernel with a double fault panic:

$ cat test.c
  int main(void)
  {
__asm__ volatile ("int $8");
  }
$ gcc test.c
$ ./a.out
panic ...

Signed-off-by: Alex Zuepke 
---
 target-i386/seg_helper.c |8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/target-i386/seg_helper.c b/target-i386/seg_helper.c
index 8c3f92c..d7f3d49 100644
--- a/target-i386/seg_helper.c
+++ b/target-i386/seg_helper.c
@@ -582,12 +582,18 @@ static void do_interrupt_protected(CPUX86State *env, int 
intno, int is_int,
 e2 = cpu_ldl_kernel(env, ptr + 4);
 /* check gate type */
 type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;
+dpl = (e2 >> DESC_DPL_SHIFT) & 3;
+cpl = env->hflags & HF_CPL_MASK;
 switch (type) {
 case 5: /* task gate */
 /* must do that check here to return the correct error code */
 if (!(e2 & DESC_P_MASK)) {
 raise_exception_err(env, EXCP0B_NOSEG, intno * 8 + 2);
 }
+/* check privilege if software int */
+if (is_int && (dpl < cpl)) {
+raise_exception_err(env, EXCP0D_GPF, intno * 8 + 2);
+}
 switch_tss(env, intno * 8, e1, e2, SWITCH_TSS_CALL, old_eip);
 if (has_error_code) {
 int type;
@@ -620,8 +626,6 @@ static void do_interrupt_protected(CPUX86State *env, int 
intno, int is_int,
 raise_exception_err(env, EXCP0D_GPF, intno * 8 + 2);
 break;
 }
-dpl = (e2 >> DESC_DPL_SHIFT) & 3;
-cpl = env->hflags & HF_CPL_MASK;
 /* check privilege if software int */
 if (is_int && dpl < cpl) {
 raise_exception_err(env, EXCP0D_GPF, intno * 8 + 2);
-- 
1.7.9.5




Re: [Qemu-devel] ARM: BKPT instructions should raise prefetch aborts with IFSR type 00010

2011-05-18 Thread Alex Zuepke
Hi,

Peter Maydell schrieb:
> On 25 March 2011 10:54, Alex Zuepke  wrote:
>> while digging through some problems with BKPT exceptions on ARM, I
>> discovered that QEMU does not update IFSR on prefetch aborts. This
>> should be done since ARMv6 according to ARM docs. Please include.
> 
> This patch is the wrong approach to fixing this bug -- the
> updating of the IFSR needs to be done when the exception
> is taken, not when we translate the breakpoint instruction.
> 
> I'll put this on my todo list. If you happen to have a convenient
> test case demonstrating the problem, that would make a fix happen
> faster ;-)
> 
> -- PMM

I tried to fix it, new patch attached.
But I'm not sure if it is required for semihosting as well.

On ARMv7-M bkpt works differently, and debug registers aren't
implemented yet, so I didn't touch it.

Best Regards,
Alex

-- 
Alexander Zuepkeazue...@sysgo.com
SYSGO AG ~ Am Pfaffenstein 14 ~ 55270 Klein-Winternheim ~ Germany
 target-arm: BKPT instructions should raise prefetch aborts with IFSR type 00010
 diff against qemu 0.14.1
 Signed-off-by: Alex Zuepke 
diff --git a/target-arm/helper.c b/target-arm/helper.c
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -847,6 +849,7 @@ void do_interrupt(CPUARMState *env)
 return;
 }
 }
+env->cp15.c5_insn = 2;
 /* Fall through to prefetch abort.  */
 case EXCP_PREFETCH_ABORT:
 new_mode = ARM_CPU_MODE_ABT;


[Qemu-devel] [PATCH 2/4] target-tricore: typo in BOL format

2014-12-12 Thread Alex Zuepke
Signed-off-by: Alex Zuepke 
---
 target-tricore/translate.c   |4 ++--
 target-tricore/tricore-opcodes.h |2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/target-tricore/translate.c b/target-tricore/translate.c
index 65abf45..c132223 100644
--- a/target-tricore/translate.c
+++ b/target-tricore/translate.c
@@ -3203,7 +3203,7 @@ static void decode_bol_opc(CPUTriCoreState *env, 
DisasContext *ctx, int32_t op1)
 tcg_gen_qemu_ld_tl(cpu_gpr_a[r1], temp, ctx->mem_idx, MO_LEUL);
 tcg_temp_free(temp);
 break;
-case OPC1_32_BOL_LD_W_LONFOFF:
+case OPC1_32_BOL_LD_W_LONGOFF:
 temp = tcg_temp_new();
 tcg_gen_addi_tl(temp, cpu_gpr_a[r2], address);
 tcg_gen_qemu_ld_tl(cpu_gpr_d[r1], temp, ctx->mem_idx, MO_LEUL);
@@ -3930,7 +3930,7 @@ static void decode_32Bit_opc(CPUTriCoreState *env, 
DisasContext *ctx)
 break;
 /* BOL-format */
 case OPC1_32_BOL_LD_A_LONGOFF:
-case OPC1_32_BOL_LD_W_LONFOFF:
+case OPC1_32_BOL_LD_W_LONGOFF:
 case OPC1_32_BOL_LEA_LONGOFF:
 case OPC1_32_BOL_ST_W_LONGOFF:
 case OPC1_32_BOL_ST_A_LONGOFF:
diff --git a/target-tricore/tricore-opcodes.h b/target-tricore/tricore-opcodes.h
index 70ac5ff..7aa6aed 100644
--- a/target-tricore/tricore-opcodes.h
+++ b/target-tricore/tricore-opcodes.h
@@ -447,7 +447,7 @@ enum {
 OPCM_32_BO_ADDRMODE_LDMST_BITREVERSE_CIRCULAR= 0x69,
 /* BOL Format */
 OPC1_32_BOL_LD_A_LONGOFF = 0x99,
-OPC1_32_BOL_LD_W_LONFOFF = 0x19,
+OPC1_32_BOL_LD_W_LONGOFF = 0x19,
 OPC1_32_BOL_LEA_LONGOFF  = 0xd9,
 OPC1_32_BOL_ST_W_LONGOFF = 0x59,
 OPC1_32_BOL_ST_A_LONGOFF = 0xb5, /* 1.6 only */
-- 
1.7.9.5




[Qemu-devel] [PATCH 3/4] target-tricore: add missing 64-bit MOV in RLC format

2014-12-12 Thread Alex Zuepke
Signed-off-by: Alex Zuepke 
---
 target-tricore/translate.c   |   12 
 target-tricore/tricore-opcodes.h |1 +
 2 files changed, 13 insertions(+)

diff --git a/target-tricore/translate.c b/target-tricore/translate.c
index c132223..e3eeedb 100644
--- a/target-tricore/translate.c
+++ b/target-tricore/translate.c
@@ -3781,6 +3781,17 @@ static void decode_rlc_opc(CPUTriCoreState *env, 
DisasContext *ctx,
 case OPC1_32_RLC_MOV:
 tcg_gen_movi_tl(cpu_gpr_d[r2], const16);
 break;
+case OPC1_32_RLC_MOV_64:
+if (tricore_feature(env, TRICORE_FEATURE_16)) {
+if ((r2 & 0x1) != 0) {
+/* TODO: raise OPD trap */
+}
+tcg_gen_movi_tl(cpu_gpr_d[r2], const16);
+tcg_gen_movi_tl(cpu_gpr_d[r2+1], const16 >> 15);
+} else {
+/* TODO: raise illegal opcode trap */
+}
+break;
 case OPC1_32_RLC_MOV_U:
 const16 = MASK_OP_RLC_CONST16(ctx->opcode);
 tcg_gen_movi_tl(cpu_gpr_d[r2], const16);
@@ -4021,6 +4032,7 @@ static void decode_32Bit_opc(CPUTriCoreState *env, 
DisasContext *ctx)
 case OPC1_32_RLC_ADDIH_A:
 case OPC1_32_RLC_MFCR:
 case OPC1_32_RLC_MOV:
+case OPC1_32_RLC_MOV_64:
 case OPC1_32_RLC_MOV_U:
 case OPC1_32_RLC_MOV_H:
 case OPC1_32_RLC_MOVH_A:
diff --git a/target-tricore/tricore-opcodes.h b/target-tricore/tricore-opcodes.h
index 7aa6aed..a76a7e4 100644
--- a/target-tricore/tricore-opcodes.h
+++ b/target-tricore/tricore-opcodes.h
@@ -487,6 +487,7 @@ enum {
 OPC1_32_RLC_ADDIH_A  = 0x11,
 OPC1_32_RLC_MFCR = 0x4d,
 OPC1_32_RLC_MOV  = 0x3b,
+OPC1_32_RLC_MOV_64   = 0xfb, /* 1.6 only */
 OPC1_32_RLC_MOV_U= 0xbb,
 OPC1_32_RLC_MOV_H= 0x7b,
 OPC1_32_RLC_MOVH_A   = 0x91,
-- 
1.7.9.5




[Qemu-devel] [PATCH 1/4] target-tricore: fix offset masking in BOL format

2014-12-12 Thread Alex Zuepke
Signed-off-by: Alex Zuepke 
---
 target-tricore/tricore-opcodes.h |2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target-tricore/tricore-opcodes.h b/target-tricore/tricore-opcodes.h
index 0a9122c..70ac5ff 100644
--- a/target-tricore/tricore-opcodes.h
+++ b/target-tricore/tricore-opcodes.h
@@ -114,7 +114,7 @@
 /* BOL Format */
 #define MASK_OP_BOL_OFF16(op)  ((MASK_BITS_SHIFT(op, 16, 21) +\
(MASK_BITS_SHIFT(op, 28, 31) << 6)) + \
-   (MASK_BITS_SHIFT(op, 22, 27) >> 10))
+   (MASK_BITS_SHIFT(op, 22, 27) << 10))
 #define MASK_OP_BOL_OFF16_SEXT(op)  ((MASK_BITS_SHIFT(op, 16, 21) +\
 (MASK_BITS_SHIFT(op, 28, 31) << 6)) + \
 (MASK_BITS_SHIFT_SEXT(op, 22, 27) << 10))
-- 
1.7.9.5




[Qemu-devel] [PATCH v2 0/4] target-tricore: fixes to opcode encoding and register dump

2014-12-12 Thread Alex Zuepke
Hi Bastian,

my previous patches again, I hope they are well-formed now:
1. fix the offset masking in BOL format
2. fix a typo in BOL format
3. add the missing 64-bit "MOV Ex, simm16" variant in RLC format
4. pretty-print register dump

Best regards
Alex


Alex Zuepke (4):
  target-tricore: fix offset masking in BOL format
  target-tricore: typo in BOL format
  target-tricore: add missing 64-bit MOV in RLC format
  target-tricore: pretty-print register dump and show more status
registers

 target-tricore/translate.c   |   32 +---
 target-tricore/tricore-opcodes.h |5 +++--
 2 files changed, 28 insertions(+), 9 deletions(-)

-- 
1.7.9.5




[Qemu-devel] [PATCH 4/4] target-tricore: pretty-print register dump and show more status registers

2014-12-12 Thread Alex Zuepke
Signed-off-by: Alex Zuepke 
---
 target-tricore/translate.c |   16 +++-
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/target-tricore/translate.c b/target-tricore/translate.c
index e3eeedb..d1b845b 100644
--- a/target-tricore/translate.c
+++ b/target-tricore/translate.c
@@ -87,19 +87,25 @@ void tricore_cpu_dump_state(CPUState *cs, FILE *f,
 CPUTriCoreState *env = &cpu->env;
 int i;
 
-cpu_fprintf(f, "PC=%08x\n", env->PC);
+cpu_fprintf(f, "PC: " TARGET_FMT_lx, env->PC);
+cpu_fprintf(f, " PCXI: " TARGET_FMT_lx, env->PCXI);
+cpu_fprintf(f, " FCX: " TARGET_FMT_lx, env->FCX);
+cpu_fprintf(f, " LCX: " TARGET_FMT_lx, env->LCX);
+cpu_fprintf(f, " PSW: " TARGET_FMT_lx, env->PSW);
+
 for (i = 0; i < 16; ++i) {
 if ((i & 3) == 0) {
-cpu_fprintf(f, "GPR A%02d:", i);
+cpu_fprintf(f, "\nGPR A%02d:", i);
 }
-cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames_a[i], env->gpr_a[i]);
+cpu_fprintf(f, " " TARGET_FMT_lx, env->gpr_a[i]);
 }
 for (i = 0; i < 16; ++i) {
 if ((i & 3) == 0) {
-cpu_fprintf(f, "GPR D%02d:", i);
+cpu_fprintf(f, "\nGPR D%02d:", i);
 }
-cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames_d[i], env->gpr_d[i]);
+cpu_fprintf(f, " " TARGET_FMT_lx, env->gpr_d[i]);
 }
+cpu_fprintf(f, "\n");
 
 }
 
-- 
1.7.9.5




[Qemu-devel] [PATCH v3] target-tricore: pretty-print register dump and show more status registers

2014-12-19 Thread Alex Zuepke
Now using psw_read() to retrieve the status bits correctly.

Signed-off-by: Alex Zuepke 
---
 target-tricore/translate.c |   21 +++--
 1 file changed, 15 insertions(+), 6 deletions(-)

diff --git a/target-tricore/translate.c b/target-tricore/translate.c
index e3eeedb..3d87346 100644
--- a/target-tricore/translate.c
+++ b/target-tricore/translate.c
@@ -85,22 +85,31 @@ void tricore_cpu_dump_state(CPUState *cs, FILE *f,
 {
 TriCoreCPU *cpu = TRICORE_CPU(cs);
 CPUTriCoreState *env = &cpu->env;
+uint32_t psw;
 int i;
 
-cpu_fprintf(f, "PC=%08x\n", env->PC);
+psw = psw_read(env);
+
+cpu_fprintf(f, "PC: " TARGET_FMT_lx, env->PC);
+cpu_fprintf(f, " PSW: " TARGET_FMT_lx, psw);
+cpu_fprintf(f, " ICR: " TARGET_FMT_lx, env->ICR);
+cpu_fprintf(f, "\nPCXI: " TARGET_FMT_lx, env->PCXI);
+cpu_fprintf(f, " FCX: " TARGET_FMT_lx, env->FCX);
+cpu_fprintf(f, " LCX: " TARGET_FMT_lx, env->LCX);
+
 for (i = 0; i < 16; ++i) {
 if ((i & 3) == 0) {
-cpu_fprintf(f, "GPR A%02d:", i);
+cpu_fprintf(f, "\nGPR A%02d:", i);
 }
-cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames_a[i], env->gpr_a[i]);
+cpu_fprintf(f, " " TARGET_FMT_lx, env->gpr_a[i]);
 }
 for (i = 0; i < 16; ++i) {
 if ((i & 3) == 0) {
-cpu_fprintf(f, "GPR D%02d:", i);
+cpu_fprintf(f, "\nGPR D%02d:", i);
 }
-cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames_d[i], env->gpr_d[i]);
+cpu_fprintf(f, " " TARGET_FMT_lx, env->gpr_d[i]);
 }
-
+cpu_fprintf(f, "\n");
 }
 
 /*
-- 
1.7.9.5




[Qemu-devel] (no subject)

2014-05-28 Thread Alex Zuepke

Put qemu-devel on CC



[Qemu-devel] [PATCH 1/1] ppc-e500: on write to MMUCSR0, pass GPR content, not SPR number, to low-level TLB-flush routine

2014-05-28 Thread Alex Zuepke
A  "mtspr SPRMMUCSR0, reg"  always flushed TLB0,
because it passed the SPR number 0x3f4 to the flush routine.
But we want to flush either TLB0 or TBL1 depending on the GPR value.

Signed-off-by: Alex Zuepke 
---
 target-ppc/translate_init.c |4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 4d94015..e4680cb 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -1455,9 +1455,7 @@ static void spr_write_e500_l1csr0 (void *opaque, int 
sprn, int gprn)
 
 static void spr_write_booke206_mmucsr0 (void *opaque, int sprn, int gprn)
 {
-TCGv_i32 t0 = tcg_const_i32(sprn);
-gen_helper_booke206_tlbflush(cpu_env, t0);
-tcg_temp_free_i32(t0);
+gen_helper_booke206_tlbflush(cpu_env, cpu_gpr[gprn]);
 }
 
 static void spr_write_booke_pid (void *opaque, int sprn, int gprn)
-- 
1.7.9.5




[Qemu-devel] [PATCH] sparc: allow CASA with ASI 0xa from user space

2015-12-04 Thread Alex Zuepke
LEON3 allows the CASA instruction to be used from user space
if the ASI is set to 0xa (user data).

Signed-off-by: Alex Zuepke 
---
 target-sparc/translate.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 41a3319..63440dd 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -5097,7 +5097,8 @@ static void disas_sparc_insn(DisasContext * dc, unsigned 
int insn)
 if (IS_IMM) {
 goto illegal_insn;
 }
-if (!supervisor(dc)) {
+/* LEON3 allows CASA from user space with ASI 0xa */
+if ((GET_FIELD(insn, 19, 26) != 0xa) && !supervisor(dc)) {
 goto priv_insn;
 }
 #endif
-- 
1.9.1




[Qemu-devel] [PATCH 0/6] ARM: MPU support for Cortex-M3/M4 emulation

2015-07-07 Thread Alex Zuepke
This patch series enables MPU support for Cortex-M3/M4 devices,
based on the existing MPU support for Cortex-R series in QEMU.
The MPU supports a variable number of windows and default to 8, the current
limit on most Cortex-M3/M4 devices. Also, the necessary registers for
exception handling and fault decoding are implemented.
Like on Cortex-R5, the MPU can be turned off by setting "pmsav7-dregion" to
zero.

Alex Zuepke (6):
  ARM: add Cortex-M3/M4 exception configuration and status registers
  ARM: accessors to Cortex-M3/M4 exception configuration and status
registers
  ARM: Cortex-M3/M4: honor STKALIGN in CCR
  ARM: Cortex-M3/M4: on exception, set basic bits in exhandling
registers
  ARM: enable ARM_FEATURE_MPU for Cortex-M3/M4
  ARM: enable PMSAv7-style MPU on Cortex-M3/M4

 hw/arm/armv7m.c   |   17 -
 hw/intc/armv7m_nvic.c |  183 ++---
 target-arm/cpu.c  |2 +
 target-arm/cpu.h  |   57 +++
 target-arm/helper.c   |   47 ++---
 target-arm/machine.c  |7 ++
 6 files changed, 295 insertions(+), 18 deletions(-)

-- 
1.7.9.5




[Qemu-devel] [PATCH 5/6] ARM: enable ARM_FEATURE_MPU for Cortex-M3/M4

2015-07-07 Thread Alex Zuepke

Signed-off-by: Alex Zuepke 
---
 hw/arm/armv7m.c |   17 -
 target-arm/cpu.c|2 ++
 target-arm/helper.c |   30 --
 3 files changed, 46 insertions(+), 3 deletions(-)

diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
index c6eab6d..db6bc3c 100644
--- a/hw/arm/armv7m.c
+++ b/hw/arm/armv7m.c
@@ -179,15 +179,30 @@ qemu_irq *armv7m_init(MemoryRegion *system_memory, int 
mem_size, int num_irq,
 int i;
 int big_endian;
 MemoryRegion *hack = g_new(MemoryRegion, 1);
+ObjectClass *cpu_oc;
+Error *err = NULL;
 
 if (cpu_model == NULL) {
cpu_model = "cortex-m3";
 }
-cpu = cpu_arm_init(cpu_model);
+cpu_oc = cpu_class_by_name(TYPE_ARM_CPU, cpu_model);
+cpu = ARM_CPU(object_new(object_class_get_name(cpu_oc)));
 if (cpu == NULL) {
 fprintf(stderr, "Unable to find CPU definition\n");
 exit(1);
 }
+/* On Cortex-M3/M4, the MPU has 8 windows */
+object_property_set_int(OBJECT(cpu), 8, "pmsav7-dregion", &err);
+if (err) {
+error_report_err(err);
+exit(1);
+}
+object_property_set_bool(OBJECT(cpu), true, "realized", &err);
+if (err) {
+error_report_err(err);
+exit(1);
+}
+
 env = &cpu->env;
 
 armv7m_bitband_init();
diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index 80669a6..d8cfbb1 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -832,6 +832,7 @@ static void cortex_m3_initfn(Object *obj)
 ARMCPU *cpu = ARM_CPU(obj);
 set_feature(&cpu->env, ARM_FEATURE_V7);
 set_feature(&cpu->env, ARM_FEATURE_M);
+set_feature(&cpu->env, ARM_FEATURE_MPU);
 cpu->midr = 0x410fc231;
 }
 
@@ -841,6 +842,7 @@ static void cortex_m4_initfn(Object *obj)
 
 set_feature(&cpu->env, ARM_FEATURE_V7);
 set_feature(&cpu->env, ARM_FEATURE_M);
+set_feature(&cpu->env, ARM_FEATURE_MPU);
 set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
 cpu->midr = 0x410fc240; /* r0p0 */
 }
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 555bc5f..637dbf6 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -5854,6 +5854,26 @@ static inline void 
get_phys_addr_pmsav7_default(CPUARMState *env,
 
 }
 
+static inline void get_phys_addr_v7m_default(CPUARMState *env,
+ ARMMMUIdx mmu_idx,
+ int32_t address, int *prot)
+{
+*prot = PAGE_READ | PAGE_WRITE;
+switch (address) {
+case 0xF000 ... 0x:
+/* the special exception return address memory region is EXEC only */
+*prot = PAGE_EXEC;
+break;
+
+case 0x ... 0x1FFF:
+case 0x2000 ... 0x3FFF:
+case 0x6000 ... 0x7FFF:
+case 0x8000 ... 0x9FFF:
+*prot |= PAGE_EXEC;
+break;
+}
+}
+
 static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address,
  int access_type, ARMMMUIdx mmu_idx,
  hwaddr *phys_ptr, int *prot, uint32_t *fsr)
@@ -5866,7 +5886,10 @@ static bool get_phys_addr_pmsav7(CPUARMState *env, 
uint32_t address,
 *prot = 0;
 
 if (regime_translation_disabled(env, mmu_idx)) { /* MPU disabled */
-get_phys_addr_pmsav7_default(env, mmu_idx, address, prot);
+if (arm_feature(env, ARM_FEATURE_M))
+get_phys_addr_v7m_default(env, mmu_idx, address, prot);
+else
+get_phys_addr_pmsav7_default(env, mmu_idx, address, prot);
 } else { /* MPU enabled */
 for (n = (int)cpu->pmsav7_dregion - 1; n >= 0; n--) {
 /* region search */
@@ -5944,7 +5967,10 @@ static bool get_phys_addr_pmsav7(CPUARMState *env, 
uint32_t address,
 *fsr = 0;
 return true;
 }
-get_phys_addr_pmsav7_default(env, mmu_idx, address, prot);
+if (arm_feature(env, ARM_FEATURE_M))
+get_phys_addr_v7m_default(env, mmu_idx, address, prot);
+else
+get_phys_addr_pmsav7_default(env, mmu_idx, address, prot);
 } else { /* a MPU hit! */
 uint32_t ap = extract32(env->pmsav7.dracr[n], 8, 3);
 
-- 
1.7.9.5




[Qemu-devel] [PATCH 4/6] ARM: Cortex-M3/M4: on exception, set basic bits in exhandling registers

2015-07-07 Thread Alex Zuepke

Signed-off-by: Alex Zuepke 
---
 target-arm/helper.c |7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/target-arm/helper.c b/target-arm/helper.c
index 812204f..555bc5f 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -4541,6 +4541,7 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
one we're raising.  */
 switch (cs->exception_index) {
 case EXCP_UDEF:
+env->v7m.cfsr |= CFSR_UNDEFINSTR;
 armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE);
 return;
 case EXCP_SWI:
@@ -4549,9 +4550,9 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
 return;
 case EXCP_PREFETCH_ABORT:
 case EXCP_DATA_ABORT:
-/* TODO: if we implemented the MPU registers, this is where we
- * should set the MMFAR, etc from exception.fsr and exception.vaddress.
- */
+env->v7m.mmfar = env->exception.vaddress;
+env->v7m.cfsr |= CFSR_MMARVALID;
+/* TODO: further decoding of exception.fsr */
 armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_MEM);
 return;
 case EXCP_BKPT:
-- 
1.7.9.5




[Qemu-devel] [PATCH 3/6] ARM: Cortex-M3/M4: honor STKALIGN in CCR

2015-07-07 Thread Alex Zuepke

Signed-off-by: Alex Zuepke 
---
 hw/intc/armv7m_nvic.c |2 +-
 target-arm/helper.c   |5 ++---
 2 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
index e6ae047..369ef94 100644
--- a/hw/intc/armv7m_nvic.c
+++ b/hw/intc/armv7m_nvic.c
@@ -373,7 +373,7 @@ static void nvic_writel(nvic_state *s, uint32_t offset, 
uint32_t value)
 break;
 case 0xd14: /* Configuration Control.  */
 cpu = ARM_CPU(current_cpu);
-cpu->env.v7m.ccr = value & 0; /* TODO: add used bits */
+cpu->env.v7m.ccr = value & CCR_STKALIGN;
 break;
 case 0xd24: /* System Handler Control.  */
 /* TODO: Real hardware allows you to set/clear the active bits
diff --git a/target-arm/helper.c b/target-arm/helper.c
index aa34159..812204f 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -4579,9 +4579,8 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
 }
 
 /* Align stack pointer.  */
-/* ??? Should only do this if Configuration Control Register
-   STACKALIGN bit is set.  */
-if (env->regs[13] & 4) {
+/* Do this only if Configuration Control Register STKALIGN bit is set. */
+if ((env->v7m.ccr & CCR_STKALIGN) && (env->regs[13] & 4)) {
 env->regs[13] -= 4;
 xpsr |= 0x200;
 }
-- 
1.7.9.5




[Qemu-devel] [PATCH 1/6] ARM: add Cortex-M3/M4 exception configuration and status registers

2015-07-07 Thread Alex Zuepke

Signed-off-by: Alex Zuepke 
---
 target-arm/cpu.h |   51 ++
 target-arm/machine.c |6 ++
 2 files changed, 57 insertions(+)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 80297b3..1089f63 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -387,6 +387,12 @@ typedef struct CPUARMState {
 uint32_t control;
 int current_sp;
 int exception;
+uint32_t ccr;
+uint32_t cfsr;
+uint32_t hfsr;
+uint32_t dfsr;
+uint32_t mmfar;
+uint32_t bfar;
 } v7m;
 
 /* Information associated with an exception about to be taken:
@@ -852,6 +858,51 @@ enum arm_cpu_mode {
 #define ARM_IWMMXT_wCGR2   10
 #define ARM_IWMMXT_wCGR3   11
 
+/* V7M CCSR bits */
+#define CCR_STKALIGN0x0200
+#define CCR_BFHFNMIGN   0x0100
+#define CCR_DIV_0_TRP   0x0010
+#define CCR_UNALIGN_TRP 0x0008
+#define CCR_USERSETMPEND0x0002
+#define CCR_NONBASETHRDENA  0x0001
+
+/* V7M CFSR bits for UFSR */
+#define CFSR_DIVBYZERO  0x0200
+#define CFSR_UNALIGNED  0x0100
+#define CFSR_NOCP   0x0008
+#define CFSR_INVPC  0x0004
+#define CFSR_INVSTATE   0x0002
+#define CFSR_UNDEFINSTR 0x0001
+
+/* V7M CFSR bits for BFSR */
+#define CFSR_BFARVALID  0x8000
+#define CFSR_LSPERR 0x2000
+#define CFSR_STKERR 0x1000
+#define CFSR_UNSTKERR   0x0800
+#define CFSR_IMPRECISERR0x0400
+#define CFSR_PRECISERR  0x0200
+#define CFSR_IBUSERR0x0100
+
+/* V7M CFSR bits for MMFSR */
+#define CFSR_MMARVALID  0x0080
+#define CFSR_MLSPERR0x0020
+#define CFSR_MSTKERR0x0010
+#define CFSR_MUNSTKERR  0x0008
+#define CFSR_DACCVIOL   0x0002
+#define CFSR_IACCVIOL   0x0001
+
+/* V7M HFSR bits */
+#define HFSR_DEBUG_VT   0x8000
+#define HFSR_FORCED 0x4000
+#define HFSR_VECTTBL0x0002
+
+/* V7M DFSR bits */
+#define DFSR_EXTERNAL   0x0010
+#define DFSR_VCATCH 0x0008
+#define DFSR_DWTTRAP0x0004
+#define DFSR_BKPT   0x0002
+#define DFSR_HALTED 0x0001
+
 /* If adding a feature bit which corresponds to a Linux ELF
  * HWCAP bit, remember to update the feature-bit-to-hwcap
  * mapping in linux-user/elfload.c:get_elf_hwcap().
diff --git a/target-arm/machine.c b/target-arm/machine.c
index 9eb51df..11dcf29 100644
--- a/target-arm/machine.c
+++ b/target-arm/machine.c
@@ -101,6 +101,12 @@ static const VMStateDescription vmstate_m = {
 VMSTATE_UINT32(env.v7m.control, ARMCPU),
 VMSTATE_INT32(env.v7m.current_sp, ARMCPU),
 VMSTATE_INT32(env.v7m.exception, ARMCPU),
+VMSTATE_UINT32(env.v7m.ccr, ARMCPU),
+VMSTATE_UINT32(env.v7m.cfsr, ARMCPU),
+VMSTATE_UINT32(env.v7m.hfsr, ARMCPU),
+VMSTATE_UINT32(env.v7m.dfsr, ARMCPU),
+VMSTATE_UINT32(env.v7m.mmfar, ARMCPU),
+VMSTATE_UINT32(env.v7m.bfar, ARMCPU),
 VMSTATE_END_OF_LIST()
 }
 };
-- 
1.7.9.5




[Qemu-devel] [PATCH 6/6] ARM: enable PMSAv7-style MPU on Cortex-M3/M4

2015-07-07 Thread Alex Zuepke

Signed-off-by: Alex Zuepke 
---
 hw/intc/armv7m_nvic.c |  113 +
 target-arm/cpu.h  |6 +++
 target-arm/helper.c   |7 ++-
 target-arm/machine.c  |1 +
 4 files changed, 126 insertions(+), 1 deletion(-)

diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
index 369ef94..5820414 100644
--- a/hw/intc/armv7m_nvic.c
+++ b/hw/intc/armv7m_nvic.c
@@ -289,6 +289,36 @@ static uint32_t nvic_readl(nvic_state *s, uint32_t offset)
 return 0x0110;
 case 0xd70: /* ISAR4.  */
 return 0x01310102;
+case 0xd90: /* MPU type register.  */
+cpu = ARM_CPU(current_cpu);
+return cpu->pmsav7_dregion << 8;
+case 0xd94: /* MPU control register.  */
+cpu = ARM_CPU(current_cpu);
+return cpu->env.v7m.mpu_ctrl;
+case 0xd98: /* MPU_RNR.  */
+cpu = ARM_CPU(current_cpu);
+return cpu->env.cp15.c6_rgnr;
+case 0xd9c: /* MPU_RBAR: MPU region base address register.  */
+case 0xda4: /* MPU_RBAR_A1.  */
+case 0xdac: /* MPU_RBAR_A2.  */
+case 0xdb4: /* MPU_RBAR_A3.  */
+cpu = ARM_CPU(current_cpu);
+if (cpu->pmsav7_dregion == 0)
+return 0;
+val = cpu->env.pmsav7.drbar[cpu->env.cp15.c6_rgnr];
+val |= cpu->env.cp15.c6_rgnr;
+return val;
+case 0xda0: /* MPU_RSAR: MPU region attribute and size register.  */
+case 0xda8: /* MPU_RSAR_A1.  */
+case 0xdb0: /* MPU_RSAR_A2.  */
+case 0xdb8: /* MPU_RSAR_A3.  */
+cpu = ARM_CPU(current_cpu);
+if (cpu->pmsav7_dregion == 0)
+return 0;
+val = cpu->env.pmsav7.dracr[cpu->env.cp15.c6_rgnr];
+val <<= 16;
+val |= cpu->env.pmsav7.drsr[cpu->env.cp15.c6_rgnr];
+return val;
 /* TODO: Implement debug registers.  */
 default:
 qemu_log_mask(LOG_GUEST_ERROR, "NVIC: Bad read offset 0x%x\n", offset);
@@ -406,6 +436,57 @@ static void nvic_writel(nvic_state *s, uint32_t offset, 
uint32_t value)
 qemu_log_mask(LOG_UNIMP,
   "NVIC: AUX fault status registers unimplemented\n");
 break;
+case 0xd94: /* MPU control register.  */
+cpu = ARM_CPU(current_cpu);
+if (cpu->pmsav7_dregion == 0)
+break;
+cpu->env.v7m.mpu_ctrl = value & 0x7;
+if (cpu->env.v7m.mpu_ctrl & MPU_CTRL_ENABLE)
+cpu->env.cp15.sctlr_ns |= SCTLR_M;
+else
+cpu->env.cp15.sctlr_ns &= ~SCTLR_M;
+/* TODO: mimic MPU_CTRL_HFNMIENA */
+if (cpu->env.v7m.mpu_ctrl & MPU_CTRL_PRIVDEFENA)
+cpu->env.cp15.sctlr_ns |= SCTLR_BR;
+else
+cpu->env.cp15.sctlr_ns &= ~SCTLR_BR;
+/* This may enable/disable the MMU, so do a TLB flush.  */
+tlb_flush(CPU(cpu), 1);
+break;
+case 0xd98: /* MPU_RNR.  */
+cpu = ARM_CPU(current_cpu);
+value &= 0xff;
+if (value < cpu->pmsav7_dregion)
+cpu->env.cp15.c6_rgnr = value;
+break;
+case 0xd9c: /* MPU_RBAR: MPU region base address register.  */
+case 0xda4: /* MPU_RBAR_A1.  */
+case 0xdac: /* MPU_RBAR_A2.  */
+case 0xdb4: /* MPU_RBAR_A3.  */
+cpu = ARM_CPU(current_cpu);
+if (cpu->pmsav7_dregion == 0)
+break;
+if (value & 0x10) {
+/* region update */
+uint32_t region = value & 0x0f;
+if (region < cpu->pmsav7_dregion)
+cpu->env.cp15.c6_rgnr = region;
+}
+value &= ~0x1f;
+cpu->env.pmsav7.drbar[cpu->env.cp15.c6_rgnr] = value;
+tlb_flush(CPU(cpu), 1); /* Mappings may have changed - purge! */
+break;
+case 0xda0: /* MPU_RSAR: MPU region attribute and size register.  */
+case 0xda8: /* MPU_RSAR_A1.  */
+case 0xdb0: /* MPU_RSAR_A2.  */
+case 0xdb8: /* MPU_RSAR_A3.  */
+cpu = ARM_CPU(current_cpu);
+if (cpu->pmsav7_dregion == 0)
+break;
+cpu->env.pmsav7.dracr[cpu->env.cp15.c6_rgnr] = value >> 16;
+cpu->env.pmsav7.drsr[cpu->env.cp15.c6_rgnr] = value & 0x;
+tlb_flush(CPU(cpu), 1); /* Mappings may have changed - purge! */
+break;
 case 0xf00: /* Software Triggered Interrupt Register */
 if ((value & 0x1ff) < s->num_irq) {
 gic_set_pending_private(&s->gic, 0, value & 0x1ff);
@@ -445,6 +526,19 @@ static uint64_t nvic_sysreg_read(void *opaque, hwaddr addr,
 return val & 0x;
 }
 break;
+case 0xda0 ... 0xdb7: /* MPU_RSAR and aliases.  */
+cpu = ARM_CPU(current_cpu);
+if (cpu->pmsav7_dregion == 0)
+break;
+if ((size == 2) && (offset & 7) == 0) {
+val = cpu->env.pmsav7.drsr[cpu->env.cp15.c6

[Qemu-devel] [PATCH 2/6] ARM: accessors to Cortex-M3/M4 exception configuration and status registers

2015-07-07 Thread Alex Zuepke

Signed-off-by: Alex Zuepke 
---
 hw/intc/armv7m_nvic.c |   70 ++---
 1 file changed, 61 insertions(+), 9 deletions(-)

diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
index e13b729..e6ae047 100644
--- a/hw/intc/armv7m_nvic.c
+++ b/hw/intc/armv7m_nvic.c
@@ -225,8 +225,8 @@ static uint32_t nvic_readl(nvic_state *s, uint32_t offset)
 /* TODO: Implement SLEEPONEXIT.  */
 return 0;
 case 0xd14: /* Configuration Control.  */
-/* TODO: Implement Configuration Control bits.  */
-return 0;
+cpu = ARM_CPU(current_cpu);
+return cpu->env.v7m.ccr;
 case 0xd24: /* System Handler Status.  */
 val = 0;
 if (s->gic.irq_state[ARMV7M_EXCP_MEM].active) val |= (1 << 0);
@@ -245,16 +245,23 @@ static uint32_t nvic_readl(nvic_state *s, uint32_t offset)
 if (s->gic.irq_state[ARMV7M_EXCP_USAGE].enabled) val |= (1 << 18);
 return val;
 case 0xd28: /* Configurable Fault Status.  */
-/* TODO: Implement Fault Status.  */
-qemu_log_mask(LOG_UNIMP, "Configurable Fault Status unimplemented\n");
-return 0;
+cpu = ARM_CPU(current_cpu);
+return cpu->env.v7m.cfsr;
 case 0xd2c: /* Hard Fault Status.  */
+cpu = ARM_CPU(current_cpu);
+return cpu->env.v7m.hfsr;
 case 0xd30: /* Debug Fault Status.  */
+cpu = ARM_CPU(current_cpu);
+return cpu->env.v7m.dfsr;
 case 0xd34: /* Mem Manage Address.  */
+cpu = ARM_CPU(current_cpu);
+return cpu->env.v7m.mmfar;
 case 0xd38: /* Bus Fault Address.  */
+cpu = ARM_CPU(current_cpu);
+return cpu->env.v7m.bfar;
 case 0xd3c: /* Aux Fault Status.  */
 /* TODO: Implement fault status registers.  */
-qemu_log_mask(LOG_UNIMP, "Fault status registers unimplemented\n");
+qemu_log_mask(LOG_UNIMP, "AUX fault status registers unimplemented\n");
 return 0;
 case 0xd40: /* PFR0.  */
 return 0x0030;
@@ -361,9 +368,12 @@ static void nvic_writel(nvic_state *s, uint32_t offset, 
uint32_t value)
 }
 break;
 case 0xd10: /* System Control.  */
-case 0xd14: /* Configuration Control.  */
 /* TODO: Implement control registers.  */
-qemu_log_mask(LOG_UNIMP, "NVIC: SCR and CCR unimplemented\n");
+qemu_log_mask(LOG_UNIMP, "NVIC: SCR unimplemented\n");
+break;
+case 0xd14: /* Configuration Control.  */
+cpu = ARM_CPU(current_cpu);
+cpu->env.v7m.ccr = value & 0; /* TODO: add used bits */
 break;
 case 0xd24: /* System Handler Control.  */
 /* TODO: Real hardware allows you to set/clear the active bits
@@ -373,13 +383,28 @@ static void nvic_writel(nvic_state *s, uint32_t offset, 
uint32_t value)
 s->gic.irq_state[ARMV7M_EXCP_USAGE].enabled = (value & (1 << 18)) != 0;
 break;
 case 0xd28: /* Configurable Fault Status.  */
+cpu = ARM_CPU(current_cpu);
+cpu->env.v7m.cfsr &= ~value;
+break;
 case 0xd2c: /* Hard Fault Status.  */
+cpu = ARM_CPU(current_cpu);
+cpu->env.v7m.hfsr &= ~value;
+break;
 case 0xd30: /* Debug Fault Status.  */
+cpu = ARM_CPU(current_cpu);
+cpu->env.v7m.dfsr &= ~value;
+break;
 case 0xd34: /* Mem Manage Address.  */
+cpu = ARM_CPU(current_cpu);
+cpu->env.v7m.mmfar = value;
+break;
 case 0xd38: /* Bus Fault Address.  */
+cpu = ARM_CPU(current_cpu);
+cpu->env.v7m.bfar = value;
+break;
 case 0xd3c: /* Aux Fault Status.  */
 qemu_log_mask(LOG_UNIMP,
-  "NVIC: fault status registers unimplemented\n");
+  "NVIC: AUX fault status registers unimplemented\n");
 break;
 case 0xf00: /* Software Triggered Interrupt Register */
 if ((value & 0x1ff) < s->num_irq) {
@@ -399,6 +424,7 @@ static uint64_t nvic_sysreg_read(void *opaque, hwaddr addr,
 uint32_t offset = addr;
 int i;
 uint32_t val;
+ARMCPU *cpu;
 
 switch (offset) {
 case 0xd18 ... 0xd23: /* System Handler Priority.  */
@@ -407,6 +433,18 @@ static uint64_t nvic_sysreg_read(void *opaque, hwaddr addr,
 val |= s->gic.priority1[(offset - 0xd14) + i][0] << (i * 8);
 }
 return val;
+case 0xd28 ... 0xd2b: /* Configurable Fault Status.  */
+cpu = ARM_CPU(current_cpu);
+val = cpu->env.v7m.cfsr;
+if (size == 1) {
+val >>= (offset - 0xd28) * 8;
+return val & 0xff;
+}
+if ((size == 2) && ((offset & 1) == 0)) {
+val >>= (offset - 0xd28) * 8;
+return val & 0x;
+}
+break;
 case 0xfe0

Re: [Qemu-devel] QEMU ARM SMP: IPI delivery delayed until next main loop event // how to improve IPI latency?

2015-06-15 Thread Alex Zuepke

Am 15.06.2015 um 20:58 schrieb Peter Maydell:

On 15 June 2015 at 16:05, Alex Züpke  wrote:

Am 15.06.2015 um 16:51 schrieb Peter Maydell:

On 15 June 2015 at 15:44, Alex Züpke  wrote:

Am 12.06.2015 um 20:03 schrieb Peter Maydell:

Probably the best approach would be to have something in
arm_cpu_set_irq() which says "if we are CPU X and we've
just caused an interrupt to be set for CPU Y, then we
should ourselves yield back to the main loop".

Something like this, maybe, though I have done no more testing
than checking it doesn't actively break kernel booting :-)



Thanks! One more check for "level" is needed to get it work:


What happens without that? It's reasonable to have it,
but extra cpu_exit()s shouldn't cause a problem beyond
being a bit inefficient...


The emulation get's stuck, for whatever reason I don't understand.


I'm beginning to suspect that your guest code has a race
condition in it, such that if the other CPU runs at a
point you weren't expecting it to then you end up
deadlocking or otherwise running into a bug in your guest.

In particular, I see the emulation getting stuck even without
this patch to arm_cpu_set_irq().

-- PMM


Yes, it's a bug, sorry for that. I removed too much code to get a simple 
testcase. It's stuck in the first spinlock where CPU#1 is waiting for 
CPU#0 to initialize the rest of the system, and I need to WFE or YIELD 
here as well.


But this is showing the original problem again: the emulation get's 
stuck spinning on CPU #1 forever, because the main loop doesn't switch 
to CPU #0 voluntarily. Just press a key on the console/emulated serial 
line to trigger an event to QEMU's main loop, and the testcase should 
continue.



Best regards
Alex



[Qemu-devel] ARM: BKPT instructions should raise prefetch aborts with IFSR type 00010

2011-03-25 Thread Alex Zuepke
Hi,

while digging through some problems with BKPT exceptions on ARM, I
discovered that QEMU does not update IFSR on prefetch aborts. This
should be done since ARMv6 according to ARM docs. Please include.

Best Regards,
Alex

-- 
Alexander Zuepkeazue...@sysgo.com
SYSGO AG ~ Am Pfaffenstein 14 ~ 55270 Klein-Winternheim ~ Germany
 target-arm: BKPT instructions should raise prefetch aborts with IFSR type 00010
 diff against qemu 0.14.0
 Signed-off-by: Alex Zuepke 
--- qemu-0.14.0.orig/target-arm/translate.c	2011-02-16 15:44:05.0 +0100
+++ qemu-0.14.0/target-arm/translate.c	2011-03-25 11:22:03.0 +0100
@@ -6389,6 +6389,7 @@
 goto illegal_op;
 }
 /* bkpt */
+env->cp15.c5_insn = 2;
 gen_exception_insn(s, 4, EXCP_BKPT);
 break;
 case 0x8: /* signed multiply */
@@ -8930,6 +8931,7 @@
 break;
 
 case 0xe: /* bkpt */
+env->cp15.c5_insn = 2;
 gen_exception_insn(s, 2, EXCP_BKPT);
 break;
 


Re: [Qemu-devel] ARM: BKPT instructions should raise prefetch aborts with IFSR type 00010

2011-03-25 Thread Alex Zuepke
Hi Peter,

Peter Maydell schrieb:
> On 25 March 2011 10:54, Alex Zuepke  wrote:
>> while digging through some problems with BKPT exceptions on ARM, I
>> discovered that QEMU does not update IFSR on prefetch aborts. This
>> should be done since ARMv6 according to ARM docs. Please include.
> 
> This patch is the wrong approach to fixing this bug -- the
> updating of the IFSR needs to be done when the exception
> is taken, not when we translate the breakpoint instruction.

--- qemu-0.14.0.orig/target-arm/helper.c2011-02-16 15:44:05.0 
+0100
+++ qemu-0.14.0/target-arm/helper.c 2011-03-25 14:00:31.0 +0100
@@ -808,6 +808,8 @@ void do_interrupt(CPUARMState *env)
 return;
 }
 }
+/* indicate debug exception in IFSR */
+env->cp15.c5_insn = 2;
 /* Fall through to prefetch abort.  */
 case EXCP_PREFETCH_ABORT:
 new_mode = ARM_CPU_MODE_ABT;


Something like this? This neither looks good ...

> I'll put this on my todo list. If you happen to have a convenient
> test case demonstrating the problem, that would make a fix happen
> faster ;-)

Testcase is attached.

$ gunzip tc.elf.gz
$ qemu-system-arm.orig -nographic --cpu cortex-a8 -kernel tc.elf
testcase: IFSR undefined on QEMU
got prefetch abort, IFSR is 12345678
test: failed
HALT
Killed
$ qemu-system-arm.fixed -nographic --cpu cortex-a8 -kernel tc.elf
testcase: IFSR undefined on QEMU
got prefetch abort, IFSR is 0002
test: OK
HALT
Killed

Best Regards,
Alex

-- 
Alexander Zuepkeazue...@sysgo.com
SYSGO AG ~ Am Pfaffenstein 14 ~ 55270 Klein-Winternheim ~ Germany


tc.elf.gz
Description: application/gzip


[PATCH] target/arm: read access to performance counters from EL0

2022-04-28 Thread Alex Zuepke
The ARMv8 manual defines that PMUSERENR_EL0.ER enables read-access
to both PMXEVCNTR_EL0 and PMEVCNTR_EL0 registers, however,
we only use it for PMXEVCNTR_EL0. Extend to PMEVCNTR_EL0 as well.

Signed-off-by: Alex Zuepke 
---
 target/arm/helper.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/target/arm/helper.c b/target/arm/helper.c
index 63397bbac1..eb42b22766 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -6679,10 +6679,10 @@ static void define_pmu_regs(ARMCPU *cpu)
   .crm = 8 | (3 & (i >> 3)), .opc1 = 0, .opc2 = i & 7,
   .access = PL0_RW, .type = ARM_CP_IO | ARM_CP_ALIAS,
   .readfn = pmevcntr_readfn, .writefn = pmevcntr_writefn,
-  .accessfn = pmreg_access },
+  .accessfn = pmreg_access_xevcntr },
 { .name = pmevcntr_el0_name, .state = ARM_CP_STATE_AA64,
   .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 8 | (3 & (i >> 3)),
-  .opc2 = i & 7, .access = PL0_RW, .accessfn = pmreg_access,
+  .opc2 = i & 7, .access = PL0_RW, .accessfn = 
pmreg_access_xevcntr,
   .type = ARM_CP_IO,
   .readfn = pmevcntr_readfn, .writefn = pmevcntr_writefn,
   .raw_readfn = pmevcntr_rawread,
-- 
2.25.1




Re: [PATCH] target/arm: read access to performance counters from EL0

2022-05-04 Thread Alex Zuepke

Hi,

wanted to ping again on this issue before it gets lost.

Am 28.04.22 um 15:27 schrieb Alex Zuepke:

The ARMv8 manual defines that PMUSERENR_EL0.ER enables read-access
to both PMXEVCNTR_EL0 and PMEVCNTR_EL0 registers, however,
we only use it for PMXEVCNTR_EL0. Extend to PMEVCNTR_EL0 as well.


I configure PMUSERENR_EL0.ER for read access to the performance counters 
in user space, but it only works when I use the indexed access via the 
PMXEVCNTR_EL0 register, and not the direct access via the 
PMEVCNTR_EL0 registers.


Real Cortex-A53:
PMXEVCNTR_EL0read access in user space OK
PMEVCNTR_EL0  read access works

QEMU:
PMXEVCNTR_EL0read access works
PMEVCNTR_EL0  exception

The patch changes the access function for 32-bit mode PMEVCNTR and 
64-bit mode PMEVCNTR_EL0 registers to the one from the "X" variant.



Best regards
Alex



Signed-off-by: Alex Zuepke 
---
  target/arm/helper.c | 4 ++--
  1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/target/arm/helper.c b/target/arm/helper.c
index 63397bbac1..eb42b22766 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -6679,10 +6679,10 @@ static void define_pmu_regs(ARMCPU *cpu)
.crm = 8 | (3 & (i >> 3)), .opc1 = 0, .opc2 = i & 7,
.access = PL0_RW, .type = ARM_CP_IO | ARM_CP_ALIAS,
.readfn = pmevcntr_readfn, .writefn = pmevcntr_writefn,
-  .accessfn = pmreg_access },
+  .accessfn = pmreg_access_xevcntr },
  { .name = pmevcntr_el0_name, .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 3, .crn = 14, .crm = 8 | (3 & (i >> 3)),
-  .opc2 = i & 7, .access = PL0_RW, .accessfn = pmreg_access,
+  .opc2 = i & 7, .access = PL0_RW, .accessfn = 
pmreg_access_xevcntr,
.type = ARM_CP_IO,
.readfn = pmevcntr_readfn, .writefn = pmevcntr_writefn,
.raw_readfn = pmevcntr_rawread,