mc146818rtc.c 28.0 KB
Newer Older
B
bellard 已提交
1 2
/*
 * QEMU MC146818 RTC emulation
3
 *
B
bellard 已提交
4
 * Copyright (c) 2003-2004 Fabrice Bellard
5
 *
B
bellard 已提交
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
24
#include "hw/hw.h"
25
#include "qemu/timer.h"
26
#include "sysemu/sysemu.h"
P
Paolo Bonzini 已提交
27
#include "hw/timer/mc146818rtc.h"
28
#include "qapi/visitor.h"
B
bellard 已提交
29

30
#ifdef TARGET_I386
P
Paolo Bonzini 已提交
31
#include "hw/i386/apic.h"
32 33
#endif

B
bellard 已提交
34
//#define DEBUG_CMOS
B
Blue Swirl 已提交
35
//#define DEBUG_COALESCED
B
bellard 已提交
36

37 38 39 40 41 42
#ifdef DEBUG_CMOS
# define CMOS_DPRINTF(format, ...)      printf(format, ## __VA_ARGS__)
#else
# define CMOS_DPRINTF(format, ...)      do { } while (0)
#endif

B
Blue Swirl 已提交
43 44 45 46 47 48
#ifdef DEBUG_COALESCED
# define DPRINTF_C(format, ...)      printf(format, ## __VA_ARGS__)
#else
# define DPRINTF_C(format, ...)      do { } while (0)
#endif

49
#define NSEC_PER_SEC    1000000000LL
50 51 52 53 54
#define SEC_PER_MIN     60
#define MIN_PER_HOUR    60
#define SEC_PER_HOUR    3600
#define HOUR_PER_DAY    24
#define SEC_PER_DAY     86400
55

G
Gleb Natapov 已提交
56
#define RTC_REINJECT_ON_ACK_COUNT 20
P
Paolo Bonzini 已提交
57
#define RTC_CLOCK_RATE            32768
58
#define UIP_HOLD_LENGTH           (8 * NSEC_PER_SEC / 32768)
59

A
Andreas Färber 已提交
60 61
#define MC146818_RTC(obj) OBJECT_CHECK(RTCState, (obj), TYPE_MC146818_RTC)

62
typedef struct RTCState {
A
Andreas Färber 已提交
63 64
    ISADevice parent_obj;

65
    MemoryRegion io;
66 67
    uint8_t cmos_data[128];
    uint8_t cmos_index;
68
    int32_t base_year;
69 70 71
    uint64_t base_rtc;
    uint64_t last_update;
    int64_t offset;
P
pbrook 已提交
72
    qemu_irq irq;
73
    qemu_irq sqw_irq;
74
    int it_shift;
75 76 77
    /* periodic timer */
    QEMUTimer *periodic_timer;
    int64_t next_periodic_time;
78 79
    /* update-ended timer */
    QEMUTimer *update_timer;
80
    uint64_t next_alarm_time;
81
    uint16_t irq_reinject_on_ack_count;
82 83
    uint32_t irq_coalesced;
    uint32_t period;
84
    QEMUTimer *coalesced_timer;
85
    Notifier clock_reset_notifier;
86
    LostTickPolicy lost_tick_policy;
87
    Notifier suspend_notifier;
88
} RTCState;
89 90

static void rtc_set_time(RTCState *s);
91
static void rtc_update_time(RTCState *s);
92
static void rtc_set_cmos(RTCState *s, const struct tm *tm);
93
static inline int rtc_from_bcd(RTCState *s, int a);
94
static uint64_t get_next_alarm(RTCState *s);
95

Y
Yang Zhang 已提交
96 97 98 99 100 101
static inline bool rtc_running(RTCState *s)
{
    return (!(s->cmos_data[RTC_REG_B] & REG_B_SET) &&
            (s->cmos_data[RTC_REG_A] & 0x70) <= 0x20);
}

102 103 104 105 106 107 108 109 110
static uint64_t get_guest_rtc_ns(RTCState *s)
{
    uint64_t guest_rtc;
    uint64_t guest_clock = qemu_get_clock_ns(rtc_clock);

    guest_rtc = s->base_rtc * NSEC_PER_SEC
                 + guest_clock - s->last_update + s->offset;
    return guest_rtc;
}
111

112 113 114 115 116 117 118 119
#ifdef TARGET_I386
static void rtc_coalesced_timer_update(RTCState *s)
{
    if (s->irq_coalesced == 0) {
        qemu_del_timer(s->coalesced_timer);
    } else {
        /* divide each RTC interval to 2 - 8 smaller intervals */
        int c = MIN(s->irq_coalesced, 7) + 1; 
120
        int64_t next_clock = qemu_get_clock_ns(rtc_clock) +
P
Paolo Bonzini 已提交
121
            muldiv64(s->period / c, get_ticks_per_sec(), RTC_CLOCK_RATE);
122 123 124 125 126 127 128 129 130 131 132
        qemu_mod_timer(s->coalesced_timer, next_clock);
    }
}

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;
B
Blue Swirl 已提交
133
        DPRINTF_C("cmos: injecting from timer\n");
