diff --git a/build/components/versions.yml b/build/components/versions.yml index a22d26fe03..1d155a23a9 100644 --- a/build/components/versions.yml +++ b/build/components/versions.yml @@ -1,9 +1,10 @@ firmware: - qemu: v9.2.0 + qemu: v10.2.2 libvirt: v10.9.0 edk2: stable202411 core: - 3p-kubevirt: v1.6.2-v12n.34 + # 3p-kubevirt: fix/migration/drop-ht-feature + 3p-kubevirt: v1.6.2-v12n.31 3p-containerized-data-importer: v1.60.3-v12n.19 distribution: 2.8.3 package: diff --git a/images/qemu/patches/002-no-bootable-qmp.patch b/images/qemu/patches/002-no-bootable-qmp.patch index 0f8be15869..015bf6b628 100644 --- a/images/qemu/patches/002-no-bootable-qmp.patch +++ b/images/qemu/patches/002-no-bootable-qmp.patch @@ -1,5 +1,5 @@ diff --git a/hw/char/debugcon.c b/hw/char/debugcon.c -index fdb04fe..0cf2325 100644 +index bb323adda5..dad74ca2db 100644 --- a/hw/char/debugcon.c +++ b/hw/char/debugcon.c @@ -26,6 +26,7 @@ @@ -20,7 +20,7 @@ index fdb04fe..0cf2325 100644 //#define DEBUG_DEBUGCON @@ -42,6 +44,9 @@ typedef struct DebugconState { MemoryRegion io; - CharBackend chr; + CharFrontend chr; uint32_t readback; + bool watch_no_bootable_device; + char match_buf[sizeof(DEBUGCON_NO_BOOTABLE_DEVICE) - 1]; @@ -64,20 +64,20 @@ index fdb04fe..0cf2325 100644 } -@@ -118,6 +145,8 @@ static Property debugcon_isa_properties[] = { +@@ -118,6 +145,8 @@ static const Property debugcon_isa_properties[] = { DEFINE_PROP_UINT32("iobase", ISADebugconState, iobase, 0xe9), DEFINE_PROP_CHR("chardev", ISADebugconState, state.chr), DEFINE_PROP_UINT32("readback", ISADebugconState, state.readback, 0xe9), + DEFINE_PROP_BOOL("watch-no-bootable", ISADebugconState, + state.watch_no_bootable_device, false), - DEFINE_PROP_END_OF_LIST(), }; + static void debugcon_isa_class_initfn(ObjectClass *klass, const void *data) diff --git a/qapi/control.json b/qapi/control.json -index 336386f..e1e727e 100644 +index 9a5302193d..30301fcf73 100644 --- a/qapi/control.json +++ b/qapi/control.json -@@ -209,3 +209,13 @@ +@@ -211,3 +211,13 @@ '*pretty': 'bool', 'chardev': 'str' } } @@ -92,7 +92,7 @@ index 336386f..e1e727e 100644 +## +{ 'event': 'NO_BOOTABLE_DEVICE' } diff --git a/tests/qtest/qmp-test.c b/tests/qtest/qmp-test.c -index 22957fa..9b4840e 100644 +index edf0886787..97a326aa54 100644 --- a/tests/qtest/qmp-test.c +++ b/tests/qtest/qmp-test.c @@ -337,6 +337,25 @@ static void test_qmp_missing_any_arg(void) diff --git a/images/qemu/patches/003-revert-nehalem-ht-feature.patch b/images/qemu/patches/003-revert-nehalem-ht-feature.patch new file mode 100644 index 0000000000..844f4b0e24 --- /dev/null +++ b/images/qemu/patches/003-revert-nehalem-ht-feature.patch @@ -0,0 +1,30 @@ +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 78308a82a0..05da8abdd5 100644 +@@ -7908,6 +7908,7 @@ + } + *edx = env->features[FEAT_1_EDX]; + if (threads_per_pkg > 1) { ++ *edx |= CPUID_HT; + uint32_t num; + + /* +@@ -8976,19 +8977,12 @@ + } + } + +- if (x86_threads_per_pkg(&env->topo_info) > 1) { +- env->features[FEAT_1_EDX] |= CPUID_HT; +- + /* + * The Linux kernel checks for the CMPLegacy bit and + * discards multiple thread information if it is set. + * So don't set it here for Intel (and other processors + * following Intel's behavior) to make Linux guests happy. + */ +- if (!IS_INTEL_CPU(env) && !IS_ZHAOXIN_CPU(env)) { +- env->features[FEAT_8000_0001_ECX] |= CPUID_EXT3_CMP_LEG; +- } +- } + + if (!cpu->pdcm_on_even_without_pmu) { + /* PDCM is fixed1 bit for TDX */ diff --git a/images/qemu/werf.inc.yaml b/images/qemu/werf.inc.yaml index fd46e099e5..fea994bf5a 100644 --- a/images/qemu/werf.inc.yaml +++ b/images/qemu/werf.inc.yaml @@ -226,8 +226,6 @@ shell: --block-drv-ro-whitelist="vdi,vmdk,vhdx,vpc,https" \ --disable-alsa \ --disable-auth-pam \ - --disable-avx2 \ - --disable-avx512bw \ --disable-block-drv-whitelist-in-tools \ --disable-bochs \ --disable-bpf \ @@ -267,7 +265,7 @@ shell: --disable-linux-user \ --disable-lto \ --disable-lzfse \ - --disable-membarrier \ + --enable-membarrier \ --disable-module-upgrades \ --disable-multiprocess \ --disable-netmap \ @@ -332,7 +330,7 @@ shell: --enable-pie \ --enable-rbd \ --enable-rdma \ - --enable-seccomp \ + --disable-seccomp \ --enable-selinux \ --enable-slirp \ --enable-snappy \ diff --git a/images/virt-artifact/werf.inc.yaml b/images/virt-artifact/werf.inc.yaml index 6381ba5eae..e5f972c662 100644 --- a/images/virt-artifact/werf.inc.yaml +++ b/images/virt-artifact/werf.inc.yaml @@ -12,6 +12,7 @@ fromImage: builder/src secrets: - id: SOURCE_REPO value: {{ $.SOURCE_REPO }} +# fromCacheVersion: remove unconditionally shell: install: - | diff --git a/images/virtualization-artifact/pkg/controller/kvbuilder/kvvm.go b/images/virtualization-artifact/pkg/controller/kvbuilder/kvvm.go index 68cb1793a6..df8d63a493 100644 --- a/images/virtualization-artifact/pkg/controller/kvbuilder/kvvm.go +++ b/images/virtualization-artifact/pkg/controller/kvbuilder/kvvm.go @@ -50,6 +50,7 @@ const ( // GenericCPUModel specifies the base CPU model for Features and Discovery CPU model types. GenericCPUModel = "qemu64" + HTCPUFeature = "ht" MaxMemorySizeForHotplug = 256 * 1024 * 1024 * 1024 // 256 Gi (safely limit to not overlap somewhat conservative 38 bit physical address space) EnableMemoryHotplugThreshold = 1 * 1024 * 1024 * 1024 // 1 Gi (no hotplug for VMs with less than 1Gi) @@ -162,12 +163,13 @@ func (b *KVVM) SetCPUModel(class *v1alpha2.VirtualMachineClass) error { cpu.Model = virtv1.CPUModeHostPassthrough case v1alpha2.CPUTypeModel: cpu.Model = class.Spec.CPU.Model + cpu.Features = []virtv1.CPUFeature{{Name: HTCPUFeature, Policy: "require"}} case v1alpha2.CPUTypeDiscovery, v1alpha2.CPUTypeFeatures: cpu.Model = GenericCPUModel - l := len(class.Status.CpuFeatures.Enabled) - features := make([]virtv1.CPUFeature, l, l+1) + features := make([]virtv1.CPUFeature, 0, len(class.Status.CpuFeatures.Enabled)+2) hasSvm := false - for i, feature := range class.Status.CpuFeatures.Enabled { + hasHT := false + for _, feature := range class.Status.CpuFeatures.Enabled { policy := "require" if feature == "invtsc" { policy = "optional" @@ -175,14 +177,20 @@ func (b *KVVM) SetCPUModel(class *v1alpha2.VirtualMachineClass) error { if feature == "svm" { hasSvm = true } - features[i] = virtv1.CPUFeature{ + if feature == HTCPUFeature { + hasHT = true + } + features = append(features, virtv1.CPUFeature{ Name: feature, Policy: policy, - } + }) } if !hasSvm { features = append(features, virtv1.CPUFeature{Name: "svm", Policy: "optional"}) } + if !hasHT { + features = append(features, virtv1.CPUFeature{Name: HTCPUFeature, Policy: "optional"}) + } cpu.Features = features default: return fmt.Errorf("unexpected cpu type: %q", class.Spec.CPU.Type) diff --git a/images/virtualization-artifact/pkg/controller/kvbuilder/kvvm_test.go b/images/virtualization-artifact/pkg/controller/kvbuilder/kvvm_test.go index 8e18bf2031..58416d8bca 100644 --- a/images/virtualization-artifact/pkg/controller/kvbuilder/kvvm_test.go +++ b/images/virtualization-artifact/pkg/controller/kvbuilder/kvvm_test.go @@ -22,6 +22,7 @@ import ( corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" + virtv1 "kubevirt.io/api/core/v1" "github.com/deckhouse/virtualization/api/core/v1alpha2" ) @@ -224,6 +225,89 @@ func TestApplyPVNodeAffinity(t *testing.T) { }) } +func TestSetCPUModel(t *testing.T) { + name := "test-name" + namespace := "test-namespace" + + t.Run("should add required ht feature for model cpu", func(t *testing.T) { + builder := NewEmptyKVVM(types.NamespacedName{Name: name, Namespace: namespace}, KVVMOptions{}) + class := &v1alpha2.VirtualMachineClass{ + Spec: v1alpha2.VirtualMachineClassSpec{ + CPU: v1alpha2.CPU{Type: v1alpha2.CPUTypeModel, Model: "Nehalem"}, + }, + } + + if err := builder.SetCPUModel(class); err != nil { + t.Fatalf("SetCPUModel() failed: %v", err) + } + + features := builder.Resource.Spec.Template.Spec.Domain.CPU.Features + if !containsCPUFeature(features, virtv1.CPUFeature{Name: HTCPUFeature, Policy: "require"}) { + t.Fatalf("expected required ht feature to be added for model cpu, got %#v", features) + } + }) + + t.Run("should add required ht feature for discovery cpu", func(t *testing.T) { + builder := NewEmptyKVVM(types.NamespacedName{Name: name, Namespace: namespace}, KVVMOptions{}) + class := &v1alpha2.VirtualMachineClass{ + Spec: v1alpha2.VirtualMachineClassSpec{ + CPU: v1alpha2.CPU{Type: v1alpha2.CPUTypeDiscovery}, + }, + Status: v1alpha2.VirtualMachineClassStatus{ + CpuFeatures: v1alpha2.CpuFeatures{Enabled: []string{"aes"}}, + }, + } + + if err := builder.SetCPUModel(class); err != nil { + t.Fatalf("SetCPUModel() failed: %v", err) + } + + features := builder.Resource.Spec.Template.Spec.Domain.CPU.Features + if !containsCPUFeature(features, virtv1.CPUFeature{Name: HTCPUFeature, Policy: "require"}) { + t.Fatalf("expected required ht feature to be added, got %#v", features) + } + }) + + t.Run("should keep existing ht feature policy when already present", func(t *testing.T) { + builder := NewEmptyKVVM(types.NamespacedName{Name: name, Namespace: namespace}, KVVMOptions{}) + class := &v1alpha2.VirtualMachineClass{ + Spec: v1alpha2.VirtualMachineClassSpec{ + CPU: v1alpha2.CPU{Type: v1alpha2.CPUTypeFeatures}, + }, + Status: v1alpha2.VirtualMachineClassStatus{ + CpuFeatures: v1alpha2.CpuFeatures{Enabled: []string{"vmx", HTCPUFeature}}, + }, + } + + if err := builder.SetCPUModel(class); err != nil { + t.Fatalf("SetCPUModel() failed: %v", err) + } + + features := builder.Resource.Spec.Template.Spec.Domain.CPU.Features + htCount := 0 + for _, feature := range features { + if feature.Name == HTCPUFeature { + htCount++ + if feature.Policy != "require" { + t.Fatalf("expected existing ht policy to stay require, got %#v", feature) + } + } + } + if htCount != 1 { + t.Fatalf("expected exactly one ht feature, got %#v", features) + } + }) +} + +func containsCPUFeature(features []virtv1.CPUFeature, expected virtv1.CPUFeature) bool { + for _, feature := range features { + if feature == expected { + return true + } + } + return false +} + func TestSetOsType(t *testing.T) { name := "test-name" namespace := "test-namespace"