2 * x86_64 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 "qemu64"
26 #define TARGET_CPU_RESET(cpu)
28 static inline void target_cpu_init(CPUX86State
*env
,
29 struct target_pt_regs
*regs
)
33 env
->cr
[0] = CR0_PG_MASK
| CR0_WP_MASK
| CR0_PE_MASK
;
34 env
->hflags
|= HF_PE_MASK
| HF_CPL_MASK
;
35 if (env
->features
[FEAT_1_EDX
] & CPUID_SSE
) {
36 env
->cr
[4] |= CR4_OSFXSR_MASK
;
37 env
->hflags
|= HF_OSFXSR_MASK
;
40 /* enable 64 bit mode if possible */
41 if (!(env
->features
[FEAT_8000_0001_EDX
] & CPUID_EXT2_LM
)) {
42 fprintf(stderr
, "The selected x86 CPU does not support 64 bit mode\n");
45 env
->cr
[4] |= CR4_PAE_MASK
;
46 env
->efer
|= MSR_EFER_LMA
| MSR_EFER_LME
;
47 env
->hflags
|= HF_LMA_MASK
;
49 /* flags setup : we activate the IRQs by default as in user mode */
50 env
->eflags
|= IF_MASK
;
53 env
->regs
[R_EAX
] = regs
->rax
;
54 env
->regs
[R_EBX
] = regs
->rbx
;
55 env
->regs
[R_ECX
] = regs
->rcx
;
56 env
->regs
[R_EDX
] = regs
->rdx
;
57 env
->regs
[R_ESI
] = regs
->rsi
;
58 env
->regs
[R_EDI
] = regs
->rdi
;
59 env
->regs
[R_EBP
] = regs
->rbp
;
60 env
->regs
[R_ESP
] = regs
->rsp
;
66 env
->idt
.base
= target_mmap(0, sizeof(uint64_t) * (env
->idt
.limit
+ 1),
67 PROT_READ
| PROT_WRITE
, MAP_ANONYMOUS
| MAP_PRIVATE
, -1, 0);
68 bsd_x86_64_set_idt_base(env
->idt
.base
);
69 bsd_x86_64_set_idt(0, 0);
70 bsd_x86_64_set_idt(1, 0);
71 bsd_x86_64_set_idt(2, 0);
72 bsd_x86_64_set_idt(3, 3);
73 bsd_x86_64_set_idt(4, 3);
74 bsd_x86_64_set_idt(5, 0);
75 bsd_x86_64_set_idt(6, 0);
76 bsd_x86_64_set_idt(7, 0);
77 bsd_x86_64_set_idt(8, 0);
78 bsd_x86_64_set_idt(9, 0);
79 bsd_x86_64_set_idt(10, 0);
80 bsd_x86_64_set_idt(11, 0);
81 bsd_x86_64_set_idt(12, 0);
82 bsd_x86_64_set_idt(13, 0);
83 bsd_x86_64_set_idt(14, 0);
84 bsd_x86_64_set_idt(15, 0);
85 bsd_x86_64_set_idt(16, 0);
86 bsd_x86_64_set_idt(17, 0);
87 bsd_x86_64_set_idt(18, 0);
88 bsd_x86_64_set_idt(19, 0);
89 bsd_x86_64_set_idt(0x80, 3);
92 env
->gdt
.base
= target_mmap(0, sizeof(uint64_t) * TARGET_GDT_ENTRIES
,
93 PROT_READ
| PROT_WRITE
, MAP_ANONYMOUS
| MAP_PRIVATE
, -1, 0);
94 env
->gdt
.limit
= sizeof(uint64_t) * TARGET_GDT_ENTRIES
- 1;
95 gdt_table
= g2h_untagged(env
->gdt
.base
);
97 /* 64 bit code segment */
98 bsd_x86_64_write_dt(&gdt_table
[__USER_CS
>> 3], 0, 0xfffff,
99 DESC_G_MASK
| DESC_B_MASK
| DESC_P_MASK
| DESC_S_MASK
| DESC_L_MASK
100 | (3 << DESC_DPL_SHIFT
) | (0xa << DESC_TYPE_SHIFT
));
102 bsd_x86_64_write_dt(&gdt_table
[__USER_DS
>> 3], 0, 0xfffff,
103 DESC_G_MASK
| DESC_B_MASK
| DESC_P_MASK
| DESC_S_MASK
|
104 (3 << DESC_DPL_SHIFT
) | (0x2 << DESC_TYPE_SHIFT
));
106 cpu_x86_load_seg(env
, R_CS
, __USER_CS
);
107 cpu_x86_load_seg(env
, R_SS
, __USER_DS
);
108 cpu_x86_load_seg(env
, R_DS
, 0);
109 cpu_x86_load_seg(env
, R_ES
, 0);
110 cpu_x86_load_seg(env
, R_FS
, 0);
111 cpu_x86_load_seg(env
, R_GS
, 0);
114 static inline void target_cpu_loop(CPUX86State
*env
)
116 CPUState
*cs
= env_cpu(env
);
119 /* target_siginfo_t info; */
123 trapnr
= cpu_exec(cs
);
125 process_queued_cpu_work(cs
);
129 /* syscall from int $0x80 */
130 if (bsd_type
== target_freebsd
) {
131 abi_ulong params
= (abi_ulong
) env
->regs
[R_ESP
] +
133 int32_t syscall_nr
= env
->regs
[R_EAX
];
134 int32_t arg1
, arg2
, arg3
, arg4
, arg5
, arg6
, arg7
, arg8
;
136 if (syscall_nr
== TARGET_FREEBSD_NR_syscall
) {
137 get_user_s32(syscall_nr
, params
);
138 params
+= sizeof(int32_t);
139 } else if (syscall_nr
== TARGET_FREEBSD_NR___syscall
) {
140 get_user_s32(syscall_nr
, params
);
141 params
+= sizeof(int64_t);
143 get_user_s32(arg1
, params
);
144 params
+= sizeof(int32_t);
145 get_user_s32(arg2
, params
);
146 params
+= sizeof(int32_t);
147 get_user_s32(arg3
, params
);
148 params
+= sizeof(int32_t);
149 get_user_s32(arg4
, params
);
150 params
+= sizeof(int32_t);
151 get_user_s32(arg5
, params
);
152 params
+= sizeof(int32_t);
153 get_user_s32(arg6
, params
);
154 params
+= sizeof(int32_t);
155 get_user_s32(arg7
, params
);
156 params
+= sizeof(int32_t);
157 get_user_s32(arg8
, params
);
158 env
->regs
[R_EAX
] = do_freebsd_syscall(env
,
168 } else { /* if (bsd_type == target_openbsd) */
169 env
->regs
[R_EAX
] = do_openbsd_syscall(env
,
178 if (((abi_ulong
)env
->regs
[R_EAX
]) >= (abi_ulong
)(-515)) {
179 env
->regs
[R_EAX
] = -env
->regs
[R_EAX
];
182 env
->eflags
&= ~CC_C
;
187 /* syscall from syscall instruction */
188 if (bsd_type
== target_freebsd
) {
189 env
->regs
[R_EAX
] = do_freebsd_syscall(env
,
197 } else { /* if (bsd_type == target_openbsd) */
198 env
->regs
[R_EAX
] = do_openbsd_syscall(env
,
207 env
->eip
= env
->exception_next_eip
;
208 if (((abi_ulong
)env
->regs
[R_EAX
]) >= (abi_ulong
)(-515)) {
209 env
->regs
[R_EAX
] = -env
->regs
[R_EAX
];
212 env
->eflags
&= ~CC_C
;
217 /* just indicate that signals should be handled asap */
221 cpu_exec_step_atomic(cs
);
225 pc
= env
->segs
[R_CS
].base
+ env
->eip
;
226 fprintf(stderr
, "qemu: 0x%08lx: unhandled CPU exception 0x%x - "
227 "aborting\n", (long)pc
, trapnr
);
230 process_pending_signals(env
);
234 static inline void target_cpu_clone_regs(CPUX86State
*env
, target_ulong newsp
)
237 env
->regs
[R_ESP
] = newsp
;
239 env
->regs
[R_EAX
] = 0;
242 static inline void target_cpu_reset(CPUArchState
*cpu
)
244 cpu_reset(env_cpu(cpu
));
247 #endif /* ! _TARGET_ARCH_CPU_H_ */