1
Hi Michael,
2
3
Could you please merge this series for ACPI stuff? All patches were already
4
reviewed by Igor. The changes against v4 are just on some patch descriptions,
5
plus the addition of Reviewed-by. No Code changes.
6
7
Thanks,
8
Mauro
9
10
-
11
12
During the development of a patch series meant to allow GHESv2 error injections,
1
During the development of a patch series meant to allow GHESv2 error injections,
13
it was requested a change on how CPER offsets are calculated, by adding a new
2
it was requested a change on how CPER offsets are calculated, by adding a new
14
BIOS pointer and reworking the GHES logic. See:
3
BIOS pointer and reworking the GHES logic. See:
15
4
16
https://lore.kernel.org/qemu-devel/cover.1726293808.git.mchehab+huawei@kernel.org/
5
https://lore.kernel.org/qemu-devel/cover.1726293808.git.mchehab+huawei@kernel.org/
...
...
25
The next series will contain the shift to use offsets from the location of the
14
The next series will contain the shift to use offsets from the location of the
26
HEST table, together with a migration logic to make it compatible with 9.1.
15
HEST table, together with a migration logic to make it compatible with 9.1.
27
16
28
---
17
---
29
18
30
v5:
31
- some changes at patches description and added some R-B;
32
- no changes at the code.
33
34
v4:
35
- merged a patch renaming the function which calculate offsets to:
36
get_hw_error_offsets(), to avoid the need of such change at the next
37
patch series;
38
- removed a functional change at the logic which makes
39
the GHES record generation more generic;
40
- a couple of trivial changes on patch descriptions and line break cleanups.
41
42
v3:
19
v3:
43
- improved some patch descriptions;
20
- improved some patch descriptions;
44
- some patches got reordered to better reflect the changes;
21
- some patches got reordered to better reflect the changes;
45
- patch v2 08/15: acpi/ghes: Prepare to support multiple sources on ghes
22
- patch v2 08/15: acpi/ghes: Prepare to support multiple sources on ghes
46
was split on two patches. The first one is in this cleanup series:
23
was split on two patches. The first one is in this cleanup series:
...
...
52
v2:
29
v2:
53
- some indentation fixes;
30
- some indentation fixes;
54
- some description improvements;
31
- some description improvements;
55
- fixed a badly-solved merge conflict that ended renaming a parameter.
32
- fixed a badly-solved merge conflict that ended renaming a parameter.
56
33
57
Mauro Carvalho Chehab (31):
34
35
Mauro Carvalho Chehab (15):
58
acpi/ghes: get rid of ACPI_HEST_SRC_ID_RESERVED
36
acpi/ghes: get rid of ACPI_HEST_SRC_ID_RESERVED
59
acpi/ghes: simplify acpi_ghes_record_errors() code
37
acpi/ghes: simplify acpi_ghes_record_errors() code
60
acpi/ghes: simplify the per-arch caller to build HEST table
38
acpi/ghes: simplify the per-arch caller to build HEST table
61
acpi/ghes: better handle source_id and notification
39
acpi/ghes: better handle source_id and notification
62
acpi/ghes: Fix acpi_ghes_record_errors() argument
40
acpi/ghes: Fix acpi_ghes_record_errors() argument
63
acpi/ghes: Remove a duplicated out of bounds check
41
acpi/ghes: Remove a duplicated out of bounds check
64
acpi/ghes: Change the type for source_id
42
acpi/ghes: Change the type for source_id
65
acpi/ghes: don't check if physical_address is not zero
66
acpi/ghes: make the GHES record generation more generic
43
acpi/ghes: make the GHES record generation more generic
67
acpi/ghes: better name GHES memory error function
44
acpi/ghes: better name GHES memory error function
68
acpi/ghes: don't crash QEMU if ghes GED is not found
45
acpi/ghes: don't crash QEMU if ghes GED is not found
69
acpi/ghes: rename etc/hardware_error file macros
46
acpi/ghes: rename etc/hardware_error file macros
70
acpi/ghes: better name the offset of the hardware error firmware
47
acpi/ghes: better name the offset of the hardware error firmware
71
acpi/ghes: Prepare to support multiple sources on ghes
72
acpi/ghes: add a firmware file with HEST address
73
acpi/ghes: Use HEST table offsets when preparing GHES records
74
acpi/generic_event_device: Update GHES migration to cover hest addr
75
acpi/generic_event_device: add logic to detect if HEST addr is
76
available
77
acpi/ghes: add a notifier to notify when error data is ready
78
acpi/generic_event_device: add an APEI error device
79
arm/virt: Wire up a GED error device for ACPI / GHES
80
qapi/acpi-hest: add an interface to do generic CPER error injection
81
scripts/ghes_inject: add a script to generate GHES error inject
82
target/arm: add an experimental mpidr arm cpu property object
83
scripts/arm_processor_error.py: retrieve mpidr if not filled
84
acpi/ghes: move offset calculus to a separate function
48
acpi/ghes: move offset calculus to a separate function
85
DEBUG
86
acpi/ghes: Change ghes fill logic to work with only one source
49
acpi/ghes: Change ghes fill logic to work with only one source
87
HACK: use GPIO as source ID for virt-9.1 machines
88
docs: acpi_hest_ghes: fix documentation for CPER size
50
docs: acpi_hest_ghes: fix documentation for CPER size
89
FIXME: acpi/ghes: properly set data record size
90
51
91
MAINTAINERS | 10 +
52
docs/specs/acpi_hest_ghes.rst | 6 +-
92
docs/specs/acpi_hest_ghes.rst | 6 +-
53
hw/acpi/generic_event_device.c | 4 +-
93
hw/acpi/Kconfig | 5 +
54
hw/acpi/ghes-stub.c | 2 +-
94
hw/acpi/aml-build.c | 10 +
55
hw/acpi/ghes.c | 256 +++++++++++++++++++--------------
95
hw/acpi/generic_event_device.c | 42 +-
56
hw/arm/virt-acpi-build.c | 5 +-
96
hw/acpi/ghes-stub.c | 2 +-
57
include/hw/acpi/ghes.h | 17 ++-
97
hw/acpi/ghes.c | 391 ++++++++++----
58
target/arm/kvm.c | 3 +-
98
hw/acpi/ghes_cper.c | 32 ++
59
7 files changed, 171 insertions(+), 122 deletions(-)
99
hw/acpi/ghes_cper_stub.c | 19 +
100
hw/acpi/meson.build | 2 +
101
hw/arm/virt-acpi-build.c | 36 +-
102
hw/arm/virt.c | 19 +-
103
hw/core/machine.c | 2 +
104
include/hw/acpi/acpi_dev_interface.h | 1 +
105
include/hw/acpi/aml-build.h | 2 +
106
include/hw/acpi/generic_event_device.h | 1 +
107
include/hw/acpi/ghes.h | 39 +-
108
include/hw/arm/virt.h | 2 +
109
qapi/acpi-hest.json | 35 ++
110
qapi/meson.build | 1 +
111
qapi/qapi-schema.json | 1 +
112
scripts/arm_processor_error.py | 390 ++++++++++++++
113
scripts/ghes_inject.py | 51 ++
114
scripts/qmp_helper.py | 702 +++++++++++++++++++++++++
115
target/arm/cpu.c | 1 +
116
target/arm/cpu.h | 1 +
117
target/arm/helper.c | 10 +-
118
target/arm/kvm.c | 2 +-
119
28 files changed, 1678 insertions(+), 137 deletions(-)
120
create mode 100644 hw/acpi/ghes_cper.c
121
create mode 100644 hw/acpi/ghes_cper_stub.c
122
create mode 100644 qapi/acpi-hest.json
123
create mode 100644 scripts/arm_processor_error.py
124
create mode 100755 scripts/ghes_inject.py
125
create mode 100644 scripts/qmp_helper.py
126
60
127
--
61
--
128
2.47.1
62
2.47.0
diff view generated by jsdifflib
...
...
54
+ ACPI_GHES_ERROR_SOURCE_COUNT
54
+ ACPI_GHES_ERROR_SOURCE_COUNT
55
};
55
};
56
56
57
typedef struct AcpiGhesState {
57
typedef struct AcpiGhesState {
58
--
58
--
59
2.47.1
59
2.47.0
diff view generated by jsdifflib
...
...
83
+ error_report("can not find Generic Error Status Block");
83
+ error_report("can not find Generic Error Status Block");
84
}
84
}
85
85
86
return ret;
86
return ret;
87
--
87
--
88
2.47.1
88
2.47.0
diff view generated by jsdifflib
...
...
89
+ BIOSLinker *linker,
89
+ BIOSLinker *linker,
90
const char *oem_id, const char *oem_table_id);
90
const char *oem_id, const char *oem_table_id);
91
void acpi_ghes_add_fw_cfg(AcpiGhesState *vms, FWCfgState *s,
91
void acpi_ghes_add_fw_cfg(AcpiGhesState *vms, FWCfgState *s,
92
GArray *hardware_errors);
92
GArray *hardware_errors);
93
--
93
--
94
2.47.1
94
2.47.0
diff view generated by jsdifflib
...
...
14
fields. Move it to two independent parameters, allowing the
14
fields. Move it to two independent parameters, allowing the
15
caller function to fill both.
15
caller function to fill both.
16
16
17
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
17
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
18
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
18
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
19
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
19
20
---
20
---
21
21
22
Chenges from v10:
22
Chenges from v10:
23
23
24
- Some changes got moved to the previous patch.
24
- Some changes got moved to the previous patch.
...
...
82
+ ACPI_GHES_NOTIFY_SEA, ACPI_HEST_SRC_ID_SEA);
82
+ ACPI_GHES_NOTIFY_SEA, ACPI_HEST_SRC_ID_SEA);
83
83
84
acpi_table_end(linker, &table);
84
acpi_table_end(linker, &table);
85
}
85
}
86
--
86
--
87
2.47.1
87
2.47.0
diff view generated by jsdifflib
...
...
30
+int acpi_ghes_record_errors(uint8_t source_id, uint64_t error_physical_addr);
30
+int acpi_ghes_record_errors(uint8_t source_id, uint64_t error_physical_addr);
31
31
32
/**
32
/**
33
* acpi_ghes_present: Report whether ACPI GHES table is present
33
* acpi_ghes_present: Report whether ACPI GHES table is present
34
--
34
--
35
2.47.1
35
2.47.0
diff view generated by jsdifflib
...
...
23
+ start_addr += source_id * sizeof(uint64_t);
23
+ start_addr += source_id * sizeof(uint64_t);
24
24
25
cpu_physical_memory_read(start_addr, &error_block_addr,
25
cpu_physical_memory_read(start_addr, &error_block_addr,
26
sizeof(error_block_addr));
26
sizeof(error_block_addr));
27
--
27
--
28
2.47.1
28
2.47.0
diff view generated by jsdifflib
...
...
6
6
7
HEST source ID is actually a 16-bit value.
7
HEST source ID is actually a 16-bit value.
8
8
9
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
9
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
10
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
10
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
11
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
12
---
11
---
13
hw/acpi/ghes-stub.c | 2 +-
12
hw/acpi/ghes-stub.c | 2 +-
14
hw/acpi/ghes.c | 2 +-
13
hw/acpi/ghes.c | 2 +-
15
include/hw/acpi/ghes.h | 2 +-
14
include/hw/acpi/ghes.h | 2 +-
16
3 files changed, 3 insertions(+), 3 deletions(-)
15
3 files changed, 3 insertions(+), 3 deletions(-)
...
...
53
+int acpi_ghes_record_errors(uint16_t source_id, uint64_t error_physical_addr);
52
+int acpi_ghes_record_errors(uint16_t source_id, uint64_t error_physical_addr);
54
53
55
/**
54
/**
56
* acpi_ghes_present: Report whether ACPI GHES table is present
55
* acpi_ghes_present: Report whether ACPI GHES table is present
57
--
56
--
58
2.47.1
57
2.47.0
diff view generated by jsdifflib
Deleted patch
1
The 'physical_address' value is a faulty page. As such, 0 is
2
as valid as any other value.
3
1
4
Suggested-by: Igor Mammedov <imammedo@redhat.com>
5
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
6
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
7
---
8
hw/acpi/ghes.c | 4 ----
9
1 file changed, 4 deletions(-)
10
11
diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/acpi/ghes.c
14
+++ b/hw/acpi/ghes.c
15
@@ -XXX,XX +XXX,XX @@ int acpi_ghes_record_errors(uint16_t source_id, uint64_t physical_address)
16
17
start_addr = le64_to_cpu(ags->ghes_addr_le);
18
19
- if (!physical_address) {
20
- return -1;
21
- }
22
-
23
start_addr += source_id * sizeof(uint64_t);
24
25
cpu_physical_memory_read(start_addr, &error_block_addr,
26
--
27
2.47.1
diff view generated by jsdifflib
1
Split the code into separate functions to allow using the
1
Split the code into separate functions to allow using the
2
common CPER filling code by different error sources.
2
common CPER filling code by different error sources.
3
3
4
The generic code was moved to ghes_record_cper_errors(),
4
The generic code was moved to ghes_record_cper_errors(),
5
and ghes_gen_err_data_uncorrectable_recoverable() now contains
5
and ghes_gen_err_data_uncorrectable_recoverable() now contains
6
only a logic to fill the Generic Error Data part of the record,
6
only a logic to fill GEGB part of the record.
7
as described at:
8
9
    ACPI 6.2: 18.3.2.7.1 Generic Error Data
10
7
11
The remaining code to generate a memory error now belongs to
8
The remaining code to generate a memory error now belongs to
12
acpi_ghes_record_errors() function.
9
acpi_ghes_record_errors() function.
13
10
14
A further patch will give it a better name.
11
A further patch will give it a better name.
15
12
16
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
13
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
17
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
18
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
19
---
14
---
20
hw/acpi/ghes.c | 121 ++++++++++++++++++++++++-----------------
15
hw/acpi/ghes.c | 122 +++++++++++++++++++++++------------------
21
include/hw/acpi/ghes.h | 3 +
16
include/hw/acpi/ghes.h | 3 +
22
2 files changed, 73 insertions(+), 51 deletions(-)
17
2 files changed, 73 insertions(+), 52 deletions(-)
23
18
24
diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c
19
diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c
25
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
26
--- a/hw/acpi/ghes.c
21
--- a/hw/acpi/ghes.c
27
+++ b/hw/acpi/ghes.c
22
+++ b/hw/acpi/ghes.c
...
...
46
/* invalid fru id: ACPI 4.0: 17.3.2.6.1 Generic Error Data,
41
/* invalid fru id: ACPI 4.0: 17.3.2.6.1 Generic Error Data,
47
* Table 17-13 Generic Error Data Entry
42
* Table 17-13 Generic Error Data Entry
48
*/
43
*/
49
QemuUUID fru_id = {};
44
QemuUUID fru_id = {};
50
- uint32_t data_length;
45
- uint32_t data_length;
51
-
46
52
- block = g_array_new(false, true /* clear */, 1);
47
- block = g_array_new(false, true /* clear */, 1);
53
-
48
-
54
- /* This is the length if adding a new generic error data entry*/
49
- /* This is the length if adding a new generic error data entry*/
55
- data_length = ACPI_GHES_DATA_LENGTH + ACPI_GHES_MEM_CPER_LENGTH;
50
- data_length = ACPI_GHES_DATA_LENGTH + ACPI_GHES_MEM_CPER_LENGTH;
56
- /*
51
/*
57
- * It should not run out of the preallocated memory if adding a new generic
52
- * It should not run out of the preallocated memory if adding a new generic
58
- * error data entry
53
- * error data entry
59
- */
54
+ * Calculate the size with this block. No need to check for
55
+ * too big CPER, as CPER size is checked at ghes_record_cper_errors()
56
*/
60
- assert((data_length + ACPI_GHES_GESB_SIZE) <=
57
- assert((data_length + ACPI_GHES_GESB_SIZE) <=
61
- ACPI_GHES_MAX_RAW_DATA_LENGTH);
58
- ACPI_GHES_MAX_RAW_DATA_LENGTH);
59
+ data_length += ACPI_GHES_GESB_SIZE;
62
60
63
/* Build the new generic error status block header */
61
/* Build the new generic error status block header */
64
acpi_ghes_generic_error_status(block, ACPI_GEBS_UNCORRECTABLE,
62
acpi_ghes_generic_error_status(block, ACPI_GEBS_UNCORRECTABLE,
65
0, 0, data_length, ACPI_CPER_SEV_RECOVERABLE);
63
0, 0, data_length, ACPI_CPER_SEV_RECOVERABLE);
66
64
...
...
103
+ }
101
+ }
104
102
105
acpi_ged_state = ACPI_GED(object_resolve_path_type("", TYPE_ACPI_GED,
103
acpi_ged_state = ACPI_GED(object_resolve_path_type("", TYPE_ACPI_GED,
106
NULL));
104
NULL));
107
@@ -XXX,XX +XXX,XX @@ int acpi_ghes_record_errors(uint16_t source_id, uint64_t physical_address)
105
@@ -XXX,XX +XXX,XX @@ int acpi_ghes_record_errors(uint16_t source_id, uint64_t physical_address)
106
107
start_addr = le64_to_cpu(ags->ghes_addr_le);
108
109
- if (!physical_address) {
110
- return -1;
111
- }
112
-
113
start_addr += source_id * sizeof(uint64_t);
114
115
cpu_physical_memory_read(start_addr, &error_block_addr,
108
sizeof(error_block_addr));
116
sizeof(error_block_addr));
109
117
110
error_block_addr = le64_to_cpu(error_block_addr);
118
error_block_addr = le64_to_cpu(error_block_addr);
111
+ if (!error_block_addr) {
119
+ if (!error_block_addr) {
112
+ error_setg(errp, "can not find Generic Error Status Block");
120
+ error_setg(errp, "can not find Generic Error Status Block");
...
...
141
}
149
}
142
150
143
- return ret;
151
- return ret;
144
+ read_ack_register = cpu_to_le64(0);
152
+ read_ack_register = cpu_to_le64(0);
145
+ /*
153
+ /*
146
+ * Clear the Read Ack Register, OSPM will write 1 to this register when
154
+ * Clear the Read Ack Register, OSPM will write it to 1 when
147
+ * it acknowledges the error.
155
+ * it acknowledges this error.
148
+ */
156
+ */
149
+ cpu_physical_memory_write(read_ack_register_addr,
157
+ cpu_physical_memory_write(read_ack_register_addr,
150
+ &read_ack_register, sizeof(uint64_t));
158
+ &read_ack_register, sizeof(uint64_t));
151
+
159
+
152
+ /* Write the generic error data entry into guest memory */
160
+ /* Write the generic error data entry into guest memory */
...
...
160
+ /* Memory Error Section Type */
168
+ /* Memory Error Section Type */
161
+ const uint8_t guid[] =
169
+ const uint8_t guid[] =
162
+ UUID_LE(0xA5BC1114, 0x6F64, 0x4EDE, 0xB8, 0x63, 0x3E, 0x83, \
170
+ UUID_LE(0xA5BC1114, 0x6F64, 0x4EDE, 0xB8, 0x63, 0x3E, 0x83, \
163
+ 0xED, 0x7C, 0x83, 0xB1);
171
+ 0xED, 0x7C, 0x83, 0xB1);
164
+ Error *errp = NULL;
172
+ Error *errp = NULL;
165
+ int data_length;
166
+ GArray *block;
173
+ GArray *block;
167
+
174
+
175
+ if (!physical_address) {
176
+ error_report("can not find Generic Error Status Block for source id %d",
177
+ source_id);
178
+ return -1;
179
+ }
180
+
168
+ block = g_array_new(false, true /* clear */, 1);
181
+ block = g_array_new(false, true /* clear */, 1);
169
+
182
+
170
+ data_length = ACPI_GHES_DATA_LENGTH + ACPI_GHES_MEM_CPER_LENGTH;
171
+ /*
172
+ * It should not run out of the preallocated memory if adding a new generic
173
+ * error data entry
174
+ */
175
+ assert((data_length + ACPI_GHES_GESB_SIZE) <=
176
+ ACPI_GHES_MAX_RAW_DATA_LENGTH);
177
+
178
+ ghes_gen_err_data_uncorrectable_recoverable(block, guid,
183
+ ghes_gen_err_data_uncorrectable_recoverable(block, guid,
179
+ data_length);
184
+ ACPI_GHES_MAX_RAW_DATA_LENGTH);
180
+
185
+
181
+ /* Build the memory section CPER for above new generic error data entry */
186
+ /* Build the memory section CPER for above new generic error data entry */
182
+ acpi_ghes_build_append_mem_cper(block, physical_address);
187
+ acpi_ghes_build_append_mem_cper(block, physical_address);
183
+
188
+
184
+ /* Report the error */
189
+ /* Report the error */
...
...
215
+ uint16_t source_id, Error **errp);
220
+ uint16_t source_id, Error **errp);
216
int acpi_ghes_record_errors(uint16_t source_id, uint64_t error_physical_addr);
221
int acpi_ghes_record_errors(uint16_t source_id, uint64_t error_physical_addr);
217
222
218
/**
223
/**
219
--
224
--
220
2.47.1
225
2.47.0
diff view generated by jsdifflib
1
The current function used to generate GHES data is specific for
1
The current function used to generate GHES data is specific for
2
memory errors. Give a better name for it, as we now have a generic
2
memory errors. Give a better name for it, as we now have a generic
3
function as well.
3
function as well.
4
4
5
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
5
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
6
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
6
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
7
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
8
---
7
---
9
hw/acpi/ghes-stub.c | 2 +-
8
hw/acpi/ghes-stub.c | 2 +-
10
hw/acpi/ghes.c | 2 +-
9
hw/acpi/ghes.c | 2 +-
11
include/hw/acpi/ghes.h | 4 ++--
10
include/hw/acpi/ghes.h | 5 +++--
12
target/arm/kvm.c | 2 +-
11
target/arm/kvm.c | 3 ++-
13
4 files changed, 5 insertions(+), 5 deletions(-)
12
4 files changed, 7 insertions(+), 5 deletions(-)
14
13
15
diff --git a/hw/acpi/ghes-stub.c b/hw/acpi/ghes-stub.c
14
diff --git a/hw/acpi/ghes-stub.c b/hw/acpi/ghes-stub.c
16
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/acpi/ghes-stub.c
16
--- a/hw/acpi/ghes-stub.c
18
+++ b/hw/acpi/ghes-stub.c
17
+++ b/hw/acpi/ghes-stub.c
...
...
44
+++ b/include/hw/acpi/ghes.h
43
+++ b/include/hw/acpi/ghes.h
45
@@ -XXX,XX +XXX,XX @@ void acpi_build_hest(GArray *table_data, GArray *hardware_errors,
44
@@ -XXX,XX +XXX,XX @@ void acpi_build_hest(GArray *table_data, GArray *hardware_errors,
46
const char *oem_id, const char *oem_table_id);
45
const char *oem_id, const char *oem_table_id);
47
void acpi_ghes_add_fw_cfg(AcpiGhesState *vms, FWCfgState *s,
46
void acpi_ghes_add_fw_cfg(AcpiGhesState *vms, FWCfgState *s,
48
GArray *hardware_errors);
47
GArray *hardware_errors);
49
+int acpi_ghes_memory_errors(uint16_t source_id, uint64_t error_physical_addr);
48
+int acpi_ghes_memory_errors(uint16_t source_id,
49
+ uint64_t error_physical_addr);
50
void ghes_record_cper_errors(const void *cper, size_t len,
50
void ghes_record_cper_errors(const void *cper, size_t len,
51
uint16_t source_id, Error **errp);
51
uint16_t source_id, Error **errp);
52
-int acpi_ghes_record_errors(uint16_t source_id, uint64_t error_physical_addr);
52
-int acpi_ghes_record_errors(uint16_t source_id, uint64_t error_physical_addr);
53
53
54
/**
54
/**
...
...
67
@@ -XXX,XX +XXX,XX @@ void kvm_arch_on_sigbus_vcpu(CPUState *c, int code, void *addr)
67
@@ -XXX,XX +XXX,XX @@ void kvm_arch_on_sigbus_vcpu(CPUState *c, int code, void *addr)
68
*/
68
*/
69
if (code == BUS_MCEERR_AR) {
69
if (code == BUS_MCEERR_AR) {
70
kvm_cpu_synchronize_state(c);
70
kvm_cpu_synchronize_state(c);
71
- if (!acpi_ghes_record_errors(ACPI_HEST_SRC_ID_SEA, paddr)) {
71
- if (!acpi_ghes_record_errors(ACPI_HEST_SRC_ID_SEA, paddr)) {
72
+ if (!acpi_ghes_memory_errors(ACPI_HEST_SRC_ID_SEA, paddr)) {
72
+ if (!acpi_ghes_memory_errors(ACPI_HEST_SRC_ID_SEA,
73
+ paddr)) {
73
kvm_inject_arm_sea(c);
74
kvm_inject_arm_sea(c);
74
} else {
75
} else {
75
error_report("failed to record the error");
76
error_report("failed to record the error");
76
--
77
--
77
2.47.1
78
2.47.0
diff view generated by jsdifflib
1
Make error handling within ghes_record_cper_errors() consistent,
1
Make error handling within ghes_record_cper_errors() consistent,
2
i.e. instead abort just print a error in case ghes GED is not found.
2
i.e. instead abort just print a error in case ghes GED is not found.
3
3
4
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
5
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
4
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
6
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
7
---
5
---
8
hw/acpi/ghes.c | 5 ++++-
6
hw/acpi/ghes.c | 5 ++++-
9
1 file changed, 4 insertions(+), 1 deletion(-)
7
1 file changed, 4 insertions(+), 1 deletion(-)
10
8
11
diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c
9
diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c
...
...
23
+ }
21
+ }
24
ags = &acpi_ged_state->ghes_state;
22
ags = &acpi_ged_state->ghes_state;
25
23
26
start_addr = le64_to_cpu(ags->ghes_addr_le);
24
start_addr = le64_to_cpu(ags->ghes_addr_le);
27
--
25
--
28
2.47.1
26
2.47.0
diff view generated by jsdifflib
...
...
103
+ fw_cfg_add_file_callback(s, ACPI_HW_ERROR_ADDR_FW_CFG_FILE, NULL, NULL,
103
+ fw_cfg_add_file_callback(s, ACPI_HW_ERROR_ADDR_FW_CFG_FILE, NULL, NULL,
104
NULL, &(ags->ghes_addr_le), sizeof(ags->ghes_addr_le), false);
104
NULL, &(ags->ghes_addr_le), sizeof(ags->ghes_addr_le), false);
105
105
106
ags->present = true;
106
ags->present = true;
107
--
107
--
108
2.47.1
108
2.47.0
diff view generated by jsdifflib
1
The etc/hardware_errors fw_cfg file is where the HEST error
1
The hardware error firmware is where HEST error structures are
2
source structures store registers pointed by Generic Address
2
stored. Those can be GHESv2, but they can also be other types.
3
Structures, as defined at:
4
3
5
    https://uefi.org/specs/ACPI/6.5/18_Platform_Error_Interfaces.html#generic-error-data-entry
4
Better name the location of the hardware error.
6
7
and
8
9
    https://uefi.org/specs/ACPI/6.5/18_Platform_Error_Interfaces.html#generic-hardware-error-source-version-2-ghesv2-structure
10
11
As the name of the firmware file is hardware_errors, better
12
name the variable where the offset pointing to it will be stored
13
from ghes_error_le to hw_error_le.
14
5
15
No functional changes.
6
No functional changes.
16
7
17
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
8
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
18
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
9
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
...
...
79
+ uint64_t hw_error_le;
70
+ uint64_t hw_error_le;
80
bool present; /* True if GHES is present at all on this board */
71
bool present; /* True if GHES is present at all on this board */
81
} AcpiGhesState;
72
} AcpiGhesState;
82
73
83
--
74
--
84
2.47.1
75
2.47.0
diff view generated by jsdifflib
Deleted patch
1
The current code is actually dependent on having just one error
2
structure with a single source.
3
1
4
As the number of sources should be arch-dependent, as it will depend on
5
what kind of synchronous/assynchronous notifications will exist, change
6
the logic to dynamically build the table.
7
8
Yet, for a proper support, we need to get the number of sources by
9
reading the number from the HEST table. However, bios currently doesn't
10
store a pointer to it.
11
12
For now just change the logic at table build time, while enforcing that
13
it will behave like before with a single source ID.
14
15
A future patch will add a HEST table bios pointer and change the logic
16
at acpi_ghes_record_errors() to dynamically use the new size.
17
18
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
19
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
20
---
21
hw/acpi/ghes.c | 43 ++++++++++++++++++++++++++--------------
22
hw/arm/virt-acpi-build.c | 5 +++++
23
include/hw/acpi/ghes.h | 21 +++++++++++++-------
24
3 files changed, 47 insertions(+), 22 deletions(-)
25
26
diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c
27
index XXXXXXX..XXXXXXX 100644
28
--- a/hw/acpi/ghes.c
29
+++ b/hw/acpi/ghes.c
30
@@ -XXX,XX +XXX,XX @@ ghes_gen_err_data_uncorrectable_recoverable(GArray *block,
31
* Initialize "etc/hardware_errors" and "etc/hardware_errors_addr" fw_cfg blobs.
32
* See docs/specs/acpi_hest_ghes.rst for blobs format.
33
*/
34
-static void build_ghes_error_table(GArray *hardware_errors, BIOSLinker *linker)
35
+static void build_ghes_error_table(GArray *hardware_errors, BIOSLinker *linker,
36
+ int num_sources)
37
{
38
int i, error_status_block_offset;
39
40
+ /*
41
+ * TODO: Current version supports only one source.
42
+ * A further patch will drop this check, after adding a proper migration
43
+ * code, as, for the code to work, we need to store a bios pointer to the
44
+ * HEST table.
45
+ */
46
+ assert(num_sources == 1);
47
+
48
/* Build error_block_address */
49
- for (i = 0; i < ACPI_GHES_ERROR_SOURCE_COUNT; i++) {
50
+ for (i = 0; i < num_sources; i++) {
51
build_append_int_noprefix(hardware_errors, 0, sizeof(uint64_t));
52
}
53
54
/* Build read_ack_register */
55
- for (i = 0; i < ACPI_GHES_ERROR_SOURCE_COUNT; i++) {
56
+ for (i = 0; i < num_sources; i++) {
57
/*
58
* Initialize the value of read_ack_register to 1, so GHES can be
59
* writable after (re)boot.
60
@@ -XXX,XX +XXX,XX @@ static void build_ghes_error_table(GArray *hardware_errors, BIOSLinker *linker)
61
62
/* Reserve space for Error Status Data Block */
63
acpi_data_push(hardware_errors,
64
- ACPI_GHES_MAX_RAW_DATA_LENGTH * ACPI_GHES_ERROR_SOURCE_COUNT);
65
+ ACPI_GHES_MAX_RAW_DATA_LENGTH * num_sources);
66
67
/* Tell guest firmware to place hardware_errors blob into RAM */
68
bios_linker_loader_alloc(linker, ACPI_HW_ERROR_FW_CFG_FILE,
69
hardware_errors, sizeof(uint64_t), false);
70
71
- for (i = 0; i < ACPI_GHES_ERROR_SOURCE_COUNT; i++) {
72
+ for (i = 0; i < num_sources; i++) {
73
/*
74
* Tell firmware to patch error_block_address entries to point to
75
* corresponding "Generic Error Status Block"
76
@@ -XXX,XX +XXX,XX @@ static void build_ghes_error_table(GArray *hardware_errors, BIOSLinker *linker)
77
/* Build Generic Hardware Error Source version 2 (GHESv2) */
78
static void build_ghes_v2(GArray *table_data,
79
BIOSLinker *linker,
80
- enum AcpiGhesNotifyType notify,
81
- uint16_t source_id)
82
+ const AcpiNotificationSourceId *notif_src,
83
+ uint16_t index, int num_sources)
84
{
85
uint64_t address_offset;
86
+ const uint16_t notify = notif_src->notify;
87
+ const uint16_t source_id = notif_src->source_id;
88
89
/*
90
* Type:
91
@@ -XXX,XX +XXX,XX @@ static void build_ghes_v2(GArray *table_data,
92
address_offset + GAS_ADDR_OFFSET,
93
sizeof(uint64_t),
94
ACPI_HW_ERROR_FW_CFG_FILE,
95
- source_id * sizeof(uint64_t));
96
+ index * sizeof(uint64_t));
97
98
/* Notification Structure */
99
build_ghes_hw_error_notification(table_data, notify);
100
@@ -XXX,XX +XXX,XX @@ static void build_ghes_v2(GArray *table_data,
101
address_offset + GAS_ADDR_OFFSET,
102
sizeof(uint64_t),
103
ACPI_HW_ERROR_FW_CFG_FILE,
104
- (ACPI_GHES_ERROR_SOURCE_COUNT + source_id)
105
- * sizeof(uint64_t));
106
+ (num_sources + index) * sizeof(uint64_t));
107
108
/*
109
* Read Ack Preserve field
110
@@ -XXX,XX +XXX,XX @@ static void build_ghes_v2(GArray *table_data,
111
/* Build Hardware Error Source Table */
112
void acpi_build_hest(GArray *table_data, GArray *hardware_errors,
113
BIOSLinker *linker,
114
+ const AcpiNotificationSourceId * const notif_source,
115
+ int num_sources,
116
const char *oem_id, const char *oem_table_id)
117
{
118
AcpiTable table = { .sig = "HEST", .rev = 1,
119
.oem_id = oem_id, .oem_table_id = oem_table_id };
120
+ int i;
121
122
- build_ghes_error_table(hardware_errors, linker);
123
+ build_ghes_error_table(hardware_errors, linker, num_sources);
124
125
acpi_table_begin(&table, table_data);
126
127
/* Error Source Count */
128
- build_append_int_noprefix(table_data, ACPI_GHES_ERROR_SOURCE_COUNT, 4);
129
- build_ghes_v2(table_data, linker,
130
- ACPI_GHES_NOTIFY_SEA, ACPI_HEST_SRC_ID_SEA);
131
+ build_append_int_noprefix(table_data, num_sources, 4);
132
+ for (i = 0; i < num_sources; i++) {
133
+ build_ghes_v2(table_data, linker, &notif_source[i], i, num_sources);
134
+ }
135
136
acpi_table_end(linker, &table);
137
}
138
@@ -XXX,XX +XXX,XX @@ void ghes_record_cper_errors(const void *cper, size_t len,
139
}
140
ags = &acpi_ged_state->ghes_state;
141
142
- assert(ACPI_GHES_ERROR_SOURCE_COUNT == 1);
143
get_hw_error_offsets(le64_to_cpu(ags->hw_error_le),
144
&cper_addr, &read_ack_register_addr);
145
146
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
147
index XXXXXXX..XXXXXXX 100644
148
--- a/hw/arm/virt-acpi-build.c
149
+++ b/hw/arm/virt-acpi-build.c
150
@@ -XXX,XX +XXX,XX @@ static void acpi_align_size(GArray *blob, unsigned align)
151
g_array_set_size(blob, ROUND_UP(acpi_data_len(blob), align));
152
}
153
154
+static const AcpiNotificationSourceId hest_ghes_notify[] = {
155
+ { ACPI_HEST_SRC_ID_SYNC, ACPI_GHES_NOTIFY_SEA },
156
+};
157
+
158
static
159
void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)
160
{
161
@@ -XXX,XX +XXX,XX @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)
162
if (vms->ras) {
163
acpi_add_table(table_offsets, tables_blob);
164
acpi_build_hest(tables_blob, tables->hardware_errors, tables->linker,
165
+ hest_ghes_notify, ARRAY_SIZE(hest_ghes_notify),
166
vms->oem_id, vms->oem_table_id);
167
}
168
169
diff --git a/include/hw/acpi/ghes.h b/include/hw/acpi/ghes.h
170
index XXXXXXX..XXXXXXX 100644
171
--- a/include/hw/acpi/ghes.h
172
+++ b/include/hw/acpi/ghes.h
173
@@ -XXX,XX +XXX,XX @@ enum AcpiGhesNotifyType {
174
ACPI_GHES_NOTIFY_RESERVED = 12
175
};
176
177
-enum {
178
- ACPI_HEST_SRC_ID_SEA = 0,
179
- /* future ids go here */
180
-
181
- ACPI_GHES_ERROR_SOURCE_COUNT
182
-};
183
-
184
typedef struct AcpiGhesState {
185
uint64_t hw_error_le;
186
bool present; /* True if GHES is present at all on this board */
187
} AcpiGhesState;
188
189
+/*
190
+ * ID numbers used to fill HEST source ID field
191
+ */
192
+enum AcpiGhesSourceID {
193
+ ACPI_HEST_SRC_ID_SYNC,
194
+};
195
+
196
+typedef struct AcpiNotificationSourceId {
197
+ enum AcpiGhesSourceID source_id;
198
+ enum AcpiGhesNotifyType notify;
199
+} AcpiNotificationSourceId;
200
+
201
void acpi_build_hest(GArray *table_data, GArray *hardware_errors,
202
BIOSLinker *linker,
203
+ const AcpiNotificationSourceId * const notif_source,
204
+ int num_sources,
205
const char *oem_id, const char *oem_table_id);
206
void acpi_ghes_add_fw_cfg(AcpiGhesState *vms, FWCfgState *s,
207
GArray *hardware_errors);
208
--
209
2.47.1
diff view generated by jsdifflib
Deleted patch
1
Store HEST table address at GPA, placing its content at
2
hest_addr_le variable.
3
1
4
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
5
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
6
7
---
8
9
Change from v8:
10
- hest_addr_lr is now pointing to the error source size and data.
11
12
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
13
---
14
hw/acpi/ghes.c | 17 ++++++++++++++++-
15
include/hw/acpi/ghes.h | 1 +
16
2 files changed, 17 insertions(+), 1 deletion(-)
17
18
diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/acpi/ghes.c
21
+++ b/hw/acpi/ghes.c
22
@@ -XXX,XX +XXX,XX @@
23
24
#define ACPI_HW_ERROR_FW_CFG_FILE "etc/hardware_errors"
25
#define ACPI_HW_ERROR_ADDR_FW_CFG_FILE "etc/hardware_errors_addr"
26
+#define ACPI_HEST_ADDR_FW_CFG_FILE "etc/acpi_table_hest_addr"
27
28
/* The max size in bytes for one error block */
29
#define ACPI_GHES_MAX_RAW_DATA_LENGTH (1 * KiB)
30
@@ -XXX,XX +XXX,XX @@ static void build_ghes_error_table(GArray *hardware_errors, BIOSLinker *linker,
31
}
32
33
/*
34
- * tell firmware to write hardware_errors GPA into
35
+ * Tell firmware to write hardware_errors GPA into
36
* hardware_errors_addr fw_cfg, once the former has been initialized.
37
*/
38
bios_linker_loader_write_pointer(linker, ACPI_HW_ERROR_ADDR_FW_CFG_FILE, 0,
39
@@ -XXX,XX +XXX,XX @@ void acpi_build_hest(GArray *table_data, GArray *hardware_errors,
40
41
acpi_table_begin(&table, table_data);
42
43
+ int hest_offset = table_data->len;
44
+
45
/* Error Source Count */
46
build_append_int_noprefix(table_data, num_sources, 4);
47
for (i = 0; i < num_sources; i++) {
48
@@ -XXX,XX +XXX,XX @@ void acpi_build_hest(GArray *table_data, GArray *hardware_errors,
49
}
50
51
acpi_table_end(linker, &table);
52
+
53
+ /*
54
+ * tell firmware to write into GPA the address of HEST via fw_cfg,
55
+ * once initialized.
56
+ */
57
+ bios_linker_loader_write_pointer(linker,
58
+ ACPI_HEST_ADDR_FW_CFG_FILE, 0,
59
+ sizeof(uint64_t),
60
+ ACPI_BUILD_TABLE_FILE, hest_offset);
61
}
62
63
void acpi_ghes_add_fw_cfg(AcpiGhesState *ags, FWCfgState *s,
64
@@ -XXX,XX +XXX,XX @@ void acpi_ghes_add_fw_cfg(AcpiGhesState *ags, FWCfgState *s,
65
fw_cfg_add_file_callback(s, ACPI_HW_ERROR_ADDR_FW_CFG_FILE, NULL, NULL,
66
NULL, &(ags->hw_error_le), sizeof(ags->hw_error_le), false);
67
68
+ fw_cfg_add_file_callback(s, ACPI_HEST_ADDR_FW_CFG_FILE, NULL, NULL,
69
+ NULL, &(ags->hest_addr_le), sizeof(ags->hest_addr_le), false);
70
+
71
ags->present = true;
72
}
73
74
diff --git a/include/hw/acpi/ghes.h b/include/hw/acpi/ghes.h
75
index XXXXXXX..XXXXXXX 100644
76
--- a/include/hw/acpi/ghes.h
77
+++ b/include/hw/acpi/ghes.h
78
@@ -XXX,XX +XXX,XX @@ enum AcpiGhesNotifyType {
79
};
80
81
typedef struct AcpiGhesState {
82
+ uint64_t hest_addr_le;
83
uint64_t hw_error_le;
84
bool present; /* True if GHES is present at all on this board */
85
} AcpiGhesState;
86
--
87
2.47.1
diff view generated by jsdifflib
Deleted patch
1
There are two pointers that are needed during error injection:
2
1
3
1. The start address of the CPER block to be stored;
4
2. The address of the ack, which needs a reset before next error.
5
6
It is preferable to calculate them from the HEST table. This allows
7
checking the source ID, the size of the table and the type of the
8
HEST error block structures.
9
10
Yet, keep the old code, as this is needed for migration purposes.
11
12
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
13
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
14
---
15
hw/acpi/ghes.c | 106 ++++++++++++++++++++++++++++++++++++++++++++-----
16
1 file changed, 96 insertions(+), 10 deletions(-)
17
18
diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/acpi/ghes.c
21
+++ b/hw/acpi/ghes.c
22
@@ -XXX,XX +XXX,XX @@
23
*/
24
#define ACPI_GHES_GESB_SIZE 20
25
26
+/*
27
+ * Offsets with regards to the start of the HEST table stored at
28
+ * ags->hest_addr_le, according with the memory layout map at
29
+ * docs/specs/acpi_hest_ghes.rst.
30
+ */
31
+
32
+/*
33
+ * ACPI 6.2: 18.3.2.8 Generic Hardware Error Source version 2
34
+ * Table 18-382 Generic Hardware Error Source version 2 (GHESv2) Structure
35
+ */
36
+#define HEST_GHES_V2_TABLE_SIZE 92
37
+#define GHES_ACK_OFFSET (64 + GAS_ADDR_OFFSET)
38
+
39
+/*
40
+ * ACPI 6.2: 18.3.2.7: Generic Hardware Error Source
41
+ * Table 18-380: 'Error Status Address' field
42
+ */
43
+#define GHES_ERR_ST_ADDR_OFFSET (20 + GAS_ADDR_OFFSET)
44
+
45
/*
46
* Values for error_severity field
47
*/
48
@@ -XXX,XX +XXX,XX @@ static void build_ghes_error_table(GArray *hardware_errors, BIOSLinker *linker,
49
{
50
int i, error_status_block_offset;
51
52
- /*
53
- * TODO: Current version supports only one source.
54
- * A further patch will drop this check, after adding a proper migration
55
- * code, as, for the code to work, we need to store a bios pointer to the
56
- * HEST table.
57
- */
58
- assert(num_sources == 1);
59
-
60
/* Build error_block_address */
61
for (i = 0; i < num_sources; i++) {
62
build_append_int_noprefix(hardware_errors, 0, sizeof(uint64_t));
63
@@ -XXX,XX +XXX,XX @@ static void get_hw_error_offsets(uint64_t ghes_addr,
64
*read_ack_register_addr = ghes_addr + sizeof(uint64_t);
65
}
66
67
+static void get_ghes_source_offsets(uint16_t source_id, uint64_t hest_addr,
68
+ uint64_t *cper_addr,
69
+ uint64_t *read_ack_start_addr,
70
+ Error **errp)
71
+{
72
+ uint64_t hest_err_block_addr, hest_read_ack_addr;
73
+ uint64_t err_source_struct, error_block_addr;
74
+ uint32_t num_sources, i;
75
+
76
+ if (!hest_addr) {
77
+ return;
78
+ }
79
+
80
+ cpu_physical_memory_read(hest_addr, &num_sources, sizeof(num_sources));
81
+ num_sources = le32_to_cpu(num_sources);
82
+
83
+ err_source_struct = hest_addr + sizeof(num_sources);
84
+
85
+ /*
86
+ * Currently, HEST Error source navigates only for GHESv2 tables
87
+ */
88
+
89
+ for (i = 0; i < num_sources; i++) {
90
+ uint64_t addr = err_source_struct;
91
+ uint16_t type, src_id;
92
+
93
+ cpu_physical_memory_read(addr, &type, sizeof(type));
94
+ type = le16_to_cpu(type);
95
+
96
+ /* For now, we only know the size of GHESv2 table */
97
+ if (type != ACPI_GHES_SOURCE_GENERIC_ERROR_V2) {
98
+ error_setg(errp, "HEST: type %d not supported.", type);
99
+ return;
100
+ }
101
+
102
+ /* Compare CPER source address at the GHESv2 structure */
103
+ addr += sizeof(type);
104
+ cpu_physical_memory_read(addr, &src_id, sizeof(src_id));
105
+
106
+ if (src_id == source_id) {
107
+ break;
108
+ }
109
+
110
+ err_source_struct += HEST_GHES_V2_TABLE_SIZE;
111
+ }
112
+ if (i == num_sources) {
113
+ error_setg(errp, "HEST: Source %d not found.", source_id);
114
+ return;
115
+ }
116
+
117
+ /* Navigate though table address pointers */
118
+ hest_err_block_addr = err_source_struct + GHES_ERR_ST_ADDR_OFFSET;
119
+ hest_read_ack_addr = err_source_struct + GHES_ACK_OFFSET;
120
+
121
+ cpu_physical_memory_read(hest_err_block_addr, &error_block_addr,
122
+ sizeof(error_block_addr));
123
+
124
+ error_block_addr = le64_to_cpu(error_block_addr);
125
+
126
+ cpu_physical_memory_read(error_block_addr, cper_addr,
127
+ sizeof(*cper_addr));
128
+
129
+ *cper_addr = le64_to_cpu(*cper_addr);
130
+
131
+ cpu_physical_memory_read(hest_read_ack_addr, read_ack_start_addr,
132
+ sizeof(*read_ack_start_addr));
133
+
134
+ *read_ack_start_addr = le64_to_cpu(*read_ack_start_addr);
135
+}
136
+
137
void ghes_record_cper_errors(const void *cper, size_t len,
138
uint16_t source_id, Error **errp)
139
{
140
@@ -XXX,XX +XXX,XX @@ void ghes_record_cper_errors(const void *cper, size_t len,
141
}
142
ags = &acpi_ged_state->ghes_state;
143
144
- get_hw_error_offsets(le64_to_cpu(ags->hw_error_le),
145
- &cper_addr, &read_ack_register_addr);
146
+ if (!ags->hest_addr_le) {
147
+ get_hw_error_offsets(le64_to_cpu(ags->hw_error_le),
148
+ &cper_addr, &read_ack_register_addr);
149
+ } else {
150
+ get_ghes_source_offsets(source_id, le64_to_cpu(ags->hest_addr_le),
151
+ &cper_addr, &read_ack_register_addr, errp);
152
+ }
153
154
if (!cper_addr) {
155
error_setg(errp, "can not find Generic Error Status Block");
156
--
157
2.47.1
diff view generated by jsdifflib
Deleted patch
1
The GHES migration logic at GED should now support HEST table
2
location too.
3
1
4
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
5
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
6
---
7
hw/acpi/generic_event_device.c | 29 +++++++++++++++++++++++++++++
8
1 file changed, 29 insertions(+)
9
10
diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c
11
index XXXXXXX..XXXXXXX 100644
12
--- a/hw/acpi/generic_event_device.c
13
+++ b/hw/acpi/generic_event_device.c
14
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_ghes_state = {
15
}
16
};
17
18
+static const VMStateDescription vmstate_hest = {
19
+ .name = "acpi-hest",
20
+ .version_id = 1,
21
+ .minimum_version_id = 1,
22
+ .fields = (const VMStateField[]) {
23
+ VMSTATE_UINT64(hest_addr_le, AcpiGhesState),
24
+ VMSTATE_END_OF_LIST()
25
+ },
26
+};
27
+
28
+static bool hest_needed(void *opaque)
29
+{
30
+ AcpiGedState *s = opaque;
31
+ return s->ghes_state.hest_addr_le;
32
+}
33
+
34
+static const VMStateDescription vmstate_hest_state = {
35
+ .name = "acpi-ged/hest",
36
+ .version_id = 1,
37
+ .minimum_version_id = 1,
38
+ .needed = hest_needed,
39
+ .fields = (const VMStateField[]) {
40
+ VMSTATE_STRUCT(ghes_state, AcpiGedState, 1,
41
+ vmstate_hest, AcpiGhesState),
42
+ VMSTATE_END_OF_LIST()
43
+ }
44
+};
45
+
46
static const VMStateDescription vmstate_acpi_ged = {
47
.name = "acpi-ged",
48
.version_id = 1,
49
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_acpi_ged = {
50
&vmstate_memhp_state,
51
&vmstate_cpuhp_state,
52
&vmstate_ghes_state,
53
+ &vmstate_hest_state,
54
NULL
55
}
56
};
57
--
58
2.47.1
diff view generated by jsdifflib
Deleted patch
1
Create a new property (x-has-hest-addr) and use it to detect if
2
the GHES table offsets can be calculated from the HEST address
3
(qemu 9.2 and upper) or via the legacy way via an offset obtained
4
from the hardware_errors firmware file.
5
1
6
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
7
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
8
---
9
hw/acpi/generic_event_device.c | 1 +
10
hw/acpi/ghes.c | 24 +++++++++++++++++-------
11
hw/arm/virt-acpi-build.c | 30 ++++++++++++++++++++++++++----
12
hw/core/machine.c | 2 ++
13
include/hw/acpi/ghes.h | 1 +
14
5 files changed, 47 insertions(+), 11 deletions(-)
15
16
diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/acpi/generic_event_device.c
19
+++ b/hw/acpi/generic_event_device.c
20
@@ -XXX,XX +XXX,XX @@ static void acpi_ged_send_event(AcpiDeviceIf *adev, AcpiEventStatusBits ev)
21
22
static Property acpi_ged_properties[] = {
23
DEFINE_PROP_UINT32("ged-event", AcpiGedState, ged_event_bitmap, 0),
24
+ DEFINE_PROP_BOOL("x-has-hest-addr", AcpiGedState, ghes_state.hest_lookup, true),
25
DEFINE_PROP_END_OF_LIST(),
26
};
27
28
diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c
29
index XXXXXXX..XXXXXXX 100644
30
--- a/hw/acpi/ghes.c
31
+++ b/hw/acpi/ghes.c
32
@@ -XXX,XX +XXX,XX @@ void acpi_build_hest(GArray *table_data, GArray *hardware_errors,
33
{
34
AcpiTable table = { .sig = "HEST", .rev = 1,
35
.oem_id = oem_id, .oem_table_id = oem_table_id };
36
+ AcpiGedState *acpi_ged_state;
37
+ AcpiGhesState *ags;
38
int i;
39
40
build_ghes_error_table(hardware_errors, linker, num_sources);
41
@@ -XXX,XX +XXX,XX @@ void acpi_build_hest(GArray *table_data, GArray *hardware_errors,
42
* tell firmware to write into GPA the address of HEST via fw_cfg,
43
* once initialized.
44
*/
45
- bios_linker_loader_write_pointer(linker,
46
- ACPI_HEST_ADDR_FW_CFG_FILE, 0,
47
- sizeof(uint64_t),
48
- ACPI_BUILD_TABLE_FILE, hest_offset);
49
+
50
+ acpi_ged_state = ACPI_GED(object_resolve_path_type("", TYPE_ACPI_GED,
51
+ NULL));
52
+ ags = &acpi_ged_state->ghes_state;
53
+ if (ags->hest_lookup) {
54
+ bios_linker_loader_write_pointer(linker,
55
+ ACPI_HEST_ADDR_FW_CFG_FILE, 0,
56
+ sizeof(uint64_t),
57
+ ACPI_BUILD_TABLE_FILE, hest_offset);
58
+ }
59
}
60
61
void acpi_ghes_add_fw_cfg(AcpiGhesState *ags, FWCfgState *s,
62
@@ -XXX,XX +XXX,XX @@ void acpi_ghes_add_fw_cfg(AcpiGhesState *ags, FWCfgState *s,
63
fw_cfg_add_file_callback(s, ACPI_HW_ERROR_ADDR_FW_CFG_FILE, NULL, NULL,
64
NULL, &(ags->hw_error_le), sizeof(ags->hw_error_le), false);
65
66
- fw_cfg_add_file_callback(s, ACPI_HEST_ADDR_FW_CFG_FILE, NULL, NULL,
67
- NULL, &(ags->hest_addr_le), sizeof(ags->hest_addr_le), false);
68
+ if (ags->hest_lookup) {
69
+ fw_cfg_add_file_callback(s, ACPI_HEST_ADDR_FW_CFG_FILE, NULL, NULL,
70
+ NULL, &(ags->hest_addr_le), sizeof(ags->hest_addr_le), false);
71
+ }
72
73
ags->present = true;
74
}
75
@@ -XXX,XX +XXX,XX @@ void ghes_record_cper_errors(const void *cper, size_t len,
76
}
77
ags = &acpi_ged_state->ghes_state;
78
79
- if (!ags->hest_addr_le) {
80
+ if (!ags->hest_lookup) {
81
get_hw_error_offsets(le64_to_cpu(ags->hw_error_le),
82
&cper_addr, &read_ack_register_addr);
83
} else {
84
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
85
index XXXXXXX..XXXXXXX 100644
86
--- a/hw/arm/virt-acpi-build.c
87
+++ b/hw/arm/virt-acpi-build.c
88
@@ -XXX,XX +XXX,XX @@ static const AcpiNotificationSourceId hest_ghes_notify[] = {
89
{ ACPI_HEST_SRC_ID_SYNC, ACPI_GHES_NOTIFY_SEA },
90
};
91
92
+static const AcpiNotificationSourceId hest_ghes_notify_9_1[] = {
93
+ { ACPI_HEST_SRC_ID_SYNC, ACPI_GHES_NOTIFY_SEA },
94
+};
95
+
96
static
97
void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)
98
{
99
@@ -XXX,XX +XXX,XX @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)
100
build_dbg2(tables_blob, tables->linker, vms);
101
102
if (vms->ras) {
103
- acpi_add_table(table_offsets, tables_blob);
104
- acpi_build_hest(tables_blob, tables->hardware_errors, tables->linker,
105
- hest_ghes_notify, ARRAY_SIZE(hest_ghes_notify),
106
- vms->oem_id, vms->oem_table_id);
107
+ AcpiGhesState *ags;
108
+ AcpiGedState *acpi_ged_state;
109
+
110
+ acpi_ged_state = ACPI_GED(object_resolve_path_type("", TYPE_ACPI_GED,
111
+ NULL));
112
+ if (acpi_ged_state) {
113
+ ags = &acpi_ged_state->ghes_state;
114
+
115
+ acpi_add_table(table_offsets, tables_blob);
116
+
117
+ if (!ags->hest_lookup) {
118
+ acpi_build_hest(tables_blob, tables->hardware_errors,
119
+ tables->linker, hest_ghes_notify_9_1,
120
+ ARRAY_SIZE(hest_ghes_notify_9_1),
121
+ vms->oem_id, vms->oem_table_id);
122
+ } else {
123
+ acpi_build_hest(tables_blob, tables->hardware_errors,
124
+ tables->linker, hest_ghes_notify,
125
+ ARRAY_SIZE(hest_ghes_notify),
126
+ vms->oem_id, vms->oem_table_id);
127
+ }
128
+ }
129
}
130
131
if (ms->numa_state->num_nodes > 0) {
132
diff --git a/hw/core/machine.c b/hw/core/machine.c
133
index XXXXXXX..XXXXXXX 100644
134
--- a/hw/core/machine.c
135
+++ b/hw/core/machine.c
136
@@ -XXX,XX +XXX,XX @@
137
#include "hw/virtio/virtio-pci.h"
138
#include "hw/virtio/virtio-net.h"
139
#include "hw/virtio/virtio-iommu.h"
140
+#include "hw/acpi/generic_event_device.h"
141
#include "audio/audio.h"
142
143
GlobalProperty hw_compat_9_1[] = {
144
{ TYPE_PCI_DEVICE, "x-pcie-ext-tag", "false" },
145
+ { TYPE_ACPI_GED, "x-has-hest-addr", "false" },
146
};
147
const size_t hw_compat_9_1_len = G_N_ELEMENTS(hw_compat_9_1);
148
149
diff --git a/include/hw/acpi/ghes.h b/include/hw/acpi/ghes.h
150
index XXXXXXX..XXXXXXX 100644
151
--- a/include/hw/acpi/ghes.h
152
+++ b/include/hw/acpi/ghes.h
153
@@ -XXX,XX +XXX,XX @@ typedef struct AcpiGhesState {
154
uint64_t hest_addr_le;
155
uint64_t hw_error_le;
156
bool present; /* True if GHES is present at all on this board */
157
+ bool hest_lookup; /* True if HEST address is present */
158
} AcpiGhesState;
159
160
/*
161
--
162
2.47.1
diff view generated by jsdifflib
Deleted patch
1
Some error injection notify methods are async, like GPIO
2
notify. Add a notifier to be used when the error record is
3
ready to be sent to the guest OS.
4
1
5
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
6
---
7
hw/acpi/ghes.c | 5 ++++-
8
include/hw/acpi/ghes.h | 3 +++
9
2 files changed, 7 insertions(+), 1 deletion(-)
10
11
diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/acpi/ghes.c
14
+++ b/hw/acpi/ghes.c
15
@@ -XXX,XX +XXX,XX @@ static void get_ghes_source_offsets(uint16_t source_id, uint64_t hest_addr,
16
*read_ack_start_addr = le64_to_cpu(*read_ack_start_addr);
17
}
18
19
+NotifierList acpi_generic_error_notifiers =
20
+ NOTIFIER_LIST_INITIALIZER(error_device_notifiers);
21
+
22
void ghes_record_cper_errors(const void *cper, size_t len,
23
uint16_t source_id, Error **errp)
24
{
25
@@ -XXX,XX +XXX,XX @@ void ghes_record_cper_errors(const void *cper, size_t len,
26
/* Write the generic error data entry into guest memory */
27
cpu_physical_memory_write(cper_addr, cper, len);
28
29
- return;
30
+ notifier_list_notify(&acpi_generic_error_notifiers, NULL);
31
}
32
33
int acpi_ghes_memory_errors(uint16_t source_id, uint64_t physical_address)
34
diff --git a/include/hw/acpi/ghes.h b/include/hw/acpi/ghes.h
35
index XXXXXXX..XXXXXXX 100644
36
--- a/include/hw/acpi/ghes.h
37
+++ b/include/hw/acpi/ghes.h
38
@@ -XXX,XX +XXX,XX @@
39
40
#include "hw/acpi/bios-linker-loader.h"
41
#include "qapi/error.h"
42
+#include "qemu/notify.h"
43
+
44
+extern NotifierList acpi_generic_error_notifiers;
45
46
/*
47
* Values for Hardware Error Notification Type field
48
--
49
2.47.1
diff view generated by jsdifflib
Deleted patch
1
Adds a generic error device to handle generic hardware error
2
events as specified at ACPI 6.5 specification at 18.3.2.7.2:
3
https://uefi.org/specs/ACPI/6.5/18_Platform_Error_Interfaces.html#event-notification-for-generic-error-sources
4
using HID PNP0C33.
5
1
6
The PNP0C33 device is used to report hardware errors to
7
the guest via ACPI APEI Generic Hardware Error Source (GHES).
8
9
Co-authored-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
10
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
11
Co-authored-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
12
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
13
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
14
---
15
hw/acpi/aml-build.c | 10 ++++++++++
16
hw/acpi/generic_event_device.c | 8 ++++++++
17
include/hw/acpi/acpi_dev_interface.h | 1 +
18
include/hw/acpi/aml-build.h | 2 ++
19
include/hw/acpi/generic_event_device.h | 1 +
20
5 files changed, 22 insertions(+)
21
22
diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
23
index XXXXXXX..XXXXXXX 100644
24
--- a/hw/acpi/aml-build.c
25
+++ b/hw/acpi/aml-build.c
26
@@ -XXX,XX +XXX,XX @@ Aml *aml_i2c_serial_bus_device(uint16_t address, const char *resource_source)
27
28
return var;
29
}
30
+
31
+/* ACPI 5.0b: 18.3.2.6.2 Event Notification For Generic Error Sources */
32
+Aml *aml_error_device(void)
33
+{
34
+ Aml *dev = aml_device(ACPI_APEI_ERROR_DEVICE);
35
+ aml_append(dev, aml_name_decl("_HID", aml_string("PNP0C33")));
36
+ aml_append(dev, aml_name_decl("_UID", aml_int(0)));
37
+
38
+ return dev;
39
+}
40
diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/hw/acpi/generic_event_device.c
43
+++ b/hw/acpi/generic_event_device.c
44
@@ -XXX,XX +XXX,XX @@ static const uint32_t ged_supported_events[] = {
45
ACPI_GED_PWR_DOWN_EVT,
46
ACPI_GED_NVDIMM_HOTPLUG_EVT,
47
ACPI_GED_CPU_HOTPLUG_EVT,
48
+ ACPI_GED_ERROR_EVT,
49
};
50
51
/*
52
@@ -XXX,XX +XXX,XX @@ void build_ged_aml(Aml *table, const char *name, HotplugHandler *hotplug_dev,
53
aml_notify(aml_name(ACPI_POWER_BUTTON_DEVICE),
54
aml_int(0x80)));
55
break;
56
+ case ACPI_GED_ERROR_EVT:
57
+ aml_append(if_ctx,
58
+ aml_notify(aml_name(ACPI_APEI_ERROR_DEVICE),
59
+ aml_int(0x80)));
60
+ break;
61
case ACPI_GED_NVDIMM_HOTPLUG_EVT:
62
aml_append(if_ctx,
63
aml_notify(aml_name("\\_SB.NVDR"),
64
@@ -XXX,XX +XXX,XX @@ static void acpi_ged_send_event(AcpiDeviceIf *adev, AcpiEventStatusBits ev)
65
sel = ACPI_GED_MEM_HOTPLUG_EVT;
66
} else if (ev & ACPI_POWER_DOWN_STATUS) {
67
sel = ACPI_GED_PWR_DOWN_EVT;
68
+ } else if (ev & ACPI_GENERIC_ERROR) {
69
+ sel = ACPI_GED_ERROR_EVT;
70
} else if (ev & ACPI_NVDIMM_HOTPLUG_STATUS) {
71
sel = ACPI_GED_NVDIMM_HOTPLUG_EVT;
72
} else if (ev & ACPI_CPU_HOTPLUG_STATUS) {
73
diff --git a/include/hw/acpi/acpi_dev_interface.h b/include/hw/acpi/acpi_dev_interface.h
74
index XXXXXXX..XXXXXXX 100644
75
--- a/include/hw/acpi/acpi_dev_interface.h
76
+++ b/include/hw/acpi/acpi_dev_interface.h
77
@@ -XXX,XX +XXX,XX @@ typedef enum {
78
ACPI_NVDIMM_HOTPLUG_STATUS = 16,
79
ACPI_VMGENID_CHANGE_STATUS = 32,
80
ACPI_POWER_DOWN_STATUS = 64,
81
+ ACPI_GENERIC_ERROR = 128,
82
} AcpiEventStatusBits;
83
84
#define TYPE_ACPI_DEVICE_IF "acpi-device-interface"
85
diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
86
index XXXXXXX..XXXXXXX 100644
87
--- a/include/hw/acpi/aml-build.h
88
+++ b/include/hw/acpi/aml-build.h
89
@@ -XXX,XX +XXX,XX @@ struct CrsRangeSet {
90
/* Consumer/Producer */
91
#define AML_SERIAL_BUS_FLAG_CONSUME_ONLY (1 << 1)
92
93
+#define ACPI_APEI_ERROR_DEVICE "GEDD"
94
/**
95
* init_aml_allocator:
96
*
97
@@ -XXX,XX +XXX,XX @@ Aml *aml_dma(AmlDmaType typ, AmlDmaBusMaster bm, AmlTransferSize sz,
98
uint8_t channel);
99
Aml *aml_sleep(uint64_t msec);
100
Aml *aml_i2c_serial_bus_device(uint16_t address, const char *resource_source);
101
+Aml *aml_error_device(void);
102
103
/* Block AML object primitives */
104
Aml *aml_scope(const char *name_format, ...) G_GNUC_PRINTF(1, 2);
105
diff --git a/include/hw/acpi/generic_event_device.h b/include/hw/acpi/generic_event_device.h
106
index XXXXXXX..XXXXXXX 100644
107
--- a/include/hw/acpi/generic_event_device.h
108
+++ b/include/hw/acpi/generic_event_device.h
109
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(AcpiGedState, ACPI_GED)
110
#define ACPI_GED_PWR_DOWN_EVT 0x2
111
#define ACPI_GED_NVDIMM_HOTPLUG_EVT 0x4
112
#define ACPI_GED_CPU_HOTPLUG_EVT 0x8
113
+#define ACPI_GED_ERROR_EVT 0x10
114
115
typedef struct GEDState {
116
MemoryRegion evt;
117
--
118
2.47.1
diff view generated by jsdifflib
Deleted patch
1
Adds support to ARM virtualization to allow handling
2
generic error ACPI Event via GED & error source device.
3
1
4
It is aligned with Linux Kernel patch:
5
https://lore.kernel.org/lkml/1272350481-27951-8-git-send-email-ying.huang@intel.com/
6
7
Co-authored-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
8
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
9
Co-authored-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
10
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
11
Acked-by: Igor Mammedov <imammedo@redhat.com>
12
13
---
14
15
Changes from v8:
16
17
- Added a call to the function that produces GHES generic
18
records, as this is now added earlier in this series.
19
20
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
21
---
22
hw/arm/virt-acpi-build.c | 1 +
23
hw/arm/virt.c | 12 +++++++++++-
24
include/hw/arm/virt.h | 1 +
25
3 files changed, 13 insertions(+), 1 deletion(-)
26
27
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
28
index XXXXXXX..XXXXXXX 100644
29
--- a/hw/arm/virt-acpi-build.c
30
+++ b/hw/arm/virt-acpi-build.c
31
@@ -XXX,XX +XXX,XX @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
32
}
33
34
acpi_dsdt_add_power_button(scope);
35
+ aml_append(scope, aml_error_device());
36
#ifdef CONFIG_TPM
37
acpi_dsdt_add_tpm(scope, vms);
38
#endif
39
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/hw/arm/virt.c
42
+++ b/hw/arm/virt.c
43
@@ -XXX,XX +XXX,XX @@ static inline DeviceState *create_acpi_ged(VirtMachineState *vms)
44
DeviceState *dev;
45
MachineState *ms = MACHINE(vms);
46
int irq = vms->irqmap[VIRT_ACPI_GED];
47
- uint32_t event = ACPI_GED_PWR_DOWN_EVT;
48
+ uint32_t event = ACPI_GED_PWR_DOWN_EVT | ACPI_GED_ERROR_EVT;
49
50
if (ms->ram_slots) {
51
event |= ACPI_GED_MEM_HOTPLUG_EVT;
52
@@ -XXX,XX +XXX,XX @@ static void virt_powerdown_req(Notifier *n, void *opaque)
53
}
54
}
55
56
+static void virt_generic_error_req(Notifier *n, void *opaque)
57
+{
58
+ VirtMachineState *s = container_of(n, VirtMachineState, generic_error_notifier);
59
+
60
+ acpi_send_event(s->acpi_dev, ACPI_GENERIC_ERROR);
61
+}
62
+
63
static void create_gpio_keys(char *fdt, DeviceState *pl061_dev,
64
uint32_t phandle)
65
{
66
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
67
68
if (has_ged && aarch64 && firmware_loaded && virt_is_acpi_enabled(vms)) {
69
vms->acpi_dev = create_acpi_ged(vms);
70
+ vms->generic_error_notifier.notify = virt_generic_error_req;
71
+ notifier_list_add(&acpi_generic_error_notifiers,
72
+ &vms->generic_error_notifier);
73
} else {
74
create_gpio_devices(vms, VIRT_GPIO, sysmem);
75
}
76
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
77
index XXXXXXX..XXXXXXX 100644
78
--- a/include/hw/arm/virt.h
79
+++ b/include/hw/arm/virt.h
80
@@ -XXX,XX +XXX,XX @@ struct VirtMachineState {
81
DeviceState *gic;
82
DeviceState *acpi_dev;
83
Notifier powerdown_notifier;
84
+ Notifier generic_error_notifier;
85
PCIBus *bus;
86
char *oem_id;
87
char *oem_table_id;
88
--
89
2.47.1
diff view generated by jsdifflib
Deleted patch
1
Creates a QMP command to be used for generic ACPI APEI hardware error
2
injection (HEST) via GHESv2, and add support for it for ARM guests.
3
1
4
Error injection uses ACPI_HEST_SRC_ID_QMP source ID to be platform
5
independent. This is mapped at arch virt bindings, depending on the
6
types supported by QEMU and by the BIOS. So, on ARM, this is supported
7
via ACPI_GHES_NOTIFY_GPIO notification type.
8
9
This patch is co-authored:
10
- original ghes logic to inject a simple ARM record by Shiju Jose;
11
- generic logic to handle block addresses by Jonathan Cameron;
12
- generic GHESv2 error inject by Mauro Carvalho Chehab;
13
14
Co-authored-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
15
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
16
Co-authored-by: Shiju Jose <shiju.jose@huawei.com>
17
Signed-off-by: Shiju Jose <shiju.jose@huawei.com>
18
Co-authored-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
19
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
20
21
---
22
23
Changes since v9:
24
- ARM source IDs renamed to reflect SYNC/ASYNC;
25
- command name changed to better reflect what it does;
26
- some improvements at JSON documentation;
27
- add a check for QMP source at the notification logic.
28
29
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
30
---
31
MAINTAINERS | 7 +++++++
32
hw/acpi/Kconfig | 5 +++++
33
hw/acpi/ghes.c | 2 +-
34
hw/acpi/ghes_cper.c | 32 ++++++++++++++++++++++++++++++++
35
hw/acpi/ghes_cper_stub.c | 19 +++++++++++++++++++
36
hw/acpi/meson.build | 2 ++
37
hw/arm/virt-acpi-build.c | 1 +
38
hw/arm/virt.c | 7 +++++++
39
include/hw/acpi/ghes.h | 1 +
40
include/hw/arm/virt.h | 1 +
41
qapi/acpi-hest.json | 35 +++++++++++++++++++++++++++++++++++
42
qapi/meson.build | 1 +
43
qapi/qapi-schema.json | 1 +
44
13 files changed, 113 insertions(+), 1 deletion(-)
45
create mode 100644 hw/acpi/ghes_cper.c
46
create mode 100644 hw/acpi/ghes_cper_stub.c
47
create mode 100644 qapi/acpi-hest.json
48
49
diff --git a/MAINTAINERS b/MAINTAINERS
50
index XXXXXXX..XXXXXXX 100644
51
--- a/MAINTAINERS
52
+++ b/MAINTAINERS
53
@@ -XXX,XX +XXX,XX @@ F: hw/acpi/ghes.c
54
F: include/hw/acpi/ghes.h
55
F: docs/specs/acpi_hest_ghes.rst
56
57
+ACPI/HEST/GHES/ARM processor CPER
58
+R: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
59
+S: Maintained
60
+F: hw/arm/ghes_cper.c
61
+F: hw/acpi/ghes_cper_stub.c
62
+F: qapi/acpi-hest.json
63
+
64
ppc4xx
65
L: qemu-ppc@nongnu.org
66
S: Orphan
67
diff --git a/hw/acpi/Kconfig b/hw/acpi/Kconfig
68
index XXXXXXX..XXXXXXX 100644
69
--- a/hw/acpi/Kconfig
70
+++ b/hw/acpi/Kconfig
71
@@ -XXX,XX +XXX,XX @@ config ACPI_APEI
72
bool
73
depends on ACPI
74
75
+config GHES_CPER
76
+ bool
77
+ depends on ACPI_APEI
78
+ default y
79
+
80
config ACPI_PCI
81
bool
82
depends on ACPI && PCI
83
diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c
84
index XXXXXXX..XXXXXXX 100644
85
--- a/hw/acpi/ghes.c
86
+++ b/hw/acpi/ghes.c
87
@@ -XXX,XX +XXX,XX @@ void ghes_record_cper_errors(const void *cper, size_t len,
88
/* Write the generic error data entry into guest memory */
89
cpu_physical_memory_write(cper_addr, cper, len);
90
91
- notifier_list_notify(&acpi_generic_error_notifiers, NULL);
92
+ notifier_list_notify(&acpi_generic_error_notifiers, &source_id);
93
}
94
95
int acpi_ghes_memory_errors(uint16_t source_id, uint64_t physical_address)
96
diff --git a/hw/acpi/ghes_cper.c b/hw/acpi/ghes_cper.c
97
new file mode 100644
98
index XXXXXXX..XXXXXXX
99
--- /dev/null
100
+++ b/hw/acpi/ghes_cper.c
101
@@ -XXX,XX +XXX,XX @@
102
+/*
103
+ * CPER payload parser for error injection
104
+ *
105
+ * Copyright(C) 2024 Huawei LTD.
106
+ *
107
+ * This code is licensed under the GPL version 2 or later. See the
108
+ * COPYING file in the top-level directory.
109
+ *
110
+ */
111
+
112
+#include "qemu/osdep.h"
113
+
114
+#include "qemu/base64.h"
115
+#include "qemu/error-report.h"
116
+#include "qemu/uuid.h"
117
+#include "qapi/qapi-commands-acpi-hest.h"
118
+#include "hw/acpi/ghes.h"
119
+
120
+void qmp_inject_ghes_error(const char *qmp_cper, Error **errp)
121
+{
122
+
123
+ uint8_t *cper;
124
+ size_t len;
125
+
126
+ cper = qbase64_decode(qmp_cper, -1, &len, errp);
127
+ if (!cper) {
128
+ error_setg(errp, "missing GHES CPER payload");
129
+ return;
130
+ }
131
+
132
+ ghes_record_cper_errors(cper, len, ACPI_HEST_SRC_ID_QMP, errp);
133
+}
134
diff --git a/hw/acpi/ghes_cper_stub.c b/hw/acpi/ghes_cper_stub.c
135
new file mode 100644
136
index XXXXXXX..XXXXXXX
137
--- /dev/null
138
+++ b/hw/acpi/ghes_cper_stub.c
139
@@ -XXX,XX +XXX,XX @@
140
+/*
141
+ * Stub interface for CPER payload parser for error injection
142
+ *
143
+ * Copyright(C) 2024 Huawei LTD.
144
+ *
145
+ * This code is licensed under the GPL version 2 or later. See the
146
+ * COPYING file in the top-level directory.
147
+ *
148
+ */
149
+
150
+#include "qemu/osdep.h"
151
+#include "qapi/error.h"
152
+#include "qapi/qapi-commands-acpi-hest.h"
153
+#include "hw/acpi/ghes.h"
154
+
155
+void qmp_inject_ghes_error(const char *cper, Error **errp)
156
+{
157
+ error_setg(errp, "GHES QMP error inject is not compiled in");
158
+}
159
diff --git a/hw/acpi/meson.build b/hw/acpi/meson.build
160
index XXXXXXX..XXXXXXX 100644
161
--- a/hw/acpi/meson.build
162
+++ b/hw/acpi/meson.build
163
@@ -XXX,XX +XXX,XX @@ endif
164
system_ss.add(when: 'CONFIG_ACPI', if_false: files('acpi-stub.c', 'aml-build-stub.c', 'ghes-stub.c', 'acpi_interface.c'))
165
system_ss.add(when: 'CONFIG_ACPI_PCI_BRIDGE', if_false: files('pci-bridge-stub.c'))
166
system_ss.add_all(when: 'CONFIG_ACPI', if_true: acpi_ss)
167
+system_ss.add(when: 'CONFIG_GHES_CPER', if_true: files('ghes_cper.c'))
168
+system_ss.add(when: 'CONFIG_GHES_CPER', if_false: files('ghes_cper_stub.c'))
169
system_ss.add(files('acpi-qmp-cmds.c'))
170
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
171
index XXXXXXX..XXXXXXX 100644
172
--- a/hw/arm/virt-acpi-build.c
173
+++ b/hw/arm/virt-acpi-build.c
174
@@ -XXX,XX +XXX,XX @@ static void acpi_align_size(GArray *blob, unsigned align)
175
176
static const AcpiNotificationSourceId hest_ghes_notify[] = {
177
{ ACPI_HEST_SRC_ID_SYNC, ACPI_GHES_NOTIFY_SEA },
178
+ { ACPI_HEST_SRC_ID_QMP, ACPI_GHES_NOTIFY_GPIO },
179
};
180
181
static const AcpiNotificationSourceId hest_ghes_notify_9_1[] = {
182
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
183
index XXXXXXX..XXXXXXX 100644
184
--- a/hw/arm/virt.c
185
+++ b/hw/arm/virt.c
186
@@ -XXX,XX +XXX,XX @@ static void virt_powerdown_req(Notifier *n, void *opaque)
187
188
static void virt_generic_error_req(Notifier *n, void *opaque)
189
{
190
+ uint16_t *source_id = opaque;
191
+
192
+ /* Currently, only QMP source ID is async */
193
+ if (*source_id != ACPI_HEST_SRC_ID_QMP) {
194
+ return;
195
+ }
196
+
197
VirtMachineState *s = container_of(n, VirtMachineState, generic_error_notifier);
198
199
acpi_send_event(s->acpi_dev, ACPI_GENERIC_ERROR);
200
diff --git a/include/hw/acpi/ghes.h b/include/hw/acpi/ghes.h
201
index XXXXXXX..XXXXXXX 100644
202
--- a/include/hw/acpi/ghes.h
203
+++ b/include/hw/acpi/ghes.h
204
@@ -XXX,XX +XXX,XX @@ typedef struct AcpiGhesState {
205
*/
206
enum AcpiGhesSourceID {
207
ACPI_HEST_SRC_ID_SYNC,
208
+ ACPI_HEST_SRC_ID_QMP, /* Use it only for QMP injected errors */
209
};
210
211
typedef struct AcpiNotificationSourceId {
212
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
213
index XXXXXXX..XXXXXXX 100644
214
--- a/include/hw/arm/virt.h
215
+++ b/include/hw/arm/virt.h
216
@@ -XXX,XX +XXX,XX @@
217
#include "exec/hwaddr.h"
218
#include "qemu/notify.h"
219
#include "hw/boards.h"
220
+#include "hw/acpi/ghes.h"
221
#include "hw/arm/boot.h"
222
#include "hw/arm/bsa.h"
223
#include "hw/block/flash.h"
224
diff --git a/qapi/acpi-hest.json b/qapi/acpi-hest.json
225
new file mode 100644
226
index XXXXXXX..XXXXXXX
227
--- /dev/null
228
+++ b/qapi/acpi-hest.json
229
@@ -XXX,XX +XXX,XX @@
230
+# -*- Mode: Python -*-
231
+# vim: filetype=python
232
+
233
+##
234
+# == GHESv2 CPER Error Injection
235
+#
236
+# Defined since ACPI Specification 6.1,
237
+# section 18.3.2.8 Generic Hardware Error Source version 2. See:
238
+#
239
+# https://uefi.org/sites/default/files/resources/ACPI_6_1.pdf
240
+##
241
+
242
+
243
+##
244
+# @inject-ghes-error:
245
+#
246
+# Inject an error with additional ACPI 6.1 GHESv2 error information
247
+#
248
+# @cper: contains a base64 encoded string with raw data for a single
249
+# CPER record with Generic Error Status Block, Generic Error Data
250
+# Entry and generic error data payload, as described at
251
+# https://uefi.org/specs/UEFI/2.10/Apx_N_Common_Platform_Error_Record.html#format
252
+#
253
+# Features:
254
+#
255
+# @unstable: This command is experimental.
256
+#
257
+# Since: 9.2
258
+##
259
+{ 'command': 'inject-ghes-error',
260
+ 'data': {
261
+ 'cper': 'str'
262
+ },
263
+ 'features': [ 'unstable' ]
264
+}
265
diff --git a/qapi/meson.build b/qapi/meson.build
266
index XXXXXXX..XXXXXXX 100644
267
--- a/qapi/meson.build
268
+++ b/qapi/meson.build
269
@@ -XXX,XX +XXX,XX @@ qapi_all_modules = [
270
if have_system
271
qapi_all_modules += [
272
'acpi',
273
+ 'acpi-hest',
274
'audio',
275
'cryptodev',
276
'qdev',
277
diff --git a/qapi/qapi-schema.json b/qapi/qapi-schema.json
278
index XXXXXXX..XXXXXXX 100644
279
--- a/qapi/qapi-schema.json
280
+++ b/qapi/qapi-schema.json
281
@@ -XXX,XX +XXX,XX @@
282
{ 'include': 'misc-target.json' }
283
{ 'include': 'audio.json' }
284
{ 'include': 'acpi.json' }
285
+{ 'include': 'acpi-hest.json' }
286
{ 'include': 'pci.json' }
287
{ 'include': 'stats.json' }
288
{ 'include': 'virtio.json' }
289
--
290
2.47.1
diff view generated by jsdifflib
Deleted patch
1
Using the QMP GHESv2 API requires preparing a raw data array
2
containing a CPER record.
3
1
4
Add a helper script with subcommands to prepare such data.
5
6
Currently, only ARM Processor error CPER record is supported.
7
8
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
9
---
10
MAINTAINERS | 3 +
11
scripts/arm_processor_error.py | 377 ++++++++++++++++++
12
scripts/ghes_inject.py | 51 +++
13
scripts/qmp_helper.py | 702 +++++++++++++++++++++++++++++++++
14
4 files changed, 1133 insertions(+)
15
create mode 100644 scripts/arm_processor_error.py
16
create mode 100755 scripts/ghes_inject.py
17
create mode 100644 scripts/qmp_helper.py
18
19
diff --git a/MAINTAINERS b/MAINTAINERS
20
index XXXXXXX..XXXXXXX 100644
21
--- a/MAINTAINERS
22
+++ b/MAINTAINERS
23
@@ -XXX,XX +XXX,XX @@ S: Maintained
24
F: hw/arm/ghes_cper.c
25
F: hw/acpi/ghes_cper_stub.c
26
F: qapi/acpi-hest.json
27
+F: scripts/ghes_inject.py
28
+F: scripts/arm_processor_error.py
29
+F: scripts/qmp_helper.py
30
31
ppc4xx
32
L: qemu-ppc@nongnu.org
33
diff --git a/scripts/arm_processor_error.py b/scripts/arm_processor_error.py
34
new file mode 100644
35
index XXXXXXX..XXXXXXX
36
--- /dev/null
37
+++ b/scripts/arm_processor_error.py
38
@@ -XXX,XX +XXX,XX @@
39
+#!/usr/bin/env python3
40
+#
41
+# pylint: disable=C0301,C0114,R0903,R0912,R0913,R0914,R0915,W0511
42
+# SPDX-License-Identifier: GPL-2.0
43
+#
44
+# Copyright (C) 2024 Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
45
+
46
+# TODO: current implementation has dummy defaults.
47
+#
48
+# For a better implementation, a QMP addition/call is needed to
49
+# retrieve some data for ARM Processor Error injection:
50
+#
51
+# - ARM registers: power_state, mpidr.
52
+
53
+import argparse
54
+import re
55
+
56
+from qmp_helper import qmp, util, cper_guid
57
+
58
+class ArmProcessorEinj:
59
+ """
60
+ Implements ARM Processor Error injection via GHES
61
+ """
62
+
63
+ DESC = """
64
+ Generates an ARM processor error CPER, compatible with
65
+ UEFI 2.9A Errata.
66
+ """
67
+
68
+ ACPI_GHES_ARM_CPER_LENGTH = 40
69
+ ACPI_GHES_ARM_CPER_PEI_LENGTH = 32
70
+
71
+ # Context types
72
+ CONTEXT_AARCH32_EL1 = 1
73
+ CONTEXT_AARCH64_EL1 = 5
74
+ CONTEXT_MISC_REG = 8
75
+
76
+ def __init__(self, subparsers):
77
+ """Initialize the error injection class and add subparser"""
78
+
79
+ # Valid choice values
80
+ self.arm_valid_bits = {
81
+ "mpidr": util.bit(0),
82
+ "affinity": util.bit(1),
83
+ "running": util.bit(2),
84
+ "vendor": util.bit(3),
85
+ }
86
+
87
+ self.pei_flags = {
88
+ "first": util.bit(0),
89
+ "last": util.bit(1),
90
+ "propagated": util.bit(2),
91
+ "overflow": util.bit(3),
92
+ }
93
+
94
+ self.pei_error_types = {
95
+ "cache": util.bit(1),
96
+ "tlb": util.bit(2),
97
+ "bus": util.bit(3),
98
+ "micro-arch": util.bit(4),
99
+ }
100
+
101
+ self.pei_valid_bits = {
102
+ "multiple-error": util.bit(0),
103
+ "flags": util.bit(1),
104
+ "error-info": util.bit(2),
105
+ "virt-addr": util.bit(3),
106
+ "phy-addr": util.bit(4),
107
+ }
108
+
109
+ self.data = bytearray()
110
+
111
+ parser = subparsers.add_parser("arm", description=self.DESC)
112
+
113
+ arm_valid_bits = ",".join(self.arm_valid_bits.keys())
114
+ flags = ",".join(self.pei_flags.keys())
115
+ error_types = ",".join(self.pei_error_types.keys())
116
+ pei_valid_bits = ",".join(self.pei_valid_bits.keys())
117
+
118
+ # UEFI N.16 ARM Validation bits
119
+ g_arm = parser.add_argument_group("ARM processor")
120
+ g_arm.add_argument("--arm", "--arm-valid",
121
+ help=f"ARM valid bits: {arm_valid_bits}")
122
+ g_arm.add_argument("-a", "--affinity", "--level", "--affinity-level",
123
+ type=lambda x: int(x, 0),
124
+ help="Affinity level (when multiple levels apply)")
125
+ g_arm.add_argument("-l", "--mpidr", type=lambda x: int(x, 0),
126
+ help="Multiprocessor Affinity Register")
127
+ g_arm.add_argument("-i", "--midr", type=lambda x: int(x, 0),
128
+ help="Main ID Register")
129
+ g_arm.add_argument("-r", "--running",
130
+ action=argparse.BooleanOptionalAction,
131
+ default=None,
132
+ help="Indicates if the processor is running or not")
133
+ g_arm.add_argument("--psci", "--psci-state",
134
+ type=lambda x: int(x, 0),
135
+ help="Power State Coordination Interface - PSCI state")
136
+
137
+ # TODO: Add vendor-specific support
138
+
139
+ # UEFI N.17 bitmaps (type and flags)
140
+ g_pei = parser.add_argument_group("ARM Processor Error Info (PEI)")
141
+ g_pei.add_argument("-t", "--type", nargs="+",
142
+ help=f"one or more error types: {error_types}")
143
+ g_pei.add_argument("-f", "--flags", nargs="*",
144
+ help=f"zero or more error flags: {flags}")
145
+ g_pei.add_argument("-V", "--pei-valid", "--error-valid", nargs="*",
146
+ help=f"zero or more PEI valid bits: {pei_valid_bits}")
147
+
148
+ # UEFI N.17 Integer values
149
+ g_pei.add_argument("-m", "--multiple-error", nargs="+",
150
+ help="Number of errors: 0: Single error, 1: Multiple errors, 2-65535: Error count if known")
151
+ g_pei.add_argument("-e", "--error-info", nargs="+",
152
+ help="Error information (UEFI 2.10 tables N.18 to N.20)")
153
+ g_pei.add_argument("-p", "--physical-address", nargs="+",
154
+ help="Physical address")
155
+ g_pei.add_argument("-v", "--virtual-address", nargs="+",
156
+ help="Virtual address")
157
+
158
+ # UEFI N.21 Context
159
+ g_ctx = parser.add_argument_group("Processor Context")
160
+ g_ctx.add_argument("--ctx-type", "--context-type", nargs="*",
161
+ help="Type of the context (0=ARM32 GPR, 5=ARM64 EL1, other values supported)")
162
+ g_ctx.add_argument("--ctx-size", "--context-size", nargs="*",
163
+ help="Minimal size of the context")
164
+ g_ctx.add_argument("--ctx-array", "--context-array", nargs="*",
165
+ help="Comma-separated arrays for each context")
166
+
167
+ # Vendor-specific data
168
+ g_vendor = parser.add_argument_group("Vendor-specific data")
169
+ g_vendor.add_argument("--vendor", "--vendor-specific", nargs="+",
170
+ help="Vendor-specific byte arrays of data")
171
+
172
+ # Add arguments for Generic Error Data
173
+ qmp.argparse(parser)
174
+
175
+ parser.set_defaults(func=self.send_cper)
176
+
177
+ def send_cper(self, args):
178
+ """Parse subcommand arguments and send a CPER via QMP"""
179
+
180
+ qmp_cmd = qmp(args.host, args.port, args.debug)
181
+
182
+ # Handle Generic Error Data arguments if any
183
+ qmp_cmd.set_args(args)
184
+
185
+ is_cpu_type = re.compile(r"^([\w+]+\-)?arm\-cpu$")
186
+ cpus = qmp_cmd.search_qom("/machine/unattached/device",
187
+ "type", is_cpu_type)
188
+
189
+ cper = {}
190
+ pei = {}
191
+ ctx = {}
192
+ vendor = {}
193
+
194
+ arg = vars(args)
195
+
196
+ # Handle global parameters
197
+ if args.arm:
198
+ arm_valid_init = False
199
+ cper["valid"] = util.get_choice(name="valid",
200
+ value=args.arm,
201
+ choices=self.arm_valid_bits,
202
+ suffixes=["-error", "-err"])
203
+ else:
204
+ cper["valid"] = 0
205
+ arm_valid_init = True
206
+
207
+ if "running" in arg:
208
+ if args.running:
209
+ cper["running-state"] = util.bit(0)
210
+ else:
211
+ cper["running-state"] = 0
212
+ else:
213
+ cper["running-state"] = 0
214
+
215
+ if arm_valid_init:
216
+ if args.affinity:
217
+ cper["valid"] |= self.arm_valid_bits["affinity"]
218
+
219
+ if args.mpidr:
220
+ cper["valid"] |= self.arm_valid_bits["mpidr"]
221
+
222
+ if "running-state" in cper:
223
+ cper["valid"] |= self.arm_valid_bits["running"]
224
+
225
+ if args.psci:
226
+ cper["valid"] |= self.arm_valid_bits["running"]
227
+
228
+ # Handle PEI
229
+ if not args.type:
230
+ args.type = ["cache-error"]
231
+
232
+ util.get_mult_choices(
233
+ pei,
234
+ name="valid",
235
+ values=args.pei_valid,
236
+ choices=self.pei_valid_bits,
237
+ suffixes=["-valid", "--addr"],
238
+ )
239
+ util.get_mult_choices(
240
+ pei,
241
+ name="type",
242
+ values=args.type,
243
+ choices=self.pei_error_types,
244
+ suffixes=["-error", "-err"],
245
+ )
246
+ util.get_mult_choices(
247
+ pei,
248
+ name="flags",
249
+ values=args.flags,
250
+ choices=self.pei_flags,
251
+ suffixes=["-error", "-cap"],
252
+ )
253
+ util.get_mult_int(pei, "error-info", args.error_info)
254
+ util.get_mult_int(pei, "multiple-error", args.multiple_error)
255
+ util.get_mult_int(pei, "phy-addr", args.physical_address)
256
+ util.get_mult_int(pei, "virt-addr", args.virtual_address)
257
+
258
+ # Handle context
259
+ util.get_mult_int(ctx, "type", args.ctx_type, allow_zero=True)
260
+ util.get_mult_int(ctx, "minimal-size", args.ctx_size, allow_zero=True)
261
+ util.get_mult_array(ctx, "register", args.ctx_array, allow_zero=True)
262
+
263
+ util.get_mult_array(vendor, "bytes", args.vendor, max_val=255)
264
+
265
+ # Store PEI
266
+ pei_data = bytearray()
267
+ default_flags = self.pei_flags["first"]
268
+ default_flags |= self.pei_flags["last"]
269
+
270
+ error_info_num = 0
271
+
272
+ for i, p in pei.items(): # pylint: disable=W0612
273
+ error_info_num += 1
274
+
275
+ # UEFI 2.10 doesn't define how to encode error information
276
+ # when multiple types are raised. So, provide a default only
277
+ # if a single type is there
278
+ if "error-info" not in p:
279
+ if p["type"] == util.bit(1):
280
+ p["error-info"] = 0x0091000F
281
+ if p["type"] == util.bit(2):
282
+ p["error-info"] = 0x0054007F
283
+ if p["type"] == util.bit(3):
284
+ p["error-info"] = 0x80D6460FFF
285
+ if p["type"] == util.bit(4):
286
+ p["error-info"] = 0x78DA03FF
287
+
288
+ if "valid" not in p:
289
+ p["valid"] = 0
290
+ if "multiple-error" in p:
291
+ p["valid"] |= self.pei_valid_bits["multiple-error"]
292
+
293
+ if "flags" in p:
294
+ p["valid"] |= self.pei_valid_bits["flags"]
295
+
296
+ if "error-info" in p:
297
+ p["valid"] |= self.pei_valid_bits["error-info"]
298
+
299
+ if "phy-addr" in p:
300
+ p["valid"] |= self.pei_valid_bits["phy-addr"]
301
+
302
+ if "virt-addr" in p:
303
+ p["valid"] |= self.pei_valid_bits["virt-addr"]
304
+
305
+ # Version
306
+ util.data_add(pei_data, 0, 1)
307
+
308
+ util.data_add(pei_data,
309
+ self.ACPI_GHES_ARM_CPER_PEI_LENGTH, 1)
310
+
311
+ util.data_add(pei_data, p["valid"], 2)
312
+ util.data_add(pei_data, p["type"], 1)
313
+ util.data_add(pei_data, p.get("multiple-error", 1), 2)
314
+ util.data_add(pei_data, p.get("flags", default_flags), 1)
315
+ util.data_add(pei_data, p.get("error-info", 0), 8)
316
+ util.data_add(pei_data, p.get("virt-addr", 0xDEADBEEF), 8)
317
+ util.data_add(pei_data, p.get("phy-addr", 0xABBA0BAD), 8)
318
+
319
+ # Store Context
320
+ ctx_data = bytearray()
321
+ context_info_num = 0
322
+
323
+ if ctx:
324
+ ret = qmp_cmd.send_cmd("query-target", may_open=True)
325
+
326
+ default_ctx = self.CONTEXT_MISC_REG
327
+
328
+ if "arch" in ret:
329
+ if ret["arch"] == "aarch64":
330
+ default_ctx = self.CONTEXT_AARCH64_EL1
331
+ elif ret["arch"] == "arm":
332
+ default_ctx = self.CONTEXT_AARCH32_EL1
333
+
334
+ for k in sorted(ctx.keys()):
335
+ context_info_num += 1
336
+
337
+ if "type" not in ctx[k]:
338
+ ctx[k]["type"] = default_ctx
339
+
340
+ if "register" not in ctx[k]:
341
+ ctx[k]["register"] = []
342
+
343
+ reg_size = len(ctx[k]["register"])
344
+ size = 0
345
+
346
+ if "minimal-size" in ctx:
347
+ size = ctx[k]["minimal-size"]
348
+
349
+ size = max(size, reg_size)
350
+
351
+ size = (size + 1) % 0xFFFE
352
+
353
+ # Version
354
+ util.data_add(ctx_data, 0, 2)
355
+
356
+ util.data_add(ctx_data, ctx[k]["type"], 2)
357
+
358
+ util.data_add(ctx_data, 8 * size, 4)
359
+
360
+ for r in ctx[k]["register"]:
361
+ util.data_add(ctx_data, r, 8)
362
+
363
+ for i in range(reg_size, size): # pylint: disable=W0612
364
+ util.data_add(ctx_data, 0, 8)
365
+
366
+ # Vendor-specific bytes are not grouped
367
+ vendor_data = bytearray()
368
+ if vendor:
369
+ for k in sorted(vendor.keys()):
370
+ for b in vendor[k]["bytes"]:
371
+ util.data_add(vendor_data, b, 1)
372
+
373
+ # Encode ARM Processor Error
374
+ data = bytearray()
375
+
376
+ util.data_add(data, cper["valid"], 4)
377
+
378
+ util.data_add(data, error_info_num, 2)
379
+ util.data_add(data, context_info_num, 2)
380
+
381
+ # Calculate the length of the CPER data
382
+ cper_length = self.ACPI_GHES_ARM_CPER_LENGTH
383
+ cper_length += len(pei_data)
384
+ cper_length += len(vendor_data)
385
+ cper_length += len(ctx_data)
386
+ util.data_add(data, cper_length, 4)
387
+
388
+ util.data_add(data, arg.get("affinity-level", 0), 1)
389
+
390
+ # Reserved
391
+ util.data_add(data, 0, 3)
392
+
393
+ if "midr-el1" not in arg:
394
+ if cpus:
395
+ cmd_arg = {
396
+ 'path': cpus[0],
397
+ 'property': "midr"
398
+ }
399
+ ret = qmp_cmd.send_cmd("qom-get", cmd_arg, may_open=True)
400
+ if isinstance(ret, int):
401
+ arg["midr-el1"] = ret
402
+
403
+ util.data_add(data, arg.get("mpidr-el1", 0), 8)
404
+ util.data_add(data, arg.get("midr-el1", 0), 8)
405
+ util.data_add(data, cper["running-state"], 4)
406
+ util.data_add(data, arg.get("psci-state", 0), 4)
407
+
408
+ # Add PEI
409
+ data.extend(pei_data)
410
+ data.extend(ctx_data)
411
+ data.extend(vendor_data)
412
+
413
+ self.data = data
414
+
415
+ qmp_cmd.send_cper(cper_guid.CPER_PROC_ARM, self.data)
416
diff --git a/scripts/ghes_inject.py b/scripts/ghes_inject.py
417
new file mode 100755
418
index XXXXXXX..XXXXXXX
419
--- /dev/null
420
+++ b/scripts/ghes_inject.py
421
@@ -XXX,XX +XXX,XX @@
422
+#!/usr/bin/env python3
423
+#
424
+# SPDX-License-Identifier: GPL-2.0
425
+#
426
+# Copyright (C) 2024 Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
427
+
428
+"""
429
+Handle ACPI GHESv2 error injection logic QEMU QMP interface.
430
+"""
431
+
432
+import argparse
433
+import sys
434
+
435
+from arm_processor_error import ArmProcessorEinj
436
+
437
+EINJ_DESC = """
438
+Handle ACPI GHESv2 error injection logic QEMU QMP interface.
439
+
440
+It allows using UEFI BIOS EINJ features to generate GHES records.
441
+
442
+It helps testing CPER and GHES drivers at the guest OS and how
443
+userspace applications at the guest handle them.
444
+"""
445
+
446
+def main():
447
+ """Main program"""
448
+
449
+ # Main parser - handle generic args like QEMU QMP TCP socket options
450
+ parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter,
451
+ usage="%(prog)s [options]",
452
+ description=EINJ_DESC)
453
+
454
+ g_options = parser.add_argument_group("QEMU QMP socket options")
455
+ g_options.add_argument("-H", "--host", default="localhost", type=str,
456
+ help="host name")
457
+ g_options.add_argument("-P", "--port", default=4445, type=int,
458
+ help="TCP port number")
459
+ g_options.add_argument('-d', '--debug', action='store_true')
460
+
461
+ subparsers = parser.add_subparsers()
462
+
463
+ ArmProcessorEinj(subparsers)
464
+
465
+ args = parser.parse_args()
466
+ if "func" in args:
467
+ args.func(args)
468
+ else:
469
+ sys.exit(f"Please specify a valid command for {sys.argv[0]}")
470
+
471
+if __name__ == "__main__":
472
+ main()
473
diff --git a/scripts/qmp_helper.py b/scripts/qmp_helper.py
474
new file mode 100644
475
index XXXXXXX..XXXXXXX
476
--- /dev/null
477
+++ b/scripts/qmp_helper.py
478
@@ -XXX,XX +XXX,XX @@
479
+#!/usr/bin/env python3
480
+#
481
+# # pylint: disable=C0103,E0213,E1135,E1136,E1137,R0902,R0903,R0912,R0913
482
+# SPDX-License-Identifier: GPL-2.0
483
+#
484
+# Copyright (C) 2024 Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
485
+
486
+"""
487
+Helper classes to be used by ghes_inject command classes.
488
+"""
489
+
490
+import json
491
+import sys
492
+
493
+from datetime import datetime
494
+from os import path as os_path
495
+
496
+try:
497
+ qemu_dir = os_path.abspath(os_path.dirname(os_path.dirname(__file__)))
498
+ sys.path.append(os_path.join(qemu_dir, 'python'))
499
+
500
+ from qemu.qmp.legacy import QEMUMonitorProtocol
501
+
502
+except ModuleNotFoundError as exc:
503
+ print(f"Module '{exc.name}' not found.")
504
+ print("Try export PYTHONPATH=top-qemu-dir/python or run from top-qemu-dir")
505
+ sys.exit(1)
506
+
507
+from base64 import b64encode
508
+
509
+class util:
510
+ """
511
+ Ancillary functions to deal with bitmaps, parse arguments,
512
+ generate GUID and encode data on a bytearray buffer.
513
+ """
514
+
515
+ #
516
+ # Helper routines to handle multiple choice arguments
517
+ #
518
+ def get_choice(name, value, choices, suffixes=None, bitmask=True):
519
+ """Produce a list from multiple choice argument"""
520
+
521
+ new_values = 0
522
+
523
+ if not value:
524
+ return new_values
525
+
526
+ for val in value.split(","):
527
+ val = val.lower()
528
+
529
+ if suffixes:
530
+ for suffix in suffixes:
531
+ val = val.removesuffix(suffix)
532
+
533
+ if val not in choices.keys():
534
+ if suffixes:
535
+ for suffix in suffixes:
536
+ if val + suffix in choices.keys():
537
+ val += suffix
538
+ break
539
+
540
+ if val not in choices.keys():
541
+ sys.exit(f"Error on '{name}': choice '{val}' is invalid.")
542
+
543
+ val = choices[val]
544
+
545
+ if bitmask:
546
+ new_values |= val
547
+ else:
548
+ if new_values:
549
+ sys.exit(f"Error on '{name}': only one value is accepted.")
550
+
551
+ new_values = val
552
+
553
+ return new_values
554
+
555
+ def get_array(name, values, max_val=None):
556
+ """Add numbered hashes from integer lists into an array"""
557
+
558
+ array = []
559
+
560
+ for value in values:
561
+ for val in value.split(","):
562
+ try:
563
+ val = int(val, 0)
564
+ except ValueError:
565
+ sys.exit(f"Error on '{name}': {val} is not an integer")
566
+
567
+ if val < 0:
568
+ sys.exit(f"Error on '{name}': {val} is not unsigned")
569
+
570
+ if max_val and val > max_val:
571
+ sys.exit(f"Error on '{name}': {val} is too little")
572
+
573
+ array.append(val)
574
+
575
+ return array
576
+
577
+ def get_mult_array(mult, name, values, allow_zero=False, max_val=None):
578
+ """Add numbered hashes from integer lists"""
579
+
580
+ if not allow_zero:
581
+ if not values:
582
+ return
583
+ else:
584
+ if values is None:
585
+ return
586
+
587
+ if not values:
588
+ i = 0
589
+ if i not in mult:
590
+ mult[i] = {}
591
+
592
+ mult[i][name] = []
593
+ return
594
+
595
+ i = 0
596
+ for value in values:
597
+ for val in value.split(","):
598
+ try:
599
+ val = int(val, 0)
600
+ except ValueError:
601
+ sys.exit(f"Error on '{name}': {val} is not an integer")
602
+
603
+ if val < 0:
604
+ sys.exit(f"Error on '{name}': {val} is not unsigned")
605
+
606
+ if max_val and val > max_val:
607
+ sys.exit(f"Error on '{name}': {val} is too little")
608
+
609
+ if i not in mult:
610
+ mult[i] = {}
611
+
612
+ if name not in mult[i]:
613
+ mult[i][name] = []
614
+
615
+ mult[i][name].append(val)
616
+
617
+ i += 1
618
+
619
+
620
+ def get_mult_choices(mult, name, values, choices,
621
+ suffixes=None, allow_zero=False):
622
+ """Add numbered hashes from multiple choice arguments"""
623
+
624
+ if not allow_zero:
625
+ if not values:
626
+ return
627
+ else:
628
+ if values is None:
629
+ return
630
+
631
+ i = 0
632
+ for val in values:
633
+ new_values = util.get_choice(name, val, choices, suffixes)
634
+
635
+ if i not in mult:
636
+ mult[i] = {}
637
+
638
+ mult[i][name] = new_values
639
+ i += 1
640
+
641
+
642
+ def get_mult_int(mult, name, values, allow_zero=False):
643
+ """Add numbered hashes from integer arguments"""
644
+ if not allow_zero:
645
+ if not values:
646
+ return
647
+ else:
648
+ if values is None:
649
+ return
650
+
651
+ i = 0
652
+ for val in values:
653
+ try:
654
+ val = int(val, 0)
655
+ except ValueError:
656
+ sys.exit(f"Error on '{name}': {val} is not an integer")
657
+
658
+ if val < 0:
659
+ sys.exit(f"Error on '{name}': {val} is not unsigned")
660
+
661
+ if i not in mult:
662
+ mult[i] = {}
663
+
664
+ mult[i][name] = val
665
+ i += 1
666
+
667
+
668
+ #
669
+ # Data encode helper functions
670
+ #
671
+ def bit(b):
672
+ """Simple macro to define a bit on a bitmask"""
673
+ return 1 << b
674
+
675
+
676
+ def data_add(data, value, num_bytes):
677
+ """Adds bytes from value inside a bitarray"""
678
+
679
+ data.extend(value.to_bytes(num_bytes, byteorder="little")) # pylint: disable=E1101
680
+
681
+ def dump_bytearray(name, data):
682
+ """Does an hexdump of a byte array, grouping in bytes"""
683
+
684
+ print(f"{name} ({len(data)} bytes):")
685
+
686
+ for ln_start in range(0, len(data), 16):
687
+ ln_end = min(ln_start + 16, len(data))
688
+ print(f" {ln_start:08x} ", end="")
689
+ for i in range(ln_start, ln_end):
690
+ print(f"{data[i]:02x} ", end="")
691
+ for i in range(ln_end, ln_start + 16):
692
+ print(" ", end="")
693
+ print(" ", end="")
694
+ for i in range(ln_start, ln_end):
695
+ if data[i] >= 32 and data[i] < 127:
696
+ print(chr(data[i]), end="")
697
+ else:
698
+ print(".", end="")
699
+
700
+ print()
701
+ print()
702
+
703
+ def time(string):
704
+ """Handle BCD timestamps used on Generic Error Data Block"""
705
+
706
+ time = None
707
+
708
+ # Formats to be used when parsing time stamps
709
+ formats = [
710
+ "%Y-%m-%d %H:%M:%S",
711
+ ]
712
+
713
+ if string == "now":
714
+ time = datetime.now()
715
+
716
+ if time is None:
717
+ for fmt in formats:
718
+ try:
719
+ time = datetime.strptime(string, fmt)
720
+ break
721
+ except ValueError:
722
+ pass
723
+
724
+ if time is None:
725
+ raise ValueError("Invalid time format")
726
+
727
+ return time
728
+
729
+class guid:
730
+ """
731
+ Simple class to handle GUID fields.
732
+ """
733
+
734
+ def __init__(self, time_low, time_mid, time_high, nodes):
735
+ """Initialize a GUID value"""
736
+
737
+ assert len(nodes) == 8
738
+
739
+ self.time_low = time_low
740
+ self.time_mid = time_mid
741
+ self.time_high = time_high
742
+ self.nodes = nodes
743
+
744
+ @classmethod
745
+ def UUID(cls, guid_str):
746
+ """Initialize a GUID using a string on its standard format"""
747
+
748
+ if len(guid_str) != 36:
749
+ print("Size not 36")
750
+ raise ValueError('Invalid GUID size')
751
+
752
+ # It is easier to parse without separators. So, drop them
753
+ guid_str = guid_str.replace('-', '')
754
+
755
+ if len(guid_str) != 32:
756
+ print("Size not 32", guid_str, len(guid_str))
757
+ raise ValueError('Invalid GUID hex size')
758
+
759
+ time_low = 0
760
+ time_mid = 0
761
+ time_high = 0
762
+ nodes = []
763
+
764
+ for i in reversed(range(16, 32, 2)):
765
+ h = guid_str[i:i + 2]
766
+ value = int(h, 16)
767
+ nodes.insert(0, value)
768
+
769
+ time_high = int(guid_str[12:16], 16)
770
+ time_mid = int(guid_str[8:12], 16)
771
+ time_low = int(guid_str[0:8], 16)
772
+
773
+ return cls(time_low, time_mid, time_high, nodes)
774
+
775
+ def __str__(self):
776
+ """Output a GUID value on its default string representation"""
777
+
778
+ clock = self.nodes[0] << 8 | self.nodes[1]
779
+
780
+ node = 0
781
+ for i in range(2, len(self.nodes)):
782
+ node = node << 8 | self.nodes[i]
783
+
784
+ s = f"{self.time_low:08x}-{self.time_mid:04x}-"
785
+ s += f"{self.time_high:04x}-{clock:04x}-{node:012x}"
786
+ return s
787
+
788
+ def to_bytes(self):
789
+ """Output a GUID value in bytes"""
790
+
791
+ data = bytearray()
792
+
793
+ util.data_add(data, self.time_low, 4)
794
+ util.data_add(data, self.time_mid, 2)
795
+ util.data_add(data, self.time_high, 2)
796
+ data.extend(bytearray(self.nodes))
797
+
798
+ return data
799
+
800
+class qmp:
801
+ """
802
+ Opens a connection and send/receive QMP commands.
803
+ """
804
+
805
+ def send_cmd(self, command, args=None, may_open=False, return_error=True):
806
+ """Send a command to QMP, optinally opening a connection"""
807
+
808
+ if may_open:
809
+ self._connect()
810
+ elif not self.connected:
811
+ return False
812
+
813
+ msg = { 'execute': command }
814
+ if args:
815
+ msg['arguments'] = args
816
+
817
+ try:
818
+ obj = self.qmp_monitor.cmd_obj(msg)
819
+ # Can we use some other exception class here?
820
+ except Exception as e: # pylint: disable=W0718
821
+ print(f"Command: {command}")
822
+ print(f"Failed to inject error: {e}.")
823
+ return None
824
+
825
+ if "return" in obj:
826
+ if isinstance(obj.get("return"), dict):
827
+ if obj["return"]:
828
+ return obj["return"]
829
+ return "OK"
830
+
831
+ return obj["return"]
832
+
833
+ if isinstance(obj.get("error"), dict):
834
+ error = obj["error"]
835
+ if return_error:
836
+ print(f"Command: {msg}")
837
+ print(f'{error["class"]}: {error["desc"]}')
838
+ else:
839
+ print(json.dumps(obj))
840
+
841
+ return None
842
+
843
+ def _close(self):
844
+ """Shutdown and close the socket, if opened"""
845
+ if not self.connected:
846
+ return
847
+
848
+ self.qmp_monitor.close()
849
+ self.connected = False
850
+
851
+ def _connect(self):
852
+ """Connect to a QMP TCP/IP port, if not connected yet"""
853
+
854
+ if self.connected:
855
+ return True
856
+
857
+ try:
858
+ self.qmp_monitor.connect(negotiate=True)
859
+ except ConnectionError:
860
+ sys.exit(f"Can't connect to QMP host {self.host}:{self.port}")
861
+
862
+ self.connected = True
863
+
864
+ return True
865
+
866
+ BLOCK_STATUS_BITS = {
867
+ "uncorrectable": util.bit(0),
868
+ "correctable": util.bit(1),
869
+ "multi-uncorrectable": util.bit(2),
870
+ "multi-correctable": util.bit(3),
871
+ }
872
+
873
+ ERROR_SEVERITY = {
874
+ "recoverable": 0,
875
+ "fatal": 1,
876
+ "corrected": 2,
877
+ "none": 3,
878
+ }
879
+
880
+ VALIDATION_BITS = {
881
+ "fru-id": util.bit(0),
882
+ "fru-text": util.bit(1),
883
+ "timestamp": util.bit(2),
884
+ }
885
+
886
+ GEDB_FLAGS_BITS = {
887
+ "recovered": util.bit(0),
888
+ "prev-error": util.bit(1),
889
+ "simulated": util.bit(2),
890
+ }
891
+
892
+ GENERIC_DATA_SIZE = 72
893
+
894
+ def argparse(parser):
895
+ """Prepare a parser group to query generic error data"""
896
+
897
+ block_status_bits = ",".join(qmp.BLOCK_STATUS_BITS.keys())
898
+ error_severity_enum = ",".join(qmp.ERROR_SEVERITY.keys())
899
+ validation_bits = ",".join(qmp.VALIDATION_BITS.keys())
900
+ gedb_flags_bits = ",".join(qmp.GEDB_FLAGS_BITS.keys())
901
+
902
+ g_gen = parser.add_argument_group("Generic Error Data") # pylint: disable=E1101
903
+ g_gen.add_argument("--block-status",
904
+ help=f"block status bits: {block_status_bits}")
905
+ g_gen.add_argument("--raw-data", nargs="+",
906
+ help="Raw data inside the Error Status Block")
907
+ g_gen.add_argument("--error-severity", "--severity",
908
+ help=f"error severity: {error_severity_enum}")
909
+ g_gen.add_argument("--gen-err-valid-bits",
910
+ "--generic-error-validation-bits",
911
+ help=f"validation bits: {validation_bits}")
912
+ g_gen.add_argument("--fru-id", type=guid.UUID,
913
+ help="GUID representing a physical device")
914
+ g_gen.add_argument("--fru-text",
915
+ help="ASCII string identifying the FRU hardware")
916
+ g_gen.add_argument("--timestamp", type=util.time,
917
+ help="Time when the error info was collected")
918
+ g_gen.add_argument("--precise", "--precise-timestamp",
919
+ action='store_true',
920
+ help="Marks the timestamp as precise if --timestamp is used")
921
+ g_gen.add_argument("--gedb-flags",
922
+ help=f"General Error Data Block flags: {gedb_flags_bits}")
923
+
924
+ def set_args(self, args):
925
+ """Set the arguments optionally defined via self.argparse()"""
926
+
927
+ if args.block_status:
928
+ self.block_status = util.get_choice(name="block-status",
929
+ value=args.block_status,
930
+ choices=self.BLOCK_STATUS_BITS,
931
+ bitmask=False)
932
+ if args.raw_data:
933
+ self.raw_data = util.get_array("raw-data", args.raw_data,
934
+ max_val=255)
935
+ print(self.raw_data)
936
+
937
+ if args.error_severity:
938
+ self.error_severity = util.get_choice(name="error-severity",
939
+ value=args.error_severity,
940
+ choices=self.ERROR_SEVERITY,
941
+ bitmask=False)
942
+
943
+ if args.fru_id:
944
+ self.fru_id = args.fru_id.to_bytes()
945
+ if not args.gen_err_valid_bits:
946
+ self.validation_bits |= self.VALIDATION_BITS["fru-id"]
947
+
948
+ if args.fru_text:
949
+ text = bytearray(args.fru_text.encode('ascii'))
950
+ if len(text) > 20:
951
+ sys.exit("FRU text is too big to fit")
952
+
953
+ self.fru_text = text
954
+ if not args.gen_err_valid_bits:
955
+ self.validation_bits |= self.VALIDATION_BITS["fru-text"]
956
+
957
+ if args.timestamp:
958
+ time = args.timestamp
959
+ century = int(time.year / 100)
960
+
961
+ bcd = bytearray()
962
+ util.data_add(bcd, (time.second // 10) << 4 | (time.second % 10), 1)
963
+ util.data_add(bcd, (time.minute // 10) << 4 | (time.minute % 10), 1)
964
+ util.data_add(bcd, (time.hour // 10) << 4 | (time.hour % 10), 1)
965
+
966
+ if args.precise:
967
+ util.data_add(bcd, 1, 1)
968
+ else:
969
+ util.data_add(bcd, 0, 1)
970
+
971
+ util.data_add(bcd, (time.day // 10) << 4 | (time.day % 10), 1)
972
+ util.data_add(bcd, (time.month // 10) << 4 | (time.month % 10), 1)
973
+ util.data_add(bcd,
974
+ ((time.year % 100) // 10) << 4 | (time.year % 10), 1)
975
+ util.data_add(bcd, ((century % 100) // 10) << 4 | (century % 10), 1)
976
+
977
+ self.timestamp = bcd
978
+ if not args.gen_err_valid_bits:
979
+ self.validation_bits |= self.VALIDATION_BITS["timestamp"]
980
+
981
+ if args.gen_err_valid_bits:
982
+ self.validation_bits = util.get_choice(name="validation",
983
+ value=args.gen_err_valid_bits,
984
+ choices=self.VALIDATION_BITS)
985
+
986
+ def __init__(self, host, port, debug=False):
987
+ """Initialize variables used by the QMP send logic"""
988
+
989
+ self.connected = False
990
+ self.host = host
991
+ self.port = port
992
+ self.debug = debug
993
+
994
+ # ACPI 6.1: 18.3.2.7.1 Generic Error Data: Generic Error Status Block
995
+ self.block_status = self.BLOCK_STATUS_BITS["uncorrectable"]
996
+ self.raw_data = []
997
+ self.error_severity = self.ERROR_SEVERITY["recoverable"]
998
+
999
+ # ACPI 6.1: 18.3.2.7.1 Generic Error Data: Generic Error Data Entry
1000
+ self.validation_bits = 0
1001
+ self.flags = 0
1002
+ self.fru_id = bytearray(16)
1003
+ self.fru_text = bytearray(20)
1004
+ self.timestamp = bytearray(8)
1005
+
1006
+ self.qmp_monitor = QEMUMonitorProtocol(address=(self.host, self.port))
1007
+
1008
+ #
1009
+ # Socket QMP send command
1010
+ #
1011
+ def send_cper_raw(self, cper_data):
1012
+ """Send a raw CPER data to QEMU though QMP TCP socket"""
1013
+
1014
+ data = b64encode(bytes(cper_data)).decode('ascii')
1015
+
1016
+ cmd_arg = {
1017
+ 'cper': data
1018
+ }
1019
+
1020
+ self._connect()
1021
+
1022
+ if self.send_cmd("inject-ghes-error", cmd_arg):
1023
+ print("Error injected.")
1024
+
1025
+ def send_cper(self, notif_type, payload):
1026
+ """Send commands to QEMU though QMP TCP socket"""
1027
+
1028
+ # Fill CPER record header
1029
+
1030
+ # NOTE: bits 4 to 13 of block status contain the number of
1031
+ # data entries in the data section. This is currently unsupported.
1032
+
1033
+ cper_length = len(payload)
1034
+ data_length = cper_length + len(self.raw_data) + self.GENERIC_DATA_SIZE
1035
+
1036
+ # Generic Error Data Entry
1037
+ gede = bytearray()
1038
+
1039
+ gede.extend(notif_type.to_bytes())
1040
+ util.data_add(gede, self.error_severity, 4)
1041
+ util.data_add(gede, 0x300, 2)
1042
+ util.data_add(gede, self.validation_bits, 1)
1043
+ util.data_add(gede, self.flags, 1)
1044
+ util.data_add(gede, cper_length, 4)
1045
+ gede.extend(self.fru_id)
1046
+ gede.extend(self.fru_text)
1047
+ gede.extend(self.timestamp)
1048
+
1049
+ # Generic Error Status Block
1050
+ gebs = bytearray()
1051
+
1052
+ if self.raw_data:
1053
+ raw_data_offset = len(gebs)
1054
+ else:
1055
+ raw_data_offset = 0
1056
+
1057
+ util.data_add(gebs, self.block_status, 4)
1058
+ util.data_add(gebs, raw_data_offset, 4)
1059
+ util.data_add(gebs, len(self.raw_data), 4)
1060
+ util.data_add(gebs, data_length, 4)
1061
+ util.data_add(gebs, self.error_severity, 4)
1062
+
1063
+ cper_data = bytearray()
1064
+ cper_data.extend(gebs)
1065
+ cper_data.extend(gede)
1066
+ cper_data.extend(bytearray(self.raw_data))
1067
+ cper_data.extend(bytearray(payload))
1068
+
1069
+ if self.debug:
1070
+ print(f"GUID: {notif_type}")
1071
+
1072
+ util.dump_bytearray("Generic Error Status Block", gebs)
1073
+ util.dump_bytearray("Generic Error Data Entry", gede)
1074
+
1075
+ if self.raw_data:
1076
+ util.dump_bytearray("Raw data", bytearray(self.raw_data))
1077
+
1078
+ util.dump_bytearray("Payload", payload)
1079
+
1080
+ self.send_cper_raw(cper_data)
1081
+
1082
+
1083
+ def search_qom(self, path, prop, regex):
1084
+ """
1085
+ Return a list of devices that match path array like:
1086
+
1087
+ /machine/unattached/device
1088
+ /machine/peripheral-anon/device
1089
+ ...
1090
+ """
1091
+
1092
+ found = []
1093
+
1094
+ i = 0
1095
+ while 1:
1096
+ dev = f"{path}[{i}]"
1097
+ args = {
1098
+ 'path': dev,
1099
+ 'property': prop
1100
+ }
1101
+ ret = self.send_cmd("qom-get", args, may_open=True, return_error=False)
1102
+ if not ret:
1103
+ break
1104
+
1105
+ if isinstance(ret, str):
1106
+ if regex.search(ret):
1107
+ found.append(dev)
1108
+
1109
+ i += 1
1110
+ if i > 10000:
1111
+ print("Too many objects returned by qom-get!")
1112
+ break
1113
+
1114
+ return found
1115
+
1116
+class cper_guid:
1117
+ """
1118
+ Contains CPER GUID, as per:
1119
+ https://uefi.org/specs/UEFI/2.10/Apx_N_Common_Platform_Error_Record.html
1120
+ """
1121
+
1122
+ CPER_PROC_GENERIC = guid(0x9876CCAD, 0x47B4, 0x4bdb,
1123
+ [0xB6, 0x5E, 0x16, 0xF1,
1124
+ 0x93, 0xC4, 0xF3, 0xDB])
1125
+
1126
+ CPER_PROC_X86 = guid(0xDC3EA0B0, 0xA144, 0x4797,
1127
+ [0xB9, 0x5B, 0x53, 0xFA,
1128
+ 0x24, 0x2B, 0x6E, 0x1D])
1129
+
1130
+ CPER_PROC_ITANIUM = guid(0xe429faf1, 0x3cb7, 0x11d4,
1131
+ [0xbc, 0xa7, 0x00, 0x80,
1132
+ 0xc7, 0x3c, 0x88, 0x81])
1133
+
1134
+ CPER_PROC_ARM = guid(0xE19E3D16, 0xBC11, 0x11E4,
1135
+ [0x9C, 0xAA, 0xC2, 0x05,
1136
+ 0x1D, 0x5D, 0x46, 0xB0])
1137
+
1138
+ CPER_PLATFORM_MEM = guid(0xA5BC1114, 0x6F64, 0x4EDE,
1139
+ [0xB8, 0x63, 0x3E, 0x83,
1140
+ 0xED, 0x7C, 0x83, 0xB1])
1141
+
1142
+ CPER_PLATFORM_MEM2 = guid(0x61EC04FC, 0x48E6, 0xD813,
1143
+ [0x25, 0xC9, 0x8D, 0xAA,
1144
+ 0x44, 0x75, 0x0B, 0x12])
1145
+
1146
+ CPER_PCIE = guid(0xD995E954, 0xBBC1, 0x430F,
1147
+ [0xAD, 0x91, 0xB4, 0x4D,
1148
+ 0xCB, 0x3C, 0x6F, 0x35])
1149
+
1150
+ CPER_PCI_BUS = guid(0xC5753963, 0x3B84, 0x4095,
1151
+ [0xBF, 0x78, 0xED, 0xDA,
1152
+ 0xD3, 0xF9, 0xC9, 0xDD])
1153
+
1154
+ CPER_PCI_DEV = guid(0xEB5E4685, 0xCA66, 0x4769,
1155
+ [0xB6, 0xA2, 0x26, 0x06,
1156
+ 0x8B, 0x00, 0x13, 0x26])
1157
+
1158
+ CPER_FW_ERROR = guid(0x81212A96, 0x09ED, 0x4996,
1159
+ [0x94, 0x71, 0x8D, 0x72,
1160
+ 0x9C, 0x8E, 0x69, 0xED])
1161
+
1162
+ CPER_DMA_GENERIC = guid(0x5B51FEF7, 0xC79D, 0x4434,
1163
+ [0x8F, 0x1B, 0xAA, 0x62,
1164
+ 0xDE, 0x3E, 0x2C, 0x64])
1165
+
1166
+ CPER_DMA_VT = guid(0x71761D37, 0x32B2, 0x45cd,
1167
+ [0xA7, 0xD0, 0xB0, 0xFE,
1168
+ 0xDD, 0x93, 0xE8, 0xCF])
1169
+
1170
+ CPER_DMA_IOMMU = guid(0x036F84E1, 0x7F37, 0x428c,
1171
+ [0xA7, 0x9E, 0x57, 0x5F,
1172
+ 0xDF, 0xAA, 0x84, 0xEC])
1173
+
1174
+ CPER_CCIX_PER = guid(0x91335EF6, 0xEBFB, 0x4478,
1175
+ [0xA6, 0xA6, 0x88, 0xB7,
1176
+ 0x28, 0xCF, 0x75, 0xD7])
1177
+
1178
+ CPER_CXL_PROT_ERR = guid(0x80B9EFB4, 0x52B5, 0x4DE3,
1179
+ [0xA7, 0x77, 0x68, 0x78,
1180
+ 0x4B, 0x77, 0x10, 0x48])
1181
--
1182
2.47.1
diff view generated by jsdifflib
Deleted patch
1
Accurately injecting an ARM Processor error ACPI/APEI GHES
2
error record requires the value of the ARM Multiprocessor
3
Affinity Register (mpidr).
4
1
5
While ARM implements it, this is currently not visible.
6
7
Add a field at CPU storing it, and place it at arm_cpu_properties
8
as experimental, thus allowing it to be queried via QMP using
9
qom-get function.
10
11
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
12
---
13
target/arm/cpu.c | 1 +
14
target/arm/cpu.h | 1 +
15
target/arm/helper.c | 10 ++++++++--
16
3 files changed, 10 insertions(+), 2 deletions(-)
17
18
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/cpu.c
21
+++ b/target/arm/cpu.c
22
@@ -XXX,XX +XXX,XX @@ static ObjectClass *arm_cpu_class_by_name(const char *cpu_model)
23
24
static Property arm_cpu_properties[] = {
25
DEFINE_PROP_UINT64("midr", ARMCPU, midr, 0),
26
+ DEFINE_PROP_UINT64("x-mpidr", ARMCPU, mpidr, 0),
27
DEFINE_PROP_UINT64("mp-affinity", ARMCPU,
28
mp_affinity, ARM64_AFFINITY_INVALID),
29
DEFINE_PROP_INT32("node-id", ARMCPU, node_id, CPU_UNSET_NUMA_NODE_ID),
30
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
31
index XXXXXXX..XXXXXXX 100644
32
--- a/target/arm/cpu.h
33
+++ b/target/arm/cpu.h
34
@@ -XXX,XX +XXX,XX @@ struct ArchCPU {
35
uint64_t reset_pmcr_el0;
36
} isar;
37
uint64_t midr;
38
+ uint64_t mpidr;
39
uint32_t revidr;
40
uint32_t reset_fpsid;
41
uint64_t ctr;
42
diff --git a/target/arm/helper.c b/target/arm/helper.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/target/arm/helper.c
45
+++ b/target/arm/helper.c
46
@@ -XXX,XX +XXX,XX @@ static uint64_t mpidr_read_val(CPUARMState *env)
47
return mpidr;
48
}
49
50
-static uint64_t mpidr_read(CPUARMState *env, const ARMCPRegInfo *ri)
51
+static uint64_t mpidr_read(CPUARMState *env)
52
{
53
unsigned int cur_el = arm_current_el(env);
54
55
@@ -XXX,XX +XXX,XX @@ static uint64_t mpidr_read(CPUARMState *env, const ARMCPRegInfo *ri)
56
return mpidr_read_val(env);
57
}
58
59
+static uint64_t mpidr_read_ri(CPUARMState *env, const ARMCPRegInfo *ri)
60
+{
61
+ return mpidr_read(env);
62
+}
63
+
64
static const ARMCPRegInfo lpae_cp_reginfo[] = {
65
/* NOP AMAIR0/1 */
66
{ .name = "AMAIR0", .state = ARM_CP_STATE_BOTH,
67
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
68
{ .name = "MPIDR_EL1", .state = ARM_CP_STATE_BOTH,
69
.opc0 = 3, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 5,
70
.fgt = FGT_MPIDR_EL1,
71
- .access = PL1_R, .readfn = mpidr_read, .type = ARM_CP_NO_RAW },
72
+ .access = PL1_R, .readfn = mpidr_read_ri, .type = ARM_CP_NO_RAW },
73
};
74
#ifdef CONFIG_USER_ONLY
75
static const ARMCPRegUserSpaceInfo mpidr_user_cp_reginfo[] = {
76
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
77
modify_arm_cp_regs(mpidr_cp_reginfo, mpidr_user_cp_reginfo);
78
#endif
79
define_arm_cp_regs(cpu, mpidr_cp_reginfo);
80
+ cpu->mpidr = mpidr_read(env);
81
}
82
83
if (arm_feature(env, ARM_FEATURE_AUXCR)) {
84
--
85
2.47.1
diff view generated by jsdifflib
Deleted patch
1
Add support to retrieve mpidr value via qom-get.
2
1
3
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
4
---
5
scripts/arm_processor_error.py | 29 +++++++++++++++++++++--------
6
1 file changed, 21 insertions(+), 8 deletions(-)
7
8
diff --git a/scripts/arm_processor_error.py b/scripts/arm_processor_error.py
9
index XXXXXXX..XXXXXXX 100644
10
--- a/scripts/arm_processor_error.py
11
+++ b/scripts/arm_processor_error.py
12
@@ -XXX,XX +XXX,XX @@
13
#
14
# Copyright (C) 2024 Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
15
16
-# TODO: current implementation has dummy defaults.
17
-#
18
-# For a better implementation, a QMP addition/call is needed to
19
-# retrieve some data for ARM Processor Error injection:
20
-#
21
-# - ARM registers: power_state, mpidr.
22
+# Note: currently it lacks a method to fill the ARM Processor Error CPER
23
+# psci field from emulation. On a real hardware, this is filled only
24
+# when a CPU is not running. Implementing support for it to simulate a
25
+# real hardware is not trivial.
26
27
import argparse
28
import re
29
@@ -XXX,XX +XXX,XX @@ def send_cper(self, args):
30
else:
31
cper["running-state"] = 0
32
33
+ if args.mpidr:
34
+ cper["mpidr-el1"] = arg["mpidr"]
35
+ elif cpus:
36
+ cmd_arg = {
37
+ 'path': cpus[0],
38
+ 'property': "x-mpidr"
39
+ }
40
+ ret = qmp_cmd.send_cmd("qom-get", cmd_arg, may_open=True)
41
+ if isinstance(ret, int):
42
+ cper["mpidr-el1"] = ret
43
+ else:
44
+ cper["mpidr-el1"] = 0
45
+ else:
46
+ cper["mpidr-el1"] = 0
47
+
48
if arm_valid_init:
49
if args.affinity:
50
cper["valid"] |= self.arm_valid_bits["affinity"]
51
52
- if args.mpidr:
53
+ if "mpidr-el1" in cper:
54
cper["valid"] |= self.arm_valid_bits["mpidr"]
55
56
if "running-state" in cper:
57
@@ -XXX,XX +XXX,XX @@ def send_cper(self, args):
58
if isinstance(ret, int):
59
arg["midr-el1"] = ret
60
61
- util.data_add(data, arg.get("mpidr-el1", 0), 8)
62
+ util.data_add(data, cper["mpidr-el1"], 8)
63
util.data_add(data, arg.get("midr-el1", 0), 8)
64
util.data_add(data, cper["running-state"], 4)
65
util.data_add(data, arg.get("psci-state", 0), 4)
66
--
67
2.47.1
diff view generated by jsdifflib
...
...
10
While here, properly name the variable which stores the cper
10
While here, properly name the variable which stores the cper
11
address.
11
address.
12
12
13
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
13
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
14
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
14
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
15
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
16
---
15
---
17
hw/acpi/ghes.c | 40 +++++++++++++++++++++++++++++++---------
16
hw/acpi/ghes.c | 41 ++++++++++++++++++++++++++++++++---------
18
1 file changed, 31 insertions(+), 9 deletions(-)
17
1 file changed, 32 insertions(+), 9 deletions(-)
19
18
20
diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c
19
diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c
21
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/acpi/ghes.c
21
--- a/hw/acpi/ghes.c
23
+++ b/hw/acpi/ghes.c
22
+++ b/hw/acpi/ghes.c
24
@@ -XXX,XX +XXX,XX @@ void acpi_ghes_add_fw_cfg(AcpiGhesState *ags, FWCfgState *s,
23
@@ -XXX,XX +XXX,XX @@ void acpi_ghes_add_fw_cfg(AcpiGhesState *ags, FWCfgState *s,
25
ags->present = true;
24
ags->present = true;
26
}
25
}
27
26
28
+static void get_hw_error_offsets(uint64_t ghes_addr,
27
+static void get_ghes_offsets(uint64_t ghes_addr,
29
+ uint64_t *cper_addr,
28
+ uint64_t *cper_addr,
30
+ uint64_t *read_ack_register_addr)
29
+ uint64_t *read_ack_register_addr)
31
+{
30
+{
32
+ if (!ghes_addr) {
31
+ if (!ghes_addr) {
33
+ return;
32
+ return;
34
+ }
33
+ }
35
+
34
+
...
...
64
63
65
start_addr += source_id * sizeof(uint64_t);
64
start_addr += source_id * sizeof(uint64_t);
66
65
67
- cpu_physical_memory_read(start_addr, &error_block_addr,
66
- cpu_physical_memory_read(start_addr, &error_block_addr,
68
- sizeof(error_block_addr));
67
- sizeof(error_block_addr));
69
+ get_hw_error_offsets(start_addr, &cper_addr, &read_ack_register_addr);
68
+ get_ghes_offsets(start_addr, &cper_addr, &read_ack_register_addr);
70
69
71
- error_block_addr = le64_to_cpu(error_block_addr);
70
- error_block_addr = le64_to_cpu(error_block_addr);
72
- if (!error_block_addr) {
71
- if (!error_block_addr) {
72
+ cper_addr = le64_to_cpu(cper_addr);
73
+ if (!cper_addr) {
73
+ if (!cper_addr) {
74
error_setg(errp, "can not find Generic Error Status Block");
74
error_setg(errp, "can not find Generic Error Status Block");
75
return;
75
return;
76
}
76
}
77
77
...
...
89
+ cpu_physical_memory_write(cper_addr, cper, len);
89
+ cpu_physical_memory_write(cper_addr, cper, len);
90
90
91
return;
91
return;
92
}
92
}
93
--
93
--
94
2.47.1
94
2.47.0
diff view generated by jsdifflib
Deleted patch
1
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
2
---
3
hw/acpi/ghes.c | 2 ++
4
1 file changed, 2 insertions(+)
5
1
6
diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c
7
index XXXXXXX..XXXXXXX 100644
8
--- a/hw/acpi/ghes.c
9
+++ b/hw/acpi/ghes.c
10
@@ -XXX,XX +XXX,XX @@ void ghes_record_cper_errors(const void *cper, size_t len,
11
ags = &acpi_ged_state->ghes_state;
12
13
if (!ags->hest_lookup) {
14
+ fprintf(stderr,"Using old GHES lookup\n");
15
get_hw_error_offsets(le64_to_cpu(ags->hw_error_le),
16
&cper_addr, &read_ack_register_addr);
17
} else {
18
+ fprintf(stderr,"Using new HEST lookup\n");
19
get_ghes_source_offsets(source_id, le64_to_cpu(ags->hest_addr_le),
20
&cper_addr, &read_ack_register_addr, errp);
21
}
22
--
23
2.47.1
diff view generated by jsdifflib
...
...
4
4
5
So, the current code supports only one source. Ensure that and simplify
5
So, the current code supports only one source. Ensure that and simplify
6
the code.
6
the code.
7
7
8
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
8
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
9
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
10
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
11
---
9
---
12
hw/acpi/ghes.c | 12 ++++--------
10
hw/acpi/ghes.c | 11 +++--------
13
1 file changed, 4 insertions(+), 8 deletions(-)
11
1 file changed, 3 insertions(+), 8 deletions(-)
14
12
15
diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c
13
diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c
16
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/acpi/ghes.c
15
--- a/hw/acpi/ghes.c
18
+++ b/hw/acpi/ghes.c
16
+++ b/hw/acpi/ghes.c
19
@@ -XXX,XX +XXX,XX @@ static void get_hw_error_offsets(uint64_t ghes_addr,
17
@@ -XXX,XX +XXX,XX @@ static void get_ghes_offsets(uint64_t ghes_addr,
20
* As the current version supports only one source, the ack offset is
18
* As the current version supports only one source, the ack offset is
21
* just sizeof(uint64_t).
19
* just sizeof(uint64_t).
22
*/
20
*/
23
- *read_ack_register_addr = ghes_addr +
21
- *read_ack_register_addr = ghes_addr +
24
-             ACPI_GHES_ERROR_SOURCE_COUNT * sizeof(uint64_t);
22
-             ACPI_GHES_ERROR_SOURCE_COUNT * sizeof(uint64_t);
...
...
39
37
40
- start_addr = le64_to_cpu(ags->hw_error_le);
38
- start_addr = le64_to_cpu(ags->hw_error_le);
41
-
39
-
42
- start_addr += source_id * sizeof(uint64_t);
40
- start_addr += source_id * sizeof(uint64_t);
43
-
41
-
44
- get_hw_error_offsets(start_addr, &cper_addr, &read_ack_register_addr);
42
- get_ghes_offsets(start_addr, &cper_addr, &read_ack_register_addr);
45
+ assert(ACPI_GHES_ERROR_SOURCE_COUNT == 1);
43
+ assert(ACPI_GHES_ERROR_SOURCE_COUNT == 1);
46
+ get_hw_error_offsets(le64_to_cpu(ags->hw_error_le),
44
+ get_ghes_offsets(le64_to_cpu(ags->hw_error_le), &cper_addr, &read_ack_register_addr);
47
+ &cper_addr, &read_ack_register_addr);
45
48
46
cper_addr = le64_to_cpu(cper_addr);
49
if (!cper_addr) {
47
if (!cper_addr) {
50
error_setg(errp, "can not find Generic Error Status Block");
51
--
48
--
52
2.47.1
49
2.47.0
diff view generated by jsdifflib
Deleted patch
1
This reverts commit 692373fc8838a6450ff5b5a8708646a673b693dd.
2
1
3
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
4
---
5
hw/arm/virt-acpi-build.c | 2 +-
6
1 file changed, 1 insertion(+), 1 deletion(-)
7
8
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
9
index XXXXXXX..XXXXXXX 100644
10
--- a/hw/arm/virt-acpi-build.c
11
+++ b/hw/arm/virt-acpi-build.c
12
@@ -XXX,XX +XXX,XX @@ static const AcpiNotificationSourceId hest_ghes_notify[] = {
13
};
14
15
static const AcpiNotificationSourceId hest_ghes_notify_9_1[] = {
16
- { ACPI_HEST_SRC_ID_SYNC, ACPI_GHES_NOTIFY_SEA },
17
+ { ACPI_HEST_SRC_ID_QMP, ACPI_GHES_NOTIFY_GPIO },
18
};
19
20
static
21
--
22
2.47.1
diff view generated by jsdifflib
1
While the spec defines a CPER size of 4KiB for each record,
1
While the spec defines a CPER size of 4KiB for each record,
2
currently it is set to 1KiB. Fix the documentation and add
2
currently it is set to 1KiB. Fix the documentation and add
3
a pointer to the macro name there, as this may help to keep
3
a pointer to the macro name there, as this may help to keep
4
it updated.
4
it updated.
5
5
6
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
6
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
7
Acked-by: Igor Mammedov <imammedo@redhat.com>
7
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
8
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
8
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
9
---
9
---
10
docs/specs/acpi_hest_ghes.rst | 6 ++++--
10
docs/specs/acpi_hest_ghes.rst | 6 ++++--
11
1 file changed, 4 insertions(+), 2 deletions(-)
11
1 file changed, 4 insertions(+), 2 deletions(-)
12
12
13
diff --git a/docs/specs/acpi_hest_ghes.rst b/docs/specs/acpi_hest_ghes.rst
13
diff --git a/docs/specs/acpi_hest_ghes.rst b/docs/specs/acpi_hest_ghes.rst
...
...
26
+ (N * 8 * 2 + N * ACPI_GHES_MAX_RAW_DATA_LENGTH) bytes.
26
+ (N * 8 * 2 + N * ACPI_GHES_MAX_RAW_DATA_LENGTH) bytes.
27
N is the number of the kinds of hardware error sources.
27
N is the number of the kinds of hardware error sources.
28
28
29
(4) QEMU generates the ACPI linker/loader script for the firmware. The
29
(4) QEMU generates the ACPI linker/loader script for the firmware. The
30
--
30
--
31
2.47.1
31
2.47.0
diff view generated by jsdifflib
Deleted patch
1
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
2
---
3
hw/acpi/ghes.c | 17 +++++++----------
4
1 file changed, 7 insertions(+), 10 deletions(-)
5
1
6
diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c
7
index XXXXXXX..XXXXXXX 100644
8
--- a/hw/acpi/ghes.c
9
+++ b/hw/acpi/ghes.c
10
@@ -XXX,XX +XXX,XX @@ ghes_gen_err_data_uncorrectable_recoverable(GArray *block,
11
*/
12
QemuUUID fru_id = {};
13
14
+ /*
15
+ * Calculate the size with this block. No need to check for
16
+ * too big CPER, as CPER size is checked at ghes_record_cper_errors()
17
+ */
18
+ data_length += ACPI_GHES_GESB_SIZE;
19
+
20
/* Build the new generic error status block header */
21
acpi_ghes_generic_error_status(block, ACPI_GEBS_UNCORRECTABLE,
22
0, 0, data_length, ACPI_CPER_SEV_RECOVERABLE);
23
@@ -XXX,XX +XXX,XX @@ int acpi_ghes_memory_errors(uint16_t source_id, uint64_t physical_address)
24
UUID_LE(0xA5BC1114, 0x6F64, 0x4EDE, 0xB8, 0x63, 0x3E, 0x83, \
25
0xED, 0x7C, 0x83, 0xB1);
26
Error *errp = NULL;
27
- int data_length;
28
GArray *block;
29
30
block = g_array_new(false, true /* clear */, 1);
31
32
- data_length = ACPI_GHES_DATA_LENGTH + ACPI_GHES_MEM_CPER_LENGTH;
33
- /*
34
- * It should not run out of the preallocated memory if adding a new generic
35
- * error data entry
36
- */
37
- assert((data_length + ACPI_GHES_GESB_SIZE) <=
38
- ACPI_GHES_MAX_RAW_DATA_LENGTH);
39
-
40
ghes_gen_err_data_uncorrectable_recoverable(block, guid,
41
- data_length);
42
+ ACPI_GHES_MAX_RAW_DATA_LENGTH);
43
44
/* Build the memory section CPER for above new generic error data entry */
45
acpi_ghes_build_append_mem_cper(block, physical_address);
46
--
47
2.47.1
diff view generated by jsdifflib