direct-io.hg

view xen/arch/x86/hvm/vpt.c @ 13501:3157835b1d45

[HVM] Whitespace cleanup.

Signed-off-by: Christian Limpach <Christian.Limpach@xensource.com>
author Christian Limpach <Christian.Limpach@xensource.com>
date Fri Jan 19 13:43:17 2007 +0000 (2007-01-19)
parents 2ef07c610729
children 704151d0e219
line source
1 /*
2 * vpt.c: Virtual Platform Timer
3 *
4 * Copyright (c) 2006, Xiaowei Yang, 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, write to the Free Software Foundation, Inc., 59 Temple
17 * Place - Suite 330, Boston, MA 02111-1307 USA.
18 *
19 */
20 #include <xen/time.h>
21 #include <asm/hvm/support.h>
22 #include <asm/hvm/vpt.h>
23 #include <asm/event.h>
25 static __inline__ void missed_ticks(struct periodic_time *pt)
26 {
27 s_time_t missed_ticks;
29 missed_ticks = NOW() - pt->scheduled;
30 if ( missed_ticks > 0 )
31 {
32 missed_ticks = missed_ticks / (s_time_t) pt->period + 1;
33 if ( missed_ticks > 1000 )
34 {
35 /* TODO: Adjust guest time together */
36 pt->pending_intr_nr++;
37 }
38 else
39 {
40 pt->pending_intr_nr += missed_ticks;
41 }
42 pt->scheduled += missed_ticks * pt->period;
43 }
44 }
46 void pt_freeze_time(struct vcpu *v)
47 {
48 struct list_head *head = &v->arch.hvm_vcpu.tm_list;
49 struct list_head *list;
50 struct periodic_time *pt;
52 if ( test_bit(_VCPUF_blocked, &v->vcpu_flags) )
53 return;
55 v->arch.hvm_vcpu.guest_time = hvm_get_guest_time(v);
57 list_for_each( list, head )
58 {
59 pt = list_entry(list, struct periodic_time, list);
60 stop_timer(&pt->timer);
61 }
62 }
64 void pt_thaw_time(struct vcpu *v)
65 {
66 struct list_head *head = &v->arch.hvm_vcpu.tm_list;
67 struct list_head *list;
68 struct periodic_time *pt;
70 if ( v->arch.hvm_vcpu.guest_time )
71 {
72 hvm_set_guest_time(v, v->arch.hvm_vcpu.guest_time);
73 v->arch.hvm_vcpu.guest_time = 0;
75 list_for_each( list, head )
76 {
77 pt = list_entry(list, struct periodic_time, list);
78 missed_ticks(pt);
79 set_timer(&pt->timer, pt->scheduled);
80 }
81 }
82 }
84 /* Hook function for the platform periodic time */
85 void pt_timer_fn(void *data)
86 {
87 struct periodic_time *pt = data;
89 pt->pending_intr_nr++;
90 pt->scheduled += pt->period;
92 missed_ticks(pt);
94 if ( !pt->one_shot )
95 set_timer(&pt->timer, pt->scheduled);
97 vcpu_kick(pt->vcpu);
98 }
100 void pt_update_irq(struct vcpu *v)
101 {
102 struct list_head *head = &v->arch.hvm_vcpu.tm_list;
103 struct list_head *list;
104 struct periodic_time *pt;
105 uint64_t max_lag = -1ULL;
106 int irq = -1;
108 list_for_each( list, head )
109 {
110 pt = list_entry(list, struct periodic_time, list);
111 if ( !is_isa_irq_masked(v, pt->irq) && pt->pending_intr_nr &&
112 ((pt->last_plt_gtime + pt->period_cycles) < max_lag) )
113 {
114 max_lag = pt->last_plt_gtime + pt->period_cycles;
115 irq = pt->irq;
116 }
117 }
119 if ( is_lvtt(v, irq) )
120 {
121 vlapic_set_irq(vcpu_vlapic(v), irq, 0);
122 }
123 else if ( irq >= 0 )
124 {
125 hvm_isa_irq_deassert(v->domain, irq);
126 hvm_isa_irq_assert(v->domain, irq);
127 }
128 }
130 struct periodic_time *is_pt_irq(struct vcpu *v, int vector, int type)
131 {
132 struct list_head *head = &v->arch.hvm_vcpu.tm_list;
133 struct list_head *list;
134 struct periodic_time *pt;
135 struct RTCState *rtc = &v->domain->arch.hvm_domain.pl_time.vrtc;
136 int vec;
138 list_for_each( list, head )
139 {
140 pt = list_entry(list, struct periodic_time, list);
141 if ( !pt->pending_intr_nr )
142 continue;
144 if ( is_lvtt(v, pt->irq) )
145 {
146 if ( pt->irq != vector )
147 continue;
148 return pt;
149 }
151 vec = get_isa_irq_vector(v, pt->irq, type);
153 /* RTC irq need special care */
154 if ( (vector != vec) || (pt->irq == 8 && !is_rtc_periodic_irq(rtc)) )
155 continue;
157 return pt;
158 }
160 return NULL;
161 }
163 void pt_intr_post(struct vcpu *v, int vector, int type)
164 {
165 struct periodic_time *pt = is_pt_irq(v, vector, type);
167 if ( pt == NULL )
168 return;
170 pt->pending_intr_nr--;
171 pt->last_plt_gtime += pt->period_cycles;
173 if ( hvm_get_guest_time(pt->vcpu) < pt->last_plt_gtime )
174 hvm_set_guest_time(pt->vcpu, pt->last_plt_gtime);
176 if ( pt->cb != NULL )
177 pt->cb(pt->vcpu, pt->priv);
178 }
180 /* If pt is enabled, discard pending intr */
181 void pt_reset(struct vcpu *v)
182 {
183 struct list_head *head = &v->arch.hvm_vcpu.tm_list;
184 struct list_head *list;
185 struct periodic_time *pt;
187 list_for_each( list, head )
188 {
189 pt = list_entry(list, struct periodic_time, list);
190 if ( pt->enabled )
191 {
192 pt->pending_intr_nr = 0;
193 pt->last_plt_gtime = hvm_get_guest_time(pt->vcpu);
194 pt->scheduled = NOW() + pt->period;
195 set_timer(&pt->timer, pt->scheduled);
196 }
197 }
198 }
200 void create_periodic_time(struct vcpu *v, struct periodic_time *pt, uint64_t period,
201 uint8_t irq, char one_shot, time_cb *cb, void *data)
202 {
203 destroy_periodic_time(pt);
205 pt->enabled = 1;
206 if ( period < 900000 ) /* < 0.9 ms */
207 {
208 gdprintk(XENLOG_WARNING,
209 "HVM_PlatformTime: program too small period %"PRIu64"\n",
210 period);
211 period = 900000; /* force to 0.9ms */
212 }
213 pt->period = period;
214 pt->vcpu = v;
215 pt->last_plt_gtime = hvm_get_guest_time(pt->vcpu);
216 pt->irq = irq;
217 pt->period_cycles = (u64)period * cpu_khz / 1000000L;
218 pt->one_shot = one_shot;
219 pt->scheduled = NOW() + period;
220 pt->cb = cb;
221 pt->priv = data;
223 list_add(&pt->list, &v->arch.hvm_vcpu.tm_list);
224 set_timer(&pt->timer, pt->scheduled);
225 }
227 void destroy_periodic_time(struct periodic_time *pt)
228 {
229 if ( pt->enabled )
230 {
231 pt->enabled = 0;
232 pt->pending_intr_nr = 0;
233 list_del(&pt->list);
234 stop_timer(&pt->timer);
235 }
236 }