Re: [PATCH] ppc/xive: Fix uint32_t overflow

2023-09-13 Thread Frederic Barrat




On 13/09/2023 07:56, Cédric Le Goater wrote:

As reported by Coverity, "idx << xive->pc_shift" is evaluated using
32-bit arithmetic, and then used in a context expecting a "uint64_t".
Add a uint64_t cast.

Fixes: Coverity CID 1519049
Fixes: b68147b7a5bf ("ppc/xive: Add support for the PC MMIOs")
Signed-off-by: Cédric Le Goater 
---



Reviewed-by: Frederic Barrat 



  hw/intc/pnv_xive.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/intc/pnv_xive.c b/hw/intc/pnv_xive.c
index 9b10e905195a..a36b3bf08c92 100644
--- a/hw/intc/pnv_xive.c
+++ b/hw/intc/pnv_xive.c
@@ -210,7 +210,7 @@ static uint64_t pnv_xive_vst_addr_remote(PnvXive *xive, 
uint32_t type,
  return 0;
  }
  
-remote_addr |= idx << xive->pc_shift;

+remote_addr |= ((uint64_t) idx) << xive->pc_shift;
  
  vst_addr = address_space_ldq_be(_space_memory, remote_addr,

  MEMTXATTRS_UNSPECIFIED, );




Re: [PATCH 4/4] ppc/xive: Add support for the PC MMIOs

2023-08-31 Thread Frederic Barrat




On 29/08/2023 16:32, Cédric Le Goater wrote:

The XIVE interrupt contoller maintains various fields on interrupt
targets in a structure called NVT. Each unit has a NVT cache, backed
by RAM.

When the NVT structure is not local (in RAM) to the chip, the XIVE
interrupt controller forwards the memory operation to the owning chip
using the PC MMIO region configured for this purpose. QEMU does not
need to be so precise since software shouldn't perform any of these
operations. The model implementation is simplified to return the RAM
address of the NVT structure which is then used by pnv_xive_vst_write
or read to perform the operation in RAM.

Remove the last use of pnv_xive_get_remote().

Signed-off-by: Cédric Le Goater 
-



Nice cleanup

Reviewed-by: Frederic Barrat 

  Fred



  hw/intc/pnv_xive.c | 84 ++
  1 file changed, 48 insertions(+), 36 deletions(-)

diff --git a/hw/intc/pnv_xive.c b/hw/intc/pnv_xive.c
index aae5cb6f607b..9b10e905195a 100644
--- a/hw/intc/pnv_xive.c
+++ b/hw/intc/pnv_xive.c
@@ -84,28 +84,6 @@ static uint8_t pnv_xive_block_id(PnvXive *xive)
  return blk;
  }
  
