apic.c 26.0 KB
Newer Older
B
bellard 已提交
1 2
/*
 *  APIC support
3
 *
B
bellard 已提交
4 5 6 7 8 9 10 11 12 13 14 15 16
 *  Copyright (c) 2004-2005 Fabrice Bellard
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library; if not, see <http://www.gnu.org/licenses/>
B
bellard 已提交
18
 */
P
pbrook 已提交
19 20
#include "hw.h"
#include "pc.h"
21 22
#include "pci.h"
#include "msix.h"
P
pbrook 已提交
23
#include "qemu-timer.h"
24
#include "host-utils.h"
J
Jan Kiszka 已提交
25
#include "kvm.h"
B
bellard 已提交
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46

//#define DEBUG_APIC

/* APIC Local Vector Table */
#define APIC_LVT_TIMER   0
#define APIC_LVT_THERMAL 1
#define APIC_LVT_PERFORM 2
#define APIC_LVT_LINT0   3
#define APIC_LVT_LINT1   4
#define APIC_LVT_ERROR   5
#define APIC_LVT_NB      6

/* APIC delivery modes */
#define APIC_DM_FIXED	0
#define APIC_DM_LOWPRI	1
#define APIC_DM_SMI	2
#define APIC_DM_NMI	4
#define APIC_DM_INIT	5
#define APIC_DM_SIPI	6
#define APIC_DM_EXTINT	7

47 48 49 50
/* APIC destination mode */
#define APIC_DESTMODE_FLAT	0xf
#define APIC_DESTMODE_CLUSTER	1

B
bellard 已提交
51 52 53 54 55 56 57 58 59 60 61 62 63 64
#define APIC_TRIGGER_EDGE  0
#define APIC_TRIGGER_LEVEL 1

#define	APIC_LVT_TIMER_PERIODIC		(1<<17)
#define	APIC_LVT_MASKED			(1<<16)
#define	APIC_LVT_LEVEL_TRIGGER		(1<<15)
#define	APIC_LVT_REMOTE_IRR		(1<<14)
#define	APIC_INPUT_POLARITY		(1<<13)
#define	APIC_SEND_PENDING		(1<<12)

#define ESR_ILLEGAL_ADDRESS (1 << 7)

#define APIC_SV_ENABLE (1 << 8)

B
bellard 已提交
65 66 67
#define MAX_APICS 255
#define MAX_APIC_WORDS 8

68 69 70 71 72 73 74 75 76 77 78 79 80
/* Intel APIC constants: from include/asm/msidef.h */
#define MSI_DATA_VECTOR_SHIFT		0
#define MSI_DATA_VECTOR_MASK		0x000000ff
#define MSI_DATA_DELIVERY_MODE_SHIFT	8
#define MSI_DATA_TRIGGER_SHIFT		15
#define MSI_DATA_LEVEL_SHIFT		14
#define MSI_ADDR_DEST_MODE_SHIFT	2
#define MSI_ADDR_DEST_ID_SHIFT		12
#define	MSI_ADDR_DEST_ID_MASK		0x00ffff0

#define MSI_ADDR_BASE                   0xfee00000
#define MSI_ADDR_SIZE                   0x100000

B
bellard 已提交
81 82 83 84
typedef struct APICState {
    CPUState *cpu_env;
    uint32_t apicbase;
    uint8_t id;
85
    uint8_t arb_id;
B
bellard 已提交
86 87
    uint8_t tpr;
    uint32_t spurious_vec;
88 89
    uint8_t log_dest;
    uint8_t dest_mode;
B
bellard 已提交
90 91 92 93 94 95 96 97 98 99 100
    uint32_t isr[8];  /* in service register */
    uint32_t tmr[8];  /* trigger mode register */
    uint32_t irr[8]; /* interrupt request register */
    uint32_t lvt[APIC_LVT_NB];
    uint32_t esr; /* error register */
    uint32_t icr[2];

    uint32_t divide_conf;
    int count_shift;
    uint32_t initial_count;
    int64_t initial_count_load_time, next_time;
G
Gleb Natapov 已提交
101
    uint32_t idx;
B
bellard 已提交
102
    QEMUTimer *timer;
103 104
    int sipi_vector;
    int wait_for_sipi;
B
bellard 已提交
105 106 107
} APICState;

static int apic_io_memory;
B
bellard 已提交
108
static APICState *local_apics[MAX_APICS + 1];
G
Gleb Natapov 已提交
109
static int last_apic_idx = 0;
110 111
static int apic_irq_delivered;

112 113 114

static void apic_set_irq(APICState *s, int vector_num, int trigger_mode);
static void apic_update_irq(APICState *s);
115 116
static void apic_get_delivery_bitmask(uint32_t *deliver_bitmask,
                                      uint8_t dest, uint8_t dest_mode);
117

118 119 120 121 122 123
/* Find first bit starting from msb */
static int fls_bit(uint32_t value)
{
    return 31 - clz32(value);
}

124
/* Find first bit starting from lsb */
B
bellard 已提交
125 126
static int ffs_bit(uint32_t value)
{
127
    return ctz32(value);
B
bellard 已提交
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
}

static inline void set_bit(uint32_t *tab, int index)
{
    int i, mask;
    i = index >> 5;
    mask = 1 << (index & 0x1f);
    tab[i] |= mask;
}

static inline void reset_bit(uint32_t *tab, int index)
{
    int i, mask;
    i = index >> 5;
    mask = 1 << (index & 0x1f);
    tab[i] &= ~mask;
}

146 147 148 149 150 151 152 153
static inline int get_bit(uint32_t *tab, int index)
{
    int i, mask;
    i = index >> 5;
    mask = 1 << (index & 0x1f);
    return !!(tab[i] & mask);
}

154
static void apic_local_deliver(CPUState *env, int vector)
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
{
    APICState *s = env->apic_state;
    uint32_t lvt = s->lvt[vector];
    int trigger_mode;

    if (lvt & APIC_LVT_MASKED)
        return;

    switch ((lvt >> 8) & 7) {
    case APIC_DM_SMI:
        cpu_interrupt(env, CPU_INTERRUPT_SMI);
        break;

    case APIC_DM_NMI:
        cpu_interrupt(env, CPU_INTERRUPT_NMI);
        break;

    case APIC_DM_EXTINT:
        cpu_interrupt(env, CPU_INTERRUPT_HARD);
        break;

    case APIC_DM_FIXED:
        trigger_mode = APIC_TRIGGER_EDGE;
        if ((vector == APIC_LVT_LINT0 || vector == APIC_LVT_LINT1) &&
            (lvt & APIC_LVT_LEVEL_TRIGGER))
            trigger_mode = APIC_TRIGGER_LEVEL;
        apic_set_irq(s, lvt & 0xff, trigger_mode);
    }
}

185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
void apic_deliver_pic_intr(CPUState *env, int level)
{
    if (level)
        apic_local_deliver(env, APIC_LVT_LINT0);
    else {
        APICState *s = env->apic_state;
        uint32_t lvt = s->lvt[APIC_LVT_LINT0];

        switch ((lvt >> 8) & 7) {
        case APIC_DM_FIXED:
            if (!(lvt & APIC_LVT_LEVEL_TRIGGER))
                break;
            reset_bit(s->irr, lvt & 0xff);
            /* fall through */
        case APIC_DM_EXTINT:
            cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
            break;
        }
    }
}

B
bellard 已提交
206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
#define foreach_apic(apic, deliver_bitmask, code) \
{\
    int __i, __j, __mask;\
    for(__i = 0; __i < MAX_APIC_WORDS; __i++) {\
        __mask = deliver_bitmask[__i];\
        if (__mask) {\
            for(__j = 0; __j < 32; __j++) {\
                if (__mask & (1 << __j)) {\
                    apic = local_apics[__i * 32 + __j];\
                    if (apic) {\
                        code;\
                    }\
                }\
            }\
        }\
    }\
}

224
static void apic_bus_deliver(const uint32_t *deliver_bitmask,
B
bellard 已提交
225
                             uint8_t delivery_mode,
226 227 228 229 230 231 232
                             uint8_t vector_num, uint8_t polarity,
                             uint8_t trigger_mode)
{
    APICState *apic_iter;

    switch (delivery_mode) {
        case APIC_DM_LOWPRI:
B
bellard 已提交
233
            /* XXX: search for focus processor, arbitration */
B
bellard 已提交
234 235 236 237 238 239 240 241 242 243 244 245 246 247 248
            {
                int i, d;
                d = -1;
                for(i = 0; i < MAX_APIC_WORDS; i++) {
                    if (deliver_bitmask[i]) {
                        d = i * 32 + ffs_bit(deliver_bitmask[i]);
                        break;
                    }
                }
                if (d >= 0) {
                    apic_iter = local_apics[d];
                    if (apic_iter) {
                        apic_set_irq(apic_iter, vector_num, trigger_mode);
                    }
                }
B
bellard 已提交
249
            }
B
bellard 已提交
250
            return;
B
bellard 已提交
251

252 253 254 255
        case APIC_DM_FIXED:
            break;

        case APIC_DM_SMI:
A
aurel32 已提交
256 257 258 259
            foreach_apic(apic_iter, deliver_bitmask,
                cpu_interrupt(apic_iter->cpu_env, CPU_INTERRUPT_SMI) );
            return;

260
        case APIC_DM_NMI:
A
aurel32 已提交
261 262 263
            foreach_apic(apic_iter, deliver_bitmask,
                cpu_interrupt(apic_iter->cpu_env, CPU_INTERRUPT_NMI) );
            return;
264 265 266

        case APIC_DM_INIT:
            /* normal INIT IPI sent to processors */
267
            foreach_apic(apic_iter, deliver_bitmask,
268
                         cpu_interrupt(apic_iter->cpu_env, CPU_INTERRUPT_INIT) );
269
            return;
270

271
        case APIC_DM_EXTINT:
272
            /* handled in I/O APIC code */
273 274 275 276 277 278
            break;

        default:
            return;
    }

279
    foreach_apic(apic_iter, deliver_bitmask,
B
bellard 已提交
280
                 apic_set_irq(apic_iter, vector_num, trigger_mode) );
281
}
B
bellard 已提交
282

