Revision 2a2af967

b/.gitignore
75 75
pc-bios/optionrom/linuxboot.bin
76 76
pc-bios/optionrom/multiboot.bin
77 77
pc-bios/optionrom/multiboot.raw
78
pc-bios/optionrom/kvmvapic.bin
78 79
.stgit-*
79 80
cscope.*
80 81
tags
b/Makefile
253 253
pxe-pcnet.rom pxe-rtl8139.rom pxe-virtio.rom \
254 254
bamboo.dtb petalogix-s3adsp1800.dtb petalogix-ml605.dtb \
255 255
mpc8544ds.dtb \
256
multiboot.bin linuxboot.bin \
256
multiboot.bin linuxboot.bin kvmvapic.bin \
257 257
s390-zipl.rom \
258 258
spapr-rtas.bin slof.bin \
259 259
palcode-clipper
b/pc-bios/optionrom/Makefile
14 14
CFLAGS += $(call cc-option, $(CFLAGS), -fno-stack-protector)
15 15
QEMU_CFLAGS = $(CFLAGS)
16 16

  
17
build-all: multiboot.bin linuxboot.bin
17
build-all: multiboot.bin linuxboot.bin kvmvapic.bin
18 18

  
19 19
# suppress auto-removal of intermediate files
20 20
.SECONDARY:
b/pc-bios/optionrom/kvmvapic.S
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
	.text 0
13
	.code16
14
.global _start
15
_start:
16
	.short 0xaa55
17
	.byte (_end - _start) / 512
18
	# clear vapic area: firmware load using rep insb may cause
19
	# stale tpr/isr/irr data to corrupt the vapic area.
20
	push %es
21
	push %cs
22
	pop %es
23
	xor %ax, %ax
24
	mov $vapic_size/2, %cx
25
	lea vapic, %di
26
	cld
27
	rep stosw
28
	pop %es
29
	mov $vapic_base, %ax
30
	out %ax, $0x7e
31
	lret
32

  
33
	.code32
34
vapic_size = 2*4096
35

  
36
.macro fixup delta=-4
37
777:
38
	.text 1
39
	.long 777b + \delta  - vapic_base
40
	.text 0
41
.endm
42

  
43
.macro reenable_vtpr
44
	out %al, $0x7e
45
.endm
46

  
47
.text 1
48
	fixup_start = .
49
.text 0
50

  
51
.align 16
52

  
53
vapic_base:
54
	.ascii "kvm aPiC"
55

  
56
	/* relocation data */
57
	.long vapic_base	; fixup
58
	.long fixup_start	; fixup
59
	.long fixup_end		; fixup
60

  
61
	.long vapic		; fixup
62
	.long vapic_size
63
vcpu_shift:
64
	.long 0
65
real_tpr:
66
	.long 0
67
	.long up_set_tpr	; fixup
68
	.long up_set_tpr_eax	; fixup
69
	.long up_get_tpr_eax	; fixup
70
	.long up_get_tpr_ecx	; fixup
71
	.long up_get_tpr_edx	; fixup
72
	.long up_get_tpr_ebx	; fixup
73
	.long 0 /* esp. won't work. */
74
	.long up_get_tpr_ebp	; fixup
75
	.long up_get_tpr_esi	; fixup
76
	.long up_get_tpr_edi	; fixup
77
	.long up_get_tpr_stack  ; fixup
78
	.long mp_set_tpr	; fixup
79
	.long mp_set_tpr_eax	; fixup
80
	.long mp_get_tpr_eax	; fixup
81
	.long mp_get_tpr_ecx	; fixup
82
	.long mp_get_tpr_edx	; fixup
83
	.long mp_get_tpr_ebx	; fixup
84
	.long 0 /* esp. won't work. */
85
	.long mp_get_tpr_ebp	; fixup
86
	.long mp_get_tpr_esi	; fixup
87
	.long mp_get_tpr_edi	; fixup
88
	.long mp_get_tpr_stack  ; fixup
89

  
90
.macro kvm_hypercall
91
	.byte 0x0f, 0x01, 0xc1
92
.endm
93

  
94
kvm_hypercall_vapic_poll_irq = 1
95

  
96
pcr_cpu = 0x51
97

  
98
.align 64
99

  
100
mp_get_tpr_eax:
101
	pushf
102
	cli
103
	reenable_vtpr
104
	push %ecx
105

  
106
	fs/movzbl pcr_cpu, %eax
107

  
108
	mov vcpu_shift, %ecx	; fixup
109
	shl %cl, %eax
110
	testb $1, vapic+4(%eax)	; fixup delta=-5
111
	jz mp_get_tpr_bad
112
	movzbl vapic(%eax), %eax ; fixup
113

  
114
mp_get_tpr_out:
115
	pop %ecx
