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