xref: /openbmc/qemu/scripts/arm_processor_error.py (revision 92a0dcbd751d771512b9dedd97e00553181b7699)
1*4cc10308SMauro Carvalho Chehab#!/usr/bin/env python3
2*4cc10308SMauro Carvalho Chehab#
3*4cc10308SMauro Carvalho Chehab# pylint: disable=C0301,C0114,R0903,R0912,R0913,R0914,R0915,W0511
4*4cc10308SMauro Carvalho Chehab# SPDX-License-Identifier: GPL-2.0-or-later
5*4cc10308SMauro Carvalho Chehab#
6*4cc10308SMauro Carvalho Chehab# Copyright (C) 2024-2025 Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
7*4cc10308SMauro Carvalho Chehab
8*4cc10308SMauro Carvalho Chehab# TODO: current implementation has dummy defaults.
9*4cc10308SMauro Carvalho Chehab#
10*4cc10308SMauro Carvalho Chehab# For a better implementation, a QMP addition/call is needed to
11*4cc10308SMauro Carvalho Chehab# retrieve some data for ARM Processor Error injection:
12*4cc10308SMauro Carvalho Chehab#
13*4cc10308SMauro Carvalho Chehab#   - ARM registers: power_state, mpidr.
14*4cc10308SMauro Carvalho Chehab
15*4cc10308SMauro Carvalho Chehab"""
16*4cc10308SMauro Carvalho ChehabGenerate an ARM processor error CPER, compatible with
17*4cc10308SMauro Carvalho ChehabUEFI 2.9A Errata.
18*4cc10308SMauro Carvalho Chehab
19*4cc10308SMauro Carvalho ChehabInjecting such errors can be done using:
20*4cc10308SMauro Carvalho Chehab
21*4cc10308SMauro Carvalho Chehab    $ ./scripts/ghes_inject.py arm
22*4cc10308SMauro Carvalho Chehab    Error injected.
23*4cc10308SMauro Carvalho Chehab
24*4cc10308SMauro Carvalho ChehabProduces a simple CPER register, as detected on a Linux guest:
25*4cc10308SMauro Carvalho Chehab
26*4cc10308SMauro Carvalho Chehab[Hardware Error]: Hardware error from APEI Generic Hardware Error Source: 1
27*4cc10308SMauro Carvalho Chehab[Hardware Error]: event severity: recoverable
28*4cc10308SMauro Carvalho Chehab[Hardware Error]:  Error 0, type: recoverable
29*4cc10308SMauro Carvalho Chehab[Hardware Error]:   section_type: ARM processor error
30*4cc10308SMauro Carvalho Chehab[Hardware Error]:   MIDR: 0x0000000000000000
31*4cc10308SMauro Carvalho Chehab[Hardware Error]:   running state: 0x0
32*4cc10308SMauro Carvalho Chehab[Hardware Error]:   Power State Coordination Interface state: 0
33*4cc10308SMauro Carvalho Chehab[Hardware Error]:   Error info structure 0:
34*4cc10308SMauro Carvalho Chehab[Hardware Error]:   num errors: 2
35*4cc10308SMauro Carvalho Chehab[Hardware Error]:    error_type: 0x02: cache error
36*4cc10308SMauro Carvalho Chehab[Hardware Error]:    error_info: 0x000000000091000f
37*4cc10308SMauro Carvalho Chehab[Hardware Error]:     transaction type: Data Access
38*4cc10308SMauro Carvalho Chehab[Hardware Error]:     cache error, operation type: Data write
39*4cc10308SMauro Carvalho Chehab[Hardware Error]:     cache level: 2
40*4cc10308SMauro Carvalho Chehab[Hardware Error]:     processor context not corrupted
41*4cc10308SMauro Carvalho Chehab[Firmware Warn]: GHES: Unhandled processor error type 0x02: cache error
42*4cc10308SMauro Carvalho Chehab
43*4cc10308SMauro Carvalho ChehabThe ARM Processor Error message can be customized via command line
44*4cc10308SMauro Carvalho Chehabparameters. For instance:
45*4cc10308SMauro Carvalho Chehab
46*4cc10308SMauro Carvalho Chehab    $ ./scripts/ghes_inject.py arm --mpidr 0x444 --running --affinity 1 \
47*4cc10308SMauro Carvalho Chehab        --error-info 12345678 --vendor 0x13,123,4,5,1 --ctx-array 0,1,2,3,4,5 \
48*4cc10308SMauro Carvalho Chehab        -t cache tlb bus micro-arch tlb,micro-arch
49*4cc10308SMauro Carvalho Chehab    Error injected.
50*4cc10308SMauro Carvalho Chehab
51*4cc10308SMauro Carvalho ChehabInjects this error, as detected on a Linux guest:
52*4cc10308SMauro Carvalho Chehab
53*4cc10308SMauro Carvalho Chehab[Hardware Error]: Hardware error from APEI Generic Hardware Error Source: 1
54*4cc10308SMauro Carvalho Chehab[Hardware Error]: event severity: recoverable
55*4cc10308SMauro Carvalho Chehab[Hardware Error]:  Error 0, type: recoverable
56*4cc10308SMauro Carvalho Chehab[Hardware Error]:   section_type: ARM processor error
57*4cc10308SMauro Carvalho Chehab[Hardware Error]:   MIDR: 0x0000000000000000
58*4cc10308SMauro Carvalho Chehab[Hardware Error]:   Multiprocessor Affinity Register (MPIDR): 0x0000000000000000
59*4cc10308SMauro Carvalho Chehab[Hardware Error]:   error affinity level: 0
60*4cc10308SMauro Carvalho Chehab[Hardware Error]:   running state: 0x1
61*4cc10308SMauro Carvalho Chehab[Hardware Error]:   Power State Coordination Interface state: 0
62*4cc10308SMauro Carvalho Chehab[Hardware Error]:   Error info structure 0:
63*4cc10308SMauro Carvalho Chehab[Hardware Error]:   num errors: 2
64*4cc10308SMauro Carvalho Chehab[Hardware Error]:    error_type: 0x02: cache error
65*4cc10308SMauro Carvalho Chehab[Hardware Error]:    error_info: 0x0000000000bc614e
66*4cc10308SMauro Carvalho Chehab[Hardware Error]:     cache level: 2
67*4cc10308SMauro Carvalho Chehab[Hardware Error]:     processor context not corrupted
68*4cc10308SMauro Carvalho Chehab[Hardware Error]:   Error info structure 1:
69*4cc10308SMauro Carvalho Chehab[Hardware Error]:   num errors: 2
70*4cc10308SMauro Carvalho Chehab[Hardware Error]:    error_type: 0x04: TLB error
71*4cc10308SMauro Carvalho Chehab[Hardware Error]:    error_info: 0x000000000054007f
72*4cc10308SMauro Carvalho Chehab[Hardware Error]:     transaction type: Instruction
73*4cc10308SMauro Carvalho Chehab[Hardware Error]:     TLB error, operation type: Instruction fetch
74*4cc10308SMauro Carvalho Chehab[Hardware Error]:     TLB level: 1
75*4cc10308SMauro Carvalho Chehab[Hardware Error]:     processor context not corrupted
76*4cc10308SMauro Carvalho Chehab[Hardware Error]:     the error has not been corrected
77*4cc10308SMauro Carvalho Chehab[Hardware Error]:     PC is imprecise
78*4cc10308SMauro Carvalho Chehab[Hardware Error]:   Error info structure 2:
79*4cc10308SMauro Carvalho Chehab[Hardware Error]:   num errors: 2
80*4cc10308SMauro Carvalho Chehab[Hardware Error]:    error_type: 0x08: bus error
81*4cc10308SMauro Carvalho Chehab[Hardware Error]:    error_info: 0x00000080d6460fff
82*4cc10308SMauro Carvalho Chehab[Hardware Error]:     transaction type: Generic
83*4cc10308SMauro Carvalho Chehab[Hardware Error]:     bus error, operation type: Generic read (type of instruction or data request cannot be determined)
84*4cc10308SMauro Carvalho Chehab[Hardware Error]:     affinity level at which the bus error occurred: 1
85*4cc10308SMauro Carvalho Chehab[Hardware Error]:     processor context corrupted
86*4cc10308SMauro Carvalho Chehab[Hardware Error]:     the error has been corrected
87*4cc10308SMauro Carvalho Chehab[Hardware Error]:     PC is imprecise
88*4cc10308SMauro Carvalho Chehab[Hardware Error]:     Program execution can be restarted reliably at the PC associated with the error.
89*4cc10308SMauro Carvalho Chehab[Hardware Error]:     participation type: Local processor observed
90*4cc10308SMauro Carvalho Chehab[Hardware Error]:     request timed out
91*4cc10308SMauro Carvalho Chehab[Hardware Error]:     address space: External Memory Access
92*4cc10308SMauro Carvalho Chehab[Hardware Error]:     memory access attributes:0x20
93*4cc10308SMauro Carvalho Chehab[Hardware Error]:     access mode: secure
94*4cc10308SMauro Carvalho Chehab[Hardware Error]:   Error info structure 3:
95*4cc10308SMauro Carvalho Chehab[Hardware Error]:   num errors: 2
96*4cc10308SMauro Carvalho Chehab[Hardware Error]:    error_type: 0x10: micro-architectural error
97*4cc10308SMauro Carvalho Chehab[Hardware Error]:    error_info: 0x0000000078da03ff
98*4cc10308SMauro Carvalho Chehab[Hardware Error]:   Error info structure 4:
99*4cc10308SMauro Carvalho Chehab[Hardware Error]:   num errors: 2
100*4cc10308SMauro Carvalho Chehab[Hardware Error]:    error_type: 0x14: TLB error|micro-architectural error
101*4cc10308SMauro Carvalho Chehab[Hardware Error]:   Context info structure 0:
102*4cc10308SMauro Carvalho Chehab[Hardware Error]:    register context type: AArch64 EL1 context registers
103*4cc10308SMauro Carvalho Chehab[Hardware Error]:    00000000: 00000000 00000000
104*4cc10308SMauro Carvalho Chehab[Hardware Error]:   Vendor specific error info has 5 bytes:
105*4cc10308SMauro Carvalho Chehab[Hardware Error]:    00000000: 13 7b 04 05 01                                   .{...
106*4cc10308SMauro Carvalho Chehab[Firmware Warn]: GHES: Unhandled processor error type 0x02: cache error
107*4cc10308SMauro Carvalho Chehab[Firmware Warn]: GHES: Unhandled processor error type 0x04: TLB error
108*4cc10308SMauro Carvalho Chehab[Firmware Warn]: GHES: Unhandled processor error type 0x08: bus error
109*4cc10308SMauro Carvalho Chehab[Firmware Warn]: GHES: Unhandled processor error type 0x10: micro-architectural error
110*4cc10308SMauro Carvalho Chehab[Firmware Warn]: GHES: Unhandled processor error type 0x14: TLB error|micro-architectural error
111*4cc10308SMauro Carvalho Chehab"""
112*4cc10308SMauro Carvalho Chehab
113*4cc10308SMauro Carvalho Chehabimport argparse
114*4cc10308SMauro Carvalho Chehabimport re
115*4cc10308SMauro Carvalho Chehab
116*4cc10308SMauro Carvalho Chehabfrom qmp_helper import qmp, util, cper_guid
117*4cc10308SMauro Carvalho Chehab
118*4cc10308SMauro Carvalho Chehab
119*4cc10308SMauro Carvalho Chehabclass ArmProcessorEinj:
120*4cc10308SMauro Carvalho Chehab    """
121*4cc10308SMauro Carvalho Chehab    Implements ARM Processor Error injection via GHES
122*4cc10308SMauro Carvalho Chehab    """
123*4cc10308SMauro Carvalho Chehab
124*4cc10308SMauro Carvalho Chehab    DESC = """
125*4cc10308SMauro Carvalho Chehab    Generates an ARM processor error CPER, compatible with
126*4cc10308SMauro Carvalho Chehab    UEFI 2.9A Errata.
127*4cc10308SMauro Carvalho Chehab    """
128*4cc10308SMauro Carvalho Chehab
129*4cc10308SMauro Carvalho Chehab    ACPI_GHES_ARM_CPER_LENGTH = 40
130*4cc10308SMauro Carvalho Chehab    ACPI_GHES_ARM_CPER_PEI_LENGTH = 32
131*4cc10308SMauro Carvalho Chehab
132*4cc10308SMauro Carvalho Chehab    # Context types
133*4cc10308SMauro Carvalho Chehab    CONTEXT_AARCH32_EL1 = 1
134*4cc10308SMauro Carvalho Chehab    CONTEXT_AARCH64_EL1 = 5
135*4cc10308SMauro Carvalho Chehab    CONTEXT_MISC_REG = 8
136*4cc10308SMauro Carvalho Chehab
137*4cc10308SMauro Carvalho Chehab    def __init__(self, subparsers):
138*4cc10308SMauro Carvalho Chehab        """Initialize the error injection class and add subparser"""
139*4cc10308SMauro Carvalho Chehab
140*4cc10308SMauro Carvalho Chehab        # Valid choice values
141*4cc10308SMauro Carvalho Chehab        self.arm_valid_bits = {
142*4cc10308SMauro Carvalho Chehab            "mpidr":    util.bit(0),
143*4cc10308SMauro Carvalho Chehab            "affinity": util.bit(1),
144*4cc10308SMauro Carvalho Chehab            "running":  util.bit(2),
145*4cc10308SMauro Carvalho Chehab            "vendor":   util.bit(3),
146*4cc10308SMauro Carvalho Chehab        }
147*4cc10308SMauro Carvalho Chehab
148*4cc10308SMauro Carvalho Chehab        self.pei_flags = {
149*4cc10308SMauro Carvalho Chehab            "first":        util.bit(0),
150*4cc10308SMauro Carvalho Chehab            "last":         util.bit(1),
151*4cc10308SMauro Carvalho Chehab            "propagated":   util.bit(2),
152*4cc10308SMauro Carvalho Chehab            "overflow":     util.bit(3),
153*4cc10308SMauro Carvalho Chehab        }
154*4cc10308SMauro Carvalho Chehab
155*4cc10308SMauro Carvalho Chehab        self.pei_error_types = {
156*4cc10308SMauro Carvalho Chehab            "cache":        util.bit(1),
157*4cc10308SMauro Carvalho Chehab            "tlb":          util.bit(2),
158*4cc10308SMauro Carvalho Chehab            "bus":          util.bit(3),
159*4cc10308SMauro Carvalho Chehab            "micro-arch":   util.bit(4),
160*4cc10308SMauro Carvalho Chehab        }
161*4cc10308SMauro Carvalho Chehab
162*4cc10308SMauro Carvalho Chehab        self.pei_valid_bits = {
163*4cc10308SMauro Carvalho Chehab            "multiple-error":   util.bit(0),
164*4cc10308SMauro Carvalho Chehab            "flags":            util.bit(1),
165*4cc10308SMauro Carvalho Chehab            "error-info":       util.bit(2),
166*4cc10308SMauro Carvalho Chehab            "virt-addr":        util.bit(3),
167*4cc10308SMauro Carvalho Chehab            "phy-addr":         util.bit(4),
168*4cc10308SMauro Carvalho Chehab        }
169*4cc10308SMauro Carvalho Chehab
170*4cc10308SMauro Carvalho Chehab        self.data = bytearray()
171*4cc10308SMauro Carvalho Chehab
172*4cc10308SMauro Carvalho Chehab        parser = subparsers.add_parser("arm", description=self.DESC)
173*4cc10308SMauro Carvalho Chehab
174*4cc10308SMauro Carvalho Chehab        arm_valid_bits = ",".join(self.arm_valid_bits.keys())
175*4cc10308SMauro Carvalho Chehab        flags = ",".join(self.pei_flags.keys())
176*4cc10308SMauro Carvalho Chehab        error_types = ",".join(self.pei_error_types.keys())
177*4cc10308SMauro Carvalho Chehab        pei_valid_bits = ",".join(self.pei_valid_bits.keys())
178*4cc10308SMauro Carvalho Chehab
179*4cc10308SMauro Carvalho Chehab        # UEFI N.16 ARM Validation bits
180*4cc10308SMauro Carvalho Chehab        g_arm = parser.add_argument_group("ARM processor")
181*4cc10308SMauro Carvalho Chehab        g_arm.add_argument("--arm", "--arm-valid",
182*4cc10308SMauro Carvalho Chehab                           help=f"ARM valid bits: {arm_valid_bits}")
183*4cc10308SMauro Carvalho Chehab        g_arm.add_argument("-a", "--affinity",  "--level", "--affinity-level",
184*4cc10308SMauro Carvalho Chehab                           type=lambda x: int(x, 0),
185*4cc10308SMauro Carvalho Chehab                           help="Affinity level (when multiple levels apply)")
186*4cc10308SMauro Carvalho Chehab        g_arm.add_argument("-l", "--mpidr", type=lambda x: int(x, 0),
187*4cc10308SMauro Carvalho Chehab                           help="Multiprocessor Affinity Register")
188*4cc10308SMauro Carvalho Chehab        g_arm.add_argument("-i", "--midr", type=lambda x: int(x, 0),
189*4cc10308SMauro Carvalho Chehab                           help="Main ID Register")
190*4cc10308SMauro Carvalho Chehab        g_arm.add_argument("-r", "--running",
191*4cc10308SMauro Carvalho Chehab                           action=argparse.BooleanOptionalAction,
192*4cc10308SMauro Carvalho Chehab                           default=None,
193*4cc10308SMauro Carvalho Chehab                           help="Indicates if the processor is running or not")
194*4cc10308SMauro Carvalho Chehab        g_arm.add_argument("--psci", "--psci-state",
195*4cc10308SMauro Carvalho Chehab                           type=lambda x: int(x, 0),
196*4cc10308SMauro Carvalho Chehab                           help="Power State Coordination Interface - PSCI state")
197*4cc10308SMauro Carvalho Chehab
198*4cc10308SMauro Carvalho Chehab        # TODO: Add vendor-specific support
199*4cc10308SMauro Carvalho Chehab
200*4cc10308SMauro Carvalho Chehab        # UEFI N.17 bitmaps (type and flags)
201*4cc10308SMauro Carvalho Chehab        g_pei = parser.add_argument_group("ARM Processor Error Info (PEI)")
202*4cc10308SMauro Carvalho Chehab        g_pei.add_argument("-t", "--type", nargs="+",
203*4cc10308SMauro Carvalho Chehab                        help=f"one or more error types: {error_types}")
204*4cc10308SMauro Carvalho Chehab        g_pei.add_argument("-f", "--flags", nargs="*",
205*4cc10308SMauro Carvalho Chehab                        help=f"zero or more error flags: {flags}")
206*4cc10308SMauro Carvalho Chehab        g_pei.add_argument("-V", "--pei-valid", "--error-valid", nargs="*",
207*4cc10308SMauro Carvalho Chehab                        help=f"zero or more PEI valid bits: {pei_valid_bits}")
208*4cc10308SMauro Carvalho Chehab
209*4cc10308SMauro Carvalho Chehab        # UEFI N.17 Integer values
210*4cc10308SMauro Carvalho Chehab        g_pei.add_argument("-m", "--multiple-error", nargs="+",
211*4cc10308SMauro Carvalho Chehab                        help="Number of errors: 0: Single error, 1: Multiple errors, 2-65535: Error count if known")
212*4cc10308SMauro Carvalho Chehab        g_pei.add_argument("-e", "--error-info", nargs="+",
213*4cc10308SMauro Carvalho Chehab                        help="Error information (UEFI 2.10 tables N.18 to N.20)")
214*4cc10308SMauro Carvalho Chehab        g_pei.add_argument("-p", "--physical-address",  nargs="+",
215*4cc10308SMauro Carvalho Chehab                        help="Physical address")
216*4cc10308SMauro Carvalho Chehab        g_pei.add_argument("-v", "--virtual-address",  nargs="+",
217*4cc10308SMauro Carvalho Chehab                        help="Virtual address")
218*4cc10308SMauro Carvalho Chehab
219*4cc10308SMauro Carvalho Chehab        # UEFI N.21 Context
220*4cc10308SMauro Carvalho Chehab        g_ctx = parser.add_argument_group("Processor Context")
221*4cc10308SMauro Carvalho Chehab        g_ctx.add_argument("--ctx-type", "--context-type", nargs="*",
222*4cc10308SMauro Carvalho Chehab                        help="Type of the context (0=ARM32 GPR, 5=ARM64 EL1, other values supported)")
223*4cc10308SMauro Carvalho Chehab        g_ctx.add_argument("--ctx-size", "--context-size", nargs="*",
224*4cc10308SMauro Carvalho Chehab                        help="Minimal size of the context")
225*4cc10308SMauro Carvalho Chehab        g_ctx.add_argument("--ctx-array", "--context-array", nargs="*",
226*4cc10308SMauro Carvalho Chehab                        help="Comma-separated arrays for each context")
227*4cc10308SMauro Carvalho Chehab
228*4cc10308SMauro Carvalho Chehab        # Vendor-specific data
229*4cc10308SMauro Carvalho Chehab        g_vendor = parser.add_argument_group("Vendor-specific data")
230*4cc10308SMauro Carvalho Chehab        g_vendor.add_argument("--vendor", "--vendor-specific", nargs="+",
231*4cc10308SMauro Carvalho Chehab                        help="Vendor-specific byte arrays of data")
232*4cc10308SMauro Carvalho Chehab
233*4cc10308SMauro Carvalho Chehab        # Add arguments for Generic Error Data
234*4cc10308SMauro Carvalho Chehab        qmp.argparse(parser)
235*4cc10308SMauro Carvalho Chehab
236*4cc10308SMauro Carvalho Chehab        parser.set_defaults(func=self.send_cper)
237*4cc10308SMauro Carvalho Chehab
238*4cc10308SMauro Carvalho Chehab    def send_cper(self, args):
239*4cc10308SMauro Carvalho Chehab        """Parse subcommand arguments and send a CPER via QMP"""
240*4cc10308SMauro Carvalho Chehab
241*4cc10308SMauro Carvalho Chehab        qmp_cmd = qmp(args.host, args.port, args.debug)
242*4cc10308SMauro Carvalho Chehab
243*4cc10308SMauro Carvalho Chehab        # Handle Generic Error Data arguments if any
244*4cc10308SMauro Carvalho Chehab        qmp_cmd.set_args(args)
245*4cc10308SMauro Carvalho Chehab
246*4cc10308SMauro Carvalho Chehab        is_cpu_type = re.compile(r"^([\w+]+\-)?arm\-cpu$")
247*4cc10308SMauro Carvalho Chehab        cpus = qmp_cmd.search_qom("/machine/unattached/device",
248*4cc10308SMauro Carvalho Chehab                                  "type", is_cpu_type)
249*4cc10308SMauro Carvalho Chehab
250*4cc10308SMauro Carvalho Chehab        cper = {}
251*4cc10308SMauro Carvalho Chehab        pei = {}
252*4cc10308SMauro Carvalho Chehab        ctx = {}
253*4cc10308SMauro Carvalho Chehab        vendor = {}
254*4cc10308SMauro Carvalho Chehab
255*4cc10308SMauro Carvalho Chehab        arg = vars(args)
256*4cc10308SMauro Carvalho Chehab
257*4cc10308SMauro Carvalho Chehab        # Handle global parameters
258*4cc10308SMauro Carvalho Chehab        if args.arm:
259*4cc10308SMauro Carvalho Chehab            arm_valid_init = False
260*4cc10308SMauro Carvalho Chehab            cper["valid"] = util.get_choice(name="valid",
261*4cc10308SMauro Carvalho Chehab                                       value=args.arm,
262*4cc10308SMauro Carvalho Chehab                                       choices=self.arm_valid_bits,
263*4cc10308SMauro Carvalho Chehab                                       suffixes=["-error", "-err"])
264*4cc10308SMauro Carvalho Chehab        else:
265*4cc10308SMauro Carvalho Chehab            cper["valid"] = 0
266*4cc10308SMauro Carvalho Chehab            arm_valid_init = True
267*4cc10308SMauro Carvalho Chehab
268*4cc10308SMauro Carvalho Chehab        if "running" in arg:
269*4cc10308SMauro Carvalho Chehab            if args.running:
270*4cc10308SMauro Carvalho Chehab                cper["running-state"] = util.bit(0)
271*4cc10308SMauro Carvalho Chehab            else:
272*4cc10308SMauro Carvalho Chehab                cper["running-state"] = 0
273*4cc10308SMauro Carvalho Chehab        else:
274*4cc10308SMauro Carvalho Chehab            cper["running-state"] = 0
275*4cc10308SMauro Carvalho Chehab
276*4cc10308SMauro Carvalho Chehab        if arm_valid_init:
277*4cc10308SMauro Carvalho Chehab            if args.affinity:
278*4cc10308SMauro Carvalho Chehab                cper["valid"] |= self.arm_valid_bits["affinity"]
279*4cc10308SMauro Carvalho Chehab
280*4cc10308SMauro Carvalho Chehab            if args.mpidr:
281*4cc10308SMauro Carvalho Chehab                cper["valid"] |= self.arm_valid_bits["mpidr"]
282*4cc10308SMauro Carvalho Chehab
283*4cc10308SMauro Carvalho Chehab            if "running-state" in cper:
284*4cc10308SMauro Carvalho Chehab                cper["valid"] |= self.arm_valid_bits["running"]
285*4cc10308SMauro Carvalho Chehab
286*4cc10308SMauro Carvalho Chehab            if args.psci:
287*4cc10308SMauro Carvalho Chehab                cper["valid"] |= self.arm_valid_bits["running"]
288*4cc10308SMauro Carvalho Chehab
289*4cc10308SMauro Carvalho Chehab        # Handle PEI
290*4cc10308SMauro Carvalho Chehab        if not args.type:
291*4cc10308SMauro Carvalho Chehab            args.type = ["cache-error"]
292*4cc10308SMauro Carvalho Chehab
293*4cc10308SMauro Carvalho Chehab        util.get_mult_choices(
294*4cc10308SMauro Carvalho Chehab            pei,
295*4cc10308SMauro Carvalho Chehab            name="valid",
296*4cc10308SMauro Carvalho Chehab            values=args.pei_valid,
297*4cc10308SMauro Carvalho Chehab            choices=self.pei_valid_bits,
298*4cc10308SMauro Carvalho Chehab            suffixes=["-valid", "--addr"],
299*4cc10308SMauro Carvalho Chehab        )
300*4cc10308SMauro Carvalho Chehab        util.get_mult_choices(
301*4cc10308SMauro Carvalho Chehab            pei,
302*4cc10308SMauro Carvalho Chehab            name="type",
303*4cc10308SMauro Carvalho Chehab            values=args.type,
304*4cc10308SMauro Carvalho Chehab            choices=self.pei_error_types,
305*4cc10308SMauro Carvalho Chehab            suffixes=["-error", "-err"],
306*4cc10308SMauro Carvalho Chehab        )
307*4cc10308SMauro Carvalho Chehab        util.get_mult_choices(
308*4cc10308SMauro Carvalho Chehab            pei,
309*4cc10308SMauro Carvalho Chehab            name="flags",
310*4cc10308SMauro Carvalho Chehab            values=args.flags,
311*4cc10308SMauro Carvalho Chehab            choices=self.pei_flags,
312*4cc10308SMauro Carvalho Chehab            suffixes=["-error", "-cap"],
313*4cc10308SMauro Carvalho Chehab        )
314*4cc10308SMauro Carvalho Chehab        util.get_mult_int(pei, "error-info", args.error_info)
315*4cc10308SMauro Carvalho Chehab        util.get_mult_int(pei, "multiple-error", args.multiple_error)
316*4cc10308SMauro Carvalho Chehab        util.get_mult_int(pei, "phy-addr", args.physical_address)
317*4cc10308SMauro Carvalho Chehab        util.get_mult_int(pei, "virt-addr", args.virtual_address)
318*4cc10308SMauro Carvalho Chehab
319*4cc10308SMauro Carvalho Chehab        # Handle context
320*4cc10308SMauro Carvalho Chehab        util.get_mult_int(ctx, "type", args.ctx_type, allow_zero=True)
321*4cc10308SMauro Carvalho Chehab        util.get_mult_int(ctx, "minimal-size", args.ctx_size, allow_zero=True)
322*4cc10308SMauro Carvalho Chehab        util.get_mult_array(ctx, "register", args.ctx_array, allow_zero=True)
323*4cc10308SMauro Carvalho Chehab
324*4cc10308SMauro Carvalho Chehab        util.get_mult_array(vendor, "bytes", args.vendor, max_val=255)
325*4cc10308SMauro Carvalho Chehab
326*4cc10308SMauro Carvalho Chehab        # Store PEI
327*4cc10308SMauro Carvalho Chehab        pei_data = bytearray()
328*4cc10308SMauro Carvalho Chehab        default_flags  = self.pei_flags["first"]
329*4cc10308SMauro Carvalho Chehab        default_flags |= self.pei_flags["last"]
330*4cc10308SMauro Carvalho Chehab
331*4cc10308SMauro Carvalho Chehab        error_info_num = 0
332*4cc10308SMauro Carvalho Chehab
333*4cc10308SMauro Carvalho Chehab        for i, p in pei.items():        # pylint: disable=W0612
334*4cc10308SMauro Carvalho Chehab            error_info_num += 1
335*4cc10308SMauro Carvalho Chehab
336*4cc10308SMauro Carvalho Chehab            # UEFI 2.10 doesn't define how to encode error information
337*4cc10308SMauro Carvalho Chehab            # when multiple types are raised. So, provide a default only
338*4cc10308SMauro Carvalho Chehab            # if a single type is there
339*4cc10308SMauro Carvalho Chehab            if "error-info" not in p:
340*4cc10308SMauro Carvalho Chehab                if p["type"] == util.bit(1):
341*4cc10308SMauro Carvalho Chehab                    p["error-info"] = 0x0091000F
342*4cc10308SMauro Carvalho Chehab                if p["type"] == util.bit(2):
343*4cc10308SMauro Carvalho Chehab                    p["error-info"] = 0x0054007F
344*4cc10308SMauro Carvalho Chehab                if p["type"] == util.bit(3):
345*4cc10308SMauro Carvalho Chehab                    p["error-info"] = 0x80D6460FFF
346*4cc10308SMauro Carvalho Chehab                if p["type"] == util.bit(4):
347*4cc10308SMauro Carvalho Chehab                    p["error-info"] = 0x78DA03FF
348*4cc10308SMauro Carvalho Chehab
349*4cc10308SMauro Carvalho Chehab            if "valid" not in p:
350*4cc10308SMauro Carvalho Chehab                p["valid"] = 0
351*4cc10308SMauro Carvalho Chehab                if "multiple-error" in p:
352*4cc10308SMauro Carvalho Chehab                    p["valid"] |= self.pei_valid_bits["multiple-error"]
353*4cc10308SMauro Carvalho Chehab
354*4cc10308SMauro Carvalho Chehab                if "flags" in p:
355*4cc10308SMauro Carvalho Chehab                    p["valid"] |= self.pei_valid_bits["flags"]
356*4cc10308SMauro Carvalho Chehab
357*4cc10308SMauro Carvalho Chehab                if "error-info" in p:
358*4cc10308SMauro Carvalho Chehab                    p["valid"] |= self.pei_valid_bits["error-info"]
359*4cc10308SMauro Carvalho Chehab
360*4cc10308SMauro Carvalho Chehab                if "phy-addr" in p:
361*4cc10308SMauro Carvalho Chehab                    p["valid"] |= self.pei_valid_bits["phy-addr"]
362*4cc10308SMauro Carvalho Chehab
363*4cc10308SMauro Carvalho Chehab                if "virt-addr" in p:
364*4cc10308SMauro Carvalho Chehab                    p["valid"] |= self.pei_valid_bits["virt-addr"]
365*4cc10308SMauro Carvalho Chehab
366*4cc10308SMauro Carvalho Chehab            # Version
367*4cc10308SMauro Carvalho Chehab            util.data_add(pei_data, 0, 1)
368*4cc10308SMauro Carvalho Chehab
369*4cc10308SMauro Carvalho Chehab            util.data_add(pei_data,
370*4cc10308SMauro Carvalho Chehab                         self.ACPI_GHES_ARM_CPER_PEI_LENGTH, 1)
371*4cc10308SMauro Carvalho Chehab
372*4cc10308SMauro Carvalho Chehab            util.data_add(pei_data, p["valid"], 2)
373*4cc10308SMauro Carvalho Chehab            util.data_add(pei_data, p["type"], 1)
374*4cc10308SMauro Carvalho Chehab            util.data_add(pei_data, p.get("multiple-error", 1), 2)
375*4cc10308SMauro Carvalho Chehab            util.data_add(pei_data, p.get("flags", default_flags), 1)
376*4cc10308SMauro Carvalho Chehab            util.data_add(pei_data, p.get("error-info", 0), 8)
377*4cc10308SMauro Carvalho Chehab            util.data_add(pei_data, p.get("virt-addr", 0xDEADBEEF), 8)
378*4cc10308SMauro Carvalho Chehab            util.data_add(pei_data, p.get("phy-addr", 0xABBA0BAD), 8)
379*4cc10308SMauro Carvalho Chehab
380*4cc10308SMauro Carvalho Chehab        # Store Context
381*4cc10308SMauro Carvalho Chehab        ctx_data = bytearray()
382*4cc10308SMauro Carvalho Chehab        context_info_num = 0
383*4cc10308SMauro Carvalho Chehab
384*4cc10308SMauro Carvalho Chehab        if ctx:
385*4cc10308SMauro Carvalho Chehab            ret = qmp_cmd.send_cmd("query-target", may_open=True)
386*4cc10308SMauro Carvalho Chehab
387*4cc10308SMauro Carvalho Chehab            default_ctx = self.CONTEXT_MISC_REG
388*4cc10308SMauro Carvalho Chehab
389*4cc10308SMauro Carvalho Chehab            if "arch" in ret:
390*4cc10308SMauro Carvalho Chehab                if ret["arch"] == "aarch64":
391*4cc10308SMauro Carvalho Chehab                    default_ctx = self.CONTEXT_AARCH64_EL1
392*4cc10308SMauro Carvalho Chehab                elif ret["arch"] == "arm":
393*4cc10308SMauro Carvalho Chehab                    default_ctx = self.CONTEXT_AARCH32_EL1
394*4cc10308SMauro Carvalho Chehab
395*4cc10308SMauro Carvalho Chehab            for k in sorted(ctx.keys()):
396*4cc10308SMauro Carvalho Chehab                context_info_num += 1
397*4cc10308SMauro Carvalho Chehab
398*4cc10308SMauro Carvalho Chehab                if "type" not in ctx[k]:
399*4cc10308SMauro Carvalho Chehab                    ctx[k]["type"] = default_ctx
400*4cc10308SMauro Carvalho Chehab
401*4cc10308SMauro Carvalho Chehab                if "register" not in ctx[k]:
402*4cc10308SMauro Carvalho Chehab                    ctx[k]["register"] = []
403*4cc10308SMauro Carvalho Chehab
404*4cc10308SMauro Carvalho Chehab                reg_size = len(ctx[k]["register"])
405*4cc10308SMauro Carvalho Chehab                size = 0
406*4cc10308SMauro Carvalho Chehab
407*4cc10308SMauro Carvalho Chehab                if "minimal-size" in ctx:
408*4cc10308SMauro Carvalho Chehab                    size = ctx[k]["minimal-size"]
409*4cc10308SMauro Carvalho Chehab
410*4cc10308SMauro Carvalho Chehab                size = max(size, reg_size)
411*4cc10308SMauro Carvalho Chehab
412*4cc10308SMauro Carvalho Chehab                size = (size + 1) % 0xFFFE
413*4cc10308SMauro Carvalho Chehab
414*4cc10308SMauro Carvalho Chehab                # Version
415*4cc10308SMauro Carvalho Chehab                util.data_add(ctx_data, 0, 2)
416*4cc10308SMauro Carvalho Chehab
417*4cc10308SMauro Carvalho Chehab                util.data_add(ctx_data, ctx[k]["type"], 2)
418*4cc10308SMauro Carvalho Chehab
419*4cc10308SMauro Carvalho Chehab                util.data_add(ctx_data, 8 * size, 4)
420*4cc10308SMauro Carvalho Chehab
421*4cc10308SMauro Carvalho Chehab                for r in ctx[k]["register"]:
422*4cc10308SMauro Carvalho Chehab                    util.data_add(ctx_data, r, 8)
423*4cc10308SMauro Carvalho Chehab
424*4cc10308SMauro Carvalho Chehab                for i in range(reg_size, size):   # pylint: disable=W0612
425*4cc10308SMauro Carvalho Chehab                    util.data_add(ctx_data, 0, 8)
426*4cc10308SMauro Carvalho Chehab
427*4cc10308SMauro Carvalho Chehab        # Vendor-specific bytes are not grouped
428*4cc10308SMauro Carvalho Chehab        vendor_data = bytearray()
429*4cc10308SMauro Carvalho Chehab        if vendor:
430*4cc10308SMauro Carvalho Chehab            for k in sorted(vendor.keys()):
431*4cc10308SMauro Carvalho Chehab                for b in vendor[k]["bytes"]:
432*4cc10308SMauro Carvalho Chehab                    util.data_add(vendor_data, b, 1)
433*4cc10308SMauro Carvalho Chehab
434*4cc10308SMauro Carvalho Chehab        # Encode ARM Processor Error
435*4cc10308SMauro Carvalho Chehab        data = bytearray()
436*4cc10308SMauro Carvalho Chehab
437*4cc10308SMauro Carvalho Chehab        util.data_add(data, cper["valid"], 4)
438*4cc10308SMauro Carvalho Chehab
439*4cc10308SMauro Carvalho Chehab        util.data_add(data, error_info_num, 2)
440*4cc10308SMauro Carvalho Chehab        util.data_add(data, context_info_num, 2)
441*4cc10308SMauro Carvalho Chehab
442*4cc10308SMauro Carvalho Chehab        # Calculate the length of the CPER data
443*4cc10308SMauro Carvalho Chehab        cper_length = self.ACPI_GHES_ARM_CPER_LENGTH
444*4cc10308SMauro Carvalho Chehab        cper_length += len(pei_data)
445*4cc10308SMauro Carvalho Chehab        cper_length += len(vendor_data)
446*4cc10308SMauro Carvalho Chehab        cper_length += len(ctx_data)
447*4cc10308SMauro Carvalho Chehab        util.data_add(data, cper_length, 4)
448*4cc10308SMauro Carvalho Chehab
449*4cc10308SMauro Carvalho Chehab        util.data_add(data, arg.get("affinity-level", 0), 1)
450*4cc10308SMauro Carvalho Chehab
451*4cc10308SMauro Carvalho Chehab        # Reserved
452*4cc10308SMauro Carvalho Chehab        util.data_add(data, 0, 3)
453*4cc10308SMauro Carvalho Chehab
454*4cc10308SMauro Carvalho Chehab        if "midr-el1" not in arg:
455*4cc10308SMauro Carvalho Chehab            if cpus:
456*4cc10308SMauro Carvalho Chehab                cmd_arg = {
457*4cc10308SMauro Carvalho Chehab                    'path': cpus[0],
458*4cc10308SMauro Carvalho Chehab                    'property': "midr"
459*4cc10308SMauro Carvalho Chehab                }
460*4cc10308SMauro Carvalho Chehab                ret = qmp_cmd.send_cmd("qom-get", cmd_arg, may_open=True)
461*4cc10308SMauro Carvalho Chehab                if isinstance(ret, int):
462*4cc10308SMauro Carvalho Chehab                    arg["midr-el1"] = ret
463*4cc10308SMauro Carvalho Chehab
464*4cc10308SMauro Carvalho Chehab        util.data_add(data, arg.get("mpidr-el1", 0), 8)
465*4cc10308SMauro Carvalho Chehab        util.data_add(data, arg.get("midr-el1", 0), 8)
466*4cc10308SMauro Carvalho Chehab        util.data_add(data, cper["running-state"], 4)
467*4cc10308SMauro Carvalho Chehab        util.data_add(data, arg.get("psci-state", 0), 4)
468*4cc10308SMauro Carvalho Chehab
469*4cc10308SMauro Carvalho Chehab        # Add PEI
470*4cc10308SMauro Carvalho Chehab        data.extend(pei_data)
471*4cc10308SMauro Carvalho Chehab        data.extend(ctx_data)
472*4cc10308SMauro Carvalho Chehab        data.extend(vendor_data)
473*4cc10308SMauro Carvalho Chehab
474*4cc10308SMauro Carvalho Chehab        self.data = data
475*4cc10308SMauro Carvalho Chehab
476*4cc10308SMauro Carvalho Chehab        qmp_cmd.send_cper(cper_guid.CPER_PROC_ARM, self.data)
477