Statistics
| Branch: | Revision:

root / hw / apic.c @ d3c61721

History | View | Annotate | Download (10.5 kB)

1 574bbf7b bellard
/*
2 574bbf7b bellard
 *  APIC support
3 574bbf7b bellard
 * 
4 574bbf7b bellard
 *  Copyright (c) 2004-2005 Fabrice Bellard
5 574bbf7b bellard
 *
6 574bbf7b bellard
 * This library is free software; you can redistribute it and/or
7 574bbf7b bellard
 * modify it under the terms of the GNU Lesser General Public
8 574bbf7b bellard
 * License as published by the Free Software Foundation; either
9 574bbf7b bellard
 * version 2 of the License, or (at your option) any later version.
10 574bbf7b bellard
 *
11 574bbf7b bellard
 * This library is distributed in the hope that it will be useful,
12 574bbf7b bellard
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 574bbf7b bellard
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 574bbf7b bellard
 * Lesser General Public License for more details.
15 574bbf7b bellard
 *
16 574bbf7b bellard
 * You should have received a copy of the GNU Lesser General Public
17 574bbf7b bellard
 * License along with this library; if not, write to the Free Software
18 574bbf7b bellard
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 574bbf7b bellard
 */
20 574bbf7b bellard
#include "vl.h"
21 574bbf7b bellard
22 574bbf7b bellard
//#define DEBUG_APIC
23 574bbf7b bellard
24 574bbf7b bellard
/* APIC Local Vector Table */
25 574bbf7b bellard
#define APIC_LVT_TIMER   0
26 574bbf7b bellard
#define APIC_LVT_THERMAL 1
27 574bbf7b bellard
#define APIC_LVT_PERFORM 2
28 574bbf7b bellard
#define APIC_LVT_LINT0   3
29 574bbf7b bellard
#define APIC_LVT_LINT1   4
30 574bbf7b bellard
#define APIC_LVT_ERROR   5
31 574bbf7b bellard
#define APIC_LVT_NB      6
32 574bbf7b bellard
33 574bbf7b bellard
/* APIC delivery modes */
34 574bbf7b bellard
#define APIC_DM_FIXED        0
35 574bbf7b bellard
#define APIC_DM_LOWPRI        1
36 574bbf7b bellard
#define APIC_DM_SMI        2
37 574bbf7b bellard
#define APIC_DM_NMI        4
38 574bbf7b bellard
#define APIC_DM_INIT        5
39 574bbf7b bellard
#define APIC_DM_SIPI        6
40 574bbf7b bellard
#define APIC_DM_EXTINT        7
41 574bbf7b bellard
42 574bbf7b bellard
#define APIC_TRIGGER_EDGE  0
43 574bbf7b bellard
#define APIC_TRIGGER_LEVEL 1
44 574bbf7b bellard
45 574bbf7b bellard
#define        APIC_LVT_TIMER_PERIODIC                (1<<17)
46 574bbf7b bellard
#define        APIC_LVT_MASKED                        (1<<16)
47 574bbf7b bellard
#define        APIC_LVT_LEVEL_TRIGGER                (1<<15)
48 574bbf7b bellard
#define        APIC_LVT_REMOTE_IRR                (1<<14)
49 574bbf7b bellard
#define        APIC_INPUT_POLARITY                (1<<13)
50 574bbf7b bellard
#define        APIC_SEND_PENDING                (1<<12)
51 574bbf7b bellard
52 574bbf7b bellard
#define ESR_ILLEGAL_ADDRESS (1 << 7)
53 574bbf7b bellard
54 574bbf7b bellard
#define APIC_SV_ENABLE (1 << 8)
55 574bbf7b bellard
56 574bbf7b bellard
typedef struct APICState {
57 574bbf7b bellard
    CPUState *cpu_env;
58 574bbf7b bellard
    uint32_t apicbase;
59 574bbf7b bellard
    uint8_t id;
60 574bbf7b bellard
    uint8_t tpr;
61 574bbf7b bellard
    uint32_t spurious_vec;
62 574bbf7b bellard
    uint32_t isr[8];  /* in service register */
63 574bbf7b bellard
    uint32_t tmr[8];  /* trigger mode register */
64 574bbf7b bellard
    uint32_t irr[8]; /* interrupt request register */
65 574bbf7b bellard
    uint32_t lvt[APIC_LVT_NB];
66 574bbf7b bellard
    uint32_t esr; /* error register */
67 574bbf7b bellard
    uint32_t icr[2];
68 574bbf7b bellard
69 574bbf7b bellard
    uint32_t divide_conf;
70 574bbf7b bellard
    int count_shift;
71 574bbf7b bellard
    uint32_t initial_count;
72 574bbf7b bellard
    int64_t initial_count_load_time, next_time;
73 574bbf7b bellard
    QEMUTimer *timer;
74 574bbf7b bellard
} APICState;
75 574bbf7b bellard
76 574bbf7b bellard
static int apic_io_memory;
77 574bbf7b bellard
78 574bbf7b bellard
void cpu_set_apic_base(CPUState *env, uint64_t val)
79 574bbf7b bellard
{
80 574bbf7b bellard
    APICState *s = env->apic_state;
81 574bbf7b bellard
#ifdef DEBUG_APIC
82 574bbf7b bellard
    printf("cpu_set_apic_base: %016llx\n", val);
83 574bbf7b bellard
#endif
84 574bbf7b bellard
    s->apicbase = (val & 0xfffff000) | 
85 574bbf7b bellard
        (s->apicbase & (MSR_IA32_APICBASE_BSP | MSR_IA32_APICBASE_ENABLE));
86 574bbf7b bellard
    /* if disabled, cannot be enabled again */
87 574bbf7b bellard
    if (!(val & MSR_IA32_APICBASE_ENABLE)) {
88 574bbf7b bellard
        s->apicbase &= ~MSR_IA32_APICBASE_ENABLE;
89 574bbf7b bellard
        env->cpuid_features &= ~CPUID_APIC;
90 574bbf7b bellard
        s->spurious_vec &= ~APIC_SV_ENABLE;
91 574bbf7b bellard
    }
92 574bbf7b bellard
}
93 574bbf7b bellard
94 574bbf7b bellard
uint64_t cpu_get_apic_base(CPUState *env)
95 574bbf7b bellard
{
96 574bbf7b bellard
    APICState *s = env->apic_state;
97 574bbf7b bellard
#ifdef DEBUG_APIC
98 574bbf7b bellard
    printf("cpu_get_apic_base: %016llx\n", (uint64_t)s->apicbase);
99 574bbf7b bellard
#endif
100 574bbf7b bellard
    return s->apicbase;
101 574bbf7b bellard
}
102 574bbf7b bellard
103 574bbf7b bellard
/* return -1 if no bit is set */
104 574bbf7b bellard
static int get_highest_priority_int(uint32_t *tab)
105 574bbf7b bellard
{
106 574bbf7b bellard
    int i;
107 574bbf7b bellard
    for(i = 0;i < 8; i++) {
108 574bbf7b bellard
        if (tab[i] != 0) {
109 574bbf7b bellard
            return i * 32 + ffs(tab[i]) - 1;
110 574bbf7b bellard
        }
111 574bbf7b bellard
    }
112 574bbf7b bellard
    return -1;
113 574bbf7b bellard
}
114 574bbf7b bellard
115 574bbf7b bellard
static inline void set_bit(uint32_t *tab, int index)
116 574bbf7b bellard
{
117 574bbf7b bellard
    int i, mask;
118 574bbf7b bellard
    i = index >> 5;
119 574bbf7b bellard
    mask = 1 << (index & 0x1f);
120 574bbf7b bellard
    tab[i] |= mask;
121 574bbf7b bellard
}
122 574bbf7b bellard
123 574bbf7b bellard
static inline void reset_bit(uint32_t *tab, int index)
124 574bbf7b bellard
{
125 574bbf7b bellard
    int i, mask;
126 574bbf7b bellard
    i = index >> 5;
127 574bbf7b bellard
    mask = 1 << (index & 0x1f);
128 574bbf7b bellard
    tab[i] &= ~mask;
129 574bbf7b bellard
}
130 574bbf7b bellard
131 574bbf7b bellard
static int apic_get_ppr(APICState *s)
132 574bbf7b bellard
{
133 574bbf7b bellard
    int tpr, isrv, ppr;
134 574bbf7b bellard
135 574bbf7b bellard
    tpr = (s->tpr >> 4);
136 574bbf7b bellard
    isrv = get_highest_priority_int(s->isr);
137 574bbf7b bellard
    if (isrv < 0)
138 574bbf7b bellard
        isrv = 0;
139 574bbf7b bellard
    isrv >>= 4;
140 574bbf7b bellard
    if (tpr >= isrv)
141 574bbf7b bellard
        ppr = s->tpr;
142 574bbf7b bellard
    else
143 574bbf7b bellard
        ppr = isrv << 4;
144 574bbf7b bellard
    return ppr;
145 574bbf7b bellard
}
146 574bbf7b bellard
147 574bbf7b bellard
/* signal the CPU if an irq is pending */
148 574bbf7b bellard
static void apic_update_irq(APICState *s)
149 574bbf7b bellard
{
150 574bbf7b bellard
    int irrv, isrv;
151 574bbf7b bellard
    irrv = get_highest_priority_int(s->irr);
152 574bbf7b bellard
    if (irrv < 0)
153 574bbf7b bellard
        return;
154 574bbf7b bellard
    isrv = get_highest_priority_int(s->isr);
155 574bbf7b bellard
    /* if the pending irq has less priority, we do not make a new request */
156 574bbf7b bellard
    if (isrv >= 0 && irrv >= isrv)
157 574bbf7b bellard
        return;
158 574bbf7b bellard
    cpu_interrupt(s->cpu_env, CPU_INTERRUPT_HARD);
159 574bbf7b bellard
}
160 574bbf7b bellard
161 574bbf7b bellard
static void apic_set_irq(APICState *s, int vector_num, int trigger_mode)
162 574bbf7b bellard
{
163 574bbf7b bellard
    set_bit(s->irr, vector_num);
164 574bbf7b bellard
    if (trigger_mode)
165 574bbf7b bellard
        set_bit(s->tmr, vector_num);
166 574bbf7b bellard
    else
167 574bbf7b bellard
        reset_bit(s->tmr, vector_num);
168 574bbf7b bellard
    apic_update_irq(s);
169 574bbf7b bellard
}
170 574bbf7b bellard
171 574bbf7b bellard
static void apic_eoi(APICState *s)
172 574bbf7b bellard
{
173 574bbf7b bellard
    int isrv;
174 574bbf7b bellard
    isrv = get_highest_priority_int(s->isr);
175 574bbf7b bellard
    if (isrv < 0)
176 574bbf7b bellard
        return;
177 574bbf7b bellard
    reset_bit(s->isr, isrv);
178 574bbf7b bellard
    apic_update_irq(s);
179 574bbf7b bellard
}
180 574bbf7b bellard
181 574bbf7b bellard
int apic_get_interrupt(CPUState *env)
182 574bbf7b bellard
{
183 574bbf7b bellard
    APICState *s = env->apic_state;
184 574bbf7b bellard
    int intno;
185 574bbf7b bellard
186 574bbf7b bellard
    /* if the APIC is installed or enabled, we let the 8259 handle the
187 574bbf7b bellard
       IRQs */
188 574bbf7b bellard
    if (!s)
189 574bbf7b bellard
        return -1;
190 574bbf7b bellard
    if (!(s->spurious_vec & APIC_SV_ENABLE))
191 574bbf7b bellard
        return -1;
192 574bbf7b bellard
    
193 574bbf7b bellard
    /* XXX: spurious IRQ handling */
194 574bbf7b bellard
    intno = get_highest_priority_int(s->irr);
195 574bbf7b bellard
    if (intno < 0)
196 574bbf7b bellard
        return -1;
197 574bbf7b bellard
    reset_bit(s->irr, intno);
198 574bbf7b bellard
    set_bit(s->isr, intno);
199 574bbf7b bellard
    apic_update_irq(s);
200 574bbf7b bellard
    return intno;
201 574bbf7b bellard
}
202 574bbf7b bellard
203 574bbf7b bellard
static uint32_t apic_get_current_count(APICState *s)
204 574bbf7b bellard
{
205 574bbf7b bellard
    int64_t d;
206 574bbf7b bellard
    uint32_t val;
207 574bbf7b bellard
    d = (qemu_get_clock(vm_clock) - s->initial_count_load_time) >> 
208 574bbf7b bellard
        s->count_shift;
209 574bbf7b bellard
    if (s->lvt[APIC_LVT_TIMER] & APIC_LVT_TIMER_PERIODIC) {
210 574bbf7b bellard
        /* periodic */
211 574bbf7b bellard
        val = s->initial_count - (d % (s->initial_count + 1));
212 574bbf7b bellard
    } else {
213 574bbf7b bellard
        if (d >= s->initial_count)
214 574bbf7b bellard
            val = 0;
215 574bbf7b bellard
        else
216 574bbf7b bellard
            val = s->initial_count - d;
217 574bbf7b bellard
    }
218 574bbf7b bellard
    return val;
219 574bbf7b bellard
}
220 574bbf7b bellard
221 574bbf7b bellard
static void apic_timer_update(APICState *s, int64_t current_time)
222 574bbf7b bellard
{
223 574bbf7b bellard
    int64_t next_time, d;
224 574bbf7b bellard
    
225 574bbf7b bellard
    if (!(s->lvt[APIC_LVT_TIMER] & APIC_LVT_MASKED)) {
226 574bbf7b bellard
        d = (current_time - s->initial_count_load_time) >> 
227 574bbf7b bellard
            s->count_shift;
228 574bbf7b bellard
        if (s->lvt[APIC_LVT_TIMER] & APIC_LVT_TIMER_PERIODIC) {
229 574bbf7b bellard
            d = ((d / (s->initial_count + 1)) + 1) * (s->initial_count + 1);
230 574bbf7b bellard
        } else {
231 574bbf7b bellard
            if (d >= s->initial_count)
232 574bbf7b bellard
                goto no_timer;
233 574bbf7b bellard
            d = s->initial_count + 1;
234 574bbf7b bellard
        }
235 574bbf7b bellard
        next_time = s->initial_count_load_time + (d << s->count_shift);
236 574bbf7b bellard
        qemu_mod_timer(s->timer, next_time);
237 574bbf7b bellard
        s->next_time = next_time;
238 574bbf7b bellard
    } else {
239 574bbf7b bellard
    no_timer:
240 574bbf7b bellard
        qemu_del_timer(s->timer);
241 574bbf7b bellard
    }
242 574bbf7b bellard
}
243 574bbf7b bellard
244 574bbf7b bellard
static void apic_timer(void *opaque)
245 574bbf7b bellard
{
246 574bbf7b bellard
    APICState *s = opaque;
247 574bbf7b bellard
248 574bbf7b bellard
    if (!(s->lvt[APIC_LVT_TIMER] & APIC_LVT_MASKED)) {
249 574bbf7b bellard
        apic_set_irq(s, s->lvt[APIC_LVT_TIMER] & 0xff, APIC_TRIGGER_EDGE);
250 574bbf7b bellard
    }
251 574bbf7b bellard
    apic_timer_update(s, s->next_time);
252 574bbf7b bellard
}
253 574bbf7b bellard
254 574bbf7b bellard
static uint32_t apic_mem_readb(void *opaque, target_phys_addr_t addr)
255 574bbf7b bellard
{
256 574bbf7b bellard
    return 0;
257 574bbf7b bellard
}
258 574bbf7b bellard
259 574bbf7b bellard
static uint32_t apic_mem_readw(void *opaque, target_phys_addr_t addr)
260 574bbf7b bellard
{
261 574bbf7b bellard
    return 0;
262 574bbf7b bellard
}
263 574bbf7b bellard
264 574bbf7b bellard
static void apic_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
265 574bbf7b bellard
{
266 574bbf7b bellard
}
267 574bbf7b bellard
268 574bbf7b bellard
static void apic_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
269 574bbf7b bellard
{
270 574bbf7b bellard
}
271 574bbf7b bellard
272 574bbf7b bellard
static uint32_t apic_mem_readl(void *opaque, target_phys_addr_t addr)
273 574bbf7b bellard
{
274 574bbf7b bellard
    CPUState *env;
275 574bbf7b bellard
    APICState *s;
276 574bbf7b bellard
    uint32_t val;
277 574bbf7b bellard
    int index;
278 574bbf7b bellard
279 574bbf7b bellard
    env = cpu_single_env;
280 574bbf7b bellard
    if (!env)
281 574bbf7b bellard
        return 0;
282 574bbf7b bellard
    s = env->apic_state;
283 574bbf7b bellard
284 574bbf7b bellard
    index = (addr >> 4) & 0xff;
285 574bbf7b bellard
    switch(index) {
286 574bbf7b bellard
    case 0x02: /* id */
287 574bbf7b bellard
        val = s->id << 24;
288 574bbf7b bellard
        break;
289 574bbf7b bellard
    case 0x03: /* version */
290 574bbf7b bellard
        val = 0x11 | ((APIC_LVT_NB - 1) << 16); /* version 0x11 */
291 574bbf7b bellard
        break;
292 574bbf7b bellard
    case 0x08:
293 574bbf7b bellard
        val = s->tpr;
294 574bbf7b bellard
        break;
295 574bbf7b bellard
    case 0x0a:
296 574bbf7b bellard
        /* ppr */
297 574bbf7b bellard
        val = apic_get_ppr(s);
298 574bbf7b bellard
        break;
299 574bbf7b bellard
    case 0x0f:
300 574bbf7b bellard
        val = s->spurious_vec;
301 574bbf7b bellard
        break;
302 574bbf7b bellard
    case 0x10 ... 0x17:
303 574bbf7b bellard
        val = s->isr[index & 7];
304 574bbf7b bellard
        break;
305 574bbf7b bellard
    case 0x18 ... 0x1f:
306 574bbf7b bellard
        val = s->tmr[index & 7];
307 574bbf7b bellard
        break;
308 574bbf7b bellard
    case 0x20 ... 0x27:
309 574bbf7b bellard
        val = s->irr[index & 7];
310 574bbf7b bellard
        break;
311 574bbf7b bellard
    case 0x28:
312 574bbf7b bellard
        val = s->esr;
313 574bbf7b bellard
        break;
314 574bbf7b bellard
    case 0x32 ... 0x37:
315 574bbf7b bellard
        val = s->lvt[index - 0x32];
316 574bbf7b bellard
        break;
317 574bbf7b bellard
    case 0x30:
318 574bbf7b bellard
    case 0x31:
319 574bbf7b bellard
        val = s->icr[index & 1];
320 574bbf7b bellard
        break;
321 574bbf7b bellard
    case 0x38:
322 574bbf7b bellard
        val = s->initial_count;
323 574bbf7b bellard
        break;
324 574bbf7b bellard
    case 0x39:
325 574bbf7b bellard
        val = apic_get_current_count(s);
326 574bbf7b bellard
        break;
327 574bbf7b bellard
    case 0x3e:
328 574bbf7b bellard
        val = s->divide_conf;
329 574bbf7b bellard
        break;
330 574bbf7b bellard
    default:
331 574bbf7b bellard
        s->esr |= ESR_ILLEGAL_ADDRESS;
332 574bbf7b bellard
        val = 0;
333 574bbf7b bellard
        break;
334 574bbf7b bellard
    }
335 574bbf7b bellard
#ifdef DEBUG_APIC
336 574bbf7b bellard
    printf("APIC read: %08x = %08x\n", (uint32_t)addr, val);
337 574bbf7b bellard
#endif
338 574bbf7b bellard
    return val;
339 574bbf7b bellard
}
340 574bbf7b bellard
341 574bbf7b bellard
static void apic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
342 574bbf7b bellard
{
343 574bbf7b bellard
    CPUState *env;
344 574bbf7b bellard
    APICState *s;
345 574bbf7b bellard
    int index;
346 574bbf7b bellard
347 574bbf7b bellard
    env = cpu_single_env;
348 574bbf7b bellard
    if (!env)
349 574bbf7b bellard
        return;
350 574bbf7b bellard
    s = env->apic_state;
351 574bbf7b bellard
352 574bbf7b bellard
#ifdef DEBUG_APIC
353 574bbf7b bellard
    printf("APIC write: %08x = %08x\n", (uint32_t)addr, val);
354 574bbf7b bellard
#endif
355 574bbf7b bellard
356 574bbf7b bellard
    index = (addr >> 4) & 0xff;
357 574bbf7b bellard
    switch(index) {
358 574bbf7b bellard
    case 0x02:
359 574bbf7b bellard
        s->id = (val >> 24);
360 574bbf7b bellard
        break;
361 574bbf7b bellard
    case 0x08:
362 574bbf7b bellard
        s->tpr = val;
363 574bbf7b bellard
        break;
364 574bbf7b bellard
    case 0x0b: /* EOI */
365 574bbf7b bellard
        apic_eoi(s);
366 574bbf7b bellard
        break;
367 574bbf7b bellard
    case 0x0f:
368 574bbf7b bellard
        s->spurious_vec = val & 0x1ff;
369 574bbf7b bellard
        break;
370 574bbf7b bellard
    case 0x30:
371 574bbf7b bellard
    case 0x31:
372 574bbf7b bellard
        s->icr[index & 1] = val;
373 574bbf7b bellard
        break;
374 574bbf7b bellard
    case 0x32 ... 0x37:
375 574bbf7b bellard
        {
376 574bbf7b bellard
            int n = index - 0x32;
377 574bbf7b bellard
            s->lvt[n] = val;
378 574bbf7b bellard
            if (n == APIC_LVT_TIMER)
379 574bbf7b bellard
                apic_timer_update(s, qemu_get_clock(vm_clock));
380 574bbf7b bellard
        }
381 574bbf7b bellard
        break;
382 574bbf7b bellard
    case 0x38:
383 574bbf7b bellard
        s->initial_count = val;
384 574bbf7b bellard
        s->initial_count_load_time = qemu_get_clock(vm_clock);
385 574bbf7b bellard
        apic_timer_update(s, s->initial_count_load_time);
386 574bbf7b bellard
        break;
387 574bbf7b bellard
    case 0x3e:
388 574bbf7b bellard
        {
389 574bbf7b bellard
            int v;
390 574bbf7b bellard
            s->divide_conf = val & 0xb;
391 574bbf7b bellard
            v = (s->divide_conf & 3) | ((s->divide_conf >> 1) & 4);
392 574bbf7b bellard
            s->count_shift = (v + 1) & 7;
393 574bbf7b bellard
        }
394 574bbf7b bellard
        break;
395 574bbf7b bellard
    default:
396 574bbf7b bellard
        s->esr |= ESR_ILLEGAL_ADDRESS;
397 574bbf7b bellard
        break;
398 574bbf7b bellard
    }
399 574bbf7b bellard
}
400 574bbf7b bellard
401 574bbf7b bellard
402 574bbf7b bellard
403 574bbf7b bellard
static CPUReadMemoryFunc *apic_mem_read[3] = {
404 574bbf7b bellard
    apic_mem_readb,
405 574bbf7b bellard
    apic_mem_readw,
406 574bbf7b bellard
    apic_mem_readl,
407 574bbf7b bellard
};
408 574bbf7b bellard
409 574bbf7b bellard
static CPUWriteMemoryFunc *apic_mem_write[3] = {
410 574bbf7b bellard
    apic_mem_writeb,
411 574bbf7b bellard
    apic_mem_writew,
412 574bbf7b bellard
    apic_mem_writel,
413 574bbf7b bellard
};
414 574bbf7b bellard
415 574bbf7b bellard
int apic_init(CPUState *env)
416 574bbf7b bellard
{
417 574bbf7b bellard
    APICState *s;
418 574bbf7b bellard
    int i;
419 574bbf7b bellard
420 574bbf7b bellard
    s = malloc(sizeof(APICState));
421 574bbf7b bellard
    if (!s)
422 574bbf7b bellard
        return -1;
423 574bbf7b bellard
    memset(s, 0, sizeof(*s));
424 574bbf7b bellard
    env->apic_state = s;
425 574bbf7b bellard
    s->cpu_env = env;
426 574bbf7b bellard
    s->apicbase = 0xfee00000 | 
427 574bbf7b bellard
        MSR_IA32_APICBASE_BSP | MSR_IA32_APICBASE_ENABLE;
428 574bbf7b bellard
    for(i = 0; i < APIC_LVT_NB; i++)
429 574bbf7b bellard
        s->lvt[i] = 1 << 16; /* mask LVT */
430 574bbf7b bellard
    s->spurious_vec = 0xff;
431 574bbf7b bellard
432 574bbf7b bellard
    if (apic_io_memory == 0) {
433 574bbf7b bellard
        /* NOTE: the APIC is directly connected to the CPU - it is not
434 574bbf7b bellard
           on the global memory bus. */
435 574bbf7b bellard
        apic_io_memory = cpu_register_io_memory(0, apic_mem_read, 
436 574bbf7b bellard
                                                apic_mem_write, NULL);
437 574bbf7b bellard
        cpu_register_physical_memory(s->apicbase & ~0xfff, 0x1000, apic_io_memory);
438 574bbf7b bellard
    }
439 574bbf7b bellard
    s->timer = qemu_new_timer(vm_clock, apic_timer, s);
440 574bbf7b bellard
    return 0;
441 574bbf7b bellard
}