From d101b4c7ea4a44b6a1f24372db785d97a2175a24 Mon Sep 17 00:00:00 2001 From: Calascibetta Romain Date: Fri, 6 Dec 2024 14:45:17 +0100 Subject: [PATCH] A simple test with a block device --- lib/miou_solo5.ml | 10 ++++++---- lib/miou_solo5.mli | 1 + lib/stubs.solo5.c | 6 +++--- test/block.json | 5 +++++ test/block.ml | 24 ++++++++++++++++++++++++ test/dune | 16 +++++++++++++++- test/run.t | 16 ++++++++++++++++ test/simple.txt | Bin 0 -> 8192 bytes 8 files changed, 70 insertions(+), 8 deletions(-) create mode 100644 test/block.json create mode 100644 test/block.ml create mode 100644 test/simple.txt diff --git a/lib/miou_solo5.ml b/lib/miou_solo5.ml index 17cc2bd..f4ed320 100644 --- a/lib/miou_solo5.ml +++ b/lib/miou_solo5.ml @@ -49,7 +49,7 @@ external miou_solo5_net_acquire : -> bytes -> bytes -> bytes - -> (int[@untagged]) = "unimplemented" "miou_solo5_net_acquire" + -> int = "unimplemented" "miou_solo5_net_acquire" [@@noalloc] external miou_solo5_net_read : @@ -58,7 +58,7 @@ external miou_solo5_net_read : -> (int[@untagged]) -> (int[@untagged]) -> bytes - -> (int[@untagged]) = "unimplemented" "miou_solo5_net_read" + -> int = "unimplemented" "miou_solo5_net_read" [@@noalloc] external miou_solo5_net_write : @@ -74,7 +74,7 @@ external miou_solo5_block_acquire : -> bytes -> bytes -> bytes - -> (int[@untagged]) = "unimplemented" "miou_solo5_block_acquire" + -> int = "unimplemented" "miou_solo5_block_acquire" [@@noalloc] external miou_solo5_block_read : @@ -102,6 +102,8 @@ let error_msgf fmt = Format.kasprintf (fun msg -> Error (`Msg msg)) fmt module Block_direct = struct type t = { handle: int; pagesize: int } + let pagesize { pagesize; _ } = pagesize + let connect name = let handle = Bytes.make 8 '\000' in let _len = Bytes.make 8 '\000' in @@ -112,7 +114,7 @@ module Block_direct = struct let _len = Int64.to_int (Bytes.get_int64_ne _len 0) in let pagesize = Int64.to_int (Bytes.get_int64_ne pagesize 0) in Ok { handle; pagesize } - | _ -> error_msgf "Impossible to connect the block-device %s" name + | errno -> error_msgf "Impossible to connect the block-device %s (%d)" name errno let unsafe_read t ~off bstr = match miou_solo5_block_read t.handle off t.pagesize bstr with diff --git a/lib/miou_solo5.mli b/lib/miou_solo5.mli index 1f6c0c6..b1f4147 100644 --- a/lib/miou_solo5.mli +++ b/lib/miou_solo5.mli @@ -144,6 +144,7 @@ end module Block : sig type t + val pagesize : t -> int val atomic_read : t -> off:int -> bigstring -> unit val atomic_write : t -> off:int -> bigstring -> unit val read : t -> off:int -> bigstring -> unit diff --git a/lib/stubs.solo5.c b/lib/stubs.solo5.c index ee9b07d..a92a491 100644 --- a/lib/stubs.solo5.c +++ b/lib/stubs.solo5.c @@ -22,7 +22,7 @@ extern void caml_leave_blocking_section(void); * solo5_handle_set_t, which can only contain file-descriptors with a value * between 0 and 63. */ -intnat miou_solo5_block_acquire(value vname, value vhandle, value vlen, value vpage) { +value miou_solo5_block_acquire(value vname, value vhandle, value vlen, value vpage) { CAMLparam4(vname, vhandle, vlen, vpage); solo5_result_t result; solo5_handle_t handle; @@ -59,7 +59,7 @@ intnat miou_solo5_block_write(intnat fd, intnat off, intnat len, value vbstr) { return result; } -intnat miou_solo5_net_acquire(value vname, value vhandle, value vmac, value vmtu) { +value miou_solo5_net_acquire(value vname, value vhandle, value vmac, value vmtu) { CAMLparam3(vname, vmac, vmtu); solo5_result_t result; solo5_handle_t handle; @@ -82,7 +82,7 @@ intnat miou_solo5_net_acquire(value vname, value vhandle, value vmac, value vmtu * small buffer and, on the OCaml side, we just need to read it. It's a bit * like the poor man's C-style reference passage in OCaml. */ -intnat miou_solo5_net_read(intnat fd, intnat off, intnat len, value vread_size, +value miou_solo5_net_read(intnat fd, intnat off, intnat len, value vread_size, value vbstr) { CAMLparam1(vread_size); solo5_handle_t handle = fd; diff --git a/test/block.json b/test/block.json new file mode 100644 index 0000000..ce3ba2d --- /dev/null +++ b/test/block.json @@ -0,0 +1,5 @@ +{ + "type": "solo5.manifest", + "version": 1, + "devices": [ { "name": "simple", "type": "BLOCK_BASIC" } ] +} diff --git a/test/block.ml b/test/block.ml new file mode 100644 index 0000000..f890798 --- /dev/null +++ b/test/block.ml @@ -0,0 +1,24 @@ +external unsafe_get_char : Miou_solo5.bigstring -> int -> char = "%caml_ba_ref_1" + +let bigstring_to_string v = + let len = Bigarray.Array1.dim v in + let res = Bytes.create len in + for i = 0 to len - 1 do + Bytes.set res i (unsafe_get_char v i) + done; + Bytes.unsafe_to_string res + +let () = Miou_solo5.(run [ block "simple" ]) @@ fun blk () -> + let pagesize = Miou_solo5.Block.pagesize blk in + let bstr = Bigarray.(Array1.create char c_layout pagesize) in + let prm = Miou.async @@ fun () -> + Miou_solo5.Block.atomic_read blk ~off:0 bstr; + let str = bigstring_to_string bstr in + let hash = Digest.string str in + Fmt.pr "%08x: %s\n%!" 0 (Digest.to_hex hash) + in + Miou_solo5.Block.atomic_read blk ~off:pagesize bstr; + let str = bigstring_to_string bstr in + let hash = Digest.string str in + Fmt.pr "%08x: %s\n%!" pagesize (Digest.to_hex hash); + Miou.await_exn prm diff --git a/test/dune b/test/dune index ade399d..dc1b315 100644 --- a/test/dune +++ b/test/dune @@ -16,6 +16,15 @@ (libraries miou-solo5) (foreign_stubs (language c) (names manifest.schedule))) +(executable + (name block) + (modules block) + (modes native) + (link_flags :standard -cclib "-z solo5-abi=hvt") + (enabled_if (= %{context_name} "solo5")) + (libraries miou-solo5 fmt hxd.core hxd.string) + (foreign_stubs (language c) (names manifest.block))) + (rule (targets manifest.sleep.c) (deps none.json) @@ -26,6 +35,11 @@ (deps none.json) (action (run solo5-elftool gen-manifest none.json manifest.schedule.c))) +(rule + (targets manifest.block.c) + (deps block.json) + (action (run solo5-elftool gen-manifest block.json manifest.block.c))) + (cram (enabled_if (= %{context_name} "solo5")) - (deps sleep.exe schedule.exe)) + (deps sleep.exe schedule.exe block.exe simple.txt)) diff --git a/test/run.t b/test/run.t index 02a933f..0e1516c 100644 --- a/test/run.t +++ b/test/run.t @@ -29,3 +29,19 @@ Tests some simple unikernels Hello World Solo5: solo5_exit(0) called + $ chmod +w simple.txt + $ solo5-hvt-debug --block:simple=simple.txt --block-sector-size:simple=512 block.exe + | ___| + __| _ \ | _ \ __ \ + \__ \ ( | | ( | ) | + ____/\___/ _|\___/____/ + Solo5: Bindings version v0.9.0 + Solo5: Memory map: 512 MB addressable: + Solo5: reserved @ (0x0 - 0xfffff) + Solo5: text @ (0x100000 - 0x1c5fff) + Solo5: rodata @ (0x1c6000 - 0x1f7fff) + Solo5: data @ (0x1f8000 - 0x267fff) + Solo5: heap >= 0x268000 < stack < 0x20000000 + 00000200: 5e00b6c8f387deac083b9718e08a361b + 00000000: 94a3b2375dd8aa75e3d2cdef54179909 + Solo5: solo5_exit(0) called diff --git a/test/simple.txt b/test/simple.txt new file mode 100644 index 0000000000000000000000000000000000000000..47966a0bdcda7c77de92245c668550d503f2705b GIT binary patch literal 8192 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

gkj#^&^2p| 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 literal 0 HcmV?d00001