debuggers.hg

view xen/arch/x86/hvm/hpet.c @ 19950:721c14d7f60b

x86 hvm: Use 'x' as parameter name for macros converting between
{vcpu,domain} and {vlapic,vpic,vrtc,hpet}. Completely avoids
accidental aliasing.

Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Jul 08 14:22:00 2009 +0100 (2009-07-08)
parents a29bb4efff00
children 809b20f066fb
line source
1 /*
2 * hpet.c: HPET emulation for HVM guests.
3 * Copyright (c) 2006, Intel Corporation.
4 * Copyright (c) 2006, Keir Fraser <keir@xensource.com>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License along with
16 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
17 * Place - Suite 330, Boston, MA 02111-1307 USA.
18 */
20 #include <asm/hvm/vpt.h>
21 #include <asm/hvm/io.h>
22 #include <asm/hvm/support.h>
23 #include <asm/current.h>
24 #include <xen/sched.h>
25 #include <xen/event.h>
27 #define domain_vhpet(x) (&(x)->arch.hvm_domain.pl_time.vhpet)
28 #define vcpu_vhpet(x) (domain_vhpet((x)->domain))
29 #define vhpet_domain(x) (container_of((x), struct domain, \
30 arch.hvm_domain.pl_time.vhpet))
31 #define vhpet_vcpu(x) (pt_global_vcpu_target(vhpet_domain(x)))
33 #define HPET_BASE_ADDRESS 0xfed00000ULL
34 #define HPET_MMAP_SIZE 1024
35 #define S_TO_NS 1000000000ULL /* 1s = 10^9 ns */
36 #define S_TO_FS 1000000000000000ULL /* 1s = 10^15 fs */
38 /* Frequency_of_Xen_systeme_time / frequency_of_HPET = 16 */
39 #define STIME_PER_HPET_TICK 16
40 #define guest_time_hpet(hpet) \
41 (hvm_get_guest_time(vhpet_vcpu(hpet)) / STIME_PER_HPET_TICK)
43 #define HPET_ID 0x000
44 #define HPET_PERIOD 0x004
45 #define HPET_CFG 0x010
46 #define HPET_STATUS 0x020
47 #define HPET_COUNTER 0x0f0
48 #define HPET_T0_CFG 0x100
49 #define HPET_T0_CMP 0x108
50 #define HPET_T0_ROUTE 0x110
51 #define HPET_T1_CFG 0x120
52 #define HPET_T1_CMP 0x128
53 #define HPET_T1_ROUTE 0x130
54 #define HPET_T2_CFG 0x140
55 #define HPET_T2_CMP 0x148
56 #define HPET_T2_ROUTE 0x150
57 #define HPET_T3_CFG 0x160
59 #define HPET_CFG_ENABLE 0x001
60 #define HPET_CFG_LEGACY 0x002
62 #define HPET_TN_INT_TYPE_LEVEL 0x002
63 #define HPET_TN_ENABLE 0x004
64 #define HPET_TN_PERIODIC 0x008
65 #define HPET_TN_PERIODIC_CAP 0x010
66 #define HPET_TN_SIZE_CAP 0x020
67 #define HPET_TN_SETVAL 0x040
68 #define HPET_TN_32BIT 0x100
69 #define HPET_TN_INT_ROUTE_MASK 0x3e00
70 #define HPET_TN_INT_ROUTE_SHIFT 9
71 #define HPET_TN_INT_ROUTE_CAP_SHIFT 32
72 #define HPET_TN_CFG_BITS_READONLY_OR_RESERVED 0xffff80b1U
74 /* can be routed to IOAPIC.redirect_table[23..20] */
75 #define HPET_TN_INT_ROUTE_CAP (0x00f00000ULL \
76 << HPET_TN_INT_ROUTE_CAP_SHIFT)
78 #define HPET_TN_INT_ROUTE_CAP_MASK (0xffffffffULL \
79 << HPET_TN_INT_ROUTE_CAP_SHIFT)
81 #define hpet_tick_to_ns(h, tick) \
82 ((s_time_t)((((tick) > (h)->hpet_to_ns_limit) ? \
83 ~0ULL : (tick) * (h)->hpet_to_ns_scale) >> 10))
85 #define timer_config(h, n) (h->hpet.timers[n].config)
86 #define timer_enabled(h, n) (timer_config(h, n) & HPET_TN_ENABLE)
87 #define timer_is_periodic(h, n) (timer_config(h, n) & HPET_TN_PERIODIC)
88 #define timer_is_32bit(h, n) (timer_config(h, n) & HPET_TN_32BIT)
89 #define hpet_enabled(h) (h->hpet.config & HPET_CFG_ENABLE)
90 #define timer_level(h, n) (timer_config(h, n) & HPET_TN_INT_TYPE_LEVEL)
92 #define timer_int_route(h, n) \
93 ((timer_config(h, n) & HPET_TN_INT_ROUTE_MASK) >> HPET_TN_INT_ROUTE_SHIFT)
95 #define timer_int_route_cap(h, n) \
96 ((timer_config(h, n) & HPET_TN_INT_ROUTE_CAP_MASK) \
97 >> HPET_TN_INT_ROUTE_CAP_SHIFT)
99 static inline uint64_t hpet_read_maincounter(HPETState *h)
100 {
101 ASSERT(spin_is_locked(&h->lock));
103 if ( hpet_enabled(h) )
104 return guest_time_hpet(h) + h->mc_offset;
105 else
106 return h->hpet.mc64;
107 }
109 static uint64_t hpet_get_comparator(HPETState *h, unsigned int tn)
110 {
111 uint64_t comparator;
112 uint64_t elapsed;
114 comparator = h->hpet.comparator64[tn];
115 if ( timer_is_periodic(h, tn) )
116 {
117 /* update comparator by number of periods elapsed since last update */
118 uint64_t period = h->hpet.period[tn];
119 if (period)
120 {
121 elapsed = hpet_read_maincounter(h) + period - 1 - comparator;
122 comparator += (elapsed / period) * period;
123 h->hpet.comparator64[tn] = comparator;
124 }
125 }
127 /* truncate if timer is in 32 bit mode */
128 if ( timer_is_32bit(h, tn) )
129 comparator = (uint32_t)comparator;
130 h->hpet.timers[tn].cmp = comparator;
131 return comparator;
132 }
133 static inline uint64_t hpet_read64(HPETState *h, unsigned long addr)
134 {
135 addr &= ~7;
137 switch ( addr )
138 {
139 case HPET_ID:
140 return h->hpet.capability;
141 case HPET_CFG:
142 return h->hpet.config;
143 case HPET_STATUS:
144 return h->hpet.isr;
145 case HPET_COUNTER:
146 return hpet_read_maincounter(h);
147 case HPET_T0_CFG:
148 case HPET_T1_CFG:
149 case HPET_T2_CFG:
150 return h->hpet.timers[(addr - HPET_T0_CFG) >> 5].config;
151 case HPET_T0_CMP:
152 case HPET_T1_CMP:
153 case HPET_T2_CMP:
154 return hpet_get_comparator(h, (addr - HPET_T0_CMP) >> 5);
155 case HPET_T0_ROUTE:
156 case HPET_T1_ROUTE:
157 case HPET_T2_ROUTE:
158 return h->hpet.timers[(addr - HPET_T0_ROUTE) >> 5].fsb;
159 }
161 return 0;
162 }
164 static inline int hpet_check_access_length(
165 unsigned long addr, unsigned long len)
166 {
167 if ( (addr & (len - 1)) || (len > 8) )
168 {
169 /*
170 * According to ICH9 specification, unaligned accesses may result
171 * in unexpected behaviour or master abort, but should not crash/hang.
172 * Hence we read all-ones, drop writes, and log a warning.
173 */
174 gdprintk(XENLOG_WARNING, "HPET: access across register boundary: "
175 "%lx %lx\n", addr, len);
176 return -EINVAL;
177 }
179 return 0;
180 }
182 static int hpet_read(
183 struct vcpu *v, unsigned long addr, unsigned long length,
184 unsigned long *pval)
185 {
186 HPETState *h = vcpu_vhpet(v);
187 unsigned long result;
188 uint64_t val;
190 addr &= HPET_MMAP_SIZE-1;
192 if ( hpet_check_access_length(addr, length) != 0 )
193 {
194 result = ~0ul;
195 goto out;
196 }
198 spin_lock(&h->lock);
200 val = hpet_read64(h, addr);
202 result = val;
203 if ( length != 8 )
204 result = (val >> ((addr & 7) * 8)) & ((1ULL << (length * 8)) - 1);
206 spin_unlock(&h->lock);
208 out:
209 *pval = result;
210 return X86EMUL_OKAY;
211 }
213 static void hpet_stop_timer(HPETState *h, unsigned int tn)
214 {
215 ASSERT(tn < HPET_TIMER_NUM);
216 ASSERT(spin_is_locked(&h->lock));
217 destroy_periodic_time(&h->pt[tn]);
218 /* read the comparator to get it updated so a read while stopped will
219 * return the expected value. */
220 hpet_get_comparator(h, tn);
221 }
223 /* the number of HPET tick that stands for
224 * 1/(2^10) second, namely, 0.9765625 milliseconds */
225 #define HPET_TINY_TIME_SPAN ((h->stime_freq >> 10) / STIME_PER_HPET_TICK)
227 static void hpet_set_timer(HPETState *h, unsigned int tn)
228 {
229 uint64_t tn_cmp, cur_tick, diff;
230 unsigned int irq;
231 unsigned int oneshot;
233 ASSERT(tn < HPET_TIMER_NUM);
234 ASSERT(spin_is_locked(&h->lock));
236 if ( (tn == 0) && (h->hpet.config & HPET_CFG_LEGACY) )
237 {
238 /* HPET specification requires PIT shouldn't generate
239 * interrupts if LegacyReplacementRoute is set for timer0 */
240 PITState *pit = &vhpet_domain(h)->arch.hvm_domain.pl_time.vpit;
241 pit_stop_channel0_irq(pit);
242 }
244 if ( !timer_enabled(h, tn) )
245 return;
247 tn_cmp = hpet_get_comparator(h, tn);
248 cur_tick = hpet_read_maincounter(h);
249 if ( timer_is_32bit(h, tn) )
250 {
251 tn_cmp = (uint32_t)tn_cmp;
252 cur_tick = (uint32_t)cur_tick;
253 }
255 diff = tn_cmp - cur_tick;
257 /*
258 * Detect time values set in the past. This is hard to do for 32-bit
259 * comparators as the timer does not have to be set that far in the future
260 * for the counter difference to wrap a 32-bit signed integer. We fudge
261 * by looking for a 'small' time value in the past.
262 */
263 if ( (int64_t)diff < 0 )
264 diff = (timer_is_32bit(h, tn) && (-diff > HPET_TINY_TIME_SPAN))
265 ? (uint32_t)diff : 0;
267 if ( (tn <= 1) && (h->hpet.config & HPET_CFG_LEGACY) )
268 /* if LegacyReplacementRoute bit is set, HPET specification requires
269 timer0 be routed to IRQ0 in NON-APIC or IRQ2 in the I/O APIC,
270 timer1 be routed to IRQ8 in NON-APIC or IRQ8 in the I/O APIC. */
271 irq = (tn == 0) ? 0 : 8;
272 else
273 irq = timer_int_route(h, tn);
275 /*
276 * diff is the time from now when the timer should fire, for a periodic
277 * timer we also need the period which may be different because time may
278 * have elapsed between the time the comparator was written and the timer
279 * being enabled (now).
280 */
281 oneshot = !timer_is_periodic(h, tn);
282 create_periodic_time(vhpet_vcpu(h), &h->pt[tn],
283 hpet_tick_to_ns(h, diff),
284 oneshot ? 0 : hpet_tick_to_ns(h, h->hpet.period[tn]),
285 irq, NULL, NULL);
286 }
288 static inline uint64_t hpet_fixup_reg(
289 uint64_t new, uint64_t old, uint64_t mask)
290 {
291 new &= mask;
292 new |= old & ~mask;
293 return new;
294 }
296 static int hpet_write(
297 struct vcpu *v, unsigned long addr,
298 unsigned long length, unsigned long val)
299 {
300 HPETState *h = vcpu_vhpet(v);
301 uint64_t old_val, new_val;
302 int tn, i;
304 /* Acculumate a bit mask of timers whos state is changed by this write. */
305 unsigned long start_timers = 0;
306 unsigned long stop_timers = 0;
307 #define set_stop_timer(n) (__set_bit((n), &stop_timers))
308 #define set_start_timer(n) (__set_bit((n), &start_timers))
309 #define set_restart_timer(n) (set_stop_timer(n),set_start_timer(n))
311 addr &= HPET_MMAP_SIZE-1;
313 if ( hpet_check_access_length(addr, length) != 0 )
314 goto out;
316 spin_lock(&h->lock);
318 old_val = hpet_read64(h, addr);
319 new_val = val;
320 if ( length != 8 )
321 new_val = hpet_fixup_reg(
322 new_val << (addr & 7) * 8, old_val,
323 ((1ULL << (length*8)) - 1) << ((addr & 7) * 8));
325 switch ( addr & ~7 )
326 {
327 case HPET_CFG:
328 h->hpet.config = hpet_fixup_reg(new_val, old_val, 0x3);
330 if ( !(old_val & HPET_CFG_ENABLE) && (new_val & HPET_CFG_ENABLE) )
331 {
332 /* Enable main counter and interrupt generation. */
333 h->mc_offset = h->hpet.mc64 - guest_time_hpet(h);
334 for ( i = 0; i < HPET_TIMER_NUM; i++ )
335 {
336 h->hpet.comparator64[i] =
337 h->hpet.timers[i].config & HPET_TN_32BIT ?
338 (uint32_t)h->hpet.timers[i].cmp :
339 h->hpet.timers[i].cmp;
340 if ( timer_enabled(h, i) )
341 set_start_timer(i);
342 }
343 }
344 else if ( (old_val & HPET_CFG_ENABLE) && !(new_val & HPET_CFG_ENABLE) )
345 {
346 /* Halt main counter and disable interrupt generation. */
347 h->hpet.mc64 = h->mc_offset + guest_time_hpet(h);
348 for ( i = 0; i < HPET_TIMER_NUM; i++ )
349 if ( timer_enabled(h, i) )
350 set_stop_timer(i);
351 }
352 break;
354 case HPET_COUNTER:
355 h->hpet.mc64 = new_val;
356 if ( hpet_enabled(h) )
357 {
358 gdprintk(XENLOG_WARNING,
359 "HPET: writing main counter but it's not halted!\n");
360 for ( i = 0; i < HPET_TIMER_NUM; i++ )
361 if ( timer_enabled(h, i) )
362 set_restart_timer(i);
363 }
364 break;
366 case HPET_T0_CFG:
367 case HPET_T1_CFG:
368 case HPET_T2_CFG:
369 tn = (addr - HPET_T0_CFG) >> 5;
371 h->hpet.timers[tn].config = hpet_fixup_reg(new_val, old_val, 0x3f4e);
373 if ( timer_level(h, tn) )
374 {
375 gdprintk(XENLOG_ERR,
376 "HPET: level triggered interrupt not supported now\n");
377 domain_crash(current->domain);
378 break;
379 }
381 if ( new_val & HPET_TN_32BIT )
382 {
383 h->hpet.timers[tn].cmp = (uint32_t)h->hpet.timers[tn].cmp;
384 h->hpet.period[tn] = (uint32_t)h->hpet.period[tn];
385 }
386 if ( hpet_enabled(h) )
387 {
388 if ( new_val & HPET_TN_ENABLE )
389 {
390 if ( (new_val ^ old_val) & HPET_TN_PERIODIC )
391 /* timer is enabled but switching mode to/from periodic/
392 * one-shot, stop and restart the vpt timer to get it in
393 * the right mode. */
394 set_restart_timer(tn);
395 else if ( (new_val & HPET_TN_32BIT) &&
396 !(old_val & HPET_TN_32BIT) )
397 /* switching from 64 bit to 32 bit mode could cause timer
398 * next fire time, or period, to change. */
399 set_restart_timer(tn);
400 else if ( !(old_val & HPET_TN_ENABLE) )
401 /* transition from timer disabled to timer enabled. */
402 set_start_timer(tn);
403 }
404 else if ( old_val & HPET_TN_ENABLE )
405 /* transition from timer enabled to timer disabled. */
406 set_stop_timer(tn);
407 }
408 break;
410 case HPET_T0_CMP:
411 case HPET_T1_CMP:
412 case HPET_T2_CMP:
413 tn = (addr - HPET_T0_CMP) >> 5;
414 if ( timer_is_32bit(h, tn) )
415 new_val = (uint32_t)new_val;
416 h->hpet.timers[tn].cmp = new_val;
417 if ( h->hpet.timers[tn].config & HPET_TN_SETVAL )
418 /*
419 * When SETVAL is one, software is able to "directly set a periodic
420 * timer's accumulator." That is, set the comparator without
421 * adjusting the period. Much the same as just setting the
422 * comparator on an enabled one-shot timer.
423 *
424 * This configuration bit clears when the comparator is written.
425 */
426 h->hpet.timers[tn].config &= ~HPET_TN_SETVAL;
427 else if ( timer_is_periodic(h, tn) )
428 {
429 /*
430 * Clamp period to reasonable min/max values:
431 * - minimum is 100us, same as timers controlled by vpt.c
432 * - maximum is to prevent overflow in time_after() calculations
433 */
434 if ( hpet_tick_to_ns(h, new_val) < MICROSECS(100) )
435 new_val = (MICROSECS(100) << 10) / h->hpet_to_ns_scale;
436 new_val &= (timer_is_32bit(h, tn) ? ~0u : ~0ull) >> 1;
437 h->hpet.period[tn] = new_val;
438 }
439 h->hpet.comparator64[tn] = new_val;
440 if ( hpet_enabled(h) && timer_enabled(h, tn) )
441 set_restart_timer(tn);
442 break;
444 case HPET_T0_ROUTE:
445 case HPET_T1_ROUTE:
446 case HPET_T2_ROUTE:
447 tn = (addr - HPET_T0_ROUTE) >> 5;
448 h->hpet.timers[tn].fsb = new_val;
449 break;
451 default:
452 /* Ignore writes to unsupported and reserved registers. */
453 break;
454 }
456 /* stop/start timers whos state was changed by this write. */
457 while (stop_timers)
458 {
459 i = find_first_set_bit(stop_timers);
460 __clear_bit(i, &stop_timers);
461 hpet_stop_timer(h, i);
462 }
464 while (start_timers)
465 {
466 i = find_first_set_bit(start_timers);
467 __clear_bit(i, &start_timers);
468 hpet_set_timer(h, i);
469 }
471 #undef set_stop_timer
472 #undef set_start_timer
473 #undef set_restart_timer
475 spin_unlock(&h->lock);
477 out:
478 return X86EMUL_OKAY;
479 }
481 static int hpet_range(struct vcpu *v, unsigned long addr)
482 {
483 return (v->domain->arch.hvm_domain.params[HVM_PARAM_HPET_ENABLED] &&
484 (addr >= HPET_BASE_ADDRESS) &&
485 (addr < (HPET_BASE_ADDRESS + HPET_MMAP_SIZE)));
486 }
488 struct hvm_mmio_handler hpet_mmio_handler = {
489 .check_handler = hpet_range,
490 .read_handler = hpet_read,
491 .write_handler = hpet_write
492 };
495 static int hpet_save(struct domain *d, hvm_domain_context_t *h)
496 {
497 HPETState *hp = domain_vhpet(d);
498 int rc;
500 spin_lock(&hp->lock);
502 /* Write the proper value into the main counter */
503 hp->hpet.mc64 = hp->mc_offset + guest_time_hpet(hp);
505 /* Save the HPET registers */
506 rc = _hvm_init_entry(h, HVM_SAVE_CODE(HPET), 0, HVM_SAVE_LENGTH(HPET));
507 if ( rc == 0 )
508 {
509 struct hvm_hw_hpet *rec = (struct hvm_hw_hpet *)&h->data[h->cur];
510 h->cur += HVM_SAVE_LENGTH(HPET);
511 memset(rec, 0, HVM_SAVE_LENGTH(HPET));
512 #define C(x) rec->x = hp->hpet.x
513 C(capability);
514 C(config);
515 C(isr);
516 C(mc64);
517 C(timers[0].config);
518 C(timers[0].fsb);
519 C(timers[1].config);
520 C(timers[1].fsb);
521 C(timers[2].config);
522 C(timers[2].fsb);
523 C(period[0]);
524 C(period[1]);
525 C(period[2]);
526 #undef C
527 /* save the 64 bit comparator in the 64 bit timer[n].cmp field
528 * regardless of whether or not the timer is in 32 bit mode. */
529 rec->timers[0].cmp = hp->hpet.comparator64[0];
530 rec->timers[1].cmp = hp->hpet.comparator64[1];
531 rec->timers[2].cmp = hp->hpet.comparator64[2];
532 }
534 spin_unlock(&hp->lock);
536 return rc;
537 }
539 static int hpet_load(struct domain *d, hvm_domain_context_t *h)
540 {
541 HPETState *hp = domain_vhpet(d);
542 struct hvm_hw_hpet *rec;
543 uint64_t cmp;
544 int i;
546 spin_lock(&hp->lock);
548 /* Reload the HPET registers */
549 if ( _hvm_check_entry(h, HVM_SAVE_CODE(HPET), HVM_SAVE_LENGTH(HPET)) )
550 {
551 spin_unlock(&hp->lock);
552 return -EINVAL;
553 }
555 rec = (struct hvm_hw_hpet *)&h->data[h->cur];
556 h->cur += HVM_SAVE_LENGTH(HPET);
558 #define C(x) hp->hpet.x = rec->x
559 C(capability);
560 C(config);
561 C(isr);
562 C(mc64);
563 /* The following define will generate a compiler error if HPET_TIMER_NUM
564 * changes. This indicates an incompatability with previous saved state. */
565 #define HPET_TIMER_NUM 3
566 for ( i = 0; i < HPET_TIMER_NUM; i++ )
567 {
568 C(timers[i].config);
569 C(timers[i].fsb);
570 C(period[i]);
571 /* restore the hidden 64 bit comparator and truncate the timer's
572 * visible comparator field if in 32 bit mode. */
573 cmp = rec->timers[i].cmp;
574 hp->hpet.comparator64[i] = cmp;
575 if ( timer_is_32bit(hp, i) )
576 cmp = (uint32_t)cmp;
577 hp->hpet.timers[i].cmp = cmp;
578 }
579 #undef C
581 /* Recalculate the offset between the main counter and guest time */
582 hp->mc_offset = hp->hpet.mc64 - guest_time_hpet(hp);
584 /* restart all timers */
586 if ( hpet_enabled(hp) )
587 for ( i = 0; i < HPET_TIMER_NUM; i++ )
588 if ( timer_enabled(hp, i) )
589 hpet_set_timer(hp, i);
591 spin_unlock(&hp->lock);
593 return 0;
594 }
596 HVM_REGISTER_SAVE_RESTORE(HPET, hpet_save, hpet_load, 1, HVMSR_PER_DOM);
598 void hpet_init(struct vcpu *v)
599 {
600 HPETState *h = vcpu_vhpet(v);
601 int i;
603 memset(h, 0, sizeof(HPETState));
605 spin_lock_init(&h->lock);
607 h->stime_freq = S_TO_NS;
609 h->hpet_to_ns_scale = ((S_TO_NS * STIME_PER_HPET_TICK) << 10) / h->stime_freq;
610 h->hpet_to_ns_limit = ~0ULL / h->hpet_to_ns_scale;
612 /* 64-bit main counter; 3 timers supported; LegacyReplacementRoute. */
613 h->hpet.capability = 0x8086A201ULL;
615 /* This is the number of femptoseconds per HPET tick. */
616 /* Here we define HPET's frequency to be 1/16 of Xen system time */
617 h->hpet.capability |= ((S_TO_FS*STIME_PER_HPET_TICK/h->stime_freq) << 32);
619 for ( i = 0; i < HPET_TIMER_NUM; i++ )
620 {
621 h->hpet.timers[i].config =
622 HPET_TN_INT_ROUTE_CAP | HPET_TN_SIZE_CAP | HPET_TN_PERIODIC_CAP;
623 h->hpet.timers[i].cmp = ~0ULL;
624 h->pt[i].source = PTSRC_isa;
625 }
626 }
628 void hpet_deinit(struct domain *d)
629 {
630 int i;
631 HPETState *h = domain_vhpet(d);
633 spin_lock(&h->lock);
635 if ( hpet_enabled(h) )
636 for ( i = 0; i < HPET_TIMER_NUM; i++ )
637 if ( timer_enabled(h, i) )
638 hpet_stop_timer(h, i);
640 spin_unlock(&h->lock);
641 }
643 void hpet_reset(struct domain *d)
644 {
645 hpet_deinit(d);
646 hpet_init(d->vcpu[0]);
647 }