116
	popf
117
	ret
118

  
119
mp_get_tpr_bad:
120
	mov real_tpr, %eax	; fixup
121
	mov (%eax), %eax
122
	jmp mp_get_tpr_out
123

  
124
mp_get_tpr_ebx:
125
	mov %eax, %ebx
126
	call mp_get_tpr_eax
127
	xchg %eax, %ebx
128
	ret
129

  
130
mp_get_tpr_ecx:
131
	mov %eax, %ecx
132
	call mp_get_tpr_eax
133
	xchg %eax, %ecx
134
	ret
135

  
136
mp_get_tpr_edx:
137
	mov %eax, %edx
138
	call mp_get_tpr_eax
139
	xchg %eax, %edx
140
	ret
141

  
142
mp_get_tpr_esi:
143
	mov %eax, %esi
144
	call mp_get_tpr_eax
145
	xchg %eax, %esi
146
	ret
147

  
148
mp_get_tpr_edi:
149
	mov %eax, %edi
150
	call mp_get_tpr_edi
151
	xchg %eax, %edi
152
	ret
153

  
154
mp_get_tpr_ebp:
155
	mov %eax, %ebp
156
	call mp_get_tpr_eax
157
	xchg %eax, %ebp
158
	ret
159

  
160
mp_get_tpr_stack:
161
	call mp_get_tpr_eax
162
	xchg %eax, 4(%esp)
163
	ret
164

  
165
mp_set_tpr_eax:
166
	push %eax
167
	call mp_set_tpr
168
	ret
169

  
170
mp_set_tpr:
171
	pushf
172
	push %eax
173
	push %ecx
174
	push %edx
175
	push %ebx
176
	cli
177
	reenable_vtpr
178

  
179
mp_set_tpr_failed:
180
	fs/movzbl pcr_cpu, %edx
181

  
182
	mov vcpu_shift, %ecx	; fixup
183
	shl %cl, %edx
184

  
185
	testb $1, vapic+4(%edx)	; fixup delta=-5
186
	jz mp_set_tpr_bad
187

  
188
	mov vapic(%edx), %eax	; fixup
189

  
190
	mov %eax, %ebx
191
	mov 24(%esp), %bl
192

  
193
	/* %ebx = new vapic (%bl = tpr, %bh = isr, %b3 = irr) */
194

  
195
	lock cmpxchg %ebx, vapic(%edx) ; fixup
196
	jnz mp_set_tpr_failed
197

  
198
	/* compute ppr */
199
	cmp %bh, %bl
200
	jae mp_tpr_is_bigger
201
mp_isr_is_bigger:
202
	mov %bh, %bl
203
mp_tpr_is_bigger:
204
	/* %bl = ppr */
205
	mov %bl, %ch   /* ch = 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 %ecx
280
	push %ebx
281
	reenable_vtpr
282

  
283
up_set_tpr_failed:
284
	mov vapic, %eax	; fixup
285

  
286
	mov %eax, %ebx
287
	mov 20(%esp), %bl
288

  
289
	/* %ebx = new vapic (%bl = tpr, %bh = isr, %b3 = irr) */
290

  
291
	lock cmpxchg %ebx, vapic ; fixup
292
	jnz up_set_tpr_failed
293

  
294
	/* compute ppr */
295
	cmp %bh, %bl
296
	jae up_tpr_is_bigger
297
up_isr_is_bigger:
298
	mov %bh, %bl
299
up_tpr_is_bigger:
300
	/* %bl = ppr */
301
	mov %bl, %ch   /* ch = ppr */
302
	rol $8, %ebx
303
	/* now: %bl = irr, %bh = ppr */
304
	cmp %bh, %bl
305
	ja up_set_tpr_poll_irq
306

  
307
up_set_tpr_out:
308
	pop %ebx
309
	pop %ecx
310
	pop %eax
311
	popf
312
	ret $4
313

  
314
up_set_tpr_poll_irq:
315
	mov $kvm_hypercall_vapic_poll_irq, %eax
316
	kvm_hypercall
317
	jmp up_set_tpr_out
318

  
319
.text 1
320
	fixup_end = .
321
.text 0
322

  
323
/*
324
 * vapic format:
325
 *  per-vcpu records of size 2^vcpu shift.
326
 *     byte 0: tpr (r/w)
327
 *     byte 1: highest in-service interrupt (isr) (r/o); bits 3:0 are zero
328
 *     byte 2: zero (r/o)
329
 *     byte 3: highest pending interrupt (irr) (r/o)
330
 */
331
.text 2
332

  
333
.align 128
334

  
335
vapic:
336
. = . + vapic_size
337

  
338
.byte 0  # reserve space for signature
339
.align 512, 0
340

  
341
_end:

Also available in: Unified diff