]> Git Repo - qemu.git/blame - hw/intc/apic.c
register: Add Register API
[qemu.git] / hw / intc / 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
8167ee88 17 * License along with this library; if not, see <http://www.gnu.org/licenses/>
574bbf7b 18 */
b6a0aa05 19#include "qemu/osdep.h"
33c11879
PB
20#include "qemu-common.h"
21#include "cpu.h"
1de7afc9 22#include "qemu/thread.h"
0d09e41a
PB
23#include "hw/i386/apic_internal.h"
24#include "hw/i386/apic.h"
25#include "hw/i386/ioapic.h"
83c9f4ca 26#include "hw/pci/msi.h"
1de7afc9 27#include "qemu/host-utils.h"
d8023f31 28#include "trace.h"
0d09e41a
PB
29#include "hw/i386/pc.h"
30#include "hw/i386/apic-msidef.h"
574bbf7b 31
d3e9db93
FB
32#define MAX_APIC_WORDS 8
33
e5ad936b
JK
34#define SYNC_FROM_VAPIC 0x1
35#define SYNC_TO_VAPIC 0x2
36#define SYNC_ISR_IRR_TO_VAPIC 0x4
37
dae01685 38static APICCommonState *local_apics[MAX_APICS + 1];
73822ec8 39
dae01685
JK
40static void apic_set_irq(APICCommonState *s, int vector_num, int trigger_mode);
41static void apic_update_irq(APICCommonState *s);
610626af
AL
42static void apic_get_delivery_bitmask(uint32_t *deliver_bitmask,
43 uint8_t dest, uint8_t dest_mode);
d592d303 44
3b63c04e 45/* Find first bit starting from msb */
edf9735e 46static int apic_fls_bit(uint32_t value)
3b63c04e
AJ
47{
48 return 31 - clz32(value);
49}
50
e95f5491 51/* Find first bit starting from lsb */
edf9735e 52static int apic_ffs_bit(uint32_t value)
d3e9db93 53{
bb7e7293 54 return ctz32(value);
d3e9db93
FB
55}
56
edf9735e 57static inline void apic_reset_bit(uint32_t *tab, int index)
d3e9db93
FB
58{
59 int i, mask;
60 i = index >> 5;
61 mask = 1 << (index & 0x1f);
62 tab[i] &= ~mask;
63}
64
e5ad936b
JK
65/* return -1 if no bit is set */
66static int get_highest_priority_int(uint32_t *tab)
67{
68 int i;
69 for (i = 7; i >= 0; i--) {
70 if (tab[i] != 0) {
edf9735e 71 return i * 32 + apic_fls_bit(tab[i]);
e5ad936b
JK
72 }
73 }
74 return -1;
75}
76
77static void apic_sync_vapic(APICCommonState *s, int sync_type)
78{
79 VAPICState vapic_state;
80 size_t length;
81 off_t start;
82 int vector;
83
84 if (!s->vapic_paddr) {
85 return;
86 }
87 if (sync_type & SYNC_FROM_VAPIC) {
eb6282f2
SW
88 cpu_physical_memory_read(s->vapic_paddr, &vapic_state,
89 sizeof(vapic_state));
e5ad936b
JK
90 s->tpr = vapic_state.tpr;
91 }
92 if (sync_type & (SYNC_TO_VAPIC | SYNC_ISR_IRR_TO_VAPIC)) {
93 start = offsetof(VAPICState, isr);
94 length = offsetof(VAPICState, enabled) - offsetof(VAPICState, isr);
95
96 if (sync_type & SYNC_TO_VAPIC) {
60e82579 97 assert(qemu_cpu_is_self(CPU(s->cpu)));
e5ad936b
JK
98
99 vapic_state.tpr = s->tpr;
100 vapic_state.enabled = 1;
101 start = 0;
102 length = sizeof(VAPICState);
103 }
104
105 vector = get_highest_priority_int(s->isr);
106 if (vector < 0) {
107 vector = 0;
108 }
109 vapic_state.isr = vector & 0xf0;
110
111 vapic_state.zero = 0;
112
113 vector = get_highest_priority_int(s->irr);
114 if (vector < 0) {
115 vector = 0;
116 }
117 vapic_state.irr = vector & 0xff;
118
2a221651
EI
119 cpu_physical_memory_write_rom(&address_space_memory,
120 s->vapic_paddr + start,
e5ad936b
JK
121 ((void *)&vapic_state) + start, length);
122 }
123}
124
125static void apic_vapic_base_update(APICCommonState *s)
126{
127 apic_sync_vapic(s, SYNC_TO_VAPIC);
128}
129
dae01685 130static void apic_local_deliver(APICCommonState *s, int vector)
a5b38b51 131{
a5b38b51
AJ
132 uint32_t lvt = s->lvt[vector];
133 int trigger_mode;
134
d8023f31
BS
135 trace_apic_local_deliver(vector, (lvt >> 8) & 7);
136
a5b38b51
AJ
137 if (lvt & APIC_LVT_MASKED)
138 return;
139
140 switch ((lvt >> 8) & 7) {
141 case APIC_DM_SMI:
c3affe56 142 cpu_interrupt(CPU(s->cpu), CPU_INTERRUPT_SMI);
a5b38b51
AJ
143 break;
144
145 case APIC_DM_NMI:
c3affe56 146 cpu_interrupt(CPU(s->cpu), CPU_INTERRUPT_NMI);
a5b38b51
AJ
147 break;
148
149 case APIC_DM_EXTINT:
c3affe56 150 cpu_interrupt(CPU(s->cpu), CPU_INTERRUPT_HARD);
a5b38b51
AJ
151 break;
152
153 case APIC_DM_FIXED:
154 trigger_mode = APIC_TRIGGER_EDGE;
155 if ((vector == APIC_LVT_LINT0 || vector == APIC_LVT_LINT1) &&
156 (lvt & APIC_LVT_LEVEL_TRIGGER))
157 trigger_mode = APIC_TRIGGER_LEVEL;
158 apic_set_irq(s, lvt & 0xff, trigger_mode);
159 }
160}
161
d3b0c9e9 162void apic_deliver_pic_intr(DeviceState *dev, int level)
1a7de94a 163{
d3b0c9e9 164 APICCommonState *s = APIC_COMMON(dev);
92a16d7a 165
cf6d64bf
BS
166 if (level) {
167 apic_local_deliver(s, APIC_LVT_LINT0);
168 } else {
1a7de94a
AJ
169 uint32_t lvt = s->lvt[APIC_LVT_LINT0];
170
171 switch ((lvt >> 8) & 7) {
172 case APIC_DM_FIXED:
173 if (!(lvt & APIC_LVT_LEVEL_TRIGGER))
174 break;
edf9735e 175 apic_reset_bit(s->irr, lvt & 0xff);
1a7de94a
AJ
176 /* fall through */
177 case APIC_DM_EXTINT:
8092cb71 178 apic_update_irq(s);
1a7de94a
AJ
179 break;
180 }
181 }
182}
183
dae01685 184static void apic_external_nmi(APICCommonState *s)
02c09195 185{
02c09195
JK
186 apic_local_deliver(s, APIC_LVT_LINT1);
187}
188
d3e9db93
FB
189#define foreach_apic(apic, deliver_bitmask, code) \
190{\
6d55574a 191 int __i, __j;\
d3e9db93 192 for(__i = 0; __i < MAX_APIC_WORDS; __i++) {\
6d55574a 193 uint32_t __mask = deliver_bitmask[__i];\
d3e9db93
FB
194 if (__mask) {\
195 for(__j = 0; __j < 32; __j++) {\
6d55574a 196 if (__mask & (1U << __j)) {\
d3e9db93
FB
197 apic = local_apics[__i * 32 + __j];\
198 if (apic) {\
199 code;\
200 }\
201 }\
202 }\
203 }\
204 }\
205}
206
5fafdf24 207static void apic_bus_deliver(const uint32_t *deliver_bitmask,
1f6f408c 208 uint8_t delivery_mode, uint8_t vector_num,
d592d303
FB
209 uint8_t trigger_mode)
210{
dae01685 211 APICCommonState *apic_iter;
d592d303
FB
212
213 switch (delivery_mode) {
214 case APIC_DM_LOWPRI:
8dd69b8f 215 /* XXX: search for focus processor, arbitration */
d3e9db93
FB
216 {
217 int i, d;
218 d = -1;
219 for(i = 0; i < MAX_APIC_WORDS; i++) {
220 if (deliver_bitmask[i]) {
edf9735e 221 d = i * 32 + apic_ffs_bit(deliver_bitmask[i]);
d3e9db93
FB
222 break;
223 }
224 }
225 if (d >= 0) {
226 apic_iter = local_apics[d];
227 if (apic_iter) {
228 apic_set_irq(apic_iter, vector_num, trigger_mode);
229 }
230 }
8dd69b8f 231 }
d3e9db93 232 return;
8dd69b8f 233
d592d303 234 case APIC_DM_FIXED:
d592d303
FB
235 break;
236
237 case APIC_DM_SMI:
e2eb9d3e 238 foreach_apic(apic_iter, deliver_bitmask,
c3affe56 239 cpu_interrupt(CPU(apic_iter->cpu), CPU_INTERRUPT_SMI)
60671e58 240 );
e2eb9d3e
AJ
241 return;
242
d592d303 243 case APIC_DM_NMI:
e2eb9d3e 244 foreach_apic(apic_iter, deliver_bitmask,
c3affe56 245 cpu_interrupt(CPU(apic_iter->cpu), CPU_INTERRUPT_NMI)
60671e58 246 );
e2eb9d3e 247 return;
d592d303
FB
248
249 case APIC_DM_INIT:
250 /* normal INIT IPI sent to processors */
5fafdf24 251 foreach_apic(apic_iter, deliver_bitmask,
c3affe56 252 cpu_interrupt(CPU(apic_iter->cpu),
60671e58
AF
253 CPU_INTERRUPT_INIT)
254 );
d592d303 255 return;
3b46e624 256
d592d303 257 case APIC_DM_EXTINT:
b1fc0348 258 /* handled in I/O APIC code */
d592d303
FB
259 break;
260
261 default:
262 return;
263 }
264
5fafdf24 265 foreach_apic(apic_iter, deliver_bitmask,
d3e9db93 266 apic_set_irq(apic_iter, vector_num, trigger_mode) );
d592d303 267}
574bbf7b 268
1f6f408c
JK
269void apic_deliver_irq(uint8_t dest, uint8_t dest_mode, uint8_t delivery_mode,
270 uint8_t vector_num, uint8_t trigger_mode)
610626af
AL
271{
272 uint32_t deliver_bitmask[MAX_APIC_WORDS];
273
d8023f31 274 trace_apic_deliver_irq(dest, dest_mode, delivery_mode, vector_num,
1f6f408c 275 trigger_mode);
d8023f31 276
610626af 277 apic_get_delivery_bitmask(deliver_bitmask, dest, dest_mode);
1f6f408c 278 apic_bus_deliver(deliver_bitmask, delivery_mode, vector_num, trigger_mode);
610626af
AL
279}
280
dae01685 281static void apic_set_base(APICCommonState *s, uint64_t val)
574bbf7b 282{
5fafdf24 283 s->apicbase = (val & 0xfffff000) |
574bbf7b
FB
284 (s->apicbase & (MSR_IA32_APICBASE_BSP | MSR_IA32_APICBASE_ENABLE));
285 /* if disabled, cannot be enabled again */
286 if (!(val & MSR_IA32_APICBASE_ENABLE)) {
287 s->apicbase &= ~MSR_IA32_APICBASE_ENABLE;
60671e58 288 cpu_clear_apic_feature(&s->cpu->env);
574bbf7b
FB
289 s->spurious_vec &= ~APIC_SV_ENABLE;
290 }
291}
292
dae01685 293static void apic_set_tpr(APICCommonState *s, uint8_t val)
574bbf7b 294{
e5ad936b
JK
295 /* Updates from cr8 are ignored while the VAPIC is active */
296 if (!s->vapic_paddr) {
297 s->tpr = val << 4;
298 apic_update_irq(s);
299 }
9230e66e
FB
300}
301
e5ad936b 302static uint8_t apic_get_tpr(APICCommonState *s)
d592d303 303{
e5ad936b
JK
304 apic_sync_vapic(s, SYNC_FROM_VAPIC);
305 return s->tpr >> 4;
d592d303
FB
306}
307
82a5e042 308int apic_get_ppr(APICCommonState *s)
574bbf7b
FB
309{
310 int tpr, isrv, ppr;
311
312 tpr = (s->tpr >> 4);
313 isrv = get_highest_priority_int(s->isr);
314 if (isrv < 0)
315 isrv = 0;
316 isrv >>= 4;
317 if (tpr >= isrv)
318 ppr = s->tpr;
319 else
320 ppr = isrv << 4;
321 return ppr;
322}
323
dae01685 324static int apic_get_arb_pri(APICCommonState *s)
d592d303
FB
325{
326 /* XXX: arbitration */
327 return 0;
328}
329
0fbfbb59
GN
330
331/*
332 * <0 - low prio interrupt,
333 * 0 - no interrupt,
334 * >0 - interrupt number
335 */
dae01685 336static int apic_irq_pending(APICCommonState *s)
574bbf7b 337{
d592d303 338 int irrv, ppr;
60e68042
PB
339
340 if (!(s->spurious_vec & APIC_SV_ENABLE)) {
341 return 0;
342 }
343
574bbf7b 344 irrv = get_highest_priority_int(s->irr);
0fbfbb59
GN
345 if (irrv < 0) {
346 return 0;
347 }
d592d303 348 ppr = apic_get_ppr(s);
0fbfbb59
GN
349 if (ppr && (irrv & 0xf0) <= (ppr & 0xf0)) {
350 return -1;
351 }
352
353 return irrv;
354}
355
356/* signal the CPU if an irq is pending */
dae01685 357static void apic_update_irq(APICCommonState *s)
0fbfbb59 358{
c3affe56 359 CPUState *cpu;
be9f8a08 360 DeviceState *dev = (DeviceState *)s;
60e82579 361
c3affe56 362 cpu = CPU(s->cpu);
60e82579 363 if (!qemu_cpu_is_self(cpu)) {
c3affe56 364 cpu_interrupt(cpu, CPU_INTERRUPT_POLL);
5d62c43a 365 } else if (apic_irq_pending(s) > 0) {
c3affe56 366 cpu_interrupt(cpu, CPU_INTERRUPT_HARD);
be9f8a08 367 } else if (!apic_accept_pic_intr(dev) || !pic_get_output(isa_pic)) {
8092cb71 368 cpu_reset_interrupt(cpu, CPU_INTERRUPT_HARD);
0fbfbb59 369 }
574bbf7b
FB
370}
371
d3b0c9e9 372void apic_poll_irq(DeviceState *dev)
e5ad936b 373{
d3b0c9e9 374 APICCommonState *s = APIC_COMMON(dev);
e5ad936b
JK
375
376 apic_sync_vapic(s, SYNC_FROM_VAPIC);
377 apic_update_irq(s);
378}
379
dae01685 380static void apic_set_irq(APICCommonState *s, int vector_num, int trigger_mode)
574bbf7b 381{
edf9735e 382 apic_report_irq_delivered(!apic_get_bit(s->irr, vector_num));
73822ec8 383
edf9735e 384 apic_set_bit(s->irr, vector_num);
574bbf7b 385 if (trigger_mode)
edf9735e 386 apic_set_bit(s->tmr, vector_num);
574bbf7b 387 else
edf9735e 388 apic_reset_bit(s->tmr, vector_num);
e5ad936b
JK
389 if (s->vapic_paddr) {
390 apic_sync_vapic(s, SYNC_ISR_IRR_TO_VAPIC);
391 /*
392 * The vcpu thread needs to see the new IRR before we pull its current
393 * TPR value. That way, if we miss a lowering of the TRP, the guest
394 * has the chance to notice the new IRR and poll for IRQs on its own.
395 */
396 smp_wmb();
397 apic_sync_vapic(s, SYNC_FROM_VAPIC);
398 }
574bbf7b
FB
399 apic_update_irq(s);
400}
401
dae01685 402static void apic_eoi(APICCommonState *s)
574bbf7b
FB
403{
404 int isrv;
405 isrv = get_highest_priority_int(s->isr);
406 if (isrv < 0)
407 return;
edf9735e
MT
408 apic_reset_bit(s->isr, isrv);
409 if (!(s->spurious_vec & APIC_SV_DIRECTED_IO) && apic_get_bit(s->tmr, isrv)) {
0280b571
JK
410 ioapic_eoi_broadcast(isrv);
411 }
e5ad936b 412 apic_sync_vapic(s, SYNC_FROM_VAPIC | SYNC_TO_VAPIC);
574bbf7b
FB
413 apic_update_irq(s);
414}
415
678e12cc
GN
416static int apic_find_dest(uint8_t dest)
417{
dae01685 418 APICCommonState *apic = local_apics[dest];
678e12cc
GN
419 int i;
420
421 if (apic && apic->id == dest)
422 return dest; /* shortcut in case apic->id == apic->idx */
423
424 for (i = 0; i < MAX_APICS; i++) {
425 apic = local_apics[i];
426 if (apic && apic->id == dest)
427 return i;
b538e53e
AW
428 if (!apic)
429 break;
678e12cc
GN
430 }
431
432 return -1;
433}
434
d3e9db93
FB
435static void apic_get_delivery_bitmask(uint32_t *deliver_bitmask,
436 uint8_t dest, uint8_t dest_mode)
d592d303 437{
dae01685 438 APICCommonState *apic_iter;
d3e9db93 439 int i;
d592d303
FB
440
441 if (dest_mode == 0) {
d3e9db93
FB
442 if (dest == 0xff) {
443 memset(deliver_bitmask, 0xff, MAX_APIC_WORDS * sizeof(uint32_t));
444 } else {
678e12cc 445 int idx = apic_find_dest(dest);
d3e9db93 446 memset(deliver_bitmask, 0x00, MAX_APIC_WORDS * sizeof(uint32_t));
678e12cc 447 if (idx >= 0)
edf9735e 448 apic_set_bit(deliver_bitmask, idx);
d3e9db93 449 }
d592d303
FB
450 } else {
451 /* XXX: cluster mode */
d3e9db93
FB
452 memset(deliver_bitmask, 0x00, MAX_APIC_WORDS * sizeof(uint32_t));
453 for(i = 0; i < MAX_APICS; i++) {
454 apic_iter = local_apics[i];
455 if (apic_iter) {
456 if (apic_iter->dest_mode == 0xf) {
457 if (dest & apic_iter->log_dest)
edf9735e 458 apic_set_bit(deliver_bitmask, i);
d3e9db93
FB
459 } else if (apic_iter->dest_mode == 0x0) {
460 if ((dest & 0xf0) == (apic_iter->log_dest & 0xf0) &&
461 (dest & apic_iter->log_dest & 0x0f)) {
edf9735e 462 apic_set_bit(deliver_bitmask, i);
d3e9db93
FB
463 }
464 }
b538e53e
AW
465 } else {
466 break;
d3e9db93 467 }
d592d303
FB
468 }
469 }
d592d303
FB
470}
471
dae01685 472static void apic_startup(APICCommonState *s, int vector_num)
e0fd8781 473{
b09ea7d5 474 s->sipi_vector = vector_num;
c3affe56 475 cpu_interrupt(CPU(s->cpu), CPU_INTERRUPT_SIPI);
b09ea7d5
GN
476}
477
d3b0c9e9 478void apic_sipi(DeviceState *dev)
b09ea7d5 479{
d3b0c9e9 480 APICCommonState *s = APIC_COMMON(dev);
92a16d7a 481
d8ed887b 482 cpu_reset_interrupt(CPU(s->cpu), CPU_INTERRUPT_SIPI);
b09ea7d5
GN
483
484 if (!s->wait_for_sipi)
e0fd8781 485 return;
e9f9d6b1 486 cpu_x86_load_seg_cache_sipi(s->cpu, s->sipi_vector);
b09ea7d5 487 s->wait_for_sipi = 0;
e0fd8781
FB
488}
489
d3b0c9e9 490static void apic_deliver(DeviceState *dev, uint8_t dest, uint8_t dest_mode,
d592d303 491 uint8_t delivery_mode, uint8_t vector_num,
1f6f408c 492 uint8_t trigger_mode)
d592d303 493{
d3b0c9e9 494 APICCommonState *s = APIC_COMMON(dev);
d3e9db93 495 uint32_t deliver_bitmask[MAX_APIC_WORDS];
d592d303 496 int dest_shorthand = (s->icr[0] >> 18) & 3;
dae01685 497 APICCommonState *apic_iter;
d592d303 498
e0fd8781 499 switch (dest_shorthand) {
d3e9db93
FB
500 case 0:
501 apic_get_delivery_bitmask(deliver_bitmask, dest, dest_mode);
502 break;
503 case 1:
504 memset(deliver_bitmask, 0x00, sizeof(deliver_bitmask));
edf9735e 505 apic_set_bit(deliver_bitmask, s->idx);
d3e9db93
FB
506 break;
507 case 2:
508 memset(deliver_bitmask, 0xff, sizeof(deliver_bitmask));
509 break;
510 case 3:
511 memset(deliver_bitmask, 0xff, sizeof(deliver_bitmask));
edf9735e 512 apic_reset_bit(deliver_bitmask, s->idx);
d3e9db93 513 break;
e0fd8781
FB
514 }
515
d592d303 516 switch (delivery_mode) {
d592d303
FB
517 case APIC_DM_INIT:
518 {
519 int trig_mode = (s->icr[0] >> 15) & 1;
520 int level = (s->icr[0] >> 14) & 1;
521 if (level == 0 && trig_mode == 1) {
5fafdf24 522 foreach_apic(apic_iter, deliver_bitmask,
d3e9db93 523 apic_iter->arb_id = apic_iter->id );
d592d303
FB
524 return;
525 }
526 }
527 break;
528
529 case APIC_DM_SIPI:
5fafdf24 530 foreach_apic(apic_iter, deliver_bitmask,
d3e9db93 531 apic_startup(apic_iter, vector_num) );
d592d303
FB
532 return;
533 }
534
1f6f408c 535 apic_bus_deliver(deliver_bitmask, delivery_mode, vector_num, trigger_mode);
d592d303
FB
536}
537
a94820dd
JK
538static bool apic_check_pic(APICCommonState *s)
539{
be9f8a08
ZG
540 DeviceState *dev = (DeviceState *)s;
541
542 if (!apic_accept_pic_intr(dev) || !pic_get_output(isa_pic)) {
a94820dd
JK
543 return false;
544 }
be9f8a08 545 apic_deliver_pic_intr(dev, 1);
a94820dd
JK
546 return true;
547}
548
d3b0c9e9 549int apic_get_interrupt(DeviceState *dev)
574bbf7b 550{
d3b0c9e9 551 APICCommonState *s = APIC_COMMON(dev);
574bbf7b
FB
552 int intno;
553
554 /* if the APIC is installed or enabled, we let the 8259 handle the
555 IRQs */
556 if (!s)
557 return -1;
558 if (!(s->spurious_vec & APIC_SV_ENABLE))
559 return -1;
3b46e624 560
e5ad936b 561 apic_sync_vapic(s, SYNC_FROM_VAPIC);
0fbfbb59
GN
562 intno = apic_irq_pending(s);
563
5224c88d
PB
564 /* if there is an interrupt from the 8259, let the caller handle
565 * that first since ExtINT interrupts ignore the priority.
566 */
567 if (intno == 0 || apic_check_pic(s)) {
e5ad936b 568 apic_sync_vapic(s, SYNC_TO_VAPIC);
574bbf7b 569 return -1;
0fbfbb59 570 } else if (intno < 0) {
e5ad936b 571 apic_sync_vapic(s, SYNC_TO_VAPIC);
d592d303 572 return s->spurious_vec & 0xff;
0fbfbb59 573 }
edf9735e
MT
574 apic_reset_bit(s->irr, intno);
575 apic_set_bit(s->isr, intno);
e5ad936b 576 apic_sync_vapic(s, SYNC_TO_VAPIC);
3db3659b 577
574bbf7b 578 apic_update_irq(s);
3db3659b 579
574bbf7b
FB
580 return intno;
581}
582
d3b0c9e9 583int apic_accept_pic_intr(DeviceState *dev)
0e21e12b 584{
d3b0c9e9 585 APICCommonState *s = APIC_COMMON(dev);
0e21e12b
TS
586 uint32_t lvt0;
587
588 if (!s)
589 return -1;
590
591 lvt0 = s->lvt[APIC_LVT_LINT0];
592
a5b38b51
AJ
593 if ((s->apicbase & MSR_IA32_APICBASE_ENABLE) == 0 ||
594 (lvt0 & APIC_LVT_MASKED) == 0)
0e21e12b
TS
595 return 1;
596
597 return 0;
598}
599
dae01685 600static uint32_t apic_get_current_count(APICCommonState *s)
574bbf7b
FB
601{
602 int64_t d;
603 uint32_t val;
bc72ad67 604 d = (qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - s->initial_count_load_time) >>
574bbf7b
FB
605 s->count_shift;
606 if (s->lvt[APIC_LVT_TIMER] & APIC_LVT_TIMER_PERIODIC) {
607 /* periodic */
d592d303 608 val = s->initial_count - (d % ((uint64_t)s->initial_count + 1));
574bbf7b
FB
609 } else {
610 if (d >= s->initial_count)
611 val = 0;
612 else
613 val = s->initial_count - d;
614 }
615 return val;
616}
617
dae01685 618static void apic_timer_update(APICCommonState *s, int64_t current_time)
574bbf7b 619{
7a380ca3 620 if (apic_next_timer(s, current_time)) {
bc72ad67 621 timer_mod(s->timer, s->next_time);
574bbf7b 622 } else {
bc72ad67 623 timer_del(s->timer);
574bbf7b
FB
624 }
625}
626
627static void apic_timer(void *opaque)
628{
dae01685 629 APICCommonState *s = opaque;
574bbf7b 630
cf6d64bf 631 apic_local_deliver(s, APIC_LVT_TIMER);
574bbf7b
FB
632 apic_timer_update(s, s->next_time);
633}
634
a8170e5e 635static uint32_t apic_mem_readb(void *opaque, hwaddr addr)
574bbf7b
FB
636{
637 return 0;
638}
639
a8170e5e 640static uint32_t apic_mem_readw(void *opaque, hwaddr addr)
574bbf7b
FB
641{
642 return 0;
643}
644
a8170e5e 645static void apic_mem_writeb(void *opaque, hwaddr addr, uint32_t val)
574bbf7b
FB
646{
647}
648
a8170e5e 649static void apic_mem_writew(void *opaque, hwaddr addr, uint32_t val)
574bbf7b
FB
650{
651}
652
a8170e5e 653static uint32_t apic_mem_readl(void *opaque, hwaddr addr)
574bbf7b 654{
d3b0c9e9 655 DeviceState *dev;
dae01685 656 APICCommonState *s;
574bbf7b
FB
657 uint32_t val;
658 int index;
659
d3b0c9e9
XZ
660 dev = cpu_get_current_apic();
661 if (!dev) {
574bbf7b 662 return 0;
0e26b7b8 663 }
d3b0c9e9 664 s = APIC_COMMON(dev);
574bbf7b
FB
665
666 index = (addr >> 4) & 0xff;
667 switch(index) {
668 case 0x02: /* id */
669 val = s->id << 24;
670 break;
671 case 0x03: /* version */
aa93200b 672 val = s->version | ((APIC_LVT_NB - 1) << 16);
574bbf7b
FB
673 break;
674 case 0x08:
e5ad936b
JK
675 apic_sync_vapic(s, SYNC_FROM_VAPIC);
676 if (apic_report_tpr_access) {
60671e58 677 cpu_report_tpr_access(&s->cpu->env, TPR_ACCESS_READ);
e5ad936b 678 }
574bbf7b
FB
679 val = s->tpr;
680 break;
d592d303
FB
681 case 0x09:
682 val = apic_get_arb_pri(s);
683 break;
574bbf7b
FB
684 case 0x0a:
685 /* ppr */
686 val = apic_get_ppr(s);
687 break;
b237db36
AJ
688 case 0x0b:
689 val = 0;
690 break;
d592d303
FB
691 case 0x0d:
692 val = s->log_dest << 24;
693 break;
694 case 0x0e:
d6c140a7 695 val = (s->dest_mode << 28) | 0xfffffff;
d592d303 696 break;
574bbf7b
FB
697 case 0x0f:
698 val = s->spurious_vec;
699 break;
700 case 0x10 ... 0x17:
701 val = s->isr[index & 7];
702 break;
703 case 0x18 ... 0x1f:
704 val = s->tmr[index & 7];
705 break;
706 case 0x20 ... 0x27:
707 val = s->irr[index & 7];
708 break;
709 case 0x28:
710 val = s->esr;
711 break;
574bbf7b
FB
712 case 0x30:
713 case 0x31:
714 val = s->icr[index & 1];
715 break;
e0fd8781
FB
716 case 0x32 ... 0x37:
717 val = s->lvt[index - 0x32];
718 break;
574bbf7b
FB
719 case 0x38:
720 val = s->initial_count;
721 break;
722 case 0x39:
723 val = apic_get_current_count(s);
724 break;
725 case 0x3e:
726 val = s->divide_conf;
727 break;
728 default:
a22bf99c 729 s->esr |= APIC_ESR_ILLEGAL_ADDRESS;
574bbf7b
FB
730 val = 0;
731 break;
732 }
d8023f31 733 trace_apic_mem_readl(addr, val);
574bbf7b
FB
734 return val;
735}
736
a8170e5e 737static void apic_send_msi(hwaddr addr, uint32_t data)
54c96da7
MT
738{
739 uint8_t dest = (addr & MSI_ADDR_DEST_ID_MASK) >> MSI_ADDR_DEST_ID_SHIFT;
740 uint8_t vector = (data & MSI_DATA_VECTOR_MASK) >> MSI_DATA_VECTOR_SHIFT;
741 uint8_t dest_mode = (addr >> MSI_ADDR_DEST_MODE_SHIFT) & 0x1;
742 uint8_t trigger_mode = (data >> MSI_DATA_TRIGGER_SHIFT) & 0x1;
743 uint8_t delivery = (data >> MSI_DATA_DELIVERY_MODE_SHIFT) & 0x7;
744 /* XXX: Ignore redirection hint. */
1f6f408c 745 apic_deliver_irq(dest, dest_mode, delivery, vector, trigger_mode);
54c96da7
MT
746}
747
a8170e5e 748static void apic_mem_writel(void *opaque, hwaddr addr, uint32_t val)
574bbf7b 749{
d3b0c9e9 750 DeviceState *dev;
dae01685 751 APICCommonState *s;
54c96da7
MT
752 int index = (addr >> 4) & 0xff;
753 if (addr > 0xfff || !index) {
754 /* MSI and MMIO APIC are at the same memory location,
755 * but actually not on the global bus: MSI is on PCI bus
756 * APIC is connected directly to the CPU.
757 * Mapping them on the global bus happens to work because
758 * MSI registers are reserved in APIC MMIO and vice versa. */
759 apic_send_msi(addr, val);
760 return;
761 }
574bbf7b 762
d3b0c9e9
XZ
763 dev = cpu_get_current_apic();
764 if (!dev) {
574bbf7b 765 return;
0e26b7b8 766 }
d3b0c9e9 767 s = APIC_COMMON(dev);
574bbf7b 768
d8023f31 769 trace_apic_mem_writel(addr, val);
574bbf7b 770
574bbf7b
FB
771 switch(index) {
772 case 0x02:
773 s->id = (val >> 24);
774 break;
e0fd8781
FB
775 case 0x03:
776 break;
574bbf7b 777 case 0x08:
e5ad936b 778 if (apic_report_tpr_access) {
60671e58 779 cpu_report_tpr_access(&s->cpu->env, TPR_ACCESS_WRITE);
e5ad936b 780 }
574bbf7b 781 s->tpr = val;
e5ad936b 782 apic_sync_vapic(s, SYNC_TO_VAPIC);
d592d303 783 apic_update_irq(s);
574bbf7b 784 break;
e0fd8781
FB
785 case 0x09:
786 case 0x0a:
787 break;
574bbf7b
FB
788 case 0x0b: /* EOI */
789 apic_eoi(s);
790 break;
d592d303
FB
791 case 0x0d:
792 s->log_dest = val >> 24;
793 break;
794 case 0x0e:
795 s->dest_mode = val >> 28;
796 break;
574bbf7b
FB
797 case 0x0f:
798 s->spurious_vec = val & 0x1ff;
d592d303 799 apic_update_irq(s);
574bbf7b 800 break;
e0fd8781
FB
801 case 0x10 ... 0x17:
802 case 0x18 ... 0x1f:
803 case 0x20 ... 0x27:
804 case 0x28:
805 break;
574bbf7b 806 case 0x30:
d592d303 807 s->icr[0] = val;
d3b0c9e9 808 apic_deliver(dev, (s->icr[1] >> 24) & 0xff, (s->icr[0] >> 11) & 1,
d592d303 809 (s->icr[0] >> 8) & 7, (s->icr[0] & 0xff),
1f6f408c 810 (s->icr[0] >> 15) & 1);
d592d303 811 break;
574bbf7b 812 case 0x31:
d592d303 813 s->icr[1] = val;
574bbf7b
FB
814 break;
815 case 0x32 ... 0x37:
816 {
817 int n = index - 0x32;
818 s->lvt[n] = val;
a94820dd 819 if (n == APIC_LVT_TIMER) {
bc72ad67 820 apic_timer_update(s, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
a94820dd
JK
821 } else if (n == APIC_LVT_LINT0 && apic_check_pic(s)) {
822 apic_update_irq(s);
823 }
574bbf7b
FB
824 }
825 break;
826 case 0x38:
827 s->initial_count = val;
bc72ad67 828 s->initial_count_load_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
574bbf7b
FB
829 apic_timer_update(s, s->initial_count_load_time);
830 break;
e0fd8781
FB
831 case 0x39:
832 break;
574bbf7b
FB
833 case 0x3e:
834 {
835 int v;
836 s->divide_conf = val & 0xb;
837 v = (s->divide_conf & 3) | ((s->divide_conf >> 1) & 4);
838 s->count_shift = (v + 1) & 7;
839 }
840 break;
841 default:
a22bf99c 842 s->esr |= APIC_ESR_ILLEGAL_ADDRESS;
574bbf7b
FB
843 break;
844 }
845}
846
e5ad936b
JK
847static void apic_pre_save(APICCommonState *s)
848{
849 apic_sync_vapic(s, SYNC_FROM_VAPIC);
850}
851
7a380ca3
JK
852static void apic_post_load(APICCommonState *s)
853{
854 if (s->timer_expiry != -1) {
bc72ad67 855 timer_mod(s->timer, s->timer_expiry);
7a380ca3 856 } else {
bc72ad67 857 timer_del(s->timer);
7a380ca3
JK
858 }
859}
860
312b4234
AK
861static const MemoryRegionOps apic_io_ops = {
862 .old_mmio = {
863 .read = { apic_mem_readb, apic_mem_readw, apic_mem_readl, },
864 .write = { apic_mem_writeb, apic_mem_writew, apic_mem_writel, },
865 },
866 .endianness = DEVICE_NATIVE_ENDIAN,
574bbf7b
FB
867};
868
ff6986ce 869static void apic_realize(DeviceState *dev, Error **errp)
8546b099 870{
ff6986ce
XZ
871 APICCommonState *s = APIC_COMMON(dev);
872
1437c94b 873 memory_region_init_io(&s->io_memory, OBJECT(s), &apic_io_ops, s, "apic-msi",
baaeda08 874 APIC_SPACE_SIZE);
8546b099 875
bc72ad67 876 s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, apic_timer, s);
8546b099 877 local_apics[s->idx] = s;
08a82ac0 878
226419d6 879 msi_nonbroken = true;
8546b099
BS
880}
881
999e12bb
AL
882static void apic_class_init(ObjectClass *klass, void *data)
883{
884 APICCommonClass *k = APIC_COMMON_CLASS(klass);
885
ff6986ce 886 k->realize = apic_realize;
999e12bb
AL
887 k->set_base = apic_set_base;
888 k->set_tpr = apic_set_tpr;
e5ad936b
JK
889 k->get_tpr = apic_get_tpr;
890 k->vapic_base_update = apic_vapic_base_update;
999e12bb 891 k->external_nmi = apic_external_nmi;
e5ad936b 892 k->pre_save = apic_pre_save;
999e12bb
AL
893 k->post_load = apic_post_load;
894}
895
8c43a6f0 896static const TypeInfo apic_info = {
39bffca2
AL
897 .name = "apic",
898 .instance_size = sizeof(APICCommonState),
899 .parent = TYPE_APIC_COMMON,
900 .class_init = apic_class_init,
8546b099
BS
901};
902
83f7d43a 903static void apic_register_types(void)
8546b099 904{
39bffca2 905 type_register_static(&apic_info);
8546b099
BS
906}
907
83f7d43a 908type_init(apic_register_types)
This page took 0.854457 seconds and 4 git commands to generate.