From: Jack Lange Date: Sat, 13 Jun 2009 00:16:12 +0000 (-0500) Subject: added locking operations to devices interfacing with host events X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=commitdiff_plain;h=62786ba1c9a264dfd00aa705f62bd65b5b0e7bb0 added locking operations to devices interfacing with host events --- diff --git a/palacios/src/devices/keyboard.c b/palacios/src/devices/keyboard.c index 5cef405..65e8797 100644 --- a/palacios/src/devices/keyboard.c +++ b/palacios/src/devices/keyboard.c @@ -21,6 +21,8 @@ #include #include +#include + #ifndef DEBUG_KEYBOARD #undef PrintDebug @@ -211,6 +213,7 @@ struct keyboard_internal { //uint_t output_queue_read; //uint_t output_queue_write; + v3_lock_t kb_lock; }; @@ -310,17 +313,20 @@ static int key_event_handler(struct guest_info * info, PrintDebug("keyboard: injected status 0x%x, and scancode 0x%x\n", evt->status, evt->scan_code); - if (evt->scan_code == 0x44) { // F10 debug dump v3_print_guest_state(info); // PrintGuestPageTables(info, info->shdw_pg_state.guest_cr3); } + addr_t irq_state = v3_lock_irqsave(state->kb_lock); + if ( (state->status_byte & STATUS_ENABLED) // onboard is enabled && (!(state->cmd_byte & CMD_DISABLE)) ) { // keyboard is enabled PushToOutputQueue(dev, evt->scan_code, OVERWRITE, DATA, KEYBOARD); } + + v3_unlock_irqrestore(state->kb_lock, irq_state); return 0; } @@ -331,10 +337,12 @@ static int mouse_event_handler(struct guest_info * info, void * private_data) { struct vm_device * dev = (struct vm_device *)private_data; struct keyboard_internal * state = (struct keyboard_internal *)(dev->private_data); - + int ret = 0; PrintDebug("keyboard: injected mouse packet 0x %x %x %x\n", evt->data[0], evt->data[1], evt->data[2]); + addr_t irq_state = v3_lock_irqsave(state->kb_lock); + memcpy(state->mouse_packet, evt->data, 3); state->status_byte |= STATUS_MOUSE_BUFFER_FULL; @@ -349,11 +357,15 @@ static int mouse_event_handler(struct guest_info * info, } break; default: - return -1; + PrintError("Invalid mouse state\n"); + ret = -1; break; } - return 0; + + v3_unlock_irqrestore(state->kb_lock, irq_state); + + return ret; } @@ -770,6 +782,9 @@ static int keyboard_write_command(ushort_t port, cmd = *((uchar_t*)src); + + addr_t irq_state = v3_lock_irqsave(state->kb_lock); + if (state->state != NORMAL) { PrintDebug("keyboard: warning - receiving command on 64h but state != NORMAL\n"); } @@ -947,8 +962,9 @@ static int keyboard_write_command(ushort_t port, break; } - return 1; + v3_unlock_irqrestore(state->kb_lock, irq_state); + return length; } static int keyboard_read_status(ushort_t port, @@ -958,19 +974,21 @@ static int keyboard_read_status(ushort_t port, { struct keyboard_internal *state = (struct keyboard_internal *)(dev->private_data); - if (length == 1) { - - PrintDebug("keyboard: read status (64h): "); - - *((uchar_t*)dest) = state->status_byte; - - PrintDebug("0x%x\n", *((uchar_t*)dest)); - - return 1; - } else { + if (length != 1) { PrintError("keyboard: >1 byte read for status (64h)\n"); return -1; } + + + PrintDebug("keyboard: read status (64h): "); + + addr_t irq_state = v3_lock_irqsave(state->kb_lock); + *((uchar_t*)dest) = state->status_byte; + v3_unlock_irqrestore(state->kb_lock, irq_state); + + PrintDebug("0x%x\n", *((uchar_t*)dest)); + + return length; } static int keyboard_write_output(ushort_t port, @@ -979,6 +997,7 @@ static int keyboard_write_output(ushort_t port, struct vm_device * dev) { struct keyboard_internal *state = (struct keyboard_internal *)(dev->private_data); + int ret = 0; if (length != 1) { PrintError("keyboard: write of 60h with >1 byte\n"); @@ -989,6 +1008,8 @@ static int keyboard_write_output(ushort_t port, PrintDebug("keyboard: output 0x%x on 60h\n", data); + addr_t irq_state = v3_lock_irqsave(state->kb_lock); + switch (state->state) { case WRITING_CMD_BYTE: state->cmd_byte = data; @@ -1081,13 +1102,15 @@ static int keyboard_write_output(ushort_t port, case 0xf8: // set all make/break case 0xf7: // set all typemaktic case 0xf6: // set defaults - PrintDebug("keyboard: unhandled known command 0x%x on output buffer (60h)\n", data); - return -1; + PrintError("keyboard: unhandled known command 0x%x on output buffer (60h)\n", data); + + ret = -1; break; default: - PrintDebug("keyboard: unhandled unknown command 0x%x on output buffer (60h)\n", data); + PrintError("keyboard: unhandled unknown command 0x%x on output buffer (60h)\n", data); state->status_byte |= 0x1; - return -1; + + ret = -1; break; } break; @@ -1095,7 +1118,13 @@ static int keyboard_write_output(ushort_t port, } - return 1; + v3_unlock_irqrestore(state->kb_lock, irq_state); + + if (ret == -1) { + return -1; + } + + return length; } static int keyboard_read_input(ushort_t port, @@ -1103,48 +1132,53 @@ static int keyboard_read_input(ushort_t port, uint_t length, struct vm_device * dev) { - struct keyboard_internal *state = (struct keyboard_internal *)(dev->private_data); - if (length == 1) { - uchar_t data; - int done_mouse; + uchar_t data; + int done_mouse; + struct keyboard_internal *state = (struct keyboard_internal *)(dev->private_data); + + if (length != 1) { + PrintError("keyboard: unknown size read from input (60h)\n"); + return -1; + } + + PrintDebug("keyboard: read from input (60h): "); - PrintDebug("keyboard: read from input (60h): "); + addr_t irq_state = v3_lock_irqsave(state->kb_lock); - if (state->state == IN_MOUSE) { - done_mouse = mouse_read_input(dev); - if (done_mouse) { - state->state = NORMAL; - } - } - - PullFromOutputQueue(dev, &data); - - if (state->state == RESET) { - // We just delivered the ack for the reset - // now we will ready ourselves to deliver the BAT code (success) - PushToOutputQueue(dev, 0xaa, OVERWRITE, COMMAND, KEYBOARD); - state->state = NORMAL; - PrintDebug(" (in reset, pushing BAT test code 0xaa) "); - } else if (state->state == KBD_ID1) { - PushToOutputQueue(dev, 0xab, OVERWRITE, COMMAND, KEYBOARD); - state->state = KBD_ID2; - PrintDebug(" (in kbd id request, pushing 1st ID val) "); - } else if (state->state == KBD_ID2) { - PushToOutputQueue(dev, 0x83, OVERWRITE, COMMAND, KEYBOARD); + if (state->state == IN_MOUSE) { + done_mouse = mouse_read_input(dev); + if (done_mouse) { state->state = NORMAL; - PrintDebug(" (in kbd id request, pushing 2nd ID val) "); } + } + + PullFromOutputQueue(dev, &data); + + if (state->state == RESET) { + // We just delivered the ack for the reset + // now we will ready ourselves to deliver the BAT code (success) + PushToOutputQueue(dev, 0xaa, OVERWRITE, COMMAND, KEYBOARD); + state->state = NORMAL; + PrintDebug(" (in reset, pushing BAT test code 0xaa) "); + } else if (state->state == KBD_ID1) { + PushToOutputQueue(dev, 0xab, OVERWRITE, COMMAND, KEYBOARD); + state->state = KBD_ID2; + PrintDebug(" (in kbd id request, pushing 1st ID val) "); + } else if (state->state == KBD_ID2) { + PushToOutputQueue(dev, 0x83, OVERWRITE, COMMAND, KEYBOARD); + state->state = NORMAL; + PrintDebug(" (in kbd id request, pushing 2nd ID val) "); + } - PrintDebug("0x%x\n", data); + v3_unlock_irqrestore(state->kb_lock, irq_state); + + PrintDebug("0x%x\n", data); + + *((uchar_t*)dest) = data; + + return length; - *((uchar_t*)dest) = data; - - return 1; - } else { - PrintError("keyboard: unknown size read from input (60h)\n"); - return -1; - } } @@ -1154,14 +1188,16 @@ static int keyboard_read_input(ushort_t port, static int keyboard_init_device(struct vm_device * dev) { - // struct keyboard_internal *data = (struct keyboard_internal *) dev->private_data; + struct keyboard_internal *data = (struct keyboard_internal *) dev->private_data; PrintDebug("keyboard: init_device\n"); - // Would read state here - keyboard_reset_device(dev); + + v3_lock_init(&(data->kb_lock)); + + // hook ports v3_dev_hook_io(dev, KEYBOARD_64H, &keyboard_read_status, &keyboard_write_command); v3_dev_hook_io(dev, KEYBOARD_60H, &keyboard_read_input, &keyboard_write_output); diff --git a/palacios/src/devices/net_cd.c b/palacios/src/devices/net_cd.c index 0e2b49c..1532b16 100644 --- a/palacios/src/devices/net_cd.c +++ b/palacios/src/devices/net_cd.c @@ -58,12 +58,13 @@ struct cd_state { static int send_all(int socket, char * buf, int length) { int bytes_sent = 0; + PrintDebug("Sending %d bytes\n", length - bytes_sent); while (bytes_sent < length) { - PrintDebug("Sending %d bytes\n", length - bytes_sent); int tmp_bytes = V3_Send(socket, buf + bytes_sent, length - bytes_sent); PrintDebug("Sent %d bytes\n", tmp_bytes); if (tmp_bytes == 0) { + PrintError("Connection Closed unexpectedly\n"); return -1; } @@ -77,12 +78,13 @@ static int send_all(int socket, char * buf, int length) { static int recv_all(int socket, char * buf, int length) { int bytes_read = 0; + PrintDebug("Reading %d bytes\n", length - bytes_read); while (bytes_read < length) { - PrintDebug("Reading %d bytes\n", length - bytes_read); int tmp_bytes = V3_Recv(socket, buf + bytes_read, length - bytes_read); PrintDebug("Received %d bytes\n", tmp_bytes); if (tmp_bytes == 0) { + PrintError("Connection Closed unexpectedly\n"); return -1; } @@ -141,7 +143,7 @@ static int cd_read(uint8_t * buf, int block_count, uint64_t lba, void * private return -1; } - PrintDebug("Reading Data\n"); + PrintDebug("Reading Data (%d bytes)\n", ret_len); if (recv_all(cd->socket, (char *)buf, ret_len) == -1) { PrintError("Read Data Error\n"); diff --git a/palacios/src/devices/nvram.c b/palacios/src/devices/nvram.c index 2606c5f..f43cbd0 100644 --- a/palacios/src/devices/nvram.c +++ b/palacios/src/devices/nvram.c @@ -22,6 +22,7 @@ #include #include +#include #include @@ -99,6 +100,8 @@ struct nvram_internal { struct vm_device * ide; + v3_lock_t nvram_lock; + uint_t us; //microseconds - for clock update - zeroed every second uint_t pus; //microseconds - for periodic interrupt - cleared every period }; @@ -206,7 +209,7 @@ static uchar_t add_to(uchar_t * left, uchar_t * right, uchar_t bcd) { } -static uchar_t days_in_month(struct vm_device * dev, uchar_t month, uchar_t bcd) { +static uchar_t days_in_month(uchar_t month, uchar_t bcd) { // This completely ignores Julian / Gregorian stuff right now if (bcd) { @@ -264,7 +267,7 @@ static uchar_t days_in_month(struct vm_device * dev, uchar_t month, uchar_t bcd) } -static void update_time(struct vm_device * dev, uint_t period_us) { +static void update_time( struct vm_device * dev, uint_t period_us) { struct nvram_internal * data = (struct nvram_internal *) (dev->private_data); struct rtc_stata * stata = (struct rtc_stata *) &((data->mem_state[NVRAM_REG_STAT_A])); struct rtc_statb * statb = (struct rtc_statb *) &((data->mem_state[NVRAM_REG_STAT_B])); @@ -387,7 +390,7 @@ static void update_time(struct vm_device * dev, uint_t period_us) { *weekday %= 0x7; // same regardless of bcd - if ((*monthday) != days_in_month(dev, *month, bcd)) { + if ((*monthday) != days_in_month(*month, bcd)) { add_to(monthday, &carry, bcd); } else { *monthday = 0x1; @@ -458,7 +461,11 @@ static int handle_timer_event(struct guest_info * info, struct vm_device * dev = (struct vm_device *)priv_data; if (dev) { + struct nvram_internal * data = (struct nvram_internal *) (dev->private_data); + + addr_t irq_state = v3_lock_irqsave(data->nvram_lock); update_time(dev, evt->period_us); + v3_unlock_irqrestore(data->nvram_lock, irq_state); } return 0; @@ -589,6 +596,8 @@ static int init_nvram_state(struct vm_device * dev) { memset(nvram->mem_state, 0, NVRAM_REG_MAX); memset(nvram->reg_map, 0, NVRAM_REG_MAX / 8); + v3_lock_init(&(nvram->nvram_lock)); + // // 2 1.44 MB floppy drives // @@ -715,8 +724,13 @@ static int nvram_read_data_port(ushort_t port, struct nvram_internal * data = (struct nvram_internal *)dev->private_data; + addr_t irq_state = v3_lock_irqsave(data->nvram_lock); + if (get_memory(data, data->thereg, (uint8_t *)dst) == -1) { PrintError("Register %d (0x%x) Not set\n", data->thereg, data->thereg); + + v3_unlock_irqrestore(data->nvram_lock, irq_state); + return -1; } @@ -727,6 +741,8 @@ static int nvram_read_data_port(ushort_t port, data->mem_state[data->thereg] ^= 0x80; // toggle Update in progess } + v3_unlock_irqrestore(data->nvram_lock, irq_state); + return 1; } @@ -738,8 +754,12 @@ static int nvram_write_data_port(ushort_t port, struct nvram_internal * data = (struct nvram_internal *)dev->private_data; + addr_t irq_state = v3_lock_irqsave(data->nvram_lock); + set_memory(data, data->thereg, *(uint8_t *)src); + v3_unlock_irqrestore(data->nvram_lock, irq_state); + PrintDebug("nvram_write_data_port(0x%x) = 0x%x\n", data->thereg, data->mem_state[data->thereg]);