diff mbox series

[RFC,v4,5/6] firmware/efi: Process CXL Component Events

Message ID 20230601-cxl-cper-v4-5-47bb901f135e@intel.com
State Superseded
Headers show
Series efi/cxl-cper: Report CPER CXL component events through trace events | expand

Commit Message

Ira Weiny Nov. 9, 2023, 10:07 p.m. UTC
BIOS can configure memory devices as firmware first.  This will send CXL
events to the firmware instead of the OS.  The firmware can then send
these events to the OS via UEFI.

UEFI v2.10 section N.2.14 defines a Common Platform Error Record (CPER)
format for CXL Component Events.  The format is mostly the same as the
CXL Common Event Record Format.  The difference is a GUID is used in
the Section Type to identify the event type.

Add EFI support to detect CXL CPER records and call a notifier chain
with the record data blobs to be processed by the CXL code.

Signed-off-by: Ira Weiny <ira.weiny@intel.com>

---
Changes from RFC v3
[Smita: ensure cper_cxl_event_rec is packed]

Changes from RFC v2
[djbw: use common event structures]
[djbw: remove print in core cper code]
[djbw: export register call as NS_GPL]
[iweiny: fix 0day issues]

Changes from RFC v1
[iweiny: use an enum for know record types and skip converting GUID to UUID]
[iweiny: commit to the UUID not being part of the event record data]
[iweiny: use defines for GUID definitions]
---
 drivers/firmware/efi/cper.c     | 15 +++++++++++++
 drivers/firmware/efi/cper_cxl.c | 40 +++++++++++++++++++++++++++++++++
 drivers/firmware/efi/cper_cxl.h | 29 ++++++++++++++++++++++++
 include/linux/cxl-event.h       | 49 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 133 insertions(+)

Comments

Smita Koralahalli Nov. 28, 2023, 8:32 p.m. UTC | #1
Hi Ira,

I tested this out. Just one correction below to make it work.

On 11/9/2023 2:07 PM, Ira Weiny wrote:
> BIOS can configure memory devices as firmware first.  This will send CXL
> events to the firmware instead of the OS.  The firmware can then send
> these events to the OS via UEFI.
> 
> UEFI v2.10 section N.2.14 defines a Common Platform Error Record (CPER)
> format for CXL Component Events.  The format is mostly the same as the
> CXL Common Event Record Format.  The difference is a GUID is used in
> the Section Type to identify the event type.
> 
> Add EFI support to detect CXL CPER records and call a notifier chain
> with the record data blobs to be processed by the CXL code.
> 
> Signed-off-by: Ira Weiny <ira.weiny@intel.com>
> 
> ---
> Changes from RFC v3
> [Smita: ensure cper_cxl_event_rec is packed]
> 
> Changes from RFC v2
> [djbw: use common event structures]
> [djbw: remove print in core cper code]
> [djbw: export register call as NS_GPL]
> [iweiny: fix 0day issues]
> 
> Changes from RFC v1
> [iweiny: use an enum for know record types and skip converting GUID to UUID]
> [iweiny: commit to the UUID not being part of the event record data]
> [iweiny: use defines for GUID definitions]
> ---

[snip]

> diff --git a/include/linux/cxl-event.h b/include/linux/cxl-event.h
> index 6b689e1efc78..733ab2ab8639 100644
> --- a/include/linux/cxl-event.h
> +++ b/include/linux/cxl-event.h
> @@ -108,4 +108,53 @@ struct cxl_event_record_raw {
>   	union cxl_event event;
>   } __packed;
>   
> +enum cxl_event_type {
> +	CXL_CPER_EVENT_GEN_MEDIA,
> +	CXL_CPER_EVENT_DRAM,
> +	CXL_CPER_EVENT_MEM_MODULE,
> +};
> +
> +#define CPER_CXL_DEVICE_ID_VALID		BIT(0)
> +#define CPER_CXL_DEVICE_SN_VALID		BIT(1)
> +#define CPER_CXL_COMP_EVENT_LOG_VALID		BIT(2)
> +struct cper_cxl_event_rec {
> +	struct {
> +		u32 length;
> +		u64 validation_bits;
> +		struct cper_cxl_event_devid {
> +			u16 vendor_id;
> +			u16 device_id;
> +			u8 func_num;
> +			u8 device_num;
> +			u8 bus_num;
> +			u16 segment_num;
> +			u16 slot_num; /* bits 2:0 reserved */
> +			u8 reserved;
> +		} device_id;
> +		struct cper_cxl_event_sn {
> +			u32 lower_dw;
> +			u32 upper_dw;
> +		} dev_serial_num;
> +	} hdr;
> +
> +	union cxl_event event;
> +} __packed;

