x86.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. // Copyright 2019 Yunion
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package arch
  15. import (
  16. "fmt"
  17. "strings"
  18. "yunion.io/x/onecloud/pkg/hostman/guestman/desc"
  19. "yunion.io/x/onecloud/pkg/hostman/guestman/qemu"
  20. "yunion.io/x/onecloud/pkg/hostman/options"
  21. "yunion.io/x/onecloud/pkg/util/sysutils"
  22. )
  23. const (
  24. X86_MAX_CPUS = 240
  25. X86_SOCKETS = 2
  26. X86_CORES = 64
  27. X86_THREADS = 1
  28. X86_MEM_DEFAULT_SLOTS = 4
  29. )
  30. var X86_MAX_MEM_MB uint = 524288
  31. type X86 struct {
  32. archBase
  33. }
  34. func (*X86) GeneratePvpanicDesc() *desc.SGuestPvpanic {
  35. return &desc.SGuestPvpanic{
  36. Ioport: 1285, //default ioport
  37. Id: "pvpanic",
  38. }
  39. }
  40. func (*X86) GenerateIsaSerialDesc() *desc.SGuestIsaSerial {
  41. return &desc.SGuestIsaSerial{
  42. Pty: desc.NewCharDev("pty", "charserial0", ""),
  43. Id: "serial0",
  44. }
  45. }
  46. func (*X86) GenerateCdromDesc(osName string, cdrom *desc.SGuestCdrom) {
  47. var id, devType string
  48. var driveOpts map[string]string
  49. switch osName {
  50. case qemu.OS_NAME_MACOS:
  51. id = "MacDVD"
  52. devType = "ide-drive"
  53. driveOpts = map[string]string{
  54. "if": "none",
  55. "snapshot": "on",
  56. }
  57. default:
  58. id = fmt.Sprintf("ide%d-cd0", cdrom.Ordinal)
  59. devType = "ide-cd"
  60. driveOpts = map[string]string{
  61. "if": "none",
  62. "media": "cdrom",
  63. }
  64. }
  65. cdrom.Ide = &desc.IDEDevice{
  66. DevType: devType,
  67. }
  68. cdrom.DriveOptions = driveOpts
  69. cdrom.Id = id
  70. }
  71. // -device floppy,drive=floppy0 -drive id=floppy0,if=none
  72. func (*X86) GenerateFloppyDesc(osName string, floppy *desc.SGuestFloppy) {
  73. var id, devType string
  74. var driveOpts map[string]string
  75. switch osName {
  76. case qemu.OS_NAME_WINDOWS:
  77. id = fmt.Sprintf("floppy%d", floppy.Ordinal)
  78. devType = "floppy"
  79. driveOpts = map[string]string{
  80. "if": "none",
  81. }
  82. floppy.Floppy = &desc.FloppyDevice{
  83. DevType: devType,
  84. }
  85. floppy.DriveOptions = driveOpts
  86. floppy.Id = id
  87. }
  88. }
  89. func (*X86) GenerateMachineDesc(accel string) *desc.SGuestMachine {
  90. return &desc.SGuestMachine{
  91. Accel: accel,
  92. }
  93. }
  94. func (*X86) GenerateMemDesc() *desc.SGuestMem {
  95. return &desc.SGuestMem{
  96. Slots: X86_MEM_DEFAULT_SLOTS,
  97. MaxMem: X86_MAX_MEM_MB,
  98. }
  99. }
  100. func (*X86) IsKernelVersionEnableHyperv(kernelVersion string) bool {
  101. return strings.HasPrefix(kernelVersion, "5.4")
  102. }
  103. func (*X86) enableHypervFeatures(features map[string]bool) {
  104. for _, feat := range []string{
  105. "hv_relaxed", "hv_vpindex", "hv_time",
  106. "hv_vapic", "hv_runtime", "hv_synic", "hv_stimer"} {
  107. features[feat] = true
  108. }
  109. }
  110. func (x86 *X86) GenerateCpuDesc(cpus uint, cpuMax uint, s KVMGuestInstance) (*desc.SGuestCpu, error) {
  111. var hideKVM = s.HideKVM()
  112. var hideHypervisor = s.HideHypervisor()
  113. var hostCPUPassthrough = options.HostOptions.HostCpuPassthrough
  114. var isCPUIntel = sysutils.IsProcessorIntel()
  115. var isCPUAMD = sysutils.IsProcessorAmd()
  116. var accel, cpuType, vendor, level string
  117. var features = make(map[string]bool, 0)
  118. if s.IsKvmSupport() {
  119. if isCPUIntel {
  120. vendor = "GenuineIntel"
  121. } else if isCPUAMD {
  122. vendor = "AuthenticAMD"
  123. }
  124. accel = "kvm"
  125. if s.GetOsName() == qemu.OS_NAME_MACOS {
  126. cpuType = "Penryn"
  127. vendor = "GenuineIntel"
  128. } else if hostCPUPassthrough {
  129. cpuType = "host"
  130. // https://unix.stackexchange.com/questions/216925/nmi-received-for-unknown-reason-20-do-you-have-a-strange-power-saving-mode-ena
  131. features["kvm_pv_eoi"] = true
  132. if s.GetOsName() == qemu.OS_NAME_WINDOWS &&
  133. !s.IsOldWindows() &&
  134. x86.IsKernelVersionEnableHyperv(s.GetKernelVersion()) {
  135. x86.enableHypervFeatures(features)
  136. }
  137. } else {
  138. cpuType = "qemu64"
  139. features["kvm_pv_eoi"] = true
  140. if isCPUIntel {
  141. for _, feat := range []string{
  142. "vmx", "ssse3", "sse4.1", "sse4.2", "aes", "avx",
  143. "vme", "pat", "ss", "pclmulqdq", "xsave",
  144. } {
  145. features[feat] = true
  146. }
  147. features["x2apic"] = false
  148. level = "13"
  149. } else if isCPUAMD {
  150. features["svm"] = true
  151. }
  152. }
  153. if hideKVM {
  154. features["kvm"] = false
  155. }
  156. if hideHypervisor {
  157. features["hypervisor"] = false
  158. }
  159. } else {
  160. accel = "tcg"
  161. cpuType = "qemu64"
  162. }
  163. return &desc.SGuestCpu{
  164. Cpus: cpus,
  165. Sockets: X86_SOCKETS,
  166. Cores: cpuMax / X86_SOCKETS / X86_THREADS,
  167. Threads: X86_THREADS,
  168. MaxCpus: cpuMax,
  169. Model: cpuType,
  170. Vendor: vendor,
  171. Level: level,
  172. Features: features,
  173. Accel: accel,
  174. }, nil
  175. }