📄 i8254.c
字号:
default: case RW_STATE_LSB: pit_load_count(pit, addr, val); break; case RW_STATE_MSB: pit_load_count(pit, addr, val << 8); break; case RW_STATE_WORD0: s->write_latch = val; s->write_state = RW_STATE_WORD1; break; case RW_STATE_WORD1: pit_load_count(pit, addr, s->write_latch | (val << 8)); s->write_state = RW_STATE_WORD0; break; } } spin_unlock(&pit->lock);}static uint32_t pit_ioport_read(struct PITState *pit, uint32_t addr){ int ret, count; struct hvm_hw_pit_channel *s; addr &= 3; s = &pit->hw.channels[addr]; spin_lock(&pit->lock); if ( s->status_latched ) { s->status_latched = 0; ret = s->status; } else if ( s->count_latched ) { switch ( s->count_latched ) { default: case RW_STATE_LSB: ret = s->latched_count & 0xff; s->count_latched = 0; break; case RW_STATE_MSB: ret = s->latched_count >> 8; s->count_latched = 0; break; case RW_STATE_WORD0: ret = s->latched_count & 0xff; s->count_latched = RW_STATE_MSB; break; } } else { switch ( s->read_state ) { default: case RW_STATE_LSB: count = pit_get_count(pit, addr); ret = count & 0xff; break; case RW_STATE_MSB: count = pit_get_count(pit, addr); ret = (count >> 8) & 0xff; break; case RW_STATE_WORD0: count = pit_get_count(pit, addr); ret = count & 0xff; s->read_state = RW_STATE_WORD1; break; case RW_STATE_WORD1: count = pit_get_count(pit, addr); ret = (count >> 8) & 0xff; s->read_state = RW_STATE_WORD0; break; } } spin_unlock(&pit->lock); return ret;}void pit_stop_channel0_irq(PITState *pit){ spin_lock(&pit->lock); destroy_periodic_time(&pit->pt0); spin_unlock(&pit->lock);}#ifdef HVM_DEBUG_SUSPENDstatic void pit_info(PITState *pit){ struct hvm_hw_pit_channel *s; struct periodic_time *pt; int i; for ( i = 0; i < 3; i++ ) { printk("*****pit channel %d's state:*****\n", i); s = &pit->hw.channels[i]; printk("pit 0x%x.\n", s->count); printk("pit 0x%x.\n", s->latched_count); printk("pit 0x%x.\n", s->count_latched); printk("pit 0x%x.\n", s->status_latched); printk("pit 0x%x.\n", s->status); printk("pit 0x%x.\n", s->read_state); printk("pit 0x%x.\n", s->write_state); printk("pit 0x%x.\n", s->write_latch); printk("pit 0x%x.\n", s->rw_mode); printk("pit 0x%x.\n", s->mode); printk("pit 0x%x.\n", s->bcd); printk("pit 0x%x.\n", s->gate); printk("pit %"PRId64"\n", pit->count_load_time[i]); } pt = &pit->pt0; printk("pit channel 0 periodic timer:\n", i); printk("pt %d.\n", pt->enabled); printk("pt %d.\n", pt->one_shot); printk("pt %d.\n", pt->irq); printk("pt %d.\n", pt->first_injected); printk("pt %d.\n", pt->pending_intr_nr); printk("pt %d.\n", pt->period); printk("pt %"PRId64"\n", pt->period_cycles); printk("pt %"PRId64"\n", pt->last_plt_gtime);}#elsestatic void pit_info(PITState *pit){}#endifstatic int pit_save(struct domain *d, hvm_domain_context_t *h){ PITState *pit = domain_vpit(d); int rc; spin_lock(&pit->lock); pit_info(pit); /* Save the PIT hardware state */ rc = hvm_save_entry(PIT, 0, h, &pit->hw); spin_unlock(&pit->lock); return rc;}static int pit_load(struct domain *d, hvm_domain_context_t *h){ PITState *pit = domain_vpit(d); int i; spin_lock(&pit->lock); /* Restore the PIT hardware state */ if ( hvm_load_entry(PIT, h, &pit->hw) ) { spin_unlock(&pit->lock); return 1; } /* Recreate platform timers from hardware state. There will be some * time jitter here, but the wall-clock will have jumped massively, so * we hope the guest can handle it. */ pit->pt0.last_plt_gtime = hvm_get_guest_time(d->vcpu[0]); for ( i = 0; i < 3; i++ ) pit_load_count(pit, i, pit->hw.channels[i].count); pit_info(pit); spin_unlock(&pit->lock); return 0;}HVM_REGISTER_SAVE_RESTORE(PIT, pit_save, pit_load, 1, HVMSR_PER_DOM);void pit_init(struct vcpu *v, unsigned long cpu_khz){ PITState *pit = vcpu_vpit(v); struct hvm_hw_pit_channel *s; int i; spin_lock_init(&pit->lock); /* Some sub-functions assert that they are called with the lock held. */ spin_lock(&pit->lock); pit->pt0.source = PTSRC_isa; register_portio_handler(v->domain, PIT_BASE, 4, handle_pit_io); register_portio_handler(v->domain, 0x61, 1, handle_speaker_io); ticks_per_sec(v) = cpu_khz * (int64_t)1000; for ( i = 0; i < 3; i++ ) { s = &pit->hw.channels[i]; s->mode = 0xff; /* the init mode */ s->gate = (i != 2); pit_load_count(pit, i, 0); } spin_unlock(&pit->lock);}void pit_deinit(struct domain *d){ PITState *pit = domain_vpit(d); destroy_periodic_time(&pit->pt0);}/* the intercept action for PIT DM retval:0--not handled; 1--handled */ static int handle_pit_io( int dir, uint32_t port, uint32_t bytes, uint32_t *val){ struct PITState *vpit = vcpu_vpit(current); if ( bytes != 1 ) { gdprintk(XENLOG_WARNING, "PIT bad access\n"); return 1; } if ( dir == IOREQ_WRITE ) { pit_ioport_write(vpit, port, *val); } else { if ( (port & 3) != 3 ) *val = pit_ioport_read(vpit, port); else gdprintk(XENLOG_WARNING, "PIT: read A1:A0=3!\n"); } return 1;}static void speaker_ioport_write( struct PITState *pit, uint32_t addr, uint32_t val){ pit->hw.speaker_data_on = (val >> 1) & 1; pit_set_gate(pit, 2, val & 1);}static uint32_t speaker_ioport_read( struct PITState *pit, uint32_t addr){ /* Refresh clock toggles at about 15us. We approximate as 2^14ns. */ unsigned int refresh_clock = ((unsigned int)NOW() >> 14) & 1; return ((pit->hw.speaker_data_on << 1) | pit_get_gate(pit, 2) | (pit_get_out(pit, 2) << 5) | (refresh_clock << 4));}static int handle_speaker_io( int dir, uint32_t port, uint32_t bytes, uint32_t *val){ struct PITState *vpit = vcpu_vpit(current); if ( bytes != 1 ) { gdprintk(XENLOG_WARNING, "PIT_SPEAKER bad access\n"); return 1; } spin_lock(&vpit->lock); if ( dir == IOREQ_WRITE ) speaker_ioport_write(vpit, port, *val); else *val = speaker_ioport_read(vpit, port); spin_unlock(&vpit->lock); return 1;}int pv_pit_handler(int port, int data, int write){ ioreq_t ioreq = { .size = 1, .type = IOREQ_TYPE_PIO, .addr = port, .dir = write ? IOREQ_WRITE : IOREQ_READ, .data = data }; if ( (current->domain->domain_id == 0) && dom0_pit_access(&ioreq) ) { /* nothing to do */; } else { uint32_t val = data; if ( port == 0x61 ) handle_speaker_io(ioreq.dir, port, 1, &val); else handle_pit_io(ioreq.dir, port, 1, &val); ioreq.data = val; } return !write ? ioreq.data : 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -