Merge tag 'pull-ppc-for-9.1-2-20240726-1' of https://gitlab.com/npiggin/qemu into staging

fixes

# -----BEGIN PGP SIGNATURE-----
#
# iQIzBAABCgAdFiEETkN92lZhb0MpsKeVZ7MCdqhiHK4FAmai5TsACgkQZ7MCdqhi
# HK4rgA//eh0ax3JnBGma1rVEDL5n5cdEYV+ATFYGc529CUZFUar3IMqSw3in8bJy
# uvQ6Cr/7IuusNEtoiYtdN1yNasqsm3fZB/hZ/Ekz32TsbpBRdkJW3ucavAu2rGM/
# EKRo7Y8gciy/Mj9y2JlIZqsDqYe+gribfGQvIg27DX+caAW/lKQdAdt4oJMTSdmr
# XR8JjtMdhUazKrI+bc/4EG6tIQyUdp+S1/z1q6Wthqt58dNRElTjkD9op4AsUWMu
# CE4a8ALCZoj3P3m+xf7xi7fT2JC2xgmNRCi3KbbhVEHdbFB6ViNYNuEYRS6GmpdC
# C6J/ZR6QXs6KB1KO7EyB+vsuxLX4Eb8aeCFxwMlzJ9Fo4g8JudABXOFzYTKX1xBn
# DUIGX91YACV43M2MvP/KuEU4zWpREO+U8MbQs/6s6fYsnCO2eKVJt/0Aaf1hmk37
# gY5Ak2DRx5TBvxlFy87zgHxHWTh/dGZodpN3IvCIDzVLnHGFlfluJbFRaoZSOecb
# 1vxDHORjIruLcAxNVEGkJ/6MxOrnjjoUzSPUQcbgJ5BpFZOdeGLiMAULu/HBLBd9
# 7dvVw+PeNEPJttYumljOD6nYc/jENhLQsvkc3++bwGNc/rpi4YngtB4jhT1HV2Cl
# oLool2ooKZgV4qx6IzeYo9feElvWVNK5XPzqDpSDlt9MaI+yTYM=
# =FxPm
# -----END PGP SIGNATURE-----
# gpg: Signature made Fri 26 Jul 2024 09:52:27 AM AEST
# gpg:                using RSA key 4E437DDA56616F4329B0A79567B30276A8621CAE
# gpg: Good signature from "Nicholas Piggin <npiggin@gmail.com>" [unknown]
# 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: 4E43 7DDA 5661 6F43 29B0  A795 67B3 0276 A862 1CAE

