diff options
Diffstat (limited to 'lib/genode')
-rw-r--r-- | lib/genode/alloc.nim | 119 | ||||
-rw-r--r-- | lib/genode/constructibles.nim | 21 | ||||
-rw-r--r-- | lib/genode/entrypoints.nim | 22 | ||||
-rw-r--r-- | lib/genode/env.nim | 29 | ||||
-rw-r--r-- | lib/genode/signals.nim | 77 |
5 files changed, 268 insertions, 0 deletions
diff --git a/lib/genode/alloc.nim b/lib/genode/alloc.nim new file mode 100644 index 000000000..24fb9954e --- /dev/null +++ b/lib/genode/alloc.nim @@ -0,0 +1,119 @@ +# +# +# Nim's Runtime Library +# (c) Copyright 2017 Emery Hemingway +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +# Low level dataspace allocator for Genode. +# For interacting with dataspaces outside of the +# standard library see the Genode Nimble package. + +when not defined(genode): + {.error: "Genode only module".} + +when not declared(GenodeEnv): + import genode/env + +type RamDataspaceCapability {. + importcpp: "Genode::Ram_dataspace_capability", pure.} = object + +type + Map = object + attachment: pointer + size: int + ds: RamDataspaceCapability + + SlabMeta = object + next: ptr MapSlab + ds: RamDataspaceCapability + + MapSlab = object + meta: SlabMeta + maps: array[1,Map] + +const SlabBackendSize = 4096 + +proc ramAvail(env: GenodeEnv): int {. + importcpp: "#->pd().avail_ram().value".} + ## Return number of bytes available for allocation. + +proc capsAvail(env: GenodeEnv): int {. + importcpp: "#->pd().avail_caps().value".} + ## Return the number of available capabilities. + ## Each dataspace allocation consumes a capability. + +proc allocDataspace(env: GenodeEnv; size: int): RamDataspaceCapability {. + importcpp: "#->pd().alloc(@)".} + ## Allocate a dataspace and its capability. + +proc attachDataspace(env: GenodeEnv; ds: RamDataspaceCapability): pointer {. + importcpp: "#->rm().attach(@)".} + ## Attach a dataspace into the component address-space. + +proc detachAddress(env: GenodeEnv; p: pointer) {. + importcpp: "#->rm().detach(@)".} + ## Detach a dataspace from the component address-space. + +proc freeDataspace(env: GenodeEnv; ds: RamDataspaceCapability) {. + importcpp: "#->pd().free(@)".} + ## Free a dataspace. + +proc newMapSlab(): ptr MapSlab = + let + ds = runtimeEnv.allocDataspace SlabBackendSize + p = runtimeEnv.attachDataspace ds + result = cast[ptr MapSlab](p) + result.meta.ds = ds + +iterator items(s: ptr MapSlab): ptr Map = + let mapCount = (SlabBackendSize - sizeof(SlabMeta)) div sizeof(Map) + for i in 0 ..< mapCount: + yield s.maps[i].addr + +var slabs: ptr MapSlab + +proc osAllocPages(size: int): pointer = + if slabs.isNil: + slabs = newMapSlab() + var + slab = slabs + map: ptr Map + let mapCount = (SlabBackendSize - sizeof(SlabMeta)) div sizeof(Map) + block findFreeMap: + while true: + # lookup first free spot in slabs + for m in slab.items: + if m.attachment.isNil: + map = m + break findFreeMap + if slab.meta.next.isNil: + slab.meta.next = newMapSlab() + # tack a new slab on the tail + slab = slab.meta.next + # move to next slab in linked list + map.ds = runtimeEnv.allocDataspace size + map.size = size + map.attachment = runtimeEnv.attachDataspace map.ds + result = map.attachment + +proc osTryAllocPages(size: int): pointer = + if runtimeEnv.ramAvail() >= size and runtimeEnv.capsAvail() > 4: + result = osAllocPages size + +proc osDeallocPages(p: pointer; size: int) = + var slab = slabs + while not slab.isNil: + # lookup first free spot in slabs + for m in slab.items: + if m.attachment == p: + if m.size != size: + echo "cannot partially detach dataspace" + rawQuit -1 + runtimeEnv.detachAddress m.attachment + runtimeEnv.freeDataspace m.ds + m[] = Map() + return + slab = slab.meta.next diff --git a/lib/genode/constructibles.nim b/lib/genode/constructibles.nim new file mode 100644 index 000000000..3a4a646e0 --- /dev/null +++ b/lib/genode/constructibles.nim @@ -0,0 +1,21 @@ +# +# +# Nim's Runtime Library +# (c) Copyright 2022 Emery Hemingway +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +type Constructible*[T] {. + importcpp: "Genode::Constructible", + header: "<util/reconstructible.h>", byref, pure.} = object + +proc construct*[T](x: Constructible[T]) {.importcpp.} + ## Construct a constructible C++ object. + +proc destruct*[T](x: Constructible[T]) {.importcpp.} + ## Destruct a constructible C++ object. + +proc constructed*[T](x: Constructible[T]): bool {.importcpp.} + ## Test if an object is constructed. diff --git a/lib/genode/entrypoints.nim b/lib/genode/entrypoints.nim new file mode 100644 index 000000000..0bf5e0e0e --- /dev/null +++ b/lib/genode/entrypoints.nim @@ -0,0 +1,22 @@ +# +# +# Nim's Runtime Library +# (c) Copyright 2022 Emery Hemingway +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +## See `Genode Foundations - Entrypoint <https://genode.org/documentation/genode-foundations/21.05/functional_specification/Entrypoint.html>` +## for a description of Entrypoints. + +type + EntrypointObj {. + importcpp: "Genode::Entrypoint", + header: "<base/entrypoint.h>", + pure.} = object + Entrypoint* = ptr EntrypointObj + ## Opaque Entrypoint object. + +proc ep*(env: GenodeEnv): Entrypoint {.importcpp: "(&#->ep())".} + ## Access the entrypoint associated with `env`. diff --git a/lib/genode/env.nim b/lib/genode/env.nim new file mode 100644 index 000000000..babe2a8a0 --- /dev/null +++ b/lib/genode/env.nim @@ -0,0 +1,29 @@ +# +# +# Nim's Runtime Library +# (c) Copyright 2018 Emery Hemingway +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +# +# This file contains the minimum required definitions +# for interacting with the initial Genode environment. +# It is reserved for use only within the standard +# library. See `componentConstructHook` in the system +# module for accessing the Genode environment after the +# standard library has finished initializating. +# + +when not defined(genode): + {.error: "Genode only module".} + +type + GenodeEnvObj* {.importcpp: "Genode::Env", header: "<base/env.h>", pure.} = object + GenodeEnvPtr* = ptr GenodeEnvObj + +const runtimeEnvSym* = "nim_runtime_env" + +when not defined(nimscript): + var runtimeEnv* {.importcpp: runtimeEnvSym.}: GenodeEnvPtr diff --git a/lib/genode/signals.nim b/lib/genode/signals.nim new file mode 100644 index 000000000..7d1875730 --- /dev/null +++ b/lib/genode/signals.nim @@ -0,0 +1,77 @@ +# +# +# Nim's Runtime Library +# (c) Copyright 2022 Emery Hemingway +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +## See `Genode Foundations - Asynchronous notifications <https://genode.org/documentation/genode-foundations/21.05/architecture/Inter-component_communication.html#Asynchronous_notifications>` +## for a description of Genode signals. + +when not defined(genode) or defined(nimdoc): + {.error: "Genode only module".} + +import ./entrypoints, ./constructibles + +export ep # Entrypoint accessor on GenodeEnv + +type + SignalContextCapability* {. + importcpp: "Genode::Signal_context_capability", + header: "<base/signal.h>", pure.} = object + ## Capability to an asynchronous signal context. + +proc isValid*(cap: SignalContextCapability): bool {.importcpp: "#.valid()".} + ## Call the Genode core to check if this `SignalContextCapability` is valid. + # TODO: RpcEffect + +type + HandlerProc = proc () {.closure, gcsafe.} + + SignalHandlerBase {. + importcpp: "Nim::SignalHandler", + header: "genode_cpp/signals.h", + pure.} = object + + SignalHandlerCpp = Constructible[SignalHandlerBase] + + SignalHandlerObj = object + cpp: SignalHandlerCpp + cb: HandlerProc + ## Signal handling procedure called during dispatch. + + SignalHandler* = ref SignalHandlerObj + ## Nim object enclosing a Genode signal handler. + +proc construct(cpp: SignalHandlerCpp; ep: Entrypoint; sh: SignalHandler) {.importcpp.} + +proc cap(cpp: SignalHandlerCpp): SignalContextCapability {.importcpp: "#->cap()".} + +proc newSignalHandler*(ep: Entrypoint; cb: HandlerProc): SignalHandler = + ## Create a new signal handler. A label is recommended for + ## debugging purposes. A signal handler will not be garbage + ## collected until after it has been dissolved. + result = SignalHandler(cb: cb) + result.cpp.construct(ep, result) + GCref result + +proc dissolve*(sig: SignalHandler) = + ## Dissolve signal dispatcher from entrypoint. + # TODO: =destroy? + destruct sig.cpp + sig.cb = nil # lose the callback + GCunref sig + +proc cap*(sig: SignalHandler): SignalContextCapability = + ## Signal context capability. Can be delegated to external components. + sig.cpp.cap + +proc submit*(cap: SignalContextCapability) {. + importcpp: "Genode::Signal_transmitter(#).submit()".} + ## Submit a signal to a context capability. + +proc nimHandleSignal(p: pointer) {.exportc.} = + ## C symbol invoked by entrypoint during signal dispatch. + cast[SignalHandler](p).cb() |