283 284 285 286 287 288 289 290 291 292 293
void apic_deliver_irq(uint8_t dest, uint8_t dest_mode,
                      uint8_t delivery_mode, uint8_t vector_num,
                      uint8_t polarity, uint8_t trigger_mode)
{
    uint32_t deliver_bitmask[MAX_APIC_WORDS];

    apic_get_delivery_bitmask(deliver_bitmask, dest, dest_mode);
    apic_bus_deliver(deliver_bitmask, delivery_mode, vector_num, polarity,
                     trigger_mode);
}

B
bellard 已提交
294 295 296 297
void cpu_set_apic_base(CPUState *env, uint64_t val)
{
    APICState *s = env->apic_state;
#ifdef DEBUG_APIC
B
bellard 已提交
298
    printf("cpu_set_apic_base: %016" PRIx64 "\n", val);
B
bellard 已提交
299
#endif
A
aurel32 已提交
300 301
    if (!s)
        return;
302
    s->apicbase = (val & 0xfffff000) |
B
bellard 已提交
303 304 305 306 307 308 309 310 311 312 313 314 315
        (s->apicbase & (MSR_IA32_APICBASE_BSP | MSR_IA32_APICBASE_ENABLE));
    /* if disabled, cannot be enabled again */
    if (!(val & MSR_IA32_APICBASE_ENABLE)) {
        s->apicbase &= ~MSR_IA32_APICBASE_ENABLE;
        env->cpuid_features &= ~CPUID_APIC;
        s->spurious_vec &= ~APIC_SV_ENABLE;
    }
}

uint64_t cpu_get_apic_base(CPUState *env)
{
    APICState *s = env->apic_state;
#ifdef DEBUG_APIC
A
aurel32 已提交
316 317
    printf("cpu_get_apic_base: %016" PRIx64 "\n",
           s ? (uint64_t)s->apicbase: 0);
B
bellard 已提交
318
#endif
A
aurel32 已提交
319
    return s ? s->apicbase : 0;
B
bellard 已提交
320 321
}

B
bellard 已提交
322 323 324
void cpu_set_apic_tpr(CPUX86State *env, uint8_t val)
{
    APICState *s = env->apic_state;
A
aurel32 已提交
325 326
    if (!s)
        return;
B
bellard 已提交
327
    s->tpr = (val & 0x0f) << 4;
328
    apic_update_irq(s);
B
bellard 已提交
329 330 331 332 333
}

uint8_t cpu_get_apic_tpr(CPUX86State *env)
{
    APICState *s = env->apic_state;
A
aurel32 已提交
334
    return s ? s->tpr >> 4 : 0;
B
bellard 已提交
335 336
}

337 338 339 340 341 342
/* return -1 if no bit is set */
static int get_highest_priority_int(uint32_t *tab)
{
    int i;
    for(i = 7; i >= 0; i--) {
        if (tab[i] != 0) {
343
            return i * 32 + fls_bit(tab[i]);
344 345 346 347 348
        }
    }
    return -1;
}

B
bellard 已提交
349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364
static int apic_get_ppr(APICState *s)
{
    int tpr, isrv, ppr;

    tpr = (s->tpr >> 4);
    isrv = get_highest_priority_int(s->isr);
    if (isrv < 0)
        isrv = 0;
    isrv >>= 4;
    if (tpr >= isrv)
        ppr = s->tpr;
    else
        ppr = isrv << 4;
    return ppr;
}

365 366 367 368 369 370
static int apic_get_arb_pri(APICState *s)
{
    /* XXX: arbitration */
    return 0;
}

B
bellard 已提交
371 372 373
/* signal the CPU if an irq is pending */
static void apic_update_irq(APICState *s)
{
374 375 376
    int irrv, ppr;
    if (!(s->spurious_vec & APIC_SV_ENABLE))
        return;
B
bellard 已提交
377 378 379
    irrv = get_highest_priority_int(s->irr);
    if (irrv < 0)
        return;
380 381
    ppr = apic_get_ppr(s);
    if (ppr && (irrv & 0xf0) <= (ppr & 0xf0))
B
bellard 已提交
382 383 384 385
        return;
    cpu_interrupt(s->cpu_env, CPU_INTERRUPT_HARD);
}

