[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] Merge with xen-ia64-unstable
# HG changeset patch # User Keir Fraser <keir@xxxxxxxxxxxxx> # Date 1181986926 -3600 # Node ID 093bc9dcbbcac00194861072b4ddcaa9a27a604a # Parent 3b51eebdf9ab83e4473913358d4924370fa75763 # Parent 1feb91894e11d3b1fac3b4c38b1eb325c8acd20b Merge with xen-ia64-unstable --- xen/arch/x86/hvm/hpet.c | 43 +++++++++++++- xen/arch/x86/hvm/hvm.c | 1 xen/arch/x86/hvm/i8254.c | 87 ++++++++++++++++++++++------- xen/arch/x86/hvm/pmtimer.c | 62 ++++++++++++++------ xen/arch/x86/hvm/rtc.c | 64 ++++++++++++++++++--- xen/arch/x86/hvm/svm/vmcb.c | 10 +++ xen/arch/x86/hvm/vpt.c | 85 +++++++++++++++++++++++++--- xen/arch/x86/mm/hap/hap.c | 123 ++++++++++++++--------------------------- xen/arch/x86/mm/p2m.c | 8 ++ xen/common/kexec.c | 3 + xen/common/timer.c | 2 xen/include/asm-x86/hvm/vcpu.h | 3 + xen/include/asm-x86/hvm/vpt.h | 6 +- 13 files changed, 349 insertions(+), 148 deletions(-) diff -r 3b51eebdf9ab -r 093bc9dcbbca xen/arch/x86/hvm/hpet.c --- a/xen/arch/x86/hvm/hpet.c Fri Jun 15 13:33:11 2007 -0600 +++ b/xen/arch/x86/hvm/hpet.c Sat Jun 16 10:42:06 2007 +0100 @@ -113,6 +113,8 @@ static inline int hpet_check_access_leng static inline uint64_t hpet_read_maincounter(HPETState *h) { + ASSERT(spin_is_locked(&h->lock)); + if ( hpet_enabled(h) ) return guest_time_hpet(h->vcpu) + h->mc_offset; else @@ -131,6 +133,8 @@ static unsigned long hpet_read( if ( hpet_check_access_length(addr, length) != 0 ) return ~0UL; + spin_lock(&h->lock); + val = hpet_read64(h, addr & ~7); if ( (addr & ~7) == HPET_COUNTER ) val = hpet_read_maincounter(h); @@ -139,12 +143,15 @@ static unsigned long hpet_read( if ( length != 8 ) result = (val >> ((addr & 7) * 8)) & ((1UL << (length * 8)) - 1); + spin_unlock(&h->lock); + return result; } static void hpet_stop_timer(HPETState *h, unsigned int tn) { ASSERT(tn < HPET_TIMER_NUM); + ASSERT(spin_is_locked(&h->lock)); stop_timer(&h->timers[tn]); } @@ -157,7 +164,8 @@ static void hpet_set_timer(HPETState *h, uint64_t tn_cmp, cur_tick, diff; ASSERT(tn < HPET_TIMER_NUM); - + ASSERT(spin_is_locked(&h->lock)); + if ( !hpet_enabled(h) || !timer_enabled(h, tn) ) return; @@ -212,6 +220,8 @@ static void hpet_write( if ( hpet_check_access_length(addr, length) != 0 ) return; + + spin_lock(&h->lock); old_val = hpet_read64(h, addr & ~7); if ( (addr & ~7) == HPET_COUNTER ) @@ -302,6 +312,8 @@ static void hpet_write( /* Ignore writes to unsupported and reserved registers. */ break; } + + spin_unlock(&h->lock); } static int hpet_range(struct vcpu *v, unsigned long addr) @@ -320,6 +332,8 @@ static void hpet_route_interrupt(HPETSta { unsigned int tn_int_route = timer_int_route(h, tn); struct domain *d = h->vcpu->domain; + + ASSERT(spin_is_locked(&h->lock)); if ( (tn <= 1) && (h->hpet.config & HPET_CFG_LEGACY) ) { @@ -352,8 +366,13 @@ static void hpet_timer_fn(void *opaque) HPETState *h = htfi->hs; unsigned int tn = htfi->tn; + spin_lock(&h->lock); + if ( !hpet_enabled(h) || !timer_enabled(h, tn) ) - return; + { + spin_unlock(&h->lock); + return; + } hpet_route_interrupt(h, tn); @@ -374,6 +393,8 @@ static void hpet_timer_fn(void *opaque) set_timer(&h->timers[tn], NOW() + hpet_tick_to_ns(h, h->hpet.period[tn])); } + + spin_unlock(&h->lock); } void hpet_migrate_timers(struct vcpu *v) @@ -391,12 +412,19 @@ static int hpet_save(struct domain *d, h static int hpet_save(struct domain *d, hvm_domain_context_t *h) { HPETState *hp = &d->arch.hvm_domain.pl_time.vhpet; + int rc; + + spin_lock(&hp->lock); /* Write the proper value into the main counter */ hp->hpet.mc64 = hp->mc_offset + guest_time_hpet(hp->vcpu); /* Save the HPET registers */ - return hvm_save_entry(HPET, 0, h, &hp->hpet); + rc = hvm_save_entry(HPET, 0, h, &hp->hpet); + + spin_unlock(&hp->lock); + + return rc; } static int hpet_load(struct domain *d, hvm_domain_context_t *h) @@ -404,9 +432,14 @@ static int hpet_load(struct domain *d, h HPETState *hp = &d->arch.hvm_domain.pl_time.vhpet; int i; + spin_lock(&hp->lock); + /* Reload the HPET registers */ if ( hvm_load_entry(HPET, h, &hp->hpet) ) + { + spin_unlock(&hp->lock); return -EINVAL; + } /* Recalculate the offset between the main counter and guest time */ hp->mc_offset = hp->hpet.mc64 - guest_time_hpet(hp->vcpu); @@ -415,6 +448,8 @@ static int hpet_load(struct domain *d, h for ( i = 0; i < HPET_TIMER_NUM; i++ ) hpet_set_timer(hp, i); + spin_unlock(&hp->lock); + return 0; } @@ -426,6 +461,8 @@ void hpet_init(struct vcpu *v) int i; memset(h, 0, sizeof(HPETState)); + + spin_lock_init(&h->lock); h->vcpu = v; h->tsc_freq = ticks_per_sec(v); diff -r 3b51eebdf9ab -r 093bc9dcbbca xen/arch/x86/hvm/hvm.c --- a/xen/arch/x86/hvm/hvm.c Fri Jun 15 13:33:11 2007 -0600 +++ b/xen/arch/x86/hvm/hvm.c Sat Jun 16 10:42:06 2007 +0100 @@ -401,6 +401,7 @@ int hvm_vcpu_initialise(struct vcpu *v) get_ioreq(v)->vp_eport = v->arch.hvm_vcpu.xen_port; spin_unlock(&v->domain->arch.hvm_domain.ioreq.lock); + spin_lock_init(&v->arch.hvm_vcpu.tm_lock); INIT_LIST_HEAD(&v->arch.hvm_vcpu.tm_list); if ( v->vcpu_id == 0 ) diff -r 3b51eebdf9ab -r 093bc9dcbbca xen/arch/x86/hvm/i8254.c --- a/xen/arch/x86/hvm/i8254.c Fri Jun 15 13:33:11 2007 -0600 +++ b/xen/arch/x86/hvm/i8254.c Sat Jun 16 10:42:06 2007 +0100 @@ -82,6 +82,8 @@ static int pit_get_count(PITState *pit, struct hvm_hw_pit_channel *c = &pit->hw.channels[channel]; struct vcpu *v = vpit_vcpu(pit); + ASSERT(spin_is_locked(&pit->lock)); + d = muldiv64(hvm_get_guest_time(v) - pit->count_load_time[channel], PIT_FREQ, ticks_per_sec(v)); @@ -111,6 +113,8 @@ static int pit_get_out(PITState *pit, in int out; struct vcpu *v = vpit_vcpu(pit); + ASSERT(spin_is_locked(&pit->lock)); + d = muldiv64(hvm_get_guest_time(v) - pit->count_load_time[channel], PIT_FREQ, ticks_per_sec(v)); @@ -142,6 +146,8 @@ static void pit_set_gate(PITState *pit, { struct hvm_hw_pit_channel *s = &pit->hw.channels[channel]; struct vcpu *v = vpit_vcpu(pit); + + ASSERT(spin_is_locked(&pit->lock)); switch ( s->mode ) { @@ -165,6 +171,7 @@ static void pit_set_gate(PITState *pit, int pit_get_gate(PITState *pit, int channel) { + ASSERT(spin_is_locked(&pit->lock)); return pit->hw.channels[channel].gate; } @@ -181,10 +188,15 @@ static void pit_load_count(PITState *pit struct periodic_time *pt = &pit->pt[channel]; struct vcpu *v = vpit_vcpu(pit); + ASSERT(spin_is_locked(&pit->lock)); + if ( val == 0 ) val = 0x10000; - pit->count_load_time[channel] = hvm_get_guest_time(pt->vcpu); + if ( v == NULL ) + rdtscll(pit->count_load_time[channel]); + else + pit->count_load_time[channel] = hvm_get_guest_time(v); s->count = val; period = DIV_ROUND((val * 1000000000ULL), PIT_FREQ); @@ -209,23 +221,29 @@ static void pit_load_count(PITState *pit } } -static void pit_latch_count(PITState *s, int channel) -{ - struct hvm_hw_pit_channel *c = &s->hw.channels[channel]; +static void pit_latch_count(PITState *pit, int channel) +{ + struct hvm_hw_pit_channel *c = &pit->hw.channels[channel]; + + ASSERT(spin_is_locked(&pit->lock)); + if ( !c->count_latched ) { - c->latched_count = pit_get_count(s, channel); + c->latched_count = pit_get_count(pit, channel); c->count_latched = c->rw_mode; } } -static void pit_latch_status(PITState *s, int channel) -{ - struct hvm_hw_pit_channel *c = &s->hw.channels[channel]; +static void pit_latch_status(PITState *pit, int channel) +{ + struct hvm_hw_pit_channel *c = &pit->hw.channels[channel]; + + ASSERT(spin_is_locked(&pit->lock)); + if ( !c->status_latched ) { /* TODO: Return NULL COUNT (bit 6). */ - c->status = ((pit_get_out(s, channel) << 7) | + c->status = ((pit_get_out(pit, channel) << 7) | (c->rw_mode << 4) | (c->mode << 1) | c->bcd); @@ -240,6 +258,8 @@ static void pit_ioport_write(struct PITS val &= 0xff; addr &= 3; + + spin_lock(&pit->lock); if ( addr == 3 ) { @@ -304,6 +324,8 @@ static void pit_ioport_write(struct PITS break; } } + + spin_unlock(&pit->lock); } static uint32_t pit_ioport_read(struct PITState *pit, uint32_t addr) @@ -313,6 +335,8 @@ static uint32_t pit_ioport_read(struct P addr &= 3; s = &pit->hw.channels[addr]; + + spin_lock(&pit->lock); if ( s->status_latched ) { @@ -364,12 +388,16 @@ static uint32_t pit_ioport_read(struct P } } + spin_unlock(&pit->lock); + return ret; } void pit_stop_channel0_irq(PITState *pit) { + spin_lock(&pit->lock); destroy_periodic_time(&pit->pt[0]); + spin_unlock(&pit->lock); } #ifdef HVM_DEBUG_SUSPEND @@ -422,11 +450,18 @@ static int pit_save(struct domain *d, hv static 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 */ - return hvm_save_entry(PIT, 0, h, &pit->hw); + 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) @@ -434,9 +469,14 @@ static int pit_load(struct domain *d, hv 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 @@ -448,6 +488,9 @@ static int pit_load(struct domain *d, hv } pit_info(pit); + + spin_unlock(&pit->lock); + return 0; } @@ -456,17 +499,15 @@ void pit_init(struct vcpu *v, unsigned l void pit_init(struct vcpu *v, unsigned long cpu_khz) { PITState *pit = vcpu_vpit(v); - struct periodic_time *pt; struct hvm_hw_pit_channel *s; int i; - pt = &pit->pt[0]; - pt[0].vcpu = v; - pt[1].vcpu = v; - pt[2].vcpu = v; + spin_lock_init(&pit->lock); + + /* Some sub-functions assert that they are called with the lock held. */ + spin_lock(&pit->lock); register_portio_handler(v->domain, PIT_BASE, 4, handle_pit_io); - /* register the speaker port */ register_portio_handler(v->domain, 0x61, 1, handle_speaker_io); ticks_per_sec(v) = cpu_khz * (int64_t)1000; @@ -477,6 +518,8 @@ void pit_init(struct vcpu *v, unsigned l s->gate = (i != 2); pit_load_count(pit, i, 0); } + + spin_unlock(&pit->lock); } void pit_deinit(struct domain *d) @@ -492,10 +535,10 @@ static int handle_pit_io(ioreq_t *p) if ( (p->size != 1) || p->data_is_ptr || (p->type != IOREQ_TYPE_PIO) ) { - gdprintk(XENLOG_WARNING, "HVM_PIT bad access\n"); + gdprintk(XENLOG_WARNING, "PIT bad access\n"); return 1; } - + if ( p->dir == IOREQ_WRITE ) { pit_ioport_write(vpit, p->addr, p->data); @@ -505,7 +548,7 @@ static int handle_pit_io(ioreq_t *p) if ( (p->addr & 3) != 3 ) p->data = pit_ioport_read(vpit, p->addr); else - gdprintk(XENLOG_WARNING, "HVM_PIT: read A1:A0=3!\n"); + gdprintk(XENLOG_WARNING, "PIT: read A1:A0=3!\n"); } return 1; @@ -533,14 +576,18 @@ static int handle_speaker_io(ioreq_t *p) if ( (p->size != 1) || p->data_is_ptr || (p->type != IOREQ_TYPE_PIO) ) { - gdprintk(XENLOG_WARNING, "HVM_SPEAKER bad access\n"); + gdprintk(XENLOG_WARNING, "PIT_SPEAKER bad access\n"); return 1; } + + spin_lock(&vpit->lock); if ( p->dir == IOREQ_WRITE ) speaker_ioport_write(vpit, p->addr, p->data); else p->data = speaker_ioport_read(vpit, p->addr); + + spin_unlock(&vpit->lock); return 1; } diff -r 3b51eebdf9ab -r 093bc9dcbbca xen/arch/x86/hvm/pmtimer.c --- a/xen/arch/x86/hvm/pmtimer.c Fri Jun 15 13:33:11 2007 -0600 +++ b/xen/arch/x86/hvm/pmtimer.c Sat Jun 16 10:42:06 2007 +0100 @@ -53,6 +53,8 @@ /* Dispatch SCIs based on the PM1a_STS and PM1a_EN registers */ static void pmt_update_sci(PMTState *s) { + ASSERT(spin_is_locked(&s->lock)); + if ( s->pm.pm1a_en & s->pm.pm1a_sts & SCI_MASK ) hvm_isa_irq_assert(s->vcpu->domain, SCI_IRQ); else @@ -66,6 +68,8 @@ static void pmt_update_time(PMTState *s) uint64_t curr_gtime; uint32_t msb = s->pm.tmr_val & TMR_VAL_MSB; + ASSERT(spin_is_locked(&s->lock)); + /* Update the timer */ curr_gtime = hvm_get_guest_time(s->vcpu); s->pm.tmr_val += ((curr_gtime - s->last_gtime) * s->scale) >> 32; @@ -89,6 +93,8 @@ static void pmt_timer_callback(void *opa uint32_t pmt_cycles_until_flip; uint64_t time_until_flip; + spin_lock(&s->lock); + /* Recalculate the timer and make sure we get an SCI if we need one */ pmt_update_time(s); @@ -103,8 +109,9 @@ static void pmt_timer_callback(void *opa /* Wake up again near the next bit-flip */ set_timer(&s->timer, NOW() + time_until_flip + MILLISECS(1)); -} - + + spin_unlock(&s->lock); +} /* Handle port I/O to the PM1a_STS and PM1a_EN registers */ static int handle_evt_io(ioreq_t *p) @@ -114,7 +121,9 @@ static int handle_evt_io(ioreq_t *p) uint32_t addr, data, byte; int i; - if ( p->dir == 0 ) /* Write */ + spin_lock(&s->lock); + + if ( p->dir == IOREQ_WRITE ) { /* Handle this I/O one byte at a time */ for ( i = p->size, addr = p->addr, data = p->data; @@ -122,7 +131,7 @@ static int handle_evt_io(ioreq_t *p) i--, addr++, data >>= 8 ) { byte = data & 0xff; - switch(addr) + switch ( addr ) { /* PM1a_STS register bits are write-to-clear */ case PM1a_STS_ADDR: @@ -149,7 +158,7 @@ static int handle_evt_io(ioreq_t *p) /* Fix up the SCI state to match the new register state */ pmt_update_sci(s); } - else /* Read */ + else /* p->dir == IOREQ_READ */ { data = s->pm.pm1a_sts | (((uint32_t) s->pm.pm1a_en) << 16); data >>= 8 * (p->addr - PM1a_STS_ADDR); @@ -157,6 +166,9 @@ static int handle_evt_io(ioreq_t *p) else if ( p->size == 2 ) data &= 0xffff; p->data = data; } + + spin_unlock(&s->lock); + return 1; } @@ -167,29 +179,31 @@ static int handle_pmt_io(ioreq_t *p) struct vcpu *v = current; PMTState *s = &v->domain->arch.hvm_domain.pl_time.vpmt; - if (p->size != 4 || - p->data_is_ptr || - p->type != IOREQ_TYPE_PIO){ - printk("HVM_PMT: wrong PM timer IO\n"); + if ( (p->size != 4) || p->data_is_ptr || (p->type != IOREQ_TYPE_PIO) ) + { + gdprintk(XENLOG_WARNING, "HVM_PMT bad access\n"); return 1; } - if (p->dir == 0) { /* write */ - /* PM_TMR_BLK is read-only */ - return 1; - } else if (p->dir == 1) { /* read */ + if ( p->dir == IOREQ_READ ) + { + spin_lock(&s->lock); pmt_update_time(s); p->data = s->pm.tmr_val; + spin_unlock(&s->lock); return 1; } + return 0; } static int pmtimer_save(struct domain *d, hvm_domain_context_t *h) { PMTState *s = &d->arch.hvm_domain.pl_time.vpmt; - uint32_t msb = s->pm.tmr_val & TMR_VAL_MSB; - uint32_t x; + uint32_t x, msb = s->pm.tmr_val & TMR_VAL_MSB; + int rc; + + spin_lock(&s->lock); /* Update the counter to the guest's current time. We always save * with the domain paused, so the saved time should be after the @@ -202,22 +216,33 @@ static int pmtimer_save(struct domain *d /* No point in setting the SCI here because we'll already have saved the * IRQ and *PIC state; we'll fix it up when we restore the domain */ - return hvm_save_entry(PMTIMER, 0, h, &s->pm); + rc = hvm_save_entry(PMTIMER, 0, h, &s->pm); + + spin_unlock(&s->lock); + + return rc; } static int pmtimer_load(struct domain *d, hvm_domain_context_t *h) { PMTState *s = &d->arch.hvm_domain.pl_time.vpmt; + + spin_lock(&s->lock); /* Reload the registers */ if ( hvm_load_entry(PMTIMER, h, &s->pm) ) + { + spin_unlock(&s->lock); return -EINVAL; + } /* Calculate future counter values from now. */ s->last_gtime = hvm_get_guest_time(s->vcpu); /* Set the SCI state from the registers */ pmt_update_sci(s); + + spin_unlock(&s->lock); return 0; } @@ -225,14 +250,11 @@ HVM_REGISTER_SAVE_RESTORE(PMTIMER, pmtim HVM_REGISTER_SAVE_RESTORE(PMTIMER, pmtimer_save, pmtimer_load, 1, HVMSR_PER_DOM); - void pmtimer_init(struct vcpu *v) { PMTState *s = &v->domain->arch.hvm_domain.pl_time.vpmt; - s->pm.tmr_val = 0; - s->pm.pm1a_sts = 0; - s->pm.pm1a_en = 0; + spin_lock_init(&s->lock); s->scale = ((uint64_t)FREQUENCE_PMTIMER << 32) / ticks_per_sec(v); s->vcpu = v; diff -r 3b51eebdf9ab -r 093bc9dcbbca xen/arch/x86/hvm/rtc.c --- a/xen/arch/x86/hvm/rtc.c Fri Jun 15 13:33:11 2007 -0600 +++ b/xen/arch/x86/hvm/rtc.c Sat Jun 16 10:42:06 2007 +0100 @@ -34,10 +34,12 @@ arch.hvm_domain.pl_time.vrtc)) #define vrtc_vcpu(rtc) (vrtc_domain(rtc)->vcpu[0]) -void rtc_periodic_cb(struct vcpu *v, void *opaque) +static void rtc_periodic_cb(struct vcpu *v, void *opaque) { RTCState *s = opaque; + spin_lock(&s->lock); s->hw.cmos_data[RTC_REG_C] |= 0xc0; + spin_unlock(&s->lock); } int is_rtc_periodic_irq(void *opaque) @@ -54,6 +56,8 @@ static void rtc_timer_update(RTCState *s { int period_code, period; struct vcpu *v = vrtc_vcpu(s); + + ASSERT(spin_is_locked(&s->lock)); 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) ) @@ -78,14 +82,21 @@ static int rtc_ioport_write(void *opaque { RTCState *s = opaque; + spin_lock(&s->lock); + if ( (addr & 1) == 0 ) { - s->hw.cmos_index = data & 0x7f; - return (s->hw.cmos_index < RTC_CMOS_SIZE); + data &= 0x7f; + s->hw.cmos_index = data; + spin_unlock(&s->lock); + return (data < RTC_CMOS_SIZE); } if ( s->hw.cmos_index >= RTC_CMOS_SIZE ) + { + spin_unlock(&s->lock); return 0; + } switch ( s->hw.cmos_index ) { @@ -134,6 +145,8 @@ static int rtc_ioport_write(void *opaque break; } + spin_unlock(&s->lock); + return 1; } @@ -158,6 +171,8 @@ static void rtc_set_time(RTCState *s) struct tm *tm = &s->current_tm; unsigned long before, after; /* XXX s_time_t */ + ASSERT(spin_is_locked(&s->lock)); + before = mktime(tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); @@ -182,6 +197,8 @@ static void rtc_copy_date(RTCState *s) const struct tm *tm = &s->current_tm; struct domain *d = vrtc_domain(s); + ASSERT(spin_is_locked(&s->lock)); + if ( s->time_offset_seconds != d->time_offset_seconds ) { s->current_tm = gmtime(get_localtime(d)); @@ -230,6 +247,8 @@ static void rtc_next_second(RTCState *s) struct tm *tm = &s->current_tm; int days_in_month; struct domain *d = vrtc_domain(s); + + ASSERT(spin_is_locked(&s->lock)); if ( s->time_offset_seconds != d->time_offset_seconds ) { @@ -279,6 +298,8 @@ static void rtc_update_second(void *opaq { RTCState *s = opaque; + spin_lock(&s->lock); + /* if the oscillator is not in normal operation, we do not update */ if ( (s->hw.cmos_data[RTC_REG_A] & RTC_DIV_CTL) != RTC_REF_CLCK_32KHZ ) { @@ -295,12 +316,16 @@ static void rtc_update_second(void *opaq /* Delay time before update cycle */ set_timer(&s->second_timer2, s->next_second_time + 244000); } + + spin_unlock(&s->lock); } static void rtc_update_second2(void *opaque) { RTCState *s = opaque; struct domain *d = vrtc_domain(s); + + spin_lock(&s->lock); if ( !(s->hw.cmos_data[RTC_REG_B] & RTC_SET) ) rtc_copy_date(s); @@ -337,15 +362,18 @@ static void rtc_update_second2(void *opa s->next_second_time += 1000000000ULL; set_timer(&s->second_timer, s->next_second_time); -} - -static uint32_t rtc_ioport_read(void *opaque, uint32_t addr) -{ - RTCState *s = opaque; + + spin_unlock(&s->lock); +} + +static uint32_t rtc_ioport_read(RTCState *s, uint32_t addr) +{ int ret; if ( (addr & 1) == 0 ) return 0xff; + + spin_lock(&s->lock); switch ( s->hw.cmos_index ) { @@ -371,6 +399,8 @@ static uint32_t rtc_ioport_read(void *op break; } + spin_unlock(&s->lock); + return ret; } @@ -413,7 +443,11 @@ static int rtc_save(struct domain *d, hv static int rtc_save(struct domain *d, hvm_domain_context_t *h) { RTCState *s = domain_vrtc(d); - return hvm_save_entry(RTC, 0, h, &s->hw); + int rc; + spin_lock(&s->lock); + rc = hvm_save_entry(RTC, 0, h, &s->hw); + spin_unlock(&s->lock); + return rc; } /* Reload the hardware state from a saved domain */ @@ -421,9 +455,14 @@ static int rtc_load(struct domain *d, hv { RTCState *s = domain_vrtc(d); + spin_lock(&s->lock); + /* Restore the registers */ if ( hvm_load_entry(RTC, h, &s->hw) != 0 ) + { + spin_unlock(&s->lock); return -EINVAL; + } /* Reset the wall-clock time. In normal running, this runs with host * time, so let's keep doing that. */ @@ -436,6 +475,8 @@ static int rtc_load(struct domain *d, hv /* Reset the periodic interrupt timer based on the registers */ rtc_timer_update(s); + spin_unlock(&s->lock); + return 0; } @@ -445,6 +486,8 @@ void rtc_init(struct vcpu *v, int base) void rtc_init(struct vcpu *v, int base) { RTCState *s = vcpu_vrtc(v); + + spin_lock_init(&s->lock); s->hw.cmos_data[RTC_REG_A] = RTC_REF_CLCK_32KHZ | 6; /* ~1kHz */ s->hw.cmos_data[RTC_REG_B] = RTC_24H; @@ -452,7 +495,10 @@ void rtc_init(struct vcpu *v, int base) s->hw.cmos_data[RTC_REG_D] = RTC_VRT; s->current_tm = gmtime(get_localtime(v->domain)); + + spin_lock(&s->lock); rtc_copy_date(s); + spin_unlock(&s->lock); init_timer(&s->second_timer, rtc_update_second, s, v->processor); init_timer(&s->second_timer2, rtc_update_second2, s, v->processor); diff -r 3b51eebdf9ab -r 093bc9dcbbca xen/arch/x86/hvm/svm/vmcb.c --- a/xen/arch/x86/hvm/svm/vmcb.c Fri Jun 15 13:33:11 2007 -0600 +++ b/xen/arch/x86/hvm/svm/vmcb.c Sat Jun 16 10:42:06 2007 +0100 @@ -236,6 +236,16 @@ static int construct_vmcb(struct vcpu *v vmcb->g_pat = 0x0007040600070406ULL; /* guest PAT */ vmcb->h_cr3 = pagetable_get_paddr(v->domain->arch.phys_table); vmcb->cr4 = arch_svm->cpu_shadow_cr4 = 0; + + /* No point in intercepting CR0/3/4 reads, because the hardware + * will return the guest versions anyway. */ + vmcb->cr_intercepts &= ~(CR_INTERCEPT_CR0_READ + |CR_INTERCEPT_CR3_READ + |CR_INTERCEPT_CR4_READ); + + /* No point in intercepting INVLPG if we don't have shadow pagetables + * that need to be fixed up. */ + vmcb->general1_intercepts &= ~GENERAL1_INTERCEPT_INVLPG; } else { diff -r 3b51eebdf9ab -r 093bc9dcbbca xen/arch/x86/hvm/vpt.c --- a/xen/arch/x86/hvm/vpt.c Fri Jun 15 13:33:11 2007 -0600 +++ b/xen/arch/x86/hvm/vpt.c Sat Jun 16 10:42:06 2007 +0100 @@ -17,11 +17,31 @@ * Place - Suite 330, Boston, MA 02111-1307 USA. * */ + #include <xen/time.h> #include <asm/hvm/support.h> #include <asm/hvm/vpt.h> #include <asm/event.h> +static void pt_lock(struct periodic_time *pt) +{ + struct vcpu *v; + + for ( ; ; ) + { + v = pt->vcpu; + spin_lock(&v->arch.hvm_vcpu.tm_lock); + if ( likely(pt->vcpu == v) ) + break; + spin_unlock(&v->arch.hvm_vcpu.tm_lock); + } +} + +static void pt_unlock(struct periodic_time *pt) +{ + spin_unlock(&pt->vcpu->arch.hvm_vcpu.tm_lock); +} + static void missed_ticks(struct periodic_time *pt) { s_time_t missed_ticks; @@ -52,16 +72,22 @@ void pt_freeze_time(struct vcpu *v) if ( test_bit(_VPF_blocked, &v->pause_flags) ) return; + spin_lock(&v->arch.hvm_vcpu.tm_lock); + v->arch.hvm_vcpu.guest_time = hvm_get_guest_time(v); list_for_each_entry ( pt, head, list ) stop_timer(&pt->timer); + + spin_unlock(&v->arch.hvm_vcpu.tm_lock); } void pt_thaw_time(struct vcpu *v) { struct list_head *head = &v->arch.hvm_vcpu.tm_list; struct periodic_time *pt; + + spin_lock(&v->arch.hvm_vcpu.tm_lock); if ( v->arch.hvm_vcpu.guest_time ) { @@ -74,11 +100,15 @@ void pt_thaw_time(struct vcpu *v) set_timer(&pt->timer, pt->scheduled); } } + + spin_unlock(&v->arch.hvm_vcpu.tm_lock); } static void pt_timer_fn(void *data) { struct periodic_time *pt = data; + + pt_lock(pt); pt->pending_intr_nr++; pt->scheduled += pt->period; @@ -89,6 +119,8 @@ static void pt_timer_fn(void *data) set_timer(&pt->timer, pt->scheduled); vcpu_kick(pt->vcpu); + + pt_unlock(pt); } void pt_update_irq(struct vcpu *v) @@ -98,6 +130,8 @@ void pt_update_irq(struct vcpu *v) uint64_t max_lag = -1ULL; int irq = -1; + spin_lock(&v->arch.hvm_vcpu.tm_lock); + list_for_each_entry ( pt, head, list ) { if ( !is_isa_irq_masked(v, pt->irq) && pt->pending_intr_nr && @@ -108,6 +142,8 @@ void pt_update_irq(struct vcpu *v) } } + spin_unlock(&v->arch.hvm_vcpu.tm_lock); + if ( is_lvtt(v, irq) ) { vlapic_set_irq(vcpu_vlapic(v), irq, 0); @@ -119,7 +155,7 @@ void pt_update_irq(struct vcpu *v) } } -struct periodic_time *is_pt_irq(struct vcpu *v, int vector, int type) +static struct periodic_time *is_pt_irq(struct vcpu *v, int vector, int type) { struct list_head *head = &v->arch.hvm_vcpu.tm_list; struct periodic_time *pt; @@ -152,25 +188,42 @@ struct periodic_time *is_pt_irq(struct v void pt_intr_post(struct vcpu *v, int vector, int type) { - struct periodic_time *pt = is_pt_irq(v, vector, type); - + struct periodic_time *pt; + time_cb *cb; + void *cb_priv; + + spin_lock(&v->arch.hvm_vcpu.tm_lock); + + pt = is_pt_irq(v, vector, type); if ( pt == NULL ) - return; + { + spin_unlock(&v->arch.hvm_vcpu.tm_lock); + return; + } + + ASSERT(pt->vcpu == v); pt->pending_intr_nr--; pt->last_plt_gtime += pt->period_cycles; - if ( hvm_get_guest_time(pt->vcpu) < pt->last_plt_gtime ) - hvm_set_guest_time(pt->vcpu, pt->last_plt_gtime); - - if ( pt->cb != NULL ) - pt->cb(pt->vcpu, pt->priv); + if ( hvm_get_guest_time(v) < pt->last_plt_gtime ) + hvm_set_guest_time(v, pt->last_plt_gtime); + + cb = pt->cb; + cb_priv = pt->priv; + + spin_unlock(&v->arch.hvm_vcpu.tm_lock); + + if ( cb != NULL ) + cb(v, cb_priv); } void pt_reset(struct vcpu *v) { struct list_head *head = &v->arch.hvm_vcpu.tm_list; struct periodic_time *pt; + + spin_lock(&v->arch.hvm_vcpu.tm_lock); list_for_each_entry ( pt, head, list ) { @@ -182,18 +235,24 @@ void pt_reset(struct vcpu *v) set_timer(&pt->timer, pt->scheduled); } } + + spin_unlock(&v->arch.hvm_vcpu.tm_lock); } void pt_migrate(struct vcpu *v) { struct list_head *head = &v->arch.hvm_vcpu.tm_list; struct periodic_time *pt; + + spin_lock(&v->arch.hvm_vcpu.tm_lock); list_for_each_entry ( pt, head, list ) { if ( pt->enabled ) migrate_timer(&pt->timer, v->processor); } + + spin_unlock(&v->arch.hvm_vcpu.tm_lock); } void create_periodic_time( @@ -201,6 +260,8 @@ void create_periodic_time( uint8_t irq, char one_shot, time_cb *cb, void *data) { destroy_periodic_time(pt); + + spin_lock(&v->arch.hvm_vcpu.tm_lock); init_timer(&pt->timer, pt_timer_fn, pt, v->processor); pt->enabled = 1; @@ -223,6 +284,8 @@ void create_periodic_time( list_add(&pt->list, &v->arch.hvm_vcpu.tm_list); set_timer(&pt->timer, pt->scheduled); + + spin_unlock(&v->arch.hvm_vcpu.tm_lock); } void destroy_periodic_time(struct periodic_time *pt) @@ -230,8 +293,10 @@ void destroy_periodic_time(struct period if ( !pt->enabled ) return; + pt_lock(pt); pt->enabled = 0; pt->pending_intr_nr = 0; list_del(&pt->list); kill_timer(&pt->timer); -} + pt_unlock(pt); +} diff -r 3b51eebdf9ab -r 093bc9dcbbca xen/arch/x86/mm/hap/hap.c --- a/xen/arch/x86/mm/hap/hap.c Fri Jun 15 13:33:11 2007 -0600 +++ b/xen/arch/x86/mm/hap/hap.c Sat Jun 16 10:42:06 2007 +0100 @@ -55,14 +55,14 @@ /* hap code to call when log_dirty is enable. return 0 if no problem found. */ int hap_enable_log_dirty(struct domain *d) { + /* turn on PG_log_dirty bit in paging mode */ hap_lock(d); - /* turn on PG_log_dirty bit in paging mode */ d->arch.paging.mode |= PG_log_dirty; + hap_unlock(d); + /* set l1e entries of P2M table to NOT_WRITABLE. */ p2m_set_flags_global(d, (_PAGE_PRESENT|_PAGE_USER)); - flush_tlb_all_pge(); - hap_unlock(d); - + flush_tlb_mask(d->domain_dirty_cpumask); return 0; } @@ -70,19 +70,20 @@ int hap_disable_log_dirty(struct domain { hap_lock(d); d->arch.paging.mode &= ~PG_log_dirty; + hap_unlock(d); + /* set l1e entries of P2M table with normal mode */ - p2m_set_flags_global(d, __PAGE_HYPERVISOR|_PAGE_USER); - hap_unlock(d); - - return 1; + p2m_set_flags_global(d, __PAGE_HYPERVISOR|_PAGE_USER); + return 0; } void hap_clean_dirty_bitmap(struct domain *d) { /* mark physical memory as NOT_WRITEABLE and flush the TLB */ p2m_set_flags_global(d, (_PAGE_PRESENT|_PAGE_USER)); - flush_tlb_all_pge(); -} + flush_tlb_mask(d->domain_dirty_cpumask); +} + /************************************************/ /* HAP SUPPORT FUNCTIONS */ /************************************************/ @@ -268,6 +269,7 @@ void hap_install_xen_entries_in_l2h(stru { struct domain *d = v->domain; l2_pgentry_t *sl2e; + l3_pgentry_t *p2m; int i; @@ -290,23 +292,18 @@ void hap_install_xen_entries_in_l2h(stru sl2e[l2_table_offset(LINEAR_PT_VIRT_START) + i] = l2e_empty(); - if ( paging_mode_translate(d) ) + /* Install the domain-specific p2m table */ + ASSERT(pagetable_get_pfn(d->arch.phys_table) != 0); + p2m = hap_map_domain_page(pagetable_get_mfn(d->arch.phys_table)); + for ( i = 0; i < MACHPHYS_MBYTES>>1; i++ ) { - /* Install the domain-specific p2m table */ - l3_pgentry_t *p2m; - ASSERT(pagetable_get_pfn(d->arch.phys_table) != 0); - p2m = hap_map_domain_page(pagetable_get_mfn(d->arch.phys_table)); - for ( i = 0; i < MACHPHYS_MBYTES>>1; i++ ) - { - sl2e[l2_table_offset(RO_MPT_VIRT_START) + i] = - (l3e_get_flags(p2m[i]) & _PAGE_PRESENT) - ? l2e_from_pfn(mfn_x(_mfn(l3e_get_pfn(p2m[i]))), - __PAGE_HYPERVISOR) - : l2e_empty(); - } - hap_unmap_domain_page(p2m); - } - + sl2e[l2_table_offset(RO_MPT_VIRT_START) + i] = + (l3e_get_flags(p2m[i]) & _PAGE_PRESENT) + ? l2e_from_pfn(mfn_x(_mfn(l3e_get_pfn(p2m[i]))), + __PAGE_HYPERVISOR) + : l2e_empty(); + } + hap_unmap_domain_page(p2m); hap_unmap_domain_page(sl2e); } #endif @@ -565,61 +562,37 @@ void hap_vcpu_init(struct vcpu *v) /************************************************/ /* HAP PAGING MODE FUNCTIONS */ /************************************************/ -/* In theory, hap should not intercept guest page fault. This function can - * be recycled to handle host/nested page fault, if needed. +/* + * HAP guests can handle page faults (in the guest page tables) without + * needing any action from Xen, so we should not be intercepting them. */ int hap_page_fault(struct vcpu *v, unsigned long va, struct cpu_user_regs *regs) { - HERE_I_AM; + HAP_ERROR("Intercepted a guest #PF (%u:%u) with HAP enabled.\n", + v->domain->domain_id, v->vcpu_id); domain_crash(v->domain); return 0; } -/* called when guest issues a invlpg request. - * Return 1 if need to issue page invalidation on CPU; Return 0 if does not - * need to do so. +/* + * HAP guests can handle invlpg without needing any action from Xen, so + * should not be intercepting it. */ int hap_invlpg(struct vcpu *v, unsigned long va) { - HERE_I_AM; + HAP_ERROR("Intercepted a guest INVLPG (%u:%u) with HAP enabled.\n", + v->domain->domain_id, v->vcpu_id); + domain_crash(v->domain); return 0; } +/* + * HAP guests do not need to take any action on CR3 writes (they are still + * intercepted, so that Xen's copy of the guest's CR3 can be kept in sync.) + */ void hap_update_cr3(struct vcpu *v, int do_locking) { - struct domain *d = v->domain; - mfn_t gmfn; - - HERE_I_AM; - /* Don't do anything on an uninitialised vcpu */ - if ( !is_hvm_domain(d) && !v->is_initialised ) - { - ASSERT(v->arch.cr3 == 0); - return; - } - - if ( do_locking ) - hap_lock(v->domain); - - ASSERT(hap_locked_by_me(v->domain)); - ASSERT(v->arch.paging.mode); - - gmfn = pagetable_get_mfn(v->arch.guest_table); - - make_cr3(v, pagetable_get_pfn(v->arch.monitor_table)); - - hvm_update_guest_cr3(v, pagetable_get_paddr(v->arch.monitor_table)); - - HAP_PRINTK("d=%u v=%u guest_table=%05lx, monitor_table = %05lx\n", - d->domain_id, v->vcpu_id, - (unsigned long)pagetable_get_pfn(v->arch.guest_table), - (unsigned long)pagetable_get_pfn(v->arch.monitor_table)); - - flush_tlb_mask(d->domain_dirty_cpumask); - - if ( do_locking ) - hap_unlock(v->domain); } void hap_update_paging_modes(struct vcpu *v) @@ -647,7 +620,7 @@ void hap_update_paging_modes(struct vcpu v->arch.paging.mode = &hap_paging_real_mode; } - v->arch.paging.translate_enabled = !!hvm_paging_enabled(v); + v->arch.paging.translate_enabled = !!hvm_paging_enabled(v); if ( pagetable_is_null(v->arch.monitor_table) ) { mfn_t mmfn = hap_make_monitor_table(v); @@ -655,7 +628,6 @@ void hap_update_paging_modes(struct vcpu make_cr3(v, mfn_x(mmfn)); } - flush_tlb_mask(d->domain_dirty_cpumask); hap_unlock(d); } @@ -702,29 +674,18 @@ hap_write_p2m_entry(struct vcpu *v, unsi hap_write_p2m_entry(struct vcpu *v, unsigned long gfn, l1_pgentry_t *p, l1_pgentry_t new, unsigned int level) { - int do_locking; - - /* This function can be called from two directions (P2M and log dirty). We - * need to make sure this lock has been held or not. - */ - do_locking = !hap_locked_by_me(v->domain); - - if ( do_locking ) - hap_lock(v->domain); + hap_lock(v->domain); safe_write_pte(p, new); #if CONFIG_PAGING_LEVELS == 3 /* install P2M in monitor table for PAE Xen */ - if ( level == 3 ) { + if ( level == 3 ) /* We have written to the p2m l3: need to sync the per-vcpu * copies of it in the monitor tables */ p2m_install_entry_in_monitors(v->domain, (l3_pgentry_t *)p); - - } #endif - if ( do_locking ) - hap_unlock(v->domain); + hap_unlock(v->domain); } /* Entry points into this mode of the hap code. */ diff -r 3b51eebdf9ab -r 093bc9dcbbca xen/arch/x86/mm/p2m.c --- a/xen/arch/x86/mm/p2m.c Fri Jun 15 13:33:11 2007 -0600 +++ b/xen/arch/x86/mm/p2m.c Sat Jun 16 10:42:06 2007 +0100 @@ -32,9 +32,13 @@ #define P2M_AUDIT 0 #define P2M_DEBUGGING 1 -/* The P2M lock. This protects all updates to the p2m table. +/* + * The P2M lock. This protects all updates to the p2m table. * Updates are expected to be safe against concurrent reads, - * which do *not* require the lock */ + * which do *not* require the lock. + * + * Locking discipline: always acquire this lock before the shadow or HAP one + */ #define p2m_lock_init(_d) \ do { \ diff -r 3b51eebdf9ab -r 093bc9dcbbca xen/common/kexec.c --- a/xen/common/kexec.c Fri Jun 15 13:33:11 2007 -0600 +++ b/xen/common/kexec.c Sat Jun 16 10:42:06 2007 +0100 @@ -19,6 +19,7 @@ #include <asm/atomic.h> #include <xen/spinlock.h> #include <xen/version.h> +#include <xen/console.h> #include <public/elfnote.h> #ifndef COMPAT @@ -110,6 +111,8 @@ void kexec_crash(void) if ( !test_bit(KEXEC_IMAGE_CRASH_BASE + pos, &kexec_flags) ) return; + console_start_sync(); + one_cpu_only(); kexec_crash_save_cpu(); machine_crash_shutdown(); diff -r 3b51eebdf9ab -r 093bc9dcbbca xen/common/timer.c --- a/xen/common/timer.c Fri Jun 15 13:33:11 2007 -0600 +++ b/xen/common/timer.c Sat Jun 16 10:42:06 2007 +0100 @@ -183,7 +183,7 @@ static inline void timer_lock(struct tim static inline void timer_unlock(struct timer *timer) { - spin_unlock(&per_cpu(timers, timer->cpu).lock); + spin_unlock(&per_cpu(timers, timer->cpu).lock); } #define timer_unlock_irq(t) \ diff -r 3b51eebdf9ab -r 093bc9dcbbca xen/include/asm-x86/hvm/vcpu.h --- a/xen/include/asm-x86/hvm/vcpu.h Fri Jun 15 13:33:11 2007 -0600 +++ b/xen/include/asm-x86/hvm/vcpu.h Sat Jun 16 10:42:06 2007 +0100 @@ -35,6 +35,9 @@ struct hvm_vcpu { struct vlapic vlapic; s64 cache_tsc_offset; u64 guest_time; + + /* Lock and list for virtual platform timers. */ + spinlock_t tm_lock; struct list_head tm_list; /* For AP startup */ diff -r 3b51eebdf9ab -r 093bc9dcbbca xen/include/asm-x86/hvm/vpt.h --- a/xen/include/asm-x86/hvm/vpt.h Fri Jun 15 13:33:11 2007 -0600 +++ b/xen/include/asm-x86/hvm/vpt.h Sat Jun 16 10:42:06 2007 +0100 @@ -31,7 +31,6 @@ #include <asm/hvm/vpic.h> #include <public/hvm/save.h> - struct HPETState; struct HPET_timer_fn_info { struct HPETState *hs; @@ -45,6 +44,7 @@ typedef struct HPETState { uint64_t mc_offset; struct timer timers[HPET_TIMER_NUM]; struct HPET_timer_fn_info timer_fn_info[HPET_TIMER_NUM]; + spinlock_t lock; } HPETState; @@ -80,6 +80,7 @@ typedef struct PITState { int64_t count_load_time[3]; /* irq handling */ struct periodic_time pt[3]; + spinlock_t lock; } PITState; typedef struct RTCState { @@ -93,6 +94,7 @@ typedef struct RTCState { struct timer second_timer2; struct periodic_time pt; int32_t time_offset_seconds; + spinlock_t lock; } RTCState; #define FREQUENCE_PMTIMER 3579545 /* Timer should run at 3.579545 MHz */ @@ -102,6 +104,7 @@ typedef struct PMTState { uint64_t last_gtime; /* Last (guest) time we updated the timer */ uint64_t scale; /* Multiplier to get from tsc to timer ticks */ struct timer timer; /* To make sure we send SCIs */ + spinlock_t lock; } PMTState; struct pl_time { /* platform time */ @@ -116,7 +119,6 @@ void pt_freeze_time(struct vcpu *v); void pt_freeze_time(struct vcpu *v); void pt_thaw_time(struct vcpu *v); void pt_update_irq(struct vcpu *v); -struct periodic_time *is_pt_irq(struct vcpu *v, int vector, int type); void pt_intr_post(struct vcpu *v, int vector, int type); void pt_reset(struct vcpu *v); void pt_migrate(struct vcpu *v); _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |