Update akaros to hook in the new topology stuff
[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 = 0x101000c, kerneladdress = 0x1010000;
52         int nr_gpcs = 1;
53         int fd = open("#c/sysctl", O_RDWR), ret;
54         void * x;
55         int kfd = -1;
56         static char cmd[512];
57         void *coreboot_tables;
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("#c/sysctl");
68                 exit(1);
69         }
70         argc--,argv++;
71         // switches ...
72         while (1) {
73                 if (*argv[0] != '-')
74                         break;
75                 switch(argv[0][1]) {
76                 case 'n':
77                         vmmflags &= ~VMM_VMCALL_PRINTF;
78                         break;
79                 default:
80                         printf("BMAFR\n");
81                         break;
82                 }
83                 argc--,argv++;
84         }
85         if (argc < 1) {
86                 fprintf(stderr, "Usage: %s vmimage coreboot_tables [loadaddress [entrypoint]]\n", argv[0]);
87                 exit(1);
88         }
89         coreboot_tables = (void *) strtoull(argv[1], 0, 0);
90         if (argc > 2)
91                 kerneladdress = strtoull(argv[2], 0, 0);
92         if (argc > 3)
93                 entry = strtoull(argv[3], 0, 0);
94         kfd = open(argv[0], O_RDONLY);
95         if (kfd < 0) {
96                 perror(argv[0]);
97                 exit(1);
98         }
99         // read in the kernel.
100         x = (void *)kerneladdress;
101         for(;;) {
102                 amt = read(kfd, x, 1048576);
103                 if (amt < 0) {
104                         perror("read");
105                         exit(1);
106                 }
107                 if (amt == 0) {
108                         break;
109                 }
110                 x += amt;
111         }
112         fprintf(stderr, "Read in %d bytes\n", x-kerneladdress);
113
114         fprintf(stderr, "Run with %d cores and vmmflags 0x%x\n", nr_gpcs, vmmflags);
115         if (ros_syscall(SYS_setup_vmm, nr_gpcs, vmmflags, 0, 0, 0, 0) != nr_gpcs) {
116                 perror("Guest pcore setup failed");
117                 exit(1);
118         }
119         /* blob that is faulted in from the EPT first.  we need this to be in low
120          * memory (not above the normal mmap_break), so the EPT can look it up.
121          * Note that we won't get 4096.  The min is 1MB now, and ld is there. */
122         mmap_blob = mmap((int*)4096, PGSIZE, PROT_READ | PROT_WRITE,
123                          MAP_ANONYMOUS, -1, 0);
124         if (mmap_blob == MAP_FAILED) {
125                 perror("Unable to mmap");
126                 exit(1);
127         }
128
129         mcp = 1; //argc - 1;
130         if (mcp) {
131                 my_threads = malloc(sizeof(pthread_t) * nr_threads);
132                 my_retvals = malloc(sizeof(void*) * nr_threads);
133                 if (!(my_retvals && my_threads))
134                         perror("Init threads/malloc");
135
136                 pthread_can_vcore_request(FALSE);       /* 2LS won't manage vcores */
137                 pthread_need_tls(FALSE);
138                 pthread_mcp_init();                                     /* gives us one vcore */
139                 vcore_request(nr_threads - 1);          /* ghetto incremental interface */
140                 for (int i = 0; i < nr_threads; i++) {
141                         x = __procinfo.vcoremap;
142                         printf("%p\n", __procinfo.vcoremap);
143                         printf("Vcore %d mapped to pcore %d\n", i,
144                                 __procinfo.vcoremap[i].pcoreid);
145                 }
146         }
147
148         if (mcp) {
149                 if (pthread_create(&my_threads[0], NULL, &talk_thread, NULL))
150                         perror("pth_create failed");
151 //              if (pthread_create(&my_threads[1], NULL, &fail, NULL))
152 //                      perror("pth_create failed");
153         }
154         printf("threads started\n");
155
156         if (0) for (int i = 0; i < nr_threads-1; i++) {
157                 int ret;
158                 if (pthread_join(my_threads[i], &my_retvals[i]))
159                         perror("pth_join failed");
160                 printf("%d %d\n", i, ret);
161         }
162         
163
164         ret = syscall(33, 1);
165         if (ret < 0) {
166                 perror("vm setup");
167                 exit(1);
168         }
169         ret = posix_memalign((void **)&p512, 4096, 3*4096);
170         printf("memalign is %p\n", p512);
171         if (ret) {
172                 perror("ptp alloc");
173                 exit(1);
174         }
175         p1 = &p512[512];
176         p2m = &p512[1024];
177         uint64_t kernbase = 0; //0xffffffff80000000;
178         p512[PML4(kernbase)] = (unsigned long long)p1 | 7;
179         p1[PML3(kernbase)] = /*0x87; */(unsigned long long)p2m | 7;
180 #define _2MiB (0x200000)
181         int i;
182         for (i = 0; i < 512; i++) {
183                 p2m[PML2(kernbase + i * _2MiB)] = 0x87 | i * _2MiB;
184         }
185
186         kernbase >>= (0+12);
187         kernbase <<= (0 + 12);
188         uint8_t *kernel = (void *)(16*1048576);
189         write_coreboot_table(coreboot_tables, kernel, 16*1048576);
190         hexdump(stdout, coreboot_tables, 128);
191         printf("kernbase for pml4 is 0x%llx and entry is %llx\n", kernbase, entry);
192         printf("p512 %p p512[0] is 0x%lx p1 %p p1[0] is 0x%x\n", p512, p512[0], p1, p1[0]);
193         sprintf(cmd, "V 0x%llx 0x%llx 0x%llx", entry, (unsigned long long) &stack[1024], (unsigned long long) p512);
194         printf("Writing command :%s:\n", cmd);
195         ret = write(fd, cmd, strlen(cmd));
196         if (ret != strlen(cmd)) {
197                 perror(cmd);
198         }
199         sprintf(cmd, "V 0 0 0");
200         while (1) {
201                 int c;
202                 printf("RESUME?\n");
203                 c = getchar();
204                 if (c == 'q')
205                         break;
206                 ret = write(fd, cmd, strlen(cmd));
207                 if (ret != strlen(cmd)) {
208                         perror(cmd);
209                 }
210         }
211         printf("shared is %d, blob is %d\n", shared, *mmap_blob);
212
213         return 0;
214 }