From nobody Sat Apr 11 23:02:25 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=reject dis=none) header.from=linux.ibm.com ARC-Seal: i=1; a=rsa-sha256; t=1773040893; cv=none; d=zohomail.com; s=zohoarc; b=MlnFBkz9fQ6ZBpnm08Ja60heMQ+oGEVGuQgyxOSMU9wiU3ex6sM+LUIuyq0P0g22bI/7TBNqaoeF1cUdPYlz0mBy0MmjrpnM4wUpH7PqWuRsSEqkFa03zTuZ1L+0GfI4gbEN8oBJRrksV+1BZ5+KviE1dXpXURjHBNrlQYnDRxc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1773040893; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=zEfKADFRDDebjpGnWoNHy/Kha4EA5tSq9mWpvIecyDo=; b=MkwmEMe/fvjieXmxOTkIolDCTxnjK1AtobyrTamW0abb6Z1zaJHzWo+xCqye6Uv3SI+n+93xVzUsNnAmeYczVWnj3zTU0B2OPg1WBVA8bjg2EEts+BRPxwo0p/oaodXugB4+lDoOtCibMY/NjzwVqn0mhOasyX75B+xzI2A3NZI= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=reject dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1773040893765694.8099807215002; Mon, 9 Mar 2026 00:21:33 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vzUus-0006PY-FX; Mon, 09 Mar 2026 03:20:38 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vzUuq-0006Os-Be; Mon, 09 Mar 2026 03:20:36 -0400 Received: from mx0a-001b2d01.pphosted.com ([148.163.156.1]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vzUuo-0006E7-At; Mon, 09 Mar 2026 03:20:36 -0400 Received: from pps.filterd (m0360083.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 6292t4xx2350421; Mon, 9 Mar 2026 07:20:32 GMT Received: from ppma12.dal12v.mail.ibm.com (dc.9e.1632.ip4.static.sl-reverse.com [50.22.158.220]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 4crcvm5h2t-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 09 Mar 2026 07:20:31 +0000 (GMT) Received: from pps.filterd (ppma12.dal12v.mail.ibm.com [127.0.0.1]) by ppma12.dal12v.mail.ibm.com (8.18.1.2/8.18.1.2) with ESMTP id 6293Q2wF021150; Mon, 9 Mar 2026 07:20:31 GMT Received: from smtprelay01.fra02v.mail.ibm.com ([9.218.2.227]) by ppma12.dal12v.mail.ibm.com (PPS) with ESMTPS id 4crxbsm4u6-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 09 Mar 2026 07:20:30 +0000 Received: from smtpav03.fra02v.mail.ibm.com (smtpav03.fra02v.mail.ibm.com [10.20.54.102]) by smtprelay01.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 6297KQJw49807814 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Mon, 9 Mar 2026 07:20:26 GMT Received: from smtpav03.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id AC7072004E; Mon, 9 Mar 2026 07:20:26 +0000 (GMT) Received: from smtpav03.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 3C78020040; Mon, 9 Mar 2026 07:20:24 +0000 (GMT) Received: from li-3c92a0cc-27cf-11b2-a85c-b804d9ca68fa.in.ibm.com (unknown [9.109.199.210]) by smtpav03.fra02v.mail.ibm.com (Postfix) with ESMTP; Mon, 9 Mar 2026 07:20:24 +0000 (GMT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=cc :content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=pp1; bh=zEfKADFRDDebjpGnW oNHy/Kha4EA5tSq9mWpvIecyDo=; b=f06Xk2WLRc7x1DanEptUvSscxMbg4dMrL q/OadK6QK/4DIjFTZyxhzUAWdQq4I5x8oKUDrhjIk0rSIh35gQ9BDfAppcTTtMNS aSp3F43WPY4FT2ONTMUn2zgh3TFsTDjMUZ9lIRfI1JZl3Q65Kid2+LncxqbPhKxF Tmw+pOvC2YbBfQ0FtdbH4eCjgkwSoqfthxJZneby9BI0NYSAmM2e6yVWjPS9O8wF VJpeMIg8Hq3cqCPuY/Q1SgUOHVqWyRQnAYNtzIiyCO/DXeeTsd3ZW8cVB38cBVCY CH0OkZieWjFf/+6MXVKswG8DYA0r4+6ZEZprzZ+4Dj41548nvM99w== From: Aditya Gupta To: Cc: , Hari Bathini , Sourabh Jain , Harsh Prateek Bora , Nicholas Piggin , Miles Glenn , Chinmay Rath , Shivang Upadhyay Subject: [PATCH v4 07/10] pnv/mpipl: Write the preserved CPU and MDRT state Date: Mon, 9 Mar 2026 12:49:56 +0530 Message-ID: <20260309072001.3136261-8-adityag@linux.ibm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260309072001.3136261-1-adityag@linux.ibm.com> References: <20260309072001.3136261-1-adityag@linux.ibm.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-TM-AS-GCONF: 00 X-Proofpoint-Reinject: loops=2 maxloops=12 X-Proofpoint-GUID: w7keFrdzyMPWq8rkI5Ee_HDZvGPUpYVM X-Proofpoint-ORIG-GUID: xAv6zukVlcbEyg7JjVheat1C1ixITwLm X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwMzA5MDA2MyBTYWx0ZWRfX+p1lpfqrAbZy Nl/1qqv/Amp0STcK4sxSz3+VVPwmrYy8d8dyfRUsvuiYIxGIW2mRSmlZYOHULig+/fyLDeVOVJP c1thukPnVvuoDeaa83UPT8m5+Ku9ogo72KIqjHCNLQx7C/BCxUZvUoVbTiA21dn+scRhMkSlq0l dxN3vZoiVtvRKFIxYtL1qC1Nyt3VNK7COPFTkT73Ve1h3DzBb9w9jDU1jnFN12uYYWkshdTdmMO rtvbx9gB1sCHOM0Xp9zKH/J5pu2iI1vKVkjJqvXmWnVyhfWpo4iXeAOi4pgMKKxqRujzTkNCxY3 scY0gktU6cqigYBC/cwSzClT0nTg28wli94SNzUONkoEWzvOSCrn/0smB/fv9IhrEpR5Ao67KOg IlkiUgsh/I9kwJ9/sbl8GTJf4DNww9CQCrxopwGDLwOVNZudgWujUX06AYXyaETVxytDU9qz4kg 2GhcjiNLX3HXTRd+Oig== X-Authority-Analysis: v=2.4 cv=B5q0EetM c=1 sm=1 tr=0 ts=69ae74c0 cx=c_pps a=bLidbwmWQ0KltjZqbj+ezA==:117 a=bLidbwmWQ0KltjZqbj+ezA==:17 a=Yq5XynenixoA:10 a=VkNPw1HP01LnGYTKEx00:22 a=RnoormkPH1_aCDwRdu11:22 a=iQ6ETzBq9ecOQQE5vZCe:22 a=VnNF1IyMAAAA:8 a=dzawcXaIV5huiJcXlfYA:9 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1143,Hydra:6.1.51,FMLib:17.12.100.49 definitions=2026-03-09_02,2026-03-06_02,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 malwarescore=0 phishscore=0 adultscore=0 lowpriorityscore=0 bulkscore=0 priorityscore=1501 spamscore=0 clxscore=1015 impostorscore=0 suspectscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2602130000 definitions=main-2603090063 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=148.163.156.1; envelope-from=adityag@linux.ibm.com; helo=mx0a-001b2d01.pphosted.com X-Spam_score_int: -9 X-Spam_score: -1.0 X-Spam_bar: - X-Spam_report: (-1.0 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.819, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.903, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @ibm.com) X-ZM-MESSAGEID: 1773040895126154100 Content-Type: text/plain; charset="utf-8" Logic for preserving the CPU registers and memory regions has been done in previous patches. Write those data at the relevant memory address, such as PROC_DUMP_AREA for CPU registers, and MDRT for preserved memory regions. Also export "mpipl-boot" device tree node, for kernel to know that it's a 'dump active' boot Reviewed-by: Hari Bathini Signed-off-by: Aditya Gupta --- hw/ppc/pnv.c | 45 +++++++++++++- hw/ppc/pnv_mpipl.c | 140 +++++++++++++++++++++++++++++++++++++++++++ include/hw/ppc/pnv.h | 1 + 3 files changed, 185 insertions(+), 1 deletion(-) diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index 3038b1626c54..0b94e0c7a19b 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -751,6 +751,8 @@ static void pnv_reset(MachineState *machine, ResetType = type) PnvMachineState *pnv =3D PNV_MACHINE(machine); IPMIBmc *bmc; void *fdt; + int node_offset; + bool is_next_boot_mpipl =3D false; =20 qemu_devices_reset(type); =20 @@ -781,7 +783,48 @@ static void pnv_reset(MachineState *machine, ResetType= type) _FDT((fdt_pack(fdt))); } =20 - if (!pnv->mpipl_state.is_next_boot_mpipl) { + /* + * Only on success of writing MPIPL data will the next boot be provided + * "mpipl-boot" property in device tree + * Otherwise boot like a normal non-MPIPL boot + */ + if (pnv->mpipl_state.is_next_boot_mpipl) { + /* Write the preserved MDRT and CPU State Data */ + bool mpipl_write_succeeded =3D do_mpipl_write(pnv); + + if (!mpipl_write_succeeded) { + is_next_boot_mpipl =3D false; + } else { + is_next_boot_mpipl =3D true; + } + } + + /* + * If it's a MPIPL boot, add the "mpipl-boot" property, and reset the + * boolean for MPIPL boot for next boot + */ + if (is_next_boot_mpipl) { + void *fdt_copy =3D g_malloc0(FDT_MAX_SIZE); + + /* Create a writable copy of the fdt */ + _FDT((fdt_open_into(fdt, fdt_copy, FDT_MAX_SIZE))); + + node_offset =3D fdt_path_offset(fdt_copy, "/ibm,opal/dump"); + _FDT((fdt_appendprop_u64(fdt_copy, node_offset, "mpipl-boot", 1))); + + /* Update the fdt, and free the original fdt */ + if (fdt !=3D machine->fdt) { + /* + * Only free the fdt if it's not machine->fdt, to prevent + * double free, since we already free machine->fdt later + */ + g_free(fdt); + } + fdt =3D fdt_copy; + + /* This boot is an MPIPL, reset the boolean for next boot */ + pnv->mpipl_state.is_next_boot_mpipl =3D false; + } else { /* * Set the "Thread Register State Entry Size", so that firmware can * allocate enough memory to capture CPU state in the event of a diff --git a/hw/ppc/pnv_mpipl.c b/hw/ppc/pnv_mpipl.c index 37f498051254..2cf54a8ec306 100644 --- a/hw/ppc/pnv_mpipl.c +++ b/hw/ppc/pnv_mpipl.c @@ -20,6 +20,8 @@ (pnv->mpipl_state.skiboot_base + MDST_TABLE_OFF) #define MDDT_TABLE_RELOCATED \ (pnv->mpipl_state.skiboot_base + MDDT_TABLE_OFF) +#define MDRT_TABLE_RELOCATED \ + (pnv->mpipl_state.skiboot_base + MDRT_TABLE_OFF) #define PROC_DUMP_RELOCATED \ (pnv->mpipl_state.skiboot_base + PROC_DUMP_AREA_OFF) =20 @@ -319,6 +321,139 @@ static bool pnv_mpipl_preserve_cpu_state(PnvMachineSt= ate *pnv) return true; } =20 +/* + * Write the preserved CPU state data in Processor Dump Area (PROC_DUMP_AR= EA) + * + * Returns true if everything went fine, else false for any error + */ +static bool pnv_mpipl_write_cpu_state(PnvMachineState *pnv) +{ + MpiplProcDumpArea *proc_area =3D &pnv->mpipl_state.proc_area; + MpiplPreservedCPUState *cpu_state =3D pnv->mpipl_state.cpu_states; + const uint32_t num_cpu_states =3D pnv->mpipl_state.num_cpu_states; + hwaddr next_regentries_hdr; + AddressSpace *default_as =3D &address_space_memory; + MemTxResult io_result; + MemTxAttrs attrs; + + /* Mark the memory transactions as privileged memory access */ + attrs.user =3D 0; + attrs.memory =3D 1; + + if (be32_to_cpu(proc_area->alloc_size) < + (num_cpu_states * sizeof(MpiplPreservedCPUState))) { + qemu_log_mask(LOG_GUEST_ERROR, + "MPIPL: Size of buffer allocate by skiboot (%u bytes) is not" + "enough to save all CPUs registers needed (%zu bytes)", + be32_to_cpu(proc_area->alloc_size), + num_cpu_states * sizeof(MpiplPreservedCPUState)); + + return false; + } + + proc_area->version =3D PROC_DUMP_AREA_VERSION_P9; + + /* + * This is the stride kernel/firmware should use to jump from a + * register entries header to next CPU's header + */ + proc_area->thread_size =3D cpu_to_be32(sizeof(MpiplPreservedCPUState)); + + /* Write the header and register entries for each CPU */ + next_regentries_hdr =3D be64_to_cpu(proc_area->alloc_addr) & (~HRMOR_B= IT); + for (int i =3D 0; i < num_cpu_states; ++i) { + io_result =3D address_space_write(default_as, next_regentries_hdr,= attrs, + &cpu_state->hdr, sizeof(MpiplRegDataHdr)); + if (io_result !=3D MEMTX_OK) { + qemu_log_mask(LOG_GUEST_ERROR, + "MPIPL: Failed to write RegEntries Header\n"); + return false; + } + + io_result =3D address_space_write(default_as, + next_regentries_hdr + sizeof(MpiplRegDataHdr), attrs, + &cpu_state->reg_entries, + NUM_REGS_PER_CPU * (sizeof(MpiplRegEntry))); + if (io_result !=3D MEMTX_OK) { + qemu_log_mask(LOG_GUEST_ERROR, + "MPIPL: Failed to write Register Entries\n"); + return false; + } + + /* + * According to HDAT section: + * "15.3.1.5 Architected Register Data content": + * + * The next register entries header will be at current header + + * "Thread Register State Entry size" + * + * Note: proc_area.thread_size =3D=3D sizeof(MpiplPreservedCPUStat= e) + */ + next_regentries_hdr +=3D sizeof(MpiplPreservedCPUState); + ++cpu_state; + } + + /* Point the destination address to the preserved memory region */ + proc_area->dest_addr =3D proc_area->alloc_addr; + proc_area->act_size =3D cpu_to_be32(num_cpu_states * + sizeof(MpiplPreservedCPUState)); + + io_result =3D address_space_write(default_as, PROC_DUMP_AREA_OFF, attr= s, + proc_area, sizeof(MpiplProcDumpArea)); + if (io_result !=3D MEMTX_OK) { + qemu_log_mask(LOG_GUEST_ERROR, + "MPIPL: Failed to write Register Entries\n"); + return false; + } + + return true; +} + +/* + * Write the preserved MDRT table, representing preserved memory regions + * + * Returns true if everything went fine, else false for any error + */ +static bool pnv_mpipl_write_mdrt(PnvMachineState *pnv) +{ + MpiplPreservedState *state =3D &pnv->mpipl_state; + AddressSpace *default_as =3D &address_space_memory; + MemTxResult io_result; + MemTxAttrs attrs; + + /* Mark the memory transactions as privileged memory access */ + attrs.user =3D 0; + attrs.memory =3D 1; + + /* + * Generally writes from platform during MPIPL don't go to a relocated + * skiboot address + * + * Though for MDRT we are doing so, as this is the address skiboot + * considers by default for MDRT + * + * MDRT/MDST/MDDT base addresses are actually meant to be shared by + * platform in SPIRA structures. + * + * Not implementing SPIRA as it increases complexity for no gains. + * Using the default address skiboot expects for MDRT, which is the + * relocated MDRT, hence writing to it + * + * Other tables like MDST/MDDT should not be written to relocated + * addresses, as skiboot will overwrite anything from SKIBOOT_BASE till + * SKIBOOT_BASE+SKIBOOT_SIZE (which is 0x30000000-0x31c00000 by defaul= t) + */ + io_result =3D address_space_write(default_as, MDRT_TABLE_RELOCATED, at= trs, + state->mdrt_table, + state->num_mdrt_entries * sizeof(MdrtTableEntry)); + if (io_result !=3D MEMTX_OK) { + qemu_log_mask(LOG_GUEST_ERROR, "MPIPL: Failed to write MDRT table\= n"); + return false; + } + + return true; +} + void do_mpipl_preserve(PnvMachineState *pnv) { pause_all_vcpus(); @@ -339,3 +474,8 @@ void do_mpipl_preserve(PnvMachineState *pnv) */ qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); } + +bool do_mpipl_write(PnvMachineState *pnv) +{ + return pnv_mpipl_write_mdrt(pnv) && pnv_mpipl_write_cpu_state(pnv); +} diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h index 7d73629f112a..98fe10fb4f2e 100644 --- a/include/hw/ppc/pnv.h +++ b/include/hw/ppc/pnv.h @@ -295,5 +295,6 @@ void pnv_bmc_set_pnor(IPMIBmc *bmc, PnvPnor *pnor); =20 /* MPIPL helpers */ void do_mpipl_preserve(PnvMachineState *pnv); +bool do_mpipl_write(PnvMachineState *pnv); =20 #endif /* PPC_PNV_H */ --=20 2.53.0