Merge remote-tracking branch 'remotes/sstabellini/tags/xen-20161028-tag' into staging
[sdk/emulator/qemu.git] / target-i386 / seg_helper.c
1 /*
2  *  x86 segmentation related helpers:
3  *  TSS, interrupts, system calls, jumps and call/task gates, descriptors
4  *
5  *  Copyright (c) 2003 Fabrice Bellard
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include "qemu/osdep.h"
22 #include "cpu.h"
23 #include "qemu/log.h"
24 #include "exec/helper-proto.h"
25 #include "exec/exec-all.h"
26 #include "exec/cpu_ldst.h"
27 #include "exec/log.h"
28
29 //#define DEBUG_PCALL
30
31 #ifdef DEBUG_PCALL
32 # define LOG_PCALL(...) qemu_log_mask(CPU_LOG_PCALL, ## __VA_ARGS__)
33 # define LOG_PCALL_STATE(cpu)                                  \
34     log_cpu_state_mask(CPU_LOG_PCALL, (cpu), CPU_DUMP_CCOP)
35 #else
36 # define LOG_PCALL(...) do { } while (0)
37 # define LOG_PCALL_STATE(cpu) do { } while (0)
38 #endif
39
40 #ifdef CONFIG_USER_ONLY
41 #define MEMSUFFIX _kernel
42 #define DATA_SIZE 1
43 #include "exec/cpu_ldst_useronly_template.h"
44
45 #define DATA_SIZE 2
46 #include "exec/cpu_ldst_useronly_template.h"
47
48 #define DATA_SIZE 4
49 #include "exec/cpu_ldst_useronly_template.h"
50
51 #define DATA_SIZE 8
52 #include "exec/cpu_ldst_useronly_template.h"
53 #undef MEMSUFFIX
54 #else
55 #define CPU_MMU_INDEX (cpu_mmu_index_kernel(env))
56 #define MEMSUFFIX _kernel
57 #define DATA_SIZE 1
58 #include "exec/cpu_ldst_template.h"
59
60 #define DATA_SIZE 2
61 #include "exec/cpu_ldst_template.h"
62
63 #define DATA_SIZE 4
64 #include "exec/cpu_ldst_template.h"
65
66 #define DATA_SIZE 8
67 #include "exec/cpu_ldst_template.h"
68 #undef CPU_MMU_INDEX
69 #undef MEMSUFFIX
70 #endif
71
72 /* return non zero if error */
73 static inline int load_segment_ra(CPUX86State *env, uint32_t *e1_ptr,
74                                uint32_t *e2_ptr, int selector,
75                                uintptr_t retaddr)
76 {
77     SegmentCache *dt;
78     int index;
79     target_ulong ptr;
80
81     if (selector & 0x4) {
82         dt = &env->ldt;
83     } else {
84         dt = &env->gdt;
85     }
86     index = selector & ~7;
87     if ((index + 7) > dt->limit) {
88         return -1;
89     }
90     ptr = dt->base + index;
91     *e1_ptr = cpu_ldl_kernel_ra(env, ptr, retaddr);
92     *e2_ptr = cpu_ldl_kernel_ra(env, ptr + 4, retaddr);
93     return 0;
94 }
95
96 static inline int load_segment(CPUX86State *env, uint32_t *e1_ptr,
97                                uint32_t *e2_ptr, int selector)
98 {
99     return load_segment_ra(env, e1_ptr, e2_ptr, selector, 0);
100 }
101
102 static inline unsigned int get_seg_limit(uint32_t e1, uint32_t e2)
103 {
104     unsigned int limit;
105
106     limit = (e1 & 0xffff) | (e2 & 0x000f0000);
107     if (e2 & DESC_G_MASK) {
108         limit = (limit << 12) | 0xfff;
109     }
110     return limit;
111 }
112
113 static inline uint32_t get_seg_base(uint32_t e1, uint32_t e2)
114 {
115     return (e1 >> 16) | ((e2 & 0xff) << 16) | (e2 & 0xff000000);
116 }
117
118 static inline void load_seg_cache_raw_dt(SegmentCache *sc, uint32_t e1,
119                                          uint32_t e2)
120 {
121     sc->base = get_seg_base(e1, e2);
122     sc->limit = get_seg_limit(e1, e2);
123     sc->flags = e2;
124 }
125
126 /* init the segment cache in vm86 mode. */
127 static inline void load_seg_vm(CPUX86State *env, int seg, int selector)
128 {
129     selector &= 0xffff;
130
131     cpu_x86_load_seg_cache(env, seg, selector, (selector << 4), 0xffff,
132                            DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
133                            DESC_A_MASK | (3 << DESC_DPL_SHIFT));
134 }
135
136 static inline void get_ss_esp_from_tss(CPUX86State *env, uint32_t *ss_ptr,
137                                        uint32_t *esp_ptr, int dpl,
138                                        uintptr_t retaddr)
139 {
140     X86CPU *cpu = x86_env_get_cpu(env);
141     int type, index, shift;
142
143 #if 0
144     {
145         int i;
146         printf("TR: base=%p limit=%x\n", env->tr.base, env->tr.limit);
147         for (i = 0; i < env->tr.limit; i++) {
148             printf("%02x ", env->tr.base[i]);
149             if ((i & 7) == 7) {
150                 printf("\n");
151             }
152         }
153         printf("\n");
154     }
155 #endif
156
157     if (!(env->tr.flags & DESC_P_MASK)) {
158         cpu_abort(CPU(cpu), "invalid tss");
159     }
160     type = (env->tr.flags >> DESC_TYPE_SHIFT) & 0xf;
161     if ((type & 7) != 1) {
162         cpu_abort(CPU(cpu), "invalid tss type");
163     }
164     shift = type >> 3;
165     index = (dpl * 4 + 2) << shift;
166     if (index + (4 << shift) - 1 > env->tr.limit) {
167         raise_exception_err_ra(env, EXCP0A_TSS, env->tr.selector & 0xfffc, retaddr);
168     }
169     if (shift == 0) {
170         *esp_ptr = cpu_lduw_kernel_ra(env, env->tr.base + index, retaddr);
171         *ss_ptr = cpu_lduw_kernel_ra(env, env->tr.base + index + 2, retaddr);
172     } else {
173         *esp_ptr = cpu_ldl_kernel_ra(env, env->tr.base + index, retaddr);
174         *ss_ptr = cpu_lduw_kernel_ra(env, env->tr.base + index + 4, retaddr);
175     }
176 }
177
178 static void tss_load_seg(CPUX86State *env, int seg_reg, int selector, int cpl,
179                          uintptr_t retaddr)
180 {
181     uint32_t e1, e2;
182     int rpl, dpl;
183
184     if ((selector & 0xfffc) != 0) {
185         if (load_segment_ra(env, &e1, &e2, selector, retaddr) != 0) {
186             raise_exception_err_ra(env, EXCP0A_TSS, selector & 0xfffc, retaddr);
187         }
188         if (!(e2 & DESC_S_MASK)) {
189             raise_exception_err_ra(env, EXCP0A_TSS, selector & 0xfffc, retaddr);
190         }
191         rpl = selector & 3;
192         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
193         if (seg_reg == R_CS) {
194             if (!(e2 & DESC_CS_MASK)) {
195                 raise_exception_err_ra(env, EXCP0A_TSS, selector & 0xfffc, retaddr);
196             }
197             if (dpl != rpl) {
198                 raise_exception_err_ra(env, EXCP0A_TSS, selector & 0xfffc, retaddr);
199             }
200         } else if (seg_reg == R_SS) {
201             /* SS must be writable data */
202             if ((e2 & DESC_CS_MASK) || !(e2 & DESC_W_MASK)) {
203                 raise_exception_err_ra(env, EXCP0A_TSS, selector & 0xfffc, retaddr);
204             }
205             if (dpl != cpl || dpl != rpl) {
206                 raise_exception_err_ra(env, EXCP0A_TSS, selector & 0xfffc, retaddr);
207             }
208         } else {
209             /* not readable code */
210             if ((e2 & DESC_CS_MASK) && !(e2 & DESC_R_MASK)) {
211                 raise_exception_err_ra(env, EXCP0A_TSS, selector & 0xfffc, retaddr);
212             }
213             /* if data or non conforming code, checks the rights */
214             if (((e2 >> DESC_TYPE_SHIFT) & 0xf) < 12) {
215                 if (dpl < cpl || dpl < rpl) {
216                     raise_exception_err_ra(env, EXCP0A_TSS, selector & 0xfffc, retaddr);
217                 }
218             }
219         }
220         if (!(e2 & DESC_P_MASK)) {
221             raise_exception_err_ra(env, EXCP0B_NOSEG, selector & 0xfffc, retaddr);
222         }
223         cpu_x86_load_seg_cache(env, seg_reg, selector,
224                                get_seg_base(e1, e2),
225                                get_seg_limit(e1, e2),
226                                e2);
227     } else {
228         if (seg_reg == R_SS || seg_reg == R_CS) {
229             raise_exception_err_ra(env, EXCP0A_TSS, selector & 0xfffc, retaddr);
230         }
231     }
232 }
233
234 #define SWITCH_TSS_JMP  0
235 #define SWITCH_TSS_IRET 1
236 #define SWITCH_TSS_CALL 2
237
238 /* XXX: restore CPU state in registers (PowerPC case) */
239 static void switch_tss_ra(CPUX86State *env, int tss_selector,
240                           uint32_t e1, uint32_t e2, int source,
241                           uint32_t next_eip, uintptr_t retaddr)
242 {
243     int tss_limit, tss_limit_max, type, old_tss_limit_max, old_type, v1, v2, i;
244     target_ulong tss_base;
245     uint32_t new_regs[8], new_segs[6];
246     uint32_t new_eflags, new_eip, new_cr3, new_ldt, new_trap;
247     uint32_t old_eflags, eflags_mask;
248     SegmentCache *dt;
249     int index;
250     target_ulong ptr;
251
252     type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
253     LOG_PCALL("switch_tss: sel=0x%04x type=%d src=%d\n", tss_selector, type,
254               source);
255
256     /* if task gate, we read the TSS segment and we load it */
257     if (type == 5) {
258         if (!(e2 & DESC_P_MASK)) {
259             raise_exception_err_ra(env, EXCP0B_NOSEG, tss_selector & 0xfffc, retaddr);
260         }
261         tss_selector = e1 >> 16;
262         if (tss_selector & 4) {
263             raise_exception_err_ra(env, EXCP0A_TSS, tss_selector & 0xfffc, retaddr);
264         }
265         if (load_segment_ra(env, &e1, &e2, tss_selector, retaddr) != 0) {
266             raise_exception_err_ra(env, EXCP0D_GPF, tss_selector & 0xfffc, retaddr);
267         }
268         if (e2 & DESC_S_MASK) {
269             raise_exception_err_ra(env, EXCP0D_GPF, tss_selector & 0xfffc, retaddr);
270         }
271         type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
272         if ((type & 7) != 1) {
273             raise_exception_err_ra(env, EXCP0D_GPF, tss_selector & 0xfffc, retaddr);
274         }
275     }
276
277     if (!(e2 & DESC_P_MASK)) {
278         raise_exception_err_ra(env, EXCP0B_NOSEG, tss_selector & 0xfffc, retaddr);
279     }
280
281     if (type & 8) {
282         tss_limit_max = 103;
283     } else {
284         tss_limit_max = 43;
285     }
286     tss_limit = get_seg_limit(e1, e2);
287     tss_base = get_seg_base(e1, e2);
288     if ((tss_selector & 4) != 0 ||
289         tss_limit < tss_limit_max) {
290         raise_exception_err_ra(env, EXCP0A_TSS, tss_selector & 0xfffc, retaddr);
291     }
292     old_type = (env->tr.flags >> DESC_TYPE_SHIFT) & 0xf;
293     if (old_type & 8) {
294         old_tss_limit_max = 103;
295     } else {
296         old_tss_limit_max = 43;
297     }
298
299     /* read all the registers from the new TSS */
300     if (type & 8) {
301         /* 32 bit */
302         new_cr3 = cpu_ldl_kernel_ra(env, tss_base + 0x1c, retaddr);
303         new_eip = cpu_ldl_kernel_ra(env, tss_base + 0x20, retaddr);
304         new_eflags = cpu_ldl_kernel_ra(env, tss_base + 0x24, retaddr);
305         for (i = 0; i < 8; i++) {
306             new_regs[i] = cpu_ldl_kernel_ra(env, tss_base + (0x28 + i * 4),
307                                             retaddr);
308         }
309         for (i = 0; i < 6; i++) {
310             new_segs[i] = cpu_lduw_kernel_ra(env, tss_base + (0x48 + i * 4),
311                                              retaddr);
312         }
313         new_ldt = cpu_lduw_kernel_ra(env, tss_base + 0x60, retaddr);
314         new_trap = cpu_ldl_kernel_ra(env, tss_base + 0x64, retaddr);
315     } else {
316         /* 16 bit */
317         new_cr3 = 0;
318         new_eip = cpu_lduw_kernel_ra(env, tss_base + 0x0e, retaddr);
319         new_eflags = cpu_lduw_kernel_ra(env, tss_base + 0x10, retaddr);
320         for (i = 0; i < 8; i++) {
321             new_regs[i] = cpu_lduw_kernel_ra(env, tss_base + (0x12 + i * 2),
322                                              retaddr) | 0xffff0000;
323         }
324         for (i = 0; i < 4; i++) {
325             new_segs[i] = cpu_lduw_kernel_ra(env, tss_base + (0x22 + i * 4),
326                                              retaddr);
327         }
328         new_ldt = cpu_lduw_kernel_ra(env, tss_base + 0x2a, retaddr);
329         new_segs[R_FS] = 0;
330         new_segs[R_GS] = 0;
331         new_trap = 0;
332     }
333     /* XXX: avoid a compiler warning, see
334      http://support.amd.com/us/Processor_TechDocs/24593.pdf
335      chapters 12.2.5 and 13.2.4 on how to implement TSS Trap bit */
336     (void)new_trap;
337
338     /* NOTE: we must avoid memory exceptions during the task switch,
339        so we make dummy accesses before */
340     /* XXX: it can still fail in some cases, so a bigger hack is
341        necessary to valid the TLB after having done the accesses */
342
343     v1 = cpu_ldub_kernel_ra(env, env->tr.base, retaddr);
344     v2 = cpu_ldub_kernel_ra(env, env->tr.base + old_tss_limit_max, retaddr);
345     cpu_stb_kernel_ra(env, env->tr.base, v1, retaddr);
346     cpu_stb_kernel_ra(env, env->tr.base + old_tss_limit_max, v2, retaddr);
347
348     /* clear busy bit (it is restartable) */
349     if (source == SWITCH_TSS_JMP || source == SWITCH_TSS_IRET) {
350         target_ulong ptr;
351         uint32_t e2;
352
353         ptr = env->gdt.base + (env->tr.selector & ~7);
354         e2 = cpu_ldl_kernel_ra(env, ptr + 4, retaddr);
355         e2 &= ~DESC_TSS_BUSY_MASK;
356         cpu_stl_kernel_ra(env, ptr + 4, e2, retaddr);
357     }
358     old_eflags = cpu_compute_eflags(env);
359     if (source == SWITCH_TSS_IRET) {
360         old_eflags &= ~NT_MASK;
361     }
362
363     /* save the current state in the old TSS */
364     if (type & 8) {
365         /* 32 bit */
366         cpu_stl_kernel_ra(env, env->tr.base + 0x20, next_eip, retaddr);
367         cpu_stl_kernel_ra(env, env->tr.base + 0x24, old_eflags, retaddr);
368         cpu_stl_kernel_ra(env, env->tr.base + (0x28 + 0 * 4), env->regs[R_EAX], retaddr);
369         cpu_stl_kernel_ra(env, env->tr.base + (0x28 + 1 * 4), env->regs[R_ECX], retaddr);
370         cpu_stl_kernel_ra(env, env->tr.base + (0x28 + 2 * 4), env->regs[R_EDX], retaddr);
371         cpu_stl_kernel_ra(env, env->tr.base + (0x28 + 3 * 4), env->regs[R_EBX], retaddr);
372         cpu_stl_kernel_ra(env, env->tr.base + (0x28 + 4 * 4), env->regs[R_ESP], retaddr);
373         cpu_stl_kernel_ra(env, env->tr.base + (0x28 + 5 * 4), env->regs[R_EBP], retaddr);
374         cpu_stl_kernel_ra(env, env->tr.base + (0x28 + 6 * 4), env->regs[R_ESI], retaddr);
375         cpu_stl_kernel_ra(env, env->tr.base + (0x28 + 7 * 4), env->regs[R_EDI], retaddr);
376         for (i = 0; i < 6; i++) {
377             cpu_stw_kernel_ra(env, env->tr.base + (0x48 + i * 4),
378                               env->segs[i].selector, retaddr);
379         }
380     } else {
381         /* 16 bit */
382         cpu_stw_kernel_ra(env, env->tr.base + 0x0e, next_eip, retaddr);
383         cpu_stw_kernel_ra(env, env->tr.base + 0x10, old_eflags, retaddr);
384         cpu_stw_kernel_ra(env, env->tr.base + (0x12 + 0 * 2), env->regs[R_EAX], retaddr);
385         cpu_stw_kernel_ra(env, env->tr.base + (0x12 + 1 * 2), env->regs[R_ECX], retaddr);
386         cpu_stw_kernel_ra(env, env->tr.base + (0x12 + 2 * 2), env->regs[R_EDX], retaddr);
387         cpu_stw_kernel_ra(env, env->tr.base + (0x12 + 3 * 2), env->regs[R_EBX], retaddr);
388         cpu_stw_kernel_ra(env, env->tr.base + (0x12 + 4 * 2), env->regs[R_ESP], retaddr);
389         cpu_stw_kernel_ra(env, env->tr.base + (0x12 + 5 * 2), env->regs[R_EBP], retaddr);
390         cpu_stw_kernel_ra(env, env->tr.base + (0x12 + 6 * 2), env->regs[R_ESI], retaddr);
391         cpu_stw_kernel_ra(env, env->tr.base + (0x12 + 7 * 2), env->regs[R_EDI], retaddr);
392         for (i = 0; i < 4; i++) {
393             cpu_stw_kernel_ra(env, env->tr.base + (0x22 + i * 4),
394                               env->segs[i].selector, retaddr);
395         }
396     }
397
398     /* now if an exception occurs, it will occurs in the next task
399        context */
400
401     if (source == SWITCH_TSS_CALL) {
402         cpu_stw_kernel_ra(env, tss_base, env->tr.selector, retaddr);
403         new_eflags |= NT_MASK;
404     }
405
406     /* set busy bit */
407     if (source == SWITCH_TSS_JMP || source == SWITCH_TSS_CALL) {
408         target_ulong ptr;
409         uint32_t e2;
410
411         ptr = env->gdt.base + (tss_selector & ~7);
412         e2 = cpu_ldl_kernel_ra(env, ptr + 4, retaddr);
413         e2 |= DESC_TSS_BUSY_MASK;
414         cpu_stl_kernel_ra(env, ptr + 4, e2, retaddr);
415     }
416
417     /* set the new CPU state */
418     /* from this point, any exception which occurs can give problems */
419     env->cr[0] |= CR0_TS_MASK;
420     env->hflags |= HF_TS_MASK;
421     env->tr.selector = tss_selector;
422     env->tr.base = tss_base;
423     env->tr.limit = tss_limit;
424     env->tr.flags = e2 & ~DESC_TSS_BUSY_MASK;
425
426     if ((type & 8) && (env->cr[0] & CR0_PG_MASK)) {
427         cpu_x86_update_cr3(env, new_cr3);
428     }
429
430     /* load all registers without an exception, then reload them with
431        possible exception */
432     env->eip = new_eip;
433     eflags_mask = TF_MASK | AC_MASK | ID_MASK |
434         IF_MASK | IOPL_MASK | VM_MASK | RF_MASK | NT_MASK;
435     if (!(type & 8)) {
436         eflags_mask &= 0xffff;
437     }
438     cpu_load_eflags(env, new_eflags, eflags_mask);
439     /* XXX: what to do in 16 bit case? */
440     env->regs[R_EAX] = new_regs[0];
441     env->regs[R_ECX] = new_regs[1];
442     env->regs[R_EDX] = new_regs[2];
443     env->regs[R_EBX] = new_regs[3];
444     env->regs[R_ESP] = new_regs[4];
445     env->regs[R_EBP] = new_regs[5];
446     env->regs[R_ESI] = new_regs[6];
447     env->regs[R_EDI] = new_regs[7];
448     if (new_eflags & VM_MASK) {
449         for (i = 0; i < 6; i++) {
450             load_seg_vm(env, i, new_segs[i]);
451         }
452     } else {
453         /* first just selectors as the rest may trigger exceptions */
454         for (i = 0; i < 6; i++) {
455             cpu_x86_load_seg_cache(env, i, new_segs[i], 0, 0, 0);
456         }
457     }
458
459     env->ldt.selector = new_ldt & ~4;
460     env->ldt.base = 0;
461     env->ldt.limit = 0;
462     env->ldt.flags = 0;
463
464     /* load the LDT */
465     if (new_ldt & 4) {
466         raise_exception_err_ra(env, EXCP0A_TSS, new_ldt & 0xfffc, retaddr);
467     }
468
469     if ((new_ldt & 0xfffc) != 0) {
470         dt = &env->gdt;
471         index = new_ldt & ~7;
472         if ((index + 7) > dt->limit) {
473             raise_exception_err_ra(env, EXCP0A_TSS, new_ldt & 0xfffc, retaddr);
474         }
475         ptr = dt->base + index;
476         e1 = cpu_ldl_kernel_ra(env, ptr, retaddr);
477         e2 = cpu_ldl_kernel_ra(env, ptr + 4, retaddr);
478         if ((e2 & DESC_S_MASK) || ((e2 >> DESC_TYPE_SHIFT) & 0xf) != 2) {
479             raise_exception_err_ra(env, EXCP0A_TSS, new_ldt & 0xfffc, retaddr);
480         }
481         if (!(e2 & DESC_P_MASK)) {
482             raise_exception_err_ra(env, EXCP0A_TSS, new_ldt & 0xfffc, retaddr);
483         }
484         load_seg_cache_raw_dt(&env->ldt, e1, e2);
485     }
486
487     /* load the segments */
488     if (!(new_eflags & VM_MASK)) {
489         int cpl = new_segs[R_CS] & 3;
490         tss_load_seg(env, R_CS, new_segs[R_CS], cpl, retaddr);
491         tss_load_seg(env, R_SS, new_segs[R_SS], cpl, retaddr);
492         tss_load_seg(env, R_ES, new_segs[R_ES], cpl, retaddr);
493         tss_load_seg(env, R_DS, new_segs[R_DS], cpl, retaddr);
494         tss_load_seg(env, R_FS, new_segs[R_FS], cpl, retaddr);
495         tss_load_seg(env, R_GS, new_segs[R_GS], cpl, retaddr);
496     }
497
498     /* check that env->eip is in the CS segment limits */
499     if (new_eip > env->segs[R_CS].limit) {
500         /* XXX: different exception if CALL? */
501         raise_exception_err_ra(env, EXCP0D_GPF, 0, retaddr);
502     }
503
504 #ifndef CONFIG_USER_ONLY
505     /* reset local breakpoints */
506     if (env->dr[7] & DR7_LOCAL_BP_MASK) {
507         cpu_x86_update_dr7(env, env->dr[7] & ~DR7_LOCAL_BP_MASK);
508     }
509 #endif
510 }
511
512 static void switch_tss(CPUX86State *env, int tss_selector,
513                        uint32_t e1, uint32_t e2, int source,
514                         uint32_t next_eip)
515 {
516     switch_tss_ra(env, tss_selector, e1, e2, source, next_eip, 0);
517 }
518
519 static inline unsigned int get_sp_mask(unsigned int e2)
520 {
521     if (e2 & DESC_B_MASK) {
522         return 0xffffffff;
523     } else {
524         return 0xffff;
525     }
526 }
527
528 static int exception_has_error_code(int intno)
529 {
530     switch (intno) {
531     case 8:
532     case 10:
533     case 11:
534     case 12:
535     case 13:
536     case 14:
537     case 17:
538         return 1;
539     }
540     return 0;
541 }
542
543 #ifdef TARGET_X86_64
544 #define SET_ESP(val, sp_mask)                                   \
545     do {                                                        \
546         if ((sp_mask) == 0xffff) {                              \
547             env->regs[R_ESP] = (env->regs[R_ESP] & ~0xffff) |   \
548                 ((val) & 0xffff);                               \
549         } else if ((sp_mask) == 0xffffffffLL) {                 \
550             env->regs[R_ESP] = (uint32_t)(val);                 \
551         } else {                                                \
552             env->regs[R_ESP] = (val);                           \
553         }                                                       \
554     } while (0)
555 #else
556 #define SET_ESP(val, sp_mask)                                   \
557     do {                                                        \
558         env->regs[R_ESP] = (env->regs[R_ESP] & ~(sp_mask)) |    \
559             ((val) & (sp_mask));                                \
560     } while (0)
561 #endif
562
563 /* in 64-bit machines, this can overflow. So this segment addition macro
564  * can be used to trim the value to 32-bit whenever needed */
565 #define SEG_ADDL(ssp, sp, sp_mask) ((uint32_t)((ssp) + (sp & (sp_mask))))
566
567 /* XXX: add a is_user flag to have proper security support */
568 #define PUSHW_RA(ssp, sp, sp_mask, val, ra)                      \
569     {                                                            \
570         sp -= 2;                                                 \
571         cpu_stw_kernel_ra(env, (ssp) + (sp & (sp_mask)), (val), ra); \
572     }
573
574 #define PUSHL_RA(ssp, sp, sp_mask, val, ra)                             \
575     {                                                                   \
576         sp -= 4;                                                        \
577         cpu_stl_kernel_ra(env, SEG_ADDL(ssp, sp, sp_mask), (uint32_t)(val), ra); \
578     }
579
580 #define POPW_RA(ssp, sp, sp_mask, val, ra)                       \
581     {                                                            \
582         val = cpu_lduw_kernel_ra(env, (ssp) + (sp & (sp_mask)), ra); \
583         sp += 2;                                                 \
584     }
585
586 #define POPL_RA(ssp, sp, sp_mask, val, ra)                              \
587     {                                                                   \
588         val = (uint32_t)cpu_ldl_kernel_ra(env, SEG_ADDL(ssp, sp, sp_mask), ra); \
589         sp += 4;                                                        \
590     }
591
592 #define PUSHW(ssp, sp, sp_mask, val) PUSHW_RA(ssp, sp, sp_mask, val, 0)
593 #define PUSHL(ssp, sp, sp_mask, val) PUSHL_RA(ssp, sp, sp_mask, val, 0)
594 #define POPW(ssp, sp, sp_mask, val) POPW_RA(ssp, sp, sp_mask, val, 0)
595 #define POPL(ssp, sp, sp_mask, val) POPL_RA(ssp, sp, sp_mask, val, 0)
596
597 /* protected mode interrupt */
598 static void do_interrupt_protected(CPUX86State *env, int intno, int is_int,
599                                    int error_code, unsigned int next_eip,
600                                    int is_hw)
601 {
602     SegmentCache *dt;
603     target_ulong ptr, ssp;
604     int type, dpl, selector, ss_dpl, cpl;
605     int has_error_code, new_stack, shift;
606     uint32_t e1, e2, offset, ss = 0, esp, ss_e1 = 0, ss_e2 = 0;
607     uint32_t old_eip, sp_mask;
608     int vm86 = env->eflags & VM_MASK;
609
610     has_error_code = 0;
611     if (!is_int && !is_hw) {
612         has_error_code = exception_has_error_code(intno);
613     }
614     if (is_int) {
615         old_eip = next_eip;
616     } else {
617         old_eip = env->eip;
618     }
619
620     dt = &env->idt;
621     if (intno * 8 + 7 > dt->limit) {
622         raise_exception_err(env, EXCP0D_GPF, intno * 8 + 2);
623     }
624     ptr = dt->base + intno * 8;
625     e1 = cpu_ldl_kernel(env, ptr);
626     e2 = cpu_ldl_kernel(env, ptr + 4);
627     /* check gate type */
628     type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;
629     switch (type) {
630     case 5: /* task gate */
631         /* must do that check here to return the correct error code */
632         if (!(e2 & DESC_P_MASK)) {
633             raise_exception_err(env, EXCP0B_NOSEG, intno * 8 + 2);
634         }
635         switch_tss(env, intno * 8, e1, e2, SWITCH_TSS_CALL, old_eip);
636         if (has_error_code) {
637             int type;
638             uint32_t mask;
639
640             /* push the error code */
641             type = (env->tr.flags >> DESC_TYPE_SHIFT) & 0xf;
642             shift = type >> 3;
643             if (env->segs[R_SS].flags & DESC_B_MASK) {
644                 mask = 0xffffffff;
645             } else {
646                 mask = 0xffff;
647             }
648             esp = (env->regs[R_ESP] - (2 << shift)) & mask;
649             ssp = env->segs[R_SS].base + esp;
650             if (shift) {
651                 cpu_stl_kernel(env, ssp, error_code);
652             } else {
653                 cpu_stw_kernel(env, ssp, error_code);
654             }
655             SET_ESP(esp, mask);
656         }
657         return;
658     case 6: /* 286 interrupt gate */
659     case 7: /* 286 trap gate */
660     case 14: /* 386 interrupt gate */
661     case 15: /* 386 trap gate */
662         break;
663     default:
664         raise_exception_err(env, EXCP0D_GPF, intno * 8 + 2);
665         break;
666     }
667     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
668     cpl = env->hflags & HF_CPL_MASK;
669     /* check privilege if software int */
670     if (is_int && dpl < cpl) {
671         raise_exception_err(env, EXCP0D_GPF, intno * 8 + 2);
672     }
673     /* check valid bit */
674     if (!(e2 & DESC_P_MASK)) {
675         raise_exception_err(env, EXCP0B_NOSEG, intno * 8 + 2);
676     }
677     selector = e1 >> 16;
678     offset = (e2 & 0xffff0000) | (e1 & 0x0000ffff);
679     if ((selector & 0xfffc) == 0) {
680         raise_exception_err(env, EXCP0D_GPF, 0);
681     }
682     if (load_segment(env, &e1, &e2, selector) != 0) {
683         raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc);
684     }
685     if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK))) {
686         raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc);
687     }
688     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
689     if (dpl > cpl) {
690         raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc);
691     }
692     if (!(e2 & DESC_P_MASK)) {
693         raise_exception_err(env, EXCP0B_NOSEG, selector & 0xfffc);
694     }
695     if (!(e2 & DESC_C_MASK) && dpl < cpl) {
696         /* to inner privilege */
697         get_ss_esp_from_tss(env, &ss, &esp, dpl, 0);
698         if ((ss & 0xfffc) == 0) {
699             raise_exception_err(env, EXCP0A_TSS, ss & 0xfffc);
700         }
701         if ((ss & 3) != dpl) {
702             raise_exception_err(env, EXCP0A_TSS, ss & 0xfffc);
703         }
704         if (load_segment(env, &ss_e1, &ss_e2, ss) != 0) {
705             raise_exception_err(env, EXCP0A_TSS, ss & 0xfffc);
706         }
707         ss_dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3;
708         if (ss_dpl != dpl) {
709             raise_exception_err(env, EXCP0A_TSS, ss & 0xfffc);
710         }
711         if (!(ss_e2 & DESC_S_MASK) ||
712             (ss_e2 & DESC_CS_MASK) ||
713             !(ss_e2 & DESC_W_MASK)) {
714             raise_exception_err(env, EXCP0A_TSS, ss & 0xfffc);
715         }
716         if (!(ss_e2 & DESC_P_MASK)) {
717             raise_exception_err(env, EXCP0A_TSS, ss & 0xfffc);
718         }
719         new_stack = 1;
720         sp_mask = get_sp_mask(ss_e2);
721         ssp = get_seg_base(ss_e1, ss_e2);
722     } else if ((e2 & DESC_C_MASK) || dpl == cpl) {
723         /* to same privilege */
724         if (vm86) {
725             raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc);
726         }
727         new_stack = 0;
728         sp_mask = get_sp_mask(env->segs[R_SS].flags);
729         ssp = env->segs[R_SS].base;
730         esp = env->regs[R_ESP];
731         dpl = cpl;
732     } else {
733         raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc);
734         new_stack = 0; /* avoid warning */
735         sp_mask = 0; /* avoid warning */
736         ssp = 0; /* avoid warning */
737         esp = 0; /* avoid warning */
738     }
739
740     shift = type >> 3;
741
742 #if 0
743     /* XXX: check that enough room is available */
744     push_size = 6 + (new_stack << 2) + (has_error_code << 1);
745     if (vm86) {
746         push_size += 8;
747     }
748     push_size <<= shift;
749 #endif
750     if (shift == 1) {
751         if (new_stack) {
752             if (vm86) {
753                 PUSHL(ssp, esp, sp_mask, env->segs[R_GS].selector);
754                 PUSHL(ssp, esp, sp_mask, env->segs[R_FS].selector);
755                 PUSHL(ssp, esp, sp_mask, env->segs[R_DS].selector);
756                 PUSHL(ssp, esp, sp_mask, env->segs[R_ES].selector);
757             }
758             PUSHL(ssp, esp, sp_mask, env->segs[R_SS].selector);
759             PUSHL(ssp, esp, sp_mask, env->regs[R_ESP]);
760         }
761         PUSHL(ssp, esp, sp_mask, cpu_compute_eflags(env));
762         PUSHL(ssp, esp, sp_mask, env->segs[R_CS].selector);
763         PUSHL(ssp, esp, sp_mask, old_eip);
764         if (has_error_code) {
765             PUSHL(ssp, esp, sp_mask, error_code);
766         }
767     } else {
768         if (new_stack) {
769             if (vm86) {
770                 PUSHW(ssp, esp, sp_mask, env->segs[R_GS].selector);
771                 PUSHW(ssp, esp, sp_mask, env->segs[R_FS].selector);
772                 PUSHW(ssp, esp, sp_mask, env->segs[R_DS].selector);
773                 PUSHW(ssp, esp, sp_mask, env->segs[R_ES].selector);
774             }
775             PUSHW(ssp, esp, sp_mask, env->segs[R_SS].selector);
776             PUSHW(ssp, esp, sp_mask, env->regs[R_ESP]);
777         }
778         PUSHW(ssp, esp, sp_mask, cpu_compute_eflags(env));
779         PUSHW(ssp, esp, sp_mask, env->segs[R_CS].selector);
780         PUSHW(ssp, esp, sp_mask, old_eip);
781         if (has_error_code) {
782             PUSHW(ssp, esp, sp_mask, error_code);
783         }
784     }
785
786     /* interrupt gate clear IF mask */
787     if ((type & 1) == 0) {
788         env->eflags &= ~IF_MASK;
789     }
790     env->eflags &= ~(TF_MASK | VM_MASK | RF_MASK | NT_MASK);
791
792     if (new_stack) {
793         if (vm86) {
794             cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0, 0);
795             cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0, 0);
796             cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0, 0);
797             cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0, 0);
798         }
799         ss = (ss & ~3) | dpl;
800         cpu_x86_load_seg_cache(env, R_SS, ss,
801                                ssp, get_seg_limit(ss_e1, ss_e2), ss_e2);
802     }
803     SET_ESP(esp, sp_mask);
804
805     selector = (selector & ~3) | dpl;
806     cpu_x86_load_seg_cache(env, R_CS, selector,
807                    get_seg_base(e1, e2),
808                    get_seg_limit(e1, e2),
809                    e2);
810     env->eip = offset;
811 }
812
813 #ifdef TARGET_X86_64
814
815 #define PUSHQ_RA(sp, val, ra)                   \
816     {                                           \
817         sp -= 8;                                \
818         cpu_stq_kernel_ra(env, sp, (val), ra);  \
819     }
820
821 #define POPQ_RA(sp, val, ra)                    \
822     {                                           \
823         val = cpu_ldq_kernel_ra(env, sp, ra);   \
824         sp += 8;                                \
825     }
826
827 #define PUSHQ(sp, val) PUSHQ_RA(sp, val, 0)
828 #define POPQ(sp, val) POPQ_RA(sp, val, 0)
829
830 static inline target_ulong get_rsp_from_tss(CPUX86State *env, int level)
831 {
832     X86CPU *cpu = x86_env_get_cpu(env);
833     int index;
834
835 #if 0
836     printf("TR: base=" TARGET_FMT_lx " limit=%x\n",
837            env->tr.base, env->tr.limit);
838 #endif
839
840     if (!(env->tr.flags & DESC_P_MASK)) {
841         cpu_abort(CPU(cpu), "invalid tss");
842     }
843     index = 8 * level + 4;
844     if ((index + 7) > env->tr.limit) {
845         raise_exception_err(env, EXCP0A_TSS, env->tr.selector & 0xfffc);
846     }
847     return cpu_ldq_kernel(env, env->tr.base + index);
848 }
849
850 /* 64 bit interrupt */
851 static void do_interrupt64(CPUX86State *env, int intno, int is_int,
852                            int error_code, target_ulong next_eip, int is_hw)
853 {
854     SegmentCache *dt;
855     target_ulong ptr;
856     int type, dpl, selector, cpl, ist;
857     int has_error_code, new_stack;
858     uint32_t e1, e2, e3, ss;
859     target_ulong old_eip, esp, offset;
860
861     has_error_code = 0;
862     if (!is_int && !is_hw) {
863         has_error_code = exception_has_error_code(intno);
864     }
865     if (is_int) {
866         old_eip = next_eip;
867     } else {
868         old_eip = env->eip;
869     }
870
871     dt = &env->idt;
872     if (intno * 16 + 15 > dt->limit) {
873         raise_exception_err(env, EXCP0D_GPF, intno * 16 + 2);
874     }
875     ptr = dt->base + intno * 16;
876     e1 = cpu_ldl_kernel(env, ptr);
877     e2 = cpu_ldl_kernel(env, ptr + 4);
878     e3 = cpu_ldl_kernel(env, ptr + 8);
879     /* check gate type */
880     type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;
881     switch (type) {
882     case 14: /* 386 interrupt gate */
883     case 15: /* 386 trap gate */
884         break;
885     default:
886         raise_exception_err(env, EXCP0D_GPF, intno * 16 + 2);
887         break;
888     }
889     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
890     cpl = env->hflags & HF_CPL_MASK;
891     /* check privilege if software int */
892     if (is_int && dpl < cpl) {
893         raise_exception_err(env, EXCP0D_GPF, intno * 16 + 2);
894     }
895     /* check valid bit */
896     if (!(e2 & DESC_P_MASK)) {
897         raise_exception_err(env, EXCP0B_NOSEG, intno * 16 + 2);
898     }
899     selector = e1 >> 16;
900     offset = ((target_ulong)e3 << 32) | (e2 & 0xffff0000) | (e1 & 0x0000ffff);
901     ist = e2 & 7;
902     if ((selector & 0xfffc) == 0) {
903         raise_exception_err(env, EXCP0D_GPF, 0);
904     }
905
906     if (load_segment(env, &e1, &e2, selector) != 0) {
907         raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc);
908     }
909     if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK))) {
910         raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc);
911     }
912     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
913     if (dpl > cpl) {
914         raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc);
915     }
916     if (!(e2 & DESC_P_MASK)) {
917         raise_exception_err(env, EXCP0B_NOSEG, selector & 0xfffc);
918     }
919     if (!(e2 & DESC_L_MASK) || (e2 & DESC_B_MASK)) {
920         raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc);
921     }
922     if ((!(e2 & DESC_C_MASK) && dpl < cpl) || ist != 0) {
923         /* to inner privilege */
924         new_stack = 1;
925         esp = get_rsp_from_tss(env, ist != 0 ? ist + 3 : dpl);
926         ss = 0;
927     } else if ((e2 & DESC_C_MASK) || dpl == cpl) {
928         /* to same privilege */
929         if (env->eflags & VM_MASK) {
930             raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc);
931         }
932         new_stack = 0;
933         esp = env->regs[R_ESP];
934         dpl = cpl;
935     } else {
936         raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc);
937         new_stack = 0; /* avoid warning */
938         esp = 0; /* avoid warning */
939     }
940     esp &= ~0xfLL; /* align stack */
941
942     PUSHQ(esp, env->segs[R_SS].selector);
943     PUSHQ(esp, env->regs[R_ESP]);
944     PUSHQ(esp, cpu_compute_eflags(env));
945     PUSHQ(esp, env->segs[R_CS].selector);
946     PUSHQ(esp, old_eip);
947     if (has_error_code) {
948         PUSHQ(esp, error_code);
949     }
950
951     /* interrupt gate clear IF mask */
952     if ((type & 1) == 0) {
953         env->eflags &= ~IF_MASK;
954     }
955     env->eflags &= ~(TF_MASK | VM_MASK | RF_MASK | NT_MASK);
956
957     if (new_stack) {
958         ss = 0 | dpl;
959         cpu_x86_load_seg_cache(env, R_SS, ss, 0, 0, 0);
960     }
961     env->regs[R_ESP] = esp;
962
963     selector = (selector & ~3) | dpl;
964     cpu_x86_load_seg_cache(env, R_CS, selector,
965                    get_seg_base(e1, e2),
966                    get_seg_limit(e1, e2),
967                    e2);
968     env->eip = offset;
969 }
970 #endif
971
972 #ifdef TARGET_X86_64
973 #if defined(CONFIG_USER_ONLY)
974 void helper_syscall(CPUX86State *env, int next_eip_addend)
975 {
976     CPUState *cs = CPU(x86_env_get_cpu(env));
977
978     cs->exception_index = EXCP_SYSCALL;
979     env->exception_next_eip = env->eip + next_eip_addend;
980     cpu_loop_exit(cs);
981 }
982 #else
983 void helper_syscall(CPUX86State *env, int next_eip_addend)
984 {
985     int selector;
986
987     if (!(env->efer & MSR_EFER_SCE)) {
988         raise_exception_err_ra(env, EXCP06_ILLOP, 0, GETPC());
989     }
990     selector = (env->star >> 32) & 0xffff;
991     if (env->hflags & HF_LMA_MASK) {
992         int code64;
993
994         env->regs[R_ECX] = env->eip + next_eip_addend;
995         env->regs[11] = cpu_compute_eflags(env);
996
997         code64 = env->hflags & HF_CS64_MASK;
998
999         env->eflags &= ~env->fmask;
1000         cpu_load_eflags(env, env->eflags, 0);
1001         cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc,
1002                            0, 0xffffffff,
1003                                DESC_G_MASK | DESC_P_MASK |
1004                                DESC_S_MASK |
1005                                DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK |
1006                                DESC_L_MASK);
1007         cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc,
1008                                0, 0xffffffff,
1009                                DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1010                                DESC_S_MASK |
1011                                DESC_W_MASK | DESC_A_MASK);
1012         if (code64) {
1013             env->eip = env->lstar;
1014         } else {
1015             env->eip = env->cstar;
1016         }
1017     } else {
1018         env->regs[R_ECX] = (uint32_t)(env->eip + next_eip_addend);
1019
1020         env->eflags &= ~(IF_MASK | RF_MASK | VM_MASK);
1021         cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc,
1022                            0, 0xffffffff,
1023                                DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1024                                DESC_S_MASK |
1025                                DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
1026         cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc,
1027                                0, 0xffffffff,
1028                                DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1029                                DESC_S_MASK |
1030                                DESC_W_MASK | DESC_A_MASK);
1031         env->eip = (uint32_t)env->star;
1032     }
1033 }
1034 #endif
1035 #endif
1036
1037 #ifdef TARGET_X86_64
1038 void helper_sysret(CPUX86State *env, int dflag)
1039 {
1040     int cpl, selector;
1041
1042     if (!(env->efer & MSR_EFER_SCE)) {
1043         raise_exception_err_ra(env, EXCP06_ILLOP, 0, GETPC());
1044     }
1045     cpl = env->hflags & HF_CPL_MASK;
1046     if (!(env->cr[0] & CR0_PE_MASK) || cpl != 0) {
1047         raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC());
1048     }
1049     selector = (env->star >> 48) & 0xffff;
1050     if (env->hflags & HF_LMA_MASK) {
1051         cpu_load_eflags(env, (uint32_t)(env->regs[11]), TF_MASK | AC_MASK
1052                         | ID_MASK | IF_MASK | IOPL_MASK | VM_MASK | RF_MASK |
1053                         NT_MASK);
1054         if (dflag == 2) {
1055             cpu_x86_load_seg_cache(env, R_CS, (selector + 16) | 3,
1056                                    0, 0xffffffff,
1057                                    DESC_G_MASK | DESC_P_MASK |
1058                                    DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
1059                                    DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK |
1060                                    DESC_L_MASK);
1061             env->eip = env->regs[R_ECX];
1062         } else {
1063             cpu_x86_load_seg_cache(env, R_CS, selector | 3,
1064                                    0, 0xffffffff,
1065                                    DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1066                                    DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
1067                                    DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
1068             env->eip = (uint32_t)env->regs[R_ECX];
1069         }
1070         cpu_x86_load_seg_cache(env, R_SS, (selector + 8) | 3,
1071                                0, 0xffffffff,
1072                                DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1073                                DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
1074                                DESC_W_MASK | DESC_A_MASK);
1075     } else {
1076         env->eflags |= IF_MASK;
1077         cpu_x86_load_seg_cache(env, R_CS, selector | 3,
1078                                0, 0xffffffff,
1079                                DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1080                                DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
1081                                DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
1082         env->eip = (uint32_t)env->regs[R_ECX];
1083         cpu_x86_load_seg_cache(env, R_SS, (selector + 8) | 3,
1084                                0, 0xffffffff,
1085                                DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1086                                DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
1087                                DESC_W_MASK | DESC_A_MASK);
1088     }
1089 }
1090 #endif
1091
1092 /* real mode interrupt */
1093 static void do_interrupt_real(CPUX86State *env, int intno, int is_int,
1094                               int error_code, unsigned int next_eip)
1095 {
1096     SegmentCache *dt;
1097     target_ulong ptr, ssp;
1098     int selector;
1099     uint32_t offset, esp;
1100     uint32_t old_cs, old_eip;
1101
1102     /* real mode (simpler!) */
1103     dt = &env->idt;
1104     if (intno * 4 + 3 > dt->limit) {
1105         raise_exception_err(env, EXCP0D_GPF, intno * 8 + 2);
1106     }
1107     ptr = dt->base + intno * 4;
1108     offset = cpu_lduw_kernel(env, ptr);
1109     selector = cpu_lduw_kernel(env, ptr + 2);
1110     esp = env->regs[R_ESP];
1111     ssp = env->segs[R_SS].base;
1112     if (is_int) {
1113         old_eip = next_eip;
1114     } else {
1115         old_eip = env->eip;
1116     }
1117     old_cs = env->segs[R_CS].selector;
1118     /* XXX: use SS segment size? */
1119     PUSHW(ssp, esp, 0xffff, cpu_compute_eflags(env));
1120     PUSHW(ssp, esp, 0xffff, old_cs);
1121     PUSHW(ssp, esp, 0xffff, old_eip);
1122
1123     /* update processor state */
1124     env->regs[R_ESP] = (env->regs[R_ESP] & ~0xffff) | (esp & 0xffff);
1125     env->eip = offset;
1126     env->segs[R_CS].selector = selector;
1127     env->segs[R_CS].base = (selector << 4);
1128     env->eflags &= ~(IF_MASK | TF_MASK | AC_MASK | RF_MASK);
1129 }
1130
1131 #if defined(CONFIG_USER_ONLY)
1132 /* fake user mode interrupt. is_int is TRUE if coming from the int
1133  * instruction. next_eip is the env->eip value AFTER the interrupt
1134  * instruction. It is only relevant if is_int is TRUE or if intno
1135  * is EXCP_SYSCALL.
1136  */
1137 static void do_interrupt_user(CPUX86State *env, int intno, int is_int,
1138                               int error_code, target_ulong next_eip)
1139 {
1140     if (is_int) {
1141         SegmentCache *dt;
1142         target_ulong ptr;
1143         int dpl, cpl, shift;
1144         uint32_t e2;
1145
1146         dt = &env->idt;
1147         if (env->hflags & HF_LMA_MASK) {
1148             shift = 4;
1149         } else {
1150             shift = 3;
1151         }
1152         ptr = dt->base + (intno << shift);
1153         e2 = cpu_ldl_kernel(env, ptr + 4);
1154
1155         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1156         cpl = env->hflags & HF_CPL_MASK;
1157         /* check privilege if software int */
1158         if (dpl < cpl) {
1159             raise_exception_err(env, EXCP0D_GPF, (intno << shift) + 2);
1160         }
1161     }
1162
1163     /* Since we emulate only user space, we cannot do more than
1164        exiting the emulation with the suitable exception and error
1165        code. So update EIP for INT 0x80 and EXCP_SYSCALL. */
1166     if (is_int || intno == EXCP_SYSCALL) {
1167         env->eip = next_eip;
1168     }
1169 }
1170
1171 #else
1172
1173 static void handle_even_inj(CPUX86State *env, int intno, int is_int,
1174                             int error_code, int is_hw, int rm)
1175 {
1176     CPUState *cs = CPU(x86_env_get_cpu(env));
1177     uint32_t event_inj = x86_ldl_phys(cs, env->vm_vmcb + offsetof(struct vmcb,
1178                                                           control.event_inj));
1179
1180     if (!(event_inj & SVM_EVTINJ_VALID)) {
1181         int type;
1182
1183         if (is_int) {
1184             type = SVM_EVTINJ_TYPE_SOFT;
1185         } else {
1186             type = SVM_EVTINJ_TYPE_EXEPT;
1187         }
1188         event_inj = intno | type | SVM_EVTINJ_VALID;
1189         if (!rm && exception_has_error_code(intno)) {
1190             event_inj |= SVM_EVTINJ_VALID_ERR;
1191             x86_stl_phys(cs, env->vm_vmcb + offsetof(struct vmcb,
1192                                              control.event_inj_err),
1193                      error_code);
1194         }
1195         x86_stl_phys(cs,
1196                  env->vm_vmcb + offsetof(struct vmcb, control.event_inj),
1197                  event_inj);
1198     }
1199 }
1200 #endif
1201
1202 /*
1203  * Begin execution of an interruption. is_int is TRUE if coming from
1204  * the int instruction. next_eip is the env->eip value AFTER the interrupt
1205  * instruction. It is only relevant if is_int is TRUE.
1206  */
1207 static void do_interrupt_all(X86CPU *cpu, int intno, int is_int,
1208                              int error_code, target_ulong next_eip, int is_hw)
1209 {
1210     CPUX86State *env = &cpu->env;
1211
1212     if (qemu_loglevel_mask(CPU_LOG_INT)) {
1213         if ((env->cr[0] & CR0_PE_MASK)) {
1214             static int count;
1215
1216             qemu_log("%6d: v=%02x e=%04x i=%d cpl=%d IP=%04x:" TARGET_FMT_lx
1217                      " pc=" TARGET_FMT_lx " SP=%04x:" TARGET_FMT_lx,
1218                      count, intno, error_code, is_int,
1219                      env->hflags & HF_CPL_MASK,
1220                      env->segs[R_CS].selector, env->eip,
1221                      (int)env->segs[R_CS].base + env->eip,
1222                      env->segs[R_SS].selector, env->regs[R_ESP]);
1223             if (intno == 0x0e) {
1224                 qemu_log(" CR2=" TARGET_FMT_lx, env->cr[2]);
1225             } else {
1226                 qemu_log(" env->regs[R_EAX]=" TARGET_FMT_lx, env->regs[R_EAX]);
1227             }
1228             qemu_log("\n");
1229             log_cpu_state(CPU(cpu), CPU_DUMP_CCOP);
1230 #if 0
1231             {
1232                 int i;
1233                 target_ulong ptr;
1234
1235                 qemu_log("       code=");
1236                 ptr = env->segs[R_CS].base + env->eip;
1237                 for (i = 0; i < 16; i++) {
1238                     qemu_log(" %02x", ldub(ptr + i));
1239                 }
1240                 qemu_log("\n");
1241             }
1242 #endif
1243             count++;
1244         }
1245     }
1246     if (env->cr[0] & CR0_PE_MASK) {
1247 #if !defined(CONFIG_USER_ONLY)
1248         if (env->hflags & HF_SVMI_MASK) {
1249             handle_even_inj(env, intno, is_int, error_code, is_hw, 0);
1250         }
1251 #endif
1252 #ifdef TARGET_X86_64
1253         if (env->hflags & HF_LMA_MASK) {
1254             do_interrupt64(env, intno, is_int, error_code, next_eip, is_hw);
1255         } else
1256 #endif
1257         {
1258             do_interrupt_protected(env, intno, is_int, error_code, next_eip,
1259                                    is_hw);
1260         }
1261     } else {
1262 #if !defined(CONFIG_USER_ONLY)
1263         if (env->hflags & HF_SVMI_MASK) {
1264             handle_even_inj(env, intno, is_int, error_code, is_hw, 1);
1265         }
1266 #endif
1267         do_interrupt_real(env, intno, is_int, error_code, next_eip);
1268     }
1269
1270 #if !defined(CONFIG_USER_ONLY)
1271     if (env->hflags & HF_SVMI_MASK) {
1272         CPUState *cs = CPU(cpu);
1273         uint32_t event_inj = x86_ldl_phys(cs, env->vm_vmcb +
1274                                       offsetof(struct vmcb,
1275                                                control.event_inj));
1276
1277         x86_stl_phys(cs,
1278                  env->vm_vmcb + offsetof(struct vmcb, control.event_inj),
1279                  event_inj & ~SVM_EVTINJ_VALID);
1280     }
1281 #endif
1282 }
1283
1284 void x86_cpu_do_interrupt(CPUState *cs)
1285 {
1286     X86CPU *cpu = X86_CPU(cs);
1287     CPUX86State *env = &cpu->env;
1288
1289 #if defined(CONFIG_USER_ONLY)
1290     /* if user mode only, we simulate a fake exception
1291        which will be handled outside the cpu execution
1292        loop */
1293     do_interrupt_user(env, cs->exception_index,
1294                       env->exception_is_int,
1295                       env->error_code,
1296                       env->exception_next_eip);
1297     /* successfully delivered */
1298     env->old_exception = -1;
1299 #else
1300     /* simulate a real cpu exception. On i386, it can
1301        trigger new exceptions, but we do not handle
1302        double or triple faults yet. */
1303     do_interrupt_all(cpu, cs->exception_index,
1304                      env->exception_is_int,
1305                      env->error_code,
1306                      env->exception_next_eip, 0);
1307     /* successfully delivered */
1308     env->old_exception = -1;
1309 #endif
1310 }
1311
1312 void do_interrupt_x86_hardirq(CPUX86State *env, int intno, int is_hw)
1313 {
1314     do_interrupt_all(x86_env_get_cpu(env), intno, 0, 0, 0, is_hw);
1315 }
1316
1317 bool x86_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
1318 {
1319     X86CPU *cpu = X86_CPU(cs);
1320     CPUX86State *env = &cpu->env;
1321     bool ret = false;
1322
1323 #if !defined(CONFIG_USER_ONLY)
1324     if (interrupt_request & CPU_INTERRUPT_POLL) {
1325         cs->interrupt_request &= ~CPU_INTERRUPT_POLL;
1326         apic_poll_irq(cpu->apic_state);
1327         /* Don't process multiple interrupt requests in a single call.
1328            This is required to make icount-driven execution deterministic. */
1329         return true;
1330     }
1331 #endif
1332     if (interrupt_request & CPU_INTERRUPT_SIPI) {
1333         do_cpu_sipi(cpu);
1334     } else if (env->hflags2 & HF2_GIF_MASK) {
1335         if ((interrupt_request & CPU_INTERRUPT_SMI) &&
1336             !(env->hflags & HF_SMM_MASK)) {
1337             cpu_svm_check_intercept_param(env, SVM_EXIT_SMI, 0);
1338             cs->interrupt_request &= ~CPU_INTERRUPT_SMI;
1339             do_smm_enter(cpu);
1340             ret = true;
1341         } else if ((interrupt_request & CPU_INTERRUPT_NMI) &&
1342                    !(env->hflags2 & HF2_NMI_MASK)) {
1343             cs->interrupt_request &= ~CPU_INTERRUPT_NMI;
1344             env->hflags2 |= HF2_NMI_MASK;
1345             do_interrupt_x86_hardirq(env, EXCP02_NMI, 1);
1346             ret = true;
1347         } else if (interrupt_request & CPU_INTERRUPT_MCE) {
1348             cs->interrupt_request &= ~CPU_INTERRUPT_MCE;
1349             do_interrupt_x86_hardirq(env, EXCP12_MCHK, 0);
1350             ret = true;
1351         } else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
1352                    (((env->hflags2 & HF2_VINTR_MASK) &&
1353                      (env->hflags2 & HF2_HIF_MASK)) ||
1354                     (!(env->hflags2 & HF2_VINTR_MASK) &&
1355                      (env->eflags & IF_MASK &&
1356                       !(env->hflags & HF_INHIBIT_IRQ_MASK))))) {
1357             int intno;
1358             cpu_svm_check_intercept_param(env, SVM_EXIT_INTR, 0);
1359             cs->interrupt_request &= ~(CPU_INTERRUPT_HARD |
1360                                        CPU_INTERRUPT_VIRQ);
1361             intno = cpu_get_pic_interrupt(env);
1362             qemu_log_mask(CPU_LOG_TB_IN_ASM,
1363                           "Servicing hardware INT=0x%02x\n", intno);
1364             do_interrupt_x86_hardirq(env, intno, 1);
1365             /* ensure that no TB jump will be modified as
1366                the program flow was changed */
1367             ret = true;
1368 #if !defined(CONFIG_USER_ONLY)
1369         } else if ((interrupt_request & CPU_INTERRUPT_VIRQ) &&
1370                    (env->eflags & IF_MASK) &&
1371                    !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
1372             int intno;
1373             /* FIXME: this should respect TPR */
1374             cpu_svm_check_intercept_param(env, SVM_EXIT_VINTR, 0);
1375             intno = x86_ldl_phys(cs, env->vm_vmcb
1376                              + offsetof(struct vmcb, control.int_vector));
1377             qemu_log_mask(CPU_LOG_TB_IN_ASM,
1378                           "Servicing virtual hardware INT=0x%02x\n", intno);
1379             do_interrupt_x86_hardirq(env, intno, 1);
1380             cs->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
1381             ret = true;
1382 #endif
1383         }
1384     }
1385
1386     return ret;
1387 }
1388
1389 void helper_lldt(CPUX86State *env, int selector)
1390 {
1391     SegmentCache *dt;
1392     uint32_t e1, e2;
1393     int index, entry_limit;
1394     target_ulong ptr;
1395
1396     selector &= 0xffff;
1397     if ((selector & 0xfffc) == 0) {
1398         /* XXX: NULL selector case: invalid LDT */
1399         env->ldt.base = 0;
1400         env->ldt.limit = 0;
1401     } else {
1402         if (selector & 0x4) {
1403             raise_exception_err_ra(env, EXCP0D_GPF, selector & 0xfffc, GETPC());
1404         }
1405         dt = &env->gdt;
1406         index = selector & ~7;
1407 #ifdef TARGET_X86_64
1408         if (env->hflags & HF_LMA_MASK) {
1409             entry_limit = 15;
1410         } else
1411 #endif
1412         {
1413             entry_limit = 7;
1414         }
1415         if ((index + entry_limit) > dt->limit) {
1416             raise_exception_err_ra(env, EXCP0D_GPF, selector & 0xfffc, GETPC());
1417         }
1418         ptr = dt->base + index;
1419         e1 = cpu_ldl_kernel_ra(env, ptr, GETPC());
1420         e2 = cpu_ldl_kernel_ra(env, ptr + 4, GETPC());
1421         if ((e2 & DESC_S_MASK) || ((e2 >> DESC_TYPE_SHIFT) & 0xf) != 2) {
1422             raise_exception_err_ra(env, EXCP0D_GPF, selector & 0xfffc, GETPC());
1423         }
1424         if (!(e2 & DESC_P_MASK)) {
1425             raise_exception_err_ra(env, EXCP0B_NOSEG, selector & 0xfffc, GETPC());
1426         }
1427 #ifdef TARGET_X86_64
1428         if (env->hflags & HF_LMA_MASK) {
1429             uint32_t e3;
1430
1431             e3 = cpu_ldl_kernel_ra(env, ptr + 8, GETPC());
1432             load_seg_cache_raw_dt(&env->ldt, e1, e2);
1433             env->ldt.base |= (target_ulong)e3 << 32;
1434         } else
1435 #endif
1436         {
1437             load_seg_cache_raw_dt(&env->ldt, e1, e2);
1438         }
1439     }
1440     env->ldt.selector = selector;
1441 }
1442
1443 void helper_ltr(CPUX86State *env, int selector)
1444 {
1445     SegmentCache *dt;
1446     uint32_t e1, e2;
1447     int index, type, entry_limit;
1448     target_ulong ptr;
1449
1450     selector &= 0xffff;
1451     if ((selector & 0xfffc) == 0) {
1452         /* NULL selector case: invalid TR */
1453         env->tr.base = 0;
1454         env->tr.limit = 0;
1455         env->tr.flags = 0;
1456     } else {
1457         if (selector & 0x4) {
1458             raise_exception_err_ra(env, EXCP0D_GPF, selector & 0xfffc, GETPC());
1459         }
1460         dt = &env->gdt;
1461         index = selector & ~7;
1462 #ifdef TARGET_X86_64
1463         if (env->hflags & HF_LMA_MASK) {
1464             entry_limit = 15;
1465         } else
1466 #endif
1467         {
1468             entry_limit = 7;
1469         }
1470         if ((index + entry_limit) > dt->limit) {
1471             raise_exception_err_ra(env, EXCP0D_GPF, selector & 0xfffc, GETPC());
1472         }
1473         ptr = dt->base + index;
1474         e1 = cpu_ldl_kernel_ra(env, ptr, GETPC());
1475         e2 = cpu_ldl_kernel_ra(env, ptr + 4, GETPC());
1476         type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
1477         if ((e2 & DESC_S_MASK) ||
1478             (type != 1 && type != 9)) {
1479             raise_exception_err_ra(env, EXCP0D_GPF, selector & 0xfffc, GETPC());
1480         }
1481         if (!(e2 & DESC_P_MASK)) {
1482             raise_exception_err_ra(env, EXCP0B_NOSEG, selector & 0xfffc, GETPC());
1483         }
1484 #ifdef TARGET_X86_64
1485         if (env->hflags & HF_LMA_MASK) {
1486             uint32_t e3, e4;
1487
1488             e3 = cpu_ldl_kernel_ra(env, ptr + 8, GETPC());
1489             e4 = cpu_ldl_kernel_ra(env, ptr + 12, GETPC());
1490             if ((e4 >> DESC_TYPE_SHIFT) & 0xf) {
1491                 raise_exception_err_ra(env, EXCP0D_GPF, selector & 0xfffc, GETPC());
1492             }
1493             load_seg_cache_raw_dt(&env->tr, e1, e2);
1494             env->tr.base |= (target_ulong)e3 << 32;
1495         } else
1496 #endif
1497         {
1498             load_seg_cache_raw_dt(&env->tr, e1, e2);
1499         }
1500         e2 |= DESC_TSS_BUSY_MASK;
1501         cpu_stl_kernel_ra(env, ptr + 4, e2, GETPC());
1502     }
1503     env->tr.selector = selector;
1504 }
1505
1506 /* only works if protected mode and not VM86. seg_reg must be != R_CS */
1507 void helper_load_seg(CPUX86State *env, int seg_reg, int selector)
1508 {
1509     uint32_t e1, e2;
1510     int cpl, dpl, rpl;
1511     SegmentCache *dt;
1512     int index;
1513     target_ulong ptr;
1514
1515     selector &= 0xffff;
1516     cpl = env->hflags & HF_CPL_MASK;
1517     if ((selector & 0xfffc) == 0) {
1518         /* null selector case */
1519         if (seg_reg == R_SS
1520 #ifdef TARGET_X86_64
1521             && (!(env->hflags & HF_CS64_MASK) || cpl == 3)
1522 #endif
1523             ) {
1524             raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC());
1525         }
1526         cpu_x86_load_seg_cache(env, seg_reg, selector, 0, 0, 0);
1527     } else {
1528
1529         if (selector & 0x4) {
1530             dt = &env->ldt;
1531         } else {
1532             dt = &env->gdt;
1533         }
1534         index = selector & ~7;
1535         if ((index + 7) > dt->limit) {
1536             raise_exception_err_ra(env, EXCP0D_GPF, selector & 0xfffc, GETPC());
1537         }
1538         ptr = dt->base + index;
1539         e1 = cpu_ldl_kernel_ra(env, ptr, GETPC());
1540         e2 = cpu_ldl_kernel_ra(env, ptr + 4, GETPC());
1541
1542         if (!(e2 & DESC_S_MASK)) {
1543             raise_exception_err_ra(env, EXCP0D_GPF, selector & 0xfffc, GETPC());
1544         }
1545         rpl = selector & 3;
1546         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1547         if (seg_reg == R_SS) {
1548             /* must be writable segment */
1549             if ((e2 & DESC_CS_MASK) || !(e2 & DESC_W_MASK)) {
1550                 raise_exception_err_ra(env, EXCP0D_GPF, selector & 0xfffc, GETPC());
1551             }
1552             if (rpl != cpl || dpl != cpl) {
1553                 raise_exception_err_ra(env, EXCP0D_GPF, selector & 0xfffc, GETPC());
1554             }
1555         } else {
1556             /* must be readable segment */
1557             if ((e2 & (DESC_CS_MASK | DESC_R_MASK)) == DESC_CS_MASK) {
1558                 raise_exception_err_ra(env, EXCP0D_GPF, selector & 0xfffc, GETPC());
1559             }
1560
1561             if (!(e2 & DESC_CS_MASK) || !(e2 & DESC_C_MASK)) {
1562                 /* if not conforming code, test rights */
1563                 if (dpl < cpl || dpl < rpl) {
1564                     raise_exception_err_ra(env, EXCP0D_GPF, selector & 0xfffc, GETPC());
1565                 }
1566             }
1567         }
1568
1569         if (!(e2 & DESC_P_MASK)) {
1570             if (seg_reg == R_SS) {
1571                 raise_exception_err_ra(env, EXCP0C_STACK, selector & 0xfffc, GETPC());
1572             } else {
1573                 raise_exception_err_ra(env, EXCP0B_NOSEG, selector & 0xfffc, GETPC());
1574             }
1575         }
1576
1577         /* set the access bit if not already set */
1578         if (!(e2 & DESC_A_MASK)) {
1579             e2 |= DESC_A_MASK;
1580             cpu_stl_kernel_ra(env, ptr + 4, e2, GETPC());
1581         }
1582
1583         cpu_x86_load_seg_cache(env, seg_reg, selector,
1584                        get_seg_base(e1, e2),
1585                        get_seg_limit(e1, e2),
1586                        e2);
1587 #if 0
1588         qemu_log("load_seg: sel=0x%04x base=0x%08lx limit=0x%08lx flags=%08x\n",
1589                 selector, (unsigned long)sc->base, sc->limit, sc->flags);
1590 #endif
1591     }
1592 }
1593
1594 /* protected mode jump */
1595 void helper_ljmp_protected(CPUX86State *env, int new_cs, target_ulong new_eip,
1596                            target_ulong next_eip)
1597 {
1598     int gate_cs, type;
1599     uint32_t e1, e2, cpl, dpl, rpl, limit;
1600
1601     if ((new_cs & 0xfffc) == 0) {
1602         raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC());
1603     }
1604     if (load_segment_ra(env, &e1, &e2, new_cs, GETPC()) != 0) {
1605         raise_exception_err_ra(env, EXCP0D_GPF, new_cs & 0xfffc, GETPC());
1606     }
1607     cpl = env->hflags & HF_CPL_MASK;
1608     if (e2 & DESC_S_MASK) {
1609         if (!(e2 & DESC_CS_MASK)) {
1610             raise_exception_err_ra(env, EXCP0D_GPF, new_cs & 0xfffc, GETPC());
1611         }
1612         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1613         if (e2 & DESC_C_MASK) {
1614             /* conforming code segment */
1615             if (dpl > cpl) {
1616                 raise_exception_err_ra(env, EXCP0D_GPF, new_cs & 0xfffc, GETPC());
1617             }
1618         } else {
1619             /* non conforming code segment */
1620             rpl = new_cs & 3;
1621             if (rpl > cpl) {
1622                 raise_exception_err_ra(env, EXCP0D_GPF, new_cs & 0xfffc, GETPC());
1623             }
1624             if (dpl != cpl) {
1625                 raise_exception_err_ra(env, EXCP0D_GPF, new_cs & 0xfffc, GETPC());
1626             }
1627         }
1628         if (!(e2 & DESC_P_MASK)) {
1629             raise_exception_err_ra(env, EXCP0B_NOSEG, new_cs & 0xfffc, GETPC());
1630         }
1631         limit = get_seg_limit(e1, e2);
1632         if (new_eip > limit &&
1633             !(env->hflags & HF_LMA_MASK) && !(e2 & DESC_L_MASK)) {
1634             raise_exception_err_ra(env, EXCP0D_GPF, new_cs & 0xfffc, GETPC());
1635         }
1636         cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
1637                        get_seg_base(e1, e2), limit, e2);
1638         env->eip = new_eip;
1639     } else {
1640         /* jump to call or task gate */
1641         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1642         rpl = new_cs & 3;
1643         cpl = env->hflags & HF_CPL_MASK;
1644         type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
1645         switch (type) {
1646         case 1: /* 286 TSS */
1647         case 9: /* 386 TSS */
1648         case 5: /* task gate */
1649             if (dpl < cpl || dpl < rpl) {
1650                 raise_exception_err_ra(env, EXCP0D_GPF, new_cs & 0xfffc, GETPC());
1651             }
1652             switch_tss_ra(env, new_cs, e1, e2, SWITCH_TSS_JMP, next_eip, GETPC());
1653             break;
1654         case 4: /* 286 call gate */
1655         case 12: /* 386 call gate */
1656             if ((dpl < cpl) || (dpl < rpl)) {
1657                 raise_exception_err_ra(env, EXCP0D_GPF, new_cs & 0xfffc, GETPC());
1658             }
1659             if (!(e2 & DESC_P_MASK)) {
1660                 raise_exception_err_ra(env, EXCP0B_NOSEG, new_cs & 0xfffc, GETPC());
1661             }
1662             gate_cs = e1 >> 16;
1663             new_eip = (e1 & 0xffff);
1664             if (type == 12) {
1665                 new_eip |= (e2 & 0xffff0000);
1666             }
1667             if (load_segment_ra(env, &e1, &e2, gate_cs, GETPC()) != 0) {
1668                 raise_exception_err_ra(env, EXCP0D_GPF, gate_cs & 0xfffc, GETPC());
1669             }
1670             dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1671             /* must be code segment */
1672             if (((e2 & (DESC_S_MASK | DESC_CS_MASK)) !=
1673                  (DESC_S_MASK | DESC_CS_MASK))) {
1674                 raise_exception_err_ra(env, EXCP0D_GPF, gate_cs & 0xfffc, GETPC());
1675             }
1676             if (((e2 & DESC_C_MASK) && (dpl > cpl)) ||
1677                 (!(e2 & DESC_C_MASK) && (dpl != cpl))) {
1678                 raise_exception_err_ra(env, EXCP0D_GPF, gate_cs & 0xfffc, GETPC());
1679             }
1680             if (!(e2 & DESC_P_MASK)) {
1681                 raise_exception_err_ra(env, EXCP0D_GPF, gate_cs & 0xfffc, GETPC());
1682             }
1683             limit = get_seg_limit(e1, e2);
1684             if (new_eip > limit) {
1685                 raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC());
1686             }
1687             cpu_x86_load_seg_cache(env, R_CS, (gate_cs & 0xfffc) | cpl,
1688                                    get_seg_base(e1, e2), limit, e2);
1689             env->eip = new_eip;
1690             break;
1691         default:
1692             raise_exception_err_ra(env, EXCP0D_GPF, new_cs & 0xfffc, GETPC());
1693             break;
1694         }
1695     }
1696 }
1697
1698 /* real mode call */
1699 void helper_lcall_real(CPUX86State *env, int new_cs, target_ulong new_eip1,
1700                        int shift, int next_eip)
1701 {
1702     int new_eip;
1703     uint32_t esp, esp_mask;
1704     target_ulong ssp;
1705
1706     new_eip = new_eip1;
1707     esp = env->regs[R_ESP];
1708     esp_mask = get_sp_mask(env->segs[R_SS].flags);
1709     ssp = env->segs[R_SS].base;
1710     if (shift) {
1711         PUSHL_RA(ssp, esp, esp_mask, env->segs[R_CS].selector, GETPC());
1712         PUSHL_RA(ssp, esp, esp_mask, next_eip, GETPC());
1713     } else {
1714         PUSHW_RA(ssp, esp, esp_mask, env->segs[R_CS].selector, GETPC());
1715         PUSHW_RA(ssp, esp, esp_mask, next_eip, GETPC());
1716     }
1717
1718     SET_ESP(esp, esp_mask);
1719     env->eip = new_eip;
1720     env->segs[R_CS].selector = new_cs;
1721     env->segs[R_CS].base = (new_cs << 4);
1722 }
1723
1724 /* protected mode call */
1725 void helper_lcall_protected(CPUX86State *env, int new_cs, target_ulong new_eip,
1726                             int shift, target_ulong next_eip)
1727 {
1728     int new_stack, i;
1729     uint32_t e1, e2, cpl, dpl, rpl, selector, offset, param_count;
1730     uint32_t ss = 0, ss_e1 = 0, ss_e2 = 0, sp, type, ss_dpl, sp_mask;
1731     uint32_t val, limit, old_sp_mask;
1732     target_ulong ssp, old_ssp;
1733
1734     LOG_PCALL("lcall %04x:%08x s=%d\n", new_cs, (uint32_t)new_eip, shift);
1735     LOG_PCALL_STATE(CPU(x86_env_get_cpu(env)));
1736     if ((new_cs & 0xfffc) == 0) {
1737         raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC());
1738     }
1739     if (load_segment_ra(env, &e1, &e2, new_cs, GETPC()) != 0) {
1740         raise_exception_err_ra(env, EXCP0D_GPF, new_cs & 0xfffc, GETPC());
1741     }
1742     cpl = env->hflags & HF_CPL_MASK;
1743     LOG_PCALL("desc=%08x:%08x\n", e1, e2);
1744     if (e2 & DESC_S_MASK) {
1745         if (!(e2 & DESC_CS_MASK)) {
1746             raise_exception_err_ra(env, EXCP0D_GPF, new_cs & 0xfffc, GETPC());
1747         }
1748         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1749         if (e2 & DESC_C_MASK) {
1750             /* conforming code segment */
1751             if (dpl > cpl) {
1752                 raise_exception_err_ra(env, EXCP0D_GPF, new_cs & 0xfffc, GETPC());
1753             }
1754         } else {
1755             /* non conforming code segment */
1756             rpl = new_cs & 3;
1757             if (rpl > cpl) {
1758                 raise_exception_err_ra(env, EXCP0D_GPF, new_cs & 0xfffc, GETPC());
1759             }
1760             if (dpl != cpl) {
1761                 raise_exception_err_ra(env, EXCP0D_GPF, new_cs & 0xfffc, GETPC());
1762             }
1763         }
1764         if (!(e2 & DESC_P_MASK)) {
1765             raise_exception_err_ra(env, EXCP0B_NOSEG, new_cs & 0xfffc, GETPC());
1766         }
1767
1768 #ifdef TARGET_X86_64
1769         /* XXX: check 16/32 bit cases in long mode */
1770         if (shift == 2) {
1771             target_ulong rsp;
1772
1773             /* 64 bit case */
1774             rsp = env->regs[R_ESP];
1775             PUSHQ_RA(rsp, env->segs[R_CS].selector, GETPC());
1776             PUSHQ_RA(rsp, next_eip, GETPC());
1777             /* from this point, not restartable */
1778             env->regs[R_ESP] = rsp;
1779             cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
1780                                    get_seg_base(e1, e2),
1781                                    get_seg_limit(e1, e2), e2);
1782             env->eip = new_eip;
1783         } else
1784 #endif
1785         {
1786             sp = env->regs[R_ESP];
1787             sp_mask = get_sp_mask(env->segs[R_SS].flags);
1788             ssp = env->segs[R_SS].base;
1789             if (shift) {
1790                 PUSHL_RA(ssp, sp, sp_mask, env->segs[R_CS].selector, GETPC());
1791                 PUSHL_RA(ssp, sp, sp_mask, next_eip, GETPC());
1792             } else {
1793                 PUSHW_RA(ssp, sp, sp_mask, env->segs[R_CS].selector, GETPC());
1794                 PUSHW_RA(ssp, sp, sp_mask, next_eip, GETPC());
1795             }
1796
1797             limit = get_seg_limit(e1, e2);
1798             if (new_eip > limit) {
1799                 raise_exception_err_ra(env, EXCP0D_GPF, new_cs & 0xfffc, GETPC());
1800             }
1801             /* from this point, not restartable */
1802             SET_ESP(sp, sp_mask);
1803             cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
1804                                    get_seg_base(e1, e2), limit, e2);
1805             env->eip = new_eip;
1806         }
1807     } else {
1808         /* check gate type */
1809         type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;
1810         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1811         rpl = new_cs & 3;
1812         switch (type) {
1813         case 1: /* available 286 TSS */
1814         case 9: /* available 386 TSS */
1815         case 5: /* task gate */
1816             if (dpl < cpl || dpl < rpl) {
1817                 raise_exception_err_ra(env, EXCP0D_GPF, new_cs & 0xfffc, GETPC());
1818             }
1819             switch_tss_ra(env, new_cs, e1, e2, SWITCH_TSS_CALL, next_eip, GETPC());
1820             return;
1821         case 4: /* 286 call gate */
1822         case 12: /* 386 call gate */
1823             break;
1824         default:
1825             raise_exception_err_ra(env, EXCP0D_GPF, new_cs & 0xfffc, GETPC());
1826             break;
1827         }
1828         shift = type >> 3;
1829
1830         if (dpl < cpl || dpl < rpl) {
1831             raise_exception_err_ra(env, EXCP0D_GPF, new_cs & 0xfffc, GETPC());
1832         }
1833         /* check valid bit */
1834         if (!(e2 & DESC_P_MASK)) {
1835             raise_exception_err_ra(env, EXCP0B_NOSEG,  new_cs & 0xfffc, GETPC());
1836         }
1837         selector = e1 >> 16;
1838         offset = (e2 & 0xffff0000) | (e1 & 0x0000ffff);
1839         param_count = e2 & 0x1f;
1840         if ((selector & 0xfffc) == 0) {
1841             raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC());
1842         }
1843
1844         if (load_segment_ra(env, &e1, &e2, selector, GETPC()) != 0) {
1845             raise_exception_err_ra(env, EXCP0D_GPF, selector & 0xfffc, GETPC());
1846         }
1847         if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK))) {
1848             raise_exception_err_ra(env, EXCP0D_GPF, selector & 0xfffc, GETPC());
1849         }
1850         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1851         if (dpl > cpl) {
1852             raise_exception_err_ra(env, EXCP0D_GPF, selector & 0xfffc, GETPC());
1853         }
1854         if (!(e2 & DESC_P_MASK)) {
1855             raise_exception_err_ra(env, EXCP0B_NOSEG, selector & 0xfffc, GETPC());
1856         }
1857
1858         if (!(e2 & DESC_C_MASK) && dpl < cpl) {
1859             /* to inner privilege */
1860             get_ss_esp_from_tss(env, &ss, &sp, dpl, GETPC());
1861             LOG_PCALL("new ss:esp=%04x:%08x param_count=%d env->regs[R_ESP]="
1862                       TARGET_FMT_lx "\n", ss, sp, param_count,
1863                       env->regs[R_ESP]);
1864             if ((ss & 0xfffc) == 0) {
1865                 raise_exception_err_ra(env, EXCP0A_TSS, ss & 0xfffc, GETPC());
1866             }
1867             if ((ss & 3) != dpl) {
1868                 raise_exception_err_ra(env, EXCP0A_TSS, ss & 0xfffc, GETPC());
1869             }
1870             if (load_segment_ra(env, &ss_e1, &ss_e2, ss, GETPC()) != 0) {
1871                 raise_exception_err_ra(env, EXCP0A_TSS, ss & 0xfffc, GETPC());
1872             }
1873             ss_dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3;
1874             if (ss_dpl != dpl) {
1875                 raise_exception_err_ra(env, EXCP0A_TSS, ss & 0xfffc, GETPC());
1876             }
1877             if (!(ss_e2 & DESC_S_MASK) ||
1878                 (ss_e2 & DESC_CS_MASK) ||
1879                 !(ss_e2 & DESC_W_MASK)) {
1880                 raise_exception_err_ra(env, EXCP0A_TSS, ss & 0xfffc, GETPC());
1881             }
1882             if (!(ss_e2 & DESC_P_MASK)) {
1883                 raise_exception_err_ra(env, EXCP0A_TSS, ss & 0xfffc, GETPC());
1884             }
1885
1886             /* push_size = ((param_count * 2) + 8) << shift; */
1887
1888             old_sp_mask = get_sp_mask(env->segs[R_SS].flags);
1889             old_ssp = env->segs[R_SS].base;
1890
1891             sp_mask = get_sp_mask(ss_e2);
1892             ssp = get_seg_base(ss_e1, ss_e2);
1893             if (shift) {
1894                 PUSHL_RA(ssp, sp, sp_mask, env->segs[R_SS].selector, GETPC());
1895                 PUSHL_RA(ssp, sp, sp_mask, env->regs[R_ESP], GETPC());
1896                 for (i = param_count - 1; i >= 0; i--) {
1897                     val = cpu_ldl_kernel_ra(env, old_ssp +
1898                                             ((env->regs[R_ESP] + i * 4) &
1899                                              old_sp_mask), GETPC());
1900                     PUSHL_RA(ssp, sp, sp_mask, val, GETPC());
1901                 }
1902             } else {
1903                 PUSHW_RA(ssp, sp, sp_mask, env->segs[R_SS].selector, GETPC());
1904                 PUSHW_RA(ssp, sp, sp_mask, env->regs[R_ESP], GETPC());
1905                 for (i = param_count - 1; i >= 0; i--) {
1906                     val = cpu_lduw_kernel_ra(env, old_ssp +
1907                                              ((env->regs[R_ESP] + i * 2) &
1908                                               old_sp_mask), GETPC());
1909                     PUSHW_RA(ssp, sp, sp_mask, val, GETPC());
1910                 }
1911             }
1912             new_stack = 1;
1913         } else {
1914             /* to same privilege */
1915             sp = env->regs[R_ESP];
1916             sp_mask = get_sp_mask(env->segs[R_SS].flags);
1917             ssp = env->segs[R_SS].base;
1918             /* push_size = (4 << shift); */
1919             new_stack = 0;
1920         }
1921
1922         if (shift) {
1923             PUSHL_RA(ssp, sp, sp_mask, env->segs[R_CS].selector, GETPC());
1924             PUSHL_RA(ssp, sp, sp_mask, next_eip, GETPC());
1925         } else {
1926             PUSHW_RA(ssp, sp, sp_mask, env->segs[R_CS].selector, GETPC());
1927             PUSHW_RA(ssp, sp, sp_mask, next_eip, GETPC());
1928         }
1929
1930         /* from this point, not restartable */
1931
1932         if (new_stack) {
1933             ss = (ss & ~3) | dpl;
1934             cpu_x86_load_seg_cache(env, R_SS, ss,
1935                                    ssp,
1936                                    get_seg_limit(ss_e1, ss_e2),
1937                                    ss_e2);
1938         }
1939
1940         selector = (selector & ~3) | dpl;
1941         cpu_x86_load_seg_cache(env, R_CS, selector,
1942                        get_seg_base(e1, e2),
1943                        get_seg_limit(e1, e2),
1944                        e2);
1945         SET_ESP(sp, sp_mask);
1946         env->eip = offset;
1947     }
1948 }
1949
1950 /* real and vm86 mode iret */
1951 void helper_iret_real(CPUX86State *env, int shift)
1952 {
1953     uint32_t sp, new_cs, new_eip, new_eflags, sp_mask;
1954     target_ulong ssp;
1955     int eflags_mask;
1956
1957     sp_mask = 0xffff; /* XXXX: use SS segment size? */
1958     sp = env->regs[R_ESP];
1959     ssp = env->segs[R_SS].base;
1960     if (shift == 1) {
1961         /* 32 bits */
1962         POPL_RA(ssp, sp, sp_mask, new_eip, GETPC());
1963         POPL_RA(ssp, sp, sp_mask, new_cs, GETPC());
1964         new_cs &= 0xffff;
1965         POPL_RA(ssp, sp, sp_mask, new_eflags, GETPC());
1966     } else {
1967         /* 16 bits */
1968         POPW_RA(ssp, sp, sp_mask, new_eip, GETPC());
1969         POPW_RA(ssp, sp, sp_mask, new_cs, GETPC());
1970         POPW_RA(ssp, sp, sp_mask, new_eflags, GETPC());
1971     }
1972     env->regs[R_ESP] = (env->regs[R_ESP] & ~sp_mask) | (sp & sp_mask);
1973     env->segs[R_CS].selector = new_cs;
1974     env->segs[R_CS].base = (new_cs << 4);
1975     env->eip = new_eip;
1976     if (env->eflags & VM_MASK) {
1977         eflags_mask = TF_MASK | AC_MASK | ID_MASK | IF_MASK | RF_MASK |
1978             NT_MASK;
1979     } else {
1980         eflags_mask = TF_MASK | AC_MASK | ID_MASK | IF_MASK | IOPL_MASK |
1981             RF_MASK | NT_MASK;
1982     }
1983     if (shift == 0) {
1984         eflags_mask &= 0xffff;
1985     }
1986     cpu_load_eflags(env, new_eflags, eflags_mask);
1987     env->hflags2 &= ~HF2_NMI_MASK;
1988 }
1989
1990 static inline void validate_seg(CPUX86State *env, int seg_reg, int cpl)
1991 {
1992     int dpl;
1993     uint32_t e2;
1994
1995     /* XXX: on x86_64, we do not want to nullify FS and GS because
1996        they may still contain a valid base. I would be interested to
1997        know how a real x86_64 CPU behaves */
1998     if ((seg_reg == R_FS || seg_reg == R_GS) &&
1999         (env->segs[seg_reg].selector & 0xfffc) == 0) {
2000         return;
2001     }
2002
2003     e2 = env->segs[seg_reg].flags;
2004     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2005     if (!(e2 & DESC_CS_MASK) || !(e2 & DESC_C_MASK)) {
2006         /* data or non conforming code segment */
2007         if (dpl < cpl) {
2008             cpu_x86_load_seg_cache(env, seg_reg, 0, 0, 0, 0);
2009         }
2010     }
2011 }
2012
2013 /* protected mode iret */
2014 static inline void helper_ret_protected(CPUX86State *env, int shift,
2015                                         int is_iret, int addend,
2016                                         uintptr_t retaddr)
2017 {
2018     uint32_t new_cs, new_eflags, new_ss;
2019     uint32_t new_es, new_ds, new_fs, new_gs;
2020     uint32_t e1, e2, ss_e1, ss_e2;
2021     int cpl, dpl, rpl, eflags_mask, iopl;
2022     target_ulong ssp, sp, new_eip, new_esp, sp_mask;
2023
2024 #ifdef TARGET_X86_64
2025     if (shift == 2) {
2026         sp_mask = -1;
2027     } else
2028 #endif
2029     {
2030         sp_mask = get_sp_mask(env->segs[R_SS].flags);
2031     }
2032     sp = env->regs[R_ESP];
2033     ssp = env->segs[R_SS].base;
2034     new_eflags = 0; /* avoid warning */
2035 #ifdef TARGET_X86_64
2036     if (shift == 2) {
2037         POPQ_RA(sp, new_eip, retaddr);
2038         POPQ_RA(sp, new_cs, retaddr);
2039         new_cs &= 0xffff;
2040         if (is_iret) {
2041             POPQ_RA(sp, new_eflags, retaddr);
2042         }
2043     } else
2044 #endif
2045     {
2046         if (shift == 1) {
2047             /* 32 bits */
2048             POPL_RA(ssp, sp, sp_mask, new_eip, retaddr);
2049             POPL_RA(ssp, sp, sp_mask, new_cs, retaddr);
2050             new_cs &= 0xffff;
2051             if (is_iret) {
2052                 POPL_RA(ssp, sp, sp_mask, new_eflags, retaddr);
2053                 if (new_eflags & VM_MASK) {
2054                     goto return_to_vm86;
2055                 }
2056             }
2057         } else {
2058             /* 16 bits */
2059             POPW_RA(ssp, sp, sp_mask, new_eip, retaddr);
2060             POPW_RA(ssp, sp, sp_mask, new_cs, retaddr);
2061             if (is_iret) {
2062                 POPW_RA(ssp, sp, sp_mask, new_eflags, retaddr);
2063             }
2064         }
2065     }
2066     LOG_PCALL("lret new %04x:" TARGET_FMT_lx " s=%d addend=0x%x\n",
2067               new_cs, new_eip, shift, addend);
2068     LOG_PCALL_STATE(CPU(x86_env_get_cpu(env)));
2069     if ((new_cs & 0xfffc) == 0) {
2070         raise_exception_err_ra(env, EXCP0D_GPF, new_cs & 0xfffc, retaddr);
2071     }
2072     if (load_segment_ra(env, &e1, &e2, new_cs, retaddr) != 0) {
2073         raise_exception_err_ra(env, EXCP0D_GPF, new_cs & 0xfffc, retaddr);
2074     }
2075     if (!(e2 & DESC_S_MASK) ||
2076         !(e2 & DESC_CS_MASK)) {
2077         raise_exception_err_ra(env, EXCP0D_GPF, new_cs & 0xfffc, retaddr);
2078     }
2079     cpl = env->hflags & HF_CPL_MASK;
2080     rpl = new_cs & 3;
2081     if (rpl < cpl) {
2082         raise_exception_err_ra(env, EXCP0D_GPF, new_cs & 0xfffc, retaddr);
2083     }
2084     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2085     if (e2 & DESC_C_MASK) {
2086         if (dpl > rpl) {
2087             raise_exception_err_ra(env, EXCP0D_GPF, new_cs & 0xfffc, retaddr);
2088         }
2089     } else {
2090         if (dpl != rpl) {
2091             raise_exception_err_ra(env, EXCP0D_GPF, new_cs & 0xfffc, retaddr);
2092         }
2093     }
2094     if (!(e2 & DESC_P_MASK)) {
2095         raise_exception_err_ra(env, EXCP0B_NOSEG, new_cs & 0xfffc, retaddr);
2096     }
2097
2098     sp += addend;
2099     if (rpl == cpl && (!(env->hflags & HF_CS64_MASK) ||
2100                        ((env->hflags & HF_CS64_MASK) && !is_iret))) {
2101         /* return to same privilege level */
2102         cpu_x86_load_seg_cache(env, R_CS, new_cs,
2103                        get_seg_base(e1, e2),
2104                        get_seg_limit(e1, e2),
2105                        e2);
2106     } else {
2107         /* return to different privilege level */
2108 #ifdef TARGET_X86_64
2109         if (shift == 2) {
2110             POPQ_RA(sp, new_esp, retaddr);
2111             POPQ_RA(sp, new_ss, retaddr);
2112             new_ss &= 0xffff;
2113         } else
2114 #endif
2115         {
2116             if (shift == 1) {
2117                 /* 32 bits */
2118                 POPL_RA(ssp, sp, sp_mask, new_esp, retaddr);
2119                 POPL_RA(ssp, sp, sp_mask, new_ss, retaddr);
2120                 new_ss &= 0xffff;
2121             } else {
2122                 /* 16 bits */
2123                 POPW_RA(ssp, sp, sp_mask, new_esp, retaddr);
2124                 POPW_RA(ssp, sp, sp_mask, new_ss, retaddr);
2125             }
2126         }
2127         LOG_PCALL("new ss:esp=%04x:" TARGET_FMT_lx "\n",
2128                   new_ss, new_esp);
2129         if ((new_ss & 0xfffc) == 0) {
2130 #ifdef TARGET_X86_64
2131             /* NULL ss is allowed in long mode if cpl != 3 */
2132             /* XXX: test CS64? */
2133             if ((env->hflags & HF_LMA_MASK) && rpl != 3) {
2134                 cpu_x86_load_seg_cache(env, R_SS, new_ss,
2135                                        0, 0xffffffff,
2136                                        DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2137                                        DESC_S_MASK | (rpl << DESC_DPL_SHIFT) |
2138                                        DESC_W_MASK | DESC_A_MASK);
2139                 ss_e2 = DESC_B_MASK; /* XXX: should not be needed? */
2140             } else
2141 #endif
2142             {
2143                 raise_exception_err_ra(env, EXCP0D_GPF, 0, retaddr);
2144             }
2145         } else {
2146             if ((new_ss & 3) != rpl) {
2147                 raise_exception_err_ra(env, EXCP0D_GPF, new_ss & 0xfffc, retaddr);
2148             }
2149             if (load_segment_ra(env, &ss_e1, &ss_e2, new_ss, retaddr) != 0) {
2150                 raise_exception_err_ra(env, EXCP0D_GPF, new_ss & 0xfffc, retaddr);
2151             }
2152             if (!(ss_e2 & DESC_S_MASK) ||
2153                 (ss_e2 & DESC_CS_MASK) ||
2154                 !(ss_e2 & DESC_W_MASK)) {
2155                 raise_exception_err_ra(env, EXCP0D_GPF, new_ss & 0xfffc, retaddr);
2156             }
2157             dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3;
2158             if (dpl != rpl) {
2159                 raise_exception_err_ra(env, EXCP0D_GPF, new_ss & 0xfffc, retaddr);
2160             }
2161             if (!(ss_e2 & DESC_P_MASK)) {
2162                 raise_exception_err_ra(env, EXCP0B_NOSEG, new_ss & 0xfffc, retaddr);
2163             }
2164             cpu_x86_load_seg_cache(env, R_SS, new_ss,
2165                                    get_seg_base(ss_e1, ss_e2),
2166                                    get_seg_limit(ss_e1, ss_e2),
2167                                    ss_e2);
2168         }
2169
2170         cpu_x86_load_seg_cache(env, R_CS, new_cs,
2171                        get_seg_base(e1, e2),
2172                        get_seg_limit(e1, e2),
2173                        e2);
2174         sp = new_esp;
2175 #ifdef TARGET_X86_64
2176         if (env->hflags & HF_CS64_MASK) {
2177             sp_mask = -1;
2178         } else
2179 #endif
2180         {
2181             sp_mask = get_sp_mask(ss_e2);
2182         }
2183
2184         /* validate data segments */
2185         validate_seg(env, R_ES, rpl);
2186         validate_seg(env, R_DS, rpl);
2187         validate_seg(env, R_FS, rpl);
2188         validate_seg(env, R_GS, rpl);
2189
2190         sp += addend;
2191     }
2192     SET_ESP(sp, sp_mask);
2193     env->eip = new_eip;
2194     if (is_iret) {
2195         /* NOTE: 'cpl' is the _old_ CPL */
2196         eflags_mask = TF_MASK | AC_MASK | ID_MASK | RF_MASK | NT_MASK;
2197         if (cpl == 0) {
2198             eflags_mask |= IOPL_MASK;
2199         }
2200         iopl = (env->eflags >> IOPL_SHIFT) & 3;
2201         if (cpl <= iopl) {
2202             eflags_mask |= IF_MASK;
2203         }
2204         if (shift == 0) {
2205             eflags_mask &= 0xffff;
2206         }
2207         cpu_load_eflags(env, new_eflags, eflags_mask);
2208     }
2209     return;
2210
2211  return_to_vm86:
2212     POPL_RA(ssp, sp, sp_mask, new_esp, retaddr);
2213     POPL_RA(ssp, sp, sp_mask, new_ss, retaddr);
2214     POPL_RA(ssp, sp, sp_mask, new_es, retaddr);
2215     POPL_RA(ssp, sp, sp_mask, new_ds, retaddr);
2216     POPL_RA(ssp, sp, sp_mask, new_fs, retaddr);
2217     POPL_RA(ssp, sp, sp_mask, new_gs, retaddr);
2218
2219     /* modify processor state */
2220     cpu_load_eflags(env, new_eflags, TF_MASK | AC_MASK | ID_MASK |
2221                     IF_MASK | IOPL_MASK | VM_MASK | NT_MASK | VIF_MASK |
2222                     VIP_MASK);
2223     load_seg_vm(env, R_CS, new_cs & 0xffff);
2224     load_seg_vm(env, R_SS, new_ss & 0xffff);
2225     load_seg_vm(env, R_ES, new_es & 0xffff);
2226     load_seg_vm(env, R_DS, new_ds & 0xffff);
2227     load_seg_vm(env, R_FS, new_fs & 0xffff);
2228     load_seg_vm(env, R_GS, new_gs & 0xffff);
2229
2230     env->eip = new_eip & 0xffff;
2231     env->regs[R_ESP] = new_esp;
2232 }
2233
2234 void helper_iret_protected(CPUX86State *env, int shift, int next_eip)
2235 {
2236     int tss_selector, type;
2237     uint32_t e1, e2;
2238
2239     /* specific case for TSS */
2240     if (env->eflags & NT_MASK) {
2241 #ifdef TARGET_X86_64
2242         if (env->hflags & HF_LMA_MASK) {
2243             raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC());
2244         }
2245 #endif
2246         tss_selector = cpu_lduw_kernel_ra(env, env->tr.base + 0, GETPC());
2247         if (tss_selector & 4) {
2248             raise_exception_err_ra(env, EXCP0A_TSS, tss_selector & 0xfffc, GETPC());
2249         }
2250         if (load_segment_ra(env, &e1, &e2, tss_selector, GETPC()) != 0) {
2251             raise_exception_err_ra(env, EXCP0A_TSS, tss_selector & 0xfffc, GETPC());
2252         }
2253         type = (e2 >> DESC_TYPE_SHIFT) & 0x17;
2254         /* NOTE: we check both segment and busy TSS */
2255         if (type != 3) {
2256             raise_exception_err_ra(env, EXCP0A_TSS, tss_selector & 0xfffc, GETPC());
2257         }
2258         switch_tss_ra(env, tss_selector, e1, e2, SWITCH_TSS_IRET, next_eip, GETPC());
2259     } else {
2260         helper_ret_protected(env, shift, 1, 0, GETPC());
2261     }
2262     env->hflags2 &= ~HF2_NMI_MASK;
2263 }
2264
2265 void helper_lret_protected(CPUX86State *env, int shift, int addend)
2266 {
2267     helper_ret_protected(env, shift, 0, addend, GETPC());
2268 }
2269
2270 void helper_sysenter(CPUX86State *env)
2271 {
2272     if (env->sysenter_cs == 0) {
2273         raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC());
2274     }
2275     env->eflags &= ~(VM_MASK | IF_MASK | RF_MASK);
2276
2277 #ifdef TARGET_X86_64
2278     if (env->hflags & HF_LMA_MASK) {
2279         cpu_x86_load_seg_cache(env, R_CS, env->sysenter_cs & 0xfffc,
2280                                0, 0xffffffff,
2281                                DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2282                                DESC_S_MASK |
2283                                DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK |
2284                                DESC_L_MASK);
2285     } else
2286 #endif
2287     {
2288         cpu_x86_load_seg_cache(env, R_CS, env->sysenter_cs & 0xfffc,
2289                                0, 0xffffffff,
2290                                DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2291                                DESC_S_MASK |
2292                                DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
2293     }
2294     cpu_x86_load_seg_cache(env, R_SS, (env->sysenter_cs + 8) & 0xfffc,
2295                            0, 0xffffffff,
2296                            DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2297                            DESC_S_MASK |
2298                            DESC_W_MASK | DESC_A_MASK);
2299     env->regs[R_ESP] = env->sysenter_esp;
2300     env->eip = env->sysenter_eip;
2301 }
2302
2303 void helper_sysexit(CPUX86State *env, int dflag)
2304 {
2305     int cpl;
2306
2307     cpl = env->hflags & HF_CPL_MASK;
2308     if (env->sysenter_cs == 0 || cpl != 0) {
2309         raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC());
2310     }
2311 #ifdef TARGET_X86_64
2312     if (dflag == 2) {
2313         cpu_x86_load_seg_cache(env, R_CS, ((env->sysenter_cs + 32) & 0xfffc) |
2314                                3, 0, 0xffffffff,
2315                                DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2316                                DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
2317                                DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK |
2318                                DESC_L_MASK);
2319         cpu_x86_load_seg_cache(env, R_SS, ((env->sysenter_cs + 40) & 0xfffc) |
2320                                3, 0, 0xffffffff,
2321                                DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2322                                DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
2323                                DESC_W_MASK | DESC_A_MASK);
2324     } else
2325 #endif
2326     {
2327         cpu_x86_load_seg_cache(env, R_CS, ((env->sysenter_cs + 16) & 0xfffc) |
2328                                3, 0, 0xffffffff,
2329                                DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2330                                DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
2331                                DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
2332         cpu_x86_load_seg_cache(env, R_SS, ((env->sysenter_cs + 24) & 0xfffc) |
2333                                3, 0, 0xffffffff,
2334                                DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2335                                DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
2336                                DESC_W_MASK | DESC_A_MASK);
2337     }
2338     env->regs[R_ESP] = env->regs[R_ECX];
2339     env->eip = env->regs[R_EDX];
2340 }
2341
2342 target_ulong helper_lsl(CPUX86State *env, target_ulong selector1)
2343 {
2344     unsigned int limit;
2345     uint32_t e1, e2, eflags, selector;
2346     int rpl, dpl, cpl, type;
2347
2348     selector = selector1 & 0xffff;
2349     eflags = cpu_cc_compute_all(env, CC_OP);
2350     if ((selector & 0xfffc) == 0) {
2351         goto fail;
2352     }
2353     if (load_segment_ra(env, &e1, &e2, selector, GETPC()) != 0) {
2354         goto fail;
2355     }
2356     rpl = selector & 3;
2357     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2358     cpl = env->hflags & HF_CPL_MASK;
2359     if (e2 & DESC_S_MASK) {
2360         if ((e2 & DESC_CS_MASK) && (e2 & DESC_C_MASK)) {
2361             /* conforming */
2362         } else {
2363             if (dpl < cpl || dpl < rpl) {
2364                 goto fail;
2365             }
2366         }
2367     } else {
2368         type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
2369         switch (type) {
2370         case 1:
2371         case 2:
2372         case 3:
2373         case 9:
2374         case 11:
2375             break;
2376         default:
2377             goto fail;
2378         }
2379         if (dpl < cpl || dpl < rpl) {
2380         fail:
2381             CC_SRC = eflags & ~CC_Z;
2382             return 0;
2383         }
2384     }
2385     limit = get_seg_limit(e1, e2);
2386     CC_SRC = eflags | CC_Z;
2387     return limit;
2388 }
2389
2390 target_ulong helper_lar(CPUX86State *env, target_ulong selector1)
2391 {
2392     uint32_t e1, e2, eflags, selector;
2393     int rpl, dpl, cpl, type;
2394
2395     selector = selector1 & 0xffff;
2396     eflags = cpu_cc_compute_all(env, CC_OP);
2397     if ((selector & 0xfffc) == 0) {
2398         goto fail;
2399     }
2400     if (load_segment_ra(env, &e1, &e2, selector, GETPC()) != 0) {
2401         goto fail;
2402     }
2403     rpl = selector & 3;
2404     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2405     cpl = env->hflags & HF_CPL_MASK;
2406     if (e2 & DESC_S_MASK) {
2407         if ((e2 & DESC_CS_MASK) && (e2 & DESC_C_MASK)) {
2408             /* conforming */
2409         } else {
2410             if (dpl < cpl || dpl < rpl) {
2411                 goto fail;
2412             }
2413         }
2414     } else {
2415         type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
2416         switch (type) {
2417         case 1:
2418         case 2:
2419         case 3:
2420         case 4:
2421         case 5:
2422         case 9:
2423         case 11:
2424         case 12:
2425             break;
2426         default:
2427             goto fail;
2428         }
2429         if (dpl < cpl || dpl < rpl) {
2430         fail:
2431             CC_SRC = eflags & ~CC_Z;
2432             return 0;
2433         }
2434     }
2435     CC_SRC = eflags | CC_Z;
2436     return e2 & 0x00f0ff00;
2437 }
2438
2439 void helper_verr(CPUX86State *env, target_ulong selector1)
2440 {
2441     uint32_t e1, e2, eflags, selector;
2442     int rpl, dpl, cpl;
2443
2444     selector = selector1 & 0xffff;
2445     eflags = cpu_cc_compute_all(env, CC_OP);
2446     if ((selector & 0xfffc) == 0) {
2447         goto fail;
2448     }
2449     if (load_segment_ra(env, &e1, &e2, selector, GETPC()) != 0) {
2450         goto fail;
2451     }
2452     if (!(e2 & DESC_S_MASK)) {
2453         goto fail;
2454     }
2455     rpl = selector & 3;
2456     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2457     cpl = env->hflags & HF_CPL_MASK;
2458     if (e2 & DESC_CS_MASK) {
2459         if (!(e2 & DESC_R_MASK)) {
2460             goto fail;
2461         }
2462         if (!(e2 & DESC_C_MASK)) {
2463             if (dpl < cpl || dpl < rpl) {
2464                 goto fail;
2465             }
2466         }
2467     } else {
2468         if (dpl < cpl || dpl < rpl) {
2469         fail:
2470             CC_SRC = eflags & ~CC_Z;
2471             return;
2472         }
2473     }
2474     CC_SRC = eflags | CC_Z;
2475 }
2476
2477 void helper_verw(CPUX86State *env, target_ulong selector1)
2478 {
2479     uint32_t e1, e2, eflags, selector;
2480     int rpl, dpl, cpl;
2481
2482     selector = selector1 & 0xffff;
2483     eflags = cpu_cc_compute_all(env, CC_OP);
2484     if ((selector & 0xfffc) == 0) {
2485         goto fail;
2486     }
2487     if (load_segment_ra(env, &e1, &e2, selector, GETPC()) != 0) {
2488         goto fail;
2489     }
2490     if (!(e2 & DESC_S_MASK)) {
2491         goto fail;
2492     }
2493     rpl = selector & 3;
2494     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2495     cpl = env->hflags & HF_CPL_MASK;
2496     if (e2 & DESC_CS_MASK) {
2497         goto fail;
2498     } else {
2499         if (dpl < cpl || dpl < rpl) {
2500             goto fail;
2501         }
2502         if (!(e2 & DESC_W_MASK)) {
2503         fail:
2504             CC_SRC = eflags & ~CC_Z;
2505             return;
2506         }
2507     }
2508     CC_SRC = eflags | CC_Z;
2509 }
2510
2511 #if defined(CONFIG_USER_ONLY)
2512 void cpu_x86_load_seg(CPUX86State *env, int seg_reg, int selector)
2513 {
2514     if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
2515         int dpl = (env->eflags & VM_MASK) ? 3 : 0;
2516         selector &= 0xffff;
2517         cpu_x86_load_seg_cache(env, seg_reg, selector,
2518                                (selector << 4), 0xffff,
2519                                DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
2520                                DESC_A_MASK | (dpl << DESC_DPL_SHIFT));
2521     } else {
2522         helper_load_seg(env, seg_reg, selector);
2523     }
2524 }
2525 #endif
2526
2527 /* check if Port I/O is allowed in TSS */
2528 static inline void check_io(CPUX86State *env, int addr, int size,
2529                             uintptr_t retaddr)
2530 {
2531     int io_offset, val, mask;
2532
2533     /* TSS must be a valid 32 bit one */
2534     if (!(env->tr.flags & DESC_P_MASK) ||
2535         ((env->tr.flags >> DESC_TYPE_SHIFT) & 0xf) != 9 ||
2536         env->tr.limit < 103) {
2537         goto fail;
2538     }
2539     io_offset = cpu_lduw_kernel_ra(env, env->tr.base + 0x66, retaddr);
2540     io_offset += (addr >> 3);
2541     /* Note: the check needs two bytes */
2542     if ((io_offset + 1) > env->tr.limit) {
2543         goto fail;
2544     }
2545     val = cpu_lduw_kernel_ra(env, env->tr.base + io_offset, retaddr);
2546     val >>= (addr & 7);
2547     mask = (1 << size) - 1;
2548     /* all bits must be zero to allow the I/O */
2549     if ((val & mask) != 0) {
2550     fail:
2551         raise_exception_err_ra(env, EXCP0D_GPF, 0, retaddr);
2552     }
2553 }
2554
2555 void helper_check_iob(CPUX86State *env, uint32_t t0)
2556 {
2557     check_io(env, t0, 1, GETPC());
2558 }
2559
2560 void helper_check_iow(CPUX86State *env, uint32_t t0)
2561 {
2562     check_io(env, t0, 2, GETPC());
2563 }
2564
2565 void helper_check_iol(CPUX86State *env, uint32_t t0)
2566 {
2567     check_io(env, t0, 4, GETPC());
2568 }