Coverage Report

Created: 2017-10-25 09:10

/root/src/xen/xen/arch/x86/hvm/rtc.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * QEMU MC146818 RTC emulation
3
 * 
4
 * Copyright (c) 2003-2004 Fabrice Bellard
5
 * 
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7
 * of this software and associated documentation files (the "Software"), to
8
 * deal in the Software without restriction, including without limitation the
9
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10
 * sell copies of the Software, and to permit persons to whom the Software is
11
 * furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22
 * IN THE SOFTWARE.
23
 */
24
25
#include <asm/mc146818rtc.h>
26
#include <asm/hvm/vpt.h>
27
#include <asm/hvm/io.h>
28
#include <asm/hvm/support.h>
29
#include <asm/current.h>
30
#include <xen/trace.h>
31
32
0
#define USEC_PER_SEC    1000000UL
33
0
#define NS_PER_USEC     1000UL
34
0
#define NS_PER_SEC      1000000000ULL
35
36
0
#define SEC_PER_MIN     60
37
0
#define SEC_PER_HOUR    3600
38
0
#define MIN_PER_HOUR    60
39
0
#define HOUR_PER_DAY    24
40
41
549
#define domain_vrtc(x) (&(x)->arch.hvm_domain.pl_time->vrtc)
42
548
#define vcpu_vrtc(x)   (domain_vrtc((x)->domain))
43
0
#define vrtc_domain(x) (container_of(x, struct pl_time, vrtc)->domain)
44
0
#define vrtc_vcpu(x)   (pt_global_vcpu_target(vrtc_domain(x)))
45
0
#define epoch_year     1900
46
0
#define get_year(x)    (x + epoch_year)
47
48
enum rtc_mode {
49
   rtc_mode_no_ack,
50
   rtc_mode_strict
51
};
52
53
/* This must be in sync with how hvmloader sets the ACPI WAET flags. */
54
0
#define mode_is(d, m) ((void)(d), rtc_mode_##m == rtc_mode_no_ack)
55
0
#define rtc_mode_is(s, m) mode_is(vrtc_domain(s), m)
56
57
static void rtc_copy_date(RTCState *s);
58
static void rtc_set_time(RTCState *s);
59
static inline int from_bcd(RTCState *s, int a);
60
static inline int convert_hour(RTCState *s, int hour);
61
62
static void rtc_update_irq(RTCState *s)
63
0
{
64
0
    ASSERT(spin_is_locked(&s->lock));
65
0
66
0
    if ( rtc_mode_is(s, strict) && (s->hw.cmos_data[RTC_REG_C] & RTC_IRQF) )
67
0
        return;
68
0
69
0
    /* IRQ is raised if any source is both raised & enabled */
70
0
    if ( !(s->hw.cmos_data[RTC_REG_B] &
71
0
           s->hw.cmos_data[RTC_REG_C] &
72
0
           (RTC_PF | RTC_AF | RTC_UF)) )
73
0
        return;
74
0
75
0
    s->hw.cmos_data[RTC_REG_C] |= RTC_IRQF;
76
0
    if ( rtc_mode_is(s, no_ack) )
77
0
        hvm_isa_irq_deassert(vrtc_domain(s), RTC_IRQ);
78
0
    hvm_isa_irq_assert(vrtc_domain(s), RTC_IRQ);
79
0
}
80
81
/* Called by the VPT code after it's injected a PF interrupt for us.
82
 * Fix up the register state to reflect what happened. */
83
static void rtc_pf_callback(struct vcpu *v, void *opaque)
84
0
{
85
0
    RTCState *s = opaque;
86
0
87
0
    spin_lock(&s->lock);
88
0
89
0
    if ( !rtc_mode_is(s, no_ack)
90
0
         && (s->hw.cmos_data[RTC_REG_C] & RTC_IRQF)
91
0
         && ++(s->pt_dead_ticks) >= 10 )
92
0
    {
93
0
        /* VM is ignoring its RTC; no point in running the timer */
94
0
        TRACE_0D(TRC_HVM_EMUL_RTC_STOP_TIMER);
95
0
        destroy_periodic_time(&s->pt);
96
0
        s->period = 0;
97
0
    }
98
0
99
0
    s->hw.cmos_data[RTC_REG_C] |= RTC_PF|RTC_IRQF;
100
0
101
0
    spin_unlock(&s->lock);
102
0
}
103
104
/* Check whether the REG_C.PF bit should have been set by a tick since
105
 * the last time we looked. This is used to track ticks when REG_B.PIE
106
 * is clear; when PIE is set, PF ticks are handled by the VPT callbacks.  */
