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 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 /* enable 64 bit mode if possible */
39 if (!(env
->features
[FEAT_8000_0001_EDX
] & CPUID_EXT2_LM
)) {
40 fprintf(stderr
, "The selected x86 CPU does not support 64 bit mode\n");
43 env
->cr
[4] |= CR4_PAE_MASK
;
44 env
->efer
|= MSR_EFER_LMA
| MSR_EFER_LME
;
45 env
->hflags
|= HF_LMA_MASK
;
47 /* flags setup : we activate the IRQs by default as in user mode */
48 env
->eflags
|= IF_MASK
;
51 env
->regs
[R_EAX
] = regs
->rax
;
52 env
->regs
[R_EBX
] = regs
->rbx
;
53 env
->regs
[R_ECX
] = regs
->rcx
;
54 env
->regs
[R_EDX
] = regs
->rdx
;
55 env
->regs
[R_ESI
] = regs
->rsi
;
56 env
->regs
[R_EDI
] = regs
->rdi
;
57 env
->regs
[R_EBP
] = regs
->rbp
;
58 env
->regs
[R_ESP
] = regs
->rsp
;
64 env
->idt
.base
= target_mmap(0, sizeof(uint64_t) * (env
->idt
.limit
+ 1),
65 PROT_READ
| PROT_WRITE
, MAP_ANONYMOUS
| MAP_PRIVATE
, -1, 0);
66 bsd_x86_64_set_idt_base(env
->idt
.base
);
67 bsd_x86_64_set_idt(0, 0);
68 bsd_x86_64_set_idt(1, 0);
69 bsd_x86_64_set_idt(2, 0);
70 bsd_x86_64_set_idt(3, 3);
71 bsd_x86_64_set_idt(4, 3);
72 bsd_x86_64_set_idt(5, 0);
73 bsd_x86_64_set_idt(6, 0);
74 bsd_x86_64_set_idt(7, 0);
75 bsd_x86_64_set_idt(8, 0);
76 bsd_x86_64_set_idt(9, 0);
77 bsd_x86_64_set_idt(10, 0);
78 bsd_x86_64_set_idt(11, 0);
79 bsd_x86_64_set_idt(12, 0);
80 bsd_x86_64_set_idt(13, 0);
81 bsd_x86_64_set_idt(14, 0);
82 bsd_x86_64_set_idt(15, 0);
83 bsd_x86_64_set_idt(16, 0);
84 bsd_x86_64_set_idt(17, 0);
85 bsd_x86_64_set_idt(18, 0);
86 bsd_x86_64_set_idt(19, 0);
87 bsd_x86_64_set_idt(0x80, 3);
90 env
->gdt
.base
= target_mmap(0, sizeof(uint64_t) * TARGET_GDT_ENTRIES
,
91 PROT_READ
| PROT_WRITE
, MAP_ANONYMOUS
| MAP_PRIVATE
, -1, 0);
92 env
->gdt
.limit
= sizeof(uint64_t) * TARGET_GDT_ENTRIES
- 1;
93 gdt_table
= g2h_untagged(env
->gdt
.base
);
95 /* 64 bit code segment */
96 bsd_x86_64_write_dt(&gdt_table
[__USER_CS
>> 3], 0, 0xfffff,
97 DESC_G_MASK
| DESC_B_MASK
| DESC_P_MASK
| DESC_S_MASK
| DESC_L_MASK
98 | (3 << DESC_DPL_SHIFT
) | (0xa << DESC_TYPE_SHIFT
));
100 bsd_x86_64_write_dt(&gdt_table
[__USER_DS
>> 3], 0, 0xfffff,
101 DESC_G_MASK
| DESC_B_MASK
| DESC_P_MASK
| DESC_S_MASK
|
102 (3 << DESC_DPL_SHIFT
) | (0x2 << DESC_TYPE_SHIFT
));
104 cpu_x86_load_seg(env
, R_CS
, __USER_CS
);
105 cpu_x86_load_seg(env
, R_SS
, __USER_DS
);
106 cpu_x86_load_seg(env
, R_DS
, 0);
107 cpu_x86_load_seg(env
, R_ES
, 0);
108 cpu_x86_load_seg(env
, R_FS
, 0);
109 cpu_x86_load_seg(env
, R_GS
, 0);
112 static inline void target_cpu_loop(CPUX86State
*env
)
114 CPUState
*cs
= env_cpu(env
);
117 /* target_siginfo_t info; */
121 trapnr
= cpu_exec(cs
);
123 process_queued_cpu_work(cs
);
127 /* syscall from int $0x80 */
128 if (bsd_type
== target_freebsd
) {
129 abi_ulong params
= (abi_ulong
) env
->regs
[R_ESP
] +
131 int32_t syscall_nr
= env
->regs
[R_EAX
];
132 int32_t arg1
, arg2
, arg3
, arg4
, arg5
, arg6
, arg7
, arg8
;
134 if (syscall_nr
== TARGET_FREEBSD_NR_syscall
) {
135 get_user_s32(syscall_nr
, params
);
136 params
+= sizeof(int32_t);
137 } else if (syscall_nr
== TARGET_FREEBSD_NR___syscall
) {
138 get_user_s32(syscall_nr
, params
);
139 params
+= sizeof(int64_t);
141 get_user_s32(arg1
, params
);
142 params
+= sizeof(int32_t);
143 get_user_s32(arg2
, params
);
144 params
+= sizeof(int32_t);
145 get_user_s32(arg3
, params
);
146 params
+= sizeof(int32_t);
147 get_user_s32(arg4
, params
);
148 params
+= sizeof(int32_t);
149 get_user_s32(arg5
, params
);
150 params
+= sizeof(int32_t);
151 get_user_s32(arg6
, params
);
152 params
+= sizeof(int32_t);
153 get_user_s32(arg7
, params
);
154 params
+= sizeof(int32_t);
155 get_user_s32(arg8
, params
);
156 env
->regs
[R_EAX
] = do_freebsd_syscall(env
,
166 } else { /* if (bsd_type == target_openbsd) */
167 env
->regs
[R_EAX
] = do_openbsd_syscall(env
,
176 if (((abi_ulong
)env
->regs
[R_EAX
]) >= (abi_ulong
)(-515)) {
177 env
->regs
[R_EAX
] = -env
->regs
[R_EAX
];
180 env
->eflags
&= ~CC_C
;
185 /* syscall from syscall instruction */
186 if (bsd_type
== target_freebsd
) {
187 env
->regs
[R_EAX
] = do_freebsd_syscall(env
,
195 } else { /* if (bsd_type == target_openbsd) */
196 env
->regs
[R_EAX
] = do_openbsd_syscall(env
,
205 env
->eip
= env
->exception_next_eip
;
206 if (((abi_ulong
)env
->regs
[R_EAX
]) >= (abi_ulong
)(-515)) {
207 env
->regs
[R_EAX
] = -env
->regs
[R_EAX
];
210 env
->eflags
&= ~CC_C
;
215 /* just indicate that signals should be handled asap */
219 cpu_exec_step_atomic(cs
);
223 pc
= env
->segs
[R_CS
].base
+ env
->eip
;
224 fprintf(stderr
, "qemu: 0x%08lx: unhandled CPU exception 0x%x - "
225 "aborting\n", (long)pc
, trapnr
);
228 process_pending_signals(env
);
232 static inline void target_cpu_clone_regs(CPUX86State
*env
, target_ulong newsp
)
235 env
->regs
[R_ESP
] = newsp
;
237 env
->regs
[R_EAX
] = 0;
240 static inline void target_cpu_reset(CPUArchState
*cpu
)
242 cpu_reset(env_cpu(cpu
));
245 #endif /* ! _TARGET_ARCH_CPU_H_ */