diff mbox series

[1/1] riscv: riscv_get_time() implementation for SMODE

Message ID 20200814174515.14383-1-xypron.glpk@gmx.de
State Rejected, archived
Delegated to: Andes
Headers show
Series [1/1] riscv: riscv_get_time() implementation for SMODE | expand

Commit Message

Heinrich Schuchardt Aug. 14, 2020, 5:45 p.m. UTC
On the Kendryte K210 OpenBSI cannot emulate the rdtime instruction. So we
have to use the Sifive CLINT driver to provide riscv_get_time() in SMODE.

Adjust Kconfig and Makefile to allow compiling the Sifive CLINT driver in
SMODE.

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
---
 arch/riscv/Kconfig                   | 16 +++++++++++-----
 arch/riscv/cpu/fu540/Kconfig         |  3 ++-
 arch/riscv/cpu/generic/Kconfig       |  3 ++-
 arch/riscv/include/asm/global_data.h |  2 +-
 arch/riscv/lib/Makefile              |  2 +-
 5 files changed, 17 insertions(+), 9 deletions(-)

--
2.28.0

Comments

Anup Patel Aug. 14, 2020, 5:52 p.m. UTC | #1
On Fri, Aug 14, 2020 at 11:15 PM Heinrich Schuchardt <xypron.glpk@gmx.de> wrote:
>
> On the Kendryte K210 OpenBSI cannot emulate the rdtime instruction. So we
> have to use the Sifive CLINT driver to provide riscv_get_time() in SMODE.

Can you elaborate why ?

The rdtime instruction should generate an illegal instruction fault which
OpenSBI will emulate.

Regards,
Anup

