vmmcp: add higherkernbase, more debugging.
[akaros.git] / tests / vmm / vmrunkernel.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 <parlib/ros_debug.h>
8 #include <unistd.h>
9 #include <errno.h>
10 #include <dirent.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <ros/syscall.h>
14 #include <sys/mman.h>
15 #include <vmm/coreboot_tables.h>
16 #include <ros/vmm.h>
17
18 /* this test will run the "kernel" in the negative address space. We hope. */
19 int *mmap_blob;
20 unsigned long long stack[1024];
21 volatile int shared = 0;
22 int mcp = 1;
23 #define V(x, t) (*((volatile t*)(x)))
24
25 uint8_t _kernel[64*1048576];
26
27 unsigned long long *p512, *p1, *p2m;
28
29 void *talk_thread(void *arg)
30 {
31         printf("talk thread ..\n");
32         for(; V(&shared, int) < 32; ){
33                 if (V(&shared, int) & 1) {
34                         printf("shared %d\n", V(&shared, int) );
35                         V(&shared, int) = V(&shared, int) + 1;
36                 }
37                 cpu_relax();
38         }
39         printf("All done, read %d\n", *mmap_blob);
40         return NULL;
41 }
42
43 pthread_t *my_threads;
44 void **my_retvals;
45 int nr_threads = 2;
46
47 int main(int argc, char **argv)
48 {
49         int amt;
50         int vmmflags = VMM_VMCALL_PRINTF;
51         uint64_t entry = 0x1000000, kerneladdress = 0x1000000;
52         int nr_gpcs = 1;
53         int fd = open("#cons/sysctl", O_RDWR), ret;
54         void * x;
55         int kfd = -1;
56         static char cmd[512];
57         void *coreboot_tables = (void *) 0x1165000;
58         /* kernel has to be in the range 16M to 64M for now. */
59         // mmap is not working for us at present.
60         if ((uint64_t)_kernel > 16*1048576) {
61                 printf("kernel array is above 16M, sucks\n");
62                 exit(1);
63         }
64         memset(_kernel, 0, sizeof(_kernel));
65
66         if (fd < 0) {
67                 perror("#cons/sysctl");
68                 exit(1);
69         }
70         argc--,argv++;
71         // switches ...
72         // Sorry, I don't much like the gnu opt parsing code.
73         while (1) {
74                 if (*argv[0] != '-')
75                         break;
76                 switch(argv[0][1]) {
77                 case 'n':
78                         vmmflags &= ~VMM_VMCALL_PRINTF;
79                         break;
80                 default:
81                         printf("BMAFR\n");
82                         break;
83                 }
84                 argc--,argv++;
85         }
86         if (argc < 1) {
87                 fprintf(stderr, "Usage: %s vmimage [-n (no vmcall printf)] [coreboot_tables [loadaddress [entrypoint]]]\n", argv[0]);
88                 exit(1);
89         }
90         if (argc > 1)
91                 coreboot_tables = (void *) strtoull(argv[1], 0, 0);
92         if (argc > 2)
93                 kerneladdress = strtoull(argv[2], 0, 0);
94         if (argc > 3)
95                 entry = strtoull(argv[3], 0, 0);
96         kfd = open(argv[0], O_RDONLY);
97         if (kfd < 0) {
98                 perror(argv[0]);
99                 exit(1);
100         }
101         // read in the kernel.
102         x = (void *)kerneladdress;
103         for(;;) {
104                 amt = read(kfd, x, 1048576);
105                 if (amt < 0) {
106                         perror("read");
107                         exit(1);
108                 }
109                 if (amt == 0) {
110                         break;
111                 }
112                 x += amt;
113         }
114         fprintf(stderr, "Read in %d bytes\n", x-kerneladdress);
115
116         fprintf(stderr, "Run with %d cores and vmmflags 0x%x\n", nr_gpcs, vmmflags);
117         if (ros_syscall(SYS_setup_vmm, nr_gpcs, vmmflags, 0, 0, 0, 0) != nr_gpcs) {
118                 perror("Guest pcore setup failed");
119                 exit(1);
120         }
121         /* blob that is faulted in from the EPT first.  we need this to be in low
122          * memory (not above the normal mmap_break), so the EPT can look it up.
123          * Note that we won't get 4096.  The min is 1MB now, and ld is there. */
124         mmap_blob = mmap((int*)4096, PGSIZE, PROT_READ | PROT_WRITE,
125                          MAP_ANONYMOUS, -1, 0);
126         if (mmap_blob == MAP_FAILED) {
127                 perror("Unable to mmap");
128                 exit(1);
129         }
130
131         mcp = 1; //argc - 1;
132         if (mcp) {
133                 my_threads = malloc(sizeof(pthread_t) * nr_threads);
134                 my_retvals = malloc(sizeof(void*) * nr_threads);
135                 if (!(my_retvals && my_threads))
136                         perror("Init threads/malloc");
137
138                 pthread_can_vcore_request(FALSE);       /* 2LS won't manage vcores */
139                 pthread_need_tls(FALSE);
140                 pthread_mcp_init();                                     /* gives us one vcore */
141                 vcore_request(nr_threads - 1);          /* ghetto incremental interface */
142                 for (int i = 0; i < nr_threads; i++) {
143                         x = __procinfo.vcoremap;
144                         printf("%p\n", __procinfo.vcoremap);
145                         printf("Vcore %d mapped to pcore %d\n", i,
146                                 __procinfo.vcoremap[i].pcoreid);
147                 }
148         }
149
150         if (mcp) {
151                 if (pthread_create(&my_threads[0], NULL, &talk_thread, NULL))
152                         perror("pth_create failed");
153 //              if (pthread_create(&my_threads[1], NULL, &fail, NULL))
154 //                      perror("pth_create failed");
155         }
156         printf("threads started\n");
157
158         if (0) for (int i = 0; i < nr_threads-1; i++) {
159                 int ret;
160                 if (pthread_join(my_threads[i], &my_retvals[i]))
161                         perror("pth_join failed");
162                 printf("%d %d\n", i, ret);
163         }
164         
165
166         ret = syscall(33, 1);
167         if (ret < 0) {
168                 perror("vm setup");
169                 exit(1);
170         }
171         ret = posix_memalign((void **)&p512, 4096, 3*4096);
172         printf("memalign is %p\n", p512);
173         if (ret) {
174                 perror("ptp alloc");
175                 exit(1);
176         }
177         p1 = &p512[512];
178         p2m = &p512[1024];
179         uint64_t kernbase = 0; //0xffffffff80000000;
180         uint64_t highkernbase = 0xffffffff80000000;
181         p512[PML4(kernbase)] = (unsigned long long)p1 | 7;
182         p1[PML3(kernbase)] = /*0x87; */(unsigned long long)p2m | 7;
183         p512[PML4(highkernbase)] = (unsigned long long)p1 | 7;
184         p1[PML3(highkernbase)] = /*0x87; */(unsigned long long)p2m | 7;
185 #define _2MiB (0x200000)
186         int i;
187         for (i = 0; i < 512; i++) {
188                 p2m[PML2(kernbase + i * _2MiB)] = 0x87 | i * _2MiB;
189         }
190
191         kernbase >>= (0+12);
192         kernbase <<= (0 + 12);
193         uint8_t *kernel = (void *)(16*1048576);
194         write_coreboot_table(coreboot_tables, kernel, 16*1048576);
195         hexdump(stdout, coreboot_tables, 128);
196         printf("kernbase for pml4 is 0x%llx and entry is %llx\n", kernbase, entry);
197         printf("p512 %p p512[0] is 0x%lx p1 %p p1[0] is 0x%x\n", p512, p512[0], p1, p1[0]);
198         sprintf(cmd, "V 0x%llx 0x%llx 0x%llx", entry, (unsigned long long) &stack[1024], (unsigned long long) p512);
199         printf("Writing command :%s:\n", cmd);
200         ret = write(fd, cmd, strlen(cmd));
201         if (ret != strlen(cmd)) {
202                 perror(cmd);
203         }
204         sprintf(cmd, "V 0 0 0");
205         while (1) {
206                 int c;
207                 printf("RESUME?\n");
208                 c = getchar();
209                 if (c == 'q')
210                         break;
211                 ret = write(fd, cmd, strlen(cmd));
212                 if (ret != strlen(cmd)) {
213                         perror(cmd);
214                 }
215         }
216         printf("shared is %d, blob is %d\n", shared, *mmap_blob);
217
218         return 0;
219 }