Jan Beulich
2013-Jan-23 07:28 UTC
[PATCH 0/6] x86/HVM: miscellaneous RTC emulation adjustments
Finally I got around to breaking up the similarly named monolithic patch that caused a regression shortly before the 4.2 release and got therefore reverted. This series consists of the broken up pieces that - according to my testing - don''t expose the reported lockup; the 7th will need debugging to understand what''s wrong there. 1: use RTC_* names instead of literal numbers 2: consolidate toggling of RTC IRQ 3: adjust rtc_timer_update() 4: fix RTC hour conversions 5: used cached original value in RTC_REG_B writing code 6: generalize IRQ raising on RTC_REG_B writes Signed-off-by: Jan Beulich <jbeulich@suse.com>
Jan Beulich
2013-Jan-23 08:08 UTC
[PATCH 1/6] x86/HVM: use RTC_* names instead of literal numbers
Signed-off-by: Jan Beulich <jbeulich@suse.com>
--- a/xen/arch/x86/hvm/rtc.c
+++ b/xen/arch/x86/hvm/rtc.c
@@ -53,8 +53,9 @@ static inline int convert_hour(RTCState
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;
+ s->hw.cmos_data[RTC_REG_C] |= RTC_PF | RTC_IRQF;
spin_unlock(&s->lock);
}
@@ -463,7 +464,7 @@ static int rtc_ioport_write(void *opaque
static inline int to_bcd(RTCState *s, int a)
{
- if ( s->hw.cmos_data[RTC_REG_B] & 0x04 )
+ if ( s->hw.cmos_data[RTC_REG_B] & RTC_DM_BINARY )
return a;
else
return ((a / 10) << 4) | (a % 10);
@@ -471,7 +472,7 @@ static inline int to_bcd(RTCState *s, in
static inline int from_bcd(RTCState *s, int a)
{
- if ( s->hw.cmos_data[RTC_REG_B] & 0x04 )
+ if ( s->hw.cmos_data[RTC_REG_B] & RTC_DM_BINARY )
return a;
else
return ((a >> 4) * 10) + (a & 0x0f);
Signed-off-by: Jan Beulich <jbeulich@suse.com>
--- a/xen/arch/x86/hvm/rtc.c
+++ b/xen/arch/x86/hvm/rtc.c
@@ -50,6 +50,16 @@ static void rtc_set_time(RTCState *s);
static inline int from_bcd(RTCState *s, int a);
static inline int convert_hour(RTCState *s, int hour);
+static void rtc_toggle_irq(RTCState *s)
+{
+ struct domain *d = vrtc_domain(s);
+
+ ASSERT(spin_is_locked(&s->lock));
+ s->hw.cmos_data[RTC_REG_C] |= RTC_IRQF;
+ hvm_isa_irq_deassert(d, RTC_IRQ);
+ hvm_isa_irq_assert(d, RTC_IRQ);
+}
+
static void rtc_periodic_cb(struct vcpu *v, void *opaque)
{
RTCState *s = opaque;
@@ -145,7 +155,6 @@ static void rtc_update_timer(void *opaqu
static void rtc_update_timer2(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))
@@ -153,11 +162,7 @@ static void rtc_update_timer2(void *opaq
s->hw.cmos_data[RTC_REG_C] |= RTC_UF;
s->hw.cmos_data[RTC_REG_A] &= ~RTC_UIP;
if ((s->hw.cmos_data[RTC_REG_B] & RTC_UIE))
- {
- s->hw.cmos_data[RTC_REG_C] |= RTC_IRQF;
- hvm_isa_irq_deassert(d, RTC_IRQ);
- hvm_isa_irq_assert(d, RTC_IRQ);
- }
+ rtc_toggle_irq(s);
check_update_timer(s);
}
spin_unlock(&s->lock);
@@ -344,7 +349,6 @@ static void alarm_timer_update(RTCState
static void rtc_alarm_cb(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))
@@ -352,11 +356,7 @@ static void rtc_alarm_cb(void *opaque)
s->hw.cmos_data[RTC_REG_C] |= RTC_AF;
/* alarm interrupt */
if (s->hw.cmos_data[RTC_REG_B] & RTC_AIE)
- {
- s->hw.cmos_data[RTC_REG_C] |= RTC_IRQF;
- hvm_isa_irq_deassert(d, RTC_IRQ);
- hvm_isa_irq_assert(d, RTC_IRQ);
- }
+ rtc_toggle_irq(s);
alarm_timer_update(s);
}
spin_unlock(&s->lock);
@@ -442,8 +442,7 @@ static int rtc_ioport_write(void *opaque
if ((data & RTC_UIE) && !(s->hw.cmos_data[RTC_REG_B]
& RTC_UIE))
if (s->hw.cmos_data[RTC_REG_C] & RTC_UF)
{
- hvm_isa_irq_deassert(d, RTC_IRQ);
- hvm_isa_irq_assert(d, RTC_IRQ);
+ rtc_toggle_irq(s);
}
s->hw.cmos_data[RTC_REG_B] = data;
if ( (data ^ orig) & RTC_PIE )
Don''t look at RTC_PIE in rtc_timer_update(), and hence don''t
call the
function on REG_B writes at all.
Also handle the two other possible clock bases.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
--- a/xen/arch/x86/hvm/rtc.c
+++ b/xen/arch/x86/hvm/rtc.c
@@ -79,19 +79,26 @@ static void rtc_timer_update(RTCState *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) )
+ switch ( s->hw.cmos_data[RTC_REG_A] & RTC_DIV_CTL )
{
- if ( period_code <= 2 )
+ case RTC_REF_CLCK_32KHZ:
+ if ( (period_code != 0) && (period_code <= 2) )
period_code += 7;
-
- period = 1 << (period_code - 1); /* period in 32 Khz cycles */
- period = DIV_ROUND((period * 1000000000ULL), 32768); /* period in ns */
- create_periodic_time(v, &s->pt, period, period, RTC_IRQ,
- rtc_periodic_cb, s);
- }
- else
- {
+ /* fall through */
+ case RTC_REF_CLCK_1MHZ:
+ case RTC_REF_CLCK_4MHZ:
+ if ( period_code != 0 )
+ {
+ period = 1 << (period_code - 1); /* period in 32 Khz cycles
*/
+ period = DIV_ROUND(period * 1000000000ULL, 32768); /* in ns */
+ create_periodic_time(v, &s->pt, period, period, RTC_IRQ,
+ rtc_periodic_cb, s);
+ break;
+ }
+ /* fall through */
+ default:
destroy_periodic_time(&s->pt);
+ break;
}
}
@@ -445,8 +452,6 @@ static int rtc_ioport_write(void *opaque
rtc_toggle_irq(s);
}
s->hw.cmos_data[RTC_REG_B] = data;
- if ( (data ^ orig) & RTC_PIE )
- rtc_timer_update(s);
check_update_timer(s);
alarm_timer_update(s);
break;
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel
Properly mask off bit 7 when retrieving the hour values in
alarm_timer_update(), and properly use RTC_HOURS_ALARM''s bit 7 when
converting from 12- to 24-hour value.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
--- a/xen/arch/x86/hvm/rtc.c
+++ b/xen/arch/x86/hvm/rtc.c
@@ -196,13 +196,11 @@ static void alarm_timer_update(RTCState
alarm_sec = from_bcd(s, s->hw.cmos_data[RTC_SECONDS_ALARM]);
alarm_min = from_bcd(s, s->hw.cmos_data[RTC_MINUTES_ALARM]);
- alarm_hour = from_bcd(s, s->hw.cmos_data[RTC_HOURS_ALARM]);
- alarm_hour = convert_hour(s, alarm_hour);
+ alarm_hour = convert_hour(s, s->hw.cmos_data[RTC_HOURS_ALARM]);
cur_sec = from_bcd(s, s->hw.cmos_data[RTC_SECONDS]);
cur_min = from_bcd(s, s->hw.cmos_data[RTC_MINUTES]);
- cur_hour = from_bcd(s, s->hw.cmos_data[RTC_HOURS]);
- cur_hour = convert_hour(s, cur_hour);
+ cur_hour = convert_hour(s, s->hw.cmos_data[RTC_HOURS]);
next_update_time = USEC_PER_SEC - (get_localtime_us(d) % USEC_PER_SEC);
next_update_time = next_update_time * NS_PER_USEC + NOW();
@@ -484,12 +482,14 @@ static inline int from_bcd(RTCState *s,
/* Hours in 12 hour mode are in 1-12 range, not 0-11.
* So we need convert it before using it*/
-static inline int convert_hour(RTCState *s, int hour)
+static inline int convert_hour(RTCState *s, int raw)
{
+ int hour = from_bcd(s, raw & 0x7f);
+
if (!(s->hw.cmos_data[RTC_REG_B] & RTC_24H))
{
hour %= 12;
- if (s->hw.cmos_data[RTC_HOURS] & 0x80)
+ if (raw & 0x80)
hour += 12;
}
return hour;
@@ -508,8 +508,7 @@ static void rtc_set_time(RTCState *s)
tm->tm_sec = from_bcd(s, s->hw.cmos_data[RTC_SECONDS]);
tm->tm_min = from_bcd(s, s->hw.cmos_data[RTC_MINUTES]);
- tm->tm_hour = from_bcd(s, s->hw.cmos_data[RTC_HOURS] & 0x7f);
- tm->tm_hour = convert_hour(s, tm->tm_hour);
+ tm->tm_hour = convert_hour(s, s->hw.cmos_data[RTC_HOURS]);
tm->tm_wday = from_bcd(s, s->hw.cmos_data[RTC_DAY_OF_WEEK]);
tm->tm_mday = from_bcd(s, s->hw.cmos_data[RTC_DAY_OF_MONTH]);
tm->tm_mon = from_bcd(s, s->hw.cmos_data[RTC_MONTH]) - 1;
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel
Jan Beulich
2013-Jan-23 08:11 UTC
[PATCH 5/6] x86/HVM: use cached original value in RTC_REG_B writing code
Signed-off-by: Jan Beulich <jbeulich@suse.com>
--- a/xen/arch/x86/hvm/rtc.c
+++ b/xen/arch/x86/hvm/rtc.c
@@ -430,7 +430,7 @@ static int rtc_ioport_write(void *opaque
/* set mode: reset UIP mode */
s->hw.cmos_data[RTC_REG_A] &= ~RTC_UIP;
/* adjust cmos before stopping */
- if (!(s->hw.cmos_data[RTC_REG_B] & RTC_SET))
+ if (!(orig & RTC_SET))
{
s->current_tm = gmtime(get_localtime(d));
rtc_copy_date(s);
@@ -439,12 +439,12 @@ static int rtc_ioport_write(void *opaque
else
{
/* if disabling set mode, update the time */
- if ( s->hw.cmos_data[RTC_REG_B] & RTC_SET )
+ if ( orig & RTC_SET )
rtc_set_time(s);
}
/* if the interrupt is already set when the interrupt become
* enabled, raise an interrupt immediately*/
- if ((data & RTC_UIE) && !(s->hw.cmos_data[RTC_REG_B]
& RTC_UIE))
+ if ((data & RTC_UIE) && !(orig & RTC_UIE))
if (s->hw.cmos_data[RTC_REG_C] & RTC_UF)
{
rtc_toggle_irq(s);
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel
Jan Beulich
2013-Jan-23 08:12 UTC
[PATCH 6/6] x86/HVM: generalize IRQ raising on RTC_REG_B writes
Raise the RTC IRQ not only when UIE gets set while UF was already set,
but generalize this to cover AIE and PIE as well.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
--- a/xen/arch/x86/hvm/rtc.c
+++ b/xen/arch/x86/hvm/rtc.c
@@ -371,7 +371,7 @@ static int rtc_ioport_write(void *opaque
{
RTCState *s = opaque;
struct domain *d = vrtc_domain(s);
- uint32_t orig;
+ uint32_t orig, mask;
spin_lock(&s->lock);
@@ -442,12 +442,17 @@ static int rtc_ioport_write(void *opaque
if ( orig & RTC_SET )
rtc_set_time(s);
}
- /* if the interrupt is already set when the interrupt become
- * enabled, raise an interrupt immediately*/
- if ((data & RTC_UIE) && !(orig & RTC_UIE))
- if (s->hw.cmos_data[RTC_REG_C] & RTC_UF)
+ /*
+ * If the interrupt is already set when the interrupt becomes
+ * enabled, raise an interrupt immediately.
+ * NB: RTC_{A,P,U}IE == RTC_{A,P,U}F respectively.
+ */
+ for ( mask = RTC_UIE; mask <= RTC_PIE; mask <<= 1 )
+ if ( (data & mask) && !(orig & mask) &&
+ (s->hw.cmos_data[RTC_REG_C] & mask) )
{
rtc_toggle_irq(s);
+ break;
}
s->hw.cmos_data[RTC_REG_B] = data;
check_update_timer(s);
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel
Keir Fraser
2013-Jan-23 09:38 UTC
Re: [PATCH 2/6] x86/HVM: consolidate toggling of RTC IRQ
On 23/01/2013 08:09, "Jan Beulich" <JBeulich@suse.com> wrote:> @@ -442,8 +442,7 @@ static int rtc_ioport_write(void *opaque > if ((data & RTC_UIE) && !(s->hw.cmos_data[RTC_REG_B] & RTC_UIE)) > if (s->hw.cmos_data[RTC_REG_C] & RTC_UF) > { > - hvm_isa_irq_deassert(d, RTC_IRQ); > - hvm_isa_irq_assert(d, RTC_IRQ); > + rtc_toggle_irq(s); > }Was it a bug that RTC_IRQF was not being set here before? Changeset comment should mention it is a bugfix as well as code reorganisation in that case. -- Keir
Keir Fraser
2013-Jan-23 09:39 UTC
Re: [PATCH 0/6] x86/HVM: miscellaneous RTC emulation adjustments
On 23/01/2013 07:28, "Jan Beulich" <JBeulich@suse.com> wrote:> Finally I got around to breaking up the similarly named monolithic > patch that caused a regression shortly before the 4.2 release and > got therefore reverted. This series consists of the broken up > pieces that - according to my testing - don''t expose the reported > lockup; the 7th will need debugging to understand what''s wrong > there. > > 1: use RTC_* names instead of literal numbers > 2: consolidate toggling of RTC IRQ > 3: adjust rtc_timer_update() > 4: fix RTC hour conversions > 5: used cached original value in RTC_REG_B writing code > 6: generalize IRQ raising on RTC_REG_B writes > > Signed-off-by: Jan Beulich <jbeulich@suse.com>Apart from minor comment on patch 2: Acked-by: Keir Fraser <keir@xen.org>> > _______________________________________________ > Xen-devel mailing list > Xen-devel@lists.xen.org > http://lists.xen.org/xen-devel
Jan Beulich
2013-Jan-23 09:54 UTC
Re: [PATCH 2/6] x86/HVM: consolidate toggling of RTC IRQ
>>> On 23.01.13 at 10:38, Keir Fraser <keir@xen.org> wrote: > On 23/01/2013 08:09, "Jan Beulich" <JBeulich@suse.com> wrote: > >> @@ -442,8 +442,7 @@ static int rtc_ioport_write(void *opaque >> if ((data & RTC_UIE) && !(s->hw.cmos_data[RTC_REG_B] & RTC_UIE)) >> if (s->hw.cmos_data[RTC_REG_C] & RTC_UF) >> { >> - hvm_isa_irq_deassert(d, RTC_IRQ); >> - hvm_isa_irq_assert(d, RTC_IRQ); >> + rtc_toggle_irq(s); >> } > > Was it a bug that RTC_IRQF was not being set here before?I think so.> Changeset comment > should mention it is a bugfix as well as code reorganisation in that case.Will do: "Note that in the RTC_UIE/RTC_UF case, this also fixes the lack of setting RTC_IRQF." Jan
Keir Fraser
2013-Jan-23 10:09 UTC
Re: [PATCH 2/6] x86/HVM: consolidate toggling of RTC IRQ
On 23/01/2013 09:54, "Jan Beulich" <JBeulich@suse.com> wrote:>>>> On 23.01.13 at 10:38, Keir Fraser <keir@xen.org> wrote: >> On 23/01/2013 08:09, "Jan Beulich" <JBeulich@suse.com> wrote: >> >>> @@ -442,8 +442,7 @@ static int rtc_ioport_write(void *opaque >>> if ((data & RTC_UIE) && !(s->hw.cmos_data[RTC_REG_B] & RTC_UIE)) >>> if (s->hw.cmos_data[RTC_REG_C] & RTC_UF) >>> { >>> - hvm_isa_irq_deassert(d, RTC_IRQ); >>> - hvm_isa_irq_assert(d, RTC_IRQ); >>> + rtc_toggle_irq(s); >>> } >> >> Was it a bug that RTC_IRQF was not being set here before? > > I think so. > >> Changeset comment >> should mention it is a bugfix as well as code reorganisation in that case. > > Will do: > > "Note that in the RTC_UIE/RTC_UF case, this also fixes the lack of > setting RTC_IRQF."Great, thanks. -- Keir> Jan > > > _______________________________________________ > Xen-devel mailing list > Xen-devel@lists.xen.org > http://lists.xen.org/xen-devel
Maybe Matching Threads
- Big Bug:Time in VM running on xen goes slower
- [PATCH v3 0/6] initial suspend support
- [PATCH 3/5] RTC: Add UIP(update in progress) check logic
- [PATCH] hvm: Correct RTC time offset update error due to tm->tm_year
- [PATCH 00/14] Remove old_portio users for memory region PIO mapping