x86.c 15 KB

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