>
> Adjust Kconfig and Makefile to allow compiling the Sifive CLINT driver in
> SMODE.
>
> Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
> ---
>  arch/riscv/Kconfig                   | 16 +++++++++++-----
>  arch/riscv/cpu/fu540/Kconfig         |  3 ++-
>  arch/riscv/cpu/generic/Kconfig       |  3 ++-
>  arch/riscv/include/asm/global_data.h |  2 +-
>  arch/riscv/lib/Makefile              |  2 +-
>  5 files changed, 17 insertions(+), 9 deletions(-)
>
> diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
> index 009a545fcf..96c386225b 100644
> --- a/arch/riscv/Kconfig
> +++ b/arch/riscv/Kconfig
> @@ -153,12 +153,18 @@ config 64BIT
>         bool
>
>  config SIFIVE_CLINT
> -       bool
> -       depends on RISCV_MMODE || SPL_RISCV_MMODE
> +       bool "SiFive's Core Local Interruptor (CLINT) driver"
>         select REGMAP
>         select SYSCON
> -       select SPL_REGMAP if SPL
> -       select SPL_SYSCON if SPL
> +       help
> +         The SiFive CLINT block holds memory-mapped control and status registers
> +         associated with software and timer interrupts.
> +
> +config SPL_SIFIVE_CLINT
> +       bool "SiFive's Core Local Interruptor (CLINT) driver in SPL"
> +       depends on SPL
> +       select SPL_REGMAP
> +       select SPL_SYSCON
>         help
>           The SiFive CLINT block holds memory-mapped control and status registers
>           associated with software and timer interrupts.
> @@ -186,7 +192,7 @@ config ANDES_PLMT
>           associated with timer tick.
>
>  config RISCV_RDTIME
> -       bool
> +       bool "Timer API via rdtime instruction"
>         default y if RISCV_SMODE || SPL_RISCV_SMODE
>         help
>           The provides the riscv_get_time() API that is implemented using the
> diff --git a/arch/riscv/cpu/fu540/Kconfig b/arch/riscv/cpu/fu540/Kconfig
> index 2dcad8e27f..8b2c83039f 100644
> --- a/arch/riscv/cpu/fu540/Kconfig
> +++ b/arch/riscv/cpu/fu540/Kconfig
> @@ -8,7 +8,8 @@ config SIFIVE_FU540
>         imply CPU
>         imply CPU_RISCV
>         imply RISCV_TIMER
> -       imply SIFIVE_CLINT if (RISCV_MMODE || SPL_RISCV_MMODE)
> +       imply SIFIVE_CLINT if RISCV_MMODE
> +       imply SPL_SIFIVE_CLINT if SPL_RISCV_MMODE
>         imply CMD_CPU
>         imply SPL_CPU_SUPPORT
>         imply SPL_OPENSBI
> diff --git a/arch/riscv/cpu/generic/Kconfig b/arch/riscv/cpu/generic/Kconfig
> index b2cb155d6d..62fcadd710 100644
> --- a/arch/riscv/cpu/generic/Kconfig
> +++ b/arch/riscv/cpu/generic/Kconfig
> @@ -8,7 +8,8 @@ config GENERIC_RISCV
>         imply CPU
>         imply CPU_RISCV
>         imply RISCV_TIMER
> -       imply SIFIVE_CLINT if (RISCV_MMODE || SPL_RISCV_MMODE)
> +       imply SIFIVE_CLINT if RISCV_MMODE
> +       imply SPL_SIFIVE_CLINT if SPL_RISCV_MMODE
>         imply CMD_CPU
>         imply SPL_CPU_SUPPORT
>         imply SPL_OPENSBI
> diff --git a/arch/riscv/include/asm/global_data.h b/arch/riscv/include/asm/global_data.h
> index 2eb14815bc..b89b469d41 100644
> --- a/arch/riscv/include/asm/global_data.h
> +++ b/arch/riscv/include/asm/global_data.h
> @@ -18,7 +18,7 @@
>  struct arch_global_data {
>         long boot_hart;         /* boot hart id */
>         phys_addr_t firmware_fdt_addr;
> -#ifdef CONFIG_SIFIVE_CLINT
> +#if CONFIG_IS_ENABLED(SIFIVE_CLINT)
>         void __iomem *clint;    /* clint base address */
>  #endif
>  #ifdef CONFIG_ANDES_PLIC
> diff --git a/arch/riscv/lib/Makefile b/arch/riscv/lib/Makefile
> index 6c503ff2b2..861d7b489f 100644
> --- a/arch/riscv/lib/Makefile
> +++ b/arch/riscv/lib/Makefile
> @@ -10,8 +10,8 @@ obj-$(CONFIG_CMD_BOOTM) += bootm.o
>  obj-$(CONFIG_CMD_BOOTI) += bootm.o image.o
>  obj-$(CONFIG_CMD_GO) += boot.o
>  obj-y  += cache.o
> +obj-$(CONFIG_$(SPL_)SIFIVE_CLINT) += sifive_clint.o
>  ifeq ($(CONFIG_$(SPL_)RISCV_MMODE),y)
> -obj-$(CONFIG_SIFIVE_CLINT) += sifive_clint.o
>  obj-$(CONFIG_ANDES_PLIC) += andes_plic.o
>  obj-$(CONFIG_ANDES_PLMT) += andes_plmt.o
>  else
> --
> 2.28.0
>
Heinrich Schuchardt Aug. 14, 2020, 5:59 p.m. UTC | #2
On 14.08.20 19:52, Anup Patel wrote:
> On Fri, Aug 14, 2020 at 11:15 PM Heinrich Schuchardt <xypron.glpk@gmx.de> wrote:
>>
>> On the Kendryte K210 OpenBSI cannot emulate the rdtime instruction. So we
>> have to use the Sifive CLINT driver to provide riscv_get_time() in SMODE.
>
> Can you elaborate why ?
>
> The rdtime instruction should generate an illegal instruction fault which
> OpenSBI will emulate.

The RISC-V Instruction Set Manual Volume II Privileged architectur 1.11
has incompatible changes relative to version 1.9.1

mtval on the Kendryte K210 delivers the bad virtual address and not the
instruction:

lib/sbi/sbi_illegal_insn.c(123) sbi_illegal_insn_handler:
insn 0x4114121602, epc 0x8058c168.

The illegal instruction being
c01027f3    rdtime a5

In the long run it may make sense to provide backwards compatibility in
OpenSBI.

Without this patch I observe a crash in the loady command. So I cannot
load a file over the UART.

Best regards

Heinrich

>
> Regards,
> Anup
>
>>
>> Adjust Kconfig and Makefile to allow compiling the Sifive CLINT driver in
>> SMODE.
>>
>> Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
>> ---
>>  arch/riscv/Kconfig                   | 16 +++++++++++-----
>>  arch/riscv/cpu/fu540/Kconfig         |  3 ++-
>>  arch/riscv/cpu/generic/Kconfig       |  3 ++-
>>  arch/riscv/include/asm/global_data.h |  2 +-
>>  arch/riscv/lib/Makefile              |  2 +-
>>  5 files changed, 17 insertions(+), 9 deletions(-)
>>
>> diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
>> index 009a545fcf..96c386225b 100644
>> --- a/arch/riscv/Kconfig
>> +++ b/arch/riscv/Kconfig
>> @@ -153,12 +153,18 @@ config 64BIT
>>         bool
>>
>>  config SIFIVE_CLINT
>> -       bool
>> -       depends on RISCV_MMODE || SPL_RISCV_MMODE
>> +       bool "SiFive's Core Local Interruptor (CLINT) driver"
>>         select REGMAP
>>         select SYSCON
>> -       select SPL_REGMAP if SPL
>> -       select SPL_SYSCON if SPL
>> +       help
>> +         The SiFive CLINT block holds memory-mapped control and status registers
>> +         associated with software and timer interrupts.
>> +
>> +config SPL_SIFIVE_CLINT
>> +       bool "SiFive's Core Local Interruptor (CLINT) driver in SPL"
>> +       depends on SPL
>> +       select SPL_REGMAP
>> +       select SPL_SYSCON
>>         help
>>           The SiFive CLINT block holds memory-mapped control and status registers
>>           associated with software and timer interrupts.
>> @@ -186,7 +192,7 @@ config ANDES_PLMT
>>           associated with timer tick.
>>
>>  config RISCV_RDTIME
>> -       bool
>> +       bool "Timer API via rdtime instruction"
>>         default y if RISCV_SMODE || SPL_RISCV_SMODE
>>         help
>>           The provides the riscv_get_time() API that is implemented using the
>> diff --git a/arch/riscv/cpu/fu540/Kconfig b/arch/riscv/cpu/fu540/Kconfig
>> index 2dcad8e27f..8b2c83039f 100644
>> --- a/arch/riscv/cpu/fu540/Kconfig
>> +++ b/arch/riscv/cpu/fu540/Kconfig
>> @@ -8,7 +8,8 @@ config SIFIVE_FU540
>>         imply CPU
>>         imply CPU_RISCV
>>         imply RISCV_TIMER
>> -       imply SIFIVE_CLINT if (RISCV_MMODE || SPL_RISCV_MMODE)
>> +       imply SIFIVE_CLINT if RISCV_MMODE
>> +       imply SPL_SIFIVE_CLINT if SPL_RISCV_MMODE
>>         imply CMD_CPU
>>         imply SPL_CPU_SUPPORT
>>         imply SPL_OPENSBI
>> diff --git a/arch/riscv/cpu/generic/Kconfig b/arch/riscv/cpu/generic/Kconfig
>> index b2cb155d6d..62fcadd710 100644
>> --- a/arch/riscv/cpu/generic/Kconfig
>> +++ b/arch/riscv/cpu/generic/Kconfig
>> @@ -8,7 +8,8 @@ config GENERIC_RISCV
>>         imply CPU
>>         imply CPU_RISCV
>>         imply RISCV_TIMER
>> -       imply SIFIVE_CLINT if (RISCV_MMODE || SPL_RISCV_MMODE)
>> +       imply SIFIVE_CLINT if RISCV_MMODE
>> +       imply SPL_SIFIVE_CLINT if SPL_RISCV_MMODE
>>         imply CMD_CPU
>>         imply SPL_CPU_SUPPORT
>>         imply SPL_OPENSBI
>> diff --git a/arch/riscv/include/asm/global_data.h b/arch/riscv/include/asm/global_data.h
>> index 2eb14815bc..b89b469d41 100644
>> --- a/arch/riscv/include/asm/global_data.h
>> +++ b/arch/riscv/include/asm/global_data.h
>> @@ -18,7 +18,7 @@
>>  struct arch_global_data {
>>         long boot_hart;         /* boot hart id */
>>         phys_addr_t firmware_fdt_addr;
>> -#ifdef CONFIG_SIFIVE_CLINT
>> +#if CONFIG_IS_ENABLED(SIFIVE_CLINT)
>>         void __iomem *clint;    /* clint base address */
>>  #endif
>>  #ifdef CONFIG_ANDES_PLIC
>> diff --git a/arch/riscv/lib/Makefile b/arch/riscv/lib/Makefile
>> index 6c503ff2b2..861d7b489f 100644
>> --- a/arch/riscv/lib/Makefile
>> +++ b/arch/riscv/lib/Makefile
>> @@ -10,8 +10,8 @@ obj-$(CONFIG_CMD_BOOTM) += bootm.o
>>  obj-$(CONFIG_CMD_BOOTI) += bootm.o image.o
>>  obj-$(CONFIG_CMD_GO) += boot.o
>>  obj-y  += cache.o
>> +obj-$(CONFIG_$(SPL_)SIFIVE_CLINT) += sifive_clint.o
>>  ifeq ($(CONFIG_$(SPL_)RISCV_MMODE),y)
>> -obj-$(CONFIG_SIFIVE_CLINT) += sifive_clint.o
>>  obj-$(CONFIG_ANDES_PLIC) += andes_plic.o
>>  obj-$(CONFIG_ANDES_PLMT) += andes_plmt.o
>>  else
>> --
>> 2.28.0
>>
Anup Patel Aug. 14, 2020, 6:38 p.m. UTC | #3
On Fri, Aug 14, 2020 at 11:35 PM Heinrich Schuchardt <xypron.glpk@gmx.de> wrote:
>
> On 14.08.20 19:52, Anup Patel wrote:
> > On Fri, Aug 14, 2020 at 11:15 PM Heinrich Schuchardt <xypron.glpk@gmx.de> wrote:
> >>
> >> On the Kendryte K210 OpenBSI cannot emulate the rdtime instruction. So we
> >> have to use the Sifive CLINT driver to provide riscv_get_time() in SMODE.
> >
> > Can you elaborate why ?
> >
> > The rdtime instruction should generate an illegal instruction fault which
> > OpenSBI will emulate.
>
> The RISC-V Instruction Set Manual Volume II Privileged architectur 1.11
> has incompatible changes relative to version 1.9.1
>
> mtval on the Kendryte K210 delivers the bad virtual address and not the
> instruction:

Ahh, I see. The MTVAL CSR is actually legacy MBADADDR CSR and this
CSR.

The S-mode software always has working rdtime instruction for all
RISC-V systems. If HW does not implement TIME CSR then OpenSBI
emulates it. Please don't break this convention for U-Boot S-mode
because we do have RISC-V systems where TIME CSR is implemeted
in HW so this will patch will break U-Boot S-mode system because
on those system we are supposed to use TIME CSR from S-mode.

>
> lib/sbi/sbi_illegal_insn.c(123) sbi_illegal_insn_handler:
> insn 0x4114121602, epc 0x8058c168.
>
> The illegal instruction being
> c01027f3    rdtime a5
>
> In the long run it may make sense to provide backwards compatibility in
> OpenSBI.

Yes, let's try to explore possible fixes in OpenSBI.

Instead of this patch, try the following change in OpenSBI ...

diff --git a/lib/sbi/sbi_illegal_insn.c b/lib/sbi/sbi_illegal_insn.c
index 0e5523f..c8f2e4a 100644
--- a/lib/sbi/sbi_illegal_insn.c
+++ b/lib/sbi/sbi_illegal_insn.c
@@ -119,12 +119,10 @@ int sbi_illegal_insn_handler(ulong insn, struct
sbi_trap_regs *regs)
        struct sbi_trap_info uptrap;

        if (unlikely((insn & 3) != 3)) {
-               if (insn == 0) {
-                       insn = sbi_get_insn(regs->mepc, &uptrap);
-                       if (uptrap.cause) {
-                               uptrap.epc = regs->mepc;
-                               return sbi_trap_redirect(regs, &uptrap);
-                       }
+               insn = sbi_get_insn(regs->mepc, &uptrap);
+               if (uptrap.cause) {
+                       uptrap.epc = regs->mepc;
+                       return sbi_trap_redirect(regs, &uptrap);
                }
                if ((insn & 3) != 3)
                        return truly_illegal_insn(insn, regs);

Regards,
Anup

>
> Without this patch I observe a crash in the loady command. So I cannot
> load a file over the UART.
>
> Best regards
>
> Heinrich
>
> >
> > Regards,
> > Anup
> >
> >>
> >> Adjust Kconfig and Makefile to allow compiling the Sifive CLINT driver in
> >> SMODE.
> >>
> >> Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
> >> ---
> >>  arch/riscv/Kconfig                   | 16 +++++++++++-----
> >>  arch/riscv/cpu/fu540/Kconfig         |  3 ++-
> >>  arch/riscv/cpu/generic/Kconfig       |  3 ++-
> >>  arch/riscv/include/asm/global_data.h |  2 +-
> >>  arch/riscv/lib/Makefile              |  2 +-
> >>  5 files changed, 17 insertions(+), 9 deletions(-)
> >>
> >> diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
> >> index 009a545fcf..96c386225b 100644
> >> --- a/arch/riscv/Kconfig
> >> +++ b/arch/riscv/Kconfig
> >> @@ -153,12 +153,18 @@ config 64BIT
> >>         bool
> >>
> >>  config SIFIVE_CLINT
> >> -       bool
> >> -       depends on RISCV_MMODE || SPL_RISCV_MMODE
> >> +       bool "SiFive's Core Local Interruptor (CLINT) driver"
> >>         select REGMAP
> >>         select SYSCON
> >> -       select SPL_REGMAP if SPL
> >> -       select SPL_SYSCON if SPL
> >> +       help
> >> +         The SiFive CLINT block holds memory-mapped control and status registers
> >> +         associated with software and timer interrupts.
> >> +
> >> +config SPL_SIFIVE_CLINT
> >> +       bool "SiFive's Core Local Interruptor (CLINT) driver in SPL"
> >> +       depends on SPL
> >> +       select SPL_REGMAP
> >> +       select SPL_SYSCON
> >>         help
> >>           The SiFive CLINT block holds memory-mapped control and status registers
> >>           associated with software and timer interrupts.
> >> @@ -186,7 +192,7 @@ config ANDES_PLMT
> >>           associated with timer tick.
> >>
> >>  config RISCV_RDTIME
> >> -       bool
> >> +       bool "Timer API via rdtime instruction"
> >>         default y if RISCV_SMODE || SPL_RISCV_SMODE
> >>         help
> >>           The provides the riscv_get_time() API that is implemented using the
> >> diff --git a/arch/riscv/cpu/fu540/Kconfig b/arch/riscv/cpu/fu540/Kconfig
> >> index 2dcad8e27f..8b2c83039f 100644
> >> --- a/arch/riscv/cpu/fu540/Kconfig
> >> +++ b/arch/riscv/cpu/fu540/Kconfig
> >> @@ -8,7 +8,8 @@ config SIFIVE_FU540
> >>         imply CPU
> >>         imply CPU_RISCV
> >>         imply RISCV_TIMER
> >> -       imply SIFIVE_CLINT if (RISCV_MMODE || SPL_RISCV_MMODE)
> >> +       imply SIFIVE_CLINT if RISCV_MMODE
> >> +       imply SPL_SIFIVE_CLINT if SPL_RISCV_MMODE
> >>         imply CMD_CPU
> >>         imply SPL_CPU_SUPPORT
> >>         imply SPL_OPENSBI
> >> diff --git a/arch/riscv/cpu/generic/Kconfig b/arch/riscv/cpu/generic/Kconfig
> >> index b2cb155d6d..62fcadd710 100644
> >> --- a/arch/riscv/cpu/generic/Kconfig
> >> +++ b/arch/riscv/cpu/generic/Kconfig
> >> @@ -8,7 +8,8 @@ config GENERIC_RISCV
> >>         imply CPU
> >>         imply CPU_RISCV
> >>         imply RISCV_TIMER
> >> -       imply SIFIVE_CLINT if (RISCV_MMODE || SPL_RISCV_MMODE)
> >> +       imply SIFIVE_CLINT if RISCV_MMODE
> >> +       imply SPL_SIFIVE_CLINT if SPL_RISCV_MMODE
> >>         imply CMD_CPU
> >>         imply SPL_CPU_SUPPORT
> >>         imply SPL_OPENSBI
> >> diff --git a/arch/riscv/include/asm/global_data.h b/arch/riscv/include/asm/global_data.h
> >> index 2eb14815bc..b89b469d41 100644
> >> --- a/arch/riscv/include/asm/global_data.h
> >> +++ b/arch/riscv/include/asm/global_data.h
> >> @@ -18,7 +18,7 @@
> >>  struct arch_global_data {
> >>         long boot_hart;         /* boot hart id */
> >>         phys_addr_t firmware_fdt_addr;
> >> -#ifdef CONFIG_SIFIVE_CLINT
> >> +#if CONFIG_IS_ENABLED(SIFIVE_CLINT)
> >>         void __iomem *clint;    /* clint base address */
> >>  #endif
> >>  #ifdef CONFIG_ANDES_PLIC
> >> diff --git a/arch/riscv/lib/Makefile b/arch/riscv/lib/Makefile
> >> index 6c503ff2b2..861d7b489f 100644
> >> --- a/arch/riscv/lib/Makefile
> >> +++ b/arch/riscv/lib/Makefile
> >> @@ -10,8 +10,8 @@ obj-$(CONFIG_CMD_BOOTM) += bootm.o
> >>  obj-$(CONFIG_CMD_BOOTI) += bootm.o image.o
> >>  obj-$(CONFIG_CMD_GO) += boot.o
> >>  obj-y  += cache.o
> >> +obj-$(CONFIG_$(SPL_)SIFIVE_CLINT) += sifive_clint.o
> >>  ifeq ($(CONFIG_$(SPL_)RISCV_MMODE),y)
> >> -obj-$(CONFIG_SIFIVE_CLINT) += sifive_clint.o
> >>  obj-$(CONFIG_ANDES_PLIC) += andes_plic.o
> >>  obj-$(CONFIG_ANDES_PLMT) += andes_plmt.o
> >>  else
> >> --
> >> 2.28.0
> >>
>
Heinrich Schuchardt Aug. 14, 2020, 7:26 p.m. UTC | #4
On 8/14/20 8:38 PM, Anup Patel wrote:
> On Fri, Aug 14, 2020 at 11:35 PM Heinrich Schuchardt <xypron.glpk@gmx.de> wrote:
>>
>> On 14.08.20 19:52, Anup Patel wrote:
>>> On Fri, Aug 14, 2020 at 11:15 PM Heinrich Schuchardt <xypron.glpk@gmx.de> wrote:
>>>>
>>>> On the Kendryte K210 OpenBSI cannot emulate the rdtime instruction. So we
>>>> have to use the Sifive CLINT driver to provide riscv_get_time() in SMODE.
>>>
>>> Can you elaborate why ?
>>>
>>> The rdtime instruction should generate an illegal instruction fault which
>>> OpenSBI will emulate.
>>
>> The RISC-V Instruction Set Manual Volume II Privileged architectur 1.11
>> has incompatible changes relative to version 1.9.1
>>
>> mtval on the Kendryte K210 delivers the bad virtual address and not the
>> instruction:
>
> Ahh, I see. The MTVAL CSR is actually legacy MBADADDR CSR and this
> CSR.
>
> The S-mode software always has working rdtime instruction for all
> RISC-V systems. If HW does not implement TIME CSR then OpenSBI
> emulates it. Please don't break this convention for U-Boot S-mode
> because we do have RISC-V systems where TIME CSR is implemeted
> in HW so this will patch will break U-Boot S-mode system because
> on those system we are supposed to use TIME CSR from S-mode.

This patch does not change anything for existing systems. It only allows
me to customize U-Boot for the K210 differently. I understand that
fixing OpenSBI is a better approach.

>
>>
>> lib/sbi/sbi_illegal_insn.c(123) sbi_illegal_insn_handler:
>> insn 0x4114121602, epc 0x8058c168.
>>
>> The illegal instruction being
>> c01027f3    rdtime a5
>>
>> In the long run it may make sense to provide backwards compatibility in
>> OpenSBI.
>
> Yes, let's try to explore possible fixes in OpenSBI.
>
> Instead of this patch, try the following change in OpenSBI ...
>
> diff --git a/lib/sbi/sbi_illegal_insn.c b/lib/sbi/sbi_illegal_insn.c
> index 0e5523f..c8f2e4a 100644
> --- a/lib/sbi/sbi_illegal_insn.c
> +++ b/lib/sbi/sbi_illegal_insn.c
> @@ -119,12 +119,10 @@ int sbi_illegal_insn_handler(ulong insn, struct
> sbi_trap_regs *regs)
>         struct sbi_trap_info uptrap;
>
>         if (unlikely((insn & 3) != 3)) {

Why do put sbi_get_insn() behind this if and not before it?

> -               if (insn == 0) {
> -                       insn = sbi_get_insn(regs->mepc, &uptrap);
> -                       if (uptrap.cause) {
> -                               uptrap.epc = regs->mepc;
> -                               return sbi_trap_redirect(regs, &uptrap);
> -                       }
> +               insn = sbi_get_insn(regs->mepc, &uptrap);
> +               if (uptrap.cause) {
> +                       uptrap.epc = regs->mepc;
> +                       return sbi_trap_redirect(regs, &uptrap);
>                 }
>                 if ((insn & 3) != 3)
>                         return truly_illegal_insn(insn, regs);
>

For this illegal instruction exception the fix works. But I think the
change is in the wrong place.

We have to cover all exceptions, e.g. unaligned access. So we better
should determine the instruction in sbi_trap_handler().

Best regards

Heinrich

> Regards,
> Anup
>
>>
>> Without this patch I observe a crash in the loady command. So I cannot
>> load a file over the UART.
>>
>> Best regards
>>
>> Heinrich
>>
>>>
>>> Regards,
>>> Anup
>>>
Anup Patel Aug. 15, 2020, 2:06 p.m. UTC | #5
On Sat, Aug 15, 2020 at 12:57 AM Heinrich Schuchardt <xypron.glpk@gmx.de> wrote:
>
> On 8/14/20 8:38 PM, Anup Patel wrote:
> > On Fri, Aug 14, 2020 at 11:35 PM Heinrich Schuchardt <xypron.glpk@gmx.de> wrote:
> >>
> >> On 14.08.20 19:52, Anup Patel wrote:
> >>> On Fri, Aug 14, 2020 at 11:15 PM Heinrich Schuchardt <xypron.glpk@gmx.de> wrote:
> >>>>
> >>>> On the Kendryte K210 OpenBSI cannot emulate the rdtime instruction. So we
> >>>> have to use the Sifive CLINT driver to provide riscv_get_time() in SMODE.
> >>>
> >>> Can you elaborate why ?
> >>>
> >>> The rdtime instruction should generate an illegal instruction fault which
> >>> OpenSBI will emulate.
> >>
> >> The RISC-V Instruction Set Manual Volume II Privileged architectur 1.11
> >> has incompatible changes relative to version 1.9.1
> >>
> >> mtval on the Kendryte K210 delivers the bad virtual address and not the
> >> instruction:
> >
> > Ahh, I see. The MTVAL CSR is actually legacy MBADADDR CSR and this
> > CSR.
> >
> > The S-mode software always has working rdtime instruction for all
> > RISC-V systems. If HW does not implement TIME CSR then OpenSBI
> > emulates it. Please don't break this convention for U-Boot S-mode
> > because we do have RISC-V systems where TIME CSR is implemeted
> > in HW so this will patch will break U-Boot S-mode system because
> > on those system we are supposed to use TIME CSR from S-mode.
>
> This patch does not change anything for existing systems. It only allows
> me to customize U-Boot for the K210 differently. I understand that
> fixing OpenSBI is a better approach.

Currently, on most RISC-V systems the CLINT timer interrupts and IPI
interrupts are hard-wired to M-mode timer and software interrupt lines.
In other words, the CLINT is integrated as M-mode only device on most
RISC-V systems.

Due to above reason, CLINT driver is M-mode only driver for Linux kernel

The Linux S-mode will use:
1. TIME CSR as free running counter
2. SBI calls for timer interrupts
3. SBI calls for injecting IPIs

For #1 above, the M-mode firmware will trap-n-emulate TIME CSR
for S-mode if HW does not implement TIME CSR.

Based on above mentioned convention, the U-Boot CLINT driver
should be M-mode only and U-Boot S-mode should use TIME CSR
as a free running counter.

>
> >
> >>
> >> lib/sbi/sbi_illegal_insn.c(123) sbi_illegal_insn_handler:
> >> insn 0x4114121602, epc 0x8058c168.
> >>
> >> The illegal instruction being
> >> c01027f3    rdtime a5
> >>
> >> In the long run it may make sense to provide backwards compatibility in
> >> OpenSBI.
> >
> > Yes, let's try to explore possible fixes in OpenSBI.
> >
> > Instead of this patch, try the following change in OpenSBI ...
> >
> > diff --git a/lib/sbi/sbi_illegal_insn.c b/lib/sbi/sbi_illegal_insn.c
> > index 0e5523f..c8f2e4a 100644
> > --- a/lib/sbi/sbi_illegal_insn.c
> > +++ b/lib/sbi/sbi_illegal_insn.c
> > @@ -119,12 +119,10 @@ int sbi_illegal_insn_handler(ulong insn, struct
> > sbi_trap_regs *regs)
> >         struct sbi_trap_info uptrap;
> >
> >         if (unlikely((insn & 3) != 3)) {
>
> Why do put sbi_get_insn() behind this if and not before it?

Currently, OpenSBI only deals with 32bit (or longer) illegal
instructions. If we see insn == 0 OR insn is 16bit then we
double-check instruction encoding using unprivileged access.

The PC in RISC-V is always 2-byte aligned address so if MTVAL
has fault instruction address instead of instruction encoding then
"(insn & 3) != 3" will be TRUE and we will be forced to double-check.
The "insn == 0" check below is causing problem RISC-V v1.9 spec
(i.e. MTVAL having instruction address) and it is totally harmless to
remove the "insn == 0" check for RISC-V v1.10 (or higher) hence
my suggestion to remove the check.

>
> > -               if (insn == 0) {
> > -                       insn = sbi_get_insn(regs->mepc, &uptrap);
> > -                       if (uptrap.cause) {
> > -                               uptrap.epc = regs->mepc;
> > -                               return sbi_trap_redirect(regs, &uptrap);
> > -                       }
> > +               insn = sbi_get_insn(regs->mepc, &uptrap);
> > +               if (uptrap.cause) {
> > +                       uptrap.epc = regs->mepc;
> > +                       return sbi_trap_redirect(regs, &uptrap);
> >                 }
> >                 if ((insn & 3) != 3)
> >                         return truly_illegal_insn(insn, regs);
> >
>
> For this illegal instruction exception the fix works. But I think the
> change is in the wrong place.
>
> We have to cover all exceptions, e.g. unaligned access. So we better
> should determine the instruction in sbi_trap_handler().

That's incorrect.

For RISC-V v1.10 (or higher), the MTVAL contains:
1. Instruction encoding for illegal instruction trap
2. Fault address for unaligned traps, page faults, and access faults

For RISC-V v1.10 (or higher), the unaligned trap does not provide
fault instruction encoding so we end-up doing unpriv access.

Base on above, it's best to work-around your issue in
sbi_illegal_insn_handler() instead of sbi_trap_handler()

Regards,
Anup

>
> Best regards
>
> Heinrich
>
> > Regards,
> > Anup
> >
> >>
> >> Without this patch I observe a crash in the loady command. So I cannot
> >> load a file over the UART.
> >>
> >> Best regards
> >>
> >> Heinrich
> >>
> >>>
> >>> Regards,
> >>> Anup
> >>>
Heinrich Schuchardt Aug. 15, 2020, 3:06 p.m. UTC | #6
Am 15. August 2020 16:06:41 MESZ schrieb Anup Patel <anup@brainfault.org>:
>On Sat, Aug 15, 2020 at 12:57 AM Heinrich Schuchardt
><xypron.glpk@gmx.de> wrote:
>>
>> On 8/14/20 8:38 PM, Anup Patel wrote:
>> > On Fri, Aug 14, 2020 at 11:35 PM Heinrich Schuchardt
><xypron.glpk@gmx.de> wrote:
>> >>
>> >> On 14.08.20 19:52, Anup Patel wrote:
>> >>> On Fri, Aug 14, 2020 at 11:15 PM Heinrich Schuchardt
><xypron.glpk@gmx.de> wrote:
>> >>>>
>> >>>> On the Kendryte K210 OpenBSI cannot emulate the rdtime
>instruction. So we
>> >>>> have to use the Sifive CLINT driver to provide riscv_get_time()
>in SMODE.
>> >>>
>> >>> Can you elaborate why ?
>> >>>
>> >>> The rdtime instruction should generate an illegal instruction
>fault which
>> >>> OpenSBI will emulate.
>> >>
>> >> The RISC-V Instruction Set Manual Volume II Privileged architectur
>1.11
>> >> has incompatible changes relative to version 1.9.1
>> >>
>> >> mtval on the Kendryte K210 delivers the bad virtual address and
>not the
>> >> instruction:
>> >
>> > Ahh, I see. The MTVAL CSR is actually legacy MBADADDR CSR and this
>> > CSR.
>> >
>> > The S-mode software always has working rdtime instruction for all
>> > RISC-V systems. If HW does not implement TIME CSR then OpenSBI
>> > emulates it. Please don't break this convention for U-Boot S-mode
>> > because we do have RISC-V systems where TIME CSR is implemeted
>> > in HW so this will patch will break U-Boot S-mode system because
>> > on those system we are supposed to use TIME CSR from S-mode.
>>
>> This patch does not change anything for existing systems. It only
>allows
>> me to customize U-Boot for the K210 differently. I understand that
>> fixing OpenSBI is a better approach.
>
>Currently, on most RISC-V systems the CLINT timer interrupts and IPI
>interrupts are hard-wired to M-mode timer and software interrupt lines.
>In other words, the CLINT is integrated as M-mode only device on most
>RISC-V systems.
>
>Due to above reason, CLINT driver is M-mode only driver for Linux
>kernel
>
>The Linux S-mode will use:
>1. TIME CSR as free running counter
>2. SBI calls for timer interrupts
>3. SBI calls for injecting IPIs
>
>For #1 above, the M-mode firmware will trap-n-emulate TIME CSR
>for S-mode if HW does not implement TIME CSR.
>
>Based on above mentioned convention, the U-Boot CLINT driver
>should be M-mode only and U-Boot S-mode should use TIME CSR
>as a free running counter.
>
>>
>> >
>> >>
>> >> lib/sbi/sbi_illegal_insn.c(123) sbi_illegal_insn_handler:
>> >> insn 0x4114121602, epc 0x8058c168.
>> >>
>> >> The illegal instruction being
>> >> c01027f3    rdtime a5
>> >>
>> >> In the long run it may make sense to provide backwards
>compatibility in
>> >> OpenSBI.
>> >
>> > Yes, let's try to explore possible fixes in OpenSBI.
>> >
>> > Instead of this patch, try the following change in OpenSBI ...
>> >
>> > diff --git a/lib/sbi/sbi_illegal_insn.c
>b/lib/sbi/sbi_illegal_insn.c
>> > index 0e5523f..c8f2e4a 100644
>> > --- a/lib/sbi/sbi_illegal_insn.c
>> > +++ b/lib/sbi/sbi_illegal_insn.c
>> > @@ -119,12 +119,10 @@ int sbi_illegal_insn_handler(ulong insn,
>struct
>> > sbi_trap_regs *regs)
>> >         struct sbi_trap_info uptrap;
>> >
>> >         if (unlikely((insn & 3) != 3)) {
>>
>> Why do put sbi_get_insn() behind this if and not before it?
>
>Currently, OpenSBI only deals with 32bit (or longer) illegal
>instructions. If we see insn == 0 OR insn is 16bit then we
>double-check instruction encoding using unprivileged access.
>
>The PC in RISC-V is always 2-byte aligned address so if MTVAL
>has fault instruction address instead of instruction encoding then
>"(insn & 3) != 3" will be TRUE and we will be forced to double-check.
>The "insn == 0" check below is causing problem RISC-V v1.9 spec
>(i.e. MTVAL having instruction address) and it is totally harmless to
>remove the "insn == 0" check for RISC-V v1.10 (or higher) hence
>my suggestion to remove the check.
>

Thank you for your detailed explanation. Maybe you can add a comment to the code.

>>
>> > -               if (insn == 0) {
>> > -                       insn = sbi_get_insn(regs->mepc, &uptrap);
>> > -                       if (uptrap.cause) {
>> > -                               uptrap.epc = regs->mepc;
>> > -                               return sbi_trap_redirect(regs,
>&uptrap);
>> > -                       }
>> > +               insn = sbi_get_insn(regs->mepc, &uptrap);
>> > +               if (uptrap.cause) {
>> > +                       uptrap.epc = regs->mepc;
>> > +                       return sbi_trap_redirect(regs, &uptrap);
>> >                 }
>> >                 if ((insn & 3) != 3)
>> >                         return truly_illegal_insn(insn, regs);
>> >
>>
>> For this illegal instruction exception the fix works. But I think the
>> change is in the wrong place.
>>
>> We have to cover all exceptions, e.g. unaligned access. So we better
>> should determine the instruction in sbi_trap_handler().
>
>That's incorrect.
>
>For RISC-V v1.10 (or higher), the MTVAL contains:
>1. Instruction encoding for illegal instruction trap
>2. Fault address for unaligned traps, page faults, and access faults
>
>For RISC-V v1.10 (or higher), the unaligned trap does not provide
>fault instruction encoding so we end-up doing unpriv access.
>
>Base on above, it's best to work-around your issue in
>sbi_illegal_insn_handler() instead of sbi_trap_handler()
>

That clarifies it.

For rdtime the change solves the problem and I can send files to the K210 via the UART using U-Boot's loady command. Will you turn the suggested change into a patch?

Even with this change grubriscv64.efi is failing on the K210 by acessing incorrect addresses. It runs without failure on QEMU. I will continue analyzing the situation.

Best regards

Heinrich

>Regards,
>Anup
>
>>
>> Best regards
>>
>> Heinrich
>>
>> > Regards,
>> > Anup
>> >
>> >>
>> >> Without this patch I observe a crash in the loady command. So I
>cannot
>> >> load a file over the UART.
>> >>
>> >> Best regards
>> >>
>> >> Heinrich
>> >>
>> >>>
>> >>> Regards,
>> >>> Anup
>> >>>
Anup Patel Aug. 15, 2020, 3:55 p.m. UTC | #7
On Sat, Aug 15, 2020 at 8:37 PM Heinrich Schuchardt <xypron.glpk@gmx.de> wrote:
>
> Am 15. August 2020 16:06:41 MESZ schrieb Anup Patel <anup@brainfault.org>:
> >On Sat, Aug 15, 2020 at 12:57 AM Heinrich Schuchardt
> ><xypron.glpk@gmx.de> wrote:
> >>
> >> On 8/14/20 8:38 PM, Anup Patel wrote:
> >> > On Fri, Aug 14, 2020 at 11:35 PM Heinrich Schuchardt
> ><xypron.glpk@gmx.de> wrote:
> >> >>
> >> >> On 14.08.20 19:52, Anup Patel wrote:
> >> >>> On Fri, Aug 14, 2020 at 11:15 PM Heinrich Schuchardt
> ><xypron.glpk@gmx.de> wrote:
> >> >>>>
> >> >>>> On the Kendryte K210 OpenBSI cannot emulate the rdtime
> >instruction. So we
> >> >>>> have to use the Sifive CLINT driver to provide riscv_get_time()
> >in SMODE.
> >> >>>
> >> >>> Can you elaborate why ?
> >> >>>
> >> >>> The rdtime instruction should generate an illegal instruction
> >fault which
> >> >>> OpenSBI will emulate.
> >> >>
> >> >> The RISC-V Instruction Set Manual Volume II Privileged architectur
> >1.11
> >> >> has incompatible changes relative to version 1.9.1
> >> >>
> >> >> mtval on the Kendryte K210 delivers the bad virtual address and
> >not the
> >> >> instruction:
> >> >
> >> > Ahh, I see. The MTVAL CSR is actually legacy MBADADDR CSR and this
> >> > CSR.
> >> >
> >> > The S-mode software always has working rdtime instruction for all
> >> > RISC-V systems. If HW does not implement TIME CSR then OpenSBI
> >> > emulates it. Please don't break this convention for U-Boot S-mode
> >> > because we do have RISC-V systems where TIME CSR is implemeted
> >> > in HW so this will patch will break U-Boot S-mode system because
> >> > on those system we are supposed to use TIME CSR from S-mode.
> >>
> >> This patch does not change anything for existing systems. It only
> >allows
> >> me to customize U-Boot for the K210 differently. I understand that
> >> fixing OpenSBI is a better approach.
> >
> >Currently, on most RISC-V systems the CLINT timer interrupts and IPI
> >interrupts are hard-wired to M-mode timer and software interrupt lines.
> >In other words, the CLINT is integrated as M-mode only device on most
> >RISC-V systems.
> >
> >Due to above reason, CLINT driver is M-mode only driver for Linux
> >kernel
> >
> >The Linux S-mode will use:
> >1. TIME CSR as free running counter
> >2. SBI calls for timer interrupts
> >3. SBI calls for injecting IPIs
> >
> >For #1 above, the M-mode firmware will trap-n-emulate TIME CSR
> >for S-mode if HW does not implement TIME CSR.
> >
> >Based on above mentioned convention, the U-Boot CLINT driver
> >should be M-mode only and U-Boot S-mode should use TIME CSR
> >as a free running counter.
> >
> >>
> >> >
> >> >>
> >> >> lib/sbi/sbi_illegal_insn.c(123) sbi_illegal_insn_handler:
> >> >> insn 0x4114121602, epc 0x8058c168.
> >> >>
> >> >> The illegal instruction being
> >> >> c01027f3    rdtime a5
> >> >>
> >> >> In the long run it may make sense to provide backwards
> >compatibility in
> >> >> OpenSBI.
> >> >
> >> > Yes, let's try to explore possible fixes in OpenSBI.
> >> >
> >> > Instead of this patch, try the following change in OpenSBI ...
> >> >
> >> > diff --git a/lib/sbi/sbi_illegal_insn.c
> >b/lib/sbi/sbi_illegal_insn.c
> >> > index 0e5523f..c8f2e4a 100644
> >> > --- a/lib/sbi/sbi_illegal_insn.c
> >> > +++ b/lib/sbi/sbi_illegal_insn.c
> >> > @@ -119,12 +119,10 @@ int sbi_illegal_insn_handler(ulong insn,
> >struct
> >> > sbi_trap_regs *regs)
> >> >         struct sbi_trap_info uptrap;
> >> >
> >> >         if (unlikely((insn & 3) != 3)) {
> >>
> >> Why do put sbi_get_insn() behind this if and not before it?
> >
> >Currently, OpenSBI only deals with 32bit (or longer) illegal
> >instructions. If we see insn == 0 OR insn is 16bit then we
> >double-check instruction encoding using unprivileged access.
> >
> >The PC in RISC-V is always 2-byte aligned address so if MTVAL
> >has fault instruction address instead of instruction encoding then
> >"(insn & 3) != 3" will be TRUE and we will be forced to double-check.
> >The "insn == 0" check below is causing problem RISC-V v1.9 spec
> >(i.e. MTVAL having instruction address) and it is totally harmless to
> >remove the "insn == 0" check for RISC-V v1.10 (or higher) hence
> >my suggestion to remove the check.
> >
>
> Thank you for your detailed explanation. Maybe you can add a comment to the code.

Sure will do.

>
> >>
> >> > -               if (insn == 0) {
> >> > -                       insn = sbi_get_insn(regs->mepc, &uptrap);
> >> > -                       if (uptrap.cause) {
> >> > -                               uptrap.epc = regs->mepc;
> >> > -                               return sbi_trap_redirect(regs,
> >&uptrap);
> >> > -                       }
> >> > +               insn = sbi_get_insn(regs->mepc, &uptrap);
> >> > +               if (uptrap.cause) {
> >> > +                       uptrap.epc = regs->mepc;
> >> > +                       return sbi_trap_redirect(regs, &uptrap);
> >> >                 }
> >> >                 if ((insn & 3) != 3)
> >> >                         return truly_illegal_insn(insn, regs);
> >> >
> >>
> >> For this illegal instruction exception the fix works. But I think the
> >> change is in the wrong place.
> >>
> >> We have to cover all exceptions, e.g. unaligned access. So we better
> >> should determine the instruction in sbi_trap_handler().
> >
> >That's incorrect.
> >
> >For RISC-V v1.10 (or higher), the MTVAL contains:
> >1. Instruction encoding for illegal instruction trap
> >2. Fault address for unaligned traps, page faults, and access faults
> >
> >For RISC-V v1.10 (or higher), the unaligned trap does not provide
> >fault instruction encoding so we end-up doing unpriv access.
> >
> >Base on above, it's best to work-around your issue in
> >sbi_illegal_insn_handler() instead of sbi_trap_handler()
> >
>
> That clarifies it.
>
> For rdtime the change solves the problem and I can send files to the K210 via the UART using U-Boot's loady command. Will you turn the suggested change into a patch?

Yes, already doing that.

>
> Even with this change grubriscv64.efi is failing on the K210 by acessing incorrect addresses. It runs without failure on QEMU. I will continue analyzing the situation.

Sure, let us know if you find any other issue.

Regards,
Anup
Heinrich Schuchardt Aug. 16, 2020, 10:14 a.m. UTC | #8
On 8/15/20 5:55 PM, Anup Patel wrote:
> On Sat, Aug 15, 2020 at 8:37 PM Heinrich Schuchardt <xypron.glpk@gmx.de> wrote:
>>
>> Am 15. August 2020 16:06:41 MESZ schrieb Anup Patel <anup@brainfault.org>:
>>> On Sat, Aug 15, 2020 at 12:57 AM Heinrich Schuchardt
>>> <xypron.glpk@gmx.de> wrote:
>>>>
>>>> On 8/14/20 8:38 PM, Anup Patel wrote:
>>>>> On Fri, Aug 14, 2020 at 11:35 PM Heinrich Schuchardt
>>> <xypron.glpk@gmx.de> wrote:
>>>>>>
>>>>>> On 14.08.20 19:52, Anup Patel wrote:
>>>>>>> On Fri, Aug 14, 2020 at 11:15 PM Heinrich Schuchardt
>>> <xypron.glpk@gmx.de> wrote:
>>>>>>>>
>>>>>>>> On the Kendryte K210 OpenBSI cannot emulate the rdtime
>>> instruction. So we
>>>>>>>> have to use the Sifive CLINT driver to provide riscv_get_time()
>>> in SMODE.
>>>>>>>
>>>>>>> Can you elaborate why ?
>>>>>>>
>>>>>>> The rdtime instruction should generate an illegal instruction
>>> fault which
>>>>>>> OpenSBI will emulate.
>>>>>>
>>>>>> The RISC-V Instruction Set Manual Volume II Privileged architectur
>>> 1.11
>>>>>> has incompatible changes relative to version 1.9.1
>>>>>>
>>>>>> mtval on the Kendryte K210 delivers the bad virtual address and
>>> not the
>>>>>> instruction:
>>>>>
>>>>> Ahh, I see. The MTVAL CSR is actually legacy MBADADDR CSR and this
>>>>> CSR.
>>>>>
>>>>> The S-mode software always has working rdtime instruction for all
>>>>> RISC-V systems. If HW does not implement TIME CSR then OpenSBI
>>>>> emulates it. Please don't break this convention for U-Boot S-mode
>>>>> because we do have RISC-V systems where TIME CSR is implemeted
>>>>> in HW so this will patch will break U-Boot S-mode system because
>>>>> on those system we are supposed to use TIME CSR from S-mode.
>>>>
>>>> This patch does not change anything for existing systems. It only
>>> allows
>>>> me to customize U-Boot for the K210 differently. I understand that
>>>> fixing OpenSBI is a better approach.
>>>
>>> Currently, on most RISC-V systems the CLINT timer interrupts and IPI
>>> interrupts are hard-wired to M-mode timer and software interrupt lines.
>>> In other words, the CLINT is integrated as M-mode only device on most
>>> RISC-V systems.
>>>
>>> Due to above reason, CLINT driver is M-mode only driver for Linux
>>> kernel
>>>
>>> The Linux S-mode will use:
>>> 1. TIME CSR as free running counter
>>> 2. SBI calls for timer interrupts
>>> 3. SBI calls for injecting IPIs
>>>
>>> For #1 above, the M-mode firmware will trap-n-emulate TIME CSR
>>> for S-mode if HW does not implement TIME CSR.
>>>
>>> Based on above mentioned convention, the U-Boot CLINT driver
>>> should be M-mode only and U-Boot S-mode should use TIME CSR
>>> as a free running counter.
>>>
>>>>
>>>>>
>>>>>>
>>>>>> lib/sbi/sbi_illegal_insn.c(123) sbi_illegal_insn_handler:
>>>>>> insn 0x4114121602, epc 0x8058c168.
>>>>>>
>>>>>> The illegal instruction being
>>>>>> c01027f3    rdtime a5
>>>>>>
>>>>>> In the long run it may make sense to provide backwards
>>> compatibility in
>>>>>> OpenSBI.
>>>>>
>>>>> Yes, let's try to explore possible fixes in OpenSBI.
>>>>>
>>>>> Instead of this patch, try the following change in OpenSBI ...
>>>>>
>>>>> diff --git a/lib/sbi/sbi_illegal_insn.c
>>> b/lib/sbi/sbi_illegal_insn.c
>>>>> index 0e5523f..c8f2e4a 100644
>>>>> --- a/lib/sbi/sbi_illegal_insn.c
>>>>> +++ b/lib/sbi/sbi_illegal_insn.c
>>>>> @@ -119,12 +119,10 @@ int sbi_illegal_insn_handler(ulong insn,
>>> struct
>>>>> sbi_trap_regs *regs)
>>>>>         struct sbi_trap_info uptrap;
>>>>>
>>>>>         if (unlikely((insn & 3) != 3)) {
>>>>
>>>> Why do put sbi_get_insn() behind this if and not before it?
>>>
>>> Currently, OpenSBI only deals with 32bit (or longer) illegal
>>> instructions. If we see insn == 0 OR insn is 16bit then we
>>> double-check instruction encoding using unprivileged access.
>>>
>>> The PC in RISC-V is always 2-byte aligned address so if MTVAL
>>> has fault instruction address instead of instruction encoding then
>>> "(insn & 3) != 3" will be TRUE and we will be forced to double-check.
>>> The "insn == 0" check below is causing problem RISC-V v1.9 spec
>>> (i.e. MTVAL having instruction address) and it is totally harmless to
>>> remove the "insn == 0" check for RISC-V v1.10 (or higher) hence
>>> my suggestion to remove the check.
>>>
>>
>> Thank you for your detailed explanation. Maybe you can add a comment to the code.
>
> Sure will do.
>
>>
>>>>
>>>>> -               if (insn == 0) {
>>>>> -                       insn = sbi_get_insn(regs->mepc, &uptrap);
>>>>> -                       if (uptrap.cause) {
>>>>> -                               uptrap.epc = regs->mepc;
>>>>> -                               return sbi_trap_redirect(regs,
>>> &uptrap);
>>>>> -                       }
>>>>> +               insn = sbi_get_insn(regs->mepc, &uptrap);
>>>>> +               if (uptrap.cause) {
>>>>> +                       uptrap.epc = regs->mepc;
>>>>> +                       return sbi_trap_redirect(regs, &uptrap);
>>>>>                 }
>>>>>                 if ((insn & 3) != 3)
>>>>>                         return truly_illegal_insn(insn, regs);
>>>>>
>>>>
>>>> For this illegal instruction exception the fix works. But I think the
>>>> change is in the wrong place.
>>>>
>>>> We have to cover all exceptions, e.g. unaligned access. So we better
>>>> should determine the instruction in sbi_trap_handler().
>>>
>>> That's incorrect.
>>>
>>> For RISC-V v1.10 (or higher), the MTVAL contains:
>>> 1. Instruction encoding for illegal instruction trap
>>> 2. Fault address for unaligned traps, page faults, and access faults
>>>
>>> For RISC-V v1.10 (or higher), the unaligned trap does not provide
>>> fault instruction encoding so we end-up doing unpriv access.
>>>
>>> Base on above, it's best to work-around your issue in
>>> sbi_illegal_insn_handler() instead of sbi_trap_handler()
>>>
>>
>> That clarifies it.
>>
>> For rdtime the change solves the problem and I can send files to the K210 via the UART using U-Boot's loady command. Will you turn the suggested change into a patch?
>
> Yes, already doing that.
>
>>
>> Even with this change grubriscv64.efi is failing on the K210 by acessing incorrect addresses. It runs without failure on QEMU. I will continue analyzing the situation.

grubriscv64.efi with too many modules loaded runs out of memory on the
Maixduino board.

With

./grub-mkimage -O riscv64-efi -o grubriscv64.efi --prefix= -d \
grub-core lsefisystab minicmd normal reboot

I get a GRUB binary containing the minimum required for the U-Boot unit
tests.

After applying the patches

lib: sbi_init: Avoid thundering hurd problem with coldbook_lock -
http://lists.infradead.org/pipermail/opensbi/2020-August/000107.html

lib: sbi: Handle the case were MTVAL has illegal instruction address
http://lists.infradead.org/pipermail/opensbi/2020-August/000108.html

to OpenSBI I can start GRUB and execute the commands used by the U-Boot
unit tests successfully on the Maixduino board.

Best regards

Heinrich

>
> Sure, let us know if you find any other issue.
>
> Regards,
> Anup
>
Anup Patel Aug. 16, 2020, 1:38 p.m. UTC | #9
On Sun, Aug 16, 2020 at 3:49 PM Heinrich Schuchardt <xypron.glpk@gmx.de> wrote:
>
> On 8/15/20 5:55 PM, Anup Patel wrote:
> > On Sat, Aug 15, 2020 at 8:37 PM Heinrich Schuchardt <xypron.glpk@gmx.de> wrote:
> >>
> >> Am 15. August 2020 16:06:41 MESZ schrieb Anup Patel <anup@brainfault.org>:
> >>> On Sat, Aug 15, 2020 at 12:57 AM Heinrich Schuchardt
> >>> <xypron.glpk@gmx.de> wrote:
> >>>>
> >>>> On 8/14/20 8:38 PM, Anup Patel wrote:
> >>>>> On Fri, Aug 14, 2020 at 11:35 PM Heinrich Schuchardt
> >>> <xypron.glpk@gmx.de> wrote:
> >>>>>>
> >>>>>> On 14.08.20 19:52, Anup Patel wrote:
> >>>>>>> On Fri, Aug 14, 2020 at 11:15 PM Heinrich Schuchardt
> >>> <xypron.glpk@gmx.de> wrote:
> >>>>>>>>
> >>>>>>>> On the Kendryte K210 OpenBSI cannot emulate the rdtime
> >>> instruction. So we
> >>>>>>>> have to use the Sifive CLINT driver to provide riscv_get_time()
> >>> in SMODE.
> >>>>>>>
> >>>>>>> Can you elaborate why ?
> >>>>>>>
> >>>>>>> The rdtime instruction should generate an illegal instruction
> >>> fault which
> >>>>>>> OpenSBI will emulate.
> >>>>>>
> >>>>>> The RISC-V Instruction Set Manual Volume II Privileged architectur
> >>> 1.11
> >>>>>> has incompatible changes relative to version 1.9.1
> >>>>>>
> >>>>>> mtval on the Kendryte K210 delivers the bad virtual address and
> >>> not the
> >>>>>> instruction:
> >>>>>
> >>>>> Ahh, I see. The MTVAL CSR is actually legacy MBADADDR CSR and this
> >>>>> CSR.
> >>>>>
> >>>>> The S-mode software always has working rdtime instruction for all
> >>>>> RISC-V systems. If HW does not implement TIME CSR then OpenSBI
> >>>>> emulates it. Please don't break this convention for U-Boot S-mode
> >>>>> because we do have RISC-V systems where TIME CSR is implemeted
> >>>>> in HW so this will patch will break U-Boot S-mode system because
> >>>>> on those system we are supposed to use TIME CSR from S-mode.
> >>>>
> >>>> This patch does not change anything for existing systems. It only
> >>> allows
> >>>> me to customize U-Boot for the K210 differently. I understand that
> >>>> fixing OpenSBI is a better approach.
> >>>
> >>> Currently, on most RISC-V systems the CLINT timer interrupts and IPI
> >>> interrupts are hard-wired to M-mode timer and software interrupt lines.
> >>> In other words, the CLINT is integrated as M-mode only device on most
> >>> RISC-V systems.
> >>>
> >>> Due to above reason, CLINT driver is M-mode only driver for Linux
> >>> kernel
> >>>
> >>> The Linux S-mode will use:
> >>> 1. TIME CSR as free running counter
> >>> 2. SBI calls for timer interrupts
> >>> 3. SBI calls for injecting IPIs
> >>>
> >>> For #1 above, the M-mode firmware will trap-n-emulate TIME CSR
> >>> for S-mode if HW does not implement TIME CSR.
> >>>
> >>> Based on above mentioned convention, the U-Boot CLINT driver
> >>> should be M-mode only and U-Boot S-mode should use TIME CSR
> >>> as a free running counter.
> >>>
> >>>>
> >>>>>
> >>>>>>
> >>>>>> lib/sbi/sbi_illegal_insn.c(123) sbi_illegal_insn_handler:
> >>>>>> insn 0x4114121602, epc 0x8058c168.
> >>>>>>
> >>>>>> The illegal instruction being
> >>>>>> c01027f3    rdtime a5
> >>>>>>
> >>>>>> In the long run it may make sense to provide backwards
> >>> compatibility in
> >>>>>> OpenSBI.
> >>>>>
> >>>>> Yes, let's try to explore possible fixes in OpenSBI.
> >>>>>
> >>>>> Instead of this patch, try the following change in OpenSBI ...
> >>>>>
> >>>>> diff --git a/lib/sbi/sbi_illegal_insn.c
> >>> b/lib/sbi/sbi_illegal_insn.c
> >>>>> index 0e5523f..c8f2e4a 100644
> >>>>> --- a/lib/sbi/sbi_illegal_insn.c
> >>>>> +++ b/lib/sbi/sbi_illegal_insn.c
> >>>>> @@ -119,12 +119,10 @@ int sbi_illegal_insn_handler(ulong insn,
> >>> struct
> >>>>> sbi_trap_regs *regs)
> >>>>>         struct sbi_trap_info uptrap;
> >>>>>
> >>>>>         if (unlikely((insn & 3) != 3)) {
> >>>>
> >>>> Why do put sbi_get_insn() behind this if and not before it?
> >>>
> >>> Currently, OpenSBI only deals with 32bit (or longer) illegal
> >>> instructions. If we see insn == 0 OR insn is 16bit then we
> >>> double-check instruction encoding using unprivileged access.
> >>>
> >>> The PC in RISC-V is always 2-byte aligned address so if MTVAL
> >>> has fault instruction address instead of instruction encoding then
> >>> "(insn & 3) != 3" will be TRUE and we will be forced to double-check.
> >>> The "insn == 0" check below is causing problem RISC-V v1.9 spec
> >>> (i.e. MTVAL having instruction address) and it is totally harmless to
> >>> remove the "insn == 0" check for RISC-V v1.10 (or higher) hence
> >>> my suggestion to remove the check.
> >>>
> >>
> >> Thank you for your detailed explanation. Maybe you can add a comment to the code.
> >
> > Sure will do.
> >
> >>
> >>>>
> >>>>> -               if (insn == 0) {
> >>>>> -                       insn = sbi_get_insn(regs->mepc, &uptrap);
> >>>>> -                       if (uptrap.cause) {
> >>>>> -                               uptrap.epc = regs->mepc;
> >>>>> -                               return sbi_trap_redirect(regs,
> >>> &uptrap);
> >>>>> -                       }
> >>>>> +               insn = sbi_get_insn(regs->mepc, &uptrap);
> >>>>> +               if (uptrap.cause) {
> >>>>> +                       uptrap.epc = regs->mepc;
> >>>>> +                       return sbi_trap_redirect(regs, &uptrap);
> >>>>>                 }
> >>>>>                 if ((insn & 3) != 3)
> >>>>>                         return truly_illegal_insn(insn, regs);
> >>>>>
> >>>>
> >>>> For this illegal instruction exception the fix works. But I think the
> >>>> change is in the wrong place.
> >>>>
> >>>> We have to cover all exceptions, e.g. unaligned access. So we better
> >>>> should determine the instruction in sbi_trap_handler().
> >>>
> >>> That's incorrect.
> >>>
> >>> For RISC-V v1.10 (or higher), the MTVAL contains:
> >>> 1. Instruction encoding for illegal instruction trap
> >>> 2. Fault address for unaligned traps, page faults, and access faults
> >>>
> >>> For RISC-V v1.10 (or higher), the unaligned trap does not provide
> >>> fault instruction encoding so we end-up doing unpriv access.
> >>>
> >>> Base on above, it's best to work-around your issue in
> >>> sbi_illegal_insn_handler() instead of sbi_trap_handler()
> >>>
> >>
> >> That clarifies it.
> >>
> >> For rdtime the change solves the problem and I can send files to the K210 via the UART using U-Boot's loady command. Will you turn the suggested change into a patch?
> >
> > Yes, already doing that.
> >
> >>
> >> Even with this change grubriscv64.efi is failing on the K210 by acessing incorrect addresses. It runs without failure on QEMU. I will continue analyzing the situation.
>
> grubriscv64.efi with too many modules loaded runs out of memory on the
> Maixduino board.
>
> With
>
> ./grub-mkimage -O riscv64-efi -o grubriscv64.efi --prefix= -d \
> grub-core lsefisystab minicmd normal reboot
>
> I get a GRUB binary containing the minimum required for the U-Boot unit
> tests.
>
> After applying the patches
>
> lib: sbi_init: Avoid thundering hurd problem with coldbook_lock -
> http://lists.infradead.org/pipermail/opensbi/2020-August/000107.html
>
> lib: sbi: Handle the case were MTVAL has illegal instruction address
> http://lists.infradead.org/pipermail/opensbi/2020-August/000108.html
>
> to OpenSBI I can start GRUB and execute the commands used by the U-Boot
> unit tests successfully on the Maixduino board.

If possible please add:
1. defconfig for U-Boot S-mode on Kendryte K210
2. documentation about how to run U-Boot S-mode on Kendryte K210

This will be very helpful to users who want to run some RTOS in S-mode
using U-Boot S-mode.

Regards,
Anup
diff mbox series

Patch

diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 009a545fcf..96c386225b 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -153,12 +153,18 @@  config 64BIT
 	bool

 config SIFIVE_CLINT
-	bool
-	depends on RISCV_MMODE || SPL_RISCV_MMODE
+	bool "SiFive's Core Local Interruptor (CLINT) driver"
 	select REGMAP
 	select SYSCON
-	select SPL_REGMAP if SPL
-	select SPL_SYSCON if SPL
+	help
+	  The SiFive CLINT block holds memory-mapped control and status registers
+	  associated with software and timer interrupts.
+
+config SPL_SIFIVE_CLINT
+	bool "SiFive's Core Local Interruptor (CLINT) driver in SPL"
+	depends on SPL
+	select SPL_REGMAP
+	select SPL_SYSCON
 	help
 	  The SiFive CLINT block holds memory-mapped control and status registers
 	  associated with software and timer interrupts.
@@ -186,7 +192,7 @@  config ANDES_PLMT
 	  associated with timer tick.

 config RISCV_RDTIME
-	bool
+	bool "Timer API via rdtime instruction"
 	default y if RISCV_SMODE || SPL_RISCV_SMODE
 	help
 	  The provides the riscv_get_time() API that is implemented using the
diff --git a/arch/riscv/cpu/fu540/Kconfig b/arch/riscv/cpu/fu540/Kconfig
index 2dcad8e27f..8b2c83039f 100644
--- a/arch/riscv/cpu/fu540/Kconfig
+++ b/arch/riscv/cpu/fu540/Kconfig
@@ -8,7 +8,8 @@  config SIFIVE_FU540
 	imply CPU
 	imply CPU_RISCV
 	imply RISCV_TIMER
-	imply SIFIVE_CLINT if (RISCV_MMODE || SPL_RISCV_MMODE)
+	imply SIFIVE_CLINT if RISCV_MMODE
+	imply SPL_SIFIVE_CLINT if SPL_RISCV_MMODE
 	imply CMD_CPU
 	imply SPL_CPU_SUPPORT
 	imply SPL_OPENSBI
diff --git a/arch/riscv/cpu/generic/Kconfig b/arch/riscv/cpu/generic/Kconfig
index b2cb155d6d..62fcadd710 100644
--- a/arch/riscv/cpu/generic/Kconfig
+++ b/arch/riscv/cpu/generic/Kconfig
@@ -8,7 +8,8 @@  config GENERIC_RISCV
 	imply CPU
 	imply CPU_RISCV
 	imply RISCV_TIMER
-	imply SIFIVE_CLINT if (RISCV_MMODE || SPL_RISCV_MMODE)
+	imply SIFIVE_CLINT if RISCV_MMODE
+	imply SPL_SIFIVE_CLINT if SPL_RISCV_MMODE
 	imply CMD_CPU
 	imply SPL_CPU_SUPPORT
 	imply SPL_OPENSBI
diff --git a/arch/riscv/include/asm/global_data.h b/arch/riscv/include/asm/global_data.h
index 2eb14815bc..b89b469d41 100644
--- a/arch/riscv/include/asm/global_data.h
+++ b/arch/riscv/include/asm/global_data.h
@@ -18,7 +18,7 @@ 
 struct arch_global_data {
 	long boot_hart;		/* boot hart id */
 	phys_addr_t firmware_fdt_addr;
-#ifdef CONFIG_SIFIVE_CLINT
+#if CONFIG_IS_ENABLED(SIFIVE_CLINT)
 	void __iomem *clint;	/* clint base address */
 #endif
 #ifdef CONFIG_ANDES_PLIC
diff --git a/arch/riscv/lib/Makefile b/arch/riscv/lib/Makefile
index 6c503ff2b2..861d7b489f 100644
--- a/arch/riscv/lib/Makefile
+++ b/arch/riscv/lib/Makefile
@@ -10,8 +10,8 @@  obj-$(CONFIG_CMD_BOOTM) += bootm.o
 obj-$(CONFIG_CMD_BOOTI) += bootm.o image.o
 obj-$(CONFIG_CMD_GO) += boot.o
 obj-y	+= cache.o
+obj-$(CONFIG_$(SPL_)SIFIVE_CLINT) += sifive_clint.o
 ifeq ($(CONFIG_$(SPL_)RISCV_MMODE),y)
-obj-$(CONFIG_SIFIVE_CLINT) += sifive_clint.o
 obj-$(CONFIG_ANDES_PLIC) += andes_plic.o
 obj-$(CONFIG_ANDES_PLMT) += andes_plmt.o
 else