-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathxmm.c
167 lines (142 loc) · 4.44 KB
/
xmm.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <unistd.h>
#include <vmm/vmm.h>
#define ITER 100000
struct virtual_machine local_vm, *vm = &local_vm;
struct vmm_gpcore_init gpci;
unsigned long long *p512, *p1, *p2m;
unsigned long long stack[512];
void **my_retvals;
int nr_threads = 4;
static volatile int guestcount, hostcount;
static volatile int fucked;
static uint8_t guest[16];
static char *_ = "deadbeefbeefdead";
void hexdump(FILE *f, void *v, int length);
void store(uint8_t *x)
{
__asm__ __volatile__ ("movdqu %%xmm0, %[x]\n": [x] "=m" (*x));
}
void load(uint8_t *x)
{
__asm__ __volatile__ ("movdqu %[x], %%xmm0\n":: [x] "m" (*x));
}
void vmexit()
{
/*
* It seems to be hard to turn off printing sometimes.
* Just have it print a null. This also makes it easy to
* track vmcalls with strace (each vmcall is a write to 1).
*/
__asm__ __volatile__("xorw %di, %di\n\tvmcall\n\t");
}
static void vmcall(void *a)
{
load((uint8_t*)_);
while ((guestcount < ITER) && (! fucked)) {
store(guest);
/* hand code memcmp */
for(int i = 0; i < 16; i++)
if (_[i] != guest[i])
fucked++;
if (fucked)
store(guest);
vmexit();
guestcount++;
}
while(1);
}
void *page(void *addr)
{
void *v;
unsigned long flags = MAP_POPULATE | MAP_ANONYMOUS;
if (addr)
flags |= MAP_FIXED;
v = (void *)mmap(addr, 4096, PROT_READ | PROT_WRITE, flags, -1, 0);
fprintf(stderr, "Page: request %p, get %p\n", addr, v);
return v;
}
int main(int argc, char **argv)
{
extern bool parlib_wants_to_be_mcp;
int vmmflags = 0; // Disabled probably forever. VMM_VMCALL_PRINTF;
uint64_t entry = (uint64_t)vmcall, kerneladdress = (uint64_t)vmcall;
void *a_page;
struct vm_trapframe *vm_tf;
parlib_wants_to_be_mcp = FALSE;
/* sanity */
load((uint8_t*)_);
store(guest);
if (memcmp(_, guest, 16)){
printf("simple test failed: input:"); hexdump(stdout, (void*)_, 16); printf(":output:"); hexdump(stdout, guest, 16);printf(":\n");
exit(1);
}
printf("sanity test passed, output:"); hexdump(stdout, guest, 16); printf(":\n");
fprintf(stderr, "%p %p %p %p\n", (void *)PGSIZE, (void *)PGSHIFT, (void *)PML1_SHIFT,
(void *)PML1_PTE_REACH);
//Place mmap(Gan)
a_page = page((void *)0xfee00000);
memset(a_page, 0, 4096);
((uint32_t *)a_page)[0x30/4] = 0x01060015;
//((uint32_t *)a_page)[0x30/4] = 0xDEADBEEF;
gpci.posted_irq_desc = page(NULL);
gpci.vapic_addr = page(NULL);
gpci.apic_addr = page((void*)0xfee00000);
vm->nr_gpcs = 1;
vm->gpcis = &gpci;
vmm_init(vm, vmmflags);
p512 = page((void *)0x1000000);
p1 = page(p512+512);
p2m = page(p1+512);
/* Allocate 3 pages for page table pages: a page of 512 GiB
* PTEs with only one entry filled to point to a page of 1 GiB
* PTEs; a page of 1 GiB PTEs with only one entry filled to
* point to a page of 2 MiB PTEs; and a page of 2 MiB PTEs,
* only a subset of which will be filled. */
/* Set up a 1:1 ("identity") page mapping from guest virtual
* to guest physical using the (host virtual)
* `kerneladdress`. This mapping is used for only a short
* time, until the guest sets up its own page tables. Be aware
* that the values stored in the table are physical addresses.
* This is subtle and mistakes are easily disguised due to the
* identity mapping, so take care when manipulating these
* mappings. */
p512[PML4(kerneladdress)] = (uint64_t)p1 | PTE_KERN_RW;
p1[PML3(kerneladdress)] = (uint64_t)p2m | PTE_KERN_RW;
p1[PML3(kerneladdress)] = PTE_PS | PTE_KERN_RW;
for (uintptr_t i = 0; i < 1024*1024*1024; i += PML2_PTE_REACH) {
p2m[PML2(kerneladdress + i)] =
(uint64_t)(kerneladdress + i) | PTE_KERN_RW | PTE_PS;
}
vm_tf = gth_to_vmtf(vm->gths[0]);
vm_tf->tf_cr3 = (uint64_t) p512;
vm_tf->tf_rip = entry /*+ 4;*/;
vm_tf->tf_rsp = (uint64_t) (stack+511);
vm_tf->tf_rdi = (uint64_t) guestcount;
start_guest_thread(vm->gths[0]);
char *_ = "0xaaffeeffeeaabbcc";
uint8_t data[16];
load((uint8_t*)_);
while ((guestcount < ITER) && (! fucked)) {
load((uint8_t*)_);
hostcount++;
while(! (guestcount&1))
;
if (guestcount % 1000 == 0)
printf("%d guest iterations\n", guestcount);
if (hostcount % 100000 == 0) {
printf("%d host iterations\n", hostcount);
}
sleep(1);
}
if (fucked) {
printf("we're fucked after %d guest iterations, %d host iterations\n", guestcount, hostcount);
store(data);
printf("guest says: "); hexdump(stdout, guest, 16); printf("\n");
printf("host says: "); hexdump(stdout, data, 16); printf("\n");
}
return 0;
}