/* * Xen emulation for hpet * * Copyright (C) 2014 Verizon Corporation * * This file is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License Version 2 (GPLv2) * as published by the Free Software Foundation. * * This file is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. . */ /* * http://www.intel.com/content/dam/www/public/us/en/documents/technical-specifications/software-developers-hpet-spec-1-0a.pdf * * xen_source is a directory that has all xen source below it. * * Usage: * xen_source=../../.. sed -e "/#include/d" -e "1i#include \"emul.h\"\n" <$xen_source/xen/arch/x86/hvm/hpet.c >hpet.c cp $xen_source/xen/include/asm-x86/hpet.h . gcc -g -o test_vhpet hpet.c main.c ./test_vhpet >test_vhpet.out * * * This is almost the same as * make run * * Or * * make -C tools/tests/vhpet run * * From a xen source tree. The differance * is that you need to be in a xen source tree * and normal make rules apply. * */ #define FORCE_THOUSANDS_SEP #include #include #include #include "emul.h" #include "hpet.h" #define S_TO_NS 1000000000ULL /* 1s = 10^9 ns */ #define START_MC64 0x108a8 static int hpet_mult = 1; static int hpet_add; static int hvm_clock_cost = 1234567; static int tick_count = 1; static int debug = 3; static int skip_load; static int skip_error_on_load; static char *global_thousep; extern const struct hvm_mmio_ops hpet_mmio_ops; struct domain dom1; struct vcpu vcpu0; struct hvm_hw_hpet hpet_save; uint64_t hvm_guest_time; static struct { hvm_save_handler save; hvm_load_handler load; const char *name; size_t size; int kind; } hvm_sr_handlers[3] = {{NULL, NULL, ""},}; static uint64_t new_guest_time[] = { 0x20, 0x2a840, 0xf4200, 0x10000000000ULL, 0x0fffffffffefff00ULL, 0x20, 0xffffffff00000000ULL, 0x20, }; static int print_error(const char *fmt, ...) { va_list args; int i = 0; if ( (debug & 0x0100) && skip_error_on_load ) return i; va_start(args, fmt); if ( debug & 0x0001 ) i = vfprintf(stdout, fmt, args); va_end(args); va_start(args, fmt); if ( debug & 0x0002 ) i = vfprintf(stderr, fmt, args); va_end(args); return i; } int current_domain_id(void) { return current->domain->domain_id; } struct vcpu *get_current() { return &vcpu0; } void __domain_crash(struct domain *d) { exit(42); } uint64_t hvm_get_guest_time(struct vcpu *v) { uint64_t ret = hvm_guest_time; hvm_guest_time += hvm_clock_cost; return ret; } int _hvm_init_entry(struct hvm_domain_context *h, uint16_t tc, uint16_t inst, uint32_t len) { h->cur = 0; h->size = sizeof(hpet_save); h->data = (void *)&hpet_save; return 0; } int _hvm_check_entry(struct hvm_domain_context *h, uint16_t type, uint32_t len, bool_t strict_length) { h->cur = 0; h->size = sizeof(hpet_save); h->data = (void *)&hpet_save; return 0; } void __init hvm_register_savevm(uint16_t typecode, const char *name, hvm_save_handler save_state, hvm_load_handler load_state, size_t size, int kind) { hvm_sr_handlers[typecode].save = save_state; hvm_sr_handlers[typecode].load = load_state; hvm_sr_handlers[typecode].name = name; hvm_sr_handlers[typecode].size = size; hvm_sr_handlers[typecode].kind = kind; } int do_save(uint16_t typecode, struct domain *d, hvm_domain_context_t *h) { return hvm_sr_handlers[typecode].save(d, h); } int do_load(uint16_t typecode, struct domain *d, hvm_domain_context_t *h) { if (skip_load & 0x1) { printf("skip_load=%#x\n", skip_load); } else { int ret; printf("do_load\n"); skip_error_on_load = 1; ret = hvm_sr_handlers[typecode].load(d, h); skip_error_on_load = 0; } } static void dump_hpet(void) { int i; unsigned long long conf; struct hvm_hw_hpet h = hpet_save; conf = (unsigned long long) h.config; printf(" HPET: capability %#llx config %#llx(%s%s)\n", (unsigned long long) h.capability, conf, conf & HPET_CFG_ENABLE ? "E" : "", conf & HPET_CFG_LEGACY ? "L" : ""); printf(" isr %#llx counter %#llx(%'lld)\n", (unsigned long long) h.isr, (unsigned long long) h.mc64, (unsigned long long) h.mc64); for (i = 0; i < HPET_TIMER_NUM; i++) { conf = (unsigned long long) h.timers[i].config; printf(" timer%i config %#llx(%s%s%s) cmp %#llx(%'lld)\n", i, conf, conf & HPET_TN_ENABLE ? "E" : "", conf & HPET_TN_PERIODIC ? "P" : "", conf & HPET_TN_32BIT ? "32" : "", (unsigned long long) h.timers[i].cmp, (unsigned long long) h.timers[i].cmp); printf(" timer%i period %#llx(%'lld) fsb %#llx\n", i, (unsigned long long) h.period[i], (unsigned long long) h.period[i], (unsigned long long) h.timers[i].fsb); } } void pit_stop_channel0_irq(PITState *pit) { printf("pit_stop_channel0_irq: pit=%p\n", pit); TRACE_1D(TRC_HVM_VCHIP_PIT_STOP_TIMER, get_cycles()); spin_lock(&pit->lock); destroy_periodic_time(&pit->pt0); spin_unlock(&pit->lock); } void destroy_periodic_time(struct periodic_time *pt) { int idx = ((long)pt) & 0x7; printf("destroy_periodic_time: pt=%d\n", idx); } void create_periodic_time(struct vcpu *v, struct periodic_time *pt, uint64_t delta, uint64_t period, uint8_t irq, time_cb *cb, void *data) { int idx = ((long)pt) & 0x7; if ( debug & 0x0010 ) { int i; printf("create_periodic_time: " "mc64=%#lx(%'ld) mc_offset=%#lx(%'ld)\n", dom1.arch.hvm_domain.pl_time.vhpet.hpet.mc64, dom1.arch.hvm_domain.pl_time.vhpet.hpet.mc64, dom1.arch.hvm_domain.pl_time.vhpet.mc_offset, dom1.arch.hvm_domain.pl_time.vhpet.mc_offset); for (i = 0; i < 3; i++) { printf(" " "[%d] cmp64=%#lx(%'ld) cmp=%#lx(%'ld)\n", i, dom1.arch.hvm_domain.pl_time.vhpet.hpet.comparator64[i], dom1.arch.hvm_domain.pl_time.vhpet.hpet.comparator64[i], dom1.arch.hvm_domain.pl_time.vhpet.hpet.timers[i].cmp, dom1.arch.hvm_domain.pl_time.vhpet.hpet.timers[i].cmp); } } if ( period ) { printf("create_periodic_time: pt=%d delta=%'"PRId64" period=%'"PRIu64 " - %'"PRIu64".%02d Hz irq=%d\n", idx, delta, period, (uint64_t)(S_TO_NS / period), (int)((S_TO_NS / (period / 100ULL)) % 100), irq); /* +160 is for hpet_tick_to_ns() not simple. */ if ( delta > (period * (hpet_mult + hpet_add + 160)) ) print_error("%s(%ld): Possible ..MP-BIOS bug: 8254 timer...: delta=%'"PRId64 " period=%'"PRIu64"\n", __func__, __LINE__, delta, period); } else printf("create_periodic_time: pt=%d delta=%'"PRId64 " period=%'"PRIu64" irq=%d\n", idx, delta, period, irq); } void udelay(int w) { } unsigned int hpet_readl(unsigned long a) { unsigned long ret = 0; hpet_mmio_ops.read(current, a, 4, &ret); return ret; } void hpet_writel(unsigned long d, unsigned long a) { hpet_mmio_ops.write(current, a, 4, d); return; } static void _hpet_print_config(const char *function, int line) { u32 i, timers, l, h; printk(KERN_INFO "hpet: %s(%d):\n", function, line); l = hpet_readl(HPET_ID); h = hpet_readl(HPET_PERIOD); timers = ((l & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT) + 1; printk(KERN_INFO "hpet: ID: 0x%x, PERIOD: 0x%x\n", l, h); l = hpet_readl(HPET_CFG); h = hpet_readl(HPET_STATUS); printk(KERN_INFO "hpet: CFG: 0x%x, STATUS: 0x%x\n", l, h); l = hpet_readl(HPET_COUNTER); h = hpet_readl(HPET_COUNTER + 4); printk(KERN_INFO "hpet: COUNTER_l: 0x%x, COUNTER_h: 0x%x\n", l, h); for (i = 0; i < timers; i++) { l = hpet_readl(HPET_Tn_CFG(i)); h = hpet_readl(HPET_Tn_CFG(i) + 4); printk(KERN_INFO "hpet: T%d: CFG_l: 0x%x, CFG_h: 0x%x\n", i, l, h); l = hpet_readl(HPET_Tn_CMP(i)); h = hpet_readl(HPET_Tn_CMP(i) + 4); printk(KERN_INFO "hpet: T%d: CMP_l: 0x%x, CMP_h: 0x%x\n", i, l, h); l = hpet_readl(HPET_Tn_ROUTE(i)); h = hpet_readl(HPET_Tn_ROUTE(i) + 4); printk(KERN_INFO "hpet: T%d ROUTE_l: 0x%x, ROUTE_h: 0x%x\n", i, l, h); } } #define hpet_print_config() \ do { \ _hpet_print_config(__func__, __LINE__); \ } while ( 0 ) static void hpet_stop_counter(void) { unsigned long cfg = hpet_readl(HPET_CFG); cfg &= ~HPET_CFG_ENABLE; hpet_writel(cfg, HPET_CFG); } static void hpet_reset_counter(unsigned long low, unsigned long high) { hpet_writel(low, HPET_COUNTER); hpet_writel(high, HPET_COUNTER + 4); } static void hpet_start_counter(void) { unsigned long cfg = hpet_readl(HPET_CFG); cfg |= HPET_CFG_ENABLE; hpet_writel(cfg, HPET_CFG); } static void hpet_restart_counter(void) { hpet_stop_counter(); hpet_reset_counter(0, 0); hpet_start_counter(); } static void hpet_set_mode(uint64_t delta, int timer) { unsigned long cfg, cmp, cmp2, now; hpet_stop_counter(); now = hpet_readl(HPET_COUNTER); cmp = now + (unsigned long)(hpet_mult * delta) + hpet_add; cfg = hpet_readl(HPET_Tn_CFG(timer)); /* Make sure we use edge triggered interrupts */ cfg &= ~HPET_TN_LEVEL; cfg |= HPET_TN_ENABLE | HPET_TN_PERIODIC | HPET_TN_SETVAL | HPET_TN_32BIT; /* Mask to 32 bits just like the hardware */ cmp = (uint32_t)cmp; delta = (uint32_t)delta; /* Do the config */ hpet_writel(cfg, HPET_Tn_CFG(timer)); hpet_writel(cmp, HPET_Tn_CMP(timer)); printf("%s(%ld): HPET_TN_SETVAL cmp=%#lx(%'ld) timer=%d\n", __func__, __LINE__, cmp, cmp, timer); udelay(1); /* * HPET on AMD 81xx needs a second write (with HPET_TN_SETVAL * cleared) to T0_CMP to set the period. The HPET_TN_SETVAL * bit is automatically cleared after the first write. * (See AMD-8111 HyperTransport I/O Hub Data Sheet, * Publication # 24674) */ hpet_writel((unsigned long) delta, HPET_Tn_CMP(timer)); printf("%s(%ld): period=%#lx(%'ld) timer=%d\n", __func__, __LINE__, (unsigned long) delta, (unsigned long) delta, timer); cmp2 = hpet_readl(HPET_Tn_CMP(timer)); if ( cmp2 != cmp ) print_error("%s(%ld): T%d Error: Set %#lx(%'ld) != %#lx(%'ld)\n", __func__, __LINE__, timer, cmp, cmp, cmp2, cmp2); hpet_start_counter(); hpet_print_config(); } hpet_check_stopped(uint64_t old_delta, int timer) { unsigned long mc_low, mc_high, old_cmp, now; unsigned long cfg, cmp, delta, cmp2, cmp3; if (skip_load & 0x2) { printf("Skip hpet_check_stopped. skip_load=%#x\n", skip_load); return; } hpet_stop_counter(); mc_low = hpet_readl(HPET_COUNTER); mc_high = hpet_readl(HPET_COUNTER + 4); old_cmp = hpet_readl(HPET_Tn_CMP(timer)); hpet_reset_counter(67752, 0); cmp = 255252; delta = 62500; now = hpet_readl(HPET_COUNTER); if ( now != 67752 ) print_error("%s(%ld): T%d Error: Set mc %#lx(%'ld) != %#lx(%'ld)\n", __func__, __LINE__, timer, 67752, 67752, now, now); cfg = hpet_readl(HPET_Tn_CFG(timer)); cfg |= HPET_TN_SETVAL; hpet_writel(cfg, HPET_Tn_CFG(timer)); hpet_writel(cmp, HPET_Tn_CMP(timer)); printf("%s(%ld): HPET_TN_SETVAL cmp=%#lx(%'ld) timer=%d\n", __func__, __LINE__, cmp, cmp, timer); cmp2 = hpet_readl(HPET_Tn_CMP(timer)); if ( cmp2 != cmp ) print_error("%s(%ld): T%d Error: Set cmp %#lx(%'ld) != %#lx(%'ld)\n", __func__, __LINE__, timer, cmp, cmp, cmp2, cmp2); hpet_writel((unsigned long) delta, HPET_Tn_CMP(timer)); printf("%s(%ld): period=%#lx(%'ld) timer=%d\n", __func__, __LINE__, (unsigned long) delta, (unsigned long) delta, timer); cmp3 = hpet_readl(HPET_Tn_CMP(timer)); if ( cmp3 != cmp ) print_error("%s(%ld): T%d Error: Set period, cmp %#lx(%'ld) != %#lx(%'ld)\n", __func__, __LINE__, timer, cmp, cmp, cmp3, cmp3); if ( dom1.arch.hvm_domain.pl_time.vhpet.hpet.period[timer] != delta ) printf("%s(%ld): T%d Warning: Set period %#lx(%'ld) != %#lx(%'ld)\n", __func__, __LINE__, timer, delta, delta, dom1.arch.hvm_domain.pl_time.vhpet.hpet.period[timer], dom1.arch.hvm_domain.pl_time.vhpet.hpet.period[timer]); hpet_reset_counter(67752, 0); cmp = 255252; delta = 62500; now = hpet_readl(HPET_COUNTER); if ( now != 67752 ) print_error("%s(%ld): T%d Error: Set mc %#lx(%'ld) != %#lx(%'ld)\n", __func__, __LINE__, timer, 67752, 67752, now, now); cfg = hpet_readl(HPET_Tn_CFG(timer)); cfg |= HPET_TN_SETVAL; hpet_writel(cfg, HPET_Tn_CFG(timer)); hpet_writel(cmp, HPET_Tn_CMP(timer)); printf("%s(%ld): HPET_TN_SETVAL cmp=%#lx(%'ld) timer=%d\n", __func__, __LINE__, cmp, cmp, timer); cmp2 = hpet_readl(HPET_Tn_CMP(timer)); if ( cmp2 != cmp ) print_error("%s(%ld): T%d Error: Set cmp %#lx(%'ld) != %#lx(%'ld)\n", __func__, __LINE__, timer, cmp, cmp, cmp2, cmp2); hpet_writel((unsigned long) delta, HPET_Tn_CMP(timer)); printf("%s(%ld): period=%#lx(%'ld) timer=%d\n", __func__, __LINE__, (unsigned long) delta, (unsigned long) delta, timer); cmp3 = hpet_readl(HPET_Tn_CMP(timer)); if ( cmp3 != cmp ) print_error("%s(%ld): T%d Error: Set period, cmp %#lx(%'ld) != %#lx(%'ld)\n", __func__, __LINE__, timer, cmp, cmp, cmp3, cmp3); if ( dom1.arch.hvm_domain.pl_time.vhpet.hpet.period[timer] != delta ) printf("%s(%ld): T%d Warning: Set period %#lx(%'ld) != %#lx(%'ld)\n", __func__, __LINE__, timer, delta, delta, dom1.arch.hvm_domain.pl_time.vhpet.hpet.period[timer], dom1.arch.hvm_domain.pl_time.vhpet.hpet.period[timer]); hpet_reset_counter(67700, 0); now = hpet_readl(HPET_COUNTER); if ( now != 67700 ) print_error("%s(%ld): T%d Error: Set mc %#lx(%'ld) != %#lx(%'ld)\n", __func__, __LINE__, timer, 67752, 67752, now, now); cmp2 = hpet_readl(HPET_Tn_CMP(timer)); if ( cmp2 != cmp ) print_error("%s(%ld): T%d Error: Set mc, cmp %#lx(%'ld) != %#lx(%'ld)\n", __func__, __LINE__, timer, cmp, cmp, cmp2, cmp2); cmp3 = hpet_readl(HPET_Tn_CMP(timer)); if ( cmp3 != cmp ) print_error("%s(%ld): T%d Error: Set mc, cmp %#lx(%'ld) != %#lx(%'ld)\n", __func__, __LINE__, timer, cmp, cmp, cmp3, cmp3); if ( dom1.arch.hvm_domain.pl_time.vhpet.hpet.period[timer] != delta ) printf("%s(%ld): T%d Warning: Set mc, period %#lx(%'ld) != %#lx(%'ld)\n", __func__, __LINE__, timer, delta, delta, dom1.arch.hvm_domain.pl_time.vhpet.hpet.period[timer], dom1.arch.hvm_domain.pl_time.vhpet.hpet.period[timer]); cmp = 67701; now = hpet_readl(HPET_COUNTER); if ( now != 67700 ) print_error("%s(%ld): T%d Error: Set cmp, mc %#lx(%'ld) != %#lx(%'ld)\n", __func__, __LINE__, timer, 67752, 67752, now, now); cfg = hpet_readl(HPET_Tn_CFG(timer)); cfg |= HPET_TN_SETVAL; hpet_writel(cfg, HPET_Tn_CFG(timer)); hpet_writel(cmp, HPET_Tn_CMP(timer)); printf("%s(%ld): HPET_TN_SETVAL cmp=%#lx(%'ld) timer=%d\n", __func__, __LINE__, cmp, cmp, timer); cmp2 = hpet_readl(HPET_Tn_CMP(timer)); if ( cmp2 != cmp ) print_error("%s(%ld): T%d Error: Set cmp, cmp %#lx(%'ld) != %#lx(%'ld)\n", __func__, __LINE__, timer, cmp, cmp, cmp2, cmp2); cmp3 = hpet_readl(HPET_Tn_CMP(timer)); if ( cmp3 != cmp ) print_error("%s(%ld): T%d Error: Set cmp, cmp %#lx(%'ld) != %#lx(%'ld)\n", __func__, __LINE__, timer, cmp, cmp, cmp3, cmp3); if ( dom1.arch.hvm_domain.pl_time.vhpet.hpet.period[timer] != delta ) printf("%s(%ld): T%d Warning: Set cmp, period %#lx(%'ld) != %#lx(%'ld)\n", __func__, __LINE__, timer, delta, delta, dom1.arch.hvm_domain.pl_time.vhpet.hpet.period[timer], dom1.arch.hvm_domain.pl_time.vhpet.hpet.period[timer]); delta = 500; now = hpet_readl(HPET_COUNTER); if ( now != 67700 ) print_error("%s(%ld): T%d Error: Set period, mc %#lx(%'ld) != %#lx(%'ld)\n", __func__, __LINE__, timer, 67752, 67752, now, now); cmp2 = hpet_readl(HPET_Tn_CMP(timer)); if ( cmp2 != cmp ) print_error("%s(%ld): T%d Error: Set period, cmp %#lx(%'ld) != %#lx(%'ld)\n", __func__, __LINE__, timer, cmp, cmp, cmp2, cmp2); hpet_writel((unsigned long) delta, HPET_Tn_CMP(timer)); printf("%s(%ld): period=%#lx(%'ld) timer=%d\n", __func__, __LINE__, (unsigned long) delta, (unsigned long) delta, timer); cmp3 = hpet_readl(HPET_Tn_CMP(timer)); if ( cmp3 != cmp ) print_error("%s(%ld): T%d Error: Set period, cmp %#lx(%'ld) != %#lx(%'ld)\n", __func__, __LINE__, timer, cmp, cmp, cmp3, cmp3); if ( dom1.arch.hvm_domain.pl_time.vhpet.hpet.period[timer] != delta ) printf("%s(%ld): T%d Warning: Set period, period %#lx(%'ld) != %#lx(%'ld)\n", __func__, __LINE__, timer, delta, delta, dom1.arch.hvm_domain.pl_time.vhpet.hpet.period[timer], dom1.arch.hvm_domain.pl_time.vhpet.hpet.period[timer]); hpet_reset_counter(mc_low, mc_high); cfg = hpet_readl(HPET_Tn_CFG(timer)); cfg |= HPET_TN_SETVAL; hpet_writel(cfg, HPET_Tn_CFG(timer)); hpet_writel(old_cmp, HPET_Tn_CMP(timer)); hpet_writel(old_delta, HPET_Tn_CMP(timer)); hpet_start_counter(); } int main(int argc, char **argv) { hvm_domain_context_t hdc; struct hvm_hw_hpet hpet0; struct hvm_hw_hpet hpet1; struct hvm_hw_hpet hpet2; int i, k; setlocale(LC_ALL, ""); #ifdef FORCE_THOUSANDS_SEP setlocale(LC_NUMERIC, "en_US.utf8"); #endif global_thousep = nl_langinfo(THOUSEP); printf("test_vhpet 1.0\n"); if ( argc > 1 ) hvm_clock_cost = atoi(argv[1]); if ( argc > 2 ) hpet_mult = atoi(argv[2]); if ( argc > 3 ) hpet_add = atoi(argv[3]); if ( argc > 4 ) tick_count = atoi(argv[4]); if ( argc > 5 ) debug = strtol(argv[5], NULL, 0); printf("hvm_clock_cost=%'d hpet_mult=%'d hpet_add=%'d tick_count=%d debug=%#x\n", hvm_clock_cost, hpet_mult, hpet_add, tick_count, debug); dom1.domain_id = 1; dom1.vcpu[0] = &vcpu0; vcpu0.vcpu_id = 0; vcpu0.domain = &dom1; __hvm_register_HPET_save_and_restore(); for (skip_load = 3; skip_load >= 0; skip_load--) { printf("\nskip_load=%d\n", skip_load); hvm_guest_time = 16; hpet_init(&vcpu0); do_save(HVM_SAVE_CODE(HPET), &dom1, &hdc); dump_hpet(); hpet0 = hpet_save; do_save(HVM_SAVE_CODE(HPET), &dom1, &hdc); dump_hpet(); hpet1 = hpet_save; if (hpet0.mc64 != hpet1.mc64) print_error("%s(%ld): With clock stopped mc64 changed: %'ld to %'ld\n", __func__, __LINE__, hpet0.mc64, hpet1.mc64); do_load(HVM_SAVE_CODE(HPET), &dom1, &hdc); do_save(HVM_SAVE_CODE(HPET), &dom1, &hdc); dump_hpet(); hpet2 = hpet_save; if (hpet1.mc64 != hpet2.mc64) print_error("%s(%ld): With clock stopped mc64 changed: %'ld to %'ld\n", __func__, __LINE__, hpet1.mc64, hpet2.mc64); dom1.arch.hvm_domain.pl_time.vhpet.hpet.mc64 = START_MC64; dom1.arch.hvm_domain.pl_time.vhpet.mc_offset = START_MC64 - hvm_guest_time - hvm_clock_cost; printf("\n" "mc64=%#lx(%'ld) mc_offset=%#lx(%'ld)\n", dom1.arch.hvm_domain.pl_time.vhpet.hpet.mc64, dom1.arch.hvm_domain.pl_time.vhpet.hpet.mc64, dom1.arch.hvm_domain.pl_time.vhpet.mc_offset, dom1.arch.hvm_domain.pl_time.vhpet.mc_offset); printf("\nhvm_guest_time=%#lx(%'ld)\n", hvm_guest_time, hvm_guest_time); do_save(HVM_SAVE_CODE(HPET), &dom1, &hdc); dump_hpet(); hpet0 = hpet_save; do_save(HVM_SAVE_CODE(HPET), &dom1, &hdc); dump_hpet(); hpet1 = hpet_save; if (hpet0.mc64 != hpet1.mc64) print_error("%s(%ld): With clock stopped mc64 changed: %'ld to %'ld\n", __func__, __LINE__, hpet0.mc64, hpet1.mc64); do_load(HVM_SAVE_CODE(HPET), &dom1, &hdc); do_save(HVM_SAVE_CODE(HPET), &dom1, &hdc); dump_hpet(); hpet2 = hpet_save; if (hpet1.mc64 != hpet2.mc64) print_error("%s(%ld): With clock stopped mc64 changed: %'ld to %'ld\n", __func__, __LINE__, hpet1.mc64, hpet2.mc64); hpet_set_mode(0xf424, 0); hpet_check_stopped(0xf424, 0); do_save(HVM_SAVE_CODE(HPET), &dom1, &hdc); dump_hpet(); hpet0 = hpet_save; do_save(HVM_SAVE_CODE(HPET), &dom1, &hdc); dump_hpet(); hpet1 = hpet_save; do_load(HVM_SAVE_CODE(HPET), &dom1, &hdc); do_save(HVM_SAVE_CODE(HPET), &dom1, &hdc); dump_hpet(); hpet2 = hpet_save; hpet_set_mode(0, 1); hpet_check_stopped(0, 1); do_save(HVM_SAVE_CODE(HPET), &dom1, &hdc); dump_hpet(); hpet0 = hpet_save; do_save(HVM_SAVE_CODE(HPET), &dom1, &hdc); dump_hpet(); hpet1 = hpet_save; do_load(HVM_SAVE_CODE(HPET), &dom1, &hdc); do_save(HVM_SAVE_CODE(HPET), &dom1, &hdc); dump_hpet(); hpet2 = hpet_save; hpet_set_mode(~0ULL, 2); hpet_check_stopped(~0ULL, 2); hpet_set_mode(0x80000000, 2); hpet_check_stopped(0x80000000, 2); do_save(HVM_SAVE_CODE(HPET), &dom1, &hdc); dump_hpet(); hpet0 = hpet_save; do_save(HVM_SAVE_CODE(HPET), &dom1, &hdc); dump_hpet(); hpet1 = hpet_save; do_load(HVM_SAVE_CODE(HPET), &dom1, &hdc); do_save(HVM_SAVE_CODE(HPET), &dom1, &hdc); dump_hpet(); hpet2 = hpet_save; for (k = 0; k < ARRAY_SIZE(new_guest_time); k++) { hvm_guest_time = new_guest_time[k]; printf("\nhvm_guest_time=%#lx(%'ld)\n", hvm_guest_time, hvm_guest_time); do_save(HVM_SAVE_CODE(HPET), &dom1, &hdc); dump_hpet(); hpet0 = hpet_save; do_save(HVM_SAVE_CODE(HPET), &dom1, &hdc); dump_hpet(); hpet1 = hpet_save; do_load(HVM_SAVE_CODE(HPET), &dom1, &hdc); do_save(HVM_SAVE_CODE(HPET), &dom1, &hdc); dump_hpet(); hpet2 = hpet_save; for (i = 0; i < tick_count; i++) { hvm_guest_time += 0x10; printf("\nhvm_guest_time=%#lx(%'ld)\n", hvm_guest_time, hvm_guest_time); do_save(HVM_SAVE_CODE(HPET), &dom1, &hdc); dump_hpet(); hpet0 = hpet_save; do_save(HVM_SAVE_CODE(HPET), &dom1, &hdc); dump_hpet(); hpet1 = hpet_save; do_load(HVM_SAVE_CODE(HPET), &dom1, &hdc); do_save(HVM_SAVE_CODE(HPET), &dom1, &hdc); dump_hpet(); hpet2 = hpet_save; } } } return 0; } /* * Local variables: * mode: C * c-file-style: "BSD" * c-basic-offset: 4 * indent-tabs-mode: nil * End: */