386 387 388 389 390 391 392 393 394 395
void apic_reset_irq_delivered(void)
{
    apic_irq_delivered = 0;
}

int apic_get_irq_delivered(void)
{
    return apic_irq_delivered;
}

B
bellard 已提交
396 397
static void apic_set_irq(APICState *s, int vector_num, int trigger_mode)
{
398 399
    apic_irq_delivered += !get_bit(s->irr, vector_num);

B
bellard 已提交
400 401 402 403 404 405 406 407 408 409 410 411 412 413 414
    set_bit(s->irr, vector_num);
    if (trigger_mode)
        set_bit(s->tmr, vector_num);
    else
        reset_bit(s->tmr, vector_num);
    apic_update_irq(s);
}

static void apic_eoi(APICState *s)
{
    int isrv;
    isrv = get_highest_priority_int(s->isr);
    if (isrv < 0)
        return;
    reset_bit(s->isr, isrv);
415 416
    /* XXX: send the EOI packet to the APIC bus to allow the I/O APIC to
            set the remote IRR bit for level triggered interrupts. */
B
bellard 已提交
417 418 419
    apic_update_irq(s);
}

G
Gleb Natapov 已提交
420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436
static int apic_find_dest(uint8_t dest)
{
    APICState *apic = local_apics[dest];
    int i;

    if (apic && apic->id == dest)
        return dest;  /* shortcut in case apic->id == apic->idx */

    for (i = 0; i < MAX_APICS; i++) {
        apic = local_apics[i];
	if (apic && apic->id == dest)
            return i;
    }

    return -1;
}

B
bellard 已提交
437 438
static void apic_get_delivery_bitmask(uint32_t *deliver_bitmask,
                                      uint8_t dest, uint8_t dest_mode)
439 440
{
    APICState *apic_iter;
B
bellard 已提交
441
    int i;
442 443

    if (dest_mode == 0) {
B
bellard 已提交
444 445 446
        if (dest == 0xff) {
            memset(deliver_bitmask, 0xff, MAX_APIC_WORDS * sizeof(uint32_t));
        } else {
G
Gleb Natapov 已提交
447
            int idx = apic_find_dest(dest);
B
bellard 已提交
448
            memset(deliver_bitmask, 0x00, MAX_APIC_WORDS * sizeof(uint32_t));
G
Gleb Natapov 已提交
449 450
            if (idx >= 0)
                set_bit(deliver_bitmask, idx);
B
bellard 已提交
451
        }
452 453
    } else {
        /* XXX: cluster mode */
B
bellard 已提交
454 455 456 457 458 459 460 461 462 463 464 465 466 467
        memset(deliver_bitmask, 0x00, MAX_APIC_WORDS * sizeof(uint32_t));
        for(i = 0; i < MAX_APICS; i++) {
            apic_iter = local_apics[i];
            if (apic_iter) {
                if (apic_iter->dest_mode == 0xf) {
                    if (dest & apic_iter->log_dest)
                        set_bit(deliver_bitmask, i);
                } else if (apic_iter->dest_mode == 0x0) {
                    if ((dest & 0xf0) == (apic_iter->log_dest & 0xf0) &&
                        (dest & apic_iter->log_dest & 0x0f)) {
                        set_bit(deliver_bitmask, i);
                    }
                }
            }
468 469 470 471 472
        }
    }
}


473
void apic_init_reset(CPUState *env)
474
{
475
    APICState *s = env->apic_state;
476 477
    int i;

478 479 480
    if (!s)
        return;

481 482 483
    s->tpr = 0;
    s->spurious_vec = 0xff;
    s->log_dest = 0;
B
bellard 已提交
484
    s->dest_mode = 0xf;
485 486 487
    memset(s->isr, 0, sizeof(s->isr));
    memset(s->tmr, 0, sizeof(s->tmr));
    memset(s->irr, 0, sizeof(s->irr));
488 489
    for(i = 0; i < APIC_LVT_NB; i++)
        s->lvt[i] = 1 << 16; /* mask LVT */
490 491 492 493 494 495 496
    s->esr = 0;
    memset(s->icr, 0, sizeof(s->icr));
    s->divide_conf = 0;
    s->count_shift = 0;
    s->initial_count = 0;
    s->initial_count_load_time = 0;
    s->next_time = 0;
497
    s->wait_for_sipi = 1;
A
aurel32 已提交
498

499
    env->halted = !(s->apicbase & MSR_IA32_APICBASE_BSP);
500 501
}

B
bellard 已提交
502 503
static void apic_startup(APICState *s, int vector_num)
{
504 505 506 507 508 509 510 511 512 513 514
    s->sipi_vector = vector_num;
    cpu_interrupt(s->cpu_env, CPU_INTERRUPT_SIPI);
}

