~jderose/ubuntu/raring/qemu/vde-again

« back to all changes in this revision

Viewing changes to hw/apic.c

  • Committer: Bazaar Package Importer
  • Author(s): Riku Voipio, Josh Triplett, Riku Voipio
  • Date: 2009-07-29 13:28:05 UTC
  • mfrom: (1.4.1 upstream)
  • mto: (12.1.1 sid) (10.1.13 sid)
  • mto: This revision was merged to the branch mainline in revision 13.
  • Revision ID: james.westby@ubuntu.com-20090729132805-cau7rfexh7dawyb8
Tags: 0.10.50+git20090729-1
[ Josh Triplett ]
* Remove myself from Uploaders.

[ Riku Voipio ]
* new upstream RC version
* nuke all linux-user patches (applied upstream)
  06_exit_segfault
  12_signal_powerpc_support
  21_net_soopts
  30_syscall_ipc
  32_syscall_sysctl
  35_syscall_sockaddr
  48_signal_terminate
  55_unmux_socketcall
* nuke all other applied-upstream patches
  01_nostrip (better version upstream)
  07_i386_exec_name (can be reintroduced in debian/rules)
  50_linuxbios_isa_bios_ram (shouldn't be needed anymore)
  51_linuxbios_piix_ram_size (applied)
  56_dhcp (crap)
  60_ppc_ld (reintroduce if needed)
  64_ppc_asm_constraints (ditto)
  66_tls_ld.patch (ditto)
  81_compile_dtb.patch (applied upstream)
  82_qemu-img_decimal (ditto)
* move to git
* simplify build rules
* Correct my email address

Show diffs side-by-side

added added

removed removed

Lines of Context:
14
14
 * Lesser General Public License for more details.
15
15
 *
16
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., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
 
17
 * License along with this library; if not, see <http://www.gnu.org/licenses/>
19
18
 */
20
19
#include "hw.h"
21
20
#include "pc.h"
 
21
#include "pci.h"
 
22
#include "msix.h"
22
23
#include "qemu-timer.h"
23
24
#include "host-utils.h"
 
25
#include "kvm.h"
24
26
 
25
27
//#define DEBUG_APIC
26
 
//#define DEBUG_IOAPIC
27
28
 
28
29
/* APIC Local Vector Table */
29
30
#define APIC_LVT_TIMER   0
57
58
#define APIC_INPUT_POLARITY             (1<<13)
58
59
#define APIC_SEND_PENDING               (1<<12)
59
60
 
60
 
#define IOAPIC_NUM_PINS                 0x18
61
 
 
62
61
#define ESR_ILLEGAL_ADDRESS (1 << 7)
63
62
 
64
63
#define APIC_SV_ENABLE (1 << 8)
66
65
#define MAX_APICS 255
67
66
#define MAX_APIC_WORDS 8
68
67
 
 
68
/* Intel APIC constants: from include/asm/msidef.h */
 
69
#define MSI_DATA_VECTOR_SHIFT           0
 
70
#define MSI_DATA_VECTOR_MASK            0x000000ff
 
71
#define MSI_DATA_DELIVERY_MODE_SHIFT    8
 
72
#define MSI_DATA_TRIGGER_SHIFT          15
 
73
#define MSI_DATA_LEVEL_SHIFT            14
 
74
#define MSI_ADDR_DEST_MODE_SHIFT        2
 
75
#define MSI_ADDR_DEST_ID_SHIFT          12
 
76
#define MSI_ADDR_DEST_ID_MASK           0x00ffff0
 
77
 
 
78
#define MSI_ADDR_BASE                   0xfee00000
 
79
#define MSI_ADDR_SIZE                   0x100000
 
80
 
69
81
typedef struct APICState {
70
82
    CPUState *cpu_env;
71
83
    uint32_t apicbase;
86
98
    int count_shift;
87
99
    uint32_t initial_count;
88
100
    int64_t initial_count_load_time, next_time;
 
101
    uint32_t idx;
89
102
    QEMUTimer *timer;
 
103
    int sipi_vector;
 
104
    int wait_for_sipi;
90
105
} APICState;
91
106
 
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
107
static int apic_io_memory;
101
108
static APICState *local_apics[MAX_APICS + 1];
102
 
static int last_apic_id = 0;
 
109
static int last_apic_idx = 0;
103
110
static int apic_irq_delivered;
104
111
 
105
112
 
106
 
static void apic_init_ipi(APICState *s);
107
113
static void apic_set_irq(APICState *s, int vector_num, int trigger_mode);
108
114
static void apic_update_irq(APICState *s);
 
115
static void apic_get_delivery_bitmask(uint32_t *deliver_bitmask,
 
116
                                      uint8_t dest, uint8_t dest_mode);
109
117
 
110
118
/* Find first bit starting from msb */
111
119
static int fls_bit(uint32_t value)
257
265
        case APIC_DM_INIT:
258
266
            /* normal INIT IPI sent to processors */
259
267
            foreach_apic(apic_iter, deliver_bitmask,
260
 
                         apic_init_ipi(apic_iter) );
 
268
                         cpu_interrupt(apic_iter->cpu_env, CPU_INTERRUPT_INIT) );
