Added Timer thread. Started by consin thread.
[akaros.git] / tests / vmm / vmrunkernelmmap.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 static void *mmap_blob;
16 unsigned long long stack[1024];
17 volatile int tr, rr, done;
18 volatile int state;
19 int debug;
20
21 unsigned long long *p512, *p1, *p2m;
22
23 void *talk_thread(void *arg)
24 {
25         printf("talk thread ..\n");
26         int c;
27         
28         // This is a a bit odd but getchar() is not echoing characters.
29         // That's good for us but makes no sense.
30         while (!done && (c = getchar())) {
31                 int i;
32                 if (debug) printf("Set rr to 0x%x\n", c | 0x80);
33                 rr = c | 0x80;
34                 if (debug) printf("rr 0x%x tr 0x%x\n", rr, tr);
35                 while (! tr)
36                         ;
37                 if (debug) printf("tr 0x%x\n", tr);
38                 putchar(tr & 0x7f);
39                 tr = 0;
40         }
41         rr = 0; 
42         return NULL;
43 }
44
45 pthread_t *my_threads;
46 void **my_retvals;
47 int nr_threads = 2;
48
49 int main(int argc, char **argv)
50 {
51         int i, amt;
52         int nr_gpcs = 1;
53         uint64_t entry;
54         int fd = open("#cons/sysctl", O_RDWR), ret;
55         int kfd = -1;
56         bool smallkernel = false;
57         void * x;
58         static char cmd[512];
59         if (fd < 0) {
60                 perror("#cons/sysctl");
61                 exit(1);
62         }
63         argc--,argv++;
64         if (argc != 2) {
65                 fprintf(stderr, "Usage: %s vmimage entrypoint\n", argv[0]);
66                 exit(1);
67         }
68         entry = strtoull(argv[1], 0, 0);
69         kfd = open(argv[0], O_RDONLY);
70         if (kfd < 0) {
71                 perror(argv[0]);
72                 exit(1);
73         }
74         if (ros_syscall(SYS_setup_vmm, nr_gpcs, 0, 0, 0, 0, 0) != nr_gpcs) {
75                 perror("Guest pcore setup failed");
76                 exit(1);
77         }
78                 my_threads = malloc(sizeof(pthread_t) * nr_threads);
79                 my_retvals = malloc(sizeof(void*) * nr_threads);
80                 if (!(my_retvals && my_threads))
81                         perror("Init threads/malloc");
82
83                 pthread_can_vcore_request(FALSE);       /* 2LS won't manage vcores */
84                 pthread_need_tls(FALSE);
85                 pthread_mcp_init();                                     /* gives us one vcore */
86                 vcore_request(nr_threads - 1);          /* ghetto incremental interface */
87                 for (int i = 0; i < nr_threads; i++) {
88                         x = __procinfo.vcoremap;
89                         printf("%p\n", __procinfo.vcoremap);
90                         printf("Vcore %d mapped to pcore %d\n", i,
91                                 __procinfo.vcoremap[i].pcoreid);
92                 }
93                 if (pthread_create(&my_threads[0], NULL, &talk_thread, NULL))
94                         perror("pth_create failed");
95 //              if (pthread_create(&my_threads[1], NULL, &fail, NULL))
96 //                      perror("pth_create failed");
97         printf("threads started\n");
98
99         if (0) for (int i = 0; i < nr_threads-1; i++) {
100                 int ret;
101                 if (pthread_join(my_threads[i], &my_retvals[i]))
102                         perror("pth_join failed");
103                 printf("%d %d\n", i, ret);
104         }
105         
106
107         ret = syscall(33, 1);
108         if (ret < 0) {
109                 perror("vm setup");
110                 exit(1);
111         }
112         /* blob that is faulted in from the EPT first.  we need this to be in low
113          * memory (not above the normal mmap_break), so the EPT can look it up.
114          * Note that we won't get 4096.  The min is 1MB now, and ld is there. */
115
116         mmap_blob = mmap((int*)(15*1048576), 16 * 1048576, PROT_EXEC | PROT_READ | PROT_WRITE,
117                          MAP_ANONYMOUS, -1, 0);
118         if (mmap_blob == MAP_FAILED) {
119                 perror("Unable to mmap");
120                 exit(1);
121         }
122
123         memset(mmap_blob, 0, 16*1048576);
124         // read in the kernel.
125         x = mmap_blob + 0x1000000;
126         for(;;) {
127                 amt = read(kfd, x, 1048576);
128                 if (amt < 0) {
129                         perror("read");
130                         exit(1);
131                 }
132                 if (amt == 0) {
133                         break;
134                 }
135                 x += amt;
136         }
137         fprintf(stderr, "Read in %d bytes\n", x-mmap_blob);
138
139         p512 = mmap_blob;
140         p1 = &p512[512];
141         p2m = &p512[1024];
142         
143         // We had thought to enter the kernel at the high address. But
144         // there's just too much state the kernel has to clean up to
145         // make this really work -- consider all the segment
146         // descriptors that have to move, etc.  So we will enter the
147         // kernel in the low part of the address space, and let it
148         // work up its page tables and the other good fun.  Map the
149         // kernel address space at low virtual, for 1G.  It's ok to
150         // map memory we have no access to.
151 #define _2MiB 0x200000
152         p512[0] = (unsigned long long)p1 | 7;
153         // if only we could guarantee 1G pages everywhere!
154         p1[0] = /*0x87; */(unsigned long long)p2m | 7;
155         for(i = 0; i < 16; i++) {
156                 p2m[i] = 0x87 | i * _2MiB;
157                 printf("pwm[%d] = 0x%llx\n", i, p2m[i]);
158         }
159         printf("p512 %p p512[0] is 0x%lx p1 %p p1[0] is 0x%x\n", p512, p512[0], p1, p1[0]);
160         sprintf(cmd, "V 0x%llx 0x%llx 0x%llx", entry, (unsigned long long) &stack[1024], (unsigned long long) p512);
161         printf("Writing command :%s:\n", cmd);
162         ret = write(fd, cmd, strlen(cmd));
163         if (ret != strlen(cmd)) {
164                 perror(cmd);
165         }
166
167         sprintf(cmd, "V 0 0 0");
168         while (! done) {
169                 char c[1];
170                 printf("hit return\n"); read(0, c, 1);
171                 if (debug)
172                         fprintf(stderr, "RESUME\n");
173                 ret = write(fd, cmd, strlen(cmd));
174                 if (ret != strlen(cmd)) {
175                         perror(cmd);
176                 }
177         }
178         return 0;
179 }