# HG changeset patch
# User Keir Fraser <keir@xxxxxxxxxxxxx>
# Date 1181900191 -3600
# Node ID ba61ec7df6321221450dbe512019c43468891a02
# Parent 9a915873be8c5672bf56fd71117a9eb9e7c69fe6
hvm: Simplify timer<->vcpu/domain conversion in RTC and PIT timer
models. These timers are always bound to vcpu0, where a specific vcpu
matters.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
xen/arch/x86/hvm/i8254.c | 123 +++++++++++++++++++++--------------------------
xen/arch/x86/hvm/rtc.c | 74 +++++++++++++++-------------
2 files changed, 96 insertions(+), 101 deletions(-)
diff -r 9a915873be8c -r ba61ec7df632 xen/arch/x86/hvm/i8254.c
--- a/xen/arch/x86/hvm/i8254.c Fri Jun 15 10:01:32 2007 +0100
+++ b/xen/arch/x86/hvm/i8254.c Fri Jun 15 10:36:31 2007 +0100
@@ -37,6 +37,12 @@
#include <asm/hvm/vpt.h>
#include <asm/current.h>
+#define domain_vpit(d) (&(d)->arch.hvm_domain.pl_time.vpit)
+#define vcpu_vpit(vcpu) (domain_vpit((vcpu)->domain))
+#define vpit_domain(pit) (container_of((pit), struct domain, \
+ arch.hvm_domain.pl_time.vpit))
+#define vpit_vcpu(pit) (vpit_domain(pit)->vcpu[0])
+
#define RW_STATE_LSB 1
#define RW_STATE_MSB 2
#define RW_STATE_WORD0 3
@@ -45,8 +51,8 @@ static int handle_pit_io(ioreq_t *p);
static int handle_pit_io(ioreq_t *p);
static int handle_speaker_io(ioreq_t *p);
-/* compute with 96 bit intermediate result: (a*b)/c */
-uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
+/* Compute with 96 bit intermediate result: (a*b)/c */
+static uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
{
union {
uint64_t ll;
@@ -69,15 +75,16 @@ uint64_t muldiv64(uint64_t a, uint32_t b
return res.ll;
}
-static int pit_get_count(PITState *s, int channel)
+static int pit_get_count(PITState *pit, int channel)
{
uint64_t d;
int counter;
- struct hvm_hw_pit_channel *c = &s->hw.channels[channel];
- struct periodic_time *pt = &s->pt[channel];
-
- d = muldiv64(hvm_get_guest_time(pt->vcpu) - s->count_load_time[channel],
- PIT_FREQ, ticks_per_sec(pt->vcpu));
+ struct hvm_hw_pit_channel *c = &pit->hw.channels[channel];
+ struct vcpu *v = vpit_vcpu(pit);
+
+ d = muldiv64(hvm_get_guest_time(v) - pit->count_load_time[channel],
+ PIT_FREQ, ticks_per_sec(v));
+
switch ( c->mode )
{
case 0:
@@ -97,15 +104,15 @@ static int pit_get_count(PITState *s, in
return counter;
}
-int pit_get_out(PITState *pit, int channel)
+static int pit_get_out(PITState *pit, int channel)
{
struct hvm_hw_pit_channel *s = &pit->hw.channels[channel];
- uint64_t d, current_time;
+ uint64_t d;
int out;
-
- current_time = hvm_get_guest_time(pit->pt[channel].vcpu);
- d = muldiv64(current_time - pit->count_load_time[channel],
- PIT_FREQ, ticks_per_sec(pit->pt[channel].vcpu));
+ struct vcpu *v = vpit_vcpu(pit);
+
+ d = muldiv64(hvm_get_guest_time(v) - pit->count_load_time[channel],
+ PIT_FREQ, ticks_per_sec(v));
switch ( s->mode )
{
@@ -131,11 +138,10 @@ int pit_get_out(PITState *pit, int chann
return out;
}
-/* val must be 0 or 1 */
-void pit_set_gate(PITState *pit, int channel, int val)
+static void pit_set_gate(PITState *pit, int channel, int val)
{
struct hvm_hw_pit_channel *s = &pit->hw.channels[channel];
- struct periodic_time *pt = &pit->pt[channel];
+ struct vcpu *v = vpit_vcpu(pit);
switch ( s->mode )
{
@@ -150,7 +156,7 @@ void pit_set_gate(PITState *pit, int cha
case 3:
/* Restart counting on rising edge. */
if ( s->gate < val )
- pit->count_load_time[channel] = hvm_get_guest_time(pt->vcpu);
+ pit->count_load_time[channel] = hvm_get_guest_time(v);
break;
}
@@ -162,7 +168,7 @@ int pit_get_gate(PITState *pit, int chan
return pit->hw.channels[channel].gate;
}
-void pit_time_fired(struct vcpu *v, void *priv)
+static void pit_time_fired(struct vcpu *v, void *priv)
{
uint64_t *count_load_time = priv;
*count_load_time = hvm_get_guest_time(v);
@@ -173,9 +179,7 @@ static void pit_load_count(PITState *pit
u32 period;
struct hvm_hw_pit_channel *s = &pit->hw.channels[channel];
struct periodic_time *pt = &pit->pt[channel];
- struct domain *d = container_of(pit, struct domain,
- arch.hvm_domain.pl_time.vpit);
- struct vcpu *v;
+ struct vcpu *v = vpit_vcpu(pit);
if ( val == 0 )
val = 0x10000;
@@ -184,14 +188,8 @@ static void pit_load_count(PITState *pit
s->count = val;
period = DIV_ROUND((val * 1000000000ULL), PIT_FREQ);
- if ( !is_hvm_domain(d) || (channel != 0) )
+ if ( (v == NULL) || !is_hvm_vcpu(v) || (channel != 0) )
return;
-
- /* Choose a vcpu to set the timer on: current if appropriate else vcpu 0 */
- if ( pit == ¤t->domain->arch.hvm_domain.pl_time.vpit )
- v = current;
- else
- v = d->vcpu[0];
switch ( s->mode )
{
@@ -235,9 +233,8 @@ static void pit_latch_status(PITState *s
}
}
-static void pit_ioport_write(void *opaque, uint32_t addr, uint32_t val)
-{
- PITState *pit = opaque;
+static void pit_ioport_write(struct PITState *pit, uint32_t addr, uint32_t val)
+{
int channel, access;
struct hvm_hw_pit_channel *s;
@@ -309,9 +306,8 @@ static void pit_ioport_write(void *opaqu
}
}
-static uint32_t pit_ioport_read(void *opaque, uint32_t addr)
-{
- PITState *pit = opaque;
+static uint32_t pit_ioport_read(struct PITState *pit, uint32_t addr)
+{
int ret, count;
struct hvm_hw_pit_channel *s;
@@ -371,7 +367,7 @@ static uint32_t pit_ioport_read(void *op
return ret;
}
-void pit_stop_channel0_irq(PITState * pit)
+void pit_stop_channel0_irq(PITState *pit)
{
destroy_periodic_time(&pit->pt[0]);
}
@@ -425,7 +421,7 @@ static void pit_info(PITState *pit)
static int pit_save(struct domain *d, hvm_domain_context_t *h)
{
- PITState *pit = &d->arch.hvm_domain.pl_time.vpit;
+ PITState *pit = domain_vpit(d);
pit_info(pit);
@@ -435,7 +431,7 @@ static int pit_save(struct domain *d, hv
static int pit_load(struct domain *d, hvm_domain_context_t *h)
{
- PITState *pit = &d->arch.hvm_domain.pl_time.vpit;
+ PITState *pit = domain_vpit(d);
int i;
/* Restore the PIT hardware state */
@@ -457,26 +453,12 @@ static int pit_load(struct domain *d, hv
HVM_REGISTER_SAVE_RESTORE(PIT, pit_save, pit_load, 1, HVMSR_PER_DOM);
-static void pit_reset(void *opaque)
-{
- PITState *pit = opaque;
+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;
-
- for ( i = 0; i < 3; i++ )
- {
- s = &pit->hw.channels[i];
- destroy_periodic_time(&pit->pt[i]);
- s->mode = 0xff; /* the init mode */
- s->gate = (i != 2);
- pit_load_count(pit, i, 0);
- }
-}
-
-void pit_init(struct vcpu *v, unsigned long cpu_khz)
-{
- PITState *pit = &v->domain->arch.hvm_domain.pl_time.vpit;
- struct periodic_time *pt;
pt = &pit->pt[0];
pt[0].vcpu = v;
@@ -487,20 +469,26 @@ void pit_init(struct vcpu *v, unsigned l
/* register the speaker port */
register_portio_handler(v->domain, 0x61, 1, handle_speaker_io);
ticks_per_sec(v) = cpu_khz * (int64_t)1000;
- pit_reset(pit);
+
+ 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);
+ }
}
void pit_deinit(struct domain *d)
{
- PITState *pit = &d->arch.hvm_domain.pl_time.vpit;
+ PITState *pit = domain_vpit(d);
destroy_periodic_time(&pit->pt[0]);
}
/* the intercept action for PIT DM retval:0--not handled; 1--handled */
static int handle_pit_io(ioreq_t *p)
{
- struct vcpu *v = current;
- struct PITState *vpit = &(v->domain->arch.hvm_domain.pl_time.vpit);
+ struct PITState *vpit = vcpu_vpit(current);
if ( (p->size != 1) || p->data_is_ptr || (p->type != IOREQ_TYPE_PIO) )
{
@@ -523,16 +511,16 @@ static int handle_pit_io(ioreq_t *p)
return 1;
}
-static void speaker_ioport_write(void *opaque, uint32_t addr, uint32_t val)
-{
- PITState *pit = opaque;
+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(void *opaque, uint32_t addr)
-{
- PITState *pit = opaque;
+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) |
@@ -541,8 +529,7 @@ static uint32_t speaker_ioport_read(void
static int handle_speaker_io(ioreq_t *p)
{
- struct vcpu *v = current;
- struct PITState *vpit = &(v->domain->arch.hvm_domain.pl_time.vpit);
+ struct PITState *vpit = vcpu_vpit(current);
if ( (p->size != 1) || p->data_is_ptr || (p->type != IOREQ_TYPE_PIO) )
{
diff -r 9a915873be8c -r ba61ec7df632 xen/arch/x86/hvm/rtc.c
--- a/xen/arch/x86/hvm/rtc.c Fri Jun 15 10:01:32 2007 +0100
+++ b/xen/arch/x86/hvm/rtc.c Fri Jun 15 10:36:31 2007 +0100
@@ -28,6 +28,12 @@
#include <asm/hvm/support.h>
#include <asm/current.h>
+#define domain_vrtc(d) (&(d)->arch.hvm_domain.pl_time.vrtc)
+#define vcpu_vrtc(vcpu) (domain_vrtc((vcpu)->domain))
+#define vrtc_domain(rtc) (container_of((rtc), struct domain, \
+ arch.hvm_domain.pl_time.vrtc))
+#define vrtc_vcpu(rtc) (vrtc_domain(rtc)->vcpu[0])
+
void rtc_periodic_cb(struct vcpu *v, void *opaque)
{
RTCState *s = opaque;
@@ -39,15 +45,15 @@ int is_rtc_periodic_irq(void *opaque)
RTCState *s = opaque;
return !(s->hw.cmos_data[RTC_REG_C] & RTC_AF ||
- s->hw.cmos_data[RTC_REG_C] & RTC_UF);
+ s->hw.cmos_data[RTC_REG_C] & RTC_UF);
}
/* Enable/configure/disable the periodic timer based on the RTC_PIE and
* RTC_RATE_SELECT settings */
-static void rtc_timer_update(RTCState *s, struct vcpu *v)
-{
- int period_code;
- int period;
+static void rtc_timer_update(RTCState *s)
+{
+ int period_code, period;
+ struct vcpu *v = vrtc_vcpu(s);
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) )
@@ -104,7 +110,7 @@ static int rtc_ioport_write(void *opaque
/* UIP bit is read only */
s->hw.cmos_data[RTC_REG_A] = (data & ~RTC_UIP) |
(s->hw.cmos_data[RTC_REG_A] & RTC_UIP);
- rtc_timer_update(s, current);
+ rtc_timer_update(s);
break;
case RTC_REG_B:
if ( data & RTC_SET )
@@ -120,7 +126,7 @@ static int rtc_ioport_write(void *opaque
rtc_set_time(s);
}
s->hw.cmos_data[RTC_REG_B] = data;
- rtc_timer_update(s, current);
+ rtc_timer_update(s);
break;
case RTC_REG_C:
case RTC_REG_D:
@@ -174,11 +180,12 @@ static void rtc_copy_date(RTCState *s)
static void rtc_copy_date(RTCState *s)
{
const struct tm *tm = &s->current_tm;
-
- if ( s->time_offset_seconds != s->pt.vcpu->domain->time_offset_seconds )
- {
- s->current_tm = gmtime(get_localtime(s->pt.vcpu->domain));
- s->time_offset_seconds = s->pt.vcpu->domain->time_offset_seconds;
+ struct domain *d = vrtc_domain(s);
+
+ if ( s->time_offset_seconds != d->time_offset_seconds )
+ {
+ s->current_tm = gmtime(get_localtime(d));
+ s->time_offset_seconds = d->time_offset_seconds;
}
s->hw.cmos_data[RTC_SECONDS] = to_bcd(s, tm->tm_sec);
@@ -222,11 +229,12 @@ static void rtc_next_second(RTCState *s)
{
struct tm *tm = &s->current_tm;
int days_in_month;
-
- if ( s->time_offset_seconds != s->pt.vcpu->domain->time_offset_seconds )
- {
- s->current_tm = gmtime(get_localtime(s->pt.vcpu->domain));
- s->time_offset_seconds = s->pt.vcpu->domain->time_offset_seconds;
+ struct domain *d = vrtc_domain(s);
+
+ if ( s->time_offset_seconds != d->time_offset_seconds )
+ {
+ s->current_tm = gmtime(get_localtime(d));
+ s->time_offset_seconds = d->time_offset_seconds;
}
tm->tm_sec++;
@@ -292,6 +300,7 @@ static void rtc_update_second2(void *opa
static void rtc_update_second2(void *opaque)
{
RTCState *s = opaque;
+ struct domain *d = vrtc_domain(s);
if ( !(s->hw.cmos_data[RTC_REG_B] & RTC_SET) )
rtc_copy_date(s);
@@ -310,8 +319,8 @@ static void rtc_update_second2(void *opa
s->current_tm.tm_hour) )
{
s->hw.cmos_data[RTC_REG_C] |= 0xa0;
- hvm_isa_irq_deassert(s->pt.vcpu->domain, RTC_IRQ);
- hvm_isa_irq_assert(s->pt.vcpu->domain, RTC_IRQ);
+ hvm_isa_irq_deassert(d, RTC_IRQ);
+ hvm_isa_irq_assert(d, RTC_IRQ);
}
}
@@ -319,8 +328,8 @@ static void rtc_update_second2(void *opa
if ( s->hw.cmos_data[RTC_REG_B] & RTC_UIE )
{
s->hw.cmos_data[RTC_REG_C] |= 0x90;
- hvm_isa_irq_deassert(s->pt.vcpu->domain, RTC_IRQ);
- hvm_isa_irq_assert(s->pt.vcpu->domain, RTC_IRQ);
+ hvm_isa_irq_deassert(d, RTC_IRQ);
+ hvm_isa_irq_assert(d, RTC_IRQ);
}
/* clear update in progress bit */
@@ -354,8 +363,8 @@ static uint32_t rtc_ioport_read(void *op
break;
case RTC_REG_C:
ret = s->hw.cmos_data[s->hw.cmos_index];
- hvm_isa_irq_deassert(s->pt.vcpu->domain, RTC_IRQ);
- s->hw.cmos_data[RTC_REG_C] = 0x00;
+ hvm_isa_irq_deassert(vrtc_domain(s), RTC_IRQ);
+ s->hw.cmos_data[RTC_REG_C] = 0x00;
break;
default:
ret = s->hw.cmos_data[s->hw.cmos_index];
@@ -367,8 +376,7 @@ static uint32_t rtc_ioport_read(void *op
static int handle_rtc_io(ioreq_t *p)
{
- struct vcpu *v = current;
- struct RTCState *vrtc = &v->domain->arch.hvm_domain.pl_time.vrtc;
+ struct RTCState *vrtc = vcpu_vrtc(current);
if ( (p->size != 1) || p->data_is_ptr || (p->type != IOREQ_TYPE_PIO) )
{
@@ -392,7 +400,7 @@ static int handle_rtc_io(ioreq_t *p)
void rtc_migrate_timers(struct vcpu *v)
{
- RTCState *s = &v->domain->arch.hvm_domain.pl_time.vrtc;
+ RTCState *s = vcpu_vrtc(v);
if ( v->vcpu_id == 0 )
{
@@ -404,13 +412,14 @@ void rtc_migrate_timers(struct vcpu *v)
/* Save RTC hardware state */
static int rtc_save(struct domain *d, hvm_domain_context_t *h)
{
- return hvm_save_entry(RTC, 0, h, &d->arch.hvm_domain.pl_time.vrtc.hw);
+ RTCState *s = domain_vrtc(d);
+ return hvm_save_entry(RTC, 0, h, &s->hw);
}
/* Reload the hardware state from a saved domain */
static int rtc_load(struct domain *d, hvm_domain_context_t *h)
{
- RTCState *s = &d->arch.hvm_domain.pl_time.vrtc;
+ RTCState *s = domain_vrtc(d);
/* Restore the registers */
if ( hvm_load_entry(RTC, h, &s->hw) != 0 )
@@ -425,7 +434,7 @@ static int rtc_load(struct domain *d, hv
set_timer(&s->second_timer2, s->next_second_time);
/* Reset the periodic interrupt timer based on the registers */
- rtc_timer_update(s, d->vcpu[0]);
+ rtc_timer_update(s);
return 0;
}
@@ -435,9 +444,8 @@ HVM_REGISTER_SAVE_RESTORE(RTC, rtc_save,
void rtc_init(struct vcpu *v, int base)
{
- RTCState *s = &v->domain->arch.hvm_domain.pl_time.vrtc;
-
- s->pt.vcpu = v;
+ RTCState *s = vcpu_vrtc(v);
+
s->hw.cmos_data[RTC_REG_A] = RTC_REF_CLCK_32KHZ | 6; /* ~1kHz */
s->hw.cmos_data[RTC_REG_B] = RTC_24H;
s->hw.cmos_data[RTC_REG_C] = 0;
@@ -457,7 +465,7 @@ void rtc_init(struct vcpu *v, int base)
void rtc_deinit(struct domain *d)
{
- RTCState *s = &d->arch.hvm_domain.pl_time.vrtc;
+ RTCState *s = domain_vrtc(d);
destroy_periodic_time(&s->pt);
kill_timer(&s->second_timer);
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|