Re: [PATCH] chardev/char-win-stdio.c: restore old console mode

2024-07-22 Thread Marc-André Lureau
Hi

On Mon, Jul 22, 2024 at 12:01 AM songziming  wrote:

> If I use `-serial stdio` on Windows, after QEMU exits, the terminal
> could not handle arrow keys and tab any more. Because stdio backend
> on Windows sets console mode to virtual terminal input when starts,
> but does not restore the old mode when finalize.
>
> This small patch saves the old console mode and set it back.
>

Thanks, we had a similar patch from Irina Ryapolova, but it didn't save the
old mode and she didn't update it.


> Signed-off-by: Ziming Song 
>

> ---
>  chardev/char-win-stdio.c | 3 +++
>  1 file changed, 3 insertions(+)
>
> diff --git a/chardev/char-win-stdio.c b/chardev/char-win-stdio.c
> index 1a18999..5b24893 100644
> --- a/chardev/char-win-stdio.c
> +++ b/chardev/char-win-stdio.c
> @@ -33,6 +33,7 @@
>  struct WinStdioChardev {
>  Chardev parent;
>  HANDLE  hStdIn;
> +DWORD   dwOldMode;
>  HANDLE  hInputReadyEvent;
>  HANDLE  hInputDoneEvent;
>  HANDLE  hInputThread;
> @@ -159,6 +160,7 @@ static void qemu_chr_open_stdio(Chardev *chr,
>  }
>
>  is_console = GetConsoleMode(stdio->hStdIn, ) != 0;
> +stdio->dwOldMode = dwMode;
>
>  if (is_console) {
>  if (qemu_add_wait_object(stdio->hStdIn,
> @@ -220,6 +222,7 @@ err1:
>  static void char_win_stdio_finalize(Object *obj)
>  {
>  WinStdioChardev *stdio = WIN_STDIO_CHARDEV(obj);
> +SetConsoleMode(stdio->hStdIn, stdio->dwOldMode);
>
>
It should not reset if the open callback was not called successfully.

You can check if it's the case by adding a if (stdio->hStdIn !=
INVALID_HANDLE_VALUE) condition.

 if (stdio->hInputReadyEvent != INVALID_HANDLE_VALUE) {
>  CloseHandle(stdio->hInputReadyEvent);
> --
> 2.45.1.windows.1
>
>
>

-- 
Marc-André Lureau


Re: [PATCH 12/13] dump: make range overlap check more readable

2024-07-22 Thread Marc-André Lureau
On Mon, Jul 22, 2024 at 8:10 AM Yao Xingtao  wrote:

> use ranges_overlap() instead of open-coding the overlap check to improve
> the readability of the code.
>
> Signed-off-by: Yao Xingtao 
>

Reviewed-by: Marc-André Lureau 


> ---
>  dump/dump.c | 12 
>  1 file changed, 8 insertions(+), 4 deletions(-)
>
> diff --git a/dump/dump.c b/dump/dump.c
> index 84064d890d2c..45e84428aea5 100644
> --- a/dump/dump.c
> +++ b/dump/dump.c
> @@ -30,6 +30,7 @@
>  #include "migration/blocker.h"
>  #include "hw/core/cpu.h"
>  #include "win_dump.h"
> +#include "qemu/range.h"
>
>  #include 
>  #ifdef CONFIG_LZO
> @@ -574,8 +575,10 @@ static void get_offset_range(hwaddr phys_addr,
>
>  QTAILQ_FOREACH(block, >guest_phys_blocks.head, next) {
>  if (dump_has_filter(s)) {
> -if (block->target_start >= s->filter_area_begin +
> s->filter_area_length ||
> -block->target_end <= s->filter_area_begin) {
> +if (!ranges_overlap(block->target_start,
> +block->target_end - block->target_start,
> +s->filter_area_begin,
> +s->filter_area_length)) {
>  /* This block is out of the range */
>  continue;
>  }
> @@ -734,8 +737,9 @@ int64_t dump_filtered_memblock_start(GuestPhysBlock
> *block,
>  {
>  if (filter_area_length) {
>  /* return -1 if the block is not within filter area */
> -if (block->target_start >= filter_area_start + filter_area_length
> ||
> -block->target_end <= filter_area_start) {
> +if (!ranges_overlap(block->target_start,
> +block->target_end - block->target_start,
> +filter_area_start, filter_area_length)) {
>  return -1;
>  }
>
> --
> 2.41.0
>
>


Re: [PATCH v2] Cursor: 8 -> 1 bit alpha downsampling improvement

2024-07-17 Thread Marc-André Lureau
Hi

On Wed, Jul 17, 2024 at 5:11 PM Phil Dennis-Jordan 
wrote:

>
> Mouse cursors with 8 bit alpha were downsampled to 1-bit opacity maps by
>>> turning alpha values of 255 into 1 and everything else into 0. This
>>> means that mostly-opaque pixels ended up completely invisible.
>>>
>>> This patch changes the behaviour so that only pixels with less than 50%
>>> alpha (0-127) are treated as transparent when converted to 1-bit alpha.
>>>
>>> This greatly improves the subjective appearance of anti-aliased mouse
>>> cursors, such as those used by macOS, when using a front-end UI without
>>> support for alpha-blended cursors, such as some VNC clients.
>>>
>>> Signed-off-by: Phil Dennis-Jordan 
>>>
>>
>> Reviewed-by: Marc-André Lureau 
>>
>
> Reviewed-by: Akihiko Odaki 
>
>
> Thanks for the reviews folks! Is there anything I can do to move this
> forward? Should I submit a v3 with the review tags included? The patch
> continues to apply cleanly so it didn't seem necessary, but I admit I'm
> still not 100% clear on whom I should badger (?) to get favourably received
> patches actually pulled into staging/master.
>
> https://patchew.org/QEMU/20240624101040.82726-1-p...@philjordan.eu/
>
>
I'll include it in a UI-related PR.

thanks

-- 
Marc-André Lureau


Re: [PATCH v2 0/4] net: update netdev stream/dgram man page

2024-07-15 Thread Marc-André Lureau
On Thu, Jul 4, 2024 at 4:48 PM Laurent Vivier  wrote:

> Add the description of "-netdev stream" and "-netdev dgram" in the QEMU
> manpage.
>
> Add some examples on how to use them, including a way to use
> "-netdev stream" and "passt" in place of "-netdev user".
> ("passt" is a non privileged translation proxy between layer-2,
> like "-netdev stream", and layer-4 on host, like TCP, UDP,
> ICMP/ICMPv6 echo)
>
> v2:
>   - split patch
>   - update unix socket description with stream and datagram words.
>
> Laurent Vivier (4):
>   net: update netdev stream/dgram man page
>   net: update netdev stream man page with unix socket
>   net: update netdev dgram man page with unix socket
>   net: update netdev stream man page with the reconnect parameter
>
>  qemu-options.hx | 189 ++++++++
>  1 file changed, 189 insertions(+)
>

Series:
Reviewed-by: Marc-André Lureau 

-- 
Marc-André Lureau


Re: [PATCH] hw/vmcoreinfo: make guest format endian safe

2024-07-12 Thread Marc-André Lureau
Hi

On Fri, Jul 12, 2024 at 10:25 AM Ani Sinha  wrote:
>
> Guest and host formats in struct FWCfgVMCoreInfo are written in little endian
> format. However, the hypervisor host might be big endian. We need to do
> appropriate conversions between the formats before comparing the values. Fix 
> it.
>

Looks right, but that shouldn't matter since the comparison is with 0.

Reviewed-by: Marc-André Lureau 

> Signed-off-by: Ani Sinha 
> ---
>  hw/misc/vmcoreinfo.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/hw/misc/vmcoreinfo.c b/hw/misc/vmcoreinfo.c
> index 833773ade5..e00df95e29 100644
> --- a/hw/misc/vmcoreinfo.c
> +++ b/hw/misc/vmcoreinfo.c
> @@ -21,9 +21,10 @@
>  static void fw_cfg_vmci_write(void *dev, off_t offset, size_t len)
>  {
>  VMCoreInfoState *s = VMCOREINFO(dev);
> +uint16_t guest_format = le16_to_cpu(s->vmcoreinfo.guest_format);
>
>  s->has_vmcoreinfo = offset == 0 && len == sizeof(s->vmcoreinfo)
> -&& s->vmcoreinfo.guest_format != FW_CFG_VMCOREINFO_FORMAT_NONE;
> +&& guest_format != FW_CFG_VMCOREINFO_FORMAT_NONE;
>  }
>
>  static void vmcoreinfo_reset(void *dev)
> --
> 2.42.0
>




Re: [PATCH] char-mux: Don't overwrite the receive buffer

2024-07-09 Thread Marc-André Lureau
Hi

On Tue, Jul 9, 2024 at 6:41 PM Ruihan Li  wrote:

> Hi,
>
> On Mon, Jul 08, 2024 at 03:21:58PM GMT, Marc-André Lureau wrote:
> > Hi
> >
> > On Mon, Jul 8, 2024 at 12:12 AM Ruihan Li  wrote:
> >
> > > Hi,
> > >
> > > Thanks for your quick review!
> > >
> > > On Sun, Jul 07, 2024 at 08:28:50PM GMT, Marc-André Lureau wrote:
> > > > Hi
> > > >
> > > > On Sun, Jul 7, 2024 at 3:26 PM Ruihan Li  wrote:
> > > >
> > > > > This commit fixes a bug that causes incorrect results when pasting
> more
> > > > > than 32 bytes, the size of the receive buffer b->buffer, into the
> > > virtio
> > > > > console.
> > > > >
> > > > > Example (note that the last 32 bytes are always correct, but
> something
> > > > > goes wrong just before the last 32 bytes):
> > > > >
> > > > > Pasting
> > > > >
> > >
> abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()
> > > > > Received
> > > > >
> > >
> abcdefg)EFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()EFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()
> > > > >
> > > > > The root cause of this bug is as follows:
> > > > >
> > > > > The mux_chr_read function passes the data to the backend via
> > > > > be->chr_read one byte at a time, either directly or via another
> > > > > mux_chr_accept_input method. However, if the receive buffer is
> full,
> > > > > there is a chance that the mux_chr_can_read method will return more
> > > than
> > > > > one byte, because in this case the method directly returns whatever
> > > > > be->chr_can_read returns.
> > > > >
> > > > > This is problematic because if mux_chr_read passes a byte to the
> > > backend
> > > > > by calling be->chr_read, it will consume the entire backend
> buffer, at
> > > > > least in the case of virtio. Once all backend buffers are used,
> > > > > mux_chr_read writes all remaining bytes to the receive buffer
> > > d->buffer,
> > > > >
> > > >
> > > > My understanding of the code execution is:
> > > > - mux_chr_can_read() returns be->chr_can_read(), say N, because
> d->buffer
> > > > is already MUX_BUFFER_SIZE.
> > > > - mux_chr_read() is called with N bytes
> > > > - mux_chr_accept_input() flushes d->buffer, writing MUX_BUFFER_SIZE
> > > > - be should still accept N-MUX_BUFFER_SIZE
> > > > - mux_proc_byte() loops for N bytes
> > > > - chr_read() should accept the N-MUX_BUFFER_SIZE
> > > > - d->buffer is then filled with the remaining MUX_BUFFER_SIZE
> > >
> > > Note this:
> > > [..] if mux_chr_read passes a byte to the backend by calling
> > > be->chr_read, it will consume the entire backend buffer, at
> > > least in the case of virtio [..]
> > >
> > > At least in the case of virtio, if the guest provides a buffer of
> length
> > > 4096, be->chr_can_read will report 4096. But if you then call
> > > be->chr_read with one byte, the whole 4096 buffer will be used. After
> > > that, be->chr_can_read will return zero instead of 4095.
> > >
> > > This should make sense since the device cannot change the number of
> > > bytes in the buffer after it has made the buffer available to the CPU.
> > >
> >
> > Thanks, that helps explaining the incorrect behaviour.
> >
> > I think the concept of extra buffer as introduced in commit
> > bd9bdce694ccb76facc882363e4c337e8a88c918 ("Add input buffer to mux chr
> > (patch by Tristan Gingold)") is flawed, as Jan Kiszka explained in commit
> > a80bf99fa3dd829ecea88b9bfb4f7cf146208f07 ("char-mux: Use separate input
> > buffers (Jan Kiszka)"):
> > Note: In contrast to the original author's claim, the buffering
> concept
> > still breaks down when the fifo of the currently active sub-device is
> > full. As we cannot accept futher data from this point on without
> risking
> > to loose it, we will also miss escape sequences, just like without
> all
> > that buffering. In short: There is no reliable escape sequence
> handling
> > without infinite buffers or the risk of loosing some data.
> >
> > Maybe the best course is to remove the cycle buffer a

Re: [PATCH] char-mux: Don't overwrite the receive buffer

2024-07-08 Thread Marc-André Lureau
Hi

On Mon, Jul 8, 2024 at 12:12 AM Ruihan Li  wrote:

> Hi,
>
> Thanks for your quick review!
>
> On Sun, Jul 07, 2024 at 08:28:50PM GMT, Marc-André Lureau wrote:
> > Hi
> >
> > On Sun, Jul 7, 2024 at 3:26 PM Ruihan Li  wrote:
> >
> > > This commit fixes a bug that causes incorrect results when pasting more
> > > than 32 bytes, the size of the receive buffer b->buffer, into the
> virtio
> > > console.
> > >
> > > Example (note that the last 32 bytes are always correct, but something
> > > goes wrong just before the last 32 bytes):
> > >
> > > Pasting
> > >
> abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()
> > > Received
> > >
> abcdefg)EFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()EFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()
> > >
> > > The root cause of this bug is as follows:
> > >
> > > The mux_chr_read function passes the data to the backend via
> > > be->chr_read one byte at a time, either directly or via another
> > > mux_chr_accept_input method. However, if the receive buffer is full,
> > > there is a chance that the mux_chr_can_read method will return more
> than
> > > one byte, because in this case the method directly returns whatever
> > > be->chr_can_read returns.
> > >
> > > This is problematic because if mux_chr_read passes a byte to the
> backend
> > > by calling be->chr_read, it will consume the entire backend buffer, at
> > > least in the case of virtio. Once all backend buffers are used,
> > > mux_chr_read writes all remaining bytes to the receive buffer
> d->buffer,
> > >
> >
> > My understanding of the code execution is:
> > - mux_chr_can_read() returns be->chr_can_read(), say N, because d->buffer
> > is already MUX_BUFFER_SIZE.
> > - mux_chr_read() is called with N bytes
> > - mux_chr_accept_input() flushes d->buffer, writing MUX_BUFFER_SIZE
> > - be should still accept N-MUX_BUFFER_SIZE
> > - mux_proc_byte() loops for N bytes
> > - chr_read() should accept the N-MUX_BUFFER_SIZE
> > - d->buffer is then filled with the remaining MUX_BUFFER_SIZE
>
> Note this:
> [..] if mux_chr_read passes a byte to the backend by calling
> be->chr_read, it will consume the entire backend buffer, at
> least in the case of virtio [..]
>
> At least in the case of virtio, if the guest provides a buffer of length
> 4096, be->chr_can_read will report 4096. But if you then call
> be->chr_read with one byte, the whole 4096 buffer will be used. After
> that, be->chr_can_read will return zero instead of 4095.
>
> This should make sense since the device cannot change the number of
> bytes in the buffer after it has made the buffer available to the CPU.
>

Thanks, that helps explaining the incorrect behaviour.

I think the concept of extra buffer as introduced in commit
bd9bdce694ccb76facc882363e4c337e8a88c918 ("Add input buffer to mux chr
(patch by Tristan Gingold)") is flawed, as Jan Kiszka explained in commit
a80bf99fa3dd829ecea88b9bfb4f7cf146208f07 ("char-mux: Use separate input
buffers (Jan Kiszka)"):
Note: In contrast to the original author's claim, the buffering concept
still breaks down when the fifo of the currently active sub-device is
full. As we cannot accept futher data from this point on without risking
to loose it, we will also miss escape sequences, just like without all
that buffering. In short: There is no reliable escape sequence handling
without infinite buffers or the risk of loosing some data.

Maybe the best course is to remove the cycle buffer and either:
- drop the data that be can't accept, but have always responsive mux (by
default)
- blocking, including mux, until the be can accept more data (not friendly)
- or allow unlimited buffering?

Given that mux is meant for developers and qemu CLI users, I guess any of
this would be acceptable.


>
> >
> >
> > > but the number of remaining bytes can be larger than the buffer size.
> > >
> >
> > By the above description, I don't see how it happens.
> >
> > This does not lead to security problems since it is a ring buffer, but
> > > it does mess up the receive data.
> > >
> > > This can be fixed by having mux_chr_can_read return either zero or one.
> > > This fix is not very efficient, but it is quite reasonable since
> > > mux_chr_read also passes the data to the backend one byte at a time.
> > >
> >
> > Could you share your testing setup? Even better if you could write a
> test!
>
> This happens

Re: [PATCH] char-mux: Don't overwrite the receive buffer

2024-07-07 Thread Marc-André Lureau
Hi

On Sun, Jul 7, 2024 at 3:26 PM Ruihan Li  wrote:

> This commit fixes a bug that causes incorrect results when pasting more
> than 32 bytes, the size of the receive buffer b->buffer, into the virtio
> console.
>
> Example (note that the last 32 bytes are always correct, but something
> goes wrong just before the last 32 bytes):
>
> Pasting
> abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()
> Received
> abcdefg)EFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()EFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()
>
> The root cause of this bug is as follows:
>
> The mux_chr_read function passes the data to the backend via
> be->chr_read one byte at a time, either directly or via another
> mux_chr_accept_input method. However, if the receive buffer is full,
> there is a chance that the mux_chr_can_read method will return more than
> one byte, because in this case the method directly returns whatever
> be->chr_can_read returns.
>
> This is problematic because if mux_chr_read passes a byte to the backend
> by calling be->chr_read, it will consume the entire backend buffer, at
> least in the case of virtio. Once all backend buffers are used,
> mux_chr_read writes all remaining bytes to the receive buffer d->buffer,
>

My understanding of the code execution is:
- mux_chr_can_read() returns be->chr_can_read(), say N, because d->buffer
is already MUX_BUFFER_SIZE.
- mux_chr_read() is called with N bytes
- mux_chr_accept_input() flushes d->buffer, writing MUX_BUFFER_SIZE
- be should still accept N-MUX_BUFFER_SIZE
- mux_proc_byte() loops for N bytes
- chr_read() should accept the N-MUX_BUFFER_SIZE
- d->buffer is then filled with the remaining MUX_BUFFER_SIZE


> but the number of remaining bytes can be larger than the buffer size.
>

By the above description, I don't see how it happens.

This does not lead to security problems since it is a ring buffer, but
> it does mess up the receive data.
>
> This can be fixed by having mux_chr_can_read return either zero or one.
> This fix is not very efficient, but it is quite reasonable since
> mux_chr_read also passes the data to the backend one byte at a time.
>

Could you share your testing setup? Even better if you could write a test!


thanks


> Signed-off-by: Ruihan Li 
> ---
>  chardev/char-mux.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/chardev/char-mux.c b/chardev/char-mux.c
> index ee2d47b..5c6eea2 100644
> --- a/chardev/char-mux.c
> +++ b/chardev/char-mux.c
> @@ -210,8 +210,8 @@ static int mux_chr_can_read(void *opaque)
>  return 1;
>  }
>
> -if (be && be->chr_can_read) {
> -    return be->chr_can_read(be->opaque);
> +if (be && be->chr_can_read && be->chr_can_read(be->opaque)) {
> +return 1;
>  }
>
>  return 0;
> --
> 2.45.2
>
>
>

-- 
Marc-André Lureau


Re: [PATCH 03/14] rust: define traits and pointer wrappers to convert from/to C representations

2024-07-03 Thread Marc-André Lureau
Hi

On Wed, Jul 3, 2024 at 4:48 PM Marc-André Lureau 
wrote:

> Hi
>
> (adding Sebastian, one of the glib-rs developers in CC)
>
> On Mon, Jul 1, 2024 at 7:02 PM Paolo Bonzini  wrote:
>
>> The qemu::util::foreign module provides:
>>
>> - A trait for structs that can be converted to a C ("foreign")
>> representation
>>   (CloneToForeign)
>>
>> - A trait for structs that can be built from a C ("foreign")
>> representation
>>   (FromForeign), and the utility IntoNative that can be used with less
>> typing
>>   (similar to the standard library's From and Into pair)
>>
>> - Automatic implementations of the above traits for Option<>, supporting
>> NULL
>>   pointers
>>
>> - A wrapper for a pointer that automatically frees the contained data.  If
>>   a struct XYZ implements CloneToForeign, you can build an
>> OwnedPointer
>>   and it will free the contents automatically unless you retrieve it with
>>   owned_ptr.into_inner()
>>
>
> [...] Also, you don't offer the equivalent of "to_glib_none" which uses a
> temporary stash and is quite useful, as a majority of functions don't take
> ownership.
>

I realize this may be somewhat offered by OwnedPointer (although not
mentioned explicitly in the doc). Its usage seems unsafe, as you have to
handle the foreign pointer lifetime manually...


-- 
Marc-André Lureau


Re: [PATCH 03/14] rust: define traits and pointer wrappers to convert from/to C representations

2024-07-03 Thread Marc-André Lureau
 +
> +/// Return the pointer that is stored in the `OwnedPointer`.  The
> +/// pointer is valid for as long as the `OwnedPointer` itself.
> +pub fn as_ptr() -> *const ::Foreign {
> +self.ptr
> +}
> +
> +pub fn as_mut_ptr() -> *mut ::Foreign {
> +self.ptr
> +}
> +
> +/// Return the pointer that is stored in the `OwnedPointer`,
> +/// consuming the `OwnedPointer` but not freeing the pointer.
> +pub fn into_inner(mut self) -> *mut ::Foreign {
> +let result = mem::replace( self.ptr, ptr::null_mut());
> +mem::forget(self);
> +result
> +}
> +}
> +
> +impl OwnedPointer {
> +/// Convert a C datum to a native Rust object, taking ownership of
> +/// the pointer or Rust object (same as `from_glib_full` in `glib-rs`)
> +pub fn into_native(self) -> T {
> +// SAFETY: the pointer was passed to the unsafe constructor
> OwnedPointer::new
> +unsafe { T::from_foreign(self.into_inner()) }
> +}
> +}
> +
> +impl Debug for OwnedPointer {
> +fn fmt(, f:  fmt::Formatter<'_>) -> fmt::Result {
> +let name = std::any::type_name::();
> +let name = format!("OwnedPointer<{}>", name);
> +f.debug_tuple().field(_ptr()).finish()
> +}
> +}
> +
> +impl Default for OwnedPointer {
> +fn default() -> Self {
> +::default().clone_to_foreign()
> +}
> +}
> +
> +impl Drop for OwnedPointer {
> +fn drop( self) {
> +let p = mem::replace( self.ptr, ptr::null_mut());
> +// SAFETY: the pointer was passed to the unsafe constructor
> OwnedPointer::new
> +unsafe { T::free_foreign(p) }
> +}
> +}
> diff --git a/qemu/src/util/mod.rs b/qemu/src/util/mod.rs
> new file mode 100644
> index 000..be00d0c
> --- /dev/null
> +++ b/qemu/src/util/mod.rs
> @@ -0,0 +1 @@
> +pub mod foreign;
> --
> 2.45.2
>
>
>

-- 
Marc-André Lureau


Re: [PATCH 1/2] ui/egl-helpers: Consolidate create-sync and create-fence

2024-07-03 Thread Marc-André Lureau
Hi

On Wed, Jul 3, 2024 at 12:57 AM  wrote:

> From: Dongwon Kim 
>
> There is no reason to split those two operations so combining
> two functions - egl_dmabuf_create_sync and egl_dmabuf_create_fence.
>
> v2: egl_dmabuf_create_fence -> egl_dmabuf_create_fence_fd
> (Marc-André Lureau )
>
> Cc: Gerd Hoffmann 
> Cc: Marc-André Lureau 
> Cc: Vivek Kasireddy 
> Signed-off-by: Dongwon Kim 
> ---
>  include/ui/egl-helpers.h |  3 +--
>  ui/egl-helpers.c | 27 +++
>  ui/gtk-egl.c | 15 +++
>  ui/gtk-gl-area.c | 10 ++
>  4 files changed, 17 insertions(+), 38 deletions(-)
>
> diff --git a/include/ui/egl-helpers.h b/include/ui/egl-helpers.h
> index 4b8c0d2281..221548e3c9 100644
> --- a/include/ui/egl-helpers.h
> +++ b/include/ui/egl-helpers.h
> @@ -51,8 +51,7 @@ int egl_get_fd_for_texture(uint32_t tex_id, EGLint
> *stride, EGLint *fourcc,
>
>  void egl_dmabuf_import_texture(QemuDmaBuf *dmabuf);
>  void egl_dmabuf_release_texture(QemuDmaBuf *dmabuf);
> -void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf);
> -void egl_dmabuf_create_fence(QemuDmaBuf *dmabuf);
> +int egl_dmabuf_create_fence_fd(QemuDmaBuf *dmabuf);
>
>  #endif
>
> diff --git a/ui/egl-helpers.c b/ui/egl-helpers.c
> index 99b2ebbe23..ddbf52bf5f 100644
> --- a/ui/egl-helpers.c
> +++ b/ui/egl-helpers.c
> @@ -371,34 +371,29 @@ void egl_dmabuf_release_texture(QemuDmaBuf *dmabuf)
>  qemu_dmabuf_set_texture(dmabuf, 0);
>  }
>
> -void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf)
> +int egl_dmabuf_create_fence_fd(QemuDmaBuf *dmabuf)
>  {
>  EGLSyncKHR sync;
> +int fence_fd = -1;
>
>  if (epoxy_has_egl_extension(qemu_egl_display,
>  "EGL_KHR_fence_sync") &&
>  epoxy_has_egl_extension(qemu_egl_display,
> -"EGL_ANDROID_native_fence_sync")) {
> +"EGL_ANDROID_native_fence_sync") &&
> +qemu_dmabuf_get_fence_fd(dmabuf) == -1) {
>  sync = eglCreateSyncKHR(qemu_egl_display,
>  EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
>  if (sync != EGL_NO_SYNC_KHR) {
> -qemu_dmabuf_set_sync(dmabuf, sync);
> +fence_fd = eglDupNativeFenceFDANDROID(qemu_egl_display,
> +  sync);
> +if (fence_fd >= 0) {
> +qemu_dmabuf_set_fence_fd(dmabuf, fence_fd);
> +}
> +eglDestroySyncKHR(qemu_egl_display, sync);
>  }
>  }
> -}
> -
> -void egl_dmabuf_create_fence(QemuDmaBuf *dmabuf)
> -{
> -void *sync = qemu_dmabuf_get_sync(dmabuf);
> -int fence_fd;
>
> -if (sync) {
> -fence_fd = eglDupNativeFenceFDANDROID(qemu_egl_display,
> -  sync);
> -qemu_dmabuf_set_fence_fd(dmabuf, fence_fd);
> -eglDestroySyncKHR(qemu_egl_display, sync);
> -qemu_dmabuf_set_sync(dmabuf, NULL);
> -}
> +return fence_fd;
>  }
>
>  #endif /* CONFIG_GBM */
> diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c
> index 9831c10e1b..8869cdee4f 100644
> --- a/ui/gtk-egl.c
> +++ b/ui/gtk-egl.c
> @@ -68,7 +68,6 @@ void gd_egl_draw(VirtualConsole *vc)
>  GdkWindow *window;
>  #ifdef CONFIG_GBM
>  QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf;
> -int fence_fd;
>  #endif
>  int ww, wh, ws;
>
> @@ -99,13 +98,12 @@ void gd_egl_draw(VirtualConsole *vc)
>  glFlush();
>  #ifdef CONFIG_GBM
>  if (dmabuf) {
> -egl_dmabuf_create_fence(dmabuf);
> -fence_fd = qemu_dmabuf_get_fence_fd(dmabuf);
> +int fence_fd = egl_dmabuf_create_fence_fd(dmabuf);
>  if (fence_fd >= 0) {
>  qemu_set_fd_handler(fence_fd, gd_hw_gl_flushed, NULL, vc);
> -return;
> +} else {
> +graphic_hw_gl_block(vc->gfx.dcl.con, false);
>  }
>

If gd_egl_draw()/gd_egl_refresh() is called multiple times before the
flushed callback, create_fence_fd() is going to return -1 and unblock the
hw. This is probably not desired. I think you need to comment on the code
to explain the interaction between dmabuf_get_draw_submitted,
gd_egl_flush(), fences and hw_block, I can't make sense of it.

thanks


> -graphic_hw_gl_block(vc->gfx.dcl.con, false);
>  }
>  #endif
>  } else {
> @@ -364,12 +362,6 @@ void gd_egl_scanout_flush(DisplayChangeListener *dcl,
>  egl_fb_blit(>gfx.win_fb, >gfx.guest_fb, !vc->gfx.y0_top);
>  }
>
> -#ifdef CONFIG_GBM
> -if

Re: [PATCH v2 00/22] qga: clean up command source locations and conditionals

2024-07-03 Thread Marc-André Lureau
Hi

On Wed, Jul 3, 2024 at 12:06 PM Daniel P. Berrangé  wrote:
>
> On Wed, Jul 03, 2024 at 10:15:44AM +0400, Marc-André Lureau wrote:
> > Hi Daniel
> >
> > On Tue, Jul 2, 2024 at 10:00 PM Daniel P. Berrangé  
> > wrote:
> > >
> > > Ping: for any review comments from QGA maintainers ?
> >
> > Maybe you could resend for patchew to correctly handle the series.
>
> I don't want to spam the list again just because patchew didn't
> handle it. If anyone can't just pull the messages from mail
> though, they are also at 
> https://gitlab.com/berrange/qemu/-/tags/qga-conditions-v2

patchew also handles R-b/A-b/T-b tags, mail ref, versioning etc..




Re: [RFC PATCH 0/4] hw/display/virtio-gpu: Introducing asynchronous guest display render

2024-07-03 Thread Marc-André Lureau
Hi

On Tue, Jul 2, 2024 at 10:11 PM Kim, Dongwon  wrote:

> Hi Marc-André,
>
> On 7/2/2024 3:29 AM, Marc-André Lureau wrote:
> > Hi
> >
> > On Fri, Jun 21, 2024 at 3:20 AM  > <mailto:dongwon@intel.com>> wrote:
> >
> > From: Dongwon Kim  dongwon@intel.com>>
> >
> > Introducing new virtio-gpu param, 'render_sync' when guest scanout
> blob
> > is used (blob=true). The new param is used to specify when to start
> > rendering a guest scanout frame.
> >
> > By default (and so far) rendering of the guest frame is started in
> > the draw event to make sure guest display update is sychronized with
> > host's vsync. But this method inevitably brings some extra wait
> because
> > most of time, the draw event is not happening right after the guest
> > scanout frame is flushed.
> >
> >
> > This delay often makes the guest stuck at certain frame for too long
> and
> > causes general performance degradation of graphic workloads on the
> > guest's
> > side especially when the display update rate is high. This unwanted
> perf
> > drop can be reduced if the guest scanout frame is rendered as soon
> > as it is
> > flushed through 'VIRTIO_GPU_CMD_RESOURCE_FLUSH' msg. The gl display
> > pipeline can be unblocked a lot earlier in this case so that guest
> can
> > move to the next display frame right away.
> >
> > However, this "asynchrounous" render mode may cause some waste of
> > resources
> > as the guest could produce more frames than what are actually
> displayed
> > on the host display. This is similar as running rendering apps with
> > no vblank
> > or vsync option. This is why this feature should stay as optional.
> >
> >
> > Indeed, I don't see much point in doing so, it's pure waste. If you want
> > to benchmark something perhaps. But then, why not simply run a benchmark
> > offscreen?
>
> Benchmark score is not the primary reason. The problem we want to avoid
> is the laggy display update due to too many asynchronous plane updates
> happening in the guest in certain situations like when moving SW mouse
> cursor rigorously on the guest. This is because the fence (as well as
> response for the resource-flush cmd) is signaled in the draw event.
>
>
Presumably, you won't get more frames displayed (perhaps even less due to
extra load), so why is it laggy? Is it because the guest is doing too much
buffering? Because the mouse event queue isn't being drained between
scanouts?


> >
> >
> > The param 'render_sync' is set to 'true' by default and this is in
> line
> > with traditional way while setting it to 'false' is basically
> enabling
> > this asynchronouse mode.
> >
> >
> > As it stands now, the option should actually be on the display backend
> > (gtk/gtk-egl), it's not implemented for other backends.
>
> We can help to deploy this concept to other backends if needed.
>

Why not make it a gtk display option instead?


> >
> > I am not convinced this is generally useful to be an extra option though.
>
> I initially thought this should be the default because the virtio-gpu
> guest should not be hold by the host for too long in any cases. And this
> new approach is comparable to the default mode with blob=false where the
> guest is released as soon as the resource flush is done. Only difference
> is the resource synchronization using the fence.
>

virgl should be blocking rendering too

Could you detail your testing setup ?

thanks


> >
> > Dongwon Kim (4):
> >hw/display/virtio-gpu: Introducing render_sync param
> >ui/egl-helpers: Consolidates create-sync and create-fence
> >ui/gtk-egl: Start rendering of guest blob scanout if render_sync
> is
> >  off
> >ui/gtk-gl-draw: Start rendering of guest blob scanout if
> render_sync
> >  is off
> >
> >   include/hw/virtio/virtio-gpu.h  |  3 ++
> >   include/ui/dmabuf.h |  4 +-
> >   include/ui/egl-helpers.h|  3 +-
> >   hw/display/vhost-user-gpu.c |  3 +-
> >   hw/display/virtio-gpu-udmabuf.c |  3 +-
> >   hw/display/virtio-gpu.c |  2 +
> >   hw/vfio/display.c   |  3 +-
> >   ui/dbus-listener.c  |  2 +-
> >   ui/dmabuf.c | 11 +++-
> >   ui/egl-helpers.c| 27 --
> >   ui/gtk-egl.c| 93
> ++---
> >   ui/gtk-gl-area.c| 90
> +++
> >   12 files changed, 146 insertions(+), 98 deletions(-)
> >
> > --
> > 2.34.1
> >
> >
> >
> >
> > --
> > Marc-André Lureau
>
>

-- 
Marc-André Lureau


Re: [PATCH v2 00/22] qga: clean up command source locations and conditionals

2024-07-03 Thread Marc-André Lureau
Hi Daniel

On Tue, Jul 2, 2024 at 10:00 PM Daniel P. Berrangé  wrote:
>
> Ping: for any review comments from QGA maintainers ?

Maybe you could resend for patchew to correctly handle the series.

thanks

>
> On Thu, Jun 13, 2024 at 04:01:05PM +0100, Daniel P. Berrangé wrote:
> > This series is a side effect of other work I started, to attempt to
> > make the QGA safe to use in confidential VMs by automatically
> > restricting the permitted commands. Since this cleanup stands on
> > its own, I'm sending it now.
> >
> > The QGA codebase has a very complicated maze of #ifdefs to create
> > stubs for the various commands that cannot be implemented on certain
> > platforms. It then has further logic to dynamically disable the stub
> > commands at runtime, except this is not consistently applied, so
> > some commands remain enabled despite being merely stubs.
> >
> > The resulting code is hard to follow, when trying to understand exactly
> > what commands are available under what circumstances, and when changing
> > impls it is easy to get the #ifdefs wrong, resulting in stubs getting
> > missed on platforms without a real impl. In some cases, we have multiple
> > stubs for the same command, due to the maze of #ifdefs.
> >
> > The QAPI schema language has support for many years for expressing
> > conditions against commands when declaring them. This results in the
> > QAPI code generator omitting their implementation entirely at build
> > time. This has mutliple benefits
> >
> >  * The unsupported commands are guaranteed to not exist at runtime
> >  * No stubs need ever be defined in the code
> >  * The generated QAPI reference manual documents the build conditions
> >
> > This series is broadly split into three parts
> >
> >  * Moving tonnes of Linux only commands out of commands-posix.c
> >into commands-linux.c to remove many #ifdefs.
> >  * Adding 'if' conditions in the QAPI schema to reflect the
> >build conditions, removing many more #ifdefs
> >  * Sanitizing the logic for disabling/enabling commands at
> >runtime to guarantee consistency
> >
> > Changed in v2:
> >
> >  - Make FSFreeze error reporting distinguish inability to enable
> >VSS from user config choice
> >
> >  - Fully remove ga_command_init_blockedrpcs() methods. No more
> >special case disabling of commands. Either they're disabled
> >at build time, or disabled by user config, or by well defined
> >rule ie not permitted during FS freeze.
> >
> >  - Apply rules later in startup to avoid crash from NULL config
> >pointer
> >
> >  - Document changed error messages in commit messages
> >
> >  - Add -c / --config command line parameter
> >
> >  - Fix mistaken enabling of fsfreeze hooks on win32
> >
> >  - Remove pointless 'blockrpcs_key' variable
> >
> >  - Allow concurrent setting of allow and block lists for
> >RPC commands
> >
> > Daniel P. Berrangé (22):
> >   qga: drop blocking of guest-get-memory-block-size command
> >   qga: move linux vcpu command impls to commands-linux.c
> >   qga: move linux suspend command impls to commands-linux.c
> >   qga: move linux fs/disk command impls to commands-linux.c
> >   qga: move linux disk/cpu stats command impls to commands-linux.c
> >   qga: move linux memory block command impls to commands-linux.c
> >   qga: move CONFIG_FSFREEZE/TRIM to be meson defined options
> >   qga: conditionalize schema for commands unsupported on Windows
> >   qga: conditionalize schema for commands unsupported on non-Linux POSIX
> >   qga: conditionalize schema for commands requiring getifaddrs
> >   qga: conditionalize schema for commands requiring linux/win32
> >   qga: conditionalize schema for commands only supported on Windows
> >   qga: conditionalize schema for commands requiring fsfreeze
> >   qga: conditionalize schema for commands requiring fstrim
> >   qga: conditionalize schema for commands requiring libudev
> >   qga: conditionalize schema for commands requiring utmpx
> >   qga: conditionalize schema for commands not supported on other UNIX
> >   qga: don't disable fsfreeze commands if vss_init fails
> >   qga: move declare of QGAConfig struct to top of file
> >   qga: remove pointless 'blockrpcs_key' variable
> >   qga: allow configuration file path via the cli
> >   qga: centralize logic for disabling/enabling commands
> >
> >  docs/interop/qemu-ga.rst |   19 +
> >  meson.build  |   16 +
> >  qga/commands-bsd.c   |   24 -
> >  qga/commands-common.h|9 -
> >  qga/commands-linux.c | 1805 +
> >  qga/commands-posix.c | 2373 +++---
> >  qga/commands-win32.c |   78 +-
> >  qga/main.c   |  216 ++--
> >  qga/qapi-schema.json |  153 ++-
> >  9 files changed, 2234 insertions(+), 2459 deletions(-)
> >
> > --
> > 2.45.1
> >
>
> With regards,
> Daniel
> --
> |: https://berrange.com  -o-https://www.flickr.com/photos/dberrange :|
> |: https://libvirt.org -o-  

Re: [PATCH v2 1/2] vfio/display: Fix potential memleak of edid info

2024-07-02 Thread Marc-André Lureau
On Mon, Jul 1, 2024 at 5:51 AM Zhenzhong Duan 
wrote:

> EDID related device region info is leaked in vfio_display_edid_init()
> error path and VFIODisplay destroying path.
>
> Fixes: 08479114b0de ("vfio/display: add edid support.")
> Signed-off-by: Zhenzhong Duan 
>

Reviewed-by: Marc-André Lureau 


> ---
>  hw/vfio/display.c | 3 +++
>  1 file changed, 3 insertions(+)
>
> diff --git a/hw/vfio/display.c b/hw/vfio/display.c
> index 661e921616..9c57fd3888 100644
> --- a/hw/vfio/display.c
> +++ b/hw/vfio/display.c
> @@ -171,7 +171,9 @@ static void vfio_display_edid_init(VFIOPCIDevice *vdev)
>
>  err:
>  trace_vfio_display_edid_write_error();
> +g_free(dpy->edid_info);
>  g_free(dpy->edid_regs);
> +dpy->edid_info = NULL;
>  dpy->edid_regs = NULL;
>  return;
>  }
> @@ -182,6 +184,7 @@ static void vfio_display_edid_exit(VFIODisplay *dpy)
>  return;
>  }
>
> +g_free(dpy->edid_info);
>  g_free(dpy->edid_regs);
>  g_free(dpy->edid_blob);
>  timer_free(dpy->edid_link_timer);
> --
> 2.34.1
>
>
>

-- 
Marc-André Lureau


Re: [RFC PATCH 0/4] hw/display/virtio-gpu: Introducing asynchronous guest display render

2024-07-02 Thread Marc-André Lureau
Hi

On Fri, Jun 21, 2024 at 3:20 AM  wrote:

> From: Dongwon Kim 
>
> Introducing new virtio-gpu param, 'render_sync' when guest scanout blob
> is used (blob=true). The new param is used to specify when to start
> rendering a guest scanout frame.
>
> By default (and so far) rendering of the guest frame is started in
> the draw event to make sure guest display update is sychronized with
> host's vsync. But this method inevitably brings some extra wait because
> most of time, the draw event is not happening right after the guest
> scanout frame is flushed.
>

> This delay often makes the guest stuck at certain frame for too long and
> causes general performance degradation of graphic workloads on the guest's
> side especially when the display update rate is high. This unwanted perf
> drop can be reduced if the guest scanout frame is rendered as soon as it is
> flushed through 'VIRTIO_GPU_CMD_RESOURCE_FLUSH' msg. The gl display
> pipeline can be unblocked a lot earlier in this case so that guest can
> move to the next display frame right away.
>
> However, this "asynchrounous" render mode may cause some waste of resources
> as the guest could produce more frames than what are actually displayed
> on the host display. This is similar as running rendering apps with no
> vblank
> or vsync option. This is why this feature should stay as optional.
>

Indeed, I don't see much point in doing so, it's pure waste. If you want to
benchmark something perhaps. But then, why not simply run a benchmark
offscreen?


>
> The param 'render_sync' is set to 'true' by default and this is in line
> with traditional way while setting it to 'false' is basically enabling
> this asynchronouse mode.
>
>
As it stands now, the option should actually be on the display backend
(gtk/gtk-egl), it's not implemented for other backends.

I am not convinced this is generally useful to be an extra option though.


> Dongwon Kim (4):
>   hw/display/virtio-gpu: Introducing render_sync param
>   ui/egl-helpers: Consolidates create-sync and create-fence
>   ui/gtk-egl: Start rendering of guest blob scanout if render_sync is
> off
>   ui/gtk-gl-draw: Start rendering of guest blob scanout if render_sync
> is off
>
>  include/hw/virtio/virtio-gpu.h  |  3 ++
>  include/ui/dmabuf.h |  4 +-
>  include/ui/egl-helpers.h|  3 +-
>  hw/display/vhost-user-gpu.c |  3 +-
>  hw/display/virtio-gpu-udmabuf.c |  3 +-
>  hw/display/virtio-gpu.c |  2 +
>  hw/vfio/display.c   |  3 +-
>  ui/dbus-listener.c  |  2 +-
>  ui/dmabuf.c | 11 +++-
>  ui/egl-helpers.c| 27 --
>  ui/gtk-egl.c| 93 ++---
>  ui/gtk-gl-area.c| 90 +++
>  12 files changed, 146 insertions(+), 98 deletions(-)
>
> --
> 2.34.1
>
>
>

-- 
Marc-André Lureau


Re: [RFC PATCH 2/4] ui/egl-helpers: Consolidates create-sync and create-fence

2024-07-02 Thread Marc-André Lureau
Hi

On Fri, Jun 21, 2024 at 3:19 AM  wrote:

> From: Dongwon Kim 
>
> There is no reason to split those two operations so combining
> two functions - egl_dmabuf_create_sync and egl_dmabuf_create_fence.
>
> Cc: Gerd Hoffmann 
> Cc: Marc-André Lureau 
> Cc: Vivek Kasireddy 
> Signed-off-by: Dongwon Kim 
>

Can you send this change as a different patch series, or earlier in the
series?

You should also remove qemu_dmabuf_{set,get}_sync() and associated fields

---
>  include/ui/egl-helpers.h |  3 +--
>  ui/egl-helpers.c | 27 +++
>  ui/gtk-egl.c | 19 +++
>  ui/gtk-gl-area.c | 10 ++
>  4 files changed, 21 insertions(+), 38 deletions(-)
>
> diff --git a/include/ui/egl-helpers.h b/include/ui/egl-helpers.h
> index 4b8c0d2281..606d6c8288 100644
> --- a/include/ui/egl-helpers.h
> +++ b/include/ui/egl-helpers.h
> @@ -51,8 +51,7 @@ int egl_get_fd_for_texture(uint32_t tex_id, EGLint
> *stride, EGLint *fourcc,
>
>  void egl_dmabuf_import_texture(QemuDmaBuf *dmabuf);
>  void egl_dmabuf_release_texture(QemuDmaBuf *dmabuf);
> -void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf);
> -void egl_dmabuf_create_fence(QemuDmaBuf *dmabuf);
> +int egl_dmabuf_create_fence(QemuDmaBuf *dmabuf);
>
>  #endif
>
> diff --git a/ui/egl-helpers.c b/ui/egl-helpers.c
> index 99b2ebbe23..e16f2cb23d 100644
> --- a/ui/egl-helpers.c
> +++ b/ui/egl-helpers.c
> @@ -371,34 +371,29 @@ void egl_dmabuf_release_texture(QemuDmaBuf *dmabuf)
>  qemu_dmabuf_set_texture(dmabuf, 0);
>  }
>
> -void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf)
> +int egl_dmabuf_create_fence(QemuDmaBuf *dmabuf)
>  {
>  EGLSyncKHR sync;
> +int fence_fd = -1;
>
>  if (epoxy_has_egl_extension(qemu_egl_display,
>  "EGL_KHR_fence_sync") &&
>  epoxy_has_egl_extension(qemu_egl_display,
> -"EGL_ANDROID_native_fence_sync")) {
> +"EGL_ANDROID_native_fence_sync") &&
> +qemu_dmabuf_get_fence_fd(dmabuf) == -1) {
>  sync = eglCreateSyncKHR(qemu_egl_display,
>  EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
>  if (sync != EGL_NO_SYNC_KHR) {
> -qemu_dmabuf_set_sync(dmabuf, sync);
> +fence_fd = eglDupNativeFenceFDANDROID(qemu_egl_display,
> +  sync);
> +if (fence_fd >= 0) {
> +qemu_dmabuf_set_fence_fd(dmabuf, fence_fd);
> +}
> +eglDestroySyncKHR(qemu_egl_display, sync);
>  }
>  }
> -}
> -
> -void egl_dmabuf_create_fence(QemuDmaBuf *dmabuf)
> -{
> -void *sync = qemu_dmabuf_get_sync(dmabuf);
> -int fence_fd;
>
> -if (sync) {
> -fence_fd = eglDupNativeFenceFDANDROID(qemu_egl_display,
> -  sync);
> -qemu_dmabuf_set_fence_fd(dmabuf, fence_fd);
> -eglDestroySyncKHR(qemu_egl_display, sync);
> -qemu_dmabuf_set_sync(dmabuf, NULL);
> -}
> +return fence_fd;
>

It should probably return qemu_dmabuf_get_fence_fd() instead. The function
should be renamed with _fd postfix since you make it return the fd.

 }
>
>  #endif /* CONFIG_GBM */
> diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c
> index 9831c10e1b..55199f8659 100644
> --- a/ui/gtk-egl.c
> +++ b/ui/gtk-egl.c
> @@ -68,7 +68,6 @@ void gd_egl_draw(VirtualConsole *vc)
>  GdkWindow *window;
>  #ifdef CONFIG_GBM
>  QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf;
> -int fence_fd;
>  #endif
>  int ww, wh, ws;
>
> @@ -99,13 +98,12 @@ void gd_egl_draw(VirtualConsole *vc)
>  glFlush();
>  #ifdef CONFIG_GBM
>  if (dmabuf) {
> -egl_dmabuf_create_fence(dmabuf);
> -fence_fd = qemu_dmabuf_get_fence_fd(dmabuf);
> +fence_fd = egl_dmabuf_create_fence(dmabuf);
>  if (fence_fd >= 0) {
>  qemu_set_fd_handler(fence_fd, gd_hw_gl_flushed, NULL, vc);
> -return;
> +} else {
> +graphic_hw_gl_block(vc->gfx.dcl.con, false);
>  }
> -graphic_hw_gl_block(vc->gfx.dcl.con, false);
>  }
>  #endif
>  } else {
> @@ -336,7 +334,11 @@ void gd_egl_scanout_flush(DisplayChangeListener *dcl,
>  {
>  VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl);
>  GdkWindow *window;
> +#ifdef CONFIG_GBM
> +QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf;
> +#endif
>  int ww, wh, ws;
> +int fence_fd;
>
>  if (!vc->gfx.scanout_m

Re: [PATCH] net: update netdev stream/dgram man page

2024-07-02 Thread Marc-André Lureau
Hi

On Wed, Jun 26, 2024 at 7:53 PM Laurent Vivier  wrote:

> Add the description of "-netdev stream" and "-netdev dgram" in the QEMU
> manpage.
>
> Add some examples on how to use them, including a way to use
> "-netdev stream" and "passt" in place of "-netdev user".
> ("passt" is a non privileged translation proxy between layer-2,
> like "-netdev stream", and layer-4 on host, like TCP, UDP,
> ICMP/ICMPv6 echo)
>

Was there any plan to have passt fallback (default / "-net passt") when
slirp is disabled ? spawning the process with -F fd etc. That would help
migrating away from slirp for some systems.

-- 
Marc-André Lureau


Re: [PATCH] net: update netdev stream/dgram man page

2024-07-02 Thread Marc-André Lureau
e case, since
afaik there is no multicast with UNIX socket? Perhaps this shouldn't be
allowed at all.

+
> +``local.path=path``
> +filesystem path to use to bind the socket
> +
> +``remote.path=path``
> +filesystem path to use as a destination (see sendto(2))
> +
> +Example (two guests connected using an UDP/UNIX socket):
> +
> +.. parsed-literal::
> +
> +# first VM
> +|qemu_system| linux.img \\
> +  -device
> virtio-net,netdev=net0,mac=52:54:00:12:34:56 \\
> +  -netdev
> dgram,id=net0,local.type=unix,local.path=/tmp/qemu0,remote.type=unix,remote.path=/tmp/qemu1
> +# second VM
> +|qemu_system| linux.img \\
> +  -device
> virtio-net,netdev=net0,mac=52:54:00:12:34:57 \\
> +  -netdev
> dgram,id=net0,local.type=unix,local.path=/tmp/qemu1,remote.type=unix,remote.path=/tmp/qemu0
> +
> +``-netdev dgram,id=str,local.type=fd,local.str=file-descriptor``
> +Configure a network backend to connect to another QEMU virtual
> +machine or a proxy using an UDP socket file descriptor.
> +
> +``local.str=file-descriptor``
> +File descriptor to use to send packets
> +
>  ``-netdev
> l2tpv3,id=id,src=srcaddr,dst=dstaddr[,srcport=srcport][,dstport=dstport],txsession=txsession[,rxsession=rxsession][,ipv6=on|off][,udp=on|off][,cookie64][,counter][,pincounter][,txcookie=txcookie][,rxcookie=rxcookie][,offset=offset]``
>  Configure a L2TPv3 pseudowire host network backend. L2TPv3 (RFC3931)
>  is a popular protocol to transport Ethernet (and other Layer 2) data
> --
> 2.45.2
>
>
>

-- 
Marc-André Lureau


Re: [PATCH] ui/gtk: Attach fullscreen toggling cb to all detached VCs

2024-07-02 Thread Marc-André Lureau
Hi

On Tue, Jul 2, 2024 at 4:09 AM  wrote:

> From: Dongwon Kim 
>
> Enable hotkey for toggling window fullscreening for all individual
> untabified VCs
>
> Cc: Marc-André Lureau 
> Cc: Vivek Kasireddy 
> Signed-off-by: Dongwon Kim 
>

Reviewed-by: Marc-André Lureau 

(/rant I wish we had more common code with gd_menu_full_screen.. and
overall cleaner..)


---
>  ui/gtk.c | 39 +++
>  1 file changed, 35 insertions(+), 4 deletions(-)
>
> diff --git a/ui/gtk.c b/ui/gtk.c
> index 93b13b7a30..768e66bec4 100644
> --- a/ui/gtk.c
> +++ b/ui/gtk.c
> @@ -1396,6 +1396,34 @@ static gboolean gd_win_grab(void *opaque)
>  return TRUE;
>  }
>
> +static void gd_vc_fullscreen_toggle(void *opaque)
> +{
> +VirtualConsole *vc = opaque;
> +GdkWindow *window;
> +GdkWindowState state;
> +
> +if (!vc->window)
> +return;
> +
> +window = gtk_widget_get_window(vc->window);
> +state = gdk_window_get_state(window);
> +
> +if (state & GDK_WINDOW_STATE_FULLSCREEN) {
> +gtk_window_unfullscreen(GTK_WINDOW(vc->window));
> +
> +if (vc->type == GD_VC_GFX) {
> +vc->gfx.scale_x = 1.0;
> +vc->gfx.scale_y = 1.0;
> +gd_update_windowsize(vc);
> +}
> +} else {
> +if (vc->type == GD_VC_GFX) {
> +gtk_widget_set_size_request(vc->gfx.drawing_area, -1, -1);
> +}
> +gtk_window_fullscreen(GTK_WINDOW(vc->window));
> +}
> +}
> +
>  static void gd_menu_untabify(GtkMenuItem *item, void *opaque)
>  {
>  GtkDisplayState *s = opaque;
> @@ -1428,10 +1456,13 @@ static void gd_menu_untabify(GtkMenuItem *item,
> void *opaque)
>  if (qemu_console_is_graphic(vc->gfx.dcl.con)) {
>  GtkAccelGroup *ag = gtk_accel_group_new();
>  gtk_window_add_accel_group(GTK_WINDOW(vc->window), ag);
> -
> -GClosure *cb = g_cclosure_new_swap(G_CALLBACK(gd_win_grab),
> -   vc, NULL);
> -gtk_accel_group_connect(ag, GDK_KEY_g, HOTKEY_MODIFIERS, 0,
> cb);
> +GClosure *cb_grab =
> g_cclosure_new_swap(G_CALLBACK(gd_win_grab),
> +vc, NULL);
> +gtk_accel_group_connect(ag, GDK_KEY_g, HOTKEY_MODIFIERS, 0,
> cb_grab);
> +GClosure *cb_fs = g_cclosure_new_swap(
> +
>  G_CALLBACK(gd_vc_fullscreen_toggle),
> + vc, NULL);
> +gtk_accel_group_connect(ag, GDK_KEY_f, HOTKEY_MODIFIERS, 0,
> cb_fs);
>  }
>
>  gd_update_geometry_hints(vc);
> --
> 2.34.1
>
>
>

-- 
Marc-André Lureau


Re: [PATCH v16 00/13] Support blob memory and venus on qemu

2024-07-01 Thread Marc-André Lureau
Hi,

All R-b now, it looks good to merge. Thanks for all the effort!

Michael, are you taking it through your tree?

On Sun, Jun 23, 2024 at 7:23 PM Dmitry Osipenko <
dmitry.osipe...@collabora.com> wrote:

> Hello,
>
> This series enables Vulkan Venus context support on virtio-gpu.
>
> All virglrender and almost all Linux kernel prerequisite changes
> needed by Venus are already in upstream. For kernel there is a pending
> KVM patchset that fixes mapping of compound pages needed for DRM drivers
> using TTM [1], othewrwise hostmem blob mapping will fail with a KVM error
> from Qemu.
>
> [1]
> https://lore.kernel.org/kvm/20240229025759.1187910-1-steve...@google.com/
>
> You'll need to use recent Mesa version containing patch that removes
> dependency on cross-device feature from Venus that isn't supported by
> Qemu [2].
>
> [2]
> https://gitlab.freedesktop.org/mesa/mesa/-/commit/087e9a96d13155e26987befae78b6ccbb7ae242b
>
> Example Qemu cmdline that enables Venus:
>
>   qemu-system-x86_64 -device virtio-vga-gl,hostmem=4G,blob=true,venus=true
> \
>   -machine q35,accel=kvm,memory-backend=mem1 \
>   -object memory-backend-memfd,id=mem1,size=8G -m 8G
>
>
> Changes from V15 to V16
>
> - Fixed resource_get_info() change made in v15 that was squshed into a
>   wrong patch. Squashed set_scanout_blob patch into the blob-commands
> patch,
>   otherwise we'll need to revert back ordering of blob patches to older v7
>   variant.
>
> - Changed hostmem mapping state to boolean, suggested by Akihiko Odaki.
>
> - Documented Venus in virtio-gpu doc. Amended "Support Venus context" patch
>   with the doc addition. Suggested by Akihiko Odaki.
>
> Changes from V14 to V15
>
> - Dropped hostmem mapping state that got unused in v14, suggested by
>   Akihiko Odaki.
>
> - Moved resource_get_info() from set_scanout_blob() to create_blob(),
>   suggested by Akihiko Odaki.
>
> - Fixed unitilized variable in create_blob(), spotted by Alex Bennée.
>
> Changes from V13 to V14
>
> - Fixed erronous fall-through in renderer_state's switch-case that was
>   spotted by Marc-André Lureau.
>
> - Reworked HOSTMEM_MR_FINISH_UNMAPPING handling as was suggested by
>   Akihiko Odaki. Now it shares the same code path with HOSTMEM_MR_MAPPED.
>
> - Made use of g_autofree in virgl_cmd_resource_create_blob() as was
>   suggested by Akihiko Odaki.
>
> - Removed virtio_gpu_virgl_deinit() and moved all deinit code to
>   virtio_gpu_gl_device_unrealize() as was suggested by Marc-André Lureau.
>
> - Replaced HAVE_FEATURE in mseon.build with virglrenderer's VERSION_MAJOR
>   check as was suggested by Marc-André Lureau.
>
> - Added trace event for cmd-suspension as was suggested by Marc-André
> Lureau.
>
> - Added patch to replace in-flight printf's with trace events as was
>   suggested by Marc-André Lureau
>
> Changes from V12 to V13
>
> - Replaced `res->async_unmap_in_progress` flag with a mapping state,
>   moved it to the virtio_gpu_virgl_hostmem_region like was suggested
>   by Akihiko Odaki.
>
> - Renamed blob_unmap function and added back cmd_suspended argument
>   to it. Suggested by Akihiko Odaki.
>
> - Reordered VirtIOGPUGL refactoring patches to minimize code changes
>   like was suggested by Akihiko Odaki.
>
> - Replaced gl->renderer_inited with gl->renderer_state, like was suggested
>   by Alex Bennée.
>
> - Added gl->renderer state resetting to gl_device_unrealize(), for
>   consistency. Suggested by Alex Bennée.
>
> - Added rb's from Alex and Manos.
>
> - Fixed compiling with !HAVE_VIRGL_RESOURCE_BLOB.
>
> Changes from V11 to V12
>
> - Fixed virgl_cmd_resource_create_blob() error handling. Now it doesn't
>   corrupt resource list and releases resource properly on error. Thanks
>   to Akihiko Odaki for spotting the bug.
>
> - Added new patch that handles virtio_gpu_virgl_init() failure gracefully,
>   fixing Qemu crash. Besides fixing the crash, it allows to implement
>   a cleaner virtio_gpu_virgl_deinit().
>
> - virtio_gpu_virgl_deinit() now assumes that previously virgl was
>   initialized successfully when it was inited at all. Suggested by
>   Akihiko Odaki.
>
> - Fixed missed freeing of print_stats timer in virtio_gpu_virgl_deinit()
>
> - Added back blob unmapping or RESOURCE_UNREF that was requested
>   by Akihiko Odaki. Added comment to the code explaining how
>   async unmapping works. Added back `res->async_unmap_in_progress`
>   flag and added comment telling why it's needed.
>
> - Moved cmdq_resume_bh to VirtIOGPUGL and made coding style changes
>   suggested by Akihiko Odaki.
>
> - Added patches that move fence_poll and print

Re: [PATCH v2] Cursor: 8 -> 1 bit alpha downsampling improvement

2024-06-29 Thread Marc-André Lureau
On Mon, Jun 24, 2024 at 2:11 PM Phil Dennis-Jordan 
wrote:

> Mouse cursors with 8 bit alpha were downsampled to 1-bit opacity maps by
> turning alpha values of 255 into 1 and everything else into 0. This
> means that mostly-opaque pixels ended up completely invisible.
>
> This patch changes the behaviour so that only pixels with less than 50%
> alpha (0-127) are treated as transparent when converted to 1-bit alpha.
>
> This greatly improves the subjective appearance of anti-aliased mouse
> cursors, such as those used by macOS, when using a front-end UI without
> support for alpha-blended cursors, such as some VNC clients.
>
> Signed-off-by: Phil Dennis-Jordan 
>

Reviewed-by: Marc-André Lureau 


> ---
>  ui/cursor.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/ui/cursor.c b/ui/cursor.c
> index 29717b3ecb..dd3853320d 100644
> --- a/ui/cursor.c
> +++ b/ui/cursor.c
> @@ -232,7 +232,7 @@ void cursor_get_mono_mask(QEMUCursor *c, int
> transparent, uint8_t *mask)
>  for (y = 0; y < c->height; y++) {
>  bit = 0x80;
>  for (x = 0; x < c->width; x++, data++) {
> -if ((*data & 0xff00) != 0xff00) {
> +if ((*data & 0x8000) == 0x0) { /* Alpha < 0x80 (128) */
>  if (transparent != 0) {
>  mask[x/8] |= bit;
>  }
> --
> 2.39.3 (Apple Git-146)
>
>
>

-- 
Marc-André Lureau


Re: [PATCH v2 4/4] ui/console: Remove dpy_cursor_define_supported()

2024-06-29 Thread Marc-André Lureau
On Thu, Jun 27, 2024 at 3:19 PM Akihiko Odaki 
wrote:

> Remove dpy_cursor_define_supported() as it brings no benefit today and
> it has a few inherent problems.
>
> All graphical displays except egl-headless support cursor composition
> without DMA-BUF, and egl-headless is meant to be used in conjunction
> with another graphical display, so dpy_cursor_define_supported()
> always returns true and meaningless.
>
> Even if we add a new display without cursor composition in the future,
> dpy_cursor_define_supported() will be problematic as a cursor display
> fix for it because some display devices like virtio-gpu cannot tell the
> lack of cursor composition capability to the guest and are unable to
> utilize the value the function returns. Therefore, all non-headless
> graphical displays must actually implement cursor composition for
> correct cursor display.
>
> Another problem with dpy_cursor_define_supported() is that it returns
> true even if only some of the display listeners support cursor
> composition, which is wrong unless all display listeners that lack
> cursor composition is headless.
>
> Signed-off-by: Akihiko Odaki 
>

Agreed,
Reviewed-by: Marc-André Lureau 

> ---
>  include/ui/console.h|  1 -
>  hw/display/qxl-render.c |  4 
>  hw/display/vmware_vga.c |  6 ++
>  ui/console.c| 13 -
>  4 files changed, 2 insertions(+), 22 deletions(-)
>
> diff --git a/include/ui/console.h b/include/ui/console.h
> index 82b573e68082..fa986ab97e3b 100644
> --- a/include/ui/console.h
> +++ b/include/ui/console.h
> @@ -324,7 +324,6 @@ void dpy_text_update(QemuConsole *con, int x, int y,
> int w, int h);
>  void dpy_text_resize(QemuConsole *con, int w, int h);
>  void dpy_mouse_set(QemuConsole *con, int x, int y, bool on);
>  void dpy_cursor_define(QemuConsole *con, QEMUCursor *cursor);
> -bool dpy_cursor_define_supported(QemuConsole *con);
>  bool dpy_gfx_check_format(QemuConsole *con,
>pixman_format_code_t format);
>
> diff --git a/hw/display/qxl-render.c b/hw/display/qxl-render.c
> index ec99ec887a6e..837d2446cd52 100644
> --- a/hw/display/qxl-render.c
> +++ b/hw/display/qxl-render.c
> @@ -307,10 +307,6 @@ int qxl_render_cursor(PCIQXLDevice *qxl,
> QXLCommandExt *ext)
>  return 1;
>  }
>
> -if (!dpy_cursor_define_supported(qxl->vga.con)) {
> -return 0;
> -}
> -
>  if (qxl->debug > 1 && cmd->type != QXL_CURSOR_MOVE) {
>  fprintf(stderr, "%s", __func__);
>  qxl_log_cmd_cursor(qxl, cmd, ext->group_id);
> diff --git a/hw/display/vmware_vga.c b/hw/display/vmware_vga.c
> index 512f224b9f58..3db3ff98f763 100644
> --- a/hw/display/vmware_vga.c
> +++ b/hw/display/vmware_vga.c
> @@ -904,10 +904,8 @@ static uint32_t vmsvga_value_read(void *opaque,
> uint32_t address)
>  caps |= SVGA_CAP_RECT_FILL;
>  #endif
>  #ifdef HW_MOUSE_ACCEL
> -if (dpy_cursor_define_supported(s->vga.con)) {
> -caps |= SVGA_CAP_CURSOR | SVGA_CAP_CURSOR_BYPASS_2 |
> -SVGA_CAP_CURSOR_BYPASS;
> -}
> +caps |= SVGA_CAP_CURSOR | SVGA_CAP_CURSOR_BYPASS_2 |
> +SVGA_CAP_CURSOR_BYPASS;
>  #endif
>  ret = caps;
>  break;
> diff --git a/ui/console.c b/ui/console.c
> index 0ec70cb50ce6..33976446425e 100644
> --- a/ui/console.c
> +++ b/ui/console.c
> @@ -1001,19 +1001,6 @@ void dpy_cursor_define(QemuConsole *c, QEMUCursor
> *cursor)
>  }
>  }
>
> -bool dpy_cursor_define_supported(QemuConsole *con)
> -{
> -DisplayState *s = con->ds;
> -DisplayChangeListener *dcl;
> -
> -QLIST_FOREACH(dcl, >listeners, next) {
> -if (dcl->ops->dpy_cursor_define) {
> -return true;
> -}
> -}
> -return false;
> -}
> -
>  QEMUGLContext dpy_gl_ctx_create(QemuConsole *con,
>  struct QEMUGLParams *qparams)
>  {
>
> --
> 2.45.2
>
>
>

-- 
Marc-André Lureau


Re: [PATCH v2 2/4] ui/console: Convert mouse visibility parameter into bool

2024-06-29 Thread Marc-André Lureau
On Thu, Jun 27, 2024 at 3:19 PM Akihiko Odaki 
wrote:

> Signed-off-by: Akihiko Odaki 
>

Reviewed-by: Marc-André Lureau 


> ---
>  include/ui/console.h|  4 ++--
>  hw/display/ati.c|  2 +-
>  hw/display/virtio-gpu.c |  3 +--
>  hw/display/vmware_vga.c |  2 +-
>  ui/console.c|  5 +++--
>  ui/dbus-listener.c  |  2 +-
>  ui/gtk.c|  2 +-
>  ui/sdl2.c   |  4 ++--
>  ui/spice-display.c  | 11 ++-
>  ui/vnc.c|  2 +-
>  10 files changed, 19 insertions(+), 18 deletions(-)
>
> diff --git a/include/ui/console.h b/include/ui/console.h
> index a208a68b8886..82b573e68082 100644
> --- a/include/ui/console.h
> +++ b/include/ui/console.h
> @@ -233,7 +233,7 @@ typedef struct DisplayChangeListenerOps {
>
>  /* optional */
>  void (*dpy_mouse_set)(DisplayChangeListener *dcl,
> -  int x, int y, int on);
> +  int x, int y, bool on);
>  /* optional */
>  void (*dpy_cursor_define)(DisplayChangeListener *dcl,
>QEMUCursor *cursor);
> @@ -322,7 +322,7 @@ void dpy_gfx_replace_surface(QemuConsole *con,
>  void dpy_text_cursor(QemuConsole *con, int x, int y);
>  void dpy_text_update(QemuConsole *con, int x, int y, int w, int h);
>  void dpy_text_resize(QemuConsole *con, int w, int h);
> -void dpy_mouse_set(QemuConsole *con, int x, int y, int on);
> +void dpy_mouse_set(QemuConsole *con, int x, int y, bool on);
>  void dpy_cursor_define(QemuConsole *con, QEMUCursor *cursor);
>  bool dpy_cursor_define_supported(QemuConsole *con);
>  bool dpy_gfx_check_format(QemuConsole *con,
> diff --git a/hw/display/ati.c b/hw/display/ati.c
> index 8d2501bd8210..b1f94f5b767d 100644
> --- a/hw/display/ati.c
> +++ b/hw/display/ati.c
> @@ -742,7 +742,7 @@ static void ati_mm_write(void *opaque, hwaddr addr,
>  if (!s->cursor_guest_mode &&
>  (s->regs.crtc_gen_cntl & CRTC2_CUR_EN) && !(t & BIT(31))) {
>  dpy_mouse_set(s->vga.con, s->regs.cur_hv_pos >> 16,
> -  s->regs.cur_hv_pos & 0x, 1);
> +  s->regs.cur_hv_pos & 0x, true);
>  }
>  break;
>  }
> diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
> index d60b1b2973af..3281842bfe1b 100644
> --- a/hw/display/virtio-gpu.c
> +++ b/hw/display/virtio-gpu.c
> @@ -109,8 +109,7 @@ static void update_cursor(VirtIOGPU *g, struct
> virtio_gpu_update_cursor *cursor)
>  s->cursor.pos.x = cursor->pos.x;
>  s->cursor.pos.y = cursor->pos.y;
>  }
> -dpy_mouse_set(s->con, cursor->pos.x, cursor->pos.y,
> -  cursor->resource_id ? 1 : 0);
> +dpy_mouse_set(s->con, cursor->pos.x, cursor->pos.y,
> cursor->resource_id);
>  }
>
>  struct virtio_gpu_simple_resource *
> diff --git a/hw/display/vmware_vga.c b/hw/display/vmware_vga.c
> index 1c0f9d9a991d..512f224b9f58 100644
> --- a/hw/display/vmware_vga.c
> +++ b/hw/display/vmware_vga.c
> @@ -1167,7 +1167,7 @@ static void vmsvga_reset(DeviceState *dev)
>  s->enable = 0;
>  s->config = 0;
>  s->svgaid = SVGA_ID;
> -s->cursor.on = 0;
> +s->cursor.on = false;
>  s->redraw_fifo_last = 0;
>  s->syncing = 0;
>
> diff --git a/ui/console.c b/ui/console.c
> index 1b2cd0c7365d..0ec70cb50ce6 100644
> --- a/ui/console.c
> +++ b/ui/console.c
> @@ -49,7 +49,8 @@ typedef struct QemuGraphicConsole {
>  uint32_t head;
>
>  QEMUCursor *cursor;
> -int cursor_x, cursor_y, cursor_on;
> +int cursor_x, cursor_y;
> +bool cursor_on;
>  } QemuGraphicConsole;
>
>  typedef QemuConsoleClass QemuGraphicConsoleClass;
> @@ -957,7 +958,7 @@ void dpy_text_resize(QemuConsole *con, int w, int h)
>  }
>  }
>
> -void dpy_mouse_set(QemuConsole *c, int x, int y, int on)
> +void dpy_mouse_set(QemuConsole *c, int x, int y, bool on)
>  {
>  QemuGraphicConsole *con = QEMU_GRAPHIC_CONSOLE(c);
>  DisplayState *s = c->ds;
> diff --git a/ui/dbus-listener.c b/ui/dbus-listener.c
> index 54900880433e..a54123acea7d 100644
> --- a/ui/dbus-listener.c
> +++ b/ui/dbus-listener.c
> @@ -726,7 +726,7 @@ static void dbus_gfx_switch(DisplayChangeListener *dcl,
>  }
>
>  static void dbus_mouse_set(DisplayChangeListener *dcl,
> -   int x, int y, int on)
> +   int x, int y, bool on)
>  {
>  DBusDisplayListener *ddl = container_of(dcl, DBusDisplayListener,
> dcl);
>
> diff --git a/ui/gtk.c b/ui/gtk.c
> index 93b13b7a30ff..bc29f7a1b4f7 100644

Re: [PATCH 2/2] vfio/display: Fix vfio_display_edid_init() error path

2024-06-29 Thread Marc-André Lureau
On Fri, Jun 28, 2024 at 1:31 PM Zhenzhong Duan 
wrote:

> vfio_display_edid_init() can fail for many reasons and return silently.
> It would be good to report the error.
>
> Old mdev driver may not support vfio edid region and we allow to go
> through in this case.
>
> vfio_display_edid_update() isn't changed because it can be called at
> runtime when UI changes (i.e. window resize).
>
> Fixes: 08479114b0de ("vfio/display: add edid support.")
> Suggested-by: Cédric Le Goater 
> Signed-off-by: Zhenzhong Duan 
>

Reviewed-by: Marc-André Lureau 

---
>  hw/vfio/display.c | 13 +++--
>  1 file changed, 7 insertions(+), 6 deletions(-)
>
> diff --git a/hw/vfio/display.c b/hw/vfio/display.c
> index 5926bd6628..462845ce69 100644
> --- a/hw/vfio/display.c
> +++ b/hw/vfio/display.c
> @@ -124,7 +124,7 @@ static void vfio_display_edid_ui_info(void *opaque,
> uint32_t idx,
>  }
>  }
>
> -static void vfio_display_edid_init(VFIOPCIDevice *vdev)
> +static bool vfio_display_edid_init(VFIOPCIDevice *vdev, Error **errp)
>  {
>  VFIODisplay *dpy = vdev->dpy;
>  int fd = vdev->vbasedev.fd;
> @@ -135,7 +135,8 @@ static void vfio_display_edid_init(VFIOPCIDevice *vdev)
> VFIO_REGION_SUBTYPE_GFX_EDID,
> >edid_info);
>  if (ret) {
> -return;
> +/* Failed to get GFX edid info, allow to go through without edid.
> */
> +return true;
>  }
>
>  trace_vfio_display_edid_available();
> @@ -167,14 +168,15 @@ static void vfio_display_edid_init(VFIOPCIDevice
> *vdev)
>  vfio_display_edid_link_up, vdev);
>
>  vfio_display_edid_update(vdev, true, 0, 0);
> -return;
> +return true;
>
>  err:
> +error_setg(errp, "vfio: failed to read GFX edid field");
>  trace_vfio_display_edid_write_error();
>  g_free(dpy->edid_info);
>  g_free(dpy->edid_regs);
>  dpy->edid_regs = NULL;
> -return;
> +return false;
>  }
>
>  static void vfio_display_edid_exit(VFIODisplay *dpy)
> @@ -367,8 +369,7 @@ static bool vfio_display_dmabuf_init(VFIOPCIDevice
> *vdev, Error **errp)
>  return false;
>  }
>  }
> -vfio_display_edid_init(vdev);
> -return true;
> +return vfio_display_edid_init(vdev, errp);
>  }
>
>  static void vfio_display_dmabuf_exit(VFIODisplay *dpy)
> --
> 2.34.1
>
>
>

-- 
Marc-André Lureau


Re: [PATCH 1/2] vfio/display: Fix potential memleak of edid info

2024-06-29 Thread Marc-André Lureau
Hi

On Fri, Jun 28, 2024 at 1:32 PM Zhenzhong Duan 
wrote:

> EDID related device region info is leaked in three paths:
> 1. In vfio_get_dev_region_info(), when edid info isn't find, the last
> device region info is leaked.
> 2. In vfio_display_edid_init() error path, edid info is leaked.
> 3. In VFIODisplay destroying path, edid info is leaked.
>
> Fixes: 08479114b0de ("vfio/display: add edid support.")
> Signed-off-by: Zhenzhong Duan 
> ---
>  hw/vfio/display.c | 2 ++
>  hw/vfio/helpers.c | 1 +
>  2 files changed, 3 insertions(+)
>
> diff --git a/hw/vfio/display.c b/hw/vfio/display.c
> index 661e921616..5926bd6628 100644
> --- a/hw/vfio/display.c
> +++ b/hw/vfio/display.c
> @@ -171,6 +171,7 @@ static void vfio_display_edid_init(VFIOPCIDevice *vdev)
>
>  err:
>  trace_vfio_display_edid_write_error();
> +g_free(dpy->edid_info);
>

It would be better to set it to NULL.


>  g_free(dpy->edid_regs);
>  dpy->edid_regs = NULL;
>  return;
> @@ -182,6 +183,7 @@ static void vfio_display_edid_exit(VFIODisplay *dpy)
>  return;
>  }
>
> +g_free(dpy->edid_info);
>  g_free(dpy->edid_regs);
>  g_free(dpy->edid_blob);
>  timer_free(dpy->edid_link_timer);
> diff --git a/hw/vfio/helpers.c b/hw/vfio/helpers.c
> index b14edd46ed..3dd32b26a4 100644
> --- a/hw/vfio/helpers.c
> +++ b/hw/vfio/helpers.c
> @@ -586,6 +586,7 @@ int vfio_get_dev_region_info(VFIODevice *vbasedev,
> uint32_t type,
>  g_free(*info);
>  }
>
> +g_free(*info);
>

This seems incorrect, it is freed at the end of the loop above if it didn't
retun.


>  *info = NULL;
>  return -ENODEV;
>  }
> --
> 2.34.1
>
>
>

-- 
Marc-André Lureau


Re: [PATCH] ui/gtk: Wait until the current guest frame is rendered before switching to RUN_STATE_SAVE_VM

2024-06-14 Thread Marc-André Lureau
Hi

On Thu, Jun 13, 2024 at 9:27 PM Kim, Dongwon  wrote:

> Hi Marc-André,
>
> On 6/13/2024 6:16 AM, Marc-André Lureau wrote:
> > Hi
> >
> > On Wed, Jun 12, 2024 at 10:50 PM Kim, Dongwon  > <mailto:dongwon@intel.com>> wrote:
> >
> > On 6/11/2024 10:44 PM, Marc-André Lureau wrote:
> >  > Hi
> >  >
> >  > On Wed, Jun 12, 2024 at 5:29 AM Kim, Dongwon
> > mailto:dongwon@intel.com>
> >  > <mailto:dongwon@intel.com <mailto:dongwon@intel.com>>>
> wrote:
> >  >
> >  > Hi,
> >  >
> >  > From: Marc-André Lureau  > <mailto:marcandre.lur...@gmail.com>
> >  > <mailto:marcandre.lur...@gmail.com
> > <mailto:marcandre.lur...@gmail.com>>>
> >  > Sent: Wednesday, June 5, 2024 12:56 AM
> >  > To: Kim, Dongwon  > <mailto:dongwon@intel.com> <mailto:dongwon@intel.com
> > <mailto:dongwon@intel.com>>>
> >  > Cc: qemu-devel@nongnu.org <mailto:qemu-devel@nongnu.org>
> > <mailto:qemu-devel@nongnu.org <mailto:qemu-devel@nongnu.org>>;
> Peter Xu
> >  > mailto:pet...@redhat.com>
> > <mailto:pet...@redhat.com <mailto:pet...@redhat.com>>>
> >  > Subject: Re: [PATCH] ui/gtk: Wait until the current guest
> > frame is
> >  > rendered before switching to RUN_STATE_SAVE_VM
> >  >
> >  > Hi
> >  >
> >  > On Tue, Jun 4, 2024 at 9:49 PM Kim, Dongwon
> >  > <mailto:dongwon@intel.com <mailto:dongwon@intel.com>
> > <mailto:dongwon@intel.com <mailto:dongwon@intel.com>>>
> wrote:
> >  > On 6/4/2024 4:12 AM, Marc-André Lureau wrote:
> >  >  > Hi
> >  >  >
> >  >  > On Thu, May 30, 2024 at 2:44 AM
> > <mailto:dongwon@intel.com <mailto:dongwon@intel.com>
> >  > <mailto:dongwon@intel.com <mailto:dongwon@intel.com>>
> >  >  > <mailto:mailto <mailto:mailto> <mailto:mailto
> > <mailto:mailto>>:dongwon@intel.com <mailto:dongwon@intel.com
> >
> >  > <mailto:dongwon@intel.com
> > <mailto:dongwon@intel.com>>>> wrote:
> >  >  >
> >  >  > From: Dongwon <mailto:dongwon@intel.com
> > <mailto:dongwon@intel.com>
> >  > <mailto:dongwon@intel.com <mailto:dongwon@intel.com>>
> > <mailto:mailto <mailto:mailto>
> >  > <mailto:mailto <mailto:mailto>>:dongwon@intel.com
> > <mailto:dongwon@intel.com> <mailto:dongwon@intel.com
> > <mailto:dongwon@intel.com>>>>
> >  >  >
> >  >  > Make sure rendering of the current frame is finished
> > before
> >  > switching
> >  >  > the run state to RUN_STATE_SAVE_VM by waiting for
> egl-sync
> >  > object to be
> >  >  > signaled.
> >  >  >
> >  >  >
> >  >  > Can you expand on what this solves?
> >  >
> >  > In current scheme, guest waits for the fence to be signaled
> > for each
> >  > frame it submits before moving to the next frame. If the
> > guest’s state
> >  > is saved while it is still waiting for the fence, The guest
> will
> >  > continue to  wait for the fence that was signaled while ago
> > when it is
> >  > restored to the point. One way to prevent it is to get it
> > finish the
> >  > current frame before changing the state.
> >  >
> >  > After the UI sets a fence, hw_ops->gl_block(true) gets
> > called, which
> >  > will block virtio-gpu/virgl from processing commands (until
> the
> >  > fence is signaled and gl_block/false called again).
> >  >
> >  > But this "blocking" state is not saved. So how does this
> affect
> >  > save/restore? Please give more details, thanks
> >  >
> >  > Yeah sure. "Blocking" state is not saved but guest's state is
> > saved
> >  > while it was still waiting fo

Re: [RFC PATCH v2 0/2] ui/gtk: Introduce new param - Connectors

2024-06-14 Thread Marc-André Lureau
Hi

On Thu, Jun 13, 2024 at 9:08 PM Kim, Dongwon  wrote:

> > "hotplug" functionality where a Guest display/window is deeply tied
> to a
> > physical monitor to make it appear to the guest that it is dealing
> with
> > a real physical monitor.
> >
> > In other words, when the physical monitor is unplugged, the
> associated
> > guest display/window gets destroyed/hidden and gets recreated/shown
> > when
> > the monitor is hotplugged again.
> >
> >
> > Interesting case that could be added to virt-viewer if it's necessary.
> >
> > The subject is sufficiently complex that there is already additional
> > documentation/specification in:
> >
> https://gitlab.com/virt-viewer/virt-viewer/-/tree/master/docs?ref_type=heads
> <
> https://gitlab.com/virt-viewer/virt-viewer/-/tree/master/docs?ref_type=heads
> >
> >
> > Honestly, I don't support the idea of duplicating this effort in QEMU.
>
> Marc-André,
>
> My assumption is virt-viewer might not be able to completely replace
> GTK-UI path in terms of performance and smoothness of display update as
> (I think) frame copy between processes is implied, which is same as
>

There is no frame copy when using DMABUF scanouts between qemu and client.

Iow, the performance difference is negligible / noise level.

spice-remote viewer. What about display-bus that you have been working
> on? Would it be a good alternative w.r.t perf concern that I specified
> above?
>

There shouldn't be much difference for the local DMABUF display case.


>
> >
> > --
> > Marc-André Lureau
>
>

-- 
Marc-André Lureau


Re: [PATCH v2 00/22] qga: clean up command source locations and conditionals

2024-06-14 Thread Marc-André Lureau
Hi

On Thu, Jun 13, 2024 at 7:02 PM Daniel P. Berrangé 
wrote:

> This series is a side effect of other work I started, to attempt to
> make the QGA safe to use in confidential VMs by automatically
> restricting the permitted commands. Since this cleanup stands on
> its own, I'm sending it now.
>
> The QGA codebase has a very complicated maze of #ifdefs to create
> stubs for the various commands that cannot be implemented on certain
> platforms. It then has further logic to dynamically disable the stub
> commands at runtime, except this is not consistently applied, so
> some commands remain enabled despite being merely stubs.
>
> The resulting code is hard to follow, when trying to understand exactly
> what commands are available under what circumstances, and when changing
> impls it is easy to get the #ifdefs wrong, resulting in stubs getting
> missed on platforms without a real impl. In some cases, we have multiple
> stubs for the same command, due to the maze of #ifdefs.
>
> The QAPI schema language has support for many years for expressing
> conditions against commands when declaring them. This results in the
> QAPI code generator omitting their implementation entirely at build
> time. This has mutliple benefits
>
>  * The unsupported commands are guaranteed to not exist at runtime
>  * No stubs need ever be defined in the code
>  * The generated QAPI reference manual documents the build conditions
>
> This series is broadly split into three parts
>
>  * Moving tonnes of Linux only commands out of commands-posix.c
>into commands-linux.c to remove many #ifdefs.
>  * Adding 'if' conditions in the QAPI schema to reflect the
>build conditions, removing many more #ifdefs
>  * Sanitizing the logic for disabling/enabling commands at
>runtime to guarantee consistency
>
> Changed in v2:
>
>  - Make FSFreeze error reporting distinguish inability to enable
>VSS from user config choice
>
>  - Fully remove ga_command_init_blockedrpcs() methods. No more
>special case disabling of commands. Either they're disabled
>at build time, or disabled by user config, or by well defined
>rule ie not permitted during FS freeze.
>
>  - Apply rules later in startup to avoid crash from NULL config
>pointer
>
>  - Document changed error messages in commit messages
>
>  - Add -c / --config command line parameter
>
>  - Fix mistaken enabling of fsfreeze hooks on win32
>
>  - Remove pointless 'blockrpcs_key' variable
>
>  - Allow concurrent setting of allow and block lists for
>RPC commands
>
> Daniel P. Berrangé (22):
>   qga: drop blocking of guest-get-memory-block-size command
>   qga: move linux vcpu command impls to commands-linux.c
>   qga: move linux suspend command impls to commands-linux.c
>   qga: move linux fs/disk command impls to commands-linux.c
>   qga: move linux disk/cpu stats command impls to commands-linux.c
>   qga: move linux memory block command impls to commands-linux.c
>   qga: move CONFIG_FSFREEZE/TRIM to be meson defined options
>   qga: conditionalize schema for commands unsupported on Windows
>   qga: conditionalize schema for commands unsupported on non-Linux POSIX
>   qga: conditionalize schema for commands requiring getifaddrs
>   qga: conditionalize schema for commands requiring linux/win32
>   qga: conditionalize schema for commands only supported on Windows
>   qga: conditionalize schema for commands requiring fsfreeze
>   qga: conditionalize schema for commands requiring fstrim
>   qga: conditionalize schema for commands requiring libudev
>   qga: conditionalize schema for commands requiring utmpx
>   qga: conditionalize schema for commands not supported on other UNIX
>   qga: don't disable fsfreeze commands if vss_init fails
>   qga: move declare of QGAConfig struct to top of file
>   qga: remove pointless 'blockrpcs_key' variable
>   qga: allow configuration file path via the cli
>   qga: centralize logic for disabling/enabling commands
>
>
Something broke patchew handling:
https://patchew.org/QEMU/20240613150127.1361931-1-berra...@redhat.com/20240613154406.1365469-1-berra...@redhat.com/

-- 
Marc-André Lureau


Re: [PATCH] ui/gtk: Wait until the current guest frame is rendered before switching to RUN_STATE_SAVE_VM

2024-06-13 Thread Marc-André Lureau
Hi

On Wed, Jun 12, 2024 at 10:50 PM Kim, Dongwon  wrote:

> On 6/11/2024 10:44 PM, Marc-André Lureau wrote:
> > Hi
> >
> > On Wed, Jun 12, 2024 at 5:29 AM Kim, Dongwon  > <mailto:dongwon@intel.com>> wrote:
> >
> > Hi,
> >
> > From: Marc-André Lureau  > <mailto:marcandre.lur...@gmail.com>>
> > Sent: Wednesday, June 5, 2024 12:56 AM
> > To: Kim, Dongwon  dongwon@intel.com>>
> > Cc: qemu-devel@nongnu.org <mailto:qemu-devel@nongnu.org>; Peter Xu
> > mailto:pet...@redhat.com>>
> > Subject: Re: [PATCH] ui/gtk: Wait until the current guest frame is
> > rendered before switching to RUN_STATE_SAVE_VM
> >
> > Hi
> >
> > On Tue, Jun 4, 2024 at 9:49 PM Kim, Dongwon
> > <mailto:dongwon@intel.com <mailto:dongwon@intel.com>> wrote:
> > On 6/4/2024 4:12 AM, Marc-André Lureau wrote:
> >  > Hi
> >  >
> >  > On Thu, May 30, 2024 at 2:44 AM <mailto:dongwon@intel.com
> > <mailto:dongwon@intel.com>
> >  > <mailto:mailto <mailto:mailto>:dongwon@intel.com
> > <mailto:dongwon@intel.com>>> wrote:
> >  >
> >  > From: Dongwon <mailto:dongwon@intel.com
> > <mailto:dongwon@intel.com> <mailto:mailto
> > <mailto:mailto>:dongwon@intel.com <mailto:dongwon@intel.com
> >>>
> >  >
> >  > Make sure rendering of the current frame is finished before
> > switching
> >  > the run state to RUN_STATE_SAVE_VM by waiting for egl-sync
> > object to be
> >  > signaled.
> >  >
> >  >
> >  > Can you expand on what this solves?
> >
> > In current scheme, guest waits for the fence to be signaled for each
> > frame it submits before moving to the next frame. If the guest’s
> state
> > is saved while it is still waiting for the fence, The guest will
> > continue to  wait for the fence that was signaled while ago when it
> is
> > restored to the point. One way to prevent it is to get it finish the
> > current frame before changing the state.
> >
> > After the UI sets a fence, hw_ops->gl_block(true) gets called, which
> > will block virtio-gpu/virgl from processing commands (until the
> > fence is signaled and gl_block/false called again).
> >
> > But this "blocking" state is not saved. So how does this affect
> > save/restore? Please give more details, thanks
> >
> > Yeah sure. "Blocking" state is not saved but guest's state is saved
> > while it was still waiting for the response for its last
> > resource-flush virtio msg. This virtio response, by the way is set
> > to be sent to the guest when the pipeline is unblocked (and when the
> > fence is signaled.). Once the guest's state is saved, current
> > instance of guest will be continued and receives the response as
> > usual. The problem is happening when we restore the saved guest's
> > state again because what guest does will be waiting for the response
> > that was sent a while ago to the original instance.
> >
> >
> > Where is the pending response saved? Can you detail how you test this?
> >
>
> There is no pending response for the guest's restored point, which is a
> problem. The response is sent out after saving is done.
>
> Normal cycle :
>
> resource-flush (scanout flush) -> gl block -> render -> gl unblock
> (after fence is signaled) -> pending response sent out to the guest ->
> guest (virtio-gpu drv) processes the next scanout frame -> (next cycle)
> resource-flush -> gl block ..
>
> When vm state is saved in the middle :
>
> resource-flush (scanout-flush) -> gl block -> saving vm-state -> render
> -> gl unblock -> pending response (resp #1) sent out to the guest ->
> guest (virtio-gpu drv) processes the next scanout frame -> (next cycle)
> resource-flush -> gl block ..
>
> Now, we restore the vm-state we saved
>
> vm-state is restored -> guest (virtio-gpu drv) can't move on as this
> state is still waiting for the response (resp #1)
>

Ok, so actually it's more of a device state issue than a UI/GTK. We end up
not saving a state that reflects the guest state. My understanding is that
the guest is waiting for a fence reply, and we don't save that. Imho, a
better fix would be to either save the fenceq (but then, what else is
missing to complete the operation on resume?), or have a wait to delay the
migration until the fences are flushed.


> So we need to make sure vm-state is saved after the cycle is completed.
>
> This situation would be only happening if you use blob=true with
> virtio-gpu drv as KMS on the linux guest. Do you have any similar setup?
>
>
No, further details to reproduce would help. Even better would be having
some automated test.


-- 
Marc-André Lureau


Re: [PATCH v1 0/3] util/readline.c: Add common but missing shortcuts

2024-06-13 Thread Marc-André Lureau
Hi

On Thu, Jun 13, 2024 at 12:07 PM Manos Pitsidianakis <
manos.pitsidiana...@linaro.org> wrote:

> Some commonly used readline shortcuts are missing from our
> implementation. This series adds:
>
> - Control-n next line, same as Down arrow key
> - Control-p previous line, same as Up arrow key
> - Control-u erase line starting from cursor
>
> Manos Pitsidianakis (3):
>   util/readline.c:fix lints for readline_handle_byte
>   util/readline.c: add C-n, C-p shortcuts
>   util/readline.c: add C-u shortcut
>
>  util/readline.c | 35 +++
>  1 file changed, 31 insertions(+), 4 deletions(-)
>
>
>
Reviewed-by: Marc-André Lureau 


-- 
Marc-André Lureau


Re: [RFC PATCH v2 0/2] ui/gtk: Introduce new param - Connectors

2024-06-13 Thread Marc-André Lureau
Hi

On Thu, Jun 13, 2024 at 3:34 AM Kim, Dongwon  wrote:

> On 6/11/2024 11:42 PM, Marc-André Lureau wrote:
> > Hi
> >
> > On Tue, Jun 11, 2024 at 10:28 PM Kim, Dongwon  > <mailto:dongwon@intel.com>> wrote:
> >
> > Hi Marc-André,
> >
> > On 6/5/2024 12:26 AM, Marc-André Lureau wrote:
> >  > Hi
> >  >
> >  > On Tue, Jun 4, 2024 at 9:59 PM Kim, Dongwon
> > mailto:dongwon@intel.com>
> >  > <mailto:dongwon@intel.com <mailto:dongwon@intel.com>>>
> wrote:
> >
> >  > Xorg may not be going away soon, but it's used less and less. As
> > one of
> >  > the developers, I am no longer running/testing it for a long
> time. I
> >  > wish we would just drop its support tbh.
> >
> > There are features offered by Xorg that are not offered by Wayland
> > compositors and again, we have customers that rely on these features.
> > One of them is the ability to position the window via
> > gtk_window_set_position(). There are strong arguments
> > made on either side when it comes to window positioning:
> >
> https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/247
> <
> https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/247
> >
> >
> > Until there is a way to do this with Wayland compositors, we have to
> > unfortunately rely on Gnome + Xorg.
> >
> >
> > It's a smaller and smaller number of users. The potential/future users
> > are greater if we focus on Wayland.
>
> Right, but until Gtk + Wayland offers the same feature parity and
> customization as that of Gtk + Xorg, there will be distros/users that
> will keep it alive.
> >
> > Fwiw, GNOME (and RHEL) is set to drop Xorg support
> > (https://gitlab.gnome.org/GNOME/gnome-session/-/merge_requests/98
> > <https://gitlab.gnome.org/GNOME/gnome-session/-/merge_requests/98>)
>
> Doesn't look like it is going to happen anytime soon given the massive
> pushback.
>

The plan is there, GNOME has made bold moves in the past. There is not much
left in the TODO. But yes, it takes a bit longer than expected.


>
> >
> > Btw, there is a similar monitor-mapping functionality implemented in
> > virt-viewer/remote-viewer:
> > https://www.mankier.com/1/virt-viewer#Configuration
> > <https://www.mankier.com/1/virt-viewer#Configuration>. Is this
> something
> > that those users could use instead?
>
> It looks a bit similar and interesting but one difference is that our
> feature uses monitor labels such as DP-1, HDMI-2 which is a bit more
> intuitive. And, the other key difference is that our feature includes
>

Intuitive, perhaps. Discoverable and portable?

"hotplug" functionality where a Guest display/window is deeply tied to a
> physical monitor to make it appear to the guest that it is dealing with
> a real physical monitor.
>
In other words, when the physical monitor is unplugged, the associated
> guest display/window gets destroyed/hidden and gets recreated/shown when
> the monitor is hotplugged again.
>
>
Interesting case that could be added to virt-viewer if it's necessary.

>
The subject is sufficiently complex that there is already additional
documentation/specification in:
https://gitlab.com/virt-viewer/virt-viewer/-/tree/master/docs?ref_type=heads

Honestly, I don't support the idea of duplicating this effort in QEMU.

-- 
Marc-André Lureau


Re: [RFC PATCH v1 1/6] build-sys: Add rust feature option

2024-06-12 Thread Marc-André Lureau
Hi

On Wed, Jun 12, 2024 at 12:05 PM Daniel P. Berrangé 
wrote:

> On Tue, Jun 11, 2024 at 02:25:39PM -0400, Stefan Hajnoczi wrote:
> > On Tue, 11 Jun 2024 at 13:54, Manos Pitsidianakis
> >  wrote:
> > >
> > > On Tue, 11 Jun 2024 at 17:05, Stefan Hajnoczi 
> wrote:
> > > >
> > > > On Mon, Jun 10, 2024 at 09:22:36PM +0300, Manos Pitsidianakis wrote:
> > > > > Add options for Rust in meson_options.txt, meson.build, configure
> to
> > > > > prepare for adding Rust code in the followup commits.
> > > > >
> > > > > `rust` is a reserved meson name, so we have to use an alternative.
> > > > > `with_rust` was chosen.
> > > > >
> > > > > Signed-off-by: Manos Pitsidianakis  >
> > > > > ---
> > > > > The cargo wrapper script hardcodes some rust target triples. This
> is
> > > > > just temporary.
> > > > > ---
> > > > >  .gitignore   |   2 +
> > > > >  configure|  12 +++
> > > > >  meson.build  |  11 ++
> > > > >  meson_options.txt|   4 +
> > > > >  scripts/cargo_wrapper.py | 211
> +++
> > > > >  5 files changed, 240 insertions(+)
> > > > >  create mode 100644 scripts/cargo_wrapper.py
>
> > > > > diff --git a/configure b/configure
> > > > > index 38ee257701..c195630771 100755
> > > > > --- a/configure
> > > > > +++ b/configure
>
> snip
>
> > > > > +  test "$with_rust_target_triple" != "" && meson_option_add
> "-Dwith_rust_target_triple=$with_rust_target_triple"
>
> So the --rust-target-triple is only needed when cross compiling,
> but this is not the way we normally handle passing cross compiler
> info to meson. Instead we create a meson cross compiler options
> file containing the target info.
>
> eg for ./configure --cross-prefix=x86_64-w64-mingw32-
>
> we end up creating:
>
> $ cat build/config-meson.cross
> # Automatically generated by configure - do not modify
> [properties]
> [built-in options]
> c_args = []
> cpp_args = []
> objc_args = []
> c_link_args = []
> cpp_link_args = []
> # environment defaults, can still be overridden on
> # the command line
> werror = true
> [project options]
>
> [binaries]
> c = ['x86_64-w64-mingw32-gcc','-m64']
> cpp = ['x86_64-w64-mingw32-g++','-m64']
> objc = ['x86_64-w64-mingw32-clang','-m64']
> ar = ['x86_64-w64-mingw32-ar']
> dlltool = ['x86_64-w64-mingw32-dlltool']
> nm = ['x86_64-w64-mingw32-nm']
> pkgconfig = ['x86_64-w64-mingw32-pkg-config']
> pkg-config = ['x86_64-w64-mingw32-pkg-config']
> ranlib = ['x86_64-w64-mingw32-ranlib']
> strip = ['x86_64-w64-mingw32-strip']
> widl = ['x86_64-w64-mingw32-widl']
> windres = ['x86_64-w64-mingw32-windres']
> windmc = ['x86_64-w64-mingw32-windmc']
> [host_machine]
> system = 'windows'
> cpu_family = 'x86_64'
> cpu = 'x86_64'
> endian = 'little'
>
>
> Should we not be passing the rust compiler target through
> this meson options file by setting something like this
>
>   rust = ['rustc', '--target', '$target_target_triple']
>

Agree


>
>
> Also I don't think we should be requiring --rust-target-triple
> to be passed by the user. For all the combinations we know &
> test, we should have configure "do the right thing" and set a
> suitable rust target triple based on the --cross-prefix argument
> that is given, so there is no extra burden on users cross
> compiling. Users should then only use --rust-target-triple
> if our default logic is wrong for some reason.
>
>
Then I think we would need to maintain some mapping between GNU
target-triplets and Rust. It would be convenient to allow users to
set/overwrite it though.


-- 
Marc-André Lureau


Re: [RFC PATCH v2 0/2] ui/gtk: Introduce new param - Connectors

2024-06-12 Thread Marc-André Lureau
Hi

On Tue, Jun 11, 2024 at 10:28 PM Kim, Dongwon  wrote:

> Hi Marc-André,
>
> On 6/5/2024 12:26 AM, Marc-André Lureau wrote:
> > Hi
> >
> > On Tue, Jun 4, 2024 at 9:59 PM Kim, Dongwon  > <mailto:dongwon@intel.com>> wrote:
>
> Xorg may not be going away soon, but it's used less and less. As one of
> > the developers, I am no longer running/testing it for a long time. I
> > wish we would just drop its support tbh.
>
> There are features offered by Xorg that are not offered by Wayland
> compositors and again, we have customers that rely on these features.
> One of them is the ability to position the window via
> gtk_window_set_position(). There are strong arguments
> made on either side when it comes to window positioning:
>
> https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/247
>
> Until there is a way to do this with Wayland compositors, we have to
> unfortunately rely on Gnome + Xorg.
>
>
It's a smaller and smaller number of users. The potential/future users are
greater if we focus on Wayland.

Fwiw, GNOME (and RHEL) is set to drop Xorg support (
https://gitlab.gnome.org/GNOME/gnome-session/-/merge_requests/98)

Btw, there is a similar monitor-mapping functionality implemented in
virt-viewer/remote-viewer:
https://www.mankier.com/1/virt-viewer#Configuration. Is this something that
those users could use instead?


-- 
Marc-André Lureau


Re: [PATCH] ui/gtk: Wait until the current guest frame is rendered before switching to RUN_STATE_SAVE_VM

2024-06-11 Thread Marc-André Lureau
Hi

On Wed, Jun 12, 2024 at 5:29 AM Kim, Dongwon  wrote:

> Hi,
>
> From: Marc-André Lureau 
> Sent: Wednesday, June 5, 2024 12:56 AM
> To: Kim, Dongwon 
> Cc: qemu-devel@nongnu.org; Peter Xu 
> Subject: Re: [PATCH] ui/gtk: Wait until the current guest frame is
> rendered before switching to RUN_STATE_SAVE_VM
>
> Hi
>
> On Tue, Jun 4, 2024 at 9:49 PM Kim, Dongwon <mailto:dongwon@intel.com>
> wrote:
> On 6/4/2024 4:12 AM, Marc-André Lureau wrote:
> > Hi
> >
> > On Thu, May 30, 2024 at 2:44 AM <mailto:dongwon@intel.com
> > <mailto:mailto:dongwon@intel.com>> wrote:
> >
> > From: Dongwon <mailto:dongwon@intel.com <mailto:mailto:
> dongwon@intel.com>>
> >
> > Make sure rendering of the current frame is finished before switching
> > the run state to RUN_STATE_SAVE_VM by waiting for egl-sync object to
> be
> > signaled.
> >
> >
> > Can you expand on what this solves?
>
> In current scheme, guest waits for the fence to be signaled for each
> frame it submits before moving to the next frame. If the guest’s state
> is saved while it is still waiting for the fence, The guest will
> continue to  wait for the fence that was signaled while ago when it is
> restored to the point. One way to prevent it is to get it finish the
> current frame before changing the state.
>
> After the UI sets a fence, hw_ops->gl_block(true) gets called, which will
> block virtio-gpu/virgl from processing commands (until the fence is
> signaled and gl_block/false called again).
>
> But this "blocking" state is not saved. So how does this affect
> save/restore? Please give more details, thanks
>
> Yeah sure. "Blocking" state is not saved but guest's state is saved while
> it was still waiting for the response for its last resource-flush virtio
> msg. This virtio response, by the way is set to be sent to the guest when
> the pipeline is unblocked (and when the fence is signaled.). Once the
> guest's state is saved, current instance of guest will be continued and
> receives the response as usual. The problem is happening when we restore
> the saved guest's state again because what guest does will be waiting for
> the response that was sent a while ago to the original instance.
>

Where is the pending response saved? Can you detail how you test this?

thanks


-- 
Marc-André Lureau


Re: [PATCH 1/3] virtio-gpu: rutabaga: Properly set stride when copying resources

2024-06-10 Thread Marc-André Lureau
Hi

On Wed, Jun 5, 2024 at 7:30 PM Weifeng Liu  wrote:

> The stride is not correctly assigned when copying pixel data, causing
> images being displayed incomplete when using 2d component of rutabaga.
>
> Signed-off-by: Weifeng Liu 
> ---
>  hw/display/virtio-gpu-rutabaga.c | 3 +++
>  1 file changed, 3 insertions(+)
>
> diff --git a/hw/display/virtio-gpu-rutabaga.c
> b/hw/display/virtio-gpu-rutabaga.c
> index 17bf701a21..2ba6869606 100644
> --- a/hw/display/virtio-gpu-rutabaga.c
> +++ b/hw/display/virtio-gpu-rutabaga.c
> @@ -53,6 +53,7 @@ virtio_gpu_rutabaga_update_cursor(VirtIOGPU *g, struct
> virtio_gpu_scanout *s,
>  transfer.z = 0;
>  transfer.w = res->width;
>  transfer.h = res->height;
> +transfer.stride = res->width * 4;
>

ok, stride defined by QEMUCursor layout


>  transfer.d = 1;
>
>  transfer_iovec.iov_base = s->current_cursor->data;
> @@ -273,6 +274,7 @@ rutabaga_cmd_resource_flush(VirtIOGPU *g, struct
> virtio_gpu_ctrl_command *cmd)
>  transfer.z = 0;
>  transfer.w = res->width;
>  transfer.h = res->height;
> +transfer.stride = pixman_image_get_stride(res->image);
>  transfer.d = 1;
>

ok (destination image stride)


>  transfer_iovec.iov_base = pixman_image_get_data(res->image);
> @@ -382,6 +384,7 @@ rutabaga_cmd_transfer_to_host_2d(VirtIOGPU *g,
>  transfer.z = 0;
>  transfer.w = t2d.r.width;
>  transfer.h = t2d.r.height;
> +transfer.stride = t2d.r.width * 4;
>

here however, it's unclear to me what the stride could be, I think it could
depend on resource format (virgl doesn't set stride either).

Gurchetan?



>  transfer.d = 1;
>
>  result = rutabaga_resource_transfer_write(vr->rutabaga, 0,
> t2d.resource_id,
> --
> 2.45.0
>
>
>

-- 
Marc-André Lureau


Re: [RFC PATCH] subprojects: add a wrapper for libvirglrenderer

2024-06-05 Thread Marc-André Lureau
Hi

On Wed, Jun 5, 2024 at 5:35 PM Alex Bennée  wrote:

> As the latest features for virtio-gpu need a pretty recent version of
> libvirglrenderer. When it is not available on the system we can use a
> meson wrapper and provide it when --download is specified in
> configure.
>
> We have to take some additional care as currently QEMU will hang
> libvirglrenderer fails to exec the render server. As the error isn't
> back propagated we make sure we at least test we have a path to an
> executable before tweaking the environment.
>
> Signed-off-by: Alex Bennée 
> Cc: Manos Pitsidianakis 
> Cc: Dmitry Osipenko 
> Cc: Akihiko Odaki 
> ---
>  meson.build|  7 ++-
>  hw/display/virtio-gpu-virgl.c  | 24 
>  subprojects/virglrenderer.wrap |  6 ++
>  3 files changed, 36 insertions(+), 1 deletion(-)
>  create mode 100644 subprojects/virglrenderer.wrap
>
> diff --git a/meson.build b/meson.build
> index 1d7346b703..e4e270df78 100644
> --- a/meson.build
> +++ b/meson.build
> @@ -1203,7 +1203,8 @@ have_vhost_user_gpu = have_tools and host_os ==
> 'linux' and pixman.found()
>  if not get_option('virglrenderer').auto() or have_system or
> have_vhost_user_gpu
>virgl = dependency('virglrenderer',
>   method: 'pkg-config',
> - required: get_option('virglrenderer'))
> + required: get_option('virglrenderer'),
> + default_options: ['default_library=static',
> 'render-server=true', 'venus=true'])
>

So the subproject won't be used unless virgl-devel is missing on the
system. Is it really so useful? maybe, I am just used to installing my
bleeding edge libraries with stow..

>

>  endif
>  rutabaga = not_found
>  if not get_option('rutabaga_gfx').auto() or have_system or
> have_vhost_user_gpu
> @@ -2314,6 +2315,10 @@ if virgl.version().version_compare('>=1.0.0')
>config_host_data.set('HAVE_VIRGL_RESOURCE_BLOB', 1)
>config_host_data.set('HAVE_VIRGL_VENUS', 1)
>  endif
> +if virgl.type_name().contains('internal')
> +  config_host_data.set('HAVE_BUNDLED_VIRGL_SERVER', 1)
> +endif
> +
>  config_host_data.set('CONFIG_VIRTFS', have_virtfs)
>  config_host_data.set('CONFIG_VTE', vte.found())
>  config_host_data.set('CONFIG_XKBCOMMON', xkbcommon.found())
> diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
> index c9d20a8a60..53d6742e79 100644
> --- a/hw/display/virtio-gpu-virgl.c
> +++ b/hw/display/virtio-gpu-virgl.c
> @@ -14,6 +14,7 @@
>  #include "qemu/osdep.h"
>  #include "qemu/error-report.h"
>  #include "qemu/iov.h"
> +#include "qemu/cutils.h"
>  #include "trace.h"
>  #include "hw/virtio/virtio.h"
>  #include "hw/virtio/virtio-gpu.h"
> @@ -1122,6 +1123,26 @@ void virtio_gpu_virgl_reset(VirtIOGPU *g)
>  virgl_renderer_reset();
>  }
>
> +/*
> + * If we fail to spawn the render server things tend to hang so it is
> + * important to do our due diligence before then. If QEMU has bundled
> + * the virgl server we want to ensure we can run it from the build
> + * directory and if installed.
> + *
> + * The principle way we can override the libvirglrenders behaviour is
> + * by setting environment variables.
> + */
> +static void virgl_set_render_env(void)
> +{
> +#ifdef HAVE_BUNDLED_VIRGL_SERVER
> +g_autofree char *file = get_relocated_path(CONFIG_QEMU_HELPERDIR
> "/virgl_render_server");
> +if (g_file_test(file, G_FILE_TEST_EXISTS |
> G_FILE_TEST_IS_EXECUTABLE)) {
> +g_setenv("RENDER_SERVER_EXEC_PATH", file, false);
> +}
> +#endif
> +}
> +
> +
>  int virtio_gpu_virgl_init(VirtIOGPU *g)
>  {
>  int ret;
> @@ -1145,6 +1166,9 @@ int virtio_gpu_virgl_init(VirtIOGPU *g)
>  }
>  #endif
>
> +/* Ensure we can find the render server */
> +virgl_set_render_env();
> +
>  ret = virgl_renderer_init(g, flags, _gpu_3d_cbs);
>  if (ret != 0) {
>  error_report("virgl could not be initialized: %d", ret);
> diff --git a/subprojects/virglrenderer.wrap
> b/subprojects/virglrenderer.wrap
> new file mode 100644
> index 00..3656a478c4
> --- /dev/null
> +++ b/subprojects/virglrenderer.wrap
> @@ -0,0 +1,6 @@
> +[wrap-git]
> +url = https://gitlab.freedesktop.org/virgl/virglrenderer.git
> +revision = virglrenderer-1.0.1
> +
> +[provide]
> +virglrenderer = libvirglrenderer_dep
> --
> 2.39.2
>
>
>

-- 
Marc-André Lureau


Re: [PATCH v3 0/3] stdvga: fix screen blanking

2024-06-05 Thread Marc-André Lureau
On Wed, Jun 5, 2024 at 5:14 PM Gerd Hoffmann  wrote:
>
>
>
> Gerd Hoffmann (3):
>   stdvga: fix screen blanking
>   ui+display: rename is_placeholder() -> surface_is_placeholder()
>   ui+display: rename is_buffer_shared() -> surface_is_allocated()
>
>  include/ui/surface.h|  6 +++---
>  hw/display/qxl-render.c |  2 +-
>  hw/display/vga.c| 24 +++-
>  hw/display/xenfb.c  |  5 +++--
>  ui/console.c|  3 ++-
>  ui/sdl2-2d.c|  2 +-
>  ui/sdl2-gl.c|  2 +-
>  7 files changed, 26 insertions(+), 18 deletions(-)
>

for the series:
Reviewed-by: Marc-André Lureau 




Re: [PATCH v2 1/3] stdvga: fix screen blanking

2024-06-05 Thread Marc-André Lureau
Hi

On Wed, Jun 5, 2024 at 11:36 AM Gerd Hoffmann  wrote:
>
> On Tue, Jun 04, 2024 at 10:27:18AM GMT, Marc-André Lureau wrote:
> > Hi
> >
> > > +if (is_buffer_shared(surface)) {
> >
> > Perhaps the suggestion to rename the function (in the following patch)
> > should instead be surface_is_allocated() ? that would match the actual
> > flag check. But callers would have to ! the result. Wdyt?
>
> surface_is_shadow() ?  Comes closer to the typical naming in computer
> graphics.

If the underlying flag is renamed too, that's ok to me.




Re: [PATCH 20/20] qga: centralize logic for disabling/enabling commands

2024-06-05 Thread Marc-André Lureau
Hi

On Wed, Jun 5, 2024 at 2:37 PM Marc-André Lureau 
wrote:

> Hi
>
> On Tue, Jun 4, 2024 at 5:51 PM Daniel P. Berrangé 
> wrote:
>
>> It is confusing having many different pieces of code enabling and
>> disabling commands, and it is not clear that they all have the same
>> semantics, especially wrt prioritization of the block/allow lists.
>>
>> Centralizing the code in a single method "ga_apply_command_filters"
>> will provide a strong guarantee of consistency and clarify the
>> intended behaviour.
>>
>> Signed-off-by: Daniel P. Berrangé 
>>
>
> The clean up is very much welcome and looks correct, but it crashes:
>
> Thread 1 "qemu-ga" received signal SIGSEGV, Segmentation fault.
> 0x5557db4f in ga_command_is_allowed (cmd=0x55632800,
> state=0x55633710) at ../qga/main.c:430
> 430if (config->allowedrpcs) {
> (gdb) bt
> #0  0x5557db4f in ga_command_is_allowed (cmd=0x55632800,
> state=0x55633710) at ../qga/main.c:430
> #1  ga_apply_command_filters_iter (cmd=0x55632800,
> opaque=0x55633710) at ../qga/main.c:473
> #2  0x5559ef81 in qmp_for_each_command (cmds=cmds@entry=0x5562c2b0
> , fn=fn@entry=0x5557db30
> , opaque=opaque@entry=0x55633710)
> at ../qapi/qmp-registry.c:93
> #3  0x55571436 in ga_apply_command_filters (state=0x55633710)
> at ../qga/main.c:492
> #4  initialize_agent (config=0x55632760, socket_activation=0) at
> ../qga/main.c:1452
> #5  main (argc=, argv=) at ../qga/main.c:1646
> (gdb) p state.config
> $1 = (GAConfig *) 0x0
>
> (meson test fails too)
>
> I wonder why s->config is set so late in initialize_agent(). Moving it
> earlier seems to solve the issue, but reviewing all code paths is tedious..
>

Actually, there seems to be few ->config users, and they don't check if
it's NULL. So I guess it's ok to move it earlier.

-- 
Marc-André Lureau


Re: [PATCH 20/20] qga: centralize logic for disabling/enabling commands

2024-06-05 Thread Marc-André Lureau
 +static void ga_apply_command_filters_iter(const QmpCommand *cmd, void
> *opaque)
>  {
> -GList *allowedrpcs = opaque;
> +GAState *state = opaque;
> +bool want = ga_command_is_allowed(cmd, state);
> +bool have = qmp_command_is_enabled(cmd);
>  const char *name = qmp_command_name(cmd);
>
> -if (g_list_find_custom(allowedrpcs, name, ga_strcmp) == NULL) {
> +if (want == have) {
> +return;
> +}
> +
> +if (qmp_command_is_enabled(cmd)) {
>  g_debug("disabling command: %s", name);
>  qmp_disable_command(_commands, name, "the command is not
> allowed");
> +} else {
> +g_debug("enabling command: %s", name);
> +qmp_enable_command(_commands, name);
>  }
>  }
>
> +static void ga_apply_command_filters(GAState *state)
> +{
> +qmp_for_each_command(_commands, ga_apply_command_filters_iter,
> state);
> +}
> +
>  static bool ga_create_file(const char *path)
>  {
>  int fd = open(path, O_CREAT | O_WRONLY, S_IWUSR | S_IRUSR);
> @@ -505,15 +524,14 @@ void ga_set_frozen(GAState *s)
>  if (ga_is_frozen(s)) {
>  return;
>  }
> -/* disable all forbidden (for frozen state) commands */
> -qmp_for_each_command(_commands, ga_disable_not_allowed_freeze,
> NULL);
>  g_warning("disabling logging due to filesystem freeze");
> -ga_disable_logging(s);
>  s->frozen = true;
>  if (!ga_create_file(s->state_filepath_isfrozen)) {
>  g_warning("unable to create %s, fsfreeze may not function
> properly",
>s->state_filepath_isfrozen);
>  }
> +ga_apply_command_filters(s);
> +ga_disable_logging(s);
>  }
>
>  void ga_unset_frozen(GAState *s)
> @@ -545,12 +563,12 @@ void ga_unset_frozen(GAState *s)
>  }
>
>  /* enable all disabled, non-blocked and allowed commands */
> -qmp_for_each_command(_commands, ga_enable_non_blocked, s);
>  s->frozen = false;
>  if (!ga_delete_file(s->state_filepath_isfrozen)) {
>  g_warning("unable to delete %s, fsfreeze may not function
> properly",
>s->state_filepath_isfrozen);
>  }
> +ga_apply_command_filters(s);
>  }
>
>  #ifdef CONFIG_FSFREEZE
> @@ -1414,7 +1432,6 @@ static GAState *initialize_agent(GAConfig *config,
> int socket_activation)
>  s->deferred_options.log_filepath = config->log_filepath;
>  }
>  ga_disable_logging(s);
> -qmp_for_each_command(_commands, ga_disable_not_allowed_freeze,
> NULL);
>  } else {
>  if (config->daemonize) {
>  become_daemon(config->pid_filepath);
> @@ -1438,25 +1455,8 @@ static GAState *initialize_agent(GAConfig *config,
> int socket_activation)
>  return NULL;
>  }
>
> -if (config->allowedrpcs) {
> -qmp_for_each_command(_commands, ga_disable_not_allowed,
> config->allowedrpcs);
> -s->allowedrpcs = config->allowedrpcs;
> -}
> +ga_apply_command_filters(s);
>
> -/*
> - * Some commands can be blocked due to system limitation.
> - * Initialize blockedrpcs list even if allowedrpcs specified.
> - */
> -config->blockedrpcs =
> ga_command_init_blockedrpcs(config->blockedrpcs);
> -if (config->blockedrpcs) {
> -GList *l = config->blockedrpcs;
> -s->blockedrpcs = config->blockedrpcs;
> -do {
> -g_debug("disabling command: %s", (char *)l->data);
> -qmp_disable_command(_commands, l->data, NULL);
> -l = g_list_next(l);
> -} while (l);
> -}
>  s->command_state = ga_command_state_new();
>  ga_command_state_init(s, s->command_state);
>  ga_command_state_init_all(s->command_state);
> --
> 2.45.1
>
>
>

-- 
Marc-André Lureau


Re: [PATCH 19/20] qga: move declare of QGAConfig struct to top of file

2024-06-05 Thread Marc-André Lureau
On Tue, Jun 4, 2024 at 5:51 PM Daniel P. Berrangé 
wrote:

> It is referenced byy QGAState already, and it is clearer to declare all
>

minor "byy" typo


> data types at the top of the file, rather than have them mixed with
> code later.
>
> Signed-off-by: Daniel P. Berrangé 
> ---
>  qga/main.c | 44 ++--
>  1 file changed, 22 insertions(+), 22 deletions(-)
>
> diff --git a/qga/main.c b/qga/main.c
> index bdf5344584..e8f52f0794 100644
> --- a/qga/main.c
> +++ b/qga/main.c
> @@ -70,6 +70,28 @@ typedef struct GAPersistentState {
>
>  typedef struct GAConfig GAConfig;
>
> +struct GAConfig {
> +char *channel_path;
> +char *method;
> +char *log_filepath;
> +char *pid_filepath;
> +#ifdef CONFIG_FSFREEZE
> +char *fsfreeze_hook;
> +#endif
> +char *state_dir;
> +#ifdef _WIN32
> +const char *service;
> +#endif
> +gchar *bliststr; /* blockedrpcs may point to this string */
> +gchar *aliststr; /* allowedrpcs may point to this string */
> +GList *blockedrpcs;
> +GList *allowedrpcs;
> +int daemonize;
> +GLogLevelFlags log_level;
> +int dumpconf;
> +bool retry_path;
> +};
> +
>  struct GAState {
>  JSONMessageParser parser;
>  GMainLoop *main_loop;
> @@ -996,28 +1018,6 @@ static GList *split_list(const gchar *str, const
> gchar *delim)
>  return list;
>  }
>
> -struct GAConfig {
> -char *channel_path;
> -char *method;
> -char *log_filepath;
> -char *pid_filepath;
> -#ifdef CONFIG_FSFREEZE
> -char *fsfreeze_hook;
> -#endif
> -char *state_dir;
> -#ifdef _WIN32
> -const char *service;
> -#endif
> -gchar *bliststr; /* blockedrpcs may point to this string */
> -gchar *aliststr; /* allowedrpcs may point to this string */
> -GList *blockedrpcs;
> -GList *allowedrpcs;
> -int daemonize;
> -GLogLevelFlags log_level;
> -int dumpconf;
> -bool retry_path;
> -};
> -
>  static void config_load(GAConfig *config)
>  {
>  GError *gerr = NULL;
> --
> 2.45.1
>
>
>

-- 
Marc-André Lureau


Re: [PATCH 07/20] qga: move CONFIG_FSFREEZE/TRIM to be meson defined options

2024-06-05 Thread Marc-André Lureau
Hi

On Tue, Jun 4, 2024 at 5:50 PM Daniel P. Berrangé 
wrote:

> Defining these at the meson level allows them to be used a conditional
> tests in the QAPI schemas.
>
> Signed-off-by: Daniel P. Berrangé 
> ---
>  meson.build   | 18 ++
>  qga/commands-common.h |  9 -
>  2 files changed, 18 insertions(+), 9 deletions(-)
>
> diff --git a/meson.build b/meson.build
> index 6386607144..356b2a4817 100644
> --- a/meson.build
> +++ b/meson.build
> @@ -2141,6 +2141,22 @@ have_virtfs_proxy_helper =
> get_option('virtfs_proxy_helper') \
>  .require(libcap_ng.found(), error_message: 'the virtfs proxy helper
> requires libcap-ng') \
>  .allowed()
>
> +qga_fsfreeze = false
> +qga_fstrim = false
> +if host_os == 'windows'
> +qga_fsfreeze = true
> +qga_fstrim = true
>

The hook code in qga/main.c compiles for win32, but it is not used. Did you
intentionally enabled that?

+elif host_os == 'linux'
> +if cc.has_header_symbol('linux/fs.h', 'FIFREEZE')
> +qga_fsfreeze = true
> +endif
> +if cc.has_header_symbol('linux/fs.h', 'FITRIM')
> +qga_fstrim = true
> +endif
> +elif host_os == 'freebsd' and cc.has_header_symbol('ufs/ffs/fs.h',
> 'UFSSUSPEND')
> +qga_fsfreeze = true
> +endif
> +
>  if get_option('block_drv_ro_whitelist') == ''
>config_host_data.set('CONFIG_BDRV_RO_WHITELIST', '')
>  else
> @@ -2375,6 +2391,8 @@ config_host_data.set('CONFIG_DEBUG_TCG',
> get_option('debug_tcg'))
>  config_host_data.set('CONFIG_DEBUG_REMAP', get_option('debug_remap'))
>  config_host_data.set('CONFIG_QOM_CAST_DEBUG',
> get_option('qom_cast_debug'))
>  config_host_data.set('CONFIG_REPLICATION',
> get_option('replication').allowed())
> +config_host_data.set('CONFIG_FSFREEZE', qga_fsfreeze)
> +config_host_data.set('CONFIG_FSTRIM', qga_fstrim)
>
>  # has_header
>  config_host_data.set('CONFIG_EPOLL', cc.has_header('sys/epoll.h'))
> diff --git a/qga/commands-common.h b/qga/commands-common.h
> index 8c1c56aac9..263e7c0525 100644
> --- a/qga/commands-common.h
> +++ b/qga/commands-common.h
> @@ -15,19 +15,10 @@
>
>  #if defined(__linux__)
>  #include 
> -#ifdef FIFREEZE
> -#define CONFIG_FSFREEZE
> -#endif
> -#ifdef FITRIM
> -#define CONFIG_FSTRIM
> -#endif
>  #endif /* __linux__ */
>
>  #ifdef __FreeBSD__
>  #include 
> -#ifdef UFSSUSPEND
> -#define CONFIG_FSFREEZE
> -#endif
>  #endif /* __FreeBSD__ */
>
>  #if defined(CONFIG_FSFREEZE) || defined(CONFIG_FSTRIM)
> --
> 2.45.1
>
>
>

-- 
Marc-André Lureau


Re: [PATCH] ui/gtk: Wait until the current guest frame is rendered before switching to RUN_STATE_SAVE_VM

2024-06-05 Thread Marc-André Lureau
Hi

On Tue, Jun 4, 2024 at 9:49 PM Kim, Dongwon  wrote:

> On 6/4/2024 4:12 AM, Marc-André Lureau wrote:
> > Hi
> >
> > On Thu, May 30, 2024 at 2:44 AM  > <mailto:dongwon@intel.com>> wrote:
> >
> > From: Dongwon mailto:dongwon@intel.com>>
> >
> > Make sure rendering of the current frame is finished before switching
> > the run state to RUN_STATE_SAVE_VM by waiting for egl-sync object to
> be
> > signaled.
> >
> >
> > Can you expand on what this solves?
>
> In current scheme, guest waits for the fence to be signaled for each
> frame it submits before moving to the next frame. If the guest’s state
> is saved while it is still waiting for the fence, The guest will
> continue to  wait for the fence that was signaled while ago when it is
> restored to the point. One way to prevent it is to get it finish the
> current frame before changing the state.
>

After the UI sets a fence, hw_ops->gl_block(true) gets called, which will
block virtio-gpu/virgl from processing commands (until the fence is
signaled and gl_block/false called again).

But this "blocking" state is not saved. So how does this affect
save/restore? Please give more details, thanks


> >
> >
> > Cc: Marc-André Lureau  > <mailto:marcandre.lur...@redhat.com>>
> > Cc: Vivek Kasireddy  > <mailto:vivek.kasire...@intel.com>>
> > Signed-off-by: Dongwon Kim  > <mailto:dongwon@intel.com>>
> > ---
> >   ui/egl-helpers.c |  2 --
> >   ui/gtk.c | 19 +++
> >   2 files changed, 19 insertions(+), 2 deletions(-)
> >
> > diff --git a/ui/egl-helpers.c b/ui/egl-helpers.c
> > index 99b2ebbe23..dafeb36074 100644
> > --- a/ui/egl-helpers.c
> > +++ b/ui/egl-helpers.c
> > @@ -396,8 +396,6 @@ void egl_dmabuf_create_fence(QemuDmaBuf *dmabuf)
> >   fence_fd = eglDupNativeFenceFDANDROID(qemu_egl_display,
> > sync);
> >   qemu_dmabuf_set_fence_fd(dmabuf, fence_fd);
> > -eglDestroySyncKHR(qemu_egl_display, sync);
> > -qemu_dmabuf_set_sync(dmabuf, NULL);
> >
> >
> > If this function is called multiple times, it will now set a new
> > fence_fd each time, and potentially leak older fd. Maybe it could first
> > check if a fence_fd exists instead.
>
> We can make that change.
>
> >
> >   }
> >   }
> >
> > diff --git a/ui/gtk.c b/ui/gtk.c
> > index 93b13b7a30..cf0dd6abed 100644
> > --- a/ui/gtk.c
> > +++ b/ui/gtk.c
> > @@ -600,9 +600,12 @@ void gd_hw_gl_flushed(void *vcon)
> >
> >   fence_fd = qemu_dmabuf_get_fence_fd(dmabuf);
> >   if (fence_fd >= 0) {
> > +void *sync = qemu_dmabuf_get_sync(dmabuf);
> >   qemu_set_fd_handler(fence_fd, NULL, NULL, NULL);
> >   close(fence_fd);
> >   qemu_dmabuf_set_fence_fd(dmabuf, -1);
> > +eglDestroySyncKHR(qemu_egl_display, sync);
> > +qemu_dmabuf_set_sync(dmabuf, NULL);
> >   graphic_hw_gl_block(vc->gfx.dcl.con, false);
> >   }
> >   }
> > @@ -682,6 +685,22 @@ static const DisplayGLCtxOps egl_ctx_ops = {
> >   static void gd_change_runstate(void *opaque, bool running,
> > RunState state)
> >   {
> >   GtkDisplayState *s = opaque;
> > +QemuDmaBuf *dmabuf;
> > +int i;
> > +
> > +if (state == RUN_STATE_SAVE_VM) {
> > +for (i = 0; i < s->nb_vcs; i++) {
> > +VirtualConsole *vc = >vc[i];
> > +dmabuf = vc->gfx.guest_fb.dmabuf;
> > +if (dmabuf && qemu_dmabuf_get_fence_fd(dmabuf) >= 0) {
> > +/* wait for the rendering to be completed */
> > +eglClientWaitSync(qemu_egl_display,
> > +  qemu_dmabuf_get_sync(dmabuf),
> > +  EGL_SYNC_FLUSH_COMMANDS_BIT_KHR,
> > +  10);
> >
> >
> >   I don't think adding waiting points in the migration path is
> > appropriate. Perhaps once you explain the actual issue, it will be
> > easier to help.
> >
> > +}
> > +}
> > +}
> >
> >   gd_update_caption(s);
> >   }
> > --
> > 2.34.1
> >
> >
> >
> >
> > --
> > Marc-André Lureau
>
>

-- 
Marc-André Lureau


Re: [RFC PATCH v2 0/2] ui/gtk: Introduce new param - Connectors

2024-06-05 Thread Marc-André Lureau
Hi

On Tue, Jun 4, 2024 at 9:59 PM Kim, Dongwon  wrote:

> Hi Marc-André,
>
> On 6/4/2024 3:37 AM, Marc-André Lureau wrote:
> > Hi
> >
> > On Fri, May 31, 2024 at 11:00 PM  > <mailto:dongwon@intel.com>> wrote:
> >
> > From: Dongwon Kim  dongwon@intel.com>>
> >
> > This patch series is a replacement of
> > https://mail.gnu.org/archive/html/qemu-devel/2023-06/msg03989.html
> > <https://mail.gnu.org/archive/html/qemu-devel/2023-06/msg03989.html>
> >
> > There is a need, expressed by several users, to assign ownership of
> one
> > or more physical monitors/connectors to individual guests. This
> creates
> > a clear notion of which guest's contents are being displayed on any
> > given
> > monitor. Given that there is always a display server/compositor
> running
> > on the host, monitor ownership can never truly be transferred to
> guests.
> > However, the closest approximation is to request the host compositor
> to
> > fullscreen the guest's windows on individual monitors. This allows
> for
> > various configurations, such as displaying four different guests'
> > windows
> > on four different monitors, a single guest's windows (or virtual
> > consoles)
> > on four monitors, or any similar combination.
> >
> > This patch series attempts to accomplish this by introducing a new
> > parameter named "connector" to assign monitors to the GFX VCs
> associated
> > with a guest. If the assigned monitor is not connected, the guest's
> > window
> > will not be displayed, similar to how a host compositor behaves when
> > connectors are not connected. Once the monitor is hot-plugged, the
> > guest's
> > window(s) will be positioned on the assigned monitor.
> >
> > Usage example:
> >
> > -display gtk,gl=on,connectors=DP-1:eDP-1:HDMI-2...
> >
> > In this example, the first graphics virtual console will be placed
> > on the
> > DP-1 display, the second on eDP-1, and the third on HDMI-2.
> >
> >
> > Unfortunately, this approach with GTK is doomed. gtk4 dropped the
> > gtk_window_set_position() altogether.
>
> Do you mean we have a plan to lift GTK version in QEMU? Are we going to
> lose all GTK3 specific features?
>

No concrete plan, no. But eventually GTK3 will go away some day.

fwiw, I wish QEMU wouldn't have N built-in UIs/Spice/VNC, but different
projects elsewhere using -display dbus. There is
https://gitlab.gnome.org/GNOME/libmks or
https://gitlab.com/marcandre.lureau/qemu-display gtk4 efforts.


> >
> > It's not even clear how the different monitors/outputs/connectors are
> > actually named, whether they are stable etc (not mentioning the
> > portability).
> >
> > Window placement & geometry is a job for the compositor. Can you discuss
> > this issue with GTK devs & the compositor you are targeting?
>
> I guess you are talking about wayland compositor. We are mainly using
> Xorg on the host and this feature works pretty good on it. I am
>

Xorg may not be going away soon, but it's used less and less. As one of the
developers, I am no longer running/testing it for a long time. I wish we
would just drop its support tbh.

wondering if we limit the feature to Xorg case or adding some warning
> messages with error return in case any of parts is not working?
> (like the warning message I added
>
> +model = gdk_monitor_get_model(monitor);
> +if (!model) {
> +g_warning("retrieving connector name using\n"
> +  "gdk_monitor_get_model isn't supported\n"
> +  "please do not use connectors param in\n"
> +  "current environment\n");
> +return -1;
> +}
> )
>

Is it really worth maintaining this upstream if we know it will only work
for a diminishing fraction of users?



-- 
Marc-André Lureau


Re: [PATCH v13 10/13] virtio-gpu: Support suspension of commands processing

2024-06-04 Thread Marc-André Lureau
Hi

On Mon, May 27, 2024 at 7:03 AM Dmitry Osipenko <
dmitry.osipe...@collabora.com> wrote:

> Check whether command processing has been finished; otherwise, stop
> processing commands and retry the command again next time. This allows
> us to support asynchronous execution of non-fenced commands needed for
> unmapping host blobs safely.
>
> Suggested-by: Akihiko Odaki 
> Signed-off-by: Dmitry Osipenko 
> ---
>  hw/display/virtio-gpu.c | 5 +
>  1 file changed, 5 insertions(+)
>
> diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
> index f3d2def9a49f..8e05a2d0c7c5 100644
> --- a/hw/display/virtio-gpu.c
> +++ b/hw/display/virtio-gpu.c
> @@ -1054,6 +1054,11 @@ void virtio_gpu_process_cmdq(VirtIOGPU *g)
>  /* process command */
>  vgc->process_cmd(g, cmd);
>
> +/* command suspended */
> +if (!cmd->finished && !(cmd->cmd_hdr.flags &
> VIRTIO_GPU_FLAG_FENCE)) {
>

Since this is not tracked in "inflight" debugging, it would be worth adding
a trace for this early break.

Btw, if you could replace the fprintf below with a trace as well, this
would be a nice cleanup too



> +break;
> +}
> +
>  QTAILQ_REMOVE(>cmdq, cmd, next);
>      if (virtio_gpu_stats_enabled(g->parent_obj.conf)) {
>  g->stats.requests++;
> --
> 2.44.0
>
>

-- 
Marc-André Lureau


Re: [PATCH v13 09/13] virtio-gpu: Support blob scanout using dmabuf fd

2024-06-04 Thread Marc-André Lureau
> +fb.format = virtio_gpu_get_pixman_format(ss.format);
> +if (!fb.format) {
> +qemu_log_mask(LOG_GUEST_ERROR, "%s: pixel format not supported
> %d\n",
> +  __func__, ss.format);
> +cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
> +return;
> +}
> +
> +fb.bytes_pp = DIV_ROUND_UP(PIXMAN_FORMAT_BPP(fb.format), 8);
> +fb.width = ss.width;
> +fb.height = ss.height;
> +fb.stride = ss.strides[0];
> +fb.offset = ss.offsets[0] + ss.r.x * fb.bytes_pp + ss.r.y * fb.stride;
> +
> +fbend = fb.offset;
> +fbend += fb.stride * (ss.r.height - 1);
> +fbend += fb.bytes_pp * ss.r.width;
> +if (fbend > res->base.blob_size) {
> +qemu_log_mask(LOG_GUEST_ERROR, "%s: fb end out of range\n",
> +  __func__);
> +cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
> +return;
> +}
> +
> +g->parent_obj.enable = 1;
> +if (virtio_gpu_update_dmabuf(g, ss.scanout_id, >base, ,
> )) {
> +qemu_log_mask(LOG_GUEST_ERROR, "%s: failed to update dmabuf\n",
> +  __func__);
> +cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
> +return;
> +}
> +
> +virtio_gpu_update_scanout(g, ss.scanout_id, >base, , );
> +}
> +#endif /* HAVE_VIRGL_RESOURCE_BLOB */
> +
>  void virtio_gpu_virgl_process_cmd(VirtIOGPU *g,
>struct virtio_gpu_ctrl_command *cmd)
>  {
> @@ -575,6 +679,11 @@ void virtio_gpu_virgl_process_cmd(VirtIOGPU *g,
>  case VIRTIO_GPU_CMD_GET_EDID:
>  virtio_gpu_get_edid(g, cmd);
>  break;
> +#ifdef HAVE_VIRGL_RESOURCE_BLOB
> +case VIRTIO_GPU_CMD_SET_SCANOUT_BLOB:
> +virgl_cmd_set_scanout_blob(g, cmd);
> +break;
> +#endif /* HAVE_VIRGL_RESOURCE_BLOB */
>  default:
>  cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
>  break;
> diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
> index 672279e57f3f..f3d2def9a49f 100644
> --- a/hw/display/virtio-gpu.c
> +++ b/hw/display/virtio-gpu.c
> @@ -380,7 +380,7 @@ static void virtio_gpu_resource_create_blob(VirtIOGPU
> *g,
>  QTAILQ_INSERT_HEAD(>reslist, res, next);
>  }
>
> -static void virtio_gpu_disable_scanout(VirtIOGPU *g, int scanout_id)
> +void virtio_gpu_disable_scanout(VirtIOGPU *g, int scanout_id)
>  {
>  struct virtio_gpu_scanout *scanout =
> >parent_obj.scanout[scanout_id];
>  struct virtio_gpu_simple_resource *res;
> @@ -597,11 +597,11 @@ static void virtio_unref_resource(pixman_image_t
> *image, void *data)
>  pixman_image_unref(data);
>  }
>
> -static void virtio_gpu_update_scanout(VirtIOGPU *g,
> -  uint32_t scanout_id,
> -  struct virtio_gpu_simple_resource
> *res,
> -  struct virtio_gpu_framebuffer *fb,
> -  struct virtio_gpu_rect *r)
> +void virtio_gpu_update_scanout(VirtIOGPU *g,
> +   uint32_t scanout_id,
> +   struct virtio_gpu_simple_resource *res,
> +   struct virtio_gpu_framebuffer *fb,
> +   struct virtio_gpu_rect *r)
>  {
>  struct virtio_gpu_simple_resource *ores;
>  struct virtio_gpu_scanout *scanout;
> diff --git a/include/hw/virtio/virtio-gpu.h
> b/include/hw/virtio/virtio-gpu.h
> index 2faeda6f6abe..0bfdfd91db46 100644
> --- a/include/hw/virtio/virtio-gpu.h
> +++ b/include/hw/virtio/virtio-gpu.h
> @@ -338,6 +338,13 @@ int virtio_gpu_update_dmabuf(VirtIOGPU *g,
>   struct virtio_gpu_framebuffer *fb,
>   struct virtio_gpu_rect *r);
>
> +void virtio_gpu_update_scanout(VirtIOGPU *g,
> +   uint32_t scanout_id,
> +   struct virtio_gpu_simple_resource *res,
> +   struct virtio_gpu_framebuffer *fb,
> +   struct virtio_gpu_rect *r);
> +void virtio_gpu_disable_scanout(VirtIOGPU *g, int scanout_id);
> +
>  /* virtio-gpu-3d.c */
>  void virtio_gpu_virgl_process_cmd(VirtIOGPU *g,
>struct virtio_gpu_ctrl_command *cmd);
> diff --git a/meson.build b/meson.build
> index 65fddfbbc3a7..e753da4c76c3 100644
> --- a/meson.build
> +++ b/meson.build
> @@ -2311,6 +2311,7 @@ config_host_data.set('CONFIG_VNC_SASL', sasl.found())
>  if virgl.version().version_compare('>=1.0.0')
>config_host_data.set('HAVE_VIRGL_D3D_INFO_EXT', 1)
>config_host_data.set('HAVE_VIRGL_CONTEXT_CREATE_WITH_FLAGS', 1)
> +  config_host_data.set('HAVE_VIRGL_RESOURCE_BLOB', 1)
>

Instead of accumulating various #define values, we could simply have
HAVE_VIRGL1 or something..

Alternatively,  virgl.version().version_compare('>=1.0.1') and use #if
VIRGL_MAJOR_VERSION >= 1 in the code.

(the VIRGL_CHECK_VERSION macro is borked, it needs a 1.0.2 release)

-- 
Marc-André Lureau


Re: [PATCH v13 04/13] virtio-gpu: Unrealize GL device

2024-06-04 Thread Marc-André Lureau
Hi

On Mon, May 27, 2024 at 7:03 AM Dmitry Osipenko <
dmitry.osipe...@collabora.com> wrote:

> Even though GL GPU doesn't support hotplugging today, free virgl
> resources when GL device is unrealized. For consistency.
>
> Signed-off-by: Dmitry Osipenko 
> ---
>  hw/display/virtio-gpu-gl.c | 13 +
>  hw/display/virtio-gpu-virgl.c  | 11 +++
>  include/hw/virtio/virtio-gpu.h |  1 +
>  3 files changed, 25 insertions(+)
>
> diff --git a/hw/display/virtio-gpu-gl.c b/hw/display/virtio-gpu-gl.c
> index 38a2b1bd3916..7978b2985e17 100644
> --- a/hw/display/virtio-gpu-gl.c
> +++ b/hw/display/virtio-gpu-gl.c
> @@ -149,6 +149,18 @@ static Property virtio_gpu_gl_properties[] = {
>  DEFINE_PROP_END_OF_LIST(),
>  };
>
> +static void virtio_gpu_gl_device_unrealize(DeviceState *qdev)
> +{
> +VirtIOGPU *g = VIRTIO_GPU(qdev);
> +VirtIOGPUGL *gl = VIRTIO_GPU_GL(qdev);
> +
> +if (gl->renderer_state >= RS_INITED) {
> +virtio_gpu_virgl_deinit(g);
>

The extra function seems unnecessary.


> +}
> +
> +gl->renderer_state = RS_START;
> +}
> +
>  static void virtio_gpu_gl_class_init(ObjectClass *klass, void *data)
>  {
>  DeviceClass *dc = DEVICE_CLASS(klass);
> @@ -162,6 +174,7 @@ static void virtio_gpu_gl_class_init(ObjectClass
> *klass, void *data)
>  vgc->update_cursor_data = virtio_gpu_gl_update_cursor_data;
>
>  vdc->realize = virtio_gpu_gl_device_realize;
> +vdc->unrealize = virtio_gpu_gl_device_unrealize;
>  vdc->reset = virtio_gpu_gl_reset;
>  device_class_set_props(dc, virtio_gpu_gl_properties);
>  }
> diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
> index fa0da8f5c7f1..66c4aab9b283 100644
> --- a/hw/display/virtio-gpu-virgl.c
> +++ b/hw/display/virtio-gpu-virgl.c
> @@ -669,3 +669,14 @@ int virtio_gpu_virgl_get_num_capsets(VirtIOGPU *g)
>
>  return capset2_max_ver ? 2 : 1;
>  }
> +
> +void virtio_gpu_virgl_deinit(VirtIOGPU *g)
> +{
> +VirtIOGPUGL *gl = VIRTIO_GPU_GL(g);
> +
> +if (virtio_gpu_stats_enabled(g->parent_obj.conf)) {
> +timer_free(gl->print_stats);
> +}
> +timer_free(gl->fence_poll);
> +virgl_renderer_cleanup(NULL);
> +}
> diff --git a/include/hw/virtio/virtio-gpu.h
> b/include/hw/virtio/virtio-gpu.h
> index 6e71d799e5da..2faeda6f6abe 100644
> --- a/include/hw/virtio/virtio-gpu.h
> +++ b/include/hw/virtio/virtio-gpu.h
> @@ -345,6 +345,7 @@ void virtio_gpu_virgl_fence_poll(VirtIOGPU *g);
>  void virtio_gpu_virgl_reset_scanout(VirtIOGPU *g);
>  void virtio_gpu_virgl_reset(VirtIOGPU *g);
>  int virtio_gpu_virgl_init(VirtIOGPU *g);
> +void virtio_gpu_virgl_deinit(VirtIOGPU *g);
>  int virtio_gpu_virgl_get_num_capsets(VirtIOGPU *g);
>
>  #endif
> --
> 2.44.0
>
>

-- 
Marc-André Lureau


Re: [PATCH v13 03/13] virtio-gpu: Handle virtio_gpu_virgl_init() failure

2024-06-04 Thread Marc-André Lureau
Hi

On Mon, May 27, 2024 at 7:03 AM Dmitry Osipenko <
dmitry.osipe...@collabora.com> wrote:

> virtio_gpu_virgl_init() may fail, leading to a further Qemu crash
> because Qemu assumes it never fails. Check virtio_gpu_virgl_init()
> return code and don't execute virtio commands on error. Failed
> virtio_gpu_virgl_init() will result in a timed out virtio commands
> for a guest OS.
>
> Signed-off-by: Dmitry Osipenko 
> ---
>  hw/display/virtio-gpu-gl.c | 29 +
>  include/hw/virtio/virtio-gpu.h | 11 +--
>  2 files changed, 30 insertions(+), 10 deletions(-)
>
> diff --git a/hw/display/virtio-gpu-gl.c b/hw/display/virtio-gpu-gl.c
> index e06be60dfbfc..38a2b1bd3916 100644
> --- a/hw/display/virtio-gpu-gl.c
> +++ b/hw/display/virtio-gpu-gl.c
> @@ -29,9 +29,14 @@ static void virtio_gpu_gl_update_cursor_data(VirtIOGPU
> *g,
>   struct virtio_gpu_scanout *s,
>   uint32_t resource_id)
>  {
> +VirtIOGPUGL *gl = VIRTIO_GPU_GL(g);
>  uint32_t width, height;
>  uint32_t pixels, *data;
>
> +if (gl->renderer_state != RS_INITED) {
> +return;
> +}
> +
>  data = virgl_renderer_get_cursor_data(resource_id, , );
>  if (!data) {
>  return;
> @@ -65,13 +70,21 @@ static void virtio_gpu_gl_handle_ctrl(VirtIODevice
> *vdev, VirtQueue *vq)
>  return;
>  }
>
> -if (!gl->renderer_inited) {
> -virtio_gpu_virgl_init(g);
> -gl->renderer_inited = true;
> -}
> -if (gl->renderer_reset) {
> -gl->renderer_reset = false;
> +switch (gl->renderer_state) {
> +case RS_RESET:
>  virtio_gpu_virgl_reset(g);
> +/* fallthrough */
> +case RS_START:
> +if (virtio_gpu_virgl_init(g)) {
> +gl->renderer_state = RS_INIT_FAILED;
> +} else {
> +gl->renderer_state = RS_INITED;
> +}
> +break;
> +case RS_INIT_FAILED:
> +return;
> +case RS_INITED:
> +break;
>  }
>
>
This still lets it go through the cmd processing after setting
gl->renderer_state = RS_INIT_FAILED, the first time.


>  cmd = virtqueue_pop(vq, sizeof(struct virtio_gpu_ctrl_command));
> @@ -98,9 +111,9 @@ static void virtio_gpu_gl_reset(VirtIODevice *vdev)
>   * GL functions must be called with the associated GL context in main
>   * thread, and when the renderer is unblocked.
>   */
> -if (gl->renderer_inited && !gl->renderer_reset) {
> +if (gl->renderer_state == RS_INITED) {
>  virtio_gpu_virgl_reset_scanout(g);
> -gl->renderer_reset = true;
> +gl->renderer_state = RS_RESET;
>  }
>  }
>
> diff --git a/include/hw/virtio/virtio-gpu.h
> b/include/hw/virtio/virtio-gpu.h
> index 7ff989a45a5c..6e71d799e5da 100644
> --- a/include/hw/virtio/virtio-gpu.h
> +++ b/include/hw/virtio/virtio-gpu.h
> @@ -224,11 +224,18 @@ struct VirtIOGPUClass {
>   Error **errp);
>  };
>
> +/* VirtIOGPUGL renderer states */
> +typedef enum {
> +RS_START,   /* starting state */
> +RS_INIT_FAILED, /* failed initialisation */
> +RS_INITED,  /* initialised and working */
> +RS_RESET,   /* inited and reset pending, moves to start after
> reset */
> +} RenderState;
> +
>  struct VirtIOGPUGL {
>  struct VirtIOGPU parent_obj;
>
> -bool renderer_inited;
> -bool renderer_reset;
> +RenderState renderer_state;
>
>  QEMUTimer *fence_poll;
>  QEMUTimer *print_stats;
> --
> 2.44.0
>
>

-- 
Marc-André Lureau


Re: [PATCH] ui/gtk: Wait until the current guest frame is rendered before switching to RUN_STATE_SAVE_VM

2024-06-04 Thread Marc-André Lureau
Hi

On Thu, May 30, 2024 at 2:44 AM  wrote:

> From: Dongwon 
>
> Make sure rendering of the current frame is finished before switching
> the run state to RUN_STATE_SAVE_VM by waiting for egl-sync object to be
> signaled.
>

Can you expand on what this solves?


>
> Cc: Marc-André Lureau 
> Cc: Vivek Kasireddy 
> Signed-off-by: Dongwon Kim 
> ---
>  ui/egl-helpers.c |  2 --
>  ui/gtk.c | 19 +++
>  2 files changed, 19 insertions(+), 2 deletions(-)
>
> diff --git a/ui/egl-helpers.c b/ui/egl-helpers.c
> index 99b2ebbe23..dafeb36074 100644
> --- a/ui/egl-helpers.c
> +++ b/ui/egl-helpers.c
> @@ -396,8 +396,6 @@ void egl_dmabuf_create_fence(QemuDmaBuf *dmabuf)
>  fence_fd = eglDupNativeFenceFDANDROID(qemu_egl_display,
>sync);
>  qemu_dmabuf_set_fence_fd(dmabuf, fence_fd);
> -eglDestroySyncKHR(qemu_egl_display, sync);
> -qemu_dmabuf_set_sync(dmabuf, NULL);
>

If this function is called multiple times, it will now set a new fence_fd
each time, and potentially leak older fd. Maybe it could first check if a
fence_fd exists instead.

 }
>  }
>
> diff --git a/ui/gtk.c b/ui/gtk.c
> index 93b13b7a30..cf0dd6abed 100644
> --- a/ui/gtk.c
> +++ b/ui/gtk.c
> @@ -600,9 +600,12 @@ void gd_hw_gl_flushed(void *vcon)
>
>  fence_fd = qemu_dmabuf_get_fence_fd(dmabuf);
>  if (fence_fd >= 0) {
> +void *sync = qemu_dmabuf_get_sync(dmabuf);
>  qemu_set_fd_handler(fence_fd, NULL, NULL, NULL);
>  close(fence_fd);
>  qemu_dmabuf_set_fence_fd(dmabuf, -1);
> +eglDestroySyncKHR(qemu_egl_display, sync);
> +qemu_dmabuf_set_sync(dmabuf, NULL);
>  graphic_hw_gl_block(vc->gfx.dcl.con, false);
>  }
>  }
> @@ -682,6 +685,22 @@ static const DisplayGLCtxOps egl_ctx_ops = {
>  static void gd_change_runstate(void *opaque, bool running, RunState state)
>  {
>  GtkDisplayState *s = opaque;
> +QemuDmaBuf *dmabuf;
> +int i;
> +
> +if (state == RUN_STATE_SAVE_VM) {
> +for (i = 0; i < s->nb_vcs; i++) {
> +VirtualConsole *vc = >vc[i];
> +dmabuf = vc->gfx.guest_fb.dmabuf;
> +if (dmabuf && qemu_dmabuf_get_fence_fd(dmabuf) >= 0) {
> +/* wait for the rendering to be completed */
> +eglClientWaitSync(qemu_egl_display,
> +  qemu_dmabuf_get_sync(dmabuf),
> +  EGL_SYNC_FLUSH_COMMANDS_BIT_KHR,
> +  10);
>

 I don't think adding waiting points in the migration path is appropriate.
Perhaps once you explain the actual issue, it will be easier to help.

+}
> +}
> +}
>
>  gd_update_caption(s);
>  }
> --
> 2.34.1
>
>
>

-- 
Marc-André Lureau


Re: [RFC PATCH v2 0/2] ui/gtk: Introduce new param - Connectors

2024-06-04 Thread Marc-André Lureau
Hi

On Fri, May 31, 2024 at 11:00 PM  wrote:

> From: Dongwon Kim 
>
> This patch series is a replacement of
> https://mail.gnu.org/archive/html/qemu-devel/2023-06/msg03989.html
>
> There is a need, expressed by several users, to assign ownership of one
> or more physical monitors/connectors to individual guests. This creates
> a clear notion of which guest's contents are being displayed on any given
> monitor. Given that there is always a display server/compositor running
> on the host, monitor ownership can never truly be transferred to guests.
> However, the closest approximation is to request the host compositor to
> fullscreen the guest's windows on individual monitors. This allows for
> various configurations, such as displaying four different guests' windows
> on four different monitors, a single guest's windows (or virtual consoles)
> on four monitors, or any similar combination.
>
> This patch series attempts to accomplish this by introducing a new
> parameter named "connector" to assign monitors to the GFX VCs associated
> with a guest. If the assigned monitor is not connected, the guest's window
> will not be displayed, similar to how a host compositor behaves when
> connectors are not connected. Once the monitor is hot-plugged, the guest's
> window(s) will be positioned on the assigned monitor.
>
> Usage example:
>
> -display gtk,gl=on,connectors=DP-1:eDP-1:HDMI-2...
>
> In this example, the first graphics virtual console will be placed on the
> DP-1 display, the second on eDP-1, and the third on HDMI-2.
>
>
Unfortunately, this approach with GTK is doomed. gtk4 dropped the
gtk_window_set_position() altogether.

It's not even clear how the different monitors/outputs/connectors are
actually named, whether they are stable etc (not mentioning the
portability).

Window placement & geometry is a job for the compositor. Can you discuss
this issue with GTK devs & the compositor you are targeting?

-- 
Marc-André Lureau


Re: [PATCH v2 1/3] stdvga: fix screen blanking

2024-06-04 Thread Marc-André Lureau
Hi

On Mon, Jun 3, 2024 at 7:18 PM Gerd Hoffmann  wrote:
>
> In case the display surface uses a shared buffer (i.e. uses vga vram
> directly instead of a shadow) go unshare the buffer before clearing it.
>
> This avoids vga memory corruption, which in turn fixes unblanking not
> working properly with X11.
>
> Cc: qemu-sta...@nongnu.org
> Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2067
> Signed-off-by: Gerd Hoffmann 
> ---
>  hw/display/vga.c | 6 ++
>  1 file changed, 6 insertions(+)
>
> diff --git a/hw/display/vga.c b/hw/display/vga.c
> index 30facc6c8e33..474b6b14c327 100644
> --- a/hw/display/vga.c
> +++ b/hw/display/vga.c
> @@ -1762,6 +1762,12 @@ static void vga_draw_blank(VGACommonState *s, int 
> full_update)
>  if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
>  return;
>
> +if (is_buffer_shared(surface)) {

Perhaps the suggestion to rename the function (in the following patch)
should instead be surface_is_allocated() ? that would match the actual
flag check. But callers would have to ! the result. Wdyt?

> +/* unshare buffer, otherwise the blanking corrupts vga vram */
> +surface = qemu_create_displaysurface(s->last_scr_width, 
> s->last_scr_height);
> +dpy_gfx_replace_surface(s->con, surface);

Ok, this looks safer than calling "resize".

thanks

> +}
> +
>  w = s->last_scr_width * surface_bytes_per_pixel(surface);
>  d = surface_data(surface);
>  for(i = 0; i < s->last_scr_height; i++) {
> --
> 2.45.1
>




Re: [PATCH v2] chardev: add path option for pty backend

2024-06-03 Thread Marc-André Lureau
On Tue, Jun 4, 2024 at 1:22 AM Octavian Purdila  wrote:
>
> Add path option to the pty char backend which will create a symbolic
> link to the given path that points to the allocated PTY.
>
> This avoids having to make QMP or HMP monitor queries to find out what
> the new PTY device path is.
>
> Based on patch from Paulo Neves:
>
> https://patchew.org/QEMU/1548509635-15776-1-git-send-email-ptsne...@gmail.com/
>
> Tested with the following invocations that the link is created and
> removed when qemu stops:
>
>   qemu-system-x86_64 -nodefaults -mon chardev=compat_monitor \
>   -chardev pty,path=test,id=compat_monitor0
>
>   qemu-system-x86_64 -nodefaults -monitor pty:test
>
> Also tested that when a link path is not passed invocations still work, e.g.:
>
>   qemu-system-x86_64 -monitor pty
>
> Co-authored-by: Paulo Neves 
> Signed-off-by: Paulo Neves 
> [OP: rebase and address original patch review comments]
> Signed-off-by: Octavian Purdila 
> ---
> Changes since v1:
>
>  * Keep the original Signed-off-by from Paulo and add one line
> description with further changes
>
>  * Update commit message with justification for why the new
> functionality is useful
>
>  * Don't close master_fd when symlink creation fails to avoid double
> close
>
>  * Update documentation for clarity
>
>  chardev/char-pty.c | 33 +
>  chardev/char.c |  5 +
>  qapi/char.json |  4 ++--
>  qemu-options.hx| 24 ++--
>  4 files changed, 58 insertions(+), 8 deletions(-)
>
> diff --git a/chardev/char-pty.c b/chardev/char-pty.c
> index cc2f7617fe..b5a4eb59fc 100644
> --- a/chardev/char-pty.c
> +++ b/chardev/char-pty.c
> @@ -29,6 +29,7 @@
>  #include "qemu/sockets.h"
>  #include "qemu/error-report.h"
>  #include "qemu/module.h"
> +#include "qemu/option.h"
>  #include "qemu/qemu-print.h"
>
>  #include "chardev/char-io.h"
> @@ -41,6 +42,7 @@ struct PtyChardev {
>
>  int connected;
>  GSource *timer_src;
> +char *symlink_path;
>  };
>  typedef struct PtyChardev PtyChardev;
>
> @@ -204,6 +206,12 @@ static void char_pty_finalize(Object *obj)
>  Chardev *chr = CHARDEV(obj);
>  PtyChardev *s = PTY_CHARDEV(obj);
>
> +/* unlink symlink */
> +if (s->symlink_path) {
> +unlink(s->symlink_path);
> +g_free(s->symlink_path);
> +}
> +
>  pty_chr_state(chr, 0);
>  object_unref(OBJECT(s->ioc));
>  pty_chr_timer_cancel(s);
> @@ -330,6 +338,7 @@ static void char_pty_open(Chardev *chr,
>  int master_fd, slave_fd;
>  char pty_name[PATH_MAX];
>  char *name;
> +char *symlink_path = backend->u.pty.data->device;
>
>  master_fd = qemu_openpty_raw(_fd, pty_name);
>  if (master_fd < 0) {
> @@ -354,12 +363,36 @@ static void char_pty_open(Chardev *chr,
>  g_free(name);
>  s->timer_src = NULL;
>  *be_opened = false;
> +
> +/* create symbolic link */
> +if (symlink_path) {
> +int res = symlink(pty_name, symlink_path);
> +
> +if (res != 0) {
> +error_setg_errno(errp, errno, "Failed to create PTY symlink");
> +} else {
> +s->symlink_path = g_strdup(symlink_path);
> +}
> +}
> +}
> +
> +static void char_pty_parse(QemuOpts *opts, ChardevBackend *backend,
> +   Error **errp)
> +{
> +const char *path = qemu_opt_get(opts, "path");
> +ChardevHostdev *dev;
> +
> +backend->type = CHARDEV_BACKEND_KIND_PTY;
> +dev = backend->u.pty.data = g_new0(ChardevHostdev, 1);
> +qemu_chr_parse_common(opts, qapi_ChardevHostdev_base(dev));
> +dev->device = path ? g_strdup(path) : NULL;

minor nit, g_strdup(NULL) returns NULL. Get rid of "?:" if you send a v3.

>  }
>
>  static void char_pty_class_init(ObjectClass *oc, void *data)
>  {
>  ChardevClass *cc = CHARDEV_CLASS(oc);
>
> +cc->parse = char_pty_parse;
>  cc->open = char_pty_open;
>  cc->chr_write = char_pty_chr_write;
>  cc->chr_update_read_handler = pty_chr_update_read_handler;
> diff --git a/chardev/char.c b/chardev/char.c
> index 3c43fb1278..404c6b8a4f 100644
> --- a/chardev/char.c
> +++ b/chardev/char.c
> @@ -428,6 +428,11 @@ QemuOpts *qemu_chr_parse_compat(const char *label, const 
> char *filename,
>  qemu_opt_set(opts, "path", p, _abort);
>  return opts;
>  }
> +if (strstart(filename, "pty:", )) {
> +qemu_opt_set(opts, "backend", "pty", _abort);
> +qemu_opt_set(opts, "path", p, _abort);
> +return opts;
> +}
>  if (strstart(filename, "tcp:", ) ||
>  strstart(filename, "telnet:", ) ||
>  strstart(filename, "tn3270:", ) ||
> diff --git a/qapi/char.json b/qapi/char.json
> index 777dde55d9..4c74bfc437 100644
> --- a/qapi/char.json
> +++ b/qapi/char.json
> @@ -509,7 +509,7 @@
>  ##
>  # @ChardevHostdevWrapper:
>  #
> -# @data: Configuration info for device and pipe chardevs
> +# @data: Configuration info for device, pty and pipe chardevs
>  #
>  # Since: 1.4
>  ##
> @@ 

Re: [PATCH v2] chardev: add path option for pty backend

2024-06-03 Thread Marc-André Lureau
On Tue, Jun 4, 2024 at 1:22 AM Octavian Purdila  wrote:
>
> Add path option to the pty char backend which will create a symbolic
> link to the given path that points to the allocated PTY.
>
> This avoids having to make QMP or HMP monitor queries to find out what
> the new PTY device path is.
>
> Based on patch from Paulo Neves:
>
> https://patchew.org/QEMU/1548509635-15776-1-git-send-email-ptsne...@gmail.com/
>
> Tested with the following invocations that the link is created and
> removed when qemu stops:
>
>   qemu-system-x86_64 -nodefaults -mon chardev=compat_monitor \
>   -chardev pty,path=test,id=compat_monitor0
>
>   qemu-system-x86_64 -nodefaults -monitor pty:test
>
> Also tested that when a link path is not passed invocations still work, e.g.:
>
>   qemu-system-x86_64 -monitor pty
>
> Co-authored-by: Paulo Neves 
> Signed-off-by: Paulo Neves 
> [OP: rebase and address original patch review comments]
> Signed-off-by: Octavian Purdila 

Reviewed-by: Marc-André Lureau 

> ---
> Changes since v1:
>
>  * Keep the original Signed-off-by from Paulo and add one line
> description with further changes
>
>  * Update commit message with justification for why the new
> functionality is useful
>
>  * Don't close master_fd when symlink creation fails to avoid double
> close
>
>  * Update documentation for clarity
>
>  chardev/char-pty.c | 33 +
>  chardev/char.c |  5 +
>  qapi/char.json |  4 ++--
>  qemu-options.hx| 24 ++--
>  4 files changed, 58 insertions(+), 8 deletions(-)
>
> diff --git a/chardev/char-pty.c b/chardev/char-pty.c
> index cc2f7617fe..b5a4eb59fc 100644
> --- a/chardev/char-pty.c
> +++ b/chardev/char-pty.c
> @@ -29,6 +29,7 @@
>  #include "qemu/sockets.h"
>  #include "qemu/error-report.h"
>  #include "qemu/module.h"
> +#include "qemu/option.h"
>  #include "qemu/qemu-print.h"
>
>  #include "chardev/char-io.h"
> @@ -41,6 +42,7 @@ struct PtyChardev {
>
>  int connected;
>  GSource *timer_src;
> +char *symlink_path;
>  };
>  typedef struct PtyChardev PtyChardev;
>
> @@ -204,6 +206,12 @@ static void char_pty_finalize(Object *obj)
>  Chardev *chr = CHARDEV(obj);
>  PtyChardev *s = PTY_CHARDEV(obj);
>
> +/* unlink symlink */
> +if (s->symlink_path) {
> +unlink(s->symlink_path);
> +g_free(s->symlink_path);
> +}
> +
>  pty_chr_state(chr, 0);
>  object_unref(OBJECT(s->ioc));
>  pty_chr_timer_cancel(s);
> @@ -330,6 +338,7 @@ static void char_pty_open(Chardev *chr,
>  int master_fd, slave_fd;
>  char pty_name[PATH_MAX];
>  char *name;
> +char *symlink_path = backend->u.pty.data->device;
>
>  master_fd = qemu_openpty_raw(_fd, pty_name);
>  if (master_fd < 0) {
> @@ -354,12 +363,36 @@ static void char_pty_open(Chardev *chr,
>  g_free(name);
>  s->timer_src = NULL;
>  *be_opened = false;
> +
> +/* create symbolic link */
> +if (symlink_path) {
> +int res = symlink(pty_name, symlink_path);
> +
> +if (res != 0) {
> +error_setg_errno(errp, errno, "Failed to create PTY symlink");
> +} else {
> +s->symlink_path = g_strdup(symlink_path);
> +}
> +}
> +}
> +
> +static void char_pty_parse(QemuOpts *opts, ChardevBackend *backend,
> +   Error **errp)
> +{
> +const char *path = qemu_opt_get(opts, "path");
> +ChardevHostdev *dev;
> +
> +backend->type = CHARDEV_BACKEND_KIND_PTY;
> +dev = backend->u.pty.data = g_new0(ChardevHostdev, 1);
> +qemu_chr_parse_common(opts, qapi_ChardevHostdev_base(dev));
> +dev->device = path ? g_strdup(path) : NULL;
>  }
>
>  static void char_pty_class_init(ObjectClass *oc, void *data)
>  {
>  ChardevClass *cc = CHARDEV_CLASS(oc);
>
> +cc->parse = char_pty_parse;
>  cc->open = char_pty_open;
>  cc->chr_write = char_pty_chr_write;
>  cc->chr_update_read_handler = pty_chr_update_read_handler;
> diff --git a/chardev/char.c b/chardev/char.c
> index 3c43fb1278..404c6b8a4f 100644
> --- a/chardev/char.c
> +++ b/chardev/char.c
> @@ -428,6 +428,11 @@ QemuOpts *qemu_chr_parse_compat(const char *label, const 
> char *filename,
>  qemu_opt_set(opts, "path", p, _abort);
>  return opts;
>  }
> +if (strstart(filename, "pty:", )) {
> +qemu_opt_set(opts, "backend", "pty", _abort);
> +qemu_opt_set(op

Re: [PATCH] stdvga: fix screen blanking

2024-06-03 Thread Marc-André Lureau
Hi

On Mon, Jun 3, 2024 at 3:51 PM Gerd Hoffmann  wrote:

> On Mon, Jun 03, 2024 at 02:24:52PM GMT, Marc-André Lureau wrote:
> > Hi
> >
> > On Thu, May 30, 2024 at 3:05 PM Gerd Hoffmann  wrote:
> >
> > > In case the display surface uses a shared buffer (i.e. uses vga vram
> > > directly instead of a shadow) go unshare the buffer before clearing it.
> > >
> > > This avoids vga memory corruption, which in turn fixes unblanking not
> > > working properly with X11.
> > >
> > > Cc: qemu-sta...@nongnu.org
> > > Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2067
> > > Signed-off-by: Gerd Hoffmann 
> > > ---
> > >  hw/display/vga.c | 6 ++
> > >  1 file changed, 6 insertions(+)
> > >
> > > diff --git a/hw/display/vga.c b/hw/display/vga.c
> > > index 30facc6c8e33..34ab8eb9b745 100644
> > > --- a/hw/display/vga.c
> > > +++ b/hw/display/vga.c
> > > @@ -1762,6 +1762,12 @@ static void vga_draw_blank(VGACommonState *s,
> int
> > > full_update)
> > >  if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
> > >  return;
> > >
> > > +if (is_buffer_shared(surface)) {
> > >
> >
> > It might be a good time to rename this function. surface_is_borrowed() ?
>
> "shared" means memory shared between guest and host (typically vga vram).
>
>
In this context, but this is now confusing because we also have shared
memory surface support for win32.

static inline int is_buffer_shared(DisplaySurface *surface)
{
return !(surface->flags & QEMU_ALLOCATED_FLAG);
}

!allocated = the surface memory is not owned.


> I doubt using the term "borrowed" instead clarifies things much,
> especially as this isn't an rust-style "borrow" (which I guess you are
> referring to).  Nothing prevents the host from writing to the surface as
> the bug clearly shows.  Also qemu is a C project, so I wouldn't expect
> developers being familiar with rust semantics and terminology.
>
>
Borrowing is not a term specific to Rust :) (and you can have mutable
borrows btw)

 I'd rather use "shared" memory for IPC purposes.

The lack of surface_ function prefix is also annoying.


> > > +/* unshare buffer, otherwise the blanking corrupts vga vram */
> > > +qemu_console_resize(s->con, s->last_scr_width,
> > > s->last_scr_height);
> >
> > If we want to guarantee that a new surface is created, we should leave a
> > comment on qemu_console_resize(),
>
> I left the comment there exactly because it isn't obvious that the
> qemu_console_resize() will create a new (not shared) surface.  So not
> sure what exactly you are suggesting here?
>
>
I meant to document qemu_console_resize() function itself, as it would be
too easy to miss and break this case.


> > or perhaps make it take a new/alloc argument?
>
> Right now qemu_console_resize() does a bunch of checks to figure
> whenever it can take a shortcut (because width + height didn't change)
> or not.
>
> We could certainly pass a boolean in instead and have the caller decide
> that way.  Didn't check whenever that makes sense, and IMHO that is well
> beyond the scope of a 3-lines bugfix.
>
>kraxel@sirius ~/projects/qemu# git grep qemu_console_resize | wc -l
>35
>

Maybe introduce a new function then?



-- 
Marc-André Lureau


Re: [PATCH] chardev: add path option for pty backend

2024-06-03 Thread Marc-André Lureau
Hi

On Mon, Jun 3, 2024 at 4:23 PM Peter Maydell  wrote:
>
> On Fri, 31 May 2024 at 22:21, Octavian Purdila  wrote:
> >
> > Add path option to the pty char backend which will create a symbolic
> > link to the given path that points to the allocated PTY.
> >
> > Based on patch from Paulo Neves:
> >
> > https://patchew.org/QEMU/1548509635-15776-1-git-send-email-ptsne...@gmail.com/
> >
> > Tested with the following invocations that the link is created and
> > removed when qemu stops:
> >
> >   qemu-system-x86_64 -nodefaults -mon chardev=compat_monitor \
> >   -chardev pty,path=test,id=compat_monitor0
> >
> >   qemu-system-x86_64 -nodefaults -monitor pty:test
> >
> > Also tested that when a link path is not passed invocations still work, 
> > e.g.:
> >
> >   qemu-system-x86_64 -monitor pty
>
> Could we have some justification here for why the new
> functionality is useful, please? (e.g. what new use cases
> it permits).
>

It avoids the need to HMP/QMP query the allocated pty path. I don't
think there are other benefits.

> > --- a/qapi/char.json
> > +++ b/qapi/char.json
> > @@ -509,7 +509,7 @@
> >  ##
> >  # @ChardevHostdevWrapper:
> >  #
> > -# @data: Configuration info for device and pipe chardevs
> > +# @data: Configuration info for device, pty and pipe chardevs
> >  #
> >  # Since: 1.4
> >  ##
> > @@ -650,7 +650,7 @@
> >  'pipe': 'ChardevHostdevWrapper',
> >  'socket': 'ChardevSocketWrapper',
> >  'udp': 'ChardevUdpWrapper',
> > -'pty': 'ChardevCommonWrapper',
> > +'pty': 'ChardevHostdevWrapper',
> >  'null': 'ChardevCommonWrapper',
> >  'mux': 'ChardevMuxWrapper',
> >  'msmouse': 'ChardevCommonWrapper',
>
> Does this break QAPI compatibility?
>
> > diff --git a/qemu-options.hx b/qemu-options.hx
> > index 8ca7f34ef0..5eec194242 100644
> > --- a/qemu-options.hx
> > +++ b/qemu-options.hx
> > @@ -3569,7 +3569,7 @@ DEF("chardev", HAS_ARG, QEMU_OPTION_chardev,
> >  "-chardev 
> > console,id=id[,mux=on|off][,logfile=PATH][,logappend=on|off]\n"
> >  "-chardev 
> > serial,id=id,path=path[,mux=on|off][,logfile=PATH][,logappend=on|off]\n"
> >  #else
> > -"-chardev pty,id=id[,mux=on|off][,logfile=PATH][,logappend=on|off]\n"
> > +"-chardev 
> > pty,id=id[,path=path][,mux=on|off][,logfile=PATH][,logappend=on|off]\n"
> >  "-chardev 
> > stdio,id=id[,mux=on|off][,signal=on|off][,logfile=PATH][,logappend=on|off]\n"
> >  #endif
> >  #ifdef CONFIG_BRLAPI
> > @@ -3808,12 +3808,16 @@ The available backends are:
> >
> >  ``path`` specifies the name of the serial device to open.
> >
> > -``-chardev pty,id=id``
> > +``-chardev pty,id=id[,path=path]``
> >  Create a new pseudo-terminal on the host and connect to it. ``pty``
> >  does not take any options.
>
> We just added an option, so we should delete the line saying
> that it doesn't take any options :-)
>
> >
> >  ``pty`` is not available on Windows hosts.
> >
> > +``path`` specifies the symbolic link path to be created that
> > +points to the pty device.
>
> I think we could usefully make this a little less terse. Perhaps
>If ``path`` is specified, QEMU will create a symbolic link at
>that location which points to the new PTY device.
> ?
>
> thanks
> -- PMM
>




Re: [PATCH] chardev: add path option for pty backend

2024-06-03 Thread Marc-André Lureau
 @@
>  ##
>  # @ChardevHostdevWrapper:
>  #
> -# @data: Configuration info for device and pipe chardevs
> +# @data: Configuration info for device, pty and pipe chardevs
>  #
>  # Since: 1.4
>  ##
> @@ -650,7 +650,7 @@
>  'pipe': 'ChardevHostdevWrapper',
>  'socket': 'ChardevSocketWrapper',
>  'udp': 'ChardevUdpWrapper',
> -'pty': 'ChardevCommonWrapper',
> +'pty': 'ChardevHostdevWrapper',
>  'null': 'ChardevCommonWrapper',
>  'mux': 'ChardevMuxWrapper',
>  'msmouse': 'ChardevCommonWrapper',
> diff --git a/qemu-options.hx b/qemu-options.hx
> index 8ca7f34ef0..5eec194242 100644
> --- a/qemu-options.hx
> +++ b/qemu-options.hx
> @@ -3569,7 +3569,7 @@ DEF("chardev", HAS_ARG, QEMU_OPTION_chardev,
>  "-chardev
> console,id=id[,mux=on|off][,logfile=PATH][,logappend=on|off]\n"
>  "-chardev
> serial,id=id,path=path[,mux=on|off][,logfile=PATH][,logappend=on|off]\n"
>  #else
> -"-chardev pty,id=id[,mux=on|off][,logfile=PATH][,logappend=on|off]\n"
> +"-chardev
> pty,id=id[,path=path][,mux=on|off][,logfile=PATH][,logappend=on|off]\n"
>  "-chardev
> stdio,id=id[,mux=on|off][,signal=on|off][,logfile=PATH][,logappend=on|off]\n"
>  #endif
>  #ifdef CONFIG_BRLAPI
> @@ -3808,12 +3808,16 @@ The available backends are:
>
>  ``path`` specifies the name of the serial device to open.
>
> -``-chardev pty,id=id``
> +``-chardev pty,id=id[,path=path]``
>  Create a new pseudo-terminal on the host and connect to it. ``pty``
>  does not take any options.
>
>  ``pty`` is not available on Windows hosts.
>
> +``path`` specifies the symbolic link path to be created that
> +points to the pty device.
> +
> +
>  ``-chardev stdio,id=id[,signal=on|off]``
>  Connect to standard input and standard output of the QEMU process.
>
> @@ -4171,8 +4175,10 @@ SRST
>
>  vc:80Cx24C
>
> -``pty``
> -[Linux only] Pseudo TTY (a new PTY is automatically allocated)
> +``pty[:path]``
> +[Linux only] Pseudo TTY (a new PTY is automatically allocated).
> +Optionally a path can be given to create a symbolic link to
> +the allocated PTY.
>
>  ``none``
>  No device is allocated. Note that for machine types which
> --
> 2.45.1.288.g0e0cd299f1-goog
>
>
>
thanks

-- 
Marc-André Lureau


Re: [PATCH] stdvga: fix screen blanking

2024-06-03 Thread Marc-André Lureau
Hi

On Thu, May 30, 2024 at 3:05 PM Gerd Hoffmann  wrote:

> In case the display surface uses a shared buffer (i.e. uses vga vram
> directly instead of a shadow) go unshare the buffer before clearing it.
>
> This avoids vga memory corruption, which in turn fixes unblanking not
> working properly with X11.
>
> Cc: qemu-sta...@nongnu.org
> Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2067
> Signed-off-by: Gerd Hoffmann 
> ---
>  hw/display/vga.c | 6 ++
>  1 file changed, 6 insertions(+)
>
> diff --git a/hw/display/vga.c b/hw/display/vga.c
> index 30facc6c8e33..34ab8eb9b745 100644
> --- a/hw/display/vga.c
> +++ b/hw/display/vga.c
> @@ -1762,6 +1762,12 @@ static void vga_draw_blank(VGACommonState *s, int
> full_update)
>  if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
>  return;
>
> +if (is_buffer_shared(surface)) {
>

It might be a good time to rename this function. surface_is_borrowed() ?


> +/* unshare buffer, otherwise the blanking corrupts vga vram */
> +qemu_console_resize(s->con, s->last_scr_width,
> s->last_scr_height);
>

If we want to guarantee that a new surface is created, we should leave a
comment on qemu_console_resize(), or perhaps make it take a new/alloc
argument?

+surface = qemu_console_surface(s->con);
> +}
> +
>  w = s->last_scr_width * surface_bytes_per_pixel(surface);
>  d = surface_data(surface);
>  for(i = 0; i < s->last_scr_height; i++) {
> --
> 2.45.1
>
>
>
thanks

-- 
Marc-André Lureau


Re: [PULL 00/11] Ui patches

2024-05-15 Thread Marc-André Lureau
Hi

On Wed, May 15, 2024 at 2:29 PM Michael Tokarev  wrote:
>
> 14.05.2024 16:17, marcandre.lur...@redhat.com wrote:
> > 
> > UI: small fixes and improvements
> >
> > 
> >
> > Bernhard Beschow (1):
> >ui/sdl2: Allow host to power down screen
> >
> > Dongwon Kim (7):
> >ui/gtk: Draw guest frame at refresh cycle
> >ui/gtk: Check if fence_fd is equal to or greater than 0
> >ui/console: new dmabuf.h and dmabuf.c for QemuDmaBuf struct and
> >  helpers
> >ui/console: Use qemu_dmabuf_get_..() helpers instead
> >ui/console: Use qemu_dmabuf_set_..() helpers instead
> >ui/console: Use qemu_dmabuf_new() and free() helpers instead
> >ui/console: move QemuDmaBuf struct def to dmabuf.c
> >
> > Sergii Zasenko (1):
> >Allow UNIX socket option for VNC websocket
> >
> > hikalium (2):
> >ui/gtk: Add gd_motion_event trace event
> >ui/gtk: Fix mouse/motion event scaling issue with GTK display backend
>
>  From this list, it looks like
>
>ui/gtk: Draw guest frame at refresh cycle

I would allow a bit more time for this to be actually more widely tested.

Dongwon, wdyt?

>ui/gtk: Check if fence_fd is equal to or greater than 0  (questionable, 
> minor issue)

minor, but fine in stable too.

>ui/gtk: Fix mouse/motion event scaling issue with GTK display backend

ok for stable imho (even though I don't like that we don't support
hidpi correctly, as I described in the patch review)



Re: [PATCH v2 3/4] virtio-gpu: add x-vmstate-version

2024-05-14 Thread Marc-André Lureau
Hi

On Tue, May 14, 2024 at 8:35 AM Peter Xu  wrote:
>
> Hey, Marc-Andre,
>
> On Mon, May 13, 2024 at 11:19:04AM +0400, marcandre.lur...@redhat.com wrote:
> > diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
> > index ae831b6b3e..7f9fb5eacc 100644
> > --- a/hw/display/virtio-gpu.c
> > +++ b/hw/display/virtio-gpu.c
> > @@ -1234,7 +1234,8 @@ static int virtio_gpu_save(QEMUFile *f, void *opaque, 
> > size_t size,
> >  }
> >  qemu_put_be32(f, 0); /* end of list */
> >
> > -return vmstate_save_state(f, _virtio_gpu_scanouts, g, NULL);
> > +return vmstate_save_state_v(f, _virtio_gpu_scanouts, g,
> > +NULL, g->vmstate_version, NULL);
> >  }
> >
> >  static bool virtio_gpu_load_restore_mapping(VirtIOGPU *g,
> > @@ -1339,7 +1340,7 @@ static int virtio_gpu_load(QEMUFile *f, void *opaque, 
> > size_t size,
> >  }
> >
> >  /* load & apply scanout state */
> > -vmstate_load_state(f, _virtio_gpu_scanouts, g, 1);
> > +vmstate_load_state(f, _virtio_gpu_scanouts, g, 
> > g->vmstate_version);
>
> [sorry for a late response; attending a conf, and will reply to the v1
>  thread later for the other discussions..]
>
> These two changes shouldn't be needed if we go with the .field_exists()
> approach, am I right?  IIUC in that case we can keep the version 1 here and
> don't boost anything, because we relied on the machine versions.
>
> IIUC this might be the reason why we found 9.0 mahines are broken on
> migration.  E.g, IIUC my original patch should work for 9.0<->9.0 too.
>

Indeed, but for consistency, shouldn't it use the x-vmstate-version
value for the top-level VMSD save/load ?

Otherwise, it feels a bit odd that this x-vmstate-version is only used
for the nested "virtio-gpu-one-scanout" version.

Or perhaps we should rename it to x-scanout-vmstate-version ? wdyt


> Thanks,
>
> >
> >  return 0;
> >  }
> > @@ -1659,6 +1660,7 @@ static Property virtio_gpu_properties[] = {
> >  DEFINE_PROP_BIT("blob", VirtIOGPU, parent_obj.conf.flags,
> >  VIRTIO_GPU_FLAG_BLOB_ENABLED, false),
> >  DEFINE_PROP_SIZE("hostmem", VirtIOGPU, parent_obj.conf.hostmem, 0),
> > +DEFINE_PROP_UINT8("x-vmstate-version", VirtIOGPU, vmstate_version, 1),
> >  DEFINE_PROP_END_OF_LIST(),
> >  };
> >
> > --
> > 2.41.0.28.gd7d8841f67
> >
>
> --
> Peter Xu
>




Re: [PATCH v2 0/4] Fix "virtio-gpu: fix scanout migration post-load"

2024-05-13 Thread Marc-André Lureau
Hi Fiona

On Mon, May 13, 2024 at 4:56 PM Fiona Ebner  wrote:
>
> Hi,
>
> Am 13.05.24 um 09:19 schrieb marcandre.lur...@redhat.com:
> > From: Marc-André Lureau 
> >
> > Hi,
> >
> > The aforementioned patch breaks virtio-gpu device migrations for versions
> > pre-9.0/9.0, both forwards and backwards. Versioning of `VMS_STRUCT` is more
> > complex than it may initially appear, as evidenced in the problematic commit
> > dfcf74fa68c ("virtio-gpu: fix scanout migration post-load").
> >
> > v2:
> >  - use a manual version field test (instead of the more complex struct 
> > variant)
> >
>
> Unfortunately, when creating a snapshot with machine type pc-i440fx-9.0
> and trying to load it afterwards (both times with patches on top of
> current master), it'll fail with:
>
> > qemu-system-x86_64: virtio-gpu-scanouts: incoming version_id 2 is too new 
> > for local version_id 1
> > qemu-system-x86_64: Missing section footer for :00:02.0/virtio-gpu
> > qemu-system-x86_64: Error -22 while loading VM state
>
> Is there a bump to virtio-gpu-scanouts' version_id missing?
>

Indeed, it needs:

diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index 5de90bb62f..3a88eb5e3a 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -1201,7 +1201,7 @@ static const VMStateDescription
vmstate_virtio_gpu_scanout = {

 static const VMStateDescription vmstate_virtio_gpu_scanouts = {
 .name = "virtio-gpu-scanouts",
-.version_id = 1,
+.version_id = 2,




Re: [PATCH] ui/sdl2: Allow host to power down screen

2024-05-13 Thread Marc-André Lureau
On Sun, May 12, 2024 at 2:00 PM Bernhard Beschow  wrote:
>
> By default, SDL disables the screen saver which prevents the host from 
> powering
> down the screen even if the screen is locked. This results in draining the
> battery needlessly when the host isn't connected to a wall charger. Fix that 
> by
> enabling the screen saver.
>
> Signed-off-by: Bernhard Beschow 

Acked-by: Marc-André Lureau 

> ---
>  ui/sdl2.c | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/ui/sdl2.c b/ui/sdl2.c
> index 4971963f00..0a0eb5a42d 100644
> --- a/ui/sdl2.c
> +++ b/ui/sdl2.c
> @@ -874,6 +874,7 @@ static void sdl2_display_init(DisplayState *ds, 
> DisplayOptions *o)
>  SDL_SetHint(SDL_HINT_ALLOW_ALT_TAB_WHILE_GRABBED, "0");
>  #endif
>  SDL_SetHint(SDL_HINT_WINDOWS_NO_CLOSE_ON_ALT_F4, "1");
> +SDL_EnableScreenSaver();
>  memset(, 0, sizeof(info));
>  SDL_VERSION();
>
> --
> 2.45.0
>




Re: [PATCH v2 2/2] ui/gtk: Fix mouse/motion event scaling issue with GTK display backend

2024-05-13 Thread Marc-André Lureau
Hi

On Sun, May 12, 2024 at 3:16 PM hikalium  wrote:
>
> Remove gtk_widget_get_scale_factor() usage from the calculation of
> the motion events in the GTK backend to make it work correctly on
> environments that have `gtk_widget_get_scale_factor() != 1`.
>
> This scale factor usage had been introduced in the commit f14aab420c and
> at that time the window size was used for calculating the things and it
> was working correctly. However, in the commit 2f31663ed4 the logic
> switched to use the widget size instead of window size and because of
> the change the usage of scale factor becomes invalid (since widgets use
> `vc->gfx.scale_{x, y}` for scaling).
>
> Tested on Crostini on ChromeOS (15823.51.0) with an external display.
>
> Fixes: 2f31663ed4 ("ui/gtk: use widget size for cursor motion event")
> Fixes: f14aab420c ("ui: fix incorrect pointer position on highdpi with
> gtk")
>

Thanks for the fix, I am okay with it.

But the QEMU displays are not working well with HiDPI. By treating
size & position with logical units, we can't let the guest handle
HiDPI. Imho, we should fix the code differently so the guest has the
non-scaled units.

This is not as trivial, since widget geometry and drawing code is a
bit more involved. And in theory we should adopt the same behaviour
for other display backends.

> Signed-off-by: hikalium 
> ---
>  ui/gtk.c | 18 +-
>  1 file changed, 13 insertions(+), 5 deletions(-)
>
> diff --git a/ui/gtk.c b/ui/gtk.c
> index ebae888d4f..4386198c95 100644
> --- a/ui/gtk.c
> +++ b/ui/gtk.c
> @@ -887,7 +887,7 @@ static gboolean gd_motion_event(GtkWidget *widget, 
> GdkEventMotion *motion,
>  int x, y;
>  int mx, my;
>  int fbh, fbw;
> -int ww, wh, ws;
> +int ww, wh;
>
>  if (!vc->gfx.ds) {
>  return TRUE;
> @@ -895,11 +895,15 @@ static gboolean gd_motion_event(GtkWidget *widget, 
> GdkEventMotion *motion,
>
>  fbw = surface_width(vc->gfx.ds) * vc->gfx.scale_x;
>  fbh = surface_height(vc->gfx.ds) * vc->gfx.scale_y;
> -
>  ww = gtk_widget_get_allocated_width(widget);
>  wh = gtk_widget_get_allocated_height(widget);
> -ws = gtk_widget_get_scale_factor(widget);
>
> +/*
> + * `widget` may not have the same size with the frame buffer.
> + * In such cases, some paddings are needed around the `vc`.
> + * To achieve that, `vc` will be displayed at (mx, my)
> + * so that it is displayed at the center of the widget.
> + */
>  mx = my = 0;
>  if (ww > fbw) {
>  mx = (ww - fbw) / 2;
> @@ -908,8 +912,12 @@ static gboolean gd_motion_event(GtkWidget *widget, 
> GdkEventMotion *motion,
>  my = (wh - fbh) / 2;
>  }
>
> -x = (motion->x - mx) / vc->gfx.scale_x * ws;
> -y = (motion->y - my) / vc->gfx.scale_y * ws;
> +/*
> + * `motion` is reported in `widget` coordinates
> + * so translating it to the coordinates in `vc`.
> + */
> +x = (motion->x - mx) / vc->gfx.scale_x;
> +y = (motion->y - my) / vc->gfx.scale_y;
>
>  trace_gd_motion_event(ww, wh, gtk_widget_get_scale_factor(widget), x, y);
>
> --
> 2.39.2
>
>


-- 
Marc-André Lureau



Re: [PATCH v2 1/2] ui/gtk: Add gd_motion_event trace event

2024-05-13 Thread Marc-André Lureau
On Sun, May 12, 2024 at 3:16 PM hikalium  wrote:
>
> Add gd_motion_event trace event for making it easy to debug
> gd_motion_event related issues.
>
> Signed-off-by: hikalium 

Acked-by: Marc-André Lureau 

> ---
>  ui/gtk.c| 2 ++
>  ui/trace-events | 1 +
>  2 files changed, 3 insertions(+)
>
> diff --git a/ui/gtk.c b/ui/gtk.c
> index 810d7fc796..ebae888d4f 100644
> --- a/ui/gtk.c
> +++ b/ui/gtk.c
> @@ -911,6 +911,8 @@ static gboolean gd_motion_event(GtkWidget *widget, 
> GdkEventMotion *motion,
>  x = (motion->x - mx) / vc->gfx.scale_x * ws;
>  y = (motion->y - my) / vc->gfx.scale_y * ws;
>
> +trace_gd_motion_event(ww, wh, gtk_widget_get_scale_factor(widget), x, y);
> +
>  if (qemu_input_is_absolute(vc->gfx.dcl.con)) {
>  if (x < 0 || y < 0 ||
>  x >= surface_width(vc->gfx.ds) ||
> diff --git a/ui/trace-events b/ui/trace-events
> index e6a2894303..69ff22955d 100644
> --- a/ui/trace-events
> +++ b/ui/trace-events
> @@ -28,6 +28,7 @@ gd_ungrab(const char *tab, const char *device) "tab=%s, 
> dev=%s"
>  gd_keymap_windowing(const char *name) "backend=%s"
>  gd_gl_area_create_context(void *ctx, int major, int minor) "ctx=%p, 
> major=%d, minor=%d"
>  gd_gl_area_destroy_context(void *ctx, void *current_ctx) "ctx=%p, 
> current_ctx=%p"
> +gd_motion_event(int ww, int wh, int ws, int x, int y) "ww=%d, wh=%d, ws=%d, 
> x=%d, y=%d"
>
>  # vnc-auth-sasl.c
>  # vnc-auth-vencrypt.c
> --
> 2.39.2
>
>


-- 
Marc-André Lureau



Re: [PATCH 3/4] virtio-gpu: use a VMState variant for the scanout field

2024-05-11 Thread Marc-André Lureau
Hi Peter

On Fri, May 10, 2024 at 9:33 PM Peter Xu  wrote:
>
> Hi, Marc-André,
>
> On Fri, May 10, 2024 at 12:39:34PM +0400, Marc-André Lureau wrote:
> > Since we don't have per VMSD version information on the wire, nested
> > struct versioning is quite limited and cumbersome. I am not sure it
> > can be changed without breaking the stream format, and whether it's
> > worthwhile.
>
> Right that's a major pain, and actually I just notice it..
>
> I think it'll be much, much simpler if we keep vmsd version on the wire for
> each VMSD (including struct fields), then it makes more sense to me.
>
> Then when I went back and see again the VSTRUCT thing...  I can hardly
> understand what it is doing, and also how it works at all.
>
> Look at the current only IPMI user, who has:
>
> VMSTATE_VSTRUCT_V(kcs, ISAIPMIKCSDevice, 2, vmstate_IPMIKCS,
>   IPMIKCS, 2),
>
> It is setting both vmsd version and struct_version to 2.  I can't tell why
> it matters then if anyway both of the fields are the same..
>
> When we do save(), there is:
>
> } else if (field->flags & VMS_STRUCT) {
> ret = vmstate_save_state(f, field->vmsd, curr_elem,
>  vmdesc_loop);
> } else if (field->flags & VMS_VSTRUCT) {
> ret = vmstate_save_state_v(f, field->vmsd, curr_elem,
>vmdesc_loop,
>field->struct_version_id, 
> errp);
>
> When we load():
>
> } else if (field->flags & VMS_STRUCT) {
> ret = vmstate_load_state(f, field->vmsd, curr_elem,
>  field->vmsd->version_id);
> } else if (field->flags & VMS_VSTRUCT) {
> ret = vmstate_load_state(f, field->vmsd, curr_elem,
>  field->struct_version_id);
> } else {
>
> In this case, passing in struct_version==version should have zero effect
> afaict, because the default behavior is passing in vmsd->version_id anyway.

IPMI KCS being a top-level section, the fields with an unsupported
version are filtered before reaching this code.

But since I can't see how a machine will have a specific version, it
only helps for backward migration, which is quite limited.

>
> Moreover, now I highly doubt whether the VMS_STRUCT whole thing makes sense
> at all as you mentioned.  Especially on the load side, here we should rely
> on vmstate_load_state() taking the last parameter as version_id on the
> wire.  Here we're passing in the struct's version_id or struct_version_id,
> and neither of them makes sense to me... if we miss that version_id
> information, afaiu we should simply fix it and put it on the wire..  It'll
> break migration, we may need to work that out, but I don't see a better
> way.  Keeping it like this like a nightmare to me.. :-(

Ack.

Do you think we should add a version on the wire for each VMSD? that
will likely be a format change.

>
> Irrelevant of all these mess.. For this specific problem, what I meant is
> exactly what Michael was requesting too (hopefully), I'd want to avoid
> further extending the complexity in this area.  I have a patch attached at
> last which I also tested 8.2<->9.0 bi-directional migrations and it worked
> for me when I smoked it.  Please have a look to see whether that makes
> sense and at the meantime avoid most of the tricks.

Works for me! thanks for figuring out how to get back the VirtioGPU* !

I'll send v2 with your patch.

>
> I'd also like to mention one more thing just in case this can cause some
> more attention to virtio guys..
>
> Normally I ran vmstate-static-checker.py before softfreeze, and I did it
> for 9.0 too without seeing this problem.  It isn't raised because all
> virtio devices are using the "self managed" VMSTATE_VIRTIO_DEVICE to
> migrate.  In that case I am out of luck.  We can further extend what
> Fabiano mentioned in the other thread to cover migration stream validations
> in the future, but just to mention IMHO that needs extra work, and may work
> most likely the same as vmstate static checker but just waste many more cpu
> resources.  It'll be good if someone could still help move virtio towards
> like most of the rest devices, or at least get covered by the static
> checker, too.  But that definitely is a separate topic too.. so we can
> address the immediate breakage first.
>
> Thanks,
>
> ==8<==
> From a24ef99670fa7102da461d795aed4a957bad86b1 Mon Sep 17 00:00:00 2001
> From: Peter Xu 
> Da

Re: [PATCH v14 0/6] ui/console: Private QemuDmaBuf struct

2024-05-10 Thread Marc-André Lureau
Hi

On Wed, May 8, 2024 at 10:01 PM  wrote:
>
> From: Dongwon Kim 
>
> This series introduces privacy enhancements to the QemuDmaBuf struct
> and its contained data to bolster security. it accomplishes this by
> introducing of helper functions for allocating, deallocating, and
> accessing individual fields within the struct and replacing all direct
> references to individual fields in the struct with methods using helpers
> throughout the codebase.
>
> This change was made based on a suggestion from Marc-André Lureau
> 
>
> (Resumitting same patch series with this new cover-leter)
>
> v6: fixed some typos in patch -
> ui/console: Introduce dpy_gl_qemu_dmabuf_get_..() helpers)
>
> v7: included minor fix (ui/gtk: Check if fence_fd is equal to or greater than 
> 0)
> (Marc-André Lureau )
>
> migrated all helpers and QemuDmaBuf struct into dmabuf.c and their 
> prototypes
> to dmabuf.h for better encapsulation (ui/dmabuf: New dmabuf.c and 
> dmabuf.h..)
> (Daniel P. Berrangé  and
>  Marc-André Lureau )
>
> removed 'dpy_gl' from all helpers' names
> Defined autoptr clean up function for QemuDmaBuf*
> (Daniel P. Berrangé )
>
> Minor corrections
>
> v8: Introduce new dmabuf.c and dmabuf.h and all helper functions in the second
> patch in the series (ui/console: new dmabuf.h and dmabuf.c for 
> QemuDma)
> (Philippe Mathieu-Daudé )
>
> v9: set dmabuf->allow_fences true when it is created in virtio-gpu-udmabuf
>
> removed unnecessary spaces were added in the patch,
> 'ui/console: Use qemu_dmabuf_new() a...'
>
> v10: Change the license type for both dmabuf.h and dmabuf.c from MIT to
>  GPL to be in line with QEMU's default license
>  (Daniel P. Berrangé )
>
> v11: New helpers added - qemu_dmabuf_dup_fd, qemu_dmabuf_close for duplicating
>  and closing dmabuf->fd. And use them in places where applicable.
>  (Daniel P. Berrangé )
>
>  qemu_dmabuf_free helper now close dmabuf->fd before freeing the struct to
>  prevent any potential leakage (This eliminates the need for
>  qemu_dmabuf_close in several places as qemu_dmabuf_close is done anyway.)
>  (Daniel P. Berrangé )
>
> v12: --- qemu_dmabuf_free does not include qemu_dmabuf_close as there are 
> cases
>  where fd still needs to be used even after QemuDmaBuf struct is
>  destroyed (virtio-gpu: res->dmabuf_fd)
>
>  --- 'dmabuf' is now allocated space so it should be freed at the end of
>  dbus_scanout_texture
>
> v13: --- Immediately free dmabuf after it is released to prevent possible
>  leaking of the ptr
>  (Marc-André Lureau )
>
>  --- Use g_autoptr macro to define *dmabuf for auto clean up instead of
>  calling qemu_dmabuf_free
>  (Marc-André Lureau )
>
> v14: In ui/console: Use qemu_dmabuf_new() and free() helpers instead
>
>  --- (vhost-user-gpu) Change qemu_dmabuf_free back to g_clear_pointer
>  as it was done because of some misunderstanding (v13).
>
>  --- (vhost-user-gpu) g->dmabuf[m->scanout_id] needs to be set to NULL
>  to prevent freed dmabuf to be accessed again in case if(fd==-1)break;
>      happens (before new dmabuf is allocated). Otherwise, it would cause
>  invalid memory access when the same function is executed. Also NULL
>  check should be done before qemu_dmabuf_close (it asserts 
> dmabuf!=NULL.).
>  (Marc-André Lureau )
>

thanks, queued

> Dongwon Kim (6):
>   ui/gtk: Check if fence_fd is equal to or greater than 0
>   ui/console: new dmabuf.h and dmabuf.c for QemuDmaBuf struct and
> helpers
>   ui/console: Use qemu_dmabuf_get_..() helpers instead
>   ui/console: Use qemu_dmabuf_set_..() helpers instead
>   ui/console: Use qemu_dmabuf_new() and free() helpers instead
>   ui/console: move QemuDmaBuf struct def to dmabuf.c
>
>  include/hw/vfio/vfio-common.h   |   2 +-
>  include/hw/virtio/virtio-gpu.h  |   4 +-
>  include/ui/console.h|  20 +--
>  include/ui/dmabuf.h |  49 +++
>  hw/display/vhost-user-gpu.c |  32 +++--
>  hw/display/virtio-gpu-udmabuf.c |  27 ++--
>  hw/vfio/display.c   |  32 ++---
>  ui/console.c|   4 +-
>  ui/dbus-console.c   |   9 +-
>  ui/dbus-listener.c  |  71 +-
>  ui/dmabuf.c | 229 
>  ui/egl-headless.c   |  23 +++-
>  ui/egl-helpers.c|  59 
>  ui/gtk-egl.c|  52 +---
>  ui/gtk-gl-area.c|  41 --
>  ui/gtk.c|  12 +-
>  ui/spice-display.c  |  50 ---
>  ui/meson.build  |   1 +
>  18 files changed, 524 insertions(+), 193 deletions(-)
>  create mode 100644 include/ui/dmabuf.h
>  create mode 100644 ui/dmabuf.c
>
> --
> 2.34.1
>
>


-- 
Marc-André Lureau



Re: [PATCH 3/4] virtio-gpu: use a VMState variant for the scanout field

2024-05-10 Thread Marc-André Lureau
Hi Michael

On Fri, May 10, 2024 at 2:26 PM Michael S. Tsirkin  wrote:
>
> On Tue, May 07, 2024 at 03:19:19PM +0400, marcandre.lur...@redhat.com wrote:
> > From: Marc-André Lureau 
> >
> > Depending on the version, use v1 or v2 of the scanout VM state.
> >
> > Signed-off-by: Marc-André Lureau 
> > ---
> >  hw/display/virtio-gpu.c | 22 +-
> >  1 file changed, 17 insertions(+), 5 deletions(-)
> >
> > diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
> > index ae831b6b3e..4fd72caf3f 100644
> > --- a/hw/display/virtio-gpu.c
> > +++ b/hw/display/virtio-gpu.c
> > @@ -1191,17 +1191,29 @@ static const VMStateDescription 
> > vmstate_virtio_gpu_scanout = {
> >  },
> >  };
> >
> > +static bool vmstate_before_v2(void *opaque, int version)
> > +{
> > +return version <= 1;
> > +}
> > +
> >  static const VMStateDescription vmstate_virtio_gpu_scanouts = {
> >  .name = "virtio-gpu-scanouts",
> > -.version_id = 1,
> > +.version_id = 2,
> > +.minimum_version_id = 1,
> >  .fields = (const VMStateField[]) {
> >  VMSTATE_INT32(parent_obj.enable, struct VirtIOGPU),
> >  VMSTATE_UINT32_EQUAL(parent_obj.conf.max_outputs,
> >   struct VirtIOGPU, NULL),
> > -VMSTATE_STRUCT_VARRAY_UINT32(parent_obj.scanout, struct VirtIOGPU,
> > - parent_obj.conf.max_outputs, 1,
> > - vmstate_virtio_gpu_scanout,
> > - struct virtio_gpu_scanout),
> > +VMSTATE_VSTRUCT_TEST_VARRAY_UINT32(parent_obj.scanout, struct 
> > VirtIOGPU,
> > +   vmstate_before_v2,
> > +   parent_obj.conf.max_outputs, 1,
> > +   vmstate_virtio_gpu_scanout,
> > +   struct virtio_gpu_scanout, 1),
> > +VMSTATE_VSTRUCT_TEST_VARRAY_UINT32(parent_obj.scanout, struct 
> > VirtIOGPU,
> > +   NULL,
> > +   parent_obj.conf.max_outputs, 2,
> > +   vmstate_virtio_gpu_scanout,
> > +   struct virtio_gpu_scanout, 2),
> >  VMSTATE_END_OF_LIST()
> >  },
>
>
> Just don't, please.
> Add a property and add a conditional field based on property, set
> from the compat machinery.
>

The version isn't propagated through the nested VMSDs, so
vmstate_virtio_gpu_scanout would only have v1, whether we have a field
test or not.

Can you be more explicit what alternative solution you propose?

thanks


-- 
Marc-André Lureau



Re: [PATCH 3/4] virtio-gpu: use a VMState variant for the scanout field

2024-05-10 Thread Marc-André Lureau
Hi

On Wed, May 8, 2024 at 12:01 AM Peter Xu  wrote:
>
> On Tue, May 07, 2024 at 03:19:19PM +0400, marcandre.lur...@redhat.com wrote:
> > From: Marc-André Lureau 
> >
> > Depending on the version, use v1 or v2 of the scanout VM state.
> >
> > Signed-off-by: Marc-André Lureau 
> > ---
> >  hw/display/virtio-gpu.c | 22 +-
> >  1 file changed, 17 insertions(+), 5 deletions(-)
> >
> > diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
> > index ae831b6b3e..4fd72caf3f 100644
> > --- a/hw/display/virtio-gpu.c
> > +++ b/hw/display/virtio-gpu.c
> > @@ -1191,17 +1191,29 @@ static const VMStateDescription 
> > vmstate_virtio_gpu_scanout = {
> >  },
> >  };
> >
> > +static bool vmstate_before_v2(void *opaque, int version)
> > +{
> > +return version <= 1;
> > +}
> > +
> >  static const VMStateDescription vmstate_virtio_gpu_scanouts = {
> >  .name = "virtio-gpu-scanouts",
> > -.version_id = 1,
> > +.version_id = 2,
> > +.minimum_version_id = 1,
> >  .fields = (const VMStateField[]) {
> >  VMSTATE_INT32(parent_obj.enable, struct VirtIOGPU),
> >  VMSTATE_UINT32_EQUAL(parent_obj.conf.max_outputs,
> >   struct VirtIOGPU, NULL),
> > -VMSTATE_STRUCT_VARRAY_UINT32(parent_obj.scanout, struct VirtIOGPU,
> > - parent_obj.conf.max_outputs, 1,
> > - vmstate_virtio_gpu_scanout,
> > - struct virtio_gpu_scanout),
> > +VMSTATE_VSTRUCT_TEST_VARRAY_UINT32(parent_obj.scanout, struct 
> > VirtIOGPU,
> > +   vmstate_before_v2,
> > +   parent_obj.conf.max_outputs, 1,
> > +   vmstate_virtio_gpu_scanout,
> > +   struct virtio_gpu_scanout, 1),
> > +VMSTATE_VSTRUCT_TEST_VARRAY_UINT32(parent_obj.scanout, struct 
> > VirtIOGPU,
> > +   NULL,
> > +   parent_obj.conf.max_outputs, 2,
> > +   vmstate_virtio_gpu_scanout,
> > +   struct virtio_gpu_scanout, 2),
>
> Personally I really wished struct_version_id never existed..  After these
> years we only have 1 user of it (hw/ipmi/isa_ipmi_kcs.c), and we need to
> keep that working.  I'm wondering whether there's way we can avoid adding
> one more user, and even more complicated..
>
> I think I get the reasoning behind "we define the same thing twice", but
> this is really tricky and definitely needs rich documents, meanwhiel all of
> these seem to rely on so many small details: one set .field_exists
> properly, one leaving it to NULL; also the two versionings used here for
> both parent vmsd, and the struct, and for each entry we need to set
> different versions to different fields..
>
> Would it work if we only make the new fields under control with
> vmstate_before_v2()?  IOW, making all below with
> .field_exists=vmstate_before_v2, so skip below when machine type is old?

The existing VMSTATE_STRUCT_VARRAY_UINT32 would always use the latest
vmstate_virtio_gpu_scanout version_id (2 in master).

The "struct_version_id" solution allows setting the
vmstate_virtio_gpu_scanout version_id to 1 if the parent struct
(vmstate_virtio_gpu_scanouts) is 1, and 2 if the parent is 2.

Since we don't have per VMSD version information on the wire, nested
struct versioning is quite limited and cumbersome. I am not sure it
can be changed without breaking the stream format, and whether it's
worthwhile.


>
>  VMSTATE_UINT32_V(fb.format, struct virtio_gpu_scanout, 2),
>  VMSTATE_UINT32_V(fb.bytes_pp, struct virtio_gpu_scanout, 2),
>  VMSTATE_UINT32_V(fb.width, struct virtio_gpu_scanout, 2),
>  VMSTATE_UINT32_V(fb.height, struct virtio_gpu_scanout, 2),
>  VMSTATE_UINT32_V(fb.stride, struct virtio_gpu_scanout, 2),
>  VMSTATE_UINT32_V(fb.offset, struct virtio_gpu_scanout, 2),
>
> Thanks,
>
> --
> Peter Xu
>
>


--
Marc-André Lureau



Re: Hermetic virtio-vsock in QEMU

2024-05-08 Thread Marc-André Lureau
Hi

On Wed, May 8, 2024 at 11:50 AM Stefano Garzarella  wrote:
>
> Hi Roman,
>
> On Tue, May 07, 2024 at 11:20:50PM GMT, Roman Kiryanov wrote:
> >Hi Stefano,
> >
> >On Tue, May 7, 2024 at 1:10 AM Stefano Garzarella  
> >wrote:
> >> I have no experience with Windows, but what we need for vhost-user is:
> >>
> >> - AF_UNIX and be able to send file descriptors using ancillary data
> >>(i.e. SCM_RIGHTS)
> >
> >As far as I understand, Windows does NOT support SCM_RIGHTS over AF_UNIX.
>
> Thank you for the information. This is unfortunate and does not allow
> us to use vhost-user as it is on Windows.
>

fwiw, Windows has other mechanisms to share resources between processes.

To share/pass sockets, you can use WSADuplicateSocket. For shared
memory and other resources, DuplicateHandle API.

(you can also share other things like D3D textures etc. those
mechanisms are used to enable -display dbus on Windows efficiently)


-- 
Marc-André Lureau



Re: [PATCH v13 5/6] ui/console: Use qemu_dmabuf_new() and free() helpers instead

2024-05-08 Thread Marc-André Lureau
Hi

On Tue, May 7, 2024 at 10:44 PM  wrote:
>
> From: Dongwon Kim 
>
> This commit introduces utility functions for the creation and deallocation
> of QemuDmaBuf instances. Additionally, it updates all relevant sections
> of the codebase to utilize these new utility functions.
>
> v7: remove prefix, "dpy_gl_" from all helpers
> qemu_dmabuf_free() returns without doing anything if input is null
> (Daniel P. Berrangé )
> call G_DEFINE_AUTOPTR_CLEANUP_FUNC for qemu_dmabuf_free()
> (Daniel P. Berrangé )
>
> v8: Introduction of helpers was removed as those were already added
> by the previous commit
>
> v9: set dmabuf->allow_fences to 'true' when dmabuf is created in
> virtio_gpu_create_dmabuf()/virtio-gpu-udmabuf.c
>
> removed unnecessary spaces were accidently added in the patch,
> 'ui/console: Use qemu_dmabuf_new() a...'
>
> v11: Calling qemu_dmabuf_close was removed as closing dmabuf->fd will be
>  done in qemu_dmabuf_free anyway.
>  (Daniel P. Berrangé )
>
> v12: --- Calling qemu_dmabuf_close separately as qemu_dmabuf_free doesn't
>  do it.
>
>  --- 'dmabuf' is now allocated space so it should be freed at the end of
>  dbus_scanout_texture
>
> v13: --- Immediately free dmabuf after it is released to prevent possible
>  leaking of the ptr
>  (Marc-André Lureau )
>
>      --- Use g_autoptr macro to define *dmabuf for auto clean up instead of
>  calling qemu_dmabuf_free
>  (Marc-André Lureau )
>
> Suggested-by: Marc-André Lureau 
> Cc: Philippe Mathieu-Daudé 
> Cc: Daniel P. Berrangé 
> Cc: Vivek Kasireddy 
> Signed-off-by: Dongwon Kim 
> ---
>  include/hw/vfio/vfio-common.h   |  2 +-
>  include/hw/virtio/virtio-gpu.h  |  4 ++--
>  hw/display/vhost-user-gpu.c | 21 +++--
>  hw/display/virtio-gpu-udmabuf.c | 24 +---
>  hw/vfio/display.c   | 26 --
>  ui/dbus-listener.c  | 28 
>  6 files changed, 47 insertions(+), 58 deletions(-)
>
> diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h
> index b9da6c08ef..d66e27db02 100644
> --- a/include/hw/vfio/vfio-common.h
> +++ b/include/hw/vfio/vfio-common.h
> @@ -148,7 +148,7 @@ typedef struct VFIOGroup {
>  } VFIOGroup;
>
>  typedef struct VFIODMABuf {
> -QemuDmaBuf buf;
> +QemuDmaBuf *buf;
>  uint32_t pos_x, pos_y, pos_updates;
>  uint32_t hot_x, hot_y, hot_updates;
>  int dmabuf_id;
> diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
> index ed44cdad6b..56d6e821bf 100644
> --- a/include/hw/virtio/virtio-gpu.h
> +++ b/include/hw/virtio/virtio-gpu.h
> @@ -169,7 +169,7 @@ struct VirtIOGPUBaseClass {
>  DEFINE_PROP_UINT32("yres", _state, _conf.yres, 800)
>
>  typedef struct VGPUDMABuf {
> -QemuDmaBuf buf;
> +QemuDmaBuf *buf;
>  uint32_t scanout_id;
>  QTAILQ_ENTRY(VGPUDMABuf) next;
>  } VGPUDMABuf;
> @@ -238,7 +238,7 @@ struct VhostUserGPU {
>  VhostUserBackend *vhost;
>  int vhost_gpu_fd; /* closed by the chardev */
>  CharBackend vhost_chr;
> -QemuDmaBuf dmabuf[VIRTIO_GPU_MAX_SCANOUTS];
> +QemuDmaBuf *dmabuf[VIRTIO_GPU_MAX_SCANOUTS];
>  bool backend_blocked;
>  };
>
> diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c
> index 454e5afcff..744792cf78 100644
> --- a/hw/display/vhost-user-gpu.c
> +++ b/hw/display/vhost-user-gpu.c
> @@ -249,6 +249,7 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, 
> VhostUserGpuMsg *msg)
>  case VHOST_USER_GPU_DMABUF_SCANOUT: {
>  VhostUserGpuDMABUFScanout *m = >payload.dmabuf_scanout;
>  int fd = qemu_chr_fe_get_msgfd(>vhost_chr);
> +uint64_t modifier = 0;
>  QemuDmaBuf *dmabuf;
>
>  if (m->scanout_id >= g->parent_obj.conf.max_outputs) {
> @@ -261,27 +262,27 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, 
> VhostUserGpuMsg *msg)
>
>  g->parent_obj.enable = 1;
>  con = g->parent_obj.scanout[m->scanout_id].con;
> -dmabuf = >dmabuf[m->scanout_id];
> +dmabuf = g->dmabuf[m->scanout_id];
>  qemu_dmabuf_close(dmabuf);
>  dpy_gl_release_dmabuf(con, dmabuf);
> +qemu_dmabuf_free(dmabuf);
>  if (fd == -1) {
>  dpy_gl_scanout_disable(con);
>  break;

This is still incorrect. You replaced g_clear_pointer(,
qemu_dmabuf_free), but that's not the point.

g->dmabuf[m->scanout_id] must be set to NULL, before breaking, at least.

>  }
> -*dmabuf = (Qe

Re: [PATCH v10 09/10] virtio-gpu: Register capsets dynamically

2024-05-08 Thread Marc-André Lureau
On Sun, May 5, 2024 at 12:29 AM Dmitry Osipenko
 wrote:
>
> From: Pierre-Eric Pelloux-Prayer 
>
> virtio_gpu_virgl_get_num_capsets will return "num_capsets", but we can't
> assume that capset_index 1 is always VIRGL2 once we'll support more capsets,
> like Venus and DRM capsets. Register capsets dynamically to avoid that 
> problem.
>
> Signed-off-by: Pierre-Eric Pelloux-Prayer 
> Signed-off-by: Dmitry Osipenko 

Reviewed-by: Marc-André Lureau 

> ---
>  hw/display/virtio-gpu-gl.c |  6 --
>  hw/display/virtio-gpu-virgl.c  | 33 +
>  include/hw/virtio/virtio-gpu.h |  4 +++-
>  3 files changed, 28 insertions(+), 15 deletions(-)
>
> diff --git a/hw/display/virtio-gpu-gl.c b/hw/display/virtio-gpu-gl.c
> index 2a9e549ad2e9..cd39e0650862 100644
> --- a/hw/display/virtio-gpu-gl.c
> +++ b/hw/display/virtio-gpu-gl.c
> @@ -125,8 +125,8 @@ static void virtio_gpu_gl_device_realize(DeviceState 
> *qdev, Error **errp)
>  }
>
>  g->parent_obj.conf.flags |= (1 << VIRTIO_GPU_FLAG_VIRGL_ENABLED);
> -VIRTIO_GPU_BASE(g)->virtio_config.num_capsets =
> -virtio_gpu_virgl_get_num_capsets(g);
> +g->capset_ids = virtio_gpu_virgl_get_capsets(g);
> +VIRTIO_GPU_BASE(g)->virtio_config.num_capsets = g->capset_ids->len;
>
>  #ifdef HAVE_VIRGL_CONTEXT_CREATE_WITH_FLAGS
>  g->parent_obj.conf.flags |= 1 << VIRTIO_GPU_FLAG_CONTEXT_INIT_ENABLED;
> @@ -149,6 +149,8 @@ static void virtio_gpu_gl_device_unrealize(DeviceState 
> *qdev)
>  if (gl->renderer_inited) {
>  virtio_gpu_virgl_deinit(g);
>  }
> +
> +g_array_unref(g->capset_ids);
>  }
>
>  static void virtio_gpu_gl_class_init(ObjectClass *klass, void *data)
> diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
> index d92c58b77865..1babda4efad5 100644
> --- a/hw/display/virtio-gpu-virgl.c
> +++ b/hw/display/virtio-gpu-virgl.c
> @@ -585,19 +585,13 @@ static void virgl_cmd_get_capset_info(VirtIOGPU *g,
>  VIRTIO_GPU_FILL_CMD(info);
>
>  memset(, 0, sizeof(resp));
> -if (info.capset_index == 0) {
> -resp.capset_id = VIRTIO_GPU_CAPSET_VIRGL;
> -virgl_renderer_get_cap_set(resp.capset_id,
> -   _max_version,
> -   _max_size);
> -} else if (info.capset_index == 1) {
> -resp.capset_id = VIRTIO_GPU_CAPSET_VIRGL2;
> +
> +if (info.capset_index < g->capset_ids->len) {
> +resp.capset_id = g_array_index(g->capset_ids, uint32_t,
> +   info.capset_index);
>  virgl_renderer_get_cap_set(resp.capset_id,
> _max_version,
> _max_size);
> -} else {
> -resp.capset_max_version = 0;
> -resp.capset_max_size = 0;
>  }
>  resp.hdr.type = VIRTIO_GPU_RESP_OK_CAPSET_INFO;
>  virtio_gpu_ctrl_response(g, cmd, , sizeof(resp));
> @@ -1120,14 +1114,29 @@ int virtio_gpu_virgl_init(VirtIOGPU *g)
>  return 0;
>  }
>
> -int virtio_gpu_virgl_get_num_capsets(VirtIOGPU *g)
> +static void virtio_gpu_virgl_add_capset(GArray *capset_ids, uint32_t 
> capset_id)
> +{
> +g_array_append_val(capset_ids, capset_id);
> +}
> +
> +GArray *virtio_gpu_virgl_get_capsets(VirtIOGPU *g)
>  {
>  uint32_t capset2_max_ver, capset2_max_size;
> +GArray *capset_ids;
> +
> +capset_ids = g_array_new(false, false, sizeof(uint32_t));
> +
> +/* VIRGL is always supported. */
> +virtio_gpu_virgl_add_capset(capset_ids, VIRTIO_GPU_CAPSET_VIRGL);
> +
>  virgl_renderer_get_cap_set(VIRTIO_GPU_CAPSET_VIRGL2,
>_max_ver,
>_max_size);
> +if (capset2_max_ver) {
> +virtio_gpu_virgl_add_capset(capset_ids, VIRTIO_GPU_CAPSET_VIRGL2);
> +}
>
> -return capset2_max_ver ? 2 : 1;
> +return capset_ids;
>  }
>
>  void virtio_gpu_virgl_deinit(VirtIOGPU *g)
> diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
> index a98847b88087..105308a36865 100644
> --- a/include/hw/virtio/virtio-gpu.h
> +++ b/include/hw/virtio/virtio-gpu.h
> @@ -213,6 +213,8 @@ struct VirtIOGPU {
>  } dmabuf;
>
>  QEMUBH *cmdq_resume_bh;
> +
> +GArray *capset_ids;
>  };
>
>  struct VirtIOGPUClass {
> @@ -347,6 +349,6 @@ void virtio_gpu_virgl_reset_scanout(VirtIOGPU *g);
>  void virtio_gpu_virgl_reset(VirtIOGPU *g);
>  int virtio_gpu_virgl_init(VirtIOGPU *g);
>  void virtio_gpu_virgl_deinit(VirtIOGPU *g);
> -int virtio_gpu_virgl_get_num_capsets(VirtIOGPU *g);
> +GArray *virtio_gpu_virgl_get_capsets(VirtIOGPU *g);
>
>  #endif
> --
> 2.44.0
>


-- 
Marc-André Lureau



Re: [PATCH v10 06/10] virtio-gpu: Support blob scanout using dmabuf fd

2024-05-08 Thread Marc-André Lureau
On Sun, May 5, 2024 at 12:29 AM Dmitry Osipenko
 wrote:
>
> From: Robert Beckett 
>
> Support displaying blob resources by handling SET_SCANOUT_BLOB
> command.
>
> Signed-by: Antonio Caggiano 
> Signed-off-by: Robert Beckett 
> Signed-off-by: Huang Rui 
> Reviewed-by: Antonio Caggiano 
> Signed-off-by: Dmitry Osipenko 

Acked-by: Marc-André Lureau 

> ---
>  hw/display/virtio-gpu-virgl.c  | 109 +
>  hw/display/virtio-gpu.c|  12 ++--
>  include/hw/virtio/virtio-gpu.h |   7 +++
>  meson.build|   1 +
>  4 files changed, 123 insertions(+), 6 deletions(-)
>
> diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
> index a040324f5024..2fedccb1fc8d 100644
> --- a/hw/display/virtio-gpu-virgl.c
> +++ b/hw/display/virtio-gpu-virgl.c
> @@ -17,6 +17,8 @@
>  #include "trace.h"
>  #include "hw/virtio/virtio.h"
>  #include "hw/virtio/virtio-gpu.h"
> +#include "hw/virtio/virtio-gpu-bswap.h"
> +#include "hw/virtio/virtio-gpu-pixman.h"
>
>  #include "ui/egl-helpers.h"
>
> @@ -78,6 +80,7 @@ static void virgl_cmd_create_resource_2d(VirtIOGPU *g,
>  res->base.height = c2d.height;
>  res->base.format = c2d.format;
>  res->base.resource_id = c2d.resource_id;
> +res->base.dmabuf_fd = -1;
>  QTAILQ_INSERT_HEAD(>reslist, >base, next);
>
>  args.handle = c2d.resource_id;
> @@ -125,6 +128,7 @@ static void virgl_cmd_create_resource_3d(VirtIOGPU *g,
>  res->base.height = c3d.height;
>  res->base.format = c3d.format;
>  res->base.resource_id = c3d.resource_id;
> +res->base.dmabuf_fd = -1;
>  QTAILQ_INSERT_HEAD(>reslist, >base, next);
>
>  args.handle = c3d.resource_id;
> @@ -507,6 +511,106 @@ static void virgl_cmd_get_capset(VirtIOGPU *g,
>  g_free(resp);
>  }
>
> +#ifdef HAVE_VIRGL_RESOURCE_BLOB
> +static void virgl_cmd_set_scanout_blob(VirtIOGPU *g,
> +   struct virtio_gpu_ctrl_command *cmd)
> +{
> +struct virtio_gpu_framebuffer fb = { 0 };
> +struct virgl_renderer_resource_info info;
> +struct virtio_gpu_virgl_resource *res;
> +struct virtio_gpu_set_scanout_blob ss;
> +uint64_t fbend;
> +
> +VIRTIO_GPU_FILL_CMD(ss);
> +virtio_gpu_scanout_blob_bswap();
> +trace_virtio_gpu_cmd_set_scanout_blob(ss.scanout_id, ss.resource_id,
> +  ss.r.width, ss.r.height, ss.r.x,
> +  ss.r.y);
> +
> +if (ss.scanout_id >= g->parent_obj.conf.max_outputs) {
> +qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal scanout id specified %d",
> +  __func__, ss.scanout_id);
> +cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_SCANOUT_ID;
> +return;
> +}
> +
> +if (ss.resource_id == 0) {
> +virtio_gpu_disable_scanout(g, ss.scanout_id);
> +return;
> +}
> +
> +if (ss.width < 16 ||
> +ss.height < 16 ||
> +ss.r.x + ss.r.width > ss.width ||
> +ss.r.y + ss.r.height > ss.height) {
> +qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal scanout %d bounds for"
> +  " resource %d, rect (%d,%d)+%d,%d, fb %d %d\n",
> +  __func__, ss.scanout_id, ss.resource_id,
> +  ss.r.x, ss.r.y, ss.r.width, ss.r.height,
> +  ss.width, ss.height);
> +cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
> +return;
> +}
> +
> +res = virtio_gpu_virgl_find_resource(g, ss.resource_id);
> +if (!res) {
> +qemu_log_mask(LOG_GUEST_ERROR, "%s: resource does not exist %d\n",
> +  __func__, ss.resource_id);
> +cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
> +return;
> +}
> +if (virgl_renderer_resource_get_info(ss.resource_id, )) {
> +qemu_log_mask(LOG_GUEST_ERROR, "%s: resource does not have info 
> %d\n",
> +  __func__, ss.resource_id);
> +cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
> +return;
> +}
> +if (res->base.dmabuf_fd < 0) {
> +res->base.dmabuf_fd = info.fd;
> +}
> +if (res->base.dmabuf_fd < 0) {
> +qemu_log_mask(LOG_GUEST_ERROR, "%s: resource not backed by dmabuf 
> %d\n",
> +  __func__, ss.resource_id);
> +cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
> +return;
> +}
> +
> +fb.format

Re: [PATCH v10 05/10] virtio-gpu: Add virgl resource management

2024-05-08 Thread Marc-André Lureau
On Sun, May 5, 2024 at 12:29 AM Dmitry Osipenko
 wrote:
>
> From: Huang Rui 
>
> In a preparation to adding host blobs support to virtio-gpu, add virgl
> resource management that allows to retrieve resource based on its ID
> and virgl resource wrapper on top of simple resource that will be contain
> fields specific to virgl.
>
> Signed-off-by: Huang Rui 
> Reviewed-by: Antonio Caggiano 
> Signed-off-by: Dmitry Osipenko 

Reviewed-by: Marc-André Lureau 

> ---
>  hw/display/virtio-gpu-virgl.c | 74 +++
>  1 file changed, 74 insertions(+)
>
> diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
> index 8306961ad502..a040324f5024 100644
> --- a/hw/display/virtio-gpu-virgl.c
> +++ b/hw/display/virtio-gpu-virgl.c
> @@ -22,6 +22,23 @@
>
>  #include 
>
> +struct virtio_gpu_virgl_resource {
> +struct virtio_gpu_simple_resource base;
> +};
> +
> +static struct virtio_gpu_virgl_resource *
> +virtio_gpu_virgl_find_resource(VirtIOGPU *g, uint32_t resource_id)
> +{
> +struct virtio_gpu_simple_resource *res;
> +
> +res = virtio_gpu_find_resource(g, resource_id);
> +if (!res) {
> +return NULL;
> +}
> +
> +return container_of(res, struct virtio_gpu_virgl_resource, base);
> +}
> +
>  #if VIRGL_RENDERER_CALLBACKS_VERSION >= 4
>  static void *
>  virgl_get_egl_display(G_GNUC_UNUSED void *cookie)
> @@ -35,11 +52,34 @@ static void virgl_cmd_create_resource_2d(VirtIOGPU *g,
>  {
>  struct virtio_gpu_resource_create_2d c2d;
>  struct virgl_renderer_resource_create_args args;
> +struct virtio_gpu_virgl_resource *res;
>
>  VIRTIO_GPU_FILL_CMD(c2d);
>  trace_virtio_gpu_cmd_res_create_2d(c2d.resource_id, c2d.format,
> c2d.width, c2d.height);
>
> +if (c2d.resource_id == 0) {
> +qemu_log_mask(LOG_GUEST_ERROR, "%s: resource id 0 is not allowed\n",
> +  __func__);
> +cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
> +return;
> +}
> +
> +res = virtio_gpu_virgl_find_resource(g, c2d.resource_id);
> +if (res) {
> +qemu_log_mask(LOG_GUEST_ERROR, "%s: resource already exists %d\n",
> +  __func__, c2d.resource_id);
> +cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
> +return;
> +}
> +
> +res = g_new0(struct virtio_gpu_virgl_resource, 1);
> +res->base.width = c2d.width;
> +res->base.height = c2d.height;
> +res->base.format = c2d.format;
> +res->base.resource_id = c2d.resource_id;
> +QTAILQ_INSERT_HEAD(>reslist, >base, next);
> +
>  args.handle = c2d.resource_id;
>  args.target = 2;
>  args.format = c2d.format;
> @@ -59,11 +99,34 @@ static void virgl_cmd_create_resource_3d(VirtIOGPU *g,
>  {
>  struct virtio_gpu_resource_create_3d c3d;
>  struct virgl_renderer_resource_create_args args;
> +struct virtio_gpu_virgl_resource *res;
>
>  VIRTIO_GPU_FILL_CMD(c3d);
>  trace_virtio_gpu_cmd_res_create_3d(c3d.resource_id, c3d.format,
> c3d.width, c3d.height, c3d.depth);
>
> +if (c3d.resource_id == 0) {
> +qemu_log_mask(LOG_GUEST_ERROR, "%s: resource id 0 is not allowed\n",
> +  __func__);
> +cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
> +return;
> +}
> +
> +res = virtio_gpu_virgl_find_resource(g, c3d.resource_id);
> +if (res) {
> +qemu_log_mask(LOG_GUEST_ERROR, "%s: resource already exists %d\n",
> +  __func__, c3d.resource_id);
> +cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
> +return;
> +}
> +
> +res = g_new0(struct virtio_gpu_virgl_resource, 1);
> +res->base.width = c3d.width;
> +res->base.height = c3d.height;
> +res->base.format = c3d.format;
> +res->base.resource_id = c3d.resource_id;
> +QTAILQ_INSERT_HEAD(>reslist, >base, next);
> +
>  args.handle = c3d.resource_id;
>  args.target = c3d.target;
>  args.format = c3d.format;
> @@ -82,12 +145,19 @@ static void virgl_cmd_resource_unref(VirtIOGPU *g,
>   struct virtio_gpu_ctrl_command *cmd)
>  {
>  struct virtio_gpu_resource_unref unref;
> +struct virtio_gpu_virgl_resource *res;
>  struct iovec *res_iovs = NULL;
>  int num_iovs = 0;
>
>  VIRTIO_GPU_FILL_CMD(unref);
>  trace_virtio_gpu_cmd_res_unref(unref.resource_id);
>
> +res = 

Re: [PATCH v10 03/10] virtio-gpu: Support context-init feature with virglrenderer

2024-05-08 Thread Marc-André Lureau
Hi

On Sun, May 5, 2024 at 12:29 AM Dmitry Osipenko
 wrote:
>
> From: Huang Rui 
>
> Patch "virtio-gpu: CONTEXT_INIT feature" has added the context_init
> feature flags. Expose this feature and support creating virglrenderer
> context with flags using context_id if libvirglrenderer is new enough.
>
> Originally-by: Antonio Caggiano 
> Signed-off-by: Huang Rui 
> Reviewed-by: Antonio Caggiano 
> Signed-off-by: Dmitry Osipenko 
> ---
>  hw/display/virtio-gpu-gl.c|  4 
>  hw/display/virtio-gpu-virgl.c | 20 ++--
>  meson.build   |  1 +
>  3 files changed, 23 insertions(+), 2 deletions(-)
>
> diff --git a/hw/display/virtio-gpu-gl.c b/hw/display/virtio-gpu-gl.c
> index 0c0a8d136954..95806999189e 100644
> --- a/hw/display/virtio-gpu-gl.c
> +++ b/hw/display/virtio-gpu-gl.c
> @@ -127,6 +127,10 @@ static void virtio_gpu_gl_device_realize(DeviceState 
> *qdev, Error **errp)
>  VIRTIO_GPU_BASE(g)->virtio_config.num_capsets =
>  virtio_gpu_virgl_get_num_capsets(g);
>
> +#ifdef HAVE_VIRGL_CONTEXT_CREATE_WITH_FLAGS
> +g->parent_obj.conf.flags |= 1 << VIRTIO_GPU_FLAG_CONTEXT_INIT_ENABLED;
> +#endif
> +
>  virtio_gpu_device_realize(qdev, errp);
>  }
>
> diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
> index b0500eccf8e0..8306961ad502 100644
> --- a/hw/display/virtio-gpu-virgl.c
> +++ b/hw/display/virtio-gpu-virgl.c
> @@ -106,8 +106,24 @@ static void virgl_cmd_context_create(VirtIOGPU *g,
>  trace_virtio_gpu_cmd_ctx_create(cc.hdr.ctx_id,
>  cc.debug_name);
>
> -virgl_renderer_context_create(cc.hdr.ctx_id, cc.nlen,
> -  cc.debug_name);
> +if (cc.context_init) {
> +if (!virtio_gpu_context_init_enabled(g->parent_obj.conf)) {
> +qemu_log_mask(LOG_GUEST_ERROR, "%s: context_init disabled",
> +  __func__);
> +cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
> +return;
> +}
> +
> +#ifdef HAVE_VIRGL_CONTEXT_CREATE_WITH_FLAGS
> +virgl_renderer_context_create_with_flags(cc.hdr.ctx_id,
> + cc.context_init,
> + cc.nlen,
> + cc.debug_name);
> +return;
> +#endif

I am wondering if there should be a:

#else
g_assert_not_reached();
#endif

rather than falling back to a regular context creation.

> +}
> +
> +virgl_renderer_context_create(cc.hdr.ctx_id, cc.nlen, cc.debug_name);
>  }
>
>  static void virgl_cmd_context_destroy(VirtIOGPU *g,
> diff --git a/meson.build b/meson.build
> index f4a4d71c1978..513cb2ea6d03 100644
> --- a/meson.build
> +++ b/meson.build
> @@ -2288,6 +2288,7 @@ config_host_data.set('CONFIG_VNC_JPEG', jpeg.found())
>  config_host_data.set('CONFIG_VNC_SASL', sasl.found())
>  if virgl.version().version_compare('>=1.0.0')
>config_host_data.set('HAVE_VIRGL_D3D_INFO_EXT', 1)
> +  config_host_data.set('HAVE_VIRGL_CONTEXT_CREATE_WITH_FLAGS', 1)
>  endif
>  config_host_data.set('CONFIG_VIRTFS', have_virtfs)
>  config_host_data.set('CONFIG_VTE', vte.found())
> --
> 2.44.0
>

Reviewed-by: Marc-André Lureau 

-- 
Marc-André Lureau



Re: [PATCH v10 02/10] virtio-gpu: Use pkgconfig version to decide which virgl features are available

2024-05-07 Thread Marc-André Lureau
Hi

On Tue, May 7, 2024 at 7:18 PM Marc-André Lureau
 wrote:
>
> Hi
>
> On Sun, May 5, 2024 at 12:29 AM Dmitry Osipenko
>  wrote:
> >
> > New virglrerenderer features were stabilized with release of v1.0.0.
> > Presence of symbols in virglrenderer.h doesn't guarantee ABI compatibility
> > with pre-release development versions of libvirglerender. Use virglrenderer
> > version to decide reliably which virgl features are available.
> >
> > Signed-off-by: Dmitry Osipenko 
> > ---
> >  meson.build | 7 ++-
> >  1 file changed, 2 insertions(+), 5 deletions(-)
> >
> > diff --git a/meson.build b/meson.build
> > index 5db2dbc12ec7..f4a4d71c1978 100644
> > --- a/meson.build
> > +++ b/meson.build
> > @@ -2286,11 +2286,8 @@ config_host_data.set('CONFIG_PNG', png.found())
> >  config_host_data.set('CONFIG_VNC', vnc.found())
> >  config_host_data.set('CONFIG_VNC_JPEG', jpeg.found())
> >  config_host_data.set('CONFIG_VNC_SASL', sasl.found())
> > -if virgl.found()
> > -  config_host_data.set('HAVE_VIRGL_D3D_INFO_EXT',
> > -   cc.has_member('struct 
> > virgl_renderer_resource_info_ext', 'd3d_tex2d',
> > - prefix: '#include ',
> > - dependencies: virgl))
> > +if virgl.version().version_compare('>=1.0.0')
> > +  config_host_data.set('HAVE_VIRGL_D3D_INFO_EXT', 1)
>
> If it checks for version >=1.0, we may as well depend on >=1.0.1 imho,
> and then simply use VIRGL_CHECK_VERSION in the code.
>

..but we would need a fallback if VIRGL_CHECK_VERSION isn't defined in
that case (which could simply fail).




-- 
Marc-André Lureau



Re: [PATCH v10 02/10] virtio-gpu: Use pkgconfig version to decide which virgl features are available

2024-05-07 Thread Marc-André Lureau
Hi

On Sun, May 5, 2024 at 12:29 AM Dmitry Osipenko
 wrote:
>
> New virglrerenderer features were stabilized with release of v1.0.0.
> Presence of symbols in virglrenderer.h doesn't guarantee ABI compatibility
> with pre-release development versions of libvirglerender. Use virglrenderer
> version to decide reliably which virgl features are available.
>
> Signed-off-by: Dmitry Osipenko 
> ---
>  meson.build | 7 ++-
>  1 file changed, 2 insertions(+), 5 deletions(-)
>
> diff --git a/meson.build b/meson.build
> index 5db2dbc12ec7..f4a4d71c1978 100644
> --- a/meson.build
> +++ b/meson.build
> @@ -2286,11 +2286,8 @@ config_host_data.set('CONFIG_PNG', png.found())
>  config_host_data.set('CONFIG_VNC', vnc.found())
>  config_host_data.set('CONFIG_VNC_JPEG', jpeg.found())
>  config_host_data.set('CONFIG_VNC_SASL', sasl.found())
> -if virgl.found()
> -  config_host_data.set('HAVE_VIRGL_D3D_INFO_EXT',
> -   cc.has_member('struct 
> virgl_renderer_resource_info_ext', 'd3d_tex2d',
> - prefix: '#include ',
> - dependencies: virgl))
> +if virgl.version().version_compare('>=1.0.0')
> +  config_host_data.set('HAVE_VIRGL_D3D_INFO_EXT', 1)

If it checks for version >=1.0, we may as well depend on >=1.0.1 imho,
and then simply use VIRGL_CHECK_VERSION in the code.

>  endif
>  config_host_data.set('CONFIG_VIRTFS', have_virtfs)
>  config_host_data.set('CONFIG_VTE', vte.found())
> --
> 2.44.0
>


-- 
Marc-André Lureau



Re: [PATCH v10 01/10] virtio-gpu: Unrealize GL device

2024-05-07 Thread Marc-André Lureau
Hi

On Sun, May 5, 2024 at 12:29 AM Dmitry Osipenko
 wrote:
>
> Even though GL GPU doesn't support hotplugging today, free virgl
> resources when GL device is unrealized. For consistency.
>
> Signed-off-by: Dmitry Osipenko 
> ---
>  hw/display/virtio-gpu-gl.c | 11 +++
>  hw/display/virtio-gpu-virgl.c  |  9 +
>  include/hw/virtio/virtio-gpu.h |  1 +
>  3 files changed, 21 insertions(+)
>
> diff --git a/hw/display/virtio-gpu-gl.c b/hw/display/virtio-gpu-gl.c
> index e06be60dfbfc..0c0a8d136954 100644
> --- a/hw/display/virtio-gpu-gl.c
> +++ b/hw/display/virtio-gpu-gl.c
> @@ -136,6 +136,16 @@ static Property virtio_gpu_gl_properties[] = {
>  DEFINE_PROP_END_OF_LIST(),
>  };
>
> +static void virtio_gpu_gl_device_unrealize(DeviceState *qdev)
> +{
> +VirtIOGPU *g = VIRTIO_GPU(qdev);
> +VirtIOGPUGL *gl = VIRTIO_GPU_GL(qdev);
> +
> +if (gl->renderer_inited) {
> +virtio_gpu_virgl_deinit(g);
> +}
> +}
> +
>  static void virtio_gpu_gl_class_init(ObjectClass *klass, void *data)
>  {
>  DeviceClass *dc = DEVICE_CLASS(klass);
> @@ -149,6 +159,7 @@ static void virtio_gpu_gl_class_init(ObjectClass *klass, 
> void *data)
>  vgc->update_cursor_data = virtio_gpu_gl_update_cursor_data;
>
>  vdc->realize = virtio_gpu_gl_device_realize;
> +vdc->unrealize = virtio_gpu_gl_device_unrealize;
>  vdc->reset = virtio_gpu_gl_reset;
>  device_class_set_props(dc, virtio_gpu_gl_properties);
>  }
> diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
> index 9f34d0e6619c..b0500eccf8e0 100644
> --- a/hw/display/virtio-gpu-virgl.c
> +++ b/hw/display/virtio-gpu-virgl.c
> @@ -665,3 +665,12 @@ int virtio_gpu_virgl_get_num_capsets(VirtIOGPU *g)
>
>  return capset2_max_ver ? 2 : 1;
>  }
> +
> +void virtio_gpu_virgl_deinit(VirtIOGPU *g)
> +{
> +if (g->fence_poll) {
> +timer_free(g->fence_poll);

might be worth to set g->fence_poll to NULL here, to be able to call
deinit() multiple times.

> +}
> +
> +virgl_renderer_cleanup(NULL);
> +}
> diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
> index ed44cdad6b34..b657187159d9 100644
> --- a/include/hw/virtio/virtio-gpu.h
> +++ b/include/hw/virtio/virtio-gpu.h
> @@ -336,6 +336,7 @@ void virtio_gpu_virgl_fence_poll(VirtIOGPU *g);
>  void virtio_gpu_virgl_reset_scanout(VirtIOGPU *g);
>  void virtio_gpu_virgl_reset(VirtIOGPU *g);
>  int virtio_gpu_virgl_init(VirtIOGPU *g);
> +void virtio_gpu_virgl_deinit(VirtIOGPU *g);
>  int virtio_gpu_virgl_get_num_capsets(VirtIOGPU *g);
>
>  #endif
> --
> 2.44.0
>

otherwise:
Reviewed-by: Marc-André Lureau 


-- 
Marc-André Lureau



Re: [PATCH] ui/gtk: Explicitly set the default size of new window when untabifying

2024-05-07 Thread Marc-André Lureau
Hi

On Wed, May 1, 2024 at 7:47 AM  wrote:
>
> From: Dongwon Kim 
>
> When untabifying, the default size of the new window was inadvertently
> set to the size smaller than quarter of the primary window size due
> to lack of explicit configuration. This commit addresses the issue by
> ensuring that the size of untabified windows is set to match the surface
> size.

>From a quick test, I don't see a difference of behaviour after the
patch. Could you help me reproduce the issue?

I also don't think it is correct for two reasons:
- the inner display widget should cause a window size reconfiguration
- the window size != display size

thanks

> Cc: Gerd Hoffmann 
> Cc: Marc-André Lureau 
> Cc: Vivek Kasireddy 
> Signed-off-by: Dongwon Kim 
> ---
>  ui/gtk.c | 3 +++
>  1 file changed, 3 insertions(+)
>
> diff --git a/ui/gtk.c b/ui/gtk.c
> index 810d7fc796..269b8207d7 100644
> --- a/ui/gtk.c
> +++ b/ui/gtk.c
> @@ -1395,6 +1395,9 @@ static void gd_menu_untabify(GtkMenuItem *item, void 
> *opaque)
>  if (!vc->window) {
>  gtk_widget_set_sensitive(vc->menu_item, false);
>  vc->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
> +gtk_window_set_default_size(GTK_WINDOW(vc->window),
> +surface_width(vc->gfx.ds),
> +surface_height(vc->gfx.ds));
>  #if defined(CONFIG_OPENGL)
>  if (vc->gfx.esurface) {
>  eglDestroySurface(qemu_egl_display, vc->gfx.esurface);
> --
> 2.34.1
>
>


-- 
Marc-André Lureau



Re: [PATCH v2] ui/gtk: Draw guest frame at refresh cycle

2024-05-07 Thread Marc-André Lureau
On Sat, Apr 27, 2024 at 2:56 AM  wrote:
>
> From: Dongwon Kim 
>
> Draw routine needs to be manually invoked in the next refresh
> if there is a scanout blob from the guest. This is to prevent
> a situation where there is a scheduled draw event but it won't
> happen bacause the window is currently in inactive state
> (minimized or tabified). If draw is not done for a long time,
> gl_block timeout and/or fence timeout (on the guest) will happen
> eventually.
>
> v2: Use gd_gl_area_draw(vc) in gtk-gl-area.c
>
> Suggested-by: Vivek Kasireddy 
> Cc: Gerd Hoffmann 
> Cc: Marc-André Lureau 
> Cc: Daniel P. Berrangé 
> Signed-off-by: Dongwon Kim 

Acked-by: Marc-André Lureau 

> ---
>  ui/gtk-egl.c | 1 +
>  ui/gtk-gl-area.c | 1 +
>  2 files changed, 2 insertions(+)
>
> diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c
> index 3af5ac5bcf..75f6b9011a 100644
> --- a/ui/gtk-egl.c
> +++ b/ui/gtk-egl.c
> @@ -150,6 +150,7 @@ void gd_egl_refresh(DisplayChangeListener *dcl)
>  vc, vc->window ? vc->window : vc->gfx.drawing_area);
>
>  if (vc->gfx.guest_fb.dmabuf && vc->gfx.guest_fb.dmabuf->draw_submitted) {
> +gd_egl_draw(vc);
>  return;
>  }
>
> diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c
> index 52dcac161e..4fff957c3f 100644
> --- a/ui/gtk-gl-area.c
> +++ b/ui/gtk-gl-area.c
> @@ -126,6 +126,7 @@ void gd_gl_area_refresh(DisplayChangeListener *dcl)
>  gd_update_monitor_refresh_rate(vc, vc->window ? vc->window : 
> vc->gfx.drawing_area);
>
>      if (vc->gfx.guest_fb.dmabuf && vc->gfx.guest_fb.dmabuf->draw_submitted) {
> +gd_gl_area_draw(vc);
>  return;
>  }
>
> --
> 2.34.1
>
>


-- 
Marc-André Lureau



Re: [PATCH v3] input-linux: Add option to not grab a device upon guest startup

2024-05-07 Thread Marc-André Lureau
Hi

On Wed, Apr 3, 2024 at 9:51 AM Justinien Bouron
 wrote:
>
> Depending on your use-case, it might be inconvenient to have qemu grab
> the input device from the host immediately upon starting the guest.
>
> Added a new bool option to input-linux: grab-on-startup. If true, the
> device is grabbed as soon as the guest is started, otherwise it is not
> grabbed until the toggle combination is entered. To avoid breaking
> existing setups, the default value of grab-on-startup is true, i.e. same
> behaviour as before this change.
>
> Signed-off-by: Justinien Bouron 
> ---
>
> Changes since v2:
> - Added missing (since 9.1) to the new option in qapi/qom.json
>
>  qapi/qom.json| 14 +-
>  ui/input-linux.c | 20 +++-
>  2 files changed, 32 insertions(+), 2 deletions(-)
>
> diff --git a/qapi/qom.json b/qapi/qom.json
> index 85e6b4f84a..2067e41991 100644
> --- a/qapi/qom.json
> +++ b/qapi/qom.json
> @@ -508,13 +508,25 @@
>  # @grab-toggle: the key or key combination that toggles device grab
>  # (default: ctrl-ctrl)
>  #
> +# @grab-on-startup: if true, grab the device immediately upon starting
> +# the guest.  Otherwise, don't grab the device until the
> +# combination is entered.  This does not influence other devices
> +# even if grab_all is true, i.e. in the unlikely scenario where
> +# device1 has grab_all=true + grab-on-startup=true and device2 has
> +# grab-on-startup=false, only device1 is grabbed on startup, then,
> +# once the grab combination is entered, grabbing is toggled off
> +# for both devices (because device1 enforces the grab_all
> +# property) until the combination is entered again at which point
> +# both devices will be grabbed.  (default: true)  (since 9.1).
> +#
>  # Since: 2.6
>  ##
>  { 'struct': 'InputLinuxProperties',
>'data': { 'evdev': 'str',
>  '*grab_all': 'bool',
>  '*repeat': 'bool',
> -'*grab-toggle': 'GrabToggleKeys' } }
> +'*grab-toggle': 'GrabToggleKeys',
> +'*grab-on-startup': 'bool'} }
>
>  ##
>  # @EventLoopBaseProperties:
> diff --git a/ui/input-linux.c b/ui/input-linux.c
> index e572a2e905..68b5c6d485 100644
> --- a/ui/input-linux.c
> +++ b/ui/input-linux.c
> @@ -44,6 +44,7 @@ struct InputLinux {
>  boolgrab_request;
>  boolgrab_active;
>  boolgrab_all;
> +boolgrab_on_startup;
>  boolkeydown[KEY_CNT];
>  int keycount;
>  int wheel;
> @@ -400,7 +401,7 @@ static void input_linux_complete(UserCreatable *uc, Error 
> **errp)
>  if (il->keycount) {
>  /* delay grab until all keys are released */
>  il->grab_request = true;
> -} else {
> +} else if (il->grab_on_startup) {
>  input_linux_toggle_grab(il);
>  }

The patch looks ok to me, but you don't handle the case where keys are
pressed at startup and the grab is delayed. You could add a if
(!il->grab_on_startup) goto skip_grab, probably instead.

>  QTAILQ_INSERT_TAIL(, il, next);
> @@ -491,6 +492,19 @@ static void input_linux_set_grab_toggle(Object *obj, int 
> value,
>  il->grab_toggle = value;
>  }
>
> +static bool input_linux_get_grab_on_startup(Object *obj, Error **errp)
> +{
> +InputLinux *il = INPUT_LINUX(obj);
> +return il->grab_on_startup;
> +}
> +
> +static void input_linux_set_grab_on_startup(Object *obj, bool value,
> +Error **errp)
> +{
> +InputLinux *il = INPUT_LINUX(obj);
> +il->grab_on_startup = value;
> +}
> +
>  static void input_linux_instance_init(Object *obj)
>  {
>  }
> @@ -498,6 +512,7 @@ static void input_linux_instance_init(Object *obj)
>  static void input_linux_class_init(ObjectClass *oc, void *data)
>  {
>  UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
> +ObjectProperty *grab_on_startup_prop;
>
>  ucc->complete = input_linux_complete;
>
> @@ -514,6 +529,9 @@ static void input_linux_class_init(ObjectClass *oc, void 
> *data)
> _lookup,
> input_linux_get_grab_toggle,
> input_linux_set_grab_toggle);
> +grab_on_startup_prop = object_class_property_add_bool(oc, 
> "grab-on-startup",
> +input_linux_get_grab_on_startup, input_linux_set_grab_on_startup);
> +object_property_set_default_bool(grab_on_startup_prop, true);
>  }
>
>  static const TypeInfo input_linux_info = {
> --
> 2.44.0
>




Re: [PATCH v12 6/6] ui/console: move QemuDmaBuf struct def to dmabuf.c

2024-05-07 Thread Marc-André Lureau
On Thu, Apr 25, 2024 at 5:58 AM  wrote:
>
> From: Dongwon Kim 
>
> To complete privatizing process of QemuDmaBuf, QemuDmaBuf struct def
> is moved to dmabuf.c
>
> Suggested-by: Marc-André Lureau 
> Cc: Philippe Mathieu-Daudé 
> Cc: Daniel P. Berrangé 
> Cc: Vivek Kasireddy 
> Signed-off-by: Dongwon Kim 

Reviewed-by: Marc-André Lureau 

> ---
>  include/ui/dmabuf.h | 19 +--
>  ui/dmabuf.c | 19 +++
>  2 files changed, 20 insertions(+), 18 deletions(-)
>
> diff --git a/include/ui/dmabuf.h b/include/ui/dmabuf.h
> index 4198cdf85a..dc74ba895a 100644
> --- a/include/ui/dmabuf.h
> +++ b/include/ui/dmabuf.h
> @@ -10,24 +10,7 @@
>  #ifndef DMABUF_H
>  #define DMABUF_H
>
> -typedef struct QemuDmaBuf {
> -int   fd;
> -uint32_t  width;
> -uint32_t  height;
> -uint32_t  stride;
> -uint32_t  fourcc;
> -uint64_t  modifier;
> -uint32_t  texture;
> -uint32_t  x;
> -uint32_t  y;
> -uint32_t  backing_width;
> -uint32_t  backing_height;
> -bool  y0_top;
> -void  *sync;
> -int   fence_fd;
> -bool  allow_fences;
> -bool  draw_submitted;
> -} QemuDmaBuf;
> +typedef struct QemuDmaBuf QemuDmaBuf;
>
>  QemuDmaBuf *qemu_dmabuf_new(uint32_t width, uint32_t height,
>  uint32_t stride, uint32_t x,
> diff --git a/ui/dmabuf.c b/ui/dmabuf.c
> index e047d5ca26..df7a09703f 100644
> --- a/ui/dmabuf.c
> +++ b/ui/dmabuf.c
> @@ -10,6 +10,25 @@
>  #include "qemu/osdep.h"
>  #include "ui/dmabuf.h"
>
> +struct QemuDmaBuf {
> +int   fd;
> +uint32_t  width;
> +uint32_t  height;
> +uint32_t  stride;
> +uint32_t  fourcc;
> +uint64_t  modifier;
> +uint32_t  texture;
> +uint32_t  x;
> +uint32_t  y;
> +uint32_t  backing_width;
> +uint32_t  backing_height;
> +bool  y0_top;
> +void  *sync;
> +int   fence_fd;
> +bool  allow_fences;
> +bool  draw_submitted;
> +};
> +
>  QemuDmaBuf *qemu_dmabuf_new(uint32_t width, uint32_t height,
>  uint32_t stride, uint32_t x,
>  uint32_t y, uint32_t backing_width,
> --
> 2.34.1
>




Re: [PATCH v12 5/6] ui/console: Use qemu_dmabuf_new() and free() helpers instead

2024-05-07 Thread Marc-André Lureau
Hi

On Thu, Apr 25, 2024 at 5:58 AM  wrote:
>
> From: Dongwon Kim 
>
> This commit introduces utility functions for the creation and deallocation
> of QemuDmaBuf instances. Additionally, it updates all relevant sections
> of the codebase to utilize these new utility functions.
>
> v7: remove prefix, "dpy_gl_" from all helpers
> qemu_dmabuf_free() returns without doing anything if input is null
> (Daniel P. Berrangé )
> call G_DEFINE_AUTOPTR_CLEANUP_FUNC for qemu_dmabuf_free()
> (Daniel P. Berrangé )
>
> v8: Introduction of helpers was removed as those were already added
> by the previous commit
>
> v9: set dmabuf->allow_fences to 'true' when dmabuf is created in
> virtio_gpu_create_dmabuf()/virtio-gpu-udmabuf.c
>
> removed unnecessary spaces were accidently added in the patch,
> 'ui/console: Use qemu_dmabuf_new() a...'
>
> v11: Calling qemu_dmabuf_close was removed as closing dmabuf->fd will be
>  done in qemu_dmabuf_free anyway.
>  (Daniel P. Berrangé )
>
> v12: --- Calling qemu_dmabuf_close separately as qemu_dmabuf_free doesn't
>  do it.
>
>  --- 'dmabuf' is now allocated space so it should be freed at the end of
>  dbus_scanout_texture
>
> Suggested-by: Marc-André Lureau 
> Cc: Philippe Mathieu-Daudé 
> Cc: Daniel P. Berrangé 
> Cc: Vivek Kasireddy 
> Signed-off-by: Dongwon Kim 
> ---
>  include/hw/vfio/vfio-common.h   |  2 +-
>  include/hw/virtio/virtio-gpu.h  |  4 ++--
>  hw/display/vhost-user-gpu.c | 21 +++--
>  hw/display/virtio-gpu-udmabuf.c | 24 +---
>  hw/vfio/display.c   | 26 --
>  ui/dbus-listener.c  | 29 +
>  6 files changed, 48 insertions(+), 58 deletions(-)
>
> diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h
> index b9da6c08ef..d66e27db02 100644
> --- a/include/hw/vfio/vfio-common.h
> +++ b/include/hw/vfio/vfio-common.h
> @@ -148,7 +148,7 @@ typedef struct VFIOGroup {
>  } VFIOGroup;
>
>  typedef struct VFIODMABuf {
> -QemuDmaBuf buf;
> +QemuDmaBuf *buf;
>  uint32_t pos_x, pos_y, pos_updates;
>  uint32_t hot_x, hot_y, hot_updates;
>  int dmabuf_id;
> diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
> index ed44cdad6b..56d6e821bf 100644
> --- a/include/hw/virtio/virtio-gpu.h
> +++ b/include/hw/virtio/virtio-gpu.h
> @@ -169,7 +169,7 @@ struct VirtIOGPUBaseClass {
>  DEFINE_PROP_UINT32("yres", _state, _conf.yres, 800)
>
>  typedef struct VGPUDMABuf {
> -QemuDmaBuf buf;
> +QemuDmaBuf *buf;
>  uint32_t scanout_id;
>  QTAILQ_ENTRY(VGPUDMABuf) next;
>  } VGPUDMABuf;
> @@ -238,7 +238,7 @@ struct VhostUserGPU {
>  VhostUserBackend *vhost;
>  int vhost_gpu_fd; /* closed by the chardev */
>  CharBackend vhost_chr;
> -QemuDmaBuf dmabuf[VIRTIO_GPU_MAX_SCANOUTS];
> +QemuDmaBuf *dmabuf[VIRTIO_GPU_MAX_SCANOUTS];
>  bool backend_blocked;
>  };
>
> diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c
> index 454e5afcff..62e7b4376b 100644
> --- a/hw/display/vhost-user-gpu.c
> +++ b/hw/display/vhost-user-gpu.c
> @@ -249,6 +249,7 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, 
> VhostUserGpuMsg *msg)
>  case VHOST_USER_GPU_DMABUF_SCANOUT: {
>  VhostUserGpuDMABUFScanout *m = >payload.dmabuf_scanout;
>  int fd = qemu_chr_fe_get_msgfd(>vhost_chr);
> +uint64_t modifier = 0;
>  QemuDmaBuf *dmabuf;
>
>  if (m->scanout_id >= g->parent_obj.conf.max_outputs) {
> @@ -261,27 +262,27 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, 
> VhostUserGpuMsg *msg)
>
>  g->parent_obj.enable = 1;
>  con = g->parent_obj.scanout[m->scanout_id].con;
> -dmabuf = >dmabuf[m->scanout_id];
> +dmabuf = g->dmabuf[m->scanout_id];
>  qemu_dmabuf_close(dmabuf);
>  dpy_gl_release_dmabuf(con, dmabuf);
> +g_clear_pointer(, qemu_dmabuf_free);

This will create a dangling pointer in g->dmabuf[m->scanout_id]...

>  if (fd == -1) {
>  dpy_gl_scanout_disable(con);
>  break;

.. which may persist here

>  }
> -*dmabuf = (QemuDmaBuf) {
> -.fd = fd,
> -.width = m->fd_width,
> -.height = m->fd_height,
> -.stride = m->fd_stride,
> -.fourcc = m->fd_drm_fourcc,
> -.y0_top = m->fd_flags & VIRTIO_GPU_RESOURCE_FLAG_Y_0_TOP,
> -};
>  if (msg->request == VHOST_USER_GPU_DM

Re: [PATCH v12 4/6] ui/console: Use qemu_dmabuf_set_..() helpers instead

2024-05-07 Thread Marc-André Lureau
Hi

On Thu, Apr 25, 2024 at 5:58 AM  wrote:
>
> From: Dongwon Kim 
>
> This commit updates all occurrences where these fields were
> set directly have been updated to utilize helper functions.
>
> v7: removed prefix, "dpy_gl_" from all helpers
>
> v8: Introduction of helpers was removed as those were already added
> by the previous commit
>
> Suggested-by: Marc-André Lureau 

Reviewed-by: Marc-André Lureau 

> Cc: Philippe Mathieu-Daudé 
> Cc: Daniel P. Berrangé 
> Cc: Vivek Kasireddy 
> Signed-off-by: Dongwon Kim 
> ---
>  ui/egl-helpers.c | 16 +---
>  ui/gtk-egl.c |  4 ++--
>  ui/gtk-gl-area.c |  4 ++--
>  ui/gtk.c |  6 +++---
>  4 files changed, 16 insertions(+), 14 deletions(-)
>
> diff --git a/ui/egl-helpers.c b/ui/egl-helpers.c
> index 3f96e63d25..99b2ebbe23 100644
> --- a/ui/egl-helpers.c
> +++ b/ui/egl-helpers.c
> @@ -348,8 +348,8 @@ void egl_dmabuf_import_texture(QemuDmaBuf *dmabuf)
>  return;
>  }
>
> -glGenTextures(1, >texture);
> -texture = qemu_dmabuf_get_texture(dmabuf);
> +glGenTextures(1, );
> +qemu_dmabuf_set_texture(dmabuf, texture);
>  glBindTexture(GL_TEXTURE_2D, texture);
>  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
>  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
> @@ -368,7 +368,7 @@ void egl_dmabuf_release_texture(QemuDmaBuf *dmabuf)
>  }
>
>  glDeleteTextures(1, );
> -dmabuf->texture = 0;
> +qemu_dmabuf_set_texture(dmabuf, 0);
>  }
>
>  void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf)
> @@ -382,7 +382,7 @@ void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf)
>  sync = eglCreateSyncKHR(qemu_egl_display,
>  EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
>  if (sync != EGL_NO_SYNC_KHR) {
> -dmabuf->sync = sync;
> +qemu_dmabuf_set_sync(dmabuf, sync);
>  }
>  }
>  }
> @@ -390,12 +390,14 @@ void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf)
>  void egl_dmabuf_create_fence(QemuDmaBuf *dmabuf)
>  {
>  void *sync = qemu_dmabuf_get_sync(dmabuf);
> +int fence_fd;
>
>  if (sync) {
> -dmabuf->fence_fd = eglDupNativeFenceFDANDROID(qemu_egl_display,
> -  sync);
> +fence_fd = eglDupNativeFenceFDANDROID(qemu_egl_display,
> +  sync);
> +qemu_dmabuf_set_fence_fd(dmabuf, fence_fd);
>  eglDestroySyncKHR(qemu_egl_display, sync);
> -dmabuf->sync = NULL;
> +qemu_dmabuf_set_sync(dmabuf, NULL);
>  }
>  }
>
> diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c
> index 7a45daefa1..ec0bf45482 100644
> --- a/ui/gtk-egl.c
> +++ b/ui/gtk-egl.c
> @@ -87,7 +87,7 @@ void gd_egl_draw(VirtualConsole *vc)
>  if (!qemu_dmabuf_get_draw_submitted(dmabuf)) {
>  return;
>  } else {
> -dmabuf->draw_submitted = false;
> +qemu_dmabuf_set_draw_submitted(dmabuf, false);
>  }
>  }
>  #endif
> @@ -381,7 +381,7 @@ void gd_egl_flush(DisplayChangeListener *dcl,
>  if (vc->gfx.guest_fb.dmabuf &&
>  !qemu_dmabuf_get_draw_submitted(vc->gfx.guest_fb.dmabuf)) {
>  graphic_hw_gl_block(vc->gfx.dcl.con, true);
> -vc->gfx.guest_fb.dmabuf->draw_submitted = true;
> +qemu_dmabuf_set_draw_submitted(vc->gfx.guest_fb.dmabuf, true);
>  gtk_egl_set_scanout_mode(vc, true);
>  gtk_widget_queue_draw_area(area, x, y, w, h);
>  return;
> diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c
> index 2d70280803..9a3f3d0d71 100644
> --- a/ui/gtk-gl-area.c
> +++ b/ui/gtk-gl-area.c
> @@ -63,7 +63,7 @@ void gd_gl_area_draw(VirtualConsole *vc)
>  if (!qemu_dmabuf_get_draw_submitted(dmabuf)) {
>  return;
>  } else {
> -dmabuf->draw_submitted = false;
> +qemu_dmabuf_set_draw_submitted(dmabuf, false);
>  }
>  }
>  #endif
> @@ -291,7 +291,7 @@ void gd_gl_area_scanout_flush(DisplayChangeListener *dcl,
>  if (vc->gfx.guest_fb.dmabuf &&
>  !qemu_dmabuf_get_draw_submitted(vc->gfx.guest_fb.dmabuf)) {
>  graphic_hw_gl_block(vc->gfx.dcl.con, true);
> -vc->gfx.guest_fb.dmabuf->draw_submitted = true;
> +qemu_dmabuf_set_draw_submitted(vc->gfx.guest_fb.dmabuf, true);
>  gtk_gl_area_set_scanout_mode(vc, true);
>  }
>  gtk_gl_area_queue_render(GTK_GL_AREA(vc->gfx.drawing_area));
> diff --git a/ui/gtk.c b/u

Re: [PATCH v12 2/6] ui/console: new dmabuf.h and dmabuf.c for QemuDmaBuf struct and helpers

2024-05-07 Thread Marc-André Lureau
On Thu, Apr 25, 2024 at 5:58 AM  wrote:
>
> From: Dongwon Kim 
>
> New header and source files are added for containing QemuDmaBuf struct
> definition and newly introduced helpers for creating/freeing the struct
> and accessing its data.
>
> v10: Change the license type for both dmabuf.h and dmabuf.c from MIT to
>  GPL to be in line with QEMU's default license
>
> v11: -- Added new helpers, qemu_dmabuf_close for closing dmabuf->fd,
> qemu_dmabuf_dup_fd for duplicating dmabuf->fd
> (Daniel P. Berrangé )
>
>  -- Let qemu_dmabuf_fee to call qemu_dmabuf_close before freeing
> the struct to make sure fd is closed.
> (Daniel P. Berrangé )
>
> v12: Not closing fd in qemu_dmabuf_free because there are cases fd
>  should still be available even after the struct is destroyed
>  (e.g. virtio-gpu: res->dmabuf_fd).
>
> Suggested-by: Marc-André Lureau 
> Cc: Philippe Mathieu-Daudé 
> Cc: Daniel P. Berrangé 
> Cc: Vivek Kasireddy 
> Signed-off-by: Dongwon Kim 

Reviewed-by: Marc-André Lureau 

> ---
>  include/ui/console.h |  20 +
>  include/ui/dmabuf.h  |  66 ++
>  ui/dmabuf.c  | 210 +++
>  ui/meson.build   |   1 +
>  4 files changed, 278 insertions(+), 19 deletions(-)
>  create mode 100644 include/ui/dmabuf.h
>  create mode 100644 ui/dmabuf.c
>
> diff --git a/include/ui/console.h b/include/ui/console.h
> index 0bc7a00ac0..a208a68b88 100644
> --- a/include/ui/console.h
> +++ b/include/ui/console.h
> @@ -7,6 +7,7 @@
>  #include "qapi/qapi-types-ui.h"
>  #include "ui/input.h"
>  #include "ui/surface.h"
> +#include "ui/dmabuf.h"
>
>  #define TYPE_QEMU_CONSOLE "qemu-console"
>  OBJECT_DECLARE_TYPE(QemuConsole, QemuConsoleClass, QEMU_CONSOLE)
> @@ -185,25 +186,6 @@ struct QEMUGLParams {
>  int minor_ver;
>  };
>
> -typedef struct QemuDmaBuf {
> -int   fd;
> -uint32_t  width;
> -uint32_t  height;
> -uint32_t  stride;
> -uint32_t  fourcc;
> -uint64_t  modifier;
> -uint32_t  texture;
> -uint32_t  x;
> -uint32_t  y;
> -uint32_t  backing_width;
> -uint32_t  backing_height;
> -bool  y0_top;
> -void  *sync;
> -int   fence_fd;
> -bool  allow_fences;
> -bool  draw_submitted;
> -} QemuDmaBuf;
> -
>  enum display_scanout {
>  SCANOUT_NONE,
>  SCANOUT_SURFACE,
> diff --git a/include/ui/dmabuf.h b/include/ui/dmabuf.h
> new file mode 100644
> index 00..4198cdf85a
> --- /dev/null
> +++ b/include/ui/dmabuf.h
> @@ -0,0 +1,66 @@
> +/*
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + *
> + * QemuDmaBuf struct and helpers used for accessing its data
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2 or later.
> + * See the COPYING file in the top-level directory.
> + */
> +
> +#ifndef DMABUF_H
> +#define DMABUF_H
> +
> +typedef struct QemuDmaBuf {
> +int   fd;
> +uint32_t  width;
> +uint32_t  height;
> +uint32_t  stride;
> +uint32_t  fourcc;
> +uint64_t  modifier;
> +uint32_t  texture;
> +uint32_t  x;
> +uint32_t  y;
> +uint32_t  backing_width;
> +uint32_t  backing_height;
> +bool  y0_top;
> +void  *sync;
> +int   fence_fd;
> +bool  allow_fences;
> +bool  draw_submitted;
> +} QemuDmaBuf;
> +
> +QemuDmaBuf *qemu_dmabuf_new(uint32_t width, uint32_t height,
> +uint32_t stride, uint32_t x,
> +uint32_t y, uint32_t backing_width,
> +uint32_t backing_height, uint32_t fourcc,
> +uint64_t modifier, int dmabuf_fd,
> +bool allow_fences, bool y0_top);
> +void qemu_dmabuf_free(QemuDmaBuf *dmabuf);
> +
> +G_DEFINE_AUTOPTR_CLEANUP_FUNC(QemuDmaBuf, qemu_dmabuf_free);
> +
> +int qemu_dmabuf_get_fd(QemuDmaBuf *dmabuf);
> +int qemu_dmabuf_dup_fd(QemuDmaBuf *dmabuf);
> +void qemu_dmabuf_close(QemuDmaBuf *dmabuf);
> +uint32_t qemu_dmabuf_get_width(QemuDmaBuf *dmabuf);
> +uint32_t qemu_dmabuf_get_height(QemuDmaBuf *dmabuf);
> +uint32_t qemu_dmabuf_get_stride(QemuDmaBuf *dmabuf);
> +uint32_t qemu_dmabuf_get_fourcc(QemuDmaBuf *dmabuf);
> +uint64_t qemu_dmabuf_get_modifier(QemuDmaBuf *dmabuf);
> +uint32_t qemu_dmabuf_get_texture(QemuDmaBuf *dmabuf);
> +uint32_t qemu_dmabuf_get_x(QemuDmaBuf *dmabuf);
> +uint32_t qemu_dmabuf_get_y(QemuDmaBuf *dmabuf);
> +uint32_t qemu_dmabuf_get_backing_width(QemuDmaBuf *dmabuf);
> +uint32_t qemu_dmabuf_get_bac

Re: [PULL 5/5] virtio-gpu: fix scanout migration post-load

2024-05-07 Thread Marc-André Lureau
Hi

On Tue, Apr 30, 2024 at 4:31 PM Fiona Ebner  wrote:
>
> Am 12.03.24 um 15:02 schrieb marcandre.lur...@redhat.com:
> > From: Marc-André Lureau 
> >
> > The current post-loading code for scanout has a FIXME: it doesn't take
> > the resource region/rect into account. But there is more, when adding
> > blob migration support in commit f66767f75c9, I didn't realize that blob
> > resources could be used for scanouts. This situationn leads to a crash
> > during post-load, as they don't have an associated res->image.
> >
> > virtio_gpu_do_set_scanout() handle all cases, but requires the
> > associated virtio_gpu_framebuffer, which is currently not saved during
> > migration.
> >
> > Add a v2 of "virtio-gpu-one-scanout" with the framebuffer fields, so we
> > can restore blob scanouts, as well as fixing the existing FIXME.
> >
> > Signed-off-by: Marc-André Lureau 
> > Reviewed-by: Sebastian Ott 
>
> Hi,
> unfortunately, this broke migration from pre-9.0 to 9.0:
>
> > vmstate_load_state_field virtio-gpu:virtio-gpu
> > vmstate_load_state_field virtio-gpu-scanouts:parent_obj.enable
> > vmstate_load_state_field virtio-gpu-scanouts:parent_obj.conf.max_outputs
> > vmstate_load_state_field virtio-gpu-scanouts:parent_obj.scanout
> > vmstate_load_state_field virtio-gpu-one-scanout:resource_id
> > vmstate_load_state_field virtio-gpu-one-scanout:width
> > vmstate_load_state_field virtio-gpu-one-scanout:height
> > vmstate_load_state_field virtio-gpu-one-scanout:x
> > vmstate_load_state_field virtio-gpu-one-scanout:y
> > vmstate_load_state_field virtio-gpu-one-scanout:cursor.resource_id
> > vmstate_load_state_field virtio-gpu-one-scanout:cursor.hot_x
> > vmstate_load_state_field virtio-gpu-one-scanout:cursor.hot_y
> > vmstate_load_state_field virtio-gpu-one-scanout:cursor.pos.x
> > vmstate_load_state_field virtio-gpu-one-scanout:cursor.pos.y
> > vmstate_load_state_field virtio-gpu-one-scanout:fb.format
> > vmstate_load_state_field virtio-gpu-one-scanout:fb.bytes_pp
> > vmstate_load_state_field virtio-gpu-one-scanout:fb.width
> > vmstate_load_state_field virtio-gpu-one-scanout:fb.height
> > vmstate_load_state_field virtio-gpu-one-scanout:fb.stride
> > vmstate_load_state_field virtio-gpu-one-scanout:fb.offset
> > qemu-system-x86_64: Missing section footer for :00:02.0/virtio-gpu
> > qemu-system-x86_64: Error -22 while loading VM state
>
> It wrongly tries to load the fb fields even though they should be
> guarded by version 2.
>
> Looking at it with GDB, in vmstate_load_state(), when we come to
> field->name == parent_obj.scanout, the
>
> > } else if (field->flags & VMS_STRUCT) {
> > ret = vmstate_load_state(f, field->vmsd, curr_elem,
> >  field->vmsd->version_id);
>
> branch will be taken and suddenly we'll have a call to
> vmstate_load_state() for vmsd==vmstate_virtio_gpu_scanout with
> version_id==2 rather than version_id==1, because that is
> field->vmsd->version_id (i.e. the .version_id in VMStateDescription
> vmstate_virtio_gpu_scanout).
>
> Would it have been necessary to version the VMStateDescription
> vmstate_virtio_gpu_scanouts too using VMS_VSTRUCT (or am I
> misinterpreting the use case for that)?
>

Sigh.. this is embarrassing. This patch didn't receive enough testing
and breaks pre-9.0/9.0 forward and backward migrations.

I think it would be reasonable to revert the patch, but it's already
in 9.0. Is that acceptable?

There are various issues about versioning:
- VMStateDescription (vmsd) version_id are not in the stream (only
start & full section headers), so any nested version bump should
somehow be bubbled up/down..
- machine versions don't have specific vmsd version_id associations
(that I can see, or is there any way to do that?)
- virtio-gpu uses even lower-level vmstate API and hardcodes version
to 1 in general

Ideally, I wished adding versionized fields the way done in this patch
would simply work, but this is really, sadly, not supported atm.

And it would be great to have some testing for back/forward migrations.

Any thoughts, corrections, encouragement perhaps? :)

thanks


--
Marc-André Lureau



Re: [PATCH v6 1/3] ui/console: Introduce dpy_gl_qemu_dmabuf_get_..() helpers

2024-04-17 Thread Marc-André Lureau
Hi

On Wed, Apr 17, 2024 at 9:06 PM Kim, Dongwon  wrote:
>
> Hi Daniel,
>
> > -Original Message-
> > From: Daniel P. Berrangé 
> > Sent: Wednesday, April 17, 2024 4:05 AM
> > To: Kim, Dongwon 
> > Cc: qemu-devel@nongnu.org; marcandre.lur...@redhat.com
> > Subject: Re: [PATCH v6 1/3] ui/console: Introduce
> > dpy_gl_qemu_dmabuf_get_..() helpers
> >
> > On Tue, Apr 16, 2024 at 09:09:52PM -0700, dongwon@intel.com wrote:
> > > From: Dongwon Kim 
> > >
> > > This commit introduces dpy_gl_qemu_dmabuf_get_... helpers to extract
> > > specific fields from the QemuDmaBuf struct. It also updates all
> > > instances where fields within the QemuDmaBuf struct are directly
> > > accessed, replacing them with calls to these new helper functions.
> > >
> > > v6: fix typos in helper names in ui/spice-display.c
> > >
> > > Suggested-by: Marc-André Lureau 
> > > Cc: Philippe Mathieu-Daudé 
> > > Cc: Vivek Kasireddy 
> > > Signed-off-by: Dongwon Kim 
> > > ---
> > >  include/ui/console.h|  17 +
> > >  hw/display/vhost-user-gpu.c |   6 +-
> > >  hw/display/virtio-gpu-udmabuf.c |   7 +-
> > >  hw/vfio/display.c   |  15 +++--
> > >  ui/console.c| 116 +++-
> > >  ui/dbus-console.c   |   9 ++-
> > >  ui/dbus-listener.c  |  43 +++-
> > >  ui/egl-headless.c   |  23 +--
> > >  ui/egl-helpers.c|  47 +++--
> > >  ui/gtk-egl.c|  48 -
> > >  ui/gtk-gl-area.c|  37 ++
> > >  ui/gtk.c|   6 +-
> > >  ui/spice-display.c  |  50 --
> > >  13 files changed, 316 insertions(+), 108 deletions(-)
> > >
> > > diff --git a/include/ui/console.h b/include/ui/console.h index
> > > 0bc7a00ac0..6292943a82 100644
> > > --- a/include/ui/console.h
> > > +++ b/include/ui/console.h
> > > @@ -358,6 +358,23 @@ void dpy_gl_cursor_dmabuf(QemuConsole *con,
> > QemuDmaBuf *dmabuf,
> > >bool have_hot, uint32_t hot_x, uint32_t
> > > hot_y);  void dpy_gl_cursor_position(QemuConsole *con,
> > >  uint32_t pos_x, uint32_t pos_y);
> > > +
> > > +int32_t dpy_gl_qemu_dmabuf_get_fd(QemuDmaBuf *dmabuf); uint32_t
> > > +dpy_gl_qemu_dmabuf_get_width(QemuDmaBuf *dmabuf); uint32_t
> > > +dpy_gl_qemu_dmabuf_get_height(QemuDmaBuf *dmabuf); uint32_t
> > > +dpy_gl_qemu_dmabuf_get_stride(QemuDmaBuf *dmabuf); uint32_t
> > > +dpy_gl_qemu_dmabuf_get_fourcc(QemuDmaBuf *dmabuf); uint64_t
> > > +dpy_gl_qemu_dmabuf_get_modifier(QemuDmaBuf *dmabuf); uint32_t
> > > +dpy_gl_qemu_dmabuf_get_texture(QemuDmaBuf *dmabuf); uint32_t
> > > +dpy_gl_qemu_dmabuf_get_x(QemuDmaBuf *dmabuf); uint32_t
> > > +dpy_gl_qemu_dmabuf_get_y(QemuDmaBuf *dmabuf); uint32_t
> > > +dpy_gl_qemu_dmabuf_get_backing_width(QemuDmaBuf *dmabuf);
> > uint32_t
> > > +dpy_gl_qemu_dmabuf_get_backing_height(QemuDmaBuf *dmabuf); bool
> > > +dpy_gl_qemu_dmabuf_get_y0_top(QemuDmaBuf *dmabuf); void
> > > +*dpy_gl_qemu_dmabuf_get_sync(QemuDmaBuf *dmabuf); int32_t
> > > +dpy_gl_qemu_dmabuf_get_fence_fd(QemuDmaBuf *dmabuf); bool
> > > +dpy_gl_qemu_dmabuf_get_allow_fences(QemuDmaBuf *dmabuf); bool
> > > +dpy_gl_qemu_dmabuf_get_draw_submitted(QemuDmaBuf *dmabuf);
> >
> > IMHO these method names don't need a "dpy_gl_" prefix on them. Since
> > they're accessors for the "QemuDmaBuf" struct, I think its sufficient to 
> > just
> > have "qemu_dmabuf_" as the name prefix, making names more compact.
> >
> > The console.{h,c} files are a bit of a dumping ground for UI code. While
> > QemuDmaBuf was just a struct with direct field access that's OK.
> >
> > With turning this into a more of an object with accessors, I think it would 
> > also
> > be desirable to move the struct definition and all its methods into separate
> > ui/dmabuf.{c,h} files, so its fully self-contained.
>
> [Kim, Dongwon] I am ok with changing function names and create
> separate c and h for dmabuf helpers as you suggested. But I would
> like to hear Marc-André's opinion about this suggestion before I make
> such changes.
>
> Marc-André, do you have any thought on Daniel's suggestion?

Sure, I was about to ask the same. Anything we can do to slim
ui/console.c helps :)




Re: [PATCH v6 3/3] ui/console: Introduce dpy_gl_qemu_dmabuf_new() and free() helpers

2024-04-17 Thread Marc-André Lureau
On Wed, Apr 17, 2024 at 8:14 AM  wrote:
>
> From: Dongwon Kim 
>
> This commit introduces utility functions for the creation and deallocation
> of QemuDmaBuf instances. Additionally, it updates all relevant sections
> of the codebase to utilize these new utility functions.
>
> Suggested-by: Marc-André Lureau 
> Cc: Philippe Mathieu-Daudé 
> Cc: Vivek Kasireddy 
> Signed-off-by: Dongwon Kim 
> ---
>  include/hw/vfio/vfio-common.h   |  2 +-
>  include/hw/virtio/virtio-gpu.h  |  4 ++--
>  include/ui/console.h|  8 +++-
>  hw/display/vhost-user-gpu.c | 32 +--
>  hw/display/virtio-gpu-udmabuf.c | 24 +--
>  hw/vfio/display.c   | 26 -
>  ui/console.c| 34 +
>  ui/dbus-listener.c  | 28 ---
>  8 files changed, 95 insertions(+), 63 deletions(-)
>
> diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h
> index b9da6c08ef..d66e27db02 100644
> --- a/include/hw/vfio/vfio-common.h
> +++ b/include/hw/vfio/vfio-common.h
> @@ -148,7 +148,7 @@ typedef struct VFIOGroup {
>  } VFIOGroup;
>
>  typedef struct VFIODMABuf {
> -QemuDmaBuf buf;
> +QemuDmaBuf *buf;
>  uint32_t pos_x, pos_y, pos_updates;
>  uint32_t hot_x, hot_y, hot_updates;
>  int dmabuf_id;
> diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
> index ed44cdad6b..56d6e821bf 100644
> --- a/include/hw/virtio/virtio-gpu.h
> +++ b/include/hw/virtio/virtio-gpu.h
> @@ -169,7 +169,7 @@ struct VirtIOGPUBaseClass {
>  DEFINE_PROP_UINT32("yres", _state, _conf.yres, 800)
>
>  typedef struct VGPUDMABuf {
> -QemuDmaBuf buf;
> +QemuDmaBuf *buf;
>  uint32_t scanout_id;
>  QTAILQ_ENTRY(VGPUDMABuf) next;
>  } VGPUDMABuf;
> @@ -238,7 +238,7 @@ struct VhostUserGPU {
>  VhostUserBackend *vhost;
>  int vhost_gpu_fd; /* closed by the chardev */
>  CharBackend vhost_chr;
> -QemuDmaBuf dmabuf[VIRTIO_GPU_MAX_SCANOUTS];
> +QemuDmaBuf *dmabuf[VIRTIO_GPU_MAX_SCANOUTS];
>  bool backend_blocked;
>  };
>
> diff --git a/include/ui/console.h b/include/ui/console.h
> index 3d9d8b9fce..6d7c03b7c5 100644
> --- a/include/ui/console.h
> +++ b/include/ui/console.h
> @@ -358,7 +358,13 @@ void dpy_gl_cursor_dmabuf(QemuConsole *con, QemuDmaBuf 
> *dmabuf,
>bool have_hot, uint32_t hot_x, uint32_t hot_y);
>  void dpy_gl_cursor_position(QemuConsole *con,
>  uint32_t pos_x, uint32_t pos_y);
> -
> +QemuDmaBuf *dpy_gl_qemu_dmabuf_new(uint32_t width, uint32_t height,
> +   uint32_t stride, uint32_t x,
> +   uint32_t y, uint32_t backing_width,
> +   uint32_t backing_height, uint32_t fourcc,
> +   uint64_t modifier, uint32_t dmabuf_fd,

An fd is an int.

> +   bool allow_fences, bool y0_top);
> +void dpy_gl_qemu_dmabuf_free(QemuDmaBuf *dmabuf);
>  int32_t dpy_gl_qemu_dmabuf_get_fd(QemuDmaBuf *dmabuf);
>  uint32_t dpy_gl_qemu_dmabuf_get_width(QemuDmaBuf *dmabuf);
>  uint32_t dpy_gl_qemu_dmabuf_get_height(QemuDmaBuf *dmabuf);
> diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c
> index 87dcfbca10..4d8461e94a 100644
> --- a/hw/display/vhost-user-gpu.c
> +++ b/hw/display/vhost-user-gpu.c
> @@ -250,6 +250,7 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, 
> VhostUserGpuMsg *msg)
>  VhostUserGpuDMABUFScanout *m = >payload.dmabuf_scanout;
>  int fd = qemu_chr_fe_get_msgfd(>vhost_chr);
>  int old_fd;
> +uint64_t modifier = 0;
>  QemuDmaBuf *dmabuf;
>
>  if (m->scanout_id >= g->parent_obj.conf.max_outputs) {
> @@ -262,31 +263,34 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, 
> VhostUserGpuMsg *msg)
>
>  g->parent_obj.enable = 1;
>  con = g->parent_obj.scanout[m->scanout_id].con;
> -dmabuf = >dmabuf[m->scanout_id];
> -old_fd = dpy_gl_qemu_dmabuf_get_fd(dmabuf);
> -if (old_fd >= 0) {
> -close(old_fd);
> -dmabuf->fd = -1;
> +dmabuf = g->dmabuf[m->scanout_id];
> +if (dmabuf) {
> +old_fd = dpy_gl_qemu_dmabuf_get_fd(dmabuf);
> +if (old_fd >= 0) {
> +close(old_fd);
> +dpy_gl_qemu_dmabuf_set_fd(dmabuf, -1);
> +}
>  }
>  dpy_gl_release_dmabuf(con, dmabuf);
> +g_clear_pointer(, dp

Re: [PATCH v6 1/3] ui/console: Introduce dpy_gl_qemu_dmabuf_get_..() helpers

2024-04-17 Thread Marc-André Lureau
Hi

On Wed, Apr 17, 2024 at 8:14 AM  wrote:
>
> From: Dongwon Kim 
>
> This commit introduces dpy_gl_qemu_dmabuf_get_... helpers to extract
> specific fields from the QemuDmaBuf struct. It also updates all instances
> where fields within the QemuDmaBuf struct are directly accessed, replacing
> them with calls to these new helper functions.
>
> v6: fix typos in helper names in ui/spice-display.c
>
> Suggested-by: Marc-André Lureau 
> Cc: Philippe Mathieu-Daudé 
> Cc: Vivek Kasireddy 
> Signed-off-by: Dongwon Kim 
> ---
>  include/ui/console.h|  17 +
>  hw/display/vhost-user-gpu.c |   6 +-
>  hw/display/virtio-gpu-udmabuf.c |   7 +-
>  hw/vfio/display.c   |  15 +++--
>  ui/console.c| 116 +++-
>  ui/dbus-console.c   |   9 ++-
>  ui/dbus-listener.c  |  43 +++-
>  ui/egl-headless.c   |  23 +--
>  ui/egl-helpers.c|  47 +++--
>  ui/gtk-egl.c|  48 -
>  ui/gtk-gl-area.c|  37 ++
>  ui/gtk.c|   6 +-
>  ui/spice-display.c  |  50 --
>  13 files changed, 316 insertions(+), 108 deletions(-)
>
> diff --git a/include/ui/console.h b/include/ui/console.h
> index 0bc7a00ac0..6292943a82 100644
> --- a/include/ui/console.h
> +++ b/include/ui/console.h
> @@ -358,6 +358,23 @@ void dpy_gl_cursor_dmabuf(QemuConsole *con, QemuDmaBuf 
> *dmabuf,
>bool have_hot, uint32_t hot_x, uint32_t hot_y);
>  void dpy_gl_cursor_position(QemuConsole *con,
>  uint32_t pos_x, uint32_t pos_y);
> +
> +int32_t dpy_gl_qemu_dmabuf_get_fd(QemuDmaBuf *dmabuf);
> +uint32_t dpy_gl_qemu_dmabuf_get_width(QemuDmaBuf *dmabuf);
> +uint32_t dpy_gl_qemu_dmabuf_get_height(QemuDmaBuf *dmabuf);
> +uint32_t dpy_gl_qemu_dmabuf_get_stride(QemuDmaBuf *dmabuf);
> +uint32_t dpy_gl_qemu_dmabuf_get_fourcc(QemuDmaBuf *dmabuf);
> +uint64_t dpy_gl_qemu_dmabuf_get_modifier(QemuDmaBuf *dmabuf);
> +uint32_t dpy_gl_qemu_dmabuf_get_texture(QemuDmaBuf *dmabuf);
> +uint32_t dpy_gl_qemu_dmabuf_get_x(QemuDmaBuf *dmabuf);
> +uint32_t dpy_gl_qemu_dmabuf_get_y(QemuDmaBuf *dmabuf);
> +uint32_t dpy_gl_qemu_dmabuf_get_backing_width(QemuDmaBuf *dmabuf);
> +uint32_t dpy_gl_qemu_dmabuf_get_backing_height(QemuDmaBuf *dmabuf);
> +bool dpy_gl_qemu_dmabuf_get_y0_top(QemuDmaBuf *dmabuf);
> +void *dpy_gl_qemu_dmabuf_get_sync(QemuDmaBuf *dmabuf);
> +int32_t dpy_gl_qemu_dmabuf_get_fence_fd(QemuDmaBuf *dmabuf);
> +bool dpy_gl_qemu_dmabuf_get_allow_fences(QemuDmaBuf *dmabuf);
> +bool dpy_gl_qemu_dmabuf_get_draw_submitted(QemuDmaBuf *dmabuf);
>  void dpy_gl_release_dmabuf(QemuConsole *con,
> QemuDmaBuf *dmabuf);
>  void dpy_gl_update(QemuConsole *con,
> diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c
> index 709c8a02a1..87dcfbca10 100644
> --- a/hw/display/vhost-user-gpu.c
> +++ b/hw/display/vhost-user-gpu.c
> @@ -249,6 +249,7 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, 
> VhostUserGpuMsg *msg)
>  case VHOST_USER_GPU_DMABUF_SCANOUT: {
>  VhostUserGpuDMABUFScanout *m = >payload.dmabuf_scanout;
>  int fd = qemu_chr_fe_get_msgfd(>vhost_chr);
> +int old_fd;
>  QemuDmaBuf *dmabuf;
>
>  if (m->scanout_id >= g->parent_obj.conf.max_outputs) {
> @@ -262,8 +263,9 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, 
> VhostUserGpuMsg *msg)
>  g->parent_obj.enable = 1;
>  con = g->parent_obj.scanout[m->scanout_id].con;
>  dmabuf = >dmabuf[m->scanout_id];
> -if (dmabuf->fd >= 0) {
> -close(dmabuf->fd);
> +old_fd = dpy_gl_qemu_dmabuf_get_fd(dmabuf);
> +if (old_fd >= 0) {
> +close(old_fd);
>  dmabuf->fd = -1;
>  }
>  dpy_gl_release_dmabuf(con, dmabuf);
> diff --git a/hw/display/virtio-gpu-udmabuf.c b/hw/display/virtio-gpu-udmabuf.c
> index d51184d658..e3f358b575 100644
> --- a/hw/display/virtio-gpu-udmabuf.c
> +++ b/hw/display/virtio-gpu-udmabuf.c
> @@ -206,6 +206,7 @@ int virtio_gpu_update_dmabuf(VirtIOGPU *g,
>  {
>  struct virtio_gpu_scanout *scanout = >parent_obj.scanout[scanout_id];
>  VGPUDMABuf *new_primary, *old_primary = NULL;
> +uint32_t width, height;
>
>  new_primary = virtio_gpu_create_dmabuf(g, scanout_id, res, fb, r);
>  if (!new_primary) {
> @@ -216,10 +217,10 @@ int virtio_gpu_update_dmabuf(VirtIOGPU *g,
>  old_primary = g->dmabuf.primary[scanout_id];
>  }
>
> +width = dpy_gl_qemu_dmabuf_get_width(_primary->buf

Re: [PATCH v5 1/3] ui/console: Introduce dpy_gl_qemu_dmabuf_get_..() helpers

2024-04-16 Thread Marc-André Lureau
Hi

On Tue, Apr 16, 2024 at 3:11 AM  wrote:
>
> From: Dongwon Kim 
>
> This commit introduces dpy_gl_qemu_dmabuf_get_... helpers to extract
> specific fields from the QemuDmaBuf struct. It also updates all instances
> where fields within the QemuDmaBuf struct are directly accessed, replacing
> them with calls to these new helper functions.
>
> Suggested-by: Marc-André Lureau 
> Cc: Philippe Mathieu-Daudé 
> Cc: Vivek Kasireddy 
> Signed-off-by: Dongwon Kim 
> ---
>  include/ui/console.h|  17 +
>  hw/display/vhost-user-gpu.c |   6 +-
>  hw/display/virtio-gpu-udmabuf.c |   7 +-
>  hw/vfio/display.c   |  15 +++--
>  ui/console.c| 116 +++-
>  ui/dbus-console.c   |   9 ++-
>  ui/dbus-listener.c  |  43 +++-
>  ui/egl-headless.c   |  23 +--
>  ui/egl-helpers.c|  47 +++--
>  ui/gtk-egl.c|  48 -
>  ui/gtk-gl-area.c|  37 ++
>  ui/gtk.c|   6 +-
>  ui/spice-display.c  |  50 --
>  13 files changed, 316 insertions(+), 108 deletions(-)
>
> diff --git a/include/ui/console.h b/include/ui/console.h
> index 0bc7a00ac0..6292943a82 100644
> --- a/include/ui/console.h
> +++ b/include/ui/console.h
> @@ -358,6 +358,23 @@ void dpy_gl_cursor_dmabuf(QemuConsole *con, QemuDmaBuf 
> *dmabuf,
>bool have_hot, uint32_t hot_x, uint32_t hot_y);
>  void dpy_gl_cursor_position(QemuConsole *con,
>  uint32_t pos_x, uint32_t pos_y);
> +
> +int32_t dpy_gl_qemu_dmabuf_get_fd(QemuDmaBuf *dmabuf);
> +uint32_t dpy_gl_qemu_dmabuf_get_width(QemuDmaBuf *dmabuf);
> +uint32_t dpy_gl_qemu_dmabuf_get_height(QemuDmaBuf *dmabuf);
> +uint32_t dpy_gl_qemu_dmabuf_get_stride(QemuDmaBuf *dmabuf);
> +uint32_t dpy_gl_qemu_dmabuf_get_fourcc(QemuDmaBuf *dmabuf);
> +uint64_t dpy_gl_qemu_dmabuf_get_modifier(QemuDmaBuf *dmabuf);
> +uint32_t dpy_gl_qemu_dmabuf_get_texture(QemuDmaBuf *dmabuf);
> +uint32_t dpy_gl_qemu_dmabuf_get_x(QemuDmaBuf *dmabuf);
> +uint32_t dpy_gl_qemu_dmabuf_get_y(QemuDmaBuf *dmabuf);
> +uint32_t dpy_gl_qemu_dmabuf_get_backing_width(QemuDmaBuf *dmabuf);
> +uint32_t dpy_gl_qemu_dmabuf_get_backing_height(QemuDmaBuf *dmabuf);
> +bool dpy_gl_qemu_dmabuf_get_y0_top(QemuDmaBuf *dmabuf);
> +void *dpy_gl_qemu_dmabuf_get_sync(QemuDmaBuf *dmabuf);
> +int32_t dpy_gl_qemu_dmabuf_get_fence_fd(QemuDmaBuf *dmabuf);
> +bool dpy_gl_qemu_dmabuf_get_allow_fences(QemuDmaBuf *dmabuf);
> +bool dpy_gl_qemu_dmabuf_get_draw_submitted(QemuDmaBuf *dmabuf);
>  void dpy_gl_release_dmabuf(QemuConsole *con,
> QemuDmaBuf *dmabuf);
>  void dpy_gl_update(QemuConsole *con,
> diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c
> index 709c8a02a1..87dcfbca10 100644
> --- a/hw/display/vhost-user-gpu.c
> +++ b/hw/display/vhost-user-gpu.c
> @@ -249,6 +249,7 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, 
> VhostUserGpuMsg *msg)
>  case VHOST_USER_GPU_DMABUF_SCANOUT: {
>  VhostUserGpuDMABUFScanout *m = >payload.dmabuf_scanout;
>  int fd = qemu_chr_fe_get_msgfd(>vhost_chr);
> +int old_fd;
>  QemuDmaBuf *dmabuf;
>
>  if (m->scanout_id >= g->parent_obj.conf.max_outputs) {
> @@ -262,8 +263,9 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, 
> VhostUserGpuMsg *msg)
>  g->parent_obj.enable = 1;
>  con = g->parent_obj.scanout[m->scanout_id].con;
>  dmabuf = >dmabuf[m->scanout_id];
> -if (dmabuf->fd >= 0) {
> -close(dmabuf->fd);
> +old_fd = dpy_gl_qemu_dmabuf_get_fd(dmabuf);
> +if (old_fd >= 0) {
> +close(old_fd);
>  dmabuf->fd = -1;
>  }
>  dpy_gl_release_dmabuf(con, dmabuf);
> diff --git a/hw/display/virtio-gpu-udmabuf.c b/hw/display/virtio-gpu-udmabuf.c
> index d51184d658..e3f358b575 100644
> --- a/hw/display/virtio-gpu-udmabuf.c
> +++ b/hw/display/virtio-gpu-udmabuf.c
> @@ -206,6 +206,7 @@ int virtio_gpu_update_dmabuf(VirtIOGPU *g,
>  {
>  struct virtio_gpu_scanout *scanout = >parent_obj.scanout[scanout_id];
>  VGPUDMABuf *new_primary, *old_primary = NULL;
> +uint32_t width, height;
>
>  new_primary = virtio_gpu_create_dmabuf(g, scanout_id, res, fb, r);
>  if (!new_primary) {
> @@ -216,10 +217,10 @@ int virtio_gpu_update_dmabuf(VirtIOGPU *g,
>  old_primary = g->dmabuf.primary[scanout_id];
>  }
>
> +width = dpy_gl_qemu_dmabuf_get_width(_primary->buf);
> +height = dpy_gl_qemu_dmabuf_get_height(_primary->

Re: [PATCH] chardev/char-win-stdio: Fix keyboard input after exit Qemu on

2024-04-16 Thread Marc-André Lureau
Hi Irina

On Mon, Mar 25, 2024 at 10:44 AM Marc-André Lureau
 wrote:
>
> Hi
>
> On Sun, Mar 24, 2024 at 7:23 PM Irina Ryapolova
>  wrote:
> >
> > After exit Qemu need to return the terminal to the default state.
> >
> > Signed-off-by: Irina Ryapolova 
> > ---
> >  chardev/char-win-stdio.c | 5 +
> >  1 file changed, 5 insertions(+)
> >
> > diff --git a/chardev/char-win-stdio.c b/chardev/char-win-stdio.c
> > index 1a18999e78..4fa2c3de8b 100644
> > --- a/chardev/char-win-stdio.c
> > +++ b/chardev/char-win-stdio.c
> > @@ -220,6 +220,7 @@ err1:
> >  static void char_win_stdio_finalize(Object *obj)
> >  {
> >  WinStdioChardev *stdio = WIN_STDIO_CHARDEV(obj);
> > +DWORD dwMode;
> >
> >  if (stdio->hInputReadyEvent != INVALID_HANDLE_VALUE) {
> >  CloseHandle(stdio->hInputReadyEvent);
> > @@ -230,6 +231,10 @@ static void char_win_stdio_finalize(Object *obj)
> >  if (stdio->hInputThread != INVALID_HANDLE_VALUE) {
> >  TerminateThread(stdio->hInputThread, 0);
> >  }
> > +
> > +GetConsoleMode(stdio->hStdIn, );
> > +dwMode &= ~ENABLE_VIRTUAL_TERMINAL_INPUT;
> > +    SetConsoleMode(stdio->hStdIn, dwMode);
>
> I'd suggest saving the mode when opening instead, to make sure we
> restore the same value.
>
> thanks

Do you agree? Could you update the patch? thanks

-- 
Marc-André Lureau



Re: [PATCH] vhost-user-gpu: fix import of DMABUF

2024-04-16 Thread Marc-André Lureau
Hi

On Tue, Apr 16, 2024 at 1:00 AM Kim, Dongwon  wrote:
>
> Hi Marc-André,
>
> > -Original Message-
> > From: marcandre.lur...@redhat.com 
> > Sent: Monday, April 15, 2024 4:16 AM
> > To: qemu-devel@nongnu.org
> > Cc: Kim, Dongwon ; dbas...@redhat.com; Marc-
> > André Lureau ; Michael S. Tsirkin
> > ; Gerd Hoffmann 
> > Subject: [PATCH] vhost-user-gpu: fix import of DMABUF
> >
> > From: Marc-André Lureau 
> >
> > When using vhost-user-gpu with GL, qemu -display gtk doesn't show output and
> > prints: qemu: eglCreateImageKHR failed
> >
> > Since commit 9ac06df8b ("virtio-gpu-udmabuf: correct naming of QemuDmaBuf
> > size properties"), egl_dmabuf_import_texture() uses backing_{width,height} 
> > for
> > the texture dimension.
> >
> > Fixes: commit 9ac06df8b ("virtio-gpu-udmabuf: correct naming of QemuDmaBuf
> > size properties")
> > Signed-off-by: Marc-André Lureau 
> > ---
> >  hw/display/vhost-user-gpu.c | 4 ++--
> >  1 file changed, 2 insertions(+), 2 deletions(-)
> >
> > diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c index
> > 709c8a02a1..baffb1c2d4 100644
> > --- a/hw/display/vhost-user-gpu.c
> > +++ b/hw/display/vhost-user-gpu.c
> > @@ -273,8 +273,8 @@ vhost_user_gpu_handle_display(VhostUserGPU *g,
> > VhostUserGpuMsg *msg)
> >  }
> >  *dmabuf = (QemuDmaBuf) {
> >  .fd = fd,
> > -.width = m->fd_width,
> > -.height = m->fd_height,
> [Kim, Dongwon]  I think we could just leave .width/.height setting here 
> although nothing will go wrong in any cases. Did you have any specific reason 
> why leaving these uninitialized?
>


Good point. In fact, there are even dedicated fields for width/height.
Fixed in v2.

thanks


-- 
Marc-André Lureau



Re: [PATCH v5 1/3] ui/console: Introduce dpy_gl_qemu_dmabuf_get_..() helpers

2024-04-15 Thread Marc-André Lureau
Hi

On Fri, Apr 12, 2024 at 7:57 AM  wrote:
>
> From: Dongwon Kim 
>

For patchew to handle your series, you need a cover letter. See:
https://www.qemu.org/docs/master/devel/submitting-a-patch.html

> This commit introduces dpy_gl_qemu_dmabuf_get_... helpers to extract
> specific fields from the QemuDmaBuf struct. It also updates all instances
> where fields within the QemuDmaBuf struct are directly accessed, replacing
> them with calls to these new helper functions.
>
> Suggested-by: Marc-André Lureau 
> Cc: Philippe Mathieu-Daudé 
> Cc: Vivek Kasireddy 
> Signed-off-by: Dongwon Kim 
> ---
>  include/ui/console.h|  17 +
>  hw/display/vhost-user-gpu.c |   6 +-
>  hw/display/virtio-gpu-udmabuf.c |   7 +-
>  hw/vfio/display.c   |  15 +++--
>  ui/console.c| 116 +++-
>  ui/dbus-console.c   |   9 ++-
>  ui/dbus-listener.c  |  43 +++-
>  ui/egl-headless.c   |  23 +--
>  ui/egl-helpers.c|  47 +++--
>  ui/gtk-egl.c|  48 -
>  ui/gtk-gl-area.c|  37 ++
>  ui/gtk.c|   6 +-
>  ui/spice-display.c  |  50 --
>  13 files changed, 316 insertions(+), 108 deletions(-)
>
> diff --git a/include/ui/console.h b/include/ui/console.h
> index 0bc7a00ac0..6292943a82 100644
> --- a/include/ui/console.h
> +++ b/include/ui/console.h
> @@ -358,6 +358,23 @@ void dpy_gl_cursor_dmabuf(QemuConsole *con, QemuDmaBuf 
> *dmabuf,
>bool have_hot, uint32_t hot_x, uint32_t hot_y);
>  void dpy_gl_cursor_position(QemuConsole *con,
>  uint32_t pos_x, uint32_t pos_y);
> +
> +int32_t dpy_gl_qemu_dmabuf_get_fd(QemuDmaBuf *dmabuf);
> +uint32_t dpy_gl_qemu_dmabuf_get_width(QemuDmaBuf *dmabuf);
> +uint32_t dpy_gl_qemu_dmabuf_get_height(QemuDmaBuf *dmabuf);
> +uint32_t dpy_gl_qemu_dmabuf_get_stride(QemuDmaBuf *dmabuf);
> +uint32_t dpy_gl_qemu_dmabuf_get_fourcc(QemuDmaBuf *dmabuf);
> +uint64_t dpy_gl_qemu_dmabuf_get_modifier(QemuDmaBuf *dmabuf);
> +uint32_t dpy_gl_qemu_dmabuf_get_texture(QemuDmaBuf *dmabuf);
> +uint32_t dpy_gl_qemu_dmabuf_get_x(QemuDmaBuf *dmabuf);
> +uint32_t dpy_gl_qemu_dmabuf_get_y(QemuDmaBuf *dmabuf);
> +uint32_t dpy_gl_qemu_dmabuf_get_backing_width(QemuDmaBuf *dmabuf);
> +uint32_t dpy_gl_qemu_dmabuf_get_backing_height(QemuDmaBuf *dmabuf);
> +bool dpy_gl_qemu_dmabuf_get_y0_top(QemuDmaBuf *dmabuf);
> +void *dpy_gl_qemu_dmabuf_get_sync(QemuDmaBuf *dmabuf);
> +int32_t dpy_gl_qemu_dmabuf_get_fence_fd(QemuDmaBuf *dmabuf);
> +bool dpy_gl_qemu_dmabuf_get_allow_fences(QemuDmaBuf *dmabuf);
> +bool dpy_gl_qemu_dmabuf_get_draw_submitted(QemuDmaBuf *dmabuf);


I don't think it's necessary to have getters for individual fields,
you could have made a few "get_info(, , )" instead.
But now that you did it, let's keep it that way.


>  void dpy_gl_release_dmabuf(QemuConsole *con,
> QemuDmaBuf *dmabuf);
>  void dpy_gl_update(QemuConsole *con,
> diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c
> index 709c8a02a1..87dcfbca10 100644
> --- a/hw/display/vhost-user-gpu.c
> +++ b/hw/display/vhost-user-gpu.c
> @@ -249,6 +249,7 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, 
> VhostUserGpuMsg *msg)
>  case VHOST_USER_GPU_DMABUF_SCANOUT: {
>  VhostUserGpuDMABUFScanout *m = >payload.dmabuf_scanout;
>  int fd = qemu_chr_fe_get_msgfd(>vhost_chr);
> +int old_fd;
>  QemuDmaBuf *dmabuf;
>
>  if (m->scanout_id >= g->parent_obj.conf.max_outputs) {
> @@ -262,8 +263,9 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, 
> VhostUserGpuMsg *msg)
>  g->parent_obj.enable = 1;
>  con = g->parent_obj.scanout[m->scanout_id].con;
>  dmabuf = >dmabuf[m->scanout_id];
> -if (dmabuf->fd >= 0) {
> -close(dmabuf->fd);
> +old_fd = dpy_gl_qemu_dmabuf_get_fd(dmabuf);
> +if (old_fd >= 0) {
> +close(old_fd);
>  dmabuf->fd = -1;


>  }
>  dpy_gl_release_dmabuf(con, dmabuf);
> diff --git a/hw/display/virtio-gpu-udmabuf.c b/hw/display/virtio-gpu-udmabuf.c
> index d51184d658..e3f358b575 100644
> --- a/hw/display/virtio-gpu-udmabuf.c
> +++ b/hw/display/virtio-gpu-udmabuf.c
> @@ -206,6 +206,7 @@ int virtio_gpu_update_dmabuf(VirtIOGPU *g,
>  {
>  struct virtio_gpu_scanout *scanout = >parent_obj.scanout[scanout_id];
>  VGPUDMABuf *new_primary, *old_primary = NULL;
> +uint32_t width, height;
>
>  new_primary = virtio_gpu_create_dmabuf(g, scanout_id, res, f

Re: [PATCH v2 01/13] ui/console-vc: Replace sprintf() by snprintf()

2024-04-11 Thread Marc-André Lureau
On Thu, Apr 11, 2024 at 2:16 PM Philippe Mathieu-Daudé
 wrote:
>
> sprintf() is deprecated on Darwin since macOS 13.0 / XCode 14.1,
> resulting in painful developper experience.
>
> Replace sprintf() by snprintf() in order to avoid:
>
>   [702/1310] Compiling C object libcommon.fa.p/ui_console-vc.c.o
>   ui/console-vc.c:824:21: warning: 'sprintf' is deprecated:
> This function is provided for compatibility reasons only.
> Due to security concerns inherent in the design of sprintf(3),
> it is highly recommended that you use snprintf(3) instead.
> [-Wdeprecated-declarations]
> sprintf(response, "\033[%d;%dR",
> ^
>   1 warning generated.
>
> Signed-off-by: Philippe Mathieu-Daudé 

Reviewed-by: Marc-André Lureau 

> ---
>  ui/console-vc.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/ui/console-vc.c b/ui/console-vc.c
> index 899fa11c94..847d5fb174 100644
> --- a/ui/console-vc.c
> +++ b/ui/console-vc.c
> @@ -821,7 +821,7 @@ static void vc_putchar(VCChardev *vc, int ch)
>  break;
>  case 6:
>  /* report cursor position */
> -sprintf(response, "\033[%d;%dR",
> +snprintf(response, sizeof(response), "\033[%d;%dR",
> (s->y_base + s->y) % s->total_height + 1,
>  s->x + 1);
>  vc_respond_str(vc, response);
> --
> 2.41.0
>




Re: [PATCH 01/12] ui/console-vc: Replace sprintf() by g_strdup_printf()

2024-04-11 Thread Marc-André Lureau
On Wed, Apr 10, 2024 at 8:06 PM Philippe Mathieu-Daudé
 wrote:
>
> sprintf() is deprecated on Darwin since macOS 13.0 / XCode 14.1,
> resulting in painful developper experience.
>
> Replace sprintf() by g_strdup_printf() in order to avoid:
>
>   [702/1310] Compiling C object libcommon.fa.p/ui_console-vc.c.o
>   ui/console-vc.c:824:21: warning: 'sprintf' is deprecated:
> This function is provided for compatibility reasons only.
> Due to security concerns inherent in the design of sprintf(3),
> it is highly recommended that you use snprintf(3) instead.
> [-Wdeprecated-declarations]
> sprintf(response, "\033[%d;%dR",
> ^
>   1 warning generated.
>
> Signed-off-by: Philippe Mathieu-Daudé 

Reviewed-by: Marc-André Lureau 

> ---
>  ui/console-vc.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/ui/console-vc.c b/ui/console-vc.c
> index 899fa11c94..b455db436d 100644
> --- a/ui/console-vc.c
> +++ b/ui/console-vc.c
> @@ -648,7 +648,7 @@ static void vc_putchar(VCChardev *vc, int ch)
>  QemuTextConsole *s = vc->console;
>  int i;
>  int x, y;
> -char response[40];
> +g_autofree char *response = NULL;
>
>  switch(vc->state) {
>  case TTY_STATE_NORM:
> @@ -821,7 +821,7 @@ static void vc_putchar(VCChardev *vc, int ch)
>  break;
>  case 6:
>  /* report cursor position */
> -sprintf(response, "\033[%d;%dR",
> +response = g_strdup_printf("\033[%d;%dR",
> (s->y_base + s->y) % s->total_height + 1,
>  s->x + 1);
>  vc_respond_str(vc, response);
> --
> 2.41.0
>




Re: [PATCH RFC v1]display: fix heap use after free in cursor_put

2024-04-10 Thread Marc-André Lureau
Hi

On Wed, Apr 10, 2024 at 2:06 PM ゞlym <707242...@qq.com> wrote:
>
>

Please send the patch as inline:
https://www.qemu.org/docs/master/devel/submitting-a-patch.html#do-not-send-as-an-attachment

The patch is doing too much changes to the ssd.lock usage without
explaining in detail which race and how it solved it.

In particular, ui/spice-display.c usage seems safer before your
change, since it takes the lock on display_refresh and
display_mouse_define. It properly temporarily releases the lock before
calling the dpy_mouse_set() and dpy_cursor_define() as well.

To me, it looks like the only offender is qxl_spice_reset_cursor(),
which lacks locking before unrefing.

Could you confirm this hypothesis if you are able to reproduce the issue?

thanks




Re: [PATCH 06/19] block/stream: fix -Werror=maybe-uninitialized false-positives

2024-04-03 Thread Marc-André Lureau
Hi

On Wed, Apr 3, 2024 at 12:31 PM Vladimir Sementsov-Ogievskiy
 wrote:
>
> On 03.04.24 11:11, Marc-André Lureau wrote:
> > Hi
> >
> > On Tue, Apr 2, 2024 at 11:24 PM Vladimir Sementsov-Ogievskiy
> >  wrote:
> >>
> >> On 02.04.24 18:34, Eric Blake wrote:
> >>> On Tue, Apr 02, 2024 at 12:58:43PM +0300, Vladimir Sementsov-Ogievskiy 
> >>> wrote:
> >>>>>> Again, same false-positives, because of WITH_GRAPH_RDLOCK_GUARD()..
> >>>>>>
> >>>>>> Didn't you try to change WITH_ macros somehow, so that compiler 
> >>>>>> believe in our good intentions?
> >>>>>>
> >>>>>
> >>>>>
> >>>>> #define WITH_QEMU_LOCK_GUARD_(x, var) \
> >>>>>for (g_autoptr(QemuLockable) var = \
> >>>>>
> >>>>> qemu_lockable_auto_lock(QEMU_MAKE_LOCKABLE_NONNULL((x))); \
> >>>>> var; \
> >>>>> qemu_lockable_auto_unlock(var), var = NULL)
> >>>>>
> >>>>> I can't think of a clever way to rewrite this. The compiler probably
> >>>>> thinks the loop may not run, due to the "var" condition. But how to
> >>>>> convince it otherwise? it's hard to introduce another variable too..
> >>>>
> >>>>
> >>>> hmm. maybe like this?
> >>>>
> >>>> #define WITH_QEMU_LOCK_GUARD_(x, var) \
> >>>>   for (g_autoptr(QemuLockable) var = \
> >>>>   
> >>>> qemu_lockable_auto_lock(QEMU_MAKE_LOCKABLE_NONNULL((x))), \
> >>>>var2 = (void *)(true); \
> >>>>var2; \
> >>>>qemu_lockable_auto_unlock(var), var2 = NULL)
> >>>>
> >>>>
> >>>> probably, it would be simpler for compiler to understand the logic this 
> >>>> way. Could you check?
> >>>
> >>> Wouldn't that attach __attribute__((cleanup(xxx))) to var2, at which
> >>> point we could cause the compiler to call xxx((void*)(true)) if the
> >>> user does an early return inside the lock guard, with disastrous
> >>> consequences?  Or is the __attribute__ applied only to the first out
> >>> of two declarations in a list?
> >>>
> >>
> >> Oh, most probably you are right, seems g_autoptr apply it to both 
> >> variables. Also, we don't need qemu_lockable_auto_unlock(var) separate 
> >> call, if we zero-out another variable. So, me fixing:
> >>
> >> #define WITH_QEMU_LOCK_GUARD_(x, var) \
> >>   for (QemuLockable *var 
> >> __attribute__((cleanup(qemu_lockable_auto_unlock))) = 
> >> qemu_lockable_auto_lock(QEMU_MAKE_LOCKABLE_NONNULL((x))), \
> >>*var2 = (void *)(true); \
> >>var2; \
> >>var2 = NULL)
> >>
> >> (and we'll need to modify qemu_lockable_auto_unlock() to take 
> >> "QemuLockable **x" argument)
> >>
> >
> > That's almost good enough. I fixed a few things to generate var2.
> >
> > I applied a similar approach to WITH_GRAPH_RDLOCK_GUARD macro:
> >
> > --- a/include/block/graph-lock.h
> > +++ b/include/block/graph-lock.h
> > @@ -224,13 +224,22 @@ graph_lockable_auto_unlock(GraphLockable *x)
> >
> >   G_DEFINE_AUTOPTR_CLEANUP_FUNC(GraphLockable, graph_lockable_auto_unlock)
> >
> > -#define WITH_GRAPH_RDLOCK_GUARD_(var)  
> >\
> > -for (g_autoptr(GraphLockable) var = 
> > graph_lockable_auto_lock(GML_OBJ_()); \
> > - var;  
> >\
> > - graph_lockable_auto_unlock(var), var = NULL)
> > +static inline void TSA_NO_TSA coroutine_fn
> > +graph_lockable_auto_cleanup(GraphLockable **x)
> > +{
> > +graph_lockable_auto_unlock(*x);
> > +}
> > +
> > +#define WITH_GRAPH_RDLOCK_GUARD__(var) \
> > +GraphLockable *var \
> > +__attribute__((cleanup(graph_lockable_auto_cleanup))) 
> > G_GNUC_UNUSED = \
> > +   graph_lockable_auto_lock(GML_OBJ_())
> > +
> > +#define WITH_GRAPH_RDLOCK_GUARD_(var, var2) \
> > +for (WITH_GRAPH_RDLOCK_GUARD__(var), *var2 = (void *)true; var2;
> > var2 = NULL)
> >
> >   #define WITH_GRAPH_RDLOCK_GUARD() \
> > -WITH_GRAPH_RDLOCK_GUARD

Re: [PATCH 06/19] block/stream: fix -Werror=maybe-uninitialized false-positives

2024-04-03 Thread Marc-André Lureau
Hi

On Tue, Apr 2, 2024 at 11:24 PM Vladimir Sementsov-Ogievskiy
 wrote:
>
> On 02.04.24 18:34, Eric Blake wrote:
> > On Tue, Apr 02, 2024 at 12:58:43PM +0300, Vladimir Sementsov-Ogievskiy 
> > wrote:
> >>>> Again, same false-positives, because of WITH_GRAPH_RDLOCK_GUARD()..
> >>>>
> >>>> Didn't you try to change WITH_ macros somehow, so that compiler believe 
> >>>> in our good intentions?
> >>>>
> >>>
> >>>
> >>> #define WITH_QEMU_LOCK_GUARD_(x, var) \
> >>>   for (g_autoptr(QemuLockable) var = \
> >>>   
> >>> qemu_lockable_auto_lock(QEMU_MAKE_LOCKABLE_NONNULL((x))); \
> >>>var; \
> >>>qemu_lockable_auto_unlock(var), var = NULL)
> >>>
> >>> I can't think of a clever way to rewrite this. The compiler probably
> >>> thinks the loop may not run, due to the "var" condition. But how to
> >>> convince it otherwise? it's hard to introduce another variable too..
> >>
> >>
> >> hmm. maybe like this?
> >>
> >> #define WITH_QEMU_LOCK_GUARD_(x, var) \
> >>  for (g_autoptr(QemuLockable) var = \
> >>  qemu_lockable_auto_lock(QEMU_MAKE_LOCKABLE_NONNULL((x))), 
> >> \
> >>   var2 = (void *)(true); \
> >>   var2; \
> >>   qemu_lockable_auto_unlock(var), var2 = NULL)
> >>
> >>
> >> probably, it would be simpler for compiler to understand the logic this 
> >> way. Could you check?
> >
> > Wouldn't that attach __attribute__((cleanup(xxx))) to var2, at which
> > point we could cause the compiler to call xxx((void*)(true)) if the
> > user does an early return inside the lock guard, with disastrous
> > consequences?  Or is the __attribute__ applied only to the first out
> > of two declarations in a list?
> >
>
> Oh, most probably you are right, seems g_autoptr apply it to both variables. 
> Also, we don't need qemu_lockable_auto_unlock(var) separate call, if we 
> zero-out another variable. So, me fixing:
>
> #define WITH_QEMU_LOCK_GUARD_(x, var) \
>  for (QemuLockable *var 
> __attribute__((cleanup(qemu_lockable_auto_unlock))) = 
> qemu_lockable_auto_lock(QEMU_MAKE_LOCKABLE_NONNULL((x))), \
>   *var2 = (void *)(true); \
>   var2; \
>   var2 = NULL)
>
> (and we'll need to modify qemu_lockable_auto_unlock() to take "QemuLockable 
> **x" argument)
>

That's almost good enough. I fixed a few things to generate var2.

I applied a similar approach to WITH_GRAPH_RDLOCK_GUARD macro:

--- a/include/block/graph-lock.h
+++ b/include/block/graph-lock.h
@@ -224,13 +224,22 @@ graph_lockable_auto_unlock(GraphLockable *x)

 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GraphLockable, graph_lockable_auto_unlock)

-#define WITH_GRAPH_RDLOCK_GUARD_(var) \
-for (g_autoptr(GraphLockable) var = graph_lockable_auto_lock(GML_OBJ_()); \
- var; \
- graph_lockable_auto_unlock(var), var = NULL)
+static inline void TSA_NO_TSA coroutine_fn
+graph_lockable_auto_cleanup(GraphLockable **x)
+{
+graph_lockable_auto_unlock(*x);
+}
+
+#define WITH_GRAPH_RDLOCK_GUARD__(var) \
+GraphLockable *var \
+__attribute__((cleanup(graph_lockable_auto_cleanup))) G_GNUC_UNUSED = \
+   graph_lockable_auto_lock(GML_OBJ_())
+
+#define WITH_GRAPH_RDLOCK_GUARD_(var, var2) \
+for (WITH_GRAPH_RDLOCK_GUARD__(var), *var2 = (void *)true; var2;
var2 = NULL)

 #define WITH_GRAPH_RDLOCK_GUARD() \
-WITH_GRAPH_RDLOCK_GUARD_(glue(graph_lockable_auto, __COUNTER__))
+WITH_GRAPH_RDLOCK_GUARD_(glue(graph_lockable_auto, __COUNTER__),
glue(graph_lockable_auto, __COUNTER__))

Unfortunately, it doesn't work in all cases. It seems to have issues
with some guards:
../block/stream.c: In function ‘stream_run’:
../block/stream.c:216:12: error: ‘ret’ may be used uninitialized
[-Werror=maybe-uninitialized]
  216 | if (ret < 0) {


What should we do? change the macros + cherry-pick the missing
false-positives, or keep this series as is?





-- 
Marc-André Lureau



Re: [PATCH 09/19] hw/sdhci: fix -Werror=maybe-uninitialized false-positive

2024-04-02 Thread Marc-André Lureau
Hi

On Thu, Mar 28, 2024 at 3:31 PM Philippe Mathieu-Daudé
 wrote:
>
> On 28/3/24 11:20, marcandre.lur...@redhat.com wrote:
> > From: Marc-André Lureau 
> >
> > ../hw/sd/sdhci.c:846:16: error: ‘res’ may be used uninitialized 
> > [-Werror=maybe-uninitialized]
> >
> > False-positive, because "length" is non-null.
> >
> > Signed-off-by: Marc-André Lureau 
> > ---
> >   hw/sd/sdhci.c | 2 +-
> >   1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
> > index c5e0bc018b..da5351d4e5 100644
> > --- a/hw/sd/sdhci.c
> > +++ b/hw/sd/sdhci.c
> > @@ -745,7 +745,7 @@ static void sdhci_do_adma(SDHCIState *s)
> >   const uint16_t block_size = s->blksize & BLOCK_SIZE_MASK;
> >   const MemTxAttrs attrs = { .memory = true };
> >   ADMADescr dscr = {};
> > -MemTxResult res;
> > +MemTxResult res = MEMTX_ERROR;
>
> Something is indeed odd here. Due to the for() loop, the variable
> initialization should be moved after the SDHC_ADMA_ATTR_ACT_TRAN
> switch case.
>

Moving the variable initialization? What do you suggest exactly?

thanks

-- 
Marc-André Lureau



Re: [PATCH 06/19] block/stream: fix -Werror=maybe-uninitialized false-positives

2024-04-02 Thread Marc-André Lureau
Hi

On Fri, Mar 29, 2024 at 12:35 PM Vladimir Sementsov-Ogievskiy
 wrote:
>
> On 28.03.24 13:20, marcandre.lur...@redhat.com wrote:
> > From: Marc-André Lureau 
> >
> > ../block/stream.c:193:19: error: ‘unfiltered_bs’ may be used uninitialized 
> > [-Werror=maybe-uninitialized]
> > ../block/stream.c:176:5: error: ‘len’ may be used uninitialized 
> > [-Werror=maybe-uninitialized]
> > trace/trace-block.h:906:9: error: ‘ret’ may be used uninitialized 
> > [-Werror=maybe-uninitialized]
> >
> > Signed-off-by: Marc-André Lureau 
>
> Again, same false-positives, because of WITH_GRAPH_RDLOCK_GUARD()..
>
> Didn't you try to change WITH_ macros somehow, so that compiler believe in 
> our good intentions?
>


#define WITH_QEMU_LOCK_GUARD_(x, var) \
for (g_autoptr(QemuLockable) var = \
qemu_lockable_auto_lock(QEMU_MAKE_LOCKABLE_NONNULL((x))); \
 var; \
 qemu_lockable_auto_unlock(var), var = NULL)

I can't think of a clever way to rewrite this. The compiler probably
thinks the loop may not run, due to the "var" condition. But how to
convince it otherwise? it's hard to introduce another variable too..

> Actually, "unused variable initialization" is bad thing too.
>
> Anyway, if no better solution for now:
> Acked-by: Vladimir Sementsov-Ogievskiy 
>
> > ---
> >   block/stream.c | 6 +++---
> >   1 file changed, 3 insertions(+), 3 deletions(-)
> >
> > diff --git a/block/stream.c b/block/stream.c
> > index 7031eef12b..9076203193 100644
> > --- a/block/stream.c
> > +++ b/block/stream.c
> > @@ -155,8 +155,8 @@ static void stream_clean(Job *job)
> >   static int coroutine_fn stream_run(Job *job, Error **errp)
> >   {
> >   StreamBlockJob *s = container_of(job, StreamBlockJob, common.job);
> > -BlockDriverState *unfiltered_bs;
> > -int64_t len;
> > +BlockDriverState *unfiltered_bs = NULL;
> > +int64_t len = -1;
> >   int64_t offset = 0;
> >   int error = 0;
> >   int64_t n = 0; /* bytes */
> > @@ -177,7 +177,7 @@ static int coroutine_fn stream_run(Job *job, Error 
> > **errp)
> >
> >   for ( ; offset < len; offset += n) {
> >   bool copy;
> > -int ret;
> > +int ret = -1;
> >
> >   /* Note that even when no rate limit is applied we need to yield
> >* with no pending I/O here so that bdrv_drain_all() returns.
>
> --
> Best regards,
> Vladimir
>
>


-- 
Marc-André Lureau



Compiling QEMU with different optimization levels & -Werror=maybe-uninitialized

2024-03-27 Thread Marc-André Lureau
Hi,

Depending -Doptimization=, I get different results (GCC 13.2.1)
- g: produces -Werror=maybe-uninitialized errors
- 0: clean build
- 1: produces -Werror=maybe-uninitialized errors
- 2: clean build
- 3: produces few -Werror=maybe-uninitialized errors
- s: produces -Werror=maybe-uninitialized errors

They are about 20, probably false-positives, although it's
understandable the compiler is confused as I am too sometime!

Is it a known issue? Are we willing to help the compiler in all those
optimization levels? I can send a patch series for review in this
case.

thanks

--
Marc-André Lureau



  1   2   3   4   5   6   7   8   9   10   >