Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


added locking operations to devices interfacing with host events
Jack Lange [Sat, 13 Jun 2009 00:16:12 +0000 (19:16 -0500)]
palacios/src/devices/keyboard.c
palacios/src/devices/net_cd.c
palacios/src/devices/nvram.c

index 5cef405..65e8797 100644 (file)
@@ -21,6 +21,8 @@
 #include <palacios/vmm.h>
 #include <palacios/vmm_types.h>
 
+#include <palacios/vmm_lock.h>
+
 
 #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);
index 0e2b49c..1532b16 100644 (file)
@@ -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");
index 2606c5f..f43cbd0 100644 (file)
@@ -22,6 +22,7 @@
 #include <palacios/vmm.h>
 #include <palacios/vmm_types.h>
 
+#include <palacios/vmm_lock.h>
 
 #include <devices/ide.h>
 
@@ -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]);