Commit d2fd1af76777687697674e7a49eeceac83907f3e

Authored by bellard
1 parent 6b23f777

x86_64 linux user emulation


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3646 c046a42c-6fe2-441c-8c8c-71466251a162
linux-user/main.c
@@ -147,8 +147,11 @@ static void write_dt(void *ptr, unsigned long addr, unsigned long limit, @@ -147,8 +147,11 @@ static void write_dt(void *ptr, unsigned long addr, unsigned long limit,
147 p[1] = tswapl(e2); 147 p[1] = tswapl(e2);
148 } 148 }
149 149
150 -static void set_gate(void *ptr, unsigned int type, unsigned int dpl,  
151 - unsigned long addr, unsigned int sel) 150 +#if TARGET_X86_64
  151 +uint64_t idt_table[512];
  152 +
  153 +static void set_gate64(void *ptr, unsigned int type, unsigned int dpl,
  154 + uint64_t addr, unsigned int sel)
152 { 155 {
153 unsigned int e1, e2; 156 unsigned int e1, e2;
154 uint32_t *p; 157 uint32_t *p;
@@ -157,15 +160,34 @@ static void set_gate(void *ptr, unsigned int type, unsigned int dpl, @@ -157,15 +160,34 @@ static void set_gate(void *ptr, unsigned int type, unsigned int dpl,
157 p = ptr; 160 p = ptr;
158 p[0] = tswapl(e1); 161 p[0] = tswapl(e1);
159 p[1] = tswapl(e2); 162 p[1] = tswapl(e2);
  163 + p[2] = addr >> 32;
160 } 164 }
161 - 165 +/* only dpl matters as we do only user space emulation */
  166 +static void set_idt(int n, unsigned int dpl)
  167 +{
  168 + set_gate64(idt_table + n * 2, 0, dpl, 0, 0);
  169 +}
  170 +#else
162 uint64_t idt_table[256]; 171 uint64_t idt_table[256];
163 172
  173 +static void set_gate(void *ptr, unsigned int type, unsigned int dpl,
  174 + uint32_t addr, unsigned int sel)
  175 +{
  176 + unsigned int e1, e2;
  177 + uint32_t *p;
  178 + e1 = (addr & 0xffff) | (sel << 16);
  179 + e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8);
  180 + p = ptr;
  181 + p[0] = tswapl(e1);
  182 + p[1] = tswapl(e2);
  183 +}
  184 +
164 /* only dpl matters as we do only user space emulation */ 185 /* only dpl matters as we do only user space emulation */
165 static void set_idt(int n, unsigned int dpl) 186 static void set_idt(int n, unsigned int dpl)
166 { 187 {
167 set_gate(idt_table + n, 0, dpl, 0, 0); 188 set_gate(idt_table + n, 0, dpl, 0, 0);
168 } 189 }
  190 +#endif
169 191
170 void cpu_loop(CPUX86State *env) 192 void cpu_loop(CPUX86State *env)
171 { 193 {
@@ -177,7 +199,7 @@ void cpu_loop(CPUX86State *env) @@ -177,7 +199,7 @@ void cpu_loop(CPUX86State *env)
177 trapnr = cpu_x86_exec(env); 199 trapnr = cpu_x86_exec(env);
178 switch(trapnr) { 200 switch(trapnr) {
179 case 0x80: 201 case 0x80:
180 - /* linux syscall */ 202 + /* linux syscall from int $0x80 */
181 env->regs[R_EAX] = do_syscall(env, 203 env->regs[R_EAX] = do_syscall(env,
182 env->regs[R_EAX], 204 env->regs[R_EAX],
183 env->regs[R_EBX], 205 env->regs[R_EBX],
@@ -187,6 +209,20 @@ void cpu_loop(CPUX86State *env) @@ -187,6 +209,20 @@ void cpu_loop(CPUX86State *env)
187 env->regs[R_EDI], 209 env->regs[R_EDI],
188 env->regs[R_EBP]); 210 env->regs[R_EBP]);
189 break; 211 break;
  212 +#ifndef TARGET_ABI32
  213 + case EXCP_SYSCALL:
  214 + /* linux syscall from syscall intruction */
  215 + env->regs[R_EAX] = do_syscall(env,
  216 + env->regs[R_EAX],
  217 + env->regs[R_EDI],
  218 + env->regs[R_ESI],
  219 + env->regs[R_EDX],
  220 + env->regs[10],
  221 + env->regs[8],
  222 + env->regs[9]);
  223 + env->eip = env->exception_next_eip;
  224 + break;
  225 +#endif
190 case EXCP0B_NOSEG: 226 case EXCP0B_NOSEG:
191 case EXCP0C_STACK: 227 case EXCP0C_STACK:
192 info.si_signo = SIGBUS; 228 info.si_signo = SIGBUS;
@@ -196,6 +232,7 @@ void cpu_loop(CPUX86State *env) @@ -196,6 +232,7 @@ void cpu_loop(CPUX86State *env)
196 queue_signal(info.si_signo, &info); 232 queue_signal(info.si_signo, &info);
197 break; 233 break;
198 case EXCP0D_GPF: 234 case EXCP0D_GPF:
  235 + /* XXX: potential problem if ABI32 */
199 #ifndef TARGET_X86_64 236 #ifndef TARGET_X86_64
200 if (env->eflags & VM_MASK) { 237 if (env->eflags & VM_MASK) {
201 handle_vm86_fault(env); 238 handle_vm86_fault(env);
@@ -2075,12 +2112,18 @@ int main(int argc, char **argv) @@ -2075,12 +2112,18 @@ int main(int argc, char **argv)
2075 env->cr[4] |= CR4_OSFXSR_MASK; 2112 env->cr[4] |= CR4_OSFXSR_MASK;
2076 env->hflags |= HF_OSFXSR_MASK; 2113 env->hflags |= HF_OSFXSR_MASK;
2077 } 2114 }
  2115 +#ifndef TARGET_ABI32
  2116 + /* enable 64 bit mode */
  2117 + env->cr[4] |= CR4_PAE_MASK;
  2118 + env->efer |= MSR_EFER_LMA;
  2119 + env->hflags |= HF_LMA_MASK;
  2120 +#endif
2078 2121
2079 /* flags setup : we activate the IRQs by default as in user mode */ 2122 /* flags setup : we activate the IRQs by default as in user mode */
2080 env->eflags |= IF_MASK; 2123 env->eflags |= IF_MASK;
2081 2124
2082 /* linux register setup */ 2125 /* linux register setup */
2083 -#if defined(TARGET_X86_64) 2126 +#ifndef TARGET_ABI32
2084 env->regs[R_EAX] = regs->rax; 2127 env->regs[R_EAX] = regs->rax;
2085 env->regs[R_EBX] = regs->rbx; 2128 env->regs[R_EBX] = regs->rbx;
2086 env->regs[R_ECX] = regs->rcx; 2129 env->regs[R_ECX] = regs->rcx;
@@ -2131,24 +2174,38 @@ int main(int argc, char **argv) @@ -2131,24 +2174,38 @@ int main(int argc, char **argv)
2131 { 2174 {
2132 uint64_t *gdt_table; 2175 uint64_t *gdt_table;
2133 gdt_table = qemu_mallocz(sizeof(uint64_t) * TARGET_GDT_ENTRIES); 2176 gdt_table = qemu_mallocz(sizeof(uint64_t) * TARGET_GDT_ENTRIES);
2134 - env->gdt.base = h2g(gdt_table); 2177 + env->gdt.base = h2g((unsigned long)gdt_table);
2135 env->gdt.limit = sizeof(uint64_t) * TARGET_GDT_ENTRIES - 1; 2178 env->gdt.limit = sizeof(uint64_t) * TARGET_GDT_ENTRIES - 1;
  2179 +#ifdef TARGET_ABI32
2136 write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff, 2180 write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff,
2137 DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK | 2181 DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
2138 (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT)); 2182 (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT));
  2183 +#else
  2184 + /* 64 bit code segment */
  2185 + write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff,
  2186 + DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
  2187 + DESC_L_MASK |
  2188 + (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT));
  2189 +#endif
2139 write_dt(&gdt_table[__USER_DS >> 3], 0, 0xfffff, 2190 write_dt(&gdt_table[__USER_DS >> 3], 0, 0xfffff,
2140 DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK | 2191 DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
2141 (3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT)); 2192 (3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT));
2142 } 2193 }
2143 cpu_x86_load_seg(env, R_CS, __USER_CS); 2194 cpu_x86_load_seg(env, R_CS, __USER_CS);
  2195 + cpu_x86_load_seg(env, R_SS, __USER_DS);
  2196 +#ifdef TARGET_ABI32
2144 cpu_x86_load_seg(env, R_DS, __USER_DS); 2197 cpu_x86_load_seg(env, R_DS, __USER_DS);
2145 cpu_x86_load_seg(env, R_ES, __USER_DS); 2198 cpu_x86_load_seg(env, R_ES, __USER_DS);
2146 - cpu_x86_load_seg(env, R_SS, __USER_DS);  
2147 cpu_x86_load_seg(env, R_FS, __USER_DS); 2199 cpu_x86_load_seg(env, R_FS, __USER_DS);
2148 cpu_x86_load_seg(env, R_GS, __USER_DS); 2200 cpu_x86_load_seg(env, R_GS, __USER_DS);
2149 -  
2150 /* This hack makes Wine work... */ 2201 /* This hack makes Wine work... */
2151 env->segs[R_FS].selector = 0; 2202 env->segs[R_FS].selector = 0;
  2203 +#else
  2204 + cpu_x86_load_seg(env, R_DS, 0);
  2205 + cpu_x86_load_seg(env, R_ES, 0);
  2206 + cpu_x86_load_seg(env, R_FS, 0);
  2207 + cpu_x86_load_seg(env, R_GS, 0);
  2208 +#endif
2152 #elif defined(TARGET_ARM) 2209 #elif defined(TARGET_ARM)
2153 { 2210 {
2154 int i; 2211 int i;
linux-user/syscall.c
@@ -2521,6 +2521,41 @@ abi_long do_get_thread_area(CPUX86State *env, abi_ulong ptr) @@ -2521,6 +2521,41 @@ abi_long do_get_thread_area(CPUX86State *env, abi_ulong ptr)
2521 return 0; 2521 return 0;
2522 } 2522 }
2523 2523
  2524 +#ifndef TARGET_ABI32
  2525 +abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr)
  2526 +{
  2527 + abi_long ret;
  2528 + abi_ulong val;
  2529 + int idx;
  2530 +
  2531 + switch(code) {
  2532 + case TARGET_ARCH_SET_GS:
  2533 + case TARGET_ARCH_SET_FS:
  2534 + if (code == TARGET_ARCH_SET_GS)
  2535 + idx = R_GS;
  2536 + else
  2537 + idx = R_FS;
  2538 + cpu_x86_load_seg(env, idx, 0);
  2539 + env->segs[idx].base = addr;
  2540 + break;
  2541 + case TARGET_ARCH_GET_GS:
  2542 + case TARGET_ARCH_GET_FS:
  2543 + if (code == TARGET_ARCH_GET_GS)
  2544 + idx = R_GS;
  2545 + else
  2546 + idx = R_FS;
  2547 + val = env->segs[idx].base;
  2548 + if (put_user(val, addr, abi_ulong))
  2549 + return -TARGET_EFAULT;
  2550 + break;
  2551 + default:
  2552 + ret = -TARGET_EINVAL;
  2553 + break;
  2554 + }
  2555 + return 0;
  2556 +}
  2557 +#endif
  2558 +
2524 #endif /* defined(TARGET_I386) */ 2559 #endif /* defined(TARGET_I386) */
2525 2560
2526 /* this stack is the equivalent of the kernel stack associated with a 2561 /* this stack is the equivalent of the kernel stack associated with a
@@ -2797,7 +2832,7 @@ void syscall_init(void) @@ -2797,7 +2832,7 @@ void syscall_init(void)
2797 target_to_host_errno_table[host_to_target_errno_table[i]] = i; 2832 target_to_host_errno_table[host_to_target_errno_table[i]] = i;
2798 2833
2799 /* automatic consistency check if same arch */ 2834 /* automatic consistency check if same arch */
2800 -#if defined(__i386__) && defined(TARGET_I386) 2835 +#if defined(__i386__) && defined(TARGET_I386) && defined(TARGET_ABI32)
2801 if (ie->target_cmd != ie->host_cmd) { 2836 if (ie->target_cmd != ie->host_cmd) {
2802 fprintf(stderr, "ERROR: ioctl: target=0x%x host=0x%x\n", 2837 fprintf(stderr, "ERROR: ioctl: target=0x%x host=0x%x\n",
2803 ie->target_cmd, ie->host_cmd); 2838 ie->target_cmd, ie->host_cmd);
@@ -3861,7 +3896,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, @@ -3861,7 +3896,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
3861 #endif 3896 #endif
3862 #ifdef TARGET_NR_mmap 3897 #ifdef TARGET_NR_mmap
3863 case TARGET_NR_mmap: 3898 case TARGET_NR_mmap:
3864 -#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_CRIS) 3899 +#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_CRIS)
3865 { 3900 {
3866 abi_ulong *v; 3901 abi_ulong *v;
3867 abi_ulong v1, v2, v3, v4, v5, v6; 3902 abi_ulong v1, v2, v3, v4, v5, v6;
@@ -4183,42 +4218,19 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, @@ -4183,42 +4218,19 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
4183 4218
4184 if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0)) 4219 if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0))
4185 goto efault; 4220 goto efault;
4186 -#if defined(TARGET_MIPS) || (defined(TARGET_SPARC64) && !defined(TARGET_ABI32))  
4187 - target_st->st_dev = tswap32(st.st_dev);  
4188 -#else  
4189 - target_st->st_dev = tswap16(st.st_dev);  
4190 -#endif  
4191 - target_st->st_ino = tswapl(st.st_ino);  
4192 -#if defined(TARGET_PPC) || defined(TARGET_MIPS)  
4193 - target_st->st_mode = tswapl(st.st_mode); /* XXX: check this */  
4194 - target_st->st_uid = tswap32(st.st_uid);  
4195 - target_st->st_gid = tswap32(st.st_gid);  
4196 -#elif defined(TARGET_SPARC64) && !defined(TARGET_ABI32)  
4197 - target_st->st_mode = tswap32(st.st_mode);  
4198 - target_st->st_uid = tswap32(st.st_uid);  
4199 - target_st->st_gid = tswap32(st.st_gid);  
4200 -#else  
4201 - target_st->st_mode = tswap16(st.st_mode);  
4202 - target_st->st_uid = tswap16(st.st_uid);  
4203 - target_st->st_gid = tswap16(st.st_gid);  
4204 -#endif  
4205 -#if defined(TARGET_MIPS)  
4206 - /* If this is the same on PPC, then just merge w/ the above ifdef */  
4207 - target_st->st_nlink = tswapl(st.st_nlink);  
4208 - target_st->st_rdev = tswapl(st.st_rdev);  
4209 -#elif defined(TARGET_SPARC64) && !defined(TARGET_ABI32)  
4210 - target_st->st_nlink = tswap32(st.st_nlink);  
4211 - target_st->st_rdev = tswap32(st.st_rdev);  
4212 -#else  
4213 - target_st->st_nlink = tswap16(st.st_nlink);  
4214 - target_st->st_rdev = tswap16(st.st_rdev);  
4215 -#endif  
4216 - target_st->st_size = tswapl(st.st_size);  
4217 - target_st->st_blksize = tswapl(st.st_blksize);  
4218 - target_st->st_blocks = tswapl(st.st_blocks);  
4219 - target_st->target_st_atime = tswapl(st.st_atime);  
4220 - target_st->target_st_mtime = tswapl(st.st_mtime);  
4221 - target_st->target_st_ctime = tswapl(st.st_ctime); 4221 + __put_user(st.st_dev, &target_st->st_dev);
  4222 + __put_user(st.st_ino, &target_st->st_ino);
  4223 + __put_user(st.st_mode, &target_st->st_mode);
  4224 + __put_user(st.st_uid, &target_st->st_uid);
  4225 + __put_user(st.st_gid, &target_st->st_gid);
  4226 + __put_user(st.st_nlink, &target_st->st_nlink);
  4227 + __put_user(st.st_rdev, &target_st->st_rdev);
  4228 + __put_user(st.st_size, &target_st->st_size);
  4229 + __put_user(st.st_blksize, &target_st->st_blksize);
  4230 + __put_user(st.st_blocks, &target_st->st_blocks);
  4231 + __put_user(st.st_atime, &target_st->target_st_atime);
  4232 + __put_user(st.st_mtime, &target_st->target_st_mtime);
  4233 + __put_user(st.st_ctime, &target_st->target_st_ctime);
4222 unlock_user_struct(target_st, arg2, 1); 4234 unlock_user_struct(target_st, arg2, 1);
4223 } 4235 }
4224 } 4236 }
@@ -4671,6 +4683,15 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, @@ -4671,6 +4683,15 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
4671 break; 4683 break;
4672 } 4684 }
4673 break; 4685 break;
  4686 +#ifdef TARGET_NR_arch_prctl
  4687 + case TARGET_NR_arch_prctl:
  4688 +#if defined(TARGET_I386) && !defined(TARGET_ABI32)
  4689 + ret = do_arch_prctl(cpu_env, arg1, arg2);
  4690 + break;
  4691 +#else
  4692 + goto unimplemented;
  4693 +#endif
  4694 +#endif