261
269
            return;
262
270
 
263
271
        case APIC_DM_EXTINT:
272
280
                 apic_set_irq(apic_iter, vector_num, trigger_mode) );
273
281
}
274
282
 
 
283
void apic_deliver_irq(uint8_t dest, uint8_t dest_mode,
 
284
                      uint8_t delivery_mode, uint8_t vector_num,
 
285
                      uint8_t polarity, uint8_t trigger_mode)
 
286
{
 
287
    uint32_t deliver_bitmask[MAX_APIC_WORDS];
 
288
 
 
289
    apic_get_delivery_bitmask(deliver_bitmask, dest, dest_mode);
 
290
    apic_bus_deliver(deliver_bitmask, delivery_mode, vector_num, polarity,
 
291
                     trigger_mode);
 
292
}
 
293
 
275
294
void cpu_set_apic_base(CPUState *env, uint64_t val)
276
295
{
277
296
    APICState *s = env->apic_state;
278
297
#ifdef DEBUG_APIC
279
298
    printf("cpu_set_apic_base: %016" PRIx64 "\n", val);
280
299
#endif
 
300
    if (!s)
 
301
        return;
281
302
    s->apicbase = (val & 0xfffff000) |
282
303
        (s->apicbase & (MSR_IA32_APICBASE_BSP | MSR_IA32_APICBASE_ENABLE));
283
304
    /* if disabled, cannot be enabled again */
292
313
{
293
314
    APICState *s = env->apic_state;
294
315
#ifdef DEBUG_APIC
295
 
    printf("cpu_get_apic_base: %016" PRIx64 "\n", (uint64_t)s->apicbase);
 
316
    printf("cpu_get_apic_base: %016" PRIx64 "\n",
 
317
           s ? (uint64_t)s->apicbase: 0);
296
318
#endif
297
 
    return s->apicbase;
 
319
    return s ? s->apicbase : 0;
298
320
}
299
321
 
300
322
void cpu_set_apic_tpr(CPUX86State *env, uint8_t val)
301
323
{
302
324
    APICState *s = env->apic_state;
 
325
    if (!s)
 
326
        return;
303
327
    s->tpr = (val & 0x0f) << 4;
304
328
    apic_update_irq(s);
305
329
}
307
331
uint8_t cpu_get_apic_tpr(CPUX86State *env)
308
332
{
309
333
    APICState *s = env->apic_state;
310
 
    return s->tpr >> 4;
 
334
    return s ? s->tpr >> 4 : 0;
311
335
}
312
336
 
313
337
/* return -1 if no bit is set */
393
417
    apic_update_irq(s);
394
418
}
395
419
 
 
420
static int apic_find_dest(uint8_t dest)
 
421
{
 
422
    APICState *apic = local_apics[dest];
 
423
    int i;
 
424
 
 
425
    if (apic && apic->id == dest)
 
426
        return dest;  /* shortcut in case apic->id == apic->idx */
 
427
 
 
428
    for (i = 0; i < MAX_APICS; i++) {
 
429
        apic = local_apics[i];
 
430
        if (apic && apic->id == dest)
 
431
            return i;
 
432
    }
 
433
 
 
434
    return -1;
 
435
}
 
436
 
396
437
static void apic_get_delivery_bitmask(uint32_t *deliver_bitmask,
397
438
                                      uint8_t dest, uint8_t dest_mode)
