1 /* 2 * vpt.h: Virtual Platform Timer definitions 3 * 4 * Copyright (c) 2004, Intel Corporation. 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, see <http://www.gnu.org/licenses/>. 17 */ 18 19 #ifndef __ASM_X86_HVM_VPT_H__ 20 #define __ASM_X86_HVM_VPT_H__ 21 22 #include <xen/init.h> 23 #include <xen/lib.h> 24 #include <xen/time.h> 25 #include <xen/errno.h> 26 #include <xen/time.h> 27 #include <xen/timer.h> 28 #include <xen/list.h> 29 #include <asm/hvm/vpic.h> 30 #include <asm/hvm/irq.h> 31 #include <public/hvm/save.h> 32 33 /* 34 * Abstract layer of periodic time, one short time. 35 */ 36 typedef void time_cb(struct vcpu *v, void *opaque); 37 38 struct periodic_time { 39 struct list_head list; 40 bool_t on_list; 41 bool_t one_shot; 42 bool_t do_not_freeze; 43 bool_t irq_issued; 44 bool_t warned_timeout_too_short; 45 #define PTSRC_isa 1 /* ISA time source */ 46 #define PTSRC_lapic 2 /* LAPIC time source */ 47 u8 source; /* PTSRC_ */ 48 u8 irq; 49 struct vcpu *vcpu; /* vcpu timer interrupt delivers to */ 50 u32 pending_intr_nr; /* pending timer interrupts */ 51 u64 period; /* frequency in ns */ 52 s_time_t scheduled; /* scheduled timer interrupt */ 53 u64 last_plt_gtime; /* platform time when last IRQ is injected */ 54 struct timer timer; /* ac_timer */ 55 time_cb *cb; 56 void *priv; /* point back to platform time source */ 57 }; 58 59 60 #define PIT_FREQ 1193182 61 #define PIT_BASE 0x40 62 63 typedef struct PITState { 64 /* Hardware state */ 65 struct hvm_hw_pit hw; 66 /* Last time the counters read zero, for calcuating counter reads */ 67 int64_t count_load_time[3]; 68 /* Channel 0 IRQ handling. */ 69 struct periodic_time pt0; 70 spinlock_t lock; 71 } PITState; 72 73 struct hpet_registers { 74 /* Memory-mapped, software visible registers */ 75 uint64_t capability; /* capabilities */ 76 uint64_t config; /* configuration */ 77 uint64_t isr; /* interrupt status reg */ 78 uint64_t mc64; /* main counter */ 79 struct { /* timers */ 80 uint64_t config; /* configuration/cap */ 81 uint64_t cmp; /* comparator */ 82 uint64_t fsb; /* FSB route, not supported now */ 83 } timers[HPET_TIMER_NUM]; 84 85 /* Hidden register state */ 86 uint64_t period[HPET_TIMER_NUM]; /* Last value written to comparator */ 87 uint64_t comparator64[HPET_TIMER_NUM]; /* 64 bit running comparator */ 88 }; 89 90 typedef struct HPETState { 91 struct hpet_registers hpet; 92 uint64_t stime_freq; 93 uint64_t hpet_to_ns_scale; /* hpet ticks to ns (multiplied by 2^10) */ 94 uint64_t hpet_to_ns_limit; /* max hpet ticks convertable to ns */ 95 uint64_t mc_offset; 96 struct periodic_time pt[HPET_TIMER_NUM]; 97 rwlock_t lock; 98 } HPETState; 99 100 typedef struct RTCState { 101 /* Hardware state */ 102 struct hvm_hw_rtc hw; 103 /* RTC's idea of the current time */ 104 struct tm current_tm; 105 /* update-ended timer */ 106 struct timer update_timer; 107 struct timer update_timer2; 108 uint64_t next_update_time; 109 /* alarm timer */ 110 struct timer alarm_timer; 111 /* periodic timer */ 112 struct periodic_time pt; 113 s_time_t start_time; 114 s_time_t check_ticks_since; 115 int period; 116 uint8_t pt_dead_ticks; 117 uint32_t use_timer; 118 spinlock_t lock; 119 } RTCState; 120 121 #define FREQUENCE_PMTIMER 3579545 /* Timer should run at 3.579545 MHz */ 122 typedef struct PMTState { 123 struct vcpu *vcpu; /* Keeps sync with this vcpu's guest-time */ 124 uint64_t last_gtime; /* Last (guest) time we updated the timer */ 125 uint32_t not_accounted; /* time not accounted at last update */ 126 uint64_t scale; /* Multiplier to get from tsc to timer ticks */ 127 struct timer timer; /* To make sure we send SCIs */ 128 spinlock_t lock; 129 } PMTState; 130 131 struct pl_time { /* platform time */ 132 struct RTCState vrtc; 133 struct HPETState vhpet; 134 struct PMTState vpmt; 135 /* guest_time = Xen sys time + stime_offset */ 136 int64_t stime_offset; 137 /* Ensures monotonicity in appropriate timer modes. */ 138 uint64_t last_guest_time; 139 spinlock_t pl_time_lock; 140 struct domain *domain; 141 }; 142 143 void pt_save_timer(struct vcpu *v); 144 void pt_restore_timer(struct vcpu *v); 145 int pt_update_irq(struct vcpu *v); 146 void pt_intr_post(struct vcpu *v, struct hvm_intack intack); 147 void pt_migrate(struct vcpu *v); 148 149 void pt_adjust_global_vcpu_target(struct vcpu *v); 150 #define pt_global_vcpu_target(d) \ 151 (is_hvm_domain(d) && (d)->arch.hvm_domain.i8259_target ? \ 152 (d)->arch.hvm_domain.i8259_target : \ 153 (d)->vcpu ? (d)->vcpu[0] : NULL) 154 155 void pt_may_unmask_irq(struct domain *d, struct periodic_time *vlapic_pt); 156 157 /* Is given periodic timer active? */ 158 #define pt_active(pt) ((pt)->on_list || (pt)->pending_intr_nr) 159 160 /* 161 * Create/destroy a periodic (or one-shot!) timer. 162 * The given periodic timer structure must be initialised with zero bytes, 163 * except for the 'source' field which must be initialised with the 164 * correct PTSRC_ value. The initialised timer structure can then be passed 165 * to {create,destroy}_periodic_time() any number of times and in any order. 166 * Note that, for a given periodic timer, invocations of these functions MUST 167 * be serialised. 168 */ 169 void create_periodic_time( 170 struct vcpu *v, struct periodic_time *pt, uint64_t delta, 171 uint64_t period, uint8_t irq, time_cb *cb, void *data); 172 void destroy_periodic_time(struct periodic_time *pt); 173 174 int pv_pit_handler(int port, int data, int write); 175 void pit_reset(struct domain *d); 176 177 void pit_init(struct domain *d, unsigned long cpu_khz); 178 void pit_stop_channel0_irq(PITState * pit); 179 void pit_deinit(struct domain *d); 180 void rtc_init(struct domain *d); 181 void rtc_migrate_timers(struct vcpu *v); 182 void rtc_deinit(struct domain *d); 183 void rtc_reset(struct domain *d); 184 void rtc_update_clock(struct domain *d); 185 186 void pmtimer_init(struct vcpu *v); 187 void pmtimer_deinit(struct domain *d); 188 void pmtimer_reset(struct domain *d); 189 int pmtimer_change_ioport(struct domain *d, unsigned int version); 190 191 void hpet_init(struct domain *d); 192 void hpet_deinit(struct domain *d); 193 void hpet_reset(struct domain *d); 194 195 #endif /* __ASM_X86_HVM_VPT_H__ */ 196