Re: [PATCH] virtiofsd: Add qemu version and copyright info

2021-03-07 Thread Sergio Lopez
On Wed, Mar 03, 2021 at 02:53:39PM -0500, Vivek Goyal wrote:
> Option "-V" currently displays the fuse protocol version virtiofsd is
> using. For example, I see this.
> 
> $ ./virtiofsd -V
> "using FUSE kernel interface version 7.33"
> 
> People also want to know software version of virtiofsd so that they can
> figure out if a certain fix is part of currently running virtiofsd or
> not. Eric Ernst ran into this issue.
> 
> David Gilbert thinks that it probably is best that we simply carry the
> qemu version and display that information given we are part of qemu
> tree. 
> 
> So this patch enhances version information and also adds qemu version
> and copyright info. Not sure if copyright information is supposed
> to be displayed along with version info. Given qemu-storage-daemon
> and other utilities are doing it, so I continued with same pattern.
> This is how now output looks like.
> 
> $ ./virtiofsd -V
> virtiofsd version 5.2.50 (v5.2.0-2357-gcbcf09872a-dirty)
> Copyright (c) 2003-2020 Fabrice Bellard and the QEMU Project developers
> using FUSE kernel interface version 7.33
> 
> Reported-by: Eric Ernst 
> Signed-off-by: Vivek Goyal 
> ---
>  tools/virtiofsd/passthrough_ll.c |8 
>  1 file changed, 8 insertions(+)

Reviewed-by: Sergio Lopez 

> Index: rhvgoyal-qemu/tools/virtiofsd/passthrough_ll.c
> ===
> --- rhvgoyal-qemu.orig/tools/virtiofsd/passthrough_ll.c   2021-03-03 
> 14:28:04.893672524 -0500
> +++ rhvgoyal-qemu/tools/virtiofsd/passthrough_ll.c2021-03-03 
> 14:37:29.381712706 -0500
> @@ -37,6 +37,8 @@
>  
>  #include "qemu/osdep.h"
>  #include "qemu/timer.h"
> +#include "qemu-version.h"
> +#include "qemu-common.h"
>  #include "fuse_virtio.h"
>  #include "fuse_log.h"
>  #include "fuse_lowlevel.h"
> @@ -3591,6 +3593,11 @@ static void fuse_lo_data_cleanup(struct
>  free(lo->source);
>  }
>  
> +static void qemu_version(void)
> +{
> +printf("virtiofsd version " QEMU_FULL_VERSION "\n" QEMU_COPYRIGHT "\n");
> +}
> +
>  int main(int argc, char *argv[])
>  {
>  struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
> @@ -3662,6 +3669,7 @@ int main(int argc, char *argv[])
>  ret = 0;
>  goto err_out1;
>  } else if (opts.show_version) {
> +qemu_version();
>  fuse_lowlevel_version();
>  ret = 0;
>  goto err_out1;
> 
> 


signature.asc
Description: PGP signature


Re: [PATCH v3 2/5] tests/acceptance/boot_linux_console: remove Armbian 19.11.3 bionic test for orangepi-pc machine

2021-03-07 Thread Philippe Mathieu-Daudé
On 3/5/21 4:16 PM, Willian Rampazzo wrote:
> On Thu, Mar 4, 2021 at 5:44 PM Niek Linnenbank  
> wrote:
>>
>> The image for Armbian 19.11.3 bionic has been removed from the armbian 
>> server.
>> Without the image as input the test arm_orangepi_bionic_19_11 cannot run.
>>
>> This commit removes the test completely and merges the code of the generic 
>> function
>> do_test_arm_orangepi_uboot_armbian back with the 20.08 test.
>>
>> Signed-off-by: Niek Linnenbank 
>> ---
>>  tests/acceptance/boot_linux_console.py | 72 --
>>  1 file changed, 23 insertions(+), 49 deletions(-)
>>
>> diff --git a/tests/acceptance/boot_linux_console.py 
>> b/tests/acceptance/boot_linux_console.py
>> index eb01286799..9fadea9958 100644
>> --- a/tests/acceptance/boot_linux_console.py
>> +++ b/tests/acceptance/boot_linux_console.py
>> @@ -802,7 +802,29 @@ def test_arm_orangepi_sd(self):
>>  # Wait for VM to shut down gracefully
>>  self.vm.wait()
>>
>> -def do_test_arm_orangepi_uboot_armbian(self, image_path):
>> +@skipUnless(os.getenv('ARMBIAN_ARTIFACTS_CACHED'),
>> +'Test artifacts fetched from unreliable apt.armbian.com')
>> +@skipUnless(os.getenv('AVOCADO_ALLOW_LARGE_STORAGE'), 'storage limited')
>> +def test_arm_orangepi_bionic_20_08(self):
>> +"""
>> +:avocado: tags=arch:arm
>> +:avocado: tags=machine:orangepi-pc
>> +:avocado: tags=device:sd
>> +"""
>> +
>> +# This test download a 275 MiB compressed image and expand it
>> +# to 1036 MiB, but the underlying filesystem is 1552 MiB...
>> +# As we expand it to 2 GiB we are safe.
>> +
>> +image_url = ('https://dl.armbian.com/orangepipc/archive/'
>> + 
>> 'Armbian_20.08.1_Orangepipc_bionic_current_5.8.5.img.xz')
> 
> The Armbian 20 is not available on this link anymore. I can browse just 21.

Cat-and-mouse game *sigh*.




Re: [PATCH v3 4/5] tests/acceptance: update sunxi kernel from armbian to 5.10.16

2021-03-07 Thread Philippe Mathieu-Daudé
On 3/5/21 4:04 PM, Willian Rampazzo wrote:
> On Thu, Mar 4, 2021 at 5:45 PM Niek Linnenbank  
> wrote:
>>
>> The linux kernel 4.20.7 binary for sunxi has been removed from 
>> apt.armbian.com:
>>
>>   $ ARMBIAN_ARTIFACTS_CACHED=yes AVOCADO_ALLOW_LARGE_STORAGE=yes avocado 
>> --show=app,console run -t machine:orangepi-pc 
>> tests/acceptance/boot_linux_console.py
>>   Fetching asset from 
>> tests/acceptance/boot_linux_console.py:BootLinuxConsole.test_arm_orangepi
>>   ...
>>   (1/6) 
>> tests/acceptance/boot_linux_console.py:BootLinuxConsole.test_arm_orangepi:
>> CANCEL: Missing asset 
>> https://apt.armbian.com/pool/main/l/linux-4.20.7-sunxi/linux-image-dev-sunxi_5.75_armhf.deb
>>  (0.55 s)
>>
>> This commit updates the sunxi kernel to 5.10.16 for the acceptance
>> tests of the orangepi-pc and cubieboard machines.
>>
>> Signed-off-by: Niek Linnenbank 
>> ---
>>  tests/acceptance/boot_linux_console.py | 40 +-
>>  tests/acceptance/replay_kernel.py  |  8 +++---
>>  2 files changed, 24 insertions(+), 24 deletions(-)
>>
> 
> I think some devs will not like it,
Maybe you refer to my previous NACKs regarding similar changes in
integration tests. Niek is the author of the test and the maintainer
of the machine, so if he is OK to stop testing the 4.20.7 kernels
and test the 5.10.16 from now on, I won't object.

> but, for me, it is fine as we
> don't have the old kernel available anymore:
> 
> Reviewed-by: Willian Rampazzo 
> 




Re: [PATCH v5 4/5] m68k: add a system controller

2021-03-07 Thread Laurent Vivier
Le 08/03/2021 à 08:30, Philippe Mathieu-Daudé a écrit :
> On 3/7/21 9:56 PM, Laurent Vivier wrote:
>> Add a system controller for the m68k-virt machine.
>> This controller allows the kernel to power off or reset the machine.
>>
>> Signed-off-by: Laurent Vivier 
>> Reviewed-by: Richard Henderson 
>> ---
>>  include/hw/misc/m68k_virt_ctrl.h |  22 +
>>  hw/misc/m68k_virt_ctrl.c | 152 +++
>>  hw/misc/Kconfig  |   3 +
>>  hw/misc/meson.build  |   3 +
>>  hw/misc/trace-events |   7 ++
>>  5 files changed, 187 insertions(+)
>>  create mode 100644 include/hw/misc/m68k_virt_ctrl.h
>>  create mode 100644 hw/misc/m68k_virt_ctrl.c
>>
>> diff --git a/include/hw/misc/m68k_virt_ctrl.h 
>> b/include/hw/misc/m68k_virt_ctrl.h
>> new file mode 100644
>> index ..1db7960e5477
>> --- /dev/null
>> +++ b/include/hw/misc/m68k_virt_ctrl.h
>> @@ -0,0 +1,22 @@
>> +/*
>> + * SPDX-License-Identifer: GPL-2.0-or-later
>> + *
>> + * Virt m68k system Controller
>> + */
>> +
>> +#ifndef M68K_VIRT_CTRL_H
>> +#define M68K_VIRT_CTRL_H
>> +
>> +#define TYPE_M68K_VIRT_CTRL "m68k-virt-ctrl"
>> +OBJECT_DECLARE_SIMPLE_TYPE(M68KVirtCtrlState, M68K_VIRT_CTRL)
>> +
>> +struct M68KVirtCtrlState {
>> +SysBusDevice parent_obj;
>> +
>> +MemoryRegion iomem;
>> +qemu_irq irq;
>> +
>> +uint32_t irq_enabled;
>> +};
>> +
>> +#endif
>> diff --git a/hw/misc/m68k_virt_ctrl.c b/hw/misc/m68k_virt_ctrl.c
>> new file mode 100644
>> index ..fb34aa10211a
>> --- /dev/null
>> +++ b/hw/misc/m68k_virt_ctrl.c
>> @@ -0,0 +1,152 @@
>> +/*
>> + * SPDX-License-Identifer: GPL-2.0-or-later
>> + *
>> + * Virt m68k system Controller
>> + */
>> +
>> +#include "qemu/osdep.h"
>> +#include "hw/irq.h"
>> +#include "hw/qdev-properties.h"
>> +#include "hw/sysbus.h"
>> +#include "migration/vmstate.h"
>> +#include "qemu/log.h"
>> +#include "trace.h"
>> +#include "sysemu/runstate.h"
>> +#include "hw/misc/m68k_virt_ctrl.h"
>> +
>> +enum {
>> +REG_FEATURES = 0x00,
>> +REG_CMD  = 0x04,
>> +};
>> +
>> +#define FEAT_POWER_CTRL 0x0001
>> +
>> +enum {
>> +CMD_NOOP,
>> +CMD_RESET,
>> +CMD_HALT,
>> +CMD_PANIC,
>> +};
>> +
>> +static uint64_t m68k_virt_ctrl_read(void *opaque, hwaddr addr,
>> +unsigned size)
>> +{
>> +M68KVirtCtrlState *s = opaque;
>> +uint64_t value = 0;
>> +
>> +switch (addr) {
>> +case REG_FEATURES:
>> +value = FEAT_POWER_CTRL;
>> +break;
>> +default:
>> +qemu_log_mask(LOG_UNIMP,
>> +  "%s: unimplemented register read 
>> 0x%02"HWADDR_PRIx"\n",
>> +  __func__, addr);
>> +break;
>> +}
>> +
>> +trace_m68k_virt_ctrl_write(s, addr, size, value);
>> +
>> +return value;
>> +}
>> +
>> +static void m68k_virt_ctrl_write(void *opaque, hwaddr addr,
>> + uint64_t value, unsigned size)
>> +{
>> +M68KVirtCtrlState *s = opaque;
>> +
>> +trace_m68k_virt_ctrl_write(s, addr, size, value);
>> +
>> +switch (addr) {
>> +case REG_CMD:
>> +switch (value) {
>> +case CMD_NOOP:
>> +break;
>> +case CMD_RESET:
>> +qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
>> +break;
>> +case CMD_HALT:
>> +qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
>> +break;
>> +case CMD_PANIC:
>> +qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_PANIC);
>> +break;
>> +}
>> +break;
>> +default:
>> +qemu_log_mask(LOG_UNIMP,
>> +  "%s: unimplemented register write 
>> 0x%02"HWADDR_PRIx"\n",
>> +  __func__, addr);
>> +break;
>> +}
>> +}
>> +
>> +static const MemoryRegionOps m68k_virt_ctrl_ops = {
>> +.read = m68k_virt_ctrl_read,
>> +.write = m68k_virt_ctrl_write,
>> +.endianness = DEVICE_NATIVE_ENDIAN,
>> +.valid.max_access_size = 4,
>> +.impl.max_access_size = 4,
>> +};
>> +
>> +static void m68k_virt_ctrl_reset(DeviceState *dev)
>> +{
>> +M68KVirtCtrlState *s = M68K_VIRT_CTRL(dev);
>> +
>> +trace_m68k_virt_ctrl_reset(s);
>> +}
>> +
>> +static void m68k_virt_ctrl_realize(DeviceState *dev, Error **errp)
>> +{
>> +M68KVirtCtrlState *s = M68K_VIRT_CTRL(dev);
>> +
>> +trace_m68k_virt_ctrl_instance_init(s);
>> +
>> +memory_region_init_io(>iomem, OBJECT(s), _virt_ctrl_ops, s,
>> +  "m68k-virt-ctrl", 0x100);
>> +}
>> +
>> +static const VMStateDescription vmstate_m68k_virt_ctrl = {
>> +.name = "m68k-virt-ctrl",
>> +.version_id = 1,
>> +.minimum_version_id = 1,
>> +.fields = (VMStateField[]) {
>> +VMSTATE_UINT32(irq_enabled, M68KVirtCtrlState),
>> +VMSTATE_END_OF_LIST()
>> +}
>> +};
>> +
>> +static void m68k_virt_ctrl_instance_init(Object *obj)
>> +{
>> +SysBusDevice *dev = 

[PATCH v3] libqos/qgraph: format qgraph comments for sphinx documentation

2021-03-07 Thread Emanuele Giuseppe Esposito
Change documentation style and fix minor typos in tests/qtest/libqos/qgraph.h
to automatically generate sphinx documentation in docs/devel/qgraph.rst

The mechanism explanation that once was in qgraph.h is now moved to qgraph.rst

There is no functional change intended.

v2 -> v3:
- add proper documentation also to the qgraph struct, to remove warnings

v1 -> v2:
- qgraph link visible in docs/devel/index but not in docs/index, since it is
a subsection of qtest.

Signed-off-by: Emanuele Giuseppe Esposito 
---
 MAINTAINERS |   1 +
 docs/devel/index.rst|   1 +
 docs/devel/qgraph.rst   | 261 +
 docs/devel/qtest.rst|   8 +
 tests/qtest/libqos/qgraph.h | 450 +---
 5 files changed, 386 insertions(+), 335 deletions(-)
 create mode 100644 docs/devel/qgraph.rst

diff --git a/MAINTAINERS b/MAINTAINERS
index 9b2aa18e1f..f22c3aaba0 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2592,6 +2592,7 @@ S: Maintained
 F: softmmu/qtest.c
 F: accel/qtest/
 F: tests/qtest/
+F: docs/devel/qgraph.rst
 X: tests/qtest/bios-tables-test*
 
 Device Fuzzing
diff --git a/docs/devel/index.rst b/docs/devel/index.rst
index 22854e334d..f0038f8722 100644
--- a/docs/devel/index.rst
+++ b/docs/devel/index.rst
@@ -12,6 +12,7 @@ Contents:
 
 .. toctree::
:maxdepth: 2
+   :includehidden:
 
build-system
kconfig
diff --git a/docs/devel/qgraph.rst b/docs/devel/qgraph.rst
new file mode 100644
index 00..62a45cbcbf
--- /dev/null
+++ b/docs/devel/qgraph.rst
@@ -0,0 +1,261 @@
+.. _qgraph:
+
+
+Qtest Driver Framework
+
+
+This Qgraph API provides all basic functions to create a graph
+and instantiate nodes representing machines, drivers and tests
+representing their relations with ``CONSUMES``, ``PRODUCES``, and
+``CONTAINS`` edges.
+
+The idea is to have a framework where each test asks for a specific
+driver, and the framework takes care of allocating the proper devices
+required and passing the correct command line arguments to QEMU.
+
+Nodes
+^^
+
+A node can be of four types:
+
+- **QNODE_MACHINE**:   for example ``arm/raspi2``
+- **QNODE_DRIVER**:for example ``generic-sdhci``
+- **QNODE_INTERFACE**: for example ``sdhci`` (interface for all ``-sdhci``
+  drivers).
+  An interface is not explicitly created, it will be automatically
+  instantiated when a node consumes or produces it.
+- **QNODE_TEST**:  for example ``sdhci-test``, consumes an interface and
+  tests the functions provided.
+
+Notes for the nodes:
+
+- QNODE_MACHINE: each machine struct must have a ``QGuestAllocator`` and
+  implement ``get_driver()`` to return the allocator mapped to the interface
+  "memory". The function can also return ``NULL`` if the allocator
+  is not set.
+- QNODE_DRIVER:  driver names must be unique, and machines and nodes
+  planned to be "consumed" by other nodes must match QEMU
+  drivers name, otherwise they won't be discovered
+
+Edges
+^^
+
+An edge relation between two nodes (drivers or machines) `X` and `Y` can be:
+
+- ``X CONSUMES Y``: `Y` can be plugged into `X`
+- ``X PRODUCES Y``: `X` provides the interface `Y`
+- ``X CONTAINS Y``: `Y` is part of `X` component
+
+Execution steps
+^^^
+
+The basic framework steps are the following:
+
+- All nodes and edges are created in their respective
+  machine/driver/test files
+- The framework starts QEMU and asks for a list of available devices
+  and machines (note that only machines and "consumed" nodes are mapped
+  1:1 with QEMU devices)
+- The framework walks the graph starting from the available machines and
+  performs a Depth First Search for tests
+- Once a test is found, the path is walked again and all drivers are
+  allocated accordingly and the final interface is passed to the test
+- The test is executed
+- Unused objects are cleaned and the path discovery is continued
+
+Depending on the QEMU binary used, only some drivers/machines will be
+available and only test that are reached by them will be executed.
+
+Creating a new driver and its interface
+"
+
+.. code::
+
+#include "qgraph.h"
+
+struct My_driver {
+QOSGraphObject obj;
+Node_produced prod;
+Node_contained cont;
+}
+
+static void my_destructor(QOSGraphObject *obj)
+{
+g_free(obj);
+}
+
+static void *my_get_driver(void *object, const char *interface) {
+My_driver *dev = object;
+if (!g_strcmp0(interface, "my_interface")) {
+return >prod;
+}
+abort();
+}
+
+static void *my_get_device(void *object, const char *device) {
+My_driver *dev = object;
+if (!g_strcmp0(device, "my_driver_contained")) {
+return >cont;
+}
+abort();
+}
+
+static void *my_driver_constructor(void *node_consumed,
+

Re: [PATCH v5 4/5] m68k: add a system controller

2021-03-07 Thread Philippe Mathieu-Daudé
On 3/7/21 9:56 PM, Laurent Vivier wrote:
> Add a system controller for the m68k-virt machine.
> This controller allows the kernel to power off or reset the machine.
> 
> Signed-off-by: Laurent Vivier 
> Reviewed-by: Richard Henderson 
> ---
>  include/hw/misc/m68k_virt_ctrl.h |  22 +
>  hw/misc/m68k_virt_ctrl.c | 152 +++
>  hw/misc/Kconfig  |   3 +
>  hw/misc/meson.build  |   3 +
>  hw/misc/trace-events |   7 ++
>  5 files changed, 187 insertions(+)
>  create mode 100644 include/hw/misc/m68k_virt_ctrl.h
>  create mode 100644 hw/misc/m68k_virt_ctrl.c
> 
> diff --git a/include/hw/misc/m68k_virt_ctrl.h 
> b/include/hw/misc/m68k_virt_ctrl.h
> new file mode 100644
> index ..1db7960e5477
> --- /dev/null
> +++ b/include/hw/misc/m68k_virt_ctrl.h
> @@ -0,0 +1,22 @@
> +/*
> + * SPDX-License-Identifer: GPL-2.0-or-later
> + *
> + * Virt m68k system Controller
> + */
> +
> +#ifndef M68K_VIRT_CTRL_H
> +#define M68K_VIRT_CTRL_H
> +
> +#define TYPE_M68K_VIRT_CTRL "m68k-virt-ctrl"
> +OBJECT_DECLARE_SIMPLE_TYPE(M68KVirtCtrlState, M68K_VIRT_CTRL)
> +
> +struct M68KVirtCtrlState {
> +SysBusDevice parent_obj;
> +
> +MemoryRegion iomem;
> +qemu_irq irq;
> +
> +uint32_t irq_enabled;
> +};
> +
> +#endif
> diff --git a/hw/misc/m68k_virt_ctrl.c b/hw/misc/m68k_virt_ctrl.c
> new file mode 100644
> index ..fb34aa10211a
> --- /dev/null
> +++ b/hw/misc/m68k_virt_ctrl.c
> @@ -0,0 +1,152 @@
> +/*
> + * SPDX-License-Identifer: GPL-2.0-or-later
> + *
> + * Virt m68k system Controller
> + */
> +
> +#include "qemu/osdep.h"
> +#include "hw/irq.h"
> +#include "hw/qdev-properties.h"
> +#include "hw/sysbus.h"
> +#include "migration/vmstate.h"
> +#include "qemu/log.h"
> +#include "trace.h"
> +#include "sysemu/runstate.h"
> +#include "hw/misc/m68k_virt_ctrl.h"
> +
> +enum {
> +REG_FEATURES = 0x00,
> +REG_CMD  = 0x04,
> +};
> +
> +#define FEAT_POWER_CTRL 0x0001
> +
> +enum {
> +CMD_NOOP,
> +CMD_RESET,
> +CMD_HALT,
> +CMD_PANIC,
> +};
> +
> +static uint64_t m68k_virt_ctrl_read(void *opaque, hwaddr addr,
> +unsigned size)
> +{
> +M68KVirtCtrlState *s = opaque;
> +uint64_t value = 0;
> +
> +switch (addr) {
> +case REG_FEATURES:
> +value = FEAT_POWER_CTRL;
> +break;
> +default:
> +qemu_log_mask(LOG_UNIMP,
> +  "%s: unimplemented register read 0x%02"HWADDR_PRIx"\n",
> +  __func__, addr);
> +break;
> +}
> +
> +trace_m68k_virt_ctrl_write(s, addr, size, value);
> +
> +return value;
> +}
> +
> +static void m68k_virt_ctrl_write(void *opaque, hwaddr addr,
> + uint64_t value, unsigned size)
> +{
> +M68KVirtCtrlState *s = opaque;
> +
> +trace_m68k_virt_ctrl_write(s, addr, size, value);
> +
> +switch (addr) {
> +case REG_CMD:
> +switch (value) {
> +case CMD_NOOP:
> +break;
> +case CMD_RESET:
> +qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
> +break;
> +case CMD_HALT:
> +qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
> +break;
> +case CMD_PANIC:
> +qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_PANIC);
> +break;
> +}
> +break;
> +default:
> +qemu_log_mask(LOG_UNIMP,
> +  "%s: unimplemented register write 
> 0x%02"HWADDR_PRIx"\n",
> +  __func__, addr);
> +break;
> +}
> +}
> +
> +static const MemoryRegionOps m68k_virt_ctrl_ops = {
> +.read = m68k_virt_ctrl_read,
> +.write = m68k_virt_ctrl_write,
> +.endianness = DEVICE_NATIVE_ENDIAN,
> +.valid.max_access_size = 4,
> +.impl.max_access_size = 4,
> +};
> +
> +static void m68k_virt_ctrl_reset(DeviceState *dev)
> +{
> +M68KVirtCtrlState *s = M68K_VIRT_CTRL(dev);
> +
> +trace_m68k_virt_ctrl_reset(s);
> +}
> +
> +static void m68k_virt_ctrl_realize(DeviceState *dev, Error **errp)
> +{
> +M68KVirtCtrlState *s = M68K_VIRT_CTRL(dev);
> +
> +trace_m68k_virt_ctrl_instance_init(s);
> +
> +memory_region_init_io(>iomem, OBJECT(s), _virt_ctrl_ops, s,
> +  "m68k-virt-ctrl", 0x100);
> +}
> +
> +static const VMStateDescription vmstate_m68k_virt_ctrl = {
> +.name = "m68k-virt-ctrl",
> +.version_id = 1,
> +.minimum_version_id = 1,
> +.fields = (VMStateField[]) {
> +VMSTATE_UINT32(irq_enabled, M68KVirtCtrlState),
> +VMSTATE_END_OF_LIST()
> +}
> +};
> +
> +static void m68k_virt_ctrl_instance_init(Object *obj)
> +{
> +SysBusDevice *dev = SYS_BUS_DEVICE(obj);
> +M68KVirtCtrlState *s = M68K_VIRT_CTRL(obj);
> +
> +trace_m68k_virt_ctrl_instance_init(s);
> +
> +sysbus_init_mmio(dev, >iomem);
> +sysbus_init_irq(dev, >irq);
> +}
> +
> +static void 

[Bug 1918084] Re: Build fails on macOS 11.2.2

2021-03-07 Thread Thomas Huth
That's a very incomplete log that you've pasted here, I think there
should be an earlier error message that should indicate the real
problem. Please recompile without "-j8" and paste the full error log at
the end.

** Changed in: qemu
   Status: New => Incomplete

-- 
You received this bug notification because you are a member of qemu-
devel-ml, which is subscribed to QEMU.
https://bugs.launchpad.net/bugs/1918084

Title:
  Build fails on macOS 11.2.2

Status in QEMU:
  Incomplete

Bug description:
  Hi,

  I got the latest version from git. I have pre-compiled the dependency
  libraries. All good. configure creates the necessary files. When I
  build I got the following error:

  [1368/6454] Compiling C object 
libcapstone.a.p/capstone_arch_AArch64_AArch64InstPrinter.c.o
  ninja: build stopped: subcommand failed.
  make[1]: *** [run-ninja] Error 1
  make: *** [all] Error 2

  I've ran make as make -j 8

  original config:

  
PKG_CONFIG_PATH="$SERVERPLUS_DIR/dependencies/glib/lib/pkgconfig:$SERVERPLUS_DIR/dependencies/pixman/lib/pkgconfig:$SERVERPLUS_DIR/dependencies
  /cyrus-sasl/lib/pkgconfig" ./configure --prefix="$SERVERPLUS_DIR"
  --enable-hvf --enable-cocoa --enable-vnc-sasl --enable-auth-pam
  --ninja=/opt/build/build/stage/tools/ninja/ninja
  --python="$SERVERPLUS_DIR/dependencies/python/bin/python3" --enable-
  bsd-user

  if I build with --target-list=x86_64-softmmu then it will build but I
  will get only the x86_64 QEMU built. With 5.0 I could build all
  emulators.

  $SERVERPLUS_DIR is my target dir.

  Thanks,

  Eddy

To manage notifications about this bug go to:
https://bugs.launchpad.net/qemu/+bug/1918084/+subscriptions



Re: [PATCH v4 4/5] m68k: add a system controller

2021-03-07 Thread Thomas Huth

On 07/03/2021 17.48, Laurent Vivier wrote:

Add a system controller for the m68k-virt machine.
This controller allows the kernel to power off or reset the machine.

Signed-off-by: Laurent Vivier 
Reviewed-by: Richard Henderson 
---
  include/hw/misc/m68k_virt_ctrl.h |  22 +
  hw/misc/m68k_virt_ctrl.c | 152 +++


Wouldn't it make more sense to place this in hw/m68k than hw/misc ?

 Thomas




Re: SubmitAPatch wiki page has broken link to coding style

2021-03-07 Thread Thomas Huth

On 08/03/2021 02.55, Rebecca Cran wrote:
In commit cbcf09872a936ccefef6a34298046d3b9aefc148 on February 25th 
CODING_STYLE.rst was moved into the developer manual. So, the "Use the QEMU 
coding style" section of https://wiki.qemu.org/Contribute/SubmitAPatch 
should probably be updated to link to:


https://gitlab.com/qemu-project/qemu/-/blob/master/docs/devel/style.rst


Thanks for the hint! I've updated it to point to:

https://qemu-project.gitlab.io/qemu/devel/style.html

 Thomas




[PATCH 2/4] block: check for sys/disk.h

2021-03-07 Thread Joelle van Dyne
Some BSD platforms do not have this header.

Signed-off-by: Joelle van Dyne 
---
 meson.build | 1 +
 block.c | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/meson.build b/meson.build
index 0e53876f69..ba0db9fa1f 100644
--- a/meson.build
+++ b/meson.build
@@ -1153,6 +1153,7 @@ config_host_data.set('HAVE_SYS_IOCCOM_H', 
cc.has_header('sys/ioccom.h'))
 config_host_data.set('HAVE_SYS_KCOV_H', cc.has_header('sys/kcov.h'))
 config_host_data.set('HAVE_SYSTEM_FUNCTION', cc.has_function('system', prefix: 
'#include '))
 config_host_data.set('HAVE_HOST_BLOCK_DEVICE', have_host_block_device)
+config_host_data.set('HAVE_SYS_DISK_H', cc.has_header('sys/disk.h'))
 
 config_host_data.set('CONFIG_PREADV', cc.has_function('preadv', prefix: 
'#include '))
 
diff --git a/block.c b/block.c
index a1f3cecd75..b2705ad225 100644
--- a/block.c
+++ b/block.c
@@ -54,7 +54,7 @@
 #ifdef CONFIG_BSD
 #include 
 #include 
-#ifndef __DragonFly__
+#if defined(HAVE_SYS_DISK_H)
 #include 
 #endif
 #endif
-- 
2.28.0




[PATCH 4/4] slirp: feature detection for smbd

2021-03-07 Thread Joelle van Dyne
Replace Windows specific macro with a more generic feature detection
macro. Allows slirp smb feature to be disabled manually as well.

Signed-off-by: Joelle van Dyne 
---
 configure   | 26 +++---
 meson.build |  3 +++
 net/slirp.c | 16 
 3 files changed, 34 insertions(+), 11 deletions(-)

diff --git a/configure b/configure
index 34fccaa2ba..8335a3e6a0 100755
--- a/configure
+++ b/configure
@@ -465,6 +465,7 @@ fuse_lseek="auto"
 multiprocess="auto"
 
 malloc_trim="auto"
+slirp_smbd="auto"
 
 # parse CC options second
 for opt do
@@ -834,8 +835,6 @@ do
 fi
 done
 
-: ${smbd=${SMBD-/usr/sbin/smbd}}
-
 # Default objcc to clang if available, otherwise use CC
 if has clang; then
   objcc=clang
@@ -1560,6 +1559,10 @@ for opt do
   ;;
   --disable-multiprocess) multiprocess="disabled"
   ;;
+  --enable-slirp-smbd) slirp_smbd=yes
+  ;;
+  --disable-slirp-smbd) slirp_smbd=no
+  ;;
   *)
   echo "ERROR: unknown option $opt"
   echo "Try '$0 --help' for more information"
@@ -1913,6 +1916,7 @@ disabled with --disable-FEATURE, default is enabled if 
available
   fuseFUSE block device export
   fuse-lseek  SEEK_HOLE/SEEK_DATA support for FUSE exports
   multiprocessOut of process device emulation support
+  slirp-smbd  use smbd (at path --smbd=*) in slirp networking
 
 NOTE: The object files are built at the place where configure is launched
 EOF
@@ -5252,6 +5256,19 @@ case "$slirp" in
 ;;
 esac
 
+# Check for slirp smbd dupport
+: ${smbd=${SMBD-/usr/sbin/smbd}}
+if test "$slirp_smbd" != "no" ; then
+  if test "$mingw32" = "yes" ; then
+if test "$slirp_smbd" = "yes" ; then
+  error_exit "Host smbd not supported on this platform."
+fi
+slirp_smbd=no
+  else
+slirp_smbd=yes
+  fi
+fi
+
 ##
 # check for usable __NR_keyctl syscall
 
@@ -5527,7 +5544,10 @@ fi
 if test "$guest_agent" = "yes" ; then
   echo "CONFIG_GUEST_AGENT=y" >> $config_host_mak
 fi
-echo "CONFIG_SMBD_COMMAND=\"$smbd\"" >> $config_host_mak
+if test "$slirp_smbd" = "yes" ; then
+  echo "CONFIG_SLIRP_SMBD=y" >> $config_host_mak
+  echo "CONFIG_SMBD_COMMAND=\"$smbd\"" >> $config_host_mak
+fi
 if test "$vde" = "yes" ; then
   echo "CONFIG_VDE=y" >> $config_host_mak
   echo "VDE_LIBS=$vde_libs" >> $config_host_mak
diff --git a/meson.build b/meson.build
index ba0db9fa1f..773ce512c7 100644
--- a/meson.build
+++ b/meson.build
@@ -2629,6 +2629,9 @@ summary_info += {'pixman':pixman.found()}
 summary_info += {'VTE support':   config_host.has_key('CONFIG_VTE')}
 # TODO: add back version
 summary_info += {'slirp support': slirp_opt == 'disabled' ? false : 
slirp_opt}
+if slirp_opt != 'disabled' and 'CONFIG_SLIRP_SMBD' in config_host
+  summary_info += {'smbd':config_host['CONFIG_SMBD_COMMAND']}
+endif
 summary_info += {'libtasn1':  config_host.has_key('CONFIG_TASN1')}
 summary_info += {'PAM':   config_host.has_key('CONFIG_AUTH_PAM')}
 summary_info += {'iconv support': iconv.found()}
diff --git a/net/slirp.c b/net/slirp.c
index be914c0be0..b3ded2aac1 100644
--- a/net/slirp.c
+++ b/net/slirp.c
@@ -27,7 +27,7 @@
 #include "net/slirp.h"
 
 
-#ifndef _WIN32
+#if defined(CONFIG_SLIRP_SMBD)
 #include 
 #include 
 #endif
