Factor out the kernel loading function. Add kernel_min, kernel_max addresses.
[virt-mem.git] / lib / virt_mem_types.ml
index 071f6de..c3da932 100644 (file)
@@ -22,6 +22,7 @@
 
 module D = Libvirt.Domain
 
+open Virt_mem_utils
 open Virt_mem_mmap
 
 type ksym = string
@@ -33,6 +34,8 @@ type image0 = {
   domname : string;
   arch : Virt_mem_utils.architecture;
   mem : ([`Wordsize], [`Endian], [`HasMapping]) Virt_mem_mmap.t;
+  kernel_min : addr;
+  kernel_max : addr;
 }
 
 type image1 =
@@ -52,3 +55,67 @@ and utsname = {
   machine : string;
   domainname : string;
 }
+
+(* This is the maximum we can download in one go over the libvirt
+ * remote connection.
+ *
+ * XXX Should have a 'D.max_peek' function.
+ *)
+let max_memory_peek = 65536
+
+type load_memory_error =
+  | AddressOutOfRange
+  | DomIsNull
+
+exception LoadMemoryError of load_memory_error * string
+
+let _load_memory mem dom start size =
+  let str = String.create size in
+  let rec loop i =
+    let remaining = size - i in
+    if remaining > 0 then (
+      let size = min remaining max_memory_peek in
+      D.memory_peek dom [D.Virtual] (start +^ Int64.of_int i) size str i;
+      loop (i + size)
+    )
+  in
+  loop 0;
+
+  add_string mem str start
+
+let load_static_memory ~dom ~domname ~arch ~wordsize ~endian
+    ~kernel_min ~kernel_max start size =
+  if start < kernel_min then
+    raise (LoadMemoryError (AddressOutOfRange,
+                           "load_memory: start < kernel_min"))
+  else if start +^ Int64.of_int size > kernel_max then
+    raise (LoadMemoryError (AddressOutOfRange,
+                           "load_memory: start+size > kernel_max"))
+  else (
+    let mem = Virt_mem_mmap.create () in
+    let mem = Virt_mem_mmap.set_wordsize mem wordsize in
+    let mem = Virt_mem_mmap.set_endian mem endian in
+
+    let mem = _load_memory mem dom start size in
+
+    { dom = Some dom; domname = domname; mem = mem; arch = arch;
+      kernel_min = kernel_min; kernel_max = kernel_max }
+  )
+
+let load_memory ({ dom = dom; mem = mem; kernel_min = kernel_min;
+                  kernel_max = kernel_max } as image) start size =
+  if start < kernel_min then
+    raise (LoadMemoryError (AddressOutOfRange,
+                           "load_memory: start < kernel_min"))
+  else if start +^ Int64.of_int size > kernel_max then
+    raise (LoadMemoryError (AddressOutOfRange,
+                           "load_memory: start+size > kernel_max"))
+  else if is_mapped_range mem start size then image
+  else (
+    match dom with
+    | None ->
+       raise (LoadMemoryError (DomIsNull, "load_memory: dom = None"))
+    | Some dom ->
+       let mem = _load_memory mem dom start size in
+       { image with mem = mem }
+  )