107
static void check_for_pf_ticks(RTCState *s)
108
0
{
109
0
    s_time_t now;
110
0
111
0
    if ( s->period == 0 || (s->hw.cmos_data[RTC_REG_B] & RTC_PIE) )
112
0
        return;
113
0
114
0
    now = NOW();
115
0
    if ( (now - s->start_time) / s->period
116
0
         != (s->check_ticks_since - s->start_time) / s->period )
117
0
        s->hw.cmos_data[RTC_REG_C] |= RTC_PF;
118
0
119
0
    s->check_ticks_since = now;
120
0
}
121
122
/* Enable/configure/disable the periodic timer based on the RTC_PIE and
123
 * RTC_RATE_SELECT settings */
124
static void rtc_timer_update(RTCState *s)
125
0
{
126
0
    int period_code, period, delta;
127
0
    struct vcpu *v = vrtc_vcpu(s);
128
0
129
0
    ASSERT(spin_is_locked(&s->lock));
130
0
131
0
    s->pt_dead_ticks = 0;
132
0
133
0
    period_code = s->hw.cmos_data[RTC_REG_A] & RTC_RATE_SELECT;
134
0
    switch ( s->hw.cmos_data[RTC_REG_A] & RTC_DIV_CTL )
135
0
    {
136
0
    case RTC_REF_CLCK_32KHZ:
137
0
        if ( (period_code != 0) && (period_code <= 2) )
138
0
            period_code += 7;
139
0
        /* fall through */
140
0
    case RTC_REF_CLCK_1MHZ:
141
0
    case RTC_REF_CLCK_4MHZ:
142
0
        if ( period_code != 0 )
143
0
        {
144
0
            period = 1 << (period_code - 1); /* period in 32 Khz cycles */
145
0
            period = DIV_ROUND(period * 1000000000ULL, 32768); /* in ns */
146
0
            if ( period != s->period )
147
0
            {
148
0
                s_time_t now = NOW();
149
0
150
0
                s->period = period;
151
0
                if ( v->domain->arch.hvm_domain.params[HVM_PARAM_VPT_ALIGN] )
152
0
                    delta = 0;
153
0
                else
154
0
                    delta = period - ((now - s->start_time) % period);
155
0
                if ( s->hw.cmos_data[RTC_REG_B] & RTC_PIE )
156
0
                {
157
0
                    TRACE_2D(TRC_HVM_EMUL_RTC_START_TIMER, delta, period);
158
0
                    create_periodic_time(v, &s->pt, delta, period,
159
0
                                         RTC_IRQ, rtc_pf_callback, s);
160
0
                }
161
0
                else
162
0
                    s->check_ticks_since = now;
163
0
            }
164
0
            break;
165
0
        }
166
0
        /* fall through */
167
0
    default:
168
0
        TRACE_0D(TRC_HVM_EMUL_RTC_STOP_TIMER);
169
0
        destroy_periodic_time(&s->pt);
170
0
        s->period = 0;
171
0
        break;
172
0
    }
173
0
}
174
175
/* handle update-ended timer */
176
static void check_update_timer(RTCState *s)
177
0
{
178
0
    uint64_t next_update_time, expire_time;
179
0
    uint64_t guest_usec;
180
0
    struct domain *d = vrtc_domain(s);
181
0
    stop_timer(&s->update_timer);
182
0
    stop_timer(&s->update_timer2);
183
0
184
0
    ASSERT(spin_is_locked(&s->lock));
185
0
186
0
    if (!(s->hw.cmos_data[RTC_REG_C] & RTC_UF) &&
187
0
            !(s->hw.cmos_data[RTC_REG_B] & RTC_SET))
188
0
    {
189
0
        s->use_timer = 1;
190
0
        guest_usec = get_localtime_us(d) % USEC_PER_SEC;
191
0
        if (guest_usec >= (USEC_PER_SEC - 244))
192
0
        {
193
0
            /* RTC is in update cycle */
194
0
            s->hw.cmos_data[RTC_REG_A] |= RTC_UIP;
195
0
            next_update_time = (USEC_PER_SEC - guest_usec) * NS_PER_USEC;
196
0
            expire_time = NOW() + next_update_time;
197
0
            /* release lock before set timer */
198
0
            spin_unlock(&s->lock);
199
0
            set_timer(&s->update_timer2, expire_time);
200
0
            /* fetch lock again */
201
0
            spin_lock(&s->lock);
202
0
        }
203
0
        else
204
0
        {
205
0
            next_update_time = (USEC_PER_SEC - guest_usec - 244) * NS_PER_USEC;
206
0
            expire_time = NOW() + next_update_time;
207
0
            s->next_update_time = expire_time;
208
0
            /* release lock before set timer */
209
0
            spin_unlock(&s->lock);
210
0
            set_timer(&s->update_timer, expire_time);
211
0
            /* fetch lock again */
212
0
            spin_lock(&s->lock);
213
0
        }
214
0
    }
215
0
    else
216
0
        s->use_timer = 0;
217
0
}
218
219
static void rtc_update_timer(void *opaque)
220
0
{
221
0
    RTCState *s = opaque;
222
0
223
0
    spin_lock(&s->lock);
224
0
    if (!(s->hw.cmos_data[RTC_REG_B] & RTC_SET))
225
0
    {
226
0
        s->hw.cmos_data[RTC_REG_A] |= RTC_UIP;
227
0
        set_timer(&s->update_timer2, s->next_update_time + 244000UL);
228
0
    }
229
0
    spin_unlock(&s->lock);
230
0
}
231
232
static void rtc_update_timer2(void *opaque)
233
0
{
234
0
    RTCState *s = opaque;
235
0
236
0
    spin_lock(&s->lock);
237
0
    if (!(s->hw.cmos_data[RTC_REG_B] & RTC_SET))
238
0
    {
239
0
        s->hw.cmos_data[RTC_REG_C] |= RTC_UF;
240
0
        s->hw.cmos_data[RTC_REG_A] &= ~RTC_UIP;
241
0
        rtc_update_irq(s);
242
0
        check_update_timer(s);
243
0
    }
244
0
    spin_unlock(&s->lock);
245
0
}
246
247
/* handle alarm timer */
248
static void alarm_timer_update(RTCState *s)
249
0
{
250
0
    uint64_t next_update_time, next_alarm_sec;
251
0
    uint64_t expire_time;
252
0
    int32_t alarm_sec, alarm_min, alarm_hour, cur_hour, cur_min, cur_sec;
253
0
    int32_t hour, min;
254
0
    struct domain *d = vrtc_domain(s);
255
0
256
0
    ASSERT(spin_is_locked(&s->lock));
257
0
258
0
    stop_timer(&s->alarm_timer);
259
0
260
0
    if (!(s->hw.cmos_data[RTC_REG_C] & RTC_AF) &&
261
0
            !(s->hw.cmos_data[RTC_REG_B] & RTC_SET))
262
0
    {
263
0
        s->current_tm = gmtime(get_localtime(d));
264
0
        rtc_copy_date(s);
265
0
266
0
        alarm_sec = from_bcd(s, s->hw.cmos_data[RTC_SECONDS_ALARM]);
267
0
        alarm_min = from_bcd(s, s->hw.cmos_data[RTC_MINUTES_ALARM]);
268
0
        alarm_hour = convert_hour(s, s->hw.cmos_data[RTC_HOURS_ALARM]);
269
0
270
0
        cur_sec = from_bcd(s, s->hw.cmos_data[RTC_SECONDS]);
271
0
        cur_min = from_bcd(s, s->hw.cmos_data[RTC_MINUTES]);
272
0
        cur_hour = convert_hour(s, s->hw.cmos_data[RTC_HOURS]);
273
0
274
0
        next_update_time = USEC_PER_SEC - (get_localtime_us(d) % USEC_PER_SEC);
275
0
        next_update_time = next_update_time * NS_PER_USEC + NOW();
276
0
277
0
        if ((s->hw.cmos_data[RTC_HOURS_ALARM] & 0xc0) == 0xc0)
278
0
        {
279
0
            if ((s->hw.cmos_data[RTC_MINUTES_ALARM] & 0xc0) == 0xc0)
280
0
            {
281
0
                if ((s->hw.cmos_data[RTC_SECONDS_ALARM] & 0xc0) == 0xc0)
282
0
                    next_alarm_sec = 1;
283
0
                else if (cur_sec < alarm_sec)
284
0
                    next_alarm_sec = alarm_sec - cur_sec;
285
0
                else
286
0
                    next_alarm_sec = alarm_sec + SEC_PER_MIN - cur_sec;
287
0
            }
288
0
            else
289
0
            {
290
0
                if (cur_min < alarm_min)
291
0
                {
292
0
                    min = alarm_min - cur_min;
293
0
                    next_alarm_sec = min * SEC_PER_MIN - cur_sec;
294
0
                    if ((s->hw.cmos_data[RTC_SECONDS_ALARM] & 0xc0) == 0xc0)
295
0
                        next_alarm_sec += 0;
296
0
                    else
297
0
                        next_alarm_sec += alarm_sec;
298
0
                }
299
0
                else if (cur_min == alarm_min)
300
0
                {
301
0
                    if ((s->hw.cmos_data[RTC_SECONDS_ALARM] & 0xc0) == 0xc0)
302
0
                        next_alarm_sec = 1;
303
0
                    else if (cur_sec < alarm_sec)
304
0
                        next_alarm_sec = alarm_sec - cur_sec;
305
0
                    else
306
0
                    {
307
0
                        min = alarm_min + MIN_PER_HOUR - cur_min;
308
0
                        next_alarm_sec =
309
0
                            alarm_sec + min * SEC_PER_MIN - cur_sec;
310
0
                    }
311
0
                }
312
0
                else
313
0
                {
314
0
                    min = alarm_min + MIN_PER_HOUR - cur_min;
315
0
                    next_alarm_sec = min * SEC_PER_MIN - cur_sec;
316
0
                    if ((s->hw.cmos_data[RTC_SECONDS_ALARM] & 0xc0) == 0xc0)
317
0
                        next_alarm_sec += 0;
318
0
                    else
319
0
                        next_alarm_sec += alarm_sec;
320
0
                }
321
0
            }
322
0
        }
323
0
        else
324
0
        {
325
0
            if (cur_hour < alarm_hour)
326
0
            {
327
0
                hour = alarm_hour - cur_hour;
328
0
                next_alarm_sec = hour * SEC_PER_HOUR -
329
0
                    cur_min * SEC_PER_MIN - cur_sec;
330
0
                if ((s->hw.cmos_data[RTC_MINUTES_ALARM] & 0xc0) == 0xc0)
331
0
                {
332
0
                    if ((s->hw.cmos_data[RTC_SECONDS_ALARM] & 0xc0) == 0xc0)
333
0
                        next_alarm_sec += 0;
334
0
                    else
335
0
                        next_alarm_sec += alarm_sec;
336
0
                }
337
0
                else
338
0
                {
339
0
                    next_alarm_sec += alarm_min * SEC_PER_MIN;
340
0
                    if ((s->hw.cmos_data[RTC_SECONDS_ALARM] & 0xc0) == 0xc0)
341
0
                        next_alarm_sec += 0;
342
0
                    else
343
0
                        next_alarm_sec += alarm_sec;
344
0
                }
345
0
            }
346
0
            else if (cur_hour == alarm_hour)
347
0
            {
348
0
                if ((s->hw.cmos_data[RTC_MINUTES_ALARM] & 0xc0) == 0xc0)
349
0
                {
350
0
                    if ((s->hw.cmos_data[RTC_SECONDS_ALARM] & 0xc0) == 0xc0)
351
0
                        next_alarm_sec = 1;
352
0
                    else if (cur_sec < alarm_sec)
353
0
                        next_alarm_sec = alarm_sec - cur_sec;
354
0
                    else
355
0
                        next_alarm_sec = alarm_sec + SEC_PER_MIN - cur_sec;
356
0
                }
357
0
                else if (cur_min < alarm_min)
358
0
                {
359
0
                    min = alarm_min - cur_min;
360
0
                    next_alarm_sec = min * SEC_PER_MIN - cur_sec;
361
0
                    if ((s->hw.cmos_data[RTC_SECONDS_ALARM] & 0xc0) == 0xc0)
362
0
                        next_alarm_sec += 0;
363
0
                    else
364
0
                        next_alarm_sec += alarm_sec;
365
0
                }
366
0
                else if (cur_min == alarm_min)
367
0
                {
368
0
                    if ((s->hw.cmos_data[RTC_SECONDS_ALARM] & 0xc0) == 0xc0)
369
0
                        next_alarm_sec = 1;
370
0
                    else if (cur_sec < alarm_sec)
371
0
                        next_alarm_sec = alarm_sec - cur_sec;
372
0
                    else
373
0
                    {
374
0
                        hour = alarm_hour + HOUR_PER_DAY - cur_hour;
375
0
                        next_alarm_sec = hour * SEC_PER_HOUR -
376
0
                            cur_min * SEC_PER_MIN - cur_sec;
377
0
                        next_alarm_sec += alarm_min * SEC_PER_MIN + alarm_sec;
378
0
                    }
379
0
                }
380
0
                else
381
0
                {
382
0
                    hour = alarm_hour + HOUR_PER_DAY - cur_hour;
383
0
                    next_alarm_sec = hour * SEC_PER_HOUR -
384
0
                        cur_min * SEC_PER_MIN - cur_sec;
385
0
                    next_alarm_sec += alarm_min * SEC_PER_MIN;
386
0
                    if ((s->hw.cmos_data[RTC_SECONDS_ALARM] & 0xc0) == 0xc0)
387
0
                        next_alarm_sec += 0;
388
0
                    else
389
0
                        next_alarm_sec += alarm_sec;
390
0
                }
391
0
            }
392
0
            else
393
0
            {
394
0
                hour = alarm_hour + HOUR_PER_DAY - cur_hour;
395
0
                next_alarm_sec = hour * SEC_PER_HOUR -
396
0
                    cur_min * SEC_PER_MIN - cur_sec;
397
0
                if ((s->hw.cmos_data[RTC_MINUTES_ALARM] & 0xc0) == 0xc0)
398
0
                {
399
0
                    if ((s->hw.cmos_data[RTC_SECONDS_ALARM] & 0xc0) == 0xc0)
400
0
                        next_alarm_sec += 0;
401
0
                    else
402
0
                        next_alarm_sec += alarm_sec;
403
0
                }
404
0
                else
405
0
                {
406
0
                    next_alarm_sec += alarm_min * SEC_PER_MIN;
407
0
                    if ((s->hw.cmos_data[RTC_SECONDS_ALARM] & 0xc0) == 0xc0)
408
0
                        next_alarm_sec += 0;
409
0
                    else
410
0
                        next_alarm_sec += alarm_sec;
411
0
                }
412
0
            }
413
0
        }
414
0
        expire_time = (next_alarm_sec - 1) * NS_PER_SEC + next_update_time;
415
0
        /* release lock before set timer */
416
0
        spin_unlock(&s->lock);
417
0
        set_timer(&s->alarm_timer, expire_time);
418
0
        /* fetch lock again */
419
0
        spin_lock(&s->lock);
420
0
    }
421
0
}
422
423
static void rtc_alarm_cb(void *opaque)
424
0
{
425
0
    RTCState *s = opaque;
426
0
427
0
    spin_lock(&s->lock);
428
0
    if (!(s->hw.cmos_data[RTC_REG_B] & RTC_SET))
429
0
    {
430
0
        s->hw.cmos_data[RTC_REG_C] |= RTC_AF;
431
0
        rtc_update_irq(s);
432
0
        alarm_timer_update(s);
433
0
    }
434
0
    spin_unlock(&s->lock);
435
0
}
436
437
static int rtc_ioport_write(void *opaque, uint32_t addr, uint32_t data)
438
0
{
439
0
    RTCState *s = opaque;
440
0
    struct domain *d = vrtc_domain(s);
441
0
    uint32_t orig;
442
0
443
0
    spin_lock(&s->lock);
444
0
445
0
    if ( (addr & 1) == 0 )
446
0
    {
447
0
        data &= 0x7f;
448
0
        s->hw.cmos_index = data;
449
0
        spin_unlock(&s->lock);
450
0
        return (data < RTC_CMOS_SIZE);
451
0
    }
452
0
453
0
    if ( s->hw.cmos_index >= RTC_CMOS_SIZE )
454
0
    {
455
0
        spin_unlock(&s->lock);
456
0
        return 0;
457
0
    }
458
0
459
0
    orig = s->hw.cmos_data[s->hw.cmos_index];
460
0
    switch ( s->hw.cmos_index )
461
0
    {
462
0
    case RTC_SECONDS_ALARM:
463
0
    case RTC_MINUTES_ALARM:
464
0
    case RTC_HOURS_ALARM:
465
0
        s->hw.cmos_data[s->hw.cmos_index] = data;
466
0
        alarm_timer_update(s);
467
0
        break;
468
0
    case RTC_SECONDS:
469
0
    case RTC_MINUTES:
470
0
    case RTC_HOURS:
471
0
    case RTC_DAY_OF_WEEK:
472
0
    case RTC_DAY_OF_MONTH:
473
0
    case RTC_MONTH:
474
0
    case RTC_YEAR:
475
0
        /* if in set mode, just write the register */
476
0
        if ( (s->hw.cmos_data[RTC_REG_B] & RTC_SET) )
477
0
            s->hw.cmos_data[s->hw.cmos_index] = data;
478
0
        else
479
0
        {
480
0
            /* Fetch the current time and update just this field. */
481
0
            s->current_tm = gmtime(get_localtime(d));
482
0
            rtc_copy_date(s);
483
0
            s->hw.cmos_data[s->hw.cmos_index] = data;
484
0
            rtc_set_time(s);
485
0
        }
486
0
        alarm_timer_update(s);
487
0
        break;
488
0
    case RTC_REG_A:
489
0
        /* UIP bit is read only */
490
0
        s->hw.cmos_data[RTC_REG_A] = (data & ~RTC_UIP) | (orig & RTC_UIP);
491
0
        if ( (data ^ orig) & ~RTC_UIP )
492
0
            rtc_timer_update(s);
493
0
        break;
494
0
    case RTC_REG_B:
495
0
        if ( data & RTC_SET )
496
0
        {
497
0
            /* set mode: reset UIP mode */
498
0
            s->hw.cmos_data[RTC_REG_A] &= ~RTC_UIP;
499
0
            /* adjust cmos before stopping */
500
0
            if (!(orig & RTC_SET))
501
0
            {
502
0
                s->current_tm = gmtime(get_localtime(d));
503
0
                rtc_copy_date(s);
504
0
            }
505
0
        }
506
0
        else
507
0
        {
508
0
            /* if disabling set mode, update the time */
509
0
            if ( orig & RTC_SET )
510
0
                rtc_set_time(s);
511
0
        }
512
0
        check_for_pf_ticks(s);
513
0
        s->hw.cmos_data[RTC_REG_B] = data;
514
0
        /*
515
0
         * If the interrupt is already set when the interrupt becomes
516
0
         * enabled, raise an interrupt immediately.
517
0
         */
518
0
        rtc_update_irq(s);
519
0
        if ( (data ^ orig) & RTC_PIE )
520
0
        {
521
0
            TRACE_0D(TRC_HVM_EMUL_RTC_STOP_TIMER);
522
0
            destroy_periodic_time(&s->pt);
523
0
            s->period = 0;
524
0
            rtc_timer_update(s);
525
0
        }
526
0
        if ( (data ^ orig) & RTC_SET )
527
0
            check_update_timer(s);
528
0
        if ( (data ^ orig) & (RTC_24H | RTC_DM_BINARY | RTC_SET) )
529
0
            alarm_timer_update(s);
530
0
        break;
531
0
    case RTC_REG_C:
532
0
    case RTC_REG_D:
533
0
        /* cannot write to them */
534
0
        break;
535
0
    }
536
0
537
0
    spin_unlock(&s->lock);
538
0
539
0
    return 1;
540
0
}
541
542
static inline int to_bcd(RTCState *s, int a)
543
0
{
544
0
    if ( s->hw.cmos_data[RTC_REG_B] & RTC_DM_BINARY )
545
0
        return a;
546
0
    else
547
0
        return ((a / 10) << 4) | (a % 10);
548
0
}
549
550
static inline int from_bcd(RTCState *s, int a)
551
0
{
552
0
    if ( s->hw.cmos_data[RTC_REG_B] & RTC_DM_BINARY )
553
0
        return a;
554
0
    else
555
0
        return ((a >> 4) * 10) + (a & 0x0f);
556
0
}
557
558
/* Hours in 12 hour mode are in 1-12 range, not 0-11.
559
 * So we need convert it before using it*/
