From: Lei Xia Date: Mon, 8 Nov 2010 19:41:51 +0000 (-0600) Subject: virtual console works with stream-serial implementation X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=commitdiff_plain;h=09a7d3811df9df65346e36419f553a38c8c45c72;p=palacios.git virtual console works with stream-serial implementation add reparent_threadd os hooks, In Linux host, every kernel thread created in Palacios has to call reparent_threadd to detach itself from the user process. --- diff --git a/palacios/include/devices/serial.h b/palacios/include/devices/serial.h index f71159c..78ff076 100644 --- a/palacios/include/devices/serial.h +++ b/palacios/include/devices/serial.h @@ -26,8 +26,13 @@ to different kinds of frontend devices that can act as a stream */ struct v3_stream_ops { + /* called by serial device to the backend stream device */ int (*read)(char *buf, uint_t len, void *private_data); int (*write)(char *buf, uint_t len, void *private_data); + + /* called by backend device to frontend serial device */ + int (*input)(char *buf, uint_t len, void *front_data); + void *front_data; }; diff --git a/palacios/include/palacios/vmm.h b/palacios/include/palacios/vmm.h index a5b47dc..dad24f6 100644 --- a/palacios/include/palacios/vmm.h +++ b/palacios/include/palacios/vmm.h @@ -211,18 +211,27 @@ struct guest_info; } while (0) - - +#define V3_Reparent_Threadd() \ + do { \ + if((os_hooks) && (os_hooks)->reparent_threaded) { \ + (os_hooks)->reparent_threaded(); \ + } \ + } while(0) /* ** */ #define V3_ASSERT(x) \ do { \ + extern struct v3_os_hooks * os_hooks; \ if (!(x)) { \ PrintDebug("Failed assertion in %s: %s at %s, line %d, RA=%lx\n", \ __func__, #x, __FILE__, __LINE__, \ (ulong_t) __builtin_return_address(0)); \ - while(1); \ + while(1){ \ + if ((os_hooks) && (os_hooks)->yield_cpu) { \ + (os_hooks)->yield_cpu(); \ + } \ + } \ } \ } while(0) \ @@ -292,7 +301,7 @@ struct v3_os_hooks { void (*interrupt_cpu)(struct v3_vm_info * vm, int logical_cpu, int vector); void (*call_on_cpu)(int logical_cpu, void (*fn)(void * arg), void * arg); void * (*start_thread_on_cpu)(int cpu_id, int (*fn)(void * arg), void * arg, char * thread_name); - + void (*reparent_threadd)(void); }; diff --git a/palacios/include/palacios/vmm_stream.h b/palacios/include/palacios/vmm_stream.h index 02b7aed..ce4cb8f 100644 --- a/palacios/include/palacios/vmm_stream.h +++ b/palacios/include/palacios/vmm_stream.h @@ -26,11 +26,11 @@ #ifdef __V3VEE__ -#define V3_StreamOpen(path, mode) \ +#define V3_StreamOpen(path, notify_fn, private_data, mode) \ ({ \ extern struct v3_stream_hooks *stream_hooks; \ ((stream_hooks) && (stream_hooks)->stream_open) ? \ - (stream_hooks)->stream_open((path), (mode)) : NULL; \ + (stream_hooks)->stream_open((path), (notify_fn), (private_data), (mode)) : NULL; \ }) #define V3_StreamRead(stream, b, l) \ @@ -62,11 +62,10 @@ #define STREAM_OPEN_MODE_WRITE (1 << 1) struct v3_stream_hooks { - void *(*stream_open)(const char *path, int mode); + void *(*stream_open)(const char *path, void (*notify)(void *), void *private_data, int mode); int (*stream_read)(void *stream, char *buf, int len); int (*stream_write)(void *stream, char *buf, int len); int (*stream_close)(void *stream); - }; diff --git a/palacios/src/devices/serial.c b/palacios/src/devices/serial.c index 7d0c10e..1cdcc80 100644 --- a/palacios/src/devices/serial.c +++ b/palacios/src/devices/serial.c @@ -12,6 +12,7 @@ * All rights reserved. * * Author: Rumou Duan + * Lei Xia * * This is free software. You are permitted to use, * redistribute, and modify it as specified in the file "V3VEE_LICENSE". @@ -289,6 +290,7 @@ struct serial_port { struct v3_stream_ops *stream_ops; void *backend_data; + struct vm_device * vm_dev; }; @@ -297,8 +299,6 @@ struct serial_state { struct serial_port com2; struct serial_port com3; struct serial_port com4; - - }; @@ -455,19 +455,6 @@ static int dequeue_data(struct serial_buffer * buf, uint8_t * data, return 0; } -/* -static void printBuffer(struct serial_buffer * buf) { - int i = 0; - - for (i = 0; i < SERIAL_BUF_LEN; i++) { - PrintDebug(" %d ", buf->buffer[i]); - } - - PrintDebug("\n the number of elements is %d \n", getNumber(buf)); -} -*/ - -//note: write to data port is NOT implemented and corresponding codes are commented out static int write_data_port(struct guest_info * core, uint16_t port, void * src, uint_t length, struct vm_device * dev) { struct serial_state * state = (struct serial_state *)dev->private_data; @@ -543,8 +530,8 @@ static int read_data_port(struct guest_info * core, uint16_t port, *val = com_port->dll.data; } else { dequeue_data(&(com_port->rx_buffer), val, com_port, dev); - } - + } + return length; } @@ -931,11 +918,21 @@ static int init_serial_port(struct serial_port * com) { return 0; } +static int serial_input(char *buf, uint_t len, void *front_data){ + struct serial_port *com_port = (struct serial_port *)front_data; + int i; + + for(i=0; irx_buffer), buf[i], com_port, com_port->vm_dev); + } + + return len; +} + static int serial_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) { struct serial_state * state = (struct serial_state *)V3_Malloc(sizeof(struct serial_state)); char * dev_id = v3_cfg_val(cfg, "ID"); - PrintDebug("UART: init_device\n"); init_serial_port(&(state->com1)); init_serial_port(&(state->com2)); init_serial_port(&(state->com3)); @@ -946,14 +943,19 @@ static int serial_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) { state->com3.irq_number = COM3_IRQ; state->com4.irq_number = COM4_IRQ; - struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, state); - if (v3_attach_device(vm, dev) == -1) { PrintError("Could not attach device %s\n", dev_id); return -1; } + state->com1.vm_dev = dev; + state->com2.vm_dev = dev; + state->com3.vm_dev = dev; + state->com4.vm_dev = dev; + + PrintDebug("Serial device attached\n"); + v3_dev_hook_io(dev, COM1_DATA_PORT, &read_data_port, &write_data_port); v3_dev_hook_io(dev, COM1_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port); v3_dev_hook_io(dev, COM1_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port); @@ -990,6 +992,8 @@ static int serial_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) { v3_dev_hook_io(dev, COM4_MODEM_STATUS_PORT, &read_status_port, &write_status_port); v3_dev_hook_io(dev, COM4_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port); + PrintDebug("Serial ports hooked\n"); + return 0; } @@ -1001,6 +1005,9 @@ int v3_stream_register_serial(struct vm_device * serial_dev, struct v3_stream_op state->com1.backend_data = private_data; /* bind to other ports here */ + ops->input = serial_input; + ops->front_data = &(state->com1); + return 0; } diff --git a/palacios/src/devices/stream.c b/palacios/src/devices/stream.c index 0c6aed2..1b0d5c7 100644 --- a/palacios/src/devices/stream.c +++ b/palacios/src/devices/stream.c @@ -27,17 +27,18 @@ #include struct stream_state { - void *stream; + void *stream_in; + void *stream_out; struct vm_device *frontend_dev; + struct v3_stream_ops stream_ops; }; - static int stream_read(char *buf, uint_t length, void *private_data) { struct vm_device *dev = (struct vm_device *) private_data; struct stream_state *state = (struct stream_state *) dev->private_data; - return V3_StreamRead(state->stream,buf,length); + return V3_StreamRead(state->stream_out,buf,length); } static int stream_write(char *buf, uint_t length, void *private_data) @@ -45,15 +46,18 @@ static int stream_write(char *buf, uint_t length, void *private_data) struct vm_device *dev = (struct vm_device *) private_data; struct stream_state *state = (struct stream_state *) dev->private_data; - return V3_StreamWrite(state->stream,buf,length); + return V3_StreamWrite(state->stream_out,buf,length); } - -static struct v3_stream_ops stream_ops = { - .write = stream_write, - .read = stream_read, -}; +static void notify(void * data){ + struct stream_state *state = (struct stream_state *)data; + char temp[1024]; + int len; + + len = V3_StreamRead(state->stream_in, temp, 1024); + state->stream_ops.input(temp, len, state->stream_ops.front_data); +} static struct v3_device_ops dev_ops = { .free = NULL, @@ -68,42 +72,43 @@ static int stream_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) const char * frontend_tag = v3_cfg_val(frontend_cfg, "tag"); struct vm_device * frontend = v3_find_dev(vm, frontend_tag); char * dev_id = v3_cfg_val(cfg, "ID"); - char * path = v3_cfg_val(cfg, "localname"); + char * stream_in = v3_cfg_val(cfg, "stream_in"); + char * stream_out = v3_cfg_val(cfg, "stream_out"); struct stream_state *state; - /* read configuration */ + V3_ASSERT(frontend_cfg); V3_ASSERT(frontend_tag); V3_ASSERT(frontend); + V3_ASSERT(stream_in); + V3_ASSERT(stream_out); - - /* allocate state */ state = (struct stream_state *)V3_Malloc(sizeof(struct stream_state)); V3_ASSERT(state); state->frontend_dev = frontend; - V3_ASSERT(path); - - /* The system is responsible for interpreting the localname of the stream */ - state->stream = V3_StreamOpen(path, STREAM_OPEN_MODE_READ | STREAM_OPEN_MODE_WRITE); - if (!state->stream) { - PrintError("Could not open localname %s\n", path); + + state->stream_out = V3_StreamOpen(stream_out, NULL, NULL, STREAM_OPEN_MODE_READ | STREAM_OPEN_MODE_WRITE); + state->stream_in = V3_StreamOpen(stream_in, notify, state, STREAM_OPEN_MODE_READ | STREAM_OPEN_MODE_WRITE); + if (!state->stream_out || !state->stream_in) { + PrintError("Could not open stream %s %s\n", stream_in, stream_out); V3_Free(state); return -1; } - - /* allocate device */ + struct vm_device *dev = v3_allocate_device(dev_id, &dev_ops, state); V3_ASSERT(dev); - /* attach device to virtual machine */ if (v3_attach_device(vm, dev) == -1) { PrintError("Could not attach device %s\n", dev_id); V3_Free(state); return -1; } - v3_stream_register_serial(frontend, &stream_ops, dev); - + state->stream_ops.read = stream_read; + state->stream_ops.write = stream_write; + + v3_stream_register_serial(frontend, &(state->stream_ops), dev); + return 0; } diff --git a/palacios/src/palacios/vmm_io.c b/palacios/src/palacios/vmm_io.c index d094d79..5f762e4 100644 --- a/palacios/src/palacios/vmm_io.c +++ b/palacios/src/palacios/vmm_io.c @@ -124,7 +124,6 @@ int v3_hook_io_port(struct v3_vm_info * vm, uint16_t port, io_hook->write = write; } - io_hook->priv_data = priv_data; if (insert_io_hook(vm, io_hook)) {