void apic_sipi(CPUState *env)
{
    APICState *s = env->apic_state;

    cpu_reset_interrupt(env, CPU_INTERRUPT_SIPI);

    if (!s->wait_for_sipi)
B
bellard 已提交
515
        return;
516

B
bellard 已提交
517
    env->eip = 0;
518
    cpu_x86_load_seg_cache(env, R_CS, s->sipi_vector << 8, s->sipi_vector << 12,
B
bellard 已提交
519
                           0xffff, 0);
B
bellard 已提交
520
    env->halted = 0;
521
    s->wait_for_sipi = 0;
B
bellard 已提交
522 523
}

524 525 526 527
static void apic_deliver(APICState *s, uint8_t dest, uint8_t dest_mode,
                         uint8_t delivery_mode, uint8_t vector_num,
                         uint8_t polarity, uint8_t trigger_mode)
{
B
bellard 已提交
528
    uint32_t deliver_bitmask[MAX_APIC_WORDS];
529 530 531
    int dest_shorthand = (s->icr[0] >> 18) & 3;
    APICState *apic_iter;

B
bellard 已提交
532
    switch (dest_shorthand) {
B
bellard 已提交
533 534 535 536 537
    case 0:
        apic_get_delivery_bitmask(deliver_bitmask, dest, dest_mode);
        break;
    case 1:
        memset(deliver_bitmask, 0x00, sizeof(deliver_bitmask));
G
Gleb Natapov 已提交
538
        set_bit(deliver_bitmask, s->idx);
B
bellard 已提交
539 540 541 542 543 544
        break;
    case 2:
        memset(deliver_bitmask, 0xff, sizeof(deliver_bitmask));
        break;
    case 3:
        memset(deliver_bitmask, 0xff, sizeof(deliver_bitmask));
G
Gleb Natapov 已提交
545
        reset_bit(deliver_bitmask, s->idx);
B
bellard 已提交
546
        break;
B
bellard 已提交
547 548
    }

549 550 551 552 553 554
    switch (delivery_mode) {
        case APIC_DM_INIT:
            {
                int trig_mode = (s->icr[0] >> 15) & 1;
                int level = (s->icr[0] >> 14) & 1;
                if (level == 0 && trig_mode == 1) {
555
                    foreach_apic(apic_iter, deliver_bitmask,
B
bellard 已提交
556
                                 apic_iter->arb_id = apic_iter->id );
557 558 559 560 561 562
                    return;
                }
            }
            break;

        case APIC_DM_SIPI:
563
            foreach_apic(apic_iter, deliver_bitmask,
B
bellard 已提交
564
                         apic_startup(apic_iter, vector_num) );
565 566 567 568 569 570 571
            return;
    }

    apic_bus_deliver(deliver_bitmask, delivery_mode, vector_num, polarity,
                     trigger_mode);
}

B
bellard 已提交
572 573 574 575 576 577 578 579 580 581 582
int apic_get_interrupt(CPUState *env)
{
    APICState *s = env->apic_state;
    int intno;

    /* if the APIC is installed or enabled, we let the 8259 handle the
       IRQs */
    if (!s)
        return -1;
    if (!(s->spurious_vec & APIC_SV_ENABLE))
        return -1;
583

B
bellard 已提交
584 585 586 587
    /* XXX: spurious IRQ handling */
    intno = get_highest_priority_int(s->irr);
    if (intno < 0)
        return -1;
588 589
    if (s->tpr && intno <= s->tpr)
        return s->spurious_vec & 0xff;
590
    reset_bit(s->irr, intno);
B
bellard 已提交
591 592 593 594 595
    set_bit(s->isr, intno);
    apic_update_irq(s);
    return intno;
}

596 597 598 599 600 601 602 603 604 605
int apic_accept_pic_intr(CPUState *env)
{
    APICState *s = env->apic_state;
    uint32_t lvt0;

    if (!s)
        return -1;

    lvt0 = s->lvt[APIC_LVT_LINT0];

606 607
    if ((s->apicbase & MSR_IA32_APICBASE_ENABLE) == 0 ||
        (lvt0 & APIC_LVT_MASKED) == 0)
608 609 610 611 612
        return 1;

    return 0;
}

B
bellard 已提交
613 614 615 616
static uint32_t apic_get_current_count(APICState *s)
{
    int64_t d;
    uint32_t val;
617
    d = (qemu_get_clock(vm_clock) - s->initial_count_load_time) >>
B
bellard 已提交
618 619 620
        s->count_shift;
    if (s->lvt[APIC_LVT_TIMER] & APIC_LVT_TIMER_PERIODIC) {
        /* periodic */
621
        val = s->initial_count - (d % ((uint64_t)s->initial_count + 1));
B
bellard 已提交
622 623 624 625 626 627 628 629 630 631 632 633
    } else {
        if (d >= s->initial_count)
            val = 0;
        else
            val = s->initial_count - d;
    }
    return val;
}

