summaryrefslogtreecommitdiff
path: root/kvm_x86.c
diff options
context:
space:
mode:
authorBryan Cantrill <bryan@joyent.com>2011-05-22 14:51:55 -0700
committerBryan Cantrill <bryan@joyent.com>2011-05-22 14:51:55 -0700
commit2a5f4abd23b30927577f0426b54f5d6a9ee767cd (patch)
tree9526bf449603d47dba6c3860f202093161af67b1 /kvm_x86.c
parent2b9c6b5cbe083dcc307820bbf2c99d78ce4dd1d9 (diff)
downloadillumos-kvm-2a5f4abd23b30927577f0426b54f5d6a9ee767cd.tar.gz
HVM-221 move local APIC functionality to kvm_lapic.c
Diffstat (limited to 'kvm_x86.c')
-rw-r--r--kvm_x86.c813
1 files changed, 0 insertions, 813 deletions
diff --git a/kvm_x86.c b/kvm_x86.c
index d678552..7863d95 100644
--- a/kvm_x86.c
+++ b/kvm_x86.c
@@ -55,10 +55,6 @@ extern int native_write_msr_safe(unsigned int msr, unsigned low, unsigned high);
extern unsigned long find_first_zero_bit(const unsigned long *addr,
unsigned long size);
-extern int kvm_apic_present(struct kvm_vcpu *vcpu);
-extern int kvm_lapic_enabled(struct kvm_vcpu *vcpu);
-extern void kvm_lapic_reset(struct kvm_vcpu *vcpu);
-extern int vm_need_virtualize_apic_accesses(struct kvm *kvm);
extern uint32_t vmcs_read32(unsigned long field);
extern uint16_t vmcs_read16(unsigned long field);
extern ulong kvm_read_cr4(struct kvm_vcpu *vcpu);
@@ -403,7 +399,6 @@ vmx_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags)
vmcs_writel(GUEST_RFLAGS, rflags);
}
-
extern void kvm_shared_msr_cpu_online(void);
int
@@ -621,251 +616,14 @@ kvm_mmu_create(struct kvm_vcpu *vcpu)
return (alloc_mmu_pages(vcpu));
}
-inline uint32_t
-apic_get_reg(struct kvm_lapic *apic, int reg_off)
-{
- return (*((uint32_t *)((uintptr_t)apic->regs + reg_off)));
-}
-
-void
-apic_set_reg(struct kvm_lapic *apic, int reg_off, uint32_t val)
-{
- *((uint32_t *)((uintptr_t)apic->regs + reg_off)) = val;
-}
-
static inline int
apic_x2apic_mode(struct kvm_lapic *apic)
{
return (apic->vcpu->arch.apic_base & X2APIC_ENABLE);
}
-static uint32_t
-apic_get_tmcct(struct kvm_lapic *apic)
-{
- hrtime_t now, remaining, elapsed;
- uint32_t tmcct;
-
- VERIFY(apic != NULL);
-
- /* if initial count is 0, current count should also be 0 */
- if (apic_get_reg(apic, APIC_TMICT) == 0)
- return (0);
-
- now = gethrtime();
- elapsed = now - apic->lapic_timer.start -
- apic->lapic_timer.period * apic->lapic_timer.intervals;
- remaining = apic->lapic_timer.period - elapsed;
-
- if (remaining < 0)
- remaining = 0;
-
- remaining = remaining % apic->lapic_timer.period;
- tmcct = remaining / (APIC_BUS_CYCLE_NS * apic->divide_count);
-
- return (tmcct);
-}
-
extern unsigned long kvm_rip_read(struct kvm_vcpu *vcpu);
-static void
-__report_tpr_access(struct kvm_lapic *apic, int write)
-{
- struct kvm_vcpu *vcpu = apic->vcpu;
- struct kvm_run *run = vcpu->run;
-
- set_bit(KVM_REQ_REPORT_TPR_ACCESS, &vcpu->requests);
- run->tpr_access.rip = kvm_rip_read(vcpu);
- run->tpr_access.is_write = write;
-}
-
-static inline void
-report_tpr_access(struct kvm_lapic *apic, int write)
-{
- if (apic->vcpu->arch.tpr_access_reporting)
- __report_tpr_access(apic, write);
-}
-
-extern void apic_update_ppr(struct kvm_lapic *apic);
-
-int
-kvm_apic_id(struct kvm_lapic *apic)
-{
- return ((apic_get_reg(apic, APIC_ID) >> 24) & 0xff);
-}
-
-static uint32_t
-__apic_read(struct kvm_lapic *apic, unsigned int offset)
-{
- uint32_t val = 0;
-
- if (offset >= LAPIC_MMIO_LENGTH)
- return (0);
-
- switch (offset) {
- case APIC_ID:
- if (apic_x2apic_mode(apic))
- val = kvm_apic_id(apic);
- else
- val = kvm_apic_id(apic) << 24;
- break;
- case APIC_ARBPRI:
- cmn_err(CE_WARN, "Access APIC ARBPRI register "
- "which is for P6\n");
- break;
-
- case APIC_TMCCT: /* Timer CCR */
- val = apic_get_tmcct(apic);
- break;
-
- case APIC_TASKPRI:
- report_tpr_access(apic, 0);
- /* fall thru */
- default:
- apic_update_ppr(apic);
- val = apic_get_reg(apic, offset);
- break;
- }
-
- return (val);
-}
-
-static inline struct kvm_lapic *
-to_lapic(struct kvm_io_device *dev)
-{
-#ifdef XXX
- return (container_of(dev, struct kvm_lapic, dev));
-#else
- XXX_KVM_PROBE;
- return (dev->lapic);
-#endif
-}
-
-int
-apic_reg_read(struct kvm_lapic *apic, uint32_t offset, int len, void *data)
-{
- unsigned char alignment = offset & 0xf;
- uint32_t result;
- /* this bitmask has a bit cleared for each reserver register */
- static const uint64_t rmask = 0x43ff01ffffffe70cULL;
-
- if ((alignment + len) > 4) {
- return (1);
- }
-
- if (offset > 0x3f0 || !(rmask & (1ULL << (offset >> 4)))) {
- return (1);
- }
-
- result = __apic_read(apic, offset & ~0xf);
-#ifdef XXX_KVM_TRACE
- trace_kvm_apic_read(offset, result);
-#endif
-
- switch (len) {
- case 1:
- case 2:
- case 4:
- memcpy(data, (char *)&result + alignment, len);
- break;
- default:
- cmn_err(CE_WARN, "Local APIC read with len = %x, "
- "should be 1,2, or 4 instead\n", len);
- break;
- }
-
- return (0);
-}
-
-inline int
-apic_hw_enabled(struct kvm_lapic *apic)
-{
- return ((apic)->vcpu->arch.apic_base & MSR_IA32_APICBASE_ENABLE);
-}
-
-static int
-apic_mmio_in_range(struct kvm_lapic *apic, gpa_t addr)
-{
- return (apic_hw_enabled(apic) &&
- addr >= apic->base_address &&
- addr < apic->base_address + LAPIC_MMIO_LENGTH);
-}
-
-static int
-apic_mmio_read(struct kvm_io_device *this, gpa_t address, int len, void *data)
-{
- struct kvm_lapic *apic = to_lapic(this);
- uint32_t offset = address - apic->base_address;
-
- if (!apic_mmio_in_range(apic, address))
- return (-EOPNOTSUPP);
-
- apic_reg_read(apic, offset, len, data);
-
- return (0);
-}
-
-#define LVT_MASK \
- (APIC_LVT_MASKED | APIC_SEND_PENDING | APIC_VECTOR_MASK)
-
-#define LINT_MASK \
- (LVT_MASK | APIC_MODE_MASK | APIC_INPUT_POLARITY | \
- APIC_LVT_REMOTE_IRR | APIC_LVT_LEVEL_TRIGGER)
-
-static unsigned int apic_lvt_mask[APIC_LVT_NUM] = {
- LVT_MASK | APIC_LVT_TIMER_PERIODIC, /* LVTT */
- LVT_MASK | APIC_MODE_MASK, /* LVTTHMR */
- LVT_MASK | APIC_MODE_MASK, /* LVTPC */
- LINT_MASK, LINT_MASK, /* LVT0-1 */
- LVT_MASK /* LVTERR */
-};
-
-static int apic_lvtt_period(struct kvm_lapic *apic)
-{
- return (apic_get_reg(apic, APIC_LVTT) & APIC_LVT_TIMER_PERIODIC);
-}
-
-void
-start_apic_timer(struct kvm_lapic *apic)
-{
- hrtime_t now = gethrtime();
-
- apic->lapic_timer.period = (uint64_t)apic_get_reg(apic, APIC_TMICT) *
- APIC_BUS_CYCLE_NS * apic->divide_count;
-
- if (!apic->lapic_timer.period)
- return;
-
- mutex_enter(&cpu_lock);
-
- apic->lapic_timer.start = gethrtime();
-
- /*
- * Do not allow the guest to program periodic timers with small
- * interval, since the hrtimers are not throttled by the host
- * scheduler.
- *
- * If it is a one shot, we want to program it differently.
- */
- if (apic_lvtt_period(apic)) {
- if (apic->lapic_timer.period < NSEC_PER_MSEC / 2)
- apic->lapic_timer.period = NSEC_PER_MSEC / 2;
- apic->lapic_timer.kvm_cyc_when.cyt_when = 0;
- apic->lapic_timer.kvm_cyc_when.cyt_interval =
- apic->lapic_timer.period;
- } else {
- apic->lapic_timer.kvm_cyc_when.cyt_when =
- apic->lapic_timer.start + apic->lapic_timer.period;
- apic->lapic_timer.kvm_cyc_when.cyt_interval = CY_INFINITY;
- }
-
- apic->lapic_timer.kvm_cyclic_id =
- cyclic_add(&apic->lapic_timer.kvm_cyc_handler,
- &apic->lapic_timer.kvm_cyc_when);
- apic->lapic_timer.active = 1;
- apic->lapic_timer.intervals = 0;
- mutex_exit(&cpu_lock);
-}
-
inline static int
kvm_is_dm_lowest_prio(struct kvm_lapic_irq *irq)
{
@@ -877,223 +635,12 @@ kvm_is_dm_lowest_prio(struct kvm_lapic_irq *irq)
#endif
}
-#define VEC_POS(v) ((v) & (32 - 1))
-#define REG_POS(v) (((v) >> 5) << 4)
-
-inline void
-apic_clear_vector(int vec, caddr_t bitmap)
-{
- clear_bit(VEC_POS(vec), (unsigned long *)(bitmap + REG_POS(vec)));
-}
-
void
kvm_inject_nmi(struct kvm_vcpu *vcpu)
{
vcpu->arch.nmi_pending = 1;
}
-inline void
-apic_set_vector(int vec, caddr_t bitmap)
-{
- set_bit(VEC_POS(vec), (unsigned long *)(bitmap + REG_POS(vec)));
-}
-
-static inline int
-apic_test_and_set_vector(int vec, caddr_t bitmap)
-{
- return (test_and_set_bit(VEC_POS(vec), (unsigned long *)(bitmap +
- REG_POS(vec))));
-}
-
-
-static inline int
-apic_test_and_set_irr(int vec, struct kvm_lapic *apic)
-{
- apic->irr_pending = 1;
- return (apic_test_and_set_vector(vec, (void *)((uintptr_t)apic->regs +
- APIC_IRR)));
-}
-
-inline int
-apic_sw_enabled(struct kvm_lapic *apic)
-{
- return (apic_get_reg(apic, APIC_SPIV) & APIC_SPIV_APIC_ENABLED);
-}
-
-inline int
-apic_enabled(struct kvm_lapic *apic)
-{
- return (apic_sw_enabled(apic) && apic_hw_enabled(apic));
-}
-
-/*
- * Add a pending IRQ into lapic.
- * Return 1 if successfully added and 0 if discarded.
- */
-int
-__apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
- int vector, int level, int trig_mode)
-{
- int result = 0;
- struct kvm_vcpu *vcpu = apic->vcpu;
-
- switch (delivery_mode) {
- case APIC_DM_LOWEST:
- vcpu->arch.apic_arb_prio++;
- case APIC_DM_FIXED:
- /* FIXME add logic for vcpu on reset */
- if (!apic_enabled(apic))
- break;
-
- if (trig_mode) {
- apic_set_vector(vector, (void *)((uintptr_t)apic->regs +
- APIC_TMR));
- } else
- apic_clear_vector(vector,
- (void *)((uintptr_t)apic->regs + APIC_TMR));
-
- result = !apic_test_and_set_irr(vector, apic);
- if (!result) {
- break;
- }
-
- kvm_vcpu_kick(vcpu);
- break;
-
- case APIC_DM_REMRD:
- break;
-
- case APIC_DM_SMI:
- break;
-
- case APIC_DM_NMI:
- result = 1;
- kvm_inject_nmi(vcpu);
- kvm_vcpu_kick(vcpu);
- break;
-
- case APIC_DM_INIT:
- if (level) {
- result = 1;
- vcpu->arch.mp_state = KVM_MP_STATE_INIT_RECEIVED;
- kvm_vcpu_kick(vcpu);
- }
- break;
-
- case APIC_DM_STARTUP:
- if (vcpu->arch.mp_state == KVM_MP_STATE_INIT_RECEIVED) {
- result = 1;
- vcpu->arch.sipi_vector = vector;
- vcpu->arch.mp_state = KVM_MP_STATE_SIPI_RECEIVED;
- kvm_vcpu_kick(vcpu);
- }
- break;
-
- case APIC_DM_EXTINT:
- /*
- * Should only be called by kvm_apic_local_deliver() with LVT0,
- * before NMI watchdog was enabled. Already handled by
- * kvm_apic_accept_pic_intr().
- */
- break;
-
- default:
- break;
- }
- return (result);
-}
-
-int
-kvm_apic_set_irq(struct kvm_vcpu *vcpu, struct kvm_lapic_irq *irq)
-{
- struct kvm_lapic *apic = vcpu->arch.apic;
-
- return (__apic_accept_irq(apic, irq->delivery_mode, irq->vector,
- irq->level, irq->trig_mode));
-}
-
-int
-kvm_apic_match_physical_addr(struct kvm_lapic *apic, uint16_t dest)
-{
- return (dest == 0xff || kvm_apic_id(apic) == dest);
-}
-
-int
-kvm_apic_match_logical_addr(struct kvm_lapic *apic, uint8_t mda)
-{
- int result = 0;
- uint32_t logical_id;
-
- if (apic_x2apic_mode(apic)) {
- logical_id = apic_get_reg(apic, APIC_LDR);
- return (logical_id & mda);
- }
-
- logical_id = GET_APIC_LOGICAL_ID(apic_get_reg(apic, APIC_LDR));
-
- switch (apic_get_reg(apic, APIC_DFR)) {
- case APIC_DFR_FLAT:
- if (logical_id & mda)
- result = 1;
- break;
- case APIC_DFR_CLUSTER:
- if (((logical_id >> 4) == (mda >> 0x4)) &&
- (logical_id & mda & 0xf))
- result = 1;
- break;
- default:
- cmn_err(CE_WARN, "Bad DFR vcpu %d: %08x\n",
- apic->vcpu->vcpu_id, apic_get_reg(apic, APIC_DFR));
- break;
- }
-
- return (result);
-}
-
-int
-kvm_apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source,
- int short_hand, int dest, int dest_mode)
-{
- int result = 0;
- struct kvm_lapic *target = vcpu->arch.apic;
-
- /* XXX - debug */
- cmn_err(CE_NOTE, "target %p, source %p, dest 0x%x, dest_mode 0x%x, "
- "short_hand 0x%x\n", target, source, dest, dest_mode, short_hand);
-
- ASSERT(target != NULL);
- switch (short_hand) {
- case APIC_DEST_NOSHORT:
- if (dest_mode == 0)
- /* Physical mode. */
- result = kvm_apic_match_physical_addr(target, dest);
- else
- /* Logical mode. */
- result = kvm_apic_match_logical_addr(target, dest);
- break;
- case APIC_DEST_SELF:
- result = (target == source);
- break;
- case APIC_DEST_ALLINC:
- result = 1;
- break;
- case APIC_DEST_ALLBUT:
- result = (target != source);
- break;
- default:
- cmn_err(CE_WARN, "Bad dest shorthand value %x\n", short_hand);
- break;
- }
-
- return (result);
-}
-
-int
-kvm_apic_compare_prio(struct kvm_vcpu *vcpu1, struct kvm_vcpu *vcpu2)
-{
- return (vcpu1->arch.apic_arb_prio - vcpu2->arch.apic_arb_prio);
-}
-
int
kvm_irq_delivery_to_apic(struct kvm *kvm, struct kvm_lapic *src,
struct kvm_lapic_irq *irq)
@@ -1137,49 +684,6 @@ kvm_irq_delivery_to_apic(struct kvm *kvm, struct kvm_lapic *src,
return (r);
}
-static void
-apic_send_ipi(struct kvm_lapic *apic)
-{
- uint32_t icr_low = apic_get_reg(apic, APIC_ICR);
- uint32_t icr_high = apic_get_reg(apic, APIC_ICR2);
- struct kvm_lapic_irq irq;
-
- irq.vector = icr_low & APIC_VECTOR_MASK;
- irq.delivery_mode = icr_low & APIC_MODE_MASK;
- irq.dest_mode = icr_low & APIC_DEST_MASK;
- irq.level = icr_low & APIC_INT_ASSERT;
- irq.trig_mode = icr_low & APIC_INT_LEVELTRIG;
- irq.shorthand = icr_low & APIC_SHORT_MASK;
- if (apic_x2apic_mode(apic))
- irq.dest_id = icr_high;
- else
- irq.dest_id = GET_APIC_DEST_FIELD(icr_high);
-
-#ifdef XXX_KVM_TRACE
- trace_kvm_apic_ipi(icr_low, irq.dest_id);
-#endif
-
- kvm_irq_delivery_to_apic(apic->vcpu->kvm, apic, &irq);
-}
-
-void
-update_divide_count(struct kvm_lapic *apic)
-{
- uint32_t tmp1, tmp2, tdcr;
-
- tdcr = apic_get_reg(apic, APIC_TDCR);
- tmp1 = tdcr & 0xf;
- tmp2 = ((tmp1 & 0x3) | ((tmp1 & 0x8) >> 1)) + 1;
- apic->divide_count = 0x1 << (tmp2 & 0x7);
-}
-
-void
-apic_set_tpr(struct kvm_lapic *apic, uint32_t tpr)
-{
- apic_set_reg(apic, APIC_TASKPRI, tpr);
- apic_update_ppr(apic);
-}
-
static int
ioapic_deliver(struct kvm_ioapic *ioapic, int irq)
{
@@ -1263,288 +767,8 @@ __kvm_ioapic_update_eoi(struct kvm_ioapic *ioapic, int vector, int trigger_mode)
}
}
-extern void kvm_ioapic_update_eoi(struct kvm *kvm,
- int vector, int trigger_mode);
-extern inline int apic_find_highest_isr(struct kvm_lapic *apic);
-
-static inline int
-apic_test_and_clear_vector(int vec, caddr_t bitmap)
-{
-#ifndef XXX
- return (test_and_clear_bit(VEC_POS(vec),
- (unsigned long *)(bitmap + REG_POS(vec))));
-#else
- if (BT_TEST((bitmap) + REG_POS(vec), VEC_POS(vec))) {
- BT_CLEAR((bitmap) + REG_POS(vec), VEC_POS(vec));
- return (1);
- } else
- return (0);
-#endif
-}
-
-static inline int
-apic_lvt_nmi_mode(uint32_t lvt_val)
-{
- return ((lvt_val & (APIC_MODE_MASK | APIC_LVT_MASKED)) == APIC_DM_NMI);
-}
-
-static void
-apic_manage_nmi_watchdog(struct kvm_lapic *apic, uint32_t lvt0_val)
-{
- int nmi_wd_enabled = apic_lvt_nmi_mode(apic_get_reg(apic, APIC_LVT0));
-
- if (apic_lvt_nmi_mode(lvt0_val)) {
- if (!nmi_wd_enabled) {
- /* XXX - debug */
- cmn_err(CE_NOTE, "Receive NMI setting on APIC_LVT0 "
- "for cpu %d\n", apic->vcpu->vcpu_id);
- apic->vcpu->kvm->arch.vapics_in_nmi_mode++;
- }
- } else if (nmi_wd_enabled)
- apic->vcpu->kvm->arch.vapics_in_nmi_mode--;
-}
-
-static void
-apic_set_eoi(struct kvm_lapic *apic)
-{
- int vector = apic_find_highest_isr(apic);
- int trigger_mode;
- /*
- * Not every write EOI will has corresponding ISR,
- * one example is when Kernel check timer on setup_IO_APIC
- */
- if (vector == -1)
- return;
-
- apic_clear_vector(vector, (void *)((uintptr_t)apic->regs + APIC_ISR));
- apic_update_ppr(apic);
-
- if (apic_test_and_clear_vector(vector, (void *)((uintptr_t)apic->regs +
- APIC_TMR)))
- trigger_mode = IOAPIC_LEVEL_TRIG;
- else
- trigger_mode = IOAPIC_EDGE_TRIG;
- if (!(apic_get_reg(apic, APIC_SPIV) & APIC_SPIV_DIRECTED_EOI))
- kvm_ioapic_update_eoi(apic->vcpu->kvm, vector, trigger_mode);
-}
-
-int
-apic_reg_write(struct kvm_lapic *apic, uint32_t reg, uint32_t val)
-{
- int ret = 0;
-
-#ifdef XXX_KVM_TRACE
- trace_kvm_apic_write(reg, val);
-#endif
-
- switch (reg) {
- case APIC_ID: /* Local APIC ID */
- if (!apic_x2apic_mode(apic))
- apic_set_reg(apic, APIC_ID, val);
- else
- ret = 1;
- break;
-
- case APIC_TASKPRI:
- report_tpr_access(apic, 1);
- apic_set_tpr(apic, val & 0xff);
- break;
-
- case APIC_EOI:
- apic_set_eoi(apic);
- break;
-
- case APIC_LDR:
- if (!apic_x2apic_mode(apic))
- apic_set_reg(apic, APIC_LDR, val & APIC_LDR_MASK);
- else
- ret = 1;
- break;
-
- case APIC_DFR:
- if (!apic_x2apic_mode(apic))
- apic_set_reg(apic, APIC_DFR, val | 0x0FFFFFFF);
- else
- ret = 1;
- break;
-
- case APIC_SPIV: {
- uint32_t mask = 0x3ff;
- if (apic_get_reg(apic, APIC_LVR) & APIC_LVR_DIRECTED_EOI)
- mask |= APIC_SPIV_DIRECTED_EOI;
- apic_set_reg(apic, APIC_SPIV, val & mask);
- if (!(val & APIC_SPIV_APIC_ENABLED)) {
- int i;
- uint32_t lvt_val;
-
- for (i = 0; i < APIC_LVT_NUM; i++) {
- lvt_val = apic_get_reg(apic,
- APIC_LVTT + 0x10 * i);
- apic_set_reg(apic, APIC_LVTT + 0x10 * i,
- lvt_val | APIC_LVT_MASKED);
- }
- /* XXX pending needs protection? */
- apic->lapic_timer.pending = 0;
- }
- break;
- }
- case APIC_ICR:
- /* No delay here, so we always clear the pending bit */
- apic_set_reg(apic, APIC_ICR, val & ~(1 << 12));
- apic_send_ipi(apic);
- break;
-
- case APIC_ICR2:
- if (!apic_x2apic_mode(apic))
- val &= 0xff000000;
- apic_set_reg(apic, APIC_ICR2, val);
- break;
-
- case APIC_LVT0:
- apic_manage_nmi_watchdog(apic, val);
- case APIC_LVTT:
- case APIC_LVTTHMR:
- case APIC_LVTPC:
- case APIC_LVT1:
- case APIC_LVTERR:
- /* TODO: Check vector */
- if (!apic_sw_enabled(apic))
- val |= APIC_LVT_MASKED;
-
- val &= apic_lvt_mask[(reg - APIC_LVTT) >> 4];
- apic_set_reg(apic, reg, val);
-
- break;
-
- case APIC_TMICT:
- mutex_enter(&cpu_lock);
- if (apic->lapic_timer.active) {
- cyclic_remove(apic->lapic_timer.kvm_cyclic_id);
- apic->lapic_timer.active = 0;
- }
- mutex_exit(&cpu_lock);
-
- apic_set_reg(apic, APIC_TMICT, val);
- start_apic_timer(apic);
- break;
-
- case APIC_TDCR:
- if (val & 4)
- cmn_err(CE_WARN, "KVM_WRITE:TDCR %x\n", val);
- apic_set_reg(apic, APIC_TDCR, val);
- update_divide_count(apic);
- break;
-
- case APIC_ESR:
- if (apic_x2apic_mode(apic) && val != 0) {
- cmn_err(CE_WARN, "KVM_WRITE:ESR not zero %x\n", val);
- ret = 1;
- }
- break;
-
- case APIC_SELF_IPI:
- if (apic_x2apic_mode(apic)) {
- apic_reg_write(apic, APIC_ICR, 0x40000 | (val & 0xff));
- } else
- ret = 1;
- break;
- default:
- ret = 1;
- break;
- }
-
- return (ret);
-}
-
-static int
-apic_mmio_write(struct kvm_io_device *this,
- gpa_t address, int len, const void *data)
-{
- struct kvm_lapic *apic = to_lapic(this);
- unsigned int offset = address - apic->base_address;
- uint32_t val;
-
- if (!apic_mmio_in_range(apic, address))
- return (-EOPNOTSUPP);
-
- /*
- * APIC register must be aligned on 128-bits boundary.
- * 32/64/128 bits registers must be accessed thru 32 bits.
- * Refer SDM 8.4.1
- */
- if (len != 4 || (offset & 0xf)) {
- /* Don't shout loud, $infamous_os would cause only noise. */
- return (0);
- }
-
- val = *(uint32_t *)data;
-
- apic_reg_write(apic, offset & 0xff0, val);
-
- return (0);
-}
-
-static const struct kvm_io_device_ops apic_mmio_ops = {
- .read = apic_mmio_read,
- .write = apic_mmio_write,
-};
-
-static int
-lapic_is_periodic(struct kvm_timer *ktimer)
-{
- struct kvm_lapic *apic = (struct kvm_lapic *)((caddr_t)ktimer -
- offsetof(struct kvm_lapic, lapic_timer));
-
- return (apic_lvtt_period(apic));
-}
-
-static struct kvm_timer_ops lapic_timer_ops = {
- .is_periodic = lapic_is_periodic,
-};
-
extern void kvm_timer_fire(void *);
-int
-kvm_create_lapic(struct kvm_vcpu *vcpu)
-{
- struct kvm_lapic *apic;
-
- ASSERT(vcpu != NULL);
-
- apic = kmem_zalloc(sizeof (*apic), KM_SLEEP);
- if (!apic)
- goto nomem;
-
- vcpu->arch.apic = apic;
-
- apic->regs = kmem_zalloc(PAGESIZE, KM_SLEEP);
- memset(apic->regs, 0, PAGESIZE);
- apic->vcpu = vcpu;
-
- apic->lapic_timer.kvm_cyc_handler.cyh_func = kvm_timer_fire;
- apic->lapic_timer.kvm_cyc_handler.cyh_arg = &apic->lapic_timer;
- apic->lapic_timer.kvm_cyc_handler.cyh_level = CY_LOW_LEVEL;
- apic->lapic_timer.active = 0;
-
- apic->lapic_timer.t_ops = &lapic_timer_ops;
- apic->lapic_timer.kvm = vcpu->kvm;
- apic->lapic_timer.vcpu = vcpu;
-
- apic->base_address = APIC_DEFAULT_PHYS_BASE;
- vcpu->arch.apic_base = APIC_DEFAULT_PHYS_BASE;
-
- kvm_lapic_reset(vcpu);
- kvm_iodevice_init(&apic->dev, &apic_mmio_ops);
- apic->dev.lapic = apic;
-
- return (0);
-nomem_free_apic:
- if (apic)
- kmem_free(apic, sizeof (struct kvm_lapic));
-nomem:
- return (-ENOMEM);
-}
-
extern int kvm_vcpu_is_bsp(struct kvm_vcpu *vcpu);
int
@@ -2008,31 +1232,6 @@ update_exception_bitmap(struct kvm_vcpu *vcpu)
}
-void
-kvm_lapic_set_base(struct kvm_vcpu *vcpu, uint64_t value)
-{
- struct kvm_lapic *apic = vcpu->arch.apic;
-
- if (!apic) {
- value |= MSR_IA32_APICBASE_BSP;
- vcpu->arch.apic_base = value;
- return;
- }
-
- if (!kvm_vcpu_is_bsp(apic->vcpu))
- value &= ~MSR_IA32_APICBASE_BSP;
-
- vcpu->arch.apic_base = value;
- if (apic_x2apic_mode(apic)) {
- uint32_t id = kvm_apic_id(apic);
- uint32_t ldr = ((id & ~0xf) << 16) | (1 << (id & 0xf));
- apic_set_reg(apic, APIC_LDR, ldr);
- }
-
- apic->base_address = apic->vcpu->arch.apic_base &
- MSR_IA32_APICBASE_BASE;
-}
-
uint64_t
kvm_get_apic_base(struct kvm_vcpu *vcpu)
{
@@ -2053,18 +1252,6 @@ kvm_set_apic_base(struct kvm_vcpu *vcpu, uint64_t data)
}
void
-kvm_lapic_set_tpr(struct kvm_vcpu *vcpu, unsigned long cr8)
-{
- struct kvm_lapic *apic = vcpu->arch.apic;
-
- if (!apic)
- return;
-
- apic_set_tpr(apic, ((cr8 & 0x0f) << 4) |
- (apic_get_reg(apic, APIC_TASKPRI) & 4));
-}
-
-void
kvm_set_cr8(struct kvm_vcpu *vcpu, unsigned long cr8)
{
if (cr8 & CR8_RESERVED_BITS) {