Re: [PATCH v7 2/3] RAS/AMD/ATL: Translate UMC normalized address to DRAM address using PRM
Borislav Petkov <[email protected]> Mon, 6 Jul 2026 17:32:04 -0700
| Newsgroups | org.kernel.vger.linux-edac,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <20260707003204.GAakxJBJWtxD2fM6Th@fat_crate.local> |
On Tue, Jun 30, 2026 at 05:06:39PM -0400, Yazen Ghannam wrote: > From: Avadhut Naik <[email protected]> > > Modern AMD SOCs provide UEFI PRM module that implements various address > translation PRM handlers.[1] These handlers can be invoked by the OS or > hypervisor at runtime to perform address translations. > > On AMD's Zen-based SOCs, Unified Memory Controller (UMC) relative > "normalized" address is reported through MCA_ADDR of UMC SMCA bank type > on occurrence of a DRAM ECC error. This address must be converted into > system physical address and DRAM address to export additional information > about the error. > > Add support to convert normalized address into DRAM address through the > appropriate PRM handler. Instead of logging the translated DRAM address > locally, export the translating function when the Address Translation > library is initialized. Modules like amd64_edac can then invoke the PRM > handler to add the DRAM address to their error records. Additionally, it > can also be exported through the RAS tracepont. Use this commit message for this patch: Modern AMD SOCs provide an UEFI PRM module that implements various address translation PRM handlers¹. These handlers can be invoked by the OS or the hypervisor at runtime to perform address translations. On AMD's Zen-based SOCs, a Unified Memory Controller (UMC) relative "normalized" address is reported through the MCA_ADDR of UMC SMCA banks on occurrence of a DRAM ECC error. This address must be converted into a system physical address and DRAM address in order to decode additional information about the error. Add support to convert a normalized address into a DRAM address using such PRM handler. ¹https://bugzilla.kernel.org/show_bug.cgi?id=220577 or run it through AI because I'm tired of adding pronouns left and right and removing text which regurgitates the code in the patch. > [1] https://bugzilla.kernel.org/show_bug.cgi?id=220577 > > [Yazen: Remove 'handler available' check] > > Signed-off-by: Avadhut Naik <[email protected]> > Signed-off-by: Yazen Ghannam <[email protected]> > --- > drivers/ras/amd/atl/core.c | 6 ++++++ > drivers/ras/amd/atl/internal.h | 11 ++++++++++- > drivers/ras/amd/atl/prm.c | 32 ++++++++++++++++++++++++++++---- > drivers/ras/amd/atl/system.c | 3 +++ > drivers/ras/amd/atl/umc.c | 9 +++++++++ > include/linux/ras.h | 14 ++++++++++++++ > 6 files changed, 70 insertions(+), 5 deletions(-) ... > +static inline int prm_umc_norm_to_dram_addr(u8 socket_id, u64 bank_id, > + unsigned long addr, struct atl_dram_addr *dram_addr) ... int prm_umc_norm_to_dram_addr(u8 socket_id, u64 bank_id, unsigned long addr, struct atl_dram_addr *dram_addr) > +{ > + return -ENODEV; > +} > +#endif > /* > * Make a gap in @data that is @num_bits long starting at @bit_num. > * e.g. data = 11111111'b > diff --git a/drivers/ras/amd/atl/prm.c b/drivers/ras/amd/atl/prm.c > index 0f9bfa96e16a..c69158f66639 100644 > --- a/drivers/ras/amd/atl/prm.c > +++ b/drivers/ras/amd/atl/prm.c > @@ -19,10 +19,11 @@ > #include <linux/prmt.h> > > /* > - * PRM parameter buffer - normalized to system physical address, as described > - * in the "PRM Parameter Buffer" section of the AMD ACPI Porting Guide. > + * PRM parameter buffer - normalized to system physical address and normalized > + * to DRAM address, as described in the "PRM Parameter Buffer" section of the > + * AMD ACPI Porting Guide. > */ > -struct norm_to_sys_param_buf { > +struct prm_parameter_buffer { struct param_buf { This is not BIOS code. > u64 norm_addr; > u8 socket; > u64 bank_id; > @@ -31,7 +32,7 @@ struct norm_to_sys_param_buf { > > unsigned long prm_umc_norm_to_sys_addr(u8 socket_id, u64 bank_id, unsigned long addr) > { > - struct norm_to_sys_param_buf p_buf; > + struct prm_parameter_buffer p_buf; > unsigned long ret_addr; > int ret; > > @@ -51,3 +52,26 @@ unsigned long prm_umc_norm_to_sys_addr(u8 socket_id, u64 bank_id, unsigned long > > return ret; > } > + > +int prm_umc_norm_to_dram_addr(u8 socket_id, u64 bank_id, > + unsigned long addr, struct atl_dram_addr *dram_addr) int prm_umc_norm_to_dram_addr(u8 socket_id, u64 bank_id, unsigned long addr, struct atl_dram_addr *dram_addr) > +{ > + struct prm_parameter_buffer p_buf; > + int ret; > + > + p_buf.norm_addr = addr; > + p_buf.socket = socket_id; > + p_buf.bank_id = bank_id; > + p_buf.out_buf = dram_addr; > + > + ret = acpi_call_prm_handler(norm_to_dram_guid, &p_buf); > + if (!ret) > + return ret; > + > + if (ret == -ENODEV) > + pr_debug("PRM module/handler not available.\n"); > + else > + pr_notice_once("PRM DRAM Address Translation failed.\n"); Dump ret here. Also, this function is an almost identical copy to prm_umc_norm_to_sys_addr(). Merge the two pls. Thx. -- Regards/Gruss, Boris. https://people.kernel.org/tglx/notes-about-netiquette