@@ -90,7 +90,7 @@ typedef struct SlirpState {
 Slirp *slirp;
 Notifier poll_notifier;
 Notifier exit_notifier;
-#ifndef _WIN32
+#if defined(CONFIG_SLIRP_SMBD)
 gchar *smb_dir;
 #endif
 GSList *fwd;
@@ -103,7 +103,7 @@ static QTAILQ_HEAD(, SlirpState) slirp_stacks =
 static int slirp_hostfwd(SlirpState *s, const char *redir_str, Error **errp);
 static int slirp_guestfwd(SlirpState *s, const char *config_str, Error **errp);
 
-#ifndef _WIN32
+#if defined(CONFIG_SLIRP_SMBD)
 static int slirp_smb(SlirpState *s, const char *exported_dir,
  struct in_addr vserver_addr, Error **errp);
 static void slirp_smb_cleanup(SlirpState *s);
@@ -367,7 +367,7 @@ static int net_slirp_init(NetClientState *peer, const char 
*model,
 struct in6_addr ip6_prefix;
 struct in6_addr ip6_host;
 struct in6_addr ip6_dns;
-#ifndef _WIN32
+#if defined(CONFIG_SLIRP_SMBD)
 struct in_addr smbsrv = { .s_addr = 0 };
 #endif
 NetClientState *nc;
@@ -477,7 +477,7 @@ static int net_slirp_init(NetClientState *peer, const char 
*model,
 return -1;
 }
 
-#ifndef _WIN32
+#if defined(CONFIG_SLIRP_SMBD)
 if (vsmbserver && !inet_aton(vsmbserver, )) {
 error_setg(errp, "Failed to parse SMB address");
 return -1;
@@ -592,7 +592,7 @@ static int net_slirp_init(NetClientState *peer, const char 
*model,
 }
 }
 }
-#ifndef _WIN32
+#if defined(CONFIG_SLIRP_SMBD)
 if (smb_export) {
 if (slirp_smb(s, smb_export, smbsrv, errp) < 0) {
 goto error;
@@ -784,7 +784,7 @@ void hmp_hostfwd_add(Monitor *mon, const QDict *qdict)
 
 }
 
-#ifndef _WIN32
+#if defined(CONFIG_SLIRP_SMBD)
 
 /* automatic 

[PATCH 3/4] block: detect DKIOCGETBLOCKCOUNT/SIZE before use

2021-03-07 Thread Joelle van Dyne
iOS hosts do not have these defined so we fallback to the
default behaviour.

Co-authored-by: Warner Losh 
Signed-off-by: Joelle van Dyne 
---
 block/file-posix.c | 18 +++---
 1 file changed, 7 insertions(+), 11 deletions(-)

diff --git a/block/file-posix.c b/block/file-posix.c
index d1ab3180ff..9b6d7ddda3 100644
--- a/block/file-posix.c
+++ b/block/file-posix.c
@@ -2326,8 +2326,10 @@ static int64_t raw_getlength(BlockDriverState *bs)
 again:
 #endif
 if (!fstat(fd, ) && (S_IFCHR & sb.st_mode)) {
+size = 0;
 #ifdef DIOCGMEDIASIZE
 if (ioctl(fd, DIOCGMEDIASIZE, (off_t *)))
+size = 0;
 #elif defined(DIOCGPART)
 {
 struct partinfo pi;
@@ -2336,9 +2338,7 @@ again:
 else
 size = 0;
 }
-if (size == 0)
-#endif
-#if defined(__APPLE__) && defined(__MACH__)
+#elif defined(DKIOCGETBLOCKCOUNT) && defined(DKIOCGETBLOCKSIZE)
 {
 uint64_t sectors = 0;
 uint32_t sector_size = 0;
@@ -2346,19 +2346,15 @@ again:
 if (ioctl(fd, DKIOCGETBLOCKCOUNT, ) == 0
&& ioctl(fd, DKIOCGETBLOCKSIZE, _size) == 0) {
 size = sectors * sector_size;
-} else {
-size = lseek(fd, 0LL, SEEK_END);
-if (size < 0) {
-return -errno;
-}
 }
 }
-#else
-size = lseek(fd, 0LL, SEEK_END);
+#endif
+if (size == 0) {
+size = lseek(fd, 0LL, SEEK_END);
+}
 if (size < 0) {
 return -errno;
 }
-#endif
 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
 switch(s->type) {
 case FTYPE_CD:
-- 
2.28.0




[PATCH 1/4] block: feature detection for host block support

2021-03-07 Thread Joelle van Dyne
On Darwin (iOS), there are no system level APIs for directly accessing
host block devices. We detect this at configure time.

Signed-off-by: Joelle van Dyne 
---
 meson.build  |  6 +-
 qapi/block-core.json | 10 +++---
 block/file-posix.c   | 33 ++---
 3 files changed, 34 insertions(+), 15 deletions(-)

diff --git a/meson.build b/meson.build
index 81d760d6e8..0e53876f69 100644
--- a/meson.build
+++ b/meson.build
@@ -181,7 +181,7 @@ if targetos == 'windows'
   include_directories: 
include_directories('.'))
 elif targetos == 'darwin'
   coref = dependency('appleframeworks', modules: 'CoreFoundation')
-  iokit = dependency('appleframeworks', modules: 'IOKit')
+  iokit = dependency('appleframeworks', modules: 'IOKit', required: false)
 elif targetos == 'sunos'
   socket = [cc.find_library('socket'),
 cc.find_library('nsl'),
@@ -1056,6 +1056,9 @@ if get_option('cfi')
   add_global_link_arguments(cfi_flags, native: false, language: ['c', 'cpp', 
'objc'])
 endif
 
+have_host_block_device = (targetos != 'darwin' or
+cc.has_header('IOKit/storage/IOMedia.h'))
+
 #
 # config-host.h #
 #
@@ -1149,6 +1152,7 @@ config_host_data.set('HAVE_PTY_H', cc.has_header('pty.h'))
 config_host_data.set('HAVE_SYS_IOCCOM_H', cc.has_header('sys/ioccom.h'))
 config_host_data.set('HAVE_SYS_KCOV_H', cc.has_header('sys/kcov.h'))
 config_host_data.set('HAVE_SYSTEM_FUNCTION', cc.has_function('system', prefix: 
'#include '))
+config_host_data.set('HAVE_HOST_BLOCK_DEVICE', have_host_block_device)
 
 config_host_data.set('CONFIG_PREADV', cc.has_function('preadv', prefix: 
'#include '))
 
diff --git a/qapi/block-core.json b/qapi/block-core.json
index 9f555d5c1d..0c2cd9e689 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -959,7 +959,8 @@
   'discriminator': 'driver',
   'data': {
   'file': 'BlockStatsSpecificFile',
-  'host_device': 'BlockStatsSpecificFile',
+  'host_device': { 'type': 'BlockStatsSpecificFile',
+   'if': 'defined(HAVE_HOST_BLOCK_DEVICE)' },
   'nvme': 'BlockStatsSpecificNvme' } }
 
 ##
@@ -2863,7 +2864,9 @@
 { 'enum': 'BlockdevDriver',
   'data': [ 'blkdebug', 'blklogwrites', 'blkreplay', 'blkverify', 'bochs',
 'cloop', 'compress', 'copy-on-read', 'dmg', 'file', 'ftp', 'ftps',
-'gluster', 'host_cdrom', 'host_device', 'http', 'https', 'iscsi',
+'gluster', 'host_cdrom',
+{'name': 'host_device', 'if': 'defined(HAVE_HOST_BLOCK_DEVICE)' },
+'http', 'https', 'iscsi',
 'luks', 'nbd', 'nfs', 'null-aio', 'null-co', 'nvme', 'parallels',
 'preallocate', 'qcow', 'qcow2', 'qed', 'quorum', 'raw', 'rbd',
 { 'name': 'replication', 'if': 'defined(CONFIG_REPLICATION)' },
@@ -4066,7 +4069,8 @@
   'ftps':   'BlockdevOptionsCurlFtps',
   'gluster':'BlockdevOptionsGluster',
   'host_cdrom': 'BlockdevOptionsFile',
-  'host_device':'BlockdevOptionsFile',
+  'host_device': { 'type': 'BlockdevOptionsFile',
+   'if': 'defined(HAVE_HOST_BLOCK_DEVICE)' },
   'http':   'BlockdevOptionsCurlHttp',
   'https':  'BlockdevOptionsCurlHttps',
   'iscsi':  'BlockdevOptionsIscsi',
diff --git a/block/file-posix.c b/block/file-posix.c
index 05079b40ca..d1ab3180ff 100644
--- a/block/file-posix.c
+++ b/block/file-posix.c
@@ -42,6 +42,8 @@
 #include "scsi/constants.h"
 
 #if defined(__APPLE__) && (__MACH__)
+#include 
+#if defined(HAVE_HOST_BLOCK_DEVICE)
 #include 
 #include 
 #include 
@@ -52,6 +54,7 @@
 //#include 
 #include 
 #include 
+#endif /* defined(HAVE_HOST_BLOCK_DEVICE) */
 #endif
 
 #ifdef __sun__
@@ -181,7 +184,17 @@ typedef struct BDRVRawReopenState {
 bool check_cache_dropped;
 } BDRVRawReopenState;
 
-static int fd_open(BlockDriverState *bs);
+static int fd_open(BlockDriverState *bs)
+{
+BDRVRawState *s = bs->opaque;
+
+/* this is just to ensure s->fd is sane (its called by io ops) */
+if (s->fd >= 0) {
+return 0;
+}
+return -EIO;
+}
+
 static int64_t raw_getlength(BlockDriverState *bs);
 
 typedef struct RawPosixAIOData {
@@ -3032,6 +3045,7 @@ static BlockStatsSpecific 
*raw_get_specific_stats(BlockDriverState *bs)
 return stats;
 }
 
+#if defined(HAVE_HOST_BLOCK_DEVICE)
 static BlockStatsSpecific *hdev_get_specific_stats(BlockDriverState *bs)
 {
 BlockStatsSpecific *stats = g_new(BlockStatsSpecific, 1);
@@ -3041,6 +3055,7 @@ static BlockStatsSpecific 
*hdev_get_specific_stats(BlockDriverState *bs)
 
 return stats;
 }
+#endif /* HAVE_HOST_BLOCK_DEVICE */
 
 static QemuOptsList raw_create_opts = {
 .name = "raw-create-opts",
@@ -3265,6 +3280,8 @@ BlockDriver bdrv_file = {
 /***/
 /* host device */
 
+#if defined(HAVE_HOST_BLOCK_DEVICE)
+
 #if defined(__APPLE__) && defined(__MACH__)
 static kern_return_t 

[PATCH 0/4] Disable unsupported features on iOS hosts

2021-03-07 Thread Joelle van Dyne
These patches disables code that cannot be compiled or run on iOS by adding
feature/header detection at configure time.

-j

Joelle van Dyne (4):
  block: feature detection for host block support
  block: check for sys/disk.h
  block: detect DKIOCGETBLOCKCOUNT/SIZE before use
  slirp: feature detection for smbd

 configure| 26 +++---
 meson.build  | 10 -
 qapi/block-core.json | 10 ++---
 block.c  |  2 +-
 block/file-posix.c   | 51 +---
 net/slirp.c  | 16 +++---
 6 files changed, 77 insertions(+), 38 deletions(-)

-- 
2.28.0




Re: [PATCH] util/osdep: Avoid mprotect() RWX->NONE on Big Sur 11.2

2021-03-07 Thread Joelle van Dyne
On Wed, Feb 10, 2021 at 2:55 AM Roman Bolshakov  wrote:
>
> There's a change in mprotect() behaviour [1] in the latest macOS on M1
> and it's not yet clear if it's going to be fixed by Apple. For now we
> can avoid unsupported mprotect() calls. QEMU and qtests work fine
> without it.
>
> 1. https://gist.github.com/hikalium/75ae822466ee4da13cbbe486498a191f
>
> Buglink: https://bugs.launchpad.net/qemu/+bug/1914849
> Apple-Feedback: FB8994773
> Signed-off-by: Roman Bolshakov 

Reviewed-by: Joelle van Dyne 

FYI the "macOS 11.2, *" means it applies to all versions of iOS. I
think it only broke in iOS 14.2 but making it return on other versions
seems to be fine from my tests.

-j



Re: [PATCH v3 04/12] libqtest: add qtest_remove_abrt_handler()

2021-03-07 Thread Thomas Huth

On 23/02/2021 15.46, Stefan Hajnoczi wrote:

Add a function to remove previously-added abrt handler functions.

Now that a symmetric pair of add/remove functions exists we can also
balance the SIGABRT handler installation. The signal handler was
installed each time qtest_add_abrt_handler() was called. Now it is
installed when the abrt handler list becomes non-empty and removed again
when the list becomes empty.

The qtest_remove_abrt_handler() function will be used by
vhost-user-blk-test.

Signed-off-by: Stefan Hajnoczi 
Reviewed-by: Wainer dos Santos Moschetta 
---
  tests/qtest/libqos/libqtest.h | 18 ++
  tests/qtest/libqtest.c| 35 +--
  2 files changed, 47 insertions(+), 6 deletions(-)


Reviewed-by: Thomas Huth 




Re: [PATCH v2 2/2] build-sys: make libslirp a meson subproject

2021-03-07 Thread Joelle van Dyne
On Sun, Jan 24, 2021 at 11:34 PM  wrote:
>
> From: Marc-André Lureau 
>
> Remove the manual build.
>
> Signed-off-by: Marc-André Lureau 

Tested-by: Joelle van Dyne 



Re: [PATCH v2 1/2] slirp: update to git master

2021-03-07 Thread Joelle van Dyne
On Sun, Jan 24, 2021 at 11:34 PM  wrote:
>
> From: Marc-André Lureau 
>
> git cherry-diff:
>
> Commits on bacb71f1c3ed5f40e393afd8be81bedfba13a401 branch that is not on 
> 8f43a99191afb47ca3f3c6972f6306209f367ece branch
> + 1021b0dc38d39f1dc95a296fe3e05a24a087cdc6 disable_dns option
> + 0f94ceec752592e4ac632a24e3c64a97dd09bf4c limit vnameserver_addr to port 53
> + b57bafa852ef16b133907a13678ec69e9531f177 libslirp.h: fix SlirpConfig v3 
> documentation
> + 1abf18b2b5edb462797629ed47ad4515a195686e Update CHANGELOG
> + ff4ecf9b6c6542b24b4ac6ea178be9d44e159f79 Release v4.3.0
> + 21f1d933050a40d62612c6274c32de60b811d9ea changelog: post-release
> + 376187c4b14c795763d472214812826eebe7e9c2 Release v4.3.1
> + 73336e08902a7e826f7d960453df037380266186 changelog: post-release
> + 5c1c9d43be61571608e9b14615045b67b830daf5 udp, udp6, icmp: handle TTL value
> + 73ed49ab71998d4288e71e954ef6214b70f23d79 icmp, icmp6: Add 
> icmp_forward_error and icmp6_forward_error
> + 7a4840a57ec7dbc37cca1ab96f058a9610b26950 udp, udp6, icmp, icmp6: Enable 
> forwarding errors on Linux
> + e9b2bc19ae652a2907f247e621b2e4773bdd2aab TCPIPHDR_DELTA: Fix potential 
> negative value
> + 39f9a363eec082f04513413046321abd04163148 .gitlab-ci: add a Coverity stage
> + 1b0093b973cfa0dc041522e5d4e6f576b2df642e sosendoob: better document what 
> urgc is used for
> + 5b9ad89ebbb8afa50162c9156fabd5fc56291088 Add G_GNUC_PRINTF to local 
> function slirp_vsnprintf
> + 8a808aa493980e212b4d5f5465330905c8294e59 meson: remove meson-dist script
> + 0b669b5fbe4d3c25a682a67f1059d8633c963b3d meson: support compiling as 
> subproject
> + 9f82a47b81f2864422b82c1e40e51a2ed9c6ac32 Add DNS resolving for iOS
> + c0eac03e8ce1b9a743231f2fe21e7cb579fc9339 Remove the QEMU-special make 
> build-system
> + 1bfd4d9368f9fa2e4f0731e1266bec05bbc83a80 socket: consume empty packets
> + 92413be68914f8cae2f5bad4bf3ab8491dcbc5d7 Release v4.4.0
> + 07e8cfac69766081871ab620d9f16a630543d302 changelog: post-release
> + 4c4e035813313d02b63fdeb920d56fb2fdc0a5b1 Remove some needless (void)casts
> + eee9db9d115d91aa82f33685c4e76d656db92976 fork_exec_child_setup: improve 
> signal handling
> + 216f434a018b3af182a4f31bbe5a00daee170343 Fix unused variables
>
> Signed-off-by: Marc-André Lureau 

Tested-by: Joelle van Dyne 



Re: [PATCH v3 03/12] libqtest: add qtest_kill_qemu()

2021-03-07 Thread Thomas Huth

On 23/02/2021 15.46, Stefan Hajnoczi wrote:

Tests that manage multiple processes may wish to kill QEMU before
destroying the QTestState. Expose a function to do that.

The vhost-user-blk-test testcase will need this.

Signed-off-by: Stefan Hajnoczi 
Reviewed-by: Wainer dos Santos Moschetta 
---
  tests/qtest/libqos/libqtest.h | 11 +++
  tests/qtest/libqtest.c|  7 ---
  2 files changed, 15 insertions(+), 3 deletions(-)


Reviewed-by: Thomas Huth 




Re: [PATCH 1/3] tests/qtest/vhost-user-test: use share=on with memfd

2021-03-07 Thread Thomas Huth

On 22/02/2021 17.10, Stefan Hajnoczi wrote:

For some reason memfd never used share=on. vhost-user relies on
mmap(MAP_SHARED) so this seems like a problem, but the tests still run
without it.

Add share=on for consistency and to prevent future bugs in the test.

Signed-off-by: Stefan Hajnoczi 
---
  tests/qtest/vhost-user-test.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/qtest/vhost-user-test.c b/tests/qtest/vhost-user-test.c
index 1a5f5313ff..2db98c4920 100644
--- a/tests/qtest/vhost-user-test.c
+++ b/tests/qtest/vhost-user-test.c
@@ -40,7 +40,7 @@
  #define QEMU_CMD_MEM" -m %d -object memory-backend-file,id=mem,size=%dM," 
\
  "mem-path=%s,share=on -numa node,memdev=mem"
  #define QEMU_CMD_MEMFD  " -m %d -object 
memory-backend-memfd,id=mem,size=%dM," \
-" -numa node,memdev=mem"
+"share=on -numa node,memdev=mem"


Even if it's not required, it seems to be a good clean up, also with regards 
to the lonely comma at the end of the previous line.


Acked-by: Thomas Huth 

I assume this will go through the vhost tree, or do you want me to take this 
single patch through my qtest tree?





[PATCH] virtio-net: calculating proper msix vectors on init

2021-03-07 Thread Jason Wang
Currently, the default msix vectors for virtio-net-pci is 3 which is
obvious not suitable for multiqueue guest, so we depends on the user
or management tools to pass a correct vectors parameter. In fact, we
can simplifying this by calculating the number of vectors on realize.

Consider we have N queues, the number of vectors needed is 2*N + 2
(#queue pais + plus one config interrupt and control vq). We didn't
check whether or not host support control vq because it was added
unconditionally by qemu to avoid breaking legacy guests such as Minix.

Signed-off-by: Jason Wang 
---
 hw/core/machine.c  | 1 +
 hw/virtio/virtio-net-pci.c | 8 +++-
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/hw/core/machine.c b/hw/core/machine.c
index 4386f57b5c..979133f8b7 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -39,6 +39,7 @@
 GlobalProperty hw_compat_5_2[] = {
 { "ICH9-LPC", "smm-compat", "on"},
 { "PIIX4_PM", "smm-compat", "on"},
+{ "virtio-net-pci", "vectors", "3"},
 };
 const size_t hw_compat_5_2_len = G_N_ELEMENTS(hw_compat_5_2);
 
diff --git a/hw/virtio/virtio-net-pci.c b/hw/virtio/virtio-net-pci.c
index 292d13d278..2894c46b66 100644
--- a/hw/virtio/virtio-net-pci.c
+++ b/hw/virtio/virtio-net-pci.c
@@ -41,7 +41,8 @@ struct VirtIONetPCI {
 static Property virtio_net_properties[] = {
 DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags,
 VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
-DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 3),
+DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors,
+   DEV_NVECTORS_UNSPECIFIED),
 DEFINE_PROP_END_OF_LIST(),
 };
 
@@ -50,6 +51,11 @@ static void virtio_net_pci_realize(VirtIOPCIProxy *vpci_dev, 
Error **errp)
 DeviceState *qdev = DEVICE(vpci_dev);
 VirtIONetPCI *dev = VIRTIO_NET_PCI(vpci_dev);
 DeviceState *vdev = DEVICE(>vdev);
+VirtIONet *net = VIRTIO_NET(vdev);
+
+if (vpci_dev->nvectors == DEV_NVECTORS_UNSPECIFIED) {
+vpci_dev->nvectors = 2 * MAX(net->nic_conf.peers.queues, 1) + 2;
+}
 
 virtio_net_set_netclient_name(>vdev, qdev->id,
   object_get_typename(OBJECT(qdev)));
-- 
2.24.3 (Apple Git-128)




Re: [RFC PATCH v3 02/10] net: Pad short frames to minimum size before send from SLiRP/TAP

2021-03-07 Thread Bin Meng
On Mon, Mar 8, 2021 at 11:48 AM Jason Wang  wrote:
>
>
> On 2021/3/4 3:11 上午, Philippe Mathieu-Daudé wrote:
> > From: Bin Meng 
> >
> > The minimum Ethernet frame length is 60 bytes. For short frames with
> > smaller length like ARP packets (only 42 bytes), on a real world NIC
> > it can choose either padding its length to the minimum required 60
> > bytes, or sending it out directly to the wire. Such behavior can be
> > hardcoded or controled by a register bit. Similarly on the receive
> > path, NICs can choose either dropping such short frames directly or
> > handing them over to software to handle.
> >
> > On the other hand, for the network backends SLiRP/TAP, they don't
> > expose a way to control the short frame behavior. As of today they
> > just send/receive data from/to the other end connected to them,
> > which means any sized packet is acceptable. So they can send and
> > receive short frames without any problem. It is observed that ARP
> > packets sent from SLiRP/TAP are 42 bytes, and SLiRP/TAP just send
> > these ARP packets to the other end which might be a NIC model that
> > does not allow short frames to pass through.
>
>
> Do we need to care about other type of networking backends? E.g socket.
>

I am not sure as I never used other backends. If someone who is more
familiar with the network codes better than me can confirm other
backends are also needed, we might do:

if (sender->info->type != NET_CLIENT_DRIVER_NIC)

> Or at least we should keep the padding logic if we can't audit all of
> the backends.

Regards,
Bin



Re: [PATCH V4 00/10] Detect reentrant RX casued by loopback

2021-03-07 Thread Jason Wang



On 2021/3/5 2:26 下午, Jason Wang wrote:

Hi All:

Followed by commit 22dc8663d9 ("net: forbid the reentrant RX"), we
still need to fix the issues casued by loopback mode where the NIC
usually it via calling nc->info->receive() directly.

The fix is to introduce new network helper and check the
queue->delivering.

This series addresses CVE-2021-3416.

Thanks



So, I've queued this series with stable cced.

Thanks




Changes since V3:
- clarify CVE number in the commit log
- ident fix

Changes since V2:
- add more fixes from Alexander

Changes since V1:

- Fix dp8393x compiling
- Add rtl8139 fix
- Tweak the commit log
- Silent patchew warning

Alexander Bulekov (4):
   rtl8139: switch to use qemu_receive_packet() for loopback
   pcnet: switch to use qemu_receive_packet() for loopback
   cadence_gem: switch to use qemu_receive_packet() for loopback
   lan9118: switch to use qemu_receive_packet() for loopback

Jason Wang (6):
   net: introduce qemu_receive_packet()
   e1000: switch to use qemu_receive_packet() for loopback
   dp8393x: switch to use qemu_receive_packet() for loopback packet
   msf2-mac: switch to use qemu_receive_packet() for loopback
   sungem: switch to use qemu_receive_packet() for loopback
   tx_pkt: switch to use qemu_receive_packet_iov() for loopback

  hw/net/cadence_gem.c |  4 ++--
  hw/net/dp8393x.c |  2 +-
  hw/net/e1000.c   |  2 +-
  hw/net/lan9118.c |  2 +-
  hw/net/msf2-emac.c   |  2 +-
  hw/net/net_tx_pkt.c  |  2 +-
  hw/net/pcnet.c   |  2 +-
  hw/net/rtl8139.c |  2 +-
  hw/net/sungem.c  |  2 +-
  include/net/net.h|  5 +
  include/net/queue.h  |  8 
  net/net.c| 38 +++---
  net/queue.c  | 22 ++
  13 files changed, 76 insertions(+), 17 deletions(-)






Re: About libfuzzer in qemu

2021-03-07 Thread Alexander Bulekov
On 210307 2242, Alexander Bulekov wrote:
> My basic workflow for that is:
> QEMU_FUZZ_TIMEOUT=0 QTEST_LOG=1 FUZZ_SERIALIZE_QTEST=1 \
> ./qemu-fuzz-target \
>--fuzz-target=generic-fuzz-virtio-vga ./crash-... > /tmp/out
   ^
Oops that should be 2> or &>

> ./scripts/oss-fuzz/reorder_fuzzer_qtest_trace.py /tmp/out > /tmp/repro
> 
> # In /tmp/out find the line "Starting qemu with Arguments:" and copy the
> # args ( without -qtest /dev/null)
> less /tmp/out 
> 
> export QEMU_ARGS="-display none -machine accel=qtest, -m 512M -machine q35 
> -nodefaults -device virtio-vga"
> 
> # Reproduce the crash on a non-fuzz binary
> ./qemu-system-i386 $QEMU_ARGS -qtest stdio < /tmp/repro



Re: [RFC PATCH v3 02/10] net: Pad short frames to minimum size before send from SLiRP/TAP

2021-03-07 Thread Jason Wang



On 2021/3/4 3:11 上午, Philippe Mathieu-Daudé wrote:

From: Bin Meng 

The minimum Ethernet frame length is 60 bytes. For short frames with
smaller length like ARP packets (only 42 bytes), on a real world NIC
it can choose either padding its length to the minimum required 60
bytes, or sending it out directly to the wire. Such behavior can be
hardcoded or controled by a register bit. Similarly on the receive
path, NICs can choose either dropping such short frames directly or
handing them over to software to handle.

On the other hand, for the network backends SLiRP/TAP, they don't
expose a way to control the short frame behavior. As of today they
just send/receive data from/to the other end connected to them,
which means any sized packet is acceptable. So they can send and
receive short frames without any problem. It is observed that ARP
packets sent from SLiRP/TAP are 42 bytes, and SLiRP/TAP just send
these ARP packets to the other end which might be a NIC model that
does not allow short frames to pass through.



Do we need to care about other type of networking backends? E.g socket.

Or at least we should keep the padding logic if we can't audit all of 
the backends.


Thanks




To provide better compatibility, for packets sent from SLiRP/TAP, we
change to pad short frames before sending it out to the other end.
This ensures SLiRP/TAP as an Ethernet sender do not violate the spec.
But with this change, the behavior of dropping short frames in the
NIC model cannot be emulated because it always receives a packet that
is spec complaint. The capability of sending short frames from NIC
models are still supported and short frames can still pass through
SLiRP/TAP interfaces.

This commit should be able to fix the issue as reported with some
NIC models before, that ARP requests get dropped, preventing the
guest from becoming visible on the network. It was workarounded in
these NIC models on the receive path, that when a short frame is
received, it is padded up to 60 bytes.

The following 2 commits seem to be the one to workaround this issue
in e1000 and vmxenet3 before, and should probably be reverted.

   commit 78aeb23eded2 ("e1000: Pad short frames to minimum size (60 bytes)")
   commit 40a87c6c9b11 ("vmxnet3: Pad short frames to minimum size (60 bytes)")

Signed-off-by: Bin Meng 
Message-Id: <1614763306-18026-2-git-send-email-bmeng...@gmail.com>
[PMD: Use struct iovec for zero-copy]
Signed-off-by: Philippe Mathieu-Daudé 
---
  include/net/eth.h |  1 +
  net/net.c | 14 ++
  2 files changed, 15 insertions(+)

diff --git a/include/net/eth.h b/include/net/eth.h
index 0671be69165..7c825ecb2f7 100644
--- a/include/net/eth.h
+++ b/include/net/eth.h
@@ -31,6 +31,7 @@
  
  #define ETH_ALEN 6

  #define ETH_HLEN 14
+#define ETH_ZLEN 60 /* Min. octets in frame sans FCS */
  
  struct eth_header {

  uint8_t  h_dest[ETH_ALEN];   /* destination eth addr */
diff --git a/net/net.c b/net/net.c
index 159e4d0ec25..d42ac9365eb 100644
--- a/net/net.c
+++ b/net/net.c
@@ -620,6 +620,7 @@ static ssize_t 
qemu_send_packet_async_with_flags(NetClientState *sender,
   const uint8_t *buf, int size,
   NetPacketSent *sent_cb)
  {
+static const uint8_t null_buf[ETH_ZLEN] = { };
  NetQueue *queue;
  int ret;
  int iovcnt = 1;
@@ -628,6 +629,10 @@ static ssize_t 
qemu_send_packet_async_with_flags(NetClientState *sender,
  .iov_base = (void *)buf,
  .iov_len = size,
  },
+[1] = {
+.iov_base = (void *)null_buf,
+.iov_len = ETH_ZLEN,
+},
  };
  
  #ifdef DEBUG_NET

@@ -639,6 +644,15 @@ static ssize_t 
qemu_send_packet_async_with_flags(NetClientState *sender,
  return size;
  }
  
+/* Pad to minimum Ethernet frame length for SLiRP and TAP */

+if (sender->info->type == NET_CLIENT_DRIVER_USER ||
+sender->info->type == NET_CLIENT_DRIVER_TAP) {
+if (size < ETH_ZLEN) {
+iov[1].iov_len = ETH_ZLEN - size;
+iovcnt = 2;
+}
+}
+
  /* Let filters handle the packet first */
  ret = filter_receive_iov(sender, NET_FILTER_DIRECTION_TX,
   sender, flags, iov, iovcnt, sent_cb);





Re: [PATCH] ui/gtk: fix NULL pointer dereference

2021-03-07 Thread Akihiko Odaki
2021年3月8日(月) 4:57 Christian Schoenebeck :
>
> DisplaySurface pointer passed to gd_switch() can be NULL, so check this
> before trying to dereference it.
>
> Fixes: c821a58ee7 ("ui/console: Pass placeholder surface to display")
> Reported-by: Coverity (CID 1448421)
> Signed-off-by: Christian Schoenebeck 
> ---
>  ui/gtk.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/ui/gtk.c b/ui/gtk.c
> index 3edaf041de..a27b27d004 100644
> --- a/ui/gtk.c
> +++ b/ui/gtk.c
> @@ -567,7 +567,7 @@ static void gd_switch(DisplayChangeListener *dcl,
>  }
>  vc->gfx.ds = surface;
>
> -if (surface->format == PIXMAN_x8r8g8b8) {
> +if (surface && surface->format == PIXMAN_x8r8g8b8) {
>  /*
>   * PIXMAN_x8r8g8b8 == CAIRO_FORMAT_RGB24
>   *
> @@ -580,7 +580,7 @@ static void gd_switch(DisplayChangeListener *dcl,
>   surface_width(surface),
>   surface_height(surface),
>   surface_stride(surface));
> -} else {
> +} else if (surface) {
>  /* Must convert surface, use pixman to do it. */
>  vc->gfx.convert = pixman_image_create_bits(PIXMAN_x8r8g8b8,
> surface_width(surface),
> --
> 2.20.1
>

When will the DisplaySurface pointer passed to gd_switch() be NULL?
Also, it affects other displays so it should be fixed in ui/console.c,
or fix all relevant displays.



Re: About libfuzzer in qemu

2021-03-07 Thread Alexander Bulekov
I see the problem. You only hit the breakpoint in the first forked
process? I was able to sort-of work around this, using detach-on-fork.


gdb -q --args ./qemu-fuzz-i386
(gef) set follow-fork-mode child
(gef) set detach-on-fork off
(gef) b generic_fuzz.c:667
(gef) r --fuzz-target=generic-fuzz-virtio-vga -runs=1000
...
Thread 3.1 "qemu-fuzz-i386" hit Breakpoint 1, generic_fuzz
(gef) c
Continuing.
[Thread 0x732defc0 (LWP 806) exited]
(gef) info inferiors
  Num  Description   Executable
  1process 31866 /home/alxndr/Downloads/qemu/build-fuzz/qemu-fuzz-i386
  2process 802   /home/alxndr/Downloads/qemu/build-fuzz/qemu-fuzz-i386
* 3/home/alxndr/Downloads/qemu/build-fuzz/qemu-fuzz-i386

# I make a guess that the parent is 802.

(gef) inferior 2 
[Switching to inferior 2 [process 802] 
(/home/alxndr/Downloads/qemu/build-fuzz/qemu-fuzz-i386)]
(gef) c
...
[New Thread 0x7fffca9fe700 (LWP 4538)]
[Switching to Thread 0x732defc0 (LWP 4537)]
Thread 3.1 "qemu-fuzz-i386" hit Breakpoint 1, generic_fuzz
(gef) c
Continuing.
[Thread 0x732defc0 (LWP 4537) exited]
(gef) inferior 2
[Switching to inferior 2 [process 802] 
(/home/alxndr/Downloads/qemu/build-fuzz/qemu-fuzz-i386)]
(gef) c
...

There's probably ways to automate most of this with gdb breakpoint
commands.


I usually don't need to debug more than one child, so this is a new
problem for me :) . Are you simply trying to reproduce a bug/crash?
My basic workflow for that is:
QEMU_FUZZ_TIMEOUT=0 QTEST_LOG=1 FUZZ_SERIALIZE_QTEST=1 \
./qemu-fuzz-target \
   --fuzz-target=generic-fuzz-virtio-vga ./crash-... > /tmp/out
./scripts/oss-fuzz/reorder_fuzzer_qtest_trace.py /tmp/out > /tmp/repro

# In /tmp/out find the line "Starting qemu with Arguments:" and copy the
# args ( without -qtest /dev/null)
less /tmp/out 

export QEMU_ARGS="-display none -machine accel=qtest, -m 512M -machine q35 
-nodefaults -device virtio-vga"

# Reproduce the crash on a non-fuzz binary
./qemu-system-i386 $QEMU_ARGS -qtest stdio < /tmp/repro

For most cases, this should work. Let me know if there's any problem
-Alex



On 210308 1058, Yan Zhiqiang wrote:
> It hasn't changed.
> Can you show me the specific details of the entire debugging process?
> This is my debugging process as follows.(It will not hit the breakpoint as
> you can see)
> 
> ☁  build_qemu  printenv
> > XDG_RUNTIME_DIR=/run/user/500
> > XDG_SESSION_ID=2
> > ZSH=/home/ubuntu/.oh-my-zsh
> > _=/usr/bin/printenv
> > *QEMU_FUZZ_TIMEOUT=0*
> 
> 
> 
> ☁  build_qemu  gdb -q --args ./qemu-fuzz-i386
> > --fuzz-target=generic-fuzz-virtio-vga fuzz-output/
> > pwndbg: loaded 189 commands. Type pwndbg [filter] for a list.
> > pwndbg: created $rebase, $ida gdb functions (can be used with print/break)
> > Reading symbols from ./qemu-fuzz-i386...done.
> > warning: File "/home/ubuntu/qemu-lastest-fuzz-test/qemu/.gdbinit"
> > auto-loading has been declined by your `auto-load safe-path' set to
> > "$debugdir:$datadir/auto-load".
> > To enable execution of this file add
> > add-auto-load-safe-path
> > /home/ubuntu/qemu-lastest-fuzz-test/qemu/.gdbinit
> > line to your configuration file "/home/ubuntu/.gdbinit".
> > To completely disable this security protection add
> > set auto-load safe-path /
> > line to your configuration file "/home/ubuntu/.gdbinit".
> > For more information about this security protection see the
> > "Auto-loading safe path" section in the GDB manual.  E.g., run from the
> > shell:
> > info "(gdb)Auto-loading safe path"
> > pwndbg> b generic_fuzz.c:655
> > Breakpoint 1 at 0x2ca5938: file ../qemu/tests/qtest/fuzz/generic_fuzz.c,
> > line 655.
> > pwndbg> set follow-fork-mode child
> > pwndbg> r
> > Starting program:
> > /home/ubuntu/qemu-lastest-fuzz-test/build_qemu/qemu-fuzz-i386
> > --fuzz-target=generic-fuzz-virtio-vga fuzz-output/
> > [Thread debugging using libthread_db enabled]
> > Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
> > [New Thread 0x70fff700 (LWP 36468)]
> > ==36456==WARNING: ASan doesn't fully support makecontext/swapcontext
> > functions and may produce false positives in some cases!
> > [New Thread 0x7fffd05ff700 (LWP 36469)]
> > INFO: libFuzzer ignores flags that start with '--'
> > INFO: Seed: 1537774383
> > INFO: Loaded 1 modules   (791403 inline 8-bit counters): 791403
> > [0x5f076000, 0x5f13736b),
> > INFO: Loaded 1 PC tables (791403 PCs): 791403
> > [0x5e461b00,0x5f0751b0),
> > [New Thread 0x7fffcd179700 (LWP 36471)]
> > INFO: 7892 files found in fuzz-output/
> > INFO: -max_len is not provided; libFuzzer will not generate inputs larger
> > than 4096 bytes
> > Matching objects by name virtio*
> > This process will try to fuzz the following MemoryRegions:
> >   * vga ioports remapped[0] (size 20)
> >   * qemu extended regs[0] (size 8)
> >   * virtio-pci-device[0] (size 1000)
> >   * vga[4] (size 1)
> >   * msix-pba[0] (size 8)
> >   * vga[2] (size 10)
> >   * bochs dispi interface[0] (size 

Re: [PATCH V4 00/10] Detect reentrant RX casued by loopback

2021-03-07 Thread Jason Wang



On 2021/3/5 5:38 下午, Philippe Mathieu-Daudé wrote:

On 3/5/21 7:26 AM, Jason Wang wrote:

Hi All:

Followed by commit 22dc8663d9 ("net: forbid the reentrant RX"), we
still need to fix the issues casued by loopback mode where the NIC
usually it via calling nc->info->receive() directly.

The fix is to introduce new network helper and check the
queue->delivering.

This series addresses CVE-2021-3416.

Thanks

Changes since V3:
- clarify CVE number in the commit log
- ident fix

Changes since V2:
- add more fixes from Alexander

Changes since V1:

- Fix dp8393x compiling
- Add rtl8139 fix
- Tweak the commit log
- Silent patchew warning

Alexander Bulekov (4):
   rtl8139: switch to use qemu_receive_packet() for loopback
   pcnet: switch to use qemu_receive_packet() for loopback
   cadence_gem: switch to use qemu_receive_packet() for loopback
   lan9118: switch to use qemu_receive_packet() for loopback

Jason Wang (6):
   net: introduce qemu_receive_packet()
   e1000: switch to use qemu_receive_packet() for loopback
   dp8393x: switch to use qemu_receive_packet() for loopback packet
   msf2-mac: switch to use qemu_receive_packet() for loopback
   sungem: switch to use qemu_receive_packet() for loopback
   tx_pkt: switch to use qemu_receive_packet_iov() for loopback

  hw/net/cadence_gem.c |  4 ++--
  hw/net/dp8393x.c |  2 +-
  hw/net/e1000.c   |  2 +-
  hw/net/lan9118.c |  2 +-
  hw/net/msf2-emac.c   |  2 +-
  hw/net/net_tx_pkt.c  |  2 +-
  hw/net/pcnet.c   |  2 +-
  hw/net/rtl8139.c |  2 +-
  hw/net/sungem.c  |  2 +-
  include/net/net.h|  5 +
  include/net/queue.h  |  8 
  net/net.c| 38 +++---
  net/queue.c  | 22 ++
  13 files changed, 76 insertions(+), 17 deletions(-)


LGTM, maybe worth adding the "Cc: qemu-sta...@nongnu.org" tag
when applying.



Yes, will do.

Thanks









[Bug 1918084] [NEW] Build fails on macOS 11.2.2

2021-03-07 Thread Eddy Hahn
Public bug reported:

Hi,

I got the latest version from git. I have pre-compiled the dependency
libraries. All good. configure creates the necessary files. When I build
I got the following error:

[1368/6454] Compiling C object 
libcapstone.a.p/capstone_arch_AArch64_AArch64InstPrinter.c.o
ninja: build stopped: subcommand failed.
make[1]: *** [run-ninja] Error 1
make: *** [all] Error 2

I've ran make as make -j 8

original config:

PKG_CONFIG_PATH="$SERVERPLUS_DIR/dependencies/glib/lib/pkgconfig:$SERVERPLUS_DIR/dependencies/pixman/lib/pkgconfig:$SERVERPLUS_DIR/dependencies
/cyrus-sasl/lib/pkgconfig" ./configure --prefix="$SERVERPLUS_DIR"
--enable-hvf --enable-cocoa --enable-vnc-sasl --enable-auth-pam
--ninja=/opt/build/build/stage/tools/ninja/ninja
--python="$SERVERPLUS_DIR/dependencies/python/bin/python3" --enable-bsd-
user

if I build with --target-list=x86_64-softmmu then it will build but I
will get only the x86_64 QEMU built. With 5.0 I could build all
emulators.

$SERVERPLUS_DIR is my target dir.

Thanks,

Eddy

** Affects: qemu
 Importance: Undecided
 Status: New

-- 
You received this bug notification because you are a member of qemu-
devel-ml, which is subscribed to QEMU.
https://bugs.launchpad.net/bugs/1918084

Title:
  Build fails on macOS 11.2.2

Status in QEMU:
  New

Bug description:
  Hi,

  I got the latest version from git. I have pre-compiled the dependency
  libraries. All good. configure creates the necessary files. When I
  build I got the following error:

  [1368/6454] Compiling C object 
libcapstone.a.p/capstone_arch_AArch64_AArch64InstPrinter.c.o
  ninja: build stopped: subcommand failed.
  make[1]: *** [run-ninja] Error 1
  make: *** [all] Error 2

  I've ran make as make -j 8

  original config:

  
PKG_CONFIG_PATH="$SERVERPLUS_DIR/dependencies/glib/lib/pkgconfig:$SERVERPLUS_DIR/dependencies/pixman/lib/pkgconfig:$SERVERPLUS_DIR/dependencies
  /cyrus-sasl/lib/pkgconfig" ./configure --prefix="$SERVERPLUS_DIR"
  --enable-hvf --enable-cocoa --enable-vnc-sasl --enable-auth-pam
  --ninja=/opt/build/build/stage/tools/ninja/ninja
  --python="$SERVERPLUS_DIR/dependencies/python/bin/python3" --enable-
  bsd-user

  if I build with --target-list=x86_64-softmmu then it will build but I
  will get only the x86_64 QEMU built. With 5.0 I could build all
  emulators.

  $SERVERPLUS_DIR is my target dir.

  Thanks,

  Eddy

To manage notifications about this bug go to:
https://bugs.launchpad.net/qemu/+bug/1918084/+subscriptions



SubmitAPatch wiki page has broken link to coding style

2021-03-07 Thread Rebecca Cran
In commit cbcf09872a936ccefef6a34298046d3b9aefc148 on February 25th 
CODING_STYLE.rst was moved into the developer manual. So, the "Use the 
QEMU coding style" section of 
https://wiki.qemu.org/Contribute/SubmitAPatch should probably be updated 
to link to:


https://gitlab.com/qemu-project/qemu/-/blob/master/docs/devel/style.rst

--
Rebecca Cran



Re: [RFC PATCH v3 00/10] net: Handle short frames for SLiRP/TAP interfaces

2021-03-07 Thread Bin Meng
On Thu, Mar 4, 2021 at 3:12 AM Philippe Mathieu-Daudé  wrote:
>
> This is Bin's series but using iovec structure in 1st patch
> for zero copy.
>
> Bin's cover:
>
> The minimum Ethernet frame length is 60 bytes. For short frames with
> smaller length like ARP packets (only 42 bytes), on a real world NIC
> it can choose either padding its length to the minimum required 60
> bytes, or sending it out directly to the wire. Such behavior can be
> hardcoded or controled by a register bit. Similarly on the receive
> path, NICs can choose either dropping such short frames directly or
> handing them over to software to handle.
>
> On the other hand, for the network backends SLiRP/TAP, they don't
> expose a way to control the short frame behavior. As of today they
> just send/receive data from/to the other end connected to them,
> which means any sized packet is acceptable. So they can send and
> receive short frames without any problem. It is observed that ARP
> packets sent from SLiRP/TAP are 42 bytes, and SLiRP/TAP just send
> these ARP packets to the other end which might be a NIC model that
> does not allow short frames to pass through.
>
> To provide better compatibility, for packets sent from SLiRP/TAP, we
> change to pad short frames before sending it out to the other end.
> This ensures SLiRP/TAP as an Ethernet sender do not violate the spec.
> But with this change, the behavior of dropping short frames in the
> NIC model cannot be emulated because it always receives a packet that
> is spec complaint. The capability of sending short frames from NIC
> models are still supported and short frames can still pass through
> SLiRP/TAP interfaces.
>
> This commit should be able to fix the issue as reported with some
> NIC models before, that ARP requests get dropped, preventing the
> guest from becoming visible on the network. It was workarounded in
> these NIC models on the receive path, that when a short frame is
> received, it is padded up to 60 bytes.

Ping?



Re: [PATCH] inet_parse: Clarify IPv6 comment and error message

2021-03-07 Thread Doug Evans
Not sure how this "Author email address is mangled" happened.

$ git format-patch -o patches/error-parsing-ipv6 -1
$ git send-email --to='qemu-devel@nongnu.org,Samuel Thibault <
samuel.thiba...@ens-lyon.org>,"Daniel P. Berrangé" ' \
--smtp-server=foo
patches/error-parsing-ipv6/0001-inet_parse-Clarify-IPv6-comment-and-error-message.patch

It's possible my smtp-server arg munged things incorrectly, but I've done
the identical thing for previous patches and not seen this for at least
some of them.
Sigh.


On Sun, Mar 7, 2021 at 4:33 PM  wrote:

> Patchew URL:
> https://patchew.org/QEMU/20210308002928.3385275-1-...@google.com/
>
>
>
> Hi,
>
> This series seems to have some coding style problems. See output below for
> more information:
>
> Type: series
> Message-id: 20210308002928.3385275-1-...@google.com
> Subject: [PATCH] inet_parse: Clarify IPv6 comment and error message
>
> === TEST SCRIPT BEGIN ===
> #!/bin/bash
> git rev-parse base > /dev/null || exit 0
> git config --local diff.renamelimit 0
> git config --local diff.renames True
> git config --local diff.algorithm histogram
> ./scripts/checkpatch.pl --mailback base..
> === TEST SCRIPT END ===
>
> Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
> From https://github.com/patchew-project/qemu
>  * [new tag] patchew/20210308002928.3385275-1-...@google.com ->
> patchew/20210308002928.3385275-1-...@google.com
> Switched to a new branch 'test'
> 6e42a49 inet_parse: Clarify IPv6 comment and error message
>
> === OUTPUT BEGIN ===
> ERROR: Author email address is mangled by the mailing list
> #2:
> Author: Doug Evans via 
>
> total: 1 errors, 0 warnings, 14 lines checked
>
> Commit 6e42a4981895 (inet_parse: Clarify IPv6 comment and error message)
> has style problems, please review.  If any of these errors
> are false positives report them to the maintainer, see
> CHECKPATCH in MAINTAINERS.
> === OUTPUT END ===
>
> Test command exited with code: 1
>
>
> The full log is available at
>
> http://patchew.org/logs/20210308002928.3385275-1-...@google.com/testing.checkpatch/?type=message
> .
> ---
> Email generated automatically by Patchew [https://patchew.org/].
> Please send your feedback to patchew-de...@redhat.com


Re: [PATCH v3] target/m68k: implement rtr instruction

2021-03-07 Thread Richard Henderson

On 3/7/21 1:25 PM, Laurent Vivier wrote:

This is needed to boot MacOS ROM.

Pull the condition code and the program counter from the stack.

Operation:

 (SP) -> CCR
 SP + 2 -> SP
 (SP) -> PC
 SP + 4 -> SP

This operation is not privileged.

Reported-by: Mark Cave-Ayland
Tested-by: Mark Cave-Ayland
Signed-off-by: Laurent Vivier
---


Reviewed-by: Richard Henderson 

r~



Re: [PATCH 2/2] target/m68k: add M68K_FEATURE_NO_DALIGN feature

2021-03-07 Thread Richard Henderson

On 3/7/21 12:26 PM, Mark Cave-Ayland wrote:

According to the M68040UM Appendix D the requirement for data accesses to be
word aligned is only for the 68000, 68008 and 68010 CPUs. Later CPUs from the
68020 onwards will allow unaligned data accesses but at the cost of being less
efficient.

Add a new M68K_FEATURE_NO_DALIGN feature to specify that data accesses are not
required to be word aligned, and don't perform the alignment on the stack
pointer when taking an exception if this feature is not selected.


How about a positive, rather than negative name, like 
M68K_FEATURE_UNALIGNED_DATA?

This points out that we should be raising Address Error without this feature. 
This requires a moderate amount of cleanup in translate, manipulating 
MO_ALIGN{,_2} as part of the MemOp parameter to tcg_gen_qemu_{ld,st}_i32.



r~



Re: [PATCH v4 1/5] char: add goldfish-tty

2021-03-07 Thread Richard Henderson

On 3/7/21 11:57 AM, Laurent Vivier wrote:

Le 07/03/2021 à 20:24, Philippe Mathieu-Daudé a écrit :

The spec says this register is only available on 64-bit targets.

Should we restrict this "#if TARGET_LONG_SIZE == 8"?
else log_mask(GUEST_ERROR)...

This seems overkill to me but that would respect the spec.


TARGET_LONG_SIZE depends on CPU, I don't think we can use it here.


TARGET_LONG_BITS is in fact poisoned -- you can't use it here.


r~



Re: [PATCH v2] target/m68k: implement rtr instruction

2021-03-07 Thread Richard Henderson

On 3/7/21 11:08 AM, Laurent Vivier wrote:

Both loads should happen (and thus exceptions recognized) before any other 
state writeback.


Something like that?

 ccr = gen_load(s, OS_WORD, QREG_SP, 0, IS_USER(s));
 tcg_gen_addi_i32(QREG_SP, QREG_SP, 2);
 tmp = gen_load(s, OS_LONG, QREG_SP, 0, IS_USER(s));
 tcg_gen_addi_i32(QREG_SP, QREG_SP, 4);


Can't change SP before final load either.

  addr = tcg_temp_new_i32();
  tcg_gen_addi_i32(addr, QREG_SP, 2);
  tmp = gen_load(s, OS_LONG, addr, 0, IS_USER(s));
  tcg_gen_addi_i32(QREG_SP, addr, 4);
  tcg_temp_free_i32(addr);


r~



Re: [PATCH] inet_parse: Clarify IPv6 comment and error message

2021-03-07 Thread no-reply
Patchew URL: https://patchew.org/QEMU/20210308002928.3385275-1-...@google.com/



Hi,

This series seems to have some coding style problems. See output below for
more information:

Type: series
Message-id: 20210308002928.3385275-1-...@google.com
Subject: [PATCH] inet_parse: Clarify IPv6 comment and error message

=== TEST SCRIPT BEGIN ===
#!/bin/bash
git rev-parse base > /dev/null || exit 0
git config --local diff.renamelimit 0
git config --local diff.renames True
git config --local diff.algorithm histogram
./scripts/checkpatch.pl --mailback base..
=== TEST SCRIPT END ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
From https://github.com/patchew-project/qemu
 * [new tag] patchew/20210308002928.3385275-1-...@google.com -> 
patchew/20210308002928.3385275-1-...@google.com
Switched to a new branch 'test'
6e42a49 inet_parse: Clarify IPv6 comment and error message

=== OUTPUT BEGIN ===
ERROR: Author email address is mangled by the mailing list
#2: 
Author: Doug Evans via 

total: 1 errors, 0 warnings, 14 lines checked

Commit 6e42a4981895 (inet_parse: Clarify IPv6 comment and error message) has 
style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
=== OUTPUT END ===

Test command exited with code: 1


The full log is available at
http://patchew.org/logs/20210308002928.3385275-1-...@google.com/testing.checkpatch/?type=message.
---
Email generated automatically by Patchew [https://patchew.org/].
Please send your feedback to patchew-de...@redhat.com

[PATCH] inet_parse: Clarify IPv6 comment and error message

2021-03-07 Thread Doug Evans via
Wrapping an IP address in square brackets does not necessarily
mean the address is an IPv6 address. The wrapping is just an aid
to parsing since IPv6 addresses have colons, but does not provide
semantic information.
E.g., [127.0.0.1] is a valid way to write 127.0.0.1.

Signed-off-by: Doug Evans 
---
 util/qemu-sockets.c | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c
index 8af0278f15..0c41d372c0 100644
--- a/util/qemu-sockets.c
+++ b/util/qemu-sockets.c
@@ -635,9 +635,12 @@ int inet_parse(InetSocketAddress *addr, const char *str, 
Error **errp)
 return -1;
 }
 } else if (str[0] == '[') {
-/* IPv6 addr */
+/*
+ * Probably, but not necessarily, an IPv6 addr.
+ * Note that [127.0.0.1] is also valid.
+ */
 if (sscanf(str, "[%64[^]]]:%32[^,]%n", host, port, ) != 2) {
-error_setg(errp, "error parsing IPv6 address '%s'", str);
+error_setg(errp, "error parsing address '%s'", str);
 return -1;
 }
 } else {
-- 
2.30.1.766.gb4fecdf3b7-goog




[PATCH 2/4] hw/mips/malta: Get pflash MemoryRegion with sysbus_mmio_get_region()

2021-03-07 Thread Philippe Mathieu-Daudé
TYPE_PFLASH_CFI01 is a TYPE_SYS_BUS_DEVICE which registers its romd
MemoryRegion with sysbus_init_mmio(), so we can use the generic
sysbus_mmio_get_region() to get the region, no need for a specific
pflash_cfi01_get_memory() helper.

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/mips/malta.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/mips/malta.c b/hw/mips/malta.c
index 9afc0b427bf..43b985bccf9 100644
--- a/hw/mips/malta.c
+++ b/hw/mips/malta.c
@@ -1295,7 +1295,7 @@ void mips_malta_init(MachineState *machine)
dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
65536,
4, 0x, 0x, 0x, 0x, be);
-bios = pflash_cfi01_get_memory(fl);
+bios = sysbus_mmio_get_region(SYS_BUS_DEVICE(fl), 0);
 fl_idx++;
 if (kernel_filename) {
 ram_low_size = MIN(ram_size, 256 * MiB);
-- 
2.26.2




[PATCH 1/4] hw/i386/pc: Get pflash MemoryRegion with sysbus_mmio_get_region()

2021-03-07 Thread Philippe Mathieu-Daudé
TYPE_PFLASH_CFI01 is a TYPE_SYS_BUS_DEVICE which registers its romd
MemoryRegion with sysbus_init_mmio(), so we can use the generic
sysbus_mmio_get_region() to get the region, no need for a specific
pflash_cfi01_get_memory() helper.

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/i386/pc_sysfw.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c
index 9fe72b370e8..caad9cbd5eb 100644
--- a/hw/i386/pc_sysfw.c
+++ b/hw/i386/pc_sysfw.c
@@ -297,7 +297,7 @@ static void pc_system_flash_map(PCMachineState *pcms,
 0x1ULL - total_size);
 
 if (i == 0) {
-flash_mem = pflash_cfi01_get_memory(system_flash);
+flash_mem = sysbus_mmio_get_region(SYS_BUS_DEVICE(system_flash), 
0);
 pc_isa_bios_init(rom_memory, flash_mem, size);
 
 /* Encrypt the pflash boot ROM */
-- 
2.26.2




[PATCH 3/4] hw/xtensa/xtfpga: Get pflash MemoryRegion with sysbus_mmio_get_region()

2021-03-07 Thread Philippe Mathieu-Daudé
TYPE_PFLASH_CFI01 is a TYPE_SYS_BUS_DEVICE which registers its romd
MemoryRegion with sysbus_init_mmio(), so we can use the generic
sysbus_mmio_get_region() to get the region, no need for a specific
pflash_cfi01_get_memory() helper.

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/xtensa/xtfpga.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/hw/xtensa/xtfpga.c b/hw/xtensa/xtfpga.c
index 7be53f1895b..1d15a9aae9f 100644
--- a/hw/xtensa/xtfpga.c
+++ b/hw/xtensa/xtfpga.c
@@ -460,10 +460,11 @@ static void xtfpga_init(const XtfpgaBoardDesc *board, 
MachineState *machine)
 }
 } else {
 if (flash) {
-MemoryRegion *flash_mr = pflash_cfi01_get_memory(flash);
+MemoryRegion *flash_mr;
 MemoryRegion *flash_io = g_malloc(sizeof(*flash_io));
 uint32_t size = env->config->sysrom.location[0].size;
 
+flash_mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(flash), 0);
 if (board->flash->size - board->flash->boot_base < size) {
 size = board->flash->size - board->flash->boot_base;
 }
-- 
2.26.2




[PATCH 4/4] hw/block/pflash_cfi01: Remove pflash_cfi01_get_memory()

2021-03-07 Thread Philippe Mathieu-Daudé
Since we replaced all uses of pflash_cfi01_get_memory() with
sysbus_mmio_get_region(), we can now remove this unused helper.

Signed-off-by: Philippe Mathieu-Daudé 
---
 include/hw/block/flash.h | 1 -
 hw/block/pflash_cfi01.c  | 5 -
 2 files changed, 6 deletions(-)

diff --git a/include/hw/block/flash.h b/include/hw/block/flash.h
index 7dde0adcee7..6c87b584c1d 100644
--- a/include/hw/block/flash.h
+++ b/include/hw/block/flash.h
@@ -22,7 +22,6 @@ PFlashCFI01 *pflash_cfi01_register(hwaddr base,
uint16_t id2, uint16_t id3,
int be);
 BlockBackend *pflash_cfi01_get_blk(PFlashCFI01 *fl);
-MemoryRegion *pflash_cfi01_get_memory(PFlashCFI01 *fl);
 void pflash_cfi01_legacy_drive(PFlashCFI01 *dev, DriveInfo *dinfo);
 
 /* pflash_cfi02.c */
diff --git a/hw/block/pflash_cfi01.c b/hw/block/pflash_cfi01.c
index 22287a1522e..d6d3d94ac68 100644
--- a/hw/block/pflash_cfi01.c
+++ b/hw/block/pflash_cfi01.c
@@ -984,11 +984,6 @@ BlockBackend *pflash_cfi01_get_blk(PFlashCFI01 *fl)
 return fl->blk;
 }
 
-MemoryRegion *pflash_cfi01_get_memory(PFlashCFI01 *fl)
-{
-return >mem;
-}
-
 /*
  * Handle -drive if=pflash for machines that use properties.
  * If @dinfo is null, do nothing.
-- 
2.26.2




[PATCH 0/4] hw/block/pflash_cfi01: Remove pflash_cfi01_get_memory()

2021-03-07 Thread Philippe Mathieu-Daudé
TYPE_PFLASH_CFI01 is a TYPE_SYS_BUS_DEVICE which registers its romd
MemoryRegion with sysbus_init_mmio(), so we can use the generic
sysbus_mmio_get_region() to get the region, no need for a specific
pflash_cfi01_get_memory() helper.

First replace the few pflash_cfi01_get_memory() uses by
sysbus_mmio_get_region(), then remove the now unused helper.

Philippe Mathieu-Daudé (4):
  hw/i386/pc: Get pflash MemoryRegion with sysbus_mmio_get_region()
  hw/mips/malta: Get pflash MemoryRegion with sysbus_mmio_get_region()
  hw/xtensa/xtfpga: Get pflash MemoryRegion with
sysbus_mmio_get_region()
  hw/block/pflash_cfi01: Remove pflash_cfi01_get_memory()

 include/hw/block/flash.h | 1 -
 hw/block/pflash_cfi01.c  | 5 -
 hw/i386/pc_sysfw.c   | 2 +-
 hw/mips/malta.c  | 2 +-
 hw/xtensa/xtfpga.c   | 3 ++-
 5 files changed, 4 insertions(+), 9 deletions(-)

-- 
2.26.2




[PATCH v3] target/m68k: implement rtr instruction

2021-03-07 Thread Laurent Vivier
This is needed to boot MacOS ROM.

Pull the condition code and the program counter from the stack.

Operation:

(SP) -> CCR
SP + 2 -> SP
(SP) -> PC
SP + 4 -> SP

This operation is not privileged.

Reported-by: Mark Cave-Ayland 
Tested-by: Mark Cave-Ayland 
Signed-off-by: Laurent Vivier 
---

Notes:
v3: put loads before state writeback

v2: update comment
SP + 4 -> SP

 target/m68k/translate.c | 20 
 1 file changed, 20 insertions(+)

diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index ac936ebe8f14..200018ae6a63 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -2969,6 +2969,25 @@ DISAS_INSN(rtd)
 gen_jmp(s, tmp);
 }
 
+DISAS_INSN(rtr)
+{
+TCGv tmp;
+TCGv ccr;
+TCGv sp;
+
+sp = tcg_temp_new();
+ccr = gen_load(s, OS_WORD, QREG_SP, 0, IS_USER(s));
+tcg_gen_addi_i32(sp, QREG_SP, 2);
+tmp = gen_load(s, OS_LONG, sp, 0, IS_USER(s));
+tcg_gen_addi_i32(QREG_SP, sp, 4);
+tcg_temp_free(sp);
+
+gen_set_sr(s, ccr, true);
+tcg_temp_free(ccr);
+
+gen_jmp(s, tmp);
+}
+
 DISAS_INSN(rts)
 {
 TCGv tmp;
@@ -6015,6 +6034,7 @@ void register_m68k_insns (CPUM68KState *env)
 BASE(nop,   4e71, );
 INSN(rtd,   4e74, , RTD);
 BASE(rts,   4e75, );
+INSN(rtr,   4e77, , M68000);
 BASE(jump,  4e80, ffc0);
 BASE(jump,  4ec0, ffc0);
 INSN(addsubq,   5000, f080, M68000);
-- 
2.29.2




Re: [PATCH 2/2] target/m68k: add M68K_FEATURE_NO_DALIGN feature

2021-03-07 Thread Laurent Vivier
Le 07/03/2021 à 21:26, Mark Cave-Ayland a écrit :
> According to the M68040UM Appendix D the requirement for data accesses to be
> word aligned is only for the 68000, 68008 and 68010 CPUs. Later CPUs from the
> 68020 onwards will allow unaligned data accesses but at the cost of being less
> efficient.
> 
> Add a new M68K_FEATURE_NO_DALIGN feature to specify that data accesses are not
> required to be word aligned, and don't perform the alignment on the stack
> pointer when taking an exception if this feature is not selected.
> 
> This is required because the MacOS DAFB driver attempts to call an A-trap
> with a byte-aligned stack pointer during initialisation and without this the
> stack pointer is off by one when the A-trap returns.
> 
> Signed-off-by: Mark Cave-Ayland 
> ---
>  target/m68k/cpu.c   | 1 +
>  target/m68k/cpu.h   | 1 +
>  target/m68k/op_helper.c | 5 -
>  3 files changed, 6 insertions(+), 1 deletion(-)
> 
> diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c
> index 37d2ed9dc7..ea51753eb0 100644
> --- a/target/m68k/cpu.c
> +++ b/target/m68k/cpu.c
> @@ -161,6 +161,7 @@ static void m68020_cpu_initfn(Object *obj)
>  m68k_set_feature(env, M68K_FEATURE_CAS);
>  m68k_set_feature(env, M68K_FEATURE_CHK2);
>  m68k_set_feature(env, M68K_FEATURE_MSP);
> +m68k_set_feature(env, M68K_FEATURE_NO_DALIGN);
>  }
>  
>  /*
> diff --git a/target/m68k/cpu.h b/target/m68k/cpu.h
> index 7c3feeaf8a..1e0876bba8 100644
> --- a/target/m68k/cpu.h
> +++ b/target/m68k/cpu.h
> @@ -505,6 +505,7 @@ enum m68k_features {
>  M68K_FEATURE_CHK2,  /* CHK2 insn. (680[2346]0, and CPU32) */
>  M68K_FEATURE_MOVEP, /* MOVEP insn. (680[01234]0, and CPU32) */
>  M68K_FEATURE_MOVEC, /* MOVEC insn. (from 68010) */
> +M68K_FEATURE_NO_DALIGN, /* Unaligned data accesses (680[2346]0) */
>  };
>  
>  static inline int m68k_feature(CPUM68KState *env, int feature)
> diff --git a/target/m68k/op_helper.c b/target/m68k/op_helper.c
> index 59a6448296..71b3df0910 100644
> --- a/target/m68k/op_helper.c
> +++ b/target/m68k/op_helper.c
> @@ -348,7 +348,10 @@ static void m68k_interrupt_all(CPUM68KState *env, int 
> is_hw)
>  cpu_m68k_set_sr(env, sr);
>  sp = env->aregs[7];
>  
> -sp &= ~1;
> +if (!m68k_feature(env, M68K_FEATURE_NO_DALIGN)) {
> +sp &= ~1;
> +}
> +
>  if (cs->exception_index == EXCP_ACCESS) {
>  if (env->mmu.fault) {
>  cpu_abort(cs, "DOUBLE MMU FAULT\n");
> 

Reviewed-by: Laurent Vivier 



Re: [PATCH 1/2] target/m68k: don't set SSW ATC bit for physical bus errors

2021-03-07 Thread Laurent Vivier
Le 07/03/2021 à 21:26, Mark Cave-Ayland a écrit :
> If a NuBus slot doesn't contain a card, the Quadra hardware generates a 
> physical
> bus error if the CPU attempts to access the slot address space. Both Linux and
> MacOS use a separate bus error handler during NuBus accesses in order to 
> detect
> and recover when addressing empty slots.
> 
> According to the MC68040 users manual the ATC bit of the SSW is used to
> distinguish between ATC faults and physical bus errors. MacOS specifically 
> checks
> the stack frame generated by a NuBus error and panics if the SSW ATC bit is 
> set.
> 
> Update m68k_cpu_transaction_failed() so that the SSW ATC bit is not set if the
> memory API returns MEMTX_DECODE_ERROR which will be used to indicate that an
> access to an empty NuBus slot occurred.
> 
> Signed-off-by: Mark Cave-Ayland 
> ---
>  target/m68k/op_helper.c | 12 +++-
>  1 file changed, 11 insertions(+), 1 deletion(-)
> 
> diff --git a/target/m68k/op_helper.c b/target/m68k/op_helper.c
> index 202498deb5..59a6448296 100644
> --- a/target/m68k/op_helper.c
> +++ b/target/m68k/op_helper.c
> @@ -468,7 +468,17 @@ void m68k_cpu_transaction_failed(CPUState *cs, hwaddr 
> physaddr, vaddr addr,
>  
>  if (m68k_feature(env, M68K_FEATURE_M68040)) {
>  env->mmu.mmusr = 0;
> -env->mmu.ssw |= M68K_ATC_040;
> +
> +/*
> + * According to the MC68040 users manual the ATC bit of the SSW is
> + * used to distinguish between ATC faults and physical bus errors.
> + * In the case of a bus error e.g. during nubus read from an empty
> + * slot this bit should not be set
> + */
> +if (response != MEMTX_DECODE_ERROR) {
> +env->mmu.ssw |= M68K_ATC_040;
> +}
> +
>  /* FIXME: manage MMU table access error */
>  env->mmu.ssw &= ~M68K_TM_040;
>  if (env->sr & SR_S) { /* SUPERVISOR */
> 

Reviewed-by: Laurent Vivier 



[PATCH v5 4/5] m68k: add a system controller

2021-03-07 Thread Laurent Vivier
Add a system controller for the m68k-virt machine.
This controller allows the kernel to power off or reset the machine.

Signed-off-by: Laurent Vivier 
Reviewed-by: Richard Henderson 
---
 include/hw/misc/m68k_virt_ctrl.h |  22 +
 hw/misc/m68k_virt_ctrl.c | 152 +++
 hw/misc/Kconfig  |   3 +
 hw/misc/meson.build  |   3 +
 hw/misc/trace-events |   7 ++
 5 files changed, 187 insertions(+)
 create mode 100644 include/hw/misc/m68k_virt_ctrl.h
 create mode 100644 hw/misc/m68k_virt_ctrl.c

diff --git a/include/hw/misc/m68k_virt_ctrl.h b/include/hw/misc/m68k_virt_ctrl.h
new file mode 100644
index ..1db7960e5477
--- /dev/null
+++ b/include/hw/misc/m68k_virt_ctrl.h
@@ -0,0 +1,22 @@
+/*
+ * SPDX-License-Identifer: GPL-2.0-or-later
+ *
+ * Virt m68k system Controller
+ */
+
+#ifndef M68K_VIRT_CTRL_H
+#define M68K_VIRT_CTRL_H
+
+#define TYPE_M68K_VIRT_CTRL "m68k-virt-ctrl"
+OBJECT_DECLARE_SIMPLE_TYPE(M68KVirtCtrlState, M68K_VIRT_CTRL)
+
+struct M68KVirtCtrlState {
+SysBusDevice parent_obj;
+
+MemoryRegion iomem;
+qemu_irq irq;
+
+uint32_t irq_enabled;
+};
+
+#endif
diff --git a/hw/misc/m68k_virt_ctrl.c b/hw/misc/m68k_virt_ctrl.c
new file mode 100644
index ..fb34aa10211a
--- /dev/null
+++ b/hw/misc/m68k_virt_ctrl.c
@@ -0,0 +1,152 @@
+/*
+ * SPDX-License-Identifer: GPL-2.0-or-later
+ *
+ * Virt m68k system Controller
+ */
+
+#include "qemu/osdep.h"
+#include "hw/irq.h"
+#include "hw/qdev-properties.h"
+#include "hw/sysbus.h"
+#include "migration/vmstate.h"
+#include "qemu/log.h"
+#include "trace.h"
+#include "sysemu/runstate.h"
+#include "hw/misc/m68k_virt_ctrl.h"
+
+enum {
+REG_FEATURES = 0x00,
+REG_CMD  = 0x04,
+};
+
+#define FEAT_POWER_CTRL 0x0001
+
+enum {
+CMD_NOOP,
+CMD_RESET,
+CMD_HALT,
+CMD_PANIC,
+};
+
+static uint64_t m68k_virt_ctrl_read(void *opaque, hwaddr addr,
+unsigned size)
+{
+M68KVirtCtrlState *s = opaque;
+uint64_t value = 0;
+
+switch (addr) {
+case REG_FEATURES:
+value = FEAT_POWER_CTRL;
+break;
+default:
+qemu_log_mask(LOG_UNIMP,
+  "%s: unimplemented register read 0x%02"HWADDR_PRIx"\n",
+  __func__, addr);
+break;
+}
+
+trace_m68k_virt_ctrl_write(s, addr, size, value);
+
+return value;
+}
+
+static void m68k_virt_ctrl_write(void *opaque, hwaddr addr,
+ uint64_t value, unsigned size)
+{
+M68KVirtCtrlState *s = opaque;
+
+trace_m68k_virt_ctrl_write(s, addr, size, value);
+
+switch (addr) {
+case REG_CMD:
+switch (value) {
+case CMD_NOOP:
+break;
+case CMD_RESET:
+qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
+break;
+case CMD_HALT:
+qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
+break;
+case CMD_PANIC:
+qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_PANIC);
+break;
+}
+break;
+default:
+qemu_log_mask(LOG_UNIMP,
+  "%s: unimplemented register write 0x%02"HWADDR_PRIx"\n",
+  __func__, addr);
+break;
+}
+}
+
+static const MemoryRegionOps m68k_virt_ctrl_ops = {
+.read = m68k_virt_ctrl_read,
+.write = m68k_virt_ctrl_write,
+.endianness = DEVICE_NATIVE_ENDIAN,
+.valid.max_access_size = 4,
+.impl.max_access_size = 4,
+};
+
+static void m68k_virt_ctrl_reset(DeviceState *dev)
+{
+M68KVirtCtrlState *s = M68K_VIRT_CTRL(dev);
+
+trace_m68k_virt_ctrl_reset(s);
+}
+
+static void m68k_virt_ctrl_realize(DeviceState *dev, Error **errp)
+{
+M68KVirtCtrlState *s = M68K_VIRT_CTRL(dev);
+
+trace_m68k_virt_ctrl_instance_init(s);
+
+memory_region_init_io(>iomem, OBJECT(s), _virt_ctrl_ops, s,
+  "m68k-virt-ctrl", 0x100);
+}
+
+static const VMStateDescription vmstate_m68k_virt_ctrl = {
+.name = "m68k-virt-ctrl",
+.version_id = 1,
+.minimum_version_id = 1,
+.fields = (VMStateField[]) {
+VMSTATE_UINT32(irq_enabled, M68KVirtCtrlState),
+VMSTATE_END_OF_LIST()
+}
+};
+
+static void m68k_virt_ctrl_instance_init(Object *obj)
+{
+SysBusDevice *dev = SYS_BUS_DEVICE(obj);
+M68KVirtCtrlState *s = M68K_VIRT_CTRL(obj);
+
+trace_m68k_virt_ctrl_instance_init(s);
+
+sysbus_init_mmio(dev, >iomem);
+sysbus_init_irq(dev, >irq);
+}
+
+static void m68k_virt_ctrl_class_init(ObjectClass *oc, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(oc);
+
+dc->reset = m68k_virt_ctrl_reset;
+dc->realize = m68k_virt_ctrl_realize;
+dc->vmsd = _m68k_virt_ctrl;
+}
+
+static const TypeInfo m68k_virt_ctrl_info = {
+.name = TYPE_M68K_VIRT_CTRL,
+.parent = TYPE_SYS_BUS_DEVICE,
+.class_init = m68k_virt_ctrl_class_init,
+.instance_init = 

[PATCH v5 3/5] m68k: add an interrupt controller

2021-03-07 Thread Laurent Vivier
A (generic) copy of the GLUE device we already have for q800 to use with
the m68k-virt machine.
The q800 one would disappear in the future as q800 uses actually the djMEMC
controller.

Signed-off-by: Laurent Vivier 
Reviewed-by: Richard Henderson 
Reviewed-by: Philippe Mathieu-Daudé 
---
 include/hw/intc/m68k_irqc.h |  41 +
 hw/intc/m68k_irqc.c | 119 
 hw/intc/Kconfig |   3 +
 hw/intc/meson.build |   1 +
 4 files changed, 164 insertions(+)
 create mode 100644 include/hw/intc/m68k_irqc.h
 create mode 100644 hw/intc/m68k_irqc.c

diff --git a/include/hw/intc/m68k_irqc.h b/include/hw/intc/m68k_irqc.h
new file mode 100644
index ..dbcfcfc2e000
--- /dev/null
+++ b/include/hw/intc/m68k_irqc.h
@@ -0,0 +1,41 @@
+/*
+ * SPDX-License-Identifer: GPL-2.0-or-later
+ *
+ * QEMU Motorola 680x0 IRQ Controller
+ *
+ * (c) 2020 Laurent Vivier 
+ *
+ */
+
+#ifndef M68K_IRQC_H
+#define M68K_IRQC_H
+
+#include "hw/sysbus.h"
+
+#define TYPE_M68K_IRQC "m68k-irq-controller"
+#define M68K_IRQC(obj) OBJECT_CHECK(M68KIRQCState, (obj), \
+TYPE_M68K_IRQC)
+
+#define M68K_IRQC_AUTOVECTOR_BASE 25
+
+enum {
+M68K_IRQC_LEVEL_1 = 0,
+M68K_IRQC_LEVEL_2,
+M68K_IRQC_LEVEL_3,
+M68K_IRQC_LEVEL_4,
+M68K_IRQC_LEVEL_5,
+M68K_IRQC_LEVEL_6,
+M68K_IRQC_LEVEL_7,
+};
+#define M68K_IRQC_LEVEL_NUM (M68K_IRQC_LEVEL_7 - M68K_IRQC_LEVEL_1 + 1)
+
+typedef struct M68KIRQCState {
+SysBusDevice parent_obj;
+
+uint8_t ipr;
+
+/* statistics */
+uint64_t stats_irq_count[M68K_IRQC_LEVEL_NUM];
+} M68KIRQCState;
+
+#endif
diff --git a/hw/intc/m68k_irqc.c b/hw/intc/m68k_irqc.c
new file mode 100644
index ..2133d2a698ab
--- /dev/null
+++ b/hw/intc/m68k_irqc.c
@@ -0,0 +1,119 @@
+/*
+ * SPDX-License-Identifer: GPL-2.0-or-later
+ *
+ * QEMU Motorola 680x0 IRQ Controller
+ *
+ * (c) 2020 Laurent Vivier 
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "migration/vmstate.h"
+#include "monitor/monitor.h"
+#include "hw/nmi.h"
+#include "hw/intc/intc.h"
+#include "hw/intc/m68k_irqc.h"
+
+
+static bool m68k_irqc_get_statistics(InterruptStatsProvider *obj,
+ uint64_t **irq_counts, unsigned int 
*nb_irqs)
+{
+M68KIRQCState *s = M68K_IRQC(obj);
+
+*irq_counts = s->stats_irq_count;
+*nb_irqs = ARRAY_SIZE(s->stats_irq_count);
+return true;
+}
+
+static void m68k_irqc_print_info(InterruptStatsProvider *obj, Monitor *mon)
+{
+M68KIRQCState *s = M68K_IRQC(obj);
+monitor_printf(mon, "m68k-irqc: ipr=0x%x\n", s->ipr);
+}
+
+static void m68k_set_irq(void *opaque, int irq, int level)
+{
+M68KIRQCState *s = opaque;
+M68kCPU *cpu = M68K_CPU(first_cpu);
+int i;
+
+if (level) {
+s->ipr |= 1 << irq;
+s->stats_irq_count[irq]++;
+} else {
+s->ipr &= ~(1 << irq);
+}
+
+for (i = M68K_IRQC_LEVEL_7; i >= M68K_IRQC_LEVEL_1; i--) {
+if ((s->ipr >> i) & 1) {
+m68k_set_irq_level(cpu, i + 1, i + M68K_IRQC_AUTOVECTOR_BASE);
+return;
+}
+}
+m68k_set_irq_level(cpu, 0, 0);
+}
+
+static void m68k_irqc_reset(DeviceState *d)
+{
+M68KIRQCState *s = M68K_IRQC(d);
+int i;
+
+s->ipr = 0;
+for (i = 0; i < ARRAY_SIZE(s->stats_irq_count); i++) {
+s->stats_irq_count[i] = 0;
+}
+}
+
+static void m68k_irqc_instance_init(Object *obj)
+{
+qdev_init_gpio_in(DEVICE(obj), m68k_set_irq, M68K_IRQC_LEVEL_NUM);
+}
+
+static void m68k_nmi(NMIState *n, int cpu_index, Error **errp)
+{
+m68k_set_irq(n, M68K_IRQC_LEVEL_7, 1);
+}
+
+static const VMStateDescription vmstate_m68k_irqc = {
+.name = "m68k-irqc",
+.version_id = 1,
+.minimum_version_id = 1,
+.fields = (VMStateField[]) {
+VMSTATE_UINT8(ipr, M68KIRQCState),
+VMSTATE_END_OF_LIST()
+}
+};
+
+static void m68k_irqc_class_init(ObjectClass *oc, void *data)
+ {
+DeviceClass *dc = DEVICE_CLASS(oc);
+NMIClass *nc = NMI_CLASS(oc);
+InterruptStatsProviderClass *ic = INTERRUPT_STATS_PROVIDER_CLASS(oc);
+
+nc->nmi_monitor_handler = m68k_nmi;
+dc->reset = m68k_irqc_reset;
+dc->vmsd = _m68k_irqc;
+ic->get_statistics = m68k_irqc_get_statistics;
+ic->print_info = m68k_irqc_print_info;
+}
+
+static const TypeInfo m68k_irqc_type_info = {
+.name = TYPE_M68K_IRQC,
+.parent = TYPE_SYS_BUS_DEVICE,
+.instance_size = sizeof(M68KIRQCState),
+.instance_init = m68k_irqc_instance_init,
+.class_init = m68k_irqc_class_init,
+.interfaces = (InterfaceInfo[]) {
+ { TYPE_NMI },
+ { TYPE_INTERRUPT_STATS_PROVIDER },
+ { }
+},
+};
+
+static void q800_irq_register_types(void)
+{
+type_register_static(_irqc_type_info);
+}
+
+type_init(q800_irq_register_types);
diff --git a/hw/intc/Kconfig b/hw/intc/Kconfig
index c4f8642dae8e..fdb4a30b98e8 100644
--- a/hw/intc/Kconfig
+++ b/hw/intc/Kconfig
@@ -67,3 +67,6 @@ config 

[PATCH v5 5/5] m68k: add Virtual M68k Machine

2021-03-07 Thread Laurent Vivier
The machine is based on Goldfish interfaces defined by Google
for Android simulator. It uses Goldfish-rtc (timer and RTC),
Goldfish-pic (PIC) and Goldfish-tty (for serial port and early tty).

The machine is created with 128 virtio-mmio bus, and they can
be used to use serial console, GPU, disk, NIC, HID, ...

Signed-off-by: Laurent Vivier 
Reviewed-by: Richard Henderson 
---
 default-configs/devices/m68k-softmmu.mak  |   1 +
 .../standard-headers/asm-m68k/bootinfo-virt.h |  18 +
 hw/m68k/virt.c| 313 ++
 MAINTAINERS   |  13 +
 hw/m68k/Kconfig   |  10 +
 hw/m68k/meson.build   |   1 +
 6 files changed, 356 insertions(+)
 create mode 100644 include/standard-headers/asm-m68k/bootinfo-virt.h
 create mode 100644 hw/m68k/virt.c

diff --git a/default-configs/devices/m68k-softmmu.mak 
b/default-configs/devices/m68k-softmmu.mak
index 6629fd2aa330..7f8619e42786 100644
--- a/default-configs/devices/m68k-softmmu.mak
+++ b/default-configs/devices/m68k-softmmu.mak
@@ -8,3 +8,4 @@ CONFIG_AN5206=y
 CONFIG_MCF5208=y
 CONFIG_NEXTCUBE=y
 CONFIG_Q800=y
+CONFIG_M68K_VIRT=y
diff --git a/include/standard-headers/asm-m68k/bootinfo-virt.h 
b/include/standard-headers/asm-m68k/bootinfo-virt.h
new file mode 100644
index ..81be1e092497
--- /dev/null
+++ b/include/standard-headers/asm-m68k/bootinfo-virt.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/*
+** asm/bootinfo-virt.h -- Virtual-m68k-specific boot information definitions
+*/
+
+#ifndef _UAPI_ASM_M68K_BOOTINFO_VIRT_H
+#define _UAPI_ASM_M68K_BOOTINFO_VIRT_H
+
+#define BI_VIRT_QEMU_VERSION   0x8000
+#define BI_VIRT_GF_PIC_BASE0x8001
+#define BI_VIRT_GF_RTC_BASE0x8002
+#define BI_VIRT_GF_TTY_BASE0x8003
+#define BI_VIRT_VIRTIO_BASE0x8004
+#define BI_VIRT_CTRL_BASE  0x8005
+
+#define VIRT_BOOTI_VERSION MK_BI_VERSION(2, 0)
+
+#endif /* _UAPI_ASM_M68K_BOOTINFO_MAC_H */
diff --git a/hw/m68k/virt.c b/hw/m68k/virt.c
new file mode 100644
index ..b813cf58eacd
--- /dev/null
+++ b/hw/m68k/virt.c
@@ -0,0 +1,313 @@
+/*
+ * SPDX-License-Identifer: GPL-2.0-or-later
+ *
+ * QEMU Vitual M68K Machine
+ *
+ * (c) 2020 Laurent Vivier 
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/units.h"
+#include "qemu-common.h"
+#include "sysemu/sysemu.h"
+#include "cpu.h"
+#include "hw/hw.h"
+#include "hw/boards.h"
+#include "hw/irq.h"
+#include "hw/qdev-properties.h"
+#include "elf.h"
+#include "hw/loader.h"
+#include "ui/console.h"
+#include "exec/address-spaces.h"
+#include "hw/sysbus.h"
+#include "standard-headers/asm-m68k/bootinfo.h"
+#include "standard-headers/asm-m68k/bootinfo-virt.h"
+#include "bootinfo.h"
+#include "net/net.h"
+#include "qapi/error.h"
+#include "sysemu/qtest.h"
+#include "sysemu/runstate.h"
+#include "sysemu/reset.h"
+
+#include "hw/intc/m68k_irqc.h"
+#include "hw/misc/m68k_virt_ctrl.h"
+#include "hw/char/goldfish_tty.h"
+#include "hw/rtc/goldfish_rtc.h"
+#include "hw/intc/goldfish_pic.h"
+#include "hw/virtio/virtio-mmio.h"
+#include "hw/virtio/virtio-blk.h"
+
+/*
+ * 6 goldfish-pic for CPU IRQ #1 to IRQ #6
+ * CPU IRQ #1 -> PIC #1
+ *   IRQ #1 to IRQ #31 -> unused
+ *   IRQ #32 -> goldfish-tty
+ * CPU IRQ #2 -> PIC #2
+ *   IRQ #1 to IRQ #32 -> virtio-mmio from 1 to 32
+ * CPU IRQ #3 -> PIC #3
+ *   IRQ #1 to IRQ #32 -> virtio-mmio from 33 to 64
+ * CPU IRQ #4 -> PIC #4
+ *   IRQ #1 to IRQ #32 -> virtio-mmio from 65 to 96
+ * CPU IRQ #5 -> PIC #5
+ *   IRQ #1 to IRQ #32 -> virtio-mmio from 97 to 128
+ * CPU IRQ #6 -> PIC #6
+ *   IRQ #1 -> goldfish-rtc
+ *   IRQ #2 to IRQ #32 -> unused
+ * CPU IRQ #7 -> NMI
+ */
+
+#define PIC_IRQ_BASE(num) (8 + (num - 1) * 32)
+#define PIC_IRQ(num, irq) (PIC_IRQ_BASE(num) + irq - 1)
+#define PIC_GPIO(pic_irq) (qdev_get_gpio_in(pic_dev[(pic_irq - 8) / 32], \
+(pic_irq - 8) % 32))
+
+#define VIRT_GF_PIC_MMIO_BASE 0xff00 /* MMIO: 0xff00 - 0xff005fff 
*/
+#define VIRT_GF_PIC_IRQ_BASE  1  /* IRQ: #1 -> #6 */
+#define VIRT_GF_PIC_NB6
+
+/* 2 goldfish-rtc (and timer) */
+#define VIRT_GF_RTC_MMIO_BASE 0xff006000 /* MMIO: 0xff006000 - 0xff007fff 
*/
+#define VIRT_GF_RTC_IRQ_BASE  PIC_IRQ(6, 1)  /* PIC: #6, IRQ: #1 */
+#define VIRT_GF_RTC_NB2
+
+/* 1 goldfish-tty */
+#define VIRT_GF_TTY_MMIO_BASE 0xff008000 /* MMIO: 0xff008000 - 0xff008fff 
*/
+#define VIRT_GF_TTY_IRQ_BASE  PIC_IRQ(1, 32) /* PIC: #1, IRQ: #32 */
+
+/* 1 m68k-virt-ctrl */
+#define VIRT_M68K_CTRL_MMIO_BASE 0xff009000/* MMIO: 0xff009000 - 
0xff009fff */
+#define VIRT_M68K_CTRL_IRQ_BASE  PIC_IRQ(1, 1) /* PIC: #1, IRQ: #1 */
+
+/*
+ * virtio-mmio size is 0x200 bytes
+ * we use 4 goldfish-pic to attach them,
+ * we can attach 32 virtio devices / goldfish-pic
+ * -> we can 

[PATCH v5 2/5] intc: add goldfish-pic

2021-03-07 Thread Laurent Vivier
Implement the goldfish pic device as defined in

https://android.googlesource.com/platform/external/qemu/+/master/docs/GOLDFISH-VIRTUAL-HARDWARE.TXT

Signed-off-by: Laurent Vivier 
Reviewed-by: Richard Henderson 
Reviewed-by: Philippe Mathieu-Daudé 
---
 include/hw/intc/goldfish_pic.h |  33 +
 hw/intc/goldfish_pic.c | 219 +
 hw/intc/Kconfig|   3 +
 hw/intc/meson.build|   1 +
 hw/intc/trace-events   |   8 ++
 5 files changed, 264 insertions(+)
 create mode 100644 include/hw/intc/goldfish_pic.h
 create mode 100644 hw/intc/goldfish_pic.c

diff --git a/include/hw/intc/goldfish_pic.h b/include/hw/intc/goldfish_pic.h
new file mode 100644
index ..ad13ab37fc3e
--- /dev/null
+++ b/include/hw/intc/goldfish_pic.h
@@ -0,0 +1,33 @@
+/*
+ * SPDX-License-Identifer: GPL-2.0-or-later
+ *
+ * Goldfish PIC
+ *
+ * (c) 2020 Laurent Vivier 
+ *
+ */
+
+#ifndef HW_INTC_GOLDFISH_PIC_H
+#define HW_INTC_GOLDFISH_PIC_H
+
+#define TYPE_GOLDFISH_PIC "goldfish_pic"
+OBJECT_DECLARE_SIMPLE_TYPE(GoldfishPICState, GOLDFISH_PIC)
+
+#define GOLDFISH_PIC_IRQ_NB 32
+
+struct GoldfishPICState {
+SysBusDevice parent_obj;
+
+MemoryRegion iomem;
+qemu_irq irq;
+
+uint32_t pending;
+uint32_t enabled;
+
+/* statistics */
+uint64_t stats_irq_count[32];
+/* for tracing */
+uint8_t idx;
+};
+
+#endif
diff --git a/hw/intc/goldfish_pic.c b/hw/intc/goldfish_pic.c
new file mode 100644
index ..e3b43a69f163
--- /dev/null
+++ b/hw/intc/goldfish_pic.c
@@ -0,0 +1,219 @@
+/*
+ * SPDX-License-Identifer: GPL-2.0-or-later
+ *
+ * Goldfish PIC
+ *
+ * (c) 2020 Laurent Vivier 
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "hw/irq.h"
+#include "hw/qdev-properties.h"
+#include "hw/sysbus.h"
+#include "migration/vmstate.h"
+#include "monitor/monitor.h"
+#include "qemu/log.h"
+#include "trace.h"
+#include "hw/intc/intc.h"
+#include "hw/intc/goldfish_pic.h"
+
+/* registers */
+
+enum {
+REG_STATUS  = 0x00,
+REG_IRQ_PENDING = 0x04,
+REG_IRQ_DISABLE_ALL = 0x08,
+REG_DISABLE = 0x0c,
+REG_ENABLE  = 0x10,
+};
+
+static bool goldfish_pic_get_statistics(InterruptStatsProvider *obj,
+uint64_t **irq_counts,
+unsigned int *nb_irqs)
+{
+GoldfishPICState *s = GOLDFISH_PIC(obj);
+
+*irq_counts = s->stats_irq_count;
+*nb_irqs = ARRAY_SIZE(s->stats_irq_count);
+return true;
+}
+
+static void goldfish_pic_print_info(InterruptStatsProvider *obj, Monitor *mon)
+{
+GoldfishPICState *s = GOLDFISH_PIC(obj);
+monitor_printf(mon, "goldfish-pic.%d: pending=0x%08x enabled=0x%08x\n",
+   s->idx, s->pending, s->enabled);
+}
+
+static void goldfish_pic_update(GoldfishPICState *s)
+{
+if (s->pending & s->enabled) {
+qemu_irq_raise(s->irq);
+} else {
+qemu_irq_lower(s->irq);
+}
+}
+
+static void goldfish_irq_request(void *opaque, int irq, int level)
+{
+GoldfishPICState *s = opaque;
+
+trace_goldfish_irq_request(s, s->idx, irq, level);
+
+if (level) {
+s->pending |= 1 << irq;
+s->stats_irq_count[irq]++;
+} else {
+s->pending &= ~(1 << irq);
+}
+goldfish_pic_update(s);
+}
+
+static uint64_t goldfish_pic_read(void *opaque, hwaddr addr,
+  unsigned size)
+{
+GoldfishPICState *s = opaque;
+uint64_t value = 0;
+
+switch (addr) {
+case REG_STATUS:
+/* The number of pending interrupts (0 to 32) */
+value = ctpop32(s->pending & s->enabled);
+break;
+case REG_IRQ_PENDING:
+/* The pending interrupt mask */
+value = s->pending & s->enabled;
+break;
+default:
+qemu_log_mask(LOG_UNIMP,
+  "%s: unimplemented register read 0x%02"HWADDR_PRIx"\n",
+  __func__, addr);
+break;
+}
+
+trace_goldfish_pic_read(s, s->idx, addr, size, value);
+
+return value;
+}
+
+static void goldfish_pic_write(void *opaque, hwaddr addr,
+   uint64_t value, unsigned size)
+{
+GoldfishPICState *s = opaque;
+
+trace_goldfish_pic_write(s, s->idx, addr, size, value);
+
+switch (addr) {
+case REG_IRQ_DISABLE_ALL:
+s->enabled = 0;
+s->pending = 0;
+break;
+case REG_DISABLE:
+s->enabled &= ~value;
+break;
+case REG_ENABLE:
+s->enabled |= value;
+break;
+default:
+qemu_log_mask(LOG_UNIMP,
+  "%s: unimplemented register write 0x%02"HWADDR_PRIx"\n",
+  __func__, addr);
+break;
+}
+goldfish_pic_update(s);
+}
+
+static const MemoryRegionOps goldfish_pic_ops = {
+.read = goldfish_pic_read,
+.write = goldfish_pic_write,
+.endianness = DEVICE_NATIVE_ENDIAN,
+.valid.max_access_size = 4,
+.impl.min_access_size = 4,
+   

[PATCH v5 0/5] m68k: add Virtual M68k Machine

2021-03-07 Thread Laurent Vivier
The Quadra 800 machine is very limited to run linux, it manages
only 1 GiB of memory and only some specific interfaces.

The Virtual M68k Machine is based on Goldfish interfaces defined by Google
for Android simulator. It uses Goldfish-rtc (timer and RTC),
Goldfish-pic (PIC) and Goldfish-tty (for serial port and early tty).

https://android.googlesource.com/platform/external/qemu/+/master/docs/GOLDFIS=
H-VIRTUAL-HARDWARE.TXT

The machine is created with 128 virtio-mmio busses, and they can
be used to add serial console, GPU, disk, NIC, HID, ...

This series re-use the goldfish-rtc implemented for RISCV, and
adds the two others based on the goldfish specs, the kernel driver
and android simulator ones.

The machine can manage up to 3.2 GiB of memory, not because of an hardware
limitation but because the kernel crashes after this value.

Simply configure qemu with:

.../configure --target-list=3Dm68k-softmmu

To run the machine you need a modified kernel you can find here:

https://github.com/vivier/linux/tree/m68k-virt

You need to compile the kernel with:

make virt_defconfig
make vmlinux

The disk must be installed using the q800 machine because the debian installer
doesn't want to be used with a kernel that is not the one on the ISO.

And then you can run the machine with something like:

qemu-system-m68k -M virt \
  -m 3399672K \
  -chardev stdio,signal=3Doff,mux=3Don,id=3Dchar0 \
  -mon chardev=3Dchar0,mode=3Dreadline \
  -kernel vmlinux \
  -append "console=3Dhvc0 root=3D/dev/vda2" \
  -blockdev node-name=3Dsystem,driver=3Dfile,filename=3Ddebian-10.0.qcow2 \
  -blockdev node-name=3Ddrive0,driver=3Dqcow2,file=3Dsystem \
  -device virtio-blk-device,drive=3Ddrive0 \
  -serial chardev:char0 \
  -device virtio-net-device,netdev=3Dhostnet0 \
  -netdev bridge,id=3Dhostnet0,br=3Dvirbr0 \
  -device virtio-rng-device \
  -device virtio-serial-device \
  -device virtio-gpu-device \
  -device virtconsole,chardev=3Dchar0 \
  -device virtio-keyboard-device \
  -device virtio-mouse-device

if you want to use Goldfish-tty for the console rather than virtconsole, you
can add "console=3DttyGF".

To start the debian-installer, you can try by adding:

  -device virtio-scsi-device \
  -blockdev node-name=3Ddebian10,driver=3Dfile,filename=3Ddebian-10.0.0-m68k-=
NETINST-1.iso \
  -blockdev node-name=3Dcdrom0,driver=3Draw,file=3Ddebian10 \
  -device scsi-cd,drive=3Dcdrom0 \
  -initrd installer-m68k/20200315/images/cdrom/initrd.gz

ISO:https://cdimage.debian.org/cdimage/ports/snapshots/2020-10-12/debian-=
10.0.0-m68k-NETINST-1.iso
initrd: https://cdimage.debian.org/cdimage/ports/debian-installer/2020-10-12/=
m68k/debian-installer-images_20200315_m68k.tar.gz

v5:
  goldfish-tty:
  Use deposit64()
  Add .impl.min_access_size
  Fix CMD_WRITE_BUFFER/CMD_READ_BUFFER

v4:
  goldfish-tty:
  Use fifo8 for the data_in buffer
  Remove the data_out buffer from the struct and put it directly in
  the function. We don't need to use the fifo8 type because we
  can't bufferize the data as we can't stop the tx queue when the buffer
  is full. We rely on qemu_chr_fe_write_all() that blocks the thread for
  that.
  goldfish-pic:
  Add DEFINE_PROP_UINT8() for the index
  Add .impl.min_access_size

v3:
  Add some #define for the interrupt controller (and fix the number of IRQs)
  Add some comments
  Update MAINTAINERS
  Remove "goldfish_rtc: re-arm the alarm after migration" that will be
  merged via the RISC-V branch.

v2:
  Add an interrupt controller to replace the Q800 GLUE
  Add a system controller to shutdown the machine
  Add a fix for goldfish_rtc (already sent alone)
  Add statistics in goldfish-pic
  Add versionned machine type
  Use two goldfish-rtc rather than only one (for timer and RTC)

Laurent Vivier (5):
  char: add goldfish-tty
  intc: add goldfish-pic
  m68k: add an interrupt controller
  m68k: add a system controller
  m68k: add Virtual M68k Machine

 default-configs/devices/m68k-softmmu.mak  |   1 +
 include/hw/char/goldfish_tty.h|  35 ++
 include/hw/intc/goldfish_pic.h|  33 ++
 include/hw/intc/m68k_irqc.h   |  41 +++
 include/hw/misc/m68k_virt_ctrl.h  |  22 ++
 .../standard-headers/asm-m68k/bootinfo-virt.h |  18 +
 hw/char/goldfish_tty.c| 283 
 hw/intc/goldfish_pic.c| 219 
 hw/intc/m68k_irqc.c   | 119 +++
 hw/m68k/virt.c| 313 ++
 hw/misc/m68k_virt_ctrl.c  | 152 +
 MAINTAINERS   |  13 +
 hw/char/Kconfig   |   3 +
 hw/char/meson.build   |   2 +
 hw/char/trace-events  |  10 +
 hw/intc/Kconfig   |   6 +
 hw/intc/meson.build   |   2 +
 hw/intc/trace-events   

[PATCH v5 1/5] char: add goldfish-tty

2021-03-07 Thread Laurent Vivier
Implement the goldfish tty device as defined in

https://android.googlesource.com/platform/external/qemu/+/master/docs/GOLDFISH-VIRTUAL-HARDWARE.TXT

and based on the kernel driver code:

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/tty/goldfish.c

Signed-off-by: Laurent Vivier 
Reviewed-by: Philippe Mathieu-Daudé 
---
 include/hw/char/goldfish_tty.h |  35 
 hw/char/goldfish_tty.c | 283 +
 hw/char/Kconfig|   3 +
 hw/char/meson.build|   2 +
 hw/char/trace-events   |  10 ++
 5 files changed, 333 insertions(+)
 create mode 100644 include/hw/char/goldfish_tty.h
 create mode 100644 hw/char/goldfish_tty.c

diff --git a/include/hw/char/goldfish_tty.h b/include/hw/char/goldfish_tty.h
new file mode 100644
index ..b9dd67362a68
--- /dev/null
+++ b/include/hw/char/goldfish_tty.h
@@ -0,0 +1,35 @@
+/*
+ * SPDX-License-Identifer: GPL-2.0-or-later
+ *
+ * Goldfish TTY
+ *
+ * (c) 2020 Laurent Vivier 
+ *
+ */
+
+#ifndef HW_CHAR_GOLDFISH_TTY_H
+#define HW_CHAR_GOLDFISH_TTY_H
+
+#include "qemu/fifo8.h"
+#include "chardev/char-fe.h"
+
+#define TYPE_GOLDFISH_TTY "goldfish_tty"
+OBJECT_DECLARE_SIMPLE_TYPE(GoldfishTTYState, GOLDFISH_TTY)
+
+#define GOLFISH_TTY_BUFFER_SIZE 128
+
+struct GoldfishTTYState {
+SysBusDevice parent_obj;
+
+MemoryRegion iomem;
+qemu_irq irq;
+CharBackend chr;
+
+uint32_t data_len;
+uint64_t data_ptr;
+bool int_enabled;
+
+Fifo8 rx_fifo;
+};
+
+#endif
diff --git a/hw/char/goldfish_tty.c b/hw/char/goldfish_tty.c
new file mode 100644
index ..9f705f8653cc
--- /dev/null
+++ b/hw/char/goldfish_tty.c
@@ -0,0 +1,283 @@
+/*
+ * SPDX-License-Identifer: GPL-2.0-or-later
+ *
+ * Goldfish TTY
+ *
+ * (c) 2020 Laurent Vivier 
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "hw/irq.h"
+#include "hw/qdev-properties-system.h"
+#include "hw/sysbus.h"
+#include "migration/vmstate.h"
+#include "chardev/char-fe.h"
+#include "qemu/log.h"
+#include "trace.h"
+#include "exec/address-spaces.h"
+#include "hw/char/goldfish_tty.h"
+
+/* registers */
+
+enum {
+REG_PUT_CHAR  = 0x00,
+REG_BYTES_READY   = 0x04,
+REG_CMD   = 0x08,
+REG_DATA_PTR  = 0x10,
+REG_DATA_LEN  = 0x14,
+REG_DATA_PTR_HIGH = 0x18,
+REG_VERSION   = 0x20,
+};
+
+/* commands */
+
+enum {
+CMD_INT_DISABLE   = 0x00,
+CMD_INT_ENABLE= 0x01,
+CMD_WRITE_BUFFER  = 0x02,
+CMD_READ_BUFFER   = 0x03,
+};
+
+static uint64_t goldfish_tty_read(void *opaque, hwaddr addr,
+  unsigned size)
+{
+GoldfishTTYState *s = opaque;
+uint64_t value = 0;
+
+switch (addr) {
+case REG_BYTES_READY:
+value = fifo8_num_used(>rx_fifo);
+break;
+case REG_VERSION:
+value = 0;
+break;
+default:
+qemu_log_mask(LOG_UNIMP,
+  "%s: unimplemented register read 0x%02"HWADDR_PRIx"\n",
+  __func__, addr);
+break;
+}
+
+trace_goldfish_tty_read(s, addr, size, value);
+
+return value;
+}
+
+static void goldfish_tty_cmd(GoldfishTTYState *s, uint32_t cmd)
+{
+uint32_t to_copy;
+uint8_t *buf;
+uint8_t data_out[GOLFISH_TTY_BUFFER_SIZE];
+int len;
+uint64_t ptr;
+
+switch (cmd) {
+case CMD_INT_DISABLE:
+if (s->int_enabled) {
+if (!fifo8_is_empty(>rx_fifo)) {
+qemu_set_irq(s->irq, 0);
+}
+s->int_enabled = false;
+}
+break;
+case CMD_INT_ENABLE:
+if (!s->int_enabled) {
+if (!fifo8_is_empty(>rx_fifo)) {
+qemu_set_irq(s->irq, 1);
+}
+s->int_enabled = true;
+}
+break;
+case CMD_WRITE_BUFFER:
+len = s->data_len;
+ptr = s->data_ptr;
+while (len) {
+to_copy = MIN(GOLFISH_TTY_BUFFER_SIZE, len);
+
+address_space_rw(_space_memory, ptr,
+ MEMTXATTRS_UNSPECIFIED, data_out, to_copy, 0);
+qemu_chr_fe_write_all(>chr, data_out, to_copy);
+
+len -= to_copy;
+ptr += to_copy;
+}
+break;
+case CMD_READ_BUFFER:
+len = s->data_len;
+ptr = s->data_ptr;
+while (len && !fifo8_is_empty(>rx_fifo)) {
+buf = (uint8_t *)fifo8_pop_buf(>rx_fifo, len, _copy);
+address_space_rw(_space_memory, ptr,
+MEMTXATTRS_UNSPECIFIED, buf, to_copy, 1);
+
+len -= to_copy;
+ptr += to_copy;
+}
+if (s->int_enabled && fifo8_is_empty(>rx_fifo)) {
+qemu_set_irq(s->irq, 0);
+}
+break;
+}
+}
+
+static void goldfish_tty_write(void *opaque, hwaddr addr,
+   uint64_t value, unsigned size)
+{
+GoldfishTTYState *s = opaque;
+unsigned char c;
+
+trace_goldfish_tty_write(s, addr, size, 

[PATCH] ui/gtk: fix NULL pointer dereference

2021-03-07 Thread Christian Schoenebeck
DisplaySurface pointer passed to gd_switch() can be NULL, so check this
before trying to dereference it.

Fixes: c821a58ee7 ("ui/console: Pass placeholder surface to display")
Reported-by: Coverity (CID 1448421)
Signed-off-by: Christian Schoenebeck 
---
 ui/gtk.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/ui/gtk.c b/ui/gtk.c
index 3edaf041de..a27b27d004 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -567,7 +567,7 @@ static void gd_switch(DisplayChangeListener *dcl,
 }
 vc->gfx.ds = surface;
 
-if (surface->format == PIXMAN_x8r8g8b8) {
+if (surface && surface->format == PIXMAN_x8r8g8b8) {
 /*
  * PIXMAN_x8r8g8b8 == CAIRO_FORMAT_RGB24
  *
@@ -580,7 +580,7 @@ static void gd_switch(DisplayChangeListener *dcl,
  surface_width(surface),
  surface_height(surface),
  surface_stride(surface));
-} else {
+} else if (surface) {
 /* Must convert surface, use pixman to do it. */
 vc->gfx.convert = pixman_image_create_bits(PIXMAN_x8r8g8b8,
surface_width(surface),
-- 
2.20.1




[PATCH 2/2] target/m68k: add M68K_FEATURE_NO_DALIGN feature

2021-03-07 Thread Mark Cave-Ayland
According to the M68040UM Appendix D the requirement for data accesses to be
word aligned is only for the 68000, 68008 and 68010 CPUs. Later CPUs from the
68020 onwards will allow unaligned data accesses but at the cost of being less
efficient.

Add a new M68K_FEATURE_NO_DALIGN feature to specify that data accesses are not
required to be word aligned, and don't perform the alignment on the stack
pointer when taking an exception if this feature is not selected.

This is required because the MacOS DAFB driver attempts to call an A-trap
with a byte-aligned stack pointer during initialisation and without this the
stack pointer is off by one when the A-trap returns.

Signed-off-by: Mark Cave-Ayland 
---
 target/m68k/cpu.c   | 1 +
 target/m68k/cpu.h   | 1 +
 target/m68k/op_helper.c | 5 -
 3 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c
index 37d2ed9dc7..ea51753eb0 100644
--- a/target/m68k/cpu.c
+++ b/target/m68k/cpu.c
@@ -161,6 +161,7 @@ static void m68020_cpu_initfn(Object *obj)
 m68k_set_feature(env, M68K_FEATURE_CAS);
 m68k_set_feature(env, M68K_FEATURE_CHK2);
 m68k_set_feature(env, M68K_FEATURE_MSP);
+m68k_set_feature(env, M68K_FEATURE_NO_DALIGN);
 }
 
 /*
diff --git a/target/m68k/cpu.h b/target/m68k/cpu.h
index 7c3feeaf8a..1e0876bba8 100644
--- a/target/m68k/cpu.h
+++ b/target/m68k/cpu.h
@@ -505,6 +505,7 @@ enum m68k_features {
 M68K_FEATURE_CHK2,  /* CHK2 insn. (680[2346]0, and CPU32) */
 M68K_FEATURE_MOVEP, /* MOVEP insn. (680[01234]0, and CPU32) */
 M68K_FEATURE_MOVEC, /* MOVEC insn. (from 68010) */
+M68K_FEATURE_NO_DALIGN, /* Unaligned data accesses (680[2346]0) */
 };
 
 static inline int m68k_feature(CPUM68KState *env, int feature)
diff --git a/target/m68k/op_helper.c b/target/m68k/op_helper.c
index 59a6448296..71b3df0910 100644
--- a/target/m68k/op_helper.c
+++ b/target/m68k/op_helper.c
@@ -348,7 +348,10 @@ static void m68k_interrupt_all(CPUM68KState *env, int 
is_hw)
 cpu_m68k_set_sr(env, sr);
 sp = env->aregs[7];
 
-sp &= ~1;
+if (!m68k_feature(env, M68K_FEATURE_NO_DALIGN)) {
+sp &= ~1;
+}
+
 if (cs->exception_index == EXCP_ACCESS) {
 if (env->mmu.fault) {
 cpu_abort(cs, "DOUBLE MMU FAULT\n");
-- 
2.20.1




[PATCH 1/2] target/m68k: don't set SSW ATC bit for physical bus errors

2021-03-07 Thread Mark Cave-Ayland
If a NuBus slot doesn't contain a card, the Quadra hardware generates a physical
bus error if the CPU attempts to access the slot address space. Both Linux and
MacOS use a separate bus error handler during NuBus accesses in order to detect
and recover when addressing empty slots.

According to the MC68040 users manual the ATC bit of the SSW is used to
distinguish between ATC faults and physical bus errors. MacOS specifically 
checks
the stack frame generated by a NuBus error and panics if the SSW ATC bit is set.

Update m68k_cpu_transaction_failed() so that the SSW ATC bit is not set if the
memory API returns MEMTX_DECODE_ERROR which will be used to indicate that an
access to an empty NuBus slot occurred.

Signed-off-by: Mark Cave-Ayland 
---
 target/m68k/op_helper.c | 12 +++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/target/m68k/op_helper.c b/target/m68k/op_helper.c
index 202498deb5..59a6448296 100644
--- a/target/m68k/op_helper.c
+++ b/target/m68k/op_helper.c
@@ -468,7 +468,17 @@ void m68k_cpu_transaction_failed(CPUState *cs, hwaddr 
physaddr, vaddr addr,
 
 if (m68k_feature(env, M68K_FEATURE_M68040)) {
 env->mmu.mmusr = 0;
-env->mmu.ssw |= M68K_ATC_040;
+
+/*
+ * According to the MC68040 users manual the ATC bit of the SSW is
+ * used to distinguish between ATC faults and physical bus errors.
+ * In the case of a bus error e.g. during nubus read from an empty
+ * slot this bit should not be set
+ */
+if (response != MEMTX_DECODE_ERROR) {
+env->mmu.ssw |= M68K_ATC_040;
+}
+
 /* FIXME: manage MMU table access error */
 env->mmu.ssw &= ~M68K_TM_040;
 if (env->sr & SR_S) { /* SUPERVISOR */
-- 
2.20.1




[PATCH 0/2] target/m68k: MacOS related fixes

2021-03-07 Thread Mark Cave-Ayland
Here are a couple of extra target/m68k patches taken from my attempts to try
and boot MacOS.

Signed-off-by: Mark Cave-Ayland 


Mark Cave-Ayland (2):
  target/m68k: don't set SSW ATC bit for physical bus errors
  target/m68k: add M68K_FEATURE_NO_DALIGN feature

 target/m68k/cpu.c   |  1 +
 target/m68k/cpu.h   |  1 +
 target/m68k/op_helper.c | 17 +++--
 3 files changed, 17 insertions(+), 2 deletions(-)

-- 
2.20.1




Re: [PATCH v4 1/5] char: add goldfish-tty

2021-03-07 Thread Laurent Vivier
Le 07/03/2021 à 20:24, Philippe Mathieu-Daudé a écrit :
> On 3/7/21 5:48 PM, Laurent Vivier wrote:
>> Implement the goldfish tty device as defined in
>>
>> https://android.googlesource.com/platform/external/qemu/+/master/docs/GOLDFISH-VIRTUAL-HARDWARE.TXT
>>
>> and based on the kernel driver code:
>>
>> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/tty/goldfish.c
>>
>> Signed-off-by: Laurent Vivier 
>> ---
>>  include/hw/char/goldfish_tty.h |  35 +
>>  hw/char/goldfish_tty.c | 272 +
>>  hw/char/Kconfig|   3 +
>>  hw/char/meson.build|   2 +
>>  hw/char/trace-events   |  10 ++
>>  5 files changed, 322 insertions(+)
>>  create mode 100644 include/hw/char/goldfish_tty.h
>>  create mode 100644 hw/char/goldfish_tty.c
> 
>> +static void goldfish_tty_write(void *opaque, hwaddr addr,
>> +   uint64_t value, unsigned size)
>> +{
>> +GoldfishTTYState *s = opaque;
>> +unsigned char c;
>> +
>> +trace_goldfish_tty_write(s, addr, size, value);
>> +
>> +switch (addr) {
>> +case REG_PUT_CHAR:
>> +c = value;
>> +qemu_chr_fe_write_all(>chr, , sizeof(c));
> 
> No IRQ here described in the spec... So this is correct.
> 
>> +break;
>> +case REG_CMD:
>> +goldfish_tty_cmd(s, value);
>> +break;
>> +case REG_DATA_PTR:
>> +s->data_ptr = value;
>> +break;
>> +case REG_DATA_PTR_HIGH:
>> +s->data_ptr = (value << 32) | (uint32_t)s->data_ptr;
> 
> Matter of taste, I find it easier to review as:
> 
>s->data_ptr = deposit64(s->data_ptr, value, 32, 32);

I agree.

> 
> The spec says this register is only available on 64-bit targets.
> 
> Should we restrict this "#if TARGET_LONG_SIZE == 8"?
> else log_mask(GUEST_ERROR)...
> 
> This seems overkill to me but that would respect the spec.

TARGET_LONG_SIZE depends on CPU, I don't think we can use it here.

>> +break;
>> +case REG_DATA_LEN:
>> +s->data_len = value;
>> +break;
>> +default:
>> +qemu_log_mask(LOG_UNIMP,
>> +  "%s: unimplemented register write 
>> 0x%02"HWADDR_PRIx"\n",
>> +  __func__, addr);
>> +break;
>> +}
>> +}
>> +
>> +static const MemoryRegionOps goldfish_tty_ops = {
>> +.read = goldfish_tty_read,
>> +.write = goldfish_tty_write,
>> +.endianness = DEVICE_NATIVE_ENDIAN,
>> +.valid.max_access_size = 4,
> 
> Again, I think you also want:
> 
>.impl.min_access_size = 4,
> 
>> +.impl.max_access_size = 4,
>> +};

OK

> 
> With min_access_size:
> Reviewed-by: Philippe Mathieu-Daudé 
> 

Thanks,
Laurent



Re: [PATCH v4 1/5] char: add goldfish-tty

2021-03-07 Thread Philippe Mathieu-Daudé
On 3/7/21 5:48 PM, Laurent Vivier wrote:
> Implement the goldfish tty device as defined in
> 
> https://android.googlesource.com/platform/external/qemu/+/master/docs/GOLDFISH-VIRTUAL-HARDWARE.TXT
> 
> and based on the kernel driver code:
> 
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/tty/goldfish.c
> 
> Signed-off-by: Laurent Vivier 
> ---
>  include/hw/char/goldfish_tty.h |  35 +
>  hw/char/goldfish_tty.c | 272 +
>  hw/char/Kconfig|   3 +
>  hw/char/meson.build|   2 +
>  hw/char/trace-events   |  10 ++
>  5 files changed, 322 insertions(+)
>  create mode 100644 include/hw/char/goldfish_tty.h
>  create mode 100644 hw/char/goldfish_tty.c

> +static void goldfish_tty_write(void *opaque, hwaddr addr,
> +   uint64_t value, unsigned size)
> +{
> +GoldfishTTYState *s = opaque;
> +unsigned char c;
> +
> +trace_goldfish_tty_write(s, addr, size, value);
> +
> +switch (addr) {
> +case REG_PUT_CHAR:
> +c = value;
> +qemu_chr_fe_write_all(>chr, , sizeof(c));

No IRQ here described in the spec... So this is correct.

> +break;
> +case REG_CMD:
> +goldfish_tty_cmd(s, value);
> +break;
> +case REG_DATA_PTR:
> +s->data_ptr = value;
> +break;
> +case REG_DATA_PTR_HIGH:
> +s->data_ptr = (value << 32) | (uint32_t)s->data_ptr;

Matter of taste, I find it easier to review as:

   s->data_ptr = deposit64(s->data_ptr, value, 32, 32);

The spec says this register is only available on 64-bit targets.

Should we restrict this "#if TARGET_LONG_SIZE == 8"?
else log_mask(GUEST_ERROR)...

This seems overkill to me but that would respect the spec.

> +break;
> +case REG_DATA_LEN:
> +s->data_len = value;
> +break;
> +default:
> +qemu_log_mask(LOG_UNIMP,
> +  "%s: unimplemented register write 
> 0x%02"HWADDR_PRIx"\n",
> +  __func__, addr);
> +break;
> +}
> +}
> +
> +static const MemoryRegionOps goldfish_tty_ops = {
> +.read = goldfish_tty_read,
> +.write = goldfish_tty_write,
> +.endianness = DEVICE_NATIVE_ENDIAN,
> +.valid.max_access_size = 4,

Again, I think you also want:

   .impl.min_access_size = 4,

> +.impl.max_access_size = 4,
> +};

With min_access_size:
Reviewed-by: Philippe Mathieu-Daudé 



Re: [PATCH v2] target/m68k: implement rtr instruction

2021-03-07 Thread Mark Cave-Ayland

On 07/03/2021 18:22, Laurent Vivier wrote:


This is needed to boot MacOS ROM.

Pull the condition code and the program counter from the stack.

Operation:

 (SP) -> CCR
 SP + 2 -> SP
 (SP) -> PC
 SP + 4 - > SP

This operation is not privileged.

Reported-by: Mark Cave-Ayland 
Signed-off-by: Laurent Vivier 
---

Notes:
 v2: update comment
 SP + 4 -> SP

  target/m68k/translate.c | 15 +++
  1 file changed, 15 insertions(+)

diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index ac936ebe8f14..e6942955713c 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -2969,6 +2969,20 @@ DISAS_INSN(rtd)
  gen_jmp(s, tmp);
  }
  
+DISAS_INSN(rtr)

+{
+TCGv tmp;
+TCGv ccr;
+
+ccr = gen_load(s, OS_WORD, QREG_SP, 0, IS_USER(s));
+gen_set_sr(s, ccr, true);
+tcg_temp_free(ccr);
+tcg_gen_addi_i32(QREG_SP, QREG_SP, 2);
+tmp = gen_load(s, OS_LONG, QREG_SP, 0, IS_USER(s));
+tcg_gen_addi_i32(QREG_SP, QREG_SP, 4);
+gen_jmp(s, tmp);
+}
+
  DISAS_INSN(rts)
  {
  TCGv tmp;
@@ -6015,6 +6029,7 @@ void register_m68k_insns (CPUM68KState *env)
  BASE(nop,   4e71, );
  INSN(rtd,   4e74, , RTD);
  BASE(rts,   4e75, );
+INSN(rtr,   4e77, , M68000);
  BASE(jump,  4e80, ffc0);
  BASE(jump,  4ec0, ffc0);
  INSN(addsubq,   5000, f080, M68000);


Solves the issue for me, so:

Tested-by: Mark Cave-Ayland 

I also have a couple of other target/m68k patches from my experimental branch which 
are probably worth adding to an m68k PR. Let me go dig them out...



ATB,

Mark.



Re: [PATCH v2] target/m68k: implement rtr instruction

2021-03-07 Thread Laurent Vivier
Le 07/03/2021 à 19:45, Richard Henderson a écrit :
> On 3/7/21 10:22 AM, Laurent Vivier wrote:
>> +    ccr = gen_load(s, OS_WORD, QREG_SP, 0, IS_USER(s));
>> +    gen_set_sr(s, ccr, true);
>> +    tcg_temp_free(ccr);
>> +    tcg_gen_addi_i32(QREG_SP, QREG_SP, 2);
>> +    tmp = gen_load(s, OS_LONG, QREG_SP, 0, IS_USER(s));
>> +    tcg_gen_addi_i32(QREG_SP, QREG_SP, 4);
>> +    gen_jmp(s, tmp);
> 
> Both loads should happen (and thus exceptions recognized) before any other 
> state writeback.

Something like that?

ccr = gen_load(s, OS_WORD, QREG_SP, 0, IS_USER(s));
tcg_gen_addi_i32(QREG_SP, QREG_SP, 2);
tmp = gen_load(s, OS_LONG, QREG_SP, 0, IS_USER(s));
tcg_gen_addi_i32(QREG_SP, QREG_SP, 4);

gen_set_sr(s, ccr, true);
tcg_temp_free(ccr);

gen_jmp(s, tmp);

Thanks,
Laurent



Re: [PATCH v2] target/m68k: implement rtr instruction

2021-03-07 Thread Richard Henderson

On 3/7/21 10:22 AM, Laurent Vivier wrote:

+ccr = gen_load(s, OS_WORD, QREG_SP, 0, IS_USER(s));
+gen_set_sr(s, ccr, true);
+tcg_temp_free(ccr);
+tcg_gen_addi_i32(QREG_SP, QREG_SP, 2);
+tmp = gen_load(s, OS_LONG, QREG_SP, 0, IS_USER(s));
+tcg_gen_addi_i32(QREG_SP, QREG_SP, 4);
+gen_jmp(s, tmp);


Both loads should happen (and thus exceptions recognized) before any other 
state writeback.



r~



Re: [PATCH v2] target/m68k: implement rtr instruction

2021-03-07 Thread BALATON Zoltan

On Sun, 7 Mar 2021, Laurent Vivier wrote:

This is needed to boot MacOS ROM.

Pull the condition code and the program counter from the stack.

Operation:

   (SP) -> CCR
   SP + 2 -> SP
   (SP) -> PC
   SP + 4 - > SP


Doesn't look like the commit message was fixed, there's still a space 
there.


Regards,
BALATON Zoltan


This operation is not privileged.

Reported-by: Mark Cave-Ayland 
Signed-off-by: Laurent Vivier 
---

Notes:
   v2: update comment
   SP + 4 -> SP

target/m68k/translate.c | 15 +++
1 file changed, 15 insertions(+)

diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index ac936ebe8f14..e6942955713c 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -2969,6 +2969,20 @@ DISAS_INSN(rtd)
gen_jmp(s, tmp);
}

+DISAS_INSN(rtr)
+{
+TCGv tmp;
+TCGv ccr;
+
+ccr = gen_load(s, OS_WORD, QREG_SP, 0, IS_USER(s));
+gen_set_sr(s, ccr, true);
+tcg_temp_free(ccr);
+tcg_gen_addi_i32(QREG_SP, QREG_SP, 2);
+tmp = gen_load(s, OS_LONG, QREG_SP, 0, IS_USER(s));
+tcg_gen_addi_i32(QREG_SP, QREG_SP, 4);
+gen_jmp(s, tmp);
+}
+
DISAS_INSN(rts)
{
TCGv tmp;
@@ -6015,6 +6029,7 @@ void register_m68k_insns (CPUM68KState *env)
BASE(nop,   4e71, );
INSN(rtd,   4e74, , RTD);
BASE(rts,   4e75, );
+INSN(rtr,   4e77, , M68000);
BASE(jump,  4e80, ffc0);
BASE(jump,  4ec0, ffc0);
INSN(addsubq,   5000, f080, M68000);





[PATCH v2] target/m68k: implement rtr instruction

2021-03-07 Thread Laurent Vivier
This is needed to boot MacOS ROM.

Pull the condition code and the program counter from the stack.

Operation:

(SP) -> CCR
SP + 2 -> SP
(SP) -> PC
SP + 4 - > SP

This operation is not privileged.

Reported-by: Mark Cave-Ayland 
Signed-off-by: Laurent Vivier 
---

Notes:
v2: update comment
SP + 4 -> SP

 target/m68k/translate.c | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index ac936ebe8f14..e6942955713c 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -2969,6 +2969,20 @@ DISAS_INSN(rtd)
 gen_jmp(s, tmp);
 }
 
+DISAS_INSN(rtr)
+{
+TCGv tmp;
+TCGv ccr;
+
+ccr = gen_load(s, OS_WORD, QREG_SP, 0, IS_USER(s));
+gen_set_sr(s, ccr, true);
+tcg_temp_free(ccr);
+tcg_gen_addi_i32(QREG_SP, QREG_SP, 2);
+tmp = gen_load(s, OS_LONG, QREG_SP, 0, IS_USER(s));
+tcg_gen_addi_i32(QREG_SP, QREG_SP, 4);
+gen_jmp(s, tmp);
+}
+
 DISAS_INSN(rts)
 {
 TCGv tmp;
@@ -6015,6 +6029,7 @@ void register_m68k_insns (CPUM68KState *env)
 BASE(nop,   4e71, );
 INSN(rtd,   4e74, , RTD);
 BASE(rts,   4e75, );
+INSN(rtr,   4e77, , M68000);
 BASE(jump,  4e80, ffc0);
 BASE(jump,  4ec0, ffc0);
 INSN(addsubq,   5000, f080, M68000);
-- 
2.29.2




Re: [PATCH] target/m68k: implement rtr instruction

2021-03-07 Thread Laurent Vivier
Le 07/03/2021 à 19:07, Laurent Vivier a écrit :
> This is needed to boot MacOS ROM.
> 
> Pull the condition code and the program counter from the stack.
> 
> Operation:
> 
> (SP) -> CCR
> SP + 2 -> SP
> (SP) -> PC
> (SP + 4) - > SP

This is in fact:

SP + 4 -> SP

> 
> This operation is not privileged.
> 
> Reported-by: Mark Cave-Ayland 
> Signed-off-by: Laurent Vivier 
> ---
>  target/m68k/translate.c | 15 +++
>  1 file changed, 15 insertions(+)
> 
> diff --git a/target/m68k/translate.c b/target/m68k/translate.c
> index ac936ebe8f14..e6942955713c 100644
> --- a/target/m68k/translate.c
> +++ b/target/m68k/translate.c
> @@ -2969,6 +2969,20 @@ DISAS_INSN(rtd)
>  gen_jmp(s, tmp);
>  }
>  
> +DISAS_INSN(rtr)
> +{
> +TCGv tmp;
> +TCGv ccr;
> +
> +ccr = gen_load(s, OS_WORD, QREG_SP, 0, IS_USER(s));
> +gen_set_sr(s, ccr, true);
> +tcg_temp_free(ccr);
> +tcg_gen_addi_i32(QREG_SP, QREG_SP, 2);
> +tmp = gen_load(s, OS_LONG, QREG_SP, 0, IS_USER(s));
> +tcg_gen_addi_i32(QREG_SP, QREG_SP, 4);
> +gen_jmp(s, tmp);
> +}
> +
>  DISAS_INSN(rts)
>  {
>  TCGv tmp;
> @@ -6015,6 +6029,7 @@ void register_m68k_insns (CPUM68KState *env)
>  BASE(nop,   4e71, );
>  INSN(rtd,   4e74, , RTD);
>  BASE(rts,   4e75, );
> +INSN(rtr,   4e77, , M68000);
>  BASE(jump,  4e80, ffc0);
>  BASE(jump,  4ec0, ffc0);
>  INSN(addsubq,   5000, f080, M68000);
> 




[RFC PATCH] vhost-vsock: SOCK_SEQPACKET feature bit support

2021-03-07 Thread Arseny Krasnov
This adds processing of VIRTIO_VSOCK_F_SEQPACKET feature bit. Guest
negotiates it with vhost, thus both will know that SOCK_SEQPACKET
supported by peer.

Signed-off-by: Arseny Krasnov 
---
 hw/virtio/vhost-vsock.c   | 16 +++-
 include/standard-headers/linux/virtio_vsock.h |  3 +++
 2 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/hw/virtio/vhost-vsock.c b/hw/virtio/vhost-vsock.c
index c8f0699b4f..06eb73f086 100644
--- a/hw/virtio/vhost-vsock.c
+++ b/hw/virtio/vhost-vsock.c
@@ -107,10 +107,23 @@ static uint64_t vhost_vsock_get_features(VirtIODevice 
*vdev,
  uint64_t requested_features,
  Error **errp)
 {
-/* No feature bits used yet */
+VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev);
+
+if (vvc->vhost_dev.features & (1ULL << VIRTIO_VSOCK_F_SEQPACKET)) {
+requested_features |= (1ULL << VIRTIO_VSOCK_F_SEQPACKET);
+}
+
 return requested_features;
 }
 
+static void vhost_vsock_set_features(VirtIODevice *vdev, uint64_t features)
+{
+VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev);
+const VhostOps *vhost_ops = vvc->vhost_dev.vhost_ops;
+
+vhost_ops->vhost_set_features(>vhost_dev, features);
+}
+
 static const VMStateDescription vmstate_virtio_vhost_vsock = {
 .name = "virtio-vhost_vsock",
 .minimum_version_id = VHOST_VSOCK_SAVEVM_VERSION,
@@ -214,6 +227,7 @@ static void vhost_vsock_class_init(ObjectClass *klass, void 
*data)
 vdc->realize = vhost_vsock_device_realize;
 vdc->unrealize = vhost_vsock_device_unrealize;
 vdc->get_features = vhost_vsock_get_features;
+vdc->set_features = vhost_vsock_set_features;
 vdc->get_config = vhost_vsock_get_config;
 vdc->set_status = vhost_vsock_set_status;
 }
diff --git a/include/standard-headers/linux/virtio_vsock.h 
b/include/standard-headers/linux/virtio_vsock.h
index be443211ce..e0d7db4328 100644
--- a/include/standard-headers/linux/virtio_vsock.h
+++ b/include/standard-headers/linux/virtio_vsock.h
@@ -38,6 +38,9 @@
 #include "standard-headers/linux/virtio_ids.h"
 #include "standard-headers/linux/virtio_config.h"
 
+/* The feature bitmap for virtio vsock */
+#define VIRTIO_VSOCK_F_SEQPACKET   0   /* SOCK_SEQPACKET supported */
+
 struct virtio_vsock_config {
uint64_t guest_cid;
 } QEMU_PACKED;
-- 
2.25.1




[PATCH] target/m68k: implement rtr instruction

2021-03-07 Thread Laurent Vivier
This is needed to boot MacOS ROM.

Pull the condition code and the program counter from the stack.

Operation:

(SP) -> CCR
SP + 2 -> SP
(SP) -> PC
(SP + 4) - > SP

This operation is not privileged.

Reported-by: Mark Cave-Ayland 
Signed-off-by: Laurent Vivier 
---
 target/m68k/translate.c | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index ac936ebe8f14..e6942955713c 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -2969,6 +2969,20 @@ DISAS_INSN(rtd)
 gen_jmp(s, tmp);
 }
 
+DISAS_INSN(rtr)
+{
+TCGv tmp;
+TCGv ccr;
+
+ccr = gen_load(s, OS_WORD, QREG_SP, 0, IS_USER(s));
+gen_set_sr(s, ccr, true);
+tcg_temp_free(ccr);
+tcg_gen_addi_i32(QREG_SP, QREG_SP, 2);
+tmp = gen_load(s, OS_LONG, QREG_SP, 0, IS_USER(s));
+tcg_gen_addi_i32(QREG_SP, QREG_SP, 4);
+gen_jmp(s, tmp);
+}
+
 DISAS_INSN(rts)
 {
 TCGv tmp;
@@ -6015,6 +6029,7 @@ void register_m68k_insns (CPUM68KState *env)
 BASE(nop,   4e71, );
 INSN(rtd,   4e74, , RTD);
 BASE(rts,   4e75, );
+INSN(rtr,   4e77, , M68000);
 BASE(jump,  4e80, ffc0);
 BASE(jump,  4ec0, ffc0);
 INSN(addsubq,   5000, f080, M68000);
-- 
2.29.2




Re: [PATCH v1 0/9] testing/next (docs, hexagon, cfi, docker)

2021-03-07 Thread Alex Bennée


Willian Rampazzo  writes:

> On Fri, Mar 5, 2021 at 6:31 AM Alex Bennée  wrote:
>>
>> Hi,
>>
>> Another week another testing/next roll. The series includes a couple
>> of my proposed documentation tweaks (including the re-org of the devel
>> manual). We also enable testing for the hexagon linux-user target to
>> avoid bitrot. I've documented the process for manually updating the
>> registry at:
>>
>>  https://wiki.qemu.org/Testing/DockerBuild#The_GitLab_Registry
>>
>
> I see a mix of valid/invalid URLs, like `registry.gitlab.example.com`
> and then `registry.gitlab.com`. For consistency, my suggestion is to
> use either the example URL or a valid URL mentioning that is an
> example for a specific docker image.

Oops bad copy/paste from my shell history. Fixed now.


-- 
Alex Bennée



[PATCH v4 1/5] char: add goldfish-tty

2021-03-07 Thread Laurent Vivier
Implement the goldfish tty device as defined in

https://android.googlesource.com/platform/external/qemu/+/master/docs/GOLDFISH-VIRTUAL-HARDWARE.TXT

and based on the kernel driver code:

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/tty/goldfish.c

Signed-off-by: Laurent Vivier 
---
 include/hw/char/goldfish_tty.h |  35 +
 hw/char/goldfish_tty.c | 272 +
 hw/char/Kconfig|   3 +
 hw/char/meson.build|   2 +
 hw/char/trace-events   |  10 ++
 5 files changed, 322 insertions(+)
 create mode 100644 include/hw/char/goldfish_tty.h
 create mode 100644 hw/char/goldfish_tty.c

diff --git a/include/hw/char/goldfish_tty.h b/include/hw/char/goldfish_tty.h
new file mode 100644
index ..b9dd67362a68
--- /dev/null
+++ b/include/hw/char/goldfish_tty.h
@@ -0,0 +1,35 @@
+/*
+ * SPDX-License-Identifer: GPL-2.0-or-later
+ *
+ * Goldfish TTY
+ *
+ * (c) 2020 Laurent Vivier 
+ *
+ */
+
+#ifndef HW_CHAR_GOLDFISH_TTY_H
+#define HW_CHAR_GOLDFISH_TTY_H
+
+#include "qemu/fifo8.h"
+#include "chardev/char-fe.h"
+
+#define TYPE_GOLDFISH_TTY "goldfish_tty"
+OBJECT_DECLARE_SIMPLE_TYPE(GoldfishTTYState, GOLDFISH_TTY)
+
+#define GOLFISH_TTY_BUFFER_SIZE 128
+
+struct GoldfishTTYState {
+SysBusDevice parent_obj;
+
+MemoryRegion iomem;
+qemu_irq irq;
+CharBackend chr;
+
+uint32_t data_len;
+uint64_t data_ptr;
+bool int_enabled;
+
+Fifo8 rx_fifo;
+};
+
+#endif
diff --git a/hw/char/goldfish_tty.c b/hw/char/goldfish_tty.c
new file mode 100644
index ..1fd29c0d9ccc
--- /dev/null
+++ b/hw/char/goldfish_tty.c
@@ -0,0 +1,272 @@
+/*
+ * SPDX-License-Identifer: GPL-2.0-or-later
+ *
+ * Goldfish TTY
+ *
+ * (c) 2020 Laurent Vivier 
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "hw/irq.h"
+#include "hw/qdev-properties-system.h"
+#include "hw/sysbus.h"
+#include "migration/vmstate.h"
+#include "chardev/char-fe.h"
+#include "qemu/log.h"
+#include "trace.h"
+#include "exec/address-spaces.h"
+#include "hw/char/goldfish_tty.h"
+
+/* registers */
+
+enum {
+REG_PUT_CHAR  = 0x00,
+REG_BYTES_READY   = 0x04,
+REG_CMD   = 0x08,
+REG_DATA_PTR  = 0x10,
+REG_DATA_LEN  = 0x14,
+REG_DATA_PTR_HIGH = 0x18,
+REG_VERSION   = 0x20,
+};
+
+/* commands */
+
+enum {
+CMD_INT_DISABLE   = 0x00,
+CMD_INT_ENABLE= 0x01,
+CMD_WRITE_BUFFER  = 0x02,
+CMD_READ_BUFFER   = 0x03,
+};
+
+static uint64_t goldfish_tty_read(void *opaque, hwaddr addr,
+  unsigned size)
+{
+GoldfishTTYState *s = opaque;
+uint64_t value = 0;
+
+switch (addr) {
+case REG_BYTES_READY:
+value = fifo8_num_used(>rx_fifo);
+break;
+case REG_VERSION:
+value = 0;
+break;
+default:
+qemu_log_mask(LOG_UNIMP,
+  "%s: unimplemented register read 0x%02"HWADDR_PRIx"\n",
+  __func__, addr);
+break;
+}
+
+trace_goldfish_tty_read(s, addr, size, value);
+
+return value;
+}
+
+static void goldfish_tty_cmd(GoldfishTTYState *s, uint32_t cmd)
+{
+uint32_t to_copy;
+uint8_t *buf;
+uint8_t data_out[GOLFISH_TTY_BUFFER_SIZE];
+
+switch (cmd) {
+case CMD_INT_DISABLE:
+if (s->int_enabled) {
+if (!fifo8_is_empty(>rx_fifo)) {
+qemu_set_irq(s->irq, 0);
+}
+s->int_enabled = false;
+}
+break;
+case CMD_INT_ENABLE:
+if (!s->int_enabled) {
+if (!fifo8_is_empty(>rx_fifo)) {
+qemu_set_irq(s->irq, 1);
+}
+s->int_enabled = true;
+}
+break;
+case CMD_WRITE_BUFFER:
+to_copy = s->data_len;
+while (to_copy) {
+int len;
+
+len = MIN(sizeof(data_out), to_copy);
+
+address_space_rw(_space_memory, s->data_ptr,
+ MEMTXATTRS_UNSPECIFIED, data_out, len, 0);
+to_copy -= len;
+qemu_chr_fe_write_all(>chr, data_out, len);
+}
+break;
+case CMD_READ_BUFFER:
+buf = (uint8_t *)fifo8_pop_buf(>rx_fifo, s->data_len, _copy);
+address_space_rw(_space_memory, s->data_ptr,
+ MEMTXATTRS_UNSPECIFIED, buf, to_copy, 1);
+if (s->int_enabled && fifo8_is_empty(>rx_fifo)) {
+qemu_set_irq(s->irq, 0);
+}
+break;
+}
+}
+
+static void goldfish_tty_write(void *opaque, hwaddr addr,
+   uint64_t value, unsigned size)
+{
+GoldfishTTYState *s = opaque;
+unsigned char c;
+
+trace_goldfish_tty_write(s, addr, size, value);
+
+switch (addr) {
+case REG_PUT_CHAR:
+c = value;
+qemu_chr_fe_write_all(>chr, , sizeof(c));
+break;
+case REG_CMD:
+goldfish_tty_cmd(s, value);
+break;
+case REG_DATA_PTR:
+s->data_ptr = value;
+

[PATCH v4 5/5] m68k: add Virtual M68k Machine

2021-03-07 Thread Laurent Vivier
The machine is based on Goldfish interfaces defined by Google
for Android simulator. It uses Goldfish-rtc (timer and RTC),
Goldfish-pic (PIC) and Goldfish-tty (for serial port and early tty).

The machine is created with 128 virtio-mmio bus, and they can
be used to use serial console, GPU, disk, NIC, HID, ...

Signed-off-by: Laurent Vivier 
Reviewed-by: Richard Henderson 
---
 default-configs/devices/m68k-softmmu.mak  |   1 +
 .../standard-headers/asm-m68k/bootinfo-virt.h |  18 +
 hw/m68k/virt.c| 313 ++
 MAINTAINERS   |  13 +
 hw/m68k/Kconfig   |  10 +
 hw/m68k/meson.build   |   1 +
 6 files changed, 356 insertions(+)
 create mode 100644 include/standard-headers/asm-m68k/bootinfo-virt.h
 create mode 100644 hw/m68k/virt.c

diff --git a/default-configs/devices/m68k-softmmu.mak 
b/default-configs/devices/m68k-softmmu.mak
index 6629fd2aa330..7f8619e42786 100644
--- a/default-configs/devices/m68k-softmmu.mak
+++ b/default-configs/devices/m68k-softmmu.mak
@@ -8,3 +8,4 @@ CONFIG_AN5206=y
 CONFIG_MCF5208=y
 CONFIG_NEXTCUBE=y
 CONFIG_Q800=y
+CONFIG_M68K_VIRT=y
diff --git a/include/standard-headers/asm-m68k/bootinfo-virt.h 
b/include/standard-headers/asm-m68k/bootinfo-virt.h
new file mode 100644
index ..81be1e092497
--- /dev/null
+++ b/include/standard-headers/asm-m68k/bootinfo-virt.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/*
+** asm/bootinfo-virt.h -- Virtual-m68k-specific boot information definitions
+*/
+
+#ifndef _UAPI_ASM_M68K_BOOTINFO_VIRT_H
+#define _UAPI_ASM_M68K_BOOTINFO_VIRT_H
+
+#define BI_VIRT_QEMU_VERSION   0x8000
+#define BI_VIRT_GF_PIC_BASE0x8001
+#define BI_VIRT_GF_RTC_BASE0x8002
+#define BI_VIRT_GF_TTY_BASE0x8003
+#define BI_VIRT_VIRTIO_BASE0x8004
+#define BI_VIRT_CTRL_BASE  0x8005
+
+#define VIRT_BOOTI_VERSION MK_BI_VERSION(2, 0)
+
+#endif /* _UAPI_ASM_M68K_BOOTINFO_MAC_H */
diff --git a/hw/m68k/virt.c b/hw/m68k/virt.c
new file mode 100644
index ..b813cf58eacd
--- /dev/null
+++ b/hw/m68k/virt.c
@@ -0,0 +1,313 @@
+/*
+ * SPDX-License-Identifer: GPL-2.0-or-later
+ *
+ * QEMU Vitual M68K Machine
+ *
+ * (c) 2020 Laurent Vivier 
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/units.h"
+#include "qemu-common.h"
+#include "sysemu/sysemu.h"
+#include "cpu.h"
+#include "hw/hw.h"
+#include "hw/boards.h"
+#include "hw/irq.h"
+#include "hw/qdev-properties.h"
+#include "elf.h"
+#include "hw/loader.h"
+#include "ui/console.h"
+#include "exec/address-spaces.h"
+#include "hw/sysbus.h"
+#include "standard-headers/asm-m68k/bootinfo.h"
+#include "standard-headers/asm-m68k/bootinfo-virt.h"
+#include "bootinfo.h"
+#include "net/net.h"
+#include "qapi/error.h"
+#include "sysemu/qtest.h"
+#include "sysemu/runstate.h"
+#include "sysemu/reset.h"
+
+#include "hw/intc/m68k_irqc.h"
+#include "hw/misc/m68k_virt_ctrl.h"
+#include "hw/char/goldfish_tty.h"
+#include "hw/rtc/goldfish_rtc.h"
+#include "hw/intc/goldfish_pic.h"
+#include "hw/virtio/virtio-mmio.h"
+#include "hw/virtio/virtio-blk.h"
+
+/*
+ * 6 goldfish-pic for CPU IRQ #1 to IRQ #6
+ * CPU IRQ #1 -> PIC #1
+ *   IRQ #1 to IRQ #31 -> unused
+ *   IRQ #32 -> goldfish-tty
+ * CPU IRQ #2 -> PIC #2
+ *   IRQ #1 to IRQ #32 -> virtio-mmio from 1 to 32
+ * CPU IRQ #3 -> PIC #3
+ *   IRQ #1 to IRQ #32 -> virtio-mmio from 33 to 64
+ * CPU IRQ #4 -> PIC #4
+ *   IRQ #1 to IRQ #32 -> virtio-mmio from 65 to 96
+ * CPU IRQ #5 -> PIC #5
+ *   IRQ #1 to IRQ #32 -> virtio-mmio from 97 to 128
+ * CPU IRQ #6 -> PIC #6
+ *   IRQ #1 -> goldfish-rtc
+ *   IRQ #2 to IRQ #32 -> unused
+ * CPU IRQ #7 -> NMI
+ */
+
+#define PIC_IRQ_BASE(num) (8 + (num - 1) * 32)
+#define PIC_IRQ(num, irq) (PIC_IRQ_BASE(num) + irq - 1)
+#define PIC_GPIO(pic_irq) (qdev_get_gpio_in(pic_dev[(pic_irq - 8) / 32], \
+(pic_irq - 8) % 32))
+
+#define VIRT_GF_PIC_MMIO_BASE 0xff00 /* MMIO: 0xff00 - 0xff005fff 
*/
+#define VIRT_GF_PIC_IRQ_BASE  1  /* IRQ: #1 -> #6 */
+#define VIRT_GF_PIC_NB6
+
+/* 2 goldfish-rtc (and timer) */
+#define VIRT_GF_RTC_MMIO_BASE 0xff006000 /* MMIO: 0xff006000 - 0xff007fff 
*/
+#define VIRT_GF_RTC_IRQ_BASE  PIC_IRQ(6, 1)  /* PIC: #6, IRQ: #1 */
+#define VIRT_GF_RTC_NB2
+
+/* 1 goldfish-tty */
+#define VIRT_GF_TTY_MMIO_BASE 0xff008000 /* MMIO: 0xff008000 - 0xff008fff 
*/
+#define VIRT_GF_TTY_IRQ_BASE  PIC_IRQ(1, 32) /* PIC: #1, IRQ: #32 */
+
+/* 1 m68k-virt-ctrl */
+#define VIRT_M68K_CTRL_MMIO_BASE 0xff009000/* MMIO: 0xff009000 - 
0xff009fff */
+#define VIRT_M68K_CTRL_IRQ_BASE  PIC_IRQ(1, 1) /* PIC: #1, IRQ: #1 */
+
+/*
+ * virtio-mmio size is 0x200 bytes
+ * we use 4 goldfish-pic to attach them,
+ * we can attach 32 virtio devices / goldfish-pic
+ * -> we can 

[PATCH v4 3/5] m68k: add an interrupt controller

2021-03-07 Thread Laurent Vivier
A (generic) copy of the GLUE device we already have for q800 to use with
the m68k-virt machine.
The q800 one would disappear in the future as q800 uses actually the djMEMC
controller.

Signed-off-by: Laurent Vivier 
Reviewed-by: Richard Henderson 
Reviewed-by: Philippe Mathieu-Daudé 
---
 include/hw/intc/m68k_irqc.h |  41 +
 hw/intc/m68k_irqc.c | 119 
 hw/intc/Kconfig |   3 +
 hw/intc/meson.build |   1 +
 4 files changed, 164 insertions(+)
 create mode 100644 include/hw/intc/m68k_irqc.h
 create mode 100644 hw/intc/m68k_irqc.c

diff --git a/include/hw/intc/m68k_irqc.h b/include/hw/intc/m68k_irqc.h
new file mode 100644
index ..dbcfcfc2e000
--- /dev/null
+++ b/include/hw/intc/m68k_irqc.h
@@ -0,0 +1,41 @@
+/*
+ * SPDX-License-Identifer: GPL-2.0-or-later
+ *
+ * QEMU Motorola 680x0 IRQ Controller
+ *
+ * (c) 2020 Laurent Vivier 
+ *
+ */
+
+#ifndef M68K_IRQC_H
+#define M68K_IRQC_H
+
+#include "hw/sysbus.h"
+
+#define TYPE_M68K_IRQC "m68k-irq-controller"
+#define M68K_IRQC(obj) OBJECT_CHECK(M68KIRQCState, (obj), \
+TYPE_M68K_IRQC)
+
+#define M68K_IRQC_AUTOVECTOR_BASE 25
+
+enum {
+M68K_IRQC_LEVEL_1 = 0,
+M68K_IRQC_LEVEL_2,
+M68K_IRQC_LEVEL_3,
+M68K_IRQC_LEVEL_4,
+M68K_IRQC_LEVEL_5,
+M68K_IRQC_LEVEL_6,
+M68K_IRQC_LEVEL_7,
+};
+#define M68K_IRQC_LEVEL_NUM (M68K_IRQC_LEVEL_7 - M68K_IRQC_LEVEL_1 + 1)
+
+typedef struct M68KIRQCState {
+SysBusDevice parent_obj;
+
+uint8_t ipr;
+
+/* statistics */
+uint64_t stats_irq_count[M68K_IRQC_LEVEL_NUM];
+} M68KIRQCState;
+
+#endif
diff --git a/hw/intc/m68k_irqc.c b/hw/intc/m68k_irqc.c
new file mode 100644
index ..2133d2a698ab
--- /dev/null
+++ b/hw/intc/m68k_irqc.c
@@ -0,0 +1,119 @@
+/*
+ * SPDX-License-Identifer: GPL-2.0-or-later
+ *
+ * QEMU Motorola 680x0 IRQ Controller
+ *
+ * (c) 2020 Laurent Vivier 
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "migration/vmstate.h"
+#include "monitor/monitor.h"
+#include "hw/nmi.h"
+#include "hw/intc/intc.h"
+#include "hw/intc/m68k_irqc.h"
+
+
+static bool m68k_irqc_get_statistics(InterruptStatsProvider *obj,
+ uint64_t **irq_counts, unsigned int 
*nb_irqs)
+{
+M68KIRQCState *s = M68K_IRQC(obj);
+
+*irq_counts = s->stats_irq_count;
+*nb_irqs = ARRAY_SIZE(s->stats_irq_count);
+return true;
+}
+
+static void m68k_irqc_print_info(InterruptStatsProvider *obj, Monitor *mon)
+{
+M68KIRQCState *s = M68K_IRQC(obj);
+monitor_printf(mon, "m68k-irqc: ipr=0x%x\n", s->ipr);
+}
+
+static void m68k_set_irq(void *opaque, int irq, int level)
+{
+M68KIRQCState *s = opaque;
+M68kCPU *cpu = M68K_CPU(first_cpu);
+int i;
+
+if (level) {
+s->ipr |= 1 << irq;
+s->stats_irq_count[irq]++;
+} else {
+s->ipr &= ~(1 << irq);
+}
+
+for (i = M68K_IRQC_LEVEL_7; i >= M68K_IRQC_LEVEL_1; i--) {
+if ((s->ipr >> i) & 1) {
+m68k_set_irq_level(cpu, i + 1, i + M68K_IRQC_AUTOVECTOR_BASE);
+return;
+}
+}
+m68k_set_irq_level(cpu, 0, 0);
+}
+
+static void m68k_irqc_reset(DeviceState *d)
+{
+M68KIRQCState *s = M68K_IRQC(d);
+int i;
+
+s->ipr = 0;
+for (i = 0; i < ARRAY_SIZE(s->stats_irq_count); i++) {
+s->stats_irq_count[i] = 0;
+}
+}
+
+static void m68k_irqc_instance_init(Object *obj)
+{
+qdev_init_gpio_in(DEVICE(obj), m68k_set_irq, M68K_IRQC_LEVEL_NUM);
+}
+
+static void m68k_nmi(NMIState *n, int cpu_index, Error **errp)
+{
+m68k_set_irq(n, M68K_IRQC_LEVEL_7, 1);
+}
+
+static const VMStateDescription vmstate_m68k_irqc = {
+.name = "m68k-irqc",
+.version_id = 1,
+.minimum_version_id = 1,
+.fields = (VMStateField[]) {
+VMSTATE_UINT8(ipr, M68KIRQCState),
+VMSTATE_END_OF_LIST()
+}
+};
+
+static void m68k_irqc_class_init(ObjectClass *oc, void *data)
+ {
+DeviceClass *dc = DEVICE_CLASS(oc);
+NMIClass *nc = NMI_CLASS(oc);
+InterruptStatsProviderClass *ic = INTERRUPT_STATS_PROVIDER_CLASS(oc);
+
+nc->nmi_monitor_handler = m68k_nmi;
+dc->reset = m68k_irqc_reset;
+dc->vmsd = _m68k_irqc;
+ic->get_statistics = m68k_irqc_get_statistics;
+ic->print_info = m68k_irqc_print_info;
+}
+
+static const TypeInfo m68k_irqc_type_info = {
+.name = TYPE_M68K_IRQC,
+.parent = TYPE_SYS_BUS_DEVICE,
+.instance_size = sizeof(M68KIRQCState),
+.instance_init = m68k_irqc_instance_init,
+.class_init = m68k_irqc_class_init,
+.interfaces = (InterfaceInfo[]) {
+ { TYPE_NMI },
+ { TYPE_INTERRUPT_STATS_PROVIDER },
+ { }
+},
+};
+
+static void q800_irq_register_types(void)
+{
+type_register_static(_irqc_type_info);
+}
+
+type_init(q800_irq_register_types);
diff --git a/hw/intc/Kconfig b/hw/intc/Kconfig
index c4f8642dae8e..fdb4a30b98e8 100644
--- a/hw/intc/Kconfig
+++ b/hw/intc/Kconfig
@@ -67,3 +67,6 @@ config 

[PATCH v4 2/5] intc: add goldfish-pic

2021-03-07 Thread Laurent Vivier
Implement the goldfish pic device as defined in

https://android.googlesource.com/platform/external/qemu/+/master/docs/GOLDFISH-VIRTUAL-HARDWARE.TXT

Signed-off-by: Laurent Vivier 
Reviewed-by: Richard Henderson 
Reviewed-by: Philippe Mathieu-Daudé 
---
 include/hw/intc/goldfish_pic.h |  33 +
 hw/intc/goldfish_pic.c | 219 +
 hw/intc/Kconfig|   3 +
 hw/intc/meson.build|   1 +
 hw/intc/trace-events   |   8 ++
 5 files changed, 264 insertions(+)
 create mode 100644 include/hw/intc/goldfish_pic.h
 create mode 100644 hw/intc/goldfish_pic.c

diff --git a/include/hw/intc/goldfish_pic.h b/include/hw/intc/goldfish_pic.h
new file mode 100644
index ..ad13ab37fc3e
--- /dev/null
+++ b/include/hw/intc/goldfish_pic.h
@@ -0,0 +1,33 @@
+/*
+ * SPDX-License-Identifer: GPL-2.0-or-later
+ *
+ * Goldfish PIC
+ *
+ * (c) 2020 Laurent Vivier 
+ *
+ */
+
+#ifndef HW_INTC_GOLDFISH_PIC_H
+#define HW_INTC_GOLDFISH_PIC_H
+
+#define TYPE_GOLDFISH_PIC "goldfish_pic"
+OBJECT_DECLARE_SIMPLE_TYPE(GoldfishPICState, GOLDFISH_PIC)
+
+#define GOLDFISH_PIC_IRQ_NB 32
+
+struct GoldfishPICState {
+SysBusDevice parent_obj;
+
+MemoryRegion iomem;
+qemu_irq irq;
+
+uint32_t pending;
+uint32_t enabled;
+
+/* statistics */
+uint64_t stats_irq_count[32];
+/* for tracing */
+uint8_t idx;
+};
+
+#endif
diff --git a/hw/intc/goldfish_pic.c b/hw/intc/goldfish_pic.c
new file mode 100644
index ..e3b43a69f163
--- /dev/null
+++ b/hw/intc/goldfish_pic.c
@@ -0,0 +1,219 @@
+/*
+ * SPDX-License-Identifer: GPL-2.0-or-later
+ *
+ * Goldfish PIC
+ *
+ * (c) 2020 Laurent Vivier 
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "hw/irq.h"
+#include "hw/qdev-properties.h"
+#include "hw/sysbus.h"
+#include "migration/vmstate.h"
+#include "monitor/monitor.h"
+#include "qemu/log.h"
+#include "trace.h"
+#include "hw/intc/intc.h"
+#include "hw/intc/goldfish_pic.h"
+
+/* registers */
+
+enum {
+REG_STATUS  = 0x00,
+REG_IRQ_PENDING = 0x04,
+REG_IRQ_DISABLE_ALL = 0x08,
+REG_DISABLE = 0x0c,
+REG_ENABLE  = 0x10,
+};
+
+static bool goldfish_pic_get_statistics(InterruptStatsProvider *obj,
+uint64_t **irq_counts,
+unsigned int *nb_irqs)
+{
+GoldfishPICState *s = GOLDFISH_PIC(obj);
+
+*irq_counts = s->stats_irq_count;
+*nb_irqs = ARRAY_SIZE(s->stats_irq_count);
+return true;
+}
+
+static void goldfish_pic_print_info(InterruptStatsProvider *obj, Monitor *mon)
+{
+GoldfishPICState *s = GOLDFISH_PIC(obj);
+monitor_printf(mon, "goldfish-pic.%d: pending=0x%08x enabled=0x%08x\n",
+   s->idx, s->pending, s->enabled);
+}
+
+static void goldfish_pic_update(GoldfishPICState *s)
+{
+if (s->pending & s->enabled) {
+qemu_irq_raise(s->irq);
+} else {
+qemu_irq_lower(s->irq);
+}
+}
+
+static void goldfish_irq_request(void *opaque, int irq, int level)
+{
+GoldfishPICState *s = opaque;
+
+trace_goldfish_irq_request(s, s->idx, irq, level);
+
+if (level) {
+s->pending |= 1 << irq;
+s->stats_irq_count[irq]++;
+} else {
+s->pending &= ~(1 << irq);
+}
+goldfish_pic_update(s);
+}
+
+static uint64_t goldfish_pic_read(void *opaque, hwaddr addr,
+  unsigned size)
+{
+GoldfishPICState *s = opaque;
+uint64_t value = 0;
+
+switch (addr) {
+case REG_STATUS:
+/* The number of pending interrupts (0 to 32) */
+value = ctpop32(s->pending & s->enabled);
+break;
+case REG_IRQ_PENDING:
+/* The pending interrupt mask */
+value = s->pending & s->enabled;
+break;
+default:
+qemu_log_mask(LOG_UNIMP,
+  "%s: unimplemented register read 0x%02"HWADDR_PRIx"\n",
+  __func__, addr);
+break;
+}
+
+trace_goldfish_pic_read(s, s->idx, addr, size, value);
+
+return value;
+}
+
+static void goldfish_pic_write(void *opaque, hwaddr addr,
+   uint64_t value, unsigned size)
+{
+GoldfishPICState *s = opaque;
+
+trace_goldfish_pic_write(s, s->idx, addr, size, value);
+
+switch (addr) {
+case REG_IRQ_DISABLE_ALL:
+s->enabled = 0;
+s->pending = 0;
+break;
+case REG_DISABLE:
+s->enabled &= ~value;
+break;
+case REG_ENABLE:
+s->enabled |= value;
+break;
+default:
+qemu_log_mask(LOG_UNIMP,
+  "%s: unimplemented register write 0x%02"HWADDR_PRIx"\n",
+  __func__, addr);
+break;
+}
+goldfish_pic_update(s);
+}
+
+static const MemoryRegionOps goldfish_pic_ops = {
+.read = goldfish_pic_read,
+.write = goldfish_pic_write,
+.endianness = DEVICE_NATIVE_ENDIAN,
+.valid.max_access_size = 4,
+.impl.min_access_size = 4,
+   

[PATCH v4 4/5] m68k: add a system controller

2021-03-07 Thread Laurent Vivier
Add a system controller for the m68k-virt machine.
This controller allows the kernel to power off or reset the machine.

Signed-off-by: Laurent Vivier 
Reviewed-by: Richard Henderson 
---
 include/hw/misc/m68k_virt_ctrl.h |  22 +
 hw/misc/m68k_virt_ctrl.c | 152 +++
 hw/misc/Kconfig  |   3 +
 hw/misc/meson.build  |   3 +
 hw/misc/trace-events |   7 ++
 5 files changed, 187 insertions(+)
 create mode 100644 include/hw/misc/m68k_virt_ctrl.h
 create mode 100644 hw/misc/m68k_virt_ctrl.c

diff --git a/include/hw/misc/m68k_virt_ctrl.h b/include/hw/misc/m68k_virt_ctrl.h
new file mode 100644
index ..1db7960e5477
--- /dev/null
+++ b/include/hw/misc/m68k_virt_ctrl.h
@@ -0,0 +1,22 @@
+/*
+ * SPDX-License-Identifer: GPL-2.0-or-later
+ *
+ * Virt m68k system Controller
+ */
+
+#ifndef M68K_VIRT_CTRL_H
+#define M68K_VIRT_CTRL_H
+
+#define TYPE_M68K_VIRT_CTRL "m68k-virt-ctrl"
+OBJECT_DECLARE_SIMPLE_TYPE(M68KVirtCtrlState, M68K_VIRT_CTRL)
+
+struct M68KVirtCtrlState {
+SysBusDevice parent_obj;
+
+MemoryRegion iomem;
+qemu_irq irq;
+
+uint32_t irq_enabled;
+};
+
+#endif
diff --git a/hw/misc/m68k_virt_ctrl.c b/hw/misc/m68k_virt_ctrl.c
new file mode 100644
index ..fb34aa10211a
--- /dev/null
+++ b/hw/misc/m68k_virt_ctrl.c
@@ -0,0 +1,152 @@
+/*
+ * SPDX-License-Identifer: GPL-2.0-or-later
+ *
+ * Virt m68k system Controller
+ */
+
+#include "qemu/osdep.h"
+#include "hw/irq.h"
+#include "hw/qdev-properties.h"
+#include "hw/sysbus.h"
+#include "migration/vmstate.h"
+#include "qemu/log.h"
+#include "trace.h"
+#include "sysemu/runstate.h"
+#include "hw/misc/m68k_virt_ctrl.h"
+
+enum {
+REG_FEATURES = 0x00,
+REG_CMD  = 0x04,
+};
+
+#define FEAT_POWER_CTRL 0x0001
+
+enum {
+CMD_NOOP,
+CMD_RESET,
+CMD_HALT,
+CMD_PANIC,
+};
+
+static uint64_t m68k_virt_ctrl_read(void *opaque, hwaddr addr,
+unsigned size)
+{
+M68KVirtCtrlState *s = opaque;
+uint64_t value = 0;
+
+switch (addr) {
+case REG_FEATURES:
+value = FEAT_POWER_CTRL;
+break;
+default:
+qemu_log_mask(LOG_UNIMP,
+  "%s: unimplemented register read 0x%02"HWADDR_PRIx"\n",
+  __func__, addr);
+break;
+}
+
+trace_m68k_virt_ctrl_write(s, addr, size, value);
+
+return value;
+}
+
+static void m68k_virt_ctrl_write(void *opaque, hwaddr addr,
+ uint64_t value, unsigned size)
+{
+M68KVirtCtrlState *s = opaque;
+
+trace_m68k_virt_ctrl_write(s, addr, size, value);
+
+switch (addr) {
+case REG_CMD:
+switch (value) {
+case CMD_NOOP:
+break;
+case CMD_RESET:
+qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
+break;
+case CMD_HALT:
+qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
+break;
+case CMD_PANIC:
+qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_PANIC);
+break;
+}
+break;
+default:
+qemu_log_mask(LOG_UNIMP,
+  "%s: unimplemented register write 0x%02"HWADDR_PRIx"\n",
+  __func__, addr);
+break;
+}
+}
+
+static const MemoryRegionOps m68k_virt_ctrl_ops = {
+.read = m68k_virt_ctrl_read,
+.write = m68k_virt_ctrl_write,
+.endianness = DEVICE_NATIVE_ENDIAN,
+.valid.max_access_size = 4,
+.impl.max_access_size = 4,
+};
+
+static void m68k_virt_ctrl_reset(DeviceState *dev)
+{
+M68KVirtCtrlState *s = M68K_VIRT_CTRL(dev);
+
+trace_m68k_virt_ctrl_reset(s);
+}
+
+static void m68k_virt_ctrl_realize(DeviceState *dev, Error **errp)
+{
+M68KVirtCtrlState *s = M68K_VIRT_CTRL(dev);
+
+trace_m68k_virt_ctrl_instance_init(s);
+
+memory_region_init_io(>iomem, OBJECT(s), _virt_ctrl_ops, s,
+  "m68k-virt-ctrl", 0x100);
+}
+
+static const VMStateDescription vmstate_m68k_virt_ctrl = {
+.name = "m68k-virt-ctrl",
+.version_id = 1,
+.minimum_version_id = 1,
+.fields = (VMStateField[]) {
+VMSTATE_UINT32(irq_enabled, M68KVirtCtrlState),
+VMSTATE_END_OF_LIST()
+}
+};
+
+static void m68k_virt_ctrl_instance_init(Object *obj)
+{
+SysBusDevice *dev = SYS_BUS_DEVICE(obj);
+M68KVirtCtrlState *s = M68K_VIRT_CTRL(obj);
+
+trace_m68k_virt_ctrl_instance_init(s);
+
+sysbus_init_mmio(dev, >iomem);
+sysbus_init_irq(dev, >irq);
+}
+
+static void m68k_virt_ctrl_class_init(ObjectClass *oc, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(oc);
+
+dc->reset = m68k_virt_ctrl_reset;
+dc->realize = m68k_virt_ctrl_realize;
+dc->vmsd = _m68k_virt_ctrl;
+}
+
+static const TypeInfo m68k_virt_ctrl_info = {
+.name = TYPE_M68K_VIRT_CTRL,
+.parent = TYPE_SYS_BUS_DEVICE,
+.class_init = m68k_virt_ctrl_class_init,
+.instance_init = 

[PATCH v4 0/5] m68k: add Virtual M68k Machine

2021-03-07 Thread Laurent Vivier
The Quadra 800 machine is very limited to run linux, it manages
only 1 GiB of memory and only some specific interfaces.

The Virtual M68k Machine is based on Goldfish interfaces defined by Google
for Android simulator. It uses Goldfish-rtc (timer and RTC),
Goldfish-pic (PIC) and Goldfish-tty (for serial port and early tty).

https://android.googlesource.com/platform/external/qemu/+/master/docs/GOLDFIS=
H-VIRTUAL-HARDWARE.TXT

The machine is created with 128 virtio-mmio busses, and they can
be used to add serial console, GPU, disk, NIC, HID, ...

This series re-use the goldfish-rtc implemented for RISCV, and
adds the two others based on the goldfish specs, the kernel driver
and android simulator ones.

The machine can manage up to 3.2 GiB of memory, not because of an hardware
limitation but because the kernel crashes after this value.

Simply configure qemu with:

.../configure --target-list=3Dm68k-softmmu

To run the machine you need a modified kernel you can find here:

https://github.com/vivier/linux/tree/m68k-virt

You need to compile the kernel with:

make virt_defconfig
make vmlinux

The disk must be installed using the q800 machine because the debian installer
doesn't want to be used with a kernel that is not the one on the ISO.

And then you can run the machine with something like:

qemu-system-m68k -M virt \
  -m 3399672K \
  -chardev stdio,signal=3Doff,mux=3Don,id=3Dchar0 \
  -mon chardev=3Dchar0,mode=3Dreadline \
  -kernel vmlinux \
  -append "console=3Dhvc0 root=3D/dev/vda2" \
  -blockdev node-name=3Dsystem,driver=3Dfile,filename=3Ddebian-10.0.qcow2 \
  -blockdev node-name=3Ddrive0,driver=3Dqcow2,file=3Dsystem \
  -device virtio-blk-device,drive=3Ddrive0 \
  -serial chardev:char0 \
  -device virtio-net-device,netdev=3Dhostnet0 \
  -netdev bridge,id=3Dhostnet0,br=3Dvirbr0 \
  -device virtio-rng-device \
  -device virtio-serial-device \
  -device virtio-gpu-device \
  -device virtconsole,chardev=3Dchar0 \
  -device virtio-keyboard-device \
  -device virtio-mouse-device

if you want to use Goldfish-tty for the console rather than virtconsole, you
can add "console=3DttyGF".

To start the debian-installer, you can try by adding:

  -device virtio-scsi-device \
  -blockdev node-name=3Ddebian10,driver=3Dfile,filename=3Ddebian-10.0.0-m68k-=
NETINST-1.iso \
  -blockdev node-name=3Dcdrom0,driver=3Draw,file=3Ddebian10 \
  -device scsi-cd,drive=3Dcdrom0 \
  -initrd installer-m68k/20200315/images/cdrom/initrd.gz

ISO:https://cdimage.debian.org/cdimage/ports/snapshots/2020-10-12/debian-=
10.0.0-m68k-NETINST-1.iso
initrd: https://cdimage.debian.org/cdimage/ports/debian-installer/2020-10-12/=
m68k/debian-installer-images_20200315_m68k.tar.gz

v4:
  goldfish-tty:
  Use fifo8 for the data_in buffer
  Remove the data_out buffer from the struct and put it directly in
  the function. We don't need to use the fifo8 type because we
  can't bufferize the data as we can't stop the tx queue when the buffer
  is full. We rely on qemu_chr_fe_write_all() that blocks the thread for
  that.
  goldfish-pic:
  Add DEFINE_PROP_UINT8() for the index
  Add .impl.min_access_size

v3:
  Add some #define for the interrupt controller (and fix the number of IRQs)
  Add some comments
  Update MAINTAINERS
  Remove "goldfish_rtc: re-arm the alarm after migration" that will be
  merged via the RISC-V branch.

v2:
  Add an interrupt controller to replace the Q800 GLUE
  Add a system controller to shutdown the machine
  Add a fix for goldfish_rtc (already sent alone)
  Add statistics in goldfish-pic
  Add versionned machine type
  Use two goldfish-rtc rather than only one (for timer and RTC)

Laurent Vivier (5):
  char: add goldfish-tty
  intc: add goldfish-pic
  m68k: add an interrupt controller
  m68k: add a system controller
  m68k: add Virtual M68k Machine

 default-configs/devices/m68k-softmmu.mak  |   1 +
 include/hw/char/goldfish_tty.h|  35 ++
 include/hw/intc/goldfish_pic.h|  33 ++
 include/hw/intc/m68k_irqc.h   |  41 +++
 include/hw/misc/m68k_virt_ctrl.h  |  22 ++
 .../standard-headers/asm-m68k/bootinfo-virt.h |  18 +
 hw/char/goldfish_tty.c| 272 +++
 hw/intc/goldfish_pic.c| 219 
 hw/intc/m68k_irqc.c   | 119 +++
 hw/m68k/virt.c| 313 ++
 hw/misc/m68k_virt_ctrl.c  | 152 +
 MAINTAINERS   |  13 +
 hw/char/Kconfig   |   3 +
 hw/char/meson.build   |   2 +
 hw/char/trace-events  |  10 +
 hw/intc/Kconfig   |   6 +
 hw/intc/meson.build   |   2 +
 hw/intc/trace-events  |   8 +
 hw/m68k/Kconfig   |  10 +
 hw/m68k/meson.build 

RESEND [PATCH v2] bsd-user: Add new maintainers

2021-03-07 Thread Warner Losh
The FreeBSD project has a number of enhancements to bsd-user. Add myself
as maintainer and Kyle Evans as a reviewer. Also add our github repo.

Signed-off-by: Warner Losh 
Signed-off-by: Kyle Evans 
Reviewed-by: Thomas Huth 
---
 MAINTAINERS | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 26c9454823..ec0e935038 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2896,9 +2896,12 @@ F: thunk.c
 F: accel/tcg/user-exec*.c
 
 BSD user
-S: Orphan
+M: Warner Losh 
+R: Kyle Evans 
+S: Maintained
 F: bsd-user/
 F: default-configs/targets/*-bsd-user.mak
+T: git https://github.com/qemu-bsd-user/qemu-bsd-user bsd-user-rebase-3.1
 
 Linux user
 M: Laurent Vivier 
-- 
2.30.0




[PATCH v2] FreeBSD: Upgrade to 12.2 release

2021-03-07 Thread Warner Losh
FreeBSD 12.1 has reached end of life. Use 12.2 instead so that FreeBSD's
project's packages will work.  Update which timezone to pick. Work around a QEMU
bug that incorrectly raises an exception on a CRC32 instruction with the FPU
disabled.  The qemu bug is described here:
https://www.mail-archive.com/qemu-devel@nongnu.org/msg784158.html

Signed-off-by: Warner Losh 

---
 tests/vm/freebsd | 14 +-
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/tests/vm/freebsd b/tests/vm/freebsd
index 09f3ee6cb8..81389d527e 100755
--- a/tests/vm/freebsd
+++ b/tests/vm/freebsd
@@ -20,12 +20,16 @@ import socket
 import subprocess
 import basevm
 
+FREEBSD_CONFIG = {
+'cpu'  : "max,sse4.2=off",
+}
+
 class FreeBSDVM(basevm.BaseVM):
 name = "freebsd"
 arch = "x86_64"
 
-link = 
"https://download.freebsd.org/ftp/releases/ISO-IMAGES/12.1/FreeBSD-12.1-RELEASE-amd64-disc1.iso.xz;
-csum = "7394c3f60a1e236e7bd3a05809cf43ae39a3b8e5d42d782004cf2f26b1cfcd88"
+link = 
"https://download.freebsd.org/ftp/releases/ISO-IMAGES/12.2/FreeBSD-12.2-RELEASE-amd64-disc1.iso.xz;
+csum = "a4530246cafbf1dd42a9bd3ea441ca9a78a6a0cd070278cbdf63f3a6f803ecae"
 size = "20G"
 pkgs = [
 # build tools
@@ -125,7 +129,7 @@ class FreeBSDVM(basevm.BaseVM):
 self.console_wait_send("IPv6",  "n")
 self.console_wait_send("Resolver",  "\n")
 
-self.console_wait_send("Time Zone Selector","a\n")
+self.console_wait_send("Time Zone Selector","0\n")
 self.console_wait_send("Confirmation",  "y")
 self.console_wait_send("Time & Date",   "\n")
 self.console_wait_send("Time & Date",   "\n")
@@ -206,4 +210,4 @@ class FreeBSDVM(basevm.BaseVM):
 self.print_step("All done")
 
 if __name__ == "__main__":
-sys.exit(basevm.main(FreeBSDVM))
+sys.exit(basevm.main(FreeBSDVM, config=FREEBSD_CONFIG))
-- 
2.30.0




Re: [PATCH v2 8/9] util/mmap-alloc: Support RAM_NORESERVE via MAP_NORESERVE

2021-03-07 Thread Marcel Apfelbaum
Hi David,

On Sun, Mar 7, 2021 at 3:18 PM David Hildenbrand  wrote:

> On 05.03.21 16:51, Peter Xu wrote:
> > On Fri, Mar 05, 2021 at 04:44:36PM +0100, David Hildenbrand wrote:
> >> On 05.03.21 16:42, Peter Xu wrote:
> >>> On Fri, Mar 05, 2021 at 11:16:33AM +0100, David Hildenbrand wrote:
>  +#define OVERCOMMIT_MEMORY_PATH "/proc/sys/vm/overcommit_memory"
>  +static bool map_noreserve_effective(int fd, bool readonly, bool
> shared)
>  +{
> >>>
> >>> [...]
> >>>
>  @@ -184,8 +251,7 @@ void *qemu_ram_mmap(int fd,
> size_t offset, total;
> void *ptr, *guardptr;
>  -if (noreserve) {
>  -error_report("Skipping reservation of swap space is not
> supported");
>  +if (noreserve && !map_noreserve_effective(fd, shared, readonly))
> {
> >>>
> >>> Need to switch "shared" & "readonly"?
> >>
> >> Indeed, interestingly it has the same effect (as we don't have anonymous
> >> read-only memory in QEMU :) )
> >
> > But note there is still a "g_assert(!shared || fd >= 0);" inside.. :)
>
> Aand, I just figured that we actually can create shared anonymous
> memory in QEMU, simply via
>
> -object memory-backend-ram,share=on
>
> Introduced in 06329ccecfa0 ("mem: add share parameter to
> memory-backend-ram"). That's also where we introduced the "shared" flag
> for qemu_anon_ram_alloc().
>
> That commit mentions a use case for "RDMA devices in order to remap
> non-contiguous QEMU virtual addresses to a contiguous virtual address
> range.". I fail to understand why that requires sharing RAM with child
> processes.
>
> Especially:
>
> a) qemu_ram_is_shared() returned false before patch #1. RAM_SHARED is
> never set.
>
> b) qemu_ram_remap() does not work as expected?
>
> c) ram_discard_range() is broken with shared anonymous memory. Instead
> of MADV_DONTNEED we need MADV_REMOVE.
>
> This looks like a partially broken feature and I wonder if there is an
> actual user.
>
> @Marcel, can you clarify if there is an actual use case for shared
> anonymous memory in QEMU? I.e., if the original use case that required
> that change is valid? (and why it wasn't able to just use proper shmem)
>
>
As you correctly stated, the PVRDMA device requires remapping of
non-contiguous QEMU
virtual addresses to a contiguous virtual address range.

In order to do so it calls
 mremap (... , MREMAP_MAYMOVE | MREMAP_FIXED, ...)
The above call succeeds only if the memory is marked as "shared".


> Shared anonymous memory is weird.
>

In this case it is not about sharing the memory between different
processes, but about being
able to remap it.

Thanks,
Marcel


>
> --
> Thanks,
>
> David / dhildenb
>
>


Re: [PATCH v2 8/9] util/mmap-alloc: Support RAM_NORESERVE via MAP_NORESERVE

2021-03-07 Thread David Hildenbrand

On 05.03.21 16:51, Peter Xu wrote:

On Fri, Mar 05, 2021 at 04:44:36PM +0100, David Hildenbrand wrote:

On 05.03.21 16:42, Peter Xu wrote:

On Fri, Mar 05, 2021 at 11:16:33AM +0100, David Hildenbrand wrote:

+#define OVERCOMMIT_MEMORY_PATH "/proc/sys/vm/overcommit_memory"
+static bool map_noreserve_effective(int fd, bool readonly, bool shared)
+{


[...]


@@ -184,8 +251,7 @@ void *qemu_ram_mmap(int fd,
   size_t offset, total;
   void *ptr, *guardptr;
-if (noreserve) {
-error_report("Skipping reservation of swap space is not supported");
+if (noreserve && !map_noreserve_effective(fd, shared, readonly)) {


Need to switch "shared" & "readonly"?


Indeed, interestingly it has the same effect (as we don't have anonymous
read-only memory in QEMU :) )


But note there is still a "g_assert(!shared || fd >= 0);" inside.. :)


Aand, I just figured that we actually can create shared anonymous 
memory in QEMU, simply via


-object memory-backend-ram,share=on

Introduced in 06329ccecfa0 ("mem: add share parameter to 
memory-backend-ram"). That's also where we introduced the "shared" flag 
for qemu_anon_ram_alloc().


That commit mentions a use case for "RDMA devices in order to remap 
non-contiguous QEMU virtual addresses to a contiguous virtual address 
range.". I fail to understand why that requires sharing RAM with child 
processes.


Especially:

a) qemu_ram_is_shared() returned false before patch #1. RAM_SHARED is 
never set.


b) qemu_ram_remap() does not work as expected?

c) ram_discard_range() is broken with shared anonymous memory. Instead 
of MADV_DONTNEED we need MADV_REMOVE.


This looks like a partially broken feature and I wonder if there is an 
actual user.


@Marcel, can you clarify if there is an actual use case for shared 
anonymous memory in QEMU? I.e., if the original use case that required 
that change is valid? (and why it wasn't able to just use proper shmem)


Shared anonymous memory is weird.

--
Thanks,

David / dhildenb




[PULL 40/42] esp: add trivial implementation of the ESP_RFLAGS register

2021-03-07 Thread Mark Cave-Ayland
The bottom 5 bits contain the number of bytes remaining in the FIFO which is
trivial to implement with Fifo8 (the remaining bits are unimplemented and left
as 0 for now).

Signed-off-by: Mark Cave-Ayland 
Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Laurent Vivier 
Message-Id: <20210304221103.6369-41-mark.cave-ayl...@ilande.co.uk>
---
 hw/scsi/esp.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c
index 34dc58da58..8a9b1500de 100644
--- a/hw/scsi/esp.c
+++ b/hw/scsi/esp.c
@@ -818,6 +818,10 @@ uint64_t esp_reg_read(ESPState *s, uint32_t saddr)
 val = s->rregs[saddr];
 }
 break;
+ case ESP_RFLAGS:
+/* Bottom 5 bits indicate number of bytes in FIFO */
+val = fifo8_num_used(>fifo);
+break;
 default:
 val = s->rregs[saddr];
 break;
-- 
2.20.1




[PULL 42/42] esp: add support for unaligned accesses

2021-03-07 Thread Mark Cave-Ayland
When the MacOS toolbox ROM transfers data from a target device to an unaligned
memory address, the first/last byte of a 16-bit transfer needs to be handled
separately. This means that the first byte is preloaded into the FIFO before
the transfer, or the last byte remains in the FIFO after the transfer.

The result of this is that the PDMA routines must be updated so that the FIFO
is loaded/unloaded if the last 16-bit word is used (rather than the last byte)
and any remaining byte from a FIFO wraparound is handled correctly.

Signed-off-by: Mark Cave-Ayland 
Reviewed-by: Laurent Vivier 
Message-Id: <20210304221103.6369-43-mark.cave-ayl...@ilande.co.uk>
---
 hw/scsi/esp.c | 48 +---
 1 file changed, 41 insertions(+), 7 deletions(-)

diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c
index f828e70865..507ab363bc 100644
--- a/hw/scsi/esp.c
+++ b/hw/scsi/esp.c
@@ -498,11 +498,22 @@ static void do_dma_pdma_cb(ESPState *s)
 
 if (to_device) {
 /* Copy FIFO data to device */
-len = MIN(fifo8_num_used(>fifo), ESP_FIFO_SZ);
+len = MIN(s->async_len, ESP_FIFO_SZ);
+len = MIN(len, fifo8_num_used(>fifo));
 memcpy(s->async_buf, fifo8_pop_buf(>fifo, len, ), len);
-s->async_buf += len;
-s->async_len -= len;
-s->ti_size += len;
+s->async_buf += n;
+s->async_len -= n;
+s->ti_size += n;
+
+if (n < len) {
+/* Unaligned accesses can cause FIFO wraparound */
+len = len - n;
+memcpy(s->async_buf, fifo8_pop_buf(>fifo, len, ), len);
+s->async_buf += n;
+s->async_len -= n;
+s->ti_size += n;
+}
+
 if (s->async_len == 0) {
 scsi_req_continue(s->current_req);
 return;
@@ -526,12 +537,18 @@ static void do_dma_pdma_cb(ESPState *s)
 
 if (esp_get_tc(s) != 0) {
 /* Copy device data to FIFO */
-len = MIN(s->async_len, fifo8_num_free(>fifo));
+len = MIN(s->async_len, esp_get_tc(s));
+len = MIN(len, fifo8_num_free(>fifo));
 fifo8_push_all(>fifo, s->async_buf, len);
 s->async_buf += len;
 s->async_len -= len;
 s->ti_size -= len;
 esp_set_tc(s, esp_get_tc(s) - len);
+
+if (esp_get_tc(s) == 0) {
+/* Indicate transfer to FIFO is complete */
+ s->rregs[ESP_RSTAT] |= STAT_TC;
+}
 return;
 }
 
@@ -606,12 +623,29 @@ static void esp_do_dma(ESPState *s)
 if (s->dma_memory_write) {
 s->dma_memory_write(s->dma_opaque, s->async_buf, len);
 } else {
+/* Adjust TC for any leftover data in the FIFO */
+if (!fifo8_is_empty(>fifo)) {
+esp_set_tc(s, esp_get_tc(s) - fifo8_num_used(>fifo));
+}
+
 /* Copy device data to FIFO */
 len = MIN(len, fifo8_num_free(>fifo));
 fifo8_push_all(>fifo, s->async_buf, len);
 s->async_buf += len;
 s->async_len -= len;
 s->ti_size -= len;
+
+/*
+ * MacOS toolbox uses a TI length of 16 bytes for all commands, so
+ * commands shorter than this must be padded accordingly
+ */
+if (len < esp_get_tc(s) && esp_get_tc(s) <= ESP_FIFO_SZ) {
+while (fifo8_num_used(>fifo) < ESP_FIFO_SZ) {
+esp_fifo_push(s, 0);
+len++;
+}
+}
+
 esp_set_tc(s, esp_get_tc(s) - len);
 s->pdma_cb = do_dma_pdma_cb;
 esp_raise_drq(s);
@@ -1160,7 +1194,7 @@ static void sysbus_esp_pdma_write(void *opaque, hwaddr 
addr,
 break;
 }
 dmalen = esp_get_tc(s);
-if (dmalen == 0 || fifo8_is_full(>fifo)) {
+if (dmalen == 0 || fifo8_num_free(>fifo) < 2) {
 s->pdma_cb(s);
 }
 }
@@ -1183,7 +1217,7 @@ static uint64_t sysbus_esp_pdma_read(void *opaque, hwaddr 
addr,
 val = (val << 8) | esp_pdma_read(s);
 break;
 }
-if (fifo8_is_empty(>fifo)) {
+if (fifo8_num_used(>fifo) < 2) {
 s->pdma_cb(s);
 }
 return val;
-- 
2.20.1




[PULL 31/42] esp: implement FIFO flush command

2021-03-07 Thread Mark Cave-Ayland
At this point it is now possible to properly implement the FIFO flush command
without causing guest errors.

Signed-off-by: Mark Cave-Ayland 
Reviewed-by: Laurent Vivier 
Message-Id: <20210304221103.6369-32-mark.cave-ayl...@ilande.co.uk>
---
 hw/scsi/esp.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c
index 2dded90be6..6aae6f91c2 100644
--- a/hw/scsi/esp.c
+++ b/hw/scsi/esp.c
@@ -769,6 +769,8 @@ void esp_reg_write(ESPState *s, uint32_t saddr, uint64_t 
val)
 case CMD_FLUSH:
 trace_esp_mem_writeb_cmd_flush(val);
 /*s->ti_size = 0;*/
+s->ti_wptr = 0;
+s->ti_rptr = 0;
 s->rregs[ESP_RINTR] = INTR_FC;
 s->rregs[ESP_RSEQ] = 0;
 s->rregs[ESP_RFLAGS] = 0;
-- 
2.20.1




[PULL 39/42] esp: convert cmdbuf from array to Fifo8

2021-03-07 Thread Mark Cave-Ayland
Rename ESP_CMDBUF_SZ to ESP_CMDFIFO_SZ and cmdbuf_cdb_offset to 
cmdfifo_cdb_offset
to indicate that the command buffer type has changed from an array to a Fifo8.

This also enables us to remove the ESPState field cmdlen since the command 
length
is now simply the number of elements used in cmdfifo.

Signed-off-by: Mark Cave-Ayland 
Reviewed-by: Laurent Vivier 
Message-Id: <20210304221103.6369-40-mark.cave-ayl...@ilande.co.uk>
---
 hw/scsi/esp.c | 151 +++---
 include/hw/scsi/esp.h |   9 +--
 2 files changed, 101 insertions(+), 59 deletions(-)

diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c
index 44e70aa789..34dc58da58 100644
--- a/hw/scsi/esp.c
+++ b/hw/scsi/esp.c
@@ -117,6 +117,25 @@ static uint8_t esp_fifo_pop(ESPState *s)
 return fifo8_pop(>fifo);
 }
 
+static void esp_cmdfifo_push(ESPState *s, uint8_t val)
+{
+if (fifo8_num_used(>cmdfifo) == ESP_CMDFIFO_SZ) {
+trace_esp_error_fifo_overrun();
+return;
+}
+
+fifo8_push(>cmdfifo, val);
+}
+
+static uint8_t esp_cmdfifo_pop(ESPState *s)
+{
+if (fifo8_is_empty(>cmdfifo)) {
+return 0;
+}
+
+return fifo8_pop(>cmdfifo);
+}
+
 static uint32_t esp_get_tc(ESPState *s)
 {
 uint32_t dmalen;
@@ -151,7 +170,7 @@ static uint8_t esp_pdma_read(ESPState *s)
 uint8_t val;
 
 if (s->do_cmd) {
-val = s->cmdbuf[s->cmdlen++];
+val = esp_cmdfifo_pop(s);
 } else {
 val = esp_fifo_pop(s);
 }
@@ -168,7 +187,7 @@ static void esp_pdma_write(ESPState *s, uint8_t val)
 }
 
 if (s->do_cmd) {
-s->cmdbuf[s->cmdlen++] = val;
+esp_cmdfifo_push(s, val);
 } else {
 esp_fifo_push(s, val);
 }
@@ -214,7 +233,7 @@ static int esp_select(ESPState *s)
 
 static uint32_t get_cmd(ESPState *s, uint32_t maxlen)
 {
-uint8_t *buf = s->cmdbuf;
+uint8_t buf[ESP_CMDFIFO_SZ];
 uint32_t dmalen, n;
 int target;
 
@@ -226,15 +245,18 @@ static uint32_t get_cmd(ESPState *s, uint32_t maxlen)
 }
 if (s->dma_memory_read) {
 s->dma_memory_read(s->dma_opaque, buf, dmalen);
+fifo8_push_all(>cmdfifo, buf, dmalen);
 } else {
 if (esp_select(s) < 0) {
+fifo8_reset(>cmdfifo);
 return -1;
 }
 esp_raise_drq(s);
+fifo8_reset(>cmdfifo);
 return 0;
 }
 } else {
-dmalen = MIN(s->ti_size, maxlen);
+dmalen = MIN(fifo8_num_used(>fifo), maxlen);
 if (dmalen == 0) {
 return 0;
 }
@@ -242,27 +264,35 @@ static uint32_t get_cmd(ESPState *s, uint32_t maxlen)
 if (dmalen >= 3) {
 buf[0] = buf[2] >> 5;
 }
+fifo8_push_all(>cmdfifo, buf, dmalen);
 }
 trace_esp_get_cmd(dmalen, target);
 
 if (esp_select(s) < 0) {
+fifo8_reset(>cmdfifo);
 return -1;
 }
 return dmalen;
 }
 
-static void do_busid_cmd(ESPState *s, uint8_t *buf, uint8_t busid)
+static void do_busid_cmd(ESPState *s, uint8_t busid)
 {
+uint32_t n, cmdlen;
 int32_t datalen;
 int lun;
 SCSIDevice *current_lun;
+uint8_t *buf;
 
 trace_esp_do_busid_cmd(busid);
 lun = busid & 7;
+cmdlen = fifo8_num_used(>cmdfifo);
+buf = (uint8_t *)fifo8_pop_buf(>cmdfifo, cmdlen, );
+
 current_lun = scsi_device_find(>bus, 0, s->current_dev->id, lun);
 s->current_req = scsi_req_new(current_lun, 0, lun, buf, s);
 datalen = scsi_req_enqueue(s->current_req);
 s->ti_size = datalen;
+fifo8_reset(>cmdfifo);
 if (datalen != 0) {
 s->rregs[ESP_RSTAT] = STAT_TC;
 s->rregs[ESP_RSEQ] = SEQ_CD;
@@ -287,18 +317,25 @@ static void do_busid_cmd(ESPState *s, uint8_t *buf, 
uint8_t busid)
 
 static void do_cmd(ESPState *s)
 {
-uint8_t *buf = s->cmdbuf;
-uint8_t busid = buf[0];
+uint8_t busid = fifo8_pop(>cmdfifo);
+uint32_t n;
+
+s->cmdfifo_cdb_offset--;
 
 /* Ignore extended messages for now */
-do_busid_cmd(s, [s->cmdbuf_cdb_offset], busid);
+if (s->cmdfifo_cdb_offset) {
+fifo8_pop_buf(>cmdfifo, s->cmdfifo_cdb_offset, );
+s->cmdfifo_cdb_offset = 0;
+}
+
+do_busid_cmd(s, busid);
 }
 
 static void satn_pdma_cb(ESPState *s)
 {
 s->do_cmd = 0;
-if (s->cmdlen) {
-s->cmdbuf_cdb_offset = 1;
+if (!fifo8_is_empty(>cmdfifo)) {
+s->cmdfifo_cdb_offset = 1;
 do_cmd(s);
 }
 }
@@ -312,13 +349,11 @@ static void handle_satn(ESPState *s)
 return;
 }
 s->pdma_cb = satn_pdma_cb;
-cmdlen = get_cmd(s, ESP_CMDBUF_SZ);
+cmdlen = get_cmd(s, ESP_CMDFIFO_SZ);
 if (cmdlen > 0) {
-s->cmdlen = cmdlen;
-s->cmdbuf_cdb_offset = 1;
+s->cmdfifo_cdb_offset = 1;
 do_cmd(s);
 } else if (cmdlen == 0) {
-s->cmdlen = 0;
 s->do_cmd = 1;
 /* Target present, but no cmd yet - switch to command phase */
 s->rregs[ESP_RSEQ] = SEQ_CD;
@@ -328,10 +363,13 

[PULL 30/42] esp: add 4 byte PDMA read and write transfers

2021-03-07 Thread Mark Cave-Ayland
The MacOS toolbox ROM performs 4 byte reads/writes when transferring data to
and from the target. Since the SCSI bus is 16-bits wide, use the memory API
to split a 4 byte access into 2 x 2 byte accesses.

Signed-off-by: Mark Cave-Ayland 
Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Laurent Vivier 
Message-Id: <20210304221103.6369-31-mark.cave-ayl...@ilande.co.uk>
---
 hw/scsi/esp.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c
index 79b84e31d3..2dded90be6 100644
--- a/hw/scsi/esp.c
+++ b/hw/scsi/esp.c
@@ -1002,7 +1002,9 @@ static const MemoryRegionOps sysbus_esp_pdma_ops = {
 .write = sysbus_esp_pdma_write,
 .endianness = DEVICE_NATIVE_ENDIAN,
 .valid.min_access_size = 1,
-.valid.max_access_size = 2,
+.valid.max_access_size = 4,
+.impl.min_access_size = 1,
+.impl.max_access_size = 2,
 };
 
 static const struct SCSIBusInfo esp_scsi_info = {
@@ -1049,7 +1051,7 @@ static void sysbus_esp_realize(DeviceState *dev, Error 
**errp)
   sysbus, "esp-regs", ESP_REGS << sysbus->it_shift);
 sysbus_init_mmio(sbd, >iomem);
 memory_region_init_io(>pdma, OBJECT(sysbus), _esp_pdma_ops,
-  sysbus, "esp-pdma", 2);
+  sysbus, "esp-pdma", 4);
 sysbus_init_mmio(sbd, >pdma);
 
 qdev_init_gpio_in(dev, sysbus_esp_gpio_demux, 2);
-- 
2.20.1




[PULL 35/42] esp: raise interrupt after every non-DMA byte transferred to the FIFO

2021-03-07 Thread Mark Cave-Ayland
This matches the description in the datasheet and is required as support for
non-DMA transfers is added.

Signed-off-by: Mark Cave-Ayland 
Reviewed-by: Laurent Vivier 
Message-Id: <20210304221103.6369-36-mark.cave-ayl...@ilande.co.uk>
---
 hw/scsi/esp.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c
index eb6681ca66..4ac299651f 100644
--- a/hw/scsi/esp.c
+++ b/hw/scsi/esp.c
@@ -760,6 +760,12 @@ void esp_reg_write(ESPState *s, uint32_t saddr, uint64_t 
val)
 s->ti_size++;
 s->ti_buf[s->ti_wptr++] = val & 0xff;
 }
+
+/* Non-DMA transfers raise an interrupt after every byte */
+if (s->rregs[ESP_CMD] == CMD_TI) {
+s->rregs[ESP_RINTR] |= INTR_FC | INTR_BS;
+esp_raise_irq(s);
+}
 break;
 case ESP_CMD:
 s->rregs[saddr] = val;
-- 
2.20.1




[PULL 38/42] esp: convert ti_buf from array to Fifo8

2021-03-07 Thread Mark Cave-Ayland
Rename TI_BUFSZ to ESP_FIFO_SZ since this constant is really describing the size
of the FIFO and is not directly related to the TI size.

Signed-off-by: Mark Cave-Ayland 
Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Laurent Vivier 
Message-Id: <20210304221103.6369-39-mark.cave-ayl...@ilande.co.uk>
---
 hw/scsi/esp.c | 118 ++
 include/hw/scsi/esp.h |   8 +--
 2 files changed, 79 insertions(+), 47 deletions(-)

diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c
index 0d5c07e4c1..44e70aa789 100644
--- a/hw/scsi/esp.c
+++ b/hw/scsi/esp.c
@@ -98,6 +98,25 @@ void esp_request_cancelled(SCSIRequest *req)
 }
 }
 
+static void esp_fifo_push(ESPState *s, uint8_t val)
+{
+if (fifo8_num_used(>fifo) == ESP_FIFO_SZ) {
+trace_esp_error_fifo_overrun();
+return;
+}
+
+fifo8_push(>fifo, val);
+}
+
+static uint8_t esp_fifo_pop(ESPState *s)
+{
+if (fifo8_is_empty(>fifo)) {
+return 0;
+}
+
+return fifo8_pop(>fifo);
+}
+
 static uint32_t esp_get_tc(ESPState *s)
 {
 uint32_t dmalen;
@@ -134,7 +153,7 @@ static uint8_t esp_pdma_read(ESPState *s)
 if (s->do_cmd) {
 val = s->cmdbuf[s->cmdlen++];
 } else {
-val = s->ti_buf[s->ti_rptr++];
+val = esp_fifo_pop(s);
 }
 
 return val;
@@ -151,7 +170,7 @@ static void esp_pdma_write(ESPState *s, uint8_t val)
 if (s->do_cmd) {
 s->cmdbuf[s->cmdlen++] = val;
 } else {
-s->ti_buf[s->ti_wptr++] = val;
+esp_fifo_push(s, val);
 }
 
 dmalen--;
@@ -165,8 +184,7 @@ static int esp_select(ESPState *s)
 target = s->wregs[ESP_WBUSID] & BUSID_DID;
 
 s->ti_size = 0;
-s->ti_rptr = 0;
-s->ti_wptr = 0;
+fifo8_reset(>fifo);
 
 if (s->current_req) {
 /* Started a new command before the old one finished.  Cancel it.  */
@@ -197,7 +215,7 @@ static int esp_select(ESPState *s)
 static uint32_t get_cmd(ESPState *s, uint32_t maxlen)
 {
 uint8_t *buf = s->cmdbuf;
-uint32_t dmalen;
+uint32_t dmalen, n;
 int target;
 
 target = s->wregs[ESP_WBUSID] & BUSID_DID;
@@ -220,7 +238,7 @@ static uint32_t get_cmd(ESPState *s, uint32_t maxlen)
 if (dmalen == 0) {
 return 0;
 }
-memcpy(buf, s->ti_buf, dmalen);
+memcpy(buf, fifo8_pop_buf(>fifo, dmalen, ), dmalen);
 if (dmalen >= 3) {
 buf[0] = buf[2] >> 5;
 }
@@ -392,12 +410,18 @@ static void write_response_pdma_cb(ESPState *s)
 
 static void write_response(ESPState *s)
 {
+uint32_t n;
+
 trace_esp_write_response(s->status);
-s->ti_buf[0] = s->status;
-s->ti_buf[1] = 0;
+
+fifo8_reset(>fifo);
+esp_fifo_push(s, s->status);
+esp_fifo_push(s, 0);
+
 if (s->dma) {
 if (s->dma_memory_write) {
-s->dma_memory_write(s->dma_opaque, s->ti_buf, 2);
+s->dma_memory_write(s->dma_opaque,
+(uint8_t *)fifo8_pop_buf(>fifo, 2, ), 2);
 s->rregs[ESP_RSTAT] = STAT_TC | STAT_ST;
 s->rregs[ESP_RINTR] |= INTR_BS | INTR_FC;
 s->rregs[ESP_RSEQ] = SEQ_CD;
@@ -408,8 +432,6 @@ static void write_response(ESPState *s)
 }
 } else {
 s->ti_size = 2;
-s->ti_rptr = 0;
-s->ti_wptr = 2;
 s->rregs[ESP_RFLAGS] = 2;
 }
 esp_raise_irq(s);
@@ -429,6 +451,7 @@ static void do_dma_pdma_cb(ESPState *s)
 {
 int to_device = ((s->rregs[ESP_RSTAT] & 7) == STAT_DO);
 int len;
+uint32_t n;
 
 if (s->do_cmd) {
 s->ti_size = 0;
@@ -441,10 +464,8 @@ static void do_dma_pdma_cb(ESPState *s)
 
 if (to_device) {
 /* Copy FIFO data to device */
-len = MIN(s->ti_wptr, TI_BUFSZ);
-memcpy(s->async_buf, s->ti_buf, len);
-s->ti_wptr = 0;
-s->ti_rptr = 0;
+len = MIN(fifo8_num_used(>fifo), ESP_FIFO_SZ);
+memcpy(s->async_buf, fifo8_pop_buf(>fifo, len, ), len);
 s->async_buf += len;
 s->async_len -= len;
 s->ti_size += len;
@@ -471,11 +492,8 @@ static void do_dma_pdma_cb(ESPState *s)
 
 if (esp_get_tc(s) != 0) {
 /* Copy device data to FIFO */
-s->ti_wptr = 0;
-s->ti_rptr = 0;
-len = MIN(s->async_len, TI_BUFSZ);
-memcpy(s->ti_buf, s->async_buf, len);
-s->ti_wptr += len;
+len = MIN(s->async_len, fifo8_num_free(>fifo));
+fifo8_push_all(>fifo, s->async_buf, len);
 s->async_buf += len;
 s->async_len -= len;
 s->ti_size -= len;
@@ -555,9 +573,8 @@ static void esp_do_dma(ESPState *s)
 s->dma_memory_write(s->dma_opaque, s->async_buf, len);
 } else {
 /* Copy device data to FIFO */
-len = MIN(len, TI_BUFSZ - s->ti_wptr);
-memcpy(>ti_buf[s->ti_wptr], s->async_buf, len);
-s->ti_wptr += len;
+len = MIN(len, fifo8_num_free(>fifo));
+

[PULL 27/42] esp: fix PDMA target selection

2021-03-07 Thread Mark Cave-Ayland
Currently the target selection for PDMA is done after the SCSI command has been
delivered which is not correct. Perform target selection as part of the initial
get_cmd() call when the command is submitted: if no target is present, don't
raise DRQ.

If the target is present then switch to the command phase since the MacOS 
toolbox
ROM checks for this before attempting to submit the SCSI command.

Signed-off-by: Mark Cave-Ayland 
Reviewed-by: Laurent Vivier 
Message-Id: <20210304221103.6369-28-mark.cave-ayl...@ilande.co.uk>
---
 hw/scsi/esp.c | 53 +--
 1 file changed, 34 insertions(+), 19 deletions(-)

diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c
index d8d7ede00a..10e63d1f62 100644
--- a/hw/scsi/esp.c
+++ b/hw/scsi/esp.c
@@ -243,6 +243,9 @@ static uint32_t get_cmd(ESPState *s)
 s->dma_memory_read(s->dma_opaque, buf, dmalen);
 } else {
 set_pdma(s, TI);
+if (esp_select(s) < 0) {
+return -1;
+}
 esp_raise_drq(s);
 return 0;
 }
@@ -257,7 +260,7 @@ static uint32_t get_cmd(ESPState *s)
 trace_esp_get_cmd(dmalen, target);
 
 if (esp_select(s) < 0) {
-return 0;
+return -1;
 }
 return dmalen;
 }
@@ -299,9 +302,6 @@ static void do_cmd(ESPState *s)
 
 static void satn_pdma_cb(ESPState *s)
 {
-if (esp_select(s) < 0) {
-return;
-}
 s->do_cmd = 0;
 if (s->cmdlen) {
 do_cmd(s);
@@ -310,24 +310,28 @@ static void satn_pdma_cb(ESPState *s)
 
 static void handle_satn(ESPState *s)
 {
+int32_t cmdlen;
+
 if (s->dma && !s->dma_enabled) {
 s->dma_cb = handle_satn;
 return;
 }
 s->pdma_cb = satn_pdma_cb;
-s->cmdlen = get_cmd(s);
-if (s->cmdlen) {
+cmdlen = get_cmd(s);
+if (cmdlen > 0) {
+s->cmdlen = cmdlen;
 do_cmd(s);
-} else {
+} else if (cmdlen == 0) {
+s->cmdlen = 0;
 s->do_cmd = 1;
+/* Target present, but no cmd yet - switch to command phase */
+s->rregs[ESP_RSEQ] = SEQ_CD;
+s->rregs[ESP_RSTAT] = STAT_CD;
 }
 }
 
 static void s_without_satn_pdma_cb(ESPState *s)
 {
-if (esp_select(s) < 0) {
-return;
-}
 s->do_cmd = 0;
 if (s->cmdlen) {
 do_busid_cmd(s, s->cmdbuf, 0);
@@ -336,24 +340,28 @@ static void s_without_satn_pdma_cb(ESPState *s)
 
 static void handle_s_without_atn(ESPState *s)
 {
+int32_t cmdlen;
+
 if (s->dma && !s->dma_enabled) {
 s->dma_cb = handle_s_without_atn;
 return;
 }
 s->pdma_cb = s_without_satn_pdma_cb;
-s->cmdlen = get_cmd(s);
-if (s->cmdlen) {
+cmdlen = get_cmd(s);
+if (cmdlen > 0) {
+s->cmdlen = cmdlen;
 do_busid_cmd(s, s->cmdbuf, 0);
-} else {
+} else if (cmdlen == 0) {
+s->cmdlen = 0;
 s->do_cmd = 1;
+/* Target present, but no cmd yet - switch to command phase */
+s->rregs[ESP_RSEQ] = SEQ_CD;
+s->rregs[ESP_RSTAT] = STAT_CD;
 }
 }
 
 static void satn_stop_pdma_cb(ESPState *s)
 {
-if (esp_select(s) < 0) {
-return;
-}
 s->do_cmd = 0;
 if (s->cmdlen) {
 trace_esp_handle_satn_stop(s->cmdlen);
@@ -367,21 +375,28 @@ static void satn_stop_pdma_cb(ESPState *s)
 
 static void handle_satn_stop(ESPState *s)
 {
+int32_t cmdlen;
+
 if (s->dma && !s->dma_enabled) {
 s->dma_cb = handle_satn_stop;
 return;
 }
 s->pdma_cb = satn_stop_pdma_cb;
-s->cmdlen = get_cmd(s);
-if (s->cmdlen) {
+cmdlen = get_cmd(s);
+if (cmdlen > 0) {
 trace_esp_handle_satn_stop(s->cmdlen);
+s->cmdlen = cmdlen;
 s->do_cmd = 1;
 s->rregs[ESP_RSTAT] = STAT_TC | STAT_CD;
 s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
 s->rregs[ESP_RSEQ] = SEQ_CD;
 esp_raise_irq(s);
-} else {
+} else if (cmdlen == 0) {
+s->cmdlen = 0;
 s->do_cmd = 1;
+/* Target present, but no cmd yet - switch to command phase */
+s->rregs[ESP_RSEQ] = SEQ_CD;
+s->rregs[ESP_RSTAT] = STAT_CD;
 }
 }
 
-- 
2.20.1




[PULL 25/42] esp: remove CMD pdma_origin

2021-03-07 Thread Mark Cave-Ayland
The cmdbuf is really just a copy of FIFO data (including extra message phase
bytes) so its pdma_origin is effectively TI. Fortunately we already know when
we are receiving a SCSI command since do_cmd == 1 which enables us to
distinguish between the two cases in esp_pdma_read()/esp_pdma_write().

Signed-off-by: Mark Cave-Ayland 
Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Laurent Vivier 
Message-Id: <20210304221103.6369-26-mark.cave-ayl...@ilande.co.uk>
---
 hw/scsi/esp.c | 22 --
 include/hw/scsi/esp.h |  1 -
 2 files changed, 12 insertions(+), 11 deletions(-)

diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c
index c80dc606e8..d5c03f9697 100644
--- a/hw/scsi/esp.c
+++ b/hw/scsi/esp.c
@@ -143,10 +143,11 @@ static uint8_t esp_pdma_read(ESPState *s)
 
 switch (s->pdma_origin) {
 case TI:
-val = s->ti_buf[s->ti_rptr++];
-break;
-case CMD:
-val = s->cmdbuf[s->cmdlen++];
+if (s->do_cmd) {
+val = s->cmdbuf[s->cmdlen++];
+} else {
+val = s->ti_buf[s->ti_rptr++];
+}
 break;
 case ASYNC:
 val = s->async_buf[0];
@@ -176,10 +177,11 @@ static void esp_pdma_write(ESPState *s, uint8_t val)
 
 switch (s->pdma_origin) {
 case TI:
-s->ti_buf[s->ti_wptr++] = val;
-break;
-case CMD:
-s->cmdbuf[s->cmdlen++] = val;
+if (s->do_cmd) {
+s->cmdbuf[s->cmdlen++] = val;
+} else {
+s->ti_buf[s->ti_wptr++] = val;
+}
 break;
 case ASYNC:
 s->async_buf[0] = val;
@@ -240,7 +242,7 @@ static uint32_t get_cmd(ESPState *s)
 if (s->dma_memory_read) {
 s->dma_memory_read(s->dma_opaque, buf, dmalen);
 } else {
-set_pdma(s, CMD);
+set_pdma(s, TI);
 esp_raise_drq(s);
 return 0;
 }
@@ -471,7 +473,7 @@ static void esp_do_dma(ESPState *s)
 if (s->dma_memory_read) {
 s->dma_memory_read(s->dma_opaque, >cmdbuf[s->cmdlen], len);
 } else {
-set_pdma(s, CMD);
+set_pdma(s, TI);
 s->pdma_cb = do_dma_pdma_cb;
 esp_raise_drq(s);
 return;
diff --git a/include/hw/scsi/esp.h b/include/hw/scsi/esp.h
index 1be4586aff..d3fc52 100644
--- a/include/hw/scsi/esp.h
+++ b/include/hw/scsi/esp.h
@@ -17,7 +17,6 @@ typedef struct ESPState ESPState;
 
 enum pdma_origin_id {
 TI,
-CMD,
 ASYNC,
 };
 
-- 
2.20.1




[PULL 41/42] esp: implement non-DMA transfers in PDMA mode

2021-03-07 Thread Mark Cave-Ayland
The MacOS toolbox ROM uses non-DMA TI commands to handle the first/last byte
of an unaligned 16-bit transfer to memory.

Signed-off-by: Mark Cave-Ayland 
Reviewed-by: Laurent Vivier 
Message-Id: <20210304221103.6369-42-mark.cave-ayl...@ilande.co.uk>
---
 hw/scsi/esp.c | 133 ++
 include/hw/scsi/esp.h |   1 +
 2 files changed, 98 insertions(+), 36 deletions(-)

diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c
index 8a9b1500de..f828e70865 100644
--- a/hw/scsi/esp.c
+++ b/hw/scsi/esp.c
@@ -296,6 +296,7 @@ static void do_busid_cmd(ESPState *s, uint8_t busid)
 if (datalen != 0) {
 s->rregs[ESP_RSTAT] = STAT_TC;
 s->rregs[ESP_RSEQ] = SEQ_CD;
+s->ti_cmd = 0;
 esp_set_tc(s, 0);
 if (datalen > 0) {
 /*
@@ -645,6 +646,71 @@ static void esp_do_dma(ESPState *s)
 esp_lower_drq(s);
 }
 
+static void esp_do_nodma(ESPState *s)
+{
+int to_device = ((s->rregs[ESP_RSTAT] & 7) == STAT_DO);
+uint32_t cmdlen, n;
+int len;
+
+if (s->do_cmd) {
+cmdlen = fifo8_num_used(>cmdfifo);
+trace_esp_handle_ti_cmd(cmdlen);
+s->ti_size = 0;
+if ((s->rregs[ESP_RSTAT] & 7) == STAT_CD) {
+/* No command received */
+if (s->cmdfifo_cdb_offset == fifo8_num_used(>cmdfifo)) {
+return;
+}
+
+/* Command has been received */
+s->do_cmd = 0;
+do_cmd(s);
+} else {
+/*
+ * Extra message out bytes received: update cmdfifo_cdb_offset
+ * and then switch to commmand phase
+ */
+s->cmdfifo_cdb_offset = fifo8_num_used(>cmdfifo);
+s->rregs[ESP_RSTAT] = STAT_TC | STAT_CD;
+s->rregs[ESP_RSEQ] = SEQ_CD;
+s->rregs[ESP_RINTR] |= INTR_BS;
+esp_raise_irq(s);
+}
+return;
+}
+
+if (s->async_len == 0) {
+/* Defer until data is available.  */
+return;
+}
+
+if (to_device) {
+len = MIN(fifo8_num_used(>fifo), ESP_FIFO_SZ);
+memcpy(s->async_buf, fifo8_pop_buf(>fifo, len, ), len);
+s->async_buf += len;
+s->async_len -= len;
+s->ti_size += len;
+} else {
+len = MIN(s->ti_size, s->async_len);
+len = MIN(len, fifo8_num_free(>fifo));
+fifo8_push_all(>fifo, s->async_buf, len);
+s->async_buf += len;
+s->async_len -= len;
+s->ti_size -= len;
+}
+
+if (s->async_len == 0) {
+scsi_req_continue(s->current_req);
+
+if (to_device || s->ti_size == 0) {
+return;
+}
+}
+
+s->rregs[ESP_RINTR] |= INTR_BS;
+esp_raise_irq(s);
+}
+
 void esp_command_complete(SCSIRequest *req, size_t resid)
 {
 ESPState *s = req->hba_private;
@@ -701,56 +767,51 @@ void esp_transfer_data(SCSIRequest *req, uint32_t len)
 return;
 }
 
-if (dmalen) {
-esp_do_dma(s);
-} else if (s->ti_size <= 0) {
+if (s->ti_cmd == 0) {
 /*
- * If this was the last part of a DMA transfer then the
- * completion interrupt is deferred to here.
+ * Always perform the initial transfer upon reception of the next TI
+ * command to ensure the DMA/non-DMA status of the command is correct.
+ * It is not possible to use s->dma directly in the section below as
+ * some OSs send non-DMA NOP commands after a DMA transfer. Hence if 
the
+ * async data transfer is delayed then s->dma is set incorrectly.
  */
-esp_dma_done(s);
-esp_lower_drq(s);
+return;
+}
+
+if (s->ti_cmd & CMD_DMA) {
+if (dmalen) {
+esp_do_dma(s);
+} else if (s->ti_size <= 0) {
+/*
+ * If this was the last part of a DMA transfer then the
+ * completion interrupt is deferred to here.
+ */
+esp_dma_done(s);
+esp_lower_drq(s);
+}
+} else {
+esp_do_nodma(s);
 }
 }
 
 static void handle_ti(ESPState *s)
 {
-uint32_t dmalen, cmdlen;
+uint32_t dmalen;
 
 if (s->dma && !s->dma_enabled) {
 s->dma_cb = handle_ti;
 return;
 }
 
-dmalen = esp_get_tc(s);
+s->ti_cmd = s->rregs[ESP_CMD];
 if (s->dma) {
+dmalen = esp_get_tc(s);
 trace_esp_handle_ti(dmalen);
 s->rregs[ESP_RSTAT] &= ~STAT_TC;
 esp_do_dma(s);
-} else if (s->do_cmd) {
-cmdlen = fifo8_num_used(>cmdfifo);
-trace_esp_handle_ti_cmd(cmdlen);
-s->ti_size = 0;
-if ((s->rregs[ESP_RSTAT] & 7) == STAT_CD) {
-/* No command received */
-if (s->cmdfifo_cdb_offset == fifo8_num_used(>cmdfifo)) {
-return;
-}
-
-/* Command has been received */
-s->do_cmd = 0;
-do_cmd(s);
-} else {
-/*
- * Extra message out bytes received: 

[PULL 36/42] esp: add maxlen parameter to get_cmd()

2021-03-07 Thread Mark Cave-Ayland
Some guests use a mixture of DMA and non-DMA transfers in combination with the
SATN and stop command to transfer message out phase and command phase bytes to
the target. Prepare for the next commit by adding a maxlen parameter to
get_cmd() to allow partial transfers.

Signed-off-by: Mark Cave-Ayland 
Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Laurent Vivier 
Message-Id: <20210304221103.6369-37-mark.cave-ayl...@ilande.co.uk>
---
 hw/scsi/esp.c | 20 +++-
 1 file changed, 11 insertions(+), 9 deletions(-)

diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c
index 4ac299651f..23fcaa90c1 100644
--- a/hw/scsi/esp.c
+++ b/hw/scsi/esp.c
@@ -194,7 +194,7 @@ static int esp_select(ESPState *s)
 return 0;
 }
 
-static uint32_t get_cmd(ESPState *s)
+static uint32_t get_cmd(ESPState *s, uint32_t maxlen)
 {
 uint8_t *buf = s->cmdbuf;
 uint32_t dmalen;
@@ -202,8 +202,8 @@ static uint32_t get_cmd(ESPState *s)
 
 target = s->wregs[ESP_WBUSID] & BUSID_DID;
 if (s->dma) {
-dmalen = esp_get_tc(s);
-if (dmalen > ESP_CMDBUF_SZ) {
+dmalen = MIN(esp_get_tc(s), maxlen);
+if (dmalen == 0) {
 return 0;
 }
 if (s->dma_memory_read) {
@@ -216,12 +216,14 @@ static uint32_t get_cmd(ESPState *s)
 return 0;
 }
 } else {
-dmalen = s->ti_size;
-if (dmalen > TI_BUFSZ) {
+dmalen = MIN(s->ti_size, maxlen);
+if (dmalen == 0) {
 return 0;
 }
 memcpy(buf, s->ti_buf, dmalen);
-buf[0] = buf[2] >> 5;
+if (dmalen >= 3) {
+buf[0] = buf[2] >> 5;
+}
 }
 trace_esp_get_cmd(dmalen, target);
 
@@ -290,7 +292,7 @@ static void handle_satn(ESPState *s)
 return;
 }
 s->pdma_cb = satn_pdma_cb;
-cmdlen = get_cmd(s);
+cmdlen = get_cmd(s, ESP_CMDBUF_SZ);
 if (cmdlen > 0) {
 s->cmdlen = cmdlen;
 do_cmd(s);
@@ -320,7 +322,7 @@ static void handle_s_without_atn(ESPState *s)
 return;
 }
 s->pdma_cb = s_without_satn_pdma_cb;
-cmdlen = get_cmd(s);
+cmdlen = get_cmd(s, ESP_CMDBUF_SZ);
 if (cmdlen > 0) {
 s->cmdlen = cmdlen;
 do_busid_cmd(s, s->cmdbuf, 0);
@@ -355,7 +357,7 @@ static void handle_satn_stop(ESPState *s)
 return;
 }
 s->pdma_cb = satn_stop_pdma_cb;
-cmdlen = get_cmd(s);
+cmdlen = get_cmd(s, ESP_CMDBUF_SZ);
 if (cmdlen > 0) {
 trace_esp_handle_satn_stop(s->cmdlen);
 s->cmdlen = cmdlen;
-- 
2.20.1




[PULL 24/42] esp: use in-built TC to determine PDMA transfer length

2021-03-07 Thread Mark Cave-Ayland
Real hardware simply counts down using the in-built TC to determine when the
the PDMA request is complete. Use the TC to determine the PDMA transfer length
which then enables us to remove the redundant pdma_len variable.

Signed-off-by: Mark Cave-Ayland 
Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Laurent Vivier 
Message-Id: <20210304221103.6369-25-mark.cave-ayl...@ilande.co.uk>
---
 hw/scsi/esp.c | 28 +---
 include/hw/scsi/esp.h |  1 -
 2 files changed, 13 insertions(+), 16 deletions(-)

diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c
index 7bf2ec9c94..c80dc606e8 100644
--- a/hw/scsi/esp.c
+++ b/hw/scsi/esp.c
@@ -127,10 +127,9 @@ static uint32_t esp_get_stc(ESPState *s)
 return dmalen;
 }
 
-static void set_pdma(ESPState *s, enum pdma_origin_id origin, uint32_t len)
+static void set_pdma(ESPState *s, enum pdma_origin_id origin)
 {
 s->pdma_origin = origin;
-s->pdma_len = len;
 }
 
 static uint8_t esp_pdma_read(ESPState *s)
@@ -138,7 +137,7 @@ static uint8_t esp_pdma_read(ESPState *s)
 uint32_t dmalen = esp_get_tc(s);
 uint8_t val;
 
-if (dmalen == 0 || s->pdma_len == 0) {
+if (dmalen == 0) {
 return 0;
 }
 
@@ -161,7 +160,6 @@ static uint8_t esp_pdma_read(ESPState *s)
 }
 
 s->ti_size--;
-s->pdma_len--;
 dmalen--;
 esp_set_tc(s, dmalen);
 
@@ -172,7 +170,7 @@ static void esp_pdma_write(ESPState *s, uint8_t val)
 {
 uint32_t dmalen = esp_get_tc(s);
 
-if (dmalen == 0 || s->pdma_len == 0) {
+if (dmalen == 0) {
 return;
 }
 
@@ -195,7 +193,6 @@ static void esp_pdma_write(ESPState *s, uint8_t val)
 }
 
 s->ti_size++;
-s->pdma_len--;
 dmalen--;
 esp_set_tc(s, dmalen);
 }
@@ -243,7 +240,7 @@ static uint32_t get_cmd(ESPState *s)
 if (s->dma_memory_read) {
 s->dma_memory_read(s->dma_opaque, buf, dmalen);
 } else {
-set_pdma(s, CMD, dmalen);
+set_pdma(s, CMD);
 esp_raise_drq(s);
 return 0;
 }
@@ -406,7 +403,7 @@ static void write_response(ESPState *s)
 s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
 s->rregs[ESP_RSEQ] = SEQ_CD;
 } else {
-set_pdma(s, TI, 2);
+set_pdma(s, TI);
 s->pdma_cb = write_response_pdma_cb;
 esp_raise_drq(s);
 return;
@@ -474,7 +471,7 @@ static void esp_do_dma(ESPState *s)
 if (s->dma_memory_read) {
 s->dma_memory_read(s->dma_opaque, >cmdbuf[s->cmdlen], len);
 } else {
-set_pdma(s, CMD, len);
+set_pdma(s, CMD);
 s->pdma_cb = do_dma_pdma_cb;
 esp_raise_drq(s);
 return;
@@ -497,7 +494,7 @@ static void esp_do_dma(ESPState *s)
 if (s->dma_memory_read) {
 s->dma_memory_read(s->dma_opaque, s->async_buf, len);
 } else {
-set_pdma(s, ASYNC, len);
+set_pdma(s, ASYNC);
 s->pdma_cb = do_dma_pdma_cb;
 esp_raise_drq(s);
 return;
@@ -506,7 +503,7 @@ static void esp_do_dma(ESPState *s)
 if (s->dma_memory_write) {
 s->dma_memory_write(s->dma_opaque, s->async_buf, len);
 } else {
-set_pdma(s, ASYNC, len);
+set_pdma(s, ASYNC);
 s->pdma_cb = do_dma_pdma_cb;
 esp_raise_drq(s);
 return;
@@ -850,7 +847,6 @@ static const VMStateDescription vmstate_esp_pdma = {
 .needed = esp_pdma_needed,
 .fields = (VMStateField[]) {
 VMSTATE_INT32(pdma_origin, ESPState),
-VMSTATE_UINT32(pdma_len, ESPState),
 VMSTATE_END_OF_LIST()
 }
 };
@@ -949,6 +945,7 @@ static void sysbus_esp_pdma_write(void *opaque, hwaddr addr,
 {
 SysBusESPState *sysbus = opaque;
 ESPState *s = ESP(>esp);
+uint32_t dmalen;
 
 trace_esp_pdma_write(size);
 
@@ -961,7 +958,8 @@ static void sysbus_esp_pdma_write(void *opaque, hwaddr addr,
 esp_pdma_write(s, val);
 break;
 }
-if (s->pdma_len == 0 && s->pdma_cb) {
+dmalen = esp_get_tc(s);
+if (dmalen == 0 && s->pdma_cb) {
 esp_lower_drq(s);
 s->pdma_cb(s);
 s->pdma_cb = NULL;
@@ -978,7 +976,7 @@ static uint64_t sysbus_esp_pdma_read(void *opaque, hwaddr 
addr,
 
 trace_esp_pdma_read(size);
 
-if (dmalen == 0 || s->pdma_len == 0) {
+if (dmalen == 0) {
 return 0;
 }
 switch (size) {
@@ -991,7 +989,7 @@ static uint64_t sysbus_esp_pdma_read(void *opaque, hwaddr 
addr,
 break;
 }
 dmalen = esp_get_tc(s);
-if (dmalen == 0 || (s->pdma_len == 0 && s->pdma_cb)) {
+if (dmalen == 0 && s->pdma_cb) {
 esp_lower_drq(s);
 s->pdma_cb(s);
 s->pdma_cb = NULL;
diff --git a/include/hw/scsi/esp.h b/include/hw/scsi/esp.h
index 26bd015cf4..1be4586aff 100644
--- a/include/hw/scsi/esp.h
+++ b/include/hw/scsi/esp.h
@@ -57,7 +57,6 @@ struct ESPState {
 void *dma_opaque;
 void 

[PULL 22/42] esp: move PDMA length adjustments into esp_pdma_read()/esp_pdma_write()

2021-03-07 Thread Mark Cave-Ayland
Here the updates to async_len and ti_size are moved into the corresponding
esp_pdma_read()/esp_pdma_write() function to eliminate the reference to
pdma_cur in do_dma_pdma_cb().

Signed-off-by: Mark Cave-Ayland 
Reviewed-by: Laurent Vivier 
Message-Id: <20210304221103.6369-23-mark.cave-ayl...@ilande.co.uk>
---
 hw/scsi/esp.c | 24 ++--
 1 file changed, 14 insertions(+), 10 deletions(-)

diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c
index 38c05e97c3..bb3a9cd5e3 100644
--- a/hw/scsi/esp.c
+++ b/hw/scsi/esp.c
@@ -153,12 +153,18 @@ static uint8_t esp_pdma_read(ESPState *s)
 s->pdma_cur++;
 break;
 case ASYNC:
-val = s->async_buf[s->pdma_cur++];
+val = s->async_buf[0];
+if (s->async_len > 0) {
+s->async_len--;
+s->async_buf++;
+}
+s->pdma_cur++;
 break;
 default:
 g_assert_not_reached();
 }
 
+s->ti_size--;
 s->pdma_len--;
 dmalen--;
 esp_set_tc(s, dmalen);
@@ -183,12 +189,18 @@ static void esp_pdma_write(ESPState *s, uint8_t val)
 s->pdma_cur++;
 break;
 case ASYNC:
-s->async_buf[s->pdma_cur++] = val;
+s->async_buf[0] = val;
+if (s->async_len > 0) {
+s->async_len--;
+s->async_buf++;
+}
+s->pdma_cur++;
 break;
 default:
 g_assert_not_reached();
 }
 
+s->ti_size++;
 s->pdma_len--;
 dmalen--;
 esp_set_tc(s, dmalen);
@@ -427,7 +439,6 @@ static void esp_dma_done(ESPState *s)
 static void do_dma_pdma_cb(ESPState *s)
 {
 int to_device = ((s->rregs[ESP_RSTAT] & 7) == STAT_DO);
-int len = s->pdma_cur;
 
 if (s->do_cmd) {
 s->ti_size = 0;
@@ -436,13 +447,6 @@ static void do_dma_pdma_cb(ESPState *s)
 do_cmd(s);
 return;
 }
-s->async_buf += len;
-s->async_len -= len;
-if (to_device) {
-s->ti_size += len;
-} else {
-s->ti_size -= len;
-}
 if (s->async_len == 0) {
 scsi_req_continue(s->current_req);
 /*
-- 
2.20.1




[PULL 37/42] esp: transition to message out phase after SATN and stop command

2021-03-07 Thread Mark Cave-Ayland
The SCSI bus should remain in the message out phase after the SATN and stop
command rather than transitioning to the command phase. A new ESPState variable
cmdbuf_cdb_offset is added which stores the offset of the CDB from the start
of cmdbuf when accumulating extended message out phase data.

Currently any extended message out data is discarded in do_cmd() before the CDB
is processed in do_busid_cmd().

Signed-off-by: Mark Cave-Ayland 
Reviewed-by: Laurent Vivier 
Message-Id: <20210304221103.6369-38-mark.cave-ayl...@ilande.co.uk>
---
 hw/scsi/esp.c | 72 ++-
 include/hw/scsi/esp.h |  2 ++
 2 files changed, 60 insertions(+), 14 deletions(-)

diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c
index 23fcaa90c1..0d5c07e4c1 100644
--- a/hw/scsi/esp.c
+++ b/hw/scsi/esp.c
@@ -272,13 +272,15 @@ static void do_cmd(ESPState *s)
 uint8_t *buf = s->cmdbuf;
 uint8_t busid = buf[0];
 
-do_busid_cmd(s, [1], busid);
+/* Ignore extended messages for now */
+do_busid_cmd(s, [s->cmdbuf_cdb_offset], busid);
 }
 
 static void satn_pdma_cb(ESPState *s)
 {
 s->do_cmd = 0;
 if (s->cmdlen) {
+s->cmdbuf_cdb_offset = 1;
 do_cmd(s);
 }
 }
@@ -295,6 +297,7 @@ static void handle_satn(ESPState *s)
 cmdlen = get_cmd(s, ESP_CMDBUF_SZ);
 if (cmdlen > 0) {
 s->cmdlen = cmdlen;
+s->cmdbuf_cdb_offset = 1;
 do_cmd(s);
 } else if (cmdlen == 0) {
 s->cmdlen = 0;
@@ -309,6 +312,7 @@ static void s_without_satn_pdma_cb(ESPState *s)
 {
 s->do_cmd = 0;
 if (s->cmdlen) {
+s->cmdbuf_cdb_offset = 0;
 do_busid_cmd(s, s->cmdbuf, 0);
 }
 }
@@ -325,6 +329,7 @@ static void handle_s_without_atn(ESPState *s)
 cmdlen = get_cmd(s, ESP_CMDBUF_SZ);
 if (cmdlen > 0) {
 s->cmdlen = cmdlen;
+s->cmdbuf_cdb_offset = 0;
 do_busid_cmd(s, s->cmdbuf, 0);
 } else if (cmdlen == 0) {
 s->cmdlen = 0;
@@ -341,6 +346,7 @@ static void satn_stop_pdma_cb(ESPState *s)
 if (s->cmdlen) {
 trace_esp_handle_satn_stop(s->cmdlen);
 s->do_cmd = 1;
+s->cmdbuf_cdb_offset = 1;
 s->rregs[ESP_RSTAT] = STAT_TC | STAT_CD;
 s->rregs[ESP_RINTR] |= INTR_BS | INTR_FC;
 s->rregs[ESP_RSEQ] = SEQ_CD;
@@ -357,21 +363,22 @@ static void handle_satn_stop(ESPState *s)
 return;
 }
 s->pdma_cb = satn_stop_pdma_cb;
-cmdlen = get_cmd(s, ESP_CMDBUF_SZ);
+cmdlen = get_cmd(s, 1);
 if (cmdlen > 0) {
-trace_esp_handle_satn_stop(s->cmdlen);
+trace_esp_handle_satn_stop(cmdlen);
 s->cmdlen = cmdlen;
 s->do_cmd = 1;
-s->rregs[ESP_RSTAT] = STAT_CD;
+s->cmdbuf_cdb_offset = 1;
+s->rregs[ESP_RSTAT] = STAT_MO;
 s->rregs[ESP_RINTR] |= INTR_BS | INTR_FC;
-s->rregs[ESP_RSEQ] = SEQ_CD;
+s->rregs[ESP_RSEQ] = SEQ_MO;
 esp_raise_irq(s);
 } else if (cmdlen == 0) {
 s->cmdlen = 0;
 s->do_cmd = 1;
-/* Target present, but no cmd yet - switch to command phase */
-s->rregs[ESP_RSEQ] = SEQ_CD;
-s->rregs[ESP_RSTAT] = STAT_CD;
+/* Target present, switch to message out phase */
+s->rregs[ESP_RSEQ] = SEQ_MO;
+s->rregs[ESP_RSTAT] = STAT_MO;
 }
 }
 
@@ -505,9 +512,27 @@ static void esp_do_dma(ESPState *s)
 }
 trace_esp_handle_ti_cmd(s->cmdlen);
 s->ti_size = 0;
-s->cmdlen = 0;
-s->do_cmd = 0;
-do_cmd(s);
+if ((s->rregs[ESP_RSTAT] & 7) == STAT_CD) {
+/* No command received */
+if (s->cmdbuf_cdb_offset == s->cmdlen) {
+return;
+}
+
+/* Command has been received */
+s->cmdlen = 0;
+s->do_cmd = 0;
+do_cmd(s);
+} else {
+/*
+ * Extra message out bytes received: update cmdbuf_cdb_offset
+ * and then switch to commmand phase
+ */
+s->cmdbuf_cdb_offset = s->cmdlen;
+s->rregs[ESP_RSTAT] = STAT_TC | STAT_CD;
+s->rregs[ESP_RSEQ] = SEQ_CD;
+s->rregs[ESP_RINTR] |= INTR_BS;
+esp_raise_irq(s);
+}
 return;
 }
 if (s->async_len == 0) {
@@ -655,9 +680,27 @@ static void handle_ti(ESPState *s)
 } else if (s->do_cmd) {
 trace_esp_handle_ti_cmd(s->cmdlen);
 s->ti_size = 0;
-s->cmdlen = 0;
-s->do_cmd = 0;
-do_cmd(s);
+if ((s->rregs[ESP_RSTAT] & 7) == STAT_CD) {
+/* No command received */
+if (s->cmdbuf_cdb_offset == s->cmdlen) {
+return;
+}
+
+/* Command has been received */
+s->cmdlen = 0;
+s->do_cmd = 0;
+do_cmd(s);
+} else {
+/*
+ * Extra message out bytes received: update cmdbuf_cdb_offset
+ * and then switch to commmand phase
+ */
+ 

[PULL 33/42] esp: defer command completion interrupt on incoming data transfers

2021-03-07 Thread Mark Cave-Ayland
The MacOS toolbox ROM issues a command to the ESP controller as part of its
"FAST" SCSI routines and then proceeds to read the incoming data soon after
receiving the command completion interrupt.

Unfortunately due to SCSI block transfers being asynchronous the incoming data
may not yet be present causing an underflow error. Resolve this by waiting for
the SCSI subsystem transfer_data callback before raising the command completion
interrupt.

Signed-off-by: Mark Cave-Ayland 
Reviewed-by: Laurent Vivier 
Message-Id: <20210304221103.6369-34-mark.cave-ayl...@ilande.co.uk>
---
 hw/scsi/esp.c | 66 ++-
 include/hw/scsi/esp.h |  1 +
 2 files changed, 54 insertions(+), 13 deletions(-)

diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c
index 54d008c609..0eecc1d05c 100644
--- a/hw/scsi/esp.c
+++ b/hw/scsi/esp.c
@@ -183,6 +183,14 @@ static int esp_select(ESPState *s)
 esp_raise_irq(s);
 return -1;
 }
+
+/*
+ * Note that we deliberately don't raise the IRQ here: this will be done
+ * either in do_busid_cmd() for DATA OUT transfers or by the deferred
+ * IRQ mechanism in esp_transfer_data() for DATA IN transfers
+ */
+s->rregs[ESP_RINTR] |= INTR_FC;
+s->rregs[ESP_RSEQ] = SEQ_CD;
 return 0;
 }
 
@@ -237,18 +245,24 @@ static void do_busid_cmd(ESPState *s, uint8_t *buf, 
uint8_t busid)
 s->ti_size = datalen;
 if (datalen != 0) {
 s->rregs[ESP_RSTAT] = STAT_TC;
+s->rregs[ESP_RSEQ] = SEQ_CD;
 esp_set_tc(s, 0);
 if (datalen > 0) {
+/*
+ * Switch to DATA IN phase but wait until initial data xfer is
+ * complete before raising the command completion interrupt
+ */
+s->data_in_ready = false;
 s->rregs[ESP_RSTAT] |= STAT_DI;
 } else {
 s->rregs[ESP_RSTAT] |= STAT_DO;
+s->rregs[ESP_RINTR] |= INTR_BS | INTR_FC;
+esp_raise_irq(s);
+esp_lower_drq(s);
 }
 scsi_req_continue(s->current_req);
+return;
 }
-s->rregs[ESP_RINTR] |= INTR_BS | INTR_FC;
-s->rregs[ESP_RSEQ] = SEQ_CD;
-esp_raise_irq(s);
-esp_lower_drq(s);
 }
 
 static void do_cmd(ESPState *s)
@@ -439,17 +453,11 @@ static void do_dma_pdma_cb(ESPState *s)
 } else {
 if (s->async_len == 0) {
 if (s->current_req) {
+/* Defer until the scsi layer has completed */
 scsi_req_continue(s->current_req);
+s->data_in_ready = false;
 }
-
-/*
- * If there is still data to be read from the device then
- * complete the DMA operation immediately.  Otherwise defer
- * until the scsi layer has completed.
- */
-if (esp_get_tc(s) != 0 || s->ti_size == 0) {
-return;
-}
+return;
 }
 
 if (esp_get_tc(s) != 0) {
@@ -602,12 +610,35 @@ void esp_command_complete(SCSIRequest *req, size_t resid)
 void esp_transfer_data(SCSIRequest *req, uint32_t len)
 {
 ESPState *s = req->hba_private;
+int to_device = ((s->rregs[ESP_RSTAT] & 7) == STAT_DO);
 uint32_t dmalen = esp_get_tc(s);
 
 assert(!s->do_cmd);
 trace_esp_transfer_data(dmalen, s->ti_size);
 s->async_len = len;
 s->async_buf = scsi_req_get_buf(req);
+
+if (!to_device && !s->data_in_ready) {
+/*
+ * Initial incoming data xfer is complete so raise command
+ * completion interrupt
+ */
+s->data_in_ready = true;
+s->rregs[ESP_RSTAT] |= STAT_TC;
+s->rregs[ESP_RINTR] |= INTR_BS;
+esp_raise_irq(s);
+
+/*
+ * If data is ready to transfer and the TI command has already
+ * been executed, start DMA immediately. Otherwise DMA will start
+ * when host sends the TI command
+ */
+if (s->ti_size && (s->rregs[ESP_CMD] == (CMD_TI | CMD_DMA))) {
+esp_do_dma(s);
+}
+return;
+}
+
 if (dmalen) {
 esp_do_dma(s);
 } else if (s->ti_size <= 0) {
@@ -869,6 +900,14 @@ static bool esp_is_before_version_5(void *opaque, int 
version_id)
 return version_id < 5;
 }
 
+static bool esp_is_version_5(void *opaque, int version_id)
+{
+ESPState *s = ESP(opaque);
+
+version_id = MIN(version_id, s->mig_version_id);
+return version_id == 5;
+}
+
 static int esp_pre_save(void *opaque)
 {
 ESPState *s = ESP(opaque);
@@ -913,6 +952,7 @@ const VMStateDescription vmstate_esp = {
 VMSTATE_UINT32(cmdlen, ESPState),
 VMSTATE_UINT32(do_cmd, ESPState),
 VMSTATE_UINT32_TEST(mig_dma_left, ESPState, esp_is_before_version_5),
+VMSTATE_BOOL_TEST(data_in_ready, ESPState, esp_is_version_5),
 VMSTATE_END_OF_LIST()
 },
 };
diff --git a/include/hw/scsi/esp.h b/include/hw/scsi/esp.h
index 91f8ffd6c8..61bc317a4c 100644
--- a/include/hw/scsi/esp.h
+++ 

[PULL 15/42] esp: introduce esp_pdma_read() and esp_pdma_write() functions

2021-03-07 Thread Mark Cave-Ayland
Signed-off-by: Mark Cave-Ayland 
Reviewed-by: Laurent Vivier 
Message-Id: <20210304221103.6369-16-mark.cave-ayl...@ilande.co.uk>
---
 hw/scsi/esp.c | 28 
 1 file changed, 20 insertions(+), 8 deletions(-)

diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c
index 07d57cb791..0fafc866a4 100644
--- a/hw/scsi/esp.c
+++ b/hw/scsi/esp.c
@@ -151,6 +151,20 @@ static uint8_t *get_pdma_buf(ESPState *s)
 return NULL;
 }
 
+static uint8_t esp_pdma_read(ESPState *s)
+{
+uint8_t *buf = get_pdma_buf(s);
+
+return buf[s->pdma_cur++];
+}
+
+static void esp_pdma_write(ESPState *s, uint8_t val)
+{
+uint8_t *buf = get_pdma_buf(s);
+
+buf[s->pdma_cur++] = val;
+}
+
 static int get_cmd_cb(ESPState *s)
 {
 int target;
@@ -909,7 +923,6 @@ static void sysbus_esp_pdma_write(void *opaque, hwaddr addr,
 SysBusESPState *sysbus = opaque;
 ESPState *s = ESP(>esp);
 uint32_t dmalen = esp_get_tc(s);
-uint8_t *buf = get_pdma_buf(s);
 
 trace_esp_pdma_write(size);
 
@@ -918,13 +931,13 @@ static void sysbus_esp_pdma_write(void *opaque, hwaddr 
addr,
 }
 switch (size) {
 case 1:
-buf[s->pdma_cur++] = val;
+esp_pdma_write(s, val);
 s->pdma_len--;
 dmalen--;
 break;
 case 2:
-buf[s->pdma_cur++] = val >> 8;
-buf[s->pdma_cur++] = val;
+esp_pdma_write(s, val >> 8);
+esp_pdma_write(s, val);
 s->pdma_len -= 2;
 dmalen -= 2;
 break;
@@ -943,7 +956,6 @@ static uint64_t sysbus_esp_pdma_read(void *opaque, hwaddr 
addr,
 SysBusESPState *sysbus = opaque;
 ESPState *s = ESP(>esp);
 uint32_t dmalen = esp_get_tc(s);
-uint8_t *buf = get_pdma_buf(s);
 uint64_t val = 0;
 
 trace_esp_pdma_read(size);
@@ -953,13 +965,13 @@ static uint64_t sysbus_esp_pdma_read(void *opaque, hwaddr 
addr,
 }
 switch (size) {
 case 1:
-val = buf[s->pdma_cur++];
+val = esp_pdma_read(s);
 s->pdma_len--;
 dmalen--;
 break;
 case 2:
-val = buf[s->pdma_cur++];
-val = (val << 8) | buf[s->pdma_cur++];
+val = esp_pdma_read(s);
+val = (val << 8) | esp_pdma_read(s);
 s->pdma_len -= 2;
 dmalen -= 2;
 break;
-- 
2.20.1




[PULL 21/42] esp: remove redundant pdma_start from ESPState

2021-03-07 Thread Mark Cave-Ayland
Now that PDMA SCSI commands are accumulated in cmdbuf in the same way as normal
commands, the existing logic for locating the start of the SCSI command in
cmdbuf via cmdlen can be used. This enables the PDMA-specific pdma_start and
also get_pdma_buf() to be removed.

Signed-off-by: Mark Cave-Ayland 
Reviewed-by: Laurent Vivier 
Message-Id: <20210304221103.6369-22-mark.cave-ayl...@ilande.co.uk>
---
 hw/scsi/esp.c | 19 ++-
 include/hw/scsi/esp.h |  1 -
 2 files changed, 2 insertions(+), 18 deletions(-)

diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c
index 44fddf082c..38c05e97c3 100644
--- a/hw/scsi/esp.c
+++ b/hw/scsi/esp.c
@@ -131,24 +131,10 @@ static void set_pdma(ESPState *s, enum pdma_origin_id 
origin,
  uint32_t index, uint32_t len)
 {
 s->pdma_origin = origin;
-s->pdma_start = index;
 s->pdma_cur = index;
 s->pdma_len = len;
 }
 
-static uint8_t *get_pdma_buf(ESPState *s)
-{
-switch (s->pdma_origin) {
-case TI:
-return s->ti_buf;
-case CMD:
-return s->cmdbuf;
-case ASYNC:
-return s->async_buf;
-}
-return NULL;
-}
-
 static uint8_t esp_pdma_read(ESPState *s)
 {
 uint32_t dmalen = esp_get_tc(s);
@@ -339,7 +325,7 @@ static void s_without_satn_pdma_cb(ESPState *s)
 }
 s->do_cmd = 0;
 if (s->cmdlen) {
-do_busid_cmd(s, get_pdma_buf(s) + s->pdma_start, 0);
+do_busid_cmd(s, s->cmdbuf, 0);
 }
 }
 
@@ -441,7 +427,7 @@ static void esp_dma_done(ESPState *s)
 static void do_dma_pdma_cb(ESPState *s)
 {
 int to_device = ((s->rregs[ESP_RSTAT] & 7) == STAT_DO);
-int len = s->pdma_cur - s->pdma_start;
+int len = s->pdma_cur;
 
 if (s->do_cmd) {
 s->ti_size = 0;
@@ -867,7 +853,6 @@ static const VMStateDescription vmstate_esp_pdma = {
 .fields = (VMStateField[]) {
 VMSTATE_INT32(pdma_origin, ESPState),
 VMSTATE_UINT32(pdma_len, ESPState),
-VMSTATE_UINT32(pdma_start, ESPState),
 VMSTATE_UINT32(pdma_cur, ESPState),
 VMSTATE_END_OF_LIST()
 }
diff --git a/include/hw/scsi/esp.h b/include/hw/scsi/esp.h
index 600d0c31ab..55b0aee762 100644
--- a/include/hw/scsi/esp.h
+++ b/include/hw/scsi/esp.h
@@ -58,7 +58,6 @@ struct ESPState {
 void (*dma_cb)(ESPState *s);
 int pdma_origin;
 uint32_t pdma_len;
-uint32_t pdma_start;
 uint32_t pdma_cur;
 void (*pdma_cb)(ESPState *s);
 
-- 
2.20.1




[PULL 34/42] esp: remove old deferred command completion mechanism

2021-03-07 Thread Mark Cave-Ayland
Commit ea84a44250 "scsi: esp: Defer command completion until previous interrupts
have been handled" provided a mechanism to delay the command completion 
interrupt
until ESP_RINTR is read after the command has completed.

With the previous fixes for latching the ESP_RINTR bits and deferring the 
setting
of the command completion interrupt for incoming data to the SCSI callback, this
workaround is no longer required and can be removed.

Signed-off-by: Mark Cave-Ayland 
Reviewed-by: Laurent Vivier 
Message-Id: <20210304221103.6369-35-mark.cave-ayl...@ilande.co.uk>
---
 hw/scsi/esp.c | 35 +--
 include/hw/scsi/esp.h |  4 ++--
 2 files changed, 11 insertions(+), 28 deletions(-)

diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c
index 0eecc1d05c..eb6681ca66 100644
--- a/hw/scsi/esp.c
+++ b/hw/scsi/esp.c
@@ -568,18 +568,20 @@ static void esp_do_dma(ESPState *s)
 esp_lower_drq(s);
 }
 
-static void esp_report_command_complete(ESPState *s, uint32_t status)
+void esp_command_complete(SCSIRequest *req, size_t resid)
 {
+ESPState *s = req->hba_private;
+
 trace_esp_command_complete();
 if (s->ti_size != 0) {
 trace_esp_command_complete_unexpected();
 }
 s->ti_size = 0;
 s->async_len = 0;
-if (status) {
+if (req->status) {
 trace_esp_command_complete_fail();
 }
-s->status = status;
+s->status = req->status;
 s->rregs[ESP_RSTAT] = STAT_ST;
 esp_dma_done(s);
 esp_lower_drq(s);
@@ -590,23 +592,6 @@ static void esp_report_command_complete(ESPState *s, 
uint32_t status)
 }
 }
 
-void esp_command_complete(SCSIRequest *req, size_t resid)
-{
-ESPState *s = req->hba_private;
-
-if (s->rregs[ESP_RSTAT] & STAT_INT) {
-/*
- * Defer handling command complete until the previous
- * interrupt has been handled.
- */
-trace_esp_command_complete_deferred();
-s->deferred_status = req->status;
-s->deferred_complete = true;
-return;
-}
-esp_report_command_complete(s, req->status);
-}
-
 void esp_transfer_data(SCSIRequest *req, uint32_t len)
 {
 ESPState *s = req->hba_private;
@@ -733,10 +718,6 @@ uint64_t esp_reg_read(ESPState *s, uint32_t saddr)
 s->rregs[ESP_RSTAT] &= ~STAT_TC;
 s->rregs[ESP_RSEQ] = SEQ_0;
 esp_lower_irq(s);
-if (s->deferred_complete) {
-esp_report_command_complete(s, s->deferred_status);
-s->deferred_complete = false;
-}
 break;
 case ESP_TCHI:
 /* Return the unique id if the value has never been written */
@@ -944,8 +925,10 @@ const VMStateDescription vmstate_esp = {
 VMSTATE_UINT32(ti_wptr, ESPState),
 VMSTATE_BUFFER(ti_buf, ESPState),
 VMSTATE_UINT32(status, ESPState),
-VMSTATE_UINT32(deferred_status, ESPState),
-VMSTATE_BOOL(deferred_complete, ESPState),
+VMSTATE_UINT32_TEST(mig_deferred_status, ESPState,
+esp_is_before_version_5),
+VMSTATE_BOOL_TEST(mig_deferred_complete, ESPState,
+  esp_is_before_version_5),
 VMSTATE_UINT32(dma, ESPState),
 VMSTATE_PARTIAL_BUFFER(cmdbuf, ESPState, 16),
 VMSTATE_BUFFER_START_MIDDLE_V(cmdbuf, ESPState, 16, 4),
diff --git a/include/hw/scsi/esp.h b/include/hw/scsi/esp.h
index 61bc317a4c..7d88fa0f92 100644
--- a/include/hw/scsi/esp.h
+++ b/include/hw/scsi/esp.h
@@ -30,8 +30,6 @@ struct ESPState {
 int32_t ti_size;
 uint32_t ti_rptr, ti_wptr;
 uint32_t status;
-uint32_t deferred_status;
-bool deferred_complete;
 uint32_t dma;
 uint8_t ti_buf[TI_BUFSZ];
 SCSIBus bus;
@@ -57,6 +55,8 @@ struct ESPState {
 
 /* Legacy fields for vmstate_esp version < 5 */
 uint32_t mig_dma_left;
+uint32_t mig_deferred_status;
+bool mig_deferred_complete;
 };
 
 #define TYPE_SYSBUS_ESP "sysbus-esp"
-- 
2.20.1




[PULL 32/42] esp: latch individual bits in ESP_RINTR register

2021-03-07 Thread Mark Cave-Ayland
Currently the ESP_RINTR register is set to a specific value as required within
the ESP state machine. In order to implement the upcoming deferred interrupt
functionality it is necessary to set individual bits within ESP_RINTR so that
a deferred interrupt will not overwrite the value of any other interrupt bits.

This also requires fixing up a few locations where the ESP_RINTR and ESP_RSEQ
registers are set/reset unexpectedly.

Signed-off-by: Mark Cave-Ayland 
Reviewed-by: Laurent Vivier 
Message-Id: <20210304221103.6369-33-mark.cave-ayl...@ilande.co.uk>
---
 hw/scsi/esp.c | 29 +
 1 file changed, 13 insertions(+), 16 deletions(-)

diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c
index 6aae6f91c2..54d008c609 100644
--- a/hw/scsi/esp.c
+++ b/hw/scsi/esp.c
@@ -178,7 +178,7 @@ static int esp_select(ESPState *s)
 if (!s->current_dev) {
 /* No such drive */
 s->rregs[ESP_RSTAT] = 0;
-s->rregs[ESP_RINTR] = INTR_DC;
+s->rregs[ESP_RINTR] |= INTR_DC;
 s->rregs[ESP_RSEQ] = SEQ_0;
 esp_raise_irq(s);
 return -1;
@@ -245,7 +245,7 @@ static void do_busid_cmd(ESPState *s, uint8_t *buf, uint8_t 
busid)
 }
 scsi_req_continue(s->current_req);
 }
-s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
+s->rregs[ESP_RINTR] |= INTR_BS | INTR_FC;
 s->rregs[ESP_RSEQ] = SEQ_CD;
 esp_raise_irq(s);
 esp_lower_drq(s);
@@ -326,7 +326,7 @@ static void satn_stop_pdma_cb(ESPState *s)
 trace_esp_handle_satn_stop(s->cmdlen);
 s->do_cmd = 1;
 s->rregs[ESP_RSTAT] = STAT_TC | STAT_CD;
-s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
+s->rregs[ESP_RINTR] |= INTR_BS | INTR_FC;
 s->rregs[ESP_RSEQ] = SEQ_CD;
 esp_raise_irq(s);
 }
@@ -346,8 +346,8 @@ static void handle_satn_stop(ESPState *s)
 trace_esp_handle_satn_stop(s->cmdlen);
 s->cmdlen = cmdlen;
 s->do_cmd = 1;
-s->rregs[ESP_RSTAT] = STAT_TC | STAT_CD;
-s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
+s->rregs[ESP_RSTAT] = STAT_CD;
+s->rregs[ESP_RINTR] |= INTR_BS | INTR_FC;
 s->rregs[ESP_RSEQ] = SEQ_CD;
 esp_raise_irq(s);
 } else if (cmdlen == 0) {
@@ -362,7 +362,7 @@ static void handle_satn_stop(ESPState *s)
 static void write_response_pdma_cb(ESPState *s)
 {
 s->rregs[ESP_RSTAT] = STAT_TC | STAT_ST;
-s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
+s->rregs[ESP_RINTR] |= INTR_BS | INTR_FC;
 s->rregs[ESP_RSEQ] = SEQ_CD;
 esp_raise_irq(s);
 }
@@ -376,7 +376,7 @@ static void write_response(ESPState *s)
 if (s->dma_memory_write) {
 s->dma_memory_write(s->dma_opaque, s->ti_buf, 2);
 s->rregs[ESP_RSTAT] = STAT_TC | STAT_ST;
-s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
+s->rregs[ESP_RINTR] |= INTR_BS | INTR_FC;
 s->rregs[ESP_RSEQ] = SEQ_CD;
 } else {
 s->pdma_cb = write_response_pdma_cb;
@@ -395,7 +395,7 @@ static void write_response(ESPState *s)
 static void esp_dma_done(ESPState *s)
 {
 s->rregs[ESP_RSTAT] |= STAT_TC;
-s->rregs[ESP_RINTR] = INTR_BS;
+s->rregs[ESP_RINTR] |= INTR_BS;
 s->rregs[ESP_RSEQ] = 0;
 s->rregs[ESP_RFLAGS] = 0;
 esp_set_tc(s, 0);
@@ -700,7 +700,7 @@ uint64_t esp_reg_read(ESPState *s, uint32_t saddr)
 val = s->rregs[ESP_RINTR];
 s->rregs[ESP_RINTR] = 0;
 s->rregs[ESP_RSTAT] &= ~STAT_TC;
-s->rregs[ESP_RSEQ] = SEQ_CD;
+s->rregs[ESP_RSEQ] = SEQ_0;
 esp_lower_irq(s);
 if (s->deferred_complete) {
 esp_report_command_complete(s, s->deferred_status);
@@ -771,9 +771,6 @@ void esp_reg_write(ESPState *s, uint32_t saddr, uint64_t 
val)
 /*s->ti_size = 0;*/
 s->ti_wptr = 0;
 s->ti_rptr = 0;
-s->rregs[ESP_RINTR] = INTR_FC;
-s->rregs[ESP_RSEQ] = 0;
-s->rregs[ESP_RFLAGS] = 0;
 break;
 case CMD_RESET:
 trace_esp_mem_writeb_cmd_reset(val);
@@ -781,8 +778,8 @@ void esp_reg_write(ESPState *s, uint32_t saddr, uint64_t 
val)
 break;
 case CMD_BUSRESET:
 trace_esp_mem_writeb_cmd_bus_reset(val);
-s->rregs[ESP_RINTR] = INTR_RST;
 if (!(s->wregs[ESP_CFG1] & CFG1_RESREPT)) {
+s->rregs[ESP_RINTR] |= INTR_RST;
 esp_raise_irq(s);
 }
 break;
@@ -793,12 +790,12 @@ void esp_reg_write(ESPState *s, uint32_t saddr, uint64_t 
val)
 case CMD_ICCS:
 trace_esp_mem_writeb_cmd_iccs(val);
 write_response(s);
-s->rregs[ESP_RINTR] = INTR_FC;
+s->rregs[ESP_RINTR] |= INTR_FC;
 s->rregs[ESP_RSTAT] |= STAT_MI;
 break;
 case CMD_MSGACC:
 trace_esp_mem_writeb_cmd_msgacc(val);
-s->rregs[ESP_RINTR] = INTR_DC;
+s->rregs[ESP_RINTR] |= INTR_DC;
 s->rregs[ESP_RSEQ] = 0;
  

[PULL 08/42] esp: determine transfer direction directly from SCSI phase

2021-03-07 Thread Mark Cave-Ayland
The transfer direction is currently determined by checking the sign of ti_size
but as this series progresses ti_size can be zero at the end of the transfer.

Use the SCSI phase to determine the transfer direction as used in other SCSI
controller implementations.

Signed-off-by: Mark Cave-Ayland 
Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Laurent Vivier 
Message-Id: <20210304221103.6369-9-mark.cave-ayl...@ilande.co.uk>
---
 hw/scsi/esp.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c
index e0676ae790..5365523f6b 100644
--- a/hw/scsi/esp.c
+++ b/hw/scsi/esp.c
@@ -356,7 +356,7 @@ static void esp_dma_done(ESPState *s)
 
 static void do_dma_pdma_cb(ESPState *s)
 {
-int to_device = (s->ti_size < 0);
+int to_device = ((s->rregs[ESP_RSTAT] & 7) == STAT_DO);
 int len = s->pdma_cur - s->pdma_start;
 if (s->do_cmd) {
 s->ti_size = 0;
@@ -392,7 +392,7 @@ static void do_dma_pdma_cb(ESPState *s)
 static void esp_do_dma(ESPState *s)
 {
 uint32_t len;
-int to_device;
+int to_device = ((s->rregs[ESP_RSTAT] & 7) == STAT_DO);
 
 len = s->dma_left;
 if (s->do_cmd) {
@@ -425,7 +425,6 @@ static void esp_do_dma(ESPState *s)
 if (len > s->async_len) {
 len = s->async_len;
 }
-to_device = (s->ti_size < 0);
 if (to_device) {
 if (s->dma_memory_read) {
 s->dma_memory_read(s->dma_opaque, s->async_buf, len);
-- 
2.20.1




[PULL 18/42] esp: accumulate SCSI commands for PDMA transfers in cmdbuf instead of pdma_buf

2021-03-07 Thread Mark Cave-Ayland
ESP SCSI commands are already accumulated in cmdbuf and so there is no need to
keep a separate pdma_buf buffer. Accumulate SCSI commands for PDMA transfers in
cmdbuf instead of pdma_buf so update cmdlen accordingly and change pdma_origin
for PDMA transfers to CMD which allows the PDMA origin to be removed.

This commit also removes a stray memcpy() from get_cmd() which is a no-op 
because
cmdlen is always zero at the start of a command.

Notionally the removal of pdma_buf from vmstate_esp_pdma also breaks migration
compatibility for the PDMA subsection until its complete removal by the end of
the series.

Signed-off-by: Mark Cave-Ayland 
Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Laurent Vivier 
Message-Id: <20210304221103.6369-19-mark.cave-ayl...@ilande.co.uk>
---
 hw/scsi/esp.c | 56 +++
 include/hw/scsi/esp.h |  2 --
 2 files changed, 25 insertions(+), 33 deletions(-)

diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c
index b8d1ec41e9..66caa95815 100644
--- a/hw/scsi/esp.c
+++ b/hw/scsi/esp.c
@@ -139,8 +139,6 @@ static void set_pdma(ESPState *s, enum pdma_origin_id 
origin,
 static uint8_t *get_pdma_buf(ESPState *s)
 {
 switch (s->pdma_origin) {
-case PDMA:
-return s->pdma_buf;
 case TI:
 return s->ti_buf;
 case CMD:
@@ -161,14 +159,12 @@ static uint8_t esp_pdma_read(ESPState *s)
 }
 
 switch (s->pdma_origin) {
-case PDMA:
-val = s->pdma_buf[s->pdma_cur++];
-break;
 case TI:
 val = s->ti_buf[s->pdma_cur++];
 break;
 case CMD:
-val = s->cmdbuf[s->pdma_cur++];
+val = s->cmdbuf[s->cmdlen++];
+s->pdma_cur++;
 break;
 case ASYNC:
 val = s->async_buf[s->pdma_cur++];
@@ -193,14 +189,12 @@ static void esp_pdma_write(ESPState *s, uint8_t val)
 }
 
 switch (s->pdma_origin) {
-case PDMA:
-s->pdma_buf[s->pdma_cur++] = val;
-break;
 case TI:
 s->ti_buf[s->pdma_cur++] = val;
 break;
 case CMD:
-s->cmdbuf[s->pdma_cur++] = val;
+s->cmdbuf[s->cmdlen++] = val;
+s->pdma_cur++;
 break;
 case ASYNC:
 s->async_buf[s->pdma_cur++] = val;
@@ -256,8 +250,7 @@ static uint32_t get_cmd(ESPState *s, uint8_t *buf, uint8_t 
buflen)
 if (s->dma_memory_read) {
 s->dma_memory_read(s->dma_opaque, buf, dmalen);
 } else {
-memcpy(s->pdma_buf, buf, dmalen);
-set_pdma(s, PDMA, 0, dmalen);
+set_pdma(s, CMD, 0, dmalen);
 esp_raise_drq(s);
 return 0;
 }
@@ -316,24 +309,24 @@ static void satn_pdma_cb(ESPState *s)
 if (get_cmd_cb(s) < 0) {
 return;
 }
-if (s->pdma_cur != s->pdma_start) {
-do_cmd(s, get_pdma_buf(s) + s->pdma_start);
+s->do_cmd = 0;
+if (s->cmdlen) {
+do_cmd(s, s->cmdbuf);
 }
 }
 
 static void handle_satn(ESPState *s)
 {
-uint8_t buf[32];
-int len;
-
 if (s->dma && !s->dma_enabled) {
 s->dma_cb = handle_satn;
 return;
 }
 s->pdma_cb = satn_pdma_cb;
-len = get_cmd(s, buf, sizeof(buf));
-if (len) {
-do_cmd(s, buf);
+s->cmdlen = get_cmd(s, s->cmdbuf, sizeof(s->cmdbuf));
+if (s->cmdlen) {
+do_cmd(s, s->cmdbuf);
+} else {
+s->do_cmd = 1;
 }
 }
 
@@ -342,24 +335,24 @@ static void s_without_satn_pdma_cb(ESPState *s)
 if (get_cmd_cb(s) < 0) {
 return;
 }
-if (s->pdma_cur != s->pdma_start) {
+s->do_cmd = 0;
+if (s->cmdlen) {
 do_busid_cmd(s, get_pdma_buf(s) + s->pdma_start, 0);
 }
 }
 
 static void handle_s_without_atn(ESPState *s)
 {
-uint8_t buf[32];
-int len;
-
 if (s->dma && !s->dma_enabled) {
 s->dma_cb = handle_s_without_atn;
 return;
 }
 s->pdma_cb = s_without_satn_pdma_cb;
-len = get_cmd(s, buf, sizeof(buf));
-if (len) {
-do_busid_cmd(s, buf, 0);
+s->cmdlen = get_cmd(s, s->cmdbuf, sizeof(s->cmdbuf));
+if (s->cmdlen) {
+do_busid_cmd(s, s->cmdbuf, 0);
+} else {
+s->do_cmd = 1;
 }
 }
 
@@ -368,7 +361,7 @@ static void satn_stop_pdma_cb(ESPState *s)
 if (get_cmd_cb(s) < 0) {
 return;
 }
-s->cmdlen = s->pdma_cur - s->pdma_start;
+s->do_cmd = 0;
 if (s->cmdlen) {
 trace_esp_handle_satn_stop(s->cmdlen);
 s->do_cmd = 1;
@@ -394,6 +387,8 @@ static void handle_satn_stop(ESPState *s)
 s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
 s->rregs[ESP_RSEQ] = SEQ_CD;
 esp_raise_irq(s);
+} else {
+s->do_cmd = 1;
 }
 }
 
@@ -864,11 +859,10 @@ static bool esp_pdma_needed(void *opaque)
 
 static const VMStateDescription vmstate_esp_pdma = {
 .name = "esp/pdma",
-.version_id = 1,
-.minimum_version_id = 1,
+.version_id = 2,
+.minimum_version_id = 2,
 .needed = esp_pdma_needed,
 .fields = (VMStateField[]) {
-VMSTATE_BUFFER(pdma_buf, 

[PULL 23/42] esp: use ti_wptr/ti_rptr to manage the current FIFO position for PDMA

2021-03-07 Thread Mark Cave-Ayland
This eliminates the last user of the PDMA-specific pdma_cur variable which can
now be removed.

Signed-off-by: Mark Cave-Ayland 
Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Laurent Vivier 
Message-Id: <20210304221103.6369-24-mark.cave-ayl...@ilande.co.uk>
---
 hw/scsi/esp.c | 23 ---
 include/hw/scsi/esp.h |  1 -
 2 files changed, 8 insertions(+), 16 deletions(-)

diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c
index bb3a9cd5e3..7bf2ec9c94 100644
--- a/hw/scsi/esp.c
+++ b/hw/scsi/esp.c
@@ -127,11 +127,9 @@ static uint32_t esp_get_stc(ESPState *s)
 return dmalen;
 }
 
-static void set_pdma(ESPState *s, enum pdma_origin_id origin,
- uint32_t index, uint32_t len)
+static void set_pdma(ESPState *s, enum pdma_origin_id origin, uint32_t len)
 {
 s->pdma_origin = origin;
-s->pdma_cur = index;
 s->pdma_len = len;
 }
 
@@ -146,11 +144,10 @@ static uint8_t esp_pdma_read(ESPState *s)
 
 switch (s->pdma_origin) {
 case TI:
-val = s->ti_buf[s->pdma_cur++];
+val = s->ti_buf[s->ti_rptr++];
 break;
 case CMD:
 val = s->cmdbuf[s->cmdlen++];
-s->pdma_cur++;
 break;
 case ASYNC:
 val = s->async_buf[0];
@@ -158,7 +155,6 @@ static uint8_t esp_pdma_read(ESPState *s)
 s->async_len--;
 s->async_buf++;
 }
-s->pdma_cur++;
 break;
 default:
 g_assert_not_reached();
@@ -182,11 +178,10 @@ static void esp_pdma_write(ESPState *s, uint8_t val)
 
 switch (s->pdma_origin) {
 case TI:
-s->ti_buf[s->pdma_cur++] = val;
+s->ti_buf[s->ti_wptr++] = val;
 break;
 case CMD:
 s->cmdbuf[s->cmdlen++] = val;
-s->pdma_cur++;
 break;
 case ASYNC:
 s->async_buf[0] = val;
@@ -194,7 +189,6 @@ static void esp_pdma_write(ESPState *s, uint8_t val)
 s->async_len--;
 s->async_buf++;
 }
-s->pdma_cur++;
 break;
 default:
 g_assert_not_reached();
@@ -249,7 +243,7 @@ static uint32_t get_cmd(ESPState *s)
 if (s->dma_memory_read) {
 s->dma_memory_read(s->dma_opaque, buf, dmalen);
 } else {
-set_pdma(s, CMD, 0, dmalen);
+set_pdma(s, CMD, dmalen);
 esp_raise_drq(s);
 return 0;
 }
@@ -412,7 +406,7 @@ static void write_response(ESPState *s)
 s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
 s->rregs[ESP_RSEQ] = SEQ_CD;
 } else {
-set_pdma(s, TI, 0, 2);
+set_pdma(s, TI, 2);
 s->pdma_cb = write_response_pdma_cb;
 esp_raise_drq(s);
 return;
@@ -480,7 +474,7 @@ static void esp_do_dma(ESPState *s)
 if (s->dma_memory_read) {
 s->dma_memory_read(s->dma_opaque, >cmdbuf[s->cmdlen], len);
 } else {
-set_pdma(s, CMD, s->cmdlen, len);
+set_pdma(s, CMD, len);
 s->pdma_cb = do_dma_pdma_cb;
 esp_raise_drq(s);
 return;
@@ -503,7 +497,7 @@ static void esp_do_dma(ESPState *s)
 if (s->dma_memory_read) {
 s->dma_memory_read(s->dma_opaque, s->async_buf, len);
 } else {
-set_pdma(s, ASYNC, 0, len);
+set_pdma(s, ASYNC, len);
 s->pdma_cb = do_dma_pdma_cb;
 esp_raise_drq(s);
 return;
@@ -512,7 +506,7 @@ static void esp_do_dma(ESPState *s)
 if (s->dma_memory_write) {
 s->dma_memory_write(s->dma_opaque, s->async_buf, len);
 } else {
-set_pdma(s, ASYNC, 0, len);
+set_pdma(s, ASYNC, len);
 s->pdma_cb = do_dma_pdma_cb;
 esp_raise_drq(s);
 return;
@@ -857,7 +851,6 @@ static const VMStateDescription vmstate_esp_pdma = {
 .fields = (VMStateField[]) {
 VMSTATE_INT32(pdma_origin, ESPState),
 VMSTATE_UINT32(pdma_len, ESPState),
-VMSTATE_UINT32(pdma_cur, ESPState),
 VMSTATE_END_OF_LIST()
 }
 };
diff --git a/include/hw/scsi/esp.h b/include/hw/scsi/esp.h
index 55b0aee762..26bd015cf4 100644
--- a/include/hw/scsi/esp.h
+++ b/include/hw/scsi/esp.h
@@ -58,7 +58,6 @@ struct ESPState {
 void (*dma_cb)(ESPState *s);
 int pdma_origin;
 uint32_t pdma_len;
-uint32_t pdma_cur;
 void (*pdma_cb)(ESPState *s);
 
 uint8_t mig_version_id;
-- 
2.20.1




[PULL 06/42] esp: fix esp_reg_read() trace event

2021-03-07 Thread Mark Cave-Ayland
Move the trace event to the end of the function so that it correctly reports
the returned value if it doesn't come directly from the rregs array.

Signed-off-by: Mark Cave-Ayland 
Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Laurent Vivier 
Message-Id: <20210304221103.6369-7-mark.cave-ayl...@ilande.co.uk>
---
 hw/scsi/esp.c | 18 --
 1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c
index 73700550f2..16c1853577 100644
--- a/hw/scsi/esp.c
+++ b/hw/scsi/esp.c
@@ -594,9 +594,8 @@ static void parent_esp_reset(ESPState *s, int irq, int 
level)
 
 uint64_t esp_reg_read(ESPState *s, uint32_t saddr)
 {
-uint32_t old_val;
+uint32_t val;
 
-trace_esp_mem_readb(saddr, s->rregs[saddr]);
 switch (saddr) {
 case ESP_FIFO:
 if ((s->rregs[ESP_RSTAT] & STAT_PIO_MASK) == 0) {
@@ -611,13 +610,14 @@ uint64_t esp_reg_read(ESPState *s, uint32_t saddr)
 s->ti_rptr = 0;
 s->ti_wptr = 0;
 }
+val = s->rregs[ESP_FIFO];
 break;
 case ESP_RINTR:
 /*
  * Clear sequence step, interrupt register and all status bits
  * except TC
  */
-old_val = s->rregs[ESP_RINTR];
+val = s->rregs[ESP_RINTR];
 s->rregs[ESP_RINTR] = 0;
 s->rregs[ESP_RSTAT] &= ~STAT_TC;
 s->rregs[ESP_RSEQ] = SEQ_CD;
@@ -626,16 +626,22 @@ uint64_t esp_reg_read(ESPState *s, uint32_t saddr)
 esp_report_command_complete(s, s->deferred_status);
 s->deferred_complete = false;
 }
-return old_val;
+break;
 case ESP_TCHI:
 /* Return the unique id if the value has never been written */
 if (!s->tchi_written) {
-return s->chip_id;
+val = s->chip_id;
+} else {
+val = s->rregs[saddr];
 }
+break;
 default:
+val = s->rregs[saddr];
 break;
 }
-return s->rregs[saddr];
+
+trace_esp_mem_readb(saddr, val);
+return val;
 }
 
 void esp_reg_write(ESPState *s, uint32_t saddr, uint64_t val)
-- 
2.20.1




  1   2   >