]> rtime.felk.cvut.cz Git - jailhouse.git/commitdiff
inmates: Add memory services to inmates framework
authorJan Kiszka <jan.kiszka@siemens.com>
Thu, 17 Jul 2014 15:18:21 +0000 (17:18 +0200)
committerJan Kiszka <jan.kiszka@siemens.com>
Mon, 21 Jul 2014 06:53:05 +0000 (08:53 +0200)
This adds a primitive memory allocator (without release) and a page
mapper (without unmap) to the inmates library. MMIO accessors are also
included. Those used for intercepted resources are encoded in assembly
to ensure that only supported instructions are used. With these
services, inmates can now access memory-mapped devices.

The allocator uses the lower memory starting from the first page.
Document this as well as the remaining memory layout.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
inmates/lib/x86/inmate.h
inmates/lib/x86/inmate.lds
inmates/lib/x86/mem.c [new file with mode: 0644]

index 38c5151a95b7a50e53d77a1b34d770125335412c..ff707f517aa3fcf4672cfe8c7132b16ab1958290 100644 (file)
@@ -10,6 +10,7 @@
  * the COPYING file in the top-level directory.
  */
 
+#define HEAP_BASE              0x000000
 #define FSEGMENT_BASE          0x0f0000
 #define COMM_REGION_BASE       0x100000
 
 #define NS_PER_MSEC            1000000UL
 #define NS_PER_SEC             1000000000UL
 
+#define PAGE_SIZE              (4 * 1024ULL)
+#ifdef __x86_64__
+#define HUGE_PAGE_SIZE         (2 * 1024 * 1024ULL)
+#else
+#define HUGE_PAGE_SIZE         (4 * 1024 * 1024ULL)
+#endif
+#define PAGE_MASK              (~(PAGE_SIZE - 1))
+#define HUGE_PAGE_MASK         (~(HUGE_PAGE_SIZE - 1))
+
 #define X2APIC_ID              0x802
 
 #ifndef __ASSEMBLY__
@@ -73,6 +83,51 @@ static inline u32 inl(u16 port)
        return v;
 }
 
+static inline u8 mmio_read8(void *address)
+{
+       return *(volatile u8 *)address;
+}
+
+static inline u16 mmio_read16(void *address)
+{
+       return *(volatile u16 *)address;
+}
+
+static inline u32 mmio_read32(void *address)
+{
+       u32 value;
+
+       /* assembly-encoded to match the hypervisor MMIO parser support */
+       asm volatile("movl (%1),%0" : "=r" (value) : "r" (address));
+       return value;
+}
+
+static inline u64 mmio_read64(void *address)
+{
+       return *(volatile u64 *)address;
+}
+
+static inline void mmio_write8(void *address, u8 value)
+{
+       *(volatile u8 *)address = value;
+}
+
+static inline void mmio_write16(void *address, u16 value)
+{
+       *(volatile u16 *)address = value;
+}
+
+static inline void mmio_write32(void *address, u32 value)
+{
+       /* assembly-encoded to match the hypervisor MMIO parser support */
+       asm volatile("movl %0,(%1)" : : "r" (value), "r" (address));
+}
+
+static inline void mmio_write64(void *address, u64 value)
+{
+       *(volatile u64 *)address = value;
+}
+
 static inline u64 read_msr(unsigned int msr)
 {
        u32 low, high;
@@ -113,4 +168,9 @@ void inmate_main(void);
 unsigned long pm_timer_read(void);
 unsigned long apic_timer_init(unsigned int vector);
 void apic_timer_set(unsigned long timeout_ns);
+
+enum map_type { MAP_CACHED, MAP_UNCACHED };
+
+void *alloc(unsigned long size, unsigned long align);
+void map_range(void *start, unsigned long size, enum map_type map_type);
 #endif
index 84d782d0d22c7af4c18afbd9271e3249159b303d..afd93758a69f723522b8fbb12308229c333b6075 100644 (file)
  * the COPYING file in the top-level directory.
  */
 
+/*
+ * Layout:
+ *  0x000000..        : heap (not configured here)
+ *          ..0x0e0000: stack
+ *  0x0e0000..0x0effff: bss
+ *  0x0f0000..0x0fffef: startup code, text, rodata, data
+ *  0x0ffff0..0x0fffff: startup code (boot address)
+ *  0x100000..0x100fff: communication region (not configured here)
+ */
 SECTIONS
 {
        /* 16-bit sections */
diff --git a/inmates/lib/x86/mem.c b/inmates/lib/x86/mem.c
new file mode 100644 (file)
index 0000000..79d49cc
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Jailhouse, a Linux-based partitioning hypervisor
+ *
+ * Copyright (c) Siemens AG, 2014
+ *
+ * Authors:
+ *  Jan Kiszka <jan.kiszka@siemens.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ */
+
+#include <inmate.h>
+
+#define PG_PRESENT     0x01
+#define PG_RW          0x02
+#define PG_PS          0x80
+#define PG_PCD         0x10
+
+static unsigned long heap_pos = HEAP_BASE;
+
+void *alloc(unsigned long size, unsigned long align)
+{
+       unsigned long base = (heap_pos + align - 1) & ~(align - 1);
+
+       heap_pos = base + size;
+       return (void *)base;
+}
+
+void map_range(void *start, unsigned long size, enum map_type map_type)
+{
+       unsigned long pt_addr, *pt_entry, *pt;
+       unsigned long vaddr = (unsigned long)start;
+
+       asm volatile("mov %%cr3,%0" : "=r" (pt_addr));
+
+       size += HUGE_PAGE_SIZE - 1;
+       size &= HUGE_PAGE_MASK;
+       while (size > 0) {
+#ifdef __x86_64__
+               pt_addr &= PAGE_MASK;
+               pt = (unsigned long *)pt_addr;
+
+               pt_entry = &pt[(vaddr >> 39) & 0x1ff];
+               if (*pt_entry & PG_PRESENT) {
+                       pt = (unsigned long *)(*pt_entry & PAGE_MASK);
+               } else {
+                       pt = alloc(PAGE_SIZE, PAGE_SIZE);
+                       *pt_entry = (unsigned long)pt | PG_RW | PG_PRESENT;
+               }
+
+               pt_entry = &pt[(vaddr >> 30) & 0x1ff];
+               if (*pt_entry & PG_PRESENT) {
+                       pt = (unsigned long *)(*pt_entry & PAGE_MASK);
+               } else {
+                       pt = alloc(PAGE_SIZE, PAGE_SIZE);
+                       *pt_entry = (unsigned long)pt | PG_RW | PG_PRESENT;
+               }
+
+               pt_entry = &pt[(vaddr >> 21) & 0x1ff];
+               *pt_entry = (vaddr & HUGE_PAGE_MASK) |
+                       (map_type == MAP_UNCACHED ? PG_PCD : 0) |
+                       PG_PS | PG_RW | PG_PRESENT;
+#else
+#error not yet implemented
+#endif
+               size -= HUGE_PAGE_SIZE;
+               vaddr += HUGE_PAGE_SIZE;
+       }
+}