static void apic_timer_update(APICState *s, int64_t current_time)
{
    int64_t next_time, d;
634

B
bellard 已提交
635
    if (!(s->lvt[APIC_LVT_TIMER] & APIC_LVT_MASKED)) {
636
        d = (current_time - s->initial_count_load_time) >>
B
bellard 已提交
637 638
            s->count_shift;
        if (s->lvt[APIC_LVT_TIMER] & APIC_LVT_TIMER_PERIODIC) {
639 640
            if (!s->initial_count)
                goto no_timer;
641
            d = ((d / ((uint64_t)s->initial_count + 1)) + 1) * ((uint64_t)s->initial_count + 1);
B
bellard 已提交
642 643 644
        } else {
            if (d >= s->initial_count)
                goto no_timer;
645
            d = (uint64_t)s->initial_count + 1;
B
bellard 已提交
646 647 648 649 650 651 652 653 654 655 656 657 658 659
        }
        next_time = s->initial_count_load_time + (d << s->count_shift);
        qemu_mod_timer(s->timer, next_time);
        s->next_time = next_time;
    } else {
    no_timer:
        qemu_del_timer(s->timer);
    }
}

static void apic_timer(void *opaque)
{
    APICState *s = opaque;

660
    apic_local_deliver(s->cpu_env, APIC_LVT_TIMER);
B
bellard 已提交
661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704
    apic_timer_update(s, s->next_time);
}

static uint32_t apic_mem_readb(void *opaque, target_phys_addr_t addr)
{
    return 0;
}

static uint32_t apic_mem_readw(void *opaque, target_phys_addr_t addr)
{
    return 0;
}

static void apic_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
{
}

static void apic_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
{
}

static uint32_t apic_mem_readl(void *opaque, target_phys_addr_t addr)
{
    CPUState *env;
    APICState *s;
    uint32_t val;
    int index;

    env = cpu_single_env;
    if (!env)
        return 0;
    s = env->apic_state;

    index = (addr >> 4) & 0xff;
    switch(index) {
    case 0x02: /* id */
        val = s->id << 24;
        break;
    case 0x03: /* version */
        val = 0x11 | ((APIC_LVT_NB - 1) << 16); /* version 0x11 */
        break;
    case 0x08:
        val = s->tpr;
        break;
705 706 707
    case 0x09:
        val = apic_get_arb_pri(s);
        break;
B
bellard 已提交
708 709 710 711
    case 0x0a:
        /* ppr */
        val = apic_get_ppr(s);
        break;
A
aurel32 已提交
712 713 714
    case 0x0b:
        val = 0;
        break;
715 716 717 718 719 720
    case 0x0d:
        val = s->log_dest << 24;
        break;
    case 0x0e:
        val = s->dest_mode << 28;
        break;
B
bellard 已提交
721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739
    case 0x0f:
        val = s->spurious_vec;
        break;
    case 0x10 ... 0x17:
        val = s->isr[index & 7];
        break;
    case 0x18 ... 0x1f:
        val = s->tmr[index & 7];
        break;
    case 0x20 ... 0x27:
        val = s->irr[index & 7];
        break;
    case 0x28:
        val = s->esr;
        break;
    case 0x30:
    case 0x31:
        val = s->icr[index & 1];
        break;
B
bellard 已提交
740 741 742
    case 0x32 ... 0x37:
        val = s->lvt[index - 0x32];
        break;
B
bellard 已提交
743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762
    case 0x38:
        val = s->initial_count;
        break;
    case 0x39:
        val = apic_get_current_count(s);
        break;
    case 0x3e:
        val = s->divide_conf;
        break;
    default:
        s->esr |= ESR_ILLEGAL_ADDRESS;
        val = 0;
        break;
    }
#ifdef DEBUG_APIC
    printf("APIC read: %08x = %08x\n", (uint32_t)addr, val);
#endif
    return val;
}

763 764 765 766 767 768 769 770 771 772 773
static void apic_send_msi(target_phys_addr_t addr, uint32 data)
{
    uint8_t dest = (addr & MSI_ADDR_DEST_ID_MASK) >> MSI_ADDR_DEST_ID_SHIFT;
    uint8_t vector = (data & MSI_DATA_VECTOR_MASK) >> MSI_DATA_VECTOR_SHIFT;
    uint8_t dest_mode = (addr >> MSI_ADDR_DEST_MODE_SHIFT) & 0x1;
    uint8_t trigger_mode = (data >> MSI_DATA_TRIGGER_SHIFT) & 0x1;
    uint8_t delivery = (data >> MSI_DATA_DELIVERY_MODE_SHIFT) & 0x7;
    /* XXX: Ignore redirection hint. */
    apic_deliver_irq(dest, dest_mode, delivery, vector, 0, trigger_mode);
}

