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