Re: [PATCH RFC 00/13] qemu: Add support for iothread to virtqueue mapping for 'virtio-scsi'

2025-02-18 Thread Stefan Hajnoczi
On Tue, Feb 18, 2025 at 12:15:46PM +0100, Peter Krempa wrote:
> On Tue, Feb 18, 2025 at 13:53:31 +0800, Stefan Hajnoczi wrote:
> > On Fri, Feb 14, 2025 at 05:29:34PM +0100, Peter Krempa wrote:
> > > The first part of the series refactors the existing code for reuse and
> > > then uses the new helpers to implement the feature.
> > > 
> > > Note that this series is in RFC state as the qemu patches are still
> > > being discussed. Thus also the capability bump is not final.
> > > 
> > > Also note that we should discuss the libvirt interface perhaps as it
> > > turns out that 'virtio-scsi' has two internal queues that need to be
> > > mapped as well.
> > > 
> > > For now I've solved this administratively by instructing users to also
> > > add mapping for queue '0' and '1' which are the special ones in case of
> > > virtio-scsi.
> > 
> > Thanks for tackling this upcoming QEMU feature! I thought about the
> > pros/cons of exposing all virtqueues in iothread-vq-mapping= whereas
> > just the command virtqueues are exposed by num_queues=. Although it's
> > confusing and inconvenient that the implicit ctrl and event virtqueues
> > need to be covered by iothread-vq-mapping= but are not counted in
> > num_queues=, I'd rather not introduce magic to hide this detail. If
> > users do need to control these virtqueues explicitly then the magic will
> > get in the way.
> 
> I thought about it a bit as well and I think we should:
> 
> 1) Document the round robin assignment a bit more prominently, so that
>users don't feel compelled to do a full mapping. Currently the
>example spells out the full maping configuration, so the first
>example should be the simpler one.

Good idea.

> 2) Modify the qemu code so that the mapping XML will explicitly name the
> 'ctrl/event' queues. Leave the numbered ones for the explicit ones
> configured via queues. That way it'll be obvious what's happening.
> 
> 
>   
> 
>   
>   
> 
> 
>   
> 
> 
>   
> 
>   
> 
> 
> 
> Libvirt will then map the above config to mapping for queues 0,1,2,3 for
> use with qemu. That way there will be no ambiguity and weirdness when
> comparing the config between virtio-blk and virtio-scsi.

Nice!

> > Does anyone have a different opinion?
> 
> I agree. We should hint the users to use the simpler configs and use the
> full mapping only if necessary. When using the full mapping the above
> XML will IMO make it obvious what's happening.
> 
> In qemu no change will be needed although the role of queues 0 and 1
> should be formalized in docs so that it doesn't change later on at least
> without notifying libvirt so that we adapt if needed.

The roles of the queues are defined in the VIRTIO specification. ctrl
and event are always 0 and 1. The only way they could change is if a new
feature bit is introduced, but this is very unlikely.

https://docs.oasis-open.org/virtio/virtio/v1.2/csd01/virtio-v1.2-csd01.html#x1-3450002

Stefan


signature.asc
Description: PGP signature


libvirt hook to change domain xml

2025-02-18 Thread Victor Toso
Hi,

I'm particularly interested in the PoC of KubeVirt to allow
custom changes in libvirt domain xml in a more straightforward
manner than they have Today [0].

When I was looking into the libvirt hooks, I was a bit excited
when I read:

 > you can also place several hook scripts in the directory
 > /etc/libvirt/hooks/qemu.d/. They are executed in alphabetical
 > order after main script. In this case each script also acts as
 > filter and can modify the domain XML and print it out on its
 > standard output. This script output is passed to standard
 > input next script in order. Empty output from any script is
 > also identical to copying the input XML without changing it.
 > In case any script returns failure common process will be
 > aborted, but all scripts from the directory will are executed.

But that's not the case for every situation. When the domain is
being defined the scripts are run but the output is ignored [1]

Is there a reason for that?

In KubeVirt we basically have to re-implement [2] what the logic
around scripts under qemu.d already does. If we could use libvirt
only it would make testing easier for users and less code on
KubeVirt.

[0] https://kubevirt.io/user-guide/user_workloads/hook-sidecar/
[1] 
https://gitlab.com/libvirt/libvirt/-/blob/master/src/qemu/qemu_process.c#L4913
[2] https://github.com/kubevirt/kubevirt/blob/main/pkg/hooks/manager.go#L200

Cheers,
Victor


signature.asc
Description: PGP signature


[PATCH 1/1] nwfilter: Fix deadlock between nwfilter-list and VM startup/migration

2025-02-18 Thread Dion Bosschieter
A deadlock occurs when `nwfilterBindingCreateXML` and 
`nwfilterConnectListAllNWFilters`
acquire locks in an inconsistent order. This patch ensures 
`nwfilterBindingCreateXML`
acquires `driverMutex` before `updateLock`, resolving the issue.

Additionally, added `driverMutex` to `nwfilterBindingDelete` to maintain 
consistent locking order.

