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 /* 49 * Though smp.modules means the number of modules in one cluster, 50 * i386 doesn't support cluster level so that the smp.clusters 51 * always defaults to 1, therefore using smp.modules directly is 52 * fine here. 53 */ 54 topo_info->modules_per_die = ms->smp.modules; 55 topo_info->cores_per_module = ms->smp.cores; 56 topo_info->threads_per_core = ms->smp.threads; 57 } 58 59 /* 60 * Calculates initial APIC ID for a specific CPU index 61 * 62 * Currently we need to be able to calculate the APIC ID from the CPU index 63 * alone (without requiring a CPU object), as the QEMU<->Seabios interfaces have 64 * no concept of "CPU index", and the NUMA tables on fw_cfg need the APIC ID of 65 * all CPUs up to max_cpus. 66 */ 67 uint32_t x86_cpu_apic_id_from_index(X86MachineState *x86ms, 68 unsigned int cpu_index) 69 { 70 X86CPUTopoInfo topo_info; 71 72 init_topo_info(&topo_info, x86ms); 73 74 return x86_apicid_from_cpu_idx(&topo_info, cpu_index); 75 } 76 77 static CpuInstanceProperties 78 x86_cpu_index_to_props(MachineState *ms, unsigned cpu_index) 79 { 80 MachineClass *mc = MACHINE_GET_CLASS(ms); 81 const CPUArchIdList *possible_cpus = mc->possible_cpu_arch_ids(ms); 82 83 assert(cpu_index < possible_cpus->len); 84 return possible_cpus->cpus[cpu_index].props; 85 } 86 87 static int64_t x86_get_default_cpu_node_id(const MachineState *ms, int idx) 88 { 89 X86CPUTopoIDs topo_ids; 90 X86MachineState *x86ms = X86_MACHINE(ms); 91 X86CPUTopoInfo topo_info; 92 93 init_topo_info(&topo_info, x86ms); 94 95 assert(idx < ms->possible_cpus->len); 96 x86_topo_ids_from_apicid(ms->possible_cpus->cpus[idx].arch_id, 97 &topo_info, &topo_ids); 98 return topo_ids.pkg_id % ms->numa_state->num_nodes; 99 } 100 101 static const CPUArchIdList *x86_possible_cpu_arch_ids(MachineState *ms) 102 { 103 X86MachineState *x86ms = X86_MACHINE(ms); 104 unsigned int max_cpus = ms->smp.max_cpus; 105 X86CPUTopoInfo topo_info; 106 int i; 107 108 if (ms->possible_cpus) { 109 /* 110 * make sure that max_cpus hasn't changed since the first use, i.e. 111 * -smp hasn't been parsed after it 112 */ 113 assert(ms->possible_cpus->len == max_cpus); 114 return ms->possible_cpus; 115 } 116 117 ms->possible_cpus = g_malloc0(sizeof(CPUArchIdList) + 118 sizeof(CPUArchId) * max_cpus); 119 ms->possible_cpus->len = max_cpus; 120 121 init_topo_info(&topo_info, x86ms); 122 123 for (i = 0; i < ms->possible_cpus->len; i++) { 124 X86CPUTopoIDs topo_ids; 125 126 ms->possible_cpus->cpus[i].type = ms->cpu_type; 127 ms->possible_cpus->cpus[i].vcpus_count = 1; 128 ms->possible_cpus->cpus[i].arch_id = 129 x86_cpu_apic_id_from_index(x86ms, i); 130 x86_topo_ids_from_apicid(ms->possible_cpus->cpus[i].arch_id, 131 &topo_info, &topo_ids); 132 ms->possible_cpus->cpus[i].props.has_socket_id = true; 133 ms->possible_cpus->cpus[i].props.socket_id = topo_ids.pkg_id; 134 if (ms->smp.dies > 1) { 135 ms->possible_cpus->cpus[i].props.has_die_id = true; 136 ms->possible_cpus->cpus[i].props.die_id = topo_ids.die_id; 137 } 138 if (ms->smp.modules > 1) { 139 ms->possible_cpus->cpus[i].props.has_module_id = true; 140 ms->possible_cpus->cpus[i].props.module_id = topo_ids.module_id; 141 } 142 ms->possible_cpus->cpus[i].props.has_core_id = true; 143 ms->possible_cpus->cpus[i].props.core_id = topo_ids.core_id; 144 ms->possible_cpus->cpus[i].props.has_thread_id = true; 145 ms->possible_cpus->cpus[i].props.thread_id = topo_ids.smt_id; 146 } 147 return ms->possible_cpus; 148 } 149 150 static void x86_nmi(NMIState *n, int cpu_index, Error **errp) 151 { 152 /* cpu index isn't used */ 153 CPUState *cs; 154 155 CPU_FOREACH(cs) { 156 X86CPU *cpu = X86_CPU(cs); 157 158 if (cpu_is_apic_enabled(cpu->apic_state)) { 159 apic_deliver_nmi(cpu->apic_state); 160 } else { 161 cpu_interrupt(cs, CPU_INTERRUPT_NMI); 162 } 163 } 164 } 165 166 bool x86_machine_is_smm_enabled(const X86MachineState *x86ms) 167 { 168 bool smm_available = false; 169 170 if (x86ms->smm == ON_OFF_AUTO_OFF) { 171 return false; 172 } 173 174 if (tcg_enabled() || qtest_enabled()) { 175 smm_available = true; 176 } else if (kvm_enabled()) { 177 smm_available = kvm_has_smm(); 178 } 179 180 if (smm_available) { 181 return true; 182 } 183 184 if (x86ms->smm == ON_OFF_AUTO_ON) { 185 error_report("System Management Mode not supported by this hypervisor."); 186 exit(1); 187 } 188 return false; 189 } 190 191 static void x86_machine_get_smm(Object *obj, Visitor *v, const char *name, 192 void *opaque, Error **errp) 193 { 194 X86MachineState *x86ms = X86_MACHINE(obj); 195 OnOffAuto smm = x86ms->smm; 196 197 visit_type_OnOffAuto(v, name, &smm, errp); 198 } 199 200 static void x86_machine_set_smm(Object *obj, Visitor *v, const char *name, 201 void *opaque, Error **errp) 202 { 203 X86MachineState *x86ms = X86_MACHINE(obj); 204 205 visit_type_OnOffAuto(v, name, &x86ms->smm, errp); 206 } 207 208 bool x86_machine_is_acpi_enabled(const X86MachineState *x86ms) 209 { 210 if (x86ms->acpi == ON_OFF_AUTO_OFF) { 211 return false; 212 } 213 return true; 214 } 215 216 static void x86_machine_get_acpi(Object *obj, Visitor *v, const char *name, 217 void *opaque, Error **errp) 218 { 219 X86MachineState *x86ms = X86_MACHINE(obj); 220 OnOffAuto acpi = x86ms->acpi; 221 222 visit_type_OnOffAuto(v, name, &acpi, errp); 223 } 224 225 static void x86_machine_set_acpi(Object *obj, Visitor *v, const char *name, 226 void *opaque, Error **errp) 227 { 228 X86MachineState *x86ms = X86_MACHINE(obj); 229 230 visit_type_OnOffAuto(v, name, &x86ms->acpi, errp); 231 } 232 233 static void x86_machine_get_pit(Object *obj, Visitor *v, const char *name, 234 void *opaque, Error **errp) 235 { 236 X86MachineState *x86ms = X86_MACHINE(obj); 237 OnOffAuto pit = x86ms->pit; 238 239 visit_type_OnOffAuto(v, name, &pit, errp); 240 } 241 242 static void x86_machine_set_pit(Object *obj, Visitor *v, const char *name, 243 void *opaque, Error **errp) 244 { 245 X86MachineState *x86ms = X86_MACHINE(obj);; 246 247 visit_type_OnOffAuto(v, name, &x86ms->pit, errp); 248 } 249 250 static void x86_machine_get_pic(Object *obj, Visitor *v, const char *name, 251 void *opaque, Error **errp) 252 { 253 X86MachineState *x86ms = X86_MACHINE(obj); 254 OnOffAuto pic = x86ms->pic; 255 256 visit_type_OnOffAuto(v, name, &pic, errp); 257 } 258 259 static void x86_machine_set_pic(Object *obj, Visitor *v, const char *name, 260 void *opaque, Error **errp) 261 { 262 X86MachineState *x86ms = X86_MACHINE(obj); 263 264 visit_type_OnOffAuto(v, name, &x86ms->pic, errp); 265 } 266 267 static char *x86_machine_get_oem_id(Object *obj, Error **errp) 268 { 269 X86MachineState *x86ms = X86_MACHINE(obj); 270 271 return g_strdup(x86ms->oem_id); 272 } 273 274 static void x86_machine_set_oem_id(Object *obj, const char *value, Error **errp) 275 { 276 X86MachineState *x86ms = X86_MACHINE(obj); 277 size_t len = strlen(value); 278 279 if (len > 6) { 280 error_setg(errp, 281 "User specified "X86_MACHINE_OEM_ID" value is bigger than " 282 "6 bytes in size"); 283 return; 284 } 285 286 strncpy(x86ms->oem_id, value, 6); 287 } 288 289 static char *x86_machine_get_oem_table_id(Object *obj, Error **errp) 290 { 291 X86MachineState *x86ms = X86_MACHINE(obj); 292 293 return g_strdup(x86ms->oem_table_id); 294 } 295 296 static void x86_machine_set_oem_table_id(Object *obj, const char *value, 297 Error **errp) 298 { 299 X86MachineState *x86ms = X86_MACHINE(obj); 300 size_t len = strlen(value); 301 302 if (len > 8) { 303 error_setg(errp, 304 "User specified "X86_MACHINE_OEM_TABLE_ID 305 " value is bigger than " 306 "8 bytes in size"); 307 return; 308 } 309 strncpy(x86ms->oem_table_id, value, 8); 310 } 311 312 static void x86_machine_get_bus_lock_ratelimit(Object *obj, Visitor *v, 313 const char *name, void *opaque, Error **errp) 314 { 315 X86MachineState *x86ms = X86_MACHINE(obj); 316 uint64_t bus_lock_ratelimit = x86ms->bus_lock_ratelimit; 317 318 visit_type_uint64(v, name, &bus_lock_ratelimit, errp); 319 } 320 321 static void x86_machine_set_bus_lock_ratelimit(Object *obj, Visitor *v, 322 const char *name, void *opaque, Error **errp) 323 { 324 X86MachineState *x86ms = X86_MACHINE(obj); 325 326 visit_type_uint64(v, name, &x86ms->bus_lock_ratelimit, errp); 327 } 328 329 static void machine_get_sgx_epc(Object *obj, Visitor *v, const char *name, 330 void *opaque, Error **errp) 331 { 332 X86MachineState *x86ms = X86_MACHINE(obj); 333 SgxEPCList *list = x86ms->sgx_epc_list; 334 335 visit_type_SgxEPCList(v, name, &list, errp); 336 } 337 338 static void machine_set_sgx_epc(Object *obj, Visitor *v, const char *name, 339 void *opaque, Error **errp) 340 { 341 X86MachineState *x86ms = X86_MACHINE(obj); 342 SgxEPCList *list; 343 344 list = x86ms->sgx_epc_list; 345 visit_type_SgxEPCList(v, name, &x86ms->sgx_epc_list, errp); 346 347 qapi_free_SgxEPCList(list); 348 } 349 350 static int x86_kvm_type(MachineState *ms, const char *vm_type) 351 { 352 /* 353 * No x86 machine has a kvm-type property. If one is added that has 354 * it, it should call kvm_get_vm_type() directly or not use it at all. 355 */ 356 assert(vm_type == NULL); 357 return kvm_enabled() ? kvm_get_vm_type(ms) : 0; 358 } 359 360 static void x86_machine_initfn(Object *obj) 361 { 362 X86MachineState *x86ms = X86_MACHINE(obj); 363 364 x86ms->smm = ON_OFF_AUTO_AUTO; 365 x86ms->acpi = ON_OFF_AUTO_AUTO; 366 x86ms->pit = ON_OFF_AUTO_AUTO; 367 x86ms->pic = ON_OFF_AUTO_AUTO; 368 x86ms->pci_irq_mask = ACPI_BUILD_PCI_IRQS; 369 x86ms->oem_id = g_strndup(ACPI_BUILD_APPNAME6, 6); 370 x86ms->oem_table_id = g_strndup(ACPI_BUILD_APPNAME8, 8); 371 x86ms->bus_lock_ratelimit = 0; 372 x86ms->above_4g_mem_start = 4 * GiB; 373 } 374 375 static void x86_machine_class_init(ObjectClass *oc, void *data) 376 { 377 MachineClass *mc = MACHINE_CLASS(oc); 378 X86MachineClass *x86mc = X86_MACHINE_CLASS(oc); 379 NMIClass *nc = NMI_CLASS(oc); 380 381 mc->cpu_index_to_instance_props = x86_cpu_index_to_props; 382 mc->get_default_cpu_node_id = x86_get_default_cpu_node_id; 383 mc->possible_cpu_arch_ids = x86_possible_cpu_arch_ids; 384 mc->kvm_type = x86_kvm_type; 385 x86mc->save_tsc_khz = true; 386 x86mc->fwcfg_dma_enabled = true; 387 nc->nmi_monitor_handler = x86_nmi; 388 389 object_class_property_add(oc, X86_MACHINE_SMM, "OnOffAuto", 390 x86_machine_get_smm, x86_machine_set_smm, 391 NULL, NULL); 392 object_class_property_set_description(oc, X86_MACHINE_SMM, 393 "Enable SMM"); 394 395 object_class_property_add(oc, X86_MACHINE_ACPI, "OnOffAuto", 396 x86_machine_get_acpi, x86_machine_set_acpi, 397 NULL, NULL); 398 object_class_property_set_description(oc, X86_MACHINE_ACPI, 399 "Enable ACPI"); 400 401 object_class_property_add(oc, X86_MACHINE_PIT, "OnOffAuto", 402 x86_machine_get_pit, 403 x86_machine_set_pit, 404 NULL, NULL); 405 object_class_property_set_description(oc, X86_MACHINE_PIT, 406 "Enable i8254 PIT"); 407 408 object_class_property_add(oc, X86_MACHINE_PIC, "OnOffAuto", 409 x86_machine_get_pic, 410 x86_machine_set_pic, 411 NULL, NULL); 412 object_class_property_set_description(oc, X86_MACHINE_PIC, 413 "Enable i8259 PIC"); 414 415 object_class_property_add_str(oc, X86_MACHINE_OEM_ID, 416 x86_machine_get_oem_id, 417 x86_machine_set_oem_id); 418 object_class_property_set_description(oc, X86_MACHINE_OEM_ID, 419 "Override the default value of field OEMID " 420 "in ACPI table header." 421 "The string may be up to 6 bytes in size"); 422 423 424 object_class_property_add_str(oc, X86_MACHINE_OEM_TABLE_ID, 425 x86_machine_get_oem_table_id, 426 x86_machine_set_oem_table_id); 427 object_class_property_set_description(oc, X86_MACHINE_OEM_TABLE_ID, 428 "Override the default value of field OEM Table ID " 429 "in ACPI table header." 430 "The string may be up to 8 bytes in size"); 431 432 object_class_property_add(oc, X86_MACHINE_BUS_LOCK_RATELIMIT, "uint64_t", 433 x86_machine_get_bus_lock_ratelimit, 434 x86_machine_set_bus_lock_ratelimit, NULL, NULL); 435 object_class_property_set_description(oc, X86_MACHINE_BUS_LOCK_RATELIMIT, 436 "Set the ratelimit for the bus locks acquired in VMs"); 437 438 object_class_property_add(oc, "sgx-epc", "SgxEPC", 439 machine_get_sgx_epc, machine_set_sgx_epc, 440 NULL, NULL); 441 object_class_property_set_description(oc, "sgx-epc", 442 "SGX EPC device"); 443 } 444 445 static const TypeInfo x86_machine_info = { 446 .name = TYPE_X86_MACHINE, 447 .parent = TYPE_MACHINE, 448 .abstract = true, 449 .instance_size = sizeof(X86MachineState), 450 .instance_init = x86_machine_initfn, 451 .class_size = sizeof(X86MachineClass), 452 .class_init = x86_machine_class_init, 453 .interfaces = (InterfaceInfo[]) { 454 { TYPE_NMI }, 455 { } 456 }, 457 }; 458 459 static void x86_machine_register_types(void) 460 { 461 type_register_static(&x86_machine_info); 462 } 463 464 type_init(x86_machine_register_types) 465