[PATCH v2] hw/smbios: allow clearing the VM bit in SMBIOS table 0

Daniil Tatianin posted 1 patch 3 months, 3 weeks ago
Patches applied successfully (tree, apply log)
git fetch https://github.com/patchew-project/qemu tags/patchew/20250724195409.43499-1-d-tatianin@yandex-team.ru
Maintainers: "Michael S. Tsirkin" <mst@redhat.com>, Igor Mammedov <imammedo@redhat.com>, Ani Sinha <anisinha@redhat.com>
hw/smbios/smbios.c           | 11 ++++++++++-
include/hw/firmware/smbios.h |  2 +-
qemu-options.hx              |  2 +-
3 files changed, 12 insertions(+), 3 deletions(-)
[PATCH v2] hw/smbios: allow clearing the VM bit in SMBIOS table 0
Posted by Daniil Tatianin 3 months, 3 weeks ago
This is useful to be able to freeze a specific version of SeaBIOS to
prevent guest visible changes between BIOS updates. This is currently
not possible since the extension byte 2 provided by SeaBIOS does not
set the VM bit, whereas QEMU sets it unconditionally.

Allowing to clear it also seems useful if we want to hide the fact that
the guest system is running inside a virtual machine.

Signed-off-by: Daniil Tatianin <d-tatianin@yandex-team.ru>
---

After talking to Michael:
Supersedes: <20250723090128.977364-1-d-tatianin@yandex-team.ru>

v2:
- Add the new option to qemu-options.hx

---
 hw/smbios/smbios.c           | 11 ++++++++++-
 include/hw/firmware/smbios.h |  2 +-
 qemu-options.hx              |  2 +-
 3 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c
index 1ac063cfb4..13e21a9c43 100644
--- a/hw/smbios/smbios.c
+++ b/hw/smbios/smbios.c
@@ -179,6 +179,10 @@ static const QemuOptDesc qemu_smbios_type0_opts[] = {
         .name = "uefi",
         .type = QEMU_OPT_BOOL,
         .help = "uefi support",
+    },{
+        .name = "vm",
+        .type = QEMU_OPT_BOOL,
+        .help = "virtual machine",
     },
     { /* end of list */ }
 };
@@ -574,10 +578,14 @@ static void smbios_build_type_0_table(void)
 
     t->bios_characteristics = cpu_to_le64(0x08); /* Not supported */
     t->bios_characteristics_extension_bytes[0] = 0;
-    t->bios_characteristics_extension_bytes[1] = 0x14; /* TCD/SVVP | VM */
+
+    t->bios_characteristics_extension_bytes[1] = 0x04; /* TCD/SVVP */
     if (smbios_type0.uefi) {
         t->bios_characteristics_extension_bytes[1] |= 0x08; /* |= UEFI */
     }