560
static inline int convert_hour(RTCState *s, int raw)
561
0
{
562
0
    int hour = from_bcd(s, raw & 0x7f);
563
0
564
0
    if (!(s->hw.cmos_data[RTC_REG_B] & RTC_24H))
565
0
    {
566
0
        hour %= 12;
567
0
        if (raw & 0x80)
568
0
            hour += 12;
569
0
    }
570
0
    return hour;
571
0
}
572
573
static void rtc_set_time(RTCState *s)
574
0
{
575
0
    struct tm *tm = &s->current_tm;
576
0
    struct domain *d = vrtc_domain(s);
577
0
    unsigned long before, after; /* XXX s_time_t */
578
0
      
579
0
    ASSERT(spin_is_locked(&s->lock));
580
0
581
0
    before = mktime(get_year(tm->tm_year), tm->tm_mon + 1, tm->tm_mday,
582
0
        tm->tm_hour, tm->tm_min, tm->tm_sec);
583
0
    
584
0
    tm->tm_sec = from_bcd(s, s->hw.cmos_data[RTC_SECONDS]);
585
0
    tm->tm_min = from_bcd(s, s->hw.cmos_data[RTC_MINUTES]);
586
0
    tm->tm_hour = convert_hour(s, s->hw.cmos_data[RTC_HOURS]);
587
0
    tm->tm_wday = from_bcd(s, s->hw.cmos_data[RTC_DAY_OF_WEEK]);
588
0
    tm->tm_mday = from_bcd(s, s->hw.cmos_data[RTC_DAY_OF_MONTH]);
589
0
    tm->tm_mon = from_bcd(s, s->hw.cmos_data[RTC_MONTH]) - 1;
590
0
    tm->tm_year = from_bcd(s, s->hw.cmos_data[RTC_YEAR]) + 100;
591
0
592
0
    after = mktime(get_year(tm->tm_year), tm->tm_mon + 1, tm->tm_mday,
593
0
                   tm->tm_hour, tm->tm_min, tm->tm_sec);
594
0
595
0
    /* We use the guest's setting of the RTC to define the local-time 
596
0
     * offset for this domain. */
597
0
    d->time_offset_seconds += (after - before);
598
0
    update_domain_wallclock_time(d);
599
0
    /* Also tell qemu-dm about it so it will be remembered for next boot. */
600
0
    send_timeoffset_req(after - before);
601
0
}
602
603
static void rtc_copy_date(RTCState *s)
604
0
{
605
0
    const struct tm *tm = &s->current_tm;
606
0
607
0
    ASSERT(spin_is_locked(&s->lock));
608
0
609
0
    s->hw.cmos_data[RTC_SECONDS] = to_bcd(s, tm->tm_sec);
610
0
    s->hw.cmos_data[RTC_MINUTES] = to_bcd(s, tm->tm_min);
611
0
    if ( s->hw.cmos_data[RTC_REG_B] & RTC_24H )
612
0
    {
613
0
        /* 24 hour format */
614
0
        s->hw.cmos_data[RTC_HOURS] = to_bcd(s, tm->tm_hour);
615
0
    }
616
0
    else
617
0
    {
618
0
        /* 12 hour format */
619
0
        int h = (tm->tm_hour % 12) ? tm->tm_hour % 12 : 12;
620
0
        s->hw.cmos_data[RTC_HOURS] = to_bcd(s, h);
621
0
        if ( tm->tm_hour >= 12 )
622
0
            s->hw.cmos_data[RTC_HOURS] |= 0x80;
623
0
    }
624
0
    s->hw.cmos_data[RTC_DAY_OF_WEEK] = to_bcd(s, tm->tm_wday);
625
0
    s->hw.cmos_data[RTC_DAY_OF_MONTH] = to_bcd(s, tm->tm_mday);
626
0
    s->hw.cmos_data[RTC_MONTH] = to_bcd(s, tm->tm_mon + 1);
627
0
    s->hw.cmos_data[RTC_YEAR] = to_bcd(s, tm->tm_year % 100);
628
0
}
629
630
static int update_in_progress(RTCState *s)
631
0
{
632
0
    uint64_t guest_usec;
633
0
    struct domain *d = vrtc_domain(s);
634
0
635
0
    if (s->hw.cmos_data[RTC_REG_B] & RTC_SET)
636
0
        return 0;
637
0
638
0
    guest_usec = get_localtime_us(d);
639
0
    /* UIP bit will be set at last 244us of every second. */
640
0
    if ((guest_usec % USEC_PER_SEC) >= (USEC_PER_SEC - 244))
641
0
        return 1;
642
0
643
0
    return 0;
644
0
}
645
646
static uint32_t rtc_ioport_read(RTCState *s, uint32_t addr)
647
0
{
648
0
    int ret;
649
0
    struct domain *d = vrtc_domain(s);
650
0
651
0
    if ( (addr & 1) == 0 )
652
0
        return 0xff;
653
0
654
0
    spin_lock(&s->lock);
655
0
656
0
    switch ( s->hw.cmos_index )
657
0
    {
658
0
    case RTC_SECONDS:
659
0
    case RTC_MINUTES:
660
0
    case RTC_HOURS:
661
0
    case RTC_DAY_OF_WEEK:
662
0
    case RTC_DAY_OF_MONTH:
663
0
    case RTC_MONTH:
664
0
    case RTC_YEAR:
665
0
        /* if not in set mode, adjust cmos before reading*/
666
0
        if (!(s->hw.cmos_data[RTC_REG_B] & RTC_SET))
667
0
        {
668
0
            s->current_tm = gmtime(get_localtime(d));
669
0
            rtc_copy_date(s);
670
0
        }
671
0
        ret = s->hw.cmos_data[s->hw.cmos_index];
672
0
        break;
673
0
    case RTC_REG_A:
674
0
        ret = s->hw.cmos_data[s->hw.cmos_index];
675
0
        if ((s->use_timer == 0) && update_in_progress(s))
676
0
            ret |= RTC_UIP;
677
0
        break;
678
0
    case RTC_REG_C:
679
0
        check_for_pf_ticks(s);
680
0
        ret = s->hw.cmos_data[s->hw.cmos_index];
681
0
        s->hw.cmos_data[RTC_REG_C] = 0x00;
682
0
        if ( ret & RTC_IRQF )
683
0
            hvm_isa_irq_deassert(d, RTC_IRQ);
684
0
        check_update_timer(s);
685
0
        alarm_timer_update(s);
686
0
        s->pt_dead_ticks = 0;
687
0
        break;
688
0
    default:
689
0
        ret = s->hw.cmos_data[s->hw.cmos_index];
690
0
        break;
691
0
    }
692
0
693
0
    spin_unlock(&s->lock);
694
0
695
0
    return ret;
696
0
}
697
698
static int handle_rtc_io(
699
    int dir, unsigned int port, unsigned int bytes, uint32_t *val)
