Re: [Qemu-devel] [PATCH 8/9] target-cris: add v17 CPU

2016-09-30 Thread Rabin Vincent
On Wed, Sep 28, 2016 at 12:42:41PM +0200, Edgar E. Iglesias wrote:
> I've applied these except patch #7 "ignore prefix insns in
> singlestep".  Patch #8 had an issue with checkpatch that I fixed up.

Oops, thank you.



Re: [Qemu-devel] [PATCH 6/9] target-cris: reduce v32isms from v10 log dumps

2016-09-26 Thread Rabin Vincent
On Tue, Sep 13, 2016 at 12:59:51AM +0200, Edgar E. Iglesias wrote:
> On Mon, Sep 05, 2016 at 01:54:09PM +0200, Rabin Vincent wrote:
> > @@ -3363,14 +3371,16 @@ void cris_cpu_dump_state(CPUState *cs, FILE *f, 
> > fprintf_function cpu_fprintf,
> >  cpu_fprintf(f, "\n");
> >  }
> >  }
> > -srs = env->pregs[PR_SRS];
> > -cpu_fprintf(f, "\nsupport function regs bank %x:\n", srs);
> > -if (srs < ARRAY_SIZE(env->sregs)) {
> > -for (i = 0; i < 16; i++) {
> > -cpu_fprintf(f, "s%2.2d=%8.8x ",
> > -i, env->sregs[srs][i]);
> > -if ((i + 1) % 4 == 0) {
> > -cpu_fprintf(f, "\n");
> > +if (env->pregs[PR_SRS] >= 32) {
> 
> 
> did you mean env->pregs[PR_VR] >= 32 here?

Here's an updated patch:

8<-
>From 4143896189ba073d14f6d89ad98ef4109d267bec Mon Sep 17 00:00:00 2001
From: Hans-Peter Nilsson <h...@axis.com>
Date: Mon, 15 Aug 2016 13:44:46 +0200
Subject: [PATCHv2] target-cris: reduce v32isms from v10 log dumps

Use the correct register names for v10 and don't dump support function
registers for pre-v32.

Signed-off-by: Hans-Peter Nilsson <h...@axis.com>
Signed-off-by: Rabin Vincent <rab...@axis.com>
---
v2: Fix PR_SRS -> PR_VR

 target-cris/translate.c | 36 +++-
 1 file changed, 23 insertions(+), 13 deletions(-)

diff --git a/target-cris/translate.c b/target-cris/translate.c
index f4a8d7d..b5ab0a5 100644
--- a/target-cris/translate.c
+++ b/target-cris/translate.c
@@ -140,14 +140,14 @@ static void gen_BUG(DisasContext *dc, const char *file, 
int line)
 cpu_abort(CPU(dc->cpu), "%s:%d\n", file, line);
 }
 
-static const char *regnames[] =
+static const char *regnames_v32[] =
 {
 "$r0", "$r1", "$r2", "$r3",
 "$r4", "$r5", "$r6", "$r7",
 "$r8", "$r9", "$r10", "$r11",
 "$r12", "$r13", "$sp", "$acr",
 };
-static const char *pregnames[] =
+static const char *pregnames_v32[] =
 {
 "$bz", "$vr", "$pid", "$srs",
 "$wz", "$exs", "$eda", "$mof",
@@ -3327,12 +3327,20 @@ void cris_cpu_dump_state(CPUState *cs, FILE *f, 
fprintf_function cpu_fprintf,
 {
 CRISCPU *cpu = CRIS_CPU(cs);
 CPUCRISState *env = >env;
+const char **regnames;
+const char **pregnames;
 int i;
-uint32_t srs;
 
 if (!env || !f) {
 return;
 }
+if (env->pregs[PR_VR] < 32) {
+pregnames = pregnames_v10;
+regnames = regnames_v10;
+} else {
+pregnames = pregnames_v32;
+regnames = regnames_v32;
+}
 
 cpu_fprintf(f, "PC=%x CCS=%x btaken=%d btarget=%x\n"
 "cc_op=%d cc_src=%d cc_dest=%d cc_result=%x cc_mask=%x\n",
@@ -3354,14 +3362,16 @@ void cris_cpu_dump_state(CPUState *cs, FILE *f, 
fprintf_function cpu_fprintf,
 cpu_fprintf(f, "\n");
 }
 }
-srs = env->pregs[PR_SRS];
-cpu_fprintf(f, "\nsupport function regs bank %x:\n", srs);
-if (srs < ARRAY_SIZE(env->sregs)) {
-for (i = 0; i < 16; i++) {
-cpu_fprintf(f, "s%2.2d=%8.8x ",
-i, env->sregs[srs][i]);
-if ((i + 1) % 4 == 0) {
-cpu_fprintf(f, "\n");
+if (env->pregs[PR_VR] >= 32) {
+uint32_t srs = env->pregs[PR_SRS];
+cpu_fprintf(f, "\nsupport function regs bank %x:\n", srs);
+if (srs < ARRAY_SIZE(env->sregs)) {
+for (i = 0; i < 16; i++) {
+cpu_fprintf(f, "s%2.2d=%8.8x ",
+i, env->sregs[srs][i]);
+if ((i + 1) % 4 == 0) {
+cpu_fprintf(f, "\n");
+}
 }
 }
 }
@@ -3406,12 +3416,12 @@ void cris_initialize_tcg(void)
 for (i = 0; i < 16; i++) {
 cpu_R[i] = tcg_global_mem_new(cpu_env,
   offsetof(CPUCRISState, regs[i]),
-  regnames[i]);
+  regnames_v32[i]);
 }
 for (i = 0; i < 16; i++) {
 cpu_PR[i] = tcg_global_mem_new(cpu_env,
offsetof(CPUCRISState, pregs[i]),
-   pregnames[i]);
+   pregnames_v32[i]);
 }
 }
 
-- 
2.1.4




Re: [Qemu-devel] [PATCH 8/9] target-cris: add v17 CPU

2016-09-26 Thread Rabin Vincent
On Tue, Sep 13, 2016 at 12:18:00AM +0200, Edgar E. Iglesias wrote:
> On Mon, Sep 05, 2016 at 01:54:11PM +0200, Rabin Vincent wrote:
> > diff --git a/target-cris/translate_v10.c b/target-cris/translate_v10.c
> > index a3da425..33d86eb 100644
> > --- a/target-cris/translate_v10.c
> > +++ b/target-cris/translate_v10.c
> > @@ -1097,6 +1097,14 @@ static unsigned int dec10_ind(CPUCRISState *env, 
> > DisasContext *dc)
> >  insn_len = dec10_bdap_m(env, dc, size);
> >  break;
> >  default:
> > +if (dc->opcode == CRISV17_IND_ADDC && dc->size == 2 &&
> > +env->pregs[PR_VR] == 17) {
> 
> Could you please add some comments on the insn encoding?
> Put the stuff from the commit msg in here.

OK, see new patch below.

> IIRC, ADDC and v17 are modifications made to the CRISv10 family of
> cores that never made it into the public manuals. Or am I wrong?

No, you're right.

8<---
>From 513465ad3f007885bafba3482705ba57cacd588b Mon Sep 17 00:00:00 2001
From: Rabin Vincent <rab...@axis.com>
Date: Mon, 15 Aug 2016 13:59:32 +0200
Subject: [PATCH] target-cris: add v17 CPU

In the CRIS v17 CPU an ADDC (add with carry) instruction has been added
compared to the v10 instruction set.

 Assembler syntax:

  ADDC [Rs],Rd
  ADDC [Rs+],Rd

 Size: Dword

 Description:

  The source data is added together with the carry flag to the
  destination register. The size of the operation is dword.

 Operation:

  Rd += s + C-flag;

 Flags affected:

  S R P U I X N Z V C
  - - - - - 0 * * * *

 Instruction format: ADDC [Rs],Rd

  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
  |Destination(Rd)| 1   0   0   1   1   0   1   0 |   Source(Rs)  |
  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+

 Instruction format: ADDC [Rs+],Rd

  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
  |Destination(Rd)| 1   1   0   1   1   0   1   0 |   Source(Rs)  |
  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+

Signed-off-by: Rabin Vincent <rab...@axis.com>
---
 target-cris/cpu.c| 14 ++
 target-cris/crisv10-decode.h |  1 +
 target-cris/translate_v10.c  | 23 +++
 3 files changed, 38 insertions(+)

diff --git a/target-cris/cpu.c b/target-cris/cpu.c
index c5a656b..d680cfb 100644
--- a/target-cris/cpu.c
+++ b/target-cris/cpu.c
@@ -246,6 +246,16 @@ static void crisv11_cpu_class_init(ObjectClass *oc, void 
*data)
 cc->gdb_read_register = crisv10_cpu_gdb_read_register;
 }
 
+static void crisv17_cpu_class_init(ObjectClass *oc, void *data)
+{
+CPUClass *cc = CPU_CLASS(oc);
+CRISCPUClass *ccc = CRIS_CPU_CLASS(oc);
+
+ccc->vr = 17;
+cc->do_interrupt = crisv10_cpu_do_interrupt;
+cc->gdb_read_register = crisv10_cpu_gdb_read_register;
+}
+
 static void crisv32_cpu_class_init(ObjectClass *oc, void *data)
 {
 CRISCPUClass *ccc = CRIS_CPU_CLASS(oc);
@@ -273,6 +283,10 @@ static const TypeInfo cris_cpu_model_type_infos[] = {
 .parent = TYPE_CRIS_CPU,
 .class_init = crisv11_cpu_class_init,
 }, {
+.name = TYPE("crisv17"),
+.parent = TYPE_CRIS_CPU,
+.class_init = crisv17_cpu_class_init,
+}, {
 .name = TYPE("crisv32"),
 .parent = TYPE_CRIS_CPU,
 .class_init = crisv32_cpu_class_init,
diff --git a/target-cris/crisv10-decode.h b/target-cris/crisv10-decode.h
index 587fbdd..bdb4b6d 100644
--- a/target-cris/crisv10-decode.h
+++ b/target-cris/crisv10-decode.h
@@ -92,6 +92,7 @@
 #define CRISV10_IND_JUMP_M   4
 #define CRISV10_IND_DIP  5
 #define CRISV10_IND_JUMP_R   6
+#define CRISV17_IND_ADDC 6
 #define CRISV10_IND_BOUND7
 #define CRISV10_IND_BCC_M7
 #define CRISV10_IND_MOVE_M_SPR   8
diff --git a/target-cris/translate_v10.c b/target-cris/translate_v10.c
index 4707a18..0e4d039 100644
--- a/target-cris/translate_v10.c
+++ b/target-cris/translate_v10.c
@@ -1094,6 +1094,29 @@ static unsigned int dec10_ind(CPUCRISState *env, 
DisasContext *dc)
 insn_len = dec10_bdap_m(env, dc, size);
 break;
 default:
+/*
+ * ADDC for v17:
+ *
+ * Instruction format: ADDC [Rs],Rd
+ *
+ *  
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+ *  |Destination(Rd)| 1   0   0   1   1   0   1   0 |   
Source(Rs)  |
+ *  
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+ *
+ * Instruction format: ADDC [Rs+],Rd
+ *
+ *  
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+ *  |Destination(Rd)| 1   1   0   1   1   0   1   0 

[Qemu-devel] [PATCHv2 1/8] tests: cris: force inlining

2016-09-12 Thread Rabin Vincent
From: Rabin Vincent <rab...@axis.com>

The CRIS tests expect that functions marked inline are always inline.
With newer versions of GCC, building them results warnings like the
following and spurious failures when they are run.

In file included from tests/tcg/cris/check_moveq.c:5:0:
tests/tcg/cris/crisutils.h:66:20: warning: inlining failed in call to
'cris_tst_cc.constprop.0': call is unlikely and code size would grow [-Winline]
tests/tcg/cris/check_moveq.c:28:13: warning: called from here [-Winline]

Use the always_inline attribute when building them to fix this.

Signed-off-by: Rabin Vincent <rab...@axis.com>
---
v2: don't redefine inline

 tests/tcg/cris/check_abs.c   |  4 ++--
 tests/tcg/cris/check_addc.c  |  2 +-
 tests/tcg/cris/check_addcm.c |  4 ++--
 tests/tcg/cris/check_bound.c |  6 +++---
 tests/tcg/cris/check_ftag.c  |  8 
 tests/tcg/cris/check_int64.c |  4 ++--
 tests/tcg/cris/check_lz.c|  2 +-
 tests/tcg/cris/check_swap.c  |  2 +-
 tests/tcg/cris/crisutils.h   | 20 ++--
 tests/tcg/cris/sys.h |  2 ++
 10 files changed, 28 insertions(+), 26 deletions(-)

diff --git a/tests/tcg/cris/check_abs.c b/tests/tcg/cris/check_abs.c
index 9770a8d..08b67b6 100644
--- a/tests/tcg/cris/check_abs.c
+++ b/tests/tcg/cris/check_abs.c
@@ -4,14 +4,14 @@
 #include "sys.h"
 #include "crisutils.h"
 
-static inline int cris_abs(int n)
+static always_inline int cris_abs(int n)
 {
int r;
asm ("abs\t%1, %0\n" : "=r" (r) : "r" (n));
return r;
 }
 
-static inline void
+static always_inline void
 verify_abs(int val, int res,
   const int n, const int z, const int v, const int c)
 {
diff --git a/tests/tcg/cris/check_addc.c b/tests/tcg/cris/check_addc.c
index facd1be..fc3fb1f 100644
--- a/tests/tcg/cris/check_addc.c
+++ b/tests/tcg/cris/check_addc.c
@@ -4,7 +4,7 @@
 #include "sys.h"
 #include "crisutils.h"
 
-static inline int cris_addc(int a, const int b)
+static always_inline int cris_addc(int a, const int b)
 {
asm ("addc\t%1, %0\n" : "+r" (a) : "r" (b));
return a;
diff --git a/tests/tcg/cris/check_addcm.c b/tests/tcg/cris/check_addcm.c
index 7928bc9..b355ba1 100644
--- a/tests/tcg/cris/check_addcm.c
+++ b/tests/tcg/cris/check_addcm.c
@@ -5,14 +5,14 @@
 #include "crisutils.h"
 
 /* need to avoid acr as source here.  */
-static inline int cris_addc_m(int a, const int *b)
+static always_inline int cris_addc_m(int a, const int *b)
 {
asm volatile ("addc [%1], %0\n" : "+r" (a) : "r" (b));
return a;
 }
 
 /* 'b' is a crisv32 constrain to avoid postinc with $acr.  */
-static inline int cris_addc_pi_m(int a, int **b)
+static always_inline int cris_addc_pi_m(int a, int **b)
 {
asm volatile ("addc [%1+], %0\n" : "+r" (a), "+b" (*b));
return a;
diff --git a/tests/tcg/cris/check_bound.c b/tests/tcg/cris/check_bound.c
index e883175..d956ab9 100644
--- a/tests/tcg/cris/check_bound.c
+++ b/tests/tcg/cris/check_bound.c
@@ -4,21 +4,21 @@
 #include "sys.h"
 #include "crisutils.h"
 
-static inline int cris_bound_b(int v, int b)
+static always_inline int cris_bound_b(int v, int b)
 {
int r = v;
asm ("bound.b\t%1, %0\n" : "+r" (r) : "ri" (b));
return r;
 }
 
-static inline int cris_bound_w(int v, int b)
+static always_inline int cris_bound_w(int v, int b)
 {
int r = v;
asm ("bound.w\t%1, %0\n" : "+r" (r) : "ri" (b));
return r;
 }
 
-static inline int cris_bound_d(int v, int b)
+static always_inline int cris_bound_d(int v, int b)
 {
int r = v;
asm ("bound.d\t%1, %0\n" : "+r" (r) : "ri" (b));
diff --git a/tests/tcg/cris/check_ftag.c b/tests/tcg/cris/check_ftag.c
index 908773a..aaa5c97 100644
--- a/tests/tcg/cris/check_ftag.c
+++ b/tests/tcg/cris/check_ftag.c
@@ -4,22 +4,22 @@
 #include "sys.h"
 #include "crisutils.h"
 
-static inline void cris_ftag_i(unsigned int x)
+static always_inline void cris_ftag_i(unsigned int x)
 {
register unsigned int v asm("$r10") = x;
asm ("ftagi\t[%0]\n" : : "r" (v) );
 }
-static inline void cris_ftag_d(unsigned int x)
+static always_inline void cris_ftag_d(unsigned int x)
 {
register unsigned int v asm("$r10") = x;
asm ("ftagd\t[%0]\n" : : "r" (v) );
 }
-static inline void cris_fidx_i(unsigned int x)
+static always_inline void cris_fidx_i(unsigned int x)
 {
register unsigned int v asm("$r10") = x;
asm ("fidxi\t[%0]\n" : : "r" (v) );
 }
-static inline void cris_fidx_d(unsigned int x)
+static always_inline void cris_fidx_d(unsigned int x)
 {
register unsigned int v asm("

Re: [Qemu-devel] [PATCH 1/9] tests: cris: force inlining

2016-09-08 Thread Rabin Vincent
On Tue, Sep 06, 2016 at 11:53:46PM +0200, Edgar E. Iglesias wrote:
> On Mon, Sep 05, 2016 at 01:54:04PM +0200, Rabin Vincent wrote:
> > From: Rabin Vincent <rab...@axis.com>
> > 
> > The CRIS tests expect that functions marked inline are always inline.
> > With newer versions of GCC, building them results warnings like the
> > following and spurious failures when they are run.
> > 
> > In file included from tests/tcg/cris/check_moveq.c:5:0:
> > tests/tcg/cris/crisutils.h:66:20: warning: inlining failed in call to
> > 'cris_tst_cc.constprop.0': call is unlikely and code size would grow 
> > [-Winline]
> > tests/tcg/cris/check_moveq.c:28:13: warning: called from here [-Winline]
> > 
> > Use the always_inline attribute when building them to fix this.
> 
> Hi Rabin,
> 
> Do you happen to have a public git tree/branch with these changes?

I've dropped the "sync CC state" patch for now and pushed the rest up to
the cris branch of https://github.com/rabinv/qemu/.



[Qemu-devel] [PATCHv2 2/8] tests: cris: fix syscall inline asm

2016-09-08 Thread Rabin Vincent
From: Rabin Vincent <rab...@axis.com>

Add the appropriate register constraints for the inline asm for the
write and exit system calls.  Without the correct constraints for the
write() function, correct failure messages are not printed succesfully
on newer version of GCC.

Signed-off-by: Rabin Vincent <rab...@axis.com>
---
v2: reworked to set up arguments correctly

 tests/tcg/cris/sys.c | 26 +-
 1 file changed, 17 insertions(+), 9 deletions(-)

diff --git a/tests/tcg/cris/sys.c b/tests/tcg/cris/sys.c
index 551c5dd..21f08c0 100644
--- a/tests/tcg/cris/sys.c
+++ b/tests/tcg/cris/sys.c
@@ -33,19 +33,27 @@ void *memset (void *s, int c, size_t n) {
 }
 
 void exit (int status) {
-   asm volatile ("moveq 1, $r9\n" /* NR_exit.  */
- "break 13\n");
+   register unsigned int callno asm ("r9") = 1; /* NR_exit */
+
+   asm volatile ("break 13\n"
+ :
+ : "r" (callno)
+ : "memory" );
while(1)
;
 }
 
 ssize_t write (int fd, const void *buf, size_t count) {
-   int r;
-   asm ("move.d %0, $r10\n"
-"move.d %1, $r11\n"
-"move.d %2, $r12\n"
-"moveq 4, $r9\n" /* NR_write.  */
-"break 13\n" : : "r" (fd), "r" (buf), "r" (count) : "memory");
-   asm ("move.d $r10, %0\n" : "=r" (r));
+   register unsigned int callno asm ("r9") = 4; /* NR_write */
+   register unsigned int r10 asm ("r10") = fd;
+   register const void *r11 asm ("r11") = buf;
+   register size_t r12 asm ("r12") = count;
+   register unsigned int r asm ("r10");
+
+   asm volatile ("break 13\n"
+: "=r" (r)
+: "r" (callno), "0" (r10), "r" (r11), "r" (r12)
+: "memory");
+
return r;
 }
-- 
2.1.4




[Qemu-devel] [PATCH 4/9] tests: cris: remove check_time1

2016-09-05 Thread Rabin Vincent
From: Rabin Vincent <rab...@axis.com>

This test, borrowed from the GDB simulator test suite, checks that every
syscall increments the time returned by gettimeofday() by exactly 1 ms.
This is not guaranteed or even desirable on QEMU so remove this test.

Signed-off-by: Rabin Vincent <rab...@axis.com>
---
 tests/tcg/cris/Makefile  |  1 -
 tests/tcg/cris/check_time1.c | 46 
 2 files changed, 47 deletions(-)
 delete mode 100644 tests/tcg/cris/check_time1.c

diff --git a/tests/tcg/cris/Makefile b/tests/tcg/cris/Makefile
index f5230fc..14a9eb5 100644
--- a/tests/tcg/cris/Makefile
+++ b/tests/tcg/cris/Makefile
@@ -114,7 +114,6 @@ TESTCASES += check_mmap1.ctst
 TESTCASES += check_mmap2.ctst
 TESTCASES += check_mmap3.ctst
 TESTCASES += check_sigalrm.ctst
-TESTCASES += check_time1.ctst
 TESTCASES += check_time2.ctst
 TESTCASES += check_settls1.ctst
 
diff --git a/tests/tcg/cris/check_time1.c b/tests/tcg/cris/check_time1.c
deleted file mode 100644
index 3fcf0e1..000
--- a/tests/tcg/cris/check_time1.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/* Basic time functionality test: check that milliseconds are
-   incremented for each syscall (does not work on host).  */
-#include 
-#include 
-#include 
-#include 
-#include 
-
-void err (const char *s)
-{
-  perror (s);
-  abort ();
-}
-
-int
-main (void)
-{
-  struct timeval t_m = {0, 0};
-  struct timezone t_z = {0, 0};
-  struct timeval t_m1 = {0, 0};
-  int i;
-
-  if (gettimeofday (_m, _z) != 0)
-err ("gettimeofday");
-
-  for (i = 1; i < 1; i++)
-if (gettimeofday (_m1, NULL) != 0)
-  err ("gettimeofday 1");
-else
-  if (t_m1.tv_sec * 100 + t_m1.tv_usec
- != (t_m.tv_sec * 100 + t_m.tv_usec + i * 1000))
-   {
- fprintf (stderr, "t0 (%ld, %ld), i %d, t1 (%ld, %ld)\n",
-  t_m.tv_sec, t_m.tv_usec, i, t_m1.tv_sec, t_m1.tv_usec);
- abort ();
-   }
-
-  if (time (NULL) != t_m1.tv_sec)
-{
-  fprintf (stderr, "time != gettod\n");
-  abort ();
-}
-
-  printf ("pass\n");
-  exit (0);
-}
-- 
2.1.4




[Qemu-devel] [PATCH 5/9] target-cris: sync CC state at load/stores.

2016-09-05 Thread Rabin Vincent
From: "Edgar E. Iglesias" <ed...@axis.com>

Icount may choose to abort and recompile a TB at any load/store.  We
need to sync the CC state at these insns.

Signed-off-by: Edgar E. Iglesias <ed...@axis.com>
Signed-off-by: Rabin Vincent <rab...@axis.com>
---
 target-cris/translate.c | 9 +
 target-cris/translate_v10.c | 3 +++
 2 files changed, 12 insertions(+)

diff --git a/target-cris/translate.c b/target-cris/translate.c
index f4a8d7d..c280e24 100644
--- a/target-cris/translate.c
+++ b/target-cris/translate.c
@@ -1098,6 +1098,9 @@ static void gen_load64(DisasContext *dc, TCGv_i64 dst, 
TCGv addr)
 {
 int mem_index = cpu_mmu_index(>cpu->env, false);
 
+/* Due to icount, we need to update the CC flags on load/stores.  */
+cris_evaluate_flags(dc);
+
 /* If we get a fault on a delayslot we must keep the jmp state in
the cpu-state to be able to re-execute the jmp.  */
 if (dc->delayed_branch == 1) {
@@ -1112,6 +1115,9 @@ static void gen_load(DisasContext *dc, TCGv dst, TCGv 
addr,
 {
 int mem_index = cpu_mmu_index(>cpu->env, false);
 
+/* Due to icount, we need to update the CC flags on load/stores.  */
+cris_evaluate_flags(dc);
+
 /* If we get a fault on a delayslot we must keep the jmp state in
the cpu-state to be able to re-execute the jmp.  */
 if (dc->delayed_branch == 1) {
@@ -1127,6 +1133,9 @@ static void gen_store (DisasContext *dc, TCGv addr, TCGv 
val,
 {
 int mem_index = cpu_mmu_index(>cpu->env, false);
 
+/* Due to icount, we need to update the CC flags on load/stores.  */
+cris_evaluate_flags(dc);
+
 /* If we get a fault on a delayslot we must keep the jmp state in
the cpu-state to be able to re-execute the jmp.  */
 if (dc->delayed_branch == 1) {
diff --git a/target-cris/translate_v10.c b/target-cris/translate_v10.c
index 4707a18..a3da425 100644
--- a/target-cris/translate_v10.c
+++ b/target-cris/translate_v10.c
@@ -99,6 +99,9 @@ static void gen_store_v10(DisasContext *dc, TCGv addr, TCGv 
val,
 {
 int mem_index = cpu_mmu_index(>cpu->env, false);
 
+/* Due to icount, we need to update the CC flags on load/stores.  */
+cris_evaluate_flags(dc);
+
 /* If we get a fault on a delayslot we must keep the jmp state in
the cpu-state to be able to re-execute the jmp.  */
 if (dc->delayed_branch == 1) {
-- 
2.1.4




[Qemu-devel] [PATCH 9/9] tests: cris: add v17 ADDC test

2016-09-05 Thread Rabin Vincent
From: Rabin Vincent <rab...@axis.com>

Add a test for the newly implemented ADDC instruction in the v17 CRIS
CPU.

Signed-off-by: Rabin Vincent <rab...@axis.com>
---
 tests/tcg/cris/Makefile| 19 ++--
 tests/tcg/cris/check_addcv17.s | 65 ++
 2 files changed, 82 insertions(+), 2 deletions(-)
 create mode 100644 tests/tcg/cris/check_addcv17.s

diff --git a/tests/tcg/cris/Makefile b/tests/tcg/cris/Makefile
index 14a9eb5..6b3dba4 100644
--- a/tests/tcg/cris/Makefile
+++ b/tests/tcg/cris/Makefile
@@ -23,6 +23,7 @@ SYS= sys.o
 TESTCASES += check_abs.tst
 TESTCASES += check_addc.tst
 TESTCASES += check_addcm.tst
+TESTCASES += check_addcv17.tst
 TESTCASES += check_addo.tst
 TESTCASES += check_addoq.tst
 TESTCASES += check_addi.tst
@@ -134,13 +135,27 @@ all: build
 %.ctst: %.o
$(CC) $(CFLAGS) $(LDLIBS) $< -o $@
 
+
+sysv10.o: sys.c
+   $(CC) $(CFLAGS) -mcpu=v10 -c $< -o $@
+
+crtv10.o: crt.s
+   $(AS) $(ASFLAGS) -mcpu=v10 -c $< -o $@
+
+check_addcv17.tst: ASFLAGS += -mcpu=v10
+check_addcv17.tst: CRT := crtv10.o
+check_addcv17.tst: SYS := sysv10.o
+check_addcv17.tst: crtv10.o sysv10.o
+
 build: $(CRT) $(SYS) $(TESTCASES)
 
 check: $(CRT) $(SYS) $(TESTCASES)
@echo -e "\nQEMU simulator."
for case in $(TESTCASES); do \
echo -n "$$case "; \
-   $(SIM) ./$$case; \
+   SIMARGS=; \
+   case $$case in *v17*) SIMARGS="-cpu crisv17";; esac; \
+   $(SIM) $$SIMARGS ./$$case; \
done
 check-g: $(CRT) $(SYS) $(TESTCASES)
@echo -e "\nGDB simulator."
@@ -150,4 +165,4 @@ check-g: $(CRT) $(SYS) $(TESTCASES)
done
 
 clean:
-   $(RM) -fr $(TESTCASES) $(CRT) $(SYS)
+   $(RM) -fr $(TESTCASES) *.o
diff --git a/tests/tcg/cris/check_addcv17.s b/tests/tcg/cris/check_addcv17.s
new file mode 100644
index 000..52ef7a9
--- /dev/null
+++ b/tests/tcg/cris/check_addcv17.s
@@ -0,0 +1,65 @@
+# mach:  crisv17
+
+ .include "testutils.inc"
+
+ .macro addc Rs Rd inc=0
+# Create the instruction manually since there is no assembler support yet
+ .word (\Rd << 12) | \Rs | (\inc << 10) | 0x09a0
+ .endm
+
+ start
+
+ .data
+mem1:
+ .dword 0x0
+mem2:
+ .dword 0x12345678
+
+ .text
+ move.d mem1,r4
+ clearf nzvc
+ addc 4 3
+ test_cc 0 1 0 0
+ checkr3 0
+
+ move.d mem1,r4
+ clearf nzvc
+ ax
+ addc 4 3
+ test_cc 0 0 0 0
+ checkr3 0
+
+ move.d mem1,r4
+ clearf nzvc
+ setf c
+ addc 4 3
+ test_cc 0 0 0 0
+ checkr3 1
+
+ move.d mem2,r4
+ moveq 2, r3
+ clearf nzvc
+ setf c
+ addc 4 3
+ test_cc 0 0 0 0
+ checkr3 1234567b
+
+ move.d mem2,r5
+ clearf nzvc
+ cmp.d r4,r5
+ test_cc 0 1 0 0
+
+ move.d mem2,r4
+ moveq 2, r3
+ clearf nzvc
+ addc 4 3 inc=1
+ test_cc 0 0 0 0
+ checkr3 1234567a
+
+ move.d mem2,r5
+ clearf nzvc
+ addq 4,r5
+ cmp.d r4,r5
+ test_cc 0 1 0 0
+
+ quit
-- 
2.1.4




[Qemu-devel] [PATCH 6/9] target-cris: reduce v32isms from v10 log dumps

2016-09-05 Thread Rabin Vincent
From: Hans-Peter Nilsson <h...@axis.com>

Use the correct register names for v10 and don't dump support function
registers for pre-v32.

Signed-off-by: Hans-Peter Nilsson <h...@axis.com>
Signed-off-by: Rabin Vincent <rab...@axis.com>
---
 target-cris/translate.c | 36 +++-
 1 file changed, 23 insertions(+), 13 deletions(-)

diff --git a/target-cris/translate.c b/target-cris/translate.c
index c280e24..a4512b5 100644
--- a/target-cris/translate.c
+++ b/target-cris/translate.c
@@ -140,14 +140,14 @@ static void gen_BUG(DisasContext *dc, const char *file, 
int line)
 cpu_abort(CPU(dc->cpu), "%s:%d\n", file, line);
 }
 
-static const char *regnames[] =
+static const char *regnames_v32[] =
 {
 "$r0", "$r1", "$r2", "$r3",
 "$r4", "$r5", "$r6", "$r7",
 "$r8", "$r9", "$r10", "$r11",
 "$r12", "$r13", "$sp", "$acr",
 };
-static const char *pregnames[] =
+static const char *pregnames_v32[] =
 {
 "$bz", "$vr", "$pid", "$srs",
 "$wz", "$exs", "$eda", "$mof",
@@ -3336,12 +3336,20 @@ void cris_cpu_dump_state(CPUState *cs, FILE *f, 
fprintf_function cpu_fprintf,
 {
 CRISCPU *cpu = CRIS_CPU(cs);
 CPUCRISState *env = >env;
+const char **regnames;
+const char **pregnames;
 int i;
-uint32_t srs;
 
 if (!env || !f) {
 return;
 }
+if (env->pregs[PR_VR] < 32) {
+pregnames = pregnames_v10;
+regnames = regnames_v10;
+} else {
+pregnames = pregnames_v32;
+regnames = regnames_v32;
+}
 
 cpu_fprintf(f, "PC=%x CCS=%x btaken=%d btarget=%x\n"
 "cc_op=%d cc_src=%d cc_dest=%d cc_result=%x cc_mask=%x\n",
@@ -3363,14 +3371,16 @@ void cris_cpu_dump_state(CPUState *cs, FILE *f, 
fprintf_function cpu_fprintf,
 cpu_fprintf(f, "\n");
 }
 }
-srs = env->pregs[PR_SRS];
-cpu_fprintf(f, "\nsupport function regs bank %x:\n", srs);
-if (srs < ARRAY_SIZE(env->sregs)) {
-for (i = 0; i < 16; i++) {
-cpu_fprintf(f, "s%2.2d=%8.8x ",
-i, env->sregs[srs][i]);
-if ((i + 1) % 4 == 0) {
-cpu_fprintf(f, "\n");
+if (env->pregs[PR_SRS] >= 32) {
+uint32_t srs = env->pregs[PR_SRS];
+cpu_fprintf(f, "\nsupport function regs bank %x:\n", srs);
+if (srs < ARRAY_SIZE(env->sregs)) {
+for (i = 0; i < 16; i++) {
+cpu_fprintf(f, "s%2.2d=%8.8x ",
+i, env->sregs[srs][i]);
+if ((i + 1) % 4 == 0) {
+cpu_fprintf(f, "\n");
+}
 }
 }
 }
@@ -3415,12 +3425,12 @@ void cris_initialize_tcg(void)
 for (i = 0; i < 16; i++) {
 cpu_R[i] = tcg_global_mem_new(cpu_env,
   offsetof(CPUCRISState, regs[i]),
-  regnames[i]);
+  regnames_v32[i]);
 }
 for (i = 0; i < 16; i++) {
 cpu_PR[i] = tcg_global_mem_new(cpu_env,
offsetof(CPUCRISState, pregs[i]),
-   pregnames[i]);
+   pregnames_v32[i]);
 }
 }
 
-- 
2.1.4




[Qemu-devel] [PATCH 2/9] tests: cris: fix syscall inline asm

2016-09-05 Thread Rabin Vincent
From: Rabin Vincent <rab...@axis.com>

Add the clobbered registeres to the inline asm for the write and exit
system calls.  Without the correct clobbers for the write() function,
correct failure messages are not printed succesfully on newer version of
GCC.

Signed-off-by: Rabin Vincent <rab...@axis.com>
---
 tests/tcg/cris/sys.c | 10 --
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/tests/tcg/cris/sys.c b/tests/tcg/cris/sys.c
index 551c5dd..dfa5e1c 100644
--- a/tests/tcg/cris/sys.c
+++ b/tests/tcg/cris/sys.c
@@ -34,7 +34,10 @@ void *memset (void *s, int c, size_t n) {
 
 void exit (int status) {
asm volatile ("moveq 1, $r9\n" /* NR_exit.  */
- "break 13\n");
+ "break 13\n"
+ :
+ :
+ : "r9", "memory" );
while(1)
;
 }
@@ -45,7 +48,10 @@ ssize_t write (int fd, const void *buf, size_t count) {
 "move.d %1, $r11\n"
 "move.d %2, $r12\n"
 "moveq 4, $r9\n" /* NR_write.  */
-"break 13\n" : : "r" (fd), "r" (buf), "r" (count) : "memory");
+"break 13\n"
+:
+: "r" (fd), "r" (buf), "r" (count)
+: "r9", "r10", "r11", "r12", "memory");
asm ("move.d $r10, %0\n" : "=r" (r));
return r;
 }
-- 
2.1.4




[Qemu-devel] [PATCH 7/9] target-cris: ignore prefix insns in singlestep

2016-09-05 Thread Rabin Vincent
From: Hans-Peter Nilsson <h...@axis.com>

Don't count prefix instructions as separate when singlestepping.

For example, for this following instruction

 1ad8:   a011 e00b   move.d r0,[r1-96]

before this patch, we get two register dumps:

 PC=1ad8 CCS=0 btaken=1 btarget=1ac6
 cc_op=1 cc_src=3746 cc_dest=1 cc_result=ea2 cc_mask=0
 $r0= $r1=4360 $r2=4308 $r3=026c
 $r4=2076 $r5=2022 $r6= $r7=
 $r8= $r9=0ea2 $r10=0002 $r11=4308
 $r12=1080 $r13=0ec0 $sp=bfd8 $pc=1ad4

 PC=1ada CCS=800 btaken=1 btarget=1ac6
 cc_op=1 cc_src=3746 cc_dest=1 cc_result=ea2 cc_mask=0
 $r0= $r1=4360 $r2=4308 $r3=026c
 $r4=2076 $r5=2022 $r6= $r7=
 $r8= $r9=0ea2 $r10=0002 $r11=4308
 $r12=1080 $r13=0ec0 $sp=bfd8 $pc=1ad4

With the patch, we get only one:

 PC=1ad8 CCS=0 btaken=1 btarget=1ac6
 cc_op=1 cc_src=3746 cc_dest=1 cc_result=ea2 cc_mask=0
 $r0= $r1=4360 $r2=4308 $r3=026c
 $r4=2076 $r5=2022 $r6= $r7=
 $r8= $r9=0ea2 $r10=0002 $r11=4308
 $r12=1080 $r13=0ec0 $sp=bfd8 $pc=1ad4

Signed-off-by: Hans-Peter Nilsson <h...@axis.com>
Signed-off-by: Rabin Vincent <rab...@axis.com>
---
 target-cris/translate.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/target-cris/translate.c b/target-cris/translate.c
index a4512b5..c9b1e65 100644
--- a/target-cris/translate.c
+++ b/target-cris/translate.c
@@ -3262,7 +3262,8 @@ void gen_intermediate_code(CPUCRISState *env, struct 
TranslationBlock *tb)
 }
 } while (!dc->is_jmp && !dc->cpustate_changed
 && !tcg_op_buf_full()
-&& !singlestep
+/* We don't count prefix insns as separate wrt. singlestep.  */
+&& (!singlestep || (dc->tb_flags & PFIX_FLAG))
 && (dc->pc < next_page_start)
 && num_insns < max_insns);
 
-- 
2.1.4




[Qemu-devel] [PATCH 8/9] target-cris: add v17 CPU

2016-09-05 Thread Rabin Vincent
From: Rabin Vincent <rab...@axis.com>

In the CRIS v17 CPU an ADDC (add with carry) instruction has been added
compared to the v10 instruction set.

 Assembler syntax:

  ADDC [Rs],Rd
  ADDC [Rs+],Rd

 Size: Dword

 Description:

  The source data is added together with the carry flag to the
  destination register. The size of the operation is dword.

 Operation:

  Rd += s + C-flag;

 Flags affected:

  S R P U I X N Z V C
  - - - - - 0 * * * *

 Instruction format: ADDC [Rs],Rd

  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
  |Destination(Rd)| 1   0   0   1   1   0   1   0 |   Source(Rs)  |
  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+

 Instruction format: ADDC [Rs+],Rd

  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
  |Destination(Rd)| 1   1   0   1   1   0   1   0 |   Source(Rs)  |
  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+

Signed-off-by: Rabin Vincent <rab...@axis.com>
---
 target-cris/cpu.c| 14 ++
 target-cris/crisv10-decode.h |  1 +
 target-cris/translate_v10.c  |  8 
 3 files changed, 23 insertions(+)

diff --git a/target-cris/cpu.c b/target-cris/cpu.c
index c5a656b..d680cfb 100644
--- a/target-cris/cpu.c
+++ b/target-cris/cpu.c
@@ -246,6 +246,16 @@ static void crisv11_cpu_class_init(ObjectClass *oc, void 
*data)
 cc->gdb_read_register = crisv10_cpu_gdb_read_register;
 }
 
+static void crisv17_cpu_class_init(ObjectClass *oc, void *data)
+{
+CPUClass *cc = CPU_CLASS(oc);
+CRISCPUClass *ccc = CRIS_CPU_CLASS(oc);
+
+ccc->vr = 17;
+cc->do_interrupt = crisv10_cpu_do_interrupt;
+cc->gdb_read_register = crisv10_cpu_gdb_read_register;
+}
+
 static void crisv32_cpu_class_init(ObjectClass *oc, void *data)
 {
 CRISCPUClass *ccc = CRIS_CPU_CLASS(oc);
@@ -273,6 +283,10 @@ static const TypeInfo cris_cpu_model_type_infos[] = {
 .parent = TYPE_CRIS_CPU,
 .class_init = crisv11_cpu_class_init,
 }, {
+.name = TYPE("crisv17"),
+.parent = TYPE_CRIS_CPU,
+.class_init = crisv17_cpu_class_init,
+}, {
 .name = TYPE("crisv32"),
 .parent = TYPE_CRIS_CPU,
 .class_init = crisv32_cpu_class_init,
diff --git a/target-cris/crisv10-decode.h b/target-cris/crisv10-decode.h
index 587fbdd..bdb4b6d 100644
--- a/target-cris/crisv10-decode.h
+++ b/target-cris/crisv10-decode.h
@@ -92,6 +92,7 @@
 #define CRISV10_IND_JUMP_M   4
 #define CRISV10_IND_DIP  5
 #define CRISV10_IND_JUMP_R   6
+#define CRISV17_IND_ADDC 6
 #define CRISV10_IND_BOUND7
 #define CRISV10_IND_BCC_M7
 #define CRISV10_IND_MOVE_M_SPR   8
diff --git a/target-cris/translate_v10.c b/target-cris/translate_v10.c
index a3da425..33d86eb 100644
--- a/target-cris/translate_v10.c
+++ b/target-cris/translate_v10.c
@@ -1097,6 +1097,14 @@ static unsigned int dec10_ind(CPUCRISState *env, 
DisasContext *dc)
 insn_len = dec10_bdap_m(env, dc, size);
 break;
 default:
+if (dc->opcode == CRISV17_IND_ADDC && dc->size == 2 &&
+env->pregs[PR_VR] == 17) {
+LOG_DIS("addc op=%d %d\n",  dc->src, dc->dst);
+cris_cc_mask(dc, CC_MASK_NZVC);
+insn_len += dec10_ind_alu(env, dc, CC_OP_ADDC, size);
+break;
+}
+
 LOG_DIS("pc=%x var-ind.%d %d r%d r%d\n",
   dc->pc, size, dc->opcode, dc->src, dc->dst);
 cpu_abort(CPU(dc->cpu), "Unhandled opcode");
-- 
2.1.4




[Qemu-devel] [PATCH 3/9] tests: cris: remove openpf4 test

2016-09-05 Thread Rabin Vincent
From: Rabin Vincent <rab...@axis.com>

This test, borrowed from the GDB simulator test suite, is meant to test
the GDB simulator's --sysroot feature and always fails in QEMU.  Remove
it.  openpf3 tests the same sequence of system calls (without assuming
the precence of --sysroot).

Signed-off-by: Rabin Vincent <rab...@axis.com>
---
 tests/tcg/cris/Makefile| 1 -
 tests/tcg/cris/check_openpf4.c | 5 -
 2 files changed, 6 deletions(-)
 delete mode 100644 tests/tcg/cris/check_openpf4.c

diff --git a/tests/tcg/cris/Makefile b/tests/tcg/cris/Makefile
index d34bfd8..f5230fc 100644
--- a/tests/tcg/cris/Makefile
+++ b/tests/tcg/cris/Makefile
@@ -108,7 +108,6 @@ TESTCASES += check_stat4.ctst
 TESTCASES += check_openpf1.ctst
 TESTCASES += check_openpf2.ctst
 TESTCASES += check_openpf3.ctst
-TESTCASES += check_openpf4.ctst
 TESTCASES += check_openpf5.ctst
 TESTCASES += check_mapbrk.ctst
 TESTCASES += check_mmap1.ctst
diff --git a/tests/tcg/cris/check_openpf4.c b/tests/tcg/cris/check_openpf4.c
deleted file mode 100644
index 8bbee41..000
--- a/tests/tcg/cris/check_openpf4.c
+++ /dev/null
@@ -1,5 +0,0 @@
-/* Basic file operations, now *with* sysroot.
-#sim: --sysroot=@exedir@
-*/
-#define PREFIX "/"
-#include "check_openpf3.c"
-- 
2.1.4




[Qemu-devel] [PATCH 1/9] tests: cris: force inlining

2016-09-05 Thread Rabin Vincent
From: Rabin Vincent <rab...@axis.com>

The CRIS tests expect that functions marked inline are always inline.
With newer versions of GCC, building them results warnings like the
following and spurious failures when they are run.

In file included from tests/tcg/cris/check_moveq.c:5:0:
tests/tcg/cris/crisutils.h:66:20: warning: inlining failed in call to
'cris_tst_cc.constprop.0': call is unlikely and code size would grow [-Winline]
tests/tcg/cris/check_moveq.c:28:13: warning: called from here [-Winline]

Use the always_inline attribute when building them to fix this.

Signed-off-by: Rabin Vincent <rab...@axis.com>
---
 tests/tcg/cris/sys.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/tests/tcg/cris/sys.h b/tests/tcg/cris/sys.h
index c5f88e1..b1bf4c5 100644
--- a/tests/tcg/cris/sys.h
+++ b/tests/tcg/cris/sys.h
@@ -3,6 +3,8 @@
 #define STRINGIFY(x) #x
 #define TOSTRING(x) STRINGIFY(x)
 
+#define inline inline __attribute__((always_inline))
+
 #define CURRENT_LOCATION __FILE__ ":" TOSTRING(__LINE__)
 
 #define err() \
-- 
2.1.4




Re: [Qemu-devel] [PATCH] nand: fix flash erase when oob is in memory

2015-11-23 Thread Rabin Vincent
(to: Kevin and cc: qemu-block)

On Fri, Nov 13, 2015 at 02:17:28PM +0100, Ricard Wanderlöf wrote:
> 
> For the "main area on file, oob in memory" case, fix the shifts so that
> we erase the correct number of pages.
> 
> Signed-off-by: Ricard Wanderlöf 
> ---
>  hw/block/nand.c |2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/hw/block/nand.c b/hw/block/nand.c
> index a68266f..f0e3413 100644
> --- a/hw/block/nand.c
> +++ b/hw/block/nand.c
> @@ -712,7 +712,7 @@ static void glue(nand_blk_erase_, 
> PAGE_SIZE)(NANDFlashState *s)
>  memset(s->storage + (PAGE(addr) << OOB_SHIFT),
>  0xff, OOB_SIZE << s->erase_shift);
>  i = SECTOR(addr);
> -page = SECTOR(addr + (ADDR_SHIFT + s->erase_shift));
> +page = SECTOR(addr + (1 << (ADDR_SHIFT + s->erase_shift)));
>  for (; i < page; i ++)
>  if (blk_write(s->blk, i, iobuf, 1) < 0) {
>  printf("%s: write error in sector %" PRIu64 "\n", __func__, 
> i);
> -- 
> 1.7.10.4
> 
> -- 
> Ricard Wolf Wanderlöf   ricardw(at)axis.com
> Axis Communications AB, Lund, Swedenwww.axis.com
> Phone +46 46 272 2016   Fax +46 46 13 61 30
> 
> 



[Qemu-devel] [PATCH] nand: fix address overflow

2015-11-10 Thread Rabin Vincent
The shifts of the address mask and value shift beyond 32 bits when there
are 5 address cycles.

Signed-off-by: Rabin Vincent <rabin.vinc...@axis.com>
---
 hw/block/nand.c |4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/block/nand.c b/hw/block/nand.c
index 61d2cec..a68266f 100644
--- a/hw/block/nand.c
+++ b/hw/block/nand.c
@@ -522,8 +522,8 @@ void nand_setio(DeviceState *dev, uint32_t value)
 
 if (s->ale) {
 unsigned int shift = s->addrlen * 8;
-unsigned int mask = ~(0xff << shift);
-unsigned int v = value << shift;
+uint64_t mask = ~(0xffull << shift);
+uint64_t v = (uint64_t)value << shift;
 
 s->addr = (s->addr & mask) | v;
 s->addrlen ++;
-- 
1.7.10.4




Re: [Qemu-devel] [PATCH] target-arm: add dump-guest-memory support

2014-12-24 Thread Rabin Vincent
On Tue, Dec 23, 2014 at 11:45:00PM +, Peter Maydell wrote:
 On 23 December 2014 at 23:29, Rabin Vincent ra...@rab.in wrote:
  +static size_t round4(size_t size)
  +{
  +return ((size + 3) / 4) * 4;
  +}
 
 Is this different from ROUND_UP(size, 4) ?
 If we can use the standard macro from the headers we should;
 if there's a real difference we should comment about what it is.

No, I'll use ROUND_UP.

  +int arm_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
  + int cpuid, void *opaque)
  +{
  +aarch64_elf_prstatus prstatus = {.pid = cpuid};
  +ARMCPU *cpu = ARM_CPU(cs);
  +
  +memcpy((prstatus.regs), cpu-env.xregs, sizeof(cpu-env.xregs));
  +prstatus.pc = cpu-env.pc;
  +prstatus.pstate = cpu-env.pstate;
 
 You need to use the correct accessor function for pstate, not
 all the bits are kept in env.pstate. Call pstate_read().

OK.

 Can we get here when a 64-bit CPU is in AArch32 mode? (eg,
 64 bit guest OS running a 32 bit compat process at the
 point of taking the memory dump). If so, what sort of
 core file should we be writing?

I'd say still 64-bit.

 Assuming the answer is still 64 bit core dump you need
 to do something here to sync the 32 bit TCG state into the
 64 bit xregs array. (KVM can take care of itself.)

I have now tested this by triggering a dump while a 32-bit process is
incrementing a register in a tight loop, and the following, which I
lifted off the exception handling code, appears to work:

if (!is_a64(cpu-env)) {   
int i;

for (i = 0; i  15; i++) {
prstatus.regs[i] = cpu-env.regs[i];
}
}

  +int cpu_get_dump_info(ArchDumpInfo *info,
  +  const struct GuestPhysBlockList *guest_phys_blocks)
  +{
  +info-d_machine = ELF_MACHINE;
  +info-d_class = (info-d_machine == EM_ARM) ? ELFCLASS32 : ELFCLASS64;
  +
  +#ifdef TARGET_WORDS_BIGENDIAN
  +info-d_endian = ELFDATA2MSB;
  +#else
  +info-d_endian = ELFDATA2LSB;
  +#endif
 
 Note that in fact ARM is never going to be TARGET_WORDS_BIGENDIAN,
 even if the guest is big-endian, because the #define represents
 the bus endianness, not whether the CPU happens to currently be
 doing byte-swizzling. Do you need to key d_endian off the CPU's
 current endianness setting? The current endianness of EL1?
 Something else?

IIUC we don't currently support anything other than little endian in
system emulation?  Attempting to boot a BE ARMv7 vexpress kernel hits
the unimplementation of setend pretty quickly, and I don't see any
machine initializing the bswap_code to big endian.

According the the ELF specification for ARM, the choice between
ELFDATA2LSB and ELFDATA2MSB will be governed by the default data order
in the execution environment.  Since we dump the full system memory I
would interpret this to be the lowest execution environment.  So I
guess for ARM this would mean setting big endian if (SCTLR.EE ||
SCTLR.B) and for AArch64 if SCTLR_EL1.E0E is set?

(I had assumed that post-analysis tools would refuse to open a dump if
the endianness does not match but this does not seem to be the case.  I
tested by generating dumps with this d_endian hardcoded to both
ELFDATA2LSB and ELFDATA2MSB and gdb appears to open them and show the
registers and memory without complaining.)



[Qemu-devel] [PATCH] target-arm: add dump-guest-memory support

2014-12-23 Thread Rabin Vincent
Enable support for the dump-guest-memory command on ARM and AArch64.
The dumped files can be analyzed with crash or similar tools.

Signed-off-by: Rabin Vincent ra...@rab.in
---
 target-arm/Makefile.objs |   2 +-
 target-arm/arch_dump.c   | 148 +++
 target-arm/cpu-qom.h |   8 +++
 target-arm/cpu.c |   4 ++
 4 files changed, 161 insertions(+), 1 deletion(-)
 create mode 100644 target-arm/arch_dump.c

diff --git a/target-arm/Makefile.objs b/target-arm/Makefile.objs
index 9460b40..38ba48c 100644
--- a/target-arm/Makefile.objs
+++ b/target-arm/Makefile.objs
@@ -7,6 +7,6 @@ obj-$(call lnot,$(CONFIG_KVM)) += kvm-stub.o
 obj-y += translate.o op_helper.o helper.o cpu.o
 obj-y += neon_helper.o iwmmxt_helper.o
 obj-y += gdbstub.o
-obj-$(CONFIG_SOFTMMU) += psci.o
+obj-$(CONFIG_SOFTMMU) += psci.o arch_dump.o
 obj-$(TARGET_AARCH64) += cpu64.o translate-a64.o helper-a64.o gdbstub64.o
 obj-y += crypto_helper.o
diff --git a/target-arm/arch_dump.c b/target-arm/arch_dump.c
new file mode 100644
index 000..4e7b9a2
--- /dev/null
+++ b/target-arm/arch_dump.c
@@ -0,0 +1,148 @@
+#include cpu.h
+
+#include sysemu/dump.h
+#include elf.h
+
+/* Matches elf_prstatus in linux/elfcore.h */
+
+typedef struct {
+char pad1[24];
+uint32_t pid;
+char pad2[44];
+uint32_t regs[18];
+char pad3[4];
+} arm_elf_prstatus;
+
+typedef struct {
+char pad1[32];
+uint32_t pid;
+char pad2[76];
+uint64_t regs[32];
+uint64_t pc;
+uint64_t pstate;
+char pad3[4];
+} aarch64_elf_prstatus;
+
+static size_t round4(size_t size)
+{
+return ((size + 3) / 4) * 4;
+}
+
+static int write_elf_note(const char *name, uint32_t type,
+  void *desc, size_t descsz,
+  WriteCoreDumpFunction f, void *opaque)
+{
+size_t note_size, name_size, note_head_size;
+DumpState *s = opaque;
+int class = s-dump_info.d_class;
+Elf64_Nhdr *note64;
+Elf32_Nhdr *note32;
+void *note;
+char *buf;
+int ret;
+
+name_size = strlen(name) + 1;
+
+if (class == ELFCLASS32) {
+note_head_size = sizeof(Elf32_Nhdr);
+} else {
+note_head_size = sizeof(Elf64_Nhdr);
+}
+
+note_size = note_head_size + round4(name_size) + descsz;
+note = g_malloc0(note_size);
+
+if (class == ELFCLASS32) {
+note32 = note;
+note32-n_namesz = cpu_to_dump32(s, name_size);
+note32-n_descsz = cpu_to_dump32(s, descsz);
+note32-n_type = cpu_to_dump32(s, type);
+} else {
+note64 = note;
+note64-n_namesz = cpu_to_dump64(s, name_size);
+note64-n_descsz = cpu_to_dump64(s, descsz);
+note64-n_type = cpu_to_dump64(s, type);
+}
+
+buf = note;
+buf += note_head_size;
+
+memcpy(buf, name, name_size);
+buf += round4(name_size);
+
+memcpy(buf, desc, descsz);
+
+ret = f(note, note_size, opaque);
+g_free(note);
+
+return ret;
+}
+
+int arm_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
+ int cpuid, void *opaque)
+{
+arm_elf_prstatus prstatus = {.pid = cpuid};
+ARMCPU *cpu = ARM_CPU(cs);
+
+memcpy((prstatus.regs), cpu-env.regs, sizeof(cpu-env.regs));
+prstatus.regs[16] = cpsr_read(cpu-env);
+
+return write_elf_note(CORE, NT_PRSTATUS,
+  prstatus, sizeof(prstatus),
+  f, opaque);
+}
+
+int arm_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
+ int cpuid, void *opaque)
+{
+aarch64_elf_prstatus prstatus = {.pid = cpuid};
+ARMCPU *cpu = ARM_CPU(cs);
+
+memcpy((prstatus.regs), cpu-env.xregs, sizeof(cpu-env.xregs));
+prstatus.pc = cpu-env.pc;
+prstatus.pstate = cpu-env.pstate;
+
+return write_elf_note(CORE, NT_PRSTATUS,
+  prstatus, sizeof(prstatus),
+  f, opaque);
+}
+
+int arm_cpu_write_elf32_qemunote(WriteCoreDumpFunction f,
+  CPUState *cpu, void *opaque)
+{
+return 0;
+}
+
+int arm_cpu_write_elf64_qemunote(WriteCoreDumpFunction f,
+  CPUState *cpu, void *opaque)
+{
+return 0;
+}
+
+int cpu_get_dump_info(ArchDumpInfo *info,
+  const struct GuestPhysBlockList *guest_phys_blocks)
+{
+info-d_machine = ELF_MACHINE;
+info-d_class = (info-d_machine == EM_ARM) ? ELFCLASS32 : ELFCLASS64;
+
+#ifdef TARGET_WORDS_BIGENDIAN
+info-d_endian = ELFDATA2MSB;
+#else
+info-d_endian = ELFDATA2LSB;
+#endif
+
+return 0;
+}
+
+ssize_t cpu_get_note_size(int class, int machine, int nr_cpus)
+{
+size_t elf_note_size = round4(sizeof(CORE));
+
+if (machine == EM_ARM) {
+elf_note_size += sizeof(Elf32_Nhdr) + sizeof(arm_elf_prstatus);
+} else {
+elf_note_size += sizeof(Elf64_Nhdr) + sizeof(aarch64_elf_prstatus);
+}
+
+return elf_note_size * nr_cpus;
+}
diff --git a/target-arm/cpu

Re: [Qemu-devel] boot arm fedora via u-boot in qemu

2014-10-26 Thread Rabin Vincent
On Wed, Oct 22, 2014 at 11:59:06AM +0200, Gerd Hoffmann wrote:
 syntax error
 ## Error: catX not defined
 syntax error
 ## Error: catX not defined
 No kernel provides dtb named vexpress-v2p-ca9.dtb
 No value for u_kernel.  Getting help.
 [ ... ]
 
 Google finds me this:
 
 https://fedoraproject.org/wiki/Architectures/ARM/F20/Installation#For_the_BeagleBone_Black
 
 Suggested fix is to replace uboot.  Heh.
 
 Anyone has clue what is going on and how to fix it?  I suspect it is
 simply one of the many CONFIG_* switches in u-boot which must be
 flipped?

The problem is that commit fe9ca3d3287185 (hush: fix some quoted
variable expansion issues) in U-Boot breaks this command in boot.scr.

 setenv catcat setenv catout\;'setenv catX setenv catout 
'\\\''\$\$catin'\\\''' \; run catX

Reverting that commit from U-Boot fixes the script problem, then you'll
need to set a few more variables to get the full boot working:

diff --git a/include/configs/vexpress_common.h 
b/include/configs/vexpress_common.h
index 54cb69f..72436d2 100644
--- a/include/configs/vexpress_common.h
+++ b/include/configs/vexpress_common.h
@@ -217,6 +217,9 @@
scriptaddr= 0x67d0\0 \
pxefile_addr_r= 0x67e0\0 \
fdt_addr_r= 0x67f0\0 \
+   u_boot= bootz\0 \
+   u_kernel= 3.11.10-301.fc20.armv7hl\0 \
+   u_extraargs= console=ttyAMA0,115200n8\0 \
ramdisk_addr_r= 0x6800\0
 #elif defined(CONFIG_VEXPRESS_EXTENDED_MEMORY_MAP)
 #define CONFIG_PLATFORM_ENV_SETTINGS \



[Qemu-devel] [PATCH 1/3] timer: add EFM32 timer

2014-05-04 Thread Rabin Vincent
Add support for the TIMER block on the EFM32GG.

Signed-off-by: Rabin Vincent ra...@rab.in
---
 hw/timer/Makefile.objs |   1 +
 hw/timer/efm32-timer.c | 204 +
 2 files changed, 205 insertions(+)
 create mode 100644 hw/timer/efm32-timer.c

diff --git a/hw/timer/Makefile.objs b/hw/timer/Makefile.objs
index 2c86c3d..440d4ec 100644
--- a/hw/timer/Makefile.objs
+++ b/hw/timer/Makefile.objs
@@ -18,6 +18,7 @@ common-obj-$(CONFIG_IMX) += imx_gpt.o
 common-obj-$(CONFIG_LM32) += lm32_timer.o
 common-obj-$(CONFIG_MILKYMIST) += milkymist-sysctl.o
 
+obj-$(CONFIG_EFM32) += efm32-timer.o
 obj-$(CONFIG_EXYNOS4) += exynos4210_mct.o
 obj-$(CONFIG_EXYNOS4) += exynos4210_pwm.o
 obj-$(CONFIG_EXYNOS4) += exynos4210_rtc.o
diff --git a/hw/timer/efm32-timer.c b/hw/timer/efm32-timer.c
new file mode 100644
index 000..bbceb43
--- /dev/null
+++ b/hw/timer/efm32-timer.c
@@ -0,0 +1,204 @@
+/*
+ * EFM32GG Timer
+ *
+ * Copyright (C) 2014 Rabin Vincent ra...@rab.in
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include hw/sysbus.h
+#include sysemu/sysemu.h
+#include qemu/timer.h
+
+enum {
+TIMER_CTRL  = 0x00,
+TIMER_CMD   = 0x04,
+TIMER_IEN   = 0x0C,
+TIMER_IF= 0x10,
+TIMER_IFS   = 0x14,
+TIMER_IFC   = 0x18,
+TIMER_CNT   = 0x24,
+TIMER_REG_SIZE  = TIMER_CNT + 4,
+
+TIMER_CTRL_MODE_UP  = 0x0,
+TIMER_CTRL_MODE_DOWN= 0x1,
+
+TIMER_CMD_START = 1  0,
+TIMER_CMD_STOP  = 1  1,
+
+TIMER_IF_OF = 1  0,
+TIMER_IF_UF = 1  1,
+};
+
+#define REG(s, x) (s-regs[(x) / 4])
+
+#define TYPE_EFM32_TIMER efm32-timer
+#define EFM32_TIMER(obj) \
+OBJECT_CHECK(Efm32TimerState, (obj), TYPE_EFM32_TIMER)
+
+typedef struct Efm32TimerState {
+SysBusDevice parent_obj;
+
+MemoryRegion iomem;
+uint32_t rate;
+QEMUTimer *timer;
+uint32_t regs[TIMER_REG_SIZE / 4];
+qemu_irq irq;
+} Efm32TimerState;
+
+#define HFPERCLK_RATE 4800
+
+static uint64_t timer_to_ns(Efm32TimerState *s, uint64_t value)
+{
+return muldiv64(value, get_ticks_per_sec(), s-rate);
+}
+
+static uint64_t ns_to_timer(Efm32TimerState *s, uint64_t value)
+{
+return muldiv64(value, s-rate, get_ticks_per_sec());
+}
+
+static uint32_t timer_mode(Efm32TimerState *s)
+{
+return REG(s, TIMER_CTRL)  0x3;
+}
+
+static void timer_update_irq(Efm32TimerState *s)
+{
+qemu_set_irq(s-irq, REG(s, TIMER_IF)  REG(s, TIMER_IEN));
+}
+
+static void timer_tick(void *opaque)
+{
+Efm32TimerState *s = opaque;
+uint32_t flag;
+
+if (timer_mode(s) == TIMER_CTRL_MODE_UP) {
+flag = TIMER_IF_OF;
+} else {
+flag = TIMER_IF_UF;
+}
+
+REG(s, TIMER_IF) |= flag;
+
+timer_update_irq(s);
+}
+
+static uint64_t timer_read(void *opaque, hwaddr offset,
+  unsigned size)
+{
+Efm32TimerState *s = opaque;
+
+switch (offset) {
+case TIMER_CTRL:
+return REG(s, TIMER_CTRL);
+case TIMER_IEN:
+return REG(s, TIMER_IEN);
+case TIMER_IF:
+return REG(s, TIMER_IF);
+case TIMER_CNT:
+return ns_to_timer(s, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
+}
+
+return 0;
+}
+
+static void timer_write(void *opaque, hwaddr offset,
+   uint64_t value, unsigned size)
+{
+Efm32TimerState *s = opaque;
+
+switch (offset) {
+case TIMER_CTRL:
+REG(s, TIMER_CTRL) = value;
+s-rate = HFPERCLK_RATE / (1  ((value  24)  0xff));
+break;
+case TIMER_IEN:
+REG(s, TIMER_IEN) = value;
+break;
+case TIMER_IFS:
+REG(s, TIMER_IF) |= value;
+break;
+case TIMER_IFC:
+REG(s, TIMER_IF) = ~value;
+break;
+case TIMER_CMD:
+if (value  TIMER_CMD_START) {
+uint32_t expiry;
+
+if (timer_mode(s) == TIMER_CTRL_MODE_UP) {
+expiry = 0x - REG(s, TIMER_CNT);
+} else if (timer_mode(s) == TIMER_CTRL_MODE_DOWN) {
+expiry = REG(s, TIMER_CNT);
+}
+
+timer_mod(s-timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) \
++ timer_to_ns(s, expiry));
+} else if (value  TIMER_CMD_STOP) {
+timer_del(s-timer);
+}
+break;
+case TIMER_CNT:
+REG(s, TIMER_CNT) = value;
+break;
+}
+
+timer_update_irq(s);
+}
+
+static const MemoryRegionOps timer_ops = {
+.read = timer_read,
+.write = timer_write,
+.endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static const VMStateDescription vmstate_efm32_timer = {
+.name = efm32-timer,
+.version_id = 1,
+.minimum_version_id = 1,
+.minimum_version_id_old = 1,
+.fields  = (VMStateField[]) {
+VMSTATE_UINT32(rate, Efm32TimerState

[Qemu-devel] [PATCH 2/3] char: add EFM32 UART

2014-05-04 Thread Rabin Vincent
Add support for the UART block on the EFM32GG.

Signed-off-by: Rabin Vincent ra...@rab.in
---
 hw/char/Makefile.objs |   1 +
 hw/char/efm32-uart.c  | 217 ++
 2 files changed, 218 insertions(+)
 create mode 100644 hw/char/efm32-uart.c

diff --git a/hw/char/Makefile.objs b/hw/char/Makefile.objs
index 317385d..7261569 100644
--- a/hw/char/Makefile.objs
+++ b/hw/char/Makefile.objs
@@ -9,6 +9,7 @@ common-obj-$(CONFIG_XILINX) += xilinx_uartlite.o
 common-obj-$(CONFIG_XEN_BACKEND) += xen_console.o
 common-obj-$(CONFIG_CADENCE) += cadence_uart.o
 
+obj-$(CONFIG_EFM32) += efm32-uart.o
 obj-$(CONFIG_EXYNOS4) += exynos4210_uart.o
 obj-$(CONFIG_COLDFIRE) += mcf_uart.o
 obj-$(CONFIG_OMAP) += omap_uart.o
diff --git a/hw/char/efm32-uart.c b/hw/char/efm32-uart.c
new file mode 100644
index 000..bca433f
--- /dev/null
+++ b/hw/char/efm32-uart.c
@@ -0,0 +1,217 @@
+/*
+ * EFM32GG UART
+ *
+ * Copyright (c) 2014 Rabin Vincent ra...@rab.in
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include hw/hw.h
+#include hw/sysbus.h
+#include sysemu/char.h
+
+enum {
+UARTn_CMD   = 0x0c,
+UARTn_STATUS= 0x10,
+UARTn_RXDATAX   = 0x18,
+UARTn_TXDATA= 0x34,
+UARTn_IF= 0x40,
+UARTn_IFS   = 0x44,
+UARTn_IFC   = 0x48,
+UARTn_IEN   = 0x4c,
+UARTn_REG_SIZE  = UARTn_IEN + 4,
+
+UARTn_STATUS_TXBL   = 1  6,
+UARTn_STATUS_RXFULL = 1  8,
+UARTn_STATUS_RXDATAV= 1  7,
+
+UARTn_RXDATAX_FERR  = 1  15,
+
+UARTn_IF_RXDATAV= 1  2,
+};
+
+#define REG(s, x) (s-regs[(x) / 4])
+
+#define TYPE_EFM32_UART efm32-uart
+#define EFM32_UART(obj) \
+OBJECT_CHECK(Efm32UartState, (obj), TYPE_EFM32_UART)
+
+struct Efm32UartState {
+SysBusDevice parent_obj;
+
+MemoryRegion regs_region;
+CharDriverState *chr;
+qemu_irq rxirq;
+qemu_irq txirq;
+
+uint32_t regs[UARTn_REG_SIZE / 4];
+};
+
+typedef struct Efm32UartState Efm32UartState;
+
+static void efm32_uart_update_irq(Efm32UartState *s)
+{
+if (REG(s, UARTn_STATUS)  UARTn_STATUS_RXDATAV) {
+REG(s, UARTn_IF) |= UARTn_IF_RXDATAV;
+} else {
+REG(s, UARTn_IF) = ~UARTn_IF_RXDATAV;
+}
+
+qemu_set_irq(s-rxirq, REG(s, UARTn_IF)  \
+   REG(s, UARTn_IEN)  \
+   UARTn_IF_RXDATAV);
+}
+
+static uint64_t efm32_uart_read(void *opaque, hwaddr addr, unsigned size)
+{
+Efm32UartState *s = opaque;
+uint32_t r = 0;
+
+switch (addr) {
+case UARTn_STATUS:
+return REG(s, UARTn_STATUS);
+case UARTn_RXDATAX:
+REG(s, UARTn_STATUS) = ~UARTn_STATUS_RXDATAV;
+return REG(s, UARTn_RXDATAX);
+case UARTn_IF:
+return REG(s, UARTn_IF);
+case UARTn_IEN:
+return REG(s, UARTn_IEN);
+}
+
+efm32_uart_update_irq(s);
+
+return r;
+}
+
+static void efm32_uart_write(void *opaque, hwaddr addr,
+ uint64_t value, unsigned size)
+{
+Efm32UartState *s = opaque;
+unsigned char ch = value;
+
+switch (addr) {
+case UARTn_TXDATA:
+if (s-chr) {
+qemu_chr_fe_write(s-chr, ch, 1);
+}
+break;
+case UARTn_IFS:
+REG(s, UARTn_IF) |= value;
+break;
+case UARTn_IFC:
+REG(s, UARTn_IF) = ~value;
+break;
+case UARTn_IEN:
+REG(s, UARTn_IEN) = value;
+break;
+}
+
+efm32_uart_update_irq(s);
+}
+
+static const MemoryRegionOps uart_mmio_ops = {
+.read = efm32_uart_read,
+.write = efm32_uart_write,
+.valid = {
+.min_access_size = 4,
+.max_access_size = 4,
+},
+.endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void efm32_uart_rx(void *opaque, const uint8_t *buf, int size)
+{
+Efm32UartState *s = opaque;
+
+REG(s, UARTn_STATUS) |= UARTn_STATUS_RXDATAV;
+REG(s, UARTn_RXDATAX) = *buf;
+
+efm32_uart_update_irq(s);
+}
+
+static int efm32_uart_can_rx(void *opaque)
+{
+Efm32UartState *s = opaque;
+
+return !(REG(s, UARTn_STATUS)  UARTn_STATUS_RXDATAV);
+}
+
+static void efm32_uart_event(void *opaque, int event)
+{
+Efm32UartState *s = opaque;
+
+if (event == CHR_EVENT_BREAK) {
+REG(s, UARTn_STATUS) |= UARTn_STATUS_RXDATAV;
+REG(s, UARTn_RXDATAX) = UARTn_RXDATAX_FERR;
+efm32_uart_update_irq(s);
+}
+}
+
+static void efm32_uart_reset(DeviceState *d)
+{
+Efm32UartState *s = EFM32_UART(d);
+
+memset(s-regs, 0, sizeof(s-regs));
+REG(s, UARTn_STATUS) |= UARTn_STATUS_TXBL;
+}
+
+static void efm32_uart_realize(DeviceState *dev, Error **errp)
+{
+Efm32UartState *s = EFM32_UART(dev);
+
+s-chr = qemu_char_get_next_serial();
+if (s-chr) {
+qemu_chr_add_handlers(s-chr, efm32_uart_can_rx, efm32_uart_rx

[Qemu-devel] [PATCH 3/3] arm: add EFM32GG-DK3750 support

2014-05-04 Thread Rabin Vincent
Add support for the EFM32GG990 MCU and its development board
EFM32GG-DK3750.  This is a Cortex-M3 platform supported
by mainline Linux.

Signed-off-by: Rabin Vincent ra...@rab.in
---
 default-configs/arm-softmmu.mak |  1 +
 hw/arm/Makefile.objs|  1 +
 hw/arm/efm32.c  | 71 +
 3 files changed, 73 insertions(+)
 create mode 100644 hw/arm/efm32.c

diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
index f3513fa..d151f27 100644
--- a/default-configs/arm-softmmu.mak
+++ b/default-configs/arm-softmmu.mak
@@ -57,6 +57,7 @@ CONFIG_PL310=y
 CONFIG_PL330=y
 CONFIG_CADENCE=y
 CONFIG_XGMAC=y
+CONFIG_EFM32=y
 CONFIG_EXYNOS4=y
 CONFIG_PXA2XX=y
 CONFIG_BITBANG_I2C=y
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 6088e53..7030a82 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -6,5 +6,6 @@ obj-y += tosa.o versatilepb.o vexpress.o virt.o xilinx_zynq.o 
z2.o
 
 obj-y += armv7m.o exynos4210.o pxa2xx.o pxa2xx_gpio.o pxa2xx_pic.o
 obj-$(CONFIG_DIGIC) += digic.o
+obj-$(CONFIG_EFM32) += efm32.o
 obj-y += omap1.o omap2.o strongarm.o
 obj-$(CONFIG_ALLWINNER_A10) += allwinner-a10.o cubieboard.o
diff --git a/hw/arm/efm32.c b/hw/arm/efm32.c
new file mode 100644
index 000..201f921
--- /dev/null
+++ b/hw/arm/efm32.c
@@ -0,0 +1,71 @@
+/*
+ * EFM32GG
+ *
+ * Copyright (C) 2014 Rabin Vincent ra...@rab.in
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include hw/sysbus.h
+#include hw/arm/arm.h
+#include hw/devices.h
+#include hw/boards.h
+#include hw/block/flash.h
+#include exec/address-spaces.h
+
+static void efm32_init(QEMUMachineInitArgs *args)
+{
+static const int timer_irq[] = {2, 12, 13, 14};
+const char *cpu_model = args-cpu_model;
+const char *kernel_filename = args-kernel_filename;
+MemoryRegion *address_space_mem = get_system_memory();
+qemu_irq *pic;
+int i;
+MemoryRegion *nor = g_new(MemoryRegion, 1);
+MemoryRegion *psram = g_new(MemoryRegion, 1);
+DriveInfo *dinfo;
+uint32_t flashsize = 16 * 1024 * 1024;
+
+pic = armv7m_init(address_space_mem, 1024, 128, kernel_filename, 
cpu_model);
+
+memory_region_init_ram(psram, NULL, psram, 4 * 1024 * 1024);
+vmstate_register_ram_global(psram);
+memory_region_add_subregion(address_space_mem, 0x8800, psram);
+
+memory_region_init_ram(nor, NULL, flash, flashsize);
+vmstate_register_ram_global(nor);
+memory_region_add_subregion(address_space_mem, 0x8C00, nor);
+memory_region_set_readonly(nor, true);
+
+sysbus_create_varargs(efm32-uart, 0x4000e400, pic[22], pic[23], NULL);
+for (i = 0; i  4; i++) {
+sysbus_create_simple(efm32-timer, 0x4001 + i * 0x400,
+ pic[timer_irq[i]]);
+}
+
+dinfo = drive_get(IF_PFLASH, 0, 0);
+if (dinfo) {
+int sector_len = 128 * 1024;
+if (!pflash_cfi01_register(0x8c00, NULL, dk.flash, flashsize,
+   dinfo ? dinfo-bdrv : NULL,
+   sector_len, flashsize / sector_len,
+   2, 0, 0, 0, 0, 0)) {
+fprintf(stderr, qemu: Error registering flash memory.\n);
+exit(1);
+}
+}
+}
+
+static QEMUMachine efm32ggdk3750_machine = {
+.name = efm32ggdk3750,
+.desc = EnergyMicro Giant Gecko Development Kit,
+.init = efm32_init,
+};
+
+static void efm32_machine_init(void)
+{
+qemu_register_machine(efm32ggdk3750_machine);
+}
+
+machine_init(efm32_machine_init);
-- 
2.0.0.rc0




[Qemu-devel] [PATCH] armv7m_nvic: fix CPUID Base Register

2014-04-20 Thread Rabin Vincent
cp15.c0_cpuid is never initialized for ARMv7-M; take the value directly
from cpu-midr instead.

Signed-off-by: Rabin Vincent ra...@rab.in
---
 hw/intc/armv7m_nvic.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
index 6066fa6..f5b0c3b 100644
--- a/hw/intc/armv7m_nvic.c
+++ b/hw/intc/armv7m_nvic.c
@@ -173,7 +173,7 @@ static uint32_t nvic_readl(nvic_state *s, uint32_t offset)
 return 1;
 case 0xd00: /* CPUID Base.  */
 cpu = ARM_CPU(current_cpu);
-return cpu-env.cp15.c0_cpuid;
+return cpu-midr;
 case 0xd04: /* Interrupt Control State.  */
 /* VECTACTIVE */
 val = s-gic.running_irq[0];
-- 
1.9.1




Re: [Qemu-devel] [PATCHv2 0/6] ARM dump-guest-memory support

2013-03-29 Thread Rabin Vincent
2013/3/25 Andreas Färber afaer...@suse.de
 This still does not address the architectural issue that I brought up.

I guess you mean the CPUArchState stuff?  AFAICS Wen Congyang (the
author of the dump code) had some answers/questions for you:

http://lists.gnu.org/archive/html/qemu-devel/2012-07/msg00382.html
http://lists.gnu.org/archive/html/qemu-devel/2012-07/msg00384.html



[Qemu-devel] [PATCHv2 0/6] ARM dump-guest-memory support

2013-03-24 Thread Rabin Vincent
A second patchset to add dump-guest-memory support for ARM.

This version of the patchset addresses the following comments from the
previous posting, and also adds some more patches to the core dump code
(patch #4 and #6):

 - memset prstatus to 0 in x86_64_write_elf64_note()
 - handle big endian in dump_write_elf_note()
 - Save CPSR in ARM prstatus
 - set correct ELF endianness for ARM BE 

Rabin Vincent (6):
  dump: create writable files
  dump: extract out note helper
  dump: extract out get note size function
  dump: fix up memory mapping dependencies / stub
  target-arm: add dump-guest-memory support
  dump: fix memory region handling

 Makefile.target  |3 +-
 configure|2 +-
 dump.c   |   88 --
 include/exec/memory.h|7 ++
 include/sysemu/dump.h|6 ++
 memory.c |   12 +++
 memory_mapping-stub.c|5 --
 memory_mapping.c |6 +-
 target-arm/Makefile.objs |2 +-
 target-arm/arch_dump.c   |   61 +
 target-i386/arch_dump.c  |  222 +++---
 11 files changed, 223 insertions(+), 191 deletions(-)
 create mode 100644 target-arm/arch_dump.c

-- 
1.7.10.4




[Qemu-devel] [PATCHv2 1/6] dump: create writable files

2013-03-24 Thread Rabin Vincent
The files dump-guest-memory are created as read-only even for the owner.
This non-standard behaviour makes it annoying to deal with the dump
files (eg. rm -f is needed to delete them or saving a new dump by
overwriting the previous one is not possible).  Change the code to
generate files with write permissions set.  If someone requires
read-only files to be created, they can achieve it by setting umask.

Signed-off-by: Rabin Vincent ra...@rab.in
---
 dump.c |3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/dump.c b/dump.c
index a25f509..8dd86b4 100644
--- a/dump.c
+++ b/dump.c
@@ -841,7 +841,8 @@ void qmp_dump_guest_memory(bool paging, const char *file, 
bool has_begin,
 #endif
 
 if  (strstart(file, file:, p)) {
-fd = qemu_open(p, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, S_IRUSR);
+fd = qemu_open(p, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
+   S_IRUSR | S_IWUSR);
 if (fd  0) {
 error_set(errp, QERR_OPEN_FILE_FAILED, p);
 return;
-- 
1.7.10.4




[Qemu-devel] [PATCHv2 3/6] dump: extract out get note size function

2013-03-24 Thread Rabin Vincent
Extract out the ELF note size function from i386 so we can use it from
other targets.

Signed-off-by: Rabin Vincent ra...@rab.in
---
 dump.c  |   15 +++
 include/sysemu/dump.h   |2 ++
 target-i386/arch_dump.c |   14 ++
 3 files changed, 19 insertions(+), 12 deletions(-)

diff --git a/dump.c b/dump.c
index c5e009a..4b7d76c 100644
--- a/dump.c
+++ b/dump.c
@@ -465,6 +465,21 @@ static hwaddr get_offset(hwaddr phys_addr,
 return -1;
 }
 
+size_t dump_get_note_size(int class, const char *name, size_t descsz)
+{
+int name_size = strlen(name) + 1;
+int note_head_size;
+
+if (class == ELFCLASS32) {
+note_head_size = sizeof(Elf32_Nhdr);
+} else {
+note_head_size = sizeof(Elf64_Nhdr);
+}
+
+return ((note_head_size + 3) / 4 + (name_size + 3) / 4
++ (descsz + 3) / 4) * 4;
+}
+
 int dump_write_elf_note(int class, const char *name, uint32_t type,
 void *desc, size_t descsz,
 write_core_dump_function f, void *opaque)
diff --git a/include/sysemu/dump.h b/include/sysemu/dump.h
index b07816a..a06b149 100644
--- a/include/sysemu/dump.h
+++ b/include/sysemu/dump.h
@@ -36,4 +36,6 @@ int dump_write_elf_note(int class, const char *name, uint32_t 
type, void *desc,
 size_t descsz, write_core_dump_function f,
 void *opaque);
 
+size_t dump_get_note_size(int class, const char *name, size_t descsz);
+
 #endif
diff --git a/target-i386/arch_dump.c b/target-i386/arch_dump.c
index eea7f7f..49fa024 100644
--- a/target-i386/arch_dump.c
+++ b/target-i386/arch_dump.c
@@ -307,18 +307,10 @@ int cpu_get_dump_info(ArchDumpInfo *info)
 
 ssize_t cpu_get_note_size(int class, int machine, int nr_cpus)
 {
-int name_size = 5; /* CORE or QEMU */
 size_t elf_note_size = 0;
 size_t qemu_note_size = 0;
 int elf_desc_size = 0;
 int qemu_desc_size = 0;
-int note_head_size;
-
-if (class == ELFCLASS32) {
-note_head_size = sizeof(Elf32_Nhdr);
-} else {
-note_head_size = sizeof(Elf64_Nhdr);
-}
 
 if (machine == EM_386) {
 elf_desc_size = sizeof(x86_elf_prstatus);
@@ -330,10 +322,8 @@ ssize_t cpu_get_note_size(int class, int machine, int 
nr_cpus)
 #endif
 qemu_desc_size = sizeof(QEMUCPUState);
 
-elf_note_size = ((note_head_size + 3) / 4 + (name_size + 3) / 4 +
- (elf_desc_size + 3) / 4) * 4;
-qemu_note_size = ((note_head_size + 3) / 4 + (name_size + 3) / 4 +
-  (qemu_desc_size + 3) / 4) * 4;
+elf_note_size = dump_get_note_size(class, CORE, elf_desc_size);
+qemu_note_size = dump_get_note_size(class, QEMU, qemu_desc_size);
 
 return (elf_note_size + qemu_note_size) * nr_cpus;
 }
-- 
1.7.10.4




[Qemu-devel] [PATCHv2 2/6] dump: extract out note helper

2013-03-24 Thread Rabin Vincent
Make a common helper function out of the x86 code to add ELF notes.

Signed-off-by: Rabin Vincent ra...@rab.in
---
 dump.c  |   51 
 include/sysemu/dump.h   |4 +
 target-i386/arch_dump.c |  208 +++
 3 files changed, 104 insertions(+), 159 deletions(-)

diff --git a/dump.c b/dump.c
index 8dd86b4..c5e009a 100644
--- a/dump.c
+++ b/dump.c
@@ -465,6 +465,57 @@ static hwaddr get_offset(hwaddr phys_addr,
 return -1;
 }
 
+int dump_write_elf_note(int class, const char *name, uint32_t type,
+void *desc, size_t descsz,
+write_core_dump_function f, void *opaque)
+{
+DumpState *s = opaque;
+int endian = s-dump_info.d_endian;
+Elf64_Nhdr *note64;
+Elf32_Nhdr *note32;
+void *note;
+char *buf;
+size_t note_size, name_size, note_head_size;
+int ret;
+
+name_size = strlen(name) + 1;
+
+if (class == ELFCLASS32) {
+note_head_size = sizeof(Elf32_Nhdr);
+} else {
+note_head_size = sizeof(Elf64_Nhdr);
+}
+note_size = ((note_head_size + 3) / 4 + (name_size + 3) / 4 +
+(descsz + 3) / 4) * 4;
+note = g_malloc(note_size);
+
+memset(note, 0, note_size);
+if (class == ELFCLASS32) {
+note32 = note;
+note32-n_namesz = cpu_convert_to_target32(name_size, endian);
+note32-n_descsz = cpu_convert_to_target32(descsz, endian);
+note32-n_type = cpu_convert_to_target32(type, endian);
+} else {
+note64 = note;
+note64-n_namesz = cpu_convert_to_target64(name_size, endian);
+note64-n_descsz = cpu_convert_to_target64(descsz, endian);
+note64-n_type = cpu_convert_to_target64(type, endian);
+}
+buf = note;
+buf += ((note_head_size + 3) / 4) * 4;
+memcpy(buf, name, name_size);
+buf += ((name_size + 3) / 4) * 4;
+memcpy(buf, desc, descsz);
+
+ret = f(note, note_size, opaque);
+g_free(note);
+if (ret  0) {
+return -1;
+}
+
+return 0;
+}
+
 static int write_elf_loads(DumpState *s)
 {
 hwaddr offset;
diff --git a/include/sysemu/dump.h b/include/sysemu/dump.h
index e25b7cf..b07816a 100644
--- a/include/sysemu/dump.h
+++ b/include/sysemu/dump.h
@@ -32,4 +32,8 @@ int cpu_write_elf32_qemunote(write_core_dump_function f, 
CPUArchState *env,
 int cpu_get_dump_info(ArchDumpInfo *info);
 ssize_t cpu_get_note_size(int class, int machine, int nr_cpus);
 
+int dump_write_elf_note(int class, const char *name, uint32_t type, void *desc,
+size_t descsz, write_core_dump_function f,
+void *opaque);
+
 #endif
diff --git a/target-i386/arch_dump.c b/target-i386/arch_dump.c
index 2cd2f7f..eea7f7f 100644
--- a/target-i386/arch_dump.c
+++ b/target-i386/arch_dump.c
@@ -38,66 +38,43 @@ static int x86_64_write_elf64_note(write_core_dump_function 
f,
CPUArchState *env, int id,
void *opaque)
 {
-x86_64_user_regs_struct regs;
-Elf64_Nhdr *note;
-char *buf;
-int descsz, note_size, name_size = 5;
-const char *name = CORE;
-int ret;
-
-regs.r15 = env-regs[15];
-regs.r14 = env-regs[14];
-regs.r13 = env-regs[13];
-regs.r12 = env-regs[12];
-regs.r11 = env-regs[11];
-regs.r10 = env-regs[10];
-regs.r9  = env-regs[9];
-regs.r8  = env-regs[8];
-regs.rbp = env-regs[R_EBP];
-regs.rsp = env-regs[R_ESP];
-regs.rdi = env-regs[R_EDI];
-regs.rsi = env-regs[R_ESI];
-regs.rdx = env-regs[R_EDX];
-regs.rcx = env-regs[R_ECX];
-regs.rbx = env-regs[R_EBX];
-regs.rax = env-regs[R_EAX];
-regs.rip = env-eip;
-regs.eflags = env-eflags;
-
-regs.orig_rax = 0; /* FIXME */
-regs.cs = env-segs[R_CS].selector;
-regs.ss = env-segs[R_SS].selector;
-regs.fs_base = env-segs[R_FS].base;
-regs.gs_base = env-segs[R_GS].base;
-regs.ds = env-segs[R_DS].selector;
-regs.es = env-segs[R_ES].selector;
-regs.fs = env-segs[R_FS].selector;
-regs.gs = env-segs[R_GS].selector;
-
-descsz = sizeof(x86_64_elf_prstatus);
-note_size = ((sizeof(Elf64_Nhdr) + 3) / 4 + (name_size + 3) / 4 +
-(descsz + 3) / 4) * 4;
-note = g_malloc(note_size);
-
-memset(note, 0, note_size);
-note-n_namesz = cpu_to_le32(name_size);
-note-n_descsz = cpu_to_le32(descsz);
-note-n_type = cpu_to_le32(NT_PRSTATUS);
-buf = (char *)note;
-buf += ((sizeof(Elf64_Nhdr) + 3) / 4) * 4;
-memcpy(buf, name, name_size);
-buf += ((name_size + 3) / 4) * 4;
-memcpy(buf + 32, id, 4); /* pr_pid */
-buf += descsz - sizeof(x86_64_user_regs_struct)-sizeof(target_ulong);
-memcpy(buf, regs, sizeof(x86_64_user_regs_struct));
-
-ret = f(note, note_size, opaque);
-g_free(note);
-if (ret  0) {
-return -1;
-}
-
-return 0;
+x86_64_elf_prstatus prstatus;
+
+memset(prstatus, 0, sizeof(prstatus

[Qemu-devel] [PATCHv2 4/6] dump: fix up memory mapping dependencies / stub

2013-03-24 Thread Rabin Vincent
dump.c won't build without the functions from memory_mapping.c (and
memory_mapping-stub.c does not help there), so build memory_mapping.c
when CONFIG_HAVE_CORE_DUMP is set.

  dump.c:84: undefined reference to `memory_mapping_list_free'
  dump.c:819: undefined reference to `memory_mapping_list_init'
  dump.c:827: undefined reference to `memory_mapping_filter'

Allow memory_mapping-stub.c to instead be used for targets which do not
set CONFIG_HAVE_GET_MEMORY_MAPPING.

Signed-off-by: Rabin Vincent ra...@rab.in
---
 Makefile.target   |3 +--
 memory_mapping-stub.c |5 -
 2 files changed, 1 insertion(+), 7 deletions(-)

diff --git a/Makefile.target b/Makefile.target
index 2bd6d14..629f48a 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -115,8 +115,7 @@ obj-$(CONFIG_FDT) += device_tree.o
 obj-$(CONFIG_KVM) += kvm-all.o
 obj-$(CONFIG_NO_KVM) += kvm-stub.o
 obj-y += memory.o savevm.o cputlb.o
-obj-$(CONFIG_HAVE_GET_MEMORY_MAPPING) += memory_mapping.o
-obj-$(CONFIG_HAVE_CORE_DUMP) += dump.o
+obj-$(CONFIG_HAVE_CORE_DUMP) += dump.o memory_mapping.o
 obj-$(CONFIG_NO_GET_MEMORY_MAPPING) += memory_mapping-stub.o
 obj-$(CONFIG_NO_CORE_DUMP) += dump-stub.o
 LIBS+=-lz
diff --git a/memory_mapping-stub.c b/memory_mapping-stub.c
index 24d5d67..6dd9e36 100644
--- a/memory_mapping-stub.c
+++ b/memory_mapping-stub.c
@@ -15,11 +15,6 @@
 #include exec/cpu-all.h
 #include sysemu/memory_mapping.h
 
-int qemu_get_guest_memory_mapping(MemoryMappingList *list)
-{
-return -2;
-}
-
 int cpu_get_memory_mapping(MemoryMappingList *list,

  CPUArchState *env)
 {
-- 
1.7.10.4




[Qemu-devel] [PATCHv2 6/6] dump: fix memory region handling

2013-03-24 Thread Rabin Vincent
RAMBlock.offset does not provide the physical address of the memory
region.  This is available in the MemoryRegion's address.  The wrong
usage leads to incorrect physical addreses in the ELF.  Fix it.

Signed-off-by: Rabin Vincent ra...@rab.in
---
 dump.c|   19 +++
 include/exec/memory.h |7 +++
 memory.c  |   12 
 memory_mapping.c  |6 --
 4 files changed, 34 insertions(+), 10 deletions(-)

diff --git a/dump.c b/dump.c
index 4b7d76c..4b0353a 100644
--- a/dump.c
+++ b/dump.c
@@ -16,6 +16,7 @@
 #include cpu.h
 #include exec/cpu-all.h
 #include exec/hwaddr.h
+#include exec/memory.h
 #include monitor/monitor.h
 #include sysemu/kvm.h
 #include sysemu/dump.h
@@ -432,26 +433,28 @@ static hwaddr get_offset(hwaddr phys_addr,
 }
 
 QTAILQ_FOREACH(block, ram_list.blocks, next) {
+hwaddr baddr = memory_region_get_addr(block-mr);
+
 if (s-has_filter) {
-if (block-offset = s-begin + s-length ||
-block-offset + block-length = s-begin) {
+if (baddr = s-begin + s-length ||
+baddr + block-length = s-begin) {
 /* This block is out of the range */
 continue;
 }
 
-if (s-begin = block-offset) {
-start = block-offset;
+if (s-begin = baddr) {
+start = baddr;
 } else {
 start = s-begin;
 }
 
-size_in_block = block-length - (start - block-offset);
-if (s-begin + s-length  block-offset + block-length) {
-size_in_block -= block-offset + block-length -
+size_in_block = block-length - (start - baddr);
+if (s-begin + s-length  baddr + block-length) {
+size_in_block -= baddr + block-length -
  (s-begin + s-length);
 }
 } else {
-start = block-offset;
+start = baddr;
 size_in_block = block-length;
 }
 
diff --git a/include/exec/memory.h b/include/exec/memory.h
index 2322732..9227190 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -665,6 +665,13 @@ void memory_region_add_subregion_overlap(MemoryRegion *mr,
  unsigned priority);
 
 /**
+ * memory_region_get_addr: Get the address of a memory region
+ *
+ * @mr: the memory region
+ */
+hwaddr memory_region_get_addr(MemoryRegion *mr);
+
+/**
  * memory_region_get_ram_addr: Get the ram address associated with a memory
  * region
  *
diff --git a/memory.c b/memory.c
index 92a2196..f90fd19 100644
--- a/memory.c
+++ b/memory.c
@@ -1427,6 +1427,18 @@ void memory_region_set_alias_offset(MemoryRegion *mr, 
hwaddr offset)
 memory_region_transaction_commit();
 }
 
+hwaddr memory_region_get_addr(MemoryRegion *mr)
+{
+hwaddr addr = 0;
+
+while (mr) {
+   addr += mr-addr;
+   mr = mr-parent;
+}
+
+return addr;
+}
+
 ram_addr_t memory_region_get_ram_addr(MemoryRegion *mr)
 {
 return mr-ram_addr;
diff --git a/memory_mapping.c b/memory_mapping.c
index ff45b3a..cf0751c 100644
--- a/memory_mapping.c
+++ b/memory_mapping.c
@@ -13,6 +13,7 @@
 
 #include cpu.h
 #include exec/cpu-all.h
+#include exec/memory.h
 #include sysemu/memory_mapping.h
 
 static void memory_mapping_list_add_mapping_sorted(MemoryMappingList *list,
@@ -201,7 +202,7 @@ int qemu_get_guest_memory_mapping(MemoryMappingList *list)
  * address.
  */
 QTAILQ_FOREACH(block, ram_list.blocks, next) {
-offset = block-offset;
+offset = memory_region_get_addr(block-mr);
 length = block-length;
 create_new_memory_mapping(list, offset, offset, length);
 }
@@ -214,7 +215,8 @@ void qemu_get_guest_simple_memory_mapping(MemoryMappingList 
*list)
 RAMBlock *block;
 
 QTAILQ_FOREACH(block, ram_list.blocks, next) {
-create_new_memory_mapping(list, block-offset, 0, block-length);
+create_new_memory_mapping(list, memory_region_get_addr(block-mr),
+  0, block-length);
 }
 }
 
-- 
1.7.10.4




[Qemu-devel] [PATCHv2 5/6] target-arm: add dump-guest-memory support

2013-03-24 Thread Rabin Vincent
Enable support for the dump-guest-memory monitor command for ARM.

Cc: Peter Maydell peter.mayd...@linaro.org
Signed-off-by: Rabin Vincent ra...@rab.in
---
 configure|2 +-
 target-arm/Makefile.objs |2 +-
 target-arm/arch_dump.c   |   61 ++
 3 files changed, 63 insertions(+), 2 deletions(-)
 create mode 100644 target-arm/arch_dump.c

diff --git a/configure b/configure
index 46a7594..f35786d 100755
--- a/configure
+++ b/configure
@@ -4184,7 +4184,7 @@ if test $target_softmmu = yes ; then
   echo CONFIG_SOFTMMU=y  $config_target_mak
   echo LIBS+=$libs_softmmu $target_libs_softmmu  $config_target_mak
   case $target_arch2 in
-i386|x86_64)
+arm|i386|x86_64)
   echo CONFIG_HAVE_CORE_DUMP=y  $config_target_mak
   esac
 fi
diff --git a/target-arm/Makefile.objs b/target-arm/Makefile.objs
index d89b57c..93baa12 100644
--- a/target-arm/Makefile.objs
+++ b/target-arm/Makefile.objs
@@ -1,5 +1,5 @@
 obj-y += arm-semi.o
-obj-$(CONFIG_SOFTMMU) += machine.o
+obj-$(CONFIG_SOFTMMU) += machine.o arch_dump.o
 obj-$(CONFIG_KVM) += kvm.o
 obj-y += translate.o op_helper.o helper.o cpu.o
 obj-y += neon_helper.o iwmmxt_helper.o
diff --git a/target-arm/arch_dump.c b/target-arm/arch_dump.c
new file mode 100644
index 000..e568ffb
--- /dev/null
+++ b/target-arm/arch_dump.c
@@ -0,0 +1,61 @@
+#include cpu.h
+#include sysemu/dump.h
+#include elf.h
+
+typedef struct {
+char pad1[24];
+uint32_t pid;
+char pad2[44];
+uint32_t regs[18];
+char pad3[4];
+} arm_elf_prstatus;
+
+int cpu_write_elf64_note(write_core_dump_function f, CPUArchState *env,
+ int cpuid, void *opaque)
+{
+return -1;
+}
+
+int cpu_write_elf32_note(write_core_dump_function f, CPUArchState *env,
+ int cpuid, void *opaque)
+{
+arm_elf_prstatus prstatus = {.pid = cpuid};
+
+memcpy((prstatus.regs), env-regs, sizeof(env-regs));
+prstatus.regs[16] = cpsr_read(env);
+
+return dump_write_elf_note(ELFCLASS32, CORE, NT_PRSTATUS,
+   prstatus, sizeof(prstatus),
+   f, opaque);
+}
+
+int cpu_write_elf64_qemunote(write_core_dump_function f, CPUArchState *env,
+ void *opaque)
+{
+return -1;
+}
+
+int cpu_write_elf32_qemunote(write_core_dump_function f, CPUArchState *env,
+ void *opaque)
+{
+return 0;
+}
+
+int cpu_get_dump_info(ArchDumpInfo *info)
+{
+info-d_machine = EM_ARM;
+#ifdef TARGET_WORDS_BIGENDIAN
+info-d_endian = ELFDATA2MSB;
+#else
+info-d_endian = ELFDATA2LSB;
+#endif
+info-d_class = ELFCLASS32;
+
+return 0;
+}
+
+ssize_t cpu_get_note_size(int class, int machine, int nr_cpus)
+{
+return nr_cpus * dump_get_note_size(ELFCLASS32, CORE,
+sizeof(arm_elf_prstatus));
+}
-- 
1.7.10.4




Re: [Qemu-devel] [PATCHv2 5/6] target-arm: add dump-guest-memory support

2013-03-24 Thread Rabin Vincent
2013/3/24 Peter Maydell peter.mayd...@linaro.org:
 On 24 March 2013 17:27, Rabin Vincent ra...@rab.in wrote:
 --- /dev/null
 +++ b/target-arm/arch_dump.c
 @@ -0,0 +1,61 @@
 +#include cpu.h
 +#include sysemu/dump.h
 +#include elf.h
 +
 +typedef struct {
 +char pad1[24];
 +uint32_t pid;
 +char pad2[44];
 +uint32_t regs[18];
 +char pad3[4];
 +} arm_elf_prstatus;

 Can you point me at the spec this struct corresponds to?

This is elf_prstatus from the Linux kernel's
include/uapi/linux/elfcore.h, with the regset begin ARM regs in this
case.

I don't know if there's a spec.  It doesn't sound like it from the
comments in the kernel file: This is mostly like the SVR4 structure,
but more Linuxy, with things that Linux does not support and which gdb
doesn't really use excluded.

The x86 implementation in target-i386/arch_dump.c uses the same
elf_prstatus with the x86 regs.


 +
 +int cpu_write_elf64_note(write_core_dump_function f, CPUArchState *env,
 + int cpuid, void *opaque)
 +{
 +return -1;
 +}

 Is there any documentation of the API we're implementing here?

I coudn't find any documentation.  It's only x86 that has the API
implemented.

 (why does it require us to provide 64 bit functions that are
 never used?)

I guess the API was made with x86 in mind.  I will see if the
requirement can be removed with some ifdefs in the dump.c file.

(come to think of it, I guess this ARM code will need to use ELFCLASS64
 when we have physical memory  4GiB (LPAE))

 +int cpu_write_elf32_qemunote(write_core_dump_function f, CPUArchState *env,
 + void *opaque)
 +{
 +return 0;
 +}

 Why is it OK to implement this as a no-op? What could we
 be doing here that we don't do? What are the effects?

This is supposed to be used to add some additional information about the
CPU state in an ELF note in a QEMU-specific structure, like the
QEMUCPUState in target-i386/arm-state.c.  It's only useful to implement
this if someone sees a need to add any such information.


 +
 +int cpu_get_dump_info(ArchDumpInfo *info)
 +{
 +info-d_machine = EM_ARM;
 +#ifdef TARGET_WORDS_BIGENDIAN
 +info-d_endian = ELFDATA2MSB;
 +#else
 +info-d_endian = ELFDATA2LSB;
 +#endif
 +info-d_class = ELFCLASS32;

 Most of this looks like it would be suitable for a default
 implementation that said endian based on TARGET_WORDS_BIGENDIAN,
 machine is ELF_MACHINE, class based on TARGET_LONG_BITS.

I will see if this can be moved into the generic dump.c.



Re: [Qemu-devel] [PATCHv2 6/6] dump: fix memory region handling

2013-03-24 Thread Rabin Vincent
2013/3/24 Peter Maydell peter.mayd...@linaro.org:
 On 24 March 2013 17:27, Rabin Vincent ra...@rab.in wrote:
  /**
 + * memory_region_get_addr: Get the address of a memory region
 + *
 + * @mr: the memory region
 + */
 +hwaddr memory_region_get_addr(MemoryRegion *mr);

 I'm afraid this doesn't make sense. A MemoryRegion by itself has
 no address -- it could be mapped into several places in several
 different address maps or none at all.

OK.  Do you mean that such a function can be used internally to the dump
code where it gets the MemoryRegion only from the RAMBlock.mr or do you
mean the dump code also shouldn't be doing it that way?

If you mean the latter, could you please suggest an alternative way to
handle this?  The problem is that the dump code assumes that
RAMBlock.offset provides the physical address, and this appears to not
be the case.  For example, with a dump generated from vexpress I get
these Program Headers in the dump:

  Type   Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  NOTE   0xf4 0x 0x 0x002a0 0x002a0 0
  LOAD   0x000394 0x 0x 0x800 0x800 0
  LOAD   0x8000394 0x 0x0800 0x400 0x400 0
  LOAD   0xc000394 0x 0x0c00 0x400 0x400 0
  LOAD   0x1394 0x 0x1000 0x200 0x200 0
  LOAD   0x12000394 0x 0x1200 0x80 0x80 0

The physical addresses are completely wrong, and with the patch I get
the right ones:

  Type   Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  NOTE   0xf4 0x 0x 0x002a0 0x002a0 0
  LOAD   0x8000394 0x 0x4000 0x400 0x400 0
  LOAD   0xc000394 0x 0x4400 0x400 0x400 0
  LOAD   0x1394 0x 0x4800 0x200 0x200 0
  LOAD   0x12000394 0x 0x4c00 0x80 0x80 0
  LOAD   0x000394 0x 0x6000 0x800 0x800 0

Thanks.



Re: [Qemu-devel] [PATCH 4/4] target-arm: add minimal dump-guest-memory support

2012-07-01 Thread Rabin Vincent
On Thu, Jun 28, 2012 at 05:46:02PM +0100, Peter Maydell wrote:
 On 20 June 2012 18:28, Rabin Vincent ra...@rab.in wrote:
  Add a minimal dump-guest-memory support for ARM.  The -p option is not
  supported and we don't add any QEMU-specific notes.
 
 So what does this patch give us? This commit message is pretty
 short and I couldn't find a cover message for the patchset...

It makes the dump-guest-memory command work for arm-softmmu.  The
resulting core dump can be analysed with a tool such as the crash
utility.

 
  Signed-off-by: Rabin Vincent ra...@rab.in
  ---
   configure                        |    4 +--
   target-arm/Makefile.objs         |    2 +-
   target-arm/arch_dump.c           |   59 
  ++
   target-arm/arch_memory_mapping.c |   13 +
   4 files changed, 75 insertions(+), 3 deletions(-)
   create mode 100644 target-arm/arch_dump.c
   create mode 100644 target-arm/arch_memory_mapping.c
 
  diff --git a/configure b/configure
  index b68c0ca..a20ad19 100755
  --- a/configure
  +++ b/configure
  @@ -3727,7 +3727,7 @@ case $target_arch2 in
      fi
   esac
   case $target_arch2 in
  -  i386|x86_64)
  +  arm|i386|x86_64)
      echo CONFIG_HAVE_GET_MEMORY_MAPPING=y  $config_target_mak
   esac
   if test $target_arch2 = ppc64 -a $fdt = yes; then
  @@ -3746,7 +3746,7 @@ if test $target_softmmu = yes ; then
      echo subdir-$target: subdir-libcacard  $config_host_mak
    fi
    case $target_arch2 in
  -    i386|x86_64)
  +    arm|i386|x86_64)
        echo CONFIG_HAVE_CORE_DUMP=y  $config_target_mak
    esac
   fi
  diff --git a/target-arm/Makefile.objs b/target-arm/Makefile.objs
  index f447c4f..837b374 100644
  --- a/target-arm/Makefile.objs
  +++ b/target-arm/Makefile.objs
  @@ -1,5 +1,5 @@
   obj-y += arm-semi.o
  -obj-$(CONFIG_SOFTMMU) += machine.o
  +obj-$(CONFIG_SOFTMMU) += machine.o arch_memory_mapping.o arch_dump.o
   obj-y += translate.o op_helper.o helper.o cpu.o
   obj-y += neon_helper.o iwmmxt_helper.o
 
  diff --git a/target-arm/arch_dump.c b/target-arm/arch_dump.c
  new file mode 100644
  index 000..47a7e40
  --- /dev/null
  +++ b/target-arm/arch_dump.c
  @@ -0,0 +1,59 @@
  +#include cpu.h
  +#include cpu-all.h
  +#include dump.h
  +#include elf.h
  +
  +typedef struct {
  +    char pad1[24];
  +    uint32_t pid;
  +    char pad2[44];
  +    uint32_t regs[18];
  +    char pad3[4];
  +} arm_elf_prstatus;
 
 I'm guessing this is following some specification's structure layout;
 what specification?

struct elf_prstatus from the Linux kernel's include/linux/elfcore.h.

 
  +
  +int cpu_write_elf64_note(write_core_dump_function f, CPUArchState *env,
  +                         int cpuid, void *opaque)
 
 Should these APIs really be taking a CPUArchState* rather rather than
 an ARMCPU* ? (Andreas?)

No idea.  Cc'ing Wen, who added the APIs.

 
  +{
  +    return -1;
  +}
  +
  +int cpu_write_elf32_note(write_core_dump_function f, CPUArchState *env,
  +                         int cpuid, void *opaque)
  +{
  +    arm_elf_prstatus prstatus;
  +
  +    memset(prstatus, 0, sizeof(prstatus));
  +    memcpy((prstatus.regs), env-regs, sizeof(env-regs));
 
 This looks a bit odd -- env-regs[] is a 16 word array but
 prstatus.regs is 18 words. What are the last two words for?

CPSR and orig_r0.  orig_r0 is not useful, but I think we can save the
CPSR in there.

 
  +    prstatus.pid = cpuid;
  +
  +    return dump_write_elf_note(ELFCLASS32, CORE, NT_PRSTATUS,
  +                               prstatus, sizeof(prstatus),
  +                               f, opaque);
  +}
  +
  +int cpu_write_elf64_qemunote(write_core_dump_function f, CPUArchState *env,
  +                             void *opaque)
  +{
  +    return -1;
  +}
  +
  +int cpu_write_elf32_qemunote(write_core_dump_function f, CPUArchState *env,
  +                             void *opaque)
  +{
  +    return 0;
  +}
  +
  +int cpu_get_dump_info(ArchDumpInfo *info)
  +{
  +    info-d_machine = EM_ARM;
  +    info-d_endian = ELFDATA2LSB;
 
 ...even for big endian ARM?

I'll use TARGET_WORDS_BIGENDIAN to check.

Though it appears we don't have a armbe-softmmu?

 
  +    info-d_class = ELFCLASS32;
  +
  +    return 0;
  +}
  +
  +ssize_t cpu_get_note_size(int class, int machine, int nr_cpus)
  +{
  +    return nr_cpus * dump_get_note_size(ELFCLASS32, CORE,
  +                                        sizeof(arm_elf_prstatus));
  +}
  diff --git a/target-arm/arch_memory_mapping.c 
  b/target-arm/arch_memory_mapping.c
  new file mode 100644
  index 000..eeaaf09
  --- /dev/null
  +++ b/target-arm/arch_memory_mapping.c
  @@ -0,0 +1,13 @@
  +#include cpu.h
  +#include cpu-all.h
  +#include memory_mapping.h
  +
  +bool cpu_paging_enabled(CPUArchState *env)
  +{
  +    return 0;
  +}
  +
  +int cpu_get_memory_mapping(MemoryMappingList *list, CPUArchState *env)
  +{
  +    return -1;
  +}
 
 Why do we need these null implementations and why do they
 work better than the default ones in memory_mapping

[Qemu-devel] [PATCH 1/4] dump: create writable files

2012-06-20 Thread Rabin Vincent
Make dump-guest-memory not create read-only files, so that it can
overwrite a file created by a previous invocation without having it to
be removed externally.

Signed-off-by: Rabin Vincent ra...@rab.in
---
 dump.c |3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/dump.c b/dump.c
index 2bf8d8d..5c5cb4d 100644
--- a/dump.c
+++ b/dump.c
@@ -845,7 +845,8 @@ void qmp_dump_guest_memory(bool paging, const char *file, 
bool has_begin,
 #endif
 
 if  (strstart(file, file:, p)) {
-fd = qemu_open(p, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, S_IRUSR);
+fd = qemu_open(p, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
+   S_IRUSR | S_IWUSR);
 if (fd  0) {
 error_set(errp, QERR_OPEN_FILE_FAILED, p);
 return;
-- 
1.7.9.5




[Qemu-devel] [PATCH 2/4] dump: extract out note helper

2012-06-20 Thread Rabin Vincent
Make a common helper function to add ELF notes.

Signed-off-by: Rabin Vincent ra...@rab.in
---
 dump.c  |   49 +++
 dump.h  |4 +
 target-i386/arch_dump.c |  206 +++
 3 files changed, 100 insertions(+), 159 deletions(-)

diff --git a/dump.c b/dump.c
index 5c5cb4d..be96c6c 100644
--- a/dump.c
+++ b/dump.c
@@ -468,6 +468,55 @@ static target_phys_addr_t get_offset(target_phys_addr_t 
phys_addr,
 return -1;
 }
 
+int dump_write_elf_note(int class, const char *name, uint32_t type,
+void *desc, size_t descsz,
+write_core_dump_function f, void *opaque)
+{
+Elf64_Nhdr *note64;
+Elf32_Nhdr *note32;
+void *note;
+char *buf;
+size_t note_size, name_size, note_head_size;
+int ret;
+
+name_size = strlen(name) + 1;
+
+if (class == ELFCLASS32) {
+note_head_size = sizeof(Elf32_Nhdr);
+} else {
+note_head_size = sizeof(Elf64_Nhdr);
+}
+note_size = ((note_head_size + 3) / 4 + (name_size + 3) / 4 +
+(descsz + 3) / 4) * 4;
+note = g_malloc(note_size);
+
+memset(note, 0, note_size);
+if (class == ELFCLASS32) {
+note32 = note;
+note32-n_namesz = cpu_to_le32(name_size);
+note32-n_descsz = cpu_to_le32(descsz);
+note32-n_type = cpu_to_le32(type);
+} else {
+note64 = note;
+note64-n_namesz = cpu_to_le32(name_size);
+note64-n_descsz = cpu_to_le32(descsz);
+note64-n_type = cpu_to_le32(type);
+}
+buf = note;
+buf += ((note_head_size + 3) / 4) * 4;
+memcpy(buf, name, name_size);
+buf += ((name_size + 3) / 4) * 4;
+memcpy(buf, desc, descsz);
+
+ret = f(note, note_size, opaque);
+g_free(note);
+if (ret  0) {
+return -1;
+}
+
+return 0;
+}
+
 static int write_elf_loads(DumpState *s)
 {
 target_phys_addr_t offset;
diff --git a/dump.h b/dump.h
index e25b7cf..b07816a 100644
--- a/dump.h
+++ b/dump.h
@@ -32,4 +32,8 @@ int cpu_write_elf32_qemunote(write_core_dump_function f, 
CPUArchState *env,
 int cpu_get_dump_info(ArchDumpInfo *info);
 ssize_t cpu_get_note_size(int class, int machine, int nr_cpus);
 
+int dump_write_elf_note(int class, const char *name, uint32_t type, void *desc,
+size_t descsz, write_core_dump_function f,
+void *opaque);
+
 #endif
diff --git a/target-i386/arch_dump.c b/target-i386/arch_dump.c
index 4240278..dbc94bc 100644
--- a/target-i386/arch_dump.c
+++ b/target-i386/arch_dump.c
@@ -38,66 +38,41 @@ static int x86_64_write_elf64_note(write_core_dump_function 
f,
CPUArchState *env, int id,
void *opaque)
 {
-x86_64_user_regs_struct regs;
-Elf64_Nhdr *note;
-char *buf;
-int descsz, note_size, name_size = 5;
-const char *name = CORE;
-int ret;
-
-regs.r15 = env-regs[15];
-regs.r14 = env-regs[14];
-regs.r13 = env-regs[13];
-regs.r12 = env-regs[12];
-regs.r11 = env-regs[11];
-regs.r10 = env-regs[10];
-regs.r9  = env-regs[9];
-regs.r8  = env-regs[8];
-regs.rbp = env-regs[R_EBP];
-regs.rsp = env-regs[R_ESP];
-regs.rdi = env-regs[R_EDI];
-regs.rsi = env-regs[R_ESI];
-regs.rdx = env-regs[R_EDX];
-regs.rcx = env-regs[R_ECX];
-regs.rbx = env-regs[R_EBX];
-regs.rax = env-regs[R_EAX];
-regs.rip = env-eip;
-regs.eflags = env-eflags;
-
-regs.orig_rax = 0; /* FIXME */
-regs.cs = env-segs[R_CS].selector;
-regs.ss = env-segs[R_SS].selector;
-regs.fs_base = env-segs[R_FS].base;
-regs.gs_base = env-segs[R_GS].base;
-regs.ds = env-segs[R_DS].selector;
-regs.es = env-segs[R_ES].selector;
-regs.fs = env-segs[R_FS].selector;
-regs.gs = env-segs[R_GS].selector;
-
-descsz = sizeof(x86_64_elf_prstatus);
-note_size = ((sizeof(Elf64_Nhdr) + 3) / 4 + (name_size + 3) / 4 +
-(descsz + 3) / 4) * 4;
-note = g_malloc(note_size);
-
-memset(note, 0, note_size);
-note-n_namesz = cpu_to_le32(name_size);
-note-n_descsz = cpu_to_le32(descsz);
-note-n_type = cpu_to_le32(NT_PRSTATUS);
-buf = (char *)note;
-buf += ((sizeof(Elf64_Nhdr) + 3) / 4) * 4;
-memcpy(buf, name, name_size);
-buf += ((name_size + 3) / 4) * 4;
-memcpy(buf + 32, id, 4); /* pr_pid */
-buf += descsz - sizeof(x86_64_user_regs_struct)-sizeof(target_ulong);
-memcpy(buf, regs, sizeof(x86_64_user_regs_struct));
-
-ret = f(note, note_size, opaque);
-g_free(note);
-if (ret  0) {
-return -1;
-}
-
-return 0;
+x86_64_elf_prstatus prstatus;
+
+prstatus.pid = id;
+prstatus.regs.r15 = env-regs[15];
+prstatus.regs.r14 = env-regs[14];
+prstatus.regs.r13 = env-regs[13];
+prstatus.regs.r12 = env-regs[12];
+prstatus.regs.r11 = env-regs[11];
+prstatus.regs.r10 = env-regs[10

[Qemu-devel] [PATCH 4/4] target-arm: add minimal dump-guest-memory support

2012-06-20 Thread Rabin Vincent
Add a minimal dump-guest-memory support for ARM.  The -p option is not
supported and we don't add any QEMU-specific notes.

Signed-off-by: Rabin Vincent ra...@rab.in
---
 configure|4 +--
 target-arm/Makefile.objs |2 +-
 target-arm/arch_dump.c   |   59 ++
 target-arm/arch_memory_mapping.c |   13 +
 4 files changed, 75 insertions(+), 3 deletions(-)
 create mode 100644 target-arm/arch_dump.c
 create mode 100644 target-arm/arch_memory_mapping.c

diff --git a/configure b/configure
index b68c0ca..a20ad19 100755
--- a/configure
+++ b/configure
@@ -3727,7 +3727,7 @@ case $target_arch2 in
 fi
 esac
 case $target_arch2 in
-  i386|x86_64)
+  arm|i386|x86_64)
 echo CONFIG_HAVE_GET_MEMORY_MAPPING=y  $config_target_mak
 esac
 if test $target_arch2 = ppc64 -a $fdt = yes; then
@@ -3746,7 +3746,7 @@ if test $target_softmmu = yes ; then
 echo subdir-$target: subdir-libcacard  $config_host_mak
   fi
   case $target_arch2 in
-i386|x86_64)
+arm|i386|x86_64)
   echo CONFIG_HAVE_CORE_DUMP=y  $config_target_mak
   esac
 fi
diff --git a/target-arm/Makefile.objs b/target-arm/Makefile.objs
index f447c4f..837b374 100644
--- a/target-arm/Makefile.objs
+++ b/target-arm/Makefile.objs
@@ -1,5 +1,5 @@
 obj-y += arm-semi.o
-obj-$(CONFIG_SOFTMMU) += machine.o
+obj-$(CONFIG_SOFTMMU) += machine.o arch_memory_mapping.o arch_dump.o
 obj-y += translate.o op_helper.o helper.o cpu.o
 obj-y += neon_helper.o iwmmxt_helper.o
 
diff --git a/target-arm/arch_dump.c b/target-arm/arch_dump.c
new file mode 100644
index 000..47a7e40
--- /dev/null
+++ b/target-arm/arch_dump.c
@@ -0,0 +1,59 @@
+#include cpu.h
+#include cpu-all.h
+#include dump.h
+#include elf.h
+
+typedef struct {
+char pad1[24];
+uint32_t pid;
+char pad2[44];
+uint32_t regs[18];
+char pad3[4];
+} arm_elf_prstatus;
+
+int cpu_write_elf64_note(write_core_dump_function f, CPUArchState *env,
+ int cpuid, void *opaque)
+{
+return -1;
+}
+
+int cpu_write_elf32_note(write_core_dump_function f, CPUArchState *env,
+ int cpuid, void *opaque)
+{
+arm_elf_prstatus prstatus;
+
+memset(prstatus, 0, sizeof(prstatus));
+memcpy((prstatus.regs), env-regs, sizeof(env-regs));
+prstatus.pid = cpuid;
+
+return dump_write_elf_note(ELFCLASS32, CORE, NT_PRSTATUS,
+   prstatus, sizeof(prstatus),
+   f, opaque);
+}
+
+int cpu_write_elf64_qemunote(write_core_dump_function f, CPUArchState *env,
+ void *opaque)
+{
+return -1;
+}
+
+int cpu_write_elf32_qemunote(write_core_dump_function f, CPUArchState *env,
+ void *opaque)
+{
+return 0;
+}
+
+int cpu_get_dump_info(ArchDumpInfo *info)
+{
+info-d_machine = EM_ARM;
+info-d_endian = ELFDATA2LSB;
+info-d_class = ELFCLASS32;
+
+return 0;
+}
+
+ssize_t cpu_get_note_size(int class, int machine, int nr_cpus)
+{
+return nr_cpus * dump_get_note_size(ELFCLASS32, CORE,
+sizeof(arm_elf_prstatus));
+}
diff --git a/target-arm/arch_memory_mapping.c b/target-arm/arch_memory_mapping.c
new file mode 100644
index 000..eeaaf09
--- /dev/null
+++ b/target-arm/arch_memory_mapping.c
@@ -0,0 +1,13 @@
+#include cpu.h
+#include cpu-all.h
+#include memory_mapping.h
+
+bool cpu_paging_enabled(CPUArchState *env)
+{
+return 0;
+}
+
+int cpu_get_memory_mapping(MemoryMappingList *list, CPUArchState *env)
+{
+return -1;
+}
-- 
1.7.9.5




[Qemu-devel] [PATCH 3/4] dump: extract out get note size function

2012-06-20 Thread Rabin Vincent
Extract out the ELF note size function from i386 so we can use it from
other targets.

Signed-off-by: Rabin Vincent ra...@rab.in
---
 dump.c  |   15 +++
 dump.h  |2 ++
 target-i386/arch_dump.c |   14 ++
 3 files changed, 19 insertions(+), 12 deletions(-)

diff --git a/dump.c b/dump.c
index be96c6c..d3ca953 100644
--- a/dump.c
+++ b/dump.c
@@ -468,6 +468,21 @@ static target_phys_addr_t get_offset(target_phys_addr_t 
phys_addr,
 return -1;
 }
 
+size_t dump_get_note_size(int class, const char *name, size_t descsz)
+{
+int name_size = strlen(name) + 1;
+int note_head_size;
+
+if (class == ELFCLASS32) {
+note_head_size = sizeof(Elf32_Nhdr);
+} else {
+note_head_size = sizeof(Elf64_Nhdr);
+}
+
+return ((note_head_size + 3) / 4 + (name_size + 3) / 4
++ (descsz + 3) / 4) * 4;
+}
+
 int dump_write_elf_note(int class, const char *name, uint32_t type,
 void *desc, size_t descsz,
 write_core_dump_function f, void *opaque)
diff --git a/dump.h b/dump.h
index b07816a..a06b149 100644
--- a/dump.h
+++ b/dump.h
@@ -36,4 +36,6 @@ int dump_write_elf_note(int class, const char *name, uint32_t 
type, void *desc,
 size_t descsz, write_core_dump_function f,
 void *opaque);
 
+size_t dump_get_note_size(int class, const char *name, size_t descsz);
+
 #endif
diff --git a/target-i386/arch_dump.c b/target-i386/arch_dump.c
index dbc94bc..e2d18a0 100644
--- a/target-i386/arch_dump.c
+++ b/target-i386/arch_dump.c
@@ -305,18 +305,10 @@ int cpu_get_dump_info(ArchDumpInfo *info)
 
 ssize_t cpu_get_note_size(int class, int machine, int nr_cpus)
 {
-int name_size = 5; /* CORE or QEMU */
 size_t elf_note_size = 0;
 size_t qemu_note_size = 0;
 int elf_desc_size = 0;
 int qemu_desc_size = 0;
-int note_head_size;
-
-if (class == ELFCLASS32) {
-note_head_size = sizeof(Elf32_Nhdr);
-} else {
-note_head_size = sizeof(Elf64_Nhdr);
-}
 
 if (machine == EM_386) {
 elf_desc_size = sizeof(x86_elf_prstatus);
@@ -328,10 +320,8 @@ ssize_t cpu_get_note_size(int class, int machine, int 
nr_cpus)
 #endif
 qemu_desc_size = sizeof(QEMUCPUState);
 
-elf_note_size = ((note_head_size + 3) / 4 + (name_size + 3) / 4 +
- (elf_desc_size + 3) / 4) * 4;
-qemu_note_size = ((note_head_size + 3) / 4 + (name_size + 3) / 4 +
-  (qemu_desc_size + 3) / 4) * 4;
+elf_note_size = dump_get_note_size(class, CORE, elf_desc_size);
+qemu_note_size = dump_get_note_size(class, QEMU, qemu_desc_size);
 
 return (elf_note_size + qemu_note_size) * nr_cpus;
 }
-- 
1.7.9.5




[Qemu-devel] [PATCH] arm_gic: handle banked enable bits for per-cpu interrupts

2011-10-28 Thread Rabin Vincent
The first enable set/clear register (which controls the PPIs and SGIs)
is supposed to be banked for each processor.  Currently it is just
handled globally and this prevents recent SMP Linux kernels from
booting, because CPU0 stops receiving localtimer interrupts when CPU1
disables them locally.

To fix this, allow the enable bits to be enabled per-cpu.  For SPIs,
always enable/disable ALL_CPU_MASK.

Cc: Peter Maydell peter.mayd...@linaro.org
Signed-off-by: Rabin Vincent ra...@rab.in
---
 hw/arm_gic.c |   35 ---
 1 files changed, 20 insertions(+), 15 deletions(-)

diff --git a/hw/arm_gic.c b/hw/arm_gic.c
index 8dd8742..f3f3516 100644
--- a/hw/arm_gic.c
+++ b/hw/arm_gic.c
@@ -37,9 +37,8 @@ static const uint8_t gic_id[] =
 
 typedef struct gic_irq_state
 {
-/* ??? The documentation seems to imply the enable bits are global, even
-   for per-cpu interrupts.  This seems strange.  */
-unsigned enabled:1;
+/* The enable bits are only banked for per-cpu interrupts.  */
+unsigned enabled:NCPU;
 unsigned pending:NCPU;
 unsigned active:NCPU;
 unsigned level:NCPU;
@@ -54,9 +53,9 @@ typedef struct gic_irq_state
 #define NUM_CPU(s) 1
 #endif
 
-#define GIC_SET_ENABLED(irq) s-irq_state[irq].enabled = 1
-#define GIC_CLEAR_ENABLED(irq) s-irq_state[irq].enabled = 0
-#define GIC_TEST_ENABLED(irq) s-irq_state[irq].enabled
+#define GIC_SET_ENABLED(irq, cm) s-irq_state[irq].enabled |= (cm)
+#define GIC_CLEAR_ENABLED(irq, cm) s-irq_state[irq].enabled = ~(cm)
+#define GIC_TEST_ENABLED(irq, cm) ((s-irq_state[irq].enabled  (cm)) != 0)
 #define GIC_SET_PENDING(irq, cm) s-irq_state[irq].pending |= (cm)
 #define GIC_CLEAR_PENDING(irq, cm) s-irq_state[irq].pending = ~(cm)
 #define GIC_TEST_PENDING(irq, cm) ((s-irq_state[irq].pending  (cm)) != 0)
@@ -128,7 +127,7 @@ static void gic_update(gic_state *s)
 best_prio = 0x100;
 best_irq = 1023;
 for (irq = 0; irq  GIC_NIRQ; irq++) {
-if (GIC_TEST_ENABLED(irq)  GIC_TEST_PENDING(irq, cm)) {
+if (GIC_TEST_ENABLED(irq, cm)  GIC_TEST_PENDING(irq, cm)) {
 if (GIC_GET_PRIORITY(irq, cpu)  best_prio) {
 best_prio = GIC_GET_PRIORITY(irq, cpu);
 best_irq = irq;
@@ -171,7 +170,7 @@ static void gic_set_irq(void *opaque, int irq, int level)
 
 if (level) {
 GIC_SET_LEVEL(irq, ALL_CPU_MASK);
-if (GIC_TEST_TRIGGER(irq) || GIC_TEST_ENABLED(irq)) {
+if (GIC_TEST_TRIGGER(irq) || GIC_TEST_ENABLED(irq, ALL_CPU_MASK)) {
 DPRINTF(Set %d pending mask %x\n, irq, GIC_TARGET(irq));
 GIC_SET_PENDING(irq, GIC_TARGET(irq));
 }
@@ -221,7 +220,7 @@ static void gic_complete_irq(gic_state * s, int cpu, int 
irq)
 if (irq != 1023) {
 /* Mark level triggered interrupts as pending if they are still
raised.  */
-if (!GIC_TEST_TRIGGER(irq)  GIC_TEST_ENABLED(irq)
+if (!GIC_TEST_TRIGGER(irq)  GIC_TEST_ENABLED(irq, cm)
  GIC_TEST_LEVEL(irq, cm)  (GIC_TARGET(irq)  cm) != 0) {
 DPRINTF(Set %d pending mask %x\n, irq, cm);
 GIC_SET_PENDING(irq, cm);
@@ -280,7 +279,7 @@ static uint32_t gic_dist_readb(void *opaque, 
target_phys_addr_t offset)
 goto bad_reg;
 res = 0;
 for (i = 0; i  8; i++) {
-if (GIC_TEST_ENABLED(irq + i)) {
+if (GIC_TEST_ENABLED(irq + i, cm)) {
 res |= (1  i);
 }
 }
@@ -412,9 +411,12 @@ static void gic_dist_writeb(void *opaque, 
target_phys_addr_t offset,
 for (i = 0; i  8; i++) {
 if (value  (1  i)) {
 int mask = (irq  32) ? (1  cpu) : GIC_TARGET(irq);
-if (!GIC_TEST_ENABLED(irq + i))
+int cm = (irq  32) ? (1  cpu) : ALL_CPU_MASK;
+
+if (!GIC_TEST_ENABLED(irq + i, cm)) {
 DPRINTF(Enabled IRQ %d\n, irq + i);
-GIC_SET_ENABLED(irq + i);
+}
+GIC_SET_ENABLED(irq + i, cm);
 /* If a raised level triggered IRQ enabled then mark
is as pending.  */
 if (GIC_TEST_LEVEL(irq + i, mask)
@@ -433,9 +435,12 @@ static void gic_dist_writeb(void *opaque, 
target_phys_addr_t offset,
   value = 0;
 for (i = 0; i  8; i++) {
 if (value  (1  i)) {
-if (GIC_TEST_ENABLED(irq + i))
+int cm = (irq  32) ? (1  cpu) : ALL_CPU_MASK;
+
+if (GIC_TEST_ENABLED(irq + i, cm)) {
 DPRINTF(Disabled IRQ %d\n, irq + i);
-GIC_CLEAR_ENABLED(irq + i);
+}
+GIC_CLEAR_ENABLED(irq + i, cm);
 }
 }
 } else if (offset  0x280) {
@@ -638,7 +643,7 @@ static void gic_reset(gic_state *s)
 #endif
 }
 for (i = 0; i  16; i++) {
-GIC_SET_ENABLED(i);
+GIC_SET_ENABLED(i, ALL_CPU_MASK

[Qemu-devel] Re: [PATCH 1/2] arm_timer: reload timer when enabled

2010-05-20 Thread Rabin Vincent
On Sun, May 02, 2010 at 03:20:51PM +0530, Rabin Vincent wrote:
 Reload the timer when TimerControl is written, if the timer is to be
 enabled.  Otherwise, if an earlier write to TimerLoad was done while
 periodic mode was not set, s-delta may incorrectly still have the value
 of the maximum limit instead of the value written to TimerLoad.
 
 This problem is evident on versatileap on current linux-next, which
 enables TIMER_CTRL_32BIT before writing to TimerLoad and then enabling
 periodic mode and starting the timer.  This causes the first periodic
 tick to be scheduled to occur after 0x periods, leading to a
 perceived hang while the kernel waits for the first timer tick.
 
 Signed-off-by: Rabin Vincent ra...@rab.in

Could these patches please be applied?  What was then linux-next is now
current Linux mainline, and it doesn't boot without this patch.

Rabin



[Qemu-devel] [PATCH 2/2] arm_timer: fix oneshot mode

2010-05-02 Thread Rabin Vincent
In oneshot mode, the delta needs to come from the TimerLoad register,
not the maximum limit.

Signed-off-by: Rabin Vincent ra...@rab.in
---
 hw/arm_timer.c |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/hw/arm_timer.c b/hw/arm_timer.c
index 5b6947a..9073ffc 100644
--- a/hw/arm_timer.c
+++ b/hw/arm_timer.c
@@ -71,7 +71,7 @@ static void arm_timer_recalibrate(arm_timer_state *s, int 
reload)
 {
 uint32_t limit;
 
-if ((s-control  TIMER_CTRL_PERIODIC) == 0) {
+if ((s-control  (TIMER_CTRL_PERIODIC | TIMER_CTRL_ONESHOT)) == 0) {
 /* Free running.  */
 if (s-control  TIMER_CTRL_32BIT)
 limit = 0x;
-- 
1.7.0.4





[Qemu-devel] [PATCH 1/2] arm_timer: reload timer when enabled

2010-05-02 Thread Rabin Vincent
Reload the timer when TimerControl is written, if the timer is to be
enabled.  Otherwise, if an earlier write to TimerLoad was done while
periodic mode was not set, s-delta may incorrectly still have the value
of the maximum limit instead of the value written to TimerLoad.

This problem is evident on versatileap on current linux-next, which
enables TIMER_CTRL_32BIT before writing to TimerLoad and then enabling
periodic mode and starting the timer.  This causes the first periodic
tick to be scheduled to occur after 0x periods, leading to a
perceived hang while the kernel waits for the first timer tick.

Signed-off-by: Rabin Vincent ra...@rab.in
---
 hw/arm_timer.c |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/hw/arm_timer.c b/hw/arm_timer.c
index 9fef191..5b6947a 100644
--- a/hw/arm_timer.c
+++ b/hw/arm_timer.c
@@ -113,7 +113,7 @@ static void arm_timer_write(void *opaque, 
target_phys_addr_t offset,
 case 1: freq = 4; break;
 case 2: freq = 8; break;
 }
-arm_timer_recalibrate(s, 0);
+arm_timer_recalibrate(s, s-control  TIMER_CTRL_ENABLE);
 ptimer_set_freq(s-timer, freq);
 if (s-control  TIMER_CTRL_ENABLE) {
 /* Restart the timer if still enabled.  */
-- 
1.7.0.4





[Qemu-devel] [PATCH] target-arm: disable PAGE_EXEC for XN pages

2010-03-19 Thread Rabin Vincent
Don't set PAGE_EXEC for XN pages, to avoid a bypass of XN protection
checking if the page is already in the TLB.

Signed-off-by: Rabin Vincent ra...@rab.in
---
 target-arm/helper.c |   10 +++---
 1 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/target-arm/helper.c b/target-arm/helper.c
index 18e22b1..e092b21 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -979,6 +979,7 @@ static int get_phys_addr_v5(CPUState *env, uint32_t 
address, int access_type,
 /* Access permission fault.  */
 goto do_fault;
 }
+*prot |= PAGE_EXEC;
 *phys_ptr = phys_addr;
 return 0;
 do_fault:
@@ -1075,6 +1076,9 @@ static int get_phys_addr_v6(CPUState *env, uint32_t 
address, int access_type,
 /* Access permission fault.  */
 goto do_fault;
 }
+if (!xn) {
+*prot |= PAGE_EXEC;
+}
 *phys_ptr = phys_addr;
 return 0;
 do_fault:
@@ -1137,6 +1141,7 @@ static int get_phys_addr_mpu(CPUState *env, uint32_t 
address, int access_type,
/* Bad permission.  */
return 1;
 }
+*prot |= PAGE_EXEC;
 return 0;
 }
 
@@ -1152,7 +1157,7 @@ static inline int get_phys_addr(CPUState *env, uint32_t 
address,
 if ((env-cp15.c1_sys  1) == 0) {
 /* MMU/MPU disabled.  */
 *phys_ptr = address;
-*prot = PAGE_READ | PAGE_WRITE;
+*prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
 *page_size = TARGET_PAGE_SIZE;
 return 0;
 } else if (arm_feature(env, ARM_FEATURE_MPU)) {
@@ -1183,8 +1188,7 @@ int cpu_arm_handle_mmu_fault (CPUState *env, target_ulong 
address,
 /* Map a single [sub]page.  */
 phys_addr = ~(uint32_t)0x3ff;
 address = ~(uint32_t)0x3ff;
-tlb_set_page (env, address, phys_addr, prot | PAGE_EXEC, mmu_idx,
-  page_size);
+tlb_set_page (env, address, phys_addr, prot, mmu_idx, page_size);
 return 0;
 }
 
-- 
1.7.0





[Qemu-devel] [PATCH 0/3] target-arm: Thumb(-2) exception support

2010-02-14 Thread Rabin Vincent
This series adds Thumb exception support and fixes a couple of instructions
related to it.

With these patches, QEMU can boot a Linux kernel built with Thumb-2.

Rabin Vincent (3):
  target-arm: fix thumb CPS
  target-arm: implement Thumb-2 exception return
  target-arm: support thumb exception handlers

 target-arm/helper.c|5 ++---
 target-arm/translate.c |   15 ---
 2 files changed, 14 insertions(+), 6 deletions(-)





[Qemu-devel] [PATCH 2/3] target-arm: implement Thumb-2 exception return

2010-02-14 Thread Rabin Vincent
Support the subs pc, lr Thumb-2 exception return instruction.

Signed-off-by: Rabin Vincent ra...@rab.in
---
 target-arm/translate.c |   13 +++--
 1 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/target-arm/translate.c b/target-arm/translate.c
index 10a516b..f0667e5 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -8001,8 +8001,17 @@ static int disas_thumb2_insn(CPUState *env, DisasContext 
*s, uint16_t insn_hw1)
 gen_bx(s, tmp);
 break;
 case 5: /* Exception return.  */
-/* Unpredictable in user mode.  */
-goto illegal_op;
+if (IS_USER(s)) {
+goto illegal_op;
+}
+
+tmp = load_reg(s, rn);
+tmp2 = new_tmp();
+tcg_gen_movi_i32(tmp2, insn  0xff);
+gen_helper_sub_cc(tmp, tmp, tmp2);
+gen_exception_return(s, tmp);
+dead_tmp(tmp2);
+break;
 case 6: /* mrs cpsr.  */
 tmp = new_tmp();
 if (IS_M(env)) {
-- 
1.6.6





[Qemu-devel] [PATCH 1/3] target-arm: fix thumb CPS

2010-02-14 Thread Rabin Vincent
The Thumb CPS currently does not work correctly: CPSID touches more bits
than the instruction wants to, and CPSIE does nothing.  Fix it by
passing the correct mask (the affect bits) and value.

Signed-off-by: Rabin Vincent ra...@rab.in
---
 target-arm/translate.c |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/target-arm/translate.c b/target-arm/translate.c
index 786c329..10a516b 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -8898,7 +8898,7 @@ static void disas_thumb_insn(CPUState *env, DisasContext 
*s)
 shift = CPSR_A | CPSR_I | CPSR_F;
 else
 shift = 0;
-gen_set_psr_im(s, shift, 0, ((insn  7)  6)  shift);
+gen_set_psr_im(s, ((insn  7)  6), 0, shift);
 }
 break;
 
-- 
1.6.6





Re: [Qemu-devel] Thumb-2 Support

2010-02-14 Thread Rabin Vincent
On Wed, Sep 23, 2009 at 02:30:01PM +0200, Crooks (Rigante) wrote:
 I was wondering what level of support there is for Thumb-2. (Qemu 0.11 RC2)
 I've compiled two linux-kernels, one with Thumb-2, and one without Thumb-2,
 using the codesourcery compilers. I've then tried to boot these kernels with
 the RealView emulation running an Cortex-A8 CPU.
 The one without Thumb-2 manages to boot, but nothing seem to happen when
 running the one compiled for Thumb-2.

This should work now, if you use the latest QEMU git and apply the three
patches I just sent to the list.  Make sure you boot a uImage, because
when using a zImage QEMU always starts up in ARM mode.

Rabin




Re: [Qemu-devel] Support for new target emulator

2009-10-27 Thread Rabin Vincent
On Fri, Oct 23, 2009 at 12:50:03PM +0200, Boyapati, Anitha wrote:
 We have a proposal to add support for AVR32 target emulation in Qemu.

I've been working on and off on AVR32 target support for a little while
now.  It's still far from being complete or mergeable, but enough of the
architecture has been implemented to boot a minimal Linux kernel in
system emulation and run busybox in linux-user emulation.

I've put up the current source at http://repo.or.cz/w/qemu/avr32.git,
and a small README and some prebuilt kernel and busybox binaries to play
with at http://rab.in/qemu/avr32/.

Current status and a TODO list are below.  Have a look.  I still hope to
complete this and get it merged at some point, but you're welcome to
beat me to it.  If you (or anyone else) decide to work off this, I'd
be happy to take patches or give you push access to the repo.

Current status:
- linux-user: Busybox (ash, ls, gzip, etc) works.

- system: Linux kernel (built for ATSTK1000) boots and is able to get a
  userspace printf(Hello) init process to run.  Busybox init doesn't
  work because fork/exec appears to be broken with the current MMU code.

TODO, off the top of my head:
- Get fork/exec working under Linux in system mode
- Code cleanup (especially remove duplicated code in translate.c)
- Make kernel args/atags work (removes need for kernel hack)
- Disassembler code integration
- Single stepping
- GDB support
- more devices (atleast framebuffer), sysbus conversion
- Implement missing insns (mul variants, packed data insns, saturating
  arithmetic, various odds  ends)
- processor variants support (UC3)?
- ...

Rabin




Re: [Qemu-devel] qemu-i386 -L / /usr/bin/perl -e 'print `perl -v`' doesn't print

2009-10-25 Thread Rabin Vincent
On Thu, Oct 22, 2009 at 10:25:59AM -0700, Jay Schulist wrote:
 I have an issue with perl and qemu that I'm hoping someone knows what
 is happening. I'm using qemu-i386 on a fedora 11 intel system and the
 following command fails:
 
 $ qemu-i386 -L / /usr/bin/perl -e 'print `perl -v`'
[...] 
 I am using qemu-i386 v0.11.0 as shown below and other binaries run
 under qemu look fine. Could you suggest a way to get this perl command
 working.

Applying this patch (i386-linux-user NPTL support) makes it work:
http://lists.gnu.org/archive/html/qemu-devel/2009-08/msg01041.html

Rabin