1 /* 2 * i386 TCG cpu class initialization 3 * 4 * Copyright (c) 2003 Fabrice Bellard 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 #include "qemu/osdep.h" 21 #include "cpu.h" 22 #include "helper-tcg.h" 23 #include "qemu/accel.h" 24 #include "hw/core/accel-cpu.h" 25 26 #ifndef CONFIG_USER_ONLY 27 #include "sysemu/sysemu.h" 28 #include "qemu/units.h" 29 #include "exec/address-spaces.h" 30 #endif 31 32 /* Frob eflags into and out of the CPU temporary format. */ 33 34 static void x86_cpu_exec_enter(CPUState *cs) 35 { 36 X86CPU *cpu = X86_CPU(cs); 37 CPUX86State *env = &cpu->env; 38 39 CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); 40 env->df = 1 - (2 * ((env->eflags >> 10) & 1)); 41 CC_OP = CC_OP_EFLAGS; 42 env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); 43 } 44 45 static void x86_cpu_exec_exit(CPUState *cs) 46 { 47 X86CPU *cpu = X86_CPU(cs); 48 CPUX86State *env = &cpu->env; 49 50 env->eflags = cpu_compute_eflags(env); 51 } 52 53 static void x86_cpu_synchronize_from_tb(CPUState *cs, 54 const TranslationBlock *tb) 55 { 56 X86CPU *cpu = X86_CPU(cs); 57 58 cpu->env.eip = tb->pc - tb->cs_base; 59 } 60 61 #include "hw/core/tcg-cpu-ops.h" 62 63 static struct TCGCPUOps x86_tcg_ops = { 64 .initialize = tcg_x86_init, 65 .synchronize_from_tb = x86_cpu_synchronize_from_tb, 66 .cpu_exec_enter = x86_cpu_exec_enter, 67 .cpu_exec_exit = x86_cpu_exec_exit, 68 .cpu_exec_interrupt = x86_cpu_exec_interrupt, 69 .do_interrupt = x86_cpu_do_interrupt, 70 .tlb_fill = x86_cpu_tlb_fill, 71 #ifndef CONFIG_USER_ONLY 72 .debug_excp_handler = breakpoint_handler, 73 #endif /* !CONFIG_USER_ONLY */ 74 }; 75 76 static void tcg_cpu_class_init(CPUClass *cc) 77 { 78 cc->tcg_ops = &x86_tcg_ops; 79 } 80 81 #ifndef CONFIG_USER_ONLY 82 83 static void x86_cpu_machine_done(Notifier *n, void *unused) 84 { 85 X86CPU *cpu = container_of(n, X86CPU, machine_done); 86 MemoryRegion *smram = 87 (MemoryRegion *) object_resolve_path("/machine/smram", NULL); 88 89 if (smram) { 90 cpu->smram = g_new(MemoryRegion, 1); 91 memory_region_init_alias(cpu->smram, OBJECT(cpu), "smram", 92 smram, 0, 4 * GiB); 93 memory_region_set_enabled(cpu->smram, true); 94 memory_region_add_subregion_overlap(cpu->cpu_as_root, 0, 95 cpu->smram, 1); 96 } 97 } 98 99 static void tcg_cpu_realizefn(CPUState *cs, Error **errp) 100 { 101 X86CPU *cpu = X86_CPU(cs); 102 103 /* 104 * The realize order is important, since x86_cpu_realize() checks if 105 * nothing else has been set by the user (or by accelerators) in 106 * cpu->ucode_rev and cpu->phys_bits, and the memory regions 107 * initialized here are needed for the vcpu initialization. 108 * 109 * realize order: 110 * tcg_cpu -> host_cpu -> x86_cpu 111 */ 112 cpu->cpu_as_mem = g_new(MemoryRegion, 1); 113 cpu->cpu_as_root = g_new(MemoryRegion, 1); 114 115 /* Outer container... */ 116 memory_region_init(cpu->cpu_as_root, OBJECT(cpu), "memory", ~0ull); 117 memory_region_set_enabled(cpu->cpu_as_root, true); 118 119 /* 120 * ... with two regions inside: normal system memory with low 121 * priority, and... 122 */ 123 memory_region_init_alias(cpu->cpu_as_mem, OBJECT(cpu), "memory", 124 get_system_memory(), 0, ~0ull); 125 memory_region_add_subregion_overlap(cpu->cpu_as_root, 0, cpu->cpu_as_mem, 0); 126 memory_region_set_enabled(cpu->cpu_as_mem, true); 127 128 cs->num_ases = 2; 129 cpu_address_space_init(cs, 0, "cpu-memory", cs->memory); 130 cpu_address_space_init(cs, 1, "cpu-smm", cpu->cpu_as_root); 131 132 /* ... SMRAM with higher priority, linked from /machine/smram. */ 133 cpu->machine_done.notify = x86_cpu_machine_done; 134 qemu_add_machine_init_done_notifier(&cpu->machine_done); 135 } 136 137 #else /* CONFIG_USER_ONLY */ 138 139 static void tcg_cpu_realizefn(CPUState *cs, Error **errp) 140 { 141 } 142 143 #endif /* !CONFIG_USER_ONLY */ 144 145 /* 146 * TCG-specific defaults that override all CPU models when using TCG 147 */ 148 static PropValue tcg_default_props[] = { 149 { "vme", "off" }, 150 { NULL, NULL }, 151 }; 152 153 static void tcg_cpu_instance_init(CPUState *cs) 154 { 155 X86CPU *cpu = X86_CPU(cs); 156 /* Special cases not set in the X86CPUDefinition structs: */ 157 x86_cpu_apply_props(cpu, tcg_default_props); 158 } 159 160 static void tcg_cpu_accel_class_init(ObjectClass *oc, void *data) 161 { 162 AccelCPUClass *acc = ACCEL_CPU_CLASS(oc); 163 164 acc->cpu_realizefn = tcg_cpu_realizefn; 165 acc->cpu_class_init = tcg_cpu_class_init; 166 acc->cpu_instance_init = tcg_cpu_instance_init; 167 } 168 static const TypeInfo tcg_cpu_accel_type_info = { 169 .name = ACCEL_CPU_NAME("tcg"), 170 171 .parent = TYPE_ACCEL_CPU, 172 .class_init = tcg_cpu_accel_class_init, 173 .abstract = true, 174 }; 175 static void tcg_cpu_accel_register_types(void) 176 { 177 type_register_static(&tcg_cpu_accel_type_info); 178 } 179 type_init(tcg_cpu_accel_register_types); 180