xref: /qemu/pc-bios/optionrom/kvmvapic.S (revision 5918ff68ff3ffe61ae8ebff5b031d6bdcc63c6bc)
12a2af967SJan Kiszka#
22a2af967SJan Kiszka# Local APIC acceleration for Windows XP and related guests
32a2af967SJan Kiszka#
42a2af967SJan Kiszka# Copyright 2011 Red Hat, Inc. and/or its affiliates
52a2af967SJan Kiszka#
62a2af967SJan Kiszka# Author: Avi Kivity <avi@redhat.com>
72a2af967SJan Kiszka#
82a2af967SJan Kiszka# This work is licensed under the terms of the GNU GPL, version 2, or (at your
92a2af967SJan Kiszka# option) any later version.  See the COPYING file in the top-level directory.
102a2af967SJan Kiszka#
112a2af967SJan Kiszka
12*50198112SJan Kiszka#include "optionrom.h"
13*50198112SJan Kiszka
14*50198112SJan KiszkaOPTION_ROM_START
15*50198112SJan Kiszka
162a2af967SJan Kiszka	# clear vapic area: firmware load using rep insb may cause
172a2af967SJan Kiszka	# stale tpr/isr/irr data to corrupt the vapic area.
182a2af967SJan Kiszka	push %es
192a2af967SJan Kiszka	push %cs
202a2af967SJan Kiszka	pop %es
212a2af967SJan Kiszka	xor %ax, %ax
222a2af967SJan Kiszka	mov $vapic_size/2, %cx
232a2af967SJan Kiszka	lea vapic, %di
242a2af967SJan Kiszka	cld
252a2af967SJan Kiszka	rep stosw
262a2af967SJan Kiszka	pop %es
27*50198112SJan Kiszka
28*50198112SJan Kiszka	# announce presence to the hypervisor
292a2af967SJan Kiszka	mov $vapic_base, %ax
302a2af967SJan Kiszka	out %ax, $0x7e
31*50198112SJan Kiszka
322a2af967SJan Kiszka	lret
332a2af967SJan Kiszka
342a2af967SJan Kiszka	.code32
352a2af967SJan Kiszkavapic_size = 2*4096
362a2af967SJan Kiszka
372a2af967SJan Kiszka.macro fixup delta=-4
382a2af967SJan Kiszka777:
392a2af967SJan Kiszka	.text 1
402a2af967SJan Kiszka	.long 777b + \delta  - vapic_base
412a2af967SJan Kiszka	.text 0
422a2af967SJan Kiszka.endm
432a2af967SJan Kiszka
442a2af967SJan Kiszka.macro reenable_vtpr
452a2af967SJan Kiszka	out %al, $0x7e
462a2af967SJan Kiszka.endm
472a2af967SJan Kiszka
482a2af967SJan Kiszka.text 1
492a2af967SJan Kiszka	fixup_start = .
502a2af967SJan Kiszka.text 0
512a2af967SJan Kiszka
522a2af967SJan Kiszka.align 16
532a2af967SJan Kiszka
542a2af967SJan Kiszkavapic_base:
552a2af967SJan Kiszka	.ascii "kvm aPiC"
562a2af967SJan Kiszka
572a2af967SJan Kiszka	/* relocation data */
582a2af967SJan Kiszka	.long vapic_base	; fixup
592a2af967SJan Kiszka	.long fixup_start	; fixup
602a2af967SJan Kiszka	.long fixup_end		; fixup
612a2af967SJan Kiszka
622a2af967SJan Kiszka	.long vapic		; fixup
632a2af967SJan Kiszka	.long vapic_size
642a2af967SJan Kiszkavcpu_shift:
652a2af967SJan Kiszka	.long 0
662a2af967SJan Kiszkareal_tpr:
672a2af967SJan Kiszka	.long 0
682a2af967SJan Kiszka	.long up_set_tpr	; fixup
692a2af967SJan Kiszka	.long up_set_tpr_eax	; fixup
702a2af967SJan Kiszka	.long up_get_tpr_eax	; fixup
712a2af967SJan Kiszka	.long up_get_tpr_ecx	; fixup
722a2af967SJan Kiszka	.long up_get_tpr_edx	; fixup
732a2af967SJan Kiszka	.long up_get_tpr_ebx	; fixup
742a2af967SJan Kiszka	.long 0 /* esp. won't work. */
752a2af967SJan Kiszka	.long up_get_tpr_ebp	; fixup
762a2af967SJan Kiszka	.long up_get_tpr_esi	; fixup
772a2af967SJan Kiszka	.long up_get_tpr_edi	; fixup
782a2af967SJan Kiszka	.long up_get_tpr_stack  ; fixup
792a2af967SJan Kiszka	.long mp_set_tpr	; fixup
802a2af967SJan Kiszka	.long mp_set_tpr_eax	; fixup
812a2af967SJan Kiszka	.long mp_get_tpr_eax	; fixup
822a2af967SJan Kiszka	.long mp_get_tpr_ecx	; fixup
832a2af967SJan Kiszka	.long mp_get_tpr_edx	; fixup
842a2af967SJan Kiszka	.long mp_get_tpr_ebx	; fixup
852a2af967SJan Kiszka	.long 0 /* esp. won't work. */
862a2af967SJan Kiszka	.long mp_get_tpr_ebp	; fixup
872a2af967SJan Kiszka	.long mp_get_tpr_esi	; fixup
882a2af967SJan Kiszka	.long mp_get_tpr_edi	; fixup
892a2af967SJan Kiszka	.long mp_get_tpr_stack  ; fixup
902a2af967SJan Kiszka
912a2af967SJan Kiszka.macro kvm_hypercall
922a2af967SJan Kiszka	.byte 0x0f, 0x01, 0xc1
932a2af967SJan Kiszka.endm
942a2af967SJan Kiszka
952a2af967SJan Kiszkakvm_hypercall_vapic_poll_irq = 1
962a2af967SJan Kiszka
972a2af967SJan Kiszkapcr_cpu = 0x51
982a2af967SJan Kiszka
992a2af967SJan Kiszka.align 64
1002a2af967SJan Kiszka
1012a2af967SJan Kiszkamp_get_tpr_eax:
1022a2af967SJan Kiszka	pushf
1032a2af967SJan Kiszka	cli
1042a2af967SJan Kiszka	reenable_vtpr
1052a2af967SJan Kiszka	push %ecx
1062a2af967SJan Kiszka
1072a2af967SJan Kiszka	fs/movzbl pcr_cpu, %eax
1082a2af967SJan Kiszka
1092a2af967SJan Kiszka	mov vcpu_shift, %ecx	; fixup
1102a2af967SJan Kiszka	shl %cl, %eax
1112a2af967SJan Kiszka	testb $1, vapic+4(%eax)	; fixup delta=-5
1122a2af967SJan Kiszka	jz mp_get_tpr_bad
1132a2af967SJan Kiszka	movzbl vapic(%eax), %eax ; fixup
1142a2af967SJan Kiszka
1152a2af967SJan Kiszkamp_get_tpr_out:
1162a2af967SJan Kiszka	pop %ecx
1172a2af967SJan Kiszka	popf
1182a2af967SJan Kiszka	ret
1192a2af967SJan Kiszka
1202a2af967SJan Kiszkamp_get_tpr_bad:
1212a2af967SJan Kiszka	mov real_tpr, %eax	; fixup
1222a2af967SJan Kiszka	mov (%eax), %eax
1232a2af967SJan Kiszka	jmp mp_get_tpr_out
1242a2af967SJan Kiszka
1252a2af967SJan Kiszkamp_get_tpr_ebx:
1262a2af967SJan Kiszka	mov %eax, %ebx
1272a2af967SJan Kiszka	call mp_get_tpr_eax
1282a2af967SJan Kiszka	xchg %eax, %ebx
1292a2af967SJan Kiszka	ret
1302a2af967SJan Kiszka
1312a2af967SJan Kiszkamp_get_tpr_ecx:
1322a2af967SJan Kiszka	mov %eax, %ecx
1332a2af967SJan Kiszka	call mp_get_tpr_eax
1342a2af967SJan Kiszka	xchg %eax, %ecx
1352a2af967SJan Kiszka	ret
1362a2af967SJan Kiszka
1372a2af967SJan Kiszkamp_get_tpr_edx:
1382a2af967SJan Kiszka	mov %eax, %edx
1392a2af967SJan Kiszka	call mp_get_tpr_eax
1402a2af967SJan Kiszka	xchg %eax, %edx
1412a2af967SJan Kiszka	ret
1422a2af967SJan Kiszka
1432a2af967SJan Kiszkamp_get_tpr_esi:
1442a2af967SJan Kiszka	mov %eax, %esi
1452a2af967SJan Kiszka	call mp_get_tpr_eax
1462a2af967SJan Kiszka	xchg %eax, %esi
1472a2af967SJan Kiszka	ret
1482a2af967SJan Kiszka
1492a2af967SJan Kiszkamp_get_tpr_edi:
1502a2af967SJan Kiszka	mov %eax, %edi
1512a2af967SJan Kiszka	call mp_get_tpr_edi
1522a2af967SJan Kiszka	xchg %eax, %edi
1532a2af967SJan Kiszka	ret
1542a2af967SJan Kiszka
1552a2af967SJan Kiszkamp_get_tpr_ebp:
1562a2af967SJan Kiszka	mov %eax, %ebp
1572a2af967SJan Kiszka	call mp_get_tpr_eax
1582a2af967SJan Kiszka	xchg %eax, %ebp
1592a2af967SJan Kiszka	ret
1602a2af967SJan Kiszka
1612a2af967SJan Kiszkamp_get_tpr_stack:
1622a2af967SJan Kiszka	call mp_get_tpr_eax
1632a2af967SJan Kiszka	xchg %eax, 4(%esp)
1642a2af967SJan Kiszka	ret
1652a2af967SJan Kiszka
1662a2af967SJan Kiszkamp_set_tpr_eax:
1672a2af967SJan Kiszka	push %eax
1682a2af967SJan Kiszka	call mp_set_tpr
1692a2af967SJan Kiszka	ret
1702a2af967SJan Kiszka
1712a2af967SJan Kiszkamp_set_tpr:
1722a2af967SJan Kiszka	pushf
1732a2af967SJan Kiszka	push %eax
1742a2af967SJan Kiszka	push %ecx
1752a2af967SJan Kiszka	push %edx
1762a2af967SJan Kiszka	push %ebx
1772a2af967SJan Kiszka	cli
1782a2af967SJan Kiszka	reenable_vtpr
1792a2af967SJan Kiszka
1802a2af967SJan Kiszkamp_set_tpr_failed:
1812a2af967SJan Kiszka	fs/movzbl pcr_cpu, %edx
1822a2af967SJan Kiszka
1832a2af967SJan Kiszka	mov vcpu_shift, %ecx	; fixup
1842a2af967SJan Kiszka	shl %cl, %edx
1852a2af967SJan Kiszka
1862a2af967SJan Kiszka	testb $1, vapic+4(%edx)	; fixup delta=-5
1872a2af967SJan Kiszka	jz mp_set_tpr_bad
1882a2af967SJan Kiszka
1892a2af967SJan Kiszka	mov vapic(%edx), %eax	; fixup
1902a2af967SJan Kiszka
1912a2af967SJan Kiszka	mov %eax, %ebx
1922a2af967SJan Kiszka	mov 24(%esp), %bl
1932a2af967SJan Kiszka
1942a2af967SJan Kiszka	/* %ebx = new vapic (%bl = tpr, %bh = isr, %b3 = irr) */
1952a2af967SJan Kiszka
1962a2af967SJan Kiszka	lock cmpxchg %ebx, vapic(%edx) ; fixup
1972a2af967SJan Kiszka	jnz mp_set_tpr_failed
1982a2af967SJan Kiszka
1992a2af967SJan Kiszka	/* compute ppr */
2002a2af967SJan Kiszka	cmp %bh, %bl
2012a2af967SJan Kiszka	jae mp_tpr_is_bigger
2022a2af967SJan Kiszkamp_isr_is_bigger:
2032a2af967SJan Kiszka	mov %bh, %bl
2042a2af967SJan Kiszkamp_tpr_is_bigger:
2052a2af967SJan Kiszka	/* %bl = ppr */
2062a2af967SJan Kiszka	rol $8, %ebx
2072a2af967SJan Kiszka	/* now: %bl = irr, %bh = ppr */
2082a2af967SJan Kiszka	cmp %bh, %bl
2092a2af967SJan Kiszka	ja mp_set_tpr_poll_irq
2102a2af967SJan Kiszka
2112a2af967SJan Kiszkamp_set_tpr_out:
2122a2af967SJan Kiszka	pop %ebx
2132a2af967SJan Kiszka	pop %edx
2142a2af967SJan Kiszka	pop %ecx
2152a2af967SJan Kiszka	pop %eax
2162a2af967SJan Kiszka	popf
2172a2af967SJan Kiszka	ret $4
2182a2af967SJan Kiszka
2192a2af967SJan Kiszkamp_set_tpr_poll_irq:
2202a2af967SJan Kiszka	mov $kvm_hypercall_vapic_poll_irq, %eax
2212a2af967SJan Kiszka	kvm_hypercall
2222a2af967SJan Kiszka	jmp mp_set_tpr_out
2232a2af967SJan Kiszka
2242a2af967SJan Kiszkamp_set_tpr_bad:
2252a2af967SJan Kiszka	mov 24(%esp), %ecx
2262a2af967SJan Kiszka	mov real_tpr, %eax	; fixup
2272a2af967SJan Kiszka	mov %ecx, (%eax)
2282a2af967SJan Kiszka	jmp mp_set_tpr_out
2292a2af967SJan Kiszka
2302a2af967SJan Kiszkaup_get_tpr_eax:
2312a2af967SJan Kiszka	reenable_vtpr
2322a2af967SJan Kiszka	movzbl vapic, %eax ; fixup
2332a2af967SJan Kiszka	ret
2342a2af967SJan Kiszka
2352a2af967SJan Kiszkaup_get_tpr_ebx:
2362a2af967SJan Kiszka	reenable_vtpr
2372a2af967SJan Kiszka	movzbl vapic, %ebx ; fixup
2382a2af967SJan Kiszka	ret
2392a2af967SJan Kiszka
2402a2af967SJan Kiszkaup_get_tpr_ecx:
2412a2af967SJan Kiszka	reenable_vtpr
2422a2af967SJan Kiszka	movzbl vapic, %ecx ; fixup
2432a2af967SJan Kiszka	ret
2442a2af967SJan Kiszka
2452a2af967SJan Kiszkaup_get_tpr_edx:
2462a2af967SJan Kiszka	reenable_vtpr
2472a2af967SJan Kiszka	movzbl vapic, %edx ; fixup
2482a2af967SJan Kiszka	ret
2492a2af967SJan Kiszka
2502a2af967SJan Kiszkaup_get_tpr_esi:
2512a2af967SJan Kiszka	reenable_vtpr
2522a2af967SJan Kiszka	movzbl vapic, %esi ; fixup
2532a2af967SJan Kiszka	ret
2542a2af967SJan Kiszka
2552a2af967SJan Kiszkaup_get_tpr_edi:
2562a2af967SJan Kiszka	reenable_vtpr
2572a2af967SJan Kiszka	movzbl vapic, %edi ; fixup
2582a2af967SJan Kiszka	ret
2592a2af967SJan Kiszka
2602a2af967SJan Kiszkaup_get_tpr_ebp:
2612a2af967SJan Kiszka	reenable_vtpr
2622a2af967SJan Kiszka	movzbl vapic, %ebp ; fixup
2632a2af967SJan Kiszka	ret
2642a2af967SJan Kiszka
2652a2af967SJan Kiszkaup_get_tpr_stack:
2662a2af967SJan Kiszka	reenable_vtpr
2672a2af967SJan Kiszka	movzbl vapic, %eax ; fixup
2682a2af967SJan Kiszka	xchg %eax, 4(%esp)
2692a2af967SJan Kiszka	ret
2702a2af967SJan Kiszka
2712a2af967SJan Kiszkaup_set_tpr_eax:
2722a2af967SJan Kiszka	push %eax
2732a2af967SJan Kiszka	call up_set_tpr
2742a2af967SJan Kiszka	ret
2752a2af967SJan Kiszka
2762a2af967SJan Kiszkaup_set_tpr:
2772a2af967SJan Kiszka	pushf
2782a2af967SJan Kiszka	push %eax
2792a2af967SJan Kiszka	push %ebx
2802a2af967SJan Kiszka	reenable_vtpr
2812a2af967SJan Kiszka
2822a2af967SJan Kiszkaup_set_tpr_failed:
2832a2af967SJan Kiszka	mov vapic, %eax	; fixup
2842a2af967SJan Kiszka
2852a2af967SJan Kiszka	mov %eax, %ebx
2861189aa51SJan Kiszka	mov 16(%esp), %bl
2872a2af967SJan Kiszka
2882a2af967SJan Kiszka	/* %ebx = new vapic (%bl = tpr, %bh = isr, %b3 = irr) */
2892a2af967SJan Kiszka
2902a2af967SJan Kiszka	lock cmpxchg %ebx, vapic ; fixup
2912a2af967SJan Kiszka	jnz up_set_tpr_failed
2922a2af967SJan Kiszka
2932a2af967SJan Kiszka	/* compute ppr */
2942a2af967SJan Kiszka	cmp %bh, %bl
2952a2af967SJan Kiszka	jae up_tpr_is_bigger
2962a2af967SJan Kiszkaup_isr_is_bigger:
2972a2af967SJan Kiszka	mov %bh, %bl
2982a2af967SJan Kiszkaup_tpr_is_bigger:
2992a2af967SJan Kiszka	/* %bl = ppr */
3002a2af967SJan Kiszka	rol $8, %ebx
3012a2af967SJan Kiszka	/* now: %bl = irr, %bh = ppr */
3022a2af967SJan Kiszka	cmp %bh, %bl
3032a2af967SJan Kiszka	ja up_set_tpr_poll_irq
3042a2af967SJan Kiszka
3052a2af967SJan Kiszkaup_set_tpr_out:
3062a2af967SJan Kiszka	pop %ebx
3072a2af967SJan Kiszka	pop %eax
3082a2af967SJan Kiszka	popf
3092a2af967SJan Kiszka	ret $4
3102a2af967SJan Kiszka
3112a2af967SJan Kiszkaup_set_tpr_poll_irq:
3122a2af967SJan Kiszka	mov $kvm_hypercall_vapic_poll_irq, %eax
3132a2af967SJan Kiszka	kvm_hypercall
3142a2af967SJan Kiszka	jmp up_set_tpr_out
3152a2af967SJan Kiszka
3162a2af967SJan Kiszka.text 1
3172a2af967SJan Kiszka	fixup_end = .
3182a2af967SJan Kiszka.text 0
3192a2af967SJan Kiszka
3202a2af967SJan Kiszka/*
3212a2af967SJan Kiszka * vapic format:
3222a2af967SJan Kiszka *  per-vcpu records of size 2^vcpu shift.
3232a2af967SJan Kiszka *     byte 0: tpr (r/w)
3242a2af967SJan Kiszka *     byte 1: highest in-service interrupt (isr) (r/o); bits 3:0 are zero
3252a2af967SJan Kiszka *     byte 2: zero (r/o)
3262a2af967SJan Kiszka *     byte 3: highest pending interrupt (irr) (r/o)
3272a2af967SJan Kiszka */
3282a2af967SJan Kiszka.text 2
3292a2af967SJan Kiszka
3302a2af967SJan Kiszka.align 128
3312a2af967SJan Kiszka
3322a2af967SJan Kiszkavapic:
3332a2af967SJan Kiszka. = . + vapic_size
3342a2af967SJan Kiszka
335*50198112SJan KiszkaOPTION_ROM_END
336