INIT_LIST_HEAD(&(guest->streams));
INIT_LIST_HEAD(&(guest->files));
INIT_LIST_HEAD(&(guest->sockets));
+ init_completion(&(guest->start_done));
init_completion(&(guest->thread_done));
kthread_run(start_palacios_vm, guest, guest->name);
- wait_for_completion(&(guest->thread_done));
+ wait_for_completion(&(guest->start_done));
return guest->vm_dev;
break;
palacios_init_stream();
palacios_file_init();
palacios_init_console();
-
-
return 0;
return ret;
}
+
static void __exit v3_exit(void) {
extern u32 pg_allocs;
extern u32 pg_frees;
extern u32 mallocs;
extern u32 frees;
+ dev_t dev = MKDEV(v3_major_num, MAX_VMS + 1);
+
printk("Removing V3 Control device\n");
- palacios_vmm_exit();
+ palacios_vmm_exit();
printk("Palacios Mallocs = %d, Frees = %d\n", mallocs, frees);
printk("Palacios Page Allocs = %d, Page Frees = %d\n", pg_allocs, pg_frees);
-
unregister_chrdev_region(MKDEV(v3_major_num, 0), MAX_VMS + 1);
+
+ cdev_del(&ctrl_dev);
+
+ device_destroy(v3_class, dev);
+ class_destroy(v3_class);
}
unlock_kernel();
-
-
guest->v3_ctx = v3_create_vm(guest->img, (void *)guest, guest->name);
if (guest->v3_ctx == NULL) {
return -1;
}
- complete(&(guest->thread_done));
-
+ complete(&(guest->start_done));
printk("palacios: launching vm\n");
if (v3_start_vm(guest->v3_ctx, 0xffffffff) < 0) {
printk("palacios: launch of vm failed\n");
return -1;
- }
+ }
complete(&(guest->thread_done));
-
printk("palacios: vm completed. returning.\n");
return 0;
int stop_palacios_vm(struct v3_guest * guest) {
-
+
v3_stop_vm(guest->v3_ctx);
wait_for_completion(&(guest->thread_done));
v3_free_vm(guest->v3_ctx);
+ device_destroy(v3_class, guest->vm_dev);
+
+ cdev_del(&(guest->cdev));
return 0;
}
struct palacios_console console;
+ struct completion start_done;
struct completion thread_done;
dev_t vm_dev;
--- /dev/null
+all: v3_ctrl v3_stop v3_cons v3_mem v3_monitor v3_serial v3_net
+
+
+v3_ctrl : v3_ctrl.c v3_ctrl.h
+ gcc -static v3_ctrl.c -o v3_ctrl
+
+v3_stop : v3_stop.c v3_ctrl.h
+ gcc -static v3_stop.c -o v3_stop
+
+v3_mem : v3_mem.c v3_ctrl.h
+ gcc -static v3_mem.c -o v3_mem
+
+
+v3_cons : v3_cons.c v3_ctrl.h
+ gcc -static v3_cons.c -o v3_cons -lcurses
+
+v3_serial : v3_serial.c v3_ctrl.h
+ gcc -static v3_serial.c -pthread -o v3_serial
+
+v3_monitor : v3_cons.c v3_ctrl.h
+ gcc -static v3_monitor.c -o v3_monitor
+
+v3_net : v3_net.c v3_ctrl.h
+ gcc -static v3_net.c -o v3_net
+
+clean:
+ rm -f v3_ctrl v3_cons v3_mem v3_monitor v3_serial v3_net
--- /dev/null
+/*
+ * V3 Console utility
+ * Taken from Palacios console display in MINIX ( by Erik Van der Kouwe )
+ * (c) Jack lange, 2010
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <assert.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <curses.h>
+#include <termios.h>
+#include <linux/kd.h>
+#include <linux/keyboard.h>
+
+#include "v3_ctrl.h"
+
+static int use_curses = 0;
+static int debug_enable = 0;
+
+
+typedef enum { CONSOLE_CURS_SET = 1,
+ CONSOLE_CHAR_SET = 2,
+ CONSOLE_SCROLL = 3,
+ CONSOLE_UPDATE = 4,
+ CONSOLE_RESOLUTION = 5 } console_op_t;
+
+
+
+static struct {
+ WINDOW * win;
+ int x;
+ int y;
+ int rows;
+ int cols;
+ struct termios termios_old;
+ unsigned char old_kbd_mode;
+} console;
+
+
+struct cursor_msg {
+ int x;
+ int y;
+} __attribute__((packed));
+
+struct character_msg {
+ int x;
+ int y;
+ char c;
+ unsigned char style;
+} __attribute__((packed));
+
+struct scroll_msg {
+ int lines;
+} __attribute__((packed));
+
+struct resolution_msg {
+ int cols;
+ int rows;
+} __attribute__((packed));
+
+
+struct cons_msg {
+ unsigned char op;
+ union {
+ struct cursor_msg cursor;
+ struct character_msg character;
+ struct scroll_msg scroll;
+ struct resolution_msg resolution;
+ };
+} __attribute__((packed));
+
+
+
+
+static int handle_char_set(struct character_msg * msg) {
+ char c = msg->c;
+
+ if (debug_enable) {
+ fprintf(stderr, "setting char (%c), at (x=%d, y=%d)\n", c, msg->x, msg->y);
+ }
+
+ if (c == 0) {
+ c = ' ';
+ }
+
+
+ if ((c < ' ') || (c >= 127)) {
+ fprintf(stderr, "unexpected control character %d\n", c);
+ c = '?';
+ }
+
+ if (use_curses) {
+ /* clip whatever falls outside the visible area to avoid errors */
+ if ((msg->x < 0) || (msg->y < 0) ||
+ (msg->x > console.win->_maxx) ||
+ (msg->y > console.win->_maxy)) {
+
+ fprintf(stderr, "Char out of range (x=%d,y=%d) MAX:(x=%d,y=%d)\n",
+ msg->x, msg->y, console.win->_maxx, console.win->_maxy);
+ return -1;
+ }
+
+ if ((msg->x == console.win->_maxx) &&
+ (msg->y == console.win->_maxy)) {
+ return -1;
+ }
+
+ mvwaddch(console.win, msg->y, msg->x, c);
+
+ } else {
+ //stdout text display
+ while (console.y < msg->y) {
+ printf("\n");
+ console.x = 0;
+ console.y++;
+ }
+
+ while (console.x < msg->x) {
+ printf(" ");
+ console.x++;
+ }
+
+ printf("%c", c);
+ console.x++;
+
+ assert(console.x <= console.cols);
+
+ if (console.x == console.cols) {
+ printf("\n");
+ console.x = 0;
+ console.y++;
+ }
+ }
+
+ return 0;
+}
+
+int handle_curs_set(struct cursor_msg * msg) {
+ if (debug_enable) {
+ fprintf(stderr, "cursor set: (x=%d, y=%d)\n", msg->x, msg->y);
+ }
+
+ if (use_curses) {
+ /* nothing to do now, cursor is set before update to make sure it isn't
+ * affected by character_set
+ */
+
+ console.x = msg->x;
+ console.y = msg->y;
+ }
+
+ return 0;
+}
+
+
+int handle_scroll(struct scroll_msg * msg) {
+ int lines = msg->lines;
+
+ if (debug_enable) {
+ fprintf(stderr, "scroll: %d lines\n", lines);
+ }
+
+
+ assert(lines >= 0);
+
+ if (use_curses) {
+ while (lines > 0) {
+ scroll(console.win);
+ lines--;
+ }
+ } else {
+ console.y -= lines;
+ }
+}
+
+int handle_text_resolution(struct resolution_msg * msg) {
+ if (debug_enable) {
+ fprintf(stderr, "text resolution: rows=%d, cols=%d\n", msg->rows, msg->cols);
+ }
+
+
+ console.rows = msg->rows;
+ console.cols = msg->cols;
+
+ return 0;
+}
+
+int handle_update( void ) {
+ if (debug_enable) {
+ fprintf(stderr, "update\n");
+ }
+
+ if (use_curses) {
+
+ if ( (console.x >= 0) && (console.y >= 0) &&
+ (console.x <= console.win->_maxx) &&
+ (console.y <= console.win->_maxy) ) {
+
+ wmove(console.win, console.y, console.x);
+
+ }
+
+ wrefresh(console.win);
+ } else {
+ fflush(stdout);
+ }
+}
+
+
+int handle_console_msg(int cons_fd) {
+ int ret = 0;
+ struct cons_msg msg;
+
+ ret = read(cons_fd, &msg, sizeof(struct cons_msg));
+
+ switch (msg.op) {
+ case CONSOLE_CURS_SET:
+ // printf("Console cursor set (x=%d, y=%d)\n", msg.cursor.x, msg.cursor.y);
+ handle_curs_set(&(msg.cursor));
+ break;
+ case CONSOLE_CHAR_SET:
+ handle_char_set(&(msg.character));
+ /* printf("Console character set (x=%d, y=%d, c=%c, style=%c)\n",
+ msg.character.x, msg.character.y, msg.character.c, msg.character.style);*/
+ break;
+ case CONSOLE_SCROLL:
+ // printf("Console scroll (lines=%d)\n", msg.scroll.lines);
+ handle_scroll(&(msg.scroll));
+ break;
+ case CONSOLE_UPDATE:
+ // printf("Console update\n");
+ handle_update();
+ break;
+ case CONSOLE_RESOLUTION:
+ handle_text_resolution(&(msg.resolution));
+ break;
+ default:
+ printf("Invalid console message operation (%d)\n", msg.op);
+ break;
+ }
+
+ return 0;
+}
+
+
+int send_key(int cons_fd, char scan_code) {
+
+ return 0;
+}
+
+
+
+void handle_exit(void) {
+ fprintf(stderr, "Exiting from console terminal\n");
+
+ if (use_curses) {
+ endwin();
+ }
+
+ tcsetattr(STDIN_FILENO, TCSANOW, &console.termios_old);
+
+ ioctl(STDIN_FILENO, KDSKBMODE, K_XLATE);
+}
+
+int main(int argc, char* argv[]) {
+ int vm_fd;
+ int cons_fd;
+ char * vm_dev = NULL;
+ struct termios termios;
+
+ use_curses = 1;
+
+ if (argc < 2) {
+ printf("Usage: ./v3_cons <vm_device>\n");
+ return -1;
+ }
+
+ vm_dev = argv[1];
+
+
+
+ vm_fd = open(vm_dev, O_RDONLY);
+
+ if (vm_fd == -1) {
+ printf("Error opening VM device: %s\n", vm_dev);
+ return -1;
+ }
+
+ cons_fd = ioctl(vm_fd, V3_VM_CONSOLE_CONNECT, NULL);
+
+ /* Close the file descriptor. */
+ close(vm_fd);
+
+ if (cons_fd < 0) {
+ printf("Error opening stream Console\n");
+ return -1;
+ }
+
+ tcgetattr(STDIN_FILENO, &console.termios_old);
+ atexit(handle_exit);
+
+ console.x = 0;
+ console.y = 0;
+
+
+ if (use_curses) {
+ gettmode();
+ console.win = initscr();
+
+ if (console.win == NULL) {
+ fprintf(stderr, "Error initialization curses screen\n");
+ exit(-1);
+ }
+
+ scrollok(console.win, 1);
+ }
+
+ /*
+ termios = console.termios_old;
+ termios.c_iflag &= ~(BRKINT | ICRNL | IGNBRK | IGNCR | IGNPAR);
+ termios.c_iflag &= ~(INLCR | INPCK | ISTRIP | IXOFF | IXON | PARMRK);
+ //termios.c_iflag &= ~(ICRNL | INLCR );
+
+ // termios.c_iflag |= SCANCODES;
+ // termios.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
+ //termios.c_lflag &= ~(ICANON | IEXTEN | ISIG | NOFLSH);
+ termios.c_lflag &= ~(ICANON | ECHO);
+
+ termios.c_cc[VMIN] = 1;
+ termios.c_cc[VTIME] = 0;
+
+ tcflush(STDIN_FILENO, TCIFLUSH);
+ tcsetattr(STDIN_FILENO, TCSANOW, &termios);
+ */
+
+ raw();
+ //cbreak();
+ noecho();
+ keypad(console.win, TRUE);
+
+ ioctl(STDIN_FILENO, KDSKBMODE, K_RAW);
+
+ while (1) {
+ int ret;
+ int bytes_read = 0;
+ fd_set rset;
+
+ FD_ZERO(&rset);
+ FD_SET(cons_fd, &rset);
+ FD_SET(STDIN_FILENO, &rset);
+
+ ret = select(cons_fd + 1, &rset, NULL, NULL, NULL);
+
+ // printf("Returned from select...\n");
+
+ if (ret == 0) {
+ continue;
+ } else if (ret == -1) {
+ perror("Select returned error...\n");
+ return -1;
+ }
+
+ if (FD_ISSET(cons_fd, &rset)) {
+ if (handle_console_msg(cons_fd) == -1) {
+ printf("Console Error\n");
+ return -1;
+ }
+ }
+
+ if (FD_ISSET(STDIN_FILENO, &rset)) {
+ unsigned char key = getch();
+
+ if (key == 0x01) { // ESC
+ break;
+ }
+
+ if (write(cons_fd, &key, 1) != 1) {
+ fprintf(stderr, "ERrror sendign key to console\n");
+ return -1;
+ }
+
+ }
+ }
+
+ close(cons_fd);
+
+ return 0;
+}
+
+
--- /dev/null
+/*
+ * V3 Control utility
+ * (c) Jack lange, 2010
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "v3_ctrl.h"
+
+int read_file(int fd, int size, unsigned char * buf);
+
+int main(int argc, char* argv[]) {
+ char * filename = argv[1];
+ char * name = argv[2];
+ int guest_fd = 0;
+ int v3_fd = 0;
+ struct v3_guest_img guest_img;
+ struct stat guest_stats;
+
+ memset(&guest_img, 0, sizeof(struct v3_guest_img));
+
+ if (argc <= 2) {
+ printf("Usage: ./v3_ctrl <guest_img> <vm name>\n");
+ return -1;
+ }
+
+ printf("Launching guest: %s\n", filename);
+
+ guest_fd = open(filename, O_RDONLY);
+
+ if (guest_fd == -1) {
+ printf("Error Opening guest image: %s\n", filename);
+ return -1;
+ }
+
+ if (fstat(guest_fd, &guest_stats) == -1) {
+ printf("ERROR: Could not stat guest image file -- %s\n", filename);
+ return -1;
+ }
+
+
+ guest_img.size = guest_stats.st_size;
+
+ // load guest image into user memory
+ guest_img.guest_data = malloc(guest_img.size);
+
+ read_file(guest_fd, guest_img.size, guest_img.guest_data);
+
+ close(guest_fd);
+
+ printf("Loaded guest image. Launching to V3Vee\n");
+
+ strncpy(guest_img.name, name, 127);
+
+
+ v3_fd = open(v3_dev, O_RDONLY);
+
+ if (v3_fd == -1) {
+ printf("Error opening V3Vee control device\n");
+ return -1;
+ }
+
+ ioctl(v3_fd, V3_START_GUEST, &guest_img);
+
+
+
+ /* Close the file descriptor. */
+ close(v3_fd);
+
+
+
+ return 0;
+}
+
+
+
+int read_file(int fd, int size, unsigned char * buf) {
+ int left_to_read = size;
+ int have_read = 0;
+
+ while (left_to_read != 0) {
+ int bytes_read = read(fd, buf + have_read, left_to_read);
+
+ if (bytes_read <= 0) {
+ break;
+ }
+
+ have_read += bytes_read;
+ left_to_read -= bytes_read;
+ }
+
+ if (left_to_read != 0) {
+ printf("Error could not finish reading file\n");
+ return -1;
+ }
+
+ return 0;
+}
--- /dev/null
+/*
+ * V3 Control utility
+ * (c) Jack lange, 2010
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "v3_ctrl.h"
+
+
+int main(int argc, char* argv[]) {
+ unsigned long long base_addr = atoll(argv[1]);
+ unsigned long long num_bytes = atoll(argv[2]);
+ int v3_fd = 0;
+ struct v3_mem_region mem;
+
+ if (argc <= 2) {
+ printf("Usage: ./v3_mem <base_addr> <num_bytes>\n");
+ return -1;
+ }
+
+ printf("Giving Palacios %dMB of memory: \n", num_bytes / (1024 * 1024));
+
+ mem.base_addr = base_addr;
+ mem.num_pages = num_bytes / 4096;
+
+ v3_fd = open(v3_dev, O_RDONLY);
+
+ if (v3_fd == -1) {
+ printf("Error opening V3Vee control device\n");
+ return -1;
+ }
+
+ ioctl(v3_fd, V3_ADD_MEMORY, &mem);
+
+
+
+ /* Close the file descriptor. */
+ close(v3_fd);
+
+
+
+ return 0;
+}
+
+
+
+int read_file(int fd, int size, unsigned char * buf) {
+ int left_to_read = size;
+ int have_read = 0;
+
+ while (left_to_read != 0) {
+ int bytes_read = read(fd, buf + have_read, left_to_read);
+
+ if (bytes_read <= 0) {
+ break;
+ }
+
+ have_read += bytes_read;
+ left_to_read -= bytes_read;
+ }
+
+ if (left_to_read != 0) {
+ printf("Error could not finish reading file\n");
+ return -1;
+ }
+
+ return 0;
+}
--- /dev/null
+/*
+ * V3 Monitor utility
+ * (c) Lei Xia, 2010
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <string.h>
+#include<linux/unistd.h>
+
+#include "v3_ctrl.h"
+
+int main(int argc, char* argv[]) {
+ int vm_fd;
+ int cons_fd;
+ fd_set rset;
+ char *vm_dev = NULL;
+ char *stream;
+
+ if (argc <= 3) {
+ printf("Usage: ./v3_cons vm_device stream_name\n");
+ return -1;
+ }
+
+ vm_dev = argv[1];
+ stream = argv[2];
+
+ vm_fd = open(vm_dev, O_RDONLY);
+ if (vm_fd == -1) {
+ printf("Error opening VM device: %s\n", vm_dev);
+ return -1;
+ }
+
+ cons_fd = ioctl(vm_fd, V3_VM_CONSOLE_CONNECT, stream);
+
+ /* Close the file descriptor. */
+ close(vm_fd);
+ if (cons_fd < 0) {
+ printf("Error opening stream Console\n");
+ return -1;
+ }
+
+ while (1) {
+ int ret;
+ char cons_buf[1024];
+ memset(cons_buf, 0, sizeof(cons_buf));
+ int bytes_read = 0;
+
+ FD_ZERO(&rset);
+ FD_SET(cons_fd, &rset);
+
+ ret = select(cons_fd + 1, &rset, NULL, NULL, NULL);
+
+ if (ret == 1) {
+ bytes_read = read(cons_fd, cons_buf, 1024);
+ cons_buf[bytes_read]='\0';
+ printf("%s", cons_buf);
+ } else {
+ printf("v3_monitor ERROR: select returned %d\n", ret);
+ return -1;
+ }
+ }
+
+
+ return 0;
+}
+
+
--- /dev/null
+/*
+ * V3 Control utility for Palacios network services
+ * (c) Lei Xia, 2010
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "v3_ctrl.h"
+
+struct v3_network {
+ unsigned char socket;
+ unsigned char packet;
+ unsigned char vnet;
+};
+
+int main(int argc, char* argv[]) {
+ int v3_fd = 0;
+ struct v3_network net;
+ int i;
+
+ if (argc <= 1) {
+ printf("Usage: ./v3_mem [socket] [packet] [vnet]\n");
+ return -1;
+ }
+
+ for (i = 1; i < argc; i++){
+ if(!strcasecmp (argv[i], "packet")){
+ net.packet = 1;
+ }else if(!strcasecmp (argv[i], "socket")){
+ net.socket = 1;
+ }else if(!strcasecmp (argv[i], "vnet")){
+ net.vnet = 1;
+ }else {
+ printf("unknown v3 network service: %s, ignored\n", argv[i]);
+ }
+ }
+
+ printf("Network service: socket: %d, packet: %d, vnet: %d\n", net.socket, net.packet, net.vnet);
+
+ v3_fd = open(v3_dev, O_RDONLY);
+
+ if (v3_fd == -1) {
+ printf("Error opening V3Vee control device\n");
+ return -1;
+ }
+
+ ioctl(v3_fd, V3_START_NETWORK, &net);
+
+
+ /* Close the file descriptor. */
+ close(v3_fd);
+
+
+ return 0;
+}
+
--- /dev/null
+/*
+ * V3 Console utility
+ * (c) Jack lange & Lei Xia, 2010
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <errno.h>
+#include<linux/unistd.h>
+#include <curses.h>
+
+
+#include "v3_ctrl.h"
+
+static int cons_fd = -1;
+static pthread_t input_handler;
+
+void *write_handler(void *val){
+ char read;
+ printf("Write handler active\n");
+ fflush(stdout);
+ while(1){
+ read = getchar();
+ if(write(cons_fd, &read, sizeof(char)) < 0){
+ printf("WRITE ERROR");
+ }
+ }
+}
+
+
+int main(int argc, char* argv[]) {
+ int vm_fd;
+ fd_set rset;
+ char *vm_dev = NULL;
+ char *stream;
+
+ if (argc < 2) {
+ printf("Usage: ./v3_cons vm_device serial_number\n");
+ return -1;
+ }
+
+ vm_dev = argv[1];
+ stream = argv[2];
+
+ vm_fd = open(vm_dev, O_RDONLY);
+ if (vm_fd == -1) {
+ printf("Error opening VM device: %s\n", vm_dev);
+ return -1;
+ }
+
+ cons_fd = ioctl(vm_fd, V3_VM_SERIAL_CONNECT, stream);
+
+ /* Close the file descriptor. */
+ close(vm_fd);
+ if (cons_fd < 0) {
+ printf("Error opening stream Console\n");
+ return -1;
+ }
+
+
+ if(pthread_create(&input_handler,0,write_handler,0)){
+ perror("pthread_create");
+ exit(-1);
+ }
+
+
+ while (1) {
+ int ret;
+ char cons_buf[1024];
+ memset(cons_buf, 0, sizeof(cons_buf));
+ int bytes_read = 0;
+
+ FD_ZERO(&rset);
+ FD_SET(cons_fd, &rset);
+
+ ret = select(cons_fd + 1, &rset, NULL, NULL, NULL);
+
+ if (ret == 1) {
+ bytes_read = read(cons_fd, cons_buf, 1024);
+ cons_buf[bytes_read]='\0';
+ printf("%s", cons_buf);
+ } else {
+ printf("v3_cons ERROR: select returned %d\n", ret);
+ return -1;
+ }
+ }
+
+
+ return 0;
+}
+
+
--- /dev/null
+/*
+ * V3 Control utility
+ * (c) Jack lange, 2010
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "v3_ctrl.h"
+
+int read_file(int fd, int size, unsigned char * buf);
+
+int main(int argc, char* argv[]) {
+ char * filename = argv[1];
+ int vm_fd = 0;
+
+
+ if (argc <= 1) {
+ printf("Usage: ./v3_stop <vm-dev>\n");
+ return -1;
+ }
+
+ printf("Stopping VM\n");
+
+ vm_fd = open(filename, O_RDONLY);
+
+ if (vm_fd == -1) {
+ printf("Error opening V3Vee VM device\n");
+ return -1;
+ }
+
+ ioctl(vm_fd, V3_VM_STOP, NULL);
+
+
+
+ /* Close the file descriptor. */
+ close(vm_fd);
+
+
+
+ return 0;
+}
+
+