PIT acceleration enhancement add a new flag in HV to control whether re-arm the actimer and handle guest PIT io, by this we can * stop the actimer and io interception if guest change previous periodic mode to other mode. * safely handle reinitialization of periodic mode from guest Signed-off-by: Edwin Zhai <edwin.zhai@intel.com> Signed-off-by: Yunhong Jiang <yunhong.jiang@intel.com> Signed-off-by: Eddie Dong <eddie.dong@intel.com> diff -r 13e9fdaeed27 tools/ioemu/hw/i8254.c --- a/tools/ioemu/hw/i8254.c Wed Feb 22 09:54:20 2006 +0100 +++ b/tools/ioemu/hw/i8254.c Wed Feb 22 22:22:51 2006 +0800 @@ -50,19 +50,18 @@ typedef struct PITChannelState { int64_t next_transition_time; QEMUTimer *irq_timer; int irq; - int hvm_channel; /* Is this accelerated by HVM ? */ } PITChannelState; struct PITState { PITChannelState channels[3]; + /* currently operate which channel for hvm use */ + int hvm_channel; }; static PITState pit_state; static void pit_irq_timer_update(PITChannelState *s, int64_t current_time); -/* currently operate which channel for hvm use */ -int hvm_channel = -1; extern FILE *logfile; static int pit_get_count(PITChannelState *s) { @@ -215,56 +214,62 @@ int pit_get_gate(PITState *pit, int chan return s->gate; } +/* change config for HVM accelerated pit channel */ void pit_reset_hvm_vectors() { extern shared_iopage_t *shared_page; ioreq_t *req; - int irq, i; + int irq; PITChannelState *s; irq = 0; - for(i = 0; i < 3; i++) { - if (pit_state.channels[i].hvm_channel) - break; - } - - if (i == 3) - return; - /* Assumes just one HVM accelerated channel */ - hvm_channel = i; - s = &pit_state.channels[hvm_channel]; + s = &pit_state.channels[pit_state.hvm_channel]; fprintf(logfile, - "HVM_PIT:guest init pit channel %d!\n", hvm_channel); + "HVM_PIT:guest init pit channel %d!\n", pit_state.hvm_channel); req = &shared_page->vcpu_iodata[0].vp_ioreq; req->state = STATE_IORESP_HOOK; /* * info passed to HV as following * -- init count:16 bit, timer vec:8 bit, - * PIT channel(0~2):2 bit, rw mode:2 bit + * PIT channel(0~2):2 bit, rw mode:2 bit, + * PIT mode(0~5):3 bit */ req->u.data = s->count; req->u.data |= (irq << 16); - req->u.data |= (hvm_channel << 24); + req->u.data |= (pit_state.hvm_channel << 24); req->u.data |= ((s->rw_mode) << 26); + req->u.data |= ((s->mode) << 28); + + /* HVM acceleration only for mode 2 */ + if (s->mode != 2) + pit_state.hvm_channel = -1; + fprintf(logfile, "HVM_PIT:pass info 0x%llx to HV!\n", req->u.data); } -static inline void pit_load_count(PITChannelState *s, int val) +static inline void pit_load_count(PITChannelState *s, int val, int chn) { if (val == 0) val = 0x10000; s->count_load_time = qemu_get_clock(vm_clock); s->count = val; - /* guest init this pit channel for periodic mode. we do not update related - * timer so the channel never send intr from device model*/ - if (hvm_channel != -1 && s->mode == 2) { + /* first time for periodic mode, mark this channel as HVM accelerated */ + if (s->mode == 2) { + if (pit_state.hvm_channel == -1) + pit_state.hvm_channel = chn; + else if (pit_state.hvm_channel != chn){ + fprintf(logfile, "HVM_PIT:should not set another pit channel as mode 2!\n"); + return; + } + } + + /* change something for hvm channel, e.g the mode,freq or vec */ + if (pit_state.hvm_channel == chn) pit_reset_hvm_vectors(); - hvm_channel = -1; - } /* pit_irq_timer_update(s, s->count_load_time);*/ } @@ -323,22 +328,20 @@ static void pit_ioport_write(void *opaqu } } else { s = &pit->channels[addr]; - s->hvm_channel = 1; - hvm_channel = addr; switch(s->write_state) { default: case RW_STATE_LSB: - pit_load_count(s, val); + pit_load_count(s, val, addr); break; case RW_STATE_MSB: - pit_load_count(s, val << 8); + pit_load_count(s, val << 8, addr); break; case RW_STATE_WORD0: s->write_latch = val; s->write_state = RW_STATE_WORD1; break; case RW_STATE_WORD1: - pit_load_count(s, s->write_latch | (val << 8)); + pit_load_count(s, s->write_latch | (val << 8), addr); s->write_state = RW_STATE_WORD0; break; } @@ -493,11 +496,12 @@ static void pit_reset(void *opaque) PITChannelState *s; int i; + pit->hvm_channel = -1; for(i = 0;i < 3; i++) { s = &pit->channels[i]; s->mode = 3; s->gate = (i != 2); - pit_load_count(s, 0); + pit_load_count(s, 0, i); } } @@ -506,6 +510,7 @@ PITState *pit_init(int base, int irq) PITState *pit = &pit_state; PITChannelState *s; + pit->hvm_channel = -1; s = &pit->channels[0]; /* the timer 0 is connected to an IRQ */ s->irq_timer = qemu_new_timer(vm_clock, pit_irq_timer, s); diff -r 13e9fdaeed27 xen/arch/x86/hvm/hvm.c --- a/xen/arch/x86/hvm/hvm.c Wed Feb 22 09:54:20 2006 +0100 +++ b/xen/arch/x86/hvm/hvm.c Wed Feb 22 22:22:51 2006 +0800 @@ -186,6 +186,7 @@ static void hvm_get_info(struct domain * unmap_domain_page(p); } +extern void pit_init(struct hvm_virpit *vpit, struct vcpu *v); void hvm_setup_platform(struct domain* d) { struct hvm_domain *platform; @@ -204,6 +205,8 @@ void hvm_setup_platform(struct domain* d spin_lock_init(&d->arch.hvm_domain.round_robin_lock); hvm_vioapic_init(d); } + + pit_init(&platform->vpit, current); } void pic_irq_request(int *interrupt_request, int level) diff -r 13e9fdaeed27 xen/arch/x86/hvm/intercept.c --- a/xen/arch/x86/hvm/intercept.c Wed Feb 22 09:54:20 2006 +0100 +++ b/xen/arch/x86/hvm/intercept.c Wed Feb 22 22:22:51 2006 +0800 @@ -35,6 +35,8 @@ extern struct hvm_mmio_handler vioapic_m extern struct hvm_mmio_handler vioapic_mmio_handler; #define HVM_MMIO_HANDLER_NR 2 +/* only accelerate for pit mode 2 */ +#define HVM_PIT_ACCEL_MODE 2 struct hvm_mmio_handler *hvm_mmio_handlers[HVM_MMIO_HANDLER_NR] { @@ -305,6 +307,10 @@ int intercept_pit_io(ioreq_t *p) struct vcpu *v = current; struct hvm_virpit *vpit = &(v->domain->arch.hvm_domain.vpit); + /* handle io only if accelerated pit mode */ + if (vpit->mode != HVM_PIT_ACCEL_MODE) + return 0; + if (p->size != 1 || p->pdata_valid || p->type != IOREQ_TYPE_PIO) @@ -353,6 +359,10 @@ static void pit_timer_fn(void *data) struct vcpu *v = data; struct hvm_virpit *vpit = &(v->domain->arch.hvm_domain.vpit); + /* re-arm actimer only if accelerated pit mode */ + if (vpit->mode != HVM_PIT_ACCEL_MODE) + return; + /* pick up missed timer tick */ missed_ticks(vpit); @@ -375,6 +385,13 @@ void pickup_deactive_ticks(struct hvm_vi } } +void pit_init(struct hvm_virpit *vpit, struct vcpu *v) +{ + vpit->mode = -1; + init_timer(&vpit->pit_timer, pit_timer_fn, v, v->processor); + register_portio_handler(0x40, 4, intercept_pit_io); +} + /* Only some PIT operations such as load init counter need a hypervisor hook. * leave all other operations in user space DM */ @@ -383,19 +400,18 @@ void hvm_hooks_assist(struct vcpu *v) vcpu_iodata_t *vio = get_vio(v->domain, v->vcpu_id); ioreq_t *p = &vio->vp_ioreq; struct hvm_virpit *vpit = &(v->domain->arch.hvm_domain.vpit); - int rw_mode, reinit = 0; + int rw_mode, mode; /* load init count*/ if (p->state == STATE_IORESP_HOOK) { - /* set up actimer, handle re-init */ - if ( active_timer(&(vpit->pit_timer)) ) { - HVM_DBG_LOG(DBG_LEVEL_1, "HVM_PIT: guest reset PIT with channel %lx!\n", (unsigned long) ((p->u.data >> 24) & 0x3) ); - stop_timer(&(vpit->pit_timer)); - reinit = 1; - - } - else { - init_timer(&vpit->pit_timer, pit_timer_fn, v, v->processor); + + mode = ((p->u.data >> 28) & 0x7); + + /* new mode is not accelerated mode */ + if (mode != HVM_PIT_ACCEL_MODE) { + vpit->mode = mode; + p->state = STATE_IORESP_READY; + return; } /* init count for this channel */ @@ -433,16 +449,18 @@ void hvm_hooks_assist(struct vcpu *v) break; } + /* XXX: any race condition with pit_timer_fn?? */ vpit->scheduled = NOW() + vpit->period; - set_timer(&vpit->pit_timer, vpit->scheduled); + + /* orignal mode is not accelerated mode */ + if (vpit->mode != HVM_PIT_ACCEL_MODE) { + vpit->mode = mode; + set_timer(&vpit->pit_timer, vpit->scheduled); + } /*restore the state*/ p->state = STATE_IORESP_READY; - /* register handler to intercept the PIT io when vm_exit */ - if (!reinit) { - register_portio_handler(0x40, 4, intercept_pit_io); - } } } diff -r 13e9fdaeed27 xen/include/asm-x86/hvm/vpit.h --- a/xen/include/asm-x86/hvm/vpit.h Wed Feb 22 09:54:20 2006 +0100 +++ b/xen/include/asm-x86/hvm/vpit.h Wed Feb 22 22:22:51 2006 +0800 @@ -43,6 +43,7 @@ struct hvm_virpit { s_time_t scheduled; /* scheduled timer interrupt */ struct timer pit_timer; /* periodic timer for mode 2*/ unsigned int channel; /* the pit channel, counter 0~2 */ + unsigned int mode; /* the pit mode, only acceleration for mode 2 */ unsigned int pending_intr_nr; /* the couner for pending timer interrupts */ u32 period; /* pit frequency in ns */ int first_injected; /* flag to prevent shadow window */ _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
On 22 Feb 2006, at 15:07, Edwin Zhai wrote:> PIT acceleration enhancement > add a new flag in HV to control whether re-arm the actimer and handle > guest PIT io, by this we can > * stop the actimer and io interception if guest change previous > periodic mode to other mode. > * safely handle reinitialization of periodic mode from guest > > Signed-off-by: Edwin Zhai <edwin.zhai@intel.com> > Signed-off-by: Yunhong Jiang <yunhong.jiang@intel.com> > Signed-off-by: Eddie Dong <eddie.dong@intel.com>Please can you just sync the PIT code with the current qemu tree and move the whole lot down into Xen? The current split between dom0 and xen is unnecessary and gross, and I hate this piecemeal ad hoc migration of PIT functionality from dom0 down to xen. Just move it all in one go. The only things that should need implementing in qemu-dm are devices whose backend cannot be implemented in Xen (net, disc, keyboard, mouse, ....) -- generally real peripheral devices. Platform devices like PITs and PICs should be done entirely in Xen. -- Keir _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Dong, Eddie
2006-Feb-23 01:24 UTC
RE: [Xen-devel] Re: [PATCH] PIT acceleration enhancement
> The only things that should need implementing in qemu-dm are devices > whose backend cannot be implemented in Xen (net, disc, keyboard, > mouse, ....) -- generally real peripheral devices. Platform devices > like PITs and PICs should be done entirely in Xen.Agree! Also to meet the requirement of supporting multiple guest time resources such as RTC, ACPI time that are used as primary platform time resource in some other non linux unmodified OSes. We are trouble in synchronizing all those time resource if they are in different place. So, it is time to pull all of them into Xen :-) thx,eddie _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel