]> git.proxmox.com Git - qemu.git/blame - hw/apic.c
COPYING: update from FSF
[qemu.git] / hw / apic.c
CommitLineData
574bbf7b
FB
1/*
2 * APIC support
5fafdf24 3 *
574bbf7b
FB
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, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
87ecb68b
PB
20#include "hw.h"
21#include "pc.h"
22#include "qemu-timer.h"
bad5b1ec 23#include "osdep.h"
574bbf7b
FB
24
25//#define DEBUG_APIC
d592d303 26//#define DEBUG_IOAPIC
574bbf7b
FB
27
28/* APIC Local Vector Table */
29#define APIC_LVT_TIMER 0
30#define APIC_LVT_THERMAL 1
31#define APIC_LVT_PERFORM 2
32#define APIC_LVT_LINT0 3
33#define APIC_LVT_LINT1 4
34#define APIC_LVT_ERROR 5
35#define APIC_LVT_NB 6
36
37/* APIC delivery modes */
38#define APIC_DM_FIXED 0
39#define APIC_DM_LOWPRI 1
40#define APIC_DM_SMI 2
41#define APIC_DM_NMI 4
42#define APIC_DM_INIT 5
43#define APIC_DM_SIPI 6
44#define APIC_DM_EXTINT 7
45
d592d303
FB
46/* APIC destination mode */
47#define APIC_DESTMODE_FLAT 0xf
48#define APIC_DESTMODE_CLUSTER 1
49
574bbf7b
FB
50#define APIC_TRIGGER_EDGE 0
51#define APIC_TRIGGER_LEVEL 1
52
53#define APIC_LVT_TIMER_PERIODIC (1<<17)
54#define APIC_LVT_MASKED (1<<16)
55#define APIC_LVT_LEVEL_TRIGGER (1<<15)
56#define APIC_LVT_REMOTE_IRR (1<<14)
57#define APIC_INPUT_POLARITY (1<<13)
58#define APIC_SEND_PENDING (1<<12)
59
d592d303
FB
60#define IOAPIC_NUM_PINS 0x18
61
574bbf7b
FB
62#define ESR_ILLEGAL_ADDRESS (1 << 7)
63
64#define APIC_SV_ENABLE (1 << 8)
65
d3e9db93
FB
66#define MAX_APICS 255
67#define MAX_APIC_WORDS 8
68
574bbf7b
FB
69typedef struct APICState {
70 CPUState *cpu_env;
71 uint32_t apicbase;
72 uint8_t id;
d592d303 73 uint8_t arb_id;
574bbf7b
FB
74 uint8_t tpr;
75 uint32_t spurious_vec;
d592d303
FB
76 uint8_t log_dest;
77 uint8_t dest_mode;
574bbf7b
FB
78 uint32_t isr[8]; /* in service register */
79 uint32_t tmr[8]; /* trigger mode register */
80 uint32_t irr[8]; /* interrupt request register */
81 uint32_t lvt[APIC_LVT_NB];
82 uint32_t esr; /* error register */
83 uint32_t icr[2];
84
85 uint32_t divide_conf;
86 int count_shift;
87 uint32_t initial_count;
88 int64_t initial_count_load_time, next_time;
89 QEMUTimer *timer;
90} APICState;
91
d592d303
FB
92struct IOAPICState {
93 uint8_t id;
94 uint8_t ioregsel;
95
96 uint32_t irr;
97 uint64_t ioredtbl[IOAPIC_NUM_PINS];
98};
99
574bbf7b 100static int apic_io_memory;
d3e9db93 101static APICState *local_apics[MAX_APICS + 1];
d592d303 102static int last_apic_id = 0;
d592d303
FB
103
104static void apic_init_ipi(APICState *s);
105static void apic_set_irq(APICState *s, int vector_num, int trigger_mode);
106static void apic_update_irq(APICState *s);
107
e95f5491 108/* Find first bit starting from msb */
d3e9db93
FB
109static int fls_bit(uint32_t value)
110{
bad5b1ec 111#if QEMU_GNUC_PREREQ(3, 4)
e95f5491
AJ
112 return 31 - __builtin_clz(value);
113#else
d3e9db93
FB
114 unsigned int ret = 0;
115
d3e9db93
FB
116 if (value > 0xffff)
117 value >>= 16, ret = 16;
118 if (value > 0xff)
119 value >>= 8, ret += 8;
120 if (value > 0xf)
121 value >>= 4, ret += 4;
122 if (value > 0x3)
123 value >>= 2, ret += 2;
124 return ret + (value >> 1);
125#endif
126}
127
e95f5491 128/* Find first bit starting from lsb */
d3e9db93
FB
129static int ffs_bit(uint32_t value)
130{
bad5b1ec 131#if QEMU_GNUC_PREREQ(3, 4)
e95f5491
AJ
132 return __builtin_ffs(value) - 1;
133#else
d3e9db93
FB
134 unsigned int ret = 0;
135
d3e9db93
FB
136 if (!value)
137 return 0;
138 if (!(value & 0xffff))
139 value >>= 16, ret = 16;
140 if (!(value & 0xff))
141 value >>= 8, ret += 8;
142 if (!(value & 0xf))
143 value >>= 4, ret += 4;
144 if (!(value & 0x3))
145 value >>= 2, ret += 2;
146 if (!(value & 0x1))
147 ret++;
148 return ret;
149#endif
150}
151
152static inline void set_bit(uint32_t *tab, int index)
153{
154 int i, mask;
155 i = index >> 5;
156 mask = 1 << (index & 0x1f);
157 tab[i] |= mask;
158}
159
160static inline void reset_bit(uint32_t *tab, int index)
161{
162 int i, mask;
163 i = index >> 5;
164 mask = 1 << (index & 0x1f);
165 tab[i] &= ~mask;
166}
167
1a7de94a 168static void apic_local_deliver(CPUState *env, int vector)
a5b38b51
AJ
169{
170 APICState *s = env->apic_state;
171 uint32_t lvt = s->lvt[vector];
172 int trigger_mode;
173
174 if (lvt & APIC_LVT_MASKED)
175 return;
176
177 switch ((lvt >> 8) & 7) {
178 case APIC_DM_SMI:
179 cpu_interrupt(env, CPU_INTERRUPT_SMI);
180 break;
181
182 case APIC_DM_NMI:
183 cpu_interrupt(env, CPU_INTERRUPT_NMI);
184 break;
185
186 case APIC_DM_EXTINT:
187 cpu_interrupt(env, CPU_INTERRUPT_HARD);
188 break;
189
190 case APIC_DM_FIXED:
191 trigger_mode = APIC_TRIGGER_EDGE;
192 if ((vector == APIC_LVT_LINT0 || vector == APIC_LVT_LINT1) &&
193 (lvt & APIC_LVT_LEVEL_TRIGGER))
194 trigger_mode = APIC_TRIGGER_LEVEL;
195 apic_set_irq(s, lvt & 0xff, trigger_mode);
196 }
197}
198
1a7de94a
AJ
199void apic_deliver_pic_intr(CPUState *env, int level)
200{
201 if (level)
202 apic_local_deliver(env, APIC_LVT_LINT0);
203 else {
204 APICState *s = env->apic_state;
205 uint32_t lvt = s->lvt[APIC_LVT_LINT0];
206
207 switch ((lvt >> 8) & 7) {
208 case APIC_DM_FIXED:
209 if (!(lvt & APIC_LVT_LEVEL_TRIGGER))
210 break;
211 reset_bit(s->irr, lvt & 0xff);
212 /* fall through */
213 case APIC_DM_EXTINT:
214 cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
215 break;
216 }
217 }
218}
219
d3e9db93
FB
220#define foreach_apic(apic, deliver_bitmask, code) \
221{\
222 int __i, __j, __mask;\
223 for(__i = 0; __i < MAX_APIC_WORDS; __i++) {\
224 __mask = deliver_bitmask[__i];\
225 if (__mask) {\
226 for(__j = 0; __j < 32; __j++) {\
227 if (__mask & (1 << __j)) {\
228 apic = local_apics[__i * 32 + __j];\
229 if (apic) {\
230 code;\
231 }\
232 }\
233 }\
234 }\
235 }\
236}
237
5fafdf24 238static void apic_bus_deliver(const uint32_t *deliver_bitmask,
d3e9db93 239 uint8_t delivery_mode,
d592d303
FB
240 uint8_t vector_num, uint8_t polarity,
241 uint8_t trigger_mode)
242{
243 APICState *apic_iter;
244
245 switch (delivery_mode) {
246 case APIC_DM_LOWPRI:
8dd69b8f 247 /* XXX: search for focus processor, arbitration */
d3e9db93
FB
248 {
249 int i, d;
250 d = -1;
251 for(i = 0; i < MAX_APIC_WORDS; i++) {
252 if (deliver_bitmask[i]) {
253 d = i * 32 + ffs_bit(deliver_bitmask[i]);
254 break;
255 }
256 }
257 if (d >= 0) {
258 apic_iter = local_apics[d];
259 if (apic_iter) {
260 apic_set_irq(apic_iter, vector_num, trigger_mode);
261 }
262 }
8dd69b8f 263 }
d3e9db93 264 return;
8dd69b8f 265
d592d303 266 case APIC_DM_FIXED:
d592d303
FB
267 break;
268
269 case APIC_DM_SMI:
e2eb9d3e
AJ
270 foreach_apic(apic_iter, deliver_bitmask,
271 cpu_interrupt(apic_iter->cpu_env, CPU_INTERRUPT_SMI) );
272 return;
273
d592d303 274 case APIC_DM_NMI:
e2eb9d3e
AJ
275 foreach_apic(apic_iter, deliver_bitmask,
276 cpu_interrupt(apic_iter->cpu_env, CPU_INTERRUPT_NMI) );
277 return;
d592d303
FB
278
279 case APIC_DM_INIT:
280 /* normal INIT IPI sent to processors */
5fafdf24 281 foreach_apic(apic_iter, deliver_bitmask,
d3e9db93 282 apic_init_ipi(apic_iter) );
d592d303 283 return;
3b46e624 284
d592d303 285 case APIC_DM_EXTINT:
b1fc0348 286 /* handled in I/O APIC code */
d592d303
FB
287 break;
288
289 default:
290 return;
291 }
292
5fafdf24 293 foreach_apic(apic_iter, deliver_bitmask,
d3e9db93 294 apic_set_irq(apic_iter, vector_num, trigger_mode) );
d592d303 295}
574bbf7b
FB
296
297void cpu_set_apic_base(CPUState *env, uint64_t val)
298{
299 APICState *s = env->apic_state;
300#ifdef DEBUG_APIC
26a76461 301 printf("cpu_set_apic_base: %016" PRIx64 "\n", val);
574bbf7b 302#endif
5fafdf24 303 s->apicbase = (val & 0xfffff000) |
574bbf7b
FB
304 (s->apicbase & (MSR_IA32_APICBASE_BSP | MSR_IA32_APICBASE_ENABLE));
305 /* if disabled, cannot be enabled again */
306 if (!(val & MSR_IA32_APICBASE_ENABLE)) {
307 s->apicbase &= ~MSR_IA32_APICBASE_ENABLE;
308 env->cpuid_features &= ~CPUID_APIC;
309 s->spurious_vec &= ~APIC_SV_ENABLE;
310 }
311}
312
313uint64_t cpu_get_apic_base(CPUState *env)
314{
315 APICState *s = env->apic_state;
316#ifdef DEBUG_APIC
26a76461 317 printf("cpu_get_apic_base: %016" PRIx64 "\n", (uint64_t)s->apicbase);
574bbf7b
FB
318#endif
319 return s->apicbase;
320}
321
9230e66e
FB
322void cpu_set_apic_tpr(CPUX86State *env, uint8_t val)
323{
324 APICState *s = env->apic_state;
325 s->tpr = (val & 0x0f) << 4;
d592d303 326 apic_update_irq(s);
9230e66e
FB
327}
328
329uint8_t cpu_get_apic_tpr(CPUX86State *env)
330{
331 APICState *s = env->apic_state;
332 return s->tpr >> 4;
333}
334
d592d303
FB
335/* return -1 if no bit is set */
336static int get_highest_priority_int(uint32_t *tab)
337{
338 int i;
339 for(i = 7; i >= 0; i--) {
340 if (tab[i] != 0) {
341 return i * 32 + fls_bit(tab[i]);
342 }
343 }
344 return -1;
345}
346
574bbf7b
FB
347static int apic_get_ppr(APICState *s)
348{
349 int tpr, isrv, ppr;
350
351 tpr = (s->tpr >> 4);
352 isrv = get_highest_priority_int(s->isr);
353 if (isrv < 0)
354 isrv = 0;
355 isrv >>= 4;
356 if (tpr >= isrv)
357 ppr = s->tpr;
358 else
359 ppr = isrv << 4;
360 return ppr;
361}
362
d592d303
FB
363static int apic_get_arb_pri(APICState *s)
364{
365 /* XXX: arbitration */
366 return 0;
367}
368
574bbf7b
FB
369/* signal the CPU if an irq is pending */
370static void apic_update_irq(APICState *s)
371{
d592d303
FB
372 int irrv, ppr;
373 if (!(s->spurious_vec & APIC_SV_ENABLE))
374 return;
574bbf7b
FB
375 irrv = get_highest_priority_int(s->irr);
376 if (irrv < 0)
377 return;
d592d303
FB
378 ppr = apic_get_ppr(s);
379 if (ppr && (irrv & 0xf0) <= (ppr & 0xf0))
574bbf7b
FB
380 return;
381 cpu_interrupt(s->cpu_env, CPU_INTERRUPT_HARD);
382}
383
384static void apic_set_irq(APICState *s, int vector_num, int trigger_mode)
385{
386 set_bit(s->irr, vector_num);
387 if (trigger_mode)
388 set_bit(s->tmr, vector_num);
389 else
390 reset_bit(s->tmr, vector_num);
391 apic_update_irq(s);
392}
393
394static void apic_eoi(APICState *s)
395{
396 int isrv;
397 isrv = get_highest_priority_int(s->isr);
398 if (isrv < 0)
399 return;
400 reset_bit(s->isr, isrv);
d592d303
FB
401 /* XXX: send the EOI packet to the APIC bus to allow the I/O APIC to
402 set the remote IRR bit for level triggered interrupts. */
574bbf7b
FB
403 apic_update_irq(s);
404}
405
d3e9db93
FB
406static void apic_get_delivery_bitmask(uint32_t *deliver_bitmask,
407 uint8_t dest, uint8_t dest_mode)
d592d303 408{
d592d303 409 APICState *apic_iter;
d3e9db93 410 int i;
d592d303
FB
411
412 if (dest_mode == 0) {
d3e9db93
FB
413 if (dest == 0xff) {
414 memset(deliver_bitmask, 0xff, MAX_APIC_WORDS * sizeof(uint32_t));
415 } else {
416 memset(deliver_bitmask, 0x00, MAX_APIC_WORDS * sizeof(uint32_t));
417 set_bit(deliver_bitmask, dest);
418 }
d592d303
FB
419 } else {
420 /* XXX: cluster mode */
d3e9db93
FB
421 memset(deliver_bitmask, 0x00, MAX_APIC_WORDS * sizeof(uint32_t));
422 for(i = 0; i < MAX_APICS; i++) {
423 apic_iter = local_apics[i];
424 if (apic_iter) {
425 if (apic_iter->dest_mode == 0xf) {
426 if (dest & apic_iter->log_dest)
427 set_bit(deliver_bitmask, i);
428 } else if (apic_iter->dest_mode == 0x0) {
429 if ((dest & 0xf0) == (apic_iter->log_dest & 0xf0) &&
430 (dest & apic_iter->log_dest & 0x0f)) {
431 set_bit(deliver_bitmask, i);
432 }
433 }
434 }
d592d303
FB
435 }
436 }
d592d303
FB
437}
438
439
440static void apic_init_ipi(APICState *s)
441{
442 int i;
443
d592d303
FB
444 s->tpr = 0;
445 s->spurious_vec = 0xff;
446 s->log_dest = 0;
e0fd8781 447 s->dest_mode = 0xf;
d592d303
FB
448 memset(s->isr, 0, sizeof(s->isr));
449 memset(s->tmr, 0, sizeof(s->tmr));
450 memset(s->irr, 0, sizeof(s->irr));
b4511723
FB
451 for(i = 0; i < APIC_LVT_NB; i++)
452 s->lvt[i] = 1 << 16; /* mask LVT */
d592d303
FB
453 s->esr = 0;
454 memset(s->icr, 0, sizeof(s->icr));
455 s->divide_conf = 0;
456 s->count_shift = 0;
457 s->initial_count = 0;
458 s->initial_count_load_time = 0;
459 s->next_time = 0;
3003b8bb
AJ
460
461 cpu_reset(s->cpu_env);
462
463 if (!(s->apicbase & MSR_IA32_APICBASE_BSP))
464 s->cpu_env->halted = 1;
d592d303
FB
465}
466
e0fd8781
FB
467/* send a SIPI message to the CPU to start it */
468static void apic_startup(APICState *s, int vector_num)
469{
470 CPUState *env = s->cpu_env;
ce5232c5 471 if (!env->halted)
e0fd8781
FB
472 return;
473 env->eip = 0;
5fafdf24 474 cpu_x86_load_seg_cache(env, R_CS, vector_num << 8, vector_num << 12,
e0fd8781 475 0xffff, 0);
ce5232c5 476 env->halted = 0;
e0fd8781
FB
477}
478
d592d303
FB
479static void apic_deliver(APICState *s, uint8_t dest, uint8_t dest_mode,
480 uint8_t delivery_mode, uint8_t vector_num,
481 uint8_t polarity, uint8_t trigger_mode)
482{
d3e9db93 483 uint32_t deliver_bitmask[MAX_APIC_WORDS];
d592d303
FB
484 int dest_shorthand = (s->icr[0] >> 18) & 3;
485 APICState *apic_iter;
486
e0fd8781 487 switch (dest_shorthand) {
d3e9db93
FB
488 case 0:
489 apic_get_delivery_bitmask(deliver_bitmask, dest, dest_mode);
490 break;
491 case 1:
492 memset(deliver_bitmask, 0x00, sizeof(deliver_bitmask));
493 set_bit(deliver_bitmask, s->id);
494 break;
495 case 2:
496 memset(deliver_bitmask, 0xff, sizeof(deliver_bitmask));
497 break;
498 case 3:
499 memset(deliver_bitmask, 0xff, sizeof(deliver_bitmask));
500 reset_bit(deliver_bitmask, s->id);
501 break;
e0fd8781
FB
502 }
503
d592d303 504 switch (delivery_mode) {
d592d303
FB
505 case APIC_DM_INIT:
506 {
507 int trig_mode = (s->icr[0] >> 15) & 1;
508 int level = (s->icr[0] >> 14) & 1;
509 if (level == 0 && trig_mode == 1) {
5fafdf24 510 foreach_apic(apic_iter, deliver_bitmask,
d3e9db93 511 apic_iter->arb_id = apic_iter->id );
d592d303
FB
512 return;
513 }
514 }
515 break;
516
517 case APIC_DM_SIPI:
5fafdf24 518 foreach_apic(apic_iter, deliver_bitmask,
d3e9db93 519 apic_startup(apic_iter, vector_num) );
d592d303
FB
520 return;
521 }
522
d592d303
FB
523 apic_bus_deliver(deliver_bitmask, delivery_mode, vector_num, polarity,
524 trigger_mode);
525}
526
574bbf7b
FB
527int apic_get_interrupt(CPUState *env)
528{
529 APICState *s = env->apic_state;
530 int intno;
531
532 /* if the APIC is installed or enabled, we let the 8259 handle the
533 IRQs */
534 if (!s)
535 return -1;
536 if (!(s->spurious_vec & APIC_SV_ENABLE))
537 return -1;
3b46e624 538
574bbf7b
FB
539 /* XXX: spurious IRQ handling */
540 intno = get_highest_priority_int(s->irr);
541 if (intno < 0)
542 return -1;
d592d303
FB
543 if (s->tpr && intno <= s->tpr)
544 return s->spurious_vec & 0xff;
b4511723 545 reset_bit(s->irr, intno);
574bbf7b
FB
546 set_bit(s->isr, intno);
547 apic_update_irq(s);
548 return intno;
549}
550
0e21e12b
TS
551int apic_accept_pic_intr(CPUState *env)
552{
553 APICState *s = env->apic_state;
554 uint32_t lvt0;
555
556 if (!s)
557 return -1;
558
559 lvt0 = s->lvt[APIC_LVT_LINT0];
560
a5b38b51
AJ
561 if ((s->apicbase & MSR_IA32_APICBASE_ENABLE) == 0 ||
562 (lvt0 & APIC_LVT_MASKED) == 0)
0e21e12b
TS
563 return 1;
564
565 return 0;
566}
567
574bbf7b
FB
568static uint32_t apic_get_current_count(APICState *s)
569{
570 int64_t d;
571 uint32_t val;
5fafdf24 572 d = (qemu_get_clock(vm_clock) - s->initial_count_load_time) >>
574bbf7b
FB
573 s->count_shift;
574 if (s->lvt[APIC_LVT_TIMER] & APIC_LVT_TIMER_PERIODIC) {
575 /* periodic */
d592d303 576 val = s->initial_count - (d % ((uint64_t)s->initial_count + 1));
574bbf7b
FB
577 } else {
578 if (d >= s->initial_count)
579 val = 0;
580 else
581 val = s->initial_count - d;
582 }
583 return val;
584}
585
586static void apic_timer_update(APICState *s, int64_t current_time)
587{
588 int64_t next_time, d;
3b46e624 589
574bbf7b 590 if (!(s->lvt[APIC_LVT_TIMER] & APIC_LVT_MASKED)) {
5fafdf24 591 d = (current_time - s->initial_count_load_time) >>
574bbf7b
FB
592 s->count_shift;
593 if (s->lvt[APIC_LVT_TIMER] & APIC_LVT_TIMER_PERIODIC) {
681f8c29
AL
594 if (!s->initial_count)
595 goto no_timer;
d592d303 596 d = ((d / ((uint64_t)s->initial_count + 1)) + 1) * ((uint64_t)s->initial_count + 1);
574bbf7b
FB
597 } else {
598 if (d >= s->initial_count)
599 goto no_timer;
d592d303 600 d = (uint64_t)s->initial_count + 1;
574bbf7b
FB
601 }
602 next_time = s->initial_count_load_time + (d << s->count_shift);
603 qemu_mod_timer(s->timer, next_time);
604 s->next_time = next_time;
605 } else {
606 no_timer:
607 qemu_del_timer(s->timer);
608 }
609}
610
611static void apic_timer(void *opaque)
612{
613 APICState *s = opaque;
614
a5b38b51 615 apic_local_deliver(s->cpu_env, APIC_LVT_TIMER);
574bbf7b
FB
616 apic_timer_update(s, s->next_time);
617}
618
619static uint32_t apic_mem_readb(void *opaque, target_phys_addr_t addr)
620{
621 return 0;
622}
623
624static uint32_t apic_mem_readw(void *opaque, target_phys_addr_t addr)
625{
626 return 0;
627}
628
629static void apic_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
630{
631}
632
633static void apic_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
634{
635}
636
637static uint32_t apic_mem_readl(void *opaque, target_phys_addr_t addr)
638{
639 CPUState *env;
640 APICState *s;
641 uint32_t val;
642 int index;
643
644 env = cpu_single_env;
645 if (!env)
646 return 0;
647 s = env->apic_state;
648
649 index = (addr >> 4) & 0xff;
650 switch(index) {
651 case 0x02: /* id */
652 val = s->id << 24;
653 break;
654 case 0x03: /* version */
655 val = 0x11 | ((APIC_LVT_NB - 1) << 16); /* version 0x11 */
656 break;
657 case 0x08:
658 val = s->tpr;
659 break;
d592d303
FB
660 case 0x09:
661 val = apic_get_arb_pri(s);
662 break;
574bbf7b
FB
663 case 0x0a:
664 /* ppr */
665 val = apic_get_ppr(s);
666 break;
b237db36
AJ
667 case 0x0b:
668 val = 0;
669 break;
d592d303
FB
670 case 0x0d:
671 val = s->log_dest << 24;
672 break;
673 case 0x0e:
674 val = s->dest_mode << 28;
675 break;
574bbf7b
FB
676 case 0x0f:
677 val = s->spurious_vec;
678 break;
679 case 0x10 ... 0x17:
680 val = s->isr[index & 7];
681 break;
682 case 0x18 ... 0x1f:
683 val = s->tmr[index & 7];
684 break;
685 case 0x20 ... 0x27:
686 val = s->irr[index & 7];
687 break;
688 case 0x28:
689 val = s->esr;
690 break;
574bbf7b
FB
691 case 0x30:
692 case 0x31:
693 val = s->icr[index & 1];
694 break;
e0fd8781
FB
695 case 0x32 ... 0x37:
696 val = s->lvt[index - 0x32];
697 break;
574bbf7b
FB
698 case 0x38:
699 val = s->initial_count;
700 break;
701 case 0x39:
702 val = apic_get_current_count(s);
703 break;
704 case 0x3e:
705 val = s->divide_conf;
706 break;
707 default:
708 s->esr |= ESR_ILLEGAL_ADDRESS;
709 val = 0;
710 break;
711 }
712#ifdef DEBUG_APIC
713 printf("APIC read: %08x = %08x\n", (uint32_t)addr, val);
714#endif
715 return val;
716}
717
718static void apic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
719{
720 CPUState *env;
721 APICState *s;
722 int index;
723
724 env = cpu_single_env;
725 if (!env)
726 return;
727 s = env->apic_state;
728
729#ifdef DEBUG_APIC
730 printf("APIC write: %08x = %08x\n", (uint32_t)addr, val);
731#endif
732
733 index = (addr >> 4) & 0xff;
734 switch(index) {
735 case 0x02:
736 s->id = (val >> 24);
737 break;
e0fd8781
FB
738 case 0x03:
739 break;
574bbf7b
FB
740 case 0x08:
741 s->tpr = val;
d592d303 742 apic_update_irq(s);
574bbf7b 743 break;
e0fd8781
FB
744 case 0x09:
745 case 0x0a:
746 break;
574bbf7b
FB
747 case 0x0b: /* EOI */
748 apic_eoi(s);
749 break;
d592d303
FB
750 case 0x0d:
751 s->log_dest = val >> 24;
752 break;
753 case 0x0e:
754 s->dest_mode = val >> 28;
755 break;
574bbf7b
FB
756 case 0x0f:
757 s->spurious_vec = val & 0x1ff;
d592d303 758 apic_update_irq(s);
574bbf7b 759 break;
e0fd8781
FB
760 case 0x10 ... 0x17:
761 case 0x18 ... 0x1f:
762 case 0x20 ... 0x27:
763 case 0x28:
764 break;
574bbf7b 765 case 0x30:
d592d303
FB
766 s->icr[0] = val;
767 apic_deliver(s, (s->icr[1] >> 24) & 0xff, (s->icr[0] >> 11) & 1,
768 (s->icr[0] >> 8) & 7, (s->icr[0] & 0xff),
769 (s->icr[0] >> 14) & 1, (s->icr[0] >> 15) & 1);
770 break;
574bbf7b 771 case 0x31:
d592d303 772 s->icr[1] = val;
574bbf7b
FB
773 break;
774 case 0x32 ... 0x37:
775 {
776 int n = index - 0x32;
777 s->lvt[n] = val;
778 if (n == APIC_LVT_TIMER)
779 apic_timer_update(s, qemu_get_clock(vm_clock));
780 }
781 break;
782 case 0x38:
783 s->initial_count = val;
784 s->initial_count_load_time = qemu_get_clock(vm_clock);
785 apic_timer_update(s, s->initial_count_load_time);
786 break;
e0fd8781
FB
787 case 0x39:
788 break;
574bbf7b
FB
789 case 0x3e:
790 {
791 int v;
792 s->divide_conf = val & 0xb;
793 v = (s->divide_conf & 3) | ((s->divide_conf >> 1) & 4);
794 s->count_shift = (v + 1) & 7;
795 }
796 break;
797 default:
798 s->esr |= ESR_ILLEGAL_ADDRESS;
799 break;
800 }
801}
802
d592d303
FB
803static void apic_save(QEMUFile *f, void *opaque)
804{
805 APICState *s = opaque;
806 int i;
807
808 qemu_put_be32s(f, &s->apicbase);
809 qemu_put_8s(f, &s->id);
810 qemu_put_8s(f, &s->arb_id);
811 qemu_put_8s(f, &s->tpr);
812 qemu_put_be32s(f, &s->spurious_vec);
813 qemu_put_8s(f, &s->log_dest);
814 qemu_put_8s(f, &s->dest_mode);
815 for (i = 0; i < 8; i++) {
816 qemu_put_be32s(f, &s->isr[i]);
817 qemu_put_be32s(f, &s->tmr[i]);
818 qemu_put_be32s(f, &s->irr[i]);
819 }
820 for (i = 0; i < APIC_LVT_NB; i++) {
821 qemu_put_be32s(f, &s->lvt[i]);
822 }
823 qemu_put_be32s(f, &s->esr);
824 qemu_put_be32s(f, &s->icr[0]);
825 qemu_put_be32s(f, &s->icr[1]);
826 qemu_put_be32s(f, &s->divide_conf);
bee8d684 827 qemu_put_be32(f, s->count_shift);
d592d303 828 qemu_put_be32s(f, &s->initial_count);
bee8d684
TS
829 qemu_put_be64(f, s->initial_count_load_time);
830 qemu_put_be64(f, s->next_time);
e6cf6a8c
FB
831
832 qemu_put_timer(f, s->timer);
d592d303
FB
833}
834
835static int apic_load(QEMUFile *f, void *opaque, int version_id)
836{
837 APICState *s = opaque;
838 int i;
839
e6cf6a8c 840 if (version_id > 2)
d592d303
FB
841 return -EINVAL;
842
843 /* XXX: what if the base changes? (registered memory regions) */
844 qemu_get_be32s(f, &s->apicbase);
845 qemu_get_8s(f, &s->id);
846 qemu_get_8s(f, &s->arb_id);
847 qemu_get_8s(f, &s->tpr);
848 qemu_get_be32s(f, &s->spurious_vec);
849 qemu_get_8s(f, &s->log_dest);
850 qemu_get_8s(f, &s->dest_mode);
851 for (i = 0; i < 8; i++) {
852 qemu_get_be32s(f, &s->isr[i]);
853 qemu_get_be32s(f, &s->tmr[i]);
854 qemu_get_be32s(f, &s->irr[i]);
855 }
856 for (i = 0; i < APIC_LVT_NB; i++) {
857 qemu_get_be32s(f, &s->lvt[i]);
858 }
859 qemu_get_be32s(f, &s->esr);
860 qemu_get_be32s(f, &s->icr[0]);
861 qemu_get_be32s(f, &s->icr[1]);
862 qemu_get_be32s(f, &s->divide_conf);
bee8d684 863 s->count_shift=qemu_get_be32(f);
d592d303 864 qemu_get_be32s(f, &s->initial_count);
bee8d684
TS
865 s->initial_count_load_time=qemu_get_be64(f);
866 s->next_time=qemu_get_be64(f);
e6cf6a8c
FB
867
868 if (version_id >= 2)
869 qemu_get_timer(f, s->timer);
d592d303
FB
870 return 0;
871}
574bbf7b 872
d592d303
FB
873static void apic_reset(void *opaque)
874{
875 APICState *s = opaque;
fec5fa02
AJ
876
877 s->apicbase = 0xfee00000 |
878 (s->id ? 0 : MSR_IA32_APICBASE_BSP) | MSR_IA32_APICBASE_ENABLE;
879
d592d303 880 apic_init_ipi(s);
0e21e12b 881
a5b38b51
AJ
882 if (s->id == 0) {
883 /*
884 * LINT0 delivery mode on CPU #0 is set to ExtInt at initialization
885 * time typically by BIOS, so PIC interrupt can be delivered to the
886 * processor when local APIC is enabled.
887 */
888 s->lvt[APIC_LVT_LINT0] = 0x700;
889 }
d592d303 890}
574bbf7b
FB
891
892static CPUReadMemoryFunc *apic_mem_read[3] = {
893 apic_mem_readb,
894 apic_mem_readw,
895 apic_mem_readl,
896};
897
898static CPUWriteMemoryFunc *apic_mem_write[3] = {
899 apic_mem_writeb,
900 apic_mem_writew,
901 apic_mem_writel,
902};
903
904int apic_init(CPUState *env)
905{
906 APICState *s;
574bbf7b 907
d3e9db93
FB
908 if (last_apic_id >= MAX_APICS)
909 return -1;
d592d303 910 s = qemu_mallocz(sizeof(APICState));
574bbf7b
FB
911 if (!s)
912 return -1;
574bbf7b 913 env->apic_state = s;
d592d303 914 s->id = last_apic_id++;
eae7629b 915 env->cpuid_apic_id = s->id;
574bbf7b 916 s->cpu_env = env;
574bbf7b 917
a5b38b51 918 apic_reset(s);
0e21e12b 919
d592d303 920 /* XXX: mapping more APICs at the same memory location */
574bbf7b
FB
921 if (apic_io_memory == 0) {
922 /* NOTE: the APIC is directly connected to the CPU - it is not
923 on the global memory bus. */
5fafdf24 924 apic_io_memory = cpu_register_io_memory(0, apic_mem_read,
574bbf7b 925 apic_mem_write, NULL);
d592d303
FB
926 cpu_register_physical_memory(s->apicbase & ~0xfff, 0x1000,
927 apic_io_memory);
574bbf7b
FB
928 }
929 s->timer = qemu_new_timer(vm_clock, apic_timer, s);
d592d303 930
be0164f2 931 register_savevm("apic", s->id, 2, apic_save, apic_load, s);
d592d303 932 qemu_register_reset(apic_reset, s);
3b46e624 933
d3e9db93 934 local_apics[s->id] = s;
d592d303
FB
935 return 0;
936}
937
938static void ioapic_service(IOAPICState *s)
939{
b1fc0348
FB
940 uint8_t i;
941 uint8_t trig_mode;
d592d303 942 uint8_t vector;
b1fc0348 943 uint8_t delivery_mode;
d592d303
FB
944 uint32_t mask;
945 uint64_t entry;
946 uint8_t dest;
947 uint8_t dest_mode;
b1fc0348 948 uint8_t polarity;
d3e9db93 949 uint32_t deliver_bitmask[MAX_APIC_WORDS];
d592d303 950
b1fc0348
FB
951 for (i = 0; i < IOAPIC_NUM_PINS; i++) {
952 mask = 1 << i;
d592d303 953 if (s->irr & mask) {
b1fc0348 954 entry = s->ioredtbl[i];
d592d303 955 if (!(entry & APIC_LVT_MASKED)) {
b1fc0348 956 trig_mode = ((entry >> 15) & 1);
d592d303
FB
957 dest = entry >> 56;
958 dest_mode = (entry >> 11) & 1;
b1fc0348
FB
959 delivery_mode = (entry >> 8) & 7;
960 polarity = (entry >> 13) & 1;
961 if (trig_mode == APIC_TRIGGER_EDGE)
962 s->irr &= ~mask;
963 if (delivery_mode == APIC_DM_EXTINT)
964 vector = pic_read_irq(isa_pic);
965 else
966 vector = entry & 0xff;
3b46e624 967
d3e9db93 968 apic_get_delivery_bitmask(deliver_bitmask, dest, dest_mode);
5fafdf24 969 apic_bus_deliver(deliver_bitmask, delivery_mode,
d3e9db93 970 vector, polarity, trig_mode);
d592d303
FB
971 }
972 }
973 }
974}
975
976void ioapic_set_irq(void *opaque, int vector, int level)
977{
978 IOAPICState *s = opaque;
979
980 if (vector >= 0 && vector < IOAPIC_NUM_PINS) {
981 uint32_t mask = 1 << vector;
982 uint64_t entry = s->ioredtbl[vector];
983
984 if ((entry >> 15) & 1) {
985 /* level triggered */
986 if (level) {
987 s->irr |= mask;
988 ioapic_service(s);
989 } else {
990 s->irr &= ~mask;
991 }
992 } else {
993 /* edge triggered */
994 if (level) {
995 s->irr |= mask;
996 ioapic_service(s);
997 }
998 }
999 }
1000}
1001
1002static uint32_t ioapic_mem_readl(void *opaque, target_phys_addr_t addr)
1003{
1004 IOAPICState *s = opaque;
1005 int index;
1006 uint32_t val = 0;
1007
1008 addr &= 0xff;
1009 if (addr == 0x00) {
1010 val = s->ioregsel;
1011 } else if (addr == 0x10) {
1012 switch (s->ioregsel) {
1013 case 0x00:
1014 val = s->id << 24;
1015 break;
1016 case 0x01:
1017 val = 0x11 | ((IOAPIC_NUM_PINS - 1) << 16); /* version 0x11 */
1018 break;
1019 case 0x02:
1020 val = 0;
1021 break;
1022 default:
1023 index = (s->ioregsel - 0x10) >> 1;
1024 if (index >= 0 && index < IOAPIC_NUM_PINS) {
1025 if (s->ioregsel & 1)
1026 val = s->ioredtbl[index] >> 32;
1027 else
1028 val = s->ioredtbl[index] & 0xffffffff;
1029 }
1030 }
1031#ifdef DEBUG_IOAPIC
1032 printf("I/O APIC read: %08x = %08x\n", s->ioregsel, val);
1033#endif
1034 }
1035 return val;
1036}
1037
1038static void ioapic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
1039{
1040 IOAPICState *s = opaque;
1041 int index;
1042
1043 addr &= 0xff;
1044 if (addr == 0x00) {
1045 s->ioregsel = val;
1046 return;
1047 } else if (addr == 0x10) {
1048#ifdef DEBUG_IOAPIC
1049 printf("I/O APIC write: %08x = %08x\n", s->ioregsel, val);
1050#endif
1051 switch (s->ioregsel) {
1052 case 0x00:
1053 s->id = (val >> 24) & 0xff;
1054 return;
1055 case 0x01:
1056 case 0x02:
1057 return;
1058 default:
1059 index = (s->ioregsel - 0x10) >> 1;
1060 if (index >= 0 && index < IOAPIC_NUM_PINS) {
1061 if (s->ioregsel & 1) {
1062 s->ioredtbl[index] &= 0xffffffff;
1063 s->ioredtbl[index] |= (uint64_t)val << 32;
1064 } else {
1065 s->ioredtbl[index] &= ~0xffffffffULL;
1066 s->ioredtbl[index] |= val;
1067 }
1068 ioapic_service(s);
1069 }
1070 }
1071 }
1072}
1073
1074static void ioapic_save(QEMUFile *f, void *opaque)
1075{
1076 IOAPICState *s = opaque;
1077 int i;
1078
1079 qemu_put_8s(f, &s->id);
1080 qemu_put_8s(f, &s->ioregsel);
1081 for (i = 0; i < IOAPIC_NUM_PINS; i++) {
1082 qemu_put_be64s(f, &s->ioredtbl[i]);
1083 }
1084}
1085
1086static int ioapic_load(QEMUFile *f, void *opaque, int version_id)
1087{
1088 IOAPICState *s = opaque;
1089 int i;
1090
1091 if (version_id != 1)
1092 return -EINVAL;
1093
1094 qemu_get_8s(f, &s->id);
1095 qemu_get_8s(f, &s->ioregsel);
1096 for (i = 0; i < IOAPIC_NUM_PINS; i++) {
1097 qemu_get_be64s(f, &s->ioredtbl[i]);
1098 }
574bbf7b
FB
1099 return 0;
1100}
d592d303
FB
1101
1102static void ioapic_reset(void *opaque)
1103{
1104 IOAPICState *s = opaque;
1105 int i;
1106
1107 memset(s, 0, sizeof(*s));
1108 for(i = 0; i < IOAPIC_NUM_PINS; i++)
1109 s->ioredtbl[i] = 1 << 16; /* mask LVT */
1110}
1111
1112static CPUReadMemoryFunc *ioapic_mem_read[3] = {
1113 ioapic_mem_readl,
1114 ioapic_mem_readl,
1115 ioapic_mem_readl,
1116};
1117
1118static CPUWriteMemoryFunc *ioapic_mem_write[3] = {
1119 ioapic_mem_writel,
1120 ioapic_mem_writel,
1121 ioapic_mem_writel,
1122};
1123
1124IOAPICState *ioapic_init(void)
1125{
1126 IOAPICState *s;
1127 int io_memory;
1128
b1fc0348 1129 s = qemu_mallocz(sizeof(IOAPICState));
d592d303
FB
1130 if (!s)
1131 return NULL;
d592d303
FB
1132 ioapic_reset(s);
1133 s->id = last_apic_id++;
1134
5fafdf24 1135 io_memory = cpu_register_io_memory(0, ioapic_mem_read,
d592d303
FB
1136 ioapic_mem_write, s);
1137 cpu_register_physical_memory(0xfec00000, 0x1000, io_memory);
1138
1139 register_savevm("ioapic", 0, 1, ioapic_save, ioapic_load, s);
1140 qemu_register_reset(ioapic_reset, s);
3b46e624 1141
d592d303
FB
1142 return s;
1143}