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