ia64/xen-unstable
changeset 13541:56228886421d
[HVM] Save/restore cleanups 01: PIT
Define public structure for the saved PIT data and use it instead
of a series of explicit loads and stores.
Don't save ephemeral Xen timer structs; rebuild them instead.
Signed-off-by: Tim Deegan <Tim.Deegan@xensource.com>
Define public structure for the saved PIT data and use it instead
of a series of explicit loads and stores.
Don't save ephemeral Xen timer structs; rebuild them instead.
Signed-off-by: Tim Deegan <Tim.Deegan@xensource.com>
author | Tim Deegan <Tim.Deegan@xensource.com> |
---|---|
date | Sat Jan 20 11:17:38 2007 +0000 (2007-01-20) |
parents | dcb145f858e3 |
children | dccdc3ee0efc |
files | xen/arch/x86/domain.c xen/arch/x86/hvm/hvm.c xen/arch/x86/hvm/i8254.c xen/arch/x86/hvm/intercept.c xen/arch/x86/hvm/vioapic.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/domain.c Fri Jan 19 15:23:41 2007 +0000 1.2 +++ b/xen/arch/x86/domain.c Sat Jan 20 11:17:38 2007 +0000 1.3 @@ -329,9 +329,6 @@ int vcpu_initialise(struct vcpu *v) 1.4 1.5 pae_l3_cache_init(&v->arch.pae_l3_cache); 1.6 1.7 - /* This should move to arch_domain_create(). */ 1.8 - if ( !is_idle_domain(d) && (v->vcpu_id == 0) ) 1.9 - pit_init(v, cpu_khz); 1.10 1.11 if ( is_hvm_domain(d) ) 1.12 { 1.13 @@ -340,6 +337,10 @@ int vcpu_initialise(struct vcpu *v) 1.14 } 1.15 else 1.16 { 1.17 + /* PV guests get an emulated PIT too for video BIOSes to use. */ 1.18 + if ( !is_idle_domain(d) && (v->vcpu_id == 0) ) 1.19 + pit_init(v, cpu_khz); 1.20 + 1.21 v->arch.schedule_tail = continue_nonidle_domain; 1.22 v->arch.ctxt_switch_from = paravirt_ctxt_switch_from; 1.23 v->arch.ctxt_switch_to = paravirt_ctxt_switch_to;
2.1 --- a/xen/arch/x86/hvm/hvm.c Fri Jan 19 15:23:41 2007 +0000 2.2 +++ b/xen/arch/x86/hvm/hvm.c Sat Jan 20 11:17:38 2007 +0000 2.3 @@ -194,6 +194,7 @@ int hvm_vcpu_initialise(struct vcpu *v) 2.4 if ( v->vcpu_id != 0 ) 2.5 return 0; 2.6 2.7 + pit_init(v, cpu_khz); 2.8 rtc_init(v, RTC_PORT(0), RTC_IRQ); 2.9 pmtimer_init(v, ACPI_PM_TMR_BLK_ADDRESS); 2.10 hpet_init(v);
3.1 --- a/xen/arch/x86/hvm/i8254.c Fri Jan 19 15:23:41 2007 +0000 3.2 +++ b/xen/arch/x86/hvm/i8254.c Sat Jan 20 11:17:38 2007 +0000 3.3 @@ -76,37 +76,42 @@ uint64_t muldiv64(uint64_t a, uint32_t b 3.4 return res.ll; 3.5 } 3.6 3.7 -static int pit_get_count(PITChannelState *s) 3.8 +static int pit_get_count(PITState *s, int channel) 3.9 { 3.10 uint64_t d; 3.11 int counter; 3.12 + struct hvm_hw_pit_channel *c = &s->hw.channels[channel]; 3.13 + struct periodic_time *pt = &s->pt[channel]; 3.14 3.15 - d = muldiv64(hvm_get_guest_time(s->pt.vcpu) - s->count_load_time, PIT_FREQ, ticks_per_sec(s->pt.vcpu)); 3.16 - switch(s->mode) { 3.17 + d = muldiv64(hvm_get_guest_time(pt->vcpu) 3.18 + - c->count_load_time, PIT_FREQ, ticks_per_sec(pt->vcpu)); 3.19 + switch(c->mode) { 3.20 case 0: 3.21 case 1: 3.22 case 4: 3.23 case 5: 3.24 - counter = (s->count - d) & 0xffff; 3.25 + counter = (c->count - d) & 0xffff; 3.26 break; 3.27 case 3: 3.28 /* XXX: may be incorrect for odd counts */ 3.29 - counter = s->count - ((2 * d) % s->count); 3.30 + counter = c->count - ((2 * d) % c->count); 3.31 break; 3.32 default: 3.33 - counter = s->count - (d % s->count); 3.34 + counter = c->count - (d % c->count); 3.35 break; 3.36 } 3.37 return counter; 3.38 } 3.39 3.40 /* get pit output bit */ 3.41 -static int pit_get_out1(PITChannelState *s, int64_t current_time) 3.42 +int pit_get_out(PITState *pit, int channel, int64_t current_time) 3.43 { 3.44 + struct hvm_hw_pit_channel *s = &pit->hw.channels[channel]; 3.45 uint64_t d; 3.46 int out; 3.47 3.48 - d = muldiv64(current_time - s->count_load_time, PIT_FREQ, ticks_per_sec(s->pt.vcpu)); 3.49 + d = muldiv64(current_time - s->count_load_time, 3.50 + PIT_FREQ, ticks_per_sec(pit->pt[channel].vcpu)); 3.51 switch(s->mode) { 3.52 default: 3.53 case 0: 3.54 @@ -132,16 +137,11 @@ static int pit_get_out1(PITChannelState 3.55 return out; 3.56 } 3.57 3.58 -int pit_get_out(PITState *pit, int channel, int64_t current_time) 3.59 -{ 3.60 - PITChannelState *s = &pit->channels[channel]; 3.61 - return pit_get_out1(s, current_time); 3.62 -} 3.63 - 3.64 /* val must be 0 or 1 */ 3.65 void pit_set_gate(PITState *pit, int channel, int val) 3.66 { 3.67 - PITChannelState *s = &pit->channels[channel]; 3.68 + struct hvm_hw_pit_channel *s = &pit->hw.channels[channel]; 3.69 + struct periodic_time *pt = &pit->pt[channel]; 3.70 3.71 switch(s->mode) { 3.72 default: 3.73 @@ -153,7 +153,7 @@ void pit_set_gate(PITState *pit, int cha 3.74 case 5: 3.75 if (s->gate < val) { 3.76 /* restart counting on rising edge */ 3.77 - s->count_load_time = hvm_get_guest_time(s->pt.vcpu); 3.78 + s->count_load_time = hvm_get_guest_time(pt->vcpu); 3.79 // pit_irq_timer_update(s, s->count_load_time); 3.80 } 3.81 break; 3.82 @@ -161,7 +161,7 @@ void pit_set_gate(PITState *pit, int cha 3.83 case 3: 3.84 if (s->gate < val) { 3.85 /* restart counting on rising edge */ 3.86 - s->count_load_time = hvm_get_guest_time(s->pt.vcpu); 3.87 + s->count_load_time = hvm_get_guest_time(pt->vcpu); 3.88 // pit_irq_timer_update(s, s->count_load_time); 3.89 } 3.90 /* XXX: disable/enable counting */ 3.91 @@ -172,23 +172,25 @@ void pit_set_gate(PITState *pit, int cha 3.92 3.93 int pit_get_gate(PITState *pit, int channel) 3.94 { 3.95 - PITChannelState *s = &pit->channels[channel]; 3.96 - return s->gate; 3.97 + return pit->hw.channels[channel].gate; 3.98 } 3.99 3.100 void pit_time_fired(struct vcpu *v, void *priv) 3.101 { 3.102 - PITChannelState *s = priv; 3.103 + struct hvm_hw_pit_channel *s = priv; 3.104 s->count_load_time = hvm_get_guest_time(v); 3.105 } 3.106 3.107 -static inline void pit_load_count(PITChannelState *s, int channel, int val) 3.108 +static inline void pit_load_count(PITState *pit, int channel, int val) 3.109 { 3.110 u32 period; 3.111 + struct hvm_hw_pit_channel *s = &pit->hw.channels[channel]; 3.112 + struct periodic_time *pt = &pit->pt[channel]; 3.113 + struct vcpu *v; 3.114 3.115 if (val == 0) 3.116 val = 0x10000; 3.117 - s->count_load_time = hvm_get_guest_time(s->pt.vcpu); 3.118 + s->count_load_time = hvm_get_guest_time(pt->vcpu); 3.119 s->count = val; 3.120 period = DIV_ROUND((val * 1000000000ULL), PIT_FREQ); 3.121 3.122 @@ -204,30 +206,38 @@ static inline void pit_load_count(PITCha 3.123 (long long)s->count_load_time); 3.124 #endif 3.125 3.126 + /* Choose a vcpu to set the timer on: current if appropriate else vcpu 0 */ 3.127 + if ( likely(pit == ¤t->domain->arch.hvm_domain.pl_time.vpit) ) 3.128 + v = current; 3.129 + else 3.130 + v = container_of(pit, struct domain, 3.131 + arch.hvm_domain.pl_time.vpit)->vcpu[0]; 3.132 + 3.133 switch (s->mode) { 3.134 case 2: 3.135 /* create periodic time */ 3.136 - create_periodic_time(current, &s->pt, period, 0, 0, pit_time_fired, s); 3.137 + create_periodic_time(v, pt, period, 0, 0, pit_time_fired, s); 3.138 break; 3.139 case 1: 3.140 /* create one shot time */ 3.141 - create_periodic_time(current, &s->pt, period, 0, 1, pit_time_fired, s); 3.142 + create_periodic_time(v, pt, period, 0, 1, pit_time_fired, s); 3.143 #ifdef DEBUG_PIT 3.144 printk("HVM_PIT: create one shot time.\n"); 3.145 #endif 3.146 break; 3.147 default: 3.148 - destroy_periodic_time(&s->pt); 3.149 + destroy_periodic_time(pt); 3.150 break; 3.151 } 3.152 } 3.153 3.154 /* if already latched, do not latch again */ 3.155 -static void pit_latch_count(PITChannelState *s) 3.156 +static void pit_latch_count(PITState *s, int channel) 3.157 { 3.158 - if (!s->count_latched) { 3.159 - s->latched_count = pit_get_count(s); 3.160 - s->count_latched = s->rw_mode; 3.161 + struct hvm_hw_pit_channel *c = &s->hw.channels[channel]; 3.162 + if (!c->count_latched) { 3.163 + c->latched_count = pit_get_count(s, channel); 3.164 + c->count_latched = c->rw_mode; 3.165 } 3.166 } 3.167 3.168 @@ -235,7 +245,7 @@ static void pit_ioport_write(void *opaqu 3.169 { 3.170 PITState *pit = opaque; 3.171 int channel, access; 3.172 - PITChannelState *s; 3.173 + struct hvm_hw_pit_channel *s; 3.174 val &= 0xff; 3.175 3.176 addr &= 3; 3.177 @@ -244,15 +254,15 @@ static void pit_ioport_write(void *opaqu 3.178 if (channel == 3) { 3.179 /* read back command */ 3.180 for(channel = 0; channel < 3; channel++) { 3.181 - s = &pit->channels[channel]; 3.182 + s = &pit->hw.channels[channel]; 3.183 if (val & (2 << channel)) { 3.184 if (!(val & 0x20)) { 3.185 - pit_latch_count(s); 3.186 + pit_latch_count(pit, channel); 3.187 } 3.188 if (!(val & 0x10) && !s->status_latched) { 3.189 /* status latch */ 3.190 /* XXX: add BCD and null count */ 3.191 - s->status = (pit_get_out1(s, hvm_get_guest_time(s->pt.vcpu)) << 7) | 3.192 + s->status = (pit_get_out(pit, channel, hvm_get_guest_time(pit->pt[channel].vcpu)) << 7) | 3.193 (s->rw_mode << 4) | 3.194 (s->mode << 1) | 3.195 s->bcd; 3.196 @@ -261,10 +271,10 @@ static void pit_ioport_write(void *opaqu 3.197 } 3.198 } 3.199 } else { 3.200 - s = &pit->channels[channel]; 3.201 + s = &pit->hw.channels[channel]; 3.202 access = (val >> 4) & 3; 3.203 if (access == 0) { 3.204 - pit_latch_count(s); 3.205 + pit_latch_count(pit, channel); 3.206 } else { 3.207 s->rw_mode = access; 3.208 s->read_state = access; 3.209 @@ -276,21 +286,21 @@ static void pit_ioport_write(void *opaqu 3.210 } 3.211 } 3.212 } else { 3.213 - s = &pit->channels[addr]; 3.214 + s = &pit->hw.channels[addr]; 3.215 switch(s->write_state) { 3.216 default: 3.217 case RW_STATE_LSB: 3.218 - pit_load_count(s, addr, val); 3.219 + pit_load_count(pit, addr, val); 3.220 break; 3.221 case RW_STATE_MSB: 3.222 - pit_load_count(s, addr, val << 8); 3.223 + pit_load_count(pit, addr, val << 8); 3.224 break; 3.225 case RW_STATE_WORD0: 3.226 s->write_latch = val; 3.227 s->write_state = RW_STATE_WORD1; 3.228 break; 3.229 case RW_STATE_WORD1: 3.230 - pit_load_count(s, addr, s->write_latch | (val << 8)); 3.231 + pit_load_count(pit, addr, s->write_latch | (val << 8)); 3.232 s->write_state = RW_STATE_WORD0; 3.233 break; 3.234 } 3.235 @@ -301,10 +311,10 @@ static uint32_t pit_ioport_read(void *op 3.236 { 3.237 PITState *pit = opaque; 3.238 int ret, count; 3.239 - PITChannelState *s; 3.240 + struct hvm_hw_pit_channel *s; 3.241 3.242 addr &= 3; 3.243 - s = &pit->channels[addr]; 3.244 + s = &pit->hw.channels[addr]; 3.245 if (s->status_latched) { 3.246 s->status_latched = 0; 3.247 ret = s->status; 3.248 @@ -328,20 +338,20 @@ static uint32_t pit_ioport_read(void *op 3.249 switch(s->read_state) { 3.250 default: 3.251 case RW_STATE_LSB: 3.252 - count = pit_get_count(s); 3.253 + count = pit_get_count(pit, addr); 3.254 ret = count & 0xff; 3.255 break; 3.256 case RW_STATE_MSB: 3.257 - count = pit_get_count(s); 3.258 + count = pit_get_count(pit, addr); 3.259 ret = (count >> 8) & 0xff; 3.260 break; 3.261 case RW_STATE_WORD0: 3.262 - count = pit_get_count(s); 3.263 + count = pit_get_count(pit, addr); 3.264 ret = count & 0xff; 3.265 s->read_state = RW_STATE_WORD1; 3.266 break; 3.267 case RW_STATE_WORD1: 3.268 - count = pit_get_count(s); 3.269 + count = pit_get_count(pit, addr); 3.270 ret = (count >> 8) & 0xff; 3.271 s->read_state = RW_STATE_WORD0; 3.272 break; 3.273 @@ -352,19 +362,19 @@ static uint32_t pit_ioport_read(void *op 3.274 3.275 void pit_stop_channel0_irq(PITState * pit) 3.276 { 3.277 - PITChannelState *s = &pit->channels[0]; 3.278 - destroy_periodic_time(&s->pt); 3.279 + destroy_periodic_time(&pit->pt[0]); 3.280 } 3.281 3.282 #ifdef HVM_DEBUG_SUSPEND 3.283 static void pit_info(PITState *pit) 3.284 { 3.285 - PITChannelState *s; 3.286 + struct hvm_hw_pit_channel *s; 3.287 + struct periodic_time *pt; 3.288 int i; 3.289 3.290 for(i = 0; i < 3; i++) { 3.291 printk("*****pit channel %d's state:*****\n", i); 3.292 - s = &pit->channels[i]; 3.293 + s = &pit->hw.channels[i]; 3.294 printk("pit 0x%x.\n", s->count); 3.295 printk("pit 0x%x.\n", s->latched_count); 3.296 printk("pit 0x%x.\n", s->count_latched); 3.297 @@ -379,8 +389,8 @@ static void pit_info(PITState *pit) 3.298 printk("pit 0x%x.\n", s->gate); 3.299 printk("pit %"PRId64"\n", s->count_load_time); 3.300 3.301 - if (s->pt) { 3.302 - struct periodic_time *pt = s->pt; 3.303 + pt = &pit->pt[i]; 3.304 + if (pt) { 3.305 printk("pit channel %d has a periodic timer:\n", i); 3.306 printk("pt %d.\n", pt->enabled); 3.307 printk("pt %d.\n", pt->one_shot); 3.308 @@ -405,131 +415,64 @@ static void pit_save(hvm_domain_context_ 3.309 { 3.310 struct domain *d = opaque; 3.311 PITState *pit = &d->arch.hvm_domain.pl_time.vpit; 3.312 - PITChannelState *s; 3.313 - struct periodic_time *pt; 3.314 - int i, pti = -1; 3.315 3.316 pit_info(pit); 3.317 3.318 - for(i = 0; i < 3; i++) { 3.319 - s = &pit->channels[i]; 3.320 - hvm_put_32u(h, s->count); 3.321 - hvm_put_16u(h, s->latched_count); 3.322 - hvm_put_8u(h, s->count_latched); 3.323 - hvm_put_8u(h, s->status_latched); 3.324 - hvm_put_8u(h, s->status); 3.325 - hvm_put_8u(h, s->read_state); 3.326 - hvm_put_8u(h, s->write_state); 3.327 - hvm_put_8u(h, s->write_latch); 3.328 - hvm_put_8u(h, s->rw_mode); 3.329 - hvm_put_8u(h, s->mode); 3.330 - hvm_put_8u(h, s->bcd); 3.331 - hvm_put_8u(h, s->gate); 3.332 - hvm_put_64u(h, s->count_load_time); 3.333 - 3.334 - if (s->pt.enabled && pti == -1) 3.335 - pti = i; 3.336 - } 3.337 - 3.338 - pt = &pit->channels[pti].pt; 3.339 - 3.340 - /* save the vcpu for pt */ 3.341 - hvm_put_32u(h, pt->vcpu->vcpu_id); 3.342 - 3.343 - /* save guest time */ 3.344 - hvm_put_8u(h, pti); 3.345 - hvm_put_32u(h, pt->pending_intr_nr); 3.346 - hvm_put_64u(h, pt->last_plt_gtime); 3.347 - 3.348 + /* Save the PIT hardware state */ 3.349 + hvm_put_struct(h, &pit->hw); 3.350 } 3.351 3.352 static int pit_load(hvm_domain_context_t *h, void *opaque, int version_id) 3.353 { 3.354 struct domain *d = opaque; 3.355 PITState *pit = &d->arch.hvm_domain.pl_time.vpit; 3.356 - PITChannelState *s; 3.357 - int i, pti, vcpu_id; 3.358 - u32 period; 3.359 + int i; 3.360 3.361 if (version_id != 1) 3.362 return -EINVAL; 3.363 3.364 + /* Restore the PIT hardware state */ 3.365 + hvm_get_struct(h, &pit->hw); 3.366 + 3.367 + /* Recreate platform timers from hardware state. There will be some 3.368 + * time jitter here, but the wall-clock will have jumped massively, so 3.369 + * we hope the guest can handle it. */ 3.370 + 3.371 for(i = 0; i < 3; i++) { 3.372 - s = &pit->channels[i]; 3.373 - s->count = hvm_get_32u(h); 3.374 - s->latched_count = hvm_get_16u(h); 3.375 - s->count_latched = hvm_get_8u(h); 3.376 - s->status_latched = hvm_get_8u(h); 3.377 - s->status = hvm_get_8u(h); 3.378 - s->read_state = hvm_get_8u(h); 3.379 - s->write_state = hvm_get_8u(h); 3.380 - s->write_latch = hvm_get_8u(h); 3.381 - s->rw_mode = hvm_get_8u(h); 3.382 - s->mode = hvm_get_8u(h); 3.383 - s->bcd = hvm_get_8u(h); 3.384 - s->gate = hvm_get_8u(h); 3.385 - s->count_load_time = hvm_get_64u(h); 3.386 + pit_load_count(pit, i, pit_get_count(pit, i)); 3.387 + pit->pt[i].last_plt_gtime = hvm_get_guest_time(d->vcpu[0]); 3.388 } 3.389 3.390 - vcpu_id = hvm_get_32u(h); 3.391 - 3.392 - pti = hvm_get_8u(h); 3.393 - if ( pti < 0 || pti > 2) { 3.394 - printk("pit load get a wrong channel %d when HVM resume.\n", pti); 3.395 - return -EINVAL; 3.396 - } 3.397 - 3.398 - s = &pit->channels[pti]; 3.399 - period = DIV_ROUND((s->count * 1000000000ULL), PIT_FREQ); 3.400 - 3.401 - printk("recreate periodic timer %d in mode %d, freq=%d.\n", pti, s->mode, period); 3.402 - switch (s->mode) { 3.403 - case 2: 3.404 - /* create periodic time */ 3.405 - create_periodic_time(d->vcpu[vcpu_id], &s->pt, period, 0, 0, pit_time_fired, s); 3.406 - break; 3.407 - case 1: 3.408 - /* create one shot time */ 3.409 - create_periodic_time(d->vcpu[vcpu_id], &s->pt, period, 0, 1, pit_time_fired, s); 3.410 - break; 3.411 - default: 3.412 - printk("pit mode %"PRId8" should not use periodic timer!\n", s->mode); 3.413 - return -EINVAL; 3.414 - } 3.415 - s->pt.pending_intr_nr = hvm_get_32u(h); 3.416 - s->pt.last_plt_gtime = hvm_get_64u(h); 3.417 - 3.418 pit_info(pit); 3.419 - 3.420 return 0; 3.421 } 3.422 3.423 static void pit_reset(void *opaque) 3.424 { 3.425 PITState *pit = opaque; 3.426 - PITChannelState *s; 3.427 + struct hvm_hw_pit_channel *s; 3.428 int i; 3.429 3.430 for(i = 0;i < 3; i++) { 3.431 - s = &pit->channels[i]; 3.432 - destroy_periodic_time(&s->pt); 3.433 + s = &pit->hw.channels[i]; 3.434 + destroy_periodic_time(&pit->pt[i]); 3.435 s->mode = 0xff; /* the init mode */ 3.436 s->gate = (i != 2); 3.437 - pit_load_count(s, i, 0); 3.438 + pit_load_count(pit, i, 0); 3.439 } 3.440 } 3.441 3.442 void pit_init(struct vcpu *v, unsigned long cpu_khz) 3.443 { 3.444 PITState *pit = &v->domain->arch.hvm_domain.pl_time.vpit; 3.445 - PITChannelState *s; 3.446 + struct periodic_time *pt; 3.447 3.448 - s = &pit->channels[0]; 3.449 - s->pt.vcpu = v; 3.450 + pt = &pit->pt[0]; 3.451 + pt->vcpu = v; 3.452 /* the timer 0 is connected to an IRQ */ 3.453 - init_timer(&s->pt.timer, pt_timer_fn, &s->pt, v->processor); 3.454 - s++; s->pt.vcpu = v; 3.455 - s++; s->pt.vcpu = v; 3.456 + init_timer(&pt->timer, pt_timer_fn, pt, v->processor); 3.457 + pt++; pt->vcpu = v; 3.458 + pt++; pt->vcpu = v; 3.459 3.460 hvm_register_savevm(v->domain, "xen_hvm_i8254", PIT_BASE, 1, pit_save, pit_load, v->domain); 3.461 register_portio_handler(v->domain, PIT_BASE, 4, handle_pit_io); 3.462 @@ -546,20 +489,18 @@ void pit_init(struct vcpu *v, unsigned l 3.463 void pit_migrate_timers(struct vcpu *v) 3.464 { 3.465 PITState *pit = &v->domain->arch.hvm_domain.pl_time.vpit; 3.466 - PITChannelState *s; 3.467 + struct periodic_time *pt; 3.468 3.469 - s = &pit->channels[0]; 3.470 - if ( s->pt.vcpu == v && s->pt.enabled ) 3.471 - migrate_timer(&s->pt.timer, v->processor); 3.472 + pt = &pit->pt[0]; 3.473 + if ( pt->vcpu == v && pt->enabled ) 3.474 + migrate_timer(&pt->timer, v->processor); 3.475 } 3.476 3.477 void pit_deinit(struct domain *d) 3.478 { 3.479 PITState *pit = &d->arch.hvm_domain.pl_time.vpit; 3.480 - PITChannelState *s; 3.481 3.482 - s = &pit->channels[0]; 3.483 - kill_timer(&s->pt.timer); 3.484 + kill_timer(&pit->pt[0].timer); 3.485 } 3.486 3.487 /* the intercept action for PIT DM retval:0--not handled; 1--handled */ 3.488 @@ -590,7 +531,7 @@ static int handle_pit_io(ioreq_t *p) 3.489 static void speaker_ioport_write(void *opaque, uint32_t addr, uint32_t val) 3.490 { 3.491 PITState *pit = opaque; 3.492 - pit->speaker_data_on = (val >> 1) & 1; 3.493 + pit->hw.speaker_data_on = (val >> 1) & 1; 3.494 pit_set_gate(pit, 2, val & 1); 3.495 } 3.496 3.497 @@ -598,10 +539,10 @@ static uint32_t speaker_ioport_read(void 3.498 { 3.499 PITState *pit = opaque; 3.500 int out = pit_get_out(pit, 2, 3.501 - hvm_get_guest_time(pit->channels[2].pt.vcpu)); 3.502 + hvm_get_guest_time(pit->pt[2].vcpu)); 3.503 /* Refresh clock toggles at about 15us. We approximate as 2^14ns. */ 3.504 unsigned int refresh_clock = ((unsigned int)NOW() >> 14) & 1; 3.505 - return ((pit->speaker_data_on << 1) | pit_get_gate(pit, 2) | 3.506 + return ((pit->hw.speaker_data_on << 1) | pit_get_gate(pit, 2) | 3.507 (out << 5) | refresh_clock << 4); 3.508 } 3.509
4.1 --- a/xen/arch/x86/hvm/intercept.c Fri Jan 19 15:23:41 2007 +0000 4.2 +++ b/xen/arch/x86/hvm/intercept.c Sat Jan 20 11:17:38 2007 +0000 4.3 @@ -358,6 +358,8 @@ int hvm_load(struct vcpu *v, hvm_domain_ 4.4 instance_id = hvm_get_32u(h); 4.5 version_id = hvm_get_32u(h); 4.6 4.7 + printk("HVM S/R Loading \"%s\" instance %#x\n", idstr, instance_id); 4.8 + 4.9 rec_len = hvm_get_32u(h); 4.10 rec_pos = hvm_ctxt_tell(h); 4.11
5.1 --- a/xen/arch/x86/hvm/vioapic.c Fri Jan 19 15:23:41 2007 +0000 5.2 +++ b/xen/arch/x86/hvm/vioapic.c Sat Jan 20 11:17:38 2007 +0000 5.3 @@ -312,7 +312,7 @@ static uint32_t ioapic_get_delivery_bitm 5.4 static inline int pit_channel0_enabled(void) 5.5 { 5.6 PITState *pit = ¤t->domain->arch.hvm_domain.pl_time.vpit; 5.7 - struct periodic_time *pt = &pit->channels[0].pt; 5.8 + struct periodic_time *pt = &pit->pt[0]; 5.9 return pt->enabled; 5.10 } 5.11
6.1 --- a/xen/include/asm-x86/hvm/support.h Fri Jan 19 15:23:41 2007 +0000 6.2 +++ b/xen/include/asm-x86/hvm/support.h Sat Jan 20 11:17:38 2007 +0000 6.3 @@ -186,7 +186,6 @@ static inline void hvm_put_buffer(hvm_do 6.4 h->cur += len; 6.5 } 6.6 6.7 - 6.8 static inline char hvm_get_byte(hvm_domain_context_t *h) 6.9 { 6.10 if (h->cur >= HVM_CTXT_SIZE) { 6.11 @@ -240,6 +239,12 @@ static inline void hvm_get_buffer(hvm_do 6.12 h->cur += len; 6.13 } 6.14 6.15 +#define hvm_put_struct(_h, _p) \ 6.16 + hvm_put_buffer((_h), (char *)(_p), sizeof(*(_p))) 6.17 +#define hvm_get_struct(_h, _p) \ 6.18 + hvm_get_buffer((_h), (char *)(_p), sizeof(*(_p))) 6.19 + 6.20 + 6.21 extern int hvm_save(struct vcpu*, hvm_domain_context_t *h); 6.22 extern int hvm_load(struct vcpu*, hvm_domain_context_t *h); 6.23
7.1 --- a/xen/include/asm-x86/hvm/vpt.h Fri Jan 19 15:23:41 2007 +0000 7.2 +++ b/xen/include/asm-x86/hvm/vpt.h Sat Jan 20 11:17:38 2007 +0000 7.3 @@ -29,7 +29,7 @@ 7.4 #include <xen/timer.h> 7.5 #include <xen/list.h> 7.6 #include <asm/hvm/vpic.h> 7.7 - 7.8 +#include <public/hvm/save.h> 7.9 7.10 #define HPET_TIMER_NUM 3 /* 3 timers supported now */ 7.11 struct HPET { 7.12 @@ -90,27 +90,11 @@ struct periodic_time { 7.13 #define PIT_FREQ 1193181 7.14 #define PIT_BASE 0x40 7.15 7.16 -typedef struct PITChannelState { 7.17 - int count; /* can be 65536 */ 7.18 - u16 latched_count; 7.19 - u8 count_latched; 7.20 - u8 status_latched; 7.21 - u8 status; 7.22 - u8 read_state; 7.23 - u8 write_state; 7.24 - u8 write_latch; 7.25 - u8 rw_mode; 7.26 - u8 mode; 7.27 - u8 bcd; /* not supported */ 7.28 - u8 gate; /* timer start */ 7.29 - s64 count_load_time; 7.30 +typedef struct PITState { 7.31 + /* Hardware state */ 7.32 + struct hvm_hw_pit hw; 7.33 /* irq handling */ 7.34 - struct periodic_time pt; 7.35 -} PITChannelState; 7.36 - 7.37 -typedef struct PITState { 7.38 - PITChannelState channels[3]; 7.39 - int speaker_data_on; 7.40 + struct periodic_time pt[3]; 7.41 } PITState; 7.42 7.43 #define RTC_SIZE 14
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/xen/include/public/hvm/save.h Sat Jan 20 11:17:38 2007 +0000 8.3 @@ -0,0 +1,138 @@ 8.4 +/* 8.5 + * hvm/save.h 8.6 + * 8.7 + * Structure definitions for HVM state that is held by Xen and must 8.8 + * be saved along with the domain's memory and device-model state. 8.9 + * 8.10 + * 8.11 + * Copyright (c) 2007 XenSource Ltd. 8.12 + * 8.13 + * Permission is hereby granted, free of charge, to any person obtaining a copy 8.14 + * of this software and associated documentation files (the "Software"), to 8.15 + * deal in the Software without restriction, including without limitation the 8.16 + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8.17 + * sell copies of the Software, and to permit persons to whom the Software is 8.18 + * furnished to do so, subject to the following conditions: 8.19 + * 8.20 + * The above copyright notice and this permission notice shall be included in 8.21 + * all copies or substantial portions of the Software. 8.22 + * 8.23 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 8.24 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 8.25 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 8.26 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 8.27 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 8.28 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 8.29 + * DEALINGS IN THE SOFTWARE. 8.30 + */ 8.31 + 8.32 +#ifndef __XEN_PUBLIC_HVM_SAVE_H__ 8.33 +#define __XEN_PUBLIC_HVM_SAVE_H__ 8.34 + 8.35 +/* 8.36 + * Structures in this header *must* have the same layout in 32bit 8.37 + * and 64bit environments: this means that all fields must be explicitly 8.38 + * sized types and aligned to their sizes. 8.39 + * 8.40 + * Only the state necessary for saving and restoring (i.e. fields 8.41 + * that are analogous to actual hardware state) should go in this file. 8.42 + * Internal mechanisms should be kept in Xen-private headers. 8.43 + */ 8.44 + 8.45 + 8.46 + 8.47 +/* 8.48 + * Processor 8.49 + */ 8.50 +#define HVM_SAVE_TYPE_CPU 1 8.51 +struct hvm_hw_cpu { 8.52 + uint64_t eip; 8.53 + uint64_t esp; 8.54 + uint64_t eflags; 8.55 + uint64_t cr0; 8.56 + uint64_t cr3; 8.57 + uint64_t cr4; 8.58 + 8.59 + uint32_t cs_sel; 8.60 + uint32_t ds_sel; 8.61 + uint32_t es_sel; 8.62 + uint32_t fs_sel; 8.63 + uint32_t gs_sel; 8.64 + uint32_t ss_sel; 8.65 + uint32_t tr_sel; 8.66 + uint32_t ldtr_sel; 8.67 + 8.68 + uint32_t cs_limit; 8.69 + uint32_t ds_limit; 8.70 + uint32_t es_limit; 8.71 + uint32_t fs_limit; 8.72 + uint32_t gs_limit; 8.73 + uint32_t ss_limit; 8.74 + uint32_t tr_limit; 8.75 + uint32_t ldtr_limit; 8.76 + uint32_t idtr_limit; 8.77 + uint32_t gdtr_limit; 8.78 + 8.79 + uint64_t cs_base; 8.80 + uint64_t ds_base; 8.81 + uint64_t es_base; 8.82 + uint64_t fs_base; 8.83 + uint64_t gs_base; 8.84 + uint64_t ss_base; 8.85 + uint64_t tr_base; 8.86 + uint64_t ldtr_base; 8.87 + uint64_t idtr_base; 8.88 + uint64_t gdtr_base; 8.89 + 8.90 + 8.91 + uint32_t cs_arbytes; 8.92 + uint32_t ds_arbytes; 8.93 + uint32_t es_arbytes; 8.94 + uint32_t fs_arbytes; 8.95 + uint32_t gs_arbytes; 8.96 + uint32_t ss_arbytes; 8.97 + uint32_t tr_arbytes; 8.98 + uint32_t ldtr_arbytes; 8.99 + 8.100 + uint32_t sysenter_cs; 8.101 + uint32_t padding0; 8.102 + 8.103 + uint64_t sysenter_esp; 8.104 + uint64_t sysenter_eip; 8.105 + 8.106 + /* msr for em64t */ 8.107 + uint64_t shadow_gs; 8.108 + uint64_t flags; 8.109 + 8.110 + /* same size as VMX_MSR_COUNT */ 8.111 + uint64_t msr_items[6]; 8.112 + uint64_t vmxassist_enabled; 8.113 +}; 8.114 + 8.115 + 8.116 +/* 8.117 + * PIT 8.118 + */ 8.119 +#define HVM_SAVE_TYPE_PIT 2 8.120 +struct hvm_hw_pit { 8.121 + struct hvm_hw_pit_channel { 8.122 + int64_t count_load_time; 8.123 + uint32_t count; /* can be 65536 */ 8.124 + uint16_t latched_count; 8.125 + uint8_t count_latched; 8.126 + uint8_t status_latched; 8.127 + uint8_t status; 8.128 + uint8_t read_state; 8.129 + uint8_t write_state; 8.130 + uint8_t write_latch; 8.131 + uint8_t rw_mode; 8.132 + uint8_t mode; 8.133 + uint8_t bcd; /* not supported */ 8.134 + uint8_t gate; /* timer start */ 8.135 + } channels[3]; /* 3 x 24 bytes */ 8.136 + uint32_t speaker_data_on; 8.137 +}; 8.138 + 8.139 + 8.140 + 8.141 +#endif /* __XEN_PUBLIC_HVM_SAVE_H__ */