diff options
Diffstat (limited to 'qemu/pc-bios/optionrom/kvmvapic.S')
-rw-r--r-- | qemu/pc-bios/optionrom/kvmvapic.S | 335 |
1 files changed, 0 insertions, 335 deletions
diff --git a/qemu/pc-bios/optionrom/kvmvapic.S b/qemu/pc-bios/optionrom/kvmvapic.S deleted file mode 100644 index aa17a402d..000000000 --- a/qemu/pc-bios/optionrom/kvmvapic.S +++ /dev/null @@ -1,335 +0,0 @@ -# -# 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. -# - -#include "optionrom.h" - -OPTION_ROM_START - - # 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 - - # announce presence to the hypervisor - 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 */ - 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 %ebx - reenable_vtpr - -up_set_tpr_failed: - mov vapic, %eax ; fixup - - mov %eax, %ebx - mov 16(%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 */ - rol $8, %ebx - /* now: %bl = irr, %bh = ppr */ - cmp %bh, %bl - ja up_set_tpr_poll_irq - -up_set_tpr_out: - pop %ebx - 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 - -OPTION_ROM_END |