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