mirror of https://gitlab.com/qemu-project/qemu
kvmvapic: Add option ROM
This imports and builds the original VAPIC option ROM of qemu-kvm. Its interaction with QEMU is described in the commit that introduces the corresponding device model. Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> Signed-off-by: Avi Kivity <avi@redhat.com>
This commit is contained in:
parent
d362e757d3
commit
2a2af967b0
|
@ -75,6 +75,7 @@ pc-bios/vgabios-pq/status
|
||||||
pc-bios/optionrom/linuxboot.bin
|
pc-bios/optionrom/linuxboot.bin
|
||||||
pc-bios/optionrom/multiboot.bin
|
pc-bios/optionrom/multiboot.bin
|
||||||
pc-bios/optionrom/multiboot.raw
|
pc-bios/optionrom/multiboot.raw
|
||||||
|
pc-bios/optionrom/kvmvapic.bin
|
||||||
.stgit-*
|
.stgit-*
|
||||||
cscope.*
|
cscope.*
|
||||||
tags
|
tags
|
||||||
|
|
2
Makefile
2
Makefile
|
@ -253,7 +253,7 @@ pxe-e1000.rom pxe-eepro100.rom pxe-ne2k_pci.rom \
|
||||||
pxe-pcnet.rom pxe-rtl8139.rom pxe-virtio.rom \
|
pxe-pcnet.rom pxe-rtl8139.rom pxe-virtio.rom \
|
||||||
bamboo.dtb petalogix-s3adsp1800.dtb petalogix-ml605.dtb \
|
bamboo.dtb petalogix-s3adsp1800.dtb petalogix-ml605.dtb \
|
||||||
mpc8544ds.dtb \
|
mpc8544ds.dtb \
|
||||||
multiboot.bin linuxboot.bin \
|
multiboot.bin linuxboot.bin kvmvapic.bin \
|
||||||
s390-zipl.rom \
|
s390-zipl.rom \
|
||||||
spapr-rtas.bin slof.bin \
|
spapr-rtas.bin slof.bin \
|
||||||
palcode-clipper
|
palcode-clipper
|
||||||
|
|
|
@ -14,7 +14,7 @@ CFLAGS += -I$(SRC_PATH)
|
||||||
CFLAGS += $(call cc-option, $(CFLAGS), -fno-stack-protector)
|
CFLAGS += $(call cc-option, $(CFLAGS), -fno-stack-protector)
|
||||||
QEMU_CFLAGS = $(CFLAGS)
|
QEMU_CFLAGS = $(CFLAGS)
|
||||||
|
|
||||||
build-all: multiboot.bin linuxboot.bin
|
build-all: multiboot.bin linuxboot.bin kvmvapic.bin
|
||||||
|
|
||||||
# suppress auto-removal of intermediate files
|
# suppress auto-removal of intermediate files
|
||||||
.SECONDARY:
|
.SECONDARY:
|
||||||
|
|
|
@ -0,0 +1,341 @@
|
||||||
|
#
|
||||||
|
# Local APIC acceleration for Windows XP and related guests
|
||||||
|
#
|
||||||
|
# Copyright 2011 Red Hat, Inc. and/or its affiliates
|
||||||
|
#
|
||||||
|
# Author: Avi Kivity <avi@redhat.com>
|
||||||
|
#
|
||||||
|
# This work is licensed under the terms of the GNU GPL, version 2, or (at your
|
||||||
|
# option) any later version. See the COPYING file in the top-level directory.
|
||||||
|
#
|
||||||
|
|
||||||
|
.text 0
|
||||||
|
.code16
|
||||||
|
.global _start
|
||||||
|
_start:
|
||||||
|
.short 0xaa55
|
||||||
|
.byte (_end - _start) / 512
|
||||||
|
# clear vapic area: firmware load using rep insb may cause
|
||||||
|
# stale tpr/isr/irr data to corrupt the vapic area.
|
||||||
|
push %es
|
||||||
|
push %cs
|
||||||
|
pop %es
|
||||||
|
xor %ax, %ax
|
||||||
|
mov $vapic_size/2, %cx
|
||||||
|
lea vapic, %di
|
||||||
|
cld
|
||||||
|
rep stosw
|
||||||
|
pop %es
|
||||||
|
mov $vapic_base, %ax
|
||||||
|
out %ax, $0x7e
|
||||||
|
lret
|
||||||
|
|
||||||
|
.code32
|
||||||
|
vapic_size = 2*4096
|
||||||
|
|
||||||
|
.macro fixup delta=-4
|
||||||
|
777:
|
||||||
|
.text 1
|
||||||
|
.long 777b + \delta - vapic_base
|
||||||
|
.text 0
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.macro reenable_vtpr
|
||||||
|
out %al, $0x7e
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.text 1
|
||||||
|
fixup_start = .
|
||||||
|
.text 0
|
||||||
|
|
||||||
|
.align 16
|
||||||
|
|
||||||
|
vapic_base:
|
||||||
|
.ascii "kvm aPiC"
|
||||||
|
|
||||||
|
/* relocation data */
|
||||||
|
.long vapic_base ; fixup
|
||||||
|
.long fixup_start ; fixup
|
||||||
|
.long fixup_end ; fixup
|
||||||
|
|
||||||
|
.long vapic ; fixup
|
||||||
|
.long vapic_size
|
||||||
|
vcpu_shift:
|
||||||
|
.long 0
|
||||||
|
real_tpr:
|
||||||
|
.long 0
|
||||||
|
.long up_set_tpr ; fixup
|
||||||
|
.long up_set_tpr_eax ; fixup
|
||||||
|
.long up_get_tpr_eax ; fixup
|
||||||
|
.long up_get_tpr_ecx ; fixup
|
||||||
|
.long up_get_tpr_edx ; fixup
|
||||||
|
.long up_get_tpr_ebx ; fixup
|
||||||
|
.long 0 /* esp. won't work. */
|
||||||
|
.long up_get_tpr_ebp ; fixup
|
||||||
|
.long up_get_tpr_esi ; fixup
|
||||||
|
.long up_get_tpr_edi ; fixup
|
||||||
|
.long up_get_tpr_stack ; fixup
|
||||||
|
.long mp_set_tpr ; fixup
|
||||||
|
.long mp_set_tpr_eax ; fixup
|
||||||
|
.long mp_get_tpr_eax ; fixup
|
||||||
|
.long mp_get_tpr_ecx ; fixup
|
||||||
|
.long mp_get_tpr_edx ; fixup
|
||||||
|
.long mp_get_tpr_ebx ; fixup
|
||||||
|
.long 0 /* esp. won't work. */
|
||||||
|
.long mp_get_tpr_ebp ; fixup
|
||||||
|
.long mp_get_tpr_esi ; fixup
|
||||||
|
.long mp_get_tpr_edi ; fixup
|
||||||
|
.long mp_get_tpr_stack ; fixup
|
||||||
|
|
||||||
|
.macro kvm_hypercall
|
||||||
|
.byte 0x0f, 0x01, 0xc1
|
||||||
|
.endm
|
||||||
|
|
||||||
|
kvm_hypercall_vapic_poll_irq = 1
|
||||||
|
|
||||||
|
pcr_cpu = 0x51
|
||||||
|
|
||||||
|
.align 64
|
||||||
|
|
||||||
|
mp_get_tpr_eax:
|
||||||
|
pushf
|
||||||
|
cli
|
||||||
|
reenable_vtpr
|
||||||
|
push %ecx
|
||||||
|
|
||||||
|
fs/movzbl pcr_cpu, %eax
|
||||||
|
|
||||||
|
mov vcpu_shift, %ecx ; fixup
|
||||||
|
shl %cl, %eax
|
||||||
|
testb $1, vapic+4(%eax) ; fixup delta=-5
|
||||||
|
jz mp_get_tpr_bad
|
||||||
|
movzbl vapic(%eax), %eax ; fixup
|
||||||
|
|
||||||
|
mp_get_tpr_out:
|
||||||
|
pop %ecx
|
||||||
|
popf
|
||||||
|
ret
|
||||||
|
|
||||||
|
mp_get_tpr_bad:
|
||||||
|
mov real_tpr, %eax ; fixup
|
||||||
|
mov (%eax), %eax
|
||||||
|
jmp mp_get_tpr_out
|
||||||
|
|
||||||
|
mp_get_tpr_ebx:
|
||||||
|
mov %eax, %ebx
|
||||||
|
call mp_get_tpr_eax
|
||||||
|
xchg %eax, %ebx
|
||||||
|
ret
|
||||||
|
|
||||||
|
mp_get_tpr_ecx:
|
||||||
|
mov %eax, %ecx
|
||||||
|
call mp_get_tpr_eax
|
||||||
|
xchg %eax, %ecx
|
||||||
|
ret
|
||||||
|
|
||||||
|
mp_get_tpr_edx:
|
||||||
|
mov %eax, %edx
|
||||||
|
call mp_get_tpr_eax
|
||||||
|
xchg %eax, %edx
|
||||||
|
ret
|
||||||
|
|
||||||
|
mp_get_tpr_esi:
|
||||||
|
mov %eax, %esi
|
||||||
|
call mp_get_tpr_eax
|
||||||
|
xchg %eax, %esi
|
||||||
|
ret
|
||||||
|
|
||||||
|
mp_get_tpr_edi:
|
||||||
|
mov %eax, %edi
|
||||||
|
call mp_get_tpr_edi
|
||||||
|
xchg %eax, %edi
|
||||||
|
ret
|
||||||
|
|
||||||
|
mp_get_tpr_ebp:
|
||||||
|
mov %eax, %ebp
|
||||||
|
call mp_get_tpr_eax
|
||||||
|
xchg %eax, %ebp
|
||||||
|
ret
|
||||||
|
|
||||||
|
mp_get_tpr_stack:
|
||||||
|
call mp_get_tpr_eax
|
||||||
|
xchg %eax, 4(%esp)
|
||||||
|
ret
|
||||||
|
|
||||||
|
mp_set_tpr_eax:
|
||||||
|
push %eax
|
||||||
|
call mp_set_tpr
|
||||||
|
ret
|
||||||
|
|
||||||
|
mp_set_tpr:
|
||||||
|
pushf
|
||||||
|
push %eax
|
||||||
|
push %ecx
|
||||||
|
push %edx
|
||||||
|
push %ebx
|
||||||
|
cli
|
||||||
|
reenable_vtpr
|
||||||
|
|
||||||
|
mp_set_tpr_failed:
|
||||||
|
fs/movzbl pcr_cpu, %edx
|
||||||
|
|
||||||
|
mov vcpu_shift, %ecx ; fixup
|
||||||
|
shl %cl, %edx
|
||||||
|
|
||||||
|
testb $1, vapic+4(%edx) ; fixup delta=-5
|
||||||
|
jz mp_set_tpr_bad
|
||||||
|
|
||||||
|
mov vapic(%edx), %eax ; fixup
|
||||||
|
|
||||||
|
mov %eax, %ebx
|
||||||
|
mov 24(%esp), %bl
|
||||||
|
|
||||||
|
/* %ebx = new vapic (%bl = tpr, %bh = isr, %b3 = irr) */
|
||||||
|
|
||||||
|
lock cmpxchg %ebx, vapic(%edx) ; fixup
|
||||||
|
jnz mp_set_tpr_failed
|
||||||
|
|
||||||
|
/* compute ppr */
|
||||||
|
cmp %bh, %bl
|
||||||
|
jae mp_tpr_is_bigger
|
||||||
|
mp_isr_is_bigger:
|
||||||
|
mov %bh, %bl
|
||||||
|
mp_tpr_is_bigger:
|
||||||
|
/* %bl = ppr */
|
||||||
|
mov %bl, %ch /* ch = ppr */
|
||||||
|
rol $8, %ebx
|
||||||
|
/* now: %bl = irr, %bh = ppr */
|
||||||
|
cmp %bh, %bl
|
||||||
|
ja mp_set_tpr_poll_irq
|
||||||
|
|
||||||
|
mp_set_tpr_out:
|
||||||
|
pop %ebx
|
||||||
|
pop %edx
|
||||||
|
pop %ecx
|
||||||
|
pop %eax
|
||||||
|
popf
|
||||||
|
ret $4
|
||||||
|
|
||||||
|
mp_set_tpr_poll_irq:
|
||||||
|
mov $kvm_hypercall_vapic_poll_irq, %eax
|
||||||
|
kvm_hypercall
|
||||||
|
jmp mp_set_tpr_out
|
||||||
|
|
||||||
|
mp_set_tpr_bad:
|
||||||
|
mov 24(%esp), %ecx
|
||||||
|
mov real_tpr, %eax ; fixup
|
||||||
|
mov %ecx, (%eax)
|
||||||
|
jmp mp_set_tpr_out
|
||||||
|
|
||||||
|
up_get_tpr_eax:
|
||||||
|
reenable_vtpr
|
||||||
|
movzbl vapic, %eax ; fixup
|
||||||
|
ret
|
||||||
|
|
||||||
|
up_get_tpr_ebx:
|
||||||
|
reenable_vtpr
|
||||||
|
movzbl vapic, %ebx ; fixup
|
||||||
|
ret
|
||||||
|
|
||||||
|
up_get_tpr_ecx:
|
||||||
|
reenable_vtpr
|
||||||
|
movzbl vapic, %ecx ; fixup
|
||||||
|
ret
|
||||||
|
|
||||||
|
up_get_tpr_edx:
|
||||||
|
reenable_vtpr
|
||||||
|
movzbl vapic, %edx ; fixup
|
||||||
|
ret
|
||||||
|
|
||||||
|
up_get_tpr_esi:
|
||||||
|
reenable_vtpr
|
||||||
|
movzbl vapic, %esi ; fixup
|
||||||
|
ret
|
||||||
|
|
||||||
|
up_get_tpr_edi:
|
||||||
|
reenable_vtpr
|
||||||
|
movzbl vapic, %edi ; fixup
|
||||||
|
ret
|
||||||
|
|
||||||
|
up_get_tpr_ebp:
|
||||||
|
reenable_vtpr
|
||||||
|
movzbl vapic, %ebp ; fixup
|
||||||
|
ret
|
||||||
|
|
||||||
|
up_get_tpr_stack:
|
||||||
|
reenable_vtpr
|
||||||
|
movzbl vapic, %eax ; fixup
|
||||||
|
xchg %eax, 4(%esp)
|
||||||
|
ret
|
||||||
|
|
||||||
|
up_set_tpr_eax:
|
||||||
|
push %eax
|
||||||
|
call up_set_tpr
|
||||||
|
ret
|
||||||
|
|
||||||
|
up_set_tpr:
|
||||||
|
pushf
|
||||||
|
push %eax
|
||||||
|
push %ecx
|
||||||
|
push %ebx
|
||||||
|
reenable_vtpr
|
||||||
|
|
||||||
|
up_set_tpr_failed:
|
||||||
|
mov vapic, %eax ; fixup
|
||||||
|
|
||||||
|
mov %eax, %ebx
|
||||||
|
mov 20(%esp), %bl
|
||||||
|
|
||||||
|
/* %ebx = new vapic (%bl = tpr, %bh = isr, %b3 = irr) */
|
||||||
|
|
||||||
|
lock cmpxchg %ebx, vapic ; fixup
|
||||||
|
jnz up_set_tpr_failed
|
||||||
|
|
||||||
|
/* compute ppr */
|
||||||
|
cmp %bh, %bl
|
||||||
|
jae up_tpr_is_bigger
|
||||||
|
up_isr_is_bigger:
|
||||||
|
mov %bh, %bl
|
||||||
|
up_tpr_is_bigger:
|
||||||
|
/* %bl = ppr */
|
||||||
|
mov %bl, %ch /* ch = ppr */
|
||||||
|
rol $8, %ebx
|
||||||
|
/* now: %bl = irr, %bh = ppr */
|
||||||
|
cmp %bh, %bl
|
||||||
|
ja up_set_tpr_poll_irq
|
||||||
|
|
||||||
|
up_set_tpr_out:
|
||||||
|
pop %ebx
|
||||||
|
pop %ecx
|
||||||
|
pop %eax
|
||||||
|
popf
|
||||||
|
ret $4
|
||||||
|
|
||||||
|
up_set_tpr_poll_irq:
|
||||||
|
mov $kvm_hypercall_vapic_poll_irq, %eax
|
||||||
|
kvm_hypercall
|
||||||
|
jmp up_set_tpr_out
|
||||||
|
|
||||||
|
.text 1
|
||||||
|
fixup_end = .
|
||||||
|
.text 0
|
||||||
|
|
||||||
|
/*
|
||||||
|
* vapic format:
|
||||||
|
* per-vcpu records of size 2^vcpu shift.
|
||||||
|
* byte 0: tpr (r/w)
|
||||||
|
* byte 1: highest in-service interrupt (isr) (r/o); bits 3:0 are zero
|
||||||
|
* byte 2: zero (r/o)
|
||||||
|
* byte 3: highest pending interrupt (irr) (r/o)
|
||||||
|
*/
|
||||||
|
.text 2
|
||||||
|
|
||||||
|
.align 128
|
||||||
|
|
||||||
|
vapic:
|
||||||
|
. = . + vapic_size
|
||||||
|
|
||||||
|
.byte 0 # reserve space for signature
|
||||||
|
.align 512, 0
|
||||||
|
|
||||||
|
_end:
|
Loading…
Reference in New Issue