1 /*
2 * vlapic.c: virtualize LAPIC for HVM vcpus.
3 *
4 * Copyright (c) 2004, Intel Corporation.
5 * Copyright (c) 2006 Keir Fraser, XenSource Inc.
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms and conditions of the GNU General Public License,
9 * version 2, as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program; If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include <xen/types.h>
21 #include <xen/mm.h>
22 #include <xen/xmalloc.h>
23 #include <xen/domain.h>
24 #include <xen/domain_page.h>
25 #include <xen/event.h>
26 #include <xen/trace.h>
27 #include <xen/lib.h>
28 #include <xen/sched.h>
29 #include <xen/numa.h>
30 #include <asm/current.h>
31 #include <asm/page.h>
32 #include <asm/apic.h>
33 #include <asm/io_apic.h>
34 #include <asm/vpmu.h>
35 #include <asm/hvm/hvm.h>
36 #include <asm/hvm/io.h>
37 #include <asm/hvm/support.h>
38 #include <asm/hvm/vmx/vmx.h>
39 #include <asm/hvm/nestedhvm.h>
40 #include <asm/hvm/viridian.h>
41 #include <public/hvm/ioreq.h>
42 #include <public/hvm/params.h>
43
44 #define VLAPIC_VERSION 0x00050014
45 #define VLAPIC_LVT_NUM 6
46
47 #define LVT_MASK \
48 (APIC_LVT_MASKED | APIC_SEND_PENDING | APIC_VECTOR_MASK)
49
50 #define LINT_MASK \
51 (LVT_MASK | APIC_MODE_MASK | APIC_INPUT_POLARITY |\
52 APIC_LVT_REMOTE_IRR | APIC_LVT_LEVEL_TRIGGER)
53
54 static const unsigned int vlapic_lvt_mask[VLAPIC_LVT_NUM] =
55 {
56 /* LVTT */
57 LVT_MASK | APIC_TIMER_MODE_MASK,
58 /* LVTTHMR */
59 LVT_MASK | APIC_MODE_MASK,
60 /* LVTPC */
61 LVT_MASK | APIC_MODE_MASK,
62 /* LVT0-1 */
63 LINT_MASK, LINT_MASK,
64 /* LVTERR */
65 LVT_MASK
66 };
67
68 #define vlapic_lvt_vector(vlapic, lvt_type) \
69 (vlapic_get_reg(vlapic, lvt_type) & APIC_VECTOR_MASK)
70
71 #define vlapic_lvt_dm(vlapic, lvt_type) \
72 (vlapic_get_reg(vlapic, lvt_type) & APIC_MODE_MASK)
73
74 #define vlapic_lvtt_period(vlapic) \
75 ((vlapic_get_reg(vlapic, APIC_LVTT) & APIC_TIMER_MODE_MASK) \
76 == APIC_TIMER_MODE_PERIODIC)
77
78 #define vlapic_lvtt_oneshot(vlapic) \
79 ((vlapic_get_reg(vlapic, APIC_LVTT) & APIC_TIMER_MODE_MASK) \
80 == APIC_TIMER_MODE_ONESHOT)
81
82 #define vlapic_lvtt_tdt(vlapic) \
83 ((vlapic_get_reg(vlapic, APIC_LVTT) & APIC_TIMER_MODE_MASK) \
84 == APIC_TIMER_MODE_TSC_DEADLINE)
85
86 static void vlapic_do_init(struct vlapic *vlapic);
87
vlapic_find_highest_vector(const void * bitmap)88 static int vlapic_find_highest_vector(const void *bitmap)
89 {
90 const uint32_t *word = bitmap;
91 unsigned int word_offset = NR_VECTORS / 32;
92
93 /* Work backwards through the bitmap (first 32-bit word in every four). */
94 while ( (word_offset != 0) && (word[(--word_offset)*4] == 0) )
95 continue;
96
97 return (fls(word[word_offset*4]) - 1) + (word_offset * 32);
98 }
99
100 /*
101 * IRR-specific bitmap update & search routines.
102 */
103
vlapic_test_and_set_irr(int vector,struct vlapic * vlapic)104 static int vlapic_test_and_set_irr(int vector, struct vlapic *vlapic)
105 {
106 return vlapic_test_and_set_vector(vector, &vlapic->regs->data[APIC_IRR]);
107 }
108
vlapic_clear_irr(int vector,struct vlapic * vlapic)109 static void vlapic_clear_irr(int vector, struct vlapic *vlapic)
110 {
111 vlapic_clear_vector(vector, &vlapic->regs->data[APIC_IRR]);
112 }
113
vlapic_find_highest_irr(struct vlapic * vlapic)114 static int vlapic_find_highest_irr(struct vlapic *vlapic)
115 {
116 if ( hvm_funcs.sync_pir_to_irr )
117 hvm_funcs.sync_pir_to_irr(vlapic_vcpu(vlapic));
118
119 return vlapic_find_highest_vector(&vlapic->regs->data[APIC_IRR]);
120 }
121
vlapic_error(struct vlapic * vlapic,unsigned int errmask)122 static void vlapic_error(struct vlapic *vlapic, unsigned int errmask)
123 {
124 unsigned long flags;
125 uint32_t esr;
126
127 spin_lock_irqsave(&vlapic->esr_lock, flags);
128 esr = vlapic_get_reg(vlapic, APIC_ESR);
129 if ( (esr & errmask) != errmask )
130 {
131 uint32_t lvterr = vlapic_get_reg(vlapic, APIC_LVTERR);
132
133 vlapic_set_reg(vlapic, APIC_ESR, esr | errmask);
134 if ( !(lvterr & APIC_LVT_MASKED) )
135 vlapic_set_irq(vlapic, lvterr & APIC_VECTOR_MASK, 0);
136 }
137 spin_unlock_irqrestore(&vlapic->esr_lock, flags);
138 }
139
vlapic_test_irq(const struct vlapic * vlapic,uint8_t vec)140 bool vlapic_test_irq(const struct vlapic *vlapic, uint8_t vec)
141 {
142 if ( unlikely(vec < 16) )
143 return false;
144
145 if ( hvm_funcs.test_pir &&
146 hvm_funcs.test_pir(const_vlapic_vcpu(vlapic), vec) )
147 return true;
148
149 return vlapic_test_vector(vec, &vlapic->regs->data[APIC_IRR]);
150 }
151
vlapic_set_irq(struct vlapic * vlapic,uint8_t vec,uint8_t trig)152 void vlapic_set_irq(struct vlapic *vlapic, uint8_t vec, uint8_t trig)
153 {
154 struct vcpu *target = vlapic_vcpu(vlapic);
155
156 if ( unlikely(vec < 16) )
157 {
158 vlapic_error(vlapic, APIC_ESR_RECVILL);
159 return;
160 }
161
162 if ( trig )
163 vlapic_set_vector(vec, &vlapic->regs->data[APIC_TMR]);
164
165 if ( hvm_funcs.update_eoi_exit_bitmap )
166 hvm_funcs.update_eoi_exit_bitmap(target, vec, trig);
167
168 if ( hvm_funcs.deliver_posted_intr )
169 hvm_funcs.deliver_posted_intr(target, vec);
170 else if ( !vlapic_test_and_set_irr(vec, vlapic) )
171 vcpu_kick(target);
172 }
173
vlapic_find_highest_isr(struct vlapic * vlapic)174 static int vlapic_find_highest_isr(struct vlapic *vlapic)
175 {
176 return vlapic_find_highest_vector(&vlapic->regs->data[APIC_ISR]);
177 }
178
vlapic_get_ppr(struct vlapic * vlapic)179 static uint32_t vlapic_get_ppr(struct vlapic *vlapic)
180 {
181 uint32_t tpr, isrv, ppr;
182 int isr;
183
184 tpr = vlapic_get_reg(vlapic, APIC_TASKPRI);
185 isr = vlapic_find_highest_isr(vlapic);
186 isrv = (isr != -1) ? isr : 0;
187
188 if ( (tpr & 0xf0) >= (isrv & 0xf0) )
189 ppr = tpr & 0xff;
190 else
191 ppr = isrv & 0xf0;
192
193 HVM_DBG_LOG(DBG_LEVEL_VLAPIC_INTERRUPT,
194 "vlapic %p, ppr %#x, isr %#x, isrv %#x",
195 vlapic, ppr, isr, isrv);
196
197 return ppr;
198 }
199
vlapic_set_ppr(struct vlapic * vlapic)200 uint32_t vlapic_set_ppr(struct vlapic *vlapic)
201 {
202 uint32_t ppr = vlapic_get_ppr(vlapic);
203
204 vlapic_set_reg(vlapic, APIC_PROCPRI, ppr);
205 return ppr;
206 }
207
vlapic_match_logical_addr(const struct vlapic * vlapic,uint32_t mda)208 static bool_t vlapic_match_logical_addr(const struct vlapic *vlapic,
209 uint32_t mda)
210 {
211 bool_t result = 0;
212 uint32_t logical_id = vlapic_get_reg(vlapic, APIC_LDR);
213
214 if ( vlapic_x2apic_mode(vlapic) )
215 return ((logical_id >> 16) == (mda >> 16)) &&
216 (uint16_t)(logical_id & mda);
217
218 logical_id = GET_xAPIC_LOGICAL_ID(logical_id);
219 mda = (uint8_t)mda;
220
221 switch ( vlapic_get_reg(vlapic, APIC_DFR) )
222 {
223 case APIC_DFR_FLAT:
224 if ( logical_id & mda )
225 result = 1;
226 break;
227 case APIC_DFR_CLUSTER:
228 if ( ((logical_id >> 4) == (mda >> 0x4)) && (logical_id & mda & 0xf) )
229 result = 1;
230 break;
231 default:
232 printk(XENLOG_G_WARNING "%pv: bad LAPIC DFR value %08x\n",
233 const_vlapic_vcpu(vlapic),
234 vlapic_get_reg(vlapic, APIC_DFR));
235 break;
236 }
237
238 return result;
239 }
240
vlapic_match_dest(const struct vlapic * target,const struct vlapic * source,int short_hand,uint32_t dest,bool_t dest_mode)241 bool_t vlapic_match_dest(
242 const struct vlapic *target, const struct vlapic *source,
243 int short_hand, uint32_t dest, bool_t dest_mode)
244 {
245 HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "target %p, source %p, dest %#x, "
246 "dest_mode %#x, short_hand %#x",
247 target, source, dest, dest_mode, short_hand);
248
249 switch ( short_hand )
250 {
251 case APIC_DEST_NOSHORT:
252 if ( dest_mode )
253 return vlapic_match_logical_addr(target, dest);
254 return (dest == _VLAPIC_ID(target, 0xffffffff)) ||
255 (dest == VLAPIC_ID(target));
256
257 case APIC_DEST_SELF:
258 return (target == source);
259
260 case APIC_DEST_ALLINC:
261 return 1;
262
263 case APIC_DEST_ALLBUT:
264 return (target != source);
265
266 default:
267 gdprintk(XENLOG_WARNING, "Bad dest shorthand value %x\n", short_hand);
268 break;
269 }
270
271 return 0;
272 }
273
vlapic_init_sipi_one(struct vcpu * target,uint32_t icr)274 static void vlapic_init_sipi_one(struct vcpu *target, uint32_t icr)
275 {
276 vcpu_pause(target);
277
278 switch ( icr & APIC_MODE_MASK )
279 {
280 case APIC_DM_INIT: {
281 bool_t fpu_initialised;
282 int rc;
283
284 /* No work on INIT de-assert for P4-type APIC. */
285 if ( (icr & (APIC_INT_LEVELTRIG | APIC_INT_ASSERT)) ==
286 APIC_INT_LEVELTRIG )
287 break;
288 /* Nothing to do if the VCPU is already reset. */
289 if ( !target->is_initialised )
290 break;
291 hvm_vcpu_down(target);
292 domain_lock(target->domain);
293 /* Reset necessary VCPU state. This does not include FPU state. */
294 fpu_initialised = target->fpu_initialised;
295 rc = vcpu_reset(target);
296 ASSERT(!rc);
297 target->fpu_initialised = fpu_initialised;
298 vlapic_do_init(vcpu_vlapic(target));
299 domain_unlock(target->domain);
300 break;
301 }
302
303 case APIC_DM_STARTUP: {
304 uint16_t reset_cs = (icr & 0xffu) << 8;
305 hvm_vcpu_reset_state(target, reset_cs, 0);
306 break;
307 }
308
309 default:
310 BUG();
311 }
312
313 vcpu_unpause(target);
314 }
315
vlapic_init_sipi_action(unsigned long _vcpu)316 static void vlapic_init_sipi_action(unsigned long _vcpu)
317 {
318 struct vcpu *origin = (struct vcpu *)_vcpu;
319 uint32_t icr = vcpu_vlapic(origin)->init_sipi.icr;
320 uint32_t dest = vcpu_vlapic(origin)->init_sipi.dest;
321 uint32_t short_hand = icr & APIC_SHORT_MASK;
322 bool_t dest_mode = !!(icr & APIC_DEST_MASK);
323 struct vcpu *v;
324
325 if ( icr == 0 )
326 return;
327
328 for_each_vcpu ( origin->domain, v )
329 {
330 if ( vlapic_match_dest(vcpu_vlapic(v), vcpu_vlapic(origin),
331 short_hand, dest, dest_mode) )
332 vlapic_init_sipi_one(v, icr);
333 }
334
335 vcpu_vlapic(origin)->init_sipi.icr = 0;
336 vcpu_unpause(origin);
337 }
338
339 /* Add a pending IRQ into lapic. */
vlapic_accept_irq(struct vcpu * v,uint32_t icr_low)340 static void vlapic_accept_irq(struct vcpu *v, uint32_t icr_low)
341 {
342 struct vlapic *vlapic = vcpu_vlapic(v);
343 uint8_t vector = (uint8_t)icr_low;
344
345 switch ( icr_low & APIC_MODE_MASK )
346 {
347 case APIC_DM_FIXED:
348 case APIC_DM_LOWEST:
349 if ( vlapic_enabled(vlapic) )
350 vlapic_set_irq(vlapic, vector, 0);
351 break;
352
353 case APIC_DM_REMRD:
354 gdprintk(XENLOG_WARNING, "Ignoring delivery mode 3\n");
355 break;
356
357 case APIC_DM_SMI:
358 gdprintk(XENLOG_WARNING, "Ignoring guest SMI\n");
359 break;
360
361 case APIC_DM_NMI:
362 if ( !test_and_set_bool(v->nmi_pending) )
363 {
364 bool_t wake = 0;
365 domain_lock(v->domain);
366 if ( v->is_initialised )
367 wake = test_and_clear_bit(_VPF_down, &v->pause_flags);
368 domain_unlock(v->domain);
369 if ( wake )
370 vcpu_wake(v);
371 vcpu_kick(v);
372 }
373 break;
374
375 case APIC_DM_INIT:
376 case APIC_DM_STARTUP:
377 BUG(); /* Handled in vlapic_ipi(). */
378
379 default:
380 gdprintk(XENLOG_ERR, "TODO: unsupported delivery mode in ICR %x\n",
381 icr_low);
382 domain_crash(v->domain);
383 }
384 }
385
vlapic_lowest_prio(struct domain * d,const struct vlapic * source,int short_hand,uint32_t dest,bool_t dest_mode)386 struct vlapic *vlapic_lowest_prio(
387 struct domain *d, const struct vlapic *source,
388 int short_hand, uint32_t dest, bool_t dest_mode)
389 {
390 int old = hvm_domain_irq(d)->round_robin_prev_vcpu;
391 uint32_t ppr, target_ppr = UINT_MAX;
392 struct vlapic *vlapic, *target = NULL;
393 struct vcpu *v;
394
395 if ( unlikely(!d->vcpu) || unlikely((v = d->vcpu[old]) == NULL) )
396 return NULL;
397
398 do {
399 v = v->next_in_list ? : d->vcpu[0];
400 vlapic = vcpu_vlapic(v);
401 if ( vlapic_match_dest(vlapic, source, short_hand, dest, dest_mode) &&
402 vlapic_enabled(vlapic) &&
403 ((ppr = vlapic_get_ppr(vlapic)) < target_ppr) )
404 {
405 target = vlapic;
406 target_ppr = ppr;
407 }
408 } while ( v->vcpu_id != old );
409
410 if ( target != NULL )
411 hvm_domain_irq(d)->round_robin_prev_vcpu =
412 vlapic_vcpu(target)->vcpu_id;
413
414 return target;
415 }
416
vlapic_EOI_set(struct vlapic * vlapic)417 void vlapic_EOI_set(struct vlapic *vlapic)
418 {
419 int vector = vlapic_find_highest_isr(vlapic);
420
421 /* Some EOI writes may not have a matching to an in-service interrupt. */
422 if ( vector == -1 )
423 return;
424
425 vlapic_clear_vector(vector, &vlapic->regs->data[APIC_ISR]);
426
427 if ( hvm_funcs.handle_eoi )
428 hvm_funcs.handle_eoi(vector);
429
430 vlapic_handle_EOI(vlapic, vector);
431 }
432
vlapic_handle_EOI(struct vlapic * vlapic,u8 vector)433 void vlapic_handle_EOI(struct vlapic *vlapic, u8 vector)
434 {
435 struct domain *d = vlapic_domain(vlapic);
436
437 if ( vlapic_test_and_clear_vector(vector, &vlapic->regs->data[APIC_TMR]) )
438 vioapic_update_EOI(d, vector);
439
440 hvm_dpci_msi_eoi(d, vector);
441 }
442
is_multicast_dest(struct vlapic * vlapic,unsigned int short_hand,uint32_t dest,bool_t dest_mode)443 static bool_t is_multicast_dest(struct vlapic *vlapic, unsigned int short_hand,
444 uint32_t dest, bool_t dest_mode)
445 {
446 if ( vlapic_domain(vlapic)->max_vcpus <= 2 )
447 return 0;
448
449 if ( short_hand )
450 return short_hand != APIC_DEST_SELF;
451
452 if ( vlapic_x2apic_mode(vlapic) )
453 return dest_mode ? hweight16(dest) > 1 : dest == 0xffffffff;
454
455 if ( dest_mode )
456 return hweight8(dest &
457 GET_xAPIC_DEST_FIELD(vlapic_get_reg(vlapic,
458 APIC_DFR))) > 1;
459
460 return dest == 0xff;
461 }
462
vlapic_ipi(struct vlapic * vlapic,uint32_t icr_low,uint32_t icr_high)463 void vlapic_ipi(
464 struct vlapic *vlapic, uint32_t icr_low, uint32_t icr_high)
465 {
466 unsigned int dest;
467 unsigned int short_hand = icr_low & APIC_SHORT_MASK;
468 bool_t dest_mode = !!(icr_low & APIC_DEST_MASK);
469
470 HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "icr = 0x%08x:%08x", icr_high, icr_low);
471
472 dest = _VLAPIC_ID(vlapic, icr_high);
473
474 switch ( icr_low & APIC_MODE_MASK )
475 {
476 case APIC_DM_INIT:
477 case APIC_DM_STARTUP:
478 if ( vlapic->init_sipi.icr != 0 )
479 {
480 WARN(); /* should be impossible but don't BUG, just in case */
481 break;
482 }
483 vcpu_pause_nosync(vlapic_vcpu(vlapic));
484 vlapic->init_sipi.icr = icr_low;
485 vlapic->init_sipi.dest = dest;
486 tasklet_schedule(&vlapic->init_sipi.tasklet);
487 break;
488
489 case APIC_DM_LOWEST: {
490 struct vlapic *target = vlapic_lowest_prio(
491 vlapic_domain(vlapic), vlapic, short_hand, dest, dest_mode);
492
493 if ( unlikely((icr_low & APIC_VECTOR_MASK) < 16) )
494 vlapic_error(vlapic, APIC_ESR_SENDILL);
495 else if ( target )
496 vlapic_accept_irq(vlapic_vcpu(target), icr_low);
497 break;
498 }
499
500 case APIC_DM_FIXED:
501 if ( unlikely((icr_low & APIC_VECTOR_MASK) < 16) )
502 {
503 vlapic_error(vlapic, APIC_ESR_SENDILL);
504 break;
505 }
506 /* fall through */
507 default: {
508 struct vcpu *v;
509 bool_t batch = is_multicast_dest(vlapic, short_hand, dest, dest_mode);
510
511 if ( batch )
512 cpu_raise_softirq_batch_begin();
513 for_each_vcpu ( vlapic_domain(vlapic), v )
514 {
515 if ( vlapic_match_dest(vcpu_vlapic(v), vlapic,
516 short_hand, dest, dest_mode) )
517 vlapic_accept_irq(v, icr_low);
518 }
519 if ( batch )
520 cpu_raise_softirq_batch_finish();
521 break;
522 }
523 }
524 }
525
vlapic_get_tmcct(struct vlapic * vlapic)526 static uint32_t vlapic_get_tmcct(struct vlapic *vlapic)
527 {
528 struct vcpu *v = current;
529 uint32_t tmcct = 0, tmict = vlapic_get_reg(vlapic, APIC_TMICT);
530 uint64_t counter_passed;
531
532 counter_passed = ((hvm_get_guest_time(v) - vlapic->timer_last_update)
533 / (APIC_BUS_CYCLE_NS * vlapic->hw.timer_divisor));
534
535 /* If timer_last_update is 0, then TMCCT should return 0 as well. */
536 if ( tmict && vlapic->timer_last_update )
537 {
538 if ( vlapic_lvtt_period(vlapic) )
539 counter_passed %= tmict;
540 if ( counter_passed < tmict )
541 tmcct = tmict - counter_passed;
542 }
543
544 HVM_DBG_LOG(DBG_LEVEL_VLAPIC_TIMER,
545 "timer initial count %d, timer current count %d, "
546 "offset %"PRId64,
547 tmict, tmcct, counter_passed);
548
549 return tmcct;
550 }
551
vlapic_set_tdcr(struct vlapic * vlapic,unsigned int val)552 static void vlapic_set_tdcr(struct vlapic *vlapic, unsigned int val)
553 {
554 /* Only bits 0, 1 and 3 are settable; others are MBZ. */
555 val &= 0xb;
556 vlapic_set_reg(vlapic, APIC_TDCR, val);
557
558 /* Update the demangled hw.timer_divisor. */
559 val = ((val & 3) | ((val & 8) >> 1)) + 1;
560 vlapic->hw.timer_divisor = 1 << (val & 7);
561
562 HVM_DBG_LOG(DBG_LEVEL_VLAPIC_TIMER,
563 "timer_divisor: %d", vlapic->hw.timer_divisor);
564 }
565
vlapic_read_aligned(struct vlapic * vlapic,unsigned int offset)566 static uint32_t vlapic_read_aligned(struct vlapic *vlapic, unsigned int offset)
567 {
568 switch ( offset )
569 {
570 case APIC_PROCPRI:
571 return vlapic_get_ppr(vlapic);
572
573 case APIC_TMCCT: /* Timer CCR */
574 if ( !vlapic_lvtt_oneshot(vlapic) && !vlapic_lvtt_period(vlapic) )
575 break;
576 return vlapic_get_tmcct(vlapic);
577
578 case APIC_TMICT: /* Timer ICR */
579 if ( !vlapic_lvtt_oneshot(vlapic) && !vlapic_lvtt_period(vlapic) )
580 break;
581 /* fall through */
582 default:
583 return vlapic_get_reg(vlapic, offset);
584 }
585
586 return 0;
587 }
588
vlapic_read(struct vcpu * v,unsigned long address,unsigned int len,unsigned long * pval)589 static int vlapic_read(
590 struct vcpu *v, unsigned long address,
591 unsigned int len, unsigned long *pval)
592 {
593 struct vlapic *vlapic = vcpu_vlapic(v);
594 unsigned int offset = address - vlapic_base_address(vlapic);
595 unsigned int alignment = offset & 3, tmp, result = 0;
596
597 if ( offset > (APIC_TDCR + 0x3) )
598 goto out;
599
600 tmp = vlapic_read_aligned(vlapic, offset & ~3);
601
602 switch ( len )
603 {
604 case 1:
605 result = *((unsigned char *)&tmp + alignment);
606 break;
607
608 case 2:
609 if ( alignment == 3 )
610 goto unaligned_exit_and_crash;
611 result = *(unsigned short *)((unsigned char *)&tmp + alignment);
612 break;
613
614 case 4:
615 if ( alignment != 0 )
616 goto unaligned_exit_and_crash;
617 result = *(unsigned int *)((unsigned char *)&tmp + alignment);
618 break;
619
620 default:
621 gdprintk(XENLOG_ERR, "Local APIC read with len=%#x, "
622 "should be 4 instead.\n", len);
623 goto exit_and_crash;
624 }
625
626 HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "offset %#x with length %#x, "
627 "and the result is %#x", offset, len, result);
628
629 out:
630 *pval = result;
631 return X86EMUL_OKAY;
632
633 unaligned_exit_and_crash:
634 gdprintk(XENLOG_ERR, "Unaligned LAPIC read len=%#x at offset=%#x.\n",
635 len, offset);
636 exit_and_crash:
637 domain_crash(v->domain);
638 return X86EMUL_OKAY;
639 }
640
hvm_x2apic_msr_read(struct vcpu * v,unsigned int msr,uint64_t * msr_content)641 int hvm_x2apic_msr_read(struct vcpu *v, unsigned int msr, uint64_t *msr_content)
642 {
643 static const unsigned long readable[] =
644 {
645 #define REG(x) (1UL << (APIC_ ## x >> 4))
646 REG(ID) | REG(LVR) | REG(TASKPRI) | REG(PROCPRI) |
647 REG(LDR) | REG(SPIV) | REG(ESR) | REG(ICR) |
648 REG(CMCI) | REG(LVTT) | REG(LVTTHMR) | REG(LVTPC) |
649 REG(LVT0) | REG(LVT1) | REG(LVTERR) | REG(TMICT) |
650 REG(TMCCT) | REG(TDCR) |
651 #undef REG
652 #define REGBLOCK(x) (((1UL << (NR_VECTORS / 32)) - 1) << (APIC_ ## x >> 4))
653 REGBLOCK(ISR) | REGBLOCK(TMR) | REGBLOCK(IRR)
654 #undef REGBLOCK
655 };
656 struct vlapic *vlapic = vcpu_vlapic(v);
657 uint32_t high = 0, reg = msr - MSR_IA32_APICBASE_MSR, offset = reg << 4;
658
659 if ( !vlapic_x2apic_mode(vlapic) ||
660 (reg >= sizeof(readable) * 8) || !test_bit(reg, readable) )
661 return X86EMUL_UNHANDLEABLE;
662
663 if ( offset == APIC_ICR )
664 high = vlapic_read_aligned(vlapic, APIC_ICR2);
665
666 *msr_content = ((uint64_t)high << 32) |
667 vlapic_read_aligned(vlapic, offset);
668
669 return X86EMUL_OKAY;
670 }
671
vlapic_pt_cb(struct vcpu * v,void * data)672 static void vlapic_pt_cb(struct vcpu *v, void *data)
673 {
674 TRACE_0D(TRC_HVM_EMUL_LAPIC_TIMER_CB);
675 *(s_time_t *)data = hvm_get_guest_time(v);
676 }
677
vlapic_tdt_pt_cb(struct vcpu * v,void * data)678 static void vlapic_tdt_pt_cb(struct vcpu *v, void *data)
679 {
680 *(s_time_t *)data = hvm_get_guest_time(v);
681 vcpu_vlapic(v)->hw.tdt_msr = 0;
682 }
683
684 /*
685 * This function is used when a register related to the APIC timer is updated.
686 * It expects the new value for the register TMICT to be set *before*
687 * being called, and the previous value of the divisor (calculated from TDCR)
688 * to be passed as argument.
689 * It expect the new value of LVTT to be set *after* being called, with this
690 * new values passed as parameter (only APIC_TIMER_MODE_MASK bits matter).
691 */
vlapic_update_timer(struct vlapic * vlapic,uint32_t lvtt,bool tmict_updated,uint32_t old_divisor)692 static void vlapic_update_timer(struct vlapic *vlapic, uint32_t lvtt,
693 bool tmict_updated, uint32_t old_divisor)
694 {
695 uint64_t period, delta = 0;
696 bool is_oneshot, is_periodic;
697
698 is_periodic = (lvtt & APIC_TIMER_MODE_MASK) == APIC_TIMER_MODE_PERIODIC;
699 is_oneshot = (lvtt & APIC_TIMER_MODE_MASK) == APIC_TIMER_MODE_ONESHOT;
700
701 period = (uint64_t)vlapic_get_reg(vlapic, APIC_TMICT)
702 * APIC_BUS_CYCLE_NS * old_divisor;
703
704 /* Calculate the next time the timer should trigger an interrupt. */
705 if ( tmict_updated )
706 delta = period;
707 else if ( period && vlapic->timer_last_update )
708 {
709 uint64_t time_passed = hvm_get_guest_time(current)
710 - vlapic->timer_last_update;
711
712 /* This depends of the previous mode, if a new mode is being set */
713 if ( vlapic_lvtt_period(vlapic) )
714 time_passed %= period;
715 if ( time_passed < period )
716 delta = period - time_passed;
717 }
718
719 if ( delta && (is_oneshot || is_periodic) )
720 {
721 if ( vlapic->hw.timer_divisor != old_divisor )
722 {
723 period = (uint64_t)vlapic_get_reg(vlapic, APIC_TMICT)
724 * APIC_BUS_CYCLE_NS * vlapic->hw.timer_divisor;
725 delta = delta * vlapic->hw.timer_divisor / old_divisor;
726 }
727
728 TRACE_2_LONG_3D(TRC_HVM_EMUL_LAPIC_START_TIMER, TRC_PAR_LONG(delta),
729 TRC_PAR_LONG(is_periodic ? period : 0),
730 vlapic->pt.irq);
731
732 create_periodic_time(current, &vlapic->pt, delta,
733 is_periodic ? period : 0, vlapic->pt.irq,
734 is_periodic ? vlapic_pt_cb : NULL,
735 &vlapic->timer_last_update);
736
737 vlapic->timer_last_update = vlapic->pt.last_plt_gtime;
738 if ( !tmict_updated )
739 vlapic->timer_last_update -= period - delta;
740
741 HVM_DBG_LOG(DBG_LEVEL_VLAPIC,
742 "bus cycle is %uns, "
743 "initial count %u, period %"PRIu64"ns",
744 APIC_BUS_CYCLE_NS,
745 vlapic_get_reg(vlapic, APIC_TMICT),
746 period);
747 }
748 else
749 {
750 TRACE_0D(TRC_HVM_EMUL_LAPIC_STOP_TIMER);
751 destroy_periodic_time(&vlapic->pt);
752 /*
753 * From now, TMCCT should return 0 until TMICT is set again.
754 * This is because the timer mode was one-shot when the counter reach 0
755 * or just because the timer is disable.
756 */
757 vlapic->timer_last_update = 0;
758 }
759 }
760
vlapic_reg_write(struct vcpu * v,unsigned int offset,uint32_t val)761 static void vlapic_reg_write(struct vcpu *v,
762 unsigned int offset, uint32_t val)
763 {
764 struct vlapic *vlapic = vcpu_vlapic(v);
765
766 memset(&vlapic->loaded, 0, sizeof(vlapic->loaded));
767
768 switch ( offset )
769 {
770 case APIC_ID:
771 vlapic_set_reg(vlapic, APIC_ID, val);
772 break;
773
774 case APIC_TASKPRI:
775 vlapic_set_reg(vlapic, APIC_TASKPRI, val & 0xff);
776 break;
777
778 case APIC_EOI:
779 vlapic_EOI_set(vlapic);
780 break;
781
782 case APIC_LDR:
783 vlapic_set_reg(vlapic, APIC_LDR, val & APIC_LDR_MASK);
784 break;
785
786 case APIC_DFR:
787 vlapic_set_reg(vlapic, APIC_DFR, val | 0x0FFFFFFF);
788 break;
789
790 case APIC_SPIV:
791 vlapic_set_reg(vlapic, APIC_SPIV, val & 0x3ff);
792
793 if ( !(val & APIC_SPIV_APIC_ENABLED) )
794 {
795 int i;
796 uint32_t lvt_val;
797
798 vlapic->hw.disabled |= VLAPIC_SW_DISABLED;
799
800 for ( i = 0; i < VLAPIC_LVT_NUM; i++ )
801 {
802 lvt_val = vlapic_get_reg(vlapic, APIC_LVTT + 0x10 * i);
803 vlapic_set_reg(vlapic, APIC_LVTT + 0x10 * i,
804 lvt_val | APIC_LVT_MASKED);
805 }
806 }
807 else
808 {
809 vlapic->hw.disabled &= ~VLAPIC_SW_DISABLED;
810 pt_may_unmask_irq(vlapic_domain(vlapic), &vlapic->pt);
811 }
812 break;
813
814 case APIC_ICR:
815 val &= ~(1 << 12); /* always clear the pending bit */
816 vlapic_ipi(vlapic, val, vlapic_get_reg(vlapic, APIC_ICR2));
817 vlapic_set_reg(vlapic, APIC_ICR, val);
818 break;
819
820 case APIC_ICR2:
821 vlapic_set_reg(vlapic, APIC_ICR2, val & 0xff000000);
822 break;
823
824 case APIC_LVTT: /* LVT Timer Reg */
825 if ( vlapic_lvtt_tdt(vlapic) !=
826 ((val & APIC_TIMER_MODE_MASK) == APIC_TIMER_MODE_TSC_DEADLINE))
827 {
828 vlapic_set_reg(vlapic, APIC_TMICT, 0);
829 vlapic->hw.tdt_msr = 0;
830 }
831 vlapic->pt.irq = val & APIC_VECTOR_MASK;
832
833 vlapic_update_timer(vlapic, val, false, vlapic->hw.timer_divisor);
834
835 /* fallthrough */
836 case APIC_LVTTHMR: /* LVT Thermal Monitor */
837 case APIC_LVTPC: /* LVT Performance Counter */
838 case APIC_LVT0: /* LVT LINT0 Reg */
839 case APIC_LVT1: /* LVT Lint1 Reg */
840 case APIC_LVTERR: /* LVT Error Reg */
841 if ( vlapic_sw_disabled(vlapic) )
842 val |= APIC_LVT_MASKED;
843 val &= vlapic_lvt_mask[(offset - APIC_LVTT) >> 4];
844 vlapic_set_reg(vlapic, offset, val);
845 if ( offset == APIC_LVT0 )
846 {
847 vlapic_adjust_i8259_target(v->domain);
848 pt_may_unmask_irq(v->domain, NULL);
849 }
850 if ( (offset == APIC_LVTT) && !(val & APIC_LVT_MASKED) )
851 pt_may_unmask_irq(NULL, &vlapic->pt);
852 if ( offset == APIC_LVTPC )
853 vpmu_lvtpc_update(val);
854 break;
855
856 case APIC_TMICT:
857 if ( !vlapic_lvtt_oneshot(vlapic) && !vlapic_lvtt_period(vlapic) )
858 break;
859
860 vlapic_set_reg(vlapic, APIC_TMICT, val);
861
862 vlapic_update_timer(vlapic, vlapic_get_reg(vlapic, APIC_LVTT), true,
863 vlapic->hw.timer_divisor);
864 break;
865
866 case APIC_TDCR:
867 {
868 uint32_t current_divisor = vlapic->hw.timer_divisor;
869
870 vlapic_set_tdcr(vlapic, val & 0xb);
871
872 vlapic_update_timer(vlapic, vlapic_get_reg(vlapic, APIC_LVTT), false,
873 current_divisor);
874 HVM_DBG_LOG(DBG_LEVEL_VLAPIC_TIMER, "timer divisor is %#x",
875 vlapic->hw.timer_divisor);
876 break;
877 }
878 }
879 }
880
vlapic_write(struct vcpu * v,unsigned long address,unsigned int len,unsigned long val)881 static int vlapic_write(struct vcpu *v, unsigned long address,
882 unsigned int len, unsigned long val)
883 {
884 struct vlapic *vlapic = vcpu_vlapic(v);
885 unsigned int offset = address - vlapic_base_address(vlapic);
886 int rc = X86EMUL_OKAY;
887
888 if ( offset != APIC_EOI )
889 HVM_DBG_LOG(DBG_LEVEL_VLAPIC,
890 "offset %#x with length %#x, and value is %#lx",
891 offset, len, val);
892
893 /*
894 * According to the IA32 Manual, all accesses should be 32 bits.
895 * Some OSes do 8- or 16-byte accesses, however.
896 */
897 if ( unlikely(len != 4) )
898 {
899 unsigned int tmp = vlapic_read_aligned(vlapic, offset & ~3);
900 unsigned char alignment = (offset & 3) * 8;
901
902 switch ( len )
903 {
904 case 1:
905 val = ((tmp & ~(0xffU << alignment)) |
906 ((val & 0xff) << alignment));
907 break;
908
909 case 2:
910 if ( alignment & 1 )
911 goto unaligned_exit_and_crash;
912 val = ((tmp & ~(0xffffU << alignment)) |
913 ((val & 0xffff) << alignment));
914 break;
915
916 default:
917 gprintk(XENLOG_ERR, "LAPIC write with len %u\n", len);
918 goto exit_and_crash;
919 }
920
921 gdprintk(XENLOG_INFO, "Notice: LAPIC write with len %u\n", len);
922 offset &= ~3;
923 }
924 else if ( unlikely(offset & 3) )
925 goto unaligned_exit_and_crash;
926
927 vlapic_reg_write(v, offset, val);
928
929 return X86EMUL_OKAY;
930
931 unaligned_exit_and_crash:
932 gprintk(XENLOG_ERR, "Unaligned LAPIC write: len=%u offset=%#x.\n",
933 len, offset);
934 exit_and_crash:
935 domain_crash(v->domain);
936 return rc;
937 }
938
vlapic_apicv_write(struct vcpu * v,unsigned int offset)939 int vlapic_apicv_write(struct vcpu *v, unsigned int offset)
940 {
941 struct vlapic *vlapic = vcpu_vlapic(v);
942 uint32_t val = vlapic_get_reg(vlapic, offset);
943
944 if ( vlapic_x2apic_mode(vlapic) )
945 {
946 if ( offset != APIC_SELF_IPI )
947 return X86EMUL_UNHANDLEABLE;
948
949 offset = APIC_ICR;
950 val = APIC_DEST_SELF | (val & APIC_VECTOR_MASK);
951 }
952
953 vlapic_reg_write(v, offset, val);
954
955 return X86EMUL_OKAY;
956 }
957
hvm_x2apic_msr_write(struct vcpu * v,unsigned int msr,uint64_t msr_content)958 int hvm_x2apic_msr_write(struct vcpu *v, unsigned int msr, uint64_t msr_content)
959 {
960 struct vlapic *vlapic = vcpu_vlapic(v);
961 uint32_t offset = (msr - MSR_IA32_APICBASE_MSR) << 4;
962
963 if ( !vlapic_x2apic_mode(vlapic) )
964 return X86EMUL_UNHANDLEABLE;
965
966 switch ( offset )
967 {
968 case APIC_TASKPRI:
969 if ( msr_content & ~APIC_TPRI_MASK )
970 return X86EMUL_UNHANDLEABLE;
971 break;
972
973 case APIC_SPIV:
974 if ( msr_content & ~(APIC_VECTOR_MASK | APIC_SPIV_APIC_ENABLED |
975 (VLAPIC_VERSION & APIC_LVR_DIRECTED_EOI
976 ? APIC_SPIV_DIRECTED_EOI : 0)) )
977 return X86EMUL_UNHANDLEABLE;
978 break;
979
980 case APIC_LVTT:
981 if ( msr_content & ~(LVT_MASK | APIC_TIMER_MODE_MASK) )
982 return X86EMUL_UNHANDLEABLE;
983 break;
984
985 case APIC_LVTTHMR:
986 case APIC_LVTPC:
987 case APIC_CMCI:
988 if ( msr_content & ~(LVT_MASK | APIC_MODE_MASK) )
989 return X86EMUL_UNHANDLEABLE;
990 break;
991
992 case APIC_LVT0:
993 case APIC_LVT1:
994 if ( msr_content & ~LINT_MASK )
995 return X86EMUL_UNHANDLEABLE;
996 break;
997
998 case APIC_LVTERR:
999 if ( msr_content & ~LVT_MASK )
1000 return X86EMUL_UNHANDLEABLE;
1001 break;
1002
1003 case APIC_TMICT:
1004 break;
1005
1006 case APIC_TDCR:
1007 if ( msr_content & ~APIC_TDR_DIV_1 )
1008 return X86EMUL_UNHANDLEABLE;
1009 break;
1010
1011 case APIC_ICR:
1012 if ( (uint32_t)msr_content & ~(APIC_VECTOR_MASK | APIC_MODE_MASK |
1013 APIC_DEST_MASK | APIC_INT_ASSERT |
1014 APIC_INT_LEVELTRIG | APIC_SHORT_MASK) )
1015 return X86EMUL_UNHANDLEABLE;
1016 vlapic_set_reg(vlapic, APIC_ICR2, msr_content >> 32);
1017 break;
1018
1019 case APIC_SELF_IPI:
1020 if ( msr_content & ~APIC_VECTOR_MASK )
1021 return X86EMUL_UNHANDLEABLE;
1022 offset = APIC_ICR;
1023 msr_content = APIC_DEST_SELF | (msr_content & APIC_VECTOR_MASK);
1024 break;
1025
1026 case APIC_EOI:
1027 case APIC_ESR:
1028 if ( msr_content )
1029 default:
1030 return X86EMUL_UNHANDLEABLE;
1031 }
1032
1033 vlapic_reg_write(v, offset, msr_content);
1034
1035 return X86EMUL_OKAY;
1036 }
1037
vlapic_range(struct vcpu * v,unsigned long addr)1038 static int vlapic_range(struct vcpu *v, unsigned long addr)
1039 {
1040 struct vlapic *vlapic = vcpu_vlapic(v);
1041 unsigned long offset = addr - vlapic_base_address(vlapic);
1042
1043 return !vlapic_hw_disabled(vlapic) &&
1044 !vlapic_x2apic_mode(vlapic) &&
1045 (offset < PAGE_SIZE);
1046 }
1047
1048 static const struct hvm_mmio_ops vlapic_mmio_ops = {
1049 .check = vlapic_range,
1050 .read = vlapic_read,
1051 .write = vlapic_write
1052 };
1053
set_x2apic_id(struct vlapic * vlapic)1054 static void set_x2apic_id(struct vlapic *vlapic)
1055 {
1056 u32 id = vlapic_vcpu(vlapic)->vcpu_id;
1057 u32 ldr = ((id & ~0xf) << 12) | (1 << (id & 0xf));
1058
1059 vlapic_set_reg(vlapic, APIC_ID, id * 2);
1060 vlapic_set_reg(vlapic, APIC_LDR, ldr);
1061 }
1062
vlapic_msr_set(struct vlapic * vlapic,uint64_t value)1063 bool_t vlapic_msr_set(struct vlapic *vlapic, uint64_t value)
1064 {
1065 if ( !has_vlapic(vlapic_domain(vlapic)) )
1066 return 0;
1067
1068 if ( (vlapic->hw.apic_base_msr ^ value) & MSR_IA32_APICBASE_ENABLE )
1069 {
1070 if ( unlikely(value & MSR_IA32_APICBASE_EXTD) )
1071 return 0;
1072 if ( value & MSR_IA32_APICBASE_ENABLE )
1073 {
1074 vlapic_reset(vlapic);
1075 vlapic->hw.disabled &= ~VLAPIC_HW_DISABLED;
1076 pt_may_unmask_irq(vlapic_domain(vlapic), &vlapic->pt);
1077 }
1078 else
1079 {
1080 vlapic->hw.disabled |= VLAPIC_HW_DISABLED;
1081 pt_may_unmask_irq(vlapic_domain(vlapic), NULL);
1082 }
1083 }
1084 else if ( ((vlapic->hw.apic_base_msr ^ value) & MSR_IA32_APICBASE_EXTD) &&
1085 unlikely(!vlapic_xapic_mode(vlapic)) )
1086 return 0;
1087
1088 vlapic->hw.apic_base_msr = value;
1089 memset(&vlapic->loaded, 0, sizeof(vlapic->loaded));
1090
1091 if ( vlapic_x2apic_mode(vlapic) )
1092 set_x2apic_id(vlapic);
1093
1094 vmx_vlapic_msr_changed(vlapic_vcpu(vlapic));
1095
1096 HVM_DBG_LOG(DBG_LEVEL_VLAPIC,
1097 "apic base msr is 0x%016"PRIx64, vlapic->hw.apic_base_msr);
1098
1099 return 1;
1100 }
1101
vlapic_tdt_msr_get(struct vlapic * vlapic)1102 uint64_t vlapic_tdt_msr_get(struct vlapic *vlapic)
1103 {
1104 if ( !vlapic_lvtt_tdt(vlapic) )
1105 return 0;
1106
1107 return vlapic->hw.tdt_msr;
1108 }
1109
vlapic_tdt_msr_set(struct vlapic * vlapic,uint64_t value)1110 void vlapic_tdt_msr_set(struct vlapic *vlapic, uint64_t value)
1111 {
1112 uint64_t guest_tsc;
1113 struct vcpu *v = vlapic_vcpu(vlapic);
1114
1115 if ( vlapic_hw_disabled(vlapic) )
1116 return;
1117
1118 if ( !vlapic_lvtt_tdt(vlapic) )
1119 {
1120 HVM_DBG_LOG(DBG_LEVEL_VLAPIC_TIMER, "ignore tsc deadline msr write");
1121 return;
1122 }
1123
1124 /* new_value = 0, >0 && <= now, > now */
1125 guest_tsc = hvm_get_guest_tsc(v);
1126 if ( value > guest_tsc )
1127 {
1128 uint64_t delta = gtsc_to_gtime(v->domain, value - guest_tsc);
1129 delta = max_t(s64, delta, 0);
1130
1131 HVM_DBG_LOG(DBG_LEVEL_VLAPIC_TIMER, "delta[0x%016"PRIx64"]", delta);
1132
1133 vlapic->hw.tdt_msr = value;
1134 /* .... reprogram tdt timer */
1135 TRACE_2_LONG_3D(TRC_HVM_EMUL_LAPIC_START_TIMER, TRC_PAR_LONG(delta),
1136 TRC_PAR_LONG(0LL), vlapic->pt.irq);
1137 create_periodic_time(v, &vlapic->pt, delta, 0,
1138 vlapic->pt.irq, vlapic_tdt_pt_cb,
1139 &vlapic->timer_last_update);
1140 vlapic->timer_last_update = vlapic->pt.last_plt_gtime;
1141 }
1142 else
1143 {
1144 vlapic->hw.tdt_msr = 0;
1145
1146 /* trigger a timer event if needed */
1147 if ( value > 0 )
1148 {
1149 TRACE_2_LONG_3D(TRC_HVM_EMUL_LAPIC_START_TIMER, TRC_PAR_LONG(0LL),
1150 TRC_PAR_LONG(0LL), vlapic->pt.irq);
1151 create_periodic_time(v, &vlapic->pt, 0, 0,
1152 vlapic->pt.irq, vlapic_tdt_pt_cb,
1153 &vlapic->timer_last_update);
1154 vlapic->timer_last_update = vlapic->pt.last_plt_gtime;
1155 }
1156 else
1157 {
1158 /* .... stop tdt timer */
1159 TRACE_0D(TRC_HVM_EMUL_LAPIC_STOP_TIMER);
1160 destroy_periodic_time(&vlapic->pt);
1161 }
1162
1163 HVM_DBG_LOG(DBG_LEVEL_VLAPIC_TIMER, "value[0x%016"PRIx64"]", value);
1164 }
1165
1166 HVM_DBG_LOG(DBG_LEVEL_VLAPIC_TIMER,
1167 "tdt_msr[0x%016"PRIx64"],"
1168 " gtsc[0x%016"PRIx64"]",
1169 vlapic->hw.tdt_msr, guest_tsc);
1170 }
1171
__vlapic_accept_pic_intr(struct vcpu * v)1172 static int __vlapic_accept_pic_intr(struct vcpu *v)
1173 {
1174 struct domain *d = v->domain;
1175 struct vlapic *vlapic = vcpu_vlapic(v);
1176 uint32_t lvt0 = vlapic_get_reg(vlapic, APIC_LVT0);
1177 union vioapic_redir_entry redir0;
1178
1179 ASSERT(has_vpic(d));
1180
1181 if ( !has_vioapic(d) )
1182 return 0;
1183
1184 redir0 = domain_vioapic(d, 0)->redirtbl[0];
1185
1186 /* We deliver 8259 interrupts to the appropriate CPU as follows. */
1187 return ((/* IOAPIC pin0 is unmasked and routing to this LAPIC? */
1188 ((redir0.fields.delivery_mode == dest_ExtINT) &&
1189 !redir0.fields.mask &&
1190 redir0.fields.dest_id == VLAPIC_ID(vlapic) &&
1191 !vlapic_disabled(vlapic)) ||
1192 /* LAPIC has LVT0 unmasked for ExtInts? */
1193 ((lvt0 & (APIC_MODE_MASK|APIC_LVT_MASKED)) == APIC_DM_EXTINT) ||
1194 /* LAPIC is fully disabled? */
1195 vlapic_hw_disabled(vlapic)));
1196 }
1197
vlapic_accept_pic_intr(struct vcpu * v)1198 int vlapic_accept_pic_intr(struct vcpu *v)
1199 {
1200 if ( vlapic_hw_disabled(vcpu_vlapic(v)) || !has_vpic(v->domain) )
1201 return 0;
1202
1203 TRACE_2D(TRC_HVM_EMUL_LAPIC_PIC_INTR,
1204 (v == v->domain->arch.hvm_domain.i8259_target),
1205 v ? __vlapic_accept_pic_intr(v) : -1);
1206
1207 return ((v == v->domain->arch.hvm_domain.i8259_target) &&
1208 __vlapic_accept_pic_intr(v));
1209 }
1210
vlapic_adjust_i8259_target(struct domain * d)1211 void vlapic_adjust_i8259_target(struct domain *d)
1212 {
1213 struct vcpu *v;
1214
1215 if ( !has_vpic(d) )
1216 return;
1217
1218 for_each_vcpu ( d, v )
1219 if ( __vlapic_accept_pic_intr(v) )
1220 goto found;
1221
1222 v = d->vcpu ? d->vcpu[0] : NULL;
1223
1224 found:
1225 if ( d->arch.hvm_domain.i8259_target == v )
1226 return;
1227 d->arch.hvm_domain.i8259_target = v;
1228 pt_adjust_global_vcpu_target(v);
1229 }
1230
vlapic_virtual_intr_delivery_enabled(void)1231 int vlapic_virtual_intr_delivery_enabled(void)
1232 {
1233 if ( hvm_funcs.virtual_intr_delivery_enabled )
1234 return hvm_funcs.virtual_intr_delivery_enabled();
1235 else
1236 return 0;
1237 }
1238
vlapic_has_pending_irq(struct vcpu * v)1239 int vlapic_has_pending_irq(struct vcpu *v)
1240 {
1241 struct vlapic *vlapic = vcpu_vlapic(v);
1242 int irr, vector, isr;
1243
1244 if ( !vlapic_enabled(vlapic) )
1245 return -1;
1246
1247 irr = vlapic_find_highest_irr(vlapic);
1248 if ( irr == -1 )
1249 return -1;
1250
1251 if ( vlapic_virtual_intr_delivery_enabled() &&
1252 !nestedhvm_vcpu_in_guestmode(v) )
1253 return irr;
1254
1255 /*
1256 * If APIC assist was used then there may have been no EOI so
1257 * we need to clear the requisite bit from the ISR here, before
1258 * comparing with the IRR.
1259 */
1260 vector = viridian_complete_apic_assist(v);
1261 if ( vector )
1262 vlapic_clear_vector(vector, &vlapic->regs->data[APIC_ISR]);
1263
1264 isr = vlapic_find_highest_isr(vlapic);
1265 if ( isr == -1 )
1266 return irr;
1267
1268 /*
1269 * A vector is pending in the ISR so, regardless of whether the new
1270 * vector in the IRR is lower or higher in priority, any pending
1271 * APIC assist must be aborted to ensure an EOI.
1272 */
1273 viridian_abort_apic_assist(v);
1274
1275 return ((isr & 0xf0) < (irr & 0xf0)) ? irr : -1;
1276 }
1277
vlapic_ack_pending_irq(struct vcpu * v,int vector,bool_t force_ack)1278 int vlapic_ack_pending_irq(struct vcpu *v, int vector, bool_t force_ack)
1279 {
1280 struct vlapic *vlapic = vcpu_vlapic(v);
1281 int isr;
1282
1283 if ( !force_ack &&
1284 vlapic_virtual_intr_delivery_enabled() )
1285 return 1;
1286
1287 /* If there's no chance of using APIC assist then bail now. */
1288 if ( !has_viridian_apic_assist(v->domain) ||
1289 vlapic_test_vector(vector, &vlapic->regs->data[APIC_TMR]) )
1290 goto done;
1291
1292 isr = vlapic_find_highest_isr(vlapic);
1293 if ( isr == -1 )
1294 {
1295 /*
1296 * This vector is edge triggered and no other vectors are pending
1297 * in the ISR so we can use APIC assist to avoid exiting for EOI.
1298 */
1299 viridian_start_apic_assist(v, vector);
1300 }
1301
1302 done:
1303 vlapic_set_vector(vector, &vlapic->regs->data[APIC_ISR]);
1304 vlapic_clear_irr(vector, vlapic);
1305 return 1;
1306 }
1307
is_vlapic_lvtpc_enabled(struct vlapic * vlapic)1308 bool_t is_vlapic_lvtpc_enabled(struct vlapic *vlapic)
1309 {
1310 return (vlapic_enabled(vlapic) &&
1311 !(vlapic_get_reg(vlapic, APIC_LVTPC) & APIC_LVT_MASKED));
1312 }
1313
1314 /* Reset the VLAPIC back to its init state. */
vlapic_do_init(struct vlapic * vlapic)1315 static void vlapic_do_init(struct vlapic *vlapic)
1316 {
1317 int i;
1318
1319 if ( !has_vlapic(vlapic_vcpu(vlapic)->domain) )
1320 return;
1321
1322 vlapic_set_reg(vlapic, APIC_LVR, VLAPIC_VERSION);
1323
1324 for ( i = 0; i < 8; i++ )
1325 {
1326 vlapic_set_reg(vlapic, APIC_IRR + 0x10 * i, 0);
1327 vlapic_set_reg(vlapic, APIC_ISR + 0x10 * i, 0);
1328 vlapic_set_reg(vlapic, APIC_TMR + 0x10 * i, 0);
1329 }
1330 vlapic_set_reg(vlapic, APIC_ICR, 0);
1331 vlapic_set_reg(vlapic, APIC_ICR2, 0);
1332 /*
1333 * LDR is read-only in x2APIC mode. Preserve its value when handling
1334 * INIT signal in x2APIC mode.
1335 */
1336 if ( !vlapic_x2apic_mode(vlapic) )
1337 vlapic_set_reg(vlapic, APIC_LDR, 0);
1338 vlapic_set_reg(vlapic, APIC_TASKPRI, 0);
1339 vlapic_set_reg(vlapic, APIC_TMICT, 0);
1340 vlapic_set_reg(vlapic, APIC_TMCCT, 0);
1341 vlapic_set_tdcr(vlapic, 0);
1342
1343 vlapic_set_reg(vlapic, APIC_DFR, 0xffffffffU);
1344
1345 for ( i = 0; i < VLAPIC_LVT_NUM; i++ )
1346 vlapic_set_reg(vlapic, APIC_LVTT + 0x10 * i, APIC_LVT_MASKED);
1347
1348 vlapic_set_reg(vlapic, APIC_SPIV, 0xff);
1349 vlapic->hw.disabled |= VLAPIC_SW_DISABLED;
1350
1351 TRACE_0D(TRC_HVM_EMUL_LAPIC_STOP_TIMER);
1352 destroy_periodic_time(&vlapic->pt);
1353 }
1354
1355 /* Reset the VLAPIC back to its power-on/reset state. */
vlapic_reset(struct vlapic * vlapic)1356 void vlapic_reset(struct vlapic *vlapic)
1357 {
1358 const struct vcpu *v = vlapic_vcpu(vlapic);
1359
1360 if ( !has_vlapic(v->domain) )
1361 return;
1362
1363 vlapic->hw.apic_base_msr = (MSR_IA32_APICBASE_ENABLE |
1364 APIC_DEFAULT_PHYS_BASE);
1365 if ( v->vcpu_id == 0 )
1366 vlapic->hw.apic_base_msr |= MSR_IA32_APICBASE_BSP;
1367
1368 vlapic_set_reg(vlapic, APIC_ID, (v->vcpu_id * 2) << 24);
1369 vlapic_do_init(vlapic);
1370 }
1371
1372 /* rearm the actimer if needed, after a HVM restore */
lapic_rearm(struct vlapic * s)1373 static void lapic_rearm(struct vlapic *s)
1374 {
1375 unsigned long tmict;
1376 uint64_t period, tdt_msr;
1377
1378 s->pt.irq = vlapic_get_reg(s, APIC_LVTT) & APIC_VECTOR_MASK;
1379
1380 if ( vlapic_lvtt_tdt(s) )
1381 {
1382 if ( (tdt_msr = vlapic_tdt_msr_get(s)) != 0 )
1383 vlapic_tdt_msr_set(s, tdt_msr);
1384 return;
1385 }
1386
1387 if ( (tmict = vlapic_get_reg(s, APIC_TMICT)) == 0 )
1388 return;
1389
1390 period = ((uint64_t)APIC_BUS_CYCLE_NS *
1391 (uint32_t)tmict * s->hw.timer_divisor);
1392 TRACE_2_LONG_3D(TRC_HVM_EMUL_LAPIC_START_TIMER, TRC_PAR_LONG(period),
1393 TRC_PAR_LONG(vlapic_lvtt_period(s) ? period : 0LL), s->pt.irq);
1394 create_periodic_time(vlapic_vcpu(s), &s->pt, period,
1395 vlapic_lvtt_period(s) ? period : 0,
1396 s->pt.irq,
1397 vlapic_lvtt_period(s) ? vlapic_pt_cb : NULL,
1398 &s->timer_last_update);
1399 s->timer_last_update = s->pt.last_plt_gtime;
1400 }
1401
lapic_save_hidden(struct domain * d,hvm_domain_context_t * h)1402 static int lapic_save_hidden(struct domain *d, hvm_domain_context_t *h)
1403 {
1404 struct vcpu *v;
1405 struct vlapic *s;
1406 int rc = 0;
1407
1408 if ( !has_vlapic(d) )
1409 return 0;
1410
1411 for_each_vcpu ( d, v )
1412 {
1413 s = vcpu_vlapic(v);
1414 if ( (rc = hvm_save_entry(LAPIC, v->vcpu_id, h, &s->hw)) != 0 )
1415 break;
1416 }
1417
1418 return rc;
1419 }
1420
lapic_save_regs(struct domain * d,hvm_domain_context_t * h)1421 static int lapic_save_regs(struct domain *d, hvm_domain_context_t *h)
1422 {
1423 struct vcpu *v;
1424 struct vlapic *s;
1425 int rc = 0;
1426
1427 if ( !has_vlapic(d) )
1428 return 0;
1429
1430 for_each_vcpu ( d, v )
1431 {
1432 if ( hvm_funcs.sync_pir_to_irr )
1433 hvm_funcs.sync_pir_to_irr(v);
1434
1435 s = vcpu_vlapic(v);
1436 if ( (rc = hvm_save_entry(LAPIC_REGS, v->vcpu_id, h, s->regs)) != 0 )
1437 break;
1438 }
1439
1440 return rc;
1441 }
1442
1443 /*
1444 * Following lapic_load_hidden()/lapic_load_regs() we may need to
1445 * correct ID and LDR when they come from an old, broken hypervisor.
1446 */
lapic_load_fixup(struct vlapic * vlapic)1447 static void lapic_load_fixup(struct vlapic *vlapic)
1448 {
1449 uint32_t id = vlapic->loaded.id;
1450
1451 if ( vlapic_x2apic_mode(vlapic) && id && vlapic->loaded.ldr == 1 )
1452 {
1453 /*
1454 * This is optional: ID != 0 contradicts LDR == 1. It's being added
1455 * to aid in eventual debugging of issues arising from the fixup done
1456 * here, but can be dropped as soon as it is found to conflict with
1457 * other (future) changes.
1458 */
1459 if ( GET_xAPIC_ID(id) != vlapic_vcpu(vlapic)->vcpu_id * 2 ||
1460 id != SET_xAPIC_ID(GET_xAPIC_ID(id)) )
1461 printk(XENLOG_G_WARNING "%pv: bogus APIC ID %#x loaded\n",
1462 vlapic_vcpu(vlapic), id);
1463 set_x2apic_id(vlapic);
1464 }
1465 else /* Undo an eventual earlier fixup. */
1466 {
1467 vlapic_set_reg(vlapic, APIC_ID, id);
1468 vlapic_set_reg(vlapic, APIC_LDR, vlapic->loaded.ldr);
1469 }
1470 }
1471
lapic_load_hidden(struct domain * d,hvm_domain_context_t * h)1472 static int lapic_load_hidden(struct domain *d, hvm_domain_context_t *h)
1473 {
1474 uint16_t vcpuid;
1475 struct vcpu *v;
1476 struct vlapic *s;
1477
1478 if ( !has_vlapic(d) )
1479 return -ENODEV;
1480
1481 /* Which vlapic to load? */
1482 vcpuid = hvm_load_instance(h);
1483 if ( vcpuid >= d->max_vcpus || (v = d->vcpu[vcpuid]) == NULL )
1484 {
1485 dprintk(XENLOG_G_ERR, "HVM restore: dom%d has no apic%u\n",
1486 d->domain_id, vcpuid);
1487 return -EINVAL;
1488 }
1489 s = vcpu_vlapic(v);
1490
1491 if ( hvm_load_entry_zeroextend(LAPIC, h, &s->hw) != 0 )
1492 return -EINVAL;
1493
1494 s->loaded.hw = 1;
1495 if ( s->loaded.regs )
1496 lapic_load_fixup(s);
1497
1498 if ( !(s->hw.apic_base_msr & MSR_IA32_APICBASE_ENABLE) &&
1499 unlikely(vlapic_x2apic_mode(s)) )
1500 return -EINVAL;
1501
1502 vmx_vlapic_msr_changed(v);
1503
1504 return 0;
1505 }
1506
lapic_load_regs(struct domain * d,hvm_domain_context_t * h)1507 static int lapic_load_regs(struct domain *d, hvm_domain_context_t *h)
1508 {
1509 uint16_t vcpuid;
1510 struct vcpu *v;
1511 struct vlapic *s;
1512
1513 if ( !has_vlapic(d) )
1514 return -ENODEV;
1515
1516 /* Which vlapic to load? */
1517 vcpuid = hvm_load_instance(h);
1518 if ( vcpuid >= d->max_vcpus || (v = d->vcpu[vcpuid]) == NULL )
1519 {
1520 dprintk(XENLOG_G_ERR, "HVM restore: dom%d has no apic%u\n",
1521 d->domain_id, vcpuid);
1522 return -EINVAL;
1523 }
1524 s = vcpu_vlapic(v);
1525
1526 if ( hvm_load_entry(LAPIC_REGS, h, s->regs) != 0 )
1527 return -EINVAL;
1528
1529 s->loaded.id = vlapic_get_reg(s, APIC_ID);
1530 s->loaded.ldr = vlapic_get_reg(s, APIC_LDR);
1531 s->loaded.regs = 1;
1532 if ( s->loaded.hw )
1533 lapic_load_fixup(s);
1534
1535 if ( hvm_funcs.process_isr )
1536 hvm_funcs.process_isr(vlapic_find_highest_isr(s), v);
1537
1538 vlapic_adjust_i8259_target(d);
1539 lapic_rearm(s);
1540 return 0;
1541 }
1542
1543 HVM_REGISTER_SAVE_RESTORE(LAPIC, lapic_save_hidden, lapic_load_hidden,
1544 1, HVMSR_PER_VCPU);
1545 HVM_REGISTER_SAVE_RESTORE(LAPIC_REGS, lapic_save_regs, lapic_load_regs,
1546 1, HVMSR_PER_VCPU);
1547
vlapic_init(struct vcpu * v)1548 int vlapic_init(struct vcpu *v)
1549 {
1550 struct vlapic *vlapic = vcpu_vlapic(v);
1551
1552 HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "%d", v->vcpu_id);
1553
1554 if ( !has_vlapic(v->domain) )
1555 {
1556 vlapic->hw.disabled = VLAPIC_HW_DISABLED;
1557 return 0;
1558 }
1559
1560 vlapic->pt.source = PTSRC_lapic;
1561
1562 if (vlapic->regs_page == NULL)
1563 {
1564 vlapic->regs_page = alloc_domheap_page(v->domain, MEMF_no_owner);
1565 if ( vlapic->regs_page == NULL )
1566 {
1567 dprintk(XENLOG_ERR, "alloc vlapic regs error: %d/%d\n",
1568 v->domain->domain_id, v->vcpu_id);
1569 return -ENOMEM;
1570 }
1571 }
1572 if (vlapic->regs == NULL)
1573 {
1574 vlapic->regs = __map_domain_page_global(vlapic->regs_page);
1575 if ( vlapic->regs == NULL )
1576 {
1577 dprintk(XENLOG_ERR, "map vlapic regs error: %d/%d\n",
1578 v->domain->domain_id, v->vcpu_id);
1579 return -ENOMEM;
1580 }
1581 }
1582 clear_page(vlapic->regs);
1583
1584 vlapic_reset(vlapic);
1585
1586 spin_lock_init(&vlapic->esr_lock);
1587
1588 tasklet_init(&vlapic->init_sipi.tasklet,
1589 vlapic_init_sipi_action,
1590 (unsigned long)v);
1591
1592 if ( v->vcpu_id == 0 )
1593 register_mmio_handler(v->domain, &vlapic_mmio_ops);
1594
1595 return 0;
1596 }
1597
vlapic_destroy(struct vcpu * v)1598 void vlapic_destroy(struct vcpu *v)
1599 {
1600 struct vlapic *vlapic = vcpu_vlapic(v);
1601
1602 if ( !has_vlapic(v->domain) )
1603 return;
1604
1605 tasklet_kill(&vlapic->init_sipi.tasklet);
1606 TRACE_0D(TRC_HVM_EMUL_LAPIC_STOP_TIMER);
1607 destroy_periodic_time(&vlapic->pt);
1608 unmap_domain_page_global(vlapic->regs);
1609 free_domheap_page(vlapic->regs_page);
1610 }
1611
1612 /*
1613 * Local variables:
1614 * mode: C
1615 * c-file-style: "BSD"
1616 * c-basic-offset: 4
1617 * indent-tabs-mode: nil
1618 * End:
1619 */
1620