1 /* 2 * Copyright (c) 2003-2004 Fabrice Bellard 3 * Copyright (c) 2019 Red Hat, Inc. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a copy 6 * of this software and associated documentation files (the "Software"), to deal 7 * in the Software without restriction, including without limitation the rights 8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 * copies of the Software, and to permit persons to whom the Software is 10 * furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be included in 13 * all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 * THE SOFTWARE. 22 */ 23 #include "qemu/osdep.h" 24 #include "qemu/error-report.h" 25 #include "qemu/units.h" 26 #include "qapi/error.h" 27 #include "qapi/qapi-visit-common.h" 28 #include "qapi/qapi-visit-machine.h" 29 #include "qapi/visitor.h" 30 #include "sysemu/qtest.h" 31 #include "sysemu/numa.h" 32 #include "trace.h" 33 34 #include "hw/acpi/aml-build.h" 35 #include "hw/i386/x86.h" 36 #include "hw/i386/topology.h" 37 38 #include "hw/nmi.h" 39 #include "kvm/kvm_i386.h" 40 41 42 void init_topo_info(X86CPUTopoInfo *topo_info, 43 const X86MachineState *x86ms) 44 { 45 MachineState *ms = MACHINE(x86ms); 46 47 topo_info->dies_per_pkg = ms->smp.dies; 48 topo_info->cores_per_die = ms->smp.cores; 49 topo_info->threads_per_core = ms->smp.threads; 50 } 51 52 /* 53 * Calculates initial APIC ID for a specific CPU index 54 * 55 * Currently we need to be able to calculate the APIC ID from the CPU index 56 * alone (without requiring a CPU object), as the QEMU<->Seabios interfaces have 57 * no concept of "CPU index", and the NUMA tables on fw_cfg need the APIC ID of 58 * all CPUs up to max_cpus. 59 */ 60 uint32_t x86_cpu_apic_id_from_index(X86MachineState *x86ms, 61 unsigned int cpu_index) 62 { 63 X86CPUTopoInfo topo_info; 64 65 init_topo_info(&topo_info, x86ms); 66 67 return x86_apicid_from_cpu_idx(&topo_info, cpu_index); 68 } 69 70 static CpuInstanceProperties 71 x86_cpu_index_to_props(MachineState *ms, unsigned cpu_index) 72 { 73 MachineClass *mc = MACHINE_GET_CLASS(ms); 74 const CPUArchIdList *possible_cpus = mc->possible_cpu_arch_ids(ms); 75 76 assert(cpu_index < possible_cpus->len); 77 return possible_cpus->cpus[cpu_index].props; 78 } 79 80 static int64_t x86_get_default_cpu_node_id(const MachineState *ms, int idx) 81 { 82 X86CPUTopoIDs topo_ids; 83 X86MachineState *x86ms = X86_MACHINE(ms); 84 X86CPUTopoInfo topo_info; 85 86 init_topo_info(&topo_info, x86ms); 87 88 assert(idx < ms->possible_cpus->len); 89 x86_topo_ids_from_apicid(ms->possible_cpus->cpus[idx].arch_id, 90 &topo_info, &topo_ids); 91 return topo_ids.pkg_id % ms->numa_state->num_nodes; 92 } 93 94 static const CPUArchIdList *x86_possible_cpu_arch_ids(MachineState *ms) 95 { 96 X86MachineState *x86ms = X86_MACHINE(ms); 97 unsigned int max_cpus = ms->smp.max_cpus; 98 X86CPUTopoInfo topo_info; 99 int i; 100 101 if (ms->possible_cpus) { 102 /* 103 * make sure that max_cpus hasn't changed since the first use, i.e. 104 * -smp hasn't been parsed after it 105 */ 106 assert(ms->possible_cpus->len == max_cpus); 107 return ms->possible_cpus; 108 } 109 110 ms->possible_cpus = g_malloc0(sizeof(CPUArchIdList) + 111 sizeof(CPUArchId) * max_cpus); 112 ms->possible_cpus->len = max_cpus; 113 114 init_topo_info(&topo_info, x86ms); 115 116 for (i = 0; i < ms->possible_cpus->len; i++) { 117 X86CPUTopoIDs topo_ids; 118 119 ms->possible_cpus->cpus[i].type = ms->cpu_type; 120 ms->possible_cpus->cpus[i].vcpus_count = 1; 121 ms->possible_cpus->cpus[i].arch_id = 122 x86_cpu_apic_id_from_index(x86ms, i); 123 x86_topo_ids_from_apicid(ms->possible_cpus->cpus[i].arch_id, 124 &topo_info, &topo_ids); 125 ms->possible_cpus->cpus[i].props.has_socket_id = true; 126 ms->possible_cpus->cpus[i].props.socket_id = topo_ids.pkg_id; 127 if (ms->smp.dies > 1) { 128 ms->possible_cpus->cpus[i].props.has_die_id = true; 129 ms->possible_cpus->cpus[i].props.die_id = topo_ids.die_id; 130 } 131 ms->possible_cpus->cpus[i].props.has_core_id = true; 132 ms->possible_cpus->cpus[i].props.core_id = topo_ids.core_id; 133 ms->possible_cpus->cpus[i].props.has_thread_id = true; 134 ms->possible_cpus->cpus[i].props.thread_id = topo_ids.smt_id; 135 } 136 return ms->possible_cpus; 137 } 138 139 static void x86_nmi(NMIState *n, int cpu_index, Error **errp) 140 { 141 /* cpu index isn't used */ 142 CPUState *cs; 143 144 CPU_FOREACH(cs) { 145 X86CPU *cpu = X86_CPU(cs); 146 147 if (cpu_is_apic_enabled(cpu->apic_state)) { 148 apic_deliver_nmi(cpu->apic_state); 149 } else { 150 cpu_interrupt(cs, CPU_INTERRUPT_NMI); 151 } 152 } 153 } 154 155 bool x86_machine_is_smm_enabled(const X86MachineState *x86ms) 156 { 157 bool smm_available = false; 158 159 if (x86ms->smm == ON_OFF_AUTO_OFF) { 160 return false; 161 } 162 163 if (tcg_enabled() || qtest_enabled()) { 164 smm_available = true; 165 } else if (kvm_enabled()) { 166 smm_available = kvm_has_smm(); 167 } 168 169 if (smm_available) { 170 return true; 171 } 172 173 if (x86ms->smm == ON_OFF_AUTO_ON) { 174 error_report("System Management Mode not supported by this hypervisor."); 175 exit(1); 176 } 177 return false; 178 } 179 180 static void x86_machine_get_smm(Object *obj, Visitor *v, const char *name, 181 void *opaque, Error **errp) 182 { 183 X86MachineState *x86ms = X86_MACHINE(obj); 184 OnOffAuto smm = x86ms->smm; 185 186 visit_type_OnOffAuto(v, name, &smm, errp); 187 } 188 189 static void x86_machine_set_smm(Object *obj, Visitor *v, const char *name, 190 void *opaque, Error **errp) 191 { 192 X86MachineState *x86ms = X86_MACHINE(obj); 193 194 visit_type_OnOffAuto(v, name, &x86ms->smm, errp); 195 } 196 197 bool x86_machine_is_acpi_enabled(const X86MachineState *x86ms) 198 { 199 if (x86ms->acpi == ON_OFF_AUTO_OFF) { 200 return false; 201 } 202 return true; 203 } 204 205 static void x86_machine_get_acpi(Object *obj, Visitor *v, const char *name, 206 void *opaque, Error **errp) 207 { 208 X86MachineState *x86ms = X86_MACHINE(obj); 209 OnOffAuto acpi = x86ms->acpi; 210 211 visit_type_OnOffAuto(v, name, &acpi, errp); 212 } 213 214 static void x86_machine_set_acpi(Object *obj, Visitor *v, const char *name, 215 void *opaque, Error **errp) 216 { 217 X86MachineState *x86ms = X86_MACHINE(obj); 218 219 visit_type_OnOffAuto(v, name, &x86ms->acpi, errp); 220 } 221 222 static void x86_machine_get_pit(Object *obj, Visitor *v, const char *name, 223 void *opaque, Error **errp) 224 { 225 X86MachineState *x86ms = X86_MACHINE(obj); 226 OnOffAuto pit = x86ms->pit; 227 228 visit_type_OnOffAuto(v, name, &pit, errp); 229 } 230 231 static void x86_machine_set_pit(Object *obj, Visitor *v, const char *name, 232 void *opaque, Error **errp) 233 { 234 X86MachineState *x86ms = X86_MACHINE(obj);; 235 236 visit_type_OnOffAuto(v, name, &x86ms->pit, errp); 237 } 238 239 static void x86_machine_get_pic(Object *obj, Visitor *v, const char *name, 240 void *opaque, Error **errp) 241 { 242 X86MachineState *x86ms = X86_MACHINE(obj); 243 OnOffAuto pic = x86ms->pic; 244 245 visit_type_OnOffAuto(v, name, &pic, errp); 246 } 247 248 static void x86_machine_set_pic(Object *obj, Visitor *v, const char *name, 249 void *opaque, Error **errp) 250 { 251 X86MachineState *x86ms = X86_MACHINE(obj); 252 253 visit_type_OnOffAuto(v, name, &x86ms->pic, errp); 254 } 255 256 static char *x86_machine_get_oem_id(Object *obj, Error **errp) 257 { 258 X86MachineState *x86ms = X86_MACHINE(obj); 259 260 return g_strdup(x86ms->oem_id); 261 } 262 263 static void x86_machine_set_oem_id(Object *obj, const char *value, Error **errp) 264 { 265 X86MachineState *x86ms = X86_MACHINE(obj); 266 size_t len = strlen(value); 267 268 if (len > 6) { 269 error_setg(errp, 270 "User specified "X86_MACHINE_OEM_ID" value is bigger than " 271 "6 bytes in size"); 272 return; 273 } 274 275 strncpy(x86ms->oem_id, value, 6); 276 } 277 278 static char *x86_machine_get_oem_table_id(Object *obj, Error **errp) 279 { 280 X86MachineState *x86ms = X86_MACHINE(obj); 281 282 return g_strdup(x86ms->oem_table_id); 283 } 284 285 static void x86_machine_set_oem_table_id(Object *obj, const char *value, 286 Error **errp) 287 { 288 X86MachineState *x86ms = X86_MACHINE(obj); 289 size_t len = strlen(value); 290 291 if (len > 8) { 292 error_setg(errp, 293 "User specified "X86_MACHINE_OEM_TABLE_ID 294 " value is bigger than " 295 "8 bytes in size"); 296 return; 297 } 298 strncpy(x86ms->oem_table_id, value, 8); 299 } 300 301 static void x86_machine_get_bus_lock_ratelimit(Object *obj, Visitor *v, 302 const char *name, void *opaque, Error **errp) 303 { 304 X86MachineState *x86ms = X86_MACHINE(obj); 305 uint64_t bus_lock_ratelimit = x86ms->bus_lock_ratelimit; 306 307 visit_type_uint64(v, name, &bus_lock_ratelimit, errp); 308 } 309 310 static void x86_machine_set_bus_lock_ratelimit(Object *obj, Visitor *v, 311 const char *name, void *opaque, Error **errp) 312 { 313 X86MachineState *x86ms = X86_MACHINE(obj); 314 315 visit_type_uint64(v, name, &x86ms->bus_lock_ratelimit, errp); 316 } 317 318 static void machine_get_sgx_epc(Object *obj, Visitor *v, const char *name, 319 void *opaque, Error **errp) 320 { 321 X86MachineState *x86ms = X86_MACHINE(obj); 322 SgxEPCList *list = x86ms->sgx_epc_list; 323 324 visit_type_SgxEPCList(v, name, &list, errp); 325 } 326 327 static void machine_set_sgx_epc(Object *obj, Visitor *v, const char *name, 328 void *opaque, Error **errp) 329 { 330 X86MachineState *x86ms = X86_MACHINE(obj); 331 SgxEPCList *list; 332 333 list = x86ms->sgx_epc_list; 334 visit_type_SgxEPCList(v, name, &x86ms->sgx_epc_list, errp); 335 336 qapi_free_SgxEPCList(list); 337 } 338 339 static int x86_kvm_type(MachineState *ms, const char *vm_type) 340 { 341 /* 342 * No x86 machine has a kvm-type property. If one is added that has 343 * it, it should call kvm_get_vm_type() directly or not use it at all. 344 */ 345 assert(vm_type == NULL); 346 return kvm_enabled() ? kvm_get_vm_type(ms) : 0; 347 } 348 349 static void x86_machine_initfn(Object *obj) 350 { 351 X86MachineState *x86ms = X86_MACHINE(obj); 352 353 x86ms->smm = ON_OFF_AUTO_AUTO; 354 x86ms->acpi = ON_OFF_AUTO_AUTO; 355 x86ms->pit = ON_OFF_AUTO_AUTO; 356 x86ms->pic = ON_OFF_AUTO_AUTO; 357 x86ms->pci_irq_mask = ACPI_BUILD_PCI_IRQS; 358 x86ms->oem_id = g_strndup(ACPI_BUILD_APPNAME6, 6); 359 x86ms->oem_table_id = g_strndup(ACPI_BUILD_APPNAME8, 8); 360 x86ms->bus_lock_ratelimit = 0; 361 x86ms->above_4g_mem_start = 4 * GiB; 362 } 363 364 static void x86_machine_class_init(ObjectClass *oc, void *data) 365 { 366 MachineClass *mc = MACHINE_CLASS(oc); 367 X86MachineClass *x86mc = X86_MACHINE_CLASS(oc); 368 NMIClass *nc = NMI_CLASS(oc); 369 370 mc->cpu_index_to_instance_props = x86_cpu_index_to_props; 371 mc->get_default_cpu_node_id = x86_get_default_cpu_node_id; 372 mc->possible_cpu_arch_ids = x86_possible_cpu_arch_ids; 373 mc->kvm_type = x86_kvm_type; 374 x86mc->save_tsc_khz = true; 375 x86mc->fwcfg_dma_enabled = true; 376 nc->nmi_monitor_handler = x86_nmi; 377 378 object_class_property_add(oc, X86_MACHINE_SMM, "OnOffAuto", 379 x86_machine_get_smm, x86_machine_set_smm, 380 NULL, NULL); 381 object_class_property_set_description(oc, X86_MACHINE_SMM, 382 "Enable SMM"); 383 384 object_class_property_add(oc, X86_MACHINE_ACPI, "OnOffAuto", 385 x86_machine_get_acpi, x86_machine_set_acpi, 386 NULL, NULL); 387 object_class_property_set_description(oc, X86_MACHINE_ACPI, 388 "Enable ACPI"); 389 390 object_class_property_add(oc, X86_MACHINE_PIT, "OnOffAuto", 391 x86_machine_get_pit, 392 x86_machine_set_pit, 393 NULL, NULL); 394 object_class_property_set_description(oc, X86_MACHINE_PIT, 395 "Enable i8254 PIT"); 396 397 object_class_property_add(oc, X86_MACHINE_PIC, "OnOffAuto", 398 x86_machine_get_pic, 399 x86_machine_set_pic, 400 NULL, NULL); 401 object_class_property_set_description(oc, X86_MACHINE_PIC, 402 "Enable i8259 PIC"); 403 404 object_class_property_add_str(oc, X86_MACHINE_OEM_ID, 405 x86_machine_get_oem_id, 406 x86_machine_set_oem_id); 407 object_class_property_set_description(oc, X86_MACHINE_OEM_ID, 408 "Override the default value of field OEMID " 409 "in ACPI table header." 410 "The string may be up to 6 bytes in size"); 411 412 413 object_class_property_add_str(oc, X86_MACHINE_OEM_TABLE_ID, 414 x86_machine_get_oem_table_id, 415 x86_machine_set_oem_table_id); 416 object_class_property_set_description(oc, X86_MACHINE_OEM_TABLE_ID, 417 "Override the default value of field OEM Table ID " 418 "in ACPI table header." 419 "The string may be up to 8 bytes in size"); 420 421 object_class_property_add(oc, X86_MACHINE_BUS_LOCK_RATELIMIT, "uint64_t", 422 x86_machine_get_bus_lock_ratelimit, 423 x86_machine_set_bus_lock_ratelimit, NULL, NULL); 424 object_class_property_set_description(oc, X86_MACHINE_BUS_LOCK_RATELIMIT, 425 "Set the ratelimit for the bus locks acquired in VMs"); 426 427 object_class_property_add(oc, "sgx-epc", "SgxEPC", 428 machine_get_sgx_epc, machine_set_sgx_epc, 429 NULL, NULL); 430 object_class_property_set_description(oc, "sgx-epc", 431 "SGX EPC device"); 432 } 433 434 static const TypeInfo x86_machine_info = { 435 .name = TYPE_X86_MACHINE, 436 .parent = TYPE_MACHINE, 437 .abstract = true, 438 .instance_size = sizeof(X86MachineState), 439 .instance_init = x86_machine_initfn, 440 .class_size = sizeof(X86MachineClass), 441 .class_init = x86_machine_class_init, 442 .interfaces = (InterfaceInfo[]) { 443 { TYPE_NMI }, 444 { } 445 }, 446 }; 447 448 static void x86_machine_register_types(void) 449 { 450 type_register_static(&x86_machine_info); 451 } 452 453 type_init(x86_machine_register_types) 454