kvm_stat: move groups and events into well defined objects
[qemu/qemu-dev-zwu.git] / pc-bios / optionrom / vapic.S
blob97fa19ca74f54e205b8c3b893bc11ffe6c0864ea
1         .text 0
2         .code16
3 .global _start
4 _start:
5         .short 0xaa55
6         .byte (_end - _start) / 512
7         # clear vapic area: firmware load using rep insb may cause
8         # stale tpr/isr/irr data to corrupt the vapic area.
9         push %es
10         push %cs
11         pop %es
12         xor %ax, %ax
13         mov $vapic_size/2, %cx
14         lea vapic, %di
15         cld
16         rep stosw
17         pop %es
18         mov $vapic_base, %ax
19         out %ax, $0x7e
20         lret
22         .code32
23 vapic_size = 2*4096
25 .macro fixup delta=-4
26 777:
27         .text 1
28         .long 777b + \delta  - vapic_base
29         .text 0
30 .endm
32 .macro reenable_vtpr
33         out %al, $0x7e
34 .endm
36 .text 1
37         fixup_start = .
38 .text 0
40 .align 16
42 vapic_base:
43         .ascii "kvm aPiC"
45         /* relocation data */
46         .long vapic_base        ; fixup
47         .long fixup_start       ; fixup
48         .long fixup_end         ; fixup
50         .long vapic             ; fixup
51         .long vapic_size
52 vcpu_shift:
53         .long 0
54 real_tpr:
55         .long 0
56         .long up_set_tpr        ; fixup
57         .long up_set_tpr_eax    ; fixup
58         .long up_get_tpr_eax    ; fixup
59         .long up_get_tpr_ecx    ; fixup
60         .long up_get_tpr_edx    ; fixup
61         .long up_get_tpr_ebx    ; fixup
62         .long 0 /* esp. won't work. */
63         .long up_get_tpr_ebp    ; fixup
64         .long up_get_tpr_esi    ; fixup
65         .long up_get_tpr_edi    ; fixup
66         .long up_get_tpr_stack  ; fixup
67         .long mp_set_tpr        ; fixup
68         .long mp_set_tpr_eax    ; fixup
69         .long mp_get_tpr_eax    ; fixup
70         .long mp_get_tpr_ecx    ; fixup
71         .long mp_get_tpr_edx    ; fixup
72         .long mp_get_tpr_ebx    ; fixup
73         .long 0 /* esp. won't work. */
74         .long mp_get_tpr_ebp    ; fixup
75         .long mp_get_tpr_esi    ; fixup
76         .long mp_get_tpr_edi    ; fixup
77         .long mp_get_tpr_stack  ; fixup
79 .macro kvm_hypercall
80         .byte 0x0f, 0x01, 0xc1
81 .endm
83 kvm_hypercall_vapic_poll_irq = 1
85 pcr_cpu = 0x51
87 .align 64
89 mp_get_tpr_eax:
90         pushf
91         cli
92         reenable_vtpr
93         push %ecx
95         fs/movzbl pcr_cpu, %eax
97         mov vcpu_shift, %ecx    ; fixup
98         shl %cl, %eax
99         testb $1, vapic+4(%eax) ; fixup delta=-5
100         jz mp_get_tpr_bad
101         movzbl vapic(%eax), %eax ; fixup
103 mp_get_tpr_out:
104         pop %ecx
105         popf
106         ret
108 mp_get_tpr_bad:
109         mov real_tpr, %eax      ; fixup
110         mov (%eax), %eax
111         jmp mp_get_tpr_out
113 mp_get_tpr_ebx:
114         mov %eax, %ebx
115         call mp_get_tpr_eax
116         xchg %eax, %ebx
117         ret
119 mp_get_tpr_ecx:
120         mov %eax, %ecx
121         call mp_get_tpr_eax
122         xchg %eax, %ecx
123         ret
125 mp_get_tpr_edx:
126         mov %eax, %edx
127         call mp_get_tpr_eax
128         xchg %eax, %edx
129         ret
131 mp_get_tpr_esi:
132         mov %eax, %esi
133         call mp_get_tpr_eax
134         xchg %eax, %esi
135         ret
137 mp_get_tpr_edi:
138         mov %eax, %edi
139         call mp_get_tpr_edi
140         xchg %eax, %edi
141         ret
143 mp_get_tpr_ebp:
144         mov %eax, %ebp
145         call mp_get_tpr_eax
146         xchg %eax, %ebp
147         ret
149 mp_get_tpr_stack:
150         call mp_get_tpr_eax
151         xchg %eax, 4(%esp)
152         ret
154 mp_set_tpr_eax:
155         push %eax
156         call mp_set_tpr
157         ret
159 mp_set_tpr:
160         pushf
161         push %eax
162         push %ecx
163         push %edx
164         push %ebx
165         cli
166         reenable_vtpr
168 mp_set_tpr_failed:
169         fs/movzbl pcr_cpu, %edx
171         mov vcpu_shift, %ecx    ; fixup
172         shl %cl, %edx
174         testb $1, vapic+4(%edx) ; fixup delta=-5
175         jz mp_set_tpr_bad
177         mov vapic(%edx), %eax   ; fixup
179         mov %eax, %ebx
180         mov 24(%esp), %bl
182         /* %ebx = new vapic (%bl = tpr, %bh = isr, %b3 = irr) */
184         lock cmpxchg %ebx, vapic(%edx) ; fixup
185         jnz mp_set_tpr_failed
187         /* compute ppr */
188         cmp %bh, %bl
189         jae mp_tpr_is_bigger
190 mp_isr_is_bigger:
191         mov %bh, %bl
192 mp_tpr_is_bigger:
193         /* %bl = ppr */
194         mov %bl, %ch   /* ch = ppr */
195         rol $8, %ebx
196         /* now: %bl = irr, %bh = ppr */
197         cmp %bh, %bl
198         ja mp_set_tpr_poll_irq
200 mp_set_tpr_out:
201         pop %ebx
202         pop %edx
203         pop %ecx
204         pop %eax
205         popf
206         ret $4
208 mp_set_tpr_poll_irq:
209         mov $kvm_hypercall_vapic_poll_irq, %eax
210         kvm_hypercall
211         jmp mp_set_tpr_out
213 mp_set_tpr_bad:
214         mov 24(%esp), %ecx
215         mov real_tpr, %eax      ; fixup
216         mov %ecx, (%eax)
217         jmp mp_set_tpr_out
219 up_get_tpr_eax:
220         reenable_vtpr
221         movzbl vapic, %eax ; fixup
222         ret
224 up_get_tpr_ebx:
225         reenable_vtpr
226         movzbl vapic, %ebx ; fixup
227         ret
229 up_get_tpr_ecx:
230         reenable_vtpr
231         movzbl vapic, %ecx ; fixup
232         ret
234 up_get_tpr_edx:
235         reenable_vtpr
236         movzbl vapic, %edx ; fixup
237         ret
239 up_get_tpr_esi:
240         reenable_vtpr
241         movzbl vapic, %esi ; fixup
242         ret
244 up_get_tpr_edi:
245         reenable_vtpr
246         movzbl vapic, %edi ; fixup
247         ret
249 up_get_tpr_ebp:
250         reenable_vtpr
251         movzbl vapic, %ebp ; fixup
252         ret
254 up_get_tpr_stack:
255         reenable_vtpr
256         movzbl vapic, %eax ; fixup
257         xchg %eax, 4(%esp)
258         ret
260 up_set_tpr_eax:
261         push %eax
262         call up_set_tpr
263         ret
265 up_set_tpr:
266         pushf
267         push %eax
268         push %ecx
269         push %ebx
270         reenable_vtpr
272 up_set_tpr_failed:
273         mov vapic, %eax ; fixup
275         mov %eax, %ebx
276         mov 20(%esp), %bl
278         /* %ebx = new vapic (%bl = tpr, %bh = isr, %b3 = irr) */
280         lock cmpxchg %ebx, vapic ; fixup
281         jnz up_set_tpr_failed
283         /* compute ppr */
284         cmp %bh, %bl
285         jae up_tpr_is_bigger
286 up_isr_is_bigger:
287         mov %bh, %bl
288 up_tpr_is_bigger:
289         /* %bl = ppr */
290         mov %bl, %ch   /* ch = ppr */
291         rol $8, %ebx
292         /* now: %bl = irr, %bh = ppr */
293         cmp %bh, %bl
294         ja up_set_tpr_poll_irq
296 up_set_tpr_out:
297         pop %ebx
298         pop %ecx
299         pop %eax
300         popf
301         ret $4
303 up_set_tpr_poll_irq:
304         mov $kvm_hypercall_vapic_poll_irq, %eax
305         kvm_hypercall
306         jmp up_set_tpr_out
308 .text 1
309         fixup_end = .
310 .text 0
313  * vapic format:
314  *  per-vcpu records of size 2^vcpu shift.
315  *     byte 0: tpr (r/w)
316  *     byte 1: highest in-service interrupt (isr) (r/o); bits 3:0 are zero
317  *     byte 2: zero (r/o)
318  *     byte 3: highest pending interrupt (irr) (r/o)
319  */
320 .text 2
322 .align 128
324 vapic:
325 . = . + vapic_size
327 .byte 0  # reserve space for signature
328 .align 512, 0
330 _end: