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