134
        qemu_irq_raise(s->irq);
135 136
        if (apic_get_irq_delivered()) {
            s->irq_coalesced--;
B
Blue Swirl 已提交
137 138
            DPRINTF_C("cmos: coalesced irqs decreased to %d\n",
                      s->irq_coalesced);
139 140 141 142 143 144 145
        }
    }

    rtc_coalesced_timer_update(s);
}
#endif

146
/* handle periodic timer */
Y
Yang Zhang 已提交
147
static void periodic_timer_update(RTCState *s, int64_t current_time)
148 149 150 151 152
{
    int period_code, period;
    int64_t cur_clock, next_irq_clock;

    period_code = s->cmos_data[RTC_REG_A] & 0x0f;
153
    if (period_code != 0
154
        && ((s->cmos_data[RTC_REG_B] & REG_B_PIE)
155
            || ((s->cmos_data[RTC_REG_B] & REG_B_SQWE) && s->sqw_irq))) {
156 157 158 159
        if (period_code <= 2)
            period_code += 7;
        /* period in 32 Khz cycles */
        period = 1 << (period_code - 1);
160
#ifdef TARGET_I386
B
Blue Swirl 已提交
161
        if (period != s->period) {
162
            s->irq_coalesced = (s->irq_coalesced * s->period) / period;
B
Blue Swirl 已提交
163 164
            DPRINTF_C("cmos: coalesced irqs scaled to %d\n", s->irq_coalesced);
        }
165 166
        s->period = period;
#endif
167
        /* compute 32 khz clock */
P
Paolo Bonzini 已提交
168
        cur_clock = muldiv64(current_time, RTC_CLOCK_RATE, get_ticks_per_sec());
169
        next_irq_clock = (cur_clock & ~(period - 1)) + period;
J
Jan Kiszka 已提交
170
        s->next_periodic_time =
P
Paolo Bonzini 已提交
171
            muldiv64(next_irq_clock, get_ticks_per_sec(), RTC_CLOCK_RATE) + 1;
172 173
        qemu_mod_timer(s->periodic_timer, s->next_periodic_time);
    } else {
174 175 176
#ifdef TARGET_I386
        s->irq_coalesced = 0;
#endif
177 178 179 180 181 182 183 184
        qemu_del_timer(s->periodic_timer);
    }
}

static void rtc_periodic_timer(void *opaque)
{
    RTCState *s = opaque;

Y
Yang Zhang 已提交
185
    periodic_timer_update(s, s->next_periodic_time);
186
    s->cmos_data[RTC_REG_C] |= REG_C_PF;
187
    if (s->cmos_data[RTC_REG_B] & REG_B_PIE) {
188
        s->cmos_data[RTC_REG_C] |= REG_C_IRQF;
189
#ifdef TARGET_I386
190
        if (s->lost_tick_policy == LOST_TICK_SLEW) {
191 192
            if (s->irq_reinject_on_ack_count >= RTC_REINJECT_ON_ACK_COUNT)
                s->irq_reinject_on_ack_count = 0;		
193
            apic_reset_irq_delivered();
194
            qemu_irq_raise(s->irq);
195 196 197
            if (!apic_get_irq_delivered()) {
                s->irq_coalesced++;
                rtc_coalesced_timer_update(s);
B
Blue Swirl 已提交
198 199
                DPRINTF_C("cmos: coalesced irqs increased to %d\n",
                          s->irq_coalesced);
200 201 202
            }
        } else
#endif
203
        qemu_irq_raise(s->irq);
204 205 206 207 208 209
    }
    if (s->cmos_data[RTC_REG_B] & REG_B_SQWE) {
        /* Not square wave at all but we don't want 2048Hz interrupts!
           Must be seen as a pulse.  */
        qemu_irq_raise(s->sqw_irq);
    }
210
}
B
bellard 已提交
211

212 213 214 215 216
/* handle update-ended timer */
static void check_update_timer(RTCState *s)
{
    uint64_t next_update_time;
    uint64_t guest_nsec;
217
    int next_alarm_sec;
218

Y
Yang Zhang 已提交
219 220 221 222
    /* From the data sheet: "Holding the dividers in reset prevents
     * interrupts from operating, while setting the SET bit allows"
     * them to occur.  However, it will prevent an alarm interrupt
     * from occurring, because the time of day is not updated.
223
     */
Y
Yang Zhang 已提交
224 225 226 227
    if ((s->cmos_data[RTC_REG_A] & 0x60) == 0x60) {
        qemu_del_timer(s->update_timer);
        return;
    }
228 229 230 231 232 233 234 235 236 237 238 239
    if ((s->cmos_data[RTC_REG_C] & REG_C_UF) &&
        (s->cmos_data[RTC_REG_B] & REG_B_SET)) {
        qemu_del_timer(s->update_timer);
        return;
    }
    if ((s->cmos_data[RTC_REG_C] & REG_C_UF) &&
        (s->cmos_data[RTC_REG_C] & REG_C_AF)) {
        qemu_del_timer(s->update_timer);
        return;
    }

    guest_nsec = get_guest_rtc_ns(s) % NSEC_PER_SEC;
240
    /* if UF is clear, reprogram to next second */
241 242
    next_update_time = qemu_get_clock_ns(rtc_clock)
        + NSEC_PER_SEC - guest_nsec;
243 244 245 246 247 248 249 250 251 252 253 254

    /* Compute time of next alarm.  One second is already accounted
     * for in next_update_time.
     */
    next_alarm_sec = get_next_alarm(s);
    s->next_alarm_time = next_update_time + (next_alarm_sec - 1) * NSEC_PER_SEC;

    if (s->cmos_data[RTC_REG_C] & REG_C_UF) {
        /* UF is set, but AF is clear.  Program the timer to target
         * the alarm time.  */
        next_update_time = s->next_alarm_time;
    }
255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
    if (next_update_time != qemu_timer_expire_time_ns(s->update_timer)) {
        qemu_mod_timer(s->update_timer, next_update_time);
    }
}