Signed-off-by: Dion Bosschieter 
---
 src/nwfilter/nwfilter_driver.c | 13 -
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/src/nwfilter/nwfilter_driver.c b/src/nwfilter/nwfilter_driver.c
index 8ece91bf7c..58e9fcfd51 100644
--- a/src/nwfilter/nwfilter_driver.c
+++ b/src/nwfilter/nwfilter_driver.c
@@ -754,11 +754,13 @@ nwfilterBindingCreateXML(virConnectPtr conn,
 if (!(ret = virGetNWFilterBinding(conn, def->portdevname, def->filter)))
 goto cleanup;
 
-VIR_WITH_MUTEX_LOCK_GUARD(&driver->updateLock) {
-if (virNWFilterInstantiateFilter(driver, def) < 0) {
-virNWFilterBindingObjListRemove(driver->bindings, obj);
-g_clear_pointer(&ret, virObjectUnref);
-goto cleanup;
+VIR_WITH_MUTEX_LOCK_GUARD(&driverMutex) {
+VIR_WITH_MUTEX_LOCK_GUARD(&driver->updateLock) {
+if (virNWFilterInstantiateFilter(driver, def) < 0) {
+virNWFilterBindingObjListRemove(driver->bindings, obj);
+g_clear_pointer(&ret, virObjectUnref);
+goto cleanup;
+}
 }
 }
 
@@ -783,6 +785,7 @@ nwfilterBindingCreateXML(virConnectPtr conn,
 static int
 nwfilterBindingDelete(virNWFilterBindingPtr binding)
 {
+VIR_LOCK_GUARD lock = virLockGuardLock(&driverMutex);
 virNWFilterBindingObj *obj;
 virNWFilterBindingDef *def;
 int ret = -1;
-- 
2.39.3 (Apple Git-146)


[PATCH 0/1] nwfilter: Fix deadlock between nwfilter-list and VM startup/migration

2025-02-18 Thread Dion Bosschieter
A deadlock occurs when `nwfilterBindingCreateXML` and 
`nwfilterConnectListAllNWFilters`
acquire locks in an inconsistent order. This affects both incoming migrations 
and
VM startups (`virsh start`), where `nwfilterBindingCreateXML` needs 
`updateLock`,
while `nwfilter-list` first acquires `driverMutex` and then locks individual 
filters.

This patch resolves the deadlock by ensuring `nwfilterBindingCreateXML` acquires
`driverMutex` before `updateLock`, following the locking pattern used by other
functions like `undefine` `nwfilterStateReload`.

Added the use of `driverMutex` in `nwfilterBindingDelete` to maintain
consistent locking order, as suggested.

Fixes: https://gitlab.com/libvirt/libvirt/-/issues/680

Dion Bosschieter (1):
  nwfilter: Fix deadlock between nwfilter-list and VM startup/migration

 src/nwfilter/nwfilter_driver.c | 13 -
 1 file changed, 8 insertions(+), 5 deletions(-)

-- 
2.39.3 (Apple Git-146)


Re: [PATCH RFC] util: pick a better runtime directory when XDG_RUNTIME_DIR isn't set

2025-02-18 Thread Daniel P . Berrangé
On Tue, Feb 18, 2025 at 02:50:52PM +, Daniel P. Berrangé wrote:
> On Tue, Feb 18, 2025 at 09:33:43AM -0500, Laine Stump wrote:
> > On 2/18/25 4:26 AM, Daniel P. Berrangé wrote:
> > > On Mon, Feb 17, 2025 at 03:11:56PM -0500, Laine Stump wrote:
> > > > On 2/17/25 5:28 AM, Daniel P. Berrangé wrote:
> > > > > On Mon, Feb 17, 2025 at 02:14:49AM -0500, Laine Stump wrote:
> > > > > > But sometimes XDG_RUNTIME_DIR isn't set in the user's environment.
> > > > > 
> > > > > Do you have examples of scenarios in which this happens, and
> > > > > yet the /run/user/ directory is still being created, as
> > > > > that rather sounds like something is broken outside of libvirt.
> > > > 
> > > > After seeing the bug report, I replicated the situation by ssh'ing in 
> > > > as a
> > > > user that hadn't previously logged in, and then unsetting 
> > > > XDG_RUNTIME_DIR. I
> > > > hadn't thought there might be some other case where the user could be 
> > > > logged
> > > > in but XDG_RUNTIME_DIR had never been set.
> > > > 
> > > > But after seeing your question I tried running
> > > > 
> > > >sudo $someuser virsh list
> > > 
> > > NB, that is the classic sudo usage trapdoor, because they didn't
> > > make "-i" (aka --login) the default, so your environment is not
> > > populated correctly.
> > > 
> > > I'd hope that when passing sudo -i ... it will do the right
> > > thing
> > 
> > It seems not. If I login as $someuser, start a guest, then in a separate
> > terminal window from root run:
> > 
> >   sudo -u $someuser -i virsh list
> > 
> > It returns an empty list (the same as if I omit the -i). By running the same
> > command without "virsh list", I'm given a shell instance, and within that
> > shell I can see that $UID, $USER, and $EUID are all set, but
> > $XDG_RUNTIME_DIR is not.
> 
> Hmm, this appears to be caused by systemd_pam
> 
> When using "su -" (similar seen with sudo)
> 
> su[5870]: pam_systemd(su-l:session): pam-systemd initializing
> su[5870]: pam_systemd(su-l:session): New sd-bus connection 
> (system-bus-pam-systemd-5870) opened.
> su[5870]: pam_systemd(su-l:session): Asking logind to create session: 
> uid=1001 pid=5870 service=su-l type=tty class=user desktop= seat= vtnr=0 
> tty=pts/3 display= remote=no remote_user=root remote_host=
> su[5870]: pam_systemd(su-l:session): Session limits: memory_max=n/a 
> tasks_max=n/a cpu_weight=n/a io_weight=n/a runtime_max_sec=n/a
> su[5870]: pam_systemd(su-l:session): Not creating session: Already running in 
> a session or user slice
> su[5870]: pam_systemd(su-l:session): pam-systemd shutting down
> 
> vs used with ssh:
> 
> sshd-session[5937]: pam_systemd(sshd:session): pam-systemd initializing
> sshd-session[5937]: pam_systemd(sshd:session): New sd-bus connection 
> (system-bus-pam-systemd-5937) opened.
> sshd-session[5937]: pam_systemd(sshd:session): Asking logind to create 
> session: uid=0 pid=5937 service=sshd type=tty class=user desktop= seat= 
> vtnr=0 tty= display= remote=yes remote_user= remote_host=10.42.28.158
> sshd-session[5937]: pam_systemd(sshd:session): Session limits: memory_max=n/a 
> tasks_max=n/a cpu_weight=n/a io_weight=n/a runtime_max_sec=n/a
> sshd-session[5937]: pam_systemd(sshd:session): Reply from logind: id=12 
> object_path=/org/freedesktop/login1/session/_312 runtime_path=/run/user/0 
> session_fd=9 seat= vtnr=0 original_uid=0
> 
> 
> So if the current user is already in a login sesssion, it'll refuse to
> start a new session.
> 
> I struggle to understand the rationale for this behaviour. It seems
> guaranteed to break stuff...

Apparently, 'su -' and 'sudo' shouldn't be used anymore if you
want a shell running as a different user which can run arbitrary
apps. Instead you're expected to use

   machinectl shell username@

Or 

   sudo machinectl shell username@

which will get the full set of env info setup.

I find it somewhat dubious to simply re-declare that decades of usage
of 'su' and 'sudo' is now wrong but that's the documented answer:

  https://github.com/systemd/systemd/issues/7451#issuecomment-346787237

Likewise in context of RHEL:

  https://access.redhat.com/solutions/6634751

Anyway, given that this is deliberate behaviour, I'm not convinced that
it is libvirt's job to workaround, even if we think that behaviour is
sub-optimal.

With regards,
Daniel
-- 
|: https://berrange.com  -o-https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o-https://fstop138.berrange.com :|
|: https://entangle-photo.org-o-https://www.instagram.com/dberrange :|


Re: libvirt hook to change domain xml

2025-02-18 Thread Jiri Denemark
On Tue, Feb 18, 2025 at 18:41:46 +0100, Victor Toso wrote:
> Hi,
> 
> I'm particularly interested in the PoC of KubeVirt to allow
> custom changes in libvirt domain xml in a more straightforward
> manner than they have Today [0].
> 
> When I was looking into the libvirt hooks, I was a bit excited
> when I read:
> 
>  > you can also place several hook scripts in the directory
>  > /etc/libvirt/hooks/qemu.d/. They are executed in alphabetical
>  > order after main script. In this case each script also acts as
>  > filter and can modify the domain XML and print it out on its
>  > standard output. This script output is passed to standard
>  > input next script in order. Empty output from any script is
>  > also identical to copying the input XML without changing it.
>  > In case any script returns failure common process will be
>  > aborted, but all scripts from the directory will are executed.
> 
> But that's not the case for every situation. When the domain is
> being defined the scripts are run but the output is ignored [1]
> 
> Is there a reason for that?

Libvirt only checks the output of pre-migration hook so that you can
change the XML on incoming migration on the destination host rather than
providing the updated XML to the migrate API.

The above paragraph talks about domain XML passing from one script to
the following one when there's more scripts defined in qemu.d/

Jirka


[PATCH 1/4] conf: introduce support for multiple ACPI tables

2025-02-18 Thread Daniel P . Berrangé
Currently we parse

   
 
   ...path...
 
   

into a flat 'char *slic_table' field which is rather an anti-pattern
as it has special cased a single attribute type.

This rewrites the internal design to permit multiple table types to
be parsed, should we add more in future. Each type is permitted to
only appear once.

The Xen code is fairly dubious in its use of 'slic_table' to hold
Xen's 'acpi_firmware' config option, as IIUC Xen's config is not
limited to accepting a single table per file. It takes a concatenation
of all data and ought to be represented as such. This is left for a
future contributor to solve.

Signed-off-by: Daniel P. Berrangé 
---
 src/conf/domain_conf.c  | 87 +
 src/conf/domain_conf.h  | 21 +++-
 src/libxl/libxl_conf.c  |  8 ++-
 src/libxl/xen_xl.c  | 22 +++--
 src/qemu/qemu_command.c | 13 +++--
 src/security/security_dac.c | 18 ---
 src/security/security_selinux.c | 16 +++---
 src/security/virt-aa-helper.c   |  5 +-
 8 files changed, 143 insertions(+), 47 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 49555efc56..04fb893587 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -1457,6 +1457,11 @@ VIR_ENUM_IMPL(virDomainOsDefFirmwareFeature,
   "secure-boot",
 );
 
+VIR_ENUM_IMPL(virDomainOsACPITable,
+  VIR_DOMAIN_OS_ACPI_TABLE_TYPE_LAST,
+  "slic",
+);
+
 VIR_ENUM_IMPL(virDomainCFPC,
   VIR_DOMAIN_CFPC_LAST,
   "none",
@@ -3899,6 +3904,15 @@ virDomainSecDefFree(virDomainSecDef *def)
 g_free(def);
 }
 
+void virDomainOSACPITableDefFree(virDomainOSACPITableDef *def)
+{
+if (!def)
+return;
+g_free(def->path);
+g_free(def);
+}
+
+
 static void
 virDomainOSDefClear(virDomainOSDef *os)
 {
@@ -3924,7 +3938,9 @@ virDomainOSDefClear(virDomainOSDef *os)
 g_free(os->cmdline);
 g_free(os->dtb);
 g_free(os->root);
-g_free(os->slic_table);
+for (i = 0; i < os->nacpiTables; i++)
+virDomainOSACPITableDefFree(os->acpiTables[i]);
+g_free(os->acpiTables);
 virDomainLoaderDefFree(os->loader);
 g_free(os->bootloader);
 g_free(os->bootloaderArgs);
@@ -17873,40 +17889,64 @@ virDomainDefParseBootAcpiOptions(virDomainDef *def,
 int n;
 g_autofree xmlNodePtr *nodes = NULL;
 g_autofree char *tmp = NULL;
+size_t ntables = 0;
+virDomainOSACPITableDef **tables = NULL;
+size_t i;
+size_t j;
 
 if ((n = virXPathNodeSet("./os/acpi/table", ctxt, &nodes)) < 0)
 return -1;
 
-if (n > 1) {
-virReportError(VIR_ERR_XML_ERROR, "%s",
-   _("Only one acpi table is supported"));
-return -1;
-}
-
-if (n == 1) {
-tmp = virXMLPropString(nodes[0], "type");
+for (i = 0; i < n; i++) {
+int type;
+tmp = virXMLPropString(nodes[i], "type");
 
 if (!tmp) {
 virReportError(VIR_ERR_XML_ERROR, "%s",
_("Missing acpi table type"));
-return -1;
+goto error;
 }
 
-if (STREQ_NULLABLE(tmp, "slic")) {
-VIR_FREE(tmp);
-if (!(tmp = virXMLNodeContentString(nodes[0])))
-return -1;
-
-def->os.slic_table = virFileSanitizePath(tmp);
-} else {
+if ((type = virDomainOsACPITableTypeFromString(tmp)) < 0) {
 virReportError(VIR_ERR_XML_ERROR,
_("Unknown acpi table type: %1$s"),
tmp);
-return -1;
+goto error;
 }
+
+for (j = 0; j < i; j++) {
+if (tables[j]->type == type) {
+virReportError(VIR_ERR_XML_ERROR,
+   _("ACPI table type '%1$s' may only appear 
once"),
+   tmp);
+goto error;
+}
+}
+
+VIR_FREE(tmp);
+if (!(tmp = virXMLNodeContentString(nodes[i])))
+goto error;
+
+tables = g_renew(virDomainOSACPITableDef *, tables, ntables + 1);
+tables[ntables] = g_new0(virDomainOSACPITableDef, 1);
+tables[ntables]->type = type;
+tables[ntables]->path = virFileSanitizePath(tmp);
+ntables++;
+
+VIR_FREE(tmp);
 }
 
+def->os.nacpiTables = ntables;
+def->os.acpiTables = tables;
+
 return 0;
+
+ error:
+for (i = 0; i < ntables; i++) {
+virDomainOSACPITableDefFree(tables[i]);
+}
+g_free(tables);
+return -1;
 }
 
 
@@ -28490,11 +28530,16 @@ virDomainDefFormatInternalSetRootName(virDomainDef 
*def,
   def->os.dtb);
 virBufferEscapeString(buf, "%s\n",
   def->os.root);
-if (def->os.slic_table) {
+
+if (def->os.nacpiTables) {
 virBufferAddLit(buf, "\n");
 virBufferAdjustIndent(buf, 2);
-virBufferEscapeString(buf, "%s\

[PATCH 2/4] src: validate permitted ACPI table types in libxl/qemu drivers

2025-02-18 Thread Daniel P . Berrangé
Signed-off-by: Daniel P. Berrangé 
---
 src/libxl/libxl_domain.c | 14 ++
 src/qemu/qemu_validate.c | 15 +++
 2 files changed, 29 insertions(+)

diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c
index 6805160923..816ed2f349 100644
--- a/src/libxl/libxl_domain.c
+++ b/src/libxl/libxl_domain.c
@@ -306,6 +306,7 @@ libxlDomainDefValidate(const virDomainDef *def,
 libxlDriverPrivate *driver = opaque;
 g_autoptr(libxlDriverConfig) cfg = libxlDriverConfigGet(driver);
 bool reqSecureBoot = false;
+size_t i;
 
 if (!virCapabilitiesDomainSupported(cfg->caps, def->os.type,
 def->os.arch,
@@ -330,6 +331,19 @@ libxlDomainDefValidate(const virDomainDef *def,
 return -1;
 }
 
+for (i = 0; i < def->os.nacpiTables; i++) {
+switch ((virDomainOsACPITable)def->os.acpiTables[i]->type) {
+case VIR_DOMAIN_OS_ACPI_TABLE_TYPE_SLIC:
+break;
+
+default:
+case VIR_DOMAIN_OS_ACPI_TABLE_TYPE_LAST:
+virReportEnumRangeError(virDomainOsACPITable,
+def->os.acpiTables[i]->type);
+return -1;
+}
+}
+
 if (def->nsounds > 0) {
 virDomainSoundDef *snd = def->sounds[0];
 
diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c
index 3e3e368da3..039f5f84e6 100644
--- a/src/qemu/qemu_validate.c
+++ b/src/qemu/qemu_validate.c
@@ -701,6 +701,8 @@ static int
 qemuValidateDomainDefBoot(const virDomainDef *def,
   virQEMUCaps *qemuCaps)
 {
+size_t i;
+
 if (def->os.bootloader || def->os.bootloaderArgs) {
 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("bootloader is not supported by QEMU"));
@@ -740,6 +742,19 @@ qemuValidateDomainDefBoot(const virDomainDef *def,
 return -1;
 }
 
+for (i = 0; i < def->os.nacpiTables; i++) {
+switch ((virDomainOsACPITable)def->os.acpiTables[i]->type) {
+case VIR_DOMAIN_OS_ACPI_TABLE_TYPE_SLIC:
+break;
+
+default:
+case VIR_DOMAIN_OS_ACPI_TABLE_TYPE_LAST:
+virReportEnumRangeError(virDomainOsACPITable,
+def->os.acpiTables[i]->type);
+return -1;
+}
+}
+
 return 0;
 }
 
-- 
2.47.1


[PATCH 0/4] Add support for MSDM ACPI table type

2025-02-18 Thread Daniel P . Berrangé
This was requested by KubeVirt in

  https://gitlab.com/libvirt/libvirt/-/issues/748

I've not functionally tested this, since I lack any suitable guest
windows environment this is looking for MSDM tables, nor does my
machine have MSDM ACPI tables to pass to a guest.

I'm blindly assuming that the QEMU CLI code is identical except for
s/SLIC/MSDM/.

Also I'm pretty unhappy about the situation with the Xen driver
support. This is pre-existing, and IMHO should never have been added
as it exists today, as it allows arbitrary passthrough of *any* set
of ACPI tables, as opposed to a single type of the specific type
listed in the XML.  This should have been handled with a different
XML syntax, but with stuck with this undesirable approach now, so
I've kept it as is.

Daniel P. Berrangé (4):
  conf: introduce support for multiple ACPI tables
  src: validate permitted ACPI table types in libxl/qemu drivers
  conf: support MSDM ACPI table type
  qemu: support MSDM ACPI table type

 docs/formatdomain.rst |  4 +-
 src/conf/domain_conf.c| 88 ++-
 src/conf/domain_conf.h| 22 -
 src/conf/schemas/domaincommon.rng |  5 +-
 src/libvirt_private.syms  |  2 +
 src/libxl/libxl_conf.c|  8 +-
 src/libxl/libxl_domain.c  | 21 +
 src/libxl/xen_xl.c| 22 -
 src/qemu/qemu_command.c   | 14 ++-
 src/qemu/qemu_validate.c  | 16 
 src/security/security_dac.c   | 18 ++--
 src/security/security_selinux.c   | 16 ++--
 src/security/virt-aa-helper.c |  5 +-
 .../acpi-table-many.x86_64-latest.args| 34 +++
 .../acpi-table-many.x86_64-latest.xml | 39 
 tests/qemuxmlconfdata/acpi-table-many.xml | 31 +++
 tests/qemuxmlconftest.c   |  1 +
 17 files changed, 296 insertions(+), 50 deletions(-)
 create mode 100644 tests/qemuxmlconfdata/acpi-table-many.x86_64-latest.args
 create mode 100644 tests/qemuxmlconfdata/acpi-table-many.x86_64-latest.xml
 create mode 100644 tests/qemuxmlconfdata/acpi-table-many.xml

-- 
2.47.1


[PATCH 3/4] conf: support MSDM ACPI table type

2025-02-18 Thread Daniel P . Berrangé
The MSDM ACPI table is a replacement for the SLIC table type, now
preferred by Microsoft for Windows Licensing checks:

  
https://learn.microsoft.com/en-us/previous-versions/windows/hardware/design/dn653305(v=vs.85)

Signed-off-by: Daniel P. Berrangé 
---
 docs/formatdomain.rst | 4 ++--
 src/conf/domain_conf.c| 1 +
 src/conf/domain_conf.h| 1 +
 src/conf/schemas/domaincommon.rng | 5 -
 src/libvirt_private.syms  | 2 ++
 src/libxl/libxl_domain.c  | 7 +++
 src/qemu/qemu_validate.c  | 7 +++
 7 files changed, 24 insertions(+), 3 deletions(-)

diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
index 381bf84f67..81dfd310ae 100644
--- a/docs/formatdomain.rst
+++ b/docs/formatdomain.rst
@@ -485,8 +485,8 @@ These options apply to any form of booting of the guest OS.
 
 ``acpi``
The ``table`` element contains a fully-qualified path to the ACPI table. The
-   ``type`` attribute contains the ACPI table type (currently only ``slic`` is
-   supported) :since:`Since 1.3.5 (QEMU)` :since:`Since 5.9.0 (Xen)`
+   ``type`` attribute contains the ACPI table type:  ``slic`` (:since:`Since 
1.3.5 (QEMU)`
+   :since:`Since 5.9.0 (Xen)`, ``msdm``.
 
 
 SMBIOS System Information
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 04fb893587..e0f9ad3123 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -1460,6 +1460,7 @@ VIR_ENUM_IMPL(virDomainOsDefFirmwareFeature,
 VIR_ENUM_IMPL(virDomainOsACPITable,
   VIR_DOMAIN_OS_ACPI_TABLE_TYPE_LAST,
   "slic",
+  "msdm",
 );
 
 VIR_ENUM_IMPL(virDomainCFPC,
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 7735cce325..d84da21cca 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -2476,6 +2476,7 @@ VIR_ENUM_DECL(virDomainOsDefFirmwareFeature);
 
 typedef enum {
 VIR_DOMAIN_OS_ACPI_TABLE_TYPE_SLIC,
+VIR_DOMAIN_OS_ACPI_TABLE_TYPE_MSDM,
 
 VIR_DOMAIN_OS_ACPI_TABLE_TYPE_LAST
 } virDomainOsACPITable;
diff --git a/src/conf/schemas/domaincommon.rng 
b/src/conf/schemas/domaincommon.rng
index 3328a63205..9bae953295 100644
--- a/src/conf/schemas/domaincommon.rng
+++ b/src/conf/schemas/domaincommon.rng
@@ -7191,7 +7191,10 @@
   
 
   
-slic
+
+  slic
+  msdm
+
   
   
 
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 30a9f806f0..db8c29ec1d 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -611,6 +611,8 @@ virDomainObjTaint;
 virDomainObjUpdateModificationImpact;
 virDomainObjWait;
 virDomainObjWaitUntil;
+virDomainOsACPITableTypeFromString;
+virDomainOsACPITableTypeToString;
 virDomainOsDefFirmwareTypeFromString;
 virDomainOsDefFirmwareTypeToString;
 virDomainOSTypeFromString;
diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c
index 816ed2f349..5fb85931f4 100644
--- a/src/libxl/libxl_domain.c
+++ b/src/libxl/libxl_domain.c
@@ -336,6 +336,13 @@ libxlDomainDefValidate(const virDomainDef *def,
 case VIR_DOMAIN_OS_ACPI_TABLE_TYPE_SLIC:
 break;
 
+case VIR_DOMAIN_OS_ACPI_TABLE_TYPE_MSDM:
+virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+   _("ACPI table '%1$s' not supported"),
+   virDomainOsACPITableTypeToString(
+   def->os.acpiTables[i]->type));
+return -1;
+
 default:
 case VIR_DOMAIN_OS_ACPI_TABLE_TYPE_LAST:
 virReportEnumRangeError(virDomainOsACPITable,
diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c
index 039f5f84e6..0b3efcd700 100644
--- a/src/qemu/qemu_validate.c
+++ b/src/qemu/qemu_validate.c
@@ -747,6 +747,13 @@ qemuValidateDomainDefBoot(const virDomainDef *def,
 case VIR_DOMAIN_OS_ACPI_TABLE_TYPE_SLIC:
 break;
 
+case VIR_DOMAIN_OS_ACPI_TABLE_TYPE_MSDM:
+virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+   _("ACPI table '%1$s' not supported"),
+   virDomainOsACPITableTypeToString(
+   def->os.acpiTables[i]->type));
+return -1;
+
 default:
 case VIR_DOMAIN_OS_ACPI_TABLE_TYPE_LAST:
 virReportEnumRangeError(virDomainOsACPITable,
-- 
2.47.1


[PATCH 4/4] qemu: support MSDM ACPI table type

2025-02-18 Thread Daniel P . Berrangé
The MSDM ACPI table is a replacement for the SLIC table type, now
preferred by Microsoft for Windows Licensing checks:

  
https://learn.microsoft.com/en-us/previous-versions/windows/hardware/design/dn653305(v=vs.85)

Resolves: https://gitlab.com/libvirt/libvirt/-/issues/748
Signed-off-by: Daniel P. Berrangé 
---
 src/qemu/qemu_command.c   |  3 +-
 src/qemu/qemu_validate.c  |  8 +---
 .../acpi-table-many.x86_64-latest.args| 34 
 .../acpi-table-many.x86_64-latest.xml | 39 +++
 tests/qemuxmlconfdata/acpi-table-many.xml | 31 +++
 tests/qemuxmlconftest.c   |  1 +
 6 files changed, 108 insertions(+), 8 deletions(-)
 create mode 100644 tests/qemuxmlconfdata/acpi-table-many.x86_64-latest.args
 create mode 100644 tests/qemuxmlconfdata/acpi-table-many.x86_64-latest.xml
 create mode 100644 tests/qemuxmlconfdata/acpi-table-many.xml

diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 1153d8e095..485b82f853 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -130,7 +130,8 @@ VIR_ENUM_IMPL(qemuNumaPolicy,
 VIR_ENUM_DECL(qemuACPITableSIG);
 VIR_ENUM_IMPL(qemuACPITableSIG,
   VIR_DOMAIN_OS_ACPI_TABLE_TYPE_LAST,
-  "SLIC");
+  "SLIC",
+  "MSDM");
 
 
 const char *
diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c
index 0b3efcd700..42f9b14f25 100644
--- a/src/qemu/qemu_validate.c
+++ b/src/qemu/qemu_validate.c
@@ -745,14 +745,8 @@ qemuValidateDomainDefBoot(const virDomainDef *def,
 for (i = 0; i < def->os.nacpiTables; i++) {
 switch ((virDomainOsACPITable)def->os.acpiTables[i]->type) {
 case VIR_DOMAIN_OS_ACPI_TABLE_TYPE_SLIC:
-break;
-
 case VIR_DOMAIN_OS_ACPI_TABLE_TYPE_MSDM:
-virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
-   _("ACPI table '%1$s' not supported"),
-   virDomainOsACPITableTypeToString(
-   def->os.acpiTables[i]->type));
-return -1;
+break;
 
 default:
 case VIR_DOMAIN_OS_ACPI_TABLE_TYPE_LAST:
diff --git a/tests/qemuxmlconfdata/acpi-table-many.x86_64-latest.args 
b/tests/qemuxmlconfdata/acpi-table-many.x86_64-latest.args
new file mode 100644
index 00..a4d4f4b53d
--- /dev/null
+++ b/tests/qemuxmlconfdata/acpi-table-many.x86_64-latest.args
@@ -0,0 +1,34 @@
+LC_ALL=C \
+PATH=/bin \
+HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1 \
+USER=test \
+LOGNAME=test \
+XDG_DATA_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.local/share \
+XDG_CACHE_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.cache \
+XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \
+/usr/bin/qemu-system-x86_64 \
+-name guest=QEMUGuest1,debug-threads=on \
+-S \
+-object 
'{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain--1-QEMUGuest1/master-key.aes"}'
 \
+-machine pc,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=on \
+-accel tcg \
+-cpu qemu64 \
+-m size=219136k \
+-object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":224395264}' \
+-overcommit mem-lock=off \
+-smp 1,sockets=1,cores=1,threads=1 \
+-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
+-display none \
+-no-user-config \
+-nodefaults \
+-chardev socket,id=charmonitor,fd=1729,server=on,wait=off \
+-mon chardev=charmonitor,id=monitor,mode=control \
+-rtc base=utc \
+-no-shutdown \
+-boot strict=on \
+-acpitable sig=SLIC,file=/var/lib/libvirt/acpi/slic.dat \
+-acpitable sig=MSDM,file=/var/lib/libvirt/acpi/msdm.dat \
+-device 
'{"driver":"piix3-usb-uhci","id":"usb","bus":"pci.0","addr":"0x1.0x2"}' \
+-audiodev '{"id":"audio1","driver":"none"}' \
+-sandbox 
on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \
+-msg timestamp=on
diff --git a/tests/qemuxmlconfdata/acpi-table-many.x86_64-latest.xml 
b/tests/qemuxmlconfdata/acpi-table-many.x86_64-latest.xml
new file mode 100644
index 00..7d42e377c9
--- /dev/null
+++ b/tests/qemuxmlconfdata/acpi-table-many.x86_64-latest.xml
@@ -0,0 +1,39 @@
+
+  QEMUGuest1
+  c7a5fdbd-edaf-9455-926a-d65c16db1809
+  219136
+  219136
+  1
+  
+hvm
+
+  /var/lib/libvirt/acpi/slic.dat
+  /var/lib/libvirt/acpi/msdm.dat
+
+
+  
+  
+
+  
+  
+qemu64
+  
+  
+  destroy
+  restart
+  destroy
+  
+/usr/bin/qemu-system-x86_64
+
+  
+
+
+  
+
+
+
+
+
+
+  
+
diff --git a/tests/qemuxmlconfdata/acpi-table-many.xml 
b/tests/qemuxmlconfdata/acpi-table-many.xml
new file mode 100644
index 00..710f3131e1
--- /dev/null
+++ b/tests/qemuxmlconfdata/acpi-table-many.xml
@@ -0,0 +1,31 @@
+
+  QEMUGuest1
+  c7a5fdbd-edaf-9455-926a-d65c16db1809
+  219136
+  219136
+  1
+  
+hvm
+
+
+  /var/lib/libvirt/acpi/slic.dat
+  /var/lib/libvirt/acpi/msdm.dat
+
+  
+  
+
+  
+  
+  destroy
+  r

[PATCH] qemu: Avoid crash in qemuDomainCheckCPU with unknown host CPU

2025-02-18 Thread Jiri Denemark
When we don't have any information about host CPU (for example when
running on an aarch64 host), the virQEMUCapsGetHostModel would return
NULL.

Fixes: https://gitlab.com/libvirt/libvirt/-/issues/747
Signed-off-by: Jiri Denemark 
---
 src/qemu/qemu_domain.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index cf05dca55a..df1ed0223d 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -11430,6 +11430,7 @@ qemuDomainCheckCPU(virArch arch,
 /* Force compat check if the CPU model is not found in qemuCaps or
  * we don't have host CPU data from QEMU */
 if (!cpu->model ||
+!hypervisorCPU ||
 hypervisorCPU->fallback != VIR_CPU_FALLBACK_FORBID ||
 virQEMUCapsGetCPUBlockers(qemuCaps, virtType,
   cpu->model, &blockers) < 0)
-- 
2.48.1


[PATCH 5/5] tests: Add test case for NVMe device configuration

2025-02-18 Thread honglei . wang
From: ray 

This completes the test coverage for the recently added NVMe disk bus support.

Signed-off-by: ray 
---
 .../disk-nvme-device.x86_64-latest.args| 38 +
 .../disk-nvme-device.x86_64-latest.xml | 49 ++
 tests/qemuxmlconfdata/disk-nvme-device.xml | 46 
 tests/qemuxmlconftest.c|  1 +
 4 files changed, 134 insertions(+)
 create mode 100644 tests/qemuxmlconfdata/disk-nvme-device.x86_64-latest.args
 create mode 100644 tests/qemuxmlconfdata/disk-nvme-device.x86_64-latest.xml
 create mode 100644 tests/qemuxmlconfdata/disk-nvme-device.xml

diff --git a/tests/qemuxmlconfdata/disk-nvme-device.x86_64-latest.args 
b/tests/qemuxmlconfdata/disk-nvme-device.x86_64-latest.args
new file mode 100644
index 00..2ac720b676
--- /dev/null
+++ b/tests/qemuxmlconfdata/disk-nvme-device.x86_64-latest.args
@@ -0,0 +1,38 @@
+LC_ALL=C \
+PATH=/bin \
+HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1 \
+USER=test \
+LOGNAME=test \
+XDG_DATA_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.local/share \
+XDG_CACHE_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.cache \
+XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \
+/usr/bin/qemu-system-x86_64 \
+-name guest=QEMUGuest1,debug-threads=on \
+-S \
+-object 
'{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain--1-QEMUGuest1/master-key.aes"}'
 \
+-machine pc,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \
+-accel tcg \
+-cpu qemu64 \
+-m size=219136k \
+-object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":224395264}' \
+-overcommit mem-lock=off \
+-smp 1,sockets=1,cores=1,threads=1 \
+-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
+-display none \
+-no-user-config \
+-nodefaults \
+-chardev socket,id=charmonitor,fd=1729,server=on,wait=off \
+-mon chardev=charmonitor,id=monitor,mode=control \
+-rtc base=utc \
+-no-shutdown \
+-boot strict=on \
+-device 
'{"driver":"piix3-usb-uhci","id":"usb","bus":"pci.0","addr":"0x1.0x2"}' \
+-device '{"driver":"virtio-scsi-pci","id":"scsi0","bus":"pci.0","addr":"0x3"}' 
\
+-device 
'{"driver":"nvme","id":"nvme0","serial":"nvme-controller-abcdef","bus":"pci.0","addr":"0x5"}'
 \
+-blockdev 
'{"driver":"file","filename":"/tmp/data-1.img","node-name":"libvirt-2-storage","read-only":false}'
 \
+-device 
'{"driver":"nvme","bus":"pci.0","addr":"0x2","drive":"libvirt-2-storage","id":"nvme-disk0","bootindex":1,"serial":"nvme-abcdef"}'
 \
+-blockdev 
'{"driver":"file","filename":"/tmp/data-2.img","node-name":"libvirt-1-storage","read-only":false}'
 \
+-device 
'{"driver":"nvme-ns","bus":"nvme0","drive":"libvirt-1-storage","id":"nvme-ns0-0-0"}'
 \
+-audiodev '{"id":"audio1","driver":"none"}' \
+-sandbox 
on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \
+-msg timestamp=on
diff --git a/tests/qemuxmlconfdata/disk-nvme-device.x86_64-latest.xml 
b/tests/qemuxmlconfdata/disk-nvme-device.x86_64-latest.xml
new file mode 100644
index 00..3f3c1a253e
--- /dev/null
+++ b/tests/qemuxmlconfdata/disk-nvme-device.x86_64-latest.xml
@@ -0,0 +1,49 @@
+
+  QEMUGuest1
+  c7a5fdbd-edaf-9455-926a-d65c16db1809
+  219136
+  219136
+  1
+  
+hvm
+
+  
+  
+qemu64
+  
+  
+  destroy
+  restart
+  destroy
+  
+/usr/bin/qemu-system-x86_64
+
+  
+  
+  
+  nvme-abcdef
+  
+
+
+  
+  
+  
+  
+
+
+  
+
+
+
+  
+
+
+  nvme-controller-abcdef
+  
+
+
+
+
+
+  
+
diff --git a/tests/qemuxmlconfdata/disk-nvme-device.xml 
b/tests/qemuxmlconfdata/disk-nvme-device.xml
new file mode 100644
index 00..27aa973677
--- /dev/null
+++ b/tests/qemuxmlconfdata/disk-nvme-device.xml
@@ -0,0 +1,46 @@
+
+  QEMUGuest1
+  c7a5fdbd-edaf-9455-926a-d65c16db1809
+  219136
+  219136
+  1
+  
+hvm
+  
+  
+qemu64
+  
+  
+  destroy
+  restart
+  destroy
+  
+/usr/bin/qemu-system-x86_64
+
+  
+  
+  nvme-abcdef
+  
+
+
+  
+  
+  
+
+
+  
+
+
+
+  
+
+  
+  nvme-controller-abcdef
+  
+
+
+
+
+
+  
+
diff --git a/tests/qemuxmlconftest.c b/tests/qemuxmlconftest.c
index c271170d25..c3d38180e6 100644
--- a/tests/qemuxmlconftest.c
+++ b/tests/qemuxmlconftest.c
@@ -1606,6 +1606,7 @@ mymain(void)
 DO_TEST_CAPS_LATEST("disk-network-ssh");
 DO_TEST_CAPS_LATEST("disk-no-boot");
 DO_TEST_CAPS_LATEST("disk-nvme");
+DO_TEST_CAPS_LATEST("disk-nvme-device");
 DO_TEST_CAPS_LATEST("disk-vhostuser-numa");
 DO_TEST_CAPS_LATEST("disk-vhostuser");
 DO_TEST_CAPS_ARCH_LATEST_FULL("disk-vhostvdpa", "x86_64",
-- 
2.11.0


[PATCH 0/5] qemu: Introduce nvme disk emulation support

2025-02-18 Thread honglei . wang
From: hongleiwang 

QEMU has supported nvme disk emulation for a long time,
see: https://qemu-project.gitlab.io/qemu/system/devices/nvme.html.

The following patches introduce nvme and nvme-ns disk bus type:
A disk with nvme as bus is represented as nvme disk that contains
only one nvme namespace. In XML, it can be used like this:

  ...
  



nvme-serial-value
  
  ...


A disk with nvme-ns as bus is represented as an nvme namespace
and needs to be attached to an nvme controller. In XML, it can be
used like this:

  ...
  




  
  
nvme-controller-serial-value

  
  ...


ray (5):
  qemu: Add support for NVMe disk bus type
  qemu: Add support for NVMe namespace disk bus type
  qemu_capabilities: Add support for NVMe disk capabilities
  docs: Add NVMe and NVMe namespace disk bus types to documentation
  tests: Add test case for NVMe device configuration

 docs/formatdomain.rst  |  5 ++-
 src/conf/domain_conf.c | 42 +++
 src/conf/domain_conf.h |  8 
 src/conf/domain_postparse.c|  4 ++
 src/conf/domain_validate.c |  5 ++-
 src/conf/schemas/domaincommon.rng  | 12 +-
 src/conf/virconftypes.h|  2 +
 src/hyperv/hyperv_driver.c |  4 ++
 src/qemu/qemu_alias.c  |  2 +
 src/qemu/qemu_capabilities.c   | 10 +
 src/qemu/qemu_capabilities.h   |  2 +
 src/qemu/qemu_command.c| 31 ++
 src/qemu/qemu_domain_address.c | 30 +++--
 src/qemu/qemu_domain_address.h |  4 ++
 src/qemu/qemu_hotplug.c| 14 +++
 src/qemu/qemu_postparse.c  |  1 +
 src/qemu/qemu_validate.c   | 40 ++
 src/test/test_driver.c |  4 ++
 src/util/virutil.c |  2 +-
 src/vbox/vbox_common.c |  3 ++
 src/vmx/vmx.c  |  2 +
 tests/domaincapsdata/qemu_10.0.0-q35.x86_64.xml|  2 +
 tests/domaincapsdata/qemu_10.0.0-tcg.x86_64.xml|  2 +
 tests/domaincapsdata/qemu_10.0.0.s390x.xml |  2 +
 tests/domaincapsdata/qemu_10.0.0.x86_64.xml|  2 +
 tests/domaincapsdata/qemu_5.2.0-q35.x86_64.xml |  2 +
 .../domaincapsdata/qemu_5.2.0-tcg-virt.riscv64.xml |  2 +
 tests/domaincapsdata/qemu_5.2.0-tcg.x86_64.xml |  2 +
 tests/domaincapsdata/qemu_5.2.0-virt.aarch64.xml   |  2 +
 tests/domaincapsdata/qemu_5.2.0-virt.riscv64.xml   |  2 +
 tests/domaincapsdata/qemu_5.2.0.aarch64.xml|  2 +
 tests/domaincapsdata/qemu_5.2.0.ppc64.xml  |  2 +
 tests/domaincapsdata/qemu_5.2.0.x86_64.xml |  2 +
 tests/domaincapsdata/qemu_6.0.0-q35.x86_64.xml |  2 +
 tests/domaincapsdata/qemu_6.0.0-tcg.x86_64.xml |  2 +
 tests/domaincapsdata/qemu_6.0.0-virt.aarch64.xml   |  2 +
 tests/domaincapsdata/qemu_6.0.0.aarch64.xml|  2 +
 tests/domaincapsdata/qemu_6.0.0.x86_64.xml |  2 +
 tests/domaincapsdata/qemu_6.1.0-q35.x86_64.xml |  2 +
 tests/domaincapsdata/qemu_6.1.0-tcg.x86_64.xml |  2 +
 tests/domaincapsdata/qemu_6.1.0.x86_64.xml |  2 +
 tests/domaincapsdata/qemu_6.2.0-q35.x86_64.xml |  2 +
 tests/domaincapsdata/qemu_6.2.0-tcg.x86_64.xml |  2 +
 tests/domaincapsdata/qemu_6.2.0-virt.aarch64.xml   |  2 +
 tests/domaincapsdata/qemu_6.2.0.aarch64.xml|  2 +
 tests/domaincapsdata/qemu_6.2.0.ppc64.xml  |  2 +
 tests/domaincapsdata/qemu_6.2.0.x86_64.xml |  2 +
 .../domaincapsdata/qemu_7.0.0-hvf.aarch64+hvf.xml  |  2 +
 tests/domaincapsdata/qemu_7.0.0-q35.x86_64.xml |  2 +
 tests/domaincapsdata/qemu_7.0.0-tcg.x86_64.xml |  2 +
 tests/domaincapsdata/qemu_7.0.0-virt.aarch64.xml   |  2 +
 tests/domaincapsdata/qemu_7.0.0.aarch64.xml|  2 +
 tests/domaincapsdata/qemu_7.0.0.ppc64.xml  |  2 +
 tests/domaincapsdata/qemu_7.0.0.x86_64.xml |  2 +
 tests/domaincapsdata/qemu_7.1.0-q35.x86_64.xml |  2 +
 tests/domaincapsdata/qemu_7.1.0-tcg.x86_64.xml |  2 +
 tests/domaincapsdata/qemu_7.1.0.ppc64.xml  |  2 +
 tests/domaincapsdata/qemu_7.1.0.x86_64.xml |  2 +
 tests/domaincapsdata/qemu_7.2.0-hvf.x86_64+hvf.xml |  2 +
 tests/domaincapsdata/qemu_7.2.0-q35.x86_64.xml |  2 +
 tests/domaincapsdata/qemu_7.2.0-tcg.x86_64+hvf.xml |  2 +
 tests/domaincapsdata/qemu_7.2.0-tcg.x86_64.xml |  2 +
 tests/domaincapsdata/qemu_7.2.0.ppc.xml|  2 +
 tests/domaincapsdata/qemu_7.2.0.x86_64.xml |  2 +
 tests/domaincapsdata/qemu_8.0.0-q35.x86_64.xml |  2 +
 .../domaincapsdata/qemu_8.0.0-tcg-virt.riscv64.xml |  2 +
 tests/domaincapsdata/qemu_8.0.0-tcg.x86_64.xml |  2 +
 tests/domaincapsdata/qemu_8.0.0-virt.riscv64.xml 

[PATCH 4/5] docs: Add NVMe and NVMe namespace disk bus types to documentation

2025-02-18 Thread honglei . wang
From: ray 

Update documentation to include nvme and nvme-ns disk bus types:
- Add "nvme" and "nvme-ns" to the list of supported disk bus types
- Extend the allowed disk target device patterns to include nvme and nvmens 
prefixes

Signed-off-by: ray 
---
 docs/formatdomain.rst |  5 +++--
 src/conf/schemas/domaincommon.rng | 12 +++-
 2 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
index 381bf84f67..92d3c58503 100644
--- a/docs/formatdomain.rst
+++ b/docs/formatdomain.rst
@@ -3248,7 +3248,8 @@ paravirtualized driver is specified via the ``disk`` 
element.
name in the guest OS. Treat it as a device ordering hint. The optional
``bus`` attribute specifies the type of disk device to emulate; possible
values are driver specific, with typical values being "ide", "scsi",
-   "virtio", "xen", "usb", "sata", or "sd" :since:`"sd" since 1.1.2`. If
+   "virtio", "xen", "usb", "sata", "sd" :since:`"sd" since 1.1.2`, "nvme" or
+   "nvme-ns":since:`"nvme" and "nvme-ns" since 11.1.0`. If
omitted, the bus type is inferred from the style of the device name (e.g. a
device named 'sda' will typically be exported using a SCSI bus). The 
optional
attribute ``tray`` indicates the tray status of the removable disks (i.e.
@@ -4047,7 +4048,7 @@ device hotplug is expected.
...
 
 Each controller has a mandatory attribute ``type``, which must be one of 'ide',
-'fdc', 'scsi', 'sata', 'usb', 'ccid', 'virtio-serial' or 'pci', and a mandatory
+'fdc', 'scsi', 'sata', 'usb', 'ccid', 'virtio-serial', 'pci' or "nvme", and a 
mandatory
 attribute ``index`` which is the decimal integer describing in which order the
 bus controller is encountered (for use in ``controller`` attributes of
  elements). :since:`Since 1.3.5` the index is optional; if not
diff --git a/src/conf/schemas/domaincommon.rng 
b/src/conf/schemas/domaincommon.rng
index 3328a63205..afa98d5266 100644
--- a/src/conf/schemas/domaincommon.rng
+++ b/src/conf/schemas/domaincommon.rng
@@ -2520,7 +2520,7 @@
 
   
 
-  (ioemu:)?(fd|hd|sd|vd|xvd|ubd)[a-zA-Z0-9_]+
+  (ioemu:)?(fd|hd|sd|vd|xvd|ubd|nvmens|nvme)[a-zA-Z0-9_]+
 
   
 
@@ -2541,6 +2541,8 @@
 uml 
 sata
 sd
+nvme
+nvme-ns
   
 
   
@@ -3046,6 +3048,14 @@
   
 
   
+  
+
+  nvme
+
+
+  
+
+  
 
 
   
-- 
2.11.0


Re: libvirt hook to change domain xml

2025-02-18 Thread Victor Toso
Hi,

On Tue, Feb 18, 2025 at 07:11:45PM +0100, Jiri Denemark wrote:
> On Tue, Feb 18, 2025 at 18:41:46 +0100, Victor Toso wrote:
> > Hi,
> > 
> > I'm particularly interested in the PoC of KubeVirt to allow
> > custom changes in libvirt domain xml in a more straightforward
> > manner than they have Today [0].
> > 
> > When I was looking into the libvirt hooks, I was a bit excited
> > when I read:
> > 
> >  > you can also place several hook scripts in the directory
> >  > /etc/libvirt/hooks/qemu.d/. They are executed in alphabetical
> >  > order after main script. In this case each script also acts as
> >  > filter and can modify the domain XML and print it out on its
> >  > standard output. This script output is passed to standard
> >  > input next script in order. Empty output from any script is
> >  > also identical to copying the input XML without changing it.
> >  > In case any script returns failure common process will be
> >  > aborted, but all scripts from the directory will are executed.
> > 
> > But that's not the case for every situation. When the domain is
> > being defined the scripts are run but the output is ignored [1]
> > 
> > Is there a reason for that?
> 
> Libvirt only checks the output of pre-migration hook so that you can
> change the XML on incoming migration on the destination host rather than
> providing the updated XML to the migrate API.
> 
> The above paragraph talks about domain XML passing from one script to
> the following one when there's more scripts defined in qemu.d/
> 
> Jirka

Indeed, I understood it after failing and re-reading the docs. My
question is more related to the possibility of using it in other
scenarios. Would patches for that be welcomed?

Cheers,
Victor


signature.asc
Description: PGP signature


Re: [PATCH 0/4] Add support for MSDM ACPI table type

2025-02-18 Thread Daniel P . Berrangé
On Tue, Feb 18, 2025 at 07:20:01PM +0100, Victor Toso wrote:
> Hi,
> 
> On Tue, Feb 18, 2025 at 06:12:49PM +, Daniel P. Berrangé wrote:
> > This was requested by KubeVirt in
> > 
> >   https://gitlab.com/libvirt/libvirt/-/issues/748
> > 
> > I've not functionally tested this, since I lack any suitable guest
> > windows environment this is looking for MSDM tables, nor does my
> > machine have MSDM ACPI tables to pass to a guest.
> > 
> > I'm blindly assuming that the QEMU CLI code is identical except for
> > s/SLIC/MSDM/.
> 
> I think it is the right assumption from what I see people using
> with the qemu:arg from qemu:commandline option in the thread:
> 
> 
> https://gist.github.com/Informatic/49bd034d43e054bd1d8d4fec38c305ec#file-domain-xml

Hmm, that's interesting in that they're not passing the 'sig' parameter
to -acpitable at all. Reading the QEMU code it seems 'sig' is indeed
optional, merely used to override the 'sig' that is embedded in the
acpitable content loaded from the file.

This is actually good, as it means we would not need to add XML syupport
for every possible ACPI table type. We can just rely on the built-in
default, which would also make it practical to reconcile the Xen problem
below

> > Also I'm pretty unhappy about the situation with the Xen driver
> > support. This is pre-existing, and IMHO should never have been added
> > as it exists today, as it allows arbitrary passthrough of *any* set
> > of ACPI tables, as opposed to a single type of the specific type
> > listed in the XML.  This should have been handled with a different
> > XML syntax, but with stuck with this undesirable approach now, so
> > I've kept it as is.
> > 
> > Daniel P. Berrangé (4):
> >   conf: introduce support for multiple ACPI tables
> >   src: validate permitted ACPI table types in libxl/qemu drivers
> >   conf: support MSDM ACPI table type
> >   qemu: support MSDM ACPI table type
> > 
> >  docs/formatdomain.rst |  4 +-
> >  src/conf/domain_conf.c| 88 ++-
> >  src/conf/domain_conf.h| 22 -
> >  src/conf/schemas/domaincommon.rng |  5 +-
> >  src/libvirt_private.syms  |  2 +
> >  src/libxl/libxl_conf.c|  8 +-
> >  src/libxl/libxl_domain.c  | 21 +
> >  src/libxl/xen_xl.c| 22 -
> >  src/qemu/qemu_command.c   | 14 ++-
> >  src/qemu/qemu_validate.c  | 16 
> >  src/security/security_dac.c   | 18 ++--
> >  src/security/security_selinux.c   | 16 ++--
> >  src/security/virt-aa-helper.c |  5 +-
> >  .../acpi-table-many.x86_64-latest.args| 34 +++
> >  .../acpi-table-many.x86_64-latest.xml | 39 
> >  tests/qemuxmlconfdata/acpi-table-many.xml | 31 +++
> >  tests/qemuxmlconftest.c   |  1 +
> >  17 files changed, 296 insertions(+), 50 deletions(-)
> >  create mode 100644 tests/qemuxmlconfdata/acpi-table-many.x86_64-latest.args
> >  create mode 100644 tests/qemuxmlconfdata/acpi-table-many.x86_64-latest.xml
> >  create mode 100644 tests/qemuxmlconfdata/acpi-table-many.xml
> 
> Cheers,
> Victor



With regards,
Daniel
-- 
|: https://berrange.com  -o-https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o-https://fstop138.berrange.com :|
|: https://entangle-photo.org-o-https://www.instagram.com/dberrange :|


Re: [PATCH 0/4] Add support for MSDM ACPI table type

2025-02-18 Thread Victor Toso
Hi,

On Tue, Feb 18, 2025 at 06:12:49PM +, Daniel P. Berrangé wrote:
> This was requested by KubeVirt in
> 
>   https://gitlab.com/libvirt/libvirt/-/issues/748
> 
> I've not functionally tested this, since I lack any suitable guest
> windows environment this is looking for MSDM tables, nor does my
> machine have MSDM ACPI tables to pass to a guest.
> 
> I'm blindly assuming that the QEMU CLI code is identical except for
> s/SLIC/MSDM/.

I think it is the right assumption from what I see people using
with the qemu:arg from qemu:commandline option in the thread:


https://gist.github.com/Informatic/49bd034d43e054bd1d8d4fec38c305ec#file-domain-xml

> Also I'm pretty unhappy about the situation with the Xen driver
> support. This is pre-existing, and IMHO should never have been added
> as it exists today, as it allows arbitrary passthrough of *any* set
> of ACPI tables, as opposed to a single type of the specific type
> listed in the XML.  This should have been handled with a different
> XML syntax, but with stuck with this undesirable approach now, so
> I've kept it as is.
> 
> Daniel P. Berrangé (4):
>   conf: introduce support for multiple ACPI tables
>   src: validate permitted ACPI table types in libxl/qemu drivers
>   conf: support MSDM ACPI table type
>   qemu: support MSDM ACPI table type
> 
>  docs/formatdomain.rst |  4 +-
>  src/conf/domain_conf.c| 88 ++-
>  src/conf/domain_conf.h| 22 -
>  src/conf/schemas/domaincommon.rng |  5 +-
>  src/libvirt_private.syms  |  2 +
>  src/libxl/libxl_conf.c|  8 +-
>  src/libxl/libxl_domain.c  | 21 +
>  src/libxl/xen_xl.c| 22 -
>  src/qemu/qemu_command.c   | 14 ++-
>  src/qemu/qemu_validate.c  | 16 
>  src/security/security_dac.c   | 18 ++--
>  src/security/security_selinux.c   | 16 ++--
>  src/security/virt-aa-helper.c |  5 +-
>  .../acpi-table-many.x86_64-latest.args| 34 +++
>  .../acpi-table-many.x86_64-latest.xml | 39 
>  tests/qemuxmlconfdata/acpi-table-many.xml | 31 +++
>  tests/qemuxmlconftest.c   |  1 +
>  17 files changed, 296 insertions(+), 50 deletions(-)
>  create mode 100644 tests/qemuxmlconfdata/acpi-table-many.x86_64-latest.args
>  create mode 100644 tests/qemuxmlconfdata/acpi-table-many.x86_64-latest.xml
>  create mode 100644 tests/qemuxmlconfdata/acpi-table-many.xml

Cheers,
Victor


signature.asc
Description: PGP signature


Re: libvirt hook to change domain xml

2025-02-18 Thread Jiri Denemark
On Tue, Feb 18, 2025 at 19:21:56 +0100, Victor Toso wrote:
> Hi,
> 
> On Tue, Feb 18, 2025 at 07:11:45PM +0100, Jiri Denemark wrote:
> > On Tue, Feb 18, 2025 at 18:41:46 +0100, Victor Toso wrote:
> > > Hi,
> > > 
> > > I'm particularly interested in the PoC of KubeVirt to allow
> > > custom changes in libvirt domain xml in a more straightforward
> > > manner than they have Today [0].
> > > 
> > > When I was looking into the libvirt hooks, I was a bit excited
> > > when I read:
> > > 
> > >  > you can also place several hook scripts in the directory
> > >  > /etc/libvirt/hooks/qemu.d/. They are executed in alphabetical
> > >  > order after main script. In this case each script also acts as
> > >  > filter and can modify the domain XML and print it out on its
> > >  > standard output. This script output is passed to standard
> > >  > input next script in order. Empty output from any script is
> > >  > also identical to copying the input XML without changing it.
> > >  > In case any script returns failure common process will be
> > >  > aborted, but all scripts from the directory will are executed.
> > > 
> > > But that's not the case for every situation. When the domain is
> > > being defined the scripts are run but the output is ignored [1]
> > > 
> > > Is there a reason for that?
> > 
> > Libvirt only checks the output of pre-migration hook so that you can
> > change the XML on incoming migration on the destination host rather than
> > providing the updated XML to the migrate API.
> > 
> > The above paragraph talks about domain XML passing from one script to
> > the following one when there's more scripts defined in qemu.d/
> > 
> > Jirka
> 
> Indeed, I understood it after failing and re-reading the docs. My
> question is more related to the possibility of using it in other
> scenarios. Would patches for that be welcomed?

It depends. Do you have a specific use case which would benefit from the
change?

In most cases hooks are run when the XML has already been processed and
used for preparing the domain so it's too late for any XML changes. The
only place where it might theoretically be early enough for XML changes
(I haven't really checked the code to see if this is true) would be
"prepare" hook. But why would anyone want to change the definition at
this point rather providing the correct XML in the first place? It's not
like migration when one host does not know the situation on another
host. With the prepare hook both the hook and the API to create a domain
are called on a single host.

Jirka


Re: [PATCH 12/12] docs: document using passt backend with

2025-02-18 Thread Laine Stump

On 2/17/25 10:48 AM, Laine Stump wrote:

On 2/17/25 9:13 AM, Andrea Bolognani wrote:

On Sat, Feb 15, 2025 at 12:20:17AM -0500, Laine Stump wrote:

+vhost-user connection with passt backend
+
+
+:since:`Since 11.1.0 (QEMU and KVM only)` passt can be used as the
+other end of the vhost-user connection. This is a compelling
+alternative, because passt provides all of its network connectivity
+without requiring any elevated privileges or capabilities, and
+vhost-user uses shared memory to make this unprivileged connection
+very high performance as well. You can set a type='vhostuser'
+interface to use passt as the backend by adding . When passt is the backend, only a single driver
+queue is supported,


This should be added to the validation step.


Good point. I figured it wouldn't work, so I wasn't surprised that it 
failed when I tried it, but I didn't think to add validation to prevent 
it. I'll make a patch for that.




Otherwise:

error: internal error: QEMU unexpectedly closed the monitor (vm='test'):
qemu-system-x86_64: -netdev
{"type":"vhost-user","chardev":"charnet0","queues":5,"id":"hostnet0"}:
Failed to read msg header. Read -1 instead of 12. Original request 1.
qemu-system-x86_64: -netdev
{"type":"vhost-user","chardev":"charnet0","queues":5,"id":"hostnet0"}:
vhost_backend_init failed: Protocol error
qemu-system-x86_64: -netdev
{"type":"vhost-user","chardev":"charnet0","queues":5,"id":"hostnet0"}:
failed to init vhost_net for queue 0
qemu-system-x86_64: -netdev
{"type":"vhost-user","chardev":"charnet0","queues":5,"id":"hostnet0"}:
Failed to connect to '/run/libvirt/qemu/passt/1-test-net0.socket':
Connection refused
qemu-system-x86_64: -netdev
{"type":"vhost-user","chardev":"charnet0","queues":5,"id":"hostnet0"}:
Device 'vhost-user' could not be initialized


and the  path/type/mode are all
+implied to be "matching the passt process" so **must not** be
+specified.


These seem to simply be ignored if specified, which I guess is better
than accepting values that we know aren't going to work. Explicitly
rejecting them might be better.


Yeah, you're again correct.


Now that I've had more time to drink coffee and retrace the past events 
(pun not intended), I remember the reason I didn't validate that the 
type & mode settings are empty:


1) The "mode" setting is just directly saved into a bool ("listen") in 
the struct (virDomainChrDef) by the parser (ie. only 2 possible values 
(t/f), not 3 (t/f/unspecified)), so by the time you get to any 
validation function you no longer have any way of knowing if that bool 
is false because mode was unspecified, or if it's false because the 
input had "mode='client'". I could have used the hack of adding a 
"mode_specified" bool to virDomainChrDef, but that struct has several 
different users in different contexts, and a "mode_specified" would be 
nonsensical and confusing for most of them (especially since the 
variable in the struct is "listen", not "mode"), and the last thing I 
want to do is add *even more* to the confusion.


2) The 'type' setting is an enum in the virDomainChrDef, and that enum 
doesn't have an "unspecified" or "default" value as 0; it instead has 
VIR_DOMAIN_CHR_TYPE_NULL. I haven't tried to see what happens if I enter 
"type='null'" for some other type of chrdev, but that value is listed 
for VIR_ENUM_IMPL(virDomainChr), and every place that 
virDomainChrTypeFromString() is called, only a return of < 0 is 
considered an error (rather than <= 0) (both the name choice and all of 
the < 0 return value checks implying that there could be/is a place 
where setting "type='null'" has some valid functionality). Anyway the 
end of this is that it seemed "risky" to begin interpreting 
VIR_DOMAIN_CHR_TYPE_NULL to mean "type not specified", and anyway that 
would require that we add special handling at each place type is 
examined (there are many). Alternatively I could add a *new* 0 value 
VIR_DOMAIN_CHR_TYPE_UNSPECIFIED (or ..._NONE or something), but that 
would still require changing all of the checks on 
virDomainChrTypeFromString() to <= 0, and then changing every 
switch(type) to equate ..._NONE with ..._UNIX (but then in the future, 
one of the other uses for that enum could want _NONE to be equivalent to 
something else rather than _UNIX). So adding a new enum value was also 
increasing the fingers of change for this functionality way beyond just 
the vhostuser interface code, and I preferred to not have to 
regression-test every single usage of virDomainChrDef just for this one 
new feature.


3) Definitely I can/should check that they haven't tried to specify the 
path when backend type='passt' - that one has none of the complications 
of type/mode





Incidentally, dumpxml doesn't report the actual values, which I kinda
expected to happen.


Since it's an internal implementation detail, and there's really nothing 
you can do with those values if you have them, I think they should just 

[PATCH v2 20/21] qemu: add RDP support

2025-02-18 Thread marcandre . lureau
From: Marc-André Lureau 

Wire the external server RDP support with QEMU.

Check the configuration, allocate a port, start the process
and set the credentials.

Signed-off-by: Marc-André Lureau 
---
 docs/formatdomain.rst |  25 --
 src/conf/domain_conf.h|   1 +
 src/qemu/qemu_extdevice.c |  46 +--
 src/qemu/qemu_hotplug.c   |  49 ++-
 src/qemu/qemu_hotplug.h   |   1 +
 src/qemu/qemu_process.c   | 167 ++
 6 files changed, 257 insertions(+), 32 deletions(-)

diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
index 381bf84f67..1bb3efd79f 100644
--- a/docs/formatdomain.rst
+++ b/docs/formatdomain.rst
@@ -6502,7 +6502,7 @@ interaction with the admin.
  

  
- 
+ 
  
  

@@ -6665,14 +6665,21 @@ interaction with the admin.
   Starts a RDP server. The ``port`` attribute specifies the TCP port number
   (with -1 as legacy syntax indicating that it should be auto-allocated).
   The ``autoport`` attribute is the new preferred syntax for indicating
-  auto-allocation of the TCP port to use. In the VirtualBox driver, the
-  ``autoport`` will make the hypervisor pick available port from 3389-3689
-  range when the VM is started. The chosen port will be reflected in the
-  ``port`` attribute. The ``multiUser`` attribute is a boolean deciding
-  whether multiple simultaneous connections to the VM are permitted. The
-  ``replaceUser`` attribute is a boolean deciding whether the existing
-  connection must be dropped and a new connection must be established by 
the
-  VRDP server, when a new client connects in single connection mode.
+  auto-allocation of the TCP port to use.
+
+  A ``dbus`` graphics is also required to enable the QEMU RDP support, 
which
+  uses an external "qemu-rdp" helper process. The ``username`` and
+  ``passwd`` attributes set the credentials (when they are not set, the RDP
+  access may be disabled by the helper). :since:`Since 11.1.0`
+
+  In the VirtualBox driver, the ``autoport`` will make the hypervisor pick
+  available port from 3389-3689 range when the VM is started. The chosen
+  port will be reflected in the ``port`` attribute. The ``multiUser``
+  attribute is a boolean deciding whether multiple simultaneous connections
+  to the VM are permitted. The ``replaceUser`` attribute is a boolean
+  deciding whether the existing connection must be dropped and a new
+  connection must be established by the VRDP server, when a new client
+  connects in single connection mode.
 
``desktop``
   This value is reserved for VirtualBox domains for the moment. It displays
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index eabb31d463..69808d8489 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -2025,6 +2025,7 @@ struct _virDomainGraphicsDef {
 } sdl;
 struct {
 int port;
+bool portReserved;
 bool autoport;
 bool replaceUser;
 bool multiUser;
diff --git a/src/qemu/qemu_extdevice.c b/src/qemu/qemu_extdevice.c
index 2384bab7a6..78e72b7c10 100644
--- a/src/qemu/qemu_extdevice.c
+++ b/src/qemu/qemu_extdevice.c
@@ -238,14 +238,28 @@ qemuExtDevicesStart(virQEMUDriver *driver,
 for (i = 0; i < def->ngraphics; i++) {
 virDomainGraphicsDef *graphics = def->graphics[i];
 
-if (graphics->type != VIR_DOMAIN_GRAPHICS_TYPE_DBUS)
+switch (graphics->type) {
+case VIR_DOMAIN_GRAPHICS_TYPE_DBUS: {
+if (graphics->data.dbus.p2p || graphics->data.dbus.fromConfig)
+continue;
+if (qemuDBusStart(driver, vm) < 0)
+return -1;
 continue;
-
-if (graphics->data.dbus.p2p || graphics->data.dbus.fromConfig)
+}
+case VIR_DOMAIN_GRAPHICS_TYPE_RDP: {
+if (qemuRdpStart(vm, graphics) < 0)
+return -1;
 continue;
-
-if (qemuDBusStart(driver, vm) < 0)
-return -1;
+}
+case VIR_DOMAIN_GRAPHICS_TYPE_SDL:
+case VIR_DOMAIN_GRAPHICS_TYPE_VNC:
+case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP:
+case VIR_DOMAIN_GRAPHICS_TYPE_SPICE:
+case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS:
+case VIR_DOMAIN_GRAPHICS_TYPE_LAST:
+default:
+continue;
+}
 }
 
 for (i = 0; i < def->ndisks; i++) {
@@ -311,6 +325,26 @@ qemuExtDevicesStop(virQEMUDriver *driver,
 qemuVirtioFSStop(driver, vm, fs);
 }
 
+for (i = 0; i < def->ngraphics; i++) {
+virDomainGraphicsDef *graphics = def->graphics[i];
+
+switch (graphics->type) {
+case VIR_DOMAIN_GRAPHICS_TYPE_RDP: {
+qemuRdpStop(vm, graphics);
+continue;
+}
+case VIR_DOMAIN_GRAPHICS_TYPE_DBUS:
+case VIR_DOMAIN_GRAPHICS_TYPE_SDL:
+case VIR_DOMAIN_GRAPHICS

[PATCH v2 01/21] build-sys: drop -Winline when optimization=g

2025-02-18 Thread marcandre . lureau
From: Marc-André Lureau 

The warning is triggered when compiling with various build options, such
as -Doptimization=g.

>From gcc(1) man page about -Winline:
seemingly insignificant changes in the source program can cause the warnings 
produced by -Winline to appear or disappear.

Such flaky behaviour is best left to the user discretion.

Signed-off-by: Marc-André Lureau 
---
 meson.build | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/meson.build b/meson.build
index c7e5947d10..5bfd37e44d 100644
--- a/meson.build
+++ b/meson.build
@@ -340,7 +340,6 @@ cc_flags += [
   '-Wimplicit-int',
   '-Wincompatible-pointer-types',
   '-Winit-self',
-  '-Winline',
   '-Wint-conversion',
   '-Wint-in-bool-context',
   '-Wint-to-pointer-cast',
@@ -444,6 +443,12 @@ cc_flags += [
   '-Wwrite-strings',
 ]
 
+if get_option('optimization') != 'g'
+  # Seemingly insignificant changes in the source program can cause the 
warnings
+  # produced by -Winline to appear or disappear.
+  cc_flags += [ '-Winline' ]
+endif
+
 if cc.get_id() == 'clang'
 # Stop CLang from doing inter-procedural analysis of calls
 # between functions in the same compilation unit. Such an
-- 
2.47.0


[PATCH v2 00/21] Add qemu RDP server support

2025-02-18 Thread marcandre . lureau
From: Marc-André Lureau 

Hi,

This patch series offers an out-of-process Remote Desktop Protocol (RDP)
server solution utilizing QEMU's -display dbus interface, offering improved
modularity and potential security benefits compared to built-in server.

This initiative was spearheaded by Mihnea Buzatu during the QEMU Summer of Code
2023. The project's goal was to develop an out-of-process RDP server using the
-display dbus interface, implemented in Rust. Given that the IronRDP crate
lacked some server support at the time, investments in IronRDP were required.

I finally released an initial v0.1 version of qemu-rdp on crates.io
(https://crates.io/crates/qemu-rdp). That should allow more people to review and
evaluate the state of this work.

On unix systems, with cargo/rust toolchain installed, it should be as easy as
running "cargo install qemu-rdp", apply this patch series for libvirt, set the
"rdp_tls_x509_cert_dir" location for your TLS certificates, and configure a VM
with both dbus & rdp graphics (run "virsh domdisplay DOMAIN" to get the display
connection details).

Thanks for the reviews & feedback!

v2: thanks to Daniel review
- drop extra error report from "qemu: report an error for unsupported graphics"
- replace g_return pre-conditions with ATTRIBUTE_NONNULL
- improve "qemu/dbus: keep a connection to the VM D-Bus" to also reconnect
- use domainLogContext for logging (for virtiofs as well)
- check for qemu-rdp availabilty for setting 'rdp' capability
- make dbus-addr qemu-rdp capability mandatory
- rebased
- add r-b tags

Marc-André Lureau (21):
  build-sys: drop -Winline when optimization=g
  build: fix -Werror=maybe-uninitialized
  qemu-slirp: drop unneeded check for OOM
  util: annotate non-null arguments for virGDBusCallMethod()
  qemu: fall-through for unsupported graphics
  qemu: add rdp state directory
  qemu: add qemu RDP configuration
  conf: parse optional RDP username & password
  conf: generalize virDomainDefHasSpiceGraphics
  qemu: use virDomainDefHasGraphics
  qemu: add RDP ports range allocator
  qemu: limit to one 
  qemu/virtiofs: use domainLogContext
  qemu/dbus: keep a connection to the VM D-Bus
  qemu/dbus: log daemon stdout/err, use domainLogContext
  qemu: validate RDP configuration
  qemu: add qemu-rdp helper unit
  qemu: pass virQEMUDriverConfig to capabilities
  qemu: add 'rdp' capability if qemu-rdp is available
  qemu: add RDP support
  tests: add qemu  test

 docs/formatdomain.rst |  25 +-
 meson.build   |   7 +-
 po/POTFILES   |   1 +
 src/conf/domain_conf.c|  28 +-
 src/conf/domain_conf.h|   5 +-
 src/conf/schemas/domaincommon.rng |  10 +
 src/libvirt_private.syms  |   2 +-
 src/qemu/libvirtd_qemu.aug|   7 +
 src/qemu/meson.build  |   1 +
 src/qemu/qemu.conf.in |  31 ++
 src/qemu/qemu_capabilities.c  |  24 +-
 src/qemu/qemu_capabilities.h  |  12 +-
 src/qemu/qemu_command.c   |   9 +-
 src/qemu/qemu_conf.c  |  56 ++-
 src/qemu/qemu_conf.h  |  13 +
 src/qemu/qemu_dbus.c  |  69 ++-
 src/qemu/qemu_dbus.h  |   3 +
 src/qemu/qemu_domain.c|   1 +
 src/qemu/qemu_domain.h|   4 +
 src/qemu/qemu_driver.c|  20 +
 src/qemu/qemu_extdevice.c |  46 +-
 src/qemu/qemu_hotplug.c   |  49 ++-
 src/qemu/qemu_hotplug.h   |   1 +
 src/qemu/qemu_process.c   | 170 ++-
 src/qemu/qemu_rdp.c   | 416 ++
 src/qemu/qemu_rdp.h   |  73 +++
 src/qemu/qemu_slirp.c |   6 -
 src/qemu/qemu_validate.c  |  48 +-
 src/qemu/qemu_virtiofs.c  |  53 +--
 src/qemu/test_libvirtd_qemu.aug.in|   5 +
 src/util/virgdbus.h   |  13 +-
 .../domaincapsdata/qemu_10.0.0-q35.x86_64.xml |   1 +
 .../domaincapsdata/qemu_10.0.0-tcg.x86_64.xml |   1 +
 tests/domaincapsdata/qemu_10.0.0.s390x.xml|   1 +
 tests/domaincapsdata/qemu_10.0.0.x86_64.xml   |   1 +
 .../domaincapsdata/qemu_7.0.0-q35.x86_64.xml  |   1 +
 .../domaincapsdata/qemu_7.0.0-tcg.x86_64.xml  |   1 +
 tests/domaincapsdata/qemu_7.0.0.x86_64.xml|   1 +
 .../domaincapsdata/qemu_7.1.0-q35.x86_64.xml  |   1 +
 .../domaincapsdata/qemu_7.1.0-tcg.x86_64.xml  |   1 +
 tests/domaincapsdata/qemu_7.1.0.x86_64.xml|   1 +
 .../qemu_7.2.0-hvf.x86_64+hvf.xml |   1 +
 .../domaincapsdata/qemu_7.2.0-q35.x86_64.xml  |   1 +
 .../qemu_7.2.0-tcg.x86_64+hvf.xml |   1 +
 .../domaincapsdata/qemu_7.2.0-tcg.x86_64.xml  |   1 +
 tests/domaincapsdata/qemu_7.2.0.ppc.xml  

[PATCH v2 02/21] build: fix -Werror=maybe-uninitialized

2025-02-18 Thread marcandre . lureau
From: Marc-André Lureau 

When compiled with -Doptimization=g

../tools/nss/libvirt_nss_macs.c:155:8: error: ‘jerr’ may be used uninitialized 
[-Werror=maybe-uninitialized]
  155 | if (jerr == json_tokener_continue) {
  |^

Signed-off-by: Marc-André Lureau 
Reviewed-by: Daniel P. Berrangé 
---
 tools/nss/libvirt_nss_leases.c | 2 +-
 tools/nss/libvirt_nss_macs.c   | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/tools/nss/libvirt_nss_leases.c b/tools/nss/libvirt_nss_leases.c
index 25ea6b0ce2..4d68787fb2 100644
--- a/tools/nss/libvirt_nss_leases.c
+++ b/tools/nss/libvirt_nss_leases.c
@@ -260,7 +260,7 @@ findLeases(const char *file,
 int ret = -1;
 json_object *jobj = NULL;
 json_tokener *tok = NULL;
-enum json_tokener_error jerr;
+enum json_tokener_error jerr = json_tokener_error_parse_eof;
 int jsonflags = JSON_TOKENER_STRICT | JSON_TOKENER_VALIDATE_UTF8;
 char line[1024];
 size_t nreadTotal = 0;
diff --git a/tools/nss/libvirt_nss_macs.c b/tools/nss/libvirt_nss_macs.c
index bac8c0e1bb..c3af9375bc 100644
--- a/tools/nss/libvirt_nss_macs.c
+++ b/tools/nss/libvirt_nss_macs.c
@@ -122,7 +122,7 @@ findMACs(const char *file,
 char line[1024];
 json_object *jobj = NULL;
 json_tokener *tok = NULL;
-enum json_tokener_error jerr;
+enum json_tokener_error jerr = json_tokener_error_parse_eof;
 int jsonflags = JSON_TOKENER_STRICT | JSON_TOKENER_VALIDATE_UTF8;
 size_t nreadTotal = 0;
 int rv;
-- 
2.47.0


[PATCH v2 15/21] qemu/dbus: log daemon stdout/err, use domainLogContext

2025-02-18 Thread marcandre . lureau
From: Marc-André Lureau 

Currently, if dbus-daemon writes on errfd, it will SIGPIPE.

Signed-off-by: Marc-André Lureau 
---
 src/qemu/qemu_dbus.c | 34 +++---
 1 file changed, 23 insertions(+), 11 deletions(-)

diff --git a/src/qemu/qemu_dbus.c b/src/qemu/qemu_dbus.c
index c9e99ea27b..a9e2fb0fe2 100644
--- a/src/qemu/qemu_dbus.c
+++ b/src/qemu/qemu_dbus.c
@@ -24,6 +24,7 @@
 #include "virlog.h"
 #include "virtime.h"
 #include "virpidfile.h"
+#include "virutil.h"
 
 #define VIR_FROM_THIS VIR_FROM_NONE
 
@@ -212,9 +213,12 @@ qemuDBusStart(virQEMUDriver *driver,
 g_autofree char *pidfile = NULL;
 g_autofree char *configfile = NULL;
 g_autofree char *sockpath = NULL;
+g_autofree char *logpath = NULL;
 virTimeBackOffVar timebackoff;
 const unsigned long long timeout = 500 * 1000; /* ms */
-VIR_AUTOCLOSE errfd = -1;
+int logfd = -1;
+g_autoptr(domainLogContext) logContext = NULL;
+
 pid_t cpid = -1;
 int ret = -1;
 
@@ -246,10 +250,21 @@ qemuDBusStart(virQEMUDriver *driver,
 if (qemuSecurityDomainSetPathLabel(driver, vm, configfile, false) < 0)
 goto cleanup;
 
+if (!(logContext = domainLogContextNew(cfg->stdioLogD, cfg->dbusStateDir,
+   QEMU_DRIVER_NAME,
+   vm, driver->privileged,
+   shortName))) {
+virLastErrorPrefixMessage("%s", _("can't open log context"));
+goto cleanup;
+}
+
+logfd = domainLogContextGetWriteFD(logContext);
+
 cmd = virCommandNew(dbusDaemonPath);
 virCommandClearCaps(cmd);
 virCommandSetPidFile(cmd, pidfile);
-virCommandSetErrorFD(cmd, &errfd);
+virCommandSetOutputFD(cmd, &logfd);
+virCommandSetErrorFD(cmd, &logfd);
 virCommandDaemonize(cmd);
 virCommandAddArgFormat(cmd, "--config-file=%s", configfile);
 
@@ -266,7 +281,7 @@ qemuDBusStart(virQEMUDriver *driver,
 if (virTimeBackOffStart(&timebackoff, 1, timeout) < 0)
 goto cleanup;
 while (virTimeBackOffWait(&timebackoff)) {
-char errbuf[1024] = { 0 };
+g_autofree char *msg = NULL;
 
 if (virFileExists(sockpath))
 break;
@@ -274,15 +289,12 @@ qemuDBusStart(virQEMUDriver *driver,
 if (virProcessKill(cpid, 0) == 0)
 continue;
 
-if (saferead(errfd, errbuf, sizeof(errbuf) - 1) < 0) {
-virReportSystemError(errno,
- _("dbus-daemon %1$s died unexpectedly"),
- dbusDaemonPath);
-} else {
-virReportError(VIR_ERR_OPERATION_FAILED,
-   _("dbus-daemon died and reported: %1$s"), errbuf);
-}
+if (domainLogContextReadFiltered(logContext, &msg, 1024) < 0)
+VIR_WARN("Unable to read from dbus-daemon log");
 
+virReportError(VIR_ERR_OPERATION_FAILED,
+   _("dbus-daemon died and reported:\n%1$s"),
+   NULLSTR(msg));
 goto cleanup;
 }
 
-- 
2.47.0


[PATCH v2 14/21] qemu/dbus: keep a connection to the VM D-Bus

2025-02-18 Thread marcandre . lureau
From: Marc-André Lureau 

The following changes are going to communicate with the qemu-rdp server
through the VM D-Bus bus, keep a connection for that and further usage.

Signed-off-by: Marc-André Lureau 
---
 src/qemu/qemu_dbus.c| 35 +++
 src/qemu/qemu_dbus.h|  3 +++
 src/qemu/qemu_domain.h  |  2 ++
 src/qemu/qemu_process.c |  3 +++
 4 files changed, 43 insertions(+)

diff --git a/src/qemu/qemu_dbus.c b/src/qemu/qemu_dbus.c
index 06b655d870..c9e99ea27b 100644
--- a/src/qemu/qemu_dbus.c
+++ b/src/qemu/qemu_dbus.c
@@ -84,6 +84,36 @@ qemuDBusGetAddress(virQEMUDriver *driver,
 }
 
 
+bool
+qemuDBusConnect(virQEMUDriver *driver,
+virDomainObj *vm)
+{
+qemuDomainObjPrivate *priv = vm->privateData;
+g_autoptr(GError) gerr = NULL;
+g_autofree char *address = NULL;
+
+if (priv->dbusConnection)
+return true;
+
+address = qemuDBusGetAddress(driver, vm);
+if (!address)
+return false;
+
+priv->dbusConnection =
+g_dbus_connection_new_for_address_sync(address,
+   
G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT|
+   
G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,
+   NULL, NULL, &gerr);
+if (!priv->dbusConnection) {
+virReportError(VIR_ERR_OPERATION_FAILED,
+  _("Failed to connect to dbus-daemon: %1$s"), 
gerr->message);
+return false;
+}
+
+return true;
+}
+
+
 static int
 qemuDBusWriteConfig(const char *filename, const char *path)
 {
@@ -140,6 +170,8 @@ qemuDBusStop(virQEMUDriver *driver,
 } else {
 priv->dbusDaemonRunning = false;
 }
+
+g_clear_object(&priv->dbusConnection);
 }
 
 
@@ -264,6 +296,9 @@ qemuDBusStart(virQEMUDriver *driver,
 if (qemuSecurityDomainSetPathLabel(driver, vm, sockpath, false) < 0)
 goto cleanup;
 
+if (!qemuDBusConnect(driver, vm))
+goto cleanup;
+
 priv->dbusDaemonRunning = true;
 ret = 0;
  cleanup:
diff --git a/src/qemu/qemu_dbus.h b/src/qemu/qemu_dbus.h
index b27f38a591..2d97c6df2d 100644
--- a/src/qemu/qemu_dbus.h
+++ b/src/qemu/qemu_dbus.h
@@ -24,6 +24,9 @@
 char *qemuDBusGetAddress(virQEMUDriver *driver,
  virDomainObj *vm);
 
+bool qemuDBusConnect(virQEMUDriver *driver,
+ virDomainObj *vm);
+
 int qemuDBusStart(virQEMUDriver *driver,
   virDomainObj *vm);
 
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index 04577f1297..03cf84695f 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -39,6 +39,7 @@
 #include "qemu_fd.h"
 #include "virchrdev.h"
 #include "virobject.h"
+#include "virgdbus.h"
 #include "virdomainmomentobjlist.h"
 #include "virenum.h"
 #include "vireventthread.h"
@@ -240,6 +241,7 @@ struct _qemuDomainObjPrivate {
 /* running backup job */
 virDomainBackupDef *backup;
 
+GDBusConnection *dbusConnection;
 bool dbusDaemonRunning;
 
 /* list of Ids to migrate */
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 0d9b8bcb93..30d6560d52 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -9456,6 +9456,9 @@ qemuProcessReconnect(void *opaque)
 if (qemuDomainObjStartWorker(obj) < 0)
 goto error;
 
+if (priv->dbusDaemonRunning && !qemuDBusConnect(driver, obj))
+goto error;
+
 VIR_DEBUG("Reconnect monitor to def=%p name='%s'", obj, obj->def->name);
 
 tryMonReconn = true;
-- 
2.47.0


[PATCH v2 16/21] qemu: validate RDP configuration

2025-02-18 Thread marcandre . lureau
From: Marc-André Lureau 

Signed-off-by: Marc-André Lureau 
Reviewed-by: Daniel P. Berrangé 
---
 src/qemu/qemu_validate.c | 30 +-
 1 file changed, 29 insertions(+), 1 deletion(-)

diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c
index da3321849c..051f93495c 100644
--- a/src/qemu/qemu_validate.c
+++ b/src/qemu/qemu_validate.c
@@ -4441,6 +4441,29 @@ qemuValidateDomainDeviceDefDBusGraphics(const 
virDomainGraphicsDef *graphics,
 }
 
 
+static int
+qemuValidateDomainDeviceDefRDPGraphics(const virDomainGraphicsDef *graphics)
+{
+if (graphics->data.rdp.replaceUser) {
+virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+   _("RDP doesn't support 'replaceUser'"));
+return -1;
+}
+if (graphics->data.rdp.multiUser) {
+virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+   _("RDP doesn't support 'multiUser'"));
+return -1;
+}
+if (graphics->data.rdp.auth.expires) {
+virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+   _("RDP password expiration isn't supported"));
+return -1;
+}
+
+return 0;
+}
+
+
 static int
 qemuValidateDomainDeviceDefGraphics(const virDomainGraphicsDef *graphics,
 const virDomainDef *def,
@@ -4512,8 +4535,13 @@ qemuValidateDomainDeviceDefGraphics(const 
virDomainGraphicsDef *graphics,
 
 break;
 
-case VIR_DOMAIN_GRAPHICS_TYPE_SDL:
 case VIR_DOMAIN_GRAPHICS_TYPE_RDP:
+if (qemuValidateDomainDeviceDefRDPGraphics(graphics) < 0)
+return -1;
+
+break;
+
+case VIR_DOMAIN_GRAPHICS_TYPE_SDL:
 case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP:
 case VIR_DOMAIN_GRAPHICS_TYPE_LAST:
 break;
-- 
2.47.0


[PATCH v2 21/21] tests: add qemu test

2025-02-18 Thread marcandre . lureau
From: Marc-André Lureau 

Signed-off-by: Marc-André Lureau 
---
 .../graphics-rdp.x86_64-latest.args   | 35 +++
 .../graphics-rdp.x86_64-latest.xml|  1 +
 tests/qemuxmlconfdata/graphics-rdp.xml| 43 +++
 tests/qemuxmlconftest.c   |  2 +
 4 files changed, 81 insertions(+)
 create mode 100644 tests/qemuxmlconfdata/graphics-rdp.x86_64-latest.args
 create mode 12 tests/qemuxmlconfdata/graphics-rdp.x86_64-latest.xml
 create mode 100644 tests/qemuxmlconfdata/graphics-rdp.xml

diff --git a/tests/qemuxmlconfdata/graphics-rdp.x86_64-latest.args 
b/tests/qemuxmlconfdata/graphics-rdp.x86_64-latest.args
new file mode 100644
index 00..292f283493
--- /dev/null
+++ b/tests/qemuxmlconfdata/graphics-rdp.x86_64-latest.args
@@ -0,0 +1,35 @@
+LC_ALL=C \
+PATH=/bin \
+HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1 \
+USER=test \
+LOGNAME=test \
+XDG_DATA_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.local/share \
+XDG_CACHE_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.cache \
+XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \
+/usr/bin/qemu-system-x86_64 \
+-name guest=QEMUGuest1,debug-threads=on \
+-S \
+-object 
'{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain--1-QEMUGuest1/master-key.aes"}'
 \
+-machine pc,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \
+-accel tcg \
+-cpu qemu64 \
+-m size=219136k \
+-object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":224395264}' \
+-overcommit mem-lock=off \
+-smp 1,sockets=1,cores=1,threads=1 \
+-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
+-no-user-config \
+-nodefaults \
+-chardev socket,id=charmonitor,fd=1729,server=on,wait=off \
+-mon chardev=charmonitor,id=monitor,mode=control \
+-rtc base=utc \
+-no-shutdown \
+-boot strict=on \
+-device 
'{"driver":"piix3-usb-uhci","id":"usb","bus":"pci.0","addr":"0x1.0x2"}' \
+-audiodev '{"id":"audio1","driver":"dbus"}' \
+-display 
dbus,addr=unix:path=/var/run/libvirt/qemu/dbus/-1-QEMUGuest1-dbus.sock \
+-device '{"driver":"cirrus-vga","id":"video0","bus":"pci.0","addr":"0x2"}' \
+-chardev dbus,id=charredir0,name=org.qemu.usbredir \
+-device 
'{"driver":"usb-redir","chardev":"charredir0","id":"redir0","bus":"usb.0","port":"1"}'
 \
+-sandbox 
on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \
+-msg timestamp=on
diff --git a/tests/qemuxmlconfdata/graphics-rdp.x86_64-latest.xml 
b/tests/qemuxmlconfdata/graphics-rdp.x86_64-latest.xml
new file mode 12
index 00..7bb46ae7c4
--- /dev/null
+++ b/tests/qemuxmlconfdata/graphics-rdp.x86_64-latest.xml
@@ -0,0 +1 @@
+graphics-rdp.xml
\ No newline at end of file
diff --git a/tests/qemuxmlconfdata/graphics-rdp.xml 
b/tests/qemuxmlconfdata/graphics-rdp.xml
new file mode 100644
index 00..7d65320f41
--- /dev/null
+++ b/tests/qemuxmlconfdata/graphics-rdp.xml
@@ -0,0 +1,43 @@
+
+  QEMUGuest1
+  c7a5fdbd-edaf-9455-926a-d65c16db1809
+  219100
+  219100
+  1
+  
+hvm
+
+  
+  
+qemu64
+  
+  
+  destroy
+  restart
+  destroy
+  
+/usr/bin/qemu-system-x86_64
+
+  
+
+
+  
+
+
+
+
+
+
+  
+
+
+
+  
+  
+
+
+  
+
+
+  
+
diff --git a/tests/qemuxmlconftest.c b/tests/qemuxmlconftest.c
index c271170d25..03c839114c 100644
--- a/tests/qemuxmlconftest.c
+++ b/tests/qemuxmlconftest.c
@@ -1756,6 +1756,8 @@ mymain(void)
 DO_TEST_CAPS_LATEST("graphics-dbus-chardev");
 DO_TEST_CAPS_LATEST("graphics-dbus-usbredir");
 
+DO_TEST_CAPS_LATEST("graphics-rdp");
+
 DO_TEST_CAPS_LATEST("input-usbmouse");
 DO_TEST_CAPS_LATEST("input-usbtablet");
 
-- 
2.47.0


Re: [PATCH] qemu: Avoid crash in qemuDomainCheckCPU with unknown host CPU

2025-02-18 Thread Michal Prívozník
On 2/18/25 11:49, Jiri Denemark wrote:
> When we don't have any information about host CPU (for example when
> running on an aarch64 host), the virQEMUCapsGetHostModel would return
> NULL.
> 
> Fixes: https://gitlab.com/libvirt/libvirt/-/issues/747
> Signed-off-by: Jiri Denemark 

Please also mention:

Fixes: f928eb5fc80ca0ed7277f2513b63aed36c09d275

> ---
>  src/qemu/qemu_domain.c | 1 +
>  1 file changed, 1 insertion(+)

Reviewed-by: Michal Privoznik 

Michal


Re: [PATCH] build-aux: squelch trailing blank warnings from binary files

2025-02-18 Thread Michal Prívozník
On 2/17/25 18:03, Daniel P. Berrangé wrote:
> These files pollute the stderr output when the sc_trailing_blank
> syntax check fails.
> 
> Signed-off-by: Daniel P. Berrangé 
> ---
>  build-aux/syntax-check.mk | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 

Reviewed-by: Michal Privoznik 
Michal


[PATCH v2 04/21] util: annotate non-null arguments for virGDBusCallMethod()

2025-02-18 Thread marcandre . lureau
From: Marc-André Lureau 

Helps avoid/debug a potential SEGV if conn is NULL, since gio will not
set the "gerror" in that case and we will crash later at:
  virReportError(VIR_ERR_DBUS_SERVICE, "%s", gerror->message);

Signed-off-by: Marc-André Lureau 
---
 src/util/virgdbus.h | 13 +++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/src/util/virgdbus.h b/src/util/virgdbus.h
index dfe6138112..65e7ba7be4 100644
--- a/src/util/virgdbus.h
+++ b/src/util/virgdbus.h
@@ -54,7 +54,11 @@ virGDBusCallMethod(GDBusConnection *conn,
const char *objectPath,
const char *ifaceName,
const char *method,
-   GVariant *data);
+   GVariant *data)
+ATTRIBUTE_NONNULL(1)
+ATTRIBUTE_NONNULL(6)
+ATTRIBUTE_NONNULL(7)
+ATTRIBUTE_NONNULL(8);
 
 int
 virGDBusCallMethodWithFD(GDBusConnection *conn,
@@ -67,7 +71,12 @@ virGDBusCallMethodWithFD(GDBusConnection *conn,
  const char *ifaceName,
  const char *method,
  GVariant *data,
- GUnixFDList *dataFD);
+ GUnixFDList *dataFD)
+ATTRIBUTE_NONNULL(1)
+ATTRIBUTE_NONNULL(7)
+ATTRIBUTE_NONNULL(8)
+ATTRIBUTE_NONNULL(9);
+
 
 int
 virGDBusIsServiceEnabled(const char *name);
-- 
2.47.0


[PATCH v2 03/21] qemu-slirp: drop unneeded check for OOM

2025-02-18 Thread marcandre . lureau
From: Marc-André Lureau 

glib anti-pattern, since it aborts on OOM.

Signed-off-by: Marc-André Lureau 
Reviewed-by: Daniel P. Berrangé 
---
 src/qemu/qemu_slirp.c | 6 --
 1 file changed, 6 deletions(-)

diff --git a/src/qemu/qemu_slirp.c b/src/qemu/qemu_slirp.c
index 66d9d77c6c..eac7e4cc47 100644
--- a/src/qemu/qemu_slirp.c
+++ b/src/qemu/qemu_slirp.c
@@ -99,12 +99,6 @@ qemuSlirpNewForHelper(const char *helper)
 size_t i, nfeatures;
 
 slirp = qemuSlirpNew();
-if (!slirp) {
-virReportError(VIR_ERR_INTERNAL_ERROR,
-   _("Failed to allocate slirp for '%1$s'"), helper);
-return NULL;
-}
-
 cmd = virCommandNewArgList(helper, "--print-capabilities", NULL);
 virCommandSetOutputBuffer(cmd, &output);
 if (virCommandRun(cmd, NULL) < 0)
-- 
2.47.0


[PATCH v2 05/21] qemu: fall-through for unsupported graphics

2025-02-18 Thread marcandre . lureau
From: Marc-André Lureau 

Without an error message, it can be tedious to figure out failure to
start, just fall-through the generic range error.

Signed-off-by: Marc-André Lureau 
---
 src/qemu/qemu_command.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 54130ac4f0..772e98fbb4 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -8448,7 +8448,6 @@ qemuBuildGraphicsCommandLine(virQEMUDriverConfig *cfg,
 break;
 case VIR_DOMAIN_GRAPHICS_TYPE_RDP:
 case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP:
-return -1;
 case VIR_DOMAIN_GRAPHICS_TYPE_LAST:
 default:
 virReportEnumRangeError(virDomainGraphicsType, graphics->type);
-- 
2.47.0


[PATCH v2 19/21] qemu: add 'rdp' capability if qemu-rdp is available

2025-02-18 Thread marcandre . lureau
From: Marc-André Lureau 

Signed-off-by: Marc-André Lureau 
---
 src/qemu/qemu_capabilities.c  | 15 +++
 src/qemu/qemu_capabilities.h  |  3 ++-
 src/qemu/qemu_rdp.c   | 11 +++
 src/qemu/qemu_rdp.h   |  2 ++
 src/qemu/qemu_validate.c  |  3 ++-
 tests/domaincapsdata/qemu_10.0.0-q35.x86_64.xml   |  1 +
 tests/domaincapsdata/qemu_10.0.0-tcg.x86_64.xml   |  1 +
 tests/domaincapsdata/qemu_10.0.0.s390x.xml|  1 +
 tests/domaincapsdata/qemu_10.0.0.x86_64.xml   |  1 +
 tests/domaincapsdata/qemu_7.0.0-q35.x86_64.xml|  1 +
 tests/domaincapsdata/qemu_7.0.0-tcg.x86_64.xml|  1 +
 tests/domaincapsdata/qemu_7.0.0.x86_64.xml|  1 +
 tests/domaincapsdata/qemu_7.1.0-q35.x86_64.xml|  1 +
 tests/domaincapsdata/qemu_7.1.0-tcg.x86_64.xml|  1 +
 tests/domaincapsdata/qemu_7.1.0.x86_64.xml|  1 +
 .../domaincapsdata/qemu_7.2.0-hvf.x86_64+hvf.xml  |  1 +
 tests/domaincapsdata/qemu_7.2.0-q35.x86_64.xml|  1 +
 .../domaincapsdata/qemu_7.2.0-tcg.x86_64+hvf.xml  |  1 +
 tests/domaincapsdata/qemu_7.2.0-tcg.x86_64.xml|  1 +
 tests/domaincapsdata/qemu_7.2.0.ppc.xml   |  1 +
 tests/domaincapsdata/qemu_7.2.0.x86_64.xml|  1 +
 tests/domaincapsdata/qemu_8.0.0-q35.x86_64.xml|  1 +
 tests/domaincapsdata/qemu_8.0.0-tcg.x86_64.xml|  1 +
 tests/domaincapsdata/qemu_8.0.0.x86_64.xml|  1 +
 tests/domaincapsdata/qemu_8.1.0-q35.x86_64.xml|  1 +
 tests/domaincapsdata/qemu_8.1.0-tcg.x86_64.xml|  1 +
 tests/domaincapsdata/qemu_8.1.0.s390x.xml |  1 +
 tests/domaincapsdata/qemu_8.1.0.x86_64.xml|  1 +
 tests/domaincapsdata/qemu_8.2.0-q35.x86_64.xml|  1 +
 .../qemu_8.2.0-tcg-virt.loongarch64.xml   |  1 +
 tests/domaincapsdata/qemu_8.2.0-tcg.x86_64.xml|  1 +
 tests/domaincapsdata/qemu_8.2.0-virt.aarch64.xml  |  1 +
 .../qemu_8.2.0-virt.loongarch64.xml   |  1 +
 tests/domaincapsdata/qemu_8.2.0.aarch64.xml   |  1 +
 tests/domaincapsdata/qemu_8.2.0.armv7l.xml|  1 +
 tests/domaincapsdata/qemu_8.2.0.s390x.xml |  1 +
 tests/domaincapsdata/qemu_8.2.0.x86_64.xml|  1 +
 tests/domaincapsdata/qemu_9.0.0-q35.x86_64.xml|  1 +
 tests/domaincapsdata/qemu_9.0.0-tcg.x86_64.xml|  1 +
 tests/domaincapsdata/qemu_9.0.0.sparc.xml |  1 +
 tests/domaincapsdata/qemu_9.0.0.x86_64.xml|  1 +
 tests/domaincapsdata/qemu_9.1.0-q35.x86_64.xml|  1 +
 .../qemu_9.1.0-tcg-virt.riscv64.xml   |  1 +
 tests/domaincapsdata/qemu_9.1.0-tcg.x86_64.xml|  1 +
 tests/domaincapsdata/qemu_9.1.0-virt.riscv64.xml  |  1 +
 tests/domaincapsdata/qemu_9.1.0.s390x.xml |  1 +
 tests/domaincapsdata/qemu_9.1.0.x86_64.xml|  1 +
 tests/domaincapsdata/qemu_9.2.0-q35.x86_64.xml|  1 +
 tests/domaincapsdata/qemu_9.2.0-tcg.x86_64.xml|  1 +
 tests/domaincapsdata/qemu_9.2.0.s390x.xml |  1 +
 tests/domaincapsdata/qemu_9.2.0.x86_64.xml|  1 +
 tests/testutilsqemu.c |  6 ++
 52 files changed, 80 insertions(+), 6 deletions(-)

diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index fed7f998d3..6bedb5cd0d 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -6487,7 +6487,8 @@ virQEMUCapsFillDomainDeviceDiskCaps(virQEMUCaps *qemuCaps,
 
 
 void
-virQEMUCapsFillDomainDeviceGraphicsCaps(virQEMUCaps *qemuCaps,
+virQEMUCapsFillDomainDeviceGraphicsCaps(virQEMUDriverConfig *cfg,
+virQEMUCaps *qemuCaps,
 virDomainCapsDeviceGraphics *dev)
 {
 dev->supported = VIR_TRISTATE_BOOL_YES;
@@ -6501,8 +6502,14 @@ virQEMUCapsFillDomainDeviceGraphicsCaps(virQEMUCaps 
*qemuCaps,
 VIR_DOMAIN_CAPS_ENUM_SET(dev->type, VIR_DOMAIN_GRAPHICS_TYPE_SPICE);
 if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_EGL_HEADLESS))
 VIR_DOMAIN_CAPS_ENUM_SET(dev->type, 
VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS);
-if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DISPLAY_DBUS))
-VIR_DOMAIN_CAPS_ENUM_SET(dev->type, VIR_DOMAIN_GRAPHICS_TYPE_DBUS);
+if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DISPLAY_DBUS)) {
+VIR_DOMAIN_CAPS_ENUM_SET(dev->type,
+ VIR_DOMAIN_GRAPHICS_TYPE_DBUS);
+if (qemuRdpAvailable(cfg->qemuRdpName)) {
+VIR_DOMAIN_CAPS_ENUM_SET(dev->type,
+ VIR_DOMAIN_GRAPHICS_TYPE_RDP);
+}
+}
 }
 
 
@@ -6986,7 +6993,7 @@ virQEMUCapsFillDomainCaps(virQEMUDriverConfig *cfg,
 virQEMUCapsFillDomainCPUCaps(qemuCaps, hostarch, domCaps);
 virQEMUCapsFillDomainMemoryBackingCaps(qemuCaps, memoryBacking);
 virQEMUCapsFillDomainDeviceDiskCaps(qemuCaps, domCaps->machine, disk);
-virQEMUCapsFillDomainDeviceGraphicsCaps(qemuCaps, graphics);
+virQEMUCapsFillDomainDeviceGraphicsCaps(cfg, qemuCaps, graphics);
 virQEM

[PATCH v2 17/21] qemu: add qemu-rdp helper unit

2025-02-18 Thread marcandre . lureau
From: Marc-André Lureau 

Helpers to start the qemu-rdp server and set it up.

Signed-off-by: Marc-André Lureau 
---
 po/POTFILES|   1 +
 src/qemu/meson.build   |   1 +
 src/qemu/qemu_domain.c |   1 +
 src/qemu/qemu_domain.h |   2 +
 src/qemu/qemu_rdp.c| 405 +
 src/qemu/qemu_rdp.h|  71 
 6 files changed, 481 insertions(+)
 create mode 100644 src/qemu/qemu_rdp.c
 create mode 100644 src/qemu/qemu_rdp.h

diff --git a/po/POTFILES b/po/POTFILES
index d4b3de781b..0c83affb44 100644
--- a/po/POTFILES
+++ b/po/POTFILES
@@ -195,6 +195,7 @@ src/qemu/qemu_passt.c
 src/qemu/qemu_postparse.c
 src/qemu/qemu_process.c
 src/qemu/qemu_qapi.c
+src/qemu/qemu_rdp.c
 src/qemu/qemu_saveimage.c
 src/qemu/qemu_slirp.c
 src/qemu/qemu_snapshot.c
diff --git a/src/qemu/meson.build b/src/qemu/meson.build
index 43a8ad7c3b..7a07d4f2c4 100644
--- a/src/qemu/meson.build
+++ b/src/qemu/meson.build
@@ -34,6 +34,7 @@ qemu_driver_sources = [
   'qemu_postparse.c',
   'qemu_process.c',
   'qemu_qapi.c',
+  'qemu_rdp.c',
   'qemu_saveimage.c',
   'qemu_security.c',
   'qemu_snapshot.c',
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index cf05dca55a..bd740f11c0 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -1038,6 +1038,7 @@ qemuDomainGraphicsPrivateDispose(void *obj)
 
 g_free(priv->tlsAlias);
 g_clear_pointer(&priv->secinfo, qemuDomainSecretInfoFree);
+g_clear_pointer(&priv->rdp, qemuRdpFree);
 }
 
 
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index 03cf84695f..d3ccbcd63c 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -35,6 +35,7 @@
 #include "qemu_capabilities.h"
 #include "qemu_migration_params.h"
 #include "qemu_nbdkit.h"
+#include "qemu_rdp.h"
 #include "qemu_slirp.h"
 #include "qemu_fd.h"
 #include "virchrdev.h"
@@ -419,6 +420,7 @@ struct _qemuDomainGraphicsPrivate {
 
 char *tlsAlias;
 qemuDomainSecretInfo *secinfo;
+qemuRdp *rdp;
 };
 
 
diff --git a/src/qemu/qemu_rdp.c b/src/qemu/qemu_rdp.c
new file mode 100644
index 00..e881b74ee3
--- /dev/null
+++ b/src/qemu/qemu_rdp.c
@@ -0,0 +1,405 @@
+/*
+ * qemu_rdp.c: QEMU Rdp support
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * .
+ */
+
+#include 
+
+#include 
+
+#include "qemu_dbus.h"
+#include "qemu_extdevice.h"
+#include "qemu_security.h"
+#include "qemu_rdp.h"
+#include "virenum.h"
+#include "virerror.h"
+#include "virjson.h"
+#include "virlog.h"
+#include "virpidfile.h"
+#include "virutil.h"
+#include "virgdbus.h"
+
+#define VIR_FROM_THIS VIR_FROM_NONE
+
+VIR_LOG_INIT("qemu.rdp");
+
+VIR_ENUM_IMPL(qemuRdpFeature,
+  QEMU_RDP_FEATURE_LAST,
+  "",
+  "dbus-address",
+  "remotefx"
+);
+
+#define ORG_QEMUDISPLAY_RDP "org.QemuDisplay.RDP"
+#define ORG_QEMUDISPLAY_RDP_PATH "/org/qemu_display/rdp"
+#define ORG_QEMUDISPLAY_RDP_IFACE "org.QemuDisplay.RDP"
+
+
+void
+qemuRdpFree(qemuRdp *rdp)
+{
+if (!rdp)
+return;
+
+virBitmapFree(rdp->features);
+g_free(rdp);
+}
+
+
+void
+qemuRdpSetFeature(qemuRdp *rdp,
+  qemuRdpFeature feature)
+{
+ignore_value(virBitmapSetBit(rdp->features, feature));
+}
+
+
+bool
+qemuRdpHasFeature(const qemuRdp *rdp,
+  qemuRdpFeature feature)
+{
+return virBitmapIsBitSet(rdp->features, feature);
+}
+
+
+qemuRdp *
+qemuRdpNew(void)
+{
+g_autoptr(qemuRdp) rdp = g_new0(qemuRdp, 1);
+
+rdp->features = virBitmapNew(QEMU_RDP_FEATURE_LAST);
+rdp->pid = -1;
+
+return g_steal_pointer(&rdp);
+}
+
+
+qemuRdp *
+qemuRdpNewForHelper(const char *helper)
+{
+g_autoptr(qemuRdp) rdp = NULL;
+g_autoptr(virCommand) cmd = NULL;
+g_autofree char *output = NULL;
+g_autoptr(virJSONValue) doc = NULL;
+virJSONValue *featuresJSON;
+g_autofree char *helperPath = NULL;
+size_t i, nfeatures;
+
+helperPath = virFindFileInPath(helper);
+if (!helperPath) {
+virReportSystemError(errno,
+ _("'%1$s' is not a suitable qemu-rdp helper 
name"),
+ helper);
+return NULL;
+}
+
+rdp = qemuRdpNew();
+cmd = virCommandNewArgList(helperPath, "--print-capabilities", NULL);
+virCommandSetOutputBuffer(cmd, &output);
+if (virCommandRun(cmd, NULL) < 0)
+return NULL;
+

[PATCH v2 18/21] qemu: pass virQEMUDriverConfig to capabilities

2025-02-18 Thread marcandre . lureau
From: Marc-André Lureau 

This will help with the following patch, which also requires config access.

Signed-off-by: Marc-André Lureau 
---
 src/qemu/qemu_capabilities.c | 9 +
 src/qemu/qemu_capabilities.h | 9 +
 src/qemu/qemu_conf.c | 9 +
 tests/domaincapstest.c   | 7 +++
 4 files changed, 18 insertions(+), 16 deletions(-)

diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 23b466c36e..fed7f998d3 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -6938,12 +6938,11 @@ virQEMUCapsFillDomainFeatureHypervCaps(virQEMUCaps 
*qemuCaps,
 
 
 int
-virQEMUCapsFillDomainCaps(virQEMUCaps *qemuCaps,
+virQEMUCapsFillDomainCaps(virQEMUDriverConfig *cfg,
+  virQEMUCaps *qemuCaps,
   virArch hostarch,
   virDomainCaps *domCaps,
-  bool privileged,
-  virFirmware **firmwares,
-  size_t nfirmwares)
+  bool privileged)
 {
 virDomainCapsOS *os = &domCaps->os;
 virDomainCapsDeviceDisk *disk = &domCaps->disk;
@@ -6960,6 +6959,8 @@ virQEMUCapsFillDomainCaps(virQEMUCaps *qemuCaps,
 virDomainCapsLaunchSecurity *launchSecurity = &domCaps->launchSecurity;
 virDomainCapsDeviceNet *net = &domCaps->net;
 virDomainCapsDevicePanic *panic = &domCaps->panic;
+virFirmware **firmwares = cfg->firmwares;
+size_t nfirmwares = cfg->nfirmwares;
 
 virQEMUCapsFillDomainFeaturesFromQEMUCaps(qemuCaps, domCaps);
 
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index ee71331a09..cca31172a6 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -28,6 +28,8 @@
 #include "virfilecache.h"
 #include "virenum.h"
 
+typedef struct _virQEMUDriverConfig virQEMUDriverConfig;
+
 /*
  * Internal flags to keep track of qemu command line capabilities
  *
@@ -864,12 +866,11 @@ void virQEMUCapsInitGuestFromBinary(virCaps *caps,
 virQEMUCaps *qemuCaps,
 virArch guestarch);
 
-int virQEMUCapsFillDomainCaps(virQEMUCaps *qemuCaps,
+int virQEMUCapsFillDomainCaps(virQEMUDriverConfig *cfg,
+  virQEMUCaps *qemuCaps,
   virArch hostarch,
   virDomainCaps *domCaps,
-  bool privileged,
-  virFirmware **firmwares,
-  size_t nfirmwares);
+  bool privileged);
 
 void virQEMUCapsFillDomainMemoryBackingCaps(virQEMUCaps *qemuCaps,
 virDomainCapsMemoryBacking 
*memoryBacking);
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index 25cadf520d..f76e701898 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -1600,10 +1600,11 @@ virQEMUDriverGetDomainCapabilities(virQEMUDriver 
*driver,
 if (!(domCaps = virDomainCapsNew(path, machine, arch, virttype)))
 return NULL;
 
-if (virQEMUCapsFillDomainCaps(qemuCaps, driver->hostarch,
-  domCaps, driver->privileged,
-  cfg->firmwares,
-  cfg->nfirmwares) < 0)
+if (virQEMUCapsFillDomainCaps(cfg,
+  qemuCaps,
+  driver->hostarch,
+  domCaps,
+  driver->privileged) < 0)
 return NULL;
 
 return g_steal_pointer(&domCaps);
diff --git a/tests/domaincapstest.c b/tests/domaincapstest.c
index e520c7d7bc..e4b03dfeab 100644
--- a/tests/domaincapstest.c
+++ b/tests/domaincapstest.c
@@ -98,10 +98,9 @@ fillQemuCaps(virDomainCaps *domCaps,
 if (!domCaps->machine)
 domCaps->machine = g_strdup(virQEMUCapsGetPreferredMachine(qemuCaps, 
virtType));
 
-if (virQEMUCapsFillDomainCaps(qemuCaps, domCaps->arch, domCaps,
-  false,
-  cfg->firmwares,
-  cfg->nfirmwares) < 0)
+if (virQEMUCapsFillDomainCaps(cfg,
+  qemuCaps, domCaps->arch, domCaps,
+  false) < 0)
 return -1;
 
 /* The function above tries to query host's VFIO capabilities by calling
-- 
2.47.0


Re: [PATCH RFC 00/13] qemu: Add support for iothread to virtqueue mapping for 'virtio-scsi'

2025-02-18 Thread Peter Krempa
On Tue, Feb 18, 2025 at 13:53:31 +0800, Stefan Hajnoczi wrote:
> On Fri, Feb 14, 2025 at 05:29:34PM +0100, Peter Krempa wrote:
> > The first part of the series refactors the existing code for reuse and
> > then uses the new helpers to implement the feature.
> > 
> > Note that this series is in RFC state as the qemu patches are still
> > being discussed. Thus also the capability bump is not final.
> > 
> > Also note that we should discuss the libvirt interface perhaps as it
> > turns out that 'virtio-scsi' has two internal queues that need to be
> > mapped as well.
> > 
> > For now I've solved this administratively by instructing users to also
> > add mapping for queue '0' and '1' which are the special ones in case of
> > virtio-scsi.
> 
> Thanks for tackling this upcoming QEMU feature! I thought about the
> pros/cons of exposing all virtqueues in iothread-vq-mapping= whereas
> just the command virtqueues are exposed by num_queues=. Although it's
> confusing and inconvenient that the implicit ctrl and event virtqueues
> need to be covered by iothread-vq-mapping= but are not counted in
> num_queues=, I'd rather not introduce magic to hide this detail. If
> users do need to control these virtqueues explicitly then the magic will
> get in the way.

I thought about it a bit as well and I think we should:

1) Document the round robin assignment a bit more prominently, so that
   users don't feel compelled to do a full mapping. Currently the
   example spells out the full maping configuration, so the first
   example should be the simpler one.

2) Modify the qemu code so that the mapping XML will explicitly name the
'ctrl/event' queues. Leave the numbered ones for the explicit ones
configured via queues. That way it'll be obvious what's happening.


  

  
  


  


  

  



Libvirt will then map the above config to mapping for queues 0,1,2,3 for
use with qemu. That way there will be no ambiguity and weirdness when
comparing the config between virtio-blk and virtio-scsi.

> Does anyone have a different opinion?

I agree. We should hint the users to use the simpler configs and use the
full mapping only if necessary. When using the full mapping the above
XML will IMO make it obvious what's happening.

In qemu no change will be needed although the role of queues 0 and 1
should be formalized in docs so that it doesn't change later on at least
without notifying libvirt so that we adapt if needed.


[PATCH 1/5] qemu: Add support for NVMe disk bus type

2025-02-18 Thread honglei . wang
From: ray 

This patch adds support for the NVMe disk bus type across multiple components:

- Extend virDomainDiskBus enum to include VIR_DOMAIN_DISK_BUS_NVME
- Update driver-specific functions to handle NVMe disks
- Modify disk name parsing to recognize 'nvme' prefix
- Ensure NVMe disks require a serial number and PCI address

Signed-off-by: ray 
---
 src/conf/domain_conf.c |  3 +++
 src/conf/domain_conf.h |  1 +
 src/conf/domain_postparse.c|  2 ++
 src/conf/domain_validate.c |  4 +++-
 src/hyperv/hyperv_driver.c |  2 ++
 src/qemu/qemu_alias.c  |  1 +
 src/qemu/qemu_command.c|  5 +
 src/qemu/qemu_domain_address.c | 25 ++---
 src/qemu/qemu_domain_address.h |  4 
 src/qemu/qemu_hotplug.c|  6 ++
 src/qemu/qemu_validate.c   | 16 
 src/test/test_driver.c |  2 ++
 src/util/virutil.c |  2 +-
 src/vbox/vbox_common.c |  1 +
 src/vmx/vmx.c  |  1 +
 15 files changed, 70 insertions(+), 5 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 49555efc56..bc101cca0e 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -372,6 +372,7 @@ VIR_ENUM_IMPL(virDomainDiskBus,
   "uml",
   "sata",
   "sd",
+  "nvme",
 );
 
 VIR_ENUM_IMPL(virDomainDiskCache,
@@ -6778,6 +6779,7 @@ virDomainDiskDefAssignAddress(virDomainXMLOption *xmlopt 
G_GNUC_UNUSED,
 case VIR_DOMAIN_DISK_BUS_USB:
 case VIR_DOMAIN_DISK_BUS_UML:
 case VIR_DOMAIN_DISK_BUS_SD:
+case VIR_DOMAIN_DISK_BUS_NVME:
 case VIR_DOMAIN_DISK_BUS_LAST:
 default:
 /* Other disk bus's aren't controller based */
@@ -29201,6 +29203,7 @@ virDiskNameToBusDeviceIndex(virDomainDiskDef *disk,
 case VIR_DOMAIN_DISK_BUS_NONE:
 case VIR_DOMAIN_DISK_BUS_SATA:
 case VIR_DOMAIN_DISK_BUS_UML:
+case VIR_DOMAIN_DISK_BUS_NVME:
 case VIR_DOMAIN_DISK_BUS_LAST:
 default:
 *busIdx = 0;
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 9da6586e66..5cde6783c2 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -401,6 +401,7 @@ typedef enum {
 VIR_DOMAIN_DISK_BUS_UML,
 VIR_DOMAIN_DISK_BUS_SATA,
 VIR_DOMAIN_DISK_BUS_SD,
+VIR_DOMAIN_DISK_BUS_NVME,
 
 VIR_DOMAIN_DISK_BUS_LAST
 } virDomainDiskBus;
diff --git a/src/conf/domain_postparse.c b/src/conf/domain_postparse.c
index bf33f29638..a07ec8d94e 100644
--- a/src/conf/domain_postparse.c
+++ b/src/conf/domain_postparse.c
@@ -523,6 +523,8 @@ virDomainDiskDefPostParse(virDomainDiskDef *disk,
 disk->bus = VIR_DOMAIN_DISK_BUS_XEN;
 else if (STRPREFIX(disk->dst, "ubd"))
 disk->bus = VIR_DOMAIN_DISK_BUS_UML;
+else if (STRPREFIX(disk->dst, "nvme"))
+disk->bus = VIR_DOMAIN_DISK_BUS_NVME;
 }
 }
 
diff --git a/src/conf/domain_validate.c b/src/conf/domain_validate.c
index 563558d920..4c96d7cacd 100644
--- a/src/conf/domain_validate.c
+++ b/src/conf/domain_validate.c
@@ -267,6 +267,7 @@ virDomainDiskAddressDiskBusCompatibility(virDomainDiskBus 
bus,
 case VIR_DOMAIN_DISK_BUS_UML:
 case VIR_DOMAIN_DISK_BUS_SD:
 case VIR_DOMAIN_DISK_BUS_NONE:
+case VIR_DOMAIN_DISK_BUS_NVME:
 case VIR_DOMAIN_DISK_BUS_LAST:
 return true;
 }
@@ -930,7 +931,8 @@ virDomainDiskDefValidate(const virDomainDef *def,
 !STRPREFIX(disk->dst, "sd") &&
 !STRPREFIX(disk->dst, "vd") &&
 !STRPREFIX(disk->dst, "xvd") &&
-!STRPREFIX(disk->dst, "ubd")) {
+!STRPREFIX(disk->dst, "ubd") &&
+!STRPREFIX(disk->dst, "nvme")) {
 virReportError(VIR_ERR_INTERNAL_ERROR,
_("Invalid harddisk device name: %1$s"), disk->dst);
 return -1;
diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c
index 43ccb9cbd7..708e10b7dc 100644
--- a/src/hyperv/hyperv_driver.c
+++ b/src/hyperv/hyperv_driver.c
@@ -948,6 +948,7 @@ hypervDomainAttachStorage(virDomainPtr domain, virDomainDef 
*def, const char *ho
 case VIR_DOMAIN_DISK_BUS_UML:
 case VIR_DOMAIN_DISK_BUS_SATA:
 case VIR_DOMAIN_DISK_BUS_SD:
+case VIR_DOMAIN_DISK_BUS_NVME:
 case VIR_DOMAIN_DISK_BUS_LAST:
 default:
 virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Unsupported 
controller type"));
@@ -3090,6 +3091,7 @@ hypervDomainAttachDeviceFlags(virDomainPtr domain, const 
char *xml, unsigned int
 case VIR_DOMAIN_DISK_BUS_UML:
 case VIR_DOMAIN_DISK_BUS_SATA:
 case VIR_DOMAIN_DISK_BUS_SD:
+case VIR_DOMAIN_DISK_BUS_NVME:
 case VIR_DOMAIN_DISK_BUS_LAST:
 default:
 virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid disk bus 
in definition"));
diff --git a/src/qemu/qemu_alias.c b/src/qemu/qemu_alias.c
index 3e6bced4a8..9d39ebd63d 100644
--- a/src/qemu/qemu_alias.c
+++ b/src/qem

Re: [PATCH RFC] util: pick a better runtime directory when XDG_RUNTIME_DIR isn't set

2025-02-18 Thread Laine Stump

On 2/18/25 4:26 AM, Daniel P. Berrangé wrote:

On Mon, Feb 17, 2025 at 03:11:56PM -0500, Laine Stump wrote:

On 2/17/25 5:28 AM, Daniel P. Berrangé wrote:

On Mon, Feb 17, 2025 at 02:14:49AM -0500, Laine Stump wrote:

But sometimes XDG_RUNTIME_DIR isn't set in the user's environment.


Do you have examples of scenarios in which this happens, and
yet the /run/user/ directory is still being created, as
that rather sounds like something is broken outside of libvirt.


After seeing the bug report, I replicated the situation by ssh'ing in as a
user that hadn't previously logged in, and then unsetting XDG_RUNTIME_DIR. I
hadn't thought there might be some other case where the user could be logged
in but XDG_RUNTIME_DIR had never been set.

But after seeing your question I tried running

   sudo $someuser virsh list


NB, that is the classic sudo usage trapdoor, because they didn't
make "-i" (aka --login) the default, so your environment is not
populated correctly.

I'd hope that when passing sudo -i ... it will do the right
thing


It seems not. If I login as $someuser, start a guest, then in a separate 
terminal window from root run:


  sudo -u $someuser -i virsh list

It returns an empty list (the same as if I omit the -i). By running the 
same command without "virsh list", I'm given a shell instance, and 
within that shell I can see that $UID, $USER, and $EUID are all set, but 
$XDG_RUNTIME_DIR is not.


Re: [PATCH] qemu: Avoid crash in qemuDomainCheckCPU with unknown host CPU

2025-02-18 Thread Jaroslav Suchanek
On Tue, Feb 18, 2025 at 11:49:53AM +0100, Jiri Denemark wrote:
> When we don't have any information about host CPU (for example when
> running on an aarch64 host), the virQEMUCapsGetHostModel would return
> NULL.

Tested-by: Jaroslav Suchanek 

> 
> Fixes: https://gitlab.com/libvirt/libvirt/-/issues/747
> Signed-off-by: Jiri Denemark 
> ---
>  src/qemu/qemu_domain.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
> index cf05dca55a..df1ed0223d 100644
> --- a/src/qemu/qemu_domain.c
> +++ b/src/qemu/qemu_domain.c
> @@ -11430,6 +11430,7 @@ qemuDomainCheckCPU(virArch arch,
>  /* Force compat check if the CPU model is not found in qemuCaps or
>   * we don't have host CPU data from QEMU */
>  if (!cpu->model ||
> +!hypervisorCPU ||
>  hypervisorCPU->fallback != VIR_CPU_FALLBACK_FORBID ||
>  virQEMUCapsGetCPUBlockers(qemuCaps, virtType,
>cpu->model, &blockers) < 0)
> -- 
> 2.48.1
> 

-- 
J.


signature.asc
Description: PGP signature


[PATCH v2 08/21] conf: parse optional RDP username & password

2025-02-18 Thread marcandre . lureau
From: Marc-André Lureau 

Like VNC, allow to set credentials for RDP.

Signed-off-by: Marc-André Lureau 
Reviewed-by: Daniel P. Berrangé 
---
 src/conf/domain_conf.c| 13 +
 src/conf/domain_conf.h|  2 ++
 src/conf/schemas/domaincommon.rng | 10 ++
 3 files changed, 25 insertions(+)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 49555efc56..81634134a7 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -1986,6 +1986,7 @@ virDomainGraphicsAuthDefClear(virDomainGraphicsAuthDef 
*def)
 if (!def)
 return;
 
+VIR_FREE(def->username);
 VIR_FREE(def->passwd);
 
 /* Don't free def */
@@ -11286,6 +11287,8 @@ virDomainGraphicsAuthDefParseXML(xmlNodePtr node,
 if (!def->passwd)
 return 0;
 
+def->username = virXMLPropString(node, "username");
+
 validTo = virXMLPropString(node, "passwdValidTo");
 if (validTo) {
 g_autoptr(GDateTime) then = NULL;
@@ -11675,6 +11678,10 @@ virDomainGraphicsDefParseXMLRDP(virDomainGraphicsDef 
*def,
 if (STREQ_NULLABLE(multiUser, "yes"))
 def->data.rdp.multiUser = true;
 
+if (virDomainGraphicsAuthDefParseXML(node, &def->data.rdp.auth,
+ def->type) < 0)
+return -1;
+
 return 0;
 }
 
@@ -26315,6 +26322,10 @@ virDomainGraphicsAuthDefFormatAttr(virBuffer *buf,
 if (!def->passwd)
 return;
 
+if (def->username)
+virBufferEscapeString(buf, " username='%s'",
+  def->username);
+
 if (flags & VIR_DOMAIN_DEF_FORMAT_SECURE)
 virBufferEscapeString(buf, " passwd='%s'",
   def->passwd);
@@ -26544,6 +26555,8 @@ virDomainGraphicsDefFormat(virBuffer *buf,
 
 virDomainGraphicsListenDefFormatAddr(buf, glisten, flags);
 
+virDomainGraphicsAuthDefFormatAttr(buf, &def->data.rdp.auth, flags);
+
 break;
 
 case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP:
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 9da6586e66..b9c8031424 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1903,6 +1903,7 @@ typedef enum {
 } virDomainGraphicsAuthConnectedType;
 
 struct _virDomainGraphicsAuthDef {
+char *username;
 char *passwd;
 bool expires; /* Whether there is an expiry time set */
 time_t validTo;  /* seconds since epoch */
@@ -2027,6 +2028,7 @@ struct _virDomainGraphicsDef {
 bool autoport;
 bool replaceUser;
 bool multiUser;
+virDomainGraphicsAuthDef auth;
 } rdp;
 struct {
 char *display;
diff --git a/src/conf/schemas/domaincommon.rng 
b/src/conf/schemas/domaincommon.rng
index 3328a63205..300ab21c57 100644
--- a/src/conf/schemas/domaincommon.rng
+++ b/src/conf/schemas/domaincommon.rng
@@ -4546,6 +4546,16 @@
   
 
   
+  
+
+  
+
+  
+  
+
+  
+
+  
   
 
 
-- 
2.47.0


[PATCH v2 09/21] conf: generalize virDomainDefHasSpiceGraphics

2025-02-18 Thread marcandre . lureau
From: Marc-André Lureau 

Generalize the function, broaden its potential usage.

Signed-off-by: Marc-André Lureau 
Reviewed-by: Daniel P. Berrangé 
---
 src/conf/domain_conf.c   | 15 ---
 src/conf/domain_conf.h   |  2 +-
 src/libvirt_private.syms |  2 +-
 src/qemu/qemu_validate.c |  4 ++--
 4 files changed, 16 insertions(+), 7 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 81634134a7..fde042a206 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -31779,15 +31779,24 @@ virDomainObjGetMessages(virDomainObj *vm,
 
 }
 
+
+/**
+ * virDomainDefHasGraphics:
+ * @def: domain definition
+ * @type: a graphics type
+ *
+ * Returns true if domain has a graphics of given type.
+ */
 bool
-virDomainDefHasSpiceGraphics(const virDomainDef *def)
+virDomainDefHasGraphics(const virDomainDef *def, virDomainGraphicsType type)
 {
 size_t i = 0;
 
 for (i = 0; i < def->ngraphics; i++) {
-if (def->graphics[i]->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE) {
+virDomainGraphicsDef *graphics = def->graphics[i];
+
+if (graphics->type == type)
 return true;
-}
 }
 
 return false;
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index b9c8031424..eabb31d463 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -4601,4 +4601,4 @@ virDomainObjGetMessages(virDomainObj *vm,
 unsigned int flags);
 
 bool
-virDomainDefHasSpiceGraphics(const virDomainDef *def);
+virDomainDefHasGraphics(const virDomainDef *def, virDomainGraphicsType type);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 30a9f806f0..2f20a124b3 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -337,6 +337,7 @@ virDomainDefGetVcpus;
 virDomainDefGetVcpusMax;
 virDomainDefGetVcpusTopology;
 virDomainDefHasDeviceAddress;
+virDomainDefHasGraphics;
 virDomainDefHasManagedPR;
 virDomainDefHasMdevHostdev;
 virDomainDefHasMemballoon;
@@ -345,7 +346,6 @@ virDomainDefHasNVMeDisk;
 virDomainDefHasOldStyleROUEFI;
 virDomainDefHasOldStyleUEFI;
 virDomainDefHasPCIHostdev;
-virDomainDefHasSpiceGraphics;
 virDomainDefHasUSB;
 virDomainDefHasVcpusOffline;
 virDomainDefHasVDPANet;
diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c
index 3e3e368da3..3dc09ca5e0 100644
--- a/src/qemu/qemu_validate.c
+++ b/src/qemu/qemu_validate.c
@@ -2126,7 +2126,7 @@ qemuValidateDomainChrSourceDef(const 
virDomainChrSourceDef *def,
 
 case VIR_DOMAIN_CHR_TYPE_SPICEVMC:
 case VIR_DOMAIN_CHR_TYPE_SPICEPORT:
-if (!virDomainDefHasSpiceGraphics(vmdef)) {
+if (!virDomainDefHasGraphics(vmdef, VIR_DOMAIN_GRAPHICS_TYPE_SPICE)) {
 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("chardev '%1$s' not supported without spice 
graphics"),
virDomainChrTypeToString(def->type));
@@ -4695,7 +4695,7 @@ qemuValidateDomainDeviceDefAudio(virDomainAudioDef *audio,
 break;
 
 case VIR_DOMAIN_AUDIO_TYPE_SPICE:
-if (!virDomainDefHasSpiceGraphics(def)) {
+if (!virDomainDefHasGraphics(def, VIR_DOMAIN_GRAPHICS_TYPE_SPICE)) {
 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("Spice audio is not supported without spice 
graphics"));
 return -1;
-- 
2.47.0


[PATCH v2 11/21] qemu: add RDP ports range allocator

2025-02-18 Thread marcandre . lureau
From: Marc-André Lureau 

RDP server uses port 3389 by default.

Signed-off-by: Marc-André Lureau 
Reviewed-by: Daniel P. Berrangé 
---
 src/qemu/qemu_conf.c   | 6 ++
 src/qemu/qemu_conf.h   | 6 ++
 src/qemu/qemu_driver.c | 8 
 3 files changed, 20 insertions(+)

diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index 746eaf0347..25cadf520d 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -64,6 +64,9 @@ VIR_LOG_INIT("qemu.qemu_conf");
 #define QEMU_REMOTE_PORT_MIN 5900
 #define QEMU_REMOTE_PORT_MAX 65535
 
+#define QEMU_RDP_PORT_MIN 3389
+#define QEMU_RDP_PORT_MAX 65535
+
 #define QEMU_WEBSOCKET_PORT_MIN 5700
 #define QEMU_WEBSOCKET_PORT_MAX 65535
 
@@ -247,6 +250,9 @@ virQEMUDriverConfig *virQEMUDriverConfigNew(bool privileged,
 cfg->remotePortMin = QEMU_REMOTE_PORT_MIN;
 cfg->remotePortMax = QEMU_REMOTE_PORT_MAX;
 
+cfg->rdpPortMin = QEMU_RDP_PORT_MIN;
+cfg->rdpPortMax = QEMU_RDP_PORT_MAX;
+
 cfg->webSocketPortMin = QEMU_WEBSOCKET_PORT_MIN;
 cfg->webSocketPortMax = QEMU_WEBSOCKET_PORT_MAX;
 
diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
index f161c4297a..ccba88f7eb 100644
--- a/src/qemu/qemu_conf.h
+++ b/src/qemu/qemu_conf.h
@@ -169,6 +169,9 @@ struct _virQEMUDriverConfig {
 unsigned int remotePortMin;
 unsigned int remotePortMax;
 
+unsigned int rdpPortMin;
+unsigned int rdpPortMax;
+
 unsigned int webSocketPortMin;
 unsigned int webSocketPortMax;
 
@@ -312,6 +315,9 @@ struct _virQEMUDriver {
 /* Immutable pointer, immutable object */
 virPortAllocatorRange *webSocketPorts;
 
+/* Immutable pointer, immutable object */
+virPortAllocatorRange *rdpPorts;
+
 /* Immutable pointer, immutable object */
 virPortAllocatorRange *migrationPorts;
 
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 091b20129e..2ac76709cb 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -701,6 +701,13 @@ qemuStateInitialize(bool privileged,
   cfg->webSocketPortMax)) == NULL)
 goto error;
 
+if ((qemu_driver->rdpPorts =
+ virPortAllocatorRangeNew(_("rdp"),
+  cfg->rdpPortMin,
+  cfg->rdpPortMax)) == NULL)
+goto error;
+
+
 if ((qemu_driver->migrationPorts =
  virPortAllocatorRangeNew(_("migration"),
   cfg->migrationPortMin,
@@ -1050,6 +1057,7 @@ qemuStateCleanup(void)
 virSysinfoDefFree(qemu_driver->hostsysinfo);
 virPortAllocatorRangeFree(qemu_driver->migrationPorts);
 virPortAllocatorRangeFree(qemu_driver->webSocketPorts);
+virPortAllocatorRangeFree(qemu_driver->rdpPorts);
 virPortAllocatorRangeFree(qemu_driver->remotePorts);
 virObjectUnref(qemu_driver->hostdevMgr);
 virObjectUnref(qemu_driver->securityManager);
-- 
2.47.0


[PATCH v2 10/21] qemu: use virDomainDefHasGraphics

2025-02-18 Thread marcandre . lureau
From: Marc-André Lureau 

Signed-off-by: Marc-André Lureau 
Reviewed-by: Daniel P. Berrangé 
---
 src/qemu/qemu_validate.c | 11 +--
 1 file changed, 1 insertion(+), 10 deletions(-)

diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c
index 3dc09ca5e0..da3321849c 100644
--- a/src/qemu/qemu_validate.c
+++ b/src/qemu/qemu_validate.c
@@ -4448,8 +4448,6 @@ qemuValidateDomainDeviceDefGraphics(const 
virDomainGraphicsDef *graphics,
 virQEMUCaps *qemuCaps)
 {
 virDomainCapsDeviceGraphics graphicsCaps = { 0 };
-bool have_egl_headless = false;
-size_t i;
 
 virQEMUCapsFillDomainDeviceGraphicsCaps(qemuCaps, &graphicsCaps);
 
@@ -4460,18 +4458,11 @@ qemuValidateDomainDeviceDefGraphics(const 
virDomainGraphicsDef *graphics,
 return -1;
 }
 
-for (i = 0; i < def->ngraphics; i++) {
-if (def->graphics[i]->type == VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS) {
-have_egl_headless = true;
-break;
-}
-}
-
 /* Only VNC and SPICE can be paired with egl-headless, the other types
  * either don't make sense to pair with egl-headless or aren't even
  * supported by QEMU.
  */
-if (have_egl_headless) {
+if (virDomainDefHasGraphics(def, VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS)) {
 if (graphics->type != VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS &&
 graphics->type != VIR_DOMAIN_GRAPHICS_TYPE_VNC &&
 graphics->type != VIR_DOMAIN_GRAPHICS_TYPE_SPICE) {
-- 
2.47.0


[PATCH v2 12/21] qemu: limit to one

2025-02-18 Thread marcandre . lureau
From: Marc-André Lureau 

Signed-off-by: Marc-André Lureau 
---
 src/qemu/qemu_command.c | 8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 772e98fbb4..4e29e841f9 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -8447,6 +8447,7 @@ qemuBuildGraphicsCommandLine(virQEMUDriverConfig *cfg,
 
 break;
 case VIR_DOMAIN_GRAPHICS_TYPE_RDP:
+break;
 case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP:
 case VIR_DOMAIN_GRAPHICS_TYPE_LAST:
 default:
@@ -9998,6 +,7 @@ qemuBuildCommandLineValidate(virQEMUDriver *driver,
 int spice = 0;
 int egl_headless = 0;
 int dbus = 0;
+int rdp = 0;
 
 if (!driver->privileged) {
 /* If we have no cgroups then we can have no tunings that
@@ -10046,15 +10048,17 @@ qemuBuildCommandLineValidate(virQEMUDriver *driver,
 ++dbus;
 break;
 case VIR_DOMAIN_GRAPHICS_TYPE_RDP:
+++rdp;
+break;
 case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP:
 case VIR_DOMAIN_GRAPHICS_TYPE_LAST:
 break;
 }
 }
 
-if (sdl > 1 || vnc > 1 || spice > 1 || egl_headless > 1 || dbus > 1) {
+if (sdl > 1 || vnc > 1 || spice > 1 || egl_headless > 1 || dbus > 1 || rdp 
> 1) {
 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-   _("only 1 graphics device of each type (sdl, vnc, 
spice, headless, dbus) is supported"));
+   _("only 1 graphics device of each type (sdl, vnc, 
spice, headless, dbus, rdp) is supported"));
 return -1;
 }
 
-- 
2.47.0


[PATCH v2 13/21] qemu/virtiofs: use domainLogContext

2025-02-18 Thread marcandre . lureau
From: Marc-André Lureau 

Signed-off-by: Marc-André Lureau 
---
 src/qemu/qemu_virtiofs.c | 53 +---
 1 file changed, 12 insertions(+), 41 deletions(-)

diff --git a/src/qemu/qemu_virtiofs.c b/src/qemu/qemu_virtiofs.c
index dd3e0dd9fe..aa282024a4 100644
--- a/src/qemu/qemu_virtiofs.c
+++ b/src/qemu/qemu_virtiofs.c
@@ -75,19 +75,6 @@ qemuVirtioFSCreateSocketFilename(virDomainObj *vm,
 }
 
 
-static char *
-qemuVirtioFSCreateLogFilename(virQEMUDriverConfig *cfg,
-  const virDomainDef *def,
-  const char *alias)
-{
-g_autofree char *name = NULL;
-
-name = g_strdup_printf("%s-%s", def->name, alias);
-
-return virFileBuildPath(cfg->logDir, name, "-virtiofsd.log");
-}
-
-
 static int
 qemuVirtioFSOpenChardev(virQEMUDriver *driver,
 virDomainObj *vm,
@@ -244,10 +231,11 @@ qemuVirtioFSStart(virQEMUDriver *driver,
 g_autoptr(virCommand) cmd = NULL;
 g_autofree char *socket_path = NULL;
 g_autofree char *pidfile = NULL;
-g_autofree char *logpath = NULL;
+g_autofree char *logname = NULL;
 pid_t pid = (pid_t) -1;
 VIR_AUTOCLOSE fd = -1;
-VIR_AUTOCLOSE logfd = -1;
+int logfd = -1;
+g_autoptr(domainLogContext) logContext = NULL;
 int rc;
 
 if (!virFileIsExecutable(fs->binary)) {
@@ -272,35 +260,18 @@ qemuVirtioFSStart(virQEMUDriver *driver,
 if ((fd = qemuVirtioFSOpenChardev(driver, vm, socket_path)) < 0)
 goto error;
 
-logpath = qemuVirtioFSCreateLogFilename(cfg, vm->def, fs->info.alias);
-
-if (cfg->stdioLogD) {
-g_autoptr(virLogManager) logManager = 
virLogManagerNew(driver->privileged);
 
-if (!logManager)
-goto error;
-
-if ((logfd = virLogManagerDomainOpenLogFile(logManager,
-"qemu",
-vm->def->uuid,
-vm->def->name,
-logpath,
-0,
-NULL, NULL)) < 0)
-goto error;
-} else {
-if ((logfd = open(logpath, O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | 
S_IWUSR)) < 0) {
-virReportSystemError(errno, _("failed to create logfile %1$s"),
- logpath);
-goto error;
-}
-if (virSetCloseExec(logfd) < 0) {
-virReportSystemError(errno, _("failed to set close-on-exec flag on 
%1$s"),
- logpath);
-goto error;
-}
+logname = g_strdup_printf("%s-%s-virtiofsd", vm->def->name, 
fs->info.alias);
+if (!(logContext = domainLogContextNew(cfg->stdioLogD, cfg->logDir,
+   QEMU_DRIVER_NAME,
+   vm, driver->privileged,
+   logname))) {
+virLastErrorPrefixMessage("%s", _("can't open log context"));
+goto error;
 }
 
+logfd = domainLogContextGetWriteFD(logContext);
+
 if (!(cmd = qemuVirtioFSBuildCommandLine(cfg, fs, &fd)))
 goto error;
 
-- 
2.47.0


[PATCH v2 07/21] qemu: add qemu RDP configuration

2025-02-18 Thread marcandre . lureau
From: Marc-André Lureau 

Signed-off-by: Marc-André Lureau 
Reviewed-by: Daniel P. Berrangé 
---
 src/qemu/libvirtd_qemu.aug |  7 ++
 src/qemu/qemu.conf.in  | 31 
 src/qemu/qemu_conf.c   | 39 ++
 src/qemu/qemu_conf.h   |  6 +
 src/qemu/test_libvirtd_qemu.aug.in |  5 
 tests/testutilsqemu.c  |  2 ++
 6 files changed, 90 insertions(+)

diff --git a/src/qemu/libvirtd_qemu.aug b/src/qemu/libvirtd_qemu.aug
index 642093c40b..0288c2895b 100644
--- a/src/qemu/libvirtd_qemu.aug
+++ b/src/qemu/libvirtd_qemu.aug
@@ -50,6 +50,11 @@ module Libvirtd_qemu =
  | bool_entry "spice_sasl"
  | str_entry "spice_sasl_dir"
 
+   let rdp_entry = str_entry "rdp_listen"
+ | str_entry "rdp_tls_x509_cert_dir"
+ | str_entry "rdp_username"
+ | str_entry "rdp_password"
+
let chardev_entry = bool_entry "chardev_tls"
  | str_entry "chardev_tls_x509_cert_dir"
  | bool_entry "chardev_tls_x509_verify"
@@ -103,6 +108,7 @@ module Libvirtd_qemu =
  | str_entry "bridge_helper"
  | str_entry "pr_helper"
  | str_entry "slirp_helper"
+ | str_entry "qemu_rdp"
  | str_entry "dbus_daemon"
  | bool_entry "set_process_name"
  | int_entry "max_processes"
@@ -156,6 +162,7 @@ module Libvirtd_qemu =
let entry = default_tls_entry
  | vnc_entry
  | spice_entry
+ | rdp_entry
  | chardev_entry
  | migrate_entry
  | backup_entry
diff --git a/src/qemu/qemu.conf.in b/src/qemu/qemu.conf.in
index 31172303dc..9354e960f1 100644
--- a/src/qemu/qemu.conf.in
+++ b/src/qemu/qemu.conf.in
@@ -229,6 +229,31 @@
 #
 #spice_sasl_dir = "/some/directory/sasl2"
 
+# RDP is configured to listen on 127.0.0.1 by default.
+# To make it listen on all public interfaces, uncomment
+# this next option.
+#
+#rdp_listen = "0.0.0.0"
+
+# In order to override the default TLS certificate location for
+# RDP certificates, supply a valid path to the certificate directory.
+# If the path is not provided, then the default_tls_x509_cert_dir path
+# will be used.
+#
+#rdp_tls_x509_cert_dir = "/etc/pki/libvirt-rdp"
+
+# The default RDP username. This parameter is only used if the
+# per-domain XML config does not already provide a username.
+#
+#rdp_username = "user"
+
+# The default RDP password. This parameter is only used if the
+# per-domain XML config does not already provide a password.
+# By default, RDP server will not allow password-less connections.
+# Obviously change this example here before you set this.
+#
+#rdp_password = "RDP12345"
+
 # Enable use of TLS encryption on the chardev TCP transports.
 #
 # It is necessary to setup CA and issue a server certificate
@@ -923,6 +948,12 @@
 # Path to the SLIRP networking helper.
 #slirp_helper = "/usr/bin/slirp-helper"
 
+
+# Path to qemu-rdp
+# If this is not an absolute path, the program will be searched for
+# in $PATH.
+#qemu_rdp = "qemu-rdp"
+
 # Path to the dbus-daemon
 # If this is not an absolute path, the program will be searched for
 # in $PATH.
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index c6e75d572d..746eaf0347 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -103,6 +103,7 @@ VIR_ONCE_GLOBAL_INIT(virQEMUConfig);
 
 #define QEMU_BRIDGE_HELPER "qemu-bridge-helper"
 #define QEMU_PR_HELPER "qemu-pr-helper"
+#define QEMU_RDP "qemu-rdp"
 #define QEMU_DBUS_DAEMON "dbus-daemon"
 
 
@@ -240,6 +241,7 @@ virQEMUDriverConfig *virQEMUDriverConfigNew(bool privileged,
 }
 
 cfg->vncListen = g_strdup(VIR_LOOPBACK_IPV4_ADDR);
+cfg->rdpListen = g_strdup(VIR_LOOPBACK_IPV4_ADDR);
 cfg->spiceListen = g_strdup(VIR_LOOPBACK_IPV4_ADDR);
 
 cfg->remotePortMin = QEMU_REMOTE_PORT_MIN;
@@ -265,6 +267,7 @@ virQEMUDriverConfig *virQEMUDriverConfigNew(bool privileged,
 cfg->prHelperName = g_strdup(QEMU_PR_HELPER);
 cfg->slirpHelperName = g_strdup(QEMU_SLIRP_HELPER);
 cfg->dbusDaemonName = g_strdup(QEMU_DBUS_DAEMON);
+cfg->qemuRdpName = g_strdup(QEMU_RDP);
 
 cfg->securityDefaultConfined = true;
 cfg->securityRequireConfined = false;
@@ -351,6 +354,11 @@ static void virQEMUDriverConfigDispose(void *obj)
 g_free(cfg->spicePassword);
 g_free(cfg->spiceSASLdir);
 
+g_free(cfg->rdpTLSx509certdir);
+g_free(cfg->rdpListen);
+g_free(cfg->rdpUsername);
+g_free(cfg->rdpPassword);
+
 g_free(cfg->chardevTLSx509certdir);
 g_free(cfg->chardevTLSx509secretUUID);
 
@@ -375,6 +383,7 @@ static void virQEMUDriverConfigDispose(void *obj)
 g_free(cfg->prHelperName);
 g_free(cfg->slirpHelperName);
 g_free(cfg->dbusDaemonName);
+g_free(cfg->qemuRdpName);
 
 g_free(cfg->saveImageFormat);
 g_free(cfg->dumpImageFormat);
@@ -502,6 +511,21 @@ vi

[PATCH v2 06/21] qemu: add rdp state directory

2025-02-18 Thread marcandre . lureau
From: Marc-André Lureau 

Signed-off-by: Marc-André Lureau 
Reviewed-by: Daniel P. Berrangé 
---
 src/qemu/qemu_conf.c   |  2 ++
 src/qemu/qemu_conf.h   |  1 +
 src/qemu/qemu_driver.c | 12 
 tests/testutilsqemu.c  |  2 ++
 4 files changed, 17 insertions(+)

diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index b73dda7e10..c6e75d572d 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -225,6 +225,7 @@ virQEMUDriverConfig *virQEMUDriverConfigNew(bool privileged,
 cfg->configDir = g_strdup_printf("%s/qemu", cfg->configBaseDir);
 cfg->autostartDir = g_strdup_printf("%s/qemu/autostart", 
cfg->configBaseDir);
 cfg->slirpStateDir = g_strdup_printf("%s/slirp", cfg->stateDir);
+cfg->rdpStateDir = g_strdup_printf("%s/rdp", cfg->stateDir);
 cfg->passtStateDir = g_strdup_printf("%s/passt", cfg->stateDir);
 cfg->dbusStateDir = g_strdup_printf("%s/dbus", cfg->stateDir);
 
@@ -326,6 +327,7 @@ static void virQEMUDriverConfigDispose(void *obj)
 g_free(cfg->slirpStateDir);
 g_free(cfg->passtStateDir);
 g_free(cfg->dbusStateDir);
+g_free(cfg->rdpStateDir);
 
 g_free(cfg->libDir);
 g_free(cfg->cacheDir);
diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
index 97214f72d0..33597bba08 100644
--- a/src/qemu/qemu_conf.h
+++ b/src/qemu/qemu_conf.h
@@ -99,6 +99,7 @@ struct _virQEMUDriverConfig {
 char *slirpStateDir;
 char *passtStateDir;
 char *dbusStateDir;
+char *rdpStateDir;
 /* These two directories are ones QEMU processes use (so must match
  * the QEMU user/group */
 char *libDir;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 1d0da1028f..091b20129e 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -648,6 +648,11 @@ qemuStateInitialize(bool privileged,
  cfg->dbusStateDir);
 goto error;
 }
+if (g_mkdir_with_parents(cfg->rdpStateDir, 0777) < 0) {
+virReportSystemError(errno, _("Failed to create rdp state dir %1$s"),
+ cfg->rdpStateDir);
+goto error;
+}
 
 qemu_driver->inhibitor = virInhibitorNew(
 VIR_INHIBITOR_WHAT_SHUTDOWN,
@@ -793,6 +798,13 @@ qemuStateInitialize(bool privileged,
  (int)cfg->group);
 goto error;
 }
+if (chown(cfg->rdpStateDir, cfg->user, cfg->group) < 0) {
+virReportSystemError(errno,
+ _("unable to set ownership of '%1$s' to 
%2$d:%3$d"),
+ cfg->rdpStateDir, (int)cfg->user,
+ (int)cfg->group);
+goto error;
+}
 
 run_uid = cfg->user;
 run_gid = cfg->group;
diff --git a/tests/testutilsqemu.c b/tests/testutilsqemu.c
index 44011c2b36..ad0c43ccdf 100644
--- a/tests/testutilsqemu.c
+++ b/tests/testutilsqemu.c
@@ -330,6 +330,8 @@ int qemuTestDriverInit(virQEMUDriver *driver)
 cfg->passtStateDir = g_strdup("/var/run/libvirt/qemu/passt");
 VIR_FREE(cfg->dbusStateDir);
 cfg->dbusStateDir = g_strdup("/var/run/libvirt/qemu/dbus");
+VIR_FREE(cfg->rdpStateDir);
+cfg->rdpStateDir = g_strdup("/var/run/libvirt/qemu/rdp");
 
 if (!g_mkdtemp(statedir)) {
 fprintf(stderr, "Cannot create fake stateDir");
-- 
2.47.0


[PATCH 2/5] qemu: Add support for NVMe namespace disk bus type

2025-02-18 Thread honglei . wang
From: ray 

This patch extends the previous NVMe disk bus support by introducing a new
nvme-ns bus type.

The nvme-ns bus disk needs to be attached to nvme controller. A controller
can contain multiple nvme-ns disk devices.

Key changes include:

- Add VIR_DOMAIN_DISK_BUS_NVME_NS to disk bus
- Add VIR_DOMAIN_CONTROLLER_TYPE_NVME to controller type
- Update driver-specific functions to handle nvme-ns disks
- Modify disk name parsing to recognize 'nvmens' prefix
- Add support for NVMe namespace-specific addressing and controller handling
- Implement NVMe controller serial number parsing and formatting

Signed-off-by: ray 
---
 src/conf/domain_conf.c | 39 +++
 src/conf/domain_conf.h |  7 +++
 src/conf/domain_postparse.c|  2 ++
 src/conf/domain_validate.c |  1 +
 src/conf/virconftypes.h|  2 ++
 src/hyperv/hyperv_driver.c |  2 ++
 src/qemu/qemu_alias.c  |  1 +
 src/qemu/qemu_command.c| 26 ++
 src/qemu/qemu_domain_address.c |  5 +
 src/qemu/qemu_hotplug.c|  8 
 src/qemu/qemu_postparse.c  |  1 +
 src/qemu/qemu_validate.c   | 12 
 src/test/test_driver.c |  2 ++
 src/util/virutil.c |  2 +-
 src/vbox/vbox_common.c |  2 ++
 src/vmx/vmx.c  |  1 +
 16 files changed, 112 insertions(+), 1 deletion(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index bc101cca0e..d21cf404e2 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -373,6 +373,7 @@ VIR_ENUM_IMPL(virDomainDiskBus,
   "sata",
   "sd",
   "nvme",
+  "nvme-ns",
 );
 
 VIR_ENUM_IMPL(virDomainDiskCache,
@@ -421,6 +422,7 @@ VIR_ENUM_IMPL(virDomainController,
   "pci",
   "xenbus",
   "isa",
+  "nvme",
 );
 
 VIR_ENUM_IMPL(virDomainControllerModelPCI,
@@ -2545,6 +2547,7 @@ virDomainControllerDefNew(virDomainControllerType type)
 case VIR_DOMAIN_CONTROLLER_TYPE_SATA:
 case VIR_DOMAIN_CONTROLLER_TYPE_CCID:
 case VIR_DOMAIN_CONTROLLER_TYPE_ISA:
+case VIR_DOMAIN_CONTROLLER_TYPE_NVME:
 case VIR_DOMAIN_CONTROLLER_TYPE_LAST:
 break;
 }
@@ -6773,6 +6776,14 @@ virDomainDiskDefAssignAddress(virDomainXMLOption *xmlopt 
G_GNUC_UNUSED,
 def->info.addr.drive.unit = idx % 2;
 break;
 
+case VIR_DOMAIN_DISK_BUS_NVME_NS:
+/* For NVME-NS, each nvme controller has a maximum of 256 nvme-ns */
+def->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE;
+def->info.addr.drive.controller = idx / 256;
+def->info.addr.drive.bus = 0;
+def->info.addr.drive.unit = idx % 256;
+break;
+
 case VIR_DOMAIN_DISK_BUS_NONE:
 case VIR_DOMAIN_DISK_BUS_VIRTIO:
 case VIR_DOMAIN_DISK_BUS_XEN:
@@ -8513,6 +8524,7 @@ virDomainControllerModelTypeFromString(const 
virDomainControllerDef *def,
 case VIR_DOMAIN_CONTROLLER_TYPE_SATA:
 case VIR_DOMAIN_CONTROLLER_TYPE_CCID:
 case VIR_DOMAIN_CONTROLLER_TYPE_XENBUS:
+case VIR_DOMAIN_CONTROLLER_TYPE_NVME:
 case VIR_DOMAIN_CONTROLLER_TYPE_LAST:
 return -1;
 }
@@ -8541,6 +8553,7 @@ 
virDomainControllerModelTypeToString(virDomainControllerDef *def,
 case VIR_DOMAIN_CONTROLLER_TYPE_SATA:
 case VIR_DOMAIN_CONTROLLER_TYPE_CCID:
 case VIR_DOMAIN_CONTROLLER_TYPE_XENBUS:
+case VIR_DOMAIN_CONTROLLER_TYPE_NVME:
 case VIR_DOMAIN_CONTROLLER_TYPE_LAST:
 return NULL;
 }
@@ -8561,6 +8574,8 @@ virDomainControllerDefParseXML(virDomainXMLOption *xmlopt,
 int ntargetNodes = 0;
 g_autofree xmlNodePtr *modelNodes = NULL;
 int nmodelNodes = 0;
+g_autofree xmlNodePtr *serialNodes = NULL;
+int nserialNodes = 0;
 int numaNode = -1;
 int ports;
 VIR_XPATH_NODE_AUTORESTORE(ctxt)
@@ -8696,6 +8711,18 @@ virDomainControllerDefParseXML(virDomainXMLOption 
*xmlopt,
 if (virXMLPropInt(node, "ports", 10, VIR_XML_PROP_NONNEGATIVE, &ports, -1) 
< 0)
 return NULL;
 
+if ((nserialNodes = virXPathNodeSet("./serial", ctxt, &serialNodes)) > 1) {
+virReportError(VIR_ERR_XML_ERROR, "%s",
+   _("Multiple  elements in controller definition 
not allowed"));
+return NULL;
+}
+
+if (nserialNodes == 1) {
+if (def->type == VIR_DOMAIN_CONTROLLER_TYPE_NVME) {
+   def->opts.nvmeopts.serial = virXMLNodeContentString(serialNodes[0]);
+}
+}
+
 switch (def->type) {
 case VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL: {
 if (virXMLPropInt(node, "vectors", 10, VIR_XML_PROP_NONNEGATIVE,
@@ -8781,6 +8808,7 @@ virDomainControllerDefParseXML(virDomainXMLOption *xmlopt,
 case VIR_DOMAIN_CONTROLLER_TYPE_SATA:
 case VIR_DOMAIN_CONTROLLER_TYPE_CCID:
 case VIR_DOMAIN_CONTROLLER_TYPE_ISA:
+case VIR_DOMAIN_CONTROLLER_TYPE_NVME:
 case VIR_DOMAIN_CONTROLLER_TYPE_LAST:
 default:
 break;
@@ -1471

[PATCH 3/5] qemu_capabilities: Add support for NVMe disk capabilities

2025-02-18 Thread honglei . wang
From: ray 

This patch extends QEMU capabilities support for nvme and nvme-ns disks.

Signed-off-by: ray 
---
 src/qemu/qemu_capabilities.c | 10 ++
 src/qemu/qemu_capabilities.h |  2 ++
 src/qemu/qemu_validate.c | 12 
 tests/domaincapsdata/qemu_10.0.0-q35.x86_64.xml  |  2 ++
 tests/domaincapsdata/qemu_10.0.0-tcg.x86_64.xml  |  2 ++
 tests/domaincapsdata/qemu_10.0.0.s390x.xml   |  2 ++
 tests/domaincapsdata/qemu_10.0.0.x86_64.xml  |  2 ++
 tests/domaincapsdata/qemu_5.2.0-q35.x86_64.xml   |  2 ++
 tests/domaincapsdata/qemu_5.2.0-tcg-virt.riscv64.xml |  2 ++
 tests/domaincapsdata/qemu_5.2.0-tcg.x86_64.xml   |  2 ++
 tests/domaincapsdata/qemu_5.2.0-virt.aarch64.xml |  2 ++
 tests/domaincapsdata/qemu_5.2.0-virt.riscv64.xml |  2 ++
 tests/domaincapsdata/qemu_5.2.0.aarch64.xml  |  2 ++
 tests/domaincapsdata/qemu_5.2.0.ppc64.xml|  2 ++
 tests/domaincapsdata/qemu_5.2.0.x86_64.xml   |  2 ++
 tests/domaincapsdata/qemu_6.0.0-q35.x86_64.xml   |  2 ++
 tests/domaincapsdata/qemu_6.0.0-tcg.x86_64.xml   |  2 ++
 tests/domaincapsdata/qemu_6.0.0-virt.aarch64.xml |  2 ++
 tests/domaincapsdata/qemu_6.0.0.aarch64.xml  |  2 ++
 tests/domaincapsdata/qemu_6.0.0.x86_64.xml   |  2 ++
 tests/domaincapsdata/qemu_6.1.0-q35.x86_64.xml   |  2 ++
 tests/domaincapsdata/qemu_6.1.0-tcg.x86_64.xml   |  2 ++
 tests/domaincapsdata/qemu_6.1.0.x86_64.xml   |  2 ++
 tests/domaincapsdata/qemu_6.2.0-q35.x86_64.xml   |  2 ++
 tests/domaincapsdata/qemu_6.2.0-tcg.x86_64.xml   |  2 ++
 tests/domaincapsdata/qemu_6.2.0-virt.aarch64.xml |  2 ++
 tests/domaincapsdata/qemu_6.2.0.aarch64.xml  |  2 ++
 tests/domaincapsdata/qemu_6.2.0.ppc64.xml|  2 ++
 tests/domaincapsdata/qemu_6.2.0.x86_64.xml   |  2 ++
 tests/domaincapsdata/qemu_7.0.0-hvf.aarch64+hvf.xml  |  2 ++
 tests/domaincapsdata/qemu_7.0.0-q35.x86_64.xml   |  2 ++
 tests/domaincapsdata/qemu_7.0.0-tcg.x86_64.xml   |  2 ++
 tests/domaincapsdata/qemu_7.0.0-virt.aarch64.xml |  2 ++
 tests/domaincapsdata/qemu_7.0.0.aarch64.xml  |  2 ++
 tests/domaincapsdata/qemu_7.0.0.ppc64.xml|  2 ++
 tests/domaincapsdata/qemu_7.0.0.x86_64.xml   |  2 ++
 tests/domaincapsdata/qemu_7.1.0-q35.x86_64.xml   |  2 ++
 tests/domaincapsdata/qemu_7.1.0-tcg.x86_64.xml   |  2 ++
 tests/domaincapsdata/qemu_7.1.0.ppc64.xml|  2 ++
 tests/domaincapsdata/qemu_7.1.0.x86_64.xml   |  2 ++
 tests/domaincapsdata/qemu_7.2.0-hvf.x86_64+hvf.xml   |  2 ++
 tests/domaincapsdata/qemu_7.2.0-q35.x86_64.xml   |  2 ++
 tests/domaincapsdata/qemu_7.2.0-tcg.x86_64+hvf.xml   |  2 ++
 tests/domaincapsdata/qemu_7.2.0-tcg.x86_64.xml   |  2 ++
 tests/domaincapsdata/qemu_7.2.0.ppc.xml  |  2 ++
 tests/domaincapsdata/qemu_7.2.0.x86_64.xml   |  2 ++
 tests/domaincapsdata/qemu_8.0.0-q35.x86_64.xml   |  2 ++
 tests/domaincapsdata/qemu_8.0.0-tcg-virt.riscv64.xml |  2 ++
 tests/domaincapsdata/qemu_8.0.0-tcg.x86_64.xml   |  2 ++
 tests/domaincapsdata/qemu_8.0.0-virt.riscv64.xml |  2 ++
 tests/domaincapsdata/qemu_8.0.0.x86_64.xml   |  2 ++
 tests/domaincapsdata/qemu_8.1.0-q35.x86_64.xml   |  2 ++
 tests/domaincapsdata/qemu_8.1.0-tcg.x86_64.xml   |  2 ++
 tests/domaincapsdata/qemu_8.1.0.x86_64.xml   |  2 ++
 tests/domaincapsdata/qemu_8.2.0-q35.x86_64.xml   |  2 ++
 tests/domaincapsdata/qemu_8.2.0-tcg-virt.loongarch64.xml |  2 ++
 tests/domaincapsdata/qemu_8.2.0-tcg.x86_64.xml   |  2 ++
 tests/domaincapsdata/qemu_8.2.0-virt.aarch64.xml |  2 ++
 tests/domaincapsdata/qemu_8.2.0-virt.loongarch64.xml |  2 ++
 tests/domaincapsdata/qemu_8.2.0.aarch64.xml  |  2 ++
 tests/domaincapsdata/qemu_8.2.0.armv7l.xml   |  2 ++
 tests/domaincapsdata/qemu_8.2.0.s390x.xml|  2 ++
 tests/domaincapsdata/qemu_8.2.0.x86_64.xml   |  2 ++
 tests/domaincapsdata/qemu_9.0.0-q35.x86_64.xml   |  2 ++
 tests/domaincapsdata/qemu_9.0.0-tcg.x86_64.xml   |  2 ++
 tests/domaincapsdata/qemu_9.0.0.x86_64.xml   |  2 ++
 tests/domaincapsdata/qemu_9.1.0-q35.x86_64.xml   |  2 ++
 tests/domaincapsdata/qemu_9.1.0-tcg-virt.riscv64.xml |  2 ++
 tests/domaincapsdata/qemu_9.1.0-tcg.x86_64.xml   |  2 ++
 tests/domaincapsdata/qemu_9.1.0-virt.riscv64.xml |  2 ++
 tests/domaincapsdata/qemu_9.1.0.s390x.xml|  2 ++
 tests/domaincapsdata/qemu_9.1.0.x86_64.xml   |  2 ++
 tests/domaincapsdata/qemu_9.2.0-q35.x86_64.xml   |  2 ++
 tests/domaincapsdata/qemu_9.2.0-tcg.x86_64.xml  

Re: [PATCH RFC] util: pick a better runtime directory when XDG_RUNTIME_DIR isn't set

2025-02-18 Thread Daniel P . Berrangé
On Tue, Feb 18, 2025 at 09:33:43AM -0500, Laine Stump wrote:
> On 2/18/25 4:26 AM, Daniel P. Berrangé wrote:
> > On Mon, Feb 17, 2025 at 03:11:56PM -0500, Laine Stump wrote:
> > > On 2/17/25 5:28 AM, Daniel P. Berrangé wrote:
> > > > On Mon, Feb 17, 2025 at 02:14:49AM -0500, Laine Stump wrote:
> > > > > But sometimes XDG_RUNTIME_DIR isn't set in the user's environment.
> > > > 
> > > > Do you have examples of scenarios in which this happens, and
> > > > yet the /run/user/ directory is still being created, as
> > > > that rather sounds like something is broken outside of libvirt.
> > > 
> > > After seeing the bug report, I replicated the situation by ssh'ing in as a
> > > user that hadn't previously logged in, and then unsetting 
> > > XDG_RUNTIME_DIR. I
> > > hadn't thought there might be some other case where the user could be 
> > > logged
> > > in but XDG_RUNTIME_DIR had never been set.
> > > 
> > > But after seeing your question I tried running
> > > 
> > >sudo $someuser virsh list
> > 
> > NB, that is the classic sudo usage trapdoor, because they didn't
> > make "-i" (aka --login) the default, so your environment is not
> > populated correctly.
> > 
> > I'd hope that when passing sudo -i ... it will do the right
> > thing
> 
> It seems not. If I login as $someuser, start a guest, then in a separate
> terminal window from root run:
> 
>   sudo -u $someuser -i virsh list
> 
> It returns an empty list (the same as if I omit the -i). By running the same
> command without "virsh list", I'm given a shell instance, and within that
> shell I can see that $UID, $USER, and $EUID are all set, but
> $XDG_RUNTIME_DIR is not.

Hmm, this appears to be caused by systemd_pam

When using "su -" (similar seen with sudo)

su[5870]: pam_systemd(su-l:session): pam-systemd initializing
su[5870]: pam_systemd(su-l:session): New sd-bus connection 
(system-bus-pam-systemd-5870) opened.
su[5870]: pam_systemd(su-l:session): Asking logind to create session: uid=1001 
pid=5870 service=su-l type=tty class=user desktop= seat= vtnr=0 tty=pts/3 
display= remote=no remote_user=root remote_host=
su[5870]: pam_systemd(su-l:session): Session limits: memory_max=n/a 
tasks_max=n/a cpu_weight=n/a io_weight=n/a runtime_max_sec=n/a
su[5870]: pam_systemd(su-l:session): Not creating session: Already running in a 
session or user slice
su[5870]: pam_systemd(su-l:session): pam-systemd shutting down

vs used with ssh:

sshd-session[5937]: pam_systemd(sshd:session): pam-systemd initializing
sshd-session[5937]: pam_systemd(sshd:session): New sd-bus connection 
(system-bus-pam-systemd-5937) opened.
sshd-session[5937]: pam_systemd(sshd:session): Asking logind to create session: 
uid=0 pid=5937 service=sshd type=tty class=user desktop= seat= vtnr=0 tty= 
display= remote=yes remote_user= remote_host=10.42.28.158
sshd-session[5937]: pam_systemd(sshd:session): Session limits: memory_max=n/a 
tasks_max=n/a cpu_weight=n/a io_weight=n/a runtime_max_sec=n/a
sshd-session[5937]: pam_systemd(sshd:session): Reply from logind: id=12 
object_path=/org/freedesktop/login1/session/_312 runtime_path=/run/user/0 
session_fd=9 seat= vtnr=0 original_uid=0


So if the current user is already in a login sesssion, it'll refuse to
start a new session.

I struggle to understand the rationale for this behaviour. It seems
guaranteed to break stuff...

With regards,
Daniel
-- 
|: https://berrange.com  -o-https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o-https://fstop138.berrange.com :|
|: https://entangle-photo.org-o-https://www.instagram.com/dberrange :|


Re: [PATCH RFC] util: pick a better runtime directory when XDG_RUNTIME_DIR isn't set

2025-02-18 Thread Daniel P . Berrangé
On Mon, Feb 17, 2025 at 03:11:56PM -0500, Laine Stump wrote:
> On 2/17/25 5:28 AM, Daniel P. Berrangé wrote:
> > On Mon, Feb 17, 2025 at 02:14:49AM -0500, Laine Stump wrote:
> > > But sometimes XDG_RUNTIME_DIR isn't set in the user's environment.
> > 
> > Do you have examples of scenarios in which this happens, and
> > yet the /run/user/ directory is still being created, as
> > that rather sounds like something is broken outside of libvirt.
> 
> After seeing the bug report, I replicated the situation by ssh'ing in as a
> user that hadn't previously logged in, and then unsetting XDG_RUNTIME_DIR. I
> hadn't thought there might be some other case where the user could be logged
> in but XDG_RUNTIME_DIR had never been set.
> 
> But after seeing your question I tried running
> 
>   sudo $someuser virsh list

NB, that is the classic sudo usage trapdoor, because they didn't
make "-i" (aka --login) the default, so your environment is not
populated correctly.

I'd hope that when passing sudo -i ... it will do the right
thing

With regards,
Daniel
-- 
|: https://berrange.com  -o-https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o-https://fstop138.berrange.com :|
|: https://entangle-photo.org-o-https://www.instagram.com/dberrange :|


Plans for 11.1.0 release (freeze on Monday 24 Feb)

2025-02-18 Thread Jiri Denemark
We are getting close to 11.1.0 release of libvirt. To aim for the
release on Monday 03 Mar I suggest entering the freeze on Monday 24
Feb and tagging RC2 on Thursday 27 Feb.

I hope this works for everyone.

Jirka