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 RTC functionality (including interrupt injection) to nvram
Peter Dinda [Mon, 28 Jul 2008 01:06:34 +0000 (01:06 +0000)]
palacios/include/devices/nvram.h
palacios/include/palacios/vmm_ctrl_regs.h
palacios/include/palacios/vmm_paging.h
palacios/src/devices/8259a.c
palacios/src/devices/nvram.c
palacios/src/geekos/timer.c
palacios/src/palacios/svm_handler.c
palacios/src/palacios/vmm_config.c
palacios/src/palacios/vmm_ctrl_regs.c

index 3936fe0..681d2e8 100644 (file)
@@ -3,8 +3,9 @@
 
 #include <palacios/vm_dev.h>
 
-
-
 struct vm_device *create_nvram();
 
+// The host os needs to call this
+void deliver_timer_interrupt_to_vmm(uint_t period_us);
+
 #endif
index 69602bb..f53034c 100644 (file)
@@ -186,4 +186,9 @@ int handle_cr3_write(struct guest_info * info);
 int handle_cr3_read(struct guest_info * info);
 
 
+#define CR3_32_SAME_BASE(source1,source2) ((source1)->pdt_base_addr == (source2)->pdt_base_addr)
+#define CR3_32_COPY_FLAGS(source,dest) do { (dest)->rsvd1=(source)->rsvd1; (dest)->pwt=(source)->pwt; (dest)->pcd=(source)->pcd; } while (0)
+#define CR3_32_COPY_BASE(source,dest) do { (dest)->pdt_base_addr = (source)->pdt_base_addr; } while (0)
+
+
 #endif
index 2663b2c..29bb19f 100644 (file)
@@ -112,6 +112,8 @@ the host state in the vmcs before entering the guest.
 #define CR3_TO_PML4E64(cr3)  (((ullong_t)cr3) & 0x000ffffffffff000LL)
 
 
+
+
 /* Accessor functions for the page table structures */
 #define PDE32_T_ADDR(x) (((x).pt_base_addr) << 12)
 #define PTE32_T_ADDR(x) (((x).page_base_addr) << 12)
