From: Jack Lange Date: Fri, 18 Mar 2011 19:57:06 +0000 (-0500) Subject: updated module cleanup and added user space tools X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=commitdiff_plain;h=4801e692b7344051eb94fff6faf1be53f621d422;p=palacios.releases.git updated module cleanup and added user space tools --- diff --git a/linux_module/palacios-dev.c b/linux_module/palacios-dev.c index 585e807..8b30352 100644 --- a/linux_module/palacios-dev.c +++ b/linux_module/palacios-dev.c @@ -125,11 +125,12 @@ static long v3_dev_ioctl(struct file * filp, 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; @@ -232,8 +233,6 @@ static int __init v3_init(void) { palacios_init_stream(); palacios_file_init(); palacios_init_console(); - - return 0; @@ -245,22 +244,29 @@ static int __init v3_init(void) { 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); } diff --git a/linux_module/palacios-vm.c b/linux_module/palacios-vm.c index cd3ba2c..1d8bfe0 100644 --- a/linux_module/palacios-vm.c +++ b/linux_module/palacios-vm.c @@ -113,8 +113,6 @@ int start_palacios_vm(void * arg) { unlock_kernel(); - - guest->v3_ctx = v3_create_vm(guest->img, (void *)guest, guest->name); if (guest->v3_ctx == NULL) { @@ -143,19 +141,17 @@ int start_palacios_vm(void * arg) { 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; @@ -165,13 +161,16 @@ int start_palacios_vm(void * arg) { 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; } diff --git a/linux_module/palacios.h b/linux_module/palacios.h index 1498b73..806e1e7 100644 --- a/linux_module/palacios.h +++ b/linux_module/palacios.h @@ -44,6 +44,7 @@ struct v3_guest { struct palacios_console console; + struct completion start_done; struct completion thread_done; dev_t vm_dev; diff --git a/linux_usr/Makefile b/linux_usr/Makefile new file mode 100644 index 0000000..2fc1ad8 --- /dev/null +++ b/linux_usr/Makefile @@ -0,0 +1,27 @@ +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 diff --git a/linux_usr/v3_cons.c b/linux_usr/v3_cons.c new file mode 100644 index 0000000..0c991a5 --- /dev/null +++ b/linux_usr/v3_cons.c @@ -0,0 +1,396 @@ +/* + * V3 Console utility + * Taken from Palacios console display in MINIX ( by Erik Van der Kouwe ) + * (c) Jack lange, 2010 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 \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; +} + + diff --git a/linux_usr/v3_ctrl.c b/linux_usr/v3_ctrl.c new file mode 100644 index 0000000..c8bf216 --- /dev/null +++ b/linux_usr/v3_ctrl.c @@ -0,0 +1,106 @@ +/* + * V3 Control utility + * (c) Jack lange, 2010 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include + +#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 \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; +} diff --git a/linux_usr/v3_mem.c b/linux_usr/v3_mem.c new file mode 100644 index 0000000..bb9758c --- /dev/null +++ b/linux_usr/v3_mem.c @@ -0,0 +1,77 @@ +/* + * V3 Control utility + * (c) Jack lange, 2010 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include + +#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 \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; +} diff --git a/linux_usr/v3_monitor.c b/linux_usr/v3_monitor.c new file mode 100644 index 0000000..e2c084c --- /dev/null +++ b/linux_usr/v3_monitor.c @@ -0,0 +1,73 @@ +/* + * V3 Monitor utility + * (c) Lei Xia, 2010 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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; +} + + diff --git a/linux_usr/v3_net.c b/linux_usr/v3_net.c new file mode 100644 index 0000000..5449cd4 --- /dev/null +++ b/linux_usr/v3_net.c @@ -0,0 +1,64 @@ +/* + * V3 Control utility for Palacios network services + * (c) Lei Xia, 2010 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include + +#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; +} + diff --git a/linux_usr/v3_serial.c b/linux_usr/v3_serial.c new file mode 100644 index 0000000..2f66c7f --- /dev/null +++ b/linux_usr/v3_serial.c @@ -0,0 +1,101 @@ +/* + * V3 Console utility + * (c) Jack lange & Lei Xia, 2010 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#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; +} + + diff --git a/linux_usr/v3_stop.c b/linux_usr/v3_stop.c new file mode 100644 index 0000000..b47347d --- /dev/null +++ b/linux_usr/v3_stop.c @@ -0,0 +1,51 @@ +/* + * V3 Control utility + * (c) Jack lange, 2010 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include + +#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 \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; +} + +