[PULL 02/17] hw/arm/aspeed: Remove dead code

2024-02-01 Thread Cédric Le Goater
From: Philippe Mathieu-Daudé 

Remove copy/paste typo from commit 6c323aba40 ("hw/arm/aspeed:
Adding new machine Tiogapass in QEMU").

Signed-off-by: Philippe Mathieu-Daudé 
Reviewed-by: Cédric Le Goater 
Reviewed-by: Richard Henderson 
Reviewed-by: Gavin Shan 
Signed-off-by: Cédric Le Goater 
---
 hw/arm/aspeed.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index cc59176563a8..4bc292ff84fc 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -1301,7 +1301,6 @@ static void 
aspeed_machine_tiogapass_class_init(ObjectClass *oc, void *data)
 mc->default_ram_size   = 1 * GiB;
 mc->default_cpus = mc->min_cpus = mc->max_cpus =
 aspeed_soc_num_cpus(amc->soc_name);
-aspeed_soc_num_cpus(amc->soc_name);
 };
 
 static void aspeed_machine_sonorapass_class_init(ObjectClass *oc, void *data)
-- 
2.43.0




Re: [PATCH] hw/pci-host/raven.c: Mark raven_io_ops as implementing unaligned accesses

2024-02-01 Thread Cédric Le Goater

On 2/1/24 14:32, Peter Maydell wrote:

On Tue, 23 Jan 2024 at 11:03, Cédric Le Goater  wrote:


On 1/12/24 14:46, Peter Maydell wrote:

The raven_io_ops MemoryRegionOps is the only one in the source tree
which sets .valid.unaligned to indicate that it should support
unaligned accesses and which does not also set .impl.unaligned to
indicate that its read and write functions can do the unaligned
handling themselves.  This is a problem, because at the moment the
core memory system does not implement the support for handling
unaligned accesses by doing a series of aligned accesses and
combining them (system/memory.c:access_with_adjusted_size() has a
TODO comment noting this).

Fortunately raven_io_read() and raven_io_write() will correctly deal
with the case of being passed an unaligned address, so we can fix the
missing unaligned access support by setting .impl.unaligned in the
MemoryRegionOps struct.

Fixes: 9a1839164c9c8f06 ("raven: Implement non-contiguous I/O region")
Signed-off-by: Peter Maydell 
---
Spotted by code inspection: I was looking for devices whose behaviour
might be changed by a patch I'm reviewing that adds that missing
support for unaligned accesses in the core memory system. But even
if we do implement it there, it's more efficient for the raven MR
to correctly mark it as handling unaligned accesses itself.

Tested with 'make check' and 'make check-avocado' only.


It doesn't affect the prep machine boot with OpenBIOS and a
"Debian GNU/Linux 3.0 6015" image.

Tested-by: Cédric Le Goater 
Reviewed-by: Cédric Le Goater 


Thanks for the review -- is this patch going to go via a
ppc queue, or should I throw it in with my upcoming
target-arm pullreq?


Please take it through target-arm. PPC is in low power state AFAICT.

Thanks,

C.






Re: [PULL 13/17] hw/fsi: Aspeed APB2OPB & On-chip peripheral bus

2024-01-31 Thread Cédric Le Goater

Here is an update version with a fix. I will include it in the next PR.

Thanks,

C.




From: Ninad Palsule 

This is a part of patchset where IBM's Flexible Service Interface is
introduced.

An APB-to-OPB bridge enabling access to the OPB from the ARM core in
the AST2600. Hardware limitations prevent the OPB from being directly
mapped into APB, so all accesses are indirect through the bridge.

The On-Chip Peripheral Bus (OPB): A low-speed bus typically found in
POWER processors. This now makes an appearance in the ASPEED SoC due
to tight integration of the FSI master IP with the OPB, mainly the
existence of an MMIO-mapping of the CFAM address straight onto a
sub-region of the OPB address space.

Signed-off-by: Andrew Jeffery 
Signed-off-by: Ninad Palsule 
Reviewed-by: Cédric Le Goater 
[ clg: - moved FSIMasterState under AspeedAPB2OPBState
   - modified fsi_opb_fsi_master_address() and
 fsi_opb_opb2fsi_address()
   - instroduced fsi_aspeed_apb2opb_init()
   - reworked fsi_aspeed_apb2opb_realize()
   - removed FSIMasterState object and fsi_opb_realize()
   - simplified OPBus
   - introduced fsi_aspeed_apb2opb_rw to fix endianness issue ]
Signed-off-by: Cédric Le Goater 
---
 include/hw/fsi/aspeed_apb2opb.h |  46 
 hw/fsi/aspeed_apb2opb.c | 367 
 hw/arm/Kconfig  |   1 +
 hw/fsi/Kconfig  |   5 +
 hw/fsi/meson.build  |   1 +
 hw/fsi/trace-events |   2 +
 6 files changed, 422 insertions(+)
 create mode 100644 include/hw/fsi/aspeed_apb2opb.h
 create mode 100644 hw/fsi/aspeed_apb2opb.c

diff --git a/include/hw/fsi/aspeed_apb2opb.h b/include/hw/fsi/aspeed_apb2opb.h
new file mode 100644
index ..f6a2387abf28
--- /dev/null
+++ b/include/hw/fsi/aspeed_apb2opb.h
@@ -0,0 +1,46 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright (C) 2024 IBM Corp.
+ *
+ * ASPEED APB2OPB Bridge
+ * IBM On-Chip Peripheral Bus
+ */
+#ifndef FSI_ASPEED_APB2OPB_H
+#define FSI_ASPEED_APB2OPB_H
+
+#include "exec/memory.h"
+#include "hw/fsi/fsi-master.h"
+#include "hw/sysbus.h"
+
+#define TYPE_FSI_OPB "fsi.opb"
+
+#define TYPE_OP_BUS "opb"
+OBJECT_DECLARE_SIMPLE_TYPE(OPBus, OP_BUS)
+
+typedef struct OPBus {
+BusState bus;
+
+MemoryRegion mr;
+AddressSpace as;
+} OPBus;
+
+#define TYPE_ASPEED_APB2OPB "aspeed.apb2opb"
+OBJECT_DECLARE_SIMPLE_TYPE(AspeedAPB2OPBState, ASPEED_APB2OPB)
+
+#define ASPEED_APB2OPB_NR_REGS ((0xe8 >> 2) + 1)
+
+#define ASPEED_FSI_NUM 2
+
+typedef struct AspeedAPB2OPBState {
+SysBusDevice parent_obj;
+
+MemoryRegion iomem;
+
+uint32_t regs[ASPEED_APB2OPB_NR_REGS];
+qemu_irq irq;
+
+OPBus opb[ASPEED_FSI_NUM];
+FSIMasterState fsi[ASPEED_FSI_NUM];
+} AspeedAPB2OPBState;
+
+#endif /* FSI_ASPEED_APB2OPB_H */
diff --git a/hw/fsi/aspeed_apb2opb.c b/hw/fsi/aspeed_apb2opb.c
new file mode 100644
index ..ea50718b6a2b
--- /dev/null
+++ b/hw/fsi/aspeed_apb2opb.c
@@ -0,0 +1,367 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright (C) 2024 IBM Corp.
+ *
+ * ASPEED APB-OPB FSI interface
+ * IBM On-chip Peripheral Bus
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qom/object.h"
+#include "qapi/error.h"
+#include "trace.h"
+
+#include "hw/fsi/aspeed_apb2opb.h"
+#include "hw/qdev-core.h"
+
+#define TO_REG(x) (x >> 2)
+
+#define APB2OPB_VERSIONTO_REG(0x00)
+#define APB2OPB_TRIGGERTO_REG(0x04)
+
+#define APB2OPB_CONTROLTO_REG(0x08)
+#define   APB2OPB_CONTROL_OFF  BE_GENMASK(31, 13)
+
+#define APB2OPB_OPB2FSITO_REG(0x0c)
+#define   APB2OPB_OPB2FSI_OFF  BE_GENMASK(31, 22)
+
+#define APB2OPB_OPB0_SEL   TO_REG(0x10)
+#define APB2OPB_OPB1_SEL   TO_REG(0x28)
+#define   APB2OPB_OPB_SEL_EN   BIT(0)
+
+#define APB2OPB_OPB0_MODE  TO_REG(0x14)
+#define APB2OPB_OPB1_MODE  TO_REG(0x2c)
+#define   APB2OPB_OPB_MODE_RD  BIT(0)
+
+#define APB2OPB_OPB0_XFER  TO_REG(0x18)
+#define APB2OPB_OPB1_XFER  TO_REG(0x30)
+#define   APB2OPB_OPB_XFER_FULLBIT(1)
+#define   APB2OPB_OPB_XFER_HALFBIT(0)
+
+#define APB2OPB_OPB0_ADDR  TO_REG(0x1c)
+#define APB2OPB_OPB0_WRITE_DATATO_REG(0x20)
+
+#define APB2OPB_OPB1_ADDR  TO_REG(0x34)
+#define APB2OPB_OPB1_WRITE_DATA  TO_REG(0x38)
+
+#define APB2OPB_IRQ_STSTO_REG(0x48)
+#define   APB2OPB_IRQ_STS_OPB1_TX_ACK  BIT(17)
+#define   APB2OPB_IRQ_STS_OPB0_TX_ACK  BIT(16)
+
+#define APB2OPB_OPB0_WRITE_WORD_ENDIAN TO_REG(0x4c)
+#define   APB2OPB_OPB0_WRITE_WORD_ENDIAN_BE 0x0011101b
+#define APB2OPB_OPB0_WRITE_BYTE_END

Re: [PATCH 0/5] buses: switch to 3-phase-reset

2024-01-31 Thread Cédric Le Goater

On 1/22/24 15:19, Cédric Le Goater wrote:

Hello,

On 1/22/24 03:06, Peter Xu wrote:

Hi, Peter,

On Fri, Jan 19, 2024 at 04:35:07PM +, Peter Maydell wrote:

I wrote this ages ago and recently picked it back up because of a
recent PCI related reset ordering problem noted by Peter Xu.  I'm not
sure if this patchset is necessary as a part of fixing that ordering
problem (it might even be possible now to have the intel_iommu device
use 3-phase reset and put the relevant parts of its reset into the
'exit' phase), but either way we really ought to do this cleanup
to reduce the amount of legacy/transitional handling we have.


The VFIO issue I was working on may not directly benefit from this series
iiuc, as it's more of an special ordering on both (1) VFIO special case
reset path using qemu_register_reset(), and (2) VT-d device is not put at
the right place in the QOM hierachy [1].

Said that, thanks a lot for posting the patches; they all look reasonable
and good cleanups to the reset infrastructure, afaict.



Yes. I took the series in my vfio testing environment (x86_64 and s390x) and
didn't see any issue. I will keep it for further testing.


Acked-by: Cédric Le Goater 
Tested-by: Cédric Le Goater 

Thanks,

C.






[PULL 1/2] vfio: use matching sizeof type

2024-01-29 Thread Cédric Le Goater
From: Paolo Bonzini 

Do not use uint64_t for the type of the declaration and __u64 when
computing the number of elements in the array.

Signed-off-by: Paolo Bonzini 
Reviewed-by: Philippe Mathieu-Daudé 
---
 hw/vfio/common.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/vfio/common.c b/hw/vfio/common.c
index 
4aa86f563c64cab9290efab54d20cb2a30c498aa..059bfdc07a85e2eb908df828c1f42104d683e911
 100644
--- a/hw/vfio/common.c
+++ b/hw/vfio/common.c
@@ -1118,7 +1118,7 @@ static int vfio_device_dma_logging_report(VFIODevice 
*vbasedev, hwaddr iova,
 {
 uint64_t buf[DIV_ROUND_UP(sizeof(struct vfio_device_feature) +
 sizeof(struct vfio_device_feature_dma_logging_report),
-sizeof(__u64))] = {};
+sizeof(uint64_t))] = {};
 struct vfio_device_feature *feature = (struct vfio_device_feature *)buf;
 struct vfio_device_feature_dma_logging_report *report =
 (struct vfio_device_feature_dma_logging_report *)feature->data;
-- 
2.43.0




[PULL 2/2] vfio/pci: Clear MSI-X IRQ index always

2024-01-29 Thread Cédric Le Goater
When doing device assignment of a physical device, MSI-X can be
enabled with no vectors enabled and this sets the IRQ index to
VFIO_PCI_MSIX_IRQ_INDEX. However, when MSI-X is disabled, the IRQ
index is left untouched if no vectors are in use. Then, when INTx
is enabled, the IRQ index value is considered incompatible (set to
MSI-X) and VFIO_DEVICE_SET_IRQS fails. QEMU complains with :

qemu-system-x86_64: vfio :08:00.0: Failed to set up TRIGGER eventfd 
signaling for interrupt INTX-0: VFIO_DEVICE_SET_IRQS failure: Invalid argument

To avoid that, unconditionaly clear the IRQ index when MSI-X is
disabled.

Buglink: https://issues.redhat.com/browse/RHEL-21293
Fixes: 5ebffa4e87e7 ("vfio/pci: use an invalid fd to enable MSI-X")
Cc: Jing Liu 
Cc: Alex Williamson 
Reviewed-by: Alex Williamson 
Signed-off-by: Cédric Le Goater 
---
 hw/vfio/pci.c | 8 +---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
index 
d7fe06715c4b9cde66a68c31aaf405315921b0d6..4fa387f0430d62ca2ba1b5ae5b7037f8f06b33f9
 100644
--- a/hw/vfio/pci.c
+++ b/hw/vfio/pci.c
@@ -826,9 +826,11 @@ static void vfio_msix_disable(VFIOPCIDevice *vdev)
 }
 }
 
-if (vdev->nr_vectors) {
-vfio_disable_irqindex(>vbasedev, VFIO_PCI_MSIX_IRQ_INDEX);
-}
+/*
+ * Always clear MSI-X IRQ index. A PF device could have enabled
+ * MSI-X with no vectors. See vfio_msix_enable().
+ */
+vfio_disable_irqindex(>vbasedev, VFIO_PCI_MSIX_IRQ_INDEX);
 
 vfio_msi_disable_common(vdev);
 vfio_intx_enable(vdev, );
-- 
2.43.0




[PULL 0/2] vfio queue

2024-01-29 Thread Cédric Le Goater
The following changes since commit 7a1dc45af581d2b643cdbf33c01fd96271616fbd:

  Merge tag 'pull-target-arm-20240126' of 
https://git.linaro.org/people/pmaydell/qemu-arm into staging (2024-01-26 
18:16:35 +)

are available in the Git repository at:

  https://github.com/legoater/qemu/ tags/pull-vfio-20240129

for you to fetch changes up to d2b668fca5652760b435ce812a743bba03d2f316:

  vfio/pci: Clear MSI-X IRQ index always (2024-01-29 08:26:25 +0100)


vfio queue:

* Array type cleanup
* Fix for IRQ enablement


Cédric Le Goater (1):
  vfio/pci: Clear MSI-X IRQ index always

Paolo Bonzini (1):
  vfio: use matching sizeof type

 hw/vfio/common.c | 2 +-
 hw/vfio/pci.c| 8 +---
 2 files changed, 6 insertions(+), 4 deletions(-)



Re: [PULL 00/17] aspeed queue

2024-01-26 Thread Cédric Le Goater

On 1/26/24 16:56, Peter Maydell wrote:

On Fri, 26 Jan 2024 at 13:33, Cédric Le Goater  wrote:


The following changes since commit e029fe22caad9b75c7ab69bd4e84853c11fb71e0:

   Merge tag 'pull-qapi-2024-01-26' of https://repo.or.cz/qemu/armbru into 
staging (2024-01-26 10:21:27 +)

are available in the Git repository at:

   https://github.com/legoater/qemu/ tags/pull-aspeed-20240126

for you to fetch changes up to b40769f4b49d15485ffaaa7acade3e3593ee6daa:

   hw/fsi: Update MAINTAINER list (2024-01-26 14:22:08 +0100)


aspeed queue:

* Update of buildroot images to 2023.11 (6.6.3 kernel)
* Check of the valid CPU type supported by aspeed machines
* Simplified models for the IBM's FSI bus and the Aspeed
   controller bridge




Looks like you have an endianness bug, either in the device
or in the test. From the s390 runner:

https://gitlab.com/qemu-project/qemu/-/jobs/6029422595

232/847 qemu:qtest+qtest-arm / qtest-arm/aspeed-fsi-test ERROR 0.38s
killed by signal 6 SIGABRT

PYTHON=/home/gitlab-runner/builds/-LCfcJ2T/0/qemu-project/qemu/build/pyvenv/bin/python3
 QTEST_QEMU_STORAGE_DAEMON_BINARY=./storage-daemon/qemu-storage-daemon 
QTEST_QEMU_BINARY=./qemu-system-arm 
G_TEST_DBUS_DAEMON=/home/gitlab-runner/builds/-LCfcJ2T/0/qemu-project/qemu/tests/dbus-vmstate-daemon.sh
 MALLOC_PERTURB_=82 QTEST_QEMU_IMG=./qemu-img 
/home/gitlab-runner/builds/-LCfcJ2T/0/qemu-project/qemu/build/tests/qtest/aspeed-fsi-test
 --tap -k

― ✀ ―
stderr:
**
ERROR:../tests/qtest/aspeed-fsi-test.c:152:test_fsi0_getcfam_addr0:
assertion failed (curval == 0x152d02c0): (3221368085 == 355271360)
(test program exited with status code -6)

where 3221368085 is 0xC0022D15, and 355271360 is 0x152D02C0...



drat. Indeed. I didn't check BE ... Sorry about that.

Ninad,

Some changes are required in fsi_aspeed_apb2opb_write().

Could you please rework the address space accesses to use
address_space_*_le() routines instead of address_space_rw() ?
This will be less concise.

To check, you can use a PPC64 debian (big-endian) on a PPC64
KVM guest or PowerVM LPAR, or a s390x LPAR.


Thanks,

C.




[PULL 16/17] hw/fsi: Added FSI documentation

2024-01-26 Thread Cédric Le Goater
From: Ninad Palsule 

Documentation for IBM FSI model.

Signed-off-by: Ninad Palsule 
Reviewed-by: Cédric Le Goater 
[ clg : - Removed source file list
- Fixed aspeed machine reference ]
Signed-off-by: Cédric Le Goater 
---
 docs/specs/fsi.rst   | 122 +++
 docs/specs/index.rst |   1 +
 2 files changed, 123 insertions(+)
 create mode 100644 docs/specs/fsi.rst

diff --git a/docs/specs/fsi.rst b/docs/specs/fsi.rst
new file mode 100644
index ..af8782253152
--- /dev/null
+++ b/docs/specs/fsi.rst
@@ -0,0 +1,122 @@
+==
+IBM's Flexible Service Interface (FSI)
+==
+
+The QEMU FSI emulation implements hardware interfaces between ASPEED SOC, FSI
+master/slave and the end engine.
+
+FSI is a point-to-point two wire interface which is capable of supporting
+distances of up to 4 meters. FSI interfaces have been used successfully for
+many years in IBM servers to attach IBM Flexible Support Processors(FSP) to
+CPUs and IBM ASICs.
+
+FSI allows a service processor access to the internal buses of a host POWER
+processor to perform configuration or debugging. FSI has long existed in POWER
+processes and so comes with some baggage, including how it has been integrated
+into the ASPEED SoC.
+
+Working backwards from the POWER processor, the fundamental pieces of interest
+for the implementation are: (see the `FSI specification`_ for more details)
+
+1. The Common FRU Access Macro (CFAM), an address space containing various
+   "engines" that drive accesses on buses internal and external to the POWER
+   chip. Examples include the SBEFIFO and I2C masters. The engines hang off of
+   an internal Local Bus (LBUS) which is described by the CFAM configuration
+   block.
+
+2. The FSI slave: The slave is the terminal point of the FSI bus for FSI
+   symbols addressed to it. Slaves can be cascaded off of one another. The
+   slave's configuration registers appear in address space of the CFAM to
+   which it is attached.
+
+3. The FSI master: A controller in the platform service processor (e.g. BMC)
+   driving CFAM engine accesses into the POWER chip. At the hardware level
+   FSI is a bit-based protocol supporting synchronous and DMA-driven accesses
+   of engines in a CFAM.
+
+4. The On-Chip Peripheral Bus (OPB): A low-speed bus typically found in POWER
+   processors. This now makes an appearance in the ASPEED SoC due to tight
+   integration of the FSI master IP with the OPB, mainly the existence of an
+   MMIO-mapping of the CFAM address straight onto a sub-region of the OPB
+   address space.
+
+5. An APB-to-OPB bridge enabling access to the OPB from the ARM core in the
+   AST2600. Hardware limitations prevent the OPB from being directly mapped
+   into APB, so all accesses are indirect through the bridge.
+
+The LBUS is modelled to maintain the qdev bus hierarchy and to take advantages
+of the object model to automatically generate the CFAM configuration block.
+The configuration block presents engines in the order they are attached to the
+CFAM's LBUS. Engine implementations should subclass the LBusDevice and set the
+'config' member of LBusDeviceClass to match the engine's type.
+
+CFAM designs offer a lot of flexibility, for instance it is possible for a
+CFAM to be simultaneously driven from multiple FSI links. The modeling is not
+so complete; it's assumed that each CFAM is attached to a single FSI slave (as
+a consequence the CFAM subclasses the FSI slave).
+
+As for FSI, its symbols and wire-protocol are not modelled at all. This is not
+necessary to get FSI off the ground thanks to the mapping of the CFAM address
+space onto the OPB address space - the models follow this directly and map the
+CFAM memory region into the OPB's memory region.
+
+The following commands start the ``rainier-bmc`` machine with built-in FSI
+model. There are no model specific arguments. Please check this document to
+learn more about Aspeed ``rainier-bmc`` machine: 
(:doc:`../../system/arm/aspeed`)
+
+.. code-block:: console
+
+  qemu-system-arm -M rainier-bmc -nographic \
+  -kernel fitImage-linux.bin \
+  -dtb aspeed-bmc-ibm-rainier.dtb \
+  -initrd obmc-phosphor-initramfs.rootfs.cpio.xz \
+  -drive file=obmc-phosphor-image.rootfs.wic.qcow2,if=sd,index=2 \
+  -append "rootwait console=ttyS4,115200n8 root=PARTLABEL=rofs-a"
+
+The implementation appears as following in the qemu device tree:
+
+.. code-block:: console
+
+  (qemu) info qtree
+  bus: main-system-bus
+type System
+...
+dev: aspeed.apb2opb, id ""
+  gpio-out "sysbus-irq" 1
+  mmio 1e79b000/1000
+  bus: opb.1
+type opb
+dev: fsi.master, id ""
+  bus: fsi.bus.1
+type fsi.bus
+dev: cfam.config, id ""
+dev: cfam, id ""
+  bus: lbus.1
+type lbus
+

[PULL 13/17] hw/fsi: Aspeed APB2OPB & On-chip peripheral bus

2024-01-26 Thread Cédric Le Goater
From: Ninad Palsule 

This is a part of patchset where IBM's Flexible Service Interface is
introduced.

An APB-to-OPB bridge enabling access to the OPB from the ARM core in
the AST2600. Hardware limitations prevent the OPB from being directly
mapped into APB, so all accesses are indirect through the bridge.

The On-Chip Peripheral Bus (OPB): A low-speed bus typically found in
POWER processors. This now makes an appearance in the ASPEED SoC due
to tight integration of the FSI master IP with the OPB, mainly the
existence of an MMIO-mapping of the CFAM address straight onto a
sub-region of the OPB address space.

Signed-off-by: Andrew Jeffery 
Signed-off-by: Ninad Palsule 
Reviewed-by: Cédric Le Goater 
[ clg: - moved FSIMasterState under AspeedAPB2OPBState
   - modified fsi_opb_fsi_master_address() and
 fsi_opb_opb2fsi_address()
   - instroduced fsi_aspeed_apb2opb_init()
   - reworked fsi_aspeed_apb2opb_realize()
   - removed FSIMasterState object and fsi_opb_realize()
   - simplified OPBus ]
Signed-off-by: Cédric Le Goater 
---
 include/hw/fsi/aspeed_apb2opb.h |  46 +
 hw/fsi/aspeed_apb2opb.c | 329 
 hw/arm/Kconfig  |   1 +
 hw/fsi/Kconfig  |   5 +
 hw/fsi/meson.build  |   1 +
 hw/fsi/trace-events |   2 +
 6 files changed, 384 insertions(+)
 create mode 100644 include/hw/fsi/aspeed_apb2opb.h
 create mode 100644 hw/fsi/aspeed_apb2opb.c

diff --git a/include/hw/fsi/aspeed_apb2opb.h b/include/hw/fsi/aspeed_apb2opb.h
new file mode 100644
index ..f6a2387abf28
--- /dev/null
+++ b/include/hw/fsi/aspeed_apb2opb.h
@@ -0,0 +1,46 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright (C) 2024 IBM Corp.
+ *
+ * ASPEED APB2OPB Bridge
+ * IBM On-Chip Peripheral Bus
+ */
+#ifndef FSI_ASPEED_APB2OPB_H
+#define FSI_ASPEED_APB2OPB_H
+
+#include "exec/memory.h"
+#include "hw/fsi/fsi-master.h"
+#include "hw/sysbus.h"
+
+#define TYPE_FSI_OPB "fsi.opb"
+
+#define TYPE_OP_BUS "opb"
+OBJECT_DECLARE_SIMPLE_TYPE(OPBus, OP_BUS)
+
+typedef struct OPBus {
+BusState bus;
+
+MemoryRegion mr;
+AddressSpace as;
+} OPBus;
+
+#define TYPE_ASPEED_APB2OPB "aspeed.apb2opb"
+OBJECT_DECLARE_SIMPLE_TYPE(AspeedAPB2OPBState, ASPEED_APB2OPB)
+
+#define ASPEED_APB2OPB_NR_REGS ((0xe8 >> 2) + 1)
+
+#define ASPEED_FSI_NUM 2
+
+typedef struct AspeedAPB2OPBState {
+SysBusDevice parent_obj;
+
+MemoryRegion iomem;
+
+uint32_t regs[ASPEED_APB2OPB_NR_REGS];
+qemu_irq irq;
+
+OPBus opb[ASPEED_FSI_NUM];
+FSIMasterState fsi[ASPEED_FSI_NUM];
+} AspeedAPB2OPBState;
+
+#endif /* FSI_ASPEED_APB2OPB_H */
diff --git a/hw/fsi/aspeed_apb2opb.c b/hw/fsi/aspeed_apb2opb.c
new file mode 100644
index ..1e0c2032e04c
--- /dev/null
+++ b/hw/fsi/aspeed_apb2opb.c
@@ -0,0 +1,329 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright (C) 2024 IBM Corp.
+ *
+ * ASPEED APB-OPB FSI interface
+ * IBM On-chip Peripheral Bus
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qom/object.h"
+#include "qapi/error.h"
+#include "trace.h"
+
+#include "hw/fsi/aspeed_apb2opb.h"
+#include "hw/qdev-core.h"
+
+#define TO_REG(x) (x >> 2)
+
+#define APB2OPB_VERSIONTO_REG(0x00)
+#define APB2OPB_TRIGGERTO_REG(0x04)
+
+#define APB2OPB_CONTROLTO_REG(0x08)
+#define   APB2OPB_CONTROL_OFF  BE_GENMASK(31, 13)
+
+#define APB2OPB_OPB2FSITO_REG(0x0c)
+#define   APB2OPB_OPB2FSI_OFF  BE_GENMASK(31, 22)
+
+#define APB2OPB_OPB0_SEL   TO_REG(0x10)
+#define APB2OPB_OPB1_SEL   TO_REG(0x28)
+#define   APB2OPB_OPB_SEL_EN   BIT(0)
+
+#define APB2OPB_OPB0_MODE  TO_REG(0x14)
+#define APB2OPB_OPB1_MODE  TO_REG(0x2c)
+#define   APB2OPB_OPB_MODE_RD  BIT(0)
+
+#define APB2OPB_OPB0_XFER  TO_REG(0x18)
+#define APB2OPB_OPB1_XFER  TO_REG(0x30)
+#define   APB2OPB_OPB_XFER_FULLBIT(1)
+#define   APB2OPB_OPB_XFER_HALFBIT(0)
+
+#define APB2OPB_OPB0_ADDR  TO_REG(0x1c)
+#define APB2OPB_OPB0_WRITE_DATATO_REG(0x20)
+
+#define APB2OPB_OPB1_ADDR  TO_REG(0x34)
+#define APB2OPB_OPB1_WRITE_DATA  TO_REG(0x38)
+
+#define APB2OPB_IRQ_STSTO_REG(0x48)
+#define   APB2OPB_IRQ_STS_OPB1_TX_ACK  BIT(17)
+#define   APB2OPB_IRQ_STS_OPB0_TX_ACK  BIT(16)
+
+#define APB2OPB_OPB0_WRITE_WORD_ENDIAN TO_REG(0x4c)
+#define   APB2OPB_OPB0_WRITE_WORD_ENDIAN_BE 0x0011101b
+#define APB2OPB_OPB0_WRITE_BYTE_ENDIAN TO_REG(0x50)
+#define   APB2OPB_OPB0_WRITE_BYTE_ENDIAN_BE 0x0c330f3f
+#define APB2OPB_OPB1_WRITE_WORD_ENDIAN TO_REG(0x54)
+#define APB2OPB_OPB1_WRITE

[PULL 07/17] hw/fsi: Introduce IBM's Local bus

2024-01-26 Thread Cédric Le Goater
From: Ninad Palsule 

This is a part of patchset where IBM's Flexible Service Interface is
introduced.

The LBUS is modelled to maintain mapped memory for the devices. The
memory is mapped after CFAM config, peek table and FSI slave registers.

Signed-off-by: Andrew Jeffery 
Signed-off-by: Ninad Palsule 
Reviewed-by: Cédric Le Goater 
[ clg: - removed lbus_add_device() bc unused
   - removed lbus_create_device() bc used only once
   - removed "address" property
   - updated meson.build to build fsi dir
   - included an empty hw/fsi/trace-events ]
Signed-off-by: Cédric Le Goater 
---
 meson.build   |  1 +
 hw/fsi/trace.h|  1 +
 include/hw/fsi/lbus.h | 32 
 hw/fsi/lbus.c | 43 +++
 hw/Kconfig|  1 +
 hw/fsi/Kconfig|  2 ++
 hw/fsi/meson.build|  1 +
 hw/fsi/trace-events   |  0
 hw/meson.build|  1 +
 9 files changed, 82 insertions(+)
 create mode 100644 hw/fsi/trace.h
 create mode 100644 include/hw/fsi/lbus.h
 create mode 100644 hw/fsi/lbus.c
 create mode 100644 hw/fsi/Kconfig
 create mode 100644 hw/fsi/meson.build
 create mode 100644 hw/fsi/trace-events

diff --git a/meson.build b/meson.build
index d0329966f1b4..7d926c6e8270 100644
--- a/meson.build
+++ b/meson.build
@@ -3290,6 +3290,7 @@ if have_system
 'hw/char',
 'hw/display',
 'hw/dma',
+'hw/fsi',
 'hw/hyperv',
 'hw/i2c',
 'hw/i386',
diff --git a/hw/fsi/trace.h b/hw/fsi/trace.h
new file mode 100644
index ..ee67c7fb04da
--- /dev/null
+++ b/hw/fsi/trace.h
@@ -0,0 +1 @@
+#include "trace/trace-hw_fsi.h"
diff --git a/include/hw/fsi/lbus.h b/include/hw/fsi/lbus.h
new file mode 100644
index ..e8a22e22a8fa
--- /dev/null
+++ b/include/hw/fsi/lbus.h
@@ -0,0 +1,32 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright (C) 2024 IBM Corp.
+ *
+ * IBM Local bus and connected device structures.
+ */
+#ifndef FSI_LBUS_H
+#define FSI_LBUS_H
+
+#include "hw/qdev-core.h"
+#include "qemu/units.h"
+#include "exec/memory.h"
+
+#define TYPE_FSI_LBUS_DEVICE "fsi.lbus.device"
+OBJECT_DECLARE_SIMPLE_TYPE(FSILBusDevice, FSI_LBUS_DEVICE)
+
+typedef struct FSILBusDevice {
+DeviceState parent;
+
+MemoryRegion iomem;
+} FSILBusDevice;
+
+#define TYPE_FSI_LBUS "fsi.lbus"
+OBJECT_DECLARE_SIMPLE_TYPE(FSILBus, FSI_LBUS)
+
+typedef struct FSILBus {
+BusState bus;
+
+MemoryRegion mr;
+} FSILBus;
+
+#endif /* FSI_LBUS_H */
diff --git a/hw/fsi/lbus.c b/hw/fsi/lbus.c
new file mode 100644
index ..44d2319087a8
--- /dev/null
+++ b/hw/fsi/lbus.c
@@ -0,0 +1,43 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright (C) 2024 IBM Corp.
+ *
+ * IBM Local bus where FSI slaves are connected
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "hw/fsi/lbus.h"
+
+#include "hw/qdev-properties.h"
+
+#include "trace.h"
+
+static void fsi_lbus_init(Object *o)
+{
+FSILBus *lbus = FSI_LBUS(o);
+
+memory_region_init(>mr, OBJECT(lbus), TYPE_FSI_LBUS, 1 * MiB);
+}
+
+static const TypeInfo fsi_lbus_info = {
+.name = TYPE_FSI_LBUS,
+.parent = TYPE_BUS,
+.instance_init = fsi_lbus_init,
+.instance_size = sizeof(FSILBus),
+};
+
+static const TypeInfo fsi_lbus_device_type_info = {
+.name = TYPE_FSI_LBUS_DEVICE,
+.parent = TYPE_DEVICE,
+.instance_size = sizeof(FSILBusDevice),
+.abstract = true,
+};
+
+static void fsi_lbus_register_types(void)
+{
+type_register_static(_lbus_info);
+type_register_static(_lbus_device_type_info);
+}
+
+type_init(fsi_lbus_register_types);
diff --git a/hw/Kconfig b/hw/Kconfig
index 9ca7b38c31f1..2c00936c28e8 100644
--- a/hw/Kconfig
+++ b/hw/Kconfig
@@ -9,6 +9,7 @@ source core/Kconfig
 source cxl/Kconfig
 source display/Kconfig
 source dma/Kconfig
+source fsi/Kconfig
 source gpio/Kconfig
 source hyperv/Kconfig
 source i2c/Kconfig
diff --git a/hw/fsi/Kconfig b/hw/fsi/Kconfig
new file mode 100644
index ..9c34a418d700
--- /dev/null
+++ b/hw/fsi/Kconfig
@@ -0,0 +1,2 @@
+config FSI
+bool
diff --git a/hw/fsi/meson.build b/hw/fsi/meson.build
new file mode 100644
index ..93ba19dd0411
--- /dev/null
+++ b/hw/fsi/meson.build
@@ -0,0 +1 @@
+system_ss.add(when: 'CONFIG_FSI', if_true: files('lbus.c'))
diff --git a/hw/fsi/trace-events b/hw/fsi/trace-events
new file mode 100644
index ..e69de29bb2d1
diff --git a/hw/meson.build b/hw/meson.build
index f01fac4617c9..463d70268304 100644
--- a/hw/meson.build
+++ b/hw/meson.build
@@ -44,6 +44,7 @@ subdir('virtio')
 subdir('watchdog')
 subdir('xen')
 subdir('xenpv')
+subdir('fsi')
 
 subdir('alpha')
 subdir('arm')
-- 
2.43.0




[PULL 17/17] hw/fsi: Update MAINTAINER list

2024-01-26 Thread Cédric Le Goater
From: Ninad Palsule 

Added maintainer for IBM FSI model

Signed-off-by: Ninad Palsule 
Reviewed-by: Cédric Le Goater 
Signed-off-by: Cédric Le Goater 
---
 MAINTAINERS | 9 +
 1 file changed, 9 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index dfaca8323e91..39deb8ee1f24 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3585,6 +3585,15 @@ F: tests/qtest/adm1272-test.c
 F: tests/qtest/max34451-test.c
 F: tests/qtest/isl_pmbus_vr-test.c
 
+FSI
+M: Ninad Palsule 
+R: Cédric Le Goater 
+S: Maintained
+F: hw/fsi/*
+F: include/hw/fsi/*
+F: docs/specs/fsi.rst
+F: tests/qtest/fsi-test.c
+
 Firmware schema specifications
 M: Philippe Mathieu-Daudé 
 R: Daniel P. Berrange 
-- 
2.43.0




[PULL 12/17] hw/fsi: Introduce IBM's FSI master

2024-01-26 Thread Cédric Le Goater
From: Ninad Palsule 

This is a part of patchset where IBM's Flexible Service Interface is
introduced.

This commit models the FSI master. CFAM is hanging out of FSI master which is a 
bus controller.

The FSI master: A controller in the platform service processor (e.g.
BMC) driving CFAM engine accesses into the POWER chip. At the
hardware level FSI is a bit-based protocol supporting synchronous and
DMA-driven accesses of engines in a CFAM.

Signed-off-by: Andrew Jeffery 
Signed-off-by: Ninad Palsule 
Reviewed-by: Cédric Le Goater 
[ clg: - move FSICFAMState object under FSIMasterState
   - introduced fsi_master_init()
   - reworked fsi_master_realize()
   - dropped FSIBus definition ]
Signed-off-by: Cédric Le Goater 
---
 include/hw/fsi/fsi-master.h |  32 +++
 hw/fsi/fsi-master.c | 170 
 hw/fsi/meson.build  |   2 +-
 hw/fsi/trace-events |   2 +
 4 files changed, 205 insertions(+), 1 deletion(-)
 create mode 100644 include/hw/fsi/fsi-master.h
 create mode 100644 hw/fsi/fsi-master.c

diff --git a/include/hw/fsi/fsi-master.h b/include/hw/fsi/fsi-master.h
new file mode 100644
index ..68e5f56db2ea
--- /dev/null
+++ b/include/hw/fsi/fsi-master.h
@@ -0,0 +1,32 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright (C) 2024 IBM Corp.
+ *
+ * IBM Flexible Service Interface Master
+ */
+#ifndef FSI_FSI_MASTER_H
+#define FSI_FSI_MASTER_H
+
+#include "exec/memory.h"
+#include "hw/qdev-core.h"
+#include "hw/fsi/fsi.h"
+#include "hw/fsi/cfam.h"
+
+#define TYPE_FSI_MASTER "fsi.master"
+OBJECT_DECLARE_SIMPLE_TYPE(FSIMasterState, FSI_MASTER)
+
+#define FSI_MASTER_NR_REGS ((0x2e0 >> 2) + 1)
+
+typedef struct FSIMasterState {
+DeviceState parent;
+MemoryRegion iomem;
+MemoryRegion opb2fsi;
+
+FSIBus bus;
+
+uint32_t regs[FSI_MASTER_NR_REGS];
+FSICFAMState cfam;
+} FSIMasterState;
+
+
+#endif /* FSI_FSI_H */
diff --git a/hw/fsi/fsi-master.c b/hw/fsi/fsi-master.c
new file mode 100644
index ..a5f0598c98ed
--- /dev/null
+++ b/hw/fsi/fsi-master.c
@@ -0,0 +1,170 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright (C) 2024 IBM Corp.
+ *
+ * IBM Flexible Service Interface master
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu/log.h"
+#include "trace.h"
+
+#include "hw/fsi/fsi-master.h"
+
+#define TYPE_OP_BUS "opb"
+
+#define TO_REG(x)   ((x) >> 2)
+
+#define FSI_MENP0   TO_REG(0x010)
+#define FSI_MENP32  TO_REG(0x014)
+#define FSI_MSENP0  TO_REG(0x018)
+#define FSI_MLEVP0  TO_REG(0x018)
+#define FSI_MSENP32 TO_REG(0x01c)
+#define FSI_MLEVP32 TO_REG(0x01c)
+#define FSI_MCENP0  TO_REG(0x020)
+#define FSI_MREFP0  TO_REG(0x020)
+#define FSI_MCENP32 TO_REG(0x024)
+#define FSI_MREFP32 TO_REG(0x024)
+
+#define FSI_MVERTO_REG(0x074)
+#define FSI_MRESP0  TO_REG(0x0d0)
+
+#define FSI_MRESB0  TO_REG(0x1d0)
+#define   FSI_MRESB0_RESET_GENERAL  BIT(31)
+#define   FSI_MRESB0_RESET_ERRORBIT(30)
+
+static uint64_t fsi_master_read(void *opaque, hwaddr addr, unsigned size)
+{
+FSIMasterState *s = FSI_MASTER(opaque);
+int reg = TO_REG(addr);
+
+trace_fsi_master_read(addr, size);
+
+if (reg >= FSI_MASTER_NR_REGS) {
+qemu_log_mask(LOG_GUEST_ERROR,
+  "%s: Out of bounds read: 0x%"HWADDR_PRIx" for %u\n",
+  __func__, addr, size);
+return 0;
+}
+
+return s->regs[reg];
+}
+
+static void fsi_master_write(void *opaque, hwaddr addr, uint64_t data,
+ unsigned size)
+{
+FSIMasterState *s = FSI_MASTER(opaque);
+int reg = TO_REG(addr);
+
+trace_fsi_master_write(addr, size, data);
+
+if (reg >= FSI_MASTER_NR_REGS) {
+qemu_log_mask(LOG_GUEST_ERROR,
+  "%s: Out of bounds write: %"HWADDR_PRIx" for %u\n",
+  __func__, addr, size);
+return;
+}
+
+switch (reg) {
+case FSI_MENP0:
+s->regs[FSI_MENP0] = data;
+break;
+case FSI_MENP32:
+s->regs[FSI_MENP32] = data;
+break;
+case FSI_MSENP0:
+s->regs[FSI_MENP0] |= data;
+break;
+case FSI_MSENP32:
+s->regs[FSI_MENP32] |= data;
+break;
+case FSI_MCENP0:
+s->regs[FSI_MENP0] &= ~data;
+break;
+case FSI_MCENP32:
+s->regs[FSI_MENP32] &= ~data;
+ 

[PULL 11/17] hw/fsi: Introduce IBM's cfam

2024-01-26 Thread Cédric Le Goater
From: Ninad Palsule 

This is a part of patchset where IBM's Flexible Service Interface is
introduced.

The Common FRU Access Macro (CFAM), an address space containing
various "engines" that drive accesses on busses internal and external
to the POWER chip. Examples include the SBEFIFO and I2C masters. The
engines hang off of an internal Local Bus (LBUS) which is described
by the CFAM configuration block.

Signed-off-by: Andrew Jeffery 
Signed-off-by: Ninad Palsule 
Reviewed-by: Cédric Le Goater 
[ clg: - moved object FSIScratchPad under FSICFAMState
   - moved FSIScratchPad code under cfam.c
   - introduced fsi_cfam_instance_init()
   - reworked fsi_cfam_realize() ]
Signed-off-by: Cédric Le Goater 
---
 include/hw/fsi/cfam.h |  34 +
 hw/fsi/cfam.c | 168 ++
 hw/fsi/meson.build|   2 +-
 hw/fsi/trace-events   |   5 ++
 4 files changed, 208 insertions(+), 1 deletion(-)
 create mode 100644 include/hw/fsi/cfam.h
 create mode 100644 hw/fsi/cfam.c

diff --git a/include/hw/fsi/cfam.h b/include/hw/fsi/cfam.h
new file mode 100644
index ..7abc3b287bef
--- /dev/null
+++ b/include/hw/fsi/cfam.h
@@ -0,0 +1,34 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright (C) 2024 IBM Corp.
+ *
+ * IBM Common FRU Access Macro
+ */
+#ifndef FSI_CFAM_H
+#define FSI_CFAM_H
+
+#include "exec/memory.h"
+
+#include "hw/fsi/fsi.h"
+#include "hw/fsi/lbus.h"
+
+#define TYPE_FSI_CFAM "cfam"
+#define FSI_CFAM(obj) OBJECT_CHECK(FSICFAMState, (obj), TYPE_FSI_CFAM)
+
+/* P9-ism */
+#define CFAM_CONFIG_NR_REGS 0x28
+
+typedef struct FSICFAMState {
+/* < private > */
+FSISlaveState parent;
+
+/* CFAM config address space */
+MemoryRegion config_iomem;
+
+MemoryRegion mr;
+
+FSILBus lbus;
+FSIScratchPad scratchpad;
+} FSICFAMState;
+
+#endif /* FSI_CFAM_H */
diff --git a/hw/fsi/cfam.c b/hw/fsi/cfam.c
new file mode 100644
index ..c62f0f78dee5
--- /dev/null
+++ b/hw/fsi/cfam.c
@@ -0,0 +1,168 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright (C) 2024 IBM Corp.
+ *
+ * IBM Common FRU Access Macro
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/units.h"
+
+#include "qapi/error.h"
+#include "trace.h"
+
+#include "hw/fsi/cfam.h"
+#include "hw/fsi/fsi.h"
+
+#include "hw/qdev-properties.h"
+
+#define ENGINE_CONFIG_NEXTBIT(31)
+#define ENGINE_CONFIG_TYPE_PEEK   (0x02 << 4)
+#define ENGINE_CONFIG_TYPE_FSI(0x03 << 4)
+#define ENGINE_CONFIG_TYPE_SCRATCHPAD (0x06 << 4)
+
+/* Valid, slots, version, type, crc */
+#define CFAM_CONFIG_REG(__VER, __TYPE, __CRC)   \
+(ENGINE_CONFIG_NEXT   |   \
+ 0x0001   |   \
+ (__VER)  |   \
+ (__TYPE) |   \
+ (__CRC))
+
+#define TO_REG(x)  ((x) >> 2)
+
+#define CFAM_CONFIG_CHIP_IDTO_REG(0x00)
+#define CFAM_CONFIG_PEEK_STATUSTO_REG(0x04)
+#define CFAM_CONFIG_CHIP_ID_P9 0xc0022d15
+#define CFAM_CONFIG_CHIP_ID_BREAK  0xc0de
+
+static uint64_t fsi_cfam_config_read(void *opaque, hwaddr addr, unsigned size)
+{
+trace_fsi_cfam_config_read(addr, size);
+
+switch (addr) {
+case 0x00:
+return CFAM_CONFIG_CHIP_ID_P9;
+case 0x04:
+return CFAM_CONFIG_REG(0x1000, ENGINE_CONFIG_TYPE_PEEK, 0xc);
+case 0x08:
+return CFAM_CONFIG_REG(0x5000, ENGINE_CONFIG_TYPE_FSI, 0xa);
+case 0xc:
+return CFAM_CONFIG_REG(0x1000, ENGINE_CONFIG_TYPE_SCRATCHPAD, 0x7);
+default:
+/*
+ * The config table contains different engines from 0xc onwards.
+ * The scratch pad is already added at address 0xc. We need to add
+ * future engines from address 0x10 onwards. Returning 0 as engine
+ * is not implemented.
+ */
+return 0;
+}
+}
+
+static void fsi_cfam_config_write(void *opaque, hwaddr addr, uint64_t data,
+  unsigned size)
+{
+FSICFAMState *cfam = FSI_CFAM(opaque);
+
+trace_fsi_cfam_config_write(addr, size, data);
+
+switch (TO_REG(addr)) {
+case CFAM_CONFIG_CHIP_ID:
+case CFAM_CONFIG_PEEK_STATUS:
+if (data == CFAM_CONFIG_CHIP_ID_BREAK) {
+bus_cold_reset(BUS(>lbus));
+}
+break;
+default:
+trace_fsi_cfam_config_write_noaddr(addr, size, data);
+}
+}
+
+static const struct MemoryRegionOps cfam_config_ops = {
+.read = fsi_cfam_config_read,
+.write = fsi_cfam_config_write,
+.valid.max_access_size = 4,
+.valid.min_access_size = 4,
+.impl.max_access_size = 4,
+.impl.min_access_size = 4,
+.endianness = DEVICE_BIG_ENDIAN,
+};
+
+static uint64_t fsi_cfam_unimplemented_read(void *opaque, hwaddr addr,
+unsign

[PULL 15/17] hw/fsi: Added qtest

2024-01-26 Thread Cédric Le Goater
From: Ninad Palsule 

Added basic qtests for FSI model.

Signed-off-by: Ninad Palsule 
Acked-by: Thomas Huth 
Signed-off-by: Cédric Le Goater 
---
 tests/qtest/aspeed-fsi-test.c | 205 ++
 tests/qtest/meson.build   |   1 +
 2 files changed, 206 insertions(+)
 create mode 100644 tests/qtest/aspeed-fsi-test.c

diff --git a/tests/qtest/aspeed-fsi-test.c b/tests/qtest/aspeed-fsi-test.c
new file mode 100644
index ..b3020dd82118
--- /dev/null
+++ b/tests/qtest/aspeed-fsi-test.c
@@ -0,0 +1,205 @@
+/*
+ * QTest testcases for IBM's Flexible Service Interface (FSI)
+ *
+ * Copyright (c) 2023 IBM Corporation
+ *
+ * Authors:
+ *   Ninad Palsule 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include 
+
+#include "qemu/module.h"
+#include "libqtest-single.h"
+
+/* Registers from ast2600 specifications */
+#define ASPEED_FSI_ENGINER_TRIGGER   0x04
+#define ASPEED_FSI_OPB0_BUS_SELECT   0x10
+#define ASPEED_FSI_OPB1_BUS_SELECT   0x28
+#define ASPEED_FSI_OPB0_RW_DIRECTION 0x14
+#define ASPEED_FSI_OPB1_RW_DIRECTION 0x2c
+#define ASPEED_FSI_OPB0_XFER_SIZE0x18
+#define ASPEED_FSI_OPB1_XFER_SIZE0x30
+#define ASPEED_FSI_OPB0_BUS_ADDR 0x1c
+#define ASPEED_FSI_OPB1_BUS_ADDR 0x34
+#define ASPEED_FSI_INTRRUPT_CLEAR0x40
+#define ASPEED_FSI_INTRRUPT_STATUS   0x48
+#define ASPEED_FSI_OPB0_BUS_STATUS   0x80
+#define ASPEED_FSI_OPB1_BUS_STATUS   0x8c
+#define ASPEED_FSI_OPB0_READ_DATA0x84
+#define ASPEED_FSI_OPB1_READ_DATA0x90
+
+/*
+ * FSI Base addresses from the ast2600 specifications.
+ */
+#define AST2600_OPB_FSI0_BASE_ADDR 0x1e79b000
+#define AST2600_OPB_FSI1_BASE_ADDR 0x1e79b100
+
+static uint32_t aspeed_fsi_base_addr;
+
+static uint32_t aspeed_fsi_readl(QTestState *s, uint32_t reg)
+{
+return qtest_readl(s, aspeed_fsi_base_addr + reg);
+}
+
+static void aspeed_fsi_writel(QTestState *s, uint32_t reg, uint32_t val)
+{
+qtest_writel(s, aspeed_fsi_base_addr + reg, val);
+}
+
+/* Setup base address and select register */
+static void test_fsi_setup(QTestState *s, uint32_t base_addr)
+{
+uint32_t curval;
+
+aspeed_fsi_base_addr = base_addr;
+
+/* Set the base select register */
+if (base_addr == AST2600_OPB_FSI0_BASE_ADDR) {
+/* Unselect FSI1 */
+aspeed_fsi_writel(s, ASPEED_FSI_OPB1_BUS_SELECT, 0x0);
+curval = aspeed_fsi_readl(s, ASPEED_FSI_OPB1_BUS_SELECT);
+g_assert_cmpuint(curval, ==, 0x0);
+
+/* Select FSI0 */
+aspeed_fsi_writel(s, ASPEED_FSI_OPB0_BUS_SELECT, 0x1);
+curval = aspeed_fsi_readl(s, ASPEED_FSI_OPB0_BUS_SELECT);
+g_assert_cmpuint(curval, ==, 0x1);
+} else if (base_addr == AST2600_OPB_FSI1_BASE_ADDR) {
+/* Unselect FSI0 */
+aspeed_fsi_writel(s, ASPEED_FSI_OPB0_BUS_SELECT, 0x0);
+curval = aspeed_fsi_readl(s, ASPEED_FSI_OPB0_BUS_SELECT);
+g_assert_cmpuint(curval, ==, 0x0);
+
+/* Select FSI1 */
+aspeed_fsi_writel(s, ASPEED_FSI_OPB1_BUS_SELECT, 0x1);
+curval = aspeed_fsi_readl(s, ASPEED_FSI_OPB1_BUS_SELECT);
+g_assert_cmpuint(curval, ==, 0x1);
+} else {
+g_assert_not_reached();
+}
+}
+
+static void test_fsi_reg_change(QTestState *s, uint32_t reg, uint32_t newval)
+{
+uint32_t base;
+uint32_t curval;
+
+base = aspeed_fsi_readl(s, reg);
+aspeed_fsi_writel(s, reg, newval);
+curval = aspeed_fsi_readl(s, reg);
+g_assert_cmpuint(curval, ==, newval);
+aspeed_fsi_writel(s, reg, base);
+curval = aspeed_fsi_readl(s, reg);
+g_assert_cmpuint(curval, ==, base);
+}
+
+static void test_fsi0_master_regs(const void *data)
+{
+QTestState *s = (QTestState *)data;
+
+test_fsi_setup(s, AST2600_OPB_FSI0_BASE_ADDR);
+
+test_fsi_reg_change(s, ASPEED_FSI_OPB0_RW_DIRECTION, 0xF3F4F514);
+test_fsi_reg_change(s, ASPEED_FSI_OPB0_XFER_SIZE, 0xF3F4F518);
+test_fsi_reg_change(s, ASPEED_FSI_OPB0_BUS_ADDR, 0xF3F4F51c);
+test_fsi_reg_change(s, ASPEED_FSI_INTRRUPT_CLEAR, 0xF3F4F540);
+test_fsi_reg_change(s, ASPEED_FSI_INTRRUPT_STATUS, 0xF3F4F548);
+test_fsi_reg_change(s, ASPEED_FSI_OPB0_BUS_STATUS, 0xF3F4F580);
+test_fsi_reg_change(s, ASPEED_FSI_OPB0_READ_DATA, 0xF3F4F584);
+}
+
+static void test_fsi1_master_regs(const void *data)
+{
+QTestState *s = (QTestState *)data;
+
+test_fsi_setup(s, AST2600_OPB_FSI1_BASE_ADDR);
+
+test_fsi_reg_change(s, ASPEED_FSI_OPB1_RW_DIRECTION, 0xF3F4F514);
+test_fsi_reg_change(s, ASPEED_FSI_OPB1_XFER_SIZE, 0xF3F4F518);
+test_fsi_reg_change(s, ASPEED_FSI_OPB1_BUS_ADDR, 0xF3F4F51c);
+test_fsi_reg_change(s, ASPEED_FSI_INTRRUPT_CLEAR, 0xF3F4F540);
+test_fsi_reg_change(s, ASPEED_FSI_INTRRUPT_STATUS, 0xF3F4F548);
+test_fsi_reg_change(s, ASPEED_FSI_OPB1_BUS_STATUS, 0xF3F4F580);
+test_fsi_reg_change(s, ASPEED_FSI_OPB1_READ_DATA, 

[PULL 06/17] hw/arm/aspeed: Check for CPU types in machine_run_board_init()

2024-01-26 Thread Cédric Le Goater
From: Philippe Mathieu-Daudé 

Aspeed SoCs use a single CPU type (set as AspeedSoCClass::cpu_type).
Convert it to a NULL-terminated array (of a single non-NULL element).

Set MachineClass::valid_cpu_types[] to use the common machine code
to provide hints when the requested CPU is invalid (see commit
e702cbc19e ("machine: Improve is_cpu_type_supported()").

Reviewed-by: Cédric Le Goater 
Reviewed-by: Richard Henderson 
Reviewed-by: Gavin Shan 
Signed-off-by: Philippe Mathieu-Daudé 
Signed-off-by: Cédric Le Goater 
---
 include/hw/arm/aspeed_soc.h |  3 ++-
 hw/arm/aspeed.c |  1 +
 hw/arm/aspeed_ast10x0.c |  6 +-
 hw/arm/aspeed_ast2400.c | 12 ++--
 hw/arm/aspeed_ast2600.c |  6 +-
 hw/arm/aspeed_soc_common.c  |  5 -
 6 files changed, 27 insertions(+), 6 deletions(-)

diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h
index a060a5991874..0db5a41e7170 100644
--- a/include/hw/arm/aspeed_soc.h
+++ b/include/hw/arm/aspeed_soc.h
@@ -128,7 +128,8 @@ struct AspeedSoCClass {
 DeviceClass parent_class;
 
 const char *name;
-const char *cpu_type;
+/** valid_cpu_types: NULL terminated array of a single CPU type. */
+const char * const *valid_cpu_types;
 uint32_t silicon_rev;
 uint64_t sram_size;
 uint64_t secsram_size;
diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index d2d490a6d142..fc8355cdce14 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -1149,6 +1149,7 @@ static void 
aspeed_machine_class_init_cpus_defaults(MachineClass *mc)
 mc->default_cpus = sc->num_cpus;
 mc->min_cpus = sc->num_cpus;
 mc->max_cpus = sc->num_cpus;
+mc->valid_cpu_types = sc->valid_cpu_types;
 }
 
 static void aspeed_machine_class_init(ObjectClass *oc, void *data)
diff --git a/hw/arm/aspeed_ast10x0.c b/hw/arm/aspeed_ast10x0.c
index dca601a3f9b6..c3b5116a6a9d 100644
--- a/hw/arm/aspeed_ast10x0.c
+++ b/hw/arm/aspeed_ast10x0.c
@@ -417,13 +417,17 @@ static void aspeed_soc_ast1030_realize(DeviceState 
*dev_soc, Error **errp)
 
 static void aspeed_soc_ast1030_class_init(ObjectClass *klass, void *data)
 {
+static const char * const valid_cpu_types[] = {
+ARM_CPU_TYPE_NAME("cortex-m4"), /* TODO cortex-m4f */
+NULL
+};
 DeviceClass *dc = DEVICE_CLASS(klass);
 AspeedSoCClass *sc = ASPEED_SOC_CLASS(dc);
 
 dc->realize = aspeed_soc_ast1030_realize;
 
 sc->name = "ast1030-a1";
-sc->cpu_type = ARM_CPU_TYPE_NAME("cortex-m4"); /* TODO cortex-m4f */
+sc->valid_cpu_types = valid_cpu_types;
 sc->silicon_rev = AST1030_A1_SILICON_REV;
 sc->sram_size = 0xc;
 sc->secsram_size = 0x4; /* 256 * KiB */
diff --git a/hw/arm/aspeed_ast2400.c b/hw/arm/aspeed_ast2400.c
index 789e591f3ad0..c613e58144dd 100644
--- a/hw/arm/aspeed_ast2400.c
+++ b/hw/arm/aspeed_ast2400.c
@@ -502,6 +502,10 @@ static void aspeed_ast2400_soc_realize(DeviceState *dev, 
Error **errp)
 
 static void aspeed_soc_ast2400_class_init(ObjectClass *oc, void *data)
 {
+static const char * const valid_cpu_types[] = {
+ARM_CPU_TYPE_NAME("arm926"),
+NULL
+};
 AspeedSoCClass *sc = ASPEED_SOC_CLASS(oc);
 DeviceClass *dc = DEVICE_CLASS(oc);
 
@@ -510,7 +514,7 @@ static void aspeed_soc_ast2400_class_init(ObjectClass *oc, 
void *data)
 dc->user_creatable = false;
 
 sc->name = "ast2400-a1";
-sc->cpu_type = ARM_CPU_TYPE_NAME("arm926");
+sc->valid_cpu_types = valid_cpu_types;
 sc->silicon_rev  = AST2400_A1_SILICON_REV;
 sc->sram_size= 0x8000;
 sc->spis_num = 1;
@@ -526,6 +530,10 @@ static void aspeed_soc_ast2400_class_init(ObjectClass *oc, 
void *data)
 
 static void aspeed_soc_ast2500_class_init(ObjectClass *oc, void *data)
 {
+static const char * const valid_cpu_types[] = {
+ARM_CPU_TYPE_NAME("arm1176"),
+NULL
+};
 AspeedSoCClass *sc = ASPEED_SOC_CLASS(oc);
 DeviceClass *dc = DEVICE_CLASS(oc);
 
@@ -534,7 +542,7 @@ static void aspeed_soc_ast2500_class_init(ObjectClass *oc, 
void *data)
 dc->user_creatable = false;
 
 sc->name = "ast2500-a1";
-sc->cpu_type = ARM_CPU_TYPE_NAME("arm1176");
+sc->valid_cpu_types = valid_cpu_types;
 sc->silicon_rev  = AST2500_A1_SILICON_REV;
 sc->sram_size= 0x9000;
 sc->spis_num = 2;
diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c
index 589a4a6eea10..24541b5284d4 100644
--- a/hw/arm/aspeed_ast2600.c
+++ b/hw/arm/aspeed_ast2600.c
@@ -628,13 +628,17 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, 
Error **errp)
 
 static void aspeed_soc_ast2600_class_init(ObjectClass *oc, void *data)
 {
+static const char * const valid_cpu_types[] = {
+ARM_CPU_TYPE_NAME("cortex-a7"),
+NULL
+};
 DeviceClass *dc = DEVI

[PULL 02/17] hw/arm/aspeed: Remove dead code

2024-01-26 Thread Cédric Le Goater
From: Philippe Mathieu-Daudé 

Remove copy/paste typo from commit 6c323aba40 ("hw/arm/aspeed:
Adding new machine Tiogapass in QEMU").

Signed-off-by: Philippe Mathieu-Daudé 
Reviewed-by: Cédric Le Goater 
Reviewed-by: Richard Henderson 
Reviewed-by: Gavin Shan 
Signed-off-by: Cédric Le Goater 
---
 hw/arm/aspeed.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index cc59176563a8..4bc292ff84fc 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -1301,7 +1301,6 @@ static void 
aspeed_machine_tiogapass_class_init(ObjectClass *oc, void *data)
 mc->default_ram_size   = 1 * GiB;
 mc->default_cpus = mc->min_cpus = mc->max_cpus =
 aspeed_soc_num_cpus(amc->soc_name);
-aspeed_soc_num_cpus(amc->soc_name);
 };
 
 static void aspeed_machine_sonorapass_class_init(ObjectClass *oc, void *data)
-- 
2.43.0




[PULL 14/17] hw/arm: Hook up FSI module in AST2600

2024-01-26 Thread Cédric Le Goater
From: Ninad Palsule 

This patchset introduces IBM's Flexible Service Interface(FSI).

Time for some fun with inter-processor buses. FSI allows a service
processor access to the internal buses of a host POWER processor to
perform configuration or debugging.

FSI has long existed in POWER processes and so comes with some baggage,
including how it has been integrated into the ASPEED SoC.

Working backwards from the POWER processor, the fundamental pieces of
interest for the implementation are:

1. The Common FRU Access Macro (CFAM), an address space containing
   various "engines" that drive accesses on buses internal and external
   to the POWER chip. Examples include the SBEFIFO and I2C masters. The
   engines hang off of an internal Local Bus (LBUS) which is described
   by the CFAM configuration block.

2. The FSI slave: The slave is the terminal point of the FSI bus for
   FSI symbols addressed to it. Slaves can be cascaded off of one
   another. The slave's configuration registers appear in address space
   of the CFAM to which it is attached.

3. The FSI master: A controller in the platform service processor (e.g.
   BMC) driving CFAM engine accesses into the POWER chip. At the
   hardware level FSI is a bit-based protocol supporting synchronous and
   DMA-driven accesses of engines in a CFAM.

4. The On-Chip Peripheral Bus (OPB): A low-speed bus typically found in
   POWER processors. This now makes an appearance in the ASPEED SoC due
   to tight integration of the FSI master IP with the OPB, mainly the
   existence of an MMIO-mapping of the CFAM address straight onto a
   sub-region of the OPB address space.

5. An APB-to-OPB bridge enabling access to the OPB from the ARM core in
   the AST2600. Hardware limitations prevent the OPB from being directly
   mapped into APB, so all accesses are indirect through the bridge.

The implementation appears as following in the qemu device tree:

(qemu) info qtree
bus: main-system-bus
  type System
  ...
  dev: aspeed.apb2opb, id ""
gpio-out "sysbus-irq" 1
mmio 1e79b000/1000
bus: opb.1
  type opb
  dev: fsi.master, id ""
bus: fsi.bus.1
  type fsi.bus
  dev: cfam.config, id ""
  dev: cfam, id ""
bus: fsi.lbus.1
  type lbus
  dev: scratchpad, id ""
address = 0 (0x0)
bus: opb.0
  type opb
  dev: fsi.master, id ""
bus: fsi.bus.0
  type fsi.bus
  dev: cfam.config, id ""
  dev: cfam, id ""
bus: fsi.lbus.0
  type lbus
  dev: scratchpad, id ""
address = 0 (0x0)

The LBUS is modelled to maintain the qdev bus hierarchy and to take
advantage of the object model to automatically generate the CFAM
configuration block. The configuration block presents engines in the
order they are attached to the CFAM's LBUS. Engine implementations
should subclass the LBusDevice and set the 'config' member of
LBusDeviceClass to match the engine's type.

CFAM designs offer a lot of flexibility, for instance it is possible for
a CFAM to be simultaneously driven from multiple FSI links. The modeling
is not so complete; it's assumed that each CFAM is attached to a single
FSI slave (as a consequence the CFAM subclasses the FSI slave).

As for FSI, its symbols and wire-protocol are not modelled at all. This
is not necessary to get FSI off the ground thanks to the mapping of the
CFAM address space onto the OPB address space - the models follow this
directly and map the CFAM memory region into the OPB's memory region.
Future work includes supporting more advanced accesses that drive the
FSI master directly rather than indirectly via the CFAM mapping, which
will require implementing the FSI state machine and methods for each of
the FSI symbols on the slave. Further down the track we can also look at
supporting the bitbanged SoftFSI drivers in Linux by extending the FSI
slave model to resolve sequences of GPIO IRQs into FSI symbols, and
calling the associated symbol method on the slave to map the access onto
the CFAM.

Testing:
Tested by reading cfam config address 0 on rainier machine type.

root@p10bmc:~# pdbg -a getcfam 0x0
p0: 0x0 = 0xc0022d15

Signed-off-by: Andrew Jeffery 
Signed-off-by: Ninad Palsule 
Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Cédric Le Goater 
Signed-off-by: Cédric Le Goater 
---
 include/hw/arm/aspeed_soc.h |  4 
 hw/arm/aspeed_ast2600.c | 19 +++
 2 files changed, 23 insertions(+)

diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h
index 0db5a41e7170..9d0af84a8cff 100644
--- a/include/hw/arm/aspeed_soc.h
+++ b/include/hw/arm/aspeed_soc.h
@@ -36,6 +36,7 @@
 #include "hw/

[PULL 05/17] hw/arm/aspeed: Introduce aspeed_soc_cpu_type() helper

2024-01-26 Thread Cédric Le Goater
From: Philippe Mathieu-Daudé 

In order to alter AspeedSoCClass::cpu_type in the next
commit, introduce the aspeed_soc_cpu_type() helper to
retrieve the per-SoC CPU type from AspeedSoCClass.

Signed-off-by: Philippe Mathieu-Daudé 
Reviewed-by: Cédric Le Goater 
Reviewed-by: Richard Henderson 
Reviewed-by: Gavin Shan 
Signed-off-by: Cédric Le Goater 
---
 include/hw/arm/aspeed_soc.h | 1 +
 hw/arm/aspeed_ast10x0.c | 2 +-
 hw/arm/aspeed_ast2400.c | 3 ++-
 hw/arm/aspeed_ast2600.c | 3 ++-
 hw/arm/aspeed_soc_common.c  | 5 +
 5 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h
index cb832bc1ee14..a060a5991874 100644
--- a/include/hw/arm/aspeed_soc.h
+++ b/include/hw/arm/aspeed_soc.h
@@ -143,6 +143,7 @@ struct AspeedSoCClass {
 qemu_irq (*get_irq)(AspeedSoCState *s, int dev);
 };
 
+const char *aspeed_soc_cpu_type(AspeedSoCClass *sc);
 
 enum {
 ASPEED_DEV_SPI_BOOT,
diff --git a/hw/arm/aspeed_ast10x0.c b/hw/arm/aspeed_ast10x0.c
index 8becb146a8df..dca601a3f9b6 100644
--- a/hw/arm/aspeed_ast10x0.c
+++ b/hw/arm/aspeed_ast10x0.c
@@ -211,7 +211,7 @@ static void aspeed_soc_ast1030_realize(DeviceState 
*dev_soc, Error **errp)
 /* AST1030 CPU Core */
 armv7m = DEVICE(>armv7m);
 qdev_prop_set_uint32(armv7m, "num-irq", 256);
-qdev_prop_set_string(armv7m, "cpu-type", sc->cpu_type);
+qdev_prop_set_string(armv7m, "cpu-type", aspeed_soc_cpu_type(sc));
 qdev_connect_clock_in(armv7m, "cpuclk", s->sysclk);
 object_property_set_link(OBJECT(>armv7m), "memory",
  OBJECT(s->memory), _abort);
diff --git a/hw/arm/aspeed_ast2400.c b/hw/arm/aspeed_ast2400.c
index 0baa2ff96e46..789e591f3ad0 100644
--- a/hw/arm/aspeed_ast2400.c
+++ b/hw/arm/aspeed_ast2400.c
@@ -155,7 +155,8 @@ static void aspeed_ast2400_soc_init(Object *obj)
 }
 
 for (i = 0; i < sc->num_cpus; i++) {
-object_initialize_child(obj, "cpu[*]", >cpu[i], sc->cpu_type);
+object_initialize_child(obj, "cpu[*]", >cpu[i],
+aspeed_soc_cpu_type(sc));
 }
 
 snprintf(typename, sizeof(typename), "aspeed.scu-%s", socname);
diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c
index 3a9a303ab8ba..589a4a6eea10 100644
--- a/hw/arm/aspeed_ast2600.c
+++ b/hw/arm/aspeed_ast2600.c
@@ -157,7 +157,8 @@ static void aspeed_soc_ast2600_init(Object *obj)
 }
 
 for (i = 0; i < sc->num_cpus; i++) {
-object_initialize_child(obj, "cpu[*]", >cpu[i], sc->cpu_type);
+object_initialize_child(obj, "cpu[*]", >cpu[i],
+aspeed_soc_cpu_type(sc));
 }
 
 snprintf(typename, sizeof(typename), "aspeed.scu-%s", socname);
diff --git a/hw/arm/aspeed_soc_common.c b/hw/arm/aspeed_soc_common.c
index 828f61093bfa..36ca189ce960 100644
--- a/hw/arm/aspeed_soc_common.c
+++ b/hw/arm/aspeed_soc_common.c
@@ -18,6 +18,11 @@
 #include "hw/char/serial.h"
 
 
+const char *aspeed_soc_cpu_type(AspeedSoCClass *sc)
+{
+return sc->cpu_type;
+}
+
 qemu_irq aspeed_soc_get_irq(AspeedSoCState *s, int dev)
 {
 return ASPEED_SOC_GET_CLASS(s)->get_irq(s, dev);
-- 
2.43.0




[PULL 09/17] hw/fsi: Introduce IBM's FSI Bus

2024-01-26 Thread Cédric Le Goater
From: Ninad Palsule 

This is a part of patchset where FSI bus is introduced.

The FSI bus is a simple bus where FSI master is attached.

Signed-off-by: Andrew Jeffery 
Signed-off-by: Ninad Palsule 
Reviewed-by: Cédric Le Goater 
[ clg: - removed include/hw/fsi/engine-scratchpad.h and
 hw/fsi/engine-scratchpad.c
   - dropped FSI_SCRATCHPAD
   - included FSIBus definition
   - dropped hw/fsi/trace-events changes ]
Signed-off-by: Cédric Le Goater 
---
 include/hw/fsi/fsi.h | 19 +++
 hw/fsi/fsi.c | 22 ++
 hw/fsi/meson.build   |  2 +-
 3 files changed, 42 insertions(+), 1 deletion(-)
 create mode 100644 include/hw/fsi/fsi.h
 create mode 100644 hw/fsi/fsi.c

diff --git a/include/hw/fsi/fsi.h b/include/hw/fsi/fsi.h
new file mode 100644
index ..50e8f5c888f1
--- /dev/null
+++ b/include/hw/fsi/fsi.h
@@ -0,0 +1,19 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright (C) 2024 IBM Corp.
+ *
+ * IBM Flexible Service Interface
+ */
+#ifndef FSI_FSI_H
+#define FSI_FSI_H
+
+#include "hw/qdev-core.h"
+
+#define TYPE_FSI_BUS "fsi.bus"
+OBJECT_DECLARE_SIMPLE_TYPE(FSIBus, FSI_BUS)
+
+typedef struct FSIBus {
+BusState bus;
+} FSIBus;
+
+#endif /* FSI_FSI_H */
diff --git a/hw/fsi/fsi.c b/hw/fsi/fsi.c
new file mode 100644
index ..60cb03f7a24e
--- /dev/null
+++ b/hw/fsi/fsi.c
@@ -0,0 +1,22 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright (C) 2024 IBM Corp.
+ *
+ * IBM Flexible Service Interface
+ */
+#include "qemu/osdep.h"
+
+#include "hw/fsi/fsi.h"
+
+static const TypeInfo fsi_bus_info = {
+.name = TYPE_FSI_BUS,
+.parent = TYPE_BUS,
+.instance_size = sizeof(FSIBus),
+};
+
+static void fsi_bus_register_types(void)
+{
+type_register_static(_bus_info);
+}
+
+type_init(fsi_bus_register_types);
diff --git a/hw/fsi/meson.build b/hw/fsi/meson.build
index 93ba19dd0411..574f5f928903 100644
--- a/hw/fsi/meson.build
+++ b/hw/fsi/meson.build
@@ -1 +1 @@
-system_ss.add(when: 'CONFIG_FSI', if_true: files('lbus.c'))
+system_ss.add(when: 'CONFIG_FSI', if_true: files('lbus.c','fsi.c'))
-- 
2.43.0




[PULL 04/17] hw/arm/aspeed: Init CPU defaults in a common helper

2024-01-26 Thread Cédric Le Goater
From: Philippe Mathieu-Daudé 

Rework aspeed_soc_num_cpus() as a new init_cpus_defaults()
helper to reduce code duplication.

Reviewed-by: Cédric Le Goater 
Reviewed-by: Richard Henderson 
Reviewed-by: Gavin Shan 
Signed-off-by: Philippe Mathieu-Daudé 
Signed-off-by: Cédric Le Goater 
---
 hw/arm/aspeed.c | 71 +++--
 1 file changed, 28 insertions(+), 43 deletions(-)

diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index 5b01a4dd28f8..d2d490a6d142 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -1141,10 +1141,14 @@ static void aspeed_machine_class_props_init(ObjectClass 
*oc)
   "Change the SPI Flash model");
 }
 
-static int aspeed_soc_num_cpus(const char *soc_name)
+static void aspeed_machine_class_init_cpus_defaults(MachineClass *mc)
 {
-   AspeedSoCClass *sc = ASPEED_SOC_CLASS(object_class_by_name(soc_name));
-   return sc->num_cpus;
+AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(mc);
+AspeedSoCClass *sc = ASPEED_SOC_CLASS(object_class_by_name(amc->soc_name));
+
+mc->default_cpus = sc->num_cpus;
+mc->min_cpus = sc->num_cpus;
+mc->max_cpus = sc->num_cpus;
 }
 
 static void aspeed_machine_class_init(ObjectClass *oc, void *data)
@@ -1176,8 +1180,7 @@ static void 
aspeed_machine_palmetto_class_init(ObjectClass *oc, void *data)
 amc->num_cs= 1;
 amc->i2c_init  = palmetto_bmc_i2c_init;
 mc->default_ram_size   = 256 * MiB;
-mc->default_cpus = mc->min_cpus = mc->max_cpus =
-aspeed_soc_num_cpus(amc->soc_name);
+aspeed_machine_class_init_cpus_defaults(mc);
 };
 
 static void aspeed_machine_quanta_q71l_class_init(ObjectClass *oc, void *data)
@@ -1193,8 +1196,7 @@ static void 
aspeed_machine_quanta_q71l_class_init(ObjectClass *oc, void *data)
 amc->num_cs= 1;
 amc->i2c_init  = quanta_q71l_bmc_i2c_init;
 mc->default_ram_size   = 128 * MiB;
-mc->default_cpus = mc->min_cpus = mc->max_cpus =
-aspeed_soc_num_cpus(amc->soc_name);
+aspeed_machine_class_init_cpus_defaults(mc);
 }
 
 static void aspeed_machine_supermicrox11_bmc_class_init(ObjectClass *oc,
@@ -1212,8 +1214,7 @@ static void 
aspeed_machine_supermicrox11_bmc_class_init(ObjectClass *oc,
 amc->macs_mask = ASPEED_MAC0_ON | ASPEED_MAC1_ON;
 amc->i2c_init  = palmetto_bmc_i2c_init;
 mc->default_ram_size = 256 * MiB;
-mc->default_cpus = mc->min_cpus = mc->max_cpus =
-aspeed_soc_num_cpus(amc->soc_name);
+aspeed_machine_class_init_cpus_defaults(mc);
 }
 
 static void aspeed_machine_supermicro_x11spi_bmc_class_init(ObjectClass *oc,
@@ -1231,8 +1232,7 @@ static void 
aspeed_machine_supermicro_x11spi_bmc_class_init(ObjectClass *oc,
 amc->macs_mask = ASPEED_MAC0_ON | ASPEED_MAC1_ON;
 amc->i2c_init  = palmetto_bmc_i2c_init;
 mc->default_ram_size = 512 * MiB;
-mc->default_cpus = mc->min_cpus = mc->max_cpus =
-aspeed_soc_num_cpus(amc->soc_name);
+aspeed_machine_class_init_cpus_defaults(mc);
 }
 
 static void aspeed_machine_ast2500_evb_class_init(ObjectClass *oc, void *data)
@@ -1248,8 +1248,7 @@ static void 
aspeed_machine_ast2500_evb_class_init(ObjectClass *oc, void *data)
 amc->num_cs= 1;
 amc->i2c_init  = ast2500_evb_i2c_init;
 mc->default_ram_size   = 512 * MiB;
-mc->default_cpus = mc->min_cpus = mc->max_cpus =
-aspeed_soc_num_cpus(amc->soc_name);
+aspeed_machine_class_init_cpus_defaults(mc);
 };
 
 static void aspeed_machine_yosemitev2_class_init(ObjectClass *oc, void *data)
@@ -1266,8 +1265,7 @@ static void 
aspeed_machine_yosemitev2_class_init(ObjectClass *oc, void *data)
 amc->num_cs= 2;
 amc->i2c_init  = yosemitev2_bmc_i2c_init;
 mc->default_ram_size   = 512 * MiB;
-mc->default_cpus = mc->min_cpus = mc->max_cpus =
-aspeed_soc_num_cpus(amc->soc_name);
+aspeed_machine_class_init_cpus_defaults(mc);
 };
 
 static void aspeed_machine_romulus_class_init(ObjectClass *oc, void *data)
@@ -1283,8 +1281,7 @@ static void aspeed_machine_romulus_class_init(ObjectClass 
*oc, void *data)
 amc->num_cs= 2;
 amc->i2c_init  = romulus_bmc_i2c_init;
 mc->default_ram_size   = 512 * MiB;
-mc->default_cpus = mc->min_cpus = mc->max_cpus =
-aspeed_soc_num_cpus(amc->soc_name);
+aspeed_machine_class_init_cpus_defaults(mc);
 };
 
 static void aspeed_machine_tiogapass_class_init(ObjectClass *oc, void *data)
@@ -1301,8 +1298,7 @@ static void 
aspeed_machine_tiogapass_class_init(ObjectClass *oc, void *data)
 amc->num_cs= 2;
 amc->i2c_init  = tiogapass_bmc_i2c_init;
 mc->default_ram_size   = 1 * GiB;
-mc->default_cpus = mc->min_cpus = mc->max_cpus =
-aspeed_soc_num_cpus(amc->soc_name);
+aspeed_machine_class_init_cpus_defaul

[PULL 03/17] hw/arm/aspeed: Set default CPU count using aspeed_soc_num_cpus()

2024-01-26 Thread Cédric Le Goater
From: Philippe Mathieu-Daudé 

Since commit b7f1a0cb76 ("arm/aspeed: Compute the number
of CPUs from the SoC definition") Aspeed machines use the
aspeed_soc_num_cpus() helper to set the number of CPUs.

Use it for the ast1030-evb (commit 356b230ed1 "aspeed/soc:
Add AST1030 support") and supermicrox11-bmc (commit 40a38df55e
"hw/arm/aspeed: Add board model for Supermicro X11 BMC") machines.

Signed-off-by: Philippe Mathieu-Daudé 
Reviewed-by: Cédric Le Goater 
Reviewed-by: Gavin Shan 
Signed-off-by: Cédric Le Goater 
---
 hw/arm/aspeed.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index 4bc292ff84fc..5b01a4dd28f8 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -1212,6 +1212,8 @@ static void 
aspeed_machine_supermicrox11_bmc_class_init(ObjectClass *oc,
 amc->macs_mask = ASPEED_MAC0_ON | ASPEED_MAC1_ON;
 amc->i2c_init  = palmetto_bmc_i2c_init;
 mc->default_ram_size = 256 * MiB;
+mc->default_cpus = mc->min_cpus = mc->max_cpus =
+aspeed_soc_num_cpus(amc->soc_name);
 }
 
 static void aspeed_machine_supermicro_x11spi_bmc_class_init(ObjectClass *oc,
@@ -1586,11 +1588,12 @@ static void 
aspeed_minibmc_machine_ast1030_evb_class_init(ObjectClass *oc,
 mc->init = aspeed_minibmc_machine_init;
 amc->i2c_init = ast1030_evb_i2c_init;
 mc->default_ram_size = 0;
-mc->default_cpus = mc->min_cpus = mc->max_cpus = 1;
 amc->fmc_model = "sst25vf032b";
 amc->spi_model = "sst25vf032b";
 amc->num_cs = 2;
 amc->macs_mask = 0;
+mc->default_cpus = mc->min_cpus = mc->max_cpus =
+aspeed_soc_num_cpus(amc->soc_name);
 }
 
 static void aspeed_machine_qcom_dc_scm_v1_class_init(ObjectClass *oc,
-- 
2.43.0




[PULL 08/17] hw/fsi: Introduce IBM's scratchpad device

2024-01-26 Thread Cédric Le Goater
From: Ninad Palsule 

This is a part of patchset where IBM's Flexible Service Interface is
introduced.

The scratchpad provides a set of non-functional registers. The firmware
is free to use them, hardware does not support any special management
support. The scratchpad registers can be read or written from LBUS
slave. The scratch pad is managed under FSI CFAM state.

Signed-off-by: Andrew Jeffery 
Signed-off-by: Ninad Palsule 
Reviewed-by: Cédric Le Goater 
[ clg: - moved object FSIScratchPad under FSICFAMState
   - moved FSIScratchPad code under cfam.c ]
Signed-off-by: Cédric Le Goater 
---
 include/hw/fsi/lbus.h | 11 ++
 hw/fsi/lbus.c | 78 +--
 hw/fsi/trace-events   |  2 ++
 3 files changed, 89 insertions(+), 2 deletions(-)

diff --git a/include/hw/fsi/lbus.h b/include/hw/fsi/lbus.h
index e8a22e22a8fa..558268c013f5 100644
--- a/include/hw/fsi/lbus.h
+++ b/include/hw/fsi/lbus.h
@@ -29,4 +29,15 @@ typedef struct FSILBus {
 MemoryRegion mr;
 } FSILBus;
 
+#define TYPE_FSI_SCRATCHPAD "fsi.scratchpad"
+#define SCRATCHPAD(obj) OBJECT_CHECK(FSIScratchPad, (obj), TYPE_FSI_SCRATCHPAD)
+
+#define FSI_SCRATCHPAD_NR_REGS 4
+
+typedef struct FSIScratchPad {
+FSILBusDevice parent;
+
+uint32_t regs[FSI_SCRATCHPAD_NR_REGS];
+} FSIScratchPad;
+
 #endif /* FSI_LBUS_H */
diff --git a/hw/fsi/lbus.c b/hw/fsi/lbus.c
index 44d2319087a8..20495f42fd99 100644
--- a/hw/fsi/lbus.c
+++ b/hw/fsi/lbus.c
@@ -8,11 +8,12 @@
 #include "qemu/osdep.h"
 #include "qapi/error.h"
 #include "hw/fsi/lbus.h"
-
 #include "hw/qdev-properties.h"
-
+#include "qemu/log.h"
 #include "trace.h"
 
+#define TO_REG(offset) ((offset) >> 2)
+
 static void fsi_lbus_init(Object *o)
 {
 FSILBus *lbus = FSI_LBUS(o);
@@ -34,10 +35,83 @@ static const TypeInfo fsi_lbus_device_type_info = {
 .abstract = true,
 };
 
+static uint64_t fsi_scratchpad_read(void *opaque, hwaddr addr, unsigned size)
+{
+FSIScratchPad *s = SCRATCHPAD(opaque);
+int reg = TO_REG(addr);
+
+trace_fsi_scratchpad_read(addr, size);
+
+if (reg >= FSI_SCRATCHPAD_NR_REGS) {
+qemu_log_mask(LOG_GUEST_ERROR,
+  "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
+  __func__, addr);
+return 0;
+}
+
+return s->regs[reg];
+}
+
+static void fsi_scratchpad_write(void *opaque, hwaddr addr, uint64_t data,
+ unsigned size)
+{
+FSIScratchPad *s = SCRATCHPAD(opaque);
+
+trace_fsi_scratchpad_write(addr, size, data);
+int reg = TO_REG(addr);
+
+if (reg >= FSI_SCRATCHPAD_NR_REGS) {
+qemu_log_mask(LOG_GUEST_ERROR,
+  "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
+  __func__, addr);
+return;
+}
+
+s->regs[reg] = data;
+}
+
+static const struct MemoryRegionOps scratchpad_ops = {
+.read = fsi_scratchpad_read,
+.write = fsi_scratchpad_write,
+.endianness = DEVICE_BIG_ENDIAN,
+};
+
+static void fsi_scratchpad_realize(DeviceState *dev, Error **errp)
+{
+FSILBusDevice *ldev = FSI_LBUS_DEVICE(dev);
+
+memory_region_init_io(>iomem, OBJECT(ldev), _ops,
+  ldev, TYPE_FSI_SCRATCHPAD, 0x400);
+}
+
+static void fsi_scratchpad_reset(DeviceState *dev)
+{
+FSIScratchPad *s = SCRATCHPAD(dev);
+
+memset(s->regs, 0, sizeof(s->regs));
+}
+
+static void fsi_scratchpad_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+
+dc->bus_type = TYPE_FSI_LBUS;
+dc->realize = fsi_scratchpad_realize;
+dc->reset = fsi_scratchpad_reset;
+}
+
+static const TypeInfo fsi_scratchpad_info = {
+.name = TYPE_FSI_SCRATCHPAD,
+.parent = TYPE_FSI_LBUS_DEVICE,
+.instance_size = sizeof(FSIScratchPad),
+.class_init = fsi_scratchpad_class_init,
+};
+
 static void fsi_lbus_register_types(void)
 {
 type_register_static(_lbus_info);
 type_register_static(_lbus_device_type_info);
+type_register_static(_scratchpad_info);
 }
 
 type_init(fsi_lbus_register_types);
diff --git a/hw/fsi/trace-events b/hw/fsi/trace-events
index e69de29bb2d1..c5753e27910a 100644
--- a/hw/fsi/trace-events
+++ b/hw/fsi/trace-events
@@ -0,0 +1,2 @@
+fsi_scratchpad_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d"
+fsi_scratchpad_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" 
PRIx64 " size=%d value=0x%"PRIx64
-- 
2.43.0




[PULL 01/17] tests/avocado/machine_aspeed.py: Update buildroot images to 2023.11

2024-01-26 Thread Cédric Le Goater
Compared to mainline buildroot, these images have some customization :

- Linux version is bumped to 6.6.3 and built with a custom config
- U-Boot is switched to the one provided by OpenBMC for more support
- defconfigs extra tools for dev

See branch [1] for more details.

There are a few changes since last update, commit ed1f5ff84209. Images
all have a password now and I2C devices have been updated in the Linux
ast2600-evb device tree [2]. Do the necessary adjustements.

[1] https://github.com/legoater/buildroot/commits/aspeed-2023.11
[2] 
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=9deb10cf160e

Signed-off-by: Cédric Le Goater 
---
 tests/avocado/machine_aspeed.py | 18 +-
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/tests/avocado/machine_aspeed.py b/tests/avocado/machine_aspeed.py
index 6fa5459a07bf..cec018142453 100644
--- a/tests/avocado/machine_aspeed.py
+++ b/tests/avocado/machine_aspeed.py
@@ -155,6 +155,7 @@ def do_test_arm_aspeed_buildroot_start(self, image, cpu_id, 
pattern='Aspeed EVB'
 time.sleep(0.1)
 exec_command(self, 'root')
 time.sleep(0.1)
+exec_command(self, "passw0rd")
 
 def do_test_arm_aspeed_buildroot_poweroff(self):
 exec_command_and_wait_for_pattern(self, 'poweroff',
@@ -167,14 +168,14 @@ def test_arm_ast2500_evb_buildroot(self):
 """
 
 image_url = ('https://github.com/legoater/qemu-aspeed-boot/raw/master/'
- 
'images/ast2500-evb/buildroot-2022.11-2-g15d3648df9/flash.img')
-image_hash = 
('f96d11db521fe7a2787745e9e391225dc3318ee0fc07c8b799b8833dd474')
+ 'images/ast2500-evb/buildroot-2023.11/flash.img')
+image_hash = 
('c23db6160cf77d0258397eb2051162c8473a56c441417c52a91ba217186e715f')
 image_path = self.fetch_asset(image_url, asset_hash=image_hash,
   algorithm='sha256')
 
 self.vm.add_args('-device',
  
'tmp105,bus=aspeed.i2c.bus.3,address=0x4d,id=tmp-test');
-self.do_test_arm_aspeed_buildroot_start(image_path, '0x0')
+self.do_test_arm_aspeed_buildroot_start(image_path, '0x0', 'Aspeed 
AST2500 EVB')
 
 exec_command_and_wait_for_pattern(self,
  'echo lm75 0x4d > /sys/class/i2c-dev/i2c-3/device/new_device',
@@ -195,8 +196,8 @@ def test_arm_ast2600_evb_buildroot(self):
 """
 
 image_url = ('https://github.com/legoater/qemu-aspeed-boot/raw/master/'
- 
'images/ast2600-evb/buildroot-2022.11-2-g15d3648df9/flash.img')
-image_hash = 
('e598d86e5ea79671ca8b59212a326c911bc8bea728dec1a1f5390d717a28bb8b')
+ 'images/ast2600-evb/buildroot-2023.11/flash.img')
+image_hash = 
('b62808daef48b438d0728ee07662290490ecfa65987bb91294cafb1bb7ad1a68')
 image_path = self.fetch_asset(image_url, asset_hash=image_hash,
   algorithm='sha256')
 
@@ -206,17 +207,17 @@ def test_arm_ast2600_evb_buildroot(self):
  'ds1338,bus=aspeed.i2c.bus.3,address=0x32');
 self.vm.add_args('-device',
  'i2c-echo,bus=aspeed.i2c.bus.3,address=0x42');
-self.do_test_arm_aspeed_buildroot_start(image_path, '0xf00')
+self.do_test_arm_aspeed_buildroot_start(image_path, '0xf00', 'Aspeed 
AST2600 EVB')
 
 exec_command_and_wait_for_pattern(self,
  'echo lm75 0x4d > /sys/class/i2c-dev/i2c-3/device/new_device',
  'i2c i2c-3: new_device: Instantiated device lm75 at 0x4d');
 exec_command_and_wait_for_pattern(self,
- 'cat /sys/class/hwmon/hwmon0/temp1_input', '0')
+ 'cat /sys/class/hwmon/hwmon1/temp1_input', '0')
 self.vm.cmd('qom-set', path='/machine/peripheral/tmp-test',
 property='temperature', value=18000);
 exec_command_and_wait_for_pattern(self,
- 'cat /sys/class/hwmon/hwmon0/temp1_input', 
'18000')
+ 'cat /sys/class/hwmon/hwmon1/temp1_input', 
'18000')
 
 exec_command_and_wait_for_pattern(self,
  'echo ds1307 0x32 > /sys/class/i2c-dev/i2c-3/device/new_device',
@@ -261,7 +262,6 @@ def test_arm_ast2600_evb_buildroot_tpm(self):
 self.vm.add_args('-device',
  
'tpm-tis-i2c,tpmdev=tpm0,bus=aspeed.i2c.bus.12,address=0x2e')
 self.do_test_arm_aspeed_buildroot_start(image_path, '0xf00', 'Aspeed 
AST2600 EVB')
-exec_command(self, "passw0rd")
 
 exec_command_and_wait_for_pattern(self,
 'echo tpm_tis_i2c 0x2e > /sys/bus/i2c/devices/i2c-12/new_device',
-- 
2.43.0




[PULL 10/17] hw/fsi: Introduce IBM's fsi-slave model

2024-01-26 Thread Cédric Le Goater
From: Ninad Palsule 

This is a part of patchset where IBM's Flexible Service Interface is
introduced.

The FSI slave: The slave is the terminal point of the FSI bus for
FSI symbols addressed to it. Slaves can be cascaded off of one
another. The slave's configuration registers appear in address space
of the CFAM to which it is attached.

Signed-off-by: Andrew Jeffery 
Signed-off-by: Ninad Palsule 
Reviewed-by: Cédric Le Goater 
Signed-off-by: Cédric Le Goater 
---
 include/hw/fsi/fsi.h | 18 ++
 hw/fsi/fsi.c | 84 ++--
 hw/fsi/trace-events  |  2 ++
 3 files changed, 102 insertions(+), 2 deletions(-)

diff --git a/include/hw/fsi/fsi.h b/include/hw/fsi/fsi.h
index 50e8f5c888f1..e00f6ef078c8 100644
--- a/include/hw/fsi/fsi.h
+++ b/include/hw/fsi/fsi.h
@@ -7,7 +7,13 @@
 #ifndef FSI_FSI_H
 #define FSI_FSI_H
 
+#include "exec/memory.h"
 #include "hw/qdev-core.h"
+#include "hw/fsi/lbus.h"
+#include "qemu/bitops.h"
+
+/* Bitwise operations at the word level. */
+#define BE_GENMASK(hb, lb)  MAKE_64BIT_MASK((lb), ((hb) - (lb) + 1))
 
 #define TYPE_FSI_BUS "fsi.bus"
 OBJECT_DECLARE_SIMPLE_TYPE(FSIBus, FSI_BUS)
@@ -16,4 +22,16 @@ typedef struct FSIBus {
 BusState bus;
 } FSIBus;
 
+#define TYPE_FSI_SLAVE "fsi.slave"
+OBJECT_DECLARE_SIMPLE_TYPE(FSISlaveState, FSI_SLAVE)
+
+#define FSI_SLAVE_CONTROL_NR_REGS ((0x40 >> 2) + 1)
+
+typedef struct FSISlaveState {
+DeviceState parent;
+
+MemoryRegion iomem;
+uint32_t regs[FSI_SLAVE_CONTROL_NR_REGS];
+} FSISlaveState;
+
 #endif /* FSI_FSI_H */
diff --git a/hw/fsi/fsi.c b/hw/fsi/fsi.c
index 60cb03f7a24e..9a5f4e616f16 100644
--- a/hw/fsi/fsi.c
+++ b/hw/fsi/fsi.c
@@ -5,18 +5,98 @@
  * IBM Flexible Service Interface
  */
 #include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu/log.h"
+#include "trace.h"
 
 #include "hw/fsi/fsi.h"
 
+#define TO_REG(x)   ((x) >> 2)
+
 static const TypeInfo fsi_bus_info = {
 .name = TYPE_FSI_BUS,
 .parent = TYPE_BUS,
 .instance_size = sizeof(FSIBus),
 };
 
-static void fsi_bus_register_types(void)
+static uint64_t fsi_slave_read(void *opaque, hwaddr addr, unsigned size)
+{
+FSISlaveState *s = FSI_SLAVE(opaque);
+int reg = TO_REG(addr);
+
+trace_fsi_slave_read(addr, size);
+
+if (reg >= FSI_SLAVE_CONTROL_NR_REGS) {
+qemu_log_mask(LOG_GUEST_ERROR,
+  "%s: Out of bounds read: 0x%"HWADDR_PRIx" for %u\n",
+  __func__, addr, size);
+return 0;
+}
+
+return s->regs[reg];
+}
+
+static void fsi_slave_write(void *opaque, hwaddr addr, uint64_t data,
+ unsigned size)
+{
+FSISlaveState *s = FSI_SLAVE(opaque);
+int reg = TO_REG(addr);
+
+trace_fsi_slave_write(addr, size, data);
+
+if (reg >= FSI_SLAVE_CONTROL_NR_REGS) {
+qemu_log_mask(LOG_GUEST_ERROR,
+  "%s: Out of bounds write: 0x%"HWADDR_PRIx" for %u\n",
+  __func__, addr, size);
+return;
+}
+
+s->regs[reg] = data;
+}
+
+static const struct MemoryRegionOps fsi_slave_ops = {
+.read = fsi_slave_read,
+.write = fsi_slave_write,
+.endianness = DEVICE_BIG_ENDIAN,
+};
+
+static void fsi_slave_reset(DeviceState *dev)
+{
+FSISlaveState *s = FSI_SLAVE(dev);
+
+/* Initialize registers */
+memset(s->regs, 0, sizeof(s->regs));
+}
+
+static void fsi_slave_init(Object *o)
+{
+FSISlaveState *s = FSI_SLAVE(o);
+
+memory_region_init_io(>iomem, OBJECT(s), _slave_ops,
+  s, TYPE_FSI_SLAVE, 0x400);
+}
+
+static void fsi_slave_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+
+dc->bus_type = TYPE_FSI_BUS;
+dc->desc = "FSI Slave";
+dc->reset = fsi_slave_reset;
+}
+
+static const TypeInfo fsi_slave_info = {
+.name = TYPE_FSI_SLAVE,
+.parent = TYPE_DEVICE,
+.instance_init = fsi_slave_init,
+.instance_size = sizeof(FSISlaveState),
+.class_init = fsi_slave_class_init,
+};
+
+static void fsi_register_types(void)
 {
 type_register_static(_bus_info);
+type_register_static(_slave_info);
 }
 
-type_init(fsi_bus_register_types);
+type_init(fsi_register_types);
diff --git a/hw/fsi/trace-events b/hw/fsi/trace-events
index c5753e27910a..8f29adb7df92 100644
--- a/hw/fsi/trace-events
+++ b/hw/fsi/trace-events
@@ -1,2 +1,4 @@
 fsi_scratchpad_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d"
 fsi_scratchpad_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" 
PRIx64 " size=%d value=0x%"PRIx64
+fsi_slave_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d"
+fsi_slave_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " 
size=%d value=0x%"PRIx64
-- 
2.43.0




[PULL 00/17] aspeed queue

2024-01-26 Thread Cédric Le Goater
The following changes since commit e029fe22caad9b75c7ab69bd4e84853c11fb71e0:

  Merge tag 'pull-qapi-2024-01-26' of https://repo.or.cz/qemu/armbru into 
staging (2024-01-26 10:21:27 +)

are available in the Git repository at:

  https://github.com/legoater/qemu/ tags/pull-aspeed-20240126

for you to fetch changes up to b40769f4b49d15485ffaaa7acade3e3593ee6daa:

  hw/fsi: Update MAINTAINER list (2024-01-26 14:22:08 +0100)


aspeed queue:

* Update of buildroot images to 2023.11 (6.6.3 kernel)
* Check of the valid CPU type supported by aspeed machines
* Simplified models for the IBM's FSI bus and the Aspeed
  controller bridge


Cédric Le Goater (1):
  tests/avocado/machine_aspeed.py: Update buildroot images to 2023.11

Ninad Palsule (11):
  hw/fsi: Introduce IBM's Local bus
  hw/fsi: Introduce IBM's scratchpad device
  hw/fsi: Introduce IBM's FSI Bus
  hw/fsi: Introduce IBM's fsi-slave model
  hw/fsi: Introduce IBM's cfam
  hw/fsi: Introduce IBM's FSI master
  hw/fsi: Aspeed APB2OPB & On-chip peripheral bus
  hw/arm: Hook up FSI module in AST2600
  hw/fsi: Added qtest
  hw/fsi: Added FSI documentation
  hw/fsi: Update MAINTAINER list

Philippe Mathieu-Daudé (5):
  hw/arm/aspeed: Remove dead code
  hw/arm/aspeed: Set default CPU count using aspeed_soc_num_cpus()
  hw/arm/aspeed: Init CPU defaults in a common helper
  hw/arm/aspeed: Introduce aspeed_soc_cpu_type() helper
  hw/arm/aspeed: Check for CPU types in machine_run_board_init()

 MAINTAINERS |   9 ++
 docs/specs/fsi.rst  | 122 +++
 docs/specs/index.rst|   1 +
 meson.build |   1 +
 hw/fsi/trace.h  |   1 +
 include/hw/arm/aspeed_soc.h |   8 +-
 include/hw/fsi/aspeed_apb2opb.h |  46 ++
 include/hw/fsi/cfam.h   |  34 +
 include/hw/fsi/fsi-master.h |  32 
 include/hw/fsi/fsi.h|  37 +
 include/hw/fsi/lbus.h   |  43 ++
 hw/arm/aspeed.c |  70 -
 hw/arm/aspeed_ast10x0.c |   8 +-
 hw/arm/aspeed_ast2400.c |  15 +-
 hw/arm/aspeed_ast2600.c |  28 +++-
 hw/arm/aspeed_soc_common.c  |   8 +
 hw/fsi/aspeed_apb2opb.c | 329 
 hw/fsi/cfam.c   | 168 
 hw/fsi/fsi-master.c | 170 +
 hw/fsi/fsi.c| 102 +
 hw/fsi/lbus.c   | 117 ++
 tests/qtest/aspeed-fsi-test.c   | 205 +
 hw/Kconfig  |   1 +
 hw/arm/Kconfig  |   1 +
 hw/fsi/Kconfig  |   7 +
 hw/fsi/meson.build  |   2 +
 hw/fsi/trace-events |  13 ++
 hw/meson.build  |   1 +
 tests/avocado/machine_aspeed.py |  18 +--
 tests/qtest/meson.build |   1 +
 30 files changed, 1540 insertions(+), 58 deletions(-)
 create mode 100644 docs/specs/fsi.rst
 create mode 100644 hw/fsi/trace.h
 create mode 100644 include/hw/fsi/aspeed_apb2opb.h
 create mode 100644 include/hw/fsi/cfam.h
 create mode 100644 include/hw/fsi/fsi-master.h
 create mode 100644 include/hw/fsi/fsi.h
 create mode 100644 include/hw/fsi/lbus.h
 create mode 100644 hw/fsi/aspeed_apb2opb.c
 create mode 100644 hw/fsi/cfam.c
 create mode 100644 hw/fsi/fsi-master.c
 create mode 100644 hw/fsi/fsi.c
 create mode 100644 hw/fsi/lbus.c
 create mode 100644 tests/qtest/aspeed-fsi-test.c
 create mode 100644 hw/fsi/Kconfig
 create mode 100644 hw/fsi/meson.build
 create mode 100644 hw/fsi/trace-events



Re: [PATCH v3 0/5] hw/arm/aspeed: Check for CPU types in machine_run_board_init()

2024-01-26 Thread Cédric Le Goater

On 1/25/24 06:55, Philippe Mathieu-Daudé wrote:

Series fully reviewed.

Since v2:
- Addressed Gavin & Richard review comments.
- Collected R-b tags

Since v1:
- Follow suggestions from Cédric from [*]

[*] 
https://lore.kernel.org/qemu-devel/e13c655b-7904-4e47-a673-4efd13c26...@kaod.org/

Based-on: <20240123222508.13826-1-phi...@linaro.org>

Philippe Mathieu-Daudé (5):
   hw/arm/aspeed: Remove dead code
   hw/arm/aspeed: Set default CPU count using aspeed_soc_num_cpus()
   hw/arm/aspeed: Init CPU defaults in a common helper
   hw/arm/aspeed: Introduce aspeed_soc_cpu_type() helper
   hw/arm/aspeed: Check for CPU types in machine_run_board_init()

  include/hw/arm/aspeed_soc.h |  4 ++-
  hw/arm/aspeed.c | 70 +++--
  hw/arm/aspeed_ast10x0.c |  8 +++--
  hw/arm/aspeed_ast2400.c | 15 ++--
  hw/arm/aspeed_ast2600.c |  9 +++--
  hw/arm/aspeed_soc_common.c  |  8 +
  6 files changed, 65 insertions(+), 49 deletions(-)



Applied to aspeed-next.

Thanks,

C.





Re: [PATCH v12 00/11] Introduce model for IBM's FSI

2024-01-26 Thread Cédric Le Goater

On 1/26/24 11:49, Ninad Palsule wrote:

Hello,

Please review the patch-set version 12.
I have incorporated review comments from Cedric.
v12:
   - Minor changes.
   - Added reviewed by tags.

Ninad Palsule (11):
   hw/fsi: Introduce IBM's Local bus
   hw/fsi: Introduce IBM's scratchpad device
   hw/fsi: Introduce IBM's FSI Bus
   hw/fsi: Introduce IBM's fsi-slave model
   hw/fsi: Introduce IBM's cfam
   hw/fsi: Introduce IBM's FSI master
   hw/fsi: Aspeed APB2OPB & On-chip peripheral bus
   hw/arm: Hook up FSI module in AST2600
   hw/fsi: Added qtest
   hw/fsi: Added FSI documentation
   hw/fsi: Update MAINTAINER list




Applied to aspeed-next.

Thanks,

C.





Re: [PATCH] tests/avocado/machine_aspeed.py: Update buildroot images to 2023.11

2024-01-26 Thread Cédric Le Goater

On 1/9/24 18:35, Cédric Le Goater wrote:

Compared to mainline buildroot, these images have some customization :

- Linux version is bumped to 6.6.3 and built with a custom config
- U-Boot is switched to the one provided by OpenBMC for more support
- defconfigs extra tools for dev

See branch [1] for more details.

There are a few changes since last update, commit ed1f5ff84209. Images
all have a password now and I2C devices have been updated in the Linux
ast2600-evb device tree [2]. Do the necessary adjustements.

[1] https://github.com/legoater/buildroot/commits/aspeed-2023.11
[2] 
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=9deb10cf160e

Signed-off-by: Cédric Le Goater 



Applied to aspeed-next.

Thanks,

C.



Re: [PATCH v12 10/11] hw/fsi: Added FSI documentation

2024-01-26 Thread Cédric Le Goater

On 1/26/24 11:49, Ninad Palsule wrote:

Documentation for IBM FSI model.

Signed-off-by: Ninad Palsule 
---
v11:
   - Removed Cedric's signoff.
---
  docs/specs/fsi.rst   | 126 +++
  docs/specs/index.rst |   1 +
  2 files changed, 127 insertions(+)
  create mode 100644 docs/specs/fsi.rst

diff --git a/docs/specs/fsi.rst b/docs/specs/fsi.rst
new file mode 100644
index 00..b33b4d565c
--- /dev/null
+++ b/docs/specs/fsi.rst
@@ -0,0 +1,126 @@
+==
+IBM's Flexible Service Interface (FSI)
+==
+
+The QEMU FSI emulation implements hardware interfaces between ASPEED SOC, FSI
+master/slave and the end engine.
+
+FSI is a point-to-point two wire interface which is capable of supporting
+distances of up to 4 meters. FSI interfaces have been used successfully for
+many years in IBM servers to attach IBM Flexible Support Processors(FSP) to
+CPUs and IBM ASICs.
+
+FSI allows a service processor access to the internal buses of a host POWER
+processor to perform configuration or debugging. FSI has long existed in POWER
+processes and so comes with some baggage, including how it has been integrated
+into the ASPEED SoC.
+
+Working backwards from the POWER processor, the fundamental pieces of interest
+for the implementation are: (see the `FSI specification`_ for more details)
+
+1. The Common FRU Access Macro (CFAM), an address space containing various
+   "engines" that drive accesses on buses internal and external to the POWER
+   chip. Examples include the SBEFIFO and I2C masters. The engines hang off of
+   an internal Local Bus (LBUS) which is described by the CFAM configuration
+   block.
+
+2. The FSI slave: The slave is the terminal point of the FSI bus for FSI
+   symbols addressed to it. Slaves can be cascaded off of one another. The
+   slave's configuration registers appear in address space of the CFAM to
+   which it is attached.
+
+3. The FSI master: A controller in the platform service processor (e.g. BMC)
+   driving CFAM engine accesses into the POWER chip. At the hardware level
+   FSI is a bit-based protocol supporting synchronous and DMA-driven accesses
+   of engines in a CFAM.
+
+4. The On-Chip Peripheral Bus (OPB): A low-speed bus typically found in POWER
+   processors. This now makes an appearance in the ASPEED SoC due to tight
+   integration of the FSI master IP with the OPB, mainly the existence of an
+   MMIO-mapping of the CFAM address straight onto a sub-region of the OPB
+   address space.
+
+5. An APB-to-OPB bridge enabling access to the OPB from the ARM core in the
+   AST2600. Hardware limitations prevent the OPB from being directly mapped
+   into APB, so all accesses are indirect through the bridge.
+
+The LBUS is modelled to maintain the qdev bus hierarchy and to take advantages
+of the object model to automatically generate the CFAM configuration block.
+The configuration block presents engines in the order they are attached to the
+CFAM's LBUS. Engine implementations should subclass the LBusDevice and set the
+'config' member of LBusDeviceClass to match the engine's type.
+
+CFAM designs offer a lot of flexibility, for instance it is possible for a
+CFAM to be simultaneously driven from multiple FSI links. The modeling is not
+so complete; it's assumed that each CFAM is attached to a single FSI slave (as
+a consequence the CFAM subclasses the FSI slave).
+
+As for FSI, its symbols and wire-protocol are not modelled at all. This is not
+necessary to get FSI off the ground thanks to the mapping of the CFAM address
+space onto the OPB address space - the models follow this directly and map the
+CFAM memory region into the OPB's memory region.
+
+QEMU files related to FSI interface are in following directories:
+ - ``hw/fsi``
+ - ``include/hw/fsi``


This is not useful.


+The following commands start the ``rainier-bmc`` machine with built-in FSI
+model. There are no model specific arguments. Please check this document to
+learn more about Aspeed ``rainier-bmc`` machine: docs/system/arm/aspeed.rst


This should be :  (:doc:`../../system/arm/aspeed`)

I will fix it.

Reviewed-by: Cédric Le Goater 

Thanks,

C.




+
+.. code-block:: console
+
+  qemu-system-arm -M rainier-bmc -nographic \
+  -kernel fitImage-linux.bin \
+  -dtb aspeed-bmc-ibm-rainier.dtb \
+  -initrd obmc-phosphor-initramfs.rootfs.cpio.xz \
+  -drive file=obmc-phosphor-image.rootfs.wic.qcow2,if=sd,index=2 \
+  -append "rootwait console=ttyS4,115200n8 root=PARTLABEL=rofs-a"
+
+The implementation appears as following in the qemu device tree:
+
+.. code-block:: console
+
+  (qemu) info qtree
+  bus: main-system-bus
+type System
+...
+dev: aspeed.apb2opb, id ""
+  gpio-out "sysbus-irq" 1
+  mmio 1e79b000/1000
+  bus: opb.1
+type opb
+dev: fsi.master, id ""
+  bus: fsi.bus.1
+

Re: [PATCH v11 00/11] Introduce model for IBM's FSI

2024-01-26 Thread Cédric Le Goater

Hello Ninad,

On 1/26/24 04:40, Ninad Palsule wrote:

Hello,
  
Please review the patch-set version 11.

I have incorporated review comments from Cedric.
v10:
   - Moved aspeed-apb2opb to hw/fsi directory
   - Split some patches.
   - Fixed crash.
   - make check
 Ok: 319
 Expected Fail:  0
 Fail:   0
 Unexpected Pass:0
 Skipped:9
 Timeout:0


I did some minor comments. v12 should be queued for upstream. I will
reorder the Signed-off (mine) trailers.

Thanks,

C.




Ninad Palsule (11):
   hw/fsi: Introduce IBM's Local bus
   hw/fsi: Introduce IBM's scratchpad device
   hw/fsi: Introduce IBM's FSI Bus
   hw/fsi: Introduce IBM's fsi-slave model
   hw/fsi: Introduce IBM's cfam
   hw/fsi: Introduce IBM's FSI master
   hw/fsi: Aspeed APB2OPB & On-chip peripheral bus
   hw/arm: Hook up FSI module in AST2600
   hw/fsi: Added qtest
   hw/fsi: Added FSI documentation
   hw/fsi: Update MAINTAINER list

  MAINTAINERS |   9 +
  docs/specs/fsi.rst  | 138 ++
  docs/specs/index.rst|   1 +
  meson.build |   1 +
  hw/fsi/trace.h  |   1 +
  include/hw/arm/aspeed_soc.h |   4 +
  include/hw/fsi/aspeed_apb2opb.h |  46 +
  include/hw/fsi/cfam.h   |  34 
  include/hw/fsi/fsi-master.h |  32 
  include/hw/fsi/fsi.h|  38 
  include/hw/fsi/lbus.h   |  43 +
  hw/arm/aspeed_ast2600.c |  19 ++
  hw/fsi/aspeed_apb2opb.c | 322 
  hw/fsi/cfam.c   | 168 +
  hw/fsi/fsi-master.c | 170 +
  hw/fsi/fsi.c| 105 +++
  hw/fsi/lbus.c   | 112 +++
  tests/qtest/aspeed-fsi-test.c   | 205 
  hw/Kconfig  |   1 +
  hw/arm/Kconfig  |   1 +
  hw/fsi/Kconfig  |   7 +
  hw/fsi/meson.build  |   2 +
  hw/fsi/trace-events |  13 ++
  hw/meson.build  |   1 +
  tests/qtest/meson.build |   1 +
  25 files changed, 1474 insertions(+)
  create mode 100644 docs/specs/fsi.rst
  create mode 100644 hw/fsi/trace.h
  create mode 100644 include/hw/fsi/aspeed_apb2opb.h
  create mode 100644 include/hw/fsi/cfam.h
  create mode 100644 include/hw/fsi/fsi-master.h
  create mode 100644 include/hw/fsi/fsi.h
  create mode 100644 include/hw/fsi/lbus.h
  create mode 100644 hw/fsi/aspeed_apb2opb.c
  create mode 100644 hw/fsi/cfam.c
  create mode 100644 hw/fsi/fsi-master.c
  create mode 100644 hw/fsi/fsi.c
  create mode 100644 hw/fsi/lbus.c
  create mode 100644 tests/qtest/aspeed-fsi-test.c
  create mode 100644 hw/fsi/Kconfig
  create mode 100644 hw/fsi/meson.build
  create mode 100644 hw/fsi/trace-events






Re: [PATCH v11 11/11] hw/fsi: Update MAINTAINER list

2024-01-26 Thread Cédric Le Goater

On 1/26/24 04:40, Ninad Palsule wrote:

Added maintainer for IBM FSI model

Signed-off-by: Ninad Palsule 
---
v11:
  - Added Cedric as reviewer.



Reviewed-by: Cédric Le Goater 

Thanks,

C.



---
  MAINTAINERS | 9 +
  1 file changed, 9 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index dfaca8323e..39deb8ee1f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3585,6 +3585,15 @@ F: tests/qtest/adm1272-test.c
  F: tests/qtest/max34451-test.c
  F: tests/qtest/isl_pmbus_vr-test.c
  
+FSI

+M: Ninad Palsule 
+R: Cédric Le Goater 
+S: Maintained
+F: hw/fsi/*
+F: include/hw/fsi/*
+F: docs/specs/fsi.rst
+F: tests/qtest/fsi-test.c
+
  Firmware schema specifications
  M: Philippe Mathieu-Daudé 
  R: Daniel P. Berrange 





Re: [PATCH v11 10/11] hw/fsi: Added FSI documentation

2024-01-26 Thread Cédric Le Goater

On 1/26/24 04:40, Ninad Palsule wrote:

Documentation for IBM FSI model.

Signed-off-by: Ninad Palsule 
---
v11:
   - Removed Cedri's signoff.
---
  docs/specs/fsi.rst   | 138 +++
  docs/specs/index.rst |   1 +
  2 files changed, 139 insertions(+)
  create mode 100644 docs/specs/fsi.rst

diff --git a/docs/specs/fsi.rst b/docs/specs/fsi.rst
new file mode 100644
index 00..05a6b6347a
--- /dev/null
+++ b/docs/specs/fsi.rst
@@ -0,0 +1,138 @@
+==
+IBM's Flexible Service Interface (FSI)
+==
+
+The QEMU FSI emulation implements hardware interfaces between ASPEED SOC, FSI
+master/slave and the end engine.
+
+FSI is a point-to-point two wire interface which is capable of supporting
+distances of up to 4 meters. FSI interfaces have been used successfully for
+many years in IBM servers to attach IBM Flexible Support Processors(FSP) to
+CPUs and IBM ASICs.
+
+FSI allows a service processor access to the internal buses of a host POWER
+processor to perform configuration or debugging. FSI has long existed in POWER
+processes and so comes with some baggage, including how it has been integrated
+into the ASPEED SoC.
+
+Working backwards from the POWER processor, the fundamental pieces of interest
+for the implementation are: (see the `FSI specification`_ for more details)
+
+1. The Common FRU Access Macro (CFAM), an address space containing various
+   "engines" that drive accesses on buses internal and external to the POWER
+   chip. Examples include the SBEFIFO and I2C masters. The engines hang off of
+   an internal Local Bus (LBUS) which is described by the CFAM configuration
+   block.
+
+2. The FSI slave: The slave is the terminal point of the FSI bus for FSI
+   symbols addressed to it. Slaves can be cascaded off of one another. The
+   slave's configuration registers appear in address space of the CFAM to
+   which it is attached.
+
+3. The FSI master: A controller in the platform service processor (e.g. BMC)
+   driving CFAM engine accesses into the POWER chip. At the hardware level
+   FSI is a bit-based protocol supporting synchronous and DMA-driven accesses
+   of engines in a CFAM.
+
+4. The On-Chip Peripheral Bus (OPB): A low-speed bus typically found in POWER
+   processors. This now makes an appearance in the ASPEED SoC due to tight
+   integration of the FSI master IP with the OPB, mainly the existence of an
+   MMIO-mapping of the CFAM address straight onto a sub-region of the OPB
+   address space.
+
+5. An APB-to-OPB bridge enabling access to the OPB from the ARM core in the
+   AST2600. Hardware limitations prevent the OPB from being directly mapped
+   into APB, so all accesses are indirect through the bridge.
+
+The LBUS is modelled to maintain the qdev bus hierarchy and to take advantages
+of the object model to automatically generate the CFAM configuration block.
+The configuration block presents engines in the order they are attached to the
+CFAM's LBUS. Engine implementations should subclass the LBusDevice and set the
+'config' member of LBusDeviceClass to match the engine's type.
+
+CFAM designs offer a lot of flexibility, for instance it is possible for a
+CFAM to be simultaneously driven from multiple FSI links. The modeling is not
+so complete; it's assumed that each CFAM is attached to a single FSI slave (as
+a consequence the CFAM subclasses the FSI slave).
+
+As for FSI, its symbols and wire-protocol are not modelled at all. This is not
+necessary to get FSI off the ground thanks to the mapping of the CFAM address
+space onto the OPB address space - the models follow this directly and map the
+CFAM memory region into the OPB's memory region.
+
+QEMU files related to FSI interface:
+ - ``hw/fsi/aspeed-apb2opb.c``
+ - ``include/hw/fsi/aspeed-apb2opb.h``
+ - ``hw/fsi/opb.c``
+ - ``include/hw/fsi/opb.h``
+ - ``hw/fsi/fsi.c``
+ - ``include/hw/fsi/fsi.h``
+ - ``hw/fsi/fsi-master.c``
+ - ``include/hw/fsi/fsi-master.h``
+ - ``hw/fsi/fsi-slave.c``
+ - ``include/hw/fsi/fsi-slave.h``
+ - ``hw/fsi/cfam.c``
+ - ``include/hw/fsi/cfam.h``
+ - ``hw/fsi/engine-scratchpad.c``
+ - ``include/hw/fsi/engine-scratchpad.h``
+ - ``include/hw/fsi/lbus.h``


Please remove the file list above.


+The following commands start the rainier machine with built-in FSI model.


rainier -> ``rainier-bmc``


+There are no model specific arguments.

I would also add a reference to the docs/system/arm/aspeed.rst page.


+
+.. code-block:: console
+
+  qemu-system-arm -M rainier-bmc -nographic \
+  -kernel fitImage-linux.bin \
+  -dtb aspeed-bmc-ibm-rainier.dtb \
+  -initrd obmc-phosphor-initramfs.rootfs.cpio.xz \
+  -drive file=obmc-phosphor-image.rootfs.wic.qcow2,if=sd,index=2 \
+  -append "rootwait console=ttyS4,115200n8 root=PARTLABEL=rofs-a"
+
+The implementation appears as following in the qemu device tree:
+
+.. code-block:: console
+
+  (qemu) info qtree
+  bus: main-system-bus
+type System
+

Re: [PATCH v11 07/11] hw/fsi: Aspeed APB2OPB & On-chip peripheral bus

2024-01-26 Thread Cédric Le Goater

On 1/26/24 04:40, Ninad Palsule wrote:

This is a part of patchset where IBM's Flexible Service Interface is
introduced.

An APB-to-OPB bridge enabling access to the OPB from the ARM core in
the AST2600. Hardware limitations prevent the OPB from being directly
mapped into APB, so all accesses are indirect through the bridge.

The On-Chip Peripheral Bus (OPB): A low-speed bus typically found in
POWER processors. This now makes an appearance in the ASPEED SoC due
to tight integration of the FSI master IP with the OPB, mainly the
existence of an MMIO-mapping of the CFAM address straight onto a
sub-region of the OPB address space.

Signed-off-by: Andrew Jeffery 
[ clg: - moved FSIMasterState under AspeedAPB2OPBState
- modified fsi_opb_fsi_master_address() and
  fsi_opb_opb2fsi_address()
- instroduced fsi_aspeed_apb2opb_init()
- reworked fsi_aspeed_apb2opb_realize()
- removed FSIMasterState object and fsi_opb_realize()
- simplified OPBus ]
Signed-off-by: Cédric Le Goater 
Signed-off-by: Ninad Palsule 
---
v9:
   - Removed unused parameters from function.
   - Used qdev_realize() instead of qdev_realize_and_undef
   - Given a name to the opb memory region.

v10:
   - Combine Aspeed APB2OPB and on-chip pheripheral bus
---
  include/hw/fsi/aspeed_apb2opb.h |  46 +
  hw/fsi/aspeed_apb2opb.c | 322 
  hw/arm/Kconfig  |   1 +
  hw/fsi/Kconfig  |   5 +
  hw/fsi/meson.build  |   1 +
  hw/fsi/trace-events |   2 +
  6 files changed, 377 insertions(+)
  create mode 100644 include/hw/fsi/aspeed_apb2opb.h
  create mode 100644 hw/fsi/aspeed_apb2opb.c

diff --git a/include/hw/fsi/aspeed_apb2opb.h b/include/hw/fsi/aspeed_apb2opb.h
new file mode 100644
index 00..f6a2387abf
--- /dev/null
+++ b/include/hw/fsi/aspeed_apb2opb.h
@@ -0,0 +1,46 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright (C) 2024 IBM Corp.
+ *
+ * ASPEED APB2OPB Bridge
+ * IBM On-Chip Peripheral Bus
+ */
+#ifndef FSI_ASPEED_APB2OPB_H
+#define FSI_ASPEED_APB2OPB_H
+
+#include "exec/memory.h"
+#include "hw/fsi/fsi-master.h"
+#include "hw/sysbus.h"
+
+#define TYPE_FSI_OPB "fsi.opb"
+
+#define TYPE_OP_BUS "opb"
+OBJECT_DECLARE_SIMPLE_TYPE(OPBus, OP_BUS)
+
+typedef struct OPBus {
+BusState bus;
+
+MemoryRegion mr;
+AddressSpace as;
+} OPBus;
+
+#define TYPE_ASPEED_APB2OPB "aspeed.apb2opb"
+OBJECT_DECLARE_SIMPLE_TYPE(AspeedAPB2OPBState, ASPEED_APB2OPB)
+
+#define ASPEED_APB2OPB_NR_REGS ((0xe8 >> 2) + 1)
+
+#define ASPEED_FSI_NUM 2
+
+typedef struct AspeedAPB2OPBState {
+SysBusDevice parent_obj;
+
+MemoryRegion iomem;
+
+uint32_t regs[ASPEED_APB2OPB_NR_REGS];
+qemu_irq irq;
+
+OPBus opb[ASPEED_FSI_NUM];
+FSIMasterState fsi[ASPEED_FSI_NUM];
+} AspeedAPB2OPBState;
+
+#endif /* FSI_ASPEED_APB2OPB_H */
diff --git a/hw/fsi/aspeed_apb2opb.c b/hw/fsi/aspeed_apb2opb.c
new file mode 100644
index 00..997ae30060
--- /dev/null
+++ b/hw/fsi/aspeed_apb2opb.c
@@ -0,0 +1,322 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright (C) 2024 IBM Corp.
+ *
+ * ASPEED APB-OPB FSI interface
+ * IBM On-chip Peripheral Bus
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qom/object.h"
+#include "qapi/error.h"
+#include "trace.h"
+
+#include "hw/fsi/aspeed_apb2opb.h"
+#include "hw/qdev-core.h"
+
+#define TO_REG(x) (x >> 2)
+
+#define APB2OPB_VERSIONTO_REG(0x00)
+#define APB2OPB_TRIGGERTO_REG(0x04)
+
+#define APB2OPB_CONTROLTO_REG(0x08)
+#define   APB2OPB_CONTROL_OFF  BE_GENMASK(31, 13)
+
+#define APB2OPB_OPB2FSITO_REG(0x0c)
+#define   APB2OPB_OPB2FSI_OFF  BE_GENMASK(31, 22)
+
+#define APB2OPB_OPB0_SEL   TO_REG(0x10)
+#define APB2OPB_OPB1_SEL   TO_REG(0x28)
+#define   APB2OPB_OPB_SEL_EN   BIT(0)
+
+#define APB2OPB_OPB0_MODE  TO_REG(0x14)
+#define APB2OPB_OPB1_MODE  TO_REG(0x2c)
+#define   APB2OPB_OPB_MODE_RD  BIT(0)
+
+#define APB2OPB_OPB0_XFER  TO_REG(0x18)
+#define APB2OPB_OPB1_XFER  TO_REG(0x30)
+#define   APB2OPB_OPB_XFER_FULLBIT(1)
+#define   APB2OPB_OPB_XFER_HALFBIT(0)
+
+#define APB2OPB_OPB0_ADDR  TO_REG(0x1c)
+#define APB2OPB_OPB0_WRITE_DATATO_REG(0x20)
+
+#define APB2OPB_OPB1_ADDR  TO_REG(0x34)
+#define APB2OPB_OPB1_WRITE_DATA  TO_REG(0x38)
+
+#define APB2OPB_IRQ_STSTO_REG(0x48)
+#define   APB2OPB_IRQ_STS_OPB1_TX_ACK  BIT(17)
+#define   APB2OPB_IRQ_STS_OPB0_TX_ACK  BIT(16)
+
+#define APB2OPB_OPB0_WRITE_WORD_ENDIAN TO_REG(0x4c)
+#define   APB2OPB_OPB0_WRITE_WORD_

Re: [PATCH v11 06/11] hw/fsi: Introduce IBM's FSI master

2024-01-26 Thread Cédric Le Goater

On 1/26/24 04:40, Ninad Palsule wrote:

This is a part of patchset where IBM's Flexible Service Interface is
introduced.

This commit models the FSI master. CFAM is hanging out of FSI master which is a 
bus controller.

The FSI master: A controller in the platform service processor (e.g.
BMC) driving CFAM engine accesses into the POWER chip. At the
hardware level FSI is a bit-based protocol supporting synchronous and
DMA-driven accesses of engines in a CFAM.

Signed-off-by: Andrew Jeffery 
Signed-off-by: Cédric Le Goater 
[ clg: - move FSICFAMState object under FSIMasterState
- introduced fsi_master_init()
- reworked fsi_master_realize()
- dropped FSIBus definition ]
Signed-off-by: Ninad Palsule 
---
v9:
   - Initialized registers.
   - Fixed the address check.
v11:
   - Replaced for loop with memset.
   - Removed Joel's review tag as per Cedric.



Reviewed-by: Cédric Le Goater 

Thanks,

C.



---
  include/hw/fsi/fsi-master.h |  32 +++
  hw/fsi/fsi-master.c | 170 
  hw/fsi/meson.build  |   2 +-
  hw/fsi/trace-events |   2 +
  4 files changed, 205 insertions(+), 1 deletion(-)
  create mode 100644 include/hw/fsi/fsi-master.h
  create mode 100644 hw/fsi/fsi-master.c

diff --git a/include/hw/fsi/fsi-master.h b/include/hw/fsi/fsi-master.h
new file mode 100644
index 00..68e5f56db2
--- /dev/null
+++ b/include/hw/fsi/fsi-master.h
@@ -0,0 +1,32 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright (C) 2024 IBM Corp.
+ *
+ * IBM Flexible Service Interface Master
+ */
+#ifndef FSI_FSI_MASTER_H
+#define FSI_FSI_MASTER_H
+
+#include "exec/memory.h"
+#include "hw/qdev-core.h"
+#include "hw/fsi/fsi.h"
+#include "hw/fsi/cfam.h"
+
+#define TYPE_FSI_MASTER "fsi.master"
+OBJECT_DECLARE_SIMPLE_TYPE(FSIMasterState, FSI_MASTER)
+
+#define FSI_MASTER_NR_REGS ((0x2e0 >> 2) + 1)
+
+typedef struct FSIMasterState {
+DeviceState parent;
+MemoryRegion iomem;
+MemoryRegion opb2fsi;
+
+FSIBus bus;
+
+uint32_t regs[FSI_MASTER_NR_REGS];
+FSICFAMState cfam;
+} FSIMasterState;
+
+
+#endif /* FSI_FSI_H */
diff --git a/hw/fsi/fsi-master.c b/hw/fsi/fsi-master.c
new file mode 100644
index 00..49ad4b988f
--- /dev/null
+++ b/hw/fsi/fsi-master.c
@@ -0,0 +1,170 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright (C) 2024 IBM Corp.
+ *
+ * IBM Flexible Service Interface master
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu/log.h"
+#include "trace.h"
+
+#include "hw/fsi/fsi-master.h"
+
+#define TYPE_OP_BUS "opb"
+
+#define TO_REG(x)   ((x) >> 2)
+
+#define FSI_MENP0   TO_REG(0x010)
+#define FSI_MENP32  TO_REG(0x014)
+#define FSI_MSENP0  TO_REG(0x018)
+#define FSI_MLEVP0  TO_REG(0x018)
+#define FSI_MSENP32 TO_REG(0x01c)
+#define FSI_MLEVP32 TO_REG(0x01c)
+#define FSI_MCENP0  TO_REG(0x020)
+#define FSI_MREFP0  TO_REG(0x020)
+#define FSI_MCENP32 TO_REG(0x024)
+#define FSI_MREFP32 TO_REG(0x024)
+
+#define FSI_MVERTO_REG(0x074)
+#define FSI_MRESP0  TO_REG(0x0d0)
+
+#define FSI_MRESB0  TO_REG(0x1d0)
+#define   FSI_MRESB0_RESET_GENERAL  BE_BIT(0)
+#define   FSI_MRESB0_RESET_ERRORBE_BIT(1)
+
+static uint64_t fsi_master_read(void *opaque, hwaddr addr, unsigned size)
+{
+FSIMasterState *s = FSI_MASTER(opaque);
+int reg = TO_REG(addr);
+
+trace_fsi_master_read(addr, size);
+
+if (reg >= FSI_MASTER_NR_REGS) {
+qemu_log_mask(LOG_GUEST_ERROR,
+  "%s: Out of bounds read: 0x%"HWADDR_PRIx" for %u\n",
+  __func__, addr, size);
+return 0;
+}
+
+return s->regs[reg];
+}
+
+static void fsi_master_write(void *opaque, hwaddr addr, uint64_t data,
+ unsigned size)
+{
+FSIMasterState *s = FSI_MASTER(opaque);
+int reg = TO_REG(addr);
+
+trace_fsi_master_write(addr, size, data);
+
+if (reg >= FSI_MASTER_NR_REGS) {
+qemu_log_mask(LOG_GUEST_ERROR,
+  "%s: Out of bounds write: %"HWADDR_PRIx" for %u\n",
+  __func__, addr, size);
+return;
+}
+
+switch (reg) {
+case FSI_MENP0:
+s->regs[FSI_MENP0] = data;
+break;
+case FSI_MENP32:
+s->regs[FSI_MENP32] = data;
+break;
+case FSI_MSENP0:
+s->regs[FSI_MENP0] |= data;
+break;
+case FSI_MSENP32:
+s

Re: [PATCH v11 05/11] hw/fsi: Introduce IBM's cfam

2024-01-26 Thread Cédric Le Goater

On 1/26/24 04:40, Ninad Palsule wrote:

This is a part of patchset where IBM's Flexible Service Interface is
introduced.

The Common FRU Access Macro (CFAM), an address space containing
various "engines" that drive accesses on busses internal and external
to the POWER chip. Examples include the SBEFIFO and I2C masters. The
engines hang off of an internal Local Bus (LBUS) which is described
by the CFAM configuration block.

Signed-off-by: Andrew Jeffery 
[ clg: - moved object FSIScratchPad under FSICFAMState
- moved FSIScratchPad code under cfam.c
- introduced fsi_cfam_instance_init()
- reworked fsi_cfam_realize() ]
Signed-off-by: Cédric Le Goater 
Signed-off-by: Ninad Palsule 
---
v9:
   - Added more registers to scratchpad
   - Removed unnecessary address space
   - Removed unnecessary header file
   - Defined macros for config values.
   - Cleaned up cfam config read.
---
  include/hw/fsi/cfam.h |  34 +
  hw/fsi/cfam.c | 168 ++
  hw/fsi/meson.build|   2 +-
  hw/fsi/trace-events   |   5 ++
  4 files changed, 208 insertions(+), 1 deletion(-)
  create mode 100644 include/hw/fsi/cfam.h
  create mode 100644 hw/fsi/cfam.c

diff --git a/include/hw/fsi/cfam.h b/include/hw/fsi/cfam.h
new file mode 100644
index 00..7abc3b287b
--- /dev/null
+++ b/include/hw/fsi/cfam.h
@@ -0,0 +1,34 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright (C) 2024 IBM Corp.
+ *
+ * IBM Common FRU Access Macro
+ */
+#ifndef FSI_CFAM_H
+#define FSI_CFAM_H
+
+#include "exec/memory.h"
+
+#include "hw/fsi/fsi.h"
+#include "hw/fsi/lbus.h"
+
+#define TYPE_FSI_CFAM "cfam"
+#define FSI_CFAM(obj) OBJECT_CHECK(FSICFAMState, (obj), TYPE_FSI_CFAM)
+
+/* P9-ism */
+#define CFAM_CONFIG_NR_REGS 0x28
+
+typedef struct FSICFAMState {
+/* < private > */
+FSISlaveState parent;
+
+/* CFAM config address space */
+MemoryRegion config_iomem;
+
+MemoryRegion mr;
+
+FSILBus lbus;
+FSIScratchPad scratchpad;
+} FSICFAMState;
+
+#endif /* FSI_CFAM_H */
diff --git a/hw/fsi/cfam.c b/hw/fsi/cfam.c
new file mode 100644
index 00..c118221bc3
--- /dev/null
+++ b/hw/fsi/cfam.c
@@ -0,0 +1,168 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright (C) 2024 IBM Corp.
+ *
+ * IBM Common FRU Access Macro
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/units.h"
+
+#include "qapi/error.h"
+#include "trace.h"
+
+#include "hw/fsi/cfam.h"
+#include "hw/fsi/fsi.h"
+
+#include "hw/qdev-properties.h"
+
+#define ENGINE_CONFIG_NEXTBE_BIT(0)


BE_BIT is not used much. I wonder if we should keep it.

Anyhow,


Reviewed-by: Cédric Le Goater 

Thanks,

C.



+#define ENGINE_CONFIG_TYPE_PEEK   (0x02 << 4)
+#define ENGINE_CONFIG_TYPE_FSI(0x03 << 4)
+#define ENGINE_CONFIG_TYPE_SCRATCHPAD (0x06 << 4)
+
+/* Valid, slots, version, type, crc */
+#define CFAM_CONFIG_REG(__VER, __TYPE, __CRC)   \
+(ENGINE_CONFIG_NEXT   |   \
+ 0x0001   |   \
+ (__VER)  |   \
+ (__TYPE) |   \
+ (__CRC))
+
+#define TO_REG(x)  ((x) >> 2)
+
+#define CFAM_CONFIG_CHIP_IDTO_REG(0x00)
+#define CFAM_CONFIG_PEEK_STATUSTO_REG(0x04)
+#define CFAM_CONFIG_CHIP_ID_P9 0xc0022d15
+#define CFAM_CONFIG_CHIP_ID_BREAK  0xc0de
+
+static uint64_t fsi_cfam_config_read(void *opaque, hwaddr addr, unsigned size)
+{
+trace_fsi_cfam_config_read(addr, size);
+
+switch (addr) {
+case 0x00:
+return CFAM_CONFIG_CHIP_ID_P9;
+case 0x04:
+return CFAM_CONFIG_REG(0x1000, ENGINE_CONFIG_TYPE_PEEK, 0xc);
+case 0x08:
+return CFAM_CONFIG_REG(0x5000, ENGINE_CONFIG_TYPE_FSI, 0xa);
+case 0xc:
+return CFAM_CONFIG_REG(0x1000, ENGINE_CONFIG_TYPE_SCRATCHPAD, 0x7);
+default:
+/*
+ * The config table contains different engines from 0xc onwards.
+ * The scratch pad is already added at address 0xc. We need to add
+ * future engines from address 0x10 onwards. Returning 0 as engine
+ * is not implemented.
+ */
+return 0;
+}
+}
+
+static void fsi_cfam_config_write(void *opaque, hwaddr addr, uint64_t data,
+  unsigned size)
+{
+FSICFAMState *cfam = FSI_CFAM(opaque);
+
+trace_fsi_cfam_config_write(addr, size, data);
+
+switch (TO_REG(addr)) {
+case CFAM_CONFIG_CHIP_ID:
+case CFAM_CONFIG_PEEK_STATUS:
+if (data == CFAM_CONFIG_CHIP_ID_BREAK) {
+bus_cold_reset(BUS(>lbus));
+}
+break;
+default:
+trace_fsi_cfam_config_write_noaddr(addr, size, data);
+}
+}
+
+static const struct MemoryRegionOps cfam_config_ops = {
+.read = fsi_cfam_config_read,
+.write = fsi_cfam_config_

Re: [PATCH v11 04/11] hw/fsi: Introduce IBM's fsi-slave model

2024-01-26 Thread Cédric Le Goater

On 1/26/24 04:40, Ninad Palsule wrote:

This is a part of patchset where IBM's Flexible Service Interface is
introduced.

The FSI slave: The slave is the terminal point of the FSI bus for
FSI symbols addressed to it. Slaves can be cascaded off of one
another. The slave's configuration registers appear in address space
of the CFAM to which it is attached.

Signed-off-by: Andrew Jeffery 
Signed-off-by: Cédric Le Goater 
Signed-off-by: Ninad Palsule 
---
  include/hw/fsi/fsi.h | 19 ++
  hw/fsi/fsi.c | 87 +++-
  hw/fsi/trace-events  |  2 +
  3 files changed, 106 insertions(+), 2 deletions(-)

diff --git a/include/hw/fsi/fsi.h b/include/hw/fsi/fsi.h
index 50e8f5c888..6e11747dd5 100644
--- a/include/hw/fsi/fsi.h
+++ b/include/hw/fsi/fsi.h
@@ -7,7 +7,14 @@
  #ifndef FSI_FSI_H
  #define FSI_FSI_H
  
+#include "exec/memory.h"

  #include "hw/qdev-core.h"
+#include "hw/fsi/lbus.h"
+#include "qemu/bitops.h"
+
+/* Bitwise operations at the word level. */
+#define BE_BIT(x)   BIT(31 - (x))
+#define BE_GENMASK(hb, lb)  MAKE_64BIT_MASK((lb), ((hb) - (lb) + 1))
  
  #define TYPE_FSI_BUS "fsi.bus"

  OBJECT_DECLARE_SIMPLE_TYPE(FSIBus, FSI_BUS)
@@ -16,4 +23,16 @@ typedef struct FSIBus {
  BusState bus;
  } FSIBus;
  
+#define TYPE_FSI_SLAVE "fsi.slave"

+OBJECT_DECLARE_SIMPLE_TYPE(FSISlaveState, FSI_SLAVE)
+
+#define FSI_SLAVE_CONTROL_NR_REGS ((0x40 >> 2) + 1)
+
+typedef struct FSISlaveState {
+DeviceState parent;
+
+MemoryRegion iomem;
+uint32_t regs[FSI_SLAVE_CONTROL_NR_REGS];
+} FSISlaveState;
+
  #endif /* FSI_FSI_H */
diff --git a/hw/fsi/fsi.c b/hw/fsi/fsi.c
index 60cb03f7a2..528323d9cf 100644
--- a/hw/fsi/fsi.c
+++ b/hw/fsi/fsi.c
@@ -5,18 +5,101 @@
   * IBM Flexible Service Interface
   */
  #include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu/log.h"
+#include "trace.h"
  
  #include "hw/fsi/fsi.h"
  
+#define TO_REG(x)   ((x) >> 2)

+
  static const TypeInfo fsi_bus_info = {
  .name = TYPE_FSI_BUS,
  .parent = TYPE_BUS,
  .instance_size = sizeof(FSIBus),
  };
  
-static void fsi_bus_register_types(void)

+static uint64_t fsi_slave_read(void *opaque, hwaddr addr, unsigned size)
+{
+FSISlaveState *s = FSI_SLAVE(opaque);
+int reg = TO_REG(addr);
+
+trace_fsi_slave_read(addr, size);
+
+if (reg >= FSI_SLAVE_CONTROL_NR_REGS) {
+qemu_log_mask(LOG_GUEST_ERROR,
+  "%s: Out of bounds read: 0x%"HWADDR_PRIx" for %u\n",
+  __func__, addr, size);
+return 0;
+}
+
+return s->regs[reg];
+}
+
+static void fsi_slave_write(void *opaque, hwaddr addr, uint64_t data,
+ unsigned size)
+{
+FSISlaveState *s = FSI_SLAVE(opaque);
+int reg = TO_REG(addr);
+
+trace_fsi_slave_write(addr, size, data);
+
+if (reg >= FSI_SLAVE_CONTROL_NR_REGS) {
+qemu_log_mask(LOG_GUEST_ERROR,
+  "%s: Out of bounds write: 0x%"HWADDR_PRIx" for %u\n",
+  __func__, addr, size);
+return;
+}
+
+s->regs[reg] = data;
+}
+
+static const struct MemoryRegionOps fsi_slave_ops = {
+.read = fsi_slave_read,
+.write = fsi_slave_write,
+.endianness = DEVICE_BIG_ENDIAN,
+};
+
+static void fsi_slave_reset(DeviceState *dev)
+{
+FSISlaveState *s = FSI_SLAVE(dev);
+int i;
+
+    /* Initialize registers */
+for (i = 0; i < FSI_SLAVE_CONTROL_NR_REGS; i++) {
+s->regs[i] = 0;
+}


memset would be better.

with that fixed,


Reviewed-by: Cédric Le Goater 

Thanks,

C.



+}
+
+static void fsi_slave_init(Object *o)
+{
+FSISlaveState *s = FSI_SLAVE(o);
+
+memory_region_init_io(>iomem, OBJECT(s), _slave_ops,
+  s, TYPE_FSI_SLAVE, 0x400);
+}
+
+static void fsi_slave_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+
+dc->bus_type = TYPE_FSI_BUS;
+dc->desc = "FSI Slave";
+dc->reset = fsi_slave_reset;
+}
+
+static const TypeInfo fsi_slave_info = {
+.name = TYPE_FSI_SLAVE,
+.parent = TYPE_DEVICE,
+.instance_init = fsi_slave_init,
+.instance_size = sizeof(FSISlaveState),
+.class_init = fsi_slave_class_init,
+};
+
+static void fsi_register_types(void)
  {
  type_register_static(_bus_info);
+type_register_static(_slave_info);
  }
  
-type_init(fsi_bus_register_types);

+type_init(fsi_register_types);
diff --git a/hw/fsi/trace-events b/hw/fsi/trace-events
index c5753e2791..8f29adb7df 100644
--- a/hw/fsi/trace-events
+++ b/hw/fsi/trace-events
@@ -1,2 +1,4 @@
  fsi_scratchpad_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d"
  fsi_scratchpad_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " 
size=%d value=0x%"PRIx64
+fsi_slave_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d"
+fsi_slave_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " 
size=%d value=0x%"PRIx64





Re: [PATCH v11 03/11] hw/fsi: Introduce IBM's FSI Bus

2024-01-26 Thread Cédric Le Goater

On 1/26/24 04:40, Ninad Palsule wrote:

This is a part of patchset where FSI bus is introduced.

The FSI bus is a simple bus where FSI master is attached.

Signed-off-by: Andrew Jeffery 
[ clg: - removed include/hw/fsi/engine-scratchpad.h and
 hw/fsi/engine-scratchpad.c
- dropped FSI_SCRATCHPAD
- included FSIBus definition
- dropped hw/fsi/trace-events changes ]
Signed-off-by: Cédric Le Goater 
Signed-off-by: Ninad Palsule 



Reviewed-by: Cédric Le Goater 

Thanks,

C.




---
v11:
   - Split the patch.
---
  include/hw/fsi/fsi.h | 19 +++
  hw/fsi/fsi.c | 22 ++
  hw/fsi/meson.build   |  2 +-
  3 files changed, 42 insertions(+), 1 deletion(-)
  create mode 100644 include/hw/fsi/fsi.h
  create mode 100644 hw/fsi/fsi.c

diff --git a/include/hw/fsi/fsi.h b/include/hw/fsi/fsi.h
new file mode 100644
index 00..50e8f5c888
--- /dev/null
+++ b/include/hw/fsi/fsi.h
@@ -0,0 +1,19 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright (C) 2024 IBM Corp.
+ *
+ * IBM Flexible Service Interface
+ */
+#ifndef FSI_FSI_H
+#define FSI_FSI_H
+
+#include "hw/qdev-core.h"
+
+#define TYPE_FSI_BUS "fsi.bus"
+OBJECT_DECLARE_SIMPLE_TYPE(FSIBus, FSI_BUS)
+
+typedef struct FSIBus {
+BusState bus;
+} FSIBus;
+
+#endif /* FSI_FSI_H */
diff --git a/hw/fsi/fsi.c b/hw/fsi/fsi.c
new file mode 100644
index 00..60cb03f7a2
--- /dev/null
+++ b/hw/fsi/fsi.c
@@ -0,0 +1,22 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright (C) 2024 IBM Corp.
+ *
+ * IBM Flexible Service Interface
+ */
+#include "qemu/osdep.h"
+
+#include "hw/fsi/fsi.h"
+
+static const TypeInfo fsi_bus_info = {
+.name = TYPE_FSI_BUS,
+.parent = TYPE_BUS,
+.instance_size = sizeof(FSIBus),
+};
+
+static void fsi_bus_register_types(void)
+{
+type_register_static(_bus_info);
+}
+
+type_init(fsi_bus_register_types);
diff --git a/hw/fsi/meson.build b/hw/fsi/meson.build
index 93ba19dd04..574f5f9289 100644
--- a/hw/fsi/meson.build
+++ b/hw/fsi/meson.build
@@ -1 +1 @@
-system_ss.add(when: 'CONFIG_FSI', if_true: files('lbus.c'))
+system_ss.add(when: 'CONFIG_FSI', if_true: files('lbus.c','fsi.c'))





Re: [PATCH v11 02/11] hw/fsi: Introduce IBM's scratchpad device

2024-01-26 Thread Cédric Le Goater

On 1/26/24 04:40, Ninad Palsule wrote:

This is a part of patchset where IBM's Flexible Service Interface is
introduced.

The scratchpad provides a set of non-functional registers. The firmware
is free to use them, hardware does not support any special management
support. The scratchpad registers can be read or written from LBUS
slave. The scratch pad is managed under FSI CFAM state.

Signed-off-by: Andrew Jeffery 
[ clg: - moved object FSIScratchPad under FSICFAMState
- moved FSIScratchPad code under cfam.c ]
Signed-off-by: Cédric Le Goater 
Signed-off-by: Ninad Palsule 
---
  include/hw/fsi/lbus.h | 11 +++
  hw/fsi/lbus.c | 69 +++
  hw/fsi/trace-events   |  2 ++
  3 files changed, 82 insertions(+)

diff --git a/include/hw/fsi/lbus.h b/include/hw/fsi/lbus.h
index e8a22e22a8..558268c013 100644
--- a/include/hw/fsi/lbus.h
+++ b/include/hw/fsi/lbus.h
@@ -29,4 +29,15 @@ typedef struct FSILBus {
  MemoryRegion mr;
  } FSILBus;
  
+#define TYPE_FSI_SCRATCHPAD "fsi.scratchpad"

+#define SCRATCHPAD(obj) OBJECT_CHECK(FSIScratchPad, (obj), TYPE_FSI_SCRATCHPAD)
+
+#define FSI_SCRATCHPAD_NR_REGS 4
+
+typedef struct FSIScratchPad {
+FSILBusDevice parent;
+
+uint32_t regs[FSI_SCRATCHPAD_NR_REGS];
+} FSIScratchPad;
+
  #endif /* FSI_LBUS_H */
diff --git a/hw/fsi/lbus.c b/hw/fsi/lbus.c
index 44d2319087..5ab7d0a741 100644
--- a/hw/fsi/lbus.c
+++ b/hw/fsi/lbus.c
@@ -13,6 +13,8 @@
  
  #include "trace.h"
  
+#define TO_REG(offset) ((offset) >> 2)

+
  static void fsi_lbus_init(Object *o)
  {
  FSILBus *lbus = FSI_LBUS(o);
@@ -34,10 +36,77 @@ static const TypeInfo fsi_lbus_device_type_info = {
  .abstract = true,
  };
  
+static uint64_t fsi_scratchpad_read(void *opaque, hwaddr addr, unsigned size)

+{
+FSIScratchPad *s = SCRATCHPAD(opaque);
+int reg = TO_REG(addr);
+
+trace_fsi_scratchpad_read(addr, size);
+
+if (reg >= FSI_SCRATCHPAD_NR_REGS) {


usually, the model logs a GUEST_ERROR in such case, specially when the MMIO
window is larger than the register set. Same comment for the write memop.

with that,
 
Reviewed-by: Cédric Le Goater 


Thanks,

C.




+return 0;
+}
+
+return s->regs[reg];
+}
+
+static void fsi_scratchpad_write(void *opaque, hwaddr addr, uint64_t data,
+ unsigned size)
+{
+FSIScratchPad *s = SCRATCHPAD(opaque);
+
+trace_fsi_scratchpad_write(addr, size, data);
+int reg = TO_REG(addr);
+
+if (reg >= FSI_SCRATCHPAD_NR_REGS) {
+return;
+}
+
+s->regs[reg] = data;
+}
+
+static const struct MemoryRegionOps scratchpad_ops = {
+.read = fsi_scratchpad_read,
+.write = fsi_scratchpad_write,
+.endianness = DEVICE_BIG_ENDIAN,
+};
+
+static void fsi_scratchpad_realize(DeviceState *dev, Error **errp)
+{
+FSILBusDevice *ldev = FSI_LBUS_DEVICE(dev);
+
+memory_region_init_io(>iomem, OBJECT(ldev), _ops,
+  ldev, TYPE_FSI_SCRATCHPAD, 0x400);
+}
+
+static void fsi_scratchpad_reset(DeviceState *dev)
+{
+FSIScratchPad *s = SCRATCHPAD(dev);
+
+memset(s->regs, 0, sizeof(s->regs));
+}
+
+static void fsi_scratchpad_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+
+dc->bus_type = TYPE_FSI_LBUS;
+dc->realize = fsi_scratchpad_realize;
+dc->reset = fsi_scratchpad_reset;
+}
+
+static const TypeInfo fsi_scratchpad_info = {
+.name = TYPE_FSI_SCRATCHPAD,
+.parent = TYPE_FSI_LBUS_DEVICE,
+.instance_size = sizeof(FSIScratchPad),
+.class_init = fsi_scratchpad_class_init,
+};
+
  static void fsi_lbus_register_types(void)
  {
  type_register_static(_lbus_info);
  type_register_static(_lbus_device_type_info);
+type_register_static(_scratchpad_info);
  }
  
  type_init(fsi_lbus_register_types);

diff --git a/hw/fsi/trace-events b/hw/fsi/trace-events
index e69de29bb2..c5753e2791 100644
--- a/hw/fsi/trace-events
+++ b/hw/fsi/trace-events
@@ -0,0 +1,2 @@
+fsi_scratchpad_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d"
+fsi_scratchpad_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " 
size=%d value=0x%"PRIx64





Re: [PATCH v11 01/11] hw/fsi: Introduce IBM's Local bus

2024-01-26 Thread Cédric Le Goater

On 1/26/24 04:40, Ninad Palsule wrote:

This is a part of patchset where IBM's Flexible Service Interface is
introduced.

The LBUS is modelled to maintain mapped memory for the devices. The
memory is mapped after CFAM config, peek table and FSI slave registers.

Signed-off-by: Andrew Jeffery 
[ clg: - removed lbus_add_device() bc unused
- removed lbus_create_device() bc used only once
- removed "address" property
- updated meson.build to build fsi dir
- included an empty hw/fsi/trace-events ]
Signed-off-by: Cédric Le Goater 
Signed-off-by: Ninad Palsule 



Reviewed-by: Cédric Le Goater 

Thanks,

C.



---
v9:
   - Changed LBUS memory region to 1MB.
v11:
   - Split lbus and scratchpad into separate patches.
   - Added fsi_ prefix for all functions in lbus.
   - Removed FSI_LBUS* typedefs.
   - Replaced for loop with memset.
---
  meson.build   |  1 +
  hw/fsi/trace.h|  1 +
  include/hw/fsi/lbus.h | 32 
  hw/fsi/lbus.c | 43 +++
  hw/Kconfig|  1 +
  hw/fsi/Kconfig|  2 ++
  hw/fsi/meson.build|  1 +
  hw/fsi/trace-events   |  0
  hw/meson.build|  1 +
  9 files changed, 82 insertions(+)
  create mode 100644 hw/fsi/trace.h
  create mode 100644 include/hw/fsi/lbus.h
  create mode 100644 hw/fsi/lbus.c
  create mode 100644 hw/fsi/Kconfig
  create mode 100644 hw/fsi/meson.build
  create mode 100644 hw/fsi/trace-events

diff --git a/meson.build b/meson.build
index d0329966f1..7d926c6e82 100644
--- a/meson.build
+++ b/meson.build
@@ -3290,6 +3290,7 @@ if have_system
  'hw/char',
  'hw/display',
  'hw/dma',
+'hw/fsi',
  'hw/hyperv',
  'hw/i2c',
  'hw/i386',
diff --git a/hw/fsi/trace.h b/hw/fsi/trace.h
new file mode 100644
index 00..ee67c7fb04
--- /dev/null
+++ b/hw/fsi/trace.h
@@ -0,0 +1 @@
+#include "trace/trace-hw_fsi.h"
diff --git a/include/hw/fsi/lbus.h b/include/hw/fsi/lbus.h
new file mode 100644
index 00..e8a22e22a8
--- /dev/null
+++ b/include/hw/fsi/lbus.h
@@ -0,0 +1,32 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright (C) 2024 IBM Corp.
+ *
+ * IBM Local bus and connected device structures.
+ */
+#ifndef FSI_LBUS_H
+#define FSI_LBUS_H
+
+#include "hw/qdev-core.h"
+#include "qemu/units.h"
+#include "exec/memory.h"
+
+#define TYPE_FSI_LBUS_DEVICE "fsi.lbus.device"
+OBJECT_DECLARE_SIMPLE_TYPE(FSILBusDevice, FSI_LBUS_DEVICE)
+
+typedef struct FSILBusDevice {
+DeviceState parent;
+
+MemoryRegion iomem;
+} FSILBusDevice;
+
+#define TYPE_FSI_LBUS "fsi.lbus"
+OBJECT_DECLARE_SIMPLE_TYPE(FSILBus, FSI_LBUS)
+
+typedef struct FSILBus {
+BusState bus;
+
+MemoryRegion mr;
+} FSILBus;
+
+#endif /* FSI_LBUS_H */
diff --git a/hw/fsi/lbus.c b/hw/fsi/lbus.c
new file mode 100644
index 00..44d2319087
--- /dev/null
+++ b/hw/fsi/lbus.c
@@ -0,0 +1,43 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright (C) 2024 IBM Corp.
+ *
+ * IBM Local bus where FSI slaves are connected
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "hw/fsi/lbus.h"
+
+#include "hw/qdev-properties.h"
+
+#include "trace.h"
+
+static void fsi_lbus_init(Object *o)
+{
+FSILBus *lbus = FSI_LBUS(o);
+
+memory_region_init(>mr, OBJECT(lbus), TYPE_FSI_LBUS, 1 * MiB);
+}
+
+static const TypeInfo fsi_lbus_info = {
+.name = TYPE_FSI_LBUS,
+.parent = TYPE_BUS,
+.instance_init = fsi_lbus_init,
+.instance_size = sizeof(FSILBus),
+};
+
+static const TypeInfo fsi_lbus_device_type_info = {
+.name = TYPE_FSI_LBUS_DEVICE,
+.parent = TYPE_DEVICE,
+.instance_size = sizeof(FSILBusDevice),
+.abstract = true,
+};
+
+static void fsi_lbus_register_types(void)
+{
+type_register_static(_lbus_info);
+type_register_static(_lbus_device_type_info);
+}
+
+type_init(fsi_lbus_register_types);
diff --git a/hw/Kconfig b/hw/Kconfig
index 9ca7b38c31..2c00936c28 100644
--- a/hw/Kconfig
+++ b/hw/Kconfig
@@ -9,6 +9,7 @@ source core/Kconfig
  source cxl/Kconfig
  source display/Kconfig
  source dma/Kconfig
+source fsi/Kconfig
  source gpio/Kconfig
  source hyperv/Kconfig
  source i2c/Kconfig
diff --git a/hw/fsi/Kconfig b/hw/fsi/Kconfig
new file mode 100644
index 00..9c34a418d7
--- /dev/null
+++ b/hw/fsi/Kconfig
@@ -0,0 +1,2 @@
+config FSI
+bool
diff --git a/hw/fsi/meson.build b/hw/fsi/meson.build
new file mode 100644
index 00..93ba19dd04
--- /dev/null
+++ b/hw/fsi/meson.build
@@ -0,0 +1 @@
+system_ss.add(when: 'CONFIG_FSI', if_true: files('lbus.c'))
diff --git a/hw/fsi/trace-events b/hw/fsi/trace-events
new file mode 100644
index 00..e69de29bb2
diff --git a/hw/meson.build b/hw/meson.build
index f01fac4617..463d702683 100644
--- a/hw/meson.build
+++ b/hw/meson.build
@@ -44,6 +44,7 @@ subdir('virtio')
  subdir('watchdog')
  subdir('xen')
  subdir('xenpv')
+subdir('fsi')
  
  subdir('alpha')

  subdir('arm')





Re: [PATCH v7 9/9] ppc/pnv: Test pnv i2c master and connected devices

2024-01-25 Thread Cédric Le Goater

On 1/25/24 23:48, Glenn Miles wrote:

Tests the following for both P9 and P10:
   - I2C master POR status
   - I2C master status after immediate reset

Tests the following for powernv10-ranier only:
   - Config pca9552 hotplug device pins as inputs then
 Read the INPUT0/1 registers to verify all pins are high
   - Connected GPIO pin tests of P10 PCA9552 device.  Tests
 output of pins 0-4 affect input of pins 5-9 respectively.
   - PCA9554 GPIO pins test.  Tests input and ouput functionality.

Reviewed-by: Cédric Le Goater 
Signed-off-by: Glenn Miles 
---

Changes from previous version:
   - Moved PNV I2C register definitions from pnv-host-i2c-test.c and
 pnv_i2c.c into pnv_i2c_regs.h.
   - Moved PNV XSCOM definitions from pnv-host-i2c-test.c and
 pnv-xscom-test.c into pnv-xscom.h.
   - Renamed pnv_i2c_dev_t to PnvI2cDev.
   - Added PnvI2cCtlr structure for conveniece in passing parameters.


LGTM. Thanks for doing the proposed changes.

If you add more tests in the future, you could consider splitting "host-i2c"
in subtests. No need to resend for that.

C.




  hw/ppc/pnv_i2c.c| 131 +
  include/hw/i2c/pnv_i2c_regs.h   | 143 ++
  tests/qtest/meson.build |   1 +
  tests/qtest/pnv-host-i2c-test.c | 491 
  tests/qtest/pnv-xscom-test.c|  61 +---
  tests/qtest/pnv-xscom.h |  80 ++
  6 files changed, 717 insertions(+), 190 deletions(-)
  create mode 100644 include/hw/i2c/pnv_i2c_regs.h
  create mode 100644 tests/qtest/pnv-host-i2c-test.c
  create mode 100644 tests/qtest/pnv-xscom.h

diff --git a/hw/ppc/pnv_i2c.c b/hw/ppc/pnv_i2c.c
index 774946d6b2..4581cc5e5d 100644
--- a/hw/ppc/pnv_i2c.c
+++ b/hw/ppc/pnv_i2c.c
@@ -22,136 +22,7 @@
  
  #include 
  
-/* I2C FIFO register */

-#define I2C_FIFO_REG0x4
-#define I2C_FIFOPPC_BITMASK(0, 7)
-
-/* I2C command register */
-#define I2C_CMD_REG 0x5
-#define I2C_CMD_WITH_START  PPC_BIT(0)
-#define I2C_CMD_WITH_ADDR   PPC_BIT(1)
-#define I2C_CMD_READ_CONT   PPC_BIT(2)
-#define I2C_CMD_WITH_STOP   PPC_BIT(3)
-#define I2C_CMD_INTR_STEERING   PPC_BITMASK(6, 7) /* P9 */
-#define   I2C_CMD_INTR_STEER_HOST   1
-#define   I2C_CMD_INTR_STEER_OCC2
-#define I2C_CMD_DEV_ADDRPPC_BITMASK(8, 14)
-#define I2C_CMD_READ_NOT_WRITE  PPC_BIT(15)
-#define I2C_CMD_LEN_BYTES   PPC_BITMASK(16, 31)
-#define I2C_MAX_TFR_LEN 0xfff0ull
-
-/* I2C mode register */
-#define I2C_MODE_REG0x6
-#define I2C_MODE_BIT_RATE_DIV   PPC_BITMASK(0, 15)
-#define I2C_MODE_PORT_NUM   PPC_BITMASK(16, 21)
-#define I2C_MODE_ENHANCED   PPC_BIT(28)
-#define I2C_MODE_DIAGNOSTIC PPC_BIT(29)
-#define I2C_MODE_PACING_ALLOW   PPC_BIT(30)
-#define I2C_MODE_WRAP   PPC_BIT(31)
-
-/* I2C watermark register */
-#define I2C_WATERMARK_REG   0x7
-#define I2C_WATERMARK_HIGH  PPC_BITMASK(16, 19)
-#define I2C_WATERMARK_LOW   PPC_BITMASK(24, 27)
-
-/*
- * I2C interrupt mask and condition registers
- *
- * NB: The function of 0x9 and 0xa changes depending on whether you're reading
- * or writing to them. When read they return the interrupt condition bits
- * and on writes they update the interrupt mask register.
- *
- *  The bit definitions are the same for all the interrupt registers.
- */
-#define I2C_INTR_MASK_REG   0x8
-
-#define I2C_INTR_RAW_COND_REG   0x9 /* read */
-#define I2C_INTR_MASK_OR_REG0x9 /* write*/
-
-#define I2C_INTR_COND_REG   0xa /* read */
-#define I2C_INTR_MASK_AND_REG   0xa /* write */
-
-#define I2C_INTR_ALLPPC_BITMASK(16, 31)
-#define I2C_INTR_INVALID_CMDPPC_BIT(16)
-#define I2C_INTR_LBUS_PARITY_ERRPPC_BIT(17)
-#define I2C_INTR_BKEND_OVERRUN_ERR  PPC_BIT(18)
-#define I2C_INTR_BKEND_ACCESS_ERR   PPC_BIT(19)
-#define I2C_INTR_ARBT_LOST_ERR  PPC_BIT(20)
-#define I2C_INTR_NACK_RCVD_ERR  PPC_BIT(21)
-#define I2C_INTR_DATA_REQ   PPC_BIT(22)
-#define I2C_INTR_CMD_COMP   PPC_BIT(23)
-#define I2C_INTR_STOP_ERR   PPC_BIT(24)
-#define I2C_INTR_I2C_BUSY   PPC_BIT(25)
-#define I2C_INTR_NOT_I2C_BUSY   PPC_BIT(26)
-#define I2C_INTR_SCL_EQ_1   PPC_BIT(28)
-#define I2C_INTR_SCL_EQ_0   PPC_BIT(29)
-#define I2C_INTR_SDA_EQ_1   PPC_BIT(30)
-#define I2C_INTR_SDA_EQ_0   PPC_BIT(31)
-
-/* I2C status register */
-#define I2C_RESET_I2C_REG   0xb /* write */
-#define I2C_RESET_ERRORS0xc
-#define I2C_STAT_REG0xb /* read */
-#define I2C_STAT_INVALID_CMDPPC_BIT(0)
-#define I2C_STAT_LBUS_PARITY_ERRPPC_BIT(1)
-#define I2C_STAT_BKEND_O

Re: [PATCH] vfio/pci: Clear MSI-X IRQ index always

2024-01-25 Thread Cédric Le Goater

On 1/25/24 15:42, Cédric Le Goater wrote:

When doing device assignment of a physical device, MSI-X can be
enabled with no vectors enabled and this sets the IRQ index to
VFIO_PCI_MSIX_IRQ_INDEX. However, when MSI-X is disabled, the IRQ
index is left untouched if no vectors are in use. Then, when INTx
is enabled, the IRQ index value is considered incompatible (set to
MSI-X) and VFIO_DEVICE_SET_IRQS fails. QEMU complains with :

qemu-system-x86_64: vfio :08:00.0: Failed to set up TRIGGER eventfd 
signaling for interrupt INTX-0: VFIO_DEVICE_SET_IRQS failure: Invalid argument

To avoid that, unconditionaly clear the IRQ index when MSI-X is
disabled.



Applied to vfio-next.

Thanks,

C.







[PATCH] vfio/pci: Clear MSI-X IRQ index always

2024-01-25 Thread Cédric Le Goater
When doing device assignment of a physical device, MSI-X can be
enabled with no vectors enabled and this sets the IRQ index to
VFIO_PCI_MSIX_IRQ_INDEX. However, when MSI-X is disabled, the IRQ
index is left untouched if no vectors are in use. Then, when INTx
is enabled, the IRQ index value is considered incompatible (set to
MSI-X) and VFIO_DEVICE_SET_IRQS fails. QEMU complains with :

qemu-system-x86_64: vfio :08:00.0: Failed to set up TRIGGER eventfd 
signaling for interrupt INTX-0: VFIO_DEVICE_SET_IRQS failure: Invalid argument

To avoid that, unconditionaly clear the IRQ index when MSI-X is
disabled.

Buglink: https://issues.redhat.com/browse/RHEL-21293
Fixes: 5ebffa4e87e7 ("vfio/pci: use an invalid fd to enable MSI-X")
Cc: Jing Liu 
Cc: Alex Williamson 
Signed-off-by: Cédric Le Goater 
---
 hw/vfio/pci.c | 8 +---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
index 
d7fe06715c4b9cde66a68c31aaf405315921b0d6..4fa387f0430d62ca2ba1b5ae5b7037f8f06b33f9
 100644
--- a/hw/vfio/pci.c
+++ b/hw/vfio/pci.c
@@ -826,9 +826,11 @@ static void vfio_msix_disable(VFIOPCIDevice *vdev)
 }
 }
 
-if (vdev->nr_vectors) {
-vfio_disable_irqindex(>vbasedev, VFIO_PCI_MSIX_IRQ_INDEX);
-}
+/*
+ * Always clear MSI-X IRQ index. A PF device could have enabled
+ * MSI-X with no vectors. See vfio_msix_enable().
+ */
+vfio_disable_irqindex(>vbasedev, VFIO_PCI_MSIX_IRQ_INDEX);
 
 vfio_msi_disable_common(vdev);
 vfio_intx_enable(vdev, );
-- 
2.43.0




Re: [PATCH] ppc/pnv: Improve pervasive topology calculation for big-core

2024-01-25 Thread Cédric Le Goater

Hello Caleb,

On 1/23/24 20:50, Caleb Schlossin wrote:

Big (SMT8) cores have a complicated function to map the core, thread ID
to pervasive topology (PIR). Fix this for power8, power9, and power10.

Signed-off-by: Caleb Schlossin 


Thanks for these changes. Looks OK.

Support for fused core will require more work, a new CPU PVR, may be with
a machine "fused=on/off" option, and various adjustements in the models.
I hope you find time to upstream these changes at least for OPAL/P10.

Reviewed-by: Cédric Le Goater 

C.



---
  include/hw/ppc/pnv_chip.h |  2 +-
  include/hw/ppc/pnv_core.h |  1 +
  hw/ppc/pnv.c  | 60 ++-
  hw/ppc/pnv_core.c |  8 +++---
  target/ppc/misc_helper.c  |  3 --
  5 files changed, 46 insertions(+), 28 deletions(-)

diff --git a/include/hw/ppc/pnv_chip.h b/include/hw/ppc/pnv_chip.h
index 0ab5c42308..d77e63b0a4 100644
--- a/include/hw/ppc/pnv_chip.h
+++ b/include/hw/ppc/pnv_chip.h
@@ -142,7 +142,7 @@ struct PnvChipClass {
  
  DeviceRealize parent_realize;
  
-uint32_t (*core_pir)(PnvChip *chip, uint32_t core_id);

+uint32_t (*chip_pir)(PnvChip *chip, uint32_t core_id, uint32_t thread_id);
  void (*intc_create)(PnvChip *chip, PowerPCCPU *cpu, Error **errp);
  void (*intc_reset)(PnvChip *chip, PowerPCCPU *cpu);
  void (*intc_destroy)(PnvChip *chip, PowerPCCPU *cpu);
diff --git a/include/hw/ppc/pnv_core.h b/include/hw/ppc/pnv_core.h
index 4db21229a6..c6d62fd145 100644
--- a/include/hw/ppc/pnv_core.h
+++ b/include/hw/ppc/pnv_core.h
@@ -36,6 +36,7 @@ struct PnvCore {
  /*< public >*/
  PowerPCCPU **threads;
  uint32_t pir;
+uint32_t hwid;
  uint64_t hrmor;
  PnvChip *chip;
  
diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c

index 0297871bdd..9964f2665a 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -141,8 +141,10 @@ static void pnv_dt_core(PnvChip *chip, PnvCore *pc, void 
*fdt)
  int smt_threads = CPU_CORE(pc)->nr_threads;
  CPUPPCState *env = >env;
  PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs);
+PnvChipClass *pnv_cc = PNV_CHIP_GET_CLASS(chip);
  g_autofree uint32_t *servers_prop = g_new(uint32_t, smt_threads);
  int i;
+uint32_t pir;
  uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40),
 0x, 0x};
  uint32_t tbfreq = PNV_TIMEBASE_FREQ;
@@ -158,15 +160,17 @@ static void pnv_dt_core(PnvChip *chip, PnvCore *pc, void 
*fdt)
  char *nodename;
  int cpus_offset = get_cpus_node(fdt);
  
-nodename = g_strdup_printf("%s@%x", dc->fw_name, pc->pir);

+pir = pnv_cc->chip_pir(chip, pc->hwid, 0);
+
+nodename = g_strdup_printf("%s@%x", dc->fw_name, pir);
  offset = fdt_add_subnode(fdt, cpus_offset, nodename);
  _FDT(offset);
  g_free(nodename);
  
  _FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id", chip->chip_id)));
  
-_FDT((fdt_setprop_cell(fdt, offset, "reg", pc->pir)));

-_FDT((fdt_setprop_cell(fdt, offset, "ibm,pir", pc->pir)));
+_FDT((fdt_setprop_cell(fdt, offset, "reg", pir)));
+_FDT((fdt_setprop_cell(fdt, offset, "ibm,pir", pir)));
  _FDT((fdt_setprop_string(fdt, offset, "device_type", "cpu")));
  
  _FDT((fdt_setprop_cell(fdt, offset, "cpu-version", env->spr[SPR_PVR])));

@@ -241,15 +245,17 @@ static void pnv_dt_core(PnvChip *chip, PnvCore *pc, void 
*fdt)
  
  /* Build interrupt servers properties */

  for (i = 0; i < smt_threads; i++) {
-servers_prop[i] = cpu_to_be32(pc->pir + i);
+servers_prop[i] = cpu_to_be32(pnv_cc->chip_pir(chip, pc->hwid, i));
  }
  _FDT((fdt_setprop(fdt, offset, "ibm,ppc-interrupt-server#s",
 servers_prop, sizeof(*servers_prop) * smt_threads)));
  }
  
-static void pnv_dt_icp(PnvChip *chip, void *fdt, uint32_t pir,

+static void pnv_dt_icp(PnvChip *chip, void *fdt, uint32_t hwid,
 uint32_t nr_threads)
  {
+PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
+uint32_t pir = pcc->chip_pir(chip, hwid, 0);
  uint64_t addr = PNV_ICP_BASE(chip) | (pir << 12);
  char *name;
  const char compat[] = "IBM,power8-icp\0IBM,ppc-xicp";
@@ -263,6 +269,7 @@ static void pnv_dt_icp(PnvChip *chip, void *fdt, uint32_t 
pir,
  rsize = sizeof(uint64_t) * 2 * nr_threads;
  reg = g_malloc(rsize);
  for (i = 0; i < nr_threads; i++) {
+/* We know P8 PIR is linear with thread id */
  reg[i * 2] = cpu_to_be64(addr | ((pir + i) * 0x1000));
  reg[i * 2 + 1] = cpu_to_be64(0x1000);
  }
@@ -315,7 +322,7 @@ static void pnv_chip_power8_dt_populate(PnvChip *chip, void 
*fdt)
  pnv_dt_core(chip, pnv_core, fdt);
  
  /* Interrupt Control Presenters (ICP). One per core. */

-pnv_dt_icp(chip, fdt, pnv_core->pir

Re: [PATCH 6/6] target/ppc: optimise ppcemb_tlb_t flushing

2024-01-25 Thread Cédric Le Goater

On 1/17/24 16:12, Nicholas Piggin wrote:

Filter TLB flushing by PID and mmuidx.

Zoltan reports that, together with the previous TLB flush changes,
performance of a sam460ex machine running lame to convert a wav to mp3
is improved nearly 10%:

   CPU timeTLB partial flushes  TLB elided flushes
Before37s 508238   7680722
After 34s 73  1143

Signed-off-by: Nicholas Piggin 




Acked-by: Cédric Le Goater 

Thanks,

C.



---
  target/ppc/mmu_helper.c | 43 +++--
  1 file changed, 37 insertions(+), 6 deletions(-)

diff --git a/target/ppc/mmu_helper.c b/target/ppc/mmu_helper.c
index ba965f1779..c071b4d5e2 100644
--- a/target/ppc/mmu_helper.c
+++ b/target/ppc/mmu_helper.c
@@ -751,11 +751,20 @@ target_ulong helper_4xx_tlbre_lo(CPUPPCState *env, 
target_ulong entry)
  
  static void ppcemb_tlb_flush(CPUState *cs, ppcemb_tlb_t *tlb)

  {
-target_ulong ea;
+unsigned mmu_idx = 0;
  
-for (ea = tlb->EPN; ea < tlb->EPN + tlb->size; ea += TARGET_PAGE_SIZE) {

-tlb_flush_page(cs, ea);
+if (tlb->prot & 0xf) {
+mmu_idx |= 0x1;
  }
+if ((tlb->prot >> 4) & 0xf) {
+mmu_idx |= 0x2;
+}
+if (tlb->attr & 1) {
+mmu_idx <<= 2;
+}
+
+tlb_flush_range_by_mmuidx(cs, tlb->EPN, tlb->size, mmu_idx,
+  TARGET_LONG_BITS);
  }
  
  void helper_4xx_tlbwe_hi(CPUPPCState *env, target_ulong entry,

@@ -770,7 +779,7 @@ void helper_4xx_tlbwe_hi(CPUPPCState *env, target_ulong 
entry,
  entry &= PPC4XX_TLB_ENTRY_MASK;
  tlb = >tlb.tlbe[entry];
  /* Invalidate previous TLB (if it's valid) */
-if (tlb->prot & PAGE_VALID) {
+if ((tlb->prot & PAGE_VALID) && tlb->PID == env->spr[SPR_40x_PID]) {
  qemu_log_mask(CPU_LOG_MMU, "%s: invalidate old TLB %d start "
TARGET_FMT_lx " end " TARGET_FMT_lx "\n", __func__,
(int)entry, tlb->EPN, tlb->EPN + tlb->size);
@@ -821,7 +830,7 @@ void helper_4xx_tlbwe_lo(CPUPPCState *env, target_ulong 
entry,
  entry &= PPC4XX_TLB_ENTRY_MASK;
  tlb = >tlb.tlbe[entry];
  /* Invalidate previous TLB (if it's valid) */
-if (tlb->prot & PAGE_VALID) {
+if ((tlb->prot & PAGE_VALID) && tlb->PID == env->spr[SPR_40x_PID]) {
  qemu_log_mask(CPU_LOG_MMU, "%s: invalidate old TLB %d start "
TARGET_FMT_lx " end " TARGET_FMT_lx "\n", __func__,
(int)entry, tlb->EPN, tlb->EPN + tlb->size);
@@ -851,6 +860,25 @@ target_ulong helper_4xx_tlbsx(CPUPPCState *env, 
target_ulong address)
  return ppcemb_tlb_search(env, address, env->spr[SPR_40x_PID]);
  }
  
+static bool mmubooke_pid_match(CPUPPCState *env, ppcemb_tlb_t *tlb)

+{
+if (tlb->PID == env->spr[SPR_BOOKE_PID]) {
+return true;
+}
+if (!env->nb_pids) {
+return false;
+}
+
+if (env->spr[SPR_BOOKE_PID1] && tlb->PID == env->spr[SPR_BOOKE_PID1]) {
+return true;
+}
+if (env->spr[SPR_BOOKE_PID2] && tlb->PID == env->spr[SPR_BOOKE_PID2]) {
+return true;
+}
+
+return false;
+}
+
  /* PowerPC 440 TLB management */
  void helper_440_tlbwe(CPUPPCState *env, uint32_t word, target_ulong entry,
target_ulong value)
@@ -863,7 +891,10 @@ void helper_440_tlbwe(CPUPPCState *env, uint32_t word, 
target_ulong entry,
  tlb = >tlb.tlbe[entry];
  
  /* Invalidate previous TLB (if it's valid) */

-if (tlb->prot & PAGE_VALID) {
+if ((tlb->prot & PAGE_VALID) && mmubooke_pid_match(env, tlb)) {
+qemu_log_mask(CPU_LOG_MMU, "%s: invalidate old TLB %d start "
+  TARGET_FMT_lx " end " TARGET_FMT_lx "\n", __func__,
+  (int)entry, tlb->EPN, tlb->EPN + tlb->size);
  ppcemb_tlb_flush(env_cpu(env), tlb);
  }
  





Re: [PATCH 4/6] target/ppc: 4xx optimise tlbwe_lo TLB flushing

2024-01-25 Thread Cédric Le Goater

On 1/17/24 16:12, Nicholas Piggin wrote:

Rather than tlbwe_lo always flushing all TCG TLBs, have it flush just
those corresponding to the old software TLB, and only if it was valid.

Signed-off-by: Nicholas Piggin 




Acked-by: Cédric Le Goater 

Thanks,

C.


---
  target/ppc/mmu_helper.c | 10 --
  1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/target/ppc/mmu_helper.c b/target/ppc/mmu_helper.c
index 68632bf54e..923779d052 100644
--- a/target/ppc/mmu_helper.c
+++ b/target/ppc/mmu_helper.c
@@ -813,12 +813,20 @@ void helper_4xx_tlbwe_hi(CPUPPCState *env, target_ulong 
entry,
  void helper_4xx_tlbwe_lo(CPUPPCState *env, target_ulong entry,
   target_ulong val)
  {
+CPUState *cs = env_cpu(env);
  ppcemb_tlb_t *tlb;
  
  qemu_log_mask(CPU_LOG_MMU, "%s entry %i val " TARGET_FMT_lx "\n",

__func__, (int)entry, val);
  entry &= PPC4XX_TLB_ENTRY_MASK;
  tlb = >tlb.tlbe[entry];
+/* Invalidate previous TLB (if it's valid) */
+if (tlb->prot & PAGE_VALID) {
+qemu_log_mask(CPU_LOG_MMU, "%s: invalidate old TLB %d start "
+  TARGET_FMT_lx " end " TARGET_FMT_lx "\n", __func__,
+  (int)entry, tlb->EPN, tlb->EPN + tlb->size);
+ppcemb_tlb_flush(cs, tlb);
+}
  tlb->attr = val & PPC4XX_TLBLO_ATTR_MASK;
  tlb->RPN = val & PPC4XX_TLBLO_RPN_MASK;
  tlb->prot = PAGE_READ;
@@ -836,8 +844,6 @@ void helper_4xx_tlbwe_lo(CPUPPCState *env, target_ulong 
entry,
tlb->prot & PAGE_WRITE ? 'w' : '-',
tlb->prot & PAGE_EXEC ? 'x' : '-',
tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
-
-env->tlb_need_flush |= TLB_NEED_LOCAL_FLUSH;
  }
  
  target_ulong helper_4xx_tlbsx(CPUPPCState *env, target_ulong address)





Re: [PATCH 5/6] target/ppc: 440 optimise tlbwe TLB flushing

2024-01-25 Thread Cédric Le Goater

On 1/17/24 16:12, Nicholas Piggin wrote:

Have 440 tlbwe flush only the range corresponding to the addresses
covered by the software TLB entry being modified rather than the
entire TLB. This matches what 4xx does.

Signed-off-by: Nicholas Piggin 



Acked-by: Cédric Le Goater 

Thanks,

C.



---
  target/ppc/mmu_helper.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/ppc/mmu_helper.c b/target/ppc/mmu_helper.c
index 923779d052..ba965f1779 100644
--- a/target/ppc/mmu_helper.c
+++ b/target/ppc/mmu_helper.c
@@ -864,7 +864,7 @@ void helper_440_tlbwe(CPUPPCState *env, uint32_t word, 
target_ulong entry,
  
  /* Invalidate previous TLB (if it's valid) */

  if (tlb->prot & PAGE_VALID) {
-tlb_flush(env_cpu(env));
+ppcemb_tlb_flush(env_cpu(env), tlb);
  }
  
  switch (word) {





Re: [PATCH 3/6] target/ppc: 4xx don't flush TLB for a newly written software TLB entry

2024-01-25 Thread Cédric Le Goater

On 1/17/24 16:12, Nicholas Piggin wrote:

BookE software TLB is implemented by flushing old translations from the
relevant TCG TLB whenever software TLB entries change. This means a new
software TLB entry should not have any corresponding cached TCG TLB
translations, so there is nothing to flush. The exception is multiple
software TLBs that cover the same address and address space, but that
is a programming error and results in undefined behaviour, and flushing
does not give an obviously better outcome in that case either.

Remove the unnecessary flush of a newly written software TLB entry.

Signed-off-by: Nicholas Piggin 



Acked-by: Cédric Le Goater 

Thanks,

C.



---
  target/ppc/mmu_helper.c | 7 ---
  1 file changed, 7 deletions(-)

diff --git a/target/ppc/mmu_helper.c b/target/ppc/mmu_helper.c
index 949ae87f4f..68632bf54e 100644
--- a/target/ppc/mmu_helper.c
+++ b/target/ppc/mmu_helper.c
@@ -808,13 +808,6 @@ void helper_4xx_tlbwe_hi(CPUPPCState *env, target_ulong 
entry,
tlb->prot & PAGE_WRITE ? 'w' : '-',
tlb->prot & PAGE_EXEC ? 'x' : '-',
tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
-/* Invalidate new TLB (if valid) */
-if (tlb->prot & PAGE_VALID) {
-qemu_log_mask(CPU_LOG_MMU, "%s: invalidate TLB %d start "
-  TARGET_FMT_lx " end " TARGET_FMT_lx "\n", __func__,
-  (int)entry, tlb->EPN, tlb->EPN + tlb->size);
-ppcemb_tlb_flush(cs, tlb);
-}
  }
  
  void helper_4xx_tlbwe_lo(CPUPPCState *env, target_ulong entry,





Re: [PATCH 2/6] target/ppc: Factor out 4xx ppcemb_tlb_t flushing

2024-01-25 Thread Cédric Le Goater

On 1/17/24 16:12, Nicholas Piggin wrote:

Flushing the TCG TLB pages that cache a software TLB is a common
operation, factor it into its own function.

Signed-off-by: Nicholas Piggin 



Acked-by: Cédric Le Goater 

Thanks,

C.



---
  target/ppc/mmu_helper.c | 24 +---
  1 file changed, 13 insertions(+), 11 deletions(-)

diff --git a/target/ppc/mmu_helper.c b/target/ppc/mmu_helper.c
index c140f3c96d..949ae87f4f 100644
--- a/target/ppc/mmu_helper.c
+++ b/target/ppc/mmu_helper.c
@@ -749,12 +749,20 @@ target_ulong helper_4xx_tlbre_lo(CPUPPCState *env, 
target_ulong entry)
  return ret;
  }
  
+static void ppcemb_tlb_flush(CPUState *cs, ppcemb_tlb_t *tlb)

+{
+target_ulong ea;
+
+for (ea = tlb->EPN; ea < tlb->EPN + tlb->size; ea += TARGET_PAGE_SIZE) {
+tlb_flush_page(cs, ea);
+}
+}
+
  void helper_4xx_tlbwe_hi(CPUPPCState *env, target_ulong entry,
   target_ulong val)
  {
  CPUState *cs = env_cpu(env);
  ppcemb_tlb_t *tlb;
-target_ulong page, end;
  
  qemu_log_mask(CPU_LOG_MMU, "%s entry %d val " TARGET_FMT_lx "\n",

__func__, (int)entry,
@@ -763,13 +771,10 @@ void helper_4xx_tlbwe_hi(CPUPPCState *env, target_ulong 
entry,
  tlb = >tlb.tlbe[entry];
  /* Invalidate previous TLB (if it's valid) */
  if (tlb->prot & PAGE_VALID) {
-end = tlb->EPN + tlb->size;
  qemu_log_mask(CPU_LOG_MMU, "%s: invalidate old TLB %d start "
TARGET_FMT_lx " end " TARGET_FMT_lx "\n", __func__,
-  (int)entry, tlb->EPN, end);
-for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE) {
-tlb_flush_page(cs, page);
-}
+  (int)entry, tlb->EPN, tlb->EPN + tlb->size);
+ppcemb_tlb_flush(cs, tlb);
  }
  tlb->size = booke_tlb_to_page_size((val >> PPC4XX_TLBHI_SIZE_SHIFT)
 & PPC4XX_TLBHI_SIZE_MASK);
@@ -805,13 +810,10 @@ void helper_4xx_tlbwe_hi(CPUPPCState *env, target_ulong 
entry,
tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
  /* Invalidate new TLB (if valid) */
  if (tlb->prot & PAGE_VALID) {
-end = tlb->EPN + tlb->size;
  qemu_log_mask(CPU_LOG_MMU, "%s: invalidate TLB %d start "
TARGET_FMT_lx " end " TARGET_FMT_lx "\n", __func__,
-  (int)entry, tlb->EPN, end);
-for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE) {
-tlb_flush_page(cs, page);
-}
+  (int)entry, tlb->EPN, tlb->EPN + tlb->size);
+ppcemb_tlb_flush(cs, tlb);
  }
  }
  





Re: [PATCH 1/6] target/ppc: Fix 440 tlbwe TLB invalidation gaps

2024-01-25 Thread Cédric Le Goater

On 1/17/24 16:12, Nicholas Piggin wrote:

The 440 software TLB write entry misses several cases that must flush
the TCG TLB:
- If the new size is smaller than the existing size, the EA no longer
   covered should be flushed. This looks like an inverted inequality test.
- If the TLB PID changes.
- If the TLB attr bit 0 (translation address space) changes.
- If low prot (access control) bits change.

Fix this by removing tricks to avoid TLB flushes, and just invalidate
the TLB if any valid entry is being changed, similarly to 4xx.

Signed-off-by: Nicholas Piggin 



Acked-by: Cédric Le Goater 

Thanks,

C.

PS: A cover letter would have been nice :) I couldn't find it.



---
  target/ppc/mmu_helper.c | 35 ++-
  1 file changed, 10 insertions(+), 25 deletions(-)

diff --git a/target/ppc/mmu_helper.c b/target/ppc/mmu_helper.c
index f87d35379a..c140f3c96d 100644
--- a/target/ppc/mmu_helper.c
+++ b/target/ppc/mmu_helper.c
@@ -855,49 +855,34 @@ void helper_440_tlbwe(CPUPPCState *env, uint32_t word, 
target_ulong entry,
target_ulong value)
  {
  ppcemb_tlb_t *tlb;
-target_ulong EPN, RPN, size;
-int do_flush_tlbs;
  
  qemu_log_mask(CPU_LOG_MMU, "%s word %d entry %d value " TARGET_FMT_lx "\n",

__func__, word, (int)entry, value);
-do_flush_tlbs = 0;
  entry &= 0x3F;
  tlb = >tlb.tlbe[entry];
+
+/* Invalidate previous TLB (if it's valid) */
+if (tlb->prot & PAGE_VALID) {
+tlb_flush(env_cpu(env));
+}
+
  switch (word) {
  default:
  /* Just here to please gcc */
  case 0:
-EPN = value & 0xFC00;
-if ((tlb->prot & PAGE_VALID) && EPN != tlb->EPN) {
-do_flush_tlbs = 1;
-}
-tlb->EPN = EPN;
-size = booke_tlb_to_page_size((value >> 4) & 0xF);
-if ((tlb->prot & PAGE_VALID) && tlb->size < size) {
-do_flush_tlbs = 1;
-}
-tlb->size = size;
+tlb->EPN = value & 0xFC00;
+tlb->size = booke_tlb_to_page_size((value >> 4) & 0xF);
  tlb->attr &= ~0x1;
  tlb->attr |= (value >> 8) & 1;
  if (value & 0x200) {
  tlb->prot |= PAGE_VALID;
  } else {
-if (tlb->prot & PAGE_VALID) {
-tlb->prot &= ~PAGE_VALID;
-do_flush_tlbs = 1;
-}
+tlb->prot &= ~PAGE_VALID;
  }
  tlb->PID = env->spr[SPR_440_MMUCR] & 0x00FF;
-if (do_flush_tlbs) {
-tlb_flush(env_cpu(env));
-}
  break;
  case 1:
-RPN = value & 0xFC0F;
-if ((tlb->prot & PAGE_VALID) && tlb->RPN != RPN) {
-tlb_flush(env_cpu(env));
-}
-tlb->RPN = RPN;
+tlb->RPN = value & 0xFC0F;
  break;
  case 2:
  tlb->attr = (tlb->attr & 0x1) | (value & 0xFF00);





Re: [PATCH v2 6/8] tests/avocado: Add pseries KVM boot_linux test

2024-01-25 Thread Cédric Le Goater

On 1/17/24 15:12, Nicholas Piggin wrote:

ppc has no avocado tests for the KVM backend. Add a KVM boot_linux.py
test for pseries.

Signed-off-by: Nicholas Piggin 



Reviewed-by: Cédric Le Goater 

Thanks,

C.



---
  tests/avocado/boot_linux.py | 8 
  1 file changed, 8 insertions(+)

diff --git a/tests/avocado/boot_linux.py b/tests/avocado/boot_linux.py
index 7c9cf6ae15..4c9b15ba06 100644
--- a/tests/avocado/boot_linux.py
+++ b/tests/avocado/boot_linux.py
@@ -102,6 +102,14 @@ def test_pseries_tcg(self):
  self.vm.add_args("-accel", "tcg")
  self.launch_and_wait(set_up_ssh_connection=False)
  
+def test_pseries_kvm(self):

+"""
+:avocado: tags=machine:pseries
+:avocado: tags=accel:kvm
+"""
+self.require_accelerator("kvm")
+self.vm.add_args("-accel", "kvm")
+self.launch_and_wait(set_up_ssh_connection=False)
  
  class BootLinuxS390X(LinuxTest):

  """





Re: [PATCH v2 5/8] tests/avocado: Add ppc pseries and powernv hash MMU tests

2024-01-25 Thread Cédric Le Goater

On 1/17/24 15:12, Nicholas Piggin wrote:

POWER CPUs support hash and radix MMU modes. Linux supports running in
either mode, but defaults to radix. To keep up testing of QEMU's hash
MMU implementation, add some Linux hash boot tests.

Signed-off-by: Nicholas Piggin 



Reviewed-by: Cédric Le Goater 

Thanks,

C.



---
  tests/avocado/ppc_powernv.py | 23 +++
  tests/avocado/ppc_pseries.py | 20 +---
  2 files changed, 36 insertions(+), 7 deletions(-)

diff --git a/tests/avocado/ppc_powernv.py b/tests/avocado/ppc_powernv.py
index d0e5c07bde..4342941d5d 100644
--- a/tests/avocado/ppc_powernv.py
+++ b/tests/avocado/ppc_powernv.py
@@ -12,11 +12,11 @@
  class powernvMachine(QemuSystemTest):
  
  timeout = 90

-KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 '
+KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 console=hvc0 '
  panic_message = 'Kernel panic - not syncing'
  good_message = 'VFS: Cannot open root device'
  
-def do_test_linux_boot(self):

+def do_test_linux_boot(self, command_line = KERNEL_COMMON_COMMAND_LINE):
  self.require_accelerator("tcg")
  kernel_url = ('https://archives.fedoraproject.org/pub/archive'
'/fedora-secondary/releases/29/Everything/ppc64le/os'
@@ -25,9 +25,8 @@ def do_test_linux_boot(self):
  kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash)
  
  self.vm.set_console()

-kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'console=hvc0'
  self.vm.add_args('-kernel', kernel_path,
- '-append', kernel_command_line)
+ '-append', command_line)
  self.vm.launch()
  
  def test_linux_boot(self):

@@ -54,6 +53,22 @@ def test_linux_smp_boot(self):
  wait_for_console_pattern(self, console_pattern, self.panic_message)
  wait_for_console_pattern(self, self.good_message, self.panic_message)
  
+def test_linux_smp_hpt_boot(self):

+"""
+:avocado: tags=arch:ppc64
+:avocado: tags=machine:powernv
+:avocado: tags=accel:tcg
+"""
+
+self.vm.add_args('-smp', '4')
+self.do_test_linux_boot(self.KERNEL_COMMON_COMMAND_LINE +
+'disable_radix')
+console_pattern = 'smp: Brought up 1 node, 4 CPUs'
+wait_for_console_pattern(self, 'hash-mmu: Initializing hash mmu',
+ self.panic_message)
+wait_for_console_pattern(self, console_pattern, self.panic_message)
+wait_for_console_pattern(self, self.good_message, self.panic_message)
+
  def test_linux_smt_boot(self):
  """
  :avocado: tags=arch:ppc64
diff --git a/tests/avocado/ppc_pseries.py b/tests/avocado/ppc_pseries.py
index a8311e6555..74aaa4ac4a 100644
--- a/tests/avocado/ppc_pseries.py
+++ b/tests/avocado/ppc_pseries.py
@@ -12,11 +12,11 @@
  class pseriesMachine(QemuSystemTest):
  
  timeout = 90

-KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 '
+KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 console=hvc0 '
  panic_message = 'Kernel panic - not syncing'
  good_message = 'VFS: Cannot open root device'
  
-def do_test_ppc64_linux_boot(self):

+def do_test_ppc64_linux_boot(self, kernel_command_line = 
KERNEL_COMMON_COMMAND_LINE):
  kernel_url = ('https://archives.fedoraproject.org/pub/archive'
'/fedora-secondary/releases/29/Everything/ppc64le/os'
'/ppc/ppc64/vmlinuz')
@@ -24,7 +24,6 @@ def do_test_ppc64_linux_boot(self):
  kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash)
  
  self.vm.set_console()

-kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'console=hvc0'
  self.vm.add_args('-kernel', kernel_path,
   '-append', kernel_command_line)
  self.vm.launch()
@@ -62,6 +61,21 @@ def test_ppc64_linux_smp_boot(self):
  wait_for_console_pattern(self, console_pattern, self.panic_message)
  wait_for_console_pattern(self, self.good_message, self.panic_message)
  
+def test_ppc64_linux_hpt_smp_boot(self):

+"""
+:avocado: tags=arch:ppc64
+:avocado: tags=machine:pseries
+"""
+
+self.vm.add_args('-smp', '4')
+self.do_test_ppc64_linux_boot(self.KERNEL_COMMON_COMMAND_LINE +
+  'disable_radix')
+console_pattern = 'smp: Brought up 1 node, 4 CPUs'
+wait_for_console_pattern(self, 'hash-mmu: Initializing hash mmu',
+ self.panic_message)
+wait_for_console_pattern(self, console_pattern, self.panic_message)
+wait_for_console_pattern(self, self.good_message, self.panic_message)
+
  def test_ppc64_linux_smt_boot(self):
  """
  :avocado: tags=arch:ppc64





Re: [PATCH] tests/avocado: improve flaky ppc/pnv boot_linux_console.py test

2024-01-25 Thread Cédric Le Goater

On 1/24/24 07:01, Nicholas Piggin wrote:

The expected MTD partition detection output does not always appear on
the console, despite the test reaching the boot loader and the string
appearing in dmesg. Possibly due to an init script that quietens the
console output. Using an earlier log message improves reliability.

Signed-off-by: Nicholas Piggin 
---
  tests/avocado/boot_linux_console.py | 4 +++-
  1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/tests/avocado/boot_linux_console.py 
b/tests/avocado/boot_linux_console.py
index 3f0180e1f8..922a9e7b79 100644
--- a/tests/avocado/boot_linux_console.py
+++ b/tests/avocado/boot_linux_console.py
@@ -1368,7 +1368,9 @@ def do_test_ppc64_powernv(self, proc):
  self.wait_for_console_pattern("CPU: " + proc + " generation 
processor")
  self.wait_for_console_pattern("zImage starting: loaded")
  self.wait_for_console_pattern("Run /init as init process")
-self.wait_for_console_pattern("Creating 1 MTD partitions")
+self.wait_for_console_pattern("rtc-opal opal-rtc: setting system 
clock")
+# MTD partition detection output is sometimes cut off from console
+# output, suspect S14silence-console init script.
  
  def test_ppc_powernv8(self):

  """




Reviewed-by: Cédric Le Goater 

Thanks,

C.





Re: [PATCH v2 2/8] tests/avocado: Mark x86-64 boot_linux.py TCG tests as long runtime

2024-01-25 Thread Cédric Le Goater

On 1/17/24 15:12, Nicholas Piggin wrote:

Re-testing gitlab CI shows the ppc64 and s390x boot_linux tests take
100-150 seconds each. The x86-64 TCG tests take a similar ~100s each,
and are the longest-running avocado tests in gitlab.
 From avocado-system-centos:

   boot_linux.py:BootLinuxX8664.test_pc_i440fx_tcg:  PASS (112.34 s)
   boot_linux.py:BootLinuxX8664.test_pc_q35_tcg:  PASS (97.05 s)
   boot_linux.py:BootLinuxPPC64.test_pseries_tcg:  PASS (148.86 s)
   boot_linux.py:BootLinuxS390X.test_s390_ccw_virtio_tcg:  PASS (149.83 s)

So mark the x86-64 tests as SPEED=slow as well.

Signed-off-by: Nicholas Piggin 

The other way we could go is enabling them all since ppc64 and s390s are
now much faster than when they were originally disabled; or to only
enable q35, giving at least one boot_linux.py test.

[https://gitlab.com/npiggin/qemu/-/jobs/5842257510 for results]



Reviewed-by: Cédric Le Goater 

Thanks,

C.



---
  tests/avocado/boot_linux.py | 16 +++-
  1 file changed, 7 insertions(+), 9 deletions(-)

diff --git a/tests/avocado/boot_linux.py b/tests/avocado/boot_linux.py
index de4c8805f7..7c9cf6ae15 100644
--- a/tests/avocado/boot_linux.py
+++ b/tests/avocado/boot_linux.py
@@ -14,6 +14,9 @@
  
  from avocado import skipUnless
  
+# We don't run TCG tests in CI, as booting the current Fedora OS in TCG tests

+# is very heavyweight (~100s per test). There are lighter weight distros which
+# we use in the machine_aarch64_virt.py, tux_baseline.py, etc.
  
  class BootLinuxX8664(LinuxTest):

  """
@@ -21,6 +24,7 @@ class BootLinuxX8664(LinuxTest):
  """
  timeout = 480
  
+@skipUnless(os.getenv('SPEED') == 'slow', 'runtime limited')

  def test_pc_i440fx_tcg(self):
  """
  :avocado: tags=machine:pc
@@ -39,6 +43,7 @@ def test_pc_i440fx_kvm(self):
  self.vm.add_args("-accel", "kvm")
  self.launch_and_wait(set_up_ssh_connection=False)
  
+@skipUnless(os.getenv('SPEED') == 'slow', 'runtime limited')

  def test_pc_q35_tcg(self):
  """
  :avocado: tags=machine:q35
@@ -58,9 +63,6 @@ def test_pc_q35_kvm(self):
  self.launch_and_wait(set_up_ssh_connection=False)
  
  
-# For Aarch64 we only boot KVM tests in CI as booting the current

-# Fedora OS in TCG tests is very heavyweight. There are lighter weight
-# distros which we use in the machine_aarch64_virt.py tests.
  class BootLinuxAarch64(LinuxTest):
  """
  :avocado: tags=arch:aarch64
@@ -84,14 +86,11 @@ def test_virt_kvm(self):
  self.launch_and_wait(set_up_ssh_connection=False)
  
  
-# See the tux_baseline.py tests for almost the same coverage in a lot

-# less time.
  class BootLinuxPPC64(LinuxTest):
  """
  :avocado: tags=arch:ppc64
  """
-
-timeout = 360
+timeout = 480
  
  @skipUnless(os.getenv('SPEED') == 'slow', 'runtime limited')

  def test_pseries_tcg(self):
@@ -108,8 +107,7 @@ class BootLinuxS390X(LinuxTest):
  """
  :avocado: tags=arch:s390x
  """
-
-timeout = 240
+timeout = 480
  
  @skipUnless(os.getenv('SPEED') == 'slow', 'runtime limited')

  def test_s390_ccw_virtio_tcg(self):





Re: [PATCH v3 0/5] hw/arm/aspeed: Check for CPU types in machine_run_board_init()

2024-01-25 Thread Cédric Le Goater

On 1/25/24 06:55, Philippe Mathieu-Daudé wrote:

Series fully reviewed.


There is not much in the aspeed queue apart from [1]. I will consider
sending a PR after a review (Reviewers please ?). Anyhow, if you need
this series soon, feel free to take it.

Thanks,

C.


[1] https://lore.kernel.org/qemu-devel/20240109173538.435781-1-...@kaod.org/



Since v2:
- Addressed Gavin & Richard review comments.
- Collected R-b tags

Since v1:
- Follow suggestions from Cédric from [*]

[*] 
https://lore.kernel.org/qemu-devel/e13c655b-7904-4e47-a673-4efd13c26...@kaod.org/

Based-on: <20240123222508.13826-1-phi...@linaro.org>

Philippe Mathieu-Daudé (5):
   hw/arm/aspeed: Remove dead code
   hw/arm/aspeed: Set default CPU count using aspeed_soc_num_cpus()
   hw/arm/aspeed: Init CPU defaults in a common helper
   hw/arm/aspeed: Introduce aspeed_soc_cpu_type() helper
   hw/arm/aspeed: Check for CPU types in machine_run_board_init()

  include/hw/arm/aspeed_soc.h |  4 ++-
  hw/arm/aspeed.c | 70 +++--
  hw/arm/aspeed_ast10x0.c |  8 +++--
  hw/arm/aspeed_ast2400.c | 15 ++--
  hw/arm/aspeed_ast2600.c |  9 +++--
  hw/arm/aspeed_soc_common.c  |  8 +
  6 files changed, 65 insertions(+), 49 deletions(-)






Re: [PATCH v2] target/i386/host-cpu: Use iommu phys_bits with VFIO assigned devices on Intel h/w

2024-01-24 Thread Cédric Le Goater

On 1/18/24 20:20, Vivek Kasireddy wrote:

Recent updates in OVMF and Seabios have resulted in MMIO regions
being placed at the upper end of the physical address space. As a
result, when a Host device is assigned to the Guest via VFIO, the
following mapping failures occur when VFIO tries to map the MMIO
regions of the device:
VFIO_MAP_DMA failed: Invalid argument
vfio_dma_map(0x557b2f2736d0, 0x3800, 0x100, 0x7f98ac40) = -22 
(Invalid argument)

The above failures are mainly seen on some Intel platforms where
the physical address width is larger than the Host's IOMMU
address width. In these cases, VFIO fails to map the MMIO regions
because the IOVAs would be larger than the IOMMU aperture regions.

Therefore, one way to solve this problem would be to ensure that
cpu->phys_bits = 
This can be done by parsing the IOMMU caps value from sysfs and
extracting the address width and using it to override the
phys_bits value as shown in this patch.

Previous attempt at solving this issue in OVMF:
https://edk2.groups.io/g/devel/topic/102359124

Cc: Gerd Hoffmann 
Cc: Philippe Mathieu-Daudé 
Cc: Alex Williamson 
Cc: Cédric Le Goater 
Cc: Laszlo Ersek 
Cc: Dongwon Kim 
Acked-by: Gerd Hoffmann 
Tested-by: Yanghang Liu 
Signed-off-by: Vivek Kasireddy 

---
v2:
- Replace the term passthrough with assigned (Laszlo)
- Update the commit message to note that both OVMF and Seabios
   guests are affected (Cédric)
- Update the subject to indicate what is done in the patch
---
  target/i386/host-cpu.c | 61 +-
  1 file changed, 60 insertions(+), 1 deletion(-)

diff --git a/target/i386/host-cpu.c b/target/i386/host-cpu.c
index 92ecb7254b..5c9fcd7dc2 100644
--- a/target/i386/host-cpu.c
+++ b/target/i386/host-cpu.c
@@ -12,6 +12,8 @@
  #include "host-cpu.h"
  #include "qapi/error.h"
  #include "qemu/error-report.h"
+#include "qemu/config-file.h"
+#include "qemu/option.h"
  #include "sysemu/sysemu.h"
  
  /* Note: Only safe for use on x86(-64) hosts */

@@ -51,11 +53,58 @@ static void host_cpu_enable_cpu_pm(X86CPU *cpu)
  env->features[FEAT_1_ECX] |= CPUID_EXT_MONITOR;
  }
  
+static int intel_iommu_check(void *opaque, QemuOpts *opts, Error **errp)

+{
+g_autofree char *dev_path = NULL, *iommu_path = NULL, *caps = NULL;
+const char *driver = qemu_opt_get(opts, "driver");
+const char *device = qemu_opt_get(opts, "host");
+uint32_t *iommu_phys_bits = opaque;
+struct stat st;
+uint64_t iommu_caps;
+
+/*
+ * Check if the user requested VFIO device assignment. We don't have
+ * to limit phys_bits if there are no valid assigned devices.
+ */
+if (g_strcmp0(driver, "vfio-pci") || !device) {
+return 0;
+}
+
+dev_path = g_strdup_printf("/sys/bus/pci/devices/%s", device);
+if (stat(dev_path, ) < 0) {
+return 0;
+}
+
+iommu_path = g_strdup_printf("%s/iommu/intel-iommu/cap", dev_path);
+if (stat(iommu_path, ) < 0) {
+return 0;
+}
+
+if (g_file_get_contents(iommu_path, , NULL, NULL)) {
+if (sscanf(caps, "%lx", _caps) != 1) {


nit. This should use a PRIx64 define.


+return 0;
+}
+*iommu_phys_bits = ((iommu_caps >> 16) & 0x3f) + 1;


Please use 0x3fULL and this could be a macro in include/hw/i386/intel_iommu.h

Thanks,

C.




+}
+
+return 0;
+}
+
+static uint32_t host_iommu_phys_bits(void)
+{
+uint32_t iommu_phys_bits = 0;
+
+qemu_opts_foreach(qemu_find_opts("device"),
+  intel_iommu_check, _phys_bits, NULL);
+return iommu_phys_bits;
+}
+
  static uint32_t host_cpu_adjust_phys_bits(X86CPU *cpu)
  {
  uint32_t host_phys_bits = host_cpu_phys_bits();
+uint32_t iommu_phys_bits = host_iommu_phys_bits();
  uint32_t phys_bits = cpu->phys_bits;
-static bool warned;
+static bool warned, warned2;
  
  /*

   * Print a warning if the user set it to a value that's not the
@@ -78,6 +127,16 @@ static uint32_t host_cpu_adjust_phys_bits(X86CPU *cpu)
  }
  }
  
+if (iommu_phys_bits && phys_bits > iommu_phys_bits) {

+phys_bits = iommu_phys_bits;
+if (!warned2) {
+warn_report("Using physical bits (%u)"
+" to prevent VFIO mapping failures",
+iommu_phys_bits);
+warned2 = true;
+}
+}
+
  return phys_bits;
  }
  





Re: [PATCH v2 5/5] hw/arm/aspeed: Check for CPU types in machine_run_board_init()

2024-01-23 Thread Cédric Le Goater

On 1/23/24 23:48, Philippe Mathieu-Daudé wrote:

Aspeed SoCs use a single CPU type (set as AspeedSoCClass::cpu_type).
Convert it to a NULL-terminated array (of a single non-NULL element).

Set MachineClass::valid_cpu_types[] to use the common machine code
to provide hints when the requested CPU is invalid (see commit
e702cbc19e ("machine: Improve is_cpu_type_supported()").

Signed-off-by: Philippe Mathieu-Daudé 



Reviewed-by: Cédric Le Goater 

Thanks,

C.



---
  include/hw/arm/aspeed_soc.h |  3 ++-
  hw/arm/aspeed.c |  1 +
  hw/arm/aspeed_ast10x0.c |  6 +-
  hw/arm/aspeed_ast2400.c | 12 ++--
  hw/arm/aspeed_ast2600.c |  6 +-
  hw/arm/aspeed_soc_common.c  |  5 -
  6 files changed, 27 insertions(+), 6 deletions(-)

diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h
index a060a59918..0db5a41e71 100644
--- a/include/hw/arm/aspeed_soc.h
+++ b/include/hw/arm/aspeed_soc.h
@@ -128,7 +128,8 @@ struct AspeedSoCClass {
  DeviceClass parent_class;
  
  const char *name;

-const char *cpu_type;
+/** valid_cpu_types: NULL terminated array of a single CPU type. */
+const char * const *valid_cpu_types;
  uint32_t silicon_rev;
  uint64_t sram_size;
  uint64_t secsram_size;
diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index 636a6269aa..1be3b6bcae 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -1149,6 +1149,7 @@ static void 
aspeed_machine_class_init_cpus_defaults(MachineClass *mc)
  mc->default_cpus = mc->min_cpus
   = mc->max_cpus
   = sc->num_cpus;
+mc->valid_cpu_types = sc->valid_cpu_types;
  }
  
  static void aspeed_machine_class_init(ObjectClass *oc, void *data)

diff --git a/hw/arm/aspeed_ast10x0.c b/hw/arm/aspeed_ast10x0.c
index dca601a3f9..c3b5116a6a 100644
--- a/hw/arm/aspeed_ast10x0.c
+++ b/hw/arm/aspeed_ast10x0.c
@@ -417,13 +417,17 @@ static void aspeed_soc_ast1030_realize(DeviceState 
*dev_soc, Error **errp)
  
  static void aspeed_soc_ast1030_class_init(ObjectClass *klass, void *data)

  {
+static const char * const valid_cpu_types[] = {
+ARM_CPU_TYPE_NAME("cortex-m4"), /* TODO cortex-m4f */
+NULL
+};
  DeviceClass *dc = DEVICE_CLASS(klass);
  AspeedSoCClass *sc = ASPEED_SOC_CLASS(dc);
  
  dc->realize = aspeed_soc_ast1030_realize;
  
  sc->name = "ast1030-a1";

-sc->cpu_type = ARM_CPU_TYPE_NAME("cortex-m4"); /* TODO cortex-m4f */
+sc->valid_cpu_types = valid_cpu_types;
  sc->silicon_rev = AST1030_A1_SILICON_REV;
  sc->sram_size = 0xc;
  sc->secsram_size = 0x4; /* 256 * KiB */
diff --git a/hw/arm/aspeed_ast2400.c b/hw/arm/aspeed_ast2400.c
index 3baf95916d..8829561bb6 100644
--- a/hw/arm/aspeed_ast2400.c
+++ b/hw/arm/aspeed_ast2400.c
@@ -503,6 +503,10 @@ static void aspeed_ast2400_soc_realize(DeviceState *dev, 
Error **errp)
  
  static void aspeed_soc_ast2400_class_init(ObjectClass *oc, void *data)

  {
+static const char * const valid_cpu_types[] = {
+ARM_CPU_TYPE_NAME("arm926"),
+NULL
+};
  AspeedSoCClass *sc = ASPEED_SOC_CLASS(oc);
  DeviceClass *dc = DEVICE_CLASS(oc);
  
@@ -511,7 +515,7 @@ static void aspeed_soc_ast2400_class_init(ObjectClass *oc, void *data)

  dc->user_creatable = false;
  
  sc->name = "ast2400-a1";

-sc->cpu_type = ARM_CPU_TYPE_NAME("arm926");
+sc->valid_cpu_types = valid_cpu_types;
  sc->silicon_rev  = AST2400_A1_SILICON_REV;
  sc->sram_size= 0x8000;
  sc->spis_num = 1;
@@ -527,6 +531,10 @@ static void aspeed_soc_ast2400_class_init(ObjectClass *oc, 
void *data)
  
  static void aspeed_soc_ast2500_class_init(ObjectClass *oc, void *data)

  {
+static const char * const valid_cpu_types[] = {
+ARM_CPU_TYPE_NAME("arm1176"),
+NULL
+};
  AspeedSoCClass *sc = ASPEED_SOC_CLASS(oc);
  DeviceClass *dc = DEVICE_CLASS(oc);
  
@@ -535,7 +543,7 @@ static void aspeed_soc_ast2500_class_init(ObjectClass *oc, void *data)

  dc->user_creatable = false;
  
  sc->name = "ast2500-a1";

-sc->cpu_type = ARM_CPU_TYPE_NAME("arm1176");
+sc->valid_cpu_types = valid_cpu_types;
  sc->silicon_rev  = AST2500_A1_SILICON_REV;
  sc->sram_size= 0x9000;
  sc->spis_num = 2;
diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c
index b264433cf0..46baba0e41 100644
--- a/hw/arm/aspeed_ast2600.c
+++ b/hw/arm/aspeed_ast2600.c
@@ -629,13 +629,17 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, 
Error **errp)
  
  static void aspeed_soc_ast2600_class_init(ObjectClass *oc, void *data)

  {
+static const char * const valid_cpu_types[] = {
+ARM_CPU_TYPE_NAME("cortex-a7"),
+NULL
+};
  DeviceClas

Re: [PATCH v2 4/5] hw/arm/aspeed: Introduce aspeed_soc_cpu_type() helper

2024-01-23 Thread Cédric Le Goater

On 1/23/24 23:48, Philippe Mathieu-Daudé wrote:

In order to alter AspeedSoCClass::cpu_type in the next
commit, introduce the aspeed_soc_cpu_type() helper to
retrieve the per-SoC CPU type from AspeedSoCClass.

Signed-off-by: Philippe Mathieu-Daudé 


Reviewed-by: Cédric Le Goater 

Thanks,

C.


---
  include/hw/arm/aspeed_soc.h | 1 +
  hw/arm/aspeed_ast10x0.c | 2 +-
  hw/arm/aspeed_ast2400.c | 3 ++-
  hw/arm/aspeed_ast2600.c | 3 ++-
  hw/arm/aspeed_soc_common.c  | 5 +
  5 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h
index cb832bc1ee..a060a59918 100644
--- a/include/hw/arm/aspeed_soc.h
+++ b/include/hw/arm/aspeed_soc.h
@@ -143,6 +143,7 @@ struct AspeedSoCClass {
  qemu_irq (*get_irq)(AspeedSoCState *s, int dev);
  };
  
+const char *aspeed_soc_cpu_type(AspeedSoCClass *sc);
  
  enum {

  ASPEED_DEV_SPI_BOOT,
diff --git a/hw/arm/aspeed_ast10x0.c b/hw/arm/aspeed_ast10x0.c
index 8becb146a8..dca601a3f9 100644
--- a/hw/arm/aspeed_ast10x0.c
+++ b/hw/arm/aspeed_ast10x0.c
@@ -211,7 +211,7 @@ static void aspeed_soc_ast1030_realize(DeviceState 
*dev_soc, Error **errp)
  /* AST1030 CPU Core */
  armv7m = DEVICE(>armv7m);
  qdev_prop_set_uint32(armv7m, "num-irq", 256);
-qdev_prop_set_string(armv7m, "cpu-type", sc->cpu_type);
+qdev_prop_set_string(armv7m, "cpu-type", aspeed_soc_cpu_type(sc));
  qdev_connect_clock_in(armv7m, "cpuclk", s->sysclk);
  object_property_set_link(OBJECT(>armv7m), "memory",
   OBJECT(s->memory), _abort);
diff --git a/hw/arm/aspeed_ast2400.c b/hw/arm/aspeed_ast2400.c
index ad76035528..3baf95916d 100644
--- a/hw/arm/aspeed_ast2400.c
+++ b/hw/arm/aspeed_ast2400.c
@@ -156,7 +156,8 @@ static void aspeed_ast2400_soc_init(Object *obj)
  }
  
  for (i = 0; i < sc->num_cpus; i++) {

-object_initialize_child(obj, "cpu[*]", >cpu[i], sc->cpu_type);
+object_initialize_child(obj, "cpu[*]", >cpu[i],
+aspeed_soc_cpu_type(sc));
  }
  
  snprintf(typename, sizeof(typename), "aspeed.scu-%s", socname);

diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c
index 386a88d4e0..b264433cf0 100644
--- a/hw/arm/aspeed_ast2600.c
+++ b/hw/arm/aspeed_ast2600.c
@@ -158,7 +158,8 @@ static void aspeed_soc_ast2600_init(Object *obj)
  }
  
  for (i = 0; i < sc->num_cpus; i++) {

-object_initialize_child(obj, "cpu[*]", >cpu[i], sc->cpu_type);
+object_initialize_child(obj, "cpu[*]", >cpu[i],
+aspeed_soc_cpu_type(sc));
  }
  
  snprintf(typename, sizeof(typename), "aspeed.scu-%s", socname);

diff --git a/hw/arm/aspeed_soc_common.c b/hw/arm/aspeed_soc_common.c
index 828f61093b..36ca189ce9 100644
--- a/hw/arm/aspeed_soc_common.c
+++ b/hw/arm/aspeed_soc_common.c
@@ -18,6 +18,11 @@
  #include "hw/char/serial.h"
  
  
+const char *aspeed_soc_cpu_type(AspeedSoCClass *sc)

+{
+return sc->cpu_type;
+}
+
  qemu_irq aspeed_soc_get_irq(AspeedSoCState *s, int dev)
  {
  return ASPEED_SOC_GET_CLASS(s)->get_irq(s, dev);





Re: [PATCH v2 3/5] hw/arm/aspeed: Init CPU defaults in a common helper

2024-01-23 Thread Cédric Le Goater
machine_sonorapass_class_init(ObjectClass *oc, void *data)

@@ -1318,8 +1314,7 @@ static void 
aspeed_machine_sonorapass_class_init(ObjectClass *oc, void *data)
  amc->num_cs= 2;
  amc->i2c_init  = sonorapass_bmc_i2c_init;
  mc->default_ram_size   = 512 * MiB;
-mc->default_cpus = mc->min_cpus = mc->max_cpus =
-aspeed_soc_num_cpus(amc->soc_name);
+aspeed_machine_class_init_cpus_defaults(mc);
  };
  
  static void aspeed_machine_witherspoon_class_init(ObjectClass *oc, void *data)

@@ -1335,8 +1330,7 @@ static void 
aspeed_machine_witherspoon_class_init(ObjectClass *oc, void *data)
  amc->num_cs= 2;
  amc->i2c_init  = witherspoon_bmc_i2c_init;
  mc->default_ram_size = 512 * MiB;
-mc->default_cpus = mc->min_cpus = mc->max_cpus =
-aspeed_soc_num_cpus(amc->soc_name);
+aspeed_machine_class_init_cpus_defaults(mc);
  };
  
  static void aspeed_machine_ast2600_evb_class_init(ObjectClass *oc, void *data)

@@ -1355,8 +1349,7 @@ static void 
aspeed_machine_ast2600_evb_class_init(ObjectClass *oc, void *data)
   ASPEED_MAC3_ON;
  amc->i2c_init  = ast2600_evb_i2c_init;
  mc->default_ram_size = 1 * GiB;
-mc->default_cpus = mc->min_cpus = mc->max_cpus =
-aspeed_soc_num_cpus(amc->soc_name);
+aspeed_machine_class_init_cpus_defaults(mc);
  };
  
  static void aspeed_machine_tacoma_class_init(ObjectClass *oc, void *data)

@@ -1374,8 +1367,7 @@ static void aspeed_machine_tacoma_class_init(ObjectClass 
*oc, void *data)
  amc->macs_mask  = ASPEED_MAC2_ON;
  amc->i2c_init  = witherspoon_bmc_i2c_init; /* Same board layout */
  mc->default_ram_size = 1 * GiB;
-mc->default_cpus = mc->min_cpus = mc->max_cpus =
-aspeed_soc_num_cpus(amc->soc_name);
+aspeed_machine_class_init_cpus_defaults(mc);
  };
  
  static void aspeed_machine_g220a_class_init(ObjectClass *oc, void *data)

@@ -1392,8 +1384,7 @@ static void aspeed_machine_g220a_class_init(ObjectClass 
*oc, void *data)
  amc->macs_mask  = ASPEED_MAC0_ON | ASPEED_MAC1_ON;
  amc->i2c_init  = g220a_bmc_i2c_init;
  mc->default_ram_size = 1024 * MiB;
-mc->default_cpus = mc->min_cpus = mc->max_cpus =
-aspeed_soc_num_cpus(amc->soc_name);
+aspeed_machine_class_init_cpus_defaults(mc);
  };
  
  static void aspeed_machine_fp5280g2_class_init(ObjectClass *oc, void *data)

@@ -1410,8 +1401,7 @@ static void 
aspeed_machine_fp5280g2_class_init(ObjectClass *oc, void *data)
  amc->macs_mask  = ASPEED_MAC0_ON | ASPEED_MAC1_ON;
  amc->i2c_init  = fp5280g2_bmc_i2c_init;
  mc->default_ram_size = 512 * MiB;
-mc->default_cpus = mc->min_cpus = mc->max_cpus =
-aspeed_soc_num_cpus(amc->soc_name);
+aspeed_machine_class_init_cpus_defaults(mc);
  };
  
  static void aspeed_machine_rainier_class_init(ObjectClass *oc, void *data)

@@ -1429,8 +1419,7 @@ static void aspeed_machine_rainier_class_init(ObjectClass 
*oc, void *data)
  amc->macs_mask  = ASPEED_MAC2_ON | ASPEED_MAC3_ON;
  amc->i2c_init  = rainier_bmc_i2c_init;
  mc->default_ram_size = 1 * GiB;
-mc->default_cpus = mc->min_cpus = mc->max_cpus =
-aspeed_soc_num_cpus(amc->soc_name);
+aspeed_machine_class_init_cpus_defaults(mc);
  };
  
  #define FUJI_BMC_RAM_SIZE ASPEED_RAM_SIZE(2 * GiB)

@@ -1451,8 +1440,7 @@ static void aspeed_machine_fuji_class_init(ObjectClass 
*oc, void *data)
  amc->i2c_init = fuji_bmc_i2c_init;
  amc->uart_default = ASPEED_DEV_UART1;
  mc->default_ram_size = FUJI_BMC_RAM_SIZE;
-mc->default_cpus = mc->min_cpus = mc->max_cpus =
-aspeed_soc_num_cpus(amc->soc_name);
+aspeed_machine_class_init_cpus_defaults(mc);
  };
  
  #define BLETCHLEY_BMC_RAM_SIZE ASPEED_RAM_SIZE(2 * GiB)

@@ -1472,8 +1460,7 @@ static void 
aspeed_machine_bletchley_class_init(ObjectClass *oc, void *data)
  amc->macs_mask = ASPEED_MAC2_ON;
  amc->i2c_init  = bletchley_bmc_i2c_init;
  mc->default_ram_size = BLETCHLEY_BMC_RAM_SIZE;
-mc->default_cpus = mc->min_cpus = mc->max_cpus =
-aspeed_soc_num_cpus(amc->soc_name);
+aspeed_machine_class_init_cpus_defaults(mc);
  }
  
  static void fby35_reset(MachineState *state, ShutdownCause reason)

@@ -1515,6 +1502,7 @@ static void aspeed_machine_fby35_class_init(ObjectClass 
*oc, void *data)
  amc->i2c_init  = fby35_i2c_init;
  /* FIXME: Replace this macro with something more general */
  mc->default_ram_size = FUJI_BMC_RAM_SIZE;
+aspeed_machine_class_init_cpus_defaults(mc); //


please remove the extra //, with that

Reviewed-by: Cédric Le Goater 

Thanks,

C.



  }
  
  #define AST1030_INTERNAL_FLASH_SIZE (1024 * 1024)

@@ -1592,8 +1580,7 @@ static void 
aspeed_minibmc_machine_ast1030_evb_class_init(ObjectClass *oc,
  amc->spi_model = "sst25vf03

Re: [PATCH v2 2/5] hw/arm/aspeed: Set default CPU count using aspeed_soc_num_cpus()

2024-01-23 Thread Cédric Le Goater

On 1/23/24 23:48, Philippe Mathieu-Daudé wrote:

Since commit b7f1a0cb76 ("arm/aspeed: Compute the number
of CPUs from the SoC definition") Aspeed machines use the
aspeed_soc_num_cpus() helper to set the number of CPUs.

Use it for the ast1030-evb (commit 356b230ed1 "aspeed/soc:
Add AST1030 support") and supermicrox11-bmc (commit 40a38df55e
"hw/arm/aspeed: Add board model for Supermicro X11 BMC") machines.

Signed-off-by: Philippe Mathieu-Daudé 



Reviewed-by: Cédric Le Goater 

Thanks,

C.



---
  hw/arm/aspeed.c | 5 -
  1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index 4bc292ff84..5b01a4dd28 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -1212,6 +1212,8 @@ static void 
aspeed_machine_supermicrox11_bmc_class_init(ObjectClass *oc,
  amc->macs_mask = ASPEED_MAC0_ON | ASPEED_MAC1_ON;
  amc->i2c_init  = palmetto_bmc_i2c_init;
  mc->default_ram_size = 256 * MiB;
+mc->default_cpus = mc->min_cpus = mc->max_cpus =
+aspeed_soc_num_cpus(amc->soc_name);
  }
  
  static void aspeed_machine_supermicro_x11spi_bmc_class_init(ObjectClass *oc,

@@ -1586,11 +1588,12 @@ static void 
aspeed_minibmc_machine_ast1030_evb_class_init(ObjectClass *oc,
  mc->init = aspeed_minibmc_machine_init;
  amc->i2c_init = ast1030_evb_i2c_init;
  mc->default_ram_size = 0;
-mc->default_cpus = mc->min_cpus = mc->max_cpus = 1;
  amc->fmc_model = "sst25vf032b";
  amc->spi_model = "sst25vf032b";
  amc->num_cs = 2;
  amc->macs_mask = 0;
+mc->default_cpus = mc->min_cpus = mc->max_cpus =
+aspeed_soc_num_cpus(amc->soc_name);
  }
  
  static void aspeed_machine_qcom_dc_scm_v1_class_init(ObjectClass *oc,





Re: [PATCH v2 1/5] hw/arm/aspeed: Remove dead code

2024-01-23 Thread Cédric Le Goater

On 1/23/24 23:48, Philippe Mathieu-Daudé wrote:

Remove copy/paste typo from commit 6c323aba40 ("hw/arm/aspeed:
Adding new machine Tiogapass in QEMU").

Signed-off-by: Philippe Mathieu-Daudé 




Reviewed-by: Cédric Le Goater 

Thanks,

C.



---
  hw/arm/aspeed.c | 1 -
  1 file changed, 1 deletion(-)

diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index cc59176563..4bc292ff84 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -1301,7 +1301,6 @@ static void 
aspeed_machine_tiogapass_class_init(ObjectClass *oc, void *data)
  mc->default_ram_size   = 1 * GiB;
  mc->default_cpus = mc->min_cpus = mc->max_cpus =
  aspeed_soc_num_cpus(amc->soc_name);
-aspeed_soc_num_cpus(amc->soc_name);
  };
  
  static void aspeed_machine_sonorapass_class_init(ObjectClass *oc, void *data)





Re: [PATCH] target/ppc: Fix crash on machine check caused by ifetch

2024-01-23 Thread Cédric Le Goater

On 1/7/24 18:05, Nicholas Piggin wrote:

is_prefix_insn_excp() loads the first word of the instruction address
which caused an exception, to determine whether or not it was prefixed
so the prefix bit can be set in [H]SRR1.

In case it was the instruction fetch itself that caused the exception,
the [H]SRR1 prefix bit is not required to be set, because it is not the
instruction itself that causes the interrupt. If the load is attempted,
t could cause a recursive exception.

Instruction storage interrupts, HDSIs caused by ifetch are excluded from
the prefix check. Machine checks caused by ifetch are not, and these
can cause bugs. For example fetching from an unmapped physical address
can result in:

   ERROR:../system/cpus.c:504:qemu_mutex_lock_iothread_impl:
   assertion failed: (!qemu_mutex_iothread_locked())
   #0  __pthread_kill_implementation
   (threadid=, signo=signo@entry=6, no_tid=no_tid@entry=0)
   at ./nptl/pthread_kill.c:44
   #1  0x7705a15f in __pthread_kill_internal
   (signo=6, threadid=) at ./nptl/pthread_kill.c:78
   #2  0x7700c472 in __GI_raise (sig=sig@entry=6)
   at ../sysdeps/posix/raise.c:26
   #3  0x76ff64b2 in __GI_abort () at ./stdlib/abort.c:79
   #4  0x773def08 in  () at /lib/x86_64-linux-gnu/libglib-2.0.so.0
   #5  0x77445e4e in g_assertion_message_expr ()
   at /lib/x86_64-linux-gnu/libglib-2.0.so.0
   #6  0x55a833f1 in qemu_mutex_lock_iothread_impl
   (file=0x55efda6e "../accel/tcg/cputlb.c", line=2033)
   at ../system/cpus.c:504
   #7  qemu_mutex_lock_iothread_impl
   (file=file@entry=0x55efda6e "../accel/tcg/cputlb.c", 
line=line@entry=2033) at ../system/cpus.c:500
   #8  0x55cbf786 in do_ld_mmio_beN
   (cpu=cpu@entry=0x56b72010, full=0x7fff5408e010, 
ret_be=ret_be@entry=0, addr=2310065133864353792, size=size@entry=4, mmu_idx=7, 
type=MMU_INST_FETCH, ra=0) at ../accel/tcg/cputlb.c:2033
   #9  0x55cc2ec6 in do_ld_4
   (ra=0, memop=MO_BEUL, type=MMU_INST_FETCH, mmu_idx=, 
p=0x7fff67dfc660, cpu=0x56b72010) at ../accel/tcg/cputlb.c:2336
   #10 do_ld4_mmu
   (cpu=cpu@entry=0x56b72010, addr=, oi=, 
ra=ra@entry=0, access_type=access_type@entry=MMU_INST_FETCH)
   at ../accel/tcg/cputlb.c:2418
   #11 0x55ccbaf6 in cpu_ldl_code
   (env=env@entry=0x56b747d0, addr=)
   at ../accel/tcg/cputlb.c:2975
   #12 0x55b7a47c in ppc_ldl_code
   (addr=, env=0x56b747d0)
   at ../target/ppc/excp_helper.c:147
   #13 is_prefix_insn_excp (excp=1, cpu=0x56b72010)
   at ../target/ppc/excp_helper.c:1350
   #14 powerpc_excp_books (excp=1, cpu=0x56b72010)
   at ../target/ppc/excp_helper.c:1415
   #15 powerpc_excp (cpu=0x56b72010, excp=)
   at ../target/ppc/excp_helper.c:1733
   #16 0x55cb1c74 in cpu_handle_exception
   (ret=, cpu=)

Fix this by excluding machine checks caused by ifetch from the prefix
check.


Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2108


Fixes: 55a7fa34f89 ("target/ppc: Machine check on invalid real address access on 
POWER9/10")
Fixes: 5a5d3b23cb2 ("target/ppc: Add SRR1 prefix indication to interrupt 
handlers")
Signed-off-by: Nicholas Piggin 
---
  target/ppc/excp_helper.c | 32 +---
  1 file changed, 21 insertions(+), 11 deletions(-)

diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index a42743a3e0..34c307b572 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -1322,6 +1322,15 @@ static bool is_prefix_insn_excp(PowerPCCPU *cpu, int 
excp)
  }
  
  switch (excp) {

+case POWERPC_EXCP_MCHECK:
+if (!(env->error_code & PPC_BIT(42))) {
+/*
+ * Fetch attempt caused a machine check, so attempting to fetch
+ * again would cause a recursive machine check.
+ */
+return false;
+}
+break;
  case POWERPC_EXCP_HDSI:
  /* HDSI PRTABLE_FAULT has the originating access type in error_code */
  if ((env->spr[SPR_HDSISR] & DSISR_PRTABLE_FAULT) &&
@@ -1332,10 +1341,10 @@ static bool is_prefix_insn_excp(PowerPCCPU *cpu, int 
excp)
   * instruction at NIP would cause recursive faults with the same
   * translation).
   */
-break;
+return false;
  }
-/* fall through */
-case POWERPC_EXCP_MCHECK:
+break;
+
  case POWERPC_EXCP_DSI:
  case POWERPC_EXCP_DSEG:
  case POWERPC_EXCP_ALIGN:
@@ -1346,17 +1355,14 @@ static bool is_prefix_insn_excp(PowerPCCPU *cpu, int 
excp)
  case POWERPC_EXCP_VPU:
  case POWERPC_EXCP_VSXU:
  case POWERPC_EXCP_FU:
-case POWERPC_EXCP_HV_FU: {
-uint32_t insn = ppc_ldl_code(env, env->nip);
-if (is_prefix_insn(env, insn)) {
-return true;
-}
+case POWERPC_EXCP_HV_FU:
  break;
-}
  default:
-break;
+return 

Re: [PATCH rfcv1 4/6] vfio: initialize IOMMUFDDevice and pass to vIOMMU

2024-01-23 Thread Cédric Le Goater

On 1/23/24 10:46, Duan, Zhenzhong wrote:




-Original Message-
From: Cédric Le Goater 
Subject: Re: [PATCH rfcv1 4/6] vfio: initialize IOMMUFDDevice and pass to
vIOMMU

On 1/15/24 11:13, Zhenzhong Duan wrote:

Initialize IOMMUFDDevice in vfio and pass to vIOMMU, so that vIOMMU
could get hw IOMMU information.

In VFIO legacy backend mode, we still pass a NULL IOMMUFDDevice to

vIOMMU,

in case vIOMMU needs some processing for VFIO legacy backend mode.

Originally-by: Yi Liu 
Signed-off-by: Nicolin Chen 
Signed-off-by: Yi Sun 
Signed-off-by: Zhenzhong Duan 
---
   include/hw/vfio/vfio-common.h |  2 ++
   hw/vfio/iommufd.c |  2 ++
   hw/vfio/pci.c | 24 +++-
   3 files changed, 23 insertions(+), 5 deletions(-)

diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-

common.h

index 9b7ef7d02b..fde0d0ca60 100644
--- a/include/hw/vfio/vfio-common.h
+++ b/include/hw/vfio/vfio-common.h
@@ -31,6 +31,7 @@
   #endif
   #include "sysemu/sysemu.h"
   #include "hw/vfio/vfio-container-base.h"
+#include "sysemu/iommufd_device.h"

   #define VFIO_MSG_PREFIX "vfio %s: "

@@ -126,6 +127,7 @@ typedef struct VFIODevice {
   bool dirty_tracking;
   int devid;
   IOMMUFDBackend *iommufd;
+IOMMUFDDevice idev;
   } VFIODevice;

   struct VFIODeviceOps {
diff --git a/hw/vfio/iommufd.c b/hw/vfio/iommufd.c
index 9bfddc1360..cbd035f148 100644
--- a/hw/vfio/iommufd.c
+++ b/hw/vfio/iommufd.c
@@ -309,6 +309,7 @@ static int iommufd_cdev_attach(const char *name,

VFIODevice *vbasedev,

   VFIOContainerBase *bcontainer;
   VFIOIOMMUFDContainer *container;
   VFIOAddressSpace *space;
+IOMMUFDDevice *idev = >idev;
   struct vfio_device_info dev_info = { .argsz = sizeof(dev_info) };
   int ret, devfd;
   uint32_t ioas_id;
@@ -428,6 +429,7 @@ found_container:
   QLIST_INSERT_HEAD(>device_list, vbasedev,

container_next);

   QLIST_INSERT_HEAD(_device_list, vbasedev, global_next);

+iommufd_device_init(idev, sizeof(*idev), container->be, vbasedev-
devid);
   trace_iommufd_cdev_device_info(vbasedev->name, devfd, vbasedev-
num_irqs,
  vbasedev->num_regions, vbasedev->flags);
   return 0;
diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
index d7fe06715c..2c3a5d267b 100644
--- a/hw/vfio/pci.c
+++ b/hw/vfio/pci.c
@@ -3107,11 +3107,21 @@ static void vfio_realize(PCIDevice *pdev,

Error **errp)


   vfio_bars_register(vdev);

-ret = vfio_add_capabilities(vdev, errp);
+if (vbasedev->iommufd) {
+ret = pci_device_set_iommu_device(pdev, >idev, errp);
+} else {
+ret = pci_device_set_iommu_device(pdev, 0, errp);



AFAICT, pci_device_set_iommu_device() with a NULL IOMMUFDDevice will
do
nothing. Why call it ?


We will do something in nesting series, see 
https://github.com/yiliu1765/qemu/commit/7f0bb59575bb5cf38618ae950f68a8661676e881


ok, that's not much. idev is used as a capability bool and later on
to pass the /dev/iommu fd.  We don't need to support the legacy mode ?


Another choice is to call pci_device_set_iommu_device() no matter which backend
is used and check idev->iommufd in vtd_dev_set_iommu_device(). Is this better
for you?


yes. Should be fine. There is more to it though.

IIUC, what will determine most of the requirements, is the legacy
mode. We also need the host iommu info in that case. As said Eric,
ideally, we should introduce a common abstract "host-iommu-info" struct
and sub structs associated with the iommu backends (iommufd + legacy)
which would be allocated accordingly.

So, IOMMUFDDevice usage should be limited to the iommufd files. All PCI
files should use the common abstract type. We should define these data
structures first. They could be simple C struct for now. We will see if
QOM applies after.

Will take a look at Eric's patchset next.

Thanks,

C.




Re: [PATCH] hw/pci-host/raven.c: Mark raven_io_ops as implementing unaligned accesses

2024-01-23 Thread Cédric Le Goater

On 1/12/24 14:46, Peter Maydell wrote:

The raven_io_ops MemoryRegionOps is the only one in the source tree
which sets .valid.unaligned to indicate that it should support
unaligned accesses and which does not also set .impl.unaligned to
indicate that its read and write functions can do the unaligned
handling themselves.  This is a problem, because at the moment the
core memory system does not implement the support for handling
unaligned accesses by doing a series of aligned accesses and
combining them (system/memory.c:access_with_adjusted_size() has a
TODO comment noting this).

Fortunately raven_io_read() and raven_io_write() will correctly deal
with the case of being passed an unaligned address, so we can fix the
missing unaligned access support by setting .impl.unaligned in the
MemoryRegionOps struct.

Fixes: 9a1839164c9c8f06 ("raven: Implement non-contiguous I/O region")
Signed-off-by: Peter Maydell 
---
Spotted by code inspection: I was looking for devices whose behaviour
might be changed by a patch I'm reviewing that adds that missing
support for unaligned accesses in the core memory system. But even
if we do implement it there, it's more efficient for the raven MR
to correctly mark it as handling unaligned accesses itself.

Tested with 'make check' and 'make check-avocado' only.


It doesn't affect the prep machine boot with OpenBIOS and a
"Debian GNU/Linux 3.0 6015" image.

Tested-by: Cédric Le Goater 
Reviewed-by: Cédric Le Goater 

Thanks,

C.




---
  hw/pci-host/raven.c | 1 +
  1 file changed, 1 insertion(+)

diff --git a/hw/pci-host/raven.c b/hw/pci-host/raven.c
index c7a0a2878ab..a7dfddd69ea 100644
--- a/hw/pci-host/raven.c
+++ b/hw/pci-host/raven.c
@@ -200,6 +200,7 @@ static const MemoryRegionOps raven_io_ops = {
  .write = raven_io_write,
  .endianness = DEVICE_LITTLE_ENDIAN,
  .impl.max_access_size = 4,
+.impl.unaligned = true,
  .valid.unaligned = true,
  };
  





Re: [PATCH] target/ppc: Fix crash on machine check caused by ifetch

2024-01-23 Thread Cédric Le Goater

On 1/7/24 18:05, Nicholas Piggin wrote:

is_prefix_insn_excp() loads the first word of the instruction address
which caused an exception, to determine whether or not it was prefixed
so the prefix bit can be set in [H]SRR1.

In case it was the instruction fetch itself that caused the exception,
the [H]SRR1 prefix bit is not required to be set, because it is not the
instruction itself that causes the interrupt. If the load is attempted,
t could cause a recursive exception.

Instruction storage interrupts, HDSIs caused by ifetch are excluded from
the prefix check. Machine checks caused by ifetch are not, and these
can cause bugs. For example fetching from an unmapped physical address
can result in:

   ERROR:../system/cpus.c:504:qemu_mutex_lock_iothread_impl:
   assertion failed: (!qemu_mutex_iothread_locked())
   #0  __pthread_kill_implementation
   (threadid=, signo=signo@entry=6, no_tid=no_tid@entry=0)
   at ./nptl/pthread_kill.c:44
   #1  0x7705a15f in __pthread_kill_internal
   (signo=6, threadid=) at ./nptl/pthread_kill.c:78
   #2  0x7700c472 in __GI_raise (sig=sig@entry=6)
   at ../sysdeps/posix/raise.c:26
   #3  0x76ff64b2 in __GI_abort () at ./stdlib/abort.c:79
   #4  0x773def08 in  () at /lib/x86_64-linux-gnu/libglib-2.0.so.0
   #5  0x77445e4e in g_assertion_message_expr ()
   at /lib/x86_64-linux-gnu/libglib-2.0.so.0
   #6  0x55a833f1 in qemu_mutex_lock_iothread_impl
   (file=0x55efda6e "../accel/tcg/cputlb.c", line=2033)
   at ../system/cpus.c:504
   #7  qemu_mutex_lock_iothread_impl
   (file=file@entry=0x55efda6e "../accel/tcg/cputlb.c", 
line=line@entry=2033) at ../system/cpus.c:500
   #8  0x55cbf786 in do_ld_mmio_beN
   (cpu=cpu@entry=0x56b72010, full=0x7fff5408e010, 
ret_be=ret_be@entry=0, addr=2310065133864353792, size=size@entry=4, mmu_idx=7, 
type=MMU_INST_FETCH, ra=0) at ../accel/tcg/cputlb.c:2033
   #9  0x55cc2ec6 in do_ld_4
   (ra=0, memop=MO_BEUL, type=MMU_INST_FETCH, mmu_idx=, 
p=0x7fff67dfc660, cpu=0x56b72010) at ../accel/tcg/cputlb.c:2336
   #10 do_ld4_mmu
   (cpu=cpu@entry=0x56b72010, addr=, oi=, 
ra=ra@entry=0, access_type=access_type@entry=MMU_INST_FETCH)
   at ../accel/tcg/cputlb.c:2418
   #11 0x55ccbaf6 in cpu_ldl_code
   (env=env@entry=0x56b747d0, addr=)
   at ../accel/tcg/cputlb.c:2975
   #12 0x55b7a47c in ppc_ldl_code
   (addr=, env=0x56b747d0)
   at ../target/ppc/excp_helper.c:147
   #13 is_prefix_insn_excp (excp=1, cpu=0x56b72010)
   at ../target/ppc/excp_helper.c:1350
   #14 powerpc_excp_books (excp=1, cpu=0x56b72010)
   at ../target/ppc/excp_helper.c:1415
   #15 powerpc_excp (cpu=0x56b72010, excp=)
   at ../target/ppc/excp_helper.c:1733
   #16 0x55cb1c74 in cpu_handle_exception
   (ret=, cpu=)

Fix this by excluding machine checks caused by ifetch from the prefix
check.

Fixes: 55a7fa34f89 ("target/ppc: Machine check on invalid real address access on 
POWER9/10")
Fixes: 5a5d3b23cb2 ("target/ppc: Add SRR1 prefix indication to interrupt 
handlers")
Signed-off-by: Nicholas Piggin 



Ack-by: Cédric Le Goater 

Thanks,

C.



---
  target/ppc/excp_helper.c | 32 +---
  1 file changed, 21 insertions(+), 11 deletions(-)

diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index a42743a3e0..34c307b572 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -1322,6 +1322,15 @@ static bool is_prefix_insn_excp(PowerPCCPU *cpu, int 
excp)
  }
  
  switch (excp) {

+case POWERPC_EXCP_MCHECK:
+if (!(env->error_code & PPC_BIT(42))) {
+/*
+ * Fetch attempt caused a machine check, so attempting to fetch
+ * again would cause a recursive machine check.
+ */
+return false;
+}
+break;
  case POWERPC_EXCP_HDSI:
  /* HDSI PRTABLE_FAULT has the originating access type in error_code */
  if ((env->spr[SPR_HDSISR] & DSISR_PRTABLE_FAULT) &&
@@ -1332,10 +1341,10 @@ static bool is_prefix_insn_excp(PowerPCCPU *cpu, int 
excp)
   * instruction at NIP would cause recursive faults with the same
   * translation).
   */
-break;
+return false;
  }
-/* fall through */
-case POWERPC_EXCP_MCHECK:
+break;
+
  case POWERPC_EXCP_DSI:
  case POWERPC_EXCP_DSEG:
  case POWERPC_EXCP_ALIGN:
@@ -1346,17 +1355,14 @@ static bool is_prefix_insn_excp(PowerPCCPU *cpu, int 
excp)
  case POWERPC_EXCP_VPU:
  case POWERPC_EXCP_VSXU:
  case POWERPC_EXCP_FU:
-case POWERPC_EXCP_HV_FU: {
-uint32_t insn = ppc_ldl_code(env, env->nip);
-if (is_prefix_insn(env, insn)) {
-return true;
-}
+case POWERPC_EXCP_HV_FU:
  b

Re: [PATCH 1/3] virtio_iommu: Clear IOMMUPciBus pointer cache when system reset

2024-01-23 Thread Cédric Le Goater

On 1/22/24 07:40, Zhenzhong Duan wrote:

IOMMUPciBus pointer cache is indexed by bus number, bus number
may not always be a fixed value, i.e., guest reboot to different
kernel which set bus number with different algorithm.

This could lead to endpoint binding to wrong iommu MR in
virtio_iommu_get_endpoint(), then vfio device setup wrong
mapping from other device.

Signed-off-by: Zhenzhong Duan 
---
  hw/virtio/virtio-iommu.c | 2 ++
  1 file changed, 2 insertions(+)

diff --git a/hw/virtio/virtio-iommu.c b/hw/virtio/virtio-iommu.c
index 8a4bd933c6..bfce3237f3 100644
--- a/hw/virtio/virtio-iommu.c
+++ b/hw/virtio/virtio-iommu.c
@@ -1264,6 +1264,8 @@ static void virtio_iommu_system_reset(void *opaque)
  
  trace_virtio_iommu_system_reset();
  
+memset(s->iommu_pcibus_by_bus_num, 0, sizeof(s->iommu_pcibus_by_bus_num));

+
  /*
   * config.bypass is sticky across device reset, but should be restored on
   * system reset


you could remove the memset in virtio_iommu_device_realize() then ?


Thanks,

C.





Re: [PATCH 6/8] hw/arm/aspeed/2600: Check for CPU types in machine_run_board_init()

2024-01-23 Thread Cédric Le Goater

On 1/23/24 10:27, Cédric Le Goater wrote:

On 1/23/24 07:38, Philippe Mathieu-Daudé wrote:

Restrict MachineClass::valid_cpu_types[] to the single
valid CPU type.

Signed-off-by: Philippe Mathieu-Daudé 
---
  hw/arm/aspeed.c | 12 
  1 file changed, 12 insertions(+)

diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index df627096d2..393c97d55e 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -1157,6 +1157,11 @@ static const char * const ast2500_a1_valid_cpu_types[] = 
{
  NULL
  };
+static const char * const ast2600_a3_valid_cpu_types[] = {
+    ARM_CPU_TYPE_NAME("cortex-a9"),


This should be "cortex-a7"

Looking closer, the CPU information is under AspeedSoCClass. Why not build the
valid_cpu_types array with something like :

     struct AspeedMachineClass {
 ...
 const char *valid_cpu_types[2];
     };

     static void aspeed_machine_set_valid_cpu_types(MachineClass *mc)
     {
     AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(mc);
     AspeedSoCClass *sc = 
ASPEED_SOC_CLASS(object_class_by_name(amc->soc_name));
     amc->valid_cpu_types[0] = sc->cpu_type;
     amc->valid_cpu_types[1] = NULL;
     mc->valid_cpu_types = amc->valid_cpu_types;
     };


or better, change AspeedSoCClass::cpu_type to an array.

mc->valid_cpu_types =

ASPEED_SOC_CLASS(object_class_by_name(amc->soc_name))->cpu_types;

C.




Re: [PATCH 6/8] hw/arm/aspeed/2600: Check for CPU types in machine_run_board_init()

2024-01-23 Thread Cédric Le Goater

On 1/23/24 07:38, Philippe Mathieu-Daudé wrote:

Restrict MachineClass::valid_cpu_types[] to the single
valid CPU type.

Signed-off-by: Philippe Mathieu-Daudé 
---
  hw/arm/aspeed.c | 12 
  1 file changed, 12 insertions(+)

diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index df627096d2..393c97d55e 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -1157,6 +1157,11 @@ static const char * const ast2500_a1_valid_cpu_types[] = 
{
  NULL
  };
  
+static const char * const ast2600_a3_valid_cpu_types[] = {

+ARM_CPU_TYPE_NAME("cortex-a9"),


This should be "cortex-a7"

Looking closer, the CPU information is under AspeedSoCClass. Why not build the
valid_cpu_types array with something like :

struct AspeedMachineClass {
...
const char *valid_cpu_types[2];
};

static void aspeed_machine_set_valid_cpu_types(MachineClass *mc)
{
AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(mc);
AspeedSoCClass *sc = 
ASPEED_SOC_CLASS(object_class_by_name(amc->soc_name));

amc->valid_cpu_types[0] = sc->cpu_type;

amc->valid_cpu_types[1] = NULL;
mc->valid_cpu_types = amc->valid_cpu_types;
};


Thanks,

C.




+NULL
+};
+
  static void aspeed_machine_class_init(ObjectClass *oc, void *data)
  {
  MachineClass *mc = MACHINE_CLASS(oc);
@@ -1373,6 +1378,7 @@ static void 
aspeed_machine_ast2600_evb_class_init(ObjectClass *oc, void *data)
  amc->macs_mask = ASPEED_MAC0_ON | ASPEED_MAC1_ON | ASPEED_MAC2_ON |
   ASPEED_MAC3_ON;
  amc->i2c_init  = ast2600_evb_i2c_init;
+mc->valid_cpu_types = ast2600_a3_valid_cpu_types;
  mc->default_ram_size = 1 * GiB;
  mc->default_cpus = mc->min_cpus = mc->max_cpus =
  aspeed_soc_num_cpus(amc->soc_name);
@@ -1392,6 +1398,7 @@ static void aspeed_machine_tacoma_class_init(ObjectClass 
*oc, void *data)
  amc->num_cs= 2;
  amc->macs_mask  = ASPEED_MAC2_ON;
  amc->i2c_init  = witherspoon_bmc_i2c_init; /* Same board layout */
+mc->valid_cpu_types = ast2600_a3_valid_cpu_types;
  mc->default_ram_size = 1 * GiB;
  mc->default_cpus = mc->min_cpus = mc->max_cpus =
  aspeed_soc_num_cpus(amc->soc_name);
@@ -1449,6 +1456,7 @@ static void aspeed_machine_rainier_class_init(ObjectClass 
*oc, void *data)
  amc->num_cs= 2;
  amc->macs_mask  = ASPEED_MAC2_ON | ASPEED_MAC3_ON;
  amc->i2c_init  = rainier_bmc_i2c_init;
+mc->valid_cpu_types = ast2600_a3_valid_cpu_types;
  mc->default_ram_size = 1 * GiB;
  mc->default_cpus = mc->min_cpus = mc->max_cpus =
  aspeed_soc_num_cpus(amc->soc_name);
@@ -1471,6 +1479,7 @@ static void aspeed_machine_fuji_class_init(ObjectClass 
*oc, void *data)
  amc->macs_mask = ASPEED_MAC3_ON;
  amc->i2c_init = fuji_bmc_i2c_init;
  amc->uart_default = ASPEED_DEV_UART1;
+mc->valid_cpu_types = ast2600_a3_valid_cpu_types;
  mc->default_ram_size = FUJI_BMC_RAM_SIZE;
  mc->default_cpus = mc->min_cpus = mc->max_cpus =
  aspeed_soc_num_cpus(amc->soc_name);
@@ -1492,6 +1501,7 @@ static void 
aspeed_machine_bletchley_class_init(ObjectClass *oc, void *data)
  amc->num_cs= 2;
  amc->macs_mask = ASPEED_MAC2_ON;
  amc->i2c_init  = bletchley_bmc_i2c_init;
+mc->valid_cpu_types = ast2600_a3_valid_cpu_types;
  mc->default_ram_size = BLETCHLEY_BMC_RAM_SIZE;
  mc->default_cpus = mc->min_cpus = mc->max_cpus =
  aspeed_soc_num_cpus(amc->soc_name);
@@ -1631,6 +1641,7 @@ static void 
aspeed_machine_qcom_dc_scm_v1_class_init(ObjectClass *oc,
  amc->num_cs= 2;
  amc->macs_mask = ASPEED_MAC2_ON | ASPEED_MAC3_ON;
  amc->i2c_init  = qcom_dc_scm_bmc_i2c_init;
+mc->valid_cpu_types = ast2600_a3_valid_cpu_types;
  mc->default_ram_size = 1 * GiB;
  mc->default_cpus = mc->min_cpus = mc->max_cpus =
  aspeed_soc_num_cpus(amc->soc_name);
@@ -1651,6 +1662,7 @@ static void 
aspeed_machine_qcom_firework_class_init(ObjectClass *oc,
  amc->num_cs= 2;
  amc->macs_mask = ASPEED_MAC2_ON | ASPEED_MAC3_ON;
  amc->i2c_init  = qcom_dc_scm_firework_i2c_init;
+mc->valid_cpu_types = ast2600_a3_valid_cpu_types;
  mc->default_ram_size = 1 * GiB;
  mc->default_cpus = mc->min_cpus = mc->max_cpus =
  aspeed_soc_num_cpus(amc->soc_name);





Re: [PATCH 4/8] hw/arm/aspeed/2400: Check for CPU types in machine_run_board_init()

2024-01-23 Thread Cédric Le Goater

On 1/23/24 07:38, Philippe Mathieu-Daudé wrote:

Restrict MachineClass::valid_cpu_types[] to the single
valid CPU type.

Signed-off-by: Philippe Mathieu-Daudé 



Reviewed-by: Cédric Le Goater 

Thanks,

C.



---
  hw/arm/aspeed.c | 8 
  1 file changed, 8 insertions(+)

diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index cc59176563..e0e0877b1d 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -1147,6 +1147,11 @@ static int aspeed_soc_num_cpus(const char *soc_name)
 return sc->num_cpus;
  }
  
+static const char * const ast2400_a1_valid_cpu_types[] = {

+ARM_CPU_TYPE_NAME("arm926"),
+NULL
+};
+
  static void aspeed_machine_class_init(ObjectClass *oc, void *data)
  {
  MachineClass *mc = MACHINE_CLASS(oc);
@@ -1175,6 +1180,7 @@ static void 
aspeed_machine_palmetto_class_init(ObjectClass *oc, void *data)
  amc->spi_model = "mx25l25635f";
  amc->num_cs= 1;
  amc->i2c_init  = palmetto_bmc_i2c_init;
+mc->valid_cpu_types = ast2400_a1_valid_cpu_types;
  mc->default_ram_size   = 256 * MiB;
  mc->default_cpus = mc->min_cpus = mc->max_cpus =
  aspeed_soc_num_cpus(amc->soc_name);
@@ -1192,6 +1198,7 @@ static void 
aspeed_machine_quanta_q71l_class_init(ObjectClass *oc, void *data)
  amc->spi_model = "mx25l25635e";
  amc->num_cs= 1;
  amc->i2c_init  = quanta_q71l_bmc_i2c_init;
+mc->valid_cpu_types = ast2400_a1_valid_cpu_types;
  mc->default_ram_size   = 128 * MiB;
  mc->default_cpus = mc->min_cpus = mc->max_cpus =
  aspeed_soc_num_cpus(amc->soc_name);
@@ -1211,6 +1218,7 @@ static void 
aspeed_machine_supermicrox11_bmc_class_init(ObjectClass *oc,
  amc->num_cs= 1;
  amc->macs_mask = ASPEED_MAC0_ON | ASPEED_MAC1_ON;
  amc->i2c_init  = palmetto_bmc_i2c_init;
+mc->valid_cpu_types = ast2400_a1_valid_cpu_types;
  mc->default_ram_size = 256 * MiB;
  }
  





Re: [PATCH 5/8] hw/arm/aspeed/2500: Check for CPU types in machine_run_board_init()

2024-01-23 Thread Cédric Le Goater

On 1/23/24 07:38, Philippe Mathieu-Daudé wrote:

Restrict MachineClass::valid_cpu_types[] to the single
valid CPU type.

Signed-off-by: Philippe Mathieu-Daudé 



Reviewed-by: Cédric Le Goater 

Thanks,

C.



---
  hw/arm/aspeed.c | 14 ++
  1 file changed, 14 insertions(+)

diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index e0e0877b1d..df627096d2 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -1152,6 +1152,11 @@ static const char * const ast2400_a1_valid_cpu_types[] = 
{
  NULL
  };
  
+static const char * const ast2500_a1_valid_cpu_types[] = {

+ARM_CPU_TYPE_NAME("arm1176"),
+NULL
+};
+
  static void aspeed_machine_class_init(ObjectClass *oc, void *data)
  {
  MachineClass *mc = MACHINE_CLASS(oc);
@@ -1236,6 +1241,7 @@ static void 
aspeed_machine_supermicro_x11spi_bmc_class_init(ObjectClass *oc,
  amc->num_cs= 1;
  amc->macs_mask = ASPEED_MAC0_ON | ASPEED_MAC1_ON;
  amc->i2c_init  = palmetto_bmc_i2c_init;
+mc->valid_cpu_types = ast2500_a1_valid_cpu_types;
  mc->default_ram_size = 512 * MiB;
  mc->default_cpus = mc->min_cpus = mc->max_cpus =
  aspeed_soc_num_cpus(amc->soc_name);
@@ -1253,6 +1259,7 @@ static void 
aspeed_machine_ast2500_evb_class_init(ObjectClass *oc, void *data)
  amc->spi_model = "mx25l25635f";
  amc->num_cs= 1;
  amc->i2c_init  = ast2500_evb_i2c_init;
+mc->valid_cpu_types = ast2500_a1_valid_cpu_types;
  mc->default_ram_size   = 512 * MiB;
  mc->default_cpus = mc->min_cpus = mc->max_cpus =
  aspeed_soc_num_cpus(amc->soc_name);
@@ -1271,6 +1278,7 @@ static void 
aspeed_machine_yosemitev2_class_init(ObjectClass *oc, void *data)
  amc->spi_model = "mx25l25635e";
  amc->num_cs= 2;
  amc->i2c_init  = yosemitev2_bmc_i2c_init;
+mc->valid_cpu_types = ast2500_a1_valid_cpu_types;
  mc->default_ram_size   = 512 * MiB;
  mc->default_cpus = mc->min_cpus = mc->max_cpus =
  aspeed_soc_num_cpus(amc->soc_name);
@@ -1288,6 +1296,7 @@ static void aspeed_machine_romulus_class_init(ObjectClass 
*oc, void *data)
  amc->spi_model = "mx66l1g45g";
  amc->num_cs= 2;
  amc->i2c_init  = romulus_bmc_i2c_init;
+mc->valid_cpu_types = ast2500_a1_valid_cpu_types;
  mc->default_ram_size   = 512 * MiB;
  mc->default_cpus = mc->min_cpus = mc->max_cpus =
  aspeed_soc_num_cpus(amc->soc_name);
@@ -1306,6 +1315,7 @@ static void 
aspeed_machine_tiogapass_class_init(ObjectClass *oc, void *data)
  amc->spi_model = "mx25l25635e";
  amc->num_cs= 2;
  amc->i2c_init  = tiogapass_bmc_i2c_init;
+mc->valid_cpu_types = ast2500_a1_valid_cpu_types;
  mc->default_ram_size   = 1 * GiB;
  mc->default_cpus = mc->min_cpus = mc->max_cpus =
  aspeed_soc_num_cpus(amc->soc_name);
@@ -1324,6 +1334,7 @@ static void 
aspeed_machine_sonorapass_class_init(ObjectClass *oc, void *data)
  amc->spi_model = "mx66l1g45g";
  amc->num_cs= 2;
  amc->i2c_init  = sonorapass_bmc_i2c_init;
+mc->valid_cpu_types = ast2500_a1_valid_cpu_types;
  mc->default_ram_size   = 512 * MiB;
  mc->default_cpus = mc->min_cpus = mc->max_cpus =
  aspeed_soc_num_cpus(amc->soc_name);
@@ -1341,6 +1352,7 @@ static void 
aspeed_machine_witherspoon_class_init(ObjectClass *oc, void *data)
  amc->spi_model = "mx66l1g45g";
  amc->num_cs= 2;
  amc->i2c_init  = witherspoon_bmc_i2c_init;
+mc->valid_cpu_types = ast2500_a1_valid_cpu_types;
  mc->default_ram_size = 512 * MiB;
  mc->default_cpus = mc->min_cpus = mc->max_cpus =
  aspeed_soc_num_cpus(amc->soc_name);
@@ -1398,6 +1410,7 @@ static void aspeed_machine_g220a_class_init(ObjectClass 
*oc, void *data)
  amc->num_cs= 2;
  amc->macs_mask  = ASPEED_MAC0_ON | ASPEED_MAC1_ON;
  amc->i2c_init  = g220a_bmc_i2c_init;
+mc->valid_cpu_types = ast2500_a1_valid_cpu_types;
  mc->default_ram_size = 1024 * MiB;
  mc->default_cpus = mc->min_cpus = mc->max_cpus =
  aspeed_soc_num_cpus(amc->soc_name);
@@ -1416,6 +1429,7 @@ static void 
aspeed_machine_fp5280g2_class_init(ObjectClass *oc, void *data)
  amc->num_cs= 2;
  amc->macs_mask  = ASPEED_MAC0_ON | ASPEED_MAC1_ON;
  amc->i2c_init  = fp5280g2_bmc_i2c_init;
+mc->valid_cpu_types = ast2500_a1_valid_cpu_types;
  mc->default_ram_size = 512 * MiB;
  mc->default_cpus = mc->min_cpus = mc->max_cpus =
  aspeed_soc_num_cpus(amc->soc_name);





Re: [PATCH rfcv1 6/6] intel_iommu: add a framework to check and sync host IOMMU cap/ecap

2024-01-23 Thread Cédric Le Goater

On 1/15/24 11:13, Zhenzhong Duan wrote:

From: Yi Liu 

Add a framework to check and synchronize host IOMMU cap/ecap with
vIOMMU cap/ecap.

Currently only stage-2 translation is supported which is backed by
shadow page table on host side. So we don't need exact matching of
each bit of cap/ecap between vIOMMU and host. However, we can still
utilize this framework to ensure compatibility of host and vIOMMU's
address width at least, i.e., vIOMMU's aw_bits <= host aw_bits,
which is missed before.

When stage-1 translation is supported in future, a.k.a. scalable
modern mode, we need to ensure compatibility of each bits. Some
bits are user controllable, they should be checked with host side
to ensure compatibility. Other bits are not, they should be synced
into vIOMMU cap/ecap for compatibility.

The sequence will be:

vtd_cap_init() initializes iommu->cap/ecap.  vtd_cap_init()
iommu->host_cap/ecap is initialized as iommu->cap/ecap.   vtd_init()
iommu->host_cap/ecap is checked and updated some bits with host cap/ecap.  
vtd_sync_hw_info()
iommu->cap/ecap is finalized as iommu->host_cap/ecap.   
vtd_machine_done_hook()

iommu->host_cap/ecap is a temporary storage to hold intermediate value
when synthesize host cap/ecap and vIOMMU's initial configured cap/ecap.



The above "sequence" paragraph is not very clear. The patch may need to
be split further.




Signed-off-by: Yi Liu 
Signed-off-by: Yi Sun 
Signed-off-by: Zhenzhong Duan 
---
  include/hw/i386/intel_iommu.h |  4 ++
  hw/i386/intel_iommu.c | 78 +++
  2 files changed, 75 insertions(+), 7 deletions(-)

diff --git a/include/hw/i386/intel_iommu.h b/include/hw/i386/intel_iommu.h
index c65fdde56f..b8abbcce12 100644
--- a/include/hw/i386/intel_iommu.h
+++ b/include/hw/i386/intel_iommu.h
@@ -292,6 +292,9 @@ struct IntelIOMMUState {
  uint64_t cap;   /* The value of capability reg */
  uint64_t ecap;  /* The value of extended capability reg */
  
+uint64_t host_cap;  /* The value of host capability reg */

+uint64_t host_ecap; /* The value of host ext-capability reg */
+
  uint32_t context_cache_gen; /* Should be in [1,MAX] */
  GHashTable *iotlb;  /* IOTLB */
  
@@ -314,6 +317,7 @@ struct IntelIOMMUState {

  bool dma_translation;   /* Whether DMA translation supported */
  bool pasid; /* Whether to support PASID */
  
+bool cap_finalized; /* Whether VTD capability finalized */

  /*
   * Protects IOMMU states in general.  Currently it protects the
   * per-IOMMU IOTLB cache, and context entry cache in VTDAddressSpace.
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index 4c1d058ebd..be03fcbf52 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -3819,6 +3819,47 @@ VTDAddressSpace *vtd_find_add_as(IntelIOMMUState *s, 
PCIBus *bus,
  return vtd_dev_as;
  }
  
+static bool vtd_sync_hw_info(IntelIOMMUState *s, struct iommu_hw_info_vtd *vtd,

+ Error **errp)
+{
+uint64_t addr_width;
+
+addr_width = (vtd->cap_reg >> 16) & 0x3fULL;


Virek uses the same kind of macro in :

  
https://lore.kernel.org/qemu-devel/20240118192049.1796763-1-vivek.kasire...@intel.com/

What about the + 1 ? Looks like it's missing here, according to 11.4.2
Capability Register.

Could we introduce a common macro in intel_iommu_internal.h ?



+if (s->aw_bits > addr_width) {
+error_setg(errp, "User aw-bits: %u > host address width: %lu",


I think %lu should be PRId64. This is a general comment. You should avoid
%llx, %lx, etc. in the code.


+   s->aw_bits, addr_width);
+return false;
+}
+
+/* TODO: check and sync host cap/ecap into vIOMMU cap/ecap */
+
+return true;
+}
+
+/*
+ * virtual VT-d which wants nested needs to check the host IOMMU
+ * nesting cap info behind the assigned devices. Thus that vIOMMU
+ * could bind guest page table to host.
+ */
+static bool vtd_check_idev(IntelIOMMUState *s, IOMMUFDDevice *idev,
+   Error **errp)
+{
+struct iommu_hw_info_vtd vtd;
+enum iommu_hw_info_type type = IOMMU_HW_INFO_TYPE_INTEL_VTD;
+
+if (iommufd_device_get_info(idev, , sizeof(vtd), )) {
+error_setg(errp, "Failed to get IOMMU capability!!!");
+return false;
+}
+
+if (type != IOMMU_HW_INFO_TYPE_INTEL_VTD) {
+error_setg(errp, "IOMMU hardware is not compatible!!!");
+return false;
+}
+
+return vtd_sync_hw_info(s, , errp);
+}
+
  static int vtd_dev_set_iommu_device(PCIBus *bus, void *opaque, int32_t devfn,
  IOMMUFDDevice *idev, Error **errp)
  {
@@ -3837,6 +3878,10 @@ static int vtd_dev_set_iommu_device(PCIBus *bus, void 
*opaque, int32_t devfn,
  return 0;
  }
  
+if (!vtd_check_idev(s, idev, errp)) {

+return -1;
+}
+
  

Re: [PATCH rfcv1 2/6] hw/pci: introduce pci_device_set/unset_iommu_device()

2024-01-22 Thread Cédric Le Goater

On 1/23/24 07:37, Duan, Zhenzhong wrote:




-Original Message-
From: Cédric Le Goater 
Subject: Re: [PATCH rfcv1 2/6] hw/pci: introduce
pci_device_set/unset_iommu_device()

On 1/15/24 11:13, Zhenzhong Duan wrote:

From: Yi Liu 

This adds pci_device_set/unset_iommu_device() to set/unset
IOMMUFDDevice for a given PCIe device. Caller of set
should fail if set operation fails.

Extract out pci_device_get_iommu_bus_devfn() to facilitate
implementation of pci_device_set/unset_iommu_device().

Signed-off-by: Yi Liu 
Signed-off-by: Yi Sun 
Signed-off-by: Nicolin Chen 
Signed-off-by: Zhenzhong Duan 
---
   include/hw/pci/pci.h | 39 ++-
   hw/pci/pci.c | 49

+++-

   2 files changed, 86 insertions(+), 2 deletions(-)

diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
index fa6313aabc..a810c0ec74 100644
--- a/include/hw/pci/pci.h
+++ b/include/hw/pci/pci.h
@@ -7,6 +7,8 @@
   /* PCI includes legacy ISA access.  */
   #include "hw/isa/isa.h"

+#include "sysemu/iommufd_device.h"
+
   extern bool pci_available;

   /* PCI bus */
@@ -384,10 +386,45 @@ typedef struct PCIIOMMUOps {
*
* @devfn: device and function number
*/
-   AddressSpace * (*get_address_space)(PCIBus *bus, void *opaque, int

devfn);

+AddressSpace * (*get_address_space)(PCIBus *bus, void *opaque, int

devfn);

+/**
+ * @set_iommu_device: set iommufd device for a PCI device to

vIOMMU

+ *
+ * Optional callback, if not implemented in vIOMMU, then vIOMMU

can't

+ * utilize iommufd specific features.
+ *
+ * Return true if iommufd device is accepted, or else return false with
+ * errp set.
+ *
+ * @bus: the #PCIBus of the PCI device.
+ *
+ * @opaque: the data passed to pci_setup_iommu().
+ *
+ * @devfn: device and function number of the PCI device.
+ *
+ * @idev: the data structure representing iommufd device.
+ *
+ */
+int (*set_iommu_device)(PCIBus *bus, void *opaque, int32_t devfn,
+IOMMUFDDevice *idev, Error **errp);
+/**
+ * @unset_iommu_device: unset iommufd device for a PCI device from

vIOMMU

+ *
+ * Optional callback.
+ *
+ * @bus: the #PCIBus of the PCI device.
+ *
+ * @opaque: the data passed to pci_setup_iommu().
+ *
+ * @devfn: device and function number of the PCI device.
+ */
+void (*unset_iommu_device)(PCIBus *bus, void *opaque, int32_t

devfn);

   } PCIIOMMUOps;

   AddressSpace *pci_device_iommu_address_space(PCIDevice *dev);
+int pci_device_set_iommu_device(PCIDevice *dev, IOMMUFDDevice

*idev,

+Error **errp);
+void pci_device_unset_iommu_device(PCIDevice *dev);

   /**
* pci_setup_iommu: Initialize specific IOMMU handlers for a PCIBus
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 76080af580..3848662f95 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -2672,7 +2672,10 @@ static void

pci_device_class_base_init(ObjectClass *klass, void *data)

   }
   }

-AddressSpace *pci_device_iommu_address_space(PCIDevice *dev)
+static void pci_device_get_iommu_bus_devfn(PCIDevice *dev,
+   PCIBus **aliased_pbus,
+   PCIBus **piommu_bus,
+   uint8_t *aliased_pdevfn)
   {
   PCIBus *bus = pci_get_bus(dev);
   PCIBus *iommu_bus = bus;
@@ -2717,6 +2720,18 @@ AddressSpace

*pci_device_iommu_address_space(PCIDevice *dev)


   iommu_bus = parent_bus;
   }
+*aliased_pbus = bus;
+*piommu_bus = iommu_bus;
+*aliased_pdevfn = devfn;
+}
+
+AddressSpace *pci_device_iommu_address_space(PCIDevice *dev)
+{
+PCIBus *bus;
+PCIBus *iommu_bus;
+uint8_t devfn;
+
+pci_device_get_iommu_bus_devfn(dev, , _bus, );
   if (!pci_bus_bypass_iommu(bus) && iommu_bus->iommu_ops) {
   return iommu_bus->iommu_ops->get_address_space(bus,
iommu_bus->iommu_opaque, devfn);
@@ -2724,6 +2739,38 @@ AddressSpace

*pci_device_iommu_address_space(PCIDevice *dev)

   return _space_memory;
   }

+int pci_device_set_iommu_device(PCIDevice *dev, IOMMUFDDevice

*idev,

+Error **errp)
+{
+PCIBus *bus;
+PCIBus *iommu_bus;
+uint8_t devfn;
+
+pci_device_get_iommu_bus_devfn(dev, , _bus, );
+if (!pci_bus_bypass_iommu(bus) && iommu_bus &&


Why do we test iommu_bus in pci_device_un/set_iommu_device routines
and
not in pci_device_iommu_address_space() ?


iommu_bus check in pci_device_iommu_address_space() is dropped in
below commit, I didn't find related discussion in mail history, maybe
by accident? I can add it back if it's not intentional.


Can iommu_bus be NULL or should we add an assert ?

C.



ba7d12eb8c  hw/pci: modify pci_setup_iommu() to set PCIIOMMUOps

Thanks
Zhenzhong





Re: [PATCH] target/ppc: Re-name registers to match ISA

2024-01-22 Thread Cédric Le Goater

On 12/1/23 13:24, Nicholas Piggin wrote:

Several registers have names that don't match the ISA (or convention
with other QEMU PPC registers), making them unintuitive to use with
GDB.

Fortunately most of these registers are obscure and/or have not been
correctly implemented in the gdb server (e.g., DEC, TB, CFAR), so risk
of breaking users should be low.

QEMU should follow the ISA for register name convention (where there is
no established GDB name).

Signed-off-by: Nicholas Piggin 



Acked-by: Cédric Le Goater 

Thanks,

C.



---
There is never a great time to change user interface, but I'd like to
make this change for 9.0.

Thanks,
Nick

  target/ppc/cpu_init.c| 20 ++--
  target/ppc/helper_regs.c |  2 +-
  2 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index 40fe14a6c2..15c1f2fdc8 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -5062,7 +5062,7 @@ static void register_970_hid_sprs(CPUPPCState *env)
  
  static void register_970_hior_sprs(CPUPPCState *env)

  {
-spr_register(env, SPR_HIOR, "SPR_HIOR",
+spr_register(env, SPR_HIOR, "HIOR",
   SPR_NOACCESS, SPR_NOACCESS,
   _read_hior, _write_hior,
   0x);
@@ -5070,11 +5070,11 @@ static void register_970_hior_sprs(CPUPPCState *env)
  
  static void register_book3s_ctrl_sprs(CPUPPCState *env)

  {
-spr_register(env, SPR_CTRL, "SPR_CTRL",
+spr_register(env, SPR_CTRL, "CTRL",
   SPR_NOACCESS, SPR_NOACCESS,
   SPR_NOACCESS, _write_CTRL,
   0x);
-spr_register(env, SPR_UCTRL, "SPR_UCTRL",
+spr_register(env, SPR_UCTRL, "UCTRL",
   _read_ureg, SPR_NOACCESS,
   _read_ureg, SPR_NOACCESS,
   0x);
@@ -5465,7 +5465,7 @@ static void register_book3s_purr_sprs(CPUPPCState *env)
  static void register_power6_dbg_sprs(CPUPPCState *env)
  {
  #if !defined(CONFIG_USER_ONLY)
-spr_register(env, SPR_CFAR, "SPR_CFAR",
+spr_register(env, SPR_CFAR, "CFAR",
   SPR_NOACCESS, SPR_NOACCESS,
   _read_cfar, _write_cfar,
   0x);
@@ -5483,7 +5483,7 @@ static void register_power5p_common_sprs(CPUPPCState *env)
  static void register_power6_common_sprs(CPUPPCState *env)
  {
  #if !defined(CONFIG_USER_ONLY)
-spr_register_kvm(env, SPR_DSCR, "SPR_DSCR",
+spr_register_kvm(env, SPR_DSCR, "DSCR",
   SPR_NOACCESS, SPR_NOACCESS,
   _read_generic, _write_generic,
   KVM_REG_PPC_DSCR, 0x);
@@ -5695,7 +5695,7 @@ static void register_power8_book4_sprs(CPUPPCState *env)
   _read_generic, _write_generic,
   KVM_REG_PPC_ACOP, 0);
  /* PID is only in BookE in ISA v2.07 */
-spr_register_kvm(env, SPR_BOOKS_PID, "PID",
+spr_register_kvm(env, SPR_BOOKS_PID, "PIDR",
   SPR_NOACCESS, SPR_NOACCESS,
   _read_generic, _write_pidr,
   KVM_REG_PPC_PID, 0);
@@ -5716,7 +5716,7 @@ static void register_power7_book4_sprs(CPUPPCState *env)
   _read_generic, _write_generic,
   KVM_REG_PPC_ACOP, 0);
  /* PID is only in BookE in ISA v2.06 */
-spr_register_kvm(env, SPR_BOOKS_PID, "PID",
+spr_register_kvm(env, SPR_BOOKS_PID, "PIDR",
   SPR_NOACCESS, SPR_NOACCESS,
   _read_generic, _write_generic32,
   KVM_REG_PPC_PID, 0);
@@ -5750,7 +5750,7 @@ static void register_power9_mmu_sprs(CPUPPCState *env)
  _read_generic, _write_generic,
  0x);
  /* PID is part of the BookS ISA from v3.0 */
-spr_register_kvm(env, SPR_BOOKS_PID, "PID",
+spr_register_kvm(env, SPR_BOOKS_PID, "PIDR",
   SPR_NOACCESS, SPR_NOACCESS,
   _read_generic, _write_pidr,
   KVM_REG_PPC_PID, 0);
@@ -5791,7 +5791,7 @@ static void register_power10_dexcr_sprs(CPUPPCState *env)
  _read_generic, _write_generic32,
  0);
  
-spr_register(env, SPR_UDEXCR, "DEXCR",

+spr_register(env, SPR_UDEXCR, "UDEXCR",
  _read_dexcr_ureg, SPR_NOACCESS,
  _read_dexcr_ureg, SPR_NOACCESS,
  0);
@@ -5802,7 +5802,7 @@ static void register_power10_dexcr_sprs(CPUPPCState *env)
  _read_generic, _write_generic32,
  0);
  
-spr_register(env, SPR_UHDEXCR, "HDEXCR",

+spr_register(env, SPR_UHDEXCR, "UHDEXCR",
  _read_dexcr_ureg, SPR_NOACCESS,
  _read_dexcr_ureg, SPR_NOACCESS,
  0);
diff --git a/t

Re: [PATCH v6 9/9] ppc/pnv: Test pnv i2c master and connected devices

2024-01-22 Thread Cédric Le Goater

On 11/27/23 19:16, Glenn Miles wrote:

Tests the following for both P9 and P10:
   - I2C master POR status
   - I2C master status after immediate reset

Tests the following for powernv10-ranier only:
   - Config pca9552 hotplug device pins as inputs then
 Read the INPUT0/1 registers to verify all pins are high
   - Connected GPIO pin tests of P10 PCA9552 device.  Tests
 output of pins 0-4 affect input of pins 5-9 respectively.
   - PCA9554 GPIO pins test.  Tests input and ouput functionality.

Signed-off-by: Glenn Miles 
---


A couple of comments below, anyhow :

Reviewed-by: Cédric Le Goater 





No change from previous version

  tests/qtest/meson.build |   1 +
  tests/qtest/pnv-host-i2c-test.c | 650 
  2 files changed, 651 insertions(+)
  create mode 100644 tests/qtest/pnv-host-i2c-test.c

diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
index 47dabf91d0..fbb0bd204c 100644
--- a/tests/qtest/meson.build
+++ b/tests/qtest/meson.build
@@ -163,6 +163,7 @@ qtests_ppc64 = \
qtests_ppc + \
(config_all_devices.has_key('CONFIG_PSERIES') ? ['device-plug-test'] : []) 
+   \
(config_all_devices.has_key('CONFIG_POWERNV') ? ['pnv-xscom-test'] : []) +  
   \
+  (config_all_devices.has_key('CONFIG_POWERNV') ? ['pnv-host-i2c-test'] : []) 
+  \
(config_all_devices.has_key('CONFIG_PSERIES') ? ['rtas-test'] : []) +   
   \
(slirp.found() ? ['pxe-test'] : []) +  \
(config_all_devices.has_key('CONFIG_USB_UHCI') ? ['usb-hcd-uhci-test'] : 
[]) + \
diff --git a/tests/qtest/pnv-host-i2c-test.c b/tests/qtest/pnv-host-i2c-test.c
new file mode 100644
index 00..377525e458
--- /dev/null
+++ b/tests/qtest/pnv-host-i2c-test.c
@@ -0,0 +1,650 @@
+/*
+ * QTest testcase for PowerNV 10 Host I2C Communications
+ *
+ * Copyright (c) 2023, IBM Corporation.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * later. See the COPYING file in the top-level directory.
+ */
+#include "qemu/osdep.h"
+#include "libqtest.h"
+#include "hw/misc/pca9554_regs.h"
+#include "hw/misc/pca9552_regs.h"
+
+#define PPC_BIT(bit)(0x8000ULL >> (bit))
+#define PPC_BIT32(bit)  (0x8000 >> (bit))
+#define PPC_BIT8(bit)   (0x80 >> (bit))
+#define PPC_BITMASK(bs, be) ((PPC_BIT(bs) - PPC_BIT(be)) | PPC_BIT(bs))
+#define PPC_BITMASK32(bs, be)   ((PPC_BIT32(bs) - PPC_BIT32(be)) | \
+ PPC_BIT32(bs))
+
+#define MASK_TO_LSH(m)  (__builtin_ffsll(m) - 1)
+#define GETFIELD(m, v)  (((v) & (m)) >> MASK_TO_LSH(m))
+#define SETFIELD(m, v, val) \
+(((v) & ~(m)) | typeof(v))(val)) << MASK_TO_LSH(m)) & (m)))
+
+#define P10_XSCOM_BASE  0x000603fcull
+#define PNV10_CHIP_MAX_I2C  5
+#define PNV10_XSCOM_I2CM_BASE   0xa
+#define PNV10_XSCOM_I2CM_SIZE   0x1000
+
+/* I2C FIFO register */
+#define I2C_FIFO_REG0x4
+#define I2C_FIFOPPC_BITMASK(0, 7)
+
+/* I2C command register */
+#define I2C_CMD_REG 0x5
+#define I2C_CMD_WITH_START  PPC_BIT(0)
+#define I2C_CMD_WITH_ADDR   PPC_BIT(1)
+#define I2C_CMD_READ_CONT   PPC_BIT(2)
+#define I2C_CMD_WITH_STOP   PPC_BIT(3)
+#define I2C_CMD_INTR_STEERING   PPC_BITMASK(6, 7) /* P9 */
+#define   I2C_CMD_INTR_STEER_HOST   1
+#define   I2C_CMD_INTR_STEER_OCC2
+#define I2C_CMD_DEV_ADDRPPC_BITMASK(8, 14)
+#define I2C_CMD_READ_NOT_WRITE  PPC_BIT(15)
+#define I2C_CMD_LEN_BYTES   PPC_BITMASK(16, 31)
+#define I2C_MAX_TFR_LEN 0xfff0ull
+
+/* I2C mode register */
+#define I2C_MODE_REG0x6
+#define I2C_MODE_BIT_RATE_DIV   PPC_BITMASK(0, 15)
+#define I2C_MODE_PORT_NUM   PPC_BITMASK(16, 21)
+#define I2C_MODE_ENHANCED   PPC_BIT(28)
+#define I2C_MODE_DIAGNOSTIC PPC_BIT(29)
+#define I2C_MODE_PACING_ALLOW   PPC_BIT(30)
+#define I2C_MODE_WRAP   PPC_BIT(31)
+
+/* I2C watermark register */
+#define I2C_WATERMARK_REG   0x7
+#define I2C_WATERMARK_HIGH  PPC_BITMASK(16, 19)
+#define I2C_WATERMARK_LOW   PPC_BITMASK(24, 27)
+
+/*
+ * I2C interrupt mask and condition registers
+ *
+ * NB: The function of 0x9 and 0xa changes depending on whether you're reading
+ * or writing to them. When read they return the interrupt condition bits
+ * and on writes they update the interrupt mask register.
+ *
+ *  The bit definitions are the same for all the interrupt registers.
+ */
+#define I2C_INTR_MASK_REG   0x8
+
+#define I2C_INTR_RAW_COND_REG   0x9 /* read */
+#define I2C_INTR_MASK_OR_REG0x9 /* write*/
+
+#define I2C_INTR_COND_REG   

Re: [PATCH v3 8/8] target/ppc: Add SMT support to time facilities

2024-01-22 Thread Cédric Le Goater

On 12/1/23 13:16, Nicholas Piggin wrote:

The TB, VTB, PURR, HDEC SPRs are per-LPAR registers, and the TFMR is a
per-core register. Add the necessary SMT synchronisation and value
sharing.

The TFMR can only drive the timebase state machine via thread 0 of the
core, which is almost certainly not right, but it is enough for skiboot
and certain other proprietary firmware.

Signed-off-by: Nicholas Piggin 



Acked-by: Cédric Le Goater 

Thanks,

C.



---
  target/ppc/timebase_helper.c | 105 ---
  target/ppc/translate.c   |  42 +-
  2 files changed, 136 insertions(+), 11 deletions(-)

diff --git a/target/ppc/timebase_helper.c b/target/ppc/timebase_helper.c
index bc1d54a427..a23fbf75ff 100644
--- a/target/ppc/timebase_helper.c
+++ b/target/ppc/timebase_helper.c
@@ -60,19 +60,55 @@ target_ulong helper_load_purr(CPUPPCState *env)
  
  void helper_store_purr(CPUPPCState *env, target_ulong val)

  {
-cpu_ppc_store_purr(env, val);
+CPUState *cs = env_cpu(env);
+CPUState *ccs;
+uint32_t nr_threads = cs->nr_threads;
+
+if (nr_threads == 1 || !(env->flags & POWERPC_FLAG_SMT_1LPAR)) {
+cpu_ppc_store_purr(env, val);
+return;
+}
+
+THREAD_SIBLING_FOREACH(cs, ccs) {
+CPUPPCState *cenv = _CPU(ccs)->env;
+cpu_ppc_store_purr(cenv, val);
+}
  }
  #endif
  
  #if !defined(CONFIG_USER_ONLY)

  void helper_store_tbl(CPUPPCState *env, target_ulong val)
  {
-cpu_ppc_store_tbl(env, val);
+CPUState *cs = env_cpu(env);
+CPUState *ccs;
+uint32_t nr_threads = cs->nr_threads;
+
+if (nr_threads == 1 || !(env->flags & POWERPC_FLAG_SMT_1LPAR)) {
+cpu_ppc_store_tbl(env, val);
+return;
+}
+
+THREAD_SIBLING_FOREACH(cs, ccs) {
+CPUPPCState *cenv = _CPU(ccs)->env;
+cpu_ppc_store_tbl(cenv, val);
+}
  }
  
  void helper_store_tbu(CPUPPCState *env, target_ulong val)

  {
-cpu_ppc_store_tbu(env, val);
+CPUState *cs = env_cpu(env);
+CPUState *ccs;
+uint32_t nr_threads = cs->nr_threads;
+
+if (nr_threads == 1 || !(env->flags & POWERPC_FLAG_SMT_1LPAR)) {
+cpu_ppc_store_tbu(env, val);
+return;
+}
+
+THREAD_SIBLING_FOREACH(cs, ccs) {
+CPUPPCState *cenv = _CPU(ccs)->env;
+cpu_ppc_store_tbu(cenv, val);
+}
  }
  
  void helper_store_atbl(CPUPPCState *env, target_ulong val)

@@ -102,17 +138,53 @@ target_ulong helper_load_hdecr(CPUPPCState *env)
  
  void helper_store_hdecr(CPUPPCState *env, target_ulong val)

  {
-cpu_ppc_store_hdecr(env, val);
+CPUState *cs = env_cpu(env);
+CPUState *ccs;
+uint32_t nr_threads = cs->nr_threads;
+
+if (nr_threads == 1 || !(env->flags & POWERPC_FLAG_SMT_1LPAR)) {
+cpu_ppc_store_hdecr(env, val);
+return;
+}
+
+THREAD_SIBLING_FOREACH(cs, ccs) {
+CPUPPCState *cenv = _CPU(ccs)->env;
+cpu_ppc_store_hdecr(cenv, val);
+}
  }
  
  void helper_store_vtb(CPUPPCState *env, target_ulong val)

  {
-cpu_ppc_store_vtb(env, val);
+CPUState *cs = env_cpu(env);
+CPUState *ccs;
+uint32_t nr_threads = cs->nr_threads;
+
+if (nr_threads == 1 || !(env->flags & POWERPC_FLAG_SMT_1LPAR)) {
+cpu_ppc_store_vtb(env, val);
+return;
+}
+
+THREAD_SIBLING_FOREACH(cs, ccs) {
+CPUPPCState *cenv = _CPU(ccs)->env;
+cpu_ppc_store_vtb(cenv, val);
+}
  }
  
  void helper_store_tbu40(CPUPPCState *env, target_ulong val)

  {
-cpu_ppc_store_tbu40(env, val);
+CPUState *cs = env_cpu(env);
+CPUState *ccs;
+uint32_t nr_threads = cs->nr_threads;
+
+if (nr_threads == 1 || !(env->flags & POWERPC_FLAG_SMT_1LPAR)) {
+cpu_ppc_store_tbu40(env, val);
+return;
+}
+
+THREAD_SIBLING_FOREACH(cs, ccs) {
+CPUPPCState *cenv = _CPU(ccs)->env;
+cpu_ppc_store_tbu40(cenv, val);
+}
  }
  
  target_ulong helper_load_40x_pit(CPUPPCState *env)

@@ -211,6 +283,21 @@ static uint64_t tfmr_new_tb_state(uint64_t tfmr, unsigned 
int tbst)
  return tfmr;
  }
  
+static void write_tfmr(CPUPPCState *env, target_ulong val)

+{
+CPUState *cs = env_cpu(env);
+
+if (cs->nr_threads == 1) {
+env->spr[SPR_TFMR] = val;
+} else {
+CPUState *ccs;
+THREAD_SIBLING_FOREACH(cs, ccs) {
+CPUPPCState *cenv = _CPU(ccs)->env;
+cenv->spr[SPR_TFMR] = val;
+}
+}
+}
+
  static void tb_state_machine_step(CPUPPCState *env)
  {
  uint64_t tfmr = env->spr[SPR_TFMR];
@@ -224,7 +311,7 @@ static void tb_state_machine_step(CPUPPCState *env)
  env->pnv_tod_tbst.tb_sync_pulse_timer--;
  } else {
  tfmr |= TFMR_TB_SYNC_OCCURED;
-env->spr[SPR_TFMR] = tfmr;
+write_tfmr(env, tfmr);
  }
  
  if (env->pnv_tod_tbst.tb_state_timer) {

@@ -262,7 +349,7 @@ static void tb_state_machine_st

Re: [PATCH v3 5/8] ppc/pnv: Wire ChipTOD model to powernv9 and powernv10 machines

2024-01-22 Thread Cédric Le Goater

On 12/1/23 13:16, Nicholas Piggin wrote:

Wire the ChipTOD model to powernv9 and powernv10 machines.

Suggested-by-by: Cédric Le Goater 
Signed-off-by: Nicholas Piggin 



Reviewed-by: Cédric Le Goater 

Thanks,

C.



---
  include/hw/ppc/pnv_chip.h |  3 +++
  hw/ppc/pnv.c  | 30 ++
  2 files changed, 33 insertions(+)

diff --git a/include/hw/ppc/pnv_chip.h b/include/hw/ppc/pnv_chip.h
index 0ab5c42308..bfc4772cf3 100644
--- a/include/hw/ppc/pnv_chip.h
+++ b/include/hw/ppc/pnv_chip.h
@@ -2,6 +2,7 @@
  #define PPC_PNV_CHIP_H
  
  #include "hw/pci-host/pnv_phb4.h"

+#include "hw/ppc/pnv_chiptod.h"
  #include "hw/ppc/pnv_core.h"
  #include "hw/ppc/pnv_homer.h"
  #include "hw/ppc/pnv_lpc.h"
@@ -78,6 +79,7 @@ struct Pnv9Chip {
  PnvXive  xive;
  Pnv9Psi  psi;
  PnvLpcController lpc;
+PnvChipTOD   chiptod;
  PnvOCC   occ;
  PnvSBE   sbe;
  PnvHomer homer;
@@ -110,6 +112,7 @@ struct Pnv10Chip {
  PnvXive2 xive;
  Pnv9Psi  psi;
  PnvLpcController lpc;
+PnvChipTOD   chiptod;
  PnvOCC   occ;
  PnvSBE   sbe;
  PnvHomer homer;
diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index b949398689..d3cb76 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -1419,6 +1419,8 @@ static void pnv_chip_power9_instance_init(Object *obj)
  
  object_initialize_child(obj, "lpc", >lpc, TYPE_PNV9_LPC);
  
+object_initialize_child(obj, "chiptod", >chiptod, TYPE_PNV9_CHIPTOD);

+
  object_initialize_child(obj, "occ", >occ, TYPE_PNV9_OCC);
  
  object_initialize_child(obj, "sbe", >sbe, TYPE_PNV9_SBE);

@@ -1565,6 +1567,19 @@ static void pnv_chip_power9_realize(DeviceState *dev, 
Error **errp)
  chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0",
  (uint64_t) PNV9_LPCM_BASE(chip));
  
+/* ChipTOD */

+object_property_set_bool(OBJECT(>chiptod), "primary",
+ chip->chip_id == 0, _abort);
+object_property_set_bool(OBJECT(>chiptod), "secondary",
+ chip->chip_id == 1, _abort);
+object_property_set_link(OBJECT(>chiptod), "chip", OBJECT(chip),
+ _abort);
+if (!qdev_realize(DEVICE(>chiptod), NULL, errp)) {
+return;
+}
+pnv_xscom_add_subregion(chip, PNV9_XSCOM_CHIPTOD_BASE,
+>chiptod.xscom_regs);
+
  /* Create the simplified OCC model */
  if (!qdev_realize(DEVICE(>occ), NULL, errp)) {
  return;
@@ -1677,6 +1692,8 @@ static void pnv_chip_power10_instance_init(Object *obj)
"xive-fabric");
  object_initialize_child(obj, "psi", >psi, TYPE_PNV10_PSI);
  object_initialize_child(obj, "lpc", >lpc, TYPE_PNV10_LPC);
+object_initialize_child(obj, "chiptod", >chiptod,
+TYPE_PNV10_CHIPTOD);
  object_initialize_child(obj, "occ",  >occ, TYPE_PNV10_OCC);
  object_initialize_child(obj, "sbe",  >sbe, TYPE_PNV10_SBE);
  object_initialize_child(obj, "homer", >homer, TYPE_PNV10_HOMER);
@@ -1810,6 +1827,19 @@ static void pnv_chip_power10_realize(DeviceState *dev, 
Error **errp)
  chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0",
  (uint64_t) PNV10_LPCM_BASE(chip));
  
+/* ChipTOD */

+object_property_set_bool(OBJECT(>chiptod), "primary",
+ chip->chip_id == 0, _abort);
+object_property_set_bool(OBJECT(>chiptod), "secondary",
+ chip->chip_id == 1, _abort);
+object_property_set_link(OBJECT(>chiptod), "chip", OBJECT(chip),
+ _abort);
+if (!qdev_realize(DEVICE(>chiptod), NULL, errp)) {
+return;
+}
+pnv_xscom_add_subregion(chip, PNV10_XSCOM_CHIPTOD_BASE,
+>chiptod.xscom_regs);
+
  /* Create the simplified OCC model */
  if (!qdev_realize(DEVICE(>occ), NULL, errp)) {
  return;





Re: [PATCH rfcv1 4/6] vfio: initialize IOMMUFDDevice and pass to vIOMMU

2024-01-22 Thread Cédric Le Goater

On 1/15/24 11:13, Zhenzhong Duan wrote:

Initialize IOMMUFDDevice in vfio and pass to vIOMMU, so that vIOMMU
could get hw IOMMU information.

In VFIO legacy backend mode, we still pass a NULL IOMMUFDDevice to vIOMMU,
in case vIOMMU needs some processing for VFIO legacy backend mode.

Originally-by: Yi Liu 
Signed-off-by: Nicolin Chen 
Signed-off-by: Yi Sun 
Signed-off-by: Zhenzhong Duan 
---
  include/hw/vfio/vfio-common.h |  2 ++
  hw/vfio/iommufd.c |  2 ++
  hw/vfio/pci.c | 24 +++-
  3 files changed, 23 insertions(+), 5 deletions(-)

diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h
index 9b7ef7d02b..fde0d0ca60 100644
--- a/include/hw/vfio/vfio-common.h
+++ b/include/hw/vfio/vfio-common.h
@@ -31,6 +31,7 @@
  #endif
  #include "sysemu/sysemu.h"
  #include "hw/vfio/vfio-container-base.h"
+#include "sysemu/iommufd_device.h"
  
  #define VFIO_MSG_PREFIX "vfio %s: "
  
@@ -126,6 +127,7 @@ typedef struct VFIODevice {

  bool dirty_tracking;
  int devid;
  IOMMUFDBackend *iommufd;
+IOMMUFDDevice idev;
  } VFIODevice;
  
  struct VFIODeviceOps {

diff --git a/hw/vfio/iommufd.c b/hw/vfio/iommufd.c
index 9bfddc1360..cbd035f148 100644
--- a/hw/vfio/iommufd.c
+++ b/hw/vfio/iommufd.c
@@ -309,6 +309,7 @@ static int iommufd_cdev_attach(const char *name, VFIODevice 
*vbasedev,
  VFIOContainerBase *bcontainer;
  VFIOIOMMUFDContainer *container;
  VFIOAddressSpace *space;
+IOMMUFDDevice *idev = >idev;
  struct vfio_device_info dev_info = { .argsz = sizeof(dev_info) };
  int ret, devfd;
  uint32_t ioas_id;
@@ -428,6 +429,7 @@ found_container:
  QLIST_INSERT_HEAD(>device_list, vbasedev, container_next);
  QLIST_INSERT_HEAD(_device_list, vbasedev, global_next);
  
+iommufd_device_init(idev, sizeof(*idev), container->be, vbasedev->devid);

  trace_iommufd_cdev_device_info(vbasedev->name, devfd, vbasedev->num_irqs,
 vbasedev->num_regions, vbasedev->flags);
  return 0;
diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
index d7fe06715c..2c3a5d267b 100644
--- a/hw/vfio/pci.c
+++ b/hw/vfio/pci.c
@@ -3107,11 +3107,21 @@ static void vfio_realize(PCIDevice *pdev, Error **errp)
  
  vfio_bars_register(vdev);
  
-ret = vfio_add_capabilities(vdev, errp);

+if (vbasedev->iommufd) {
+ret = pci_device_set_iommu_device(pdev, >idev, errp);
+} else {
+ret = pci_device_set_iommu_device(pdev, 0, errp);



AFAICT, pci_device_set_iommu_device() with a NULL IOMMUFDDevice will do
nothing. Why call it ?


Thanks,

C.




+}
  if (ret) {
+error_prepend(errp, "Failed to set iommu_device: ");
  goto out_teardown;
  }
  
+ret = vfio_add_capabilities(vdev, errp);

+if (ret) {
+goto out_unset_idev;
+}
+
  if (vdev->vga) {
  vfio_vga_quirk_setup(vdev);
  }
@@ -3128,7 +3138,7 @@ static void vfio_realize(PCIDevice *pdev, Error **errp)
  error_setg(errp,
 "cannot support IGD OpRegion feature on hotplugged "
 "device");
-goto out_teardown;
+goto out_unset_idev;
  }
  
  ret = vfio_get_dev_region_info(vbasedev,

@@ -3137,13 +3147,13 @@ static void vfio_realize(PCIDevice *pdev, Error **errp)
  if (ret) {
  error_setg_errno(errp, -ret,
   "does not support requested IGD OpRegion 
feature");
-goto out_teardown;
+goto out_unset_idev;
  }
  
  ret = vfio_pci_igd_opregion_init(vdev, opregion, errp);

  g_free(opregion);
  if (ret) {
-goto out_teardown;
+goto out_unset_idev;
  }
  }
  
@@ -3229,6 +3239,8 @@ out_deregister:

  if (vdev->intx.mmap_timer) {
  timer_free(vdev->intx.mmap_timer);
  }
+out_unset_idev:
+pci_device_unset_iommu_device(pdev);
  out_teardown:
  vfio_teardown_msi(vdev);
  vfio_bars_exit(vdev);
@@ -3257,6 +3269,7 @@ static void vfio_instance_finalize(Object *obj)
  static void vfio_exitfn(PCIDevice *pdev)
  {
  VFIOPCIDevice *vdev = VFIO_PCI(pdev);
+VFIODevice *vbasedev = >vbasedev;
  
  vfio_unregister_req_notifier(vdev);

  vfio_unregister_err_notifier(vdev);
@@ -3271,7 +3284,8 @@ static void vfio_exitfn(PCIDevice *pdev)
  vfio_teardown_msi(vdev);
  vfio_pci_disable_rp_atomics(vdev);
  vfio_bars_exit(vdev);
-vfio_migration_exit(>vbasedev);
+vfio_migration_exit(vbasedev);
+pci_device_unset_iommu_device(pdev);
  }
  
  static void vfio_pci_reset(DeviceState *dev)





Re: [PATCH rfcv1 3/6] intel_iommu: add set/unset_iommu_device callback

2024-01-22 Thread Cédric Le Goater

On 1/15/24 11:13, Zhenzhong Duan wrote:

From: Yi Liu 

This adds set/unset_iommu_device() implementation in Intel vIOMMU.
In set call, IOMMUFDDevice is recorded in hash table indexed by
PCI BDF.

Signed-off-by: Yi Liu 
Signed-off-by: Yi Sun 
Signed-off-by: Zhenzhong Duan 
---
  include/hw/i386/intel_iommu.h | 10 +
  hw/i386/intel_iommu.c | 79 +++
  2 files changed, 89 insertions(+)

diff --git a/include/hw/i386/intel_iommu.h b/include/hw/i386/intel_iommu.h
index 7fa0a695c8..c65fdde56f 100644
--- a/include/hw/i386/intel_iommu.h
+++ b/include/hw/i386/intel_iommu.h
@@ -62,6 +62,7 @@ typedef union VTD_IR_TableEntry VTD_IR_TableEntry;
  typedef union VTD_IR_MSIAddress VTD_IR_MSIAddress;
  typedef struct VTDPASIDDirEntry VTDPASIDDirEntry;
  typedef struct VTDPASIDEntry VTDPASIDEntry;
+typedef struct VTDIOMMUFDDevice VTDIOMMUFDDevice;
  
  /* Context-Entry */

  struct VTDContextEntry {
@@ -148,6 +149,13 @@ struct VTDAddressSpace {
  IOVATree *iova_tree;
  };
  
+struct VTDIOMMUFDDevice {

+PCIBus *bus;
+uint8_t devfn;
+IOMMUFDDevice *idev;
+IntelIOMMUState *iommu_state;
+};


Does the VTDIOMMUFDDevice definition need to be public ?


  struct VTDIOTLBEntry {
  uint64_t gfn;
  uint16_t domain_id;
@@ -292,6 +300,8 @@ struct IntelIOMMUState {
  /* list of registered notifiers */
  QLIST_HEAD(, VTDAddressSpace) vtd_as_with_notifiers;
  
+GHashTable *vtd_iommufd_dev; /* VTDIOMMUFDDevice */

+
  /* interrupt remapping */
  bool intr_enabled;  /* Whether guest enabled IR */
  dma_addr_t intr_root;   /* Interrupt remapping table pointer */
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index ed5677c0ae..95faf697eb 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -237,6 +237,13 @@ static gboolean vtd_as_equal(gconstpointer v1, 
gconstpointer v2)
 (key1->pasid == key2->pasid);
  }
  
+static gboolean vtd_as_idev_equal(gconstpointer v1, gconstpointer v2)

+{
+const struct vtd_as_key *key1 = v1;
+const struct vtd_as_key *key2 = v2;
+
+return (key1->bus == key2->bus) && (key1->devfn == key2->devfn);
+}
  /*
   * Note that we use pointer to PCIBus as the key, so hashing/shifting
   * based on the pointer value is intended. Note that we deal with
@@ -3812,6 +3819,74 @@ VTDAddressSpace *vtd_find_add_as(IntelIOMMUState *s, 
PCIBus *bus,
  return vtd_dev_as;
  }
  
+static int vtd_dev_set_iommu_device(PCIBus *bus, void *opaque, int32_t devfn,

+IOMMUFDDevice *idev, Error **errp)
+{
+IntelIOMMUState *s = opaque;
+VTDIOMMUFDDevice *vtd_idev;
+struct vtd_as_key key = {
+.bus = bus,
+.devfn = devfn,
+};
+struct vtd_as_key *new_key;
+
+assert(0 <= devfn && devfn < PCI_DEVFN_MAX);


Can we move the assert earlier in the call stack ?
pci_device_get_iommu_bus_devfn() looks like a good place.


+
+/* None IOMMUFD case */
+if (!idev) {
+return 0;
+}


Can we move this test in the helper ? (Looks like an error to me).


Thanks,

C.



+
+vtd_iommu_lock(s);
+
+vtd_idev = g_hash_table_lookup(s->vtd_iommufd_dev, );
+
+if (vtd_idev) {
+error_setg(errp, "IOMMUFD device already exist");
+return -1;
+}
+
+new_key = g_malloc(sizeof(*new_key));
+new_key->bus = bus;
+new_key->devfn = devfn;
+
+vtd_idev = g_malloc0(sizeof(VTDIOMMUFDDevice));
+vtd_idev->bus = bus;
+vtd_idev->devfn = (uint8_t)devfn;
+vtd_idev->iommu_state = s;
+vtd_idev->idev = idev;
+
+g_hash_table_insert(s->vtd_iommufd_dev, new_key, vtd_idev);
+
+vtd_iommu_unlock(s);
+
+return 0;
+}
+
+static void vtd_dev_unset_iommu_device(PCIBus *bus, void *opaque, int32_t 
devfn)
+{
+IntelIOMMUState *s = opaque;
+VTDIOMMUFDDevice *vtd_idev;
+struct vtd_as_key key = {
+.bus = bus,
+.devfn = devfn,
+};
+
+assert(0 <= devfn && devfn < PCI_DEVFN_MAX);
+
+vtd_iommu_lock(s);
+
+vtd_idev = g_hash_table_lookup(s->vtd_iommufd_dev, );
+if (!vtd_idev) {
+vtd_iommu_unlock(s);
+return;
+}
+
+g_hash_table_remove(s->vtd_iommufd_dev, );
+
+vtd_iommu_unlock(s);
+}
+
  /* Unmap the whole range in the notifier's scope. */
  static void vtd_address_space_unmap(VTDAddressSpace *as, IOMMUNotifier *n)
  {
@@ -4107,6 +4182,8 @@ static AddressSpace *vtd_host_dma_iommu(PCIBus *bus, void 
*opaque, int devfn)
  
  static PCIIOMMUOps vtd_iommu_ops = {

  .get_address_space = vtd_host_dma_iommu,
+.set_iommu_device = vtd_dev_set_iommu_device,
+.unset_iommu_device = vtd_dev_unset_iommu_device,
  };
  
  static bool vtd_decide_config(IntelIOMMUState *s, Error **errp)

@@ -4230,6 +4307,8 @@ static void vtd_realize(DeviceState *dev, Error **errp)
   g_free, g_free);
  s->vtd_address_spaces = g_hash_table_new_full(vtd_as_hash, vtd_as_equal,
   

Re: [PATCH rfcv1 2/6] hw/pci: introduce pci_device_set/unset_iommu_device()

2024-01-22 Thread Cédric Le Goater

On 1/15/24 11:13, Zhenzhong Duan wrote:

From: Yi Liu 

This adds pci_device_set/unset_iommu_device() to set/unset
IOMMUFDDevice for a given PCIe device. Caller of set
should fail if set operation fails.

Extract out pci_device_get_iommu_bus_devfn() to facilitate
implementation of pci_device_set/unset_iommu_device().

Signed-off-by: Yi Liu 
Signed-off-by: Yi Sun 
Signed-off-by: Nicolin Chen 
Signed-off-by: Zhenzhong Duan 
---
  include/hw/pci/pci.h | 39 ++-
  hw/pci/pci.c | 49 +++-
  2 files changed, 86 insertions(+), 2 deletions(-)

diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
index fa6313aabc..a810c0ec74 100644
--- a/include/hw/pci/pci.h
+++ b/include/hw/pci/pci.h
@@ -7,6 +7,8 @@
  /* PCI includes legacy ISA access.  */
  #include "hw/isa/isa.h"
  
+#include "sysemu/iommufd_device.h"

+
  extern bool pci_available;
  
  /* PCI bus */

@@ -384,10 +386,45 @@ typedef struct PCIIOMMUOps {
   *
   * @devfn: device and function number
   */
-   AddressSpace * (*get_address_space)(PCIBus *bus, void *opaque, int devfn);
+AddressSpace * (*get_address_space)(PCIBus *bus, void *opaque, int devfn);
+/**
+ * @set_iommu_device: set iommufd device for a PCI device to vIOMMU
+ *
+ * Optional callback, if not implemented in vIOMMU, then vIOMMU can't
+ * utilize iommufd specific features.
+ *
+ * Return true if iommufd device is accepted, or else return false with
+ * errp set.
+ *
+ * @bus: the #PCIBus of the PCI device.
+ *
+ * @opaque: the data passed to pci_setup_iommu().
+ *
+ * @devfn: device and function number of the PCI device.
+ *
+ * @idev: the data structure representing iommufd device.
+ *
+ */
+int (*set_iommu_device)(PCIBus *bus, void *opaque, int32_t devfn,
+IOMMUFDDevice *idev, Error **errp);
+/**
+ * @unset_iommu_device: unset iommufd device for a PCI device from vIOMMU
+ *
+ * Optional callback.
+ *
+ * @bus: the #PCIBus of the PCI device.
+ *
+ * @opaque: the data passed to pci_setup_iommu().
+ *
+ * @devfn: device and function number of the PCI device.
+ */
+void (*unset_iommu_device)(PCIBus *bus, void *opaque, int32_t devfn);
  } PCIIOMMUOps;
  
  AddressSpace *pci_device_iommu_address_space(PCIDevice *dev);

+int pci_device_set_iommu_device(PCIDevice *dev, IOMMUFDDevice *idev,
+Error **errp);
+void pci_device_unset_iommu_device(PCIDevice *dev);
  
  /**

   * pci_setup_iommu: Initialize specific IOMMU handlers for a PCIBus
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 76080af580..3848662f95 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -2672,7 +2672,10 @@ static void pci_device_class_base_init(ObjectClass 
*klass, void *data)
  }
  }
  
-AddressSpace *pci_device_iommu_address_space(PCIDevice *dev)

+static void pci_device_get_iommu_bus_devfn(PCIDevice *dev,
+   PCIBus **aliased_pbus,
+   PCIBus **piommu_bus,
+   uint8_t *aliased_pdevfn)
  {
  PCIBus *bus = pci_get_bus(dev);
  PCIBus *iommu_bus = bus;
@@ -2717,6 +2720,18 @@ AddressSpace *pci_device_iommu_address_space(PCIDevice 
*dev)
  
  iommu_bus = parent_bus;

  }
+*aliased_pbus = bus;
+*piommu_bus = iommu_bus;
+*aliased_pdevfn = devfn;
+}
+
+AddressSpace *pci_device_iommu_address_space(PCIDevice *dev)
+{
+PCIBus *bus;
+PCIBus *iommu_bus;
+uint8_t devfn;
+
+pci_device_get_iommu_bus_devfn(dev, , _bus, );
  if (!pci_bus_bypass_iommu(bus) && iommu_bus->iommu_ops) {
  return iommu_bus->iommu_ops->get_address_space(bus,
   iommu_bus->iommu_opaque, devfn);
@@ -2724,6 +2739,38 @@ AddressSpace *pci_device_iommu_address_space(PCIDevice 
*dev)
  return _space_memory;
  }
  
+int pci_device_set_iommu_device(PCIDevice *dev, IOMMUFDDevice *idev,

+Error **errp)
+{
+PCIBus *bus;
+PCIBus *iommu_bus;
+uint8_t devfn;
+
+pci_device_get_iommu_bus_devfn(dev, , _bus, );
+if (!pci_bus_bypass_iommu(bus) && iommu_bus &&


Why do we test iommu_bus in pci_device_un/set_iommu_device routines and
not in pci_device_iommu_address_space() ?


Thanks,

C.



+iommu_bus->iommu_ops && iommu_bus->iommu_ops->set_iommu_device) {
+return iommu_bus->iommu_ops->set_iommu_device(pci_get_bus(dev),
+  iommu_bus->iommu_opaque,
+  dev->devfn, idev, errp);
+}
+return 0;
+}
+
+void pci_device_unset_iommu_device(PCIDevice *dev)
+{
+PCIBus *bus;
+PCIBus *iommu_bus;
+uint8_t devfn;
+
+pci_device_get_iommu_bus_devfn(dev, , _bus, );
+if (!pci_bus_bypass_iommu(bus) && iommu_bus &&
+

Re: [PATCH rfcv1 1/6] backends/iommufd_device: introduce IOMMUFDDevice

2024-01-22 Thread Cédric Le Goater

On 1/19/24 08:31, Duan, Zhenzhong wrote:




-Original Message-
From: Eric Auger 
Subject: Re: [PATCH rfcv1 1/6] backends/iommufd_device: introduce
IOMMUFDDevice



On 1/15/24 11:13, Zhenzhong Duan wrote:

IOMMUFDDevice represents a device in iommufd and can be used as
a communication interface between devices (i.e., VFIO, VDPA) and
vIOMMU.

Currently it includes iommufd handler and device id information
which could be used by vIOMMU to get hw IOMMU information.

In future nested translation support, vIOMMU is going to have
more iommufd related operations like allocate hwpt for a device,
attach/detach hwpt, etc. So IOMMUFDDevice will be further expanded.

IOMMUFDDevice is willingly not a QOM object because we don't want
it to be visible from the user interface.

Introduce a helper iommufd_device_init to initialize IOMMUFDDevice.

Originally-by: Yi Liu 
Signed-off-by: Yi Sun 
Signed-off-by: Zhenzhong Duan 
---
  MAINTAINERS |  4 +--
  include/sysemu/iommufd_device.h | 31 
  backends/iommufd_device.c   | 50

+
Maybe it is still time to move the iommufd files in a sepate dir, under
hw at the same level as vfio.

Thoughts?


Any reason for the movement? Hw dir contains entries to emulate different
Devices. Iommufd is not a real device. It's more a backend.


I would include the new services in the existing iommufd .[ch] files.
No need for a new file since the changes are all related to the IOMMUFD
device usage.

Thanks,

C.






Re: [PATCH 0/5] buses: switch to 3-phase-reset

2024-01-22 Thread Cédric Le Goater

Hello,

On 1/22/24 03:06, Peter Xu wrote:

Hi, Peter,

On Fri, Jan 19, 2024 at 04:35:07PM +, Peter Maydell wrote:

I wrote this ages ago and recently picked it back up because of a
recent PCI related reset ordering problem noted by Peter Xu.  I'm not
sure if this patchset is necessary as a part of fixing that ordering
problem (it might even be possible now to have the intel_iommu device
use 3-phase reset and put the relevant parts of its reset into the
'exit' phase), but either way we really ought to do this cleanup
to reduce the amount of legacy/transitional handling we have.


The VFIO issue I was working on may not directly benefit from this series
iiuc, as it's more of an special ordering on both (1) VFIO special case
reset path using qemu_register_reset(), and (2) VT-d device is not put at
the right place in the QOM hierachy [1].

Said that, thanks a lot for posting the patches; they all look reasonable
and good cleanups to the reset infrastructure, afaict.



Yes. I took the series in my vfio testing environment (x86_64 and s390x) and
didn't see any issue. I will keep it for further testing.

Thanks,

C.






Re: [PATCH 2/2] ppc/pnv: Change powernv default to powernv10

2024-01-19 Thread Cédric Le Goater

On 1/18/24 15:14, Nicholas Piggin wrote:

POWER10 is the latest IBM Power machine. Although it is not offered in
"OPAL mode" (i.e., powernv configuration), so there is a case that it
should remain at powernv9, most of the development work is going into
powernv10 at the moment.

Signed-off-by: Nicholas Piggin 


May be we could drop support for power10_v1.0 and power9_v1.0 ? These
were bringup CPUs.

Anyhow,

Reviewed-by: Cédric Le Goater 

Thanks,

C.



---
  hw/ppc/pnv.c | 4 ++--
  1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index 0297871bdd..b949398689 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -2242,8 +2242,6 @@ static void pnv_machine_power9_class_init(ObjectClass 
*oc, void *data)
  
  xfc->match_nvt = pnv_match_nvt;
  
-mc->alias = "powernv";

-
  pmc->compat = compat;
  pmc->compat_size = sizeof(compat);
  pmc->dt_power_mgt = pnv_dt_power_mgt;
@@ -2267,6 +2265,8 @@ static void pnv_machine_power10_class_init(ObjectClass 
*oc, void *data)
  mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power10_v2.0");
  compat_props_add(mc->compat_props, phb_compat, G_N_ELEMENTS(phb_compat));
  
+mc->alias = "powernv";

+
  pmc->compat = compat;
  pmc->compat_size = sizeof(compat);
  pmc->dt_power_mgt = pnv_dt_power_mgt;





Re: [PATCH 8/8] ppc/pnv: Update skiboot to v7.1

2024-01-19 Thread Cédric Le Goater

On 1/18/24 15:09, Nicholas Piggin wrote:

This includes a number of improvements and fixes. Importantly there
is a change for QEMU platforms to permit the ChipTOD to be initialised
if it is present in the device tree. This will facilitate ChipTOD
enablement in pnv.

Signed-off-by: Nicholas Piggin 



Reviewed-by: Cédric Le Goater 

Thanks,

C.



---> [blob omitted, patch is just for comments]

  pc-bios/skiboot.lid | Bin 2527240 -> 2527328 bytes
  roms/skiboot|   2 +-
  2 files changed, 1 insertion(+), 1 deletion(-)

diff --git a/roms/skiboot b/roms/skiboot
index 24a7eb3596..dbd5de6624 16
--- a/roms/skiboot
+++ b/roms/skiboot
@@ -1 +1 @@
-Subproject commit 24a7eb35966d93455520bc2debdd7954314b638b
+Subproject commit dbd5de6624d7466bb67d1eb4e57bc3a8e2ad9e87





Re: [PATCH 00/26] target/ppc: TCG improvements and fixes

2024-01-19 Thread Cédric Le Goater

Hello Nick,

On 1/18/24 16:06, Nicholas Piggin wrote:

This is mostly TCG core emulation improvements and fixes. I
got the chiptod model in there because it's intertwined with
TFMR SPR.

Other non-TCG patches are spapr MSR entry point change which
goes together with the other machine check / MSR[ME] fixes.
And Saif's gdb patches, as well as some SPR renaming.

Will probably a bit more similar patches too, e.g., Dan's SPR
patches, but I'll just get this out for review before
upstreaming it.


Before we start a new round of reviews, could we please uptream the ones
reviewed in the previous cycle [1] ? Some are part of this series and we
shoudn't have to go through them again.

Thanks,

C.

[1] https://patchwork.ozlabs.org/project/qemu-ppc/list/




Re: [PATCH v2 0/3] s390x/pci: fix ISM reset

2024-01-18 Thread Cédric Le Goater

On 1/18/24 19:51, Matthew Rosato wrote:

Commit ef1535901a0 (re-)introduced an issue where passthrough ISM devices
on s390x would enter an error state after reboot.  This was previously fixed
by 03451953c79e, using device reset callbacks, however the change in
ef1535901a0 effectively triggers a cold reset of the pci bus before the
device reset callbacks are triggered.

To resolve this, this series proposes to remove the use of the reset callback
for ISM cleanup and instead trigger ISM reset from subsystem_reset before
triggering bus resets.  This has to happen before the bus resets because the
reset of s390-pcihost will trigger reset of the PCI bus followed by the
s390-pci bus, and the former will trigger vfio-pci reset / the aperture-wide
unmap that ISM gets upset about.
  
   /s390-pcihost (s390-pcihost)

 /pci.0 (PCI)
 /s390-pcibus.0 (s390-pcibus)
 
While fixing this, it was also noted that kernel warnings could be seen that

indicate a guest ISC reference count error.  That's because in some reset
cases we were not bothering to disable AIF, but would again re-enable it after
the reset (causing the reference count to grow erroneously).  This was a base
issue that went unnoticed because the kernel previously did not detect and
issue a warning for this scenario.


Changes for v2:
- Fold a typo fix from patch 2 into patch 1 where it belongs
- Add block comment re: timing of ISM reset
- Add review tags



Reviewed-by: Cédric Le Goater 

Thanks,

C.






Re: [PATCH 0/4] ppc: add machine check injection HMP command

2024-01-18 Thread Cédric Le Goater

Hello Nick,

On 1/18/24 15:34, Nicholas Piggin wrote:

I'd like to resurrect this and get it merged, because it's quite
useful for testing (has caught several Linux bugs in the past).

IIRC the main concern David had last time it came up was that it
should have QMP commands too. Which is valid. But I ended up
deciding it wouldn't be nice to expose this low level interface too
much, it would be better to use maybe a higher level error injection
interface that would be emulated in more detail (e.g., not just a
MCE, but would set relevant FIR registers and go through error
handling logic).

Since x86 has a low level 'mce' hmp command without qmp equivalent,
and since better error injection might take some time, I'd like to
just hold nose and take this for now.



I reworked this series some years ago :

  https://lore.kernel.org/qemu-devel/20211013214042.618918-1-...@kaod.org/

Did you take into account the changes ?


Thanks,

C.




Thanks,
Nick

Nicholas Piggin (4):
   nmi: add MCE class for implementing machine check injection commands
   ppc/spapr: Implement mce injection
   target/ppc: Add machine check interrupt injection helper
   ppc/pnv: Implement mce injection

  include/hw/nmi.h | 20 
  include/hw/ppc/spapr.h   |  3 ++
  include/monitor/hmp-target.h |  1 -
  include/monitor/hmp.h|  1 +
  target/ppc/cpu.h |  1 +
  hw/core/nmi.c| 61 
  hw/ppc/pnv.c | 55 
  hw/ppc/spapr.c   | 54 +++
  hw/ppc/spapr_events.c|  3 +-
  monitor/hmp-cmds.c   |  1 +
  target/ppc/excp_helper.c |  7 +
  target/ppc/ppc-qmp-cmds.c| 10 ++
  hmp-commands.hx  | 20 +++-
  13 files changed, 233 insertions(+), 4 deletions(-)






Re: [PATCH] vfio: use matching sizeof type

2024-01-17 Thread Cédric Le Goater

On 1/18/24 06:09, Peter Xu wrote:

On Wed, Jan 17, 2024 at 05:03:44PM +0100, Paolo Bonzini wrote:

Do not use uint64_t for the type of the declaration and __u64 when
computing the number of elements in the array.

Signed-off-by: Paolo Bonzini 
---
  hw/vfio/common.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/vfio/common.c b/hw/vfio/common.c
index 0b3352f2a9d..0da4003ecf5 100644
--- a/hw/vfio/common.c
+++ b/hw/vfio/common.c
@@ -1118,7 +1118,7 @@ static int vfio_device_dma_logging_report(VFIODevice 
*vbasedev, hwaddr iova,
  {
  uint64_t buf[DIV_ROUND_UP(sizeof(struct vfio_device_feature) +
  sizeof(struct vfio_device_feature_dma_logging_report),
-sizeof(__u64))] = {};
+sizeof(uint64_t))] = {};
  struct vfio_device_feature *feature = (struct vfio_device_feature *)buf;
  struct vfio_device_feature_dma_logging_report *report =
  (struct vfio_device_feature_dma_logging_report *)feature->data;


There seem to have other places in the sme file that reference __u64.  Are
we going to remove all __u64 references?  Or maybe something else?


AFAIUI, this change is to match the types of the 'buf' array and
the one used by sizeof.
 

Copy Alex/Cedric to make sure this won't get lost..


Applied to vfio-next.

Thanks,

C.




Re: [PATCH 3/3] s390x/pci: drive ISM reset from subsystem reset

2024-01-17 Thread Cédric Le Goater

On 1/17/24 22:11, Matthew Rosato wrote:

On 1/17/24 10:19 AM, Matthew Rosato wrote:

On 1/17/24 6:01 AM, Cédric Le Goater wrote:

Adding Alex,

On 1/16/24 23:31, Matthew Rosato wrote:

ISM devices are sensitive to manipulation of the IOMMU, so the ISM device
needs to be reset before the vfio-pci device is reset (triggering a full
UNMAP).  In order to ensure this occurs, trigger ISM device resets from
subsystem_reset before triggering the PCI bus reset (which will also
trigger vfio-pci reset).  This only needs to be done for ISM devices
which were enabled for use by the guest.
Further, ensure that AIF is disabled as part of the reset event.

Fixes: ef1535901a ("s390x: do a subsystem reset before the unprotect on reboot")
Fixes: 03451953c7 ("s390x/pci: reset ISM passthrough devices on shutdown and system 
reset")
Reported-by: Cédric Le Goater 
Signed-off-by: Matthew Rosato 
---
   hw/s390x/s390-pci-bus.c | 26 +-
   hw/s390x/s390-virtio-ccw.c  |  2 ++
   include/hw/s390x/s390-pci-bus.h |  1 +
   3 files changed, 20 insertions(+), 9 deletions(-)

diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c
index 347580ebac..3e57d5faca 100644
--- a/hw/s390x/s390-pci-bus.c
+++ b/hw/s390x/s390-pci-bus.c
@@ -151,20 +151,12 @@ static void s390_pci_shutdown_notifier(Notifier *n, void 
*opaque)
   pci_device_reset(pbdev->pdev);
   }
   -static void s390_pci_reset_cb(void *opaque)
-{
-    S390PCIBusDevice *pbdev = opaque;
-
-    pci_device_reset(pbdev->pdev);
-}
-
   static void s390_pci_perform_unplug(S390PCIBusDevice *pbdev)
   {
   HotplugHandler *hotplug_ctrl;
     if (pbdev->pft == ZPCI_PFT_ISM) {
   notifier_remove(>shutdown_notifier);
-    qemu_unregister_reset(s390_pci_reset_cb, pbdev);
   }
     /* Unplug the PCI device */
@@ -1132,7 +1124,6 @@ static void s390_pcihost_plug(HotplugHandler 
*hotplug_dev, DeviceState *dev,
   if (pbdev->pft == ZPCI_PFT_ISM) {
   pbdev->shutdown_notifier.notify = s390_pci_shutdown_notifier;
   qemu_register_shutdown_notifier(>shutdown_notifier);
-    qemu_register_reset(s390_pci_reset_cb, pbdev);
   }
   } else {
   pbdev->fh |= FH_SHM_EMUL;
@@ -1279,6 +1270,23 @@ static void s390_pci_enumerate_bridge(PCIBus *bus, 
PCIDevice *pdev,
   pci_default_write_config(pdev, PCI_SUBORDINATE_BUS, s->bus_no, 1);
   }
   +void s390_pci_ism_reset(void)
+{
+    S390pciState *s = s390_get_phb();
+
+    S390PCIBusDevice *pbdev, *next;
+
+    /* Trigger reset event for each passthrough ISM device currently in-use */
+    QTAILQ_FOREACH_SAFE(pbdev, >zpci_devs, link, next) {
+    if (pbdev->interp && pbdev->pft == ZPCI_PFT_ISM &&
+    pbdev->fh & FH_MASK_ENABLE) {
+    s390_pci_kvm_aif_disable(pbdev);
+
+    pci_device_reset(pbdev->pdev);
+    }
+    }
+}



Could we instead define a VFIOPCIDevice::resetfn handler for these
ISM devices (1014:04ed) ? This would be cleaner if possible.

If so, as a prerequisite, we would need to introduce in a little VFIO
helper to define custom reset handlers.

Thanks,

C.



Oh interesting, I had not noticed that.  This may well work -- resetfn is 
currently setup via vfio_setup_resetfn_quirk but it would probably be easier to 
have a helper that takes the vdev and a function pointer so that we can provide 
a platform-specific reset handler (rather than having hw/vfio/pci-quirks.c 
worry about CONFIG_S390 etc).  I'll have to play around with this.
  



Hmm, it was a good idea but I don't think this will work.  I tried to hack 
something together today but I'm definitely seeing paths where the 
vfio_listener_region_del happens before the call to vfio_pci_reset (which would 
ultimately trigger the new custom resetfn).


OK.
 

Perhaps we should stick with the call from subsystem_reset -- it will ensure 
that the ISM cleanup happens after guest CPUs are stopped but before vfio does 
its cleanup.


Let's keep the subsystem_reset() method then. Please add a comment on the reset 
ordering.

Thanks,

C.










Re: [PATCH v2 2/2] docs/about: Deprecate the old "power5+" and "power7+" CPU names

2024-01-17 Thread Cédric Le Goater

On 1/17/24 15:10, Thomas Huth wrote:

For consistency we should drop the names with a "+" in it in the
long run.

Signed-off-by: Thomas Huth 



Reviewed-by: Cédric Le Goater 

Thanks,

C.



---
  docs/about/deprecated.rst | 9 +
  1 file changed, 9 insertions(+)

diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst
index b47763330c..251723d264 100644
--- a/docs/about/deprecated.rst
+++ b/docs/about/deprecated.rst
@@ -217,6 +217,15 @@ Nios II CPU (since 8.2)
  The Nios II architecture is orphan. The ``nios2`` guest CPU support is
  deprecated and will be removed in a future version of QEMU.
  
+``power5+`` and ``power7+`` CPU names (since 9.0)

+'
+
+The character "+" in device (and thus also CPU) names is not allowed
+in the QEMU object model anymore. ``power5+``, ``power5+_v2.1``,
+``power7+`` and ``power7+_v2.1`` are currently still supported via
+an alias, but for consistency these will get removed in a future
+release, too. Use ``power5p_v2.1`` and ``power7p_v2.1`` instead.
+
  
  System emulator machines

  





Re: [PATCH v2 1/2] target/ppc/cpu-models: Rename power5+ and power7+ for new QOM naming rules

2024-01-17 Thread Cédric Le Goater

On 1/17/24 15:10, Thomas Huth wrote:

The character "+" is now forbidden in QOM device names (see commit
b447378e1217 - "Limit type names to alphanumerical and some few special
characters"). For the "power5+" and "power7+" CPU names, there is
currently a hack in type_name_is_valid() to still allow them for
compatibility reasons. However, there is a much nicer solution for this:
Simply use aliases! This way we can still support the old names without
the need for the ugly hack in type_name_is_valid().

Signed-off-by: Thomas Huth 



Reviewed-by: Cédric Le Goater 

Thanks,

C.



---
  hw/ppc/spapr_cpu_core.c |  4 ++--
  qom/object.c|  4 
  target/ppc/cpu-models.c | 10 ++
  3 files changed, 8 insertions(+), 10 deletions(-)

diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c
index 5aa1ed474a..0c0fb3f1b0 100644
--- a/hw/ppc/spapr_cpu_core.c
+++ b/hw/ppc/spapr_cpu_core.c
@@ -389,9 +389,9 @@ static const TypeInfo spapr_cpu_core_type_infos[] = {
  DEFINE_SPAPR_CPU_CORE_TYPE("970_v2.2"),
  DEFINE_SPAPR_CPU_CORE_TYPE("970mp_v1.0"),
  DEFINE_SPAPR_CPU_CORE_TYPE("970mp_v1.1"),
-DEFINE_SPAPR_CPU_CORE_TYPE("power5+_v2.1"),
+DEFINE_SPAPR_CPU_CORE_TYPE("power5p_v2.1"),
  DEFINE_SPAPR_CPU_CORE_TYPE("power7_v2.3"),
-DEFINE_SPAPR_CPU_CORE_TYPE("power7+_v2.1"),
+DEFINE_SPAPR_CPU_CORE_TYPE("power7p_v2.1"),
  DEFINE_SPAPR_CPU_CORE_TYPE("power8_v2.0"),
  DEFINE_SPAPR_CPU_CORE_TYPE("power8e_v2.1"),
  DEFINE_SPAPR_CPU_CORE_TYPE("power8nvl_v1.0"),
diff --git a/qom/object.c b/qom/object.c
index 654e1afaf2..2c4c64d2b6 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -160,10 +160,6 @@ static bool type_name_is_valid(const char *name)
  
  /* Allow some legacy names with '+' in it for compatibility reasons */

  if (name[plen] == '+') {
-if (plen == 6 && g_str_has_prefix(name, "power")) {
-/* Allow "power5+" and "power7+" CPU names*/
-return true;
-}
  if (plen >= 17 && g_str_has_prefix(name, "Sun-UltraSparc-I")) {
  /* Allow "Sun-UltraSparc-IV+" and "Sun-UltraSparc-IIIi+" */
  return true;
diff --git a/target/ppc/cpu-models.c b/target/ppc/cpu-models.c
index 7dbb47de64..36e465b390 100644
--- a/target/ppc/cpu-models.c
+++ b/target/ppc/cpu-models.c
@@ -716,11 +716,11 @@
  "PowerPC 970MP v1.0")
  POWERPC_DEF("970mp_v1.1",CPU_POWERPC_970MP_v11,  970,
  "PowerPC 970MP v1.1")
-POWERPC_DEF("power5+_v2.1",  CPU_POWERPC_POWER5P_v21,POWER5P,
+POWERPC_DEF("power5p_v2.1",  CPU_POWERPC_POWER5P_v21,POWER5P,
  "POWER5+ v2.1")
  POWERPC_DEF("power7_v2.3",   CPU_POWERPC_POWER7_v23, POWER7,
  "POWER7 v2.3")
-POWERPC_DEF("power7+_v2.1",  CPU_POWERPC_POWER7P_v21,POWER7,
+POWERPC_DEF("power7p_v2.1",  CPU_POWERPC_POWER7P_v21,POWER7,
  "POWER7+ v2.1")
  POWERPC_DEF("power8e_v2.1",  CPU_POWERPC_POWER8E_v21,POWER8,
  "POWER8E v2.1")
@@ -902,10 +902,12 @@ PowerPCCPUAlias ppc_cpu_aliases[] = {
  { "970", "970_v2.2" },
  { "970fx", "970fx_v3.1" },
  { "970mp", "970mp_v1.1" },
-{ "power5+", "power5+_v2.1" },
+{ "power5+", "power5p_v2.1" },
+{ "power5+_v2.1", "power5p_v2.1" },
  { "power5gs", "power5+_v2.1" },
  { "power7", "power7_v2.3" },
-{ "power7+", "power7+_v2.1" },
+{ "power7+", "power7p_v2.1" },
+{ "power7+_v2.1", "power7p_v2.1" },
  { "power8e", "power8e_v2.1" },
  { "power8", "power8_v2.0" },
  { "power8nvl", "power8nvl_v1.0" },





Re: [PATCH 2/4] reset: Allow multiple stages of system resets

2024-01-17 Thread Cédric Le Goater

On 1/17/24 11:28, Eric Auger wrote:

Hi Peter,
On 1/17/24 10:15, pet...@redhat.com wrote:

From: Peter Xu 

QEMU resets do not have a way to order reset hooks.  Add one coarse grained
reset stage so that some devices can be reset later than some others.

I would precise that the lowest stage has the highest priority and is
handled first.


yes. May be add an enum like we have for migration :

typedef enum {
MIG_PRI_DEFAULT = 0,
MIG_PRI_IOMMU,  /* Must happen before PCI devices */
MIG_PRI_PCI_BUS,/* Must happen before IOMMU */
MIG_PRI_VIRTIO_MEM, /* Must happen before IOMMU */
MIG_PRI_GICV3_ITS,  /* Must happen before PCI devices */
MIG_PRI_GICV3,  /* Must happen before the ITS */
MIG_PRI_MAX,
} MigrationPriority;

I think it would help understand the reset ordering and maintenance
when grepping qemu_register_reset_one().

Thanks,

C.





Signed-off-by: Peter Xu 
---
  include/sysemu/reset.h |  5 
  hw/core/reset.c| 60 +++---
  2 files changed, 49 insertions(+), 16 deletions(-)

diff --git a/include/sysemu/reset.h b/include/sysemu/reset.h
index 609e4d50c2..0de697ce9f 100644
--- a/include/sysemu/reset.h
+++ b/include/sysemu/reset.h
@@ -5,9 +5,14 @@
  
  typedef void QEMUResetHandler(void *opaque);
  
+#define  QEMU_RESET_STAGES_N  2

+
  void qemu_register_reset(QEMUResetHandler *func, void *opaque);
+void qemu_register_reset_one(QEMUResetHandler *func, void *opaque,
+ bool skip_snap, int stage);
  void qemu_register_reset_nosnapshotload(QEMUResetHandler *func, void *opaque);
  void qemu_unregister_reset(QEMUResetHandler *func, void *opaque);
+void qemu_unregister_reset_one(QEMUResetHandler *func, void *opaque, int 
stage);
  void qemu_devices_reset(ShutdownCause reason);
  
  #endif

diff --git a/hw/core/reset.c b/hw/core/reset.c
index 8cf60b2b09..a84c9bee84 100644
--- a/hw/core/reset.c
+++ b/hw/core/reset.c
@@ -36,55 +36,83 @@ typedef struct QEMUResetEntry {
  bool skip_on_snapshot_load;
  } QEMUResetEntry;
  
-static QTAILQ_HEAD(, QEMUResetEntry) reset_handlers =

-QTAILQ_HEAD_INITIALIZER(reset_handlers);
+typedef QTAILQ_HEAD(QEMUResetList, QEMUResetEntry) QEMUResetList;
+static QEMUResetList reset_handlers[QEMU_RESET_STAGES_N];
  
-static void qemu_register_reset_one(QEMUResetHandler *func, void *opaque,

-bool skip_snap)
+static void __attribute__((__constructor__)) qemu_reset_handlers_init(void)
+{
+QEMUResetList *head;
+int i = 0;

nit: you may put the declarations within the block

+
+for (i = 0; i < QEMU_RESET_STAGES_N; i++) {
+head = _handlers[i];
+QTAILQ_INIT(head);
+}
+}
+
+void qemu_register_reset_one(QEMUResetHandler *func, void *opaque,
+ bool skip_snap, int stage)
  {
  QEMUResetEntry *re = g_new0(QEMUResetEntry, 1);
+QEMUResetList *head;
+
+assert(stage >= 0 && stage < QEMU_RESET_STAGES_N);
+head = _handlers[stage];
  
  re->func = func;

  re->opaque = opaque;
  re->skip_on_snapshot_load = skip_snap;
-QTAILQ_INSERT_TAIL(_handlers, re, entry);
+QTAILQ_INSERT_TAIL(head, re, entry);
  }
  
  void qemu_register_reset(QEMUResetHandler *func, void *opaque)

  {
-/* By default, do not skip during load of a snapshot */

Shouldn't the above comment stay since the statement is not affected by
this patch? Or remove it in previous patch?

-qemu_register_reset_one(func, opaque, false);
+qemu_register_reset_one(func, opaque, false, 0);
  }
  
  void qemu_register_reset_nosnapshotload(QEMUResetHandler *func, void *opaque)

  {
-qemu_register_reset_one(func, opaque, true);
+qemu_register_reset_one(func, opaque, true, 0);
  }
  
-void qemu_unregister_reset(QEMUResetHandler *func, void *opaque)

+void qemu_unregister_reset_one(QEMUResetHandler *func, void *opaque, int stage)
  {
+QEMUResetList *head;
  QEMUResetEntry *re;
  
-QTAILQ_FOREACH(re, _handlers, entry) {

+assert(stage >= 0 && stage < QEMU_RESET_STAGES_N);
+head = _handlers[stage];
+
+QTAILQ_FOREACH(re, head, entry) {
  if (re->func == func && re->opaque == opaque) {
-QTAILQ_REMOVE(_handlers, re, entry);
+QTAILQ_REMOVE(head, re, entry);
  g_free(re);
  return;
  }
  }
  }
  
+void qemu_unregister_reset(QEMUResetHandler *func, void *opaque)

+{
+qemu_unregister_reset_one(func, opaque, 0);
+}
+
  void qemu_devices_reset(ShutdownCause reason)
  {
  QEMUResetEntry *re, *nre;
+QEMUResetList *head;
+int stage;
  
  /* reset all devices */

-QTAILQ_FOREACH_SAFE(re, _handlers, entry, nre) {
-if (reason == SHUTDOWN_CAUSE_SNAPSHOT_LOAD &&
-re->skip_on_snapshot_load) {
-continue;
+for (stage = 0; stage < QEMU_RESET_STAGES_N; stage++) {
+head = _handlers[stage];
+

Re: [PATCH 3/3] s390x/pci: drive ISM reset from subsystem reset

2024-01-17 Thread Cédric Le Goater

Adding Alex,

On 1/16/24 23:31, Matthew Rosato wrote:

ISM devices are sensitive to manipulation of the IOMMU, so the ISM device
needs to be reset before the vfio-pci device is reset (triggering a full
UNMAP).  In order to ensure this occurs, trigger ISM device resets from
subsystem_reset before triggering the PCI bus reset (which will also
trigger vfio-pci reset).  This only needs to be done for ISM devices
which were enabled for use by the guest.
Further, ensure that AIF is disabled as part of the reset event.

Fixes: ef1535901a ("s390x: do a subsystem reset before the unprotect on reboot")
Fixes: 03451953c7 ("s390x/pci: reset ISM passthrough devices on shutdown and system 
reset")
Reported-by: Cédric Le Goater 
Signed-off-by: Matthew Rosato 
---
  hw/s390x/s390-pci-bus.c | 26 +-
  hw/s390x/s390-virtio-ccw.c  |  2 ++
  include/hw/s390x/s390-pci-bus.h |  1 +
  3 files changed, 20 insertions(+), 9 deletions(-)

diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c
index 347580ebac..3e57d5faca 100644
--- a/hw/s390x/s390-pci-bus.c
+++ b/hw/s390x/s390-pci-bus.c
@@ -151,20 +151,12 @@ static void s390_pci_shutdown_notifier(Notifier *n, void 
*opaque)
  pci_device_reset(pbdev->pdev);
  }
  
-static void s390_pci_reset_cb(void *opaque)

-{
-S390PCIBusDevice *pbdev = opaque;
-
-pci_device_reset(pbdev->pdev);
-}
-
  static void s390_pci_perform_unplug(S390PCIBusDevice *pbdev)
  {
  HotplugHandler *hotplug_ctrl;
  
  if (pbdev->pft == ZPCI_PFT_ISM) {

  notifier_remove(>shutdown_notifier);
-qemu_unregister_reset(s390_pci_reset_cb, pbdev);
  }
  
  /* Unplug the PCI device */

@@ -1132,7 +1124,6 @@ static void s390_pcihost_plug(HotplugHandler 
*hotplug_dev, DeviceState *dev,
  if (pbdev->pft == ZPCI_PFT_ISM) {
  pbdev->shutdown_notifier.notify = s390_pci_shutdown_notifier;
  qemu_register_shutdown_notifier(>shutdown_notifier);
-qemu_register_reset(s390_pci_reset_cb, pbdev);
  }
  } else {
  pbdev->fh |= FH_SHM_EMUL;
@@ -1279,6 +1270,23 @@ static void s390_pci_enumerate_bridge(PCIBus *bus, 
PCIDevice *pdev,
  pci_default_write_config(pdev, PCI_SUBORDINATE_BUS, s->bus_no, 1);
  }
  
+void s390_pci_ism_reset(void)

+{
+S390pciState *s = s390_get_phb();
+
+S390PCIBusDevice *pbdev, *next;
+
+/* Trigger reset event for each passthrough ISM device currently in-use */
+QTAILQ_FOREACH_SAFE(pbdev, >zpci_devs, link, next) {
+if (pbdev->interp && pbdev->pft == ZPCI_PFT_ISM &&
+pbdev->fh & FH_MASK_ENABLE) {
+s390_pci_kvm_aif_disable(pbdev);
+
+pci_device_reset(pbdev->pdev);
+}
+}
+}



Could we instead define a VFIOPCIDevice::resetfn handler for these
ISM devices (1014:04ed) ? This would be cleaner if possible.

If so, as a prerequisite, we would need to introduce in a little VFIO
helper to define custom reset handlers.

Thanks,

C.





+
  static void s390_pcihost_reset(DeviceState *dev)
  {
  S390pciState *s = S390_PCI_HOST_BRIDGE(dev);
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index 1169e20b94..4de04f7e9f 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -118,6 +118,8 @@ static void subsystem_reset(void)
  DeviceState *dev;
  int i;
  
+s390_pci_ism_reset();

+
  for (i = 0; i < ARRAY_SIZE(reset_dev_types); i++) {
  dev = DEVICE(object_resolve_path_type("", reset_dev_types[i], NULL));
  if (dev) {
diff --git a/include/hw/s390x/s390-pci-bus.h b/include/hw/s390x/s390-pci-bus.h
index 435e788867..2c43ea123f 100644
--- a/include/hw/s390x/s390-pci-bus.h
+++ b/include/hw/s390x/s390-pci-bus.h
@@ -401,5 +401,6 @@ S390PCIBusDevice *s390_pci_find_dev_by_target(S390pciState 
*s,
const char *target);
  S390PCIBusDevice *s390_pci_find_next_avail_dev(S390pciState *s,
 S390PCIBusDevice *pbdev);
+void s390_pci_ism_reset(void);
  
  #endif





Re: [PATCH 1/3] s390x/pci: avoid double enable/disable of aif

2024-01-17 Thread Cédric Le Goater

On 1/16/24 23:31, Matthew Rosato wrote:

Use a flag to keep track of whether AIF is currently enabled.  This can be
used to avoid enabling/disabling AIF multiple times as well as to determine
whether or not it should be disabled during reset processing.


Why don't we disable AIF always at reset ? Doesn't KVM handle multiple calls
to KVM_S390_ZPCIOP_DEREG_AEN cleanly ? Just asking, I am no expert there.

Thanks,

C.



Fixes: d0bc7091c2 ("s390x/pci: enable adapter event notification for interpreted 
devices")
Reported-by: Cédric Le Goater 
Signed-off-by: Matthew Rosato 
---
  hw/s390x/s390-pci-kvm.c | 25 +++--
  include/hw/s390x/s390-pci-bus.h |  1 +
  2 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/hw/s390x/s390-pci-kvm.c b/hw/s390x/s390-pci-kvm.c
index ff41e4106d..f7e10cfa72 100644
--- a/hw/s390x/s390-pci-kvm.c
+++ b/hw/s390x/s390-pci-kvm.c
@@ -27,6 +27,7 @@ bool s390_pci_kvm_interp_allowed(void)
  
  int s390_pci_kvm_aif_enable(S390PCIBusDevice *pbdev, ZpciFib *fib, bool assist)

  {
+int rc;
  struct kvm_s390_zpci_op args = {
  .fh = pbdev->fh,
  .op = KVM_S390_ZPCIOP_REG_AEN,
@@ -38,15 +39,35 @@ int s390_pci_kvm_aif_enable(S390PCIBusDevice *pbdev, 
ZpciFib *fib, bool assist)
  .u.reg_aen.flags = (assist) ? 0 : KVM_S390_ZPCIOP_REGAEN_HOST
  };
  
-return kvm_vm_ioctl(kvm_state, KVM_S390_ZPCI_OP, );

+if (pbdev->aif) {
+return -EINVAL;
+}
+
+rc = kvm_vm_ioctl(kvm_state, KVM_S390_ZPCI_OP, );
+if (rc == 0) {
+pbdev->aif = true;
+}
+
+return rc;
  }
  
  int s390_pci_kvm_aif_disable(S390PCIBusDevice *pbdev)

  {
+int rc;
+
  struct kvm_s390_zpci_op args = {
  .fh = pbdev->fh,
  .op = KVM_S390_ZPCIOP_DEREG_AEN
  };
  
-return kvm_vm_ioctl(kvm_state, KVM_S390_ZPCI_OP, );

+if (!pbdev->aif) {
+return -EINVAL;
+}
+
+rc = kvm_vm_ioctl(kvm_state, KVM_S390_ZPCI_OP, );
+if (rc == 0) {
+pbev->aif = false;
+}
+
+return rc;
  }
diff --git a/include/hw/s390x/s390-pci-bus.h b/include/hw/s390x/s390-pci-bus.h
index b1bdbeaeb5..435e788867 100644
--- a/include/hw/s390x/s390-pci-bus.h
+++ b/include/hw/s390x/s390-pci-bus.h
@@ -361,6 +361,7 @@ struct S390PCIBusDevice {
  bool unplug_requested;
  bool interp;
  bool forwarding_assist;
+bool aif;
  QTAILQ_ENTRY(S390PCIBusDevice) link;
  };
  





Re: [PATCH 2/3] s390x/pci: refresh fh before disabling aif

2024-01-17 Thread Cédric Le Goater

On 1/16/24 23:31, Matthew Rosato wrote:

Typically we refresh the host fh during CLP enable, however it's possible
that the device goes through multiple reset events before the guest
performs another CLP enable.  Let's handle this for now by refreshing the
host handle from vfio before disabling aif.

Fixes: 03451953c7 ("s390x/pci: reset ISM passthrough devices on shutdown and system 
reset")
Reported-by: Cédric Le Goater 
Signed-off-by: Matthew Rosato 
---
  hw/s390x/s390-pci-kvm.c | 11 ++-
  1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/hw/s390x/s390-pci-kvm.c b/hw/s390x/s390-pci-kvm.c
index f7e10cfa72..9eef4fc3ec 100644
--- a/hw/s390x/s390-pci-kvm.c
+++ b/hw/s390x/s390-pci-kvm.c
@@ -18,6 +18,7 @@
  #include "hw/s390x/s390-pci-bus.h"
  #include "hw/s390x/s390-pci-kvm.h"
  #include "hw/s390x/s390-pci-inst.h"
+#include "hw/s390x/s390-pci-vfio.h"
  #include "cpu_models.h"
  
  bool s390_pci_kvm_interp_allowed(void)

@@ -64,9 +65,17 @@ int s390_pci_kvm_aif_disable(S390PCIBusDevice *pbdev)
  return -EINVAL;
  }
  
+/*

+ * The device may have already been reset but we still want to relinquish
+ * the guest ISC, so always be sure to use an up-to-date host fh.
+ */
+if (!s390_pci_get_host_fh(pbdev, )) {
+return -EPERM;
+}


The callers of s390_pci_kvm_aif_disable() all test the original host
function with :

   if (pbdev->interp && (pbdev->fh & FH_MASK_ENABLE))

This change possibly fetches a new one. Shouldn't we move the test
also in s390_pci_kvm_aif_disable() ?


Thanks,

C.




+
  rc = kvm_vm_ioctl(kvm_state, KVM_S390_ZPCI_OP, );
  if (rc == 0) {
-pbev->aif = false;
+pbdev->aif = false;
  }
  
  return rc;





Re: [PATCH 2/3] s390x/pci: refresh fh before disabling aif

2024-01-17 Thread Cédric Le Goater

Hello Matthew,

On 1/16/24 23:31, Matthew Rosato wrote:

Typically we refresh the host fh during CLP enable, however it's possible
that the device goes through multiple reset events before the guest
performs another CLP enable.  Let's handle this for now by refreshing the
host handle from vfio before disabling aif.

Fixes: 03451953c7 ("s390x/pci: reset ISM passthrough devices on shutdown and system 
reset")
Reported-by: Cédric Le Goater 
Signed-off-by: Matthew Rosato 
---
  hw/s390x/s390-pci-kvm.c | 11 ++-
  1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/hw/s390x/s390-pci-kvm.c b/hw/s390x/s390-pci-kvm.c
index f7e10cfa72..9eef4fc3ec 100644
--- a/hw/s390x/s390-pci-kvm.c
+++ b/hw/s390x/s390-pci-kvm.c
@@ -18,6 +18,7 @@
  #include "hw/s390x/s390-pci-bus.h"
  #include "hw/s390x/s390-pci-kvm.h"
  #include "hw/s390x/s390-pci-inst.h"
+#include "hw/s390x/s390-pci-vfio.h"
  #include "cpu_models.h"
  
  bool s390_pci_kvm_interp_allowed(void)

@@ -64,9 +65,17 @@ int s390_pci_kvm_aif_disable(S390PCIBusDevice *pbdev)
  return -EINVAL;
  }
  
+/*

+ * The device may have already been reset but we still want to relinquish
+ * the guest ISC, so always be sure to use an up-to-date host fh.
+ */
+if (!s390_pci_get_host_fh(pbdev, )) {
+return -EPERM;
+}
+
  rc = kvm_vm_ioctl(kvm_state, KVM_S390_ZPCI_OP, );
  if (rc == 0) {
-pbev->aif = false;
+pbdev->aif = false;
  }


This belongs to patch 1.


Thanks,

C.


  
  return rc;





Re: [PATCH v3 22/46] hw/arm/aspeed: use qemu_configure_nic_device()

2024-01-16 Thread Cédric Le Goater

On 1/8/24 21:26, David Woodhouse wrote:

From: David Woodhouse 

Signed-off-by: David Woodhouse 
---
  hw/arm/aspeed.c | 9 -
  1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index cc59176563..bed5e4f40b 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -356,7 +356,6 @@ static void aspeed_machine_init(MachineState *machine)
  AspeedMachineClass *amc = ASPEED_MACHINE_GET_CLASS(machine);
  AspeedSoCClass *sc;
  int i;
-NICInfo *nd = _table[0];
  
  bmc->soc = ASPEED_SOC(object_new(amc->soc_name));

  object_property_add_child(OBJECT(machine), "soc", OBJECT(bmc->soc));
@@ -371,10 +370,10 @@ static void aspeed_machine_init(MachineState *machine)
   _fatal);
  
  for (i = 0; i < sc->macs_num; i++) {

-if ((amc->macs_mask & (1 << i)) && nd->used) {
-qemu_check_nic_model(nd, TYPE_FTGMAC100);
-qdev_set_nic_properties(DEVICE(>soc->ftgmac100[i]), nd);
-nd++;
+if ((amc->macs_mask & (1 << i)) &&
+!qemu_configure_nic_device(DEVICE(>soc->ftgmac100[i]),
+   true, NULL)) {
+    break; /* No configs left; stop asking */
  }
  }
  


Acked-by: Cédric Le Goater 

Thanks,

C.





Re: [PATCH 00/33] hw/cpu/arm: Remove one use of qemu_get_cpu() in A7/A15 MPCore priv

2024-01-15 Thread Cédric Le Goater

On 1/12/24 20:54, Fabiano Rosas wrote:

Cédric Le Goater  writes:


On 1/10/24 14:19, Fabiano Rosas wrote:

Markus Armbruster  writes:


Peter Xu  writes:


On Tue, Jan 09, 2024 at 10:22:31PM +0100, Philippe Mathieu-Daudé wrote:

Hi Fabiano,

On 9/1/24 21:21, Fabiano Rosas wrote:

Cédric Le Goater  writes:


On 1/9/24 18:40, Fabiano Rosas wrote:

Cédric Le Goater  writes:


On 1/3/24 20:53, Fabiano Rosas wrote:

Philippe Mathieu-Daudé  writes:


+Peter/Fabiano

On 2/1/24 17:41, Cédric Le Goater wrote:

On 1/2/24 17:15, Philippe Mathieu-Daudé wrote:

Hi Cédric,

On 2/1/24 15:55, Cédric Le Goater wrote:

On 12/12/23 17:29, Philippe Mathieu-Daudé wrote:

Hi,

When a MPCore cluster is used, the Cortex-A cores belong the the
cluster container, not to the board/soc layer. This series move
the creation of vCPUs to the MPCore private container.

Doing so we consolidate the QOM model, moving common code in a
central place (abstract MPCore parent).


Changing the QOM hierarchy has an impact on the state of the machine
and some fixups are then required to maintain migration compatibility.
This can become a real headache for KVM machines like virt for which
migration compatibility is a feature, less for emulated ones.


All changes are either moving properties (which are not migrated)
or moving non-migrated QOM members (i.e. pointers of ARMCPU, which
is still migrated elsewhere). So I don't see any obvious migration
problem, but I might be missing something, so I Cc'ed Juan :>


FWIW, I didn't spot anything problematic either.

I've ran this through my migration compatibility series [1] and it
doesn't regress aarch64 migration from/to 8.2. The tests use '-M
virt -cpu max', so the cortex-a7 and cortex-a15 are not covered. I don't
think we even support migration of anything non-KVM on arm.


it happens we do.



Oh, sorry, I didn't mean TCG here. Probably meant to say something like
non-KVM-capable cpus, as in 32-bit. Nevermind.


Theoretically, we should be able to migrate to a TCG guest. Well, this
worked in the past for PPC. When I was doing more KVM related changes,
this was very useful for dev. Also, some machines are partially emulated.
Anyhow I agree this is not a strong requirement and we often break it.
Let's focus on KVM only.


1- https://gitlab.com/farosas/qemu/-/jobs/5853599533


yes it depends on the QOM hierarchy and virt seems immune to the changes.
Good.

However, changing the QOM topology clearly breaks migration compat,


Well, "clearly" is relative =) You've mentioned pseries and aspeed
already, do you have a pointer to one of those cases were we broke
migration


Regarding pseries, migration compat broke because of 5bc8d26de20c
("spapr: allocate the ICPState object from under sPAPRCPUCore") which
is similar to the changes proposed by this series, it impacts the QOM
hierarchy. Here is the workaround/fix from Greg : 46f7afa37096
("spapr: fix migration of ICPState objects from/to older QEMU") which
is quite an headache and this turned out to raise another problem some
months ago ... :/ That's why I sent [1] to prepare removal of old
machines and workarounds becoming a burden.


This feels like something that could be handled by the vmstate code
somehow. The state is there, just under a different path.


What, the QOM path is used in migration? ...


Hopefully not..


Unfortunately the original fix doesn't mention _what_ actually broke
with migration. I assumed the QOM path was needed because otherwise I
don't think the fix makes sense. The thread discussing that patch also
directly mentions the QOM path:

https://www.mail-archive.com/qemu-devel@nongnu.org/msg450912.html

But I probably misunderstood something while reading that thread.





See recent discussions on "QOM path stability":
https://lore.kernel.org/qemu-devel/zzfyvlmcxbcia...@redhat.com/
https://lore.kernel.org/qemu-devel/87jzojbxt7@pond.sub.org/
https://lore.kernel.org/qemu-devel/87v883by34@pond.sub.org/


If I read it right, the commit 46f7afa37096 example is pretty special that
the QOM path more or less decided more than the hierachy itself but changes
the existances of objects.


Let's see whether I got this...

We removed some useless objects, moved the useful ones to another home.
The move changed their QOM path.

The problem was the removal of useless objects, because this also
removed their vmstate.


If you checkout at the removal commit (5bc8d26de20c), the vmstate has
been kept untouched.



The fix was adding the vmstate back as a dummy.


Since the vmstate was kept I don't see why would we need a dummy. The
incoming migration stream would still have the state, only at a
different point in the stream. It's surprising to me that that would
cause an issue, but I'm not well versed in that code.



The QOM patch changes are *not* part of the problem.


The only explanation I can come up with is that after the patch
migration has broken after a hotplug or similar operation. In s

Re: Possible race condition in aspeed ast2600 smp boot on TCG QEMU

2024-01-12 Thread Cédric Le Goater

Adding Aspeed Engineers. This reminds me of a discussion a while ago.

On 1/11/24 18:38, Stephen Longfield wrote:

We’ve noticed inconsistent behavior when running a large number of aspeed 
ast2600 executions, that seems to be tied to a race condition in the smp boot 
when executing on TCG-QEMU, and were wondering what a good mediation strategy 
might be.

The problem first shows up as part of SMP boot. On a run that’s likely to later 
run into issues, we’ll see something like:

```
[    0.008350] smp: Bringing up secondary CPUs ...
[    1.168584] CPU1: failed to come online
[    1.187277] smp: Brought up 1 node, 1 CPU
```

Compared to the more likely to succeed:

```
[    0.080313] smp: Bringing up secondary CPUs ...
[    0.093166] smp: Brought up 1 node, 2 CPUs
[    0.093345] SMP: Total of 2 processors activated (4800.00 BogoMIPS).
```

It’s somewhat reliably reproducible by running the ast2600-evb with an OpenBMC 
image, using ‘-icount auto’ to slow execution and make the race condition more 
frequent (it happens without this, just easier to debug if we can reproduce):


```
./aarch64-softmmu/qemu-system-aarch64 -machine ast2600-evb -nographic -drive 
file=~/bmc-bin/image-obmc-ast2600,if=mtd,bus=0,unit=0,snapshot=on -nic user 
-icount auto
```

Our current hypothesis is that the problem comes up in the platform uboot.  As 
part of the boot, the secondary core waits for the smp mailbox to get a magic 
number written by the primary core:

https://github.com/AspeedTech-BMC/u-boot/blob/aspeed-master-v2019.04/arch/arm/mach-aspeed/ast2600/platform.S#L168
 


However, this memory address is cleared on boot:

https://github.com/AspeedTech-BMC/u-boot/blob/aspeed-master-v2019.04/arch/arm/mach-aspeed/ast2600/platform.S#L146
 


The race condition occurs if the primary core runs far ahead of the secondary 
core: if the primary core gets to the point where it signals the secondary 
core’s mailbox before the secondary core gets past the point where it does the 
initial reset and starts waiting, the reset will clear the signal, and then the 
secondary core will never get past the point where it’s looping in 
`poll_smp_mbox_ready`.

We’ve observed this race happening by dumping all SCU reads and writes, and 
validated that this is the problem by using a modified `platform.S` that 
doesn’t clear the =SCU_SMP_READY mailbox on reset, but would rather not have to 
use a modified version of SMP boot just for QEMU-TCG execution.


you could use '-trace aspeed_scu*' to collect the MMIO accesses on
the SCU unit. A TCG plugin also.


Is there a way to have QEMU insert a barrier synchronization at some point in 
the bootloader?  I think getting both cores past the =SCU_SMP_READY reset would 
get rid of this race, but I’m not aware of a way to do that kind of thing in 
QEMU-TCG.

Thanks for any insights!


Could we change the default value to registers 0x180 ... 0x18C in
hw/misc/aspeed_scu.c to make sure the SMP regs are immune to the
race ?

Thanks,

C.







Re: [PATCH v10 9/9] hw/fsi: Update MAINTAINER list

2024-01-12 Thread Cédric Le Goater

On 1/11/24 00:15, Ninad Palsule wrote:

Added maintainer for IBM FSI model

Signed-off-by: Cédric Le Goater 


Please remove my S-o-b.


Signed-off-by: Ninad Palsule 
---
  MAINTAINERS | 8 
  1 file changed, 8 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 00ec1f7eca..79f97a3fb9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3569,6 +3569,14 @@ F: tests/qtest/adm1272-test.c
  F: tests/qtest/max34451-test.c
  F: tests/qtest/isl_pmbus_vr-test.c
  
+FSI

+M: Ninad Palsule 


and add me as Reviewer.

Thanks,

C.



+S: Maintained
+F: hw/fsi/*
+F: include/hw/fsi/*
+F: docs/specs/fsi.rst
+F: tests/qtest/fsi-test.c
+
  Firmware schema specifications
  M: Philippe Mathieu-Daudé 
  R: Daniel P. Berrange 





Re: [PATCH v10 8/9] hw/fsi: Added FSI documentation

2024-01-12 Thread Cédric Le Goater

On 1/11/24 00:15, Ninad Palsule wrote:

Documentation for IBM FSI model.

Signed-off-by: Cédric Le Goater 


Please remove mu S-o-b.

Thanks,

C.



Signed-off-by: Ninad Palsule 
---
  docs/specs/fsi.rst   | 138 +++
  docs/specs/index.rst |   1 +
  2 files changed, 139 insertions(+)
  create mode 100644 docs/specs/fsi.rst

diff --git a/docs/specs/fsi.rst b/docs/specs/fsi.rst
new file mode 100644
index 00..05a6b6347a
--- /dev/null
+++ b/docs/specs/fsi.rst
@@ -0,0 +1,138 @@
+==
+IBM's Flexible Service Interface (FSI)
+==
+
+The QEMU FSI emulation implements hardware interfaces between ASPEED SOC, FSI
+master/slave and the end engine.
+
+FSI is a point-to-point two wire interface which is capable of supporting
+distances of up to 4 meters. FSI interfaces have been used successfully for
+many years in IBM servers to attach IBM Flexible Support Processors(FSP) to
+CPUs and IBM ASICs.
+
+FSI allows a service processor access to the internal buses of a host POWER
+processor to perform configuration or debugging. FSI has long existed in POWER
+processes and so comes with some baggage, including how it has been integrated
+into the ASPEED SoC.
+
+Working backwards from the POWER processor, the fundamental pieces of interest
+for the implementation are: (see the `FSI specification`_ for more details)
+
+1. The Common FRU Access Macro (CFAM), an address space containing various
+   "engines" that drive accesses on buses internal and external to the POWER
+   chip. Examples include the SBEFIFO and I2C masters. The engines hang off of
+   an internal Local Bus (LBUS) which is described by the CFAM configuration
+   block.
+
+2. The FSI slave: The slave is the terminal point of the FSI bus for FSI
+   symbols addressed to it. Slaves can be cascaded off of one another. The
+   slave's configuration registers appear in address space of the CFAM to
+   which it is attached.
+
+3. The FSI master: A controller in the platform service processor (e.g. BMC)
+   driving CFAM engine accesses into the POWER chip. At the hardware level
+   FSI is a bit-based protocol supporting synchronous and DMA-driven accesses
+   of engines in a CFAM.
+
+4. The On-Chip Peripheral Bus (OPB): A low-speed bus typically found in POWER
+   processors. This now makes an appearance in the ASPEED SoC due to tight
+   integration of the FSI master IP with the OPB, mainly the existence of an
+   MMIO-mapping of the CFAM address straight onto a sub-region of the OPB
+   address space.
+
+5. An APB-to-OPB bridge enabling access to the OPB from the ARM core in the
+   AST2600. Hardware limitations prevent the OPB from being directly mapped
+   into APB, so all accesses are indirect through the bridge.
+
+The LBUS is modelled to maintain the qdev bus hierarchy and to take advantages
+of the object model to automatically generate the CFAM configuration block.
+The configuration block presents engines in the order they are attached to the
+CFAM's LBUS. Engine implementations should subclass the LBusDevice and set the
+'config' member of LBusDeviceClass to match the engine's type.
+
+CFAM designs offer a lot of flexibility, for instance it is possible for a
+CFAM to be simultaneously driven from multiple FSI links. The modeling is not
+so complete; it's assumed that each CFAM is attached to a single FSI slave (as
+a consequence the CFAM subclasses the FSI slave).
+
+As for FSI, its symbols and wire-protocol are not modelled at all. This is not
+necessary to get FSI off the ground thanks to the mapping of the CFAM address
+space onto the OPB address space - the models follow this directly and map the
+CFAM memory region into the OPB's memory region.
+
+QEMU files related to FSI interface:
+ - ``hw/fsi/aspeed-apb2opb.c``
+ - ``include/hw/fsi/aspeed-apb2opb.h``
+ - ``hw/fsi/opb.c``
+ - ``include/hw/fsi/opb.h``
+ - ``hw/fsi/fsi.c``
+ - ``include/hw/fsi/fsi.h``
+ - ``hw/fsi/fsi-master.c``
+ - ``include/hw/fsi/fsi-master.h``
+ - ``hw/fsi/fsi-slave.c``
+ - ``include/hw/fsi/fsi-slave.h``
+ - ``hw/fsi/cfam.c``
+ - ``include/hw/fsi/cfam.h``
+ - ``hw/fsi/engine-scratchpad.c``
+ - ``include/hw/fsi/engine-scratchpad.h``
+ - ``include/hw/fsi/lbus.h``
+
+The following commands start the rainier machine with built-in FSI model.
+There are no model specific arguments.
+
+.. code-block:: console
+
+  qemu-system-arm -M rainier-bmc -nographic \
+  -kernel fitImage-linux.bin \
+  -dtb aspeed-bmc-ibm-rainier.dtb \
+  -initrd obmc-phosphor-initramfs.rootfs.cpio.xz \
+  -drive file=obmc-phosphor-image.rootfs.wic.qcow2,if=sd,index=2 \
+  -append "rootwait console=ttyS4,115200n8 root=PARTLABEL=rofs-a"
+
+The implementation appears as following in the qemu device tree:
+
+.. code-block:: console
+
+  (qemu) info qtree
+  bus: main-system-bus
+type System
+...
+dev: aspeed.apb2opb, id ""
+  gpio-out "sysbus-

<    2   3   4   5   6   7   8   9   10   11   >