static const char * const proc_type_strs[] = {
        "IA32/X64",
        "IA64",
+       "ARM",
 };
 
 static const char * const proc_isa_strs[] = {
        "IA32",
        "IA64",
        "X64",
+       "ARM A32/T32",
+       "ARM A64",
 };
 
 static const char * const proc_error_type_strs[] = {
                printk("%s""IP: 0x%016llx\n", pfx, proc->ip);
 }
 
+#if defined(CONFIG_ARM64) || defined(CONFIG_ARM)
+static const char * const arm_reg_ctx_strs[] = {
+       "AArch32 general purpose registers",
+       "AArch32 EL1 context registers",
+       "AArch32 EL2 context registers",
+       "AArch32 secure context registers",
+       "AArch64 general purpose registers",
+       "AArch64 EL1 context registers",
+       "AArch64 EL2 context registers",
+       "AArch64 EL3 context registers",
+       "Misc. system register structure",
+};
+
+static void cper_print_proc_arm(const char *pfx,
+                               const struct cper_sec_proc_arm *proc)
+{
+       int i, len, max_ctx_type;
+       struct cper_arm_err_info *err_info;
+       struct cper_arm_ctx_info *ctx_info;
+       char newpfx[64];
+
+       printk("%sMIDR: 0x%016llx\n", pfx, proc->midr);
+
+       len = proc->section_length - (sizeof(*proc) +
+               proc->err_info_num * (sizeof(*err_info)));
+       if (len < 0) {
+               printk("%ssection length: %d\n", pfx, proc->section_length);
+               printk("%ssection length is too small\n", pfx);
+               printk("%sfirmware-generated error record is incorrect\n", pfx);
+               printk("%sERR_INFO_NUM is %d\n", pfx, proc->err_info_num);
+               return;
+       }
+
+       if (proc->validation_bits & CPER_ARM_VALID_MPIDR)
+               printk("%sMultiprocessor Affinity Register (MPIDR): 0x%016llx\n",
+                       pfx, proc->mpidr);
+
+       if (proc->validation_bits & CPER_ARM_VALID_AFFINITY_LEVEL)
+               printk("%serror affinity level: %d\n", pfx,
+                       proc->affinity_level);
+
+       if (proc->validation_bits & CPER_ARM_VALID_RUNNING_STATE) {
+               printk("%srunning state: 0x%x\n", pfx, proc->running_state);
+               printk("%sPower State Coordination Interface state: %d\n",
+                       pfx, proc->psci_state);
+       }
+
+       snprintf(newpfx, sizeof(newpfx), "%s%s", pfx, INDENT_SP);
+
+       err_info = (struct cper_arm_err_info *)(proc + 1);
+       for (i = 0; i < proc->err_info_num; i++) {
+               printk("%sError info structure %d:\n", pfx, i);
+
+               printk("%snum errors: %d\n", pfx, err_info->multiple_error + 1);
+
+               if (err_info->validation_bits & CPER_ARM_INFO_VALID_FLAGS) {
+                       if (err_info->flags & CPER_ARM_INFO_FLAGS_FIRST)
+                               printk("%sfirst error captured\n", newpfx);
+                       if (err_info->flags & CPER_ARM_INFO_FLAGS_LAST)
+                               printk("%slast error captured\n", newpfx);
+                       if (err_info->flags & CPER_ARM_INFO_FLAGS_PROPAGATED)
+                               printk("%spropagated error captured\n",
+                                      newpfx);
+                       if (err_info->flags & CPER_ARM_INFO_FLAGS_OVERFLOW)
+                               printk("%soverflow occurred, error info is incomplete\n",
+                                      newpfx);
+               }
+
+               printk("%serror_type: %d, %s\n", newpfx, err_info->type,
+                       err_info->type < ARRAY_SIZE(proc_error_type_strs) ?
+                       proc_error_type_strs[err_info->type] : "unknown");
+               if (err_info->validation_bits & CPER_ARM_INFO_VALID_ERR_INFO)
+                       printk("%serror_info: 0x%016llx\n", newpfx,
+                              err_info->error_info);
+               if (err_info->validation_bits & CPER_ARM_INFO_VALID_VIRT_ADDR)
+                       printk("%svirtual fault address: 0x%016llx\n",
+                               newpfx, err_info->virt_fault_addr);
+               if (err_info->validation_bits & CPER_ARM_INFO_VALID_PHYSICAL_ADDR)
+                       printk("%sphysical fault address: 0x%016llx\n",
+                               newpfx, err_info->physical_fault_addr);
+               err_info += 1;
+       }
+
+       ctx_info = (struct cper_arm_ctx_info *)err_info;
+       max_ctx_type = ARRAY_SIZE(arm_reg_ctx_strs) - 1;
+       for (i = 0; i < proc->context_info_num; i++) {
+               int size = sizeof(*ctx_info) + ctx_info->size;
+
+               printk("%sContext info structure %d:\n", pfx, i);
+               if (len < size) {
+                       printk("%ssection length is too small\n", newpfx);
+                       printk("%sfirmware-generated error record is incorrect\n", pfx);
+                       return;
+               }
+               if (ctx_info->type > max_ctx_type) {
+                       printk("%sInvalid context type: %d (max: %d)\n",
+                               newpfx, ctx_info->type, max_ctx_type);
+                       return;
+               }
+               printk("%sregister context type: %s\n", newpfx,
+                       arm_reg_ctx_strs[ctx_info->type]);
+               print_hex_dump(newpfx, "", DUMP_PREFIX_OFFSET, 16, 4,
+                               (ctx_info + 1), ctx_info->size, 0);
+               len -= size;
+               ctx_info = (struct cper_arm_ctx_info *)((long)ctx_info + size);
+       }
+
+       if (len > 0) {
+               printk("%sVendor specific error info has %u bytes:\n", pfx,
+                      len);
+               print_hex_dump(newpfx, "", DUMP_PREFIX_OFFSET, 16, 4, ctx_info,
+                               len, true);
+       }
+}
+#endif
+
 static const char * const mem_err_type_strs[] = {
        "unknown",
        "no error",
                        cper_print_pcie(newpfx, pcie, gdata);
                else
                        goto err_section_too_small;
+#if defined(CONFIG_ARM64) || defined(CONFIG_ARM)
+       } else if (!uuid_le_cmp(*sec_type, CPER_SEC_PROC_ARM)) {
+               struct cper_sec_proc_arm *arm_err = acpi_hest_get_payload(gdata);
+
+               printk("%ssection_type: ARM processor error\n", newpfx);
+               if (gdata->error_data_length >= sizeof(*arm_err))
+                       cper_print_proc_arm(newpfx, arm_err);
+               else
+                       goto err_section_too_small;
+#endif
        } else
                printk("%s""section type: unknown, %pUl\n", newpfx, sec_type);
 
 
 #define CPER_SEC_PROC_IPF                                              \
        UUID_LE(0xE429FAF1, 0x3CB7, 0x11D4, 0x0B, 0xCA, 0x07, 0x00,     \
                0x80, 0xC7, 0x3C, 0x88, 0x81)