398
439
{
403
444
        if (dest == 0xff) {
404
445
            memset(deliver_bitmask, 0xff, MAX_APIC_WORDS * sizeof(uint32_t));
405
446
        } else {
 
447
            int idx = apic_find_dest(dest);
406
448
            memset(deliver_bitmask, 0x00, MAX_APIC_WORDS * sizeof(uint32_t));
407
 
            set_bit(deliver_bitmask, dest);
 
449
            if (idx >= 0)
 
450
                set_bit(deliver_bitmask, idx);
408
451
        }
409
452
    } else {
410
453
        /* XXX: cluster mode */
427
470
}
428
471
 
429
472
 
430
 
static void apic_init_ipi(APICState *s)
 
473
void apic_init_reset(CPUState *env)
431
474
{
 
475
    APICState *s = env->apic_state;
432
476
    int i;
433
477
 
 
478
    if (!s)
 
479
        return;
 
480
 
434
481
    s->tpr = 0;
435
482
    s->spurious_vec = 0xff;
436
483
    s->log_dest = 0;
447
494
    s->initial_count = 0;
448
495
    s->initial_count_load_time = 0;
449
496
    s->next_time = 0;
450
 
 
451
 
    cpu_reset(s->cpu_env);
452
 
 
453
 
    if (!(s->apicbase & MSR_IA32_APICBASE_BSP))
454
 
        s->cpu_env->halted = 1;
 
497
    s->wait_for_sipi = 1;
 
498
 
 
499
    env->halted = !(s->apicbase & MSR_IA32_APICBASE_BSP);
455
500
}
456
501
 
457
 
/* send a SIPI message to the CPU to start it */
458
502
static void apic_startup(APICState *s, int vector_num)
459
503
{
460
 
    CPUState *env = s->cpu_env;
461
 
    if (!env->halted)
 
504
    s->sipi_vector = vector_num;
 
505
    cpu_interrupt(s->cpu_env, CPU_INTERRUPT_SIPI);
 
506
}
 
507
 
 
508
void apic_sipi(CPUState *env)
 
509
{
 
510
    APICState *s = env->apic_state;
 
511
 
 
512
    cpu_reset_interrupt(env, CPU_INTERRUPT_SIPI);
 
513
 
 
514
    if (!s->wait_for_sipi)
462
515
        return;
 
516
 
463
517
    env->eip = 0;
464
 
    cpu_x86_load_seg_cache(env, R_CS, vector_num << 8, vector_num << 12,
 
518
    cpu_x86_load_seg_cache(env, R_CS, s->sipi_vector << 8, s->sipi_vector << 12,
465
519
                           0xffff, 0);
466
520
    env->halted = 0;
 
521
    s->wait_for_sipi = 0;
467
522
}
468
523
 
469
524
static void apic_deliver(APICState *s, uint8_t dest, uint8_t dest_mode,
480
535
        break;
481
536
    case 1:
482
537
        memset(deliver_bitmask, 0x00, sizeof(deliver_bitmask));
483
 
        set_bit(deliver_bitmask, s->id);
 
538
        set_bit(deliver_bitmask, s->idx);
484
539
        break;
485
540
    case 2:
486
541
        memset(deliver_bitmask, 0xff, sizeof(deliver_bitmask));
487
542
        break;
488
543
    case 3:
489
544
        memset(deliver_bitmask, 0xff, sizeof(deliver_bitmask));
490
 
        reset_bit(deliver_bitmask, s->id);
 
545
        reset_bit(deliver_bitmask, s->idx);
491
546
        break;
492
547
    }
493
548
 
705
760
    return val;
706
761
}
707
762
 
 
763
static void apic_send_msi(target_phys_addr_t addr, uint32 data)
 
764
{
 
765
    uint8_t dest = (addr & MSI_ADDR_DEST_ID_MASK) >> MSI_ADDR_DEST_ID_SHIFT;
 
766
    uint8_t vector = (data & MSI_DATA_VECTOR_MASK) >> MSI_DATA_VECTOR_SHIFT;
 
767
    uint8_t dest_mode = (addr >> MSI_ADDR_DEST_MODE_SHIFT) & 0x1;
 
768
    uint8_t trigger_mode = (data >> MSI_DATA_TRIGGER_SHIFT) & 0x1;
 
769
    uint8_t delivery = (data >> MSI_DATA_DELIVERY_MODE_SHIFT) & 0x7;
 
770
    /* XXX: Ignore redirection hint. */
 
771
    apic_deliver_irq(dest, dest_mode, delivery, vector, 0, trigger_mode);
 
772
}
 
