User:Demindiro/SBI: Difference between revisions

From OSDev.wiki
Jump to navigation Jump to search
Content added Content deleted
(Important note about QEMU being buggy)
(I messed up and accidently used MAX instead of MIN)
Line 52: Line 52:
muldiv64(diff, NANOSECONDS_PER_SECOND, timebase_freq);
muldiv64(diff, NANOSECONDS_PER_SECOND, timebase_freq);
+ /* ensure next does not overflow, as timer_mod takes a signed value */
+ /* ensure next does not overflow, as timer_mod takes a signed value */
+ next = MAX(next, INT64_MAX);
+ next = MIN(next, INT64_MAX);
timer_mod(cpu->env.timer, next);
timer_mod(cpu->env.timer, next);
}
}

Revision as of 18:45, 16 August 2021

This page is a stub.
You can help the wiki by accurately adding more contents to it.
This page is a work in progress.
This page may thus be incomplete. Its content may be changed in the near future.


The RISC-V SBI (Supervisor Binary Interface) defines a common interface for RISC-V platforms for OSes. It hides platform-specific implementation details such that OSes are more portable.

Notably, it adds methods to facilitate IPI (Inter-Processor Interrupts).

The reference implementation is OpenSBI.

OpenSBI on QEMU

To run OpenSBI on QEMU, download the source and compile with make PLATFORM=generic CROSS_COMPILE=riscv64-your-os-. Then add -bios path/to/opensbi/build/platform/generic/firmware/fw_jump.bin

fw_jump vs fw_payload vs fw_dynamic

  • fw_jump should be used in conjunction with QEMU's -kernel option
  • fw_payload should directly include the kernel binary.
  • fw_dynamic should be used if you use another bootloader that passes more information to OpenSBI.


Interface

The calling convention is the RISC-V ELF psABI. This means you'll need to save caller-saved registers!

The main difference is that the EID (Extension ID) goes into a7 and FID (Function ID) into a6.


Extensions

Avoid the legacy extensions (EID 0x00 - 0xFF) as those are deprecated.

Timer (0x54494D45)

The timer extension has a single function sbi_set_timer with FID 0x00. It takes a single uint64_t argument.

To reset the timer, pass UINT64_MAX. This clears the STIP bit and effectively disables the timer.

QEMU as of 6.1.0-rc3 does not handle UINT64_MAX properly. To fix this, apply the following patch:

diff --git a/hw/intc/sifive_clint.c b/hw/intc/sifive_clint.c
index 0f41e5ea1c..e65e71e5ec 100644
--- a/hw/intc/sifive_clint.c
+++ b/hw/intc/sifive_clint.c
@@ -61,6 +61,8 @@ static void sifive_clint_write_timecmp(RISCVCPU *cpu, uint64_t value,
     /* back to ns (note args switched in muldiv64) */
     next = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
         muldiv64(diff, NANOSECONDS_PER_SECOND, timebase_freq);
+    /* ensure next does not overflow, as timer_mod takes a signed value */
+    next = MIN(next, INT64_MAX);
     timer_mod(cpu->env.timer, next);
 }

See Also

External Links