Skip to content
5 changes: 3 additions & 2 deletions build/components/versions.yml
Original file line number Diff line number Diff line change
@@ -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:
Expand Down
14 changes: 7 additions & 7 deletions images/qemu/patches/002-no-bootable-qmp.patch
Original file line number Diff line number Diff line change
@@ -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 @@
Expand All @@ -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];
Expand Down Expand Up @@ -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'
} }
Expand All @@ -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)
Expand Down
6 changes: 2 additions & 4 deletions images/qemu/werf.inc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand Down Expand Up @@ -267,7 +265,7 @@ shell:
--disable-linux-user \
--disable-lto \
--disable-lzfse \
--disable-membarrier \
--enable-membarrier \
--disable-module-upgrades \
--disable-multiprocess \
--disable-netmap \
Expand Down Expand Up @@ -332,7 +330,7 @@ shell:
--enable-pie \
--enable-rbd \
--enable-rdma \
--enable-seccomp \
--disable-seccomp \
--enable-selinux \
--enable-slirp \
--enable-snappy \
Expand Down
1 change: 1 addition & 0 deletions images/virt-artifact/werf.inc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ fromImage: builder/src
secrets:
- id: SOURCE_REPO
value: {{ $.SOURCE_REPO }}
# fromCacheVersion: remove unconditionally
shell:
install:
- |
Expand Down
18 changes: 13 additions & 5 deletions images/virtualization-artifact/pkg/controller/kvbuilder/kvvm.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -162,27 +163,34 @@ 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"
}
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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)
Expand Down Expand Up @@ -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"
Expand Down
Loading