VMM: Adds Ron's test programs
authorBarret Rhoden <brho@cs.berkeley.edu>
Mon, 15 Jun 2015 19:07:59 +0000 (15:07 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Thu, 18 Jun 2015 20:31:59 +0000 (16:31 -0400)
This collection is from a bunch of partial commits.

tests/vmm/virtioconsole.c [new file with mode: 0644]
tests/vmm/virtiopiocons.c [new file with mode: 0644]
tests/vmm/virtiostress.c [new file with mode: 0644]
tests/vmm/vmmcpkernel.c [new file with mode: 0644]
tests/vmm/vmresume.c [new file with mode: 0644]
tests/vmm/vmrunkernel.c [new file with mode: 0644]
tests/vmm/vmrunkernelmmap.c [new file with mode: 0644]

diff --git a/tests/vmm/virtioconsole.c b/tests/vmm/virtioconsole.c
new file mode 100644 (file)
index 0000000..656ee4c
--- /dev/null
@@ -0,0 +1,250 @@
+#include <stdio.h> 
+#include <pthread.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <parlib/arch/arch.h>
+#include <unistd.h>
+#include <errno.h>
+#include <dirent.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ros/syscall.h>
+#include <sys/mman.h>
+#include <vmm/virtio.h>
+
+int *mmap_blob;
+void *stack;
+volatile int shared = 0;
+int mcp = 1;
+#define V(x, t) (*((volatile t*)(x)))
+// NOTE: p is both our virtual and guest physical.
+void *p;
+int debug = 0;
+struct virtqueue *head, *consin, *consout;
+pthread_t *my_threads;
+void **my_retvals;
+int nr_threads = 2;
+       char *line, *consline, *outline;
+       struct scatterlist iov[32];
+       unsigned int inlen, outlen, conslen;
+       /* unlike Linux, this shared struct is for both host and guest. */
+//     struct virtqueue *constoguest = 
+//             vring_new_virtqueue(0, 512, 8192, 0, inpages, NULL, NULL, "test");
+volatile int gaveit = 0, gotitback = 0;
+struct virtqueue *guesttocons;
+       struct scatterlist out[] = { {NULL, sizeof(outline)}, };
+       struct scatterlist in[] = { {NULL, sizeof(line)}, };
+       int iter = 1;
+volatile int done = 0;
+
+
+
+static void *fail(void *arg)
+{
+               uint16_t head = 0;
+
+       int i, j, ret;
+       for(i = 0; i < 8;) {
+               /* guest: make a line available to host */
+               if ((gotitback == gaveit) && (!virtqueue_add_inbuf_avail(guesttocons, in, 1, line, 0))) {
+                       gaveit++;
+               }
+
+               /* guest code. Get all your buffers back */
+               char *cp = NULL;
+               while ((cp = virtqueue_get_buf_used(guesttocons, &conslen))) {
+                       if (cp != line) {
+                               gotitback++;
+                               continue;
+                       }
+                       //fprintf(stderr, "guest: from host: %s\n", cp);
+                       /* guest: push some buffers into the channel for the host to use */
+                       /* can't use sprintf here ... */
+                       outline[0] = '0' + i;
+                       for(j = 0; line[j] != 0; j++)
+                               outline[j+1] = line[j];
+                       j++;
+                       outline[j] = 0;
+                       
+//                             sprintf(outline, "guest: outline %d:%s:\n", iter, line);
+                       ret = virtqueue_add_outbuf_avail(guesttocons, out, 1, outline, 0);
+                       i++;
+               }
+       }
+
+       done = 1;
+       __asm__ __volatile__("vmcall");
+       __asm__ __volatile__("mov $0xdeadbeef, %rbx; mov 5, %rax\n");
+}
+
+unsigned long long *p512, *p1, *p2m;
+
+void *talk_thread(void *arg)
+{
+       fprintf(stderr, "talk thread ..\n");
+       uint16_t head;
+       int i;
+       int num;
+       for(num = 0; num < 8;) {
+               /* host: use any buffers we should have been sent. */
+               head = wait_for_vq_desc(guesttocons, iov, &outlen, &inlen);
+               if (debug)
+               printf("vq desc head %d, gaveit %d gotitback %d\n", head, gaveit, gotitback);
+               for(i = 0; debug && i < outlen + inlen; i++)
+                       printf("v[%d/%d] v %p len %d\n", i, outlen + inlen, iov[i].v, iov[i].length);
+               /* host: if we got an output buffer, just output it. */
+               for(i = 0; i < outlen; i++) {
+                       num++;
+                       printf("Host:%s:\n", (char *)iov[i].v);
+               }
+               
+               if (debug) printf("outlen is %d; inlen is %d\n", outlen, inlen);
+               /* host: fill in the writeable buffers. */
+               for (i = outlen; i < outlen + inlen; i++) {
+                       /* host: read a line. */
+                       memset(consline, 0, 128);
+                       if (1) {
+                               if (fgets(consline, 4096-256, stdin) == NULL) {
+                                       exit(0);
+                               } 
+                               if (debug) printf("GOT A LINE:%s:\n", consline);
+                       } else {
+                               sprintf(consline, "hi there. %d\n", i);
+                       }
+                       memmove(iov[i].v, consline, strlen(consline)+ 1);
+                       iov[i].length = strlen(consline) + 1;
+               }
+               
+               /* host: now ack that we used them all. */
+               add_used(guesttocons, head, outlen+inlen);
+       }
+       fprintf(stderr, "All done\n");
+       return NULL;
+}
+
+int main(int argc, char **argv)
+{
+       int nr_gpcs = 1;
+       int fd = open("#c/sysctl", O_RDWR), ret;
+       void * x;
+       static char cmd[512];
+       debug = argc > 1;
+       if (fd < 0) {
+               perror("#c/sysctl");
+               exit(1);
+       }
+
+       if (ros_syscall(SYS_setup_vmm, nr_gpcs, 0, 0, 0, 0, 0) != nr_gpcs) {
+               perror("Guest pcore setup failed");
+               exit(1);
+       }
+       /* blob that is faulted in from the EPT first.  we need this to be in low
+        * memory (not above the normal mmap_break), so the EPT can look it up.
+        * Note that we won't get 4096.  The min is 1MB now, and ld is there. */
+       mmap_blob = mmap((int*)4096, PGSIZE, PROT_READ | PROT_WRITE,
+                        MAP_ANONYMOUS, -1, 0);
+       if (mmap_blob == MAP_FAILED) {
+               perror("Unable to mmap");
+               exit(1);
+       }
+
+       void *outpages;
+       outpages = mmap((int*)4096, 1048576, PROT_READ | PROT_WRITE,
+                        MAP_ANONYMOUS, -1, 0);
+       if (outpages == MAP_FAILED) {
+               perror("Unable to mmap");
+               exit(1);
+       }
+       line = outpages;
+       outline = outpages + 128;
+       consline = outpages + 256;
+       outpages += 4096;
+       stack = mmap((int*)4096, 8192, PROT_READ | PROT_WRITE,
+                        MAP_ANONYMOUS, -1, 0);
+       if (stack == MAP_FAILED) {
+               perror("Unable to mmap");
+               exit(1);
+       }
+
+       my_threads = calloc(sizeof(pthread_t) , nr_threads);
+       my_retvals = calloc(sizeof(void *) , nr_threads);
+       if (!(my_retvals && my_threads))
+               perror("Init threads/malloc");
+
+       pthread_lib_init();     /* gives us one vcore */
+       vcore_request(nr_threads - 1);  /* ghetto incremental interface */
+       for (int i = 0; i < nr_threads; i++) {
+               x = __procinfo.vcoremap;
+               fprintf(stderr, "%p\n", __procinfo.vcoremap);
+               fprintf(stderr, "Vcore %d mapped to pcore %d\n", i,
+                          __procinfo.vcoremap[i].pcoreid);
+       }
+
+       guesttocons = vring_new_virtqueue(0, 512, 8192, 0, outpages, NULL, NULL, "test");
+       fprintf(stderr, "guesttocons is %p\n", guesttocons);
+       out[0].v = outline;
+       in[0].v = line;
+       if (mcp) {
+               if (pthread_create(&my_threads[0], NULL, &talk_thread, NULL))
+                       perror("pth_create failed");
+//      if (pthread_create(&my_threads[1], NULL, &fail, NULL))
+//          perror("pth_create failed");
+       }
+       fprintf(stderr, "threads started\n");
+       
+       ret = syscall(33, 1);
+       if (ret < 0) {
+               perror("vm setup");
+               exit(1);
+       }
+       ret = posix_memalign((void **)&p512, 4096, 3 * 4096);
+       if (ret) {
+               perror("ptp alloc");
+               exit(1);
+       }
+       p1 = &p512[512];
+       p2m = &p512[1024];
+       p512[0] = (unsigned long long)p1 | 7;
+       p1[0] = /*0x87; */ (unsigned long long)p2m | 7;
+       p2m[0] = 0x87;
+       p2m[1] = 0x200000 | 0x87;
+       p2m[2] = 0x400000 | 0x87;
+       p2m[3] = 0x600000 | 0x87;
+       
+       fprintf(stderr, "p512 %p p512[0] is 0x%lx p1 %p p1[0] is 0x%x\n", p512, p512[0], p1,
+              p1[0]);
+       sprintf(cmd, "V 0x%x 0x%x 0x%x", (unsigned long long)fail,
+               (unsigned long long)stack+8192, (unsigned long long)p512);
+       showscatterlist(in, 1);
+       showscatterlist(out, 1);
+       showvq(guesttocons);
+       //showdesc(guesttocons, 0);
+       if (debug)
+               fprintf(stderr, "Writing command :%s:\n", cmd);
+       ret = write(fd, cmd, strlen(cmd));
+       if (ret != strlen(cmd)) {
+               perror(cmd);
+       }
+       sprintf(cmd, "V 0 0 0");
+       while (! done) {
+               if (debug)
+                       fprintf(stderr, "RESUME\n");
+               ret = write(fd, cmd, strlen(cmd));
+               if (ret != strlen(cmd)) {
+                       perror(cmd);
+               }
+       }
+
+       if (debug)
+               fprintf(stderr, "shared is %d\n", shared);
+
+       for (int i = 0; i < nr_threads - 1; i++) {
+               int ret;
+               if (pthread_join(my_threads[i], &my_retvals[i]))
+                       perror("pth_join failed");
+               fprintf(stderr, "%d %d\n", i, ret);
+       }
+       
+       return 0;
+}
diff --git a/tests/vmm/virtiopiocons.c b/tests/vmm/virtiopiocons.c
new file mode 100644 (file)
index 0000000..e1e60db
--- /dev/null
@@ -0,0 +1,160 @@
+#include <stdio.h> 
+#include <pthread.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <parlib/arch/arch.h>
+#include <unistd.h>
+#include <errno.h>
+#include <dirent.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ros/syscall.h>
+#include <sys/mman.h>
+
+int *mmap_blob;
+unsigned long long stack[1024];
+volatile int tr, rr, done;
+volatile int state;
+int debug;
+
+static void *fail(void*arg)
+{
+
+       while (1) {
+               state = 0;
+               if (rr & 0x80) {
+                       state++;
+                       if ((rr & 0x7f) == 'x')
+                               break;
+                       tr = rr;
+                       state++;
+                       rr = 0;
+                       state++;
+               }
+                       
+       }
+       tr = 0x80;
+       done = 1;
+       while (1);
+}
+
+unsigned long long *p512, *p1, *p2m;
+
+void *talk_thread(void *arg)
+{
+       printf("talk thread ..\n");
+       int c;
+       
+       // This is a a bit odd but getchar() is not echoing characters.
+       // That's good for us but makes no sense.
+       while (!done && (c = getchar())) {
+               int i;
+               if (debug) printf("Set rr to 0x%x\n", c | 0x80);
+               rr = c | 0x80;
+               if (debug) printf("rr 0x%x tr 0x%x\n", rr, tr);
+               while (! tr)
+                       ;
+               if (debug) printf("tr 0x%x\n", tr);
+               putchar(tr & 0x7f);
+               tr = 0;
+       }
+       rr = 0; 
+       return NULL;
+}
+
+pthread_t *my_threads;
+void **my_retvals;
+int nr_threads = 2;
+
+int main(int argc, char **argv)
+{
+       int nr_gpcs = 1;
+       int fd = open("#c/sysctl", O_RDWR), ret;
+       void * x;
+       static char cmd[512];
+       if (fd < 0) {
+               perror("#c/sysctl");
+               exit(1);
+       }
+       if (ros_syscall(SYS_setup_vmm, nr_gpcs, 0, 0, 0, 0, 0) != nr_gpcs) {
+               perror("Guest pcore setup failed");
+               exit(1);
+       }
+       /* blob that is faulted in from the EPT first.  we need this to be in low
+        * memory (not above the normal mmap_break), so the EPT can look it up.
+        * Note that we won't get 4096.  The min is 1MB now, and ld is there. */
+       mmap_blob = mmap((int*)4096, PGSIZE, PROT_READ | PROT_WRITE,
+                        MAP_ANONYMOUS, -1, 0);
+       if (mmap_blob == MAP_FAILED) {
+               perror("Unable to mmap");
+               exit(1);
+       }
+
+               my_threads = malloc(sizeof(pthread_t) * nr_threads);
+               my_retvals = malloc(sizeof(void*) * nr_threads);
+               if (!(my_retvals && my_threads))
+                       perror("Init threads/malloc");
+
+               pthread_can_vcore_request(FALSE);       /* 2LS won't manage vcores */
+               pthread_need_tls(FALSE);
+               pthread_lib_init();                                     /* gives us one vcore */
+               vcore_request(nr_threads - 1);          /* ghetto incremental interface */
+               for (int i = 0; i < nr_threads; i++) {
+                       x = __procinfo.vcoremap;
+                       printf("%p\n", __procinfo.vcoremap);
+                       printf("Vcore %d mapped to pcore %d\n", i,
+                               __procinfo.vcoremap[i].pcoreid);
+               }
+               if (pthread_create(&my_threads[0], NULL, &talk_thread, NULL))
+                       perror("pth_create failed");
+//             if (pthread_create(&my_threads[1], NULL, &fail, NULL))
+//                     perror("pth_create failed");
+       printf("threads started\n");
+
+       if (0) for (int i = 0; i < nr_threads-1; i++) {
+               int ret;
+               if (pthread_join(my_threads[i], &my_retvals[i]))
+                       perror("pth_join failed");
+               printf("%d %d\n", i, ret);
+       }
+       
+
+       ret = syscall(33, 1);
+       if (ret < 0) {
+               perror("vm setup");
+               exit(1);
+       }
+       ret = posix_memalign((void **)&p512, 4096, 3*4096);
+       if (ret) {
+               perror("ptp alloc");
+               exit(1);
+       }
+       p1 = &p512[512];
+       p2m = &p512[1024];
+       p512[0] = (unsigned long long)p1 | 7;
+       p1[0] = /*0x87; */(unsigned long long)p2m | 7;
+       p2m[0] = 0x87;
+       p2m[1] = 0x200000 | 0x87;
+       p2m[2] = 0x400000 | 0x87;
+       p2m[3] = 0x600000 | 0x87;
+
+       printf("p512 %p p512[0] is 0x%lx p1 %p p1[0] is 0x%x\n", p512, p512[0], p1, p1[0]);
+       sprintf(cmd, "V 0x%x 0x%x 0x%x", (unsigned long long)fail, (unsigned long long) &stack[1024], (unsigned long long) p512);
+       printf("Writing command :%s:\n", cmd);
+       ret = write(fd, cmd, strlen(cmd));
+       if (ret != strlen(cmd)) {
+               perror(cmd);
+       }
+
+       sprintf(cmd, "V 0 0 0");
+       while (! done) {
+               if (debug)
+                       fprintf(stderr, "RESUME\n");
+               ret = write(fd, cmd, strlen(cmd));
+               if (ret != strlen(cmd)) {
+                       perror(cmd);
+               }
+       }
+       return 0;
+}
diff --git a/tests/vmm/virtiostress.c b/tests/vmm/virtiostress.c
new file mode 100644 (file)
index 0000000..2fac3a8
--- /dev/null
@@ -0,0 +1,328 @@
+#include <stdio.h> 
+#include <pthread.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <parlib/arch/arch.h>
+#include <unistd.h>
+#include <errno.h>
+#include <dirent.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ros/syscall.h>
+#include <sys/mman.h>
+#include <vmm/virtio.h>
+
+
+struct u16_pool *id;
+int *mmap_blob;
+void *stack;
+volatile int shared = 0;
+int mcp = 1;
+#define V(x, t) (*((volatile t*)(x)))
+// NOTE: p is both our virtual and guest physical.
+void *p;
+int debug = 0;
+struct virtqueue *head, *consin, *consout;
+struct page {uint8_t d[4096];};
+void *ringpages;
+struct page *datapages;
+pthread_t *my_threads;
+void **my_retvals;
+int nr_threads = 2;
+       char *line, *consline, *outline;
+       struct scatterlist iov[512];
+       unsigned int inlen, outlen, conslen;
+       /* unlike Linux, this shared struct is for both host and guest. */
+//     struct virtqueue *constoguest = 
+//             vring_new_virtqueue(0, 512, 8192, 0, inpages, NULL, NULL, "test");
+struct virtqueue *guesttocons;
+struct scatterlist io[512];
+int iter = 1;
+volatile int done = 0;
+volatile int cnt;
+volatile int failed, done, added, badput, badget, bogus;
+volatile struct page *usedhead;
+volatile int fstate;
+volatile int failiter;
+
+#define MAX_U16_POOL_SZ (1 << 16)
+
+/* IDS is the stack of 16 bit integers we give out.  TOS is the top of stack -
+ * it is the index of the next slot that can be popped, if there are any.  It's
+ * a u32 so it can be greater than a u16.
+ *
+ * All free slots in ids will be below the TOS, ranging from indexes [0, TOS),
+ * where if TOS == 0, then there are no free slots to push.
+ *
+ * We can hand out u16s in the range [0, 65535].
+ *
+ * The check array is used instead of a bitfield because these architectures
+ * suck at those. */
+
+struct u16_pool {
+       uint32_t tos;
+       uint16_t *ids;
+       uint8_t *check;
+       int size;
+};
+
+struct u16_pool *create_u16_pool(unsigned int num)
+{
+       struct u16_pool *id;
+       int tot = sizeof(*id) + sizeof(uint16_t) * num + num;
+       /* We could have size be a u16, but this might catch bugs where users
+        * tried to ask for more than 2^16 and had it succeed. */
+       if (num > MAX_U16_POOL_SZ)
+               return NULL;
+       /* ids and check are alloced and aligned right after the id struct */
+       id = mmap((int*)4096, tot, PROT_READ | PROT_WRITE, MAP_ANONYMOUS, -1, 0);
+       if (id == MAP_FAILED) {
+               perror("create_u16_pool: Unable to mmap");
+               exit(1);
+       }
+
+       id->size = num;
+       id->ids = (void *)&id[1];
+       id->check = (void *)&id->ids[id->size];
+       for (int i = 0; i < id->size; i++) {
+               id->ids[i] = i;
+               // fe rhymes with "free"
+               id->check[i] = 0xfe;
+       }
+       id->tos = 0;
+       return id;
+}
+
+/* Returns an unused u16, or -1 on failure (pool full or corruption).
+ *
+ * The invariant is that the stackpointer (TOS) will always point to the next
+ * slot that can be popped, if there are any.  All free slots will be below the
+ * TOS, ranging from indexes [0, TOS), where if TOS == 0, then there are no free
+ * slots to push.  The last valid slot is when TOS == size - 1. */
+int get_u16(struct u16_pool *id)
+{
+       uint16_t v;
+
+       if (id->tos == id->size) {
+               return -1;
+       }
+       v = id->ids[id->tos++];
+       /* v is ours, we can freely read and write its check field */
+       if (id->check[v] != 0xfe) {
+               badget++;
+               return -1;
+       }
+       id->check[v] = 0x5a;
+       return v;
+}
+
+void put_u16(struct u16_pool *id, int v)
+{
+       /* we could check for if v is in range before dereferencing. */
+       if (id->check[v] != 0x5a) {
+               badput;
+               return;
+       }
+       id->check[v] = 0xfe;
+       id->ids[--id->tos] = v;
+}
+
+static void *fail(void *arg)
+{
+               uint16_t head = 0;
+
+       int i, j, v, ret;
+
+       for(i = 0; i < 4096;) {
+               /* get all the free ones you can, and add them all */
+               fstate = 1;
+               for(cnt = 0, v = get_u16(id); v >= 0; v = get_u16(id), cnt++) {
+                       failiter++;
+                       added++;
+                       /* 1:1 mapping of iovs to data pages for now */
+                       io[cnt].v = &datapages[v];
+               }
+
+               fstate++;
+               if (! cnt)
+                       continue;
+               if (virtqueue_add_inbuf_avail(guesttocons, io, cnt, datapages, 0)) {
+                       failed = 1;
+                       break;
+               }
+               fstate++;
+
+               while (cnt > 0) {
+                       if ((usedhead = virtqueue_get_buf_used(guesttocons, &conslen))) {
+                               if (usedhead != datapages) { failed = 1; goto verybad;}
+                               for(j = 0; j < conslen; j++) {          
+                                       int idx = (struct page *)io[j].v - usedhead;
+                                       put_u16(id, idx);
+                                       cnt--;
+                               }
+                       } else bogus++;
+               }
+               i++;
+               fstate++;
+       }
+
+       done = 1;
+verybad:
+       __asm__ __volatile__("vmcall");
+}
+
+unsigned long long *p512, *p1, *p2m;
+
+void *talk_thread(void *arg)
+{
+       fprintf(stderr, "talk thread ..\n");
+       uint16_t head;
+       int i;
+       int num;
+       int tot = 0;
+       for(;;) {
+               /* host: use any buffers we should have been sent. */
+               head = wait_for_vq_desc(guesttocons, iov, &outlen, &inlen);
+               if (debug)
+                       printf("vq desc head %d\n", head);
+               if ((outlen == 0) && (inlen == 0)) // EOF
+                       break;
+               tot += outlen + inlen;
+               for(i = 0; debug && i < outlen + inlen; i++)
+                       printf("v[%d/%d] v %p len %d\n", i, outlen + inlen, iov[i].v, iov[i].length);
+
+               if (debug) printf("outlen is %d; inlen is %d\n", outlen, inlen);
+               if (0)
+               { printf("BEFORE ADD USED cnt %d conslen %d badget %d badput %d usedhead %p bogus %d\n", cnt, conslen, badget, badput, usedhead, bogus); showvq(guesttocons); getchar();}
+               /* host: now ack that we used them all. */
+               add_used(guesttocons, head, outlen+inlen);
+               if (0)
+               { printf("cnt %d conslen %d badget %d badput %d usedhead %p bogus %d\n", cnt, conslen, badget, badput, usedhead, bogus); showvq(guesttocons); getchar();} 
+               if (debug)
+                       printf("LOOP fstate %d \n", fstate);
+       }
+       fprintf(stderr, "All done, tot %d, failed %d, failiter %d\n", tot, failed, failiter);
+       return NULL;
+}
+
+int main(int argc, char **argv)
+{
+       int nr_gpcs = 1;
+       int fd = open("#c/sysctl", O_RDWR), ret;
+       void * x;
+       static char cmd[512];
+       debug = argc > 1;
+       if (fd < 0) {
+               perror("#c/sysctl");
+               exit(1);
+       }
+
+       if (ros_syscall(SYS_setup_vmm, nr_gpcs, 0, 0, 0, 0, 0) != nr_gpcs) {
+               perror("Guest pcore setup failed");
+               exit(1);
+       }
+       /* blob that is faulted in from the EPT first.  we need this to be in low
+        * memory (not above the normal mmap_break), so the EPT can look it up.
+        * Note that we won't get 4096.  The min is 1MB now, and ld is there. */
+       mmap_blob = mmap((int*)4096, PGSIZE, PROT_READ | PROT_WRITE,
+                        MAP_ANONYMOUS, -1, 0);
+       if (mmap_blob == MAP_FAILED) {
+               perror("Unable to mmap");
+               exit(1);
+       }
+
+
+       p512 = mmap((int*)4096, (3 + 256 + 512)*4096, PROT_READ | PROT_WRITE,
+                        MAP_ANONYMOUS, -1, 0);
+       if (ringpages == MAP_FAILED) {
+               perror("Unable to mmap");
+               exit(1);
+       }
+       ringpages = p512 + 3*4096;
+       datapages = ringpages + 256*4096;
+       
+       stack = mmap((int*)4096, 8192, PROT_READ | PROT_WRITE,
+                        MAP_ANONYMOUS, -1, 0);
+       if (stack == MAP_FAILED) {
+               perror("Unable to mmap");
+               exit(1);
+       }
+
+       my_threads = calloc(sizeof(pthread_t) , nr_threads);
+       my_retvals = calloc(sizeof(void *) , nr_threads);
+       if (!(my_retvals && my_threads))
+               perror("Init threads/malloc");
+
+       pthread_lib_init();     /* gives us one vcore */
+       vcore_request(nr_threads - 1);  /* ghetto incremental interface */
+       for (int i = 0; i < nr_threads; i++) {
+               x = __procinfo.vcoremap;
+               fprintf(stderr, "%p\n", __procinfo.vcoremap);
+               fprintf(stderr, "Vcore %d mapped to pcore %d\n", i,
+                          __procinfo.vcoremap[i].pcoreid);
+       }
+       id = create_u16_pool(512); //1<<16);
+
+       guesttocons = vring_new_virtqueue(0, 512, 8192, 0, ringpages, NULL, NULL, "test");
+       fprintf(stderr, "guesttocons is %p\n", guesttocons);
+
+       if (mcp) {
+               if (pthread_create(&my_threads[0], NULL, &talk_thread, NULL))
+                       perror("pth_create failed");
+//      if (pthread_create(&my_threads[1], NULL, &fail, NULL))
+//          perror("pth_create failed");
+       }
+       fprintf(stderr, "threads started\n");
+       
+       ret = syscall(33, 1);
+       if (ret < 0) {
+               perror("vm setup");
+               exit(1);
+       }
+
+       p1 = &p512[512];
+       p2m = &p512[1024];
+       p512[0] = (unsigned long long)p1 | 7;
+       p1[0] = /*0x87; */ (unsigned long long)p2m | 7;
+       p2m[0] = 0x87;
+       p2m[1] = 0x200000 | 0x87;
+       p2m[2] = 0x400000 | 0x87;
+       p2m[3] = 0x600000 | 0x87;
+       
+       fprintf(stderr, "p512 %p p512[0] is 0x%lx p1 %p p1[0] is 0x%x\n", p512, p512[0], p1,
+              p1[0]);
+       sprintf(cmd, "V 0x%x 0x%x 0x%x", (unsigned long long)fail,
+               (unsigned long long)stack+8192, (unsigned long long)p512);
+       showvq(guesttocons);
+       //showdesc(guesttocons, 0);
+       if (debug)
+               fprintf(stderr, "Writing command :%s:\n", cmd);
+       ret = write(fd, cmd, strlen(cmd));
+       if (ret != strlen(cmd)) {
+               perror(cmd);
+       }
+       sprintf(cmd, "V 0 0 0");
+       while (! done && ! failed) {
+               if (debug)
+                       fprintf(stderr, "RESUME\n");
+               ret = write(fd, cmd, strlen(cmd));
+               if (ret != strlen(cmd)) {
+                       perror(cmd);
+               }
+       }
+
+       printf("VM DONE, done %d failed %d\n", done, failed);
+       virtqueue_close(guesttocons);
+       if (debug)
+               fprintf(stderr, "shared is %d\n", shared);
+
+       for (int i = 0; i < nr_threads - 1; i++) {
+               int ret;
+               if (pthread_join(my_threads[i], &my_retvals[i]))
+                       perror("pth_join failed");
+               fprintf(stderr, "%d %d\n", i, ret);
+       }
+       
+       return 0;
+}
diff --git a/tests/vmm/vmmcpkernel.c b/tests/vmm/vmmcpkernel.c
new file mode 100644 (file)
index 0000000..ae44eac
--- /dev/null
@@ -0,0 +1,169 @@
+#include <stdio.h> 
+#include <pthread.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <parlib/arch/arch.h>
+#include <unistd.h>
+#include <errno.h>
+#include <dirent.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ros/syscall.h>
+#include <sys/mman.h>
+
+/* this test will run the "kernel" in the negative address space. We hope. */
+int *mmap_blob;
+unsigned long long stack[1024];
+volatile int shared = 0;
+int mcp = 1;
+#define V(x, t) (*((volatile t*)(x)))
+
+uint8_t _kernel[64*1048576];
+
+static void *fail(void*arg)
+{
+
+       __asm__ __volatile__("vmcall\n");
+       *mmap_blob = 1337;
+       if (mcp)
+       while (V(&shared, int) < 31) {
+               if (! (V(&shared, int) & 1))
+                       V(&shared, int) = V(&shared, int) + 1;
+//             cpu_relax();
+       }
+       V(&shared, int) = 55;
+
+       __asm__ __volatile__("vmcall\n");
+       __asm__ __volatile__("mov $0xdeadbeef, %rbx; mov 5, %rax\n");   
+}
+
+unsigned long long *p512, *p1, *p2m;
+
+void *talk_thread(void *arg)
+{
+       printf("talk thread ..\n");
+       for(; V(&shared, int) < 32; ){
+               if (V(&shared, int) & 1) {
+                       printf("shared %d\n", V(&shared, int) );
+                       V(&shared, int) = V(&shared, int) + 1;
+               }
+               cpu_relax();
+       }
+       printf("All done, read %d\n", *mmap_blob);
+       return NULL;
+}
+
+pthread_t *my_threads;
+void **my_retvals;
+int nr_threads = 2;
+
+int main(int argc, char **argv)
+{
+       int nr_gpcs = 1;
+       int fd = open("#c/sysctl", O_RDWR), ret;
+       void * x;
+       static char cmd[512];
+       /* kernel has to be in the range 16M to 64M for now. */
+       // mmap is not working for us at present.
+       if ((uint64_t)_kernel > 16*1048576) {
+               printf("kernel array is above 16M, sucks\n");
+               exit(1);
+       }
+
+       if (fd < 0) {
+               perror("#c/sysctl");
+               exit(1);
+       }
+       if (ros_syscall(SYS_setup_vmm, nr_gpcs, 0, 0, 0, 0, 0) != nr_gpcs) {
+               perror("Guest pcore setup failed");
+               exit(1);
+       }
+       /* blob that is faulted in from the EPT first.  we need this to be in low
+        * memory (not above the normal mmap_break), so the EPT can look it up.
+        * Note that we won't get 4096.  The min is 1MB now, and ld is there. */
+       mmap_blob = mmap((int*)4096, PGSIZE, PROT_READ | PROT_WRITE,
+                        MAP_ANONYMOUS, -1, 0);
+       if (mmap_blob == MAP_FAILED) {
+               perror("Unable to mmap");
+               exit(1);
+       }
+
+       mcp = 1; //argc - 1;
+       if (mcp) {
+               my_threads = malloc(sizeof(pthread_t) * nr_threads);
+               my_retvals = malloc(sizeof(void*) * nr_threads);
+               if (!(my_retvals && my_threads))
+                       perror("Init threads/malloc");
+
+               pthread_can_vcore_request(FALSE);       /* 2LS won't manage vcores */
+               pthread_need_tls(FALSE);
+               pthread_lib_init();                                     /* gives us one vcore */
+               vcore_request(nr_threads - 1);          /* ghetto incremental interface */
+               for (int i = 0; i < nr_threads; i++) {
+                       x = __procinfo.vcoremap;
+                       printf("%p\n", __procinfo.vcoremap);
+                       printf("Vcore %d mapped to pcore %d\n", i,
+                               __procinfo.vcoremap[i].pcoreid);
+               }
+       }
+
+       if (mcp) {
+               if (pthread_create(&my_threads[0], NULL, &talk_thread, NULL))
+                       perror("pth_create failed");
+//             if (pthread_create(&my_threads[1], NULL, &fail, NULL))
+//                     perror("pth_create failed");
+       }
+       printf("threads started\n");
+
+       if (0) for (int i = 0; i < nr_threads-1; i++) {
+               int ret;
+               if (pthread_join(my_threads[i], &my_retvals[i]))
+                       perror("pth_join failed");
+               printf("%d %d\n", i, ret);
+       }
+       
+
+       ret = syscall(33, 1);
+       if (ret < 0) {
+               perror("vm setup");
+               exit(1);
+       }
+       ret = posix_memalign((void **)&p512, 4096, 3*4096);
+       printf("memalign is %p\n", p512);
+       if (ret) {
+               perror("ptp alloc");
+               exit(1);
+       }
+       p1 = &p512[512];
+       p2m = &p512[1024];
+       uint64_t kernbase = 0; //0xffffffff80000000;
+       p512[PML4(kernbase)] = (unsigned long long)p1 | 7;
+       p1[PML3(kernbase)] = /*0x87; */(unsigned long long)p2m | 7;
+#define _2MiB (0x200000)
+       int i;
+       for (i = 0; i < 512; i++) {
+               p2m[PML2(kernbase + i * _2MiB)] = 0x87 | i * _2MiB;
+       }
+
+       kernbase >>= (0+12);
+       kernbase <<= (0 + 12);
+       uint64_t entry = kernbase + (uint64_t) fail;
+       uint8_t *kernel = (void *)(16*1048576);
+       uint8_t program[] = {0x0f, 0x1, 0xc1, 0xeb, 0xfe};
+       memmove(kernel, program, sizeof(program));
+       entry = (uint64_t)kernel;
+       printf("kernbase for pml4 is 0x%llx and entry is %llx\n", kernbase, entry);
+       printf("p512 %p p512[0] is 0x%lx p1 %p p1[0] is 0x%x\n", p512, p512[0], p1, p1[0]);
+       sprintf(cmd, "V 0x%llx 0x%llx 0x%llx", entry, (unsigned long long) &stack[1024], (unsigned long long) p512);
+       printf("Writing command :%s:\n", cmd);
+       ret = write(fd, cmd, strlen(cmd));
+       if (ret != strlen(cmd)) {
+               perror(cmd);
+       }
+       printf("shared is %d, blob is %d\n", shared, *mmap_blob);
+       printf("Hit return to end, ...\n");
+       read(0, p512, 1);
+
+       return 0;
+}
diff --git a/tests/vmm/vmresume.c b/tests/vmm/vmresume.c
new file mode 100644 (file)
index 0000000..637f50b
--- /dev/null
@@ -0,0 +1,109 @@
+#include <stdio.h> 
+#include <pthread.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <parlib/arch/arch.h>
+#include <unistd.h>
+#include <errno.h>
+#include <dirent.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ros/syscall.h>
+#include <sys/mman.h>
+
+int *mmap_blob;
+unsigned long long stack[1024];
+volatile int shared = 0;
+int mcp = 1;
+#define V(x, t) (*((volatile t*)(x)))
+
+static void *fail(void*arg)
+{
+
+       *mmap_blob = 1337;
+       if (mcp)
+       while (V(&shared, int) < 31) {
+               if (! (V(&shared, int) & 1))
+                       V(&shared, int) = V(&shared, int) + 1;
+//     __asm__ __volatile__("vmcall\n");
+//             cpu_relax();
+       }
+       V(&shared, int) = 55;
+
+       __asm__ __volatile__("vmcall\n");
+       __asm__ __volatile__("mov $0xdeadbeef, %rbx; mov 5, %rax\n");   
+}
+
+unsigned long long *p512, *p1, *p2m;
+
+int main(int argc, char **argv)
+{
+       int nr_gpcs = 1;
+       int fd = open("#c/sysctl", O_RDWR), ret;
+       void * x;
+       static char cmd[512];
+       if (fd < 0) {
+               perror("#c/sysctl");
+               exit(1);
+       }
+       if (ros_syscall(SYS_setup_vmm, nr_gpcs, 0, 0, 0, 0, 0) != nr_gpcs) {
+               perror("Guest pcore setup failed");
+               exit(1);
+       }
+       /* blob that is faulted in from the EPT first.  we need this to be in low
+        * memory (not above the normal mmap_break), so the EPT can look it up.
+        * Note that we won't get 4096.  The min is 1MB now, and ld is there. */
+       mmap_blob = mmap((int*)4096, PGSIZE, PROT_READ | PROT_WRITE,
+                        MAP_ANONYMOUS, -1, 0);
+       if (mmap_blob == MAP_FAILED) {
+               perror("Unable to mmap");
+               exit(1);
+       }
+
+       ret = syscall(33, 1);
+       if (ret < 0) {
+               perror("vm setup");
+               exit(1);
+       }
+       ret = posix_memalign((void **)&p512, 4096, 3*4096);
+       if (ret) {
+               perror("ptp alloc");
+               exit(1);
+       }
+       p1 = &p512[512];
+       p2m = &p512[1024];
+       p512[0] = (unsigned long long)p1 | 7;
+       p1[0] = /*0x87; */(unsigned long long)p2m | 7;
+       p2m[0] = 0x87;
+       p2m[1] = 0x200000 | 0x87;
+       p2m[2] = 0x400000 | 0x87;
+       p2m[3] = 0x600000 | 0x87;
+
+       printf("p512 %p p512[0] is 0x%lx p1 %p p1[0] is 0x%x\n", p512, p512[0], p1, p1[0]);
+       sprintf(cmd, "V 0x%x 0x%x 0x%x", (unsigned long long)fail, (unsigned long long) &stack[1024], (unsigned long long) p512);
+       printf("Writing command :%s:\n", cmd);
+       ret = write(fd, cmd, strlen(cmd));
+       if (ret != strlen(cmd)) {
+               perror(cmd);
+       }
+       sprintf(cmd, "V 0 0 0");
+       while (V(&shared, int) < 31) {
+               printf("RESUME?\n");
+               if (V(&shared, int) & 1) {
+                       printf("shared %d\n", V(&shared, int) );
+               }
+               getchar();
+               ret = write(fd, cmd, strlen(cmd));
+               if (ret != strlen(cmd)) {
+                       perror(cmd);
+               }
+               if (V(&shared, int) & 1) {
+                       printf("shared %d\n", V(&shared, int) );
+                       V(&shared, int) = V(&shared, int) + 1;
+               }
+       }
+       printf("shared is %d, blob is %d\n", shared, *mmap_blob);
+
+       return 0;
+}
diff --git a/tests/vmm/vmrunkernel.c b/tests/vmm/vmrunkernel.c
new file mode 100644 (file)
index 0000000..c8e6e54
--- /dev/null
@@ -0,0 +1,193 @@
+#include <stdio.h> 
+#include <pthread.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <parlib/arch/arch.h>
+#include <unistd.h>
+#include <errno.h>
+#include <dirent.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ros/syscall.h>
+#include <sys/mman.h>
+
+/* this test will run the "kernel" in the negative address space. We hope. */
+int *mmap_blob;
+unsigned long long stack[1024];
+volatile int shared = 0;
+int mcp = 1;
+#define V(x, t) (*((volatile t*)(x)))
+
+uint8_t _kernel[64*1048576];
+
+unsigned long long *p512, *p1, *p2m;
+
+void *talk_thread(void *arg)
+{
+       printf("talk thread ..\n");
+       for(; V(&shared, int) < 32; ){
+               if (V(&shared, int) & 1) {
+                       printf("shared %d\n", V(&shared, int) );
+                       V(&shared, int) = V(&shared, int) + 1;
+               }
+               cpu_relax();
+       }
+       printf("All done, read %d\n", *mmap_blob);
+       return NULL;
+}
+
+pthread_t *my_threads;
+void **my_retvals;
+int nr_threads = 2;
+
+int main(int argc, char **argv)
+{
+       int amt;
+       uint64_t entry = 0x101000c, kerneladdress = 0x1010000;
+       int nr_gpcs = 1;
+       int fd = open("#c/sysctl", O_RDWR), ret;
+       void * x;
+       int kfd = -1;
+       static char cmd[512];
+       /* kernel has to be in the range 16M to 64M for now. */
+       // mmap is not working for us at present.
+       if ((uint64_t)_kernel > 16*1048576) {
+               printf("kernel array is above 16M, sucks\n");
+               exit(1);
+       }
+       memset(_kernel, 0, sizeof(_kernel));
+
+       if (fd < 0) {
+               perror("#c/sysctl");
+               exit(1);
+       }
+       argc--,argv++;
+       if (argc < 1) {
+               fprintf(stderr, "Usage: %s vmimage [loadaddress [entrypoint]]\n", argv[0]);
+               exit(1);
+       }
+       if (argc > 1)
+               kerneladdress = strtoull(argv[1], 0, 0);
+       if (argc > 2)
+               entry = strtoull(argv[2], 0, 0);
+       kfd = open(argv[0], O_RDONLY);
+       if (kfd < 0) {
+               perror(argv[0]);
+               exit(1);
+       }
+       // read in the kernel.
+       x = (void *)kerneladdress;
+       for(;;) {
+               amt = read(kfd, x, 1048576);
+               if (amt < 0) {
+                       perror("read");
+                       exit(1);
+               }
+               if (amt == 0) {
+                       break;
+               }
+               x += amt;
+       }
+       fprintf(stderr, "Read in %d bytes\n", x-kerneladdress);
+
+       if (ros_syscall(SYS_setup_vmm, nr_gpcs, 0, 0, 0, 0, 0) != nr_gpcs) {
+               perror("Guest pcore setup failed");
+               exit(1);
+       }
+       /* blob that is faulted in from the EPT first.  we need this to be in low
+        * memory (not above the normal mmap_break), so the EPT can look it up.
+        * Note that we won't get 4096.  The min is 1MB now, and ld is there. */
+       mmap_blob = mmap((int*)4096, PGSIZE, PROT_READ | PROT_WRITE,
+                        MAP_ANONYMOUS, -1, 0);
+       if (mmap_blob == MAP_FAILED) {
+               perror("Unable to mmap");
+               exit(1);
+       }
+
+       mcp = 1; //argc - 1;
+       if (mcp) {
+               my_threads = malloc(sizeof(pthread_t) * nr_threads);
+               my_retvals = malloc(sizeof(void*) * nr_threads);
+               if (!(my_retvals && my_threads))
+                       perror("Init threads/malloc");
+
+               pthread_can_vcore_request(FALSE);       /* 2LS won't manage vcores */
+               pthread_need_tls(FALSE);
+               pthread_lib_init();                                     /* gives us one vcore */
+               vcore_request(nr_threads - 1);          /* ghetto incremental interface */
+               for (int i = 0; i < nr_threads; i++) {
+                       x = __procinfo.vcoremap;
+                       printf("%p\n", __procinfo.vcoremap);
+                       printf("Vcore %d mapped to pcore %d\n", i,
+                               __procinfo.vcoremap[i].pcoreid);
+               }
+       }
+
+       if (mcp) {
+               if (pthread_create(&my_threads[0], NULL, &talk_thread, NULL))
+                       perror("pth_create failed");
+//             if (pthread_create(&my_threads[1], NULL, &fail, NULL))
+//                     perror("pth_create failed");
+       }
+       printf("threads started\n");
+
+       if (0) for (int i = 0; i < nr_threads-1; i++) {
+               int ret;
+               if (pthread_join(my_threads[i], &my_retvals[i]))
+                       perror("pth_join failed");
+               printf("%d %d\n", i, ret);
+       }
+       
+
+       ret = syscall(33, 1);
+       if (ret < 0) {
+               perror("vm setup");
+               exit(1);
+       }
+       ret = posix_memalign((void **)&p512, 4096, 3*4096);
+       printf("memalign is %p\n", p512);
+       if (ret) {
+               perror("ptp alloc");
+               exit(1);
+       }
+       p1 = &p512[512];
+       p2m = &p512[1024];
+       uint64_t kernbase = 0; //0xffffffff80000000;
+       p512[PML4(kernbase)] = (unsigned long long)p1 | 7;
+       p1[PML3(kernbase)] = /*0x87; */(unsigned long long)p2m | 7;
+#define _2MiB (0x200000)
+       int i;
+       for (i = 0; i < 512; i++) {
+               p2m[PML2(kernbase + i * _2MiB)] = 0x87 | i * _2MiB;
+       }
+
+       kernbase >>= (0+12);
+       kernbase <<= (0 + 12);
+       uint8_t *kernel = (void *)(16*1048576);
+       uint8_t program[] = {0x0f, 0x1, 0xc1, 0xeb, 0xfe};
+       memmove(kernel, program, sizeof(program));
+       printf("kernbase for pml4 is 0x%llx and entry is %llx\n", kernbase, entry);
+       printf("p512 %p p512[0] is 0x%lx p1 %p p1[0] is 0x%x\n", p512, p512[0], p1, p1[0]);
+       sprintf(cmd, "V 0x%llx 0x%llx 0x%llx", entry, (unsigned long long) &stack[1024], (unsigned long long) p512);
+       printf("Writing command :%s:\n", cmd);
+       ret = write(fd, cmd, strlen(cmd));
+       if (ret != strlen(cmd)) {
+               perror(cmd);
+       }
+       sprintf(cmd, "V 0 0 0");
+       while (1) {
+               int c;
+               printf("RESUME?\n");
+               c = getchar();
+               if (c == 'q')
+                       break;
+               ret = write(fd, cmd, strlen(cmd));
+               if (ret != strlen(cmd)) {
+                       perror(cmd);
+               }
+       }
+       printf("shared is %d, blob is %d\n", shared, *mmap_blob);
+
+       return 0;
+}
diff --git a/tests/vmm/vmrunkernelmmap.c b/tests/vmm/vmrunkernelmmap.c
new file mode 100644 (file)
index 0000000..27c40d7
--- /dev/null
@@ -0,0 +1,179 @@
+#include <stdio.h> 
+#include <pthread.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <parlib/arch/arch.h>
+#include <unistd.h>
+#include <errno.h>
+#include <dirent.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ros/syscall.h>
+#include <sys/mman.h>
+
+static void *mmap_blob;
+unsigned long long stack[1024];
+volatile int tr, rr, done;
+volatile int state;
+int debug;
+
+unsigned long long *p512, *p1, *p2m;
+
+void *talk_thread(void *arg)
+{
+       printf("talk thread ..\n");
+       int c;
+       
+       // This is a a bit odd but getchar() is not echoing characters.
+       // That's good for us but makes no sense.
+       while (!done && (c = getchar())) {
+               int i;
+               if (debug) printf("Set rr to 0x%x\n", c | 0x80);
+               rr = c | 0x80;
+               if (debug) printf("rr 0x%x tr 0x%x\n", rr, tr);
+               while (! tr)
+                       ;
+               if (debug) printf("tr 0x%x\n", tr);
+               putchar(tr & 0x7f);
+               tr = 0;
+       }
+       rr = 0; 
+       return NULL;
+}
+
+pthread_t *my_threads;
+void **my_retvals;
+int nr_threads = 2;
+
+int main(int argc, char **argv)
+{
+       int i, amt;
+       int nr_gpcs = 1;
+       uint64_t entry;
+       int fd = open("#c/sysctl", O_RDWR), ret;
+       int kfd = -1;
+       bool smallkernel = false;
+       void * x;
+       static char cmd[512];
+       if (fd < 0) {
+               perror("#c/sysctl");
+               exit(1);
+       }
+       argc--,argv++;
+       if (argc != 2) {
+               fprintf(stderr, "Usage: %s vmimage entrypoint\n", argv[0]);
+               exit(1);
+       }
+       entry = strtoull(argv[1], 0, 0);
+       kfd = open(argv[0], O_RDONLY);
+       if (kfd < 0) {
+               perror(argv[0]);
+               exit(1);
+       }
+       if (ros_syscall(SYS_setup_vmm, nr_gpcs, 0, 0, 0, 0, 0) != nr_gpcs) {
+               perror("Guest pcore setup failed");
+               exit(1);
+       }
+               my_threads = malloc(sizeof(pthread_t) * nr_threads);
+               my_retvals = malloc(sizeof(void*) * nr_threads);
+               if (!(my_retvals && my_threads))
+                       perror("Init threads/malloc");
+
+               pthread_can_vcore_request(FALSE);       /* 2LS won't manage vcores */
+               pthread_need_tls(FALSE);
+               pthread_lib_init();                                     /* gives us one vcore */
+               vcore_request(nr_threads - 1);          /* ghetto incremental interface */
+               for (int i = 0; i < nr_threads; i++) {
+                       x = __procinfo.vcoremap;
+                       printf("%p\n", __procinfo.vcoremap);
+                       printf("Vcore %d mapped to pcore %d\n", i,
+                               __procinfo.vcoremap[i].pcoreid);
+               }
+               if (pthread_create(&my_threads[0], NULL, &talk_thread, NULL))
+                       perror("pth_create failed");
+//             if (pthread_create(&my_threads[1], NULL, &fail, NULL))
+//                     perror("pth_create failed");
+       printf("threads started\n");
+
+       if (0) for (int i = 0; i < nr_threads-1; i++) {
+               int ret;
+               if (pthread_join(my_threads[i], &my_retvals[i]))
+                       perror("pth_join failed");
+               printf("%d %d\n", i, ret);
+       }
+       
+
+       ret = syscall(33, 1);
+       if (ret < 0) {
+               perror("vm setup");
+               exit(1);
+       }
+       /* blob that is faulted in from the EPT first.  we need this to be in low
+        * memory (not above the normal mmap_break), so the EPT can look it up.
+        * Note that we won't get 4096.  The min is 1MB now, and ld is there. */
+
+       mmap_blob = mmap((int*)(15*1048576), 16 * 1048576, PROT_EXEC | PROT_READ | PROT_WRITE,
+                        MAP_ANONYMOUS, -1, 0);
+       if (mmap_blob == MAP_FAILED) {
+               perror("Unable to mmap");
+               exit(1);
+       }
+
+       memset(mmap_blob, 0, 16*1048576);
+       // read in the kernel.
+       x = mmap_blob + 0x1000000;
+       for(;;) {
+               amt = read(kfd, x, 1048576);
+               if (amt < 0) {
+                       perror("read");
+                       exit(1);
+               }
+               if (amt == 0) {
+                       break;
+               }
+               x += amt;
+       }
+       fprintf(stderr, "Read in %d bytes\n", x-mmap_blob);
+
+       p512 = mmap_blob;
+       p1 = &p512[512];
+       p2m = &p512[1024];
+       
+       // We had thought to enter the kernel at the high address. But
+       // there's just too much state the kernel has to clean up to
+       // make this really work -- consider all the segment
+       // descriptors that have to move, etc.  So we will enter the
+       // kernel in the low part of the address space, and let it
+       // work up its page tables and the other good fun.  Map the
+       // kernel address space at low virtual, for 1G.  It's ok to
+       // map memory we have no access to.
+#define _2MiB 0x200000
+       p512[0] = (unsigned long long)p1 | 7;
+       // if only we could guarantee 1G pages everywhere!
+       p1[0] = /*0x87; */(unsigned long long)p2m | 7;
+       for(i = 0; i < 16; i++) {
+               p2m[i] = 0x87 | i * _2MiB;
+               printf("pwm[%d] = 0x%llx\n", i, p2m[i]);
+       }
+       printf("p512 %p p512[0] is 0x%lx p1 %p p1[0] is 0x%x\n", p512, p512[0], p1, p1[0]);
+       sprintf(cmd, "V 0x%llx 0x%llx 0x%llx", entry, (unsigned long long) &stack[1024], (unsigned long long) p512);
+       printf("Writing command :%s:\n", cmd);
+       ret = write(fd, cmd, strlen(cmd));
+       if (ret != strlen(cmd)) {
+               perror(cmd);
+       }
+
+       sprintf(cmd, "V 0 0 0");
+       while (! done) {
+               char c[1];
+               printf("hit return\n"); read(0, c, 1);
+               if (debug)
+                       fprintf(stderr, "RESUME\n");
+               ret = write(fd, cmd, strlen(cmd));
+               if (ret != strlen(cmd)) {
+                       perror(cmd);
+               }
+       }
+       return 0;
+}