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