__packed attribute just for cper_cxl_event_rec still fails to properly 
align structure elements. Looks like, __packed attribute is needed for 
all structs (cper_cxl_event_devid and cper_cxl_event_sn) inside 
cper_cxl_event_rec.

Seems easier to use global pragma instead.. I could test and obtain the 
output as expected using pragma..

Thanks,
Smita

> +
> +struct cxl_cper_notifier_data {
> +	enum cxl_event_type event_type;
> +	struct cper_cxl_event_rec *rec;
> +};
> +
> +#ifdef CONFIG_UEFI_CPER
> +int register_cxl_cper_notifier(struct notifier_block *nb);
> +void unregister_cxl_cper_notifier(struct notifier_block *nb);
> +#else
> +static inline int register_cxl_cper_notifier(struct notifier_block *nb)
> +{
> +	return 0;
> +}
> +
> +static inline void unregister_cxl_cper_notifier(struct notifier_block *nb) { }
> +#endif
> +
>   #endif /* _LINUX_CXL_EVENT_H */
>
Ira Weiny Nov. 29, 2023, 2:28 p.m. UTC | #2
Smita Koralahalli wrote:
> Hi Ira,
> 
> I tested this out. Just one correction below to make it work.
> 

[snip]

> > +
> > +#define CPER_CXL_DEVICE_ID_VALID		BIT(0)
> > +#define CPER_CXL_DEVICE_SN_VALID		BIT(1)
> > +#define CPER_CXL_COMP_EVENT_LOG_VALID		BIT(2)
> > +struct cper_cxl_event_rec {
> > +	struct {
> > +		u32 length;
> > +		u64 validation_bits;
> > +		struct cper_cxl_event_devid {
> > +			u16 vendor_id;
> > +			u16 device_id;
> > +			u8 func_num;
> > +			u8 device_num;
> > +			u8 bus_num;
> > +			u16 segment_num;
> > +			u16 slot_num; /* bits 2:0 reserved */
> > +			u8 reserved;
> > +		} device_id;
> > +		struct cper_cxl_event_sn {
> > +			u32 lower_dw;
> > +			u32 upper_dw;
> > +		} dev_serial_num;
> > +	} hdr;
> > +
> > +	union cxl_event event;
> > +} __packed;
> 
> __packed attribute just for cper_cxl_event_rec still fails to properly 
> align structure elements. Looks like, __packed attribute is needed for 
> all structs (cper_cxl_event_devid and cper_cxl_event_sn) inside 
> cper_cxl_event_rec.
> 
> Seems easier to use global pragma instead.. I could test and obtain the 
> output as expected using pragma..

I did not know that was acceptable in the kernel but I see you used it in
cper_cxl.h before...

Ok I'll do that and spin again.

Thanks so much for testing this!  I was out last week and still don't have
a test environment.

Ira
Jonathan Cameron Dec. 13, 2023, 5:13 p.m. UTC | #3
On Wed, 29 Nov 2023 06:28:01 -0800
Ira Weiny <ira.weiny@intel.com> wrote:

