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.


Split telemetry into global and per-core to avoid race printing core telemetry
[palacios.git] / palacios / src / devices / keyboard.c
index 43dd816..794e8b3 100644 (file)
@@ -28,7 +28,7 @@
 #include <palacios/vm_guest.h>
 
 
-#ifndef CONFIG_DEBUG_KEYBOARD
+#ifndef V3_CONFIG_DEBUG_KEYBOARD
 #undef PrintDebug
 #define PrintDebug(fmt, args...)
 #endif
@@ -185,6 +185,9 @@ struct keyboard_internal {
        // After the Keyboard SET_RATE is called
        // we wait for the output byte on 64?
        SET_RATE,
+        // after having a f0 sent to 60
+       // we wait for a new output byte on 60
+       GETSET_SCANCODES,
     } state;
 
 
@@ -208,7 +211,8 @@ struct keyboard_internal {
     // Data for system
     uint8_t wrap;     
 
-    int mouse_enabled;
+    uint8_t mouse_enabled;
+    uint8_t scancode_set;
 
     struct queue kbd_queue;
     struct queue mouse_queue;
@@ -331,7 +335,7 @@ static int pull_from_output_queue(struct keyboard_internal * state, uint8_t * va
 
 
 #include <palacios/vmm_telemetry.h>
-#ifdef CONFIG_SYMMOD
+#ifdef V3_CONFIG_SYMMOD
 #include <palacios/vmm_symmod.h>
 #endif
 
@@ -349,7 +353,7 @@ static int key_event_handler(struct v3_vm_info * vm,
        }
        //      PrintGuestPageTables(info, info->shdw_pg_state.guest_cr3);
     } 
-#ifdef CONFIG_SYMCALL
+#ifdef V3_CONFIG_SYMCALL
     else if (evt->scan_code == 0x43) { // F9 Sym test
        struct guest_info * core = &(vm->cores[0]);
        PrintDebug("Testing sym call\n");
@@ -381,13 +385,13 @@ static int key_event_handler(struct v3_vm_info * vm,
        v3_dbg_enable ^= 1;
 
     } 
-#ifdef CONFIG_TELEMETRY
+#ifdef V3_CONFIG_TELEMETRY
 
     else if (evt->scan_code == 0x41) { // F7 telemetry dump
-       v3_print_telemetry(vm);
+       v3_print_global_telemetry(vm);
     } 
 #endif
-#ifdef CONFIG_SYMMOD
+#ifdef V3_CONFIG_SYMMOD
     else if (evt->scan_code == 0x40) { // F6 Test symmod load
        v3_load_sym_capsule(vm, "lnx_test");
     }
@@ -441,41 +445,7 @@ static int mouse_event_handler(struct v3_vm_info * vm,
 }
 
 
-static int keyboard_reset_device(struct keyboard_internal * kbd) {
-  
-    memset(kbd, 0, sizeof(struct keyboard_internal));
-
-    kbd->state = NORMAL;
-    kbd->mouse_state = STREAM;
-
 
-    // PS2, keyboard+mouse enabled, generic translation    
-    kbd->cmd.val = 0;
-
-    kbd->cmd.irq_en = 1;
-    kbd->cmd.mouse_irq_en = 1;
-    kbd->cmd.self_test_ok = 1;
-    /** **/
-
-
-    // buffers empty, no errors
-    kbd->status.val = 0; 
-
-    kbd->status.self_test_ok = 1; // self-tests passed
-    kbd->status.enabled = 1;// keyboard ready
-    /** **/
-
-    
-    kbd->output_byte = 0;  //  ?
-
-    kbd->input_byte = INPUT_RAM;  // we have some
-    // also display=color, jumper 0, keyboard enabled 
-
-    PrintDebug("keyboard: reset device\n");
-    return 0;
-
-}
 
 
 
@@ -603,7 +573,7 @@ static int mouse_write_output(struct keyboard_internal * kbd, uint8_t data) {
 
 
 #if KEYBOARD_DEBUG_80H
-static int keyboard_write_delay(ushort_t port, void * src,  uint_t length, void * priv_data) {
+static int keyboard_write_delay(struct guest_info *core, ushort_t port, void * src,  uint_t length, void * priv_data) {
 
     if (length == 1) { 
        PrintDebug("keyboard: write of 0x%x to 80h\n", *((uint8_t*)src));
@@ -900,6 +870,34 @@ static int keyboard_write_output(struct guest_info * core, ushort_t port, void *
            kbd->state = NORMAL;
            break;
 
+       case GETSET_SCANCODES:
+           switch (data) {
+               case 0:
+                   PrintDebug("Keyboard: scancode set being read\n");
+                   push_to_output_queue(kbd, 0x45 - 2 * kbd->scancode_set, COMMAND, KEYBOARD);
+                   break;
+               case 1:
+                   PrintError("keyboard: unsupported scancode set %d selected\n", data);
+                   return -1;
+               case 2:
+                   PrintDebug("Keyboard: scancode set being set to %d\n", data);
+                   kbd->scancode_set = data;
+                   push_to_output_queue(kbd, 0xfa, COMMAND, KEYBOARD);
+                   break;
+               case 3:
+                   /* OpenBSD wants scancode set 3, but falls back to 2 if a
+                    * subsequent read reveals that the request was ignored
+                    */
+                   PrintError("keyboard: ignoring request for scancode set %d\n", data);
+                   break;
+               default:
+                   PrintError("keyboard: unknown scancode set %d selected\n", data);
+                   return -1;
+  
+           }
+           kbd->state = NORMAL;
+           break;
+
        default:
        case NORMAL: {
            // command is being sent to keyboard controller
@@ -939,6 +937,11 @@ static int keyboard_write_output(struct guest_info * core, ushort_t port, void *
                    push_to_output_queue(kbd, 0xee, COMMAND, KEYBOARD);
                    break;
 
+               case 0xf0: // get/set scancode set
+                   push_to_output_queue(kbd, 0xfa, COMMAND, KEYBOARD);
+                   kbd->state = GETSET_SCANCODES;
+                   break;
+
                case 0xfe: // resend
                case 0xfd: // set key type make
                case 0xfc: // set key typ make/break
@@ -991,18 +994,107 @@ static int keyboard_read_input(struct guest_info * core, ushort_t port, void * d
 
 
 
-static int keyboard_free(struct vm_device * dev) {
+static int keyboard_free(struct keyboard_internal * kbd) {
     
+
+    // unhook host events
+
+    V3_Free(kbd);
     return 0;
 }
 
 
 
 
+static int keyboard_reset_device(struct keyboard_internal * kbd) {
+  
+
+    kbd->mouse_queue.start = 0;
+    kbd->mouse_queue.end = 0;
+    kbd->mouse_queue.count = 0;
+
+    kbd->kbd_queue.start = 0;
+    kbd->kbd_queue.end = 0;
+    kbd->kbd_queue.count = 0;
 
-static struct v3_device_ops dev_ops = { 
-    .free = keyboard_free,
+    kbd->mouse_enabled = 0;
+    kbd->scancode_set = 2;
+
+    kbd->state = NORMAL;
+    kbd->mouse_state = STREAM;
+
+    // PS2, keyboard+mouse enabled, generic translation    
+    kbd->cmd.val = 0;
+
+    kbd->cmd.irq_en = 1;
+    kbd->cmd.mouse_irq_en = 1;
+    kbd->cmd.self_test_ok = 1;
+    /** **/
+
+
+    // buffers empty, no errors
+    kbd->status.val = 0; 
+
+    kbd->status.self_test_ok = 1; // self-tests passed
+    kbd->status.enabled = 1;// keyboard ready
+    /** **/
 
+    
+    kbd->output_byte = 0;  //  ?
+
+    kbd->input_byte = INPUT_RAM;  // we have some
+    // also display=color, jumper 0, keyboard enabled 
+
+    PrintDebug("keyboard: reset device\n");
+    return 0;
+
+}
+
+#ifdef V3_CONFIG_CHECKPOINT
+static int keyboard_save(struct v3_chkpt_ctx * ctx, void * private_data) {
+    struct keyboard_internal * kbd = (struct keyboard_internal *)private_data;
+
+    v3_chkpt_save_8(ctx, "CMD_REG", &(kbd->cmd.val));
+    v3_chkpt_save_8(ctx, "STATUS_REG", &(kbd->status.val));
+    v3_chkpt_save_8(ctx, "STATE", &(kbd->state));
+    v3_chkpt_save_8(ctx, "MOUSE_STATE", &(kbd->mouse_state));
+    v3_chkpt_save_8(ctx, "OUTPUT", &(kbd->output_byte));
+    v3_chkpt_save_8(ctx, "INPUT", &(kbd->input_byte));
+    v3_chkpt_save_8(ctx, "SCANCODE_SET", &(kbd->scancode_set));
+    v3_chkpt_save_8(ctx, "MOUSE_ENABLED", &(kbd->mouse_enabled));
+
+
+    return 0;
+}
+
+
+static int keyboard_load(struct v3_chkpt_ctx * ctx, void * private_data) {
+    struct keyboard_internal * kbd = (struct keyboard_internal *)private_data;
+    keyboard_reset_device(kbd);
+
+    v3_chkpt_load_8(ctx, "CMD_REG", &(kbd->cmd.val));
+    v3_chkpt_load_8(ctx, "STATUS_REG", &(kbd->status.val));
+    v3_chkpt_load_8(ctx, "STATE", &(kbd->state));
+    v3_chkpt_load_8(ctx, "MOUSE_STATE", &(kbd->mouse_state));
+    v3_chkpt_load_8(ctx, "OUTPUT", &(kbd->output_byte));
+    v3_chkpt_load_8(ctx, "INPUT", &(kbd->input_byte));
+    v3_chkpt_load_8(ctx, "SCANCODE_SET", &(kbd->scancode_set));
+    v3_chkpt_load_8(ctx, "MOUSE_ENABLED", &(kbd->mouse_enabled));
+
+
+    return 0;
+}
+
+#endif
+
+
+static struct v3_device_ops dev_ops = { 
+    .free = (int (*)(void *))keyboard_free,
+#ifdef V3_CONFIG_CHECKPOINT
+    .save = keyboard_save,
+    .load = keyboard_load
+#endif
 };
 
 
@@ -1011,6 +1103,7 @@ static struct v3_device_ops dev_ops = {
 static int keyboard_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
     struct keyboard_internal * kbd = NULL;
     char * dev_id = v3_cfg_val(cfg, "ID");
+    int ret = 0;
 
     PrintDebug("keyboard: init_device\n");
 
@@ -1020,20 +1113,11 @@ static int keyboard_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
 
     kbd->vm = vm;
 
-    kbd->mouse_queue.start = 0;
-    kbd->mouse_queue.end = 0;
-    kbd->mouse_queue.count = 0;
+    struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, kbd);
 
-    kbd->kbd_queue.start = 0;
-    kbd->kbd_queue.end = 0;
-    kbd->kbd_queue.count = 0;
-
-    kbd->mouse_enabled = 0;
-
-    struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, kbd);
-
-    if (v3_attach_device(vm, dev) == -1) {
+    if (dev == NULL) {
        PrintError("Could not attach device %s\n", dev_id);
+       V3_Free(kbd);
        return -1;
     }
 
@@ -1044,11 +1128,17 @@ static int keyboard_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
 
 
     // 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);
+    ret |= v3_dev_hook_io(dev, KEYBOARD_64H, &keyboard_read_status, &keyboard_write_command);
+    ret |= v3_dev_hook_io(dev, KEYBOARD_60H, &keyboard_read_input, &keyboard_write_output);
+
+    if (ret != 0) {
+       PrintError("Error hooking keyboard IO ports\n");
+       v3_remove_device(dev);
+       return -1;
+    }
 
-    v3_hook_host_event(vm, HOST_KEYBOARD_EVT, V3_HOST_EVENT_HANDLER(key_event_handler), dev);
-    v3_hook_host_event(vm, HOST_MOUSE_EVT, V3_HOST_EVENT_HANDLER(mouse_event_handler), dev);
+    v3_hook_host_event(vm, HOST_KEYBOARD_EVT, V3_HOST_EVENT_HANDLER(key_event_handler), kbd);
+    v3_hook_host_event(vm, HOST_MOUSE_EVT, V3_HOST_EVENT_HANDLER(mouse_event_handler), kbd);
 
 
 #if KEYBOARD_DEBUG_80H