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"
24 #define TARGET_DEFAULT_CPU_MODEL "qemu32"
26 static inline void target_cpu_init(CPUX86State
*env
,
27 struct target_pt_regs
*regs
)
31 env
->cr
[0] = CR0_PG_MASK
| CR0_WP_MASK
| CR0_PE_MASK
;
32 env
->hflags
|= HF_PE_MASK
| HF_CPL_MASK
;
33 if (env
->features
[FEAT_1_EDX
] & CPUID_SSE
) {
34 env
->cr
[4] |= CR4_OSFXSR_MASK
;
35 env
->hflags
|= HF_OSFXSR_MASK
;
38 /* flags setup : we activate the IRQs by default as in user mode */
39 env
->eflags
|= IF_MASK
;
42 env
->regs
[R_EAX
] = regs
->eax
;
43 env
->regs
[R_EBX
] = regs
->ebx
;
44 env
->regs
[R_ECX
] = regs
->ecx
;
45 env
->regs
[R_EDX
] = regs
->edx
;
46 env
->regs
[R_ESI
] = regs
->esi
;
47 env
->regs
[R_EDI
] = regs
->edi
;
48 env
->regs
[R_EBP
] = regs
->ebp
;
49 env
->regs
[R_ESP
] = regs
->esp
;
55 env
->idt
.base
= target_mmap(0, sizeof(uint64_t) * (env
->idt
.limit
+ 1),
56 PROT_READ
| PROT_WRITE
, MAP_ANONYMOUS
| MAP_PRIVATE
, -1, 0);
57 bsd_i386_set_idt_base(env
->idt
.base
);
58 bsd_i386_set_idt(0, 0);
59 bsd_i386_set_idt(1, 0);
60 bsd_i386_set_idt(2, 0);
61 bsd_i386_set_idt(3, 3);
62 bsd_i386_set_idt(4, 3);
63 bsd_i386_set_idt(5, 0);
64 bsd_i386_set_idt(6, 0);
65 bsd_i386_set_idt(7, 0);
66 bsd_i386_set_idt(8, 0);
67 bsd_i386_set_idt(9, 0);
68 bsd_i386_set_idt(10, 0);
69 bsd_i386_set_idt(11, 0);
70 bsd_i386_set_idt(12, 0);
71 bsd_i386_set_idt(13, 0);
72 bsd_i386_set_idt(14, 0);
73 bsd_i386_set_idt(15, 0);
74 bsd_i386_set_idt(16, 0);
75 bsd_i386_set_idt(17, 0);
76 bsd_i386_set_idt(18, 0);
77 bsd_i386_set_idt(19, 0);
78 bsd_i386_set_idt(0x80, 3);
81 env
->gdt
.base
= target_mmap(0, sizeof(uint64_t) * TARGET_GDT_ENTRIES
,
82 PROT_READ
| PROT_WRITE
, MAP_ANONYMOUS
| MAP_PRIVATE
, -1, 0);
83 env
->gdt
.limit
= sizeof(uint64_t) * TARGET_GDT_ENTRIES
- 1;
84 gdt_table
= g2h_untagged(env
->gdt
.base
);
86 bsd_i386_write_dt(&gdt_table
[__USER_CS
>> 3], 0, 0xfffff,
87 DESC_G_MASK
| DESC_B_MASK
| DESC_P_MASK
| DESC_S_MASK
|
88 (3 << DESC_DPL_SHIFT
) | (0xa << DESC_TYPE_SHIFT
));
90 bsd_i386_write_dt(&gdt_table
[__USER_DS
>> 3], 0, 0xfffff,
91 DESC_G_MASK
| DESC_B_MASK
| DESC_P_MASK
| DESC_S_MASK
|
92 (3 << DESC_DPL_SHIFT
) | (0x2 << DESC_TYPE_SHIFT
));
94 cpu_x86_load_seg(env
, R_CS
, __USER_CS
);
95 cpu_x86_load_seg(env
, R_SS
, __USER_DS
);
96 cpu_x86_load_seg(env
, R_DS
, __USER_DS
);
97 cpu_x86_load_seg(env
, R_ES
, __USER_DS
);
98 cpu_x86_load_seg(env
, R_FS
, __USER_DS
);
99 cpu_x86_load_seg(env
, R_GS
, __USER_DS
);
100 /* This hack makes Wine work... */
101 env
->segs
[R_FS
].selector
= 0;
104 static inline void target_cpu_loop(CPUX86State
*env
)
106 CPUState
*cs
= env_cpu(env
);
109 /* target_siginfo_t info; */
113 trapnr
= cpu_exec(cs
);
115 process_queued_cpu_work(cs
);
119 /* syscall from int $0x80 */
120 if (bsd_type
== target_freebsd
) {
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
,
158 } else { /* if (bsd_type == target_openbsd) */
159 env
->regs
[R_EAX
] = do_openbsd_syscall(env
,
168 if (((abi_ulong
)env
->regs
[R_EAX
]) >= (abi_ulong
)(-515)) {
169 env
->regs
[R_EAX
] = -env
->regs
[R_EAX
];
172 env
->eflags
&= ~CC_C
;
177 /* just indicate that signals should be handled asap */
181 cpu_exec_step_atomic(cs
);
185 pc
= env
->segs
[R_CS
].base
+ env
->eip
;
186 fprintf(stderr
, "qemu: 0x%08lx: unhandled CPU exception 0x%x - "
187 "aborting\n", (long)pc
, trapnr
);
190 process_pending_signals(env
);
194 static inline void target_cpu_clone_regs(CPUX86State
*env
, target_ulong newsp
)
197 env
->regs
[R_ESP
] = newsp
;
199 env
->regs
[R_EAX
] = 0;
202 static inline void target_cpu_reset(CPUArchState
*cpu
)
204 cpu_reset(env_cpu(cpu
));
207 #endif /* ! _TARGET_ARCH_CPU_H_ */