[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] [HVM] Save/restore: save RTC state.
# HG changeset patch # User Tim Deegan <Tim.Deegan@xxxxxxxxxxxxx> # Date 1170239327 0 # Node ID 9130206e27f8a5dacaea350ebbd895b14c9b09e2 # Parent ffcd586dbaae1c1f81132f0d7c697d8699b292bd [HVM] Save/restore: save RTC state. Signed-off-by: Tim Deegan <Tim.Deegan@xxxxxxxxxxxxx> --- xen/arch/x86/hvm/hvm.c | 2 xen/arch/x86/hvm/intercept.c | 8 + xen/arch/x86/hvm/rtc.c | 195 ++++++++++++++++++++++---------------- xen/include/asm-x86/hvm/support.h | 15 +- xen/include/asm-x86/hvm/vpt.h | 9 - xen/include/public/hvm/save.h | 17 +++ 6 files changed, 149 insertions(+), 97 deletions(-) diff -r ffcd586dbaae -r 9130206e27f8 xen/arch/x86/hvm/hvm.c --- a/xen/arch/x86/hvm/hvm.c Wed Jan 31 10:27:10 2007 +0000 +++ b/xen/arch/x86/hvm/hvm.c Wed Jan 31 10:28:47 2007 +0000 @@ -254,7 +254,7 @@ int hvm_vcpu_initialise(struct vcpu *v) return 0; pit_init(v, cpu_khz); - rtc_init(v, RTC_PORT(0), RTC_IRQ); + rtc_init(v, RTC_PORT(0)); pmtimer_init(v, ACPI_PM_TMR_BLK_ADDRESS); hpet_init(v); diff -r ffcd586dbaae -r 9130206e27f8 xen/arch/x86/hvm/intercept.c --- a/xen/arch/x86/hvm/intercept.c Wed Jan 31 10:27:10 2007 +0000 +++ b/xen/arch/x86/hvm/intercept.c Wed Jan 31 10:28:47 2007 +0000 @@ -161,10 +161,12 @@ static struct { static struct { hvm_save_handler save; hvm_load_handler load; -} hvm_sr_handlers [HVM_SAVE_CODE_MAX + 1] = {{NULL, NULL},}; + const char *name; +} hvm_sr_handlers [HVM_SAVE_CODE_MAX + 1] = {{NULL, NULL, "<?>"},}; /* Init-time function to add entries to that list */ void hvm_register_savevm(uint16_t typecode, + const char *name, hvm_save_handler save_state, hvm_load_handler load_state) { @@ -173,6 +175,7 @@ void hvm_register_savevm(uint16_t typeco ASSERT(hvm_sr_handlers[typecode].load == NULL); hvm_sr_handlers[typecode].save = save_state; hvm_sr_handlers[typecode].load = load_state; + hvm_sr_handlers[typecode].name = name; } @@ -211,6 +214,7 @@ int hvm_save(struct domain *d, hvm_domai handler = hvm_sr_handlers[i].save; if ( handler != NULL ) { + gdprintk(XENLOG_INFO, "HVM save: %s\n", hvm_sr_handlers[i].name); if ( handler(d, h) != 0 ) { gdprintk(XENLOG_ERR, @@ -312,6 +316,8 @@ int hvm_load(struct domain *d, hvm_domai } /* Load the entry */ + gdprintk(XENLOG_INFO, "HVM restore: %s %"PRIu16"\n", + hvm_sr_handlers[desc->typecode].name, desc->instance); if ( handler(d, h) != 0 ) { gdprintk(XENLOG_ERR, diff -r ffcd586dbaae -r 9130206e27f8 xen/arch/x86/hvm/rtc.c --- a/xen/arch/x86/hvm/rtc.c Wed Jan 31 10:27:10 2007 +0000 +++ b/xen/arch/x86/hvm/rtc.c Wed Jan 31 10:28:47 2007 +0000 @@ -33,26 +33,26 @@ void rtc_periodic_cb(struct vcpu *v, voi void rtc_periodic_cb(struct vcpu *v, void *opaque) { RTCState *s = opaque; - s->cmos_data[RTC_REG_C] |= 0xc0; + s->hw.cmos_data[RTC_REG_C] |= 0xc0; } int is_rtc_periodic_irq(void *opaque) { RTCState *s = opaque; - return !(s->cmos_data[RTC_REG_C] & RTC_AF || - s->cmos_data[RTC_REG_C] & RTC_UF); + return !(s->hw.cmos_data[RTC_REG_C] & RTC_AF || + s->hw.cmos_data[RTC_REG_C] & RTC_UF); } /* Enable/configure/disable the periodic timer based on the RTC_PIE and * RTC_RATE_SELECT settings */ -static void rtc_timer_update(RTCState *s) +static void rtc_timer_update(RTCState *s, struct vcpu *v) { int period_code; int period; - period_code = s->cmos_data[RTC_REG_A] & RTC_RATE_SELECT; - if ( (period_code != 0) && (s->cmos_data[RTC_REG_B] & RTC_PIE) ) + period_code = s->hw.cmos_data[RTC_REG_A] & RTC_RATE_SELECT; + if ( (period_code != 0) && (s->hw.cmos_data[RTC_REG_B] & RTC_PIE) ) { if ( period_code <= 2 ) period_code += 7; @@ -62,7 +62,7 @@ static void rtc_timer_update(RTCState *s #ifdef DEBUG_RTC printk("HVM_RTC: period = %uns\n", period); #endif - create_periodic_time(current, &s->pt, period, RTC_IRQ, 0, rtc_periodic_cb, s); + create_periodic_time(v, &s->pt, period, RTC_IRQ, 0, rtc_periodic_cb, s); } else destroy_periodic_time(&s->pt); @@ -76,24 +76,24 @@ static int rtc_ioport_write(void *opaque if ( (addr & 1) == 0 ) { - s->cmos_index = data & 0x7f; - return (s->cmos_index < RTC_SIZE); - } - - if (s->cmos_index >= RTC_SIZE) + s->hw.cmos_index = data & 0x7f; + return (s->hw.cmos_index < RTC_CMOS_SIZE); + } + + if (s->hw.cmos_index >= RTC_CMOS_SIZE) return 0; #ifdef DEBUG_RTC printk("HVM_RTC: write index=0x%02x val=0x%02x\n", - s->cmos_index, data); + s->hw.cmos_index, data); #endif - switch ( s->cmos_index ) + switch ( s->hw.cmos_index ) { case RTC_SECONDS_ALARM: case RTC_MINUTES_ALARM: case RTC_HOURS_ALARM: - s->cmos_data[s->cmos_index] = data; + s->hw.cmos_data[s->hw.cmos_index] = data; break; case RTC_SECONDS: case RTC_MINUTES: @@ -102,32 +102,32 @@ static int rtc_ioport_write(void *opaque case RTC_DAY_OF_MONTH: case RTC_MONTH: case RTC_YEAR: - s->cmos_data[s->cmos_index] = data; + s->hw.cmos_data[s->hw.cmos_index] = data; /* if in set mode, do not update the time */ - if ( !(s->cmos_data[RTC_REG_B] & RTC_SET) ) + if ( !(s->hw.cmos_data[RTC_REG_B] & RTC_SET) ) rtc_set_time(s); break; case RTC_REG_A: /* UIP bit is read only */ - s->cmos_data[RTC_REG_A] = (data & ~RTC_UIP) | - (s->cmos_data[RTC_REG_A] & RTC_UIP); - rtc_timer_update(s); + s->hw.cmos_data[RTC_REG_A] = (data & ~RTC_UIP) | + (s->hw.cmos_data[RTC_REG_A] & RTC_UIP); + rtc_timer_update(s, current); break; case RTC_REG_B: if ( data & RTC_SET ) { /* set mode: reset UIP mode */ - s->cmos_data[RTC_REG_A] &= ~RTC_UIP; + s->hw.cmos_data[RTC_REG_A] &= ~RTC_UIP; data &= ~RTC_UIE; } else { /* if disabling set mode, update the time */ - if ( s->cmos_data[RTC_REG_B] & RTC_SET ) + if ( s->hw.cmos_data[RTC_REG_B] & RTC_SET ) rtc_set_time(s); } - s->cmos_data[RTC_REG_B] = data; - rtc_timer_update(s); + s->hw.cmos_data[RTC_REG_B] = data; + rtc_timer_update(s, current); break; case RTC_REG_C: case RTC_REG_D: @@ -140,7 +140,7 @@ static int rtc_ioport_write(void *opaque static inline int to_bcd(RTCState *s, int a) { - if ( s->cmos_data[RTC_REG_B] & 0x04 ) + if ( s->hw.cmos_data[RTC_REG_B] & 0x04 ) return a; else return ((a / 10) << 4) | (a % 10); @@ -148,7 +148,7 @@ static inline int to_bcd(RTCState *s, in static inline int from_bcd(RTCState *s, int a) { - if ( s->cmos_data[RTC_REG_B] & 0x04 ) + if ( s->hw.cmos_data[RTC_REG_B] & 0x04 ) return a; else return ((a >> 4) * 10) + (a & 0x0f); @@ -158,40 +158,40 @@ static void rtc_set_time(RTCState *s) { struct tm *tm = &s->current_tm; - tm->tm_sec = from_bcd(s, s->cmos_data[RTC_SECONDS]); - tm->tm_min = from_bcd(s, s->cmos_data[RTC_MINUTES]); - tm->tm_hour = from_bcd(s, s->cmos_data[RTC_HOURS] & 0x7f); - if ( !(s->cmos_data[RTC_REG_B] & 0x02) && - (s->cmos_data[RTC_HOURS] & 0x80) ) + tm->tm_sec = from_bcd(s, s->hw.cmos_data[RTC_SECONDS]); + tm->tm_min = from_bcd(s, s->hw.cmos_data[RTC_MINUTES]); + tm->tm_hour = from_bcd(s, s->hw.cmos_data[RTC_HOURS] & 0x7f); + if ( !(s->hw.cmos_data[RTC_REG_B] & 0x02) && + (s->hw.cmos_data[RTC_HOURS] & 0x80) ) tm->tm_hour += 12; - tm->tm_wday = from_bcd(s, s->cmos_data[RTC_DAY_OF_WEEK]); - tm->tm_mday = from_bcd(s, s->cmos_data[RTC_DAY_OF_MONTH]); - tm->tm_mon = from_bcd(s, s->cmos_data[RTC_MONTH]) - 1; - tm->tm_year = from_bcd(s, s->cmos_data[RTC_YEAR]) + 100; + tm->tm_wday = from_bcd(s, s->hw.cmos_data[RTC_DAY_OF_WEEK]); + tm->tm_mday = from_bcd(s, s->hw.cmos_data[RTC_DAY_OF_MONTH]); + tm->tm_mon = from_bcd(s, s->hw.cmos_data[RTC_MONTH]) - 1; + tm->tm_year = from_bcd(s, s->hw.cmos_data[RTC_YEAR]) + 100; } static void rtc_copy_date(RTCState *s) { const struct tm *tm = &s->current_tm; - s->cmos_data[RTC_SECONDS] = to_bcd(s, tm->tm_sec); - s->cmos_data[RTC_MINUTES] = to_bcd(s, tm->tm_min); - if ( s->cmos_data[RTC_REG_B] & RTC_24H ) + s->hw.cmos_data[RTC_SECONDS] = to_bcd(s, tm->tm_sec); + s->hw.cmos_data[RTC_MINUTES] = to_bcd(s, tm->tm_min); + if ( s->hw.cmos_data[RTC_REG_B] & RTC_24H ) { /* 24 hour format */ - s->cmos_data[RTC_HOURS] = to_bcd(s, tm->tm_hour); + s->hw.cmos_data[RTC_HOURS] = to_bcd(s, tm->tm_hour); } else { /* 12 hour format */ - s->cmos_data[RTC_HOURS] = to_bcd(s, tm->tm_hour % 12); + s->hw.cmos_data[RTC_HOURS] = to_bcd(s, tm->tm_hour % 12); if ( tm->tm_hour >= 12 ) - s->cmos_data[RTC_HOURS] |= 0x80; - } - s->cmos_data[RTC_DAY_OF_WEEK] = to_bcd(s, tm->tm_wday); - s->cmos_data[RTC_DAY_OF_MONTH] = to_bcd(s, tm->tm_mday); - s->cmos_data[RTC_MONTH] = to_bcd(s, tm->tm_mon + 1); - s->cmos_data[RTC_YEAR] = to_bcd(s, tm->tm_year % 100); + s->hw.cmos_data[RTC_HOURS] |= 0x80; + } + s->hw.cmos_data[RTC_DAY_OF_WEEK] = to_bcd(s, tm->tm_wday); + s->hw.cmos_data[RTC_DAY_OF_MONTH] = to_bcd(s, tm->tm_mday); + s->hw.cmos_data[RTC_MONTH] = to_bcd(s, tm->tm_mon + 1); + s->hw.cmos_data[RTC_YEAR] = to_bcd(s, tm->tm_year % 100); } /* month is between 0 and 11. */ @@ -251,7 +251,7 @@ static void rtc_update_second(void *opaq RTCState *s = opaque; /* if the oscillator is not in normal operation, we do not update */ - if ( (s->cmos_data[RTC_REG_A] & RTC_DIV_CTL) != RTC_REF_CLCK_32KHZ ) + if ( (s->hw.cmos_data[RTC_REG_A] & RTC_DIV_CTL) != RTC_REF_CLCK_32KHZ ) { s->next_second_time += 1000000000ULL; set_timer(&s->second_timer, s->next_second_time); @@ -260,8 +260,8 @@ static void rtc_update_second(void *opaq { rtc_next_second(&s->current_tm); - if ( !(s->cmos_data[RTC_REG_B] & RTC_SET) ) - s->cmos_data[RTC_REG_A] |= RTC_UIP; + if ( !(s->hw.cmos_data[RTC_REG_B] & RTC_SET) ) + s->hw.cmos_data[RTC_REG_A] |= RTC_UIP; /* Delay time before update cycle */ set_timer(&s->second_timer2, s->next_second_time + 244000); @@ -272,38 +272,38 @@ static void rtc_update_second2(void *opa { RTCState *s = opaque; - if ( !(s->cmos_data[RTC_REG_B] & RTC_SET) ) + if ( !(s->hw.cmos_data[RTC_REG_B] & RTC_SET) ) rtc_copy_date(s); /* check alarm */ - if ( s->cmos_data[RTC_REG_B] & RTC_AIE ) - { - if ( ((s->cmos_data[RTC_SECONDS_ALARM] & 0xc0) == 0xc0 || - from_bcd(s, s->cmos_data[RTC_SECONDS_ALARM]) == + if ( s->hw.cmos_data[RTC_REG_B] & RTC_AIE ) + { + if ( ((s->hw.cmos_data[RTC_SECONDS_ALARM] & 0xc0) == 0xc0 || + from_bcd(s, s->hw.cmos_data[RTC_SECONDS_ALARM]) == s->current_tm.tm_sec) && - ((s->cmos_data[RTC_MINUTES_ALARM] & 0xc0) == 0xc0 || - from_bcd(s, s->cmos_data[RTC_MINUTES_ALARM]) == + ((s->hw.cmos_data[RTC_MINUTES_ALARM] & 0xc0) == 0xc0 || + from_bcd(s, s->hw.cmos_data[RTC_MINUTES_ALARM]) == s->current_tm.tm_min) && - ((s->cmos_data[RTC_HOURS_ALARM] & 0xc0) == 0xc0 || - from_bcd(s, s->cmos_data[RTC_HOURS_ALARM]) == + ((s->hw.cmos_data[RTC_HOURS_ALARM] & 0xc0) == 0xc0 || + from_bcd(s, s->hw.cmos_data[RTC_HOURS_ALARM]) == s->current_tm.tm_hour) ) { - s->cmos_data[RTC_REG_C] |= 0xa0; - hvm_isa_irq_deassert(s->pt.vcpu->domain, s->irq); - hvm_isa_irq_assert(s->pt.vcpu->domain, s->irq); + s->hw.cmos_data[RTC_REG_C] |= 0xa0; + hvm_isa_irq_deassert(s->pt.vcpu->domain, RTC_IRQ); + hvm_isa_irq_assert(s->pt.vcpu->domain, RTC_IRQ); } } /* update ended interrupt */ - if ( s->cmos_data[RTC_REG_B] & RTC_UIE ) - { - s->cmos_data[RTC_REG_C] |= 0x90; - hvm_isa_irq_deassert(s->pt.vcpu->domain, s->irq); - hvm_isa_irq_assert(s->pt.vcpu->domain, s->irq); + if ( s->hw.cmos_data[RTC_REG_B] & RTC_UIE ) + { + s->hw.cmos_data[RTC_REG_C] |= 0x90; + hvm_isa_irq_deassert(s->pt.vcpu->domain, RTC_IRQ); + hvm_isa_irq_assert(s->pt.vcpu->domain, RTC_IRQ); } /* clear update in progress bit */ - s->cmos_data[RTC_REG_A] &= ~RTC_UIP; + s->hw.cmos_data[RTC_REG_A] &= ~RTC_UIP; s->next_second_time += 1000000000ULL; set_timer(&s->second_timer, s->next_second_time); @@ -317,7 +317,7 @@ static uint32_t rtc_ioport_read(void *op if ( (addr & 1) == 0 ) return 0xff; - switch ( s->cmos_index ) + switch ( s->hw.cmos_index ) { case RTC_SECONDS: case RTC_MINUTES: @@ -326,24 +326,24 @@ static uint32_t rtc_ioport_read(void *op case RTC_DAY_OF_MONTH: case RTC_MONTH: case RTC_YEAR: - ret = s->cmos_data[s->cmos_index]; + ret = s->hw.cmos_data[s->hw.cmos_index]; break; case RTC_REG_A: - ret = s->cmos_data[s->cmos_index]; + ret = s->hw.cmos_data[s->hw.cmos_index]; break; case RTC_REG_C: - ret = s->cmos_data[s->cmos_index]; - hvm_isa_irq_deassert(s->pt.vcpu->domain, s->irq); - s->cmos_data[RTC_REG_C] = 0x00; + ret = s->hw.cmos_data[s->hw.cmos_index]; + hvm_isa_irq_deassert(s->pt.vcpu->domain, RTC_IRQ); + s->hw.cmos_data[RTC_REG_C] = 0x00; break; default: - ret = s->cmos_data[s->cmos_index]; + ret = s->hw.cmos_data[s->hw.cmos_index]; break; } #ifdef DEBUG_RTC printk("HVM_RTC: read index=0x%02x val=0x%02x\n", - s->cmos_index, ret); + s->hw.cmos_index, ret); #endif return ret; @@ -365,7 +365,7 @@ static int handle_rtc_io(ioreq_t *p) if ( rtc_ioport_write(vrtc, p->addr, p->data & 0xFF) ) return 1; } - else if ( (p->dir == 1) && (vrtc->cmos_index < RTC_SIZE) ) /* read */ + else if ( (p->dir == 1) && (vrtc->hw.cmos_index < RTC_CMOS_SIZE) ) /* read */ { p->data = rtc_ioport_read(vrtc, p->addr); return 1; @@ -388,16 +388,47 @@ void rtc_migrate_timers(struct vcpu *v) } } -void rtc_init(struct vcpu *v, int base, int irq) +/* Save RTC hardware state */ +static int rtc_save(struct domain *d, hvm_domain_context_t *h) +{ + return hvm_save_entry(RTC, 0, h, &d->arch.hvm_domain.pl_time.vrtc.hw); +} + +/* Reload the hardware state from a saved domain */ +static int rtc_load(struct domain *d, hvm_domain_context_t *h) +{ + RTCState *s = &d->arch.hvm_domain.pl_time.vrtc; + + /* Restore the registers */ + if ( hvm_load_entry(RTC, h, &s->hw) != 0 ) + return -EINVAL; + + /* Reset the wall-clock time. In normal running, this runs with host + * time, so let's keep doing that. */ + s->current_tm = gmtime(get_localtime(d)); + rtc_copy_date(s); + s->next_second_time = NOW() + 1000000000ULL; + stop_timer(&s->second_timer); + set_timer(&s->second_timer2, s->next_second_time); + + /* Reset the periodic interrupt timer based on the registers */ + rtc_timer_update(s, d->vcpu[0]); + + return 0; +} + +HVM_REGISTER_SAVE_RESTORE(RTC, rtc_save, rtc_load); + + +void rtc_init(struct vcpu *v, int base) { RTCState *s = &v->domain->arch.hvm_domain.pl_time.vrtc; s->pt.vcpu = v; - s->irq = irq; - s->cmos_data[RTC_REG_A] = RTC_REF_CLCK_32KHZ | 6; /* ~1kHz */ - s->cmos_data[RTC_REG_B] = RTC_24H; - s->cmos_data[RTC_REG_C] = 0; - s->cmos_data[RTC_REG_D] = RTC_VRT; + s->hw.cmos_data[RTC_REG_A] = RTC_REF_CLCK_32KHZ | 6; /* ~1kHz */ + s->hw.cmos_data[RTC_REG_B] = RTC_24H; + s->hw.cmos_data[RTC_REG_C] = 0; + s->hw.cmos_data[RTC_REG_D] = RTC_VRT; s->current_tm = gmtime(get_localtime(v->domain)); rtc_copy_date(s); diff -r ffcd586dbaae -r 9130206e27f8 xen/include/asm-x86/hvm/support.h --- a/xen/include/asm-x86/hvm/support.h Wed Jan 31 10:27:10 2007 +0000 +++ b/xen/include/asm-x86/hvm/support.h Wed Jan 31 10:28:47 2007 +0000 @@ -215,17 +215,18 @@ typedef int (*hvm_load_handler) (struct hvm_domain_context_t *h); /* Init-time function to declare a pair of handlers for a type */ -void hvm_register_savevm(uint16_t typecode, +void hvm_register_savevm(uint16_t typecode, + const char *name, hvm_save_handler save_state, hvm_load_handler load_state); /* Syntactic sugar around that function */ -#define HVM_REGISTER_SAVE_RESTORE(_x, _save, _load) \ -static int __hvm_register_##_x##_save_and_restore(void) \ -{ \ - hvm_register_savevm(HVM_SAVE_CODE(_x), &_save, &_load); \ - return 0; \ -} \ +#define HVM_REGISTER_SAVE_RESTORE(_x, _save, _load) \ +static int __hvm_register_##_x##_save_and_restore(void) \ +{ \ + hvm_register_savevm(HVM_SAVE_CODE(_x), #_x, &_save, &_load); \ + return 0; \ +} \ __initcall(__hvm_register_##_x##_save_and_restore); diff -r ffcd586dbaae -r 9130206e27f8 xen/include/asm-x86/hvm/vpt.h --- a/xen/include/asm-x86/hvm/vpt.h Wed Jan 31 10:27:10 2007 +0000 +++ b/xen/include/asm-x86/hvm/vpt.h Wed Jan 31 10:28:47 2007 +0000 @@ -97,12 +97,11 @@ typedef struct PITState { struct periodic_time pt[3]; } PITState; -#define RTC_SIZE 14 typedef struct RTCState { - uint8_t cmos_data[RTC_SIZE]; /* Only handle time/interrupt part in HV */ - uint8_t cmos_index; + /* Hardware state */ + struct hvm_hw_rtc hw; + /* RTC's idea of the current time */ struct tm current_tm; - int irq; /* second update */ int64_t next_second_time; struct timer second_timer; @@ -145,7 +144,7 @@ void pit_stop_channel0_irq(PITState * pi void pit_stop_channel0_irq(PITState * pit); void pit_migrate_timers(struct vcpu *v); void pit_deinit(struct domain *d); -void rtc_init(struct vcpu *v, int base, int irq); +void rtc_init(struct vcpu *v, int base); void rtc_migrate_timers(struct vcpu *v); void rtc_deinit(struct domain *d); int is_rtc_periodic_irq(void *opaque); diff -r ffcd586dbaae -r 9130206e27f8 xen/include/public/hvm/save.h --- a/xen/include/public/hvm/save.h Wed Jan 31 10:27:10 2007 +0000 +++ b/xen/include/public/hvm/save.h Wed Jan 31 10:28:47 2007 +0000 @@ -367,9 +367,24 @@ DECLARE_HVM_SAVE_TYPE(LAPIC_REGS, 8, str /* + * RTC + */ + +#define RTC_CMOS_SIZE 14 +struct hvm_hw_rtc { + /* CMOS bytes */ + uint8_t cmos_data[RTC_CMOS_SIZE]; + /* Index register for 2-part operations */ + uint8_t cmos_index; +}; + +DECLARE_HVM_SAVE_TYPE(RTC, 9, struct hvm_hw_rtc); + + +/* * Largest type-code in use */ -#define HVM_SAVE_CODE_MAX 8 +#define HVM_SAVE_CODE_MAX 9 /* _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |