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