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.


Cleanup and sanity-checking of use of strncpy/strcpy (Coverity static analysis)
[palacios.git] / palacios / src / devices / generic.c
index 21b2fc4..23f00ce 100644 (file)
 #include <palacios/vmm_dev_mgr.h>
 #include <palacios/vm_guest_mem.h>
 
-#ifdef CONFIG_HOST_DEVICE
+#ifdef V3_CONFIG_HOST_DEVICE
 #include <interfaces/vmm_host_dev.h>
 #endif
 
-#ifndef CONFIG_DEBUG_GENERIC
+#ifndef V3_CONFIG_DEBUG_GENERIC
 #undef PrintDebug
 #define PrintDebug(fmt, args...)
 #endif
@@ -45,7 +45,7 @@ typedef enum {GENERIC_IGNORE,
 
 struct generic_internal {
     enum {GENERIC_PHYSICAL, GENERIC_HOST} forward_type;
-#ifdef CONFIG_HOST_DEVICE
+#ifdef V3_CONFIG_HOST_DEVICE
     v3_host_dev_t                         host_dev;
 #endif
     struct vm_device                      *dev; // me
@@ -88,7 +88,7 @@ static int generic_write_port_passthrough(struct guest_info * core,
            }
            return length;
            break;
-#ifdef CONFIG_HOST_DEVICE
+#ifdef V3_CONFIG_HOST_DEVICE
        case GENERIC_HOST:
            if (state->host_dev) { 
                return v3_host_dev_write_io(state->host_dev,port,src,length);
@@ -98,7 +98,7 @@ static int generic_write_port_passthrough(struct guest_info * core,
            break;
 #endif
        default:
-           PrintError("generic (%s): unknown forwarding type\n", state->name);
+           PrintError(core->vm_info, core, "generic (%s): unknown forwarding type\n", state->name);
            return -1;
            break;
     }
@@ -109,26 +109,26 @@ static int generic_write_port_print_and_passthrough(struct guest_info * core, ui
     uint_t i;
     int rc;
 
-#ifdef CONFIG_DEBUG_GENERIC
+#ifdef V3_CONFIG_DEBUG_GENERIC
     struct generic_internal *state = (struct generic_internal *) priv_data;
 #endif
 
-    PrintDebug("generic (%s): writing 0x%x bytes to port 0x%x using %s ...", state->name,
+    PrintDebug(core->vm_info, core, "generic (%s): writing 0x%x bytes to port 0x%x using %s ...", state->name,
               length, port,
               state->forward_type == GENERIC_PHYSICAL ? "physical" :
               state->forward_type == GENERIC_HOST ? "host" : "UNKNOWN");
 
-    PrintDebug("generic (%s): writing 0x", state->name);
+    PrintDebug(core->vm_info, core, "generic (%s): writing 0x", state->name);
 
     for (i = 0; i < length; i++) { 
-       PrintDebug("%x", ((uint8_t *)src)[i]);
+       PrintDebug(core->vm_info, core, "%x", ((uint8_t *)src)[i]);
     }
   
-    PrintDebug(" to port 0x%x ... ", port);
+    PrintDebug(core->vm_info, core, " to port 0x%x ... ", port);
 
     rc=generic_write_port_passthrough(core,port,src,length,priv_data);
 
-    PrintDebug(" done\n");
+    PrintDebug(core->vm_info, core, " done\n");
   
     return rc;
 }
@@ -162,7 +162,7 @@ static int generic_read_port_passthrough(struct guest_info * core,
            }
            return length;
            break;
-#ifdef CONFIG_HOST_DEVICE
+#ifdef V3_CONFIG_HOST_DEVICE
        case GENERIC_HOST:
            if (state->host_dev) { 
                return v3_host_dev_read_io(state->host_dev,port,dst,length);
@@ -170,7 +170,7 @@ static int generic_read_port_passthrough(struct guest_info * core,
            break;
 #endif
        default:
-           PrintError("generic (%s): unknown forwarding type\n", state->name);
+           PrintError(core->vm_info, core, "generic (%s): unknown forwarding type\n", state->name);
            return -1;
            break;
     }
@@ -183,24 +183,24 @@ static int generic_read_port_print_and_passthrough(struct guest_info * core, uin
     uint_t i;
     int rc;
 
-#ifdef CONFIG_DEBUG_GENERIC
+#ifdef V3_CONFIG_DEBUG_GENERIC
     struct generic_internal *state = (struct generic_internal *) priv_data;
 #endif
 
-    PrintDebug("generic (%s): reading 0x%x bytes from port 0x%x using %s ...", state->name, length, port,
+    PrintDebug(core->vm_info, core, "generic (%s): reading 0x%x bytes from port 0x%x using %s ...", state->name, length, port,
               state->forward_type == GENERIC_PHYSICAL ? "physical" :
               state->forward_type == GENERIC_HOST ? "host" : "UNKNOWN");
 
 
     rc=generic_read_port_passthrough(core,port,src,length,priv_data);
 
-    PrintDebug(" done ... read 0x");
+    PrintDebug(core->vm_info, core, " done ... read 0x");
 
     for (i = 0; i < rc; i++) { 
-       PrintDebug("%x", ((uint8_t *)src)[i]);
+       PrintDebug(core->vm_info, core, "%x", ((uint8_t *)src)[i]);
     }
 
-    PrintDebug("\n");
+    PrintDebug(core->vm_info, core, "\n");
 
     return rc;
 }
@@ -217,17 +217,17 @@ static int generic_read_port_ignore(struct guest_info * core, uint16_t port, voi
 static int generic_read_port_print_and_ignore(struct guest_info * core, uint16_t port, void * src, 
                                              uint_t length, void * priv_data) {
    
-#ifdef CONFIG_DEBUG_GENERIC
+#ifdef V3_CONFIG_DEBUG_GENERIC
     struct generic_internal *state = (struct generic_internal *) priv_data;
 #endif
 
-    PrintDebug("generic (%s): reading 0x%x bytes from port 0x%x using %s ...", state->name, length, port,
+    PrintDebug(core->vm_info, core, "generic (%s): reading 0x%x bytes from port 0x%x using %s ...", state->name, length, port,
               state->forward_type == GENERIC_PHYSICAL ? "physical" :
               state->forward_type == GENERIC_HOST ? "host" : "UNKNOWN");
 
 
     memset((uint8_t *)src, 0, length);
-    PrintDebug(" ignored (return zeroed buffer)\n");
+    PrintDebug(core->vm_info, core, " ignored (return zeroed buffer)\n");
 
     return length;
 }
@@ -242,22 +242,22 @@ static int generic_write_port_print_and_ignore(struct guest_info * core, uint16_
                                              uint_t length, void * priv_data) {
     int i;
 
-#ifdef CONFIG_DEBUG_GENERIC
+#ifdef V3_CONFIG_DEBUG_GENERIC
     struct generic_internal *state = (struct generic_internal *) priv_data;
 #endif
 
-    PrintDebug("generic (%s): writing 0x%x bytes to port 0x%x using %s ", state->name, length, port,
+    PrintDebug(core->vm_info, core, "generic (%s): writing 0x%x bytes to port 0x%x using %s ", state->name, length, port,
               state->forward_type == GENERIC_PHYSICAL ? "physical" :
               state->forward_type == GENERIC_HOST ? "host" : "UNKNOWN");
     
     memset((uint8_t *)src, 0, length);
-    PrintDebug(" ignored - data was: 0x");
+    PrintDebug(core->vm_info, core, " ignored - data was: 0x");
 
     for (i = 0; i < length; i++) { 
-       PrintDebug("%x", ((uint8_t *)src)[i]);
+       PrintDebug(core->vm_info, core, "%x", ((uint8_t *)src)[i]);
     }
     
-    PrintDebug("\n");
+    PrintDebug(core->vm_info, core, "\n");
 
     return length;
 }
@@ -278,7 +278,7 @@ static int generic_write_mem_passthrough(struct guest_info * core,
            memcpy(V3_VAddr((void*)gpa),src,len);
            return len;
            break;
-#ifdef CONFIG_HOST_DEVICE
+#ifdef V3_CONFIG_HOST_DEVICE
        case GENERIC_HOST:
            if (state->host_dev) { 
                return v3_host_dev_write_mem(state->host_dev,gpa,src,len);
@@ -288,7 +288,7 @@ static int generic_write_mem_passthrough(struct guest_info * core,
            break;
 #endif
        default:
-           PrintError("generic (%s): unknown forwarding type\n", state->name);
+           PrintError(core->vm_info, core, "generic (%s): unknown forwarding type\n", state->name);
            return -1;
            break;
     }
@@ -300,19 +300,19 @@ static int generic_write_mem_print_and_passthrough(struct guest_info * core,
                                                   uint_t              len,
                                                   void              * priv)
 {
-#ifdef CONFIG_DEBUG_GENERIC
+#ifdef V3_CONFIG_DEBUG_GENERIC
     struct vm_device *dev = (struct vm_device *) priv;
     struct generic_internal *state = (struct generic_internal *) dev->private_data;
 #endif
 
-    PrintDebug("generic (%s): writing %u bytes to GPA 0x%p via %s ... ", state->name,
+    PrintDebug(core->vm_info, core, "generic (%s): writing %u bytes to GPA 0x%p via %s ... ", state->name,
               len,(void*)gpa,
               state->forward_type == GENERIC_PHYSICAL ? "physical" : 
               state->forward_type == GENERIC_HOST ? "host" : "UNKNOWN");
     
     int rc = generic_write_mem_passthrough(core,gpa,src,len,priv);
 
-    PrintDebug("done\n");
+    PrintDebug(core->vm_info, core, "done\n");
     
     return rc;
 }
@@ -332,12 +332,12 @@ static int generic_write_mem_print_and_ignore(struct guest_info * core,
                                              uint_t              len,
                                              void              * priv)
 {
-#ifdef CONFIG_DEBUG_GENERIC
+#ifdef V3_CONFIG_DEBUG_GENERIC
     struct vm_device *dev = (struct vm_device *) priv;
     struct generic_internal *state = (struct generic_internal *) dev->private_data;
 #endif
 
-    PrintDebug("generic (%s): ignoring write of %u bytes to GPA 0x%p via %s", state->name,
+    PrintDebug(core->vm_info, core, "generic (%s): ignoring write of %u bytes to GPA 0x%p via %s", state->name,
               len,(void*)gpa,
               state->forward_type == GENERIC_PHYSICAL ? "physical" : 
               state->forward_type == GENERIC_HOST ? "host" : "UNKNOWN");
@@ -359,7 +359,7 @@ static int generic_read_mem_passthrough(struct guest_info * core,
            memcpy(dst,V3_VAddr((void*)gpa),len);
            return len;
            break;
-#ifdef CONFIG_HOST_DEVICE
+#ifdef V3_CONFIG_HOST_DEVICE
        case GENERIC_HOST:
            if (state->host_dev) { 
                return v3_host_dev_read_mem(state->host_dev,gpa,dst,len);
@@ -369,7 +369,7 @@ static int generic_read_mem_passthrough(struct guest_info * core,
            break;
 #endif
        default:
-           PrintError("generic (%s): unknown forwarding type\n", state->name);
+           PrintError(core->vm_info, core, "generic (%s): unknown forwarding type\n", state->name);
            break;
     }
     
@@ -382,19 +382,19 @@ static int generic_read_mem_print_and_passthrough(struct guest_info * core,
                                                  uint_t              len,
                                                  void              * priv)
 {
-#ifdef CONFIG_DEBUG_GENERIC
+#ifdef V3_CONFIG_DEBUG_GENERIC
     struct vm_device *dev = (struct vm_device *) priv;
     struct generic_internal *state = (struct generic_internal *) dev->private_data;
 #endif
 
-    PrintDebug("generic (%s): attempting to read %u bytes from GPA 0x%p via %s ... ", state->name,
+    PrintDebug(core->vm_info, core, "generic (%s): attempting to read %u bytes from GPA 0x%p via %s ... ", state->name,
               len,(void*)gpa,
               state->forward_type == GENERIC_PHYSICAL ? "physical" : 
               state->forward_type == GENERIC_HOST ? "host" : "UNKNOWN");
     
     int rc = generic_read_mem_passthrough(core,gpa,dst,len,priv);
 
-    PrintDebug("done - read %d bytes\n", rc);
+    PrintDebug(core->vm_info, core, "done - read %d bytes\n", rc);
     
     return rc;
 }
@@ -405,19 +405,19 @@ static int generic_read_mem_ignore(struct guest_info * core,
                                   uint_t              len,
                                   void              * priv)
 {
-#ifdef CONFIG_DEBUG_GENERIC
+#ifdef V3_CONFIG_DEBUG_GENERIC
     struct vm_device *dev = (struct vm_device *) priv;
     struct generic_internal *state = (struct generic_internal *) dev->private_data;
 #endif
 
-    PrintDebug("generic (%s): ignoring attempt to read %u bytes from GPA 0x%p via %s ... ", state->name,
+    PrintDebug(core->vm_info, core, "generic (%s): ignoring attempt to read %u bytes from GPA 0x%p via %s ... ", state->name,
               len,(void*)gpa,
               state->forward_type == GENERIC_PHYSICAL ? "physical" : 
               state->forward_type == GENERIC_HOST ? "host" : "UNKNOWN");
 
     memset((uint8_t *)dst, 0, len);
 
-    PrintDebug("returning zeros\n");
+    PrintDebug(core->vm_info, core, "returning zeros\n");
 
     return len;
 }
@@ -437,9 +437,9 @@ static int generic_read_mem_print_and_ignore(struct guest_info * core,
 static int generic_free(struct generic_internal * state) {
     int i;
     
-    PrintDebug("generic (%s): deinit_device\n", state->name);
+    PrintDebug(VM_NONE,VCORE_NONE, "generic (%s): deinit_device\n", state->name);
     
-#ifdef CONFIG_HOST_DEVICE
+#ifdef V3_CONFIG_HOST_DEVICE
     if (state->host_dev) { 
        v3_host_dev_close(state->host_dev);
        state->host_dev=0;
@@ -450,7 +450,7 @@ static int generic_free(struct generic_internal * state) {
     // We need to handle unhooking memory regions    
     for (i=0;i<state->num_mem_hooks;i++) {
        if (v3_unhook_mem(state->dev->vm,V3_MEM_CORE_ANY,state->mem_hook[i])<0) { 
-           PrintError("generic (%s): unable to unhook memory starting at 0x%p\n", state->name,(void*)(state->mem_hook[i]));
+           PrintError(VM_NONE,VCORE_NONE , "generic (%s): unable to unhook memory starting at 0x%p\n", state->name,(void*)(state->mem_hook[i]));
            return -1;
        }
     }
@@ -475,7 +475,7 @@ static int add_port_range(struct vm_device * dev, uint_t start, uint_t end, gene
 
     struct generic_internal *state = (struct generic_internal *) dev->private_data;
 
-    PrintDebug("generic (%s): adding port range 0x%x to 0x%x as %s\n", state->name,
+    PrintDebug(VM_NONE, VCORE_NONE, "generic (%s): adding port range 0x%x to 0x%x as %s\n", state->name,
               start, end, 
               (mode == GENERIC_PRINT_AND_PASSTHROUGH) ? "print-and-passthrough" : 
               (mode == GENERIC_PRINT_AND_IGNORE) ? "print-and-ignore" :
@@ -488,7 +488,7 @@ static int add_port_range(struct vm_device * dev, uint_t start, uint_t end, gene
                if (v3_dev_hook_io(dev, i, 
                                   &generic_read_port_print_and_passthrough, 
                                   &generic_write_port_print_and_passthrough) == -1) { 
-                   PrintError("generic (%s): can't hook port 0x%x (already hooked?)\n", state->name, i);
+                   PrintError(VM_NONE, VCORE_NONE, "generic (%s): can't hook port 0x%x (already hooked?)\n", state->name, i);
                    return -1;
                }
                break;
@@ -497,7 +497,7 @@ static int add_port_range(struct vm_device * dev, uint_t start, uint_t end, gene
                if (v3_dev_hook_io(dev, i, 
                                   &generic_read_port_print_and_ignore, 
                                   &generic_write_port_print_and_ignore) == -1) { 
-                   PrintError("generic (%s): can't hook port 0x%x (already hooked?)\n", state->name, i);
+                   PrintError(VM_NONE, VCORE_NONE, "generic (%s): can't hook port 0x%x (already hooked?)\n", state->name, i);
                    return -1;
                }
                break;
@@ -505,7 +505,7 @@ static int add_port_range(struct vm_device * dev, uint_t start, uint_t end, gene
                if (v3_dev_hook_io(dev, i, 
                                   &generic_read_port_passthrough, 
                                   &generic_write_port_passthrough) == -1) { 
-                   PrintError("generic (%s): can't hook port 0x%x (already hooked?)\n", state->name, i);
+                   PrintError(VM_NONE, VCORE_NONE, "generic (%s): can't hook port 0x%x (already hooked?)\n", state->name, i);
                    return -1;
                }
                break;
@@ -513,12 +513,12 @@ static int add_port_range(struct vm_device * dev, uint_t start, uint_t end, gene
                if (v3_dev_hook_io(dev, i, 
                                   &generic_read_port_ignore, 
                                   &generic_write_port_ignore) == -1) { 
-                   PrintError("generic (%s): can't hook port 0x%x (already hooked?)\n", state->name, i);
+                   PrintError(VM_NONE, VCORE_NONE, "generic (%s): can't hook port 0x%x (already hooked?)\n", state->name, i);
                    return -1;
                }
                break;
            default:
-               PrintError("generic (%s): huh?\n", state->name);
+               PrintError(VM_NONE, VCORE_NONE, "generic (%s): huh?\n", state->name);
                break;
        }
     }
@@ -531,7 +531,7 @@ static int add_mem_range(struct vm_device * dev, addr_t start, addr_t end, gener
 
     struct generic_internal *state = (struct generic_internal *) dev->private_data;
 
-    PrintDebug("generic (%s): adding memory range 0x%p to 0x%p as %s\n", state->name,
+    PrintDebug(VM_NONE, VCORE_NONE, "generic (%s): adding memory range 0x%p to 0x%p as %s\n", state->name,
               (void*)start, (void*)end, 
               (mode == GENERIC_PRINT_AND_PASSTHROUGH) ? "print-and-passthrough" : 
               (mode == GENERIC_PRINT_AND_IGNORE) ? "print-and-ignore" :
@@ -543,7 +543,7 @@ static int add_mem_range(struct vm_device * dev, addr_t start, addr_t end, gener
            if (v3_hook_full_mem(dev->vm, V3_MEM_CORE_ANY, start, end+1, 
                                 &generic_read_mem_print_and_passthrough, 
                                 &generic_write_mem_print_and_passthrough, dev) == -1) { 
-               PrintError("generic (%s): can't hook memory region 0x%p to 0x%p\n", state->name,(void*)start,(void*)end);
+               PrintError(VM_NONE, VCORE_NONE, "generic (%s): can't hook memory region 0x%p to 0x%p\n", state->name,(void*)start,(void*)end);
                return -1;
            }
            break;
@@ -552,7 +552,7 @@ static int add_mem_range(struct vm_device * dev, addr_t start, addr_t end, gener
            if (v3_hook_full_mem(dev->vm, V3_MEM_CORE_ANY, start, end+1, 
                                 &generic_read_mem_print_and_ignore, 
                                 &generic_write_mem_print_and_ignore, dev) == -1) { 
-               PrintError("generic (%s): can't hook memory region 0x%p to 0x%p\n", state->name,(void*)start,(void*)end);
+               PrintError(VM_NONE, VCORE_NONE, "generic (%s): can't hook memory region 0x%p to 0x%p\n", state->name,(void*)start,(void*)end);
                return -1;
            }
            break;
@@ -561,28 +561,81 @@ static int add_mem_range(struct vm_device * dev, addr_t start, addr_t end, gener
            if (v3_hook_full_mem(dev->vm, V3_MEM_CORE_ANY, start, end+1, 
                                 &generic_read_mem_passthrough, 
                                 &generic_write_mem_passthrough, dev) == -1) { 
-               PrintError("generic (%s): can't hook memory region 0x%p to 0x%p\n", state->name,(void*)start,(void*)end);
+               PrintError(VM_NONE, VCORE_NONE, "generic (%s): can't hook memory region 0x%p to 0x%p\n", state->name,(void*)start,(void*)end);
                return -1;
            }
            break;
-
+           
        case  GENERIC_IGNORE:
            if (v3_hook_full_mem(dev->vm, V3_MEM_CORE_ANY, start, end+1, 
                                 &generic_read_mem_ignore, 
                                 &generic_write_mem_ignore, dev) == -1) { 
-               PrintError("generic (%s): can't hook memory region 0x%p to 0x%p\n", state->name,(void*)start,(void*)end);
+               PrintError(VM_NONE, VCORE_NONE, "generic (%s): can't hook memory region 0x%p to 0x%p\n", state->name,(void*)start,(void*)end);
                return -1;
            }
            break;
        default:
-           PrintError("generic (%s): huh?\n",state->name);
+           PrintError(VM_NONE, VCORE_NONE, "generic (%s): huh?\n",state->name);
            break;
     }
+    
+    return 0;
+}
+
+
+#if 1
+
+//This is a hack for host device testing and will be removed
+
+static int osdebug_hcall(struct guest_info *core, uint_t hcall_id, void * priv_data) 
+{
+    struct generic_internal * state = (struct generic_internal *)priv_data;
+
+    int msg_len = core->vm_regs.rcx;
+    addr_t msg_gpa = core->vm_regs.rbx;
+    int buf_is_va = core->vm_regs.rdx;
+    int i;
+    uint8_t c; 
+    PrintDebug(core->vm_info, core, "generic (%s): handling hypercall (len=%d) as sequence of port writes\n",
+              state->name, msg_len);
+
+
+    for (i=0;i<msg_len;i++) { 
+       if (buf_is_va == 1) {
+           if (v3_read_gva_memory(core, msg_gpa+i, 1, &c) != 1) {
+               PrintError(core->vm_info, core, "generic (%s): could not read debug message\n",state->name);
+               return -1;
+           }
+       } else {
+           if (v3_read_gpa_memory(core, msg_gpa+i, 1, &c) != 1) { 
+               PrintError(core->vm_info, core, "generic (%s): Could not read debug message\n",state->name);
+               return -1;
+           }
+       }
+       if (generic_write_port_print_and_passthrough(core,0xc0c0,&c,1,priv_data)!=1) { 
+           PrintError(core->vm_info, core, "generic (%s): write port passthrough failed\n",state->name);
+           return -1;
+       }
+    }  
 
     return 0;
 }
 
+#endif
 
+#ifdef V3_CONFIG_HOST_DEVICE
+static void generic_intr_update_callback(v3_host_dev_t hdev, v3_guest_dev_t gdev, uint8_t irq, int raise)
+{
+    if (gdev) { 
+       struct vm_device *dev = (struct vm_device *) gdev;
+       if (raise) { 
+           v3_raise_irq(dev->vm,irq);
+       } else {
+           v3_lower_irq(dev->vm,irq);
+       }
+    }
+}
+#endif
 
 /*
    The device can be used to forward to the underlying physical device 
@@ -600,7 +653,7 @@ static int add_mem_range(struct vm_device * dev, addr_t start, addr_t end, gener
 
 
    <device class="generic" id="my_id" 
-         empty | forward="physical_device" or forward="host_device" host_device="url">
+         empty | forward="physical_device" or forward="host_device" hostdev="url">
 
   (empty implies physical_dev)
 
@@ -622,7 +675,7 @@ static int generic_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
     struct generic_internal * state = NULL;
     char * dev_id = v3_cfg_val(cfg, "ID");
     char * forward = v3_cfg_val(cfg, "forward");
-#ifdef CONFIG_HOST_DEVICE
+#ifdef V3_CONFIG_HOST_DEVICE
     char * host_dev = v3_cfg_val(cfg, "hostdev");
 #endif
     v3_cfg_tree_t * port_cfg = v3_cfg_subtree(cfg, "ports");
@@ -632,12 +685,13 @@ static int generic_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
     state = (struct generic_internal *)V3_Malloc(sizeof(struct generic_internal));
 
     if (state == NULL) {
-       PrintError("generic (%s): could not allocate generic state\n",dev_id);
+       PrintError(vm, VCORE_NONE, "generic (%s): could not allocate generic state\n",dev_id);
        return -1;
     }
     
     memset(state, 0, sizeof(struct generic_internal));
     strncpy(state->name,dev_id,MAX_NAME);
+    state->name[MAX_NAME-1] = 0;
 
     if (!forward) { 
        state->forward_type=GENERIC_PHYSICAL;
@@ -645,15 +699,15 @@ static int generic_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
        if (!strcasecmp(forward,"physical_device")) { 
            state->forward_type=GENERIC_PHYSICAL;
        } else if (!strcasecmp(forward,"host_device")) { 
-#ifdef CONFIG_HOST_DEVICE
+#ifdef V3_CONFIG_HOST_DEVICE
            state->forward_type=GENERIC_HOST;
 #else
-           PrintError("generic (%s): cannot configure host device since host device support is not built in\n", state->name);
+           PrintError(vm, VCORE_NONE, "generic (%s): cannot configure host device since host device support is not built in\n", state->name);
            V3_Free(state);
            return -1;
 #endif
        } else {
-           PrintError("generic (%s): unknown forwarding type \"%s\"\n", state->name, forward);
+           PrintError(vm, VCORE_NONE, "generic (%s): unknown forwarding type \"%s\"\n", state->name, forward);
            V3_Free(state);
            return -1;
        }
@@ -662,7 +716,7 @@ static int generic_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
     struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, state);
 
     if (dev == NULL) {
-       PrintError("generic: could not attach device %s\n", state->name);
+       PrintError(vm, VCORE_NONE, "generic: could not attach device %s\n", state->name);
        V3_Free(state);
        return -1;
     }
@@ -670,32 +724,36 @@ static int generic_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
     state->dev=dev;
 
 
-#ifdef CONFIG_HOST_DEVICE
+#ifdef V3_CONFIG_HOST_DEVICE
     if (state->forward_type==GENERIC_HOST) { 
        if (!host_dev) { 
-           PrintError("generic (%s): host forwarding requested, but no host device given\n", state->name);
+           PrintError(vm, VCORE_NONE, "generic (%s): host forwarding requested, but no host device given\n", state->name);
            v3_remove_device(dev);
            return -1;
        } else {
-           state->host_dev = v3_host_dev_open(host_dev,V3_BUS_CLASS_DIRECT,dev);
+           state->host_dev = v3_host_dev_open(host_dev,V3_BUS_CLASS_DIRECT,dev,generic_intr_update_callback,vm);
            if (!(state->host_dev)) { 
-               PrintError("generic (%s): unable to open host device \"%s\"\n", state->name,host_dev);
+               PrintError(vm, VCORE_NONE, "generic (%s): unable to open host device \"%s\"\n", state->name,host_dev);
                v3_remove_device(dev);
                return -1;
            } else {
-               PrintDebug("generic (%s): successfully attached host device \"%s\"\n", state->name,host_dev);
+               PrintDebug(vm, VCORE_NONE, "generic (%s): successfully attached host device \"%s\"\n", state->name,host_dev);
            }
        }
     }
 #endif
 
-    PrintDebug("generic (%s): init_device\n", state->name);
+    PrintDebug(vm, VCORE_NONE, "generic (%s): init_device\n", state->name);
 
     // scan port list....
     while (port_cfg) {
        uint16_t start = atox(v3_cfg_val(port_cfg, "start"));
        uint16_t end = atox(v3_cfg_val(port_cfg, "end"));
        char * mode_str = v3_cfg_val(port_cfg, "mode");
+    if (!mode_str) {
+        PrintError(vm, VCORE_NONE, "generic (%s): error getting port mode\n", state->name);
+        return -1;
+    }
        generic_mode_t mode = GENERIC_IGNORE;
        if (strcasecmp(mode_str, "print_and_ignore") == 0) {
            mode = GENERIC_PRINT_AND_IGNORE;
@@ -706,14 +764,14 @@ static int generic_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
        } else if (strcasecmp(mode_str, "ignore") == 0) {
            mode = GENERIC_IGNORE;
        } else {
-           PrintError("generic (%s): invalid mode %s in adding ports\n", state->name, mode_str);
+           PrintError(vm, VCORE_NONE, "generic (%s): invalid mode %s in adding ports\n", state->name, mode_str);
            v3_remove_device(dev);
            return -1;
        }
        
        
        if (add_port_range(dev, start, end, mode) == -1) {
-           PrintError("generic (%s): could not add port range 0x%x to 0x%x\n", state->name, start, end);
+           PrintError(vm, VCORE_NONE, "generic (%s): could not add port range 0x%x to 0x%x\n", state->name, start, end);
            v3_remove_device(dev);
            return -1;
        }
@@ -737,19 +795,19 @@ static int generic_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
        } else if (strcasecmp(mode_str, "ignore") == 0) {
            mode = GENERIC_IGNORE;
        } else {
-           PrintError("generic (%s): invalid mode %s for adding memory\n", state->name, mode_str);
+           PrintError(vm, VCORE_NONE, "generic (%s): invalid mode %s for adding memory\n", state->name, mode_str);
            v3_remove_device(dev);
            return -1;
        }
 
        if (state->num_mem_hooks>=MAX_MEM_HOOKS) { 
-           PrintError("generic (%s): cannot add another memory hook (increase MAX_MEM_HOOKS)\n", state->name);
+           PrintError(vm, VCORE_NONE, "generic (%s): cannot add another memory hook (increase MAX_MEM_HOOKS)\n", state->name);
            v3_remove_device(dev);
            return -1;
        }
        
        if (add_mem_range(dev, start, end, mode) == -1) {
-           PrintError("generic (%s): could not add memory range 0x%p to 0x%p\n", state->name, (void*)start, (void*)end);
+           PrintError(vm, VCORE_NONE, "generic (%s): could not add memory range 0x%p to 0x%p\n", state->name, (void*)start, (void*)end);
            v3_remove_device(dev);
            return -1;
        }
@@ -759,8 +817,16 @@ static int generic_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
 
        mem_cfg = v3_cfg_next_branch(port_cfg);
     }
+
+#if 1
+    // hack for os debug testing
+    if (strcasecmp(state->name,"os debug")==0) { 
+       PrintDebug(vm, VCORE_NONE, "generic (%s): adding hypercall for os debug device\n", state->name);
+       v3_register_hypercall(vm,0xc0c0,osdebug_hcall,state);
+    }
+#endif
     
-    PrintDebug("generic (%s): initialization complete\n", state->name);
+    PrintDebug(vm, VCORE_NONE, "generic (%s): initialization complete\n", state->name);
 
     return 0;
 }