direct-io.hg

changeset 13741:9130206e27f8

[HVM] Save/restore: save RTC state.
Signed-off-by: Tim Deegan <Tim.Deegan@xensource.com>
author Tim Deegan <Tim.Deegan@xensource.com>
date Wed Jan 31 10:28:47 2007 +0000 (2007-01-31)
parents ffcd586dbaae
children d653e4bcead0
files xen/arch/x86/hvm/hvm.c xen/arch/x86/hvm/intercept.c xen/arch/x86/hvm/rtc.c xen/include/asm-x86/hvm/support.h xen/include/asm-x86/hvm/vpt.h xen/include/public/hvm/save.h
line diff
     1.1 --- a/xen/arch/x86/hvm/hvm.c	Wed Jan 31 10:27:10 2007 +0000
     1.2 +++ b/xen/arch/x86/hvm/hvm.c	Wed Jan 31 10:28:47 2007 +0000
     1.3 @@ -254,7 +254,7 @@ int hvm_vcpu_initialise(struct vcpu *v)
     1.4          return 0;
     1.5  
     1.6      pit_init(v, cpu_khz);
     1.7 -    rtc_init(v, RTC_PORT(0), RTC_IRQ);
     1.8 +    rtc_init(v, RTC_PORT(0));
     1.9      pmtimer_init(v, ACPI_PM_TMR_BLK_ADDRESS);
    1.10      hpet_init(v);
    1.11   
     2.1 --- a/xen/arch/x86/hvm/intercept.c	Wed Jan 31 10:27:10 2007 +0000
     2.2 +++ b/xen/arch/x86/hvm/intercept.c	Wed Jan 31 10:28:47 2007 +0000
     2.3 @@ -161,10 +161,12 @@ static inline void hvm_mmio_access(struc
     2.4  static struct { 
     2.5      hvm_save_handler save;
     2.6      hvm_load_handler load; 
     2.7 -} hvm_sr_handlers [HVM_SAVE_CODE_MAX + 1] = {{NULL, NULL},};
     2.8 +    const char *name;
     2.9 +} hvm_sr_handlers [HVM_SAVE_CODE_MAX + 1] = {{NULL, NULL, "<?>"},};
    2.10  
    2.11  /* Init-time function to add entries to that list */
    2.12  void hvm_register_savevm(uint16_t typecode, 
    2.13 +                         const char *name,
    2.14                           hvm_save_handler save_state,
    2.15                           hvm_load_handler load_state)
    2.16  {
    2.17 @@ -173,6 +175,7 @@ void hvm_register_savevm(uint16_t typeco
    2.18      ASSERT(hvm_sr_handlers[typecode].load == NULL);
    2.19      hvm_sr_handlers[typecode].save = save_state;
    2.20      hvm_sr_handlers[typecode].load = load_state;
    2.21 +    hvm_sr_handlers[typecode].name = name;
    2.22  }
    2.23  
    2.24  
    2.25 @@ -211,6 +214,7 @@ int hvm_save(struct domain *d, hvm_domai
    2.26          handler = hvm_sr_handlers[i].save;
    2.27          if ( handler != NULL ) 
    2.28          {
    2.29 +            gdprintk(XENLOG_INFO, "HVM save: %s\n",  hvm_sr_handlers[i].name);
    2.30              if ( handler(d, h) != 0 ) 
    2.31              {
    2.32                  gdprintk(XENLOG_ERR, 
    2.33 @@ -312,6 +316,8 @@ int hvm_load(struct domain *d, hvm_domai
    2.34          }
    2.35  
    2.36          /* Load the entry */
    2.37 +        gdprintk(XENLOG_INFO, "HVM restore: %s %"PRIu16"\n",  
    2.38 +                 hvm_sr_handlers[desc->typecode].name, desc->instance);
    2.39          if ( handler(d, h) != 0 ) 
    2.40          {
    2.41              gdprintk(XENLOG_ERR, 
     3.1 --- a/xen/arch/x86/hvm/rtc.c	Wed Jan 31 10:27:10 2007 +0000
     3.2 +++ b/xen/arch/x86/hvm/rtc.c	Wed Jan 31 10:28:47 2007 +0000
     3.3 @@ -33,26 +33,26 @@
     3.4  void rtc_periodic_cb(struct vcpu *v, void *opaque)
     3.5  {
     3.6      RTCState *s = opaque;
     3.7 -    s->cmos_data[RTC_REG_C] |= 0xc0;
     3.8 +    s->hw.cmos_data[RTC_REG_C] |= 0xc0;
     3.9  }
    3.10  
    3.11  int is_rtc_periodic_irq(void *opaque)
    3.12  {
    3.13      RTCState *s = opaque;
    3.14  
    3.15 -    return !(s->cmos_data[RTC_REG_C] & RTC_AF || 
    3.16 -           s->cmos_data[RTC_REG_C] & RTC_UF);
    3.17 +    return !(s->hw.cmos_data[RTC_REG_C] & RTC_AF || 
    3.18 +           s->hw.cmos_data[RTC_REG_C] & RTC_UF);
    3.19  }
    3.20  
    3.21  /* Enable/configure/disable the periodic timer based on the RTC_PIE and
    3.22   * RTC_RATE_SELECT settings */
    3.23 -static void rtc_timer_update(RTCState *s)
    3.24 +static void rtc_timer_update(RTCState *s, struct vcpu *v)
    3.25  {
    3.26      int period_code; 
    3.27      int period;
    3.28  
    3.29 -    period_code = s->cmos_data[RTC_REG_A] & RTC_RATE_SELECT;
    3.30 -    if ( (period_code != 0) && (s->cmos_data[RTC_REG_B] & RTC_PIE) )
    3.31 +    period_code = s->hw.cmos_data[RTC_REG_A] & RTC_RATE_SELECT;
    3.32 +    if ( (period_code != 0) && (s->hw.cmos_data[RTC_REG_B] & RTC_PIE) )
    3.33      {
    3.34          if ( period_code <= 2 )
    3.35              period_code += 7;
    3.36 @@ -62,7 +62,7 @@ static void rtc_timer_update(RTCState *s
    3.37  #ifdef DEBUG_RTC
    3.38          printk("HVM_RTC: period = %uns\n", period);
    3.39  #endif
    3.40 -        create_periodic_time(current, &s->pt, period, RTC_IRQ, 0, rtc_periodic_cb, s);
    3.41 +        create_periodic_time(v, &s->pt, period, RTC_IRQ, 0, rtc_periodic_cb, s);
    3.42      } 
    3.43      else
    3.44          destroy_periodic_time(&s->pt);
    3.45 @@ -76,24 +76,24 @@ static int rtc_ioport_write(void *opaque
    3.46  
    3.47      if ( (addr & 1) == 0 )
    3.48      {
    3.49 -        s->cmos_index = data & 0x7f;
    3.50 -        return (s->cmos_index < RTC_SIZE);
    3.51 +        s->hw.cmos_index = data & 0x7f;
    3.52 +        return (s->hw.cmos_index < RTC_CMOS_SIZE);
    3.53      }
    3.54  
    3.55 -    if (s->cmos_index >= RTC_SIZE)
    3.56 +    if (s->hw.cmos_index >= RTC_CMOS_SIZE)
    3.57          return 0;
    3.58  
    3.59  #ifdef DEBUG_RTC
    3.60      printk("HVM_RTC: write index=0x%02x val=0x%02x\n",
    3.61 -           s->cmos_index, data);
    3.62 +           s->hw.cmos_index, data);
    3.63  #endif
    3.64  
    3.65 -    switch ( s->cmos_index )
    3.66 +    switch ( s->hw.cmos_index )
    3.67      {
    3.68      case RTC_SECONDS_ALARM:
    3.69      case RTC_MINUTES_ALARM:
    3.70      case RTC_HOURS_ALARM:
    3.71 -        s->cmos_data[s->cmos_index] = data;
    3.72 +        s->hw.cmos_data[s->hw.cmos_index] = data;
    3.73          break;
    3.74      case RTC_SECONDS:
    3.75      case RTC_MINUTES:
    3.76 @@ -102,32 +102,32 @@ static int rtc_ioport_write(void *opaque
    3.77      case RTC_DAY_OF_MONTH:
    3.78      case RTC_MONTH:
    3.79      case RTC_YEAR:
    3.80 -        s->cmos_data[s->cmos_index] = data;
    3.81 +        s->hw.cmos_data[s->hw.cmos_index] = data;
    3.82          /* if in set mode, do not update the time */
    3.83 -        if ( !(s->cmos_data[RTC_REG_B] & RTC_SET) )
    3.84 +        if ( !(s->hw.cmos_data[RTC_REG_B] & RTC_SET) )
    3.85              rtc_set_time(s);
    3.86          break;
    3.87      case RTC_REG_A:
    3.88          /* UIP bit is read only */
    3.89 -        s->cmos_data[RTC_REG_A] = (data & ~RTC_UIP) |
    3.90 -            (s->cmos_data[RTC_REG_A] & RTC_UIP);
    3.91 -        rtc_timer_update(s);
    3.92 +        s->hw.cmos_data[RTC_REG_A] = (data & ~RTC_UIP) |
    3.93 +            (s->hw.cmos_data[RTC_REG_A] & RTC_UIP);
    3.94 +        rtc_timer_update(s, current);
    3.95          break;
    3.96      case RTC_REG_B:
    3.97          if ( data & RTC_SET )
    3.98          {
    3.99              /* set mode: reset UIP mode */
   3.100 -            s->cmos_data[RTC_REG_A] &= ~RTC_UIP;
   3.101 +            s->hw.cmos_data[RTC_REG_A] &= ~RTC_UIP;
   3.102              data &= ~RTC_UIE;
   3.103          }
   3.104          else
   3.105          {
   3.106              /* if disabling set mode, update the time */
   3.107 -            if ( s->cmos_data[RTC_REG_B] & RTC_SET )
   3.108 +            if ( s->hw.cmos_data[RTC_REG_B] & RTC_SET )
   3.109                  rtc_set_time(s);
   3.110          }
   3.111 -        s->cmos_data[RTC_REG_B] = data;
   3.112 -        rtc_timer_update(s);
   3.113 +        s->hw.cmos_data[RTC_REG_B] = data;
   3.114 +        rtc_timer_update(s, current);
   3.115          break;
   3.116      case RTC_REG_C:
   3.117      case RTC_REG_D:
   3.118 @@ -140,7 +140,7 @@ static int rtc_ioport_write(void *opaque
   3.119  
   3.120  static inline int to_bcd(RTCState *s, int a)
   3.121  {
   3.122 -    if ( s->cmos_data[RTC_REG_B] & 0x04 )
   3.123 +    if ( s->hw.cmos_data[RTC_REG_B] & 0x04 )
   3.124          return a;
   3.125      else
   3.126          return ((a / 10) << 4) | (a % 10);
   3.127 @@ -148,7 +148,7 @@ static inline int to_bcd(RTCState *s, in
   3.128  
   3.129  static inline int from_bcd(RTCState *s, int a)
   3.130  {
   3.131 -    if ( s->cmos_data[RTC_REG_B] & 0x04 )
   3.132 +    if ( s->hw.cmos_data[RTC_REG_B] & 0x04 )
   3.133          return a;
   3.134      else
   3.135          return ((a >> 4) * 10) + (a & 0x0f);
   3.136 @@ -158,40 +158,40 @@ static void rtc_set_time(RTCState *s)
   3.137  {
   3.138      struct tm *tm = &s->current_tm;
   3.139      
   3.140 -    tm->tm_sec = from_bcd(s, s->cmos_data[RTC_SECONDS]);
   3.141 -    tm->tm_min = from_bcd(s, s->cmos_data[RTC_MINUTES]);
   3.142 -    tm->tm_hour = from_bcd(s, s->cmos_data[RTC_HOURS] & 0x7f);
   3.143 -    if ( !(s->cmos_data[RTC_REG_B] & 0x02) &&
   3.144 -         (s->cmos_data[RTC_HOURS] & 0x80) )
   3.145 +    tm->tm_sec = from_bcd(s, s->hw.cmos_data[RTC_SECONDS]);
   3.146 +    tm->tm_min = from_bcd(s, s->hw.cmos_data[RTC_MINUTES]);
   3.147 +    tm->tm_hour = from_bcd(s, s->hw.cmos_data[RTC_HOURS] & 0x7f);
   3.148 +    if ( !(s->hw.cmos_data[RTC_REG_B] & 0x02) &&
   3.149 +         (s->hw.cmos_data[RTC_HOURS] & 0x80) )
   3.150          tm->tm_hour += 12;
   3.151 -    tm->tm_wday = from_bcd(s, s->cmos_data[RTC_DAY_OF_WEEK]);
   3.152 -    tm->tm_mday = from_bcd(s, s->cmos_data[RTC_DAY_OF_MONTH]);
   3.153 -    tm->tm_mon = from_bcd(s, s->cmos_data[RTC_MONTH]) - 1;
   3.154 -    tm->tm_year = from_bcd(s, s->cmos_data[RTC_YEAR]) + 100;
   3.155 +    tm->tm_wday = from_bcd(s, s->hw.cmos_data[RTC_DAY_OF_WEEK]);
   3.156 +    tm->tm_mday = from_bcd(s, s->hw.cmos_data[RTC_DAY_OF_MONTH]);
   3.157 +    tm->tm_mon = from_bcd(s, s->hw.cmos_data[RTC_MONTH]) - 1;
   3.158 +    tm->tm_year = from_bcd(s, s->hw.cmos_data[RTC_YEAR]) + 100;
   3.159  }
   3.160  
   3.161  static void rtc_copy_date(RTCState *s)
   3.162  {
   3.163      const struct tm *tm = &s->current_tm;
   3.164  
   3.165 -    s->cmos_data[RTC_SECONDS] = to_bcd(s, tm->tm_sec);
   3.166 -    s->cmos_data[RTC_MINUTES] = to_bcd(s, tm->tm_min);
   3.167 -    if ( s->cmos_data[RTC_REG_B] & RTC_24H )
   3.168 +    s->hw.cmos_data[RTC_SECONDS] = to_bcd(s, tm->tm_sec);
   3.169 +    s->hw.cmos_data[RTC_MINUTES] = to_bcd(s, tm->tm_min);
   3.170 +    if ( s->hw.cmos_data[RTC_REG_B] & RTC_24H )
   3.171      {
   3.172          /* 24 hour format */
   3.173 -        s->cmos_data[RTC_HOURS] = to_bcd(s, tm->tm_hour);
   3.174 +        s->hw.cmos_data[RTC_HOURS] = to_bcd(s, tm->tm_hour);
   3.175      }
   3.176      else
   3.177      {
   3.178          /* 12 hour format */
   3.179 -        s->cmos_data[RTC_HOURS] = to_bcd(s, tm->tm_hour % 12);
   3.180 +        s->hw.cmos_data[RTC_HOURS] = to_bcd(s, tm->tm_hour % 12);
   3.181          if ( tm->tm_hour >= 12 )
   3.182 -            s->cmos_data[RTC_HOURS] |= 0x80;
   3.183 +            s->hw.cmos_data[RTC_HOURS] |= 0x80;
   3.184      }
   3.185 -    s->cmos_data[RTC_DAY_OF_WEEK] = to_bcd(s, tm->tm_wday);
   3.186 -    s->cmos_data[RTC_DAY_OF_MONTH] = to_bcd(s, tm->tm_mday);
   3.187 -    s->cmos_data[RTC_MONTH] = to_bcd(s, tm->tm_mon + 1);
   3.188 -    s->cmos_data[RTC_YEAR] = to_bcd(s, tm->tm_year % 100);
   3.189 +    s->hw.cmos_data[RTC_DAY_OF_WEEK] = to_bcd(s, tm->tm_wday);
   3.190 +    s->hw.cmos_data[RTC_DAY_OF_MONTH] = to_bcd(s, tm->tm_mday);
   3.191 +    s->hw.cmos_data[RTC_MONTH] = to_bcd(s, tm->tm_mon + 1);
   3.192 +    s->hw.cmos_data[RTC_YEAR] = to_bcd(s, tm->tm_year % 100);
   3.193  }
   3.194  
   3.195  /* month is between 0 and 11. */
   3.196 @@ -251,7 +251,7 @@ static void rtc_update_second(void *opaq
   3.197      RTCState *s = opaque;
   3.198  
   3.199      /* if the oscillator is not in normal operation, we do not update */
   3.200 -    if ( (s->cmos_data[RTC_REG_A] & RTC_DIV_CTL) != RTC_REF_CLCK_32KHZ )
   3.201 +    if ( (s->hw.cmos_data[RTC_REG_A] & RTC_DIV_CTL) != RTC_REF_CLCK_32KHZ )
   3.202      {
   3.203          s->next_second_time += 1000000000ULL;
   3.204          set_timer(&s->second_timer, s->next_second_time);
   3.205 @@ -260,8 +260,8 @@ static void rtc_update_second(void *opaq
   3.206      {
   3.207          rtc_next_second(&s->current_tm);
   3.208          
   3.209 -        if ( !(s->cmos_data[RTC_REG_B] & RTC_SET) )
   3.210 -            s->cmos_data[RTC_REG_A] |= RTC_UIP;
   3.211 +        if ( !(s->hw.cmos_data[RTC_REG_B] & RTC_SET) )
   3.212 +            s->hw.cmos_data[RTC_REG_A] |= RTC_UIP;
   3.213  
   3.214          /* Delay time before update cycle */
   3.215          set_timer(&s->second_timer2, s->next_second_time + 244000);
   3.216 @@ -272,38 +272,38 @@ static void rtc_update_second2(void *opa
   3.217  {
   3.218      RTCState *s = opaque;
   3.219  
   3.220 -    if ( !(s->cmos_data[RTC_REG_B] & RTC_SET) )
   3.221 +    if ( !(s->hw.cmos_data[RTC_REG_B] & RTC_SET) )
   3.222          rtc_copy_date(s);
   3.223  
   3.224      /* check alarm */
   3.225 -    if ( s->cmos_data[RTC_REG_B] & RTC_AIE )
   3.226 +    if ( s->hw.cmos_data[RTC_REG_B] & RTC_AIE )
   3.227      {
   3.228 -        if ( ((s->cmos_data[RTC_SECONDS_ALARM] & 0xc0) == 0xc0 ||
   3.229 -              from_bcd(s, s->cmos_data[RTC_SECONDS_ALARM]) ==
   3.230 +        if ( ((s->hw.cmos_data[RTC_SECONDS_ALARM] & 0xc0) == 0xc0 ||
   3.231 +              from_bcd(s, s->hw.cmos_data[RTC_SECONDS_ALARM]) ==
   3.232                s->current_tm.tm_sec) &&
   3.233 -             ((s->cmos_data[RTC_MINUTES_ALARM] & 0xc0) == 0xc0 ||
   3.234 -              from_bcd(s, s->cmos_data[RTC_MINUTES_ALARM]) ==
   3.235 +             ((s->hw.cmos_data[RTC_MINUTES_ALARM] & 0xc0) == 0xc0 ||
   3.236 +              from_bcd(s, s->hw.cmos_data[RTC_MINUTES_ALARM]) ==
   3.237                s->current_tm.tm_min) &&
   3.238 -             ((s->cmos_data[RTC_HOURS_ALARM] & 0xc0) == 0xc0 ||
   3.239 -              from_bcd(s, s->cmos_data[RTC_HOURS_ALARM]) ==
   3.240 +             ((s->hw.cmos_data[RTC_HOURS_ALARM] & 0xc0) == 0xc0 ||
   3.241 +              from_bcd(s, s->hw.cmos_data[RTC_HOURS_ALARM]) ==
   3.242                s->current_tm.tm_hour) )
   3.243          {
   3.244 -            s->cmos_data[RTC_REG_C] |= 0xa0; 
   3.245 -            hvm_isa_irq_deassert(s->pt.vcpu->domain, s->irq);
   3.246 -            hvm_isa_irq_assert(s->pt.vcpu->domain, s->irq);
   3.247 +            s->hw.cmos_data[RTC_REG_C] |= 0xa0; 
   3.248 +            hvm_isa_irq_deassert(s->pt.vcpu->domain, RTC_IRQ);
   3.249 +            hvm_isa_irq_assert(s->pt.vcpu->domain, RTC_IRQ);
   3.250          }
   3.251      }
   3.252  
   3.253      /* update ended interrupt */
   3.254 -    if ( s->cmos_data[RTC_REG_B] & RTC_UIE )
   3.255 +    if ( s->hw.cmos_data[RTC_REG_B] & RTC_UIE )
   3.256      {
   3.257 -        s->cmos_data[RTC_REG_C] |= 0x90; 
   3.258 -        hvm_isa_irq_deassert(s->pt.vcpu->domain, s->irq);
   3.259 -        hvm_isa_irq_assert(s->pt.vcpu->domain, s->irq);
   3.260 +        s->hw.cmos_data[RTC_REG_C] |= 0x90; 
   3.261 +        hvm_isa_irq_deassert(s->pt.vcpu->domain, RTC_IRQ);
   3.262 +        hvm_isa_irq_assert(s->pt.vcpu->domain, RTC_IRQ);
   3.263      }
   3.264  
   3.265      /* clear update in progress bit */
   3.266 -    s->cmos_data[RTC_REG_A] &= ~RTC_UIP;
   3.267 +    s->hw.cmos_data[RTC_REG_A] &= ~RTC_UIP;
   3.268  
   3.269      s->next_second_time += 1000000000ULL;
   3.270      set_timer(&s->second_timer, s->next_second_time);
   3.271 @@ -317,7 +317,7 @@ static uint32_t rtc_ioport_read(void *op
   3.272      if ( (addr & 1) == 0 )
   3.273          return 0xff;
   3.274  
   3.275 -    switch ( s->cmos_index )
   3.276 +    switch ( s->hw.cmos_index )
   3.277      {
   3.278      case RTC_SECONDS:
   3.279      case RTC_MINUTES:
   3.280 @@ -326,24 +326,24 @@ static uint32_t rtc_ioport_read(void *op
   3.281      case RTC_DAY_OF_MONTH:
   3.282      case RTC_MONTH:
   3.283      case RTC_YEAR:
   3.284 -        ret = s->cmos_data[s->cmos_index];
   3.285 +        ret = s->hw.cmos_data[s->hw.cmos_index];
   3.286          break;
   3.287      case RTC_REG_A:
   3.288 -        ret = s->cmos_data[s->cmos_index];
   3.289 +        ret = s->hw.cmos_data[s->hw.cmos_index];
   3.290          break;
   3.291      case RTC_REG_C:
   3.292 -        ret = s->cmos_data[s->cmos_index];
   3.293 -        hvm_isa_irq_deassert(s->pt.vcpu->domain, s->irq);
   3.294 -        s->cmos_data[RTC_REG_C] = 0x00; 
   3.295 +        ret = s->hw.cmos_data[s->hw.cmos_index];
   3.296 +        hvm_isa_irq_deassert(s->pt.vcpu->domain, RTC_IRQ);
   3.297 +        s->hw.cmos_data[RTC_REG_C] = 0x00; 
   3.298          break;
   3.299      default:
   3.300 -        ret = s->cmos_data[s->cmos_index];
   3.301 +        ret = s->hw.cmos_data[s->hw.cmos_index];
   3.302          break;
   3.303      }
   3.304  
   3.305  #ifdef DEBUG_RTC
   3.306      printk("HVM_RTC: read index=0x%02x val=0x%02x\n",
   3.307 -           s->cmos_index, ret);
   3.308 +           s->hw.cmos_index, ret);
   3.309  #endif
   3.310  
   3.311      return ret;
   3.312 @@ -365,7 +365,7 @@ static int handle_rtc_io(ioreq_t *p)
   3.313          if ( rtc_ioport_write(vrtc, p->addr, p->data & 0xFF) )
   3.314              return 1;
   3.315      }
   3.316 -    else if ( (p->dir == 1) && (vrtc->cmos_index < RTC_SIZE) ) /* read */
   3.317 +    else if ( (p->dir == 1) && (vrtc->hw.cmos_index < RTC_CMOS_SIZE) ) /* read */
   3.318      {
   3.319          p->data = rtc_ioport_read(vrtc, p->addr);
   3.320          return 1;
   3.321 @@ -388,16 +388,47 @@ void rtc_migrate_timers(struct vcpu *v)
   3.322      }
   3.323  }
   3.324  
   3.325 -void rtc_init(struct vcpu *v, int base, int irq)
   3.326 +/* Save RTC hardware state */
   3.327 +static int rtc_save(struct domain *d, hvm_domain_context_t *h)
   3.328 +{
   3.329 +    return hvm_save_entry(RTC, 0, h, &d->arch.hvm_domain.pl_time.vrtc.hw);
   3.330 +}
   3.331 +
   3.332 +/* Reload the hardware state from a saved domain */
   3.333 +static int rtc_load(struct domain *d, hvm_domain_context_t *h)
   3.334 +{
   3.335 +    RTCState *s = &d->arch.hvm_domain.pl_time.vrtc;    
   3.336 +
   3.337 +    /* Restore the registers */
   3.338 +    if ( hvm_load_entry(RTC, h, &s->hw) != 0 )
   3.339 +        return -EINVAL;
   3.340 +
   3.341 +    /* Reset the wall-clock time.  In normal running, this runs with host 
   3.342 +     * time, so let's keep doing that. */
   3.343 +    s->current_tm = gmtime(get_localtime(d));
   3.344 +    rtc_copy_date(s);
   3.345 +    s->next_second_time = NOW() + 1000000000ULL;
   3.346 +    stop_timer(&s->second_timer);
   3.347 +    set_timer(&s->second_timer2, s->next_second_time);
   3.348 +
   3.349 +    /* Reset the periodic interrupt timer based on the registers */
   3.350 +    rtc_timer_update(s, d->vcpu[0]);
   3.351 +
   3.352 +    return 0;
   3.353 +}
   3.354 +
   3.355 +HVM_REGISTER_SAVE_RESTORE(RTC, rtc_save, rtc_load);
   3.356 +
   3.357 +
   3.358 +void rtc_init(struct vcpu *v, int base)
   3.359  {
   3.360      RTCState *s = &v->domain->arch.hvm_domain.pl_time.vrtc;
   3.361  
   3.362      s->pt.vcpu = v;
   3.363 -    s->irq = irq;
   3.364 -    s->cmos_data[RTC_REG_A] = RTC_REF_CLCK_32KHZ | 6; /* ~1kHz */
   3.365 -    s->cmos_data[RTC_REG_B] = RTC_24H;
   3.366 -    s->cmos_data[RTC_REG_C] = 0;
   3.367 -    s->cmos_data[RTC_REG_D] = RTC_VRT;
   3.368 +    s->hw.cmos_data[RTC_REG_A] = RTC_REF_CLCK_32KHZ | 6; /* ~1kHz */
   3.369 +    s->hw.cmos_data[RTC_REG_B] = RTC_24H;
   3.370 +    s->hw.cmos_data[RTC_REG_C] = 0;
   3.371 +    s->hw.cmos_data[RTC_REG_D] = RTC_VRT;
   3.372  
   3.373      s->current_tm = gmtime(get_localtime(v->domain));
   3.374      rtc_copy_date(s);
     4.1 --- a/xen/include/asm-x86/hvm/support.h	Wed Jan 31 10:27:10 2007 +0000
     4.2 +++ b/xen/include/asm-x86/hvm/support.h	Wed Jan 31 10:28:47 2007 +0000
     4.3 @@ -215,17 +215,18 @@ typedef int (*hvm_load_handler) (struct 
     4.4                                   hvm_domain_context_t *h);
     4.5  
     4.6  /* Init-time function to declare a pair of handlers for a type */
     4.7 -void hvm_register_savevm(uint16_t typecode, 
     4.8 +void hvm_register_savevm(uint16_t typecode,
     4.9 +                         const char *name, 
    4.10                           hvm_save_handler save_state,
    4.11                           hvm_load_handler load_state);
    4.12  
    4.13  /* Syntactic sugar around that function */
    4.14 -#define HVM_REGISTER_SAVE_RESTORE(_x, _save, _load)             \
    4.15 -static int __hvm_register_##_x##_save_and_restore(void)         \
    4.16 -{                                                               \
    4.17 -    hvm_register_savevm(HVM_SAVE_CODE(_x), &_save, &_load);     \
    4.18 -    return 0;                                                   \
    4.19 -}                                                               \
    4.20 +#define HVM_REGISTER_SAVE_RESTORE(_x, _save, _load)                     \
    4.21 +static int __hvm_register_##_x##_save_and_restore(void)                 \
    4.22 +{                                                                       \
    4.23 +    hvm_register_savevm(HVM_SAVE_CODE(_x), #_x, &_save, &_load);        \
    4.24 +    return 0;                                                           \
    4.25 +}                                                                       \
    4.26  __initcall(__hvm_register_##_x##_save_and_restore);
    4.27  
    4.28  
     5.1 --- a/xen/include/asm-x86/hvm/vpt.h	Wed Jan 31 10:27:10 2007 +0000
     5.2 +++ b/xen/include/asm-x86/hvm/vpt.h	Wed Jan 31 10:28:47 2007 +0000
     5.3 @@ -97,12 +97,11 @@ typedef struct PITState {
     5.4      struct periodic_time pt[3];
     5.5  } PITState;
     5.6  
     5.7 -#define RTC_SIZE 14
     5.8  typedef struct RTCState {
     5.9 -    uint8_t cmos_data[RTC_SIZE];  /* Only handle time/interrupt part in HV */
    5.10 -    uint8_t cmos_index;
    5.11 +    /* Hardware state */
    5.12 +    struct hvm_hw_rtc hw;
    5.13 +    /* RTC's idea of the current time */
    5.14      struct tm current_tm;
    5.15 -    int irq;
    5.16      /* second update */
    5.17      int64_t next_second_time;
    5.18      struct timer second_timer;
    5.19 @@ -145,7 +144,7 @@ void pit_init(struct vcpu *v, unsigned l
    5.20  void pit_stop_channel0_irq(PITState * pit);
    5.21  void pit_migrate_timers(struct vcpu *v);
    5.22  void pit_deinit(struct domain *d);
    5.23 -void rtc_init(struct vcpu *v, int base, int irq);
    5.24 +void rtc_init(struct vcpu *v, int base);
    5.25  void rtc_migrate_timers(struct vcpu *v);
    5.26  void rtc_deinit(struct domain *d);
    5.27  int is_rtc_periodic_irq(void *opaque);
     6.1 --- a/xen/include/public/hvm/save.h	Wed Jan 31 10:27:10 2007 +0000
     6.2 +++ b/xen/include/public/hvm/save.h	Wed Jan 31 10:28:47 2007 +0000
     6.3 @@ -367,9 +367,24 @@ DECLARE_HVM_SAVE_TYPE(LAPIC_REGS, 8, str
     6.4  
     6.5  
     6.6  /* 
     6.7 + * RTC
     6.8 + */ 
     6.9 +
    6.10 +#define RTC_CMOS_SIZE 14
    6.11 +struct hvm_hw_rtc {
    6.12 +    /* CMOS bytes */
    6.13 +    uint8_t cmos_data[RTC_CMOS_SIZE];
    6.14 +    /* Index register for 2-part operations */
    6.15 +    uint8_t cmos_index;
    6.16 +};
    6.17 +
    6.18 +DECLARE_HVM_SAVE_TYPE(RTC, 9, struct hvm_hw_rtc);
    6.19 +
    6.20 +
    6.21 +/* 
    6.22   * Largest type-code in use
    6.23   */
    6.24 -#define HVM_SAVE_CODE_MAX 8
    6.25 +#define HVM_SAVE_CODE_MAX 9
    6.26  
    6.27  
    6.28  /*