Commit 610626af30fc142e3d420cbce6ac8bdb70377b50
1 parent
d154615d
From 67e94ae77f8de4d5d822917f1723cefa7ebfb64d Mon Sep 17 00:00:00 2001
From: Xiantao Zhang <xiantao.zhang@intel.com> Date: Tue, 3 Mar 2009 13:33:13 +0800 Subject: [PATCH] Split ioapic logic from the current apic. Add a new ioapic.c to hold ioapic's logic, and also make it work for ia64. Signed-off-by: Xiantao Zhang <xiantao.zhang@intel.com> --- Makefile.target | 2 +- hw/apic.c | 237 +++---------------------------------------------- hw/ioapic.c | 263 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ hw/pc.h | 5 +- 4 files changed, 281 insertions(+), 226 deletions(-) create mode 100644 hw/ioapic.c git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6827 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
4 changed files
with
279 additions
and
224 deletions
Makefile.target
| ... | ... | @@ -586,7 +586,7 @@ ifeq ($(TARGET_BASE_ARCH), i386) |
| 586 | 586 | # Hardware support |
| 587 | 587 | OBJS+= ide.o pckbd.o ps2.o vga.o $(SOUND_HW) dma.o |
| 588 | 588 | OBJS+= fdc.o mc146818rtc.o serial.o i8259.o i8254.o pcspk.o pc.o |
| 589 | -OBJS+= cirrus_vga.o apic.o parallel.o acpi.o piix_pci.o | |
| 589 | +OBJS+= cirrus_vga.o apic.o ioapic.o parallel.o acpi.o piix_pci.o | |
| 590 | 590 | OBJS+= usb-uhci.o vmmouse.o vmport.o vmware_vga.o hpet.o |
| 591 | 591 | OBJS += device-hotplug.o pci-hotplug.o |
| 592 | 592 | CPPFLAGS += -DHAS_AUDIO -DHAS_AUDIO_CHOICE | ... | ... |
hw/apic.c
| ... | ... | @@ -23,7 +23,6 @@ |
| 23 | 23 | #include "host-utils.h" |
| 24 | 24 | |
| 25 | 25 | //#define DEBUG_APIC |
| 26 | -//#define DEBUG_IOAPIC | |
| 27 | 26 | |
| 28 | 27 | /* APIC Local Vector Table */ |
| 29 | 28 | #define APIC_LVT_TIMER 0 |
| ... | ... | @@ -57,8 +56,6 @@ |
| 57 | 56 | #define APIC_INPUT_POLARITY (1<<13) |
| 58 | 57 | #define APIC_SEND_PENDING (1<<12) |
| 59 | 58 | |
| 60 | -#define IOAPIC_NUM_PINS 0x18 | |
| 61 | - | |
| 62 | 59 | #define ESR_ILLEGAL_ADDRESS (1 << 7) |
| 63 | 60 | |
| 64 | 61 | #define APIC_SV_ENABLE (1 << 8) |
| ... | ... | @@ -89,14 +86,6 @@ typedef struct APICState { |
| 89 | 86 | QEMUTimer *timer; |
| 90 | 87 | } APICState; |
| 91 | 88 | |
| 92 | -struct IOAPICState { | |
| 93 | - uint8_t id; | |
| 94 | - uint8_t ioregsel; | |
| 95 | - | |
| 96 | - uint32_t irr; | |
| 97 | - uint64_t ioredtbl[IOAPIC_NUM_PINS]; | |
| 98 | -}; | |
| 99 | - | |
| 100 | 89 | static int apic_io_memory; |
| 101 | 90 | static APICState *local_apics[MAX_APICS + 1]; |
| 102 | 91 | static int last_apic_id = 0; |
| ... | ... | @@ -106,6 +95,8 @@ static int apic_irq_delivered; |
| 106 | 95 | static void apic_init_ipi(APICState *s); |
| 107 | 96 | static void apic_set_irq(APICState *s, int vector_num, int trigger_mode); |
| 108 | 97 | static void apic_update_irq(APICState *s); |
| 98 | +static void apic_get_delivery_bitmask(uint32_t *deliver_bitmask, | |
| 99 | + uint8_t dest, uint8_t dest_mode); | |
| 109 | 100 | |
| 110 | 101 | /* Find first bit starting from msb */ |
| 111 | 102 | static int fls_bit(uint32_t value) |
| ... | ... | @@ -272,6 +263,17 @@ static void apic_bus_deliver(const uint32_t *deliver_bitmask, |
| 272 | 263 | apic_set_irq(apic_iter, vector_num, trigger_mode) ); |
| 273 | 264 | } |
| 274 | 265 | |
| 266 | +void apic_deliver_irq(uint8_t dest, uint8_t dest_mode, | |
| 267 | + uint8_t delivery_mode, uint8_t vector_num, | |
| 268 | + uint8_t polarity, uint8_t trigger_mode) | |
| 269 | +{ | |
| 270 | + uint32_t deliver_bitmask[MAX_APIC_WORDS]; | |
| 271 | + | |
| 272 | + apic_get_delivery_bitmask(deliver_bitmask, dest, dest_mode); | |
| 273 | + apic_bus_deliver(deliver_bitmask, delivery_mode, vector_num, polarity, | |
| 274 | + trigger_mode); | |
| 275 | +} | |
| 276 | + | |
| 275 | 277 | void cpu_set_apic_base(CPUState *env, uint64_t val) |
| 276 | 278 | { |
| 277 | 279 | APICState *s = env->apic_state; |
| ... | ... | @@ -923,214 +925,3 @@ int apic_init(CPUState *env) |
| 923 | 925 | return 0; |
| 924 | 926 | } |
| 925 | 927 | |
| 926 | -static void ioapic_service(IOAPICState *s) | |
| 927 | -{ | |
| 928 | - uint8_t i; | |
| 929 | - uint8_t trig_mode; | |
| 930 | - uint8_t vector; | |
| 931 | - uint8_t delivery_mode; | |
| 932 | - uint32_t mask; | |
| 933 | - uint64_t entry; | |
| 934 | - uint8_t dest; | |
| 935 | - uint8_t dest_mode; | |
| 936 | - uint8_t polarity; | |
| 937 | - uint32_t deliver_bitmask[MAX_APIC_WORDS]; | |
| 938 | - | |
| 939 | - for (i = 0; i < IOAPIC_NUM_PINS; i++) { | |
| 940 | - mask = 1 << i; | |
| 941 | - if (s->irr & mask) { | |
| 942 | - entry = s->ioredtbl[i]; | |
| 943 | - if (!(entry & APIC_LVT_MASKED)) { | |
| 944 | - trig_mode = ((entry >> 15) & 1); | |
| 945 | - dest = entry >> 56; | |
| 946 | - dest_mode = (entry >> 11) & 1; | |
| 947 | - delivery_mode = (entry >> 8) & 7; | |
| 948 | - polarity = (entry >> 13) & 1; | |
| 949 | - if (trig_mode == APIC_TRIGGER_EDGE) | |
| 950 | - s->irr &= ~mask; | |
| 951 | - if (delivery_mode == APIC_DM_EXTINT) | |
| 952 | - vector = pic_read_irq(isa_pic); | |
| 953 | - else | |
| 954 | - vector = entry & 0xff; | |
| 955 | - | |
| 956 | - apic_get_delivery_bitmask(deliver_bitmask, dest, dest_mode); | |
| 957 | - apic_bus_deliver(deliver_bitmask, delivery_mode, | |
| 958 | - vector, polarity, trig_mode); | |
| 959 | - } | |
| 960 | - } | |
| 961 | - } | |
| 962 | -} | |
| 963 | - | |
| 964 | -void ioapic_set_irq(void *opaque, int vector, int level) | |
| 965 | -{ | |
| 966 | - IOAPICState *s = opaque; | |
| 967 | - | |
| 968 | - /* ISA IRQs map to GSI 1-1 except for IRQ0 which maps | |
| 969 | - * to GSI 2. GSI maps to ioapic 1-1. This is not | |
| 970 | - * the cleanest way of doing it but it should work. */ | |
| 971 | - | |
| 972 | - if (vector == 0) | |
| 973 | - vector = 2; | |
| 974 | - | |
| 975 | - if (vector >= 0 && vector < IOAPIC_NUM_PINS) { | |
| 976 | - uint32_t mask = 1 << vector; | |
| 977 | - uint64_t entry = s->ioredtbl[vector]; | |
| 978 | - | |
| 979 | - if ((entry >> 15) & 1) { | |
| 980 | - /* level triggered */ | |
| 981 | - if (level) { | |
| 982 | - s->irr |= mask; | |
| 983 | - ioapic_service(s); | |
| 984 | - } else { | |
| 985 | - s->irr &= ~mask; | |
| 986 | - } | |
| 987 | - } else { | |
| 988 | - /* edge triggered */ | |
| 989 | - if (level) { | |
| 990 | - s->irr |= mask; | |
| 991 | - ioapic_service(s); | |
| 992 | - } | |
| 993 | - } | |
| 994 | - } | |
| 995 | -} | |
| 996 | - | |
| 997 | -static uint32_t ioapic_mem_readl(void *opaque, target_phys_addr_t addr) | |
| 998 | -{ | |
| 999 | - IOAPICState *s = opaque; | |
| 1000 | - int index; | |
| 1001 | - uint32_t val = 0; | |
| 1002 | - | |
| 1003 | - addr &= 0xff; | |
| 1004 | - if (addr == 0x00) { | |
| 1005 | - val = s->ioregsel; | |
| 1006 | - } else if (addr == 0x10) { | |
| 1007 | - switch (s->ioregsel) { | |
| 1008 | - case 0x00: | |
| 1009 | - val = s->id << 24; | |
| 1010 | - break; | |
| 1011 | - case 0x01: | |
| 1012 | - val = 0x11 | ((IOAPIC_NUM_PINS - 1) << 16); /* version 0x11 */ | |
| 1013 | - break; | |
| 1014 | - case 0x02: | |
| 1015 | - val = 0; | |
| 1016 | - break; | |
| 1017 | - default: | |
| 1018 | - index = (s->ioregsel - 0x10) >> 1; | |
| 1019 | - if (index >= 0 && index < IOAPIC_NUM_PINS) { | |
| 1020 | - if (s->ioregsel & 1) | |
| 1021 | - val = s->ioredtbl[index] >> 32; | |
| 1022 | - else | |
| 1023 | - val = s->ioredtbl[index] & 0xffffffff; | |
| 1024 | - } | |
| 1025 | - } | |
| 1026 | -#ifdef DEBUG_IOAPIC | |
| 1027 | - printf("I/O APIC read: %08x = %08x\n", s->ioregsel, val); | |
| 1028 | -#endif | |
| 1029 | - } | |
| 1030 | - return val; | |
| 1031 | -} | |
| 1032 | - | |
| 1033 | -static void ioapic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val) | |
| 1034 | -{ | |
| 1035 | - IOAPICState *s = opaque; | |
| 1036 | - int index; | |
| 1037 | - | |
| 1038 | - addr &= 0xff; | |
| 1039 | - if (addr == 0x00) { | |
| 1040 | - s->ioregsel = val; | |
| 1041 | - return; | |
| 1042 | - } else if (addr == 0x10) { | |
| 1043 | -#ifdef DEBUG_IOAPIC | |
| 1044 | - printf("I/O APIC write: %08x = %08x\n", s->ioregsel, val); | |
| 1045 | -#endif | |
| 1046 | - switch (s->ioregsel) { | |
| 1047 | - case 0x00: | |
| 1048 | - s->id = (val >> 24) & 0xff; | |
| 1049 | - return; | |
| 1050 | - case 0x01: | |
| 1051 | - case 0x02: | |
| 1052 | - return; | |
| 1053 | - default: | |
| 1054 | - index = (s->ioregsel - 0x10) >> 1; | |
| 1055 | - if (index >= 0 && index < IOAPIC_NUM_PINS) { | |
| 1056 | - if (s->ioregsel & 1) { | |
| 1057 | - s->ioredtbl[index] &= 0xffffffff; | |
| 1058 | - s->ioredtbl[index] |= (uint64_t)val << 32; | |
| 1059 | - } else { | |
| 1060 | - s->ioredtbl[index] &= ~0xffffffffULL; | |
| 1061 | - s->ioredtbl[index] |= val; | |
| 1062 | - } | |
| 1063 | - ioapic_service(s); | |
| 1064 | - } | |
| 1065 | - } | |
| 1066 | - } | |
| 1067 | -} | |
| 1068 | - | |
| 1069 | -static void ioapic_save(QEMUFile *f, void *opaque) | |
| 1070 | -{ | |
| 1071 | - IOAPICState *s = opaque; | |
| 1072 | - int i; | |
| 1073 | - | |
| 1074 | - qemu_put_8s(f, &s->id); | |
| 1075 | - qemu_put_8s(f, &s->ioregsel); | |
| 1076 | - for (i = 0; i < IOAPIC_NUM_PINS; i++) { | |
| 1077 | - qemu_put_be64s(f, &s->ioredtbl[i]); | |
| 1078 | - } | |
| 1079 | -} | |
| 1080 | - | |
| 1081 | -static int ioapic_load(QEMUFile *f, void *opaque, int version_id) | |
| 1082 | -{ | |
| 1083 | - IOAPICState *s = opaque; | |
| 1084 | - int i; | |
| 1085 | - | |
| 1086 | - if (version_id != 1) | |
| 1087 | - return -EINVAL; | |
| 1088 | - | |
| 1089 | - qemu_get_8s(f, &s->id); | |
| 1090 | - qemu_get_8s(f, &s->ioregsel); | |
| 1091 | - for (i = 0; i < IOAPIC_NUM_PINS; i++) { | |
| 1092 | - qemu_get_be64s(f, &s->ioredtbl[i]); | |
| 1093 | - } | |
| 1094 | - return 0; | |
| 1095 | -} | |
| 1096 | - | |
| 1097 | -static void ioapic_reset(void *opaque) | |
| 1098 | -{ | |
| 1099 | - IOAPICState *s = opaque; | |
| 1100 | - int i; | |
| 1101 | - | |
| 1102 | - memset(s, 0, sizeof(*s)); | |
| 1103 | - for(i = 0; i < IOAPIC_NUM_PINS; i++) | |
| 1104 | - s->ioredtbl[i] = 1 << 16; /* mask LVT */ | |
| 1105 | -} | |
| 1106 | - | |
| 1107 | -static CPUReadMemoryFunc *ioapic_mem_read[3] = { | |
| 1108 | - ioapic_mem_readl, | |
| 1109 | - ioapic_mem_readl, | |
| 1110 | - ioapic_mem_readl, | |
| 1111 | -}; | |
| 1112 | - | |
| 1113 | -static CPUWriteMemoryFunc *ioapic_mem_write[3] = { | |
| 1114 | - ioapic_mem_writel, | |
| 1115 | - ioapic_mem_writel, | |
| 1116 | - ioapic_mem_writel, | |
| 1117 | -}; | |
| 1118 | - | |
| 1119 | -IOAPICState *ioapic_init(void) | |
| 1120 | -{ | |
| 1121 | - IOAPICState *s; | |
| 1122 | - int io_memory; | |
| 1123 | - | |
| 1124 | - s = qemu_mallocz(sizeof(IOAPICState)); | |
| 1125 | - ioapic_reset(s); | |
| 1126 | - s->id = last_apic_id++; | |
| 1127 | - | |
| 1128 | - io_memory = cpu_register_io_memory(0, ioapic_mem_read, | |
| 1129 | - ioapic_mem_write, s); | |
| 1130 | - cpu_register_physical_memory(0xfec00000, 0x1000, io_memory); | |
| 1131 | - | |
| 1132 | - register_savevm("ioapic", 0, 1, ioapic_save, ioapic_load, s); | |
| 1133 | - qemu_register_reset(ioapic_reset, s); | |
| 1134 | - | |
| 1135 | - return s; | |
| 1136 | -} | ... | ... |
hw/ioapic.c
0 โ 100644
| 1 | +/* | |
| 2 | + * ioapic.c IOAPIC emulation logic | |
| 3 | + * | |
| 4 | + * Copyright (c) 2004-2005 Fabrice Bellard | |
| 5 | + * | |
| 6 | + * Split the ioapic logic from apic.c | |
| 7 | + * Xiantao Zhang <xiantao.zhang@intel.com> | |
| 8 | + * | |
| 9 | + * This library is free software; you can redistribute it and/or | |
| 10 | + * modify it under the terms of the GNU Lesser General Public | |
| 11 | + * License as published by the Free Software Foundation; either | |
| 12 | + * version 2 of the License, or (at your option) any later version. | |
| 13 | + * | |
| 14 | + * This library is distributed in the hope that it will be useful, | |
| 15 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 16 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 17 | + * Lesser General Public License for more details. | |
| 18 | + * | |
| 19 | + * You should have received a copy of the GNU Lesser General Public | |
| 20 | + * License along with this library; if not, write to the Free Software | |
| 21 | + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA | |
| 22 | + */ | |
| 23 | + | |
| 24 | +#include "hw.h" | |
| 25 | +#include "pc.h" | |
| 26 | +#include "qemu-timer.h" | |
| 27 | +#include "host-utils.h" | |
| 28 | + | |
| 29 | +//#define DEBUG_IOAPIC | |
| 30 | + | |
| 31 | +#define IOAPIC_NUM_PINS 0x18 | |
| 32 | +#define IOAPIC_LVT_MASKED (1<<16) | |
| 33 | + | |
| 34 | +#define IOAPIC_TRIGGER_EDGE 0 | |
| 35 | +#define IOAPIC_TRIGGER_LEVEL 1 | |
| 36 | + | |
| 37 | +/*io{apic,sapic} delivery mode*/ | |
| 38 | +#define IOAPIC_DM_FIXED 0x0 | |
| 39 | +#define IOAPIC_DM_LOWEST_PRIORITY 0x1 | |
| 40 | +#define IOAPIC_DM_PMI 0x2 | |
| 41 | +#define IOAPIC_DM_NMI 0x4 | |
| 42 | +#define IOAPIC_DM_INIT 0x5 | |
| 43 | +#define IOAPIC_DM_SIPI 0x5 | |
| 44 | +#define IOAPIC_DM_EXTINT 0x7 | |
| 45 | + | |
| 46 | +struct IOAPICState { | |
| 47 | + uint8_t id; | |
| 48 | + uint8_t ioregsel; | |
| 49 | + | |
| 50 | + uint32_t irr; | |
| 51 | + uint64_t ioredtbl[IOAPIC_NUM_PINS]; | |
| 52 | +}; | |
| 53 | + | |
| 54 | +static void ioapic_service(IOAPICState *s) | |
| 55 | +{ | |
| 56 | + uint8_t i; | |
| 57 | + uint8_t trig_mode; | |
| 58 | + uint8_t vector; | |
| 59 | + uint8_t delivery_mode; | |
| 60 | + uint32_t mask; | |
| 61 | + uint64_t entry; | |
| 62 | + uint8_t dest; | |
| 63 | + uint8_t dest_mode; | |
| 64 | + uint8_t polarity; | |
| 65 | + | |
| 66 | + for (i = 0; i < IOAPIC_NUM_PINS; i++) { | |
| 67 | + mask = 1 << i; | |
| 68 | + if (s->irr & mask) { | |
| 69 | + entry = s->ioredtbl[i]; | |
| 70 | + if (!(entry & IOAPIC_LVT_MASKED)) { | |
| 71 | + trig_mode = ((entry >> 15) & 1); | |
| 72 | + dest = entry >> 56; | |
| 73 | + dest_mode = (entry >> 11) & 1; | |
| 74 | + delivery_mode = (entry >> 8) & 7; | |
| 75 | + polarity = (entry >> 13) & 1; | |
| 76 | + if (trig_mode == IOAPIC_TRIGGER_EDGE) | |
| 77 | + s->irr &= ~mask; | |
| 78 | + if (delivery_mode == IOAPIC_DM_EXTINT) | |
| 79 | + vector = pic_read_irq(isa_pic); | |
| 80 | + else | |
| 81 | + vector = entry & 0xff; | |
| 82 | + | |
| 83 | + apic_deliver_irq(dest, dest_mode, delivery_mode, | |
| 84 | + vector, polarity, trig_mode); | |
| 85 | + } | |
| 86 | + } | |
| 87 | + } | |
| 88 | +} | |
| 89 | + | |
| 90 | +void ioapic_set_irq(void *opaque, int vector, int level) | |
| 91 | +{ | |
| 92 | + IOAPICState *s = opaque; | |
| 93 | + | |
| 94 | + /* ISA IRQs map to GSI 1-1 except for IRQ0 which maps | |
| 95 | + * to GSI 2. GSI maps to ioapic 1-1. This is not | |
| 96 | + * the cleanest way of doing it but it should work. */ | |
| 97 | + | |
| 98 | + if (vector == 0) | |
| 99 | + vector = 2; | |
| 100 | + | |
| 101 | + if (vector >= 0 && vector < IOAPIC_NUM_PINS) { | |
| 102 | + uint32_t mask = 1 << vector; | |
| 103 | + uint64_t entry = s->ioredtbl[vector]; | |
| 104 | + | |
| 105 | + if ((entry >> 15) & 1) { | |
| 106 | + /* level triggered */ | |
| 107 | + if (level) { | |
| 108 | + s->irr |= mask; | |
| 109 | + ioapic_service(s); | |
| 110 | + } else { | |
| 111 | + s->irr &= ~mask; | |
| 112 | + } | |
| 113 | + } else { | |
| 114 | + /* edge triggered */ | |
| 115 | + if (level) { | |
| 116 | + s->irr |= mask; | |
| 117 | + ioapic_service(s); | |
| 118 | + } | |
| 119 | + } | |
| 120 | + } | |
| 121 | +} | |
| 122 | + | |
| 123 | +static uint32_t ioapic_mem_readl(void *opaque, target_phys_addr_t addr) | |
| 124 | +{ | |
| 125 | + IOAPICState *s = opaque; | |
| 126 | + int index; | |
| 127 | + uint32_t val = 0; | |
| 128 | + | |
| 129 | + addr &= 0xff; | |
| 130 | + if (addr == 0x00) { | |
| 131 | + val = s->ioregsel; | |
| 132 | + } else if (addr == 0x10) { | |
| 133 | + switch (s->ioregsel) { | |
| 134 | + case 0x00: | |
| 135 | + val = s->id << 24; | |
| 136 | + break; | |
| 137 | + case 0x01: | |
| 138 | + val = 0x11 | ((IOAPIC_NUM_PINS - 1) << 16); /* version 0x11 */ | |
| 139 | + break; | |
| 140 | + case 0x02: | |
| 141 | + val = 0; | |
| 142 | + break; | |
| 143 | + default: | |
| 144 | + index = (s->ioregsel - 0x10) >> 1; | |
| 145 | + if (index >= 0 && index < IOAPIC_NUM_PINS) { | |
| 146 | + if (s->ioregsel & 1) | |
| 147 | + val = s->ioredtbl[index] >> 32; | |
| 148 | + else | |
| 149 | + val = s->ioredtbl[index] & 0xffffffff; | |
| 150 | + } | |
| 151 | + } | |
| 152 | +#ifdef DEBUG_IOAPIC | |
| 153 | + printf("I/O APIC read: %08x = %08x\n", s->ioregsel, val); | |
| 154 | +#endif | |
| 155 | + } | |
| 156 | + return val; | |
| 157 | +} | |
| 158 | + | |
| 159 | +static void ioapic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val) | |
| 160 | +{ | |
| 161 | + IOAPICState *s = opaque; | |
| 162 | + int index; | |
| 163 | + | |
| 164 | + addr &= 0xff; | |
| 165 | + if (addr == 0x00) { | |
| 166 | + s->ioregsel = val; | |
| 167 | + return; | |
| 168 | + } else if (addr == 0x10) { | |
| 169 | +#ifdef DEBUG_IOAPIC | |
| 170 | + printf("I/O APIC write: %08x = %08x\n", s->ioregsel, val); | |
| 171 | +#endif | |
| 172 | + switch (s->ioregsel) { | |
| 173 | + case 0x00: | |
| 174 | + s->id = (val >> 24) & 0xff; | |
| 175 | + return; | |
| 176 | + case 0x01: | |
| 177 | + case 0x02: | |
| 178 | + return; | |
| 179 | + default: | |
| 180 | + index = (s->ioregsel - 0x10) >> 1; | |
| 181 | + if (index >= 0 && index < IOAPIC_NUM_PINS) { | |
| 182 | + if (s->ioregsel & 1) { | |
| 183 | + s->ioredtbl[index] &= 0xffffffff; | |
| 184 | + s->ioredtbl[index] |= (uint64_t)val << 32; | |
| 185 | + } else { | |
| 186 | + s->ioredtbl[index] &= ~0xffffffffULL; | |
| 187 | + s->ioredtbl[index] |= val; | |
| 188 | + } | |
| 189 | + ioapic_service(s); | |
| 190 | + } | |
| 191 | + } | |
| 192 | + } | |
| 193 | +} | |
| 194 | + | |
| 195 | +static void ioapic_save(QEMUFile *f, void *opaque) | |
| 196 | +{ | |
| 197 | + IOAPICState *s = opaque; | |
| 198 | + int i; | |
| 199 | + | |
| 200 | + qemu_put_8s(f, &s->id); | |
| 201 | + qemu_put_8s(f, &s->ioregsel); | |
| 202 | + for (i = 0; i < IOAPIC_NUM_PINS; i++) { | |
| 203 | + qemu_put_be64s(f, &s->ioredtbl[i]); | |
| 204 | + } | |
| 205 | +} | |
| 206 | + | |
| 207 | +static int ioapic_load(QEMUFile *f, void *opaque, int version_id) | |
| 208 | +{ | |
| 209 | + IOAPICState *s = opaque; | |
| 210 | + int i; | |
| 211 | + | |
| 212 | + if (version_id != 1) | |
| 213 | + return -EINVAL; | |
| 214 | + | |
| 215 | + qemu_get_8s(f, &s->id); | |
| 216 | + qemu_get_8s(f, &s->ioregsel); | |
| 217 | + for (i = 0; i < IOAPIC_NUM_PINS; i++) { | |
| 218 | + qemu_get_be64s(f, &s->ioredtbl[i]); | |
| 219 | + } | |
| 220 | + return 0; | |
| 221 | +} | |
| 222 | + | |
| 223 | +static void ioapic_reset(void *opaque) | |
| 224 | +{ | |
| 225 | + IOAPICState *s = opaque; | |
| 226 | + int i; | |
| 227 | + | |
| 228 | + memset(s, 0, sizeof(*s)); | |
| 229 | + for(i = 0; i < IOAPIC_NUM_PINS; i++) | |
| 230 | + s->ioredtbl[i] = 1 << 16; /* mask LVT */ | |
| 231 | +} | |
| 232 | + | |
| 233 | +static CPUReadMemoryFunc *ioapic_mem_read[3] = { | |
| 234 | + ioapic_mem_readl, | |
| 235 | + ioapic_mem_readl, | |
| 236 | + ioapic_mem_readl, | |
| 237 | +}; | |
| 238 | + | |
| 239 | +static CPUWriteMemoryFunc *ioapic_mem_write[3] = { | |
| 240 | + ioapic_mem_writel, | |
| 241 | + ioapic_mem_writel, | |
| 242 | + ioapic_mem_writel, | |
| 243 | +}; | |
| 244 | + | |
| 245 | +IOAPICState *ioapic_init(void) | |
| 246 | +{ | |
| 247 | + IOAPICState *s; | |
| 248 | + int io_memory; | |
| 249 | + | |
| 250 | + s = qemu_mallocz(sizeof(IOAPICState)); | |
| 251 | + ioapic_reset(s); | |
| 252 | + | |
| 253 | + io_memory = cpu_register_io_memory(0, ioapic_mem_read, | |
| 254 | + ioapic_mem_write, s); | |
| 255 | + cpu_register_physical_memory(0xfec00000, 0x1000, io_memory); | |
| 256 | + | |
| 257 | + register_savevm("ioapic", 0, 1, ioapic_save, ioapic_load, s); | |
| 258 | + qemu_register_reset(ioapic_reset, s); | |
| 259 | + | |
| 260 | + return s; | |
| 261 | +} | ... | ... |
hw/pc.h
| ... | ... | @@ -42,7 +42,10 @@ void irq_info(Monitor *mon); |
| 42 | 42 | |
| 43 | 43 | /* APIC */ |
| 44 | 44 | typedef struct IOAPICState IOAPICState; |
| 45 | - | |
| 45 | +void apic_deliver_irq(uint8_t dest, uint8_t dest_mode, | |
| 46 | + uint8_t delivery_mode, | |
| 47 | + uint8_t vector_num, uint8_t polarity, | |
| 48 | + uint8_t trigger_mode); | |
| 46 | 49 | int apic_init(CPUState *env); |
| 47 | 50 | int apic_accept_pic_intr(CPUState *env); |
| 48 | 51 | void apic_deliver_pic_intr(CPUState *env, int level); | ... | ... |