lapic.h 4.1 KB
Newer Older
1 2 3 4 5 6 7
#ifndef __KVM_X86_LAPIC_H
#define __KVM_X86_LAPIC_H

#include "iodev.h"

#include <linux/kvm_host.h>

8 9 10 11 12 13 14 15
struct kvm_timer {
	struct hrtimer timer;
	s64 period; 				/* unit: ns */
	u32 timer_mode_mask;
	u64 tscdeadline;
	atomic_t pending;			/* accumulated triggered timers */
};

16 17 18
struct kvm_lapic {
	unsigned long base_address;
	struct kvm_io_device dev;
19 20
	struct kvm_timer lapic_timer;
	u32 divide_count;
21
	struct kvm_vcpu *vcpu;
22
	bool irr_pending;
M
Michael S. Tsirkin 已提交
23 24 25 26
	/* Number of bits set in ISR. */
	s16 isr_count;
	/* The highest vector set in ISR; if -1 - invalid, must scan ISR. */
	int highest_isr_cache;
27 28 29 30 31
	/**
	 * APIC register page.  The layout matches the register layout seen by
	 * the guest 1:1, because it is accessed by the vmx microcode.
	 * Note: Only one register, the TPR, is used by the microcode.
	 */
32
	void *regs;
A
Avi Kivity 已提交
33 34
	gpa_t vapic_addr;
	struct page *vapic_page;
35 36 37 38 39 40 41 42 43 44
};
int kvm_create_lapic(struct kvm_vcpu *vcpu);
void kvm_free_lapic(struct kvm_vcpu *vcpu);

int kvm_apic_has_interrupt(struct kvm_vcpu *vcpu);
int kvm_apic_accept_pic_intr(struct kvm_vcpu *vcpu);
int kvm_get_apic_interrupt(struct kvm_vcpu *vcpu);
void kvm_lapic_reset(struct kvm_vcpu *vcpu);
u64 kvm_lapic_get_cr8(struct kvm_vcpu *vcpu);
void kvm_lapic_set_tpr(struct kvm_vcpu *vcpu, unsigned long cr8);
45
void kvm_lapic_set_eoi(struct kvm_vcpu *vcpu);
46
void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value);
47
u64 kvm_lapic_get_base(struct kvm_vcpu *vcpu);
48
void kvm_apic_set_version(struct kvm_vcpu *vcpu);
49 50 51

int kvm_apic_match_physical_addr(struct kvm_lapic *apic, u16 dest);
int kvm_apic_match_logical_addr(struct kvm_lapic *apic, u8 mda);
52
int kvm_apic_set_irq(struct kvm_vcpu *vcpu, struct kvm_lapic_irq *irq);
A
Avi Kivity 已提交
53
int kvm_apic_local_deliver(struct kvm_lapic *apic, int lvt_type);
54

55 56 57
bool kvm_irq_delivery_to_apic_fast(struct kvm *kvm, struct kvm_lapic *src,
		struct kvm_lapic_irq *irq, int *r);

58 59
u64 kvm_get_apic_base(struct kvm_vcpu *vcpu);
void kvm_set_apic_base(struct kvm_vcpu *vcpu, u64 data);
60 61
void kvm_apic_post_state_restore(struct kvm_vcpu *vcpu,
		struct kvm_lapic_state *s);
62 63
int kvm_lapic_find_highest_irr(struct kvm_vcpu *vcpu);

64 65 66
u64 kvm_get_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu);
void kvm_set_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu, u64 data);

67 68
void kvm_apic_write_nodecode(struct kvm_vcpu *vcpu, u32 offset);

A
Avi Kivity 已提交
69 70 71 72
void kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr);
void kvm_lapic_sync_from_vapic(struct kvm_vcpu *vcpu);
void kvm_lapic_sync_to_vapic(struct kvm_vcpu *vcpu);

G
Gleb Natapov 已提交
73 74
int kvm_x2apic_msr_write(struct kvm_vcpu *vcpu, u32 msr, u64 data);
int kvm_x2apic_msr_read(struct kvm_vcpu *vcpu, u32 msr, u64 *data);
G
Gleb Natapov 已提交
75 76 77 78 79 80 81 82

int kvm_hv_vapic_msr_write(struct kvm_vcpu *vcpu, u32 msr, u64 data);
int kvm_hv_vapic_msr_read(struct kvm_vcpu *vcpu, u32 msr, u64 *data);

static inline bool kvm_hv_vapic_assist_page_enabled(struct kvm_vcpu *vcpu)
{
	return vcpu->arch.hv_vapic & HV_X64_MSR_APIC_ASSIST_PAGE_ENABLE;
}
83 84

int kvm_lapic_enable_pv_eoi(struct kvm_vcpu *vcpu, u64 data);
85
void kvm_lapic_init(void);
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128

static inline u32 kvm_apic_get_reg(struct kvm_lapic *apic, int reg_off)
{
	        return *((u32 *) (apic->regs + reg_off));
}

extern struct static_key kvm_no_apic_vcpu;

static inline bool kvm_vcpu_has_lapic(struct kvm_vcpu *vcpu)
{
	if (static_key_false(&kvm_no_apic_vcpu))
		return vcpu->arch.apic;
	return true;
}

extern struct static_key_deferred apic_hw_disabled;

static inline int kvm_apic_hw_enabled(struct kvm_lapic *apic)
{
	if (static_key_false(&apic_hw_disabled.key))
		return apic->vcpu->arch.apic_base & MSR_IA32_APICBASE_ENABLE;
	return MSR_IA32_APICBASE_ENABLE;
}

extern struct static_key_deferred apic_sw_disabled;

static inline int kvm_apic_sw_enabled(struct kvm_lapic *apic)
{
	if (static_key_false(&apic_sw_disabled.key))
		return kvm_apic_get_reg(apic, APIC_SPIV) & APIC_SPIV_APIC_ENABLED;
	return APIC_SPIV_APIC_ENABLED;
}

static inline bool kvm_apic_present(struct kvm_vcpu *vcpu)
{
	return kvm_vcpu_has_lapic(vcpu) && kvm_apic_hw_enabled(vcpu->arch.apic);
}

static inline int kvm_lapic_enabled(struct kvm_vcpu *vcpu)
{
	return kvm_apic_present(vcpu) && kvm_apic_sw_enabled(vcpu->arch.apic);
}

129 130 131 132 133
static inline int apic_x2apic_mode(struct kvm_lapic *apic)
{
	return apic->vcpu->arch.apic_base & X2APIC_ENABLE;
}

134
#endif