-/*

- * Remote access to controllers. HW uses MMIOs. For now, a simple scan
- * of the chips is good enough.
- *
- * TODO: Block scope support
- */
-static PnvXive *pnv_xive_get_remote(uint8_t blk)
-{
-PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine());
-int i;
-
-for (i = 0; i < pnv->num_chips; i++) {
-Pnv9Chip *chip9 = PNV9_CHIP(pnv->chips[i]);
-PnvXive *xive = >xive;
-
-if (pnv_xive_block_id(xive) == blk) {
-return xive;
-}
-}
-return NULL;
-}
-
  /*
   * VST accessors for SBE, EAT, ENDT, NVT
   *
@@ -209,6 +187,42 @@ static uint64_t pnv_xive_vst_addr_indirect(PnvXive *xive, 
uint32_t type,
  return pnv_xive_vst_addr_direct(xive, type, vsd, (idx % vst_per_page));
  }
  
+/*

+ * This is a simplified model of operation forwarding on a remote IC.
+ *
+ * A PC MMIO address is built to identify the NVT structure. The load
+ * on the remote IC will return the address of the structure in RAM,
+ * which will then be used by pnv_xive_vst_write/read to perform the
+ * RAM operation.
+ */
+static uint64_t pnv_xive_vst_addr_remote(PnvXive *xive, uint32_t type,
+ uint64_t vsd, uint8_t blk,
+ uint32_t idx)
+{
+const XiveVstInfo *info = _infos[type];
+uint64_t remote_addr = vsd & VSD_ADDRESS_MASK;
+uint64_t vst_addr;
+MemTxResult result;
+
+if (type != VST_TSEL_VPDT) {
+xive_error(xive, "VST: invalid access on remote VST %s %x/%x !?",
+   info->name, blk, idx);
+return 0;
+}
+
+remote_addr |= idx << xive->pc_shift;
+
+vst_addr = address_space_ldq_be(_space_memory, remote_addr,
+MEMTXATTRS_UNSPECIFIED, );
+if (result != MEMTX_OK) {
+xive_error(xive, "VST: read failed at @0x%"  HWADDR_PRIx
+   " for NVT %x/%x\n", remote_addr, blk, idx);
+return 0;
+}
+
+return vst_addr;
+}
+
  static uint64_t pnv_xive_vst_addr(PnvXive *xive, uint32_t type, uint8_t blk,
uint32_t idx)
  {
@@ -225,14 +239,7 @@ static uint64_t pnv_xive_vst_addr(PnvXive *xive, uint32_t 
type, uint8_t blk,
  
  /* Remote VST access */

  if (GETFIELD(VSD_MODE, vsd) == VSD_MODE_FORWARD) {
-if (type != VST_TSEL_VPDT) {
-xive_error(xive, "VST: invalid access on remote VST %s %x/%x !?",
-   info->name, blk, idx);
-return 0;
-}
-xive = pnv_xive_get_remote(blk);
-
-return xive ? pnv_xive_vst_addr(xive, type, blk, idx) : 0;
+return pnv_xive_vst_addr_remote(xive, type, vsd, blk, idx);
  }
  
  if (VSD_INDIRECT & vsd) {

@@ -1785,16 +1792,20 @@ static const MemoryRegionOps pnv_xive_vc_ops = {
  };
  
  /*

- * Presenter Controller MMIO region. The Virtualization Controller
- * updates the IPB in the NVT table when required. Not modeled.
+ * Presenter Controller MMIO region. Points to the NVT sets.
+ *
+ * HW implements all possible mem ops to the underlying NVT structure
+ * but QEMU does not need to be so precise. The model implementation
+ * simply returns the RAM address of the NVT structure which is then
+ * used by pnv_xive_vst_write/read to perform the RAM operation.
   */
-static uint64_t pnv_xive_pc_read(void *opaque, hwaddr addr,
- unsigned size)
+static uint64_t pnv_xive_pc_read(void *opaque, hwaddr offset, unsigned size)
  {
  PnvXive *xive = PNV_XIVE(opaque);
+uint32_t nvt_idx = offset >> xive->pc_shift;
+uint8_t blk = pnv_xive_block_id(xive); /* TODO: VDT -> block xlate */
  
-xive_error(xive, "PC: invalid read @%"HWADDR_PRIx, addr);

-return -1;
+re

Re: [PATCH 3/4] ppc/xive: Handle END triggers between chips with MMIOs

2023-08-31 Thread Frederic Barrat




On 29/08/2023 16:32, Cédric Le Goater wrote:

The notify page of the interrupt controller can either be used to
receive trigger events from the HW controllers (PHB, PSI) or to
reroute interrupts between Interrupt Controllers. In which case, the
VSD table is used to determine the address of the notify page of the
remote IC and the store data is forwarded.

Today, our model grabs the remote VSD (EAS, END, NVT) address using
pnv_xive_get_remote() helper. Be more precise and implement remote END
triggers using a store on the remote IC notify page.

We still have a shortcut in the model for the NVT accesses which we
will address later.

Signed-off-by: Cédric Le Goater 
---



Reviewed-by: Frederic Barrat 

  Fred



  hw/intc/pnv_xive_regs.h |  1 +
  hw/intc/pnv_xive.c  | 69 +++--
  2 files changed, 68 insertions(+), 2 deletions(-)

diff --git a/hw/intc/pnv_xive_regs.h b/hw/intc/pnv_xive_regs.h
index c78f030c0260..793847638bce 100644
--- a/hw/intc/pnv_xive_regs.h
+++ b/hw/intc/pnv_xive_regs.h
@@ -228,6 +228,7 @@
   *   VSD and is only meant to be used in indirect mode !
   */
  #define VSD_MODEPPC_BITMASK(0, 1)
+#define  VSD_MODE_INVALID   0
  #define  VSD_MODE_SHARED1
  #define  VSD_MODE_EXCLUSIVE 2
  #define  VSD_MODE_FORWARD   3
diff --git a/hw/intc/pnv_xive.c b/hw/intc/pnv_xive.c
index b2bafd61b157..aae5cb6f607b 100644
--- a/hw/intc/pnv_xive.c
+++ b/hw/intc/pnv_xive.c
@@ -225,6 +225,11 @@ static uint64_t pnv_xive_vst_addr(PnvXive *xive, uint32_t 
type, uint8_t blk,
  
  /* Remote VST access */

  if (GETFIELD(VSD_MODE, vsd) == VSD_MODE_FORWARD) {
+if (type != VST_TSEL_VPDT) {
+xive_error(xive, "VST: invalid access on remote VST %s %x/%x !?",
+   info->name, blk, idx);
+return 0;
+}
  xive = pnv_xive_get_remote(blk);
  
  return xive ? pnv_xive_vst_addr(xive, type, blk, idx) : 0;

@@ -294,12 +299,26 @@ static int pnv_xive_vst_write(PnvXive *xive, uint32_t 
type, uint8_t blk,
  static int pnv_xive_get_end(XiveRouter *xrtr, uint8_t blk, uint32_t idx,
  XiveEND *end)
  {
+PnvXive *xive = PNV_XIVE(xrtr);
+
+if (pnv_xive_block_id(xive) != blk) {
+xive_error(xive, "VST: END %x/%x is remote !?", blk, idx);
+return -1;
+}
+
  return pnv_xive_vst_read(PNV_XIVE(xrtr), VST_TSEL_EQDT, blk, idx, end);
  }
  
  static int pnv_xive_write_end(XiveRouter *xrtr, uint8_t blk, uint32_t idx,

XiveEND *end, uint8_t word_number)
  {
+PnvXive *xive = PNV_XIVE(xrtr);
+
+if (pnv_xive_block_id(xive) != blk) {
+xive_error(xive, "VST: END %x/%x is remote !?", blk, idx);
+return -1;
+}
+
  return pnv_xive_vst_write(PNV_XIVE(xrtr), VST_TSEL_EQDT, blk, idx, end,
word_number);
  }
@@ -1368,6 +1387,50 @@ static const MemoryRegionOps pnv_xive_ic_reg_ops = {
  #define PNV_XIVE_SYNC_PUSH  0xf00 /* Sync push context */
  #define PNV_XIVE_SYNC_VPC   0xf80 /* Sync remove VPC store */
  
+static void pnv_xive_end_notify(XiveRouter *xrtr, XiveEAS *eas)

+{
+PnvXive *xive = PNV_XIVE(xrtr);
+uint8_t end_blk = xive_get_field64(EAS_END_BLOCK, eas->w);
+uint32_t end_idx = xive_get_field64(EAS_END_INDEX, eas->w);
+uint32_t end_data = xive_get_field64(EAS_END_DATA, eas->w);
+uint64_t end_vsd = xive->vsds[VST_TSEL_EQDT][end_blk];
+
+switch (GETFIELD(VSD_MODE, end_vsd)) {
+case VSD_MODE_EXCLUSIVE:
+/* Perform the END notification on the local IC. */
+xive_router_end_notify(xrtr, eas);
+break;
+
+case VSD_MODE_FORWARD: {
+MemTxResult result;
+uint64_t notif_port = end_vsd & VSD_ADDRESS_MASK;
+uint64_t data = XIVE_TRIGGER_END | XIVE_TRIGGER_PQ |
+be64_to_cpu(eas->w);
+
+/* Forward the store on the remote IC notify page. */
+address_space_stq_be(_space_memory, notif_port, data,
+ MEMTXATTRS_UNSPECIFIED, );
+if (result != MEMTX_OK) {
+xive_error(xive, "IC: Forward notif END %x/%x [%x] failed @%"
+   HWADDR_PRIx, end_blk, end_idx, end_data, notif_port);
+return;
+}
+break;
+}
+
+case VSD_MODE_INVALID:
+default:
+/* Set FIR */
+xive_error(xive, "IC: Invalid END VSD for block %x", end_blk);
+return;
+}
+}
+
+/*
+ * The notify page can either be used to receive trigger events from
+ * the HW controllers (PHB, PSI) or to reroute interrupts between
+ * Interrupt controllers.
+ */
  static void pnv_xive_ic_hw_trigger(PnvXive *xive, hwaddr addr, uint64_t val)
  {
  uint8_t blk;
@@ -1376,8 +1439,8 @@ static void pnv_xive_ic_hw_trigger(PnvXive *xive, hwaddr 
addr, uint64_t val)
  trace_pnv_xive_ic_hw_trigger(addr, val

Re: [PATCH 2/4] ppc/xive: Introduce a new XiveRouter end_notify() handler

2023-08-31 Thread Frederic Barrat




On 29/08/2023 16:32, Cédric Le Goater wrote:

It will help us model the END triggers on the PowerNV machine, which
can be rerouted to another interrupt controller.

Signed-off-by: Cédric Le Goater 
---





diff --git a/hw/intc/xive.c b/hw/intc/xive.c
index 56670b2cac6e..df3ee0496fe7 100644
--- a/hw/intc/xive.c
+++ b/hw/intc/xive.c
@@ -1518,6 +1518,13 @@ static void xive_router_realize(DeviceState *dev, Error 
**errp)
  assert(xrtr->xfb);
  }
  
+static void xive_router_end_notify_handler(XiveRouter *xrtr, XiveEAS *eas)

+{
+XiveRouterClass *xrc = XIVE_ROUTER_GET_CLASS(xrtr);
+
+return xrc->end_notify(xrtr, eas);
+}
+
  /*
   * Encode the HW CAM line in the block group mode format :
   *
@@ -1664,8 +1671,7 @@ static bool xive_router_end_es_notify(XiveRouter *xrtr, 
uint8_t end_blk,
   * another chip. We don't model the PowerBus but the END trigger
   * message has the same parameters than in the function below.
   */
-static void xive_router_end_notify(XiveRouter *xrtr, uint8_t end_blk,
-   uint32_t end_idx, uint32_t end_data)
+void xive_router_end_notify(XiveRouter *xrtr, XiveEAS *eas)
  {
  XiveEND end;
  uint8_t priority;
@@ -1675,6 +1681,10 @@ static void xive_router_end_notify(XiveRouter *xrtr, 
uint8_t end_blk,
  XiveNVT nvt;
  bool found;
  
+uint8_t end_blk = xive_get_field64(EAS_END_BLOCK, eas->w);

+uint32_t end_idx = xive_get_field64(EAS_END_INDEX, eas->w);
+uint32_t end_data = xive_get_field64(EAS_END_DATA,  eas->w);
+
  /* END cache lookup */
  if (xive_router_get_end(xrtr, end_blk, end_idx, )) {
  qemu_log_mask(LOG_GUEST_ERROR, "XIVE: No END %x/%x\n", end_blk,
@@ -1817,10 +1827,7 @@ do_escalation:
  /*
   * The END trigger becomes an Escalation trigger
   */
-xive_router_end_notify(xrtr,
-   xive_get_field32(END_W4_ESC_END_BLOCK, end.w4),
-   xive_get_field32(END_W4_ESC_END_INDEX, end.w4),
-   xive_get_field32(END_W5_ESC_END_DATA,  end.w5));
+xive_router_end_notify_handler(xrtr, (XiveEAS *) );



I didn't like the cast, but I can see why you're doing it this way. We 
should be fine as long as the notify handler is not testing the validity 
bit of the EAS structure.


Reviewed-by: Frederic Barrat 

  Fred



  }
  
  void xive_router_notify(XiveNotifier *xn, uint32_t lisn, bool pq_checked)

@@ -1871,10 +1878,7 @@ void xive_router_notify(XiveNotifier *xn, uint32_t lisn, 
bool pq_checked)
  /*
   * The event trigger becomes an END trigger
   */
-xive_router_end_notify(xrtr,
-   xive_get_field64(EAS_END_BLOCK, eas.w),
-   xive_get_field64(EAS_END_INDEX, eas.w),
-   xive_get_field64(EAS_END_DATA,  eas.w));
+xive_router_end_notify_handler(xrtr, );
  }
  
  static Property xive_router_properties[] = {

@@ -1887,12 +1891,16 @@ static void xive_router_class_init(ObjectClass *klass, 
void *data)
  {
  DeviceClass *dc = DEVICE_CLASS(klass);
  XiveNotifierClass *xnc = XIVE_NOTIFIER_CLASS(klass);
+XiveRouterClass *xrc = XIVE_ROUTER_CLASS(klass);
  
  dc->desc= "XIVE Router Engine";

  device_class_set_props(dc, xive_router_properties);
  /* Parent is SysBusDeviceClass. No need to call its realize hook */
  dc->realize = xive_router_realize;
  xnc->notify = xive_router_notify;
+
+/* By default, the router handles END triggers locally */
+xrc->end_notify = xive_router_end_notify;
  }
  
  static const TypeInfo xive_router_info = {




Re: [PATCH 1/4] ppc/xive: Use address_space routines to access the machine RAM

2023-08-31 Thread Frederic Barrat




On 29/08/2023 16:32, Cédric Le Goater wrote:

to log an error in case of bad configuration of the XIVE tables by the FW.

Signed-off-by: Cédric Le Goater 
---
  hw/intc/pnv_xive.c  | 27 +++
  hw/intc/pnv_xive2.c | 27 +++
  2 files changed, 46 insertions(+), 8 deletions(-)

diff --git a/hw/intc/pnv_xive.c b/hw/intc/pnv_xive.c
index e536b3ec26e5..b2bafd61b157 100644
--- a/hw/intc/pnv_xive.c
+++ b/hw/intc/pnv_xive.c
@@ -242,12 +242,20 @@ static int pnv_xive_vst_read(PnvXive *xive, uint32_t 
type, uint8_t blk,
  {
  const XiveVstInfo *info = _infos[type];
  uint64_t addr = pnv_xive_vst_addr(xive, type, blk, idx);
+MemTxResult result;
  
  if (!addr) {

  return -1;
  }
  
-cpu_physical_memory_read(addr, data, info->size);

+result = address_space_read(_space_memory, addr,
+MEMTXATTRS_UNSPECIFIED, data,
+info->size);



I had been wondering which is the "right" API to update the guest 
memory. Since the cpu_physical_memory_* family ends up calling its 
address_space_* equivalent, I'm guessing the point of the change is 
really to catch any error and remove any potential ambiguity about the 
address space?


In any case,
Reviewed-by: Frederic Barrat 

  Fred



+if (result != MEMTX_OK) {
+xive_error(xive, "VST: read failed at @0x%" HWADDR_PRIx
+   " for VST %s %x/%x\n", addr, info->name, blk, idx);
+return -1;
+}
  return 0;
  }
  
@@ -258,16 +266,27 @@ static int pnv_xive_vst_write(PnvXive *xive, uint32_t type, uint8_t blk,

  {
  const XiveVstInfo *info = _infos[type];
  uint64_t addr = pnv_xive_vst_addr(xive, type, blk, idx);
+MemTxResult result;
  
  if (!addr) {

  return -1;
  }
  
  if (word_number == XIVE_VST_WORD_ALL) {

-cpu_physical_memory_write(addr, data, info->size);
+result = address_space_write(_space_memory, addr,
+ MEMTXATTRS_UNSPECIFIED, data,
+ info->size);
  } else {
-cpu_physical_memory_write(addr + word_number * 4,
-  data + word_number * 4, 4);
+result = address_space_write(_space_memory,
+ addr + word_number * 4,
+ MEMTXATTRS_UNSPECIFIED,
+ data + word_number * 4, 4);
+}
+
+if (result != MEMTX_OK) {
+xive_error(xive, "VST: write failed at @0x%" HWADDR_PRIx
+"for VST %s %x/%x\n", addr, info->name, blk, idx);
+return -1;
  }
  return 0;
  }
diff --git a/hw/intc/pnv_xive2.c b/hw/intc/pnv_xive2.c
index bbb44a533cff..4b8d0a5d8120 100644
--- a/hw/intc/pnv_xive2.c
+++ b/hw/intc/pnv_xive2.c
@@ -240,12 +240,20 @@ static int pnv_xive2_vst_read(PnvXive2 *xive, uint32_t 
type, uint8_t blk,
  {
  const XiveVstInfo *info = _infos[type];
  uint64_t addr = pnv_xive2_vst_addr(xive, type, blk, idx);
+MemTxResult result;
  
  if (!addr) {

  return -1;
  }
  
-cpu_physical_memory_read(addr, data, info->size);

+result = address_space_read(_space_memory, addr,
+MEMTXATTRS_UNSPECIFIED, data,
+info->size);
+if (result != MEMTX_OK) {
+xive2_error(xive, "VST: read failed at @0x%" HWADDR_PRIx
+   " for VST %s %x/%x\n", addr, info->name, blk, idx);
+return -1;
+}
  return 0;
  }
  
@@ -256,16 +264,27 @@ static int pnv_xive2_vst_write(PnvXive2 *xive, uint32_t type, uint8_t blk,

  {
  const XiveVstInfo *info = _infos[type];
  uint64_t addr = pnv_xive2_vst_addr(xive, type, blk, idx);
+MemTxResult result;
  
  if (!addr) {

  return -1;
  }
  
  if (word_number == XIVE_VST_WORD_ALL) {

-cpu_physical_memory_write(addr, data, info->size);
+result = address_space_write(_space_memory, addr,
+ MEMTXATTRS_UNSPECIFIED, data,
+ info->size);
  } else {
-cpu_physical_memory_write(addr + word_number * 4,
-  data + word_number * 4, 4);
+result = address_space_write(_space_memory,
+ addr + word_number * 4,
+ MEMTXATTRS_UNSPECIFIED,
+ data + word_number * 4, 4);
+}
+
+if (result != MEMTX_OK) {
+xive2_error(xive, "VST: write failed at @0x%" HWADDR_PRIx
+   "for VST %s %x/%x\n", addr, info->name, blk, idx);
+return -1;
  }
  return 0;
  }




Re: [PATCH for-8.2 2/3] pnv/lpc: Hook up xscom region for P9/P10

2023-08-09 Thread Frederic Barrat

Hello Joel,

So we're re-using the same xscom ops as on P8. A quick look at the 
definition of those 4 registers on P8 (0xb0020) and on P9/P10 
(0x00090040) seem to show they are not the same though. Am i missing 
something?


  Fred


On 08/08/2023 10:34, Joel Stanley wrote:

 From P9 on the LPC bus is memory mapped. However the xscom access still
is possible, so add it too.

Signed-off-by: Joel Stanley 
---
  include/hw/ppc/pnv_xscom.h | 6 ++
  hw/ppc/pnv.c   | 4 
  hw/ppc/pnv_lpc.c   | 6 ++
  3 files changed, 16 insertions(+)

diff --git a/include/hw/ppc/pnv_xscom.h b/include/hw/ppc/pnv_xscom.h
index 9bc64635471e..42601bdf419d 100644
--- a/include/hw/ppc/pnv_xscom.h
+++ b/include/hw/ppc/pnv_xscom.h
@@ -96,6 +96,9 @@ struct PnvXScomInterfaceClass {
  #define PNV9_XSCOM_SBE_CTRL_BASE  0x00050008
  #define PNV9_XSCOM_SBE_CTRL_SIZE  0x1
  
+#define PNV9_XSCOM_LPC_BASE   0x00090040

+#define PNV9_XSCOM_LPC_SIZE   PNV_XSCOM_LPC_SIZE
+
  #define PNV9_XSCOM_SBE_MBOX_BASE  0x000D0050
  #define PNV9_XSCOM_SBE_MBOX_SIZE  0x16
  
@@ -155,6 +158,9 @@ struct PnvXScomInterfaceClass {

  #define PNV10_XSCOM_SBE_CTRL_BASE  PNV9_XSCOM_SBE_CTRL_BASE
  #define PNV10_XSCOM_SBE_CTRL_SIZE  PNV9_XSCOM_SBE_CTRL_SIZE
  
+#define PNV10_XSCOM_LPC_BASE   PNV9_XSCOM_LPC_BASE

+#define PNV10_XSCOM_LPC_SIZE   PNV9_XSCOM_LPC_SIZE
+
  #define PNV10_XSCOM_SBE_MBOX_BASE  PNV9_XSCOM_SBE_MBOX_BASE
  #define PNV10_XSCOM_SBE_MBOX_SIZE  PNV9_XSCOM_SBE_MBOX_SIZE
  
diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c

index afdaa25c2b26..a5db655b41b6 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -1566,6 +1566,8 @@ static void pnv_chip_power9_realize(DeviceState *dev, 
Error **errp)
  }
  memory_region_add_subregion(get_system_memory(), PNV9_LPCM_BASE(chip),
  >lpc.mmio_regs);
+pnv_xscom_add_subregion(chip, PNV9_XSCOM_LPC_BASE,
+>lpc.xscom_regs);
  
  chip->fw_mr = >lpc.isa_fw;

  chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0",
@@ -1785,6 +1787,8 @@ static void pnv_chip_power10_realize(DeviceState *dev, 
Error **errp)
  }
  memory_region_add_subregion(get_system_memory(), PNV10_LPCM_BASE(chip),
  >lpc.mmio_regs);
+pnv_xscom_add_subregion(chip, PNV10_XSCOM_LPC_BASE,
+>lpc.xscom_regs);
  
  chip->fw_mr = >lpc.isa_fw;

  chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0",
diff --git a/hw/ppc/pnv_lpc.c b/hw/ppc/pnv_lpc.c
index caf5e10a5f96..6c6a3134087f 100644
--- a/hw/ppc/pnv_lpc.c
+++ b/hw/ppc/pnv_lpc.c
@@ -666,6 +666,12 @@ static void pnv_lpc_power9_realize(DeviceState *dev, Error 
**errp)
  /* P9 uses a MMIO region */
  memory_region_init_io(>mmio_regs, OBJECT(lpc), _lpc_mmio_ops,
lpc, "lpcm", PNV9_LPCM_SIZE);
+
+/* but the XSCOM region still exists */
+pnv_xscom_region_init(>xscom_regs, OBJECT(lpc),
+  _lpc_xscom_ops, lpc, "xscom-lpc",
+  PNV_XSCOM_LPC_SIZE);
+
  }
  
  static void pnv_lpc_power9_class_init(ObjectClass *klass, void *data)




[PATCH] pnv/xive: Print CPU target in all TIMA traces

2023-07-05 Thread Frederic Barrat
Add the CPU target in the trace when reading/writing the TIMA
space. It was already done for other TIMA ops (notify, accept, ...),
only missing for those 2. Useful for debug and even more now that we
experiment with SMT.

Signed-off-by: Frederic Barrat 
---
 hw/intc/trace-events | 4 ++--
 hw/intc/xive.c   | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/hw/intc/trace-events b/hw/intc/trace-events
index 5c6094c457..36ff71f947 100644
--- a/hw/intc/trace-events
+++ b/hw/intc/trace-events
@@ -265,8 +265,8 @@ xive_source_esb_read(uint64_t addr, uint32_t srcno, 
uint64_t value) "@0x%"PRIx64
 xive_source_esb_write(uint64_t addr, uint32_t srcno, uint64_t value) 
"@0x%"PRIx64" IRQ 0x%x val=0x%"PRIx64
 xive_router_end_notify(uint8_t end_blk, uint32_t end_idx, uint32_t end_data) 
"END 0x%02x/0x%04x -> enqueue 0x%08x"
 xive_router_end_escalate(uint8_t end_blk, uint32_t end_idx, uint8_t esc_blk, 
uint32_t esc_idx, uint32_t end_data) "END 0x%02x/0x%04x -> escalate END 
0x%02x/0x%04x data 0x%08x"
-xive_tctx_tm_write(uint64_t offset, unsigned int size, uint64_t value) 
"@0x%"PRIx64" sz=%d val=0x%" PRIx64
-xive_tctx_tm_read(uint64_t offset, unsigned int size, uint64_t value) 
"@0x%"PRIx64" sz=%d val=0x%" PRIx64
+xive_tctx_tm_write(uint32_t index, uint64_t offset, unsigned int size, 
uint64_t value) "target=%d @0x%"PRIx64" sz=%d val=0x%" PRIx64
+xive_tctx_tm_read(uint32_t index, uint64_t offset, unsigned int size, uint64_t 
value) "target=%d @0x%"PRIx64" sz=%d val=0x%" PRIx64
 xive_presenter_notify(uint8_t nvt_blk, uint32_t nvt_idx, uint8_t ring) "found 
NVT 0x%x/0x%x ring=0x%x"
 xive_end_source_read(uint8_t end_blk, uint32_t end_idx, uint64_t addr) "END 
0x%x/0x%x @0x%"PRIx64
 
diff --git a/hw/intc/xive.c b/hw/intc/xive.c
index c014e961a4..56670b2cac 100644
--- a/hw/intc/xive.c
+++ b/hw/intc/xive.c
@@ -566,7 +566,7 @@ void xive_tctx_tm_write(XivePresenter *xptr, XiveTCTX 
*tctx, hwaddr offset,
 {
 const XiveTmOp *xto;
 
-trace_xive_tctx_tm_write(offset, size, value);
+trace_xive_tctx_tm_write(tctx->cs->cpu_index, offset, size, value);
 
 /*
  * TODO: check V bit in Q[0-3]W2
@@ -639,7 +639,7 @@ uint64_t xive_tctx_tm_read(XivePresenter *xptr, XiveTCTX 
*tctx, hwaddr offset,
  */
 ret = xive_tm_raw_read(tctx, offset, size);
 out:
-trace_xive_tctx_tm_read(offset, size, ret);
+trace_xive_tctx_tm_read(tctx->cs->cpu_index, offset, size, ret);
 return ret;
 }
 
-- 
2.41.0




[PATCH] pnv/xive2: Always pass a presenter object when accessing the TIMA

2023-07-05 Thread Frederic Barrat
The low-level functions to access the TIMA take a presenter object as
a first argument. When accessing the TIMA from the IC BAR,
i.e. indirect calls, we currently pass a NULL pointer for the
presenter argument. While it appears ok with the current usage, it's
dangerous. And it's pretty easy to figure out the presenter in that
context, so this patch fixes it.

Signed-off-by: Frederic Barrat 
---
 hw/intc/pnv_xive2.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/hw/intc/pnv_xive2.c b/hw/intc/pnv_xive2.c
index 82fcd3ea22..bbb44a533c 100644
--- a/hw/intc/pnv_xive2.c
+++ b/hw/intc/pnv_xive2.c
@@ -1624,6 +1624,7 @@ static uint64_t pnv_xive2_ic_tm_indirect_read(void 
*opaque, hwaddr offset,
   unsigned size)
 {
 PnvXive2 *xive = PNV_XIVE2(opaque);
+XivePresenter *xptr = XIVE_PRESENTER(xive);
 hwaddr hw_page_offset;
 uint32_t pir;
 XiveTCTX *tctx;
@@ -1633,7 +1634,7 @@ static uint64_t pnv_xive2_ic_tm_indirect_read(void 
*opaque, hwaddr offset,
 hw_page_offset = pnv_xive2_ic_tm_get_hw_page_offset(xive, offset);
 tctx = pnv_xive2_get_indirect_tctx(xive, pir);
 if (tctx) {
-val = xive_tctx_tm_read(NULL, tctx, hw_page_offset, size);
+val = xive_tctx_tm_read(xptr, tctx, hw_page_offset, size);
 }
 
 return val;
@@ -1643,6 +1644,7 @@ static void pnv_xive2_ic_tm_indirect_write(void *opaque, 
hwaddr offset,
uint64_t val, unsigned size)
 {
 PnvXive2 *xive = PNV_XIVE2(opaque);
+XivePresenter *xptr = XIVE_PRESENTER(xive);
 hwaddr hw_page_offset;
 uint32_t pir;
 XiveTCTX *tctx;
@@ -1651,7 +1653,7 @@ static void pnv_xive2_ic_tm_indirect_write(void *opaque, 
hwaddr offset,
 hw_page_offset = pnv_xive2_ic_tm_get_hw_page_offset(xive, offset);
 tctx = pnv_xive2_get_indirect_tctx(xive, pir);
 if (tctx) {
-xive_tctx_tm_write(NULL, tctx, hw_page_offset, val, size);
+xive_tctx_tm_write(xptr, tctx, hw_page_offset, val, size);
 }
 }
 
-- 
2.41.0




Re: [RFC PATCH 0/4] ppc: Improve multisocket support

2023-07-04 Thread Frederic Barrat




On 04/07/2023 15:49, Cédric Le Goater wrote:

Hello,

Here are changes improving multisocket support of the XIVE models
(POWER9 only). When a source has an END target on another chip, the
XIVE IC will use an MMIO store to forward the notification to the
remote chip. The long term plan is to get rid of pnv_xive_get_remote()
whic is a modeling shortcut. I have had them for while, they compile,
they seem to still work but this is not for merge yet. If someone
could take over, that would be nice.

The best way to test is to start a 2 sockets * 1 cpu system with devices
attached to the PCI buses of chip 0 and to offline CPU 0. All sources
should be configured to be served by CPU 1 on socket 1 and trigger
notifications on chip 0 should be forwarded to chip 1.

Last patch adds support for degenerative interrupts. This is used by
the lowest level FW of POWER systems. Difficult to test.




Thanks for the series! My crystal ball tells me the PC MMIO patch will 
come handy soon (to be adapted for P10 and groups). And the remote 
routing looks pretty interesting too.

The last patch (LSI) may rot a bit longer though :)

  Fred



Thanks,

C.

Cédric Le Goater (4):
   ppc/xive: introduce a new XiveRouter end_notify() handler
   ppc/pnv: handle END triggers between chips with MMIOs
   ppc/pnv: add support for the PC MMIOs
   ppc/pnv: Add support for degenerative interrupts (POWER LSI)

  hw/intc/pnv_xive_regs.h   |   1 +
  include/hw/ppc/pnv_xive.h |  15 +++
  include/hw/ppc/xive.h |   3 +
  hw/intc/pnv_xive.c| 262 +++---
  hw/intc/xive.c|  50 ++--
  5 files changed, 278 insertions(+), 53 deletions(-)





[PATCH] pnv/xive: Allow mmio operations of any size on the ESB CI pages

2023-07-04 Thread Frederic Barrat
We currently only allow 64-bit operations on the ESB CI pages. There's
no real reason for that limitation, skiboot/linux didn't need
more. However the hardware supports any size, so this patch relaxes
that restriction. It impacts both the ESB pages for "normal"
interrupts as well as the ESB pages for escalation interrupts defined
for the ENDs.

Signed-off-by: Frederic Barrat 
---

This should wrap-up the cleanup about mmio size for the xive BARs. The
NVPG and NVC BAR accesses should also be relaxed but we don't really
implement them, any load/store currently fails. Something to address
when/if we implement them.

 hw/intc/xive.c  | 8 
 hw/intc/xive2.c | 4 ++--
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/hw/intc/xive.c b/hw/intc/xive.c
index f60c878345..c014e961a4 100644
--- a/hw/intc/xive.c
+++ b/hw/intc/xive.c
@@ -1175,11 +1175,11 @@ static const MemoryRegionOps xive_source_esb_ops = {
 .write = xive_source_esb_write,
 .endianness = DEVICE_BIG_ENDIAN,
 .valid = {
-.min_access_size = 8,
+.min_access_size = 1,
 .max_access_size = 8,
 },
 .impl = {
-.min_access_size = 8,
+.min_access_size = 1,
 .max_access_size = 8,
 },
 };
@@ -2006,11 +2006,11 @@ static const MemoryRegionOps xive_end_source_ops = {
 .write = xive_end_source_write,
 .endianness = DEVICE_BIG_ENDIAN,
 .valid = {
-.min_access_size = 8,
+.min_access_size = 1,
 .max_access_size = 8,
 },
 .impl = {
-.min_access_size = 8,
+.min_access_size = 1,
 .max_access_size = 8,
 },
 };
diff --git a/hw/intc/xive2.c b/hw/intc/xive2.c
index 4d9ff41956..c37ef25d44 100644
--- a/hw/intc/xive2.c
+++ b/hw/intc/xive2.c
@@ -954,11 +954,11 @@ static const MemoryRegionOps xive2_end_source_ops = {
 .write = xive2_end_source_write,
 .endianness = DEVICE_BIG_ENDIAN,
 .valid = {
-.min_access_size = 8,
+.min_access_size = 1,
 .max_access_size = 8,
 },
 .impl = {
-.min_access_size = 8,
+.min_access_size = 1,
 .max_access_size = 8,
 },
 };
-- 
2.41.0




Re: [PATCH v2 4/5] ppc/pnv: Add P10 core xscom model

2023-07-04 Thread Frederic Barrat




On 04/07/2023 07:42, Joel Stanley wrote:

Like the quad xscoms, add a core model for P10 to allow future
differentiation from P9.

Signed-off-by: Joel Stanley 
---



Reviewed-by: Frederic Barrat 

  Fred



  hw/ppc/pnv_core.c | 44 ++--
  1 file changed, 42 insertions(+), 2 deletions(-)

diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c
index e4df435b15e9..1eec28c88c41 100644
--- a/hw/ppc/pnv_core.c
+++ b/hw/ppc/pnv_core.c
@@ -167,6 +167,47 @@ static const MemoryRegionOps pnv_core_power9_xscom_ops = {
  .endianness = DEVICE_BIG_ENDIAN,
  };
  
+/*

+ * POWER10 core controls
+ */
+
+static uint64_t pnv_core_power10_xscom_read(void *opaque, hwaddr addr,
+   unsigned int width)
+{
+uint32_t offset = addr >> 3;
+uint64_t val = 0;
+
+switch (offset) {
+default:
+qemu_log_mask(LOG_UNIMP, "Warning: reading reg=0x%" HWADDR_PRIx "\n",
+  addr);
+}
+
+return val;
+}
+
+static void pnv_core_power10_xscom_write(void *opaque, hwaddr addr,
+ uint64_t val, unsigned int width)
+{
+uint32_t offset = addr >> 3;
+
+switch (offset) {
+default:
+qemu_log_mask(LOG_UNIMP, "Warning: writing to reg=0x%" HWADDR_PRIx 
"\n",
+  addr);
+}
+}
+
+static const MemoryRegionOps pnv_core_power10_xscom_ops = {
+.read = pnv_core_power10_xscom_read,
+.write = pnv_core_power10_xscom_write,
+.valid.min_access_size = 8,
+.valid.max_access_size = 8,
+.impl.min_access_size = 8,
+.impl.max_access_size = 8,
+.endianness = DEVICE_BIG_ENDIAN,
+};
+
  static void pnv_core_cpu_realize(PnvCore *pc, PowerPCCPU *cpu, Error **errp)
  {
  CPUPPCState *env = >env;
@@ -315,8 +356,7 @@ static void pnv_core_power10_class_init(ObjectClass *oc, 
void *data)
  {
  PnvCoreClass *pcc = PNV_CORE_CLASS(oc);
  
-/* TODO: Use the P9 XSCOMs for now on P10 */

-pcc->xscom_ops = _core_power9_xscom_ops;
+pcc->xscom_ops = _core_power10_xscom_ops;
  }
  
  static void pnv_core_class_init(ObjectClass *oc, void *data)




Re: [PATCH v2 5/5] ppc/pnv: Return zero for core thread state xscom

2023-07-04 Thread Frederic Barrat




On 04/07/2023 07:42, Joel Stanley wrote:

Firmware now warns if booting in LPAR per core mode (PPC bit 62). So
this warning doesn't trigger, report the core thread state is 0.

Reviewed-by: Cédric Le Goater 
Signed-off-by: Joel Stanley 
---



Reviewed-by: Frederic Barrat 

  Fred


  hw/ppc/pnv_core.c | 10 ++
  1 file changed, 10 insertions(+)

diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c
index 1eec28c88c41..b7223bb44597 100644
--- a/hw/ppc/pnv_core.c
+++ b/hw/ppc/pnv_core.c
@@ -116,6 +116,8 @@ static const MemoryRegionOps pnv_core_power8_xscom_ops = {
  #define PNV9_XSCOM_EC_PPM_SPECIAL_WKUP_HYP 0xf010d
  #define PNV9_XSCOM_EC_PPM_SPECIAL_WKUP_OTR 0xf010a
  
+#define PNV9_XSCOM_EC_CORE_THREAD_STATE0x10ab3

+
  static uint64_t pnv_core_power9_xscom_read(void *opaque, hwaddr addr,
 unsigned int width)
  {
@@ -134,6 +136,9 @@ static uint64_t pnv_core_power9_xscom_read(void *opaque, 
hwaddr addr,
  case PNV9_XSCOM_EC_PPM_SPECIAL_WKUP_OTR:
  val = 0x0;
  break;
+case PNV9_XSCOM_EC_CORE_THREAD_STATE:
+val = 0;
+break;
  default:
  qemu_log_mask(LOG_UNIMP, "Warning: reading reg=0x%" HWADDR_PRIx "\n",
addr);
@@ -171,6 +176,8 @@ static const MemoryRegionOps pnv_core_power9_xscom_ops = {
   * POWER10 core controls
   */
  
+#define PNV10_XSCOM_EC_CORE_THREAD_STATE0x412

+
  static uint64_t pnv_core_power10_xscom_read(void *opaque, hwaddr addr,
 unsigned int width)
  {
@@ -178,6 +185,9 @@ static uint64_t pnv_core_power10_xscom_read(void *opaque, 
hwaddr addr,
  uint64_t val = 0;
  
  switch (offset) {

+case PNV10_XSCOM_EC_CORE_THREAD_STATE:
+val = 0;
+break;
  default:
  qemu_log_mask(LOG_UNIMP, "Warning: reading reg=0x%" HWADDR_PRIx "\n",
addr);




Re: [PATCH v2 3/5] ppc/pnv: Add P10 quad xscom model

2023-07-04 Thread Frederic Barrat




On 04/07/2023 07:42, Joel Stanley wrote:

Add a PnvQuad class for the P10 powernv machine. No xscoms are
implemented yet, but this allows them to be added.

The size is reduced to avoid the quad region from overlapping with the
core region.

   address-space: xscom-0
 -0003 (prio 0, i/o): xscom-0
   0001-0001000f (prio 0, i/o): xscom-quad.0
   000100108000-000100907fff (prio 0, i/o): xscom-core.3
   00010011-00010090 (prio 0, i/o): xscom-core.2
   00010012-00010091 (prio 0, i/o): xscom-core.1
   00010014-00010093 (prio 0, i/o): xscom-core.0

Signed-off-by: Joel Stanley 
---



Reviewed-by: Frederic Barrat 


  Fred



v2: Fix unimp read message
 Wrap lines at 80 col
 Set size
---
  include/hw/ppc/pnv_xscom.h |  2 +-
  hw/ppc/pnv.c   |  2 +-
  hw/ppc/pnv_core.c  | 54 ++
  3 files changed, 56 insertions(+), 2 deletions(-)

diff --git a/include/hw/ppc/pnv_xscom.h b/include/hw/ppc/pnv_xscom.h
index cbe848d27ba0..f7da9a1dc617 100644
--- a/include/hw/ppc/pnv_xscom.h
+++ b/include/hw/ppc/pnv_xscom.h
@@ -129,7 +129,7 @@ struct PnvXScomInterfaceClass {
  
  #define PNV10_XSCOM_EQ_BASE(core) \

  ((uint64_t) PNV10_XSCOM_EQ(PNV10_XSCOM_EQ_CHIPLET(core)))
-#define PNV10_XSCOM_EQ_SIZE0x10
+#define PNV10_XSCOM_EQ_SIZE0x2
  
  #define PNV10_XSCOM_EC_BASE(core) \

  ((uint64_t) PNV10_XSCOM_EQ_BASE(core) | PNV10_XSCOM_EC(core & 0x3))
diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index c77fdb6747a4..5f25fe985ab2 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -1669,7 +1669,7 @@ static void pnv_chip_power10_quad_realize(Pnv10Chip 
*chip10, Error **errp)
  PnvQuad *eq = >quads[i];
  
  pnv_chip_quad_realize_one(chip, eq, chip->cores[i * 4],

-  PNV_QUAD_TYPE_NAME("power9"));
+  PNV_QUAD_TYPE_NAME("power10"));
  
  pnv_xscom_add_subregion(chip, PNV10_XSCOM_EQ_BASE(eq->quad_id),

  >xscom_regs);
diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c
index 73d25409c937..e4df435b15e9 100644
--- a/hw/ppc/pnv_core.c
+++ b/hw/ppc/pnv_core.c
@@ -404,6 +404,47 @@ static const MemoryRegionOps pnv_quad_power9_xscom_ops = {
  .endianness = DEVICE_BIG_ENDIAN,
  };
  
+/*

+ * POWER10 Quads
+ */
+
+static uint64_t pnv_quad_power10_xscom_read(void *opaque, hwaddr addr,
+unsigned int width)
+{
+uint32_t offset = addr >> 3;
+uint64_t val = -1;
+
+switch (offset) {
+default:
+qemu_log_mask(LOG_UNIMP, "%s: reading @0x%08x\n", __func__,
+  offset);
+}
+
+return val;
+}
+
+static void pnv_quad_power10_xscom_write(void *opaque, hwaddr addr,
+ uint64_t val, unsigned int width)
+{
+uint32_t offset = addr >> 3;
+
+switch (offset) {
+default:
+qemu_log_mask(LOG_UNIMP, "%s: writing @0x%08x\n", __func__,
+  offset);
+}
+}
+
+static const MemoryRegionOps pnv_quad_power10_xscom_ops = {
+.read = pnv_quad_power10_xscom_read,
+.write = pnv_quad_power10_xscom_write,
+.valid.min_access_size = 8,
+.valid.max_access_size = 8,
+.impl.min_access_size = 8,
+.impl.max_access_size = 8,
+.endianness = DEVICE_BIG_ENDIAN,
+};
+
  static void pnv_quad_realize(DeviceState *dev, Error **errp)
  {
  PnvQuad *eq = PNV_QUAD(dev);
@@ -430,6 +471,14 @@ static void pnv_quad_power9_class_init(ObjectClass *oc, 
void *data)
  pqc->xscom_size = PNV9_XSCOM_EQ_SIZE;
  }
  
+static void pnv_quad_power10_class_init(ObjectClass *oc, void *data)

+{
+PnvQuadClass *pqc = PNV_QUAD_CLASS(oc);
+
+pqc->xscom_ops = _quad_power10_xscom_ops;
+pqc->xscom_size = PNV10_XSCOM_EQ_SIZE;
+}
+
  static void pnv_quad_class_init(ObjectClass *oc, void *data)
  {
  DeviceClass *dc = DEVICE_CLASS(oc);
@@ -453,6 +502,11 @@ static const TypeInfo pnv_quad_infos[] = {
  .name = PNV_QUAD_TYPE_NAME("power9"),
  .class_init = pnv_quad_power9_class_init,
  },
+{
+.parent = TYPE_PNV_QUAD,
+.name = PNV_QUAD_TYPE_NAME("power10"),
+.class_init = pnv_quad_power10_class_init,
+},
  };
  
  DEFINE_TYPES(pnv_quad_infos);




Re: [PATCH v2 2/5] ppc/pnv: Subclass quad xscom callbacks

2023-07-04 Thread Frederic Barrat




On 04/07/2023 07:42, Joel Stanley wrote:

Make the existing pnv_quad_xscom_read/write be P9 specific, in
preparation for a different P10 callback.

Reviewed-by: Cédric Le Goater 
Signed-off-by: Joel Stanley 
---



Reviewed-by: Frederic Barrat 

  Fred



v2: Add scom region size to class
---
  include/hw/ppc/pnv_core.h | 13 -
  hw/ppc/pnv.c  | 11 +++
  hw/ppc/pnv_core.c | 40 ++-
  3 files changed, 46 insertions(+), 18 deletions(-)

diff --git a/include/hw/ppc/pnv_core.h b/include/hw/ppc/pnv_core.h
index 3d75706e95da..77ef00f47a72 100644
--- a/include/hw/ppc/pnv_core.h
+++ b/include/hw/ppc/pnv_core.h
@@ -60,8 +60,19 @@ static inline PnvCPUState *pnv_cpu_state(PowerPCCPU *cpu)
  return (PnvCPUState *)cpu->machine_data;
  }
  
+struct PnvQuadClass {

+DeviceClass parent_class;
+
+const MemoryRegionOps *xscom_ops;
+uint64_t xscom_size;
+};
+
  #define TYPE_PNV_QUAD "powernv-cpu-quad"
-OBJECT_DECLARE_SIMPLE_TYPE(PnvQuad, PNV_QUAD)
+
+#define PNV_QUAD_TYPE_SUFFIX "-" TYPE_PNV_QUAD
+#define PNV_QUAD_TYPE_NAME(cpu_model) cpu_model PNV_QUAD_TYPE_SUFFIX
+
+OBJECT_DECLARE_TYPE(PnvQuad, PnvQuadClass, PNV_QUAD)
  
  struct PnvQuad {

  DeviceState parent_obj;
diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index fc083173f346..c77fdb6747a4 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -1429,14 +1429,15 @@ static void pnv_chip_power9_instance_init(Object *obj)
  }
  
  static void pnv_chip_quad_realize_one(PnvChip *chip, PnvQuad *eq,

-  PnvCore *pnv_core)
+  PnvCore *pnv_core,
+  const char *type)
  {
  char eq_name[32];
  int core_id = CPU_CORE(pnv_core)->core_id;
  
  snprintf(eq_name, sizeof(eq_name), "eq[%d]", core_id);

  object_initialize_child_with_props(OBJECT(chip), eq_name, eq,
-   sizeof(*eq), TYPE_PNV_QUAD,
+   sizeof(*eq), type,
 _fatal, NULL);
  
  object_property_set_int(OBJECT(eq), "quad-id", core_id, _fatal);

@@ -1454,7 +1455,8 @@ static void pnv_chip_quad_realize(Pnv9Chip *chip9, Error 
**errp)
  for (i = 0; i < chip9->nr_quads; i++) {
  PnvQuad *eq = >quads[i];
  
-pnv_chip_quad_realize_one(chip, eq, chip->cores[i * 4]);

+pnv_chip_quad_realize_one(chip, eq, chip->cores[i * 4],
+  PNV_QUAD_TYPE_NAME("power9"));
  
  pnv_xscom_add_subregion(chip, PNV9_XSCOM_EQ_BASE(eq->quad_id),

  >xscom_regs);
@@ -1666,7 +1668,8 @@ static void pnv_chip_power10_quad_realize(Pnv10Chip 
*chip10, Error **errp)
  for (i = 0; i < chip10->nr_quads; i++) {
  PnvQuad *eq = >quads[i];
  
-pnv_chip_quad_realize_one(chip, eq, chip->cores[i * 4]);

+pnv_chip_quad_realize_one(chip, eq, chip->cores[i * 4],
+  PNV_QUAD_TYPE_NAME("power9"));
  
  pnv_xscom_add_subregion(chip, PNV10_XSCOM_EQ_BASE(eq->quad_id),

  >xscom_regs);
diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c
index 0f451b3b6e1f..73d25409c937 100644
--- a/hw/ppc/pnv_core.c
+++ b/hw/ppc/pnv_core.c
@@ -407,12 +407,14 @@ static const MemoryRegionOps pnv_quad_power9_xscom_ops = {
  static void pnv_quad_realize(DeviceState *dev, Error **errp)
  {
  PnvQuad *eq = PNV_QUAD(dev);
+PnvQuadClass *pqc = PNV_QUAD_GET_CLASS(eq);
  char name[32];
  
  snprintf(name, sizeof(name), "xscom-quad.%d", eq->quad_id);

  pnv_xscom_region_init(>xscom_regs, OBJECT(dev),
-  _quad_power9_xscom_ops,
-  eq, name, PNV9_XSCOM_EQ_SIZE);
+  pqc->xscom_ops,
+  eq, name,
+  pqc->xscom_size);
  }
  
  static Property pnv_quad_properties[] = {

@@ -420,6 +422,14 @@ static Property pnv_quad_properties[] = {
  DEFINE_PROP_END_OF_LIST(),
  };
  
+static void pnv_quad_power9_class_init(ObjectClass *oc, void *data)

+{
+PnvQuadClass *pqc = PNV_QUAD_CLASS(oc);
+
+pqc->xscom_ops = _quad_power9_xscom_ops;
+pqc->xscom_size = PNV9_XSCOM_EQ_SIZE;
+}
+
  static void pnv_quad_class_init(ObjectClass *oc, void *data)
  {
  DeviceClass *dc = DEVICE_CLASS(oc);
@@ -429,16 +439,20 @@ static void pnv_quad_class_init(ObjectClass *oc, void 
*data)
  dc->user_creatable = false;
  }
  
-static const TypeInfo pnv_quad_info = {

-.name  = TYPE_PNV_QUAD,
-.parent= TYPE_DEVICE,
-.instance_size = sizeof(PnvQuad),
-.class_init= pnv_quad_class_init,
+static const TypeInfo pnv_quad_infos[] = {
+{
+.name  = TYPE_PNV_QUAD,
+.p

Re: [PATCH v2 1/5] ppc/pnv: quad xscom callbacks are P9 specific

2023-07-04 Thread Frederic Barrat




On 04/07/2023 07:42, Joel Stanley wrote:

Rename the functions to include P9 in the name in preparation for adding
P10 versions.

Correct the unimp read message while we're changing the function.

Reviewed-by: Cédric Le Goater 
Signed-off-by: Joel Stanley 
---



Reviewed-by: Frederic Barrat 



v2: Fix unimp print, and grammar in the commit message
---
  hw/ppc/pnv_core.c | 19 ++-
  1 file changed, 10 insertions(+), 9 deletions(-)

diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c
index 0bc3ad41c81c..0f451b3b6e1f 100644
--- a/hw/ppc/pnv_core.c
+++ b/hw/ppc/pnv_core.c
@@ -360,8 +360,8 @@ DEFINE_TYPES(pnv_core_infos)
  
  #define P9X_EX_NCU_SPEC_BAR 0x11010
  
-static uint64_t pnv_quad_xscom_read(void *opaque, hwaddr addr,

-unsigned int width)
+static uint64_t pnv_quad_power9_xscom_read(void *opaque, hwaddr addr,
+   unsigned int width)
  {
  uint32_t offset = addr >> 3;
  uint64_t val = -1;
@@ -372,15 +372,15 @@ static uint64_t pnv_quad_xscom_read(void *opaque, hwaddr 
addr,
  val = 0;
  break;
  default:
-qemu_log_mask(LOG_UNIMP, "%s: writing @0x%08x\n", __func__,
+qemu_log_mask(LOG_UNIMP, "%s: reading @0x%08x\n", __func__,
offset);
  }
  
  return val;

  }
  
-static void pnv_quad_xscom_write(void *opaque, hwaddr addr, uint64_t val,

- unsigned int width)
+static void pnv_quad_power9_xscom_write(void *opaque, hwaddr addr, uint64_t 
val,
+unsigned int width)
  {
  uint32_t offset = addr >> 3;
  
@@ -394,9 +394,9 @@ static void pnv_quad_xscom_write(void *opaque, hwaddr addr, uint64_t val,

  }
  }
  
-static const MemoryRegionOps pnv_quad_xscom_ops = {

-.read = pnv_quad_xscom_read,
-.write = pnv_quad_xscom_write,
+static const MemoryRegionOps pnv_quad_power9_xscom_ops = {
+.read = pnv_quad_power9_xscom_read,
+.write = pnv_quad_power9_xscom_write,
  .valid.min_access_size = 8,
  .valid.max_access_size = 8,
  .impl.min_access_size = 8,
@@ -410,7 +410,8 @@ static void pnv_quad_realize(DeviceState *dev, Error **errp)
  char name[32];
  
  snprintf(name, sizeof(name), "xscom-quad.%d", eq->quad_id);

-pnv_xscom_region_init(>xscom_regs, OBJECT(dev), _quad_xscom_ops,
+pnv_xscom_region_init(>xscom_regs, OBJECT(dev),
+  _quad_power9_xscom_ops,
eq, name, PNV9_XSCOM_EQ_SIZE);
  }
  




[PATCH v2 1/2] pnv/xive: Add property on xive sources to define PQ state on reset

2023-07-03 Thread Frederic Barrat
The PQ state of a xive interrupt is always initialized to Q=1, which
means the interrupt is disabled. Since a xive source can be embedded
in many objects, this patch adds a property to allow that behavior to
be refined if needed.

Signed-off-by: Frederic Barrat 
---
 hw/intc/xive.c| 8 ++--
 include/hw/ppc/xive.h | 1 +
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/hw/intc/xive.c b/hw/intc/xive.c
index 84c079b034..f60c878345 100644
--- a/hw/intc/xive.c
+++ b/hw/intc/xive.c
@@ -1232,8 +1232,7 @@ static void xive_source_reset(void *dev)
 
 /* Do not clear the LSI bitmap */
 
-/* PQs are initialized to 0b01 (Q=1) which corresponds to "ints off" */
-memset(xsrc->status, XIVE_ESB_OFF, xsrc->nr_irqs);
+memset(xsrc->status, xsrc->reset_pq, xsrc->nr_irqs);
 }
 
 static void xive_source_realize(DeviceState *dev, Error **errp)
@@ -1287,6 +1286,11 @@ static Property xive_source_properties[] = {
 DEFINE_PROP_UINT64("flags", XiveSource, esb_flags, 0),
 DEFINE_PROP_UINT32("nr-irqs", XiveSource, nr_irqs, 0),
 DEFINE_PROP_UINT32("shift", XiveSource, esb_shift, XIVE_ESB_64K_2PAGE),
+/*
+ * By default, PQs are initialized to 0b01 (Q=1) which corresponds
+ * to "ints off"
+ */
+DEFINE_PROP_UINT8("reset-pq", XiveSource, reset_pq, XIVE_ESB_OFF),
 DEFINE_PROP_LINK("xive", XiveSource, xive, TYPE_XIVE_NOTIFIER,
  XiveNotifier *),
 DEFINE_PROP_END_OF_LIST(),
diff --git a/include/hw/ppc/xive.h b/include/hw/ppc/xive.h
index 3dfb06e002..9f580a2699 100644
--- a/include/hw/ppc/xive.h
+++ b/include/hw/ppc/xive.h
@@ -187,6 +187,7 @@ struct XiveSource {
 
 /* PQ bits and LSI assertion bit */
 uint8_t *status;
+uint8_t reset_pq; /* PQ state on reset */
 
 /* ESB memory region */
 uint64_tesb_flags;
-- 
2.41.0




[PATCH v2 2/2] pnv/psi: Initialize the PSIHB interrupts to match hardware

2023-07-03 Thread Frederic Barrat
On the powernv9 and powernv10 machines, the PSIHB interrupts are
currently initialized with a PQ state of 0b01, i.e. interrupts are
disabled. However real hardware initializes them to 0b00 for the
PSIHB. This patch updates it, in case an hypervisor is in the mood of
checking it.

Signed-off-by: Frederic Barrat 
---
 hw/ppc/pnv_psi.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/hw/ppc/pnv_psi.c b/hw/ppc/pnv_psi.c
index 46da58dff8..daaa2f0575 100644
--- a/hw/ppc/pnv_psi.c
+++ b/hw/ppc/pnv_psi.c
@@ -863,6 +863,8 @@ static void pnv_psi_power9_realize(DeviceState *dev, Error 
**errp)
 object_property_set_int(OBJECT(xsrc), "nr-irqs", PSIHB9_NUM_IRQS,
 _fatal);
 object_property_set_link(OBJECT(xsrc), "xive", OBJECT(psi), _abort);
+object_property_set_int(OBJECT(xsrc), "reset-pq", XIVE_ESB_RESET,
+_abort);
 if (!qdev_realize(DEVICE(xsrc), NULL, errp)) {
 return;
 }
-- 
2.41.0




[PATCH v2 0/2] Fix PSIHB interrupts init PQ state

2023-07-03 Thread Frederic Barrat
On P9 and 10, the real hardware defines the PQ state of the PSIHB
interrupts to be 0b00. Qemu defaults to 0b01.

It doesn't matter to skiboot, which doesn't rely on it and explicitly
masks the interrupts during intialization. But this patch fixes it,
just in case some other hypervisor checks it.

Changelog:
v2: rename property/struct member
rebase to Daniel's ppc-next branch


Frederic Barrat (2):
  pnv/xive: Add property on xive sources to define PQ state on reset
  pnv/psi: Initialize the PSIHB interrupts to match hardware

 hw/intc/xive.c| 8 ++--
 hw/ppc/pnv_psi.c  | 2 ++
 include/hw/ppc/xive.h | 1 +
 3 files changed, 9 insertions(+), 2 deletions(-)

-- 
2.41.0




[PATCH v2] pnv/xive2: Fix TIMA offset for indirect access

2023-07-03 Thread Frederic Barrat
Direct TIMA operations can be done through 4 pages, each with a
different privilege level dictating what fields can be accessed. On
the other hand, indirect TIMA accesses on P10 are done through a
single page, which is the equivalent of the most privileged page of
direct TIMA accesses.

The offset in the IC bar of an indirect access specifies what hw
thread is targeted (page shift bits) and the offset in the
TIMA being accessed (the page offset bits). When the indirect
access is calling the underlying direct access functions, it is
therefore important to clearly separate the 2, as the direct functions
assume any page shift bits define the privilege ring level. For
indirect accesses, those bits must be 0. This patch fixes the offset
passed to direct TIMA functions.

It didn't matter for SMT1, as the 2 least significant bits of the page
shift are part of the hw thread ID and always 0, so the direct TIMA
functions were accessing the privilege ring 0 page. With SMT4/8, it is
no longer true.

The fix is specific to P10, as indirect TIMA access on P9 was handled
differently.

Signed-off-by: Frederic Barrat 
---
Changelog:
v2: rename function and variable
rebase to Danel's ppc-next

hw/intc/pnv_xive2.c | 20 ++--
 1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/hw/intc/pnv_xive2.c b/hw/intc/pnv_xive2.c
index e8ab176de6..82fcd3ea22 100644
--- a/hw/intc/pnv_xive2.c
+++ b/hw/intc/pnv_xive2.c
@@ -1590,6 +1590,18 @@ static uint32_t pnv_xive2_ic_tm_get_pir(PnvXive2 *xive, 
hwaddr offset)
 return xive->chip->chip_id << 8 | offset >> xive->ic_shift;
 }
 
+static uint32_t pnv_xive2_ic_tm_get_hw_page_offset(PnvXive2 *xive,
+   hwaddr offset)
+{
+/*
+ * Indirect TIMA accesses are similar to direct accesses for
+ * privilege ring 0. So remove any traces of the hw thread ID from
+ * the offset in the IC BAR as it could be interpreted as the ring
+ * privilege when calling the underlying direct access functions.
+ */
+return offset & ((1ull << xive->ic_shift) - 1);
+}
+
 static XiveTCTX *pnv_xive2_get_indirect_tctx(PnvXive2 *xive, uint32_t pir)
 {
 PnvChip *chip = xive->chip;
@@ -1612,14 +1624,16 @@ static uint64_t pnv_xive2_ic_tm_indirect_read(void 
*opaque, hwaddr offset,
   unsigned size)
 {
 PnvXive2 *xive = PNV_XIVE2(opaque);
+hwaddr hw_page_offset;
 uint32_t pir;
 XiveTCTX *tctx;
 uint64_t val = -1;
 
 pir = pnv_xive2_ic_tm_get_pir(xive, offset);
+hw_page_offset = pnv_xive2_ic_tm_get_hw_page_offset(xive, offset);
 tctx = pnv_xive2_get_indirect_tctx(xive, pir);
 if (tctx) {
-val = xive_tctx_tm_read(NULL, tctx, offset, size);
+val = xive_tctx_tm_read(NULL, tctx, hw_page_offset, size);
 }
 
 return val;
@@ -1629,13 +1643,15 @@ static void pnv_xive2_ic_tm_indirect_write(void 
*opaque, hwaddr offset,
uint64_t val, unsigned size)
 {
 PnvXive2 *xive = PNV_XIVE2(opaque);
+hwaddr hw_page_offset;
 uint32_t pir;
 XiveTCTX *tctx;
 
 pir = pnv_xive2_ic_tm_get_pir(xive, offset);
+hw_page_offset = pnv_xive2_ic_tm_get_hw_page_offset(xive, offset);
 tctx = pnv_xive2_get_indirect_tctx(xive, pir);
 if (tctx) {
-xive_tctx_tm_write(NULL, tctx, offset, val, size);
+xive_tctx_tm_write(NULL, tctx, hw_page_offset, val, size);
 }
 }
 
-- 
2.41.0




[PATCH 0/2] Fix PSIHB interrupts init PQ state

2023-06-30 Thread Frederic Barrat
On P9 and 10, the real hardware defines the PQ state of the PSIHB
interrupts to be 0b00. Qemu defaults to 0b01.

It doesn't matter to skiboot, which doesn't rely on it and explicitly
masks the interrupts during intialization. But this patch fixes it,
just in case some other hypervisor checks it.


Frederic Barrat (2):
  pnv/xive: Add property on xive sources to define PQ state on reset
  pnv/psi: Initialize the PSIHB interrupts to match hardware

 hw/intc/xive.c| 8 ++--
 hw/ppc/pnv_psi.c  | 2 ++
 include/hw/ppc/xive.h | 1 +
 3 files changed, 9 insertions(+), 2 deletions(-)

-- 
2.41.0




[PATCH 1/2] pnv/xive: Add property on xive sources to define PQ state on reset

2023-06-30 Thread Frederic Barrat
The PQ state of a xive interrupt is always initialized to Q=1, which
means the interrupt is disabled. Since a xive source can be embedded
in many objects, this patch adds a property to allow that behavior to
be refined if needed.

Signed-off-by: Frederic Barrat 
---
 hw/intc/xive.c| 8 ++--
 include/hw/ppc/xive.h | 1 +
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/hw/intc/xive.c b/hw/intc/xive.c
index 84c079b034..c553b32638 100644
--- a/hw/intc/xive.c
+++ b/hw/intc/xive.c
@@ -1232,8 +1232,7 @@ static void xive_source_reset(void *dev)
 
 /* Do not clear the LSI bitmap */
 
-/* PQs are initialized to 0b01 (Q=1) which corresponds to "ints off" */
-memset(xsrc->status, XIVE_ESB_OFF, xsrc->nr_irqs);
+memset(xsrc->status, xsrc->pq_init, xsrc->nr_irqs);
 }
 
 static void xive_source_realize(DeviceState *dev, Error **errp)
@@ -1287,6 +1286,11 @@ static Property xive_source_properties[] = {
 DEFINE_PROP_UINT64("flags", XiveSource, esb_flags, 0),
 DEFINE_PROP_UINT32("nr-irqs", XiveSource, nr_irqs, 0),
 DEFINE_PROP_UINT32("shift", XiveSource, esb_shift, XIVE_ESB_64K_2PAGE),
+/*
+ * By default, PQs are initialized to 0b01 (Q=1) which corresponds
+ * to "ints off"
+ */
+DEFINE_PROP_UINT8("pq-init", XiveSource, pq_init, XIVE_ESB_OFF),
 DEFINE_PROP_LINK("xive", XiveSource, xive, TYPE_XIVE_NOTIFIER,
  XiveNotifier *),
 DEFINE_PROP_END_OF_LIST(),
diff --git a/include/hw/ppc/xive.h b/include/hw/ppc/xive.h
index 3dfb06e002..7969f06bcf 100644
--- a/include/hw/ppc/xive.h
+++ b/include/hw/ppc/xive.h
@@ -187,6 +187,7 @@ struct XiveSource {
 
 /* PQ bits and LSI assertion bit */
 uint8_t *status;
+uint8_t pq_init; /* PQ state on reset */
 
 /* ESB memory region */
 uint64_tesb_flags;
-- 
2.41.0




[PATCH 2/2] pnv/psi: Initialize the PSIHB interrupts to match hardware

2023-06-30 Thread Frederic Barrat
On P9/P10, the PSIHB interrupts are initialized with a PQ state of
0b01, i.e. interrupts are disabled. However the real hardware
initializes them to 0b00 for the PSIHB. This patch updates it, in case
an hypervisor is in the mood of checking it.

Signed-off-by: Frederic Barrat 
---
 hw/ppc/pnv_psi.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/hw/ppc/pnv_psi.c b/hw/ppc/pnv_psi.c
index 46da58dff8..f232935d27 100644
--- a/hw/ppc/pnv_psi.c
+++ b/hw/ppc/pnv_psi.c
@@ -863,6 +863,8 @@ static void pnv_psi_power9_realize(DeviceState *dev, Error 
**errp)
 object_property_set_int(OBJECT(xsrc), "nr-irqs", PSIHB9_NUM_IRQS,
 _fatal);
 object_property_set_link(OBJECT(xsrc), "xive", OBJECT(psi), _abort);
+object_property_set_int(OBJECT(xsrc), "pq-init", XIVE_ESB_RESET,
+_abort);
 if (!qdev_realize(DEVICE(xsrc), NULL, errp)) {
 return;
 }
-- 
2.41.0




[PATCH] pnv/xive2: Fix TIMA offset for indirect access

2023-06-30 Thread Frederic Barrat
Direct TIMA operations can be done through 4 pages, each with a
different privilege level dictating what fields can be accessed. On
the other hand, indirect TIMA accesses on P10 are done through a
single page, which is the equivalent of the most privileged page of
direct TIMA accesses.

The offset in the IC bar of an indirect access specifies what hw
thread is targeted (page shift bits) and the offset in the
TIMA being accessed (the page offset bits). When the indirect
access is calling the underlying direct access functions, it is
therefore important to clearly separate the 2, as the direct functions
assume any page shift bits define the privilege ring level. For
indirect accesses, those bits must be 0. This patch fixes the offset
passed to direct TIMA functions.

It didn't matter for SMT1, as the 2 least significant bits of the page
shift are part of the hw thread ID and always 0, so the direct TIMA
functions were accessing the privilege ring 0 page. With SMT4/8, it is
no longer true.

The fix is specific to P10, as indirect TIMA access on P9 was handled
differently.

Signed-off-by: Frederic Barrat 
---
 hw/intc/pnv_xive2.c | 19 +--
 1 file changed, 17 insertions(+), 2 deletions(-)

diff --git a/hw/intc/pnv_xive2.c b/hw/intc/pnv_xive2.c
index ed438a20ed..0618e6b0da 100644
--- a/hw/intc/pnv_xive2.c
+++ b/hw/intc/pnv_xive2.c
@@ -1590,6 +1590,17 @@ static uint32_t pnv_xive2_ic_tm_get_pir(PnvXive2 *xive, 
hwaddr offset)
 return xive->chip->chip_id << 8 | offset >> xive->ic_shift;
 }
 
+static uint32_t pnv_xive2_ic_tm_get_offset(PnvXive2 *xive, hwaddr offset)
+{
+/*
+ * Indirect TIMA accesses are similar to direct accesses for
+ * privilege ring 0. So remove any traces of the hw thread ID from
+ * the offset in the IC BAR as it could be interpreted as the ring
+ * privilege when calling the underlying direct access functions.
+ */
+return offset & ((1 << xive->ic_shift) - 1);
+}
+
 static XiveTCTX *pnv_xive2_get_indirect_tctx(PnvXive2 *xive, uint32_t pir)
 {
 PnvChip *chip = xive->chip;
@@ -1612,14 +1623,16 @@ static uint64_t pnv_xive2_ic_tm_indirect_read(void 
*opaque, hwaddr offset,
   unsigned size)
 {
 PnvXive2 *xive = PNV_XIVE2(opaque);
+hwaddr tima_offset;
 uint32_t pir;
 XiveTCTX *tctx;
 uint64_t val = -1;
 
 pir = pnv_xive2_ic_tm_get_pir(xive, offset);
+tima_offset = pnv_xive2_ic_tm_get_offset(xive, offset);
 tctx = pnv_xive2_get_indirect_tctx(xive, pir);
 if (tctx) {
-val = xive_tctx_tm_read(NULL, tctx, offset, size);
+val = xive_tctx_tm_read(NULL, tctx, tima_offset, size);
 }
 
 return val;
@@ -1629,13 +1642,15 @@ static void pnv_xive2_ic_tm_indirect_write(void 
*opaque, hwaddr offset,
uint64_t val, unsigned size)
 {
 PnvXive2 *xive = PNV_XIVE2(opaque);
+hwaddr tima_offset;
 uint32_t pir;
 XiveTCTX *tctx;
 
 pir = pnv_xive2_ic_tm_get_pir(xive, offset);
+tima_offset = pnv_xive2_ic_tm_get_offset(xive, offset);
 tctx = pnv_xive2_get_indirect_tctx(xive, pir);
 if (tctx) {
-xive_tctx_tm_write(NULL, tctx, offset, val, size);
+xive_tctx_tm_write(NULL, tctx, tima_offset, val, size);
 }
 }
 
-- 
2.41.0




[PATCH] pnv/psi: Allow access to PSI registers through xscom

2023-06-30 Thread Frederic Barrat
skiboot only uses mmio to access the PSI registers (once the BAR is
set) but we don't have any reason to block the accesses through
xscom. This patch enables xscom access to the PSI registers. It
converts the xscom addresses to mmio addresses, which requires a bit
of care for the PSIHB, then reuse the existing mmio ops.

Signed-off-by: Frederic Barrat 
---
 hw/ppc/pnv_psi.c | 31 +--
 1 file changed, 21 insertions(+), 10 deletions(-)

diff --git a/hw/ppc/pnv_psi.c b/hw/ppc/pnv_psi.c
index 8aa09ab26b..46da58dff8 100644
--- a/hw/ppc/pnv_psi.c
+++ b/hw/ppc/pnv_psi.c
@@ -121,8 +121,12 @@
 #define PSIHB9_BAR_MASK 0x00f0ull
 #define PSIHB9_FSPBAR_MASK  0x00ffull
 
+/* mmio address to xscom address */
 #define PSIHB_REG(addr) (((addr) >> 3) + PSIHB_XSCOM_BAR)
 
+/* xscom address to mmio address */
+#define PSIHB_MMIO(reg) ((reg - PSIHB_XSCOM_BAR) << 3)
+
 static void pnv_psi_set_bar(PnvPsi *psi, uint64_t bar)
 {
 PnvPsiClass *ppc = PNV_PSI_GET_CLASS(psi);
@@ -769,24 +773,31 @@ static const MemoryRegionOps pnv_psi_p9_mmio_ops = {
 
 static uint64_t pnv_psi_p9_xscom_read(void *opaque, hwaddr addr, unsigned size)
 {
-/* No read are expected */
-qemu_log_mask(LOG_GUEST_ERROR, "PSI: xscom read at 0x%" PRIx64 "\n", addr);
-return -1;
+uint32_t reg = addr >> 3;
+uint64_t val = -1;
+
+if (reg < PSIHB_XSCOM_BAR) {
+/* FIR, not modeled */
+qemu_log_mask(LOG_UNIMP, "PSI: xscom read at 0x%08x\n", reg);
+} else {
+val = pnv_psi_p9_mmio_read(opaque, PSIHB_MMIO(reg), size);
+}
+return val;
 }
 
 static void pnv_psi_p9_xscom_write(void *opaque, hwaddr addr,
 uint64_t val, unsigned size)
 {
 PnvPsi *psi = PNV_PSI(opaque);
+uint32_t reg = addr >> 3;
 
-/* XSCOM is only used to set the PSIHB MMIO region */
-switch (addr >> 3) {
-case PSIHB_XSCOM_BAR:
+if (reg < PSIHB_XSCOM_BAR) {
+/* FIR, not modeled */
+qemu_log_mask(LOG_UNIMP, "PSI: xscom write at 0x%08x\n", reg);
+} else if (reg == PSIHB_XSCOM_BAR) {
 pnv_psi_set_bar(psi, val);
-break;
-default:
-qemu_log_mask(LOG_GUEST_ERROR, "PSI: xscom write at 0x%" PRIx64 "\n",
-  addr);
+} else {
+pnv_psi_p9_mmio_write(opaque, PSIHB_MMIO(reg), val, size);
 }
 }
 
-- 
2.41.0




Re: [PATCH 3/4] ppc/pnv: Add P10 quad ops

2023-06-30 Thread Frederic Barrat




On 30/06/2023 05:55, Joel Stanley wrote:

diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c
index b9a57463aec4..7fff2fd9e298 100644
--- a/hw/ppc/pnv_core.c
+++ b/hw/ppc/pnv_core.c



+static uint64_t pnv_quad_power10_xscom_read(void *opaque, hwaddr addr,

...

+qemu_log_mask(LOG_UNIMP, "%s: writing @0x%08x\n", __func__,


 ^^^ reading

I'm guessing we'll need to flush out that function pretty soon, so not 
worth resending.


  Fred



Re: [PATCH] hw/ppc: Fix clock update drift

2023-06-29 Thread Frederic Barrat




On 29/06/2023 04:07, Nicholas Piggin wrote:

The clock update logic reads the clock twice to compute the new clock
value, with a value derived from the later time subtracted from a value
derived from the earlier time. The delta causes time to be lost.

This can ultimately result in time becoming unsynchronized between CPUs
and that can cause OS lockups, timeouts, watchdogs, etc. This can be
seen running a KVM guest (that causes lots of TB updates) on a powernv
SMP machine.

Fix this by reading the clock once.

Cc: qemu-sta...@nongnu.org
Signed-off-by: Nicholas Piggin 
---



Nice! It must have been a nightmare to debug.
Do you know where that ATB spr comes from? I can't relate it to the ISA.

Reviewed-by: Frederic Barrat 




I also made a test case that can trigger this with kvm-unit-tests, but
it's been taking me a while to get that upstreamed.

Thanks,
Nick

  hw/ppc/ppc.c | 33 +
  1 file changed, 17 insertions(+), 16 deletions(-)

diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c
index 82e4408c5c..6233f43c01 100644
--- a/hw/ppc/ppc.c
+++ b/hw/ppc/ppc.c
@@ -535,23 +535,24 @@ static inline void cpu_ppc_store_tb(ppc_tb_t *tb_env, 
uint64_t vmclk,
  void cpu_ppc_store_tbl (CPUPPCState *env, uint32_t value)
  {
  ppc_tb_t *tb_env = env->tb_env;
+int64_t clock = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
  uint64_t tb;
  
-tb = cpu_ppc_get_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), tb_env->tb_offset);

+tb = cpu_ppc_get_tb(tb_env, clock, tb_env->tb_offset);
  tb &= 0xULL;
-cpu_ppc_store_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
- _env->tb_offset, tb | (uint64_t)value);
+cpu_ppc_store_tb(tb_env, clock, _env->tb_offset, tb | (uint64_t)value);
  }
  
  static inline void _cpu_ppc_store_tbu(CPUPPCState *env, uint32_t value)

  {
  ppc_tb_t *tb_env = env->tb_env;
+int64_t clock = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
  uint64_t tb;
  
-tb = cpu_ppc_get_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), tb_env->tb_offset);

+tb = cpu_ppc_get_tb(tb_env, clock, tb_env->tb_offset);
  tb &= 0xULL;
-cpu_ppc_store_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
- _env->tb_offset, ((uint64_t)value << 32) | tb);
+cpu_ppc_store_tb(tb_env, clock, _env->tb_offset,
+ ((uint64_t)value << 32) | tb);
  }
  
  void cpu_ppc_store_tbu (CPUPPCState *env, uint32_t value)

@@ -584,23 +585,24 @@ uint32_t cpu_ppc_load_atbu (CPUPPCState *env)
  void cpu_ppc_store_atbl (CPUPPCState *env, uint32_t value)
  {
  ppc_tb_t *tb_env = env->tb_env;
+int64_t clock = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
  uint64_t tb;
  
-tb = cpu_ppc_get_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), tb_env->atb_offset);

+tb = cpu_ppc_get_tb(tb_env, clock, tb_env->atb_offset);
  tb &= 0xULL;
-cpu_ppc_store_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
- _env->atb_offset, tb | (uint64_t)value);
+cpu_ppc_store_tb(tb_env, clock, _env->atb_offset, tb | (uint64_t)value);
  }
  
  void cpu_ppc_store_atbu (CPUPPCState *env, uint32_t value)

  {
  ppc_tb_t *tb_env = env->tb_env;
+int64_t clock = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
  uint64_t tb;
  
-tb = cpu_ppc_get_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), tb_env->atb_offset);

+tb = cpu_ppc_get_tb(tb_env, clock, tb_env->atb_offset);
  tb &= 0xULL;
-cpu_ppc_store_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
- _env->atb_offset, ((uint64_t)value << 32) | tb);
+cpu_ppc_store_tb(tb_env, clock, _env->atb_offset,
+ ((uint64_t)value << 32) | tb);
  }
  
  uint64_t cpu_ppc_load_vtb(CPUPPCState *env)

@@ -622,14 +624,13 @@ void cpu_ppc_store_vtb(CPUPPCState *env, uint64_t value)
  void cpu_ppc_store_tbu40(CPUPPCState *env, uint64_t value)
  {
  ppc_tb_t *tb_env = env->tb_env;
+int64_t clock = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
  uint64_t tb;
  
-tb = cpu_ppc_get_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),

-tb_env->tb_offset);
+tb = cpu_ppc_get_tb(tb_env, clock, tb_env->tb_offset);
  tb &= 0xFFUL;
  tb |= (value & ~0xFFUL);
-cpu_ppc_store_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
- _env->tb_offset, tb);
+cpu_ppc_store_tb(tb_env, clock, _env->tb_offset, tb);
  }
  
  static void cpu_ppc_tb_stop (CPUPPCState *env)




Re: [PATCH] pnv/xive2: Allow indirect TIMA accesses of all sizes

2023-06-26 Thread Frederic Barrat




On 26/06/2023 11:48, Philippe Mathieu-Daudé wrote:

On 26/6/23 11:40, Frederic Barrat wrote:

Booting linux on the powernv10 machine logs a few errors like:

Invalid read at addr 0x38, size 1, region 'xive-ic-tm-indirect', 
reason: invalid size (min:8 max:8)
Invalid write at addr 0x38, size 1, region 'xive-ic-tm-indirect', 
reason: invalid size (min:8 max:8)
Invalid read at addr 0x38, size 1, region 'xive-ic-tm-indirect', 
reason: invalid size (min:8 max:8)


Those errors happen when linux is resetting XIVE. We're trying to
read/write the enablement bit for the hardware context and qemu
doesn't allow indirect TIMA accesses of less than 8 bytes. Direct TIMA
access can go through though, as well as indirect TIMA accesses on P9.
So even though there are some restrictions regarding the address/size
combinations for TIMA access, the example above is perfectly valid.

This patch lets indirect TIMA accesses of all sizes go through. The
special operations will be intercepted and the default "raw" handlers
will pick up all other requests and complain about invalid sizes as
appropriate.

Tested-by: Nicholas Piggin 
Signed-off-by: Frederic Barrat 
---
  hw/intc/pnv_xive2.c | 4 ++--
  1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/intc/pnv_xive2.c b/hw/intc/pnv_xive2.c
index ed438a20ed..e8ab176de6 100644
--- a/hw/intc/pnv_xive2.c
+++ b/hw/intc/pnv_xive2.c
@@ -1644,11 +1644,11 @@ static const MemoryRegionOps 
pnv_xive2_ic_tm_indirect_ops = {

  .write = pnv_xive2_ic_tm_indirect_write,
  .endianness = DEVICE_BIG_ENDIAN,
  .valid = {
-    .min_access_size = 8,
+    .min_access_size = 1,


Maybe. Is there a bus involved in between?

What about other I/O regions?



XIVE is attached to the main system bus and the CPU can trigger 1, 2, 4 
and 8-byte accesses. The TIMA is a part of XIVE which supports various 
size of mmio operations, all the way down to byte operations. It 
actually relies on it.


There are 2 memory regions where we want to allow byte-access. One, 
known as TIMA direct access, already allows access with min size = 1. 
I'm just aligning the other one, known as TIMA indirect access, to do 
the same, since it's what the hardware allows.
This is similar to what we had on P9 and both regions are already 
defined with min size = 1 there. So it really looks like what I'm 
changing here was just an oversight.




  .max_access_size = 8,
  },
  .impl = {
-    .min_access_size = 8,
+    .min_access_size = 1,


Unlikely. This is for the handler implementation, not related to HW.



The handlers for the TIMA regions are aware of the size of the access, 
and behave differently based on it (see xive_tm_find_op() for example). 
So I think this is correct. Let me know if I'm missing something here.


  Fred




  .max_access_size = 8,
  },
  };






[PATCH] pnv/xive2: Allow indirect TIMA accesses of all sizes

2023-06-26 Thread Frederic Barrat
Booting linux on the powernv10 machine logs a few errors like:

Invalid read at addr 0x38, size 1, region 'xive-ic-tm-indirect', reason: 
invalid size (min:8 max:8)
Invalid write at addr 0x38, size 1, region 'xive-ic-tm-indirect', reason: 
invalid size (min:8 max:8)
Invalid read at addr 0x38, size 1, region 'xive-ic-tm-indirect', reason: 
invalid size (min:8 max:8)

Those errors happen when linux is resetting XIVE. We're trying to
read/write the enablement bit for the hardware context and qemu
doesn't allow indirect TIMA accesses of less than 8 bytes. Direct TIMA
access can go through though, as well as indirect TIMA accesses on P9.
So even though there are some restrictions regarding the address/size
combinations for TIMA access, the example above is perfectly valid.

This patch lets indirect TIMA accesses of all sizes go through. The
special operations will be intercepted and the default "raw" handlers
will pick up all other requests and complain about invalid sizes as
appropriate.

Tested-by: Nicholas Piggin 
Signed-off-by: Frederic Barrat 
---
 hw/intc/pnv_xive2.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/intc/pnv_xive2.c b/hw/intc/pnv_xive2.c
index ed438a20ed..e8ab176de6 100644
--- a/hw/intc/pnv_xive2.c
+++ b/hw/intc/pnv_xive2.c
@@ -1644,11 +1644,11 @@ static const MemoryRegionOps 
pnv_xive2_ic_tm_indirect_ops = {
 .write = pnv_xive2_ic_tm_indirect_write,
 .endianness = DEVICE_BIG_ENDIAN,
 .valid = {
-.min_access_size = 8,
+.min_access_size = 1,
 .max_access_size = 8,
 },
 .impl = {
-.min_access_size = 8,
+.min_access_size = 1,
 .max_access_size = 8,
 },
 };
-- 
2.41.0




[PATCH v2 0/2] pnv/xive2: Fix TIMA special ops detection

2023-06-22 Thread Frederic Barrat
Fix the TIMA special ops detection regression, as spotted by Coverity.

Tested by running a pseries guest on top of a powernv9 and powernv10 host.

Changelog:
v2: define get_config for spapr


Frederic Barrat (2):
  pnv/xive2: Add a get_config() method on the presenter class
  pnv/xive2: Check TIMA special ops against a dedicated array for P10

 hw/intc/pnv_xive.c| 11 +
 hw/intc/pnv_xive2.c   | 44 +
 hw/intc/spapr_xive.c  | 16 
 hw/intc/xive.c| 57 +--
 include/hw/ppc/xive.h |  3 +++
 5 files changed, 91 insertions(+), 40 deletions(-)

-- 
2.41.0




[PATCH v2 2/2] pnv/xive2: Check TIMA special ops against a dedicated array for P10

2023-06-22 Thread Frederic Barrat
Accessing the TIMA from some specific ring/offset combination can
trigger a special operation, with or without side effects. It is
implemented in qemu with an array of special operations to compare
accesses against. Since the presenter on P10 is pretty similar to P9,
we had the full array defined for P9 and we just had a special case
for P10 to treat one access differently. With a recent change,
6f2cbd133d4 ("pnv/xive2: Handle TIMA access through all ports"), we
now ignore some of the bits of the TIMA address, but that patch
managed to botch the detection of the special case for P10.

To clean that up, this patch introduces a full array of special ops to
be used for P10. The code to detect a special access is common with
P9, only the array of operations differs. The presenter can pick the
correct array of special ops based on its configuration introduced in
a previous patch.

Fixes: Coverity CID 1512997, 1512998
Fixes: 6f2cbd133d4 ("pnv/xive2: Handle TIMA access through all ports")
Signed-off-by: Frederic Barrat 
---
 hw/intc/pnv_xive2.c | 32 
 hw/intc/xive.c  | 52 +
 2 files changed, 43 insertions(+), 41 deletions(-)

diff --git a/hw/intc/pnv_xive2.c b/hw/intc/pnv_xive2.c
index 59534f6843..ed438a20ed 100644
--- a/hw/intc/pnv_xive2.c
+++ b/hw/intc/pnv_xive2.c
@@ -1656,17 +1656,6 @@ static const MemoryRegionOps 
pnv_xive2_ic_tm_indirect_ops = {
 /*
  * TIMA ops
  */
-
-/*
- * Special TIMA offsets to handle accesses in a POWER10 way.
- *
- * Only the CAM line updates done by the hypervisor should be handled
- * specifically.
- */
-#define HV_PAGE_OFFSET (XIVE_TM_HV_PAGE << TM_SHIFT)
-#define HV_PUSH_OS_CTX_OFFSET  (HV_PAGE_OFFSET | (TM_QW1_OS + TM_WORD2))
-#define HV_PULL_OS_CTX_OFFSET  (HV_PAGE_OFFSET | TM_SPC_PULL_OS_CTX)
-
 static void pnv_xive2_tm_write(void *opaque, hwaddr offset,
uint64_t value, unsigned size)
 {
@@ -1674,18 +1663,7 @@ static void pnv_xive2_tm_write(void *opaque, hwaddr 
offset,
 PnvXive2 *xive = pnv_xive2_tm_get_xive(cpu);
 XiveTCTX *tctx = XIVE_TCTX(pnv_cpu_state(cpu)->intc);
 XivePresenter *xptr = XIVE_PRESENTER(xive);
-bool gen1_tima_os =
-xive->cq_regs[CQ_XIVE_CFG >> 3] & CQ_XIVE_CFG_GEN1_TIMA_OS;
-
-offset &= TM_ADDRESS_MASK;
 
-/* TODO: should we switch the TM ops table instead ? */
-if (!gen1_tima_os && offset == HV_PUSH_OS_CTX_OFFSET) {
-xive2_tm_push_os_ctx(xptr, tctx, offset, value, size);
-return;
-}
-
-/* Other TM ops are the same as XIVE1 */
 xive_tctx_tm_write(xptr, tctx, offset, value, size);
 }
 
@@ -1695,17 +1673,7 @@ static uint64_t pnv_xive2_tm_read(void *opaque, hwaddr 
offset, unsigned size)
 PnvXive2 *xive = pnv_xive2_tm_get_xive(cpu);
 XiveTCTX *tctx = XIVE_TCTX(pnv_cpu_state(cpu)->intc);
 XivePresenter *xptr = XIVE_PRESENTER(xive);
-bool gen1_tima_os =
-xive->cq_regs[CQ_XIVE_CFG >> 3] & CQ_XIVE_CFG_GEN1_TIMA_OS;
-
-offset &= TM_ADDRESS_MASK;
-
-/* TODO: should we switch the TM ops table instead ? */
-if (!gen1_tima_os && offset == HV_PULL_OS_CTX_OFFSET) {
-return xive2_tm_pull_os_ctx(xptr, tctx, offset, size);
-}
 
-/* Other TM ops are the same as XIVE1 */
 return xive_tctx_tm_read(xptr, tctx, offset, size);
 }
 
diff --git a/hw/intc/xive.c b/hw/intc/xive.c
index 34a868b185..84c079b034 100644
--- a/hw/intc/xive.c
+++ b/hw/intc/xive.c
@@ -20,6 +20,7 @@
 #include "monitor/monitor.h"
 #include "hw/irq.h"
 #include "hw/ppc/xive.h"
+#include "hw/ppc/xive2.h"
 #include "hw/ppc/xive_regs.h"
 #include "trace.h"
 
@@ -461,7 +462,7 @@ static void xive_tm_push_os_ctx(XivePresenter *xptr, 
XiveTCTX *tctx,
 }
 }
 
-static __attribute__((unused)) uint32_t 
xive_presenter_get_config(XivePresenter *xptr)
+static uint32_t xive_presenter_get_config(XivePresenter *xptr)
 {
 XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr);
 
@@ -504,14 +505,47 @@ static const XiveTmOp xive_tm_operations[] = {
 { XIVE_TM_HV_PAGE, TM_SPC_PULL_POOL_CTX,  8, NULL, xive_tm_pull_pool_ctx },
 };
 
-static const XiveTmOp *xive_tm_find_op(hwaddr offset, unsigned size, bool 
write)
+static const XiveTmOp xive2_tm_operations[] = {
+/*
+ * MMIOs below 2K : raw values and special operations without side
+ * effects
+ */
+{ XIVE_TM_OS_PAGE, TM_QW1_OS + TM_CPPR,   1, xive_tm_set_os_cppr, NULL },
+{ XIVE_TM_HV_PAGE, TM_QW1_OS + TM_WORD2,  4, xive2_tm_push_os_ctx, NULL },
+{ XIVE_TM_HV_PAGE, TM_QW3_HV_PHYS + TM_CPPR, 1, xive_tm_set_hv_cppr, NULL 
},
+{ XIVE_TM_HV_PAGE, TM_QW3_HV_PHYS + TM_WORD2, 1, xive_tm_vt_push, NULL },
+{ XIVE_TM_HV_PAGE, TM_QW3_HV_PHYS + TM_WORD2, 1, NULL, xive_tm_vt_poll },
+
+/* MMIOs above 2K : special operations with side effects */
+{ XIVE_TM

[PATCH v2 1/2] pnv/xive2: Add a get_config() method on the presenter class

2023-06-22 Thread Frederic Barrat
The presenters for xive on P9 and P10 are mostly similar but the
behavior can be tuned through a few CQ registers. This patch adds a
"get_config" method, which will allow to access that config from the
presenter in a later patch.
For now, just define the config for the TIMA version.

Signed-off-by: Frederic Barrat 
---
 hw/intc/pnv_xive.c| 11 +++
 hw/intc/pnv_xive2.c   | 12 
 hw/intc/spapr_xive.c  | 16 
 hw/intc/xive.c|  7 +++
 include/hw/ppc/xive.h |  3 +++
 5 files changed, 49 insertions(+)

diff --git a/hw/intc/pnv_xive.c b/hw/intc/pnv_xive.c
index 622f9d28b7..e536b3ec26 100644
--- a/hw/intc/pnv_xive.c
+++ b/hw/intc/pnv_xive.c
@@ -479,6 +479,16 @@ static int pnv_xive_match_nvt(XivePresenter *xptr, uint8_t 
format,
 return count;
 }
 
+static uint32_t pnv_xive_presenter_get_config(XivePresenter *xptr)
+{
+uint32_t cfg = 0;
+
+/* TIMA GEN1 is all P9 knows */
+cfg |= XIVE_PRESENTER_GEN1_TIMA_OS;
+
+return cfg;
+}
+
 static uint8_t pnv_xive_get_block_id(XiveRouter *xrtr)
 {
 return pnv_xive_block_id(PNV_XIVE(xrtr));
@@ -1991,6 +2001,7 @@ static void pnv_xive_class_init(ObjectClass *klass, void 
*data)
 
 xnc->notify = pnv_xive_notify;
 xpc->match_nvt  = pnv_xive_match_nvt;
+xpc->get_config = pnv_xive_presenter_get_config;
 };
 
 static const TypeInfo pnv_xive_info = {
diff --git a/hw/intc/pnv_xive2.c b/hw/intc/pnv_xive2.c
index ec1edeb385..59534f6843 100644
--- a/hw/intc/pnv_xive2.c
+++ b/hw/intc/pnv_xive2.c
@@ -501,6 +501,17 @@ static int pnv_xive2_match_nvt(XivePresenter *xptr, 
uint8_t format,
 return count;
 }
 
+static uint32_t pnv_xive2_presenter_get_config(XivePresenter *xptr)
+{
+PnvXive2 *xive = PNV_XIVE2(xptr);
+uint32_t cfg = 0;
+
+if (xive->cq_regs[CQ_XIVE_CFG >> 3] & CQ_XIVE_CFG_GEN1_TIMA_OS) {
+cfg |= XIVE_PRESENTER_GEN1_TIMA_OS;
+}
+return cfg;
+}
+
 static uint8_t pnv_xive2_get_block_id(Xive2Router *xrtr)
 {
 return pnv_xive2_block_id(PNV_XIVE2(xrtr));
@@ -1987,6 +1998,7 @@ static void pnv_xive2_class_init(ObjectClass *klass, void 
*data)
 xnc->notify= pnv_xive2_notify;
 
 xpc->match_nvt  = pnv_xive2_match_nvt;
+xpc->get_config = pnv_xive2_presenter_get_config;
 };
 
 static const TypeInfo pnv_xive2_info = {
diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c
index dc641cc604..8bcab2846c 100644
--- a/hw/intc/spapr_xive.c
+++ b/hw/intc/spapr_xive.c
@@ -475,6 +475,21 @@ static int spapr_xive_match_nvt(XivePresenter *xptr, 
uint8_t format,
 return count;
 }
 
+static uint32_t spapr_xive_presenter_get_config(XivePresenter *xptr)
+{
+uint32_t cfg = 0;
+
+/*
+ * Let's claim GEN1 TIMA format. If running with KVM on P10, the
+ * correct answer is deep in the hardware and not accessible to
+ * us.  But it shouldn't matter as it only affects the presenter
+ * as seen by a guest OS.
+ */
+cfg |= XIVE_PRESENTER_GEN1_TIMA_OS;
+
+return cfg;
+}
+
 static uint8_t spapr_xive_get_block_id(XiveRouter *xrtr)
 {
 return SPAPR_XIVE_BLOCK_ID;
@@ -832,6 +847,7 @@ static void spapr_xive_class_init(ObjectClass *klass, void 
*data)
 sicc->post_load = spapr_xive_post_load;
 
 xpc->match_nvt  = spapr_xive_match_nvt;
+xpc->get_config = spapr_xive_presenter_get_config;
 xpc->in_kernel  = spapr_xive_in_kernel_xptr;
 }
 
diff --git a/hw/intc/xive.c b/hw/intc/xive.c
index 5204c14b87..34a868b185 100644
--- a/hw/intc/xive.c
+++ b/hw/intc/xive.c
@@ -461,6 +461,13 @@ static void xive_tm_push_os_ctx(XivePresenter *xptr, 
XiveTCTX *tctx,
 }
 }
 
+static __attribute__((unused)) uint32_t 
xive_presenter_get_config(XivePresenter *xptr)
+{
+XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr);
+
+return xpc->get_config(xptr);
+}
+
 /*
  * Define a mapping of "special" operations depending on the TIMA page
  * offset and the size of the operation.
diff --git a/include/hw/ppc/xive.h b/include/hw/ppc/xive.h
index f7eea4ca81..3dfb06e002 100644
--- a/include/hw/ppc/xive.h
+++ b/include/hw/ppc/xive.h
@@ -430,6 +430,8 @@ typedef struct XivePresenterClass XivePresenterClass;
 DECLARE_CLASS_CHECKERS(XivePresenterClass, XIVE_PRESENTER,
TYPE_XIVE_PRESENTER)
 
+#define XIVE_PRESENTER_GEN1_TIMA_OS 0x1
+
 struct XivePresenterClass {
 InterfaceClass parent;
 int (*match_nvt)(XivePresenter *xptr, uint8_t format,
@@ -437,6 +439,7 @@ struct XivePresenterClass {
  bool cam_ignore, uint8_t priority,
  uint32_t logic_serv, XiveTCTXMatch *match);
 bool (*in_kernel)(const XivePresenter *xptr);
+uint32_t (*get_config)(XivePresenter *xptr);
 };
 
 int xive_presenter_tctx_match(XivePresenter *xptr, XiveTCTX *tctx,
-- 
2.41.0




Re: [PATCH 1/2] pnv/xive2: Add a get_config() method on the presenter class

2023-06-22 Thread Frederic Barrat




On 22/06/2023 09:01, Cédric Le Goater wrote:

On 6/21/23 18:03, Frederic Barrat wrote:

The presenters for xive on P9 and P10 are mostly similar but the
behavior can be tuned through a few CQ registers. This patch adds a
"get_config" method, which will allow to access that config from the
presenter in a later patch.
For now, just define the config for the TIMA version.

Signed-off-by: Frederic Barrat 
---
  hw/intc/pnv_xive.c    | 11 +++
  hw/intc/pnv_xive2.c   | 12 


spapr_xive.c needs an update too else QEMU will SEGV at first interrupt.



Sigh... I should really start using your qemu-ppc-boot tests.

  Fred



Thanks,

C.


  hw/intc/xive.c    |  7 +++
  include/hw/ppc/xive.h |  3 +++
  4 files changed, 33 insertions(+)

diff --git a/hw/intc/pnv_xive.c b/hw/intc/pnv_xive.c
index 622f9d28b7..e536b3ec26 100644
--- a/hw/intc/pnv_xive.c
+++ b/hw/intc/pnv_xive.c
@@ -479,6 +479,16 @@ static int pnv_xive_match_nvt(XivePresenter 
*xptr, uint8_t format,

  return count;
  }
+static uint32_t pnv_xive_presenter_get_config(XivePresenter *xptr)
+{
+    uint32_t cfg = 0;
+
+    /* TIMA GEN1 is all P9 knows */
+    cfg |= XIVE_PRESENTER_GEN1_TIMA_OS;
+
+    return cfg;
+}
+
  static uint8_t pnv_xive_get_block_id(XiveRouter *xrtr)
  {
  return pnv_xive_block_id(PNV_XIVE(xrtr));
@@ -1991,6 +2001,7 @@ static void pnv_xive_class_init(ObjectClass 
*klass, void *data)

  xnc->notify = pnv_xive_notify;
  xpc->match_nvt  = pnv_xive_match_nvt;
+    xpc->get_config = pnv_xive_presenter_get_config;
  };
  static const TypeInfo pnv_xive_info = {
diff --git a/hw/intc/pnv_xive2.c b/hw/intc/pnv_xive2.c
index ec1edeb385..59534f6843 100644
--- a/hw/intc/pnv_xive2.c
+++ b/hw/intc/pnv_xive2.c
@@ -501,6 +501,17 @@ static int pnv_xive2_match_nvt(XivePresenter 
*xptr, uint8_t format,

  return count;
  }
+static uint32_t pnv_xive2_presenter_get_config(XivePresenter *xptr)
+{
+    PnvXive2 *xive = PNV_XIVE2(xptr);
+    uint32_t cfg = 0;
+
+    if (xive->cq_regs[CQ_XIVE_CFG >> 3] & CQ_XIVE_CFG_GEN1_TIMA_OS) {
+    cfg |= XIVE_PRESENTER_GEN1_TIMA_OS;
+    }
+    return cfg;
+}
+
  static uint8_t pnv_xive2_get_block_id(Xive2Router *xrtr)
  {
  return pnv_xive2_block_id(PNV_XIVE2(xrtr));
@@ -1987,6 +1998,7 @@ static void pnv_xive2_class_init(ObjectClass 
*klass, void *data)

  xnc->notify    = pnv_xive2_notify;
  xpc->match_nvt  = pnv_xive2_match_nvt;
+    xpc->get_config = pnv_xive2_presenter_get_config;
  };
  static const TypeInfo pnv_xive2_info = {
diff --git a/hw/intc/xive.c b/hw/intc/xive.c
index 5204c14b87..34a868b185 100644
--- a/hw/intc/xive.c
+++ b/hw/intc/xive.c
@@ -461,6 +461,13 @@ static void xive_tm_push_os_ctx(XivePresenter 
*xptr, XiveTCTX *tctx,

  }
  }
+static __attribute__((unused)) uint32_t 
xive_presenter_get_config(XivePresenter *xptr)

+{
+    XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr);
+
+    return xpc->get_config(xptr);
+}
+
  /*
   * Define a mapping of "special" operations depending on the TIMA page
   * offset and the size of the operation.
diff --git a/include/hw/ppc/xive.h b/include/hw/ppc/xive.h
index f7eea4ca81..3dfb06e002 100644
--- a/include/hw/ppc/xive.h
+++ b/include/hw/ppc/xive.h
@@ -430,6 +430,8 @@ typedef struct XivePresenterClass XivePresenterClass;
  DECLARE_CLASS_CHECKERS(XivePresenterClass, XIVE_PRESENTER,
 TYPE_XIVE_PRESENTER)
+#define XIVE_PRESENTER_GEN1_TIMA_OS 0x1
+
  struct XivePresenterClass {
  InterfaceClass parent;
  int (*match_nvt)(XivePresenter *xptr, uint8_t format,
@@ -437,6 +439,7 @@ struct XivePresenterClass {
   bool cam_ignore, uint8_t priority,
   uint32_t logic_serv, XiveTCTXMatch *match);
  bool (*in_kernel)(const XivePresenter *xptr);
+    uint32_t (*get_config)(XivePresenter *xptr);
  };
  int xive_presenter_tctx_match(XivePresenter *xptr, XiveTCTX *tctx,






Re: [PATCH 0/2] pnv/xive2: Fix TIMA special ops detection

2023-06-21 Thread Frederic Barrat




On 21/06/2023 19:23, Cédric Le Goater wrote:

FYI,

It is possible to force Gen1 on XIVE2 also. It you set the "capabilities"
property on the command line :

   -global driver=pnv-xive2,property=capabilities,value=0x1000120076f000FC



Thanks, I hadn't noticed. And "config" too! Good to know...

  Fred



[PATCH 1/2] pnv/xive2: Add a get_config() method on the presenter class

2023-06-21 Thread Frederic Barrat
The presenters for xive on P9 and P10 are mostly similar but the
behavior can be tuned through a few CQ registers. This patch adds a
"get_config" method, which will allow to access that config from the
presenter in a later patch.
For now, just define the config for the TIMA version.

Signed-off-by: Frederic Barrat 
---
 hw/intc/pnv_xive.c| 11 +++
 hw/intc/pnv_xive2.c   | 12 
 hw/intc/xive.c|  7 +++
 include/hw/ppc/xive.h |  3 +++
 4 files changed, 33 insertions(+)

diff --git a/hw/intc/pnv_xive.c b/hw/intc/pnv_xive.c
index 622f9d28b7..e536b3ec26 100644
--- a/hw/intc/pnv_xive.c
+++ b/hw/intc/pnv_xive.c
@@ -479,6 +479,16 @@ static int pnv_xive_match_nvt(XivePresenter *xptr, uint8_t 
format,
 return count;
 }
 
+static uint32_t pnv_xive_presenter_get_config(XivePresenter *xptr)
+{
+uint32_t cfg = 0;
+
+/* TIMA GEN1 is all P9 knows */
+cfg |= XIVE_PRESENTER_GEN1_TIMA_OS;
+
+return cfg;
+}
+
 static uint8_t pnv_xive_get_block_id(XiveRouter *xrtr)
 {
 return pnv_xive_block_id(PNV_XIVE(xrtr));
@@ -1991,6 +2001,7 @@ static void pnv_xive_class_init(ObjectClass *klass, void 
*data)
 
 xnc->notify = pnv_xive_notify;
 xpc->match_nvt  = pnv_xive_match_nvt;
+xpc->get_config = pnv_xive_presenter_get_config;
 };
 
 static const TypeInfo pnv_xive_info = {
diff --git a/hw/intc/pnv_xive2.c b/hw/intc/pnv_xive2.c
index ec1edeb385..59534f6843 100644
--- a/hw/intc/pnv_xive2.c
+++ b/hw/intc/pnv_xive2.c
@@ -501,6 +501,17 @@ static int pnv_xive2_match_nvt(XivePresenter *xptr, 
uint8_t format,
 return count;
 }
 
+static uint32_t pnv_xive2_presenter_get_config(XivePresenter *xptr)
+{
+PnvXive2 *xive = PNV_XIVE2(xptr);
+uint32_t cfg = 0;
+
+if (xive->cq_regs[CQ_XIVE_CFG >> 3] & CQ_XIVE_CFG_GEN1_TIMA_OS) {
+cfg |= XIVE_PRESENTER_GEN1_TIMA_OS;
+}
+return cfg;
+}
+
 static uint8_t pnv_xive2_get_block_id(Xive2Router *xrtr)
 {
 return pnv_xive2_block_id(PNV_XIVE2(xrtr));
@@ -1987,6 +1998,7 @@ static void pnv_xive2_class_init(ObjectClass *klass, void 
*data)
 xnc->notify= pnv_xive2_notify;
 
 xpc->match_nvt  = pnv_xive2_match_nvt;
+xpc->get_config = pnv_xive2_presenter_get_config;
 };
 
 static const TypeInfo pnv_xive2_info = {
diff --git a/hw/intc/xive.c b/hw/intc/xive.c
index 5204c14b87..34a868b185 100644
--- a/hw/intc/xive.c
+++ b/hw/intc/xive.c
@@ -461,6 +461,13 @@ static void xive_tm_push_os_ctx(XivePresenter *xptr, 
XiveTCTX *tctx,
 }
 }
 
+static __attribute__((unused)) uint32_t 
xive_presenter_get_config(XivePresenter *xptr)
+{
+XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr);
+
+return xpc->get_config(xptr);
+}
+
 /*
  * Define a mapping of "special" operations depending on the TIMA page
  * offset and the size of the operation.
diff --git a/include/hw/ppc/xive.h b/include/hw/ppc/xive.h
index f7eea4ca81..3dfb06e002 100644
--- a/include/hw/ppc/xive.h
+++ b/include/hw/ppc/xive.h
@@ -430,6 +430,8 @@ typedef struct XivePresenterClass XivePresenterClass;
 DECLARE_CLASS_CHECKERS(XivePresenterClass, XIVE_PRESENTER,
TYPE_XIVE_PRESENTER)
 
+#define XIVE_PRESENTER_GEN1_TIMA_OS 0x1
+
 struct XivePresenterClass {
 InterfaceClass parent;
 int (*match_nvt)(XivePresenter *xptr, uint8_t format,
@@ -437,6 +439,7 @@ struct XivePresenterClass {
  bool cam_ignore, uint8_t priority,
  uint32_t logic_serv, XiveTCTXMatch *match);
 bool (*in_kernel)(const XivePresenter *xptr);
+uint32_t (*get_config)(XivePresenter *xptr);
 };
 
 int xive_presenter_tctx_match(XivePresenter *xptr, XiveTCTX *tctx,
-- 
2.41.0




[PATCH 2/2] pnv/xive2: Check TIMA special ops against a dedicated array for P10

2023-06-21 Thread Frederic Barrat
Accessing the TIMA from some specific ring/offset combination can
trigger a special operation, with or without side effects. It is
implemented in qemu with an array of special operations to compare
accesses against. Since the presenter on P10 is pretty similar to P9,
we had the full array defined for P9 and we just had a special case
for P10 to treat one access differently. With a recent change,
6f2cbd133d4 ("pnv/xive2: Handle TIMA access through all ports"), we
now ignore some of the bits of the TIMA address, but that patch
managed to botch the detection of the special case for P10.

To clean that up, this patch introduces a full array of special ops to
be used for P10. The code to detect a special access is common with
P9, only the array of operations differs. The presenter can pick the
correct array of special ops based on its configuration introduced in
a previous patch.

Fixes: Coverity CID 1512997, 1512998
Fixes: 6f2cbd133d4 ("pnv/xive2: Handle TIMA access through all ports")
Signed-off-by: Frederic Barrat 
---
 hw/intc/pnv_xive2.c | 32 
 hw/intc/xive.c  | 52 +
 2 files changed, 43 insertions(+), 41 deletions(-)

diff --git a/hw/intc/pnv_xive2.c b/hw/intc/pnv_xive2.c
index 59534f6843..ed438a20ed 100644
--- a/hw/intc/pnv_xive2.c
+++ b/hw/intc/pnv_xive2.c
@@ -1656,17 +1656,6 @@ static const MemoryRegionOps 
pnv_xive2_ic_tm_indirect_ops = {
 /*
  * TIMA ops
  */
-
-/*
- * Special TIMA offsets to handle accesses in a POWER10 way.
- *
- * Only the CAM line updates done by the hypervisor should be handled
- * specifically.
- */
-#define HV_PAGE_OFFSET (XIVE_TM_HV_PAGE << TM_SHIFT)
-#define HV_PUSH_OS_CTX_OFFSET  (HV_PAGE_OFFSET | (TM_QW1_OS + TM_WORD2))
-#define HV_PULL_OS_CTX_OFFSET  (HV_PAGE_OFFSET | TM_SPC_PULL_OS_CTX)
-
 static void pnv_xive2_tm_write(void *opaque, hwaddr offset,
uint64_t value, unsigned size)
 {
@@ -1674,18 +1663,7 @@ static void pnv_xive2_tm_write(void *opaque, hwaddr 
offset,
 PnvXive2 *xive = pnv_xive2_tm_get_xive(cpu);
 XiveTCTX *tctx = XIVE_TCTX(pnv_cpu_state(cpu)->intc);
 XivePresenter *xptr = XIVE_PRESENTER(xive);
-bool gen1_tima_os =
-xive->cq_regs[CQ_XIVE_CFG >> 3] & CQ_XIVE_CFG_GEN1_TIMA_OS;
-
-offset &= TM_ADDRESS_MASK;
 
-/* TODO: should we switch the TM ops table instead ? */
-if (!gen1_tima_os && offset == HV_PUSH_OS_CTX_OFFSET) {
-xive2_tm_push_os_ctx(xptr, tctx, offset, value, size);
-return;
-}
-
-/* Other TM ops are the same as XIVE1 */
 xive_tctx_tm_write(xptr, tctx, offset, value, size);
 }
 
@@ -1695,17 +1673,7 @@ static uint64_t pnv_xive2_tm_read(void *opaque, hwaddr 
offset, unsigned size)
 PnvXive2 *xive = pnv_xive2_tm_get_xive(cpu);
 XiveTCTX *tctx = XIVE_TCTX(pnv_cpu_state(cpu)->intc);
 XivePresenter *xptr = XIVE_PRESENTER(xive);
-bool gen1_tima_os =
-xive->cq_regs[CQ_XIVE_CFG >> 3] & CQ_XIVE_CFG_GEN1_TIMA_OS;
-
-offset &= TM_ADDRESS_MASK;
-
-/* TODO: should we switch the TM ops table instead ? */
-if (!gen1_tima_os && offset == HV_PULL_OS_CTX_OFFSET) {
-return xive2_tm_pull_os_ctx(xptr, tctx, offset, size);
-}
 
-/* Other TM ops are the same as XIVE1 */
 return xive_tctx_tm_read(xptr, tctx, offset, size);
 }
 
diff --git a/hw/intc/xive.c b/hw/intc/xive.c
index 34a868b185..84c079b034 100644
--- a/hw/intc/xive.c
+++ b/hw/intc/xive.c
@@ -20,6 +20,7 @@
 #include "monitor/monitor.h"
 #include "hw/irq.h"
 #include "hw/ppc/xive.h"
+#include "hw/ppc/xive2.h"
 #include "hw/ppc/xive_regs.h"
 #include "trace.h"
 
@@ -461,7 +462,7 @@ static void xive_tm_push_os_ctx(XivePresenter *xptr, 
XiveTCTX *tctx,
 }
 }
 
-static __attribute__((unused)) uint32_t 
xive_presenter_get_config(XivePresenter *xptr)
+static uint32_t xive_presenter_get_config(XivePresenter *xptr)
 {
 XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr);
 
@@ -504,14 +505,47 @@ static const XiveTmOp xive_tm_operations[] = {
 { XIVE_TM_HV_PAGE, TM_SPC_PULL_POOL_CTX,  8, NULL, xive_tm_pull_pool_ctx },
 };
 
-static const XiveTmOp *xive_tm_find_op(hwaddr offset, unsigned size, bool 
write)
+static const XiveTmOp xive2_tm_operations[] = {
+/*
+ * MMIOs below 2K : raw values and special operations without side
+ * effects
+ */
+{ XIVE_TM_OS_PAGE, TM_QW1_OS + TM_CPPR,   1, xive_tm_set_os_cppr, NULL },
+{ XIVE_TM_HV_PAGE, TM_QW1_OS + TM_WORD2,  4, xive2_tm_push_os_ctx, NULL },
+{ XIVE_TM_HV_PAGE, TM_QW3_HV_PHYS + TM_CPPR, 1, xive_tm_set_hv_cppr, NULL 
},
+{ XIVE_TM_HV_PAGE, TM_QW3_HV_PHYS + TM_WORD2, 1, xive_tm_vt_push, NULL },
+{ XIVE_TM_HV_PAGE, TM_QW3_HV_PHYS + TM_WORD2, 1, NULL, xive_tm_vt_poll },
+
+/* MMIOs above 2K : special operations with side effects */
+{ XIVE_TM

[PATCH 0/2] pnv/xive2: Fix TIMA special ops detection

2023-06-21 Thread Frederic Barrat
Fix the TIMA special ops detection regression, as spotted by Coverity.

Tested by running a pseries guest on top of a powernv9 and powernv10 host.

Frederic Barrat (2):
  pnv/xive2: Add a get_config() method on the presenter class
  pnv/xive2: Check TIMA special ops against a dedicated array for P10

 hw/intc/pnv_xive.c| 11 +
 hw/intc/pnv_xive2.c   | 44 +
 hw/intc/xive.c| 57 +--
 include/hw/ppc/xive.h |  3 +++
 4 files changed, 75 insertions(+), 40 deletions(-)

-- 
2.41.0




Re: [PULL 05/29] pnv/xive2: Handle TIMA access through all ports

2023-06-21 Thread Frederic Barrat




On 21/06/2023 09:18, Cédric Le Goater wrote:

The XIVE2 TM ops are implemented with a shortcut (See the TODO in
pnv_xive2_tm_*()). We could

1. extend xive_tctx_tm_write/read with a 'bool gen1_tima_os' parameter:

 xive_tctx_tm_write(xptr, tctx, offset, value, size, gen1_tima_os);

    and use the bool in xive_tm_find_op() to select a XiveTmOp array.
    The new xive2_tm_operations[] would be defined as xive_tm_operations[]
    but with an override of HV_PUSH_OS_CTX_OFFSET and 
HV_PULL_OS_CTX_OFFSET.


2. or extend the XivePresenterClass with a get_config() handler like it
    was done for Xive2RouterClass().

3. or introduce an array of XiveTmOp under XivePresenterClass defined by
    the controller variant.

In any case, we need a new xive2_tm_operations[] for the XIVE2 TM register
layout. Option 1 is simpler I think.



I was also leaning on introducing a xive2_tm_operations[] array of 
operations to fix it correctly.


While I agree it's the simplest, I'm not fond of (1), since we'd need to 
carry that extra parameter to xive_tm_find_op(). Admittedly it's just 
one extra level, but I went with something which is hopefully what you 
had in mind for (2). I like that we can easily extend it in the future.




This would  also "fix" the indirect ops in XIVE2, not that we care much
but it will be cleaner.


I'm not sure I see what you mean here. It cleans up nicely 
pnv_xive2_tm_read/write(), but is that really what you had in mind?



Something related I notice is that when doing an indirect access to the 
TIMA through the IC BAR, we call the TIMA access functions with a NULL 
reference to the presenter:


static uint64_t pnv_xive2_ic_tm_indirect_read(void *opaque, hwaddr offset,
  unsigned size)
{
PnvXive2 *xive = PNV_XIVE2(opaque);
...
tctx = pnv_xive2_get_indirect_tctx(xive, pir);
if (tctx) {
val = xive_tctx_tm_read(NULL, tctx, offset, size);
}

We seem to mostly ignore that first parameter in 
xive_tctx_tm_read/write(). IIUC, the special ops will be checked with a 
page offset matching ring 0 and won't match anything. Still, it seems a 
bit dangerous and I was wondering:

1. can't we just create it from the PnvXive2 we have at hand?
2. in any case, isn't it always redundant with tctxt->presenter?

  Fred



Re: [PULL 05/29] pnv/xive2: Handle TIMA access through all ports

2023-06-20 Thread Frederic Barrat




On 20/06/2023 13:20, Cédric Le Goater wrote:

On 6/20/23 12:45, Peter Maydell wrote:

On Sat, 10 Jun 2023 at 14:31, Daniel Henrique Barboza
 wrote:


From: Frederic Barrat 

The Thread Interrupt Management Area (TIMA) can be accessed through 4
ports, targeted by the address. The base address of a TIMA
is using port 0 and the other ports are 0x80 apart. Using one port or
another can be useful to balance the load on the snoop buses. With
skiboot and linux, we currently use port 0, but as it tends to be
busy, another hypervisor is using port 1 for TIMA access.

The port address bits fall in between the special op indication
bits (the 2 MSBs) and the register offset bits (the 6 LSBs). They are
"don't care" for the hardware when processing a TIMA operation. This
patch filters out those port address bits so that a TIMA operation can
be triggered using any port.

It is also true for indirect access (through the IC BAR) and it's
actually nothing new, it was already the case on P9. Which helps here,
as the TIMA handling code is common between P9 (xive) and P10 (xive2).

Signed-off-by: Frederic Barrat 
Reviewed-by: Cédric Le Goater 
Message-Id: <20230601121331.487207-6-fbar...@linux.ibm.com>
Signed-off-by: Daniel Henrique Barboza 
---


Hi -- Coverity points out that there's a problem with this
change (CID 1512997, 1512998):


--- a/hw/intc/pnv_xive2.c
+++ b/hw/intc/pnv_xive2.c
@@ -1662,6 +1662,8 @@ static void pnv_xive2_tm_write(void *opaque, 
hwaddr offset,

  bool gen1_tima_os =
  xive->cq_regs[CQ_XIVE_CFG >> 3] & CQ_XIVE_CFG_GEN1_TIMA_OS;

+    offset &= TM_ADDRESS_MASK;


Here we now mask off most of the bytes of 'offset',
because TM_ADDRESS_MASK is 0xC3F...


+
  /* TODO: should we switch the TM ops table instead ? */
  if (!gen1_tima_os && offset == HV_PUSH_OS_CTX_OFFSET) {


...but here we compare offset against HV_PUSH_OS_CTX_OFFSET,
which is defined as
#define HV_PUSH_OS_CTX_OFFSET  (HV_PAGE_OFFSET | (TM_QW1_OS + TM_WORD2))
and since
#define HV_PAGE_OFFSET (XIVE_TM_HV_PAGE << TM_SHIFT)
#define XIVE_TM_HV_PAGE 0x1
#define TM_SHIFT    16

that means HV_PUSH_OS_CTX_OFFSET has bits defined in the
upper 16 bits, and the comparison can now never be true,
making the if() dead code.


  xive2_tm_push_os_ctx(xptr, tctx, offset, value, size);
@@ -1681,6 +1683,8 @@ static uint64_t pnv_xive2_tm_read(void *opaque, 
hwaddr offset, unsigned size)

  bool gen1_tima_os =
  xive->cq_regs[CQ_XIVE_CFG >> 3] & CQ_XIVE_CFG_GEN1_TIMA_OS;

+    offset &= TM_ADDRESS_MASK;
+
  /* TODO: should we switch the TM ops table instead ? */
  if (!gen1_tima_os && offset == HV_PULL_OS_CTX_OFFSET) {
  return xive2_tm_pull_os_ctx(xptr, tctx, offset, size);


Similarly here.



yes. I think this went unnoticed because the push/pull os context
commands are only used by the HV when a vCPU is dipatched on a HW
thread. We would need a test for a KVM guest running under the QEMU
PowerNV POWER10 machine. This requires an image with some tuning
because emulation is a bit slow. I use to have a buildroot image
including a qemu and smaller buildroot image for it.



Working on a fix. It's true that I hadn't run a guest within the powernv 
machine for quite a while. I'm dusting off my buildroot repo to test it 
this time...


  Fred




So, offset is within the full TIMA region (4 pages) and
TM_ADDRESS_MASK is a mask within a page. This needs a fix.

Thanks,

C.





Re: [PATCH 3/9] MAINTAINERS: Add reviewer for XIVE

2023-06-20 Thread Frederic Barrat




On 20/06/2023 07:59, Cédric Le Goater wrote:

Fred discusses frequently with the IBM HW designers, he is fluent in
XIVE logic, add him as a reviewer.

Cc: Frédéric Barrat 
Signed-off-by: Cédric Le Goater 
---


Acked-by: Frederic Barrat 

  Fred



  MAINTAINERS | 1 +
  1 file changed, 1 insertion(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 90fb83c4cb58..2e8c715eaca4 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2445,6 +2445,7 @@ T: git https://github.com/philmd/qemu.git fw_cfg-next
  
  XIVE

  M: Cédric Le Goater 
+R: Frédéric Barrat 
  L: qemu-...@nongnu.org
  S: Odd Fixes
  F: hw/*/*xive*




Re: [PATCH 1/9] MAINTAINERS: Add reviewers for PowerNV baremetal emulation

2023-06-20 Thread Frederic Barrat




On 20/06/2023 07:59, Cédric Le Goater wrote:

Fred and Nick have been hacking baremetal POWER systems (OPAL) for
many years. They use and modify the QEMU models regularly. Add them as
PowerNV reviewers.

Cc: Frédéric Barrat 
Cc: Nicholas Piggin 
Signed-off-by: Cédric Le Goater 
---



Acked-by: Frederic Barrat 

  Fred



  MAINTAINERS | 2 ++
  1 file changed, 2 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 88b5a7ee0a79..e6f3dade2230 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1448,6 +1448,8 @@ F: tests/avocado/ppc_pseries.py
  
  PowerNV (Non-Virtualized)

  M: Cédric Le Goater 
+R: Frédéric Barrat 
+R: Nicholas Piggin 
  L: qemu-...@nongnu.org
  S: Odd Fixes
  F: docs/system/ppc/powernv.rst




[PATCH v2 3/5] pnv/xive2: Allow writes to the Physical Thread Enable registers

2023-06-01 Thread Frederic Barrat
Fix what was probably a silly mistake and allow to write the Physical
Thread enable registers 0 and 1. Skiboot prefers to use the ENx_SET
variant so it went unnoticed, but there's no reason to discard a write
to the full register, it is Read-Write.

Fixes: da71b7e3ed45 ("ppc/pnv: Add a XIVE2 controller to the POWER10 chip")
Signed-off-by: Frederic Barrat 
Reviewed-by: Cédric Le Goater 
---
 hw/intc/pnv_xive2.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/hw/intc/pnv_xive2.c b/hw/intc/pnv_xive2.c
index 9778c102ff..5fc4240216 100644
--- a/hw/intc/pnv_xive2.c
+++ b/hw/intc/pnv_xive2.c
@@ -1298,6 +1298,7 @@ static void pnv_xive2_ic_tctxt_write(void *opaque, hwaddr 
offset,
  */
 case TCTXT_EN0: /* Physical Thread Enable */
 case TCTXT_EN1: /* Physical Thread Enable (fused core) */
+xive->tctxt_regs[reg] = val;
 break;
 
 case TCTXT_EN0_SET:
-- 
2.40.1




[PATCH v2 4/5] pnv/xive2: Introduce macros to manipulate TIMA addresses

2023-06-01 Thread Frederic Barrat
TIMA addresses are somewhat special and are split in several bit
fields with different meanings. This patch describes it and introduce
macros to more easily access the various fields.

Signed-off-by: Frederic Barrat 
---
 hw/intc/xive.c | 14 +++---
 include/hw/ppc/xive_regs.h | 16 
 2 files changed, 23 insertions(+), 7 deletions(-)

diff --git a/hw/intc/xive.c b/hw/intc/xive.c
index a986b96843..ebe399bc09 100644
--- a/hw/intc/xive.c
+++ b/hw/intc/xive.c
@@ -249,7 +249,7 @@ static const uint8_t *xive_tm_views[] = {
 static uint64_t xive_tm_mask(hwaddr offset, unsigned size, bool write)
 {
 uint8_t page_offset = (offset >> TM_SHIFT) & 0x3;
-uint8_t reg_offset = offset & 0x3F;
+uint8_t reg_offset = offset & TM_REG_OFFSET;
 uint8_t reg_mask = write ? 0x1 : 0x2;
 uint64_t mask = 0x0;
 int i;
@@ -266,8 +266,8 @@ static uint64_t xive_tm_mask(hwaddr offset, unsigned size, 
bool write)
 static void xive_tm_raw_write(XiveTCTX *tctx, hwaddr offset, uint64_t value,
   unsigned size)
 {
-uint8_t ring_offset = offset & 0x30;
-uint8_t reg_offset = offset & 0x3F;
+uint8_t ring_offset = offset & TM_RING_OFFSET;
+uint8_t reg_offset = offset & TM_REG_OFFSET;
 uint64_t mask = xive_tm_mask(offset, size, true);
 int i;
 
@@ -296,8 +296,8 @@ static void xive_tm_raw_write(XiveTCTX *tctx, hwaddr 
offset, uint64_t value,
 
 static uint64_t xive_tm_raw_read(XiveTCTX *tctx, hwaddr offset, unsigned size)
 {
-uint8_t ring_offset = offset & 0x30;
-uint8_t reg_offset = offset & 0x3F;
+uint8_t ring_offset = offset & TM_RING_OFFSET;
+uint8_t reg_offset = offset & TM_REG_OFFSET;
 uint64_t mask = xive_tm_mask(offset, size, false);
 uint64_t ret;
 int i;
@@ -534,7 +534,7 @@ void xive_tctx_tm_write(XivePresenter *xptr, XiveTCTX 
*tctx, hwaddr offset,
 /*
  * First, check for special operations in the 2K region
  */
-if (offset & 0x800) {
+if (offset & TM_SPECIAL_OP) {
 xto = xive_tm_find_op(offset, size, true);
 if (!xto) {
 qemu_log_mask(LOG_GUEST_ERROR, "XIVE: invalid write access at TIMA 
"
@@ -573,7 +573,7 @@ uint64_t xive_tctx_tm_read(XivePresenter *xptr, XiveTCTX 
*tctx, hwaddr offset,
 /*
  * First, check for special operations in the 2K region
  */
-if (offset & 0x800) {
+if (offset & TM_SPECIAL_OP) {
 xto = xive_tm_find_op(offset, size, false);
 if (!xto) {
 qemu_log_mask(LOG_GUEST_ERROR, "XIVE: invalid read access to TIMA"
diff --git a/include/hw/ppc/xive_regs.h b/include/hw/ppc/xive_regs.h
index b7fde2354e..4a3c9badd3 100644
--- a/include/hw/ppc/xive_regs.h
+++ b/include/hw/ppc/xive_regs.h
@@ -48,6 +48,22 @@
 
 #define TM_SHIFT16
 
+/*
+ * TIMA addresses are 12-bits (4k page).
+ * The MSB indicates a special op with side effect, which can be
+ * refined with bit 10 (see below).
+ * The registers, logically grouped in 4 rings (a quad-word each), are
+ * defined on the 6 LSBs (offset below 0x40)
+ * In between, we can add a cache line index from 0...3 (ie, 0, 0x80,
+ * 0x100, 0x180) to select a specific snooper. Those 'snoop port
+ * address' bits should be dropped when processing the operations as
+ * they are all equivalent.
+ */
+#define TM_ADDRESS_MASK 0xC3F
+#define TM_SPECIAL_OP   0x800
+#define TM_RING_OFFSET  0x30
+#define TM_REG_OFFSET   0x3F
+
 /* TM register offsets */
 #define TM_QW0_USER 0x000 /* All rings */
 #define TM_QW1_OS   0x010 /* Ring 0..2 */
-- 
2.40.1




[PATCH v2 5/5] pnv/xive2: Handle TIMA access through all ports

2023-06-01 Thread Frederic Barrat
The Thread Interrupt Management Area (TIMA) can be accessed through 4
ports, targeted by the address. The base address of a TIMA
is using port 0 and the other ports are 0x80 apart. Using one port or
another can be useful to balance the load on the snoop buses. With
skiboot and linux, we currently use port 0, but as it tends to be
busy, another hypervisor is using port 1 for TIMA access.

The port address bits fall in between the special op indication
bits (the 2 MSBs) and the register offset bits (the 6 LSBs). They are
"don't care" for the hardware when processing a TIMA operation. This
patch filters out those port address bits so that a TIMA operation can
be triggered using any port.

It is also true for indirect access (through the IC BAR) and it's
actually nothing new, it was already the case on P9. Which helps here,
as the TIMA handling code is common between P9 (xive) and P10 (xive2).

Signed-off-by: Frederic Barrat 
---
 hw/intc/pnv_xive2.c | 4 
 hw/intc/xive.c  | 2 +-
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/hw/intc/pnv_xive2.c b/hw/intc/pnv_xive2.c
index 5fc4240216..ec1edeb385 100644
--- a/hw/intc/pnv_xive2.c
+++ b/hw/intc/pnv_xive2.c
@@ -1666,6 +1666,8 @@ static void pnv_xive2_tm_write(void *opaque, hwaddr 
offset,
 bool gen1_tima_os =
 xive->cq_regs[CQ_XIVE_CFG >> 3] & CQ_XIVE_CFG_GEN1_TIMA_OS;
 
+offset &= TM_ADDRESS_MASK;
+
 /* TODO: should we switch the TM ops table instead ? */
 if (!gen1_tima_os && offset == HV_PUSH_OS_CTX_OFFSET) {
 xive2_tm_push_os_ctx(xptr, tctx, offset, value, size);
@@ -1685,6 +1687,8 @@ static uint64_t pnv_xive2_tm_read(void *opaque, hwaddr 
offset, unsigned size)
 bool gen1_tima_os =
 xive->cq_regs[CQ_XIVE_CFG >> 3] & CQ_XIVE_CFG_GEN1_TIMA_OS;
 
+offset &= TM_ADDRESS_MASK;
+
 /* TODO: should we switch the TM ops table instead ? */
 if (!gen1_tima_os && offset == HV_PULL_OS_CTX_OFFSET) {
 return xive2_tm_pull_os_ctx(xptr, tctx, offset, size);
diff --git a/hw/intc/xive.c b/hw/intc/xive.c
index ebe399bc09..5204c14b87 100644
--- a/hw/intc/xive.c
+++ b/hw/intc/xive.c
@@ -500,7 +500,7 @@ static const XiveTmOp xive_tm_operations[] = {
 static const XiveTmOp *xive_tm_find_op(hwaddr offset, unsigned size, bool 
write)
 {
 uint8_t page_offset = (offset >> TM_SHIFT) & 0x3;
-uint32_t op_offset = offset & 0xFFF;
+uint32_t op_offset = offset & TM_ADDRESS_MASK;
 int i;
 
 for (i = 0; i < ARRAY_SIZE(xive_tm_operations); i++) {
-- 
2.40.1




[PATCH v2 0/5] Various xive fixes

2023-06-01 Thread Frederic Barrat
A set of small fixes for the interrupt controller (xive2) on P10.

Change log:
v2:
  split last patch to do a bit of cleanup first
  add Cedric's reviewed-by on the first 3 patches

Frederic Barrat (5):
  pnv/xive2: Add definition for TCTXT Config register
  pnv/xive2: Add definition for the ESB cache configuration register
  pnv/xive2: Allow writes to the Physical Thread Enable registers
  pnv/xive2: Introduce macros to manipulate TIMA addresses
  pnv/xive2: Handle TIMA access through all ports

 hw/intc/pnv_xive2.c| 20 +++-
 hw/intc/pnv_xive2_regs.h   |  8 
 hw/intc/xive.c | 16 
 include/hw/ppc/xive_regs.h | 16 
 4 files changed, 51 insertions(+), 9 deletions(-)

-- 
2.40.1




[PATCH v2 2/5] pnv/xive2: Add definition for the ESB cache configuration register

2023-06-01 Thread Frederic Barrat
Add basic read/write support for the ESB cache configuration register
on P10. We don't model the ESB cache in qemu so reading/writing the
register won't do anything, but it avoids logging a guest error when
skiboot configures it:

qemu-system-ppc64 -machine powernv10 ... -d guest_errors
  ...
XIVE[0] - VC: invalid read @240
XIVE[0] - VC: invalid write @240

Signed-off-by: Frederic Barrat 
Reviewed-by: Cédric Le Goater 
---
 hw/intc/pnv_xive2.c  | 7 +++
 hw/intc/pnv_xive2_regs.h | 4 
 2 files changed, 11 insertions(+)

diff --git a/hw/intc/pnv_xive2.c b/hw/intc/pnv_xive2.c
index f0817a124f..9778c102ff 100644
--- a/hw/intc/pnv_xive2.c
+++ b/hw/intc/pnv_xive2.c
@@ -959,6 +959,10 @@ static uint64_t pnv_xive2_ic_vc_read(void *opaque, hwaddr 
offset,
 val = xive->vc_regs[reg];
 break;
 
+case VC_ESBC_CFG:
+val = xive->vc_regs[reg];
+break;
+
 /*
  * EAS cache updates (not modeled)
  */
@@ -1050,6 +1054,9 @@ static void pnv_xive2_ic_vc_write(void *opaque, hwaddr 
offset,
 /* ESB update */
 break;
 
+case VC_ESBC_CFG:
+break;
+
 /*
  * EAS cache updates (not modeled)
  */
diff --git a/hw/intc/pnv_xive2_regs.h b/hw/intc/pnv_xive2_regs.h
index 8f1e0a1fde..7165dc8704 100644
--- a/hw/intc/pnv_xive2_regs.h
+++ b/hw/intc/pnv_xive2_regs.h
@@ -232,6 +232,10 @@
 #define  VC_ESBC_FLUSH_POLL_BLOCK_ID_MASK   PPC_BITMASK(32, 35)
 #define  VC_ESBC_FLUSH_POLL_OFFSET_MASK PPC_BITMASK(36, 63) /* 28-bit 
*/
 
+/* ESBC configuration */
+#define X_VC_ESBC_CFG   0x148
+#define VC_ESBC_CFG 0x240
+
 /* EASC flush control register */
 #define X_VC_EASC_FLUSH_CTRL0x160
 #define VC_EASC_FLUSH_CTRL  0x300
-- 
2.40.1




[PATCH v2 1/5] pnv/xive2: Add definition for TCTXT Config register

2023-06-01 Thread Frederic Barrat
Add basic read/write support for the TCTXT Config register on P10. qemu
doesn't do anything with it yet, but it avoids logging a guest error
when skiboot configures the fused-core state:

qemu-system-ppc64 -machine powernv10 ... -d guest_errors
  ...
[0.13167,5] XIVE: [ IC 00  ] Initializing XIVE block ID 0...
XIVE[0] - TCTXT: invalid read @140
XIVE[0] - TCTXT: invalid write @140

Signed-off-by: Frederic Barrat 
Reviewed-by: Cédric Le Goater 
---
 hw/intc/pnv_xive2.c  | 8 +++-
 hw/intc/pnv_xive2_regs.h | 4 
 2 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/hw/intc/pnv_xive2.c b/hw/intc/pnv_xive2.c
index e688381536..f0817a124f 100644
--- a/hw/intc/pnv_xive2.c
+++ b/hw/intc/pnv_xive2.c
@@ -1269,6 +1269,9 @@ static uint64_t pnv_xive2_ic_tctxt_read(void *opaque, 
hwaddr offset,
 case TCTXT_EN1_RESET:
 val = xive->tctxt_regs[TCTXT_EN1 >> 3];
 break;
+case TCTXT_CFG:
+val = xive->tctxt_regs[reg];
+break;
 default:
 xive2_error(xive, "TCTXT: invalid read @%"HWADDR_PRIx, offset);
 }
@@ -1280,6 +1283,7 @@ static void pnv_xive2_ic_tctxt_write(void *opaque, hwaddr 
offset,
  uint64_t val, unsigned size)
 {
 PnvXive2 *xive = PNV_XIVE2(opaque);
+uint32_t reg = offset >> 3;
 
 switch (offset) {
 /*
@@ -1301,7 +1305,9 @@ static void pnv_xive2_ic_tctxt_write(void *opaque, hwaddr 
offset,
 case TCTXT_EN1_RESET:
 xive->tctxt_regs[TCTXT_EN1 >> 3] &= ~val;
 break;
-
+case TCTXT_CFG:
+xive->tctxt_regs[reg] = val;
+break;
 default:
 xive2_error(xive, "TCTXT: invalid write @%"HWADDR_PRIx, offset);
 return;
diff --git a/hw/intc/pnv_xive2_regs.h b/hw/intc/pnv_xive2_regs.h
index 0c096e4adb..8f1e0a1fde 100644
--- a/hw/intc/pnv_xive2_regs.h
+++ b/hw/intc/pnv_xive2_regs.h
@@ -405,6 +405,10 @@
 #define X_TCTXT_EN1_RESET   0x307
 #define TCTXT_EN1_RESET 0x038
 
+/* TCTXT Config register */
+#define X_TCTXT_CFG 0x328
+#define TCTXT_CFG   0x140
+
 /*
  * VSD Tables
  */
-- 
2.40.1




[PATCH] pnv/xive2: Quiet down some error messages

2023-05-31 Thread Frederic Barrat
When dumping the END and NVP tables ("info pic" from the HMP) on the
P10 model, we're likely to be flooded with error messages such as:

  XIVE[0] - VST: invalid NVPT entry f33800 !?

The error is printed when finding an empty VSD in an indirect
table (thus END and NVP tables with skiboot), which is going to happen
when dumping the xive state. So let's tune down those messages. They
can be re-enabled easily with a macro if needed.

Those errors were already hidden on xive/P9, for the same reason.

Signed-off-by: Frederic Barrat 
---
 hw/intc/pnv_xive2.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/hw/intc/pnv_xive2.c b/hw/intc/pnv_xive2.c
index c80316657a..397679390c 100644
--- a/hw/intc/pnv_xive2.c
+++ b/hw/intc/pnv_xive2.c
@@ -163,7 +163,9 @@ static uint64_t pnv_xive2_vst_addr_indirect(PnvXive2 *xive, 
uint32_t type,
 ldq_be_dma(_space_memory, vsd_addr, , MEMTXATTRS_UNSPECIFIED);
 
 if (!(vsd & VSD_ADDRESS_MASK)) {
+#ifdef XIVE2_DEBUG
 xive2_error(xive, "VST: invalid %s entry %x !?", info->name, idx);
+#endif
 return 0;
 }
 
@@ -185,7 +187,9 @@ static uint64_t pnv_xive2_vst_addr_indirect(PnvXive2 *xive, 
uint32_t type,
MEMTXATTRS_UNSPECIFIED);
 
 if (!(vsd & VSD_ADDRESS_MASK)) {
+#ifdef XIVE2_DEBUG
 xive2_error(xive, "VST: invalid %s entry %x !?", info->name, idx);
+#endif
 return 0;
 }
 
-- 
2.40.1




Re: [PATCH 1/4] pnv/xive2: Add definition for TCTXT Config register

2023-05-30 Thread Frederic Barrat




On 30/05/2023 18:31, Cédric Le Goater wrote:

On 5/30/23 18:11, Frederic Barrat wrote:

Add basic read/write support for the TCTXT Config register on P10. qemu
doesn't do anything with it yet, but it avoids logging a guest error
when skiboot configures the fused-core state:

qemu-system-ppc64 -machine powernv10 ... -d guest_errors
   ...
[    0.13167,5] XIVE: [ IC 00  ] Initializing XIVE block ID 0...
XIVE[0] - TCTXT: invalid read @140
XIVE[0] - TCTXT: invalid write @140


Reviewed-by: Cédric Le Goater 

If you respin, please add the same kind of support to POWER9.



It's already in place for read and write:

static void pnv_xive_ic_reg_write()
...
  case PC_TCTXT_CFG:


Skiboot is using it and we don't get an error message, even with 
guest_errors. So it looks good.


 Fred




Thanks,

C.



Signed-off-by: Frederic Barrat 
---
  hw/intc/pnv_xive2.c  | 8 +++-
  hw/intc/pnv_xive2_regs.h | 4 
  2 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/hw/intc/pnv_xive2.c b/hw/intc/pnv_xive2.c
index 7176d70234..889e409929 100644
--- a/hw/intc/pnv_xive2.c
+++ b/hw/intc/pnv_xive2.c
@@ -1265,6 +1265,9 @@ static uint64_t pnv_xive2_ic_tctxt_read(void 
*opaque, hwaddr offset,

  case TCTXT_EN1_RESET:
  val = xive->tctxt_regs[TCTXT_EN1 >> 3];
  break;
+    case TCTXT_CFG:
+    val = xive->tctxt_regs[reg];
+    break;
  default:
  xive2_error(xive, "TCTXT: invalid read @%"HWADDR_PRIx, offset);
  }
@@ -1276,6 +1279,7 @@ static void pnv_xive2_ic_tctxt_write(void 
*opaque, hwaddr offset,

   uint64_t val, unsigned size)
  {
  PnvXive2 *xive = PNV_XIVE2(opaque);
+    uint32_t reg = offset >> 3;
  switch (offset) {
  /*
@@ -1297,7 +1301,9 @@ static void pnv_xive2_ic_tctxt_write(void 
*opaque, hwaddr offset,

  case TCTXT_EN1_RESET:
  xive->tctxt_regs[TCTXT_EN1 >> 3] &= ~val;
  break;
-
+    case TCTXT_CFG:
+    xive->tctxt_regs[reg] = val;
+    break;
  default:
  xive2_error(xive, "TCTXT: invalid write @%"HWADDR_PRIx, 
offset);

  return;
diff --git a/hw/intc/pnv_xive2_regs.h b/hw/intc/pnv_xive2_regs.h
index 0c096e4adb..8f1e0a1fde 100644
--- a/hw/intc/pnv_xive2_regs.h
+++ b/hw/intc/pnv_xive2_regs.h
@@ -405,6 +405,10 @@
  #define X_TCTXT_EN1_RESET   0x307
  #define TCTXT_EN1_RESET 0x038
+/* TCTXT Config register */
+#define X_TCTXT_CFG 0x328
+#define TCTXT_CFG   0x140
+
  /*
   * VSD Tables
   */






Re: [PATCH 4/4] pnv/xive2: Handle TIMA access through all ports

2023-05-30 Thread Frederic Barrat




On 30/05/2023 18:49, Cédric Le Goater wrote:

On 5/30/23 18:40, Cédric Le Goater wrote:

On 5/30/23 18:11, Frederic Barrat wrote:

The Thread Interrupt Management Area (TIMA) can be accessed through 4
ports/snoop buses, targeted by the address. The base address of a TIMA
is using port 0 and the other ports are 0x80 apart. Using one port or
another can be useful to balance the load on the snoop buses.


and can we have some nice examples of how these ports are used ? only for
snooping or also for balancing operations ? which ones ?


The TIMA registers are in the 0x0 -> 0x3F range and there are 2
indication bits for special operations (bits 10 and 11; everything
fits on a 4k page). So the port address bits fall in between and are
"don't care" for the hardware when processing the TIMA operation. So
this patch filters out those port address bits so that a TIMA
operation can be triggered using any port.

It is also true for indirect access (through the IC BAR) and it's
actually nothing new, it was already the case on P9. Which helps here,
as the TIMA handling code is common between P9 (xive) and P10 (xive2).

Signed-off-by: Frederic Barrat 


Reviewed-by: Cédric Le Goater 


one extra comment, since we already have one mask for the tima offsets :

     /*
  * First, check for special operations in the 2K region
  */
     if (offset & 0x800) {

I think it would be cleaner to add some defines in the reg definition file.



Yeah, you're right, I should respin it with some proper defines. And 
I'll add one for the special op bit(s).


  Fred




Can come later.

Thanks,

C.





Re: [PATCH 4/4] pnv/xive2: Handle TIMA access through all ports

2023-05-30 Thread Frederic Barrat




On 30/05/2023 18:40, Cédric Le Goater wrote:

On 5/30/23 18:11, Frederic Barrat wrote:

The Thread Interrupt Management Area (TIMA) can be accessed through 4
ports/snoop buses, targeted by the address. The base address of a TIMA
is using port 0 and the other ports are 0x80 apart. Using one port or
another can be useful to balance the load on the snoop buses.


and can we have some nice examples of how these ports are used ? only for
snooping or also for balancing operations ? which ones ?



This is really "static" balancing. The snoop bus 0 and 3 are known to be 
the busiest, for various kind of operations. We found out recently that 
another hypervisor is always using snoop bus 1 for TIMA accesses, to 
spread the load. So it is really empirical.


xive_tm_raw_write/read() were actually working (by chance?), since they 
only retain the least significant bits, so the snoop address bits were 
dropped. The problem was really for the special op detection, which 
matches on the full address.


  Fred



The TIMA registers are in the 0x0 -> 0x3F range and there are 2
indication bits for special operations (bits 10 and 11; everything
fits on a 4k page). So the port address bits fall in between and are
"don't care" for the hardware when processing the TIMA operation. So
this patch filters out those port address bits so that a TIMA
operation can be triggered using any port.

It is also true for indirect access (through the IC BAR) and it's
actually nothing new, it was already the case on P9. Which helps here,
as the TIMA handling code is common between P9 (xive) and P10 (xive2).

Signed-off-by: Frederic Barrat 


Reviewed-by: Cédric Le Goater 

Thanks,

C.


---
  hw/intc/pnv_xive2.c |  4 
  hw/intc/xive.c  | 18 ++
  2 files changed, 22 insertions(+)

diff --git a/hw/intc/pnv_xive2.c b/hw/intc/pnv_xive2.c
index 132f82a035..c80316657a 100644
--- a/hw/intc/pnv_xive2.c
+++ b/hw/intc/pnv_xive2.c
@@ -1662,6 +1662,8 @@ static void pnv_xive2_tm_write(void *opaque, 
hwaddr offset,

  bool gen1_tima_os =
  xive->cq_regs[CQ_XIVE_CFG >> 3] & CQ_XIVE_CFG_GEN1_TIMA_OS;
+    offset &= 0xC3F; /* See comment in xive_tctx_tm_write() */
+
  /* TODO: should we switch the TM ops table instead ? */
  if (!gen1_tima_os && offset == HV_PUSH_OS_CTX_OFFSET) {
  xive2_tm_push_os_ctx(xptr, tctx, offset, value, size);
@@ -1681,6 +1683,8 @@ static uint64_t pnv_xive2_tm_read(void *opaque, 
hwaddr offset, unsigned size)

  bool gen1_tima_os =
  xive->cq_regs[CQ_XIVE_CFG >> 3] & CQ_XIVE_CFG_GEN1_TIMA_OS;
+    offset &= 0xC3F; /* See comment in xive_tctx_tm_read() */
+
  /* TODO: should we switch the TM ops table instead ? */
  if (!gen1_tima_os && offset == HV_PULL_OS_CTX_OFFSET) {
  return xive2_tm_pull_os_ctx(xptr, tctx, offset, size);
diff --git a/hw/intc/xive.c b/hw/intc/xive.c
index a986b96843..c1abfae31d 100644
--- a/hw/intc/xive.c
+++ b/hw/intc/xive.c
@@ -527,6 +527,15 @@ void xive_tctx_tm_write(XivePresenter *xptr, 
XiveTCTX *tctx, hwaddr offset,

  trace_xive_tctx_tm_write(offset, size, value);
+    /*
+ * The TIMA can be accessed through 4 ports/snoop buses, with
+ * addresses 0x80 apart.
+ * However, the offset bits between the "special op" bits and the
+ * MSB of the range used for the TIMA registers are "don't care"
+ * for the hardware, so we filter them out.
+ */
+    offset &= 0xC3F;
+
  /*
   * TODO: check V bit in Q[0-3]W2
   */
@@ -566,6 +575,15 @@ uint64_t xive_tctx_tm_read(XivePresenter *xptr, 
XiveTCTX *tctx, hwaddr offset,

  const XiveTmOp *xto;
  uint64_t ret;
+    /*
+ * The TIMA can be accessed through 4 ports/snoop buses, with
+ * addresses 0x80 apart.
+ * However, the offset bits between the "special op" bits and the
+ * MSB of the range used for the TIMA registers are "don't care"
+ * for the hardware, so we filter them out.
+ */
+    offset &= 0xC3F;
+
  /*
   * TODO: check V bit in Q[0-3]W2
   */






[PATCH 0/4] Various xive fixes

2023-05-30 Thread Frederic Barrat
A set of small fixes for the interrupt controller (xive2) on P10.

Frederic Barrat (4):
  pnv/xive2: Add definition for TCTXT Config register
  pnv/xive2: Add definition for the ESB cache configuration register
  pnv/xive2: Allow writes to the Physical Thread Enable registers
  pnv/xive2: Handle TIMA access through all ports

 hw/intc/pnv_xive2.c  | 20 +++-
 hw/intc/pnv_xive2_regs.h |  8 
 hw/intc/xive.c   | 18 ++
 3 files changed, 45 insertions(+), 1 deletion(-)

-- 
2.40.1




[PATCH 4/4] pnv/xive2: Handle TIMA access through all ports

2023-05-30 Thread Frederic Barrat
The Thread Interrupt Management Area (TIMA) can be accessed through 4
ports/snoop buses, targeted by the address. The base address of a TIMA
is using port 0 and the other ports are 0x80 apart. Using one port or
another can be useful to balance the load on the snoop buses.

The TIMA registers are in the 0x0 -> 0x3F range and there are 2
indication bits for special operations (bits 10 and 11; everything
fits on a 4k page). So the port address bits fall in between and are
"don't care" for the hardware when processing the TIMA operation. So
this patch filters out those port address bits so that a TIMA
operation can be triggered using any port.

It is also true for indirect access (through the IC BAR) and it's
actually nothing new, it was already the case on P9. Which helps here,
as the TIMA handling code is common between P9 (xive) and P10 (xive2).

Signed-off-by: Frederic Barrat 
---
 hw/intc/pnv_xive2.c |  4 
 hw/intc/xive.c  | 18 ++
 2 files changed, 22 insertions(+)

diff --git a/hw/intc/pnv_xive2.c b/hw/intc/pnv_xive2.c
index 132f82a035..c80316657a 100644
--- a/hw/intc/pnv_xive2.c
+++ b/hw/intc/pnv_xive2.c
@@ -1662,6 +1662,8 @@ static void pnv_xive2_tm_write(void *opaque, hwaddr 
offset,
 bool gen1_tima_os =
 xive->cq_regs[CQ_XIVE_CFG >> 3] & CQ_XIVE_CFG_GEN1_TIMA_OS;
 
+offset &= 0xC3F; /* See comment in xive_tctx_tm_write() */
+
 /* TODO: should we switch the TM ops table instead ? */
 if (!gen1_tima_os && offset == HV_PUSH_OS_CTX_OFFSET) {
 xive2_tm_push_os_ctx(xptr, tctx, offset, value, size);
@@ -1681,6 +1683,8 @@ static uint64_t pnv_xive2_tm_read(void *opaque, hwaddr 
offset, unsigned size)
 bool gen1_tima_os =
 xive->cq_regs[CQ_XIVE_CFG >> 3] & CQ_XIVE_CFG_GEN1_TIMA_OS;
 
+offset &= 0xC3F; /* See comment in xive_tctx_tm_read() */
+
 /* TODO: should we switch the TM ops table instead ? */
 if (!gen1_tima_os && offset == HV_PULL_OS_CTX_OFFSET) {
 return xive2_tm_pull_os_ctx(xptr, tctx, offset, size);
diff --git a/hw/intc/xive.c b/hw/intc/xive.c
index a986b96843..c1abfae31d 100644
--- a/hw/intc/xive.c
+++ b/hw/intc/xive.c
@@ -527,6 +527,15 @@ void xive_tctx_tm_write(XivePresenter *xptr, XiveTCTX 
*tctx, hwaddr offset,
 
 trace_xive_tctx_tm_write(offset, size, value);
 
+/*
+ * The TIMA can be accessed through 4 ports/snoop buses, with
+ * addresses 0x80 apart.
+ * However, the offset bits between the "special op" bits and the
+ * MSB of the range used for the TIMA registers are "don't care"
+ * for the hardware, so we filter them out.
+ */
+offset &= 0xC3F;
+
 /*
  * TODO: check V bit in Q[0-3]W2
  */
@@ -566,6 +575,15 @@ uint64_t xive_tctx_tm_read(XivePresenter *xptr, XiveTCTX 
*tctx, hwaddr offset,
 const XiveTmOp *xto;
 uint64_t ret;
 
+/*
+ * The TIMA can be accessed through 4 ports/snoop buses, with
+ * addresses 0x80 apart.
+ * However, the offset bits between the "special op" bits and the
+ * MSB of the range used for the TIMA registers are "don't care"
+ * for the hardware, so we filter them out.
+ */
+offset &= 0xC3F;
+
 /*
  * TODO: check V bit in Q[0-3]W2
  */
-- 
2.40.1




[PATCH 2/4] pnv/xive2: Add definition for the ESB cache configuration register

2023-05-30 Thread Frederic Barrat
Add basic read/write support for the ESB cache configuration register
on P10. We don't model the ESB cache in qemu so reading/writing the
register won't do anything, but it avoids logging a guest error when
skiboot configures it:

qemu-system-ppc64 -machine powernv10 ... -d guest_errors
  ...
XIVE[0] - VC: invalid read @240
XIVE[0] - VC: invalid write @240

Signed-off-by: Frederic Barrat 
---
 hw/intc/pnv_xive2.c  | 7 +++
 hw/intc/pnv_xive2_regs.h | 4 
 2 files changed, 11 insertions(+)

diff --git a/hw/intc/pnv_xive2.c b/hw/intc/pnv_xive2.c
index 889e409929..a75ff270ac 100644
--- a/hw/intc/pnv_xive2.c
+++ b/hw/intc/pnv_xive2.c
@@ -955,6 +955,10 @@ static uint64_t pnv_xive2_ic_vc_read(void *opaque, hwaddr 
offset,
 val = xive->vc_regs[reg];
 break;
 
+case VC_ESBC_CFG:
+val = xive->vc_regs[reg];
+break;
+
 /*
  * EAS cache updates (not modeled)
  */
@@ -1046,6 +1050,9 @@ static void pnv_xive2_ic_vc_write(void *opaque, hwaddr 
offset,
 /* ESB update */
 break;
 
+case VC_ESBC_CFG:
+break;
+
 /*
  * EAS cache updates (not modeled)
  */
diff --git a/hw/intc/pnv_xive2_regs.h b/hw/intc/pnv_xive2_regs.h
index 8f1e0a1fde..7165dc8704 100644
--- a/hw/intc/pnv_xive2_regs.h
+++ b/hw/intc/pnv_xive2_regs.h
@@ -232,6 +232,10 @@
 #define  VC_ESBC_FLUSH_POLL_BLOCK_ID_MASK   PPC_BITMASK(32, 35)
 #define  VC_ESBC_FLUSH_POLL_OFFSET_MASK PPC_BITMASK(36, 63) /* 28-bit 
*/
 
+/* ESBC configuration */
+#define X_VC_ESBC_CFG   0x148
+#define VC_ESBC_CFG 0x240
+
 /* EASC flush control register */
 #define X_VC_EASC_FLUSH_CTRL0x160
 #define VC_EASC_FLUSH_CTRL  0x300
-- 
2.40.1




[PATCH 1/4] pnv/xive2: Add definition for TCTXT Config register

2023-05-30 Thread Frederic Barrat
Add basic read/write support for the TCTXT Config register on P10. qemu
doesn't do anything with it yet, but it avoids logging a guest error
when skiboot configures the fused-core state:

qemu-system-ppc64 -machine powernv10 ... -d guest_errors
  ...
[0.13167,5] XIVE: [ IC 00  ] Initializing XIVE block ID 0...
XIVE[0] - TCTXT: invalid read @140
XIVE[0] - TCTXT: invalid write @140

Signed-off-by: Frederic Barrat 
---
 hw/intc/pnv_xive2.c  | 8 +++-
 hw/intc/pnv_xive2_regs.h | 4 
 2 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/hw/intc/pnv_xive2.c b/hw/intc/pnv_xive2.c
index 7176d70234..889e409929 100644
--- a/hw/intc/pnv_xive2.c
+++ b/hw/intc/pnv_xive2.c
@@ -1265,6 +1265,9 @@ static uint64_t pnv_xive2_ic_tctxt_read(void *opaque, 
hwaddr offset,
 case TCTXT_EN1_RESET:
 val = xive->tctxt_regs[TCTXT_EN1 >> 3];
 break;
+case TCTXT_CFG:
+val = xive->tctxt_regs[reg];
+break;
 default:
 xive2_error(xive, "TCTXT: invalid read @%"HWADDR_PRIx, offset);
 }
@@ -1276,6 +1279,7 @@ static void pnv_xive2_ic_tctxt_write(void *opaque, hwaddr 
offset,
  uint64_t val, unsigned size)
 {
 PnvXive2 *xive = PNV_XIVE2(opaque);
+uint32_t reg = offset >> 3;
 
 switch (offset) {
 /*
@@ -1297,7 +1301,9 @@ static void pnv_xive2_ic_tctxt_write(void *opaque, hwaddr 
offset,
 case TCTXT_EN1_RESET:
 xive->tctxt_regs[TCTXT_EN1 >> 3] &= ~val;
 break;
-
+case TCTXT_CFG:
+xive->tctxt_regs[reg] = val;
+break;
 default:
 xive2_error(xive, "TCTXT: invalid write @%"HWADDR_PRIx, offset);
 return;
diff --git a/hw/intc/pnv_xive2_regs.h b/hw/intc/pnv_xive2_regs.h
index 0c096e4adb..8f1e0a1fde 100644
--- a/hw/intc/pnv_xive2_regs.h
+++ b/hw/intc/pnv_xive2_regs.h
@@ -405,6 +405,10 @@
 #define X_TCTXT_EN1_RESET   0x307
 #define TCTXT_EN1_RESET 0x038
 
+/* TCTXT Config register */
+#define X_TCTXT_CFG 0x328
+#define TCTXT_CFG   0x140
+
 /*
  * VSD Tables
  */
-- 
2.40.1




[PATCH 3/4] pnv/xive2: Allow writes to the Physical Thread Enable registers

2023-05-30 Thread Frederic Barrat
Fix what was probably a silly mistake and allow to write the Physical
Thread enable registers 0 and 1. Skiboot prefers to use the ENx_SET
variant so it went unnoticed, but there's no reason to discard a write
to the full register, it is Read-Write.

Signed-off-by: Frederic Barrat 
---
 hw/intc/pnv_xive2.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/hw/intc/pnv_xive2.c b/hw/intc/pnv_xive2.c
index a75ff270ac..132f82a035 100644
--- a/hw/intc/pnv_xive2.c
+++ b/hw/intc/pnv_xive2.c
@@ -1294,6 +1294,7 @@ static void pnv_xive2_ic_tctxt_write(void *opaque, hwaddr 
offset,
  */
 case TCTXT_EN0: /* Physical Thread Enable */
 case TCTXT_EN1: /* Physical Thread Enable (fused core) */
+xive->tctxt_regs[reg] = val;
 break;
 
 case TCTXT_EN0_SET:
-- 
2.40.1




Re: [PATCH] pnv_lpc: disable reentrancy detection for lpc-hc

2023-05-26 Thread Frederic Barrat




On 26/05/2023 09:38, Cédric Le Goater wrote:

From: Alexander Bulekov 

As lpc-hc is designed for re-entrant calls from xscom, mark it
re-entrancy safe.

Reported-by: Thomas Huth 
Signed-off-by: Alexander Bulekov 
[clg: mark opb_master_regs as re-entrancy safe also ]
Signed-off-by: Cédric Le Goater 
---



Reviewed-by: Frederic Barrat 

Thanks,

  Fred



  hw/ppc/pnv_lpc.c | 3 +++
  1 file changed, 3 insertions(+)

diff --git a/hw/ppc/pnv_lpc.c b/hw/ppc/pnv_lpc.c
index 01f44c19ebba..605d3908617a 100644
--- a/hw/ppc/pnv_lpc.c
+++ b/hw/ppc/pnv_lpc.c
@@ -734,10 +734,13 @@ static void pnv_lpc_realize(DeviceState *dev, Error 
**errp)
  /* Create MMIO regions for LPC HC and OPB registers */
  memory_region_init_io(>opb_master_regs, OBJECT(dev), _master_ops,
lpc, "lpc-opb-master", LPC_OPB_REGS_OPB_SIZE);
+lpc->opb_master_regs.disable_reentrancy_guard = true;
  memory_region_add_subregion(>opb_mr, LPC_OPB_REGS_OPB_ADDR,
  >opb_master_regs);
  memory_region_init_io(>lpc_hc_regs, OBJECT(dev), _hc_ops, lpc,
"lpc-hc", LPC_HC_REGS_OPB_SIZE);
+/* xscom writes to lpc-hc. As such mark lpc-hc re-entrancy safe */
+lpc->lpc_hc_regs.disable_reentrancy_guard = true;
  memory_region_add_subregion(>opb_mr, LPC_HC_REGS_OPB_ADDR,
  >lpc_hc_regs);
  




Re: [PATCH v4] target/ppc: Add POWER9 DD2.2 model

2023-05-16 Thread Frederic Barrat




On 15/05/2023 18:02, Nicholas Piggin wrote:

POWER9 DD2.1 and earlier had significant limitations when running KVM,
including lack of "mixed mode" MMU support (ability to run HPT and RPT
mode on threads of the same core), and a translation prefetch issue
which is worked around by disabling "AIL" mode for the guest.

These processors are not widely available, and it's difficult to deal
with all these quirks in qemu +/- KVM, so create a POWER9 DD2.2 CPU
and make it the default POWER9 CPU.

Signed-off-by: Nicholas Piggin 
---



I almost forgot: the patch doesn't apply cleanly on latest upstream.

  Fred



This is unchanged since v3, just reposting.

Thanks,
Nick

  hw/ppc/pnv.c   |  2 +-
  hw/ppc/pnv_core.c  |  2 +-
  hw/ppc/spapr.c |  2 +-
  hw/ppc/spapr_cpu_core.c|  1 +
  include/hw/ppc/pnv.h   |  2 +-
  target/ppc/cpu-models.c|  4 +++-
  target/ppc/cpu-models.h|  1 +
  target/ppc/cpu_init.c  | 21 +++--
  tests/qtest/device-plug-test.c |  4 ++--
  9 files changed, 30 insertions(+), 9 deletions(-)

diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index 11cb48af2f..590fc64b32 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -2171,7 +2171,7 @@ static void pnv_machine_power9_class_init(ObjectClass 
*oc, void *data)
  };
  
  mc->desc = "IBM PowerNV (Non-Virtualized) POWER9";

-mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.0");
+mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.2");
  compat_props_add(mc->compat_props, phb_compat, G_N_ELEMENTS(phb_compat));
  
  xfc->match_nvt = pnv_match_nvt;

diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c
index 410f31bdf8..0bc3ad41c8 100644
--- a/hw/ppc/pnv_core.c
+++ b/hw/ppc/pnv_core.c
@@ -348,7 +348,7 @@ static const TypeInfo pnv_core_infos[] = {
  DEFINE_PNV_CORE_TYPE(power8, "power8e_v2.1"),
  DEFINE_PNV_CORE_TYPE(power8, "power8_v2.0"),
  DEFINE_PNV_CORE_TYPE(power8, "power8nvl_v1.0"),
-DEFINE_PNV_CORE_TYPE(power9, "power9_v2.0"),
+DEFINE_PNV_CORE_TYPE(power9, "power9_v2.2"),
  DEFINE_PNV_CORE_TYPE(power10, "power10_v2.0"),
  };
  
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c

index ddc9c7b1a1..b58e69afd7 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -4631,7 +4631,7 @@ static void spapr_machine_class_init(ObjectClass *oc, 
void *data)
  
  smc->dr_lmb_enabled = true;

  smc->update_dt_enabled = true;
-mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.0");
+mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.2");
  mc->has_hotpluggable_cpus = true;
  mc->nvdimm_supported = true;
  smc->resize_hpt_default = SPAPR_RESIZE_HPT_ENABLED;
diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c
index 8a4861f45a..9b88dd549a 100644
--- a/hw/ppc/spapr_cpu_core.c
+++ b/hw/ppc/spapr_cpu_core.c
@@ -390,6 +390,7 @@ static const TypeInfo spapr_cpu_core_type_infos[] = {
  DEFINE_SPAPR_CPU_CORE_TYPE("power8nvl_v1.0"),
  DEFINE_SPAPR_CPU_CORE_TYPE("power9_v1.0"),
  DEFINE_SPAPR_CPU_CORE_TYPE("power9_v2.0"),
+DEFINE_SPAPR_CPU_CORE_TYPE("power9_v2.2"),
  DEFINE_SPAPR_CPU_CORE_TYPE("power10_v1.0"),
  DEFINE_SPAPR_CPU_CORE_TYPE("power10_v2.0"),
  #ifdef CONFIG_KVM
diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h
index 409f3bf763..7e5fef7c43 100644
--- a/include/hw/ppc/pnv.h
+++ b/include/hw/ppc/pnv.h
@@ -48,7 +48,7 @@ DECLARE_INSTANCE_CHECKER(PnvChip, PNV_CHIP_POWER8,
  DECLARE_INSTANCE_CHECKER(PnvChip, PNV_CHIP_POWER8NVL,
   TYPE_PNV_CHIP_POWER8NVL)
  
-#define TYPE_PNV_CHIP_POWER9 PNV_CHIP_TYPE_NAME("power9_v2.0")

+#define TYPE_PNV_CHIP_POWER9 PNV_CHIP_TYPE_NAME("power9_v2.2")
  DECLARE_INSTANCE_CHECKER(PnvChip, PNV_CHIP_POWER9,
   TYPE_PNV_CHIP_POWER9)
  
diff --git a/target/ppc/cpu-models.c b/target/ppc/cpu-models.c

index 912b037c63..7dbb47de64 100644
--- a/target/ppc/cpu-models.c
+++ b/target/ppc/cpu-models.c
@@ -732,6 +732,8 @@
  "POWER9 v1.0")
  POWERPC_DEF("power9_v2.0",   CPU_POWERPC_POWER9_DD20,POWER9,
  "POWER9 v2.0")
+POWERPC_DEF("power9_v2.2",   CPU_POWERPC_POWER9_DD22,POWER9,
+"POWER9 v2.2")
  POWERPC_DEF("power10_v1.0",  CPU_POWERPC_POWER10_DD1,POWER10,
  "POWER10 v1.0")
  POWERPC_DEF("power10_v2.0",  CPU_POWERPC_POWER10_DD20,   POWER10,
@@ -907,7 +909,7 @@ PowerPCCPUAlias ppc_cpu_aliases[] = {
  { "power8e", "power8e_v2.1" },
  { "power8", "power8_v2.0" },
  { "power8nvl", "power8nvl_v1.0" },
-{ "power9", "power9_v2.0" },
+{ "power9", "power9_v2.2" },
  { "power10", "power10_v2.0" },
  #endif
  
diff --git a/target/ppc/cpu-models.h b/target/ppc/cpu-models.h

index a77e036b3a..572b5e553a 100644
--- a/target/ppc/cpu-models.h
+++ b/target/ppc/cpu-models.h
@@ -350,6 +350,7 @@ enum {
  CPU_POWERPC_POWER9_BASE= 0x004E,
  

Re: [PATCH v4] target/ppc: Add POWER9 DD2.2 model

2023-05-16 Thread Frederic Barrat




On 15/05/2023 18:02, Nicholas Piggin wrote:

POWER9 DD2.1 and earlier had significant limitations when running KVM,
including lack of "mixed mode" MMU support (ability to run HPT and RPT
mode on threads of the same core), and a translation prefetch issue
which is worked around by disabling "AIL" mode for the guest.

These processors are not widely available, and it's difficult to deal
with all these quirks in qemu +/- KVM, so create a POWER9 DD2.2 CPU
and make it the default POWER9 CPU.

Signed-off-by: Nicholas Piggin 
---


Reviewed-by: Frederic Barrat 

Which makes me wonder if the P9 DD1 and P10 DD1 cpu definitions are 
worth keeping, since we don't really try emulating the differences and 
we don't support them in firmware/skiboot. The only place where we seem 
to bother is in target/ppc/kvm.c and that's precisely what this patch is 
trying to avoid.


  Fred



This is unchanged since v3, just reposting.

Thanks,
Nick

  hw/ppc/pnv.c   |  2 +-
  hw/ppc/pnv_core.c  |  2 +-
  hw/ppc/spapr.c |  2 +-
  hw/ppc/spapr_cpu_core.c|  1 +
  include/hw/ppc/pnv.h   |  2 +-
  target/ppc/cpu-models.c|  4 +++-
  target/ppc/cpu-models.h|  1 +
  target/ppc/cpu_init.c  | 21 +++--
  tests/qtest/device-plug-test.c |  4 ++--
  9 files changed, 30 insertions(+), 9 deletions(-)

diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index 11cb48af2f..590fc64b32 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -2171,7 +2171,7 @@ static void pnv_machine_power9_class_init(ObjectClass 
*oc, void *data)
  };
  
  mc->desc = "IBM PowerNV (Non-Virtualized) POWER9";

-mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.0");
+mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.2");
  compat_props_add(mc->compat_props, phb_compat, G_N_ELEMENTS(phb_compat));
  
  xfc->match_nvt = pnv_match_nvt;

diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c
index 410f31bdf8..0bc3ad41c8 100644
--- a/hw/ppc/pnv_core.c
+++ b/hw/ppc/pnv_core.c
@@ -348,7 +348,7 @@ static const TypeInfo pnv_core_infos[] = {
  DEFINE_PNV_CORE_TYPE(power8, "power8e_v2.1"),
  DEFINE_PNV_CORE_TYPE(power8, "power8_v2.0"),
  DEFINE_PNV_CORE_TYPE(power8, "power8nvl_v1.0"),
-DEFINE_PNV_CORE_TYPE(power9, "power9_v2.0"),
+DEFINE_PNV_CORE_TYPE(power9, "power9_v2.2"),
  DEFINE_PNV_CORE_TYPE(power10, "power10_v2.0"),
  };
  
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c

index ddc9c7b1a1..b58e69afd7 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -4631,7 +4631,7 @@ static void spapr_machine_class_init(ObjectClass *oc, 
void *data)
  
  smc->dr_lmb_enabled = true;

  smc->update_dt_enabled = true;
-mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.0");
+mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.2");
  mc->has_hotpluggable_cpus = true;
  mc->nvdimm_supported = true;
  smc->resize_hpt_default = SPAPR_RESIZE_HPT_ENABLED;
diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c
index 8a4861f45a..9b88dd549a 100644
--- a/hw/ppc/spapr_cpu_core.c
+++ b/hw/ppc/spapr_cpu_core.c
@@ -390,6 +390,7 @@ static const TypeInfo spapr_cpu_core_type_infos[] = {
  DEFINE_SPAPR_CPU_CORE_TYPE("power8nvl_v1.0"),
  DEFINE_SPAPR_CPU_CORE_TYPE("power9_v1.0"),
  DEFINE_SPAPR_CPU_CORE_TYPE("power9_v2.0"),
+DEFINE_SPAPR_CPU_CORE_TYPE("power9_v2.2"),
  DEFINE_SPAPR_CPU_CORE_TYPE("power10_v1.0"),
  DEFINE_SPAPR_CPU_CORE_TYPE("power10_v2.0"),
  #ifdef CONFIG_KVM
diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h
index 409f3bf763..7e5fef7c43 100644
--- a/include/hw/ppc/pnv.h
+++ b/include/hw/ppc/pnv.h
@@ -48,7 +48,7 @@ DECLARE_INSTANCE_CHECKER(PnvChip, PNV_CHIP_POWER8,
  DECLARE_INSTANCE_CHECKER(PnvChip, PNV_CHIP_POWER8NVL,
   TYPE_PNV_CHIP_POWER8NVL)
  
-#define TYPE_PNV_CHIP_POWER9 PNV_CHIP_TYPE_NAME("power9_v2.0")

+#define TYPE_PNV_CHIP_POWER9 PNV_CHIP_TYPE_NAME("power9_v2.2")
  DECLARE_INSTANCE_CHECKER(PnvChip, PNV_CHIP_POWER9,
   TYPE_PNV_CHIP_POWER9)
  
diff --git a/target/ppc/cpu-models.c b/target/ppc/cpu-models.c

index 912b037c63..7dbb47de64 100644
--- a/target/ppc/cpu-models.c
+++ b/target/ppc/cpu-models.c
@@ -732,6 +732,8 @@
  "POWER9 v1.0")
  POWERPC_DEF("power9_v2.0",   CPU_POWERPC_POWER9_DD20,POWER9,
  "POWER9 v2.0")
+POWERPC_DEF("power9_v2.2",   CPU_POWERPC_POWER9_DD22,POWER9,
+"POWER9 v2.2")
  POWERPC_DEF("power10_v1.0",  CPU_POWERPC_POWER10_DD1,POWER10,
  "POWER10 v1.0")
  POWERPC_DEF(&

Re: [PATCH] pnv_lpc: disable reentrancy detection for lpc-hc

2023-05-15 Thread Frederic Barrat




On 11/05/2023 11:15, Alexander Bulekov wrote:

On 230511 1104, Cédric Le Goater wrote:

Hello Alexander

On 5/11/23 10:53, Alexander Bulekov wrote:

As lpc-hc is designed for re-entrant calls from xscom, mark it
re-entrancy safe.

Reported-by: Thomas Huth 
Signed-off-by: Alexander Bulekov 
---
   hw/ppc/pnv_lpc.c | 2 ++
   1 file changed, 2 insertions(+)

diff --git a/hw/ppc/pnv_lpc.c b/hw/ppc/pnv_lpc.c
index 01f44c19eb..67fd049a7f 100644
--- a/hw/ppc/pnv_lpc.c
+++ b/hw/ppc/pnv_lpc.c
@@ -738,6 +738,8 @@ static void pnv_lpc_realize(DeviceState *dev, Error **errp)
   >opb_master_regs);
   memory_region_init_io(>lpc_hc_regs, OBJECT(dev), _hc_ops, lpc,
 "lpc-hc", LPC_HC_REGS_OPB_SIZE);
+/* xscom writes to lpc-hc. As such mark lpc-hc re-entrancy safe */
+lpc->lpc_hc_regs.disable_reentrancy_guard = true;
   memory_region_add_subregion(>opb_mr, LPC_HC_REGS_OPB_ADDR,
   >lpc_hc_regs);


The warning changed :

   qemu-system-ppc64: warning: Blocked re-entrant IO on MemoryRegion: 
lpc-opb-master at addr: 0x8

I will take a look unless you know exactly what to do.



That does not show up for me with "./qemu-system-ppc64 -M powernv8"
Do I need to boot a kernel to see the message?

I was worried that there might be other re-entrant IO in this device.
Maybe there should be a way to just mark the whole device re-entrancy
safe.


Hello,

I was also started hitting it, with machine powernv10. And indeed, 
disabling the check on both lpc_hc_regs and opb_master_regs should be 
all we need (and it's working fine for me).


  Fred




Re: [PATCH 1/4] pnv_phb4_pec: Keep track of instantiated PHBs

2023-03-03 Thread Frederic Barrat




On 02/03/2023 23:21, Philippe Mathieu-Daudé wrote:

Hi Frederic,

On 2/3/23 17:37, Frederic Barrat wrote:

Add an array on the PEC object to keep track of the PHBs which are
instantiated. The array can be sparsely populated when using
user-created PHBs. It will be useful for the next patch to only export
instantiated PHBs in the device tree.

Signed-off-by: Frederic Barrat 
---
  hw/pci-host/pnv_phb4_pec.c | 12 +++-
  hw/ppc/pnv.c   |  1 +
  include/hw/pci-host/pnv_phb4.h |  2 ++
  3 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/hw/pci-host/pnv_phb4_pec.c b/hw/pci-host/pnv_phb4_pec.c
index 43267a428f..97c06bb0a0 100644
--- a/hw/pci-host/pnv_phb4_pec.c
+++ b/hw/pci-host/pnv_phb4_pec.c



+static PnvPHB *pnv_pec_default_phb_realize(PnvPhb4PecState *pec,
+   int stack_no,
+   Error **errp)
  {
  PnvPHB *phb = PNV_PHB(qdev_new(TYPE_PNV_PHB));
  int phb_id = pnv_phb4_pec_get_phb_id(pec, stack_no);
@@ -128,8 +128,9 @@ static void 
pnv_pec_default_phb_realize(PnvPhb4PecState *pec,

  _fatal);
  if (!sysbus_realize(SYS_BUS_DEVICE(phb), errp)) {
-    return;
+    return NULL;
  }
+    return phb;
  }



diff --git a/include/hw/pci-host/pnv_phb4.h 
b/include/hw/pci-host/pnv_phb4.h

index 28d61b96c7..0b72ef1471 100644
--- a/include/hw/pci-host/pnv_phb4.h
+++ b/include/hw/pci-host/pnv_phb4.h
@@ -185,6 +185,8 @@ struct PnvPhb4PecState {
  /* PHBs */
  uint32_t num_phbs;
+#define MAX_PHBS_PER_PEC    3
+    PnvPHB *phbs[MAX_PHBS_PER_PEC];
  PnvChip *chip;
  };


 From QOM PoV, better would be to 'embed' the PnvPHB structure (not only
a pointer to it), and initialize the PnvPHB instance calling
object_initialize_child() instead of qdev_new().


Hi Phil,
Daniel beat me to it, but we used to do precisely that but went the
opposite direction (see 0d512c7120a2), because we can now specify from 
the command line what PHB to implement so we don't want to allocate all 
of them.


  Fred




See for example the recent conversion of OHCISysBusState in commit
01c400ae43 ("hw/display/sm501: Embed OHCI QOM child in chipset").

Regards,

Phil.




[PATCH 1/4] pnv_phb4_pec: Keep track of instantiated PHBs

2023-03-02 Thread Frederic Barrat
Add an array on the PEC object to keep track of the PHBs which are
instantiated. The array can be sparsely populated when using
user-created PHBs. It will be useful for the next patch to only export
instantiated PHBs in the device tree.

Signed-off-by: Frederic Barrat 
---
 hw/pci-host/pnv_phb4_pec.c | 12 +++-
 hw/ppc/pnv.c   |  1 +
 include/hw/pci-host/pnv_phb4.h |  2 ++
 3 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/hw/pci-host/pnv_phb4_pec.c b/hw/pci-host/pnv_phb4_pec.c
index 43267a428f..97c06bb0a0 100644
--- a/hw/pci-host/pnv_phb4_pec.c
+++ b/hw/pci-host/pnv_phb4_pec.c
@@ -112,9 +112,9 @@ static const MemoryRegionOps pnv_pec_pci_xscom_ops = {
 .endianness = DEVICE_BIG_ENDIAN,
 };
 
-static void pnv_pec_default_phb_realize(PnvPhb4PecState *pec,
-int stack_no,
-Error **errp)
+static PnvPHB *pnv_pec_default_phb_realize(PnvPhb4PecState *pec,
+   int stack_no,
+   Error **errp)
 {
 PnvPHB *phb = PNV_PHB(qdev_new(TYPE_PNV_PHB));
 int phb_id = pnv_phb4_pec_get_phb_id(pec, stack_no);
@@ -128,8 +128,9 @@ static void pnv_pec_default_phb_realize(PnvPhb4PecState 
*pec,
 _fatal);
 
 if (!sysbus_realize(SYS_BUS_DEVICE(phb), errp)) {
-return;
+return NULL;
 }
+return phb;
 }
 
 static void pnv_pec_realize(DeviceState *dev, Error **errp)
@@ -148,8 +149,9 @@ static void pnv_pec_realize(DeviceState *dev, Error **errp)
 
 /* Create PHBs if running with defaults */
 if (defaults_enabled()) {
+g_assert(pec->num_phbs <= MAX_PHBS_PER_PEC);
 for (i = 0; i < pec->num_phbs; i++) {
-pnv_pec_default_phb_realize(pec, i, errp);
+pec->phbs[i] = pnv_pec_default_phb_realize(pec, i, errp);
 }
 }
 
diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index 44b1fbbc93..24bf8461d6 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -314,6 +314,7 @@ static PnvPhb4PecState *pnv_phb4_get_pec(PnvChip *chip, 
PnvPHB4 *phb,
 
 for (j = 0; j < pec->num_phbs; j++) {
 if (index == pnv_phb4_pec_get_phb_id(pec, j)) {
+pec->phbs[j] = phb->phb_base;
 return pec;
 }
 }
diff --git a/include/hw/pci-host/pnv_phb4.h b/include/hw/pci-host/pnv_phb4.h
index 28d61b96c7..0b72ef1471 100644
--- a/include/hw/pci-host/pnv_phb4.h
+++ b/include/hw/pci-host/pnv_phb4.h
@@ -185,6 +185,8 @@ struct PnvPhb4PecState {
 
 /* PHBs */
 uint32_t num_phbs;
+#define MAX_PHBS_PER_PEC3
+PnvPHB *phbs[MAX_PHBS_PER_PEC];
 
 PnvChip *chip;
 };
-- 
2.39.2




[PATCH 4/4] pnv_phb4_pec: Simplify/align code to parent user-created PHBs

2023-03-02 Thread Frederic Barrat
When instantiating a user-created PHB on P9/P10, we don't really have
a reason any more to go through an indirection in pnv_chip_add_phb()
in pnv.c, we can go straight to the right function in
pnv_phb4_pec.c. That way, default PHBs and user-created PHBs are all
handled in the same file.  This patch also renames pnv_phb4_get_pec()
to pnv_pec_add_phb() to better reflect that it "hooks" a PHB to a PEC.

For P8, the PHBs are parented to the chip directly, so it makes sense
to keep calling pnv_chip_add_phb() in pnv.c, to also be consistent
with where default PHBs are handled. The only change here is that,
since that function is now only used for P8, we can refine the return
type.

So overall, the PnvPHB front-end now has a pnv_phb_user_get_parent()
function which handles the parenting of the user-created PHBs by
calling the right function in the right file based on the processor
version. It's also easily extensible if we ever need to support a
different parent object.

Signed-off-by: Frederic Barrat 
---
 hw/pci-host/pnv_phb.c  | 11 ++-
 hw/pci-host/pnv_phb4_pec.c |  3 ++-
 hw/ppc/pnv.c   | 29 -
 include/hw/pci-host/pnv_phb4.h |  2 +-
 include/hw/ppc/pnv.h   |  2 +-
 5 files changed, 22 insertions(+), 25 deletions(-)

diff --git a/hw/pci-host/pnv_phb.c b/hw/pci-host/pnv_phb.c
index c62b08538a..82332d7a05 100644
--- a/hw/pci-host/pnv_phb.c
+++ b/hw/pci-host/pnv_phb.c
@@ -62,6 +62,15 @@ static bool pnv_parent_fixup(Object *parent, BusState 
*parent_bus,
 return true;
 }
 
+static Object *pnv_phb_user_get_parent(PnvChip *chip, PnvPHB *phb, Error 
**errp)
+{
+if (phb->version == 3) {
+return OBJECT(pnv_chip_add_phb(chip, phb));
+} else {
+return OBJECT(pnv_pec_add_phb(chip, phb, errp));
+}
+}
+
 /*
  * User created devices won't have the initial setup that default
  * devices have. This setup consists of assigning a parent device
@@ -79,7 +88,7 @@ static bool pnv_phb_user_device_init(PnvPHB *phb, Error 
**errp)
 return false;
 }
 
-parent = pnv_chip_add_phb(chip, phb, errp);
+parent = pnv_phb_user_get_parent(chip, phb, errp);
 if (!parent) {
 return false;
 }
diff --git a/hw/pci-host/pnv_phb4_pec.c b/hw/pci-host/pnv_phb4_pec.c
index 6e2e5ae186..3b2850f7a3 100644
--- a/hw/pci-host/pnv_phb4_pec.c
+++ b/hw/pci-host/pnv_phb4_pec.c
@@ -112,7 +112,7 @@ static const MemoryRegionOps pnv_pec_pci_xscom_ops = {
 .endianness = DEVICE_BIG_ENDIAN,
 };
 
-PnvPhb4PecState *pnv_phb4_get_pec(PnvChip *chip, PnvPHB *phb, Error **errp)
+PnvPhb4PecState *pnv_pec_add_phb(PnvChip *chip, PnvPHB *phb, Error **errp)
 {
 PnvPhb4PecState *pecs = NULL;
 int chip_id = phb->chip_id;
@@ -141,6 +141,7 @@ PnvPhb4PecState *pnv_phb4_get_pec(PnvChip *chip, PnvPHB 
*phb, Error **errp)
 for (j = 0; j < pec->num_phbs; j++) {
 if (index == pnv_phb4_pec_get_phb_id(pec, j)) {
 pec->phbs[j] = phb;
+phb->pec = pec;
 return pec;
 }
 }
diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index 46010b30ad..11cb48af2f 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -285,31 +285,18 @@ static void pnv_dt_icp(PnvChip *chip, void *fdt, uint32_t 
pir,
 }
 
 /*
- * Adds a PnvPHB to the chip. Returns the parent obj of the
- * PHB which varies with each version (phb version 3 is parented
- * by the chip, version 4 and 5 are parented by the PEC
- * device).
- *
- * TODO: for version 3 we're still parenting the PHB with the
- * chip. We should parent with a (so far not implemented)
- * PHB3 PEC device.
+ * Adds a PnvPHB to the chip on P8.
+ * Implemented here, like for defaults PHBs
  */
-Object *pnv_chip_add_phb(PnvChip *chip, PnvPHB *phb, Error **errp)
+PnvChip *pnv_chip_add_phb(PnvChip *chip, PnvPHB *phb)
 {
-if (phb->version == 3) {
-Pnv8Chip *chip8 = PNV8_CHIP(chip);
-
-phb->chip = chip;
-
-chip8->phbs[chip8->num_phbs] = phb;
-chip8->num_phbs++;
-
-return OBJECT(chip);
-}
+Pnv8Chip *chip8 = PNV8_CHIP(chip);
 
-phb->pec = pnv_phb4_get_pec(chip, phb, errp);
+phb->chip = chip;
 
-return OBJECT(phb->pec);
+chip8->phbs[chip8->num_phbs] = phb;
+chip8->num_phbs++;
+return chip;
 }
 
 static void pnv_chip_power8_dt_populate(PnvChip *chip, void *fdt)
diff --git a/include/hw/pci-host/pnv_phb4.h b/include/hw/pci-host/pnv_phb4.h
index 5c5edb2941..2d026db9a3 100644
--- a/include/hw/pci-host/pnv_phb4.h
+++ b/include/hw/pci-host/pnv_phb4.h
@@ -157,7 +157,7 @@ struct PnvPHB4 {
 
 void pnv_phb4_pic_print_info(PnvPHB4 *phb, Monitor *mon);
 int pnv_phb4_pec_get_phb_id(PnvPhb4PecState *pec, int stack_index);
-PnvPhb4PecState *pnv_phb4_get_pec(PnvChip *chip, PnvPHB *phb, Error **errp);
+PnvPhb4PecState *pnv_pec_add_phb(PnvChip *chip, PnvPHB *phb, Error **errp);
 void pnv_phb4_bus_init(DeviceState *dev, PnvPHB4 *phb);
 extern con

[PATCH 3/4] pnv_phb4_pec: Move pnv_phb4_get_pec() to rightful file

2023-03-02 Thread Frederic Barrat
The function pnv_phb4_get_pec() exposes some internals of the PEC and
PHB logic, yet it was in the higher level hw/ppc/pnv.c file for
historical reasons: P8 implements the PHBs from pnv.c directly, but on
P9/P10, it's done through the CEC model, which has its own file. So
move pnv_phb4_get_pec() to hw/pci-host/pnv_phb4_pec.c, where it fits
naturally.

While at it, replace the PnvPHB4 parameter by the PnvPHB front-end,
since it has all the information needed and simplify it a bit.

No functional changes.

Signed-off-by: Frederic Barrat 
---
 hw/pci-host/pnv_phb4_pec.c | 40 +++
 hw/ppc/pnv.c   | 44 +-
 include/hw/pci-host/pnv_phb4.h |  1 +
 3 files changed, 42 insertions(+), 43 deletions(-)

diff --git a/hw/pci-host/pnv_phb4_pec.c b/hw/pci-host/pnv_phb4_pec.c
index 6c9b386069..6e2e5ae186 100644
--- a/hw/pci-host/pnv_phb4_pec.c
+++ b/hw/pci-host/pnv_phb4_pec.c
@@ -112,6 +112,46 @@ static const MemoryRegionOps pnv_pec_pci_xscom_ops = {
 .endianness = DEVICE_BIG_ENDIAN,
 };
 
+PnvPhb4PecState *pnv_phb4_get_pec(PnvChip *chip, PnvPHB *phb, Error **errp)
+{
+PnvPhb4PecState *pecs = NULL;
+int chip_id = phb->chip_id;
+int index = phb->phb_id;
+int i, j;
+
+if (phb->version == 4) {
+Pnv9Chip *chip9 = PNV9_CHIP(chip);
+
+pecs = chip9->pecs;
+} else if (phb->version == 5) {
+Pnv10Chip *chip10 = PNV10_CHIP(chip);
+
+pecs = chip10->pecs;
+} else {
+g_assert_not_reached();
+}
+
+for (i = 0; i < chip->num_pecs; i++) {
+/*
+ * For each PEC, check the amount of phbs it supports
+ * and see if the given phb4 index matches an index.
+ */
+PnvPhb4PecState *pec = [i];
+
+for (j = 0; j < pec->num_phbs; j++) {
+if (index == pnv_phb4_pec_get_phb_id(pec, j)) {
+pec->phbs[j] = phb;
+return pec;
+}
+}
+}
+error_setg(errp,
+   "pnv-phb4 chip-id %d index %d didn't match any existing PEC",
+   chip_id, index);
+
+return NULL;
+}
+
 static PnvPHB *pnv_pec_default_phb_realize(PnvPhb4PecState *pec,
int stack_no,
Error **errp)
diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index 24bf8461d6..46010b30ad 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -284,48 +284,6 @@ static void pnv_dt_icp(PnvChip *chip, void *fdt, uint32_t 
pir,
 g_free(reg);
 }
 
-static PnvPhb4PecState *pnv_phb4_get_pec(PnvChip *chip, PnvPHB4 *phb,
- Error **errp)
-{
-PnvPHB *phb_base = phb->phb_base;
-PnvPhb4PecState *pecs = NULL;
-int chip_id = phb->chip_id;
-int index = phb->phb_id;
-int i, j;
-
-if (phb_base->version == 4) {
-Pnv9Chip *chip9 = PNV9_CHIP(chip);
-
-pecs = chip9->pecs;
-} else if (phb_base->version == 5) {
-Pnv10Chip *chip10 = PNV10_CHIP(chip);
-
-pecs = chip10->pecs;
-} else {
-g_assert_not_reached();
-}
-
-for (i = 0; i < chip->num_pecs; i++) {
-/*
- * For each PEC, check the amount of phbs it supports
- * and see if the given phb4 index matches an index.
- */
-PnvPhb4PecState *pec = [i];
-
-for (j = 0; j < pec->num_phbs; j++) {
-if (index == pnv_phb4_pec_get_phb_id(pec, j)) {
-pec->phbs[j] = phb->phb_base;
-return pec;
-}
-}
-}
-error_setg(errp,
-   "pnv-phb4 chip-id %d index %d didn't match any existing PEC",
-   chip_id, index);
-
-return NULL;
-}
-
 /*
  * Adds a PnvPHB to the chip. Returns the parent obj of the
  * PHB which varies with each version (phb version 3 is parented
@@ -349,7 +307,7 @@ Object *pnv_chip_add_phb(PnvChip *chip, PnvPHB *phb, Error 
**errp)
 return OBJECT(chip);
 }
 
-phb->pec = pnv_phb4_get_pec(chip, PNV_PHB4(phb->backend), errp);
+phb->pec = pnv_phb4_get_pec(chip, phb, errp);
 
 return OBJECT(phb->pec);
 }
diff --git a/include/hw/pci-host/pnv_phb4.h b/include/hw/pci-host/pnv_phb4.h
index 0b72ef1471..5c5edb2941 100644
--- a/include/hw/pci-host/pnv_phb4.h
+++ b/include/hw/pci-host/pnv_phb4.h
@@ -157,6 +157,7 @@ struct PnvPHB4 {
 
 void pnv_phb4_pic_print_info(PnvPHB4 *phb, Monitor *mon);
 int pnv_phb4_pec_get_phb_id(PnvPhb4PecState *pec, int stack_index);
+PnvPhb4PecState *pnv_phb4_get_pec(PnvChip *chip, PnvPHB *phb, Error **errp);
 void pnv_phb4_bus_init(DeviceState *dev, PnvPHB4 *phb);
 extern const MemoryRegionOps pnv_phb4_xscom_ops;
 
-- 
2.39.2




[PATCH 2/4] pnv_phb4_pec: Only export existing PHBs to the device tree

2023-03-02 Thread Frederic Barrat
So far, we were always exporting all possible PHBs to the device
tree. It works well when using the default config but it potentially
adds non-existing devices when using '-nodefaults' and user-created
PHBs, causing the firmware (skiboot) to report errors when probing
those PHBs. This patch only exports PHBs which have been realized to
the device tree.

Fixes: d786be3fe746 ("ppc/pnv: enable user created pnv-phb for powernv9")
Signed-off-by: Frederic Barrat 
---
 hw/pci-host/pnv_phb4_pec.c | 8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/hw/pci-host/pnv_phb4_pec.c b/hw/pci-host/pnv_phb4_pec.c
index 97c06bb0a0..6c9b386069 100644
--- a/hw/pci-host/pnv_phb4_pec.c
+++ b/hw/pci-host/pnv_phb4_pec.c
@@ -199,9 +199,12 @@ static int pnv_pec_dt_xscom(PnvXScomInterface *dev, void 
*fdt,
   pecc->compat_size)));
 
 for (i = 0; i < pec->num_phbs; i++) {
-int phb_id = pnv_phb4_pec_get_phb_id(pec, i);
 int stk_offset;
 
+if (!pec->phbs[i]) {
+continue;
+}
+
 name = g_strdup_printf("stack@%x", i);
 stk_offset = fdt_add_subnode(fdt, offset, name);
 _FDT(stk_offset);
@@ -209,7 +212,8 @@ static int pnv_pec_dt_xscom(PnvXScomInterface *dev, void 
*fdt,
 _FDT((fdt_setprop(fdt, stk_offset, "compatible", pecc->stk_compat,
   pecc->stk_compat_size)));
 _FDT((fdt_setprop_cell(fdt, stk_offset, "reg", i)));
-_FDT((fdt_setprop_cell(fdt, stk_offset, "ibm,phb-index", phb_id)));
+_FDT((fdt_setprop_cell(fdt, stk_offset, "ibm,phb-index",
+   pec->phbs[i]->phb_id)));
 }
 
 return 0;
-- 
2.39.2




[PATCH 0/4] user-created PHB cleanup

2023-03-02 Thread Frederic Barrat
A short series with some cleanup around user-created PHB. The main
point is to remove errors seen from the firmware (skiboot) when using
user-created PHBs, as we were always showing all the default PHBs in
the device tree, so skiboot tried to probe non-existing devices. The
first 2 patches allow to only export the user-created PHBs in the
device tree when 'nodefaults' is used.
The last 2 are more cosmetic and moving code around where it makes
more sense.


Frederic Barrat (4):
  pnv_phb4_pec: Keep track of instantiated PHBs
  pnv_phb4_pec: Only export existing PHBs to the device tree
  pnv_phb4_pec: Move pnv_phb4_get_pec() to rightful file
  pnv_phb4_pec: Simplify/align code to parent user-created PHBs

 hw/pci-host/pnv_phb.c  | 11 +-
 hw/pci-host/pnv_phb4_pec.c | 61 +
 hw/ppc/pnv.c   | 70 --
 include/hw/pci-host/pnv_phb4.h |  3 ++
 include/hw/ppc/pnv.h   |  2 +-
 5 files changed, 76 insertions(+), 71 deletions(-)

-- 
2.39.2




[PATCH 2/4] ppc/pnv/pci: Remove duplicate definition of PNV_PHB5_DEVICE_ID

2023-01-27 Thread Frederic Barrat
PNV_PHB5_DEVICE_ID is defined in two different headers. The definition
in hw/pci-host/pnv_phb4.h was left out in a previous rework.

Remaining definition is in hw/pci-host/pnv_phb.h.

Signed-off-by: Frederic Barrat 
---
 include/hw/pci-host/pnv_phb4.h | 1 -
 1 file changed, 1 deletion(-)

diff --git a/include/hw/pci-host/pnv_phb4.h b/include/hw/pci-host/pnv_phb4.h
index 17aef08f91..761525686e 100644
--- a/include/hw/pci-host/pnv_phb4.h
+++ b/include/hw/pci-host/pnv_phb4.h
@@ -215,7 +215,6 @@ struct PnvPhb4PecClass {
 OBJECT_CHECK(PnvPhb4, (obj), TYPE_PNV_PHB5)
 
 #define PNV_PHB5_VERSION   0x00a50001ull
-#define PNV_PHB5_DEVICE_ID 0x0652
 
 #define TYPE_PNV_PHB5_PEC "pnv-phb5-pec"
 #define PNV_PHB5_PEC(obj) \
-- 
2.39.1




[PATCH 0/4] PCI-related cleanup for ppc/powernv

2023-01-27 Thread Frederic Barrat
Pretty simple PCI-related cleanup for powernv

Frederic Barrat (4):
  ppc/pnv/pci: Cleanup PnvPHBPecState structure
  ppc/pnv/pci: Remove duplicate definition of PNV_PHB5_DEVICE_ID
  ppc/pnv/pci: Update PHB5 version register
  ppc/pnv/pci: Fix PHB xscom registers memory region name

 hw/pci-host/pnv_phb4.c | 2 +-
 include/hw/pci-host/pnv_phb4.h | 5 +
 2 files changed, 2 insertions(+), 5 deletions(-)

-- 
2.39.1




[PATCH 4/4] ppc/pnv/pci: Fix PHB xscom registers memory region name

2023-01-27 Thread Frederic Barrat
The name is for the region mapping the PHB xscom registers. It was
apparently a bad cut-and-paste from the per-stack pci xscom area just
above, so we had two regions with the same name.

Signed-off-by: Frederic Barrat 
---
 hw/pci-host/pnv_phb4.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c
index ccbde841fc..542f9e2932 100644
--- a/hw/pci-host/pnv_phb4.c
+++ b/hw/pci-host/pnv_phb4.c
@@ -1497,7 +1497,7 @@ static void pnv_phb4_xscom_realize(PnvPHB4 *phb)
   PHB4_PEC_PCI_STK_REGS_COUNT);
 
 /* PHB pass-through */
-snprintf(name, sizeof(name), "xscom-pec-%d.%d-pci-phb-%d",
+snprintf(name, sizeof(name), "xscom-pec-%d.%d-phb-%d",
  pec->chip_id, pec->index, stack_no);
 pnv_xscom_region_init(>phb_regs_mr, OBJECT(phb),
   _phb4_xscom_ops, phb, name, 0x40);
-- 
2.39.1




[PATCH 1/4] ppc/pnv/pci: Cleanup PnvPHBPecState structure

2023-01-27 Thread Frederic Barrat
Remove unused structure member 'system_memory'.

Signed-off-by: Frederic Barrat 
---
 include/hw/pci-host/pnv_phb4.h | 2 --
 1 file changed, 2 deletions(-)

diff --git a/include/hw/pci-host/pnv_phb4.h b/include/hw/pci-host/pnv_phb4.h
index 1f3237c9d5..17aef08f91 100644
--- a/include/hw/pci-host/pnv_phb4.h
+++ b/include/hw/pci-host/pnv_phb4.h
@@ -173,8 +173,6 @@ struct PnvPhb4PecState {
 uint32_t index;
 uint32_t chip_id;
 
-MemoryRegion *system_memory;
-
 /* Nest registers, excuding per-stack */
 #define PHB4_PEC_NEST_REGS_COUNT0xf
 uint64_t nest_regs[PHB4_PEC_NEST_REGS_COUNT];
-- 
2.39.1




[PATCH 3/4] ppc/pnv/pci: Update PHB5 version register

2023-01-27 Thread Frederic Barrat
Update register value per its P10 DD2 definition.

Signed-off-by: Frederic Barrat 
---
 include/hw/pci-host/pnv_phb4.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/hw/pci-host/pnv_phb4.h b/include/hw/pci-host/pnv_phb4.h
index 761525686e..28d61b96c7 100644
--- a/include/hw/pci-host/pnv_phb4.h
+++ b/include/hw/pci-host/pnv_phb4.h
@@ -214,7 +214,7 @@ struct PnvPhb4PecClass {
 #define PNV_PHB5(obj) \
 OBJECT_CHECK(PnvPhb4, (obj), TYPE_PNV_PHB5)
 
-#define PNV_PHB5_VERSION   0x00a50001ull
+#define PNV_PHB5_VERSION   0x00a50002ull
 
 #define TYPE_PNV_PHB5_PEC "pnv-phb5-pec"
 #define PNV_PHB5_PEC(obj) \
-- 
2.39.1




Re: [PATCH v6 09/14] hw/ppc: set machine->fdt in pnv_reset()

2022-09-07 Thread Frederic Barrat




On 05/09/2022 01:34, Daniel Henrique Barboza wrote:

This will enable support for the 'dumpdtb' QMP/HMP command for
all powernv machines.

Cc: Cédric Le Goater 
Cc: Frederic Barrat 
Signed-off-by: Daniel Henrique Barboza 
---



LGTM
Reviewed-by: Frederic Barrat 

  Fred



  hw/ppc/pnv.c | 8 +++-
  1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index 354aa289d1..6a20c4811f 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -678,7 +678,13 @@ static void pnv_reset(MachineState *machine)
  qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt));
  cpu_physical_memory_write(PNV_FDT_ADDR, fdt, fdt_totalsize(fdt));
  
-g_free(fdt);

+/*
+ * Set machine->fdt for 'dumpdtb' QMP/HMP command. Free
+ * the existing machine->fdt to avoid leaking it during
+ * a reset.
+ */
+g_free(machine->fdt);
+machine->fdt = fdt;
  }
  
  static ISABus *pnv_chip_power8_isa_create(PnvChip *chip, Error **errp)




Re: [PATCH for-7.2 v2 2/2] ppc/pnv: fix QOM parenting of user creatable root ports

2022-08-23 Thread Frederic Barrat




On 19/08/2022 11:47, Daniel Henrique Barboza wrote:

User creatable root ports are being parented by the 'peripheral' or the
'peripheral-anon' container. This happens because this is the regular
QOM schema for sysbus devices that are added via the command line.

Let's make this QOM hierarchy similar to what we have with default root
ports, i.e. the root port must be parented by the pnv-root-bus. To do
that we change the qom and bus parent of the root port during
root_port_realize(). The realize() is shared by the default root port
code path, so we can remove the code inside pnv_phb_attach_root_port()
that was adding the root port as a child of the bus as well.

After all that, remove pnv_phb_attach_root_port() and create the root
port explictly in the 'default_enabled()' case of pnv_phb_realize().

Signed-off-by: Daniel Henrique Barboza 
---



Reviewed-by: Frederic Barrat 



  hw/pci-host/pnv_phb.c | 47 ++-
  1 file changed, 20 insertions(+), 27 deletions(-)

diff --git a/hw/pci-host/pnv_phb.c b/hw/pci-host/pnv_phb.c
index 4ea33fb6ba..7b11f1e8dd 100644
--- a/hw/pci-host/pnv_phb.c
+++ b/hw/pci-host/pnv_phb.c
@@ -62,29 +62,6 @@ static bool pnv_parent_fixup(Object *parent, BusState 
*parent_bus,
  return true;
  }
  
-/*

- * Attach a root port device.
- *
- * 'index' will be used both as a PCIE slot value and to calculate
- * QOM id. 'chip_id' is going to be used as PCIE chassis for the
- * root port.
- */
-static void pnv_phb_attach_root_port(PCIHostState *pci)
-{
-PCIDevice *root = pci_new(PCI_DEVFN(0, 0), TYPE_PNV_PHB_ROOT_PORT);
-const char *dev_id = DEVICE(root)->id;
-g_autofree char *default_id = NULL;
-int index;
-
-index = object_property_get_int(OBJECT(pci->bus), "phb-id", _fatal);
-default_id = g_strdup_printf("%s[%d]", TYPE_PNV_PHB_ROOT_PORT, index);
-
-object_property_add_child(OBJECT(pci->bus), dev_id ? dev_id : default_id,
-  OBJECT(root));
-
-pci_realize_and_unref(root, pci->bus, _fatal);
-}
-
  /*
   * User created devices won't have the initial setup that default
   * devices have. This setup consists of assigning a parent device
@@ -180,11 +157,11 @@ static void pnv_phb_realize(DeviceState *dev, Error 
**errp)
  pnv_phb4_bus_init(dev, PNV_PHB4(phb->backend));
  }
  
-if (!defaults_enabled()) {

-return;
-}
+if (defaults_enabled()) {
+PCIDevice *root = pci_new(PCI_DEVFN(0, 0), TYPE_PNV_PHB_ROOT_PORT);
  
-pnv_phb_attach_root_port(pci);

+pci_realize_and_unref(root, pci->bus, errp);
+}
  }
  
  static const char *pnv_phb_root_bus_path(PCIHostState *host_bridge,

@@ -259,6 +236,11 @@ static void pnv_phb_root_port_realize(DeviceState *dev, 
Error **errp)
  Error *local_err = NULL;
  int chip_id, index;
  
+/*

+ * 'index' will be used both as a PCIE slot value and to calculate
+ * QOM id. 'chip_id' is going to be used as PCIE chassis for the
+ * root port.
+ */
  chip_id = object_property_get_int(OBJECT(bus), "chip-id", _fatal);
  index = object_property_get_int(OBJECT(bus), "phb-id", _fatal);
  
@@ -266,6 +248,17 @@ static void pnv_phb_root_port_realize(DeviceState *dev, Error **errp)

  qdev_prop_set_uint8(dev, "chassis", chip_id);
  qdev_prop_set_uint16(dev, "slot", index);
  
+/*

+ * User created root ports are QOM parented to one of
+ * the peripheral containers but it's already at the right
+ * parent bus. Change the QOM parent to be the same as the
+ * parent bus it's already assigned to.
+ */
+if (!pnv_parent_fixup(OBJECT(bus), BUS(bus), OBJECT(dev),
+  index, errp)) {
+return;
+}
+
  rpc->parent_realize(dev, _err);
  if (local_err) {
  error_propagate(errp, local_err);




Re: [PATCH for-7.2 v2 1/2] ppc/pnv: consolidate pnv_parent_*_fixup() helpers

2022-08-23 Thread Frederic Barrat




On 19/08/2022 11:47, Daniel Henrique Barboza wrote:

We have 2 helpers that amends the QOM and parent bus of a given object,
repectively. These 2 helpers are called together, and not by accident.
Due to QOM internals, doing an object_unparent() will result in the
device being removed from its parent bus. This means that changing the
QOM parent requires reassigning the parent bus again.

Create a single helper called pnv_parent_fixup(), documenting some of
the QOM specifics that we're dealing with the unparenting/parenting
mechanics, and handle both the QOM and the parent bus assignment.

Next patch will make use of this function to handle a case where we need
to change the QOM parent while keeping the same parent bus assigned
beforehand.

Signed-off-by: Daniel Henrique Barboza 
---


Thanks for the explanation.

Reviewed-by: Frederic Barrat 




  hw/pci-host/pnv_phb.c | 43 ---
  1 file changed, 28 insertions(+), 15 deletions(-)

diff --git a/hw/pci-host/pnv_phb.c b/hw/pci-host/pnv_phb.c
index 17d9960aa1..4ea33fb6ba 100644
--- a/hw/pci-host/pnv_phb.c
+++ b/hw/pci-host/pnv_phb.c
@@ -21,34 +21,45 @@
  
  
  /*

- * Set the QOM parent of an object child. If the device state
- * associated with the child has an id, use it as QOM id. Otherwise
- * use object_typename[index] as QOM id.
+ * Set the QOM parent and parent bus of an object child. If the device
+ * state associated with the child has an id, use it as QOM id.
+ * Otherwise use object_typename[index] as QOM id.
+ *
+ * This helper does both operations at the same time because seting
+ * a new QOM child will erase the bus parent of the device. This happens
+ * because object_unparent() will call object_property_del_child(),
+ * which in turn calls the property release callback prop->release if
+ * it's defined. In our case this callback is set to
+ * object_finalize_child_property(), which was assigned during the
+ * first object_property_add_child() call. This callback will end up
+ * calling device_unparent(), and this function removes the device
+ * from its parent bus.
+ *
+ * The QOM and parent bus to be set aren´t necessarily related, so
+ * let's receive both as arguments.
   */
-static void pnv_parent_qom_fixup(Object *parent, Object *child, int index)
+static bool pnv_parent_fixup(Object *parent, BusState *parent_bus,
+ Object *child, int index,
+ Error **errp)
  {
  g_autofree char *default_id =
  g_strdup_printf("%s[%d]", object_get_typename(child), index);
  const char *dev_id = DEVICE(child)->id;
  
  if (child->parent == parent) {

-return;
+return true;
  }
  
  object_ref(child);

  object_unparent(child);
  object_property_add_child(parent, dev_id ? dev_id : default_id, child);
  object_unref(child);
-}
-
-static void pnv_parent_bus_fixup(DeviceState *parent, DeviceState *child,
- Error **errp)
-{
-BusState *parent_bus = qdev_get_parent_bus(parent);
  
-if (!qdev_set_parent_bus(child, parent_bus, errp)) {

-return;
+if (!qdev_set_parent_bus(DEVICE(child), parent_bus, errp)) {
+return false;
  }
+
+return true;
  }
  
  /*

@@ -101,8 +112,10 @@ static bool pnv_phb_user_device_init(PnvPHB *phb, Error 
**errp)
   * correctly the device tree. pnv_xscom_dt() needs every
   * PHB to be a child of the chip to build the DT correctly.
   */
-pnv_parent_qom_fixup(parent, OBJECT(phb), phb->phb_id);
-pnv_parent_bus_fixup(DEVICE(chip), DEVICE(phb), errp);
+if (!pnv_parent_fixup(parent, qdev_get_parent_bus(DEVICE(chip)),
+  OBJECT(phb), phb->phb_id, errp)) {
+return false;
+}
  
  return true;

  }




Re: [PATCH for-7.2 v4 06/11] ppc/pnv: enable user created pnv-phb for powernv8

2022-08-12 Thread Frederic Barrat




On 11/08/2022 18:39, Daniel Henrique Barboza wrote:

The bulk of the work was already done by previous patches.

Use defaults_enabled() to determine whether we need to create the
default devices or not.

Reviewed-by: Cédric Le Goater 
Signed-off-by: Daniel Henrique Barboza 
---



The QOM relationship for user-created root port is not ideal, but it's 
addressed in the last patch of the series.

Reviewed-by: Frederic Barrat 

  Fred



  hw/pci-host/pnv_phb.c |  9 +++--
  hw/ppc/pnv.c  | 32 ++--
  2 files changed, 25 insertions(+), 16 deletions(-)

diff --git a/hw/pci-host/pnv_phb.c b/hw/pci-host/pnv_phb.c
index 5dc44f45d1..1f53ff77c5 100644
--- a/hw/pci-host/pnv_phb.c
+++ b/hw/pci-host/pnv_phb.c
@@ -17,6 +17,7 @@
  #include "hw/ppc/pnv.h"
  #include "hw/qdev-properties.h"
  #include "qom/object.h"
+#include "sysemu/sysemu.h"
  
  
  /*

@@ -166,6 +167,10 @@ static void pnv_phb_realize(DeviceState *dev, Error **errp)
  pnv_phb4_bus_init(dev, PNV_PHB4(phb->backend));
  }
  
+if (phb->version == 3 && !defaults_enabled()) {

+return;
+}
+
  pnv_phb_attach_root_port(pci);
  }
  
@@ -201,7 +206,7 @@ static void pnv_phb_class_init(ObjectClass *klass, void *data)

  dc->realize = pnv_phb_realize;
  device_class_set_props(dc, pnv_phb_properties);
  set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
-dc->user_creatable = false;
+dc->user_creatable = true;
  }
  
  static void pnv_phb_root_port_reset(DeviceState *dev)

@@ -292,7 +297,7 @@ static void pnv_phb_root_port_class_init(ObjectClass 
*klass, void *data)
  device_class_set_parent_reset(dc, pnv_phb_root_port_reset,
>parent_reset);
  dc->reset = _phb_root_port_reset;
-dc->user_creatable = false;
+dc->user_creatable = true;
  
  k->vendor_id = PCI_VENDOR_ID_IBM;

  /* device_id will be written during realize() */
diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index e53e9e297d..e82d6522f0 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -1178,20 +1178,22 @@ static void pnv_chip_power8_instance_init(Object *obj)
  
  object_initialize_child(obj, "homer", >homer, TYPE_PNV8_HOMER);
  
-chip8->num_phbs = pcc->num_phbs;

-
-for (i = 0; i < chip8->num_phbs; i++) {
-Object *phb = object_new(TYPE_PNV_PHB);
-
-/*
- * We need the chip to parent the PHB to allow the DT
- * to build correctly (via pnv_xscom_dt()).
- *
- * TODO: the PHB should be parented by a PEC device that, at
- * this moment, is not modelled powernv8/phb3.
- */
-object_property_add_child(obj, "phb[*]", phb);
-chip8->phbs[i] = PNV_PHB(phb);
+if (defaults_enabled()) {
+chip8->num_phbs = pcc->num_phbs;
+
+for (i = 0; i < chip8->num_phbs; i++) {
+Object *phb = object_new(TYPE_PNV_PHB);
+
+/*
+ * We need the chip to parent the PHB to allow the DT
+ * to build correctly (via pnv_xscom_dt()).
+ *
+ * TODO: the PHB should be parented by a PEC device that, at
+ * this moment, is not modelled powernv8/phb3.
+ */
+object_property_add_child(obj, "phb[*]", phb);
+chip8->phbs[i] = PNV_PHB(phb);
+}
  }
  
  }

@@ -2130,6 +2132,8 @@ static void pnv_machine_power8_class_init(ObjectClass 
*oc, void *data)
  
  pmc->compat = compat;

  pmc->compat_size = sizeof(compat);
+
+machine_class_allow_dynamic_sysbus_dev(mc, TYPE_PNV_PHB);
  }
  
  static void pnv_machine_power9_class_init(ObjectClass *oc, void *data)




Re: [PATCH for-7.2 v4 08/11] ppc/pnv: enable user created pnv-phb for powernv9

2022-08-12 Thread Frederic Barrat




On 11/08/2022 18:39, Daniel Henrique Barboza wrote:

Enable pnv-phb user created devices for powernv9 now that we have
everything in place.

Reviewed-by: Cédric Le Goater 
Signed-off-by: Daniel Henrique Barboza 
---



Same comment as in patch 6 regarding the QOM relationship of the 
user-created root port.

Reviewed-by: Frederic Barrat 

  Fred



  hw/pci-host/pnv_phb.c  | 2 +-
  hw/pci-host/pnv_phb4_pec.c | 6 --
  hw/ppc/pnv.c   | 2 ++
  3 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/hw/pci-host/pnv_phb.c b/hw/pci-host/pnv_phb.c
index 1f53ff77c5..17d9960aa1 100644
--- a/hw/pci-host/pnv_phb.c
+++ b/hw/pci-host/pnv_phb.c
@@ -167,7 +167,7 @@ static void pnv_phb_realize(DeviceState *dev, Error **errp)
  pnv_phb4_bus_init(dev, PNV_PHB4(phb->backend));
  }
  
-if (phb->version == 3 && !defaults_enabled()) {

+if (!defaults_enabled()) {
  return;
  }
  
diff --git a/hw/pci-host/pnv_phb4_pec.c b/hw/pci-host/pnv_phb4_pec.c

index 8dc363d69c..9871f462cd 100644
--- a/hw/pci-host/pnv_phb4_pec.c
+++ b/hw/pci-host/pnv_phb4_pec.c
@@ -146,8 +146,10 @@ static void pnv_pec_realize(DeviceState *dev, Error **errp)
  pec->num_phbs = pecc->num_phbs[pec->index];
  
  /* Create PHBs if running with defaults */

-for (i = 0; i < pec->num_phbs; i++) {
-pnv_pec_default_phb_realize(pec, i, errp);
+if (defaults_enabled()) {
+for (i = 0; i < pec->num_phbs; i++) {
+pnv_pec_default_phb_realize(pec, i, errp);
+}
  }
  
  /* Initialize the XSCOM regions for the PEC registers */

diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index 0644f45a1d..ec0558ed1c 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -2188,6 +2188,8 @@ static void pnv_machine_power9_class_init(ObjectClass 
*oc, void *data)
  pmc->compat = compat;
  pmc->compat_size = sizeof(compat);
  pmc->dt_power_mgt = pnv_dt_power_mgt;
+
+machine_class_allow_dynamic_sysbus_dev(mc, TYPE_PNV_PHB);
  }
  
  static void pnv_machine_power10_class_init(ObjectClass *oc, void *data)




Re: [PATCH for-7.2 v4 11/11] ppc/pnv: fix QOM parenting of user creatable root ports

2022-08-12 Thread Frederic Barrat




On 11/08/2022 18:39, Daniel Henrique Barboza wrote:

User creatable root ports are being parented by the 'peripheral' or the
'peripheral-anon' container. This happens because this is the regular
QOM schema for sysbus devices that are added via the command line.

Let's make this QOM hierarchy similar to what we have with default root
ports, i.e. the root port must be parented by the pnv-root-bus. To do
that we change the qom and bus parent of the root port during
root_port_realize(). The realize() is shared by the default root port
code path, so we can remove the code inside pnv_phb_attach_root_port()
that was adding the root port as a child of the bus as well.

While we're at it, change pnv_phb_attach_root_port() to receive a PCIBus
instead of a PCIHostState to make it clear that the function does not
make use of the PHB.

Signed-off-by: Daniel Henrique Barboza 
---
  hw/pci-host/pnv_phb.c | 35 +++
  1 file changed, 15 insertions(+), 20 deletions(-)

diff --git a/hw/pci-host/pnv_phb.c b/hw/pci-host/pnv_phb.c
index 17d9960aa1..65ed1f9eb4 100644
--- a/hw/pci-host/pnv_phb.c
+++ b/hw/pci-host/pnv_phb.c
@@ -51,27 +51,11 @@ static void pnv_parent_bus_fixup(DeviceState *parent, 
DeviceState *child,
  }
  }
  
-/*

- * Attach a root port device.
- *
- * 'index' will be used both as a PCIE slot value and to calculate
- * QOM id. 'chip_id' is going to be used as PCIE chassis for the
- * root port.
- */
-static void pnv_phb_attach_root_port(PCIHostState *pci)
+static void pnv_phb_attach_root_port(PCIBus *bus)
  {
  PCIDevice *root = pci_new(PCI_DEVFN(0, 0), TYPE_PNV_PHB_ROOT_PORT);
-const char *dev_id = DEVICE(root)->id;
-g_autofree char *default_id = NULL;
-int index;
-
-index = object_property_get_int(OBJECT(pci->bus), "phb-id", _fatal);
-default_id = g_strdup_printf("%s[%d]", TYPE_PNV_PHB_ROOT_PORT, index);
-
-object_property_add_child(OBJECT(pci->bus), dev_id ? dev_id : default_id,
-  OBJECT(root));
  
-pci_realize_and_unref(root, pci->bus, _fatal);

+pci_realize_and_unref(root, bus, _fatal);
  }
  
  /*

@@ -171,7 +155,7 @@ static void pnv_phb_realize(DeviceState *dev, Error **errp)
  return;
  }
  
-pnv_phb_attach_root_port(pci);

+pnv_phb_attach_root_port(pci->bus);
  }
  
  static const char *pnv_phb_root_bus_path(PCIHostState *host_bridge,

@@ -240,12 +224,18 @@ static void pnv_phb_root_port_realize(DeviceState *dev, 
Error **errp)
  {
  PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(dev);
  PnvPHBRootPort *phb_rp = PNV_PHB_ROOT_PORT(dev);
-PCIBus *bus = PCI_BUS(qdev_get_parent_bus(dev));
+BusState *qbus = qdev_get_parent_bus(dev);
+PCIBus *bus = PCI_BUS(qbus);
  PCIDevice *pci = PCI_DEVICE(dev);
  uint16_t device_id = 0;
  Error *local_err = NULL;
  int chip_id, index;
  
+/*

+ * 'index' will be used both as a PCIE slot value and to calculate
+ * QOM id. 'chip_id' is going to be used as PCIE chassis for the
+ * root port.
+ */
  chip_id = object_property_get_int(OBJECT(bus), "chip-id", _fatal);
  index = object_property_get_int(OBJECT(bus), "phb-id", _fatal);
  
@@ -253,6 +243,11 @@ static void pnv_phb_root_port_realize(DeviceState *dev, Error **errp)

  qdev_prop_set_uint8(dev, "chassis", chip_id);
  qdev_prop_set_uint16(dev, "slot", index);
  
+pnv_parent_qom_fixup(OBJECT(bus), OBJECT(dev), index);

+if (!qdev_set_parent_bus(dev, qbus, _fatal)) {



That line looks surprising at first, because we got qbus from 
qdev_get_parent_bus() just above, so it looks like a noop. I talked to 
Daniel about it: the device<->bus relationship is correct when entering 
the function but the call to pnv_parent_qom_fixup() interferes with the 
bus relationship, so it needs to be re-established.

Short of a better suggestion, it probably need a comment.

  Fred




+return;
+}
+
  rpc->parent_realize(dev, _err);
  if (local_err) {
  error_propagate(errp, local_err);




Re: [PATCH for-7.2 v4 10/11] ppc/pnv: user creatable pnv-phb for powernv10

2022-08-12 Thread Frederic Barrat




On 11/08/2022 18:39, Daniel Henrique Barboza wrote:

Given that powernv9 and powernv10 uses the same pnv-phb backend, the
logic to allow user created pnv-phbs for powernv10 is already in place.
Let's flip the switch.

Reviewed-by: Cédric Le Goater 
Signed-off-by: Daniel Henrique Barboza 
---



Reviewed-by: Frederic Barrat 

  Fred



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

diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index e6c14fe231..9bf35ca9d6 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -2226,6 +2226,8 @@ static void pnv_machine_power10_class_init(ObjectClass 
*oc, void *data)
  pmc->dt_power_mgt = pnv_dt_power_mgt;
  
  xfc->match_nvt = pnv10_xive_match_nvt;

+
+machine_class_allow_dynamic_sysbus_dev(mc, TYPE_PNV_PHB);
  }
  
  static bool pnv_machine_get_hb(Object *obj, Error **errp)




Re: [PATCH for-7.2 v4 09/11] ppc/pnv: change pnv_phb4_get_pec() to also retrieve chip10->pecs

2022-08-12 Thread Frederic Barrat




On 11/08/2022 18:39, Daniel Henrique Barboza wrote:

The function assumes that we're always dealing with a PNV9_CHIP()
object. This is not the case when the pnv-phb device belongs to a
powernv10 machine.

Change pnv_phb4_get_pec() to be able to work with PNV10_CHIP() if
necessary.

Signed-off-by: Daniel Henrique Barboza 
---



Reviewed-by: Frederic Barrat 

  Fred



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

diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index ec0558ed1c..e6c14fe231 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -284,17 +284,30 @@ static void pnv_dt_icp(PnvChip *chip, void *fdt, uint32_t 
pir,
  static PnvPhb4PecState *pnv_phb4_get_pec(PnvChip *chip, PnvPHB4 *phb,
   Error **errp)
  {
-Pnv9Chip *chip9 = PNV9_CHIP(chip);
+PnvPHB *phb_base = phb->phb_base;
+PnvPhb4PecState *pecs = NULL;
  int chip_id = phb->chip_id;
  int index = phb->phb_id;
  int i, j;
  
+if (phb_base->version == 4) {

+Pnv9Chip *chip9 = PNV9_CHIP(chip);
+
+pecs = chip9->pecs;
+} else if (phb_base->version == 5) {
+Pnv10Chip *chip10 = PNV10_CHIP(chip);
+
+pecs = chip10->pecs;
+} else {
+g_assert_not_reached();
+}
+
  for (i = 0; i < chip->num_pecs; i++) {
  /*
   * For each PEC, check the amount of phbs it supports
   * and see if the given phb4 index matches an index.
   */
-PnvPhb4PecState *pec = >pecs[i];
+PnvPhb4PecState *pec = [i];
  
  for (j = 0; j < pec->num_phbs; j++) {

  if (index == pnv_phb4_pec_get_phb_id(pec, j)) {




Re: [PATCH for-7.2 v4 07/11] ppc/pnv: add PHB4 helpers for user created pnv-phb

2022-08-12 Thread Frederic Barrat




On 11/08/2022 18:39, Daniel Henrique Barboza wrote:

The PHB4 backend relies on a link with the corresponding PEC element.
This is trivial to do during machine_init() time for default devices,
but not so much for user created ones.

pnv_phb4_get_pec() is a small variation of the function that was
reverted by commit 9c10d86fee "ppc/pnv: Remove user-created PHB{3,4,5}
devices". We'll use it to determine the appropriate PEC for a given user
created pnv-phb that uses a PHB4 backend.

This is done during realize() time, in pnv_phb_user_device_init().

Signed-off-by: Daniel Henrique Barboza 
---



Reviewed-by: Frederic Barrat 

  Fred



  hw/ppc/pnv.c | 35 ---
  1 file changed, 32 insertions(+), 3 deletions(-)

diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index e82d6522f0..0644f45a1d 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -281,6 +281,34 @@ static void pnv_dt_icp(PnvChip *chip, void *fdt, uint32_t 
pir,
  g_free(reg);
  }
  
+static PnvPhb4PecState *pnv_phb4_get_pec(PnvChip *chip, PnvPHB4 *phb,

+ Error **errp)
+{
+Pnv9Chip *chip9 = PNV9_CHIP(chip);
+int chip_id = phb->chip_id;
+int index = phb->phb_id;
+int i, j;
+
+for (i = 0; i < chip->num_pecs; i++) {
+/*
+ * For each PEC, check the amount of phbs it supports
+ * and see if the given phb4 index matches an index.
+ */
+PnvPhb4PecState *pec = >pecs[i];
+
+for (j = 0; j < pec->num_phbs; j++) {
+if (index == pnv_phb4_pec_get_phb_id(pec, j)) {
+return pec;
+}
+}
+}
+error_setg(errp,
+   "pnv-phb4 chip-id %d index %d didn't match any existing PEC",
+   chip_id, index);
+
+return NULL;
+}
+
  /*
   * Adds a PnvPHB to the chip. Returns the parent obj of the
   * PHB which varies with each version (phb version 3 is parented
@@ -302,10 +330,11 @@ Object *pnv_chip_add_phb(PnvChip *chip, PnvPHB *phb, 
Error **errp)
  chip8->num_phbs++;
  
  return OBJECT(chip);

-} else {
-/* phb4 support will be added later */
-return NULL;
  }
+
+phb->pec = pnv_phb4_get_pec(chip, PNV_PHB4(phb->backend), errp);
+
+return OBJECT(phb->pec);
  }
  
  static void pnv_chip_power8_dt_populate(PnvChip *chip, void *fdt)




Re: [PATCH for-7.2 v4 05/11] ppc/pnv: turn chip8->phbs[] into a PnvPHB* array

2022-08-12 Thread Frederic Barrat




On 11/08/2022 18:39, Daniel Henrique Barboza wrote:

When enabling user created PHBs (a change reverted by commit 9c10d86fee)
we were handling PHBs created by default versus by the user in different
manners. The only difference between these PHBs is that one will have a
valid phb3->chip that is assigned during pnv_chip_power8_realize(),
while the user created needs to search which chip it belongs to.

Aside from that there shouldn't be any difference. Making the default
PHBs behave in line with the user created ones will make it easier to
re-introduce them later on. It will also make the code easier to follow
since we are dealing with them in equal manner.

The first step is to turn chip8->phbs[] into a PnvPHB3 pointer array.
This will allow us to assign user created PHBs into it later on. The way
we initilize the default case is now more in line with that would happen
with the user created case: the object is created, parented by the chip
because pnv_xscom_dt() relies on it, and then assigned to the array.

Signed-off-by: Daniel Henrique Barboza 
---



Reviewed-by: Frederic Barrat 

  Fred



  hw/ppc/pnv.c | 27 ++-
  include/hw/ppc/pnv.h |  6 +-
  2 files changed, 27 insertions(+), 6 deletions(-)

diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index 2deaac17f7..e53e9e297d 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -294,6 +294,13 @@ static void pnv_dt_icp(PnvChip *chip, void *fdt, uint32_t 
pir,
  Object *pnv_chip_add_phb(PnvChip *chip, PnvPHB *phb, Error **errp)
  {
  if (phb->version == 3) {
+Pnv8Chip *chip8 = PNV8_CHIP(chip);
+
+phb->chip = chip;
+
+chip8->phbs[chip8->num_phbs] = phb;
+chip8->num_phbs++;
+
  return OBJECT(chip);
  } else {
  /* phb4 support will be added later */
@@ -681,7 +688,7 @@ static void pnv_chip_power8_pic_print_info(PnvChip *chip, 
Monitor *mon)
  ics_pic_print_info(>psi.ics, mon);
  
  for (i = 0; i < chip8->num_phbs; i++) {

-PnvPHB *phb = >phbs[i];
+PnvPHB *phb = chip8->phbs[i];
  PnvPHB3 *phb3 = PNV_PHB3(phb->backend);
  
  pnv_phb3_msi_pic_print_info(>msis, mon);

@@ -1174,7 +1181,17 @@ static void pnv_chip_power8_instance_init(Object *obj)
  chip8->num_phbs = pcc->num_phbs;
  
  for (i = 0; i < chip8->num_phbs; i++) {

-object_initialize_child(obj, "phb[*]", >phbs[i], TYPE_PNV_PHB);
+Object *phb = object_new(TYPE_PNV_PHB);
+
+/*
+ * We need the chip to parent the PHB to allow the DT
+ * to build correctly (via pnv_xscom_dt()).
+ *
+ * TODO: the PHB should be parented by a PEC device that, at
+ * this moment, is not modelled powernv8/phb3.
+ */
+object_property_add_child(obj, "phb[*]", phb);
+chip8->phbs[i] = PNV_PHB(phb);
  }
  
  }

@@ -1290,7 +1307,7 @@ static void pnv_chip_power8_realize(DeviceState *dev, 
Error **errp)
  
  /* PHB controllers */

  for (i = 0; i < chip8->num_phbs; i++) {
-PnvPHB *phb = >phbs[i];
+PnvPHB *phb = chip8->phbs[i];
  
  object_property_set_int(OBJECT(phb), "index", i, _fatal);

  object_property_set_int(OBJECT(phb), "chip-id", chip->chip_id,
@@ -1958,7 +1975,7 @@ static ICSState *pnv_ics_get(XICSFabric *xi, int irq)
  }
  
  for (j = 0; j < chip8->num_phbs; j++) {

-PnvPHB *phb = >phbs[j];
+PnvPHB *phb = chip8->phbs[j];
  PnvPHB3 *phb3 = PNV_PHB3(phb->backend);
  
  if (ics_valid_irq(>lsis, irq)) {

@@ -1997,7 +2014,7 @@ static void pnv_ics_resend(XICSFabric *xi)
  ics_resend(>psi.ics);
  
  for (j = 0; j < chip8->num_phbs; j++) {

-PnvPHB *phb = >phbs[j];
+PnvPHB *phb = chip8->phbs[j];
  PnvPHB3 *phb3 = PNV_PHB3(phb->backend);
  
  ics_resend(>lsis);

diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h
index 781d0acffa..49433281d7 100644
--- a/include/hw/ppc/pnv.h
+++ b/include/hw/ppc/pnv.h
@@ -81,7 +81,11 @@ struct Pnv8Chip {
  PnvHomer homer;
  
  #define PNV8_CHIP_PHB3_MAX 4

-PnvPHB   phbs[PNV8_CHIP_PHB3_MAX];
+/*
+ * The array is used to allow quick access to the phbs by
+ * pnv_ics_get_child() and pnv_ics_resend_child().
+ */
+PnvPHB   *phbs[PNV8_CHIP_PHB3_MAX];
  uint32_t num_phbs;
  
  XICSFabric*xics;




Re: [PATCH for-7.2 v4 04/11] ppc/pnv: add helpers for pnv-phb user devices

2022-08-12 Thread Frederic Barrat




On 11/08/2022 18:39, Daniel Henrique Barboza wrote:

pnv_parent_qom_fixup() and pnv_parent_bus_fixup() are versions of the
helpers that were reverted by commit 9c10d86fee "ppc/pnv: Remove
user-created PHB{3,4,5} devices". They are needed to amend the QOM and
bus hierarchies of user created pnv-phbs, matching them with default
pnv-phbs.

A new helper pnv_phb_user_device_init() is created to handle
user-created devices setup. We're going to call it inside
pnv_phb_realize() in case we're realizing an user created device. This
will centralize all user device realated in a single spot, leaving the
realize functions of the phb3/phb4 backends untouched.

Another helper called pnv_chip_add_phb() was added to handle the
particularities of each chip version when adding a new PHB.

Signed-off-by: Daniel Henrique Barboza 
---



Just a minor typo in a comment below.
Reviewed-by: Frederic Barrat 



diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index f9e5a3d248..2deaac17f7 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -281,6 +281,26 @@ static void pnv_dt_icp(PnvChip *chip, void *fdt, uint32_t 
pir,
  g_free(reg);
  }
  
+/*

+ * Adds a PnvPHB to the chip. Returns the parent obj of the
+ * PHB which varies with each version (phb version 3 is parented
+ * by the chip, version 4 and 4 are parented by the PEC



typo-^

  Fred



+ * device).
+ *
+ * TODO: for version 3 we're still parenting the PHB with the
+ * chip. We should parent with a (so far not implemented)
+ * PHB3 PEC device.
+ */
+Object *pnv_chip_add_phb(PnvChip *chip, PnvPHB *phb, Error **errp)
+{
+if (phb->version == 3) {
+return OBJECT(chip);
+} else {
+/* phb4 support will be added later */
+return NULL;
+}
+}
+
  static void pnv_chip_power8_dt_populate(PnvChip *chip, void *fdt)
  {
  static const char compat[] = "ibm,power8-xscom\0ibm,xscom";
diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h
index 033d907287..781d0acffa 100644
--- a/include/hw/ppc/pnv.h
+++ b/include/hw/ppc/pnv.h
@@ -231,6 +231,7 @@ struct PnvMachineState {
  };
  
  PnvChip *pnv_get_chip(PnvMachineState *pnv, uint32_t chip_id);

+Object *pnv_chip_add_phb(PnvChip *chip, PnvPHB *phb, Error **errp);
  
  #define PNV_FDT_ADDR  0x0100

  #define PNV_TIMEBASE_FREQ 51200ULL




Re: [PATCH for-7.2 v4 01/11] ppc/pnv: add phb-id/chip-id PnvPHB3RootBus properties

2022-08-12 Thread Frederic Barrat




On 11/08/2022 18:39, Daniel Henrique Barboza wrote:

We rely on the phb-id and chip-id, which are PHB properties, to assign
chassis and slot to the root port. For default devices this is no big
deal: the root port is being created under pnv_phb_realize() and the
values are being passed on via the 'index' and 'chip-id' of the
pnv_phb_attach_root_port() helper.

If we want to implement user created root ports we have a problem. The
user created root port will not be aware of which PHB it belongs to,
unless we're willing to violate QOM best practices and access the PHB
via dev->parent_bus->parent. What we can do is to access the root bus
parent bus.

Since we're already assigning the root port as QOM child of the bus, and
the bus is initiated using PHB properties, let's add phb-id and chip-id
as properties of the bus. This will allow us trivial access to them, for
both user-created and default root ports, without doing anything too
shady with QOM.

Reviewed-by: Cédric Le Goater 
Signed-off-by: Daniel Henrique Barboza 
---



Reviewed-by: Frederic Barrat 

  Fred



  hw/pci-host/pnv_phb3.c | 50 ++
  include/hw/pci-host/pnv_phb3.h |  9 +-
  2 files changed, 58 insertions(+), 1 deletion(-)

diff --git a/hw/pci-host/pnv_phb3.c b/hw/pci-host/pnv_phb3.c
index d4c04a281a..af8575c007 100644
--- a/hw/pci-host/pnv_phb3.c
+++ b/hw/pci-host/pnv_phb3.c
@@ -1006,6 +1006,11 @@ void pnv_phb3_bus_init(DeviceState *dev, PnvPHB3 *phb)
   >pci_mmio, >pci_io,
   0, 4, TYPE_PNV_PHB3_ROOT_BUS);
  
+object_property_set_int(OBJECT(pci->bus), "phb-id", phb->phb_id,

+_abort);
+object_property_set_int(OBJECT(pci->bus), "chip-id", phb->chip_id,
+_abort);
+
  pci_setup_iommu(pci->bus, pnv_phb3_dma_iommu, phb);
  }
  
@@ -1105,10 +1110,55 @@ static const TypeInfo pnv_phb3_type_info = {

  .instance_init = pnv_phb3_instance_init,
  };
  
+static void pnv_phb3_root_bus_get_prop(Object *obj, Visitor *v,

+   const char *name,
+   void *opaque, Error **errp)
+{
+PnvPHB3RootBus *bus = PNV_PHB3_ROOT_BUS(obj);
+uint64_t value = 0;
+
+if (strcmp(name, "phb-id") == 0) {
+value = bus->phb_id;
+} else {
+value = bus->chip_id;
+}
+
+visit_type_size(v, name, , errp);
+}
+
+static void pnv_phb3_root_bus_set_prop(Object *obj, Visitor *v,
+   const char *name,
+   void *opaque, Error **errp)
+
+{
+PnvPHB3RootBus *bus = PNV_PHB3_ROOT_BUS(obj);
+uint64_t value;
+
+if (!visit_type_size(v, name, , errp)) {
+return;
+}
+
+if (strcmp(name, "phb-id") == 0) {
+bus->phb_id = value;
+} else {
+bus->chip_id = value;
+}
+}
+
  static void pnv_phb3_root_bus_class_init(ObjectClass *klass, void *data)
  {
  BusClass *k = BUS_CLASS(klass);
  
+object_class_property_add(klass, "phb-id", "int",

+  pnv_phb3_root_bus_get_prop,
+  pnv_phb3_root_bus_set_prop,
+  NULL, NULL);
+
+object_class_property_add(klass, "chip-id", "int",
+  pnv_phb3_root_bus_get_prop,
+  pnv_phb3_root_bus_set_prop,
+  NULL, NULL);
+
  /*
   * PHB3 has only a single root complex. Enforce the limit on the
   * parent bus
diff --git a/include/hw/pci-host/pnv_phb3.h b/include/hw/pci-host/pnv_phb3.h
index bff69201d9..4854f6d2f6 100644
--- a/include/hw/pci-host/pnv_phb3.h
+++ b/include/hw/pci-host/pnv_phb3.h
@@ -104,9 +104,16 @@ struct PnvPBCQState {
  };
  
  /*

- * PHB3 PCIe Root port
+ * PHB3 PCIe Root Bus
   */
  #define TYPE_PNV_PHB3_ROOT_BUS "pnv-phb3-root"
+struct PnvPHB3RootBus {
+PCIBus parent;
+
+uint32_t chip_id;
+uint32_t phb_id;
+};
+OBJECT_DECLARE_SIMPLE_TYPE(PnvPHB3RootBus, PNV_PHB3_ROOT_BUS)
  
  /*

   * PHB3 PCIe Host Bridge for PowerNV machines (POWER8)




Re: [PATCH for-7.2 v4 03/11] ppc/pnv: set root port chassis and slot using Bus properties

2022-08-12 Thread Frederic Barrat




On 11/08/2022 18:39, Daniel Henrique Barboza wrote:

For default root ports we have a way of accessing chassis and slot,
before root_port_realize(), via pnv_phb_attach_root_port(). For the
future user created root ports this won't be the case: we can't use
this helper because we don't have access to the PHB phb-id/chip-id
values.

In earlier patches we've added phb-id and chip-id to pnv-phb-root-bus
objects. We're now able to use the bus to retrieve them. The bus is
reachable for both user created and default devices, so we're changing
all the code paths. This also allow us to validate these changes with
the existing default devices.

Reviewed-by: Cédric Le Goater 
Signed-off-by: Daniel Henrique Barboza 
---



Reviewed-by: Frederic Barrat 

  Fred



  hw/pci-host/pnv_phb.c | 25 -
  1 file changed, 16 insertions(+), 9 deletions(-)

diff --git a/hw/pci-host/pnv_phb.c b/hw/pci-host/pnv_phb.c
index c47ed92462..826c0c144e 100644
--- a/hw/pci-host/pnv_phb.c
+++ b/hw/pci-host/pnv_phb.c
@@ -25,21 +25,19 @@
   * QOM id. 'chip_id' is going to be used as PCIE chassis for the
   * root port.
   */
-static void pnv_phb_attach_root_port(PCIHostState *pci, int index, int chip_id)
+static void pnv_phb_attach_root_port(PCIHostState *pci)
  {
  PCIDevice *root = pci_new(PCI_DEVFN(0, 0), TYPE_PNV_PHB_ROOT_PORT);
-g_autofree char *default_id = g_strdup_printf("%s[%d]",
-  TYPE_PNV_PHB_ROOT_PORT,
-  index);
  const char *dev_id = DEVICE(root)->id;
+g_autofree char *default_id = NULL;
+int index;
+
+index = object_property_get_int(OBJECT(pci->bus), "phb-id", _fatal);
+default_id = g_strdup_printf("%s[%d]", TYPE_PNV_PHB_ROOT_PORT, index);
  
  object_property_add_child(OBJECT(pci->bus), dev_id ? dev_id : default_id,

OBJECT(root));
  
-/* Set unique chassis/slot values for the root port */

-qdev_prop_set_uint8(DEVICE(root), "chassis", chip_id);
-qdev_prop_set_uint16(DEVICE(root), "slot", index);
-
  pci_realize_and_unref(root, pci->bus, _fatal);
  }
  
@@ -93,7 +91,7 @@ static void pnv_phb_realize(DeviceState *dev, Error **errp)

  pnv_phb4_bus_init(dev, PNV_PHB4(phb->backend));
  }
  
-pnv_phb_attach_root_port(pci, phb->phb_id, phb->chip_id);

+pnv_phb_attach_root_port(pci);
  }
  
  static const char *pnv_phb_root_bus_path(PCIHostState *host_bridge,

@@ -162,9 +160,18 @@ static void pnv_phb_root_port_realize(DeviceState *dev, 
Error **errp)
  {
  PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(dev);
  PnvPHBRootPort *phb_rp = PNV_PHB_ROOT_PORT(dev);
+PCIBus *bus = PCI_BUS(qdev_get_parent_bus(dev));
  PCIDevice *pci = PCI_DEVICE(dev);
  uint16_t device_id = 0;
  Error *local_err = NULL;
+int chip_id, index;
+
+chip_id = object_property_get_int(OBJECT(bus), "chip-id", _fatal);
+index = object_property_get_int(OBJECT(bus), "phb-id", _fatal);
+
+/* Set unique chassis/slot values for the root port */
+qdev_prop_set_uint8(dev, "chassis", chip_id);
+qdev_prop_set_uint16(dev, "slot", index);
  
  rpc->parent_realize(dev, _err);

  if (local_err) {




Re: [PATCH for-7.2 v4 02/11] ppc/pnv: add phb-id/chip-id PnvPHB4RootBus properties

2022-08-12 Thread Frederic Barrat




On 11/08/2022 18:39, Daniel Henrique Barboza wrote:

The same rationale provided in the PHB3 bus case applies here.

Note: we could have merged both buses in a single object, like we did
with the root ports, and spare some boilerplate. The reason we opted to
preserve both buses objects is twofold:

- there's not user side advantage in doing so. Unifying the root ports
presents a clear user QOL change when we enable user created devices back.
The buses objects, aside from having a different QOM name, is transparent
to the user;

- we leave a door opened in case we want to increase the root port limit
for phb4/5 later on without having to deal with phb3 code.

Reviewed-by: Cédric Le Goater 
Signed-off-by: Daniel Henrique Barboza 
---



Reviewed-by: Frederic Barrat 

  Fred



  hw/pci-host/pnv_phb4.c | 51 ++
  include/hw/pci-host/pnv_phb4.h | 10 +++
  2 files changed, 61 insertions(+)

diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c
index b98c394713..824e1a73fb 100644
--- a/hw/pci-host/pnv_phb4.c
+++ b/hw/pci-host/pnv_phb4.c
@@ -1551,6 +1551,12 @@ void pnv_phb4_bus_init(DeviceState *dev, PnvPHB4 *phb)
   pnv_phb4_set_irq, pnv_phb4_map_irq, phb,
   >pci_mmio, >pci_io,
   0, 4, TYPE_PNV_PHB4_ROOT_BUS);
+
+object_property_set_int(OBJECT(pci->bus), "phb-id", phb->phb_id,
+_abort);
+object_property_set_int(OBJECT(pci->bus), "chip-id", phb->chip_id,
+_abort);
+
  pci_setup_iommu(pci->bus, pnv_phb4_dma_iommu, phb);
  pci->bus->flags |= PCI_BUS_EXTENDED_CONFIG_SPACE;
  }
@@ -1708,10 +1714,55 @@ static const TypeInfo pnv_phb5_type_info = {
  .instance_size = sizeof(PnvPHB4),
  };
  
+static void pnv_phb4_root_bus_get_prop(Object *obj, Visitor *v,

+   const char *name,
+   void *opaque, Error **errp)
+{
+PnvPHB4RootBus *bus = PNV_PHB4_ROOT_BUS(obj);
+uint64_t value = 0;
+
+if (strcmp(name, "phb-id") == 0) {
+value = bus->phb_id;
+} else {
+value = bus->chip_id;
+}
+
+visit_type_size(v, name, , errp);
+}
+
+static void pnv_phb4_root_bus_set_prop(Object *obj, Visitor *v,
+   const char *name,
+   void *opaque, Error **errp)
+
+{
+PnvPHB4RootBus *bus = PNV_PHB4_ROOT_BUS(obj);
+uint64_t value;
+
+if (!visit_type_size(v, name, , errp)) {
+return;
+}
+
+if (strcmp(name, "phb-id") == 0) {
+bus->phb_id = value;
+} else {
+bus->chip_id = value;
+}
+}
+
  static void pnv_phb4_root_bus_class_init(ObjectClass *klass, void *data)
  {
  BusClass *k = BUS_CLASS(klass);
  
+object_class_property_add(klass, "phb-id", "int",

+  pnv_phb4_root_bus_get_prop,
+  pnv_phb4_root_bus_set_prop,
+  NULL, NULL);
+
+object_class_property_add(klass, "chip-id", "int",
+  pnv_phb4_root_bus_get_prop,
+  pnv_phb4_root_bus_set_prop,
+  NULL, NULL);
+
  /*
   * PHB4 has only a single root complex. Enforce the limit on the
   * parent bus
diff --git a/include/hw/pci-host/pnv_phb4.h b/include/hw/pci-host/pnv_phb4.h
index 20aa4819d3..50d4faa001 100644
--- a/include/hw/pci-host/pnv_phb4.h
+++ b/include/hw/pci-host/pnv_phb4.h
@@ -45,7 +45,17 @@ typedef struct PnvPhb4DMASpace {
  QLIST_ENTRY(PnvPhb4DMASpace) list;
  } PnvPhb4DMASpace;
  
+/*

+ * PHB4 PCIe Root Bus
+ */
  #define TYPE_PNV_PHB4_ROOT_BUS "pnv-phb4-root"
+struct PnvPHB4RootBus {
+PCIBus parent;
+
+uint32_t chip_id;
+uint32_t phb_id;
+};
+OBJECT_DECLARE_SIMPLE_TYPE(PnvPHB4RootBus, PNV_PHB4_ROOT_BUS)
  
  /*

   * PHB4 PCIe Host Bridge for PowerNV machines (POWER9)




Re: [PATCH for-7.2 00/10] enable pnv-phb user created devices

2022-08-05 Thread Frederic Barrat

Hi Daniel,

Other than my comment on patch 6 regarding the qom parenting of the root 
port, that series looks pretty good to me!


  Fred



On 03/08/2022 15:44, Daniel Henrique Barboza wrote:

Hi,

This is a rebase on top of ppc-7.2 of the previous patches sent
here:

https://lists.gnu.org/archive/html/qemu-devel/2022-07/msg01542.html

Now that we have the pnv-phb rework in the tree.

As a recap, the changes introduced in this series compared to what we've
done in "[PATCH v2 00/16] powernv: introduce pnv-phb base/proxy
devices" [1], is:

- the Root Buses objects are now inheriting phb-id and chip-id. This
turned out to be a clean way of keeping the code QOM compliant, without
having to do things like dev->parent_bus->parent. All the attributes
that the root port needs are found in its bus parent;

- the logic exclusive to user created devices is all centered in a
single helper inside pnv-phb realize(). PHB3/PHB4 realize() are
oblivious to whether the device is user created or not. I believe this
approach is clearer than what I was doing before.

[1] https://lists.gnu.org/archive/html/qemu-devel/2022-05/msg06254.html

Daniel Henrique Barboza (10):
   ppc/pnv: add phb-id/chip-id PnvPHB3RootBus properties
   ppc/pnv: add phb-id/chip-id PnvPHB4RootBus properties
   ppc/pnv: set root port chassis and slot using Bus properties
   ppc/pnv: add helpers for pnv-phb user devices
   ppc/pnv: turn chip8->phbs[] into a PnvPHB* array
   ppc/pnv: enable user created pnv-phb for powernv8
   ppc/pnv: add PHB4 helpers for user created pnv-phb
   ppc/pnv: enable user created pnv-phb powernv9
   ppc/pnv: change pnv_phb4_get_pec() to also retrieve chip10->pecs
   ppc/pnv: user creatable pnv-phb for powernv10

  hw/pci-host/pnv_phb.c  | 166 ++---
  hw/pci-host/pnv_phb3.c |  50 ++
  hw/pci-host/pnv_phb4.c |  51 ++
  hw/pci-host/pnv_phb4_pec.c |   6 +-
  hw/ppc/pnv.c   |  30 +-
  include/hw/pci-host/pnv_phb3.h |   9 +-
  include/hw/pci-host/pnv_phb4.h |  10 ++
  include/hw/ppc/pnv.h   |   6 +-
  8 files changed, 308 insertions(+), 20 deletions(-)





Re: [PATCH for-7.2 v2 09/20] hw/ppc: set machine->fdt in pnv_reset()

2022-08-05 Thread Frederic Barrat




On 05/08/2022 11:39, Daniel Henrique Barboza wrote:

This will enable support for 'dumpdtb' and 'info fdt' HMP commands for
all powernv machines.

Cc: Cédric Le Goater 
Cc: Frederic Barrat 
Signed-off-by: Daniel Henrique Barboza 
---
  hw/ppc/pnv.c | 6 +-
  1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index d3f77c8367..f5162f8b7b 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -608,7 +608,11 @@ static void pnv_reset(MachineState *machine)
  qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt));
  cpu_physical_memory_write(PNV_FDT_ADDR, fdt, fdt_totalsize(fdt));
  
-g_free(fdt);

+/*
+ * Update the machine->fdt pointer to enable support for
+ * 'dumpdtb' and 'info fdt' commands.
+ */
+machine->fdt = fdt;



Can pnv_reset() be called several times in the same instance of the qemu 
process, in which case we leak memory?


  Fred



  }
  
  static ISABus *pnv_chip_power8_isa_create(PnvChip *chip, Error **errp)




Re: [PATCH for-7.2 06/10] ppc/pnv: enable user created pnv-phb for powernv8

2022-08-05 Thread Frederic Barrat





diff --git a/hw/pci-host/pnv_phb.c b/hw/pci-host/pnv_phb.c
index 077f391d59..953c384bf6 100644
--- a/hw/pci-host/pnv_phb.c
+++ b/hw/pci-host/pnv_phb.c
@@ -17,6 +17,7 @@
  #include "hw/ppc/pnv.h"
  #include "hw/qdev-properties.h"
  #include "qom/object.h"
+#include "sysemu/sysemu.h"
  
  
  /*

@@ -171,6 +172,10 @@ static void pnv_phb_realize(DeviceState *dev, Error **errp)
  pnv_phb4_bus_init(dev, PNV_PHB4(phb->backend));
  }
  
+if (phb->version == 3 && !defaults_enabled()) {

+return;
+}
+
  pnv_phb_attach_root_port(pci);
  }



So we skip the call to pnv_phb_attach_root_port() for the user created PHBs.

I seem to remember that when the user creates a PHB on the command line, 
they also need to create the root port and we can't just create one by 
default with the PHB. It seems heavy when just using the qemu CLI but 
that was a requirement from libvirt. Did I get that right?


In any case, I can see a problem. pnv_phb_attach_root_port() creates the 
root port object, so if the above is correct, we want to skip that. But 
it also creates the PHB->root port relationship in QOM. That we don't do 
anywhere for the user-created case.


Calling qemu with "-nodefaults -device pnv-phb -device 
pnv-phb-root-port", here is what I see in QOM, which shows the wrong 
parenting of the root port:

  /peripheral-anon (container)
/device[1] (pnv-phb-root-port)
  /bus master container[0] (memory-region)
  /bus master[0] (memory-region)
  /pci_bridge_io[0] (memory-region)
  /pci_bridge_io[1] (memory-region)
  /pci_bridge_mem[0] (memory-region)
  /pci_bridge_pci[0] (memory-region)
  /pci_bridge_pref_mem[0] (memory-region)
  /pci_bridge_vga_io_hi[0] (memory-region)
  /pci_bridge_vga_io_lo[0] (memory-region)
  /pci_bridge_vga_mem[0] (memory-region)
  /pcie.0 (PCIE)


With the full series, same problem on P8/P9/P10

  Fred








Re: [PATCH for-7.2 04/10] ppc/pnv: add helpers for pnv-phb user devices

2022-08-05 Thread Frederic Barrat




On 03/08/2022 15:44, Daniel Henrique Barboza wrote:

pnv_parent_qom_fixup() and pnv_parent_bus_fixup() are versions of the
helpers that were reverted by commit 9c10d86fee "ppc/pnv: Remove
user-created PHB{3,4,5} devices". They are needed to amend the QOM and
bus hierarchies of user created pnv-phbs, matching them with default
pnv-phbs.

A new helper pnv_phb_user_device_init() is created to handle
user-created devices setup. We're going to call it inside
pnv_phb_realize() in case we're realizing an user created device. This
will centralize all user device realated in a single spot, leaving the
realize functions of the phb3/phb4 backends untouched.

Signed-off-by: Daniel Henrique Barboza 
---
  hw/pci-host/pnv_phb.c | 69 +++
  1 file changed, 69 insertions(+)

diff --git a/hw/pci-host/pnv_phb.c b/hw/pci-host/pnv_phb.c
index 826c0c144e..da779dc298 100644
--- a/hw/pci-host/pnv_phb.c
+++ b/hw/pci-host/pnv_phb.c
@@ -18,6 +18,37 @@
  #include "hw/qdev-properties.h"
  #include "qom/object.h"
  
+

+/*
+ * Set the QOM parent of an object child. If the device state
+ * associated with the child has an id, use it as QOM id. Otherwise
+ * use object_typename[index] as QOM id.
+ */
+static void pnv_parent_qom_fixup(Object *parent, Object *child, int index)
+{
+g_autofree char *default_id =
+g_strdup_printf("%s[%d]", object_get_typename(child), index);
+const char *dev_id = DEVICE(child)->id;
+
+if (child->parent == parent) {
+return;
+}
+
+object_ref(child);
+object_unparent(child);
+object_property_add_child(parent, dev_id ? dev_id : default_id, child);
+object_unref(child);
+}
+
+static void pnv_parent_bus_fixup(DeviceState *parent, DeviceState *child)
+{
+BusState *parent_bus = qdev_get_parent_bus(parent);
+
+if (!qdev_set_parent_bus(child, parent_bus, _fatal)) {
+return;
+}
+}
+
  /*
   * Attach a root port device.
   *
@@ -41,6 +72,36 @@ static void pnv_phb_attach_root_port(PCIHostState *pci)
  pci_realize_and_unref(root, pci->bus, _fatal);
  }
  
+/*

+ * User created devices won't have the initial setup that default
+ * devices have. This setup consists of assigning a parent device
+ * (chip for PHB3, PEC for PHB4/5) that will be the QOM/bus parent
+ * of the PHB.
+ */
+static void pnv_phb_user_device_init(PnvPHB *phb)
+{
+PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine());
+PnvChip *chip = pnv_get_chip(pnv, phb->chip_id);
+Object *parent = NULL;
+
+if (!chip) {
+error_setg(_fatal, "invalid chip id: %d", phb->chip_id);
+return;
+}
+
+/*
+ * Reparent user created devices to the chip to build
+ * correctly the device tree. pnv_xscom_dt() needs every
+ * PHB to be a child of the chip to build the DT correctly.
+ *
+ * TODO: for version 3 we're still parenting the PHB with the
+ * chip. We should parent with a (so far not implemented)
+ * PHB3 PEC device.
+ */
+pnv_parent_qom_fixup(parent, OBJECT(phb), phb->phb_id);



Here we reparent the phb to NULL. I can see in the following patches why 
it's done this way and the end result is ok. After this patch, we can't 
create a user device yet, so no harm can be done. But a (temporary) 
comment could save the reviewer a heart attack :-)


  Fred



+pnv_parent_bus_fixup(DEVICE(chip), DEVICE(phb));
+}
+
  static void pnv_phb_realize(DeviceState *dev, Error **errp)
  {
  PnvPHB *phb = PNV_PHB(dev);
@@ -74,6 +135,14 @@ static void pnv_phb_realize(DeviceState *dev, Error **errp)
  object_property_set_uint(phb->backend, "chip-id", phb->chip_id, errp);
  object_property_set_link(phb->backend, "phb-base", OBJECT(phb), errp);
  
+/*

+ * Handle user created devices. User devices will not have a
+ * pointer to a chip (PHB3) and a PEC (PHB4/5).
+ */
+if (!phb->chip && !phb->pec) {
+pnv_phb_user_device_init(phb);
+}
+
  if (phb->version == 3) {
  object_property_set_link(phb->backend, "chip",
   OBJECT(phb->chip), errp);




Re: [PATCH v3 05/12] ppc/pnv: turn PnvPHB4 into a PnvPHB backend

2022-07-27 Thread Frederic Barrat




On 24/06/2022 10:49, Daniel Henrique Barboza wrote:


diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index 1df91971b8..b7273f386e 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -672,7 +672,14 @@ static void pnv_chip_power8_pic_print_info(PnvChip *chip, 
Monitor *mon)
  static int pnv_chip_power9_pic_print_info_child(Object *child, void *opaque)
  {
  Monitor *mon = opaque;
-PnvPHB4 *phb4 = (PnvPHB4 *) object_dynamic_cast(child, TYPE_PNV_PHB4);
+PnvPHB *phb =  (PnvPHB *) object_dynamic_cast(child, TYPE_PNV_PHB);
+PnvPHB4 *phb4;
+
+if (!phb) {
+return 0;
+}
+
+phb4 = (PnvPHB4 *)phb->backend;
  
  if (phb4) {

  pnv_phb4_pic_print_info(phb4, mon);



The full code in pnv_chip_power9_pic_print_info_child() looks like this:

PnvPHB *phb =  (PnvPHB *) object_dynamic_cast(child, TYPE_PNV_PHB);
PnvPHB4 *phb4;

if (!phb) {
return 0;
}

phb4 = (PnvPHB4 *)phb->backend;

if (phb4) {
pnv_phb4_pic_print_info(phb4, mon);
}

Which is correct. However, if I want to nitpick, phb->backend is defined 
when the PnvPHB object is realized, so I don't think we can get here 
with the pointer being null, so we could remove the second if statement 
for readability. The reason I mention it is that we don't take that much 
care in the pnv_chip_power8_pic_print_info() function just above, so it 
looks a bit odd.


In any case:
Reviewed-by: Frederic Barrat 

  Fred





@@ -2122,8 +2129,14 @@ static void pnv_machine_power9_class_init(ObjectClass 
*oc, void *data)
  PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc);
  static const char compat[] = "qemu,powernv9\0ibm,powernv";
  
+static GlobalProperty phb_compat[] = {

+{ TYPE_PNV_PHB, "version", "4" },
+};
+
  mc->desc = "IBM PowerNV (Non-Virtualized) POWER9";
  mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.0");
+compat_props_add(mc->compat_props, phb_compat, G_N_ELEMENTS(phb_compat));
+
  xfc->match_nvt = pnv_match_nvt;
  
  mc->alias = "powernv";

@@ -2140,8 +2153,13 @@ static void pnv_machine_power10_class_init(ObjectClass 
*oc, void *data)
  XiveFabricClass *xfc = XIVE_FABRIC_CLASS(oc);
  static const char compat[] = "qemu,powernv10\0ibm,powernv";
  
+static GlobalProperty phb_compat[] = {

+{ TYPE_PNV_PHB, "version", "5" },
+};
+
  mc->desc = "IBM PowerNV (Non-Virtualized) POWER10";
  mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power10_v2.0");
+compat_props_add(mc->compat_props, phb_compat, G_N_ELEMENTS(phb_compat));
  
  pmc->compat = compat;

  pmc->compat_size = sizeof(compat);
diff --git a/include/hw/pci-host/pnv_phb4.h b/include/hw/pci-host/pnv_phb4.h
index 90843ac3a9..f22253358f 100644
--- a/include/hw/pci-host/pnv_phb4.h
+++ b/include/hw/pci-host/pnv_phb4.h
@@ -18,6 +18,7 @@
  typedef struct PnvPhb4PecState PnvPhb4PecState;
  typedef struct PnvPhb4PecStack PnvPhb4PecStack;
  typedef struct PnvPHB4 PnvPHB4;
+typedef struct PnvPHB PnvPHB;
  typedef struct PnvChip PnvChip;
  
  /*

@@ -78,7 +79,9 @@ OBJECT_DECLARE_SIMPLE_TYPE(PnvPHB4, PNV_PHB4)
  #define PCI_MMIO_TOTAL_SIZE(0x1ull << 60)
  
  struct PnvPHB4 {

-PCIExpressHost parent_obj;
+DeviceState parent;
+
+PnvPHB *phb_base;
  
  uint32_t chip_id;

  uint32_t phb_id;




Re: [PATCH v3 10/12] ppc/pnv: remove pecc->rp_model

2022-07-27 Thread Frederic Barrat




On 24/06/2022 10:49, Daniel Henrique Barboza wrote:

The attribute is unused.

Signed-off-by: Daniel Henrique Barboza 
---



Reviewed-by: Frederic Barrat 

  Fred



  hw/pci-host/pnv_phb4_pec.c | 2 --
  include/hw/pci-host/pnv_phb4.h | 1 -
  2 files changed, 3 deletions(-)

diff --git a/hw/pci-host/pnv_phb4_pec.c b/hw/pci-host/pnv_phb4_pec.c
index 0ef66b9a9b..8dc363d69c 100644
--- a/hw/pci-host/pnv_phb4_pec.c
+++ b/hw/pci-host/pnv_phb4_pec.c
@@ -260,7 +260,6 @@ static void pnv_pec_class_init(ObjectClass *klass, void 
*data)
  pecc->version = PNV_PHB4_VERSION;
  pecc->phb_type = TYPE_PNV_PHB4;
  pecc->num_phbs = pnv_pec_num_phbs;
-pecc->rp_model = TYPE_PNV_PHB_ROOT_PORT;
  }
  
  static const TypeInfo pnv_pec_type_info = {

@@ -313,7 +312,6 @@ static void pnv_phb5_pec_class_init(ObjectClass *klass, 
void *data)
  pecc->version = PNV_PHB5_VERSION;
  pecc->phb_type = TYPE_PNV_PHB5;
  pecc->num_phbs = pnv_phb5_pec_num_stacks;
-pecc->rp_model = TYPE_PNV_PHB_ROOT_PORT;
  }
  
  static const TypeInfo pnv_phb5_pec_type_info = {

diff --git a/include/hw/pci-host/pnv_phb4.h b/include/hw/pci-host/pnv_phb4.h
index 29c49ac79c..61a0cb9989 100644
--- a/include/hw/pci-host/pnv_phb4.h
+++ b/include/hw/pci-host/pnv_phb4.h
@@ -200,7 +200,6 @@ struct PnvPhb4PecClass {
  uint64_t version;
  const char *phb_type;
  const uint32_t *num_phbs;
-const char *rp_model;
  };
  
  /*




Re: [PATCH v3 09/12] ppc/pnv: remove root port name from pnv_phb_attach_root_port()

2022-07-27 Thread Frederic Barrat




On 24/06/2022 10:49, Daniel Henrique Barboza wrote:

We support only a single root port, PNV_PHB_ROOT_PORT.

Signed-off-by: Daniel Henrique Barboza 
---



Reviewed-by: Frederic Barrat 

  Fred



  hw/pci-host/pnv_phb.c | 7 +--
  hw/ppc/pnv.c  | 9 +
  include/hw/ppc/pnv.h  | 3 +--
  3 files changed, 7 insertions(+), 12 deletions(-)

diff --git a/hw/pci-host/pnv_phb.c b/hw/pci-host/pnv_phb.c
index da729e89e7..cc15a949c9 100644
--- a/hw/pci-host/pnv_phb.c
+++ b/hw/pci-host/pnv_phb.c
@@ -24,7 +24,6 @@ static void pnv_phb_realize(DeviceState *dev, Error **errp)
  PnvPHB *phb = PNV_PHB(dev);
  PCIHostState *pci = PCI_HOST_BRIDGE(dev);
  g_autofree char *phb_typename = NULL;
-g_autofree char *phb_rootport_typename = NULL;
  
  if (!phb->version) {

  error_setg(errp, "version not specified");
@@ -34,15 +33,12 @@ static void pnv_phb_realize(DeviceState *dev, Error **errp)
  switch (phb->version) {
  case 3:
  phb_typename = g_strdup(TYPE_PNV_PHB3);
-phb_rootport_typename = g_strdup(TYPE_PNV_PHB_ROOT_PORT);
  break;
  case 4:
  phb_typename = g_strdup(TYPE_PNV_PHB4);
-phb_rootport_typename = g_strdup(TYPE_PNV_PHB_ROOT_PORT);
  break;
  case 5:
  phb_typename = g_strdup(TYPE_PNV_PHB5);
-phb_rootport_typename = g_strdup(TYPE_PNV_PHB_ROOT_PORT);
  break;
  default:
  g_assert_not_reached();
@@ -73,8 +69,7 @@ static void pnv_phb_realize(DeviceState *dev, Error **errp)
  pnv_phb4_bus_init(dev, PNV_PHB4(phb->backend));
  }
  
-pnv_phb_attach_root_port(pci, phb_rootport_typename,

- phb->phb_id, phb->chip_id);
+pnv_phb_attach_root_port(pci, phb->phb_id, phb->chip_id);
  }
  
  static const char *pnv_phb_root_bus_path(PCIHostState *host_bridge,

diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index 159899103e..5b7cbfc699 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -1199,11 +1199,12 @@ static void pnv_chip_icp_realize(Pnv8Chip *chip8, Error 
**errp)
   * QOM id. 'chip_id' is going to be used as PCIE chassis for the
   * root port.
   */
-void pnv_phb_attach_root_port(PCIHostState *pci, const char *name,
-  int index, int chip_id)
+void pnv_phb_attach_root_port(PCIHostState *pci, int index, int chip_id)
  {
-PCIDevice *root = pci_new(PCI_DEVFN(0, 0), name);
-g_autofree char *default_id = g_strdup_printf("%s[%d]", name, index);
+PCIDevice *root = pci_new(PCI_DEVFN(0, 0), TYPE_PNV_PHB_ROOT_PORT);
+g_autofree char *default_id = g_strdup_printf("%s[%d]",
+  TYPE_PNV_PHB_ROOT_PORT,
+  index);
  const char *dev_id = DEVICE(root)->id;
  
  object_property_add_child(OBJECT(pci->bus), dev_id ? dev_id : default_id,

diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h
index 33b7b52f45..fbad11d6a7 100644
--- a/include/hw/ppc/pnv.h
+++ b/include/hw/ppc/pnv.h
@@ -190,8 +190,7 @@ DECLARE_INSTANCE_CHECKER(PnvChip, PNV_CHIP_POWER10,
   TYPE_PNV_CHIP_POWER10)
  
  PowerPCCPU *pnv_chip_find_cpu(PnvChip *chip, uint32_t pir);

-void pnv_phb_attach_root_port(PCIHostState *pci, const char *name,
-  int index, int chip_id);
+void pnv_phb_attach_root_port(PCIHostState *pci, int index, int chip_id);
  
  #define TYPE_PNV_MACHINE   MACHINE_TYPE_NAME("powernv")

  typedef struct PnvMachineClass PnvMachineClass;




Re: [PATCH v3 06/12] ppc/pnv: add pnv-phb-root-port device

2022-07-27 Thread Frederic Barrat




On 24/06/2022 10:49, Daniel Henrique Barboza wrote:

We have two very similar root-port devices, pnv-phb3-root-port and
pnv-phb4-root-port. Both consist of a wrapper around the PCIESlot device
that, until now, has no additional attributes.

The main difference between the PHB3 and PHB4 root ports is that
pnv-phb4-root-port has the pnv_phb4_root_port_reset() callback. All
other differences can be merged in a single device without too much
trouble.

This patch introduces the unified pnv-phb-root-port that, in time, will
be used as the default root port for the pnv-phb device.

Signed-off-by: Daniel Henrique Barboza 
---



Reviewed-by: Frederic Barrat 

  Fred



  hw/pci-host/pnv_phb.c | 115 +++---
  hw/pci-host/pnv_phb.h |  16 ++
  2 files changed, 123 insertions(+), 8 deletions(-)

diff --git a/hw/pci-host/pnv_phb.c b/hw/pci-host/pnv_phb.c
index abcbcca445..5e61f85614 100644
--- a/hw/pci-host/pnv_phb.c
+++ b/hw/pci-host/pnv_phb.c
@@ -112,15 +112,114 @@ static void pnv_phb_class_init(ObjectClass *klass, void 
*data)
  dc->user_creatable = false;
  }
  
-static void pnv_phb_register_type(void)

+static void pnv_phb_root_port_reset(DeviceState *dev)
  {
-static const TypeInfo pnv_phb_type_info = {
-.name  = TYPE_PNV_PHB,
-.parent= TYPE_PCIE_HOST_BRIDGE,
-.instance_size = sizeof(PnvPHB),
-.class_init= pnv_phb_class_init,
-};
+PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(dev);
+PnvPHBRootPort *phb_rp = PNV_PHB_ROOT_PORT(dev);
+PCIDevice *d = PCI_DEVICE(dev);
+uint8_t *conf = d->config;
  
+rpc->parent_reset(dev);

+
+if (phb_rp->version == 3) {
+return;
+}
+
+/* PHB4 and later requires these extra reset steps */
+pci_byte_test_and_set_mask(conf + PCI_IO_BASE,
+   PCI_IO_RANGE_MASK & 0xff);
+pci_byte_test_and_clear_mask(conf + PCI_IO_LIMIT,
+ PCI_IO_RANGE_MASK & 0xff);
+pci_set_word(conf + PCI_MEMORY_BASE, 0);
+pci_set_word(conf + PCI_MEMORY_LIMIT, 0xfff0);
+pci_set_word(conf + PCI_PREF_MEMORY_BASE, 0x1);
+pci_set_word(conf + PCI_PREF_MEMORY_LIMIT, 0xfff1);
+pci_set_long(conf + PCI_PREF_BASE_UPPER32, 0x1); /* Hack */
+pci_set_long(conf + PCI_PREF_LIMIT_UPPER32, 0x);
+pci_config_set_interrupt_pin(conf, 0);
+}
+
+static void pnv_phb_root_port_realize(DeviceState *dev, Error **errp)
+{
+PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(dev);
+PnvPHBRootPort *phb_rp = PNV_PHB_ROOT_PORT(dev);
+PCIDevice *pci = PCI_DEVICE(dev);
+uint16_t device_id = 0;
+Error *local_err = NULL;
+
+rpc->parent_realize(dev, _err);
+if (local_err) {
+error_propagate(errp, local_err);
+return;
+}
+
+switch (phb_rp->version) {
+case 3:
+device_id = PNV_PHB3_DEVICE_ID;
+break;
+case 4:
+device_id = PNV_PHB4_DEVICE_ID;
+break;
+case 5:
+device_id = PNV_PHB5_DEVICE_ID;
+break;
+default:
+g_assert_not_reached();
+}
+
+pci_config_set_device_id(pci->config, device_id);
+pci_config_set_interrupt_pin(pci->config, 0);
+}
+
+static Property pnv_phb_root_port_properties[] = {
+DEFINE_PROP_UINT32("version", PnvPHBRootPort, version, 0),
+
+DEFINE_PROP_END_OF_LIST(),
+};
+
+static void pnv_phb_root_port_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+PCIERootPortClass *rpc = PCIE_ROOT_PORT_CLASS(klass);
+
+dc->desc = "IBM PHB PCIE Root Port";
+
+device_class_set_props(dc, pnv_phb_root_port_properties);
+device_class_set_parent_realize(dc, pnv_phb_root_port_realize,
+>parent_realize);
+device_class_set_parent_reset(dc, pnv_phb_root_port_reset,
+  >parent_reset);
+dc->reset = _phb_root_port_reset;
+dc->user_creatable = false;
+
+k->vendor_id = PCI_VENDOR_ID_IBM;
+/* device_id will be written during realize() */
+k->device_id = 0;
+k->revision  = 0;
+
+rpc->exp_offset = 0x48;
+rpc->aer_offset = 0x100;
+}
+
+static const TypeInfo pnv_phb_type_info = {
+.name  = TYPE_PNV_PHB,
+.parent= TYPE_PCIE_HOST_BRIDGE,
+.instance_size = sizeof(PnvPHB),
+.class_init= pnv_phb_class_init,
+};
+
+static const TypeInfo pnv_phb_root_port_info = {
+.name  = TYPE_PNV_PHB_ROOT_PORT,
+.parent= TYPE_PCIE_ROOT_PORT,
+.instance_size = sizeof(PnvPHBRootPort),
+.class_init= pnv_phb_root_port_class_init,
+};
+
+static void pnv_phb_register_types(void)
+{
  type_register_static(_phb_type_info);
+type_register_static(_phb_root_port_info);
  }
-type_init(pnv_phb_register_type)
+
+type_init(pnv_phb_register_types)
diff 

Re: [PATCH v3 12/12] ppc/pnv: move attach_root_port helper to pnv-phb.c

2022-07-27 Thread Frederic Barrat




On 24/06/2022 10:49, Daniel Henrique Barboza wrote:

The helper is only used in this file.

Signed-off-by: Daniel Henrique Barboza 
---



Reviewed-by: Frederic Barrat 

  Fred



  hw/pci-host/pnv_phb.c | 24 
  hw/ppc/pnv.c  | 25 -
  include/hw/ppc/pnv.h  |  1 -
  3 files changed, 24 insertions(+), 26 deletions(-)

diff --git a/hw/pci-host/pnv_phb.c b/hw/pci-host/pnv_phb.c
index cc15a949c9..c47ed92462 100644
--- a/hw/pci-host/pnv_phb.c
+++ b/hw/pci-host/pnv_phb.c
@@ -18,6 +18,30 @@
  #include "hw/qdev-properties.h"
  #include "qom/object.h"
  
+/*

+ * Attach a root port device.
+ *
+ * 'index' will be used both as a PCIE slot value and to calculate
+ * QOM id. 'chip_id' is going to be used as PCIE chassis for the
+ * root port.
+ */
+static void pnv_phb_attach_root_port(PCIHostState *pci, int index, int chip_id)
+{
+PCIDevice *root = pci_new(PCI_DEVFN(0, 0), TYPE_PNV_PHB_ROOT_PORT);
+g_autofree char *default_id = g_strdup_printf("%s[%d]",
+  TYPE_PNV_PHB_ROOT_PORT,
+  index);
+const char *dev_id = DEVICE(root)->id;
+
+object_property_add_child(OBJECT(pci->bus), dev_id ? dev_id : default_id,
+  OBJECT(root));
+
+/* Set unique chassis/slot values for the root port */
+qdev_prop_set_uint8(DEVICE(root), "chassis", chip_id);
+qdev_prop_set_uint16(DEVICE(root), "slot", index);
+
+pci_realize_and_unref(root, pci->bus, _fatal);
+}
  
  static void pnv_phb_realize(DeviceState *dev, Error **errp)

  {
diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index 5b7cbfc699..d649ed6b1b 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -1192,31 +1192,6 @@ static void pnv_chip_icp_realize(Pnv8Chip *chip8, Error 
**errp)
  }
  }
  
-/*

- * Attach a root port device.
- *
- * 'index' will be used both as a PCIE slot value and to calculate
- * QOM id. 'chip_id' is going to be used as PCIE chassis for the
- * root port.
- */
-void pnv_phb_attach_root_port(PCIHostState *pci, int index, int chip_id)
-{
-PCIDevice *root = pci_new(PCI_DEVFN(0, 0), TYPE_PNV_PHB_ROOT_PORT);
-g_autofree char *default_id = g_strdup_printf("%s[%d]",
-  TYPE_PNV_PHB_ROOT_PORT,
-  index);
-const char *dev_id = DEVICE(root)->id;
-
-object_property_add_child(OBJECT(pci->bus), dev_id ? dev_id : default_id,
-  OBJECT(root));
-
-/* Set unique chassis/slot values for the root port */
-qdev_prop_set_uint8(DEVICE(root), "chassis", chip_id);
-qdev_prop_set_uint16(DEVICE(root), "slot", index);
-
-pci_realize_and_unref(root, pci->bus, _fatal);
-}
-
  static void pnv_chip_power8_realize(DeviceState *dev, Error **errp)
  {
  PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h
index fbad11d6a7..033d907287 100644
--- a/include/hw/ppc/pnv.h
+++ b/include/hw/ppc/pnv.h
@@ -190,7 +190,6 @@ DECLARE_INSTANCE_CHECKER(PnvChip, PNV_CHIP_POWER10,
   TYPE_PNV_CHIP_POWER10)
  
  PowerPCCPU *pnv_chip_find_cpu(PnvChip *chip, uint32_t pir);

-void pnv_phb_attach_root_port(PCIHostState *pci, int index, int chip_id);
  
  #define TYPE_PNV_MACHINE   MACHINE_TYPE_NAME("powernv")

  typedef struct PnvMachineClass PnvMachineClass;




Re: [PATCH v3 08/12] ppc/pnv: remove pnv-phb4-root-port

2022-07-27 Thread Frederic Barrat




On 24/06/2022 10:49, Daniel Henrique Barboza wrote:

The unified pnv-phb-root-port can be used instead. The phb4-root-port
device isn't exposed to the user in any official QEMU release so there's
no ABI breakage in removing it.

Signed-off-by: Daniel Henrique Barboza 
---



Reviewed-by: Frederic Barrat 

  Fred



  hw/pci-host/pnv_phb.c  |  4 +-
  hw/pci-host/pnv_phb4.c | 85 --
  hw/pci-host/pnv_phb4_pec.c |  4 +-
  hw/ppc/pnv.c   |  2 +
  include/hw/pci-host/pnv_phb4.h |  9 
  5 files changed, 6 insertions(+), 98 deletions(-)

diff --git a/hw/pci-host/pnv_phb.c b/hw/pci-host/pnv_phb.c
index cdddc6a389..da729e89e7 100644
--- a/hw/pci-host/pnv_phb.c
+++ b/hw/pci-host/pnv_phb.c
@@ -38,11 +38,11 @@ static void pnv_phb_realize(DeviceState *dev, Error **errp)
  break;
  case 4:
  phb_typename = g_strdup(TYPE_PNV_PHB4);
-phb_rootport_typename = g_strdup(TYPE_PNV_PHB4_ROOT_PORT);
+phb_rootport_typename = g_strdup(TYPE_PNV_PHB_ROOT_PORT);
  break;
  case 5:
  phb_typename = g_strdup(TYPE_PNV_PHB5);
-phb_rootport_typename = g_strdup(TYPE_PNV_PHB5_ROOT_PORT);
+phb_rootport_typename = g_strdup(TYPE_PNV_PHB_ROOT_PORT);
  break;
  default:
  g_assert_not_reached();
diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c
index 74cf62dc1a..fefdd3ad89 100644
--- a/hw/pci-host/pnv_phb4.c
+++ b/hw/pci-host/pnv_phb4.c
@@ -1741,94 +1741,9 @@ static const TypeInfo pnv_phb4_root_bus_info = {
  .class_init = pnv_phb4_root_bus_class_init,
  };
  
-static void pnv_phb4_root_port_reset(DeviceState *dev)

-{
-PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(dev);
-PCIDevice *d = PCI_DEVICE(dev);
-uint8_t *conf = d->config;
-
-rpc->parent_reset(dev);
-
-pci_byte_test_and_set_mask(conf + PCI_IO_BASE,
-   PCI_IO_RANGE_MASK & 0xff);
-pci_byte_test_and_clear_mask(conf + PCI_IO_LIMIT,
- PCI_IO_RANGE_MASK & 0xff);
-pci_set_word(conf + PCI_MEMORY_BASE, 0);
-pci_set_word(conf + PCI_MEMORY_LIMIT, 0xfff0);
-pci_set_word(conf + PCI_PREF_MEMORY_BASE, 0x1);
-pci_set_word(conf + PCI_PREF_MEMORY_LIMIT, 0xfff1);
-pci_set_long(conf + PCI_PREF_BASE_UPPER32, 0x1); /* Hack */
-pci_set_long(conf + PCI_PREF_LIMIT_UPPER32, 0x);
-pci_config_set_interrupt_pin(conf, 0);
-}
-
-static void pnv_phb4_root_port_realize(DeviceState *dev, Error **errp)
-{
-PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(dev);
-Error *local_err = NULL;
-
-rpc->parent_realize(dev, _err);
-if (local_err) {
-error_propagate(errp, local_err);
-return;
-}
-}
-
-static void pnv_phb4_root_port_class_init(ObjectClass *klass, void *data)
-{
-DeviceClass *dc = DEVICE_CLASS(klass);
-PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-PCIERootPortClass *rpc = PCIE_ROOT_PORT_CLASS(klass);
-
-dc->desc = "IBM PHB4 PCIE Root Port";
-dc->user_creatable = false;
-
-device_class_set_parent_realize(dc, pnv_phb4_root_port_realize,
->parent_realize);
-device_class_set_parent_reset(dc, pnv_phb4_root_port_reset,
-  >parent_reset);
-
-k->vendor_id = PCI_VENDOR_ID_IBM;
-k->device_id = PNV_PHB4_DEVICE_ID;
-k->revision  = 0;
-
-rpc->exp_offset = 0x48;
-rpc->aer_offset = 0x100;
-
-dc->reset = _phb4_root_port_reset;
-}
-
-static const TypeInfo pnv_phb4_root_port_info = {
-.name  = TYPE_PNV_PHB4_ROOT_PORT,
-.parent= TYPE_PCIE_ROOT_PORT,
-.instance_size = sizeof(PnvPHB4RootPort),
-.class_init= pnv_phb4_root_port_class_init,
-};
-
-static void pnv_phb5_root_port_class_init(ObjectClass *klass, void *data)
-{
-DeviceClass *dc = DEVICE_CLASS(klass);
-PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-
-dc->desc = "IBM PHB5 PCIE Root Port";
-dc->user_creatable = false;
-
-k->vendor_id = PCI_VENDOR_ID_IBM;
-k->device_id = PNV_PHB5_DEVICE_ID;
-}
-
-static const TypeInfo pnv_phb5_root_port_info = {
-.name  = TYPE_PNV_PHB5_ROOT_PORT,
-.parent= TYPE_PNV_PHB4_ROOT_PORT,
-.instance_size = sizeof(PnvPHB4RootPort),
-.class_init= pnv_phb5_root_port_class_init,
-};
-
  static void pnv_phb4_register_types(void)
  {
  type_register_static(_phb4_root_bus_info);
-type_register_static(_phb5_root_port_info);
-type_register_static(_phb4_root_port_info);
  type_register_static(_phb4_type_info);
  type_register_static(_phb5_type_info);
  type_register_static(_phb4_iommu_memory_region_info);
diff --git a/hw/pci-host/pnv_phb4_pec.c b/hw/pci-host/pnv_phb4_pec.c
index 4a0a9fbe8b..0ef66b9a9b 100644
--- a/hw/pci-host/pnv_phb4_pec.c
+++ b/hw/pci-host/pnv_phb4_pec.c
@@ -260,7 +260,7 @@ stat

Re: [PATCH v3 11/12] ppc/pnv: remove PnvPHB4.version

2022-07-27 Thread Frederic Barrat




On 24/06/2022 10:49, Daniel Henrique Barboza wrote:

It's unused.

Signed-off-by: Daniel Henrique Barboza 
---



Reviewed-by: Frederic Barrat 

  Fred



  include/hw/pci-host/pnv_phb4.h | 2 --
  1 file changed, 2 deletions(-)

diff --git a/include/hw/pci-host/pnv_phb4.h b/include/hw/pci-host/pnv_phb4.h
index 61a0cb9989..20aa4819d3 100644
--- a/include/hw/pci-host/pnv_phb4.h
+++ b/include/hw/pci-host/pnv_phb4.h
@@ -77,8 +77,6 @@ struct PnvPHB4 {
  uint32_t chip_id;
  uint32_t phb_id;
  
-uint64_t version;

-
  /* The owner PEC */
  PnvPhb4PecState *pec;
  




Re: [PATCH v3 02/12] ppc/pnv: add PnvPHB base/proxy device

2022-07-27 Thread Frederic Barrat




On 24/06/2022 10:49, Daniel Henrique Barboza wrote:

The PnvPHB device is going to be the base device for all other powernv
PHBs. It consists of a device that has the same user API as the other
PHB, namely being a PCIHostBridge and having chip-id and index
properties. It also has a 'backend' pointer that will be initialized
with the PHB implementation that the device is going to use.

The initialization of the PHB backend is done by checking the PHB
version via a 'version' attribute that can be set via a global machine
property.  The 'version' field will be used to make adjustments based on
the running version, e.g. PHB3 uses a 'chip' reference while PHB4 uses
'pec'. To init the PnvPHB bus we'll rely on helpers for each version.
The version 3 helper is already added (pnv_phb3_bus_init), the PHB4
helper will be added later on.

For now let's add the basic logic of the PnvPHB object, which consists
mostly of pnv_phb_realize() doing all the work of checking the
phb->version set, initializing the proper backend, passing through its
attributes to the chosen backend, finalizing the backend realize and
adding a root port in the end.

Signed-off-by: Daniel Henrique Barboza 
---



Reviewed-by: Frederic Barrat 

  Fred



  hw/pci-host/meson.build |   3 +-
  hw/pci-host/pnv_phb.c   | 124 
  hw/pci-host/pnv_phb.h   |  39 +
  3 files changed, 165 insertions(+), 1 deletion(-)
  create mode 100644 hw/pci-host/pnv_phb.c
  create mode 100644 hw/pci-host/pnv_phb.h

diff --git a/hw/pci-host/meson.build b/hw/pci-host/meson.build
index c07596d0d1..e832babc9d 100644
--- a/hw/pci-host/meson.build
+++ b/hw/pci-host/meson.build
@@ -35,5 +35,6 @@ specific_ss.add(when: 'CONFIG_PCI_POWERNV', if_true: files(
'pnv_phb3_msi.c',
'pnv_phb3_pbcq.c',
'pnv_phb4.c',
-  'pnv_phb4_pec.c'
+  'pnv_phb4_pec.c',
+  'pnv_phb.c',
  ))
diff --git a/hw/pci-host/pnv_phb.c b/hw/pci-host/pnv_phb.c
new file mode 100644
index 00..6fefff7d44
--- /dev/null
+++ b/hw/pci-host/pnv_phb.c
@@ -0,0 +1,124 @@
+/*
+ * QEMU PowerPC PowerNV Proxy PHB model
+ *
+ * Copyright (c) 2022, IBM Corporation.
+ *
+ * This code is licensed under the GPL version 2 or later. See the
+ * COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qapi/visitor.h"
+#include "qapi/error.h"
+#include "hw/pci-host/pnv_phb.h"
+#include "hw/pci-host/pnv_phb3.h"
+#include "hw/pci-host/pnv_phb4.h"
+#include "hw/ppc/pnv.h"
+#include "hw/qdev-properties.h"
+#include "qom/object.h"
+
+
+static void pnv_phb_realize(DeviceState *dev, Error **errp)
+{
+PnvPHB *phb = PNV_PHB(dev);
+PCIHostState *pci = PCI_HOST_BRIDGE(dev);
+g_autofree char *phb_typename = NULL;
+g_autofree char *phb_rootport_typename = NULL;
+
+if (!phb->version) {
+error_setg(errp, "version not specified");
+return;
+}
+
+switch (phb->version) {
+case 3:
+phb_typename = g_strdup(TYPE_PNV_PHB3);
+phb_rootport_typename = g_strdup(TYPE_PNV_PHB3_ROOT_PORT);
+break;
+case 4:
+phb_typename = g_strdup(TYPE_PNV_PHB4);
+phb_rootport_typename = g_strdup(TYPE_PNV_PHB4_ROOT_PORT);
+break;
+case 5:
+phb_typename = g_strdup(TYPE_PNV_PHB5);
+phb_rootport_typename = g_strdup(TYPE_PNV_PHB5_ROOT_PORT);
+break;
+default:
+g_assert_not_reached();
+}
+
+phb->backend = object_new(phb_typename);
+object_property_add_child(OBJECT(dev), "phb-backend", phb->backend);
+
+/* Passthrough child device properties to the proxy device */
+object_property_set_uint(phb->backend, "index", phb->phb_id, errp);
+object_property_set_uint(phb->backend, "chip-id", phb->chip_id, errp);
+object_property_set_link(phb->backend, "phb-base", OBJECT(phb), errp);
+
+if (phb->version == 3) {
+object_property_set_link(phb->backend, "chip",
+ OBJECT(phb->chip), errp);
+} else {
+object_property_set_link(phb->backend, "pec", OBJECT(phb->pec), errp);
+}
+
+if (!qdev_realize(DEVICE(phb->backend), NULL, errp)) {
+return;
+}
+
+if (phb->version == 3) {
+pnv_phb3_bus_init(dev, PNV_PHB3(phb->backend));
+}
+
+pnv_phb_attach_root_port(pci, phb_rootport_typename,
+ phb->phb_id, phb->chip_id);
+}
+
+static const char *pnv_phb_root_bus_path(PCIHostState *host_bridge,
+ PCIBus *rootbus)
+{
+PnvPHB *phb = PNV_PHB(host_bridge);
+
+snprintf(phb->bus_path, sizeof(phb->bus_path), "00%02x:%02x",
+ phb->chip_id, phb->phb_id);
+return phb->bus_path;
+}
+
+static Property pnv

Re: [PATCH v3 07/12] ppc/pnv: remove pnv-phb3-root-port

2022-07-27 Thread Frederic Barrat




On 24/06/2022 10:49, Daniel Henrique Barboza wrote:

The unified pnv-phb-root-port can be used in its place. There is no ABI
breakage in doing so because no official QEMU release introduced user
creatable pnv-phb3-root-port devices.

Signed-off-by: Daniel Henrique Barboza 
---



Reviewed-by: Frederic Barrat 

  Fred



  hw/pci-host/pnv_phb.c  |  2 +-
  hw/pci-host/pnv_phb3.c | 42 --
  hw/ppc/pnv.c   |  1 +
  include/hw/pci-host/pnv_phb3.h |  6 -
  4 files changed, 2 insertions(+), 49 deletions(-)

diff --git a/hw/pci-host/pnv_phb.c b/hw/pci-host/pnv_phb.c
index 5e61f85614..cdddc6a389 100644
--- a/hw/pci-host/pnv_phb.c
+++ b/hw/pci-host/pnv_phb.c
@@ -34,7 +34,7 @@ static void pnv_phb_realize(DeviceState *dev, Error **errp)
  switch (phb->version) {
  case 3:
  phb_typename = g_strdup(TYPE_PNV_PHB3);
-phb_rootport_typename = g_strdup(TYPE_PNV_PHB3_ROOT_PORT);
+phb_rootport_typename = g_strdup(TYPE_PNV_PHB_ROOT_PORT);
  break;
  case 4:
  phb_typename = g_strdup(TYPE_PNV_PHB4);
diff --git a/hw/pci-host/pnv_phb3.c b/hw/pci-host/pnv_phb3.c
index ad5d67a8e8..2966374008 100644
--- a/hw/pci-host/pnv_phb3.c
+++ b/hw/pci-host/pnv_phb3.c
@@ -1122,51 +1122,9 @@ static const TypeInfo pnv_phb3_root_bus_info = {
  .class_init = pnv_phb3_root_bus_class_init,
  };
  
-static void pnv_phb3_root_port_realize(DeviceState *dev, Error **errp)

-{
-PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(dev);
-PCIDevice *pci = PCI_DEVICE(dev);
-Error *local_err = NULL;
-
-rpc->parent_realize(dev, _err);
-if (local_err) {
-error_propagate(errp, local_err);
-return;
-}
-pci_config_set_interrupt_pin(pci->config, 0);
-}
-
-static void pnv_phb3_root_port_class_init(ObjectClass *klass, void *data)
-{
-DeviceClass *dc = DEVICE_CLASS(klass);
-PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-PCIERootPortClass *rpc = PCIE_ROOT_PORT_CLASS(klass);
-
-dc->desc = "IBM PHB3 PCIE Root Port";
-
-device_class_set_parent_realize(dc, pnv_phb3_root_port_realize,
->parent_realize);
-dc->user_creatable = false;
-
-k->vendor_id = PCI_VENDOR_ID_IBM;
-k->device_id = 0x03dc;
-k->revision  = 0;
-
-rpc->exp_offset = 0x48;
-rpc->aer_offset = 0x100;
-}
-
-static const TypeInfo pnv_phb3_root_port_info = {
-.name  = TYPE_PNV_PHB3_ROOT_PORT,
-.parent= TYPE_PCIE_ROOT_PORT,
-.instance_size = sizeof(PnvPHB3RootPort),
-.class_init= pnv_phb3_root_port_class_init,
-};
-
  static void pnv_phb3_register_types(void)
  {
  type_register_static(_phb3_root_bus_info);
-type_register_static(_phb3_root_port_info);
  type_register_static(_phb3_type_info);
  type_register_static(_phb3_iommu_memory_region_info);
  }
diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index b7273f386e..d82c66ca6f 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -2108,6 +2108,7 @@ static void pnv_machine_power8_class_init(ObjectClass 
*oc, void *data)
  
  static GlobalProperty phb_compat[] = {

  { TYPE_PNV_PHB, "version", "3" },
+{ TYPE_PNV_PHB_ROOT_PORT, "version", "3" },
  };
  
  mc->desc = "IBM PowerNV (Non-Virtualized) POWER8";

diff --git a/include/hw/pci-host/pnv_phb3.h b/include/hw/pci-host/pnv_phb3.h
index 3b9ff1096a..bff69201d9 100644
--- a/include/hw/pci-host/pnv_phb3.h
+++ b/include/hw/pci-host/pnv_phb3.h
@@ -108,12 +108,6 @@ struct PnvPBCQState {
   */
  #define TYPE_PNV_PHB3_ROOT_BUS "pnv-phb3-root"
  
-#define TYPE_PNV_PHB3_ROOT_PORT "pnv-phb3-root-port"

-
-typedef struct PnvPHB3RootPort {
-PCIESlot parent_obj;
-} PnvPHB3RootPort;
-
  /*
   * PHB3 PCIe Host Bridge for PowerNV machines (POWER8)
   */




Re: [PATCH v3 04/12] ppc/pnv: add PHB4 bus init helper

2022-07-27 Thread Frederic Barrat




On 24/06/2022 10:49, Daniel Henrique Barboza wrote:

Similar to what we already did for the PnvPHB3 device, let's add a
helper to init the bus when using a PnvPHB4. This helper will be used by
PnvPHb when PnvPHB4 turns into a backend.

Signed-off-by: Daniel Henrique Barboza 
---



Reviewed-by: Frederic Barrat 

  Fred



  hw/pci-host/pnv_phb.c  |  2 ++
  hw/pci-host/pnv_phb4.c | 39 --
  include/hw/pci-host/pnv_phb4.h |  1 +
  3 files changed, 26 insertions(+), 16 deletions(-)

diff --git a/hw/pci-host/pnv_phb.c b/hw/pci-host/pnv_phb.c
index 6fefff7d44..abcbcca445 100644
--- a/hw/pci-host/pnv_phb.c
+++ b/hw/pci-host/pnv_phb.c
@@ -69,6 +69,8 @@ static void pnv_phb_realize(DeviceState *dev, Error **errp)
  
  if (phb->version == 3) {

  pnv_phb3_bus_init(dev, PNV_PHB3(phb->backend));
+} else {
+pnv_phb4_bus_init(dev, PNV_PHB4(phb->backend));
  }
  
  pnv_phb_attach_root_port(pci, phb_rootport_typename,

diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c
index d225ab5b0f..a7a4519f30 100644
--- a/hw/pci-host/pnv_phb4.c
+++ b/hw/pci-host/pnv_phb4.c
@@ -1544,30 +1544,16 @@ static void pnv_phb4_instance_init(Object *obj)
  object_initialize_child(obj, "source", >xsrc, TYPE_XIVE_SOURCE);
  }
  
-static void pnv_phb4_realize(DeviceState *dev, Error **errp)

+void pnv_phb4_bus_init(DeviceState *dev, PnvPHB4 *phb)
  {
-PnvPHB4 *phb = PNV_PHB4(dev);
-PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(phb->pec);
  PCIHostState *pci = PCI_HOST_BRIDGE(dev);
-XiveSource *xsrc = >xsrc;
-int nr_irqs;
  char name[32];
  
-/* Set the "big_phb" flag */

-phb->big_phb = phb->phb_id == 0 || phb->phb_id == 3;
-
-/* Controller Registers */
-snprintf(name, sizeof(name), "phb4-%d.%d-regs", phb->chip_id,
- phb->phb_id);
-memory_region_init_io(>mr_regs, OBJECT(phb), _phb4_reg_ops, phb,
-  name, 0x2000);
-
  /*
   * PHB4 doesn't support IO space. However, qemu gets very upset if
   * we don't have an IO region to anchor IO BARs onto so we just
   * initialize one which we never hook up to anything
   */
-
  snprintf(name, sizeof(name), "phb4-%d.%d-pci-io", phb->chip_id,
   phb->phb_id);
  memory_region_init(>pci_io, OBJECT(phb), name, 0x1);
@@ -1577,12 +1563,33 @@ static void pnv_phb4_realize(DeviceState *dev, Error 
**errp)
  memory_region_init(>pci_mmio, OBJECT(phb), name,
 PCI_MMIO_TOTAL_SIZE);
  
-pci->bus = pci_register_root_bus(dev, dev->id,

+pci->bus = pci_register_root_bus(dev, dev->id ? dev->id : NULL,
   pnv_phb4_set_irq, pnv_phb4_map_irq, phb,
   >pci_mmio, >pci_io,
   0, 4, TYPE_PNV_PHB4_ROOT_BUS);
  pci_setup_iommu(pci->bus, pnv_phb4_dma_iommu, phb);
  pci->bus->flags |= PCI_BUS_EXTENDED_CONFIG_SPACE;
+}
+
+static void pnv_phb4_realize(DeviceState *dev, Error **errp)
+{
+PnvPHB4 *phb = PNV_PHB4(dev);
+PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(phb->pec);
+PCIHostState *pci = PCI_HOST_BRIDGE(dev);
+XiveSource *xsrc = >xsrc;
+int nr_irqs;
+char name[32];
+
+/* Set the "big_phb" flag */
+phb->big_phb = phb->phb_id == 0 || phb->phb_id == 3;
+
+/* Controller Registers */
+snprintf(name, sizeof(name), "phb4-%d.%d-regs", phb->chip_id,
+ phb->phb_id);
+memory_region_init_io(>mr_regs, OBJECT(phb), _phb4_reg_ops, phb,
+  name, 0x2000);
+
+pnv_phb4_bus_init(dev, phb);
  
  /* Add a single Root port if running with defaults */

  pnv_phb_attach_root_port(pci, pecc->rp_model,
diff --git a/include/hw/pci-host/pnv_phb4.h b/include/hw/pci-host/pnv_phb4.h
index 19dcbd6f87..90843ac3a9 100644
--- a/include/hw/pci-host/pnv_phb4.h
+++ b/include/hw/pci-host/pnv_phb4.h
@@ -157,6 +157,7 @@ struct PnvPHB4 {
  
  void pnv_phb4_pic_print_info(PnvPHB4 *phb, Monitor *mon);

  int pnv_phb4_pec_get_phb_id(PnvPhb4PecState *pec, int stack_index);
+void pnv_phb4_bus_init(DeviceState *dev, PnvPHB4 *phb);
  extern const MemoryRegionOps pnv_phb4_xscom_ops;
  
  /*




Re: [PATCH v3 01/12] ppc/pnv: add PHB3 bus init helper

2022-07-27 Thread Frederic Barrat




On 24/06/2022 10:49, Daniel Henrique Barboza wrote:

The PnvPHB3 bus init consists of initializing the pci_io and pci_mmio
regions, registering it via pci_register_root_bus() and then setup the
iommu.

We'll want to init the bus from outside pnv_phb3.c when the bus is
removed from the PnvPHB3 device and put into a new parent PnvPHB device.
The new pnv_phb3_bus_init() helper will be used by the parent to init
the bus when using the PHB3 backend.

Signed-off-by: Daniel Henrique Barboza 
---


Reviewed-by: Frederic Barrat 

  Fred


  hw/pci-host/pnv_phb3.c | 39 --
  include/hw/pci-host/pnv_phb3.h |  1 +
  2 files changed, 24 insertions(+), 16 deletions(-)

diff --git a/hw/pci-host/pnv_phb3.c b/hw/pci-host/pnv_phb3.c
index d58d3c1701..058cbab555 100644
--- a/hw/pci-host/pnv_phb3.c
+++ b/hw/pci-host/pnv_phb3.c
@@ -986,6 +986,28 @@ static void pnv_phb3_instance_init(Object *obj)
  
  }
  
+void pnv_phb3_bus_init(DeviceState *dev, PnvPHB3 *phb)

+{
+PCIHostState *pci = PCI_HOST_BRIDGE(dev);
+
+/*
+ * PHB3 doesn't support IO space. However, qemu gets very upset if
+ * we don't have an IO region to anchor IO BARs onto so we just
+ * initialize one which we never hook up to anything
+ */
+memory_region_init(>pci_io, OBJECT(phb), "pci-io", 0x1);
+memory_region_init(>pci_mmio, OBJECT(phb), "pci-mmio",
+   PCI_MMIO_TOTAL_SIZE);
+
+pci->bus = pci_register_root_bus(dev,
+ dev->id ? dev->id : NULL,
+ pnv_phb3_set_irq, pnv_phb3_map_irq, phb,
+ >pci_mmio, >pci_io,
+ 0, 4, TYPE_PNV_PHB3_ROOT_BUS);
+
+pci_setup_iommu(pci->bus, pnv_phb3_dma_iommu, phb);
+}
+
  static void pnv_phb3_realize(DeviceState *dev, Error **errp)
  {
  PnvPHB3 *phb = PNV_PHB3(dev);
@@ -1035,22 +1057,7 @@ static void pnv_phb3_realize(DeviceState *dev, Error 
**errp)
  memory_region_init_io(>mr_regs, OBJECT(phb), _phb3_reg_ops, phb,
"phb3-regs", 0x1000);
  
-/*

- * PHB3 doesn't support IO space. However, qemu gets very upset if
- * we don't have an IO region to anchor IO BARs onto so we just
- * initialize one which we never hook up to anything
- */
-memory_region_init(>pci_io, OBJECT(phb), "pci-io", 0x1);
-memory_region_init(>pci_mmio, OBJECT(phb), "pci-mmio",
-   PCI_MMIO_TOTAL_SIZE);
-
-pci->bus = pci_register_root_bus(dev,
- dev->id ? dev->id : NULL,
- pnv_phb3_set_irq, pnv_phb3_map_irq, phb,
- >pci_mmio, >pci_io,
- 0, 4, TYPE_PNV_PHB3_ROOT_BUS);
-
-pci_setup_iommu(pci->bus, pnv_phb3_dma_iommu, phb);
+pnv_phb3_bus_init(dev, phb);
  
  pnv_phb_attach_root_port(pci, TYPE_PNV_PHB3_ROOT_PORT,

   phb->phb_id, phb->chip_id);
diff --git a/include/hw/pci-host/pnv_phb3.h b/include/hw/pci-host/pnv_phb3.h
index af6ec83cf6..1375f18fc1 100644
--- a/include/hw/pci-host/pnv_phb3.h
+++ b/include/hw/pci-host/pnv_phb3.h
@@ -164,5 +164,6 @@ uint64_t pnv_phb3_reg_read(void *opaque, hwaddr off, 
unsigned size);
  void pnv_phb3_reg_write(void *opaque, hwaddr off, uint64_t val, unsigned 
size);
  void pnv_phb3_update_regions(PnvPHB3 *phb);
  void pnv_phb3_remap_irqs(PnvPHB3 *phb);
+void pnv_phb3_bus_init(DeviceState *dev, PnvPHB3 *phb);
  
  #endif /* PCI_HOST_PNV_PHB3_H */




Re: [PATCH v3 03/12] ppc/pnv: turn PnvPHB3 into a PnvPHB backend

2022-07-27 Thread Frederic Barrat




On 24/06/2022 10:49, Daniel Henrique Barboza wrote:

We need a handful of changes that needs to be done in a single swoop to
turn PnvPHB3 into a PnvPHB backend.

In the PnvPHB3, since the PnvPHB device implements PCIExpressHost and
will hold the PCI bus, change PnvPHB3 parent to TYPE_DEVICE. There are a
couple of instances in pnv_phb3.c that needs to access the PCI bus, so a
phb_base pointer is added to allow access to the parent PnvPHB. The
PnvPHB3 root port will now be connected to a PnvPHB object.

In pnv.c, the powernv8 machine chip8 will now hold an array of PnvPHB
objects.  pnv_get_phb3_child() needs to be adapted to return the PnvPHB3
backend from the PnvPHB child. A global property is added in
pnv_machine_power8_class_init() to ensure that all PnvPHBs are created
with phb->version = 3.

After all these changes we're still able to boot a powernv8 machine with
default settings. The real gain will come with user created PnvPHB
devices, coming up next.

Signed-off-by: Daniel Henrique Barboza 
---



A very minor indentation issue below, but other than that:
Reviewed-by: Frederic Barrat 



  hw/pci-host/pnv_phb3.c | 27 +--
  hw/ppc/pnv.c   | 21 +++--
  include/hw/pci-host/pnv_phb3.h |  5 -
  include/hw/ppc/pnv.h   |  3 ++-
  4 files changed, 26 insertions(+), 30 deletions(-)

diff --git a/hw/pci-host/pnv_phb3.c b/hw/pci-host/pnv_phb3.c
index 058cbab555..ad5d67a8e8 100644
--- a/hw/pci-host/pnv_phb3.c
+++ b/hw/pci-host/pnv_phb3.c
@@ -11,6 +11,7 @@
  #include "qapi/visitor.h"
  #include "qapi/error.h"
  #include "hw/pci-host/pnv_phb3_regs.h"
+#include "hw/pci-host/pnv_phb.h"
  #include "hw/pci-host/pnv_phb3.h"
  #include "hw/pci/pcie_host.h"
  #include "hw/pci/pcie_port.h"
@@ -26,7 +27,7 @@
  
  static PCIDevice *pnv_phb3_find_cfg_dev(PnvPHB3 *phb)

  {
-PCIHostState *pci = PCI_HOST_BRIDGE(phb);
+PCIHostState *pci = PCI_HOST_BRIDGE(phb->phb_base);
  uint64_t addr = phb->regs[PHB_CONFIG_ADDRESS >> 3];
  uint8_t bus, devfn;
  
@@ -590,7 +591,7 @@ void pnv_phb3_reg_write(void *opaque, hwaddr off, uint64_t val, unsigned size)

  uint64_t pnv_phb3_reg_read(void *opaque, hwaddr off, unsigned size)
  {
  PnvPHB3 *phb = opaque;
-PCIHostState *pci = PCI_HOST_BRIDGE(phb);
+PCIHostState *pci = PCI_HOST_BRIDGE(phb->phb_base);
  uint64_t val;
  
  if ((off & 0xfffc) == PHB_CONFIG_DATA) {

@@ -1011,7 +1012,6 @@ void pnv_phb3_bus_init(DeviceState *dev, PnvPHB3 *phb)
  static void pnv_phb3_realize(DeviceState *dev, Error **errp)
  {
  PnvPHB3 *phb = PNV_PHB3(dev);
-PCIHostState *pci = PCI_HOST_BRIDGE(dev);
  PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine());
  int i;
  
@@ -1056,11 +1056,6 @@ static void pnv_phb3_realize(DeviceState *dev, Error **errp)

  /* Controller Registers */
  memory_region_init_io(>mr_regs, OBJECT(phb), _phb3_reg_ops, phb,
"phb3-regs", 0x1000);
-
-pnv_phb3_bus_init(dev, phb);
-
-pnv_phb_attach_root_port(pci, TYPE_PNV_PHB3_ROOT_PORT,
- phb->phb_id, phb->chip_id);
  }
  
  void pnv_phb3_update_regions(PnvPHB3 *phb)

@@ -1085,38 +1080,26 @@ void pnv_phb3_update_regions(PnvPHB3 *phb)
  pnv_phb3_check_all_m64s(phb);
  }
  
-static const char *pnv_phb3_root_bus_path(PCIHostState *host_bridge,

-  PCIBus *rootbus)
-{
-PnvPHB3 *phb = PNV_PHB3(host_bridge);
-
-snprintf(phb->bus_path, sizeof(phb->bus_path), "00%02x:%02x",
- phb->chip_id, phb->phb_id);
-return phb->bus_path;
-}
-
  static Property pnv_phb3_properties[] = {
  DEFINE_PROP_UINT32("index", PnvPHB3, phb_id, 0),
  DEFINE_PROP_UINT32("chip-id", PnvPHB3, chip_id, 0),
  DEFINE_PROP_LINK("chip", PnvPHB3, chip, TYPE_PNV_CHIP, PnvChip *),
+DEFINE_PROP_LINK("phb-base", PnvPHB3, phb_base, TYPE_PNV_PHB, PnvPHB *),
  DEFINE_PROP_END_OF_LIST(),
  };
  
  static void pnv_phb3_class_init(ObjectClass *klass, void *data)

  {
-PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(klass);
  DeviceClass *dc = DEVICE_CLASS(klass);
  
-hc->root_bus_path = pnv_phb3_root_bus_path;

  dc->realize = pnv_phb3_realize;
  device_class_set_props(dc, pnv_phb3_properties);
-set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
  dc->user_creatable = false;
  }
  
  static const TypeInfo pnv_phb3_type_info = {

  .name  = TYPE_PNV_PHB3,
-.parent= TYPE_PCIE_HOST_BRIDGE,
+.parent = TYPE_DEVICE,


Missing spaces here ^^
  Fred



  .instance_size = sizeof(PnvPHB3),
  .class_init= pnv_phb3_class_init,
  .instance_init = pnv_phb3_instance_init,
diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index d3f77c8367..1df91971b8 100644
--- a/hw/ppc/pnv.c
++

  1   2   >