summary refs log tree commit diff stats
path: root/lib/genode
diff options
context:
space:
mode:
authorEmery Hemingway <emery@vfemail.net>2018-05-17 12:56:18 +0200
committerEmery Hemingway <emery@vfemail.net>2018-06-07 07:21:20 +0200
commit22f714585b943d0b2457c66a78917113072f4503 (patch)
treef346be91bab4f267527043057ec3a5c5276eb7af /lib/genode
parentbf394ed1a1d27d8d38d4bc386946e3442736cd75 (diff)
downloadNim-22f714585b943d0b2457c66a78917113072f4503.tar.gz
Native access to Genode environment
Add a 'GenodeEnv' type and a 'componentConstructHook' to the system
module. The 'componentConstructHook' allows for detection of POSIX style
programs that exit implicitly or native Genode components that
initialize to serve RPC requests and OS signals.

This hook takes a 'GenodeEnv' argument so that the environment interface
is passed cleanly to application code after globals are initialized.
This is an typed pointer to a C++ object, procedures for accessing the
environment will be available from a Nimble library and not included in
the standard library.

The standard library has an internal pointer to the environment object
but this is not for external use, the undocumented global environment
pointer has been removed.
Diffstat (limited to 'lib/genode')
-rw-r--r--lib/genode/alloc.nim119
-rw-r--r--lib/genode/env.nim29
2 files changed, 148 insertions, 0 deletions
diff --git a/lib/genode/alloc.nim b/lib/genode/alloc.nim
new file mode 100644
index 000000000..52dc1c32c
--- /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):
+  include genode/env
+
+type DataspaceCapability {.
+  importcpp: "Genode::Dataspace_capability", pure.} = object
+
+type
+  Map = object
+    attachment: pointer
+    size: int
+    ds: DataspaceCapability
+
+  SlabMeta = object
+    next: ptr MapSlab
+    ds: DataspaceCapability
+
+  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): DataspaceCapability {.
+  importcpp: "#->pd().alloc(@)".}
+  ## Allocate a dataspace and its capability.
+
+proc attachDataspace(env: GenodeEnv; ds: DataspaceCapability): 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: DataspaceCapability) {.
+  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"
+          quit -1
+        runtimeEnv.detachAddress m.attachment
+        runtimeEnv.freeDataspace m.ds
+        m[] = Map()
+        return
+    slab = slab.meta.next
diff --git a/lib/genode/env.nim b/lib/genode/env.nim
new file mode 100644
index 000000000..2b180d1b3
--- /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 include".}
+
+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