]> rtime.felk.cvut.cz Git - jailhouse.git/blob - inmates/lib/x86/mem.c
inmates: Add memory services to inmates framework
[jailhouse.git] / inmates / lib / x86 / mem.c
1 /*
2  * Jailhouse, a Linux-based partitioning hypervisor
3  *
4  * Copyright (c) Siemens AG, 2014
5  *
6  * Authors:
7  *  Jan Kiszka <jan.kiszka@siemens.com>
8  *
9  * This work is licensed under the terms of the GNU GPL, version 2.  See
10  * the COPYING file in the top-level directory.
11  */
12
13 #include <inmate.h>
14
15 #define PG_PRESENT      0x01
16 #define PG_RW           0x02
17 #define PG_PS           0x80
18 #define PG_PCD          0x10
19
20 static unsigned long heap_pos = HEAP_BASE;
21
22 void *alloc(unsigned long size, unsigned long align)
23 {
24         unsigned long base = (heap_pos + align - 1) & ~(align - 1);
25
26         heap_pos = base + size;
27         return (void *)base;
28 }
29
30 void map_range(void *start, unsigned long size, enum map_type map_type)
31 {
32         unsigned long pt_addr, *pt_entry, *pt;
33         unsigned long vaddr = (unsigned long)start;
34
35         asm volatile("mov %%cr3,%0" : "=r" (pt_addr));
36
37         size += HUGE_PAGE_SIZE - 1;
38         size &= HUGE_PAGE_MASK;
39         while (size > 0) {
40 #ifdef __x86_64__
41                 pt_addr &= PAGE_MASK;
42                 pt = (unsigned long *)pt_addr;
43
44                 pt_entry = &pt[(vaddr >> 39) & 0x1ff];
45                 if (*pt_entry & PG_PRESENT) {
46                         pt = (unsigned long *)(*pt_entry & PAGE_MASK);
47                 } else {
48                         pt = alloc(PAGE_SIZE, PAGE_SIZE);
49                         *pt_entry = (unsigned long)pt | PG_RW | PG_PRESENT;
50                 }
51
52                 pt_entry = &pt[(vaddr >> 30) & 0x1ff];
53                 if (*pt_entry & PG_PRESENT) {
54                         pt = (unsigned long *)(*pt_entry & PAGE_MASK);
55                 } else {
56                         pt = alloc(PAGE_SIZE, PAGE_SIZE);
57                         *pt_entry = (unsigned long)pt | PG_RW | PG_PRESENT;
58                 }
59
60                 pt_entry = &pt[(vaddr >> 21) & 0x1ff];
61                 *pt_entry = (vaddr & HUGE_PAGE_MASK) |
62                         (map_type == MAP_UNCACHED ? PG_PCD : 0) |
63                         PG_PS | PG_RW | PG_PRESENT;
64 #else
65 #error not yet implemented
66 #endif
67                 size -= HUGE_PAGE_SIZE;
68                 vaddr += HUGE_PAGE_SIZE;
69         }
70 }