773
 
708
774
static void apic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
709
775
{
710
776
    CPUState *env;
711
777
    APICState *s;
712
 
    int index;
 
778
    int index = (addr >> 4) & 0xff;
 
779
    if (addr > 0xfff || !index) {
 
780
        /* MSI and MMIO APIC are at the same memory location,
 
781
         * but actually not on the global bus: MSI is on PCI bus
 
782
         * APIC is connected directly to the CPU.
 
783
         * Mapping them on the global bus happens to work because
 
784
         * MSI registers are reserved in APIC MMIO and vice versa. */
 
785
        apic_send_msi(addr, val);
 
786
        return;
 
787
    }
713
788
 
714
789
    env = cpu_single_env;
715
790
    if (!env)
720
795
    printf("APIC write: %08x = %08x\n", (uint32_t)addr, val);
721
796
#endif
722
797
 
723
 
    index = (addr >> 4) & 0xff;
724
798
    switch(index) {
725
799
    case 0x02:
726
800
        s->id = (val >> 24);
863
937
static void apic_reset(void *opaque)
864
938
{
865
939
    APICState *s = opaque;
 
940
    int bsp = cpu_is_bsp(s->cpu_env);
866
941
 
867
942
    s->apicbase = 0xfee00000 |
868
 
        (s->id ? 0 : MSR_IA32_APICBASE_BSP) | MSR_IA32_APICBASE_ENABLE;
869
 
 
870
 
    apic_init_ipi(s);
871
 
 
872
 
    if (s->id == 0) {
 
943
        (bsp ? MSR_IA32_APICBASE_BSP : 0) | MSR_IA32_APICBASE_ENABLE;
 
944
 
 
945
    cpu_reset(s->cpu_env);
 
946
    apic_init_reset(s->cpu_env);
 
947
 
 
948
    if (bsp) {
873
949
        /*
874
950
         * LINT0 delivery mode on CPU #0 is set to ExtInt at initialization
875
951
         * time typically by BIOS, so PIC interrupt can be delivered to the
877
953
         */
878
954
        s->lvt[APIC_LVT_LINT0] = 0x700;
879
955
    }
 
956
 
 
957
    cpu_synchronize_state(s->cpu_env, 1);
880
958
}
881
959
 
882
960
static CPUReadMemoryFunc *apic_mem_read[3] = {
895
973
{
896
974
    APICState *s;
897
975
 
898
 
    if (last_apic_id >= MAX_APICS)
 
976
    if (last_apic_idx >= MAX_APICS)
899
977
        return -1;
900
978
    s = qemu_mallocz(sizeof(APICState));
901
979
    env->apic_state = s;
902
 
    s->id = last_apic_id++;
903
 
    env->cpuid_apic_id = s->id;
 
980
    s->idx = last_apic_idx++;
 
981
    s->id = env->cpuid_apic_id;
904
982
    s->cpu_env = env;
905
983
 
906
984
    apic_reset(s);
 
985
    msix_supported = 1;
907
986
 
908
987
    /* XXX: mapping more APICs at the same memory location */
909
988
    if (apic_io_memory == 0) {
910
989
        /* NOTE: the APIC is directly connected to the CPU - it is not
911
990
           on the global memory bus. */
912
 
        apic_io_memory = cpu_register_io_memory(0, apic_mem_read,
 
991
        apic_io_memory = cpu_register_io_memory(apic_mem_read,
913
992
                                                apic_mem_write, NULL);
914
 
        cpu_register_physical_memory(s->apicbase & ~0xfff, 0x1000,
 
993
        /* XXX: what if the base changes? */
 
994
        cpu_register_physical_memory(MSI_ADDR_BASE, MSI_ADDR_SIZE,
915
995
                                     apic_io_memory);
916
996
    }
917
997
    s->timer = qemu_new_timer(vm_clock, apic_timer, s);
918
998
 
919
 
    register_savevm("apic", s->id, 2, apic_save, apic_load, s);
 
999
    register_savevm("apic", s->idx, 2, apic_save, apic_load, s);
920
1000
    qemu_register_reset(apic_reset, s);
921
1001
 
922
 
    local_apics[s->id] = s;
923
 
    return 0;
924
 
}
925
 
 
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;
 
1002
    local_apics[s->idx] = s;
 
1003
    return 0;
1136
1004
}