Re: [Qemu-devel] [PATCH v2 11/15] ppc/pnv: POWER9 XSCOM quad support

2019-03-07 Thread David Gibson
On Thu, Mar 07, 2019 at 11:35:44PM +0100, Cédric Le Goater wrote:
> The POWER9 processor does not support per-core frequency control. The
> cores are arranged in groups of four, along with their respective L2
> and L3 caches, into a structure known as a Quad. The frequency must be
> managed at the Quad level.
> 
> Provide a basic Quad model to fake the settings done by the firmware
> on the Non-Cacheable Unit (NCU). Each core pair (EX) needs a special
> BAR setting for the TIMA area of XIVE because it resides on the same
> address on all chips.
> 
> Signed-off-by: Cédric Le Goater 

Applied, thanks.

> ---
>  include/hw/ppc/pnv.h   |  4 ++
>  include/hw/ppc/pnv_core.h  | 10 +
>  include/hw/ppc/pnv_xscom.h | 12 --
>  hw/ppc/pnv.c   | 38 -
>  hw/ppc/pnv_core.c  | 87 ++
>  5 files changed, 146 insertions(+), 5 deletions(-)
> 
> diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h
> index 39888f9d52c1..e5b00d373ed2 100644
> --- a/include/hw/ppc/pnv.h
> +++ b/include/hw/ppc/pnv.h
> @@ -26,6 +26,7 @@
>  #include "hw/ppc/pnv_psi.h"
>  #include "hw/ppc/pnv_occ.h"
>  #include "hw/ppc/pnv_xive.h"
> +#include "hw/ppc/pnv_core.h"
>  
>  #define TYPE_PNV_CHIP "pnv-chip"
>  #define PNV_CHIP(obj) OBJECT_CHECK(PnvChip, (obj), TYPE_PNV_CHIP)
> @@ -89,6 +90,9 @@ typedef struct Pnv9Chip {
>  Pnv9Psi  psi;
>  PnvLpcController lpc;
>  PnvOCC   occ;
> +
> +uint32_t nr_quads;
> +PnvQuad  *quads;
>  } Pnv9Chip;
>  
>  typedef struct PnvChipClass {
> diff --git a/include/hw/ppc/pnv_core.h b/include/hw/ppc/pnv_core.h
> index cbe9ad36f32c..50cdb2b35838 100644
> --- a/include/hw/ppc/pnv_core.h
> +++ b/include/hw/ppc/pnv_core.h
> @@ -58,4 +58,14 @@ static inline PnvCPUState *pnv_cpu_state(PowerPCCPU *cpu)
>  return (PnvCPUState *)cpu->machine_data;
>  }
>  
> +#define TYPE_PNV_QUAD "powernv-cpu-quad"
> +#define PNV_QUAD(obj) \
> +OBJECT_CHECK(PnvQuad, (obj), TYPE_PNV_QUAD)
> +
> +typedef struct PnvQuad {
> +DeviceState parent_obj;
> +
> +uint32_t id;
> +MemoryRegion xscom_regs;
> +} PnvQuad;
>  #endif /* _PPC_PNV_CORE_H */
> diff --git a/include/hw/ppc/pnv_xscom.h b/include/hw/ppc/pnv_xscom.h
> index 3292459fbb78..68dfae0dfe41 100644
> --- a/include/hw/ppc/pnv_xscom.h
> +++ b/include/hw/ppc/pnv_xscom.h
> @@ -60,10 +60,6 @@ typedef struct PnvXScomInterfaceClass {
>  (PNV_XSCOM_EX_CORE_BASE | ((uint64_t)(core) << 24))
>  #define PNV_XSCOM_EX_SIZE 0x10
>  
> -#define PNV_XSCOM_P9_EC_BASE(core) \
> -((uint64_t)(((core) & 0x1F) + 0x20) << 24)
> -#define PNV_XSCOM_P9_EC_SIZE  0x10
> -
>  #define PNV_XSCOM_LPC_BASE0xb0020
>  #define PNV_XSCOM_LPC_SIZE0x4
>  
> @@ -73,6 +69,14 @@ typedef struct PnvXScomInterfaceClass {
>  #define PNV_XSCOM_OCC_BASE0x0066000
>  #define PNV_XSCOM_OCC_SIZE0x6000
>  
> +#define PNV9_XSCOM_EC_BASE(core) \
> +((uint64_t)(((core) & 0x1F) + 0x20) << 24)
> +#define PNV9_XSCOM_EC_SIZE0x10
> +
> +#define PNV9_XSCOM_EQ_BASE(core) \
> +((uint64_t)(((core) & 0x1C) + 0x40) << 22)
> +#define PNV9_XSCOM_EQ_SIZE0x10
> +
>  #define PNV9_XSCOM_OCC_BASE   PNV_XSCOM_OCC_BASE
>  #define PNV9_XSCOM_OCC_SIZE   0x8000
>  
> diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
> index 1559a733235b..e68d419203e8 100644
> --- a/hw/ppc/pnv.c
> +++ b/hw/ppc/pnv.c
> @@ -963,6 +963,36 @@ static void pnv_chip_power9_instance_init(Object *obj)
> OBJECT(>psi), _abort);
>  }
>  
> +static void pnv_chip_quad_realize(Pnv9Chip *chip9, Error **errp)
> +{
> +PnvChip *chip = PNV_CHIP(chip9);
> +const char *typename = pnv_chip_core_typename(chip);
> +size_t typesize = object_type_get_instance_size(typename);
> +int i;
> +
> +chip9->nr_quads = DIV_ROUND_UP(chip->nr_cores, 4);
> +chip9->quads = g_new0(PnvQuad, chip9->nr_quads);
> +
> +for (i = 0; i < chip9->nr_quads; i++) {
> +char eq_name[32];
> +PnvQuad *eq = >quads[i];
> +PnvCore *pnv_core = PNV_CORE(chip->cores + (i * 4) * typesize);
> +int core_id = CPU_CORE(pnv_core)->core_id;
> +
> +object_initialize(eq, sizeof(*eq), TYPE_PNV_QUAD);
> +snprintf(eq_name, sizeof(eq_name), "eq[%d]", core_id);
> +
> +object_property_add_child(OBJECT(chip), eq_name, OBJECT(eq),
> +  _fatal);
> +object_property_set_int(OBJECT(eq), core_id, "id", _fatal);
> +object_property_set_bool(OBJECT(eq), true, "realized", _fatal);
> +object_unref(OBJECT(eq));
> +
> +pnv_xscom_add_subregion(chip, PNV9_XSCOM_EQ_BASE(eq->id),
> +>xscom_regs);
> +}
> +}
> +
>  static void pnv_chip_power9_realize(DeviceState *dev, Error **errp)
>  {
>  PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
> @@ -977,6 +1007,12 @@ static void pnv_chip_power9_realize(DeviceState *dev, 
> Error **errp)
>  

[Qemu-devel] [PATCH v2 11/15] ppc/pnv: POWER9 XSCOM quad support

2019-03-07 Thread Cédric Le Goater
The POWER9 processor does not support per-core frequency control. The
cores are arranged in groups of four, along with their respective L2
and L3 caches, into a structure known as a Quad. The frequency must be
managed at the Quad level.

Provide a basic Quad model to fake the settings done by the firmware
on the Non-Cacheable Unit (NCU). Each core pair (EX) needs a special
BAR setting for the TIMA area of XIVE because it resides on the same
address on all chips.

Signed-off-by: Cédric Le Goater 
---
 include/hw/ppc/pnv.h   |  4 ++
 include/hw/ppc/pnv_core.h  | 10 +
 include/hw/ppc/pnv_xscom.h | 12 --
 hw/ppc/pnv.c   | 38 -
 hw/ppc/pnv_core.c  | 87 ++
 5 files changed, 146 insertions(+), 5 deletions(-)

diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h
index 39888f9d52c1..e5b00d373ed2 100644
--- a/include/hw/ppc/pnv.h
+++ b/include/hw/ppc/pnv.h
@@ -26,6 +26,7 @@
 #include "hw/ppc/pnv_psi.h"
 #include "hw/ppc/pnv_occ.h"
 #include "hw/ppc/pnv_xive.h"
+#include "hw/ppc/pnv_core.h"
 
 #define TYPE_PNV_CHIP "pnv-chip"
 #define PNV_CHIP(obj) OBJECT_CHECK(PnvChip, (obj), TYPE_PNV_CHIP)
@@ -89,6 +90,9 @@ typedef struct Pnv9Chip {
 Pnv9Psi  psi;
 PnvLpcController lpc;
 PnvOCC   occ;
+
+uint32_t nr_quads;
+PnvQuad  *quads;
 } Pnv9Chip;
 
 typedef struct PnvChipClass {
diff --git a/include/hw/ppc/pnv_core.h b/include/hw/ppc/pnv_core.h
index cbe9ad36f32c..50cdb2b35838 100644
--- a/include/hw/ppc/pnv_core.h
+++ b/include/hw/ppc/pnv_core.h
@@ -58,4 +58,14 @@ static inline PnvCPUState *pnv_cpu_state(PowerPCCPU *cpu)
 return (PnvCPUState *)cpu->machine_data;
 }
 
+#define TYPE_PNV_QUAD "powernv-cpu-quad"
+#define PNV_QUAD(obj) \
+OBJECT_CHECK(PnvQuad, (obj), TYPE_PNV_QUAD)
+
+typedef struct PnvQuad {
+DeviceState parent_obj;
+
+uint32_t id;
+MemoryRegion xscom_regs;
+} PnvQuad;
 #endif /* _PPC_PNV_CORE_H */
diff --git a/include/hw/ppc/pnv_xscom.h b/include/hw/ppc/pnv_xscom.h
index 3292459fbb78..68dfae0dfe41 100644
--- a/include/hw/ppc/pnv_xscom.h
+++ b/include/hw/ppc/pnv_xscom.h
@@ -60,10 +60,6 @@ typedef struct PnvXScomInterfaceClass {
 (PNV_XSCOM_EX_CORE_BASE | ((uint64_t)(core) << 24))
 #define PNV_XSCOM_EX_SIZE 0x10
 
-#define PNV_XSCOM_P9_EC_BASE(core) \
-((uint64_t)(((core) & 0x1F) + 0x20) << 24)
-#define PNV_XSCOM_P9_EC_SIZE  0x10
-
 #define PNV_XSCOM_LPC_BASE0xb0020
 #define PNV_XSCOM_LPC_SIZE0x4
 
@@ -73,6 +69,14 @@ typedef struct PnvXScomInterfaceClass {
 #define PNV_XSCOM_OCC_BASE0x0066000
 #define PNV_XSCOM_OCC_SIZE0x6000
 
+#define PNV9_XSCOM_EC_BASE(core) \
+((uint64_t)(((core) & 0x1F) + 0x20) << 24)
+#define PNV9_XSCOM_EC_SIZE0x10
+
+#define PNV9_XSCOM_EQ_BASE(core) \
+((uint64_t)(((core) & 0x1C) + 0x40) << 22)
+#define PNV9_XSCOM_EQ_SIZE0x10
+
 #define PNV9_XSCOM_OCC_BASE   PNV_XSCOM_OCC_BASE
 #define PNV9_XSCOM_OCC_SIZE   0x8000
 
diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index 1559a733235b..e68d419203e8 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -963,6 +963,36 @@ static void pnv_chip_power9_instance_init(Object *obj)
OBJECT(>psi), _abort);
 }
 
+static void pnv_chip_quad_realize(Pnv9Chip *chip9, Error **errp)
+{
+PnvChip *chip = PNV_CHIP(chip9);
+const char *typename = pnv_chip_core_typename(chip);
+size_t typesize = object_type_get_instance_size(typename);
+int i;
+
+chip9->nr_quads = DIV_ROUND_UP(chip->nr_cores, 4);
+chip9->quads = g_new0(PnvQuad, chip9->nr_quads);
+
+for (i = 0; i < chip9->nr_quads; i++) {
+char eq_name[32];
+PnvQuad *eq = >quads[i];
+PnvCore *pnv_core = PNV_CORE(chip->cores + (i * 4) * typesize);
+int core_id = CPU_CORE(pnv_core)->core_id;
+
+object_initialize(eq, sizeof(*eq), TYPE_PNV_QUAD);
+snprintf(eq_name, sizeof(eq_name), "eq[%d]", core_id);
+
+object_property_add_child(OBJECT(chip), eq_name, OBJECT(eq),
+  _fatal);
+object_property_set_int(OBJECT(eq), core_id, "id", _fatal);
+object_property_set_bool(OBJECT(eq), true, "realized", _fatal);
+object_unref(OBJECT(eq));
+
+pnv_xscom_add_subregion(chip, PNV9_XSCOM_EQ_BASE(eq->id),
+>xscom_regs);
+}
+}
+
 static void pnv_chip_power9_realize(DeviceState *dev, Error **errp)
 {
 PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
@@ -977,6 +1007,12 @@ static void pnv_chip_power9_realize(DeviceState *dev, 
Error **errp)
 return;
 }
 
+pnv_chip_quad_realize(chip9, _err);
+if (local_err) {
+error_propagate(errp, local_err);
+return;
+}
+
 /* XIVE interrupt controller (POWER9) */
 object_property_set_int(OBJECT(>xive), PNV9_XIVE_IC_BASE(chip),
 "ic-bar", _fatal);
@@ -1135,7 +1171,7 @@ static void