+/* Processor Specific: ARM */
+#define CPER_SEC_PROC_ARM                                              \
+       UUID_LE(0xE19E3D16, 0xBC11, 0x11E4, 0x9C, 0xAA, 0xC2, 0x05,     \
+               0x1D, 0x5D, 0x46, 0xB0)
 /* Platform Memory */
 #define CPER_SEC_PLATFORM_MEM                                          \
        UUID_LE(0xA5BC1114, 0x6F64, 0x4EDE, 0xB8, 0x63, 0x3E, 0x83,     \
 
 #define CPER_PCIE_SLOT_SHIFT                   3
 
+#define CPER_ARM_VALID_MPIDR                   BIT(0)
+#define CPER_ARM_VALID_AFFINITY_LEVEL          BIT(1)
+#define CPER_ARM_VALID_RUNNING_STATE           BIT(2)
+#define CPER_ARM_VALID_VENDOR_INFO             BIT(3)
+
+#define CPER_ARM_INFO_VALID_MULTI_ERR          BIT(0)
+#define CPER_ARM_INFO_VALID_FLAGS              BIT(1)
+#define CPER_ARM_INFO_VALID_ERR_INFO           BIT(2)
+#define CPER_ARM_INFO_VALID_VIRT_ADDR          BIT(3)
+#define CPER_ARM_INFO_VALID_PHYSICAL_ADDR      BIT(4)
+
+#define CPER_ARM_INFO_FLAGS_FIRST              BIT(0)
+#define CPER_ARM_INFO_FLAGS_LAST               BIT(1)
+#define CPER_ARM_INFO_FLAGS_PROPAGATED         BIT(2)
+#define CPER_ARM_INFO_FLAGS_OVERFLOW           BIT(3)
+
 /*
  * All tables and structs must be byte-packed to match CPER
  * specification, since the tables are provided by the system BIOS
        __u64   mm_reg_addr;
 };
 
+/* ARM Processor Error Section */
+struct cper_sec_proc_arm {
+       __u32   validation_bits;
+       __u16   err_info_num;           /* Number of Processor Error Info */
+       __u16   context_info_num;       /* Number of Processor Context Info Records*/
+       __u32   section_length;
+       __u8    affinity_level;
+       __u8    reserved[3];            /* must be zero */
+       __u64   mpidr;
+       __u64   midr;
+       __u32   running_state;          /* Bit 0 set - Processor running. PSCI = 0 */
+       __u32   psci_state;
+};
+
+/* ARM Processor Error Information Structure */
+struct cper_arm_err_info {
+       __u8    version;
+       __u8    length;
+       __u16   validation_bits;
+       __u8    type;
+       __u16   multiple_error;
+       __u8    flags;
+       __u64   error_info;
+       __u64   virt_fault_addr;
+       __u64   physical_fault_addr;
+};
+
+/* ARM Processor Context Information Structure */
+struct cper_arm_ctx_info {
+       __u16   version;
+       __u16   type;
+       __u32   size;
+};
+
 /* Old Memory Error Section UEFI 2.1, 2.2 */
 struct cper_sec_mem_err_old {
        __u64   validation_bits;