cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

kvmvapic.S (5233B)


      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 <avi@redhat.com>
      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
     14OPTION_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
     35vapic_size = 2*4096
     36
     37.macro fixup delta=-4
     38777:
     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
     54vapic_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
     64vcpu_shift:
     65	.long 0
     66real_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
     95kvm_hypercall_vapic_poll_irq = 1
     96
     97pcr_cpu = 0x51
     98
     99.align 64
    100
    101mp_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
    115mp_get_tpr_out:
    116	pop %ecx
    117	popf
    118	ret
    119
    120mp_get_tpr_bad:
    121	mov real_tpr, %eax	; fixup
    122	mov (%eax), %eax
    123	jmp mp_get_tpr_out
    124
    125mp_get_tpr_ebx:
    126	mov %eax, %ebx
    127	call mp_get_tpr_eax
    128	xchg %eax, %ebx
    129	ret
    130
    131mp_get_tpr_ecx:
    132	mov %eax, %ecx
    133	call mp_get_tpr_eax
    134	xchg %eax, %ecx
    135	ret
    136
    137mp_get_tpr_edx:
    138	mov %eax, %edx
    139	call mp_get_tpr_eax
    140	xchg %eax, %edx
    141	ret
    142
    143mp_get_tpr_esi:
    144	mov %eax, %esi
    145	call mp_get_tpr_eax
    146	xchg %eax, %esi
    147	ret
    148
    149mp_get_tpr_edi:
    150	mov %eax, %edi
    151	call mp_get_tpr_edi
    152	xchg %eax, %edi
    153	ret
    154
    155mp_get_tpr_ebp:
    156	mov %eax, %ebp
    157	call mp_get_tpr_eax
    158	xchg %eax, %ebp
    159	ret
    160
    161mp_get_tpr_stack:
    162	call mp_get_tpr_eax
    163	xchg %eax, 4(%esp)
    164	ret
    165
    166mp_set_tpr_eax:
    167	push %eax
    168	call mp_set_tpr
    169	ret
    170
    171mp_set_tpr:
    172	pushf
    173	push %eax
    174	push %ecx
    175	push %edx
    176	push %ebx
    177	cli
    178	reenable_vtpr
    179
    180mp_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
    202mp_isr_is_bigger:
    203	mov %bh, %bl
    204mp_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
    211mp_set_tpr_out:
    212	pop %ebx
    213	pop %edx
    214	pop %ecx
    215	pop %eax
    216	popf
    217	ret $4
    218
    219mp_set_tpr_poll_irq:
    220	mov $kvm_hypercall_vapic_poll_irq, %eax
    221	kvm_hypercall
    222	jmp mp_set_tpr_out
    223
    224mp_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
    230up_get_tpr_eax:
    231	reenable_vtpr
    232	movzbl vapic, %eax ; fixup
    233	ret
    234
    235up_get_tpr_ebx:
    236	reenable_vtpr
    237	movzbl vapic, %ebx ; fixup
    238	ret
    239
    240up_get_tpr_ecx:
    241	reenable_vtpr
    242	movzbl vapic, %ecx ; fixup
    243	ret
    244
    245up_get_tpr_edx:
    246	reenable_vtpr
    247	movzbl vapic, %edx ; fixup
    248	ret
    249
    250up_get_tpr_esi:
    251	reenable_vtpr
    252	movzbl vapic, %esi ; fixup
    253	ret
    254
    255up_get_tpr_edi:
    256	reenable_vtpr
    257	movzbl vapic, %edi ; fixup
    258	ret
    259
    260up_get_tpr_ebp:
    261	reenable_vtpr
    262	movzbl vapic, %ebp ; fixup
    263	ret
    264
    265up_get_tpr_stack:
    266	reenable_vtpr
    267	movzbl vapic, %eax ; fixup
    268	xchg %eax, 4(%esp)
    269	ret
    270
    271up_set_tpr_eax:
    272	push %eax
    273	call up_set_tpr
    274	ret
    275
    276up_set_tpr:
    277	pushf
    278	push %eax
    279	push %ebx
    280	reenable_vtpr
    281
    282up_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
    296up_isr_is_bigger:
    297	mov %bh, %bl
    298up_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
    305up_set_tpr_out:
    306	pop %ebx
    307	pop %eax
    308	popf
    309	ret $4
    310
    311up_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
    332vapic:
    333. = . + vapic_size
    334
    335OPTION_ROM_END