static inline uint8_t convert_hour(RTCState *s, uint8_t hour)
{
    if (!(s->cmos_data[RTC_REG_B] & REG_B_24H)) {
        hour %= 12;
        if (s->cmos_data[RTC_HOURS] & 0x80) {
            hour += 12;
        }
    }
    return hour;
}

271
static uint64_t get_next_alarm(RTCState *s)
272
{
273 274 275 276
    int32_t alarm_sec, alarm_min, alarm_hour, cur_hour, cur_min, cur_sec;
    int32_t hour, min, sec;

    rtc_update_time(s);
277 278 279 280

    alarm_sec = rtc_from_bcd(s, s->cmos_data[RTC_SECONDS_ALARM]);
    alarm_min = rtc_from_bcd(s, s->cmos_data[RTC_MINUTES_ALARM]);
    alarm_hour = rtc_from_bcd(s, s->cmos_data[RTC_HOURS_ALARM]);
281
    alarm_hour = alarm_hour == -1 ? -1 : convert_hour(s, alarm_hour);
282 283 284 285 286 287

    cur_sec = rtc_from_bcd(s, s->cmos_data[RTC_SECONDS]);
    cur_min = rtc_from_bcd(s, s->cmos_data[RTC_MINUTES]);
    cur_hour = rtc_from_bcd(s, s->cmos_data[RTC_HOURS]);
    cur_hour = convert_hour(s, cur_hour);

288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334
    if (alarm_hour == -1) {
        alarm_hour = cur_hour;
        if (alarm_min == -1) {
            alarm_min = cur_min;
            if (alarm_sec == -1) {
                alarm_sec = cur_sec + 1;
            } else if (cur_sec > alarm_sec) {
                alarm_min++;
            }
        } else if (cur_min == alarm_min) {
            if (alarm_sec == -1) {
                alarm_sec = cur_sec + 1;
            } else {
                if (cur_sec > alarm_sec) {
                    alarm_hour++;
                }
            }
            if (alarm_sec == SEC_PER_MIN) {
                /* wrap to next hour, minutes is not in don't care mode */
                alarm_sec = 0;
                alarm_hour++;
            }
        } else if (cur_min > alarm_min) {
            alarm_hour++;
        }
    } else if (cur_hour == alarm_hour) {
        if (alarm_min == -1) {
            alarm_min = cur_min;
            if (alarm_sec == -1) {
                alarm_sec = cur_sec + 1;
            } else if (cur_sec > alarm_sec) {
                alarm_min++;
            }

            if (alarm_sec == SEC_PER_MIN) {
                alarm_sec = 0;
                alarm_min++;
            }
            /* wrap to next day, hour is not in don't care mode */
            alarm_min %= MIN_PER_HOUR;
        } else if (cur_min == alarm_min) {
            if (alarm_sec == -1) {
                alarm_sec = cur_sec + 1;
            }
            /* wrap to next day, hours+minutes not in don't care mode */
            alarm_sec %= SEC_PER_MIN;
        }
335 336
    }

337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359
    /* values that are still don't care fire at the next min/sec */
    if (alarm_min == -1) {
        alarm_min = 0;
    }
    if (alarm_sec == -1) {
        alarm_sec = 0;
    }

    /* keep values in range */
    if (alarm_sec == SEC_PER_MIN) {
        alarm_sec = 0;
        alarm_min++;
    }
    if (alarm_min == MIN_PER_HOUR) {
        alarm_min = 0;
        alarm_hour++;
    }
    alarm_hour %= HOUR_PER_DAY;

    hour = alarm_hour - cur_hour;
    min = hour * MIN_PER_HOUR + alarm_min - cur_min;
    sec = min * SEC_PER_MIN + alarm_sec - cur_sec;
    return sec <= 0 ? sec + SEC_PER_DAY : sec;
360 361 362 363 364 365 366 367
}

