]> Git Repo - qemu.git/blob - hw/apic.c
qxl: add user-friendly bar size properties
[qemu.git] / hw / apic.c
1 /*
2  *  APIC support
3  *
4  *  Copyright (c) 2004-2005 Fabrice Bellard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, see <http://www.gnu.org/licenses/>
18  */
19 #include "apic_internal.h"
20 #include "apic.h"
21 #include "ioapic.h"
22 #include "host-utils.h"
23 #include "trace.h"
24 #include "pc.h"
25
26 #define MAX_APIC_WORDS 8
27
28 /* Intel APIC constants: from include/asm/msidef.h */
29 #define MSI_DATA_VECTOR_SHIFT           0
30 #define MSI_DATA_VECTOR_MASK            0x000000ff
31 #define MSI_DATA_DELIVERY_MODE_SHIFT    8
32 #define MSI_DATA_TRIGGER_SHIFT          15
33 #define MSI_DATA_LEVEL_SHIFT            14
34 #define MSI_ADDR_DEST_MODE_SHIFT        2
35 #define MSI_ADDR_DEST_ID_SHIFT          12
36 #define MSI_ADDR_DEST_ID_MASK           0x00ffff0
37
38 static APICCommonState *local_apics[MAX_APICS + 1];
39
40 static void apic_set_irq(APICCommonState *s, int vector_num, int trigger_mode);
41 static void apic_update_irq(APICCommonState *s);
42 static void apic_get_delivery_bitmask(uint32_t *deliver_bitmask,
43                                       uint8_t dest, uint8_t dest_mode);
44
45 /* Find first bit starting from msb */
46 static int fls_bit(uint32_t value)
47 {
48     return 31 - clz32(value);
49 }
50
51 /* Find first bit starting from lsb */
52 static int ffs_bit(uint32_t value)
53 {
54     return ctz32(value);
55 }
56
57 static inline void set_bit(uint32_t *tab, int index)
58 {
59     int i, mask;
60     i = index >> 5;
61     mask = 1 << (index & 0x1f);
62     tab[i] |= mask;
63 }
64
65 static inline void reset_bit(uint32_t *tab, int index)
66 {
67     int i, mask;
68     i = index >> 5;
69     mask = 1 << (index & 0x1f);
70     tab[i] &= ~mask;
71 }
72
73 static inline int get_bit(uint32_t *tab, int index)
74 {
75     int i, mask;
76     i = index >> 5;
77     mask = 1 << (index & 0x1f);
78     return !!(tab[i] & mask);
79 }
80
81 static void apic_local_deliver(APICCommonState *s, int vector)
82 {
83     uint32_t lvt = s->lvt[vector];
84     int trigger_mode;
85
86     trace_apic_local_deliver(vector, (lvt >> 8) & 7);
87
88     if (lvt & APIC_LVT_MASKED)
89         return;
90
91     switch ((lvt >> 8) & 7) {
92     case APIC_DM_SMI:
93         cpu_interrupt(s->cpu_env, CPU_INTERRUPT_SMI);
94         break;
95
96     case APIC_DM_NMI:
97         cpu_interrupt(s->cpu_env, CPU_INTERRUPT_NMI);
98         break;
99
100     case APIC_DM_EXTINT:
101         cpu_interrupt(s->cpu_env, CPU_INTERRUPT_HARD);
102         break;
103
104     case APIC_DM_FIXED:
105         trigger_mode = APIC_TRIGGER_EDGE;
106         if ((vector == APIC_LVT_LINT0 || vector == APIC_LVT_LINT1) &&
107             (lvt & APIC_LVT_LEVEL_TRIGGER))
108             trigger_mode = APIC_TRIGGER_LEVEL;
109         apic_set_irq(s, lvt & 0xff, trigger_mode);
110     }
111 }
112
113 void apic_deliver_pic_intr(DeviceState *d, int level)
114 {
115     APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d);
116
117     if (level) {
118         apic_local_deliver(s, APIC_LVT_LINT0);
119     } else {
120         uint32_t lvt = s->lvt[APIC_LVT_LINT0];
121
122         switch ((lvt >> 8) & 7) {
123         case APIC_DM_FIXED:
124             if (!(lvt & APIC_LVT_LEVEL_TRIGGER))
125                 break;
126             reset_bit(s->irr, lvt & 0xff);
127             /* fall through */
128         case APIC_DM_EXTINT:
129             cpu_reset_interrupt(s->cpu_env, CPU_INTERRUPT_HARD);
130             break;
131         }
132     }
133 }
134
135 static void apic_external_nmi(APICCommonState *s)
136 {
137     apic_local_deliver(s, APIC_LVT_LINT1);
138 }
139
140 #define foreach_apic(apic, deliver_bitmask, code) \
141 {\
142     int __i, __j, __mask;\
143     for(__i = 0; __i < MAX_APIC_WORDS; __i++) {\
144         __mask = deliver_bitmask[__i];\
145         if (__mask) {\
146             for(__j = 0; __j < 32; __j++) {\
147                 if (__mask & (1 << __j)) {\
148                     apic = local_apics[__i * 32 + __j];\
149                     if (apic) {\
150                         code;\
151                     }\
152                 }\
153             }\
154         }\
155     }\
156 }
157
158 static void apic_bus_deliver(const uint32_t *deliver_bitmask,
159                              uint8_t delivery_mode, uint8_t vector_num,
160                              uint8_t trigger_mode)
161 {
162     APICCommonState *apic_iter;
163
164     switch (delivery_mode) {
165         case APIC_DM_LOWPRI:
166             /* XXX: search for focus processor, arbitration */
167             {
168                 int i, d;
169                 d = -1;
170                 for(i = 0; i < MAX_APIC_WORDS; i++) {
171                     if (deliver_bitmask[i]) {
172                         d = i * 32 + ffs_bit(deliver_bitmask[i]);
173                         break;
174                     }
175                 }
176                 if (d >= 0) {
177                     apic_iter = local_apics[d];
178                     if (apic_iter) {
179                         apic_set_irq(apic_iter, vector_num, trigger_mode);
180                     }
181                 }
182             }
183             return;
184
185         case APIC_DM_FIXED:
186             break;
187
188         case APIC_DM_SMI:
189             foreach_apic(apic_iter, deliver_bitmask,
190                 cpu_interrupt(apic_iter->cpu_env, CPU_INTERRUPT_SMI) );
191             return;
192
193         case APIC_DM_NMI:
194             foreach_apic(apic_iter, deliver_bitmask,
195                 cpu_interrupt(apic_iter->cpu_env, CPU_INTERRUPT_NMI) );
196             return;
197
198         case APIC_DM_INIT:
199             /* normal INIT IPI sent to processors */
200             foreach_apic(apic_iter, deliver_bitmask,
201                          cpu_interrupt(apic_iter->cpu_env, CPU_INTERRUPT_INIT) );
202             return;
203
204         case APIC_DM_EXTINT:
205             /* handled in I/O APIC code */
206             break;
207
208         default:
209             return;
210     }
211
212     foreach_apic(apic_iter, deliver_bitmask,
213                  apic_set_irq(apic_iter, vector_num, trigger_mode) );
214 }
215
216 void apic_deliver_irq(uint8_t dest, uint8_t dest_mode, uint8_t delivery_mode,
217                       uint8_t vector_num, uint8_t trigger_mode)
218 {
219     uint32_t deliver_bitmask[MAX_APIC_WORDS];
220
221     trace_apic_deliver_irq(dest, dest_mode, delivery_mode, vector_num,
222                            trigger_mode);
223
224     apic_get_delivery_bitmask(deliver_bitmask, dest, dest_mode);
225     apic_bus_deliver(deliver_bitmask, delivery_mode, vector_num, trigger_mode);
226 }
227
228 static void apic_set_base(APICCommonState *s, uint64_t val)
229 {
230     s->apicbase = (val & 0xfffff000) |
231         (s->apicbase & (MSR_IA32_APICBASE_BSP | MSR_IA32_APICBASE_ENABLE));
232     /* if disabled, cannot be enabled again */
233     if (!(val & MSR_IA32_APICBASE_ENABLE)) {
234         s->apicbase &= ~MSR_IA32_APICBASE_ENABLE;
235         cpu_clear_apic_feature(s->cpu_env);
236         s->spurious_vec &= ~APIC_SV_ENABLE;
237     }
238 }
239
240 static void apic_set_tpr(APICCommonState *s, uint8_t val)
241 {
242     s->tpr = (val & 0x0f) << 4;
243     apic_update_irq(s);
244 }
245
246 /* return -1 if no bit is set */
247 static int get_highest_priority_int(uint32_t *tab)
248 {
249     int i;
250     for(i = 7; i >= 0; i--) {
251         if (tab[i] != 0) {
252             return i * 32 + fls_bit(tab[i]);
253         }
254     }
255     return -1;
256 }
257
258 static int apic_get_ppr(APICCommonState *s)
259 {
260     int tpr, isrv, ppr;
261
262     tpr = (s->tpr >> 4);
263     isrv = get_highest_priority_int(s->isr);
264     if (isrv < 0)
265         isrv = 0;
266     isrv >>= 4;
267     if (tpr >= isrv)
268         ppr = s->tpr;
269     else
270         ppr = isrv << 4;
271     return ppr;
272 }
273
274 static int apic_get_arb_pri(APICCommonState *s)
275 {
276     /* XXX: arbitration */
277     return 0;
278 }
279
280
281 /*
282  * <0 - low prio interrupt,
283  * 0  - no interrupt,
284  * >0 - interrupt number
285  */
286 static int apic_irq_pending(APICCommonState *s)
287 {
288     int irrv, ppr;
289     irrv = get_highest_priority_int(s->irr);
290     if (irrv < 0) {
291         return 0;
292     }
293     ppr = apic_get_ppr(s);
294     if (ppr && (irrv & 0xf0) <= (ppr & 0xf0)) {
295         return -1;
296     }
297
298     return irrv;
299 }
300
301 /* signal the CPU if an irq is pending */
302 static void apic_update_irq(APICCommonState *s)
303 {
304     if (!(s->spurious_vec & APIC_SV_ENABLE)) {
305         return;
306     }
307     if (apic_irq_pending(s) > 0) {
308         cpu_interrupt(s->cpu_env, CPU_INTERRUPT_HARD);
309     } else if (apic_accept_pic_intr(&s->busdev.qdev) &&
310                pic_get_output(isa_pic)) {
311         apic_deliver_pic_intr(&s->busdev.qdev, 1);
312     }
313 }
314
315 static void apic_set_irq(APICCommonState *s, int vector_num, int trigger_mode)
316 {
317     apic_report_irq_delivered(!get_bit(s->irr, vector_num));
318
319     set_bit(s->irr, vector_num);
320     if (trigger_mode)
321         set_bit(s->tmr, vector_num);
322     else
323         reset_bit(s->tmr, vector_num);
324     apic_update_irq(s);
325 }
326
327 static void apic_eoi(APICCommonState *s)
328 {
329     int isrv;
330     isrv = get_highest_priority_int(s->isr);
331     if (isrv < 0)
332         return;
333     reset_bit(s->isr, isrv);
334     if (!(s->spurious_vec & APIC_SV_DIRECTED_IO) && get_bit(s->tmr, isrv)) {
335         ioapic_eoi_broadcast(isrv);
336     }
337     apic_update_irq(s);
338 }
339
340 static int apic_find_dest(uint8_t dest)
341 {
342     APICCommonState *apic = local_apics[dest];
343     int i;
344
345     if (apic && apic->id == dest)
346         return dest;  /* shortcut in case apic->id == apic->idx */
347
348     for (i = 0; i < MAX_APICS; i++) {
349         apic = local_apics[i];
350         if (apic && apic->id == dest)
351             return i;
352         if (!apic)
353             break;
354     }
355
356     return -1;
357 }
358
359 static void apic_get_delivery_bitmask(uint32_t *deliver_bitmask,
360                                       uint8_t dest, uint8_t dest_mode)
361 {
362     APICCommonState *apic_iter;
363     int i;
364
365     if (dest_mode == 0) {
366         if (dest == 0xff) {
367             memset(deliver_bitmask, 0xff, MAX_APIC_WORDS * sizeof(uint32_t));
368         } else {
369             int idx = apic_find_dest(dest);
370             memset(deliver_bitmask, 0x00, MAX_APIC_WORDS * sizeof(uint32_t));
371             if (idx >= 0)
372                 set_bit(deliver_bitmask, idx);
373         }
374     } else {
375         /* XXX: cluster mode */
376         memset(deliver_bitmask, 0x00, MAX_APIC_WORDS * sizeof(uint32_t));
377         for(i = 0; i < MAX_APICS; i++) {
378             apic_iter = local_apics[i];
379             if (apic_iter) {
380                 if (apic_iter->dest_mode == 0xf) {
381                     if (dest & apic_iter->log_dest)
382                         set_bit(deliver_bitmask, i);
383                 } else if (apic_iter->dest_mode == 0x0) {
384                     if ((dest & 0xf0) == (apic_iter->log_dest & 0xf0) &&
385                         (dest & apic_iter->log_dest & 0x0f)) {
386                         set_bit(deliver_bitmask, i);
387                     }
388                 }
389             } else {
390                 break;
391             }
392         }
393     }
394 }
395
396 static void apic_startup(APICCommonState *s, int vector_num)
397 {
398     s->sipi_vector = vector_num;
399     cpu_interrupt(s->cpu_env, CPU_INTERRUPT_SIPI);
400 }
401
402 void apic_sipi(DeviceState *d)
403 {
404     APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d);
405
406     cpu_reset_interrupt(s->cpu_env, CPU_INTERRUPT_SIPI);
407
408     if (!s->wait_for_sipi)
409         return;
410     cpu_x86_load_seg_cache_sipi(s->cpu_env, s->sipi_vector);
411     s->wait_for_sipi = 0;
412 }
413
414 static void apic_deliver(DeviceState *d, uint8_t dest, uint8_t dest_mode,
415                          uint8_t delivery_mode, uint8_t vector_num,
416                          uint8_t trigger_mode)
417 {
418     APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d);
419     uint32_t deliver_bitmask[MAX_APIC_WORDS];
420     int dest_shorthand = (s->icr[0] >> 18) & 3;
421     APICCommonState *apic_iter;
422
423     switch (dest_shorthand) {
424     case 0:
425         apic_get_delivery_bitmask(deliver_bitmask, dest, dest_mode);
426         break;
427     case 1:
428         memset(deliver_bitmask, 0x00, sizeof(deliver_bitmask));
429         set_bit(deliver_bitmask, s->idx);
430         break;
431     case 2:
432         memset(deliver_bitmask, 0xff, sizeof(deliver_bitmask));
433         break;
434     case 3:
435         memset(deliver_bitmask, 0xff, sizeof(deliver_bitmask));
436         reset_bit(deliver_bitmask, s->idx);
437         break;
438     }
439
440     switch (delivery_mode) {
441         case APIC_DM_INIT:
442             {
443                 int trig_mode = (s->icr[0] >> 15) & 1;
444                 int level = (s->icr[0] >> 14) & 1;
445                 if (level == 0 && trig_mode == 1) {
446                     foreach_apic(apic_iter, deliver_bitmask,
447                                  apic_iter->arb_id = apic_iter->id );
448                     return;
449                 }
450             }
451             break;
452
453         case APIC_DM_SIPI:
454             foreach_apic(apic_iter, deliver_bitmask,
455                          apic_startup(apic_iter, vector_num) );
456             return;
457     }
458
459     apic_bus_deliver(deliver_bitmask, delivery_mode, vector_num, trigger_mode);
460 }
461
462 int apic_get_interrupt(DeviceState *d)
463 {
464     APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d);
465     int intno;
466
467     /* if the APIC is installed or enabled, we let the 8259 handle the
468        IRQs */
469     if (!s)
470         return -1;
471     if (!(s->spurious_vec & APIC_SV_ENABLE))
472         return -1;
473
474     intno = apic_irq_pending(s);
475
476     if (intno == 0) {
477         return -1;
478     } else if (intno < 0) {
479         return s->spurious_vec & 0xff;
480     }
481     reset_bit(s->irr, intno);
482     set_bit(s->isr, intno);
483     apic_update_irq(s);
484     return intno;
485 }
486
487 int apic_accept_pic_intr(DeviceState *d)
488 {
489     APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d);
490     uint32_t lvt0;
491
492     if (!s)
493         return -1;
494
495     lvt0 = s->lvt[APIC_LVT_LINT0];
496
497     if ((s->apicbase & MSR_IA32_APICBASE_ENABLE) == 0 ||
498         (lvt0 & APIC_LVT_MASKED) == 0)
499         return 1;
500
501     return 0;
502 }
503
504 static uint32_t apic_get_current_count(APICCommonState *s)
505 {
506     int64_t d;
507     uint32_t val;
508     d = (qemu_get_clock_ns(vm_clock) - s->initial_count_load_time) >>
509         s->count_shift;
510     if (s->lvt[APIC_LVT_TIMER] & APIC_LVT_TIMER_PERIODIC) {
511         /* periodic */
512         val = s->initial_count - (d % ((uint64_t)s->initial_count + 1));
513     } else {
514         if (d >= s->initial_count)
515             val = 0;
516         else
517             val = s->initial_count - d;
518     }
519     return val;
520 }
521
522 static void apic_timer_update(APICCommonState *s, int64_t current_time)
523 {
524     if (apic_next_timer(s, current_time)) {
525         qemu_mod_timer(s->timer, s->next_time);
526     } else {
527         qemu_del_timer(s->timer);
528     }
529 }
530
531 static void apic_timer(void *opaque)
532 {
533     APICCommonState *s = opaque;
534
535     apic_local_deliver(s, APIC_LVT_TIMER);
536     apic_timer_update(s, s->next_time);
537 }
538
539 static uint32_t apic_mem_readb(void *opaque, target_phys_addr_t addr)
540 {
541     return 0;
542 }
543
544 static uint32_t apic_mem_readw(void *opaque, target_phys_addr_t addr)
545 {
546     return 0;
547 }
548
549 static void apic_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
550 {
551 }
552
553 static void apic_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
554 {
555 }
556
557 static uint32_t apic_mem_readl(void *opaque, target_phys_addr_t addr)
558 {
559     DeviceState *d;
560     APICCommonState *s;
561     uint32_t val;
562     int index;
563
564     d = cpu_get_current_apic();
565     if (!d) {
566         return 0;
567     }
568     s = DO_UPCAST(APICCommonState, busdev.qdev, d);
569
570     index = (addr >> 4) & 0xff;
571     switch(index) {
572     case 0x02: /* id */
573         val = s->id << 24;
574         break;
575     case 0x03: /* version */
576         val = 0x11 | ((APIC_LVT_NB - 1) << 16); /* version 0x11 */
577         break;
578     case 0x08:
579         val = s->tpr;
580         break;
581     case 0x09:
582         val = apic_get_arb_pri(s);
583         break;
584     case 0x0a:
585         /* ppr */
586         val = apic_get_ppr(s);
587         break;
588     case 0x0b:
589         val = 0;
590         break;
591     case 0x0d:
592         val = s->log_dest << 24;
593         break;
594     case 0x0e:
595         val = s->dest_mode << 28;
596         break;
597     case 0x0f:
598         val = s->spurious_vec;
599         break;
600     case 0x10 ... 0x17:
601         val = s->isr[index & 7];
602         break;
603     case 0x18 ... 0x1f:
604         val = s->tmr[index & 7];
605         break;
606     case 0x20 ... 0x27:
607         val = s->irr[index & 7];
608         break;
609     case 0x28:
610         val = s->esr;
611         break;
612     case 0x30:
613     case 0x31:
614         val = s->icr[index & 1];
615         break;
616     case 0x32 ... 0x37:
617         val = s->lvt[index - 0x32];
618         break;
619     case 0x38:
620         val = s->initial_count;
621         break;
622     case 0x39:
623         val = apic_get_current_count(s);
624         break;
625     case 0x3e:
626         val = s->divide_conf;
627         break;
628     default:
629         s->esr |= ESR_ILLEGAL_ADDRESS;
630         val = 0;
631         break;
632     }
633     trace_apic_mem_readl(addr, val);
634     return val;
635 }
636
637 static void apic_send_msi(target_phys_addr_t addr, uint32_t data)
638 {
639     uint8_t dest = (addr & MSI_ADDR_DEST_ID_MASK) >> MSI_ADDR_DEST_ID_SHIFT;
640     uint8_t vector = (data & MSI_DATA_VECTOR_MASK) >> MSI_DATA_VECTOR_SHIFT;
641     uint8_t dest_mode = (addr >> MSI_ADDR_DEST_MODE_SHIFT) & 0x1;
642     uint8_t trigger_mode = (data >> MSI_DATA_TRIGGER_SHIFT) & 0x1;
643     uint8_t delivery = (data >> MSI_DATA_DELIVERY_MODE_SHIFT) & 0x7;
644     /* XXX: Ignore redirection hint. */
645     apic_deliver_irq(dest, dest_mode, delivery, vector, trigger_mode);
646 }
647
648 static void apic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
649 {
650     DeviceState *d;
651     APICCommonState *s;
652     int index = (addr >> 4) & 0xff;
653     if (addr > 0xfff || !index) {
654         /* MSI and MMIO APIC are at the same memory location,
655          * but actually not on the global bus: MSI is on PCI bus
656          * APIC is connected directly to the CPU.
657          * Mapping them on the global bus happens to work because
658          * MSI registers are reserved in APIC MMIO and vice versa. */
659         apic_send_msi(addr, val);
660         return;
661     }
662
663     d = cpu_get_current_apic();
664     if (!d) {
665         return;
666     }
667     s = DO_UPCAST(APICCommonState, busdev.qdev, d);
668
669     trace_apic_mem_writel(addr, val);
670
671     switch(index) {
672     case 0x02:
673         s->id = (val >> 24);
674         break;
675     case 0x03:
676         break;
677     case 0x08:
678         s->tpr = val;
679         apic_update_irq(s);
680         break;
681     case 0x09:
682     case 0x0a:
683         break;
684     case 0x0b: /* EOI */
685         apic_eoi(s);
686         break;
687     case 0x0d:
688         s->log_dest = val >> 24;
689         break;
690     case 0x0e:
691         s->dest_mode = val >> 28;
692         break;
693     case 0x0f:
694         s->spurious_vec = val & 0x1ff;
695         apic_update_irq(s);
696         break;
697     case 0x10 ... 0x17:
698     case 0x18 ... 0x1f:
699     case 0x20 ... 0x27:
700     case 0x28:
701         break;
702     case 0x30:
703         s->icr[0] = val;
704         apic_deliver(d, (s->icr[1] >> 24) & 0xff, (s->icr[0] >> 11) & 1,
705                      (s->icr[0] >> 8) & 7, (s->icr[0] & 0xff),
706                      (s->icr[0] >> 15) & 1);
707         break;
708     case 0x31:
709         s->icr[1] = val;
710         break;
711     case 0x32 ... 0x37:
712         {
713             int n = index - 0x32;
714             s->lvt[n] = val;
715             if (n == APIC_LVT_TIMER)
716                 apic_timer_update(s, qemu_get_clock_ns(vm_clock));
717         }
718         break;
719     case 0x38:
720         s->initial_count = val;
721         s->initial_count_load_time = qemu_get_clock_ns(vm_clock);
722         apic_timer_update(s, s->initial_count_load_time);
723         break;
724     case 0x39:
725         break;
726     case 0x3e:
727         {
728             int v;
729             s->divide_conf = val & 0xb;
730             v = (s->divide_conf & 3) | ((s->divide_conf >> 1) & 4);
731             s->count_shift = (v + 1) & 7;
732         }
733         break;
734     default:
735         s->esr |= ESR_ILLEGAL_ADDRESS;
736         break;
737     }
738 }
739
740 static void apic_post_load(APICCommonState *s)
741 {
742     if (s->timer_expiry != -1) {
743         qemu_mod_timer(s->timer, s->timer_expiry);
744     } else {
745         qemu_del_timer(s->timer);
746     }
747 }
748
749 static const MemoryRegionOps apic_io_ops = {
750     .old_mmio = {
751         .read = { apic_mem_readb, apic_mem_readw, apic_mem_readl, },
752         .write = { apic_mem_writeb, apic_mem_writew, apic_mem_writel, },
753     },
754     .endianness = DEVICE_NATIVE_ENDIAN,
755 };
756
757 static void apic_init(APICCommonState *s)
758 {
759     memory_region_init_io(&s->io_memory, &apic_io_ops, s, "apic-msi",
760                           MSI_SPACE_SIZE);
761
762     s->timer = qemu_new_timer_ns(vm_clock, apic_timer, s);
763     local_apics[s->idx] = s;
764 }
765
766 static void apic_class_init(ObjectClass *klass, void *data)
767 {
768     APICCommonClass *k = APIC_COMMON_CLASS(klass);
769
770     k->init = apic_init;
771     k->set_base = apic_set_base;
772     k->set_tpr = apic_set_tpr;
773     k->external_nmi = apic_external_nmi;
774     k->post_load = apic_post_load;
775 }
776
777 static TypeInfo apic_info = {
778     .name          = "apic",
779     .instance_size = sizeof(APICCommonState),
780     .parent        = TYPE_APIC_COMMON,
781     .class_init    = apic_class_init,
782 };
783
784 static void apic_register_types(void)
785 {
786     type_register_static(&apic_info);
787 }
788
789 type_init(apic_register_types)
This page took 0.065379 seconds and 4 git commands to generate.