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

Anup Patel anup at brainfault.org
Sat Aug 15 16:06:41 CEST 2020


On Sat, Aug 15, 2020 at 12:57 AM Heinrich Schuchardt <xypron.glpk at 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 at 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 at 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
> >>>


More information about the U-Boot mailing list