700
0
{
701
0
    struct RTCState *vrtc = vcpu_vrtc(current);
702
0
703
0
    if ( bytes != 1 )
704
0
    {
705
0
        gdprintk(XENLOG_WARNING, "HVM_RTC bad access\n");
706
0
        *val = ~0;
707
0
        return X86EMUL_OKAY;
708
0
    }
709
0
    
710
0
    if ( dir == IOREQ_WRITE )
711
0
    {
712
0
        if ( rtc_ioport_write(vrtc, port, (uint8_t)*val) )
713
0
            return X86EMUL_OKAY;
714
0
    }
715
0
    else if ( vrtc->hw.cmos_index < RTC_CMOS_SIZE )
716
0
    {
717
0
        *val = rtc_ioport_read(vrtc, port);
718
0
        return X86EMUL_OKAY;
719
0
    }
720
0
721
0
    return X86EMUL_UNHANDLEABLE;
722
0
}
723
724
void rtc_migrate_timers(struct vcpu *v)
725
548
{
726
548
    RTCState *s = vcpu_vrtc(v);
727
548
728
548
    if ( !has_vrtc(v->domain) )
729
548
        return;
730
548
731
0
    if ( v->vcpu_id == 0 )
732
0
    {
733
0
        migrate_timer(&s->update_timer, v->processor);
734
0
        migrate_timer(&s->update_timer2, v->processor);
735
0
        migrate_timer(&s->alarm_timer, v->processor);
736
0
    }
737
0
}
738
739
/* Save RTC hardware state */
740
static int rtc_save(struct domain *d, hvm_domain_context_t *h)
741
0
{
742
0
    RTCState *s = domain_vrtc(d);
743
0
    int rc;
744
0
745
0
    if ( !has_vrtc(d) )
746
0
        return 0;
747
0
748
0
    spin_lock(&s->lock);
749
0
    rc = hvm_save_entry(RTC, 0, h, &s->hw);
750
0
    spin_unlock(&s->lock);
751
0
    return rc;
752
0
}
753
754
/* Reload the hardware state from a saved domain */
755
static int rtc_load(struct domain *d, hvm_domain_context_t *h)
756
0
{
757
0
    RTCState *s = domain_vrtc(d);
758
0
759
0
    if ( !has_vrtc(d) )
760
0
        return -ENODEV;
761
0
762
0
    spin_lock(&s->lock);
763
0
764
0
    /* Restore the registers */
765
0
    if ( hvm_load_entry(RTC, h, &s->hw) != 0 )
766
0
    {
767
0
        spin_unlock(&s->lock);
768
0
        return -EINVAL;
769
0
    }
770
0
771
0
    /* Reset the wall-clock time.  In normal running, this runs with host 
772
0
     * time, so let's keep doing that. */
773
0
    s->current_tm = gmtime(get_localtime(d));
774
0
    rtc_copy_date(s);
775
0
776
0
    /* Reset the periodic interrupt timer based on the registers */
777
0
    rtc_timer_update(s);
778
0
    check_update_timer(s);
779
0
    alarm_timer_update(s);
780
0
781
0
    spin_unlock(&s->lock);
782
0
783
0
    return 0;
784
0
}
785
786
HVM_REGISTER_SAVE_RESTORE(RTC, rtc_save, rtc_load, 1, HVMSR_PER_DOM);
787
788
void rtc_reset(struct domain *d)
789
0
{
790
0
    RTCState *s = domain_vrtc(d);
791
0
792
0
    if ( !has_vrtc(d) )
793
0
        return;
794
0
795
0
    TRACE_0D(TRC_HVM_EMUL_RTC_STOP_TIMER);
796
0
    destroy_periodic_time(&s->pt);
797
0
    s->period = 0;
798
0
    s->pt.source = PTSRC_isa;
799
0
}
800
801
void rtc_init(struct domain *d)
802
1
{
803
1
    RTCState *s = domain_vrtc(d);
804
1
805
1
    if ( !has_vrtc(d) )
806
1
        return;
807
1
808
0
    spin_lock_init(&s->lock);
809
0
810
0
    init_timer(&s->update_timer, rtc_update_timer, s, smp_processor_id());
811
0
    init_timer(&s->update_timer2, rtc_update_timer2, s, smp_processor_id());
812
0
    init_timer(&s->alarm_timer, rtc_alarm_cb, s, smp_processor_id());
813
0
814
0
    register_portio_handler(d, RTC_PORT(0), 2, handle_rtc_io);
815
0
816
0
    rtc_reset(d);
817
0
818
0
    spin_lock(&s->lock);
819
0
820
0
    s->hw.cmos_data[RTC_REG_A] = RTC_REF_CLCK_32KHZ | 6; /* ~1kHz */
821
0
    s->hw.cmos_data[RTC_REG_B] = RTC_24H;
822
0
    s->hw.cmos_data[RTC_REG_C] = 0;
823
0
    s->hw.cmos_data[RTC_REG_D] = RTC_VRT;
824
0
825
0
    s->current_tm = gmtime(get_localtime(d));
826
0
    s->start_time = NOW();
827
0
828
0
    rtc_copy_date(s);
829
0
830
0
    check_update_timer(s);
831
0
    spin_unlock(&s->lock);
832
0
}
833
834
void rtc_deinit(struct domain *d)
835
0
{
836
0
    RTCState *s = domain_vrtc(d);
837
0
838
0
    if ( !has_vrtc(d) )
839
0
        return;
840
0
841
0
    spin_barrier(&s->lock);
842
0
843
0
    TRACE_0D(TRC_HVM_EMUL_RTC_STOP_TIMER);
844
0
    destroy_periodic_time(&s->pt);
845
0
    kill_timer(&s->update_timer);
846
0
    kill_timer(&s->update_timer2);
847
0
    kill_timer(&s->alarm_timer);
848
0
}
849
850
void rtc_update_clock(struct domain *d)
851
0
{
852
0
    RTCState *s = domain_vrtc(d);
853
0
854
0
    if ( !has_vrtc(d) )
855
0
        return;
856
0
857
0
    spin_lock(&s->lock);
858
0
    s->current_tm = gmtime(get_localtime(d));
859
0
    spin_unlock(&s->lock);
860
0
}
861
862
/*
863
 * Local variables:
864
 * mode: C
865
 * c-file-style: "BSD"
866
 * c-basic-offset: 4
867
 * indent-tabs-mode: nil
868
 * End:
869
 */