index deabacd..ee901ef 100644 (file)
@@ -348,12 +348,17 @@ int write_master_port1(ushort_t port, void * src, uint_t length, struct vm_devic
   struct pic_internal * state = (struct pic_internal*)dev->private_data;
   uchar_t cw = *(uchar_t *)src;
 
+  PrintDebug("8259 PIC: Write master port 1 with 0x%x\n",cw);
+
   if (length != 1) {
     PrintError("8259 PIC: Invalid Write length (wr_Master1)\n");
     return -1;
   }
   
   if (IS_ICW1(cw)) {
+
+    PrintDebug("8259 PIC: Setting ICW1 = %x (wr_Master1)\n", cw);
+    
     state->master_icw1 = cw;
     state->master_state = ICW2;
 
@@ -362,6 +367,7 @@ int write_master_port1(ushort_t port, void * src, uint_t length, struct vm_devic
       // handle the EOI here
       struct ocw2 * cw2 =  (struct ocw2*)&cw;
 
+      PrintDebug("8259 PIC: Handling OCW2 = %x (wr_Master1)\n", cw);
       
       if ((cw2->EOI) && (!cw2->R) && (cw2->SL)) {
        // specific EOI;
@@ -384,6 +390,7 @@ int write_master_port1(ushort_t port, void * src, uint_t length, struct vm_devic
 
       state->master_ocw2 = cw;
     } else if (IS_OCW3(cw)) {
+      PrintDebug("8259 PIC: Handling OCW3 = %x (wr_Master1)\n", cw);
       state->master_ocw3 = cw;
     } else {
       PrintError("8259 PIC: Invalid OCW to PIC (wr_Master1)\n");
@@ -403,6 +410,8 @@ int write_master_port2(ushort_t port, void * src, uint_t length, struct vm_devic
     struct pic_internal * state = (struct pic_internal*)dev->private_data;
     uchar_t cw = *(uchar_t *)src;    
 
+    PrintDebug("8259 PIC: Write master port 2 with 0x%x\n",cw);
+  
     if (length != 1) {
       PrintError("8259 PIC: Invalid Write length (wr_Master2)\n");
       return -1;
@@ -425,6 +434,8 @@ int write_master_port2(ushort_t port, void * src, uint_t length, struct vm_devic
     } else if (state->master_state == ICW3) {
       struct icw1 * cw1 = (struct icw1 *)&(state->master_icw1);
 
+      PrintDebug("8259 PIC: Setting ICW3 = %x (wr_Master2)\n", cw);
+
       state->master_icw3 = cw;
 
       if (cw1->ic4 == 1) {
@@ -434,9 +445,11 @@ int write_master_port2(ushort_t port, void * src, uint_t length, struct vm_devic
       }
 
     } else if (state->master_state == ICW4) {
+      PrintDebug("8259 PIC: Setting ICW4 = %x (wr_Master2)\n", cw);
       state->master_icw4 = cw;
       state->master_state = READY;
     } else if (state->master_state == READY) {
+      PrintDebug("8259 PIC: Setting IMR = %x (wr_Master2)\n", cw);
       state->master_imr = cw;
     } else {
       // error
@@ -451,6 +464,8 @@ int write_slave_port1(ushort_t port, void * src, uint_t length, struct vm_device
   struct pic_internal * state = (struct pic_internal*)dev->private_data;
   uchar_t cw = *(uchar_t *)src;
 
+  PrintDebug("8259 PIC: Write slave port 1 with 0x%x\n",cw);
+
   if (length != 1) {
     // error
     PrintError("8259 PIC: Invalid Write length (wr_Slave1)\n");
@@ -458,12 +473,15 @@ int write_slave_port1(ushort_t port, void * src, uint_t length, struct vm_device
   }
 
   if (IS_ICW1(cw)) {
+    PrintDebug("8259 PIC: Setting ICW1 = %x (wr_Slave1)\n", cw);
     state->slave_icw1 = cw;
     state->slave_state = ICW2;
   } else if (state->slave_state == READY) {
     if (IS_OCW2(cw)) {
       // handle the EOI here
       struct ocw2 * cw2 =  (struct ocw2 *)&cw;
+
+      PrintDebug("8259 PIC: Setting OCW2 = %x (wr_Slave1)\n", cw);
       
       if ((cw2->EOI) && (!cw2->R) && (cw2->SL)) {
        // specific EOI;
@@ -487,6 +505,7 @@ int write_slave_port1(ushort_t port, void * src, uint_t length, struct vm_device
       state->slave_ocw2 = cw;
     } else if (IS_OCW3(cw)) {
       // Basically sets the IRR/ISR read flag
+      PrintDebug("8259 PIC: Setting OCW3 = %x (wr_Slave1)\n", cw);
       state->slave_ocw3 = cw;
     } else {
       PrintError("8259 PIC: Invalid command work (wr_Slave1)\n");
@@ -504,6 +523,8 @@ int write_slave_port2(ushort_t port, void * src, uint_t length, struct vm_device
     struct pic_internal * state = (struct pic_internal*)dev->private_data;
     uchar_t cw = *(uchar_t *)src;    
 
+    PrintDebug("8259 PIC: Write slave port 2 with 0x%x\n",cw);
+
     if (length != 1) {
       PrintError("8259 PIC: Invalid write length (wr_Slave2)\n");
       return -1;
@@ -512,6 +533,8 @@ int write_slave_port2(ushort_t port, void * src, uint_t length, struct vm_device
     if (state->slave_state == ICW2) {
       struct icw1 * cw1 =  (struct icw1 *)&(state->master_icw1);
 
+      PrintDebug("8259 PIC: Setting ICW2 = %x (wr_Slave2)\n", cw);
+
       state->slave_icw2 = cw;
 
       if (cw1->sngl == 0) {
@@ -525,6 +548,8 @@ int write_slave_port2(ushort_t port, void * src, uint_t length, struct vm_device
     } else if (state->slave_state == ICW3) {
       struct icw1 * cw1 =  (struct icw1 *)&(state->master_icw1);
 
+      PrintDebug("8259 PIC: Setting ICW3 = %x (wr_Slave2)\n", cw);
+
       state->slave_icw3 = cw;
 
       if (cw1->ic4 == 1) {
@@ -534,9 +559,11 @@ int write_slave_port2(ushort_t port, void * src, uint_t length, struct vm_device
       }
 
     } else if (state->slave_state == ICW4) {
+      PrintDebug("8259 PIC: Setting ICW4 = %x (wr_Slave2)\n", cw);
       state->slave_icw4 = cw;
       state->slave_state = READY;
     } else if (state->slave_state == READY) {
+      PrintDebug("8259 PIC: Setting IMR = %x (wr_Slave2)\n", cw);
       state->slave_imr = cw;
     } else {
       PrintError("8259 PIC: Invalid State at write (wr_Slave2)\n");
index ef37366..8df8b79 100644 (file)
@@ -9,12 +9,10 @@
 #endif
 
 
-
-
-
 #define NVRAM_REG_PORT  0x70
 #define NVRAM_DATA_PORT 0x71
 
+#define NVRAM_RTC_IRQ   0x8
 
 
 typedef enum {NVRAM_READY, NVRAM_REG_POSTED} nvram_state_t;
@@ -75,14 +73,312 @@ struct nvram_internal {
   nvram_state_t dev_state;
   uchar_t       thereg;
   uchar_t       mem_state[NVRAM_REG_MAX];
+
+  uint_t        us;   //microseconds - for clock update - zeroed every second
+  uint_t        pus;  //microseconds - for periodic interrupt - cleared every period
 };
 
 
+struct rtc_stata {
+  uint_t        rate: 4;  // clock rate = 65536Hz / 2 rate (0110=1024 Hz)
+  uint_t        basis: 3; // time base, 010 = 32,768 Hz
+  uint_t        uip: 1;   // 1=update in progress
+} __attribute__((__packed__)) __attribute__((__aligned__ (1)))  ;
+
+struct rtc_statb {
+  uint_t        sum: 1;  // 1=summer (daylight savings)
+  uint_t        h24: 1;  // 1=24h clock
+  uint_t        dm: 1;   // 1=date/time is in bcd, 0=binary
+  uint_t        rec: 1;  // 1=rectangular signal
+  uint_t        ui: 1;   // 1=update interrupt
+  uint_t        ai: 1;   // 1=alarm interrupt
+  uint_t        pi: 1;   // 1=periodic interrupt
+  uint_t        set: 1;  // 1=blocked update
+} __attribute__((__packed__))  __attribute__((__aligned__ (1))) ;
+
+struct rtc_statc {
+  uint_t        res: 4;   // reserved
+  uint_t        uf: 1;    // 1=source of interrupt is update
+  uint_t        af: 1;    // 1=source of interrupt is alarm interrupt
+  uint_t        pf: 1;    // 1=source of interrupt is periodic interrupt
+  uint_t        irq: 1;   // 1=interrupt requested
+}  __attribute__((__packed__))  __attribute__((__aligned__ (1))) ;
+
+struct rtc_statd {
+  uint_t        res: 7;   // reserved
+  uint_t        val: 1;   // 1=cmos ram data is OK
+}  __attribute__((__packed__))  __attribute__((__aligned__ (1))) ;
+
+
+
+
+struct vm_device *thedev=NULL;
+
+
+static struct vm_device *demultiplex_timer_interrupt(uint_t period_us)
+{
+  // hack
+  return thedev;
+}
+
+struct bcd_num {
+  uchar_t bot:4;
+  uchar_t top:4;
+} ;
+
+static uchar_t add_to(uchar_t *left, uchar_t *right, uchar_t bcd)
+{
+  uchar_t temp;
+
+  if (bcd) { 
+    struct bcd_num *bl = (struct bcd_num *)left;
+    struct bcd_num *br = (struct bcd_num *)right;
+    uchar_t carry=0;
+
+    bl->bot += br->bot;
+    carry = bl->bot / 0xa;
+    bl->bot %= 0xa;
+    bl->top += carry + br->top;
+    carry = bl->top / 0xa;
+    bl->top %= 0xa;
+    return carry;
+  } else {
+    temp=*left;
+    *left+=*right;
+    if (*left<temp) { 
+      return 1;
+    } else {
+      return 0;
+    }
+  }
+  
+}
+
+
+static uchar_t days_in_month(struct vm_device *dev, uchar_t month, uchar_t bcd)
+{
+  // This completely ignores Julian / Gregorian stuff right now
+
+  if (bcd) { 
+    switch (month) {
+    case 0x1: //jan
+    case 0x3: //march
+    case 0x5: //may
+    case 0x7: //july
+    case 0x8: //aug
+    case 0x10: //oct
+    case 0x12: //dec
+      return 0x31;
+      break;
+    case 0x4: //april
+    case 0x6: //june
+    case 0x9: //sept
+    case 0x11: //nov
+      return 0x30;
+      break;
+    case 0x2: //feb
+      return 0x28;
+      break;
+    default:
+      return 0x30;
+    }
+  } else {
+    switch (month) {
+    case 1: //jan
+    case 3: //march
+    case 5: //may
+    case 7: //july
+    case 8: //aug
+    case 10: //oct
+    case 12: //dec
+      return 31;
+      break;
+    case 4: //april
+    case 6: //june
+    case 9: //sept
+    case 11: //nov
+      return 30;
+      break;
+    case 2: //feb
+      return 28;
+      break;
+    default:
+      return 30;
+    }
+  }
+}
+
+
+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]));
+  struct rtc_statc *statc = (struct rtc_statc *) &((data->mem_state[NVRAM_REG_STAT_C]));
+  //struct rtc_statd *statd = (struct rtc_statd *) &((data->mem_state[NVRAM_REG_STAT_D]));
+  uchar_t *sec = (uchar_t *) &(data->mem_state[NVRAM_REG_SEC]);
+  uchar_t *min = (uchar_t *) &(data->mem_state[NVRAM_REG_MIN]);
+  uchar_t *hour = (uchar_t *) &(data->mem_state[NVRAM_REG_HOUR]);
+  uchar_t *weekday = (uchar_t *) &(data->mem_state[NVRAM_REG_WEEK_DAY]);
+  uchar_t *monthday = (uchar_t *) &(data->mem_state[NVRAM_REG_MONTH_DAY]);
+  uchar_t *month = (uchar_t *) &(data->mem_state[NVRAM_REG_MONTH]);
+  uchar_t *year = (uchar_t *) &(data->mem_state[NVRAM_REG_YEAR]);
+  uchar_t *cent = (uchar_t *) &(data->mem_state[NVRAM_REG_IBM_CENTURY_BYTE]);
+  uchar_t *seca = (uchar_t *) &(data->mem_state[NVRAM_REG_SEC_ALARM]);
+  uchar_t *mina = (uchar_t *) &(data->mem_state[NVRAM_REG_MIN_ALARM]);
+  uchar_t *houra = (uchar_t *) &(data->mem_state[NVRAM_REG_HOUR_ALARM]);
+  uchar_t hour24;
+
+  uchar_t bcd = (statb->dm==1);
+  uchar_t carry=0;
+  uchar_t nextday=0;
+  uint_t  periodic_period;
+
+  //PrintDebug("nvram: sizeof(struct rtc_stata)=%d\n", sizeof(struct rtc_stata));
+
+
+  //PrintDebug("nvram: update_time\n",statb->pi);
+  
+  // We will set these flags on exit
+  statc->irq=statc->pf=statc->af=statc->uf=0;
+
+  // We will reset us after one second
+  data->us += period_us;
+  // We will reset pus after one periodic_period
+  data->pus += period_us;
+
+  if (data->us > 1000000) { 
+    carry=1;
+    //PrintDebug("nvram: adding 1 to seconds=0x%x (bcd=%d)...", *sec, bcd);
+    carry=add_to(sec,&carry,bcd);
+    //PrintDebug("got 0x%x with carry=%d\n",*sec,carry);
+    if (carry) { PrintDebug("nvram: somehow managed to get a carry in second update\n"); }
+    if ((bcd && *sec==0x60) || (!bcd && *sec==60)) { 
+      *sec=0;
+      carry=1;
+      carry=add_to(min,&carry,bcd);
+      if (carry) { PrintDebug("nvram: somehow managed to get a carry in minute update\n"); }
+      if ((bcd && *min==0x60) || (!bcd && *min==60)) { 
+       *min=0;
+       hour24 = *hour;
+       if (!(statb->h24)) { 
+         if (hour24&0x80) { 
+           hour24&=0x8f;
+           uchar_t temp = bcd ? 0x12 : 12;
+           add_to(&hour24,&temp, bcd);
+         }
+       }
+       carry=1;
+       carry=add_to(&hour24,&carry,bcd);
+       if (carry) { PrintDebug("nvram: somehow managed to get a carry in hour update\n"); }
+       if ((bcd && hour24==0x24) || (!bcd && hour24==24)) { 
+         carry=1;
+         nextday=1;
+         hour24=0;
+       } else {
+         carry=0;
+       }
+       if (statb->h24) { 
+         *hour=hour24;
+       } else {
+         if ((bcd && hour24<0x12) || (!bcd && hour24<12)) { 
+           *hour=hour24;
+         } else {
+           if (!bcd) { 
+             *hour = (hour24-12) | 0x80;
+           } else {
+             *hour = hour24;
+             struct bcd_num *n = (struct bcd_num *) hour;
+             if (n->bot<0x2) { 
+               n->top--;
+               n->bot+=0xa;
+             }
+             n->bot-=0x2;
+             n->top-=0x1;
+           }
+         }
+       }
+       // now see if we need to carry into the days and further
+       if (nextday) { 
+         carry=1;
+         add_to(weekday, &carry, bcd);
+         *weekday%=0x7;  // same regardless of bcd
+         if (!(*monthday==days_in_month(dev,*month,bcd))) {
+           add_to(monthday, &carry, bcd);
+         } else {
+           *monthday=0x1;
+           carry=1;
+           add_to(month,&carry,bcd);
+           if ((bcd && *month==0x13) || (!bcd && *month==13)) { 
+             *month=1; // same for both 
+             carry=1;
+             carry=add_to(year,&carry,bcd);
+             if ((bcd && carry) || (!bcd && *year==100)) { 
+               *year=0;
+               carry=1;
+               add_to(cent,&carry,bcd);
+             }
+           }
+         }
+       }
+      }
+    }
+    data->us-=1000000;
+    // OK, now check for the alarm, if it is set to interrupt
+    if (statb->ai) { 
+      if (*sec==*seca && *min==*mina && *hour==*houra) { 
+       statc->af=1;
+       PrintDebug("nvram: interrupt on alarm\n");
+      }
+    }
+  }
+
+  if (statb->pi) { 
+    periodic_period = 1000000/(65536/(0x1 << stata->rate));
+    if (data->pus >= periodic_period) { 
+      statc->pf=1;
+      data->pus -= periodic_period;
+      PrintDebug("nvram: interrupt on periodic\n");
+    }
+  }
+
+  if (statb->ui) { 
+    statc->uf=1;
+    PrintDebug("nvram: interrupt on update\n");
+  }
+
+  statc->irq= statc->pf || statc->af || statc->uf;
+  
+  //PrintDebug("nvram: time is now: YMDHMS: 0x%x:0x%x:0x%x:0x%x:0x%x,0x%x bcd=%d\n", *year, *month, *monthday, *hour, *min, *sec,bcd);
+  
+  // Interrupt associated VM, if needed
+  if (statc->irq) { 
+    PrintDebug("nvram: injecting interrupt\n");
+    dev->vm->vm_ops.raise_irq(dev->vm, NVRAM_RTC_IRQ);
+  }
+}
+
+
+
+
+void deliver_timer_interrupt_to_vmm(uint_t period_us)
+{
+  struct vm_device *dev = demultiplex_timer_interrupt(period_us);
+
+  if (dev) {
+    update_time(dev,period_us);
+  }
+  
+}
+
 
 static int set_nvram_defaults(struct vm_device *dev)
 {
   struct nvram_internal * nvram_state = (struct nvram_internal*) dev->private_data;
 
+
+
+
   //
   // 2 1.44 MB floppy drives
   //
@@ -139,17 +435,31 @@ static int set_nvram_defaults(struct vm_device *dev)
 
 
   // RTC status A
-  // time update in progress, default timebase (32KHz, default interrupt rate 1KHz)
-  // 10100110
-  nvram_state->mem_state[NVRAM_REG_STAT_A] = 0xa6;
+  // 00100110 = no update in progress, base=32768 Hz, rate = 1024 Hz
+  nvram_state->mem_state[NVRAM_REG_STAT_A] = 0x26; 
 
   // RTC status B
-  // time updates, default timebase (32KHz, default interrupt rate 1KHz)
-  // 10100110
-  //nvram_state->mem_state[NVRAM_REG_STAT_B] = 0xa6;
-  
+  // 00000100 = not setting, no interrupts, blocked rect signal, bcd mode, 24 hour, normal time
+  nvram_state->mem_state[NVRAM_REG_STAT_B] = 0x06; 
 
 
+  // RTC status C
+  // No IRQ requested, result not do to any source
+  nvram_state->mem_state[NVRAM_REG_STAT_C] = 0x00;
+
+  // RTC status D
+  // Battery is OK
+  nvram_state->mem_state[NVRAM_REG_STAT_D] = 0x80;
+
+
+  // january 1, 2008, 00:00:00
+  nvram_state->mem_state[NVRAM_REG_MONTH] = 0x1;
+  nvram_state->mem_state[NVRAM_REG_MONTH_DAY] = 0x1;
+  nvram_state->mem_state[NVRAM_REG_WEEK_DAY] = 0x1;
+  nvram_state->mem_state[NVRAM_REG_YEAR] = 0x08;
+
+  nvram_state->us=nvram_state->pus=0;
+
   return 0;
 
 }
@@ -292,10 +602,15 @@ static struct vm_device_ops dev_ops = {
 struct vm_device *create_nvram() {
   struct nvram_internal * nvram_state = (struct nvram_internal *)V3_Malloc(sizeof(struct nvram_internal)+1000);
 
-  PrintDebug("internal at %x\n",nvram_state);
+  PrintDebug("nvram: internal at %x\n",nvram_state);
 
   struct vm_device *device = create_device("NVRAM", &dev_ops, nvram_state);
 
+  if (thedev!=NULL) {
+    PrintDebug("nvram: warning! overwriting thedev\n");
+  }
+
+  thedev=device;
 
   return device;
 }
index 7355efb..7c15550 100644 (file)
@@ -2,7 +2,7 @@
  * GeekOS timer interrupt support
  * Copyright (c) 2001,2003 David H. Hovemeyer <daveho@cs.umd.edu>
  * Copyright (c) 2003, Jeffrey K. Hollingsworth <hollings@cs.umd.edu>
- * $Revision: 1.8 $
+ * $Revision: 1.9 $
  * 
  * This is free software.  You are permitted to use,
  * redistribute, and modify it as specified in the file "COPYING".
@@ -19,6 +19,9 @@
 #include <geekos/debug.h>
 
 
+/* PAD this currently is in nvram.c */
+extern void deliver_timer_interrupt_to_vmm(uint_t period_us);
+
 /* JRL Add a cpu frequency measurement */
 uint_t cpu_khz_freq;
 
@@ -232,6 +235,8 @@ static void Timer_Interrupt_Handler(struct Interrupt_State* state)
     }
 
 
+    deliver_timer_interrupt_to_vmm(1000000/HZ);
+
     End_IRQ(state);
 }
 
index b5ad69f..73f154a 100644 (file)
@@ -322,9 +322,12 @@ int handle_svm_exit(struct guest_info * info) {
       return -1;
     }
 
+  } else {
+#ifdef DEBUG_INTERRUPTS
+    PrintDebug("No interrupts/exceptions pending\n");
+#endif
   }
 
-
   guest_state->cr0 = info->ctrl_regs.cr0;
   guest_state->cr2 = info->ctrl_regs.cr2;
   guest_state->cr3 = info->ctrl_regs.cr3;
index dfb7974..bdb471f 100644 (file)
@@ -118,6 +118,8 @@ int config_guest(struct guest_info * info, void * config_ptr) {
 #if GENERIC
     generic_port_range_type range[] = {
 #if 1
+      // Make the DMA controller invisible
+
       {0x00, 0x07, GENERIC_PRINT_AND_IGNORE},   // DMA 1 channels 0,1,2,3 (address, counter)
       {0xc0, 0xc7, GENERIC_PRINT_AND_IGNORE},   // DMA 2 channels 4,5,6,7 (address, counter)
       {0x87, 0x87, GENERIC_PRINT_AND_IGNORE},   // DMA 1 channel 0 page register
@@ -132,13 +134,28 @@ int config_guest(struct guest_info * info, void * config_ptr) {
       {0xd0, 0xde, GENERIC_PRINT_AND_IGNORE},   // DMA 2 misc registers
 #endif
       
-      
+
+#if 1      
+      // Make the Serial ports invisible 
+
       {0x3f8, 0x3f8+7, GENERIC_PRINT_AND_IGNORE},      // COM 1
       {0x2f8, 0x2f8+7, GENERIC_PRINT_AND_IGNORE},      // COM 2
       {0x3e8, 0x3e8+7, GENERIC_PRINT_AND_IGNORE},      // COM 3
       {0x2e8, 0x2e8+7, GENERIC_PRINT_AND_IGNORE},      // COM 4
-      
+#endif
+
+
+#if 1
+      // Make the PCI bus invisible (at least it's configuration)
+
+      {0xcf8, 0xcf8, GENERIC_PRINT_AND_IGNORE}, // PCI Config Address
+      {0xcfc, 0xcfc, GENERIC_PRINT_AND_IGNORE}, // PCI Config Data
+#endif
 #if 0
+
+      // Monitor the IDE controllers (very slow)
+
       {0x170, 0x178, GENERIC_PRINT_AND_PASSTHROUGH}, // IDE 1
       {0x376, 0x377, GENERIC_PRINT_AND_PASSTHROUGH}, // IDE 1
       {0x1f0, 0x1f8, GENERIC_PRINT_AND_PASSTHROUGH}, // IDE 0
@@ -147,6 +164,9 @@ int config_guest(struct guest_info * info, void * config_ptr) {
       
 
 #if 0
+
+      // Make the floppy controllers invisible
+
       {0x3f0, 0x3f2, GENERIC_PRINT_AND_IGNORE}, // Primary floppy controller (base,statusa/statusb,DOR)
       {0x3f4, 0x3f5, GENERIC_PRINT_AND_IGNORE}, // Primary floppy controller (mainstat/datarate,data)
       {0x3f7, 0x3f7, GENERIC_PRINT_AND_IGNORE}, // Primary floppy controller (DIR)
@@ -156,6 +176,46 @@ int config_guest(struct guest_info * info, void * config_ptr) {
       
 #endif
 
+#if 1
+
+      // Make the parallel port invisible
+      
+      {0x378, 0x37f, GENERIC_PRINT_AND_IGNORE},
+
+#endif
+
+#if 1
+
+      // Monitor graphics card operations
+
+      {0x3b0, 0x3bb, GENERIC_PRINT_AND_PASSTHROUGH},
+      {0x3c0, 0x3df, GENERIC_PRINT_AND_PASSTHROUGH},
+      
+#endif
+
+
+#if 1
+      // Make the ISA PNP features invisible
+
+      {0x274, 0x277, GENERIC_PRINT_AND_IGNORE},
+      {0x279, 0x279, GENERIC_PRINT_AND_IGNORE},
+      {0xa79, 0xa79, GENERIC_PRINT_AND_IGNORE},
+#endif
+
+
+#if 1
+      // Monitor any network card (realtek ne2000) operations 
+      {0xc100, 0xc1ff, GENERIC_PRINT_AND_PASSTHROUGH},
+#endif
+
+
+#if 1
+      // Make any Bus master ide controller invisible
+      
+      {0xc000, 0xc00f, GENERIC_PRINT_AND_IGNORE},
+#endif
+
+
       //         {0x378, 0x400, GENERIC_PRINT_AND_IGNORE}
       
       {0,0,0},  // sentinal - must be last
index ba83f3b..2fcd3b6 100644 (file)
@@ -450,6 +450,7 @@ int handle_cr3_write(struct guest_info * info) {
       new_cr3 = (struct cr3_32 *)first_operand;
 
       if (info->shdw_pg_mode == SHADOW_PAGING) {
+       int flushed=0;
        addr_t shadow_pt;
        struct cr3_32 * shadow_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.shadow_cr3);
        struct cr3_32 * guest_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
@@ -463,7 +464,13 @@ int handle_cr3_write(struct guest_info * info) {
        */
 
        /* Delete the current Page Tables */
-       delete_page_tables_pde32((pde32_t *)CR3_TO_PDE32(*(uint_t*)shadow_cr3));
+       if (!CR3_32_SAME_BASE(new_cr3,guest_cr3)) { 
+         PrintDebug("New CR3 is different - flushing shadow page table\n");
+         delete_page_tables_pde32((pde32_t *)CR3_TO_PDE32(*(uint_t*)shadow_cr3));
+         flushed=1;
+       } else {
+         PrintDebug("New CR3 (0x%x) has same base as previous CR3 (0x%x) - reusing shadow page table\n", *((uint_t*)new_cr3), *((uint_t*)guest_cr3));
+       }
 
        PrintDebug("Old Shadow CR3=%x; Old Guest CR3=%x\n", 
                   *(uint_t*)shadow_cr3, *(uint_t*)guest_cr3);
@@ -472,10 +479,13 @@ int handle_cr3_write(struct guest_info * info) {
        *guest_cr3 = *new_cr3;
 
 
-
-       // Something like this
-       shadow_pt =  create_new_shadow_pt32(info);
-       //shadow_pt = setup_shadow_pt32(info, CR3_TO_PDE32(*(addr_t *)new_cr3));
+       if (flushed) { 
+         // Something like this
+         shadow_pt =  create_new_shadow_pt32(info);
+         //shadow_pt = setup_shadow_pt32(info, CR3_TO_PDE32(*(addr_t *)new_cr3));
+       } else {
+         shadow_pt = shadow_cr3->pdt_base_addr<<12;
+       }
 
        /* Copy Various flags */
        *shadow_cr3 = *new_cr3;
@@ -496,9 +506,6 @@ int handle_cr3_write(struct guest_info * info) {
        PrintDebug("New Shadow CR3=%x; New Guest CR3=%x\n", 
                   *(uint_t*)shadow_cr3, *(uint_t*)guest_cr3);
 
-
-
-
       }
       info->rip += index;
 
@@ -581,6 +588,7 @@ int handle_cr3_write(struct guest_info * info) {
       new_cr3 = (struct cr3_32 *)first_operand;
 
       if (info->shdw_pg_mode == SHADOW_PAGING) {
+       int flushed=0;
        addr_t shadow_pt;
        struct cr3_32 * shadow_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.shadow_cr3);
        struct cr3_32 * guest_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
@@ -594,7 +602,13 @@ int handle_cr3_write(struct guest_info * info) {
        */
 
        /* Delete the current Page Tables */
-       delete_page_tables_pde32((pde32_t *)CR3_TO_PDE32(*(uint_t*)shadow_cr3));
+       if (!CR3_32_SAME_BASE(guest_cr3,new_cr3)) { 
+         PrintDebug("New CR3 is different - flushing shadow page table\n");
+         delete_page_tables_pde32((pde32_t *)CR3_TO_PDE32(*(uint_t*)shadow_cr3));
+         flushed=1;
+       } else {
+         PrintDebug("New CR3 (0x%x) has same base as previous CR3 (0x%x) - reusing shadow page table\n",*((uint_t*)new_cr3), *((uint_t*)guest_cr3));
+       }
 
        PrintDebug("Old Shadow CR3=%x; Old Guest CR3=%x\n", 
                   *(uint_t*)shadow_cr3, *(uint_t*)guest_cr3);
@@ -602,12 +616,15 @@ int handle_cr3_write(struct guest_info * info) {
 
        *guest_cr3 = *new_cr3;
 
+       if (flushed) { 
+         // Something like this
+         shadow_pt =  create_new_shadow_pt32(info);
+         //shadow_pt = setup_shadow_pt32(info, CR3_TO_PDE32(*(addr_t *)new_cr3));
+       } else {
+         shadow_pt =shadow_cr3->pdt_base_addr << 12;
+       }
 
 
-       // Something like this
-       shadow_pt =  create_new_shadow_pt32(info);
-       //shadow_pt = setup_shadow_pt32(info, CR3_TO_PDE32(*(addr_t *)new_cr3));
-
        /* Copy Various flags */
        *shadow_cr3 = *new_cr3;