EXAMPLE_EXECS = v3_user_host_dev_example \
v3_os_debug \
v3_user_keyed_stream_example \
- v3_user_keyed_stream_file
+ v3_user_keyed_stream_file \
+ v3_guest_mem_example
#
# Currently experimental things
#
# Libraries that we need to build
#
-LIBS = libv3_user_host_dev.a libv3_user_keyed_stream.a libv3_ctrl.a
+LIBS = libv3_user_host_dev.a libv3_user_keyed_stream.a libv3_ctrl.a libv3_guest_mem.a
BUILD_EXECS = $(BASE_EXECS) $(EXAMPLE_EXECS) $(EXPERIMENTAL_EXECS)
BUILD_LIBS = $(LIBS)
$(CC) $(CFLAGS) $< -I../linux_module -L. -lv3_user_keyed_stream -o $@
+# guest memory access by mmap and example
+#
+libv3_guest_mem.a : v3_guest_mem.c v3_guest_mem.h v3_ctrl.h
+ $(CC) $(CFLAGS) -c v3_guest_mem.c
+ $(AR) ruv libv3_guest_mem.a v3_guest_mem.o
+ rm -f v3_guest_mem.o
+
+v3_guest_mem_example : v3_guest_mem_example.c libv3_guest_mem.a
+ $(CC) $(CFLAGS) $< -L. -lv3_guest_mem -o $@
+
+
#
# VNC support is compiled separately
--- /dev/null
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+
+#include "v3_guest_mem.h"
+
+
+#define GUEST_FILE "/proc/v3vee/v3-guests"
+//#define GUEST_FILE "/441/pdinda/test.proc"
+#define MAXLINE 65536
+
+struct v3_guest_mem_map * v3_guest_mem_get_map(char *vmdev)
+{
+ FILE *f;
+ char buf[MAXLINE];
+ char name[MAXLINE];
+ char dev[MAXLINE];
+ char state[MAXLINE];
+ uint64_t start, end;
+
+
+ if (!(f=fopen(GUEST_FILE,"r"))) {
+ fprintf(stderr,"Cannot open %s - is Palacios active?\n",GUEST_FILE);
+ return 0;
+ }
+
+ // This is using the current "single memory region" model
+ // and will change when /proc convention changes to conform to
+ // multiple region model
+ while (fgets(buf,MAXLINE,f)) {
+ if (sscanf(buf,
+ "%s %s %s [0x%llx-0x%llx]",
+ name,
+ dev,
+ state,
+ &start,
+ &end)!=5) {
+ fprintf(stderr, "Cannot parse following line\n%s\n",buf);
+ fclose(f);
+ return 0;
+ }
+ if (!strcmp(dev,vmdev)) {
+ struct v3_guest_mem_map *m =
+ (struct v3_guest_mem_map *) malloc(sizeof(struct v3_guest_mem_map)+1*sizeof(struct v3_guest_mem_block));
+ if (!m) {
+ fprintf(stderr, "Cannot allocate space\n");
+ fclose(f);
+ return 0;
+ }
+
+ memset(m,0,sizeof(struct v3_guest_mem_map)+1*sizeof(struct v3_guest_mem_block));
+
+ m->numblocks=1;
+ m->block[0].gpa=0;
+ m->block[0].hpa=(void*)start;
+ m->block[0].numpages = (end-start+1) / 4096;
+ fclose(f);
+ return m;
+ }
+ }
+
+ fprintf(stderr,"%s not found\n",vmdev);
+ fclose(f);
+ return 0;
+
+}
+
+int v3_map_guest_mem(struct v3_guest_mem_map *map)
+{
+ uint64_t i;
+
+ if (map->fd) {
+ fprintf(stderr, "Memory appears to already be mapped\n");
+ return -1;
+ }
+
+ map->fd = open("/dev/mem", O_RDWR | O_SYNC);
+
+ if (map->fd<0) {
+ fprintf(stderr, "Cannot open /dev/mem - are you root?\n");
+ map->fd=0;
+ return -1;
+ }
+
+ for (i=0; i<map->numblocks; i++) {
+ fprintf(stderr,"Mapping %llu bytes of /dev/mem offset 0x%llx\n",
+ map->block[i].numpages*4096, (off_t)(map->block[i].hpa));
+ map->block[i].uva = mmap(NULL,
+ map->block[i].numpages*4096,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED,
+ map->fd,
+ (off_t) (map->block[i].hpa));
+
+ if (map->block[i].uva == MAP_FAILED) {
+ fprintf(stderr, "Failed to map block %llu\n",i);
+ map->block[i].uva=0;
+ v3_unmap_guest_mem(map);
+ return -1;
+ }
+ }
+
+ return 0;
+
+}
+
+int v3_unmap_guest_mem(struct v3_guest_mem_map *map)
+{
+ uint64_t i;
+
+ for (i=0; i<map->numblocks; i++) {
+ if (map->block[i].uva) {
+ munmap(map->block[i].uva, map->block[i].numpages*4096);
+ map->block[i].uva=0;
+ }
+ }
+ if (map->fd) {
+ close(map->fd);
+ map->fd=0;
+ }
+ return 0;
+}
--- /dev/null
+#ifndef _V3_GUEST_MEM_
+#define _V3_GUEST_MEM_
+
+#include <stdint.h>
+#include "v3_ctrl.h"
+
+struct v3_guest_mem_block {
+ void *gpa; // guest physical address is
+ void *hpa; // mapped to this host physical address
+ void *uva; // which is mapped here in this process
+ uint64_t numpages; // this many 4K pages
+};
+
+// Whole memory map of guest's physical memory
+// that is backed by host physical memory (ie, everything we
+// can read or write from the host user space)
+struct v3_guest_mem_map {
+ int fd; // used by mmap
+ uint64_t numblocks;
+ struct v3_guest_mem_block block[0];
+};
+
+// This function gets the basic memory map, but does not map it
+struct v3_guest_mem_map * v3_guest_mem_get_map(char *vmdev);
+// This function mmaps it into the guest address space
+// and fills out the "myaddr" fields
+int v3_map_guest_mem(struct v3_guest_mem_map *map);
+// This function unmaps it - it assumes myaddrs are valid
+int v3_unmap_guest_mem(struct v3_guest_mem_map *map);
+
+
+#endif
+
--- /dev/null
+#include <stdint.h>
+#include <stdio.h>
+
+#include "v3_guest_mem.h"
+
+void usage()
+{
+ fprintf(stderr,"usage: v3_guest_mem_example /dev/v3-vmN read|write gpa_hex numbytes [<data]\n");
+}
+
+int main(int argc, char *argv[])
+{
+ char *vmdev;
+ enum {READ, WRITE} mode;
+ uint64_t gpa;
+ uint64_t numbytes;
+ struct v3_guest_mem_map *map;
+ uint64_t i;
+
+ if (argc!=5) {
+ usage();
+ return -1;
+ }
+
+ vmdev=argv[1];
+
+ if (toupper(argv[2][0])=='R') {
+ mode=READ;
+ } else if (toupper(argv[2][0]=='W')) {
+ mode=WRITE;
+ } else {
+ fprintf(stderr,"Unknown mode %s\n", argv[2]);
+ return -1;
+ }
+
+ if (sscanf(argv[3],"%llx",&gpa)!=1) {
+ fprintf(stderr,"Don't understand address %s\n",argv[3]);
+ return -1;
+ }
+
+ numbytes=atol(argv[4]);
+
+ if (!(map=v3_guest_mem_get_map(vmdev))) {
+ fprintf(stderr,"Cannot get guest memory map for %s\n",vmdev);
+ return -1;
+ }
+
+ for (i=0; i< map->numblocks; i++) {
+ fprintf(stderr,"Region %llu: gpa=%p, hpa=%p, numpages=%llu\n",
+ i, map->block[i].gpa, map->block[i].hpa, map->block[i].numpages);
+ }
+
+ if (map->numblocks!=1) {
+ fprintf(stderr,"Don't handle multiregion map yet\n");
+ return -1;
+ }
+
+ if (!( ((void*)(gpa) >= map->block[0].gpa) &&
+ (numbytes <= map->block[0].numpages*4096))) {
+ fprintf(stderr,"request (%p to %p) is out of range\n",
+ gpa, gpa+numbytes-1);
+ return -1;
+ }
+
+ if (v3_map_guest_mem(map)) {
+ fprintf(stderr, "Cannot map guest memory\n");
+ free(map);
+ return -1;
+ }
+
+ for (i=0; i<numbytes; i++) {
+ uint8_t cur;
+ if (mode==WRITE) {
+ if (read(0,&cur,1)!=1) {
+ fprintf(stderr,"can't get data from stdin for byte %llu\n", i);
+ break;
+ }
+ *((uint8_t*)(map->block[0].uva+gpa+i))=cur;
+ } else {
+ cur = *((uint8_t *)(map->block[0].uva+gpa+i));
+ // fprintf(stderr, "read %llu from uva=%p, ptr=%p\n",i,map->block[0].uva, map->block[0].uva+gpa+i);
+ if (write(1,&cur,1)!=1) {
+ fprintf(stderr,"can't write data to stdout for byte %llu\n", i);
+ break;
+ }
+ }
+ }
+
+
+ if (v3_unmap_guest_mem(map)) {
+ fprintf(stderr, "Cannot unmap guest memory\n");
+ free(map);
+ return -1;
+ }
+}
+