* tag 'pull-ppc-for-9.1-2-20240726-1' of https://gitlab.com/npiggin/qemu: (96 commits)
  target/ppc: Remove includes from mmu-book3s-v3.h
  target/ppc/mmu-radix64: Remove externally unused parts from header
  target/ppc: Unexport some functions from mmu-book3s-v3.h
  target/ppc/mmu-hash32.c: Move get_pteg_offset32() to the header
  target/ppc/mmu-hash32.c: Inline and remove ppc_hash32_pte_raddr()
  target/ppc/mmu_common.c: Remove mmu_ctx_t
  target/ppc/mmu_common.c: Stop using ctx in get_bat_6xx_tlb()
  target/ppc: Remove bat_size_prot()
  target/ppc/mmu_common.c: Use defines instead of numeric constants
  target/ppc/mmu_common.c: Rename function parameter
  target/ppc/mmu_common.c: Stop using ctx in ppc6xx_tlb_check()
  target/ppc/mmu_common.c: Remove key field from mmu_ctx_t
  target/ppc/mmu_common.c: Init variable in function that relies on it
  target/ppc/mmu-hash32.c: Inline and remove ppc_hash32_pte_prot()
  target/ppc: Add function to get protection key for hash32 MMU
  target/ppc/mmu_common.c: Remove ptem field from mmu_ctx_t
  target/ppc/mmu_common.c: Inline and remove ppc6xx_tlb_pte_check()
  target/ppc/mmu_common.c: Simplify a switch statement
  target/ppc/mmu_common.c: Remove single use local variable
  target/ppc/mmu_common.c: Convert local variable to bool
  ...

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson
2024-07-26 15:10:45 +10:00
69 changed files with 4429 additions and 1414 deletions
+12
View File
@@ -398,6 +398,18 @@ int kvm_create_vcpu(CPUState *cpu)
return 0;
}
int kvm_create_and_park_vcpu(CPUState *cpu)
{
int ret = 0;
ret = kvm_create_vcpu(cpu);
if (!ret) {
kvm_park_vcpu(cpu);
}
return ret;
}
static int do_kvm_destroy_vcpu(CPUState *cpu)
{
KVMState *s = kvm_state;
+4 -3
View File
@@ -57,14 +57,12 @@ void cpu_list_unlock(void)
qemu_mutex_unlock(&qemu_cpu_list_lock);
}
static bool cpu_index_auto_assigned;
static int cpu_get_free_index(void)
int cpu_get_free_index(void)
{
CPUState *some_cpu;
int max_cpu_index = 0;
cpu_index_auto_assigned = true;
CPU_FOREACH(some_cpu) {
if (some_cpu->cpu_index >= max_cpu_index) {
max_cpu_index = some_cpu->cpu_index + 1;
@@ -83,8 +81,11 @@ unsigned int cpu_list_generation_id_get(void)
void cpu_list_add(CPUState *cpu)
{
static bool cpu_index_auto_assigned;
QEMU_LOCK_GUARD(&qemu_cpu_list_lock);
if (cpu->cpu_index == UNASSIGNED_CPU_INDEX) {
cpu_index_auto_assigned = true;
cpu->cpu_index = cpu_get_free_index();
assert(cpu->cpu_index != UNASSIGNED_CPU_INDEX);
} else {
+3
View File
@@ -357,6 +357,9 @@ static const FlashPartInfo known_devices[] = {
.sfdp_read = m25p80_sfdp_w25q512jv },
{ INFO("w25q01jvq", 0xef4021, 0, 64 << 10, 2048, ER_4K),
.sfdp_read = m25p80_sfdp_w25q01jvq },
/* Microchip */
{ INFO("25csm04", 0x29cc00, 0x100, 64 << 10, 8, 0) },
};
typedef enum {
+475 -91
View File
File diff suppressed because it is too large Load Diff
+108
View File
@@ -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 cache flush inject register */
#define X_VC_ESBC_FLUSH_INJECT 0x142
#define VC_ESBC_FLUSH_INJECT 0x210
/* ESBC configuration */
#define X_VC_ESBC_CFG 0x148
#define VC_ESBC_CFG 0x240
@@ -250,6 +254,10 @@
#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 */
/* EASC flush inject register */
#define X_VC_EASC_FLUSH_INJECT 0x162
#define VC_EASC_FLUSH_INJECT 0x310
/*
* VC2
*/
@@ -270,6 +278,10 @@
#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 flush inject register */
#define X_VC_ENDC_FLUSH_INJECT 0x182
#define VC_ENDC_FLUSH_INJECT 0x410
/* ENDC Sync done */
#define X_VC_ENDC_SYNC_DONE 0x184
#define VC_ENDC_SYNC_DONE 0x420
@@ -283,6 +295,15 @@
#define VC_ENDC_SYNC_QUEUE_HARD PPC_BIT(6)
#define VC_QUEUE_COUNT 7
/* ENDC cache watch assign */
#define X_VC_ENDC_WATCH_ASSIGN 0x186
#define VC_ENDC_WATCH_ASSIGN 0x430
/* ENDC configuration register */
#define X_VC_ENDC_CFG 0x188
#define VC_ENDC_CFG 0x440
#define VC_ENDC_CFG_CACHE_WATCH_ASSIGN PPC_BITMASK(32, 35)
/* ENDC cache watch specification 0 */
#define X_VC_ENDC_WATCH0_SPEC 0x1A0
#define VC_ENDC_WATCH0_SPEC 0x500
@@ -302,6 +323,42 @@
#define VC_ENDC_WATCH0_DATA2 0x530
#define VC_ENDC_WATCH0_DATA3 0x538
/* ENDC cache watch 1 */
#define X_VC_ENDC_WATCH1_SPEC 0x1A8
#define VC_ENDC_WATCH1_SPEC 0x540
#define X_VC_ENDC_WATCH1_DATA0 0x1AC
#define X_VC_ENDC_WATCH1_DATA1 0x1AD
#define X_VC_ENDC_WATCH1_DATA2 0x1AE
#define X_VC_ENDC_WATCH1_DATA3 0x1AF
#define VC_ENDC_WATCH1_DATA0 0x560
#define VC_ENDC_WATCH1_DATA1 0x568
#define VC_ENDC_WATCH1_DATA2 0x570
#define VC_ENDC_WATCH1_DATA3 0x578
/* ENDC cache watch 2 */
#define X_VC_ENDC_WATCH2_SPEC 0x1B0
#define VC_ENDC_WATCH2_SPEC 0x580
#define X_VC_ENDC_WATCH2_DATA0 0x1B4
#define X_VC_ENDC_WATCH2_DATA1 0x1B5
#define X_VC_ENDC_WATCH2_DATA2 0x1B6
#define X_VC_ENDC_WATCH2_DATA3 0x1B7
#define VC_ENDC_WATCH2_DATA0 0x5A0
#define VC_ENDC_WATCH2_DATA1 0x5A8
#define VC_ENDC_WATCH2_DATA2 0x5B0
#define VC_ENDC_WATCH2_DATA3 0x5B8
/* ENDC cache watch 3 */
#define X_VC_ENDC_WATCH3_SPEC 0x1B8
#define VC_ENDC_WATCH3_SPEC 0x5C0
#define X_VC_ENDC_WATCH3_DATA0 0x1BC
#define X_VC_ENDC_WATCH3_DATA1 0x1BD
#define X_VC_ENDC_WATCH3_DATA2 0x1BE
#define X_VC_ENDC_WATCH3_DATA3 0x1BF
#define VC_ENDC_WATCH3_DATA0 0x5E0
#define VC_ENDC_WATCH3_DATA1 0x5E8
#define VC_ENDC_WATCH3_DATA2 0x5F0
#define VC_ENDC_WATCH3_DATA3 0x5F8
/*
* PC LSB1
*/
@@ -358,6 +415,21 @@
#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 flush inject */
#define X_PC_NXC_FLUSH_INJECT 0x282
#define PC_NXC_FLUSH_INJECT 0x410
/* NxC Cache watch assign */
#define X_PC_NXC_WATCH_ASSIGN 0x286
#define PC_NXC_WATCH_ASSIGN 0x430
/* NxC Proc config */
#define X_PC_NXC_PROC_CONFIG 0x28A
#define PC_NXC_PROC_CONFIG 0x450
#define PC_NXC_PROC_CONFIG_WATCH_ASSIGN PPC_BITMASK(0, 3)
#define PC_NXC_PROC_CONFIG_NVG_TABLE_COMPRESS PPC_BITMASK(32, 35)
#define PC_NXC_PROC_CONFIG_NVC_TABLE_COMPRESS PPC_BITMASK(36, 39)
/* NxC Cache Watch 0 Specification */
#define X_PC_NXC_WATCH0_SPEC 0x2A0
#define PC_NXC_WATCH0_SPEC 0x500
@@ -381,6 +453,42 @@
#define PC_NXC_WATCH0_DATA2 0x530
#define PC_NXC_WATCH0_DATA3 0x538
/* NxC Cache Watch 1 */
#define X_PC_NXC_WATCH1_SPEC 0x2A8
#define PC_NXC_WATCH1_SPEC 0x540
#define X_PC_NXC_WATCH1_DATA0 0x2AC
#define X_PC_NXC_WATCH1_DATA1 0x2AD
#define X_PC_NXC_WATCH1_DATA2 0x2AE
#define X_PC_NXC_WATCH1_DATA3 0x2AF
#define PC_NXC_WATCH1_DATA0 0x560
#define PC_NXC_WATCH1_DATA1 0x568
#define PC_NXC_WATCH1_DATA2 0x570
#define PC_NXC_WATCH1_DATA3 0x578
/* NxC Cache Watch 2 */
#define X_PC_NXC_WATCH2_SPEC 0x2B0
#define PC_NXC_WATCH2_SPEC 0x580
#define X_PC_NXC_WATCH2_DATA0 0x2B4
#define X_PC_NXC_WATCH2_DATA1 0x2B5
#define X_PC_NXC_WATCH2_DATA2 0x2B6
#define X_PC_NXC_WATCH2_DATA3 0x2B7
#define PC_NXC_WATCH2_DATA0 0x5A0
#define PC_NXC_WATCH2_DATA1 0x5A8
#define PC_NXC_WATCH2_DATA2 0x5B0
#define PC_NXC_WATCH2_DATA3 0x5B8
/* NxC Cache Watch 3 */
#define X_PC_NXC_WATCH3_SPEC 0x2B8
#define PC_NXC_WATCH3_SPEC 0x5C0
#define X_PC_NXC_WATCH3_DATA0 0x2BC
#define X_PC_NXC_WATCH3_DATA1 0x2BD
#define X_PC_NXC_WATCH3_DATA2 0x2BE
#define X_PC_NXC_WATCH3_DATA3 0x2BF
#define PC_NXC_WATCH3_DATA0 0x5E0
#define PC_NXC_WATCH3_DATA1 0x5E8
#define PC_NXC_WATCH3_DATA2 0x5F0
#define PC_NXC_WATCH3_DATA3 0x5F8
/*
* TCTXT Registers
*/
+9 -3
View File
@@ -692,9 +692,15 @@ void xive_tctx_pic_print_info(XiveTCTX *tctx, GString *buf)
}
}
g_string_append_printf(buf, "CPU[%04x]: "
"QW NSR CPPR IPB LSMFB ACK# INC AGE PIPR W2\n",
cpu_index);
if (xive_presenter_get_config(tctx->xptr) & XIVE_PRESENTER_GEN1_TIMA_OS) {
g_string_append_printf(buf, "CPU[%04x]: "
"QW NSR CPPR IPB LSMFB ACK# INC AGE PIPR"
" W2\n", cpu_index);
} else {
g_string_append_printf(buf, "CPU[%04x]: "
"QW NSR CPPR IPB LSMFB - LGS T PIPR"
" W2\n", cpu_index);
}
for (i = 0; i < XIVE_TM_RING_COUNT; i++) {
char *s = xive_tctx_ring_print(&tctx->regs[i * XIVE_TM_RING_SIZE]);
+31 -2
View File
@@ -89,7 +89,7 @@ void xive2_end_pic_print_info(Xive2End *end, uint32_t end_idx, GString *buf)
pq = xive_get_field32(END2_W1_ESn, end->w1);
g_string_append_printf(buf,
" %08x %c%c %c%c%c%c%c%c%c%c%c%c "
" %08x %c%c %c%c%c%c%c%c%c%c%c%c%c %c%c "
"prio:%d nvp:%02x/%04x",
end_idx,
pq & XIVE_ESB_VAL_P ? 'P' : '-',
@@ -98,12 +98,15 @@ void xive2_end_pic_print_info(Xive2End *end, uint32_t end_idx, GString *buf)
xive2_end_is_enqueue(end) ? 'q' : '-',
xive2_end_is_notify(end) ? 'n' : '-',
xive2_end_is_backlog(end) ? 'b' : '-',
xive2_end_is_precluded_escalation(end) ? 'p' : '-',
xive2_end_is_escalate(end) ? 'e' : '-',
xive2_end_is_escalate_end(end) ? 'N' : '-',
xive2_end_is_uncond_escalation(end) ? 'u' : '-',
xive2_end_is_silent_escalation(end) ? 's' : '-',
xive2_end_is_firmware1(end) ? 'f' : '-',
xive2_end_is_firmware2(end) ? 'F' : '-',
xive2_end_is_ignore(end) ? 'i' : '-',
xive2_end_is_crowd(end) ? 'c' : '-',
priority, nvp_blk, nvp_idx);
if (qaddr_base) {
@@ -137,6 +140,32 @@ void xive2_end_eas_pic_print_info(Xive2End *end, uint32_t end_idx,
(uint32_t) xive_get_field64(EAS2_END_DATA, eas->w));
}
void xive2_nvp_pic_print_info(Xive2Nvp *nvp, uint32_t nvp_idx, GString *buf)
{
uint8_t eq_blk = xive_get_field32(NVP2_W5_VP_END_BLOCK, nvp->w5);
uint32_t eq_idx = xive_get_field32(NVP2_W5_VP_END_INDEX, nvp->w5);
if (!xive2_nvp_is_valid(nvp)) {
return;
}
g_string_append_printf(buf, " %08x end:%02x/%04x IPB:%02x",
nvp_idx, eq_blk, eq_idx,
xive_get_field32(NVP2_W2_IPB, nvp->w2));
/*
* When the NVP is HW controlled, more fields are updated
*/
if (xive2_nvp_is_hw(nvp)) {
g_string_append_printf(buf, " CPPR:%02x",
xive_get_field32(NVP2_W2_CPPR, nvp->w2));
if (xive2_nvp_is_co(nvp)) {
g_string_append_printf(buf, " CO:%04x",
xive_get_field32(NVP2_W1_CO_THRID, nvp->w1));
}
}
g_string_append_c(buf, '\n');
}
static void xive2_end_enqueue(Xive2End *end, uint32_t data)
{
uint64_t qaddr_base = xive2_end_qaddr(end);
@@ -650,7 +679,7 @@ static void xive2_router_end_notify(Xive2Router *xrtr, uint8_t end_blk,
}
found = xive_presenter_notify(xrtr->xfb, format, nvp_blk, nvp_idx,
xive_get_field32(END2_W6_IGNORE, end.w7),
xive2_end_is_ignore(&end),
priority,
xive_get_field32(END2_W7_F1_LOG_SERVER_ID, end.w7));
+3
View File
@@ -39,6 +39,9 @@ config POWERNV
select PCI_POWERNV
select PCA9552
select PCA9554
select SSI
select SSI_M25P80
select PNV_SPI
config PPC405
bool
+1
View File
@@ -42,6 +42,7 @@ endif
ppc_ss.add(when: 'CONFIG_POWERNV', if_true: files(
'pnv.c',
'pnv_xscom.c',
'pnv_adu.c',
'pnv_core.c',
'pnv_i2c.c',
'pnv_lpc.c',
+322 -63
View File
File diff suppressed because it is too large Load Diff
+206
View File
@@ -0,0 +1,206 @@
/*
* QEMU PowerPC PowerNV ADU unit
*
* The ADU unit actually implements XSCOM, which is the bridge between MMIO
* and PIB. However it also includes control and status registers and other
* functions that are exposed as PIB (xscom) registers.
*
* To keep things simple, pnv_xscom.c remains the XSCOM bridge
* implementation, and pnv_adu.c implements the ADU registers and other
* functions.
*
* Copyright (c) 2024, IBM Corporation.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "qemu/osdep.h"
#include "qemu/log.h"
#include "hw/qdev-properties.h"
#include "hw/ppc/pnv.h"
#include "hw/ppc/pnv_adu.h"
#include "hw/ppc/pnv_chip.h"
#include "hw/ppc/pnv_lpc.h"
#include "hw/ppc/pnv_xscom.h"
#include "trace.h"
#define ADU_LPC_BASE_REG 0x40
#define ADU_LPC_CMD_REG 0x41
#define ADU_LPC_DATA_REG 0x42
#define ADU_LPC_STATUS_REG 0x43
static uint64_t pnv_adu_xscom_read(void *opaque, hwaddr addr, unsigned width)
{
PnvADU *adu = PNV_ADU(opaque);
uint32_t offset = addr >> 3;
uint64_t val = 0;
switch (offset) {
case 0x18: /* Receive status reg */
case 0x12: /* log register */
case 0x13: /* error register */
break;
case ADU_LPC_BASE_REG:
/*
* LPC Address Map in Pervasive ADU Workbook
*
* return PNV10_LPCM_BASE(chip) & PPC_BITMASK(8, 31);
* XXX: implement as class property, or get from LPC?
*/
qemu_log_mask(LOG_UNIMP, "ADU: LPC_BASE_REG is not implemented\n");
break;
case ADU_LPC_CMD_REG:
val = adu->lpc_cmd_reg;
break;
case ADU_LPC_DATA_REG:
val = adu->lpc_data_reg;
break;
case ADU_LPC_STATUS_REG:
val = PPC_BIT(0); /* ack / done */
break;
default:
qemu_log_mask(LOG_UNIMP, "ADU Unimplemented read register: Ox%08x\n",
offset);
}
trace_pnv_adu_xscom_read(addr, val);
return val;
}
static bool lpc_cmd_read(PnvADU *adu)
{
return !!(adu->lpc_cmd_reg & PPC_BIT(0));
}
static bool lpc_cmd_write(PnvADU *adu)
{
return !lpc_cmd_read(adu);
}
static uint32_t lpc_cmd_addr(PnvADU *adu)
{
return (adu->lpc_cmd_reg & PPC_BITMASK(32, 63)) >> PPC_BIT_NR(63);
}
static uint32_t lpc_cmd_size(PnvADU *adu)
{
return (adu->lpc_cmd_reg & PPC_BITMASK(5, 11)) >> PPC_BIT_NR(11);
}
static void pnv_adu_xscom_write(void *opaque, hwaddr addr, uint64_t val,
unsigned width)
{
PnvADU *adu = PNV_ADU(opaque);
uint32_t offset = addr >> 3;
trace_pnv_adu_xscom_write(addr, val);
switch (offset) {
case 0x18: /* Receive status reg */
case 0x12: /* log register */
case 0x13: /* error register */
break;
case ADU_LPC_BASE_REG:
qemu_log_mask(LOG_UNIMP,
"ADU: Changing LPC_BASE_REG is not implemented\n");
break;
case ADU_LPC_CMD_REG:
adu->lpc_cmd_reg = val;
if (lpc_cmd_read(adu)) {
uint32_t lpc_addr = lpc_cmd_addr(adu);
uint32_t lpc_size = lpc_cmd_size(adu);
uint64_t data = 0;
pnv_lpc_opb_read(adu->lpc, lpc_addr, (void *)&data, lpc_size);
/*
* ADU access is performed within 8-byte aligned sectors. Smaller
* access sizes don't get formatted to the least significant byte,
* but rather appear in the data reg at the same offset as the
* address in memory. This shifts them into that position.
*/
adu->lpc_data_reg = be64_to_cpu(data) >> ((lpc_addr & 7) * 8);
}
break;
case ADU_LPC_DATA_REG:
adu->lpc_data_reg = val;
if (lpc_cmd_write(adu)) {
uint32_t lpc_addr = lpc_cmd_addr(adu);
uint32_t lpc_size = lpc_cmd_size(adu);
uint64_t data;
data = cpu_to_be64(val) >> ((lpc_addr & 7) * 8); /* See above */
pnv_lpc_opb_write(adu->lpc, lpc_addr, (void *)&data, lpc_size);
}
break;
case ADU_LPC_STATUS_REG:
qemu_log_mask(LOG_UNIMP,
"ADU: Changing LPC_STATUS_REG is not implemented\n");
break;
default:
qemu_log_mask(LOG_UNIMP, "ADU Unimplemented write register: Ox%08x\n",
offset);
}
}
const MemoryRegionOps pnv_adu_xscom_ops = {
.read = pnv_adu_xscom_read,
.write = pnv_adu_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_adu_realize(DeviceState *dev, Error **errp)
{
PnvADU *adu = PNV_ADU(dev);
assert(adu->lpc);
/* XScom regions for ADU registers */
pnv_xscom_region_init(&adu->xscom_regs, OBJECT(dev),
&pnv_adu_xscom_ops, adu, "xscom-adu",
PNV9_XSCOM_ADU_SIZE);
}
static Property pnv_adu_properties[] = {
DEFINE_PROP_LINK("lpc", PnvADU, lpc, TYPE_PNV_LPC, PnvLpcController *),
DEFINE_PROP_END_OF_LIST(),
};
static void pnv_adu_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
dc->realize = pnv_adu_realize;
dc->desc = "PowerNV ADU";
device_class_set_props(dc, pnv_adu_properties);
dc->user_creatable = false;
}
static const TypeInfo pnv_adu_type_info = {
.name = TYPE_PNV_ADU,
.parent = TYPE_DEVICE,
.instance_size = sizeof(PnvADU),
.class_init = pnv_adu_class_init,
.interfaces = (InterfaceInfo[]) {
{ TYPE_PNV_XSCOM_INTERFACE },
{ } },
};
static void pnv_adu_register_types(void)
{
type_register_static(&pnv_adu_type_info);
}
type_init(pnv_adu_register_types);
+3 -4
View File
@@ -364,8 +364,7 @@ static void pnv_chiptod_xscom_write(void *opaque, hwaddr addr,
qemu_log_mask(LOG_GUEST_ERROR, "pnv_chiptod: xscom write reg"
" TOD_MOVE_TOD_TO_TB_REG with no slave target\n");
} else {
PowerPCCPU *cpu = chiptod->slave_pc_target->threads[0];
CPUPPCState *env = &cpu->env;
PnvCore *pc = chiptod->slave_pc_target;
/*
* Moving TOD to TB will set the TB of all threads in a
@@ -377,8 +376,8 @@ static void pnv_chiptod_xscom_write(void *opaque, hwaddr addr,
* thread 0.
*/
if (env->pnv_tod_tbst.tb_ready_for_tod) {
env->pnv_tod_tbst.tod_sent_to_tb = 1;
if (pc->tod_state.tb_ready_for_tod) {
pc->tod_state.tod_sent_to_tb = 1;
} else {
qemu_log_mask(LOG_GUEST_ERROR, "pnv_chiptod: xscom write reg"
" TOD_MOVE_TOD_TO_TB_REG with TB not ready to"
+118 -9
View File
@@ -58,6 +58,10 @@ static void pnv_core_cpu_reset(PnvCore *pc, PowerPCCPU *cpu)
env->nip = 0x10;
env->msr |= MSR_HVB; /* Hypervisor mode */
env->spr[SPR_HRMOR] = pc->hrmor;
if (pc->big_core) {
/* Clear "small core" bit on Power9/10 (this is set in default PVR) */
env->spr[SPR_PVR] &= ~PPC_BIT(51);
}
hreg_compute_hflags(env);
ppc_maybe_interrupt(env);
@@ -181,16 +185,43 @@ static const MemoryRegionOps pnv_core_power9_xscom_ops = {
*/
#define PNV10_XSCOM_EC_CORE_THREAD_STATE 0x412
#define PNV10_XSCOM_EC_CORE_THREAD_INFO 0x413
#define PNV10_XSCOM_EC_CORE_DIRECT_CONTROLS 0x449
#define PNV10_XSCOM_EC_CORE_RAS_STATUS 0x454
static uint64_t pnv_core_power10_xscom_read(void *opaque, hwaddr addr,
unsigned int width)
{
PnvCore *pc = PNV_CORE(opaque);
int nr_threads = CPU_CORE(pc)->nr_threads;
int i;
uint32_t offset = addr >> 3;
uint64_t val = 0;
switch (offset) {
case PNV10_XSCOM_EC_CORE_THREAD_STATE:
val = 0;
for (i = 0; i < nr_threads; i++) {
PowerPCCPU *cpu = pc->threads[i];
CPUState *cs = CPU(cpu);
if (cs->halted) {
val |= PPC_BIT(56 + i);
}
}
if (pc->lpar_per_core) {
val |= PPC_BIT(62);
}
break;
case PNV10_XSCOM_EC_CORE_THREAD_INFO:
break;
case PNV10_XSCOM_EC_CORE_RAS_STATUS:
for (i = 0; i < nr_threads; i++) {
PowerPCCPU *cpu = pc->threads[i];
CPUState *cs = CPU(cpu);
if (cs->stopped) {
val |= PPC_BIT(0 + 8 * i) | PPC_BIT(1 + 8 * i);
}
}
break;
default:
qemu_log_mask(LOG_UNIMP, "%s: unimp read 0x%08x\n", __func__,
@@ -203,9 +234,46 @@ static uint64_t pnv_core_power10_xscom_read(void *opaque, hwaddr addr,
static void pnv_core_power10_xscom_write(void *opaque, hwaddr addr,
uint64_t val, unsigned int width)
{
PnvCore *pc = PNV_CORE(opaque);
int nr_threads = CPU_CORE(pc)->nr_threads;
int i;
uint32_t offset = addr >> 3;
switch (offset) {
case PNV10_XSCOM_EC_CORE_DIRECT_CONTROLS:
for (i = 0; i < nr_threads; i++) {
PowerPCCPU *cpu = pc->threads[i];
CPUState *cs = CPU(cpu);
if (val & PPC_BIT(7 + 8 * i)) { /* stop */
val &= ~PPC_BIT(7 + 8 * i);
cpu_pause(cs);
}
if (val & PPC_BIT(6 + 8 * i)) { /* start */
val &= ~PPC_BIT(6 + 8 * i);
cpu_resume(cs);
}
if (val & PPC_BIT(4 + 8 * i)) { /* sreset */
val &= ~PPC_BIT(4 + 8 * i);
pnv_cpu_do_nmi_resume(cs);
}
if (val & PPC_BIT(3 + 8 * i)) { /* clear maint */
/*
* Hardware has very particular cases for where clear maint
* must be used and where start must be used to resume a
* thread. These are not modelled exactly, just treat
* this and start the same.
*/
val &= ~PPC_BIT(3 + 8 * i);
cpu_resume(cs);
}
}
if (val) {
qemu_log_mask(LOG_UNIMP, "%s: unimp bits in DIRECT_CONTROLS "
"0x%016" PRIx64 "\n", __func__, val);
}
break;
default:
qemu_log_mask(LOG_UNIMP, "%s: unimp write 0x%08x\n", __func__,
offset);
@@ -227,8 +295,9 @@ static void pnv_core_cpu_realize(PnvCore *pc, PowerPCCPU *cpu, Error **errp,
{
CPUPPCState *env = &cpu->env;
int core_hwid;
ppc_spr_t *pir = &env->spr_cb[SPR_PIR];
ppc_spr_t *tir = &env->spr_cb[SPR_TIR];
ppc_spr_t *pir_spr = &env->spr_cb[SPR_PIR];
ppc_spr_t *tir_spr = &env->spr_cb[SPR_TIR];
uint32_t pir, tir;
Error *local_err = NULL;
PnvChipClass *pcc = PNV_CHIP_GET_CLASS(pc->chip);
@@ -244,8 +313,20 @@ static void pnv_core_cpu_realize(PnvCore *pc, PowerPCCPU *cpu, Error **errp,
core_hwid = object_property_get_uint(OBJECT(pc), "hwid", &error_abort);
tir->default_value = thread_index;
pir->default_value = pcc->chip_pir(pc->chip, core_hwid, thread_index);
pcc->get_pir_tir(pc->chip, core_hwid, thread_index, &pir, &tir);
pir_spr->default_value = pir;
tir_spr->default_value = tir;
if (pc->big_core) {
/* 2 "small cores" get the same core index for SMT operations */
env->core_index = core_hwid >> 1;
} else {
env->core_index = core_hwid;
}
if (pc->lpar_per_core) {
cpu_ppc_set_1lpar(cpu);
}
/* Set time-base frequency to 512 MHz */
cpu_ppc_tb_init(env, PNV_TIMEBASE_FREQ);
@@ -278,16 +359,22 @@ static void pnv_core_realize(DeviceState *dev, Error **errp)
pc->threads = g_new(PowerPCCPU *, cc->nr_threads);
for (i = 0; i < cc->nr_threads; i++) {
PowerPCCPU *cpu;
PnvCPUState *pnv_cpu;
obj = object_new(typename);
cpu = POWERPC_CPU(obj);
pc->threads[i] = POWERPC_CPU(obj);
if (cc->nr_threads > 1) {
cpu->env.has_smt_siblings = true;
}
snprintf(name, sizeof(name), "thread[%d]", i);
object_property_add_child(OBJECT(pc), name, obj);
cpu->machine_data = g_new0(PnvCPUState, 1);
pnv_cpu = pnv_cpu_state(cpu);
pnv_cpu->pnv_core = pc;
object_unref(obj);
}
@@ -344,6 +431,10 @@ static void pnv_core_unrealize(DeviceState *dev)
static Property pnv_core_properties[] = {
DEFINE_PROP_UINT32("hwid", PnvCore, hwid, 0),
DEFINE_PROP_UINT64("hrmor", PnvCore, hrmor, 0),
DEFINE_PROP_BOOL("big-core", PnvCore, big_core, false),
DEFINE_PROP_BOOL("quirk-tb-big-core", PnvCore, tod_state.big_core_quirk,
false),
DEFINE_PROP_BOOL("lpar-per-core", PnvCore, lpar_per_core, false),
DEFINE_PROP_LINK("chip", PnvCore, chip, TYPE_PNV_CHIP, PnvChip *),
DEFINE_PROP_END_OF_LIST(),
};
@@ -504,6 +595,7 @@ static const MemoryRegionOps pnv_quad_power10_xscom_ops = {
static uint64_t pnv_qme_power10_xscom_read(void *opaque, hwaddr addr,
unsigned int width)
{
PnvQuad *eq = PNV_QUAD(opaque);
uint32_t offset = addr >> 3;
uint64_t val = -1;
@@ -511,10 +603,14 @@ static uint64_t pnv_qme_power10_xscom_read(void *opaque, hwaddr addr,
* Forth nibble selects the core within a quad, mask it to process read
* for any core.
*/
switch (offset & ~0xf000) {
case P10_QME_SPWU_HYP:
switch (offset & ~PPC_BITMASK32(16, 19)) {
case P10_QME_SSH_HYP:
return 0;
val = 0;
if (eq->special_wakeup_done) {
val |= PPC_BIT(1); /* SPWU DONE */
val |= PPC_BIT(4); /* SSH SPWU DONE */
}
break;
default:
qemu_log_mask(LOG_UNIMP, "%s: unimp read 0x%08x\n", __func__,
offset);
@@ -526,9 +622,22 @@ static uint64_t pnv_qme_power10_xscom_read(void *opaque, hwaddr addr,
static void pnv_qme_power10_xscom_write(void *opaque, hwaddr addr,
uint64_t val, unsigned int width)
{
PnvQuad *eq = PNV_QUAD(opaque);
uint32_t offset = addr >> 3;
bool set;
int i;
switch (offset) {
switch (offset & ~PPC_BITMASK32(16, 19)) {
case P10_QME_SPWU_HYP:
set = !!(val & PPC_BIT(0));
eq->special_wakeup_done = set;
for (i = 0; i < 4; i++) {
/* These bits select cores in the quad */
if (offset & PPC_BIT32(16 + i)) {
eq->special_wakeup[i] = set;
}
}
break;
default:
qemu_log_mask(LOG_UNIMP, "%s: unimp write 0x%08x\n", __func__,
offset);
+132 -34
View File
@@ -64,6 +64,7 @@ enum {
#define LPC_HC_IRQSER_START_4CLK 0x00000000
#define LPC_HC_IRQSER_START_6CLK 0x01000000
#define LPC_HC_IRQSER_START_8CLK 0x02000000
#define LPC_HC_IRQSER_AUTO_CLEAR 0x00800000
#define LPC_HC_IRQMASK 0x34 /* same bit defs as LPC_HC_IRQSTAT */
#define LPC_HC_IRQSTAT 0x38
#define LPC_HC_IRQ_SERIRQ0 0x80000000 /* all bits down to ... */
@@ -235,16 +236,16 @@ int pnv_dt_lpc(PnvChip *chip, void *fdt, int root_offset, uint64_t lpcm_addr,
* TODO: rework to use address_space_stq() and address_space_ldq()
* instead.
*/
static bool opb_read(PnvLpcController *lpc, uint32_t addr, uint8_t *data,
int sz)
bool pnv_lpc_opb_read(PnvLpcController *lpc, uint32_t addr,
uint8_t *data, int sz)
{
/* XXX Handle access size limits and FW read caching here */
return !address_space_read(&lpc->opb_as, addr, MEMTXATTRS_UNSPECIFIED,
data, sz);
}
static bool opb_write(PnvLpcController *lpc, uint32_t addr, uint8_t *data,
int sz)
bool pnv_lpc_opb_write(PnvLpcController *lpc, uint32_t addr,
uint8_t *data, int sz)
{
/* XXX Handle access size limits here */
return !address_space_write(&lpc->opb_as, addr, MEMTXATTRS_UNSPECIFIED,
@@ -276,7 +277,7 @@ static void pnv_lpc_do_eccb(PnvLpcController *lpc, uint64_t cmd)
}
if (cmd & ECCB_CTL_READ) {
success = opb_read(lpc, opb_addr, data, sz);
success = pnv_lpc_opb_read(lpc, opb_addr, data, sz);
if (success) {
lpc->eccb_stat_reg = ECCB_STAT_OP_DONE |
(((uint64_t)data[0]) << 24 |
@@ -293,7 +294,7 @@ static void pnv_lpc_do_eccb(PnvLpcController *lpc, uint64_t cmd)
data[2] = lpc->eccb_data_reg >> 8;
data[3] = lpc->eccb_data_reg;
success = opb_write(lpc, opb_addr, data, sz);
success = pnv_lpc_opb_write(lpc, opb_addr, data, sz);
lpc->eccb_stat_reg = ECCB_STAT_OP_DONE;
}
/* XXX Which error bit (if any) to signal OPB error ? */
@@ -420,32 +421,90 @@ static const MemoryRegionOps pnv_lpc_mmio_ops = {
.endianness = DEVICE_BIG_ENDIAN,
};
/* Program the POWER9 LPC irq to PSI serirq routing table */
static void pnv_lpc_eval_serirq_routes(PnvLpcController *lpc)
{
int irq;
if (!lpc->psi_has_serirq) {
if ((lpc->opb_irq_route0 & PPC_BITMASK(8, 13)) ||
(lpc->opb_irq_route1 & PPC_BITMASK(4, 31))) {
qemu_log_mask(LOG_GUEST_ERROR,
"OPB: setting serirq routing on POWER8 system, ignoring.\n");
}
return;
}
for (irq = 0; irq <= 13; irq++) {
int serirq = (lpc->opb_irq_route1 >> (31 - 5 - (irq * 2))) & 0x3;
lpc->irq_to_serirq_route[irq] = serirq;
}
for (irq = 14; irq < ISA_NUM_IRQS; irq++) {
int serirq = (lpc->opb_irq_route0 >> (31 - 9 - (irq * 2))) & 0x3;
lpc->irq_to_serirq_route[irq] = serirq;
}
}
static void pnv_lpc_eval_irqs(PnvLpcController *lpc)
{
bool lpc_to_opb_irq = false;
uint32_t active_irqs = 0;
if (lpc->lpc_hc_irqstat & PPC_BITMASK32(16, 31)) {
qemu_log_mask(LOG_UNIMP, "LPC HC Unimplemented irqs in IRQSTAT: "
"0x%08"PRIx32"\n", lpc->lpc_hc_irqstat);
}
/* Update LPC controller to OPB line */
if (lpc->lpc_hc_irqser_ctrl & LPC_HC_IRQSER_EN) {
uint32_t irqs;
irqs = lpc->lpc_hc_irqstat & lpc->lpc_hc_irqmask;
lpc_to_opb_irq = (irqs != 0);
active_irqs = lpc->lpc_hc_irqstat & lpc->lpc_hc_irqmask;
}
/* We don't honor the polarity register, it's pointless and unused
* anyway
*/
if (lpc_to_opb_irq) {
lpc->opb_irq_input |= OPB_MASTER_IRQ_LPC;
} else {
lpc->opb_irq_input &= ~OPB_MASTER_IRQ_LPC;
}
/* Update OPB internal latch */
lpc->opb_irq_stat |= lpc->opb_irq_input & lpc->opb_irq_mask;
/* Reflect the interrupt */
qemu_set_irq(lpc->psi_irq, lpc->opb_irq_stat != 0);
if (!lpc->psi_has_serirq) {
/*
* POWER8 ORs all irqs together (also with LPCHC internal interrupt
* sources) and outputs a single line that raises the PSI LPCHC irq
* which then latches an OPB IRQ status register that sends the irq
* to PSI.
*
* We don't honor the polarity register, it's pointless and unused
* anyway
*/
if (active_irqs) {
lpc->opb_irq_input |= OPB_MASTER_IRQ_LPC;
} else {
lpc->opb_irq_input &= ~OPB_MASTER_IRQ_LPC;
}
/* Update OPB internal latch */
lpc->opb_irq_stat |= lpc->opb_irq_input & lpc->opb_irq_mask;
qemu_set_irq(lpc->psi_irq_lpchc, lpc->opb_irq_stat != 0);
} else {
/*
* POWER9 and POWER10 have routing fields in OPB master registers that
* send LPC irqs to 4 output lines that raise the PSI SERIRQ irqs.
* These don't appear to get latched into an OPB register like the
* LPCHC irqs.
*
* POWER9 LPC controller internal irqs still go via the OPB
* and LPCHC PSI irqs like P8, but we have no such internal sources
* modelled yet.
*/
bool serirq_out[4] = { false, false, false, false };
int irq;
for (irq = 0; irq < ISA_NUM_IRQS; irq++) {
if (active_irqs & (LPC_HC_IRQ_SERIRQ0 >> irq)) {
serirq_out[lpc->irq_to_serirq_route[irq]] = true;
}
}
qemu_set_irq(lpc->psi_irq_serirq[0], serirq_out[0]);
qemu_set_irq(lpc->psi_irq_serirq[1], serirq_out[1]);
qemu_set_irq(lpc->psi_irq_serirq[2], serirq_out[2]);
qemu_set_irq(lpc->psi_irq_serirq[3], serirq_out[3]);
}
}
static uint64_t lpc_hc_read(void *opaque, hwaddr addr, unsigned size)
@@ -505,7 +564,14 @@ static void lpc_hc_write(void *opaque, hwaddr addr, uint64_t val,
pnv_lpc_eval_irqs(lpc);
break;
case LPC_HC_IRQSTAT:
lpc->lpc_hc_irqstat &= ~val;
/*
* This register is write-to-clear for the IRQSER (LPC device IRQ)
* status. However if the device has not de-asserted its interrupt
* that will just raise this IRQ status bit again. Model this by
* keeping track of the inputs and only clearing if the inputs are
* deasserted.
*/
lpc->lpc_hc_irqstat &= ~(val & ~lpc->lpc_hc_irq_inputs);
pnv_lpc_eval_irqs(lpc);
break;
case LPC_HC_ERROR_ADDRESS:
@@ -536,10 +602,10 @@ static uint64_t opb_master_read(void *opaque, hwaddr addr, unsigned size)
uint64_t val = 0xfffffffffffffffful;
switch (addr) {
case OPB_MASTER_LS_ROUTE0: /* TODO */
case OPB_MASTER_LS_ROUTE0:
val = lpc->opb_irq_route0;
break;
case OPB_MASTER_LS_ROUTE1: /* TODO */
case OPB_MASTER_LS_ROUTE1:
val = lpc->opb_irq_route1;
break;
case OPB_MASTER_LS_IRQ_STAT:
@@ -568,11 +634,15 @@ static void opb_master_write(void *opaque, hwaddr addr,
PnvLpcController *lpc = opaque;
switch (addr) {
case OPB_MASTER_LS_ROUTE0: /* TODO */
case OPB_MASTER_LS_ROUTE0:
lpc->opb_irq_route0 = val;
pnv_lpc_eval_serirq_routes(lpc);
pnv_lpc_eval_irqs(lpc);
break;
case OPB_MASTER_LS_ROUTE1: /* TODO */
case OPB_MASTER_LS_ROUTE1:
lpc->opb_irq_route1 = val;
pnv_lpc_eval_serirq_routes(lpc);
pnv_lpc_eval_irqs(lpc);
break;
case OPB_MASTER_LS_IRQ_STAT:
lpc->opb_irq_stat &= ~val;
@@ -657,6 +727,8 @@ static void pnv_lpc_power9_realize(DeviceState *dev, Error **errp)
PnvLpcClass *plc = PNV_LPC_GET_CLASS(dev);
Error *local_err = NULL;
object_property_set_bool(OBJECT(lpc), "psi-serirq", true, &error_abort);
plc->parent_realize(dev, &local_err);
if (local_err) {
error_propagate(errp, local_err);
@@ -666,6 +738,9 @@ static void pnv_lpc_power9_realize(DeviceState *dev, Error **errp)
/* P9 uses a MMIO region */
memory_region_init_io(&lpc->xscom_regs, OBJECT(lpc), &pnv_lpc_mmio_ops,
lpc, "lpcm", PNV9_LPCM_SIZE);
/* P9 LPC routes ISA irqs to 4 PSI SERIRQ lines */
qdev_init_gpio_out_named(dev, lpc->psi_irq_serirq, "SERIRQ", 4);
}
static void pnv_lpc_power9_class_init(ObjectClass *klass, void *data)
@@ -744,13 +819,19 @@ static void pnv_lpc_realize(DeviceState *dev, Error **errp)
memory_region_add_subregion(&lpc->opb_mr, LPC_HC_REGS_OPB_ADDR,
&lpc->lpc_hc_regs);
qdev_init_gpio_out(dev, &lpc->psi_irq, 1);
qdev_init_gpio_out_named(dev, &lpc->psi_irq_lpchc, "LPCHC", 1);
}
static Property pnv_lpc_properties[] = {
DEFINE_PROP_BOOL("psi-serirq", PnvLpcController, psi_has_serirq, false),
DEFINE_PROP_END_OF_LIST(),
};
static void pnv_lpc_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
device_class_set_props(dc, pnv_lpc_properties);
dc->realize = pnv_lpc_realize;
dc->desc = "PowerNV LPC Controller";
dc->user_creatable = false;
@@ -796,18 +877,34 @@ static void pnv_lpc_isa_irq_handler_cpld(void *opaque, int n, int level)
}
if (pnv->cpld_irqstate != old_state) {
qemu_set_irq(lpc->psi_irq, pnv->cpld_irqstate != 0);
qemu_set_irq(lpc->psi_irq_lpchc, pnv->cpld_irqstate != 0);
}
}
static void pnv_lpc_isa_irq_handler(void *opaque, int n, int level)
{
PnvLpcController *lpc = PNV_LPC(opaque);
uint32_t irq_bit = LPC_HC_IRQ_SERIRQ0 >> n;
/* The Naples HW latches the 1 levels, clearing is done by SW */
if (level) {
lpc->lpc_hc_irqstat |= LPC_HC_IRQ_SERIRQ0 >> n;
lpc->lpc_hc_irq_inputs |= irq_bit;
/*
* The LPC HC in Naples and later latches LPC IRQ into a bit field in
* the IRQSTAT register, and that drives the PSI IRQ to the IC.
* Software clears this bit manually (see LPC_HC_IRQSTAT handler).
*/
lpc->lpc_hc_irqstat |= irq_bit;
pnv_lpc_eval_irqs(lpc);
} else {
lpc->lpc_hc_irq_inputs &= ~irq_bit;
/* POWER9 adds an auto-clear mode that clears IRQSTAT bits on EOI */
if (lpc->psi_has_serirq &&
(lpc->lpc_hc_irqser_ctrl & LPC_HC_IRQSER_AUTO_CLEAR)) {
lpc->lpc_hc_irqstat &= ~irq_bit;
pnv_lpc_eval_irqs(lpc);
}
}
}
@@ -838,6 +935,7 @@ ISABus *pnv_lpc_isa_create(PnvLpcController *lpc, bool use_cpld, Error **errp)
handler = pnv_lpc_isa_irq_handler;
}
/* POWER has a 17th irq, QEMU only implements the 16 regular device irqs */
irqs = qemu_allocate_irqs(handler, lpc, ISA_NUM_IRQS);
isa_bus_register_input_irqs(isa_bus, irqs);
-9
View File
@@ -75,11 +75,6 @@ static uint64_t xscom_read_default(PnvChip *chip, uint32_t pcba)
case PRD_P9_IPOLL_REG_MASK:
case PRD_P9_IPOLL_REG_STATUS:
/* P9 xscom reset */
case 0x0090018: /* Receive status reg */
case 0x0090012: /* log register */
case 0x0090013: /* error register */
/* P8 xscom reset */
case 0x2020007: /* ADU stuff, log register */
case 0x2020009: /* ADU stuff, error register */
@@ -119,10 +114,6 @@ static bool xscom_write_default(PnvChip *chip, uint32_t pcba, uint64_t val)
case 0x1010c03: /* PIBAM FIR MASK */
case 0x1010c04: /* PIBAM FIR MASK */
case 0x1010c05: /* PIBAM FIR MASK */
/* P9 xscom reset */
case 0x0090018: /* Receive status reg */
case 0x0090012: /* log register */
case 0x0090013: /* error register */
/* P8 xscom reset */
case 0x2020007: /* ADU stuff, log register */
+1
View File
@@ -2195,6 +2195,7 @@ static const VMStateDescription vmstate_spapr = {
&vmstate_spapr_cap_fwnmi,
&vmstate_spapr_fwnmi,
&vmstate_spapr_cap_rpt_invalidate,
&vmstate_spapr_cap_ail_mode_3,
&vmstate_spapr_cap_nested_papr,
NULL
}
+1
View File
@@ -974,6 +974,7 @@ SPAPR_CAP_MIG_STATE(large_decr, SPAPR_CAP_LARGE_DECREMENTER);
SPAPR_CAP_MIG_STATE(ccf_assist, SPAPR_CAP_CCF_ASSIST);
SPAPR_CAP_MIG_STATE(fwnmi, SPAPR_CAP_FWNMI);
SPAPR_CAP_MIG_STATE(rpt_invalidate, SPAPR_CAP_RPT_INVALIDATE);
SPAPR_CAP_MIG_STATE(ail_mode_3, SPAPR_CAP_AIL_MODE_3);
void spapr_caps_init(SpaprMachineState *spapr)
{
+13 -3
View File
@@ -300,11 +300,13 @@ static PowerPCCPU *spapr_create_vcpu(SpaprCpuCore *sc, int i, Error **errp)
g_autofree char *id = NULL;
CPUState *cs;
PowerPCCPU *cpu;
CPUPPCState *env;
obj = object_new(scc->cpu_type);
cs = CPU(obj);
cpu = POWERPC_CPU(obj);
env = &cpu->env;
/*
* All CPUs start halted. CPU0 is unhalted from the machine level reset code
* and the rest are explicitly started up by the guest using an RTAS call.
@@ -315,6 +317,8 @@ static PowerPCCPU *spapr_create_vcpu(SpaprCpuCore *sc, int i, Error **errp)
return NULL;
}
env->core_index = cc->core_id;
cpu->node_id = sc->node_id;
id = g_strdup_printf("thread[%d]", i);
@@ -345,9 +349,15 @@ static void spapr_cpu_core_realize(DeviceState *dev, Error **errp)
qemu_register_reset(spapr_cpu_core_reset_handler, sc);
sc->threads = g_new0(PowerPCCPU *, cc->nr_threads);
for (i = 0; i < cc->nr_threads; i++) {
sc->threads[i] = spapr_create_vcpu(sc, i, errp);
if (!sc->threads[i] ||
!spapr_realize_vcpu(sc->threads[i], spapr, sc, i, errp)) {
PowerPCCPU *cpu;
cpu = spapr_create_vcpu(sc, i, errp);
sc->threads[i] = cpu;
if (cpu && cc->nr_threads > 1) {
cpu->env.has_smt_siblings = true;
}
if (!cpu || !spapr_realize_vcpu(cpu, spapr, sc, i, errp)) {
spapr_cpu_core_unrealize(dev);
return;
}
+4 -17
View File
@@ -15,19 +15,6 @@
#include "helper_regs.h"
#include "hw/ppc/spapr.h"
#include "mmu-hash64.h"
#include "mmu-book3s-v3.h"
static inline bool valid_ptex(PowerPCCPU *cpu, target_ulong ptex)
{
/*
* hash value/pteg group index is normalized by HPT mask
*/
if (((ptex & ~7ULL) / HPTES_PER_GROUP) & ~ppc_hash64_hpt_mask(cpu)) {
return false;
}
return true;
}
static target_ulong h_enter(PowerPCCPU *cpu, SpaprMachineState *spapr,
target_ulong opcode, target_ulong *args)
@@ -70,7 +57,7 @@ static target_ulong h_enter(PowerPCCPU *cpu, SpaprMachineState *spapr,
pteh &= ~0x60ULL;
if (!valid_ptex(cpu, ptex)) {
if (!ppc_hash64_valid_ptex(cpu, ptex)) {
return H_PARAMETER;
}
@@ -119,7 +106,7 @@ static RemoveResult remove_hpte(PowerPCCPU *cpu
const ppc_hash_pte64_t *hptes;
target_ulong v, r;
if (!valid_ptex(cpu, ptex)) {
if (!ppc_hash64_valid_ptex(cpu, ptex)) {
return REMOVE_PARM;
}
@@ -250,7 +237,7 @@ static target_ulong h_protect(PowerPCCPU *cpu, SpaprMachineState *spapr,
const ppc_hash_pte64_t *hptes;
target_ulong v, r;
if (!valid_ptex(cpu, ptex)) {
if (!ppc_hash64_valid_ptex(cpu, ptex)) {
return H_PARAMETER;
}
@@ -287,7 +274,7 @@ static target_ulong h_read(PowerPCCPU *cpu, SpaprMachineState *spapr,
int i, ridx, n_entries = 1;
const ppc_hash_pte64_t *hptes;
if (!valid_ptex(cpu, ptex)) {
if (!ppc_hash64_valid_ptex(cpu, ptex)) {
return H_PARAMETER;
}
+1 -1
View File
@@ -28,7 +28,7 @@ target_ulong spapr_h_vof_client(PowerPCCPU *cpu, SpaprMachineState *spapr,
void spapr_vof_client_dt_finalize(SpaprMachineState *spapr, void *fdt)
{
char *stdout_path = spapr_vio_stdout_path(spapr->vio_bus);
g_autofree char *stdout_path = spapr_vio_stdout_path(spapr->vio_bus);
vof_build_dt(fdt, spapr->vof);

Some files were not shown because too many files have changed in this diff Show More