riscv: implement VirtIO target

This allows running RISC-V tests in CI using QEMU, which should help
catch bugs.
This commit is contained in:
Ayke van Laethem
2020-03-22 20:11:46 +01:00
committed by Ron Evans
parent c4fd19be99
commit 980068543a
6 changed files with 132 additions and 33 deletions
-33
View File
@@ -16,21 +16,6 @@ import (
type timeUnit int64
//go:extern _sbss
var _sbss [0]byte
//go:extern _ebss
var _ebss [0]byte
//go:extern _sdata
var _sdata [0]byte
//go:extern _sidata
var _sidata [0]byte
//go:extern _edata
var _edata [0]byte
func postinit() {}
//go:export main
@@ -108,24 +93,6 @@ func initPeripherals() {
machine.UART0.Configure(machine.UARTConfig{})
}
func preinit() {
// Initialize .bss: zero-initialized global variables.
ptr := unsafe.Pointer(&_sbss)
for ptr != unsafe.Pointer(&_ebss) {
*(*uint32)(ptr) = 0
ptr = unsafe.Pointer(uintptr(ptr) + 4)
}
// Initialize .data: global variables initialized from flash.
src := unsafe.Pointer(&_sidata)
dst := unsafe.Pointer(&_sdata)
for dst != unsafe.Pointer(&_edata) {
*(*uint32)(dst) = *(*uint32)(src)
dst = unsafe.Pointer(uintptr(dst) + 4)
src = unsafe.Pointer(uintptr(src) + 4)
}
}
func putchar(c byte) {
machine.UART0.WriteByte(c)
}
+38
View File
@@ -0,0 +1,38 @@
// +build tinygo.riscv
package runtime
import "unsafe"
//go:extern _sbss
var _sbss [0]byte
//go:extern _ebss
var _ebss [0]byte
//go:extern _sdata
var _sdata [0]byte
//go:extern _sidata
var _sidata [0]byte
//go:extern _edata
var _edata [0]byte
func preinit() {
// Initialize .bss: zero-initialized global variables.
ptr := unsafe.Pointer(&_sbss)
for ptr != unsafe.Pointer(&_ebss) {
*(*uint32)(ptr) = 0
ptr = unsafe.Pointer(uintptr(ptr) + 4)
}
// Initialize .data: global variables initialized from flash.
src := unsafe.Pointer(&_sidata)
dst := unsafe.Pointer(&_sdata)
for dst != unsafe.Pointer(&_edata) {
*(*uint32)(dst) = *(*uint32)(src)
dst = unsafe.Pointer(uintptr(dst) + 4)
src = unsafe.Pointer(uintptr(src) + 4)
}
}
+63
View File
@@ -0,0 +1,63 @@
// +build tinygo.riscv,qemu
package runtime
import (
"device/riscv"
"runtime/volatile"
"unsafe"
)
// This file implements the VirtIO RISC-V interface implemented in QEMU, which
// is an interface designed for emulation.
type timeUnit int64
const tickMicros = 1
var timestamp timeUnit
func postinit() {}
//go:export main
func main() {
preinit()
run()
abort()
}
const asyncScheduler = false
func sleepTicks(d timeUnit) {
// TODO: actually sleep here for the given time.
timestamp += d
}
func ticks() timeUnit {
return timestamp
}
// Memory-mapped I/O as defined by QEMU.
// Source: https://github.com/qemu/qemu/blob/master/hw/riscv/virt.c
// Technically this is an implementation detail but hopefully they won't change
// the memory-mapped I/O registers.
var (
// UART0 output register.
stdoutWrite = (*volatile.Register8)(unsafe.Pointer(uintptr(0x10000000)))
// SiFive test finisher
testFinisher = (*volatile.Register16)(unsafe.Pointer(uintptr(0x100000)))
)
func putchar(c byte) {
stdoutWrite.Set(uint8(c))
}
func abort() {
// Make sure the QEMU process exits.
testFinisher.Set(0x5555) // FINISHER_PASS
// Lock up forever (as a fallback).
for {
riscv.Asm("wfi")
}
}