aboutsummaryrefslogtreecommitdiffstats
path: root/xen/arch/x86/hvm/rtc.c
diff options
context:
space:
mode:
authorkfraser@localhost.localdomain <kfraser@localhost.localdomain>2006-11-21 19:22:25 +0000
committerkfraser@localhost.localdomain <kfraser@localhost.localdomain>2006-11-21 19:22:25 +0000
commitd46c9ce0d7b805e6b4bbf54b381728a391e23e45 (patch)
treeea5cbf1372bb5d4f2dbc953eb70a84a90f4cc7d0 /xen/arch/x86/hvm/rtc.c
parent3b724073d6a410b5a967a6827d2f8c50693aadfb (diff)
downloadxen-d46c9ce0d7b805e6b4bbf54b381728a391e23e45.tar.gz
xen-d46c9ce0d7b805e6b4bbf54b381728a391e23e45.tar.bz2
xen-d46c9ce0d7b805e6b4bbf54b381728a391e23e45.zip
[HVM] Reworked interrupt distribution logic.
TODO: 1. Fix IO-APIC ID to not conflict with LAPIC IDS. 2. Fix i8259 device model (seems to work already though!). 3. Add INTSRC overrides in MPBIOS and ACPI tables so that PCI legacy IRQ routing always ends up at an IO-APIC input with level trigger. Restricting link routing to {5,6,10,11} and setting overrides for all four of those would work. Signed-off-by: Keir Fraser <keir@xensource.com>
Diffstat (limited to 'xen/arch/x86/hvm/rtc.c')
-rw-r--r--xen/arch/x86/hvm/rtc.c272
1 files changed, 141 insertions, 131 deletions
diff --git a/xen/arch/x86/hvm/rtc.c b/xen/arch/x86/hvm/rtc.c
index b669d60dfe..ea7f0ce9df 100644
--- a/xen/arch/x86/hvm/rtc.c
+++ b/xen/arch/x86/hvm/rtc.c
@@ -34,12 +34,10 @@
void rtc_pie_callback(void *opaque)
{
RTCState *s = opaque;
- struct hvm_domain *plat = &s->vcpu->domain->arch.hvm_domain;
- struct vpic *pic = &plat->vpic;
/* Record that we have fired */
s->cmos_data[RTC_REG_C] |= (RTC_IRQF|RTC_PF); /* 0xc0 */
/* Fire */
- pic_set_irq(pic, s->irq, 1);
+ hvm_isa_irq_assert(s->vcpu->domain, s->irq);
/* Remember to fire again */
s->next_pie = NOW() + s->period;
set_timer(&s->pie_timer, s->next_pie);
@@ -53,8 +51,9 @@ static void rtc_timer_update(RTCState *s)
int period;
period_code = s->cmos_data[RTC_REG_A] & RTC_RATE_SELECT;
- if (period_code != 0 && (s->cmos_data[RTC_REG_B] & RTC_PIE)) {
- if (period_code <= 2)
+ if ( (period_code != 0) && (s->cmos_data[RTC_REG_B] & RTC_PIE) )
+ {
+ if ( period_code <= 2 )
period_code += 7;
period = 1 << (period_code - 1); /* period in 32 Khz cycles */
@@ -65,7 +64,9 @@ static void rtc_timer_update(RTCState *s)
#endif
s->next_pie = NOW() + s->period;
set_timer(&s->pie_timer, s->next_pie);
- } else {
+ }
+ else
+ {
stop_timer(&s->pie_timer);
}
}
@@ -76,80 +77,84 @@ static int rtc_ioport_write(void *opaque, uint32_t addr, uint32_t data)
{
RTCState *s = opaque;
- if ((addr & 1) == 0) {
+ if ( (addr & 1) == 0 )
+ {
s->cmos_index = data & 0x7f;
- if (s->cmos_index < RTC_SIZE)
- return 1;
- } else if (s->cmos_index < RTC_SIZE) {
+ return (s->cmos_index < RTC_SIZE);
+ }
+
+ if (s->cmos_index >= RTC_SIZE)
+ return 0;
+
#ifdef DEBUG_RTC
- printk("HVM_RTC: write index=0x%02x val=0x%02x\n",
- s->cmos_index, data);
-#endif
- switch(s->cmos_index) {
- case RTC_SECONDS_ALARM:
- case RTC_MINUTES_ALARM:
- case RTC_HOURS_ALARM:
- s->cmos_data[s->cmos_index] = data;
- break;
- case RTC_SECONDS:
- case RTC_MINUTES:
- case RTC_HOURS:
- case RTC_DAY_OF_WEEK:
- case RTC_DAY_OF_MONTH:
- case RTC_MONTH:
- case RTC_YEAR:
- s->cmos_data[s->cmos_index] = data;
- /* if in set mode, do not update the time */
- if (!(s->cmos_data[RTC_REG_B] & RTC_SET)) {
+ printk("HVM_RTC: write index=0x%02x val=0x%02x\n",
+ s->cmos_index, data);
+#endif
+
+ switch ( s->cmos_index )
+ {
+ case RTC_SECONDS_ALARM:
+ case RTC_MINUTES_ALARM:
+ case RTC_HOURS_ALARM:
+ s->cmos_data[s->cmos_index] = data;
+ break;
+ case RTC_SECONDS:
+ case RTC_MINUTES:
+ case RTC_HOURS:
+ case RTC_DAY_OF_WEEK:
+ case RTC_DAY_OF_MONTH:
+ case RTC_MONTH:
+ case RTC_YEAR:
+ s->cmos_data[s->cmos_index] = data;
+ /* if in set mode, do not update the time */
+ if ( !(s->cmos_data[RTC_REG_B] & RTC_SET) )
+ rtc_set_time(s);
+ break;
+ case RTC_REG_A:
+ /* UIP bit is read only */
+ s->cmos_data[RTC_REG_A] = (data & ~RTC_UIP) |
+ (s->cmos_data[RTC_REG_A] & RTC_UIP);
+ rtc_timer_update(s);
+ break;
+ case RTC_REG_B:
+ if ( data & RTC_SET )
+ {
+ /* set mode: reset UIP mode */
+ s->cmos_data[RTC_REG_A] &= ~RTC_UIP;
+ data &= ~RTC_UIE;
+ }
+ else
+ {
+ /* if disabling set mode, update the time */
+ if ( s->cmos_data[RTC_REG_B] & RTC_SET )
rtc_set_time(s);
- }
- break;
- case RTC_REG_A:
- /* UIP bit is read only */
- s->cmos_data[RTC_REG_A] = (data & ~RTC_UIP) |
- (s->cmos_data[RTC_REG_A] & RTC_UIP);
- rtc_timer_update(s);
- break;
- case RTC_REG_B:
- if (data & RTC_SET) {
- /* set mode: reset UIP mode */
- s->cmos_data[RTC_REG_A] &= ~RTC_UIP;
- data &= ~RTC_UIE;
- } else {
- /* if disabling set mode, update the time */
- if (s->cmos_data[RTC_REG_B] & RTC_SET) {
- rtc_set_time(s);
- }
- }
- s->cmos_data[RTC_REG_B] = data;
- rtc_timer_update(s);
- break;
- case RTC_REG_C:
- case RTC_REG_D:
- /* cannot write to them */
- break;
}
- return 1;
+ s->cmos_data[RTC_REG_B] = data;
+ rtc_timer_update(s);
+ break;
+ case RTC_REG_C:
+ case RTC_REG_D:
+ /* cannot write to them */
+ break;
}
- return 0;
+
+ return 1;
}
static inline int to_bcd(RTCState *s, int a)
{
- if (s->cmos_data[RTC_REG_B] & 0x04) {
+ if ( s->cmos_data[RTC_REG_B] & 0x04 )
return a;
- } else {
+ else
return ((a / 10) << 4) | (a % 10);
- }
}
static inline int from_bcd(RTCState *s, int a)
{
- if (s->cmos_data[RTC_REG_B] & 0x04) {
+ if ( s->cmos_data[RTC_REG_B] & 0x04 )
return a;
- } else {
+ else
return ((a >> 4) * 10) + (a & 0x0f);
- }
}
static void rtc_set_time(RTCState *s)
@@ -159,10 +164,9 @@ static void rtc_set_time(RTCState *s)
tm->tm_sec = from_bcd(s, s->cmos_data[RTC_SECONDS]);
tm->tm_min = from_bcd(s, s->cmos_data[RTC_MINUTES]);
tm->tm_hour = from_bcd(s, s->cmos_data[RTC_HOURS] & 0x7f);
- if (!(s->cmos_data[RTC_REG_B] & 0x02) &&
- (s->cmos_data[RTC_HOURS] & 0x80)) {
+ if ( !(s->cmos_data[RTC_REG_B] & 0x02) &&
+ (s->cmos_data[RTC_HOURS] & 0x80) )
tm->tm_hour += 12;
- }
tm->tm_wday = from_bcd(s, s->cmos_data[RTC_DAY_OF_WEEK]);
tm->tm_mday = from_bcd(s, s->cmos_data[RTC_DAY_OF_MONTH]);
tm->tm_mon = from_bcd(s, s->cmos_data[RTC_MONTH]) - 1;
@@ -175,13 +179,16 @@ static void rtc_copy_date(RTCState *s)
s->cmos_data[RTC_SECONDS] = to_bcd(s, tm->tm_sec);
s->cmos_data[RTC_MINUTES] = to_bcd(s, tm->tm_min);
- if (s->cmos_data[RTC_REG_B] & RTC_24H) {
+ if ( s->cmos_data[RTC_REG_B] & RTC_24H )
+ {
/* 24 hour format */
s->cmos_data[RTC_HOURS] = to_bcd(s, tm->tm_hour);
- } else {
+ }
+ else
+ {
/* 12 hour format */
s->cmos_data[RTC_HOURS] = to_bcd(s, tm->tm_hour % 12);
- if (tm->tm_hour >= 12)
+ if ( tm->tm_hour >= 12 )
s->cmos_data[RTC_HOURS] |= 0x80;
}
s->cmos_data[RTC_DAY_OF_WEEK] = to_bcd(s, tm->tm_wday);
@@ -197,13 +204,12 @@ static int get_days_in_month(int month, int year)
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
int d;
- if ((unsigned )month >= 12)
+ if ( (unsigned)month >= 12 )
return 31;
d = days_tab[month];
- if (month == 1) {
- if ((year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0))
+ if ( month == 1 )
+ if ( (year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0) )
d++;
- }
return d;
}
@@ -248,16 +254,18 @@ static void rtc_update_second(void *opaque)
RTCState *s = opaque;
/* if the oscillator is not in normal operation, we do not update */
- if ((s->cmos_data[RTC_REG_A] & RTC_DIV_CTL) != RTC_REF_CLCK_32KHZ) {
+ if ( (s->cmos_data[RTC_REG_A] & RTC_DIV_CTL) != RTC_REF_CLCK_32KHZ )
+ {
s->next_second_time += 1000000000ULL;
set_timer(&s->second_timer, s->next_second_time);
- } else {
+ }
+ else
+ {
rtc_next_second(&s->current_tm);
- if (!(s->cmos_data[RTC_REG_B] & RTC_SET)) {
- /* update in progress bit */
+ if ( !(s->cmos_data[RTC_REG_B] & RTC_SET) )
s->cmos_data[RTC_REG_A] |= RTC_UIP;
- }
+
/* Delay time before update cycle */
set_timer(&s->second_timer2, s->next_second_time + 244000);
}
@@ -266,33 +274,32 @@ static void rtc_update_second(void *opaque)
static void rtc_update_second2(void *opaque)
{
RTCState *s = opaque;
- struct hvm_domain *plat = &s->vcpu->domain->arch.hvm_domain;
- struct vpic *pic = &plat->vpic;
- if (!(s->cmos_data[RTC_REG_B] & RTC_SET)) {
+ if ( !(s->cmos_data[RTC_REG_B] & RTC_SET) )
rtc_copy_date(s);
- }
/* check alarm */
- if (s->cmos_data[RTC_REG_B] & RTC_AIE) {
- if (((s->cmos_data[RTC_SECONDS_ALARM] & 0xc0) == 0xc0 ||
- s->cmos_data[RTC_SECONDS_ALARM] == s->current_tm.tm_sec) &&
- ((s->cmos_data[RTC_MINUTES_ALARM] & 0xc0) == 0xc0 ||
- s->cmos_data[RTC_MINUTES_ALARM] == s->current_tm.tm_mon) &&
- ((s->cmos_data[RTC_HOURS_ALARM] & 0xc0) == 0xc0 ||
- s->cmos_data[RTC_HOURS_ALARM] == s->current_tm.tm_hour)) {
-
+ if ( s->cmos_data[RTC_REG_B] & RTC_AIE )
+ {
+ if ( ((s->cmos_data[RTC_SECONDS_ALARM] & 0xc0) == 0xc0 ||
+ s->cmos_data[RTC_SECONDS_ALARM] == s->current_tm.tm_sec) &&
+ ((s->cmos_data[RTC_MINUTES_ALARM] & 0xc0) == 0xc0 ||
+ s->cmos_data[RTC_MINUTES_ALARM] == s->current_tm.tm_mon) &&
+ ((s->cmos_data[RTC_HOURS_ALARM] & 0xc0) == 0xc0 ||
+ s->cmos_data[RTC_HOURS_ALARM] == s->current_tm.tm_hour) )
+ {
s->cmos_data[RTC_REG_C] |= 0xa0;
- pic_set_irq(pic, s->irq, 0);
- pic_set_irq(pic, s->irq, 1);
+ hvm_isa_irq_deassert(s->vcpu->domain, s->irq);
+ hvm_isa_irq_assert(s->vcpu->domain, s->irq);
}
}
/* update ended interrupt */
- if (s->cmos_data[RTC_REG_B] & RTC_UIE) {
+ if ( s->cmos_data[RTC_REG_B] & RTC_UIE )
+ {
s->cmos_data[RTC_REG_C] |= 0x90;
- pic_set_irq(pic, s->irq, 0);
- pic_set_irq(pic, s->irq, 1);
+ hvm_isa_irq_deassert(s->vcpu->domain, s->irq);
+ hvm_isa_irq_assert(s->vcpu->domain, s->irq);
}
/* clear update in progress bit */
@@ -305,41 +312,41 @@ static void rtc_update_second2(void *opaque)
static uint32_t rtc_ioport_read(void *opaque, uint32_t addr)
{
RTCState *s = opaque;
- struct hvm_domain *plat = &s->vcpu->domain->arch.hvm_domain;
- struct vpic *pic = &plat->vpic;
int ret;
- if ((addr & 1) == 0) {
+ if ( (addr & 1) == 0 )
return 0xff;
- } else {
- switch(s->cmos_index) {
- case RTC_SECONDS:
- case RTC_MINUTES:
- case RTC_HOURS:
- case RTC_DAY_OF_WEEK:
- case RTC_DAY_OF_MONTH:
- case RTC_MONTH:
- case RTC_YEAR:
- ret = s->cmos_data[s->cmos_index];
- break;
- case RTC_REG_A:
- ret = s->cmos_data[s->cmos_index];
- break;
- case RTC_REG_C:
- ret = s->cmos_data[s->cmos_index];
- pic_set_irq(pic, s->irq, 0);
- s->cmos_data[RTC_REG_C] = 0x00;
- break;
- default:
- ret = s->cmos_data[s->cmos_index];
- break;
- }
+
+ switch ( s->cmos_index )
+ {
+ case RTC_SECONDS:
+ case RTC_MINUTES:
+ case RTC_HOURS:
+ case RTC_DAY_OF_WEEK:
+ case RTC_DAY_OF_MONTH:
+ case RTC_MONTH:
+ case RTC_YEAR:
+ ret = s->cmos_data[s->cmos_index];
+ break;
+ case RTC_REG_A:
+ ret = s->cmos_data[s->cmos_index];
+ break;
+ case RTC_REG_C:
+ ret = s->cmos_data[s->cmos_index];
+ hvm_isa_irq_deassert(s->vcpu->domain, s->irq);
+ s->cmos_data[RTC_REG_C] = 0x00;
+ break;
+ default:
+ ret = s->cmos_data[s->cmos_index];
+ break;
+ }
+
#ifdef DEBUG_RTC
- printk("HVM_RTC: read index=0x%02x val=0x%02x\n",
- s->cmos_index, ret);
+ printk("HVM_RTC: read index=0x%02x val=0x%02x\n",
+ s->cmos_index, ret);
#endif
- return ret;
- }
+
+ return ret;
}
static int handle_rtc_io(ioreq_t *p)
@@ -347,20 +354,23 @@ static int handle_rtc_io(ioreq_t *p)
struct vcpu *v = current;
struct RTCState *vrtc = &v->domain->arch.hvm_domain.pl_time.vrtc;
- if (p->size != 1 ||
- p->data_is_ptr ||
- p->type != IOREQ_TYPE_PIO){
+ if ( (p->size != 1) || p->data_is_ptr || (p->type != IOREQ_TYPE_PIO) )
+ {
printk("HVM_RTC: wrong RTC IO!\n");
return 1;
}
- if (p->dir == 0) { /* write */
- if (rtc_ioport_write(vrtc, p->addr, p->data & 0xFF))
+ if ( p->dir == 0 ) /* write */
+ {
+ if ( rtc_ioport_write(vrtc, p->addr, p->data & 0xFF) )
return 1;
- } else if (p->dir == 1 && vrtc->cmos_index < RTC_SIZE) { /* read */
+ }
+ else if ( (p->dir == 1) && (vrtc->cmos_index < RTC_SIZE) ) /* read */
+ {
p->data = rtc_ioport_read(vrtc, p->addr);
return 1;
}
+
return 0;
}