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.


integrated new configuration system
[palacios.git] / palacios / src / devices / nvram.c
index 2606c5f..565c183 100644 (file)
  */
 
 
-#include <devices/nvram.h>
+#include <palacios/vmm_dev_mgr.h>
 #include <palacios/vmm.h>
 #include <palacios/vmm_types.h>
 
+#include <palacios/vmm_lock.h>
 
 #include <devices/ide.h>
+#include <palacios/vmm_intr.h>
+#include <palacios/vmm_host_events.h>
+#include <palacios/vm_guest.h>
 
-#ifndef DEBUG_NVRAM
+#ifndef CONFIG_DEBUG_NVRAM
 #undef PrintDebug
 #define PrintDebug(fmt, args...)
 #endif
@@ -99,6 +103,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 +212,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 +270,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 +393,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 +464,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 +599,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 +727,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 +744,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 +757,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]);
 
@@ -748,25 +771,11 @@ static int nvram_write_data_port(ushort_t port,
 
 
 
-static int nvram_init_device(struct vm_device * dev) {
-    PrintDebug("nvram: init_device\n");
-
-    init_nvram_state(dev);
-
-    // hook ports
-    v3_dev_hook_io(dev, NVRAM_REG_PORT, NULL, &nvram_write_reg_port);
-    v3_dev_hook_io(dev, NVRAM_DATA_PORT, &nvram_read_data_port, &nvram_write_data_port);
-  
-    v3_hook_host_event(dev->vm, HOST_TIMER_EVT, V3_HOST_EVENT_HANDLER(handle_timer_event), dev);
-
-    return 0;
-}
 
-static int nvram_deinit_device(struct vm_device * dev) {
+static int nvram_free(struct vm_device * dev) {
     v3_dev_unhook_io(dev, NVRAM_REG_PORT);
     v3_dev_unhook_io(dev, NVRAM_DATA_PORT);
 
-    nvram_reset_device(dev);
     return 0;
 }
 
@@ -774,9 +783,8 @@ static int nvram_deinit_device(struct vm_device * dev) {
 
 
 
-static struct vm_device_ops dev_ops = { 
-    .init = nvram_init_device, 
-    .deinit = nvram_deinit_device,
+static struct v3_device_ops dev_ops = {  
+    .free = nvram_free,
     .reset = nvram_reset_device,
     .start = nvram_start_device,
     .stop = nvram_stop_device,
@@ -785,16 +793,41 @@ static struct vm_device_ops dev_ops = {
 
 
 
-struct vm_device * v3_create_nvram(struct vm_device * ide) {
+
+static int nvram_init(struct guest_info * vm, v3_cfg_tree_t * cfg) {
     struct nvram_internal * nvram_state = NULL;
+    struct vm_device * ide = v3_find_dev(vm, v3_cfg_val(cfg, "storage"));
+    char * name = v3_cfg_val(cfg, "name");
 
+    if (!ide) {
+       PrintError("Could not find IDE device\n");
+       return -1;
+    }
+
+    PrintDebug("nvram: init_device\n");
     nvram_state = (struct nvram_internal *)V3_Malloc(sizeof(struct nvram_internal) + 1000);
 
     PrintDebug("nvram: internal at %p\n", (void *)nvram_state);
 
     nvram_state->ide = ide;
 
-    struct vm_device * device = v3_create_device("NVRAM", &dev_ops, nvram_state);
+    struct vm_device * dev = v3_allocate_device(name, &dev_ops, nvram_state);
+
+
+    if (v3_attach_device(vm, dev) == -1) {
+       PrintError("Could not attach device %s\n", name);
+       return -1;
+    }
+
+    init_nvram_state(dev);
 
-    return device;
+    // hook ports
+    v3_dev_hook_io(dev, NVRAM_REG_PORT, NULL, &nvram_write_reg_port);
+    v3_dev_hook_io(dev, NVRAM_DATA_PORT, &nvram_read_data_port, &nvram_write_data_port);
+  
+    v3_hook_host_event(vm, HOST_TIMER_EVT, V3_HOST_EVENT_HANDLER(handle_timer_event), dev);
+
+    return 0;
 }
+
+device_register("NVRAM", nvram_init)