static void rtc_update_timer(void *opaque)
{
    RTCState *s = opaque;
    int32_t irqs = REG_C_UF;
    int32_t new_irqs;

Y
Yang Zhang 已提交
368 369
    assert((s->cmos_data[RTC_REG_A] & 0x60) != 0x60);

370 371 372 373
    /* UIP might have been latched, update time and clear it.  */
    rtc_update_time(s);
    s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;

374
    if (qemu_get_clock_ns(rtc_clock) >= s->next_alarm_time) {
375 376 377 378 379
        irqs |= REG_C_AF;
        if (s->cmos_data[RTC_REG_B] & REG_B_AIE) {
            qemu_system_wakeup_request(QEMU_WAKEUP_REASON_RTC);
        }
    }
380

381 382 383 384 385 386 387 388 389
    new_irqs = irqs & ~s->cmos_data[RTC_REG_C];
    s->cmos_data[RTC_REG_C] |= irqs;
    if ((new_irqs & s->cmos_data[RTC_REG_B]) != 0) {
        s->cmos_data[RTC_REG_C] |= REG_C_IRQF;
        qemu_irq_raise(s->irq);
    }
    check_update_timer(s);
}

390 391
static void cmos_ioport_write(void *opaque, hwaddr addr,
                              uint64_t data, unsigned size)
B
bellard 已提交
392
{
B
bellard 已提交
393
    RTCState *s = opaque;
B
bellard 已提交
394 395 396 397

    if ((addr & 1) == 0) {
        s->cmos_index = data & 0x7f;
    } else {
398 399
        CMOS_DPRINTF("cmos: write index=0x%02x val=0x%02x\n",
                     s->cmos_index, data);
400
        switch(s->cmos_index) {
B
bellard 已提交
401 402 403 404
        case RTC_SECONDS_ALARM:
        case RTC_MINUTES_ALARM:
        case RTC_HOURS_ALARM:
            s->cmos_data[s->cmos_index] = data;
405
            check_update_timer(s);
B
bellard 已提交
406
            break;
407 408 409 410
	case RTC_IBM_PS2_CENTURY_BYTE:
            s->cmos_index = RTC_CENTURY;
            /* fall through */
        case RTC_CENTURY:
B
bellard 已提交
411 412 413 414 415 416 417 418
        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;
419
            /* if in set mode, do not update the time */
Y
Yang Zhang 已提交
420
            if (rtc_running(s)) {
421
                rtc_set_time(s);
422
                check_update_timer(s);
423
            }
B
bellard 已提交
424 425
            break;
        case RTC_REG_A:
Y
Yang Zhang 已提交
426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444
            if ((data & 0x60) == 0x60) {
                if (rtc_running(s)) {
                    rtc_update_time(s);
                }
                /* What happens to UIP when divider reset is enabled is
                 * unclear from the datasheet.  Shouldn't matter much
                 * though.
                 */
                s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
            } else if (((s->cmos_data[RTC_REG_A] & 0x60) == 0x60) &&
                    (data & 0x70)  <= 0x20) {
                /* when the divider reset is removed, the first update cycle
                 * begins one-half second later*/
                if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
                    s->offset = 500000000;
                    rtc_set_time(s);
                }
                s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
            }
445 446 447
            /* UIP bit is read only */
            s->cmos_data[RTC_REG_A] = (data & ~REG_A_UIP) |
                (s->cmos_data[RTC_REG_A] & REG_A_UIP);
Y
Yang Zhang 已提交
448
            periodic_timer_update(s, qemu_get_clock_ns(rtc_clock));
449
            check_update_timer(s);
450
            break;
B
bellard 已提交
451
        case RTC_REG_B:
452
            if (data & REG_B_SET) {
453
                /* update cmos to when the rtc was stopping */
Y
Yang Zhang 已提交
454
                if (rtc_running(s)) {
455 456
                    rtc_update_time(s);
                }
457 458 459 460 461
                /* set mode: reset UIP mode */
                s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
                data &= ~REG_B_UIE;
            } else {
                /* if disabling set mode, update the time */
Y
Yang Zhang 已提交
462 463
                if ((s->cmos_data[RTC_REG_B] & REG_B_SET) &&
                    (s->cmos_data[RTC_REG_A] & 0x70) <= 0x20) {
464
                    s->offset = get_guest_rtc_ns(s) % NSEC_PER_SEC;
465 466 467
                    rtc_set_time(s);
                }
            }
468 469 470 471 472 473 474 475 476
            /* if an interrupt flag is already set when the interrupt
             * becomes enabled, raise an interrupt immediately.  */
            if (data & s->cmos_data[RTC_REG_C] & REG_C_MASK) {
                s->cmos_data[RTC_REG_C] |= REG_C_IRQF;
                qemu_irq_raise(s->irq);
            } else {
                s->cmos_data[RTC_REG_C] &= ~REG_C_IRQF;
                qemu_irq_lower(s->irq);
            }
477
            s->cmos_data[RTC_REG_B] = data;
Y
Yang Zhang 已提交
478
            periodic_timer_update(s, qemu_get_clock_ns(rtc_clock));
479
            check_update_timer(s);
B
bellard 已提交
480 481 482 483 484 485 486 487 488 489 490 491
            break;
        case RTC_REG_C:
        case RTC_REG_D:
            /* cannot write to them */
            break;
        default:
            s->cmos_data[s->cmos_index] = data;
            break;
        }
    }
}

