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