mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-20 12:29:03 +00:00
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b9ce6c3374 | |||
| cab3834bc9 | |||
| 7f970a45c2 | |||
| ebf70ab18e | |||
| 226744a538 | |||
| dc876c6ed4 | |||
| 5a09084c73 | |||
| 6c9074772c | |||
| e49663809b | |||
| 7d6d93f7aa |
@@ -165,6 +165,7 @@ jobs:
|
|||||||
ln -s ~/lib/tinygo/bin/tinygo ~/go/bin/tinygo
|
ln -s ~/lib/tinygo/bin/tinygo ~/go/bin/tinygo
|
||||||
- run: make tinygo-test-wasip1-fast
|
- run: make tinygo-test-wasip1-fast
|
||||||
- run: make tinygo-test-wasip2-fast
|
- run: make tinygo-test-wasip2-fast
|
||||||
|
- run: make tinygo-test-wasm
|
||||||
- run: make smoketest
|
- run: make smoketest
|
||||||
assert-test-linux:
|
assert-test-linux:
|
||||||
# Run all tests that can run on Linux, with LLVM assertions enabled to catch
|
# Run all tests that can run on Linux, with LLVM assertions enabled to catch
|
||||||
@@ -277,7 +278,7 @@ jobs:
|
|||||||
run: make tinygo-test
|
run: make tinygo-test
|
||||||
- run: make smoketest
|
- run: make smoketest
|
||||||
- run: make wasmtest
|
- run: make wasmtest
|
||||||
- run: make tinygo-baremetal
|
- run: make tinygo-test-baremetal
|
||||||
build-linux-cross:
|
build-linux-cross:
|
||||||
# Build ARM Linux binaries, ready for release.
|
# Build ARM Linux binaries, ready for release.
|
||||||
# This intentionally uses an older Linux image, so that we compile against
|
# This intentionally uses an older Linux image, so that we compile against
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ name: LLVM
|
|||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [ build-llvm-image ]
|
branches: [ build-llvm-image ]
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
|||||||
+45
-5
@@ -407,6 +407,43 @@ TEST_PACKAGES_WINDOWS := \
|
|||||||
text/template/parse \
|
text/template/parse \
|
||||||
$(nil)
|
$(nil)
|
||||||
|
|
||||||
|
|
||||||
|
# These packages cannot be tested on wasm, mostly because these tests assume a
|
||||||
|
# working filesystem. This could perhaps be fixed, by supporting filesystem
|
||||||
|
# access when running inside Node.js.
|
||||||
|
TEST_PACKAGES_WASM = $(filter-out $(TEST_PACKAGES_NONWASM), $(TEST_PACKAGES_FAST))
|
||||||
|
TEST_PACKAGES_NONWASM = \
|
||||||
|
compress/lzw \
|
||||||
|
compress/zlib \
|
||||||
|
crypto/ecdsa \
|
||||||
|
debug/macho \
|
||||||
|
embed/internal/embedtest \
|
||||||
|
go/format \
|
||||||
|
os \
|
||||||
|
testing \
|
||||||
|
$(nil)
|
||||||
|
|
||||||
|
# These packages cannot be tested on baremetal.
|
||||||
|
#
|
||||||
|
# Some reasons why the tests don't pass on baremetal:
|
||||||
|
#
|
||||||
|
# * No filesystem is available, so packages like compress/zlib can't be tested
|
||||||
|
# (just like wasm).
|
||||||
|
# * picolibc math functions apparently are less precise, the math package
|
||||||
|
# fails on baremetal.
|
||||||
|
# * Some packages fail or hang for an unknown reason, this should be
|
||||||
|
# investigated and fixed.
|
||||||
|
TEST_PACKAGES_BAREMETAL = $(filter-out $(TEST_PACKAGES_NONBAREMETAL), $(TEST_PACKAGES_FAST))
|
||||||
|
TEST_PACKAGES_NONBAREMETAL = \
|
||||||
|
$(TEST_PACKAGES_NONWASM) \
|
||||||
|
crypto/elliptic \
|
||||||
|
math \
|
||||||
|
reflect \
|
||||||
|
encoding/asn1 \
|
||||||
|
encoding/base32 \
|
||||||
|
go/ast \
|
||||||
|
$(nil)
|
||||||
|
|
||||||
# Report platforms on which each standard library package is known to pass tests
|
# Report platforms on which each standard library package is known to pass tests
|
||||||
jointmp := $(shell echo /tmp/join.$$$$)
|
jointmp := $(shell echo /tmp/join.$$$$)
|
||||||
report-stdlib-tests-pass:
|
report-stdlib-tests-pass:
|
||||||
@@ -450,6 +487,8 @@ tinygo-bench-fast:
|
|||||||
$(TINYGO) test -bench . $(TEST_PACKAGES_HOST)
|
$(TINYGO) test -bench . $(TEST_PACKAGES_HOST)
|
||||||
|
|
||||||
# Same thing, except for wasi rather than the current platform.
|
# Same thing, except for wasi rather than the current platform.
|
||||||
|
tinygo-test-wasm:
|
||||||
|
$(TINYGO) test -target wasm $(TEST_PACKAGES_WASM)
|
||||||
tinygo-test-wasi:
|
tinygo-test-wasi:
|
||||||
$(TINYGO) test -target wasip1 $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_SLOW) ./tests/runtime_wasi
|
$(TINYGO) test -target wasip1 $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_SLOW) ./tests/runtime_wasi
|
||||||
tinygo-test-wasip1:
|
tinygo-test-wasip1:
|
||||||
@@ -484,6 +523,10 @@ tinygo-bench-wasip2:
|
|||||||
tinygo-bench-wasip2-fast:
|
tinygo-bench-wasip2-fast:
|
||||||
$(TINYGO) test -target wasip2 -bench . $(TEST_PACKAGES_FAST)
|
$(TINYGO) test -target wasip2 -bench . $(TEST_PACKAGES_FAST)
|
||||||
|
|
||||||
|
# Run tests on riscv-qemu since that one provides a large amount of memory.
|
||||||
|
tinygo-test-baremetal:
|
||||||
|
$(TINYGO) test -target riscv-qemu $(TEST_PACKAGES_BAREMETAL)
|
||||||
|
|
||||||
# Test external packages in a large corpus.
|
# Test external packages in a large corpus.
|
||||||
test-corpus:
|
test-corpus:
|
||||||
CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GO) test $(GOTESTFLAGS) -timeout=1h -buildmode exe -tags byollvm -run TestCorpus . -corpus=testdata/corpus.yaml
|
CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GO) test $(GOTESTFLAGS) -timeout=1h -buildmode exe -tags byollvm -run TestCorpus . -corpus=testdata/corpus.yaml
|
||||||
@@ -494,11 +537,6 @@ test-corpus-wasi: wasi-libc
|
|||||||
test-corpus-wasip2: wasi-libc
|
test-corpus-wasip2: wasi-libc
|
||||||
CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GO) test $(GOTESTFLAGS) -timeout=1h -buildmode exe -tags byollvm -run TestCorpus . -corpus=testdata/corpus.yaml -target=wasip2
|
CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GO) test $(GOTESTFLAGS) -timeout=1h -buildmode exe -tags byollvm -run TestCorpus . -corpus=testdata/corpus.yaml -target=wasip2
|
||||||
|
|
||||||
tinygo-baremetal:
|
|
||||||
# Regression tests that run on a baremetal target and don't fit in either main_test.go or smoketest.
|
|
||||||
# regression test for #2666: e.g. encoding/hex must pass on baremetal
|
|
||||||
$(TINYGO) test -target cortex-m-qemu encoding/hex
|
|
||||||
|
|
||||||
.PHONY: testchdir
|
.PHONY: testchdir
|
||||||
testchdir:
|
testchdir:
|
||||||
# test 'build' command with{,out} -C argument
|
# test 'build' command with{,out} -C argument
|
||||||
@@ -585,6 +623,8 @@ ifneq ($(WASM), 0)
|
|||||||
@$(MD5SUM) test.wasm
|
@$(MD5SUM) test.wasm
|
||||||
GOOS=js GOARCH=wasm $(TINYGO) build -size short -o test.wasm -tags=gopher_badge examples/blinky1
|
GOOS=js GOARCH=wasm $(TINYGO) build -size short -o test.wasm -tags=gopher_badge examples/blinky1
|
||||||
@$(MD5SUM) test.wasm
|
@$(MD5SUM) test.wasm
|
||||||
|
GOOS=js GOARCH=wasm $(TINYGO) build -size short -o test.wasm -tags=pico examples/blinky1
|
||||||
|
@$(MD5SUM) test.wasm
|
||||||
endif
|
endif
|
||||||
# test all targets/boards
|
# test all targets/boards
|
||||||
$(TINYGO) build -size short -o test.hex -target=pca10040-s132v6 examples/blinky1
|
$(TINYGO) build -size short -o test.hex -target=pca10040-s132v6 examples/blinky1
|
||||||
|
|||||||
+1
-1
@@ -446,7 +446,7 @@ func (c *compilerContext) parsePragmas(info *functionInfo, f *ssa.Function) {
|
|||||||
// The list of allowed types is based on this proposal:
|
// The list of allowed types is based on this proposal:
|
||||||
// https://github.com/golang/go/issues/59149
|
// https://github.com/golang/go/issues/59149
|
||||||
func (c *compilerContext) checkWasmImportExport(f *ssa.Function, pragma string) {
|
func (c *compilerContext) checkWasmImportExport(f *ssa.Function, pragma string) {
|
||||||
if c.pkg.Path() == "runtime" || c.pkg.Path() == "syscall/js" || c.pkg.Path() == "syscall" {
|
if c.pkg.Path() == "runtime" || c.pkg.Path() == "syscall/js" || c.pkg.Path() == "syscall" || c.pkg.Path() == "crypto/internal/sysrand" {
|
||||||
// The runtime is a special case. Allow all kinds of parameters
|
// The runtime is a special case. Allow all kinds of parameters
|
||||||
// (importantly, including pointers).
|
// (importantly, including pointers).
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
//go:build nrf || (stm32 && !(stm32f103 || stm32l0x1)) || (sam && atsamd51) || (sam && atsame5x) || esp32c3 || tkey
|
//go:build nrf || (stm32 && !(stm32f103 || stm32l0x1)) || (sam && atsamd51) || (sam && atsame5x) || esp32c3 || tkey || (tinygo.riscv32 && virt)
|
||||||
|
|
||||||
// If you update the above build constraint, you'll probably also need to update
|
// If you update the above build constraint, you'll probably also need to update
|
||||||
// src/runtime/rand_hwrng.go.
|
// src/runtime/rand_hwrng.go.
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
cpuFreq = 125 * MHz
|
cpuFreq = 200 * MHz
|
||||||
_NUMBANK0_GPIOS = 30
|
_NUMBANK0_GPIOS = 30
|
||||||
_NUMBANK0_IRQS = 4
|
_NUMBANK0_IRQS = 4
|
||||||
_NUMIRQ = 32
|
_NUMIRQ = 32
|
||||||
@@ -208,3 +208,16 @@ func (clks *clocksType) initTicks() {} // No ticks on RP2040
|
|||||||
func (wd *watchdogImpl) startTick(cycles uint32) {
|
func (wd *watchdogImpl) startTick(cycles uint32) {
|
||||||
rp.WATCHDOG.TICK.Set(cycles | rp.WATCHDOG_TICK_ENABLE)
|
rp.WATCHDOG.TICK.Set(cycles | rp.WATCHDOG_TICK_ENABLE)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func adjustCoreVoltage() bool {
|
||||||
|
if cpuFreq <= 133*MHz {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// The rp2040 is certified to run at 200MHz with the
|
||||||
|
// core voltage set to 1150mV.
|
||||||
|
const targetVoltage = 1150
|
||||||
|
// 0b0101 maps to 800mV and each step is 50mV.
|
||||||
|
const vreg = 0b0101 + (targetVoltage-800)/50
|
||||||
|
rp.VREG_AND_CHIP_RESET.SetVREG_VSEL(vreg)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|||||||
@@ -222,3 +222,7 @@ func EnterBootloader() {
|
|||||||
func (wd *watchdogImpl) startTick(cycles uint32) {
|
func (wd *watchdogImpl) startTick(cycles uint32) {
|
||||||
rp.TICKS.WATCHDOG_CTRL.SetBits(1)
|
rp.TICKS.WATCHDOG_CTRL.SetBits(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func adjustCoreVoltage() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|||||||
@@ -42,6 +42,10 @@ type clock struct {
|
|||||||
cix clockIndex
|
cix clockIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The delay in seconds for core voltage adjustments to
|
||||||
|
// settle. Taken from the Pico SDK.
|
||||||
|
const _VREG_VOLTAGE_AUTO_ADJUST_DELAY = 1 / 1e3
|
||||||
|
|
||||||
// clock returns the clock identified by cix.
|
// clock returns the clock identified by cix.
|
||||||
func (clks *clocksType) clock(cix clockIndex) clock {
|
func (clks *clocksType) clock(cix clockIndex) clock {
|
||||||
return clock{
|
return clock{
|
||||||
@@ -188,6 +192,14 @@ func (clks *clocksType) init() {
|
|||||||
xoscFreq,
|
xoscFreq,
|
||||||
xoscFreq)
|
xoscFreq)
|
||||||
|
|
||||||
|
if adjustCoreVoltage() {
|
||||||
|
// Wait for the voltage to settle.
|
||||||
|
const cycles = _VREG_VOLTAGE_AUTO_ADJUST_DELAY * xoscFreq * MHz
|
||||||
|
for i := 0; i < cycles; i++ {
|
||||||
|
arm.Asm("nop")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// clkSys = pllSys (125MHz) / 1 = 125MHz
|
// clkSys = pllSys (125MHz) / 1 = 125MHz
|
||||||
csys := clks.clock(clkSys)
|
csys := clks.clock(clkSys)
|
||||||
csys.configure(rp.CLOCKS_CLK_SYS_CTRL_SRC_CLKSRC_CLK_SYS_AUX,
|
csys.configure(rp.CLOCKS_CLK_SYS_CTRL_SRC_CLKSRC_CLK_SYS_AUX,
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ type irqSummary struct {
|
|||||||
|
|
||||||
type ioBank0Type struct {
|
type ioBank0Type struct {
|
||||||
io [_NUMBANK0_GPIOS]ioType
|
io [_NUMBANK0_GPIOS]ioType
|
||||||
|
_ [rp2350ExtraReg][128]byte
|
||||||
irqsum [rp2350ExtraReg]irqSummary
|
irqsum [rp2350ExtraReg]irqSummary
|
||||||
intR [_NUMBANK0_IRQS]volatile.Register32
|
intR [_NUMBANK0_IRQS]volatile.Register32
|
||||||
proc0IRQctrl irqCtrl
|
proc0IRQctrl irqCtrl
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
//go:build rp2040 || rp2350 || gopher_badge
|
//go:build rp2040 || rp2350 || gopher_badge || pico
|
||||||
|
|
||||||
package machine
|
package machine
|
||||||
|
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ func (uart *UART) Configure(config UARTConfig) error {
|
|||||||
uart.Interrupt.SetPriority(0x80)
|
uart.Interrupt.SetPriority(0x80)
|
||||||
uart.Interrupt.Enable()
|
uart.Interrupt.Enable()
|
||||||
|
|
||||||
// setup interrupt on receive
|
// Setup interrupt on receive.
|
||||||
uart.Bus.UARTIMSC.Set(rp.UART0_UARTIMSC_RXIM)
|
uart.Bus.UARTIMSC.Set(rp.UART0_UARTIMSC_RXIM)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@@ -153,7 +153,7 @@ func initUART(uart *UART) {
|
|||||||
// handleInterrupt should be called from the appropriate interrupt handler for
|
// handleInterrupt should be called from the appropriate interrupt handler for
|
||||||
// this UART instance.
|
// this UART instance.
|
||||||
func (uart *UART) handleInterrupt(interrupt.Interrupt) {
|
func (uart *UART) handleInterrupt(interrupt.Interrupt) {
|
||||||
for uart.Bus.UARTFR.HasBits(rp.UART0_UARTFR_RXFE) {
|
for !uart.Bus.UARTFR.HasBits(rp.UART0_UARTFR_RXFE) {
|
||||||
|
uart.Receive(byte((uart.Bus.UARTDR.Get() & 0xFF)))
|
||||||
}
|
}
|
||||||
uart.Receive(byte((uart.Bus.UARTDR.Get() & 0xFF)))
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,189 @@
|
|||||||
|
//go:build tinygo.riscv32 && virt
|
||||||
|
|
||||||
|
// Machine implementation for VirtIO targets.
|
||||||
|
// At the moment only QEMU RISC-V is supported, but support for ARM for example
|
||||||
|
// should not be difficult to add with a change to virtioFindDevice.
|
||||||
|
|
||||||
|
package machine
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"runtime/volatile"
|
||||||
|
"sync"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
const deviceName = "riscv-qemu"
|
||||||
|
|
||||||
|
func (p Pin) Set(high bool) {
|
||||||
|
// no pins defined
|
||||||
|
}
|
||||||
|
|
||||||
|
var rngLock sync.Mutex
|
||||||
|
var rngDevice *virtioDevice1
|
||||||
|
var rngBuf volatile.Register32
|
||||||
|
|
||||||
|
var errNoRNG = errors.New("machine: no entropy source found")
|
||||||
|
var errNoRNGData = errors.New("machine: entropy source didn't return enough data")
|
||||||
|
|
||||||
|
// GetRNG returns random numbers from a VirtIO entropy source.
|
||||||
|
// When running in QEMU, it requires adding the RNG device:
|
||||||
|
//
|
||||||
|
// -device virtio-rng-device
|
||||||
|
func GetRNG() (uint32, error) {
|
||||||
|
rngLock.Lock()
|
||||||
|
|
||||||
|
// Initialize the device on first use.
|
||||||
|
if rngDevice == nil {
|
||||||
|
// Search for an available RNG.
|
||||||
|
rngDevice = virtioFindDevice(virtioDeviceEntropySource)
|
||||||
|
if rngDevice == nil {
|
||||||
|
rngLock.Unlock()
|
||||||
|
return 0, errNoRNG
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize the device.
|
||||||
|
rngDevice.status.Set(0) // reset device
|
||||||
|
rngDevice.status.Set(virtioDeviceStatusAcknowledge)
|
||||||
|
rngDevice.status.Set(virtioDeviceStatusAcknowledge | virtioDeviceStatusDriver)
|
||||||
|
rngDevice.hostFeaturesSel.Set(0)
|
||||||
|
rngDevice.status.Set(virtioDeviceStatusAcknowledge | virtioDeviceStatusDriver | virtioDeviceStatusDriverOk)
|
||||||
|
rngDevice.guestPageSize.Set(4096)
|
||||||
|
|
||||||
|
// Configure queue, according to section 4.2.4 "Legacy interface".
|
||||||
|
// Note: we're skipping checks for queuePFM and queueNumMax.
|
||||||
|
rngDevice.queueSel.Set(0) // use queue 0 (the only queue)
|
||||||
|
rngDevice.queueNum.Set(1) // use a single buffer in the queue
|
||||||
|
rngDevice.queueAlign.Set(4096) // default alignment appears to be 4096
|
||||||
|
rngDevice.queuePFN.Set(uint32(uintptr(unsafe.Pointer(&rngQueue))) / 4096)
|
||||||
|
|
||||||
|
// Configure the only buffer in the queue (but don't increment
|
||||||
|
// rngQueue.available yet).
|
||||||
|
rngQueue.buffers[0].address = uint64(uintptr(unsafe.Pointer(&rngBuf)))
|
||||||
|
rngQueue.buffers[0].length = uint32(unsafe.Sizeof(rngBuf))
|
||||||
|
rngQueue.buffers[0].flags = 2 // 2 means write-only buffer
|
||||||
|
}
|
||||||
|
|
||||||
|
// Increment the available ring buffer. This doesn't actually change the
|
||||||
|
// buffer index (it's a ring with a single entry), but the number needs to
|
||||||
|
// be incremented otherwise the device won't recognize a new buffer.
|
||||||
|
index := rngQueue.available.index
|
||||||
|
rngQueue.available.index = index + 1
|
||||||
|
rngDevice.queueNotify.Set(0) // notify the device of the 'new' (reused) buffer
|
||||||
|
for rngQueue.used.index.Get() != index+1 {
|
||||||
|
// Busy wait until the RNG buffer is filled.
|
||||||
|
// A better way would be to wait for an interrupt, but since this driver
|
||||||
|
// implementation is mostly used for testing it's good enough for now.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that we indeed got 4 bytes back.
|
||||||
|
if rngQueue.used.ring[0].length != 4 {
|
||||||
|
rngLock.Unlock()
|
||||||
|
return 0, errNoRNGData
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the resulting random numbers.
|
||||||
|
result := rngBuf.Get()
|
||||||
|
|
||||||
|
rngLock.Unlock()
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implement a driver for the VirtIO entropy device.
|
||||||
|
// https://docs.oasis-open.org/virtio/virtio/v1.2/csd01/virtio-v1.2-csd01.html
|
||||||
|
// http://wiki.osdev.org/Virtio
|
||||||
|
// http://www.dumais.io/index.php?article=aca38a9a2b065b24dfa1dee728062a12
|
||||||
|
|
||||||
|
const (
|
||||||
|
virtioDeviceStatusAcknowledge = 1
|
||||||
|
virtioDeviceStatusDriver = 2
|
||||||
|
virtioDeviceStatusDriverOk = 4
|
||||||
|
virtioDeviceStatusFeaturesOk = 8
|
||||||
|
virtioDeviceStatusFailed = 128
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
virtioDeviceReserved = iota
|
||||||
|
virtioDeviceNetworkCard
|
||||||
|
virtioDeviceBlockDevice
|
||||||
|
virtioDeviceConsole
|
||||||
|
virtioDeviceEntropySource
|
||||||
|
// there are more device types
|
||||||
|
)
|
||||||
|
|
||||||
|
// VirtIO device version 1
|
||||||
|
type virtioDevice1 struct {
|
||||||
|
magic volatile.Register32 // always 0x74726976
|
||||||
|
version volatile.Register32
|
||||||
|
deviceID volatile.Register32
|
||||||
|
vendorID volatile.Register32
|
||||||
|
hostFeatures volatile.Register32
|
||||||
|
hostFeaturesSel volatile.Register32
|
||||||
|
_ [2]uint32
|
||||||
|
guestFeatures volatile.Register32
|
||||||
|
guestFeaturesSel volatile.Register32
|
||||||
|
guestPageSize volatile.Register32
|
||||||
|
_ uint32
|
||||||
|
queueSel volatile.Register32
|
||||||
|
queueNumMax volatile.Register32
|
||||||
|
queueNum volatile.Register32
|
||||||
|
queueAlign volatile.Register32
|
||||||
|
queuePFN volatile.Register32
|
||||||
|
_ [3]uint32
|
||||||
|
queueNotify volatile.Register32
|
||||||
|
_ [3]uint32
|
||||||
|
interruptStatus volatile.Register32
|
||||||
|
interruptAck volatile.Register32
|
||||||
|
_ [2]uint32
|
||||||
|
status volatile.Register32
|
||||||
|
}
|
||||||
|
|
||||||
|
// VirtIO queue, with a single buffer.
|
||||||
|
type virtioQueue struct {
|
||||||
|
buffers [1]struct {
|
||||||
|
address uint64
|
||||||
|
length uint32
|
||||||
|
flags uint16
|
||||||
|
next uint16
|
||||||
|
} // 16 bytes
|
||||||
|
|
||||||
|
available struct {
|
||||||
|
flags uint16
|
||||||
|
index uint16
|
||||||
|
ring [1]uint16
|
||||||
|
eventIndex uint16
|
||||||
|
} // 8 bytes
|
||||||
|
|
||||||
|
_ [4096 - 16*1 - 8*1]byte // padding (to align on a 4096 byte boundary)
|
||||||
|
|
||||||
|
used struct {
|
||||||
|
flags uint16
|
||||||
|
index volatile.Register16
|
||||||
|
ring [1]struct {
|
||||||
|
index uint32
|
||||||
|
length uint32
|
||||||
|
}
|
||||||
|
availEvent uint16
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func virtioFindDevice(deviceID uint32) *virtioDevice1 {
|
||||||
|
// On RISC-V, QEMU defines 8 VirtIO devices starting at 0x10001000 and
|
||||||
|
// repeating every 0x1000 bytes.
|
||||||
|
// The memory map can be seen in the QEMU source code:
|
||||||
|
// https://github.com/qemu/qemu/blob/master/hw/riscv/virt.c
|
||||||
|
for i := 0; i < 8; i++ {
|
||||||
|
dev := (*virtioDevice1)(unsafe.Pointer(uintptr(0x10001000 + i*0x1000)))
|
||||||
|
if dev.magic.Get() != 0x74726976 || dev.version.Get() != 1 || dev.deviceID.Get() != deviceID {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return dev
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// A VirtIO queue needs to be page-aligned.
|
||||||
|
//
|
||||||
|
//go:align 4096
|
||||||
|
var rngQueue virtioQueue
|
||||||
@@ -134,6 +134,10 @@ func Pipe() (r *File, w *File, err error) {
|
|||||||
return nil, nil, ErrNotImplemented
|
return nil, nil, ErrNotImplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Symlink(oldname, newname string) error {
|
||||||
|
return ErrNotImplemented
|
||||||
|
}
|
||||||
|
|
||||||
func Readlink(name string) (string, error) {
|
func Readlink(name string) (string, error) {
|
||||||
return "", ErrNotImplemented
|
return "", ErrNotImplemented
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
//go:build baremetal && (nrf || (stm32 && !(stm32f103 || stm32l0x1)) || (sam && atsamd51) || (sam && atsame5x) || esp32c3 || tkey)
|
//go:build baremetal && (nrf || (stm32 && !(stm32f103 || stm32l0x1)) || (sam && atsamd51) || (sam && atsame5x) || esp32c3 || tkey || (tinygo.riscv32 && virt))
|
||||||
|
|
||||||
// If you update the above build constraint, you'll probably also need to update
|
// If you update the above build constraint, you'll probably also need to update
|
||||||
// src/crypto/rand/rand_baremetal.go.
|
// src/crypto/rand/rand_baremetal.go.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
//go:build baremetal && !(nrf || (stm32 && !(stm32f103 || stm32l0x1)) || (sam && atsamd51) || (sam && atsame5x) || esp32c3 || tkey)
|
//go:build baremetal && !(nrf || (stm32 && !(stm32f103 || stm32l0x1)) || (sam && atsamd51) || (sam && atsame5x) || esp32c3 || tkey || (tinygo.riscv32 && virt))
|
||||||
|
|
||||||
package runtime
|
package runtime
|
||||||
|
|
||||||
|
|||||||
@@ -4,5 +4,5 @@
|
|||||||
"build-tags": ["virt", "qemu"],
|
"build-tags": ["virt", "qemu"],
|
||||||
"default-stack-size": 4096,
|
"default-stack-size": 4096,
|
||||||
"linkerscript": "targets/riscv-qemu.ld",
|
"linkerscript": "targets/riscv-qemu.ld",
|
||||||
"emulator": "qemu-system-riscv32 -machine virt -nographic -bios none -kernel {}"
|
"emulator": "qemu-system-riscv32 -machine virt -nographic -bios none -device virtio-rng-device -kernel {}"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
|
|
||||||
/* Memory map:
|
/* Memory map:
|
||||||
* https://github.com/qemu/qemu/blob/master/hw/riscv/virt.c
|
* https://github.com/qemu/qemu/blob/master/hw/riscv/virt.c
|
||||||
* RAM and flash are set to 1MB each. That should be enough for the foreseeable
|
* Looks like we can use any address starting from 0x80000000 (so 2GB of space).
|
||||||
* future. QEMU does not seem to limit the flash/RAM size and in fact doesn't
|
* However, using a large space slows down tests.
|
||||||
* seem to differentiate between it.
|
|
||||||
*/
|
*/
|
||||||
MEMORY
|
MEMORY
|
||||||
{
|
{
|
||||||
FLASH_TEXT (rw) : ORIGIN = 0x80000000, LENGTH = 0x100000
|
RAM (rwx) : ORIGIN = 0x80000000, LENGTH = 100M
|
||||||
RAM (xrw) : ORIGIN = 0x80100000, LENGTH = 0x100000
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
REGION_ALIAS("FLASH_TEXT", RAM)
|
||||||
|
|
||||||
_stack_size = 2K;
|
_stack_size = 2K;
|
||||||
|
|
||||||
INCLUDE "targets/riscv.ld"
|
INCLUDE "targets/riscv.ld"
|
||||||
|
|||||||
Reference in New Issue
Block a user