Merge branch 'upstream-merge'
[qemu-kvm/markmc.git] / pc-bios / optionrom / vapic.S
blob1924eebde04c7f8575c7cc52bf835382526a6991
1         .text 0
2         .code16
3 .global _start
4 _start:
5         .short 0xaa55
6         .byte (_end - _start) / 512
7         mov $vapic_base, %ax
8         out %ax, $0x7e
9         lret
11         .code32
12 vapic_size = 2*4096
14 .macro fixup delta=-4
15 777:
16         .text 1
17         .long 777b + \delta  - vapic_base
18         .text 0
19 .endm
21 .macro reenable_vtpr
22         out %al, $0x7e
23 .endm
25 .text 1
26         fixup_start = .
27 .text 0
29 vapic_base:
30         .ascii "kvm aPiC"
32         /* relocation data */
33         .long vapic_base        ; fixup
34         .long fixup_start       ; fixup
35         .long fixup_end         ; fixup
37         .long vapic             ; fixup
38         .long vapic_size
39 vcpu_shift:
40         .long 0
41 real_tpr:
42         .long 0
43         .long up_set_tpr        ; fixup
44         .long up_set_tpr_eax    ; fixup
45         .long up_get_tpr_eax    ; fixup
46         .long up_get_tpr_ecx    ; fixup
47         .long up_get_tpr_edx    ; fixup
48         .long up_get_tpr_ebx    ; fixup
49         .long 0 /* esp. won't work. */
50         .long up_get_tpr_ebp    ; fixup
51         .long up_get_tpr_esi    ; fixup
52         .long up_get_tpr_edi    ; fixup
53         .long up_get_tpr_stack  ; fixup
54         .long mp_set_tpr        ; fixup
55         .long mp_set_tpr_eax    ; fixup
56         .long mp_get_tpr_eax    ; fixup
57         .long mp_get_tpr_ecx    ; fixup
58         .long mp_get_tpr_edx    ; fixup
59         .long mp_get_tpr_ebx    ; fixup
60         .long 0 /* esp. won't work. */
61         .long mp_get_tpr_ebp    ; fixup
62         .long mp_get_tpr_esi    ; fixup
63         .long mp_get_tpr_edi    ; fixup
64         .long mp_get_tpr_stack  ; fixup
66 .macro kvm_hypercall
67         .byte 0x0f, 0x01, 0xc1
68 .endm
70 kvm_hypercall_vapic_poll_irq = 1
72 pcr_cpu = 0x51
74 .align 64
76 mp_get_tpr_eax:
77         pushf
78         cli
79         reenable_vtpr
80         push %ecx
82         fs/movzbl pcr_cpu, %eax
84         mov vcpu_shift, %ecx    ; fixup
85         shl %cl, %eax
86         testb $1, vapic+4(%eax) ; fixup delta=-5
87         jz mp_get_tpr_bad
88         movzbl vapic(%eax), %eax ; fixup
90 mp_get_tpr_out:
91         pop %ecx
92         popf
93         ret
95 mp_get_tpr_bad:
96         mov real_tpr, %eax      ; fixup
97         mov (%eax), %eax
98         jmp mp_get_tpr_out
100 mp_get_tpr_ebx:
101         mov %eax, %ebx
102         call mp_get_tpr_eax
103         xchg %eax, %ebx
104         ret
106 mp_get_tpr_ecx:
107         mov %eax, %ecx
108         call mp_get_tpr_eax
109         xchg %eax, %ecx
110         ret
112 mp_get_tpr_edx:
113         mov %eax, %edx
114         call mp_get_tpr_eax
115         xchg %eax, %edx
116         ret
118 mp_get_tpr_esi:
119         mov %eax, %esi
120         call mp_get_tpr_eax
121         xchg %eax, %esi
122         ret
124 mp_get_tpr_edi:
125         mov %eax, %edi
126         call mp_get_tpr_edi
127         xchg %eax, %edi
128         ret
130 mp_get_tpr_ebp:
131         mov %eax, %ebp
132         call mp_get_tpr_eax
133         xchg %eax, %ebp
134         ret
136 mp_get_tpr_stack:
137         call mp_get_tpr_eax
138         xchg %eax, 4(%esp)
139         ret
141 mp_set_tpr_eax:
142         push %eax
143         call mp_set_tpr
144         ret
146 mp_set_tpr:
147         pushf
148         push %eax
149         push %ecx
150         push %edx
151         push %ebx
152         cli
153         reenable_vtpr
155 mp_set_tpr_failed:
156         fs/movzbl pcr_cpu, %edx
158         mov vcpu_shift, %ecx    ; fixup
159         shl %cl, %edx
161         testb $1, vapic+4(%edx) ; fixup delta=-5
162         jz mp_set_tpr_bad
164         mov vapic(%edx), %eax   ; fixup
166         mov %eax, %ebx
167         mov 24(%esp), %bl
169         /* %ebx = new vapic (%bl = tpr, %bh = isr, %b3 = irr) */
171         lock cmpxchg %ebx, vapic(%edx) ; fixup
172         jnz mp_set_tpr_failed
174         /* compute ppr */
175         cmp %bh, %bl
176         jae mp_tpr_is_bigger
177 mp_isr_is_bigger:
178         mov %bh, %bl
179 mp_tpr_is_bigger:
180         /* %bl = ppr */
181         mov %bl, %ch   /* ch = ppr */
182         rol $8, %ebx
183         /* now: %bl = irr, %bh = ppr */
184         cmp %bh, %bl
185         ja mp_set_tpr_poll_irq
187 mp_set_tpr_out:
188         pop %ebx
189         pop %edx
190         pop %ecx
191         pop %eax
192         popf
193         ret $4
195 mp_set_tpr_poll_irq:
196         mov $kvm_hypercall_vapic_poll_irq, %eax
197         kvm_hypercall
198         jmp mp_set_tpr_out
200 mp_set_tpr_bad:
201         mov 24(%esp), %ecx
202         mov real_tpr, %eax      ; fixup
203         mov %ecx, (%eax)
204         jmp mp_set_tpr_out
206 up_get_tpr_eax:
207         reenable_vtpr
208         movzbl vapic, %eax ; fixup
209         ret
211 up_get_tpr_ebx:
212         reenable_vtpr
213         movzbl vapic, %ebx ; fixup
214         ret
216 up_get_tpr_ecx:
217         reenable_vtpr
218         movzbl vapic, %ecx ; fixup
219         ret
221 up_get_tpr_edx:
222         reenable_vtpr
223         movzbl vapic, %edx ; fixup
224         ret
226 up_get_tpr_esi:
227         reenable_vtpr
228         movzbl vapic, %esi ; fixup
229         ret
231 up_get_tpr_edi:
232         reenable_vtpr
233         movzbl vapic, %edi ; fixup
234         ret
236 up_get_tpr_ebp:
237         reenable_vtpr
238         movzbl vapic, %ebp ; fixup
239         ret
241 up_get_tpr_stack:
242         reenable_vtpr
243         movzbl vapic, %eax ; fixup
244         xchg %eax, 4(%esp)
245         ret
247 up_set_tpr_eax:
248         push %eax
249         call up_set_tpr
250         ret
252 up_set_tpr:
253         pushf
254         push %eax
255         push %ecx
256         push %ebx
257         reenable_vtpr
259 up_set_tpr_failed:
260         mov vapic, %eax ; fixup
262         mov %eax, %ebx
263         mov 20(%esp), %bl
265         /* %ebx = new vapic (%bl = tpr, %bh = isr, %b3 = irr) */
267         lock cmpxchg %ebx, vapic ; fixup
268         jnz up_set_tpr_failed
270         /* compute ppr */
271         cmp %bh, %bl
272         jae up_tpr_is_bigger
273 up_isr_is_bigger:
274         mov %bh, %bl
275 up_tpr_is_bigger:
276         /* %bl = ppr */
277         mov %bl, %ch   /* ch = ppr */
278         rol $8, %ebx
279         /* now: %bl = irr, %bh = ppr */
280         cmp %bh, %bl
281         ja up_set_tpr_poll_irq
283 up_set_tpr_out:
284         pop %ebx
285         pop %ecx
286         pop %eax
287         popf
288         ret $4
290 up_set_tpr_poll_irq:
291         mov $kvm_hypercall_vapic_poll_irq, %eax
292         kvm_hypercall
293         jmp up_set_tpr_out
295 .text 1
296         fixup_end = .
297 .text 0
299 .align 128
301  * vapic format:
302  *  per-vcpu records of size 2^vcpu shift.
303  *     byte 0: tpr (r/w)
304  *     byte 1: highest in-service interrupt (isr) (r/o); bits 3:0 are zero
305  *     byte 2: zero (r/o)
306  *     byte 3: highest pending interrupt (irr) (r/o)
307  */
308 .text 2
309 vapic:
310 . = . + vapic_size
311 _end: