mc146818rtc: embrace all x86 specific code

Introduce a function, rtc_policy_slew_deliver_irq(), which delivers
irq if LOST_TICK_POLICY_SLEW is used, as which is only supported on
x86, other platforms call it will trigger a assert

After that, we can move the x86 specific code to the common place

Signed-off-by: Xiao Guangrong <xiaoguangrong@tencent.com>
Message-Id: <20170510083259.3900-6-xiaoguangrong@tencent.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Xiao Guangrong 2017-05-10 16:32:59 +08:00 committed by Paolo Bonzini
parent 388ad5d296
commit e0c8b950d1

View File

@ -125,17 +125,34 @@ static void rtc_coalesced_timer_update(RTCState *s)
}
}
static QLIST_HEAD(, RTCState) rtc_devices =
QLIST_HEAD_INITIALIZER(rtc_devices);
#ifdef TARGET_I386
void qmp_rtc_reset_reinjection(Error **errp)
{
RTCState *s;
QLIST_FOREACH(s, &rtc_devices, link) {
s->irq_coalesced = 0;
}
}
static bool rtc_policy_slew_deliver_irq(RTCState *s)
{
apic_reset_irq_delivered();
qemu_irq_raise(s->irq);
return apic_get_irq_delivered();
}
static void rtc_coalesced_timer(void *opaque)
{
RTCState *s = opaque;
if (s->irq_coalesced != 0) {
apic_reset_irq_delivered();
s->cmos_data[RTC_REG_C] |= 0xc0;
DPRINTF_C("cmos: injecting from timer\n");
qemu_irq_raise(s->irq);
if (apic_get_irq_delivered()) {
if (rtc_policy_slew_deliver_irq(s)) {
s->irq_coalesced--;
DPRINTF_C("cmos: coalesced irqs decreased to %d\n",
s->irq_coalesced);
@ -144,6 +161,12 @@ static void rtc_coalesced_timer(void *opaque)
rtc_coalesced_timer_update(s);
}
#else
static bool rtc_policy_slew_deliver_irq(RTCState *s)
{
assert(0);
return false;
}
#endif
static uint32_t rtc_periodic_clock_ticks(RTCState *s)
@ -254,21 +277,17 @@ static void rtc_periodic_timer(void *opaque)
s->cmos_data[RTC_REG_C] |= REG_C_PF;
if (s->cmos_data[RTC_REG_B] & REG_B_PIE) {
s->cmos_data[RTC_REG_C] |= REG_C_IRQF;
#ifdef TARGET_I386
if (s->lost_tick_policy == LOST_TICK_POLICY_SLEW) {
if (s->irq_reinject_on_ack_count >= RTC_REINJECT_ON_ACK_COUNT)
s->irq_reinject_on_ack_count = 0;
apic_reset_irq_delivered();
qemu_irq_raise(s->irq);
if (!apic_get_irq_delivered()) {
s->irq_reinject_on_ack_count = 0;
if (!rtc_policy_slew_deliver_irq(s)) {
s->irq_coalesced++;
rtc_coalesced_timer_update(s);
DPRINTF_C("cmos: coalesced irqs increased to %d\n",
s->irq_coalesced);
}
} else
#endif
qemu_irq_raise(s->irq);
qemu_irq_raise(s->irq);
}
}
@ -612,20 +631,6 @@ static void rtc_get_time(RTCState *s, struct tm *tm)
rtc_from_bcd(s, s->cmos_data[RTC_CENTURY]) * 100 - 1900;
}
static QLIST_HEAD(, RTCState) rtc_devices =
QLIST_HEAD_INITIALIZER(rtc_devices);
#ifdef TARGET_I386
void qmp_rtc_reset_reinjection(Error **errp)
{
RTCState *s;
QLIST_FOREACH(s, &rtc_devices, link) {
s->irq_coalesced = 0;
}
}
#endif
static void rtc_set_time(RTCState *s)
{
struct tm tm;
@ -745,22 +750,19 @@ static uint64_t cmos_ioport_read(void *opaque, hwaddr addr,
if (ret & (REG_C_UF | REG_C_AF)) {
check_update_timer(s);
}
#ifdef TARGET_I386
if(s->irq_coalesced &&
(s->cmos_data[RTC_REG_B] & REG_B_PIE) &&
s->irq_reinject_on_ack_count < RTC_REINJECT_ON_ACK_COUNT) {
s->irq_reinject_on_ack_count++;
s->cmos_data[RTC_REG_C] |= REG_C_IRQF | REG_C_PF;
apic_reset_irq_delivered();
DPRINTF_C("cmos: injecting on ack\n");
qemu_irq_raise(s->irq);
if (apic_get_irq_delivered()) {
if (rtc_policy_slew_deliver_irq(s)) {
s->irq_coalesced--;
DPRINTF_C("cmos: coalesced irqs decreased to %d\n",
s->irq_coalesced);
}
}
#endif
break;
default:
ret = s->cmos_data[s->cmos_index];