+    if (smbios_type0.vm) {
+        t->bios_characteristics_extension_bytes[1] |= 0x10; /* |= VM */
+    }
 
     if (smbios_type0.have_major_minor) {
         t->system_bios_major_release = smbios_type0.major;
@@ -1405,6 +1413,7 @@ void smbios_entry_add(QemuOpts *opts, Error **errp)
             save_opt(&smbios_type0.version, opts, "version");
             save_opt(&smbios_type0.date, opts, "date");
             smbios_type0.uefi = qemu_opt_get_bool(opts, "uefi", false);
+            smbios_type0.vm = qemu_opt_get_bool(opts, "vm", true);
 
             val = qemu_opt_get(opts, "release");
             if (val) {
diff --git a/include/hw/firmware/smbios.h b/include/hw/firmware/smbios.h
index f066ab7262..3ea732f4e6 100644
--- a/include/hw/firmware/smbios.h
+++ b/include/hw/firmware/smbios.h
@@ -22,7 +22,7 @@ extern GArray *usr_blobs_sizes;
 
 typedef struct {
     const char *vendor, *version, *date;
-    bool have_major_minor, uefi;
+    bool have_major_minor, uefi, vm;
     uint8_t major, minor;
 } smbios_type0_t;
 extern smbios_type0_t smbios_type0;
diff --git a/qemu-options.hx b/qemu-options.hx
index ab23f14d21..11204c47eb 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -2693,7 +2693,7 @@ DEF("smbios", HAS_ARG, QEMU_OPTION_smbios,
     "-smbios file=binary\n"
     "                load SMBIOS entry from binary file\n"
     "-smbios type=0[,vendor=str][,version=str][,date=str][,release=%d.%d]\n"
-    "              [,uefi=on|off]\n"
+    "              [,uefi=on|off][,vm=on|off]\n"
     "                specify SMBIOS type 0 fields\n"
     "-smbios type=1[,manufacturer=str][,product=str][,version=str][,serial=str]\n"
     "              [,uuid=uuid][,sku=str][,family=str]\n"
-- 
2.34.1
Re: [PATCH v2] hw/smbios: allow clearing the VM bit in SMBIOS table 0
Posted by Daniil Tatianin 3 months, 1 week ago
Ping :)

On 7/24/25 10:54 PM, Daniil Tatianin wrote:
> This is useful to be able to freeze a specific version of SeaBIOS to
> prevent guest visible changes between BIOS updates. This is currently
> not possible since the extension byte 2 provided by SeaBIOS does not
> set the VM bit, whereas QEMU sets it unconditionally.
>
> Allowing to clear it also seems useful if we want to hide the fact that
> the guest system is running inside a virtual machine.
>
> Signed-off-by: Daniil Tatianin <d-tatianin@yandex-team.ru>
> ---
>
> After talking to Michael:
> Supersedes: <20250723090128.977364-1-d-tatianin@yandex-team.ru>
>
> v2:
> - Add the new option to qemu-options.hx
>
> ---
>   hw/smbios/smbios.c           | 11 ++++++++++-
>   include/hw/firmware/smbios.h |  2 +-
>   qemu-options.hx              |  2 +-
>   3 files changed, 12 insertions(+), 3 deletions(-)
>
> diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c
> index 1ac063cfb4..13e21a9c43 100644
> --- a/hw/smbios/smbios.c
> +++ b/hw/smbios/smbios.c
> @@ -179,6 +179,10 @@ static const QemuOptDesc qemu_smbios_type0_opts[] = {
>           .name = "uefi",
>           .type = QEMU_OPT_BOOL,
>           .help = "uefi support",
> +    },{
> +        .name = "vm",
> +        .type = QEMU_OPT_BOOL,
> +        .help = "virtual machine",
>       },
>       { /* end of list */ }
>   };
> @@ -574,10 +578,14 @@ static void smbios_build_type_0_table(void)
>   
>       t->bios_characteristics = cpu_to_le64(0x08); /* Not supported */
>       t->bios_characteristics_extension_bytes[0] = 0;
> -    t->bios_characteristics_extension_bytes[1] = 0x14; /* TCD/SVVP | VM */
> +
> +    t->bios_characteristics_extension_bytes[1] = 0x04; /* TCD/SVVP */
>       if (smbios_type0.uefi) {
>           t->bios_characteristics_extension_bytes[1] |= 0x08; /* |= UEFI */
>       }
> +    if (smbios_type0.vm) {
> +        t->bios_characteristics_extension_bytes[1] |= 0x10; /* |= VM */
> +    }
>   
>       if (smbios_type0.have_major_minor) {
>           t->system_bios_major_release = smbios_type0.major;
> @@ -1405,6 +1413,7 @@ void smbios_entry_add(QemuOpts *opts, Error **errp)
>               save_opt(&smbios_type0.version, opts, "version");
>               save_opt(&smbios_type0.date, opts, "date");
>               smbios_type0.uefi = qemu_opt_get_bool(opts, "uefi", false);
> +            smbios_type0.vm = qemu_opt_get_bool(opts, "vm", true);
>   
>               val = qemu_opt_get(opts, "release");
>               if (val) {
> diff --git a/include/hw/firmware/smbios.h b/include/hw/firmware/smbios.h
> index f066ab7262..3ea732f4e6 100644
> --- a/include/hw/firmware/smbios.h
> +++ b/include/hw/firmware/smbios.h
> @@ -22,7 +22,7 @@ extern GArray *usr_blobs_sizes;
>   
>   typedef struct {
>       const char *vendor, *version, *date;
> -    bool have_major_minor, uefi;
> +    bool have_major_minor, uefi, vm;
>       uint8_t major, minor;
>   } smbios_type0_t;
>   extern smbios_type0_t smbios_type0;
> diff --git a/qemu-options.hx b/qemu-options.hx
> index ab23f14d21..11204c47eb 100644
> --- a/qemu-options.hx
> +++ b/qemu-options.hx
> @@ -2693,7 +2693,7 @@ DEF("smbios", HAS_ARG, QEMU_OPTION_smbios,
>       "-smbios file=binary\n"
>       "                load SMBIOS entry from binary file\n"
>       "-smbios type=0[,vendor=str][,version=str][,date=str][,release=%d.%d]\n"
> -    "              [,uefi=on|off]\n"
> +    "              [,uefi=on|off][,vm=on|off]\n"
>       "                specify SMBIOS type 0 fields\n"
>       "-smbios type=1[,manufacturer=str][,product=str][,version=str][,serial=str]\n"
>       "              [,uuid=uuid][,sku=str][,family=str]\n"
Re: [PATCH v2] hw/smbios: allow clearing the VM bit in SMBIOS table 0
Posted by Michael S. Tsirkin 3 months, 3 weeks ago
On Thu, Jul 24, 2025 at 10:54:09PM +0300, Daniil Tatianin wrote:
> This is useful to be able to freeze a specific version of SeaBIOS to
> prevent guest visible changes between BIOS updates. This is currently
> not possible since the extension byte 2 provided by SeaBIOS does not
> set the VM bit, whereas QEMU sets it unconditionally.
> 
> Allowing to clear it also seems useful if we want to hide the fact that
> the guest system is running inside a virtual machine.
> 
> Signed-off-by: Daniil Tatianin <d-tatianin@yandex-team.ru>
> ---
> 
> After talking to Michael:
> Supersedes: <20250723090128.977364-1-d-tatianin@yandex-team.ru>
> 
> v2:
> - Add the new option to qemu-options.hx
> 
> ---
>  hw/smbios/smbios.c           | 11 ++++++++++-
>  include/hw/firmware/smbios.h |  2 +-
>  qemu-options.hx              |  2 +-
>  3 files changed, 12 insertions(+), 3 deletions(-)
> 
> diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c
> index 1ac063cfb4..13e21a9c43 100644
> --- a/hw/smbios/smbios.c
> +++ b/hw/smbios/smbios.c
> @@ -179,6 +179,10 @@ static const QemuOptDesc qemu_smbios_type0_opts[] = {
>          .name = "uefi",
>          .type = QEMU_OPT_BOOL,
>          .help = "uefi support",
> +    },{
> +        .name = "vm",
> +        .type = QEMU_OPT_BOOL,
> +        .help = "virtual machine",
>      },
>      { /* end of list */ }
>  };


Can/should we just poke at "hypervisor" CPU property?

Cc Paolo for comments.

> @@ -574,10 +578,14 @@ static void smbios_build_type_0_table(void)
>  
>      t->bios_characteristics = cpu_to_le64(0x08); /* Not supported */
>      t->bios_characteristics_extension_bytes[0] = 0;
> -    t->bios_characteristics_extension_bytes[1] = 0x14; /* TCD/SVVP | VM */
> +
> +    t->bios_characteristics_extension_bytes[1] = 0x04; /* TCD/SVVP */
>      if (smbios_type0.uefi) {
>          t->bios_characteristics_extension_bytes[1] |= 0x08; /* |= UEFI */
>      }
> +    if (smbios_type0.vm) {
> +        t->bios_characteristics_extension_bytes[1] |= 0x10; /* |= VM */
> +    }
>  
>      if (smbios_type0.have_major_minor) {
>          t->system_bios_major_release = smbios_type0.major;
> @@ -1405,6 +1413,7 @@ void smbios_entry_add(QemuOpts *opts, Error **errp)
>              save_opt(&smbios_type0.version, opts, "version");
>              save_opt(&smbios_type0.date, opts, "date");
>              smbios_type0.uefi = qemu_opt_get_bool(opts, "uefi", false);
> +            smbios_type0.vm = qemu_opt_get_bool(opts, "vm", true);
>  
>              val = qemu_opt_get(opts, "release");
>              if (val) {
> diff --git a/include/hw/firmware/smbios.h b/include/hw/firmware/smbios.h
> index f066ab7262..3ea732f4e6 100644
> --- a/include/hw/firmware/smbios.h
> +++ b/include/hw/firmware/smbios.h
> @@ -22,7 +22,7 @@ extern GArray *usr_blobs_sizes;
>  
>  typedef struct {
>      const char *vendor, *version, *date;
> -    bool have_major_minor, uefi;
> +    bool have_major_minor, uefi, vm;
>      uint8_t major, minor;
>  } smbios_type0_t;
>  extern smbios_type0_t smbios_type0;
> diff --git a/qemu-options.hx b/qemu-options.hx
> index ab23f14d21..11204c47eb 100644
> --- a/qemu-options.hx
> +++ b/qemu-options.hx
> @@ -2693,7 +2693,7 @@ DEF("smbios", HAS_ARG, QEMU_OPTION_smbios,
>      "-smbios file=binary\n"
>      "                load SMBIOS entry from binary file\n"
>      "-smbios type=0[,vendor=str][,version=str][,date=str][,release=%d.%d]\n"
> -    "              [,uefi=on|off]\n"
> +    "              [,uefi=on|off][,vm=on|off]\n"
>      "                specify SMBIOS type 0 fields\n"
>      "-smbios type=1[,manufacturer=str][,product=str][,version=str][,serial=str]\n"
>      "              [,uuid=uuid][,sku=str][,family=str]\n"
> -- 
> 2.34.1
Re: [PATCH v2] hw/smbios: allow clearing the VM bit in SMBIOS table 0
Posted by Daniil Tatianin 3 months, 3 weeks ago
On 7/25/25 4:20 PM, Michael S. Tsirkin wrote:
> On Thu, Jul 24, 2025 at 10:54:09PM +0300, Daniil Tatianin wrote:
>> This is useful to be able to freeze a specific version of SeaBIOS to
>> prevent guest visible changes between BIOS updates. This is currently
>> not possible since the extension byte 2 provided by SeaBIOS does not
>> set the VM bit, whereas QEMU sets it unconditionally.
>>
>> Allowing to clear it also seems useful if we want to hide the fact that
>> the guest system is running inside a virtual machine.
>>
>> Signed-off-by: Daniil Tatianin <d-tatianin@yandex-team.ru>
>> ---
>>
>> After talking to Michael:
>> Supersedes: <20250723090128.977364-1-d-tatianin@yandex-team.ru>
>>
>> v2:
>> - Add the new option to qemu-options.hx
>>
>> ---
>>   hw/smbios/smbios.c           | 11 ++++++++++-
>>   include/hw/firmware/smbios.h |  2 +-
>>   qemu-options.hx              |  2 +-
>>   3 files changed, 12 insertions(+), 3 deletions(-)
>>
>> diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c
>> index 1ac063cfb4..13e21a9c43 100644
>> --- a/hw/smbios/smbios.c
>> +++ b/hw/smbios/smbios.c
>> @@ -179,6 +179,10 @@ static const QemuOptDesc qemu_smbios_type0_opts[] = {
>>           .name = "uefi",
>>           .type = QEMU_OPT_BOOL,
>>           .help = "uefi support",
>> +    },{
>> +        .name = "vm",
>> +        .type = QEMU_OPT_BOOL,
>> +        .help = "virtual machine",
>>       },
>>       { /* end of list */ }
>>   };
>
> Can/should we just poke at "hypervisor" CPU property?

Well that property is part of the CPUID flags, and this one is part of 
SMBIOS.
Sometimes you may wish to have one set, but the other clear.
For example for SeaBIOS compatibility, like some fields already do here 
(look at the comments for some of them).
SeaBIOS never sets the VM flag at all, so IMO QEMU shouldn't have as 
well, but since that's already the default
we can at least add an option to make it not do that if going for 
SeaBIOS compatibility.

>
> Cc Paolo for comments.
>
>> @@ -574,10 +578,14 @@ static void smbios_build_type_0_table(void)
>>   
>>       t->bios_characteristics = cpu_to_le64(0x08); /* Not supported */
>>       t->bios_characteristics_extension_bytes[0] = 0;
>> -    t->bios_characteristics_extension_bytes[1] = 0x14; /* TCD/SVVP | VM */
>> +
>> +    t->bios_characteristics_extension_bytes[1] = 0x04; /* TCD/SVVP */
>>       if (smbios_type0.uefi) {
>>           t->bios_characteristics_extension_bytes[1] |= 0x08; /* |= UEFI */
>>       }
>> +    if (smbios_type0.vm) {
>> +        t->bios_characteristics_extension_bytes[1] |= 0x10; /* |= VM */
>> +    }
>>   
>>       if (smbios_type0.have_major_minor) {
>>           t->system_bios_major_release = smbios_type0.major;
>> @@ -1405,6 +1413,7 @@ void smbios_entry_add(QemuOpts *opts, Error **errp)
>>               save_opt(&smbios_type0.version, opts, "version");
>>               save_opt(&smbios_type0.date, opts, "date");
>>               smbios_type0.uefi = qemu_opt_get_bool(opts, "uefi", false);
>> +            smbios_type0.vm = qemu_opt_get_bool(opts, "vm", true);
>>   
>>               val = qemu_opt_get(opts, "release");
>>               if (val) {
>> diff --git a/include/hw/firmware/smbios.h b/include/hw/firmware/smbios.h
>> index f066ab7262..3ea732f4e6 100644
>> --- a/include/hw/firmware/smbios.h
>> +++ b/include/hw/firmware/smbios.h
>> @@ -22,7 +22,7 @@ extern GArray *usr_blobs_sizes;
>>   
>>   typedef struct {
>>       const char *vendor, *version, *date;
>> -    bool have_major_minor, uefi;
>> +    bool have_major_minor, uefi, vm;
>>       uint8_t major, minor;
>>   } smbios_type0_t;
>>   extern smbios_type0_t smbios_type0;
>> diff --git a/qemu-options.hx b/qemu-options.hx
>> index ab23f14d21..11204c47eb 100644
>> --- a/qemu-options.hx
>> +++ b/qemu-options.hx
>> @@ -2693,7 +2693,7 @@ DEF("smbios", HAS_ARG, QEMU_OPTION_smbios,
>>       "-smbios file=binary\n"
>>       "                load SMBIOS entry from binary file\n"
>>       "-smbios type=0[,vendor=str][,version=str][,date=str][,release=%d.%d]\n"
>> -    "              [,uefi=on|off]\n"
>> +    "              [,uefi=on|off][,vm=on|off]\n"
>>       "                specify SMBIOS type 0 fields\n"
>>       "-smbios type=1[,manufacturer=str][,product=str][,version=str][,serial=str]\n"
>>       "              [,uuid=uuid][,sku=str][,family=str]\n"
>> -- 
>> 2.34.1