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/ |
17 | 6 | ||
18 | Such change ended being a big patch, so several intermediate steps are needed, | 7 | Such change ended being a big patch, so several intermediate steps are needed, |
19 | together with several cleanups and renames. | 8 | together with several cleanups and renames. |
20 | 9 | ||
21 | As agreed duing v10 review, I'll be splitting the big patch series into separate pull | 10 | As agreed during v10 review, I'll be splitting the big patch series into separate pull |
22 | requests, starting with the cleanup series. This is the first patch set, containing | 11 | requests, starting with the cleanup series. This is the first patch set, containing |
23 | only such preparation patches. | 12 | only such preparation patches. |
24 | 13 | ||
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: | 19 | v5: |
31 | - some changes at patches description and added some R-B; | 20 | - added a new patch: |
32 | - no changes at the code. | 21 | acpi/ghes: don't check if physical_address is not zero |
22 | - removed a duplicated le64_to_cpu(); | ||
23 | - changed a comment about writing 1 to read ack register. | ||
33 | 24 | ||
34 | v4: | 25 | v4: |
35 | - merged a patch renaming the function which calculate offsets to: | 26 | - 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 | 27 | get_hw_error_offsets(), to avoid the need of such change at the next |
37 | patch series; | 28 | patch series; |
... | ... | ||
52 | v2: | 43 | v2: |
53 | - some indentation fixes; | 44 | - some indentation fixes; |
54 | - some description improvements; | 45 | - some description improvements; |
55 | - fixed a badly-solved merge conflict that ended renaming a parameter. | 46 | - fixed a badly-solved merge conflict that ended renaming a parameter. |
56 | 47 | ||
57 | Mauro Carvalho Chehab (31): | 48 | Mauro Carvalho Chehab (16): |
58 | acpi/ghes: get rid of ACPI_HEST_SRC_ID_RESERVED | 49 | acpi/ghes: get rid of ACPI_HEST_SRC_ID_RESERVED |
59 | acpi/ghes: simplify acpi_ghes_record_errors() code | 50 | acpi/ghes: simplify acpi_ghes_record_errors() code |
60 | acpi/ghes: simplify the per-arch caller to build HEST table | 51 | acpi/ghes: simplify the per-arch caller to build HEST table |
61 | acpi/ghes: better handle source_id and notification | 52 | acpi/ghes: better handle source_id and notification |
62 | acpi/ghes: Fix acpi_ghes_record_errors() argument | 53 | acpi/ghes: Fix acpi_ghes_record_errors() argument |
... | ... | ||
66 | acpi/ghes: make the GHES record generation more generic | 57 | acpi/ghes: make the GHES record generation more generic |
67 | acpi/ghes: better name GHES memory error function | 58 | acpi/ghes: better name GHES memory error function |
68 | acpi/ghes: don't crash QEMU if ghes GED is not found | 59 | acpi/ghes: don't crash QEMU if ghes GED is not found |
69 | acpi/ghes: rename etc/hardware_error file macros | 60 | acpi/ghes: rename etc/hardware_error file macros |
70 | acpi/ghes: better name the offset of the hardware error firmware | 61 | 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 | 62 | acpi/ghes: move offset calculus to a separate function |
85 | DEBUG | ||
86 | acpi/ghes: Change ghes fill logic to work with only one source | 63 | 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 | 64 | docs: acpi_hest_ghes: fix documentation for CPER size |
89 | FIXME: acpi/ghes: properly set data record size | ||
90 | 65 | ||
91 | MAINTAINERS | 10 + | 66 | docs/specs/acpi_hest_ghes.rst | 6 +- |
92 | docs/specs/acpi_hest_ghes.rst | 6 +- | 67 | hw/acpi/generic_event_device.c | 4 +- |
93 | hw/acpi/Kconfig | 5 + | 68 | hw/acpi/ghes-stub.c | 2 +- |
94 | hw/acpi/aml-build.c | 10 + | 69 | hw/acpi/ghes.c | 259 +++++++++++++++++++-------------- |
95 | hw/acpi/generic_event_device.c | 42 +- | 70 | hw/arm/virt-acpi-build.c | 5 +- |
96 | hw/acpi/ghes-stub.c | 2 +- | 71 | include/hw/acpi/ghes.h | 16 +- |
97 | hw/acpi/ghes.c | 391 ++++++++++---- | 72 | target/arm/kvm.c | 2 +- |
98 | hw/acpi/ghes_cper.c | 32 ++ | 73 | 7 files changed, 169 insertions(+), 125 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 | 74 | ||
127 | -- | 75 | -- |
128 | 2.47.1 | 76 | 2.47.1 | diff view generated by jsdifflib |
1 | This is just duplicating ACPI_GHES_ERROR_SOURCE_COUNT, which | 1 | This is just duplicating ACPI_GHES_ERROR_SOURCE_COUNT, which |
---|---|---|---|
2 | has a better name. So, drop the duplication. | 2 | has a better name. So, drop the duplication. |
3 | 3 | ||
4 | Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org> | 4 | Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org> |
5 | Reviewed-by: Igor Mammedov <imammedo@redhat.com> | 5 | Reviewed-by: Igor Mammedov <imammedo@redhat.com> |
6 | Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> | 6 | Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> |
7 | --- | 7 | --- |
8 | hw/acpi/ghes.c | 7 ++----- | 8 | hw/acpi/ghes.c | 7 ++----- |
9 | include/hw/acpi/ghes.h | 3 ++- | 9 | include/hw/acpi/ghes.h | 3 ++- |
10 | 2 files changed, 4 insertions(+), 6 deletions(-) | 10 | 2 files changed, 4 insertions(+), 6 deletions(-) |
11 | 11 | ||
12 | diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c | 12 | diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c |
13 | index XXXXXXX..XXXXXXX 100644 | 13 | index XXXXXXX..XXXXXXX 100644 |
14 | --- a/hw/acpi/ghes.c | 14 | --- a/hw/acpi/ghes.c |
15 | +++ b/hw/acpi/ghes.c | 15 | +++ b/hw/acpi/ghes.c |
16 | @@ -XXX,XX +XXX,XX @@ | 16 | @@ -XXX,XX +XXX,XX @@ |
17 | /* The max size in bytes for one error block */ | 17 | /* The max size in bytes for one error block */ |
18 | #define ACPI_GHES_MAX_RAW_DATA_LENGTH (1 * KiB) | 18 | #define ACPI_GHES_MAX_RAW_DATA_LENGTH (1 * KiB) |
19 | 19 | ||
20 | -/* Now only support ARMv8 SEA notification type error source */ | 20 | -/* Now only support ARMv8 SEA notification type error source */ |
21 | -#define ACPI_GHES_ERROR_SOURCE_COUNT 1 | 21 | -#define ACPI_GHES_ERROR_SOURCE_COUNT 1 |
22 | - | 22 | - |
23 | /* Generic Hardware Error Source version 2 */ | 23 | /* Generic Hardware Error Source version 2 */ |
24 | #define ACPI_GHES_SOURCE_GENERIC_ERROR_V2 10 | 24 | #define ACPI_GHES_SOURCE_GENERIC_ERROR_V2 10 |
25 | 25 | ||
26 | @@ -XXX,XX +XXX,XX @@ int acpi_ghes_record_errors(uint8_t source_id, uint64_t physical_address) | 26 | @@ -XXX,XX +XXX,XX @@ int acpi_ghes_record_errors(uint8_t source_id, uint64_t physical_address) |
27 | AcpiGedState *acpi_ged_state; | 27 | AcpiGedState *acpi_ged_state; |
28 | AcpiGhesState *ags; | 28 | AcpiGhesState *ags; |
29 | 29 | ||
30 | - assert(source_id < ACPI_HEST_SRC_ID_RESERVED); | 30 | - assert(source_id < ACPI_HEST_SRC_ID_RESERVED); |
31 | + assert(source_id < ACPI_GHES_ERROR_SOURCE_COUNT); | 31 | + assert(source_id < ACPI_GHES_ERROR_SOURCE_COUNT); |
32 | 32 | ||
33 | acpi_ged_state = ACPI_GED(object_resolve_path_type("", TYPE_ACPI_GED, | 33 | acpi_ged_state = ACPI_GED(object_resolve_path_type("", TYPE_ACPI_GED, |
34 | NULL)); | 34 | NULL)); |
35 | @@ -XXX,XX +XXX,XX @@ int acpi_ghes_record_errors(uint8_t source_id, uint64_t physical_address) | 35 | @@ -XXX,XX +XXX,XX @@ int acpi_ghes_record_errors(uint8_t source_id, uint64_t physical_address) |
36 | 36 | ||
37 | if (physical_address) { | 37 | if (physical_address) { |
38 | 38 | ||
39 | - if (source_id < ACPI_HEST_SRC_ID_RESERVED) { | 39 | - if (source_id < ACPI_HEST_SRC_ID_RESERVED) { |
40 | + if (source_id < ACPI_GHES_ERROR_SOURCE_COUNT) { | 40 | + if (source_id < ACPI_GHES_ERROR_SOURCE_COUNT) { |
41 | start_addr += source_id * sizeof(uint64_t); | 41 | start_addr += source_id * sizeof(uint64_t); |
42 | } | 42 | } |
43 | 43 | ||
44 | diff --git a/include/hw/acpi/ghes.h b/include/hw/acpi/ghes.h | 44 | diff --git a/include/hw/acpi/ghes.h b/include/hw/acpi/ghes.h |
45 | index XXXXXXX..XXXXXXX 100644 | 45 | index XXXXXXX..XXXXXXX 100644 |
46 | --- a/include/hw/acpi/ghes.h | 46 | --- a/include/hw/acpi/ghes.h |
47 | +++ b/include/hw/acpi/ghes.h | 47 | +++ b/include/hw/acpi/ghes.h |
48 | @@ -XXX,XX +XXX,XX @@ enum AcpiGhesNotifyType { | 48 | @@ -XXX,XX +XXX,XX @@ enum AcpiGhesNotifyType { |
49 | enum { | 49 | enum { |
50 | ACPI_HEST_SRC_ID_SEA = 0, | 50 | ACPI_HEST_SRC_ID_SEA = 0, |
51 | /* future ids go here */ | 51 | /* future ids go here */ |
52 | - ACPI_HEST_SRC_ID_RESERVED, | 52 | - ACPI_HEST_SRC_ID_RESERVED, |
53 | + | 53 | + |
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.1 | diff view generated by jsdifflib |
1 | Reduce the ident of the function and prepares it for | 1 | Reduce the ident of the function and prepares it for |
---|---|---|---|
2 | the next changes. | 2 | the next changes. |
3 | 3 | ||
4 | No functional changes. | 4 | No functional changes. |
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 | Reviewed-by: Igor Mammedov <imammedo@redhat.com> | 7 | Reviewed-by: Igor Mammedov <imammedo@redhat.com> |
8 | Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> | 8 | Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> |
9 | --- | 9 | --- |
10 | hw/acpi/ghes.c | 56 ++++++++++++++++++++++++++------------------------ | 10 | hw/acpi/ghes.c | 56 ++++++++++++++++++++++++++------------------------ |
11 | 1 file changed, 29 insertions(+), 27 deletions(-) | 11 | 1 file changed, 29 insertions(+), 27 deletions(-) |
12 | 12 | ||
13 | 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 |
14 | index XXXXXXX..XXXXXXX 100644 | 14 | index XXXXXXX..XXXXXXX 100644 |
15 | --- a/hw/acpi/ghes.c | 15 | --- a/hw/acpi/ghes.c |
16 | +++ b/hw/acpi/ghes.c | 16 | +++ b/hw/acpi/ghes.c |
17 | @@ -XXX,XX +XXX,XX @@ int acpi_ghes_record_errors(uint8_t source_id, uint64_t physical_address) | 17 | @@ -XXX,XX +XXX,XX @@ int acpi_ghes_record_errors(uint8_t source_id, uint64_t physical_address) |
18 | 18 | ||
19 | start_addr = le64_to_cpu(ags->ghes_addr_le); | 19 | start_addr = le64_to_cpu(ags->ghes_addr_le); |
20 | 20 | ||
21 | - if (physical_address) { | 21 | - if (physical_address) { |
22 | + if (!physical_address) { | 22 | + if (!physical_address) { |
23 | + return -1; | 23 | + return -1; |
24 | + } | 24 | + } |
25 | 25 | ||
26 | - if (source_id < ACPI_GHES_ERROR_SOURCE_COUNT) { | 26 | - if (source_id < ACPI_GHES_ERROR_SOURCE_COUNT) { |
27 | - start_addr += source_id * sizeof(uint64_t); | 27 | - start_addr += source_id * sizeof(uint64_t); |
28 | - } | 28 | - } |
29 | + if (source_id < ACPI_GHES_ERROR_SOURCE_COUNT) { | 29 | + if (source_id < ACPI_GHES_ERROR_SOURCE_COUNT) { |
30 | + start_addr += source_id * sizeof(uint64_t); | 30 | + start_addr += source_id * sizeof(uint64_t); |
31 | + } | 31 | + } |
32 | 32 | ||
33 | - cpu_physical_memory_read(start_addr, &error_block_addr, | 33 | - cpu_physical_memory_read(start_addr, &error_block_addr, |
34 | - sizeof(error_block_addr)); | 34 | - sizeof(error_block_addr)); |
35 | + cpu_physical_memory_read(start_addr, &error_block_addr, | 35 | + cpu_physical_memory_read(start_addr, &error_block_addr, |
36 | + sizeof(error_block_addr)); | 36 | + sizeof(error_block_addr)); |
37 | 37 | ||
38 | - error_block_addr = le64_to_cpu(error_block_addr); | 38 | - error_block_addr = le64_to_cpu(error_block_addr); |
39 | + error_block_addr = le64_to_cpu(error_block_addr); | 39 | + error_block_addr = le64_to_cpu(error_block_addr); |
40 | 40 | ||
41 | - read_ack_register_addr = start_addr + | 41 | - read_ack_register_addr = start_addr + |
42 | - ACPI_GHES_ERROR_SOURCE_COUNT * sizeof(uint64_t); | 42 | - ACPI_GHES_ERROR_SOURCE_COUNT * sizeof(uint64_t); |
43 | + read_ack_register_addr = start_addr + | 43 | + read_ack_register_addr = start_addr + |
44 | + ACPI_GHES_ERROR_SOURCE_COUNT * sizeof(uint64_t); | 44 | + ACPI_GHES_ERROR_SOURCE_COUNT * sizeof(uint64_t); |
45 | 45 | ||
46 | - cpu_physical_memory_read(read_ack_register_addr, | 46 | - cpu_physical_memory_read(read_ack_register_addr, |
47 | - &read_ack_register, sizeof(read_ack_register)); | 47 | - &read_ack_register, sizeof(read_ack_register)); |
48 | + cpu_physical_memory_read(read_ack_register_addr, | 48 | + cpu_physical_memory_read(read_ack_register_addr, |
49 | + &read_ack_register, sizeof(read_ack_register)); | 49 | + &read_ack_register, sizeof(read_ack_register)); |
50 | 50 | ||
51 | - /* zero means OSPM does not acknowledge the error */ | 51 | - /* zero means OSPM does not acknowledge the error */ |
52 | - if (!read_ack_register) { | 52 | - if (!read_ack_register) { |
53 | - error_report("OSPM does not acknowledge previous error," | 53 | - error_report("OSPM does not acknowledge previous error," |
54 | - " so can not record CPER for current error anymore"); | 54 | - " so can not record CPER for current error anymore"); |
55 | - } else if (error_block_addr) { | 55 | - } else if (error_block_addr) { |
56 | - read_ack_register = cpu_to_le64(0); | 56 | - read_ack_register = cpu_to_le64(0); |
57 | - /* | 57 | - /* |
58 | - * Clear the Read Ack Register, OSPM will write it to 1 when | 58 | - * Clear the Read Ack Register, OSPM will write it to 1 when |
59 | - * it acknowledges this error. | 59 | - * it acknowledges this error. |
60 | - */ | 60 | - */ |
61 | - cpu_physical_memory_write(read_ack_register_addr, | 61 | - cpu_physical_memory_write(read_ack_register_addr, |
62 | - &read_ack_register, sizeof(uint64_t)); | 62 | - &read_ack_register, sizeof(uint64_t)); |
63 | + /* zero means OSPM does not acknowledge the error */ | 63 | + /* zero means OSPM does not acknowledge the error */ |
64 | + if (!read_ack_register) { | 64 | + if (!read_ack_register) { |
65 | + error_report("OSPM does not acknowledge previous error," | 65 | + error_report("OSPM does not acknowledge previous error," |
66 | + " so can not record CPER for current error anymore"); | 66 | + " so can not record CPER for current error anymore"); |
67 | + } else if (error_block_addr) { | 67 | + } else if (error_block_addr) { |
68 | + read_ack_register = cpu_to_le64(0); | 68 | + read_ack_register = cpu_to_le64(0); |
69 | + /* | 69 | + /* |
70 | + * Clear the Read Ack Register, OSPM will write it to 1 when | 70 | + * Clear the Read Ack Register, OSPM will write it to 1 when |
71 | + * it acknowledges this error. | 71 | + * it acknowledges this error. |
72 | + */ | 72 | + */ |
73 | + cpu_physical_memory_write(read_ack_register_addr, | 73 | + cpu_physical_memory_write(read_ack_register_addr, |
74 | + &read_ack_register, sizeof(uint64_t)); | 74 | + &read_ack_register, sizeof(uint64_t)); |
75 | 75 | ||
76 | - ret = acpi_ghes_record_mem_error(error_block_addr, | 76 | - ret = acpi_ghes_record_mem_error(error_block_addr, |
77 | - physical_address); | 77 | - physical_address); |
78 | - } else | 78 | - } else |
79 | - error_report("can not find Generic Error Status Block"); | 79 | - error_report("can not find Generic Error Status Block"); |
80 | + ret = acpi_ghes_record_mem_error(error_block_addr, | 80 | + ret = acpi_ghes_record_mem_error(error_block_addr, |
81 | + physical_address); | 81 | + physical_address); |
82 | + } else { | 82 | + } else { |
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.1 | diff view generated by jsdifflib |
1 | The GHES driver requires not only a HEST table, but also a | 1 | The GHES driver requires not only a HEST table, but also a |
---|---|---|---|
2 | separate firmware file to store Error Structure records. | 2 | separate firmware file to store Error Structure records. |
3 | It can't do one without the other. | 3 | It can't do one without the other. |
4 | 4 | ||
5 | Simplify the caller logic for it to require one function. | 5 | Simplify the caller logic for it to require one function. |
6 | 6 | ||
7 | No functional changes. | 7 | No functional changes. |
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> | 11 | Reviewed-by: Igor Mammedov <imammedo@redhat.com> |
12 | 12 | ||
13 | --- | 13 | --- |
14 | 14 | ||
15 | Changes from v10: | 15 | Changes from v10: |
16 | - Removed the logic which associates notification and source | 16 | - Removed the logic which associates notification and source |
17 | ID. This will be placed on a separate patch. | 17 | ID. This will be placed on a separate patch. |
18 | 18 | ||
19 | Changes from v8: | 19 | Changes from v8: |
20 | - Non-rename/cleanup changes merged altogether; | 20 | - Non-rename/cleanup changes merged altogether; |
21 | - source ID is now more generic, defined per guest target. | 21 | - source ID is now more generic, defined per guest target. |
22 | That should make easier to add support for 86. | 22 | That should make easier to add support for 86. |
23 | 23 | ||
24 | Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org> | 24 | Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org> |
25 | --- | 25 | --- |
26 | hw/acpi/ghes.c | 7 +++++-- | 26 | hw/acpi/ghes.c | 7 +++++-- |
27 | hw/arm/virt-acpi-build.c | 5 ++--- | 27 | hw/arm/virt-acpi-build.c | 5 ++--- |
28 | include/hw/acpi/ghes.h | 4 ++-- | 28 | include/hw/acpi/ghes.h | 4 ++-- |
29 | 3 files changed, 9 insertions(+), 7 deletions(-) | 29 | 3 files changed, 9 insertions(+), 7 deletions(-) |
30 | 30 | ||
31 | diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c | 31 | diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c |
32 | index XXXXXXX..XXXXXXX 100644 | 32 | index XXXXXXX..XXXXXXX 100644 |
33 | --- a/hw/acpi/ghes.c | 33 | --- a/hw/acpi/ghes.c |
34 | +++ b/hw/acpi/ghes.c | 34 | +++ b/hw/acpi/ghes.c |
35 | @@ -XXX,XX +XXX,XX @@ static int acpi_ghes_record_mem_error(uint64_t error_block_address, | 35 | @@ -XXX,XX +XXX,XX @@ static int acpi_ghes_record_mem_error(uint64_t error_block_address, |
36 | * Initialize "etc/hardware_errors" and "etc/hardware_errors_addr" fw_cfg blobs. | 36 | * Initialize "etc/hardware_errors" and "etc/hardware_errors_addr" fw_cfg blobs. |
37 | * See docs/specs/acpi_hest_ghes.rst for blobs format. | 37 | * See docs/specs/acpi_hest_ghes.rst for blobs format. |
38 | */ | 38 | */ |
39 | -void build_ghes_error_table(GArray *hardware_errors, BIOSLinker *linker) | 39 | -void build_ghes_error_table(GArray *hardware_errors, BIOSLinker *linker) |
40 | +static void build_ghes_error_table(GArray *hardware_errors, BIOSLinker *linker) | 40 | +static void build_ghes_error_table(GArray *hardware_errors, BIOSLinker *linker) |
41 | { | 41 | { |
42 | int i, error_status_block_offset; | 42 | int i, error_status_block_offset; |
43 | 43 | ||
44 | @@ -XXX,XX +XXX,XX @@ static void build_ghes_v2(GArray *table_data, int source_id, BIOSLinker *linker) | 44 | @@ -XXX,XX +XXX,XX @@ static void build_ghes_v2(GArray *table_data, int source_id, BIOSLinker *linker) |
45 | } | 45 | } |
46 | 46 | ||
47 | /* Build Hardware Error Source Table */ | 47 | /* Build Hardware Error Source Table */ |
48 | -void acpi_build_hest(GArray *table_data, BIOSLinker *linker, | 48 | -void acpi_build_hest(GArray *table_data, BIOSLinker *linker, |
49 | +void acpi_build_hest(GArray *table_data, GArray *hardware_errors, | 49 | +void acpi_build_hest(GArray *table_data, GArray *hardware_errors, |
50 | + BIOSLinker *linker, | 50 | + BIOSLinker *linker, |
51 | const char *oem_id, const char *oem_table_id) | 51 | const char *oem_id, const char *oem_table_id) |
52 | { | 52 | { |
53 | AcpiTable table = { .sig = "HEST", .rev = 1, | 53 | AcpiTable table = { .sig = "HEST", .rev = 1, |
54 | .oem_id = oem_id, .oem_table_id = oem_table_id }; | 54 | .oem_id = oem_id, .oem_table_id = oem_table_id }; |
55 | 55 | ||
56 | + build_ghes_error_table(hardware_errors, linker); | 56 | + build_ghes_error_table(hardware_errors, linker); |
57 | + | 57 | + |
58 | acpi_table_begin(&table, table_data); | 58 | acpi_table_begin(&table, table_data); |
59 | 59 | ||
60 | /* Error Source Count */ | 60 | /* Error Source Count */ |
61 | diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c | 61 | diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c |
62 | index XXXXXXX..XXXXXXX 100644 | 62 | index XXXXXXX..XXXXXXX 100644 |
63 | --- a/hw/arm/virt-acpi-build.c | 63 | --- a/hw/arm/virt-acpi-build.c |
64 | +++ b/hw/arm/virt-acpi-build.c | 64 | +++ b/hw/arm/virt-acpi-build.c |
65 | @@ -XXX,XX +XXX,XX @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables) | 65 | @@ -XXX,XX +XXX,XX @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables) |
66 | build_dbg2(tables_blob, tables->linker, vms); | 66 | build_dbg2(tables_blob, tables->linker, vms); |
67 | 67 | ||
68 | if (vms->ras) { | 68 | if (vms->ras) { |
69 | - build_ghes_error_table(tables->hardware_errors, tables->linker); | 69 | - build_ghes_error_table(tables->hardware_errors, tables->linker); |
70 | acpi_add_table(table_offsets, tables_blob); | 70 | acpi_add_table(table_offsets, tables_blob); |
71 | - acpi_build_hest(tables_blob, tables->linker, vms->oem_id, | 71 | - acpi_build_hest(tables_blob, tables->linker, vms->oem_id, |
72 | - vms->oem_table_id); | 72 | - vms->oem_table_id); |
73 | + acpi_build_hest(tables_blob, tables->hardware_errors, tables->linker, | 73 | + acpi_build_hest(tables_blob, tables->hardware_errors, tables->linker, |
74 | + vms->oem_id, vms->oem_table_id); | 74 | + vms->oem_id, vms->oem_table_id); |
75 | } | 75 | } |
76 | 76 | ||
77 | if (ms->numa_state->num_nodes > 0) { | 77 | if (ms->numa_state->num_nodes > 0) { |
78 | diff --git a/include/hw/acpi/ghes.h b/include/hw/acpi/ghes.h | 78 | diff --git a/include/hw/acpi/ghes.h b/include/hw/acpi/ghes.h |
79 | index XXXXXXX..XXXXXXX 100644 | 79 | index XXXXXXX..XXXXXXX 100644 |
80 | --- a/include/hw/acpi/ghes.h | 80 | --- a/include/hw/acpi/ghes.h |
81 | +++ b/include/hw/acpi/ghes.h | 81 | +++ b/include/hw/acpi/ghes.h |
82 | @@ -XXX,XX +XXX,XX @@ typedef struct AcpiGhesState { | 82 | @@ -XXX,XX +XXX,XX @@ typedef struct AcpiGhesState { |
83 | bool present; /* True if GHES is present at all on this board */ | 83 | bool present; /* True if GHES is present at all on this board */ |
84 | } AcpiGhesState; | 84 | } AcpiGhesState; |
85 | 85 | ||
86 | -void build_ghes_error_table(GArray *hardware_errors, BIOSLinker *linker); | 86 | -void build_ghes_error_table(GArray *hardware_errors, BIOSLinker *linker); |
87 | -void acpi_build_hest(GArray *table_data, BIOSLinker *linker, | 87 | -void acpi_build_hest(GArray *table_data, BIOSLinker *linker, |
88 | +void acpi_build_hest(GArray *table_data, GArray *hardware_errors, | 88 | +void acpi_build_hest(GArray *table_data, GArray *hardware_errors, |
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.1 | diff view generated by jsdifflib |
1 | GHES has two fields that are stored on HEST error source | 1 | GHES has two fields that are stored on HEST error source |
---|---|---|---|
2 | blocks associated with notifications: | 2 | blocks associated with notifications: |
3 | 3 | ||
4 | - notification type, which is a number defined at the ACPI spec | 4 | - notification type, which is a number defined at the ACPI spec |
5 | containing several arch-specific synchronous and assynchronous | 5 | containing several arch-specific synchronous and assynchronous |
6 | types; | 6 | types; |
7 | - source id, which is a HW/FW defined number, used to distinguish | 7 | - source id, which is a HW/FW defined number, used to distinguish |
8 | between different implemented sources. | 8 | between different implemented sources. |
9 | 9 | ||
10 | There could be several sources with the same notification type, | 10 | There could be several sources with the same notification type, |
11 | which is dependent of the way each architecture maps notifications. | 11 | which is dependent of the way each architecture maps notifications. |
12 | 12 | ||
13 | Right now, build_ghes_v2() hardcodes a 1:1 mapping between such | 13 | Right now, build_ghes_v2() hardcodes a 1:1 mapping between such |
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 | Reviewed-by: Igor Mammedov <imammedo@redhat.com> |
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. |
25 | 25 | ||
26 | Changes from v8: | 26 | Changes from v8: |
27 | - Non-rename/cleanup changes merged altogether; | 27 | - Non-rename/cleanup changes merged altogether; |
28 | - source ID is now more generic, defined per guest target. | 28 | - source ID is now more generic, defined per guest target. |
29 | That should make easier to add support for 86. | 29 | That should make easier to add support for 86. |
30 | 30 | ||
31 | Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org> | 31 | Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org> |
32 | --- | 32 | --- |
33 | hw/acpi/ghes.c | 23 +++++++++-------------- | 33 | hw/acpi/ghes.c | 23 +++++++++-------------- |
34 | 1 file changed, 9 insertions(+), 14 deletions(-) | 34 | 1 file changed, 9 insertions(+), 14 deletions(-) |
35 | 35 | ||
36 | diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c | 36 | diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c |
37 | index XXXXXXX..XXXXXXX 100644 | 37 | index XXXXXXX..XXXXXXX 100644 |
38 | --- a/hw/acpi/ghes.c | 38 | --- a/hw/acpi/ghes.c |
39 | +++ b/hw/acpi/ghes.c | 39 | +++ b/hw/acpi/ghes.c |
40 | @@ -XXX,XX +XXX,XX @@ static void build_ghes_error_table(GArray *hardware_errors, BIOSLinker *linker) | 40 | @@ -XXX,XX +XXX,XX @@ static void build_ghes_error_table(GArray *hardware_errors, BIOSLinker *linker) |
41 | } | 41 | } |
42 | 42 | ||
43 | /* Build Generic Hardware Error Source version 2 (GHESv2) */ | 43 | /* Build Generic Hardware Error Source version 2 (GHESv2) */ |
44 | -static void build_ghes_v2(GArray *table_data, int source_id, BIOSLinker *linker) | 44 | -static void build_ghes_v2(GArray *table_data, int source_id, BIOSLinker *linker) |
45 | +static void build_ghes_v2(GArray *table_data, | 45 | +static void build_ghes_v2(GArray *table_data, |
46 | + BIOSLinker *linker, | 46 | + BIOSLinker *linker, |
47 | + enum AcpiGhesNotifyType notify, | 47 | + enum AcpiGhesNotifyType notify, |
48 | + uint16_t source_id) | 48 | + uint16_t source_id) |
49 | { | 49 | { |
50 | uint64_t address_offset; | 50 | uint64_t address_offset; |
51 | + | 51 | + |
52 | /* | 52 | /* |
53 | * Type: | 53 | * Type: |
54 | * Generic Hardware Error Source version 2(GHESv2 - Type 10) | 54 | * Generic Hardware Error Source version 2(GHESv2 - Type 10) |
55 | @@ -XXX,XX +XXX,XX @@ static void build_ghes_v2(GArray *table_data, int source_id, BIOSLinker *linker) | 55 | @@ -XXX,XX +XXX,XX @@ static void build_ghes_v2(GArray *table_data, int source_id, BIOSLinker *linker) |
56 | address_offset + GAS_ADDR_OFFSET, sizeof(uint64_t), | 56 | address_offset + GAS_ADDR_OFFSET, sizeof(uint64_t), |
57 | ACPI_GHES_ERRORS_FW_CFG_FILE, source_id * sizeof(uint64_t)); | 57 | ACPI_GHES_ERRORS_FW_CFG_FILE, source_id * sizeof(uint64_t)); |
58 | 58 | ||
59 | - switch (source_id) { | 59 | - switch (source_id) { |
60 | - case ACPI_HEST_SRC_ID_SEA: | 60 | - case ACPI_HEST_SRC_ID_SEA: |
61 | - /* | 61 | - /* |
62 | - * Notification Structure | 62 | - * Notification Structure |
63 | - * Now only enable ARMv8 SEA notification type | 63 | - * Now only enable ARMv8 SEA notification type |
64 | - */ | 64 | - */ |
65 | - build_ghes_hw_error_notification(table_data, ACPI_GHES_NOTIFY_SEA); | 65 | - build_ghes_hw_error_notification(table_data, ACPI_GHES_NOTIFY_SEA); |
66 | - break; | 66 | - break; |
67 | - default: | 67 | - default: |
68 | - error_report("Not support this error source"); | 68 | - error_report("Not support this error source"); |
69 | - abort(); | 69 | - abort(); |
70 | - } | 70 | - } |
71 | + /* Notification Structure */ | 71 | + /* Notification Structure */ |
72 | + build_ghes_hw_error_notification(table_data, notify); | 72 | + build_ghes_hw_error_notification(table_data, notify); |
73 | 73 | ||
74 | /* Error Status Block Length */ | 74 | /* Error Status Block Length */ |
75 | build_append_int_noprefix(table_data, ACPI_GHES_MAX_RAW_DATA_LENGTH, 4); | 75 | build_append_int_noprefix(table_data, ACPI_GHES_MAX_RAW_DATA_LENGTH, 4); |
76 | @@ -XXX,XX +XXX,XX @@ void acpi_build_hest(GArray *table_data, GArray *hardware_errors, | 76 | @@ -XXX,XX +XXX,XX @@ void acpi_build_hest(GArray *table_data, GArray *hardware_errors, |
77 | 77 | ||
78 | /* Error Source Count */ | 78 | /* Error Source Count */ |
79 | build_append_int_noprefix(table_data, ACPI_GHES_ERROR_SOURCE_COUNT, 4); | 79 | build_append_int_noprefix(table_data, ACPI_GHES_ERROR_SOURCE_COUNT, 4); |
80 | - build_ghes_v2(table_data, ACPI_HEST_SRC_ID_SEA, linker); | 80 | - build_ghes_v2(table_data, ACPI_HEST_SRC_ID_SEA, linker); |
81 | + build_ghes_v2(table_data, linker, | 81 | + build_ghes_v2(table_data, linker, |
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.1 | diff view generated by jsdifflib |
1 | Align the header file with the actual implementation of | 1 | Align the header file with the actual implementation of |
---|---|---|---|
2 | this function, as the first argument is source ID and not | 2 | this function, as the first argument is source ID and not |
3 | notification type. | 3 | notification type. |
4 | 4 | ||
5 | Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org> | 5 | Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org> |
6 | Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> | 6 | Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> |
7 | Reviewed-by: Igor Mammedov <imammedo@redhat.com> | 7 | Reviewed-by: Igor Mammedov <imammedo@redhat.com> |
8 | 8 | ||
9 | --- | 9 | --- |
10 | 10 | ||
11 | Changes from v8: | 11 | Changes from v8: |
12 | - Non-rename/cleanup changes merged altogether; | 12 | - Non-rename/cleanup changes merged altogether; |
13 | - source ID is now more generic, defined per guest target. | 13 | - source ID is now more generic, defined per guest target. |
14 | That should make easier to add support for 86. | 14 | That should make easier to add support for 86. |
15 | 15 | ||
16 | Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org> | 16 | Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org> |
17 | --- | 17 | --- |
18 | include/hw/acpi/ghes.h | 2 +- | 18 | include/hw/acpi/ghes.h | 2 +- |
19 | 1 file changed, 1 insertion(+), 1 deletion(-) | 19 | 1 file changed, 1 insertion(+), 1 deletion(-) |
20 | 20 | ||
21 | diff --git a/include/hw/acpi/ghes.h b/include/hw/acpi/ghes.h | 21 | diff --git a/include/hw/acpi/ghes.h b/include/hw/acpi/ghes.h |
22 | index XXXXXXX..XXXXXXX 100644 | 22 | index XXXXXXX..XXXXXXX 100644 |
23 | --- a/include/hw/acpi/ghes.h | 23 | --- a/include/hw/acpi/ghes.h |
24 | +++ b/include/hw/acpi/ghes.h | 24 | +++ b/include/hw/acpi/ghes.h |
25 | @@ -XXX,XX +XXX,XX @@ void acpi_build_hest(GArray *table_data, GArray *hardware_errors, | 25 | @@ -XXX,XX +XXX,XX @@ void acpi_build_hest(GArray *table_data, GArray *hardware_errors, |
26 | const char *oem_id, const char *oem_table_id); | 26 | const char *oem_id, const char *oem_table_id); |
27 | void acpi_ghes_add_fw_cfg(AcpiGhesState *vms, FWCfgState *s, | 27 | void acpi_ghes_add_fw_cfg(AcpiGhesState *vms, FWCfgState *s, |
28 | GArray *hardware_errors); | 28 | GArray *hardware_errors); |
29 | -int acpi_ghes_record_errors(uint8_t notify, uint64_t error_physical_addr); | 29 | -int acpi_ghes_record_errors(uint8_t notify, uint64_t error_physical_addr); |
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.1 | diff view generated by jsdifflib |
1 | acpi_ghes_record_errors() has an assert() at the beginning | 1 | acpi_ghes_record_errors() has an assert() at the beginning |
---|---|---|---|
2 | to ensure that source_id will be lower than | 2 | to ensure that source_id will be lower than |
3 | ACPI_GHES_ERROR_SOURCE_COUNT. Remove a duplicated check. | 3 | ACPI_GHES_ERROR_SOURCE_COUNT. Remove a duplicated check. |
4 | 4 | ||
5 | Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org> | 5 | Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org> |
6 | Reviewed-by: Igor Mammedov <imammedo@redhat.com> | 6 | Reviewed-by: Igor Mammedov <imammedo@redhat.com> |
7 | Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> | 7 | Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> |
8 | --- | 8 | --- |
9 | hw/acpi/ghes.c | 4 +--- | 9 | hw/acpi/ghes.c | 4 +--- |
10 | 1 file changed, 1 insertion(+), 3 deletions(-) | 10 | 1 file changed, 1 insertion(+), 3 deletions(-) |
11 | 11 | ||
12 | diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c | 12 | diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c |
13 | index XXXXXXX..XXXXXXX 100644 | 13 | index XXXXXXX..XXXXXXX 100644 |
14 | --- a/hw/acpi/ghes.c | 14 | --- a/hw/acpi/ghes.c |
15 | +++ b/hw/acpi/ghes.c | 15 | +++ b/hw/acpi/ghes.c |
16 | @@ -XXX,XX +XXX,XX @@ int acpi_ghes_record_errors(uint8_t source_id, uint64_t physical_address) | 16 | @@ -XXX,XX +XXX,XX @@ int acpi_ghes_record_errors(uint8_t source_id, uint64_t physical_address) |
17 | return -1; | 17 | return -1; |
18 | } | 18 | } |
19 | 19 | ||
20 | - if (source_id < ACPI_GHES_ERROR_SOURCE_COUNT) { | 20 | - if (source_id < ACPI_GHES_ERROR_SOURCE_COUNT) { |
21 | - start_addr += source_id * sizeof(uint64_t); | 21 | - start_addr += source_id * sizeof(uint64_t); |
22 | - } | 22 | - } |
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.1 | diff view generated by jsdifflib |
1 | As described at: ACPI 6.5 spec at: | 1 | As described at: ACPI 6.5 spec at: |
---|---|---|---|
2 | 18.3.2. ACPI Error Source | 2 | 18.3.2. ACPI Error Source |
3 | 3 | ||
4 | In particular at GHES/GHESv2 table: | 4 | In particular at GHES/GHESv2 table: |
5 | Table 18.10 Generic Hardware Error Source Structure | 5 | Table 18.10 Generic Hardware Error Source Structure |
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> | 11 | Reviewed-by: Igor Mammedov <imammedo@redhat.com> |
12 | --- | 12 | --- |
13 | hw/acpi/ghes-stub.c | 2 +- | 13 | hw/acpi/ghes-stub.c | 2 +- |
14 | hw/acpi/ghes.c | 2 +- | 14 | hw/acpi/ghes.c | 2 +- |
15 | include/hw/acpi/ghes.h | 2 +- | 15 | include/hw/acpi/ghes.h | 2 +- |
16 | 3 files changed, 3 insertions(+), 3 deletions(-) | 16 | 3 files changed, 3 insertions(+), 3 deletions(-) |
17 | 17 | ||
18 | diff --git a/hw/acpi/ghes-stub.c b/hw/acpi/ghes-stub.c | 18 | diff --git a/hw/acpi/ghes-stub.c b/hw/acpi/ghes-stub.c |
19 | index XXXXXXX..XXXXXXX 100644 | 19 | index XXXXXXX..XXXXXXX 100644 |
20 | --- a/hw/acpi/ghes-stub.c | 20 | --- a/hw/acpi/ghes-stub.c |
21 | +++ b/hw/acpi/ghes-stub.c | 21 | +++ b/hw/acpi/ghes-stub.c |
22 | @@ -XXX,XX +XXX,XX @@ | 22 | @@ -XXX,XX +XXX,XX @@ |
23 | #include "qemu/osdep.h" | 23 | #include "qemu/osdep.h" |
24 | #include "hw/acpi/ghes.h" | 24 | #include "hw/acpi/ghes.h" |
25 | 25 | ||
26 | -int acpi_ghes_record_errors(uint8_t source_id, uint64_t physical_address) | 26 | -int acpi_ghes_record_errors(uint8_t source_id, uint64_t physical_address) |
27 | +int acpi_ghes_record_errors(uint16_t source_id, uint64_t physical_address) | 27 | +int acpi_ghes_record_errors(uint16_t source_id, uint64_t physical_address) |
28 | { | 28 | { |
29 | return -1; | 29 | return -1; |
30 | } | 30 | } |
31 | diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c | 31 | diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c |
32 | index XXXXXXX..XXXXXXX 100644 | 32 | index XXXXXXX..XXXXXXX 100644 |
33 | --- a/hw/acpi/ghes.c | 33 | --- a/hw/acpi/ghes.c |
34 | +++ b/hw/acpi/ghes.c | 34 | +++ b/hw/acpi/ghes.c |
35 | @@ -XXX,XX +XXX,XX @@ void acpi_ghes_add_fw_cfg(AcpiGhesState *ags, FWCfgState *s, | 35 | @@ -XXX,XX +XXX,XX @@ void acpi_ghes_add_fw_cfg(AcpiGhesState *ags, FWCfgState *s, |
36 | ags->present = true; | 36 | ags->present = true; |
37 | } | 37 | } |
38 | 38 | ||
39 | -int acpi_ghes_record_errors(uint8_t source_id, uint64_t physical_address) | 39 | -int acpi_ghes_record_errors(uint8_t source_id, uint64_t physical_address) |
40 | +int acpi_ghes_record_errors(uint16_t source_id, uint64_t physical_address) | 40 | +int acpi_ghes_record_errors(uint16_t source_id, uint64_t physical_address) |
41 | { | 41 | { |
42 | uint64_t error_block_addr, read_ack_register_addr, read_ack_register = 0; | 42 | uint64_t error_block_addr, read_ack_register_addr, read_ack_register = 0; |
43 | uint64_t start_addr; | 43 | uint64_t start_addr; |
44 | diff --git a/include/hw/acpi/ghes.h b/include/hw/acpi/ghes.h | 44 | diff --git a/include/hw/acpi/ghes.h b/include/hw/acpi/ghes.h |
45 | index XXXXXXX..XXXXXXX 100644 | 45 | index XXXXXXX..XXXXXXX 100644 |
46 | --- a/include/hw/acpi/ghes.h | 46 | --- a/include/hw/acpi/ghes.h |
47 | +++ b/include/hw/acpi/ghes.h | 47 | +++ b/include/hw/acpi/ghes.h |
48 | @@ -XXX,XX +XXX,XX @@ void acpi_build_hest(GArray *table_data, GArray *hardware_errors, | 48 | @@ -XXX,XX +XXX,XX @@ void acpi_build_hest(GArray *table_data, GArray *hardware_errors, |
49 | const char *oem_id, const char *oem_table_id); | 49 | const char *oem_id, const char *oem_table_id); |
50 | void acpi_ghes_add_fw_cfg(AcpiGhesState *vms, FWCfgState *s, | 50 | void acpi_ghes_add_fw_cfg(AcpiGhesState *vms, FWCfgState *s, |
51 | GArray *hardware_errors); | 51 | GArray *hardware_errors); |
52 | -int acpi_ghes_record_errors(uint8_t source_id, uint64_t error_physical_addr); | 52 | -int acpi_ghes_record_errors(uint8_t source_id, uint64_t error_physical_addr); |
53 | +int acpi_ghes_record_errors(uint16_t source_id, uint64_t error_physical_addr); | 53 | +int acpi_ghes_record_errors(uint16_t source_id, uint64_t error_physical_addr); |
54 | 54 | ||
55 | /** | 55 | /** |
56 | * acpi_ghes_present: Report whether ACPI GHES table is present | 56 | * acpi_ghes_present: Report whether ACPI GHES table is present |
57 | -- | 57 | -- |
58 | 2.47.1 | 58 | 2.47.1 | diff view generated by jsdifflib |
1 | The 'physical_address' value is a faulty page. As such, 0 is | 1 | The 'physical_address' value is a faulty page. As such, 0 is |
---|---|---|---|
2 | as valid as any other value. | 2 | as valid as any other value. |
3 | 3 | ||
4 | Suggested-by: Igor Mammedov <imammedo@redhat.com> | 4 | Suggested-by: Igor Mammedov <imammedo@redhat.com> |
5 | Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org> | 5 | Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org> |
6 | Reviewed-by: Igor Mammedov <imammedo@redhat.com> | ||
7 | --- | 6 | --- |
8 | hw/acpi/ghes.c | 4 ---- | 7 | hw/acpi/ghes.c | 4 ---- |
9 | 1 file changed, 4 deletions(-) | 8 | 1 file changed, 4 deletions(-) |
10 | 9 | ||
11 | diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c | 10 | diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c |
... | ... | diff view generated by jsdifflib |
... | ... | ||
---|---|---|---|
12 | acpi_ghes_record_errors() function. | 12 | acpi_ghes_record_errors() function. |
13 | 13 | ||
14 | A further patch will give it a better name. | 14 | A further patch will give it a better name. |
15 | 15 | ||
16 | Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org> | 16 | Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org> |
17 | Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> | 17 | |
18 | Reviewed-by: Igor Mammedov <imammedo@redhat.com> | 18 | # Conflicts: |
19 | # roms/edk2 | ||
19 | --- | 20 | --- |
20 | hw/acpi/ghes.c | 121 ++++++++++++++++++++++++----------------- | 21 | hw/acpi/ghes.c | 121 ++++++++++++++++++++++++----------------- |
21 | include/hw/acpi/ghes.h | 3 + | 22 | include/hw/acpi/ghes.h | 3 + |
22 | 2 files changed, 73 insertions(+), 51 deletions(-) | 23 | 2 files changed, 73 insertions(+), 51 deletions(-) |
23 | 24 | ||
... | ... | 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 | Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org> | ||
6 | Reviewed-by: Igor Mammedov <imammedo@redhat.com> | 5 | Reviewed-by: Igor Mammedov <imammedo@redhat.com> |
7 | Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> | 6 | Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> |
7 | Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org> | ||
8 | --- | 8 | --- |
9 | hw/acpi/ghes-stub.c | 2 +- | 9 | hw/acpi/ghes-stub.c | 2 +- |
10 | hw/acpi/ghes.c | 2 +- | 10 | hw/acpi/ghes.c | 2 +- |
11 | include/hw/acpi/ghes.h | 4 ++-- | 11 | include/hw/acpi/ghes.h | 4 ++-- |
12 | target/arm/kvm.c | 2 +- | 12 | target/arm/kvm.c | 2 +- |
... | ... | 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> | 4 | Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> |
5 | Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org> | 5 | Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org> |
6 | Reviewed-by: Igor Mammedov <imammedo@redhat.com> | 6 | Reviewed-by: Igor Mammedov <imammedo@redhat.com> |
7 | --- | 7 | --- |
8 | hw/acpi/ghes.c | 5 ++++- | 8 | hw/acpi/ghes.c | 5 ++++- |
9 | 1 file changed, 4 insertions(+), 1 deletion(-) | 9 | 1 file changed, 4 insertions(+), 1 deletion(-) |
10 | 10 | ||
11 | diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c | 11 | diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c |
12 | index XXXXXXX..XXXXXXX 100644 | 12 | index XXXXXXX..XXXXXXX 100644 |
13 | --- a/hw/acpi/ghes.c | 13 | --- a/hw/acpi/ghes.c |
14 | +++ b/hw/acpi/ghes.c | 14 | +++ b/hw/acpi/ghes.c |
15 | @@ -XXX,XX +XXX,XX @@ void ghes_record_cper_errors(const void *cper, size_t len, | 15 | @@ -XXX,XX +XXX,XX @@ void ghes_record_cper_errors(const void *cper, size_t len, |
16 | 16 | ||
17 | acpi_ged_state = ACPI_GED(object_resolve_path_type("", TYPE_ACPI_GED, | 17 | acpi_ged_state = ACPI_GED(object_resolve_path_type("", TYPE_ACPI_GED, |
18 | NULL)); | 18 | NULL)); |
19 | - g_assert(acpi_ged_state); | 19 | - g_assert(acpi_ged_state); |
20 | + if (!acpi_ged_state) { | 20 | + if (!acpi_ged_state) { |
21 | + error_setg(errp, "Can't find ACPI_GED object"); | 21 | + error_setg(errp, "Can't find ACPI_GED object"); |
22 | + return; | 22 | + return; |
23 | + } | 23 | + } |
24 | ags = &acpi_ged_state->ghes_state; | 24 | ags = &acpi_ged_state->ghes_state; |
25 | 25 | ||
26 | start_addr = le64_to_cpu(ags->ghes_addr_le); | 26 | start_addr = le64_to_cpu(ags->ghes_addr_le); |
27 | -- | 27 | -- |
28 | 2.47.1 | 28 | 2.47.1 | diff view generated by jsdifflib |
1 | Now that we have also have a file to store HEST data location, | 1 | Now that we have also have a file to store HEST data location, |
---|---|---|---|
2 | which is part of GHES, better name the file where CPER records | 2 | which is part of GHES, better name the file where CPER records |
3 | are stored. | 3 | are stored. |
4 | 4 | ||
5 | No functional changes. | 5 | No functional changes. |
6 | 6 | ||
7 | Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org> | 7 | Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org> |
8 | Reviewed-by: Igor Mammedov <imammedo@redhat.com> | 8 | Reviewed-by: Igor Mammedov <imammedo@redhat.com> |
9 | Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> | 9 | Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> |
10 | --- | 10 | --- |
11 | hw/acpi/ghes.c | 38 +++++++++++++++++++++++--------------- | 11 | hw/acpi/ghes.c | 38 +++++++++++++++++++++++--------------- |
12 | 1 file changed, 23 insertions(+), 15 deletions(-) | 12 | 1 file changed, 23 insertions(+), 15 deletions(-) |
13 | 13 | ||
14 | diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c | 14 | diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c |
15 | index XXXXXXX..XXXXXXX 100644 | 15 | index XXXXXXX..XXXXXXX 100644 |
16 | --- a/hw/acpi/ghes.c | 16 | --- a/hw/acpi/ghes.c |
17 | +++ b/hw/acpi/ghes.c | 17 | +++ b/hw/acpi/ghes.c |
18 | @@ -XXX,XX +XXX,XX @@ | 18 | @@ -XXX,XX +XXX,XX @@ |
19 | #include "hw/nvram/fw_cfg.h" | 19 | #include "hw/nvram/fw_cfg.h" |
20 | #include "qemu/uuid.h" | 20 | #include "qemu/uuid.h" |
21 | 21 | ||
22 | -#define ACPI_GHES_ERRORS_FW_CFG_FILE "etc/hardware_errors" | 22 | -#define ACPI_GHES_ERRORS_FW_CFG_FILE "etc/hardware_errors" |
23 | -#define ACPI_GHES_DATA_ADDR_FW_CFG_FILE "etc/hardware_errors_addr" | 23 | -#define ACPI_GHES_DATA_ADDR_FW_CFG_FILE "etc/hardware_errors_addr" |
24 | +#define ACPI_HW_ERROR_FW_CFG_FILE "etc/hardware_errors" | 24 | +#define ACPI_HW_ERROR_FW_CFG_FILE "etc/hardware_errors" |
25 | +#define ACPI_HW_ERROR_ADDR_FW_CFG_FILE "etc/hardware_errors_addr" | 25 | +#define ACPI_HW_ERROR_ADDR_FW_CFG_FILE "etc/hardware_errors_addr" |
26 | 26 | ||
27 | /* The max size in bytes for one error block */ | 27 | /* The max size in bytes for one error block */ |
28 | #define ACPI_GHES_MAX_RAW_DATA_LENGTH (1 * KiB) | 28 | #define ACPI_GHES_MAX_RAW_DATA_LENGTH (1 * KiB) |
29 | @@ -XXX,XX +XXX,XX @@ static void build_ghes_error_table(GArray *hardware_errors, BIOSLinker *linker) | 29 | @@ -XXX,XX +XXX,XX @@ static void build_ghes_error_table(GArray *hardware_errors, BIOSLinker *linker) |
30 | ACPI_GHES_MAX_RAW_DATA_LENGTH * ACPI_GHES_ERROR_SOURCE_COUNT); | 30 | ACPI_GHES_MAX_RAW_DATA_LENGTH * ACPI_GHES_ERROR_SOURCE_COUNT); |
31 | 31 | ||
32 | /* Tell guest firmware to place hardware_errors blob into RAM */ | 32 | /* Tell guest firmware to place hardware_errors blob into RAM */ |
33 | - bios_linker_loader_alloc(linker, ACPI_GHES_ERRORS_FW_CFG_FILE, | 33 | - bios_linker_loader_alloc(linker, ACPI_GHES_ERRORS_FW_CFG_FILE, |
34 | + bios_linker_loader_alloc(linker, ACPI_HW_ERROR_FW_CFG_FILE, | 34 | + bios_linker_loader_alloc(linker, ACPI_HW_ERROR_FW_CFG_FILE, |
35 | hardware_errors, sizeof(uint64_t), false); | 35 | hardware_errors, sizeof(uint64_t), false); |
36 | 36 | ||
37 | for (i = 0; i < ACPI_GHES_ERROR_SOURCE_COUNT; i++) { | 37 | for (i = 0; i < ACPI_GHES_ERROR_SOURCE_COUNT; i++) { |
38 | @@ -XXX,XX +XXX,XX @@ static void build_ghes_error_table(GArray *hardware_errors, BIOSLinker *linker) | 38 | @@ -XXX,XX +XXX,XX @@ static void build_ghes_error_table(GArray *hardware_errors, BIOSLinker *linker) |
39 | * corresponding "Generic Error Status Block" | 39 | * corresponding "Generic Error Status Block" |
40 | */ | 40 | */ |
41 | bios_linker_loader_add_pointer(linker, | 41 | bios_linker_loader_add_pointer(linker, |
42 | - ACPI_GHES_ERRORS_FW_CFG_FILE, sizeof(uint64_t) * i, | 42 | - ACPI_GHES_ERRORS_FW_CFG_FILE, sizeof(uint64_t) * i, |
43 | - sizeof(uint64_t), ACPI_GHES_ERRORS_FW_CFG_FILE, | 43 | - sizeof(uint64_t), ACPI_GHES_ERRORS_FW_CFG_FILE, |
44 | - error_status_block_offset + i * ACPI_GHES_MAX_RAW_DATA_LENGTH); | 44 | - error_status_block_offset + i * ACPI_GHES_MAX_RAW_DATA_LENGTH); |
45 | + ACPI_HW_ERROR_FW_CFG_FILE, | 45 | + ACPI_HW_ERROR_FW_CFG_FILE, |
46 | + sizeof(uint64_t) * i, | 46 | + sizeof(uint64_t) * i, |
47 | + sizeof(uint64_t), | 47 | + sizeof(uint64_t), |
48 | + ACPI_HW_ERROR_FW_CFG_FILE, | 48 | + ACPI_HW_ERROR_FW_CFG_FILE, |
49 | + error_status_block_offset + | 49 | + error_status_block_offset + |
50 | + i * ACPI_GHES_MAX_RAW_DATA_LENGTH); | 50 | + i * ACPI_GHES_MAX_RAW_DATA_LENGTH); |
51 | } | 51 | } |
52 | 52 | ||
53 | /* | 53 | /* |
54 | * tell firmware to write hardware_errors GPA into | 54 | * tell firmware to write hardware_errors GPA into |
55 | * hardware_errors_addr fw_cfg, once the former has been initialized. | 55 | * hardware_errors_addr fw_cfg, once the former has been initialized. |
56 | */ | 56 | */ |
57 | - bios_linker_loader_write_pointer(linker, ACPI_GHES_DATA_ADDR_FW_CFG_FILE, | 57 | - bios_linker_loader_write_pointer(linker, ACPI_GHES_DATA_ADDR_FW_CFG_FILE, |
58 | - 0, sizeof(uint64_t), ACPI_GHES_ERRORS_FW_CFG_FILE, 0); | 58 | - 0, sizeof(uint64_t), ACPI_GHES_ERRORS_FW_CFG_FILE, 0); |
59 | + bios_linker_loader_write_pointer(linker, ACPI_HW_ERROR_ADDR_FW_CFG_FILE, 0, | 59 | + bios_linker_loader_write_pointer(linker, ACPI_HW_ERROR_ADDR_FW_CFG_FILE, 0, |
60 | + sizeof(uint64_t), | 60 | + sizeof(uint64_t), |
61 | + ACPI_HW_ERROR_FW_CFG_FILE, 0); | 61 | + ACPI_HW_ERROR_FW_CFG_FILE, 0); |
62 | } | 62 | } |
63 | 63 | ||
64 | /* Build Generic Hardware Error Source version 2 (GHESv2) */ | 64 | /* Build Generic Hardware Error Source version 2 (GHESv2) */ |
65 | @@ -XXX,XX +XXX,XX @@ static void build_ghes_v2(GArray *table_data, | 65 | @@ -XXX,XX +XXX,XX @@ static void build_ghes_v2(GArray *table_data, |
66 | build_append_gas(table_data, AML_AS_SYSTEM_MEMORY, 0x40, 0, | 66 | build_append_gas(table_data, AML_AS_SYSTEM_MEMORY, 0x40, 0, |
67 | 4 /* QWord access */, 0); | 67 | 4 /* QWord access */, 0); |
68 | bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE, | 68 | bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE, |
69 | - address_offset + GAS_ADDR_OFFSET, sizeof(uint64_t), | 69 | - address_offset + GAS_ADDR_OFFSET, sizeof(uint64_t), |
70 | - ACPI_GHES_ERRORS_FW_CFG_FILE, source_id * sizeof(uint64_t)); | 70 | - ACPI_GHES_ERRORS_FW_CFG_FILE, source_id * sizeof(uint64_t)); |
71 | + address_offset + GAS_ADDR_OFFSET, | 71 | + address_offset + GAS_ADDR_OFFSET, |
72 | + sizeof(uint64_t), | 72 | + sizeof(uint64_t), |
73 | + ACPI_HW_ERROR_FW_CFG_FILE, | 73 | + ACPI_HW_ERROR_FW_CFG_FILE, |
74 | + source_id * sizeof(uint64_t)); | 74 | + source_id * sizeof(uint64_t)); |
75 | 75 | ||
76 | /* Notification Structure */ | 76 | /* Notification Structure */ |
77 | build_ghes_hw_error_notification(table_data, notify); | 77 | build_ghes_hw_error_notification(table_data, notify); |
78 | @@ -XXX,XX +XXX,XX @@ static void build_ghes_v2(GArray *table_data, | 78 | @@ -XXX,XX +XXX,XX @@ static void build_ghes_v2(GArray *table_data, |
79 | build_append_gas(table_data, AML_AS_SYSTEM_MEMORY, 0x40, 0, | 79 | build_append_gas(table_data, AML_AS_SYSTEM_MEMORY, 0x40, 0, |
80 | 4 /* QWord access */, 0); | 80 | 4 /* QWord access */, 0); |
81 | bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE, | 81 | bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE, |
82 | - address_offset + GAS_ADDR_OFFSET, | 82 | - address_offset + GAS_ADDR_OFFSET, |
83 | - sizeof(uint64_t), ACPI_GHES_ERRORS_FW_CFG_FILE, | 83 | - sizeof(uint64_t), ACPI_GHES_ERRORS_FW_CFG_FILE, |
84 | - (ACPI_GHES_ERROR_SOURCE_COUNT + source_id) * sizeof(uint64_t)); | 84 | - (ACPI_GHES_ERROR_SOURCE_COUNT + source_id) * sizeof(uint64_t)); |
85 | + address_offset + GAS_ADDR_OFFSET, | 85 | + address_offset + GAS_ADDR_OFFSET, |
86 | + sizeof(uint64_t), | 86 | + sizeof(uint64_t), |
87 | + ACPI_HW_ERROR_FW_CFG_FILE, | 87 | + ACPI_HW_ERROR_FW_CFG_FILE, |
88 | + (ACPI_GHES_ERROR_SOURCE_COUNT + source_id) | 88 | + (ACPI_GHES_ERROR_SOURCE_COUNT + source_id) |
89 | + * sizeof(uint64_t)); | 89 | + * sizeof(uint64_t)); |
90 | 90 | ||
91 | /* | 91 | /* |
92 | * Read Ack Preserve field | 92 | * Read Ack Preserve field |
93 | @@ -XXX,XX +XXX,XX @@ void acpi_ghes_add_fw_cfg(AcpiGhesState *ags, FWCfgState *s, | 93 | @@ -XXX,XX +XXX,XX @@ void acpi_ghes_add_fw_cfg(AcpiGhesState *ags, FWCfgState *s, |
94 | GArray *hardware_error) | 94 | GArray *hardware_error) |
95 | { | 95 | { |
96 | /* Create a read-only fw_cfg file for GHES */ | 96 | /* Create a read-only fw_cfg file for GHES */ |
97 | - fw_cfg_add_file(s, ACPI_GHES_ERRORS_FW_CFG_FILE, hardware_error->data, | 97 | - fw_cfg_add_file(s, ACPI_GHES_ERRORS_FW_CFG_FILE, hardware_error->data, |
98 | + fw_cfg_add_file(s, ACPI_HW_ERROR_FW_CFG_FILE, hardware_error->data, | 98 | + fw_cfg_add_file(s, ACPI_HW_ERROR_FW_CFG_FILE, hardware_error->data, |
99 | hardware_error->len); | 99 | hardware_error->len); |
100 | 100 | ||
101 | /* Create a read-write fw_cfg file for Address */ | 101 | /* Create a read-write fw_cfg file for Address */ |
102 | - fw_cfg_add_file_callback(s, ACPI_GHES_DATA_ADDR_FW_CFG_FILE, NULL, NULL, | 102 | - fw_cfg_add_file_callback(s, ACPI_GHES_DATA_ADDR_FW_CFG_FILE, NULL, NULL, |
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.1 | 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> |
... | ... | 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, ¬if_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 | 40 +++++++++++++++++++++++++++++++--------- |
18 | 1 file changed, 31 insertions(+), 9 deletions(-) | 17 | 1 file changed, 31 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 |
... | ... | 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 |
1 | Extending to multiple sources require a BIOS pointer to the | 1 | Extending to multiple sources require a BIOS pointer to the |
---|---|---|---|
2 | beginning of the HEST table, which in turn requires a backward-compatible | 2 | beginning of the HEST table, which in turn requires a backward-compatible |
3 | code. | 3 | code. |
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> | 9 | Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> |
10 | Reviewed-by: Igor Mammedov <imammedo@redhat.com> | 10 | Reviewed-by: Igor Mammedov <imammedo@redhat.com> |
11 | --- | 11 | --- |
12 | hw/acpi/ghes.c | 12 ++++-------- | 12 | hw/acpi/ghes.c | 12 ++++-------- |
13 | 1 file changed, 4 insertions(+), 8 deletions(-) | 13 | 1 file changed, 4 insertions(+), 8 deletions(-) |
14 | 14 | ||
15 | diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c | 15 | diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c |
16 | index XXXXXXX..XXXXXXX 100644 | 16 | index XXXXXXX..XXXXXXX 100644 |
17 | --- a/hw/acpi/ghes.c | 17 | --- a/hw/acpi/ghes.c |
18 | +++ b/hw/acpi/ghes.c | 18 | +++ b/hw/acpi/ghes.c |
19 | @@ -XXX,XX +XXX,XX @@ static void get_hw_error_offsets(uint64_t ghes_addr, | 19 | @@ -XXX,XX +XXX,XX @@ static void get_hw_error_offsets(uint64_t ghes_addr, |
20 | * As the current version supports only one source, the ack offset is | 20 | * As the current version supports only one source, the ack offset is |
21 | * just sizeof(uint64_t). | 21 | * just sizeof(uint64_t). |
22 | */ | 22 | */ |
23 | - *read_ack_register_addr = ghes_addr + | 23 | - *read_ack_register_addr = ghes_addr + |
24 | - ACPI_GHES_ERROR_SOURCE_COUNT * sizeof(uint64_t); | 24 | - ACPI_GHES_ERROR_SOURCE_COUNT * sizeof(uint64_t); |
25 | + *read_ack_register_addr = ghes_addr + sizeof(uint64_t); | 25 | + *read_ack_register_addr = ghes_addr + sizeof(uint64_t); |
26 | } | 26 | } |
27 | 27 | ||
28 | void ghes_record_cper_errors(const void *cper, size_t len, | 28 | void ghes_record_cper_errors(const void *cper, size_t len, |
29 | uint16_t source_id, Error **errp) | 29 | uint16_t source_id, Error **errp) |
30 | { | 30 | { |
31 | uint64_t cper_addr = 0, read_ack_register_addr = 0, read_ack_register; | 31 | uint64_t cper_addr = 0, read_ack_register_addr = 0, read_ack_register; |
32 | - uint64_t start_addr; | 32 | - uint64_t start_addr; |
33 | AcpiGedState *acpi_ged_state; | 33 | AcpiGedState *acpi_ged_state; |
34 | AcpiGhesState *ags; | 34 | AcpiGhesState *ags; |
35 | 35 | ||
36 | @@ -XXX,XX +XXX,XX @@ void ghes_record_cper_errors(const void *cper, size_t len, | 36 | @@ -XXX,XX +XXX,XX @@ void ghes_record_cper_errors(const void *cper, size_t len, |
37 | } | 37 | } |
38 | ags = &acpi_ged_state->ghes_state; | 38 | ags = &acpi_ged_state->ghes_state; |
39 | 39 | ||
40 | - start_addr = le64_to_cpu(ags->hw_error_le); | 40 | - start_addr = le64_to_cpu(ags->hw_error_le); |
41 | - | 41 | - |
42 | - start_addr += source_id * sizeof(uint64_t); | 42 | - start_addr += source_id * sizeof(uint64_t); |
43 | - | 43 | - |
44 | - get_hw_error_offsets(start_addr, &cper_addr, &read_ack_register_addr); | 44 | - get_hw_error_offsets(start_addr, &cper_addr, &read_ack_register_addr); |
45 | + assert(ACPI_GHES_ERROR_SOURCE_COUNT == 1); | 45 | + assert(ACPI_GHES_ERROR_SOURCE_COUNT == 1); |
46 | + get_hw_error_offsets(le64_to_cpu(ags->hw_error_le), | 46 | + get_hw_error_offsets(le64_to_cpu(ags->hw_error_le), |
47 | + &cper_addr, &read_ack_register_addr); | 47 | + &cper_addr, &read_ack_register_addr); |
48 | 48 | ||
49 | if (!cper_addr) { | 49 | if (!cper_addr) { |
50 | error_setg(errp, "can not find Generic Error Status Block"); | 50 | error_setg(errp, "can not find Generic Error Status Block"); |
51 | -- | 51 | -- |
52 | 2.47.1 | 52 | 2.47.1 | 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 | Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> | 7 | Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> |
8 | Reviewed-by: Igor Mammedov <imammedo@redhat.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 |
14 | index XXXXXXX..XXXXXXX 100644 | 14 | index XXXXXXX..XXXXXXX 100644 |
15 | --- a/docs/specs/acpi_hest_ghes.rst | 15 | --- a/docs/specs/acpi_hest_ghes.rst |
16 | +++ b/docs/specs/acpi_hest_ghes.rst | 16 | +++ b/docs/specs/acpi_hest_ghes.rst |
17 | @@ -XXX,XX +XXX,XX @@ Design Details | 17 | @@ -XXX,XX +XXX,XX @@ Design Details |
18 | (3) The address registers table contains N Error Block Address entries | 18 | (3) The address registers table contains N Error Block Address entries |
19 | and N Read Ack Register entries. The size for each entry is 8-byte. | 19 | and N Read Ack Register entries. The size for each entry is 8-byte. |
20 | The Error Status Data Block table contains N Error Status Data Block | 20 | The Error Status Data Block table contains N Error Status Data Block |
21 | - entries. The size for each entry is 4096(0x1000) bytes. The total size | 21 | - entries. The size for each entry is 4096(0x1000) bytes. The total size |
22 | - for the "etc/hardware_errors" fw_cfg blob is (N * 8 * 2 + N * 4096) bytes. | 22 | - for the "etc/hardware_errors" fw_cfg blob is (N * 8 * 2 + N * 4096) bytes. |
23 | + entries. The size for each entry is defined at the source code as | 23 | + entries. The size for each entry is defined at the source code as |
24 | + ACPI_GHES_MAX_RAW_DATA_LENGTH (currently 1024 bytes). The total size | 24 | + ACPI_GHES_MAX_RAW_DATA_LENGTH (currently 1024 bytes). The total size |
25 | + for the "etc/hardware_errors" fw_cfg blob is | 25 | + for the "etc/hardware_errors" fw_cfg blob is |
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.1 | 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 |