P
Paul Brook 已提交
492
static inline int rtc_to_bcd(RTCState *s, int a)
B
bellard 已提交
493
{
A
aurel32 已提交
494
    if (s->cmos_data[RTC_REG_B] & REG_B_DM) {
495 496 497 498
        return a;
    } else {
        return ((a / 10) << 4) | (a % 10);
    }
B
bellard 已提交
499 500
}

P
Paul Brook 已提交
501
static inline int rtc_from_bcd(RTCState *s, int a)
B
bellard 已提交
502
{
503 504 505
    if ((a & 0xc0) == 0xc0) {
        return -1;
    }
A
aurel32 已提交
506
    if (s->cmos_data[RTC_REG_B] & REG_B_DM) {
507 508 509 510 511 512
        return a;
    } else {
        return ((a >> 4) * 10) + (a & 0x0f);
    }
}

513
static void rtc_get_time(RTCState *s, struct tm *tm)
514
{
P
Paul Brook 已提交
515 516 517
    tm->tm_sec = rtc_from_bcd(s, s->cmos_data[RTC_SECONDS]);
    tm->tm_min = rtc_from_bcd(s, s->cmos_data[RTC_MINUTES]);
    tm->tm_hour = rtc_from_bcd(s, s->cmos_data[RTC_HOURS] & 0x7f);
P
Paolo Bonzini 已提交
518 519 520 521 522
    if (!(s->cmos_data[RTC_REG_B] & REG_B_24H)) {
        tm->tm_hour %= 12;
        if (s->cmos_data[RTC_HOURS] & 0x80) {
            tm->tm_hour += 12;
        }
523
    }
P
Paul Brook 已提交
524 525 526
    tm->tm_wday = rtc_from_bcd(s, s->cmos_data[RTC_DAY_OF_WEEK]) - 1;
    tm->tm_mday = rtc_from_bcd(s, s->cmos_data[RTC_DAY_OF_MONTH]);
    tm->tm_mon = rtc_from_bcd(s, s->cmos_data[RTC_MONTH]) - 1;
P
Paolo Bonzini 已提交
527 528 529
    tm->tm_year =
        rtc_from_bcd(s, s->cmos_data[RTC_YEAR]) + s->base_year +
        rtc_from_bcd(s, s->cmos_data[RTC_CENTURY]) * 100 - 1900;
530 531 532 533 534
}

static void rtc_set_time(RTCState *s)
{
    struct tm tm;
535

536 537
    rtc_get_time(s, &tm);
    s->base_rtc = mktimegm(&tm);
538 539
    s->last_update = qemu_get_clock_ns(rtc_clock);

540
    rtc_change_mon_event(&tm);
541 542
}

543
static void rtc_set_cmos(RTCState *s, const struct tm *tm)
544
{
545
    int year;
546

P
Paul Brook 已提交
547 548
    s->cmos_data[RTC_SECONDS] = rtc_to_bcd(s, tm->tm_sec);
    s->cmos_data[RTC_MINUTES] = rtc_to_bcd(s, tm->tm_min);
A
Aurelien Jarno 已提交
549
    if (s->cmos_data[RTC_REG_B] & REG_B_24H) {
550
        /* 24 hour format */
P
Paul Brook 已提交
551
        s->cmos_data[RTC_HOURS] = rtc_to_bcd(s, tm->tm_hour);
552 553
    } else {
        /* 12 hour format */
P
Paolo Bonzini 已提交
554 555
        int h = (tm->tm_hour % 12) ? tm->tm_hour % 12 : 12;
        s->cmos_data[RTC_HOURS] = rtc_to_bcd(s, h);
556 557 558
        if (tm->tm_hour >= 12)
            s->cmos_data[RTC_HOURS] |= 0x80;
    }
P
Paul Brook 已提交
559 560 561
    s->cmos_data[RTC_DAY_OF_WEEK] = rtc_to_bcd(s, tm->tm_wday + 1);
    s->cmos_data[RTC_DAY_OF_MONTH] = rtc_to_bcd(s, tm->tm_mday);
    s->cmos_data[RTC_MONTH] = rtc_to_bcd(s, tm->tm_mon + 1);
P
Paolo Bonzini 已提交
562 563 564
    year = tm->tm_year + 1900 - s->base_year;
    s->cmos_data[RTC_YEAR] = rtc_to_bcd(s, year % 100);
    s->cmos_data[RTC_CENTURY] = rtc_to_bcd(s, year / 100);
565 566
}

567
static void rtc_update_time(RTCState *s)
568
{
569 570 571 572 573 574 575
    struct tm ret;
    time_t guest_sec;
    int64_t guest_nsec;

    guest_nsec = get_guest_rtc_ns(s);
    guest_sec = guest_nsec / NSEC_PER_SEC;
    gmtime_r(&guest_sec, &ret);
576 577 578 579 580

    /* Is SET flag of Register B disabled? */
    if ((s->cmos_data[RTC_REG_B] & REG_B_SET) == 0) {
        rtc_set_cmos(s, &ret);
    }
581 582
}

