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