* 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__
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;
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
* 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 */
--- /dev/null
+/*
+ * 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;
+ }
+}