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