[PATCH v2 2/4] net: update netdev stream man page with unix socket

2024-07-04 Thread Laurent Vivier
Add the description of "-netdev stream" with a unix domain socket.
The code has been added but the man page has not been updated.

Include an example how 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)

Fixes: 13c6be96618c ("net: stream: add unix socket")
Signed-off-by: Laurent Vivier 
---
 qemu-options.hx | 40 
 1 file changed, 40 insertions(+)

diff --git a/qemu-options.hx b/qemu-options.hx
index 2a099731ea0a..ef476b593cd1 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -3393,6 +3393,46 @@ SRST
   -device virtio-net,netdev=net0,mac=52:54:00:12:34:57 \\
   -netdev 
stream,id=net0,server=off,addr.type=inet,addr.host=localhost,addr.port=1234
 
+``-netdev 
stream,id=str[,server=on|off],addr.type=unix,addr.path=path[,abstract=on|off][,tight=on|off]``
+Configure a network backend to connect to another QEMU virtual machine or 
a proxy using a stream oriented unix domain socket.
+
+``server=on|off``
+if ``on`` create a server socket
+
+``addr.path=path``
+filesystem path to use
+
+``abstract=on|off``
+if ``on``, this is a Linux abstract socket address.
+
+``tight=on|off``
+if false, pad an abstract socket address with enough null bytes to 
make it fill struct sockaddr_un member sun_path.
+
+Example (using passt as a replacement of -netdev user):
+
+.. parsed-literal::
+
+# start passt server as a non privileged user
+passt
+UNIX domain socket bound at /tmp/passt_1.socket
+# start QEMU to connect to passt
+|qemu_system| linux.img \\
+  -device virtio-net,netdev=net0 \\
+  -netdev 
stream,id=net0,server=off,addr.type=unix,addr.path=/tmp/passt_1.socket
+
+Example (two guests connected using a stream oriented unix domain socket):
+
+.. parsed-literal::
+
+# first VM
+|qemu_system| linux.img \\
+  -device virtio-net,netdev=net0,mac=52:54:00:12:34:56 \\
+  netdev 
stream,id=net0,server=on,addr.type=unix,addr.path=/tmp/qemu0
+# second VM
+|qemu_system| linux.img \\
+  -device virtio-net,netdev=net0,mac=52:54:00:12:34:57 \\
+  -netdev 
stream,id=net0,server=off,addr.type=unix,addr.path=/tmp/qemu0
+
 ``-netdev stream,id=str[,server=on|off],addr.type=fd,addr.str=file-descriptor``
 Configure a network backend to connect to another QEMU virtual machine or 
a proxy using a stream oriented socket file descriptor.
 
-- 
2.45.2




[PATCH v2 3/4] net: update netdev dgram man page with unix socket

2024-07-04 Thread Laurent Vivier
Add the description of "-netdev dgram" with a unix domain socket.
The code has been added but the man page has not been updated.

Fixes: 784e7a253104 ("net: dgram: add unix socket")
Signed-off-by: Laurent Vivier 
---
 qemu-options.hx | 23 +++
 1 file changed, 23 insertions(+)

diff --git a/qemu-options.hx b/qemu-options.hx
index ef476b593cd1..1bbf629b9959 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -3500,6 +3500,29 @@ SRST
   -device virtio-net,netdev=net0,mac=52:54:00:12:34:56 \\
   -netdev 
dgram,id=net0,local.type=inet,local.host=localhost,local.port=1235,remote.type=inet,remote.host=localhost,remote.port=1234
 
+``-netdev 
dgram,id=str,local.type=unix,local.path=path[,remote.type=unix,remote.path=path]``
+Configure a network backend to connect to another QEMU virtual
+machine or a proxy using a datagram oriented unix socket.
+
+``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 a datagram oriented socket file descriptor.
-- 
2.45.2




[PATCH v2 4/4] net: update netdev stream man page with the reconnect parameter

2024-07-04 Thread Laurent Vivier
"-netdev stream" supports a reconnect parameter that attempts to
reconnect automatically the socket if it is disconnected. The code
has been added but the man page has not been updated.

Fixes: 148fbf0d58a6 ("net: stream: add a new option to automatically reconnect"
Signed-off-by: Laurent Vivier 
---
 qemu-options.hx | 22 +-
 1 file changed, 17 insertions(+), 5 deletions(-)

diff --git a/qemu-options.hx b/qemu-options.hx
index 1bbf629b9959..c78f69851bf3 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -3353,7 +3353,7 @@ SRST
  -device e1000,netdev=n1,mac=52:54:00:12:34:56 \\
  -netdev 
socket,id=n1,mcast=239.192.168.1:1102,localaddr=1.2.3.4
 
-``-netdev 
stream,id=str[,server=on|off],addr.type=inet,addr.host=host,addr.port=port[,to=maxport][,numeric=on|off][,keep-alive=on|off][,mptcp=on|off][,addr.ipv4=on|off][,addr.ipv6=on|off]``
+``-netdev 
stream,id=str[,server=on|off],addr.type=inet,addr.host=host,addr.port=port[,to=maxport][,numeric=on|off][,keep-alive=on|off][,mptcp=on|off][,addr.ipv4=on|off][,addr.ipv6=on|off][,reconnect=seconds]``
 Configure a network backend to connect to another QEMU virtual machine or 
a proxy using a TCP/IP socket.
 
 ``server=on|off``
@@ -3380,6 +3380,10 @@ SRST
 ``ipv6=on|off``
 whether to accept IPv6 addresses, default to try both IPv4 and IPv6
 
+``reconnect=seconds``
+for a client socket, if a socket is disconnected, then attempt a 
reconnect after the given number of seconds.
+Setting this to zero disables this function.  (default: 0)
+
 Example (two guests connected using a TCP/IP socket):
 
 .. parsed-literal::
@@ -3391,9 +3395,9 @@ SRST
 # second VM
 |qemu_system| linux.img \\
   -device virtio-net,netdev=net0,mac=52:54:00:12:34:57 \\
-  -netdev 
stream,id=net0,server=off,addr.type=inet,addr.host=localhost,addr.port=1234
+  -netdev 
stream,id=net0,server=off,addr.type=inet,addr.host=localhost,addr.port=1234,reconnect=5
 
-``-netdev 
stream,id=str[,server=on|off],addr.type=unix,addr.path=path[,abstract=on|off][,tight=on|off]``
+``-netdev 
stream,id=str[,server=on|off],addr.type=unix,addr.path=path[,abstract=on|off][,tight=on|off][,reconnect=seconds]``
 Configure a network backend to connect to another QEMU virtual machine or 
a proxy using a stream oriented unix domain socket.
 
 ``server=on|off``
@@ -3408,6 +3412,10 @@ SRST
 ``tight=on|off``
 if false, pad an abstract socket address with enough null bytes to 
make it fill struct sockaddr_un member sun_path.
 
+``reconnect=seconds``
+for a client socket, if a socket is disconnected, then attempt a 
reconnect after the given number of seconds.
+Setting this to zero disables this function.  (default: 0)
+
 Example (using passt as a replacement of -netdev user):
 
 .. parsed-literal::
@@ -3431,9 +3439,9 @@ SRST
 # second VM
 |qemu_system| linux.img \\
   -device virtio-net,netdev=net0,mac=52:54:00:12:34:57 \\
-  -netdev 
stream,id=net0,server=off,addr.type=unix,addr.path=/tmp/qemu0
+  -netdev 
stream,id=net0,server=off,addr.type=unix,addr.path=/tmp/qemu0,reconnect=5
 
-``-netdev stream,id=str[,server=on|off],addr.type=fd,addr.str=file-descriptor``
+``-netdev 
stream,id=str[,server=on|off],addr.type=fd,addr.str=file-descriptor[,reconnect=seconds]``
 Configure a network backend to connect to another QEMU virtual machine or 
a proxy using a stream oriented socket file descriptor.
 
 ``server=on|off``
@@ -3442,6 +3450,10 @@ SRST
 ``addr.str=file-descriptor``
 file descriptor number to use as a socket
 
+``reconnect=seconds``
+for a client socket, if a socket is disconnected, then attempt a 
reconnect after the given number of seconds.
+Setting this to zero disables this function.  (default: 0)
+
 ``-netdev 
dgram,id=str,remote.type=inet,remote.host=maddr,remote.port=port[,local.type=inet,local.host=addr]``
 Configure a network backend to connect to a multicast address.
 
-- 
2.45.2




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

2024-07-04 Thread Laurent Vivier
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(+)

-- 
2.45.2





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

2024-07-04 Thread Laurent Vivier
Add the description of "-netdev stream" and "-netdev dgram" in the QEMU
manpage.

Add some examples on how to use them.

Fixes: 5166fe0ae46d ("qapi: net: add stream and dgram netdevs")
Signed-off-by: Laurent Vivier 
---
 qemu-options.hx | 114 
 1 file changed, 114 insertions(+)

diff --git a/qemu-options.hx b/qemu-options.hx
index 8ca7f34ef0c8..2a099731ea0a 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -3353,6 +3353,120 @@ SRST
  -device e1000,netdev=n1,mac=52:54:00:12:34:56 \\
  -netdev 
socket,id=n1,mcast=239.192.168.1:1102,localaddr=1.2.3.4
 
+``-netdev 
stream,id=str[,server=on|off],addr.type=inet,addr.host=host,addr.port=port[,to=maxport][,numeric=on|off][,keep-alive=on|off][,mptcp=on|off][,addr.ipv4=on|off][,addr.ipv6=on|off]``
+Configure a network backend to connect to another QEMU virtual machine or 
a proxy using a TCP/IP socket.
+
+``server=on|off``
+if ``on`` create a server socket
+
+``addr.host=host,addr.port=port``
+socket address to listen on (server=on) or connect to (server=off)
+
+``to=maxport``
+if present, this is range of possible addresses, with port between 
``port`` and ``maxport``.
+
+``numeric=on|off``
+if ``on`` ``host`` and ``port`` are guaranteed to be numeric, 
otherwise a name resolution should be attempted (default: ``off``)
+
+``keep-alive=on|off``
+enable keep-alive when connecting to this socket.  Not supported for 
passive sockets.
+
+``mptcp=on|off``
+enable multipath TCP
+
+``ipv4=on|off``
+whether to accept IPv4 addresses, default to try both IPv4 and IPv6
+
+``ipv6=on|off``
+whether to accept IPv6 addresses, default to try both IPv4 and IPv6
+
+Example (two guests connected using a TCP/IP socket):
+
+.. parsed-literal::
+
+# first VM
+|qemu_system| linux.img \\
+  -device virtio-net,netdev=net0,mac=52:54:00:12:34:56 \\
+  -netdev 
stream,id=net0,server=on,addr.type=inet,addr.host=localhost,addr.port=1234
+# second VM
+|qemu_system| linux.img \\
+  -device virtio-net,netdev=net0,mac=52:54:00:12:34:57 \\
+  -netdev 
stream,id=net0,server=off,addr.type=inet,addr.host=localhost,addr.port=1234
+
+``-netdev stream,id=str[,server=on|off],addr.type=fd,addr.str=file-descriptor``
+Configure a network backend to connect to another QEMU virtual machine or 
a proxy using a stream oriented socket file descriptor.
+
+``server=on|off``
+if ``on`` create a server socket
+
+``addr.str=file-descriptor``
+file descriptor number to use as a socket
+
+``-netdev 
dgram,id=str,remote.type=inet,remote.host=maddr,remote.port=port[,local.type=inet,local.host=addr]``
+Configure a network backend to connect to a multicast address.
+
+``remote.host=maddr,remote.port=port``
+multicast address
+
+``local.host=addr``
+specify the host address to send packets from
+
+Example:
+
+.. parsed-literal::
+
+# launch one QEMU instance
+|qemu_system| linux.img \\
+  -device virtio-net,netdev=net0,mac=52:54:00:12:34:56 \\
+  -netdev 
dgram,id=net0,remote.type=inet,remote.host=224.0.0.1,remote.port=1234
+# launch another QEMU instance on same "bus"
+|qemu_system| linux.img \\
+  -device virtio-net,netdev=net0,mac=52:54:00:12:34:57 \\
+  -netdev 
dgram,id=net0,remote.type=inet,remote.host=224.0.0.1,remote.port=1234
+# launch yet another QEMU instance on same "bus"
+|qemu_system| linux.img \\
+  -device virtio-net,netdev=net0,mac=52:54:00:12:34:58 \\
+  -netdev 
dgram,id=net0,remote.type=inet,remote.host=224.0.0.1,remote.port=1234
+
+``-netdev 
dgram,id=str,remote.type=inet,remote.host=maddr,remote.port=port[,local.type=fd,local.str=file-descriptor]``
+Configure a network backend to connect to a multicast address using a UDP 
socket file descriptor.
+
+``remote.host=maddr,remote.port=port``
+multicast address
+
+``local.str=file-descriptor``
+File descriptor to use to send packets
+
+``-netdev 
dgram,id=str,local.type=inet,local.host=addr,local.port=port[,remote.type=inet,remote.host=addr,remote.port=port]``
+Configure a network backend to connect to another QEMU virtual
+machine or a proxy using a datagram oriented unix domain socket.
+
+``local.host=addr,local.port=port``
+IP address to use to send the packets from
+
+``remote.host=addr,remote.port=port``
+Destination IP address
+
+Example (two guests connected using an UDP/IP socket):
+
+.. parsed-literal::
+
+# first VM
+|qemu_system| linux.img \\
+  -d

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

2024-07-04 Thread Laurent Vivier

Hi Marc-André,

thank you for your comments, you're right I should not mix TCP/UDP and unix socket.  I'm 
going to fix that.


Thanks,
Laurent

On 02/07/2024 09:39, Marc-André Lureau wrote:

Hi

On Wed, Jun 26, 2024 at 7:53 PM Laurent Vivier <mailto:lviv...@redhat.com>> 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)

Fixes: 5166fe0ae46d ("qapi: net: add stream and dgram netdevs")
Fixes: 13c6be96618c ("net: stream: add unix socket")
Fixes: 784e7a253104 ("net: dgram: add unix socket")
    Fixes: 148fbf0d58a6 ("net: stream: add a new option to automatically 
reconnect"
Signed-off-by: Laurent Vivier mailto:lviv...@redhat.com>>


Could be easier to review if this documentation addition is splitted in various 
patches.

---
  qemu-options.hx | 189 
  1 file changed, 189 insertions(+)

diff --git a/qemu-options.hx b/qemu-options.hx
index 8ca7f34ef0c8..b8a1a65f05e7 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -3353,6 +3353,195 @@ SRST
                           -device e1000,netdev=n1,mac=52:54:00:12:34:56 \\
                           -netdev socket,id=n1,mcast=239.192.168.1:1102
<http://239.192.168.1:1102>,localaddr=1.2.3.4

+``-netdev

stream,id=str[,server=on|off],addr.type=inet,addr.host=host,addr.port=port[,to=maxport][,numeric=on|off][,keep-alive=on|off][,mptcp=on|off][,addr.ipv4=on|off][,addr.ipv6=on|off][,reconnect=seconds]``
+    Configure a network backend to connect to another QEMU virtual machine 
or a proxy
using a TCP/IP socket.
+
+    ``server=on|off``
+        if ``on`` create a server socket
+
+    ``addr.host=host,addr.port=port``
+        socket address to listen on (server=on) or connect to (server=off)
+
+    ``to=maxport``
+        if present, this is range of possible addresses, with port between 
``port``
and ``maxport``.
+
+    ``numeric=on|off``
+        if ``on`` ``host`` and ``port`` are guaranteed to be numeric, 
otherwise a
name resolution should be attempted (default: ``off``)
+
+    ``keep-alive=on|off``
+        enable keep-alive when connecting to this socket.  Not supported 
for passive
sockets.
+
+    ``mptcp=on|off``
+        enable multipath TCP
+
+    ``ipv4=on|off``
+        whether to accept IPv4 addresses, default to try both IPv4 and IPv6
+
+    ``ipv6=on|off``
+        whether to accept IPv6 addresses, default to try both IPv4 and IPv6
+
+    ``reconnect=seconds``
+        for a client socket, if a socket is disconnected, then attempt a 
reconnect
after the given number of seconds.
+        Setting this to zero disables this function.  (default: 0)
+
+    Example (two guests connected using a TCP/IP socket):
+
+    .. parsed-literal::
+
+        # first VM
+        |qemu_system| linux.img \\
+                      -device virtio-net,netdev=net0,mac=52:54:00:12:34:56 
\\
+                      -netdev
stream,id=net0,server=on,addr.type=inet,addr.host=localhost,addr.port=1234
+        # second VM
+        |qemu_system| linux.img \\
+                      -device virtio-net,netdev=net0,mac=52:54:00:12:34:57 
\\
+                      -netdev

stream,id=net0,server=off,addr.type=inet,addr.host=localhost,addr.port=1234,reconnect=5
+
+``-netdev

stream,id=str[,server=on|off],addr.type=unix,addr.path=path[,abstract=on|off][,tight=on|off][,reconnect=seconds]``
+    Configure a network backend to connect to another QEMU virtual machine 
or a proxy
using a TCP/UNIX socket.


  "TCP/UNIX": just UNIX instead?

+
+    ``server=on|off``
+        if ``on`` create a server socket
+
+    ``addr.path=path``
+        filesystem path to use
+
+    ``abstract=on|off``
+        if ``on``, this is a Linux abstract socket address.
+
+    ``tight=on|off``
+        if false, pad an abstract socket address with enough null bytes to 
make it
fill struct sockaddr_un member sun_path.
+
+    ``reconnect=seconds``
+        for a client socket, if a socket is disconnected, then attempt a 
reconnect
after the given number of seconds.
+        Setting this to zero disables this function.  (default: 0)
+
+    Example (using passt as a replacement of -netdev user):
+
+    .. parsed-literal::
+
+        # start pa

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

2024-07-02 Thread Laurent Vivier

On 02/07/2024 10:08, Marc-André Lureau wrote:

Hi

On Wed, Jun 26, 2024 at 7:53 PM Laurent Vivier <mailto:lviv...@redhat.com>> 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.


Yes, I'm planning to add a "-netdev passt" that will start passt and connect it to a 
stream socket to QEMU. Perhaps at some point we can have a "-netdev slirp" and "-netdev 
user" will us by default passt?


I'm also working on a vhost-user interface for passt that will also improve performance of 
user mode networking with QEMU.


Thanks,
Laurent




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

2024-06-26 Thread Laurent Vivier
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)

