ia64/xen-unstable
changeset 9777:5765497cf75e
Sync PIT device model with latest qemu and move it to hypervisor.
Signed-off-by: Edwin Zhai <edwin.zhai@intel.com>
Signed-off-by: Edwin Zhai <edwin.zhai@intel.com>
author | kaf24@firebug.cl.cam.ac.uk |
---|---|
date | Wed Apr 19 18:38:14 2006 +0100 (2006-04-19) |
parents | 72f9c751d3ea |
children | 123ff1c70728 |
files | tools/ioemu/hw/pc.c tools/ioemu/target-i386-dm/Makefile xen/arch/x86/hvm/Makefile xen/arch/x86/hvm/hvm.c xen/arch/x86/hvm/i8254.c xen/arch/x86/hvm/intercept.c xen/arch/x86/hvm/io.c xen/arch/x86/hvm/svm/intr.c xen/arch/x86/hvm/svm/svm.c xen/arch/x86/hvm/svm/vmcb.c xen/arch/x86/hvm/vmx/io.c xen/arch/x86/hvm/vmx/vmx.c xen/include/asm-x86/hvm/vpit.h |
line diff
1.1 --- a/tools/ioemu/hw/pc.c Wed Apr 19 18:32:20 2006 +0100 1.2 +++ b/tools/ioemu/hw/pc.c Wed Apr 19 18:38:14 2006 +0100 1.3 @@ -40,7 +40,6 @@ int speaker_data_on; 1.4 int dummy_refresh_clock; 1.5 static fdctrl_t *floppy_controller; 1.6 static RTCState *rtc_state; 1.7 -static PITState *pit; 1.8 1.9 static void ioport80_write(void *opaque, uint32_t addr, uint32_t data) 1.10 { 1.11 @@ -243,17 +242,13 @@ static void cmos_init(uint64_t ram_size, 1.12 1.13 static void speaker_ioport_write(void *opaque, uint32_t addr, uint32_t val) 1.14 { 1.15 - speaker_data_on = (val >> 1) & 1; 1.16 - pit_set_gate(pit, 2, val & 1); 1.17 + fprintf(stderr, "speaker port should not be handled in DM!\n"); 1.18 } 1.19 1.20 static uint32_t speaker_ioport_read(void *opaque, uint32_t addr) 1.21 { 1.22 - int out; 1.23 - out = pit_get_out(pit, 2, qemu_get_clock(vm_clock)); 1.24 - dummy_refresh_clock ^= 1; 1.25 - return (speaker_data_on << 1) | pit_get_gate(pit, 2) | (out << 5) | 1.26 - (dummy_refresh_clock << 4); 1.27 + fprintf(stderr, "speaker port should not be handled in DM!\n"); 1.28 + return 0; 1.29 } 1.30 1.31 static void ioport92_write(void *opaque, uint32_t addr, uint32_t val) 1.32 @@ -529,7 +524,6 @@ void pc_init(uint64_t ram_size, int vga_ 1.33 register_ioport_write(0x92, 1, 1, ioport92_write, NULL); 1.34 1.35 pic_init(); 1.36 - pit = pit_init(0x40, 0); 1.37 1.38 for(i = 0; i < MAX_SERIAL_PORTS; i++) { 1.39 if (serial_hds[i]) {
2.1 --- a/tools/ioemu/target-i386-dm/Makefile Wed Apr 19 18:32:20 2006 +0100 2.2 +++ b/tools/ioemu/target-i386-dm/Makefile Wed Apr 19 18:38:14 2006 +0100 2.3 @@ -277,7 +277,7 @@ endif 2.4 2.5 # Hardware support 2.6 VL_OBJS+= ide.o ne2000.o pckbd.o vga.o dma.o 2.7 -VL_OBJS+= fdc.o mc146818rtc.o serial.o i8259_stub.o i8254.o pc.o port-e9.o 2.8 +VL_OBJS+= fdc.o mc146818rtc.o serial.o i8259_stub.o pc.o port-e9.o 2.9 VL_OBJS+= cirrus_vga.o pcnet.o 2.10 VL_OBJS+= $(SOUND_HW) $(AUDIODRV) mixeng.o 2.11
3.1 --- a/xen/arch/x86/hvm/Makefile Wed Apr 19 18:32:20 2006 +0100 3.2 +++ b/xen/arch/x86/hvm/Makefile Wed Apr 19 18:38:14 2006 +0100 3.3 @@ -2,6 +2,7 @@ subdir-y += svm 3.4 subdir-y += vmx 3.5 3.6 obj-y += hvm.o 3.7 +obj-y += i8254.o 3.8 obj-y += i8259.o 3.9 obj-y += intercept.o 3.10 obj-y += io.o
4.1 --- a/xen/arch/x86/hvm/hvm.c Wed Apr 19 18:32:20 2006 +0100 4.2 +++ b/xen/arch/x86/hvm/hvm.c Wed Apr 19 18:38:14 2006 +0100 4.3 @@ -203,6 +203,8 @@ void hvm_setup_platform(struct domain* d 4.4 spin_lock_init(&d->arch.hvm_domain.round_robin_lock); 4.5 hvm_vioapic_init(d); 4.6 } 4.7 + 4.8 + pit_init(&platform->vpit, current); 4.9 } 4.10 4.11 void pic_irq_request(void *data, int level)
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/xen/arch/x86/hvm/i8254.c Wed Apr 19 18:38:14 2006 +0100 5.3 @@ -0,0 +1,594 @@ 5.4 +/* 5.5 + * QEMU 8253/8254 interval timer emulation 5.6 + * 5.7 + * Copyright (c) 2003-2004 Fabrice Bellard 5.8 + * Copyright (c) 2006 Intel Corperation 5.9 + * 5.10 + * Permission is hereby granted, free of charge, to any person obtaining a copy 5.11 + * of this software and associated documentation files (the "Software"), to deal 5.12 + * in the Software without restriction, including without limitation the rights 5.13 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 5.14 + * copies of the Software, and to permit persons to whom the Software is 5.15 + * furnished to do so, subject to the following conditions: 5.16 + * 5.17 + * The above copyright notice and this permission notice shall be included in 5.18 + * all copies or substantial portions of the Software. 5.19 + * 5.20 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 5.21 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 5.22 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 5.23 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 5.24 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 5.25 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 5.26 + * THE SOFTWARE. 5.27 + */ 5.28 +/* Edwin Zhai <edwin.zhai@intel.com> 5.29 + * Ported to xen: 5.30 + * use actimer for intr generation; 5.31 + * move speaker io access to hypervisor; 5.32 + * use new method for counter/intrs calculation 5.33 + */ 5.34 + 5.35 +#include <xen/config.h> 5.36 +#include <xen/types.h> 5.37 +#include <xen/mm.h> 5.38 +#include <xen/xmalloc.h> 5.39 +#include <xen/lib.h> 5.40 +#include <xen/errno.h> 5.41 +#include <xen/sched.h> 5.42 +#include <asm/hvm/hvm.h> 5.43 +#include <asm/hvm/io.h> 5.44 +#include <asm/hvm/support.h> 5.45 +#include <asm/hvm/vpit.h> 5.46 +#include <asm/current.h> 5.47 + 5.48 +/*#define DEBUG_PIT*/ 5.49 + 5.50 +#define RW_STATE_LSB 1 5.51 +#define RW_STATE_MSB 2 5.52 +#define RW_STATE_WORD0 3 5.53 +#define RW_STATE_WORD1 4 5.54 + 5.55 +#ifndef NSEC_PER_SEC 5.56 +#define NSEC_PER_SEC (1000000000ULL) 5.57 +#endif 5.58 + 5.59 +#ifndef TIMER_SLOP 5.60 +#define TIMER_SLOP (50*1000) /* ns */ 5.61 +#endif 5.62 + 5.63 +static void pit_irq_timer_update(PITChannelState *s, s64 current_time); 5.64 + 5.65 +s_time_t hvm_get_clock(void) 5.66 +{ 5.67 + /* TODO: add pause/unpause support */ 5.68 + return NOW(); 5.69 +} 5.70 + 5.71 +static int pit_get_count(PITChannelState *s) 5.72 +{ 5.73 + u64 d; 5.74 + u64 counter; 5.75 + 5.76 + d = hvm_get_clock() - s->count_load_time; 5.77 + switch(s->mode) { 5.78 + case 0: 5.79 + case 1: 5.80 + case 4: 5.81 + case 5: 5.82 + counter = (s->period - d) & 0xffff; 5.83 + break; 5.84 + case 3: 5.85 + /* XXX: may be incorrect for odd counts */ 5.86 + counter = s->period - ((2 * d) % s->period); 5.87 + break; 5.88 + default: 5.89 + /* mod 2 counter handle */ 5.90 + d = hvm_get_clock() - s->hvm_time->count_point; 5.91 + d += s->hvm_time->count_advance; 5.92 + counter = s->period - (d % s->period); 5.93 + break; 5.94 + } 5.95 + /* change from ns to pit counter */ 5.96 + counter = DIV_ROUND( (counter * PIT_FREQ), NSEC_PER_SEC); 5.97 + return counter; 5.98 +} 5.99 + 5.100 +/* get pit output bit */ 5.101 +static int pit_get_out1(PITChannelState *s, s64 current_time) 5.102 +{ 5.103 + u64 d; 5.104 + int out; 5.105 + 5.106 + d = current_time - s->count_load_time; 5.107 + switch(s->mode) { 5.108 + default: 5.109 + case 0: 5.110 + out = (d >= s->period); 5.111 + break; 5.112 + case 1: 5.113 + out = (d < s->period); 5.114 + break; 5.115 + case 2: 5.116 + /* mod2 out is no meaning, since intr are generated in background */ 5.117 + if ((d % s->period) == 0 && d != 0) 5.118 + out = 1; 5.119 + else 5.120 + out = 0; 5.121 + break; 5.122 + case 3: 5.123 + out = (d % s->period) < ((s->period + 1) >> 1); 5.124 + break; 5.125 + case 4: 5.126 + case 5: 5.127 + out = (d == s->period); 5.128 + break; 5.129 + } 5.130 + return out; 5.131 +} 5.132 + 5.133 +int pit_get_out(hvm_virpit *pit, int channel, s64 current_time) 5.134 +{ 5.135 + PITChannelState *s = &pit->channels[channel]; 5.136 + return pit_get_out1(s, current_time); 5.137 +} 5.138 + 5.139 +static __inline__ s64 missed_ticks(PITChannelState *s, s64 current_time) 5.140 +{ 5.141 + struct hvm_time_info *hvm_time = s->hvm_time; 5.142 + /* ticks from current time(expected time) to NOW */ 5.143 + int missed_ticks; 5.144 + /* current_time is expected time for next intr, check if it's true 5.145 + * (actimer has a TIMER_SLOP in advance) 5.146 + */ 5.147 + s64 missed_time = hvm_get_clock() + TIMER_SLOP - current_time; 5.148 + 5.149 + if (missed_time >= 0) { 5.150 + missed_ticks = missed_time/(s_time_t)s->period + 1; 5.151 + hvm_time->pending_intr_nr += missed_ticks; 5.152 + s->next_transition_time = current_time + (missed_ticks ) * s->period; 5.153 + } else 5.154 + printk("HVM_PIT:missed ticks < 0 \n"); 5.155 + 5.156 + return s->next_transition_time; 5.157 +} 5.158 + 5.159 +/* only rearm the actimer when return value > 0 5.160 + * -2: init state 5.161 + * -1: the mode has expired 5.162 + * 0: current VCPU is not running 5.163 + * >0: the next fired time 5.164 + */ 5.165 +s64 pit_get_next_transition_time(PITChannelState *s, 5.166 + s64 current_time) 5.167 +{ 5.168 + s64 d, next_time, base; 5.169 + int period2; 5.170 + struct hvm_time_info *hvm_time = s->hvm_time; 5.171 + 5.172 + d = current_time - s->count_load_time; 5.173 + switch(s->mode) { 5.174 + default: 5.175 + case 0: 5.176 + case 1: 5.177 + if (d < s->period) 5.178 + next_time = s->period; 5.179 + else 5.180 + return -1; 5.181 + break; 5.182 + case 2: 5.183 + if (test_bit(_VCPUF_running, &(hvm_time->vcpu->vcpu_flags)) ) 5.184 + next_time = missed_ticks(s, current_time); 5.185 + else 5.186 + return 0; 5.187 + break; 5.188 + case 3: 5.189 + base = (d / s->period) * s->period; 5.190 + period2 = ((s->period + 1) >> 1); 5.191 + if ((d - base) < period2) 5.192 + next_time = base + period2; 5.193 + else 5.194 + next_time = base + s->period; 5.195 + break; 5.196 + case 4: 5.197 + case 5: 5.198 + if (d < s->period) 5.199 + next_time = s->period; 5.200 + else if (d == s->period) 5.201 + next_time = s->period + 1; 5.202 + else 5.203 + return -1; 5.204 + break; 5.205 + case 0xff: 5.206 + return -2; /* for init state */ 5.207 + break; 5.208 + } 5.209 + /* XXX: better solution: use a clock at PIT_FREQ Hz */ 5.210 + if (next_time <= current_time){ 5.211 +#ifdef DEBUG_PIT 5.212 + printk("HVM_PIT:next_time <= current_time. next=0x%llx, current=0x%llx!\n",next_time, current_time); 5.213 +#endif 5.214 + next_time = current_time + 1; 5.215 + } 5.216 + return next_time; 5.217 +} 5.218 + 5.219 +/* val must be 0 or 1 */ 5.220 +void pit_set_gate(hvm_virpit *pit, int channel, int val) 5.221 +{ 5.222 + PITChannelState *s = &pit->channels[channel]; 5.223 + 5.224 + switch(s->mode) { 5.225 + default: 5.226 + case 0: 5.227 + case 4: 5.228 + /* XXX: just disable/enable counting */ 5.229 + break; 5.230 + case 1: 5.231 + case 5: 5.232 + if (s->gate < val) { 5.233 + /* restart counting on rising edge */ 5.234 + s->count_load_time = hvm_get_clock(); 5.235 + pit_irq_timer_update(s, s->count_load_time); 5.236 + } 5.237 + break; 5.238 + case 2: 5.239 + case 3: 5.240 + if (s->gate < val) { 5.241 + /* restart counting on rising edge */ 5.242 + s->count_load_time = hvm_get_clock(); 5.243 + pit_irq_timer_update(s, s->count_load_time); 5.244 + } 5.245 + /* XXX: disable/enable counting */ 5.246 + break; 5.247 + } 5.248 + s->gate = val; 5.249 +} 5.250 + 5.251 +int pit_get_gate(hvm_virpit *pit, int channel) 5.252 +{ 5.253 + PITChannelState *s = &pit->channels[channel]; 5.254 + return s->gate; 5.255 +} 5.256 + 5.257 +static inline void pit_load_count(PITChannelState *s, int val) 5.258 +{ 5.259 + if (val == 0) 5.260 + val = 0x10000; 5.261 + 5.262 + s->count_load_time = hvm_get_clock(); 5.263 + s->count = val; 5.264 + s->period = DIV_ROUND(((s->count) * NSEC_PER_SEC), PIT_FREQ); 5.265 + 5.266 +#ifdef DEBUG_PIT 5.267 + printk("HVM_PIT: pit-load-counter, count=0x%x,period=0x%u us,mode=%d, load_time=%lld\n", 5.268 + val, 5.269 + s->period / 1000, 5.270 + s->mode, 5.271 + s->count_load_time); 5.272 +#endif 5.273 + 5.274 + if (s->mode == HVM_PIT_ACCEL_MODE) { 5.275 + if (!s->hvm_time) { 5.276 + printk("HVM_PIT:guest should only set mod 2 on channel 0!\n"); 5.277 + return; 5.278 + } 5.279 + s->hvm_time->period_cycles = (u64)s->period * cpu_khz / 1000000L; 5.280 + s->hvm_time->first_injected = 0; 5.281 + 5.282 + if (s->period < 900000) { /* < 0.9 ms */ 5.283 + printk("HVM_PIT: guest programmed too small an count: %x\n", 5.284 + s->count); 5.285 + s->period = 1000000; 5.286 + } 5.287 + } 5.288 + 5.289 + pit_irq_timer_update(s, s->count_load_time); 5.290 +} 5.291 + 5.292 +/* if already latched, do not latch again */ 5.293 +static void pit_latch_count(PITChannelState *s) 5.294 +{ 5.295 + if (!s->count_latched) { 5.296 + s->latched_count = pit_get_count(s); 5.297 + s->count_latched = s->rw_mode; 5.298 + } 5.299 +} 5.300 + 5.301 +static void pit_ioport_write(void *opaque, u32 addr, u32 val) 5.302 +{ 5.303 + hvm_virpit *pit = opaque; 5.304 + int channel, access; 5.305 + PITChannelState *s; 5.306 + val &= 0xff; 5.307 + 5.308 + addr &= 3; 5.309 + if (addr == 3) { 5.310 + channel = val >> 6; 5.311 + if (channel == 3) { 5.312 + /* read back command */ 5.313 + for(channel = 0; channel < 3; channel++) { 5.314 + s = &pit->channels[channel]; 5.315 + if (val & (2 << channel)) { 5.316 + if (!(val & 0x20)) { 5.317 + pit_latch_count(s); 5.318 + } 5.319 + if (!(val & 0x10) && !s->status_latched) { 5.320 + /* status latch */ 5.321 + /* XXX: add BCD and null count */ 5.322 + s->status = (pit_get_out1(s, hvm_get_clock()) << 7) | 5.323 + (s->rw_mode << 4) | 5.324 + (s->mode << 1) | 5.325 + s->bcd; 5.326 + s->status_latched = 1; 5.327 + } 5.328 + } 5.329 + } 5.330 + } else { 5.331 + s = &pit->channels[channel]; 5.332 + access = (val >> 4) & 3; 5.333 + if (access == 0) { 5.334 + pit_latch_count(s); 5.335 + } else { 5.336 + s->rw_mode = access; 5.337 + s->read_state = access; 5.338 + s->write_state = access; 5.339 + 5.340 + s->mode = (val >> 1) & 7; 5.341 + s->bcd = val & 1; 5.342 + /* XXX: update irq timer ? */ 5.343 + } 5.344 + } 5.345 + } else { 5.346 + s = &pit->channels[addr]; 5.347 + switch(s->write_state) { 5.348 + default: 5.349 + case RW_STATE_LSB: 5.350 + pit_load_count(s, val); 5.351 + break; 5.352 + case RW_STATE_MSB: 5.353 + pit_load_count(s, val << 8); 5.354 + break; 5.355 + case RW_STATE_WORD0: 5.356 + s->write_latch = val; 5.357 + s->write_state = RW_STATE_WORD1; 5.358 + break; 5.359 + case RW_STATE_WORD1: 5.360 + pit_load_count(s, s->write_latch | (val << 8)); 5.361 + s->write_state = RW_STATE_WORD0; 5.362 + break; 5.363 + } 5.364 + } 5.365 +} 5.366 + 5.367 +static u32 pit_ioport_read(void *opaque, u32 addr) 5.368 +{ 5.369 + hvm_virpit *pit = opaque; 5.370 + int ret, count; 5.371 + PITChannelState *s; 5.372 + 5.373 + addr &= 3; 5.374 + s = &pit->channels[addr]; 5.375 + if (s->status_latched) { 5.376 + s->status_latched = 0; 5.377 + ret = s->status; 5.378 + } else if (s->count_latched) { 5.379 + switch(s->count_latched) { 5.380 + default: 5.381 + case RW_STATE_LSB: 5.382 + ret = s->latched_count & 0xff; 5.383 + s->count_latched = 0; 5.384 + break; 5.385 + case RW_STATE_MSB: 5.386 + ret = s->latched_count >> 8; 5.387 + s->count_latched = 0; 5.388 + break; 5.389 + case RW_STATE_WORD0: 5.390 + ret = s->latched_count & 0xff; 5.391 + s->count_latched = RW_STATE_MSB; 5.392 + break; 5.393 + } 5.394 + } else { 5.395 + switch(s->read_state) { 5.396 + default: 5.397 + case RW_STATE_LSB: 5.398 + count = pit_get_count(s); 5.399 + ret = count & 0xff; 5.400 + break; 5.401 + case RW_STATE_MSB: 5.402 + count = pit_get_count(s); 5.403 + ret = (count >> 8) & 0xff; 5.404 + break; 5.405 + case RW_STATE_WORD0: 5.406 + count = pit_get_count(s); 5.407 + ret = count & 0xff; 5.408 + s->read_state = RW_STATE_WORD1; 5.409 + break; 5.410 + case RW_STATE_WORD1: 5.411 + count = pit_get_count(s); 5.412 + ret = (count >> 8) & 0xff; 5.413 + s->read_state = RW_STATE_WORD0; 5.414 + break; 5.415 + } 5.416 + } 5.417 + return ret; 5.418 +} 5.419 + 5.420 +static void pit_irq_timer_update(PITChannelState *s, s64 current_time) 5.421 +{ 5.422 + s64 expire_time; 5.423 + int irq_level; 5.424 + struct vcpu *v = current; 5.425 + struct hvm_virpic *pic= &v->domain->arch.hvm_domain.vpic; 5.426 + 5.427 + if (!s->hvm_time || s->mode == 0xff) 5.428 + return; 5.429 + 5.430 + expire_time = pit_get_next_transition_time(s, current_time); 5.431 + /* not generate intr by direct pic_set_irq in mod 2 5.432 + * XXX:mod 3 should be same as mod 2 5.433 + */ 5.434 + if (s->mode != HVM_PIT_ACCEL_MODE) { 5.435 + irq_level = pit_get_out1(s, current_time); 5.436 + pic_set_irq(pic, s->irq, irq_level); 5.437 + s->next_transition_time = expire_time; 5.438 +#ifdef DEBUG_PIT 5.439 + printk("HVM_PIT:irq_level=%d next_delay=%l ns\n", 5.440 + irq_level, 5.441 + (expire_time - current_time)); 5.442 +#endif 5.443 + } 5.444 + 5.445 + if (expire_time > 0) 5.446 + set_timer(&(s->hvm_time->pit_timer), s->next_transition_time); 5.447 + 5.448 +} 5.449 + 5.450 +static void pit_irq_timer(void *data) 5.451 +{ 5.452 + PITChannelState *s = data; 5.453 + 5.454 + pit_irq_timer_update(s, s->next_transition_time); 5.455 +} 5.456 + 5.457 +static void pit_reset(void *opaque) 5.458 +{ 5.459 + hvm_virpit *pit = opaque; 5.460 + PITChannelState *s; 5.461 + int i; 5.462 + 5.463 + for(i = 0;i < 3; i++) { 5.464 + s = &pit->channels[i]; 5.465 + s->mode = 0xff; /* the init mode */ 5.466 + s->gate = (i != 2); 5.467 + pit_load_count(s, 0); 5.468 + } 5.469 +} 5.470 + 5.471 +/* hvm_io_assist light-weight version, specific to PIT DM */ 5.472 +static void resume_pit_io(ioreq_t *p) 5.473 +{ 5.474 + struct cpu_user_regs *regs = guest_cpu_user_regs(); 5.475 + unsigned long old_eax = regs->eax; 5.476 + p->state = STATE_INVALID; 5.477 + 5.478 + switch(p->size) { 5.479 + case 1: 5.480 + regs->eax = (old_eax & 0xffffff00) | (p->u.data & 0xff); 5.481 + break; 5.482 + case 2: 5.483 + regs->eax = (old_eax & 0xffff0000) | (p->u.data & 0xffff); 5.484 + break; 5.485 + case 4: 5.486 + regs->eax = (p->u.data & 0xffffffff); 5.487 + break; 5.488 + default: 5.489 + BUG(); 5.490 + } 5.491 +} 5.492 + 5.493 +/* the intercept action for PIT DM retval:0--not handled; 1--handled */ 5.494 +int handle_pit_io(ioreq_t *p) 5.495 +{ 5.496 + struct vcpu *v = current; 5.497 + struct hvm_virpit *vpit = &(v->domain->arch.hvm_domain.vpit); 5.498 + 5.499 + if (p->size != 1 || 5.500 + p->pdata_valid || 5.501 + p->type != IOREQ_TYPE_PIO){ 5.502 + printk("HVM_PIT:wrong PIT IO!\n"); 5.503 + return 1; 5.504 + } 5.505 + 5.506 + if (p->dir == 0) {/* write */ 5.507 + pit_ioport_write(vpit, p->addr, p->u.data); 5.508 + } else if (p->dir == 1) { /* read */ 5.509 + p->u.data = pit_ioport_read(vpit, p->addr); 5.510 + resume_pit_io(p); 5.511 + } 5.512 + 5.513 + /* always return 1, since PIT sit in HV now */ 5.514 + return 1; 5.515 +} 5.516 + 5.517 +static void speaker_ioport_write(void *opaque, uint32_t addr, uint32_t val) 5.518 +{ 5.519 + hvm_virpit *pit = opaque; 5.520 + val &= 0xff; 5.521 + pit->speaker_data_on = (val >> 1) & 1; 5.522 + pit_set_gate(pit, 2, val & 1); 5.523 +} 5.524 + 5.525 +static uint32_t speaker_ioport_read(void *opaque, uint32_t addr) 5.526 +{ 5.527 + int out; 5.528 + hvm_virpit *pit = opaque; 5.529 + out = pit_get_out(pit, 2, hvm_get_clock()); 5.530 + pit->dummy_refresh_clock ^= 1; 5.531 + 5.532 + return (pit->speaker_data_on << 1) | pit_get_gate(pit, 2) | (out << 5) | 5.533 + (pit->dummy_refresh_clock << 4); 5.534 +} 5.535 + 5.536 +int handle_speaker_io(ioreq_t *p) 5.537 +{ 5.538 + struct vcpu *v = current; 5.539 + struct hvm_virpit *vpit = &(v->domain->arch.hvm_domain.vpit); 5.540 + 5.541 + if (p->size != 1 || 5.542 + p->pdata_valid || 5.543 + p->type != IOREQ_TYPE_PIO){ 5.544 + printk("HVM_SPEAKER:wrong SPEAKER IO!\n"); 5.545 + return 1; 5.546 + } 5.547 + 5.548 + if (p->dir == 0) {/* write */ 5.549 + speaker_ioport_write(vpit, p->addr, p->u.data); 5.550 + } else if (p->dir == 1) {/* read */ 5.551 + p->u.data = speaker_ioport_read(vpit, p->addr); 5.552 + resume_pit_io(p); 5.553 + } 5.554 + 5.555 + return 1; 5.556 +} 5.557 + 5.558 +/* pick up missed timer ticks at deactive time */ 5.559 +void pickup_deactive_ticks(struct hvm_virpit *vpit) 5.560 +{ 5.561 + s64 next_time; 5.562 + PITChannelState *s = &(vpit->channels[0]); 5.563 + if ( !active_timer(&(vpit->time_info.pit_timer)) ) { 5.564 + next_time = pit_get_next_transition_time(s, s->next_transition_time); 5.565 + if (next_time > 0) 5.566 + set_timer(&(s->hvm_time->pit_timer), s->next_transition_time); 5.567 + else { 5.568 + printk("HVM_PIT:not set_timer before resume next_time=%lld!\n", next_time); 5.569 + next_time = s->next_transition_time; 5.570 + } 5.571 + } 5.572 +} 5.573 + 5.574 +void pit_init(struct hvm_virpit *pit, struct vcpu *v) 5.575 +{ 5.576 + PITChannelState *s; 5.577 + struct hvm_time_info *hvm_time; 5.578 + 5.579 + s = &pit->channels[0]; 5.580 + /* the timer 0 is connected to an IRQ */ 5.581 + s->irq = 0; 5.582 + /* channel 0 need access the related time info for intr injection */ 5.583 + hvm_time = s->hvm_time = &pit->time_info; 5.584 + hvm_time->vcpu = v; 5.585 + 5.586 + init_timer(&(hvm_time->pit_timer), pit_irq_timer, s, v->processor); 5.587 + 5.588 + register_portio_handler(PIT_BASE, 4, handle_pit_io); 5.589 + 5.590 + /* register the speaker port */ 5.591 + register_portio_handler(0x61, 1, handle_speaker_io); 5.592 + 5.593 + pit_reset(pit); 5.594 + 5.595 + return; 5.596 + 5.597 +}
6.1 --- a/xen/arch/x86/hvm/intercept.c Wed Apr 19 18:32:20 2006 +0100 6.2 +++ b/xen/arch/x86/hvm/intercept.c Wed Apr 19 18:38:14 2006 +0100 6.3 @@ -206,139 +206,6 @@ int register_io_handler(unsigned long ad 6.4 return 1; 6.5 } 6.6 6.7 -static void pit_cal_count(struct hvm_virpit *vpit) 6.8 -{ 6.9 - u64 nsec_delta = (unsigned int)((NOW() - vpit->count_point)); 6.10 - 6.11 - nsec_delta += vpit->count_advance; 6.12 - if (nsec_delta > vpit->period) 6.13 - HVM_DBG_LOG(DBG_LEVEL_1, 6.14 - "HVM_PIT: long time has passed from last injection!"); 6.15 - 6.16 - if(vpit->init_val == 0) 6.17 - { 6.18 - printk("PIT init value == 0!\n"); 6.19 - domain_crash_synchronous(); 6.20 - } 6.21 - 6.22 - vpit->count = vpit->init_val 6.23 - - ((nsec_delta * PIT_FREQ / 1000000000ULL) % vpit->init_val); 6.24 -} 6.25 - 6.26 -static void pit_latch_io(struct hvm_virpit *vpit) 6.27 -{ 6.28 - pit_cal_count(vpit); 6.29 - 6.30 - switch(vpit->read_state) { 6.31 - case MSByte: 6.32 - vpit->count_MSB_latched=1; 6.33 - break; 6.34 - case LSByte: 6.35 - vpit->count_LSB_latched=1; 6.36 - break; 6.37 - case LSByte_multiple: 6.38 - vpit->count_LSB_latched=1; 6.39 - vpit->count_MSB_latched=1; 6.40 - break; 6.41 - case MSByte_multiple: 6.42 - HVM_DBG_LOG(DBG_LEVEL_1, 6.43 - "HVM_PIT: latch PIT counter before MSB_multiple!"); 6.44 - vpit->read_state=LSByte_multiple; 6.45 - vpit->count_LSB_latched=1; 6.46 - vpit->count_MSB_latched=1; 6.47 - break; 6.48 - default: 6.49 - domain_crash_synchronous(); 6.50 - } 6.51 -} 6.52 - 6.53 -static int pit_read_io(struct hvm_virpit *vpit) 6.54 -{ 6.55 - if(vpit->count_LSB_latched) { 6.56 - /* Read Least Significant Byte */ 6.57 - if(vpit->read_state==LSByte_multiple) { 6.58 - vpit->read_state=MSByte_multiple; 6.59 - } 6.60 - vpit->count_LSB_latched=0; 6.61 - return (vpit->count & 0xFF); 6.62 - } else if(vpit->count_MSB_latched) { 6.63 - /* Read Most Significant Byte */ 6.64 - if(vpit->read_state==MSByte_multiple) { 6.65 - vpit->read_state=LSByte_multiple; 6.66 - } 6.67 - vpit->count_MSB_latched=0; 6.68 - return ((vpit->count>>8) & 0xFF); 6.69 - } else { 6.70 - /* Unlatched Count Read */ 6.71 - HVM_DBG_LOG(DBG_LEVEL_1, "HVM_PIT: unlatched read"); 6.72 - pit_cal_count(vpit); 6.73 - if(!(vpit->read_state & 0x1)) { 6.74 - /* Read Least Significant Byte */ 6.75 - if(vpit->read_state==LSByte_multiple) { 6.76 - vpit->read_state=MSByte_multiple; 6.77 - } 6.78 - return (vpit->count & 0xFF); 6.79 - } else { 6.80 - /* Read Most Significant Byte */ 6.81 - if(vpit->read_state==MSByte_multiple) { 6.82 - vpit->read_state=LSByte_multiple; 6.83 - } 6.84 - return ((vpit->count>>8) & 0xFF); 6.85 - } 6.86 - } 6.87 -} 6.88 - 6.89 -/* hvm_io_assist light-weight version, specific to PIT DM */ 6.90 -static void resume_pit_io(ioreq_t *p) 6.91 -{ 6.92 - struct cpu_user_regs *regs = guest_cpu_user_regs(); 6.93 - unsigned long old_eax = regs->eax; 6.94 - p->state = STATE_INVALID; 6.95 - 6.96 - switch(p->size) { 6.97 - case 1: 6.98 - regs->eax = (old_eax & 0xffffff00) | (p->u.data & 0xff); 6.99 - break; 6.100 - case 2: 6.101 - regs->eax = (old_eax & 0xffff0000) | (p->u.data & 0xffff); 6.102 - break; 6.103 - case 4: 6.104 - regs->eax = (p->u.data & 0xffffffff); 6.105 - break; 6.106 - default: 6.107 - BUG(); 6.108 - } 6.109 -} 6.110 - 6.111 -/* the intercept action for PIT DM retval:0--not handled; 1--handled */ 6.112 -int intercept_pit_io(ioreq_t *p) 6.113 -{ 6.114 - struct vcpu *v = current; 6.115 - struct hvm_virpit *vpit = &(v->domain->arch.hvm_domain.vpit); 6.116 - 6.117 - if (p->size != 1 || 6.118 - p->pdata_valid || 6.119 - p->type != IOREQ_TYPE_PIO) 6.120 - return 0; 6.121 - 6.122 - if (p->addr == PIT_MODE && 6.123 - p->dir == 0 && /* write */ 6.124 - ((p->u.data >> 4) & 0x3) == 0 && /* latch command */ 6.125 - ((p->u.data >> 6) & 0x3) == (vpit->channel)) {/* right channel */ 6.126 - pit_latch_io(vpit); 6.127 - return 1; 6.128 - } 6.129 - 6.130 - if (p->addr == (PIT_CH0 + vpit->channel) && 6.131 - p->dir == 1) { /* read */ 6.132 - p->u.data = pit_read_io(vpit); 6.133 - resume_pit_io(p); 6.134 - return 1; 6.135 - } 6.136 - 6.137 - return 0; 6.138 -} 6.139 - 6.140 /* hooks function for the HLT instruction emulation wakeup */ 6.141 void hlt_timer_fn(void *data) 6.142 { 6.143 @@ -347,109 +214,6 @@ void hlt_timer_fn(void *data) 6.144 evtchn_set_pending(v, iopacket_port(v)); 6.145 } 6.146 6.147 -static __inline__ void missed_ticks(struct hvm_virpit*vpit) 6.148 -{ 6.149 - int missed_ticks; 6.150 - 6.151 - missed_ticks = (NOW() - vpit->scheduled)/(s_time_t) vpit->period; 6.152 - if ( missed_ticks++ >= 0 ) { 6.153 - vpit->pending_intr_nr += missed_ticks; 6.154 - vpit->scheduled += missed_ticks * vpit->period; 6.155 - } 6.156 -} 6.157 - 6.158 -/* hooks function for the PIT when the guest is active */ 6.159 -static void pit_timer_fn(void *data) 6.160 -{ 6.161 - struct vcpu *v = data; 6.162 - struct hvm_virpit *vpit = &(v->domain->arch.hvm_domain.vpit); 6.163 - 6.164 - /* pick up missed timer tick */ 6.165 - missed_ticks(vpit); 6.166 - if ( test_bit(_VCPUF_running, &v->vcpu_flags) ) { 6.167 - set_timer(&vpit->pit_timer, vpit->scheduled); 6.168 - } 6.169 -} 6.170 - 6.171 -/* pick up missed timer ticks at deactive time */ 6.172 -void pickup_deactive_ticks(struct hvm_virpit *vpit) 6.173 -{ 6.174 - if ( !active_timer(&(vpit->pit_timer)) ) { 6.175 - missed_ticks(vpit); 6.176 - set_timer(&vpit->pit_timer, vpit->scheduled); 6.177 - } 6.178 -} 6.179 - 6.180 -/* Only some PIT operations such as load init counter need a hypervisor hook. 6.181 - * leave all other operations in user space DM 6.182 - */ 6.183 -void hvm_hooks_assist(struct vcpu *v) 6.184 -{ 6.185 - vcpu_iodata_t *vio = get_vio(v->domain, v->vcpu_id); 6.186 - ioreq_t *p = &vio->vp_ioreq; 6.187 - struct hvm_virpit *vpit = &(v->domain->arch.hvm_domain.vpit); 6.188 - int rw_mode, reinit = 0; 6.189 - 6.190 - /* load init count*/ 6.191 - if (p->state == STATE_IORESP_HOOK) { 6.192 - /* set up actimer, handle re-init */ 6.193 - if ( active_timer(&(vpit->pit_timer)) ) { 6.194 - HVM_DBG_LOG(DBG_LEVEL_1, "HVM_PIT: guest reset PIT with channel %lx!\n", (unsigned long) ((p->u.data >> 24) & 0x3) ); 6.195 - stop_timer(&(vpit->pit_timer)); 6.196 - reinit = 1; 6.197 - 6.198 - } 6.199 - else { 6.200 - init_timer(&vpit->pit_timer, pit_timer_fn, v, v->processor); 6.201 - } 6.202 - 6.203 - /* init count for this channel */ 6.204 - vpit->init_val = (p->u.data & 0xFFFF) ; 6.205 - /* frequency(ns) of pit */ 6.206 - vpit->period = DIV_ROUND(((vpit->init_val) * 1000000000ULL), PIT_FREQ); 6.207 - HVM_DBG_LOG(DBG_LEVEL_1,"HVM_PIT: guest set init pit freq:%u ns, initval:0x%x\n", vpit->period, vpit->init_val); 6.208 - if (vpit->period < 900000) { /* < 0.9 ms */ 6.209 - printk("HVM_PIT: guest programmed too small an init_val: %x\n", 6.210 - vpit->init_val); 6.211 - vpit->period = 1000000; 6.212 - } 6.213 - vpit->period_cycles = (u64)vpit->period * cpu_khz / 1000000L; 6.214 - printk("HVM_PIT: guest freq in cycles=%lld\n",(long long)vpit->period_cycles); 6.215 - 6.216 - vpit->channel = ((p->u.data >> 24) & 0x3); 6.217 - vpit->first_injected = 0; 6.218 - 6.219 - vpit->count_LSB_latched = 0; 6.220 - vpit->count_MSB_latched = 0; 6.221 - 6.222 - rw_mode = ((p->u.data >> 26) & 0x3); 6.223 - switch(rw_mode) { 6.224 - case 0x1: 6.225 - vpit->read_state=LSByte; 6.226 - break; 6.227 - case 0x2: 6.228 - vpit->read_state=MSByte; 6.229 - break; 6.230 - case 0x3: 6.231 - vpit->read_state=LSByte_multiple; 6.232 - break; 6.233 - default: 6.234 - printk("HVM_PIT:wrong PIT rw_mode!\n"); 6.235 - break; 6.236 - } 6.237 - 6.238 - vpit->scheduled = NOW() + vpit->period; 6.239 - set_timer(&vpit->pit_timer, vpit->scheduled); 6.240 - 6.241 - /*restore the state*/ 6.242 - p->state = STATE_IORESP_READY; 6.243 - 6.244 - /* register handler to intercept the PIT io when vm_exit */ 6.245 - if (!reinit) { 6.246 - register_portio_handler(0x40, 4, intercept_pit_io); 6.247 - } 6.248 - } 6.249 -} 6.250 6.251 /* 6.252 * Local variables:
7.1 --- a/xen/arch/x86/hvm/io.c Wed Apr 19 18:32:20 2006 +0100 7.2 +++ b/xen/arch/x86/hvm/io.c Wed Apr 19 18:38:14 2006 +0100 7.3 @@ -674,8 +674,6 @@ void hvm_io_assist(struct vcpu *v) 7.4 } 7.5 7.6 p = &vio->vp_ioreq; 7.7 - if (p->state == STATE_IORESP_HOOK) 7.8 - hvm_hooks_assist(v); 7.9 7.10 /* clear IO wait HVM flag */ 7.11 if (test_bit(ARCH_HVM_IO_WAIT, &v->arch.hvm_vcpu.ioflags)) {
8.1 --- a/xen/arch/x86/hvm/svm/intr.c Wed Apr 19 18:32:20 2006 +0100 8.2 +++ b/xen/arch/x86/hvm/svm/intr.c Wed Apr 19 18:38:14 2006 +0100 8.3 @@ -46,44 +46,43 @@ 8.4 8.5 u64 svm_get_guest_time(struct vcpu *v) 8.6 { 8.7 - struct hvm_virpit *vpit = &(v->domain->arch.hvm_domain.vpit); 8.8 + struct hvm_time_info *time_info = &(v->domain->arch.hvm_domain.vpit.time_info); 8.9 u64 host_tsc; 8.10 8.11 rdtscll(host_tsc); 8.12 - return host_tsc + vpit->cache_tsc_offset; 8.13 + return host_tsc + time_info->cache_tsc_offset; 8.14 } 8.15 8.16 void svm_set_guest_time(struct vcpu *v, u64 gtime) 8.17 { 8.18 - struct hvm_virpit *vpit = &(v->domain->arch.hvm_domain.vpit); 8.19 + struct hvm_time_info *time_info = &(v->domain->arch.hvm_domain.vpit.time_info); 8.20 u64 host_tsc; 8.21 8.22 rdtscll(host_tsc); 8.23 8.24 - vpit->cache_tsc_offset = gtime - host_tsc; 8.25 - v->arch.hvm_svm.vmcb->tsc_offset = vpit->cache_tsc_offset; 8.26 + time_info->cache_tsc_offset = gtime - host_tsc; 8.27 + v->arch.hvm_svm.vmcb->tsc_offset = time_info->cache_tsc_offset; 8.28 } 8.29 8.30 static inline void 8.31 interrupt_post_injection(struct vcpu * v, int vector, int type) 8.32 { 8.33 struct hvm_virpit *vpit = &(v->domain->arch.hvm_domain.vpit); 8.34 + struct hvm_time_info *time_info = &vpit->time_info; 8.35 8.36 if ( is_pit_irq(v, vector, type) ) { 8.37 - if ( !vpit->first_injected ) { 8.38 - vpit->pending_intr_nr = 0; 8.39 - vpit->last_pit_gtime = svm_get_guest_time(v); 8.40 - vpit->scheduled = NOW() + vpit->period; 8.41 - set_timer(&vpit->pit_timer, vpit->scheduled); 8.42 - vpit->first_injected = 1; 8.43 + if ( !time_info->first_injected ) { 8.44 + time_info->pending_intr_nr = 0; 8.45 + time_info->last_pit_gtime = svm_get_guest_time(v); 8.46 + time_info->first_injected = 1; 8.47 } else { 8.48 - vpit->pending_intr_nr--; 8.49 + time_info->pending_intr_nr--; 8.50 } 8.51 - vpit->count_advance = 0; 8.52 - vpit->count_point = NOW(); 8.53 + time_info->count_advance = 0; 8.54 + time_info->count_point = NOW(); 8.55 8.56 - vpit->last_pit_gtime += vpit->period_cycles; 8.57 - svm_set_guest_time(v, vpit->last_pit_gtime); 8.58 + time_info->last_pit_gtime += time_info->period_cycles; 8.59 + svm_set_guest_time(v, time_info->last_pit_gtime); 8.60 } 8.61 8.62 switch(type) 8.63 @@ -123,6 +122,7 @@ asmlinkage void svm_intr_assist(void) 8.64 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; 8.65 struct hvm_domain *plat=&v->domain->arch.hvm_domain; 8.66 struct hvm_virpit *vpit = &plat->vpit; 8.67 + struct hvm_time_info *time_info = &vpit->time_info; 8.68 struct hvm_virpic *pic= &plat->vpic; 8.69 int intr_type = VLAPIC_DELIV_MODE_EXT; 8.70 int intr_vector = -1; 8.71 @@ -185,7 +185,7 @@ asmlinkage void svm_intr_assist(void) 8.72 if ( cpu_has_pending_irq(v) ) { 8.73 intr_vector = cpu_get_interrupt(v, &intr_type); 8.74 } 8.75 - else if ( (v->vcpu_id == 0) && vpit->pending_intr_nr ) { 8.76 + else if ( (v->vcpu_id == 0) && time_info->pending_intr_nr ) { 8.77 pic_set_irq(pic, 0, 0); 8.78 pic_set_irq(pic, 0, 1); 8.79 intr_vector = cpu_get_interrupt(v, &intr_type); 8.80 @@ -201,7 +201,7 @@ asmlinkage void svm_intr_assist(void) 8.81 /* Re-injecting a PIT interruptt? */ 8.82 if (re_injecting && 8.83 is_pit_irq(v, intr_vector, intr_type)) { 8.84 - ++vpit->pending_intr_nr; 8.85 + ++time_info->pending_intr_nr; 8.86 } 8.87 /* let's inject this interrupt */ 8.88 TRACE_3D(TRC_VMX_INT, v->domain->domain_id, intr_vector, 0);
9.1 --- a/xen/arch/x86/hvm/svm/svm.c Wed Apr 19 18:32:20 2006 +0100 9.2 +++ b/xen/arch/x86/hvm/svm/svm.c Wed Apr 19 18:38:14 2006 +0100 9.3 @@ -675,12 +675,12 @@ static void arch_svm_do_launch(struct vc 9.4 9.5 static void svm_freeze_time(struct vcpu *v) 9.6 { 9.7 - struct hvm_virpit *vpit = &v->domain->arch.hvm_domain.vpit; 9.8 + struct hvm_time_info *time_info = &v->domain->arch.hvm_domain.vpit.time_info; 9.9 9.10 - if ( vpit->first_injected && !v->domain->arch.hvm_domain.guest_time ) { 9.11 + if ( time_info->first_injected && !v->domain->arch.hvm_domain.guest_time ) { 9.12 v->domain->arch.hvm_domain.guest_time = svm_get_guest_time(v); 9.13 - vpit->count_advance += (NOW() - vpit->count_point); 9.14 - stop_timer(&(vpit->pit_timer)); 9.15 + time_info->count_advance += (NOW() - time_info->count_point); 9.16 + stop_timer(&(time_info->pit_timer)); 9.17 } 9.18 } 9.19 9.20 @@ -750,7 +750,7 @@ static void svm_relinquish_guest_resourc 9.21 } 9.22 } 9.23 9.24 - kill_timer(&d->arch.hvm_domain.vpit.pit_timer); 9.25 + kill_timer(&d->arch.hvm_domain.vpit.time_info.pit_timer); 9.26 9.27 if ( d->arch.hvm_domain.shared_page_va ) 9.28 unmap_domain_page_global( 9.29 @@ -780,10 +780,10 @@ void arch_svm_do_resume(struct vcpu *v) 9.30 9.31 void svm_migrate_timers(struct vcpu *v) 9.32 { 9.33 - struct hvm_virpit *vpit = &(v->domain->arch.hvm_domain.vpit); 9.34 - 9.35 - migrate_timer( &vpit->pit_timer, v->processor ); 9.36 - migrate_timer( &v->arch.hvm_svm.hlt_timer, v->processor ); 9.37 + struct hvm_time_info *time_info = &v->domain->arch.hvm_domain.vpit.time_info; 9.38 + 9.39 + migrate_timer(&time_info->pit_timer, v->processor); 9.40 + migrate_timer(&v->arch.hvm_svm.hlt_timer, v->processor); 9.41 if ( hvm_apic_support(v->domain) && VLAPIC( v )) 9.42 migrate_timer( &(VLAPIC(v)->vlapic_timer ), v->processor ); 9.43 } 9.44 @@ -1843,11 +1843,11 @@ static inline void svm_do_msr_access(str 9.45 switch (regs->ecx) { 9.46 case MSR_IA32_TIME_STAMP_COUNTER: 9.47 { 9.48 - struct hvm_virpit *vpit; 9.49 + struct hvm_time_info *time_info; 9.50 9.51 rdtscll(msr_content); 9.52 - vpit = &(v->domain->arch.hvm_domain.vpit); 9.53 - msr_content += vpit->cache_tsc_offset; 9.54 + time_info = &v->domain->arch.hvm_domain.vpit.time_info; 9.55 + msr_content += time_info->cache_tsc_offset; 9.56 break; 9.57 } 9.58 case MSR_IA32_SYSENTER_CS:
10.1 --- a/xen/arch/x86/hvm/svm/vmcb.c Wed Apr 19 18:32:20 2006 +0100 10.2 +++ b/xen/arch/x86/hvm/svm/vmcb.c Wed Apr 19 18:38:14 2006 +0100 10.3 @@ -478,14 +478,15 @@ void svm_do_resume(struct vcpu *v) 10.4 { 10.5 struct domain *d = v->domain; 10.6 struct hvm_virpit *vpit = &d->arch.hvm_domain.vpit; 10.7 + struct hvm_time_info *time_info = &vpit->time_info; 10.8 10.9 svm_stts(v); 10.10 10.11 /* pick up the elapsed PIT ticks and re-enable pit_timer */ 10.12 - if ( vpit->first_injected ) { 10.13 + if ( time_info->first_injected ) { 10.14 if ( v->domain->arch.hvm_domain.guest_time ) { 10.15 svm_set_guest_time(v, v->domain->arch.hvm_domain.guest_time); 10.16 - vpit->count_point = NOW(); 10.17 + time_info->count_point = NOW(); 10.18 v->domain->arch.hvm_domain.guest_time = 0; 10.19 } 10.20 pickup_deactive_ticks(vpit);
11.1 --- a/xen/arch/x86/hvm/vmx/io.c Wed Apr 19 18:32:20 2006 +0100 11.2 +++ b/xen/arch/x86/hvm/vmx/io.c Wed Apr 19 18:38:14 2006 +0100 11.3 @@ -51,44 +51,43 @@ void __set_tsc_offset(u64 offset) 11.4 11.5 u64 get_guest_time(struct vcpu *v) 11.6 { 11.7 - struct hvm_virpit *vpit = &(v->domain->arch.hvm_domain.vpit); 11.8 + struct hvm_time_info *time_info = &(v->domain->arch.hvm_domain.vpit.time_info); 11.9 u64 host_tsc; 11.10 11.11 rdtscll(host_tsc); 11.12 - return host_tsc + vpit->cache_tsc_offset; 11.13 + return host_tsc + time_info->cache_tsc_offset; 11.14 } 11.15 11.16 void set_guest_time(struct vcpu *v, u64 gtime) 11.17 { 11.18 - struct hvm_virpit *vpit = &(v->domain->arch.hvm_domain.vpit); 11.19 + struct hvm_time_info *time_info = &(v->domain->arch.hvm_domain.vpit.time_info); 11.20 u64 host_tsc; 11.21 11.22 rdtscll(host_tsc); 11.23 11.24 - vpit->cache_tsc_offset = gtime - host_tsc; 11.25 - __set_tsc_offset(vpit->cache_tsc_offset); 11.26 + time_info->cache_tsc_offset = gtime - host_tsc; 11.27 + __set_tsc_offset(time_info->cache_tsc_offset); 11.28 } 11.29 11.30 static inline void 11.31 interrupt_post_injection(struct vcpu * v, int vector, int type) 11.32 { 11.33 struct hvm_virpit *vpit = &(v->domain->arch.hvm_domain.vpit); 11.34 + struct hvm_time_info *time_info = &vpit->time_info; 11.35 11.36 if ( is_pit_irq(v, vector, type) ) { 11.37 - if ( !vpit->first_injected ) { 11.38 - vpit->pending_intr_nr = 0; 11.39 - vpit->last_pit_gtime = get_guest_time(v); 11.40 - vpit->scheduled = NOW() + vpit->period; 11.41 - set_timer(&vpit->pit_timer, vpit->scheduled); 11.42 - vpit->first_injected = 1; 11.43 + if ( !time_info->first_injected ) { 11.44 + time_info->pending_intr_nr = 0; 11.45 + time_info->last_pit_gtime = get_guest_time(v); 11.46 + time_info->first_injected = 1; 11.47 } else { 11.48 - vpit->pending_intr_nr--; 11.49 + time_info->pending_intr_nr--; 11.50 } 11.51 - vpit->count_advance = 0; 11.52 - vpit->count_point = NOW(); 11.53 + time_info->count_advance = 0; 11.54 + time_info->count_point = NOW(); 11.55 11.56 - vpit->last_pit_gtime += vpit->period_cycles; 11.57 - set_guest_time(v, vpit->last_pit_gtime); 11.58 + time_info->last_pit_gtime += time_info->period_cycles; 11.59 + set_guest_time(v, time_info->last_pit_gtime); 11.60 } 11.61 11.62 switch(type) 11.63 @@ -152,13 +151,13 @@ asmlinkage void vmx_intr_assist(void) 11.64 unsigned long eflags; 11.65 struct vcpu *v = current; 11.66 struct hvm_domain *plat=&v->domain->arch.hvm_domain; 11.67 - struct hvm_virpit *vpit = &plat->vpit; 11.68 + struct hvm_time_info *time_info = &plat->vpit.time_info; 11.69 struct hvm_virpic *pic= &plat->vpic; 11.70 11.71 if ( v->vcpu_id == 0 ) 11.72 hvm_pic_assist(v); 11.73 11.74 - if ( (v->vcpu_id == 0) && vpit->pending_intr_nr ) { 11.75 + if ( (v->vcpu_id == 0) && time_info->pending_intr_nr ) { 11.76 pic_set_irq(pic, 0, 0); 11.77 pic_set_irq(pic, 0, 1); 11.78 } 11.79 @@ -203,13 +202,14 @@ void vmx_do_resume(struct vcpu *v) 11.80 { 11.81 struct domain *d = v->domain; 11.82 struct hvm_virpit *vpit = &v->domain->arch.hvm_domain.vpit; 11.83 + struct hvm_time_info *time_info = &vpit->time_info; 11.84 11.85 vmx_stts(); 11.86 11.87 /* pick up the elapsed PIT ticks and re-enable pit_timer */ 11.88 - if ( vpit->first_injected ) { 11.89 + if ( time_info->first_injected ) { 11.90 if ( v->domain->arch.hvm_domain.guest_time ) { 11.91 - vpit->count_point = NOW(); 11.92 + time_info->count_point = NOW(); 11.93 set_guest_time(v, v->domain->arch.hvm_domain.guest_time); 11.94 v->domain->arch.hvm_domain.guest_time = 0; 11.95 }
12.1 --- a/xen/arch/x86/hvm/vmx/vmx.c Wed Apr 19 18:32:20 2006 +0100 12.2 +++ b/xen/arch/x86/hvm/vmx/vmx.c Wed Apr 19 18:38:14 2006 +0100 12.3 @@ -102,7 +102,7 @@ static void vmx_relinquish_guest_resourc 12.4 } 12.5 } 12.6 12.7 - kill_timer(&d->arch.hvm_domain.vpit.pit_timer); 12.8 + kill_timer(&d->arch.hvm_domain.vpit.time_info.pit_timer); 12.9 12.10 if ( d->arch.hvm_domain.shared_page_va ) 12.11 unmap_domain_page_global( 12.12 @@ -358,12 +358,12 @@ static inline int long_mode_do_msr_write 12.13 12.14 static void vmx_freeze_time(struct vcpu *v) 12.15 { 12.16 - struct hvm_virpit *vpit = &v->domain->arch.hvm_domain.vpit; 12.17 + struct hvm_time_info *time_info = &(v->domain->arch.hvm_domain.vpit.time_info); 12.18 12.19 - if ( vpit->first_injected && !v->domain->arch.hvm_domain.guest_time ) { 12.20 + if ( time_info->first_injected && !v->domain->arch.hvm_domain.guest_time ) { 12.21 v->domain->arch.hvm_domain.guest_time = get_guest_time(v); 12.22 - vpit->count_advance += (NOW() - vpit->count_point); 12.23 - stop_timer(&(vpit->pit_timer)); 12.24 + time_info->count_advance += (NOW() - time_info->count_point); 12.25 + stop_timer(&(time_info->pit_timer)); 12.26 } 12.27 } 12.28 12.29 @@ -393,9 +393,9 @@ int vmx_initialize_guest_resources(struc 12.30 12.31 void vmx_migrate_timers(struct vcpu *v) 12.32 { 12.33 - struct hvm_virpit *vpit = &(v->domain->arch.hvm_domain.vpit); 12.34 + struct hvm_time_info *time_info = &v->domain->arch.hvm_domain.vpit.time_info; 12.35 12.36 - migrate_timer(&vpit->pit_timer, v->processor); 12.37 + migrate_timer(&time_info->pit_timer, v->processor); 12.38 migrate_timer(&v->arch.hvm_vmx.hlt_timer, v->processor); 12.39 if ( hvm_apic_support(v->domain) && VLAPIC(v)) 12.40 migrate_timer(&(VLAPIC(v)->vlapic_timer), v->processor); 12.41 @@ -1836,11 +1836,11 @@ static inline void vmx_do_msr_read(struc 12.42 switch (regs->ecx) { 12.43 case MSR_IA32_TIME_STAMP_COUNTER: 12.44 { 12.45 - struct hvm_virpit *vpit; 12.46 + struct hvm_time_info *time_info; 12.47 12.48 rdtscll(msr_content); 12.49 - vpit = &(v->domain->arch.hvm_domain.vpit); 12.50 - msr_content += vpit->cache_tsc_offset; 12.51 + time_info = &(v->domain->arch.hvm_domain.vpit.time_info); 12.52 + msr_content += time_info->cache_tsc_offset; 12.53 break; 12.54 } 12.55 case MSR_IA32_SYSENTER_CS:
13.1 --- a/xen/include/asm-x86/hvm/vpit.h Wed Apr 19 18:32:20 2006 +0100 13.2 +++ b/xen/include/asm-x86/hvm/vpit.h Wed Apr 19 18:38:14 2006 +0100 13.3 @@ -30,47 +30,65 @@ 13.4 13.5 #define PIT_FREQ 1193181 13.6 13.7 -#define LSByte 0 13.8 -#define MSByte 1 13.9 -#define LSByte_multiple 2 13.10 -#define MSByte_multiple 3 13.11 +#define PIT_BASE 0x40 13.12 +#define HVM_PIT_ACCEL_MODE 2 13.13 13.14 -struct hvm_virpit { 13.15 - /* for simulation of counter 0 in mode 2 */ 13.16 +typedef struct PITChannelState { 13.17 + int count; /* can be 65536 */ 13.18 + u16 latched_count; 13.19 + u8 count_latched; 13.20 + u8 status_latched; 13.21 + u8 status; 13.22 + u8 read_state; 13.23 + u8 write_state; 13.24 + u8 write_latch; 13.25 + u8 rw_mode; 13.26 + u8 mode; 13.27 + u8 bcd; /* not supported */ 13.28 + u8 gate; /* timer start */ 13.29 + s64 count_load_time; 13.30 + /* irq handling */ 13.31 + s64 next_transition_time; 13.32 + int irq; 13.33 + struct hvm_time_info *hvm_time; 13.34 + u32 period; /* period(ns) based on count */ 13.35 +} PITChannelState; 13.36 + 13.37 +struct hvm_time_info { 13.38 + /* extra info for the mode 2 channel */ 13.39 + struct timer pit_timer; 13.40 + struct vcpu *vcpu; /* which vcpu the ac_timer bound to */ 13.41 u64 period_cycles; /* pit frequency in cpu cycles */ 13.42 s_time_t count_advance; /* accumulated count advance since last fire */ 13.43 s_time_t count_point; /* last point accumulating count advance */ 13.44 - s_time_t scheduled; /* scheduled timer interrupt */ 13.45 - struct timer pit_timer; /* periodic timer for mode 2*/ 13.46 - unsigned int channel; /* the pit channel, counter 0~2 */ 13.47 unsigned int pending_intr_nr; /* the couner for pending timer interrupts */ 13.48 - u32 period; /* pit frequency in ns */ 13.49 int first_injected; /* flag to prevent shadow window */ 13.50 s64 cache_tsc_offset; /* cache of VMCS TSC_OFFSET offset */ 13.51 u64 last_pit_gtime; /* guest time when last pit is injected */ 13.52 +}; 13.53 13.54 - /* virtual PIT state for handle related I/O */ 13.55 - int read_state; 13.56 - int count_LSB_latched; 13.57 - int count_MSB_latched; 13.58 +typedef struct hvm_virpit { 13.59 + PITChannelState channels[3]; 13.60 + struct hvm_time_info time_info; 13.61 + int speaker_data_on; 13.62 + int dummy_refresh_clock; 13.63 +}hvm_virpit; 13.64 13.65 - unsigned int count; /* the 16 bit channel count */ 13.66 - unsigned int init_val; /* the init value for the counter */ 13.67 -}; 13.68 13.69 static __inline__ s_time_t get_pit_scheduled( 13.70 struct vcpu *v, 13.71 struct hvm_virpit *vpit) 13.72 { 13.73 + struct PITChannelState *s = &(vpit->channels[0]); 13.74 if ( is_irq_enabled(v, 0) ) { 13.75 - return vpit->scheduled; 13.76 + return s->next_transition_time; 13.77 } 13.78 else 13.79 return -1; 13.80 } 13.81 13.82 /* to hook the ioreq packet to get the PIT initialization info */ 13.83 -extern void hvm_hooks_assist(struct vcpu *v); 13.84 -void pickup_deactive_ticks(struct hvm_virpit *vpit); 13.85 +extern void pit_init(struct hvm_virpit *pit, struct vcpu *v); 13.86 +extern void pickup_deactive_ticks(struct hvm_virpit *vpit); 13.87 13.88 #endif /* __ASM_X86_HVM_VPIT_H__ */