2 * KVM in-kernel APIC support
4 * Copyright (c) 2011 Siemens AG
7 * Jan Kiszka <jan.kiszka@siemens.com>
9 * This work is licensed under the terms of the GNU GPL version 2.
10 * See the COPYING file in the top-level directory.
13 #include "qemu/osdep.h"
14 #include "qemu/module.h"
15 #include "hw/i386/apic_internal.h"
16 #include "hw/pci/msi.h"
17 #include "sysemu/hw_accel.h"
18 #include "sysemu/kvm.h"
19 #include "kvm/kvm_i386.h"
21 static inline void kvm_apic_set_reg(struct kvm_lapic_state
*kapic
,
22 int reg_id
, uint32_t val
)
24 *((uint32_t *)(kapic
->regs
+ (reg_id
<< 4))) = val
;
27 static inline uint32_t kvm_apic_get_reg(struct kvm_lapic_state
*kapic
,
30 return *((uint32_t *)(kapic
->regs
+ (reg_id
<< 4)));
33 static void kvm_put_apic_state(APICCommonState
*s
, struct kvm_lapic_state
*kapic
)
37 memset(kapic
, 0, sizeof(*kapic
));
38 if (kvm_has_x2apic_api() && s
->apicbase
& MSR_IA32_APICBASE_EXTD
) {
39 kvm_apic_set_reg(kapic
, 0x2, s
->initial_apic_id
);
41 kvm_apic_set_reg(kapic
, 0x2, s
->id
<< 24);
43 kvm_apic_set_reg(kapic
, 0x8, s
->tpr
);
44 kvm_apic_set_reg(kapic
, 0xd, s
->log_dest
<< 24);
45 kvm_apic_set_reg(kapic
, 0xe, s
->dest_mode
<< 28 | 0x0fffffff);
46 kvm_apic_set_reg(kapic
, 0xf, s
->spurious_vec
);
47 for (i
= 0; i
< 8; i
++) {
48 kvm_apic_set_reg(kapic
, 0x10 + i
, s
->isr
[i
]);
49 kvm_apic_set_reg(kapic
, 0x18 + i
, s
->tmr
[i
]);
50 kvm_apic_set_reg(kapic
, 0x20 + i
, s
->irr
[i
]);
52 kvm_apic_set_reg(kapic
, 0x28, s
->esr
);
53 kvm_apic_set_reg(kapic
, 0x30, s
->icr
[0]);
54 kvm_apic_set_reg(kapic
, 0x31, s
->icr
[1]);
55 for (i
= 0; i
< APIC_LVT_NB
; i
++) {
56 kvm_apic_set_reg(kapic
, 0x32 + i
, s
->lvt
[i
]);
58 kvm_apic_set_reg(kapic
, 0x38, s
->initial_count
);
59 kvm_apic_set_reg(kapic
, 0x3e, s
->divide_conf
);
62 void kvm_get_apic_state(DeviceState
*dev
, struct kvm_lapic_state
*kapic
)
64 APICCommonState
*s
= APIC_COMMON(dev
);
67 if (kvm_has_x2apic_api() && s
->apicbase
& MSR_IA32_APICBASE_EXTD
) {
68 assert(kvm_apic_get_reg(kapic
, 0x2) == s
->initial_apic_id
);
70 s
->id
= kvm_apic_get_reg(kapic
, 0x2) >> 24;
72 s
->tpr
= kvm_apic_get_reg(kapic
, 0x8);
73 s
->arb_id
= kvm_apic_get_reg(kapic
, 0x9);
74 s
->log_dest
= kvm_apic_get_reg(kapic
, 0xd) >> 24;
75 s
->dest_mode
= kvm_apic_get_reg(kapic
, 0xe) >> 28;
76 s
->spurious_vec
= kvm_apic_get_reg(kapic
, 0xf);
77 for (i
= 0; i
< 8; i
++) {
78 s
->isr
[i
] = kvm_apic_get_reg(kapic
, 0x10 + i
);
79 s
->tmr
[i
] = kvm_apic_get_reg(kapic
, 0x18 + i
);
80 s
->irr
[i
] = kvm_apic_get_reg(kapic
, 0x20 + i
);
82 s
->esr
= kvm_apic_get_reg(kapic
, 0x28);
83 s
->icr
[0] = kvm_apic_get_reg(kapic
, 0x30);
84 s
->icr
[1] = kvm_apic_get_reg(kapic
, 0x31);
85 for (i
= 0; i
< APIC_LVT_NB
; i
++) {
86 s
->lvt
[i
] = kvm_apic_get_reg(kapic
, 0x32 + i
);
88 s
->initial_count
= kvm_apic_get_reg(kapic
, 0x38);
89 s
->divide_conf
= kvm_apic_get_reg(kapic
, 0x3e);
91 v
= (s
->divide_conf
& 3) | ((s
->divide_conf
>> 1) & 4);
92 s
->count_shift
= (v
+ 1) & 7;
94 s
->initial_count_load_time
= qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
);
95 apic_next_timer(s
, s
->initial_count_load_time
);
98 static void kvm_apic_set_base(APICCommonState
*s
, uint64_t val
)
103 static void kvm_apic_set_tpr(APICCommonState
*s
, uint8_t val
)
105 s
->tpr
= (val
& 0x0f) << 4;
108 static uint8_t kvm_apic_get_tpr(APICCommonState
*s
)
113 static void kvm_apic_enable_tpr_reporting(APICCommonState
*s
, bool enable
)
115 struct kvm_tpr_access_ctl ctl
= {
119 kvm_vcpu_ioctl(CPU(s
->cpu
), KVM_TPR_ACCESS_REPORTING
, &ctl
);
122 static void kvm_apic_vapic_base_update(APICCommonState
*s
)
124 struct kvm_vapic_addr vapid_addr
= {
125 .vapic_addr
= s
->vapic_paddr
,
129 ret
= kvm_vcpu_ioctl(CPU(s
->cpu
), KVM_SET_VAPIC_ADDR
, &vapid_addr
);
131 fprintf(stderr
, "KVM: setting VAPIC address failed (%s)\n",
137 static void kvm_apic_put(CPUState
*cs
, run_on_cpu_data data
)
139 APICCommonState
*s
= data
.host_ptr
;
140 struct kvm_lapic_state kapic
;
143 kvm_put_apicbase(s
->cpu
, s
->apicbase
);
144 kvm_put_apic_state(s
, &kapic
);
146 ret
= kvm_vcpu_ioctl(CPU(s
->cpu
), KVM_SET_LAPIC
, &kapic
);
148 fprintf(stderr
, "KVM_SET_LAPIC failed: %s\n", strerror(ret
));
153 static void kvm_apic_post_load(APICCommonState
*s
)
155 run_on_cpu(CPU(s
->cpu
), kvm_apic_put
, RUN_ON_CPU_HOST_PTR(s
));
158 static void do_inject_external_nmi(CPUState
*cpu
, run_on_cpu_data data
)
160 APICCommonState
*s
= data
.host_ptr
;
164 cpu_synchronize_state(cpu
);
166 lvt
= s
->lvt
[APIC_LVT_LINT1
];
167 if (!(lvt
& APIC_LVT_MASKED
) && ((lvt
>> 8) & 7) == APIC_DM_NMI
) {
168 ret
= kvm_vcpu_ioctl(cpu
, KVM_NMI
);
170 fprintf(stderr
, "KVM: injection failed, NMI lost (%s)\n",
176 static void kvm_apic_external_nmi(APICCommonState
*s
)
178 run_on_cpu(CPU(s
->cpu
), do_inject_external_nmi
, RUN_ON_CPU_HOST_PTR(s
));
181 static void kvm_send_msi(MSIMessage
*msg
)
186 * The message has already passed through interrupt remapping if enabled,
187 * but the legacy extended destination ID in low bits still needs to be
190 msg
->address
= kvm_swizzle_msi_ext_dest_id(msg
->address
);
192 ret
= kvm_irqchip_send_msi(kvm_state
, *msg
);
194 fprintf(stderr
, "KVM: injection failed, MSI lost (%s)\n",
199 static uint64_t kvm_apic_mem_read(void *opaque
, hwaddr addr
,
205 static void kvm_apic_mem_write(void *opaque
, hwaddr addr
,
206 uint64_t data
, unsigned size
)
208 MSIMessage msg
= { .address
= addr
, .data
= data
};
213 static const MemoryRegionOps kvm_apic_io_ops
= {
214 .read
= kvm_apic_mem_read
,
215 .write
= kvm_apic_mem_write
,
216 .endianness
= DEVICE_NATIVE_ENDIAN
,
219 static void kvm_apic_reset(APICCommonState
*s
)
221 /* Not used by KVM, which uses the CPU mp_state instead. */
222 s
->wait_for_sipi
= 0;
224 run_on_cpu(CPU(s
->cpu
), kvm_apic_put
, RUN_ON_CPU_HOST_PTR(s
));
227 static void kvm_apic_realize(DeviceState
*dev
, Error
**errp
)
229 APICCommonState
*s
= APIC_COMMON(dev
);
231 memory_region_init_io(&s
->io_memory
, OBJECT(s
), &kvm_apic_io_ops
, s
,
232 "kvm-apic-msi", APIC_SPACE_SIZE
);
234 assert(kvm_has_gsi_routing());
235 msi_nonbroken
= true;
238 static void kvm_apic_unrealize(DeviceState
*dev
)
242 static void kvm_apic_class_init(ObjectClass
*klass
, void *data
)
244 APICCommonClass
*k
= APIC_COMMON_CLASS(klass
);
246 k
->realize
= kvm_apic_realize
;
247 k
->unrealize
= kvm_apic_unrealize
;
248 k
->reset
= kvm_apic_reset
;
249 k
->set_base
= kvm_apic_set_base
;
250 k
->set_tpr
= kvm_apic_set_tpr
;
251 k
->get_tpr
= kvm_apic_get_tpr
;
252 k
->post_load
= kvm_apic_post_load
;
253 k
->enable_tpr_reporting
= kvm_apic_enable_tpr_reporting
;
254 k
->vapic_base_update
= kvm_apic_vapic_base_update
;
255 k
->external_nmi
= kvm_apic_external_nmi
;
256 k
->send_msi
= kvm_send_msi
;
259 static const TypeInfo kvm_apic_info
= {
261 .parent
= TYPE_APIC_COMMON
,
262 .instance_size
= sizeof(APICCommonState
),
263 .class_init
= kvm_apic_class_init
,
266 static void kvm_apic_register_types(void)
268 type_register_static(&kvm_apic_info
);
271 type_init(kvm_apic_register_types
)