Revision 92a16d7a hw/apic.c
b/hw/apic.c | ||
---|---|---|
18 | 18 |
*/ |
19 | 19 |
#include "hw.h" |
20 | 20 |
#include "apic.h" |
21 |
#include "msix.h" |
|
22 | 21 |
#include "qemu-timer.h" |
23 | 22 |
#include "host-utils.h" |
24 | 23 |
#include "sysbus.h" |
... | ... | |
89 | 88 |
#define MSI_ADDR_DEST_ID_SHIFT 12 |
90 | 89 |
#define MSI_ADDR_DEST_ID_MASK 0x00ffff0 |
91 | 90 |
|
92 |
#define MSI_ADDR_BASE 0xfee00000 |
|
93 | 91 |
#define MSI_ADDR_SIZE 0x100000 |
94 | 92 |
|
93 |
typedef struct APICState APICState; |
|
94 |
|
|
95 | 95 |
struct APICState { |
96 | 96 |
SysBusDevice busdev; |
97 | 97 |
void *cpu_env; |
... | ... | |
195 | 195 |
} |
196 | 196 |
} |
197 | 197 |
|
198 |
void apic_deliver_pic_intr(APICState *s, int level)
|
|
198 |
void apic_deliver_pic_intr(DeviceState *d, int level)
|
|
199 | 199 |
{ |
200 |
APICState *s = DO_UPCAST(APICState, busdev.qdev, d); |
|
201 |
|
|
200 | 202 |
if (level) { |
201 | 203 |
apic_local_deliver(s, APIC_LVT_LINT0); |
202 | 204 |
} else { |
... | ... | |
306 | 308 |
trigger_mode); |
307 | 309 |
} |
308 | 310 |
|
309 |
void cpu_set_apic_base(APICState *s, uint64_t val)
|
|
311 |
void cpu_set_apic_base(DeviceState *d, uint64_t val)
|
|
310 | 312 |
{ |
313 |
APICState *s = DO_UPCAST(APICState, busdev.qdev, d); |
|
314 |
|
|
311 | 315 |
DPRINTF("cpu_set_apic_base: %016" PRIx64 "\n", val); |
312 | 316 |
if (!s) |
313 | 317 |
return; |
... | ... | |
321 | 325 |
} |
322 | 326 |
} |
323 | 327 |
|
324 |
uint64_t cpu_get_apic_base(APICState *s)
|
|
328 |
uint64_t cpu_get_apic_base(DeviceState *d)
|
|
325 | 329 |
{ |
330 |
APICState *s = DO_UPCAST(APICState, busdev.qdev, d); |
|
331 |
|
|
326 | 332 |
DPRINTF("cpu_get_apic_base: %016" PRIx64 "\n", |
327 | 333 |
s ? (uint64_t)s->apicbase: 0); |
328 | 334 |
return s ? s->apicbase : 0; |
329 | 335 |
} |
330 | 336 |
|
331 |
void cpu_set_apic_tpr(APICState *s, uint8_t val)
|
|
337 |
void cpu_set_apic_tpr(DeviceState *d, uint8_t val)
|
|
332 | 338 |
{ |
339 |
APICState *s = DO_UPCAST(APICState, busdev.qdev, d); |
|
340 |
|
|
333 | 341 |
if (!s) |
334 | 342 |
return; |
335 | 343 |
s->tpr = (val & 0x0f) << 4; |
336 | 344 |
apic_update_irq(s); |
337 | 345 |
} |
338 | 346 |
|
339 |
uint8_t cpu_get_apic_tpr(APICState *s)
|
|
347 |
uint8_t cpu_get_apic_tpr(DeviceState *d)
|
|
340 | 348 |
{ |
349 |
APICState *s = DO_UPCAST(APICState, busdev.qdev, d); |
|
350 |
|
|
341 | 351 |
return s ? s->tpr >> 4 : 0; |
342 | 352 |
} |
343 | 353 |
|
... | ... | |
479 | 489 |
} |
480 | 490 |
} |
481 | 491 |
|
482 |
|
|
483 |
void apic_init_reset(APICState *s) |
|
492 |
void apic_init_reset(DeviceState *d) |
|
484 | 493 |
{ |
494 |
APICState *s = DO_UPCAST(APICState, busdev.qdev, d); |
|
485 | 495 |
int i; |
486 | 496 |
|
487 | 497 |
if (!s) |
... | ... | |
512 | 522 |
cpu_interrupt(s->cpu_env, CPU_INTERRUPT_SIPI); |
513 | 523 |
} |
514 | 524 |
|
515 |
void apic_sipi(APICState *s)
|
|
525 |
void apic_sipi(DeviceState *d)
|
|
516 | 526 |
{ |
527 |
APICState *s = DO_UPCAST(APICState, busdev.qdev, d); |
|
528 |
|
|
517 | 529 |
cpu_reset_interrupt(s->cpu_env, CPU_INTERRUPT_SIPI); |
518 | 530 |
|
519 | 531 |
if (!s->wait_for_sipi) |
... | ... | |
522 | 534 |
s->wait_for_sipi = 0; |
523 | 535 |
} |
524 | 536 |
|
525 |
static void apic_deliver(APICState *s, uint8_t dest, uint8_t dest_mode,
|
|
537 |
static void apic_deliver(DeviceState *d, uint8_t dest, uint8_t dest_mode,
|
|
526 | 538 |
uint8_t delivery_mode, uint8_t vector_num, |
527 | 539 |
uint8_t polarity, uint8_t trigger_mode) |
528 | 540 |
{ |
541 |
APICState *s = DO_UPCAST(APICState, busdev.qdev, d); |
|
529 | 542 |
uint32_t deliver_bitmask[MAX_APIC_WORDS]; |
530 | 543 |
int dest_shorthand = (s->icr[0] >> 18) & 3; |
531 | 544 |
APICState *apic_iter; |
... | ... | |
570 | 583 |
trigger_mode); |
571 | 584 |
} |
572 | 585 |
|
573 |
int apic_get_interrupt(APICState *s)
|
|
586 |
int apic_get_interrupt(DeviceState *d)
|
|
574 | 587 |
{ |
588 |
APICState *s = DO_UPCAST(APICState, busdev.qdev, d); |
|
575 | 589 |
int intno; |
576 | 590 |
|
577 | 591 |
/* if the APIC is installed or enabled, we let the 8259 handle the |
... | ... | |
593 | 607 |
return intno; |
594 | 608 |
} |
595 | 609 |
|
596 |
int apic_accept_pic_intr(APICState *s)
|
|
610 |
int apic_accept_pic_intr(DeviceState *d)
|
|
597 | 611 |
{ |
612 |
APICState *s = DO_UPCAST(APICState, busdev.qdev, d); |
|
598 | 613 |
uint32_t lvt0; |
599 | 614 |
|
600 | 615 |
if (!s) |
... | ... | |
680 | 695 |
|
681 | 696 |
static uint32_t apic_mem_readl(void *opaque, target_phys_addr_t addr) |
682 | 697 |
{ |
698 |
DeviceState *d; |
|
683 | 699 |
APICState *s; |
684 | 700 |
uint32_t val; |
685 | 701 |
int index; |
686 | 702 |
|
687 |
s = cpu_get_current_apic();
|
|
688 |
if (!s) {
|
|
703 |
d = cpu_get_current_apic();
|
|
704 |
if (!d) {
|
|
689 | 705 |
return 0; |
690 | 706 |
} |
707 |
s = DO_UPCAST(APICState, busdev.qdev, d); |
|
691 | 708 |
|
692 | 709 |
index = (addr >> 4) & 0xff; |
693 | 710 |
switch(index) { |
... | ... | |
769 | 786 |
|
770 | 787 |
static void apic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val) |
771 | 788 |
{ |
789 |
DeviceState *d; |
|
772 | 790 |
APICState *s; |
773 | 791 |
int index = (addr >> 4) & 0xff; |
774 | 792 |
if (addr > 0xfff || !index) { |
... | ... | |
781 | 799 |
return; |
782 | 800 |
} |
783 | 801 |
|
784 |
s = cpu_get_current_apic();
|
|
785 |
if (!s) {
|
|
802 |
d = cpu_get_current_apic();
|
|
803 |
if (!d) {
|
|
786 | 804 |
return; |
787 | 805 |
} |
806 |
s = DO_UPCAST(APICState, busdev.qdev, d); |
|
788 | 807 |
|
789 | 808 |
DPRINTF("write: " TARGET_FMT_plx " = %08x\n", addr, val); |
790 | 809 |
|
... | ... | |
821 | 840 |
break; |
822 | 841 |
case 0x30: |
823 | 842 |
s->icr[0] = val; |
824 |
apic_deliver(s, (s->icr[1] >> 24) & 0xff, (s->icr[0] >> 11) & 1,
|
|
843 |
apic_deliver(d, (s->icr[1] >> 24) & 0xff, (s->icr[0] >> 11) & 1,
|
|
825 | 844 |
(s->icr[0] >> 8) & 7, (s->icr[0] & 0xff), |
826 | 845 |
(s->icr[0] >> 14) & 1, (s->icr[0] >> 15) & 1); |
827 | 846 |
break; |
... | ... | |
935 | 954 |
s->apicbase = 0xfee00000 | |
936 | 955 |
(bsp ? MSR_IA32_APICBASE_BSP : 0) | MSR_IA32_APICBASE_ENABLE; |
937 | 956 |
|
938 |
apic_init_reset(s);
|
|
957 |
apic_init_reset(d);
|
|
939 | 958 |
|
940 | 959 |
if (bsp) { |
941 | 960 |
/* |
... | ... | |
959 | 978 |
apic_mem_writel, |
960 | 979 |
}; |
961 | 980 |
|
962 |
APICState *apic_init(void *env, uint8_t apic_id) |
|
963 |
{ |
|
964 |
DeviceState *dev; |
|
965 |
SysBusDevice *d; |
|
966 |
APICState *s; |
|
967 |
static int apic_mapped; |
|
968 |
|
|
969 |
dev = qdev_create(NULL, "apic"); |
|
970 |
qdev_prop_set_uint8(dev, "id", apic_id); |
|
971 |
qdev_prop_set_ptr(dev, "cpu_env", env); |
|
972 |
qdev_init_nofail(dev); |
|
973 |
d = sysbus_from_qdev(dev); |
|
974 |
|
|
975 |
/* XXX: mapping more APICs at the same memory location */ |
|
976 |
if (apic_mapped == 0) { |
|
977 |
/* NOTE: the APIC is directly connected to the CPU - it is not |
|
978 |
on the global memory bus. */ |
|
979 |
/* XXX: what if the base changes? */ |
|
980 |
sysbus_mmio_map(d, 0, MSI_ADDR_BASE); |
|
981 |
apic_mapped = 1; |
|
982 |
} |
|
983 |
|
|
984 |
msix_supported = 1; |
|
985 |
|
|
986 |
s = DO_UPCAST(APICState, busdev.qdev, dev); |
|
987 |
|
|
988 |
return s; |
|
989 |
} |
|
990 |
|
|
991 | 981 |
static int apic_init1(SysBusDevice *dev) |
992 | 982 |
{ |
993 | 983 |
APICState *s = FROM_SYSBUS(APICState, dev); |
Also available in: Unified diff