Adding vmexits to proc.
[akaros.git] / tests / vmm / vmmcpkernel.c
1 #include <stdio.h> 
2 #include <pthread.h>
3 #include <sys/types.h>
4 #include <sys/stat.h>
5 #include <fcntl.h>
6 #include <parlib/arch/arch.h>
7 #include <unistd.h>
8 #include <errno.h>
9 #include <dirent.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <ros/syscall.h>
13 #include <sys/mman.h>
14
15 /* this test will run the "kernel" in the negative address space. We hope. */
16 int *mmap_blob;
17 unsigned long long stack[1024];
18 volatile int shared = 0;
19 int mcp = 1;
20 #define V(x, t) (*((volatile t*)(x)))
21
22 uint8_t _kernel[64*1048576];
23
24 void *fail(void*arg)
25 {
26
27         __asm__ __volatile__(
28                         "MOVl $0xc0000082, %ecx\nrdmsr\naddl $1, %eax\nwrmsr\n"
29                         "MOVl $0xc0000100, %ecx\nrdmsr\naddl $1, %eax\nwrmsr\n"
30                         "MOVl $0xc0000101, %ecx\nrdmsr\naddl $1, %eax\nwrmsr\n"
31                         "MOVl $0xc0000102, %ecx\nrdmsr\naddl $1, %eax\nwrmsr\n"
32                         "mov $0x30, %rdi\nvmcall\nhlt\n");
33         *mmap_blob = 1337;
34         if (mcp)
35         while (V(&shared, int) < 31) {
36                 if (! (V(&shared, int) & 1))
37                         V(&shared, int) = V(&shared, int) + 1;
38 //              cpu_relax();
39         }
40         V(&shared, int) = 55;
41
42         __asm__ __volatile__("vmcall\n");
43         __asm__ __volatile__("mov $0xdeadbeef, %rbx; mov 5, %rax\n");   
44 }
45
46 unsigned long long *p512, *p1, *p2m;
47
48 void *talk_thread(void *arg)
49 {
50         printf("talk thread ..\n");
51         for(; V(&shared, int) < 32; ){
52                 if (V(&shared, int) & 1) {
53                         printf("shared %d\n", V(&shared, int) );
54                         V(&shared, int) = V(&shared, int) + 1;
55                 }
56                 cpu_relax();
57         }
58         printf("All done, read %d\n", *mmap_blob);
59         return NULL;
60 }
61
62 pthread_t *my_threads;
63 void **my_retvals;
64 int nr_threads = 2;
65
66 int main(int argc, char **argv)
67 {
68         int nr_gpcs = 1;
69         int fd = open("#cons/sysctl", O_RDWR), ret;
70         void * x;
71         static char cmd[512];
72         /* kernel has to be in the range 16M to 64M for now. */
73         // mmap is not working for us at present.
74         if ((uint64_t)_kernel > 16*1048576) {
75                 printf("kernel array is above 16M, sucks\n");
76                 exit(1);
77         }
78
79         if (fd < 0) {
80                 perror("#cons/sysctl");
81                 exit(1);
82         }
83         if (ros_syscall(SYS_setup_vmm, nr_gpcs, 0, 0, 0, 0, 0) != nr_gpcs) {
84                 perror("Guest pcore setup failed");
85                 exit(1);
86         }
87         /* blob that is faulted in from the EPT first.  we need this to be in low
88          * memory (not above the normal mmap_break), so the EPT can look it up.
89          * Note that we won't get 4096.  The min is 1MB now, and ld is there. */
90         mmap_blob = mmap((int*)4096, PGSIZE, PROT_READ | PROT_WRITE,
91                          MAP_ANONYMOUS, -1, 0);
92         if (mmap_blob == MAP_FAILED) {
93                 perror("Unable to mmap");
94                 exit(1);
95         }
96
97         mcp = 1; //argc - 1;
98         if (mcp) {
99                 my_threads = malloc(sizeof(pthread_t) * nr_threads);
100                 my_retvals = malloc(sizeof(void*) * nr_threads);
101                 if (!(my_retvals && my_threads))
102                         perror("Init threads/malloc");
103
104                 pthread_can_vcore_request(FALSE);       /* 2LS won't manage vcores */
105                 pthread_need_tls(FALSE);
106                 pthread_mcp_init();                                     /* gives us one vcore */
107                 vcore_request(nr_threads - 1);          /* ghetto incremental interface */
108                 for (int i = 0; i < nr_threads; i++) {
109                         x = __procinfo.vcoremap;
110                         printf("%p\n", __procinfo.vcoremap);
111                         printf("Vcore %d mapped to pcore %d\n", i,
112                                 __procinfo.vcoremap[i].pcoreid);
113                 }
114         }
115
116         if (mcp) {
117                 if (pthread_create(&my_threads[0], NULL, &talk_thread, NULL))
118                         perror("pth_create failed");
119 //              if (pthread_create(&my_threads[1], NULL, &fail, NULL))
120 //                      perror("pth_create failed");
121         }
122         printf("threads started\n");
123
124         if (0) for (int i = 0; i < nr_threads-1; i++) {
125                 int ret;
126                 if (pthread_join(my_threads[i], &my_retvals[i]))
127                         perror("pth_join failed");
128                 printf("%d %d\n", i, ret);
129         }
130         
131
132         ret = syscall(33, 1);
133         if (ret < 0) {
134                 perror("vm setup");
135                 exit(1);
136         }
137         ret = posix_memalign((void **)&p512, 4096, 3*4096);
138         printf("memalign is %p\n", p512);
139         if (ret) {
140                 perror("ptp alloc");
141                 exit(1);
142         }
143         p1 = &p512[512];
144         p2m = &p512[1024];
145         uint64_t kernbase = 0; //0xffffffff80000000;
146         p512[PML4(kernbase)] = (unsigned long long)p1 | 7;
147         p1[PML3(kernbase)] = /*0x87; */(unsigned long long)p2m | 7;
148 #define _2MiB (0x200000)
149         int i;
150         for (i = 0; i < 512; i++) {
151                 p2m[PML2(kernbase + i * _2MiB)] = 0x87 | i * _2MiB;
152         }
153
154         kernbase >>= (0+12);
155         kernbase <<= (0 + 12);
156         uint64_t entry = kernbase + (uint64_t) fail;
157         uint8_t *kernel = (void *)(16*1048576);
158         uint8_t program[] = {0x0f, 0x1, 0xc1, 0xeb, 0xfe};
159         printf("memmove(%p, %p, %d\n", kernel, fail, 4096);
160         memmove(kernel, fail, 4096);
161         entry = (uint64_t)kernel;
162         printf("kernbase for pml4 is 0x%llx and entry is %llx\n", kernbase, entry);
163         printf("p512 %p p512[0] is 0x%lx p1 %p p1[0] is 0x%x\n", p512, p512[0], p1, p1[0]);
164         sprintf(cmd, "V 0x%llx 0x%llx 0x%llx", entry, (unsigned long long) &stack[1024], (unsigned long long) p512);
165         printf("Writing command :%s:\n", cmd);
166         ret = write(fd, cmd, strlen(cmd));
167         if (ret != strlen(cmd)) {
168                 perror(cmd);
169         }
170         printf("shared is %d, blob is %d\n", shared, *mmap_blob);
171         printf("Hit return to end, ...\n");
172         read(0, p512, 1);
173
174         return 0;
175 }