1 /*
2 * QEMU PC System Emulator
3 *
4 * Copyright (c) 2003-2004 Fabrice Bellard
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24 /* Modified for Unicorn Engine by Nguyen Anh Quynh, 2015 */
25
26 #include "hw/hw.h"
27 #include "hw/i386/pc.h"
28 #include "sysemu/sysemu.h"
29 #include "qapi-visit.h"
30
31
32 /* XXX: add IGNNE support */
cpu_set_ferr(CPUX86State * s)33 void cpu_set_ferr(CPUX86State *s)
34 {
35 // qemu_irq_raise(ferr_irq);
36 }
37
38 /* TSC handling */
cpu_get_tsc(CPUX86State * env)39 uint64_t cpu_get_tsc(CPUX86State *env)
40 {
41 return cpu_get_ticks();
42 }
43
44 /* SMM support */
45
46 static cpu_set_smm_t smm_set;
47 static void *smm_arg;
48
cpu_smm_register(cpu_set_smm_t callback,void * arg)49 void cpu_smm_register(cpu_set_smm_t callback, void *arg)
50 {
51 assert(smm_set == NULL);
52 assert(smm_arg == NULL);
53 smm_set = callback;
54 smm_arg = arg;
55 }
56
cpu_smm_update(CPUX86State * env)57 void cpu_smm_update(CPUX86State *env)
58 {
59 struct uc_struct *uc = x86_env_get_cpu(env)->parent_obj.uc;
60
61 if (smm_set && smm_arg && CPU(x86_env_get_cpu(env)) == uc->cpu) {
62 smm_set(!!(env->hflags & HF_SMM_MASK), smm_arg);
63 }
64 }
65
66 /* IRQ handling */
cpu_get_pic_interrupt(CPUX86State * env)67 int cpu_get_pic_interrupt(CPUX86State *env)
68 {
69 X86CPU *cpu = x86_env_get_cpu(env);
70 int intno;
71
72 intno = apic_get_interrupt(cpu->apic_state);
73 if (intno >= 0) {
74 return intno;
75 }
76 /* read the irq from the PIC */
77 if (!apic_accept_pic_intr(cpu->apic_state)) {
78 return -1;
79 }
80
81 return 0;
82 }
83
cpu_get_current_apic(struct uc_struct * uc)84 DeviceState *cpu_get_current_apic(struct uc_struct *uc)
85 {
86 if (uc->current_cpu) {
87 X86CPU *cpu = X86_CPU(uc, uc->current_cpu);
88 return cpu->apic_state;
89 } else {
90 return NULL;
91 }
92 }
93
pc_new_cpu(struct uc_struct * uc,const char * cpu_model,int64_t apic_id,Error ** errp)94 static X86CPU *pc_new_cpu(struct uc_struct *uc, const char *cpu_model, int64_t apic_id,
95 Error **errp)
96 {
97 X86CPU *cpu;
98 Error *local_err = NULL;
99
100 cpu = cpu_x86_create(uc, cpu_model, &local_err);
101 if (local_err != NULL) {
102 error_propagate(errp, local_err);
103 return NULL;
104 }
105
106 object_property_set_int(uc, OBJECT(cpu), apic_id, "apic-id", &local_err);
107 object_property_set_bool(uc, OBJECT(cpu), true, "realized", &local_err);
108
109 if (local_err) {
110 error_propagate(errp, local_err);
111 object_unref(uc, OBJECT(cpu));
112 cpu = NULL;
113 }
114 return cpu;
115 }
116
pc_cpus_init(struct uc_struct * uc,const char * cpu_model)117 int pc_cpus_init(struct uc_struct *uc, const char *cpu_model)
118 {
119 int i;
120 Error *error = NULL;
121
122 /* init CPUs */
123 if (cpu_model == NULL) {
124 #ifdef TARGET_X86_64
125 cpu_model = "qemu64";
126 #else
127 cpu_model = "qemu32";
128 #endif
129 }
130
131 for (i = 0; i < smp_cpus; i++) {
132 uc->cpu = (CPUState *)pc_new_cpu(uc, cpu_model, x86_cpu_apic_id_from_index(i), &error);
133 if (error) {
134 //error_report("%s", error_get_pretty(error));
135 error_free(error);
136 return -1;
137 }
138 }
139
140 return 0;
141 }
142
pc_machine_initfn(struct uc_struct * uc,Object * obj,void * opaque)143 static void pc_machine_initfn(struct uc_struct *uc, Object *obj, void *opaque)
144 {
145 }
146
pc_machine_class_init(struct uc_struct * uc,ObjectClass * oc,void * data)147 static void pc_machine_class_init(struct uc_struct *uc, ObjectClass *oc, void *data)
148 {
149 }
150
151 static const TypeInfo pc_machine_info = {
152 TYPE_PC_MACHINE,
153 TYPE_MACHINE,
154
155 sizeof(PCMachineClass),
156 sizeof(PCMachineState),
157 NULL,
158
159 pc_machine_initfn,
160 NULL,
161 NULL,
162
163 NULL,
164
165 pc_machine_class_init,
166 NULL,
167 NULL,
168
169 true,
170
171 NULL,
172 NULL,
173
174 // should this be added somehow?
175 //.interfaces = (InterfaceInfo[]) { { } },
176 };
177
pc_machine_register_types(struct uc_struct * uc)178 void pc_machine_register_types(struct uc_struct *uc)
179 {
180 type_register_static(uc, &pc_machine_info);
181 }
182