Statistics
| Branch: | Revision:

root / hw / apic.c @ a8d3431a

History | View | Annotate | Download (10.7 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 9230e66e bellard
void cpu_set_apic_tpr(CPUX86State *env, uint8_t val)
104 9230e66e bellard
{
105 9230e66e bellard
    APICState *s = env->apic_state;
106 9230e66e bellard
    s->tpr = (val & 0x0f) << 4;
107 9230e66e bellard
}
108 9230e66e bellard
109 9230e66e bellard
uint8_t cpu_get_apic_tpr(CPUX86State *env)
110 9230e66e bellard
{
111 9230e66e bellard
    APICState *s = env->apic_state;
112 9230e66e bellard
    return s->tpr >> 4;
113 9230e66e bellard
}
114 9230e66e bellard
115 574bbf7b bellard
/* return -1 if no bit is set */
116 574bbf7b bellard
static int get_highest_priority_int(uint32_t *tab)
117 574bbf7b bellard
{
118 574bbf7b bellard
    int i;
119 574bbf7b bellard
    for(i = 0;i < 8; i++) {
120 574bbf7b bellard
        if (tab[i] != 0) {
121 574bbf7b bellard
            return i * 32 + ffs(tab[i]) - 1;
122 574bbf7b bellard
        }
123 574bbf7b bellard
    }
124 574bbf7b bellard
    return -1;
125 574bbf7b bellard
}
126 574bbf7b bellard
127 574bbf7b bellard
static inline void set_bit(uint32_t *tab, int index)
128 574bbf7b bellard
{
129 574bbf7b bellard
    int i, mask;
130 574bbf7b bellard
    i = index >> 5;
131 574bbf7b bellard
    mask = 1 << (index & 0x1f);
132 574bbf7b bellard
    tab[i] |= mask;
133 574bbf7b bellard
}
134 574bbf7b bellard
135 574bbf7b bellard
static inline void reset_bit(uint32_t *tab, int index)
136 574bbf7b bellard
{
137 574bbf7b bellard
    int i, mask;
138 574bbf7b bellard
    i = index >> 5;
139 574bbf7b bellard
    mask = 1 << (index & 0x1f);
140 574bbf7b bellard
    tab[i] &= ~mask;
141 574bbf7b bellard
}
142 574bbf7b bellard
143 574bbf7b bellard
static int apic_get_ppr(APICState *s)
144 574bbf7b bellard
{
145 574bbf7b bellard
    int tpr, isrv, ppr;
146 574bbf7b bellard
147 574bbf7b bellard
    tpr = (s->tpr >> 4);
148 574bbf7b bellard
    isrv = get_highest_priority_int(s->isr);
149 574bbf7b bellard
    if (isrv < 0)
150 574bbf7b bellard
        isrv = 0;
151 574bbf7b bellard
    isrv >>= 4;
152 574bbf7b bellard
    if (tpr >= isrv)
153 574bbf7b bellard
        ppr = s->tpr;
154 574bbf7b bellard
    else
155 574bbf7b bellard
        ppr = isrv << 4;
156 574bbf7b bellard
    return ppr;
157 574bbf7b bellard
}
158 574bbf7b bellard
159 574bbf7b bellard
/* signal the CPU if an irq is pending */
160 574bbf7b bellard
static void apic_update_irq(APICState *s)
161 574bbf7b bellard
{
162 574bbf7b bellard
    int irrv, isrv;
163 574bbf7b bellard
    irrv = get_highest_priority_int(s->irr);
164 574bbf7b bellard
    if (irrv < 0)
165 574bbf7b bellard
        return;
166 574bbf7b bellard
    isrv = get_highest_priority_int(s->isr);
167 574bbf7b bellard
    /* if the pending irq has less priority, we do not make a new request */
168 574bbf7b bellard
    if (isrv >= 0 && irrv >= isrv)
169 574bbf7b bellard
        return;
170 574bbf7b bellard
    cpu_interrupt(s->cpu_env, CPU_INTERRUPT_HARD);
171 574bbf7b bellard
}
172 574bbf7b bellard
173 574bbf7b bellard
static void apic_set_irq(APICState *s, int vector_num, int trigger_mode)
174 574bbf7b bellard
{
175 574bbf7b bellard
    set_bit(s->irr, vector_num);
176 574bbf7b bellard
    if (trigger_mode)
177 574bbf7b bellard
        set_bit(s->tmr, vector_num);
178 574bbf7b bellard
    else
179 574bbf7b bellard
        reset_bit(s->tmr, vector_num);
180 574bbf7b bellard
    apic_update_irq(s);
181 574bbf7b bellard
}
182 574bbf7b bellard
183 574bbf7b bellard
static void apic_eoi(APICState *s)
184 574bbf7b bellard
{
185 574bbf7b bellard
    int isrv;
186 574bbf7b bellard
    isrv = get_highest_priority_int(s->isr);
187 574bbf7b bellard
    if (isrv < 0)
188 574bbf7b bellard
        return;
189 574bbf7b bellard
    reset_bit(s->isr, isrv);
190 574bbf7b bellard
    apic_update_irq(s);
191 574bbf7b bellard
}
192 574bbf7b bellard
193 574bbf7b bellard
int apic_get_interrupt(CPUState *env)
194 574bbf7b bellard
{
195 574bbf7b bellard
    APICState *s = env->apic_state;
196 574bbf7b bellard
    int intno;
197 574bbf7b bellard
198 574bbf7b bellard
    /* if the APIC is installed or enabled, we let the 8259 handle the
199 574bbf7b bellard
       IRQs */
200 574bbf7b bellard
    if (!s)
201 574bbf7b bellard
        return -1;
202 574bbf7b bellard
    if (!(s->spurious_vec & APIC_SV_ENABLE))
203 574bbf7b bellard
        return -1;
204 574bbf7b bellard
    
205 574bbf7b bellard
    /* XXX: spurious IRQ handling */
206 574bbf7b bellard
    intno = get_highest_priority_int(s->irr);
207 574bbf7b bellard
    if (intno < 0)
208 574bbf7b bellard
        return -1;
209 574bbf7b bellard
    reset_bit(s->irr, intno);
210 574bbf7b bellard
    set_bit(s->isr, intno);
211 574bbf7b bellard
    apic_update_irq(s);
212 574bbf7b bellard
    return intno;
213 574bbf7b bellard
}
214 574bbf7b bellard
215 574bbf7b bellard
static uint32_t apic_get_current_count(APICState *s)
216 574bbf7b bellard
{
217 574bbf7b bellard
    int64_t d;
218 574bbf7b bellard
    uint32_t val;
219 574bbf7b bellard
    d = (qemu_get_clock(vm_clock) - s->initial_count_load_time) >> 
220 574bbf7b bellard
        s->count_shift;
221 574bbf7b bellard
    if (s->lvt[APIC_LVT_TIMER] & APIC_LVT_TIMER_PERIODIC) {
222 574bbf7b bellard
        /* periodic */
223 574bbf7b bellard
        val = s->initial_count - (d % (s->initial_count + 1));
224 574bbf7b bellard
    } else {
225 574bbf7b bellard
        if (d >= s->initial_count)
226 574bbf7b bellard
            val = 0;
227 574bbf7b bellard
        else
228 574bbf7b bellard
            val = s->initial_count - d;
229 574bbf7b bellard
    }
230 574bbf7b bellard
    return val;
231 574bbf7b bellard
}
232 574bbf7b bellard
233 574bbf7b bellard
static void apic_timer_update(APICState *s, int64_t current_time)
234 574bbf7b bellard
{
235 574bbf7b bellard
    int64_t next_time, d;
236 574bbf7b bellard
    
237 574bbf7b bellard
    if (!(s->lvt[APIC_LVT_TIMER] & APIC_LVT_MASKED)) {
238 574bbf7b bellard
        d = (current_time - s->initial_count_load_time) >> 
239 574bbf7b bellard
            s->count_shift;
240 574bbf7b bellard
        if (s->lvt[APIC_LVT_TIMER] & APIC_LVT_TIMER_PERIODIC) {
241 574bbf7b bellard
            d = ((d / (s->initial_count + 1)) + 1) * (s->initial_count + 1);
242 574bbf7b bellard
        } else {
243 574bbf7b bellard
            if (d >= s->initial_count)
244 574bbf7b bellard
                goto no_timer;
245 574bbf7b bellard
            d = s->initial_count + 1;
246 574bbf7b bellard
        }
247 574bbf7b bellard
        next_time = s->initial_count_load_time + (d << s->count_shift);
248 574bbf7b bellard
        qemu_mod_timer(s->timer, next_time);
249 574bbf7b bellard
        s->next_time = next_time;
250 574bbf7b bellard
    } else {
251 574bbf7b bellard
    no_timer:
252 574bbf7b bellard
        qemu_del_timer(s->timer);
253 574bbf7b bellard
    }
254 574bbf7b bellard
}
255 574bbf7b bellard
256 574bbf7b bellard
static void apic_timer(void *opaque)
257 574bbf7b bellard
{
258 574bbf7b bellard
    APICState *s = opaque;
259 574bbf7b bellard
260 574bbf7b bellard
    if (!(s->lvt[APIC_LVT_TIMER] & APIC_LVT_MASKED)) {
261 574bbf7b bellard
        apic_set_irq(s, s->lvt[APIC_LVT_TIMER] & 0xff, APIC_TRIGGER_EDGE);
262 574bbf7b bellard
    }
263 574bbf7b bellard
    apic_timer_update(s, s->next_time);
264 574bbf7b bellard
}
265 574bbf7b bellard
266 574bbf7b bellard
static uint32_t apic_mem_readb(void *opaque, target_phys_addr_t addr)
267 574bbf7b bellard
{
268 574bbf7b bellard
    return 0;
269 574bbf7b bellard
}
270 574bbf7b bellard
271 574bbf7b bellard
static uint32_t apic_mem_readw(void *opaque, target_phys_addr_t addr)
272 574bbf7b bellard
{
273 574bbf7b bellard
    return 0;
274 574bbf7b bellard
}
275 574bbf7b bellard
276 574bbf7b bellard
static void apic_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
277 574bbf7b bellard
{
278 574bbf7b bellard
}
279 574bbf7b bellard
280 574bbf7b bellard
static void apic_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
281 574bbf7b bellard
{
282 574bbf7b bellard
}
283 574bbf7b bellard
284 574bbf7b bellard
static uint32_t apic_mem_readl(void *opaque, target_phys_addr_t addr)
285 574bbf7b bellard
{
286 574bbf7b bellard
    CPUState *env;
287 574bbf7b bellard
    APICState *s;
288 574bbf7b bellard
    uint32_t val;
289 574bbf7b bellard
    int index;
290 574bbf7b bellard
291 574bbf7b bellard
    env = cpu_single_env;
292 574bbf7b bellard
    if (!env)
293 574bbf7b bellard
        return 0;
294 574bbf7b bellard
    s = env->apic_state;
295 574bbf7b bellard
296 574bbf7b bellard
    index = (addr >> 4) & 0xff;
297 574bbf7b bellard
    switch(index) {
298 574bbf7b bellard
    case 0x02: /* id */
299 574bbf7b bellard
        val = s->id << 24;
300 574bbf7b bellard
        break;
301 574bbf7b bellard
    case 0x03: /* version */
302 574bbf7b bellard
        val = 0x11 | ((APIC_LVT_NB - 1) << 16); /* version 0x11 */
303 574bbf7b bellard
        break;
304 574bbf7b bellard
    case 0x08:
305 574bbf7b bellard
        val = s->tpr;
306 574bbf7b bellard
        break;
307 574bbf7b bellard
    case 0x0a:
308 574bbf7b bellard
        /* ppr */
309 574bbf7b bellard
        val = apic_get_ppr(s);
310 574bbf7b bellard
        break;
311 574bbf7b bellard
    case 0x0f:
312 574bbf7b bellard
        val = s->spurious_vec;
313 574bbf7b bellard
        break;
314 574bbf7b bellard
    case 0x10 ... 0x17:
315 574bbf7b bellard
        val = s->isr[index & 7];
316 574bbf7b bellard
        break;
317 574bbf7b bellard
    case 0x18 ... 0x1f:
318 574bbf7b bellard
        val = s->tmr[index & 7];
319 574bbf7b bellard
        break;
320 574bbf7b bellard
    case 0x20 ... 0x27:
321 574bbf7b bellard
        val = s->irr[index & 7];
322 574bbf7b bellard
        break;
323 574bbf7b bellard
    case 0x28:
324 574bbf7b bellard
        val = s->esr;
325 574bbf7b bellard
        break;
326 574bbf7b bellard
    case 0x32 ... 0x37:
327 574bbf7b bellard
        val = s->lvt[index - 0x32];
328 574bbf7b bellard
        break;
329 574bbf7b bellard
    case 0x30:
330 574bbf7b bellard
    case 0x31:
331 574bbf7b bellard
        val = s->icr[index & 1];
332 574bbf7b bellard
        break;
333 574bbf7b bellard
    case 0x38:
334 574bbf7b bellard
        val = s->initial_count;
335 574bbf7b bellard
        break;
336 574bbf7b bellard
    case 0x39:
337 574bbf7b bellard
        val = apic_get_current_count(s);
338 574bbf7b bellard
        break;
339 574bbf7b bellard
    case 0x3e:
340 574bbf7b bellard
        val = s->divide_conf;
341 574bbf7b bellard
        break;
342 574bbf7b bellard
    default:
343 574bbf7b bellard
        s->esr |= ESR_ILLEGAL_ADDRESS;
344 574bbf7b bellard
        val = 0;
345 574bbf7b bellard
        break;
346 574bbf7b bellard
    }
347 574bbf7b bellard
#ifdef DEBUG_APIC
348 574bbf7b bellard
    printf("APIC read: %08x = %08x\n", (uint32_t)addr, val);
349 574bbf7b bellard
#endif
350 574bbf7b bellard
    return val;
351 574bbf7b bellard
}
352 574bbf7b bellard
353 574bbf7b bellard
static void apic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
354 574bbf7b bellard
{
355 574bbf7b bellard
    CPUState *env;
356 574bbf7b bellard
    APICState *s;
357 574bbf7b bellard
    int index;
358 574bbf7b bellard
359 574bbf7b bellard
    env = cpu_single_env;
360 574bbf7b bellard
    if (!env)
361 574bbf7b bellard
        return;
362 574bbf7b bellard
    s = env->apic_state;
363 574bbf7b bellard
364 574bbf7b bellard
#ifdef DEBUG_APIC
365 574bbf7b bellard
    printf("APIC write: %08x = %08x\n", (uint32_t)addr, val);
366 574bbf7b bellard
#endif
367 574bbf7b bellard
368 574bbf7b bellard
    index = (addr >> 4) & 0xff;
369 574bbf7b bellard
    switch(index) {
370 574bbf7b bellard
    case 0x02:
371 574bbf7b bellard
        s->id = (val >> 24);
372 574bbf7b bellard
        break;
373 574bbf7b bellard
    case 0x08:
374 574bbf7b bellard
        s->tpr = val;
375 574bbf7b bellard
        break;
376 574bbf7b bellard
    case 0x0b: /* EOI */
377 574bbf7b bellard
        apic_eoi(s);
378 574bbf7b bellard
        break;
379 574bbf7b bellard
    case 0x0f:
380 574bbf7b bellard
        s->spurious_vec = val & 0x1ff;
381 574bbf7b bellard
        break;
382 574bbf7b bellard
    case 0x30:
383 574bbf7b bellard
    case 0x31:
384 574bbf7b bellard
        s->icr[index & 1] = val;
385 574bbf7b bellard
        break;
386 574bbf7b bellard
    case 0x32 ... 0x37:
387 574bbf7b bellard
        {
388 574bbf7b bellard
            int n = index - 0x32;
389 574bbf7b bellard
            s->lvt[n] = val;
390 574bbf7b bellard
            if (n == APIC_LVT_TIMER)
391 574bbf7b bellard
                apic_timer_update(s, qemu_get_clock(vm_clock));
392 574bbf7b bellard
        }
393 574bbf7b bellard
        break;
394 574bbf7b bellard
    case 0x38:
395 574bbf7b bellard
        s->initial_count = val;
396 574bbf7b bellard
        s->initial_count_load_time = qemu_get_clock(vm_clock);
397 574bbf7b bellard
        apic_timer_update(s, s->initial_count_load_time);
398 574bbf7b bellard
        break;
399 574bbf7b bellard
    case 0x3e:
400 574bbf7b bellard
        {
401 574bbf7b bellard
            int v;
402 574bbf7b bellard
            s->divide_conf = val & 0xb;
403 574bbf7b bellard
            v = (s->divide_conf & 3) | ((s->divide_conf >> 1) & 4);
404 574bbf7b bellard
            s->count_shift = (v + 1) & 7;
405 574bbf7b bellard
        }
406 574bbf7b bellard
        break;
407 574bbf7b bellard
    default:
408 574bbf7b bellard
        s->esr |= ESR_ILLEGAL_ADDRESS;
409 574bbf7b bellard
        break;
410 574bbf7b bellard
    }
411 574bbf7b bellard
}
412 574bbf7b bellard
413 574bbf7b bellard
414 574bbf7b bellard
415 574bbf7b bellard
static CPUReadMemoryFunc *apic_mem_read[3] = {
416 574bbf7b bellard
    apic_mem_readb,
417 574bbf7b bellard
    apic_mem_readw,
418 574bbf7b bellard
    apic_mem_readl,
419 574bbf7b bellard
};
420 574bbf7b bellard
421 574bbf7b bellard
static CPUWriteMemoryFunc *apic_mem_write[3] = {
422 574bbf7b bellard
    apic_mem_writeb,
423 574bbf7b bellard
    apic_mem_writew,
424 574bbf7b bellard
    apic_mem_writel,
425 574bbf7b bellard
};
426 574bbf7b bellard
427 574bbf7b bellard
int apic_init(CPUState *env)
428 574bbf7b bellard
{
429 574bbf7b bellard
    APICState *s;
430 574bbf7b bellard
    int i;
431 574bbf7b bellard
432 574bbf7b bellard
    s = malloc(sizeof(APICState));
433 574bbf7b bellard
    if (!s)
434 574bbf7b bellard
        return -1;
435 574bbf7b bellard
    memset(s, 0, sizeof(*s));
436 574bbf7b bellard
    env->apic_state = s;
437 574bbf7b bellard
    s->cpu_env = env;
438 574bbf7b bellard
    s->apicbase = 0xfee00000 | 
439 574bbf7b bellard
        MSR_IA32_APICBASE_BSP | MSR_IA32_APICBASE_ENABLE;
440 574bbf7b bellard
    for(i = 0; i < APIC_LVT_NB; i++)
441 574bbf7b bellard
        s->lvt[i] = 1 << 16; /* mask LVT */
442 574bbf7b bellard
    s->spurious_vec = 0xff;
443 574bbf7b bellard
444 574bbf7b bellard
    if (apic_io_memory == 0) {
445 574bbf7b bellard
        /* NOTE: the APIC is directly connected to the CPU - it is not
446 574bbf7b bellard
           on the global memory bus. */
447 574bbf7b bellard
        apic_io_memory = cpu_register_io_memory(0, apic_mem_read, 
448 574bbf7b bellard
                                                apic_mem_write, NULL);
449 574bbf7b bellard
        cpu_register_physical_memory(s->apicbase & ~0xfff, 0x1000, apic_io_memory);
450 574bbf7b bellard
    }
451 574bbf7b bellard
    s->timer = qemu_new_timer(vm_clock, apic_timer, s);
452 574bbf7b bellard
    return 0;
453 574bbf7b bellard
}