Re: [PULL 1/1] target/openrisc: Set EPCR to next PC on FPE exceptions

2023-08-10 Thread Stafford Horne
On Thu, Aug 10, 2023 at 09:35:18AM +0300, Michael Tokarev wrote:
> 09.08.2023 23:34, Stafford Horne пишет:
> > The architecture specification calls for the EPCR to be set to "Address
> > of next not executed instruction" when there is a floating point
> > exception (FPE).  This was not being done, so fix it by using the same
> > pattern as syscall.  Also, we move this logic down to be done for
> > instructions not in the delay slot as called for by the architecture
> > manual.
> > 
> > Without this patch FPU exceptions will loop, as the exception handling
> > will always return back to the failed floating point instruction.
> > 
> > This was not noticed in earlier testing because:
> > 
> >   1. The compiler usually generates code which clobbers the input operand
> >  such as:
> > 
> >lf.div.s r19,r17,r19
> > 
> >   2. The target will store the operation output before to the register
> >  before handling the exception.  So an operation such as:
> > 
> >float a = 100.0f;
> >float b = 0.0f;
> >float c = a / b;/* lf.div.s r19,r17,r19 */
> > 
> >  Will first execute:
> > 
> >100 / 0-> Store inf to c (r19)
> >   -> triggering divide by zero exception
> >   -> handle and return
> > 
> >  Then it will execute:
> > 
> >100 / inf  -> Store 0 to c  (no exception)
> > 
> > To confirm the looping behavior and the fix I used the following:
> > 
> >  float fpu_div(float a, float b) {
> > float c;
> > asm volatile("lf.div.s %0, %1, %2"
> >   : "+r" (c)
> >   : "r" (a), "r" (b));
> > return c;
> >  }
> 
> Is it a -stable material?  It applies cleanly to 8.0 and 7.2.
> Or maybe it is not needed on older versions, not being noticed before?

I would say no, it will work on 8.0 an 7.2 but this code path is not very useful
withouth the other 8.1 Floating Point Exception handling updates.

-Stafford



[PULL 0/1] OpenRISC FPU Fix for 8.1

2023-08-09 Thread Stafford Horne
The following changes since commit ccdd31267678db9d80578b5f80bbe94141609ef4:

  Merge tag 'pull-qapi-2023-07-26-v2' of https://repo.or.cz/qemu/armbru into 
staging (2023-07-26 07:16:19 -0700)

are available in the Git repository at:

  https://github.com/stffrdhrn/qemu.git tags/or1k-pull-request-20230809

for you to fetch changes up to 765fdc1e8355d4bae563b3b185c5f9d079384164:

  target/openrisc: Set EPCR to next PC on FPE exceptions (2023-07-31 22:01:03 
+0100)


OpenRISC FPU Fix for 8.1

A patch to pass the correct exception address when handling floating
point exceptions.


Stafford Horne (1):
  target/openrisc: Set EPCR to next PC on FPE exceptions

 target/openrisc/interrupt.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)



[PULL 1/1] target/openrisc: Set EPCR to next PC on FPE exceptions

2023-08-09 Thread Stafford Horne
The architecture specification calls for the EPCR to be set to "Address
of next not executed instruction" when there is a floating point
exception (FPE).  This was not being done, so fix it by using the same
pattern as syscall.  Also, we move this logic down to be done for
instructions not in the delay slot as called for by the architecture
manual.

Without this patch FPU exceptions will loop, as the exception handling
will always return back to the failed floating point instruction.

This was not noticed in earlier testing because:

 1. The compiler usually generates code which clobbers the input operand
such as:

  lf.div.s r19,r17,r19

 2. The target will store the operation output before to the register
before handling the exception.  So an operation such as:

  float a = 100.0f;
  float b = 0.0f;
  float c = a / b;/* lf.div.s r19,r17,r19 */

Will first execute:

  100 / 0-> Store inf to c (r19)
 -> triggering divide by zero exception
 -> handle and return

Then it will execute:

  100 / inf  -> Store 0 to c  (no exception)

To confirm the looping behavior and the fix I used the following:

float fpu_div(float a, float b) {
float c;
asm volatile("lf.div.s %0, %1, %2"
  : "+r" (c)
  : "r" (a), "r" (b));
return c;
    }

Reviewed-by: Richard Henderson 
Signed-off-by: Stafford Horne 
---
 target/openrisc/interrupt.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/target/openrisc/interrupt.c b/target/openrisc/interrupt.c
index 3887812810..d4fdb8ce8e 100644
--- a/target/openrisc/interrupt.c
+++ b/target/openrisc/interrupt.c
@@ -34,9 +34,7 @@ void openrisc_cpu_do_interrupt(CPUState *cs)
 int exception = cs->exception_index;
 
 env->epcr = env->pc;