4674 #ifdef TARGET_NR_pread 4695 #ifdef TARGET_NR_pread
4675 case TARGET_NR_pread: 4696 case TARGET_NR_pread:
4676 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0))) 4697 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
linux-user/syscall_defs.h
@@ -881,7 +881,7 @@ struct target_winsize { @@ -881,7 +881,7 @@ struct target_winsize {
881 #define TARGET_MAP_NONBLOCK 0x10000 /* do not block on IO */ 881 #define TARGET_MAP_NONBLOCK 0x10000 /* do not block on IO */
882 #endif 882 #endif
883 883
884 -#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_CRIS) 884 +#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || defined(TARGET_ARM) || defined(TARGET_CRIS)
885 struct target_stat { 885 struct target_stat {
886 unsigned short st_dev; 886 unsigned short st_dev;
887 unsigned short __pad1; 887 unsigned short __pad1;
@@ -1474,6 +1474,30 @@ struct target_stat64 { @@ -1474,6 +1474,30 @@ struct target_stat64 {
1474 unsigned long long st_ino; 1474 unsigned long long st_ino;
1475 }; 1475 };
1476 1476
  1477 +#elif defined(TARGET_I386) && !defined(TARGET_ABI32)
  1478 +struct target_stat {
  1479 + abi_ulong st_dev;
  1480 + abi_ulong st_ino;
  1481 + abi_ulong st_nlink;
  1482 +
  1483 + unsigned int st_mode;
  1484 + unsigned int st_uid;
  1485 + unsigned int st_gid;
  1486 + unsigned int __pad0;
  1487 + abi_ulong st_rdev;
  1488 + abi_long st_size;
  1489 + abi_long st_blksize;
  1490 + abi_long st_blocks; /* Number 512-byte blocks allocated. */
  1491 +
  1492 + abi_ulong target_st_atime;
  1493 + abi_ulong target_st_atime_nsec;
  1494 + abi_ulong target_st_mtime;
  1495 + abi_ulong target_st_mtime_nsec;
  1496 + abi_ulong target_st_ctime;
  1497 + abi_ulong target_st_ctime_nsec;
  1498 +
  1499 + abi_long __unused[3];
  1500 +};
1477 #else 1501 #else
1478 #error unsupported CPU 1502 #error unsupported CPU
1479 #endif 1503 #endif
linux-user/x86_64/syscall.h
@@ -91,3 +91,8 @@ struct target_msqid64_ds { @@ -91,3 +91,8 @@ struct target_msqid64_ds {
91 }; 91 };
92 92
93 #define UNAME_MACHINE "x86_64" 93 #define UNAME_MACHINE "x86_64"
  94 +
  95 +#define TARGET_ARCH_SET_GS 0x1001
  96 +#define TARGET_ARCH_SET_FS 0x1002
  97 +#define TARGET_ARCH_GET_FS 0x1003
  98 +#define TARGET_ARCH_GET_GS 0x1004
target-i386/cpu.h
@@ -340,6 +340,9 @@ @@ -340,6 +340,9 @@
340 #define EXCP11_ALGN 17 340 #define EXCP11_ALGN 17
341 #define EXCP12_MCHK 18 341 #define EXCP12_MCHK 18
342 342
  343 +#define EXCP_SYSCALL 0x100 /* only happens in user only emulation
  344 + for syscall instruction */
  345 +
343 enum { 346 enum {
344 CC_OP_DYNAMIC, /* must use dynamic code to get cc_op */ 347 CC_OP_DYNAMIC, /* must use dynamic code to get cc_op */
345 CC_OP_EFLAGS, /* all cc are explicitely computed, CC_SRC = flags */ 348 CC_OP_EFLAGS, /* all cc are explicitely computed, CC_SRC = flags */
target-i386/helper.c
@@ -971,6 +971,14 @@ static void do_interrupt64(int intno, int is_int, int error_code, @@ -971,6 +971,14 @@ static void do_interrupt64(int intno, int is_int, int error_code,
971 } 971 }
972 #endif 972 #endif
973 973
  974 +#if defined(CONFIG_USER_ONLY)
  975 +void helper_syscall(int next_eip_addend)
  976 +{
  977 + env->exception_index = EXCP_SYSCALL;
  978 + env->exception_next_eip = env->eip + next_eip_addend;
  979 + cpu_loop_exit();
  980 +}
  981 +#else
974 void helper_syscall(int next_eip_addend) 982 void helper_syscall(int next_eip_addend)
975 { 983 {
976 int selector; 984 int selector;
@@ -1024,6 +1032,7 @@ void helper_syscall(int next_eip_addend) @@ -1024,6 +1032,7 @@ void helper_syscall(int next_eip_addend)
1024 env->eip = (uint32_t)env->star; 1032 env->eip = (uint32_t)env->star;
1025 } 1033 }
1026 } 1034 }
  1035 +#endif
1027 1036
1028 void helper_sysret(int dflag) 1037 void helper_sysret(int dflag)
1029 { 1038 {
@@ -1143,18 +1152,23 @@ void do_interrupt_user(int intno, int is_int, int error_code, @@ -1143,18 +1152,23 @@ void do_interrupt_user(int intno, int is_int, int error_code,
1143 { 1152 {
1144 SegmentCache *dt; 1153 SegmentCache *dt;
1145 target_ulong ptr; 1154 target_ulong ptr;
1146 - int dpl, cpl; 1155 + int dpl, cpl, shift;
1147 uint32_t e2; 1156 uint32_t e2;
1148 1157
1149 dt = &env->idt; 1158 dt = &env->idt;
1150 - ptr = dt->base + (intno * 8); 1159 + if (env->hflags & HF_LMA_MASK) {
  1160 + shift = 4;
  1161 + } else {
  1162 + shift = 3;
  1163 + }
  1164 + ptr = dt->base + (intno << shift);
1151 e2 = ldl_kernel(ptr + 4); 1165 e2 = ldl_kernel(ptr + 4);
1152 1166
1153 dpl = (e2 >> DESC_DPL_SHIFT) & 3; 1167 dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1154 cpl = env->hflags & HF_CPL_MASK; 1168 cpl = env->hflags & HF_CPL_MASK;
1155 /* check privledge if software int */ 1169 /* check privledge if software int */
1156 if (is_int && dpl < cpl) 1170 if (is_int && dpl < cpl)
1157 - raise_exception_err(EXCP0D_GPF, intno * 8 + 2); 1171 + raise_exception_err(EXCP0D_GPF, (intno << shift) + 2);
1158 1172
1159 /* Since we emulate only user space, we cannot do more than 1173 /* Since we emulate only user space, we cannot do more than
1160 exiting the emulation with the suitable exception and error 1174 exiting the emulation with the suitable exception and error