B
bellard 已提交
774 775 776 777
static void apic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
{
    CPUState *env;
    APICState *s;
778 779 780 781 782 783 784 785 786 787
    int index = (addr >> 4) & 0xff;
    if (addr > 0xfff || !index) {
        /* MSI and MMIO APIC are at the same memory location,
         * but actually not on the global bus: MSI is on PCI bus
         * APIC is connected directly to the CPU.
         * Mapping them on the global bus happens to work because
         * MSI registers are reserved in APIC MMIO and vice versa. */
        apic_send_msi(addr, val);
        return;
    }
B
bellard 已提交
788 789 790 791 792 793 794 795 796 797 798 799 800 801

    env = cpu_single_env;
    if (!env)
        return;
    s = env->apic_state;

#ifdef DEBUG_APIC
    printf("APIC write: %08x = %08x\n", (uint32_t)addr, val);
#endif

    switch(index) {
    case 0x02:
        s->id = (val >> 24);
        break;
B
bellard 已提交
802 803
    case 0x03:
        break;
B
bellard 已提交
804 805
    case 0x08:
        s->tpr = val;
806
        apic_update_irq(s);
B
bellard 已提交
807
        break;
B
bellard 已提交
808 809 810
    case 0x09:
    case 0x0a:
        break;
B
bellard 已提交
811 812 813
    case 0x0b: /* EOI */
        apic_eoi(s);
        break;
814 815 816 817 818 819
    case 0x0d:
        s->log_dest = val >> 24;
        break;
    case 0x0e:
        s->dest_mode = val >> 28;
        break;
B
bellard 已提交
820 821
    case 0x0f:
        s->spurious_vec = val & 0x1ff;
822
        apic_update_irq(s);
B
bellard 已提交
823
        break;
B
bellard 已提交
824 825 826 827 828
    case 0x10 ... 0x17:
    case 0x18 ... 0x1f:
    case 0x20 ... 0x27:
    case 0x28:
        break;
B
bellard 已提交
829
    case 0x30:
830 831 832 833 834
        s->icr[0] = val;
        apic_deliver(s, (s->icr[1] >> 24) & 0xff, (s->icr[0] >> 11) & 1,
                     (s->icr[0] >> 8) & 7, (s->icr[0] & 0xff),
                     (s->icr[0] >> 14) & 1, (s->icr[0] >> 15) & 1);
        break;
B
bellard 已提交
835
    case 0x31:
836
        s->icr[1] = val;
B
bellard 已提交
837 838 839 840 841 842 843 844 845 846 847 848 849 850
        break;
    case 0x32 ... 0x37:
        {
            int n = index - 0x32;
            s->lvt[n] = val;
            if (n == APIC_LVT_TIMER)
                apic_timer_update(s, qemu_get_clock(vm_clock));
        }
        break;
    case 0x38:
        s->initial_count = val;
        s->initial_count_load_time = qemu_get_clock(vm_clock);
        apic_timer_update(s, s->initial_count_load_time);
        break;
B
bellard 已提交
851 852
    case 0x39:
        break;
B
bellard 已提交
853 854 855 856 857 858 859 860 861 862 863 864 865 866
    case 0x3e:
        {
            int v;
            s->divide_conf = val & 0xb;
            v = (s->divide_conf & 3) | ((s->divide_conf >> 1) & 4);
            s->count_shift = (v + 1) & 7;
        }
        break;
    default:
        s->esr |= ESR_ILLEGAL_ADDRESS;
        break;
    }
}

J
Juan Quintela 已提交
867 868
/* This function is only used for old state version 1 and 2 */
static int apic_load_old(QEMUFile *f, void *opaque, int version_id)
869 870 871 872
{
    APICState *s = opaque;
    int i;

B
bellard 已提交
873
    if (version_id > 2)
874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895
        return -EINVAL;

    /* XXX: what if the base changes? (registered memory regions) */
    qemu_get_be32s(f, &s->apicbase);
    qemu_get_8s(f, &s->id);
    qemu_get_8s(f, &s->arb_id);
    qemu_get_8s(f, &s->tpr);
    qemu_get_be32s(f, &s->spurious_vec);
    qemu_get_8s(f, &s->log_dest);
    qemu_get_8s(f, &s->dest_mode);
    for (i = 0; i < 8; i++) {
        qemu_get_be32s(f, &s->isr[i]);
        qemu_get_be32s(f, &s->tmr[i]);
        qemu_get_be32s(f, &s->irr[i]);
    }
    for (i = 0; i < APIC_LVT_NB; i++) {
        qemu_get_be32s(f, &s->lvt[i]);
    }
    qemu_get_be32s(f, &s->esr);
    qemu_get_be32s(f, &s->icr[0]);
    qemu_get_be32s(f, &s->icr[1]);
    qemu_get_be32s(f, &s->divide_conf);
896
    s->count_shift=qemu_get_be32(f);
897
    qemu_get_be32s(f, &s->initial_count);
898 899
    s->initial_count_load_time=qemu_get_be64(f);
    s->next_time=qemu_get_be64(f);
B
bellard 已提交
900 901 902

    if (version_id >= 2)
        qemu_get_timer(f, s->timer);
903 904
    return 0;
}
B
bellard 已提交
905