583
static int update_in_progress(RTCState *s)
584
{
585
    int64_t guest_nsec;
586

Y
Yang Zhang 已提交
587
    if (!rtc_running(s)) {
588
        return 0;
589
    }
590 591 592 593 594 595
    if (qemu_timer_pending(s->update_timer)) {
        int64_t next_update_time = qemu_timer_expire_time_ns(s->update_timer);
        /* Latch UIP until the timer expires.  */
        if (qemu_get_clock_ns(rtc_clock) >= (next_update_time - UIP_HOLD_LENGTH)) {
            s->cmos_data[RTC_REG_A] |= REG_A_UIP;
            return 1;
596 597 598
        }
    }

599 600 601 602
    guest_nsec = get_guest_rtc_ns(s);
    /* UIP bit will be set at last 244us of every second. */
    if ((guest_nsec % NSEC_PER_SEC) >= (NSEC_PER_SEC - UIP_HOLD_LENGTH)) {
        return 1;
603
    }
604
    return 0;
B
bellard 已提交
605 606
}

607 608
static uint64_t cmos_ioport_read(void *opaque, hwaddr addr,
                                 unsigned size)
B
bellard 已提交
609
{
B
bellard 已提交
610
    RTCState *s = opaque;
B
bellard 已提交
611 612 613 614 615
    int ret;
    if ((addr & 1) == 0) {
        return 0xff;
    } else {
        switch(s->cmos_index) {
616 617 618 619
	case RTC_IBM_PS2_CENTURY_BYTE:
            s->cmos_index = RTC_CENTURY;
            /* fall through */
        case RTC_CENTURY:
B
bellard 已提交
620 621 622 623 624 625 626
        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:
627 628
            /* if not in set mode, calibrate cmos before
             * reading*/
Y
Yang Zhang 已提交
629
            if (rtc_running(s)) {
630 631
                rtc_update_time(s);
            }
B
bellard 已提交
632 633 634
            ret = s->cmos_data[s->cmos_index];
            break;
        case RTC_REG_A:
635 636 637 638 639
            if (update_in_progress(s)) {
                s->cmos_data[s->cmos_index] |= REG_A_UIP;
            } else {
                s->cmos_data[s->cmos_index] &= ~REG_A_UIP;
            }
B
bellard 已提交
640 641 642 643
            ret = s->cmos_data[s->cmos_index];
            break;
        case RTC_REG_C:
            ret = s->cmos_data[s->cmos_index];
P
pbrook 已提交
644
            qemu_irq_lower(s->irq);
645
            s->cmos_data[RTC_REG_C] = 0x00;
646 647 648
            if (ret & (REG_C_UF | REG_C_AF)) {
                check_update_timer(s);
            }
649 650
#ifdef TARGET_I386
            if(s->irq_coalesced &&
651
                    (s->cmos_data[RTC_REG_B] & REG_B_PIE) &&
652 653
                    s->irq_reinject_on_ack_count < RTC_REINJECT_ON_ACK_COUNT) {
                s->irq_reinject_on_ack_count++;
654
                s->cmos_data[RTC_REG_C] |= REG_C_IRQF | REG_C_PF;
655
                apic_reset_irq_delivered();
B
Blue Swirl 已提交
656
                DPRINTF_C("cmos: injecting on ack\n");
657
                qemu_irq_raise(s->irq);
B
Blue Swirl 已提交
658
                if (apic_get_irq_delivered()) {
659
                    s->irq_coalesced--;
B
Blue Swirl 已提交
660 661 662
                    DPRINTF_C("cmos: coalesced irqs decreased to %d\n",
                              s->irq_coalesced);
                }
663 664
            }
#endif
B
bellard 已提交
665 666 667 668 669
            break;
        default:
            ret = s->cmos_data[s->cmos_index];
            break;
        }
670 671
        CMOS_DPRINTF("cmos: read index=0x%02x val=0x%02x\n",
                     s->cmos_index, ret);
B
bellard 已提交
672 673 674 675
        return ret;
    }
}

676
void rtc_set_memory(ISADevice *dev, int addr, int val)
677
{
A
Andreas Färber 已提交
678
    RTCState *s = MC146818_RTC(dev);
679 680 681 682
    if (addr >= 0 && addr <= 127)
        s->cmos_data[addr] = val;
}

683 684 685 686 687 688 689
int rtc_get_memory(ISADevice *dev, int addr)
{
    RTCState *s = MC146818_RTC(dev);
    assert(addr >= 0 && addr <= 127);
    return s->cmos_data[addr];
}

690
static void rtc_set_date_from_host(ISADevice *dev)
691
{
A
Andreas Färber 已提交
692
    RTCState *s = MC146818_RTC(dev);
693
    struct tm tm;
694

695
    qemu_get_timedate(&tm, 0);
696 697 698 699 700 701

    s->base_rtc = mktimegm(&tm);
    s->last_update = qemu_get_clock_ns(rtc_clock);
    s->offset = 0;

    /* set the CMOS date */
702
    rtc_set_cmos(s, &tm);
703 704
}

