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