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