|
|
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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.