186797937017f52bff088d02edf64fb931177a7eaJun Nakajima/*
286797937017f52bff088d02edf64fb931177a7eaJun Nakajima *  APIC support
386797937017f52bff088d02edf64fb931177a7eaJun Nakajima *
486797937017f52bff088d02edf64fb931177a7eaJun Nakajima *  Copyright (c) 2004-2005 Fabrice Bellard
586797937017f52bff088d02edf64fb931177a7eaJun Nakajima *
686797937017f52bff088d02edf64fb931177a7eaJun Nakajima * This library is free software; you can redistribute it and/or
786797937017f52bff088d02edf64fb931177a7eaJun Nakajima * modify it under the terms of the GNU Lesser General Public
886797937017f52bff088d02edf64fb931177a7eaJun Nakajima * License as published by the Free Software Foundation; either
986797937017f52bff088d02edf64fb931177a7eaJun Nakajima * version 2 of the License, or (at your option) any later version.
1086797937017f52bff088d02edf64fb931177a7eaJun Nakajima *
1186797937017f52bff088d02edf64fb931177a7eaJun Nakajima * This library is distributed in the hope that it will be useful,
1286797937017f52bff088d02edf64fb931177a7eaJun Nakajima * but WITHOUT ANY WARRANTY; without even the implied warranty of
1386797937017f52bff088d02edf64fb931177a7eaJun Nakajima * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1486797937017f52bff088d02edf64fb931177a7eaJun Nakajima * Lesser General Public License for more details.
1586797937017f52bff088d02edf64fb931177a7eaJun Nakajima *
1686797937017f52bff088d02edf64fb931177a7eaJun Nakajima * You should have received a copy of the GNU Lesser General Public
1786797937017f52bff088d02edf64fb931177a7eaJun Nakajima * License along with this library; if not, write to the Free Software
1886797937017f52bff088d02edf64fb931177a7eaJun Nakajima * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
1986797937017f52bff088d02edf64fb931177a7eaJun Nakajima */
2086797937017f52bff088d02edf64fb931177a7eaJun Nakajima#include "hw.h"
2186797937017f52bff088d02edf64fb931177a7eaJun Nakajima#include "pc.h"
2286797937017f52bff088d02edf64fb931177a7eaJun Nakajima#include "qemu-timer.h"
2386797937017f52bff088d02edf64fb931177a7eaJun Nakajima#include "host-utils.h"
2486797937017f52bff088d02edf64fb931177a7eaJun Nakajima
2586797937017f52bff088d02edf64fb931177a7eaJun Nakajima//#define DEBUG_APIC
2686797937017f52bff088d02edf64fb931177a7eaJun Nakajima
2786797937017f52bff088d02edf64fb931177a7eaJun Nakajima/* APIC Local Vector Table */
2886797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define APIC_LVT_TIMER   0
2986797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define APIC_LVT_THERMAL 1
3086797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define APIC_LVT_PERFORM 2
3186797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define APIC_LVT_LINT0   3
3286797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define APIC_LVT_LINT1   4
3386797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define APIC_LVT_ERROR   5
3486797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define APIC_LVT_NB      6
3586797937017f52bff088d02edf64fb931177a7eaJun Nakajima
3686797937017f52bff088d02edf64fb931177a7eaJun Nakajima/* APIC delivery modes */
3786797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define APIC_DM_FIXED	0
3886797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define APIC_DM_LOWPRI	1
3986797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define APIC_DM_SMI	2
4086797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define APIC_DM_NMI	4
4186797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define APIC_DM_INIT	5
4286797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define APIC_DM_SIPI	6
4386797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define APIC_DM_EXTINT	7
4486797937017f52bff088d02edf64fb931177a7eaJun Nakajima
4586797937017f52bff088d02edf64fb931177a7eaJun Nakajima/* APIC destination mode */
4686797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define APIC_DESTMODE_FLAT	0xf
4786797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define APIC_DESTMODE_CLUSTER	1
4886797937017f52bff088d02edf64fb931177a7eaJun Nakajima
4986797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define APIC_TRIGGER_EDGE  0
5086797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define APIC_TRIGGER_LEVEL 1
5186797937017f52bff088d02edf64fb931177a7eaJun Nakajima
5286797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define	APIC_LVT_TIMER_PERIODIC		(1<<17)
5386797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define	APIC_LVT_MASKED			(1<<16)
5486797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define	APIC_LVT_LEVEL_TRIGGER		(1<<15)
5586797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define	APIC_LVT_REMOTE_IRR		(1<<14)
5686797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define	APIC_INPUT_POLARITY		(1<<13)
5786797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define	APIC_SEND_PENDING		(1<<12)
5886797937017f52bff088d02edf64fb931177a7eaJun Nakajima
5986797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define ESR_ILLEGAL_ADDRESS (1 << 7)
6086797937017f52bff088d02edf64fb931177a7eaJun Nakajima
6186797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define APIC_SV_ENABLE (1 << 8)
6286797937017f52bff088d02edf64fb931177a7eaJun Nakajima
6386797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define MAX_APICS 255
6486797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define MAX_APIC_WORDS 8
6586797937017f52bff088d02edf64fb931177a7eaJun Nakajima
6686797937017f52bff088d02edf64fb931177a7eaJun Nakajimatypedef struct APICState {
6786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    CPUState *cpu_env;
6886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    uint32_t apicbase;
6986797937017f52bff088d02edf64fb931177a7eaJun Nakajima    uint8_t id;
7086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    uint8_t arb_id;
7186797937017f52bff088d02edf64fb931177a7eaJun Nakajima    uint8_t tpr;
7286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    uint32_t spurious_vec;
7386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    uint8_t log_dest;
7486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    uint8_t dest_mode;
7586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    uint32_t isr[8];  /* in service register */
7686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    uint32_t tmr[8];  /* trigger mode register */
7786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    uint32_t irr[8]; /* interrupt request register */
7886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    uint32_t lvt[APIC_LVT_NB];
7986797937017f52bff088d02edf64fb931177a7eaJun Nakajima    uint32_t esr; /* error register */
8086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    uint32_t icr[2];
8186797937017f52bff088d02edf64fb931177a7eaJun Nakajima
8286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    uint32_t divide_conf;
8386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    int count_shift;
8486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    uint32_t initial_count;
8586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    int64_t initial_count_load_time, next_time;
8686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    uint32_t idx;
8786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    QEMUTimer *timer;
8886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    int sipi_vector;
8986797937017f52bff088d02edf64fb931177a7eaJun Nakajima    int wait_for_sipi;
9086797937017f52bff088d02edf64fb931177a7eaJun Nakajima} APICState;
9186797937017f52bff088d02edf64fb931177a7eaJun Nakajima
9286797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic int apic_io_memory;
9386797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic APICState *local_apics[MAX_APICS + 1];
9486797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic int last_apic_idx = 0;
9586797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic int apic_irq_delivered;
9686797937017f52bff088d02edf64fb931177a7eaJun Nakajima
9786797937017f52bff088d02edf64fb931177a7eaJun Nakajima
9886797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic void apic_set_irq(APICState *s, int vector_num, int trigger_mode);
9986797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic void apic_update_irq(APICState *s);
10086797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic void apic_get_delivery_bitmask(uint32_t *deliver_bitmask,
10186797937017f52bff088d02edf64fb931177a7eaJun Nakajima                                      uint8_t dest, uint8_t dest_mode);
10286797937017f52bff088d02edf64fb931177a7eaJun Nakajima
10386797937017f52bff088d02edf64fb931177a7eaJun Nakajima/* Find first bit starting from msb */
10486797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic int fls_bit(uint32_t value)
10586797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
10686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    return 31 - clz32(value);
10786797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
10886797937017f52bff088d02edf64fb931177a7eaJun Nakajima
10986797937017f52bff088d02edf64fb931177a7eaJun Nakajima/* Find first bit starting from lsb */
11086797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic int ffs_bit(uint32_t value)
11186797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
11286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    return ctz32(value);
11386797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
11486797937017f52bff088d02edf64fb931177a7eaJun Nakajima
11586797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic inline void set_bit(uint32_t *tab, int index)
11686797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
11786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    int i, mask;
11886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    i = index >> 5;
11986797937017f52bff088d02edf64fb931177a7eaJun Nakajima    mask = 1 << (index & 0x1f);
12086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    tab[i] |= mask;
12186797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
12286797937017f52bff088d02edf64fb931177a7eaJun Nakajima
12386797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic inline void reset_bit(uint32_t *tab, int index)
12486797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
12586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    int i, mask;
12686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    i = index >> 5;
12786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    mask = 1 << (index & 0x1f);
12886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    tab[i] &= ~mask;
12986797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
13086797937017f52bff088d02edf64fb931177a7eaJun Nakajima
13186797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic inline int get_bit(uint32_t *tab, int index)
13286797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
13386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    int i, mask;
13486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    i = index >> 5;
13586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    mask = 1 << (index & 0x1f);
13686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    return !!(tab[i] & mask);
13786797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
13886797937017f52bff088d02edf64fb931177a7eaJun Nakajima
13986797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic void apic_local_deliver(CPUState *env, int vector)
14086797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
14186797937017f52bff088d02edf64fb931177a7eaJun Nakajima    APICState *s = env->apic_state;
14286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    uint32_t lvt = s->lvt[vector];
14386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    int trigger_mode;
14486797937017f52bff088d02edf64fb931177a7eaJun Nakajima
14586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    if (lvt & APIC_LVT_MASKED)
14686797937017f52bff088d02edf64fb931177a7eaJun Nakajima        return;
14786797937017f52bff088d02edf64fb931177a7eaJun Nakajima
14886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    switch ((lvt >> 8) & 7) {
14986797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case APIC_DM_SMI:
15086797937017f52bff088d02edf64fb931177a7eaJun Nakajima        cpu_interrupt(env, CPU_INTERRUPT_SMI);
15186797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
15286797937017f52bff088d02edf64fb931177a7eaJun Nakajima
15386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case APIC_DM_NMI:
15486797937017f52bff088d02edf64fb931177a7eaJun Nakajima        cpu_interrupt(env, CPU_INTERRUPT_NMI);
15586797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
15686797937017f52bff088d02edf64fb931177a7eaJun Nakajima
15786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case APIC_DM_EXTINT:
15886797937017f52bff088d02edf64fb931177a7eaJun Nakajima        cpu_interrupt(env, CPU_INTERRUPT_HARD);
15986797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
16086797937017f52bff088d02edf64fb931177a7eaJun Nakajima
16186797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case APIC_DM_FIXED:
16286797937017f52bff088d02edf64fb931177a7eaJun Nakajima        trigger_mode = APIC_TRIGGER_EDGE;
16386797937017f52bff088d02edf64fb931177a7eaJun Nakajima        if ((vector == APIC_LVT_LINT0 || vector == APIC_LVT_LINT1) &&
16486797937017f52bff088d02edf64fb931177a7eaJun Nakajima            (lvt & APIC_LVT_LEVEL_TRIGGER))
16586797937017f52bff088d02edf64fb931177a7eaJun Nakajima            trigger_mode = APIC_TRIGGER_LEVEL;
16686797937017f52bff088d02edf64fb931177a7eaJun Nakajima        apic_set_irq(s, lvt & 0xff, trigger_mode);
16786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    }
16886797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
16986797937017f52bff088d02edf64fb931177a7eaJun Nakajima
17086797937017f52bff088d02edf64fb931177a7eaJun Nakajimavoid apic_deliver_pic_intr(CPUState *env, int level)
17186797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
17286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    if (level)
17386797937017f52bff088d02edf64fb931177a7eaJun Nakajima        apic_local_deliver(env, APIC_LVT_LINT0);
17486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    else {
17586797937017f52bff088d02edf64fb931177a7eaJun Nakajima        APICState *s = env->apic_state;
17686797937017f52bff088d02edf64fb931177a7eaJun Nakajima        uint32_t lvt = s->lvt[APIC_LVT_LINT0];
17786797937017f52bff088d02edf64fb931177a7eaJun Nakajima
17886797937017f52bff088d02edf64fb931177a7eaJun Nakajima        switch ((lvt >> 8) & 7) {
17986797937017f52bff088d02edf64fb931177a7eaJun Nakajima        case APIC_DM_FIXED:
18086797937017f52bff088d02edf64fb931177a7eaJun Nakajima            if (!(lvt & APIC_LVT_LEVEL_TRIGGER))
18186797937017f52bff088d02edf64fb931177a7eaJun Nakajima                break;
18286797937017f52bff088d02edf64fb931177a7eaJun Nakajima            reset_bit(s->irr, lvt & 0xff);
18386797937017f52bff088d02edf64fb931177a7eaJun Nakajima            /* fall through */
18486797937017f52bff088d02edf64fb931177a7eaJun Nakajima        case APIC_DM_EXTINT:
18586797937017f52bff088d02edf64fb931177a7eaJun Nakajima            cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
18686797937017f52bff088d02edf64fb931177a7eaJun Nakajima            break;
18786797937017f52bff088d02edf64fb931177a7eaJun Nakajima        }
18886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    }
18986797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
19086797937017f52bff088d02edf64fb931177a7eaJun Nakajima
19186797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define foreach_apic(apic, deliver_bitmask, code) \
19286797937017f52bff088d02edf64fb931177a7eaJun Nakajima{\
19386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    int __i, __j, __mask;\
19486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    for(__i = 0; __i < MAX_APIC_WORDS; __i++) {\
19586797937017f52bff088d02edf64fb931177a7eaJun Nakajima        __mask = deliver_bitmask[__i];\
19686797937017f52bff088d02edf64fb931177a7eaJun Nakajima        if (__mask) {\
19786797937017f52bff088d02edf64fb931177a7eaJun Nakajima            for(__j = 0; __j < 32; __j++) {\
19886797937017f52bff088d02edf64fb931177a7eaJun Nakajima                if (__mask & (1 << __j)) {\
19986797937017f52bff088d02edf64fb931177a7eaJun Nakajima                    apic = local_apics[__i * 32 + __j];\
20086797937017f52bff088d02edf64fb931177a7eaJun Nakajima                    if (apic) {\
20186797937017f52bff088d02edf64fb931177a7eaJun Nakajima                        code;\
20286797937017f52bff088d02edf64fb931177a7eaJun Nakajima                    }\
20386797937017f52bff088d02edf64fb931177a7eaJun Nakajima                }\
20486797937017f52bff088d02edf64fb931177a7eaJun Nakajima            }\
20586797937017f52bff088d02edf64fb931177a7eaJun Nakajima        }\
20686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    }\
20786797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
20886797937017f52bff088d02edf64fb931177a7eaJun Nakajima
20986797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic void apic_bus_deliver(const uint32_t *deliver_bitmask,
21086797937017f52bff088d02edf64fb931177a7eaJun Nakajima                             uint8_t delivery_mode,
21186797937017f52bff088d02edf64fb931177a7eaJun Nakajima                             uint8_t vector_num, uint8_t polarity,
21286797937017f52bff088d02edf64fb931177a7eaJun Nakajima                             uint8_t trigger_mode)
21386797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
21486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    APICState *apic_iter;
21586797937017f52bff088d02edf64fb931177a7eaJun Nakajima
21686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    switch (delivery_mode) {
21786797937017f52bff088d02edf64fb931177a7eaJun Nakajima        case APIC_DM_LOWPRI:
21886797937017f52bff088d02edf64fb931177a7eaJun Nakajima            /* XXX: search for focus processor, arbitration */
21986797937017f52bff088d02edf64fb931177a7eaJun Nakajima            {
22086797937017f52bff088d02edf64fb931177a7eaJun Nakajima                int i, d;
22186797937017f52bff088d02edf64fb931177a7eaJun Nakajima                d = -1;
22286797937017f52bff088d02edf64fb931177a7eaJun Nakajima                for(i = 0; i < MAX_APIC_WORDS; i++) {
22386797937017f52bff088d02edf64fb931177a7eaJun Nakajima                    if (deliver_bitmask[i]) {
22486797937017f52bff088d02edf64fb931177a7eaJun Nakajima                        d = i * 32 + ffs_bit(deliver_bitmask[i]);
22586797937017f52bff088d02edf64fb931177a7eaJun Nakajima                        break;
22686797937017f52bff088d02edf64fb931177a7eaJun Nakajima                    }
22786797937017f52bff088d02edf64fb931177a7eaJun Nakajima                }
22886797937017f52bff088d02edf64fb931177a7eaJun Nakajima                if (d >= 0) {
22986797937017f52bff088d02edf64fb931177a7eaJun Nakajima                    apic_iter = local_apics[d];
23086797937017f52bff088d02edf64fb931177a7eaJun Nakajima                    if (apic_iter) {
23186797937017f52bff088d02edf64fb931177a7eaJun Nakajima                        apic_set_irq(apic_iter, vector_num, trigger_mode);
23286797937017f52bff088d02edf64fb931177a7eaJun Nakajima                    }
23386797937017f52bff088d02edf64fb931177a7eaJun Nakajima                }
23486797937017f52bff088d02edf64fb931177a7eaJun Nakajima            }
23586797937017f52bff088d02edf64fb931177a7eaJun Nakajima            return;
23686797937017f52bff088d02edf64fb931177a7eaJun Nakajima
23786797937017f52bff088d02edf64fb931177a7eaJun Nakajima        case APIC_DM_FIXED:
23886797937017f52bff088d02edf64fb931177a7eaJun Nakajima            break;
23986797937017f52bff088d02edf64fb931177a7eaJun Nakajima
24086797937017f52bff088d02edf64fb931177a7eaJun Nakajima        case APIC_DM_SMI:
24186797937017f52bff088d02edf64fb931177a7eaJun Nakajima            foreach_apic(apic_iter, deliver_bitmask,
24286797937017f52bff088d02edf64fb931177a7eaJun Nakajima                cpu_interrupt(apic_iter->cpu_env, CPU_INTERRUPT_SMI) );
24386797937017f52bff088d02edf64fb931177a7eaJun Nakajima            return;
24486797937017f52bff088d02edf64fb931177a7eaJun Nakajima
24586797937017f52bff088d02edf64fb931177a7eaJun Nakajima        case APIC_DM_NMI:
24686797937017f52bff088d02edf64fb931177a7eaJun Nakajima            foreach_apic(apic_iter, deliver_bitmask,
24786797937017f52bff088d02edf64fb931177a7eaJun Nakajima                cpu_interrupt(apic_iter->cpu_env, CPU_INTERRUPT_NMI) );
24886797937017f52bff088d02edf64fb931177a7eaJun Nakajima            return;
24986797937017f52bff088d02edf64fb931177a7eaJun Nakajima
25086797937017f52bff088d02edf64fb931177a7eaJun Nakajima        case APIC_DM_INIT:
25186797937017f52bff088d02edf64fb931177a7eaJun Nakajima            /* normal INIT IPI sent to processors */
25286797937017f52bff088d02edf64fb931177a7eaJun Nakajima            foreach_apic(apic_iter, deliver_bitmask,
25386797937017f52bff088d02edf64fb931177a7eaJun Nakajima                         cpu_interrupt(apic_iter->cpu_env, CPU_INTERRUPT_INIT) );
25486797937017f52bff088d02edf64fb931177a7eaJun Nakajima            return;
25586797937017f52bff088d02edf64fb931177a7eaJun Nakajima
25686797937017f52bff088d02edf64fb931177a7eaJun Nakajima        case APIC_DM_EXTINT:
25786797937017f52bff088d02edf64fb931177a7eaJun Nakajima            /* handled in I/O APIC code */
25886797937017f52bff088d02edf64fb931177a7eaJun Nakajima            break;
25986797937017f52bff088d02edf64fb931177a7eaJun Nakajima
26086797937017f52bff088d02edf64fb931177a7eaJun Nakajima        default:
26186797937017f52bff088d02edf64fb931177a7eaJun Nakajima            return;
26286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    }
26386797937017f52bff088d02edf64fb931177a7eaJun Nakajima
26486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    foreach_apic(apic_iter, deliver_bitmask,
26586797937017f52bff088d02edf64fb931177a7eaJun Nakajima                 apic_set_irq(apic_iter, vector_num, trigger_mode) );
26686797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
26786797937017f52bff088d02edf64fb931177a7eaJun Nakajima
26886797937017f52bff088d02edf64fb931177a7eaJun Nakajimavoid apic_deliver_irq(uint8_t dest, uint8_t dest_mode,
26986797937017f52bff088d02edf64fb931177a7eaJun Nakajima                      uint8_t delivery_mode, uint8_t vector_num,
27086797937017f52bff088d02edf64fb931177a7eaJun Nakajima                      uint8_t polarity, uint8_t trigger_mode)
27186797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
27286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    uint32_t deliver_bitmask[MAX_APIC_WORDS];
27386797937017f52bff088d02edf64fb931177a7eaJun Nakajima
27486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    apic_get_delivery_bitmask(deliver_bitmask, dest, dest_mode);
27586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    apic_bus_deliver(deliver_bitmask, delivery_mode, vector_num, polarity,
27686797937017f52bff088d02edf64fb931177a7eaJun Nakajima                     trigger_mode);
27786797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
27886797937017f52bff088d02edf64fb931177a7eaJun Nakajima
27986797937017f52bff088d02edf64fb931177a7eaJun Nakajimavoid cpu_set_apic_base(CPUState *env, uint64_t val)
28086797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
28186797937017f52bff088d02edf64fb931177a7eaJun Nakajima    APICState *s = env->apic_state;
28286797937017f52bff088d02edf64fb931177a7eaJun Nakajima#ifdef DEBUG_APIC
28386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    printf("cpu_set_apic_base: %016" PRIx64 "\n", val);
28486797937017f52bff088d02edf64fb931177a7eaJun Nakajima#endif
28586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    if (!s)
28686797937017f52bff088d02edf64fb931177a7eaJun Nakajima        return;
28786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s->apicbase = (val & 0xfffff000) |
28886797937017f52bff088d02edf64fb931177a7eaJun Nakajima        (s->apicbase & (MSR_IA32_APICBASE_BSP | MSR_IA32_APICBASE_ENABLE));
28986797937017f52bff088d02edf64fb931177a7eaJun Nakajima    /* if disabled, cannot be enabled again */
29086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    if (!(val & MSR_IA32_APICBASE_ENABLE)) {
29186797937017f52bff088d02edf64fb931177a7eaJun Nakajima        s->apicbase &= ~MSR_IA32_APICBASE_ENABLE;
29286797937017f52bff088d02edf64fb931177a7eaJun Nakajima        env->cpuid_features &= ~CPUID_APIC;
29386797937017f52bff088d02edf64fb931177a7eaJun Nakajima        s->spurious_vec &= ~APIC_SV_ENABLE;
29486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    }
29586797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
29686797937017f52bff088d02edf64fb931177a7eaJun Nakajima
29786797937017f52bff088d02edf64fb931177a7eaJun Nakajimauint64_t cpu_get_apic_base(CPUState *env)
29886797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
29986797937017f52bff088d02edf64fb931177a7eaJun Nakajima    APICState *s = env->apic_state;
30086797937017f52bff088d02edf64fb931177a7eaJun Nakajima#ifdef DEBUG_APIC
30186797937017f52bff088d02edf64fb931177a7eaJun Nakajima    printf("cpu_get_apic_base: %016" PRIx64 "\n",
30286797937017f52bff088d02edf64fb931177a7eaJun Nakajima           s ? (uint64_t)s->apicbase: 0);
30386797937017f52bff088d02edf64fb931177a7eaJun Nakajima#endif
30486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    return s ? s->apicbase : 0;
30586797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
30686797937017f52bff088d02edf64fb931177a7eaJun Nakajima
30786797937017f52bff088d02edf64fb931177a7eaJun Nakajimavoid cpu_set_apic_tpr(CPUX86State *env, uint8_t val)
30886797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
30986797937017f52bff088d02edf64fb931177a7eaJun Nakajima    APICState *s = env->apic_state;
31086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    if (!s)
31186797937017f52bff088d02edf64fb931177a7eaJun Nakajima        return;
31286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s->tpr = (val & 0x0f) << 4;
31386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    apic_update_irq(s);
31486797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
31586797937017f52bff088d02edf64fb931177a7eaJun Nakajima
31686797937017f52bff088d02edf64fb931177a7eaJun Nakajimauint8_t cpu_get_apic_tpr(CPUX86State *env)
31786797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
31886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    APICState *s = env->apic_state;
31986797937017f52bff088d02edf64fb931177a7eaJun Nakajima    return s ? s->tpr >> 4 : 0;
32086797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
32186797937017f52bff088d02edf64fb931177a7eaJun Nakajima
32286797937017f52bff088d02edf64fb931177a7eaJun Nakajima/* return -1 if no bit is set */
32386797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic int get_highest_priority_int(uint32_t *tab)
32486797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
32586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    int i;
32686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    for(i = 7; i >= 0; i--) {
32786797937017f52bff088d02edf64fb931177a7eaJun Nakajima        if (tab[i] != 0) {
32886797937017f52bff088d02edf64fb931177a7eaJun Nakajima            return i * 32 + fls_bit(tab[i]);
32986797937017f52bff088d02edf64fb931177a7eaJun Nakajima        }
33086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    }
33186797937017f52bff088d02edf64fb931177a7eaJun Nakajima    return -1;
33286797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
33386797937017f52bff088d02edf64fb931177a7eaJun Nakajima
33486797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic int apic_get_ppr(APICState *s)
33586797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
33686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    int tpr, isrv, ppr;
33786797937017f52bff088d02edf64fb931177a7eaJun Nakajima
33886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    tpr = (s->tpr >> 4);
33986797937017f52bff088d02edf64fb931177a7eaJun Nakajima    isrv = get_highest_priority_int(s->isr);
34086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    if (isrv < 0)
34186797937017f52bff088d02edf64fb931177a7eaJun Nakajima        isrv = 0;
34286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    isrv >>= 4;
34386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    if (tpr >= isrv)
34486797937017f52bff088d02edf64fb931177a7eaJun Nakajima        ppr = s->tpr;
34586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    else
34686797937017f52bff088d02edf64fb931177a7eaJun Nakajima        ppr = isrv << 4;
34786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    return ppr;
34886797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
34986797937017f52bff088d02edf64fb931177a7eaJun Nakajima
35086797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic int apic_get_arb_pri(APICState *s)
35186797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
35286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    /* XXX: arbitration */
35386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    return 0;
35486797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
35586797937017f52bff088d02edf64fb931177a7eaJun Nakajima
35686797937017f52bff088d02edf64fb931177a7eaJun Nakajima/* signal the CPU if an irq is pending */
35786797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic void apic_update_irq(APICState *s)
35886797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
35986797937017f52bff088d02edf64fb931177a7eaJun Nakajima    int irrv, ppr;
36086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    if (!(s->spurious_vec & APIC_SV_ENABLE))
36186797937017f52bff088d02edf64fb931177a7eaJun Nakajima        return;
36286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    irrv = get_highest_priority_int(s->irr);
36386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    if (irrv < 0)
36486797937017f52bff088d02edf64fb931177a7eaJun Nakajima        return;
36586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    ppr = apic_get_ppr(s);
36686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    if (ppr && (irrv & 0xf0) <= (ppr & 0xf0))
36786797937017f52bff088d02edf64fb931177a7eaJun Nakajima        return;
36886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    cpu_interrupt(s->cpu_env, CPU_INTERRUPT_HARD);
36986797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
37086797937017f52bff088d02edf64fb931177a7eaJun Nakajima
37186797937017f52bff088d02edf64fb931177a7eaJun Nakajimavoid apic_reset_irq_delivered(void)
37286797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
37386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    apic_irq_delivered = 0;
37486797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
37586797937017f52bff088d02edf64fb931177a7eaJun Nakajima
37686797937017f52bff088d02edf64fb931177a7eaJun Nakajimaint apic_get_irq_delivered(void)
37786797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
37886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    return apic_irq_delivered;
37986797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
38086797937017f52bff088d02edf64fb931177a7eaJun Nakajima
38186797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic void apic_set_irq(APICState *s, int vector_num, int trigger_mode)
38286797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
38386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    apic_irq_delivered += !get_bit(s->irr, vector_num);
38486797937017f52bff088d02edf64fb931177a7eaJun Nakajima
38586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    set_bit(s->irr, vector_num);
38686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    if (trigger_mode)
38786797937017f52bff088d02edf64fb931177a7eaJun Nakajima        set_bit(s->tmr, vector_num);
38886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    else
38986797937017f52bff088d02edf64fb931177a7eaJun Nakajima        reset_bit(s->tmr, vector_num);
39086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    apic_update_irq(s);
39186797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
39286797937017f52bff088d02edf64fb931177a7eaJun Nakajima
39386797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic void apic_eoi(APICState *s)
39486797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
39586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    int isrv;
39686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    isrv = get_highest_priority_int(s->isr);
39786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    if (isrv < 0)
39886797937017f52bff088d02edf64fb931177a7eaJun Nakajima        return;
39986797937017f52bff088d02edf64fb931177a7eaJun Nakajima    reset_bit(s->isr, isrv);
40086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    /* XXX: send the EOI packet to the APIC bus to allow the I/O APIC to
40186797937017f52bff088d02edf64fb931177a7eaJun Nakajima            set the remote IRR bit for level triggered interrupts. */
40286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    apic_update_irq(s);
40386797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
40486797937017f52bff088d02edf64fb931177a7eaJun Nakajima
40586797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic int apic_find_dest(uint8_t dest)
40686797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
40786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    APICState *apic = local_apics[dest];
40886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    int i;
40986797937017f52bff088d02edf64fb931177a7eaJun Nakajima
41086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    if (apic && apic->id == dest)
41186797937017f52bff088d02edf64fb931177a7eaJun Nakajima        return dest;  /* shortcut in case apic->id == apic->idx */
41286797937017f52bff088d02edf64fb931177a7eaJun Nakajima
41386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    for (i = 0; i < MAX_APICS; i++) {
41486797937017f52bff088d02edf64fb931177a7eaJun Nakajima        apic = local_apics[i];
41586797937017f52bff088d02edf64fb931177a7eaJun Nakajima	if (apic && apic->id == dest)
41686797937017f52bff088d02edf64fb931177a7eaJun Nakajima            return i;
41786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    }
41886797937017f52bff088d02edf64fb931177a7eaJun Nakajima
41986797937017f52bff088d02edf64fb931177a7eaJun Nakajima    return -1;
42086797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
42186797937017f52bff088d02edf64fb931177a7eaJun Nakajima
42286797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic void apic_get_delivery_bitmask(uint32_t *deliver_bitmask,
42386797937017f52bff088d02edf64fb931177a7eaJun Nakajima                                      uint8_t dest, uint8_t dest_mode)
42486797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
42586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    APICState *apic_iter;
42686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    int i;
42786797937017f52bff088d02edf64fb931177a7eaJun Nakajima
42886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    if (dest_mode == 0) {
42986797937017f52bff088d02edf64fb931177a7eaJun Nakajima        if (dest == 0xff) {
43086797937017f52bff088d02edf64fb931177a7eaJun Nakajima            memset(deliver_bitmask, 0xff, MAX_APIC_WORDS * sizeof(uint32_t));
43186797937017f52bff088d02edf64fb931177a7eaJun Nakajima        } else {
43286797937017f52bff088d02edf64fb931177a7eaJun Nakajima            int idx = apic_find_dest(dest);
43386797937017f52bff088d02edf64fb931177a7eaJun Nakajima            memset(deliver_bitmask, 0x00, MAX_APIC_WORDS * sizeof(uint32_t));
43486797937017f52bff088d02edf64fb931177a7eaJun Nakajima            if (idx >= 0)
43586797937017f52bff088d02edf64fb931177a7eaJun Nakajima                set_bit(deliver_bitmask, idx);
43686797937017f52bff088d02edf64fb931177a7eaJun Nakajima        }
43786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    } else {
43886797937017f52bff088d02edf64fb931177a7eaJun Nakajima        /* XXX: cluster mode */
43986797937017f52bff088d02edf64fb931177a7eaJun Nakajima        memset(deliver_bitmask, 0x00, MAX_APIC_WORDS * sizeof(uint32_t));
44086797937017f52bff088d02edf64fb931177a7eaJun Nakajima        for(i = 0; i < MAX_APICS; i++) {
44186797937017f52bff088d02edf64fb931177a7eaJun Nakajima            apic_iter = local_apics[i];
44286797937017f52bff088d02edf64fb931177a7eaJun Nakajima            if (apic_iter) {
44386797937017f52bff088d02edf64fb931177a7eaJun Nakajima                if (apic_iter->dest_mode == 0xf) {
44486797937017f52bff088d02edf64fb931177a7eaJun Nakajima                    if (dest & apic_iter->log_dest)
44586797937017f52bff088d02edf64fb931177a7eaJun Nakajima                        set_bit(deliver_bitmask, i);
44686797937017f52bff088d02edf64fb931177a7eaJun Nakajima                } else if (apic_iter->dest_mode == 0x0) {
44786797937017f52bff088d02edf64fb931177a7eaJun Nakajima                    if ((dest & 0xf0) == (apic_iter->log_dest & 0xf0) &&
44886797937017f52bff088d02edf64fb931177a7eaJun Nakajima                        (dest & apic_iter->log_dest & 0x0f)) {
44986797937017f52bff088d02edf64fb931177a7eaJun Nakajima                        set_bit(deliver_bitmask, i);
45086797937017f52bff088d02edf64fb931177a7eaJun Nakajima                    }
45186797937017f52bff088d02edf64fb931177a7eaJun Nakajima                }
45286797937017f52bff088d02edf64fb931177a7eaJun Nakajima            }
45386797937017f52bff088d02edf64fb931177a7eaJun Nakajima        }
45486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    }
45586797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
45686797937017f52bff088d02edf64fb931177a7eaJun Nakajima
45786797937017f52bff088d02edf64fb931177a7eaJun Nakajima
45886797937017f52bff088d02edf64fb931177a7eaJun Nakajimavoid apic_init_reset(CPUState *env)
45986797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
46086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    APICState *s = env->apic_state;
46186797937017f52bff088d02edf64fb931177a7eaJun Nakajima    int i;
46286797937017f52bff088d02edf64fb931177a7eaJun Nakajima
46386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    if (!s)
46486797937017f52bff088d02edf64fb931177a7eaJun Nakajima        return;
46586797937017f52bff088d02edf64fb931177a7eaJun Nakajima
46686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s->tpr = 0;
46786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s->spurious_vec = 0xff;
46886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s->log_dest = 0;
46986797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s->dest_mode = 0xf;
47086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    memset(s->isr, 0, sizeof(s->isr));
47186797937017f52bff088d02edf64fb931177a7eaJun Nakajima    memset(s->tmr, 0, sizeof(s->tmr));
47286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    memset(s->irr, 0, sizeof(s->irr));
47386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    for(i = 0; i < APIC_LVT_NB; i++)
47486797937017f52bff088d02edf64fb931177a7eaJun Nakajima        s->lvt[i] = 1 << 16; /* mask LVT */
47586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s->esr = 0;
47686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    memset(s->icr, 0, sizeof(s->icr));
47786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s->divide_conf = 0;
47886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s->count_shift = 0;
47986797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s->initial_count = 0;
48086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s->initial_count_load_time = 0;
48186797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s->next_time = 0;
48286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s->wait_for_sipi = 1;
48386797937017f52bff088d02edf64fb931177a7eaJun Nakajima
48486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    env->halted = !(s->apicbase & MSR_IA32_APICBASE_BSP);
48586797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
48686797937017f52bff088d02edf64fb931177a7eaJun Nakajima
48786797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic void apic_startup(APICState *s, int vector_num)
48886797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
48986797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s->sipi_vector = vector_num;
49086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    cpu_interrupt(s->cpu_env, CPU_INTERRUPT_SIPI);
49186797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
49286797937017f52bff088d02edf64fb931177a7eaJun Nakajima
49386797937017f52bff088d02edf64fb931177a7eaJun Nakajimavoid apic_sipi(CPUState *env)
49486797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
49586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    APICState *s = env->apic_state;
49686797937017f52bff088d02edf64fb931177a7eaJun Nakajima
49786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    cpu_reset_interrupt(env, CPU_INTERRUPT_SIPI);
49886797937017f52bff088d02edf64fb931177a7eaJun Nakajima
49986797937017f52bff088d02edf64fb931177a7eaJun Nakajima    if (!s->wait_for_sipi)
50086797937017f52bff088d02edf64fb931177a7eaJun Nakajima        return;
50186797937017f52bff088d02edf64fb931177a7eaJun Nakajima
50286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    env->eip = 0;
50386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    cpu_x86_load_seg_cache(env, R_CS, s->sipi_vector << 8, s->sipi_vector << 12,
50486797937017f52bff088d02edf64fb931177a7eaJun Nakajima                           0xffff, 0);
50586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    env->halted = 0;
50686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s->wait_for_sipi = 0;
50786797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
50886797937017f52bff088d02edf64fb931177a7eaJun Nakajima
50986797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic void apic_deliver(APICState *s, uint8_t dest, uint8_t dest_mode,
51086797937017f52bff088d02edf64fb931177a7eaJun Nakajima                         uint8_t delivery_mode, uint8_t vector_num,
51186797937017f52bff088d02edf64fb931177a7eaJun Nakajima                         uint8_t polarity, uint8_t trigger_mode)
51286797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
51386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    uint32_t deliver_bitmask[MAX_APIC_WORDS];
51486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    int dest_shorthand = (s->icr[0] >> 18) & 3;
51586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    APICState *apic_iter;
51686797937017f52bff088d02edf64fb931177a7eaJun Nakajima
51786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    switch (dest_shorthand) {
51886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 0:
51986797937017f52bff088d02edf64fb931177a7eaJun Nakajima        apic_get_delivery_bitmask(deliver_bitmask, dest, dest_mode);
52086797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
52186797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 1:
52286797937017f52bff088d02edf64fb931177a7eaJun Nakajima        memset(deliver_bitmask, 0x00, sizeof(deliver_bitmask));
52386797937017f52bff088d02edf64fb931177a7eaJun Nakajima        set_bit(deliver_bitmask, s->idx);
52486797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
52586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 2:
52686797937017f52bff088d02edf64fb931177a7eaJun Nakajima        memset(deliver_bitmask, 0xff, sizeof(deliver_bitmask));
52786797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
52886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 3:
52986797937017f52bff088d02edf64fb931177a7eaJun Nakajima        memset(deliver_bitmask, 0xff, sizeof(deliver_bitmask));
53086797937017f52bff088d02edf64fb931177a7eaJun Nakajima        reset_bit(deliver_bitmask, s->idx);
53186797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
53286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    }
53386797937017f52bff088d02edf64fb931177a7eaJun Nakajima
53486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    switch (delivery_mode) {
53586797937017f52bff088d02edf64fb931177a7eaJun Nakajima        case APIC_DM_INIT:
53686797937017f52bff088d02edf64fb931177a7eaJun Nakajima            {
53786797937017f52bff088d02edf64fb931177a7eaJun Nakajima                int trig_mode = (s->icr[0] >> 15) & 1;
53886797937017f52bff088d02edf64fb931177a7eaJun Nakajima                int level = (s->icr[0] >> 14) & 1;
53986797937017f52bff088d02edf64fb931177a7eaJun Nakajima                if (level == 0 && trig_mode == 1) {
54086797937017f52bff088d02edf64fb931177a7eaJun Nakajima                    foreach_apic(apic_iter, deliver_bitmask,
54186797937017f52bff088d02edf64fb931177a7eaJun Nakajima                                 apic_iter->arb_id = apic_iter->id );
54286797937017f52bff088d02edf64fb931177a7eaJun Nakajima                    return;
54386797937017f52bff088d02edf64fb931177a7eaJun Nakajima                }
54486797937017f52bff088d02edf64fb931177a7eaJun Nakajima            }
54586797937017f52bff088d02edf64fb931177a7eaJun Nakajima            break;
54686797937017f52bff088d02edf64fb931177a7eaJun Nakajima
54786797937017f52bff088d02edf64fb931177a7eaJun Nakajima        case APIC_DM_SIPI:
54886797937017f52bff088d02edf64fb931177a7eaJun Nakajima            foreach_apic(apic_iter, deliver_bitmask,
54986797937017f52bff088d02edf64fb931177a7eaJun Nakajima                         apic_startup(apic_iter, vector_num) );
55086797937017f52bff088d02edf64fb931177a7eaJun Nakajima            return;
55186797937017f52bff088d02edf64fb931177a7eaJun Nakajima    }
55286797937017f52bff088d02edf64fb931177a7eaJun Nakajima
55386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    apic_bus_deliver(deliver_bitmask, delivery_mode, vector_num, polarity,
55486797937017f52bff088d02edf64fb931177a7eaJun Nakajima                     trigger_mode);
55586797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
55686797937017f52bff088d02edf64fb931177a7eaJun Nakajima
55786797937017f52bff088d02edf64fb931177a7eaJun Nakajimaint apic_get_interrupt(CPUState *env)
55886797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
55986797937017f52bff088d02edf64fb931177a7eaJun Nakajima    APICState *s = env->apic_state;
56086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    int intno;
56186797937017f52bff088d02edf64fb931177a7eaJun Nakajima
56286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    /* if the APIC is installed or enabled, we let the 8259 handle the
56386797937017f52bff088d02edf64fb931177a7eaJun Nakajima       IRQs */
56486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    if (!s)
56586797937017f52bff088d02edf64fb931177a7eaJun Nakajima        return -1;
56686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    if (!(s->spurious_vec & APIC_SV_ENABLE))
56786797937017f52bff088d02edf64fb931177a7eaJun Nakajima        return -1;
56886797937017f52bff088d02edf64fb931177a7eaJun Nakajima
56986797937017f52bff088d02edf64fb931177a7eaJun Nakajima    /* XXX: spurious IRQ handling */
57086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    intno = get_highest_priority_int(s->irr);
57186797937017f52bff088d02edf64fb931177a7eaJun Nakajima    if (intno < 0)
57286797937017f52bff088d02edf64fb931177a7eaJun Nakajima        return -1;
57386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    if (s->tpr && intno <= s->tpr)
57486797937017f52bff088d02edf64fb931177a7eaJun Nakajima        return s->spurious_vec & 0xff;
57586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    reset_bit(s->irr, intno);
57686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    set_bit(s->isr, intno);
57786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    apic_update_irq(s);
57886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    return intno;
57986797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
58086797937017f52bff088d02edf64fb931177a7eaJun Nakajima
58186797937017f52bff088d02edf64fb931177a7eaJun Nakajimaint apic_accept_pic_intr(CPUState *env)
58286797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
58386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    APICState *s = env->apic_state;
58486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    uint32_t lvt0;
58586797937017f52bff088d02edf64fb931177a7eaJun Nakajima
58686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    if (!s)
58786797937017f52bff088d02edf64fb931177a7eaJun Nakajima        return -1;
58886797937017f52bff088d02edf64fb931177a7eaJun Nakajima
58986797937017f52bff088d02edf64fb931177a7eaJun Nakajima    lvt0 = s->lvt[APIC_LVT_LINT0];
59086797937017f52bff088d02edf64fb931177a7eaJun Nakajima
59186797937017f52bff088d02edf64fb931177a7eaJun Nakajima    if ((s->apicbase & MSR_IA32_APICBASE_ENABLE) == 0 ||
59286797937017f52bff088d02edf64fb931177a7eaJun Nakajima        (lvt0 & APIC_LVT_MASKED) == 0)
59386797937017f52bff088d02edf64fb931177a7eaJun Nakajima        return 1;
59486797937017f52bff088d02edf64fb931177a7eaJun Nakajima
59586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    return 0;
59686797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
59786797937017f52bff088d02edf64fb931177a7eaJun Nakajima
59886797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic uint32_t apic_get_current_count(APICState *s)
59986797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
60086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    int64_t d;
60186797937017f52bff088d02edf64fb931177a7eaJun Nakajima    uint32_t val;
6025973c775c853e26f684de58ad28c267281aaffd6David 'Digit' Turner    d = (qemu_get_clock_ns(vm_clock) - s->initial_count_load_time) >>
60386797937017f52bff088d02edf64fb931177a7eaJun Nakajima        s->count_shift;
60486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    if (s->lvt[APIC_LVT_TIMER] & APIC_LVT_TIMER_PERIODIC) {
60586797937017f52bff088d02edf64fb931177a7eaJun Nakajima        /* periodic */
60686797937017f52bff088d02edf64fb931177a7eaJun Nakajima        val = s->initial_count - (d % ((uint64_t)s->initial_count + 1));
60786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    } else {
60886797937017f52bff088d02edf64fb931177a7eaJun Nakajima        if (d >= s->initial_count)
60986797937017f52bff088d02edf64fb931177a7eaJun Nakajima            val = 0;
61086797937017f52bff088d02edf64fb931177a7eaJun Nakajima        else
61186797937017f52bff088d02edf64fb931177a7eaJun Nakajima            val = s->initial_count - d;
61286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    }
61386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    return val;
61486797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
61586797937017f52bff088d02edf64fb931177a7eaJun Nakajima
61686797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic void apic_timer_update(APICState *s, int64_t current_time)
61786797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
61886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    int64_t next_time, d;
61986797937017f52bff088d02edf64fb931177a7eaJun Nakajima
62086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    if (!(s->lvt[APIC_LVT_TIMER] & APIC_LVT_MASKED)) {
62186797937017f52bff088d02edf64fb931177a7eaJun Nakajima        d = (current_time - s->initial_count_load_time) >>
62286797937017f52bff088d02edf64fb931177a7eaJun Nakajima            s->count_shift;
62386797937017f52bff088d02edf64fb931177a7eaJun Nakajima        if (s->lvt[APIC_LVT_TIMER] & APIC_LVT_TIMER_PERIODIC) {
62486797937017f52bff088d02edf64fb931177a7eaJun Nakajima            if (!s->initial_count)
62586797937017f52bff088d02edf64fb931177a7eaJun Nakajima                goto no_timer;
62686797937017f52bff088d02edf64fb931177a7eaJun Nakajima            d = ((d / ((uint64_t)s->initial_count + 1)) + 1) * ((uint64_t)s->initial_count + 1);
62786797937017f52bff088d02edf64fb931177a7eaJun Nakajima        } else {
62886797937017f52bff088d02edf64fb931177a7eaJun Nakajima            if (d >= s->initial_count)
62986797937017f52bff088d02edf64fb931177a7eaJun Nakajima                goto no_timer;
63086797937017f52bff088d02edf64fb931177a7eaJun Nakajima            d = (uint64_t)s->initial_count + 1;
63186797937017f52bff088d02edf64fb931177a7eaJun Nakajima        }
63286797937017f52bff088d02edf64fb931177a7eaJun Nakajima        next_time = s->initial_count_load_time + (d << s->count_shift);
63386797937017f52bff088d02edf64fb931177a7eaJun Nakajima        qemu_mod_timer(s->timer, next_time);
63486797937017f52bff088d02edf64fb931177a7eaJun Nakajima        s->next_time = next_time;
63586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    } else {
63686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    no_timer:
63786797937017f52bff088d02edf64fb931177a7eaJun Nakajima        qemu_del_timer(s->timer);
63886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    }
63986797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
64086797937017f52bff088d02edf64fb931177a7eaJun Nakajima
64186797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic void apic_timer(void *opaque)
64286797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
64386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    APICState *s = opaque;
64486797937017f52bff088d02edf64fb931177a7eaJun Nakajima
64586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    apic_local_deliver(s->cpu_env, APIC_LVT_TIMER);
64686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    apic_timer_update(s, s->next_time);
64786797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
64886797937017f52bff088d02edf64fb931177a7eaJun Nakajima
64986797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic uint32_t apic_mem_readb(void *opaque, target_phys_addr_t addr)
65086797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
65186797937017f52bff088d02edf64fb931177a7eaJun Nakajima    return 0;
65286797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
65386797937017f52bff088d02edf64fb931177a7eaJun Nakajima
65486797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic uint32_t apic_mem_readw(void *opaque, target_phys_addr_t addr)
65586797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
65686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    return 0;
65786797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
65886797937017f52bff088d02edf64fb931177a7eaJun Nakajima
65986797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic void apic_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
66086797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
66186797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
66286797937017f52bff088d02edf64fb931177a7eaJun Nakajima
66386797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic void apic_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
66486797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
66586797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
66686797937017f52bff088d02edf64fb931177a7eaJun Nakajima
66786797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic uint32_t apic_mem_readl(void *opaque, target_phys_addr_t addr)
66886797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
66986797937017f52bff088d02edf64fb931177a7eaJun Nakajima    CPUState *env;
67086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    APICState *s;
67186797937017f52bff088d02edf64fb931177a7eaJun Nakajima    uint32_t val;
67286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    int index;
67386797937017f52bff088d02edf64fb931177a7eaJun Nakajima
67486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    env = cpu_single_env;
67586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    if (!env)
67686797937017f52bff088d02edf64fb931177a7eaJun Nakajima        return 0;
67786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s = env->apic_state;
67886797937017f52bff088d02edf64fb931177a7eaJun Nakajima
67986797937017f52bff088d02edf64fb931177a7eaJun Nakajima    index = (addr >> 4) & 0xff;
68086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    switch(index) {
68186797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 0x02: /* id */
68286797937017f52bff088d02edf64fb931177a7eaJun Nakajima        val = s->id << 24;
68386797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
68486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 0x03: /* version */
68586797937017f52bff088d02edf64fb931177a7eaJun Nakajima        val = 0x11 | ((APIC_LVT_NB - 1) << 16); /* version 0x11 */
68686797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
68786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 0x08:
68886797937017f52bff088d02edf64fb931177a7eaJun Nakajima        val = s->tpr;
68986797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
69086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 0x09:
69186797937017f52bff088d02edf64fb931177a7eaJun Nakajima        val = apic_get_arb_pri(s);
69286797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
69386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 0x0a:
69486797937017f52bff088d02edf64fb931177a7eaJun Nakajima        /* ppr */
69586797937017f52bff088d02edf64fb931177a7eaJun Nakajima        val = apic_get_ppr(s);
69686797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
69786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 0x0b:
69886797937017f52bff088d02edf64fb931177a7eaJun Nakajima        val = 0;
69986797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
70086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 0x0d:
70186797937017f52bff088d02edf64fb931177a7eaJun Nakajima        val = s->log_dest << 24;
70286797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
70386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 0x0e:
70486797937017f52bff088d02edf64fb931177a7eaJun Nakajima        val = s->dest_mode << 28;
70586797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
70686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 0x0f:
70786797937017f52bff088d02edf64fb931177a7eaJun Nakajima        val = s->spurious_vec;
70886797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
70986797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 0x10 ... 0x17:
71086797937017f52bff088d02edf64fb931177a7eaJun Nakajima        val = s->isr[index & 7];
71186797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
71286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 0x18 ... 0x1f:
71386797937017f52bff088d02edf64fb931177a7eaJun Nakajima        val = s->tmr[index & 7];
71486797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
71586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 0x20 ... 0x27:
71686797937017f52bff088d02edf64fb931177a7eaJun Nakajima        val = s->irr[index & 7];
71786797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
71886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 0x28:
71986797937017f52bff088d02edf64fb931177a7eaJun Nakajima        val = s->esr;
72086797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
72186797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 0x30:
72286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 0x31:
72386797937017f52bff088d02edf64fb931177a7eaJun Nakajima        val = s->icr[index & 1];
72486797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
72586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 0x32 ... 0x37:
72686797937017f52bff088d02edf64fb931177a7eaJun Nakajima        val = s->lvt[index - 0x32];
72786797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
72886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 0x38:
72986797937017f52bff088d02edf64fb931177a7eaJun Nakajima        val = s->initial_count;
73086797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
73186797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 0x39:
73286797937017f52bff088d02edf64fb931177a7eaJun Nakajima        val = apic_get_current_count(s);
73386797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
73486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 0x3e:
73586797937017f52bff088d02edf64fb931177a7eaJun Nakajima        val = s->divide_conf;
73686797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
73786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    default:
73886797937017f52bff088d02edf64fb931177a7eaJun Nakajima        s->esr |= ESR_ILLEGAL_ADDRESS;
73986797937017f52bff088d02edf64fb931177a7eaJun Nakajima        val = 0;
74086797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
74186797937017f52bff088d02edf64fb931177a7eaJun Nakajima    }
74286797937017f52bff088d02edf64fb931177a7eaJun Nakajima#ifdef DEBUG_APIC
74386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    printf("APIC read: %08x = %08x\n", (uint32_t)addr, val);
74486797937017f52bff088d02edf64fb931177a7eaJun Nakajima#endif
74586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    return val;
74686797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
74786797937017f52bff088d02edf64fb931177a7eaJun Nakajima
74886797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic void apic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
74986797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
75086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    CPUState *env;
75186797937017f52bff088d02edf64fb931177a7eaJun Nakajima    APICState *s;
75286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    int index;
75386797937017f52bff088d02edf64fb931177a7eaJun Nakajima
75486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    env = cpu_single_env;
75586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    if (!env)
75686797937017f52bff088d02edf64fb931177a7eaJun Nakajima        return;
75786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s = env->apic_state;
75886797937017f52bff088d02edf64fb931177a7eaJun Nakajima
75986797937017f52bff088d02edf64fb931177a7eaJun Nakajima#ifdef DEBUG_APIC
76086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    printf("APIC write: %08x = %08x\n", (uint32_t)addr, val);
76186797937017f52bff088d02edf64fb931177a7eaJun Nakajima#endif
76286797937017f52bff088d02edf64fb931177a7eaJun Nakajima
76386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    index = (addr >> 4) & 0xff;
76486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    switch(index) {
76586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 0x02:
76686797937017f52bff088d02edf64fb931177a7eaJun Nakajima        s->id = (val >> 24);
76786797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
76886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 0x03:
76986797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
77086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 0x08:
77186797937017f52bff088d02edf64fb931177a7eaJun Nakajima        s->tpr = val;
77286797937017f52bff088d02edf64fb931177a7eaJun Nakajima        apic_update_irq(s);
77386797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
77486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 0x09:
77586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 0x0a:
77686797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
77786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 0x0b: /* EOI */
77886797937017f52bff088d02edf64fb931177a7eaJun Nakajima        apic_eoi(s);
77986797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
78086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 0x0d:
78186797937017f52bff088d02edf64fb931177a7eaJun Nakajima        s->log_dest = val >> 24;
78286797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
78386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 0x0e:
78486797937017f52bff088d02edf64fb931177a7eaJun Nakajima        s->dest_mode = val >> 28;
78586797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
78686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 0x0f:
78786797937017f52bff088d02edf64fb931177a7eaJun Nakajima        s->spurious_vec = val & 0x1ff;
78886797937017f52bff088d02edf64fb931177a7eaJun Nakajima        apic_update_irq(s);
78986797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
79086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 0x10 ... 0x17:
79186797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 0x18 ... 0x1f:
79286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 0x20 ... 0x27:
79386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 0x28:
79486797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
79586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 0x30:
79686797937017f52bff088d02edf64fb931177a7eaJun Nakajima        s->icr[0] = val;
79786797937017f52bff088d02edf64fb931177a7eaJun Nakajima        apic_deliver(s, (s->icr[1] >> 24) & 0xff, (s->icr[0] >> 11) & 1,
79886797937017f52bff088d02edf64fb931177a7eaJun Nakajima                     (s->icr[0] >> 8) & 7, (s->icr[0] & 0xff),
79986797937017f52bff088d02edf64fb931177a7eaJun Nakajima                     (s->icr[0] >> 14) & 1, (s->icr[0] >> 15) & 1);
80086797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
80186797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 0x31:
80286797937017f52bff088d02edf64fb931177a7eaJun Nakajima        s->icr[1] = val;
80386797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
80486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 0x32 ... 0x37:
80586797937017f52bff088d02edf64fb931177a7eaJun Nakajima        {
80686797937017f52bff088d02edf64fb931177a7eaJun Nakajima            int n = index - 0x32;
80786797937017f52bff088d02edf64fb931177a7eaJun Nakajima            s->lvt[n] = val;
80886797937017f52bff088d02edf64fb931177a7eaJun Nakajima            if (n == APIC_LVT_TIMER)
8095973c775c853e26f684de58ad28c267281aaffd6David 'Digit' Turner                apic_timer_update(s, qemu_get_clock_ns(vm_clock));
81086797937017f52bff088d02edf64fb931177a7eaJun Nakajima        }
81186797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
81286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 0x38:
81386797937017f52bff088d02edf64fb931177a7eaJun Nakajima        s->initial_count = val;
8145973c775c853e26f684de58ad28c267281aaffd6David 'Digit' Turner        s->initial_count_load_time = qemu_get_clock_ns(vm_clock);
81586797937017f52bff088d02edf64fb931177a7eaJun Nakajima        apic_timer_update(s, s->initial_count_load_time);
81686797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
81786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 0x39:
81886797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
81986797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 0x3e:
82086797937017f52bff088d02edf64fb931177a7eaJun Nakajima        {
82186797937017f52bff088d02edf64fb931177a7eaJun Nakajima            int v;
82286797937017f52bff088d02edf64fb931177a7eaJun Nakajima            s->divide_conf = val & 0xb;
82386797937017f52bff088d02edf64fb931177a7eaJun Nakajima            v = (s->divide_conf & 3) | ((s->divide_conf >> 1) & 4);
82486797937017f52bff088d02edf64fb931177a7eaJun Nakajima            s->count_shift = (v + 1) & 7;
82586797937017f52bff088d02edf64fb931177a7eaJun Nakajima        }
82686797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
82786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    default:
82886797937017f52bff088d02edf64fb931177a7eaJun Nakajima        s->esr |= ESR_ILLEGAL_ADDRESS;
82986797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
83086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    }
83186797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
83286797937017f52bff088d02edf64fb931177a7eaJun Nakajima
83386797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic void apic_save(QEMUFile *f, void *opaque)
83486797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
83586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    APICState *s = opaque;
83686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    int i;
83786797937017f52bff088d02edf64fb931177a7eaJun Nakajima
83886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    qemu_put_be32s(f, &s->apicbase);
83986797937017f52bff088d02edf64fb931177a7eaJun Nakajima    qemu_put_8s(f, &s->id);
84086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    qemu_put_8s(f, &s->arb_id);
84186797937017f52bff088d02edf64fb931177a7eaJun Nakajima    qemu_put_8s(f, &s->tpr);
84286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    qemu_put_be32s(f, &s->spurious_vec);
84386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    qemu_put_8s(f, &s->log_dest);
84486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    qemu_put_8s(f, &s->dest_mode);
84586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    for (i = 0; i < 8; i++) {
84686797937017f52bff088d02edf64fb931177a7eaJun Nakajima        qemu_put_be32s(f, &s->isr[i]);
84786797937017f52bff088d02edf64fb931177a7eaJun Nakajima        qemu_put_be32s(f, &s->tmr[i]);
84886797937017f52bff088d02edf64fb931177a7eaJun Nakajima        qemu_put_be32s(f, &s->irr[i]);
84986797937017f52bff088d02edf64fb931177a7eaJun Nakajima    }
85086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    for (i = 0; i < APIC_LVT_NB; i++) {
85186797937017f52bff088d02edf64fb931177a7eaJun Nakajima        qemu_put_be32s(f, &s->lvt[i]);
85286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    }
85386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    qemu_put_be32s(f, &s->esr);
85486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    qemu_put_be32s(f, &s->icr[0]);
85586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    qemu_put_be32s(f, &s->icr[1]);
85686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    qemu_put_be32s(f, &s->divide_conf);
85786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    qemu_put_be32(f, s->count_shift);
85886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    qemu_put_be32s(f, &s->initial_count);
85986797937017f52bff088d02edf64fb931177a7eaJun Nakajima    qemu_put_be64(f, s->initial_count_load_time);
86086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    qemu_put_be64(f, s->next_time);
86186797937017f52bff088d02edf64fb931177a7eaJun Nakajima
86286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    qemu_put_timer(f, s->timer);
86386797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
86486797937017f52bff088d02edf64fb931177a7eaJun Nakajima
86586797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic int apic_load(QEMUFile *f, void *opaque, int version_id)
86686797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
86786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    APICState *s = opaque;
86886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    int i;
86986797937017f52bff088d02edf64fb931177a7eaJun Nakajima
87086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    if (version_id > 2)
87186797937017f52bff088d02edf64fb931177a7eaJun Nakajima        return -EINVAL;
87286797937017f52bff088d02edf64fb931177a7eaJun Nakajima
87386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    /* XXX: what if the base changes? (registered memory regions) */
87486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    qemu_get_be32s(f, &s->apicbase);
87586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    qemu_get_8s(f, &s->id);
87686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    qemu_get_8s(f, &s->arb_id);
87786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    qemu_get_8s(f, &s->tpr);
87886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    qemu_get_be32s(f, &s->spurious_vec);
87986797937017f52bff088d02edf64fb931177a7eaJun Nakajima    qemu_get_8s(f, &s->log_dest);
88086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    qemu_get_8s(f, &s->dest_mode);
88186797937017f52bff088d02edf64fb931177a7eaJun Nakajima    for (i = 0; i < 8; i++) {
88286797937017f52bff088d02edf64fb931177a7eaJun Nakajima        qemu_get_be32s(f, &s->isr[i]);
88386797937017f52bff088d02edf64fb931177a7eaJun Nakajima        qemu_get_be32s(f, &s->tmr[i]);
88486797937017f52bff088d02edf64fb931177a7eaJun Nakajima        qemu_get_be32s(f, &s->irr[i]);
88586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    }
88686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    for (i = 0; i < APIC_LVT_NB; i++) {
88786797937017f52bff088d02edf64fb931177a7eaJun Nakajima        qemu_get_be32s(f, &s->lvt[i]);
88886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    }
88986797937017f52bff088d02edf64fb931177a7eaJun Nakajima    qemu_get_be32s(f, &s->esr);
89086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    qemu_get_be32s(f, &s->icr[0]);
89186797937017f52bff088d02edf64fb931177a7eaJun Nakajima    qemu_get_be32s(f, &s->icr[1]);
89286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    qemu_get_be32s(f, &s->divide_conf);
89386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s->count_shift=qemu_get_be32(f);
89486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    qemu_get_be32s(f, &s->initial_count);
89586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s->initial_count_load_time=qemu_get_be64(f);
89686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s->next_time=qemu_get_be64(f);
89786797937017f52bff088d02edf64fb931177a7eaJun Nakajima
89886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    if (version_id >= 2)
89986797937017f52bff088d02edf64fb931177a7eaJun Nakajima        qemu_get_timer(f, s->timer);
90086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    return 0;
90186797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
90286797937017f52bff088d02edf64fb931177a7eaJun Nakajima
90386797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic void apic_reset(void *opaque)
90486797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
90586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    APICState *s = opaque;
90686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    int bsp = cpu_is_bsp(s->cpu_env);
90786797937017f52bff088d02edf64fb931177a7eaJun Nakajima
90886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s->apicbase = 0xfee00000 |
90986797937017f52bff088d02edf64fb931177a7eaJun Nakajima        (bsp ? MSR_IA32_APICBASE_BSP : 0) | MSR_IA32_APICBASE_ENABLE;
91086797937017f52bff088d02edf64fb931177a7eaJun Nakajima
91186797937017f52bff088d02edf64fb931177a7eaJun Nakajima    cpu_reset(s->cpu_env);
91286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    apic_init_reset(s->cpu_env);
91386797937017f52bff088d02edf64fb931177a7eaJun Nakajima
91486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    if (bsp) {
91586797937017f52bff088d02edf64fb931177a7eaJun Nakajima        /*
91686797937017f52bff088d02edf64fb931177a7eaJun Nakajima         * LINT0 delivery mode on CPU #0 is set to ExtInt at initialization
91786797937017f52bff088d02edf64fb931177a7eaJun Nakajima         * time typically by BIOS, so PIC interrupt can be delivered to the
91886797937017f52bff088d02edf64fb931177a7eaJun Nakajima         * processor when local APIC is enabled.
91986797937017f52bff088d02edf64fb931177a7eaJun Nakajima         */
92086797937017f52bff088d02edf64fb931177a7eaJun Nakajima        s->lvt[APIC_LVT_LINT0] = 0x700;
92186797937017f52bff088d02edf64fb931177a7eaJun Nakajima    }
92286797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
92386797937017f52bff088d02edf64fb931177a7eaJun Nakajima
92486797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic CPUReadMemoryFunc *apic_mem_read[3] = {
92586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    apic_mem_readb,
92686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    apic_mem_readw,
92786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    apic_mem_readl,
92886797937017f52bff088d02edf64fb931177a7eaJun Nakajima};
92986797937017f52bff088d02edf64fb931177a7eaJun Nakajima
93086797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic CPUWriteMemoryFunc *apic_mem_write[3] = {
93186797937017f52bff088d02edf64fb931177a7eaJun Nakajima    apic_mem_writeb,
93286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    apic_mem_writew,
93386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    apic_mem_writel,
93486797937017f52bff088d02edf64fb931177a7eaJun Nakajima};
93586797937017f52bff088d02edf64fb931177a7eaJun Nakajima
93686797937017f52bff088d02edf64fb931177a7eaJun Nakajimaint apic_init(CPUState *env)
93786797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
93886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    APICState *s;
93986797937017f52bff088d02edf64fb931177a7eaJun Nakajima
94086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    if (last_apic_idx >= MAX_APICS)
94186797937017f52bff088d02edf64fb931177a7eaJun Nakajima        return -1;
94286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s = qemu_mallocz(sizeof(APICState));
94386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    env->apic_state = s;
94486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s->idx = last_apic_idx++;
94586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s->id = env->cpuid_apic_id;
94686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s->cpu_env = env;
94786797937017f52bff088d02edf64fb931177a7eaJun Nakajima
94886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    apic_reset(s);
94986797937017f52bff088d02edf64fb931177a7eaJun Nakajima
95086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    /* XXX: mapping more APICs at the same memory location */
95186797937017f52bff088d02edf64fb931177a7eaJun Nakajima    if (apic_io_memory == 0) {
95286797937017f52bff088d02edf64fb931177a7eaJun Nakajima        /* NOTE: the APIC is directly connected to the CPU - it is not
95386797937017f52bff088d02edf64fb931177a7eaJun Nakajima           on the global memory bus. */
95486797937017f52bff088d02edf64fb931177a7eaJun Nakajima        apic_io_memory = cpu_register_io_memory(apic_mem_read,
95586797937017f52bff088d02edf64fb931177a7eaJun Nakajima                                                apic_mem_write, NULL);
95686797937017f52bff088d02edf64fb931177a7eaJun Nakajima        cpu_register_physical_memory(s->apicbase & ~0xfff, 0x1000,
95786797937017f52bff088d02edf64fb931177a7eaJun Nakajima                                     apic_io_memory);
95886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    }
9595973c775c853e26f684de58ad28c267281aaffd6David 'Digit' Turner    s->timer = qemu_new_timer_ns(vm_clock, apic_timer, s);
96086797937017f52bff088d02edf64fb931177a7eaJun Nakajima
96186797937017f52bff088d02edf64fb931177a7eaJun Nakajima    register_savevm("apic", s->idx, 2, apic_save, apic_load, s);
96286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    qemu_register_reset(apic_reset, 0, s);
96386797937017f52bff088d02edf64fb931177a7eaJun Nakajima
96486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    local_apics[s->idx] = s;
96586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    return 0;
96686797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
96786797937017f52bff088d02edf64fb931177a7eaJun Nakajima
968