diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 8782782..b0d1128 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -541,6 +541,7 @@ static void *spapr_create_fdt_skel(hwaddr initrd_base,
         refpoints, sizeof(refpoints))));
 
     _FDT((fdt_property_cell(fdt, "rtas-error-log-max", RTAS_ERROR_LOG_MAX)));
+    _FDT((fdt_property_cell(fdt, "rtas-event-scan-rate", RTAS_EVENT_SCAN_RATE)));
 
     /*
      * According to PAPR, rtas ibm,os-term does not guarantee a return
diff --git a/hw/ppc/spapr_events.c b/hw/ppc/spapr_events.c
index c634a3b..be82815 100644
--- a/hw/ppc/spapr_events.c
+++ b/hw/ppc/spapr_events.c
@@ -236,17 +236,18 @@ void spapr_events_fdt_skel(void *fdt, uint32_t check_exception_irq)
     _FDT((fdt_end_node(fdt)));
 }
 
-static void rtas_event_log_queue(int log_type, void *data)
+static void rtas_event_log_queue(int log_type, void *data, bool exception)
 {
     sPAPREventLogEntry *entry = g_new(sPAPREventLogEntry, 1);
 
     g_assert(data);
     entry->log_type = log_type;
+    entry->exception = exception;
     entry->data = data;
     QTAILQ_INSERT_TAIL(&spapr->pending_events, entry, next);
 }
 
-static sPAPREventLogEntry *rtas_event_log_dequeue(uint32_t event_mask)
+static sPAPREventLogEntry *rtas_event_log_dequeue(uint32_t event_mask, bool exception)
 {
     sPAPREventLogEntry *entry = NULL;
 
@@ -256,6 +257,10 @@ static sPAPREventLogEntry *rtas_event_log_dequeue(uint32_t event_mask)
     }
 
     QTAILQ_FOREACH(entry, &spapr->pending_events, next) {
+        if (entry->exception != exception) {
+            continue;
+        }
+
         /* EPOW and hotplug events are surfaced in the same manner */
         if (entry->log_type == RTAS_LOG_TYPE_EPOW ||
             entry->log_type == RTAS_LOG_TYPE_HOTPLUG) {
@@ -270,7 +275,7 @@ static sPAPREventLogEntry *rtas_event_log_dequeue(uint32_t event_mask)
     return entry;
 }
 
-static bool rtas_event_log_contains(uint32_t event_mask)
+static bool rtas_event_log_contains(uint32_t event_mask, bool exception)
 {
     sPAPREventLogEntry *entry = NULL;
 
@@ -280,6 +285,10 @@ static bool rtas_event_log_contains(uint32_t event_mask)
     }
 
     QTAILQ_FOREACH(entry, &spapr->pending_events, next) {
+        if (entry->exception != exception) {
+            continue;
+        }
+
         /* EPOW and hotplug events are surfaced in the same manner */
         if (entry->log_type == RTAS_LOG_TYPE_EPOW ||
             entry->log_type == RTAS_LOG_TYPE_HOTPLUG) {
@@ -367,7 +376,7 @@ static void spapr_powerdown_req(Notifier *n, void *opaque)
     epow->event_modifier = RTAS_LOG_V6_EPOW_MODIFIER_NORMAL;
     epow->extended_modifier = RTAS_LOG_V6_EPOW_XMODIFIER_PARTITION_SPECIFIC;
 
-    rtas_event_log_queue(RTAS_LOG_TYPE_EPOW, new_epow);
+    rtas_event_log_queue(RTAS_LOG_TYPE_EPOW, new_epow, true);
 
     qemu_irq_pulse(xics_get_qirq(spapr->icp, spapr->check_exception_irq));
 }
@@ -428,7 +437,7 @@ static void spapr_hotplug_req_event(sPAPRDRConnector *drc, uint8_t hp_action)
         return;
     }
 
-    rtas_event_log_queue(RTAS_LOG_TYPE_HOTPLUG, new_hp);
+    rtas_event_log_queue(RTAS_LOG_TYPE_HOTPLUG, new_hp, true);
 
     qemu_irq_pulse(xics_get_qirq(spapr->icp, spapr->check_exception_irq));
 }
@@ -466,7 +475,7 @@ static void check_exception(PowerPCCPU *cpu, sPAPREnvironment *spapr,
         xinfo |= (uint64_t)rtas_ld(args, 6) << 32;
     }
 
-    event = rtas_event_log_dequeue(mask);
+    event = rtas_event_log_dequeue(mask, true);
     if (!event) {
         goto out_no_events;
     }
@@ -488,7 +497,7 @@ static void check_exception(PowerPCCPU *cpu, sPAPREnvironment *spapr,
      * do the latter here, since our code relies on edge-triggered
      * interrupts.
      */
-    if (rtas_event_log_contains(mask)) {
+    if (rtas_event_log_contains(mask, true)) {
         qemu_irq_pulse(xics_get_qirq(spapr->icp, spapr->check_exception_irq));
     }
 
@@ -498,6 +507,46 @@ out_no_events:
     rtas_st(rets, 0, RTAS_OUT_NO_ERRORS_FOUND);
 }
 
+static void event_scan(PowerPCCPU *cpu, sPAPREnvironment *spapr,
+                       uint32_t token, uint32_t nargs,
+                       target_ulong args,
+                       uint32_t nret, target_ulong rets)
+{
+    uint32_t mask, buf, len, event_len;
+    sPAPREventLogEntry *event;
+    struct rtas_error_log *hdr;
+
+    if (nargs != 4 || nret != 1) {
+        rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
+        return;
+    }
+
+    mask = rtas_ld(args, 0);
+    buf = rtas_ld(args, 2);
+    len = rtas_ld(args, 3);
+
+    event = rtas_event_log_dequeue(mask, false);
+    if (!event) {
+        goto out_no_events;
+    }
+
+    hdr = event->data;
+    event_len = be32_to_cpu(hdr->extended_length) + sizeof(*hdr);
+
+    if (event_len < len) {
+        len = event_len;
+    }
+
+    cpu_physical_memory_write(buf, event->data, len);
+    rtas_st(rets, 0, RTAS_OUT_SUCCESS);
+    g_free(event->data);
+    g_free(event);
+    return;
+
+out_no_events:
+    rtas_st(rets, 0, RTAS_OUT_NO_ERRORS_FOUND);
+}
+
 void spapr_events_init(sPAPREnvironment *spapr)
 {
     QTAILQ_INIT(&spapr->pending_events);
@@ -506,4 +555,5 @@ void spapr_events_init(sPAPREnvironment *spapr)
     qemu_register_powerdown_notifier(&spapr->epow_notifier);
     spapr_rtas_register(RTAS_CHECK_EXCEPTION, "check-exception",
                         check_exception);
+    spapr_rtas_register(RTAS_EVENT_SCAN, "event-scan", event_scan);
 }
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index 4935a7b..4ab289b 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -506,6 +506,8 @@ int spapr_rtas_device_tree_setup(void *fdt, hwaddr rtas_addr,
 
 #define RTAS_ERROR_LOG_MAX      2048
 
+#define RTAS_EVENT_SCAN_RATE    1
+
 typedef struct sPAPRTCETable sPAPRTCETable;
 
 #define TYPE_SPAPR_TCE_TABLE "spapr-tce-table"
@@ -529,6 +531,7 @@ struct sPAPRTCETable {
 
 struct sPAPREventLogEntry {
     int log_type;
+    bool exception;
     void *data;
     QTAILQ_ENTRY(sPAPREventLogEntry) next;
 };
