Annotation of qemu/pc-bios/optionrom/kvmvapic.S, revision 1.1

1.1     ! root        1: #
        !             2: # Local APIC acceleration for Windows XP and related guests
        !             3: #
        !             4: # Copyright 2011 Red Hat, Inc. and/or its affiliates
        !             5: #
        !             6: # Author: Avi Kivity <[email protected]>
        !             7: #
        !             8: # This work is licensed under the terms of the GNU GPL, version 2, or (at your
        !             9: # option) any later version.  See the COPYING file in the top-level directory.
        !            10: #
        !            11: 
        !            12: #include "optionrom.h"
        !            13: 
        !            14: OPTION_ROM_START
        !            15: 
        !            16:        # clear vapic area: firmware load using rep insb may cause
        !            17:        # stale tpr/isr/irr data to corrupt the vapic area.
        !            18:        push %es
        !            19:        push %cs
        !            20:        pop %es
        !            21:        xor %ax, %ax
        !            22:        mov $vapic_size/2, %cx
        !            23:        lea vapic, %di
        !            24:        cld
        !            25:        rep stosw
        !            26:        pop %es
        !            27: 
        !            28:        # announce presence to the hypervisor
        !            29:        mov $vapic_base, %ax
        !            30:        out %ax, $0x7e
        !            31: 
        !            32:        lret
        !            33: 
        !            34:        .code32
        !            35: vapic_size = 2*4096
        !            36: 
        !            37: .macro fixup delta=-4
        !            38: 777:
        !            39:        .text 1
        !            40:        .long 777b + \delta  - vapic_base
        !            41:        .text 0
        !            42: .endm
        !            43: 
        !            44: .macro reenable_vtpr
        !            45:        out %al, $0x7e
        !            46: .endm
        !            47: 
        !            48: .text 1
        !            49:        fixup_start = .
        !            50: .text 0
        !            51: 
        !            52: .align 16
        !            53: 
        !            54: vapic_base:
        !            55:        .ascii "kvm aPiC"
        !            56: 
        !            57:        /* relocation data */
        !            58:        .long vapic_base        ; fixup
        !            59:        .long fixup_start       ; fixup
        !            60:        .long fixup_end         ; fixup
        !            61: 
        !            62:        .long vapic             ; fixup
        !            63:        .long vapic_size
        !            64: vcpu_shift:
        !            65:        .long 0
        !            66: real_tpr:
        !            67:        .long 0
        !            68:        .long up_set_tpr        ; fixup
        !            69:        .long up_set_tpr_eax    ; fixup
        !            70:        .long up_get_tpr_eax    ; fixup
        !            71:        .long up_get_tpr_ecx    ; fixup
        !            72:        .long up_get_tpr_edx    ; fixup
        !            73:        .long up_get_tpr_ebx    ; fixup
        !            74:        .long 0 /* esp. won't work. */
        !            75:        .long up_get_tpr_ebp    ; fixup
        !            76:        .long up_get_tpr_esi    ; fixup
        !            77:        .long up_get_tpr_edi    ; fixup
        !            78:        .long up_get_tpr_stack  ; fixup
        !            79:        .long mp_set_tpr        ; fixup
        !            80:        .long mp_set_tpr_eax    ; fixup
        !            81:        .long mp_get_tpr_eax    ; fixup
        !            82:        .long mp_get_tpr_ecx    ; fixup
        !            83:        .long mp_get_tpr_edx    ; fixup
        !            84:        .long mp_get_tpr_ebx    ; fixup
        !            85:        .long 0 /* esp. won't work. */
        !            86:        .long mp_get_tpr_ebp    ; fixup
        !            87:        .long mp_get_tpr_esi    ; fixup
        !            88:        .long mp_get_tpr_edi    ; fixup
        !            89:        .long mp_get_tpr_stack  ; fixup
        !            90: 
        !            91: .macro kvm_hypercall
        !            92:        .byte 0x0f, 0x01, 0xc1
        !            93: .endm
        !            94: 
        !            95: kvm_hypercall_vapic_poll_irq = 1
        !            96: 
        !            97: pcr_cpu = 0x51
        !            98: 
        !            99: .align 64
        !           100: 
        !           101: mp_get_tpr_eax:
        !           102:        pushf
        !           103:        cli
        !           104:        reenable_vtpr
        !           105:        push %ecx
        !           106: 
        !           107:        fs/movzbl pcr_cpu, %eax
        !           108: 
        !           109:        mov vcpu_shift, %ecx    ; fixup
        !           110:        shl %cl, %eax
        !           111:        testb $1, vapic+4(%eax) ; fixup delta=-5
        !           112:        jz mp_get_tpr_bad
        !           113:        movzbl vapic(%eax), %eax ; fixup
        !           114: 
        !           115: mp_get_tpr_out:
        !           116:        pop %ecx
        !           117:        popf
        !           118:        ret
        !           119: 
        !           120: mp_get_tpr_bad:
        !           121:        mov real_tpr, %eax      ; fixup
        !           122:        mov (%eax), %eax
        !           123:        jmp mp_get_tpr_out
        !           124: 
        !           125: mp_get_tpr_ebx:
        !           126:        mov %eax, %ebx
        !           127:        call mp_get_tpr_eax
        !           128:        xchg %eax, %ebx
        !           129:        ret
        !           130: 
        !           131: mp_get_tpr_ecx:
        !           132:        mov %eax, %ecx
        !           133:        call mp_get_tpr_eax
        !           134:        xchg %eax, %ecx
        !           135:        ret
        !           136: 
        !           137: mp_get_tpr_edx:
        !           138:        mov %eax, %edx
        !           139:        call mp_get_tpr_eax
        !           140:        xchg %eax, %edx
        !           141:        ret
        !           142: 
        !           143: mp_get_tpr_esi:
        !           144:        mov %eax, %esi
        !           145:        call mp_get_tpr_eax
        !           146:        xchg %eax, %esi
        !           147:        ret
        !           148: 
        !           149: mp_get_tpr_edi:
        !           150:        mov %eax, %edi
        !           151:        call mp_get_tpr_edi
        !           152:        xchg %eax, %edi
        !           153:        ret
        !           154: 
        !           155: mp_get_tpr_ebp:
        !           156:        mov %eax, %ebp
        !           157:        call mp_get_tpr_eax
        !           158:        xchg %eax, %ebp
        !           159:        ret
        !           160: 
        !           161: mp_get_tpr_stack:
        !           162:        call mp_get_tpr_eax
        !           163:        xchg %eax, 4(%esp)
        !           164:        ret
        !           165: 
        !           166: mp_set_tpr_eax:
        !           167:        push %eax
        !           168:        call mp_set_tpr
        !           169:        ret
        !           170: 
        !           171: mp_set_tpr:
        !           172:        pushf
        !           173:        push %eax
        !           174:        push %ecx
        !           175:        push %edx
        !           176:        push %ebx
        !           177:        cli
        !           178:        reenable_vtpr
        !           179: 
        !           180: mp_set_tpr_failed:
        !           181:        fs/movzbl pcr_cpu, %edx
        !           182: 
        !           183:        mov vcpu_shift, %ecx    ; fixup
        !           184:        shl %cl, %edx
        !           185: 
        !           186:        testb $1, vapic+4(%edx) ; fixup delta=-5
        !           187:        jz mp_set_tpr_bad
        !           188: 
        !           189:        mov vapic(%edx), %eax   ; fixup
        !           190: 
        !           191:        mov %eax, %ebx
        !           192:        mov 24(%esp), %bl
        !           193: 
        !           194:        /* %ebx = new vapic (%bl = tpr, %bh = isr, %b3 = irr) */
        !           195: 
        !           196:        lock cmpxchg %ebx, vapic(%edx) ; fixup
        !           197:        jnz mp_set_tpr_failed
        !           198: 
        !           199:        /* compute ppr */
        !           200:        cmp %bh, %bl
        !           201:        jae mp_tpr_is_bigger
        !           202: mp_isr_is_bigger:
        !           203:        mov %bh, %bl
        !           204: mp_tpr_is_bigger:
        !           205:        /* %bl = ppr */
        !           206:        rol $8, %ebx
        !           207:        /* now: %bl = irr, %bh = ppr */
        !           208:        cmp %bh, %bl
        !           209:        ja mp_set_tpr_poll_irq
        !           210: 
        !           211: mp_set_tpr_out:
        !           212:        pop %ebx
        !           213:        pop %edx
        !           214:        pop %ecx
        !           215:        pop %eax
        !           216:        popf
        !           217:        ret $4
        !           218: 
        !           219: mp_set_tpr_poll_irq:
        !           220:        mov $kvm_hypercall_vapic_poll_irq, %eax
        !           221:        kvm_hypercall
        !           222:        jmp mp_set_tpr_out
        !           223: 
        !           224: mp_set_tpr_bad:
        !           225:        mov 24(%esp), %ecx
        !           226:        mov real_tpr, %eax      ; fixup
        !           227:        mov %ecx, (%eax)
        !           228:        jmp mp_set_tpr_out
        !           229: 
        !           230: up_get_tpr_eax:
        !           231:        reenable_vtpr
        !           232:        movzbl vapic, %eax ; fixup
        !           233:        ret
        !           234: 
        !           235: up_get_tpr_ebx:
        !           236:        reenable_vtpr
        !           237:        movzbl vapic, %ebx ; fixup
        !           238:        ret
        !           239: 
        !           240: up_get_tpr_ecx:
        !           241:        reenable_vtpr
        !           242:        movzbl vapic, %ecx ; fixup
        !           243:        ret
        !           244: 
        !           245: up_get_tpr_edx:
        !           246:        reenable_vtpr
        !           247:        movzbl vapic, %edx ; fixup
        !           248:        ret
        !           249: 
        !           250: up_get_tpr_esi:
        !           251:        reenable_vtpr
        !           252:        movzbl vapic, %esi ; fixup
        !           253:        ret
        !           254: 
        !           255: up_get_tpr_edi:
        !           256:        reenable_vtpr
        !           257:        movzbl vapic, %edi ; fixup
        !           258:        ret
        !           259: 
        !           260: up_get_tpr_ebp:
        !           261:        reenable_vtpr
        !           262:        movzbl vapic, %ebp ; fixup
        !           263:        ret
        !           264: 
        !           265: up_get_tpr_stack:
        !           266:        reenable_vtpr
        !           267:        movzbl vapic, %eax ; fixup
        !           268:        xchg %eax, 4(%esp)
        !           269:        ret
        !           270: 
        !           271: up_set_tpr_eax:
        !           272:        push %eax
        !           273:        call up_set_tpr
        !           274:        ret
        !           275: 
        !           276: up_set_tpr:
        !           277:        pushf
        !           278:        push %eax
        !           279:        push %ebx
        !           280:        reenable_vtpr
        !           281: 
        !           282: up_set_tpr_failed:
        !           283:        mov vapic, %eax ; fixup
        !           284: 
        !           285:        mov %eax, %ebx
        !           286:        mov 16(%esp), %bl
        !           287: 
        !           288:        /* %ebx = new vapic (%bl = tpr, %bh = isr, %b3 = irr) */
        !           289: 
        !           290:        lock cmpxchg %ebx, vapic ; fixup
        !           291:        jnz up_set_tpr_failed
        !           292: 
        !           293:        /* compute ppr */
        !           294:        cmp %bh, %bl
        !           295:        jae up_tpr_is_bigger
        !           296: up_isr_is_bigger:
        !           297:        mov %bh, %bl
        !           298: up_tpr_is_bigger:
        !           299:        /* %bl = ppr */
        !           300:        rol $8, %ebx
        !           301:        /* now: %bl = irr, %bh = ppr */
        !           302:        cmp %bh, %bl
        !           303:        ja up_set_tpr_poll_irq
        !           304: 
        !           305: up_set_tpr_out:
        !           306:        pop %ebx
        !           307:        pop %eax
        !           308:        popf
        !           309:        ret $4
        !           310: 
        !           311: up_set_tpr_poll_irq:
        !           312:        mov $kvm_hypercall_vapic_poll_irq, %eax
        !           313:        kvm_hypercall
        !           314:        jmp up_set_tpr_out
        !           315: 
        !           316: .text 1
        !           317:        fixup_end = .
        !           318: .text 0
        !           319: 
        !           320: /*
        !           321:  * vapic format:
        !           322:  *  per-vcpu records of size 2^vcpu shift.
        !           323:  *     byte 0: tpr (r/w)
        !           324:  *     byte 1: highest in-service interrupt (isr) (r/o); bits 3:0 are zero
        !           325:  *     byte 2: zero (r/o)
        !           326:  *     byte 3: highest pending interrupt (irr) (r/o)
        !           327:  */
        !           328: .text 2
        !           329: 
        !           330: .align 128
        !           331: 
        !           332: vapic:
        !           333: . = . + vapic_size
        !           334: 
        !           335: OPTION_ROM_END

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.