> Smita Koralahalli wrote:
> > Hi Ira,
> > 
> > I tested this out. Just one correction below to make it work.
> >   
> 
> [snip]
> 
> > > +
> > > +#define CPER_CXL_DEVICE_ID_VALID		BIT(0)
> > > +#define CPER_CXL_DEVICE_SN_VALID		BIT(1)
> > > +#define CPER_CXL_COMP_EVENT_LOG_VALID		BIT(2)
> > > +struct cper_cxl_event_rec {
> > > +	struct {
> > > +		u32 length;
> > > +		u64 validation_bits;
> > > +		struct cper_cxl_event_devid {
> > > +			u16 vendor_id;
> > > +			u16 device_id;
> > > +			u8 func_num;
> > > +			u8 device_num;
> > > +			u8 bus_num;
> > > +			u16 segment_num;
> > > +			u16 slot_num; /* bits 2:0 reserved */
> > > +			u8 reserved;
> > > +		} device_id;
> > > +		struct cper_cxl_event_sn {
> > > +			u32 lower_dw;
> > > +			u32 upper_dw;
> > > +		} dev_serial_num;
> > > +	} hdr;
> > > +
> > > +	union cxl_event event;
> > > +} __packed;  
> > 
> > __packed attribute just for cper_cxl_event_rec still fails to properly 
> > align structure elements. Looks like, __packed attribute is needed for 
> > all structs (cper_cxl_event_devid and cper_cxl_event_sn) inside 
> > cper_cxl_event_rec.
> > 
> > Seems easier to use global pragma instead.. I could test and obtain the 
> > output as expected using pragma..  
> 
> I did not know that was acceptable in the kernel but I see you used it in
> cper_cxl.h before...
> 
> Ok I'll do that and spin again.
> 
> Thanks so much for testing this!  I was out last week and still don't have
> a test environment.