J
Juan Quintela 已提交
705
static int rtc_post_load(void *opaque, int version_id)
B
bellard 已提交
706
{
707 708
    RTCState *s = opaque;

709 710 711 712 713 714 715
    if (version_id <= 2) {
        rtc_set_time(s);
        s->offset = 0;
        check_update_timer(s);
    }

#ifdef TARGET_I386
716
    if (version_id >= 2) {
717
        if (s->lost_tick_policy == LOST_TICK_SLEW) {
718 719 720
            rtc_coalesced_timer_update(s);
        }
    }
J
Juan Quintela 已提交
721
#endif
722 723 724
    return 0;
}

J
Juan Quintela 已提交
725 726
static const VMStateDescription vmstate_rtc = {
    .name = "mc146818rtc",
727
    .version_id = 3,
J
Juan Quintela 已提交
728 729 730 731 732 733
    .minimum_version_id = 1,
    .minimum_version_id_old = 1,
    .post_load = rtc_post_load,
    .fields      = (VMStateField []) {
        VMSTATE_BUFFER(cmos_data, RTCState),
        VMSTATE_UINT8(cmos_index, RTCState),
P
Paolo Bonzini 已提交
734
        VMSTATE_UNUSED(7*4),
J
Juan Quintela 已提交
735 736
        VMSTATE_TIMER(periodic_timer, RTCState),
        VMSTATE_INT64(next_periodic_time, RTCState),
737
        VMSTATE_UNUSED(3*8),
J
Juan Quintela 已提交
738 739
        VMSTATE_UINT32_V(irq_coalesced, RTCState, 2),
        VMSTATE_UINT32_V(period, RTCState, 2),
740 741 742 743
        VMSTATE_UINT64_V(base_rtc, RTCState, 3),
        VMSTATE_UINT64_V(last_update, RTCState, 3),
        VMSTATE_INT64_V(offset, RTCState, 3),
        VMSTATE_TIMER_V(update_timer, RTCState, 3),
744
        VMSTATE_UINT64_V(next_alarm_time, RTCState, 3),
J
Juan Quintela 已提交
745 746 747 748
        VMSTATE_END_OF_LIST()
    }
};

749 750 751 752 753
static void rtc_notify_clock_reset(Notifier *notifier, void *data)
{
    RTCState *s = container_of(notifier, RTCState, clock_reset_notifier);
    int64_t now = *(int64_t *)data;

A
Andreas Färber 已提交
754
    rtc_set_date_from_host(ISA_DEVICE(s));
Y
Yang Zhang 已提交
755
    periodic_timer_update(s, now);
756
    check_update_timer(s);
757
#ifdef TARGET_I386
758
    if (s->lost_tick_policy == LOST_TICK_SLEW) {
759 760 761 762 763
        rtc_coalesced_timer_update(s);
    }
#endif
}

764 765 766 767 768
/* set CMOS shutdown status register (index 0xF) as S3_resume(0xFE)
   BIOS will read it and start S3 resume at POST Entry */
static void rtc_notify_suspend(Notifier *notifier, void *data)
{
    RTCState *s = container_of(notifier, RTCState, suspend_notifier);
A
Andreas Färber 已提交
769
    rtc_set_memory(ISA_DEVICE(s), 0xF, 0xFE);
770 771
}

G
Gleb Natapov 已提交
772 773 774 775
static void rtc_reset(void *opaque)
{
    RTCState *s = opaque;

776 777
    s->cmos_data[RTC_REG_B] &= ~(REG_B_PIE | REG_B_AIE | REG_B_SQWE);
    s->cmos_data[RTC_REG_C] &= ~(REG_C_UF | REG_C_IRQF | REG_C_PF | REG_C_AF);
778
    check_update_timer(s);
G
Gleb Natapov 已提交
779

780
    qemu_irq_lower(s->irq);
G
Gleb Natapov 已提交
781 782

#ifdef TARGET_I386
783 784 785
    if (s->lost_tick_policy == LOST_TICK_SLEW) {
        s->irq_coalesced = 0;
    }
G
Gleb Natapov 已提交
786 787 788
#endif
}

789
static const MemoryRegionOps cmos_ops = {
790 791 792 793 794 795 796
    .read = cmos_ioport_read,
    .write = cmos_ioport_write,
    .impl = {
        .min_access_size = 1,
        .max_access_size = 1,
    },
    .endianness = DEVICE_LITTLE_ENDIAN,
797 798
};

799
static void rtc_get_date(Object *obj, Visitor *v, void *opaque,
800 801
                         const char *name, Error **errp)
{
A
Andreas Färber 已提交
802
    RTCState *s = MC146818_RTC(obj);
803
    struct tm current_tm;
804

805
    rtc_update_time(s);
806
    rtc_get_time(s, &current_tm);
807
    visit_start_struct(v, NULL, "struct tm", name, 0, errp);
808 809 810 811 812 813
    visit_type_int32(v, &current_tm.tm_year, "tm_year", errp);
    visit_type_int32(v, &current_tm.tm_mon, "tm_mon", errp);
    visit_type_int32(v, &current_tm.tm_mday, "tm_mday", errp);
    visit_type_int32(v, &current_tm.tm_hour, "tm_hour", errp);
    visit_type_int32(v, &current_tm.tm_min, "tm_min", errp);
    visit_type_int32(v, &current_tm.tm_sec, "tm_sec", errp);
814 815 816
    visit_end_struct(v, errp);
}

