source: trunk/packages/xen-common/xen-common/tools/ioemu/hw/apic.c @ 34

Last change on this file since 34 was 34, checked in by hartmans, 17 years ago

Add xen and xen-common

File size: 26.5 KB
Line 
1/*
2 *  APIC support
3 *
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 */
20#include "vl.h"
21
22//#define DEBUG_APIC
23//#define DEBUG_IOAPIC
24
25/* APIC Local Vector Table */
26#define APIC_LVT_TIMER   0
27#define APIC_LVT_THERMAL 1
28#define APIC_LVT_PERFORM 2
29#define APIC_LVT_LINT0   3
30#define APIC_LVT_LINT1   4
31#define APIC_LVT_ERROR   5
32#define APIC_LVT_NB      6
33
34/* APIC delivery modes */
35#define APIC_DM_FIXED   0
36#define APIC_DM_LOWPRI  1
37#define APIC_DM_SMI     2
38#define APIC_DM_NMI     4
39#define APIC_DM_INIT    5
40#define APIC_DM_SIPI    6
41#define APIC_DM_EXTINT  7
42
43/* APIC destination mode */
44#define APIC_DESTMODE_FLAT      0xf
45#define APIC_DESTMODE_CLUSTER   1
46
47#define APIC_TRIGGER_EDGE  0
48#define APIC_TRIGGER_LEVEL 1
49
50#define APIC_LVT_TIMER_PERIODIC         (1<<17)
51#define APIC_LVT_MASKED                 (1<<16)
52#define APIC_LVT_LEVEL_TRIGGER          (1<<15)
53#define APIC_LVT_REMOTE_IRR             (1<<14)
54#define APIC_INPUT_POLARITY             (1<<13)
55#define APIC_SEND_PENDING               (1<<12)
56
57#define IOAPIC_NUM_PINS                 0x18
58
59#define ESR_ILLEGAL_ADDRESS (1 << 7)
60
61#define APIC_SV_ENABLE (1 << 8)
62
63#define MAX_APICS 255
64#define MAX_APIC_WORDS 8
65
66typedef struct APICState {
67    CPUState *cpu_env;
68    uint32_t apicbase;
69    uint8_t id;
70    uint8_t arb_id;
71    uint8_t tpr;
72    uint32_t spurious_vec;
73    uint8_t log_dest;
74    uint8_t dest_mode;
75    uint32_t isr[8];  /* in service register */
76    uint32_t tmr[8];  /* trigger mode register */
77    uint32_t irr[8]; /* interrupt request register */
78    uint32_t lvt[APIC_LVT_NB];
79    uint32_t esr; /* error register */
80    uint32_t icr[2];
81
82    uint32_t divide_conf;
83    int count_shift;
84    uint32_t initial_count;
85    int64_t initial_count_load_time, next_time;
86    QEMUTimer *timer;
87} APICState;
88
89struct IOAPICState {
90    uint8_t id;
91    uint8_t ioregsel;
92
93    uint32_t irr;
94    uint64_t ioredtbl[IOAPIC_NUM_PINS];
95};
96
97static int apic_io_memory;
98static APICState *local_apics[MAX_APICS + 1];
99static int last_apic_id = 0;
100
101static void apic_init_ipi(APICState *s);
102static void apic_set_irq(APICState *s, int vector_num, int trigger_mode);
103static void apic_update_irq(APICState *s);
104
105/* Find first bit starting from msb. Return 0 if value = 0 */
106static int fls_bit(uint32_t value)
107{
108    unsigned int ret = 0;
109
110#if defined(HOST_I386)
111    __asm__ __volatile__ ("bsr %1, %0\n" : "+r" (ret) : "rm" (value));
112    return ret;
113#else
114    if (value > 0xffff)
115        value >>= 16, ret = 16;
116    if (value > 0xff)
117        value >>= 8, ret += 8;
118    if (value > 0xf)
119        value >>= 4, ret += 4;
120    if (value > 0x3)
121        value >>= 2, ret += 2;
122    return ret + (value >> 1);
123#endif
124}
125
126/* Find first bit starting from lsb. Return 0 if value = 0 */
127static int ffs_bit(uint32_t value)
128{
129    unsigned int ret = 0;
130
131#if defined(HOST_I386)
132    __asm__ __volatile__ ("bsf %1, %0\n" : "+r" (ret) : "rm" (value));
133    return ret;
134#else
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
167#define foreach_apic(apic, deliver_bitmask, code) \
168{\
169    int __i, __j, __mask;\
170    for(__i = 0; __i < MAX_APIC_WORDS; __i++) {\
171        __mask = deliver_bitmask[__i];\
172        if (__mask) {\
173            for(__j = 0; __j < 32; __j++) {\
174                if (__mask & (1 << __j)) {\
175                    apic = local_apics[__i * 32 + __j];\
176                    if (apic) {\
177                        code;\
178                    }\
179                }\
180            }\
181        }\
182    }\
183}
184
185static void apic_bus_deliver(const uint32_t *deliver_bitmask, 
186                             uint8_t delivery_mode,
187                             uint8_t vector_num, uint8_t polarity,
188                             uint8_t trigger_mode)
189{
190    APICState *apic_iter;
191
192    switch (delivery_mode) {
193        case APIC_DM_LOWPRI:
194            /* XXX: search for focus processor, arbitration */
195            {
196                int i, d;
197                d = -1;
198                for(i = 0; i < MAX_APIC_WORDS; i++) {
199                    if (deliver_bitmask[i]) {
200                        d = i * 32 + ffs_bit(deliver_bitmask[i]);
201                        break;
202                    }
203                }
204                if (d >= 0) {
205                    apic_iter = local_apics[d];
206                    if (apic_iter) {
207                        apic_set_irq(apic_iter, vector_num, trigger_mode);
208                    }
209                }
210            }
211            return;
212
213        case APIC_DM_FIXED:
214            break;
215
216        case APIC_DM_SMI:
217        case APIC_DM_NMI:
218            break;
219
220        case APIC_DM_INIT:
221            /* normal INIT IPI sent to processors */
222            foreach_apic(apic_iter, deliver_bitmask, 
223                         apic_init_ipi(apic_iter) );
224            return;
225   
226        case APIC_DM_EXTINT:
227            /* handled in I/O APIC code */
228            break;
229
230        default:
231            return;
232    }
233
234    foreach_apic(apic_iter, deliver_bitmask, 
235                 apic_set_irq(apic_iter, vector_num, trigger_mode) );
236}
237
238void cpu_set_apic_base(CPUState *env, uint64_t val)
239{
240    APICState *s = env->apic_state;
241#ifdef DEBUG_APIC
242    printf("cpu_set_apic_base: %016" PRIx64 "\n", val);
243#endif
244    s->apicbase = (val & 0xfffff000) | 
245        (s->apicbase & (MSR_IA32_APICBASE_BSP | MSR_IA32_APICBASE_ENABLE));
246    /* if disabled, cannot be enabled again */
247    if (!(val & MSR_IA32_APICBASE_ENABLE)) {
248        s->apicbase &= ~MSR_IA32_APICBASE_ENABLE;
249        env->cpuid_features &= ~CPUID_APIC;
250        s->spurious_vec &= ~APIC_SV_ENABLE;
251    }
252}
253
254uint64_t cpu_get_apic_base(CPUState *env)
255{
256    APICState *s = env->apic_state;
257#ifdef DEBUG_APIC
258    printf("cpu_get_apic_base: %016" PRIx64 "\n", (uint64_t)s->apicbase);
259#endif
260    return s->apicbase;
261}
262
263void cpu_set_apic_tpr(CPUX86State *env, uint8_t val)
264{
265    APICState *s = env->apic_state;
266    s->tpr = (val & 0x0f) << 4;
267    apic_update_irq(s);
268}
269
270uint8_t cpu_get_apic_tpr(CPUX86State *env)
271{
272    APICState *s = env->apic_state;
273    return s->tpr >> 4;
274}
275
276/* return -1 if no bit is set */
277static int get_highest_priority_int(uint32_t *tab)
278{
279    int i;
280    for(i = 7; i >= 0; i--) {
281        if (tab[i] != 0) {
282            return i * 32 + fls_bit(tab[i]);
283        }
284    }
285    return -1;
286}
287
288static int apic_get_ppr(APICState *s)
289{
290    int tpr, isrv, ppr;
291
292    tpr = (s->tpr >> 4);
293    isrv = get_highest_priority_int(s->isr);
294    if (isrv < 0)
295        isrv = 0;
296    isrv >>= 4;
297    if (tpr >= isrv)
298        ppr = s->tpr;
299    else
300        ppr = isrv << 4;
301    return ppr;
302}
303
304static int apic_get_arb_pri(APICState *s)
305{
306    /* XXX: arbitration */
307    return 0;
308}
309
310/* signal the CPU if an irq is pending */
311static void apic_update_irq(APICState *s)
312{
313    int irrv, ppr;
314    if (!(s->spurious_vec & APIC_SV_ENABLE))
315        return;
316    irrv = get_highest_priority_int(s->irr);
317    if (irrv < 0)
318        return;
319    ppr = apic_get_ppr(s);
320    if (ppr && (irrv & 0xf0) <= (ppr & 0xf0))
321        return;
322    cpu_interrupt(s->cpu_env, CPU_INTERRUPT_HARD);
323}
324
325static void apic_set_irq(APICState *s, int vector_num, int trigger_mode)
326{
327    set_bit(s->irr, vector_num);
328    if (trigger_mode)
329        set_bit(s->tmr, vector_num);
330    else
331        reset_bit(s->tmr, vector_num);
332    apic_update_irq(s);
333}
334
335static void apic_eoi(APICState *s)
336{
337    int isrv;
338    isrv = get_highest_priority_int(s->isr);
339    if (isrv < 0)
340        return;
341    reset_bit(s->isr, isrv);
342    /* XXX: send the EOI packet to the APIC bus to allow the I/O APIC to
343            set the remote IRR bit for level triggered interrupts. */
344    apic_update_irq(s);
345}
346
347static void apic_get_delivery_bitmask(uint32_t *deliver_bitmask,
348                                      uint8_t dest, uint8_t dest_mode)
349{
350    APICState *apic_iter;
351    int i;
352
353    if (dest_mode == 0) {
354        if (dest == 0xff) {
355            memset(deliver_bitmask, 0xff, MAX_APIC_WORDS * sizeof(uint32_t));
356        } else {
357            memset(deliver_bitmask, 0x00, MAX_APIC_WORDS * sizeof(uint32_t));
358            set_bit(deliver_bitmask, dest);
359        }
360    } else {
361        /* XXX: cluster mode */
362        memset(deliver_bitmask, 0x00, MAX_APIC_WORDS * sizeof(uint32_t));
363        for(i = 0; i < MAX_APICS; i++) {
364            apic_iter = local_apics[i];
365            if (apic_iter) {
366                if (apic_iter->dest_mode == 0xf) {
367                    if (dest & apic_iter->log_dest)
368                        set_bit(deliver_bitmask, i);
369                } else if (apic_iter->dest_mode == 0x0) {
370                    if ((dest & 0xf0) == (apic_iter->log_dest & 0xf0) &&
371                        (dest & apic_iter->log_dest & 0x0f)) {
372                        set_bit(deliver_bitmask, i);
373                    }
374                }
375            }
376        }
377    }
378}
379
380
381static void apic_init_ipi(APICState *s)
382{
383    int i;
384
385    for(i = 0; i < APIC_LVT_NB; i++)
386        s->lvt[i] = 1 << 16; /* mask LVT */
387    s->tpr = 0;
388    s->spurious_vec = 0xff;
389    s->log_dest = 0;
390    s->dest_mode = 0xf;
391    memset(s->isr, 0, sizeof(s->isr));
392    memset(s->tmr, 0, sizeof(s->tmr));
393    memset(s->irr, 0, sizeof(s->irr));
394    memset(s->lvt, 0, sizeof(s->lvt));
395    s->esr = 0;
396    memset(s->icr, 0, sizeof(s->icr));
397    s->divide_conf = 0;
398    s->count_shift = 0;
399    s->initial_count = 0;
400    s->initial_count_load_time = 0;
401    s->next_time = 0;
402}
403
404/* send a SIPI message to the CPU to start it */
405static void apic_startup(APICState *s, int vector_num)
406{
407    CPUState *env = s->cpu_env;
408    if (!(env->hflags & HF_HALTED_MASK))
409        return;
410    env->eip = 0;
411    cpu_x86_load_seg_cache(env, R_CS, vector_num << 8, vector_num << 12, 
412                           0xffff, 0);
413    env->hflags &= ~HF_HALTED_MASK;
414}
415
416static void apic_deliver(APICState *s, uint8_t dest, uint8_t dest_mode,
417                         uint8_t delivery_mode, uint8_t vector_num,
418                         uint8_t polarity, uint8_t trigger_mode)
419{
420    uint32_t deliver_bitmask[MAX_APIC_WORDS];
421    int dest_shorthand = (s->icr[0] >> 18) & 3;
422    APICState *apic_iter;
423
424    switch (dest_shorthand) {
425    case 0:
426        apic_get_delivery_bitmask(deliver_bitmask, dest, dest_mode);
427        break;
428    case 1:
429        memset(deliver_bitmask, 0x00, sizeof(deliver_bitmask));
430        set_bit(deliver_bitmask, s->id);
431        break;
432    case 2:
433        memset(deliver_bitmask, 0xff, sizeof(deliver_bitmask));
434        break;
435    case 3:
436        memset(deliver_bitmask, 0xff, sizeof(deliver_bitmask));
437        reset_bit(deliver_bitmask, s->id);
438        break;
439    }
440
441    switch (delivery_mode) {
442        case APIC_DM_INIT:
443            {
444                int trig_mode = (s->icr[0] >> 15) & 1;
445                int level = (s->icr[0] >> 14) & 1;
446                if (level == 0 && trig_mode == 1) {
447                    foreach_apic(apic_iter, deliver_bitmask, 
448                                 apic_iter->arb_id = apic_iter->id );
449                    return;
450                }
451            }
452            break;
453
454        case APIC_DM_SIPI:
455            foreach_apic(apic_iter, deliver_bitmask, 
456                         apic_startup(apic_iter, vector_num) );
457            return;
458    }
459
460    apic_bus_deliver(deliver_bitmask, delivery_mode, vector_num, polarity,
461                     trigger_mode);
462}
463
464int apic_get_interrupt(CPUState *env)
465{
466    APICState *s = env->apic_state;
467    int intno;
468
469    /* if the APIC is installed or enabled, we let the 8259 handle the
470       IRQs */
471    if (!s)
472        return -1;
473    if (!(s->spurious_vec & APIC_SV_ENABLE))
474        return -1;
475   
476    /* XXX: spurious IRQ handling */
477    intno = get_highest_priority_int(s->irr);
478    if (intno < 0)
479        return -1;
480    reset_bit(s->irr, intno);
481    if (s->tpr && intno <= s->tpr)
482        return s->spurious_vec & 0xff;
483    set_bit(s->isr, intno);
484    apic_update_irq(s);
485    return intno;
486}
487
488static uint32_t apic_get_current_count(APICState *s)
489{
490    int64_t d;
491    uint32_t val;
492    d = (qemu_get_clock(vm_clock) - s->initial_count_load_time) >> 
493        s->count_shift;
494    if (s->lvt[APIC_LVT_TIMER] & APIC_LVT_TIMER_PERIODIC) {
495        /* periodic */
496        val = s->initial_count - (d % ((uint64_t)s->initial_count + 1));
497    } else {
498        if (d >= s->initial_count)
499            val = 0;
500        else
501            val = s->initial_count - d;
502    }
503    return val;
504}
505
506static void apic_timer_update(APICState *s, int64_t current_time)
507{
508    int64_t next_time, d;
509   
510    if (!(s->lvt[APIC_LVT_TIMER] & APIC_LVT_MASKED)) {
511        d = (current_time - s->initial_count_load_time) >> 
512            s->count_shift;
513        if (s->lvt[APIC_LVT_TIMER] & APIC_LVT_TIMER_PERIODIC) {
514            d = ((d / ((uint64_t)s->initial_count + 1)) + 1) * ((uint64_t)s->initial_count + 1);
515        } else {
516            if (d >= s->initial_count)
517                goto no_timer;
518            d = (uint64_t)s->initial_count + 1;
519        }
520        next_time = s->initial_count_load_time + (d << s->count_shift);
521        qemu_mod_timer(s->timer, next_time);
522        s->next_time = next_time;
523    } else {
524    no_timer:
525        qemu_del_timer(s->timer);
526    }
527}
528
529static void apic_timer(void *opaque)
530{
531    APICState *s = opaque;
532
533    if (!(s->lvt[APIC_LVT_TIMER] & APIC_LVT_MASKED)) {
534        apic_set_irq(s, s->lvt[APIC_LVT_TIMER] & 0xff, APIC_TRIGGER_EDGE);
535    }
536    apic_timer_update(s, s->next_time);
537}
538
539static uint32_t apic_mem_readb(void *opaque, target_phys_addr_t addr)
540{
541    return 0;
542}
543
544static uint32_t apic_mem_readw(void *opaque, target_phys_addr_t addr)
545{
546    return 0;
547}
548
549static void apic_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
550{
551}
552
553static void apic_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
554{
555}
556
557static uint32_t apic_mem_readl(void *opaque, target_phys_addr_t addr)
558{
559    CPUState *env;
560    APICState *s;
561    uint32_t val;
562    int index;
563
564    env = cpu_single_env;
565    if (!env)
566        return 0;
567    s = env->apic_state;
568
569    index = (addr >> 4) & 0xff;
570    switch(index) {
571    case 0x02: /* id */
572        val = s->id << 24;
573        break;
574    case 0x03: /* version */
575        val = 0x11 | ((APIC_LVT_NB - 1) << 16); /* version 0x11 */
576        break;
577    case 0x08:
578        val = s->tpr;
579        break;
580    case 0x09:
581        val = apic_get_arb_pri(s);
582        break;
583    case 0x0a:
584        /* ppr */
585        val = apic_get_ppr(s);
586        break;
587    case 0x0d:
588        val = s->log_dest << 24;
589        break;
590    case 0x0e:
591        val = s->dest_mode << 28;
592        break;
593    case 0x0f:
594        val = s->spurious_vec;
595        break;
596    case 0x10 ... 0x17:
597        val = s->isr[index & 7];
598        break;
599    case 0x18 ... 0x1f:
600        val = s->tmr[index & 7];
601        break;
602    case 0x20 ... 0x27:
603        val = s->irr[index & 7];
604        break;
605    case 0x28:
606        val = s->esr;
607        break;
608    case 0x30:
609    case 0x31:
610        val = s->icr[index & 1];
611        break;
612    case 0x32 ... 0x37:
613        val = s->lvt[index - 0x32];
614        break;
615    case 0x38:
616        val = s->initial_count;
617        break;
618    case 0x39:
619        val = apic_get_current_count(s);
620        break;
621    case 0x3e:
622        val = s->divide_conf;
623        break;
624    default:
625        s->esr |= ESR_ILLEGAL_ADDRESS;
626        val = 0;
627        break;
628    }
629#ifdef DEBUG_APIC
630    printf("APIC read: %08x = %08x\n", (uint32_t)addr, val);
631#endif
632    return val;
633}
634
635static void apic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
636{
637    CPUState *env;
638    APICState *s;
639    int index;
640
641    env = cpu_single_env;
642    if (!env)
643        return;
644    s = env->apic_state;
645
646#ifdef DEBUG_APIC
647    printf("APIC write: %08x = %08x\n", (uint32_t)addr, val);
648#endif
649
650    index = (addr >> 4) & 0xff;
651    switch(index) {
652    case 0x02:
653        s->id = (val >> 24);
654        break;
655    case 0x03:
656        break;
657    case 0x08:
658        s->tpr = val;
659        apic_update_irq(s);
660        break;
661    case 0x09:
662    case 0x0a:
663        break;
664    case 0x0b: /* EOI */
665        apic_eoi(s);
666        break;
667    case 0x0d:
668        s->log_dest = val >> 24;
669        break;
670    case 0x0e:
671        s->dest_mode = val >> 28;
672        break;
673    case 0x0f:
674        s->spurious_vec = val & 0x1ff;
675        apic_update_irq(s);
676        break;
677    case 0x10 ... 0x17:
678    case 0x18 ... 0x1f:
679    case 0x20 ... 0x27:
680    case 0x28:
681        break;
682    case 0x30:
683        s->icr[0] = val;
684        apic_deliver(s, (s->icr[1] >> 24) & 0xff, (s->icr[0] >> 11) & 1,
685                     (s->icr[0] >> 8) & 7, (s->icr[0] & 0xff),
686                     (s->icr[0] >> 14) & 1, (s->icr[0] >> 15) & 1);
687        break;
688    case 0x31:
689        s->icr[1] = val;
690        break;
691    case 0x32 ... 0x37:
692        {
693            int n = index - 0x32;
694            s->lvt[n] = val;
695            if (n == APIC_LVT_TIMER)
696                apic_timer_update(s, qemu_get_clock(vm_clock));
697        }
698        break;
699    case 0x38:
700        s->initial_count = val;
701        s->initial_count_load_time = qemu_get_clock(vm_clock);
702        apic_timer_update(s, s->initial_count_load_time);
703        break;
704    case 0x39:
705        break;
706    case 0x3e:
707        {
708            int v;
709            s->divide_conf = val & 0xb;
710            v = (s->divide_conf & 3) | ((s->divide_conf >> 1) & 4);
711            s->count_shift = (v + 1) & 7;
712        }
713        break;
714    default:
715        s->esr |= ESR_ILLEGAL_ADDRESS;
716        break;
717    }
718}
719
720static void apic_save(QEMUFile *f, void *opaque)
721{
722    APICState *s = opaque;
723    int i;
724
725    qemu_put_be32s(f, &s->apicbase);
726    qemu_put_8s(f, &s->id);
727    qemu_put_8s(f, &s->arb_id);
728    qemu_put_8s(f, &s->tpr);
729    qemu_put_be32s(f, &s->spurious_vec);
730    qemu_put_8s(f, &s->log_dest);
731    qemu_put_8s(f, &s->dest_mode);
732    for (i = 0; i < 8; i++) {
733        qemu_put_be32s(f, &s->isr[i]);
734        qemu_put_be32s(f, &s->tmr[i]);
735        qemu_put_be32s(f, &s->irr[i]);
736    }
737    for (i = 0; i < APIC_LVT_NB; i++) {
738        qemu_put_be32s(f, &s->lvt[i]);
739    }
740    qemu_put_be32s(f, &s->esr);
741    qemu_put_be32s(f, &s->icr[0]);
742    qemu_put_be32s(f, &s->icr[1]);
743    qemu_put_be32s(f, &s->divide_conf);
744    qemu_put_be32s(f, &s->count_shift);
745    qemu_put_be32s(f, &s->initial_count);
746    qemu_put_be64s(f, &s->initial_count_load_time);
747    qemu_put_be64s(f, &s->next_time);
748}
749
750static int apic_load(QEMUFile *f, void *opaque, int version_id)
751{
752    APICState *s = opaque;
753    int i;
754
755    if (version_id != 1)
756        return -EINVAL;
757
758    /* XXX: what if the base changes? (registered memory regions) */
759    qemu_get_be32s(f, &s->apicbase);
760    qemu_get_8s(f, &s->id);
761    qemu_get_8s(f, &s->arb_id);
762    qemu_get_8s(f, &s->tpr);
763    qemu_get_be32s(f, &s->spurious_vec);
764    qemu_get_8s(f, &s->log_dest);
765    qemu_get_8s(f, &s->dest_mode);
766    for (i = 0; i < 8; i++) {
767        qemu_get_be32s(f, &s->isr[i]);
768        qemu_get_be32s(f, &s->tmr[i]);
769        qemu_get_be32s(f, &s->irr[i]);
770    }
771    for (i = 0; i < APIC_LVT_NB; i++) {
772        qemu_get_be32s(f, &s->lvt[i]);
773    }
774    qemu_get_be32s(f, &s->esr);
775    qemu_get_be32s(f, &s->icr[0]);
776    qemu_get_be32s(f, &s->icr[1]);
777    qemu_get_be32s(f, &s->divide_conf);
778    qemu_get_be32s(f, &s->count_shift);
779    qemu_get_be32s(f, &s->initial_count);
780    qemu_get_be64s(f, &s->initial_count_load_time);
781    qemu_get_be64s(f, &s->next_time);
782    return 0;
783}
784
785static void apic_reset(void *opaque)
786{
787    APICState *s = opaque;
788    apic_init_ipi(s);
789}
790
791static CPUReadMemoryFunc *apic_mem_read[3] = {
792    apic_mem_readb,
793    apic_mem_readw,
794    apic_mem_readl,
795};
796
797static CPUWriteMemoryFunc *apic_mem_write[3] = {
798    apic_mem_writeb,
799    apic_mem_writew,
800    apic_mem_writel,
801};
802
803int apic_init(CPUState *env)
804{
805    APICState *s;
806
807    if (last_apic_id >= MAX_APICS)
808        return -1;
809    s = qemu_mallocz(sizeof(APICState));
810    if (!s)
811        return -1;
812    env->apic_state = s;
813    apic_init_ipi(s);
814    s->id = last_apic_id++;
815    s->cpu_env = env;
816    s->apicbase = 0xfee00000 | 
817        (s->id ? 0 : MSR_IA32_APICBASE_BSP) | MSR_IA32_APICBASE_ENABLE;
818
819    /* XXX: mapping more APICs at the same memory location */
820    if (apic_io_memory == 0) {
821        /* NOTE: the APIC is directly connected to the CPU - it is not
822           on the global memory bus. */
823        apic_io_memory = cpu_register_io_memory(0, apic_mem_read, 
824                                                apic_mem_write, NULL);
825        cpu_register_physical_memory(s->apicbase & ~0xfff, 0x1000,
826                                     apic_io_memory);
827    }
828    s->timer = qemu_new_timer(vm_clock, apic_timer, s);
829
830    register_savevm("apic", 0, 1, apic_save, apic_load, s);
831    qemu_register_reset(apic_reset, s);
832   
833    local_apics[s->id] = s;
834    return 0;
835}
836
837static void ioapic_service(IOAPICState *s)
838{
839    uint8_t i;
840    uint8_t trig_mode;
841    uint8_t vector;
842    uint8_t delivery_mode;
843    uint32_t mask;
844    uint64_t entry;
845    uint8_t dest;
846    uint8_t dest_mode;
847    uint8_t polarity;
848    uint32_t deliver_bitmask[MAX_APIC_WORDS];
849
850    for (i = 0; i < IOAPIC_NUM_PINS; i++) {
851        mask = 1 << i;
852        if (s->irr & mask) {
853            entry = s->ioredtbl[i];
854            if (!(entry & APIC_LVT_MASKED)) {
855                trig_mode = ((entry >> 15) & 1);
856                dest = entry >> 56;
857                dest_mode = (entry >> 11) & 1;
858                delivery_mode = (entry >> 8) & 7;
859                polarity = (entry >> 13) & 1;
860                if (trig_mode == APIC_TRIGGER_EDGE)
861                    s->irr &= ~mask;
862                if (delivery_mode == APIC_DM_EXTINT)
863                    vector = pic_read_irq(isa_pic);
864                else
865                    vector = entry & 0xff;
866               
867                apic_get_delivery_bitmask(deliver_bitmask, dest, dest_mode);
868                apic_bus_deliver(deliver_bitmask, delivery_mode, 
869                                 vector, polarity, trig_mode);
870            }
871        }
872    }
873}
874
875void ioapic_set_irq(void *opaque, int vector, int level)
876{
877    IOAPICState *s = opaque;
878
879    if (vector >= 0 && vector < IOAPIC_NUM_PINS) {
880        uint32_t mask = 1 << vector;
881        uint64_t entry = s->ioredtbl[vector];
882
883        if ((entry >> 15) & 1) {
884            /* level triggered */
885            if (level) {
886                s->irr |= mask;
887                ioapic_service(s);
888            } else {
889                s->irr &= ~mask;
890            }
891        } else {
892            /* edge triggered */
893            if (level) {
894                s->irr |= mask;
895                ioapic_service(s);
896            }
897        }
898    }
899}
900
901static uint32_t ioapic_mem_readl(void *opaque, target_phys_addr_t addr)
902{
903    IOAPICState *s = opaque;
904    int index;
905    uint32_t val = 0;
906
907    addr &= 0xff;
908    if (addr == 0x00) {
909        val = s->ioregsel;
910    } else if (addr == 0x10) {
911        switch (s->ioregsel) {
912            case 0x00:
913                val = s->id << 24;
914                break;
915            case 0x01:
916                val = 0x11 | ((IOAPIC_NUM_PINS - 1) << 16); /* version 0x11 */
917                break;
918            case 0x02:
919                val = 0;
920                break;
921            default:
922                index = (s->ioregsel - 0x10) >> 1;
923                if (index >= 0 && index < IOAPIC_NUM_PINS) {
924                    if (s->ioregsel & 1)
925                        val = s->ioredtbl[index] >> 32;
926                    else
927                        val = s->ioredtbl[index] & 0xffffffff;
928                }
929        }
930#ifdef DEBUG_IOAPIC
931        printf("I/O APIC read: %08x = %08x\n", s->ioregsel, val);
932#endif
933    }
934    return val;
935}
936
937static void ioapic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
938{
939    IOAPICState *s = opaque;
940    int index;
941
942    addr &= 0xff;
943    if (addr == 0x00)  {
944        s->ioregsel = val;
945        return;
946    } else if (addr == 0x10) {
947#ifdef DEBUG_IOAPIC
948        printf("I/O APIC write: %08x = %08x\n", s->ioregsel, val);
949#endif
950        switch (s->ioregsel) {
951            case 0x00:
952                s->id = (val >> 24) & 0xff;
953                return;
954            case 0x01:
955            case 0x02:
956                return;
957            default:
958                index = (s->ioregsel - 0x10) >> 1;
959                if (index >= 0 && index < IOAPIC_NUM_PINS) {
960                    if (s->ioregsel & 1) {
961                        s->ioredtbl[index] &= 0xffffffff;
962                        s->ioredtbl[index] |= (uint64_t)val << 32;
963                    } else {
964                        s->ioredtbl[index] &= ~0xffffffffULL;
965                        s->ioredtbl[index] |= val;
966                    }
967                    ioapic_service(s);
968                }
969        }
970    }
971}
972
973static void ioapic_save(QEMUFile *f, void *opaque)
974{
975    IOAPICState *s = opaque;
976    int i;
977
978    qemu_put_8s(f, &s->id);
979    qemu_put_8s(f, &s->ioregsel);
980    for (i = 0; i < IOAPIC_NUM_PINS; i++) {
981        qemu_put_be64s(f, &s->ioredtbl[i]);
982    }
983}
984
985static int ioapic_load(QEMUFile *f, void *opaque, int version_id)
986{
987    IOAPICState *s = opaque;
988    int i;
989
990    if (version_id != 1)
991        return -EINVAL;
992
993    qemu_get_8s(f, &s->id);
994    qemu_get_8s(f, &s->ioregsel);
995    for (i = 0; i < IOAPIC_NUM_PINS; i++) {
996        qemu_get_be64s(f, &s->ioredtbl[i]);
997    }
998    return 0;
999}
1000
1001static void ioapic_reset(void *opaque)
1002{
1003    IOAPICState *s = opaque;
1004    int i;
1005
1006    memset(s, 0, sizeof(*s));
1007    for(i = 0; i < IOAPIC_NUM_PINS; i++)
1008        s->ioredtbl[i] = 1 << 16; /* mask LVT */
1009}
1010
1011static CPUReadMemoryFunc *ioapic_mem_read[3] = {
1012    ioapic_mem_readl,
1013    ioapic_mem_readl,
1014    ioapic_mem_readl,
1015};
1016
1017static CPUWriteMemoryFunc *ioapic_mem_write[3] = {
1018    ioapic_mem_writel,
1019    ioapic_mem_writel,
1020    ioapic_mem_writel,
1021};
1022
1023IOAPICState *ioapic_init(void)
1024{
1025    IOAPICState *s;
1026    int io_memory;
1027
1028    s = qemu_mallocz(sizeof(IOAPICState));
1029    if (!s)
1030        return NULL;
1031    ioapic_reset(s);
1032    s->id = last_apic_id++;
1033
1034    io_memory = cpu_register_io_memory(0, ioapic_mem_read, 
1035                                       ioapic_mem_write, s);
1036    cpu_register_physical_memory(0xfec00000, 0x1000, io_memory);
1037
1038    register_savevm("ioapic", 0, 1, ioapic_save, ioapic_load, s);
1039    qemu_register_reset(ioapic_reset, s);
1040   
1041    return s;
1042}
Note: See TracBrowser for help on using the repository browser.