Easy to hack into QEMU :)  Hmm. I have a CCIX patch set from years ago
somewhere that does similar. Would be easy to repurposed. Looks like
I never published them (just told people to ask if they wanted them :( ).

Anyhow, if useful I can dig them out.

> 
> Ira
Ira Weiny Dec. 13, 2023, 10:28 p.m. UTC | #4
Jonathan Cameron wrote:
> On Wed, 29 Nov 2023 06:28:01 -0800
> Ira Weiny <ira.weiny@intel.com> wrote:
> 

[snip]

> > > __packed attribute just for cper_cxl_event_rec still fails to properly 
> > > align structure elements. Looks like, __packed attribute is needed for 
> > > all structs (cper_cxl_event_devid and cper_cxl_event_sn) inside 
> > > cper_cxl_event_rec.
> > > 
> > > Seems easier to use global pragma instead.. I could test and obtain the 
> > > output as expected using pragma..  
> > 
> > I did not know that was acceptable in the kernel but I see you used it in
> > cper_cxl.h before...
> > 
> > Ok I'll do that and spin again.
> > 
> > Thanks so much for testing this!  I was out last week and still don't have
> > a test environment.
> 
> Easy to hack into QEMU :)  Hmm. I have a CCIX patch set from years ago
> somewhere that does similar. Would be easy to repurposed. Looks like
> I never published them (just told people to ask if they wanted them :( ).
> 
> Anyhow, if useful I can dig them out.

If you have a branch with them with a somewhat latest qemu that could work
too.

Ira
Jonathan Cameron Dec. 19, 2023, 5:12 p.m. UTC | #5
On Wed, 13 Dec 2023 14:28:03 -0800
Ira Weiny <ira.weiny@intel.com> wrote:

> Jonathan Cameron wrote:
> > On Wed, 29 Nov 2023 06:28:01 -0800
> > Ira Weiny <ira.weiny@intel.com> wrote:
> >   
> 
> [snip]
> 
> > > > __packed attribute just for cper_cxl_event_rec still fails to properly 
> > > > align structure elements. Looks like, __packed attribute is needed for 
> > > > all structs (cper_cxl_event_devid and cper_cxl_event_sn) inside 
> > > > cper_cxl_event_rec.
> > > > 
> > > > Seems easier to use global pragma instead.. I could test and obtain the 
> > > > output as expected using pragma..    
> > > 
> > > I did not know that was acceptable in the kernel but I see you used it in
> > > cper_cxl.h before...
> > > 
> > > Ok I'll do that and spin again.
> > > 
> > > Thanks so much for testing this!  I was out last week and still don't have
> > > a test environment.  
> > 
> > Easy to hack into QEMU :)  Hmm. I have a CCIX patch set from years ago
> > somewhere that does similar. Would be easy to repurposed. Looks like
> > I never published them (just told people to ask if they wanted them :( ).
> > 
> > Anyhow, if useful I can dig them out.  
> 
> If you have a branch with them with a somewhat latest qemu that could work
> too.
They are ancient and based on GHES emulation that got reworked before being
merged. I had a quick go at a forwards port but this is a bigger job than
I expected. May be a little while :(

Jonathan

> 
> Ira
Ira Weiny Dec. 20, 2023, 11:48 p.m. UTC | #6
Jonathan Cameron wrote:
> On Wed, 13 Dec 2023 14:28:03 -0800
> Ira Weiny <ira.weiny@intel.com> wrote:
> 
> > Jonathan Cameron wrote:
> > > On Wed, 29 Nov 2023 06:28:01 -0800
> > > Ira Weiny <ira.weiny@intel.com> wrote:
> > >   
> > 
> > [snip]
> > 
> > > > > __packed attribute just for cper_cxl_event_rec still fails to properly 
> > > > > align structure elements. Looks like, __packed attribute is needed for 
> > > > > all structs (cper_cxl_event_devid and cper_cxl_event_sn) inside 
> > > > > cper_cxl_event_rec.
> > > > > 
> > > > > Seems easier to use global pragma instead.. I could test and obtain the 
> > > > > output as expected using pragma..    
> > > > 
> > > > I did not know that was acceptable in the kernel but I see you used it in
> > > > cper_cxl.h before...
> > > > 
> > > > Ok I'll do that and spin again.
> > > > 
> > > > Thanks so much for testing this!  I was out last week and still don't have
> > > > a test environment.  
> > > 
> > > Easy to hack into QEMU :)  Hmm. I have a CCIX patch set from years ago
> > > somewhere that does similar. Would be easy to repurposed. Looks like
> > > I never published them (just told people to ask if they wanted them :( ).
> > > 
> > > Anyhow, if useful I can dig them out.  
> > 
> > If you have a branch with them with a somewhat latest qemu that could work
> > too.
> They are ancient and based on GHES emulation that got reworked before being
> merged. I had a quick go at a forwards port but this is a bigger job than
> I expected. May be a little while :(
> 

Let's not waste the time on it then.  Dan and I would like to get this
merged in 6.8 if possible.

Ira
Jonathan Cameron Jan. 3, 2024, 5:50 p.m. UTC | #7
On Tue, 19 Dec 2023 17:12:10 +0000
Jonathan Cameron <Jonathan.Cameron@Huawei.com> wrote:

> On Wed, 13 Dec 2023 14:28:03 -0800
> Ira Weiny <ira.weiny@intel.com> wrote:
> 
> > Jonathan Cameron wrote:  
> > > On Wed, 29 Nov 2023 06:28:01 -0800
> > > Ira Weiny <ira.weiny@intel.com> wrote:
> > >     
> > 
> > [snip]
> >   
> > > > > __packed attribute just for cper_cxl_event_rec still fails to properly 
> > > > > align structure elements. Looks like, __packed attribute is needed for 
> > > > > all structs (cper_cxl_event_devid and cper_cxl_event_sn) inside 
> > > > > cper_cxl_event_rec.
> > > > > 
> > > > > Seems easier to use global pragma instead.. I could test and obtain the 
> > > > > output as expected using pragma..      
> > > > 
> > > > I did not know that was acceptable in the kernel but I see you used it in
> > > > cper_cxl.h before...
> > > > 
> > > > Ok I'll do that and spin again.
> > > > 
> > > > Thanks so much for testing this!  I was out last week and still don't have
> > > > a test environment.    
> > > 
> > > Easy to hack into QEMU :)  Hmm. I have a CCIX patch set from years ago
> > > somewhere that does similar. Would be easy to repurposed. Looks like
> > > I never published them (just told people to ask if they wanted them :( ).
> > > 
> > > Anyhow, if useful I can dig them out.    
> > 
> > If you have a branch with them with a somewhat latest qemu that could work
> > too.  
> They are ancient and based on GHES emulation that got reworked before being
> merged. I had a quick go at a forwards port but this is a bigger job than
> I expected. May be a little while :(

Working again (embarrassingly I had the error source numbers reversed due
to a merge resolution that went wrong which took me a day to find). I'll flesh
out the injection but it will basically look like normal error injection
via qmp (json records) with a bonus parameter to stick them out as via
GHESv2 / CPER rather than AER internal error.  I've not figured out how
to wire HEST up for x86 emulation yet though so it's ARM virt only for now.
(HEST isn't created for x86 qemu machines whereas it is for arm virt with ras=on)
Obviously that emulation is wrong in all sorts of ways as I should be dealing
with firmware/OSPM negotiation and setting the messaging up etc but meh
- it works for exercising the code :)

On the plus side I get nice trace points using your series and Smita's one.
Quite a bit of data is 0s at the moment as I'm lazy and it's the end of the day
here - I'll fix that up later this week as I can see 'everything' in QEMU
and the register values etc are already handled via the native injection paths.

Jonathan

> 
> Jonathan
> 
> > 
> > Ira  
> 
>
Ira Weiny Jan. 3, 2024, 8:40 p.m. UTC | #8
Jonathan Cameron wrote:
> On Tue, 19 Dec 2023 17:12:10 +0000
> Jonathan Cameron <Jonathan.Cameron@Huawei.com> wrote:
> 
> > On Wed, 13 Dec 2023 14:28:03 -0800
> > Ira Weiny <ira.weiny@intel.com> wrote:
> > 
> > > Jonathan Cameron wrote:  
> > > > On Wed, 29 Nov 2023 06:28:01 -0800
> > > > Ira Weiny <ira.weiny@intel.com> wrote:
> > > >     
> > > 
> > > [snip]
> > >   
> > > > > > __packed attribute just for cper_cxl_event_rec still fails to properly 
> > > > > > align structure elements. Looks like, __packed attribute is needed for 
> > > > > > all structs (cper_cxl_event_devid and cper_cxl_event_sn) inside 
> > > > > > cper_cxl_event_rec.
> > > > > > 
> > > > > > Seems easier to use global pragma instead.. I could test and obtain the 
> > > > > > output as expected using pragma..      
> > > > > 
> > > > > I did not know that was acceptable in the kernel but I see you used it in
> > > > > cper_cxl.h before...
> > > > > 
> > > > > Ok I'll do that and spin again.
> > > > > 
> > > > > Thanks so much for testing this!  I was out last week and still don't have
> > > > > a test environment.    
> > > > 
> > > > Easy to hack into QEMU :)  Hmm. I have a CCIX patch set from years ago
> > > > somewhere that does similar. Would be easy to repurposed. Looks like
> > > > I never published them (just told people to ask if they wanted them :( ).
> > > > 
> > > > Anyhow, if useful I can dig them out.    
> > > 
> > > If you have a branch with them with a somewhat latest qemu that could work
> > > too.  
> > They are ancient and based on GHES emulation that got reworked before being
> > merged. I had a quick go at a forwards port but this is a bigger job than
> > I expected. May be a little while :(
> 
> Working again (embarrassingly I had the error source numbers reversed due
> to a merge resolution that went wrong which took me a day to find). I'll flesh
> out the injection but it will basically look like normal error injection
> via qmp (json records) with a bonus parameter to stick them out as via
> GHESv2 / CPER rather than AER internal error.  I've not figured out how
> to wire HEST up for x86 emulation yet though so it's ARM virt only for now.
> (HEST isn't created for x86 qemu machines whereas it is for arm virt with ras=on)
> Obviously that emulation is wrong in all sorts of ways as I should be dealing
> with firmware/OSPM negotiation and setting the messaging up etc but meh
> - it works for exercising the code :)
> 
> On the plus side I get nice trace points using your series and Smita's one.
> Quite a bit of data is 0s at the moment as I'm lazy and it's the end of the day
> here - I'll fix that up later this week as I can see 'everything' in QEMU
> and the register values etc are already handled via the native injection paths.

Thanks for the testing!
Ira
diff mbox series

Patch

diff --git a/drivers/firmware/efi/cper.c b/drivers/firmware/efi/cper.c
index 35c37f667781..3d0b60144a07 100644
--- a/drivers/firmware/efi/cper.c
+++ b/drivers/firmware/efi/cper.c
@@ -22,6 +22,7 @@ 
 #include <linux/aer.h>
 #include <linux/printk.h>
 #include <linux/bcd.h>
+#include <linux/cxl-event.h>
 #include <acpi/ghes.h>
 #include <ras/ras_event.h>
 #include "cper_cxl.h"
@@ -607,6 +608,20 @@  cper_estatus_print_section(const char *pfx, struct acpi_hest_generic_data *gdata
 			cper_print_prot_err(newpfx, prot_err);
 		else
 			goto err_section_too_small;
+	} else if (guid_equal(sec_type, &CPER_SEC_CXL_GEN_MEDIA) ||
+		   guid_equal(sec_type, &CPER_SEC_CXL_DRAM) ||
+		   guid_equal(sec_type, &CPER_SEC_CXL_MEM_MODULE)) {
+		struct cper_cxl_event_rec *rec = acpi_hest_get_payload(gdata);
+
+		if (rec->hdr.length <= sizeof(rec->hdr))
+			goto err_section_too_small;
+
+		if (rec->hdr.length > sizeof(*rec)) {
+			pr_err(FW_WARN "error section length is too big\n");
+			return;
+		}
+
+		cper_post_cxl_event(newpfx, sec_type, rec);
 	} else {
 		const void *err = acpi_hest_get_payload(gdata);
 
diff --git a/drivers/firmware/efi/cper_cxl.c b/drivers/firmware/efi/cper_cxl.c
index a55771b99a97..bf642962a7ba 100644
--- a/drivers/firmware/efi/cper_cxl.c
+++ b/drivers/firmware/efi/cper_cxl.c
@@ -8,6 +8,7 @@ 
  */
 
 #include <linux/cper.h>
+#include <linux/cxl-event.h>
 #include "cper_cxl.h"
 
 #define PROT_ERR_VALID_AGENT_TYPE		BIT_ULL(0)
@@ -187,3 +188,42 @@  void cper_print_prot_err(const char *pfx, const struct cper_sec_prot_err *prot_e
 			       sizeof(cxl_ras->header_log), 0);
 	}
 }
+
+/* CXL CPER notifier chain */
+static BLOCKING_NOTIFIER_HEAD(cxl_cper_chain_head);
+
+void cper_post_cxl_event(const char *pfx, guid_t *sec_type,
+			 struct cper_cxl_event_rec *rec)
+{
+	struct cxl_cper_notifier_data nd = {
+		.rec = rec,
+	};
+
+	if (!(rec->hdr.validation_bits & CPER_CXL_COMP_EVENT_LOG_VALID)) {
+		pr_err(FW_WARN "cxl event no Component Event Log present\n");
+		return;
+	}
+
+	if (guid_equal(sec_type, &CPER_SEC_CXL_GEN_MEDIA))
+		nd.event_type = CXL_CPER_EVENT_GEN_MEDIA;
+	else if (guid_equal(sec_type, &CPER_SEC_CXL_DRAM))
+		nd.event_type = CXL_CPER_EVENT_DRAM;
+	else if (guid_equal(sec_type, &CPER_SEC_CXL_MEM_MODULE))
+		nd.event_type = CXL_CPER_EVENT_MEM_MODULE;
+
+	if (blocking_notifier_call_chain(&cxl_cper_chain_head, 0, (void *)&nd)
+			== NOTIFY_BAD)
+		pr_err(FW_WARN "cxl event notifier chain failed\n");
+}
+
+int register_cxl_cper_notifier(struct notifier_block *nb)
+{
+	return blocking_notifier_chain_register(&cxl_cper_chain_head, nb);
+}
+EXPORT_SYMBOL_NS_GPL(register_cxl_cper_notifier, CXL);
+
+void unregister_cxl_cper_notifier(struct notifier_block *nb)
+{
+	blocking_notifier_chain_unregister(&cxl_cper_chain_head, nb);
+}
+EXPORT_SYMBOL_NS_GPL(unregister_cxl_cper_notifier, CXL);
diff --git a/drivers/firmware/efi/cper_cxl.h b/drivers/firmware/efi/cper_cxl.h
index 86bfcf7909ec..aa3d36493586 100644
--- a/drivers/firmware/efi/cper_cxl.h
+++ b/drivers/firmware/efi/cper_cxl.h
@@ -10,11 +10,38 @@ 
 #ifndef LINUX_CPER_CXL_H
 #define LINUX_CPER_CXL_H
 
+#include <linux/cxl-event.h>
+
 /* CXL Protocol Error Section */
 #define CPER_SEC_CXL_PROT_ERR						\
 	GUID_INIT(0x80B9EFB4, 0x52B5, 0x4DE3, 0xA7, 0x77, 0x68, 0x78,	\
 		  0x4B, 0x77, 0x10, 0x48)
 
+/* CXL Event record UUIDs are formated at GUIDs and reported in section type */
+/*
+ * General Media Event Record
+ * CXL rev 3.0 Section 8.2.9.2.1.1; Table 8-43
+ */
+#define CPER_SEC_CXL_GEN_MEDIA						\
+	GUID_INIT(0xfbcd0a77, 0xc260, 0x417f,				\
+		  0x85, 0xa9, 0x08, 0x8b, 0x16, 0x21, 0xeb, 0xa6)
+
+/*
+ * DRAM Event Record
+ * CXL rev 3.0 section 8.2.9.2.1.2; Table 8-44
+ */
+#define CPER_SEC_CXL_DRAM						\
+	GUID_INIT(0x601dcbb3, 0x9c06, 0x4eab,				\
+		  0xb8, 0xaf, 0x4e, 0x9b, 0xfb, 0x5c, 0x96, 0x24)
+
+/*
+ * Memory Module Event Record
+ * CXL rev 3.0 section 8.2.9.2.1.3; Table 8-45
+ */
+#define CPER_SEC_CXL_MEM_MODULE						\
+	GUID_INIT(0xfe927475, 0xdd59, 0x4339,				\
+		  0xa5, 0x86, 0x79, 0xba, 0xb1, 0x13, 0xb7, 0x74)
+
 #pragma pack(1)
 
 /* Compute Express Link Protocol Error Section, UEFI v2.10 sec N.2.13 */
@@ -62,5 +89,7 @@  struct cper_sec_prot_err {
 #pragma pack()
 
 void cper_print_prot_err(const char *pfx, const struct cper_sec_prot_err *prot_err);
+void cper_post_cxl_event(const char *pfx, guid_t *sec_type,
+			 struct cper_cxl_event_rec *rec);
 
 #endif //__CPER_CXL_
diff --git a/include/linux/cxl-event.h b/include/linux/cxl-event.h
index 6b689e1efc78..733ab2ab8639 100644
--- a/include/linux/cxl-event.h
+++ b/include/linux/cxl-event.h
@@ -108,4 +108,53 @@  struct cxl_event_record_raw {
 	union cxl_event event;
 } __packed;
 
+enum cxl_event_type {
+	CXL_CPER_EVENT_GEN_MEDIA,
+	CXL_CPER_EVENT_DRAM,
+	CXL_CPER_EVENT_MEM_MODULE,
+};
+
+#define CPER_CXL_DEVICE_ID_VALID		BIT(0)
+#define CPER_CXL_DEVICE_SN_VALID		BIT(1)
+#define CPER_CXL_COMP_EVENT_LOG_VALID		BIT(2)
+struct cper_cxl_event_rec {
+	struct {
+		u32 length;
+		u64 validation_bits;
+		struct cper_cxl_event_devid {
+			u16 vendor_id;
+			u16 device_id;
+			u8 func_num;
+			u8 device_num;
+			u8 bus_num;
+			u16 segment_num;
+			u16 slot_num; /* bits 2:0 reserved */
+			u8 reserved;
+		} device_id;
+		struct cper_cxl_event_sn {
+			u32 lower_dw;
+			u32 upper_dw;
+		} dev_serial_num;
+	} hdr;
+
+	union cxl_event event;
+} __packed;
+
+struct cxl_cper_notifier_data {
+	enum cxl_event_type event_type;
+	struct cper_cxl_event_rec *rec;
+};
+
+#ifdef CONFIG_UEFI_CPER
+int register_cxl_cper_notifier(struct notifier_block *nb);
+void unregister_cxl_cper_notifier(struct notifier_block *nb);
+#else
+static inline int register_cxl_cper_notifier(struct notifier_block *nb)
+{
+	return 0;
+}
+
+static inline void unregister_cxl_cper_notifier(struct notifier_block *nb) { }
+#endif
+
 #endif /* _LINUX_CXL_EVENT_H */