Fixes: 5166fe0ae46d ("qapi: net: add stream and dgram netdevs")
Fixes: 13c6be96618c ("net: stream: add unix socket")
Fixes: 784e7a253104 ("net: dgram: add unix socket")
Fixes: 148fbf0d58a6 ("net: stream: add a new option to automatically reconnect"
Signed-off-by: Laurent Vivier 
---
 qemu-options.hx | 189 
 1 file changed, 189 insertions(+)

diff --git a/qemu-options.hx b/qemu-options.hx
index 8ca7f34ef0c8..b8a1a65f05e7 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -3353,6 +3353,195 @@ SRST
  -device e1000,netdev=n1,mac=52:54:00:12:34:56 \\
  -netdev 
socket,id=n1,mcast=239.192.168.1:1102,localaddr=1.2.3.4
 
+``-netdev 
stream,id=str[,server=on|off],addr.type=inet,addr.host=host,addr.port=port[,to=maxport][,numeric=on|off][,keep-alive=on|off][,mptcp=on|off][,addr.ipv4=on|off][,addr.ipv6=on|off][,reconnect=seconds]``
+Configure a network backend to connect to another QEMU virtual machine or 
a proxy using a TCP/IP socket.
+
+``server=on|off``
+if ``on`` create a server socket
+
+``addr.host=host,addr.port=port``
+socket address to listen on (server=on) or connect to (server=off)
+
+``to=maxport``
+if present, this is range of possible addresses, with port between 
``port`` and ``maxport``.
+
+``numeric=on|off``
+if ``on`` ``host`` and ``port`` are guaranteed to be numeric, 
otherwise a name resolution should be attempted (default: ``off``)
+
+``keep-alive=on|off``
+enable keep-alive when connecting to this socket.  Not supported for 
passive sockets.
+
+``mptcp=on|off``
+enable multipath TCP
+
+``ipv4=on|off``
+whether to accept IPv4 addresses, default to try both IPv4 and IPv6
+
+``ipv6=on|off``
+whether to accept IPv6 addresses, default to try both IPv4 and IPv6
+
+``reconnect=seconds``
+for a client socket, if a socket is disconnected, then attempt a 
reconnect after the given number of seconds.
+Setting this to zero disables this function.  (default: 0)
+
+Example (two guests connected using a TCP/IP socket):
+
+.. parsed-literal::
+
+# first VM
+|qemu_system| linux.img \\
+  -device virtio-net,netdev=net0,mac=52:54:00:12:34:56 \\
+  -netdev 
stream,id=net0,server=on,addr.type=inet,addr.host=localhost,addr.port=1234
+# second VM
+|qemu_system| linux.img \\
+  -device virtio-net,netdev=net0,mac=52:54:00:12:34:57 \\
+  -netdev 
stream,id=net0,server=off,addr.type=inet,addr.host=localhost,addr.port=1234,reconnect=5
+
+``-netdev 
stream,id=str[,server=on|off],addr.type=unix,addr.path=path[,abstract=on|off][,tight=on|off][,reconnect=seconds]``
+Configure a network backend to connect to another QEMU virtual machine or 
a proxy using a TCP/UNIX socket.
+
+``server=on|off``
+if ``on`` create a server socket
+
+``addr.path=path``
+filesystem path to use
+
+``abstract=on|off``
+if ``on``, this is a Linux abstract socket address.
+
+``tight=on|off``
+if false, pad an abstract socket address with enough null bytes to 
make it fill struct sockaddr_un member sun_path.
+
+``reconnect=seconds``
+for a client socket, if a socket is disconnected, then attempt a 
reconnect after the given number of seconds.
+Setting this to zero disables this function.  (default: 0)
+
+Example (using passt as a replacement of -netdev user):
+
+.. parsed-literal::
+
+# start passt server as a non privileged user
+passt
+UNIX domain socket bound at /tmp/passt_1.socket
+# start QEMU to connect to passt
+|qemu_system| linux.img \\
+  -device virtio-net,netdev=net0 \\
+  -netdev 
stream,id=net0,server=off,addr.type=unix,addr.path=/tmp/passt_1.socket
+
+Example (two guests connected using a TCP/UNIX socket):
+
+.. parsed-literal::
+
+# first VM
+|qemu_system| linux.img \\
+  -device virtio-net,netdev=net0,mac=52:54:00:12:34:56 \\
+  netdev 
stream,id=net0,server=on,addr.type=unix,addr.path=/tmp/qemu0
+# second VM
+|qemu_system| linux.img \\
+  -device virtio-net,netdev=net0,mac=52:54:00:12:34:57 \\
+  -netdev 
stream,id=net0,server=off,addr.type=unix,addr.path=/tmp/qemu0,re

Re: [PATCH 0/4] hw/m68k/virt: Add some devices

2024-06-20 Thread Laurent Vivier

Le 27/05/2024 à 19:15, Jiaxun Yang a écrit :

Hi all,

This series added some devices that I found lacking when
I was trying to port U-Boot to m68k virt machine.


I have a branch with a bootloader based on petitboot.

See https://github.com/vivier/qemu-m68k/commits/m68k-virt/

Thanks
Laurent



Please review.
Thanks

Signed-off-by: Jiaxun Yang 
---
Jiaxun Yang (4):
   hw/m68k/virt: Add a XHCI controller
   hw/m68k/virt: Add fw_cfg controller
   hw/m68k/virt: Add a pflash controller for BIOS firmware
   hw/m68k/virt: Supply bootinfo for BIOS

  hw/m68k/Kconfig   |   3 +
  hw/m68k/virt.c| 231 --
  include/standard-headers/asm-m68k/bootinfo-virt.h |   4 +
  3 files changed, 176 insertions(+), 62 deletions(-)
---
base-commit: 60b54b67c63d8f076152e0f7dccf39854dfc6a77
change-id: 20240527-m68k-bios-a0a2370181f5

Best regards,





Re: [PULL 0/4] Trivial patches for 2024-04-02

2024-04-02 Thread Laurent Vivier

Le 02/04/2024 à 12:41, Michael Tokarev a écrit :



Author: Stefan Weil via 


*SIGH*  This happened *again*.


(you'll need to tell git log "--no-mailmap" to not get confused
by the mapping we have for the last time one of these slipped
through...)


Now this is interesting.  And this is exactly why I haven't noticed
it - I did pay attention to Author lines this time.  -- because
it is displayed with mailmap applied.  How very useful.

I have to use `git show --no-mailmap' to see the original " via.."
version.



To post PR I generally use git-publish and I have a hook that checks that.

$ cat .git/hooks/pre-publish-send-email
!/bin/bash

NAME=$(git config --get user.name)
EMAIL=$(git config --get user.email)

for PATCH in $1/*.patch; do
if [ $(basename $PATCH) = "-cover-letter.patch" ]; then
continue
fi
if ! grep -q "^Signed-off-by: $NAME <$EMAIL>" $PATCH; then
echo "Error: Missing sender S-o-B in $PATCH"
exit 1
fi
if grep "^From: " $PATCH | grep -q "" ; then
echo "Error: Author email address is mangled by the mailing list in 
$PATCH"
exit 1
fi
done
exit 0




[PULL 1/1] virt: set the CPU type in BOOTINFO

2024-03-11 Thread Laurent Vivier
BI_CPUTYPE/BI_MMUTYPE/BI_FPUTYPE were statically assigned to the
68040 information.
This patch changes the code to set in bootinfo the information
provided by the command line '-cpu' parameter.

Bug: https://gitlab.com/qemu-project/qemu/-/issues/2091
Reported-by: Daniel Palmer 
Signed-off-by: Laurent Vivier 
Reviewed-by: Mark Cave-Ayland 
Message-ID: <20240223155742.2790252-1-laur...@vivier.eu>
---
 hw/m68k/virt.c | 17 ++---
 1 file changed, 14 insertions(+), 3 deletions(-)

diff --git a/hw/m68k/virt.c b/hw/m68k/virt.c
index e2792ef46d93..b8e5e102e6b9 100644
--- a/hw/m68k/virt.c
+++ b/hw/m68k/virt.c
@@ -239,9 +239,20 @@ static void virt_init(MachineState *machine)
 param_ptr = param_blob;
 
 BOOTINFO1(param_ptr, BI_MACHTYPE, MACH_VIRT);
-BOOTINFO1(param_ptr, BI_FPUTYPE, FPU_68040);
-BOOTINFO1(param_ptr, BI_MMUTYPE, MMU_68040);
-BOOTINFO1(param_ptr, BI_CPUTYPE, CPU_68040);
+if (m68k_feature(>env, M68K_FEATURE_M68020)) {
+BOOTINFO1(param_ptr, BI_CPUTYPE, CPU_68020);
+} else if (m68k_feature(>env, M68K_FEATURE_M68030)) {
+BOOTINFO1(param_ptr, BI_MMUTYPE, MMU_68030);
+BOOTINFO1(param_ptr, BI_CPUTYPE, CPU_68030);
+} else if (m68k_feature(>env, M68K_FEATURE_M68040)) {
+BOOTINFO1(param_ptr, BI_FPUTYPE, FPU_68040);
+BOOTINFO1(param_ptr, BI_MMUTYPE, MMU_68040);
+BOOTINFO1(param_ptr, BI_CPUTYPE, CPU_68040);
+} else if (m68k_feature(>env, M68K_FEATURE_M68060)) {
+BOOTINFO1(param_ptr, BI_FPUTYPE, FPU_68060);
+BOOTINFO1(param_ptr, BI_MMUTYPE, MMU_68060);
+BOOTINFO1(param_ptr, BI_CPUTYPE, CPU_68060);
+}
 BOOTINFO2(param_ptr, BI_MEMCHUNK, 0, ram_size);
 
 BOOTINFO1(param_ptr, BI_VIRT_QEMU_VERSION,
-- 
2.43.2




[PULL 0/1] M68k for 9.0 patches

2024-03-11 Thread Laurent Vivier
The following changes since commit 7489f7f3f81dcb776df8c1b9a9db281fc21bf05f:

  Merge tag 'hw-misc-20240309' of https://github.com/philmd/qemu into staging 
(2024-03-09 20:12:21 +)

are available in the Git repository at:

  https://github.com/vivier/qemu-m68k.git tags/m68k-for-9.0-pull-request

for you to fetch changes up to e39a0809b99bbbe5f0ec432fdd9e8c943ba24936:

  virt: set the CPU type in BOOTINFO (2024-03-11 09:38:08 +0100)


Pull request for m68k 20240311



Laurent Vivier (1):
  virt: set the CPU type in BOOTINFO

 hw/m68k/virt.c | 17 ++---
 1 file changed, 14 insertions(+), 3 deletions(-)

-- 
2.43.2




Re: [PATCH v3 2/2] e1000e: fix link state on resume

2024-03-08 Thread Laurent Vivier

On 3/8/24 09:56, Laurent Vivier wrote:

On resume e1000e_vm_state_change() always calls e1000e_autoneg_resume()
that sets link_down to false, and thus activates the link even
if we have disabled it.

The problem can be reproduced starting qemu in paused state (-S) and
then set the link to down. When we resume the machine the link appears
to be up.

Reproducer:

# qemu-system-x86_64 ... -device e1000e,netdev=netdev0,id=net0 -S

{"execute": "qmp_capabilities" }
{"execute": "set_link", "arguments": {"name": "net0", "up": false}}
{"execute": "cont" }

To fix the problem, merge the content of e1000e_vm_state_change()
into e1000e_core_post_load() as e1000 does.

Buglink: https://issues.redhat.com/browse/RHEL-21867
Suggested-by: Akihiko Odaki 
Signed-off-by: Laurent Vivier 
---
  hw/net/e1000e_core.c | 56 +++-
  hw/net/e1000e_core.h |  2 --
  2 files changed, 3 insertions(+), 55 deletions(-)


v3:
  - remove e1000e_autoneg_pause()





[PATCH v3 1/2] igb: fix link state on resume

2024-03-08 Thread Laurent Vivier
On resume igb_vm_state_change() always calls igb_autoneg_resume()
that sets link_down to false, and thus activates the link even
if we have disabled it.

The problem can be reproduced starting qemu in paused state (-S) and
then set the link to down. When we resume the machine the link appears
to be up.

Reproducer:

   # qemu-system-x86_64 ... -device igb,netdev=netdev0,id=net0 -S

   {"execute": "qmp_capabilities" }
   {"execute": "set_link", "arguments": {"name": "net0", "up": false}}
   {"execute": "cont" }

To fix the problem, merge the content of igb_vm_state_change()
into igb_core_post_load() as e1000 does.

Buglink: https://issues.redhat.com/browse/RHEL-21867
Suggested-by: Akihiko Odaki 
Signed-off-by: Laurent Vivier 
---
 hw/net/igb_core.c | 47 +++
 hw/net/igb_core.h |  2 --
 2 files changed, 3 insertions(+), 46 deletions(-)

diff --git a/hw/net/igb_core.c b/hw/net/igb_core.c
index 2a7a11aa9ed5..31ab959ab8ff 100644
--- a/hw/net/igb_core.c
+++ b/hw/net/igb_core.c
@@ -160,14 +160,6 @@ igb_intmgr_timer_resume(IGBIntrDelayTimer *timer)
 }
 }
 
-static void
-igb_intmgr_timer_pause(IGBIntrDelayTimer *timer)
-{
-if (timer->running) {
-timer_del(timer->timer);
-}
-}
-
 static void
 igb_intrmgr_on_msix_throttling_timer(void *opaque)
 {
@@ -212,16 +204,6 @@ igb_intrmgr_resume(IGBCore *core)
 }
 }
 
-static void
-igb_intrmgr_pause(IGBCore *core)
-{
-int i;
-
-for (i = 0; i < IGB_INTR_NUM; i++) {
-igb_intmgr_timer_pause(>eitr[i]);
-}
-}
-
 static void
 igb_intrmgr_reset(IGBCore *core)
 {
@@ -4290,12 +4272,6 @@ igb_core_read(IGBCore *core, hwaddr addr, unsigned size)
 return 0;
 }
 
-static inline void
-igb_autoneg_pause(IGBCore *core)
-{
-timer_del(core->autoneg_timer);
-}
-
 static void
 igb_autoneg_resume(IGBCore *core)
 {
@@ -4307,22 +4283,6 @@ igb_autoneg_resume(IGBCore *core)
 }
 }
 
-static void
-igb_vm_state_change(void *opaque, bool running, RunState state)
-{
-IGBCore *core = opaque;
-
-if (running) {
-trace_e1000e_vm_state_running();
-igb_intrmgr_resume(core);
-igb_autoneg_resume(core);
-} else {
-trace_e1000e_vm_state_stopped();
-igb_autoneg_pause(core);
-igb_intrmgr_pause(core);
-}
-}
-
 void
 igb_core_pci_realize(IGBCore*core,
  const uint16_t *eeprom_templ,
@@ -4335,8 +4295,6 @@ igb_core_pci_realize(IGBCore*core,
igb_autoneg_timer, core);
 igb_intrmgr_pci_realize(core);
 
-core->vmstate = qemu_add_vm_change_state_handler(igb_vm_state_change, 
core);
-
 for (i = 0; i < IGB_NUM_QUEUES; i++) {
 net_tx_pkt_init(>tx[i].tx_pkt, E1000E_MAX_TX_FRAGS);
 }
@@ -4360,8 +4318,6 @@ igb_core_pci_uninit(IGBCore *core)
 
 igb_intrmgr_pci_unint(core);
 
-qemu_del_vm_change_state_handler(core->vmstate);
-
 for (i = 0; i < IGB_NUM_QUEUES; i++) {
 net_tx_pkt_uninit(core->tx[i].tx_pkt);
 }
@@ -4586,5 +4542,8 @@ igb_core_post_load(IGBCore *core)
  */
 nc->link_down = (core->mac[STATUS] & E1000_STATUS_LU) == 0;
 
+igb_intrmgr_resume(core);
+igb_autoneg_resume(core);
+
 return 0;
 }
diff --git a/hw/net/igb_core.h b/hw/net/igb_core.h
index bf8c46f26b51..d70b54e318f1 100644
--- a/hw/net/igb_core.h
+++ b/hw/net/igb_core.h
@@ -90,8 +90,6 @@ struct IGBCore {
 
 IGBIntrDelayTimer eitr[IGB_INTR_NUM];
 
-VMChangeStateEntry *vmstate;
-
 uint32_t eitr_guest_value[IGB_INTR_NUM];
 
 uint8_t permanent_mac[ETH_ALEN];
-- 
2.43.0




[PATCH v3 2/2] e1000e: fix link state on resume

2024-03-08 Thread Laurent Vivier
On resume e1000e_vm_state_change() always calls e1000e_autoneg_resume()
that sets link_down to false, and thus activates the link even
if we have disabled it.

The problem can be reproduced starting qemu in paused state (-S) and
then set the link to down. When we resume the machine the link appears
to be up.

Reproducer:

   # qemu-system-x86_64 ... -device e1000e,netdev=netdev0,id=net0 -S

   {"execute": "qmp_capabilities" }
   {"execute": "set_link", "arguments": {"name": "net0", "up": false}}
   {"execute": "cont" }

To fix the problem, merge the content of e1000e_vm_state_change()
into e1000e_core_post_load() as e1000 does.

Buglink: https://issues.redhat.com/browse/RHEL-21867
Suggested-by: Akihiko Odaki 
Signed-off-by: Laurent Vivier 
---
 hw/net/e1000e_core.c | 56 +++-
 hw/net/e1000e_core.h |  2 --
 2 files changed, 3 insertions(+), 55 deletions(-)

diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c
index e324c02dd589..c0cce2a3fe40 100644
--- a/hw/net/e1000e_core.c
+++ b/hw/net/e1000e_core.c
@@ -123,14 +123,6 @@ e1000e_intmgr_timer_resume(E1000IntrDelayTimer *timer)
 }
 }
 
-static void
-e1000e_intmgr_timer_pause(E1000IntrDelayTimer *timer)
-{
-if (timer->running) {
-timer_del(timer->timer);
-}
-}
-
 static inline void
 e1000e_intrmgr_stop_timer(E1000IntrDelayTimer *timer)
 {
@@ -398,24 +390,6 @@ e1000e_intrmgr_resume(E1000ECore *core)
 }
 }
 
-static void
-e1000e_intrmgr_pause(E1000ECore *core)
-{
-int i;
-
-e1000e_intmgr_timer_pause(>radv);
-e1000e_intmgr_timer_pause(>rdtr);
-e1000e_intmgr_timer_pause(>raid);
-e1000e_intmgr_timer_pause(>tidv);
-e1000e_intmgr_timer_pause(>tadv);
-
-e1000e_intmgr_timer_pause(>itr);
-
-for (i = 0; i < E1000E_MSIX_VEC_NUM; i++) {
-e1000e_intmgr_timer_pause(>eitr[i]);
-}
-}
-
 static void
 e1000e_intrmgr_reset(E1000ECore *core)
 {
@@ -3334,12 +3308,6 @@ e1000e_core_read(E1000ECore *core, hwaddr addr, unsigned 
size)
 return 0;
 }
 
-static inline void
-e1000e_autoneg_pause(E1000ECore *core)
-{
-timer_del(core->autoneg_timer);
-}
-
 static void
 e1000e_autoneg_resume(E1000ECore *core)
 {
@@ -3351,22 +3319,6 @@ e1000e_autoneg_resume(E1000ECore *core)
 }
 }
 
-static void
-e1000e_vm_state_change(void *opaque, bool running, RunState state)
-{
-E1000ECore *core = opaque;
-
-if (running) {
-trace_e1000e_vm_state_running();
-e1000e_intrmgr_resume(core);
-e1000e_autoneg_resume(core);
-} else {
-trace_e1000e_vm_state_stopped();
-e1000e_autoneg_pause(core);
-e1000e_intrmgr_pause(core);
-}
-}
-
 void
 e1000e_core_pci_realize(E1000ECore *core,
 const uint16_t *eeprom_templ,
@@ -3379,9 +3331,6 @@ e1000e_core_pci_realize(E1000ECore *core,
e1000e_autoneg_timer, core);
 e1000e_intrmgr_pci_realize(core);
 
-core->vmstate =
-qemu_add_vm_change_state_handler(e1000e_vm_state_change, core);
-
 for (i = 0; i < E1000E_NUM_QUEUES; i++) {
 net_tx_pkt_init(>tx[i].tx_pkt, E1000E_MAX_TX_FRAGS);
 }
@@ -3405,8 +3354,6 @@ e1000e_core_pci_uninit(E1000ECore *core)
 
 e1000e_intrmgr_pci_unint(core);
 
-qemu_del_vm_change_state_handler(core->vmstate);
-
 for (i = 0; i < E1000E_NUM_QUEUES; i++) {
 net_tx_pkt_uninit(core->tx[i].tx_pkt);
 }
@@ -3576,5 +3523,8 @@ e1000e_core_post_load(E1000ECore *core)
  */
 nc->link_down = (core->mac[STATUS] & E1000_STATUS_LU) == 0;
 
+e1000e_intrmgr_resume(core);
+e1000e_autoneg_resume(core);
+
 return 0;
 }
diff --git a/hw/net/e1000e_core.h b/hw/net/e1000e_core.h
index 66b025cc43f1..01510ca78b47 100644
--- a/hw/net/e1000e_core.h
+++ b/hw/net/e1000e_core.h
@@ -98,8 +98,6 @@ struct E1000Core {
 
 E1000IntrDelayTimer eitr[E1000E_MSIX_VEC_NUM];
 
-VMChangeStateEntry *vmstate;
-
 uint32_t itr_guest_value;
 uint32_t eitr_guest_value[E1000E_MSIX_VEC_NUM];
 
-- 
2.43.0




Re: [PATCH v2 2/2] e1000e: fix link state on resume

2024-03-08 Thread Laurent Vivier

On 3/8/24 09:09, Jason Wang wrote:

On Tue, Mar 5, 2024 at 6:07 PM Laurent Vivier  wrote:


On 2/1/24 06:45, Jason Wang wrote:

On Wed, Jan 24, 2024 at 6:40 PM Laurent Vivier  wrote:


On resume e1000e_vm_state_change() always calls e1000e_autoneg_resume()
that sets link_down to false, and thus activates the link even
if we have disabled it.

The problem can be reproduced starting qemu in paused state (-S) and
then set the link to down. When we resume the machine the link appears
to be up.

Reproducer:

 # qemu-system-x86_64 ... -device e1000e,netdev=netdev0,id=net0 -S

 {"execute": "qmp_capabilities" }
 {"execute": "set_link", "arguments": {"name": "net0", "up": false}}
 {"execute": "cont" }

To fix the problem, merge the content of e1000e_vm_state_change()
into e1000e_core_post_load() as e1000 does.

Buglink: https://issues.redhat.com/browse/RHEL-21867
Fixes: 6f3fbe4ed06a ("net: Introduce e1000e device emulation")
Suggested-by: Akihiko Odaki 
Signed-off-by: Laurent Vivier 
---



I've queued this.


Ping?

Thanks,
Laurent



This fail CI at:

https://gitlab.com/jasowang/qemu/-/jobs/6348725267

It looks to me we can safely drop e1000e_autoneg_pause()?

Thanks



Yes, I'm going to send a new version of the patch.

Thanks,
Laurent




Re: [PATCH v2 2/2] e1000e: fix link state on resume

2024-03-05 Thread Laurent Vivier

On 2/1/24 06:45, Jason Wang wrote:

On Wed, Jan 24, 2024 at 6:40 PM Laurent Vivier  wrote:


On resume e1000e_vm_state_change() always calls e1000e_autoneg_resume()
that sets link_down to false, and thus activates the link even
if we have disabled it.

The problem can be reproduced starting qemu in paused state (-S) and
then set the link to down. When we resume the machine the link appears
to be up.

Reproducer:

# qemu-system-x86_64 ... -device e1000e,netdev=netdev0,id=net0 -S

{"execute": "qmp_capabilities" }
{"execute": "set_link", "arguments": {"name": "net0", "up": false}}
{"execute": "cont" }

To fix the problem, merge the content of e1000e_vm_state_change()
into e1000e_core_post_load() as e1000 does.

Buglink: https://issues.redhat.com/browse/RHEL-21867
Fixes: 6f3fbe4ed06a ("net: Introduce e1000e device emulation")
Suggested-by: Akihiko Odaki 
Signed-off-by: Laurent Vivier 
---



I've queued this.


Ping?

Thanks,
Laurent




[PATCH] virt: set the CPU type in BOOTINFO

2024-02-23 Thread Laurent Vivier
BI_CPUTYPE/BI_MMUTYPE/BI_FPUTYPE were statically assigned to the
68040 information.
This patch changes the code to set in bootinfo the information
provided by the command line '-cpu' parameter.

Bug: https://gitlab.com/qemu-project/qemu/-/issues/2091
Reported-by: Daniel Palmer 
Signed-off-by: Laurent Vivier 
---
 hw/m68k/virt.c | 17 ++---
 1 file changed, 14 insertions(+), 3 deletions(-)

diff --git a/hw/m68k/virt.c b/hw/m68k/virt.c
index e2792ef46d93..b8e5e102e6b9 100644
--- a/hw/m68k/virt.c
+++ b/hw/m68k/virt.c
@@ -239,9 +239,20 @@ static void virt_init(MachineState *machine)
 param_ptr = param_blob;
 
 BOOTINFO1(param_ptr, BI_MACHTYPE, MACH_VIRT);
-BOOTINFO1(param_ptr, BI_FPUTYPE, FPU_68040);
-BOOTINFO1(param_ptr, BI_MMUTYPE, MMU_68040);
-BOOTINFO1(param_ptr, BI_CPUTYPE, CPU_68040);
+if (m68k_feature(>env, M68K_FEATURE_M68020)) {
+BOOTINFO1(param_ptr, BI_CPUTYPE, CPU_68020);
+} else if (m68k_feature(>env, M68K_FEATURE_M68030)) {
+BOOTINFO1(param_ptr, BI_MMUTYPE, MMU_68030);
+BOOTINFO1(param_ptr, BI_CPUTYPE, CPU_68030);
+} else if (m68k_feature(>env, M68K_FEATURE_M68040)) {
+BOOTINFO1(param_ptr, BI_FPUTYPE, FPU_68040);
+BOOTINFO1(param_ptr, BI_MMUTYPE, MMU_68040);
+BOOTINFO1(param_ptr, BI_CPUTYPE, CPU_68040);
+} else if (m68k_feature(>env, M68K_FEATURE_M68060)) {
+BOOTINFO1(param_ptr, BI_FPUTYPE, FPU_68060);
+BOOTINFO1(param_ptr, BI_MMUTYPE, MMU_68060);
+BOOTINFO1(param_ptr, BI_CPUTYPE, CPU_68060);
+}
 BOOTINFO2(param_ptr, BI_MEMCHUNK, 0, ram_size);
 
 BOOTINFO1(param_ptr, BI_VIRT_QEMU_VERSION,
-- 
2.43.0




Re: [PATCH v3 0/3] nubus: add nubus-virtio-mmio device

2024-02-23 Thread Laurent Vivier

Le 11/01/2024 à 11:29, Mark Cave-Ayland a écrit :

This series introduces a new nubus-virtio-mmio device which can be plugged into
the q800 machine to enable a 68k Classic MacOS guest to access virtio devices
such as virtio-9p-device (host filesharing), virtio-gpu (extended framebuffer
support) and virtio-tablet-device (absolute positioning).

Once the nubus-virtio-mmio device has been plugged into the q800 machine, virtio
devices can be accessed by a Classic MacOS guest using the drivers from the
classicvirtio project at https://github.com/elliotnunn/classicvirtio.

The nubus-virtio-mmio device is purposefully designed to be similar to the
virtio-mmio interface used by the existing 68k virt machine, making use of a
similar memory layout and the goldfish PIC for simple interrupt management. The
main difference is that only a single goldfish PIC is used, however that still
allows up to 32 virtio devices to be connected using a single nubus card.

Patch 1 fixes an alignment bug in the existing nubus-device Declaration ROM code
whereby some ROM images could trigger an assert() in QEMU, patch 2 increases the
maximum Declaration ROM size (to aid development), whilst patch 3 adds the
nubus-virtio-mmio device itself.

Signed-off-by: Mark Cave-Ayland 

[Patches still needing review: 2, 3]

v3:
- Rebase onto master
- Update patch 1 alignment calculation to use intermediatery uint8_t rom_ptr
   variable, add Phil's R-B tag
- Add patch 2 to increase maximum Declaration ROM size to 1MB

v2:
- Rebase onto master
- Adjust comment in patch 1 as suggested by Phil


Mark Cave-Ayland (3):
   nubus-device: round Declaration ROM memory region address to
 qemu_target_page_size()
   nubus.h: increase maximum Declaration ROM size from 128k to 1Mb
   nubus: add nubus-virtio-mmio device

  hw/nubus/meson.build |   1 +
  hw/nubus/nubus-device.c  |  18 +++--
  hw/nubus/nubus-virtio-mmio.c | 102 +++
  include/hw/nubus/nubus-virtio-mmio.h |  36 ++
  include/hw/nubus/nubus.h |   2 +-
  5 files changed, 154 insertions(+), 5 deletions(-)
  create mode 100644 hw/nubus/nubus-virtio-mmio.c
  create mode 100644 include/hw/nubus/nubus-virtio-mmio.h



Series Reviewed-by: Laurent Vivier 



Re: [PATCH] target/m68k: Fix exception frame format for 68010

2024-02-23 Thread Laurent Vivier

Le 15/01/2024 à 11:16, Daniel Palmer a écrit :

 From the 68010 a word with the frame format and exception vector
are placed on the stack before the PC and SR.

M68K_FEATURE_QUAD_MULDIV is currently checked to workout if to do
this or not for the configured CPU but that flag isn't set for
68010 so currently the exception stack when 68010 is configured
is incorrect.

It seems like checking M68K_FEATURE_MOVEFROMSR_PRIV would do but
adding a new flag that shows exactly what is going on here is
maybe clearer.

Add a new flag for the behaviour, M68K_FEATURE_EXCEPTION_FORMAT_VEC,
and set it for 68010 and above, and then use it to control if the
format and vector word are pushed/pop during exception entry/exit.

Signed-off-by: Daniel Palmer 
---
  target/m68k/cpu.c   | 4 +++-
  target/m68k/cpu.h   | 2 ++
  target/m68k/op_helper.c | 4 ++--
  3 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c
index 1421e77c2c07..20718944b4c8 100644
--- a/target/m68k/cpu.c
+++ b/target/m68k/cpu.c
@@ -137,7 +137,8 @@ static void m68000_cpu_initfn(Object *obj)
  }
  
  /*

- * Adds BKPT, MOVE-from-SR *now priv instr, and MOVEC, MOVES, RTD
+ * Adds BKPT, MOVE-from-SR *now priv instr, and MOVEC, MOVES, RTD,
+ *  format+vector in exception frame.
   */
  static void m68010_cpu_initfn(Object *obj)
  {
@@ -150,6 +151,7 @@ static void m68010_cpu_initfn(Object *obj)
  m68k_set_feature(env, M68K_FEATURE_BKPT);
  m68k_set_feature(env, M68K_FEATURE_MOVEC);
  m68k_set_feature(env, M68K_FEATURE_MOVEFROMSR_PRIV);
+m68k_set_feature(env, M68K_FEATURE_EXCEPTION_FORMAT_VEC);
  }
  
  /*

diff --git a/target/m68k/cpu.h b/target/m68k/cpu.h
index d13427b0fe61..0fc591e618f6 100644
--- a/target/m68k/cpu.h
+++ b/target/m68k/cpu.h
@@ -549,6 +549,8 @@ enum m68k_features {
  M68K_FEATURE_TRAPCC,
  /* MOVE from SR privileged (from 68010) */
  M68K_FEATURE_MOVEFROMSR_PRIV,
+/* Exception frame with format+vector (from 68010) */
+M68K_FEATURE_EXCEPTION_FORMAT_VEC,
  };
  
  static inline bool m68k_feature(CPUM68KState *env, int feature)

diff --git a/target/m68k/op_helper.c b/target/m68k/op_helper.c
index 1ce850bbc594..b09771672dec 100644
--- a/target/m68k/op_helper.c
+++ b/target/m68k/op_helper.c
@@ -52,7 +52,7 @@ throwaway:
  sp += 2;
  env->pc = cpu_ldl_mmuidx_ra(env, sp, MMU_KERNEL_IDX, 0);
  sp += 4;
-if (m68k_feature(env, M68K_FEATURE_QUAD_MULDIV)) {
+if (m68k_feature(env, M68K_FEATURE_EXCEPTION_FORMAT_VEC)) {
  /*  all except 68000 */
  fmt = cpu_lduw_mmuidx_ra(env, sp, MMU_KERNEL_IDX, 0);
  sp += 2;
@@ -256,7 +256,7 @@ static inline void do_stack_frame(CPUM68KState *env, 
uint32_t *sp,
uint16_t format, uint16_t sr,
uint32_t addr, uint32_t retaddr)
  {
-if (m68k_feature(env, M68K_FEATURE_QUAD_MULDIV)) {
+if (m68k_feature(env, M68K_FEATURE_EXCEPTION_FORMAT_VEC)) {
  /*  all except 68000 */
  CPUState *cs = env_cpu(env);
  switch (format) {


Reviewed-by: Laurent Vivier 



Re: [PATCH] iothread: Simplify expression in qemu_in_iothread()

2024-02-08 Thread Laurent Vivier

Le 08/02/2024 à 11:16, Kevin Wolf a écrit :

'a == b ? false : true' is a rather convoluted way of writing 'a != b'.
Use the more obvious way to write it.

Signed-off-by: Kevin Wolf 
---
  iothread.c | 3 +--
  1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/iothread.c b/iothread.c
index 6c1fc8c856..e1e9e04736 100644
--- a/iothread.c
+++ b/iothread.c
@@ -404,6 +404,5 @@ IOThread *iothread_by_id(const char *id)
  
  bool qemu_in_iothread(void)

  {
-return qemu_get_current_aio_context() == qemu_get_aio_context() ?
-false : true;
+return qemu_get_current_aio_context() != qemu_get_aio_context();
  }


Reviewed-by: Laurent Vivier 



Re: [PATCH trivial 1/2] close_all_open_fd(): move to oslib-posix.c

2024-01-25 Thread Laurent Vivier

Le 25/01/2024 à 23:29, Michael Tokarev a écrit :

Initially in async-teardown.c, but the same construct is used
elsewhere too.

Signed-off-by: Michael Tokarev 
---
  include/sysemu/os-posix.h |  1 +
  system/async-teardown.c   | 37 +
  util/oslib-posix.c| 36 
  3 files changed, 38 insertions(+), 36 deletions(-)

diff --git a/include/sysemu/os-posix.h b/include/sysemu/os-posix.h
index dff32ae185..4c91d03f44 100644
--- a/include/sysemu/os-posix.h
+++ b/include/sysemu/os-posix.h
@@ -53,6 +53,7 @@ bool os_set_runas(const char *user_id);
  void os_set_chroot(const char *path);
  void os_setup_post(void);
  int os_mlock(void);
+void os_close_all_open_fd(int minfd);
  
  /**

   * qemu_alloc_stack:
diff --git a/system/async-teardown.c b/system/async-teardown.c
index 396963c091..41d3d94935 100644
--- a/system/async-teardown.c
+++ b/system/async-teardown.c
@@ -26,40 +26,6 @@
  
  static pid_t the_ppid;
  
-/*

- * Close all open file descriptors.
- */
-static void close_all_open_fd(void)
-{
-struct dirent *de;
-int fd, dfd;
-DIR *dir;
-
-#ifdef CONFIG_CLOSE_RANGE
-int r = close_range(0, ~0U, 0);
-if (!r) {
-/* Success, no need to try other ways. */
-return;
-}
-#endif
-
-dir = opendir("/proc/self/fd");
-if (!dir) {
-/* If /proc is not mounted, there is nothing that can be done. */
-return;
-}
-/* Avoid closing the directory. */
-dfd = dirfd(dir);
-
-for (de = readdir(dir); de; de = readdir(dir)) {
-fd = atoi(de->d_name);
-if (fd != dfd) {
-close(fd);
-}
-}
-closedir(dir);
-}
-
  static void hup_handler(int signal)
  {
  /* Check every second if this process has been reparented. */
@@ -85,9 +51,8 @@ static int async_teardown_fn(void *arg)
  /*
   * Close all file descriptors that might have been inherited from the
   * main qemu process when doing clone, needed to make libvirt happy.
- * Not using close_range for increased compatibility with older kernels.
   */
-close_all_open_fd();
+os_close_all_open_fd(0);
  
  /* Set up a handler for SIGHUP and unblock SIGHUP. */

  sigaction(SIGHUP, , NULL);
diff --git a/util/oslib-posix.c b/util/oslib-posix.c
index 7c297003b9..09d0ce4da6 100644
--- a/util/oslib-posix.c
+++ b/util/oslib-posix.c
@@ -27,6 +27,7 @@
   */
  
  #include "qemu/osdep.h"

+#include 
  #include 
  
  #include 

@@ -106,6 +107,41 @@ int qemu_get_thread_id(void)
  #endif
  }
  
+/*

+ * Close all open file descriptors starting with minfd and up.
+ * Not using close_range for increased compatibility with older kernels.
+ */
+void os_close_all_open_fd(int minfd)
+{
+struct dirent *de;
+int fd, dfd;
+DIR *dir;
+
+#ifdef CONFIG_CLOSE_RANGE
+int r = close_range(minfd, ~0U, 0);
+if (!r) {
+/* Success, no need to try other ways. */
+return;
+}
+#endif
+
+dir = opendir("/proc/self/fd");
+if (!dir) {
+/* If /proc is not mounted, there is nothing that can be done. */
+return;
+}
+/* Avoid closing the directory. */
+dfd = dirfd(dir);
+
+for (de = readdir(dir); de; de = readdir(dir)) {
+fd = atoi(de->d_name);
+if (fd >= minfd && fd != dfd) {
+close(fd);
+}
+}
+closedir(dir);
+}


I think the way using sysconf(_SC_OPEN_MAX) is more portable, simpler and cleaner than the one using 
/proc/self/fd.


Thanks,
Laurent

+
  int qemu_daemon(int nochdir, int noclose)
  {
  return daemon(nochdir, noclose);





[PATCH v2 2/2] e1000e: fix link state on resume

2024-01-24 Thread Laurent Vivier
On resume e1000e_vm_state_change() always calls e1000e_autoneg_resume()
that sets link_down to false, and thus activates the link even
if we have disabled it.

The problem can be reproduced starting qemu in paused state (-S) and
then set the link to down. When we resume the machine the link appears
to be up.

Reproducer:

   # qemu-system-x86_64 ... -device e1000e,netdev=netdev0,id=net0 -S

   {"execute": "qmp_capabilities" }
   {"execute": "set_link", "arguments": {"name": "net0", "up": false}}
   {"execute": "cont" }

To fix the problem, merge the content of e1000e_vm_state_change()
into e1000e_core_post_load() as e1000 does.

Buglink: https://issues.redhat.com/browse/RHEL-21867
Fixes: 6f3fbe4ed06a ("net: Introduce e1000e device emulation")
Suggested-by: Akihiko Odaki 
Signed-off-by: Laurent Vivier 
---

Notes:
v2: Add Fixes: and a comment about e1000e_intrmgr_resume() purpose.

 hw/net/e1000e_core.c | 54 ++--
 hw/net/e1000e_core.h |  2 --
 2 files changed, 7 insertions(+), 49 deletions(-)

diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c
index e324c02dd589..ac8d4bb2433a 100644
--- a/hw/net/e1000e_core.c
+++ b/hw/net/e1000e_core.c
@@ -123,14 +123,6 @@ e1000e_intmgr_timer_resume(E1000IntrDelayTimer *timer)
 }
 }
 
-static void
-e1000e_intmgr_timer_pause(E1000IntrDelayTimer *timer)
-{
-if (timer->running) {
-timer_del(timer->timer);
-}
-}
-
 static inline void
 e1000e_intrmgr_stop_timer(E1000IntrDelayTimer *timer)
 {
@@ -398,24 +390,6 @@ e1000e_intrmgr_resume(E1000ECore *core)
 }
 }
 
-static void
-e1000e_intrmgr_pause(E1000ECore *core)
-{
-int i;
-
-e1000e_intmgr_timer_pause(>radv);
-e1000e_intmgr_timer_pause(>rdtr);
-e1000e_intmgr_timer_pause(>raid);
-e1000e_intmgr_timer_pause(>tidv);
-e1000e_intmgr_timer_pause(>tadv);
-
-e1000e_intmgr_timer_pause(>itr);
-
-for (i = 0; i < E1000E_MSIX_VEC_NUM; i++) {
-e1000e_intmgr_timer_pause(>eitr[i]);
-}
-}
-
 static void
 e1000e_intrmgr_reset(E1000ECore *core)
 {
@@ -3351,22 +3325,6 @@ e1000e_autoneg_resume(E1000ECore *core)
 }
 }
 
-static void
-e1000e_vm_state_change(void *opaque, bool running, RunState state)
-{
-E1000ECore *core = opaque;
-
-if (running) {
-trace_e1000e_vm_state_running();
-e1000e_intrmgr_resume(core);
-e1000e_autoneg_resume(core);
-} else {
-trace_e1000e_vm_state_stopped();
-e1000e_autoneg_pause(core);
-e1000e_intrmgr_pause(core);
-}
-}
-
 void
 e1000e_core_pci_realize(E1000ECore *core,
 const uint16_t *eeprom_templ,
@@ -3379,9 +3337,6 @@ e1000e_core_pci_realize(E1000ECore *core,
e1000e_autoneg_timer, core);
 e1000e_intrmgr_pci_realize(core);
 
-core->vmstate =
-qemu_add_vm_change_state_handler(e1000e_vm_state_change, core);
-
 for (i = 0; i < E1000E_NUM_QUEUES; i++) {
 net_tx_pkt_init(>tx[i].tx_pkt, E1000E_MAX_TX_FRAGS);
 }
@@ -3405,8 +3360,6 @@ e1000e_core_pci_uninit(E1000ECore *core)
 
 e1000e_intrmgr_pci_unint(core);
 
-qemu_del_vm_change_state_handler(core->vmstate);
-
 for (i = 0; i < E1000E_NUM_QUEUES; i++) {
 net_tx_pkt_uninit(core->tx[i].tx_pkt);
 }
@@ -3576,5 +3529,12 @@ e1000e_core_post_load(E1000ECore *core)
  */
 nc->link_down = (core->mac[STATUS] & E1000_STATUS_LU) == 0;
 
+/*
+ * we need to restart intrmgr timers, as an older version of
+ * QEMU can have stopped them before migration
+ */
+e1000e_intrmgr_resume(core);
+e1000e_autoneg_resume(core);
+
 return 0;
 }
diff --git a/hw/net/e1000e_core.h b/hw/net/e1000e_core.h
index 66b025cc43f1..01510ca78b47 100644
--- a/hw/net/e1000e_core.h
+++ b/hw/net/e1000e_core.h
@@ -98,8 +98,6 @@ struct E1000Core {
 
 E1000IntrDelayTimer eitr[E1000E_MSIX_VEC_NUM];
 
-VMChangeStateEntry *vmstate;
-
 uint32_t itr_guest_value;
 uint32_t eitr_guest_value[E1000E_MSIX_VEC_NUM];
 
-- 
2.43.0




[PATCH v2 1/2] igb: fix link state on resume

2024-01-24 Thread Laurent Vivier
On resume igb_vm_state_change() always calls igb_autoneg_resume()
that sets link_down to false, and thus activates the link even
if we have disabled it.

The problem can be reproduced starting qemu in paused state (-S) and
then set the link to down. When we resume the machine the link appears
to be up.

Reproducer:

   # qemu-system-x86_64 ... -device igb,netdev=netdev0,id=net0 -S

   {"execute": "qmp_capabilities" }
   {"execute": "set_link", "arguments": {"name": "net0", "up": false}}
   {"execute": "cont" }

To fix the problem, merge the content of igb_vm_state_change()
into igb_core_post_load() as e1000 does.

Buglink: https://issues.redhat.com/browse/RHEL-21867
Fixes: 3a977deebe6b ("Intrdocue igb device emulation")
Cc: akihiko.od...@daynix.com
Suggested-by: Akihiko Odaki 
Signed-off-by: Laurent Vivier 
---

Notes:
v2: Add Fixes: and a comment about igb_intrmgr_resume() purpose.

 hw/net/igb_core.c | 51 +++
 hw/net/igb_core.h |  2 --
 2 files changed, 7 insertions(+), 46 deletions(-)

diff --git a/hw/net/igb_core.c b/hw/net/igb_core.c
index 2a7a11aa9ed5..bcd5f6cd9cdd 100644
--- a/hw/net/igb_core.c
+++ b/hw/net/igb_core.c
@@ -160,14 +160,6 @@ igb_intmgr_timer_resume(IGBIntrDelayTimer *timer)
 }
 }
 
-static void
-igb_intmgr_timer_pause(IGBIntrDelayTimer *timer)
-{
-if (timer->running) {
-timer_del(timer->timer);
-}
-}
-
 static void
 igb_intrmgr_on_msix_throttling_timer(void *opaque)
 {
@@ -212,16 +204,6 @@ igb_intrmgr_resume(IGBCore *core)
 }
 }
 
-static void
-igb_intrmgr_pause(IGBCore *core)
-{
-int i;
-
-for (i = 0; i < IGB_INTR_NUM; i++) {
-igb_intmgr_timer_pause(>eitr[i]);
-}
-}
-
 static void
 igb_intrmgr_reset(IGBCore *core)
 {
@@ -4290,12 +4272,6 @@ igb_core_read(IGBCore *core, hwaddr addr, unsigned size)
 return 0;
 }
 
-static inline void
-igb_autoneg_pause(IGBCore *core)
-{
-timer_del(core->autoneg_timer);
-}
-
 static void
 igb_autoneg_resume(IGBCore *core)
 {
@@ -4307,22 +4283,6 @@ igb_autoneg_resume(IGBCore *core)
 }
 }
 
-static void
-igb_vm_state_change(void *opaque, bool running, RunState state)
-{
-IGBCore *core = opaque;
-
-if (running) {
-trace_e1000e_vm_state_running();
-igb_intrmgr_resume(core);
-igb_autoneg_resume(core);
-} else {
-trace_e1000e_vm_state_stopped();
-igb_autoneg_pause(core);
-igb_intrmgr_pause(core);
-}
-}
-
 void
 igb_core_pci_realize(IGBCore*core,
  const uint16_t *eeprom_templ,
@@ -4335,8 +4295,6 @@ igb_core_pci_realize(IGBCore*core,
igb_autoneg_timer, core);
 igb_intrmgr_pci_realize(core);
 
-core->vmstate = qemu_add_vm_change_state_handler(igb_vm_state_change, 
core);
-
 for (i = 0; i < IGB_NUM_QUEUES; i++) {
 net_tx_pkt_init(>tx[i].tx_pkt, E1000E_MAX_TX_FRAGS);
 }
@@ -4360,8 +4318,6 @@ igb_core_pci_uninit(IGBCore *core)
 
 igb_intrmgr_pci_unint(core);
 
-qemu_del_vm_change_state_handler(core->vmstate);
-
 for (i = 0; i < IGB_NUM_QUEUES; i++) {
 net_tx_pkt_uninit(core->tx[i].tx_pkt);
 }
@@ -4586,5 +4542,12 @@ igb_core_post_load(IGBCore *core)
  */
 nc->link_down = (core->mac[STATUS] & E1000_STATUS_LU) == 0;
 
+/*
+ * we need to restart intrmgr timers, as an older version of
+ * QEMU can have stopped them before migration
+ */
+igb_intrmgr_resume(core);
+igb_autoneg_resume(core);
+
 return 0;
 }
diff --git a/hw/net/igb_core.h b/hw/net/igb_core.h
index bf8c46f26b51..d70b54e318f1 100644
--- a/hw/net/igb_core.h
+++ b/hw/net/igb_core.h
@@ -90,8 +90,6 @@ struct IGBCore {
 
 IGBIntrDelayTimer eitr[IGB_INTR_NUM];
 
-VMChangeStateEntry *vmstate;
-
 uint32_t eitr_guest_value[IGB_INTR_NUM];
 
 uint8_t permanent_mac[ETH_ALEN];
-- 
2.43.0




[PATCH 1/2] igb: fix link state on resume

2024-01-23 Thread Laurent Vivier
On resume igb_vm_state_change() always calls igb_autoneg_resume()
that sets link_down to false, and thus activates the link even
if we have disabled it.

The problem can be reproduced starting qemu in paused state (-S) and
then set the link to down. When we resume the machine the link appears
to be up.

Reproducer:

   # qemu-system-x86_64 ... -device igb,netdev=netdev0,id=net0 -S

   {"execute": "qmp_capabilities" }
   {"execute": "set_link", "arguments": {"name": "net0", "up": false}}
   {"execute": "cont" }

To fix the problem, merge the content of igb_vm_state_change()
into igb_core_post_load() as e1000 does.

Buglink: https://issues.redhat.com/browse/RHEL-21867
Suggested-by: Akihiko Odaki 
Signed-off-by: Laurent Vivier 
---
 hw/net/igb_core.c | 47 +++
 hw/net/igb_core.h |  2 --
 2 files changed, 3 insertions(+), 46 deletions(-)

diff --git a/hw/net/igb_core.c b/hw/net/igb_core.c
index 2a7a11aa9ed5..31ab959ab8ff 100644
--- a/hw/net/igb_core.c
+++ b/hw/net/igb_core.c
@@ -160,14 +160,6 @@ igb_intmgr_timer_resume(IGBIntrDelayTimer *timer)
 }
 }
 
-static void
-igb_intmgr_timer_pause(IGBIntrDelayTimer *timer)
-{
-if (timer->running) {
-timer_del(timer->timer);
-}
-}
-
 static void
 igb_intrmgr_on_msix_throttling_timer(void *opaque)
 {
@@ -212,16 +204,6 @@ igb_intrmgr_resume(IGBCore *core)
 }
 }
 
-static void
-igb_intrmgr_pause(IGBCore *core)
-{
-int i;
-
-for (i = 0; i < IGB_INTR_NUM; i++) {
-igb_intmgr_timer_pause(>eitr[i]);
-}
-}
-
 static void
 igb_intrmgr_reset(IGBCore *core)
 {
@@ -4290,12 +4272,6 @@ igb_core_read(IGBCore *core, hwaddr addr, unsigned size)
 return 0;
 }
 
-static inline void
-igb_autoneg_pause(IGBCore *core)
-{
-timer_del(core->autoneg_timer);
-}
-
 static void
 igb_autoneg_resume(IGBCore *core)
 {
@@ -4307,22 +4283,6 @@ igb_autoneg_resume(IGBCore *core)
 }
 }
 
-static void
-igb_vm_state_change(void *opaque, bool running, RunState state)
-{
-IGBCore *core = opaque;
-
-if (running) {
-trace_e1000e_vm_state_running();
-igb_intrmgr_resume(core);
-igb_autoneg_resume(core);
-} else {
-trace_e1000e_vm_state_stopped();
-igb_autoneg_pause(core);
-igb_intrmgr_pause(core);
-}
-}
-
 void
 igb_core_pci_realize(IGBCore*core,
  const uint16_t *eeprom_templ,
@@ -4335,8 +4295,6 @@ igb_core_pci_realize(IGBCore*core,
igb_autoneg_timer, core);
 igb_intrmgr_pci_realize(core);
 
-core->vmstate = qemu_add_vm_change_state_handler(igb_vm_state_change, 
core);
-
 for (i = 0; i < IGB_NUM_QUEUES; i++) {
 net_tx_pkt_init(>tx[i].tx_pkt, E1000E_MAX_TX_FRAGS);
 }
@@ -4360,8 +4318,6 @@ igb_core_pci_uninit(IGBCore *core)
 
 igb_intrmgr_pci_unint(core);
 
-qemu_del_vm_change_state_handler(core->vmstate);
-
 for (i = 0; i < IGB_NUM_QUEUES; i++) {
 net_tx_pkt_uninit(core->tx[i].tx_pkt);
 }
@@ -4586,5 +4542,8 @@ igb_core_post_load(IGBCore *core)
  */
 nc->link_down = (core->mac[STATUS] & E1000_STATUS_LU) == 0;
 
+igb_intrmgr_resume(core);
+igb_autoneg_resume(core);
+
 return 0;
 }
diff --git a/hw/net/igb_core.h b/hw/net/igb_core.h
index bf8c46f26b51..d70b54e318f1 100644
--- a/hw/net/igb_core.h
+++ b/hw/net/igb_core.h
@@ -90,8 +90,6 @@ struct IGBCore {
 
 IGBIntrDelayTimer eitr[IGB_INTR_NUM];
 
-VMChangeStateEntry *vmstate;
-
 uint32_t eitr_guest_value[IGB_INTR_NUM];
 
 uint8_t permanent_mac[ETH_ALEN];
-- 
2.43.0




[PATCH 2/2] e1000e: fix link state on resume

2024-01-23 Thread Laurent Vivier
On resume e1000e_vm_state_change() always calls e1000e_autoneg_resume()
that sets link_down to false, and thus activates the link even
if we have disabled it.

The problem can be reproduced starting qemu in paused state (-S) and
then set the link to down. When we resume the machine the link appears
to be up.

Reproducer:

   # qemu-system-x86_64 ... -device e1000e,netdev=netdev0,id=net0 -S

   {"execute": "qmp_capabilities" }
   {"execute": "set_link", "arguments": {"name": "net0", "up": false}}
   {"execute": "cont" }

To fix the problem, merge the content of e1000e_vm_state_change()
into e1000e_core_post_load() as e1000 does.

Buglink: https://issues.redhat.com/browse/RHEL-21867
Suggested-by: Akihiko Odaki 
Signed-off-by: Laurent Vivier 
---
 hw/net/e1000e_core.c | 50 +++-
 hw/net/e1000e_core.h |  2 --
 2 files changed, 3 insertions(+), 49 deletions(-)

diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c
index e324c02dd589..95311fd60530 100644
--- a/hw/net/e1000e_core.c
+++ b/hw/net/e1000e_core.c
@@ -123,14 +123,6 @@ e1000e_intmgr_timer_resume(E1000IntrDelayTimer *timer)
 }
 }
 
-static void
-e1000e_intmgr_timer_pause(E1000IntrDelayTimer *timer)
-{
-if (timer->running) {
-timer_del(timer->timer);
-}
-}
-
 static inline void
 e1000e_intrmgr_stop_timer(E1000IntrDelayTimer *timer)
 {
@@ -398,24 +390,6 @@ e1000e_intrmgr_resume(E1000ECore *core)
 }
 }
 
-static void
-e1000e_intrmgr_pause(E1000ECore *core)
-{
-int i;
-
-e1000e_intmgr_timer_pause(>radv);
-e1000e_intmgr_timer_pause(>rdtr);
-e1000e_intmgr_timer_pause(>raid);
-e1000e_intmgr_timer_pause(>tidv);
-e1000e_intmgr_timer_pause(>tadv);
-
-e1000e_intmgr_timer_pause(>itr);
-
-for (i = 0; i < E1000E_MSIX_VEC_NUM; i++) {
-e1000e_intmgr_timer_pause(>eitr[i]);
-}
-}
-
 static void
 e1000e_intrmgr_reset(E1000ECore *core)
 {
@@ -3351,22 +3325,6 @@ e1000e_autoneg_resume(E1000ECore *core)
 }
 }
 
-static void
-e1000e_vm_state_change(void *opaque, bool running, RunState state)
-{
-E1000ECore *core = opaque;
-
-if (running) {
-trace_e1000e_vm_state_running();
-e1000e_intrmgr_resume(core);
-e1000e_autoneg_resume(core);
-} else {
-trace_e1000e_vm_state_stopped();
-e1000e_autoneg_pause(core);
-e1000e_intrmgr_pause(core);
-}
-}
-
 void
 e1000e_core_pci_realize(E1000ECore *core,
 const uint16_t *eeprom_templ,
@@ -3379,9 +3337,6 @@ e1000e_core_pci_realize(E1000ECore *core,
e1000e_autoneg_timer, core);
 e1000e_intrmgr_pci_realize(core);
 
-core->vmstate =
-qemu_add_vm_change_state_handler(e1000e_vm_state_change, core);
-
 for (i = 0; i < E1000E_NUM_QUEUES; i++) {
 net_tx_pkt_init(>tx[i].tx_pkt, E1000E_MAX_TX_FRAGS);
 }
@@ -3405,8 +3360,6 @@ e1000e_core_pci_uninit(E1000ECore *core)
 
 e1000e_intrmgr_pci_unint(core);
 
-qemu_del_vm_change_state_handler(core->vmstate);
-
 for (i = 0; i < E1000E_NUM_QUEUES; i++) {
 net_tx_pkt_uninit(core->tx[i].tx_pkt);
 }
@@ -3576,5 +3529,8 @@ e1000e_core_post_load(E1000ECore *core)
  */
 nc->link_down = (core->mac[STATUS] & E1000_STATUS_LU) == 0;
 
+e1000e_intrmgr_resume(core);
+e1000e_autoneg_resume(core);
+
 return 0;
 }
diff --git a/hw/net/e1000e_core.h b/hw/net/e1000e_core.h
index 66b025cc43f1..01510ca78b47 100644
--- a/hw/net/e1000e_core.h
+++ b/hw/net/e1000e_core.h
@@ -98,8 +98,6 @@ struct E1000Core {
 
 E1000IntrDelayTimer eitr[E1000E_MSIX_VEC_NUM];
 
-VMChangeStateEntry *vmstate;
-
 uint32_t itr_guest_value;
 uint32_t eitr_guest_value[E1000E_MSIX_VEC_NUM];
 
-- 
2.43.0




Re: Goldfish TTY enhancement

2024-01-12 Thread Laurent Vivier

Hi Jason,

Le 11/01/2024 à 19:58, Jason Thorpe a écrit :



On Jan 10, 2024, at 8:01 AM, Philippe Mathieu-Daudé  wrote:

IIUC Goldfish virtual HW is maintained externally by Google
https://android.googlesource.com/platform/external/qemu/+/master/docs/GOLDFISH-VIRTUAL-HARDWARE.TXT

I suppose the spec needs to be updated before the change can be
accepted in mainstream QEMU, but since I'm not sure I Cc'ed Alex,
David and Laurent.


Hey Philippe,

I have seen that document didn’t realize that it was the source of truth for 
the Goldfish devices in Qemu, as Qemu already has Goldfish devices that deviate 
in behavior from that document.  In particular:

1. There is no distinction between “rtc” and “timer” in Qemu.

2. The Goldfish “pic” device does not behave as that document describes.  In 
particular, the “NUMBER” register is described in that document as returning 
the lowest pending interrupt index or 0 for none (i.e. a number in the range 
0..32).  But Qemu returns a bitmask of pending interrupts when that register is 
read.  And despite the name “DISABLE_ALL” that document claims that writing to 
it merely clears the pending interrupts without disabling them (which would be 
quite the trick with level-triggered interrupt sources) whereas in Qemu, it 
does both clear and disable.

(I am not, in any way, advocating for a behavior change in Qemu, BTW… I just 
thought that referenced docuemnt was no longer relevant.)


In fact the source of truth is the kernel. The idea of using Goldfish in the virt m68k machine is to 
only have to code the QEMU part and to use the kernel part as-is. And the kernel part has diverged 
from the documentation...


Thanks,
Laurent



Re: [PATCH] hw/timer: fix systick trace message

2024-01-10 Thread Laurent Vivier

Le 09/01/2024 à 19:45, Samuel Tardieu a écrit :

Signed-off-by: Samuel Tardieu 
Fixes: ff68dacbc786 ("armv7m: Split systick out from NVIC")
---
  hw/timer/trace-events | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/timer/trace-events b/hw/timer/trace-events
index 3eccef83858..8145e18e3da 100644
--- a/hw/timer/trace-events
+++ b/hw/timer/trace-events
@@ -35,7 +35,7 @@ aspeed_timer_read(uint64_t offset, unsigned size, uint64_t value) 
"From 0x%" PRI
  
  # armv7m_systick.c

  systick_reload(void) "systick reload"
-systick_timer_tick(void) "systick reload"
+systick_timer_tick(void) "systick tick"
  systick_read(uint64_t addr, uint32_t value, unsigned size) "systick read addr 0x%" PRIx64 " 
data 0x%" PRIx32 " size %u"
  systick_write(uint64_t addr, uint32_t value, unsigned size) "systick write addr 0x%" PRIx64 
" data 0x%" PRIx32 " size %u"
  


Reviewed-by: Laurent Vivier 



Re: [PATCH] q800: move dp8393x_prom memory region to Q800MachineState

2023-12-28 Thread Laurent Vivier

Le 27/12/2023 à 22:02, Mark Cave-Ayland a écrit :

There is no need to dynamically allocate the memory region from the heap.

Signed-off-by: Mark Cave-Ayland 
---
  hw/m68k/q800.c | 7 +++
  include/hw/m68k/q800.h | 1 +
  2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/hw/m68k/q800.c b/hw/m68k/q800.c
index 83d1571d02..b80a3b6d5f 100644
--- a/hw/m68k/q800.c
+++ b/hw/m68k/q800.c
@@ -253,7 +253,6 @@ static void q800_machine_init(MachineState *machine)
  int bios_size;
  ram_addr_t initrd_base;
  int32_t initrd_size;
-MemoryRegion *dp8393x_prom = g_new(MemoryRegion, 1);
  uint8_t *prom;
  int i, checksum;
  MacFbMode *macfb_mode;
@@ -406,13 +405,13 @@ static void q800_machine_init(MachineState *machine)
  sysbus_connect_irq(sysbus, 0,
 qdev_get_gpio_in(DEVICE(>glue), GLUE_IRQ_IN_SONIC));
  
-memory_region_init_rom(dp8393x_prom, NULL, "dp8393x-q800.prom",

+memory_region_init_rom(>dp8393x_prom, NULL, "dp8393x-q800.prom",
 SONIC_PROM_SIZE, _fatal);
  memory_region_add_subregion(get_system_memory(), SONIC_PROM_BASE,
-dp8393x_prom);
+>dp8393x_prom);
  
  /* Add MAC address with valid checksum to PROM */

-prom = memory_region_get_ram_ptr(dp8393x_prom);
+prom = memory_region_get_ram_ptr(>dp8393x_prom);
  checksum = 0;
  for (i = 0; i < 6; i++) {
  prom[i] = revbit8(nd_table[0].macaddr.a[i]);
diff --git a/include/hw/m68k/q800.h b/include/hw/m68k/q800.h
index a9661f65f6..34365c9860 100644
--- a/include/hw/m68k/q800.h
+++ b/include/hw/m68k/q800.h
@@ -55,6 +55,7 @@ struct Q800MachineState {
  MOS6522Q800VIA1State via1;
  MOS6522Q800VIA2State via2;
  dp8393xState dp8393x;
+MemoryRegion dp8393x_prom;
  ESCCState escc;
  OrIRQState escc_orgate;
  SysBusESPState esp;


Reviewed-by: Laurent Vivier 



Re: [PATCH 1/2] linux-user: Define TARGET_O_LARGEFILE for aarch64

2023-12-03 Thread Laurent Vivier

Le 01/12/2023 à 04:21, Shu-Chun Weng a écrit :

In 050a1ba, when moving the macros from preprocessor-guarding to
file-based definition, TARGET_O_LARGEFILE appeared to have been
accidentally left off.

This may have correctness implication, but so far I was only confused by
strace's output.

Signed-off-by: Shu-Chun Weng 
---
  linux-user/aarch64/target_fcntl.h | 1 +
  1 file changed, 1 insertion(+)

diff --git a/linux-user/aarch64/target_fcntl.h 
b/linux-user/aarch64/target_fcntl.h
index efdf6e5f05..55ab788a7c 100644
--- a/linux-user/aarch64/target_fcntl.h
+++ b/linux-user/aarch64/target_fcntl.h
@@ -11,6 +11,7 @@
  #define TARGET_O_DIRECTORY  04 /* must be a directory */
  #define TARGET_O_NOFOLLOW  010 /* don't follow links */
  #define TARGET_O_DIRECT020 /* direct disk access hint */
+#define TARGET_O_LARGEFILE 040
  
  #include "../generic/fcntl.h"

  #endif


Reviewed-by: Laurent Vivier 



Re: [RFC 1/2] qapi/virtio: introduce the "show-bits" argument for x-query-virtio-status

2023-12-01 Thread Laurent Vivier

On 12/1/23 16:21, Markus Armbruster wrote:

Laurent Vivier  writes:


On 11/21/23 08:58, Markus Armbruster wrote:

Laurent, there's a question for you at the end.

Yong Huang  writes:


On Thu, Nov 16, 2023 at 10:44 PM Markus Armbruster 
wrote:


Hyman Huang  writes:


This patch allows to display feature and status bits in virtio-status.

An optional argument is introduced: show-bits. For example:
{"execute": "x-query-virtio-status",
   "arguments": {"path": "/machine/peripheral-anon/device[1]/virtio-backend",
 "show-bits": true}

Features and status bits could be helpful for applications to compare
directly. For instance, when an upper application aims to ensure the
virtio negotiation correctness between guest, QEMU, and OVS-DPDK, it use
the "ovs-vsctl list interface" command to retrieve interface features
(in number format) and the QMP command x-query-virtio-status to retrieve
vhost-user net device features. If "show-bits" is added, the application
can compare the two features directly; No need to encoding the features
returned by the QMP command.

This patch also serves as a preparation for the next one, which implements
a vhost-user test case about acked features of vhost-user protocol.

Note that since the matching HMP command is typically used for human,
leave it unchanged.

Signed-off-by: Hyman Huang 


[...]


Double-checking...  @feature-bits provides the exact same information as
@features, only in another encoding.  Correct?




Same for all the other new -bits.  Correct?


Yes, all the new fields are only about providing another encoding.


Why do we want to return the same information in two different
encodings?  I figure the commit message tries to answer this question:

   Features and status bits could be helpful for applications to compare
   directly. For instance, when an upper application aims to ensure the
   virtio negotiation correctness between guest, QEMU, and OVS-DPDK, it use
   the "ovs-vsctl list interface" command to retrieve interface features
   (in number format) and the QMP command x-query-virtio-status to retrieve
   vhost-user net device features. If "show-bits" is added, the application
   can compare the two features directly; No need to encoding the features
   returned by the QMP command.

   This patch also serves as a preparation for the next one, which 
implements
   a vhost-user test case about acked features of vhost-user protocol.

I guess you're trying to simplify use cases where the QMP client wants
to compare entire feature sets without caring for individual features.

The comparison is easy if both sets are represented the same way,
e.g. both are numbers, or both are lists of symbols.

With different representations, we first have to map to a common
representation.  Unfortunately, the design of x-query-virtio-status
makes this harder than it should be.

We use QAPI types VirtioDeviceStatus, VhostDeviceProtocols,
VirtioDeviceFeatures to represent feature sets.  They all work the same
way: array of strings plus a number.  For each bit QEMU knows, there's a
string in the array.  Any remaining bits go into the number.

The format of the string is undocumented.  They look like

  "WELL_KNOWN_SYMBOL: human readable explanation"

Mapping from bit to this string in a client would require duplicating
QEMU's code exactly.

Mapping both bit and string to just "WELL_KNOWN_SYMBOL" could perhaps be
done.

The mapping between symbols and bits is not visible in QMP.  Mapping
from string to bit requires exploiting the undocumented format: extract
the well-known symbol and decode it.

This encoding of feature sets goes back to commit f3034ad71fc (qmp:
decode feature & status bits in virtio-status) v7.2.  Before that, the
command returned the bits as a number.

For example, return value "member "status":

  Before f3034ad71fc:

  "status": 15,

  Since f3034ad71fc:

  "status": {
  "statuses": [
  "VIRTIO_CONFIG_S_ACKNOWLEDGE: Valid virtio device found",
  "VIRTIO_CONFIG_S_DRIVER: Guest OS compatible with device",
  "VIRTIO_CONFIG_S_FEATURES_OK: Feature negotiation complete",
  "VIRTIO_CONFIG_S_DRIVER_OK: Driver setup and ready"
  ]},

  With your patch:

  "status": {
  "statuses": [
  "VIRTIO_CONFIG_S_ACKNOWLEDGE: Valid virtio device found",
  "VIRTIO_CONFIG_S_DRIVER: Guest OS compatible with device",
  "VIRTIO_CONFIG_S_FEATURES_OK: Feature negotiation complete",
  "VIRTIO_CONFIG_S_DRIVER_OK: Driver setup and ready"
  ]},
  "

Re: [RFC 1/2] qapi/virtio: introduce the "show-bits" argument for x-query-virtio-status

2023-12-01 Thread Laurent Vivier

On 11/21/23 08:58, Markus Armbruster wrote:

Laurent, there's a question for you at the end.

Yong Huang  writes:


On Thu, Nov 16, 2023 at 10:44 PM Markus Armbruster 
wrote:


Hyman Huang  writes:


This patch allows to display feature and status bits in virtio-status.

An optional argument is introduced: show-bits. For example:
{"execute": "x-query-virtio-status",
  "arguments": {"path": "/machine/peripheral-anon/device[1]/virtio-backend",
"show-bits": true}

Features and status bits could be helpful for applications to compare
directly. For instance, when an upper application aims to ensure the
virtio negotiation correctness between guest, QEMU, and OVS-DPDK, it use
the "ovs-vsctl list interface" command to retrieve interface features
(in number format) and the QMP command x-query-virtio-status to retrieve
vhost-user net device features. If "show-bits" is added, the application
can compare the two features directly; No need to encoding the features
returned by the QMP command.

This patch also serves as a preparation for the next one, which implements
a vhost-user test case about acked features of vhost-user protocol.

Note that since the matching HMP command is typically used for human,
leave it unchanged.

Signed-off-by: Hyman Huang 
---
  hw/virtio/virtio-hmp-cmds.c |  2 +-
  hw/virtio/virtio-qmp.c  | 21 +++-
  qapi/virtio.json| 49 ++---
  3 files changed, 67 insertions(+), 5 deletions(-)

diff --git a/hw/virtio/virtio-hmp-cmds.c b/hw/virtio/virtio-hmp-cmds.c
index 477c97dea2..3774f3d4bf 100644
--- a/hw/virtio/virtio-hmp-cmds.c
+++ b/hw/virtio/virtio-hmp-cmds.c
@@ -108,7 +108,7 @@ void hmp_virtio_status(Monitor *mon, const QDict *qdict)
  {
  Error *err = NULL;
  const char *path = qdict_get_try_str(qdict, "path");
-VirtioStatus *s = qmp_x_query_virtio_status(path, );
+VirtioStatus *s = qmp_x_query_virtio_status(path, false, false, );

  if (err != NULL) {
  hmp_handle_error(mon, err);
diff --git a/hw/virtio/virtio-qmp.c b/hw/virtio/virtio-qmp.c
index 1dd96ed20f..2e92bf28ac 100644
--- a/hw/virtio/virtio-qmp.c
+++ b/hw/virtio/virtio-qmp.c
@@ -718,10 +718,15 @@ VirtIODevice *qmp_find_virtio_device(const char *path)
  return VIRTIO_DEVICE(dev);
  }

-VirtioStatus *qmp_x_query_virtio_status(const char *path, Error **errp)
+VirtioStatus *qmp_x_query_virtio_status(const char *path,
+bool has_show_bits,
+bool show_bits,
+Error **errp)
  {
  VirtIODevice *vdev;
  VirtioStatus *status;
+bool display_bits =
+has_show_bits ? show_bits : false;


Since !has_show_bits implies !show_bits, you can simply use
if (show_bits).


Ok





  vdev = qmp_find_virtio_device(path);
  if (vdev == NULL) {
@@ -733,6 +738,11 @@ VirtioStatus *qmp_x_query_virtio_status(const char *path, 
Error **errp)
  status->name = g_strdup(vdev->name);
  status->device_id = vdev->device_id;
  status->vhost_started = vdev->vhost_started;
+if (display_bits) {
+status->guest_features_bits = vdev->guest_features;
+status->host_features_bits = vdev->host_features;
+status->backend_features_bits = vdev->backend_features;
+}
  status->guest_features = qmp_decode_features(vdev->device_id,
   vdev->guest_features);
  status->host_features = qmp_decode_features(vdev->device_id,
@@ -753,6 +763,9 @@ VirtioStatus *qmp_x_query_virtio_status(const char *path, 
Error **errp)
  }

  status->num_vqs = virtio_get_num_queues(vdev);
+if (display_bits) {
+status->status_bits = vdev->status;
+}
  status->status = qmp_decode_status(vdev->status);
  status->isr = vdev->isr;
  status->queue_sel = vdev->queue_sel;
@@ -775,6 +788,12 @@ VirtioStatus *qmp_x_query_virtio_status(const char *path, 
Error **errp)
  status->vhost_dev->n_tmp_sections = hdev->n_tmp_sections;
  status->vhost_dev->nvqs = hdev->nvqs;
  status->vhost_dev->vq_index = hdev->vq_index;
+if (display_bits) {
+status->vhost_dev->features_bits = hdev->features;
+status->vhost_dev->acked_features_bits = hdev->acked_features;
+status->vhost_dev->backend_features_bits = hdev->backend_features;
+status->vhost_dev->protocol_features_bits = 
hdev->protocol_features;
+}
  status->vhost_dev->features =
  qmp_decode_features(vdev->device_id, hdev->features);
  status->vhost_dev->acked_features =
diff --git a/qapi/virtio.json b/qapi/virtio.json
index e6dcee7b83..608b841a89 100644
--- a/qapi/virtio.json
+++ b/qapi/virtio.json
@@ -79,12 +79,20 @@
  #
  # @vq-index: vhost_dev vq_index
  #
+# @features-bits: vhost_dev features in decimal format


Say "encoded as a number".  The number is decimal just because the
transport 

[PULL 2/4] macfb: rename DAFB_RESET to DAFB_LUT_INDEX

2023-11-06 Thread Laurent Vivier
From: Mark Cave-Ayland 

When A/UX uses the MacOS Device Manager Status (GetEntries) call to read the
contents of the CLUT, it is easy to see that the requested index is written to
the DAFB_RESET register. Update the palette_current index with the requested
value, and rename it to DAFB_LUT_INDEX to reflect its true purpose.

Signed-off-by: Mark Cave-Ayland 
Reviewed-by: Laurent Vivier 
Message-ID: <20231026085650.917663-3-mark.cave-ayl...@ilande.co.uk>
Signed-off-by: Laurent Vivier 
---
 hw/display/macfb.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/hw/display/macfb.c b/hw/display/macfb.c
index 28db2e9f246a..eb4ce6b824c4 100644
--- a/hw/display/macfb.c
+++ b/hw/display/macfb.c
@@ -36,7 +36,7 @@
 #define DAFB_INTR_MASK  0x104
 #define DAFB_INTR_STAT  0x108
 #define DAFB_INTR_CLEAR 0x10c
-#define DAFB_RESET  0x200
+#define DAFB_LUT_INDEX  0x200
 #define DAFB_LUT0x213
 
 #define DAFB_INTR_VBL   0x4
@@ -583,8 +583,8 @@ static void macfb_ctrl_write(void *opaque,
 s->regs[DAFB_INTR_STAT >> 2] &= ~DAFB_INTR_VBL;
 macfb_update_irq(s);
 break;
-case DAFB_RESET:
-s->palette_current = 0;
+case DAFB_LUT_INDEX:
+s->palette_current = (val & 0xff) * 3;
 break;
 case DAFB_LUT:
 s->color_palette[s->palette_current] = val;
-- 
2.41.0




[PULL 4/4] macfb: allow reads from the DAFB_LUT register

2023-11-06 Thread Laurent Vivier
From: Mark Cave-Ayland 

This enables A/UX to correctly retrieve the LUT entries when used with
applications that use the MacOS Device Manager Status (GetEntries) call.

Signed-off-by: Mark Cave-Ayland 
Reviewed-by: Laurent Vivier 
Message-ID: <20231026085650.917663-5-mark.cave-ayl...@ilande.co.uk>
Signed-off-by: Laurent Vivier 
---
 hw/display/macfb.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/hw/display/macfb.c b/hw/display/macfb.c
index 4a1c75d5720f..d61541ccb5d5 100644
--- a/hw/display/macfb.c
+++ b/hw/display/macfb.c
@@ -537,6 +537,11 @@ static uint64_t macfb_ctrl_read(void *opaque,
 case DAFB_MODE_SENSE:
 val = macfb_sense_read(s);
 break;
+case DAFB_LUT ... DAFB_LUT + 3:
+val = s->color_palette[s->palette_current];
+s->palette_current = (s->palette_current + 1) %
+ ARRAY_SIZE(s->color_palette);
+break;
 default:
 if (addr < MACFB_CTRL_TOPADDR) {
 val = s->regs[addr >> 2];
-- 
2.41.0




[PULL 3/4] macfb: allow larger write accesses to the DAFB_LUT register

2023-11-06 Thread Laurent Vivier
From: Mark Cave-Ayland 

The original tests with MacOS showed that only the bottom 8 bits of the DAFB_LUT
register were used when writing to the LUT, however A/UX performs some of its
writes using 4 byte accesses. Expand the address range for the DAFB_LUT register
so that different size accesses write the correct value to the color_palette
array.

Signed-off-by: Mark Cave-Ayland 
Reviewed-by: Laurent Vivier 
Message-ID: <20231026085650.917663-4-mark.cave-ayl...@ilande.co.uk>
Signed-off-by: Laurent Vivier 
---
 hw/display/macfb.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/hw/display/macfb.c b/hw/display/macfb.c
index eb4ce6b824c4..4a1c75d5720f 100644
--- a/hw/display/macfb.c
+++ b/hw/display/macfb.c
@@ -37,7 +37,7 @@
 #define DAFB_INTR_STAT  0x108
 #define DAFB_INTR_CLEAR 0x10c
 #define DAFB_LUT_INDEX  0x200
-#define DAFB_LUT0x213
+#define DAFB_LUT0x210
 
 #define DAFB_INTR_VBL   0x4
 
@@ -586,8 +586,8 @@ static void macfb_ctrl_write(void *opaque,
 case DAFB_LUT_INDEX:
 s->palette_current = (val & 0xff) * 3;
 break;
-case DAFB_LUT:
-s->color_palette[s->palette_current] = val;
+case DAFB_LUT ... DAFB_LUT + 3:
+s->color_palette[s->palette_current] = val & 0xff;
 s->palette_current = (s->palette_current + 1) %
  ARRAY_SIZE(s->color_palette);
 if (s->palette_current % 3) {
-- 
2.41.0




[PULL 0/4] Q800 for 8.2 patches

2023-11-06 Thread Laurent Vivier
The following changes since commit d762bf97931b58839316b68a570eecc6143c9e3e:

  Merge tag 'pull-target-arm-20231102' of 
https://git.linaro.org/people/pmaydell/qemu-arm into staging (2023-11-03 
10:04:12 +0800)

are available in the Git repository at:

  https://github.com/vivier/qemu-m68k.git tags/q800-for-8.2-pull-request

for you to fetch changes up to 95f3943210416e054751bc230d4cec7d87995525:

  macfb: allow reads from the DAFB_LUT register (2023-11-05 15:48:36 +0100)


Q800 pull request 20231106

macfb: A/UX fixes for colour LUT



Mark Cave-Ayland (4):
  macfb: don't clear interrupts when writing to DAFB_RESET
  macfb: rename DAFB_RESET to DAFB_LUT_INDEX
  macfb: allow larger write accesses to the DAFB_LUT register
  macfb: allow reads from the DAFB_LUT register

 hw/display/macfb.c | 19 +++
 1 file changed, 11 insertions(+), 8 deletions(-)

-- 
2.41.0




[PULL 1/4] macfb: don't clear interrupts when writing to DAFB_RESET

2023-11-06 Thread Laurent Vivier
From: Mark Cave-Ayland 

Traces from A/UX suggest that this register is only used to reset the 
framebuffer
LUT (colour lookup table) and not any other device state.

Signed-off-by: Mark Cave-Ayland 
Reviewed-by: Laurent Vivier 
Message-ID: <20231026085650.917663-2-mark.cave-ayl...@ilande.co.uk>
Signed-off-by: Laurent Vivier 
---
 hw/display/macfb.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/hw/display/macfb.c b/hw/display/macfb.c
index 2f8e01656640..28db2e9f246a 100644
--- a/hw/display/macfb.c
+++ b/hw/display/macfb.c
@@ -585,8 +585,6 @@ static void macfb_ctrl_write(void *opaque,
 break;
 case DAFB_RESET:
 s->palette_current = 0;
-s->regs[DAFB_INTR_STAT >> 2] &= ~DAFB_INTR_VBL;
-macfb_update_irq(s);
 break;
 case DAFB_LUT:
 s->color_palette[s->palette_current] = val;
-- 
2.41.0




Re: [PATCH 4/4] macfb: allow reads from the DAFB_LUT register

2023-11-05 Thread Laurent Vivier

Le 26/10/2023 à 10:56, Mark Cave-Ayland a écrit :

This enables A/UX to correctly retrieve the LUT entries when used with
applications that use the MacOS Device Manager Status (GetEntries) call.

Signed-off-by: Mark Cave-Ayland 
---
  hw/display/macfb.c | 5 +
  1 file changed, 5 insertions(+)

diff --git a/hw/display/macfb.c b/hw/display/macfb.c
index 4a1c75d572..d61541ccb5 100644
--- a/hw/display/macfb.c
+++ b/hw/display/macfb.c
@@ -537,6 +537,11 @@ static uint64_t macfb_ctrl_read(void *opaque,
  case DAFB_MODE_SENSE:
  val = macfb_sense_read(s);
  break;
+case DAFB_LUT ... DAFB_LUT + 3:
+val = s->color_palette[s->palette_current];
+s->palette_current = (s->palette_current + 1) %
+ ARRAY_SIZE(s->color_palette);
+break;
  default:
  if (addr < MACFB_CTRL_TOPADDR) {
  val = s->regs[addr >> 2];


Reviewed-by: Laurent Vivier 



Re: [PATCH 2/4] macfb: rename DAFB_RESET to DAFB_LUT_INDEX

2023-11-05 Thread Laurent Vivier

Le 26/10/2023 à 10:56, Mark Cave-Ayland a écrit :

When A/UX uses the MacOS Device Manager Status (GetEntries) call to read the
contents of the CLUT, it is easy to see that the requested index is written to
the DAFB_RESET register. Update the palette_current index with the requested
value, and rename it to DAFB_LUT_INDEX to reflect its true purpose.

Signed-off-by: Mark Cave-Ayland 
---
  hw/display/macfb.c | 6 +++---
  1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/hw/display/macfb.c b/hw/display/macfb.c
index 28db2e9f24..eb4ce6b824 100644
--- a/hw/display/macfb.c
+++ b/hw/display/macfb.c
@@ -36,7 +36,7 @@
  #define DAFB_INTR_MASK  0x104
  #define DAFB_INTR_STAT  0x108
  #define DAFB_INTR_CLEAR 0x10c
-#define DAFB_RESET  0x200
+#define DAFB_LUT_INDEX  0x200
  #define DAFB_LUT0x213
  
  #define DAFB_INTR_VBL   0x4

@@ -583,8 +583,8 @@ static void macfb_ctrl_write(void *opaque,
  s->regs[DAFB_INTR_STAT >> 2] &= ~DAFB_INTR_VBL;
  macfb_update_irq(s);
  break;
-case DAFB_RESET:
-s->palette_current = 0;
+case DAFB_LUT_INDEX:
+s->palette_current = (val & 0xff) * 3;
  break;
  case DAFB_LUT:
  s->color_palette[s->palette_current] = val;


Reviewed-by: Laurent Vivier 



Re: [PATCH 3/4] macfb: allow larger write accesses to the DAFB_LUT register

2023-11-05 Thread Laurent Vivier

Le 26/10/2023 à 10:56, Mark Cave-Ayland a écrit :

The original tests with MacOS showed that only the bottom 8 bits of the DAFB_LUT
register were used when writing to the LUT, however A/UX performs some of its
writes using 4 byte accesses. Expand the address range for the DAFB_LUT register
so that different size accesses write the correct value to the color_palette
array.

Signed-off-by: Mark Cave-Ayland 
---
  hw/display/macfb.c | 6 +++---
  1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/hw/display/macfb.c b/hw/display/macfb.c
index eb4ce6b824..4a1c75d572 100644
--- a/hw/display/macfb.c
+++ b/hw/display/macfb.c
@@ -37,7 +37,7 @@
  #define DAFB_INTR_STAT  0x108
  #define DAFB_INTR_CLEAR 0x10c
  #define DAFB_LUT_INDEX  0x200
-#define DAFB_LUT0x213
+#define DAFB_LUT0x210
  
  #define DAFB_INTR_VBL   0x4
  
@@ -586,8 +586,8 @@ static void macfb_ctrl_write(void *opaque,

  case DAFB_LUT_INDEX:
  s->palette_current = (val & 0xff) * 3;
  break;
-case DAFB_LUT:
-s->color_palette[s->palette_current] = val;
+case DAFB_LUT ... DAFB_LUT + 3:
+s->color_palette[s->palette_current] = val & 0xff;
  s->palette_current = (s->palette_current + 1) %
   ARRAY_SIZE(s->color_palette);
  if (s->palette_current % 3) {


Reviewed-by: Laurent Vivier 



Re: [PATCH 1/4] macfb: don't clear interrupts when writing to DAFB_RESET

2023-11-05 Thread Laurent Vivier

Le 26/10/2023 à 10:56, Mark Cave-Ayland a écrit :

Traces from A/UX suggest that this register is only used to reset the 
framebuffer
LUT (colour lookup table) and not any other device state.

Signed-off-by: Mark Cave-Ayland 
---
  hw/display/macfb.c | 2 --
  1 file changed, 2 deletions(-)

diff --git a/hw/display/macfb.c b/hw/display/macfb.c
index 2f8e016566..28db2e9f24 100644
--- a/hw/display/macfb.c
+++ b/hw/display/macfb.c
@@ -585,8 +585,6 @@ static void macfb_ctrl_write(void *opaque,
  break;
  case DAFB_RESET:
  s->palette_current = 0;
-s->regs[DAFB_INTR_STAT >> 2] &= ~DAFB_INTR_VBL;
-macfb_update_irq(s);
  break;
  case DAFB_LUT:
  s->color_palette[s->palette_current] = val;


Reviewed-by: Laurent Vivier 



[PULL 14/20] mac_via: work around underflow in TimeDBRA timing loop in SETUPTIMEK

2023-10-08 Thread Laurent Vivier
From: Mark Cave-Ayland 

The MacOS toolbox ROM calculates the number of branches that can be executed
per millisecond as part of its timer calibration. Since modern hosts are
considerably quicker than original hardware, the negative counter reaches zero
before the calibration completes leading to division by zero later in
CALCULATESLOD.

Instead of trying to fudge the timing loop (which won't work for 
TimeDBRA/TimeSCCDB
anyhow), use the pattern of access to the VIA1 registers to detect when 
SETUPTIMEK
has finished executing and write some well-known good timer values to TimeDBRA
and TimeSCCDB taken from real hardware with a suitable scaling factor.

Signed-off-by: Mark Cave-Ayland 
Reviewed-by: Laurent Vivier 
Message-ID: <20231004083806.757242-15-mark.cave-ayl...@ilande.co.uk>
Signed-off-by: Laurent Vivier 
---
 include/hw/misc/mac_via.h |   3 +
 hw/misc/mac_via.c | 115 ++
 hw/misc/trace-events  |   1 +
 3 files changed, 119 insertions(+)

diff --git a/include/hw/misc/mac_via.h b/include/hw/misc/mac_via.h
index 422da43bf90a..63cdcf7c69c9 100644
--- a/include/hw/misc/mac_via.h
+++ b/include/hw/misc/mac_via.h
@@ -74,6 +74,9 @@ struct MOS6522Q800VIA1State {
 int64_t next_second;
 QEMUTimer *sixty_hz_timer;
 int64_t next_sixty_hz;
+
+/* SETUPTIMEK hack */
+int timer_hack_state;
 };
 
 
diff --git a/hw/misc/mac_via.c b/hw/misc/mac_via.c
index e87a1b82d8c5..f2ccb12d643b 100644
--- a/hw/misc/mac_via.c
+++ b/hw/misc/mac_via.c
@@ -16,6 +16,7 @@
  */
 
 #include "qemu/osdep.h"
+#include "exec/address-spaces.h"
 #include "migration/vmstate.h"
 #include "hw/sysbus.h"
 #include "hw/irq.h"
@@ -871,6 +872,112 @@ static void via1_auxmode_update(MOS6522Q800VIA1State *v1s)
 }
 }
 
+/*
+ * Addresses and real values for TimeDBRA/TimeSCCB to allow timer calibration
+ * to succeed (NOTE: both values have been multiplied by 3 to cope with the
+ * speed of QEMU execution on a modern host
+ */
+#define MACOS_TIMEDBRA0xd00
+#define MACOS_TIMESCCB0xd02
+
+#define MACOS_TIMEDBRA_VALUE  (0x2a00 * 3)
+#define MACOS_TIMESCCB_VALUE  (0x079d * 3)
+
+static bool via1_is_toolbox_timer_calibrated(void)
+{
+/*
+ * Indicate whether the MacOS toolbox has been calibrated by checking
+ * for the value of our magic constants
+ */
+uint16_t timedbra = lduw_be_phys(_space_memory, MACOS_TIMEDBRA);
+uint16_t timesccdb = lduw_be_phys(_space_memory, MACOS_TIMESCCB);
+
+return (timedbra == MACOS_TIMEDBRA_VALUE &&
+timesccdb == MACOS_TIMESCCB_VALUE);
+}
+
+static void via1_timer_calibration_hack(MOS6522Q800VIA1State *v1s, int addr,
+uint64_t val, int size)
+{
+/*
+ * Work around timer calibration to ensure we that we have non-zero and
+ * known good values for TIMEDRBA and TIMESCCDB.
+ *
+ * This works by attempting to detect the reset and calibration sequence
+ * of writes to VIA1
+ */
+int old_timer_hack_state = v1s->timer_hack_state;
+
+switch (v1s->timer_hack_state) {
+case 0:
+if (addr == VIA_REG_PCR && val == 0x22) {
+/* VIA_REG_PCR: configure VIA1 edge triggering */
+v1s->timer_hack_state = 1;
+}
+break;
+case 1:
+if (addr == VIA_REG_T2CL && val == 0xc) {
+/* VIA_REG_T2CL: low byte of 1ms counter */
+if (!via1_is_toolbox_timer_calibrated()) {
+v1s->timer_hack_state = 2;
+} else {
+v1s->timer_hack_state = 0;
+}
+}
+break;
+case 2:
+if (addr == VIA_REG_T2CH && val == 0x3) {
+/*
+ * VIA_REG_T2CH: high byte of 1ms counter (very likely at the
+ * start of SETUPTIMEK)
+ */
+if (!via1_is_toolbox_timer_calibrated()) {
+v1s->timer_hack_state = 3;
+} else {
+v1s->timer_hack_state = 0;
+}
+}
+break;
+case 3:
+if (addr == VIA_REG_IER && val == 0x20) {
+/*
+ * VIA_REG_IER: update at end of SETUPTIMEK
+ *
+ * Timer calibration has finished: unfortunately the values in
+ * TIMEDBRA (0xd00) and TIMESCCDB (0xd02) are so far out they
+ * cause divide by zero errors.
+ *
+ * Update them with values obtained from a real Q800 but with
+ * a x3 scaling factor which seems to work well
+ */
+stw_be_phys(_space_memory, MACOS_TIMEDBRA,
+MACOS_TIMEDBRA_VALUE);
+stw_be_phys(_space_memory, MACOS_TIMESCCB,
+MACOS_TIMESCCB_VALUE);
+
+v1s->timer_hack_state = 4;
+}
+break;
+case 4:
+/*
+ * This is th

[PULL 15/20] mac_via: workaround NetBSD ADB bus enumeration issue

2023-10-08 Thread Laurent Vivier
From: Mark Cave-Ayland 

NetBSD assumes it can send its first ADB command after sending the ADB_BUSRESET
command in ADB_STATE_NEW without changing the state back to ADB_STATE_IDLE
first as detailed in the ADB protocol.

Add a workaround to detect this condition at the start of ADB enumeration
and send the next command written to SR after a ADB_BUSRESET onto the bus
regardless, even if we don't detect a state transition to ADB_STATE_NEW.

Signed-off-by: Mark Cave-Ayland 
Reviewed-by: Laurent Vivier 
Message-ID: <20231004083806.757242-16-mark.cave-ayl...@ilande.co.uk>
Signed-off-by: Laurent Vivier 
---
 hw/misc/mac_via.c| 34 ++
 hw/misc/trace-events |  1 +
 2 files changed, 35 insertions(+)

diff --git a/hw/misc/mac_via.c b/hw/misc/mac_via.c
index f2ccb12d643b..9f9c2815d0e9 100644
--- a/hw/misc/mac_via.c
+++ b/hw/misc/mac_via.c
@@ -1001,6 +1001,8 @@ static void mos6522_q800_via1_write(void *opaque, hwaddr 
addr, uint64_t val,
 {
 MOS6522Q800VIA1State *v1s = MOS6522_Q800_VIA1(opaque);
 MOS6522State *ms = MOS6522(v1s);
+int oldstate, state;
+int oldsr = ms->sr;
 
 addr = (addr >> 9) & 0xf;
 
@@ -1016,6 +1018,38 @@ static void mos6522_q800_via1_write(void *opaque, hwaddr 
addr, uint64_t val,
 
 v1s->last_b = ms->b;
 break;
+
+case VIA_REG_SR:
+{
+/*
+ * NetBSD assumes it can send its first ADB command after sending
+ * the ADB_BUSRESET command in ADB_STATE_NEW without changing the
+ * state back to ADB_STATE_IDLE first as detailed in the ADB
+ * protocol.
+ *
+ * Add a workaround to detect this condition at the start of ADB
+ * enumeration and send the next command written to SR after a
+ * ADB_BUSRESET onto the bus regardless, even if we don't detect a
+ * state transition to ADB_STATE_NEW.
+ *
+ * Note that in my tests the NetBSD state machine takes one ADB
+ * operation to recover which means the probe for an ADB device at
+ * address 1 always fails. However since the first device is at
+ * address 2 then this will work fine, without having to come up
+ * with a more complicated and invasive solution.
+ */
+oldstate = (v1s->last_b & VIA1B_vADB_StateMask) >>
+   VIA1B_vADB_StateShift;
+state = (ms->b & VIA1B_vADB_StateMask) >> VIA1B_vADB_StateShift;
+
+if (oldstate == ADB_STATE_NEW && state == ADB_STATE_NEW &&
+(ms->acr & VIA1ACR_vShiftOut) &&
+oldsr == 0 /* ADB_BUSRESET */) {
+trace_via1_adb_netbsd_enum_hack();
+adb_via_send(v1s, state, ms->sr);
+}
+}
+break;
 }
 }
 
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
index 5a998f5e4e38..24ba7cc4d0e9 100644
--- a/hw/misc/trace-events
+++ b/hw/misc/trace-events
@@ -271,6 +271,7 @@ via1_rtc_cmd_pram_sect_write(int sector, int offset, int 
addr, int value) "secto
 via1_adb_send(const char *state, uint8_t data, const char *vadbint) "state %s 
data=0x%02x vADBInt=%s"
 via1_adb_receive(const char *state, uint8_t data, const char *vadbint, int 
status, int index, int size) "state %s data=0x%02x vADBInt=%s status=0x%x 
index=%d size=%d"
 via1_adb_poll(uint8_t data, const char *vadbint, int status, int index, int 
size) "data=0x%02x vADBInt=%s status=0x%x index=%d size=%d"
+via1_adb_netbsd_enum_hack(void) "using NetBSD enum hack"
 via1_auxmode(int mode) "setting auxmode to %d"
 via1_timer_hack_state(int state) "setting timer_hack_state to %d"
 
-- 
2.41.0




[PULL 07/20] audio: add Apple Sound Chip (ASC) emulation

2023-10-08 Thread Laurent Vivier
From: Mark Cave-Ayland 

The Apple Sound Chip was primarily used by the Macintosh II to generate sound
in hardware which was previously handled by the toolbox ROM with software
interrupts.

Implement both the standard ASC and also the enhanced ASC (EASC) functionality
which is used in the Quadra 800.

Note that whilst real ASC hardware uses AUDIO_FORMAT_S8, this implementation 
uses
AUDIO_FORMAT_U8 instead because AUDIO_FORMAT_S8 is rarely used and not supported
by some audio backends like PulseAudio and DirectSound when played directly with
-audiodev out.mixing-engine=off.

Co-developed-by: Laurent Vivier 
Co-developed-by: Volker Rümelin 
Signed-off-by: Mark Cave-Ayland 
Message-ID: <20231004083806.757242-8-mark.cave-ayl...@ilande.co.uk>
Signed-off-by: Laurent Vivier 
---
 MAINTAINERS|   2 +
 include/hw/audio/asc.h |  84 +
 hw/audio/asc.c | 708 +
 hw/audio/Kconfig   |   3 +
 hw/audio/meson.build   |   1 +
 hw/audio/trace-events  |  10 +
 hw/m68k/Kconfig|   1 +
 7 files changed, 809 insertions(+)
 create mode 100644 include/hw/audio/asc.h
 create mode 100644 hw/audio/asc.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 38fc8e0a22b8..ac865c4e5932 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1231,6 +1231,7 @@ F: hw/display/macfb.c
 F: hw/block/swim.c
 F: hw/misc/djmemc.c
 F: hw/misc/iosb.c
+F: hw/audio/asc.c
 F: hw/m68k/bootinfo.h
 F: include/standard-headers/asm-m68k/bootinfo.h
 F: include/standard-headers/asm-m68k/bootinfo-mac.h
@@ -1242,6 +1243,7 @@ F: include/hw/m68k/q800.h
 F: include/hw/m68k/q800-glue.h
 F: include/hw/misc/djmemc.h
 F: include/hw/misc/iosb.h
+F: include/hw/audio/asc.h
 
 virt
 M: Laurent Vivier 
diff --git a/include/hw/audio/asc.h b/include/hw/audio/asc.h
new file mode 100644
index ..d9412815c324
--- /dev/null
+++ b/include/hw/audio/asc.h
@@ -0,0 +1,84 @@
+/*
+ * QEMU Apple Sound Chip emulation
+ *
+ * Apple Sound Chip (ASC) 344S0063
+ * Enhanced Apple Sound Chip (EASC) 343S1063
+ *
+ * Copyright (c) 2012-2018 Laurent Vivier 
+ * Copyright (c) 2022 Mark Cave-Ayland 
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef HW_AUDIO_ASC_H
+#define HW_AUDIO_ASC_H
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+#include "audio/audio.h"
+
+#define ASC_FREQ 22257
+
+enum {
+ASC_TYPE_ASC= 0,  /* original discrete Apple Sound Chip */
+ASC_TYPE_EASC   = 1   /* discrete Enhanced Apple Sound Chip */
+};
+
+#define ASC_FIFO_OFFSET0x0
+#define ASC_FIFO_SIZE  0x400
+
+#define ASC_REG_OFFSET 0x800
+#define ASC_REG_SIZE   0x60
+
+#define ASC_EXTREG_OFFSET  0xf00
+#define ASC_EXTREG_SIZE0x20
+
+typedef struct ASCFIFOState {
+int index;
+
+MemoryRegion mem_fifo;
+uint8_t fifo[ASC_FIFO_SIZE];
+uint8_t int_status;
+
+int cnt;
+int wptr;
+int rptr;
+
+MemoryRegion mem_extregs;
+uint8_t extregs[ASC_EXTREG_SIZE];
+
+int xa_cnt;
+uint8_t xa_val;
+uint8_t xa_flags;
+int16_t xa_last[2];
+} ASCFIFOState;
+
+struct ASCState {
+SysBusDevice parent_obj;
+
+uint8_t type;
+MemoryRegion asc;
+MemoryRegion mem_fifo;
+MemoryRegion mem_regs;
+MemoryRegion mem_extregs;
+
+QEMUSoundCard card;
+SWVoiceOut *voice;
+uint8_t *mixbuf;
+int samples;
+int shift;
+
+/* Time when we were last able to generate samples */
+int64_t fifo_empty_ns;
+
+qemu_irq irq;
+
+ASCFIFOState fifos[2];
+
+uint8_t regs[ASC_REG_SIZE];
+};
+
+#define TYPE_ASC "apple-sound-chip"
+OBJECT_DECLARE_SIMPLE_TYPE(ASCState, ASC)
+
+#endif
diff --git a/hw/audio/asc.c b/hw/audio/asc.c
new file mode 100644
index ..9084708eafab
--- /dev/null
+++ b/hw/audio/asc.c
@@ -0,0 +1,708 @@
+/*
+ * QEMU Apple Sound Chip emulation
+ *
+ * Apple Sound Chip (ASC) 344S0063
+ * Enhanced Apple Sound Chip (EASC) 343S1063
+ *
+ * Copyright (c) 2012-2018 Laurent Vivier 
+ * Copyright (c) 2022 Mark Cave-Ayland 
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/timer.h"
+#include "hw/sysbus.h"
+#include "hw/irq.h"
+#include "audio/audio.h"
+#include "hw/audio/asc.h"
+#include "hw/qdev-properties.h"
+#include "migration/vmstate.h"
+#include "trace.h"
+
+/*
+ * Linux doesn't provide information about ASC, see arch/m68k/mac/macboing.c
+ * and arch/m68k/include/asm/mac_asc.h
+ *
+ * best information is coming from MAME:
+ *   https://github.com/mamedev/mame/blob/master/src/devices/sound/asc.h
+ *   https://github.com/mamedev/mame/blob/master/src/devices/sound/asc.cpp
+ *   Emulation by R. Belmont
+ * or MESS:
+ *   http://mess.redump.net/mess/driver_info/easc
+ *
+ * 0x800: VERSION
+ * 0x801: MODE
+ *1=FIFO mode,
+ *2=wavetable mode
+ * 0x802: CONTROL
+ *bit 0=analog or PWM output,
+ *1=s

[PULL 10/20] q800: add easc bool machine class property to switch between ASC and EASC

2023-10-08 Thread Laurent Vivier
From: Mark Cave-Ayland 

This determines whether the Apple Sound Chip (ASC) is set to enhanced mode
(default) or to original mode. The real Q800 hardware used an EASC chip however
a lot of older software only works with the older ASC chip.

Adding this as a machine parameter allows QEMU to be used as an developer aid
for testing and migrating code from ASC to EASC.

Signed-off-by: Mark Cave-Ayland 
Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Laurent Vivier 
Message-ID: <20231004083806.757242-11-mark.cave-ayl...@ilande.co.uk>
Signed-off-by: Laurent Vivier 
---
 include/hw/m68k/q800.h |  1 +
 hw/m68k/q800.c | 30 +-
 2 files changed, 30 insertions(+), 1 deletion(-)

diff --git a/include/hw/m68k/q800.h b/include/hw/m68k/q800.h
index 790cf433f38d..fbaacd88bd57 100644
--- a/include/hw/m68k/q800.h
+++ b/include/hw/m68k/q800.h
@@ -47,6 +47,7 @@
 struct Q800MachineState {
 MachineState parent_obj;
 
+bool easc;
 M68kCPU cpu;
 MemoryRegion rom;
 GLUEState glue;
diff --git a/hw/m68k/q800.c b/hw/m68k/q800.c
index 249fedde7a92..ac3115d32844 100644
--- a/hw/m68k/q800.c
+++ b/hw/m68k/q800.c
@@ -484,7 +484,8 @@ static void q800_machine_init(MachineState *machine)
 /* Apple Sound Chip */
 
 object_initialize_child(OBJECT(machine), "asc", >asc, TYPE_ASC);
-qdev_prop_set_uint8(DEVICE(>asc), "asctype", ASC_TYPE_EASC);
+qdev_prop_set_uint8(DEVICE(>asc), "asctype", m->easc ? ASC_TYPE_EASC
+: ASC_TYPE_ASC);
 if (machine->audiodev) {
 qdev_prop_set_string(DEVICE(>asc), "audiodev", machine->audiodev);
 }
@@ -677,6 +678,28 @@ static void q800_machine_init(MachineState *machine)
 }
 }
 
+static bool q800_get_easc(Object *obj, Error **errp)
+{
+Q800MachineState *ms = Q800_MACHINE(obj);
+
+return ms->easc;
+}
+
+static void q800_set_easc(Object *obj, bool value, Error **errp)
+{
+Q800MachineState *ms = Q800_MACHINE(obj);
+
+ms->easc = value;
+}
+
+static void q800_init(Object *obj)
+{
+Q800MachineState *ms = Q800_MACHINE(obj);
+
+/* Default to EASC */
+ms->easc = true;
+}
+
 static GlobalProperty hw_compat_q800[] = {
 { "scsi-hd", "quirk_mode_page_vendor_specific_apple", "on" },
 { "scsi-hd", "vendor", " SEAGATE" },
@@ -710,11 +733,16 @@ static void q800_machine_class_init(ObjectClass *oc, void 
*data)
 mc->default_ram_id = "m68k_mac.ram";
 machine_add_audiodev_property(mc);
 compat_props_add(mc->compat_props, hw_compat_q800, hw_compat_q800_len);
+
+object_class_property_add_bool(oc, "easc", q800_get_easc, q800_set_easc);
+object_class_property_set_description(oc, "easc",
+"Set to off to use ASC rather than EASC");
 }
 
 static const TypeInfo q800_machine_typeinfo = {
 .name   = MACHINE_TYPE_NAME("q800"),
 .parent = TYPE_MACHINE,
+.instance_init = q800_init,
 .instance_size = sizeof(Q800MachineState),
 .class_init = q800_machine_class_init,
 };
-- 
2.41.0




[PULL 03/20] q800: add machine id register

2023-10-08 Thread Laurent Vivier
From: Mark Cave-Ayland 

MacOS reads this address to identify the hardware.

This is a basic implementation returning the ID of Quadra 800.

Details:

  http://mess.redump.net/mess/driver_info/mac_technical_notes

"There are 3 ID schemes [...]
 The third and most scalable is a machine ID register at 0x5ffc.
 The top word must be 0xa55a to be valid. Then bits 15-11 are 0 for
 consumer Macs, 1 for portables, 2 for high-end 68k, and 3 for high-end
 PowerPC. Bit 10 is 1 if additional ID bits appear elsewhere (e.g. in VIA1).
 The rest of the bits are a per-model identifier.

 Model  Lower 16 bits of ID
...
 Quadra/Centris 610/650/800 0x2BAD"

Co-developed-by: Laurent Vivier 
Signed-off-by: Mark Cave-Ayland 
Reviewed-by: Philippe Mathieu-Daudé 
Message-ID: <20231004083806.757242-4-mark.cave-ayl...@ilande.co.uk>
Signed-off-by: Laurent Vivier 
---
 include/hw/m68k/q800.h |  1 +
 hw/m68k/q800.c | 29 +
 2 files changed, 30 insertions(+)

diff --git a/include/hw/m68k/q800.h b/include/hw/m68k/q800.h
index f6ae4c1c4fd5..dd7d7a6f2c48 100644
--- a/include/hw/m68k/q800.h
+++ b/include/hw/m68k/q800.h
@@ -60,6 +60,7 @@ struct Q800MachineState {
 DJMEMCState djmemc;
 MemoryRegion macio;
 MemoryRegion macio_alias;
+MemoryRegion machine_id;
 };
 
 #define TYPE_Q800_MACHINE MACHINE_TYPE_NAME("q800")
diff --git a/hw/m68k/q800.c b/hw/m68k/q800.c
index f9ecc1fbb094..ac8509ba6f7e 100644
--- a/hw/m68k/q800.c
+++ b/hw/m68k/q800.c
@@ -91,6 +91,9 @@
 #define Q800_NUBUS_SLOTS_AVAILABLE(BIT(0x9) | BIT(0xc) | BIT(0xd) | \
BIT(0xe))
 
+/* Quadra 800 machine ID */
+#define Q800_MACHINE_ID0xa55a2bad
+
 
 static void main_cpu_reset(void *opaque)
 {
@@ -192,6 +195,27 @@ static const MemoryRegionOps macio_alias_ops = {
 },
 };
 
+static uint64_t machine_id_read(void *opaque, hwaddr addr, unsigned size)
+{
+return Q800_MACHINE_ID;
+}
+
+static void machine_id_write(void *opaque, hwaddr addr, uint64_t val,
+ unsigned size)
+{
+return;
+}
+
+static const MemoryRegionOps machine_id_ops = {
+.read = machine_id_read,
+.write = machine_id_write,
+.endianness = DEVICE_BIG_ENDIAN,
+.valid = {
+.min_access_size = 4,
+.max_access_size = 4,
+},
+};
+
 static void q800_machine_init(MachineState *machine)
 {
 Q800MachineState *m = Q800_MACHINE(machine);
@@ -253,6 +277,11 @@ static void q800_machine_init(MachineState *machine)
 memory_region_add_subregion(get_system_memory(), IO_BASE + IO_SLICE,
 >macio_alias);
 
+memory_region_init_io(>machine_id, NULL, _id_ops, NULL,
+  "Machine ID", 4);
+memory_region_add_subregion(get_system_memory(), 0x5ffc,
+>machine_id);
+
 /* IRQ Glue */
 object_initialize_child(OBJECT(machine), "glue", >glue, TYPE_GLUE);
 object_property_set_link(OBJECT(>glue), "cpu", OBJECT(>cpu),
-- 
2.41.0




[PULL 16/20] mac_via: implement ADB_STATE_IDLE state if shift register in input mode

2023-10-08 Thread Laurent Vivier
From: Mark Cave-Ayland 

NetBSD switches directly to IDLE state without switching the shift register to
input mode. Duplicate the existing ADB_STATE_IDLE logic in input mode from when
the shift register is in output mode which allows the ADB autopoll handler to
handle the response.

Signed-off-by: Mark Cave-Ayland 
Reviewed-by: Laurent Vivier 
Message-ID: <20231004083806.757242-17-mark.cave-ayl...@ilande.co.uk>
Signed-off-by: Laurent Vivier 
---
 hw/misc/mac_via.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/hw/misc/mac_via.c b/hw/misc/mac_via.c
index 9f9c2815d0e9..3c41d6263d45 100644
--- a/hw/misc/mac_via.c
+++ b/hw/misc/mac_via.c
@@ -702,6 +702,12 @@ static void adb_via_send(MOS6522Q800VIA1State *v1s, int 
state, uint8_t data)
 break;
 
 case ADB_STATE_IDLE:
+ms->b |= VIA1B_vADBInt;
+adb_autopoll_unblock(adb_bus);
+
+trace_via1_adb_send("IDLE", data,
+(ms->b & VIA1B_vADBInt) ? "+" : "-");
+
 return;
 }
 
-- 
2.41.0




[PULL 01/20] q800-glue.c: convert to Resettable interface

2023-10-08 Thread Laurent Vivier
From: Mark Cave-Ayland 

Convert the GLUE device to 3-phase reset. The legacy method
doesn't do anything that's invalid in the hold phase, so the
conversion is simple and not a behaviour change.

Signed-off-by: Mark Cave-Ayland 
Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Laurent Vivier 
Message-ID: <20231004083806.757242-2-mark.cave-ayl...@ilande.co.uk>
Signed-off-by: Laurent Vivier 
---
 hw/m68k/q800-glue.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/hw/m68k/q800-glue.c b/hw/m68k/q800-glue.c
index 34c4f0e9876d..710a5c331ec9 100644
--- a/hw/m68k/q800-glue.c
+++ b/hw/m68k/q800-glue.c
@@ -166,9 +166,9 @@ static void glue_nmi_release(void *opaque)
 GLUE_set_irq(s, GLUE_IRQ_IN_NMI, 0);
 }
 
-static void glue_reset(DeviceState *dev)
+static void glue_reset_hold(Object *obj)
 {
-GLUEState *s = GLUE(dev);
+GLUEState *s = GLUE(obj);
 
 s->ipr = 0;
 s->auxmode = 0;
@@ -223,11 +223,12 @@ static void glue_init(Object *obj)
 static void glue_class_init(ObjectClass *klass, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(klass);
+ResettableClass *rc = RESETTABLE_CLASS(klass);
 NMIClass *nc = NMI_CLASS(klass);
 
 dc->vmsd = _glue;
-dc->reset = glue_reset;
 device_class_set_props(dc, glue_properties);
+rc->phases.hold = glue_reset_hold;
 nc->nmi_monitor_handler = glue_nmi;
 }
 
-- 
2.41.0




[PULL 12/20] swim: split into separate IWM and ISM register blocks

2023-10-08 Thread Laurent Vivier
From: Mark Cave-Ayland 

The swim chip provides an implementation of both Apple's IWM and ISM floppy disk
controllers. Split the existing implementation into separate register banks for
each controller, whilst also switching the IWM registers from 16-bit to 8-bit
as implemented in real hardware.

Signed-off-by: Mark Cave-Ayland 
Reviewed-by: Laurent Vivier 
Message-ID: <20231004083806.757242-13-mark.cave-ayl...@ilande.co.uk>
Signed-off-by: Laurent Vivier 
---
 include/hw/block/swim.h | 15 +++-
 hw/block/swim.c | 85 -
 hw/block/trace-events   |  4 +-
 3 files changed, 58 insertions(+), 46 deletions(-)

diff --git a/include/hw/block/swim.h b/include/hw/block/swim.h
index 9b3dcb029d3f..1bc7635d0212 100644
--- a/include/hw/block/swim.h
+++ b/include/hw/block/swim.h
@@ -43,23 +43,18 @@ typedef struct FDrive {
 } FDrive;
 
 struct SWIMCtrl {
-MemoryRegion iomem;
+MemoryRegion swim;
+MemoryRegion iwm;
+MemoryRegion ism;
 FDrive drives[SWIM_MAX_FD];
 int mode;
 /* IWM mode */
 int iwm_switch;
-uint16_t regs[8];
-#define IWM_PH0   0
-#define IWM_PH1   1
-#define IWM_PH2   2
-#define IWM_PH3   3
-#define IWM_MTR   4
-#define IWM_DRIVE 5
-#define IWM_Q66
-#define IWM_Q77
+uint8_t iwmregs[16];
 uint8_t iwm_data;
 uint8_t iwm_mode;
 /* SWIM mode */
+uint8_t ismregs[16];
 uint8_t swim_phase;
 uint8_t swim_mode;
 SWIMBus bus;
diff --git a/hw/block/swim.c b/hw/block/swim.c
index 7df36ea139cb..505718bdae3f 100644
--- a/hw/block/swim.c
+++ b/hw/block/swim.c
@@ -126,7 +126,14 @@
 #define SWIM_HEDSEL  0x20
 #define SWIM_MOTON   0x80
 
-static const char *swim_reg_names[] = {
+static const char *iwm_reg_names[] = {
+"PH0L", "PH0H", "PH1L", "PH1H",
+"PH2L", "PH2H", "PH3L", "PH3H",
+"MTROFF", "MTRON", "INTDRIVE", "EXTDRIVE",
+"Q6L", "Q6H", "Q7L", "Q7H"
+};
+
+static const char *ism_reg_names[] = {
 "WRITE_DATA", "WRITE_MARK", "WRITE_CRC", "WRITE_PARAMETER",
 "WRITE_PHASE", "WRITE_SETUP", "WRITE_MODE0", "WRITE_MODE1",
 "READ_DATA", "READ_MARK", "READ_ERROR", "READ_PARAMETER",
@@ -274,12 +281,11 @@ static void iwmctrl_write(void *opaque, hwaddr reg, 
uint64_t value,
 
 reg >>= REG_SHIFT;
 
-swimctrl->regs[reg >> 1] = reg & 1;
-trace_swim_iwmctrl_write((reg >> 1), size, (reg & 1));
+swimctrl->iwmregs[reg] = value;
+trace_swim_iwmctrl_write(reg, iwm_reg_names[reg], size, value);
 
-if (swimctrl->regs[IWM_Q6] &&
-swimctrl->regs[IWM_Q7]) {
-if (swimctrl->regs[IWM_MTR]) {
+if (swimctrl->iwmregs[IWM_Q7H]) {
+if (swimctrl->iwmregs[IWM_MTRON]) {
 /* data register */
 swimctrl->iwm_data = value;
 } else {
@@ -307,6 +313,12 @@ static void iwmctrl_write(void *opaque, hwaddr reg, 
uint64_t value,
 swimctrl->mode = SWIM_MODE_SWIM;
 swimctrl->iwm_switch = 0;
 trace_swim_iwm_switch();
+
+/* Switch to ISM registers */
+memory_region_del_subregion(>swim,
+>iwm);
+memory_region_add_subregion(>swim, 0x0,
+>ism);
 }
 break;
 }
@@ -317,28 +329,30 @@ static void iwmctrl_write(void *opaque, hwaddr reg, 
uint64_t value,
 static uint64_t iwmctrl_read(void *opaque, hwaddr reg, unsigned size)
 {
 SWIMCtrl *swimctrl = opaque;
+uint8_t value;
 
 reg >>= REG_SHIFT;
 
-swimctrl->regs[reg >> 1] = reg & 1;
+value = swimctrl->iwmregs[reg];
+trace_swim_iwmctrl_read(reg, iwm_reg_names[reg], size, value);
 
-trace_swim_iwmctrl_read((reg >> 1), size, (reg & 1));
-return 0;
+return value;
 }
 
-static void swimctrl_write(void *opaque, hwaddr reg, uint64_t value,
-   unsigned size)
+static const MemoryRegionOps swimctrl_iwm_ops = {
+.write = iwmctrl_write,
+.read = iwmctrl_read,
+.endianness = DEVICE_BIG_ENDIAN,
+};
+
+static void ismctrl_write(void *opaque, hwaddr reg, uint64_t value,
+  unsigned size)
 {
 SWIMCtrl *swimctrl = opaque;
 
-if (swimctrl->mode == SWIM_MODE_IWM) {
-iwmctrl_write(opaque, reg, value, size);
-return;
-}
-
 reg >>= REG_SHIFT;
 
-trace_swim_swimctrl_write(reg, swim_reg_names[reg], size, value);
+trace_swim_swimctrl_write(reg, ism_reg_names[reg], size, value);
 
 switch (reg) {
 case SWIM_WRITE_PHASE

[PULL 08/20] asc: generate silence if FIFO empty but engine still running

2023-10-08 Thread Laurent Vivier
From: Mark Cave-Ayland 

MacOS (un)helpfully leaves the FIFO engine running even when all the samples 
have
been written to the hardware, and expects the FIFO status flags and IRQ to be
updated continuously.

There is an additional problem in that not all audio backends guarantee an
all-zero output when there is no FIFO data available, in particular the Windows
dsound backend which re-uses its internal circular buffer causing the last 
played
sound to loop indefinitely.

Whilst this is effectively a bug in the Windows dsound backend, work around it
for now using a simple heuristic: if the FIFO remains empty for half a cycle
(~23ms) then continuously fill the generated buffer with empty silence.

Signed-off-by: Mark Cave-Ayland 
Reviewed-by: Laurent Vivier 
Message-ID: <20231004083806.757242-9-mark.cave-ayl...@ilande.co.uk>
Signed-off-by: Laurent Vivier 
---
 include/hw/audio/asc.h |  2 ++
 hw/audio/asc.c | 19 +++
 2 files changed, 21 insertions(+)

diff --git a/include/hw/audio/asc.h b/include/hw/audio/asc.h
index d9412815c324..4741f92c4613 100644
--- a/include/hw/audio/asc.h
+++ b/include/hw/audio/asc.h
@@ -68,6 +68,8 @@ struct ASCState {
 int samples;
 int shift;
 
+uint8_t *silentbuf;
+
 /* Time when we were last able to generate samples */
 int64_t fifo_empty_ns;
 
diff --git a/hw/audio/asc.c b/hw/audio/asc.c
index 9084708eafab..0f36b4ce9b6f 100644
--- a/hw/audio/asc.c
+++ b/hw/audio/asc.c
@@ -341,6 +341,21 @@ static void asc_out_cb(void *opaque, int free_b)
 }
 
 if (!generated) {
+/* Workaround for audio underflow bug on Windows dsound backend */
+int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+int silent_samples = muldiv64(now - s->fifo_empty_ns,
+  NANOSECONDS_PER_SECOND, ASC_FREQ);
+
+if (silent_samples > ASC_FIFO_CYCLE_TIME / 2) {
+/*
+ * No new FIFO data within half a cycle time (~23ms) so fill the
+ * entire available buffer with silence. This prevents an issue
+ * with the Windows dsound backend whereby the sound appears to
+ * loop because the FIFO has run out of data, and the driver
+ * reuses the stale content in its circular audio buffer.
+ */
+AUD_write(s->voice, s->silentbuf, samples << s->shift);
+}
 return;
 }
 
@@ -618,6 +633,7 @@ static void asc_unrealize(DeviceState *dev)
 ASCState *s = ASC(dev);
 
 g_free(s->mixbuf);
+g_free(s->silentbuf);
 
 AUD_remove_card(>card);
 }
@@ -642,6 +658,9 @@ static void asc_realize(DeviceState *dev, Error **errp)
 s->samples = AUD_get_buffer_size_out(s->voice) >> s->shift;
 s->mixbuf = g_malloc0(s->samples << s->shift);
 
+s->silentbuf = g_malloc0(s->samples << s->shift);
+memset(s->silentbuf, 0x80, s->samples << s->shift);
+
 /* Add easc registers if required */
 if (s->type == ASC_TYPE_EASC) {
 memory_region_add_subregion(>asc, ASC_EXTREG_OFFSET,
-- 
2.41.0




[PULL 06/20] q800: allow accesses to RAM area even if less memory is available

2023-10-08 Thread Laurent Vivier
From: Mark Cave-Ayland 

MacOS attempts a series of writes and reads over the entire RAM area in order
to determine the amount of RAM within the machine. Allow accesses to the
entire RAM area ignoring writes and always reading zero for areas where there
is no physical RAM installed to allow MacOS to detect the memory size without
faulting.

Signed-off-by: Mark Cave-Ayland 
Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Laurent Vivier 
Message-ID: <20231004083806.757242-7-mark.cave-ayl...@ilande.co.uk>
Signed-off-by: Laurent Vivier 
---
 include/hw/m68k/q800.h |  1 +
 hw/m68k/q800.c | 30 +-
 2 files changed, 30 insertions(+), 1 deletion(-)

diff --git a/include/hw/m68k/q800.h b/include/hw/m68k/q800.h
index 98097165d954..04e4e0bce35a 100644
--- a/include/hw/m68k/q800.h
+++ b/include/hw/m68k/q800.h
@@ -60,6 +60,7 @@ struct Q800MachineState {
 MacfbNubusState macfb;
 DJMEMCState djmemc;
 IOSBState iosb;
+MemoryRegion ramio;
 MemoryRegion macio;
 MemoryRegion macio_alias;
 MemoryRegion machine_id;
diff --git a/hw/m68k/q800.c b/hw/m68k/q800.c
index 081b95e9cf66..3209309173f3 100644
--- a/hw/m68k/q800.c
+++ b/hw/m68k/q800.c
@@ -86,6 +86,9 @@
 
 #define MAC_CLOCK  3686418
 
+/* Size of whole RAM area */
+#define RAM_SIZE  0x4000
+
 /*
  * Slot 0x9 is reserved for use by the in-built framebuffer whilst only
  * slots 0xc, 0xd and 0xe physically exist on the Quadra 800
@@ -218,6 +221,27 @@ static const MemoryRegionOps machine_id_ops = {
 },
 };
 
+static uint64_t ramio_read(void *opaque, hwaddr addr, unsigned size)
+{
+return 0x0;
+}
+
+static void ramio_write(void *opaque, hwaddr addr, uint64_t val,
+unsigned size)
+{
+return;
+}
+
+static const MemoryRegionOps ramio_ops = {
+.read = ramio_read,
+.write = ramio_write,
+.endianness = DEVICE_BIG_ENDIAN,
+.valid = {
+.min_access_size = 1,
+.max_access_size = 4,
+},
+};
+
 static void q800_machine_init(MachineState *machine)
 {
 Q800MachineState *m = Q800_MACHINE(machine);
@@ -262,7 +286,11 @@ static void q800_machine_init(MachineState *machine)
 qemu_register_reset(main_cpu_reset, >cpu);
 
 /* RAM */
-memory_region_add_subregion(get_system_memory(), 0, machine->ram);
+memory_region_init_io(>ramio, OBJECT(machine), _ops, >ramio,
+  "ram", RAM_SIZE);
+memory_region_add_subregion(get_system_memory(), 0x0, >ramio);
+
+memory_region_add_subregion(>ramio, 0, machine->ram);
 
 /*
  * Create container for all IO devices
-- 
2.41.0




[PULL 05/20] q800: add IOSB subsystem

2023-10-08 Thread Laurent Vivier
From: Mark Cave-Ayland 

It is needed because it defines the BIOSConfig area.

Co-developed-by: Laurent Vivier 
Signed-off-by: Mark Cave-Ayland 
Reviewed-by: BALATON Zoltan 
Message-ID: <20231004083806.757242-6-mark.cave-ayl...@ilande.co.uk>
Signed-off-by: Laurent Vivier 
---
 MAINTAINERS|   2 +
 include/hw/m68k/q800.h |   2 +
 include/hw/misc/iosb.h |  25 
 hw/m68k/q800.c |   9 +++
 hw/misc/iosb.c | 133 +
 hw/m68k/Kconfig|   1 +
 hw/misc/Kconfig|   3 +
 hw/misc/meson.build|   1 +
 hw/misc/trace-events   |   4 ++
 9 files changed, 180 insertions(+)
 create mode 100644 include/hw/misc/iosb.h
 create mode 100644 hw/misc/iosb.c

diff --git a/MAINTAINERS b/MAINTAINERS
index dead0d4a47e3..38fc8e0a22b8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1230,6 +1230,7 @@ F: hw/nubus/*
 F: hw/display/macfb.c
 F: hw/block/swim.c
 F: hw/misc/djmemc.c
+F: hw/misc/iosb.c
 F: hw/m68k/bootinfo.h
 F: include/standard-headers/asm-m68k/bootinfo.h
 F: include/standard-headers/asm-m68k/bootinfo-mac.h
@@ -1240,6 +1241,7 @@ F: include/hw/block/swim.h
 F: include/hw/m68k/q800.h
 F: include/hw/m68k/q800-glue.h
 F: include/hw/misc/djmemc.h
+F: include/hw/misc/iosb.h
 
 virt
 M: Laurent Vivier 
diff --git a/include/hw/m68k/q800.h b/include/hw/m68k/q800.h
index dd7d7a6f2c48..98097165d954 100644
--- a/include/hw/m68k/q800.h
+++ b/include/hw/m68k/q800.h
@@ -37,6 +37,7 @@
 #include "hw/nubus/mac-nubus-bridge.h"
 #include "hw/display/macfb.h"
 #include "hw/misc/djmemc.h"
+#include "hw/misc/iosb.h"
 
 /*
  * The main Q800 machine
@@ -58,6 +59,7 @@ struct Q800MachineState {
 MacNubusBridge mac_nubus_bridge;
 MacfbNubusState macfb;
 DJMEMCState djmemc;
+IOSBState iosb;
 MemoryRegion macio;
 MemoryRegion macio_alias;
 MemoryRegion machine_id;
diff --git a/include/hw/misc/iosb.h b/include/hw/misc/iosb.h
new file mode 100644
index ..377f8ca7e2fa
--- /dev/null
+++ b/include/hw/misc/iosb.h
@@ -0,0 +1,25 @@
+/*
+ * QEMU IOSB emulation
+ *
+ * Copyright (c) 2019 Laurent Vivier
+ * Copyright (c) 2022 Mark Cave-Ayland
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef HW_MEM_IOSB_H
+#define HW_MEM_IOSB_H
+
+#define IOSB_REGS 7
+
+struct IOSBState {
+SysBusDevice parent_obj;
+
+MemoryRegion mem_regs;
+uint32_t regs[IOSB_REGS];
+};
+
+#define TYPE_IOSB "IOSB"
+OBJECT_DECLARE_SIMPLE_TYPE(IOSBState, IOSB);
+
+#endif
diff --git a/hw/m68k/q800.c b/hw/m68k/q800.c
index ac8509ba6f7e..081b95e9cf66 100644
--- a/hw/m68k/q800.c
+++ b/hw/m68k/q800.c
@@ -41,6 +41,7 @@
 #include "hw/m68k/q800-glue.h"
 #include "hw/misc/mac_via.h"
 #include "hw/misc/djmemc.h"
+#include "hw/misc/iosb.h"
 #include "hw/input/adb.h"
 #include "hw/nubus/mac-nubus-bridge.h"
 #include "hw/display/macfb.h"
@@ -71,6 +72,7 @@
 #define ESP_BASE  (IO_BASE + 0x1)
 #define ESP_PDMA  (IO_BASE + 0x10100)
 #define ASC_BASE  (IO_BASE + 0x14000)
+#define IOSB_BASE (IO_BASE + 0x18000)
 #define SWIM_BASE (IO_BASE + 0x1E000)
 
 #define SONIC_PROM_SIZE   0x1000
@@ -296,6 +298,13 @@ static void q800_machine_init(MachineState *machine)
 memory_region_add_subregion(>macio, DJMEMC_BASE - IO_BASE,
 sysbus_mmio_get_region(sysbus, 0));
 
+/* IOSB subsystem */
+object_initialize_child(OBJECT(machine), "iosb", >iosb, TYPE_IOSB);
+sysbus = SYS_BUS_DEVICE(>iosb);
+sysbus_realize_and_unref(sysbus, _fatal);
+memory_region_add_subregion(>macio, IOSB_BASE - IO_BASE,
+sysbus_mmio_get_region(sysbus, 0));
+
 /* VIA 1 */
 object_initialize_child(OBJECT(machine), "via1", >via1,
 TYPE_MOS6522_Q800_VIA1);
diff --git a/hw/misc/iosb.c b/hw/misc/iosb.c
new file mode 100644
index ..e7e9dcca476c
--- /dev/null
+++ b/hw/misc/iosb.c
@@ -0,0 +1,133 @@
+/*
+ * QEMU IOSB emulation
+ *
+ * Copyright (c) 2019 Laurent Vivier
+ * Copyright (c) 2022 Mark Cave-Ayland
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "migration/vmstate.h"
+#include "hw/sysbus.h"
+#include "hw/misc/iosb.h"
+#include "trace.h"
+
+#define IOSB_SIZE  0x2000
+
+#define IOSB_CONFIG0x0
+#define IOSB_CONFIG2   0x100
+#define IOSB_SONIC_SCSI0x200
+#define IOSB_REVISION  0x300
+#define IOSB_SCSI_RESID0x400
+#define IOSB_BRIGHTNESS0x500
+#define IOSB_TIMEOUT   0x600
+
+
+static uint64_t iosb_read(void *opaque, hwaddr addr,
+  unsigned size)
+{
+IOSBState *s = IOSB(opaque);
+uint64_t val = 0;
+
+switch (addr) {
+case IOSB_CONFIG:
+case IOSB_CONFI

[PULL 09/20] q800: add Apple Sound Chip (ASC) audio to machine

2023-10-08 Thread Laurent Vivier
From: Mark Cave-Ayland 

The Quadra 800 has the enhanced ASC (EASC) audio chip which supports both the
legacy IRQ routing through VIA2 and also "A/UX" mode routing direct to the
CPU.

Co-developed-by: Laurent Vivier 
Signed-off-by: Mark Cave-Ayland 
Message-ID: <20231004083806.757242-10-mark.cave-ayl...@ilande.co.uk>
Signed-off-by: Laurent Vivier 
---
 include/hw/m68k/q800-glue.h |  4 +++-
 include/hw/m68k/q800.h  |  2 ++
 hw/m68k/q800-glue.c | 11 ++-
 hw/m68k/q800.c  | 21 +
 4 files changed, 36 insertions(+), 2 deletions(-)

diff --git a/include/hw/m68k/q800-glue.h b/include/hw/m68k/q800-glue.h
index a35efc1c534d..ceb916d16c14 100644
--- a/include/hw/m68k/q800-glue.h
+++ b/include/hw/m68k/q800-glue.h
@@ -35,7 +35,7 @@ struct GLUEState {
 M68kCPU *cpu;
 uint8_t ipr;
 uint8_t auxmode;
-qemu_irq irqs[1];
+qemu_irq irqs[2];
 QEMUTimer *nmi_release;
 };
 
@@ -44,7 +44,9 @@ struct GLUEState {
 #define GLUE_IRQ_IN_SONIC  2
 #define GLUE_IRQ_IN_ESCC   3
 #define GLUE_IRQ_IN_NMI4
+#define GLUE_IRQ_IN_ASC5
 
 #define GLUE_IRQ_NUBUS_9   0
+#define GLUE_IRQ_ASC   1
 
 #endif
diff --git a/include/hw/m68k/q800.h b/include/hw/m68k/q800.h
index 04e4e0bce35a..790cf433f38d 100644
--- a/include/hw/m68k/q800.h
+++ b/include/hw/m68k/q800.h
@@ -38,6 +38,7 @@
 #include "hw/display/macfb.h"
 #include "hw/misc/djmemc.h"
 #include "hw/misc/iosb.h"
+#include "hw/audio/asc.h"
 
 /*
  * The main Q800 machine
@@ -60,6 +61,7 @@ struct Q800MachineState {
 MacfbNubusState macfb;
 DJMEMCState djmemc;
 IOSBState iosb;
+ASCState asc;
 MemoryRegion ramio;
 MemoryRegion macio;
 MemoryRegion macio_alias;
diff --git a/hw/m68k/q800-glue.c b/hw/m68k/q800-glue.c
index 710a5c331ec9..f413b1599a2c 100644
--- a/hw/m68k/q800-glue.c
+++ b/hw/m68k/q800-glue.c
@@ -97,6 +97,11 @@ static void GLUE_set_irq(void *opaque, int irq, int level)
 irq = 6;
 break;
 
+case GLUE_IRQ_IN_ASC:
+/* Route to VIA2 instead, negative edge-triggered */
+qemu_set_irq(s->irqs[GLUE_IRQ_ASC], !level);
+return;
+
 default:
 g_assert_not_reached();
 }
@@ -123,6 +128,10 @@ static void GLUE_set_irq(void *opaque, int irq, int level)
 irq = 6;
 break;
 
+case GLUE_IRQ_IN_ASC:
+irq = 4;
+break;
+
 default:
 g_assert_not_reached();
 }
@@ -214,7 +223,7 @@ static void glue_init(Object *obj)
 qdev_init_gpio_in(dev, GLUE_set_irq, 8);
 qdev_init_gpio_in_named(dev, glue_auxmode_set_irq, "auxmode", 1);
 
-qdev_init_gpio_out(dev, s->irqs, 1);
+qdev_init_gpio_out(dev, s->irqs, 2);
 
 /* NMI release timer */
 s->nmi_release = timer_new_ms(QEMU_CLOCK_VIRTUAL, glue_nmi_release, s);
diff --git a/hw/m68k/q800.c b/hw/m68k/q800.c
index 3209309173f3..249fedde7a92 100644
--- a/hw/m68k/q800.c
+++ b/hw/m68k/q800.c
@@ -43,6 +43,7 @@
 #include "hw/misc/djmemc.h"
 #include "hw/misc/iosb.h"
 #include "hw/input/adb.h"
+#include "hw/audio/asc.h"
 #include "hw/nubus/mac-nubus-bridge.h"
 #include "hw/display/macfb.h"
 #include "hw/block/swim.h"
@@ -480,6 +481,25 @@ static void q800_machine_init(MachineState *machine)
 
 scsi_bus_legacy_handle_cmdline(>bus);
 
+/* Apple Sound Chip */
+
+object_initialize_child(OBJECT(machine), "asc", >asc, TYPE_ASC);
+qdev_prop_set_uint8(DEVICE(>asc), "asctype", ASC_TYPE_EASC);
+if (machine->audiodev) {
+qdev_prop_set_string(DEVICE(>asc), "audiodev", machine->audiodev);
+}
+sysbus = SYS_BUS_DEVICE(>asc);
+sysbus_realize_and_unref(sysbus, _fatal);
+memory_region_add_subregion(>macio, ASC_BASE - IO_BASE,
+sysbus_mmio_get_region(sysbus, 0));
+sysbus_connect_irq(sysbus, 0, qdev_get_gpio_in(DEVICE(>glue),
+   GLUE_IRQ_IN_ASC));
+
+/* Wire ASC IRQ via GLUE for use in classic mode */
+qdev_connect_gpio_out(DEVICE(>glue), GLUE_IRQ_ASC,
+  qdev_get_gpio_in(DEVICE(>via2),
+   VIA2_IRQ_ASC_BIT));
+
 /* SWIM floppy controller */
 
 object_initialize_child(OBJECT(machine), "swim", >swim,
@@ -688,6 +708,7 @@ static void q800_machine_class_init(ObjectClass *oc, void 
*data)
 mc->max_cpus = 1;
 mc->block_default_type = IF_SCSI;
 mc->default_ram_id = "m68k_mac.ram";
+machine_add_audiodev_property(mc);
 compat_props_add(mc->compat_props, hw_compat_q800, hw_compat_q800_len);
 }
 
-- 
2.41.0




[PULL 02/20] q800: add djMEMC memory controller

2023-10-08 Thread Laurent Vivier
From: Mark Cave-Ayland 

The djMEMC controller is used to store information related to the physical 
memory
configuration.

Co-developed-by: Laurent Vivier 
Signed-off-by: Mark Cave-Ayland 
Reviewed-by: Philippe Mathieu-Daudé 
Message-ID: <20231004083806.757242-3-mark.cave-ayl...@ilande.co.uk>
Signed-off-by: Laurent Vivier 
---
 MAINTAINERS  |   2 +
 include/hw/m68k/q800.h   |   2 +
 include/hw/misc/djmemc.h |  30 +
 hw/m68k/q800.c   |  10 +++
 hw/misc/djmemc.c | 135 +++
 hw/m68k/Kconfig  |   1 +
 hw/misc/Kconfig  |   3 +
 hw/misc/meson.build  |   1 +
 hw/misc/trace-events |   4 ++
 9 files changed, 188 insertions(+)
 create mode 100644 include/hw/misc/djmemc.h
 create mode 100644 hw/misc/djmemc.c

diff --git a/MAINTAINERS b/MAINTAINERS
index ea91f9e80481..dead0d4a47e3 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1229,6 +1229,7 @@ F: hw/misc/mac_via.c
 F: hw/nubus/*
 F: hw/display/macfb.c
 F: hw/block/swim.c
+F: hw/misc/djmemc.c
 F: hw/m68k/bootinfo.h
 F: include/standard-headers/asm-m68k/bootinfo.h
 F: include/standard-headers/asm-m68k/bootinfo-mac.h
@@ -1238,6 +1239,7 @@ F: include/hw/display/macfb.h
 F: include/hw/block/swim.h
 F: include/hw/m68k/q800.h
 F: include/hw/m68k/q800-glue.h
+F: include/hw/misc/djmemc.h
 
 virt
 M: Laurent Vivier 
diff --git a/include/hw/m68k/q800.h b/include/hw/m68k/q800.h
index b3d77f1cba6e..f6ae4c1c4fd5 100644
--- a/include/hw/m68k/q800.h
+++ b/include/hw/m68k/q800.h
@@ -36,6 +36,7 @@
 #include "hw/block/swim.h"
 #include "hw/nubus/mac-nubus-bridge.h"
 #include "hw/display/macfb.h"
+#include "hw/misc/djmemc.h"
 
 /*
  * The main Q800 machine
@@ -56,6 +57,7 @@ struct Q800MachineState {
 Swim swim;
 MacNubusBridge mac_nubus_bridge;
 MacfbNubusState macfb;
+DJMEMCState djmemc;
 MemoryRegion macio;
 MemoryRegion macio_alias;
 };
diff --git a/include/hw/misc/djmemc.h b/include/hw/misc/djmemc.h
new file mode 100644
index ..82d4e4a2fee2
--- /dev/null
+++ b/include/hw/misc/djmemc.h
@@ -0,0 +1,30 @@
+/*
+ * djMEMC, macintosh memory and interrupt controller
+ * (Quadra 610/650/800 & Centris 610/650)
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef HW_MISC_DJMEMC_H
+#define HW_MISC_DJMEMC_H
+
+#include "hw/sysbus.h"
+
+#define DJMEMC_SIZE0x2000
+#define DJMEMC_NUM_REGS(0x38 / sizeof(uint32_t))
+
+#define DJMEMC_MAXBANKS10
+
+struct DJMEMCState {
+SysBusDevice parent_obj;
+
+MemoryRegion mem_regs;
+
+/* Memory controller */
+uint32_t regs[DJMEMC_NUM_REGS];
+};
+
+#define TYPE_DJMEMC "djMEMC"
+OBJECT_DECLARE_SIMPLE_TYPE(DJMEMCState, DJMEMC);
+
+#endif
diff --git a/hw/m68k/q800.c b/hw/m68k/q800.c
index b770b71d5475..f9ecc1fbb094 100644
--- a/hw/m68k/q800.c
+++ b/hw/m68k/q800.c
@@ -40,6 +40,7 @@
 #include "hw/m68k/q800.h"
 #include "hw/m68k/q800-glue.h"
 #include "hw/misc/mac_via.h"
+#include "hw/misc/djmemc.h"
 #include "hw/input/adb.h"
 #include "hw/nubus/mac-nubus-bridge.h"
 #include "hw/display/macfb.h"
@@ -66,6 +67,7 @@
 #define SONIC_PROM_BASE   (IO_BASE + 0x08000)
 #define SONIC_BASE(IO_BASE + 0x0a000)
 #define SCC_BASE  (IO_BASE + 0x0c020)
+#define DJMEMC_BASE   (IO_BASE + 0x0e000)
 #define ESP_BASE  (IO_BASE + 0x1)
 #define ESP_PDMA  (IO_BASE + 0x10100)
 #define ASC_BASE  (IO_BASE + 0x14000)
@@ -257,6 +259,14 @@ static void q800_machine_init(MachineState *machine)
  _abort);
 sysbus_realize(SYS_BUS_DEVICE(>glue), _fatal);
 
+/* djMEMC memory controller */
+object_initialize_child(OBJECT(machine), "djmemc", >djmemc,
+TYPE_DJMEMC);
+sysbus = SYS_BUS_DEVICE(>djmemc);
+sysbus_realize_and_unref(sysbus, _fatal);
+memory_region_add_subregion(>macio, DJMEMC_BASE - IO_BASE,
+sysbus_mmio_get_region(sysbus, 0));
+
 /* VIA 1 */
 object_initialize_child(OBJECT(machine), "via1", >via1,
 TYPE_MOS6522_Q800_VIA1);
diff --git a/hw/misc/djmemc.c b/hw/misc/djmemc.c
new file mode 100644
index ..fd02640838b8
--- /dev/null
+++ b/hw/misc/djmemc.c
@@ -0,0 +1,135 @@
+/*
+ * djMEMC, macintosh memory and interrupt controller
+ * (Quadra 610/650/800 & Centris 610/650)
+ *
+ *https://mac68k.info/wiki/display/mac68k/djMEMC+Information
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "migration/vmstate.h"
+#include "hw/misc/djmemc.h"
+#include "hw/qdev-properties.h"
+#include "trace.h"
+
+
+#define DJMEMC_INTERLEAVECONF   0x0
+#define DJMEMC_BANK0CONF0x4
+#define DJMEMC_BANK1CONF

[PULL 18/20] q800: add ESCC alias at 0xc000

2023-10-08 Thread Laurent Vivier
From: Mark Cave-Ayland 

Tests on real Q800 hardware show that the ESCC is addressable at multiple 
locations
within the ESCC memory region - at least 0xc000, 0xc020 (as expected by the 
MacOS
toolbox ROM) and 0xc040.

All released NetBSD kernels before 10 use the 0xc000 address which causes a 
fatal
error when running the MacOS booter. Add a single memory region alias at 0xc000
to enable NetBSD kernels to start booting under QEMU.

Signed-off-by: Mark Cave-Ayland 
Reviewed-by: Laurent Vivier 
Message-ID: <20231004083806.757242-19-mark.cave-ayl...@ilande.co.uk>
Signed-off-by: Laurent Vivier 
---
 include/hw/m68k/q800.h | 1 +
 hw/m68k/q800.c | 6 ++
 2 files changed, 7 insertions(+)

diff --git a/include/hw/m68k/q800.h b/include/hw/m68k/q800.h
index fbaacd88bd57..348eaf4703d0 100644
--- a/include/hw/m68k/q800.h
+++ b/include/hw/m68k/q800.h
@@ -67,6 +67,7 @@ struct Q800MachineState {
 MemoryRegion macio;
 MemoryRegion macio_alias;
 MemoryRegion machine_id;
+MemoryRegion escc_alias;
 };
 
 #define TYPE_Q800_MACHINE MACHINE_TYPE_NAME("q800")
diff --git a/hw/m68k/q800.c b/hw/m68k/q800.c
index ac3115d32844..27a0b3c08a98 100644
--- a/hw/m68k/q800.c
+++ b/hw/m68k/q800.c
@@ -451,6 +451,12 @@ static void q800_machine_init(MachineState *machine)
 memory_region_add_subregion(>macio, SCC_BASE - IO_BASE,
 sysbus_mmio_get_region(sysbus, 0));
 
+/* Create alias for NetBSD */
+memory_region_init_alias(>escc_alias, OBJECT(machine), "escc-alias",
+ sysbus_mmio_get_region(sysbus, 0), 0, 0x8);
+memory_region_add_subregion(>macio, SCC_BASE - IO_BASE - 0x20,
+>escc_alias);
+
 /* SCSI */
 
 object_initialize_child(OBJECT(machine), "esp", >esp,
-- 
2.41.0




[PULL 20/20] mac_via: extend timer calibration hack to work with A/UX

2023-10-08 Thread Laurent Vivier
From: Mark Cave-Ayland 

The A/UX timer calibration loop runs continuously until 2 consecutive iterations
differ by at least 0x492 timer ticks. Modern hosts execute the timer calibration
loop so fast that this situation never occurs causing a hang on boot.

Use a similar method to Shoebill which is to randomly add 0x500 to the T2
counter value during calibration to enable it to eventually succeed.

Signed-off-by: Mark Cave-Ayland 
Reviewed-by: Laurent Vivier 
Message-ID: <20231004083806.757242-21-mark.cave-ayl...@ilande.co.uk>
Signed-off-by: Laurent Vivier 
---
 hw/misc/mac_via.c | 56 +++
 1 file changed, 56 insertions(+)

diff --git a/hw/misc/mac_via.c b/hw/misc/mac_via.c
index 500ece5872bd..b6206ef73ca7 100644
--- a/hw/misc/mac_via.c
+++ b/hw/misc/mac_via.c
@@ -983,6 +983,44 @@ static void 
via1_timer_calibration_hack(MOS6522Q800VIA1State *v1s, int addr,
 /* Looks like there has been a reset? */
 v1s->timer_hack_state = 1;
 }
+
+if (addr == VIA_REG_T2CL && val == 0xf0) {
+/* VIA_REG_T2CL: low byte of counter (A/UX) */
+v1s->timer_hack_state = 5;
+}
+break;
+case 5:
+if (addr == VIA_REG_T2CH && val == 0x3c) {
+/*
+ * VIA_REG_T2CH: high byte of counter (A/UX). We are now extremely
+ * likely to be in the A/UX timer calibration routine, so move to
+ * the next state where we enable the calibration hack.
+ */
+v1s->timer_hack_state = 6;
+} else if ((addr == VIA_REG_IER && val == 0x20) ||
+   addr == VIA_REG_T2CH) {
+/* We're doing something else with the timer, not calibration */
+v1s->timer_hack_state = 0;
+}
+break;
+case 6:
+if ((addr == VIA_REG_IER && val == 0x20) || addr == VIA_REG_T2CH) {
+/* End of A/UX timer calibration routine, or another write */
+v1s->timer_hack_state = 7;
+} else {
+v1s->timer_hack_state = 0;
+}
+break;
+case 7:
+/*
+ * This is the normal post-calibration timer state once both the
+ * MacOS toolbox and A/UX have been calibrated, until we see a write
+ * to VIA_REG_PCR to suggest a reset
+ */
+if (addr == VIA_REG_PCR && val == 0x22) {
+/* Looks like there has been a reset? */
+v1s->timer_hack_state = 1;
+}
 break;
 default:
 g_assert_not_reached();
@@ -998,6 +1036,7 @@ static uint64_t mos6522_q800_via1_read(void *opaque, 
hwaddr addr, unsigned size)
 MOS6522Q800VIA1State *s = MOS6522_Q800_VIA1(opaque);
 MOS6522State *ms = MOS6522(s);
 uint64_t ret;
+int64_t now;
 
 addr = (addr >> 9) & 0xf;
 ret = mos6522_read(ms, addr, size);
@@ -1007,6 +1046,23 @@ static uint64_t mos6522_q800_via1_read(void *opaque, 
hwaddr addr, unsigned size)
 /* Quadra 800 Id */
 ret = (ret & ~VIA1A_CPUID_MASK) | VIA1A_CPUID_Q800;
 break;
+case VIA_REG_T2CH:
+if (s->timer_hack_state == 6) {
+/*
+ * The A/UX timer calibration loop runs continuously until 2
+ * consecutive iterations differ by at least 0x492 timer ticks.
+ * Modern hosts execute the timer calibration loop so fast that
+ * this situation never occurs causing a hang on boot. Use a
+ * similar method to Shoebill which is to randomly add 0x500 to
+ * the T2 counter value during calibration to enable it to
+ * eventually succeed.
+ */
+now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+if (now & 1) {
+ret += 0x5;
+}
+}
+break;
 }
 return ret;
 }
-- 
2.41.0




[PULL 00/20] Q800 for 8.2 patches

2023-10-08 Thread Laurent Vivier
The following changes since commit 2f3913f4b2ad74baeb5a6f1d36efbd9ecdf1057d:

  Merge tag 'for_upstream' of https://git.kernel.org/pub/scm/virt/kvm/mst/qemu 
into staging (2023-10-05 09:01:01 -0400)

are available in the Git repository at:

  https://github.com/vivier/qemu-m68k.git tags/q800-for-8.2-pull-request

for you to fetch changes up to b4d3a83b89fba814613f7ead6b6ea92e0b2c3cd8:

  mac_via: extend timer calibration hack to work with A/UX (2023-10-06 10:33:43 
+0200)


Pull request q800 20231008

add support for booting:
  - MacOS 7.1 - 8.1, with or without virtual memory enabled
  - A/UX 3.0.1
  - NetBSD 9.3
  - Linux (via EMILE)



Mark Cave-Ayland (20):
  q800-glue.c: convert to Resettable interface
  q800: add djMEMC memory controller
  q800: add machine id register
  q800: implement additional machine id bits on VIA1 port A
  q800: add IOSB subsystem
  q800: allow accesses to RAM area even if less memory is available
  audio: add Apple Sound Chip (ASC) emulation
  asc: generate silence if FIFO empty but engine still running
  q800: add Apple Sound Chip (ASC) audio to machine
  q800: add easc bool machine class property to switch between ASC and
EASC
  swim: add trace events for IWM and ISM registers
  swim: split into separate IWM and ISM register blocks
  swim: update IWM/ISM register block decoding
  mac_via: work around underflow in TimeDBRA timing loop in SETUPTIMEK
  mac_via: workaround NetBSD ADB bus enumeration issue
  mac_via: implement ADB_STATE_IDLE state if shift register in input
mode
  mac_via: always clear ADB interrupt when switching to A/UX mode
  q800: add ESCC alias at 0xc000
  q800: add alias for MacOS toolbox ROM at 0x4000
  mac_via: extend timer calibration hack to work with A/UX

 MAINTAINERS |   6 +
 include/hw/audio/asc.h  |  86 +
 include/hw/block/swim.h |  21 +-
 include/hw/m68k/q800-glue.h |   4 +-
 include/hw/m68k/q800.h  |  11 +
 include/hw/misc/djmemc.h|  30 ++
 include/hw/misc/iosb.h  |  25 ++
 include/hw/misc/mac_via.h   |   3 +
 hw/audio/asc.c  | 727 
 hw/block/swim.c | 261 -
 hw/m68k/q800-glue.c |  18 +-
 hw/m68k/q800.c  | 138 ++-
 hw/misc/djmemc.c| 135 +++
 hw/misc/iosb.c  | 133 +++
 hw/misc/mac_via.c   | 234 +++-
 hw/audio/Kconfig|   3 +
 hw/audio/meson.build|   1 +
 hw/audio/trace-events   |  10 +
 hw/block/trace-events   |   8 +
 hw/m68k/Kconfig |   3 +
 hw/misc/Kconfig |   6 +
 hw/misc/meson.build |   2 +
 hw/misc/trace-events|  10 +
 23 files changed, 1769 insertions(+), 106 deletions(-)
 create mode 100644 include/hw/audio/asc.h
 create mode 100644 include/hw/misc/djmemc.h
 create mode 100644 include/hw/misc/iosb.h
 create mode 100644 hw/audio/asc.c
 create mode 100644 hw/misc/djmemc.c
 create mode 100644 hw/misc/iosb.c

-- 
2.41.0




[PULL 04/20] q800: implement additional machine id bits on VIA1 port A

2023-10-08 Thread Laurent Vivier
From: Mark Cave-Ayland 

Co-developed-by: Laurent Vivier 
Signed-off-by: Mark Cave-Ayland 
Reviewed-by: Philippe Mathieu-Daudé 
Message-ID: <20231004083806.757242-5-mark.cave-ayl...@ilande.co.uk>
Signed-off-by: Laurent Vivier 
---
 hw/misc/mac_via.c | 14 +-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/hw/misc/mac_via.c b/hw/misc/mac_via.c
index f84cc68849ab..e87a1b82d8c5 100644
--- a/hw/misc/mac_via.c
+++ b/hw/misc/mac_via.c
@@ -114,6 +114,9 @@
 #define VIA1A_CPUID10x04/* CPU id bit 0 on RBV, others */
 #define VIA1A_CPUID20x10/* CPU id bit 0 on RBV, others */
 #define VIA1A_CPUID30x40/* CPU id bit 0 on RBV, others */
+#define VIA1A_CPUID_MASK (VIA1A_CPUID0 | VIA1A_CPUID1 | \
+  VIA1A_CPUID2 | VIA1A_CPUID3)
+#define VIA1A_CPUID_Q800 (VIA1A_CPUID0 | VIA1A_CPUID2)
 
 /*
  * Info on VIA1B is from Macintosh Family Hardware & MkLinux.
@@ -872,9 +875,18 @@ static uint64_t mos6522_q800_via1_read(void *opaque, 
hwaddr addr, unsigned size)
 {
 MOS6522Q800VIA1State *s = MOS6522_Q800_VIA1(opaque);
 MOS6522State *ms = MOS6522(s);
+uint64_t ret;
 
 addr = (addr >> 9) & 0xf;
-return mos6522_read(ms, addr, size);
+ret = mos6522_read(ms, addr, size);
+switch (addr) {
+case VIA_REG_A:
+case VIA_REG_ANH:
+/* Quadra 800 Id */
+ret = (ret & ~VIA1A_CPUID_MASK) | VIA1A_CPUID_Q800;
+break;
+}
+return ret;
 }
 
 static void mos6522_q800_via1_write(void *opaque, hwaddr addr, uint64_t val,
-- 
2.41.0




[PULL 13/20] swim: update IWM/ISM register block decoding

2023-10-08 Thread Laurent Vivier
From: Mark Cave-Ayland 

Update the IWM/ISM register block decoding to match the description given in the
"SWIM Chip Users Reference". This allows us to validate the device response to
the guest OS which currently only does just enough to indicate that the floppy
drive is unavailable.

Signed-off-by: Mark Cave-Ayland 
Reviewed-by: Laurent Vivier 
Message-ID: <20231004083806.757242-14-mark.cave-ayl...@ilande.co.uk>
Signed-off-by: Laurent Vivier 
---
 include/hw/block/swim.h |   8 +-
 hw/block/swim.c | 212 +---
 hw/block/trace-events   |   7 +-
 3 files changed, 143 insertions(+), 84 deletions(-)

diff --git a/include/hw/block/swim.h b/include/hw/block/swim.h
index 1bc7635d0212..5f567e8d5957 100644
--- a/include/hw/block/swim.h
+++ b/include/hw/block/swim.h
@@ -50,13 +50,15 @@ struct SWIMCtrl {
 int mode;
 /* IWM mode */
 int iwm_switch;
-uint8_t iwmregs[16];
-uint8_t iwm_data;
-uint8_t iwm_mode;
+uint8_t iwm_latches;
+uint8_t iwmregs[8];
 /* SWIM mode */
 uint8_t ismregs[16];
 uint8_t swim_phase;
 uint8_t swim_mode;
+uint8_t swim_status;
+uint8_t pram[16];
+uint8_t pram_idx;
 SWIMBus bus;
 };
 
diff --git a/hw/block/swim.c b/hw/block/swim.c
index 505718bdae3f..fd65c59f8a10 100644
--- a/hw/block/swim.c
+++ b/hw/block/swim.c
@@ -21,24 +21,28 @@
 #include "hw/qdev-properties.h"
 #include "trace.h"
 
+
+/* IWM latch bits */
+
+#define IWMLB_PHASE00
+#define IWMLB_PHASE11
+#define IWMLB_PHASE22
+#define IWMLB_PHASE33
+#define IWMLB_MOTORON   4
+#define IWMLB_DRIVESEL  5
+#define IWMLB_L66
+#define IWMLB_L77
+
 /* IWM registers */
 
-#define IWM_PH0L0
-#define IWM_PH0H1
-#define IWM_PH1L2
-#define IWM_PH1H3
-#define IWM_PH2L4
-#define IWM_PH2H5
-#define IWM_PH3L6
-#define IWM_PH3H7
-#define IWM_MTROFF  8
-#define IWM_MTRON   9
-#define IWM_INTDRIVE10
-#define IWM_EXTDRIVE11
-#define IWM_Q6L 12
-#define IWM_Q6H 13
-#define IWM_Q7L 14
-#define IWM_Q7H 15
+#define IWM_READALLONES 0
+#define IWM_READDATA1
+#define IWM_READSTATUS0 2
+#define IWM_READSTATUS1 3
+#define IWM_READWHANDSHAKE0 4
+#define IWM_READWHANDSHAKE1 5
+#define IWM_WRITESETMODE6
+#define IWM_WRITEDATA   7
 
 /* SWIM registers */
 
@@ -62,8 +66,9 @@
 
 #define REG_SHIFT   9
 
-#define SWIM_MODE_IWM  0
-#define SWIM_MODE_SWIM 1
+#define SWIM_MODE_STATUS_BIT6
+#define SWIM_MODE_IWM   0
+#define SWIM_MODE_ISM   1
 
 /* bits in phase register */
 
@@ -127,10 +132,8 @@
 #define SWIM_MOTON   0x80
 
 static const char *iwm_reg_names[] = {
-"PH0L", "PH0H", "PH1L", "PH1H",
-"PH2L", "PH2H", "PH3L", "PH3H",
-"MTROFF", "MTRON", "INTDRIVE", "EXTDRIVE",
-"Q6L", "Q6H", "Q7L", "Q7H"
+"READALLONES", "READDATA", "READSTATUS0", "READSTATUS1",
+"READWHANDSHAKE0", "READWHANDSHAKE1", "WRITESETMODE", "WRITEDATA"
 };
 
 static const char *ism_reg_names[] = {
@@ -274,68 +277,99 @@ static const TypeInfo swim_bus_info = {
 .instance_size = sizeof(SWIMBus),
 };
 
-static void iwmctrl_write(void *opaque, hwaddr reg, uint64_t value,
+static void iwmctrl_write(void *opaque, hwaddr addr, uint64_t value,
   unsigned size)
 {
 SWIMCtrl *swimctrl = opaque;
+uint8_t latch, reg, ism_bit;
 
-reg >>= REG_SHIFT;
+addr >>= REG_SHIFT;
+
+/* A3-A1 select a latch, A0 specifies the value */
+latch = (addr >> 1) & 7;
+if (addr & 1) {
+swimctrl->iwm_latches |= (1 << latch);
+} else {
+swimctrl->iwm_latches &= ~(1 << latch);
+}
+
+reg = (swimctrl->iwm_latches & 0xc0) >> 5 |
+  (swimctrl->iwm_latches & 0x10) >> 4;
 
 swimctrl->iwmregs[reg] = value;
 trace_swim_iwmctrl_write(reg, iwm_reg_names[reg], size, value);
 
-if (swimctrl->iwmregs[IWM_Q7H]) {
-if (swimctrl->iwmregs[IWM_MTRON]) {
-/* data register */
-swimctrl->iwm_data = value;
-} else {
-/* mode register */
-swimctrl->iwm_mode = value;
-/* detect sequence to switch from IWM mode to SWIM mode */
-switch (swimctrl->iwm_switch) {
-case 0:
-if (value == 0x57) {
-swimctrl->

[PULL 19/20] q800: add alias for MacOS toolbox ROM at 0x40000000

2023-10-08 Thread Laurent Vivier
From: Mark Cave-Ayland 

According to the Apple Quadra 800 Developer Note document, the Quadra 800 ROM
consists of 2 ROM code sections based at offsets 0x0 and 0x80. A/UX attempts
to access the toolbox ROM at the lower offset during startup, so provide a
memory alias to allow the access to succeed.

Signed-off-by: Mark Cave-Ayland 
Reviewed-by: Laurent Vivier 
Message-ID: <20231004083806.757242-20-mark.cave-ayl...@ilande.co.uk>
Signed-off-by: Laurent Vivier 
---
 include/hw/m68k/q800.h | 1 +
 hw/m68k/q800.c | 5 +
 2 files changed, 6 insertions(+)

diff --git a/include/hw/m68k/q800.h b/include/hw/m68k/q800.h
index 348eaf4703d0..a9661f65f695 100644
--- a/include/hw/m68k/q800.h
+++ b/include/hw/m68k/q800.h
@@ -50,6 +50,7 @@ struct Q800MachineState {
 bool easc;
 M68kCPU cpu;
 MemoryRegion rom;
+MemoryRegion rom_alias;
 GLUEState glue;
 MOS6522Q800VIA1State via1;
 MOS6522Q800VIA2State via2;
diff --git a/hw/m68k/q800.c b/hw/m68k/q800.c
index 27a0b3c08a98..1d7cd5ff1c31 100644
--- a/hw/m68k/q800.c
+++ b/hw/m68k/q800.c
@@ -660,6 +660,11 @@ static void q800_machine_init(MachineState *machine)
 filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
 memory_region_add_subregion(get_system_memory(), MACROM_ADDR, >rom);
 
+memory_region_init_alias(>rom_alias, NULL, "m68k_mac.rom-alias",
+ >rom, 0, MACROM_SIZE);
+memory_region_add_subregion(get_system_memory(), 0x4000,
+>rom_alias);
+
 /* Load MacROM binary */
 if (filename) {
 bios_size = load_image_targphys(filename, MACROM_ADDR, 
MACROM_SIZE);
-- 
2.41.0




[PULL 11/20] swim: add trace events for IWM and ISM registers

2023-10-08 Thread Laurent Vivier
From: Mark Cave-Ayland 

Signed-off-by: Mark Cave-Ayland 
Reviewed-by: Laurent Vivier 
Message-ID: <20231004083806.757242-12-mark.cave-ayl...@ilande.co.uk>
Signed-off-by: Laurent Vivier 
---
 hw/block/swim.c   | 14 ++
 hw/block/trace-events |  7 +++
 2 files changed, 21 insertions(+)

diff --git a/hw/block/swim.c b/hw/block/swim.c
index 333da08ce093..7df36ea139cb 100644
--- a/hw/block/swim.c
+++ b/hw/block/swim.c
@@ -19,6 +19,7 @@
 #include "hw/block/block.h"
 #include "hw/block/swim.h"
 #include "hw/qdev-properties.h"
+#include "trace.h"
 
 /* IWM registers */
 
@@ -125,6 +126,13 @@
 #define SWIM_HEDSEL  0x20
 #define SWIM_MOTON   0x80
 
+static const char *swim_reg_names[] = {
+"WRITE_DATA", "WRITE_MARK", "WRITE_CRC", "WRITE_PARAMETER",
+"WRITE_PHASE", "WRITE_SETUP", "WRITE_MODE0", "WRITE_MODE1",
+"READ_DATA", "READ_MARK", "READ_ERROR", "READ_PARAMETER",
+"READ_PHASE", "READ_SETUP", "READ_STATUS", "READ_HANDSHAKE"
+};
+
 static void fd_recalibrate(FDrive *drive)
 {
 }
@@ -267,6 +275,7 @@ static void iwmctrl_write(void *opaque, hwaddr reg, 
uint64_t value,
 reg >>= REG_SHIFT;
 
 swimctrl->regs[reg >> 1] = reg & 1;
+trace_swim_iwmctrl_write((reg >> 1), size, (reg & 1));
 
 if (swimctrl->regs[IWM_Q6] &&
 swimctrl->regs[IWM_Q7]) {
@@ -297,6 +306,7 @@ static void iwmctrl_write(void *opaque, hwaddr reg, 
uint64_t value,
 if (value == 0x57) {
 swimctrl->mode = SWIM_MODE_SWIM;
 swimctrl->iwm_switch = 0;
+trace_swim_iwm_switch();
 }
 break;
 }
@@ -312,6 +322,7 @@ static uint64_t iwmctrl_read(void *opaque, hwaddr reg, 
unsigned size)
 
 swimctrl->regs[reg >> 1] = reg & 1;
 
+trace_swim_iwmctrl_read((reg >> 1), size, (reg & 1));
 return 0;
 }
 
@@ -327,6 +338,8 @@ static void swimctrl_write(void *opaque, hwaddr reg, 
uint64_t value,
 
 reg >>= REG_SHIFT;
 
+trace_swim_swimctrl_write(reg, swim_reg_names[reg], size, value);
+
 switch (reg) {
 case SWIM_WRITE_PHASE:
 swimctrl->swim_phase = value;
@@ -376,6 +389,7 @@ static uint64_t swimctrl_read(void *opaque, hwaddr reg, 
unsigned size)
 break;
 }
 
+trace_swim_swimctrl_read(reg, swim_reg_names[reg], size, value);
 return value;
 }
 
diff --git a/hw/block/trace-events b/hw/block/trace-events
index 34be8b9135f5..c041ec45e312 100644
--- a/hw/block/trace-events
+++ b/hw/block/trace-events
@@ -90,3 +90,10 @@ m25p80_read_data(void *s, uint32_t pos, uint8_t v) "[%p] 
Read data 0x%"PRIx32"=0
 m25p80_read_sfdp(void *s, uint32_t addr, uint8_t v) "[%p] Read SFDP 
0x%"PRIx32"=0x%"PRIx8
 m25p80_binding(void *s) "[%p] Binding to IF_MTD drive"
 m25p80_binding_no_bdrv(void *s) "[%p] No BDRV - binding to RAM"
+
+# swim.c
+swim_swimctrl_read(int reg, const char *name, unsigned size, uint64_t value) 
"reg=%d [%s] size=%u value=0x%"PRIx64
+swim_swimctrl_write(int reg, const char *name, unsigned size, uint64_t value) 
"reg=%d [%s] size=%u value=0x%"PRIx64
+swim_iwmctrl_read(int reg, unsigned size, uint64_t value) "reg=%d size=%u 
value=0x%"PRIx64
+swim_iwmctrl_write(int reg, unsigned size, uint64_t value) "reg=%d size=%u 
value=0x%"PRIx64
+swim_iwm_switch(void) "switch from IWM to SWIM mode"
-- 
2.41.0




[PULL 17/20] mac_via: always clear ADB interrupt when switching to A/UX mode

2023-10-08 Thread Laurent Vivier
From: Mark Cave-Ayland 

When the NetBSD kernel initialises it can leave the ADB interrupt asserted
depending upon where in the ADB poll cycle the MacOS ADB interrupt handler
is when the NetBSD kernel disables interrupts.

The NetBSD ADB driver uses the ADB interrupt state to determine if the ADB
is busy and refuses to send ADB commands unless it is clear. To ensure that
this doesn't happen, always clear the ADB interrupt when switching to A/UX
mode to ensure that the bus enumeration always occurs.

Signed-off-by: Mark Cave-Ayland 
Reviewed-by: Laurent Vivier 
Message-ID: <20231004083806.757242-18-mark.cave-ayl...@ilande.co.uk>
Signed-off-by: Laurent Vivier 
---
 hw/misc/mac_via.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/hw/misc/mac_via.c b/hw/misc/mac_via.c
index 3c41d6263d45..500ece5872bd 100644
--- a/hw/misc/mac_via.c
+++ b/hw/misc/mac_via.c
@@ -875,6 +875,15 @@ static void via1_auxmode_update(MOS6522Q800VIA1State *v1s)
 if (irq != oldirq) {
 trace_via1_auxmode(irq);
 qemu_set_irq(v1s->auxmode_irq, irq);
+
+/*
+ * Clear the ADB interrupt. MacOS can leave VIA1B_vADBInt asserted
+ * (low) if a poll sequence doesn't complete before NetBSD disables
+ * interrupts upon boot. Fortunately NetBSD switches to the so-called
+ * "A/UX" interrupt mode after it initialises, so we can use this as
+ * a convenient place to clear the ADB interrupt for now.
+ */
+s->b |= VIA1B_vADBInt;
 }
 }
 
-- 
2.41.0




Re: [PATCH v4 00/20] q800: add support for booting MacOS Classic - part 2

2023-10-06 Thread Laurent Vivier

Le 04/10/2023 à 10:37, Mark Cave-Ayland a écrit :

This series contains the remaining patches needed to allow QEMU's q800
machine to boot MacOS Classic when used in conjunction with a real
Quadra 800 ROM image. In fact with this series applied it is possible
to boot all of the following OSs:

   - MacOS 7.1 - 8.1, with or without virtual memory enabled
   - A/UX 3.0.1
   - NetBSD 9.3
   - Linux (via EMILE)

If you are ready to experience some 90s nostalgia then all you need is
to grab yourself a copy of the Quadra 800 ROM (checksum 0xf1acad13) and a
suitable install ISO as follows:

   # Prepare a PRAM image
   $ qemu-img create -f raw pram.img 256b

   # Launch QEMU with blank disk and install CDROM
   $ ./qemu-system-m68k \
   -M q800 \
   -m 128 \
   -bios Quadra800.rom \
   -drive file=pram.img,format=raw,if=mtd \
   -drive file=disk.img,media=disk,format=raw,if=none,id=hd \
   -device scsi-hd,scsi-id=0,drive=hd \
   -drive file=cdrom.iso,media=cdrom,if=none,id=cd \
   -device scsi-cd,scsi-id=3,drive=cd

And off you go! For more in-depth information about the installation process
I highly recommend the installation guide over at emaculation.com [1].
Compatibility is generally very good, and I'm pleased to report it is possible
to run one of the most popular productivity apps from the 90s [2].

I'd like to add a big thank you to all the people who have helped me work on
this series, including testing on real hardware, answering questions about
MacOS Classic internals and helping to diagnose and fix bugs in the 68k
emulation. In particular thanks go to Laurent Vivier, Finn Thain, Howard
Spoelstra, Volker Rümelin, Richard Henderson, Martin Husemann, Rin Okuyama,
Elliot Nunn, and SolraBizna.

Signed-off-by: Mark Cave-Ayland 

[1] https://www.emaculation.com/doku.php/qemu
[2] https://www.youtube.com/watch?v=yI21gURQ1Ew


v4:
- Rebase onto master
- Add R-B tag from Zoltan to patch 5
- Adjust AUD_register_card() and add machine audiodev property for ASC to 
reflect Paolo's
   recent audiodev changes

v3:
- Rebase onto master
- Add R-B tags from Laurent
- Squash fixes from Volker into patch 7 ("audio: add Apple Sound Chip (ASC) 
emulation")
- Change iwmregs from uint16_t to uint8_t in patch 12 ("swim: split into 
separate IWM
   and ISM register blocks")

v2:
- Rebase onto master
- Add R-B tags from Phil and Laurent
- Improve ASC logic for generating interrupts when FIFO underflow occurs
- Rework ASC silence generation logic similar to Volker's original proposal
- Update A/UX timer calibration hack to reflect the change of accesses now that
   #360 is resolved


Mark Cave-Ayland (20):
   q800-glue.c: convert to Resettable interface
   q800: add djMEMC memory controller
   q800: add machine id register
   q800: implement additional machine id bits on VIA1 port A
   q800: add IOSB subsystem
   q800: allow accesses to RAM area even if less memory is available
   audio: add Apple Sound Chip (ASC) emulation
   asc: generate silence if FIFO empty but engine still running
   q800: add Apple Sound Chip (ASC) audio to machine
   q800: add easc bool machine class property to switch between ASC and
 EASC
   swim: add trace events for IWM and ISM registers
   swim: split into separate IWM and ISM register blocks
   swim: update IWM/ISM register block decoding
   mac_via: work around underflow in TimeDBRA timing loop in SETUPTIMEK
   mac_via: workaround NetBSD ADB bus enumeration issue
   mac_via: implement ADB_STATE_IDLE state if shift register in input
 mode
   mac_via: always clear ADB interrupt when switching to A/UX mode
   q800: add ESCC alias at 0xc000
   q800: add alias for MacOS toolbox ROM at 0x4000
   mac_via: extend timer calibration hack to work with A/UX

  MAINTAINERS |   6 +
  hw/audio/Kconfig|   3 +
  hw/audio/asc.c  | 727 
  hw/audio/meson.build|   1 +
  hw/audio/trace-events   |  10 +
  hw/block/swim.c | 261 -
  hw/block/trace-events   |   8 +
  hw/m68k/Kconfig |   3 +
  hw/m68k/q800-glue.c |  18 +-
  hw/m68k/q800.c  | 138 ++-
  hw/misc/Kconfig |   6 +
  hw/misc/djmemc.c| 135 +++
  hw/misc/iosb.c  | 133 +++
  hw/misc/mac_via.c   | 234 +++-
  hw/misc/meson.build |   2 +
  hw/misc/trace-events|  10 +
  include/hw/audio/asc.h  |  86 +
  include/hw/block/swim.h |  21 +-
  include/hw/m68k/q800-glue.h |   4 +-
  include/hw/m68k/q800.h  |  11 +
  include/hw/misc/djmemc.h|  30 ++
  include/hw/misc/iosb.h  |  25 ++
  include/hw/misc/mac_via.h   |   3 +
  23 files changed, 1769 insertions(+), 106 deletions(-)
  create mode 100644 hw/audio/asc.c
  create mode 100644 hw/misc/djmemc.c
  create mode 100644 hw/misc/iosb.c
  create mode 100644 include/hw/audio/asc.h
  create mode 100644 include/hw/misc/dj

Re: [PATCH v2 13/20] swim: update IWM/ISM register block decoding

2023-09-26 Thread Laurent Vivier
g_names[reg], size, value);
  return value;
  }
  
@@ -417,13 +476,11 @@ static void sysbus_swim_reset(DeviceState *d)
  
  ctrl->mode = 0;

  ctrl->iwm_switch = 0;
-ctrl->iwm_data = 0;
-ctrl->iwm_mode = 0;
-memset(ctrl->iwmregs, 0, 16);
+memset(ctrl->iwmregs, 0, sizeof(ctrl->iwmregs));
  
  ctrl->swim_phase = 0;

  ctrl->swim_mode = 0;
-memset(ctrl->ismregs, 0, 16);
+memset(ctrl->ismregs, 0, sizeof(ctrl->ismregs));
  for (i = 0; i < SWIM_MAX_FD; i++) {
  fd_recalibrate(>drives[i]);
  }
@@ -472,9 +529,8 @@ static const VMStateDescription vmstate_swim = {
  VMSTATE_INT32(mode, SWIMCtrl),
  /* IWM mode */
  VMSTATE_INT32(iwm_switch, SWIMCtrl),
-VMSTATE_UINT8_ARRAY(iwmregs, SWIMCtrl, 16),
-VMSTATE_UINT8(iwm_data, SWIMCtrl),
-VMSTATE_UINT8(iwm_mode, SWIMCtrl),
+VMSTATE_UINT8(iwm_latches, SWIMCtrl),
+VMSTATE_UINT8_ARRAY(iwmregs, SWIMCtrl, 8),
  /* SWIM mode */
  VMSTATE_UINT8_ARRAY(ismregs, SWIMCtrl, 16),
  VMSTATE_UINT8(swim_phase, SWIMCtrl),
diff --git a/hw/block/trace-events b/hw/block/trace-events
index ea84ad6c77..bab21d3a1c 100644
--- a/hw/block/trace-events
+++ b/hw/block/trace-events
@@ -92,8 +92,9 @@ m25p80_binding(void *s) "[%p] Binding to IF_MTD drive"
  m25p80_binding_no_bdrv(void *s) "[%p] No BDRV - binding to RAM"
  
  # swim.c

-swim_swimctrl_read(int reg, const char *name, unsigned size, uint64_t value) 
"reg=%d [%s] size=%u value=0x%"PRIx64
-swim_swimctrl_write(int reg, const char *name, unsigned size, uint64_t value) 
"reg=%d [%s] size=%u value=0x%"PRIx64
+swim_ismctrl_read(int reg, const char *name, unsigned size, uint64_t value) "reg=%d 
[%s] size=%u value=0x%"PRIx64
+swim_ismctrl_write(int reg, const char *name, unsigned size, uint64_t value) 
"reg=%d [%s] size=%u value=0x%"PRIx64
  swim_iwmctrl_read(int reg, const char *name, unsigned size, uint64_t value) 
"reg=%d [%s] size=%u value=0x%"PRIx64
  swim_iwmctrl_write(int reg, const char *name, unsigned size, uint64_t value) 
"reg=%d [%s] size=%u value=0x%"PRIx64
-swim_iwm_switch(void) "switch from IWM to SWIM mode"
+swim_switch_to_ism(void) "switch from IWM to ISM mode"
+swim_switch_to_iwm(void) "switch from ISM to IWM mode"
diff --git a/include/hw/block/swim.h b/include/hw/block/swim.h
index 1bc7635d02..5f567e8d59 100644
--- a/include/hw/block/swim.h
+++ b/include/hw/block/swim.h
@@ -50,13 +50,15 @@ struct SWIMCtrl {
  int mode;
  /* IWM mode */
  int iwm_switch;
-uint8_t iwmregs[16];
-uint8_t iwm_data;
-uint8_t iwm_mode;
+uint8_t iwm_latches;
+uint8_t iwmregs[8];
  /* SWIM mode */
  uint8_t ismregs[16];
  uint8_t swim_phase;
  uint8_t swim_mode;
+uint8_t swim_status;
+uint8_t pram[16];
+uint8_t pram_idx;
  SWIMBus bus;
  };
  


Reviewed-by: Laurent Vivier 




Re: [PATCH v2 12/20] swim: split into separate IWM and ISM register blocks

2023-09-26 Thread Laurent Vivier
_mem_ops = {

-.write = swimctrl_write,
-.read = swimctrl_read,
-.endianness = DEVICE_NATIVE_ENDIAN,
+static const MemoryRegionOps swimctrl_ism_ops = {
+.write = ismctrl_write,
+.read = ismctrl_read,
+.endianness = DEVICE_BIG_ENDIAN,
  };
  
  static void sysbus_swim_reset(DeviceState *d)

@@ -407,13 +417,13 @@ static void sysbus_swim_reset(DeviceState *d)
  
  ctrl->mode = 0;

  ctrl->iwm_switch = 0;
-for (i = 0; i < 8; i++) {
-ctrl->regs[i] = 0;
-}
  ctrl->iwm_data = 0;
  ctrl->iwm_mode = 0;
+memset(ctrl->iwmregs, 0, 16);
+
  ctrl->swim_phase = 0;
  ctrl->swim_mode = 0;
+memset(ctrl->ismregs, 0, 16);
  for (i = 0; i < SWIM_MAX_FD; i++) {
  fd_recalibrate(>drives[i]);
  }
@@ -425,9 +435,12 @@ static void sysbus_swim_init(Object *obj)
  Swim *sbs = SWIM(obj);
  SWIMCtrl *swimctrl = >ctrl;
  
-memory_region_init_io(>iomem, obj, _mem_ops, swimctrl,

-  "swim", 0x2000);
-sysbus_init_mmio(sbd, >iomem);
+memory_region_init(>swim, obj, "swim", 0x2000);
+memory_region_init_io(>iwm, obj, _iwm_ops, swimctrl,
+  "iwm", 0x2000);
+memory_region_init_io(>ism, obj, _ism_ops, swimctrl,
+  "ism", 0x2000);
+sysbus_init_mmio(sbd, >swim);
  }
  
  static void sysbus_swim_realize(DeviceState *dev, Error **errp)

@@ -437,6 +450,9 @@ static void sysbus_swim_realize(DeviceState *dev, Error 
**errp)
  
  qbus_init(>bus, sizeof(SWIMBus), TYPE_SWIM_BUS, dev, NULL);

  swimctrl->bus.ctrl = swimctrl;
+
+/* Default register set is IWM */
+memory_region_add_subregion(>swim, 0x0, >iwm);
  }
  
  static const VMStateDescription vmstate_fdrive = {

@@ -456,10 +472,11 @@ static const VMStateDescription vmstate_swim = {
  VMSTATE_INT32(mode, SWIMCtrl),
  /* IWM mode */
  VMSTATE_INT32(iwm_switch, SWIMCtrl),
-VMSTATE_UINT16_ARRAY(regs, SWIMCtrl, 8),
+VMSTATE_UINT8_ARRAY(iwmregs, SWIMCtrl, 16),
  VMSTATE_UINT8(iwm_data, SWIMCtrl),
  VMSTATE_UINT8(iwm_mode, SWIMCtrl),
  /* SWIM mode */
+VMSTATE_UINT8_ARRAY(ismregs, SWIMCtrl, 16),
  VMSTATE_UINT8(swim_phase, SWIMCtrl),
  VMSTATE_UINT8(swim_mode, SWIMCtrl),
  /* Drives */
diff --git a/hw/block/trace-events b/hw/block/trace-events
index c041ec45e3..ea84ad6c77 100644
--- a/hw/block/trace-events
+++ b/hw/block/trace-events
@@ -94,6 +94,6 @@ m25p80_binding_no_bdrv(void *s) "[%p] No BDRV - binding to 
RAM"
  # swim.c
  swim_swimctrl_read(int reg, const char *name, unsigned size, uint64_t value) 
"reg=%d [%s] size=%u value=0x%"PRIx64
  swim_swimctrl_write(int reg, const char *name, unsigned size, uint64_t value) 
"reg=%d [%s] size=%u value=0x%"PRIx64
-swim_iwmctrl_read(int reg, unsigned size, uint64_t value) "reg=%d size=%u 
value=0x%"PRIx64
-swim_iwmctrl_write(int reg, unsigned size, uint64_t value) "reg=%d size=%u 
value=0x%"PRIx64
+swim_iwmctrl_read(int reg, const char *name, unsigned size, uint64_t value) "reg=%d 
[%s] size=%u value=0x%"PRIx64
+swim_iwmctrl_write(int reg, const char *name, unsigned size, uint64_t value) 
"reg=%d [%s] size=%u value=0x%"PRIx64
  swim_iwm_switch(void) "switch from IWM to SWIM mode"
diff --git a/include/hw/block/swim.h b/include/hw/block/swim.h
index 9b3dcb029d..1bc7635d02 100644
--- a/include/hw/block/swim.h
+++ b/include/hw/block/swim.h
@@ -43,23 +43,18 @@ typedef struct FDrive {
  } FDrive;
  
  struct SWIMCtrl {

-MemoryRegion iomem;
+MemoryRegion swim;
+MemoryRegion iwm;
+MemoryRegion ism;
  FDrive drives[SWIM_MAX_FD];
  int mode;
  /* IWM mode */
  int iwm_switch;
-uint16_t regs[8];
-#define IWM_PH0   0
-#define IWM_PH1   1
-#define IWM_PH2   2
-#define IWM_PH3   3
-#define IWM_MTR   4
-#define IWM_DRIVE 5
-#define IWM_Q66
-#define IWM_Q77
+uint8_t iwmregs[16];
  uint8_t iwm_data;
  uint8_t iwm_mode;
  /* SWIM mode */
+uint8_t ismregs[16];
  uint8_t swim_phase;
  uint8_t swim_mode;
  SWIMBus bus;


Reviewed-by: Laurent Vivier 




Re: [PATCH v2 19/20] q800: add alias for MacOS toolbox ROM at 0x40000000

2023-09-26 Thread Laurent Vivier

Le 09/09/2023 à 11:48, Mark Cave-Ayland a écrit :

According to the Apple Quadra 800 Developer Note document, the Quadra 800 ROM
consists of 2 ROM code sections based at offsets 0x0 and 0x80. A/UX attempts
to access the toolbox ROM at the lower offset during startup, so provide a
memory alias to allow the access to succeed.

Signed-off-by: Mark Cave-Ayland 
---
  hw/m68k/q800.c | 5 +
  include/hw/m68k/q800.h | 1 +
  2 files changed, 6 insertions(+)

diff --git a/hw/m68k/q800.c b/hw/m68k/q800.c
index b5b2cabc33..87665c6407 100644
--- a/hw/m68k/q800.c
+++ b/hw/m68k/q800.c
@@ -657,6 +657,11 @@ static void q800_machine_init(MachineState *machine)
  filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
  memory_region_add_subregion(get_system_memory(), MACROM_ADDR, 
>rom);
  
+memory_region_init_alias(>rom_alias, NULL, "m68k_mac.rom-alias",

+ >rom, 0, MACROM_SIZE);
+memory_region_add_subregion(get_system_memory(), 0x4000,
+>rom_alias);
+
  /* Load MacROM binary */
  if (filename) {
  bios_size = load_image_targphys(filename, MACROM_ADDR, 
MACROM_SIZE);
diff --git a/include/hw/m68k/q800.h b/include/hw/m68k/q800.h
index 348eaf4703..a9661f65f6 100644
--- a/include/hw/m68k/q800.h
+++ b/include/hw/m68k/q800.h
@@ -50,6 +50,7 @@ struct Q800MachineState {
  bool easc;
  M68kCPU cpu;
  MemoryRegion rom;
+MemoryRegion rom_alias;
  GLUEState glue;
  MOS6522Q800VIA1State via1;
  MOS6522Q800VIA2State via2;


Reviewed-by: Laurent Vivier 




Re: [PATCH v2 20/20] mac_via: extend timer calibration hack to work with A/UX

2023-09-26 Thread Laurent Vivier

Le 09/09/2023 à 11:48, Mark Cave-Ayland a écrit :

The A/UX timer calibration loop runs continuously until 2 consecutive iterations
differ by at least 0x492 timer ticks. Modern hosts execute the timer calibration
loop so fast that this situation never occurs causing a hang on boot.

Use a similar method to Shoebill which is to randomly add 0x500 to the T2
counter value during calibration to enable it to eventually succeed.

Signed-off-by: Mark Cave-Ayland 
---
  hw/misc/mac_via.c | 56 +++
  1 file changed, 56 insertions(+)

diff --git a/hw/misc/mac_via.c b/hw/misc/mac_via.c
index 5d1adf5863..2ce389e435 100644
--- a/hw/misc/mac_via.c
+++ b/hw/misc/mac_via.c
@@ -983,6 +983,44 @@ static void 
via1_timer_calibration_hack(MOS6522Q800VIA1State *v1s, int addr,
  /* Looks like there has been a reset? */
  v1s->timer_hack_state = 1;
  }
+
+if (addr == VIA_REG_T2CL && val == 0xf0) {
+/* VIA_REG_T2CL: low byte of counter (A/UX) */
+v1s->timer_hack_state = 5;
+}
+break;
+case 5:
+if (addr == VIA_REG_T2CH && val == 0x3c) {
+/*
+ * VIA_REG_T2CH: high byte of counter (A/UX). We are now extremely
+ * likely to be in the A/UX timer calibration routine, so move to
+ * the next state where we enable the calibration hack.
+ */
+v1s->timer_hack_state = 6;
+} else if ((addr == VIA_REG_IER && val == 0x20) ||
+   addr == VIA_REG_T2CH) {
+/* We're doing something else with the timer, not calibration */
+v1s->timer_hack_state = 0;
+}
+break;
+case 6:
+if ((addr == VIA_REG_IER && val == 0x20) || addr == VIA_REG_T2CH) {
+/* End of A/UX timer calibration routine, or another write */
+v1s->timer_hack_state = 7;
+} else {
+v1s->timer_hack_state = 0;
+}
+break;
+case 7:
+/*
+ * This is the normal post-calibration timer state once both the
+ * MacOS toolbox and A/UX have been calibrated, until we see a write
+ * to VIA_REG_PCR to suggest a reset
+ */
+if (addr == VIA_REG_PCR && val == 0x22) {
+/* Looks like there has been a reset? */
+v1s->timer_hack_state = 1;
+}
  break;
  default:
  g_assert_not_reached();
@@ -998,6 +1036,7 @@ static uint64_t mos6522_q800_via1_read(void *opaque, 
hwaddr addr, unsigned size)
  MOS6522Q800VIA1State *s = MOS6522_Q800_VIA1(opaque);
  MOS6522State *ms = MOS6522(s);
  uint64_t ret;
+int64_t now;
  
  addr = (addr >> 9) & 0xf;

  ret = mos6522_read(ms, addr, size);
@@ -1007,6 +1046,23 @@ static uint64_t mos6522_q800_via1_read(void *opaque, 
hwaddr addr, unsigned size)
  /* Quadra 800 Id */
  ret = (ret & ~VIA1A_CPUID_MASK) | VIA1A_CPUID_Q800;
  break;
+case VIA_REG_T2CH:
+if (s->timer_hack_state == 6) {
+/*
+ * The A/UX timer calibration loop runs continuously until 2
+ * consecutive iterations differ by at least 0x492 timer ticks.
+ * Modern hosts execute the timer calibration loop so fast that
+ * this situation never occurs causing a hang on boot. Use a
+ * similar method to Shoebill which is to randomly add 0x500 to
+ * the T2 counter value during calibration to enable it to
+ * eventually succeed.
+ */
+now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+if (now & 1) {
+ret += 0x5;
+    }
+    }
+break;
  }
  return ret;
  }


Reviewed-by: Laurent Vivier 




Re: [PATCH v2 18/20] q800: add ESCC alias at 0xc000

2023-09-26 Thread Laurent Vivier

Le 09/09/2023 à 11:48, Mark Cave-Ayland a écrit :

Tests on real Q800 hardware show that the ESCC is addressable at multiple 
locations
within the ESCC memory region - at least 0xc000, 0xc020 (as expected by the 
MacOS
toolbox ROM) and 0xc040.

All released NetBSD kernels before 10 use the 0xc000 address which causes a 
fatal
error when running the MacOS booter. Add a single memory region alias at 0xc000
to enable NetBSD kernels to start booting under QEMU.

Signed-off-by: Mark Cave-Ayland 
---
  hw/m68k/q800.c | 6 ++
  include/hw/m68k/q800.h | 1 +
  2 files changed, 7 insertions(+)

diff --git a/hw/m68k/q800.c b/hw/m68k/q800.c
index 5ae7c37760..b5b2cabc33 100644
--- a/hw/m68k/q800.c
+++ b/hw/m68k/q800.c
@@ -451,6 +451,12 @@ static void q800_machine_init(MachineState *machine)
  memory_region_add_subregion(>macio, SCC_BASE - IO_BASE,
  sysbus_mmio_get_region(sysbus, 0));
  
+/* Create alias for NetBSD */

+memory_region_init_alias(>escc_alias, OBJECT(machine), "escc-alias",
+ sysbus_mmio_get_region(sysbus, 0), 0, 0x8);
+memory_region_add_subregion(>macio, SCC_BASE - IO_BASE - 0x20,
+>escc_alias);
+
  /* SCSI */
  
  object_initialize_child(OBJECT(machine), "esp", >esp,

diff --git a/include/hw/m68k/q800.h b/include/hw/m68k/q800.h
index fbaacd88bd..348eaf4703 100644
--- a/include/hw/m68k/q800.h
+++ b/include/hw/m68k/q800.h
@@ -67,6 +67,7 @@ struct Q800MachineState {
  MemoryRegion macio;
  MemoryRegion macio_alias;
  MemoryRegion machine_id;
+MemoryRegion escc_alias;
  };
  
  #define TYPE_Q800_MACHINE MACHINE_TYPE_NAME("q800")


Reviewed-by: Laurent Vivier 




Re: [PATCH v2 17/20] mac_via: always clear ADB interrupt when switching to A/UX mode

2023-09-26 Thread Laurent Vivier

Le 09/09/2023 à 11:48, Mark Cave-Ayland a écrit :

When the NetBSD kernel initialises it can leave the ADB interrupt asserted
depending upon where in the ADB poll cycle the MacOS ADB interrupt handler
is when the NetBSD kernel disables interrupts.

The NetBSD ADB driver uses the ADB interrupt state to determine if the ADB
is busy and refuses to send ADB commands unless it is clear. To ensure that
this doesn't happen, always clear the ADB interrupt when switching to A/UX
mode to ensure that the bus enumeration always occurs.

Signed-off-by: Mark Cave-Ayland 
---
  hw/misc/mac_via.c | 9 +
  1 file changed, 9 insertions(+)

diff --git a/hw/misc/mac_via.c b/hw/misc/mac_via.c
index 398e8d1967..5d1adf5863 100644
--- a/hw/misc/mac_via.c
+++ b/hw/misc/mac_via.c
@@ -875,6 +875,15 @@ static void via1_auxmode_update(MOS6522Q800VIA1State *v1s)
  if (irq != oldirq) {
  trace_via1_auxmode(irq);
  qemu_set_irq(v1s->auxmode_irq, irq);
+
+/*
+ * Clear the ADB interrupt. MacOS can leave VIA1B_vADBInt asserted
+ * (low) if a poll sequence doesn't complete before NetBSD disables
+ * interrupts upon boot. Fortunately NetBSD switches to the so-called
+ * "A/UX" interrupt mode after it initialises, so we can use this as
+ * a convenient place to clear the ADB interrupt for now.
+ */
+s->b |= VIA1B_vADBInt;
  }
  }
  


Reviewed-by: Laurent Vivier 




Re: [PATCH v2 16/20] mac_via: implement ADB_STATE_IDLE state if shift register in input mode

2023-09-26 Thread Laurent Vivier

Le 09/09/2023 à 11:48, Mark Cave-Ayland a écrit :

NetBSD switches directly to IDLE state without switching the shift register to
input mode. Duplicate the existing ADB_STATE_IDLE logic in input mode from when
the shift register is in output mode which allows the ADB autopoll handler to
handle the response.

Signed-off-by: Mark Cave-Ayland 
---
  hw/misc/mac_via.c | 6 ++
  1 file changed, 6 insertions(+)

diff --git a/hw/misc/mac_via.c b/hw/misc/mac_via.c
index 208216aed3..398e8d1967 100644
--- a/hw/misc/mac_via.c
+++ b/hw/misc/mac_via.c
@@ -702,6 +702,12 @@ static void adb_via_send(MOS6522Q800VIA1State *v1s, int 
state, uint8_t data)
  break;
  
  case ADB_STATE_IDLE:

+ms->b |= VIA1B_vADBInt;
+adb_autopoll_unblock(adb_bus);
+
+trace_via1_adb_send("IDLE", data,
+(ms->b & VIA1B_vADBInt) ? "+" : "-");
+
      return;
  }
  

Reviewed-by: Laurent Vivier 




Re: [PATCH v2 15/20] mac_via: workaround NetBSD ADB bus enumeration issue

2023-09-26 Thread Laurent Vivier

Le 09/09/2023 à 11:48, Mark Cave-Ayland a écrit :

NetBSD assumes it can send its first ADB command after sending the ADB_BUSRESET
command in ADB_STATE_NEW without changing the state back to ADB_STATE_IDLE
first as detailed in the ADB protocol.

Add a workaround to detect this condition at the start of ADB enumeration
and send the next command written to SR after a ADB_BUSRESET onto the bus
regardless, even if we don't detect a state transition to ADB_STATE_NEW.

Signed-off-by: Mark Cave-Ayland 
---
  hw/misc/mac_via.c| 34 ++
  hw/misc/trace-events |  1 +
  2 files changed, 35 insertions(+)

diff --git a/hw/misc/mac_via.c b/hw/misc/mac_via.c
index 766a32a95d..208216aed3 100644
--- a/hw/misc/mac_via.c
+++ b/hw/misc/mac_via.c
@@ -1001,6 +1001,8 @@ static void mos6522_q800_via1_write(void *opaque, hwaddr 
addr, uint64_t val,
  {
  MOS6522Q800VIA1State *v1s = MOS6522_Q800_VIA1(opaque);
  MOS6522State *ms = MOS6522(v1s);
+int oldstate, state;
+int oldsr = ms->sr;
  
  addr = (addr >> 9) & 0xf;
  
@@ -1016,6 +1018,38 @@ static void mos6522_q800_via1_write(void *opaque, hwaddr addr, uint64_t val,
  
  v1s->last_b = ms->b;

  break;
+
+case VIA_REG_SR:
+{
+/*
+ * NetBSD assumes it can send its first ADB command after sending
+ * the ADB_BUSRESET command in ADB_STATE_NEW without changing the
+ * state back to ADB_STATE_IDLE first as detailed in the ADB
+ * protocol.
+ *
+ * Add a workaround to detect this condition at the start of ADB
+ * enumeration and send the next command written to SR after a
+ * ADB_BUSRESET onto the bus regardless, even if we don't detect a
+ * state transition to ADB_STATE_NEW.
+ *
+ * Note that in my tests the NetBSD state machine takes one ADB
+ * operation to recover which means the probe for an ADB device at
+ * address 1 always fails. However since the first device is at
+ * address 2 then this will work fine, without having to come up
+ * with a more complicated and invasive solution.
+ */
+oldstate = (v1s->last_b & VIA1B_vADB_StateMask) >>
+   VIA1B_vADB_StateShift;
+state = (ms->b & VIA1B_vADB_StateMask) >> VIA1B_vADB_StateShift;
+
+if (oldstate == ADB_STATE_NEW && state == ADB_STATE_NEW &&
+(ms->acr & VIA1ACR_vShiftOut) &&
+oldsr == 0 /* ADB_BUSRESET */) {
+trace_via1_adb_netbsd_enum_hack();
+adb_via_send(v1s, state, ms->sr);
+}
+}
+break;
  }
  }
  
diff --git a/hw/misc/trace-events b/hw/misc/trace-events

index 0c9762fdf6..db8bb2d28a 100644
--- a/hw/misc/trace-events
+++ b/hw/misc/trace-events
@@ -271,6 +271,7 @@ via1_rtc_cmd_pram_sect_write(int sector, int offset, int addr, 
int value) "secto
  via1_adb_send(const char *state, uint8_t data, const char *vadbint) "state %s 
data=0x%02x vADBInt=%s"
  via1_adb_receive(const char *state, uint8_t data, const char *vadbint, int status, int 
index, int size) "state %s data=0x%02x vADBInt=%s status=0x%x index=%d size=%d"
  via1_adb_poll(uint8_t data, const char *vadbint, int status, int index, int size) 
"data=0x%02x vADBInt=%s status=0x%x index=%d size=%d"
+via1_adb_netbsd_enum_hack(void) "using NetBSD enum hack"
  via1_auxmode(int mode) "setting auxmode to %d"
  via1_timer_hack_state(int state) "setting timer_hack_state to %d"
  


Did you ask NetBSD to fix their code?

Reviewed-by: Laurent Vivier 




Re: [PATCH v2 14/20] mac_via: work around underflow in TimeDBRA timing loop in SETUPTIMEK

2023-09-26 Thread Laurent Vivier
_state != v1s->timer_hack_state) {
+trace_via1_timer_hack_state(v1s->timer_hack_state);
+}
+}
+
  static uint64_t mos6522_q800_via1_read(void *opaque, hwaddr addr, unsigned 
size)
  {
  MOS6522Q800VIA1State *s = MOS6522_Q800_VIA1(opaque);
@@ -896,6 +1003,9 @@ static void mos6522_q800_via1_write(void *opaque, hwaddr 
addr, uint64_t val,
  MOS6522State *ms = MOS6522(v1s);
  
  addr = (addr >> 9) & 0xf;

+
+via1_timer_calibration_hack(v1s, addr, val, size);
+
  mos6522_write(ms, addr, val, size);
  
  switch (addr) {

@@ -1008,6 +1118,9 @@ static void mos6522_q800_via1_reset_hold(Object *obj)
  adb_set_autopoll_enabled(adb_bus, true);
  v1s->cmd = REG_EMPTY;
  v1s->alt = REG_EMPTY;
+
+/* Timer calibration hack */
+v1s->timer_hack_state = 0;
  }
  
  static void mos6522_q800_via1_realize(DeviceState *dev, Error **errp)

@@ -1100,6 +1213,8 @@ static const VMStateDescription vmstate_q800_via1 = {
  VMSTATE_INT64(next_second, MOS6522Q800VIA1State),
  VMSTATE_TIMER_PTR(sixty_hz_timer, MOS6522Q800VIA1State),
  VMSTATE_INT64(next_sixty_hz, MOS6522Q800VIA1State),
+/* Timer hack */
+VMSTATE_INT32(timer_hack_state, MOS6522Q800VIA1State),
  VMSTATE_END_OF_LIST()
  }
  };
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
index c9bdb0d30e..0c9762fdf6 100644
--- a/hw/misc/trace-events
+++ b/hw/misc/trace-events
@@ -272,6 +272,7 @@ via1_adb_send(const char *state, uint8_t data, const char 
*vadbint) "state %s da
  via1_adb_receive(const char *state, uint8_t data, const char *vadbint, int status, int 
index, int size) "state %s data=0x%02x vADBInt=%s status=0x%x index=%d size=%d"
  via1_adb_poll(uint8_t data, const char *vadbint, int status, int index, int size) 
"data=0x%02x vADBInt=%s status=0x%x index=%d size=%d"
  via1_auxmode(int mode) "setting auxmode to %d"
+via1_timer_hack_state(int state) "setting timer_hack_state to %d"
  
  # grlib_ahb_apb_pnp.c

  grlib_ahb_pnp_read(uint64_t addr, unsigned size, uint32_t value) "AHB PnP read 
addr:0x%03"PRIx64" size:%u data:0x%08x"
diff --git a/include/hw/misc/mac_via.h b/include/hw/misc/mac_via.h
index 422da43bf9..63cdcf7c69 100644
--- a/include/hw/misc/mac_via.h
+++ b/include/hw/misc/mac_via.h
@@ -74,6 +74,9 @@ struct MOS6522Q800VIA1State {
  int64_t next_second;
  QEMUTimer *sixty_hz_timer;
  int64_t next_sixty_hz;
+
+/* SETUPTIMEK hack */
+int timer_hack_state;
  };
  
  

Reviewed-by: Laurent Vivier 




Re: [PATCH v2 11/20] swim: add trace events for IWM and ISM registers

2023-09-26 Thread Laurent Vivier

Le 09/09/2023 à 11:48, Mark Cave-Ayland a écrit :

Signed-off-by: Mark Cave-Ayland 
---
  hw/block/swim.c   | 14 ++
  hw/block/trace-events |  7 +++
  2 files changed, 21 insertions(+)

diff --git a/hw/block/swim.c b/hw/block/swim.c
index 333da08ce0..7df36ea139 100644
--- a/hw/block/swim.c
+++ b/hw/block/swim.c
@@ -19,6 +19,7 @@
  #include "hw/block/block.h"
  #include "hw/block/swim.h"
  #include "hw/qdev-properties.h"
+#include "trace.h"
  
  /* IWM registers */
  
@@ -125,6 +126,13 @@

  #define SWIM_HEDSEL  0x20
  #define SWIM_MOTON   0x80
  
+static const char *swim_reg_names[] = {

+"WRITE_DATA", "WRITE_MARK", "WRITE_CRC", "WRITE_PARAMETER",
+"WRITE_PHASE", "WRITE_SETUP", "WRITE_MODE0", "WRITE_MODE1",
+"READ_DATA", "READ_MARK", "READ_ERROR", "READ_PARAMETER",
+"READ_PHASE", "READ_SETUP", "READ_STATUS", "READ_HANDSHAKE"
+};
+
  static void fd_recalibrate(FDrive *drive)
  {
  }
@@ -267,6 +275,7 @@ static void iwmctrl_write(void *opaque, hwaddr reg, 
uint64_t value,
  reg >>= REG_SHIFT;
  
  swimctrl->regs[reg >> 1] = reg & 1;

+trace_swim_iwmctrl_write((reg >> 1), size, (reg & 1));
  
  if (swimctrl->regs[IWM_Q6] &&

  swimctrl->regs[IWM_Q7]) {
@@ -297,6 +306,7 @@ static void iwmctrl_write(void *opaque, hwaddr reg, 
uint64_t value,
  if (value == 0x57) {
  swimctrl->mode = SWIM_MODE_SWIM;
  swimctrl->iwm_switch = 0;
+trace_swim_iwm_switch();
  }
  break;
  }
@@ -312,6 +322,7 @@ static uint64_t iwmctrl_read(void *opaque, hwaddr reg, 
unsigned size)
  
  swimctrl->regs[reg >> 1] = reg & 1;
  
+trace_swim_iwmctrl_read((reg >> 1), size, (reg & 1));

  return 0;
  }
  
@@ -327,6 +338,8 @@ static void swimctrl_write(void *opaque, hwaddr reg, uint64_t value,
  
  reg >>= REG_SHIFT;
  
+trace_swim_swimctrl_write(reg, swim_reg_names[reg], size, value);

+
  switch (reg) {
  case SWIM_WRITE_PHASE:
  swimctrl->swim_phase = value;
@@ -376,6 +389,7 @@ static uint64_t swimctrl_read(void *opaque, hwaddr reg, 
unsigned size)
  break;
  }
  
+trace_swim_swimctrl_read(reg, swim_reg_names[reg], size, value);

  return value;
  }
  
diff --git a/hw/block/trace-events b/hw/block/trace-events

index 34be8b9135..c041ec45e3 100644
--- a/hw/block/trace-events
+++ b/hw/block/trace-events
@@ -90,3 +90,10 @@ m25p80_read_data(void *s, uint32_t pos, uint8_t v) "[%p] Read data 
0x%"PRIx32"=0
  m25p80_read_sfdp(void *s, uint32_t addr, uint8_t v) "[%p] Read SFDP 
0x%"PRIx32"=0x%"PRIx8
  m25p80_binding(void *s) "[%p] Binding to IF_MTD drive"
  m25p80_binding_no_bdrv(void *s) "[%p] No BDRV - binding to RAM"
+
+# swim.c
+swim_swimctrl_read(int reg, const char *name, unsigned size, uint64_t value) 
"reg=%d [%s] size=%u value=0x%"PRIx64
+swim_swimctrl_write(int reg, const char *name, unsigned size, uint64_t value) 
"reg=%d [%s] size=%u value=0x%"PRIx64
+swim_iwmctrl_read(int reg, unsigned size, uint64_t value) "reg=%d size=%u 
value=0x%"PRIx64
+swim_iwmctrl_write(int reg, unsigned size, uint64_t value) "reg=%d size=%u 
value=0x%"PRIx64
+swim_iwm_switch(void) "switch from IWM to SWIM mode"


Reviewed-by: Laurent Vivier 




Re: [PATCH v2 10/20] q800: add easc bool machine class property to switch between ASC and EASC

2023-09-26 Thread Laurent Vivier

Le 09/09/2023 à 11:48, Mark Cave-Ayland a écrit :

This determines whether the Apple Sound Chip (ASC) is set to enhanced mode
(default) or to original mode. The real Q800 hardware used an EASC chip however
a lot of older software only works with the older ASC chip.

Adding this as a machine parameter allows QEMU to be used as an developer aid
for testing and migrating code from ASC to EASC.

Signed-off-by: Mark Cave-Ayland 
Reviewed-by: Philippe Mathieu-Daudé 
---
  hw/m68k/q800.c | 30 +-
  include/hw/m68k/q800.h |  1 +
  2 files changed, 30 insertions(+), 1 deletion(-)

diff --git a/hw/m68k/q800.c b/hw/m68k/q800.c
index ae07aa20ff..5ae7c37760 100644
--- a/hw/m68k/q800.c
+++ b/hw/m68k/q800.c
@@ -484,7 +484,8 @@ static void q800_machine_init(MachineState *machine)
  /* Apple Sound Chip */
  
  object_initialize_child(OBJECT(machine), "asc", >asc, TYPE_ASC);

-qdev_prop_set_uint8(DEVICE(>asc), "asctype", ASC_TYPE_EASC);
+qdev_prop_set_uint8(DEVICE(>asc), "asctype", m->easc ? ASC_TYPE_EASC
+: ASC_TYPE_ASC);
  sysbus = SYS_BUS_DEVICE(>asc);
  sysbus_realize_and_unref(sysbus, _fatal);
  memory_region_add_subregion(>macio, ASC_BASE - IO_BASE,
@@ -674,6 +675,28 @@ static void q800_machine_init(MachineState *machine)
  }
  }
  
+static bool q800_get_easc(Object *obj, Error **errp)

+{
+Q800MachineState *ms = Q800_MACHINE(obj);
+
+return ms->easc;
+}
+
+static void q800_set_easc(Object *obj, bool value, Error **errp)
+{
+Q800MachineState *ms = Q800_MACHINE(obj);
+
+ms->easc = value;
+}
+
+static void q800_init(Object *obj)
+{
+Q800MachineState *ms = Q800_MACHINE(obj);
+
+/* Default to EASC */
+ms->easc = true;
+}
+
  static GlobalProperty hw_compat_q800[] = {
  { "scsi-hd", "quirk_mode_page_vendor_specific_apple", "on" },
  { "scsi-hd", "vendor", " SEAGATE" },
@@ -706,11 +729,16 @@ static void q800_machine_class_init(ObjectClass *oc, void 
*data)
  mc->block_default_type = IF_SCSI;
  mc->default_ram_id = "m68k_mac.ram";
  compat_props_add(mc->compat_props, hw_compat_q800, hw_compat_q800_len);
+
+object_class_property_add_bool(oc, "easc", q800_get_easc, q800_set_easc);
+object_class_property_set_description(oc, "easc",
+"Set to off to use ASC rather than EASC");
  }
  
  static const TypeInfo q800_machine_typeinfo = {

  .name   = MACHINE_TYPE_NAME("q800"),
  .parent = TYPE_MACHINE,
+.instance_init = q800_init,
  .instance_size = sizeof(Q800MachineState),
  .class_init = q800_machine_class_init,
  };
diff --git a/include/hw/m68k/q800.h b/include/hw/m68k/q800.h
index 790cf433f3..fbaacd88bd 100644
--- a/include/hw/m68k/q800.h
+++ b/include/hw/m68k/q800.h
@@ -47,6 +47,7 @@
  struct Q800MachineState {
  MachineState parent_obj;
  
+bool easc;

  M68kCPU cpu;
  MemoryRegion rom;
  GLUEState glue;


Reviewed-by: Laurent Vivier 




Re: [PATCH] m68k: Silence -Wshadow=local warnings in the m68k code

2023-09-26 Thread Laurent Vivier

Le 25/09/2023 à 20:56, Thomas Huth a écrit :

Rename the innermost variables to make the code compile
without warnings when using -Wshadow=local.

Signed-off-by: Thomas Huth 
---
  hw/m68k/bootinfo.h  | 10 --
  disas/m68k.c|  8 
  target/m68k/translate.c |  8 
  3 files changed, 12 insertions(+), 14 deletions(-)

diff --git a/hw/m68k/bootinfo.h b/hw/m68k/bootinfo.h
index a3d37e3c80..d077d03559 100644
--- a/hw/m68k/bootinfo.h
+++ b/hw/m68k/bootinfo.h
@@ -44,15 +44,14 @@
  
  #define BOOTINFOSTR(base, id, string) \

  do { \
-int i; \
  stw_p(base, id); \
  base += 2; \
  stw_p(base, \
   (sizeof(struct bi_record) + strlen(string) + \
1 /* null termination */ + 3 /* padding */) & ~3); \
  base += 2; \
-for (i = 0; string[i]; i++) { \
-stb_p(base++, string[i]); \
+for (int _i = 0; string[_i]; _i++) { \
+stb_p(base++, string[_i]); \
  } \
  stb_p(base++, 0); \
  base = QEMU_ALIGN_PTR_UP(base, 4); \
@@ -60,7 +59,6 @@
  
  #define BOOTINFODATA(base, id, data, len) \

  do { \
-int i; \
  stw_p(base, id); \
  base += 2; \
  stw_p(base, \
@@ -69,8 +67,8 @@
  base += 2; \
  stw_p(base, len); \
  base += 2; \
-for (i = 0; i < len; ++i) { \
-stb_p(base++, data[i]); \
+for (int _i = 0; _i < len; ++_i) { \
+stb_p(base++, data[_i]); \
  } \
  base = QEMU_ALIGN_PTR_UP(base, 4); \
  } while (0)
diff --git a/disas/m68k.c b/disas/m68k.c
index aefaecfbd6..a384b4cb64 100644
--- a/disas/m68k.c
+++ b/disas/m68k.c
@@ -1632,10 +1632,10 @@ print_insn_arg (const char *d,
  case '2':
  case '3':
{
-   int val = fetch_arg (buffer, place, 5, info);
+   int val2 = fetch_arg (buffer, place, 5, info);
  const char *name = 0;
  
-	switch (val)

+   switch (val2)
  {
  case 2: name = "%tt0"; break;
  case 3: name = "%tt1"; break;
@@ -1655,12 +1655,12 @@ print_insn_arg (const char *d,
  int break_reg = ((buffer[3] >> 2) & 7);
  
  	  (*info->fprintf_func)

-   (info->stream, val == 0x1c ? "%%bad%d" : "%%bac%d",
+   (info->stream, val2 == 0x1c ? "%%bad%d" : "%%bac%d",
 break_reg);
}
break;
  default:
-   (*info->fprintf_func) (info->stream, "", val);
+   (*info->fprintf_func) (info->stream, "", val2);
  }
if (name)
  (*info->fprintf_func) (info->stream, "%s", name);


"reg" would be a better name than "val2".


diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index 9e224fe796..b28d7f7d4b 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -824,14 +824,14 @@ static TCGv gen_ea_mode(CPUM68KState *env, DisasContext 
*s, int mode, int reg0,
  reg = get_areg(s, reg0);
  result = gen_ldst(s, opsize, reg, val, what, index);
  if (what == EA_STORE || !addrp) {
-TCGv tmp = tcg_temp_new();
+TCGv tmp2 = tcg_temp_new();
  if (reg0 == 7 && opsize == OS_BYTE &&
  m68k_feature(s->env, M68K_FEATURE_M68K)) {
-tcg_gen_addi_i32(tmp, reg, 2);
+tcg_gen_addi_i32(tmp2, reg, 2);
  } else {
-tcg_gen_addi_i32(tmp, reg, opsize_bytes(opsize));
+tcg_gen_addi_i32(tmp2, reg, opsize_bytes(opsize));
  }
-delay_set_areg(s, reg0, tmp, true);
+delay_set_areg(s, reg0, tmp2, true);
  }
  return result;
  case 4: /* Indirect predecrememnt.  */


"inc" would be a better name than "val2".

Otherwise:

Reviewed-by: Laurent Vivier 


Thanks,
Laurent




Re: [PATCH v2 08/20] asc: generate silence if FIFO empty but engine still running

2023-09-25 Thread Laurent Vivier

Le 09/09/2023 à 11:48, Mark Cave-Ayland a écrit :

MacOS (un)helpfully leaves the FIFO engine running even when all the samples 
have
been written to the hardware, and expects the FIFO status flags and IRQ to be
updated continuously.

There is an additional problem in that not all audio backends guarantee an
all-zero output when there is no FIFO data available, in particular the Windows
dsound backend which re-uses its internal circular buffer causing the last 
played
sound to loop indefinitely.

Whilst this is effectively a bug in the Windows dsound backend, work around it
for now using a simple heuristic: if the FIFO remains empty for half a cycle
(~23ms) then continuously fill the generated buffer with empty silence.

Signed-off-by: Mark Cave-Ayland 
---
  hw/audio/asc.c | 19 +++
  include/hw/audio/asc.h |  2 ++
  2 files changed, 21 insertions(+)

diff --git a/hw/audio/asc.c b/hw/audio/asc.c
index 336ace0cd6..b01b285512 100644
--- a/hw/audio/asc.c
+++ b/hw/audio/asc.c
@@ -334,6 +334,21 @@ static void asc_out_cb(void *opaque, int free_b)
  }
  
  if (!generated) {

+/* Workaround for audio underflow bug on Windows dsound backend */
+int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+int silent_samples = muldiv64(now - s->fifo_empty_ns,
+  NANOSECONDS_PER_SECOND, ASC_FREQ);
+
+if (silent_samples > ASC_FIFO_CYCLE_TIME / 2) {
+/*
+ * No new FIFO data within half a cycle time (~23ms) so fill the
+ * entire available buffer with silence. This prevents an issue
+ * with the Windows dsound backend whereby the sound appears to
+ * loop because the FIFO has run out of data, and the driver
+ * reuses the stale content in its circular audio buffer.
+ */
+AUD_write(s->voice, s->silentbuf, samples << s->shift);
+}
  return;
  }
  
@@ -611,6 +626,7 @@ static void asc_unrealize(DeviceState *dev)

  ASCState *s = ASC(dev);
  
  g_free(s->mixbuf);

+g_free(s->silentbuf);
  
  AUD_remove_card(>card);

  }
@@ -633,6 +649,9 @@ static void asc_realize(DeviceState *dev, Error **errp)
  s->samples = AUD_get_buffer_size_out(s->voice) >> s->shift;
  s->mixbuf = g_malloc0(s->samples << s->shift);
  
+s->silentbuf = g_malloc0(s->samples << s->shift);

+memset(s->silentbuf, 0x80, s->samples << s->shift);
+
  /* Add easc registers if required */
  if (s->type == ASC_TYPE_EASC) {
  memory_region_add_subregion(>asc, ASC_EXTREG_OFFSET,
diff --git a/include/hw/audio/asc.h b/include/hw/audio/asc.h
index d9412815c3..4741f92c46 100644
--- a/include/hw/audio/asc.h
+++ b/include/hw/audio/asc.h
@@ -68,6 +68,8 @@ struct ASCState {
  int samples;
  int shift;
  
+uint8_t *silentbuf;

+
  /* Time when we were last able to generate samples */
  int64_t fifo_empty_ns;
  


If it's specific to Windows why not using "#if defined(CONFIG_WIN32) && 
defined(CONFIG_AUDIO_DSOUND)" to clearly identify this piece of code as specific to a windows bug 
with dsound?


Anyway, code looks good:

Reviewed-by: Laurent Vivier 




Re: [PATCH v2 01/20] q800-glue.c: convert to Resettable interface

2023-09-25 Thread Laurent Vivier

Le 09/09/2023 à 11:48, Mark Cave-Ayland a écrit :

Convert the GLUE device to 3-phase reset. The legacy method
doesn't do anything that's invalid in the hold phase, so the
conversion is simple and not a behaviour change.

Signed-off-by: Mark Cave-Ayland 
Reviewed-by: Philippe Mathieu-Daudé 
---
  hw/m68k/q800-glue.c | 7 ---
  1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/hw/m68k/q800-glue.c b/hw/m68k/q800-glue.c
index 34c4f0e987..710a5c331e 100644
--- a/hw/m68k/q800-glue.c
+++ b/hw/m68k/q800-glue.c
@@ -166,9 +166,9 @@ static void glue_nmi_release(void *opaque)
  GLUE_set_irq(s, GLUE_IRQ_IN_NMI, 0);
  }
  
-static void glue_reset(DeviceState *dev)

+static void glue_reset_hold(Object *obj)
  {
-GLUEState *s = GLUE(dev);
+GLUEState *s = GLUE(obj);
  
  s->ipr = 0;

  s->auxmode = 0;
@@ -223,11 +223,12 @@ static void glue_init(Object *obj)
  static void glue_class_init(ObjectClass *klass, void *data)
  {
  DeviceClass *dc = DEVICE_CLASS(klass);
+ResettableClass *rc = RESETTABLE_CLASS(klass);
  NMIClass *nc = NMI_CLASS(klass);
  
  dc->vmsd = _glue;

-dc->reset = glue_reset;
  device_class_set_props(dc, glue_properties);
+rc->phases.hold = glue_reset_hold;
  nc->nmi_monitor_handler = glue_nmi;
  }
  


Reviewed-by: Laurent Vivier 




[PATCH 4/5] linux-user/syscall.c: clean up local variable shadowing in TARGET_NR_getcpu

2023-09-25 Thread Laurent Vivier
Fix following warnings:

.../linux-user/syscall.c: In function 'do_syscall1':
.../linux-user/syscall.c:11180:22: warning: declaration of 'cpu' shadows a 
previous local [-Wshadow=local]
11180 | unsigned cpu, node;
  |  ^~~
.../linux-user/syscall.c:8963:15: note: shadowed declaration is here
 8963 | CPUState *cpu = env_cpu(cpu_env);
  |   ^~~

Signed-off-by: Laurent Vivier 
---
 linux-user/syscall.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index c81e8d344486..6139c00ddceb 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -11177,14 +11177,14 @@ static abi_long do_syscall1(CPUArchState *cpu_env, 
int num, abi_long arg1,
 }
 case TARGET_NR_getcpu:
 {
-unsigned cpu, node;
-ret = get_errno(sys_getcpu(arg1 ?  : NULL,
+unsigned cpuid, node;
+ret = get_errno(sys_getcpu(arg1 ?  : NULL,
arg2 ?  : NULL,
NULL));
 if (is_error(ret)) {
 return ret;
 }
-if (arg1 && put_user_u32(cpu, arg1)) {
+if (arg1 && put_user_u32(cpuid, arg1)) {
 return -TARGET_EFAULT;
 }
 if (arg2 && put_user_u32(node, arg2)) {
-- 
2.41.0




[PATCH 5/5] linux-user/syscall.c: clean up local variable shadowing in xattr syscalls

2023-09-25 Thread Laurent Vivier
p is a generic variable in syscall() and can be used by any syscall
case, so this patch removes the useless local variable declaration for
the following syscalls: TARGET_NR_llistxattr, TARGET_NR_listxattr,
TARGET_NR_setxattr, TARGET_NR_lsetxattr, TARGET_NR_getxattr,
TARGET_NR_lgetxattr, TARGET_NR_removexattr, TARGET_NR_lremovexattr.

Fix following warnings:

.../linux-user/syscall.c:12342:15: warning: declaration of 'p' shadows a 
previous local [-Wshadow=compatible-local]
12342 | void *p, *b = 0;
  |   ^
.../linux-user/syscall.c:8975:11: note: shadowed declaration is here
 8975 | void *p;
  |   ^
.../linux-user/syscall.c:12379:19: warning: declaration of 'p' shadows a 
previous local [-Wshadow=compatible-local]
12379 | void *p, *n, *v = 0;
  |   ^
.../linux-user/syscall.c:8975:11: note: shadowed declaration is here
 8975 | void *p;
  |   ^
.../linux-user/syscall.c:12424:19: warning: declaration of 'p' shadows a 
previous local [-Wshadow=compatible-local]
12424 | void *p, *n, *v = 0;
  |   ^
.../linux-user/syscall.c:8975:11: note: shadowed declaration is here
 8975 | void *p;
  |   ^
.../linux-user/syscall.c:12469:19: warning: declaration of 'p' shadows a 
previous local [-Wshadow=compatible-local]
12469 | void *p, *n;
  |   ^
.../linux-user/syscall.c:8975:11: note: shadowed declaration is here
 8975 | void *p;
  |   ^

Signed-off-by: Laurent Vivier 
---
 linux-user/syscall.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 6139c00ddceb..fe228f7db3a7 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -12339,7 +12339,7 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int 
num, abi_long arg1,
 case TARGET_NR_listxattr:
 case TARGET_NR_llistxattr:
 {
-void *p, *b = 0;
+void *b = 0;
 if (arg2) {
 b = lock_user(VERIFY_WRITE, arg2, arg3, 0);
 if (!b) {
@@ -12376,7 +12376,7 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int 
num, abi_long arg1,
 case TARGET_NR_setxattr:
 case TARGET_NR_lsetxattr:
 {
-void *p, *n, *v = 0;
+void *n, *v = 0;
 if (arg3) {
 v = lock_user(VERIFY_READ, arg3, arg4, 1);
 if (!v) {
@@ -12421,7 +12421,7 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int 
num, abi_long arg1,
 case TARGET_NR_getxattr:
 case TARGET_NR_lgetxattr:
 {
-void *p, *n, *v = 0;
+void *n, *v = 0;
 if (arg3) {
 v = lock_user(VERIFY_WRITE, arg3, arg4, 0);
 if (!v) {
@@ -12466,7 +12466,7 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int 
num, abi_long arg1,
 case TARGET_NR_removexattr:
 case TARGET_NR_lremovexattr:
 {
-void *p, *n;
+void *n;
 p = lock_user_string(arg1);
 n = lock_user_string(arg2);
 if (p && n) {
-- 
2.41.0




[PATCH 3/5] linux-user/syscall.c: clean up local variable shadowing in do_ioctl_dm()

2023-09-25 Thread Laurent Vivier
Fix following warnings:

.../linux-user/syscall.c: In function 'do_ioctl_dm':
.../linux-user/syscall.c:5053:23: warning: declaration of 'arg_type' shadows a 
previous local [-Wshadow=local]
 5053 | const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_spec) };
  |   ^~~~
.../linux-user/syscall.c:4991:20: note: shadowed declaration is here
 4991 | const argtype *arg_type = ie->arg_type;
  |^~~~
...//linux-user/syscall.c:5102:27: warning: declaration of 'arg_type' shadows a 
previous local [-Wshadow=local]
 5102 | const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_name_list) 
};
  |   ^~~~
.../linux-user/syscall.c:4991:20: note: shadowed declaration is here
 4991 | const argtype *arg_type = ie->arg_type;
  |^~~~
.../linux-user/syscall.c:5130:27: warning: declaration of 'arg_type' shadows a 
previous local [-Wshadow=local]
 5130 | const argtype arg_type[] = { 
MK_STRUCT(STRUCT_dm_target_spec) };
  |   ^~~~
.../linux-user/syscall.c:4991:20: note: shadowed declaration is here
 4991 | const argtype *arg_type = ie->arg_type;
  |^~~~
.../linux-user/syscall.c:5170:27: warning: declaration of 'arg_type' shadows a 
previous local [-Wshadow=local]
 5170 | const argtype arg_type[] = { 
MK_STRUCT(STRUCT_dm_target_versions) };
  |   ^~~~
.../linux-user/syscall.c:4991:20: note: shadowed declaration is here
 4991 | const argtype *arg_type = ie->arg_type;
  |^~~~

Signed-off-by: Laurent Vivier 
---
 linux-user/syscall.c | 22 +++---
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 3521a2d70b00..c81e8d344486 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -5050,8 +5050,8 @@ static abi_long do_ioctl_dm(const IOCTLEntry *ie, uint8_t 
*buf_temp, int fd,
 {
 void *gspec = argptr;
 void *cur_data = host_data;
-const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_spec) };
-int spec_size = thunk_type_size(arg_type, 0);
+const argtype dm_arg_type[] = { MK_STRUCT(STRUCT_dm_target_spec) };
+int spec_size = thunk_type_size(dm_arg_type, 0);
 int i;
 
 for (i = 0; i < host_dm->target_count; i++) {
@@ -5059,7 +5059,7 @@ static abi_long do_ioctl_dm(const IOCTLEntry *ie, uint8_t 
*buf_temp, int fd,
 uint32_t next;
 int slen;
 
-thunk_convert(spec, gspec, arg_type, THUNK_HOST);
+thunk_convert(spec, gspec, dm_arg_type, THUNK_HOST);
 slen = strlen((char*)gspec + spec_size) + 1;
 next = spec->next;
 spec->next = sizeof(*spec) + slen;
@@ -5099,7 +5099,7 @@ static abi_long do_ioctl_dm(const IOCTLEntry *ie, uint8_t 
*buf_temp, int fd,
 struct dm_name_list *nl = (void*)host_dm + host_dm->data_start;
 uint32_t remaining_data = guest_data_size;
 void *cur_data = argptr;
-const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_name_list) };
+const argtype dm_arg_type[] = { MK_STRUCT(STRUCT_dm_name_list) };
 int nl_size = 12; /* can't use thunk_size due to alignment */
 
 while (1) {
@@ -5111,7 +5111,7 @@ static abi_long do_ioctl_dm(const IOCTLEntry *ie, uint8_t 
*buf_temp, int fd,
 host_dm->flags |= DM_BUFFER_FULL_FLAG;
 break;
 }
-thunk_convert(cur_data, nl, arg_type, THUNK_TARGET);
+thunk_convert(cur_data, nl, dm_arg_type, THUNK_TARGET);
 strcpy(cur_data + nl_size, nl->name);
 cur_data += nl->next;
 remaining_data -= nl->next;
@@ -5127,8 +5127,8 @@ static abi_long do_ioctl_dm(const IOCTLEntry *ie, uint8_t 
*buf_temp, int fd,
 {
 struct dm_target_spec *spec = (void*)host_dm + host_dm->data_start;
 void *cur_data = argptr;
-const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_spec) };
-int spec_size = thunk_type_size(arg_type, 0);
+const argtype dm_arg_type[] = { MK_STRUCT(STRUCT_dm_target_spec) };
+int spec_size = thunk_type_size(dm_arg_type, 0);
 int i;
 
 for (i = 0; i < host_dm->target_count; i++) {
@@ -5139,7 +5139,7 @@ static abi_long do_ioctl_dm(const IOCTLEntry *ie, uint8_t 
*buf_temp, int fd,
 host_dm->flags |= DM_BUFFER_FULL_FLAG;
 break;
 }
-thunk_convert(cur_data, spec, arg_type, THUNK_TARGET);
+thunk_convert(cur_data, spec, dm_arg_type, THUNK_TARGET);
 strcpy(cur_data + spec_size, (char*)[1]);
 cur_data = argptr +

[PATCH 1/5] linux-user/flatload: clean up local variable shadowing

2023-09-25 Thread Laurent Vivier
Fix following warnings:

.../linux-user/flatload.c: In function 'load_flt_binary':
.../linux-user/flatload.c:758:23: warning: declaration of 'p' shadows a 
previous local [-Wshadow=compatible-local]
  758 | abi_ulong p;
  |   ^
../../../Projects/qemu/linux-user/flatload.c:722:15: note: shadowed declaration 
is here
  722 | abi_ulong p;
  |   ^

Signed-off-by: Laurent Vivier 
---
 linux-user/flatload.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/linux-user/flatload.c b/linux-user/flatload.c
index 4331a11bf010..fdcc4610fa30 100644
--- a/linux-user/flatload.c
+++ b/linux-user/flatload.c
@@ -755,15 +755,15 @@ int load_flt_binary(struct linux_binprm *bprm, struct 
image_info *info)
 /* Update data segment pointers for all libraries */
 for (i=0; i

[PATCH 2/5] linux-user/mmap.c: clean up local variable shadowing

2023-09-25 Thread Laurent Vivier
Fix following warnings:

.../linux-user/mmap.c: In function 'target_mremap':
.../linux-user/mmap.c:913:13: warning: declaration of 'prot' shadows a previous 
local [-Wshadow=compatible-local]
  913 | int prot = 0;
  | ^~~~
../../../Projects/qemu/linux-user/mmap.c:871:9: note: shadowed declaration is 
here
  871 | int prot;
  | ^~~~

Signed-off-by: Laurent Vivier 
---
 linux-user/mmap.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index 8eaf57b208b0..8ccaab78590f 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -910,16 +910,16 @@ abi_long target_mremap(abi_ulong old_addr, abi_ulong 
old_size,
 }
 }
 } else {
-int prot = 0;
+int page_flags = 0;
 if (reserved_va && old_size < new_size) {
 abi_ulong addr;
 for (addr = old_addr + old_size;
  addr < old_addr + new_size;
  addr++) {
-prot |= page_get_flags(addr);
+page_flags |= page_get_flags(addr);
 }
 }
-if (prot == 0) {
+if (page_flags == 0) {
 host_addr = mremap(g2h_untagged(old_addr),
old_size, new_size, flags);
 
-- 
2.41.0




[PATCH 0/5] linux-user: clean up local variable shadowing

2023-09-25 Thread Laurent Vivier



Laurent Vivier (5):
  linux-user/flatload: clean up local variable shadowing
  linux-user/mmap.c:  clean up local variable shadowing
  linux-user/syscall.c: clean up local variable shadowing in
do_ioctl_dm()
  linux-user/syscall.c: clean up local variable shadowing in
TARGET_NR_getcpu
  linux-user/syscall.c: clean up local variable shadowing in xattr
syscalls

 linux-user/flatload.c |  8 
 linux-user/mmap.c |  6 +++---
 linux-user/syscall.c  | 36 ++--
 3 files changed, 25 insertions(+), 25 deletions(-)

-- 
2.41.0




[PATCH] disas/m68k: clean up local variable shadowing

2023-09-25 Thread Laurent Vivier
Fix following warnings

.../disas/m68k.c: In function ‘print_insn_arg’:
.../disas/m68k.c:1635:13: warning: declaration of ‘val’ shadows a previous 
local [-Wshadow=compatible-local]
 1635 | int val = fetch_arg (buffer, place, 5, info);
  | ^~~
.../disas/m68k.c:1093:7: note: shadowed declaration is here
 1093 |   int val = 0;
  |   ^~~

Signed-off-by: Laurent Vivier 
---
 disas/m68k.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/disas/m68k.c b/disas/m68k.c
index aefaecfbd6cb..1f16e295ab41 100644
--- a/disas/m68k.c
+++ b/disas/m68k.c
@@ -1632,10 +1632,10 @@ print_insn_arg (const char *d,
 case '2':
 case '3':
   {
-   int val = fetch_arg (buffer, place, 5, info);
+   int reg = fetch_arg (buffer, place, 5, info);
 const char *name = 0;
 
-   switch (val)
+   switch (reg)
  {
  case 2: name = "%tt0"; break;
  case 3: name = "%tt1"; break;
@@ -1655,12 +1655,12 @@ print_insn_arg (const char *d,
  int break_reg = ((buffer[3] >> 2) & 7);
 
  (*info->fprintf_func)
-   (info->stream, val == 0x1c ? "%%bad%d" : "%%bac%d",
+   (info->stream, reg == 0x1c ? "%%bad%d" : "%%bac%d",
 break_reg);
}
break;
  default:
-   (*info->fprintf_func) (info->stream, "", val);
+   (*info->fprintf_func) (info->stream, "", reg);
  }
if (name)
  (*info->fprintf_func) (info->stream, "%s", name);
-- 
2.41.0




Re: [PATCH] tests/qtest/netdev-socket: Raise connection timeout to 120 seconds

2023-09-12 Thread Laurent Vivier

On 9/12/23 15:42, Daniel P. Berrangé wrote:

On Tue, Sep 12, 2023 at 09:33:10AM -0400, Stefan Hajnoczi wrote:

The test still fails intermittently with a 60 second timeout in the
GitLab CI environment. Raise the timeout to 120 seconds.

   576/839 ERROR:../tests/qtest/netdev-socket.c:293:test_stream_unix: assertion failed (resp == 
expect): ("st0: index=0,type=stream,connection error\r\n" == "st0: 
index=0,type=stream,unix:/tmp/netdev-socket.UW5IA2/stream_unix\r\n") ERROR
   576/839 qemu:qtest+qtest-sh4 / qtest-sh4/netdev-socket   
 ERROR  62.85s   killed by signal 6 SIGABRT
   >>> MALLOC_PERTURB_=249 QTEST_QEMU_BINARY=./qemu-system-sh4 
QTEST_QEMU_STORAGE_DAEMON_BINARY=./storage-daemon/qemu-storage-daemon 
G_TEST_DBUS_DAEMON=/home/gitlab-runner/builds/-LCfcJ2T/0/qemu-project/qemu/tests/dbus-vmstate-daemon.sh
 QTEST_QEMU_IMG=./qemu-img 
/home/gitlab-runner/builds/-LCfcJ2T/0/qemu-project/qemu/build/tests/qtest/netdev-socket 
--tap -k
   ― ✀  
―
   stderr:
   **
   ERROR:../tests/qtest/netdev-socket.c:293:test_stream_unix: assertion failed (resp == expect): 
("st0: index=0,type=stream,connection error\r\n" == "st0: 
index=0,type=stream,unix:/tmp/netdev-socket.UW5IA2/stream_unix\r\n")
   (test program exited with status code -6)

Buglink: https://gitlab.com/qemu-project/qemu/-/issues/1881
Fixes: 417296c8d858 ("tests/qtest/netdev-socket: Raise connection timeout to 60 
seconds")
Signed-off-by: Stefan Hajnoczi 


That bumped the timeout from 5 seconds to 60 seconds to
cope with intermittent failures, which was a x12
increases. I'm concerned that it would still be failing
in largely the same way after that, and possibly we are
instead hitting a race condition causing setup to fail,
which masquerades as a timeout.


---
  tests/qtest/netdev-socket.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/qtest/netdev-socket.c b/tests/qtest/netdev-socket.c
index 8eed54801f..b2501d72a1 100644
--- a/tests/qtest/netdev-socket.c
+++ b/tests/qtest/netdev-socket.c
@@ -16,7 +16,7 @@
  #include "qapi/qobject-input-visitor.h"
  #include "qapi/qapi-visit-sockets.h"
  
-#define CONNECTION_TIMEOUT60

+#define CONNECTION_TIMEOUT120
  
  #define EXPECT_STATE(q, e, t) \

  do {  \


I'll add

Reviewed-by: Daniel P. Berrangé 

but with the caveat that i'm only 50/50 on whether this is actually
the right fix. Doesn't hurt to try it, but if 120 seconds still shows
failures I'd say we're hitting a functional race not a timeout.


It can also happen if the first QEMU (server) crashes. Do we have some traces 
from this side?

Reviewed-by: Laurent Vivier 

Thanks,
Laurent




Re: [PATCH] tests/qtest/netdev-socket: Avoid variable-length array in inet_get_free_port_multiple()

2023-08-25 Thread Laurent Vivier

On 8/24/23 18:45, Peter Maydell wrote:

We use a variable-length array in inet_get_free_port_multiple().
This is only test code called at the start of a test, so switch to a
heap allocation instead.

The codebase has very few VLAs, and if we can get rid of them all we
can make the compiler error on new additions.  This is a defensive
measure against security bugs where an on-stack dynamic allocation
isn't correctly size-checked (e.g.  CVE-2021-3527).

Signed-off-by: Peter Maydell 
---
  tests/qtest/netdev-socket.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/qtest/netdev-socket.c b/tests/qtest/netdev-socket.c
index 097abc0230b..8eed54801f2 100644
--- a/tests/qtest/netdev-socket.c
+++ b/tests/qtest/netdev-socket.c
@@ -82,7 +82,7 @@ static int inet_get_free_port_socket_ipv6(int sock)
  
  static int inet_get_free_port_multiple(int nb, int *port, bool ipv6)

  {
-int sock[nb];
+g_autofree int *sock = g_new(int, nb);
  int i;
  
  for (i = 0; i < nb; i++) {


Reviewed-by: Laurent Vivier 




Re: Funny results with long double denorms on m68k

2023-08-21 Thread Laurent Vivier

Le 21/08/2023 à 10:34, Laurent Vivier a écrit :

Le 20/08/2023 à 22:55, Keith Packard a écrit :

#include 
#include 

#define X   0x1p+16383l
#define Y   0x1p-16446l

static long double build_mul = X * Y;
static volatile long double x = X;
static volatile long double y = Y;

static void
dump_ld(const char *label, long double ld)
{
 union {
 long double d;
 struct {
 uint32_t    exp:16;
 uint32_t    space:16;
 uint32_t    h;
 uint32_t    l;
 };
 } u;

 u.d = ld;
 printf("%12s: % -27La 0x%04x 0x%08x 0x%08x\n", label, u.d, u.exp, u.h, 
u.l);
}

int main(void)
{
 long double runtime_mul = x * y;

 dump_ld("x", x);
 dump_ld("y", y);
 dump_ld("build_mul", build_mul);
 dump_ld("runtime_mul", runtime_mul);
 return 0;
}


FYI, result of this program on a real hardware (q800/m68040) is:

    x:  0x8p+16380 0x7ffe 0x8000 0x
    y:  0x0.001p-16386 0x 0x 0x0001
    build_mul:  0x8p-66    0x3fc0 0x8000 0x
  runtime_mul:  0x8p-66    0x3fc0 0x8000 0x



When I developped the FPU emulation I compared the result of QEMU and a real hardware using 
https://github.com/vivier/m68k-testfloat and https://github.com/vivier/m68k-softfloat


Thanks,
Laurent




Re: Funny results with long double denorms on m68k

2023-08-21 Thread Laurent Vivier

Le 20/08/2023 à 22:55, Keith Packard a écrit :

#include 
#include 

#define X   0x1p+16383l
#define Y   0x1p-16446l

static long double build_mul = X * Y;
static volatile long double x = X;
static volatile long double y = Y;

static void
dump_ld(const char *label, long double ld)
{
 union {
 long double d;
 struct {
 uint32_texp:16;
 uint32_tspace:16;
 uint32_th;
 uint32_tl;
 };
 } u;

 u.d = ld;
 printf("%12s: % -27La 0x%04x 0x%08x 0x%08x\n", label, u.d, u.exp, u.h, 
u.l);
}

int main(void)
{
 long double runtime_mul = x * y;

 dump_ld("x", x);
 dump_ld("y", y);
 dump_ld("build_mul", build_mul);
 dump_ld("runtime_mul", runtime_mul);
 return 0;
}


FYI, result of this program on a real hardware (q800/m68040) is:

   x:  0x8p+16380 0x7ffe 0x8000 0x
   y:  0x0.001p-16386 0x 0x 0x0001
   build_mul:  0x8p-660x3fc0 0x8000 0x
 runtime_mul:  0x8p-660x3fc0 0x8000 0x

Thanks,
Laurent



Re: [PATCH] hw: Add compat machines for 8.2

2023-07-21 Thread Laurent Vivier
E_CLASS(m);
  
  pc_q35_8_1_machine_options(m);

-m->alias = NULL;
  compat_props_add(m->compat_props, hw_compat_8_0, hw_compat_8_0_len);
  compat_props_add(m->compat_props, pc_compat_8_0, pc_compat_8_0_len);
  
diff --git a/hw/m68k/virt.c b/hw/m68k/virt.c

index 731205b215b2..a0813f75c060 100644
--- a/hw/m68k/virt.c
+++ b/hw/m68k/virt.c
@@ -347,10 +347,17 @@ type_init(virt_machine_register_types)
  } \
  type_init(machvirt_machine_##major##_##minor##_init);
  
+static void virt_machine_8_2_options(MachineClass *mc)

+{
+}
+DEFINE_VIRT_MACHINE(8, 2, true)
+
  static void virt_machine_8_1_options(MachineClass *mc)
  {
+virt_machine_8_2_options(mc);
+compat_props_add(mc->compat_props, hw_compat_8_1, hw_compat_8_1_len);
  }
-DEFINE_VIRT_MACHINE(8, 1, true)
+DEFINE_VIRT_MACHINE(8, 1, false)
  
  static void virt_machine_8_0_options(MachineClass *mc)

  {
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 1c8b8d57a70a..622fea825605 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -4752,15 +4752,26 @@ static void 
spapr_machine_latest_class_options(MachineClass *mc)
  }\
  type_init(spapr_machine_register_##suffix)
  
+/*

+ * pseries-8.2
+ */
+static void spapr_machine_8_2_class_options(MachineClass *mc)
+{
+/* Defaults for the latest behaviour inherited from the base class */
+}
+
+DEFINE_SPAPR_MACHINE(8_2, "8.2", true);
+
  /*
   * pseries-8.1
   */
  static void spapr_machine_8_1_class_options(MachineClass *mc)
  {
-/* Defaults for the latest behaviour inherited from the base class */
+spapr_machine_8_2_class_options(mc);
+compat_props_add(mc->compat_props, hw_compat_8_1, hw_compat_8_1_len);
  }
  
-DEFINE_SPAPR_MACHINE(8_1, "8.1", true);

+DEFINE_SPAPR_MACHINE(8_1, "8.1", false);
  
  /*

   * pseries-8.0
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index 4516d73ff5fc..c52a1fcf6700 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -828,14 +828,26 @@ bool css_migration_enabled(void)
  } 
\
  type_init(ccw_machine_register_##suffix)
  
+static void ccw_machine_8_2_instance_options(MachineState *machine)

+{
+}
+
+static void ccw_machine_8_2_class_options(MachineClass *mc)
+{
+}
+DEFINE_CCW_MACHINE(8_2, "8.2", true);
+
  static void ccw_machine_8_1_instance_options(MachineState *machine)
  {
+ccw_machine_8_2_instance_options(machine);
  }
  
  static void ccw_machine_8_1_class_options(MachineClass *mc)

  {
+ccw_machine_8_2_class_options(mc);
+compat_props_add(mc->compat_props, hw_compat_8_1, hw_compat_8_1_len);
  }
-DEFINE_CCW_MACHINE(8_1, "8.1", true);
+DEFINE_CCW_MACHINE(8_1, "8.1", false);
  
  static void ccw_machine_8_0_instance_options(MachineState *machine)

  {
diff --git a/include/hw/boards.h b/include/hw/boards.h
index ed8336019801..3b541ffd2472 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -390,6 +390,9 @@ struct MachineState {
  } \
  type_init(machine_initfn##_register_types)
  
+extern GlobalProperty hw_compat_8_1[];

+extern const size_t hw_compat_8_1_len;
+
  extern GlobalProperty hw_compat_8_0[];
  extern const size_t hw_compat_8_0_len;
  
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h

index d54e8b1101e4..0fabece236cf 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -200,6 +200,9 @@ void pc_madt_cpu_entry(int uid, const CPUArchIdList 
*apic_ids,
  /* sgx.c */
  void pc_machine_init_sgx_epc(PCMachineState *pcms);
  
+extern GlobalProperty pc_compat_8_1[];

+extern const size_t pc_compat_8_1_len;
+
  extern GlobalProperty pc_compat_8_0[];
  extern const size_t pc_compat_8_0_len;
  


For m68k part:
Acked-by: Laurent Vivier 



Re: [PATCH] Wrong unpacked structure for epoll_event on qemu-or1k (openrisc user-space)

2023-07-19 Thread Laurent Vivier

Le 18/07/2023 à 17:06, Luca Bonissi a écrit :

On 18/07/23 16:40, Peter Maydell wrote:

Hi; thanks for this patch. Unfortunately we need patches
to include a Signed-off-by: line that says you're legally
OK with it being contributed to QEMU, or we can't take them.


Sorry for the missing "signed-off-by" line, adding it just now:

==
The or1k epoll_event structure - unlike other architectures - is packed, so we need to define it as 
packed in qemu-user, otherwise it leads to infinite loop due to missing file descriptor in the 
returned data:



Signed-off-by: Luca Bonissi 
---

diff -up a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
--- a/linux-user/syscall_defs.h    2023-03-27 15:41:42.0 +0200
+++ b/linux-user/syscall_defs.h    2023-06-30 17:29:39.034322213 +0200
@@ -2714,7 +2709,7 @@
  #define FUTEX_CMD_MASK  ~(FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME)

  #ifdef CONFIG_EPOLL
-#if defined(TARGET_X86_64)
+#if defined(TARGET_X86_64) || defined(TARGET_OPENRISC)
  #define TARGET_EPOLL_PACKED QEMU_PACKED
  #else
  #define TARGET_EPOLL_PACKED


According to linux/glibc sourced, epoll is only packed for x86_64.

Did you try to check the alignment of the structure with gdb of a C program using offsetof() in an 
openrisc VM or linux-user container?


Perhaps the default alignment of long is not correctly defined in qemu for 
openrisc?

You can check with:

int main(void)
{
printf("alignof(short) %ld\n", __alignof__(short));
printf("alignof(int) %ld\n", __alignof__(int));
printf("alignof(long) %ld\n", __alignof__(long));
printf("alignof(long long) %ld\n", __alignof__(long long));
}

See include/exec/user/abitypes.h to update the value.

Thanks,
Laurent



Re: [PULL 35/47] linux-user: Use page_find_range_empty for mmap_find_vma_reserved

2023-07-18 Thread Laurent Vivier

Hi Richard,

thank you for the linux-user PR (I have really no time to do that).

I've  run the LTP test suite (20230127) on master and found some problems introduced by 
this patch.


With armhf and Debian bionic and stretch, brk01 brk02 recvmsg01 fail:

tst_test.c:1560: TINFO: Timeout per run is 0h 00m 30s
brk01.c:24: TINFO: Testing libc variant
brk01.c:54: TFAIL: brk() failed: ENOMEM (12)
brk01.c:61: TFAIL: brk() failed to set address have 0x40049000 expected 
0x4004afff
brk01.c:21: TINFO: Testing syscall variant
brk01.c:61: TFAIL: brk() failed to set address have 0x40049000 expected 
0x4004afff

tst_test.c:1560: TINFO: Timeout per run is 0h 00m 30s
brk02.c:42: TINFO: Testing libc variant
brk02.c:27: TFAIL: brk() failed: ENOMEM (12)
brk02.c:60: TFAIL: Cannot expand brk() by page size: ENOMEM (12)
brk02.c:39: TINFO: Testing syscall variant
brk02.c:60: TFAIL: Cannot expand brk() by page size: EFAULT (14)

recvmsg011  TPASS  :  bad file descriptor successful
recvmsg012  TPASS  :  invalid socket successful
recvmsg013  TPASS  :  invalid socket buffer successful
recvmsg014  TPASS  :  invalid socket length successful
recvmsg015  TPASS  :  invalid recv buffer successful
recvmsg016  TPASS  :  invalid iovec buffer successful
recvmsg017  TPASS  :  invalid iovec count successful
recvmsg018  TPASS  :  rights reception successful
recvmsg019  TPASS  :  invalid MSG_OOB flag set successful
recvmsg01   10  TPASS  :  invalid MSG_ERRQUEUE flag set successful
recvmsg01   11  TPASS  :  invalid cmsg length successful
recvmsg01   12  TFAIL  :  recvmsg01.c:236: large cmesg length ; returned -1 (expected 0), 
errno 14 (expected 0)


With mips/stretch and mipsel/stretch I have one more, sbrk01:

sbrk01  1  TFAIL  :  sbrk01.c:102: sbrk - Increase by 8192 bytes failed: 
TEST_ERRNO=ENOMEM(12): Cannot allocate memory

sbrk01  2  TPASS  :  sbrk - Increase by -8192 bytes returned 0x4005f000

Thanks,
Laurent

On 7/15/23 15:53, Richard Henderson wrote:

Use the interval tree to find empty space, rather than
probing each page in turn.

Signed-off-by: Richard Henderson 
Message-Id: <20230707204054.8792-19-richard.hender...@linaro.org>
---
  linux-user/mmap.c | 52 ++-
  1 file changed, 6 insertions(+), 46 deletions(-)

diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index c4b2515271..738b9b797d 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -318,55 +318,15 @@ unsigned long last_brk;
  static abi_ulong mmap_find_vma_reserved(abi_ulong start, abi_ulong size,
  abi_ulong align)
  {
-abi_ulong addr, end_addr, incr = qemu_host_page_size;
-int prot;
-bool looped = false;
+target_ulong ret;
  
-if (size > reserved_va) {

-return (abi_ulong)-1;
+ret = page_find_range_empty(start, reserved_va, size, align);
+if (ret == -1 && start > mmap_min_addr) {
+/* Restart at the beginning of the address space. */
+ret = page_find_range_empty(mmap_min_addr, start - 1, size, align);
  }
  
-/* Note that start and size have already been aligned by mmap_find_vma. */

-
-end_addr = start + size;
-/*
- * Start at the top of the address space, ignoring the last page.
- * If reserved_va == UINT32_MAX, then end_addr wraps to 0,
- * throwing the rest of the calculations off.
- * TODO: rewrite using last_addr instead.
- * TODO: use the interval tree instead of probing every page.
- */
-if (start > reserved_va - size) {
-end_addr = ((reserved_va - size) & -align) + size;
-looped = true;
-}
-
-/* Search downward from END_ADDR, checking to see if a page is in use.  */
-addr = end_addr;
-while (1) {
-addr -= incr;
-if (addr > end_addr) {
-if (looped) {
-/* Failure.  The entire address space has been searched.  */
-return (abi_ulong)-1;
-}
-/* Re-start at the top of the address space (see above). */
-addr = end_addr = ((reserved_va - size) & -align) + size;
-looped = true;
-} else {
-prot = page_get_flags(addr);
-if (prot) {
-/* Page in use.  Restart below this page.  */
-addr = end_addr = ((addr - size) & -align) + size;
-} else if (addr && addr + size == end_addr) {
-/* Success!  All pages between ADDR and END_ADDR are free.  */
-if (start == mmap_next_start) {
-mmap_next_start = addr;
-}
-return addr;
-}
-}
-}
+return ret;
  }
  
  /*





Re: [PATCH 06/21] q800: allow accesses to RAM area even if less memory is available

2023-07-05 Thread Laurent Vivier

Le 02/07/2023 à 17:48, Mark Cave-Ayland a écrit :

MacOS attempts a series of writes and reads over the entire RAM area in order
to determine the amount of RAM within the machine. Allow accesses to the
entire RAM area ignoring writes and always reading zero for areas where there
is no physical RAM installed to allow MacOS to detect the memory size without
faulting.

Signed-off-by: Mark Cave-Ayland 
---
  hw/m68k/q800.c | 30 +-
  include/hw/m68k/q800.h |  1 +
  2 files changed, 30 insertions(+), 1 deletion(-)

diff --git a/hw/m68k/q800.c b/hw/m68k/q800.c
index 081b95e9cf..3209309173 100644
--- a/hw/m68k/q800.c
+++ b/hw/m68k/q800.c
@@ -86,6 +86,9 @@
  
  #define MAC_CLOCK  3686418
  
+/* Size of whole RAM area */

+#define RAM_SIZE  0x4000
+
  /*
   * Slot 0x9 is reserved for use by the in-built framebuffer whilst only
   * slots 0xc, 0xd and 0xe physically exist on the Quadra 800
@@ -218,6 +221,27 @@ static const MemoryRegionOps machine_id_ops = {
  },
  };
  
+static uint64_t ramio_read(void *opaque, hwaddr addr, unsigned size)

+{
+return 0x0;
+}
+
+static void ramio_write(void *opaque, hwaddr addr, uint64_t val,
+unsigned size)
+{
+return;
+}
+
+static const MemoryRegionOps ramio_ops = {
+.read = ramio_read,
+.write = ramio_write,
+.endianness = DEVICE_BIG_ENDIAN,
+.valid = {
+.min_access_size = 1,
+.max_access_size = 4,
+},
+};
+
  static void q800_machine_init(MachineState *machine)
  {
  Q800MachineState *m = Q800_MACHINE(machine);
@@ -262,7 +286,11 @@ static void q800_machine_init(MachineState *machine)
  qemu_register_reset(main_cpu_reset, >cpu);
  
  /* RAM */

-memory_region_add_subregion(get_system_memory(), 0, machine->ram);
+memory_region_init_io(>ramio, OBJECT(machine), _ops, >ramio,
+  "ram", RAM_SIZE);
+memory_region_add_subregion(get_system_memory(), 0x0, >ramio);
+
+memory_region_add_subregion(>ramio, 0, machine->ram);
  
  /*

   * Create container for all IO devices
diff --git a/include/hw/m68k/q800.h b/include/hw/m68k/q800.h
index 98097165d9..04e4e0bce3 100644
--- a/include/hw/m68k/q800.h
+++ b/include/hw/m68k/q800.h
@@ -60,6 +60,7 @@ struct Q800MachineState {
  MacfbNubusState macfb;
  DJMEMCState djmemc;
  IOSBState iosb;
+MemoryRegion ramio;
  MemoryRegion macio;
  MemoryRegion macio_alias;
  MemoryRegion machine_id;


Reviewed-by: Laurent Vivier 



Re: [PATCH v2 1/1] vhost-vdpa: mute unaligned memory error report

2023-07-04 Thread Laurent Vivier

On 7/4/23 09:25, David Hildenbrand wrote:

On 04.07.23 09:19, Laurent Vivier wrote:

With TPM CRM device, vhost-vdpa reports an error when it tries
to register a listener for a non aligned memory region:

   qemu-system-x86_64: vhost_vdpa_listener_region_add received unaligned region
   qemu-system-x86_64: vhost_vdpa_listener_region_del received unaligned region

This error can be confusing for the user whereas we only need to skip
the region (as it's already done after the error_report())

Rather than introducing a special case for TPM CRB memory section
to not display the message in this case, simply replace the
error_report() by a trace function (with more information, like the
memory region name).

Signed-off-by: Laurent Vivier 
---
  hw/virtio/trace-events | 2 ++
  hw/virtio/vhost-vdpa.c | 8 ++--
  2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events
index 8f8d05cf9b01..9b0d643b9475 100644
--- a/hw/virtio/trace-events
+++ b/hw/virtio/trace-events
@@ -34,7 +34,9 @@ vhost_vdpa_dma_map(void *vdpa, int fd, uint32_t msg_type, uint32_t 
asid, uint64_
  vhost_vdpa_dma_unmap(void *vdpa, int fd, uint32_t msg_type, uint32_t asid, uint64_t 
iova, uint64_t size, uint8_t type) "vdpa:%p fd: %d msg_type: %"PRIu32" asid: %"PRIu32" 
iova: 0x%"PRIx64" size: 0x%"PRIx64" type: %"PRIu8
  vhost_vdpa_listener_begin_batch(void *v, int fd, uint32_t msg_type, uint8_t type)  
"vdpa:%p fd: %d msg_type: %"PRIu32" type: %"PRIu8
  vhost_vdpa_listener_commit(void *v, int fd, uint32_t msg_type, uint8_t type)  "vdpa:%p 
fd: %d msg_type: %"PRIu32" type: %"PRIu8
+vhost_vdpa_listener_region_add_unaligned(void *v, const char *name, uint64_t offset_as, 
uint64_t offset_page) "vdpa: %p region %s offset_within_address_space %"PRIu64" 
offset_within_region %"PRIu64
  vhost_vdpa_listener_region_add(void *vdpa, uint64_t iova, uint64_t llend, void *vaddr, 
bool readonly) "vdpa: %p iova 0x%"PRIx64" llend 0x%"PRIx64" vaddr: %p read-only: %d"
+vhost_vdpa_listener_region_del_unaligned(void *v, const char *name, uint64_t offset_as, 
uint64_t offset_page) "vdpa: %p region %s offset_within_address_space %"PRIu64" 
offset_within_region %"PRIu64
  vhost_vdpa_listener_region_del(void *vdpa, uint64_t iova, uint64_t llend) "vdpa: %p 
iova 0x%"PRIx64" llend 0x%"PRIx64

  vhost_vdpa_add_status(void *dev, uint8_t status) "dev: %p status: 0x%"PRIx8
  vhost_vdpa_init(void *dev, void *vdpa) "dev: %p vdpa: %p"
diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c
index 3c575a9a6e9e..24d32f0d3728 100644
--- a/hw/virtio/vhost-vdpa.c
+++ b/hw/virtio/vhost-vdpa.c
@@ -323,7 +323,9 @@ static void vhost_vdpa_listener_region_add(MemoryListener 
*listener,
  if (unlikely((section->offset_within_address_space & ~TARGET_PAGE_MASK) !=
   (section->offset_within_region & ~TARGET_PAGE_MASK))) {
-    error_report("%s received unaligned region", __func__);
+    trace_vhost_vdpa_listener_region_add_unaligned(v, section->mr->name,
+   section->offset_within_address_space & 
~TARGET_PAGE_MASK,
+   section->offset_within_region & ~TARGET_PAGE_MASK);
  return;
  }
@@ -405,7 +407,9 @@ static void vhost_vdpa_listener_region_del(MemoryListener 
*listener,
  if (unlikely((section->offset_within_address_space & ~TARGET_PAGE_MASK) !=
   (section->offset_within_region & ~TARGET_PAGE_MASK))) {
-    error_report("%s received unaligned region", __func__);
+    trace_vhost_vdpa_listener_region_del_unaligned(v, section->mr->name,
+   section->offset_within_address_space & 
~TARGET_PAGE_MASK,
+   section->offset_within_region & ~TARGET_PAGE_MASK);
  return;
  }


Reviewed-by: David Hildenbrand 


Do we also want to touch the vfio side in vfio_listener_valid_section(), or why is that 
one unaffected?




I don't know if we can apply the same solution for VFIO.
I don't know if the error message is relevant or if we can keep only the trace and remove 
the error_report() for all the cases (in this case vfio_known_safe_misalignment() becomes 
useless).


Thanks,
Laurent




[PATCH v2 0/1] vhost-vdpa: skip TPM CRB memory section

2023-07-04 Thread Laurent Vivier
An error is reported for vhost-vdpa case:
qemu-kvm: vhost_vdpa_listener_region_add received unaligned region

Marc-André has proposed a fix to this problem by skipping
the memory region owned by the TPM CRB but it seems more generic
to skip not aligned memory.

v1 of this series proposed to set the RAM_PROTECTED flag for the
TPM CRB memory region.

v2:
  - do not introduce special case for TPM CRB
  - do not set RAM_PROTECTED flag for TPM CRB
  - remove error_report() and replace it with a trace

For the previous discussions, see

https://lists.nongnu.org/archive/html/qemu-devel/2022-11/msg03670.html

and from Eric for VFIO:

https://lore.kernel.org/all/20220506132510.1847942-1-eric.au...@redhat.com/
https://lore.kernel.org/all/20220524091405.416256-1-eric.au...@redhat.com/

Bug: https://bugzilla.redhat.com/show_bug.cgi?id=2141965

Thanks,
Laurent

Laurent Vivier (1):
  vhost-vdpa: mute unaligned memory error report

 hw/virtio/trace-events | 2 ++
 hw/virtio/vhost-vdpa.c | 8 ++--
 2 files changed, 8 insertions(+), 2 deletions(-)

-- 
2.41.0




[PATCH v2 1/1] vhost-vdpa: mute unaligned memory error report

2023-07-04 Thread Laurent Vivier
With TPM CRM device, vhost-vdpa reports an error when it tries
to register a listener for a non aligned memory region:

  qemu-system-x86_64: vhost_vdpa_listener_region_add received unaligned region
  qemu-system-x86_64: vhost_vdpa_listener_region_del received unaligned region

This error can be confusing for the user whereas we only need to skip
the region (as it's already done after the error_report())

Rather than introducing a special case for TPM CRB memory section
to not display the message in this case, simply replace the
error_report() by a trace function (with more information, like the
memory region name).

Signed-off-by: Laurent Vivier 
---
 hw/virtio/trace-events | 2 ++
 hw/virtio/vhost-vdpa.c | 8 ++--
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events
index 8f8d05cf9b01..9b0d643b9475 100644
--- a/hw/virtio/trace-events
+++ b/hw/virtio/trace-events
@@ -34,7 +34,9 @@ vhost_vdpa_dma_map(void *vdpa, int fd, uint32_t msg_type, 
uint32_t asid, uint64_
 vhost_vdpa_dma_unmap(void *vdpa, int fd, uint32_t msg_type, uint32_t asid, 
uint64_t iova, uint64_t size, uint8_t type) "vdpa:%p fd: %d msg_type: %"PRIu32" 
asid: %"PRIu32" iova: 0x%"PRIx64" size: 0x%"PRIx64" type: %"PRIu8
 vhost_vdpa_listener_begin_batch(void *v, int fd, uint32_t msg_type, uint8_t 
type)  "vdpa:%p fd: %d msg_type: %"PRIu32" type: %"PRIu8
 vhost_vdpa_listener_commit(void *v, int fd, uint32_t msg_type, uint8_t type)  
"vdpa:%p fd: %d msg_type: %"PRIu32" type: %"PRIu8
+vhost_vdpa_listener_region_add_unaligned(void *v, const char *name, uint64_t 
offset_as, uint64_t offset_page) "vdpa: %p region %s 
offset_within_address_space %"PRIu64" offset_within_region %"PRIu64
 vhost_vdpa_listener_region_add(void *vdpa, uint64_t iova, uint64_t llend, void 
*vaddr, bool readonly) "vdpa: %p iova 0x%"PRIx64" llend 0x%"PRIx64" vaddr: %p 
read-only: %d"
+vhost_vdpa_listener_region_del_unaligned(void *v, const char *name, uint64_t 
offset_as, uint64_t offset_page) "vdpa: %p region %s 
offset_within_address_space %"PRIu64" offset_within_region %"PRIu64
 vhost_vdpa_listener_region_del(void *vdpa, uint64_t iova, uint64_t llend) 
"vdpa: %p iova 0x%"PRIx64" llend 0x%"PRIx64
 vhost_vdpa_add_status(void *dev, uint8_t status) "dev: %p status: 0x%"PRIx8
 vhost_vdpa_init(void *dev, void *vdpa) "dev: %p vdpa: %p"
diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c
index 3c575a9a6e9e..24d32f0d3728 100644
--- a/hw/virtio/vhost-vdpa.c
+++ b/hw/virtio/vhost-vdpa.c
@@ -323,7 +323,9 @@ static void vhost_vdpa_listener_region_add(MemoryListener 
*listener,
 
 if (unlikely((section->offset_within_address_space & ~TARGET_PAGE_MASK) !=
  (section->offset_within_region & ~TARGET_PAGE_MASK))) {
-error_report("%s received unaligned region", __func__);
+trace_vhost_vdpa_listener_region_add_unaligned(v, section->mr->name,
+   section->offset_within_address_space & 
~TARGET_PAGE_MASK,
+   section->offset_within_region & ~TARGET_PAGE_MASK);
 return;
 }
 
@@ -405,7 +407,9 @@ static void vhost_vdpa_listener_region_del(MemoryListener 
*listener,
 
 if (unlikely((section->offset_within_address_space & ~TARGET_PAGE_MASK) !=
  (section->offset_within_region & ~TARGET_PAGE_MASK))) {
-error_report("%s received unaligned region", __func__);
+trace_vhost_vdpa_listener_region_del_unaligned(v, section->mr->name,
+   section->offset_within_address_space & 
~TARGET_PAGE_MASK,
+   section->offset_within_region & ~TARGET_PAGE_MASK);
 return;
 }
 
-- 
2.41.0




Re: [PATCH 2/2] tpm_crb: mark memory as protected

2023-07-04 Thread Laurent Vivier

Hi,

as the region is already skipped by the test of the memory region alignment, I'm going to 
update my patches by only removing the error_report() as proposed by Peter.


I will replace it by a trace to help to debug.

Thanks,
Laurent

On 7/4/23 05:07, Jason Wang wrote:

On Thu, Jun 22, 2023 at 9:39 PM Laurent Vivier  wrote:


On 6/22/23 15:12, Peter Maydell wrote:

On Tue, 20 Jun 2023 at 20:51, Laurent Vivier  wrote:


This memory is not correctly aligned and cannot be registered
by vDPA and VFIO.


Isn't this a vDPA/VFIO problem? There's no requirement
for RAM MemoryRegions to be aligned in any way.


It's more about the limitation of the IOMMU which can't do subpage protection.


Code
that doesn't want to work with small or weirdly aligned
regions should skip them if that's the right behaviour
for that particular code IMHO.


We had already had this:

 if ((!memory_region_is_ram(section->mr) &&
  !memory_region_is_iommu(section->mr)) ||
 memory_region_is_protected(section->mr) ||
 /* vhost-vDPA doesn't allow MMIO to be mapped  */
 memory_region_is_ram_device(section->mr)) {
 return true;
 }





Marc-André proposed to modify vDPA code to skip the region but Michal disagreed:

https://lists.nongnu.org/archive/html/qemu-devel/2022-11/msg03670.html

No one wants the modification, so the problem cannot be fixed.



Yes, otherwise we end up with explicit check for TPM crb in vhost code...

Thanks


Thanks,
Laurent








Re: [PATCH 2/2] tpm_crb: mark memory as protected

2023-06-22 Thread Laurent Vivier

On 6/22/23 15:12, Peter Maydell wrote:

On Tue, 20 Jun 2023 at 20:51, Laurent Vivier  wrote:


This memory is not correctly aligned and cannot be registered
by vDPA and VFIO.


Isn't this a vDPA/VFIO problem? There's no requirement
for RAM MemoryRegions to be aligned in any way. Code
that doesn't want to work with small or weirdly aligned
regions should skip them if that's the right behaviour
for that particular code IMHO.



Marc-André proposed to modify vDPA code to skip the region but Michal disagreed:

https://lists.nongnu.org/archive/html/qemu-devel/2022-11/msg03670.html

No one wants the modification, so the problem cannot be fixed.

Thanks,
Laurent




Re: [PATCH 2/2] tpm_crb: mark memory as protected

2023-06-22 Thread Laurent Vivier

On 6/21/23 11:13, David Hildenbrand wrote:

On 20.06.23 21:50, Laurent Vivier wrote:

This memory is not correctly aligned and cannot be registered
by vDPA and VFIO.

An error is reported for vhost-vdpa case:
qemu-kvm: vhost_vdpa_listener_region_add received unaligned region

To make it ignored by VFIO and vDPA devices, mark it as RAM_PROTECTED.


So, VFIO will simply skip these sections via vfio_listener_valid_section() I 
guess.

Yes, it will report an error but it will happily continue.

So regarding vDPA, we're also only concerned about removing the reported error, everything 
else works as expected?




Yes, it has been tested and vDPA works as expected.

Thanks,
Laurent




[PULL 22/24] q800: move macfb device to Q800MachineState

2023-06-22 Thread Laurent Vivier
From: Mark Cave-Ayland 

Also change the instantiation of the macfb device to use 
object_initialize_child().

Signed-off-by: Mark Cave-Ayland 
Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Laurent Vivier 
Message-Id: <20230621085353.113233-23-mark.cave-ayl...@ilande.co.uk>
Signed-off-by: Laurent Vivier 
---
 include/hw/m68k/q800.h | 2 ++
 hw/m68k/q800.c | 6 --
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/include/hw/m68k/q800.h b/include/hw/m68k/q800.h
index 8f2c572a81e0..b3d77f1cba6e 100644
--- a/include/hw/m68k/q800.h
+++ b/include/hw/m68k/q800.h
@@ -35,6 +35,7 @@
 #include "hw/scsi/esp.h"
 #include "hw/block/swim.h"
 #include "hw/nubus/mac-nubus-bridge.h"
+#include "hw/display/macfb.h"
 
 /*
  * The main Q800 machine
@@ -54,6 +55,7 @@ struct Q800MachineState {
 SysBusESPState esp;
 Swim swim;
 MacNubusBridge mac_nubus_bridge;
+MacfbNubusState macfb;
 MemoryRegion macio;
 MemoryRegion macio_alias;
 };
diff --git a/hw/m68k/q800.c b/hw/m68k/q800.c
index a32e6fbf8dec..b770b71d5475 100644
--- a/hw/m68k/q800.c
+++ b/hw/m68k/q800.c
@@ -452,7 +452,9 @@ static void q800_machine_init(MachineState *machine)
 
 /* framebuffer in nubus slot #9 */
 
-dev = qdev_new(TYPE_NUBUS_MACFB);
+object_initialize_child(OBJECT(machine), "macfb", >macfb,
+TYPE_NUBUS_MACFB);
+dev = DEVICE(>macfb);
 qdev_prop_set_uint32(dev, "slot", 9);
 qdev_prop_set_uint32(dev, "width", graphic_width);
 qdev_prop_set_uint32(dev, "height", graphic_height);
@@ -462,7 +464,7 @@ static void q800_machine_init(MachineState *machine)
 } else {
 qdev_prop_set_uint8(dev, "display", MACFB_DISPLAY_VGA);
 }
-qdev_realize_and_unref(dev, BUS(nubus), _fatal);
+qdev_realize(dev, BUS(nubus), _fatal);
 
 macfb_mode = (NUBUS_MACFB(dev)->macfb).mode;
 
-- 
2.40.1




[PULL 02/24] q800: add missing space after parent object in GLUEState

2023-06-22 Thread Laurent Vivier
From: Mark Cave-Ayland 

This brings GLUEState in line with our current QOM guidelines.

Signed-off-by: Mark Cave-Ayland 
Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Laurent Vivier 
Message-Id: <20230621085353.113233-3-mark.cave-ayl...@ilande.co.uk>
Signed-off-by: Laurent Vivier 
---
 hw/m68k/q800.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/hw/m68k/q800.c b/hw/m68k/q800.c
index dda57c60bfd9..465c510c186e 100644
--- a/hw/m68k/q800.c
+++ b/hw/m68k/q800.c
@@ -100,6 +100,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(GLUEState, GLUE)
 
 struct GLUEState {
 SysBusDevice parent_obj;
+
 M68kCPU *cpu;
 uint8_t ipr;
 uint8_t auxmode;
-- 
2.40.1




  1   2   3   4   5   6   7   8   9   10   >