817
static void rtc_realizefn(DeviceState *dev, Error **errp)
818
{
819
    ISADevice *isadev = ISA_DEVICE(dev);
A
Andreas Färber 已提交
820
    RTCState *s = MC146818_RTC(dev);
821
    int base = 0x70;
B
bellard 已提交
822 823 824 825 826 827

    s->cmos_data[RTC_REG_A] = 0x26;
    s->cmos_data[RTC_REG_B] = 0x02;
    s->cmos_data[RTC_REG_C] = 0x00;
    s->cmos_data[RTC_REG_D] = 0x80;

P
Paolo Bonzini 已提交
828 829 830 831 832 833 834 835 836 837 838 839
    /* This is for historical reasons.  The default base year qdev property
     * was set to 2000 for most machine types before the century byte was
     * implemented.
     *
     * This if statement means that the century byte will be always 0
     * (at least until 2079...) for base_year = 1980, but will be set
     * correctly for base_year = 2000.
     */
    if (s->base_year == 2000) {
        s->base_year = 0;
    }

840
    rtc_set_date_from_host(isadev);
841

842
#ifdef TARGET_I386
843 844
    switch (s->lost_tick_policy) {
    case LOST_TICK_SLEW:
J
Jan Kiszka 已提交
845
        s->coalesced_timer =
846
            qemu_new_timer_ns(rtc_clock, rtc_coalesced_timer, s);
847 848 849 850
        break;
    case LOST_TICK_DISCARD:
        break;
    default:
851 852
        error_setg(errp, "Invalid lost tick policy.");
        return;
853
    }
854
#endif
855 856

    s->periodic_timer = qemu_new_timer_ns(rtc_clock, rtc_periodic_timer, s);
857 858
    s->update_timer = qemu_new_timer_ns(rtc_clock, rtc_update_timer, s);
    check_update_timer(s);
859

860 861 862
    s->clock_reset_notifier.notify = rtc_notify_clock_reset;
    qemu_register_clock_reset_notifier(rtc_clock, &s->clock_reset_notifier);

863 864 865
    s->suspend_notifier.notify = rtc_notify_suspend;
    qemu_register_suspend_notifier(&s->suspend_notifier);

866
    memory_region_init_io(&s->io, OBJECT(s), &cmos_ops, s, "rtc", 2);
867
    isa_register_ioport(isadev, &s->io, base);
868

869
    qdev_set_legacy_instance_id(dev, base, 3);
870
    qemu_register_reset(rtc_reset, s);
871

872 873
    object_property_add(OBJECT(s), "date", "struct tm",
                        rtc_get_date, NULL, NULL, s, NULL);
874 875
}

876
ISADevice *rtc_init(ISABus *bus, int base_year, qemu_irq intercept_irq)
877
{
A
Andreas Färber 已提交
878 879
    DeviceState *dev;
    ISADevice *isadev;
880
    RTCState *s;
G
Gleb Natapov 已提交
881

A
Andreas Färber 已提交
882 883 884 885 886
    isadev = isa_create(bus, TYPE_MC146818_RTC);
    dev = DEVICE(isadev);
    s = MC146818_RTC(isadev);
    qdev_prop_set_int32(dev, "base_year", base_year);
    qdev_init_nofail(dev);
887 888 889
    if (intercept_irq) {
        s->irq = intercept_irq;
    } else {
A
Andreas Färber 已提交
890
        isa_init_irq(isadev, &s->irq, RTC_ISA_IRQ);
891
    }
A
Andreas Färber 已提交
892
    return isadev;
B
bellard 已提交
893 894
}

895 896 897 898 899 900 901
static Property mc146818rtc_properties[] = {
    DEFINE_PROP_INT32("base_year", RTCState, base_year, 1980),
    DEFINE_PROP_LOSTTICKPOLICY("lost_tick_policy", RTCState,
                               lost_tick_policy, LOST_TICK_DISCARD),
    DEFINE_PROP_END_OF_LIST(),
};

902 903
static void rtc_class_initfn(ObjectClass *klass, void *data)
{
904
    DeviceClass *dc = DEVICE_CLASS(klass);
905 906

    dc->realize = rtc_realizefn;
907 908 909
    dc->no_user = 1;
    dc->vmsd = &vmstate_rtc;
    dc->props = mc146818rtc_properties;
910 911
}

912
static const TypeInfo mc146818rtc_info = {
A
Andreas Färber 已提交
913
    .name          = TYPE_MC146818_RTC,
914 915 916
    .parent        = TYPE_ISA_DEVICE,
    .instance_size = sizeof(RTCState),
    .class_init    = rtc_class_initfn,
917 918
};

A
Andreas Färber 已提交
919
static void mc146818rtc_register_types(void)
920
{
921
    type_register_static(&mc146818rtc_info);
922
}
A
Andreas Färber 已提交
923 924

type_init(mc146818rtc_register_types)