2 * i386 cpu init and loop
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, see <http://www.gnu.org/licenses/>.
19 #ifndef TARGET_ARCH_CPU_H
20 #define TARGET_ARCH_CPU_H
22 #include "target_arch.h"
23 #include "signal-common.h"
25 #define TARGET_DEFAULT_CPU_MODEL "qemu32"
27 static inline void target_cpu_init(CPUX86State
*env
,
28 struct target_pt_regs
*regs
)
32 env
->cr
[0] = CR0_PG_MASK
| CR0_WP_MASK
| CR0_PE_MASK
;
33 env
->hflags
|= HF_PE_MASK
| HF_CPL_MASK
;
34 if (env
->features
[FEAT_1_EDX
] & CPUID_SSE
) {
35 env
->cr
[4] |= CR4_OSFXSR_MASK
;
36 env
->hflags
|= HF_OSFXSR_MASK
;
39 /* flags setup : we activate the IRQs by default as in user mode */
40 env
->eflags
|= IF_MASK
;
43 env
->regs
[R_EAX
] = regs
->eax
;
44 env
->regs
[R_EBX
] = regs
->ebx
;
45 env
->regs
[R_ECX
] = regs
->ecx
;
46 env
->regs
[R_EDX
] = regs
->edx
;
47 env
->regs
[R_ESI
] = regs
->esi
;
48 env
->regs
[R_EDI
] = regs
->edi
;
49 env
->regs
[R_EBP
] = regs
->ebp
;
50 env
->regs
[R_ESP
] = regs
->esp
;
56 env
->idt
.base
= target_mmap(0, sizeof(uint64_t) * (env
->idt
.limit
+ 1),
57 PROT_READ
| PROT_WRITE
, MAP_ANONYMOUS
| MAP_PRIVATE
, -1, 0);
58 bsd_i386_set_idt_base(env
->idt
.base
);
59 bsd_i386_set_idt(0, 0);
60 bsd_i386_set_idt(1, 0);
61 bsd_i386_set_idt(2, 0);
62 bsd_i386_set_idt(3, 3);
63 bsd_i386_set_idt(4, 3);
64 bsd_i386_set_idt(5, 0);
65 bsd_i386_set_idt(6, 0);
66 bsd_i386_set_idt(7, 0);
67 bsd_i386_set_idt(8, 0);
68 bsd_i386_set_idt(9, 0);
69 bsd_i386_set_idt(10, 0);
70 bsd_i386_set_idt(11, 0);
71 bsd_i386_set_idt(12, 0);
72 bsd_i386_set_idt(13, 0);
73 bsd_i386_set_idt(14, 0);
74 bsd_i386_set_idt(15, 0);
75 bsd_i386_set_idt(16, 0);
76 bsd_i386_set_idt(17, 0);
77 bsd_i386_set_idt(18, 0);
78 bsd_i386_set_idt(19, 0);
79 bsd_i386_set_idt(0x80, 3);
82 env
->gdt
.base
= target_mmap(0, sizeof(uint64_t) * TARGET_GDT_ENTRIES
,
83 PROT_READ
| PROT_WRITE
, MAP_ANONYMOUS
| MAP_PRIVATE
, -1, 0);
84 env
->gdt
.limit
= sizeof(uint64_t) * TARGET_GDT_ENTRIES
- 1;
85 gdt_table
= g2h_untagged(env
->gdt
.base
);
87 bsd_i386_write_dt(&gdt_table
[__USER_CS
>> 3], 0, 0xfffff,
88 DESC_G_MASK
| DESC_B_MASK
| DESC_P_MASK
| DESC_S_MASK
|
89 (3 << DESC_DPL_SHIFT
) | (0xa << DESC_TYPE_SHIFT
));
91 bsd_i386_write_dt(&gdt_table
[__USER_DS
>> 3], 0, 0xfffff,
92 DESC_G_MASK
| DESC_B_MASK
| DESC_P_MASK
| DESC_S_MASK
|
93 (3 << DESC_DPL_SHIFT
) | (0x2 << DESC_TYPE_SHIFT
));
95 cpu_x86_load_seg(env
, R_CS
, __USER_CS
);
96 cpu_x86_load_seg(env
, R_SS
, __USER_DS
);
97 cpu_x86_load_seg(env
, R_DS
, __USER_DS
);
98 cpu_x86_load_seg(env
, R_ES
, __USER_DS
);
99 cpu_x86_load_seg(env
, R_FS
, __USER_DS
);
100 cpu_x86_load_seg(env
, R_GS
, __USER_DS
);
101 /* This hack makes Wine work... */
102 env
->segs
[R_FS
].selector
= 0;
105 static inline void target_cpu_loop(CPUX86State
*env
)
107 CPUState
*cs
= env_cpu(env
);
110 /* target_siginfo_t info; */
114 trapnr
= cpu_exec(cs
);
116 process_queued_cpu_work(cs
);
120 /* syscall from int $0x80 */
121 abi_ulong params
= (abi_ulong
) env
->regs
[R_ESP
] +
123 int32_t syscall_nr
= env
->regs
[R_EAX
];
124 int32_t arg1
, arg2
, arg3
, arg4
, arg5
, arg6
, arg7
, arg8
;
126 if (syscall_nr
== TARGET_FREEBSD_NR_syscall
) {
127 get_user_s32(syscall_nr
, params
);
128 params
+= sizeof(int32_t);
129 } else if (syscall_nr
== TARGET_FREEBSD_NR___syscall
) {
130 get_user_s32(syscall_nr
, params
);
131 params
+= sizeof(int64_t);
133 get_user_s32(arg1
, params
);
134 params
+= sizeof(int32_t);
135 get_user_s32(arg2
, params
);
136 params
+= sizeof(int32_t);
137 get_user_s32(arg3
, params
);
138 params
+= sizeof(int32_t);
139 get_user_s32(arg4
, params
);
140 params
+= sizeof(int32_t);
141 get_user_s32(arg5
, params
);
142 params
+= sizeof(int32_t);
143 get_user_s32(arg6
, params
);
144 params
+= sizeof(int32_t);
145 get_user_s32(arg7
, params
);
146 params
+= sizeof(int32_t);
147 get_user_s32(arg8
, params
);
148 env
->regs
[R_EAX
] = do_freebsd_syscall(env
,
159 if (((abi_ulong
)env
->regs
[R_EAX
]) >= (abi_ulong
)(-515)) {
160 env
->regs
[R_EAX
] = -env
->regs
[R_EAX
];
163 env
->eflags
&= ~CC_C
;
168 /* just indicate that signals should be handled asap */
172 cpu_exec_step_atomic(cs
);
176 pc
= env
->segs
[R_CS
].base
+ env
->eip
;
177 fprintf(stderr
, "qemu: 0x%08lx: unhandled CPU exception 0x%x - "
178 "aborting\n", (long)pc
, trapnr
);
181 process_pending_signals(env
);
185 static inline void target_cpu_clone_regs(CPUX86State
*env
, target_ulong newsp
)
188 env
->regs
[R_ESP
] = newsp
;
190 env
->regs
[R_EAX
] = 0;
193 static inline void target_cpu_reset(CPUArchState
*env
)
195 cpu_reset(env_cpu(env
));
198 #endif /* TARGET_ARCH_CPU_H */