-if (exception == EXCP_SYSCALL) {
-env->epcr += 4;
-}
+
 /* When we have an illegal instruction the error effective address
shall be set to the illegal instruction address.  */
 if (exception == EXCP_ILLEGAL) {
@@ -63,6 +61,9 @@ void openrisc_cpu_do_interrupt(CPUState *cs)
 env->epcr -= 4;
 } else {
 env->sr &= ~SR_DSX;
+if (exception == EXCP_SYSCALL || exception == EXCP_FPE) {
+env->epcr += 4;
+}
 }
 
 if (exception > 0 && exception < EXCP_NR) {
-- 
2.39.1




[PATCH v2] target/openrisc: Set EPCR to next PC on FPE exceptions

2023-07-31 Thread Stafford Horne
The architecture specification calls for the EPCR to be set to "Address
of next not executed instruction" when there is a floating point
exception (FPE).  This was not being done, so fix it by using the same
pattern as syscall.  Also, we move this logic down to be done for
instructions not in the delay slot as called for by the architecture
manual.

Without this patch FPU exceptions will loop, as the exception handling
will always return back to the failed floating point instruction.

This was not noticed in earlier testing because:

 1. The compiler usually generates code which clobbers the input operand
such as:

  lf.div.s r19,r17,r19

 2. The target will store the operation output before to the register
before handling the exception.  So an operation such as:

  float a = 100.0f;
  float b = 0.0f;
  float c = a / b;/* lf.div.s r19,r17,r19 */

Will first execute:

  100 / 0-> Store inf to c (r19)
 -> triggering divide by zero exception
 -> handle and return

Then it will execute:

  100 / inf  -> Store 0 to c  (no exception)

To confirm the looping behavior and the fix I used the following:

float fpu_div(float a, float b) {
float c;
asm volatile("lf.div.s %0, %1, %2"
  : "+r" (c)
  : "r" (a), "r" (b));
return c;
    }

Reviewed-by: Richard Henderson 
Signed-off-by: Stafford Horne 
---
 target/openrisc/interrupt.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/target/openrisc/interrupt.c b/target/openrisc/interrupt.c
index 3887812810..d4fdb8ce8e 100644
--- a/target/openrisc/interrupt.c
+++ b/target/openrisc/interrupt.c
@@ -34,9 +34,7 @@ void openrisc_cpu_do_interrupt(CPUState *cs)
 int exception = cs->exception_index;
 
 env->epcr = env->pc;
-if (exception == EXCP_SYSCALL) {
-env->epcr += 4;
-}
+
 /* When we have an illegal instruction the error effective address
shall be set to the illegal instruction address.  */
 if (exception == EXCP_ILLEGAL) {
@@ -63,6 +61,9 @@ void openrisc_cpu_do_interrupt(CPUState *cs)
 env->epcr -= 4;
 } else {
 env->sr &= ~SR_DSX;
+if (exception == EXCP_SYSCALL || exception == EXCP_FPE) {
+env->epcr += 4;
+}
 }
 
 if (exception > 0 && exception < EXCP_NR) {
-- 
2.39.1




Re: [PATCH] target/openrisc: Set EPCR to next PC on FPE exceptions

2023-07-31 Thread Stafford Horne
On Sun, Jul 30, 2023 at 10:43:45AM -0700, Richard Henderson wrote:
> On 7/29/23 14:08, Stafford Horne wrote:
> > The architecture specification calls for the EPCR to be set to "Address
> > of next not executed instruction" when there is a floating point
> > exception (FPE).  This was not being done, so fix it by using the same
> > method as syscall.  Note, this may need a lot more work if we start
> > seeing floating point operations in delay slots which exceptions
> > enabled.
> > 
> > Without this patch FPU exceptions will loop, as the exception hanlding
> > will always return back to the failed floating point instruction.
> > 
> > This was not noticed in earlier testing because:
> > 
> >   1. The compiler usually generates code which clobbers the input operand
> >  such as:
> > 
> >lf.div.s r19,r17,r19
> > 
> >   2. The target will store the operation output before to the register
> >  before handling the exception.  So an operation such as:
> > 
> >float a = 100.0f;
> >float b = 0.0f;
> >float c = a / b;/* lf.div.s r19,r17,r19 */
> > 
> >  Will first execute:
> > 
> >100 / 0-> Store inf to c (r19)
> >   -> triggering divide by zero exception
> >   -> handle and return
> > 
> >  Then it will exectute:
> > 
> >100 / inf  -> Store 0 to c  (no exception)
> > 
> > To confirm the looping behavoid and the fix I used the following:
> > 
> >  float fpu_div(float a, float b) {
> > float c;
> > asm volatile("lf.div.s %0, %1, %2"
> >   : "+r" (c)
> >   : "r" (a), "r" (b));
> > return c;
> >  }
> > 
> > Signed-off-by: Stafford Horne 
> > ---
> >   target/openrisc/interrupt.c | 2 +-
> >   1 file changed, 1 insertion(+), 1 deletion(-)
> > 
> > diff --git a/target/openrisc/interrupt.c b/target/openrisc/interrupt.c
> > index 3887812810..9b14b8a2c6 100644
> > --- a/target/openrisc/interrupt.c
> > +++ b/target/openrisc/interrupt.c
> > @@ -34,7 +34,7 @@ void openrisc_cpu_do_interrupt(CPUState *cs)
> >   int exception = cs->exception_index;
> >   env->epcr = env->pc;
> > -if (exception == EXCP_SYSCALL) {
> > +if (exception == EXCP_SYSCALL || exception == EXCP_FPE) {
> >   env->epcr += 4;
> >   }
> >   /* When we have an illegal instruction the error effective address
> 
> According to Table 6-3, when in a delay slot the EPCR should be the address
> of the jump, for both syscall and fpe.  This whole block should be moved
> down...
> 
> > /* Set/clear dsx to indicate if we are in a delay slot exception.  */
> > if (env->dflag) {
> > env->dflag = 0;
> > env->sr |= SR_DSX;
> > env->epcr -= 4;
> > } else {
> > env->sr &= ~SR_DSX;
> > }
> 
> ... into the else.

Thanks for looking at this.  This is correct.  I will fix it this way, though
this points to an issue in the architecture (in the manual as "Particular delay
slot issues").  If we have instructions causing exceptions in delay slots like
l.sys it will cause looping.

> With that,
> Reviewed-by: Richard Henderson 

Thank you.

-Stafford



Re: [PATCH] target/openrisc: Set EPCR to next PC on FPE exceptions

2023-07-29 Thread Stafford Horne
On Sat, Jul 29, 2023 at 10:08:51PM +0100, Stafford Horne wrote:
> The architecture specification calls for the EPCR to be set to "Address
> of next not executed instruction" when there is a floating point
> exception (FPE).  This was not being done, so fix it by using the same
> method as syscall.  Note, this may need a lot more work if we start
> seeing floating point operations in delay slots which exceptions
> enabled.

It should be "with exceptions enabled."

> 
> Without this patch FPU exceptions will loop, as the exception hanlding

"handling"

> will always return back to the failed floating point instruction.
> 
> This was not noticed in earlier testing because:
> 
>  1. The compiler usually generates code which clobbers the input operand
> such as:
> 
>   lf.div.s r19,r17,r19
> 
>  2. The target will store the operation output before to the register
> before handling the exception.  So an operation such as:
> 
>   float a = 100.0f;
>   float b = 0.0f;
>   float c = a / b;/* lf.div.s r19,r17,r19 */
> 
> Will first execute:
> 
>   100 / 0-> Store inf to c (r19)
>  -> triggering divide by zero exception
>  -> handle and return
> 
> Then it will exectute:
> 
>   100 / inf  -> Store 0 to c  (no exception)
> 
> To confirm the looping behavoid and the fix I used the following:

"behavior"

> float fpu_div(float a, float b) {
>   float c;
>   asm volatile("lf.div.s %0, %1, %2"
> : "+r" (c)
> : "r" (a), "r" (b));
>   return c;
> }
> 
> Signed-off-by: Stafford Horne 

-Stafford

> ---
>  target/openrisc/interrupt.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/target/openrisc/interrupt.c b/target/openrisc/interrupt.c
> index 3887812810..9b14b8a2c6 100644
> --- a/target/openrisc/interrupt.c
> +++ b/target/openrisc/interrupt.c
> @@ -34,7 +34,7 @@ void openrisc_cpu_do_interrupt(CPUState *cs)
>  int exception = cs->exception_index;
>  
>  env->epcr = env->pc;
> -if (exception == EXCP_SYSCALL) {
> +if (exception == EXCP_SYSCALL || exception == EXCP_FPE) {
>  env->epcr += 4;
>  }
>  /* When we have an illegal instruction the error effective address
> -- 
> 2.39.1
> 



[PATCH] target/openrisc: Set EPCR to next PC on FPE exceptions

2023-07-29 Thread Stafford Horne
The architecture specification calls for the EPCR to be set to "Address
of next not executed instruction" when there is a floating point
exception (FPE).  This was not being done, so fix it by using the same
method as syscall.  Note, this may need a lot more work if we start
seeing floating point operations in delay slots which exceptions
enabled.

Without this patch FPU exceptions will loop, as the exception hanlding
will always return back to the failed floating point instruction.

This was not noticed in earlier testing because:

 1. The compiler usually generates code which clobbers the input operand
such as:

  lf.div.s r19,r17,r19

 2. The target will store the operation output before to the register
before handling the exception.  So an operation such as:

  float a = 100.0f;
  float b = 0.0f;
  float c = a / b;/* lf.div.s r19,r17,r19 */

Will first execute:

  100 / 0-> Store inf to c (r19)
 -> triggering divide by zero exception
 -> handle and return

Then it will exectute:

  100 / inf  -> Store 0 to c  (no exception)

To confirm the looping behavoid and the fix I used the following:

float fpu_div(float a, float b) {
float c;
asm volatile("lf.div.s %0, %1, %2"
  : "+r" (c)
  : "r" (a), "r" (b));
return c;
}

Signed-off-by: Stafford Horne 
---
 target/openrisc/interrupt.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/openrisc/interrupt.c b/target/openrisc/interrupt.c
index 3887812810..9b14b8a2c6 100644
--- a/target/openrisc/interrupt.c
+++ b/target/openrisc/interrupt.c
@@ -34,7 +34,7 @@ void openrisc_cpu_do_interrupt(CPUState *cs)
 int exception = cs->exception_index;
 
 env->epcr = env->pc;
-if (exception == EXCP_SYSCALL) {
+if (exception == EXCP_SYSCALL || exception == EXCP_FPE) {
 env->epcr += 4;
 }
 /* When we have an illegal instruction the error effective address
-- 
2.39.1




[PULL 0/3] OpenRISC FPU Updates for 8.1

2023-05-13 Thread Stafford Horne
The following changes since commit c1eb2ddf0f8075faddc5f7c3d39feae3e8e9d6b4:

  Update version for v8.0.0 release (2023-04-19 17:27:13 +0100)

are available in the Git repository at:

  https://github.com/stffrdhrn/qemu.git tags/or1k-pull-request-20230513

for you to fetch changes up to 874c52991e1fbe020812b4b15440b6875369aacf:

  target/openrisc: Setup FPU for detecting tininess before rounding (2023-05-11 
15:40:28 +0100)


OpenRISC FPU Updates for 8.1

A few fixes and updates to bring OpenRISC inline with the latest
architecture spec updates:

 - Allow FPCSR to be accessed in user mode
 - Select tininess detection before rounding
 - Fix FPE Exception PC value


Stafford Horne (3):
  target/openrisc: Allow fpcsr access in user mode
  target/openrisc: Set PC to cpu state on FPU exception
  target/openrisc: Setup FPU for detecting tininess before rounding

 target/openrisc/cpu.c|  4 +++
 target/openrisc/fpu_helper.c | 13 ++--
 target/openrisc/sys_helper.c | 45 ---
 target/openrisc/translate.c  | 72 
 4 files changed, 81 insertions(+), 53 deletions(-)



[PULL 3/3] target/openrisc: Setup FPU for detecting tininess before rounding

2023-05-13 Thread Stafford Horne
OpenRISC defines tininess to be detected before rounding.  Setup qemu to
obey this.

Signed-off-by: Stafford Horne 
Reviewed-by: Richard Henderson 
---
 target/openrisc/cpu.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/target/openrisc/cpu.c b/target/openrisc/cpu.c
index 0ce4f796fa..61d748cfdc 100644
--- a/target/openrisc/cpu.c
+++ b/target/openrisc/cpu.c
@@ -22,6 +22,7 @@
 #include "qemu/qemu-print.h"
 #include "cpu.h"
 #include "exec/exec-all.h"
+#include "fpu/softfloat-helpers.h"
 #include "tcg/tcg.h"
 
 static void openrisc_cpu_set_pc(CPUState *cs, vaddr value)
@@ -90,6 +91,9 @@ static void openrisc_cpu_reset_hold(Object *obj)
 s->exception_index = -1;
 cpu_set_fpcsr(>env, 0);
 
+set_float_detect_tininess(float_tininess_before_rounding,
+  >env.fp_status);
+
 #ifndef CONFIG_USER_ONLY
 cpu->env.picmr = 0x;
 cpu->env.picsr = 0x;
-- 
2.39.1




[PULL 1/3] target/openrisc: Allow fpcsr access in user mode

2023-05-13 Thread Stafford Horne
As per OpenRISC spec 1.4 FPCSR can be read and written in user mode.

Update mtspr and mfspr helpers to support this by moving the is_user
check into the helper.

Link: 
https://raw.githubusercontent.com/openrisc/doc/master/openrisc-arch-1.4-rev0.pdf
Signed-off-by: Stafford Horne 
Reviewed-by: Richard Henderson 
---
 target/openrisc/sys_helper.c | 45 --
 target/openrisc/translate.c  | 72 
 2 files changed, 66 insertions(+), 51 deletions(-)

diff --git a/target/openrisc/sys_helper.c b/target/openrisc/sys_helper.c
index ec145960e3..ccdee3b8be 100644
--- a/target/openrisc/sys_helper.c
+++ b/target/openrisc/sys_helper.c
@@ -29,17 +29,37 @@
 
 #define TO_SPR(group, number) (((group) << 11) + (number))
 
+static inline bool is_user(CPUOpenRISCState *env)
+{
+#ifdef CONFIG_USER_ONLY
+return true;
+#else
+return (env->sr & SR_SM) == 0;
+#endif
+}
+
 void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong spr, target_ulong rb)
 {
-#ifndef CONFIG_USER_ONLY
 OpenRISCCPU *cpu = env_archcpu(env);
+#ifndef CONFIG_USER_ONLY
 CPUState *cs = env_cpu(env);
 target_ulong mr;
 int idx;
 #endif
 
+/* Handle user accessible SPRs first.  */
 switch (spr) {
+case TO_SPR(0, 20): /* FPCSR */
+cpu_set_fpcsr(env, rb);
+return;
+}
+
+if (is_user(env)) {
+raise_exception(cpu, EXCP_ILLEGAL);
+}
+
 #ifndef CONFIG_USER_ONLY
+switch (spr) {
 case TO_SPR(0, 11): /* EVBAR */
 env->evbar = rb;
 break;
@@ -187,27 +207,33 @@ void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong 
spr, target_ulong rb)
 cpu_openrisc_timer_update(cpu);
 qemu_mutex_unlock_iothread();
 break;
-#endif
-
-case TO_SPR(0, 20): /* FPCSR */
-cpu_set_fpcsr(env, rb);
-break;
 }
+#endif
 }
 
 target_ulong HELPER(mfspr)(CPUOpenRISCState *env, target_ulong rd,
target_ulong spr)
 {
+OpenRISCCPU *cpu = env_archcpu(env);
 #ifndef CONFIG_USER_ONLY
 uint64_t data[TARGET_INSN_START_WORDS];
 MachineState *ms = MACHINE(qdev_get_machine());
-OpenRISCCPU *cpu = env_archcpu(env);
 CPUState *cs = env_cpu(env);
 int idx;
 #endif
 
+/* Handle user accessible SPRs first.  */
 switch (spr) {
+case TO_SPR(0, 20): /* FPCSR */
+return env->fpcsr;
+}
+
+if (is_user(env)) {
+raise_exception(cpu, EXCP_ILLEGAL);
+}
+
 #ifndef CONFIG_USER_ONLY
+switch (spr) {
 case TO_SPR(0, 0): /* VR */
 return env->vr;
 
@@ -324,11 +350,8 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env, 
target_ulong rd,
 cpu_openrisc_count_update(cpu);
 qemu_mutex_unlock_iothread();
 return cpu_openrisc_count_get(cpu);
-#endif
-
-case TO_SPR(0, 20): /* FPCSR */
-return env->fpcsr;
 }
+#endif
 
 /* for rd is passed in, if rd unchanged, just keep it back.  */
 return rd;
diff --git a/target/openrisc/translate.c b/target/openrisc/translate.c
index 76e53c78d4..43ba0cc1ad 100644
--- a/target/openrisc/translate.c
+++ b/target/openrisc/translate.c
@@ -819,45 +819,12 @@ static bool trans_l_xori(DisasContext *dc, arg_rri *a)
 
 static bool trans_l_mfspr(DisasContext *dc, arg_l_mfspr *a)
 {
-check_r0_write(dc, a->d);
-
-if (is_user(dc)) {
-gen_illegal_exception(dc);
-} else {
-TCGv spr = tcg_temp_new();
-
-if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
-gen_io_start();
-if (dc->delayed_branch) {
-tcg_gen_mov_tl(cpu_pc, jmp_pc);
-tcg_gen_discard_tl(jmp_pc);
-} else {
-tcg_gen_movi_tl(cpu_pc, dc->base.pc_next + 4);
-}
-dc->base.is_jmp = DISAS_EXIT;
-}
+TCGv spr = tcg_temp_new();
 
-tcg_gen_ori_tl(spr, cpu_R(dc, a->a), a->k);
-gen_helper_mfspr(cpu_R(dc, a->d), cpu_env, cpu_R(dc, a->d), spr);
-}
-return true;
-}
-
-static bool trans_l_mtspr(DisasContext *dc, arg_l_mtspr *a)
-{
-if (is_user(dc)) {
-gen_illegal_exception(dc);
-} else {
-TCGv spr;
+check_r0_write(dc, a->d);
 
-if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
-gen_io_start();
-}
-/* For SR, we will need to exit the TB to recognize the new
- * exception state.  For NPC, in theory this counts as a branch
- * (although the SPR only exists for use by an ICE).  Save all
- * of the cpu state first, allowing it to be overwritten.
- */
+if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
+gen_io_start();
 if (dc->delayed_branch) {
 tcg_gen_mov_tl(cpu_pc, jmp_pc);
 tcg_gen_discard_tl(jmp_pc);
@@ -865,11 +832,36 @@ static bool trans_l_mtspr(DisasContext *dc, arg_l_mtspr 
*a)
 tcg_gen_movi_tl(cpu_pc, dc->base.pc_next + 4);
 }
  

[PULL 2/3] target/openrisc: Set PC to cpu state on FPU exception

2023-05-13 Thread Stafford Horne
Store the PC to ensure the correct value can be read in the exception
handler.

Signed-off-by: Stafford Horne 
Reviewed-by: Richard Henderson 
---
 target/openrisc/fpu_helper.c | 13 +++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/target/openrisc/fpu_helper.c b/target/openrisc/fpu_helper.c
index f9e34fa2cc..8b81d2f62f 100644
--- a/target/openrisc/fpu_helper.c
+++ b/target/openrisc/fpu_helper.c
@@ -20,8 +20,8 @@
 
 #include "qemu/osdep.h"
 #include "cpu.h"
+#include "exec/exec-all.h"
 #include "exec/helper-proto.h"
-#include "exception.h"
 #include "fpu/softfloat.h"
 
 static int ieee_ex_to_openrisc(int fexcp)
@@ -45,6 +45,15 @@ static int ieee_ex_to_openrisc(int fexcp)
 return ret;
 }
 
+static G_NORETURN
+void do_fpe(CPUOpenRISCState *env, uintptr_t pc)
+{
+CPUState *cs = env_cpu(env);
+
+cs->exception_index = EXCP_FPE;
+cpu_loop_exit_restore(cs, pc);
+}
+
 void HELPER(update_fpcsr)(CPUOpenRISCState *env)
 {
 int tmp = get_float_exception_flags(>fp_status);
@@ -55,7 +64,7 @@ void HELPER(update_fpcsr)(CPUOpenRISCState *env)
 if (tmp) {
 env->fpcsr |= tmp;
 if (env->fpcsr & FPCSR_FPEE) {
-helper_exception(env, EXCP_FPE);
+do_fpe(env, GETPC());
 }
 }
 }
-- 
2.39.1




[PATCH v3 3/3] target/openrisc: Setup FPU for detecting tininess before rounding

2023-05-11 Thread Stafford Horne
OpenRISC defines tininess to be detected before rounding.  Setup qemu to
obey this.

Signed-off-by: Stafford Horne 
Reviewed-by: Richard Henderson 
---
Since v2:
 - Add reviewed-by
Since v1:
 - Remove setting default NaN behavior.

 target/openrisc/cpu.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/target/openrisc/cpu.c b/target/openrisc/cpu.c
index 0ce4f796fa..61d748cfdc 100644
--- a/target/openrisc/cpu.c
+++ b/target/openrisc/cpu.c
@@ -22,6 +22,7 @@
 #include "qemu/qemu-print.h"
 #include "cpu.h"
 #include "exec/exec-all.h"
+#include "fpu/softfloat-helpers.h"
 #include "tcg/tcg.h"
 
 static void openrisc_cpu_set_pc(CPUState *cs, vaddr value)
@@ -90,6 +91,9 @@ static void openrisc_cpu_reset_hold(Object *obj)
 s->exception_index = -1;
 cpu_set_fpcsr(>env, 0);
 
+set_float_detect_tininess(float_tininess_before_rounding,
+  >env.fp_status);
+
 #ifndef CONFIG_USER_ONLY
 cpu->env.picmr = 0x;
 cpu->env.picsr = 0x;
-- 
2.39.1




[PATCH v3 0/3] OpenRISC updates for user space FPU

2023-05-11 Thread Stafford Horne
Hello,

Since v2:
 - Add reviewed-by's from Richard
 - Pull cpu definition out of ifdef in helper_mfspr
Since v1:
 - Fixups suggested by Richard Henderson

This series adds support for the FPU related architecture changes defined in
architecture spec revision v1.4.

 - https://openrisc.io/revisions/r1.4

In summary the architecture changes are:

 - Change FPCSR SPR permissions to allow for reading and writing from user
   space.
 - Clarify that FPU underflow detection is done by detecting tininess before
   rounding.

Previous to this series FPCSR reads and writes from user-mode in QEMU would
throw an illegal argument exception.  The proper behavior should have been to
treat these operations as no-ops as the cpu implementations do.  As mentioned
series changes FPCSR read/write to follow the spec.

The series has been tested with the FPU support added in glibc test suite and
all math tests are passing.


Stafford Horne (3):
  target/openrisc: Allow fpcsr access in user mode
  target/openrisc: Set PC to cpu state on FPU exception
  target/openrisc: Setup FPU for detecting tininess before rounding

 target/openrisc/cpu.c|  4 ++
 target/openrisc/fpu_helper.c | 13 ++-
 target/openrisc/sys_helper.c | 45 --
 target/openrisc/translate.c  | 72 
 4 files changed, 81 insertions(+), 53 deletions(-)

-- 
2.39.1




[PATCH v3 1/3] target/openrisc: Allow fpcsr access in user mode

2023-05-11 Thread Stafford Horne
As per OpenRISC spec 1.4 FPCSR can be read and written in user mode.

Update mtspr and mfspr helpers to support this by moving the is_user
check into the helper.

Link: 
https://raw.githubusercontent.com/openrisc/doc/master/openrisc-arch-1.4-rev0.pdf
Signed-off-by: Stafford Horne 
Reviewed-by: Richard Henderson 
---

Since v2:
 - Add reviewed-by
 - In helper_mfspr bring cpu out of ifdef to avoid replicatig the definition.
   Originally I left it in the ifdef to avoid having to mix having pointers and
   the data array defined on the stack.  But that's overthinking.
Since v1:
 - Update commit message to remove text about no-existant logic change.

 target/openrisc/sys_helper.c | 45 --
 target/openrisc/translate.c  | 72 
 2 files changed, 66 insertions(+), 51 deletions(-)

diff --git a/target/openrisc/sys_helper.c b/target/openrisc/sys_helper.c
index ec145960e3..ccdee3b8be 100644
--- a/target/openrisc/sys_helper.c
+++ b/target/openrisc/sys_helper.c
@@ -29,17 +29,37 @@
 
 #define TO_SPR(group, number) (((group) << 11) + (number))
 
+static inline bool is_user(CPUOpenRISCState *env)
+{
+#ifdef CONFIG_USER_ONLY
+return true;
+#else
+return (env->sr & SR_SM) == 0;
+#endif
+}
+
 void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong spr, target_ulong rb)
 {
-#ifndef CONFIG_USER_ONLY
 OpenRISCCPU *cpu = env_archcpu(env);
+#ifndef CONFIG_USER_ONLY
 CPUState *cs = env_cpu(env);
 target_ulong mr;
 int idx;
 #endif
 
+/* Handle user accessible SPRs first.  */
 switch (spr) {
+case TO_SPR(0, 20): /* FPCSR */
+cpu_set_fpcsr(env, rb);
+return;
+}
+
+if (is_user(env)) {
+raise_exception(cpu, EXCP_ILLEGAL);
+}
+
 #ifndef CONFIG_USER_ONLY
+switch (spr) {
 case TO_SPR(0, 11): /* EVBAR */
 env->evbar = rb;
 break;
@@ -187,27 +207,33 @@ void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong 
spr, target_ulong rb)
 cpu_openrisc_timer_update(cpu);
 qemu_mutex_unlock_iothread();
 break;
-#endif
-
-case TO_SPR(0, 20): /* FPCSR */
-cpu_set_fpcsr(env, rb);
-break;
 }
+#endif
 }
 
 target_ulong HELPER(mfspr)(CPUOpenRISCState *env, target_ulong rd,
target_ulong spr)
 {
+OpenRISCCPU *cpu = env_archcpu(env);
 #ifndef CONFIG_USER_ONLY
 uint64_t data[TARGET_INSN_START_WORDS];
 MachineState *ms = MACHINE(qdev_get_machine());
-OpenRISCCPU *cpu = env_archcpu(env);
 CPUState *cs = env_cpu(env);
 int idx;
 #endif
 
+/* Handle user accessible SPRs first.  */
 switch (spr) {
+case TO_SPR(0, 20): /* FPCSR */
+return env->fpcsr;
+}
+
+if (is_user(env)) {
+raise_exception(cpu, EXCP_ILLEGAL);
+}
+
 #ifndef CONFIG_USER_ONLY
+switch (spr) {
 case TO_SPR(0, 0): /* VR */
 return env->vr;
 
@@ -324,11 +350,8 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env, 
target_ulong rd,
 cpu_openrisc_count_update(cpu);
 qemu_mutex_unlock_iothread();
 return cpu_openrisc_count_get(cpu);
-#endif
-
-case TO_SPR(0, 20): /* FPCSR */
-return env->fpcsr;
 }
+#endif
 
 /* for rd is passed in, if rd unchanged, just keep it back.  */
 return rd;
diff --git a/target/openrisc/translate.c b/target/openrisc/translate.c
index 76e53c78d4..43ba0cc1ad 100644
--- a/target/openrisc/translate.c
+++ b/target/openrisc/translate.c
@@ -819,45 +819,12 @@ static bool trans_l_xori(DisasContext *dc, arg_rri *a)
 
 static bool trans_l_mfspr(DisasContext *dc, arg_l_mfspr *a)
 {
-check_r0_write(dc, a->d);
-
-if (is_user(dc)) {
-gen_illegal_exception(dc);
-} else {
-TCGv spr = tcg_temp_new();
-
-if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
-gen_io_start();
-if (dc->delayed_branch) {
-tcg_gen_mov_tl(cpu_pc, jmp_pc);
-tcg_gen_discard_tl(jmp_pc);
-} else {
-tcg_gen_movi_tl(cpu_pc, dc->base.pc_next + 4);
-}
-dc->base.is_jmp = DISAS_EXIT;
-}
+TCGv spr = tcg_temp_new();
 
-tcg_gen_ori_tl(spr, cpu_R(dc, a->a), a->k);
-gen_helper_mfspr(cpu_R(dc, a->d), cpu_env, cpu_R(dc, a->d), spr);
-}
-return true;
-}
-
-static bool trans_l_mtspr(DisasContext *dc, arg_l_mtspr *a)
-{
-if (is_user(dc)) {
-gen_illegal_exception(dc);
-} else {
-TCGv spr;
+check_r0_write(dc, a->d);
 
-if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
-gen_io_start();
-}
-/* For SR, we will need to exit the TB to recognize the new
- * exception state.  For NPC, in theory this counts as a branch
- * (although the SPR only exists for use by an ICE).  Save all
- * of the cpu state first, allowing it to be overwritten.
- */
+if (tb_cflags(dc->

[PATCH v3 2/3] target/openrisc: Set PC to cpu state on FPU exception

2023-05-11 Thread Stafford Horne
Store the PC to ensure the correct value can be read in the exception
handler.

Signed-off-by: Stafford Horne 
Reviewed-by: Richard Henderson 
---
Since v2:
 - Add reviewed-by
Since v1:
 - Use function do_fpe (similar to do_range) to raise exception.

 target/openrisc/fpu_helper.c | 13 +++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/target/openrisc/fpu_helper.c b/target/openrisc/fpu_helper.c
index f9e34fa2cc..8b81d2f62f 100644
--- a/target/openrisc/fpu_helper.c
+++ b/target/openrisc/fpu_helper.c
@@ -20,8 +20,8 @@
 
 #include "qemu/osdep.h"
 #include "cpu.h"
+#include "exec/exec-all.h"
 #include "exec/helper-proto.h"
-#include "exception.h"
 #include "fpu/softfloat.h"
 
 static int ieee_ex_to_openrisc(int fexcp)
@@ -45,6 +45,15 @@ static int ieee_ex_to_openrisc(int fexcp)
 return ret;
 }
 
+static G_NORETURN
+void do_fpe(CPUOpenRISCState *env, uintptr_t pc)
+{
+CPUState *cs = env_cpu(env);
+
+cs->exception_index = EXCP_FPE;
+cpu_loop_exit_restore(cs, pc);
+}
+
 void HELPER(update_fpcsr)(CPUOpenRISCState *env)
 {
 int tmp = get_float_exception_flags(>fp_status);
@@ -55,7 +64,7 @@ void HELPER(update_fpcsr)(CPUOpenRISCState *env)
 if (tmp) {
 env->fpcsr |= tmp;
 if (env->fpcsr & FPCSR_FPEE) {
-helper_exception(env, EXCP_FPE);
+do_fpe(env, GETPC());
 }
 }
 }
-- 
2.39.1




Re: [PATCH v2 3/3] target/openrisc: Setup FPU for detecting tininess before rounding

2023-05-11 Thread Stafford Horne
On Wed, May 10, 2023 at 05:16:20PM +0100, Richard Henderson wrote:
> On 5/10/23 16:32, Stafford Horne wrote:
> > OpenRISC defines tininess to be detected before rounding.  Setup qemu to
> > obey this.
> > 
> > Signed-off-by: Stafford Horne 
> > ---
> > Since v1:
> >   - Remove setting default NaN behavior.  I discussed with the FPU 
> > developers and
> > they mentioned the OpenRISC hardware should be IEEE compliant when 
> > handling
> > and forwarding NaN payloads, and they don't want try change this.
> 
> There is no such thing as IEEE compliant for NaN payloads.
> All of that is implementation defined.

I see, I haven't yet seen to IEEE 754 spec so I don't know how much is covered.
It was incorrect to assume forwarding semantics was covered.

> All OpenRISC needs to do is document its intentions (and then double-check
> that fpu/softfloat-specialize.c.inc does what is documented).

Understood, that makes sense, also reading that code I see how all other
architectures are able to ifdef their way to a specific behavior.  I will see
what our current implementions do and update the spec and qemu as a separate
task.

> 
> Anyway, back to this patch,
> Reviewed-by: Richard Henderson 
> 
> :-)

Thank you ^_^

-Stafford



Re: [PATCH v2 1/3] target/openrisc: Allow fpcsr access in user mode

2023-05-11 Thread Stafford Horne
On Wed, May 10, 2023 at 05:13:03PM +0100, Richard Henderson wrote:
> On 5/10/23 16:32, Stafford Horne wrote:
> >   void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong spr, target_ulong 
> > rb)
> >   {
> > -#ifndef CONFIG_USER_ONLY
> >   OpenRISCCPU *cpu = env_archcpu(env);
> > +#ifndef CONFIG_USER_ONLY
> >   CPUState *cs = env_cpu(env);
> 
> Pulled cpu out if ifdef here...
> 
> > @@ -204,10 +220,22 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env, 
> > target_ulong rd,
> >   OpenRISCCPU *cpu = env_archcpu(env);
> >   CPUState *cs = env_cpu(env);
> >   int idx;
> > +#else
> > +OpenRISCCPU *cpu = env_archcpu(env);
> >   #endif
> 
> But replicated it here.

Right, let me make it consistent in this patch.

> Otherwise,
> Reviewed-by: Richard Henderson 

Thank you,

-Stafford



[PATCH v2 3/3] target/openrisc: Setup FPU for detecting tininess before rounding

2023-05-10 Thread Stafford Horne
OpenRISC defines tininess to be detected before rounding.  Setup qemu to
obey this.

Signed-off-by: Stafford Horne 
---
Since v1:
 - Remove setting default NaN behavior.  I discussed with the FPU developers and
   they mentioned the OpenRISC hardware should be IEEE compliant when handling
   and forwarding NaN payloads, and they don't want try change this.

 target/openrisc/cpu.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/target/openrisc/cpu.c b/target/openrisc/cpu.c
index 0ce4f796fa..61d748cfdc 100644
--- a/target/openrisc/cpu.c
+++ b/target/openrisc/cpu.c
@@ -22,6 +22,7 @@
 #include "qemu/qemu-print.h"
 #include "cpu.h"
 #include "exec/exec-all.h"
+#include "fpu/softfloat-helpers.h"
 #include "tcg/tcg.h"
 
 static void openrisc_cpu_set_pc(CPUState *cs, vaddr value)
@@ -90,6 +91,9 @@ static void openrisc_cpu_reset_hold(Object *obj)
 s->exception_index = -1;
 cpu_set_fpcsr(>env, 0);
 
+set_float_detect_tininess(float_tininess_before_rounding,
+  >env.fp_status);
+
 #ifndef CONFIG_USER_ONLY
 cpu->env.picmr = 0x;
 cpu->env.picsr = 0x;
-- 
2.39.1




[PATCH v2 2/3] target/openrisc: Set PC to cpu state on FPU exception

2023-05-10 Thread Stafford Horne
Store the PC to ensure the correct value can be read in the exception
handler.

Signed-off-by: Stafford Horne 
---
Since v1:
 - Use function do_fpe (similar to do_range) to raise exception.

 target/openrisc/fpu_helper.c | 13 +++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/target/openrisc/fpu_helper.c b/target/openrisc/fpu_helper.c
index f9e34fa2cc..8b81d2f62f 100644
--- a/target/openrisc/fpu_helper.c
+++ b/target/openrisc/fpu_helper.c
@@ -20,8 +20,8 @@
 
 #include "qemu/osdep.h"
 #include "cpu.h"
+#include "exec/exec-all.h"
 #include "exec/helper-proto.h"
-#include "exception.h"
 #include "fpu/softfloat.h"
 
 static int ieee_ex_to_openrisc(int fexcp)
@@ -45,6 +45,15 @@ static int ieee_ex_to_openrisc(int fexcp)
 return ret;
 }
 
+static G_NORETURN
+void do_fpe(CPUOpenRISCState *env, uintptr_t pc)
+{
+CPUState *cs = env_cpu(env);
+
+cs->exception_index = EXCP_FPE;
+cpu_loop_exit_restore(cs, pc);
+}
+
 void HELPER(update_fpcsr)(CPUOpenRISCState *env)
 {
 int tmp = get_float_exception_flags(>fp_status);
@@ -55,7 +64,7 @@ void HELPER(update_fpcsr)(CPUOpenRISCState *env)
 if (tmp) {
 env->fpcsr |= tmp;
 if (env->fpcsr & FPCSR_FPEE) {
-helper_exception(env, EXCP_FPE);
+do_fpe(env, GETPC());
 }
 }
 }
-- 
2.39.1




[PATCH v2 0/3] OpenRISC updates for user space FPU

2023-05-10 Thread Stafford Horne
Since v1:
 - Fixups suggested by Richard Henderson

This series adds support for the FPU related architecture changes defined in
architecture spec revision v1.4.

 - https://openrisc.io/revisions/r1.4

In summary the architecture changes are:

 - Change FPCSR SPR permissions to allow for reading and writing from user
   space.
 - Clarify that FPU underflow detection is done by detecting tininess before
   rounding.

Previous to this series FPCSR reads and writes from user-mode in QEMU would
throw an illegal argument exception.  The proper behavior should have been to
treat these operations as no-ops as the cpu implementations do.  As mentioned
series changes FPCSR read/write to follow the spec.

The series has been tested with the FPU support added in glibc test suite and
all math tests are passing.

Stafford Horne (3):
  target/openrisc: Allow fpcsr access in user mode
  target/openrisc: Set PC to cpu state on FPU exception
  target/openrisc: Setup FPU for detecting tininess before rounding

 target/openrisc/cpu.c|  4 ++
 target/openrisc/fpu_helper.c | 13 ++-
 target/openrisc/sys_helper.c | 45 +-
 target/openrisc/translate.c  | 72 
 4 files changed, 82 insertions(+), 52 deletions(-)

-- 
2.39.1




[PATCH v2 1/3] target/openrisc: Allow fpcsr access in user mode

2023-05-10 Thread Stafford Horne
As per OpenRISC spec 1.4 FPCSR can be read and written in user mode.

Update mtspr and mfspr helpers to support this by moving the is_user
check into the helper.

Link: 
https://raw.githubusercontent.com/openrisc/doc/master/openrisc-arch-1.4-rev0.pdf
Signed-off-by: Stafford Horne 
---
Since v1:
 - Update commit message to remove text about no-existant logic change.

 target/openrisc/sys_helper.c | 45 +-
 target/openrisc/translate.c  | 72 
 2 files changed, 67 insertions(+), 50 deletions(-)

diff --git a/target/openrisc/sys_helper.c b/target/openrisc/sys_helper.c
index ec145960e3..8a0259c710 100644
--- a/target/openrisc/sys_helper.c
+++ b/target/openrisc/sys_helper.c
@@ -29,17 +29,37 @@
 
 #define TO_SPR(group, number) (((group) << 11) + (number))
 
+static inline bool is_user(CPUOpenRISCState *env)
+{
+#ifdef CONFIG_USER_ONLY
+return true;
+#else
+return (env->sr & SR_SM) == 0;
+#endif
+}
+
 void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong spr, target_ulong rb)
 {
-#ifndef CONFIG_USER_ONLY
 OpenRISCCPU *cpu = env_archcpu(env);
+#ifndef CONFIG_USER_ONLY
 CPUState *cs = env_cpu(env);
 target_ulong mr;
 int idx;
 #endif
 
+/* Handle user accessible SPRs first.  */
 switch (spr) {
+case TO_SPR(0, 20): /* FPCSR */
+cpu_set_fpcsr(env, rb);
+return;
+}
+
+if (is_user(env)) {
+raise_exception(cpu, EXCP_ILLEGAL);
+}
+
 #ifndef CONFIG_USER_ONLY
+switch (spr) {
 case TO_SPR(0, 11): /* EVBAR */
 env->evbar = rb;
 break;
@@ -187,12 +207,8 @@ void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong 
spr, target_ulong rb)
 cpu_openrisc_timer_update(cpu);
 qemu_mutex_unlock_iothread();
 break;
-#endif
-
-case TO_SPR(0, 20): /* FPCSR */
-cpu_set_fpcsr(env, rb);
-break;
 }
+#endif
 }
 
 target_ulong HELPER(mfspr)(CPUOpenRISCState *env, target_ulong rd,
@@ -204,10 +220,22 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env, 
target_ulong rd,
 OpenRISCCPU *cpu = env_archcpu(env);
 CPUState *cs = env_cpu(env);
 int idx;
+#else
+OpenRISCCPU *cpu = env_archcpu(env);
 #endif
 
+/* Handle user accessible SPRs first.  */
 switch (spr) {
+case TO_SPR(0, 20): /* FPCSR */
+return env->fpcsr;
+}
+
+if (is_user(env)) {
+raise_exception(cpu, EXCP_ILLEGAL);
+}
+
 #ifndef CONFIG_USER_ONLY
+switch (spr) {
 case TO_SPR(0, 0): /* VR */
 return env->vr;
 
@@ -324,11 +352,8 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env, 
target_ulong rd,
 cpu_openrisc_count_update(cpu);
 qemu_mutex_unlock_iothread();
 return cpu_openrisc_count_get(cpu);
-#endif
-
-case TO_SPR(0, 20): /* FPCSR */
-return env->fpcsr;
 }
+#endif
 
 /* for rd is passed in, if rd unchanged, just keep it back.  */
 return rd;
diff --git a/target/openrisc/translate.c b/target/openrisc/translate.c
index 76e53c78d4..43ba0cc1ad 100644
--- a/target/openrisc/translate.c
+++ b/target/openrisc/translate.c
@@ -819,45 +819,12 @@ static bool trans_l_xori(DisasContext *dc, arg_rri *a)
 
 static bool trans_l_mfspr(DisasContext *dc, arg_l_mfspr *a)
 {
-check_r0_write(dc, a->d);
-
-if (is_user(dc)) {
-gen_illegal_exception(dc);
-} else {
-TCGv spr = tcg_temp_new();
-
-if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
-gen_io_start();
-if (dc->delayed_branch) {
-tcg_gen_mov_tl(cpu_pc, jmp_pc);
-tcg_gen_discard_tl(jmp_pc);
-} else {
-tcg_gen_movi_tl(cpu_pc, dc->base.pc_next + 4);
-}
-dc->base.is_jmp = DISAS_EXIT;
-}
+TCGv spr = tcg_temp_new();
 
-tcg_gen_ori_tl(spr, cpu_R(dc, a->a), a->k);
-gen_helper_mfspr(cpu_R(dc, a->d), cpu_env, cpu_R(dc, a->d), spr);
-}
-return true;
-}
-
-static bool trans_l_mtspr(DisasContext *dc, arg_l_mtspr *a)
-{
-if (is_user(dc)) {
-gen_illegal_exception(dc);
-} else {
-TCGv spr;
+check_r0_write(dc, a->d);
 
-if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
-gen_io_start();
-}
-/* For SR, we will need to exit the TB to recognize the new
- * exception state.  For NPC, in theory this counts as a branch
- * (although the SPR only exists for use by an ICE).  Save all
- * of the cpu state first, allowing it to be overwritten.
- */
+if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
+gen_io_start();
 if (dc->delayed_branch) {
 tcg_gen_mov_tl(cpu_pc, jmp_pc);
 tcg_gen_discard_tl(jmp_pc);
@@ -865,11 +832,36 @@ static bool trans_l_mtspr(DisasContext *dc, arg_l_mtspr 
*a)
 tcg_gen_movi_tl(cpu_pc, dc->base.pc_next + 4);
 }
 dc->

Re: [PATCH] scripts/coverity-scan: Add xtensa and openrisc components

2023-05-05 Thread Stafford Horne
On Thu, May 04, 2023 at 02:45:26PM +0100, Peter Maydell wrote:
> We have two target architectures which don't have Coverity components
> defined for them: xtensa and openrisc. Add them.
> 
> Signed-off-by: Peter Maydell 
> ---
> As usual with coverity components, these will need to be added
> manually via the scanner UI, since it has no import-from-file...
> 
>  scripts/coverity-scan/COMPONENTS.md | 6 ++
>  1 file changed, 6 insertions(+)
> 
> diff --git a/scripts/coverity-scan/COMPONENTS.md 
> b/scripts/coverity-scan/COMPONENTS.md
> index 7c48e0f1d21..add7c5a279c 100644
> --- a/scripts/coverity-scan/COMPONENTS.md
> +++ b/scripts/coverity-scan/COMPONENTS.md
> @@ -143,3 +143,9 @@ loongarch
>  
>  riscv
>~ 
> (/qemu)?((/include)?/hw/riscv/.*|/target/riscv/.*|/hw/.*/(riscv_|ibex_|sifive_).*)
> +
> +openrisc
> +  ~ (/qemu)?((/include)?/hw/openrisc/.*|/target/openrisc/.*)

This looks good to me for OpenRISC.  Where can we view the coverity reports?

  Is it this?: https://scan.coverity.com/projects/378

Acked-by: Stafford Horne 

> +xtensa
> +  ~ (/qemu)?((/include)?/hw/xtensa/.*|/target/xtensa/.*)



Re: [PATCH 3/3] target/openrisc: Setup FPU for detecting tininess before rounding

2023-05-03 Thread Stafford Horne
On Wed, May 03, 2023 at 10:41:42AM +0100, Richard Henderson wrote:
> On 5/3/23 10:14, Stafford Horne wrote:
> > > > +set_default_nan_mode(1, >env.fp_status);
> > > > +set_float_detect_tininess(float_tininess_before_rounding,
> > > > +  >env.fp_status);
> > > 
> > > You don't mention the nan change in the commit message.
> > 
> > Right, and I am not sure I need it.  Let me remove it and run tests again.  
> > I
> > was just adding it as a few other architectures did who set
> > float_tininess_before_rounding.
> 
> What that does is *not* propagate NaN payloads from (some) input to the
> output.  This is certainly true of RISC-V, which specifies this in their
> architecture manual.  OpenRISC does not specify any NaN behaviour at all.

Thanks, that is what I also gathered from reading up on it.

> It's not a bad choice, really, and it almost certainly simplifies the design
> of the FPU, as you can do NaN propagation and silencing in one step.

Right, it makes sense to optimize.  It doesn't look like any of our FPU
implementation do that at the moment.

I will check with bandvig who implemented the FPU to understand his thought on
this.  It at least deserves to be discussed how nan payload is to be handled in
the architecture spec.

-Stafford



Re: [PATCH 3/3] target/openrisc: Setup FPU for detecting tininess before rounding

2023-05-03 Thread Stafford Horne
On Wed, May 03, 2023 at 08:37:31AM +0100, Richard Henderson wrote:
> On 5/2/23 19:57, Stafford Horne wrote:
> > OpenRISC defines tininess to be detected before rounding.  Setup qemu to
> > obey this.
> > 
> > Signed-off-by: Stafford Horne 
> > ---
> >   target/openrisc/cpu.c | 5 +
> >   1 file changed, 5 insertions(+)
> > 
> > diff --git a/target/openrisc/cpu.c b/target/openrisc/cpu.c
> > index 0ce4f796fa..cdbff26fb5 100644
> > --- a/target/openrisc/cpu.c
> > +++ b/target/openrisc/cpu.c
> > @@ -22,6 +22,7 @@
> >   #include "qemu/qemu-print.h"
> >   #include "cpu.h"
> >   #include "exec/exec-all.h"
> > +#include "fpu/softfloat-helpers.h"
> >   #include "tcg/tcg.h"
> >   static void openrisc_cpu_set_pc(CPUState *cs, vaddr value)
> > @@ -90,6 +91,10 @@ static void openrisc_cpu_reset_hold(Object *obj)
> >   s->exception_index = -1;
> >   cpu_set_fpcsr(>env, 0);
> > +set_default_nan_mode(1, >env.fp_status);
> > +set_float_detect_tininess(float_tininess_before_rounding,
> > +  >env.fp_status);
> 
> You don't mention the nan change in the commit message.

Right, and I am not sure I need it.  Let me remove it and run tests again.  I
was just adding it as a few other architectures did who set
float_tininess_before_rounding.

Will clean this up.



Re: [PATCH 2/3] target/openrisc: Set PC to cpu state on FPU exception

2023-05-03 Thread Stafford Horne
On Wed, May 03, 2023 at 08:36:13AM +0100, Richard Henderson wrote:
> On 5/2/23 19:57, Stafford Horne wrote:
> > @@ -55,6 +56,9 @@ void HELPER(update_fpcsr)(CPUOpenRISCState *env)
> >   if (tmp) {
> >   env->fpcsr |= tmp;
> >   if (env->fpcsr & FPCSR_FPEE) {
> > +CPUState *cs = env_cpu(env);
> > +
> > +cpu_restore_state(cs, GETPC());
> >   helper_exception(env, EXCP_FPE);
> 
> Better to mirror do_range().

OK.



Re: [PATCH 1/3] target/openrisc: Allow fpcsr access in user mode

2023-05-03 Thread Stafford Horne
On Tue, May 02, 2023 at 07:57:29PM +0100, Stafford Horne wrote:
> As per OpenRISC spec 1.4 FPCSR can be read and written in user mode.
> 
> Update mtspr and mfspr helpers to support this by moving the is_user
> check into the helper.
> 
> There is a logic change here to no longer throw an illegal instruction
> exception when executing mtspr/mfspr in user mode.  The illegal
> instruction exception is not part of the spec, so this should be OK.

This is wrong, I considered doing it but left the exception in (moved to the
helper).  I will remove this bit of the commit messages in the next version.
But it is something we could consider doing.

Conversely, the architecture pec should be more clear as to what happens when
mfspr/mtspr privileges are violated.

-Stafford

> Link: 
> https://raw.githubusercontent.com/openrisc/doc/master/openrisc-arch-1.4-rev0.pdf
> Signed-off-by: Stafford Horne 
> ---
>  target/openrisc/sys_helper.c | 45 +-
>  target/openrisc/translate.c  | 72 
>  2 files changed, 67 insertions(+), 50 deletions(-)
> 
> diff --git a/target/openrisc/sys_helper.c b/target/openrisc/sys_helper.c
> index ec145960e3..8a0259c710 100644
> --- a/target/openrisc/sys_helper.c
> +++ b/target/openrisc/sys_helper.c
> @@ -29,17 +29,37 @@
>  
>  #define TO_SPR(group, number) (((group) << 11) + (number))
>  
> +static inline bool is_user(CPUOpenRISCState *env)
> +{
> +#ifdef CONFIG_USER_ONLY
> +return true;
> +#else
> +return (env->sr & SR_SM) == 0;
> +#endif
> +}
> +
>  void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong spr, target_ulong rb)
>  {
> -#ifndef CONFIG_USER_ONLY
>  OpenRISCCPU *cpu = env_archcpu(env);
> +#ifndef CONFIG_USER_ONLY
>  CPUState *cs = env_cpu(env);
>  target_ulong mr;
>  int idx;
>  #endif
>  
> +/* Handle user accessible SPRs first.  */
>  switch (spr) {
> +case TO_SPR(0, 20): /* FPCSR */
> +cpu_set_fpcsr(env, rb);
> +return;
> +}
> +
> +if (is_user(env)) {
> +raise_exception(cpu, EXCP_ILLEGAL);
> +}
> +
>  #ifndef CONFIG_USER_ONLY
> +switch (spr) {
>  case TO_SPR(0, 11): /* EVBAR */
>  env->evbar = rb;
>  break;
> @@ -187,12 +207,8 @@ void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong 
> spr, target_ulong rb)
>  cpu_openrisc_timer_update(cpu);
>  qemu_mutex_unlock_iothread();
>  break;
> -#endif
> -
> -case TO_SPR(0, 20): /* FPCSR */
> -cpu_set_fpcsr(env, rb);
> -break;
>  }
> +#endif
>  }
>  
>  target_ulong HELPER(mfspr)(CPUOpenRISCState *env, target_ulong rd,
> @@ -204,10 +220,22 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env, 
> target_ulong rd,
>  OpenRISCCPU *cpu = env_archcpu(env);
>  CPUState *cs = env_cpu(env);
>  int idx;
> +#else
> +OpenRISCCPU *cpu = env_archcpu(env);
>  #endif
>  
> +/* Handle user accessible SPRs first.  */
>  switch (spr) {
> +case TO_SPR(0, 20): /* FPCSR */
> +return env->fpcsr;
> +}
> +
> +if (is_user(env)) {
> +raise_exception(cpu, EXCP_ILLEGAL);
> +}
> +
>  #ifndef CONFIG_USER_ONLY
> +switch (spr) {
>  case TO_SPR(0, 0): /* VR */
>  return env->vr;
>  
> @@ -324,11 +352,8 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env, 
> target_ulong rd,
>  cpu_openrisc_count_update(cpu);
>  qemu_mutex_unlock_iothread();
>  return cpu_openrisc_count_get(cpu);
> -#endif
> -
> -case TO_SPR(0, 20): /* FPCSR */
> -return env->fpcsr;
>  }
> +#endif
>  
>  /* for rd is passed in, if rd unchanged, just keep it back.  */
>  return rd;
> diff --git a/target/openrisc/translate.c b/target/openrisc/translate.c
> index 76e53c78d4..43ba0cc1ad 100644
> --- a/target/openrisc/translate.c
> +++ b/target/openrisc/translate.c
> @@ -819,45 +819,12 @@ static bool trans_l_xori(DisasContext *dc, arg_rri *a)
>  
>  static bool trans_l_mfspr(DisasContext *dc, arg_l_mfspr *a)
>  {
> -check_r0_write(dc, a->d);
> -
> -if (is_user(dc)) {
> -gen_illegal_exception(dc);
> -} else {
> -TCGv spr = tcg_temp_new();
> -
> -if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
> -gen_io_start();
> -if (dc->delayed_branch) {
> -tcg_gen_mov_tl(cpu_pc, jmp_pc);
> -tcg_gen_discard_tl(jmp_pc);
> -} else {
> -tcg_gen_movi_tl(cpu_pc, dc->base.pc_next + 4);
> -}
> -dc->base.is_jmp = DISAS_EXIT;
> - 

[PATCH 2/3] target/openrisc: Set PC to cpu state on FPU exception

2023-05-02 Thread Stafford Horne
Store the PC to ensure the correct value can be read in the exception
handler.

Signed-off-by: Stafford Horne 
---
 target/openrisc/fpu_helper.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/target/openrisc/fpu_helper.c b/target/openrisc/fpu_helper.c
index f9e34fa2cc..1feebb9ac7 100644
--- a/target/openrisc/fpu_helper.c
+++ b/target/openrisc/fpu_helper.c
@@ -20,6 +20,7 @@
 
 #include "qemu/osdep.h"
 #include "cpu.h"
+#include "exec/exec-all.h"
 #include "exec/helper-proto.h"
 #include "exception.h"
 #include "fpu/softfloat.h"
@@ -55,6 +56,9 @@ void HELPER(update_fpcsr)(CPUOpenRISCState *env)
 if (tmp) {
 env->fpcsr |= tmp;
 if (env->fpcsr & FPCSR_FPEE) {
+CPUState *cs = env_cpu(env);
+
+cpu_restore_state(cs, GETPC());
 helper_exception(env, EXCP_FPE);
 }
 }
-- 
2.39.1




[PATCH 1/3] target/openrisc: Allow fpcsr access in user mode

2023-05-02 Thread Stafford Horne
As per OpenRISC spec 1.4 FPCSR can be read and written in user mode.

Update mtspr and mfspr helpers to support this by moving the is_user
check into the helper.

There is a logic change here to no longer throw an illegal instruction
exception when executing mtspr/mfspr in user mode.  The illegal
instruction exception is not part of the spec, so this should be OK.

Link: 
https://raw.githubusercontent.com/openrisc/doc/master/openrisc-arch-1.4-rev0.pdf
Signed-off-by: Stafford Horne 
---
 target/openrisc/sys_helper.c | 45 +-
 target/openrisc/translate.c  | 72 
 2 files changed, 67 insertions(+), 50 deletions(-)

diff --git a/target/openrisc/sys_helper.c b/target/openrisc/sys_helper.c
index ec145960e3..8a0259c710 100644
--- a/target/openrisc/sys_helper.c
+++ b/target/openrisc/sys_helper.c
@@ -29,17 +29,37 @@
 
 #define TO_SPR(group, number) (((group) << 11) + (number))
 
+static inline bool is_user(CPUOpenRISCState *env)
+{
+#ifdef CONFIG_USER_ONLY
+return true;
+#else
+return (env->sr & SR_SM) == 0;
+#endif
+}
+
 void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong spr, target_ulong rb)
 {
-#ifndef CONFIG_USER_ONLY
 OpenRISCCPU *cpu = env_archcpu(env);
+#ifndef CONFIG_USER_ONLY
 CPUState *cs = env_cpu(env);
 target_ulong mr;
 int idx;
 #endif
 
+/* Handle user accessible SPRs first.  */
 switch (spr) {
+case TO_SPR(0, 20): /* FPCSR */
+cpu_set_fpcsr(env, rb);
+return;
+}
+
+if (is_user(env)) {
+raise_exception(cpu, EXCP_ILLEGAL);
+}
+
 #ifndef CONFIG_USER_ONLY
+switch (spr) {
 case TO_SPR(0, 11): /* EVBAR */
 env->evbar = rb;
 break;
@@ -187,12 +207,8 @@ void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong 
spr, target_ulong rb)
 cpu_openrisc_timer_update(cpu);
 qemu_mutex_unlock_iothread();
 break;
-#endif
-
-case TO_SPR(0, 20): /* FPCSR */
-cpu_set_fpcsr(env, rb);
-break;
 }
+#endif
 }
 
 target_ulong HELPER(mfspr)(CPUOpenRISCState *env, target_ulong rd,
@@ -204,10 +220,22 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env, 
target_ulong rd,
 OpenRISCCPU *cpu = env_archcpu(env);
 CPUState *cs = env_cpu(env);
 int idx;
+#else
+OpenRISCCPU *cpu = env_archcpu(env);
 #endif
 
+/* Handle user accessible SPRs first.  */
 switch (spr) {
+case TO_SPR(0, 20): /* FPCSR */
+return env->fpcsr;
+}
+
+if (is_user(env)) {
+raise_exception(cpu, EXCP_ILLEGAL);
+}
+
 #ifndef CONFIG_USER_ONLY
+switch (spr) {
 case TO_SPR(0, 0): /* VR */
 return env->vr;
 
@@ -324,11 +352,8 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env, 
target_ulong rd,
 cpu_openrisc_count_update(cpu);
 qemu_mutex_unlock_iothread();
 return cpu_openrisc_count_get(cpu);
-#endif
-
-case TO_SPR(0, 20): /* FPCSR */
-return env->fpcsr;
 }
+#endif
 
 /* for rd is passed in, if rd unchanged, just keep it back.  */
 return rd;
diff --git a/target/openrisc/translate.c b/target/openrisc/translate.c
index 76e53c78d4..43ba0cc1ad 100644
--- a/target/openrisc/translate.c
+++ b/target/openrisc/translate.c
@@ -819,45 +819,12 @@ static bool trans_l_xori(DisasContext *dc, arg_rri *a)
 
 static bool trans_l_mfspr(DisasContext *dc, arg_l_mfspr *a)
 {
-check_r0_write(dc, a->d);
-
-if (is_user(dc)) {
-gen_illegal_exception(dc);
-} else {
-TCGv spr = tcg_temp_new();
-
-if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
-gen_io_start();
-if (dc->delayed_branch) {
-tcg_gen_mov_tl(cpu_pc, jmp_pc);
-tcg_gen_discard_tl(jmp_pc);
-} else {
-tcg_gen_movi_tl(cpu_pc, dc->base.pc_next + 4);
-}
-dc->base.is_jmp = DISAS_EXIT;
-}
+TCGv spr = tcg_temp_new();
 
-tcg_gen_ori_tl(spr, cpu_R(dc, a->a), a->k);
-gen_helper_mfspr(cpu_R(dc, a->d), cpu_env, cpu_R(dc, a->d), spr);
-}
-return true;
-}
-
-static bool trans_l_mtspr(DisasContext *dc, arg_l_mtspr *a)
-{
-if (is_user(dc)) {
-gen_illegal_exception(dc);
-} else {
-TCGv spr;
+check_r0_write(dc, a->d);
 
-if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
-gen_io_start();
-}
-/* For SR, we will need to exit the TB to recognize the new
- * exception state.  For NPC, in theory this counts as a branch
- * (although the SPR only exists for use by an ICE).  Save all
- * of the cpu state first, allowing it to be overwritten.
- */
+if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
+gen_io_start();
 if (dc->delayed_branch) {
 tcg_gen_mov_tl(cpu_pc, jmp_pc);
 tcg_gen_discard_tl(jmp_pc);
@@ -865,11 +832,36 @@ static bool trans_l_mtspr(DisasContext *dc

[PATCH 3/3] target/openrisc: Setup FPU for detecting tininess before rounding

2023-05-02 Thread Stafford Horne
OpenRISC defines tininess to be detected before rounding.  Setup qemu to
obey this.

Signed-off-by: Stafford Horne 
---
 target/openrisc/cpu.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/target/openrisc/cpu.c b/target/openrisc/cpu.c
index 0ce4f796fa..cdbff26fb5 100644
--- a/target/openrisc/cpu.c
+++ b/target/openrisc/cpu.c
@@ -22,6 +22,7 @@
 #include "qemu/qemu-print.h"
 #include "cpu.h"
 #include "exec/exec-all.h"
+#include "fpu/softfloat-helpers.h"
 #include "tcg/tcg.h"
 
 static void openrisc_cpu_set_pc(CPUState *cs, vaddr value)
@@ -90,6 +91,10 @@ static void openrisc_cpu_reset_hold(Object *obj)
 s->exception_index = -1;
 cpu_set_fpcsr(>env, 0);
 
+set_default_nan_mode(1, >env.fp_status);
+set_float_detect_tininess(float_tininess_before_rounding,
+  >env.fp_status);
+
 #ifndef CONFIG_USER_ONLY
 cpu->env.picmr = 0x;
 cpu->env.picsr = 0x;
-- 
2.39.1




[PATCH 0/3] OpenRISC updates for user space FPU

2023-05-02 Thread Stafford Horne
This series adds support for the FPU related architecture changes defined in
architecture spec revision v1.4.

 - https://openrisc.io/revisions/r1.4

In summary the architecture changes are:

 - Change FPCSR SPR permissions to allow for reading and writing from user
   space.
 - Clarify that FPU underflow detection is done by detecting tininess before
   rounding.

Previous to this series FPCSR reads and writes from user-mode in QEMU would
throw an illegal argument exception.  The proper behavior should have been to
treat these operations as no-ops as the cpu implementations do.  As mentioned
series changes FPCSR read/write to follow the spec.

The series has been tested with the FPU support added in glibc test suite and
all math tests are passing.

Stafford Horne (3):
  target/openrisc: Allow fpcsr access in user mode
  target/openrisc: Set PC to cpu state on FPU exception
  target/openrisc: Setup FPU for detecting tininess before rounding

 target/openrisc/cpu.c|  5 +++
 target/openrisc/fpu_helper.c |  4 ++
 target/openrisc/sys_helper.c | 45 +-
 target/openrisc/translate.c  | 72 
 4 files changed, 76 insertions(+), 50 deletions(-)

-- 
2.39.1




Re: [PATCH v3 6/8] openrisc: re-randomize rng-seed on reboot

2022-10-15 Thread Stafford Horne
Hi Jason,

On Thu, Oct 13, 2022 at 08:16:51PM -0600, Jason A. Donenfeld wrote:
> When the system reboots, the rng-seed that the FDT has should be
> re-randomized, so that the new boot gets a new seed. Since the FDT is in
> the ROM region at this point, we add a hook right after the ROM has been
> added, so that we have a pointer to that copy of the FDT.

This looks good to me.

Acked-by: Stafford Horne 

> Cc: Stafford Horne 
> Signed-off-by: Jason A. Donenfeld 
> ---
>  hw/openrisc/boot.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/hw/openrisc/boot.c b/hw/openrisc/boot.c
> index 128ccbcba2..007e80cd5a 100644
> --- a/hw/openrisc/boot.c
> +++ b/hw/openrisc/boot.c
> @@ -14,6 +14,7 @@
>  #include "hw/openrisc/boot.h"
>  #include "sysemu/device_tree.h"
>  #include "sysemu/qtest.h"
> +#include "sysemu/reset.h"
>  
>  #include 
>  
> @@ -111,6 +112,8 @@ uint32_t openrisc_load_fdt(void *fdt, hwaddr load_start,
>  
>  rom_add_blob_fixed_as("fdt", fdt, fdtsize, fdt_addr,
>_space_memory);
> +qemu_register_reset_nosnapshotload(qemu_fdt_randomize_seeds,
> +rom_ptr_for_as(_space_memory, fdt_addr, 
> fdtsize));
>  
>  return fdt_addr;
>  }
> -- 
> 2.37.3
> 



[PULL 09/11] target/openrisc: Interrupt handling fixes

2022-09-04 Thread Stafford Horne
When running SMP systems we sometimes were seeing lockups where
IPI interrupts were being raised by never handled.

This looks to be caused by 2 issues in the openrisc interrupt handling
logic.

 1. After clearing an interrupt the openrisc_cpu_set_irq handler will
always clear PICSR.  This is not correct as masked interrupts
should still be visible in PICSR.
 2. After setting PICMR (mask register) and exposed interrupts should
cause an interrupt to be raised.  This was not being done so add it.

This patch fixes both issues.

Reviewed-by: Richard Henderson 
Signed-off-by: Stafford Horne 
---
 target/openrisc/cpu.c| 1 -
 target/openrisc/sys_helper.c | 7 +++
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/target/openrisc/cpu.c b/target/openrisc/cpu.c
index 41d1b2a24a..cb9f35f408 100644
--- a/target/openrisc/cpu.c
+++ b/target/openrisc/cpu.c
@@ -98,7 +98,6 @@ static void openrisc_cpu_set_irq(void *opaque, int irq, int 
level)
 cpu_interrupt(cs, CPU_INTERRUPT_HARD);
 } else {
 cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
-cpu->env.picsr = 0;
 }
 }
 #endif
diff --git a/target/openrisc/sys_helper.c b/target/openrisc/sys_helper.c
index da88ad9e77..09b3c97d7c 100644
--- a/target/openrisc/sys_helper.c
+++ b/target/openrisc/sys_helper.c
@@ -139,6 +139,13 @@ void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong 
spr, target_ulong rb)
 break;
 case TO_SPR(9, 0):  /* PICMR */
 env->picmr = rb;
+qemu_mutex_lock_iothread();
+if (env->picsr & env->picmr) {
+cpu_interrupt(cs, CPU_INTERRUPT_HARD);
+} else {
+cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
+}
+qemu_mutex_unlock_iothread();
 break;
 case TO_SPR(9, 2):  /* PICSR */
 env->picsr &= ~rb;
-- 
2.37.2




[PULL 11/11] docs/system: openrisc: Add OpenRISC documentation

2022-09-04 Thread Stafford Horne
Reviewed-by: Richard Henderson 
Signed-off-by: Stafford Horne 
---
 docs/system/openrisc/cpu-features.rst | 15 ++
 docs/system/openrisc/emulation.rst| 17 +++
 docs/system/openrisc/or1k-sim.rst | 43 
 docs/system/openrisc/virt.rst | 50 +++
 docs/system/target-openrisc.rst   | 71 +++
 docs/system/targets.rst   |  1 +
 6 files changed, 197 insertions(+)
 create mode 100644 docs/system/openrisc/cpu-features.rst
 create mode 100644 docs/system/openrisc/emulation.rst
 create mode 100644 docs/system/openrisc/or1k-sim.rst
 create mode 100644 docs/system/openrisc/virt.rst
 create mode 100644 docs/system/target-openrisc.rst

diff --git a/docs/system/openrisc/cpu-features.rst 
b/docs/system/openrisc/cpu-features.rst
new file mode 100644
index 00..aeb65e22ff
--- /dev/null
+++ b/docs/system/openrisc/cpu-features.rst
@@ -0,0 +1,15 @@
+CPU Features
+
+
+The QEMU emulation of the OpenRISC architecture provides following built in
+features.
+
+- Shadow GPRs
+- MMU TLB with 128 entries, 1 way
+- Power Management (PM)
+- Programmable Interrupt Controller (PIC)
+- Tick Timer
+
+These features are on by default and the presence can be confirmed by checking
+the contents of the Unit Presence Register (``UPR``) and CPU Configuration
+Register (``CPUCFGR``).
diff --git a/docs/system/openrisc/emulation.rst 
b/docs/system/openrisc/emulation.rst
new file mode 100644
index 00..0af898ab20
--- /dev/null
+++ b/docs/system/openrisc/emulation.rst
@@ -0,0 +1,17 @@
+OpenRISC 1000 CPU architecture support
+==
+
+QEMU's TCG emulation includes support for the OpenRISC or1200 implementation of
+the OpenRISC 1000 cpu architecture.
+
+The or1200 cpu also has support for the following instruction subsets:
+
+- ORBIS32 (OpenRISC Basic Instruction Set)
+- ORFPX32 (OpenRISC Floating-Point eXtension)
+
+In addition to the instruction subsets the QEMU TCG emulation also has support
+for most Class II (optional) instructions.
+
+For information on all OpenRISC instructions please refer to the latest
+architecture manual available on the OpenRISC website in the
+`OpenRISC Architecture <https://openrisc.io/architecture>`_ section.
diff --git a/docs/system/openrisc/or1k-sim.rst 
b/docs/system/openrisc/or1k-sim.rst
new file mode 100644
index 00..ef10439737
--- /dev/null
+++ b/docs/system/openrisc/or1k-sim.rst
@@ -0,0 +1,43 @@
+Or1ksim board
+=
+
+The QEMU Or1ksim machine emulates the standard OpenRISC board simulator which 
is
+also the standard SoC configuration.
+
+Supported devices
+-
+
+ * 16550A UART
+ * ETHOC Ethernet controller
+ * SMP (OpenRISC multicore using ompic)
+
+Boot options
+
+
+The Or1ksim machine can be started using the ``-kernel`` and ``-initrd`` 
options
+to load a Linux kernel and optional disk image.
+
+.. code-block:: bash
+
+  $ qemu-system-or1k -cpu or1220 -M or1k-sim -nographic \
+-kernel vmlinux \
+-initrd initramfs.cpio.gz \
+-m 128
+
+Linux guest kernel configuration
+""""""""""""""""""""""""""""""""
+
+The 'or1ksim_defconfig' for Linux openrisc kernels includes the right
+drivers for the or1ksim machine.  If you would like to run an SMP system
+choose the 'simple_smp_defconfig' config.
+
+Hardware configuration information
+""""""""""""""""""""""""""""""""""
+
+The ``or1k-sim`` board automatically generates a device tree blob ("dtb")
+which it passes to the guest. This provides information about the
+addresses, interrupt lines and other configuration of the various devices
+in the system.
+
+The location of the DTB will be passed in register ``r3`` to the guest 
operating
+system.
diff --git a/docs/system/openrisc/virt.rst b/docs/system/openrisc/virt.rst
new file mode 100644
index 00..2fe61ac942
--- /dev/null
+++ b/docs/system/openrisc/virt.rst
@@ -0,0 +1,50 @@
+'virt' generic virtual platform
+===
+
+The ``virt`` board is a platform which does not correspond to any
+real hardware; it is designed for use in virtual machines.
+It is the recommended board type if you simply want to run
+a guest such as Linux and do not care about reproducing the
+idiosyncrasies and limitations of a particular bit of real-world
+hardware.
+
+Supported devices
+-
+
+ * PCI/PCIe devices
+ * 8 virtio-mmio transport devices
+ * 16550A UART
+ * Goldfish RTC
+ * SiFive Test device for poweroff and reboot
+ * SMP (OpenRISC multicore using ompic)
+
+Boot options
+
+
+The virt machine can be started using the ``-kernel`` a

[PULL 07/11] target/openrisc: Add interrupted CPU to log

2022-09-04 Thread Stafford Horne
When we are tracing it's helpful to know which CPU's are getting
interrupted, add that detail to the log line.

Reviewed-by: Richard Henderson 
Signed-off-by: Stafford Horne 
---
 target/openrisc/interrupt.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/target/openrisc/interrupt.c b/target/openrisc/interrupt.c
index e5724f5371..c31c6f12c4 100644
--- a/target/openrisc/interrupt.c
+++ b/target/openrisc/interrupt.c
@@ -83,7 +83,9 @@ void openrisc_cpu_do_interrupt(CPUState *cs)
 [EXCP_TRAP] = "TRAP",
 };
 
-qemu_log_mask(CPU_LOG_INT, "INT: %s\n", int_name[exception]);
+qemu_log_mask(CPU_LOG_INT, "CPU: %d INT: %s\n",
+  cs->cpu_index,
+  int_name[exception]);
 
 hwaddr vect_pc = exception << 8;
 if (env->cpucfgr & CPUCFGR_EVBARP) {
-- 
2.37.2




[PULL 05/11] hw/openrisc: Add PCI bus support to virt

2022-09-04 Thread Stafford Horne
This is mostly borrowed from xtensa and riscv as examples.  The
create_pcie_irq_map swizzle function is almost and exact copy
but here we use a single cell interrupt, possibly we can make
this generic.

Signed-off-by: Stafford Horne 
---
 hw/openrisc/Kconfig |   3 +
 hw/openrisc/virt.c  | 160 ++--
 2 files changed, 157 insertions(+), 6 deletions(-)

diff --git a/hw/openrisc/Kconfig b/hw/openrisc/Kconfig
index 202134668e..97af258b55 100644
--- a/hw/openrisc/Kconfig
+++ b/hw/openrisc/Kconfig
@@ -7,8 +7,11 @@ config OR1K_SIM
 
 config OR1K_VIRT
 bool
+imply PCI_DEVICES
 imply VIRTIO_VGA
 imply TEST_DEVICES
+select PCI
+select PCI_EXPRESS_GENERIC_BRIDGE
 select GOLDFISH_RTC
 select SERIAL
 select SIFIVE_TEST
diff --git a/hw/openrisc/virt.c b/hw/openrisc/virt.c
index 54f2732a6b..9a78234a28 100644
--- a/hw/openrisc/virt.c
+++ b/hw/openrisc/virt.c
@@ -17,6 +17,8 @@
 #include "hw/core/split-irq.h"
 #include "hw/openrisc/boot.h"
 #include "hw/misc/sifive_test.h"
+#include "hw/pci/pci.h"
+#include "hw/pci-host/gpex.h"
 #include "hw/qdev-properties.h"
 #include "hw/rtc/goldfish_rtc.h"
 #include "hw/sysbus.h"
@@ -47,6 +49,9 @@ typedef struct OR1KVirtState {
 
 enum {
 VIRT_DRAM,
+VIRT_ECAM,
+VIRT_MMIO,
+VIRT_PIO,
 VIRT_TEST,
 VIRT_RTC,
 VIRT_VIRTIO,
@@ -60,6 +65,7 @@ enum {
 VIRT_RTC_IRQ = 3,
 VIRT_VIRTIO_IRQ = 4, /* to 12 */
 VIRTIO_COUNT = 8,
+VIRT_PCI_IRQ_BASE = 13, /* to 17 */
 };
 
 static const struct MemmapEntry {
@@ -72,6 +78,9 @@ static const struct MemmapEntry {
 [VIRT_RTC] =   { 0x96005000, 0x1000 },
 [VIRT_VIRTIO] ={ 0x9700, 0x1000 },
 [VIRT_OMPIC] = { 0x9800, VIRT_CPUS_MAX * 8 },
+[VIRT_ECAM] =  { 0x9e00,  0x100 },
+[VIRT_PIO] =   { 0x9f00,  0x100 },
+[VIRT_MMIO] =  { 0xa000, 0x1000 },
 };
 
 static struct openrisc_boot_info {
@@ -115,12 +124,12 @@ static qemu_irq get_per_cpu_irq(OpenRISCCPU *cpus[], int 
num_cpus, int irq_pin)
 static void openrisc_create_fdt(OR1KVirtState *state,
 const struct MemmapEntry *memmap,
 int num_cpus, uint64_t mem_size,
-const char *cmdline)
+const char *cmdline,
+int32_t *pic_phandle)
 {
 void *fdt;
 int cpu;
 char *nodename;
-int pic_ph;
 
 fdt = state->fdt = create_device_tree(>fdt_size);
 if (!fdt) {
@@ -163,14 +172,14 @@ static void openrisc_create_fdt(OR1KVirtState *state,
 
 nodename = (char *)"/pic";
 qemu_fdt_add_subnode(fdt, nodename);
-pic_ph = qemu_fdt_alloc_phandle(fdt);
+*pic_phandle = qemu_fdt_alloc_phandle(fdt);
 qemu_fdt_setprop_string(fdt, nodename, "compatible",
 "opencores,or1k-pic-level");
 qemu_fdt_setprop_cell(fdt, nodename, "#interrupt-cells", 1);
 qemu_fdt_setprop(fdt, nodename, "interrupt-controller", NULL, 0);
-qemu_fdt_setprop_cell(fdt, nodename, "phandle", pic_ph);
+qemu_fdt_setprop_cell(fdt, nodename, "phandle", *pic_phandle);
 
-qemu_fdt_setprop_cell(fdt, "/", "interrupt-parent", pic_ph);
+qemu_fdt_setprop_cell(fdt, "/", "interrupt-parent", *pic_phandle);
 
 qemu_fdt_add_subnode(fdt, "/chosen");
 if (cmdline) {
@@ -275,6 +284,7 @@ static void openrisc_virt_test_init(OR1KVirtState *state, 
hwaddr base,
 g_free(nodename);
 
 }
+
 static void openrisc_virt_rtc_init(OR1KVirtState *state, hwaddr base,
hwaddr size, int num_cpus,
OpenRISCCPU *cpus[], int irq_pin)
@@ -296,6 +306,134 @@ static void openrisc_virt_rtc_init(OR1KVirtState *state, 
hwaddr base,
 g_free(nodename);
 
 }
+
+static void create_pcie_irq_map(void *fdt, char *nodename, int irq_base,
+uint32_t irqchip_phandle)
+{
+int pin, dev;
+uint32_t irq_map_stride = 0;
+uint32_t full_irq_map[GPEX_NUM_IRQS * GPEX_NUM_IRQS * 6] = {};
+uint32_t *irq_map = full_irq_map;
+
+/*
+ * This code creates a standard swizzle of interrupts such that
+ * each device's first interrupt is based on it's PCI_SLOT number.
+ * (See pci_swizzle_map_irq_fn())
+ *
+ * We only need one entry per interrupt in the table (not one per
+ * possible slot) seeing the interrupt-map-mask will allow the table
+ * to wrap to any number of devices.
+ */
+for (dev = 0; dev < GPEX_NUM_IRQS; dev++) {
+int devfn = dev << 3;
+
+for (pin = 0; pin < GPEX_NUM_IRQS; pin++) {
+int irq_nr = irq_base + ((pin + PCI_SLOT(devfn)) % GPEX_NUM_IRQS);
+  

[PULL 08/11] target/openrisc: Enable MTTCG

2022-09-04 Thread Stafford Horne
This patch enables multithread TCG for OpenRISC.  Since the or1k shared
syncrhonized timer can be updated from each vCPU via helpers we use a
mutex to synchronize updates.

Reviewed-by: Richard Henderson 
Signed-off-by: Stafford Horne 
---
 configs/targets/or1k-softmmu.mak | 1 +
 target/openrisc/cpu.h| 2 ++
 target/openrisc/sys_helper.c | 7 ++-
 3 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/configs/targets/or1k-softmmu.mak b/configs/targets/or1k-softmmu.mak
index 263e970870..432f855a30 100644
--- a/configs/targets/or1k-softmmu.mak
+++ b/configs/targets/or1k-softmmu.mak
@@ -1,3 +1,4 @@
 TARGET_ARCH=openrisc
+TARGET_SUPPORTS_MTTCG=y
 TARGET_BIG_ENDIAN=y
 TARGET_NEED_FDT=y
diff --git a/target/openrisc/cpu.h b/target/openrisc/cpu.h
index b9584f10d4..1d5efa5ca2 100644
--- a/target/openrisc/cpu.h
+++ b/target/openrisc/cpu.h
@@ -25,6 +25,8 @@
 #include "hw/core/cpu.h"
 #include "qom/object.h"
 
+#define TCG_GUEST_DEFAULT_MO (0)
+
 #define TYPE_OPENRISC_CPU "or1k-cpu"
 
 OBJECT_DECLARE_CPU_TYPE(OpenRISCCPU, OpenRISCCPUClass, OPENRISC_CPU)
diff --git a/target/openrisc/sys_helper.c b/target/openrisc/sys_helper.c
index 48674231e7..da88ad9e77 100644
--- a/target/openrisc/sys_helper.c
+++ b/target/openrisc/sys_helper.c
@@ -145,6 +145,7 @@ void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong spr, 
target_ulong rb)
 break;
 case TO_SPR(10, 0): /* TTMR */
 {
+qemu_mutex_lock_iothread();
 if ((env->ttmr & TTMR_M) ^ (rb & TTMR_M)) {
 switch (rb & TTMR_M) {
 case TIMER_NONE:
@@ -168,14 +169,16 @@ void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong 
spr, target_ulong rb)
 env->ttmr = rb & ~TTMR_IP;
 cs->interrupt_request &= ~CPU_INTERRUPT_TIMER;
 }
-
 cpu_openrisc_timer_update(cpu);
+qemu_mutex_unlock_iothread();
 }
 break;
 
 case TO_SPR(10, 1): /* TTCR */
+qemu_mutex_lock_iothread();
 cpu_openrisc_count_set(cpu, rb);
 cpu_openrisc_timer_update(cpu);
+qemu_mutex_unlock_iothread();
 break;
 #endif
 
@@ -303,7 +306,9 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env, 
target_ulong rd,
 return env->ttmr;
 
 case TO_SPR(10, 1): /* TTCR */
+qemu_mutex_lock_iothread();
 cpu_openrisc_count_update(cpu);
+qemu_mutex_unlock_iothread();
 return cpu_openrisc_count_get(cpu);
 #endif
 
-- 
2.37.2




[PULL 04/11] hw/openrisc: Add the OpenRISC virtual machine

2022-09-04 Thread Stafford Horne
This patch adds the OpenRISC virtual machine 'virt' for OpenRISC.  This
platform allows for a convenient CI platform for toolchain, software
ports and the OpenRISC linux kernel port.

Much of this has been sourced from the m68k and riscv virt platforms.

The platform provides:
 - OpenRISC SMP with up to 4 cpus
 - A virtio bus with up to 8 devices
 - Standard ns16550a serial
 - Goldfish RTC
 - SiFive TEST device for poweroff and reboot
 - Generated Device Tree to automatically configure the guest kernel

Signed-off-by: Stafford Horne 
---
 configs/devices/or1k-softmmu/default.mak |   1 +
 hw/openrisc/Kconfig  |   9 +
 hw/openrisc/meson.build  |   1 +
 hw/openrisc/virt.c   | 417 +++
 4 files changed, 428 insertions(+)
 create mode 100644 hw/openrisc/virt.c

diff --git a/configs/devices/or1k-softmmu/default.mak 
b/configs/devices/or1k-softmmu/default.mak
index 168101c39a..89c39e3123 100644
--- a/configs/devices/or1k-softmmu/default.mak
+++ b/configs/devices/or1k-softmmu/default.mak
@@ -3,3 +3,4 @@
 # Boards:
 #
 CONFIG_OR1K_SIM=y
+CONFIG_OR1K_VIRT=y
diff --git a/hw/openrisc/Kconfig b/hw/openrisc/Kconfig
index 8f284f3ba0..202134668e 100644
--- a/hw/openrisc/Kconfig
+++ b/hw/openrisc/Kconfig
@@ -4,3 +4,12 @@ config OR1K_SIM
 select OPENCORES_ETH
 select OMPIC
 select SPLIT_IRQ
+
+config OR1K_VIRT
+bool
+imply VIRTIO_VGA
+imply TEST_DEVICES
+select GOLDFISH_RTC
+select SERIAL
+select SIFIVE_TEST
+select VIRTIO_MMIO
diff --git a/hw/openrisc/meson.build b/hw/openrisc/meson.build
index ab563820c5..2dbc6365bb 100644
--- a/hw/openrisc/meson.build
+++ b/hw/openrisc/meson.build
@@ -2,5 +2,6 @@ openrisc_ss = ss.source_set()
 openrisc_ss.add(files('cputimer.c'))
 openrisc_ss.add(files('boot.c'))
 openrisc_ss.add(when: 'CONFIG_OR1K_SIM', if_true: [files('openrisc_sim.c'), 
fdt])
+openrisc_ss.add(when: 'CONFIG_OR1K_VIRT', if_true: [files('virt.c'), fdt])
 
 hw_arch += {'openrisc': openrisc_ss}
diff --git a/hw/openrisc/virt.c b/hw/openrisc/virt.c
new file mode 100644
index 00..54f2732a6b
--- /dev/null
+++ b/hw/openrisc/virt.c
@@ -0,0 +1,417 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * OpenRISC QEMU virtual machine.
+ *
+ * (c) 2022 Stafford Horne 
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/error-report.h"
+#include "qapi/error.h"
+#include "cpu.h"
+#include "exec/address-spaces.h"
+#include "hw/irq.h"
+#include "hw/boards.h"
+#include "hw/char/serial.h"
+#include "hw/core/split-irq.h"
+#include "hw/openrisc/boot.h"
+#include "hw/misc/sifive_test.h"
+#include "hw/qdev-properties.h"
+#include "hw/rtc/goldfish_rtc.h"
+#include "hw/sysbus.h"
+#include "hw/virtio/virtio-mmio.h"
+#include "sysemu/device_tree.h"
+#include "sysemu/sysemu.h"
+#include "sysemu/qtest.h"
+#include "sysemu/reset.h"
+
+#include 
+
+#define VIRT_CPUS_MAX 4
+#define VIRT_CLK_MHZ 2000
+
+#define TYPE_VIRT_MACHINE MACHINE_TYPE_NAME("virt")
+#define VIRT_MACHINE(obj) \
+OBJECT_CHECK(OR1KVirtState, (obj), TYPE_VIRT_MACHINE)
+
+typedef struct OR1KVirtState {
+/*< private >*/
+MachineState parent_obj;
+
+/*< public >*/
+void *fdt;
+int fdt_size;
+
+} OR1KVirtState;
+
+enum {
+VIRT_DRAM,
+VIRT_TEST,
+VIRT_RTC,
+VIRT_VIRTIO,
+VIRT_UART,
+VIRT_OMPIC,
+};
+
+enum {
+VIRT_OMPIC_IRQ = 1,
+VIRT_UART_IRQ = 2,
+VIRT_RTC_IRQ = 3,
+VIRT_VIRTIO_IRQ = 4, /* to 12 */
+VIRTIO_COUNT = 8,
+};
+
+static const struct MemmapEntry {
+hwaddr base;
+hwaddr size;
+} virt_memmap[] = {
+[VIRT_DRAM] =  { 0x,  0 },
+[VIRT_UART] =  { 0x9000,  0x100 },
+[VIRT_TEST] =  { 0x9600,0x8 },
+[VIRT_RTC] =   { 0x96005000, 0x1000 },
+[VIRT_VIRTIO] ={ 0x9700, 0x1000 },
+[VIRT_OMPIC] = { 0x9800, VIRT_CPUS_MAX * 8 },
+};
+
+static struct openrisc_boot_info {
+uint32_t bootstrap_pc;
+uint32_t fdt_addr;
+} boot_info;
+
+static void main_cpu_reset(void *opaque)
+{
+OpenRISCCPU *cpu = opaque;
+CPUState *cs = CPU(cpu);
+
+cpu_reset(CPU(cpu));
+
+cpu_set_pc(cs, boot_info.bootstrap_pc);
+cpu_set_gpr(>env, 3, boot_info.fdt_addr);
+}
+
+static qemu_irq get_cpu_irq(OpenRISCCPU *cpus[], int cpunum, int irq_pin)
+{
+return qdev_get_gpio_in_named(DEVICE(cpus[cpunum]), "IRQ", irq_pin);
+}
+
+static qemu_irq get_per_cpu_irq(OpenRISCCPU *cpus[], int num_cpus, int irq_pin)
+{
+int i;
+
+if (num_cpus > 1) {
+DeviceState *splitter = qdev_new(TYPE_SPLIT_IRQ);
+qdev_prop_set_uint32(splitter, "num-lines", num_cpus);
+qdev_realize_and_unref(splitter, NULL, _fatal);
+for (i = 0; i <

[PULL 06/11] hw/openrisc: Initialize timer time at startup

2022-09-04 Thread Stafford Horne
The last_clk time was initialized at zero, this means when we calculate
the first delta we will calculate 0 vs current time which could cause
unnecessary hops.

This patch moves timer initialization to the cpu reset.  There are two
resets registered here:

 1. Per cpu timer mask (ttmr) reset.
 2. Global cpu timer (last_clk and ttcr) reset, attached to the first
cpu only.

Reviewed-by: Richard Henderson 
Signed-off-by: Stafford Horne 
---
 hw/openrisc/cputimer.c | 22 +-
 1 file changed, 21 insertions(+), 1 deletion(-)

diff --git a/hw/openrisc/cputimer.c b/hw/openrisc/cputimer.c
index 93268815d8..10163b391b 100644
--- a/hw/openrisc/cputimer.c
+++ b/hw/openrisc/cputimer.c
@@ -22,6 +22,7 @@
 #include "cpu.h"
 #include "migration/vmstate.h"
 #include "qemu/timer.h"
+#include "sysemu/reset.h"
 
 #define TIMER_PERIOD 50 /* 50 ns period for 20 MHz timer */
 
@@ -122,6 +123,24 @@ static void openrisc_timer_cb(void *opaque)
 qemu_cpu_kick(CPU(cpu));
 }
 
+/* Reset the per CPU counter state. */
+static void openrisc_count_reset(void *opaque)
+{
+OpenRISCCPU *cpu = opaque;
+
+if (cpu->env.is_counting) {
+cpu_openrisc_count_stop(cpu);
+}
+cpu->env.ttmr = 0x;
+}
+
+/* Reset the global timer state. */
+static void openrisc_timer_reset(void *opaque)
+{
+or1k_timer->ttcr = 0x;
+or1k_timer->last_clk = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+}
+
 static const VMStateDescription vmstate_or1k_timer = {
 .name = "or1k_timer",
 .version_id = 1,
@@ -136,10 +155,11 @@ static const VMStateDescription vmstate_or1k_timer = {
 void cpu_openrisc_clock_init(OpenRISCCPU *cpu)
 {
 cpu->env.timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, _timer_cb, cpu);
-cpu->env.ttmr = 0x;
 
+qemu_register_reset(openrisc_count_reset, cpu);
 if (or1k_timer == NULL) {
 or1k_timer = g_new0(OR1KTimerState, 1);
+qemu_register_reset(openrisc_timer_reset, cpu);
 vmstate_register(NULL, 0, _or1k_timer, or1k_timer);
 }
 }
-- 
2.37.2




[PULL 01/11] hw/openrisc: Split re-usable boot time apis out to boot.c

2022-09-04 Thread Stafford Horne
These will be shared with the virt platform.

Reviewed-by: Richard Henderson 
Signed-off-by: Stafford Horne 
---
 hw/openrisc/boot.c | 116 +
 hw/openrisc/meson.build|   1 +
 hw/openrisc/openrisc_sim.c | 106 ++---
 include/hw/openrisc/boot.h |  34 +++
 4 files changed, 157 insertions(+), 100 deletions(-)
 create mode 100644 hw/openrisc/boot.c
 create mode 100644 include/hw/openrisc/boot.h

diff --git a/hw/openrisc/boot.c b/hw/openrisc/boot.c
new file mode 100644
index 00..128ccbcba2
--- /dev/null
+++ b/hw/openrisc/boot.c
@@ -0,0 +1,116 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * QEMU OpenRISC boot helpers.
+ *
+ * (c) 2022 Stafford Horne 
+ */
+
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "exec/cpu-defs.h"
+#include "elf.h"
+#include "hw/loader.h"
+#include "hw/openrisc/boot.h"
+#include "sysemu/device_tree.h"
+#include "sysemu/qtest.h"
+
+#include 
+
+#define KERNEL_LOAD_ADDR 0x100
+
+hwaddr openrisc_load_kernel(ram_addr_t ram_size,
+const char *kernel_filename,
+uint32_t *bootstrap_pc)
+{
+long kernel_size;
+uint64_t elf_entry;
+uint64_t high_addr;
+hwaddr entry;
+
+if (kernel_filename && !qtest_enabled()) {
+kernel_size = load_elf(kernel_filename, NULL, NULL, NULL,
+   _entry, NULL, _addr, NULL, 1,
+   EM_OPENRISC, 1, 0);
+entry = elf_entry;
+if (kernel_size < 0) {
+kernel_size = load_uimage(kernel_filename,
+  , NULL, NULL, NULL, NULL);
+high_addr = entry + kernel_size;
+}
+if (kernel_size < 0) {
+kernel_size = load_image_targphys(kernel_filename,
+  KERNEL_LOAD_ADDR,
+  ram_size - KERNEL_LOAD_ADDR);
+high_addr = KERNEL_LOAD_ADDR + kernel_size;
+}
+
+if (entry <= 0) {
+entry = KERNEL_LOAD_ADDR;
+}
+
+if (kernel_size < 0) {
+error_report("couldn't load the kernel '%s'", kernel_filename);
+exit(1);
+}
+*bootstrap_pc = entry;
+
+return high_addr;
+}
+return 0;
+}
+
+hwaddr openrisc_load_initrd(void *fdt, const char *filename,
+hwaddr load_start, uint64_t mem_size)
+{
+int size;
+hwaddr start;
+
+/* We put the initrd right after the kernel; page aligned. */
+start = TARGET_PAGE_ALIGN(load_start);
+
+size = load_ramdisk(filename, start, mem_size - start);
+if (size < 0) {
+size = load_image_targphys(filename, start, mem_size - start);
+if (size < 0) {
+error_report("could not load ramdisk '%s'", filename);
+exit(1);
+}
+}
+
+if (fdt) {
+qemu_fdt_setprop_cell(fdt, "/chosen",
+  "linux,initrd-start", start);
+qemu_fdt_setprop_cell(fdt, "/chosen",
+  "linux,initrd-end", start + size);
+}
+
+return start + size;
+}
+
+uint32_t openrisc_load_fdt(void *fdt, hwaddr load_start,
+   uint64_t mem_size)
+{
+uint32_t fdt_addr;
+int ret;
+int fdtsize = fdt_totalsize(fdt);
+
+if (fdtsize <= 0) {
+error_report("invalid device-tree");
+exit(1);
+}
+
+/* We put fdt right after the kernel and/or initrd. */
+fdt_addr = TARGET_PAGE_ALIGN(load_start);
+
+ret = fdt_pack(fdt);
+/* Should only fail if we've built a corrupted tree */
+g_assert(ret == 0);
+/* copy in the device tree */
+qemu_fdt_dumpdtb(fdt, fdtsize);
+
+rom_add_blob_fixed_as("fdt", fdt, fdtsize, fdt_addr,
+  _space_memory);
+
+return fdt_addr;
+}
diff --git a/hw/openrisc/meson.build b/hw/openrisc/meson.build
index ec48172c9d..ab563820c5 100644
--- a/hw/openrisc/meson.build
+++ b/hw/openrisc/meson.build
@@ -1,5 +1,6 @@
 openrisc_ss = ss.source_set()
 openrisc_ss.add(files('cputimer.c'))
+openrisc_ss.add(files('boot.c'))
 openrisc_ss.add(when: 'CONFIG_OR1K_SIM', if_true: [files('openrisc_sim.c'), 
fdt])
 
 hw_arch += {'openrisc': openrisc_ss}
diff --git a/hw/openrisc/openrisc_sim.c b/hw/openrisc/openrisc_sim.c
index 35adce17ac..35da123aef 100644
--- a/hw/openrisc/openrisc_sim.c
+++ b/hw/openrisc/openrisc_sim.c
@@ -24,10 +24,9 @@
 #include "cpu.h"
 #include "hw/irq.h"
 #include "hw/boards.h"
-#include "elf.h"
 #include "hw/char/serial.h"
 #include "net/net.h"
-#include "hw/loader.h"
+#include "hw/openrisc/boot.h"
 #includ

[PULL 10/11] hw/openrisc: virt: pass random seed to fdt

2022-09-04 Thread Stafford Horne
From: "Jason A. Donenfeld" 

If the FDT contains /chosen/rng-seed, then the Linux RNG will use it to
initialize early. Set this using the usual guest random number
generation function. This is confirmed to successfully initialize the
RNG on Linux 5.19-rc2.

Signed-off-by: Jason A. Donenfeld 
Reviewed-by: Richard Henderson 
Signed-off-by: Stafford Horne 
---
 hw/openrisc/virt.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/hw/openrisc/virt.c b/hw/openrisc/virt.c
index 9a78234a28..f8a68a6a6b 100644
--- a/hw/openrisc/virt.c
+++ b/hw/openrisc/virt.c
@@ -8,6 +8,7 @@
 
 #include "qemu/osdep.h"
 #include "qemu/error-report.h"
+#include "qemu/guest-random.h"
 #include "qapi/error.h"
 #include "cpu.h"
 #include "exec/address-spaces.h"
@@ -130,6 +131,7 @@ static void openrisc_create_fdt(OR1KVirtState *state,
 void *fdt;
 int cpu;
 char *nodename;
+uint8_t rng_seed[32];
 
 fdt = state->fdt = create_device_tree(>fdt_size);
 if (!fdt) {
@@ -186,6 +188,10 @@ static void openrisc_create_fdt(OR1KVirtState *state,
 qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", cmdline);
 }
 
+/* Pass seed to RNG. */
+qemu_guest_getrandom_nofail(rng_seed, sizeof(rng_seed));
+qemu_fdt_setprop(fdt, "/chosen", "rng-seed", rng_seed, sizeof(rng_seed));
+
 /* Create aliases node for use by devices. */
 qemu_fdt_add_subnode(fdt, "/aliases");
 }
-- 
2.37.2




[PULL 03/11] goldfish_rtc: Add big-endian property

2022-09-04 Thread Stafford Horne
Add a new property "big-endian" to allow configuring the RTC as either
little or big endian, the default is little endian.

Currently overriding the default to big endian is only used by the m68k
virt platform.  New platforms should prefer to use little endian and not
set this.

Cc: Laurent Vivier 
Reviewed-by: Anup Patel 
Reviewed-by: Richard Henderson 
Signed-off-by: Stafford Horne 
---
 hw/m68k/virt.c|  1 +
 hw/rtc/goldfish_rtc.c | 37 ++-
 include/hw/rtc/goldfish_rtc.h |  2 ++
 3 files changed, 31 insertions(+), 9 deletions(-)

diff --git a/hw/m68k/virt.c b/hw/m68k/virt.c
index 3122c8ef2c..2f3ffc0de6 100644
--- a/hw/m68k/virt.c
+++ b/hw/m68k/virt.c
@@ -173,6 +173,7 @@ static void virt_init(MachineState *machine)
 io_base = VIRT_GF_RTC_MMIO_BASE;
 for (i = 0; i < VIRT_GF_RTC_NB; i++) {
 dev = qdev_new(TYPE_GOLDFISH_RTC);
+qdev_prop_set_bit(dev, "big-endian", true);
 sysbus = SYS_BUS_DEVICE(dev);
 sysbus_realize_and_unref(sysbus, _fatal);
 sysbus_mmio_map(sysbus, 0, io_base);
diff --git a/hw/rtc/goldfish_rtc.c b/hw/rtc/goldfish_rtc.c
index 35e493be31..19a56402a0 100644
--- a/hw/rtc/goldfish_rtc.c
+++ b/hw/rtc/goldfish_rtc.c
@@ -216,14 +216,25 @@ static int goldfish_rtc_post_load(void *opaque, int 
version_id)
 return 0;
 }
 
-static const MemoryRegionOps goldfish_rtc_ops = {
-.read = goldfish_rtc_read,
-.write = goldfish_rtc_write,
-.endianness = DEVICE_NATIVE_ENDIAN,
-.valid = {
-.min_access_size = 4,
-.max_access_size = 4
-}
+static const MemoryRegionOps goldfish_rtc_ops[2] = {
+[false] = {
+.read = goldfish_rtc_read,
+.write = goldfish_rtc_write,
+.endianness = DEVICE_LITTLE_ENDIAN,
+.valid = {
+.min_access_size = 4,
+.max_access_size = 4
+}
+},
+[true] = {
+.read = goldfish_rtc_read,
+.write = goldfish_rtc_write,
+.endianness = DEVICE_BIG_ENDIAN,
+.valid = {
+.min_access_size = 4,
+.max_access_size = 4
+}
+},
 };
 
 static const VMStateDescription goldfish_rtc_vmstate = {
@@ -265,7 +276,8 @@ static void goldfish_rtc_realize(DeviceState *d, Error 
**errp)
 SysBusDevice *dev = SYS_BUS_DEVICE(d);
 GoldfishRTCState *s = GOLDFISH_RTC(d);
 
-memory_region_init_io(>iomem, OBJECT(s), _rtc_ops, s,
+memory_region_init_io(>iomem, OBJECT(s),
+  _rtc_ops[s->big_endian], s,
   "goldfish_rtc", 0x24);
 sysbus_init_mmio(dev, >iomem);
 
@@ -274,10 +286,17 @@ static void goldfish_rtc_realize(DeviceState *d, Error 
**errp)
 s->timer = timer_new_ns(rtc_clock, goldfish_rtc_interrupt, s);
 }
 
+static Property goldfish_rtc_properties[] = {
+DEFINE_PROP_BOOL("big-endian", GoldfishRTCState, big_endian,
+  false),
+DEFINE_PROP_END_OF_LIST(),
+};
+
 static void goldfish_rtc_class_init(ObjectClass *klass, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(klass);
 
+device_class_set_props(dc, goldfish_rtc_properties);
 dc->realize = goldfish_rtc_realize;
 dc->reset = goldfish_rtc_reset;
 dc->vmsd = _rtc_vmstate;
diff --git a/include/hw/rtc/goldfish_rtc.h b/include/hw/rtc/goldfish_rtc.h
index 79ca7daf5d..162be33863 100644
--- a/include/hw/rtc/goldfish_rtc.h
+++ b/include/hw/rtc/goldfish_rtc.h
@@ -42,6 +42,8 @@ struct GoldfishRTCState {
 uint32_t irq_pending;
 uint32_t irq_enabled;
 uint32_t time_high;
+
+bool big_endian;
 };
 
 #endif
-- 
2.37.2




[PULL 02/11] target/openrisc: Fix memory reading in debugger

2022-09-04 Thread Stafford Horne
In commit f0655423ca ("target/openrisc: Reorg tlb lookup") data and
instruction TLB reads were combined.  This, broke debugger reads where
we first tried to map using the data tlb then fall back to the
instruction tlb.

This patch replicates this logic by first requesting a PAGE_READ
protection mapping then falling back to PAGE_EXEC.

Reviewed-by: Richard Henderson 
Signed-off-by: Stafford Horne 
---
 target/openrisc/mmu.c | 8 +++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/target/openrisc/mmu.c b/target/openrisc/mmu.c
index d7e1320998..0b8afdbacf 100644
--- a/target/openrisc/mmu.c
+++ b/target/openrisc/mmu.c
@@ -148,7 +148,13 @@ hwaddr openrisc_cpu_get_phys_page_debug(CPUState *cs, 
vaddr addr)
 case SR_DME | SR_IME:
 /* The mmu is definitely enabled.  */
 excp = get_phys_mmu(cpu, _addr, , addr,
-PAGE_EXEC | PAGE_READ | PAGE_WRITE,
+PAGE_READ,
+(sr & SR_SM) != 0);
+if (!excp) {
+return phys_addr;
+}
+excp = get_phys_mmu(cpu, _addr, , addr,
+PAGE_EXEC,
 (sr & SR_SM) != 0);
 return excp ? -1 : phys_addr;
 
-- 
2.37.2




[PULL 00/11] OpenRISC updates for 7.2.0

2022-09-04 Thread Stafford Horne
The following changes since commit 61fd710b8da8aedcea9b4f197283dc38638e4b60:

  Merge tag 'for-upstream' of https://gitlab.com/bonzini/qemu into staging 
(2022-09-02 13:24:28 -0400)

are available in the Git repository at:

  g...@github.com:stffrdhrn/qemu.git tags/pull-or1k-20220904

for you to fetch changes up to b14df228d7c4fe6e86e7f8a4998e9ccf4967b678:

  docs/system: openrisc: Add OpenRISC documentation (2022-09-04 07:02:57 +0100)


OpenRISC updates for 7.2.0

Updates to add the OpenRISC virt plaform to QEMU. Highlights
include:

- New virt plaform with, virtio and pci bus support
- OpenRISC support for MTTCG
- Goldfish RTC device endianness is configurable now


Jason A. Donenfeld (1):
  hw/openrisc: virt: pass random seed to fdt

Stafford Horne (10):
  hw/openrisc: Split re-usable boot time apis out to boot.c
  target/openrisc: Fix memory reading in debugger
  goldfish_rtc: Add big-endian property
  hw/openrisc: Add the OpenRISC virtual machine
  hw/openrisc: Add PCI bus support to virt
  hw/openrisc: Initialize timer time at startup
  target/openrisc: Add interrupted CPU to log
  target/openrisc: Enable MTTCG
  target/openrisc: Interrupt handling fixes
  docs/system: openrisc: Add OpenRISC documentation

 configs/devices/or1k-softmmu/default.mak |   1 +
 configs/targets/or1k-softmmu.mak |   1 +
 docs/system/openrisc/cpu-features.rst|  15 +
 docs/system/openrisc/emulation.rst   |  17 +
 docs/system/openrisc/or1k-sim.rst|  43 +++
 docs/system/openrisc/virt.rst|  50 +++
 docs/system/target-openrisc.rst  |  71 
 docs/system/targets.rst  |   1 +
 hw/m68k/virt.c   |   1 +
 hw/openrisc/Kconfig  |  12 +
 hw/openrisc/boot.c   | 116 +++
 hw/openrisc/cputimer.c   |  22 +-
 hw/openrisc/meson.build  |   2 +
 hw/openrisc/openrisc_sim.c   | 106 +-
 hw/openrisc/virt.c   | 571 +++
 hw/rtc/goldfish_rtc.c|  37 +-
 include/hw/openrisc/boot.h   |  34 ++
 include/hw/rtc/goldfish_rtc.h|   2 +
 target/openrisc/cpu.c|   1 -
 target/openrisc/cpu.h|   2 +
 target/openrisc/interrupt.c  |   4 +-
 target/openrisc/mmu.c|   8 +-
 target/openrisc/sys_helper.c |  14 +-
 23 files changed, 1017 insertions(+), 114 deletions(-)
 create mode 100644 docs/system/openrisc/cpu-features.rst
 create mode 100644 docs/system/openrisc/emulation.rst
 create mode 100644 docs/system/openrisc/or1k-sim.rst
 create mode 100644 docs/system/openrisc/virt.rst
 create mode 100644 docs/system/target-openrisc.rst
 create mode 100644 hw/openrisc/boot.c
 create mode 100644 hw/openrisc/virt.c
 create mode 100644 include/hw/openrisc/boot.h

Jason A. Donenfeld (1):
  hw/openrisc: virt: pass random seed to fdt

Stafford Horne (10):
  hw/openrisc: Split re-usable boot time apis out to boot.c
  target/openrisc: Fix memory reading in debugger
  goldfish_rtc: Add big-endian property
  hw/openrisc: Add the OpenRISC virtual machine
  hw/openrisc: Add PCI bus support to virt
  hw/openrisc: Initialize timer time at startup
  target/openrisc: Add interrupted CPU to log
  target/openrisc: Enable MTTCG
  target/openrisc: Interrupt handling fixes
  docs/system: openrisc: Add OpenRISC documentation

 configs/devices/or1k-softmmu/default.mak |   1 +
 configs/targets/or1k-softmmu.mak |   1 +
 docs/system/openrisc/cpu-features.rst|  15 +
 docs/system/openrisc/emulation.rst   |  17 +
 docs/system/openrisc/or1k-sim.rst|  43 ++
 docs/system/openrisc/virt.rst|  50 ++
 docs/system/target-openrisc.rst  |  71 +++
 docs/system/targets.rst  |   1 +
 hw/m68k/virt.c   |   1 +
 hw/openrisc/Kconfig  |  12 +
 hw/openrisc/boot.c   | 116 +
 hw/openrisc/cputimer.c   |  22 +-
 hw/openrisc/meson.build  |   2 +
 hw/openrisc/openrisc_sim.c   | 106 +
 hw/openrisc/virt.c   | 571 +++
 hw/rtc/goldfish_rtc.c|  37 +-
 include/hw/openrisc/boot.h   |  34 ++
 include/hw/rtc/goldfish_rtc.h|   2 +
 target/openrisc/cpu.c|   1 -
 target/openrisc/cpu.h|   2 +
 target/openrisc/interrupt.c  |   4 +-
 target/openrisc/mmu.c|   8 +-
 target/openrisc/sys_helper.c |  14 +-
 23 files changed, 1017 insertions(+), 114 deletions(-)
 create mode 100644 docs/system/openrisc/cpu-features.rst
 create mode 100644 docs/system/openrisc/emulation.rst
 create mode 100644 docs

Re: [PATCH v3 08/11] target/openrisc: Enable MTTCG

2022-08-01 Thread Stafford Horne
On Fri, Jul 29, 2022 at 04:42:54PM -0700, Richard Henderson wrote:
> On 7/29/22 16:01, Stafford Horne wrote:
> > This patch enables multithread TCG for OpenRISC.  Since the or1k shared
> > syncrhonized timer can be updated from each vCPU via helpers we use a
> > mutex to synchronize updates.
> > 
> > Signed-off-by: Stafford Horne
> > ---
> > Since v2:
> >   - Removed cpu_openrisc_timer_has_advanced lock optimization, measuring 
> > revealed
> > it did not help much.
> > 
> >   configs/targets/or1k-softmmu.mak | 1 +
> >   target/openrisc/cpu.h| 2 ++
> >   target/openrisc/sys_helper.c | 7 ++-
> >   3 files changed, 9 insertions(+), 1 deletion(-)
> 
> Reviewed-by: Richard Henderson 

Thank you,

I guess this whole series is a bit late for 7.1.0 now.

I will post the PR after 7.1.0 is released and target it for 7.2.0.

-Stafford



[PATCH v3 11/11] docs/system: openrisc: Add OpenRISC documentation

2022-07-29 Thread Stafford Horne
Reviewed-by: Richard Henderson 
Signed-off-by: Stafford Horne 
---
Since v2;
 - Added Reviewed-by

 docs/system/openrisc/cpu-features.rst | 15 ++
 docs/system/openrisc/emulation.rst| 17 +++
 docs/system/openrisc/or1k-sim.rst | 43 
 docs/system/openrisc/virt.rst | 50 +++
 docs/system/target-openrisc.rst   | 72 +++
 docs/system/targets.rst   |  1 +
 6 files changed, 198 insertions(+)
 create mode 100644 docs/system/openrisc/cpu-features.rst
 create mode 100644 docs/system/openrisc/emulation.rst
 create mode 100644 docs/system/openrisc/or1k-sim.rst
 create mode 100644 docs/system/openrisc/virt.rst
 create mode 100644 docs/system/target-openrisc.rst

diff --git a/docs/system/openrisc/cpu-features.rst 
b/docs/system/openrisc/cpu-features.rst
new file mode 100644
index 00..aeb65e22ff
--- /dev/null
+++ b/docs/system/openrisc/cpu-features.rst
@@ -0,0 +1,15 @@
+CPU Features
+
+
+The QEMU emulation of the OpenRISC architecture provides following built in
+features.
+
+- Shadow GPRs
+- MMU TLB with 128 entries, 1 way
+- Power Management (PM)
+- Programmable Interrupt Controller (PIC)
+- Tick Timer
+
+These features are on by default and the presence can be confirmed by checking
+the contents of the Unit Presence Register (``UPR``) and CPU Configuration
+Register (``CPUCFGR``).
diff --git a/docs/system/openrisc/emulation.rst 
b/docs/system/openrisc/emulation.rst
new file mode 100644
index 00..0af898ab20
--- /dev/null
+++ b/docs/system/openrisc/emulation.rst
@@ -0,0 +1,17 @@
+OpenRISC 1000 CPU architecture support
+==
+
+QEMU's TCG emulation includes support for the OpenRISC or1200 implementation of
+the OpenRISC 1000 cpu architecture.
+
+The or1200 cpu also has support for the following instruction subsets:
+
+- ORBIS32 (OpenRISC Basic Instruction Set)
+- ORFPX32 (OpenRISC Floating-Point eXtension)
+
+In addition to the instruction subsets the QEMU TCG emulation also has support
+for most Class II (optional) instructions.
+
+For information on all OpenRISC instructions please refer to the latest
+architecture manual available on the OpenRISC website in the
+`OpenRISC Architecture <https://openrisc.io/architecture>`_ section.
diff --git a/docs/system/openrisc/or1k-sim.rst 
b/docs/system/openrisc/or1k-sim.rst
new file mode 100644
index 00..ef10439737
--- /dev/null
+++ b/docs/system/openrisc/or1k-sim.rst
@@ -0,0 +1,43 @@
+Or1ksim board
+=
+
+The QEMU Or1ksim machine emulates the standard OpenRISC board simulator which 
is
+also the standard SoC configuration.
+
+Supported devices
+-
+
+ * 16550A UART
+ * ETHOC Ethernet controller
+ * SMP (OpenRISC multicore using ompic)
+
+Boot options
+
+
+The Or1ksim machine can be started using the ``-kernel`` and ``-initrd`` 
options
+to load a Linux kernel and optional disk image.
+
+.. code-block:: bash
+
+  $ qemu-system-or1k -cpu or1220 -M or1k-sim -nographic \
+-kernel vmlinux \
+-initrd initramfs.cpio.gz \
+-m 128
+
+Linux guest kernel configuration
+""""""""""""""""""""""""""""""""
+
+The 'or1ksim_defconfig' for Linux openrisc kernels includes the right
+drivers for the or1ksim machine.  If you would like to run an SMP system
+choose the 'simple_smp_defconfig' config.
+
+Hardware configuration information
+""""""""""""""""""""""""""""""""""
+
+The ``or1k-sim`` board automatically generates a device tree blob ("dtb")
+which it passes to the guest. This provides information about the
+addresses, interrupt lines and other configuration of the various devices
+in the system.
+
+The location of the DTB will be passed in register ``r3`` to the guest 
operating
+system.
diff --git a/docs/system/openrisc/virt.rst b/docs/system/openrisc/virt.rst
new file mode 100644
index 00..2fe61ac942
--- /dev/null
+++ b/docs/system/openrisc/virt.rst
@@ -0,0 +1,50 @@
+'virt' generic virtual platform
+===
+
+The ``virt`` board is a platform which does not correspond to any
+real hardware; it is designed for use in virtual machines.
+It is the recommended board type if you simply want to run
+a guest such as Linux and do not care about reproducing the
+idiosyncrasies and limitations of a particular bit of real-world
+hardware.
+
+Supported devices
+-
+
+ * PCI/PCIe devices
+ * 8 virtio-mmio transport devices
+ * 16550A UART
+ * Goldfish RTC
+ * SiFive Test device for poweroff and reboot
+ * SMP (OpenRISC multicore using ompic)
+
+Boot options
+
+
+The virt machine can b

[PATCH v3 08/11] target/openrisc: Enable MTTCG

2022-07-29 Thread Stafford Horne
This patch enables multithread TCG for OpenRISC.  Since the or1k shared
syncrhonized timer can be updated from each vCPU via helpers we use a
mutex to synchronize updates.

Signed-off-by: Stafford Horne 
---
Since v2:
 - Removed cpu_openrisc_timer_has_advanced lock optimization, measuring revealed
   it did not help much.

 configs/targets/or1k-softmmu.mak | 1 +
 target/openrisc/cpu.h| 2 ++
 target/openrisc/sys_helper.c | 7 ++-
 3 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/configs/targets/or1k-softmmu.mak b/configs/targets/or1k-softmmu.mak
index 263e970870..432f855a30 100644
--- a/configs/targets/or1k-softmmu.mak
+++ b/configs/targets/or1k-softmmu.mak
@@ -1,3 +1,4 @@
 TARGET_ARCH=openrisc
+TARGET_SUPPORTS_MTTCG=y
 TARGET_BIG_ENDIAN=y
 TARGET_NEED_FDT=y
diff --git a/target/openrisc/cpu.h b/target/openrisc/cpu.h
index b9584f10d4..1d5efa5ca2 100644
--- a/target/openrisc/cpu.h
+++ b/target/openrisc/cpu.h
@@ -25,6 +25,8 @@
 #include "hw/core/cpu.h"
 #include "qom/object.h"
 
+#define TCG_GUEST_DEFAULT_MO (0)
+
 #define TYPE_OPENRISC_CPU "or1k-cpu"
 
 OBJECT_DECLARE_CPU_TYPE(OpenRISCCPU, OpenRISCCPUClass, OPENRISC_CPU)
diff --git a/target/openrisc/sys_helper.c b/target/openrisc/sys_helper.c
index 48674231e7..da88ad9e77 100644
--- a/target/openrisc/sys_helper.c
+++ b/target/openrisc/sys_helper.c
@@ -145,6 +145,7 @@ void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong spr, 
target_ulong rb)
 break;
 case TO_SPR(10, 0): /* TTMR */
 {
+qemu_mutex_lock_iothread();
 if ((env->ttmr & TTMR_M) ^ (rb & TTMR_M)) {
 switch (rb & TTMR_M) {
 case TIMER_NONE:
@@ -168,14 +169,16 @@ void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong 
spr, target_ulong rb)
 env->ttmr = rb & ~TTMR_IP;
 cs->interrupt_request &= ~CPU_INTERRUPT_TIMER;
 }
-
 cpu_openrisc_timer_update(cpu);
+qemu_mutex_unlock_iothread();
 }
 break;
 
 case TO_SPR(10, 1): /* TTCR */
+qemu_mutex_lock_iothread();
 cpu_openrisc_count_set(cpu, rb);
 cpu_openrisc_timer_update(cpu);
+qemu_mutex_unlock_iothread();
 break;
 #endif
 
@@ -303,7 +306,9 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env, 
target_ulong rd,
 return env->ttmr;
 
 case TO_SPR(10, 1): /* TTCR */
+qemu_mutex_lock_iothread();
 cpu_openrisc_count_update(cpu);
+qemu_mutex_unlock_iothread();
 return cpu_openrisc_count_get(cpu);
 #endif
 
-- 
2.37.1




[PATCH v3 03/11] goldfish_rtc: Add big-endian property

2022-07-29 Thread Stafford Horne
Add a new property "big-endian" to allow configuring the RTC as either
little or big endian, the default is little endian.

Currently overriding the default to big endian is only used by the m68k
virt platform.  New platforms should prefer to use little endian and not
set this.

Cc: Laurent Vivier 
Reviewed-by: Anup Patel 
Signed-off-by: Stafford Horne 
---
Since v2:
 - Added Reviewed-by
 - Changed from enum property to boolean as suggested by Richard

 hw/m68k/virt.c|  1 +
 hw/rtc/goldfish_rtc.c | 37 ++-
 include/hw/rtc/goldfish_rtc.h |  2 ++
 3 files changed, 31 insertions(+), 9 deletions(-)

diff --git a/hw/m68k/virt.c b/hw/m68k/virt.c
index 0aa383fa6b..c7a6c766e3 100644
--- a/hw/m68k/virt.c
+++ b/hw/m68k/virt.c
@@ -173,6 +173,7 @@ static void virt_init(MachineState *machine)
 io_base = VIRT_GF_RTC_MMIO_BASE;
 for (i = 0; i < VIRT_GF_RTC_NB; i++) {
 dev = qdev_new(TYPE_GOLDFISH_RTC);
+qdev_prop_set_bit(dev, "big-endian", true);
 sysbus = SYS_BUS_DEVICE(dev);
 sysbus_realize_and_unref(sysbus, _fatal);
 sysbus_mmio_map(sysbus, 0, io_base);
diff --git a/hw/rtc/goldfish_rtc.c b/hw/rtc/goldfish_rtc.c
index 35e493be31..19a56402a0 100644
--- a/hw/rtc/goldfish_rtc.c
+++ b/hw/rtc/goldfish_rtc.c
@@ -216,14 +216,25 @@ static int goldfish_rtc_post_load(void *opaque, int 
version_id)
 return 0;
 }
 
-static const MemoryRegionOps goldfish_rtc_ops = {
-.read = goldfish_rtc_read,
-.write = goldfish_rtc_write,
-.endianness = DEVICE_NATIVE_ENDIAN,
-.valid = {
-.min_access_size = 4,
-.max_access_size = 4
-}
+static const MemoryRegionOps goldfish_rtc_ops[2] = {
+[false] = {
+.read = goldfish_rtc_read,
+.write = goldfish_rtc_write,
+.endianness = DEVICE_LITTLE_ENDIAN,
+.valid = {
+.min_access_size = 4,
+.max_access_size = 4
+}
+},
+[true] = {
+.read = goldfish_rtc_read,
+.write = goldfish_rtc_write,
+.endianness = DEVICE_BIG_ENDIAN,
+.valid = {
+.min_access_size = 4,
+.max_access_size = 4
+}
+},
 };
 
 static const VMStateDescription goldfish_rtc_vmstate = {
@@ -265,7 +276,8 @@ static void goldfish_rtc_realize(DeviceState *d, Error 
**errp)
 SysBusDevice *dev = SYS_BUS_DEVICE(d);
 GoldfishRTCState *s = GOLDFISH_RTC(d);
 
-memory_region_init_io(>iomem, OBJECT(s), _rtc_ops, s,
+memory_region_init_io(>iomem, OBJECT(s),
+  _rtc_ops[s->big_endian], s,
   "goldfish_rtc", 0x24);
 sysbus_init_mmio(dev, >iomem);
 
@@ -274,10 +286,17 @@ static void goldfish_rtc_realize(DeviceState *d, Error 
**errp)
 s->timer = timer_new_ns(rtc_clock, goldfish_rtc_interrupt, s);
 }
 
+static Property goldfish_rtc_properties[] = {
+DEFINE_PROP_BOOL("big-endian", GoldfishRTCState, big_endian,
+  false),
+DEFINE_PROP_END_OF_LIST(),
+};
+
 static void goldfish_rtc_class_init(ObjectClass *klass, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(klass);
 
+device_class_set_props(dc, goldfish_rtc_properties);
 dc->realize = goldfish_rtc_realize;
 dc->reset = goldfish_rtc_reset;
 dc->vmsd = _rtc_vmstate;
diff --git a/include/hw/rtc/goldfish_rtc.h b/include/hw/rtc/goldfish_rtc.h
index 79ca7daf5d..162be33863 100644
--- a/include/hw/rtc/goldfish_rtc.h
+++ b/include/hw/rtc/goldfish_rtc.h
@@ -42,6 +42,8 @@ struct GoldfishRTCState {
 uint32_t irq_pending;
 uint32_t irq_enabled;
 uint32_t time_high;
+
+bool big_endian;
 };
 
 #endif
-- 
2.37.1




[PATCH v3 10/11] hw/openrisc: virt: pass random seed to fdt

2022-07-29 Thread Stafford Horne
From: "Jason A. Donenfeld" 

If the FDT contains /chosen/rng-seed, then the Linux RNG will use it to
initialize early. Set this using the usual guest random number
generation function. This is confirmed to successfully initialize the
RNG on Linux 5.19-rc2.

Signed-off-by: Jason A. Donenfeld 
Reviewed-by: Richard Henderson 
Signed-off-by: Stafford Horne 
---
Since v2:
 - No changes

 hw/openrisc/virt.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/hw/openrisc/virt.c b/hw/openrisc/virt.c
index 9a78234a28..f8a68a6a6b 100644
--- a/hw/openrisc/virt.c
+++ b/hw/openrisc/virt.c
@@ -8,6 +8,7 @@
 
 #include "qemu/osdep.h"
 #include "qemu/error-report.h"
+#include "qemu/guest-random.h"
 #include "qapi/error.h"
 #include "cpu.h"
 #include "exec/address-spaces.h"
@@ -130,6 +131,7 @@ static void openrisc_create_fdt(OR1KVirtState *state,
 void *fdt;
 int cpu;
 char *nodename;
+uint8_t rng_seed[32];
 
 fdt = state->fdt = create_device_tree(>fdt_size);
 if (!fdt) {
@@ -186,6 +188,10 @@ static void openrisc_create_fdt(OR1KVirtState *state,
 qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", cmdline);
 }
 
+/* Pass seed to RNG. */
+qemu_guest_getrandom_nofail(rng_seed, sizeof(rng_seed));
+qemu_fdt_setprop(fdt, "/chosen", "rng-seed", rng_seed, sizeof(rng_seed));
+
 /* Create aliases node for use by devices. */
 qemu_fdt_add_subnode(fdt, "/aliases");
 }
-- 
2.37.1




[PATCH v3 07/11] target/openrisc: Add interrupted CPU to log

2022-07-29 Thread Stafford Horne
When we are tracing it's helpful to know which CPU's are getting
interrupted, add that detail to the log line.

Reviewed-by: Richard Henderson 
Signed-off-by: Stafford Horne 
---
Since v2:
 - Added Reviewed-by

 target/openrisc/interrupt.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/target/openrisc/interrupt.c b/target/openrisc/interrupt.c
index e5724f5371..c31c6f12c4 100644
--- a/target/openrisc/interrupt.c
+++ b/target/openrisc/interrupt.c
@@ -83,7 +83,9 @@ void openrisc_cpu_do_interrupt(CPUState *cs)
 [EXCP_TRAP] = "TRAP",
 };
 
-qemu_log_mask(CPU_LOG_INT, "INT: %s\n", int_name[exception]);
+qemu_log_mask(CPU_LOG_INT, "CPU: %d INT: %s\n",
+  cs->cpu_index,
+  int_name[exception]);
 
 hwaddr vect_pc = exception << 8;
 if (env->cpucfgr & CPUCFGR_EVBARP) {
-- 
2.37.1




[PATCH v3 05/11] hw/openrisc: Add PCI bus support to virt

2022-07-29 Thread Stafford Horne
This is mostly borrowed from xtensa and riscv as examples.  The
create_pcie_irq_map swizzle function is almost and exact copy
but here we use a single cell interrupt, possibly we can make
this generic.

Signed-off-by: Stafford Horne 
---
Since v2:
 - No changes

 hw/openrisc/Kconfig |   3 +
 hw/openrisc/virt.c  | 160 ++--
 2 files changed, 157 insertions(+), 6 deletions(-)

diff --git a/hw/openrisc/Kconfig b/hw/openrisc/Kconfig
index 202134668e..97af258b55 100644
--- a/hw/openrisc/Kconfig
+++ b/hw/openrisc/Kconfig
@@ -7,8 +7,11 @@ config OR1K_SIM
 
 config OR1K_VIRT
 bool
+imply PCI_DEVICES
 imply VIRTIO_VGA
 imply TEST_DEVICES
+select PCI
+select PCI_EXPRESS_GENERIC_BRIDGE
 select GOLDFISH_RTC
 select SERIAL
 select SIFIVE_TEST
diff --git a/hw/openrisc/virt.c b/hw/openrisc/virt.c
index 54f2732a6b..9a78234a28 100644
--- a/hw/openrisc/virt.c
+++ b/hw/openrisc/virt.c
@@ -17,6 +17,8 @@
 #include "hw/core/split-irq.h"
 #include "hw/openrisc/boot.h"
 #include "hw/misc/sifive_test.h"
+#include "hw/pci/pci.h"
+#include "hw/pci-host/gpex.h"
 #include "hw/qdev-properties.h"
 #include "hw/rtc/goldfish_rtc.h"
 #include "hw/sysbus.h"
@@ -47,6 +49,9 @@ typedef struct OR1KVirtState {
 
 enum {
 VIRT_DRAM,
+VIRT_ECAM,
+VIRT_MMIO,
+VIRT_PIO,
 VIRT_TEST,
 VIRT_RTC,
 VIRT_VIRTIO,
@@ -60,6 +65,7 @@ enum {
 VIRT_RTC_IRQ = 3,
 VIRT_VIRTIO_IRQ = 4, /* to 12 */
 VIRTIO_COUNT = 8,
+VIRT_PCI_IRQ_BASE = 13, /* to 17 */
 };
 
 static const struct MemmapEntry {
@@ -72,6 +78,9 @@ static const struct MemmapEntry {
 [VIRT_RTC] =   { 0x96005000, 0x1000 },
 [VIRT_VIRTIO] ={ 0x9700, 0x1000 },
 [VIRT_OMPIC] = { 0x9800, VIRT_CPUS_MAX * 8 },
+[VIRT_ECAM] =  { 0x9e00,  0x100 },
+[VIRT_PIO] =   { 0x9f00,  0x100 },
+[VIRT_MMIO] =  { 0xa000, 0x1000 },
 };
 
 static struct openrisc_boot_info {
@@ -115,12 +124,12 @@ static qemu_irq get_per_cpu_irq(OpenRISCCPU *cpus[], int 
num_cpus, int irq_pin)
 static void openrisc_create_fdt(OR1KVirtState *state,
 const struct MemmapEntry *memmap,
 int num_cpus, uint64_t mem_size,
-const char *cmdline)
+const char *cmdline,
+int32_t *pic_phandle)
 {
 void *fdt;
 int cpu;
 char *nodename;
-int pic_ph;
 
 fdt = state->fdt = create_device_tree(>fdt_size);
 if (!fdt) {
@@ -163,14 +172,14 @@ static void openrisc_create_fdt(OR1KVirtState *state,
 
 nodename = (char *)"/pic";
 qemu_fdt_add_subnode(fdt, nodename);
-pic_ph = qemu_fdt_alloc_phandle(fdt);
+*pic_phandle = qemu_fdt_alloc_phandle(fdt);
 qemu_fdt_setprop_string(fdt, nodename, "compatible",
 "opencores,or1k-pic-level");
 qemu_fdt_setprop_cell(fdt, nodename, "#interrupt-cells", 1);
 qemu_fdt_setprop(fdt, nodename, "interrupt-controller", NULL, 0);
-qemu_fdt_setprop_cell(fdt, nodename, "phandle", pic_ph);
+qemu_fdt_setprop_cell(fdt, nodename, "phandle", *pic_phandle);
 
-qemu_fdt_setprop_cell(fdt, "/", "interrupt-parent", pic_ph);
+qemu_fdt_setprop_cell(fdt, "/", "interrupt-parent", *pic_phandle);
 
 qemu_fdt_add_subnode(fdt, "/chosen");
 if (cmdline) {
@@ -275,6 +284,7 @@ static void openrisc_virt_test_init(OR1KVirtState *state, 
hwaddr base,
 g_free(nodename);
 
 }
+
 static void openrisc_virt_rtc_init(OR1KVirtState *state, hwaddr base,
hwaddr size, int num_cpus,
OpenRISCCPU *cpus[], int irq_pin)
@@ -296,6 +306,134 @@ static void openrisc_virt_rtc_init(OR1KVirtState *state, 
hwaddr base,
 g_free(nodename);
 
 }
+
+static void create_pcie_irq_map(void *fdt, char *nodename, int irq_base,
+uint32_t irqchip_phandle)
+{
+int pin, dev;
+uint32_t irq_map_stride = 0;
+uint32_t full_irq_map[GPEX_NUM_IRQS * GPEX_NUM_IRQS * 6] = {};
+uint32_t *irq_map = full_irq_map;
+
+/*
+ * This code creates a standard swizzle of interrupts such that
+ * each device's first interrupt is based on it's PCI_SLOT number.
+ * (See pci_swizzle_map_irq_fn())
+ *
+ * We only need one entry per interrupt in the table (not one per
+ * possible slot) seeing the interrupt-map-mask will allow the table
+ * to wrap to any number of devices.
+ */
+for (dev = 0; dev < GPEX_NUM_IRQS; dev++) {
+int devfn = dev << 3;
+
+for (pin = 0; pin < GPEX_NUM_IRQS; pin++) {
+int irq_nr = irq_base + ((pin + PCI_SLOT(devfn)) % GPEX_NUM_IRQS);
+

[PATCH v3 02/11] target/openrisc: Fix memory reading in debugger

2022-07-29 Thread Stafford Horne
In commit f0655423ca ("target/openrisc: Reorg tlb lookup") data and
instruction TLB reads were combined.  This, broke debugger reads where
we first tried to map using the data tlb then fall back to the
instruction tlb.

This patch replicates this logic by first requesting a PAGE_READ
protection mapping then falling back to PAGE_EXEC.

Reviewed-by: Richard Henderson 
Signed-off-by: Stafford Horne 
---
Since v2:
 - No changes, added Reviewed-by

 target/openrisc/mmu.c | 8 +++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/target/openrisc/mmu.c b/target/openrisc/mmu.c
index d7e1320998..0b8afdbacf 100644
--- a/target/openrisc/mmu.c
+++ b/target/openrisc/mmu.c
@@ -148,7 +148,13 @@ hwaddr openrisc_cpu_get_phys_page_debug(CPUState *cs, 
vaddr addr)
 case SR_DME | SR_IME:
 /* The mmu is definitely enabled.  */
 excp = get_phys_mmu(cpu, _addr, , addr,
-PAGE_EXEC | PAGE_READ | PAGE_WRITE,
+PAGE_READ,
+(sr & SR_SM) != 0);
+if (!excp) {
+return phys_addr;
+}
+excp = get_phys_mmu(cpu, _addr, , addr,
+PAGE_EXEC,
 (sr & SR_SM) != 0);
 return excp ? -1 : phys_addr;
 
-- 
2.37.1




[PATCH v3 01/11] hw/openrisc: Split re-usable boot time apis out to boot.c

2022-07-29 Thread Stafford Horne
These will be shared with the virt platform.

Reviewed-by: Richard Henderson 
Signed-off-by: Stafford Horne 
---
Since v2:
 - No changes

 hw/openrisc/boot.c | 117 +
 hw/openrisc/meson.build|   1 +
 hw/openrisc/openrisc_sim.c | 106 ++---
 include/hw/openrisc/boot.h |  34 +++
 4 files changed, 158 insertions(+), 100 deletions(-)
 create mode 100644 hw/openrisc/boot.c
 create mode 100644 include/hw/openrisc/boot.h

diff --git a/hw/openrisc/boot.c b/hw/openrisc/boot.c
new file mode 100644
index 00..ca773b385e
--- /dev/null
+++ b/hw/openrisc/boot.c
@@ -0,0 +1,117 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * QEMU OpenRISC boot helpers.
+ *
+ * (c) 2022 Stafford Horne 
+ */
+
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "exec/cpu-defs.h"
+#include "elf.h"
+#include "hw/loader.h"
+#include "hw/openrisc/boot.h"
+#include "sysemu/device_tree.h"
+#include "sysemu/qtest.h"
+
+#include 
+
+#define KERNEL_LOAD_ADDR 0x100
+
+hwaddr openrisc_load_kernel(ram_addr_t ram_size,
+const char *kernel_filename,
+uint32_t *bootstrap_pc)
+{
+long kernel_size;
+uint64_t elf_entry;
+uint64_t high_addr;
+hwaddr entry;
+
+if (kernel_filename && !qtest_enabled()) {
+kernel_size = load_elf(kernel_filename, NULL, NULL, NULL,
+   _entry, NULL, _addr, NULL, 1,
+   EM_OPENRISC, 1, 0);
+entry = elf_entry;
+if (kernel_size < 0) {
+kernel_size = load_uimage(kernel_filename,
+  , NULL, NULL, NULL, NULL);
+high_addr = entry + kernel_size;
+}
+if (kernel_size < 0) {
+kernel_size = load_image_targphys(kernel_filename,
+  KERNEL_LOAD_ADDR,
+  ram_size - KERNEL_LOAD_ADDR);
+high_addr = KERNEL_LOAD_ADDR + kernel_size;
+}
+
+if (entry <= 0) {
+entry = KERNEL_LOAD_ADDR;
+}
+
+if (kernel_size < 0) {
+error_report("couldn't load the kernel '%s'", kernel_filename);
+exit(1);
+}
+*bootstrap_pc = entry;
+
+return high_addr;
+}
+return 0;
+}
+
+hwaddr openrisc_load_initrd(void *fdt, const char *filename,
+hwaddr load_start, uint64_t mem_size)
+{
+int size;
+hwaddr start;
+
+/* We put the initrd right after the kernel; page aligned. */
+start = TARGET_PAGE_ALIGN(load_start);
+
+size = load_ramdisk(filename, start, mem_size - start);
+if (size < 0) {
+size = load_image_targphys(filename, start, mem_size - start);
+if (size < 0) {
+error_report("could not load ramdisk '%s'", filename);
+exit(1);
+}
+}
+
+if (fdt) {
+qemu_fdt_setprop_cell(fdt, "/chosen",
+  "linux,initrd-start", start);
+qemu_fdt_setprop_cell(fdt, "/chosen",
+  "linux,initrd-end", start + size);
+}
+
+return start + size;
+}
+
+uint32_t openrisc_load_fdt(void *fdt, hwaddr load_start,
+   uint64_t mem_size)
+{
+uint32_t fdt_addr;
+int ret;
+int fdtsize = fdt_totalsize(fdt);
+
+if (fdtsize <= 0) {
+error_report("invalid device-tree");
+exit(1);
+}
+
+/* We put fdt right after the kernel and/or initrd. */
+fdt_addr = TARGET_PAGE_ALIGN(load_start);
+
+ret = fdt_pack(fdt);
+/* Should only fail if we've built a corrupted tree */
+g_assert(ret == 0);
+/* copy in the device tree */
+qemu_fdt_dumpdtb(fdt, fdtsize);
+
+rom_add_blob_fixed_as("fdt", fdt, fdtsize, fdt_addr,
+  _space_memory);
+
+return fdt_addr;
+}
+
diff --git a/hw/openrisc/meson.build b/hw/openrisc/meson.build
index ec48172c9d..ab563820c5 100644
--- a/hw/openrisc/meson.build
+++ b/hw/openrisc/meson.build
@@ -1,5 +1,6 @@
 openrisc_ss = ss.source_set()
 openrisc_ss.add(files('cputimer.c'))
+openrisc_ss.add(files('boot.c'))
 openrisc_ss.add(when: 'CONFIG_OR1K_SIM', if_true: [files('openrisc_sim.c'), 
fdt])
 
 hw_arch += {'openrisc': openrisc_ss}
diff --git a/hw/openrisc/openrisc_sim.c b/hw/openrisc/openrisc_sim.c
index 35adce17ac..35da123aef 100644
--- a/hw/openrisc/openrisc_sim.c
+++ b/hw/openrisc/openrisc_sim.c
@@ -24,10 +24,9 @@
 #include "cpu.h"
 #include "hw/irq.h"
 #include "hw/boards.h"
-#include "elf.h"
 #include "hw/char/serial.h"
 #include "net/net.h"
-#include "hw/loader.h"
+#include "hw/openrisc/boot.h"
 #includ

[PATCH v3 09/11] target/openrisc: Interrupt handling fixes

2022-07-29 Thread Stafford Horne
When running SMP systems we sometimes were seeing lockups where
IPI interrupts were being raised by never handled.

This looks to be caused by 2 issues in the openrisc interrupt handling
logic.

 1. After clearing an interrupt the openrisc_cpu_set_irq handler will
always clear PICSR.  This is not correct as masked interrupts
should still be visible in PICSR.
 2. After setting PICMR (mask register) and exposed interrupts should
cause an interrupt to be raised.  This was not being done so add it.

This patch fixes both issues.

Reviewed-by: Richard Henderson 
Signed-off-by: Stafford Horne 
---
Since v2:
 - Added Reviewed-by

 target/openrisc/cpu.c| 1 -
 target/openrisc/sys_helper.c | 7 +++
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/target/openrisc/cpu.c b/target/openrisc/cpu.c
index 41d1b2a24a..cb9f35f408 100644
--- a/target/openrisc/cpu.c
+++ b/target/openrisc/cpu.c
@@ -98,7 +98,6 @@ static void openrisc_cpu_set_irq(void *opaque, int irq, int 
level)
 cpu_interrupt(cs, CPU_INTERRUPT_HARD);
 } else {
 cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
-cpu->env.picsr = 0;
 }
 }
 #endif
diff --git a/target/openrisc/sys_helper.c b/target/openrisc/sys_helper.c
index da88ad9e77..09b3c97d7c 100644
--- a/target/openrisc/sys_helper.c
+++ b/target/openrisc/sys_helper.c
@@ -139,6 +139,13 @@ void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong 
spr, target_ulong rb)
 break;
 case TO_SPR(9, 0):  /* PICMR */
 env->picmr = rb;
+qemu_mutex_lock_iothread();
+if (env->picsr & env->picmr) {
+cpu_interrupt(cs, CPU_INTERRUPT_HARD);
+} else {
+cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
+}
+qemu_mutex_unlock_iothread();
 break;
 case TO_SPR(9, 2):  /* PICSR */
 env->picsr &= ~rb;
-- 
2.37.1




[PATCH v3 06/11] hw/openrisc: Initialize timer time at startup

2022-07-29 Thread Stafford Horne
The last_clk time was initialized at zero, this means when we calculate
the first delta we will calculate 0 vs current time which could cause
unnecessary hops.

This patch moves timer initialization to the cpu reset.  There are two
resets registered here:

 1. Per cpu timer mask (ttmr) reset.
 2. Global cpu timer (last_clk and ttcr) reset, attached to the first
cpu only.

Signed-off-by: Stafford Horne 
---
Since v2:
 - Moved timer init from init to reset suggested by Richard

 hw/openrisc/cputimer.c | 22 +-
 1 file changed, 21 insertions(+), 1 deletion(-)

diff --git a/hw/openrisc/cputimer.c b/hw/openrisc/cputimer.c
index 93268815d8..10163b391b 100644
--- a/hw/openrisc/cputimer.c
+++ b/hw/openrisc/cputimer.c
@@ -22,6 +22,7 @@
 #include "cpu.h"
 #include "migration/vmstate.h"
 #include "qemu/timer.h"
+#include "sysemu/reset.h"
 
 #define TIMER_PERIOD 50 /* 50 ns period for 20 MHz timer */
 
@@ -122,6 +123,24 @@ static void openrisc_timer_cb(void *opaque)
 qemu_cpu_kick(CPU(cpu));
 }
 
+/* Reset the per CPU counter state. */
+static void openrisc_count_reset(void *opaque)
+{
+OpenRISCCPU *cpu = opaque;
+
+if (cpu->env.is_counting) {
+cpu_openrisc_count_stop(cpu);
+}
+cpu->env.ttmr = 0x;
+}
+
+/* Reset the global timer state. */
+static void openrisc_timer_reset(void *opaque)
+{
+or1k_timer->ttcr = 0x;
+or1k_timer->last_clk = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+}
+
 static const VMStateDescription vmstate_or1k_timer = {
 .name = "or1k_timer",
 .version_id = 1,
@@ -136,10 +155,11 @@ static const VMStateDescription vmstate_or1k_timer = {
 void cpu_openrisc_clock_init(OpenRISCCPU *cpu)
 {
 cpu->env.timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, _timer_cb, cpu);
-cpu->env.ttmr = 0x;
 
+qemu_register_reset(openrisc_count_reset, cpu);
 if (or1k_timer == NULL) {
 or1k_timer = g_new0(OR1KTimerState, 1);
+qemu_register_reset(openrisc_timer_reset, cpu);
 vmstate_register(NULL, 0, _or1k_timer, or1k_timer);
 }
 }
-- 
2.37.1




[PATCH v3 04/11] hw/openrisc: Add the OpenRISC virtual machine

2022-07-29 Thread Stafford Horne
This patch adds the OpenRISC virtual machine 'virt' for OpenRISC.  This
platform allows for a convenient CI platform for toolchain, software
ports and the OpenRISC linux kernel port.

Much of this has been sourced from the m68k and riscv virt platforms.

The platform provides:
 - OpenRISC SMP with up to 4 cpus
 - A virtio bus with up to 8 devices
 - Standard ns16550a serial
 - Goldfish RTC
 - SiFive TEST device for poweroff and reboot
 - Generated Device Tree to automatically configure the guest kernel

Signed-off-by: Stafford Horne 
---
Since v2:
 - No changes

 configs/devices/or1k-softmmu/default.mak |   1 +
 hw/openrisc/Kconfig  |   9 +
 hw/openrisc/meson.build  |   1 +
 hw/openrisc/virt.c   | 417 +++
 4 files changed, 428 insertions(+)
 create mode 100644 hw/openrisc/virt.c

diff --git a/configs/devices/or1k-softmmu/default.mak 
b/configs/devices/or1k-softmmu/default.mak
index 168101c39a..89c39e3123 100644
--- a/configs/devices/or1k-softmmu/default.mak
+++ b/configs/devices/or1k-softmmu/default.mak
@@ -3,3 +3,4 @@
 # Boards:
 #
 CONFIG_OR1K_SIM=y
+CONFIG_OR1K_VIRT=y
diff --git a/hw/openrisc/Kconfig b/hw/openrisc/Kconfig
index 8f284f3ba0..202134668e 100644
--- a/hw/openrisc/Kconfig
+++ b/hw/openrisc/Kconfig
@@ -4,3 +4,12 @@ config OR1K_SIM
 select OPENCORES_ETH
 select OMPIC
 select SPLIT_IRQ
+
+config OR1K_VIRT
+bool
+imply VIRTIO_VGA
+imply TEST_DEVICES
+select GOLDFISH_RTC
+select SERIAL
+select SIFIVE_TEST
+select VIRTIO_MMIO
diff --git a/hw/openrisc/meson.build b/hw/openrisc/meson.build
index ab563820c5..2dbc6365bb 100644
--- a/hw/openrisc/meson.build
+++ b/hw/openrisc/meson.build
@@ -2,5 +2,6 @@ openrisc_ss = ss.source_set()
 openrisc_ss.add(files('cputimer.c'))
 openrisc_ss.add(files('boot.c'))
 openrisc_ss.add(when: 'CONFIG_OR1K_SIM', if_true: [files('openrisc_sim.c'), 
fdt])
+openrisc_ss.add(when: 'CONFIG_OR1K_VIRT', if_true: [files('virt.c'), fdt])
 
 hw_arch += {'openrisc': openrisc_ss}
diff --git a/hw/openrisc/virt.c b/hw/openrisc/virt.c
new file mode 100644
index 00..54f2732a6b
--- /dev/null
+++ b/hw/openrisc/virt.c
@@ -0,0 +1,417 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * OpenRISC QEMU virtual machine.
+ *
+ * (c) 2022 Stafford Horne 
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/error-report.h"
+#include "qapi/error.h"
+#include "cpu.h"
+#include "exec/address-spaces.h"
+#include "hw/irq.h"
+#include "hw/boards.h"
+#include "hw/char/serial.h"
+#include "hw/core/split-irq.h"
+#include "hw/openrisc/boot.h"
+#include "hw/misc/sifive_test.h"
+#include "hw/qdev-properties.h"
+#include "hw/rtc/goldfish_rtc.h"
+#include "hw/sysbus.h"
+#include "hw/virtio/virtio-mmio.h"
+#include "sysemu/device_tree.h"
+#include "sysemu/sysemu.h"
+#include "sysemu/qtest.h"
+#include "sysemu/reset.h"
+
+#include 
+
+#define VIRT_CPUS_MAX 4
+#define VIRT_CLK_MHZ 2000
+
+#define TYPE_VIRT_MACHINE MACHINE_TYPE_NAME("virt")
+#define VIRT_MACHINE(obj) \
+OBJECT_CHECK(OR1KVirtState, (obj), TYPE_VIRT_MACHINE)
+
+typedef struct OR1KVirtState {
+/*< private >*/
+MachineState parent_obj;
+
+/*< public >*/
+void *fdt;
+int fdt_size;
+
+} OR1KVirtState;
+
+enum {
+VIRT_DRAM,
+VIRT_TEST,
+VIRT_RTC,
+VIRT_VIRTIO,
+VIRT_UART,
+VIRT_OMPIC,
+};
+
+enum {
+VIRT_OMPIC_IRQ = 1,
+VIRT_UART_IRQ = 2,
+VIRT_RTC_IRQ = 3,
+VIRT_VIRTIO_IRQ = 4, /* to 12 */
+VIRTIO_COUNT = 8,
+};
+
+static const struct MemmapEntry {
+hwaddr base;
+hwaddr size;
+} virt_memmap[] = {
+[VIRT_DRAM] =  { 0x,  0 },
+[VIRT_UART] =  { 0x9000,  0x100 },
+[VIRT_TEST] =  { 0x9600,0x8 },
+[VIRT_RTC] =   { 0x96005000, 0x1000 },
+[VIRT_VIRTIO] ={ 0x9700, 0x1000 },
+[VIRT_OMPIC] = { 0x9800, VIRT_CPUS_MAX * 8 },
+};
+
+static struct openrisc_boot_info {
+uint32_t bootstrap_pc;
+uint32_t fdt_addr;
+} boot_info;
+
+static void main_cpu_reset(void *opaque)
+{
+OpenRISCCPU *cpu = opaque;
+CPUState *cs = CPU(cpu);
+
+cpu_reset(CPU(cpu));
+
+cpu_set_pc(cs, boot_info.bootstrap_pc);
+cpu_set_gpr(>env, 3, boot_info.fdt_addr);
+}
+
+static qemu_irq get_cpu_irq(OpenRISCCPU *cpus[], int cpunum, int irq_pin)
+{
+return qdev_get_gpio_in_named(DEVICE(cpus[cpunum]), "IRQ", irq_pin);
+}
+
+static qemu_irq get_per_cpu_irq(OpenRISCCPU *cpus[], int num_cpus, int irq_pin)
+{
+int i;
+
+if (num_cpus > 1) {
+DeviceState *splitter = qdev_new(TYPE_SPLIT_IRQ);
+qdev_prop_set_uint32(splitter, "num-lines", num_cpus);
+qdev_realize_and_unref(splitter, NULL, _fatal);

[PATCH v3 00/11] OpenRISC Virtual Machine

2022-07-29 Thread Stafford Horne
Hello,

This is the OpenRISC Virtual Machine plaform which we are now using for OpenRISC
CI such as the wireguard testing that Jason has been working on.  I also have
recently used it to test glibc 2.36 and it worked well. Previous glibc testsuite
runs on my FPGA board took about 3 days, running on qemu virt now takes 6 hours.

The first few patches help get OpenRISC QEMU ready for the virtual machine.
There is one bug fix for GDB debugging there too.

Next we have the Virt patch followed by a separate patch to add PCI support
which is split out because it's a bit easier to review that way I thought.  The
next few patches are fixes to get the Multicore platform stable, such as adding
MTTCG support and fixing some interrupt and timer related bugs.

The platform is relatively stable now, but every few boots we get about 10
second hangs.  However, overall this is much more stable than the SMP support we
had before.  So I want to submit this for review and maybe upstream it before
tracking down these last issues which might take significant more time.

This is being tested with the or1k-5.20-updates kernel branch here:

  https://github.com/stffrdhrn/linux/commits/or1k-5.20-updates

  This tree has support for: OpenRISC PCI and virt_defconfig and an irqchip bug
  fix.

Changes since v2:
 - Changed goldfish_rtc endian property to boolean
 - Moved or1k timer init from init to reset
 - Removed cpu_openrisc_timer_has_advanced lock optimization in MTTCG patch,
   measuring revealed it did not help much.
Changes since v1:
 - Dropped semihosting support
 - Added PCI support
 - Added OpenRISC documentation
 - Added OpenRISC support for MTTCG
 - Support Configurating Goldfish RTC endianness
 - Added a few bug fix patches

Jason A. Donenfeld (1):
  hw/openrisc: virt: pass random seed to fdt

Stafford Horne (10):
  hw/openrisc: Split re-usable boot time apis out to boot.c
  target/openrisc: Fix memory reading in debugger
  goldfish_rtc: Add big-endian property
  hw/openrisc: Add the OpenRISC virtual machine
  hw/openrisc: Add PCI bus support to virt
  hw/openrisc: Initialize timer time at startup
  target/openrisc: Add interrupted CPU to log
  target/openrisc: Enable MTTCG
  target/openrisc: Interrupt handling fixes
  docs/system: openrisc: Add OpenRISC documentation

 configs/devices/or1k-softmmu/default.mak |   1 +
 configs/targets/or1k-softmmu.mak |   1 +
 docs/system/openrisc/cpu-features.rst|  15 +
 docs/system/openrisc/emulation.rst   |  17 +
 docs/system/openrisc/or1k-sim.rst|  43 ++
 docs/system/openrisc/virt.rst|  50 ++
 docs/system/target-openrisc.rst  |  72 +++
 docs/system/targets.rst  |   1 +
 hw/m68k/virt.c   |   1 +
 hw/openrisc/Kconfig  |  12 +
 hw/openrisc/boot.c   | 117 +
 hw/openrisc/cputimer.c   |  22 +-
 hw/openrisc/meson.build  |   2 +
 hw/openrisc/openrisc_sim.c   | 106 +
 hw/openrisc/virt.c   | 571 +++
 hw/rtc/goldfish_rtc.c|  37 +-
 include/hw/openrisc/boot.h   |  34 ++
 include/hw/rtc/goldfish_rtc.h|   2 +
 target/openrisc/cpu.c|   1 -
 target/openrisc/cpu.h|   2 +
 target/openrisc/interrupt.c  |   4 +-
 target/openrisc/mmu.c|   8 +-
 target/openrisc/sys_helper.c |  14 +-
 23 files changed, 1019 insertions(+), 114 deletions(-)
 create mode 100644 docs/system/openrisc/cpu-features.rst
 create mode 100644 docs/system/openrisc/emulation.rst
 create mode 100644 docs/system/openrisc/or1k-sim.rst
 create mode 100644 docs/system/openrisc/virt.rst
 create mode 100644 docs/system/target-openrisc.rst
 create mode 100644 hw/openrisc/boot.c
 create mode 100644 hw/openrisc/virt.c
 create mode 100644 include/hw/openrisc/boot.h

-- 
2.37.1




Re: [PATCH v2 03/11] goldfish_rtc: Add endianness property

2022-07-04 Thread Stafford Horne
On Mon, Jul 04, 2022 at 12:23:23PM +0200, Laurent Vivier wrote:
> On 04/07/2022 12:21, Richard Henderson wrote:
> > On 7/4/22 15:46, Laurent Vivier wrote:
> > > On 04/07/2022 11:59, Richard Henderson wrote:
> > > > On 7/4/22 02:58, Stafford Horne wrote:
> > > > > -static const MemoryRegionOps goldfish_rtc_ops = {
> > > > > -    .read = goldfish_rtc_read,
> > > > > -    .write = goldfish_rtc_write,
> > > > > -    .endianness = DEVICE_NATIVE_ENDIAN,
> > > > > -    .valid = {
> > > > > -    .min_access_size = 4,
> > > > > -    .max_access_size = 4
> > > > > -    }
> > > > > +static const MemoryRegionOps goldfish_rtc_ops[3] = {
> > > > > +    [DEVICE_NATIVE_ENDIAN] = {
> > > > > +    .read = goldfish_rtc_read,
> > > > > +    .write = goldfish_rtc_write,
> > > > > +    .endianness = DEVICE_NATIVE_ENDIAN,
> > > > > +    .valid = {
> > > > > +    .min_access_size = 4,
> > > > > +    .max_access_size = 4
> > > > > +    }
> > > > > +    },
> > > > > +    [DEVICE_LITTLE_ENDIAN] = {
> > > > > +    .read = goldfish_rtc_read,
> > > > > +    .write = goldfish_rtc_write,
> > > > > +    .endianness = DEVICE_LITTLE_ENDIAN,
> > > > > +    .valid = {
> > > > > +    .min_access_size = 4,
> > > > > +    .max_access_size = 4
> > > > > +    }
> > > > > +    },
> > > > > +    [DEVICE_BIG_ENDIAN] = {
> > > > > +    .read = goldfish_rtc_read,
> > > > > +    .write = goldfish_rtc_write,
> > > > > +    .endianness = DEVICE_BIG_ENDIAN,
> > > > > +    .valid = {
> > > > > +    .min_access_size = 4,
> > > > > +    .max_access_size = 4
> > > > > +    }
> > > > > +    },
> > > > >   };
> > > > 
> > > > You don't need 3 copies, only big and little.
> > > > 
> > > > > +static Property goldfish_rtc_properties[] = {
> > > > > +    DEFINE_PROP_UINT8("endianness", GoldfishRTCState, endianness,
> > > > > +  DEVICE_NATIVE_ENDIAN),
> > > > > +    DEFINE_PROP_END_OF_LIST(),
> > > > > +};
> > > > 
> > > > ... and I think the clear desire for default is little-endian. 
> > > > I would make the property be bool, and add a comment that this
> > > > is only for m68k compatibility, so don't use it in new code.
> > > 
> > > m68k doesn't really need this.
> > > 
> > > kernel with the m68k virt machine and goldfish device supports
> > > "native" mode so I think it's not needed to add another layer of
> > > complexity for it.
> > 
> > "Another level"?  I'm talking about removing "native", and only having
> > "big" and "little", which is less complexity.
> 
> "Less complexity" is to keep only native. I'm not against the change, I'm
> just saying it's not needed by m68k.

Hi Laurent,

I would agree if we only had m68k.  But I am making this change so that OpenRISC
(another big-endian architecture) could use this.  In the OpenRISC case we want
to use this as little-endian so no kernel updates would be needed.

So in the end we will have the following qemu platforms:

  riscv{LE}--->goldfish_rtc{LE}
  mips-longsoon3{LE}-->goldfish_rtc{LE}
  openrisc{BE}>goldfish_rtc{LE} (LE to BE conversion done in driver)
  m68k{BE}>goldfish_rtc{BE} (only big-endian user)

-Stafford



Re: [PATCH v2 03/11] goldfish_rtc: Add endianness property

2022-07-04 Thread Stafford Horne
On Mon, Jul 04, 2022 at 03:29:57PM +0530, Richard Henderson wrote:
> On 7/4/22 02:58, Stafford Horne wrote:
> > -static const MemoryRegionOps goldfish_rtc_ops = {
> > -.read = goldfish_rtc_read,
> > -.write = goldfish_rtc_write,
> > -.endianness = DEVICE_NATIVE_ENDIAN,
> > -.valid = {
> > -.min_access_size = 4,
> > -.max_access_size = 4
> > -}
> > +static const MemoryRegionOps goldfish_rtc_ops[3] = {
> > +[DEVICE_NATIVE_ENDIAN] = {
> > +.read = goldfish_rtc_read,
> > +.write = goldfish_rtc_write,
> > +.endianness = DEVICE_NATIVE_ENDIAN,
> > +.valid = {
> > +.min_access_size = 4,
> > +.max_access_size = 4
> > +}
> > +},
> > +[DEVICE_LITTLE_ENDIAN] = {
> > +.read = goldfish_rtc_read,
> > +.write = goldfish_rtc_write,
> > +.endianness = DEVICE_LITTLE_ENDIAN,
> > +.valid = {
> > +.min_access_size = 4,
> > +.max_access_size = 4
> > +}
> > +},
> > +[DEVICE_BIG_ENDIAN] = {
> > +.read = goldfish_rtc_read,
> > +.write = goldfish_rtc_write,
> > +.endianness = DEVICE_BIG_ENDIAN,
> > +.valid = {
> > +.min_access_size = 4,
> > +.max_access_size = 4
> > +}
> > +},
> >   };
> 
> You don't need 3 copies, only big and little.
> 
> > +static Property goldfish_rtc_properties[] = {
> > +DEFINE_PROP_UINT8("endianness", GoldfishRTCState, endianness,
> > +  DEVICE_NATIVE_ENDIAN),
> > +DEFINE_PROP_END_OF_LIST(),
> > +};
> 
> ... and I think the clear desire for default is little-endian.  I would make
> the property be bool, and add a comment that this is only for m68k
> compatibility, so don't use it in new code.

Yeah, that makes sense.

-Stafford



Re: [PATCH v2 06/11] hw/openrisc: Initialize timer time at startupi

2022-07-04 Thread Stafford Horne
On Mon, Jul 04, 2022 at 03:33:26PM +0530, Richard Henderson wrote:
> On 7/4/22 02:58, Stafford Horne wrote:
> > The last_clk time was initialized at zero, this means when we calculate
> > the first delta we will calculate 0 vs current time which could cause
> > unnecessary hops.
> > 
> > Initialize last_clk to the qemu clock on initialization.
> > 
> > Signed-off-by: Stafford Horne 
> > ---
> >   hw/openrisc/cputimer.c | 1 +
> >   1 file changed, 1 insertion(+)
> > 
> > diff --git a/hw/openrisc/cputimer.c b/hw/openrisc/cputimer.c
> > index 93268815d8..4dbba3a3d4 100644
> > --- a/hw/openrisc/cputimer.c
> > +++ b/hw/openrisc/cputimer.c
> > @@ -140,6 +140,7 @@ void cpu_openrisc_clock_init(OpenRISCCPU *cpu)
> >   if (or1k_timer == NULL) {
> >   or1k_timer = g_new0(OR1KTimerState, 1);
> > +or1k_timer->last_clk = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
> >   vmstate_register(NULL, 0, _or1k_timer, or1k_timer);
> >   }
> >   }
> 
> Init doesn't seem right.  Should be in reset?

Good point, I think reset would be better.



Re: [PATCH v2 08/11] target/openrisc: Enable MTTCG

2022-07-04 Thread Stafford Horne
On Mon, Jul 04, 2022 at 03:37:04PM +0530, Richard Henderson wrote:
> On 7/4/22 02:58, Stafford Horne wrote:
> >   case TO_SPR(10, 1): /* TTCR */
> > -cpu_openrisc_count_update(cpu);
> > +if (cpu_openrisc_timer_has_advanced(cpu)) {
> > +qemu_mutex_lock_iothread();
> > +cpu_openrisc_count_update(cpu);
> > +qemu_mutex_unlock_iothread();
> > +}
> 
> Lock around the whole if, I think.  Otherwise looks good.

Well, actually the cpu_openrisc_timer_has_advanced read is done once outside the
lock as an optimization to avoid taking the lock when it is not needed. i.e. if
we have 4 cores that all try to update the clock at the same time in theory only
one will have to take the lock and update the shared timer.

But I do see that could be flawed as after it takes the lock the timer could
have been updated by then.  Ill move it inside and see if there is any
perfromance hit / increase in the sync-profile.

> Reviewed-by: Richard Henderson 
> 
> 
> r~



Re: [PATCH v2 07/11] target/openrisc: Add interrupted CPU to log

2022-07-04 Thread Stafford Horne
On Mon, Jul 04, 2022 at 03:34:52PM +0530, Richard Henderson wrote:
> On 7/4/22 02:58, Stafford Horne wrote:
> > When we are tracing it's helpful to know which CPU's are getting
> > interrupted, att that detail to the log line.
> 
> "at".
> 
> Reviewed-by: Richard Henderson 

Actually it should be "add", thanks I fixed it.

-Stafford



[PATCH v2 11/11] docs/system: openrisc: Add OpenRISC documentation

2022-07-03 Thread Stafford Horne
Signed-off-by: Stafford Horne 
---
 docs/system/openrisc/cpu-features.rst | 15 ++
 docs/system/openrisc/emulation.rst| 17 +++
 docs/system/openrisc/or1k-sim.rst | 43 
 docs/system/openrisc/virt.rst | 50 +++
 docs/system/target-openrisc.rst   | 72 +++
 docs/system/targets.rst   |  1 +
 6 files changed, 198 insertions(+)
 create mode 100644 docs/system/openrisc/cpu-features.rst
 create mode 100644 docs/system/openrisc/emulation.rst
 create mode 100644 docs/system/openrisc/or1k-sim.rst
 create mode 100644 docs/system/openrisc/virt.rst
 create mode 100644 docs/system/target-openrisc.rst

diff --git a/docs/system/openrisc/cpu-features.rst 
b/docs/system/openrisc/cpu-features.rst
new file mode 100644
index 00..aeb65e22ff
--- /dev/null
+++ b/docs/system/openrisc/cpu-features.rst
@@ -0,0 +1,15 @@
+CPU Features
+
+
+The QEMU emulation of the OpenRISC architecture provides following built in
+features.
+
+- Shadow GPRs
+- MMU TLB with 128 entries, 1 way
+- Power Management (PM)
+- Programmable Interrupt Controller (PIC)
+- Tick Timer
+
+These features are on by default and the presence can be confirmed by checking
+the contents of the Unit Presence Register (``UPR``) and CPU Configuration
+Register (``CPUCFGR``).
diff --git a/docs/system/openrisc/emulation.rst 
b/docs/system/openrisc/emulation.rst
new file mode 100644
index 00..0af898ab20
--- /dev/null
+++ b/docs/system/openrisc/emulation.rst
@@ -0,0 +1,17 @@
+OpenRISC 1000 CPU architecture support
+==
+
+QEMU's TCG emulation includes support for the OpenRISC or1200 implementation of
+the OpenRISC 1000 cpu architecture.
+
+The or1200 cpu also has support for the following instruction subsets:
+
+- ORBIS32 (OpenRISC Basic Instruction Set)
+- ORFPX32 (OpenRISC Floating-Point eXtension)
+
+In addition to the instruction subsets the QEMU TCG emulation also has support
+for most Class II (optional) instructions.
+
+For information on all OpenRISC instructions please refer to the latest
+architecture manual available on the OpenRISC website in the
+`OpenRISC Architecture <https://openrisc.io/architecture>`_ section.
diff --git a/docs/system/openrisc/or1k-sim.rst 
b/docs/system/openrisc/or1k-sim.rst
new file mode 100644
index 00..ef10439737
--- /dev/null
+++ b/docs/system/openrisc/or1k-sim.rst
@@ -0,0 +1,43 @@
+Or1ksim board
+=
+
+The QEMU Or1ksim machine emulates the standard OpenRISC board simulator which 
is
+also the standard SoC configuration.
+
+Supported devices
+-
+
+ * 16550A UART
+ * ETHOC Ethernet controller
+ * SMP (OpenRISC multicore using ompic)
+
+Boot options
+
+
+The Or1ksim machine can be started using the ``-kernel`` and ``-initrd`` 
options
+to load a Linux kernel and optional disk image.
+
+.. code-block:: bash
+
+  $ qemu-system-or1k -cpu or1220 -M or1k-sim -nographic \
+-kernel vmlinux \
+-initrd initramfs.cpio.gz \
+-m 128
+
+Linux guest kernel configuration
+""""""""""""""""""""""""""""""""
+
+The 'or1ksim_defconfig' for Linux openrisc kernels includes the right
+drivers for the or1ksim machine.  If you would like to run an SMP system
+choose the 'simple_smp_defconfig' config.
+
+Hardware configuration information
+""""""""""""""""""""""""""""""""""
+
+The ``or1k-sim`` board automatically generates a device tree blob ("dtb")
+which it passes to the guest. This provides information about the
+addresses, interrupt lines and other configuration of the various devices
+in the system.
+
+The location of the DTB will be passed in register ``r3`` to the guest 
operating
+system.
diff --git a/docs/system/openrisc/virt.rst b/docs/system/openrisc/virt.rst
new file mode 100644
index 00..2fe61ac942
--- /dev/null
+++ b/docs/system/openrisc/virt.rst
@@ -0,0 +1,50 @@
+'virt' generic virtual platform
+===
+
+The ``virt`` board is a platform which does not correspond to any
+real hardware; it is designed for use in virtual machines.
+It is the recommended board type if you simply want to run
+a guest such as Linux and do not care about reproducing the
+idiosyncrasies and limitations of a particular bit of real-world
+hardware.
+
+Supported devices
+-
+
+ * PCI/PCIe devices
+ * 8 virtio-mmio transport devices
+ * 16550A UART
+ * Goldfish RTC
+ * SiFive Test device for poweroff and reboot
+ * SMP (OpenRISC multicore using ompic)
+
+Boot options
+
+
+The virt machine can be started using the ``-kernel`` and ``-initrd`` option

[PATCH v2 10/11] hw/openrisc: virt: pass random seed to fdt

2022-07-03 Thread Stafford Horne
From: "Jason A. Donenfeld" 

If the FDT contains /chosen/rng-seed, then the Linux RNG will use it to
initialize early. Set this using the usual guest random number
generation function. This is confirmed to successfully initialize the
RNG on Linux 5.19-rc2.

Cc: Stafford Horne 
Signed-off-by: Jason A. Donenfeld 
Signed-off-by: Stafford Horne 
---
 hw/openrisc/virt.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/hw/openrisc/virt.c b/hw/openrisc/virt.c
index f1d1293eeb..a301d0d769 100644
--- a/hw/openrisc/virt.c
+++ b/hw/openrisc/virt.c
@@ -8,6 +8,7 @@
 
 #include "qemu/osdep.h"
 #include "qemu/error-report.h"
+#include "qemu/guest-random.h"
 #include "qapi/error.h"
 #include "cpu.h"
 #include "exec/address-spaces.h"
@@ -130,6 +131,7 @@ static void openrisc_create_fdt(OR1KVirtState *state,
 void *fdt;
 int cpu;
 char *nodename;
+uint8_t rng_seed[32];
 
 fdt = state->fdt = create_device_tree(>fdt_size);
 if (!fdt) {
@@ -186,6 +188,10 @@ static void openrisc_create_fdt(OR1KVirtState *state,
 qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", cmdline);
 }
 
+/* Pass seed to RNG. */
+qemu_guest_getrandom_nofail(rng_seed, sizeof(rng_seed));
+qemu_fdt_setprop(fdt, "/chosen", "rng-seed", rng_seed, sizeof(rng_seed));
+
 /* Create aliases node for use by devices. */
 qemu_fdt_add_subnode(fdt, "/aliases");
 }
-- 
2.36.1




[PATCH v2 08/11] target/openrisc: Enable MTTCG

2022-07-03 Thread Stafford Horne
This patch enables multithread TCG for OpenRISC.  Since the or1k shared
syncrhonized timer can be updated from each vCPU via helpers we use a
mutex to synchronize updates.

Signed-off-by: Stafford Horne 
---
 configs/targets/or1k-softmmu.mak |  1 +
 hw/openrisc/cputimer.c   | 17 +
 target/openrisc/cpu.h|  3 +++
 target/openrisc/sys_helper.c | 11 +--
 4 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/configs/targets/or1k-softmmu.mak b/configs/targets/or1k-softmmu.mak
index 263e970870..432f855a30 100644
--- a/configs/targets/or1k-softmmu.mak
+++ b/configs/targets/or1k-softmmu.mak
@@ -1,3 +1,4 @@
 TARGET_ARCH=openrisc
+TARGET_SUPPORTS_MTTCG=y
 TARGET_BIG_ENDIAN=y
 TARGET_NEED_FDT=y
diff --git a/hw/openrisc/cputimer.c b/hw/openrisc/cputimer.c
index 4dbba3a3d4..2298eff8b9 100644
--- a/hw/openrisc/cputimer.c
+++ b/hw/openrisc/cputimer.c
@@ -43,6 +43,23 @@ uint32_t cpu_openrisc_count_get(OpenRISCCPU *cpu)
 return or1k_timer->ttcr;
 }
 
+/*
+ * Check to see if calling cpu_openrisc_count_update will
+ * actually advance the time.
+ *
+ * Used in hot spots to avoid taking expensive locks.
+ */
+bool cpu_openrisc_timer_has_advanced(OpenRISCCPU *cpu)
+{
+uint64_t now;
+
+if (!cpu->env.is_counting) {
+return false;
+}
+now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+return (now - or1k_timer->last_clk) >= TIMER_PERIOD;
+}
+
 /* Add elapsed ticks to ttcr */
 void cpu_openrisc_count_update(OpenRISCCPU *cpu)
 {
diff --git a/target/openrisc/cpu.h b/target/openrisc/cpu.h
index b9584f10d4..5354d681f5 100644
--- a/target/openrisc/cpu.h
+++ b/target/openrisc/cpu.h
@@ -25,6 +25,8 @@
 #include "hw/core/cpu.h"
 #include "qom/object.h"
 
+#define TCG_GUEST_DEFAULT_MO (0)
+
 #define TYPE_OPENRISC_CPU "or1k-cpu"
 
 OBJECT_DECLARE_CPU_TYPE(OpenRISCCPU, OpenRISCCPUClass, OPENRISC_CPU)
@@ -333,6 +335,7 @@ void cpu_openrisc_pic_init(OpenRISCCPU *cpu);
 
 /* hw/openrisc_timer.c */
 void cpu_openrisc_clock_init(OpenRISCCPU *cpu);
+bool cpu_openrisc_timer_has_advanced(OpenRISCCPU *cpu);
 uint32_t cpu_openrisc_count_get(OpenRISCCPU *cpu);
 void cpu_openrisc_count_set(OpenRISCCPU *cpu, uint32_t val);
 void cpu_openrisc_count_update(OpenRISCCPU *cpu);
diff --git a/target/openrisc/sys_helper.c b/target/openrisc/sys_helper.c
index 48674231e7..7c0d3d6187 100644
--- a/target/openrisc/sys_helper.c
+++ b/target/openrisc/sys_helper.c
@@ -145,6 +145,7 @@ void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong spr, 
target_ulong rb)
 break;
 case TO_SPR(10, 0): /* TTMR */
 {
+qemu_mutex_lock_iothread();
 if ((env->ttmr & TTMR_M) ^ (rb & TTMR_M)) {
 switch (rb & TTMR_M) {
 case TIMER_NONE:
@@ -168,14 +169,16 @@ void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong 
spr, target_ulong rb)
 env->ttmr = rb & ~TTMR_IP;
 cs->interrupt_request &= ~CPU_INTERRUPT_TIMER;
 }
-
 cpu_openrisc_timer_update(cpu);
+qemu_mutex_unlock_iothread();
 }
 break;
 
 case TO_SPR(10, 1): /* TTCR */
+qemu_mutex_lock_iothread();
 cpu_openrisc_count_set(cpu, rb);
 cpu_openrisc_timer_update(cpu);
+qemu_mutex_unlock_iothread();
 break;
 #endif
 
@@ -303,7 +306,11 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env, 
target_ulong rd,
 return env->ttmr;
 
 case TO_SPR(10, 1): /* TTCR */
-cpu_openrisc_count_update(cpu);
+if (cpu_openrisc_timer_has_advanced(cpu)) {
+qemu_mutex_lock_iothread();
+cpu_openrisc_count_update(cpu);
+qemu_mutex_unlock_iothread();
+}
 return cpu_openrisc_count_get(cpu);
 #endif
 
-- 
2.36.1




[PATCH v2 09/11] target/openrisc: Interrupt handling fixes

2022-07-03 Thread Stafford Horne
When running SMP systems we sometimes were seeing lockups where
IPI interrupts were being raised by never handled.

This looks to be caused by 2 issues in the openrisc interrupt handling
logic.

 1. After clearing an interrupt the openrisc_cpu_set_irq handler will
always clear PICSR.  This is not correct as masked interrupts
should still be visible in PICSR.
 2. After setting PICMR (mask register) and exposed interrupts should
cause an interrupt to be raised.  This was not being done so add it.

This patch fixes both issues.

Signed-off-by: Stafford Horne 
---
 target/openrisc/cpu.c| 1 -
 target/openrisc/sys_helper.c | 7 +++
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/target/openrisc/cpu.c b/target/openrisc/cpu.c
index 41d1b2a24a..cb9f35f408 100644
--- a/target/openrisc/cpu.c
+++ b/target/openrisc/cpu.c
@@ -98,7 +98,6 @@ static void openrisc_cpu_set_irq(void *opaque, int irq, int 
level)
 cpu_interrupt(cs, CPU_INTERRUPT_HARD);
 } else {
 cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
-cpu->env.picsr = 0;
 }
 }
 #endif
diff --git a/target/openrisc/sys_helper.c b/target/openrisc/sys_helper.c
index 7c0d3d6187..5336110b5e 100644
--- a/target/openrisc/sys_helper.c
+++ b/target/openrisc/sys_helper.c
@@ -139,6 +139,13 @@ void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong 
spr, target_ulong rb)
 break;
 case TO_SPR(9, 0):  /* PICMR */
 env->picmr = rb;
+qemu_mutex_lock_iothread();
+if (env->picsr & env->picmr) {
+cpu_interrupt(cs, CPU_INTERRUPT_HARD);
+} else {
+cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
+}
+qemu_mutex_unlock_iothread();
 break;
 case TO_SPR(9, 2):  /* PICSR */
 env->picsr &= ~rb;
-- 
2.36.1




[PATCH v2 04/11] hw/openrisc: Add the OpenRISC virtual machine

2022-07-03 Thread Stafford Horne
This patch adds the OpenRISC virtual machine 'virt' for OpenRISC.  This
platform allows for a convenient CI platform for toolchain, software
ports and the OpenRISC linux kernel port.

Much of this has been sourced from the m68k and riscv virt platforms.

The platform provides:
 - OpenRISC SMP with up to 4 cpus
 - A virtio bus with up to 8 devices
 - Standard ns16550a serial
 - Goldfish RTC
 - SiFive TEST device for poweroff and reboot
 - Generated Device Tree to automatically configure the guest kernel

Signed-off-by: Stafford Horne 
---
 configs/devices/or1k-softmmu/default.mak |   1 +
 hw/openrisc/Kconfig  |   9 +
 hw/openrisc/meson.build  |   1 +
 hw/openrisc/virt.c   | 424 +++
 4 files changed, 435 insertions(+)
 create mode 100644 hw/openrisc/virt.c

diff --git a/configs/devices/or1k-softmmu/default.mak 
b/configs/devices/or1k-softmmu/default.mak
index 168101c39a..89c39e3123 100644
--- a/configs/devices/or1k-softmmu/default.mak
+++ b/configs/devices/or1k-softmmu/default.mak
@@ -3,3 +3,4 @@
 # Boards:
 #
 CONFIG_OR1K_SIM=y
+CONFIG_OR1K_VIRT=y
diff --git a/hw/openrisc/Kconfig b/hw/openrisc/Kconfig
index 8f284f3ba0..202134668e 100644
--- a/hw/openrisc/Kconfig
+++ b/hw/openrisc/Kconfig
@@ -4,3 +4,12 @@ config OR1K_SIM
 select OPENCORES_ETH
 select OMPIC
 select SPLIT_IRQ
+
+config OR1K_VIRT
+bool
+imply VIRTIO_VGA
+imply TEST_DEVICES
+select GOLDFISH_RTC
+select SERIAL
+select SIFIVE_TEST
+select VIRTIO_MMIO
diff --git a/hw/openrisc/meson.build b/hw/openrisc/meson.build
index ab563820c5..2dbc6365bb 100644
--- a/hw/openrisc/meson.build
+++ b/hw/openrisc/meson.build
@@ -2,5 +2,6 @@ openrisc_ss = ss.source_set()
 openrisc_ss.add(files('cputimer.c'))
 openrisc_ss.add(files('boot.c'))
 openrisc_ss.add(when: 'CONFIG_OR1K_SIM', if_true: [files('openrisc_sim.c'), 
fdt])
+openrisc_ss.add(when: 'CONFIG_OR1K_VIRT', if_true: [files('virt.c'), fdt])
 
 hw_arch += {'openrisc': openrisc_ss}
diff --git a/hw/openrisc/virt.c b/hw/openrisc/virt.c
new file mode 100644
index 00..bdb00f6e32
--- /dev/null
+++ b/hw/openrisc/virt.c
@@ -0,0 +1,424 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * OpenRISC QEMU virtual machine.
+ *
+ * (c) 2022 Stafford Horne 
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/error-report.h"
+#include "qapi/error.h"
+#include "cpu.h"
+#include "exec/address-spaces.h"
+#include "hw/irq.h"
+#include "hw/boards.h"
+#include "hw/char/serial.h"
+#include "hw/core/split-irq.h"
+#include "hw/openrisc/boot.h"
+#include "hw/misc/sifive_test.h"
+#include "hw/qdev-properties.h"
+#include "hw/rtc/goldfish_rtc.h"
+#include "hw/sysbus.h"
+#include "hw/virtio/virtio-mmio.h"
+#include "sysemu/device_tree.h"
+#include "sysemu/sysemu.h"
+#include "sysemu/qtest.h"
+#include "sysemu/reset.h"
+
+#include 
+
+#define VIRT_CPUS_MAX 4
+#define VIRT_CLK_MHZ 2000
+
+#define TYPE_VIRT_MACHINE MACHINE_TYPE_NAME("virt")
+#define VIRT_MACHINE(obj) \
+OBJECT_CHECK(OR1KVirtState, (obj), TYPE_VIRT_MACHINE)
+
+typedef struct OR1KVirtState {
+/*< private >*/
+MachineState parent_obj;
+
+/*< public >*/
+void *fdt;
+int fdt_size;
+
+} OR1KVirtState;
+
+enum {
+VIRT_DRAM,
+VIRT_TEST,
+VIRT_RTC,
+VIRT_VIRTIO,
+VIRT_UART,
+VIRT_OMPIC,
+};
+
+enum {
+VIRT_OMPIC_IRQ = 1,
+VIRT_UART_IRQ = 2,
+VIRT_RTC_IRQ = 3,
+VIRT_VIRTIO_IRQ = 4, /* to 12 */
+VIRTIO_COUNT = 8,
+};
+
+static const struct MemmapEntry {
+hwaddr base;
+hwaddr size;
+} virt_memmap[] = {
+[VIRT_DRAM] =  { 0x,  0 },
+[VIRT_UART] =  { 0x9000,  0x100 },
+[VIRT_TEST] =  { 0x9600,0x8 },
+[VIRT_RTC] =   { 0x96005000, 0x1000 },
+[VIRT_VIRTIO] ={ 0x9700, 0x1000 },
+[VIRT_OMPIC] = { 0x9800, VIRT_CPUS_MAX * 8 },
+};
+
+static struct openrisc_boot_info {
+uint32_t bootstrap_pc;
+uint32_t fdt_addr;
+} boot_info;
+
+static void main_cpu_reset(void *opaque)
+{
+OpenRISCCPU *cpu = opaque;
+CPUState *cs = CPU(cpu);
+
+cpu_reset(CPU(cpu));
+
+cpu_set_pc(cs, boot_info.bootstrap_pc);
+cpu_set_gpr(>env, 3, boot_info.fdt_addr);
+}
+
+static qemu_irq get_cpu_irq(OpenRISCCPU *cpus[], int cpunum, int irq_pin)
+{
+return qdev_get_gpio_in_named(DEVICE(cpus[cpunum]), "IRQ", irq_pin);
+}
+
+static qemu_irq get_per_cpu_irq(OpenRISCCPU *cpus[], int num_cpus, int irq_pin)
+{
+int i;
+
+if (num_cpus > 1) {
+DeviceState *splitter = qdev_new(TYPE_SPLIT_IRQ);
+qdev_prop_set_uint32(splitter, "num-lines", num_cpus);
+qdev_realize_and_unref(splitter, NULL, _fatal);
+for (i = 0; i <

[PATCH v2 06/11] hw/openrisc: Initialize timer time at startup

2022-07-03 Thread Stafford Horne
The last_clk time was initialized at zero, this means when we calculate
the first delta we will calculate 0 vs current time which could cause
unnecessary hops.

Initialize last_clk to the qemu clock on initialization.

Signed-off-by: Stafford Horne 
---
 hw/openrisc/cputimer.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/hw/openrisc/cputimer.c b/hw/openrisc/cputimer.c
index 93268815d8..4dbba3a3d4 100644
--- a/hw/openrisc/cputimer.c
+++ b/hw/openrisc/cputimer.c
@@ -140,6 +140,7 @@ void cpu_openrisc_clock_init(OpenRISCCPU *cpu)
 
 if (or1k_timer == NULL) {
 or1k_timer = g_new0(OR1KTimerState, 1);
+or1k_timer->last_clk = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
 vmstate_register(NULL, 0, _or1k_timer, or1k_timer);
 }
 }
-- 
2.36.1




[PATCH v2 07/11] target/openrisc: Add interrupted CPU to log

2022-07-03 Thread Stafford Horne
When we are tracing it's helpful to know which CPU's are getting
interrupted, att that detail to the log line.

Signed-off-by: Stafford Horne 
---
 target/openrisc/interrupt.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/target/openrisc/interrupt.c b/target/openrisc/interrupt.c
index e5724f5371..c31c6f12c4 100644
--- a/target/openrisc/interrupt.c
+++ b/target/openrisc/interrupt.c
@@ -83,7 +83,9 @@ void openrisc_cpu_do_interrupt(CPUState *cs)
 [EXCP_TRAP] = "TRAP",
 };
 
-qemu_log_mask(CPU_LOG_INT, "INT: %s\n", int_name[exception]);
+qemu_log_mask(CPU_LOG_INT, "CPU: %d INT: %s\n",
+  cs->cpu_index,
+  int_name[exception]);
 
 hwaddr vect_pc = exception << 8;
 if (env->cpucfgr & CPUCFGR_EVBARP) {
-- 
2.36.1




[PATCH v2 05/11] hw/openrisc: Add PCI bus support to virt

2022-07-03 Thread Stafford Horne
This is mostly borrowed from xtensa and riscv as examples.  The
create_pcie_irq_map swizzle function is almost and exact copy
but here we use a single cell interrupt, possibly we can make
this generic.

Signed-off-by: Stafford Horne 
---
 hw/openrisc/Kconfig |   3 +
 hw/openrisc/virt.c  | 160 ++--
 2 files changed, 157 insertions(+), 6 deletions(-)

diff --git a/hw/openrisc/Kconfig b/hw/openrisc/Kconfig
index 202134668e..97af258b55 100644
--- a/hw/openrisc/Kconfig
+++ b/hw/openrisc/Kconfig
@@ -7,8 +7,11 @@ config OR1K_SIM
 
 config OR1K_VIRT
 bool
+imply PCI_DEVICES
 imply VIRTIO_VGA
 imply TEST_DEVICES
+select PCI
+select PCI_EXPRESS_GENERIC_BRIDGE
 select GOLDFISH_RTC
 select SERIAL
 select SIFIVE_TEST
diff --git a/hw/openrisc/virt.c b/hw/openrisc/virt.c
index bdb00f6e32..f1d1293eeb 100644
--- a/hw/openrisc/virt.c
+++ b/hw/openrisc/virt.c
@@ -17,6 +17,8 @@
 #include "hw/core/split-irq.h"
 #include "hw/openrisc/boot.h"
 #include "hw/misc/sifive_test.h"
+#include "hw/pci/pci.h"
+#include "hw/pci-host/gpex.h"
 #include "hw/qdev-properties.h"
 #include "hw/rtc/goldfish_rtc.h"
 #include "hw/sysbus.h"
@@ -47,6 +49,9 @@ typedef struct OR1KVirtState {
 
 enum {
 VIRT_DRAM,
+VIRT_ECAM,
+VIRT_MMIO,
+VIRT_PIO,
 VIRT_TEST,
 VIRT_RTC,
 VIRT_VIRTIO,
@@ -60,6 +65,7 @@ enum {
 VIRT_RTC_IRQ = 3,
 VIRT_VIRTIO_IRQ = 4, /* to 12 */
 VIRTIO_COUNT = 8,
+VIRT_PCI_IRQ_BASE = 13, /* to 17 */
 };
 
 static const struct MemmapEntry {
@@ -72,6 +78,9 @@ static const struct MemmapEntry {
 [VIRT_RTC] =   { 0x96005000, 0x1000 },
 [VIRT_VIRTIO] ={ 0x9700, 0x1000 },
 [VIRT_OMPIC] = { 0x9800, VIRT_CPUS_MAX * 8 },
+[VIRT_ECAM] =  { 0x9e00,  0x100 },
+[VIRT_PIO] =   { 0x9f00,  0x100 },
+[VIRT_MMIO] =  { 0xa000, 0x1000 },
 };
 
 static struct openrisc_boot_info {
@@ -115,12 +124,12 @@ static qemu_irq get_per_cpu_irq(OpenRISCCPU *cpus[], int 
num_cpus, int irq_pin)
 static void openrisc_create_fdt(OR1KVirtState *state,
 const struct MemmapEntry *memmap,
 int num_cpus, uint64_t mem_size,
-const char *cmdline)
+const char *cmdline,
+int32_t *pic_phandle)
 {
 void *fdt;
 int cpu;
 char *nodename;
-int pic_ph;
 
 fdt = state->fdt = create_device_tree(>fdt_size);
 if (!fdt) {
@@ -163,14 +172,14 @@ static void openrisc_create_fdt(OR1KVirtState *state,
 
 nodename = (char *)"/pic";
 qemu_fdt_add_subnode(fdt, nodename);
-pic_ph = qemu_fdt_alloc_phandle(fdt);
+*pic_phandle = qemu_fdt_alloc_phandle(fdt);
 qemu_fdt_setprop_string(fdt, nodename, "compatible",
 "opencores,or1k-pic-level");
 qemu_fdt_setprop_cell(fdt, nodename, "#interrupt-cells", 1);
 qemu_fdt_setprop(fdt, nodename, "interrupt-controller", NULL, 0);
-qemu_fdt_setprop_cell(fdt, nodename, "phandle", pic_ph);
+qemu_fdt_setprop_cell(fdt, nodename, "phandle", *pic_phandle);
 
-qemu_fdt_setprop_cell(fdt, "/", "interrupt-parent", pic_ph);
+qemu_fdt_setprop_cell(fdt, "/", "interrupt-parent", *pic_phandle);
 
 qemu_fdt_add_subnode(fdt, "/chosen");
 if (cmdline) {
@@ -275,6 +284,7 @@ static void openrisc_virt_test_init(OR1KVirtState *state, 
hwaddr base,
 g_free(nodename);
 
 }
+
 static void openrisc_virt_rtc_init(OR1KVirtState *state, hwaddr base,
hwaddr size, int num_cpus,
OpenRISCCPU *cpus[], int irq_pin)
@@ -303,6 +313,134 @@ static void openrisc_virt_rtc_init(OR1KVirtState *state, 
hwaddr base,
 g_free(nodename);
 
 }
+
+static void create_pcie_irq_map(void *fdt, char *nodename, int irq_base,
+uint32_t irqchip_phandle)
+{
+int pin, dev;
+uint32_t irq_map_stride = 0;
+uint32_t full_irq_map[GPEX_NUM_IRQS * GPEX_NUM_IRQS * 6] = {};
+uint32_t *irq_map = full_irq_map;
+
+/*
+ * This code creates a standard swizzle of interrupts such that
+ * each device's first interrupt is based on it's PCI_SLOT number.
+ * (See pci_swizzle_map_irq_fn())
+ *
+ * We only need one entry per interrupt in the table (not one per
+ * possible slot) seeing the interrupt-map-mask will allow the table
+ * to wrap to any number of devices.
+ */
+for (dev = 0; dev < GPEX_NUM_IRQS; dev++) {
+int devfn = dev << 3;
+
+for (pin = 0; pin < GPEX_NUM_IRQS; pin++) {
+int irq_nr = irq_base + ((pin + PCI_SLOT(devfn)) % GPEX_NUM_IRQS);
+  

[PATCH v2 03/11] goldfish_rtc: Add endianness property

2022-07-03 Thread Stafford Horne
Add an endianness property to allow configuring the RTC as either
native, little or big endian.

Cc: Laurent Vivier 
Signed-off-by: Stafford Horne 
---
 hw/rtc/goldfish_rtc.c | 46 ---
 include/hw/rtc/goldfish_rtc.h |  2 ++
 2 files changed, 39 insertions(+), 9 deletions(-)

diff --git a/hw/rtc/goldfish_rtc.c b/hw/rtc/goldfish_rtc.c
index 35e493be31..24f6587086 100644
--- a/hw/rtc/goldfish_rtc.c
+++ b/hw/rtc/goldfish_rtc.c
@@ -216,14 +216,34 @@ static int goldfish_rtc_post_load(void *opaque, int 
version_id)
 return 0;
 }
 
-static const MemoryRegionOps goldfish_rtc_ops = {
-.read = goldfish_rtc_read,
-.write = goldfish_rtc_write,
-.endianness = DEVICE_NATIVE_ENDIAN,
-.valid = {
-.min_access_size = 4,
-.max_access_size = 4
-}
+static const MemoryRegionOps goldfish_rtc_ops[3] = {
+[DEVICE_NATIVE_ENDIAN] = {
+.read = goldfish_rtc_read,
+.write = goldfish_rtc_write,
+.endianness = DEVICE_NATIVE_ENDIAN,
+.valid = {
+.min_access_size = 4,
+.max_access_size = 4
+}
+},
+[DEVICE_LITTLE_ENDIAN] = {
+.read = goldfish_rtc_read,
+.write = goldfish_rtc_write,
+.endianness = DEVICE_LITTLE_ENDIAN,
+.valid = {
+.min_access_size = 4,
+.max_access_size = 4
+}
+},
+[DEVICE_BIG_ENDIAN] = {
+.read = goldfish_rtc_read,
+.write = goldfish_rtc_write,
+.endianness = DEVICE_BIG_ENDIAN,
+.valid = {
+.min_access_size = 4,
+.max_access_size = 4
+}
+},
 };
 
 static const VMStateDescription goldfish_rtc_vmstate = {
@@ -265,7 +285,8 @@ static void goldfish_rtc_realize(DeviceState *d, Error 
**errp)
 SysBusDevice *dev = SYS_BUS_DEVICE(d);
 GoldfishRTCState *s = GOLDFISH_RTC(d);
 
-memory_region_init_io(>iomem, OBJECT(s), _rtc_ops, s,
+memory_region_init_io(>iomem, OBJECT(s),
+  _rtc_ops[s->endianness], s,
   "goldfish_rtc", 0x24);
 sysbus_init_mmio(dev, >iomem);
 
@@ -274,10 +295,17 @@ static void goldfish_rtc_realize(DeviceState *d, Error 
**errp)
 s->timer = timer_new_ns(rtc_clock, goldfish_rtc_interrupt, s);
 }
 
+static Property goldfish_rtc_properties[] = {
+DEFINE_PROP_UINT8("endianness", GoldfishRTCState, endianness,
+  DEVICE_NATIVE_ENDIAN),
+DEFINE_PROP_END_OF_LIST(),
+};
+
 static void goldfish_rtc_class_init(ObjectClass *klass, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(klass);
 
+device_class_set_props(dc, goldfish_rtc_properties);
 dc->realize = goldfish_rtc_realize;
 dc->reset = goldfish_rtc_reset;
 dc->vmsd = _rtc_vmstate;
diff --git a/include/hw/rtc/goldfish_rtc.h b/include/hw/rtc/goldfish_rtc.h
index 79ca7daf5d..8e1aeb85e3 100644
--- a/include/hw/rtc/goldfish_rtc.h
+++ b/include/hw/rtc/goldfish_rtc.h
@@ -42,6 +42,8 @@ struct GoldfishRTCState {
 uint32_t irq_pending;
 uint32_t irq_enabled;
 uint32_t time_high;
+
+uint8_t endianness;
 };
 
 #endif
-- 
2.36.1




[PATCH v2 00/11] OpenRISC Virtual Machine

2022-07-03 Thread Stafford Horne
Hello,

This is the OpenRISC Virtual Machine plaform which we are now using for OpenRISC
CI such as the wireguard testing that Jason has been working on.

The first few patches help get OpenRISC QEMU ready for the virtual machine.
There is one bug fix for GDB debugging there too.

Next we have the Virt patch followed by a separate patch to add PCI support
which is split out because it's a bit easier to review that way I thought.  The
next few patches are fixes to get the Multicore platform stable, such as adding
MTTCG support and fixing some interrupt and timer related bugs.

The platform is relatively stable now, but every few boots we get ~10 second 
soft
lockups.  My hunch is that this is another interrupt race condition where IPI's
end up getting lost.  However, overall the is much more stable than the SMP
support we had before.  So I want to submit this for review and maybe upstream
it before tracking down these last issues which might take significant more
time.

This is being tested with my or1k-virt kernel branch here:

  https://github.com/stffrdhrn/linux/commits/or1k-virt

  This tree has support for: OpenRISC PCI and virt_defconfig and an irqchip bug
  fix.

Changes since v1:
 - Dropped semihosting support
 - Added PCI support
 - Added OpenRISC documentation
 - Added OpenRISC support for MTTCG
 - Support Configurating Goldfish RTC endianness
 - Added a few bug fix patches

-Stafford

Jason A. Donenfeld (1):
  hw/openrisc: virt: pass random seed to fdt

Stafford Horne (10):
  hw/openrisc: Split re-usable boot time apis out to boot.c
  target/openrisc: Fix memory reading in debugger
  goldfish_rtc: Add endianness property
  hw/openrisc: Add the OpenRISC virtual machine
  hw/openrisc: Add PCI bus support to virt
  hw/openrisc: Initialize timer time at startup
  target/openrisc: Add interrupted CPU to log
  target/openrisc: Enable MTTCG
  target/openrisc: Interrupt handling fixes
  docs/system: openrisc: Add OpenRISC documentation

 configs/devices/or1k-softmmu/default.mak |   1 +
 configs/targets/or1k-softmmu.mak |   1 +
 docs/system/openrisc/cpu-features.rst|  15 +
 docs/system/openrisc/emulation.rst   |  17 +
 docs/system/openrisc/or1k-sim.rst|  43 ++
 docs/system/openrisc/virt.rst|  50 ++
 docs/system/target-openrisc.rst  |  72 +++
 docs/system/targets.rst  |   1 +
 hw/openrisc/Kconfig  |  12 +
 hw/openrisc/boot.c   | 117 +
 hw/openrisc/cputimer.c   |  18 +
 hw/openrisc/meson.build  |   2 +
 hw/openrisc/openrisc_sim.c   | 106 +
 hw/openrisc/virt.c   | 578 +++
 hw/rtc/goldfish_rtc.c|  46 +-
 include/hw/openrisc/boot.h   |  34 ++
 include/hw/rtc/goldfish_rtc.h|   2 +
 target/openrisc/cpu.c|   1 -
 target/openrisc/cpu.h|   3 +
 target/openrisc/interrupt.c  |   4 +-
 target/openrisc/mmu.c|   8 +-
 target/openrisc/sys_helper.c |  18 +-
 22 files changed, 1035 insertions(+), 114 deletions(-)
 create mode 100644 docs/system/openrisc/cpu-features.rst
 create mode 100644 docs/system/openrisc/emulation.rst
 create mode 100644 docs/system/openrisc/or1k-sim.rst
 create mode 100644 docs/system/openrisc/virt.rst
 create mode 100644 docs/system/target-openrisc.rst
 create mode 100644 hw/openrisc/boot.c
 create mode 100644 hw/openrisc/virt.c
 create mode 100644 include/hw/openrisc/boot.h

-- 
2.36.1




[PATCH v2 02/11] target/openrisc: Fix memory reading in debugger

2022-07-03 Thread Stafford Horne
In commit f0655423ca ("target/openrisc: Reorg tlb lookup") data and
instruction TLB reads were combined.  This, broke debugger reads where
we first tried to map using the data tlb then fall back to the
instruction tlb.

This patch replicates this logic by first requesting a PAGE_READ
protection mapping then falling back to PAGE_EXEC.

Signed-off-by: Stafford Horne 
---
 target/openrisc/mmu.c | 8 +++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/target/openrisc/mmu.c b/target/openrisc/mmu.c
index d7e1320998..0b8afdbacf 100644
--- a/target/openrisc/mmu.c
+++ b/target/openrisc/mmu.c
@@ -148,7 +148,13 @@ hwaddr openrisc_cpu_get_phys_page_debug(CPUState *cs, 
vaddr addr)
 case SR_DME | SR_IME:
 /* The mmu is definitely enabled.  */
 excp = get_phys_mmu(cpu, _addr, , addr,
-PAGE_EXEC | PAGE_READ | PAGE_WRITE,
+PAGE_READ,
+(sr & SR_SM) != 0);
+if (!excp) {
+return phys_addr;
+}
+excp = get_phys_mmu(cpu, _addr, , addr,
+PAGE_EXEC,
 (sr & SR_SM) != 0);
 return excp ? -1 : phys_addr;
 
-- 
2.36.1




[PATCH v2 01/11] hw/openrisc: Split re-usable boot time apis out to boot.c

2022-07-03 Thread Stafford Horne
These will be shared with the virt platform.

Reviewed-by: Richard Henderson 
Signed-off-by: Stafford Horne 
---
 hw/openrisc/boot.c | 117 +
 hw/openrisc/meson.build|   1 +
 hw/openrisc/openrisc_sim.c | 106 ++---
 include/hw/openrisc/boot.h |  34 +++
 4 files changed, 158 insertions(+), 100 deletions(-)
 create mode 100644 hw/openrisc/boot.c
 create mode 100644 include/hw/openrisc/boot.h

diff --git a/hw/openrisc/boot.c b/hw/openrisc/boot.c
new file mode 100644
index 00..ca773b385e
--- /dev/null
+++ b/hw/openrisc/boot.c
@@ -0,0 +1,117 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * QEMU OpenRISC boot helpers.
+ *
+ * (c) 2022 Stafford Horne 
+ */
+
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "exec/cpu-defs.h"
+#include "elf.h"
+#include "hw/loader.h"
+#include "hw/openrisc/boot.h"
+#include "sysemu/device_tree.h"
+#include "sysemu/qtest.h"
+
+#include 
+
+#define KERNEL_LOAD_ADDR 0x100
+
+hwaddr openrisc_load_kernel(ram_addr_t ram_size,
+const char *kernel_filename,
+uint32_t *bootstrap_pc)
+{
+long kernel_size;
+uint64_t elf_entry;
+uint64_t high_addr;
+hwaddr entry;
+
+if (kernel_filename && !qtest_enabled()) {
+kernel_size = load_elf(kernel_filename, NULL, NULL, NULL,
+   _entry, NULL, _addr, NULL, 1,
+   EM_OPENRISC, 1, 0);
+entry = elf_entry;
+if (kernel_size < 0) {
+kernel_size = load_uimage(kernel_filename,
+  , NULL, NULL, NULL, NULL);
+high_addr = entry + kernel_size;
+}
+if (kernel_size < 0) {
+kernel_size = load_image_targphys(kernel_filename,
+  KERNEL_LOAD_ADDR,
+  ram_size - KERNEL_LOAD_ADDR);
+high_addr = KERNEL_LOAD_ADDR + kernel_size;
+}
+
+if (entry <= 0) {
+entry = KERNEL_LOAD_ADDR;
+}
+
+if (kernel_size < 0) {
+error_report("couldn't load the kernel '%s'", kernel_filename);
+exit(1);
+}
+*bootstrap_pc = entry;
+
+return high_addr;
+}
+return 0;
+}
+
+hwaddr openrisc_load_initrd(void *fdt, const char *filename,
+hwaddr load_start, uint64_t mem_size)
+{
+int size;
+hwaddr start;
+
+/* We put the initrd right after the kernel; page aligned. */
+start = TARGET_PAGE_ALIGN(load_start);
+
+size = load_ramdisk(filename, start, mem_size - start);
+if (size < 0) {
+size = load_image_targphys(filename, start, mem_size - start);
+if (size < 0) {
+error_report("could not load ramdisk '%s'", filename);
+exit(1);
+}
+}
+
+if (fdt) {
+qemu_fdt_setprop_cell(fdt, "/chosen",
+  "linux,initrd-start", start);
+qemu_fdt_setprop_cell(fdt, "/chosen",
+  "linux,initrd-end", start + size);
+}
+
+return start + size;
+}
+
+uint32_t openrisc_load_fdt(void *fdt, hwaddr load_start,
+   uint64_t mem_size)
+{
+uint32_t fdt_addr;
+int ret;
+int fdtsize = fdt_totalsize(fdt);
+
+if (fdtsize <= 0) {
+error_report("invalid device-tree");
+exit(1);
+}
+
+/* We put fdt right after the kernel and/or initrd. */
+fdt_addr = TARGET_PAGE_ALIGN(load_start);
+
+ret = fdt_pack(fdt);
+/* Should only fail if we've built a corrupted tree */
+g_assert(ret == 0);
+/* copy in the device tree */
+qemu_fdt_dumpdtb(fdt, fdtsize);
+
+rom_add_blob_fixed_as("fdt", fdt, fdtsize, fdt_addr,
+  _space_memory);
+
+return fdt_addr;
+}
+
diff --git a/hw/openrisc/meson.build b/hw/openrisc/meson.build
index ec48172c9d..ab563820c5 100644
--- a/hw/openrisc/meson.build
+++ b/hw/openrisc/meson.build
@@ -1,5 +1,6 @@
 openrisc_ss = ss.source_set()
 openrisc_ss.add(files('cputimer.c'))
+openrisc_ss.add(files('boot.c'))
 openrisc_ss.add(when: 'CONFIG_OR1K_SIM', if_true: [files('openrisc_sim.c'), 
fdt])
 
 hw_arch += {'openrisc': openrisc_ss}
diff --git a/hw/openrisc/openrisc_sim.c b/hw/openrisc/openrisc_sim.c
index 35adce17ac..35da123aef 100644
--- a/hw/openrisc/openrisc_sim.c
+++ b/hw/openrisc/openrisc_sim.c
@@ -24,10 +24,9 @@
 #include "cpu.h"
 #include "hw/irq.h"
 #include "hw/boards.h"
-#include "elf.h"
 #include "hw/char/serial.h"
 #include "net/net.h"
-#include "hw/loader.h"
+#include "hw/openrisc/boot.h"
 #includ

Re: [PATCH v2] hw/openrisc: virt: pass random seed to fdt

2022-06-23 Thread Stafford Horne
On Wed, Jun 22, 2022 at 01:45:13PM +0200, Jason A. Donenfeld wrote:
> If the FDT contains /chosen/rng-seed, then the Linux RNG will use it to
> initialize early. Set this using the usual guest random number
> generation function. This is confirmed to successfully initialize the
> RNG on Linux 5.19-rc2.
> 
> Cc: Stafford Horne 
> Signed-off-by: Jason A. Donenfeld 
> ---
> Changes v1->v2:
> - This is rebased on top of your "or1k-virt-2" branch.
> - It makes the change to the new "virt" platform, since that's where it
>   makes most sense to have.

Thanks I have placed this on my or1k-virt-2 branch.

-Stafford



Re: [PATCH] hw/openrisc: pass random seed to fdt

2022-06-12 Thread Stafford Horne
On Sun, Jun 12, 2022 at 11:59:49PM +0200, Jason A. Donenfeld wrote:
> If the FDT contains /chosen/rng-seed, then the Linux RNG will use it to
> initialize early. Set this using the usual guest random number
> generation function. This is confirmed to successfully initialize the
> RNG on Linux 5.19-rc2.
>
> Cc: Stafford Horne 
> Signed-off-by: Jason A. Donenfeld 
> ---
>  hw/openrisc/openrisc_sim.c | 6 ++
>  1 file changed, 6 insertions(+)
> 
> diff --git a/hw/openrisc/openrisc_sim.c b/hw/openrisc/openrisc_sim.c
> index 35adce17ac..41821b5f30 100644
> --- a/hw/openrisc/openrisc_sim.c
> +++ b/hw/openrisc/openrisc_sim.c
> @@ -20,6 +20,7 @@
>  
>  #include "qemu/osdep.h"
>  #include "qemu/error-report.h"
> +#include "qemu/guest-random.h"
>  #include "qapi/error.h"
>  #include "cpu.h"
>  #include "hw/irq.h"
> @@ -115,6 +116,7 @@ static void openrisc_create_fdt(Or1ksimState *state,
>  int cpu;
>  char *nodename;
>  int pic_ph;
> +uint8_t rng_seed[32];
>  
>  fdt = state->fdt = create_device_tree(>fdt_size);
>  if (!fdt) {
> @@ -165,6 +167,10 @@ static void openrisc_create_fdt(Or1ksimState *state,
>  qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", cmdline);
>  }
>  
> +/* Pass seed to RNG. */
> +qemu_guest_getrandom_nofail(rng_seed, sizeof(rng_seed));
> +qemu_fdt_setprop(fdt, "/chosen", "rng-seed", rng_seed, sizeof(rng_seed));
> +
>  /* Create aliases node for use by devices. */
>  qemu_fdt_add_subnode(fdt, "/aliases");
>  }

This all looks fine to me.  I will queue it with my current changes.  Since this
is only applying to openrisc_sim I would like to also apply it to virt.  To do
that I need to have a common core openrisc system creation api.  That way I
don't end up copying and pasting this to every platform.

-Stafford



[PATCH] goldfish_rtc: Add endianness property

2022-06-12 Thread Stafford Horne
Add an endianness property to allow configuring the RTC as either
native, little or big endian.

Cc: Laurent Vivier 
Cc: Arnd Bergmann 
Signed-off-by: Stafford Horne 
---
In a recent mail thread[0] it was discussed that future users of goldfish 
devices
should use little-endian rather than native endian.  This is to avoid having to
define special ioread/write routines in the Linux kernel as the default of the
Linux kernel is to use little-endian.

I have defined a property to allow us to make this change the endianness of the
device at initialization time.  For OpenRISC we can now set the qemu device
endianness property to little-endian and the device works.

For now I kept the default as DEVICE_NATIVE_ENDIAN for illustration purposes I
could also do:

 - Add the "endianness" property to all goldfish devices.
 - Switch the default to LITTLE_ENDIAN and just set BIG_ENDIAN for m68k only.
 - Just the bare minimum, using this patch and also set little-endian in
   OpenRISC.
 - Just drop this patch and use BIG_ENDIAN access for goldfish in the kernel for
   OpenRISC like m68k does.

I have tested this with the OpenRISC virt platform[1] available here (now with 
pci
support).

[0] 
https://lore.kernel.org/all/cak8p3a13ptsmexyxzm5szm3wbk-8honfjyoi19phmkkcjqm...@mail.gmail.com/
[1] https://github.com/stffrdhrn/qemu/commits/or1k-virt-2

 hw/rtc/goldfish_rtc.c | 45 ---
 include/hw/rtc/goldfish_rtc.h |  2 ++
 2 files changed, 38 insertions(+), 9 deletions(-)

diff --git a/hw/rtc/goldfish_rtc.c b/hw/rtc/goldfish_rtc.c
index 35e493be31..ab1e15a3e2 100644
--- a/hw/rtc/goldfish_rtc.c
+++ b/hw/rtc/goldfish_rtc.c
@@ -216,14 +216,34 @@ static int goldfish_rtc_post_load(void *opaque, int 
version_id)
 return 0;
 }
 
-static const MemoryRegionOps goldfish_rtc_ops = {
-.read = goldfish_rtc_read,
-.write = goldfish_rtc_write,
-.endianness = DEVICE_NATIVE_ENDIAN,
-.valid = {
-.min_access_size = 4,
-.max_access_size = 4
-}
+static const MemoryRegionOps goldfish_rtc_ops[3] = {
+[DEVICE_NATIVE_ENDIAN] = {
+.read = goldfish_rtc_read,
+.write = goldfish_rtc_write,
+.endianness = DEVICE_NATIVE_ENDIAN,
+.valid = {
+.min_access_size = 4,
+.max_access_size = 4
+}
+},
+[DEVICE_LITTLE_ENDIAN] = {
+.read = goldfish_rtc_read,
+.write = goldfish_rtc_write,
+.endianness = DEVICE_LITTLE_ENDIAN,
+.valid = {
+.min_access_size = 4,
+.max_access_size = 4
+}
+},
+[DEVICE_BIG_ENDIAN] = {
+.read = goldfish_rtc_read,
+.write = goldfish_rtc_write,
+.endianness = DEVICE_BIG_ENDIAN,
+.valid = {
+.min_access_size = 4,
+.max_access_size = 4
+}
+},
 };
 
 static const VMStateDescription goldfish_rtc_vmstate = {
@@ -265,7 +285,8 @@ static void goldfish_rtc_realize(DeviceState *d, Error 
**errp)
 SysBusDevice *dev = SYS_BUS_DEVICE(d);
 GoldfishRTCState *s = GOLDFISH_RTC(d);
 
-memory_region_init_io(>iomem, OBJECT(s), _rtc_ops, s,
+memory_region_init_io(>iomem, OBJECT(s),
+  _rtc_ops[s->endianness], s,
   "goldfish_rtc", 0x24);
 sysbus_init_mmio(dev, >iomem);
 
@@ -274,10 +295,16 @@ static void goldfish_rtc_realize(DeviceState *d, Error 
**errp)
 s->timer = timer_new_ns(rtc_clock, goldfish_rtc_interrupt, s);
 }
 
+static Property goldfish_rtc_properties[] = {
+DEFINE_PROP_UINT8("endianness", GoldfishRTCState, endianness, 
DEVICE_NATIVE_ENDIAN),
+DEFINE_PROP_END_OF_LIST(),
+};
+
 static void goldfish_rtc_class_init(ObjectClass *klass, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(klass);
 
+device_class_set_props(dc, goldfish_rtc_properties);
 dc->realize = goldfish_rtc_realize;
 dc->reset = goldfish_rtc_reset;
 dc->vmsd = _rtc_vmstate;
diff --git a/include/hw/rtc/goldfish_rtc.h b/include/hw/rtc/goldfish_rtc.h
index 79ca7daf5d..8e1aeb85e3 100644
--- a/include/hw/rtc/goldfish_rtc.h
+++ b/include/hw/rtc/goldfish_rtc.h
@@ -42,6 +42,8 @@ struct GoldfishRTCState {
 uint32_t irq_pending;
 uint32_t irq_enabled;
 uint32_t time_high;
+
+uint8_t endianness;
 };
 
 #endif
-- 
2.36.1




Re: [RFC PATCH 3/3] hw/openrisc: Add the OpenRISC virtual machine

2022-06-07 Thread Stafford Horne
On Tue, Jun 07, 2022 at 11:43:08AM +0100, Peter Maydell wrote:
> So I don't have a strong view on whether these devices should
> be DEVICE_NATIVE_ENDIAN or DEVICE_LITTLE_ENDIAN (except that
> my impression is that a DEVICE_LITTLE_ENDIAN device on a
> big-endian system is a bit weird, because it means the guest
> has to byteswap everything. You see that with PCI devices because
> the PCI spec mandates LE, but not often elsewhere).
> 
> If there's an official-ish spec for how goldfish devices are
> supposed to behave (does anybody have a pointer to one?) and it says
> "always little-endian" then that would probably suggest that fixing
> m68k would be nice if we can.

I think there are some conflicting thoughts on this.

In Geert's he mentioned:

  Using Goldfish devices as little-endian devices should be fine.

In Arnd's mail he mentions:

  
https://lore.kernel.org/lkml/CAK8P3a1oN8NrUjkh2X8jHQbyz42Xo6GSa=5n0gd6vqcxrjm...@mail.gmail.com/#t

  ... the device was clearly defined as having little-endian
  registers,

Based on that I was thinking that switching to DEVICE_LITTLE_ENDIAN would make
sense.

However, in a followup mail from Laurent we see:

  https://lore.kernel.org/lkml/cb884368-0226-e913-80d2-62d2b7b2e...@vivier.eu/

  The reference document[1] doesn't define the endianness of goldfish.

  [1] 
https://android.googlesource.com/platform/external/qemu/+/master/docs/GOLDFISH-VIRTUAL-HARDWARE.TXT


The documentation does not clearly specify it.  So maybe maybe or1k should just
be updated on the linux side and add gf_ioread32/gf_iowrite32 big-endian
accessors.

-Stafford



Re: [RFC PATCH 3/3] hw/openrisc: Add the OpenRISC virtual machine

2022-06-07 Thread Stafford Horne
On Tue, Jun 07, 2022 at 10:42:08AM +0200, Arnd Bergmann wrote:
> On Tue, Jun 7, 2022 at 10:11 AM Geert Uytterhoeven  
> wrote:
> > On Sun, Jun 5, 2022 at 9:32 AM Stafford Horne  wrote:
> > > On Sun, Jun 05, 2022 at 10:58:14AM +0900, Stafford Horne wrote:
> > > It might be a good idea to revisit the qemu implementation and make
> > > sure that the extra byteswap is only inserted on m68k and not on
> > > other targets, but hopefully there are no new targets based on 
> > > goldfish
> > > anymore and we don't need to care.
> > >
> > > So, it seems that in addition to my patch we would need something in m68k 
> > > to
> > > switch it back to 'native' (big) endian?
> > >
> > > Looking at the m68k kernel/qemu interface I see:
> > >
> > > Pre 5.19:
> > >(data) <-- kernel(readl / little) <-- m68k qemu (native / big) - 
> > > RTC/PIC
> > >(data) <-- kernel(__raw_readl / big) <-- m68k qemu (native / big) - TTY
> > >
> > > 5.19:
> > >(data) <-- kernel(gf_ioread32 / big) <-- m68k qemu (native / big) - all
> > >
> > > The new fixes to add gf_ioread32/gf_iowrite32 fix this for goldfish and 
> > > m68k.
> > > This wouldn't have been an issue for little-endian platforms where 
> > > readl/writel
> > > were originally used.
> > >
> > > Why can't m68k switch to little-endian in qemu and the kernel?  The m68k 
> > > virt
> > > platform is not that old, 1 year? Are there a lot of users that this 
> > > would be a big
> > > problem?
> > >
> > > [1] 
> > > https://lore.kernel.org/lkml/CAK8P3a1oN8NrUjkh2X8jHQbyz42Xo6GSa=5n0gd6vqcxrjm...@mail.gmail.com/
> 
> Goldfish is a very old platform, as far as I know only the kernel port is new.
> I don't know when qemu started shipping goldfish, but changing it now would
> surely break compatibility with whatever OS the port was originally made for.

Hi Arnd,

As far as I can tell goldfish in qemu is not very old. There are 3 devices, 2 
were
added for the m68k virt machine, and 1 for riscv virt.

$ git lo -- hw/rtc/goldfish_rtc.c
2022-01-28 2f93d8b04a Peter Maydellrtc: Move RTC function prototypes to 
their own header 
2021-03-04 6b9409ba5f Laurent Vivier   goldfish_rtc: re-arm the alarm after 
migration 
2020-10-13 16b66c5626 Laurent Vivier   goldfish_rtc: change MemoryRegionOps 
endianness to DEVICE_NATIVE_ENDIAN 
2020-07-22 8380b3a453 Jessica Clarke   goldfish_rtc: Fix non-atomic read 
behaviour of TIME_LOW/TIME_HIGH 
2020-02-10 9a5b40b842 Anup Patel   hw: rtc: Add Goldfish RTC device 

$ git lo -- hw/char/goldfish_tty.c
2021-11-09 65b4c8c759 Philippe Mathieu-Daudé hw/m68k: Fix typo in SPDX tag 
2021-03-15 8c6df16ff6 Laurent Vivier   hw/char: add goldfish-tty 

$  git lo -- hw/intc/goldfish_pic.c
2021-11-09 65b4c8c759 Philippe Mathieu-Daudé hw/m68k: Fix typo in SPDX tag 
2021-03-15 8785559390 Laurent Vivier   hw/intc: add goldfish-pic 

The mips/loongson3_virt machine now also uses the goldfish_rtc.

The problem with the goldfish device models is that they were defined as
DEVICE_NATIVE_ENDIAN.

$ grep endianness hw/*/goldfish*
hw/char/goldfish_tty.c:.endianness = DEVICE_NATIVE_ENDIAN,
hw/intc/goldfish_pic.c:.endianness = DEVICE_NATIVE_ENDIAN,
hw/rtc/goldfish_rtc.c:.endianness = DEVICE_NATIVE_ENDIAN,

RISC-V is little-endian so when it was added there was no problem with running
linux goldfish drivers.

MIPS Longson3, added last year, seems to be running as little-endian well, I
understand MIPS can support both big and little endian. However according to
this all Loongson cores are little-endian.

https://en.wikipedia.org/wiki/Loongson

As I understand when endianness of the devices in qemu are defined as
DEVICE_NATIVE_ENDIAN the device endian takes the endian of the target CPU.
This means that MIPS Loongson3 and RISC-V are affectively running as
little-endian which is what would be expected.

So it appears to me that in qemu that m68k is the only architecture that is
providing goldfish devices on a big-endian architecture.  Also, as far as I
know Linux is the only OS that was updated to cater for that.  If there are
other firmware/bootloaders that expect that maybe they could be updated too?

-Stafford



Re: [RFC PATCH 3/3] hw/openrisc: Add the OpenRISC virtual machine

2022-06-05 Thread Stafford Horne
On Sun, Jun 05, 2022 at 10:58:14AM +0900, Stafford Horne wrote:
> On Fri, Jun 03, 2022 at 09:05:09AM +0200, Geert Uytterhoeven wrote:
> > Hi Stafford,
> > 
> > On Thu, Jun 2, 2022 at 9:59 PM Stafford Horne  wrote:
> > > On Thu, Jun 02, 2022 at 09:08:52PM +0200, Geert Uytterhoeven wrote:
> > > > On Thu, Jun 2, 2022 at 1:42 PM Joel Stanley  wrote:
> > > > > On Fri, 27 May 2022 at 17:27, Stafford Horne  wrote:
> > > > > > This patch add the OpenRISC virtual machine 'virt' for OpenRISC.  
> > > > > > This
> > > > > > platform allows for a convenient CI platform for toolchain, software
> > > > > > ports and the OpenRISC linux kernel port.
> > > > > >
> > > > > > Much of this has been sourced from the m68k and riscv virt 
> > > > > > platforms.
> > > >
> > > > > I enabled the options:
> > > > >
> > > > > CONFIG_RTC_CLASS=y
> > > > > # CONFIG_RTC_SYSTOHC is not set
> > > > > # CONFIG_RTC_NVMEM is not set
> > > > > CONFIG_RTC_DRV_GOLDFISH=y
> > > > >
> > > > > But it didn't work. It seems the goldfish rtc model doesn't handle a
> > > > > big endian guest running on my little endian host.
> > > > >
> > > > > Doing this fixes it:
> > > > >
> > > > > -.endianness = DEVICE_NATIVE_ENDIAN,
> > > > > +.endianness = DEVICE_HOST_ENDIAN,
> > > > >
> > > > > [0.19] goldfish_rtc 96005000.rtc: registered as rtc0
> > > > > [0.19] goldfish_rtc 96005000.rtc: setting system clock to
> > > > > 2022-06-02T11:16:04 UTC (1654168564)
> > > > >
> > > > > But literally no other model in the tree does this, so I suspect it's
> > > > > not the right fix.
> > > >
> > > > Goldfish devices are supposed to be little endian.
> > > > Unfortunately m68k got this wrong, cfr.
> > > > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=2e2ac4a3327479f7e2744cdd88a5c823f2057bad
> > > > Please don't duplicate this bad behavior for new architectures
> > >
> > > Thanks for the pointer, I just wired in the goldfish RTC because I wanted 
> > > to
> > > play with it.  I was not attached to it. I can either remove it our find 
> > > another
> > > RTC.
> > 
> > Sorry for being too unclear: the mistake was not to use the Goldfish
> > RTC, but to make its register accesses big-endian.
> > Using Goldfish devices as little-endian devices should be fine.
> 
> OK, then I would think this patch would be needed on Goldfish.  I tested this
> out and it seems to work:

Sorry, it seems maybe I mis-understood this again.  In Arnd's mail [1] he, at
the end, mentions.

It might be a good idea to revisit the qemu implementation and make
sure that the extra byteswap is only inserted on m68k and not on
other targets, but hopefully there are no new targets based on goldfish
anymore and we don't need to care.

So, it seems that in addition to my patch we would need something in m68k to
switch it back to 'native' (big) endian?

Looking at the m68k kernel/qemu interface I see:

Pre 5.19:
   (data) <-- kernel(readl / little) <-- m68k qemu (native / big) - RTC/PIC
   (data) <-- kernel(__raw_readl / big) <-- m68k qemu (native / big) - TTY

5.19:
   (data) <-- kernel(gf_ioread32 / big) <-- m68k qemu (native / big) - all

The new fixes to add gf_ioread32/gf_iowrite32 fix this for goldfish and m68k.
This wouldn't have been an issue for little-endian platforms where readl/writel
were originally used.

Why can't m68k switch to little-endian in qemu and the kernel?  The m68k virt
platform is not that old, 1 year? Are there a lot of users that this would be a 
big
problem?

[1] 
https://lore.kernel.org/lkml/CAK8P3a1oN8NrUjkh2X8jHQbyz42Xo6GSa=5n0gd6vqcxrjm...@mail.gmail.com/

-Stafford

> Patch:
> 
> diff --git a/hw/rtc/goldfish_rtc.c b/hw/rtc/goldfish_rtc.c
> index 35e493be31..f1dc5af297 100644
> --- a/hw/rtc/goldfish_rtc.c
> +++ b/hw/rtc/goldfish_rtc.c
> @@ -219,7 +219,7 @@ static int goldfish_rtc_post_load(void *opaque, int
> version_id)
>  static const MemoryRegionOps goldfish_rtc_ops = {
>  .read = goldfish_rtc_read,
>  .write = goldfish_rtc_write,
> -.endianness = DEVICE_NATIVE_ENDIAN,
> +.endianness = DEVICE_LITTLE_ENDIAN,
>  .valid = {
>  .min_access_size = 4,
>  .max_access_size = 4
> 
> Boot Log:
> 
> io scheduler mq-deadline registered
> io scheduler kyber registered
> Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled
> 9000.serial: ttyS0 at MMIO 0x9000 (irq = 2, base_baud = 125) 
> is a 16550A
> printk: console [ttyS0] enabled
> loop: module loaded
> virtio_blk virtio1: [vda] 32768 512-byte logical blocks (16.8 MB/16.0 MiB)
> Freeing initrd memory: 1696K
>*goldfish_rtc 96005000.rtc: registered as rtc0
>*goldfish_rtc 96005000.rtc: setting system clock to 2022-06-05T01:49:57 
> UTC (1654393797)
> NET: Registered PF_PACKET protocol family
> random: fast init done
> 
> -Stafford



Re: [RFC PATCH 3/3] hw/openrisc: Add the OpenRISC virtual machine

2022-06-04 Thread Stafford Horne
On Thu, Jun 02, 2022 at 11:42:30AM +, Joel Stanley wrote:
> Hi Stafford,
> 
> On Fri, 27 May 2022 at 17:27, Stafford Horne  wrote:
> >
> > This patch add the OpenRISC virtual machine 'virt' for OpenRISC.  This
> > platform allows for a convenient CI platform for toolchain, software
> > ports and the OpenRISC linux kernel port.
> >
> > Much of this has been sourced from the m68k and riscv virt platforms.
> 
> It's a good idea! I did some playing around with your patch today.
> 
> I'd suggest adding something to docs/system/target-openrsic.rst,
> including an example command lines.

Yeah, good idea, this is the command I am using:

qemu-system-or1k -cpu or1200 -M virt \
  -kernel /home/shorne/work/linux/vmlinux \
  -initrd /home/shorne/work/linux/initramfs.cpio.gz \
  -device virtio-net-device,netdev=user -netdev 
user,id=user,net=10.9.0.1/24,host=10.9.0.100 \
  -serial mon:stdio -nographic \
  -device virtio-blk-device,drive=d0 -drive 
file=/home/shorne/work/linux/virt.qcow2,id=d0,if=none,format=qcow2 \
  -gdb tcp::10001 -smp cpus=2 -m 64

I should have mentioned it but the config I am using is here:

  https://github.com/stffrdhrn/linux/commits/or1k-virt

> >
> > The platform provides:
> >  - OpenRISC SMP with up to 8 cpus
> 
> You have this:
> 
> #define VIRT_CPUS_MAX 4
> i
> I tried booting with -smp 4 and it locked up when starting userspace
> (or I stopped getting serial output?):
> 
> [0.06] smp: Brought up 1 node, 4 CPUs
> ...
> [0.96] Run /init as init process
> 
> Running with -smp 2 and 3 worked. It does make booting much much slower.

Right, it should be 4, I just write 8 from memory.  You are also, right I have
issues with running 4 CPU's.  I will try richard's suggestion.  I have some old
patches to configure MTTCG also, but it had some limitations.  I will dig those
up and get this fixed for this series.

> >  - Generated RTC to automatically configure the guest kernel
> 
> Did you mean device tree?

Yeah, thats what I meant.

> >
> > Signed-off-by: Stafford Horne 
> > ---
> >  configs/devices/or1k-softmmu/default.mak |   1 +
> >  hw/openrisc/Kconfig  |   9 +
> >  hw/openrisc/meson.build  |   1 +
> >  hw/openrisc/virt.c   | 429 +++
> >  4 files changed, 440 insertions(+)
> >  create mode 100644 hw/openrisc/virt.c
> >
> > diff --git a/configs/devices/or1k-softmmu/default.mak 
> > b/configs/devices/or1k-softmmu/default.mak
> > index 5b3ac89491..f3bf816067 100644
> > --- a/configs/devices/or1k-softmmu/default.mak
> > +++ b/configs/devices/or1k-softmmu/default.mak
> > @@ -5,3 +5,4 @@ CONFIG_SEMIHOSTING=y
> >  # Boards:
> >  #
> >  CONFIG_OR1K_SIM=y
> > +CONFIG_OR1K_VIRT=y
> > diff --git a/hw/openrisc/Kconfig b/hw/openrisc/Kconfig
> > index 8f284f3ba0..202134668e 100644
> > --- a/hw/openrisc/Kconfig
> > +++ b/hw/openrisc/Kconfig
> > @@ -4,3 +4,12 @@ config OR1K_SIM
> >  select OPENCORES_ETH
> >  select OMPIC
> >  select SPLIT_IRQ
> > +
> > +config OR1K_VIRT
> > +bool
> > +imply VIRTIO_VGA
> > +imply TEST_DEVICES
> > +select GOLDFISH_RTC
> > +select SERIAL
> > +select SIFIVE_TEST
> > +select VIRTIO_MMIO
> 
> You could include the liteeth device too if we merged that.

I think we could add that with a litex machine.  For that we would need at least
the litex UART and SoC for reset.

> > diff --git a/hw/openrisc/virt.c b/hw/openrisc/virt.c
> > new file mode 100644
> > index 00..147196fda3
> > --- /dev/null
> > +++ b/hw/openrisc/virt.c
> > @@ -0,0 +1,429 @@
> > +/*
> > + * OpenRISC QEMU virtual machine.
> > + *
> > + * Copyright (c) 2022 Stafford Horne 
> > + *
> > + * This library is free software; you can redistribute it and/or
> > + * modify it under the terms of the GNU Lesser General Public
> > + * License as published by the Free Software Foundation; either
> > + * version 2.1 of the License, or (at your option) any later version.
> > + *
> > + * This library is distributed in the hope that it will be useful,
> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> > + * Lesser General Public License for more details.
> > + *
> > + * You should have received a copy of the GNU Lesser General Public
> > + * License along with this library; if not, see 
> > <http://www.gnu.org/licenses/>.
> 
> I think you can use the SPDX tag here instead of

Re: [RFC PATCH 3/3] hw/openrisc: Add the OpenRISC virtual machine

2022-06-04 Thread Stafford Horne
On Fri, Jun 03, 2022 at 09:05:09AM +0200, Geert Uytterhoeven wrote:
> Hi Stafford,
> 
> On Thu, Jun 2, 2022 at 9:59 PM Stafford Horne  wrote:
> > On Thu, Jun 02, 2022 at 09:08:52PM +0200, Geert Uytterhoeven wrote:
> > > On Thu, Jun 2, 2022 at 1:42 PM Joel Stanley  wrote:
> > > > On Fri, 27 May 2022 at 17:27, Stafford Horne  wrote:
> > > > > This patch add the OpenRISC virtual machine 'virt' for OpenRISC.  This
> > > > > platform allows for a convenient CI platform for toolchain, software
> > > > > ports and the OpenRISC linux kernel port.
> > > > >
> > > > > Much of this has been sourced from the m68k and riscv virt platforms.
> > >
> > > > I enabled the options:
> > > >
> > > > CONFIG_RTC_CLASS=y
> > > > # CONFIG_RTC_SYSTOHC is not set
> > > > # CONFIG_RTC_NVMEM is not set
> > > > CONFIG_RTC_DRV_GOLDFISH=y
> > > >
> > > > But it didn't work. It seems the goldfish rtc model doesn't handle a
> > > > big endian guest running on my little endian host.
> > > >
> > > > Doing this fixes it:
> > > >
> > > > -.endianness = DEVICE_NATIVE_ENDIAN,
> > > > +.endianness = DEVICE_HOST_ENDIAN,
> > > >
> > > > [0.19] goldfish_rtc 96005000.rtc: registered as rtc0
> > > > [0.19] goldfish_rtc 96005000.rtc: setting system clock to
> > > > 2022-06-02T11:16:04 UTC (1654168564)
> > > >
> > > > But literally no other model in the tree does this, so I suspect it's
> > > > not the right fix.
> > >
> > > Goldfish devices are supposed to be little endian.
> > > Unfortunately m68k got this wrong, cfr.
> > > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=2e2ac4a3327479f7e2744cdd88a5c823f2057bad
> > > Please don't duplicate this bad behavior for new architectures
> >
> > Thanks for the pointer, I just wired in the goldfish RTC because I wanted to
> > play with it.  I was not attached to it. I can either remove it our find 
> > another
> > RTC.
> 
> Sorry for being too unclear: the mistake was not to use the Goldfish
> RTC, but to make its register accesses big-endian.
> Using Goldfish devices as little-endian devices should be fine.

OK, then I would think this patch would be needed on Goldfish.  I tested this
out and it seems to work:

Patch:

diff --git a/hw/rtc/goldfish_rtc.c b/hw/rtc/goldfish_rtc.c
index 35e493be31..f1dc5af297 100644
--- a/hw/rtc/goldfish_rtc.c
+++ b/hw/rtc/goldfish_rtc.c
@@ -219,7 +219,7 @@ static int goldfish_rtc_post_load(void *opaque, int
version_id)
 static const MemoryRegionOps goldfish_rtc_ops = {
 .read = goldfish_rtc_read,
 .write = goldfish_rtc_write,
-.endianness = DEVICE_NATIVE_ENDIAN,
+.endianness = DEVICE_LITTLE_ENDIAN,
 .valid = {
 .min_access_size = 4,
 .max_access_size = 4

Boot Log:

io scheduler mq-deadline registered
io scheduler kyber registered
Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled
9000.serial: ttyS0 at MMIO 0x9000 (irq = 2, base_baud = 125) is 
a 16550A
printk: console [ttyS0] enabled
loop: module loaded
virtio_blk virtio1: [vda] 32768 512-byte logical blocks (16.8 MB/16.0 MiB)
Freeing initrd memory: 1696K
   *goldfish_rtc 96005000.rtc: registered as rtc0
   *goldfish_rtc 96005000.rtc: setting system clock to 2022-06-05T01:49:57 UTC 
(1654393797)
NET: Registered PF_PACKET protocol family
random: fast init done

-Stafford



Re: [RFC PATCH 1/3] target/openrisc: Add basic support for semihosting

2022-06-04 Thread Stafford Horne
On Thu, Jun 02, 2022 at 08:39:21AM -0700, Richard Henderson wrote:
> On 5/27/22 10:27, Stafford Horne wrote:
> > +void do_or1k_semihosting(CPUOpenRISCState *env, uint32_t k);
> ...
> > +DEF_HELPER_FLAGS_2(nop, 0, void, env, i32)
> 
> Just call the helper "semihosting" and be done with it.
> And the helper wants an ifdef for system mode.
> 
> > @@ -10,6 +10,7 @@ openrisc_ss.add(files(
> > 'fpu_helper.c',
> > 'gdbstub.c',
> > 'interrupt_helper.c',
> > +  'openrisc-semi.c',
> > 'sys_helper.c',
> > 'translate.c',
> >   ))
> 
> You want to add the new file for system mode only.
> Or, now that I think of it, conditional on CONFIG_SEMIHOSTING itself.

That's right, I'll update it.

> > +static void or1k_semi_return_u32(CPUOpenRISCState *env, uint32_t ret)
> > +{
> > +cpu_set_gpr(env, 11, ret);
> > +}
> 
> Let's drop this until you actually use it.  This appears to be attempting to
> mirror other, more complete semihosting, but missing the third "error"
> argument

Sure, I did mention I kept these here for future (real) semihosting support.
But I don't think that will happen.  So I can remove.

> > +void do_or1k_semihosting(CPUOpenRISCState *env, uint32_t k)
> > +{
> > +uint32_t result;
> > +
> > +switch (k) {
> > +case HOSTED_EXIT:
> > +gdb_exit(cpu_get_gpr(env, 3));
> > +exit(cpu_get_gpr(env, 3));
> > +case HOSTED_RESET:
> > +#ifndef CONFIG_USER_ONLY
> > +qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
> > +return;
> > +#endif
> 
> Do you in fact want to exit to the main loop after asking for reset?
> That's the only way that "no return value" makes sense to me...

OK. I'll look at this more.
 
> > +default:
> > +qemu_log_mask(LOG_GUEST_ERROR, "or1k-semihosting: unsupported "
> > +  "semihosting syscall %d\n", k);
> 
> %u.

OK.

> >   static bool trans_l_nop(DisasContext *dc, arg_l_nop *a)
> >   {
> > +if (semihosting_enabled() &&
> > +a->k != 0) {
> > +gen_helper_nop(cpu_env, tcg_constant_i32(a->k));
> > +}
> 
> Perhaps cleaner to move the semihosting dispatch switch here, instead of
> leaving it to the runtime?  The reason we have a runtime switch for other
> guests is that the semihosting syscall number is in a register.  This would
> then be
> 
> if (semihosting_enabled()) {
> switch (a->k) {
> case 0:
> break; /* normal nop */
> case HOSTED_EXIT:
> gen_helper_semihost_exit(cpu_R(dc, 3));
> break;
> case HOSTED_RESET:
> gen_helper_semihost_reset();
> tcg_gen_movi_tl(cpu_pc, dc->base.pc_next + 4);
> 
> dc->base.is_jmp = DISAS_EXIT;
> break;
> ...
> }
> }

Yeah, that makes sense. I had written it in a way that would allow expanding for
real semi-hosting.  But I don't think we will do that with OpenRISC, so this is
good enough.

I am not sure if you saw the cover letter. I sent this RFC series to help
illustrate two options for providing OpenRISC targets that support poweroff and
reset.

One option being using these NOP's, the second is to create a virt target with
reset/poweroff hardware.

I am kind of leaning towards dropping the semi-hosting patches and only moving
forward with the virt patches.  The reason being that 1. we would not need to
expand the architecture spec to support the qemu virt platform, and we would
need to document the NOP's formally, and 2. OpenRISC doesn't really support the
full "semihosting" facilities for file open/close/write etc.

Any thoughts?  I guess this "semihosting" patch is pretty trivial.  But, maybe
it causes more confusion compared to just going with the virt route.  Also, if
we have virt I can't imagine anyone using the semihosting much.

-Stafford



Re: [RFC PATCH 3/3] hw/openrisc: Add the OpenRISC virtual machine

2022-06-02 Thread Stafford Horne
On Thu, Jun 02, 2022 at 09:08:52PM +0200, Geert Uytterhoeven wrote:
> Hi Joel,
> 
> On Thu, Jun 2, 2022 at 1:42 PM Joel Stanley  wrote:
> > On Fri, 27 May 2022 at 17:27, Stafford Horne  wrote:
> > > This patch add the OpenRISC virtual machine 'virt' for OpenRISC.  This
> > > platform allows for a convenient CI platform for toolchain, software
> > > ports and the OpenRISC linux kernel port.
> > >
> > > Much of this has been sourced from the m68k and riscv virt platforms.
> 
> > I enabled the options:
> >
> > CONFIG_RTC_CLASS=y
> > # CONFIG_RTC_SYSTOHC is not set
> > # CONFIG_RTC_NVMEM is not set
> > CONFIG_RTC_DRV_GOLDFISH=y
> >
> > But it didn't work. It seems the goldfish rtc model doesn't handle a
> > big endian guest running on my little endian host.
> >
> > Doing this fixes it:
> >
> > -.endianness = DEVICE_NATIVE_ENDIAN,
> > +.endianness = DEVICE_HOST_ENDIAN,
> >
> > [0.19] goldfish_rtc 96005000.rtc: registered as rtc0
> > [0.19] goldfish_rtc 96005000.rtc: setting system clock to
> > 2022-06-02T11:16:04 UTC (1654168564)
> >
> > But literally no other model in the tree does this, so I suspect it's
> > not the right fix.
> 
> Goldfish devices are supposed to be little endian.
> Unfortunately m68k got this wrong, cfr.
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=2e2ac4a3327479f7e2744cdd88a5c823f2057bad
> Please don't duplicate this bad behavior for new architectures

Thanks for the pointer, I just wired in the goldfish RTC because I wanted to
play with it.  I was not attached to it. I can either remove it our find another
RTC.

-Stafford



[RFC PATCH 3/3] hw/openrisc: Add the OpenRISC virtual machine

2022-05-27 Thread Stafford Horne
This patch add the OpenRISC virtual machine 'virt' for OpenRISC.  This
platform allows for a convenient CI platform for toolchain, software
ports and the OpenRISC linux kernel port.

Much of this has been sourced from the m68k and riscv virt platforms.

The platform provides:
 - OpenRISC SMP with up to 8 cpus
 - A virtio bus with up to 8 devices
 - Standard ns16550a serial
 - Goldfish RTC
 - SiFive TEST device for poweroff and reboot
 - Generated RTC to automatically configure the guest kernel

Signed-off-by: Stafford Horne 
---
 configs/devices/or1k-softmmu/default.mak |   1 +
 hw/openrisc/Kconfig  |   9 +
 hw/openrisc/meson.build  |   1 +
 hw/openrisc/virt.c   | 429 +++
 4 files changed, 440 insertions(+)
 create mode 100644 hw/openrisc/virt.c

diff --git a/configs/devices/or1k-softmmu/default.mak 
b/configs/devices/or1k-softmmu/default.mak
index 5b3ac89491..f3bf816067 100644
--- a/configs/devices/or1k-softmmu/default.mak
+++ b/configs/devices/or1k-softmmu/default.mak
@@ -5,3 +5,4 @@ CONFIG_SEMIHOSTING=y
 # Boards:
 #
 CONFIG_OR1K_SIM=y
+CONFIG_OR1K_VIRT=y
diff --git a/hw/openrisc/Kconfig b/hw/openrisc/Kconfig
index 8f284f3ba0..202134668e 100644
--- a/hw/openrisc/Kconfig
+++ b/hw/openrisc/Kconfig
@@ -4,3 +4,12 @@ config OR1K_SIM
 select OPENCORES_ETH
 select OMPIC
 select SPLIT_IRQ
+
+config OR1K_VIRT
+bool
+imply VIRTIO_VGA
+imply TEST_DEVICES
+select GOLDFISH_RTC
+select SERIAL
+select SIFIVE_TEST
+select VIRTIO_MMIO
diff --git a/hw/openrisc/meson.build b/hw/openrisc/meson.build
index ab563820c5..2dbc6365bb 100644
--- a/hw/openrisc/meson.build
+++ b/hw/openrisc/meson.build
@@ -2,5 +2,6 @@ openrisc_ss = ss.source_set()
 openrisc_ss.add(files('cputimer.c'))
 openrisc_ss.add(files('boot.c'))
 openrisc_ss.add(when: 'CONFIG_OR1K_SIM', if_true: [files('openrisc_sim.c'), 
fdt])
+openrisc_ss.add(when: 'CONFIG_OR1K_VIRT', if_true: [files('virt.c'), fdt])
 
 hw_arch += {'openrisc': openrisc_ss}
diff --git a/hw/openrisc/virt.c b/hw/openrisc/virt.c
new file mode 100644
index 00..147196fda3
--- /dev/null
+++ b/hw/openrisc/virt.c
@@ -0,0 +1,429 @@
+/*
+ * OpenRISC QEMU virtual machine.
+ *
+ * Copyright (c) 2022 Stafford Horne 
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/error-report.h"
+#include "qapi/error.h"
+#include "cpu.h"
+#include "hw/irq.h"
+#include "hw/boards.h"
+#include "hw/char/serial.h"
+#include "hw/openrisc/boot.h"
+#include "hw/misc/sifive_test.h"
+#include "hw/qdev-properties.h"
+#include "exec/address-spaces.h"
+#include "sysemu/device_tree.h"
+#include "sysemu/sysemu.h"
+#include "hw/sysbus.h"
+#include "sysemu/qtest.h"
+#include "sysemu/reset.h"
+#include "hw/core/split-irq.h"
+
+#include 
+
+#define VIRT_CPUS_MAX 4
+#define VIRT_CLK_MHZ 2000
+
+#define TYPE_VIRT_MACHINE MACHINE_TYPE_NAME("virt")
+#define VIRT_MACHINE(obj) \
+OBJECT_CHECK(OR1KVirtState, (obj), TYPE_VIRT_MACHINE)
+
+typedef struct OR1KVirtState {
+/*< private >*/
+MachineState parent_obj;
+
+/*< public >*/
+void *fdt;
+int fdt_size;
+
+} OR1KVirtState;
+
+enum {
+VIRT_DRAM,
+VIRT_TEST,
+VIRT_RTC,
+VIRT_VIRTIO,
+VIRT_UART,
+VIRT_OMPIC,
+};
+
+enum {
+VIRT_OMPIC_IRQ = 1,
+VIRT_UART_IRQ = 2,
+VIRT_RTC_IRQ = 3,
+VIRT_VIRTIO_IRQ = 4, /* to 12 */
+VIRTIO_COUNT = 8,
+};
+
+static const struct MemmapEntry {
+hwaddr base;
+hwaddr size;
+} virt_memmap[] = {
+[VIRT_DRAM] =  { 0x,  0 },
+[VIRT_UART] =  { 0x9000,  0x100 },
+[VIRT_TEST] =  { 0x9600,0x8 },
+[VIRT_RTC] =   { 0x96005000, 0x1000 },
+[VIRT_VIRTIO] ={ 0x9700, 0x1000 },
+[VIRT_OMPIC] = { 0x9800, VIRT_CPUS_MAX * 8 },
+};
+
+static struct openrisc_boot_info {
+uint32_t bootstrap_pc;
+uint32_t fdt_addr;
+} boot_info;
+
+static void main_cpu_reset(void *opaque)
+{
+OpenRISCCPU *cpu = opaque;
+CPUState *cs = CPU(cpu);
+
+cpu_reset(CPU(cpu));
+
+cpu_set_pc(cs, boot_info.bootstrap_pc);
+  

[RFC PATCH 1/3] target/openrisc: Add basic support for semihosting

2022-05-27 Thread Stafford Horne
For OpenRISC we currently only use semihosting for system exit and
reset.  This patch implements that.

The implementation uses a helper to delegate to the semihosting
facility.  The helper is marked as having side effects but currently
does not have any.  I have defined it like this as our other
unimplemented semihosting calls will have side effects and return
results in register r11.

Signed-off-by: Stafford Horne 
---
 configs/devices/or1k-softmmu/default.mak |  2 +
 qemu-options.hx  | 16 ---
 target/openrisc/cpu.h|  2 +
 target/openrisc/helper.h |  1 +
 target/openrisc/meson.build  |  1 +
 target/openrisc/openrisc-semi.c  | 54 
 target/openrisc/sys_helper.c |  5 +++
 target/openrisc/translate.c  |  6 +++
 8 files changed, 82 insertions(+), 5 deletions(-)
 create mode 100644 target/openrisc/openrisc-semi.c

diff --git a/configs/devices/or1k-softmmu/default.mak 
b/configs/devices/or1k-softmmu/default.mak
index 168101c39a..5b3ac89491 100644
--- a/configs/devices/or1k-softmmu/default.mak
+++ b/configs/devices/or1k-softmmu/default.mak
@@ -1,5 +1,7 @@
 # Default configuration for or1k-softmmu
 
+CONFIG_SEMIHOSTING=y
+
 # Boards:
 #
 CONFIG_OR1K_SIM=y
diff --git a/qemu-options.hx b/qemu-options.hx
index b484640067..312c68b065 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -4566,10 +4566,12 @@ ERST
 DEF("semihosting", 0, QEMU_OPTION_semihosting,
 "-semihostingsemihosting mode\n",
 QEMU_ARCH_ARM | QEMU_ARCH_M68K | QEMU_ARCH_XTENSA |
-QEMU_ARCH_MIPS | QEMU_ARCH_NIOS2 | QEMU_ARCH_RISCV)
+QEMU_ARCH_MIPS | QEMU_ARCH_NIOS2 | QEMU_ARCH_RISCV |
+QEMU_ARCH_OPENRISC)
 SRST
 ``-semihosting``
-Enable semihosting mode (ARM, M68K, Xtensa, MIPS, Nios II, RISC-V only).
+Enable semihosting mode (ARM, M68K, Xtensa, MIPS, Nios II, RISC-V,
+OpenRISC only).
 
 Note that this allows guest direct access to the host filesystem, so
 should only be used with a trusted guest OS.
@@ -4581,11 +4583,12 @@ DEF("semihosting-config", HAS_ARG, 
QEMU_OPTION_semihosting_config,
 "-semihosting-config 
[enable=on|off][,target=native|gdb|auto][,chardev=id][,arg=str[,...]]\n" \
 "semihosting configuration\n",
 QEMU_ARCH_ARM | QEMU_ARCH_M68K | QEMU_ARCH_XTENSA |
-QEMU_ARCH_MIPS | QEMU_ARCH_NIOS2 | QEMU_ARCH_RISCV)
+QEMU_ARCH_MIPS | QEMU_ARCH_NIOS2 | QEMU_ARCH_RISCV |
+QEMU_ARCH_OPENRISC)
 SRST
 ``-semihosting-config 
[enable=on|off][,target=native|gdb|auto][,chardev=id][,arg=str[,...]]``
-Enable and configure semihosting (ARM, M68K, Xtensa, MIPS, Nios II, RISC-V
-only).
+Enable and configure semihosting (ARM, M68K, Xtensa, MIPS, Nios II, RISC-V,
+OpenRISC only).
 
 Note that this allows guest direct access to the host filesystem, so
 should only be used with a trusted guest OS.
@@ -4601,6 +4604,9 @@ SRST
 
 On RISC-V this implements the standard semihosting API, version 0.2.
 
+On OpenRISC this only supports providing simulation exit and reset
+facilities.
+
 ``target=native|gdb|auto``
 Defines where the semihosting calls will be addressed, to QEMU
 (``native``) or to GDB (``gdb``). The default is ``auto``, which
diff --git a/target/openrisc/cpu.h b/target/openrisc/cpu.h
index b9584f10d4..4617f1272b 100644
--- a/target/openrisc/cpu.h
+++ b/target/openrisc/cpu.h
@@ -407,4 +407,6 @@ void cpu_set_fpcsr(CPUOpenRISCState *env, uint32_t val);
 
 #define CPU_INTERRUPT_TIMER   CPU_INTERRUPT_TGT_INT_0
 
+void do_or1k_semihosting(CPUOpenRISCState *env, uint32_t k);
+
 #endif /* OPENRISC_CPU_H */
diff --git a/target/openrisc/helper.h b/target/openrisc/helper.h
index d847814a28..2fe3e4e4ca 100644
--- a/target/openrisc/helper.h
+++ b/target/openrisc/helper.h
@@ -64,3 +64,4 @@ DEF_HELPER_FLAGS_1(rfe, 0, void, env)
 /* sys */
 DEF_HELPER_FLAGS_3(mtspr, 0, void, env, tl, tl)
 DEF_HELPER_FLAGS_3(mfspr, TCG_CALL_NO_WG, tl, env, tl, tl)
+DEF_HELPER_FLAGS_2(nop, 0, void, env, i32)
diff --git a/target/openrisc/meson.build b/target/openrisc/meson.build
index 84322086ec..1c1758b846 100644
--- a/target/openrisc/meson.build
+++ b/target/openrisc/meson.build
@@ -10,6 +10,7 @@ openrisc_ss.add(files(
   'fpu_helper.c',
   'gdbstub.c',
   'interrupt_helper.c',
+  'openrisc-semi.c',
   'sys_helper.c',
   'translate.c',
 ))
diff --git a/target/openrisc/openrisc-semi.c b/target/openrisc/openrisc-semi.c
new file mode 100644
index 00..97d6aaacdb
--- /dev/null
+++ b/target/openrisc/openrisc-semi.c
@@ -0,0 +1,54 @@
+/*
+ *  OpenRISC Semihosting syscall interface.
+ *
+ *  Copyright (c) 2022 Stafford Horne
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version

[RFC PATCH 2/3] hw/openrisc: Split re-usable boot time apis out to boot.c

2022-05-27 Thread Stafford Horne
These will be shared with the virt platform.

Signed-off-by: Stafford Horne 
---
 hw/openrisc/boot.c | 127 +
 hw/openrisc/meson.build|   1 +
 hw/openrisc/openrisc_sim.c | 106 ++-
 include/hw/openrisc/boot.h |  34 ++
 4 files changed, 168 insertions(+), 100 deletions(-)
 create mode 100644 hw/openrisc/boot.c
 create mode 100644 include/hw/openrisc/boot.h

diff --git a/hw/openrisc/boot.c b/hw/openrisc/boot.c
new file mode 100644
index 00..32f0925a8c
--- /dev/null
+++ b/hw/openrisc/boot.c
@@ -0,0 +1,127 @@
+/*
+ * QEMU OpenRISC boot helpers.
+ *
+ * Copyright (c) 2022 Stafford Horne 
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "exec/cpu-defs.h"
+#include "elf.h"
+#include "hw/loader.h"
+#include "hw/openrisc/boot.h"
+#include "sysemu/device_tree.h"
+#include "sysemu/qtest.h"
+
+#include 
+
+#define KERNEL_LOAD_ADDR 0x100
+
+hwaddr openrisc_load_kernel(ram_addr_t ram_size,
+const char *kernel_filename,
+uint32_t *bootstrap_pc)
+{
+long kernel_size;
+uint64_t elf_entry;
+uint64_t high_addr;
+hwaddr entry;
+
+if (kernel_filename && !qtest_enabled()) {
+kernel_size = load_elf(kernel_filename, NULL, NULL, NULL,
+   _entry, NULL, _addr, NULL, 1,
+   EM_OPENRISC, 1, 0);
+entry = elf_entry;
+if (kernel_size < 0) {
+kernel_size = load_uimage(kernel_filename,
+  , NULL, NULL, NULL, NULL);
+high_addr = entry + kernel_size;
+}
+if (kernel_size < 0) {
+kernel_size = load_image_targphys(kernel_filename,
+  KERNEL_LOAD_ADDR,
+  ram_size - KERNEL_LOAD_ADDR);
+high_addr = KERNEL_LOAD_ADDR + kernel_size;
+}
+
+if (entry <= 0) {
+entry = KERNEL_LOAD_ADDR;
+}
+
+if (kernel_size < 0) {
+error_report("couldn't load the kernel '%s'", kernel_filename);
+exit(1);
+}
+*bootstrap_pc = entry;
+
+return high_addr;
+}
+return 0;
+}
+
+hwaddr openrisc_load_initrd(void *fdt, const char *filename,
+hwaddr load_start, uint64_t mem_size)
+{
+int size;
+hwaddr start;
+
+/* We put the initrd right after the kernel; page aligned. */
+start = TARGET_PAGE_ALIGN(load_start);
+
+size = load_ramdisk(filename, start, mem_size - start);
+if (size < 0) {
+size = load_image_targphys(filename, start, mem_size - start);
+if (size < 0) {
+error_report("could not load ramdisk '%s'", filename);
+exit(1);
+}
+}
+
+if (fdt) {
+qemu_fdt_setprop_cell(fdt, "/chosen",
+  "linux,initrd-start", start);
+qemu_fdt_setprop_cell(fdt, "/chosen",
+  "linux,initrd-end", start + size);
+}
+
+return start + size;
+}
+
+uint32_t openrisc_load_fdt(void *fdt, hwaddr load_start,
+   uint64_t mem_size)
+{
+uint32_t fdt_addr;
+int ret;
+int fdtsize = fdt_totalsize(fdt);
+
+if (fdtsize <= 0) {
+error_report("invalid device-tree");
+exit(1);
+}
+
+/* We put fdt right after the kernel and/or initrd. */
+fdt_addr = TARGET_PAGE_ALIGN(load_start);
+
+ret = fdt_pack(fdt);
+/* Should only fail if we've built a corrupted tree */
+g_assert(ret == 0);
+/* copy in the device tree */
+qemu_fdt_dumpdtb(fdt, fdtsize);
+
+rom_add_blob_fixed_as("fdt", fdt, fdtsize, fdt_addr,
+  _space_memory);
+
+return fdt_addr;
+}
+
diff --git a/hw/openrisc/meson.build b/hw/openrisc/meson.build
index ec48172c9d..ab563820c5 100644
--- a/hw/openrisc/meson.build
+++ b/hw/openrisc/meson.build
@@ -1,5 +1,6 @@
 openrisc_ss = ss.source_set()
 openrisc_ss.add(files('cputimer.c'))
+openrisc_ss.add(files('boot.c'))
 openrisc_ss.add(when: 'CONFIG_OR1K_SIM', if_true: [files('openris

[RFC PATCH 0/3] OpenRISC Semihosting and Virt

2022-05-27 Thread Stafford Horne
Hello,

I provide 2 options here 2 help with OpenRISC CI testing sush as the wireguard
testing that Jason has been working on.

The two are:

 1. Add semihosting to openrisc to handle l.nop based Halt and Reset
 2. Define a new virt platform, this includes widing in the sifive test device
that provides a syscon interface to allow for shutdown and reboot.

We could upstream both of them or just one. I am leaning toward dropping the
semi-hosting work and just going ahead with virt.

The semi-hosting stuff was discussed here:

 - https://www.mail-archive.com/qemu-devel@nongnu.org/msg884560.html

Also, I started to propose architecture changes here:

 - https://github.com/openrisc/openrisc.github.io/pull/18

However, looking at how other platforms define semihosting it seems the openrisc
requirements are quite different.  We do not use the open/close/write etc
syscalls as riscv, arm etc do.

Stafford Horne (3):
  target/openrisc: Add basic support for semihosting
  hw/openrisc: Split re-usable boot time apis out to boot.c
  hw/openrisc: Add the OpenRISC virtual machine

 configs/devices/or1k-softmmu/default.mak |   3 +
 hw/openrisc/Kconfig  |   9 +
 hw/openrisc/boot.c   | 127 +++
 hw/openrisc/meson.build  |   2 +
 hw/openrisc/openrisc_sim.c   | 106 +-
 hw/openrisc/virt.c   | 429 +++
 include/hw/openrisc/boot.h   |  34 ++
 qemu-options.hx  |  16 +-
 target/openrisc/cpu.h|   2 +
 target/openrisc/helper.h |   1 +
 target/openrisc/meson.build  |   1 +
 target/openrisc/openrisc-semi.c  |  54 +++
 target/openrisc/sys_helper.c |   5 +
 target/openrisc/translate.c  |   6 +
 14 files changed, 690 insertions(+), 105 deletions(-)
 create mode 100644 hw/openrisc/boot.c
 create mode 100644 hw/openrisc/virt.c
 create mode 100644 include/hw/openrisc/boot.h
 create mode 100644 target/openrisc/openrisc-semi.c

-- 
2.31.1




Re: [PULL 0/4] OpenRISC fixes for QEMU 2022-05-15

2022-05-15 Thread Stafford Horne
On Sun, May 15, 2022 at 04:12:50PM -0700, Richard Henderson wrote:
> On 5/14/22 18:39, Stafford Horne wrote:
> > The following changes since commit 2e3408b3cc7de4e87a9adafc8c19bfce3abec947:
> > 
> >Merge tag 'misc-pull-request' of gitlab.com:marcandre.lureau/qemu into 
> > staging (2022-05-03 09:13:17 -0700)
> > 
> > are available in the Git repository at:
> > 
> >https://github.com/stffrdhrn/qemu.git tags/or1k-pull-request-20220515
> > 
> > for you to fetch changes up to e8f0ab0cd674241cbab7231ce05ac1bfa0b4f5ed:
> > 
> >target/openrisc: Do not reset delay slot flag on early tb exit 
> > (2022-05-15 10:33:01 +0900)
> > 
> > 
> > OpenRISC Fixes for 7.0
> > 
> >   - A few or1ksim fixes and enhancements
> >   - A fix for OpenRISC tcg backend around delay slot handling
> 
> Applied, thanks.  Please update https://wiki.qemu.org/ChangeLog/7.1 as 
> appropriate.
> 
> The gpg key I have for you is expired.  Have you refreshed the expiration
> date and pushed the new copy somewhere?

Hello Richard,

I updated my PGP key (C3B31C2D5E6627E4) last year or so to extend the expiry
day.  It should be uploaded to pgp.mit.edu, but for some reason that server is
not responding to searches for me right now.

I have also just uploaded it to keyserver.ubuntu.com if that helps.

 - 
https://keyserver.ubuntu.com/pks/lookup?search=stafford+horne=on=index

sec  rsa4096/C3B31C2D5E6627E4
 created: 2016-09-14  expires: never   usage: SC

If you still have any issue I can try to work it out.

-Stafford



[PULL 4/4] target/openrisc: Do not reset delay slot flag on early tb exit

2022-05-14 Thread Stafford Horne
This was found when running linux crypto algorithm selftests used by
wireguard.  We found that randomly the tests would fail.  We found
through investigation that a combination of a tick timer interrupt,
raised when executing a delay slot instruction at a page boundary caused
the issue.

This was caused when handling the TB_EXIT_REQUESTED case in cpu_tb_exec.
On OpenRISC, which doesn't implement synchronize_from_tb, set_pc was
being used as a fallback.  The OpenRISC set_pc implementation clears
dflag, which caused the exception handling logic to not account for the
delay slot.  This was the bug, because it meant when execution resumed
after the interrupt was handling it resumed in the wrong place.

Fix this by implementing synchronize_from_tb which simply updates pc,
and not clear the delay slot flag.

Reported-by: Jason A. Donenfeld 
Reviewed-by: Richard Henderson 
Signed-off-by: Stafford Horne 
---
 target/openrisc/cpu.c | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/target/openrisc/cpu.c b/target/openrisc/cpu.c
index dfbafc5236..41d1b2a24a 100644
--- a/target/openrisc/cpu.c
+++ b/target/openrisc/cpu.c
@@ -21,6 +21,7 @@
 #include "qapi/error.h"
 #include "qemu/qemu-print.h"
 #include "cpu.h"
+#include "exec/exec-all.h"
 
 static void openrisc_cpu_set_pc(CPUState *cs, vaddr value)
 {
@@ -30,6 +31,15 @@ static void openrisc_cpu_set_pc(CPUState *cs, vaddr value)
 cpu->env.dflag = 0;
 }
 
+static void openrisc_cpu_synchronize_from_tb(CPUState *cs,
+ const TranslationBlock *tb)
+{
+OpenRISCCPU *cpu = OPENRISC_CPU(cs);
+
+cpu->env.pc = tb->pc;
+}
+
+
 static bool openrisc_cpu_has_work(CPUState *cs)
 {
 return cs->interrupt_request & (CPU_INTERRUPT_HARD |
@@ -186,6 +196,7 @@ static const struct SysemuCPUOps openrisc_sysemu_ops = {
 
 static const struct TCGCPUOps openrisc_tcg_ops = {
 .initialize = openrisc_translate_init,
+.synchronize_from_tb = openrisc_cpu_synchronize_from_tb,
 
 #ifndef CONFIG_USER_ONLY
 .tlb_fill = openrisc_cpu_tlb_fill,
-- 
2.31.1




[PULL 2/4] hw/openrisc: support 4 serial ports in or1ksim

2022-05-14 Thread Stafford Horne
From: "Jason A. Donenfeld" 

The 8250 serial controller supports 4 serial ports, so wire them all up,
so that we can have more than one basic I/O channel.

Cc: Stafford Horne 
Signed-off-by: Jason A. Donenfeld 
[smh:Fixup indentation and lines over 80 chars]
Signed-off-by: Stafford Horne 
---
 hw/openrisc/openrisc_sim.c | 22 --
 1 file changed, 16 insertions(+), 6 deletions(-)

diff --git a/hw/openrisc/openrisc_sim.c b/hw/openrisc/openrisc_sim.c
index 99b14940f4..6873124f74 100644
--- a/hw/openrisc/openrisc_sim.c
+++ b/hw/openrisc/openrisc_sim.c
@@ -71,6 +71,10 @@ enum {
 OR1KSIM_ETHOC_IRQ = 4,
 };
 
+enum {
+OR1KSIM_UART_COUNT = 4
+};
+
 static const struct MemmapEntry {
 hwaddr base;
 hwaddr size;
@@ -239,11 +243,13 @@ static void openrisc_sim_ompic_init(Or1ksimState *state, 
hwaddr base,
 
 static void openrisc_sim_serial_init(Or1ksimState *state, hwaddr base,
  hwaddr size, int num_cpus,
- OpenRISCCPU *cpus[], int irq_pin)
+ OpenRISCCPU *cpus[], int irq_pin,
+ int uart_idx)
 {
 void *fdt = state->fdt;
 char *nodename;
 qemu_irq serial_irq;
+char alias[sizeof("uart0")];
 int i;
 
 if (num_cpus > 1) {
@@ -258,7 +264,8 @@ static void openrisc_sim_serial_init(Or1ksimState *state, 
hwaddr base,
 serial_irq = get_cpu_irq(cpus, 0, irq_pin);
 }
 serial_mm_init(get_system_memory(), base, 0, serial_irq, 115200,
-   serial_hd(0), DEVICE_NATIVE_ENDIAN);
+   serial_hd(OR1KSIM_UART_COUNT - uart_idx - 1),
+   DEVICE_NATIVE_ENDIAN);
 
 /* Add device tree node for serial. */
 nodename = g_strdup_printf("/serial@%" HWADDR_PRIx, base);
@@ -271,7 +278,8 @@ static void openrisc_sim_serial_init(Or1ksimState *state, 
hwaddr base,
 
 /* The /chosen node is created during fdt creation. */
 qemu_fdt_setprop_string(fdt, "/chosen", "stdout-path", nodename);
-qemu_fdt_setprop_string(fdt, "/aliases", "uart0", nodename);
+snprintf(alias, sizeof(alias), "uart%d", uart_idx);
+qemu_fdt_setprop_string(fdt, "/aliases", alias, nodename);
 g_free(nodename);
 }
 
@@ -414,9 +422,11 @@ static void openrisc_sim_init(MachineState *machine)
 smp_cpus, cpus, OR1KSIM_OMPIC_IRQ);
 }
 
-openrisc_sim_serial_init(state, or1ksim_memmap[OR1KSIM_UART].base,
- or1ksim_memmap[OR1KSIM_UART].size, smp_cpus, cpus,
- OR1KSIM_UART_IRQ);
+for (n = 0; n < OR1KSIM_UART_COUNT; ++n)
+openrisc_sim_serial_init(state, or1ksim_memmap[OR1KSIM_UART].base +
+or1ksim_memmap[OR1KSIM_UART].size * n,
+ or1ksim_memmap[OR1KSIM_UART].size,
+ smp_cpus, cpus, OR1KSIM_UART_IRQ, n);
 
 load_addr = openrisc_load_kernel(ram_size, kernel_filename);
 if (load_addr > 0) {
-- 
2.31.1




[PULL 3/4] hw/openrisc: use right OMPIC size variable

2022-05-14 Thread Stafford Horne
From: "Jason A. Donenfeld" 

This appears to be a copy and paste error. The UART size was used
instead of the much smaller OMPIC size. But actually that smaller OMPIC
size is wrong too and doesn't allow the IPI to work in Linux. So set it
to the old value.

Signed-off-by: Jason A. Donenfeld 
[smh:Updated OR1KSIM_OMPIC size to use OR1KSIM_CPUS_MAX]
Signed-off-by: Stafford Horne 
---
 hw/openrisc/openrisc_sim.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/openrisc/openrisc_sim.c b/hw/openrisc/openrisc_sim.c
index 6873124f74..35adce17ac 100644
--- a/hw/openrisc/openrisc_sim.c
+++ b/hw/openrisc/openrisc_sim.c
@@ -82,7 +82,7 @@ static const struct MemmapEntry {
 [OR1KSIM_DRAM] =  { 0x,  0 },
 [OR1KSIM_UART] =  { 0x9000,  0x100 },
 [OR1KSIM_ETHOC] = { 0x9200,  0x800 },
-[OR1KSIM_OMPIC] = { 0x9800, 16 },
+[OR1KSIM_OMPIC] = { 0x9800, OR1KSIM_CPUS_MAX * 8 },
 };
 
 static struct openrisc_boot_info {
@@ -418,7 +418,7 @@ static void openrisc_sim_init(MachineState *machine)
 
 if (smp_cpus > 1) {
 openrisc_sim_ompic_init(state, or1ksim_memmap[OR1KSIM_OMPIC].base,
-or1ksim_memmap[OR1KSIM_UART].size,
+or1ksim_memmap[OR1KSIM_OMPIC].size,
 smp_cpus, cpus, OR1KSIM_OMPIC_IRQ);
 }
 
-- 
2.31.1




[PULL 1/4] hw/openrisc: page-align FDT address

2022-05-14 Thread Stafford Horne
From: "Jason A. Donenfeld" 

The QEMU-provided FDT was only being recognized by the kernel when it
was used in conjunction with -initrd. Without it, the magic bytes
wouldn't be there and the kernel couldn't load it. This patch fixes the
issue by page aligning the provided FDT.

Cc: Stafford Horne 
Cc: Peter Maydell 
Signed-off-by: Jason A. Donenfeld 
Signed-off-by: Stafford Horne 
---
 hw/openrisc/openrisc_sim.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/openrisc/openrisc_sim.c b/hw/openrisc/openrisc_sim.c
index 8184caa60b..99b14940f4 100644
--- a/hw/openrisc/openrisc_sim.c
+++ b/hw/openrisc/openrisc_sim.c
@@ -356,7 +356,7 @@ static uint32_t openrisc_load_fdt(Or1ksimState *state, 
hwaddr load_start,
 }
 
 /* We put fdt right after the kernel and/or initrd. */
-fdt_addr = ROUND_UP(load_start, 4);
+fdt_addr = TARGET_PAGE_ALIGN(load_start);
 
 ret = fdt_pack(fdt);
 /* Should only fail if we've built a corrupted tree */
-- 
2.31.1




[PULL 0/4] OpenRISC fixes for QEMU 2022-05-15

2022-05-14 Thread Stafford Horne
The following changes since commit 2e3408b3cc7de4e87a9adafc8c19bfce3abec947:

  Merge tag 'misc-pull-request' of gitlab.com:marcandre.lureau/qemu into 
staging (2022-05-03 09:13:17 -0700)

are available in the Git repository at:

  https://github.com/stffrdhrn/qemu.git tags/or1k-pull-request-20220515

for you to fetch changes up to e8f0ab0cd674241cbab7231ce05ac1bfa0b4f5ed:

  target/openrisc: Do not reset delay slot flag on early tb exit (2022-05-15 
10:33:01 +0900)


OpenRISC Fixes for 7.0

 - A few or1ksim fixes and enhancements
 - A fix for OpenRISC tcg backend around delay slot handling


Jason A. Donenfeld (3):
  hw/openrisc: page-align FDT address
  hw/openrisc: support 4 serial ports in or1ksim
  hw/openrisc: use right OMPIC size variable

Stafford Horne (1):
  target/openrisc: Do not reset delay slot flag on early tb exit

 hw/openrisc/openrisc_sim.c | 28 +++-
 target/openrisc/cpu.c  | 11 +++
 2 files changed, 30 insertions(+), 9 deletions(-)

Jason A. Donenfeld (3):
  hw/openrisc: page-align FDT address
  hw/openrisc: support 4 serial ports in or1ksim
  hw/openrisc: use right OMPIC size variable

Stafford Horne (1):
  target/openrisc: Do not reset delay slot flag on early tb exit

 hw/openrisc/openrisc_sim.c | 28 +++-
 target/openrisc/cpu.c  | 11 +++
 2 files changed, 30 insertions(+), 9 deletions(-)

-- 
2.31.1




Re: [PATCH] target/openrisc: Do not reset delay slot flag on early tb exit

2022-05-12 Thread Stafford Horne
On Wed, May 11, 2022 at 07:11:20PM -0700, Richard Henderson wrote:
> On 5/11/22 15:34, Stafford Horne wrote:
> > In this case I don't see how the tb->flag would be updated, ooh, I guess it
> > would have been set earlier when the TB was generated.  Maybe that is what 
> > I am
> > missing.
> 
> Correct, it should be unchanged (and correct) from generation.

OK, its very clear now thanks.

With that said, I am still not convinced we need something like:

--- a/target/openrisc/cpu.c
+++ b/target/openrisc/cpu.c
@@ -37,6 +37,7 @@ static void openrisc_cpu_synchronize_from_tb(CPUState *cs,
 OpenRISCCPU *cpu = OPENRISC_CPU(cs);
 
 cpu->env.pc = tb->pc;
+cpu->env.dflag = (tb->flags & TB_FLAGS_DFLAG) ? 1 : 0;
 }


I will leave it out for now as I feel comfortable that the env.dflag will be
correct.  But if you think of something let me know.

-Stafford



Re: [PATCH] target/openrisc: Do not reset delay slot flag on early tb exit

2022-05-11 Thread Stafford Horne
On Wed, May 11, 2022 at 02:56:37PM -0700, Richard Henderson wrote:
> On 5/11/22 14:43, Stafford Horne wrote:
> > At this point how would tb->flags have the right value?  Would it always be 
> > set
> > correctly by `cpu_get_tb_cpu_state` in the `lookup_tb_ptr`call?
> 
> Well, it would be set by cpu_get_tb_cpu_state in cpu_exec, which is then
> passed to tb_gen_code.  If we go around a loop and look it up a second time,
> we'll find a tb with a matching set of flags.

Right, cpu_get_tb_cpu_state called in lookup_tb_ptr will not update tb->flags.

What you mention, that is for when we have to generate a new TB, the tb->flags
get set right before tb_gen_code.

But for the case where we exit the delay-slot TB due to a pending exception I
think the flow would go.

 TB chain:
 -> branch-TB : set env->flag 1
 -> delay-slot-TB : exit_tb due to condition
 Exit:
 -> return to cpu_tb_exec
   -> tcg_ops->synchronize_from_tb

In this case I don't see how the tb->flag would be updated, ooh, I guess it
would have been set earlier when the TB was generated.  Maybe that is what I am
missing.

-Stafford



Re: [PATCH] target/openrisc: Do not reset delay slot flag on early tb exit

2022-05-11 Thread Stafford Horne
On Wed, May 11, 2022 at 07:32:58AM -0700, Richard Henderson wrote:
> On 5/11/22 05:05, Stafford Horne wrote:
> > +static void openrisc_cpu_synchronize_from_tb(CPUState *cs,
> > + const TranslationBlock *tb)
> > +{
> > +OpenRISCCPU *cpu = OPENRISC_CPU(cs);
> > +
> > +cpu->env.pc = tb->pc;
> > +}
> 
> If mips is a guide, you'd want to set dflag based on
> 
>   tb->flags & TB_FLAGS_DFLAG
> 
> as well.   But I think openrisc is more careful to keep dflag up-to-date.

I was thinking that too so I left it out.

For example:

0xc01e3ffc:  l.bf  3
0xc01e4000:   l.ori r12, r0, 1

---

  c01e3ffc 
 movcond_i32 jmp_pc,sr_f,$0x0,$0xc01e4008,$0xc01e4004,ne  sync: 0  dead: 0 
1 2 3 4  pref=0x
 mov_i32 dflag,$0x1   sync: 0  dead: 0 1  pref=0x
 mov_i32 ppc,$0xc01e3ffc  sync: 0  dead: 0 1  pref=0x
 mov_i32 pc,$0xc01e4000   sync: 0  dead: 0 1  pref=0x
 call lookup_tb_ptr,$0x6,$1,tmp7,env  dead: 1  pref=none
 goto_ptr tmp7dead: 0
 set_label $L0  
 exit_tb $0x7f7b047f3b43

---

 ld_i32 tmp0,env,$0xfff0  pref=0x
 brcond_i32 tmp0,$0x0,lt,$L0  dead: 0

  c01e4000 0001
 mov_i32 r12,$0x1 sync: 0  dead: 0 1  pref=0x
 mov_i32 dflag,$0x0   sync: 0  dead: 0 1  pref=0x
 mov_i32 ppc,$0xc01e4000  sync: 0  dead: 0 1  pref=0x
 mov_i32 pc,jmp_pcsync: 0  dead: 0 1  pref=0x
 discard jmp_pc   pref=none
 call lookup_tb_ptr,$0x6,$1,tmp4,env  dead: 1  pref=none
 goto_ptr tmp4dead: 0
 set_label $L0  
 exit_tb $0x7f7b047f3c83


This is an example of a branch followed by a branch delay slot.  If we exit the
branch delay slot via `exit_tb $0x7f7b047f3c83`.  The `mov_i32 dflag,$0x1` 
instruction
would have run from `c01e3ffc` having env already updated.

At this point how would tb->flags have the right value?  Would it always be set
correctly by `cpu_get_tb_cpu_state` in the `lookup_tb_ptr`call?

-Stafford



Re: [PULL 3/4] Normalize header guard symbol definition

2022-05-11 Thread Stafford Horne
On Wed, May 11, 2022 at 04:59:21PM +0200, Markus Armbruster wrote:
> We commonly define the header guard symbol without an explicit value.
> Normalize the exceptions.
> 
> Done with scripts/clean-header-guards.pl.
> 
> Signed-off-by: Markus Armbruster 
> Message-Id: <20220506134911.2856099-4-arm...@redhat.com>
> Reviewed-by: Richard Henderson 
> ---
>  include/exec/memopidx.h   | 2 +-
>  include/tcg/tcg-ldst.h| 2 +-
>  target/alpha/cpu-param.h  | 2 +-
>  target/arm/cpu-param.h| 2 +-
>  target/cris/cpu-param.h   | 2 +-
>  target/hppa/cpu-param.h   | 2 +-
>  target/i386/cpu-param.h   | 2 +-
>  target/m68k/cpu-param.h   | 2 +-
>  target/microblaze/cpu-param.h | 2 +-
>  target/mips/cpu-param.h   | 2 +-
>  target/nios2/cpu-param.h  | 2 +-
>  target/openrisc/cpu-param.h   | 2 +-
>  target/ppc/cpu-param.h| 2 +-
>  target/riscv/cpu-param.h  | 2 +-
>  target/s390x/cpu-param.h  | 2 +-
>  target/sh4/cpu-param.h| 2 +-
>  target/sparc/cpu-param.h  | 2 +-
>  target/tricore/cpu-param.h| 2 +-
>  target/xtensa/cpu-param.h | 2 +-
>  tcg/tcg-internal.h| 2 +-
>  20 files changed, 20 insertions(+), 20 deletions(-)

I looked at this for the OpenRISC changes, but the whole patch looks ok to me.

Reviewed-by: Stafford Horne 



[PATCH] target/openrisc: Do not reset delay slot flag on early tb exit

2022-05-11 Thread Stafford Horne
This was found when running linux crypto algorithm selftests used by
wireguard.  We found that randomly the tests would fail.  We found
through investigation that a combination of a tick timer interrupt,
raised when executing a delay slot instruction at a page boundary caused
the issue.

This was caused when handling the TB_EXIT_REQUESTED case in cpu_tb_exec.
On OpenRISC, which doesn't implement synchronize_from_tb, set_pc was
being used as a fallback.  The OpenRISC set_pc implementation clears
dflag, which caused the exception handling logic to not account for the
delay slot.  This was the bug, because it meant when execution resumed
after the interrupt was handling it resumed in the wrong place.

Fix this by implementing synchronize_from_tb which simply updates pc,
and not clear the delay slot flag.

Reported-by: Jason A. Donenfeld 
Signed-off-by: Stafford Horne 
---
 target/openrisc/cpu.c | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/target/openrisc/cpu.c b/target/openrisc/cpu.c
index dfbafc5236..41d1b2a24a 100644
--- a/target/openrisc/cpu.c
+++ b/target/openrisc/cpu.c
@@ -21,6 +21,7 @@
 #include "qapi/error.h"
 #include "qemu/qemu-print.h"
 #include "cpu.h"
+#include "exec/exec-all.h"
 
 static void openrisc_cpu_set_pc(CPUState *cs, vaddr value)
 {
@@ -30,6 +31,15 @@ static void openrisc_cpu_set_pc(CPUState *cs, vaddr value)
 cpu->env.dflag = 0;
 }
 
+static void openrisc_cpu_synchronize_from_tb(CPUState *cs,
+ const TranslationBlock *tb)
+{
+OpenRISCCPU *cpu = OPENRISC_CPU(cs);
+
+cpu->env.pc = tb->pc;
+}
+
+
 static bool openrisc_cpu_has_work(CPUState *cs)
 {
 return cs->interrupt_request & (CPU_INTERRUPT_HARD |
@@ -186,6 +196,7 @@ static const struct SysemuCPUOps openrisc_sysemu_ops = {
 
 static const struct TCGCPUOps openrisc_tcg_ops = {
 .initialize = openrisc_translate_init,
+.synchronize_from_tb = openrisc_cpu_synchronize_from_tb,
 
 #ifndef CONFIG_USER_ONLY
 .tlb_fill = openrisc_cpu_tlb_fill,
-- 
2.31.1




Re: [PATCH v2] hw/openrisc: use right OMPIC size variable

2022-05-04 Thread Stafford Horne
On Wed, May 04, 2022 at 01:10:04PM +0200, Jason A. Donenfeld wrote:
> On Tue, May 3, 2022 at 10:22 PM Stafford Horne  wrote:
> >
> > On Tue, May 03, 2022 at 11:45:33AM +0200, Jason A. Donenfeld wrote:
> > > This appears to be a copy and paste error. The UART size was used
> > > instead of the much smaller OMPIC size. But actually that smaller OMPIC
> > > size is wrong too and doesn't allow the IPI to work in Linux. So set it
> > > to the old value.
> > >
> > > Signed-off-by: Jason A. Donenfeld 
> > > ---
> > >  hw/openrisc/openrisc_sim.c | 4 ++--
> > >  1 file changed, 2 insertions(+), 2 deletions(-)
> > >
> > > diff --git a/hw/openrisc/openrisc_sim.c b/hw/openrisc/openrisc_sim.c
> > > index 99b14940f4..3218db6656 100644
> > > --- a/hw/openrisc/openrisc_sim.c
> > > +++ b/hw/openrisc/openrisc_sim.c
> > > @@ -78,7 +78,7 @@ static const struct MemmapEntry {
> > >  [OR1KSIM_DRAM] =  { 0x,  0 },
> > >  [OR1KSIM_UART] =  { 0x9000,  0x100 },
> > >  [OR1KSIM_ETHOC] = { 0x9200,  0x800 },
> > > -[OR1KSIM_OMPIC] = { 0x9800, 16 },
> > > +[OR1KSIM_OMPIC] = { 0x9800,  0x100 },
> >
> > Right, I missed this as part of my series.  OMPIC will allocate 2 32-bit
> > registers per CPU.  I documented this here:
> >
> >   - 
> > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/irqchip/irq-ompic.c
> >
> > I think what we will want here is something like:
> >
> > [OR1KSIM_OMPIC] = { 0x9800, 8 * OR1KSIM_CPUS_MAX },
> 
> Do you want a v3 or are you going to fix it up yourself?

I'll fix it up.

-Stafford



Re: [PATCH v2] hw/openrisc: use right OMPIC size variable

2022-05-03 Thread Stafford Horne
On Tue, May 03, 2022 at 11:45:33AM +0200, Jason A. Donenfeld wrote:
> This appears to be a copy and paste error. The UART size was used
> instead of the much smaller OMPIC size. But actually that smaller OMPIC
> size is wrong too and doesn't allow the IPI to work in Linux. So set it
> to the old value.
> 
> Signed-off-by: Jason A. Donenfeld 
> ---
>  hw/openrisc/openrisc_sim.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/hw/openrisc/openrisc_sim.c b/hw/openrisc/openrisc_sim.c
> index 99b14940f4..3218db6656 100644
> --- a/hw/openrisc/openrisc_sim.c
> +++ b/hw/openrisc/openrisc_sim.c
> @@ -78,7 +78,7 @@ static const struct MemmapEntry {
>  [OR1KSIM_DRAM] =  { 0x,  0 },
>  [OR1KSIM_UART] =  { 0x9000,  0x100 },
>  [OR1KSIM_ETHOC] = { 0x9200,  0x800 },
> -[OR1KSIM_OMPIC] = { 0x9800, 16 },
> +[OR1KSIM_OMPIC] = { 0x9800,  0x100 },

Right, I missed this as part of my series.  OMPIC will allocate 2 32-bit
registers per CPU.  I documented this here:

  - 
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/irqchip/irq-ompic.c

I think what we will want here is something like:

[OR1KSIM_OMPIC] = { 0x9800, 8 * OR1KSIM_CPUS_MAX },

>  };
>  
>  static struct openrisc_boot_info {
> @@ -410,7 +410,7 @@ static void openrisc_sim_init(MachineState *machine)
>  
>  if (smp_cpus > 1) {
>  openrisc_sim_ompic_init(state, or1ksim_memmap[OR1KSIM_OMPIC].base,
> -or1ksim_memmap[OR1KSIM_UART].size,
> +or1ksim_memmap[OR1KSIM_OMPIC].size,
>  smp_cpus, cpus, OR1KSIM_OMPIC_IRQ);
>  }
>  
> -- 
> 2.35.1
> 



  1   2   3   4   5   >