J
Juan Quintela 已提交
906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935
static const VMStateDescription vmstate_apic = {
    .name = "apic",
    .version_id = 3,
    .minimum_version_id = 3,
    .minimum_version_id_old = 1,
    .load_state_old = apic_load_old,
    .fields      = (VMStateField []) {
        VMSTATE_UINT32(apicbase, APICState),
        VMSTATE_UINT8(id, APICState),
        VMSTATE_UINT8(arb_id, APICState),
        VMSTATE_UINT8(tpr, APICState),
        VMSTATE_UINT32(spurious_vec, APICState),
        VMSTATE_UINT8(log_dest, APICState),
        VMSTATE_UINT8(dest_mode, APICState),
        VMSTATE_UINT32_ARRAY(isr, APICState, 8),
        VMSTATE_UINT32_ARRAY(tmr, APICState, 8),
        VMSTATE_UINT32_ARRAY(irr, APICState, 8),
        VMSTATE_UINT32_ARRAY(lvt, APICState, APIC_LVT_NB),
        VMSTATE_UINT32(esr, APICState),
        VMSTATE_UINT32_ARRAY(icr, APICState, 2),
        VMSTATE_UINT32(divide_conf, APICState),
        VMSTATE_INT32(count_shift, APICState),
        VMSTATE_UINT32(initial_count, APICState),
        VMSTATE_INT64(initial_count_load_time, APICState),
        VMSTATE_INT64(next_time, APICState),
        VMSTATE_TIMER(timer, APICState),
        VMSTATE_END_OF_LIST()
    }
};

936 937 938
static void apic_reset(void *opaque)
{
    APICState *s = opaque;
G
Gleb Natapov 已提交
939
    int bsp = cpu_is_bsp(s->cpu_env);
A
aurel32 已提交
940 941

    s->apicbase = 0xfee00000 |
G
Gleb Natapov 已提交
942
        (bsp ? MSR_IA32_APICBASE_BSP : 0) | MSR_IA32_APICBASE_ENABLE;
A
aurel32 已提交
943

944 945
    cpu_reset(s->cpu_env);
    apic_init_reset(s->cpu_env);
946

G
Gleb Natapov 已提交
947
    if (bsp) {
948 949 950 951 952 953 954
        /*
         * LINT0 delivery mode on CPU #0 is set to ExtInt at initialization
         * time typically by BIOS, so PIC interrupt can be delivered to the
         * processor when local APIC is enabled.
         */
        s->lvt[APIC_LVT_LINT0] = 0x700;
    }
J
Jan Kiszka 已提交
955 956

    cpu_synchronize_state(s->cpu_env, 1);
957
}
B
bellard 已提交
958

959
static CPUReadMemoryFunc * const apic_mem_read[3] = {
B
bellard 已提交
960 961 962 963 964
    apic_mem_readb,
    apic_mem_readw,
    apic_mem_readl,
};

965
static CPUWriteMemoryFunc * const apic_mem_write[3] = {
B
bellard 已提交
966 967 968 969 970 971 972 973 974
    apic_mem_writeb,
    apic_mem_writew,
    apic_mem_writel,
};

int apic_init(CPUState *env)
{
    APICState *s;

G
Gleb Natapov 已提交
975
    if (last_apic_idx >= MAX_APICS)
B
bellard 已提交
976
        return -1;
977
    s = qemu_mallocz(sizeof(APICState));
B
bellard 已提交
978
    env->apic_state = s;
G
Gleb Natapov 已提交
979 980
    s->idx = last_apic_idx++;
    s->id = env->cpuid_apic_id;
B
bellard 已提交
981 982
    s->cpu_env = env;

983
    apic_reset(s);
984
    msix_supported = 1;
985

986
    /* XXX: mapping more APICs at the same memory location */
B
bellard 已提交
987 988 989
    if (apic_io_memory == 0) {
        /* NOTE: the APIC is directly connected to the CPU - it is not
           on the global memory bus. */
990
        apic_io_memory = cpu_register_io_memory(apic_mem_read,
B
bellard 已提交
991
                                                apic_mem_write, NULL);
992 993
        /* XXX: what if the base changes? */
        cpu_register_physical_memory(MSI_ADDR_BASE, MSI_ADDR_SIZE,
994
                                     apic_io_memory);
B
bellard 已提交
995 996
    }
    s->timer = qemu_new_timer(vm_clock, apic_timer, s);
997

J
Juan Quintela 已提交
998
    vmstate_register(s->idx, &vmstate_apic, s);
999
    qemu_register_reset(apic_reset, s);
1000

G
Gleb Natapov 已提交
1001
    local_apics[s->idx] = s;
1002 1003
    return 0;
}