mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'remotes/legoater/tags/pull-ppc-20220302' into staging
ppc-7.0 queue * ppc/pnv fixes * PMU EBB support * target/ppc: PowerISA Vector/VSX instruction batch * ppc/pnv: Extension of the powernv10 machine with XIVE2 ans PHB5 models * spapr allocation cleanups # gpg: Signature made Wed 02 Mar 2022 11:00:42 GMT # gpg: using RSA key A0F66548F04895EBFE6B0B6051A343C7CFFBECA1 # gpg: Good signature from "Cédric Le Goater <clg@kaod.org>" [undefined] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: A0F6 6548 F048 95EB FE6B 0B60 51A3 43C7 CFFB ECA1 * remotes/legoater/tags/pull-ppc-20220302: (87 commits) hw/ppc/spapr_vio.c: use g_autofree in spapr_dt_vdevice() hw/ppc/spapr_rtas.c: use g_autofree in rtas_ibm_get_system_parameter() spapr_pci_nvlink2.c: use g_autofree in spapr_phb_nvgpu_ram_populate_dt() hw/ppc/spapr_numa.c: simplify spapr_numa_write_assoc_lookup_arrays() hw/ppc/spapr_drc.c: use g_autofree in spapr_drc_by_index() hw/ppc/spapr_drc.c: use g_autofree in spapr_dr_connector_new() hw/ppc/spapr_drc.c: use g_autofree in drc_unrealize() hw/ppc/spapr_drc.c: use g_autofree in drc_realize() hw/ppc/spapr_drc.c: use g_auto in spapr_dt_drc() hw/ppc/spapr_caps.c: use g_autofree in spapr_caps_add_properties() hw/ppc/spapr_caps.c: use g_autofree in spapr_cap_get_string() hw/ppc/spapr_caps.c: use g_autofree in spapr_cap_set_string() hw/ppc/spapr.c: fail early if no firmware found in machine_init() hw/ppc/spapr.c: use g_autofree in spapr_dt_chosen() pnv/xive2: Add support for 8bits thread id pnv/xive2: Add support for automatic save&restore xive2: Add a get_config() handler for the router configuration pnv/xive2: Add support XIVE2 P9-compat mode (or Gen1) ppc/pnv: add XIVE Gen2 TIMA support pnv/xive2: Introduce new capability bits ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
+2
-2
@@ -42,7 +42,7 @@ specific_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_intc.c'))
|
||||
specific_ss.add(when: 'CONFIG_OMPIC', if_true: files('ompic.c'))
|
||||
specific_ss.add(when: ['CONFIG_KVM', 'CONFIG_OPENPIC'],
|
||||
if_true: files('openpic_kvm.c'))
|
||||
specific_ss.add(when: 'CONFIG_POWERNV', if_true: files('xics_pnv.c', 'pnv_xive.c'))
|
||||
specific_ss.add(when: 'CONFIG_POWERNV', if_true: files('xics_pnv.c', 'pnv_xive.c', 'pnv_xive2.c'))
|
||||
specific_ss.add(when: 'CONFIG_PPC_UIC', if_true: files('ppc-uic.c'))
|
||||
specific_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2835_ic.c', 'bcm2836_control.c'))
|
||||
specific_ss.add(when: 'CONFIG_RX_ICU', if_true: files('rx_icu.c'))
|
||||
@@ -52,7 +52,7 @@ specific_ss.add(when: 'CONFIG_SH_INTC', if_true: files('sh_intc.c'))
|
||||
specific_ss.add(when: 'CONFIG_RISCV_ACLINT', if_true: files('riscv_aclint.c'))
|
||||
specific_ss.add(when: 'CONFIG_RISCV_APLIC', if_true: files('riscv_aplic.c'))
|
||||
specific_ss.add(when: 'CONFIG_SIFIVE_PLIC', if_true: files('sifive_plic.c'))
|
||||
specific_ss.add(when: 'CONFIG_XICS', if_true: files('xics.c'))
|
||||
specific_ss.add(when: 'CONFIG_XICS', if_true: files('xics.c', 'xive2.c'))
|
||||
specific_ss.add(when: ['CONFIG_KVM', 'CONFIG_XICS'],
|
||||
if_true: files('xics_kvm.c'))
|
||||
specific_ss.add(when: 'CONFIG_PSERIES', if_true: files('xics_spapr.c', 'spapr_xive.c'))
|
||||
|
||||
+34
-3
@@ -403,6 +403,34 @@ static int pnv_xive_get_eas(XiveRouter *xrtr, uint8_t blk, uint32_t idx,
|
||||
return pnv_xive_vst_read(xive, VST_TSEL_IVT, blk, idx, eas);
|
||||
}
|
||||
|
||||
static int pnv_xive_get_pq(XiveRouter *xrtr, uint8_t blk, uint32_t idx,
|
||||
uint8_t *pq)
|
||||
{
|
||||
PnvXive *xive = PNV_XIVE(xrtr);
|
||||
|
||||
if (pnv_xive_block_id(xive) != blk) {
|
||||
xive_error(xive, "VST: EAS %x is remote !?", XIVE_EAS(blk, idx));
|
||||
return -1;
|
||||
}
|
||||
|
||||
*pq = xive_source_esb_get(&xive->ipi_source, idx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pnv_xive_set_pq(XiveRouter *xrtr, uint8_t blk, uint32_t idx,
|
||||
uint8_t *pq)
|
||||
{
|
||||
PnvXive *xive = PNV_XIVE(xrtr);
|
||||
|
||||
if (pnv_xive_block_id(xive) != blk) {
|
||||
xive_error(xive, "VST: EAS %x is remote !?", XIVE_EAS(blk, idx));
|
||||
return -1;
|
||||
}
|
||||
|
||||
*pq = xive_source_esb_set(&xive->ipi_source, idx, *pq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* One bit per thread id. The first register PC_THREAD_EN_REG0 covers
|
||||
* the first cores 0-15 (normal) of the chip or 0-7 (fused). The
|
||||
@@ -499,12 +527,12 @@ static PnvXive *pnv_xive_tm_get_xive(PowerPCCPU *cpu)
|
||||
* event notification to the Router. This is required on a multichip
|
||||
* system.
|
||||
*/
|
||||
static void pnv_xive_notify(XiveNotifier *xn, uint32_t srcno)
|
||||
static void pnv_xive_notify(XiveNotifier *xn, uint32_t srcno, bool pq_checked)
|
||||
{
|
||||
PnvXive *xive = PNV_XIVE(xn);
|
||||
uint8_t blk = pnv_xive_block_id(xive);
|
||||
|
||||
xive_router_notify(xn, XIVE_EAS(blk, srcno));
|
||||
xive_router_notify(xn, XIVE_EAS(blk, srcno), pq_checked);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1351,7 +1379,8 @@ static void pnv_xive_ic_hw_trigger(PnvXive *xive, hwaddr addr, uint64_t val)
|
||||
blk = XIVE_EAS_BLOCK(val);
|
||||
idx = XIVE_EAS_INDEX(val);
|
||||
|
||||
xive_router_notify(XIVE_NOTIFIER(xive), XIVE_EAS(blk, idx));
|
||||
xive_router_notify(XIVE_NOTIFIER(xive), XIVE_EAS(blk, idx),
|
||||
!!(val & XIVE_TRIGGER_PQ));
|
||||
}
|
||||
|
||||
static void pnv_xive_ic_notify_write(void *opaque, hwaddr addr, uint64_t val,
|
||||
@@ -1971,6 +2000,8 @@ static void pnv_xive_class_init(ObjectClass *klass, void *data)
|
||||
device_class_set_props(dc, pnv_xive_properties);
|
||||
|
||||
xrc->get_eas = pnv_xive_get_eas;
|
||||
xrc->get_pq = pnv_xive_get_pq;
|
||||
xrc->set_pq = pnv_xive_set_pq;
|
||||
xrc->get_end = pnv_xive_get_end;
|
||||
xrc->write_end = pnv_xive_write_end;
|
||||
xrc->get_nvt = pnv_xive_get_nvt;
|
||||
|
||||
+2128
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,442 @@
|
||||
/*
|
||||
* QEMU PowerPC XIVE2 interrupt controller model (POWER10)
|
||||
*
|
||||
* Copyright (c) 2019-2022, IBM Corporation.
|
||||
*
|
||||
* This code is licensed under the GPL version 2 or later. See the
|
||||
* COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef PPC_PNV_XIVE2_REGS_H
|
||||
#define PPC_PNV_XIVE2_REGS_H
|
||||
|
||||
/*
|
||||
* CQ Common Queue (PowerBus bridge) Registers
|
||||
*/
|
||||
|
||||
/* XIVE2 Capabilities */
|
||||
#define X_CQ_XIVE_CAP 0x02
|
||||
#define CQ_XIVE_CAP 0x010
|
||||
#define CQ_XIVE_CAP_VERSION PPC_BITMASK(0, 3)
|
||||
/* 4:6 reserved */
|
||||
#define CQ_XIVE_CAP_USER_INT_PRIO PPC_BITMASK(8, 9)
|
||||
#define CQ_XIVE_CAP_USER_INT_PRIO_1 0
|
||||
#define CQ_XIVE_CAP_USER_INT_PRIO_1_2 1
|
||||
#define CQ_XIVE_CAP_USER_INT_PRIO_1_4 2
|
||||
#define CQ_XIVE_CAP_USER_INT_PRIO_1_8 3
|
||||
#define CQ_XIVE_CAP_VP_INT_PRIO PPC_BITMASK(10, 11)
|
||||
#define CQ_XIVE_CAP_VP_INT_PRIO_1_8 0
|
||||
#define CQ_XIVE_CAP_VP_INT_PRIO_2_8 1
|
||||
#define CQ_XIVE_CAP_VP_INT_PRIO_4_8 2
|
||||
#define CQ_XIVE_CAP_VP_INT_PRIO_8 3
|
||||
#define CQ_XIVE_CAP_BLOCK_ID_WIDTH PPC_BITMASK(12, 13)
|
||||
#define CQ_XIVE_CAP_VP_SAVE_RESTORE PPC_BIT(38)
|
||||
|
||||
#define CQ_XIVE_CAP_PHB_PQ_DISABLE PPC_BIT(56)
|
||||
#define CQ_XIVE_CAP_PHB_ABT PPC_BIT(57)
|
||||
#define CQ_XIVE_CAP_EXPLOITATION_MODE PPC_BIT(58)
|
||||
#define CQ_XIVE_CAP_STORE_EOI PPC_BIT(59)
|
||||
|
||||
/* XIVE2 Configuration */
|
||||
#define X_CQ_XIVE_CFG 0x03
|
||||
#define CQ_XIVE_CFG 0x018
|
||||
|
||||
/* 0:7 reserved */
|
||||
#define CQ_XIVE_CFG_USER_INT_PRIO PPC_BITMASK(8, 9)
|
||||
#define CQ_XIVE_CFG_VP_INT_PRIO PPC_BITMASK(10, 11)
|
||||
#define CQ_XIVE_CFG_INT_PRIO_1 0
|
||||
#define CQ_XIVE_CFG_INT_PRIO_2 1
|
||||
#define CQ_XIVE_CFG_INT_PRIO_4 2
|
||||
#define CQ_XIVE_CFG_INT_PRIO_8 3
|
||||
#define CQ_XIVE_CFG_BLOCK_ID_WIDTH PPC_BITMASK(12, 13)
|
||||
#define CQ_XIVE_CFG_BLOCK_ID_4BITS 0
|
||||
#define CQ_XIVE_CFG_BLOCK_ID_5BITS 1
|
||||
#define CQ_XIVE_CFG_BLOCK_ID_6BITS 2
|
||||
#define CQ_XIVE_CFG_BLOCK_ID_7BITS 3
|
||||
#define CQ_XIVE_CFG_HYP_HARD_RANGE PPC_BITMASK(14, 15)
|
||||
#define CQ_XIVE_CFG_THREADID_7BITS 0
|
||||
#define CQ_XIVE_CFG_THREADID_8BITS 1
|
||||
#define CQ_XIVE_CFG_THREADID_9BITS 2
|
||||
#define CQ_XIVE_CFG_THREADID_10BITs 3
|
||||
#define CQ_XIVE_CFG_HYP_HARD_BLKID_OVERRIDE PPC_BIT(16)
|
||||
#define CQ_XIVE_CFG_HYP_HARD_BLOCK_ID PPC_BITMASK(17, 23)
|
||||
|
||||
#define CQ_XIVE_CFG_GEN1_TIMA_OS PPC_BIT(24)
|
||||
#define CQ_XIVE_CFG_GEN1_TIMA_HYP PPC_BIT(25)
|
||||
#define CQ_XIVE_CFG_GEN1_TIMA_HYP_BLK0 PPC_BIT(26) /* 0 if bit[25]=0 */
|
||||
#define CQ_XIVE_CFG_GEN1_TIMA_CROWD_DIS PPC_BIT(27) /* 0 if bit[25]=0 */
|
||||
#define CQ_XIVE_CFG_GEN1_END_ESX PPC_BIT(28)
|
||||
#define CQ_XIVE_CFG_EN_VP_SAVE_RESTORE PPC_BIT(38) /* 0 if bit[25]=1 */
|
||||
#define CQ_XIVE_CFG_EN_VP_SAVE_REST_STRICT PPC_BIT(39) /* 0 if bit[25]=1 */
|
||||
|
||||
/* Interrupt Controller Base Address Register - 512 pages (32M) */
|
||||
#define X_CQ_IC_BAR 0x08
|
||||
#define CQ_IC_BAR 0x040
|
||||
#define CQ_IC_BAR_VALID PPC_BIT(0)
|
||||
#define CQ_IC_BAR_64K PPC_BIT(1)
|
||||
/* 2:7 reserved */
|
||||
#define CQ_IC_BAR_ADDR PPC_BITMASK(8, 42)
|
||||
/* 43:63 reserved */
|
||||
|
||||
/* Thread Management Base Address Register - 4 pages */
|
||||
#define X_CQ_TM_BAR 0x09
|
||||
#define CQ_TM_BAR 0x048
|
||||
#define CQ_TM_BAR_VALID PPC_BIT(0)
|
||||
#define CQ_TM_BAR_64K PPC_BIT(1)
|
||||
#define CQ_TM_BAR_ADDR PPC_BITMASK(8, 49)
|
||||
|
||||
/* ESB Base Address Register */
|
||||
#define X_CQ_ESB_BAR 0x0A
|
||||
#define CQ_ESB_BAR 0x050
|
||||
#define CQ_BAR_VALID PPC_BIT(0)
|
||||
#define CQ_BAR_64K PPC_BIT(1)
|
||||
/* 2:7 reserved */
|
||||
#define CQ_BAR_ADDR PPC_BITMASK(8, 39)
|
||||
#define CQ_BAR_SET_DIV PPC_BITMASK(56, 58)
|
||||
#define CQ_BAR_RANGE PPC_BITMASK(59, 63)
|
||||
/* 0 (16M) - 16 (16T) */
|
||||
|
||||
/* END Base Address Register */
|
||||
#define X_CQ_END_BAR 0x0B
|
||||
#define CQ_END_BAR 0x058
|
||||
|
||||
/* NVPG Base Address Register */
|
||||
#define X_CQ_NVPG_BAR 0x0C
|
||||
#define CQ_NVPG_BAR 0x060
|
||||
|
||||
/* NVC Base Address Register */
|
||||
#define X_CQ_NVC_BAR 0x0D
|
||||
#define CQ_NVC_BAR 0x068
|
||||
|
||||
/* Table Address Register */
|
||||
#define X_CQ_TAR 0x0E
|
||||
#define CQ_TAR 0x070
|
||||
#define CQ_TAR_AUTOINC PPC_BIT(0)
|
||||
#define CQ_TAR_SELECT PPC_BITMASK(12, 15)
|
||||
#define CQ_TAR_ESB 0 /* 0 - 15 */
|
||||
#define CQ_TAR_END 2 /* 0 - 15 */
|
||||
#define CQ_TAR_NVPG 3 /* 0 - 15 */
|
||||
#define CQ_TAR_NVC 5 /* 0 - 15 */
|
||||
#define CQ_TAR_ENTRY_SELECT PPC_BITMASK(28, 31)
|
||||
|
||||
/* Table Data Register */
|
||||
#define X_CQ_TDR 0x0F
|
||||
#define CQ_TDR 0x078
|
||||
/* for the NVPG, NVC, ESB, END Set Translation Tables */
|
||||
#define CQ_TDR_VALID PPC_BIT(0)
|
||||
#define CQ_TDR_BLOCK_ID PPC_BITMASK(60, 63)
|
||||
|
||||
/*
|
||||
* Processor Cores Enabled for MsgSnd
|
||||
* Identifies which of the 32 possible core chiplets are enabled and
|
||||
* available to receive the MsgSnd command
|
||||
*/
|
||||
#define X_CQ_MSGSND 0x10
|
||||
#define CQ_MSGSND 0x080
|
||||
|
||||
/* Interrupt Unit Reset Control */
|
||||
#define X_CQ_RST_CTL 0x12
|
||||
#define CQ_RST_CTL 0x090
|
||||
#define CQ_RST_SYNC_RESET PPC_BIT(0) /* Write Only */
|
||||
#define CQ_RST_QUIESCE_PB PPC_BIT(1) /* RW */
|
||||
#define CQ_RST_MASTER_IDLE PPC_BIT(2) /* Read Only */
|
||||
#define CQ_RST_SAVE_IDLE PPC_BIT(3) /* Read Only */
|
||||
#define CQ_RST_PB_BAR_RESET PPC_BIT(4) /* Write Only */
|
||||
|
||||
/* PowerBus General Configuration */
|
||||
#define X_CQ_CFG_PB_GEN 0x14
|
||||
#define CQ_CFG_PB_GEN 0x0A0
|
||||
#define CQ_CFG_PB_GEN_PB_INIT PPC_BIT(45)
|
||||
|
||||
/*
|
||||
* FIR
|
||||
* (And-Mask)
|
||||
* (Or-Mask)
|
||||
*/
|
||||
#define X_CQ_FIR 0x30
|
||||
#define X_CQ_FIR_AND 0x31
|
||||
#define X_CQ_FIR_OR 0x32
|
||||
#define CQ_FIR 0x180
|
||||
#define CQ_FIR_AND 0x188
|
||||
#define CQ_FIR_OR 0x190
|
||||
#define CQ_FIR_PB_RCMDX_CI_ERR1 PPC_BIT(19)
|
||||
#define CQ_FIR_VC_INFO_ERROR_0_2 PPC_BITMASK(61, 63)
|
||||
|
||||
/*
|
||||
* FIR Mask
|
||||
* (And-Mask)
|
||||
* (Or-Mask)
|
||||
*/
|
||||
#define X_CQ_FIRMASK 0x33
|
||||
#define X_CQ_FIRMASK_AND 0x34
|
||||
#define X_CQ_FIRMASK_OR 0x35
|
||||
#define CQ_FIRMASK 0x198
|
||||
#define CQ_FIRMASK_AND 0x1A0
|
||||
#define CQ_FIRMASK_OR 0x1A8
|
||||
|
||||
/*
|
||||
* VC0
|
||||
*/
|
||||
|
||||
/* VSD table address */
|
||||
#define X_VC_VSD_TABLE_ADDR 0x100
|
||||
#define VC_VSD_TABLE_ADDR 0x000
|
||||
#define VC_VSD_TABLE_AUTOINC PPC_BIT(0)
|
||||
#define VC_VSD_TABLE_SELECT PPC_BITMASK(12, 15)
|
||||
#define VC_VSD_TABLE_ADDRESS PPC_BITMASK(28, 31)
|
||||
|
||||
/* VSD table data */
|
||||
#define X_VC_VSD_TABLE_DATA 0x101
|
||||
#define VC_VSD_TABLE_DATA 0x008
|
||||
|
||||
/* AIB AT macro indirect kill */
|
||||
#define X_VC_AT_MACRO_KILL 0x102
|
||||
#define VC_AT_MACRO_KILL 0x010
|
||||
#define VC_AT_MACRO_KILL_VALID PPC_BIT(0)
|
||||
#define VC_AT_MACRO_KILL_VSD PPC_BITMASK(12, 15)
|
||||
#define VC_AT_MACRO_KILL_BLOCK_ID PPC_BITMASK(28, 31)
|
||||
#define VC_AT_MACRO_KILL_OFFSET PPC_BITMASK(48, 60)
|
||||
|
||||
/* AIB AT macro indirect kill mask (same bit definitions) */
|
||||
#define X_VC_AT_MACRO_KILL_MASK 0x103
|
||||
#define VC_AT_MACRO_KILL_MASK 0x018
|
||||
|
||||
/* Remote IRQs and ERQs configuration [n] (n = 0:6) */
|
||||
#define X_VC_QUEUES_CFG_REM0 0x117
|
||||
|
||||
#define VC_QUEUES_CFG_REM0 0x0B8
|
||||
#define VC_QUEUES_CFG_REM1 0x0C0
|
||||
#define VC_QUEUES_CFG_REM2 0x0C8
|
||||
#define VC_QUEUES_CFG_REM3 0x0D0
|
||||
#define VC_QUEUES_CFG_REM4 0x0D8
|
||||
#define VC_QUEUES_CFG_REM5 0x0E0
|
||||
#define VC_QUEUES_CFG_REM6 0x0E8
|
||||
#define VC_QUEUES_CFG_MEMB_EN PPC_BIT(38)
|
||||
#define VC_QUEUES_CFG_MEMB_SZ PPC_BITMASK(42, 47)
|
||||
|
||||
/*
|
||||
* VC1
|
||||
*/
|
||||
|
||||
/* ESBC cache flush control trigger */
|
||||
#define X_VC_ESBC_FLUSH_CTRL 0x140
|
||||
#define VC_ESBC_FLUSH_CTRL 0x200
|
||||
#define VC_ESBC_FLUSH_CTRL_POLL_VALID PPC_BIT(0)
|
||||
#define VC_ESBC_FLUSH_CTRL_WANT_CACHE_DISABLE PPC_BIT(2)
|
||||
|
||||
/* ESBC cache flush poll trigger */
|
||||
#define X_VC_ESBC_FLUSH_POLL 0x141
|
||||
#define VC_ESBC_FLUSH_POLL 0x208
|
||||
#define VC_ESBC_FLUSH_POLL_BLOCK_ID PPC_BITMASK(0, 3)
|
||||
#define VC_ESBC_FLUSH_POLL_OFFSET PPC_BITMASK(4, 31) /* 28-bit */
|
||||
#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 */
|
||||
|
||||
/* EASC flush control register */
|
||||
#define X_VC_EASC_FLUSH_CTRL 0x160
|
||||
#define VC_EASC_FLUSH_CTRL 0x300
|
||||
#define VC_EASC_FLUSH_CTRL_POLL_VALID PPC_BIT(0)
|
||||
#define VC_EASC_FLUSH_CTRL_WANT_CACHE_DISABLE PPC_BIT(2)
|
||||
|
||||
/* EASC flush poll register */
|
||||
#define X_VC_EASC_FLUSH_POLL 0x161
|
||||
#define VC_EASC_FLUSH_POLL 0x308
|
||||
#define VC_EASC_FLUSH_POLL_BLOCK_ID PPC_BITMASK(0, 3)
|
||||
#define VC_EASC_FLUSH_POLL_OFFSET PPC_BITMASK(4, 31) /* 28-bit */
|
||||
#define VC_EASC_FLUSH_POLL_BLOCK_ID_MASK PPC_BITMASK(32, 35)
|
||||
#define VC_EASC_FLUSH_POLL_OFFSET_MASK PPC_BITMASK(36, 63) /* 28-bit */
|
||||
|
||||
/*
|
||||
* VC2
|
||||
*/
|
||||
|
||||
/* ENDC flush control register */
|
||||
#define X_VC_ENDC_FLUSH_CTRL 0x180
|
||||
#define VC_ENDC_FLUSH_CTRL 0x400
|
||||
#define VC_ENDC_FLUSH_CTRL_POLL_VALID PPC_BIT(0)
|
||||
#define VC_ENDC_FLUSH_CTRL_WANT_CACHE_DISABLE PPC_BIT(2)
|
||||
#define VC_ENDC_FLUSH_CTRL_WANT_INVALIDATE PPC_BIT(3)
|
||||
#define VC_ENDC_FLUSH_CTRL_INJECT_INVALIDATE PPC_BIT(7)
|
||||
|
||||
/* ENDC flush poll register */
|
||||
#define X_VC_ENDC_FLUSH_POLL 0x181
|
||||
#define VC_ENDC_FLUSH_POLL 0x408
|
||||
#define VC_ENDC_FLUSH_POLL_BLOCK_ID PPC_BITMASK(4, 7)
|
||||
#define VC_ENDC_FLUSH_POLL_OFFSET PPC_BITMASK(8, 31) /* 24-bit */
|
||||
#define VC_ENDC_FLUSH_POLL_BLOCK_ID_MASK PPC_BITMASK(36, 39)
|
||||
#define VC_ENDC_FLUSH_POLL_OFFSET_MASK PPC_BITMASK(40, 63) /* 24-bit */
|
||||
|
||||
/* ENDC Sync done */
|
||||
#define X_VC_ENDC_SYNC_DONE 0x184
|
||||
#define VC_ENDC_SYNC_DONE 0x420
|
||||
#define VC_ENDC_SYNC_POLL_DONE PPC_BITMASK(0, 6)
|
||||
#define VC_ENDC_SYNC_QUEUE_IPI PPC_BIT(0)
|
||||
#define VC_ENDC_SYNC_QUEUE_HWD PPC_BIT(1)
|
||||
#define VC_ENDC_SYNC_QUEUE_NXC PPC_BIT(2)
|
||||
#define VC_ENDC_SYNC_QUEUE_INT PPC_BIT(3)
|
||||
#define VC_ENDC_SYNC_QUEUE_OS PPC_BIT(4)
|
||||
#define VC_ENDC_SYNC_QUEUE_POOL PPC_BIT(5)
|
||||
#define VC_ENDC_SYNC_QUEUE_HARD PPC_BIT(6)
|
||||
#define VC_QUEUE_COUNT 7
|
||||
|
||||
/* ENDC cache watch specification 0 */
|
||||
#define X_VC_ENDC_WATCH0_SPEC 0x1A0
|
||||
#define VC_ENDC_WATCH0_SPEC 0x500
|
||||
#define VC_ENDC_WATCH_CONFLICT PPC_BIT(0)
|
||||
#define VC_ENDC_WATCH_FULL PPC_BIT(8)
|
||||
#define VC_ENDC_WATCH_BLOCK_ID PPC_BITMASK(28, 31)
|
||||
#define VC_ENDC_WATCH_INDEX PPC_BITMASK(40, 63)
|
||||
|
||||
/* ENDC cache watch data 0 */
|
||||
#define X_VC_ENDC_WATCH0_DATA0 0x1A4
|
||||
#define X_VC_ENDC_WATCH0_DATA1 0x1A5
|
||||
#define X_VC_ENDC_WATCH0_DATA2 0x1A6
|
||||
#define X_VC_ENDC_WATCH0_DATA3 0x1A7
|
||||
|
||||
#define VC_ENDC_WATCH0_DATA0 0x520
|
||||
#define VC_ENDC_WATCH0_DATA1 0x528
|
||||
#define VC_ENDC_WATCH0_DATA2 0x530
|
||||
#define VC_ENDC_WATCH0_DATA3 0x538
|
||||
|
||||
/*
|
||||
* PC LSB1
|
||||
*/
|
||||
|
||||
/* VSD table address register */
|
||||
#define X_PC_VSD_TABLE_ADDR 0x200
|
||||
#define PC_VSD_TABLE_ADDR 0x000
|
||||
#define PC_VSD_TABLE_AUTOINC PPC_BIT(0)
|
||||
#define PC_VSD_TABLE_SELECT PPC_BITMASK(12, 15)
|
||||
#define PC_VSD_TABLE_ADDRESS PPC_BITMASK(28, 31)
|
||||
|
||||
/* VSD table data register */
|
||||
#define X_PC_VSD_TABLE_DATA 0x201
|
||||
#define PC_VSD_TABLE_DATA 0x008
|
||||
|
||||
/* AT indirect kill register */
|
||||
#define X_PC_AT_KILL 0x202
|
||||
#define PC_AT_KILL 0x010
|
||||
#define PC_AT_KILL_VALID PPC_BIT(0)
|
||||
#define PC_AT_KILL_VSD_TYPE PPC_BITMASK(24, 27)
|
||||
/* Only NVP, NVG, NVC */
|
||||
#define PC_AT_KILL_BLOCK_ID PPC_BITMASK(28, 31)
|
||||
#define PC_AT_KILL_OFFSET PPC_BITMASK(48, 60)
|
||||
|
||||
/* AT indirect kill mask register */
|
||||
#define X_PC_AT_KILL_MASK 0x203
|
||||
#define PC_AT_KILL_MASK 0x018
|
||||
#define PC_AT_KILL_MASK_VSD_TYPE PPC_BITMASK(24, 27)
|
||||
#define PC_AT_KILL_MASK_BLOCK_ID PPC_BITMASK(28, 31)
|
||||
#define PC_AT_KILL_MASK_OFFSET PPC_BITMASK(48, 60)
|
||||
|
||||
/*
|
||||
* PC LSB2
|
||||
*/
|
||||
|
||||
/* NxC Cache flush control */
|
||||
#define X_PC_NXC_FLUSH_CTRL 0x280
|
||||
#define PC_NXC_FLUSH_CTRL 0x400
|
||||
#define PC_NXC_FLUSH_CTRL_POLL_VALID PPC_BIT(0)
|
||||
#define PC_NXC_FLUSH_CTRL_WANT_CACHE_DISABLE PPC_BIT(2)
|
||||
#define PC_NXC_FLUSH_CTRL_WANT_INVALIDATE PPC_BIT(3)
|
||||
#define PC_NXC_FLUSH_CTRL_INJECT_INVALIDATE PPC_BIT(7)
|
||||
|
||||
/* NxC Cache flush poll */
|
||||
#define X_PC_NXC_FLUSH_POLL 0x281
|
||||
#define PC_NXC_FLUSH_POLL 0x408
|
||||
#define PC_NXC_FLUSH_POLL_NXC_TYPE PPC_BITMASK(2, 3)
|
||||
#define PC_NXC_FLUSH_POLL_NXC_TYPE_NVP 0
|
||||
#define PC_NXC_FLUSH_POLL_NXC_TYPE_NVG 2
|
||||
#define PC_NXC_FLUSH_POLL_NXC_TYPE_NVC 3
|
||||
#define PC_NXC_FLUSH_POLL_BLOCK_ID PPC_BITMASK(4, 7)
|
||||
#define PC_NXC_FLUSH_POLL_OFFSET PPC_BITMASK(8, 31) /* 24-bit */
|
||||
#define PC_NXC_FLUSH_POLL_NXC_TYPE_MASK PPC_BITMASK(34, 35) /* 0: Ign */
|
||||
#define PC_NXC_FLUSH_POLL_BLOCK_ID_MASK PPC_BITMASK(36, 39)
|
||||
#define PC_NXC_FLUSH_POLL_OFFSET_MASK PPC_BITMASK(40, 63) /* 24-bit */
|
||||
|
||||
/* NxC Cache Watch 0 Specification */
|
||||
#define X_PC_NXC_WATCH0_SPEC 0x2A0
|
||||
#define PC_NXC_WATCH0_SPEC 0x500
|
||||
#define PC_NXC_WATCH_CONFLICT PPC_BIT(0)
|
||||
#define PC_NXC_WATCH_FULL PPC_BIT(8)
|
||||
#define PC_NXC_WATCH_NXC_TYPE PPC_BITMASK(26, 27)
|
||||
#define PC_NXC_WATCH_NXC_NVP 0
|
||||
#define PC_NXC_WATCH_NXC_NVG 2
|
||||
#define PC_NXC_WATCH_NXC_NVC 3
|
||||
#define PC_NXC_WATCH_BLOCK_ID PPC_BITMASK(28, 31)
|
||||
#define PC_NXC_WATCH_INDEX PPC_BITMASK(40, 63)
|
||||
|
||||
/* NxC Cache Watch 0 Data */
|
||||
#define X_PC_NXC_WATCH0_DATA0 0x2A4
|
||||
#define X_PC_NXC_WATCH0_DATA1 0x2A5
|
||||
#define X_PC_NXC_WATCH0_DATA2 0x2A6
|
||||
#define X_PC_NXC_WATCH0_DATA3 0x2A7
|
||||
|
||||
#define PC_NXC_WATCH0_DATA0 0x520
|
||||
#define PC_NXC_WATCH0_DATA1 0x528
|
||||
#define PC_NXC_WATCH0_DATA2 0x530
|
||||
#define PC_NXC_WATCH0_DATA3 0x538
|
||||
|
||||
/*
|
||||
* TCTXT Registers
|
||||
*/
|
||||
|
||||
/* Physical Thread Enable0 register */
|
||||
#define X_TCTXT_EN0 0x300
|
||||
#define TCTXT_EN0 0x000
|
||||
|
||||
/* Physical Thread Enable0 Set register */
|
||||
#define X_TCTXT_EN0_SET 0x302
|
||||
#define TCTXT_EN0_SET 0x010
|
||||
|
||||
/* Physical Thread Enable0 Reset register */
|
||||
#define X_TCTXT_EN0_RESET 0x303
|
||||
#define TCTXT_EN0_RESET 0x018
|
||||
|
||||
/* Physical Thread Enable1 register */
|
||||
#define X_TCTXT_EN1 0x304
|
||||
#define TCTXT_EN1 0x020
|
||||
|
||||
/* Physical Thread Enable1 Set register */
|
||||
#define X_TCTXT_EN1_SET 0x306
|
||||
#define TCTXT_EN1_SET 0x030
|
||||
|
||||
/* Physical Thread Enable1 Reset register */
|
||||
#define X_TCTXT_EN1_RESET 0x307
|
||||
#define TCTXT_EN1_RESET 0x038
|
||||
|
||||
/*
|
||||
* VSD Tables
|
||||
*/
|
||||
#define VST_ESB 0
|
||||
#define VST_EAS 1 /* No used by PC */
|
||||
#define VST_END 2
|
||||
#define VST_NVP 3
|
||||
#define VST_NVG 4
|
||||
#define VST_NVC 5
|
||||
#define VST_IC 6 /* No used by PC */
|
||||
#define VST_SYNC 7
|
||||
#define VST_ERQ 8 /* No used by PC */
|
||||
|
||||
/*
|
||||
* Bits in a VSD entry.
|
||||
*
|
||||
* Note: the address is naturally aligned, we don't use a PPC_BITMASK,
|
||||
* but just a mask to apply to the address before OR'ing it in.
|
||||
*
|
||||
* Note: VSD_FIRMWARE is a SW bit ! It hijacks an unused bit in the
|
||||
* VSD and is only meant to be used in indirect mode !
|
||||
*/
|
||||
#define VSD_MODE PPC_BITMASK(0, 1)
|
||||
#define VSD_MODE_SHARED 1
|
||||
#define VSD_MODE_EXCLUSIVE 2
|
||||
#define VSD_MODE_FORWARD 3
|
||||
#define VSD_FIRMWARE PPC_BIT(2) /* Read warning */
|
||||
#define VSD_FIRMWARE2 PPC_BIT(3) /* unused */
|
||||
#define VSD_RESERVED PPC_BITMASK(4, 7) /* P10 reserved */
|
||||
#define VSD_ADDRESS_MASK 0x00fffffffffff000ull
|
||||
#define VSD_MIGRATION_REG PPC_BITMASK(52, 55)
|
||||
#define VSD_INDIRECT PPC_BIT(56)
|
||||
#define VSD_TSIZE PPC_BITMASK(59, 63)
|
||||
|
||||
#endif /* PPC_PNV_XIVE2_REGS_H */
|
||||
@@ -480,6 +480,29 @@ static uint8_t spapr_xive_get_block_id(XiveRouter *xrtr)
|
||||
return SPAPR_XIVE_BLOCK_ID;
|
||||
}
|
||||
|
||||
static int spapr_xive_get_pq(XiveRouter *xrtr, uint8_t blk, uint32_t idx,
|
||||
uint8_t *pq)
|
||||
{
|
||||
SpaprXive *xive = SPAPR_XIVE(xrtr);
|
||||
|
||||
assert(SPAPR_XIVE_BLOCK_ID == blk);
|
||||
|
||||
*pq = xive_source_esb_get(&xive->source, idx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int spapr_xive_set_pq(XiveRouter *xrtr, uint8_t blk, uint32_t idx,
|
||||
uint8_t *pq)
|
||||
{
|
||||
SpaprXive *xive = SPAPR_XIVE(xrtr);
|
||||
|
||||
assert(SPAPR_XIVE_BLOCK_ID == blk);
|
||||
|
||||
*pq = xive_source_esb_set(&xive->source, idx, *pq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static const VMStateDescription vmstate_spapr_xive_end = {
|
||||
.name = TYPE_SPAPR_XIVE "/end",
|
||||
.version_id = 1,
|
||||
@@ -788,6 +811,8 @@ static void spapr_xive_class_init(ObjectClass *klass, void *data)
|
||||
dc->vmsd = &vmstate_spapr_xive;
|
||||
|
||||
xrc->get_eas = spapr_xive_get_eas;
|
||||
xrc->get_pq = spapr_xive_get_pq;
|
||||
xrc->set_pq = spapr_xive_set_pq;
|
||||
xrc->get_end = spapr_xive_get_end;
|
||||
xrc->write_end = spapr_xive_write_end;
|
||||
xrc->get_nvt = spapr_xive_get_nvt;
|
||||
|
||||
+70
-7
@@ -886,6 +886,16 @@ static bool xive_source_lsi_trigger(XiveSource *xsrc, uint32_t srcno)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Sources can be configured with PQ offloading in which case the check
|
||||
* on the PQ state bits of MSIs is disabled
|
||||
*/
|
||||
static bool xive_source_esb_disabled(XiveSource *xsrc, uint32_t srcno)
|
||||
{
|
||||
return (xsrc->esb_flags & XIVE_SRC_PQ_DISABLE) &&
|
||||
!xive_source_irq_is_lsi(xsrc, srcno);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns whether the event notification should be forwarded.
|
||||
*/
|
||||
@@ -895,6 +905,10 @@ static bool xive_source_esb_trigger(XiveSource *xsrc, uint32_t srcno)
|
||||
|
||||
assert(srcno < xsrc->nr_irqs);
|
||||
|
||||
if (xive_source_esb_disabled(xsrc, srcno)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
ret = xive_esb_trigger(&xsrc->status[srcno]);
|
||||
|
||||
if (xive_source_irq_is_lsi(xsrc, srcno) &&
|
||||
@@ -915,6 +929,11 @@ static bool xive_source_esb_eoi(XiveSource *xsrc, uint32_t srcno)
|
||||
|
||||
assert(srcno < xsrc->nr_irqs);
|
||||
|
||||
if (xive_source_esb_disabled(xsrc, srcno)) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "XIVE: invalid EOI for IRQ %d\n", srcno);
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = xive_esb_eoi(&xsrc->status[srcno]);
|
||||
|
||||
/*
|
||||
@@ -936,9 +955,10 @@ static bool xive_source_esb_eoi(XiveSource *xsrc, uint32_t srcno)
|
||||
static void xive_source_notify(XiveSource *xsrc, int srcno)
|
||||
{
|
||||
XiveNotifierClass *xnc = XIVE_NOTIFIER_GET_CLASS(xsrc->xive);
|
||||
bool pq_checked = !xive_source_esb_disabled(xsrc, srcno);
|
||||
|
||||
if (xnc->notify) {
|
||||
xnc->notify(xsrc->xive, srcno);
|
||||
xnc->notify(xsrc->xive, srcno, pq_checked);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1061,6 +1081,15 @@ static void xive_source_esb_write(void *opaque, hwaddr addr,
|
||||
notify = xive_source_esb_eoi(xsrc, srcno);
|
||||
break;
|
||||
|
||||
/*
|
||||
* This is an internal offset used to inject triggers when the PQ
|
||||
* state bits are not controlled locally. Such as for LSIs when
|
||||
* under ABT mode.
|
||||
*/
|
||||
case XIVE_ESB_INJECT ... XIVE_ESB_INJECT + 0x3FF:
|
||||
notify = true;
|
||||
break;
|
||||
|
||||
case XIVE_ESB_SET_PQ_00 ... XIVE_ESB_SET_PQ_00 + 0x0FF:
|
||||
case XIVE_ESB_SET_PQ_01 ... XIVE_ESB_SET_PQ_01 + 0x0FF:
|
||||
case XIVE_ESB_SET_PQ_10 ... XIVE_ESB_SET_PQ_10 + 0x0FF:
|
||||
@@ -1361,6 +1390,24 @@ int xive_router_get_eas(XiveRouter *xrtr, uint8_t eas_blk, uint32_t eas_idx,
|
||||
return xrc->get_eas(xrtr, eas_blk, eas_idx, eas);
|
||||
}
|
||||
|
||||
static
|
||||
int xive_router_get_pq(XiveRouter *xrtr, uint8_t eas_blk, uint32_t eas_idx,
|
||||
uint8_t *pq)
|
||||
{
|
||||
XiveRouterClass *xrc = XIVE_ROUTER_GET_CLASS(xrtr);
|
||||
|
||||
return xrc->get_pq(xrtr, eas_blk, eas_idx, pq);
|
||||
}
|
||||
|
||||
static
|
||||
int xive_router_set_pq(XiveRouter *xrtr, uint8_t eas_blk, uint32_t eas_idx,
|
||||
uint8_t *pq)
|
||||
{
|
||||
XiveRouterClass *xrc = XIVE_ROUTER_GET_CLASS(xrtr);
|
||||
|
||||
return xrc->set_pq(xrtr, eas_blk, eas_idx, pq);
|
||||
}
|
||||
|
||||
int xive_router_get_end(XiveRouter *xrtr, uint8_t end_blk, uint32_t end_idx,
|
||||
XiveEND *end)
|
||||
{
|
||||
@@ -1712,7 +1759,7 @@ do_escalation:
|
||||
xive_get_field32(END_W5_ESC_END_DATA, end.w5));
|
||||
}
|
||||
|
||||
void xive_router_notify(XiveNotifier *xn, uint32_t lisn)
|
||||
void xive_router_notify(XiveNotifier *xn, uint32_t lisn, bool pq_checked)
|
||||
{
|
||||
XiveRouter *xrtr = XIVE_ROUTER(xn);
|
||||
uint8_t eas_blk = XIVE_EAS_BLOCK(lisn);
|
||||
@@ -1725,11 +1772,27 @@ void xive_router_notify(XiveNotifier *xn, uint32_t lisn)
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* The IVRE checks the State Bit Cache at this point. We skip the
|
||||
* SBC lookup because the state bits of the sources are modeled
|
||||
* internally in QEMU.
|
||||
*/
|
||||
if (!pq_checked) {
|
||||
bool notify;
|
||||
uint8_t pq;
|
||||
|
||||
/* PQ cache lookup */
|
||||
if (xive_router_get_pq(xrtr, eas_blk, eas_idx, &pq)) {
|
||||
/* Set FIR */
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
notify = xive_esb_trigger(&pq);
|
||||
|
||||
if (xive_router_set_pq(xrtr, eas_blk, eas_idx, &pq)) {
|
||||
/* Set FIR */
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
if (!notify) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!xive_eas_is_valid(&eas)) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "XIVE: invalid LISN %x\n", lisn);
|
||||
|
||||
+1018
File diff suppressed because it is too large
Load Diff
+117
-26
@@ -485,6 +485,15 @@ static void pnv_phb4_update_xsrc(PnvPHB4 *phb)
|
||||
flags = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* When the PQ disable configuration bit is set, the check on the
|
||||
* PQ state bits is disabled on the PHB side (for MSI only) and it
|
||||
* is performed on the IC side instead.
|
||||
*/
|
||||
if (phb->regs[PHB_CTRLR >> 3] & PHB_CTRLR_IRQ_PQ_DISABLE) {
|
||||
flags |= XIVE_SRC_PQ_DISABLE;
|
||||
}
|
||||
|
||||
phb->xsrc.esb_shift = shift;
|
||||
phb->xsrc.esb_flags = flags;
|
||||
|
||||
@@ -1568,40 +1577,36 @@ static PnvPhb4PecState *pnv_phb4_get_pec(PnvChip *chip, PnvPHB4 *phb,
|
||||
static void pnv_phb4_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
PnvPHB4 *phb = PNV_PHB4(dev);
|
||||
PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine());
|
||||
PnvChip *chip = pnv_get_chip(pnv, phb->chip_id);
|
||||
PCIHostState *pci = PCI_HOST_BRIDGE(dev);
|
||||
XiveSource *xsrc = &phb->xsrc;
|
||||
BusState *s;
|
||||
Error *local_err = NULL;
|
||||
int nr_irqs;
|
||||
char name[32];
|
||||
|
||||
/* User created PHB */
|
||||
if (!chip) {
|
||||
error_setg(errp, "invalid chip id: %d", phb->chip_id);
|
||||
return;
|
||||
}
|
||||
|
||||
/* User created PHBs need to be assigned to a PEC */
|
||||
if (!phb->pec) {
|
||||
PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine());
|
||||
PnvChip *chip = pnv_get_chip(pnv, phb->chip_id);
|
||||
BusState *s;
|
||||
|
||||
if (!chip) {
|
||||
error_setg(errp, "invalid chip id: %d", phb->chip_id);
|
||||
return;
|
||||
}
|
||||
|
||||
phb->pec = pnv_phb4_get_pec(chip, phb, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Reparent user created devices to the chip to build
|
||||
* correctly the device tree.
|
||||
*/
|
||||
pnv_chip_parent_fixup(chip, OBJECT(phb), phb->phb_id);
|
||||
/* Reparent the PHB to the chip to build the device tree */
|
||||
pnv_chip_parent_fixup(chip, OBJECT(phb), phb->phb_id);
|
||||
|
||||
s = qdev_get_parent_bus(DEVICE(chip));
|
||||
if (!qdev_set_parent_bus(DEVICE(phb), s, &local_err)) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
}
|
||||
s = qdev_get_parent_bus(DEVICE(chip));
|
||||
if (!qdev_set_parent_bus(DEVICE(phb), s, &local_err)) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set the "big_phb" flag */
|
||||
@@ -1664,15 +1669,64 @@ static const char *pnv_phb4_root_bus_path(PCIHostState *host_bridge,
|
||||
return phb->bus_path;
|
||||
}
|
||||
|
||||
static void pnv_phb4_xive_notify(XiveNotifier *xf, uint32_t srcno)
|
||||
/*
|
||||
* Address base trigger mode (POWER10)
|
||||
*
|
||||
* Trigger directly the IC ESB page
|
||||
*/
|
||||
static void pnv_phb4_xive_notify_abt(PnvPHB4 *phb, uint32_t srcno,
|
||||
bool pq_checked)
|
||||
{
|
||||
uint64_t notif_port = phb->regs[PHB_INT_NOTIFY_ADDR >> 3];
|
||||
uint64_t data = 0; /* trigger data : don't care */
|
||||
hwaddr addr;
|
||||
MemTxResult result;
|
||||
int esb_shift;
|
||||
|
||||
if (notif_port & PHB_INT_NOTIFY_ADDR_64K) {
|
||||
esb_shift = 16;
|
||||
} else {
|
||||
esb_shift = 12;
|
||||
}
|
||||
|
||||
/* Compute the address of the IC ESB management page */
|
||||
addr = (notif_port & ~PHB_INT_NOTIFY_ADDR_64K);
|
||||
addr |= (1ull << (esb_shift + 1)) * srcno;
|
||||
addr |= (1ull << esb_shift);
|
||||
|
||||
/*
|
||||
* When the PQ state bits are checked on the PHB, the associated
|
||||
* PQ state bits on the IC should be ignored. Use the unconditional
|
||||
* trigger offset to inject a trigger on the IC. This is always
|
||||
* the case for LSIs
|
||||
*/
|
||||
if (pq_checked) {
|
||||
addr |= XIVE_ESB_INJECT;
|
||||
}
|
||||
|
||||
trace_pnv_phb4_xive_notify_ic(addr, data);
|
||||
|
||||
address_space_stq_be(&address_space_memory, addr, data,
|
||||
MEMTXATTRS_UNSPECIFIED, &result);
|
||||
if (result != MEMTX_OK) {
|
||||
phb_error(phb, "trigger failed @%"HWADDR_PRIx "\n", addr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void pnv_phb4_xive_notify_ic(PnvPHB4 *phb, uint32_t srcno,
|
||||
bool pq_checked)
|
||||
{
|
||||
PnvPHB4 *phb = PNV_PHB4(xf);
|
||||
uint64_t notif_port = phb->regs[PHB_INT_NOTIFY_ADDR >> 3];
|
||||
uint32_t offset = phb->regs[PHB_INT_NOTIFY_INDEX >> 3];
|
||||
uint64_t data = XIVE_TRIGGER_PQ | offset | srcno;
|
||||
uint64_t data = offset | srcno;
|
||||
MemTxResult result;
|
||||
|
||||
trace_pnv_phb4_xive_notify(notif_port, data);
|
||||
if (pq_checked) {
|
||||
data |= XIVE_TRIGGER_PQ;
|
||||
}
|
||||
|
||||
trace_pnv_phb4_xive_notify_ic(notif_port, data);
|
||||
|
||||
address_space_stq_be(&address_space_memory, notif_port, data,
|
||||
MEMTXATTRS_UNSPECIFIED, &result);
|
||||
@@ -1682,6 +1736,18 @@ static void pnv_phb4_xive_notify(XiveNotifier *xf, uint32_t srcno)
|
||||
}
|
||||
}
|
||||
|
||||
static void pnv_phb4_xive_notify(XiveNotifier *xf, uint32_t srcno,
|
||||
bool pq_checked)
|
||||
{
|
||||
PnvPHB4 *phb = PNV_PHB4(xf);
|
||||
|
||||
if (phb->regs[PHB_CTRLR >> 3] & PHB_CTRLR_IRQ_ABT_MODE) {
|
||||
pnv_phb4_xive_notify_abt(phb, srcno, pq_checked);
|
||||
} else {
|
||||
pnv_phb4_xive_notify_ic(phb, srcno, pq_checked);
|
||||
}
|
||||
}
|
||||
|
||||
static Property pnv_phb4_properties[] = {
|
||||
DEFINE_PROP_UINT32("index", PnvPHB4, phb_id, 0),
|
||||
DEFINE_PROP_UINT32("chip-id", PnvPHB4, chip_id, 0),
|
||||
@@ -1816,9 +1882,29 @@ static const TypeInfo pnv_phb4_root_port_info = {
|
||||
.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 = true;
|
||||
|
||||
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(&pnv_phb4_root_bus_info);
|
||||
type_register_static(&pnv_phb5_root_port_info);
|
||||
type_register_static(&pnv_phb4_root_port_info);
|
||||
type_register_static(&pnv_phb4_type_info);
|
||||
type_register_static(&pnv_phb4_iommu_memory_region_info);
|
||||
@@ -1828,10 +1914,15 @@ type_init(pnv_phb4_register_types);
|
||||
|
||||
void pnv_phb4_pic_print_info(PnvPHB4 *phb, Monitor *mon)
|
||||
{
|
||||
uint64_t notif_port =
|
||||
phb->regs[PHB_INT_NOTIFY_ADDR >> 3] & ~PHB_INT_NOTIFY_ADDR_64K;
|
||||
uint32_t offset = phb->regs[PHB_INT_NOTIFY_INDEX >> 3];
|
||||
bool abt = !!(phb->regs[PHB_CTRLR >> 3] & PHB_CTRLR_IRQ_ABT_MODE);
|
||||
|
||||
monitor_printf(mon, "PHB4[%x:%x] Source %08x .. %08x\n",
|
||||
monitor_printf(mon, "PHB4[%x:%x] Source %08x .. %08x %s @%"HWADDR_PRIx"\n",
|
||||
phb->chip_id, phb->phb_id,
|
||||
offset, offset + phb->xsrc.nr_irqs - 1);
|
||||
offset, offset + phb->xsrc.nr_irqs - 1,
|
||||
abt ? "ABT" : "",
|
||||
notif_port);
|
||||
xive_source_pic_print_info(&phb->xsrc, 0, mon);
|
||||
}
|
||||
|
||||
@@ -281,9 +281,62 @@ static const TypeInfo pnv_pec_type_info = {
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* POWER10 definitions
|
||||
*/
|
||||
|
||||
static uint32_t pnv_phb5_pec_xscom_pci_base(PnvPhb4PecState *pec)
|
||||
{
|
||||
return PNV10_XSCOM_PEC_PCI_BASE + 0x1000000 * pec->index;
|
||||
}
|
||||
|
||||
static uint32_t pnv_phb5_pec_xscom_nest_base(PnvPhb4PecState *pec)
|
||||
{
|
||||
/* index goes down ... */
|
||||
return PNV10_XSCOM_PEC_NEST_BASE - 0x1000000 * pec->index;
|
||||
}
|
||||
|
||||
/*
|
||||
* PEC0 -> 3 stacks
|
||||
* PEC1 -> 3 stacks
|
||||
*/
|
||||
static const uint32_t pnv_phb5_pec_num_stacks[] = { 3, 3 };
|
||||
|
||||
static void pnv_phb5_pec_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
PnvPhb4PecClass *pecc = PNV_PHB4_PEC_CLASS(klass);
|
||||
static const char compat[] = "ibm,power10-pbcq";
|
||||
static const char stk_compat[] = "ibm,power10-phb-stack";
|
||||
|
||||
pecc->xscom_nest_base = pnv_phb5_pec_xscom_nest_base;
|
||||
pecc->xscom_pci_base = pnv_phb5_pec_xscom_pci_base;
|
||||
pecc->xscom_nest_size = PNV10_XSCOM_PEC_NEST_SIZE;
|
||||
pecc->xscom_pci_size = PNV10_XSCOM_PEC_PCI_SIZE;
|
||||
pecc->compat = compat;
|
||||
pecc->compat_size = sizeof(compat);
|
||||
pecc->stk_compat = stk_compat;
|
||||
pecc->stk_compat_size = sizeof(stk_compat);
|
||||
pecc->version = PNV_PHB5_VERSION;
|
||||
pecc->num_phbs = pnv_phb5_pec_num_stacks;
|
||||
pecc->rp_model = TYPE_PNV_PHB5_ROOT_PORT;
|
||||
}
|
||||
|
||||
static const TypeInfo pnv_phb5_pec_type_info = {
|
||||
.name = TYPE_PNV_PHB5_PEC,
|
||||
.parent = TYPE_PNV_PHB4_PEC,
|
||||
.instance_size = sizeof(PnvPhb4PecState),
|
||||
.class_init = pnv_phb5_pec_class_init,
|
||||
.class_size = sizeof(PnvPhb4PecClass),
|
||||
.interfaces = (InterfaceInfo[]) {
|
||||
{ TYPE_PNV_XSCOM_INTERFACE },
|
||||
{ }
|
||||
}
|
||||
};
|
||||
|
||||
static void pnv_pec_register_types(void)
|
||||
{
|
||||
type_register_static(&pnv_pec_type_info);
|
||||
type_register_static(&pnv_phb5_pec_type_info);
|
||||
}
|
||||
|
||||
type_init(pnv_pec_register_types);
|
||||
|
||||
@@ -32,3 +32,5 @@ unin_read(uint64_t addr, uint64_t value) "addr=0x%" PRIx64 " val=0x%"PRIx64
|
||||
|
||||
# pnv_phb4.c
|
||||
pnv_phb4_xive_notify(uint64_t notif_port, uint64_t data) "notif=@0x%"PRIx64" data=0x%"PRIx64
|
||||
pnv_phb4_xive_notify_ic(uint64_t addr, uint64_t data) "addr=@0x%"PRIx64" data=0x%"PRIx64
|
||||
pnv_phb4_xive_notify_abt(uint64_t notif_port, uint64_t data) "notif=@0x%"PRIx64" data=0x%"PRIx64
|
||||
|
||||
+213
-14
@@ -380,9 +380,12 @@ static void pnv_dt_serial(ISADevice *d, void *fdt, int lpc_off)
|
||||
cpu_to_be32(io_base),
|
||||
cpu_to_be32(8)
|
||||
};
|
||||
uint32_t irq;
|
||||
char *name;
|
||||
int node;
|
||||
|
||||
irq = object_property_get_uint(OBJECT(d), "irq", &error_fatal);
|
||||
|
||||
name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base);
|
||||
node = fdt_add_subnode(fdt, lpc_off, name);
|
||||
_FDT(node);
|
||||
@@ -394,7 +397,7 @@ static void pnv_dt_serial(ISADevice *d, void *fdt, int lpc_off)
|
||||
|
||||
_FDT((fdt_setprop_cell(fdt, node, "clock-frequency", 1843200)));
|
||||
_FDT((fdt_setprop_cell(fdt, node, "current-speed", 115200)));
|
||||
_FDT((fdt_setprop_cell(fdt, node, "interrupts", d->isairq[0])));
|
||||
_FDT((fdt_setprop_cell(fdt, node, "interrupts", irq)));
|
||||
_FDT((fdt_setprop_cell(fdt, node, "interrupt-parent",
|
||||
fdt_get_phandle(fdt, lpc_off))));
|
||||
|
||||
@@ -722,7 +725,11 @@ static void pnv_chip_power10_pic_print_info(PnvChip *chip, Monitor *mon)
|
||||
{
|
||||
Pnv10Chip *chip10 = PNV10_CHIP(chip);
|
||||
|
||||
pnv_xive2_pic_print_info(&chip10->xive, mon);
|
||||
pnv_psi_pic_print_info(&chip10->psi, mon);
|
||||
|
||||
object_child_foreach_recursive(OBJECT(chip),
|
||||
pnv_chip_power9_pic_print_info_child, mon);
|
||||
}
|
||||
|
||||
/* Always give the first 1GB to chip 0 else we won't boot */
|
||||
@@ -1044,27 +1051,45 @@ static void pnv_chip_power9_intc_print_info(PnvChip *chip, PowerPCCPU *cpu,
|
||||
static void pnv_chip_power10_intc_create(PnvChip *chip, PowerPCCPU *cpu,
|
||||
Error **errp)
|
||||
{
|
||||
Pnv10Chip *chip10 = PNV10_CHIP(chip);
|
||||
Error *local_err = NULL;
|
||||
Object *obj;
|
||||
PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
|
||||
|
||||
/* Will be defined when the interrupt controller is */
|
||||
pnv_cpu->intc = NULL;
|
||||
/*
|
||||
* The core creates its interrupt presenter but the XIVE2 interrupt
|
||||
* controller object is initialized afterwards. Hopefully, it's
|
||||
* only used at runtime.
|
||||
*/
|
||||
obj = xive_tctx_create(OBJECT(cpu), XIVE_PRESENTER(&chip10->xive),
|
||||
&local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
}
|
||||
|
||||
pnv_cpu->intc = obj;
|
||||
}
|
||||
|
||||
static void pnv_chip_power10_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
|
||||
{
|
||||
;
|
||||
PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
|
||||
|
||||
xive_tctx_reset(XIVE_TCTX(pnv_cpu->intc));
|
||||
}
|
||||
|
||||
static void pnv_chip_power10_intc_destroy(PnvChip *chip, PowerPCCPU *cpu)
|
||||
{
|
||||
PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
|
||||
|
||||
xive_tctx_destroy(XIVE_TCTX(pnv_cpu->intc));
|
||||
pnv_cpu->intc = NULL;
|
||||
}
|
||||
|
||||
static void pnv_chip_power10_intc_print_info(PnvChip *chip, PowerPCCPU *cpu,
|
||||
Monitor *mon)
|
||||
{
|
||||
xive_tctx_pic_print_info(XIVE_TCTX(pnv_cpu_state(cpu)->intc), mon);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1366,6 +1391,21 @@ static void pnv_chip_power9_instance_init(Object *obj)
|
||||
}
|
||||
}
|
||||
|
||||
static void pnv_chip_quad_realize_one(PnvChip *chip, PnvQuad *eq,
|
||||
PnvCore *pnv_core)
|
||||
{
|
||||
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,
|
||||
&error_fatal, NULL);
|
||||
|
||||
object_property_set_int(OBJECT(eq), "quad-id", core_id, &error_fatal);
|
||||
qdev_realize(DEVICE(eq), NULL, &error_fatal);
|
||||
}
|
||||
|
||||
static void pnv_chip_quad_realize(Pnv9Chip *chip9, Error **errp)
|
||||
{
|
||||
PnvChip *chip = PNV_CHIP(chip9);
|
||||
@@ -1375,18 +1415,9 @@ static void pnv_chip_quad_realize(Pnv9Chip *chip9, Error **errp)
|
||||
chip9->quads = g_new0(PnvQuad, chip9->nr_quads);
|
||||
|
||||
for (i = 0; i < chip9->nr_quads; i++) {
|
||||
char eq_name[32];
|
||||
PnvQuad *eq = &chip9->quads[i];
|
||||
PnvCore *pnv_core = chip->cores[i * 4];
|
||||
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,
|
||||
&error_fatal, NULL);
|
||||
|
||||
object_property_set_int(OBJECT(eq), "quad-id", core_id, &error_fatal);
|
||||
qdev_realize(DEVICE(eq), NULL, &error_fatal);
|
||||
pnv_chip_quad_realize_one(chip, eq, chip->cores[i * 4]);
|
||||
|
||||
pnv_xscom_add_subregion(chip, PNV9_XSCOM_EQ_BASE(eq->quad_id),
|
||||
&eq->xscom_regs);
|
||||
@@ -1469,6 +1500,9 @@ static void pnv_chip_power9_realize(DeviceState *dev, Error **errp)
|
||||
/* Processor Service Interface (PSI) Host Bridge */
|
||||
object_property_set_int(OBJECT(&chip9->psi), "bar", PNV9_PSIHB_BASE(chip),
|
||||
&error_fatal);
|
||||
/* This is the only device with 4k ESB pages */
|
||||
object_property_set_int(OBJECT(&chip9->psi), "shift", XIVE_ESB_4K,
|
||||
&error_fatal);
|
||||
if (!qdev_realize(DEVICE(&chip9->psi), NULL, errp)) {
|
||||
return;
|
||||
}
|
||||
@@ -1553,10 +1587,73 @@ static void pnv_chip_power9_class_init(ObjectClass *klass, void *data)
|
||||
|
||||
static void pnv_chip_power10_instance_init(Object *obj)
|
||||
{
|
||||
PnvChip *chip = PNV_CHIP(obj);
|
||||
Pnv10Chip *chip10 = PNV10_CHIP(obj);
|
||||
PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj);
|
||||
int i;
|
||||
|
||||
object_initialize_child(obj, "xive", &chip10->xive, TYPE_PNV_XIVE2);
|
||||
object_property_add_alias(obj, "xive-fabric", OBJECT(&chip10->xive),
|
||||
"xive-fabric");
|
||||
object_initialize_child(obj, "psi", &chip10->psi, TYPE_PNV10_PSI);
|
||||
object_initialize_child(obj, "lpc", &chip10->lpc, TYPE_PNV10_LPC);
|
||||
object_initialize_child(obj, "occ", &chip10->occ, TYPE_PNV10_OCC);
|
||||
object_initialize_child(obj, "homer", &chip10->homer, TYPE_PNV10_HOMER);
|
||||
|
||||
if (defaults_enabled()) {
|
||||
chip->num_pecs = pcc->num_pecs;
|
||||
}
|
||||
|
||||
for (i = 0; i < chip->num_pecs; i++) {
|
||||
object_initialize_child(obj, "pec[*]", &chip10->pecs[i],
|
||||
TYPE_PNV_PHB5_PEC);
|
||||
}
|
||||
}
|
||||
|
||||
static void pnv_chip_power10_quad_realize(Pnv10Chip *chip10, Error **errp)
|
||||
{
|
||||
PnvChip *chip = PNV_CHIP(chip10);
|
||||
int i;
|
||||
|
||||
chip10->nr_quads = DIV_ROUND_UP(chip->nr_cores, 4);
|
||||
chip10->quads = g_new0(PnvQuad, chip10->nr_quads);
|
||||
|
||||
for (i = 0; i < chip10->nr_quads; i++) {
|
||||
PnvQuad *eq = &chip10->quads[i];
|
||||
|
||||
pnv_chip_quad_realize_one(chip, eq, chip->cores[i * 4]);
|
||||
|
||||
pnv_xscom_add_subregion(chip, PNV10_XSCOM_EQ_BASE(eq->quad_id),
|
||||
&eq->xscom_regs);
|
||||
}
|
||||
}
|
||||
|
||||
static void pnv_chip_power10_phb_realize(PnvChip *chip, Error **errp)
|
||||
{
|
||||
Pnv10Chip *chip10 = PNV10_CHIP(chip);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < chip->num_pecs; i++) {
|
||||
PnvPhb4PecState *pec = &chip10->pecs[i];
|
||||
PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec);
|
||||
uint32_t pec_nest_base;
|
||||
uint32_t pec_pci_base;
|
||||
|
||||
object_property_set_int(OBJECT(pec), "index", i, &error_fatal);
|
||||
object_property_set_int(OBJECT(pec), "chip-id", chip->chip_id,
|
||||
&error_fatal);
|
||||
object_property_set_link(OBJECT(pec), "chip", OBJECT(chip),
|
||||
&error_fatal);
|
||||
if (!qdev_realize(DEVICE(pec), NULL, errp)) {
|
||||
return;
|
||||
}
|
||||
|
||||
pec_nest_base = pecc->xscom_nest_base(pec);
|
||||
pec_pci_base = pecc->xscom_pci_base(pec);
|
||||
|
||||
pnv_xscom_add_subregion(chip, pec_nest_base, &pec->nest_regs_mr);
|
||||
pnv_xscom_add_subregion(chip, pec_pci_base, &pec->pci_regs_mr);
|
||||
}
|
||||
}
|
||||
|
||||
static void pnv_chip_power10_realize(DeviceState *dev, Error **errp)
|
||||
@@ -1580,9 +1677,39 @@ static void pnv_chip_power10_realize(DeviceState *dev, Error **errp)
|
||||
return;
|
||||
}
|
||||
|
||||
pnv_chip_power10_quad_realize(chip10, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
}
|
||||
|
||||
/* XIVE2 interrupt controller (POWER10) */
|
||||
object_property_set_int(OBJECT(&chip10->xive), "ic-bar",
|
||||
PNV10_XIVE2_IC_BASE(chip), &error_fatal);
|
||||
object_property_set_int(OBJECT(&chip10->xive), "esb-bar",
|
||||
PNV10_XIVE2_ESB_BASE(chip), &error_fatal);
|
||||
object_property_set_int(OBJECT(&chip10->xive), "end-bar",
|
||||
PNV10_XIVE2_END_BASE(chip), &error_fatal);
|
||||
object_property_set_int(OBJECT(&chip10->xive), "nvpg-bar",
|
||||
PNV10_XIVE2_NVPG_BASE(chip), &error_fatal);
|
||||
object_property_set_int(OBJECT(&chip10->xive), "nvc-bar",
|
||||
PNV10_XIVE2_NVC_BASE(chip), &error_fatal);
|
||||
object_property_set_int(OBJECT(&chip10->xive), "tm-bar",
|
||||
PNV10_XIVE2_TM_BASE(chip), &error_fatal);
|
||||
object_property_set_link(OBJECT(&chip10->xive), "chip", OBJECT(chip),
|
||||
&error_abort);
|
||||
if (!sysbus_realize(SYS_BUS_DEVICE(&chip10->xive), errp)) {
|
||||
return;
|
||||
}
|
||||
pnv_xscom_add_subregion(chip, PNV10_XSCOM_XIVE2_BASE,
|
||||
&chip10->xive.xscom_regs);
|
||||
|
||||
/* Processor Service Interface (PSI) Host Bridge */
|
||||
object_property_set_int(OBJECT(&chip10->psi), "bar",
|
||||
PNV10_PSIHB_BASE(chip), &error_fatal);
|
||||
/* PSI can now be configured to use 64k ESB pages on POWER10 */
|
||||
object_property_set_int(OBJECT(&chip10->psi), "shift", XIVE_ESB_64K,
|
||||
&error_fatal);
|
||||
if (!qdev_realize(DEVICE(&chip10->psi), NULL, errp)) {
|
||||
return;
|
||||
}
|
||||
@@ -1601,6 +1728,41 @@ static void pnv_chip_power10_realize(DeviceState *dev, Error **errp)
|
||||
chip->fw_mr = &chip10->lpc.isa_fw;
|
||||
chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0",
|
||||
(uint64_t) PNV10_LPCM_BASE(chip));
|
||||
|
||||
/* Create the simplified OCC model */
|
||||
object_property_set_link(OBJECT(&chip10->occ), "psi", OBJECT(&chip10->psi),
|
||||
&error_abort);
|
||||
if (!qdev_realize(DEVICE(&chip10->occ), NULL, errp)) {
|
||||
return;
|
||||
}
|
||||
pnv_xscom_add_subregion(chip, PNV10_XSCOM_OCC_BASE,
|
||||
&chip10->occ.xscom_regs);
|
||||
|
||||
/* OCC SRAM model */
|
||||
memory_region_add_subregion(get_system_memory(),
|
||||
PNV10_OCC_SENSOR_BASE(chip),
|
||||
&chip10->occ.sram_regs);
|
||||
|
||||
/* HOMER */
|
||||
object_property_set_link(OBJECT(&chip10->homer), "chip", OBJECT(chip),
|
||||
&error_abort);
|
||||
if (!qdev_realize(DEVICE(&chip10->homer), NULL, errp)) {
|
||||
return;
|
||||
}
|
||||
/* Homer Xscom region */
|
||||
pnv_xscom_add_subregion(chip, PNV10_XSCOM_PBA_BASE,
|
||||
&chip10->homer.pba_regs);
|
||||
|
||||
/* Homer mmio region */
|
||||
memory_region_add_subregion(get_system_memory(), PNV10_HOMER_BASE(chip),
|
||||
&chip10->homer.regs);
|
||||
|
||||
/* PHBs */
|
||||
pnv_chip_power10_phb_realize(chip, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t pnv_chip_power10_xscom_pcba(PnvChip *chip, uint64_t addr)
|
||||
@@ -1627,6 +1789,7 @@ static void pnv_chip_power10_class_init(ObjectClass *klass, void *data)
|
||||
k->xscom_core_base = pnv_chip_power10_xscom_core_base;
|
||||
k->xscom_pcba = pnv_chip_power10_xscom_pcba;
|
||||
dc->desc = "PowerNV Chip POWER10";
|
||||
k->num_pecs = PNV10_CHIP_MAX_PEC;
|
||||
|
||||
device_class_set_parent_realize(dc, pnv_chip_power10_realize,
|
||||
&k->parent_realize);
|
||||
@@ -1924,6 +2087,35 @@ static int pnv_match_nvt(XiveFabric *xfb, uint8_t format,
|
||||
return total_count;
|
||||
}
|
||||
|
||||
static int pnv10_xive_match_nvt(XiveFabric *xfb, uint8_t format,
|
||||
uint8_t nvt_blk, uint32_t nvt_idx,
|
||||
bool cam_ignore, uint8_t priority,
|
||||
uint32_t logic_serv,
|
||||
XiveTCTXMatch *match)
|
||||
{
|
||||
PnvMachineState *pnv = PNV_MACHINE(xfb);
|
||||
int total_count = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < pnv->num_chips; i++) {
|
||||
Pnv10Chip *chip10 = PNV10_CHIP(pnv->chips[i]);
|
||||
XivePresenter *xptr = XIVE_PRESENTER(&chip10->xive);
|
||||
XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr);
|
||||
int count;
|
||||
|
||||
count = xpc->match_nvt(xptr, format, nvt_blk, nvt_idx, cam_ignore,
|
||||
priority, logic_serv, match);
|
||||
|
||||
if (count < 0) {
|
||||
return count;
|
||||
}
|
||||
|
||||
total_count += count;
|
||||
}
|
||||
|
||||
return total_count;
|
||||
}
|
||||
|
||||
static void pnv_machine_power8_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
MachineClass *mc = MACHINE_CLASS(oc);
|
||||
@@ -1968,6 +2160,7 @@ static void pnv_machine_power10_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
MachineClass *mc = MACHINE_CLASS(oc);
|
||||
PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc);
|
||||
XiveFabricClass *xfc = XIVE_FABRIC_CLASS(oc);
|
||||
static const char compat[] = "qemu,powernv10\0ibm,powernv";
|
||||
|
||||
mc->desc = "IBM PowerNV (Non-Virtualized) POWER10";
|
||||
@@ -1976,6 +2169,8 @@ static void pnv_machine_power10_class_init(ObjectClass *oc, void *data)
|
||||
pmc->compat = compat;
|
||||
pmc->compat_size = sizeof(compat);
|
||||
pmc->dt_power_mgt = pnv_dt_power_mgt;
|
||||
|
||||
xfc->match_nvt = pnv10_xive_match_nvt;
|
||||
}
|
||||
|
||||
static bool pnv_machine_get_hb(Object *obj, Error **errp)
|
||||
@@ -2087,6 +2282,10 @@ static const TypeInfo types[] = {
|
||||
.name = MACHINE_TYPE_NAME("powernv10"),
|
||||
.parent = TYPE_PNV_MACHINE,
|
||||
.class_init = pnv_machine_power10_class_init,
|
||||
.interfaces = (InterfaceInfo[]) {
|
||||
{ TYPE_XIVE_FABRIC },
|
||||
{ },
|
||||
},
|
||||
},
|
||||
{
|
||||
.name = MACHINE_TYPE_NAME("powernv9"),
|
||||
|
||||
@@ -332,6 +332,69 @@ static const TypeInfo pnv_homer_power9_type_info = {
|
||||
.class_init = pnv_homer_power9_class_init,
|
||||
};
|
||||
|
||||
static uint64_t pnv_homer_power10_pba_read(void *opaque, hwaddr addr,
|
||||
unsigned size)
|
||||
{
|
||||
PnvHomer *homer = PNV_HOMER(opaque);
|
||||
PnvChip *chip = homer->chip;
|
||||
uint32_t reg = addr >> 3;
|
||||
uint64_t val = 0;
|
||||
|
||||
switch (reg) {
|
||||
case PBA_BAR0:
|
||||
val = PNV10_HOMER_BASE(chip);
|
||||
break;
|
||||
case PBA_BARMASK0: /* P10 homer region mask */
|
||||
val = (PNV10_HOMER_SIZE - 1) & 0x300000;
|
||||
break;
|
||||
case PBA_BAR2: /* P10 occ common area */
|
||||
val = PNV10_OCC_COMMON_AREA_BASE;
|
||||
break;
|
||||
case PBA_BARMASK2: /* P10 occ common area size */
|
||||
val = (PNV10_OCC_COMMON_AREA_SIZE - 1) & 0x700000;
|
||||
break;
|
||||
default:
|
||||
qemu_log_mask(LOG_UNIMP, "PBA: read to unimplemented register: Ox%"
|
||||
HWADDR_PRIx "\n", addr >> 3);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
static void pnv_homer_power10_pba_write(void *opaque, hwaddr addr,
|
||||
uint64_t val, unsigned size)
|
||||
{
|
||||
qemu_log_mask(LOG_UNIMP, "PBA: write to unimplemented register: Ox%"
|
||||
HWADDR_PRIx "\n", addr >> 3);
|
||||
}
|
||||
|
||||
static const MemoryRegionOps pnv_homer_power10_pba_ops = {
|
||||
.read = pnv_homer_power10_pba_read,
|
||||
.write = pnv_homer_power10_pba_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_homer_power10_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
PnvHomerClass *homer = PNV_HOMER_CLASS(klass);
|
||||
|
||||
homer->pba_size = PNV10_XSCOM_PBA_SIZE;
|
||||
homer->pba_ops = &pnv_homer_power10_pba_ops;
|
||||
homer->homer_size = PNV10_HOMER_SIZE;
|
||||
homer->homer_ops = &pnv_power9_homer_ops; /* TODO */
|
||||
homer->core_max_base = PNV9_CORE_MAX_BASE;
|
||||
}
|
||||
|
||||
static const TypeInfo pnv_homer_power10_type_info = {
|
||||
.name = TYPE_PNV10_HOMER,
|
||||
.parent = TYPE_PNV_HOMER,
|
||||
.instance_size = sizeof(PnvHomer),
|
||||
.class_init = pnv_homer_power10_class_init,
|
||||
};
|
||||
|
||||
static void pnv_homer_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
PnvHomer *homer = PNV_HOMER(dev);
|
||||
@@ -377,6 +440,7 @@ static void pnv_homer_register_types(void)
|
||||
type_register_static(&pnv_homer_type_info);
|
||||
type_register_static(&pnv_homer_power8_type_info);
|
||||
type_register_static(&pnv_homer_power9_type_info);
|
||||
type_register_static(&pnv_homer_power10_type_info);
|
||||
}
|
||||
|
||||
type_init(pnv_homer_register_types);
|
||||
|
||||
@@ -236,7 +236,9 @@ static const MemoryRegionOps pnv_occ_power9_xscom_ops = {
|
||||
static void pnv_occ_power9_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
PnvOCCClass *poc = PNV_OCC_CLASS(klass);
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
|
||||
dc->desc = "PowerNV OCC Controller (POWER9)";
|
||||
poc->xscom_size = PNV9_XSCOM_OCC_SIZE;
|
||||
poc->xscom_ops = &pnv_occ_power9_xscom_ops;
|
||||
poc->psi_irq = PSIHB9_IRQ_OCC;
|
||||
@@ -249,6 +251,19 @@ static const TypeInfo pnv_occ_power9_type_info = {
|
||||
.class_init = pnv_occ_power9_class_init,
|
||||
};
|
||||
|
||||
static void pnv_occ_power10_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
|
||||
dc->desc = "PowerNV OCC Controller (POWER10)";
|
||||
}
|
||||
|
||||
static const TypeInfo pnv_occ_power10_type_info = {
|
||||
.name = TYPE_PNV10_OCC,
|
||||
.parent = TYPE_PNV9_OCC,
|
||||
.class_init = pnv_occ_power10_class_init,
|
||||
};
|
||||
|
||||
static void pnv_occ_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
PnvOCC *occ = PNV_OCC(dev);
|
||||
@@ -297,6 +312,7 @@ static void pnv_occ_register_types(void)
|
||||
type_register_static(&pnv_occ_type_info);
|
||||
type_register_static(&pnv_occ_power8_type_info);
|
||||
type_register_static(&pnv_occ_power9_type_info);
|
||||
type_register_static(&pnv_occ_power10_type_info);
|
||||
}
|
||||
|
||||
type_init(pnv_occ_register_types);
|
||||
|
||||
+30
-8
@@ -601,7 +601,6 @@ static const TypeInfo pnv_psi_power8_info = {
|
||||
#define PSIHB9_IRQ_METHOD PPC_BIT(0)
|
||||
#define PSIHB9_IRQ_RESET PPC_BIT(1)
|
||||
#define PSIHB9_ESB_CI_BASE 0x60
|
||||
#define PSIHB9_ESB_CI_64K PPC_BIT(1)
|
||||
#define PSIHB9_ESB_CI_ADDR_MASK PPC_BITMASK(8, 47)
|
||||
#define PSIHB9_ESB_CI_VALID PPC_BIT(63)
|
||||
#define PSIHB9_ESB_NOTIF_ADDR 0x68
|
||||
@@ -646,7 +645,15 @@ static const TypeInfo pnv_psi_power8_info = {
|
||||
#define PSIHB9_IRQ_STAT_DIO PPC_BIT(12)
|
||||
#define PSIHB9_IRQ_STAT_PSU PPC_BIT(13)
|
||||
|
||||
static void pnv_psi_notify(XiveNotifier *xf, uint32_t srcno)
|
||||
/* P10 register extensions */
|
||||
|
||||
#define PSIHB10_CR PSIHB9_CR
|
||||
#define PSIHB10_CR_STORE_EOI PPC_BIT(12)
|
||||
|
||||
#define PSIHB10_ESB_CI_BASE PSIHB9_ESB_CI_BASE
|
||||
#define PSIHB10_ESB_CI_64K PPC_BIT(1)
|
||||
|
||||
static void pnv_psi_notify(XiveNotifier *xf, uint32_t srcno, bool pq_checked)
|
||||
{
|
||||
PnvPsi *psi = PNV_PSI(xf);
|
||||
uint64_t notif_port = psi->regs[PSIHB_REG(PSIHB9_ESB_NOTIF_ADDR)];
|
||||
@@ -655,9 +662,13 @@ static void pnv_psi_notify(XiveNotifier *xf, uint32_t srcno)
|
||||
|
||||
uint32_t offset =
|
||||
(psi->regs[PSIHB_REG(PSIHB9_IVT_OFFSET)] >> PSIHB9_IVT_OFF_SHIFT);
|
||||
uint64_t data = XIVE_TRIGGER_PQ | offset | srcno;
|
||||
uint64_t data = offset | srcno;
|
||||
MemTxResult result;
|
||||
|
||||
if (pq_checked) {
|
||||
data |= XIVE_TRIGGER_PQ;
|
||||
}
|
||||
|
||||
if (!valid) {
|
||||
return;
|
||||
}
|
||||
@@ -704,6 +715,13 @@ static void pnv_psi_p9_mmio_write(void *opaque, hwaddr addr,
|
||||
|
||||
switch (addr) {
|
||||
case PSIHB9_CR:
|
||||
if (val & PSIHB10_CR_STORE_EOI) {
|
||||
psi9->source.esb_flags |= XIVE_SRC_STORE_EOI;
|
||||
} else {
|
||||
psi9->source.esb_flags &= ~XIVE_SRC_STORE_EOI;
|
||||
}
|
||||
break;
|
||||
|
||||
case PSIHB9_SEMR:
|
||||
/* FSP stuff */
|
||||
break;
|
||||
@@ -715,15 +733,20 @@ static void pnv_psi_p9_mmio_write(void *opaque, hwaddr addr,
|
||||
break;
|
||||
|
||||
case PSIHB9_ESB_CI_BASE:
|
||||
if (val & PSIHB10_ESB_CI_64K) {
|
||||
psi9->source.esb_shift = XIVE_ESB_64K;
|
||||
} else {
|
||||
psi9->source.esb_shift = XIVE_ESB_4K;
|
||||
}
|
||||
if (!(val & PSIHB9_ESB_CI_VALID)) {
|
||||
if (psi->regs[reg] & PSIHB9_ESB_CI_VALID) {
|
||||
memory_region_del_subregion(sysmem, &psi9->source.esb_mmio);
|
||||
}
|
||||
} else {
|
||||
if (!(psi->regs[reg] & PSIHB9_ESB_CI_VALID)) {
|
||||
memory_region_add_subregion(sysmem,
|
||||
val & ~PSIHB9_ESB_CI_VALID,
|
||||
&psi9->source.esb_mmio);
|
||||
hwaddr addr = val & ~(PSIHB9_ESB_CI_VALID | PSIHB10_ESB_CI_64K);
|
||||
memory_region_add_subregion(sysmem, addr,
|
||||
&psi9->source.esb_mmio);
|
||||
}
|
||||
}
|
||||
psi->regs[reg] = val;
|
||||
@@ -831,6 +854,7 @@ static void pnv_psi_power9_instance_init(Object *obj)
|
||||
Pnv9Psi *psi = PNV9_PSI(obj);
|
||||
|
||||
object_initialize_child(obj, "source", &psi->source, TYPE_XIVE_SOURCE);
|
||||
object_property_add_alias(obj, "shift", OBJECT(&psi->source), "shift");
|
||||
}
|
||||
|
||||
static void pnv_psi_power9_realize(DeviceState *dev, Error **errp)
|
||||
@@ -839,8 +863,6 @@ static void pnv_psi_power9_realize(DeviceState *dev, Error **errp)
|
||||
XiveSource *xsrc = &PNV9_PSI(psi)->source;
|
||||
int i;
|
||||
|
||||
/* This is the only device with 4k ESB pages */
|
||||
object_property_set_int(OBJECT(xsrc), "shift", XIVE_ESB_4K, &error_fatal);
|
||||
object_property_set_int(OBJECT(xsrc), "nr-irqs", PSIHB9_NUM_IRQS,
|
||||
&error_fatal);
|
||||
object_property_set_link(OBJECT(xsrc), "xive", OBJECT(psi), &error_abort);
|
||||
|
||||
+13
-18
@@ -1018,9 +1018,9 @@ static void spapr_dt_chosen(SpaprMachineState *spapr, void *fdt, bool reset)
|
||||
|
||||
if (reset) {
|
||||
const char *boot_device = spapr->boot_device;
|
||||
char *stdout_path = spapr_vio_stdout_path(spapr->vio_bus);
|
||||
g_autofree char *stdout_path = spapr_vio_stdout_path(spapr->vio_bus);
|
||||
size_t cb = 0;
|
||||
char *bootlist = get_boot_devices_list(&cb);
|
||||
g_autofree char *bootlist = get_boot_devices_list(&cb);
|
||||
|
||||
if (machine->kernel_cmdline && machine->kernel_cmdline[0]) {
|
||||
_FDT(fdt_setprop_string(fdt, chosen, "bootargs",
|
||||
@@ -1087,9 +1087,6 @@ static void spapr_dt_chosen(SpaprMachineState *spapr, void *fdt, bool reset)
|
||||
}
|
||||
|
||||
spapr_dt_ov5_platform_support(spapr, fdt, chosen);
|
||||
|
||||
g_free(stdout_path);
|
||||
g_free(bootlist);
|
||||
}
|
||||
|
||||
_FDT(spapr_dt_ovec(fdt, chosen, spapr->ov5_cas, "ibm,architecture-vec-5"));
|
||||
@@ -2710,15 +2707,25 @@ static void spapr_machine_init(MachineState *machine)
|
||||
MachineClass *mc = MACHINE_GET_CLASS(machine);
|
||||
const char *bios_default = spapr->vof ? FW_FILE_NAME_VOF : FW_FILE_NAME;
|
||||
const char *bios_name = machine->firmware ?: bios_default;
|
||||
g_autofree char *filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
|
||||
const char *kernel_filename = machine->kernel_filename;
|
||||
const char *initrd_filename = machine->initrd_filename;
|
||||
PCIHostState *phb;
|
||||
int i;
|
||||
MemoryRegion *sysmem = get_system_memory();
|
||||
long load_limit, fw_size;
|
||||
char *filename;
|
||||
Error *resize_hpt_err = NULL;
|
||||
|
||||
if (!filename) {
|
||||
error_report("Could not find LPAR firmware '%s'", bios_name);
|
||||
exit(1);
|
||||
}
|
||||
fw_size = load_image_targphys(filename, 0, FW_MAX_SIZE);
|
||||
if (fw_size <= 0) {
|
||||
error_report("Could not load LPAR firmware '%s'", filename);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* if Secure VM (PEF) support is configured, then initialize it
|
||||
*/
|
||||
@@ -2999,18 +3006,6 @@ static void spapr_machine_init(MachineState *machine)
|
||||
}
|
||||
}
|
||||
|
||||
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
|
||||
if (!filename) {
|
||||
error_report("Could not find LPAR firmware '%s'", bios_name);
|
||||
exit(1);
|
||||
}
|
||||
fw_size = load_image_targphys(filename, 0, FW_MAX_SIZE);
|
||||
if (fw_size <= 0) {
|
||||
error_report("Could not load LPAR firmware '%s'", filename);
|
||||
exit(1);
|
||||
}
|
||||
g_free(filename);
|
||||
|
||||
/* FIXME: Should register things through the MachineState's qdev
|
||||
* interface, this is a legacy from the sPAPREnvironment structure
|
||||
* which predated MachineState but had a similar function */
|
||||
|
||||
+8
-14
@@ -95,12 +95,12 @@ static void spapr_cap_set_bool(Object *obj, Visitor *v, const char *name,
|
||||
}
|
||||
|
||||
|
||||
static void spapr_cap_get_string(Object *obj, Visitor *v, const char *name,
|
||||
void *opaque, Error **errp)
|
||||
static void spapr_cap_get_string(Object *obj, Visitor *v, const char *name,
|
||||
void *opaque, Error **errp)
|
||||
{
|
||||
SpaprCapabilityInfo *cap = opaque;
|
||||
SpaprMachineState *spapr = SPAPR_MACHINE(obj);
|
||||
char *val = NULL;
|
||||
g_autofree char *val = NULL;
|
||||
uint8_t value = spapr_get_cap(spapr, cap->index);
|
||||
|
||||
if (value >= cap->possible->num) {
|
||||
@@ -111,7 +111,6 @@ static void spapr_cap_get_string(Object *obj, Visitor *v, const char *name,
|
||||
val = g_strdup(cap->possible->vals[value]);
|
||||
|
||||
visit_type_str(v, name, &val, errp);
|
||||
g_free(val);
|
||||
}
|
||||
|
||||
static void spapr_cap_set_string(Object *obj, Visitor *v, const char *name,
|
||||
@@ -120,7 +119,7 @@ static void spapr_cap_set_string(Object *obj, Visitor *v, const char *name,
|
||||
SpaprCapabilityInfo *cap = opaque;
|
||||
SpaprMachineState *spapr = SPAPR_MACHINE(obj);
|
||||
uint8_t i;
|
||||
char *val;
|
||||
g_autofree char *val = NULL;
|
||||
|
||||
if (!visit_type_str(v, name, &val, errp)) {
|
||||
return;
|
||||
@@ -128,20 +127,18 @@ static void spapr_cap_set_string(Object *obj, Visitor *v, const char *name,
|
||||
|
||||
if (!strcmp(val, "?")) {
|
||||
error_setg(errp, "%s", cap->possible->help);
|
||||
goto out;
|
||||
return;
|
||||
}
|
||||
for (i = 0; i < cap->possible->num; i++) {
|
||||
if (!strcasecmp(val, cap->possible->vals[i])) {
|
||||
spapr->cmd_line_caps[cap->index] = true;
|
||||
spapr->eff.caps[cap->index] = i;
|
||||
goto out;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
error_setg(errp, "Invalid capability mode \"%s\" for cap-%s", val,
|
||||
cap->name);
|
||||
out:
|
||||
g_free(val);
|
||||
}
|
||||
|
||||
static void spapr_cap_get_pagesize(Object *obj, Visitor *v, const char *name,
|
||||
@@ -933,16 +930,13 @@ void spapr_caps_add_properties(SpaprMachineClass *smc)
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(capability_table); i++) {
|
||||
SpaprCapabilityInfo *cap = &capability_table[i];
|
||||
char *name = g_strdup_printf("cap-%s", cap->name);
|
||||
char *desc;
|
||||
g_autofree char *name = g_strdup_printf("cap-%s", cap->name);
|
||||
g_autofree char *desc = g_strdup_printf("%s", cap->description);
|
||||
|
||||
object_class_property_add(klass, name, cap->type,
|
||||
cap->get, cap->set,
|
||||
NULL, cap);
|
||||
|
||||
desc = g_strdup_printf("%s", cap->description);
|
||||
object_class_property_set_description(klass, name, desc);
|
||||
g_free(name);
|
||||
g_free(desc);
|
||||
}
|
||||
}
|
||||
|
||||
+17
-30
@@ -519,8 +519,8 @@ static const VMStateDescription vmstate_spapr_drc = {
|
||||
static void drc_realize(DeviceState *d, Error **errp)
|
||||
{
|
||||
SpaprDrc *drc = SPAPR_DR_CONNECTOR(d);
|
||||
g_autofree gchar *link_name = g_strdup_printf("%x", spapr_drc_index(drc));
|
||||
Object *root_container;
|
||||
gchar *link_name;
|
||||
const char *child_name;
|
||||
|
||||
trace_spapr_drc_realize(spapr_drc_index(drc));
|
||||
@@ -532,12 +532,10 @@ static void drc_realize(DeviceState *d, Error **errp)
|
||||
* existing in the composition tree
|
||||
*/
|
||||
root_container = container_get(object_get_root(), DRC_CONTAINER_PATH);
|
||||
link_name = g_strdup_printf("%x", spapr_drc_index(drc));
|
||||
child_name = object_get_canonical_path_component(OBJECT(drc));
|
||||
trace_spapr_drc_realize_child(spapr_drc_index(drc), child_name);
|
||||
object_property_add_alias(root_container, link_name,
|
||||
drc->owner, child_name);
|
||||
g_free(link_name);
|
||||
vmstate_register(VMSTATE_IF(drc), spapr_drc_index(drc), &vmstate_spapr_drc,
|
||||
drc);
|
||||
trace_spapr_drc_realize_complete(spapr_drc_index(drc));
|
||||
@@ -546,22 +544,20 @@ static void drc_realize(DeviceState *d, Error **errp)
|
||||
static void drc_unrealize(DeviceState *d)
|
||||
{
|
||||
SpaprDrc *drc = SPAPR_DR_CONNECTOR(d);
|
||||
g_autofree gchar *name = g_strdup_printf("%x", spapr_drc_index(drc));
|
||||
Object *root_container;
|
||||
gchar *name;
|
||||
|
||||
trace_spapr_drc_unrealize(spapr_drc_index(drc));
|
||||
vmstate_unregister(VMSTATE_IF(drc), &vmstate_spapr_drc, drc);
|
||||
root_container = container_get(object_get_root(), DRC_CONTAINER_PATH);
|
||||
name = g_strdup_printf("%x", spapr_drc_index(drc));
|
||||
object_property_del(root_container, name);
|
||||
g_free(name);
|
||||
}
|
||||
|
||||
SpaprDrc *spapr_dr_connector_new(Object *owner, const char *type,
|
||||
uint32_t id)
|
||||
{
|
||||
SpaprDrc *drc = SPAPR_DR_CONNECTOR(object_new(type));
|
||||
char *prop_name;
|
||||
g_autofree char *prop_name = NULL;
|
||||
|
||||
drc->id = id;
|
||||
drc->owner = owner;
|
||||
@@ -570,7 +566,6 @@ SpaprDrc *spapr_dr_connector_new(Object *owner, const char *type,
|
||||
object_property_add_child(owner, prop_name, OBJECT(drc));
|
||||
object_unref(OBJECT(drc));
|
||||
qdev_realize(DEVICE(drc), NULL, NULL);
|
||||
g_free(prop_name);
|
||||
|
||||
return drc;
|
||||
}
|
||||
@@ -803,11 +798,9 @@ static const TypeInfo spapr_drc_pmem_info = {
|
||||
SpaprDrc *spapr_drc_by_index(uint32_t index)
|
||||
{
|
||||
Object *obj;
|
||||
gchar *name;
|
||||
|
||||
name = g_strdup_printf("%s/%x", DRC_CONTAINER_PATH, index);
|
||||
g_autofree gchar *name = g_strdup_printf("%s/%x", DRC_CONTAINER_PATH,
|
||||
index);
|
||||
obj = object_resolve_path(name, NULL);
|
||||
g_free(name);
|
||||
|
||||
return !obj ? NULL : SPAPR_DR_CONNECTOR(obj);
|
||||
}
|
||||
@@ -841,8 +834,14 @@ int spapr_dt_drc(void *fdt, int offset, Object *owner, uint32_t drc_type_mask)
|
||||
ObjectProperty *prop;
|
||||
ObjectPropertyIterator iter;
|
||||
uint32_t drc_count = 0;
|
||||
GArray *drc_indexes, *drc_power_domains;
|
||||
GString *drc_names, *drc_types;
|
||||
g_autoptr(GArray) drc_indexes = g_array_new(false, true,
|
||||
sizeof(uint32_t));
|
||||
g_autoptr(GArray) drc_power_domains = g_array_new(false, true,
|
||||
sizeof(uint32_t));
|
||||
g_autoptr(GString) drc_names = g_string_set_size(g_string_new(NULL),
|
||||
sizeof(uint32_t));
|
||||
g_autoptr(GString) drc_types = g_string_set_size(g_string_new(NULL),
|
||||
sizeof(uint32_t));
|
||||
int ret;
|
||||
|
||||
/*
|
||||
@@ -857,12 +856,8 @@ int spapr_dt_drc(void *fdt, int offset, Object *owner, uint32_t drc_type_mask)
|
||||
* reserve the space now and set the offsets accordingly so we
|
||||
* can fill them in later.
|
||||
*/
|
||||
drc_indexes = g_array_new(false, true, sizeof(uint32_t));
|
||||
drc_indexes = g_array_set_size(drc_indexes, 1);
|
||||
drc_power_domains = g_array_new(false, true, sizeof(uint32_t));
|
||||
drc_power_domains = g_array_set_size(drc_power_domains, 1);
|
||||
drc_names = g_string_set_size(g_string_new(NULL), sizeof(uint32_t));
|
||||
drc_types = g_string_set_size(g_string_new(NULL), sizeof(uint32_t));
|
||||
|
||||
/* aliases for all DRConnector objects will be rooted in QOM
|
||||
* composition tree at DRC_CONTAINER_PATH
|
||||
@@ -874,7 +869,7 @@ int spapr_dt_drc(void *fdt, int offset, Object *owner, uint32_t drc_type_mask)
|
||||
Object *obj;
|
||||
SpaprDrc *drc;
|
||||
SpaprDrcClass *drck;
|
||||
char *drc_name = NULL;
|
||||
g_autofree char *drc_name = NULL;
|
||||
uint32_t drc_index, drc_power_domain;
|
||||
|
||||
if (!strstart(prop->type, "link<", NULL)) {
|
||||
@@ -908,7 +903,6 @@ int spapr_dt_drc(void *fdt, int offset, Object *owner, uint32_t drc_type_mask)
|
||||
drc_name = spapr_drc_name(drc);
|
||||
drc_names = g_string_append(drc_names, drc_name);
|
||||
drc_names = g_string_insert_len(drc_names, -1, "\0", 1);
|
||||
g_free(drc_name);
|
||||
|
||||
/* ibm,drc-types */
|
||||
drc_types = g_string_append(drc_types, drck->typename);
|
||||
@@ -928,7 +922,7 @@ int spapr_dt_drc(void *fdt, int offset, Object *owner, uint32_t drc_type_mask)
|
||||
drc_indexes->len * sizeof(uint32_t));
|
||||
if (ret) {
|
||||
error_report("Couldn't create ibm,drc-indexes property");
|
||||
goto out;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = fdt_setprop(fdt, offset, "ibm,drc-power-domains",
|
||||
@@ -936,29 +930,22 @@ int spapr_dt_drc(void *fdt, int offset, Object *owner, uint32_t drc_type_mask)
|
||||
drc_power_domains->len * sizeof(uint32_t));
|
||||
if (ret) {
|
||||
error_report("Couldn't finalize ibm,drc-power-domains property");
|
||||
goto out;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = fdt_setprop(fdt, offset, "ibm,drc-names",
|
||||
drc_names->str, drc_names->len);
|
||||
if (ret) {
|
||||
error_report("Couldn't finalize ibm,drc-names property");
|
||||
goto out;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = fdt_setprop(fdt, offset, "ibm,drc-types",
|
||||
drc_types->str, drc_types->len);
|
||||
if (ret) {
|
||||
error_report("Couldn't finalize ibm,drc-types property");
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
g_array_free(drc_indexes, true);
|
||||
g_array_free(drc_power_domains, true);
|
||||
g_string_free(drc_names, true);
|
||||
g_string_free(drc_types, true);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
+8
-8
@@ -431,12 +431,14 @@ int spapr_numa_write_assoc_lookup_arrays(SpaprMachineState *spapr, void *fdt,
|
||||
int max_distance_ref_points = get_max_dist_ref_points(spapr);
|
||||
int nb_numa_nodes = machine->numa_state->num_nodes;
|
||||
int nr_nodes = nb_numa_nodes ? nb_numa_nodes : 1;
|
||||
uint32_t *int_buf, *cur_index, buf_len;
|
||||
int ret, i;
|
||||
g_autofree uint32_t *int_buf = NULL;
|
||||
uint32_t *cur_index;
|
||||
int i;
|
||||
|
||||
/* ibm,associativity-lookup-arrays */
|
||||
buf_len = (nr_nodes * max_distance_ref_points + 2) * sizeof(uint32_t);
|
||||
cur_index = int_buf = g_malloc0(buf_len);
|
||||
int_buf = g_malloc0((nr_nodes * max_distance_ref_points + 2) *
|
||||
sizeof(uint32_t));
|
||||
cur_index = int_buf;
|
||||
int_buf[0] = cpu_to_be32(nr_nodes);
|
||||
/* Number of entries per associativity list */
|
||||
int_buf[1] = cpu_to_be32(max_distance_ref_points);
|
||||
@@ -451,11 +453,9 @@ int spapr_numa_write_assoc_lookup_arrays(SpaprMachineState *spapr, void *fdt,
|
||||
sizeof(uint32_t) * max_distance_ref_points);
|
||||
cur_index += max_distance_ref_points;
|
||||
}
|
||||
ret = fdt_setprop(fdt, offset, "ibm,associativity-lookup-arrays", int_buf,
|
||||
(cur_index - int_buf) * sizeof(uint32_t));
|
||||
g_free(int_buf);
|
||||
|
||||
return ret;
|
||||
return fdt_setprop(fdt, offset, "ibm,associativity-lookup-arrays",
|
||||
int_buf, (cur_index - int_buf) * sizeof(uint32_t));
|
||||
}
|
||||
|
||||
static void spapr_numa_FORM1_write_rtas_dt(SpaprMachineState *spapr,
|
||||
|
||||
@@ -320,7 +320,7 @@ void spapr_phb_nvgpu_populate_dt(SpaprPhbState *sphb, void *fdt, int bus_off,
|
||||
void spapr_phb_nvgpu_ram_populate_dt(SpaprPhbState *sphb, void *fdt)
|
||||
{
|
||||
int i, j, linkidx, npuoff;
|
||||
char *npuname;
|
||||
g_autofree char *npuname = NULL;
|
||||
|
||||
if (!sphb->nvgpus) {
|
||||
return;
|
||||
@@ -333,11 +333,10 @@ void spapr_phb_nvgpu_ram_populate_dt(SpaprPhbState *sphb, void *fdt)
|
||||
_FDT(fdt_setprop_cell(fdt, npuoff, "#size-cells", 0));
|
||||
/* Advertise NPU as POWER9 so the guest can enable NPU2 contexts */
|
||||
_FDT((fdt_setprop_string(fdt, npuoff, "compatible", "ibm,power9-npu")));
|
||||
g_free(npuname);
|
||||
|
||||
for (i = 0, linkidx = 0; i < sphb->nvgpus->num; ++i) {
|
||||
for (j = 0; j < sphb->nvgpus->slots[i].linknum; ++j) {
|
||||
char *linkname = g_strdup_printf("link@%d", linkidx);
|
||||
g_autofree char *linkname = g_strdup_printf("link@%d", linkidx);
|
||||
int off = fdt_add_subnode(fdt, npuoff, linkname);
|
||||
|
||||
_FDT(off);
|
||||
@@ -347,7 +346,6 @@ void spapr_phb_nvgpu_ram_populate_dt(SpaprPhbState *sphb, void *fdt)
|
||||
_FDT((fdt_setprop_cell(fdt, off, "phandle",
|
||||
PHANDLE_NVLINK(sphb, i, j))));
|
||||
_FDT((fdt_setprop_cell(fdt, off, "ibm,npu-link-index", linkidx)));
|
||||
g_free(linkname);
|
||||
++linkidx;
|
||||
}
|
||||
}
|
||||
@@ -360,7 +358,8 @@ void spapr_phb_nvgpu_ram_populate_dt(SpaprPhbState *sphb, void *fdt)
|
||||
&error_abort);
|
||||
uint64_t size = object_property_get_uint(nv_mrobj, "size", NULL);
|
||||
uint64_t mem_reg[2] = { cpu_to_be64(nvslot->gpa), cpu_to_be64(size) };
|
||||
char *mem_name = g_strdup_printf("memory@%"PRIx64, nvslot->gpa);
|
||||
g_autofree char *mem_name = g_strdup_printf("memory@%"PRIx64,
|
||||
nvslot->gpa);
|
||||
int off = fdt_add_subnode(fdt, 0, mem_name);
|
||||
|
||||
_FDT(off);
|
||||
@@ -378,7 +377,6 @@ void spapr_phb_nvgpu_ram_populate_dt(SpaprPhbState *sphb, void *fdt)
|
||||
sizeof(mem_reg))));
|
||||
_FDT((fdt_setprop_cell(fdt, off, "phandle",
|
||||
PHANDLE_GPURAM(sphb, i))));
|
||||
g_free(mem_name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+12
-13
@@ -279,30 +279,29 @@ static void rtas_ibm_get_system_parameter(PowerPCCPU *cpu,
|
||||
|
||||
switch (parameter) {
|
||||
case RTAS_SYSPARM_SPLPAR_CHARACTERISTICS: {
|
||||
char *param_val = g_strdup_printf("MaxEntCap=%d,"
|
||||
"DesMem=%" PRIu64 ","
|
||||
"DesProcs=%d,"
|
||||
"MaxPlatProcs=%d",
|
||||
ms->smp.max_cpus,
|
||||
ms->ram_size / MiB,
|
||||
ms->smp.cpus,
|
||||
ms->smp.max_cpus);
|
||||
g_autofree char *param_val = g_strdup_printf("MaxEntCap=%d,"
|
||||
"DesMem=%" PRIu64 ","
|
||||
"DesProcs=%d,"
|
||||
"MaxPlatProcs=%d",
|
||||
ms->smp.max_cpus,
|
||||
ms->ram_size / MiB,
|
||||
ms->smp.cpus,
|
||||
ms->smp.max_cpus);
|
||||
if (pcc->n_host_threads > 0) {
|
||||
char *hostthr_val, *old = param_val;
|
||||
|
||||
/*
|
||||
* Add HostThrs property. This property is not present in PAPR but
|
||||
* is expected by some guests to communicate the number of physical
|
||||
* host threads per core on the system so that they can scale
|
||||
* information which varies based on the thread configuration.
|
||||
*/
|
||||
hostthr_val = g_strdup_printf(",HostThrs=%d", pcc->n_host_threads);
|
||||
g_autofree char *hostthr_val = g_strdup_printf(",HostThrs=%d",
|
||||
pcc->n_host_threads);
|
||||
char *old = param_val;
|
||||
|
||||
param_val = g_strconcat(param_val, hostthr_val, NULL);
|
||||
g_free(hostthr_val);
|
||||
g_free(old);
|
||||
}
|
||||
ret = sysparm_st(buffer, length, param_val, strlen(param_val) + 1);
|
||||
g_free(param_val);
|
||||
break;
|
||||
}
|
||||
case RTAS_SYSPARM_DIAGNOSTICS_RUN_MODE: {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user