From 18bfba7277b1224a403aec184b0c32360ff1fa3d Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Mon, 22 Nov 2021 11:26:51 +0800 Subject: [PATCH 01/54] qapi/machine.json: Fix incorrect description for die-id In terms of scope, die-id should mean "the die number within socket the CPU belongs to" instead of "the die number within node/board the CPU belongs to". Fix it to avoid confusing the Doc reader. Fixes: 176d2cda0d ("i386/cpu: Consolidate die-id validity in smp context") Signed-off-by: Yanan Wang Reviewed-by: Eric Blake Message-Id: <20211122032651.16064-1-wangyanan55@huawei.com> Signed-off-by: Paolo Bonzini --- ...n-Fix-incorrect-description-for-die-.patch | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 qapi-machine.json-Fix-incorrect-description-for-die-.patch diff --git a/qapi-machine.json-Fix-incorrect-description-for-die-.patch b/qapi-machine.json-Fix-incorrect-description-for-die-.patch new file mode 100644 index 0000000..24d8643 --- /dev/null +++ b/qapi-machine.json-Fix-incorrect-description-for-die-.patch @@ -0,0 +1,35 @@ +From b04e92ed13e49f666f62c8f3daa5746109caf17b Mon Sep 17 00:00:00 2001 +From: Yanan Wang +Date: Mon, 22 Nov 2021 11:26:51 +0800 +Subject: [PATCH] qapi/machine.json: Fix incorrect description for die-id + +In terms of scope, die-id should mean "the die number within +socket the CPU belongs to" instead of "the die number within +node/board the CPU belongs to". Fix it to avoid confusing +the Doc reader. + +Fixes: 176d2cda0d ("i386/cpu: Consolidate die-id validity in smp context") +Signed-off-by: Yanan Wang +Reviewed-by: Eric Blake +Message-Id: <20211122032651.16064-1-wangyanan55@huawei.com> +Signed-off-by: Paolo Bonzini +--- + qapi/machine.json | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/qapi/machine.json b/qapi/machine.json +index 067e3f5378..f1839acf20 100644 +--- a/qapi/machine.json ++++ b/qapi/machine.json +@@ -867,7 +867,7 @@ + # + # @node-id: NUMA node ID the CPU belongs to + # @socket-id: socket number within node/board the CPU belongs to +-# @die-id: die number within node/board the CPU belongs to (Since 4.1) ++# @die-id: die number within socket the CPU belongs to (since 4.1) + # @core-id: core number within die the CPU belongs to + # @thread-id: thread number within core the CPU belongs to + # +-- +2.27.0 + -- Gitee From e606ada14a6498a3d2a0bec64af02a64727b8a37 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Mon, 15 Nov 2021 12:32:09 +0100 Subject: [PATCH 02/54] tests/unit/test-smp-parse: Pass machine type as argument to tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use g_test_add_data_func() instead of g_test_add_func() so we can pass the machine type to the tests (we will soon have different machine types). Reviewed-by: Richard Henderson Reviewed-by: Yanan Wang Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20211216132015.815493-2-philmd@redhat.com> --- ...smp-parse-Pass-machine-type-as-argum.patch | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 tests-unit-test-smp-parse-Pass-machine-type-as-argum.patch diff --git a/tests-unit-test-smp-parse-Pass-machine-type-as-argum.patch b/tests-unit-test-smp-parse-Pass-machine-type-as-argum.patch new file mode 100644 index 0000000..ba381ba --- /dev/null +++ b/tests-unit-test-smp-parse-Pass-machine-type-as-argum.patch @@ -0,0 +1,69 @@ +From d8b2aee4fd6ccd8eb621522b647c392c1dd7955c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Mon, 15 Nov 2021 12:32:09 +0100 +Subject: [PATCH] tests/unit/test-smp-parse: Pass machine type as argument to + tests +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Use g_test_add_data_func() instead of g_test_add_func() so we can +pass the machine type to the tests (we will soon have different +machine types). + +Reviewed-by: Richard Henderson +Reviewed-by: Yanan Wang +Signed-off-by: Philippe Mathieu-Daudé +Message-Id: <20211216132015.815493-2-philmd@redhat.com> +--- + tests/unit/test-smp-parse.c | 18 ++++++++++++------ + 1 file changed, 12 insertions(+), 6 deletions(-) + +diff --git a/tests/unit/test-smp-parse.c b/tests/unit/test-smp-parse.c +index b02450e25a..37c6b4981d 100644 +--- a/tests/unit/test-smp-parse.c ++++ b/tests/unit/test-smp-parse.c +@@ -487,9 +487,10 @@ static void machine_base_class_init(ObjectClass *oc, void *data) + mc->name = g_strdup(SMP_MACHINE_NAME); + } + +-static void test_generic(void) ++static void test_generic(const void *opaque) + { +- Object *obj = object_new(TYPE_MACHINE); ++ const char *machine_type = opaque; ++ Object *obj = object_new(machine_type); + MachineState *ms = MACHINE(obj); + MachineClass *mc = MACHINE_GET_CLASS(obj); + SMPTestData *data = &(SMPTestData){{ }}; +@@ -525,9 +526,10 @@ static void test_generic(void) + object_unref(obj); + } + +-static void test_with_dies(void) ++static void test_with_dies(const void *opaque) + { +- Object *obj = object_new(TYPE_MACHINE); ++ const char *machine_type = opaque; ++ Object *obj = object_new(machine_type); + MachineState *ms = MACHINE(obj); + MachineClass *mc = MACHINE_GET_CLASS(obj); + SMPTestData *data = &(SMPTestData){{ }}; +@@ -599,8 +601,12 @@ int main(int argc, char *argv[]) + + g_test_init(&argc, &argv, NULL); + +- g_test_add_func("/test-smp-parse/generic", test_generic); +- g_test_add_func("/test-smp-parse/with_dies", test_with_dies); ++ g_test_add_data_func("/test-smp-parse/generic", ++ TYPE_MACHINE, ++ test_generic); ++ g_test_add_data_func("/test-smp-parse/with_dies", ++ TYPE_MACHINE, ++ test_with_dies); + + g_test_run(); + +-- +2.27.0 + -- Gitee From 31673dfba129484d35ff6d12c4e1e0d04c6ee8a4 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Mon, 15 Nov 2021 12:35:43 +0100 Subject: [PATCH 03/54] tests/unit/test-smp-parse: Split the 'generic' test in valid / invalid MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Split the 'generic' test in two tests: 'valid' and 'invalid'. This will allow us to remove the hack which modifies the MachineClass internal state. Reviewed-by: Richard Henderson Reviewed-by: Yanan Wang Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20211216132015.815493-3-philmd@redhat.com> --- ...smp-parse-Split-the-generic-test-in-.patch | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 tests-unit-test-smp-parse-Split-the-generic-test-in-.patch diff --git a/tests-unit-test-smp-parse-Split-the-generic-test-in-.patch b/tests-unit-test-smp-parse-Split-the-generic-test-in-.patch new file mode 100644 index 0000000..33dea58 --- /dev/null +++ b/tests-unit-test-smp-parse-Split-the-generic-test-in-.patch @@ -0,0 +1,71 @@ +From fad259cf9996dbc4001cb94ec3c846d649401027 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Mon, 15 Nov 2021 12:35:43 +0100 +Subject: [PATCH] tests/unit/test-smp-parse: Split the 'generic' test in valid + / invalid +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Split the 'generic' test in two tests: 'valid' and 'invalid'. +This will allow us to remove the hack which modifies the +MachineClass internal state. + +Reviewed-by: Richard Henderson +Reviewed-by: Yanan Wang +Signed-off-by: Philippe Mathieu-Daudé +Message-Id: <20211216132015.815493-3-philmd@redhat.com> +--- + tests/unit/test-smp-parse.c | 21 ++++++++++++++++++--- + 1 file changed, 18 insertions(+), 3 deletions(-) + +diff --git a/tests/unit/test-smp-parse.c b/tests/unit/test-smp-parse.c +index 37c6b4981d..425ed6b6b9 100644 +--- a/tests/unit/test-smp-parse.c ++++ b/tests/unit/test-smp-parse.c +@@ -487,7 +487,7 @@ static void machine_base_class_init(ObjectClass *oc, void *data) + mc->name = g_strdup(SMP_MACHINE_NAME); + } + +-static void test_generic(const void *opaque) ++static void test_generic_valid(const void *opaque) + { + const char *machine_type = opaque; + Object *obj = object_new(machine_type); +@@ -508,6 +508,18 @@ static void test_generic(const void *opaque) + smp_parse_test(ms, data, true); + } + ++ object_unref(obj); ++} ++ ++static void test_generic_invalid(const void *opaque) ++{ ++ const char *machine_type = opaque; ++ Object *obj = object_new(machine_type); ++ MachineState *ms = MACHINE(obj); ++ MachineClass *mc = MACHINE_GET_CLASS(obj); ++ SMPTestData *data = &(SMPTestData){}; ++ int i; ++ + /* Force invalid min CPUs and max CPUs */ + mc->min_cpus = 2; + mc->max_cpus = 511; +@@ -601,9 +613,12 @@ int main(int argc, char *argv[]) + + g_test_init(&argc, &argv, NULL); + +- g_test_add_data_func("/test-smp-parse/generic", ++ g_test_add_data_func("/test-smp-parse/generic/valid", ++ TYPE_MACHINE, ++ test_generic_valid); ++ g_test_add_data_func("/test-smp-parse/generic/invalid", + TYPE_MACHINE, +- test_generic); ++ test_generic_invalid); + g_test_add_data_func("/test-smp-parse/with_dies", + TYPE_MACHINE, + test_with_dies); +-- +2.27.0 + -- Gitee From ec5fc3e111bf2da88666233aa30a0907849da215 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Mon, 15 Nov 2021 12:39:12 +0100 Subject: [PATCH 04/54] tests/unit/test-smp-parse: Add 'smp-with-dies' machine type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoid modifying the MachineClass internals by adding the 'smp-with-dies' machine, which inherits from TYPE_MACHINE. Reviewed-by: Richard Henderson Reviewed-by: Yanan Wang Tested-by: Yanan Wang Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20211216132015.815493-4-philmd@redhat.com> --- ...smp-parse-Add-smp-with-dies-machine-.patch | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 tests-unit-test-smp-parse-Add-smp-with-dies-machine-.patch diff --git a/tests-unit-test-smp-parse-Add-smp-with-dies-machine-.patch b/tests-unit-test-smp-parse-Add-smp-with-dies-machine-.patch new file mode 100644 index 0000000..3422a49 --- /dev/null +++ b/tests-unit-test-smp-parse-Add-smp-with-dies-machine-.patch @@ -0,0 +1,84 @@ +From 4981e75623db6ca681d13719ffcf61b0cfac3edc Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Mon, 15 Nov 2021 12:39:12 +0100 +Subject: [PATCH] tests/unit/test-smp-parse: Add 'smp-with-dies' machine type +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Avoid modifying the MachineClass internals by adding the +'smp-with-dies' machine, which inherits from TYPE_MACHINE. + +Reviewed-by: Richard Henderson +Reviewed-by: Yanan Wang +Tested-by: Yanan Wang +Signed-off-by: Philippe Mathieu-Daudé +Message-Id: <20211216132015.815493-4-philmd@redhat.com> +--- + tests/unit/test-smp-parse.c | 22 +++++++++++++++------- + 1 file changed, 15 insertions(+), 7 deletions(-) + +diff --git a/tests/unit/test-smp-parse.c b/tests/unit/test-smp-parse.c +index 425ed6b6b9..f66cf7bb59 100644 +--- a/tests/unit/test-smp-parse.c ++++ b/tests/unit/test-smp-parse.c +@@ -487,6 +487,16 @@ static void machine_base_class_init(ObjectClass *oc, void *data) + mc->name = g_strdup(SMP_MACHINE_NAME); + } + ++static void machine_with_dies_class_init(ObjectClass *oc, void *data) ++{ ++ MachineClass *mc = MACHINE_CLASS(oc); ++ ++ mc->min_cpus = MIN_CPUS; ++ mc->max_cpus = MAX_CPUS; ++ ++ mc->smp_props.dies_supported = true; ++} ++ + static void test_generic_valid(const void *opaque) + { + const char *machine_type = opaque; +@@ -548,9 +558,6 @@ static void test_with_dies(const void *opaque) + unsigned int num_dies = 2; + int i; + +- /* Force the SMP compat properties */ +- mc->smp_props.dies_supported = true; +- + for (i = 0; i < ARRAY_SIZE(data_generic_valid); i++) { + *data = data_generic_valid[i]; + unsupported_params_init(mc, data); +@@ -588,9 +595,6 @@ static void test_with_dies(const void *opaque) + smp_parse_test(ms, data, false); + } + +- /* Restore the SMP compat properties */ +- mc->smp_props.dies_supported = false; +- + object_unref(obj); + } + +@@ -602,6 +606,10 @@ static const TypeInfo smp_machine_types[] = { + .class_init = machine_base_class_init, + .class_size = sizeof(MachineClass), + .instance_size = sizeof(MachineState), ++ }, { ++ .name = MACHINE_TYPE_NAME("smp-with-dies"), ++ .parent = TYPE_MACHINE, ++ .class_init = machine_with_dies_class_init, + } + }; + +@@ -620,7 +628,7 @@ int main(int argc, char *argv[]) + TYPE_MACHINE, + test_generic_invalid); + g_test_add_data_func("/test-smp-parse/with_dies", +- TYPE_MACHINE, ++ MACHINE_TYPE_NAME("smp-with-dies"), + test_with_dies); + + g_test_run(); +-- +2.27.0 + -- Gitee From 0b4b06afe409ad074cc41c2f2b5f273faeb2c6ab Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Mon, 15 Nov 2021 15:44:07 +0100 Subject: [PATCH 05/54] tests/unit/test-smp-parse: Add 'smp-generic-invalid' machine type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoid modifying the MachineClass internals by adding the 'smp-generic-invalid' machine, which inherits from TYPE_MACHINE. Reviewed-by: Richard Henderson Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Yanan Wang Message-Id: <20211216132015.815493-5-philmd@redhat.com> --- ...smp-parse-Add-smp-generic-invalid-ma.patch | 87 +++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 tests-unit-test-smp-parse-Add-smp-generic-invalid-ma.patch diff --git a/tests-unit-test-smp-parse-Add-smp-generic-invalid-ma.patch b/tests-unit-test-smp-parse-Add-smp-generic-invalid-ma.patch new file mode 100644 index 0000000..52fa8a1 --- /dev/null +++ b/tests-unit-test-smp-parse-Add-smp-generic-invalid-ma.patch @@ -0,0 +1,87 @@ +From 9a98659dcb37c81e69f54d8f6cbe5116ceba5a36 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Mon, 15 Nov 2021 15:44:07 +0100 +Subject: [PATCH] tests/unit/test-smp-parse: Add 'smp-generic-invalid' machine + type +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Avoid modifying the MachineClass internals by adding the +'smp-generic-invalid' machine, which inherits from TYPE_MACHINE. + +Reviewed-by: Richard Henderson +Signed-off-by: Philippe Mathieu-Daudé +Reviewed-by: Yanan Wang +Message-Id: <20211216132015.815493-5-philmd@redhat.com> +--- + tests/unit/test-smp-parse.c | 25 ++++++++++++++++--------- + 1 file changed, 16 insertions(+), 9 deletions(-) + +diff --git a/tests/unit/test-smp-parse.c b/tests/unit/test-smp-parse.c +index f66cf7bb59..47e11089e2 100644 +--- a/tests/unit/test-smp-parse.c ++++ b/tests/unit/test-smp-parse.c +@@ -487,6 +487,17 @@ static void machine_base_class_init(ObjectClass *oc, void *data) + mc->name = g_strdup(SMP_MACHINE_NAME); + } + ++static void machine_generic_invalid_class_init(ObjectClass *oc, void *data) ++{ ++ MachineClass *mc = MACHINE_CLASS(oc); ++ ++ /* Force invalid min CPUs and max CPUs */ ++ mc->min_cpus = 2; ++ mc->max_cpus = 511; ++ ++ mc->smp_props.dies_supported = false; ++} ++ + static void machine_with_dies_class_init(ObjectClass *oc, void *data) + { + MachineClass *mc = MACHINE_CLASS(oc); +@@ -530,10 +541,6 @@ static void test_generic_invalid(const void *opaque) + SMPTestData *data = &(SMPTestData){}; + int i; + +- /* Force invalid min CPUs and max CPUs */ +- mc->min_cpus = 2; +- mc->max_cpus = 511; +- + for (i = 0; i < ARRAY_SIZE(data_generic_invalid); i++) { + *data = data_generic_invalid[i]; + unsupported_params_init(mc, data); +@@ -541,10 +548,6 @@ static void test_generic_invalid(const void *opaque) + smp_parse_test(ms, data, false); + } + +- /* Reset the supported min CPUs and max CPUs */ +- mc->min_cpus = MIN_CPUS; +- mc->max_cpus = MAX_CPUS; +- + object_unref(obj); + } + +@@ -606,6 +609,10 @@ static const TypeInfo smp_machine_types[] = { + .class_init = machine_base_class_init, + .class_size = sizeof(MachineClass), + .instance_size = sizeof(MachineState), ++ }, { ++ .name = MACHINE_TYPE_NAME("smp-generic-invalid"), ++ .parent = TYPE_MACHINE, ++ .class_init = machine_generic_invalid_class_init, + }, { + .name = MACHINE_TYPE_NAME("smp-with-dies"), + .parent = TYPE_MACHINE, +@@ -625,7 +632,7 @@ int main(int argc, char *argv[]) + TYPE_MACHINE, + test_generic_valid); + g_test_add_data_func("/test-smp-parse/generic/invalid", +- TYPE_MACHINE, ++ MACHINE_TYPE_NAME("smp-generic-invalid"), + test_generic_invalid); + g_test_add_data_func("/test-smp-parse/with_dies", + MACHINE_TYPE_NAME("smp-with-dies"), +-- +2.27.0 + -- Gitee From 6d83e9ca872b16190c487d0d2f7073ae29970296 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Mon, 15 Nov 2021 15:49:59 +0100 Subject: [PATCH 06/54] tests/unit/test-smp-parse: Add 'smp-generic-valid' machine type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Keep the common TYPE_MACHINE class initialization in machine_base_class_init(), make it abstract, and move the non-common code to a new class: "smp-generic-valid". Reviewed-by: Richard Henderson Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Yanan Wang Message-Id: <20211216132015.815493-6-philmd@redhat.com> --- ...smp-parse-Add-smp-generic-valid-mach.patch | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 tests-unit-test-smp-parse-Add-smp-generic-valid-mach.patch diff --git a/tests-unit-test-smp-parse-Add-smp-generic-valid-mach.patch b/tests-unit-test-smp-parse-Add-smp-generic-valid-mach.patch new file mode 100644 index 0000000..07ee180 --- /dev/null +++ b/tests-unit-test-smp-parse-Add-smp-generic-valid-mach.patch @@ -0,0 +1,75 @@ +From c33c7dd51eebf5ae7b7ece1e829b0a5ffdcebfe1 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Mon, 15 Nov 2021 15:49:59 +0100 +Subject: [PATCH] tests/unit/test-smp-parse: Add 'smp-generic-valid' machine + type +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Keep the common TYPE_MACHINE class initialization in +machine_base_class_init(), make it abstract, and move +the non-common code to a new class: "smp-generic-valid". + +Reviewed-by: Richard Henderson +Signed-off-by: Philippe Mathieu-Daudé +Reviewed-by: Yanan Wang +Message-Id: <20211216132015.815493-6-philmd@redhat.com> +--- + tests/unit/test-smp-parse.c | 19 +++++++++++++++---- + 1 file changed, 15 insertions(+), 4 deletions(-) + +diff --git a/tests/unit/test-smp-parse.c b/tests/unit/test-smp-parse.c +index 47e11089e2..b20bf2c235 100644 +--- a/tests/unit/test-smp-parse.c ++++ b/tests/unit/test-smp-parse.c +@@ -478,13 +478,19 @@ static void machine_base_class_init(ObjectClass *oc, void *data) + { + MachineClass *mc = MACHINE_CLASS(oc); + ++ mc->smp_props.prefer_sockets = true; ++ ++ mc->name = g_strdup(SMP_MACHINE_NAME); ++} ++ ++static void machine_generic_valid_class_init(ObjectClass *oc, void *data) ++{ ++ MachineClass *mc = MACHINE_CLASS(oc); ++ + mc->min_cpus = MIN_CPUS; + mc->max_cpus = MAX_CPUS; + +- mc->smp_props.prefer_sockets = true; + mc->smp_props.dies_supported = false; +- +- mc->name = g_strdup(SMP_MACHINE_NAME); + } + + static void machine_generic_invalid_class_init(ObjectClass *oc, void *data) +@@ -606,9 +612,14 @@ static const TypeInfo smp_machine_types[] = { + { + .name = TYPE_MACHINE, + .parent = TYPE_OBJECT, ++ .abstract = true, + .class_init = machine_base_class_init, + .class_size = sizeof(MachineClass), + .instance_size = sizeof(MachineState), ++ }, { ++ .name = MACHINE_TYPE_NAME("smp-generic-valid"), ++ .parent = TYPE_MACHINE, ++ .class_init = machine_generic_valid_class_init, + }, { + .name = MACHINE_TYPE_NAME("smp-generic-invalid"), + .parent = TYPE_MACHINE, +@@ -629,7 +640,7 @@ int main(int argc, char *argv[]) + g_test_init(&argc, &argv, NULL); + + g_test_add_data_func("/test-smp-parse/generic/valid", +- TYPE_MACHINE, ++ MACHINE_TYPE_NAME("smp-generic-valid"), + test_generic_valid); + g_test_add_data_func("/test-smp-parse/generic/invalid", + MACHINE_TYPE_NAME("smp-generic-invalid"), +-- +2.27.0 + -- Gitee From 022328cda23f4b0b2fd5d37eca1713e3cc1c2906 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Thu, 11 Nov 2021 08:58:40 +0100 Subject: [PATCH 07/54] tests/unit/test-smp-parse: Simplify pointer to compound literal use MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We can simply use a local variable (and pass its pointer) instead of a pointer to a compound literal. Reviewed-by: Andrew Jones Reviewed-by: Richard Henderson Reviewed-by: Yanan Wang Tested-by: Yanan Wang Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20211216132015.815493-7-philmd@redhat.com> --- ...smp-parse-Simplify-pointer-to-compou.patch | 143 ++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 tests-unit-test-smp-parse-Simplify-pointer-to-compou.patch diff --git a/tests-unit-test-smp-parse-Simplify-pointer-to-compou.patch b/tests-unit-test-smp-parse-Simplify-pointer-to-compou.patch new file mode 100644 index 0000000..26da0c5 --- /dev/null +++ b/tests-unit-test-smp-parse-Simplify-pointer-to-compou.patch @@ -0,0 +1,143 @@ +From 964965721bbed1941bf77e5a748efc1274b7c289 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Thu, 11 Nov 2021 08:58:40 +0100 +Subject: [PATCH] tests/unit/test-smp-parse: Simplify pointer to compound + literal use +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +We can simply use a local variable (and pass its pointer) instead +of a pointer to a compound literal. + +Reviewed-by: Andrew Jones +Reviewed-by: Richard Henderson +Reviewed-by: Yanan Wang +Tested-by: Yanan Wang +Signed-off-by: Philippe Mathieu-Daudé +Message-Id: <20211216132015.815493-7-philmd@redhat.com> +--- + tests/unit/test-smp-parse.c | 66 ++++++++++++++++++------------------- + 1 file changed, 33 insertions(+), 33 deletions(-) + +diff --git a/tests/unit/test-smp-parse.c b/tests/unit/test-smp-parse.c +index b20bf2c235..395929b66c 100644 +--- a/tests/unit/test-smp-parse.c ++++ b/tests/unit/test-smp-parse.c +@@ -520,19 +520,19 @@ static void test_generic_valid(const void *opaque) + Object *obj = object_new(machine_type); + MachineState *ms = MACHINE(obj); + MachineClass *mc = MACHINE_GET_CLASS(obj); +- SMPTestData *data = &(SMPTestData){{ }}; ++ SMPTestData data = {}; + int i; + + for (i = 0; i < ARRAY_SIZE(data_generic_valid); i++) { +- *data = data_generic_valid[i]; +- unsupported_params_init(mc, data); ++ data = data_generic_valid[i]; ++ unsupported_params_init(mc, &data); + +- smp_parse_test(ms, data, true); ++ smp_parse_test(ms, &data, true); + + /* Unsupported parameters can be provided with their values as 1 */ +- data->config.has_dies = true; +- data->config.dies = 1; +- smp_parse_test(ms, data, true); ++ data.config.has_dies = true; ++ data.config.dies = 1; ++ smp_parse_test(ms, &data, true); + } + + object_unref(obj); +@@ -544,14 +544,14 @@ static void test_generic_invalid(const void *opaque) + Object *obj = object_new(machine_type); + MachineState *ms = MACHINE(obj); + MachineClass *mc = MACHINE_GET_CLASS(obj); +- SMPTestData *data = &(SMPTestData){}; ++ SMPTestData data = {}; + int i; + + for (i = 0; i < ARRAY_SIZE(data_generic_invalid); i++) { +- *data = data_generic_invalid[i]; +- unsupported_params_init(mc, data); ++ data = data_generic_invalid[i]; ++ unsupported_params_init(mc, &data); + +- smp_parse_test(ms, data, false); ++ smp_parse_test(ms, &data, false); + } + + object_unref(obj); +@@ -563,45 +563,45 @@ static void test_with_dies(const void *opaque) + Object *obj = object_new(machine_type); + MachineState *ms = MACHINE(obj); + MachineClass *mc = MACHINE_GET_CLASS(obj); +- SMPTestData *data = &(SMPTestData){{ }}; ++ SMPTestData data = {}; + unsigned int num_dies = 2; + int i; + + for (i = 0; i < ARRAY_SIZE(data_generic_valid); i++) { +- *data = data_generic_valid[i]; +- unsupported_params_init(mc, data); ++ data = data_generic_valid[i]; ++ unsupported_params_init(mc, &data); + + /* when dies parameter is omitted, it will be set as 1 */ +- data->expect_prefer_sockets.dies = 1; +- data->expect_prefer_cores.dies = 1; ++ data.expect_prefer_sockets.dies = 1; ++ data.expect_prefer_cores.dies = 1; + +- smp_parse_test(ms, data, true); ++ smp_parse_test(ms, &data, true); + + /* when dies parameter is specified */ +- data->config.has_dies = true; +- data->config.dies = num_dies; +- if (data->config.has_cpus) { +- data->config.cpus *= num_dies; ++ data.config.has_dies = true; ++ data.config.dies = num_dies; ++ if (data.config.has_cpus) { ++ data.config.cpus *= num_dies; + } +- if (data->config.has_maxcpus) { +- data->config.maxcpus *= num_dies; ++ if (data.config.has_maxcpus) { ++ data.config.maxcpus *= num_dies; + } + +- data->expect_prefer_sockets.dies = num_dies; +- data->expect_prefer_sockets.cpus *= num_dies; +- data->expect_prefer_sockets.max_cpus *= num_dies; +- data->expect_prefer_cores.dies = num_dies; +- data->expect_prefer_cores.cpus *= num_dies; +- data->expect_prefer_cores.max_cpus *= num_dies; ++ data.expect_prefer_sockets.dies = num_dies; ++ data.expect_prefer_sockets.cpus *= num_dies; ++ data.expect_prefer_sockets.max_cpus *= num_dies; ++ data.expect_prefer_cores.dies = num_dies; ++ data.expect_prefer_cores.cpus *= num_dies; ++ data.expect_prefer_cores.max_cpus *= num_dies; + +- smp_parse_test(ms, data, true); ++ smp_parse_test(ms, &data, true); + } + + for (i = 0; i < ARRAY_SIZE(data_with_dies_invalid); i++) { +- *data = data_with_dies_invalid[i]; +- unsupported_params_init(mc, data); ++ data = data_with_dies_invalid[i]; ++ unsupported_params_init(mc, &data); + +- smp_parse_test(ms, data, false); ++ smp_parse_test(ms, &data, false); + } + + object_unref(obj); +-- +2.27.0 + -- Gitee From b9a559307df468e6c21c66d6f1ea8e8305d7e8a5 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Thu, 11 Nov 2021 10:23:06 +0100 Subject: [PATCH 08/54] tests/unit/test-smp-parse: Constify some pointer/struct MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Declare structures const when we don't need to modify them at runtime. Reviewed-by: Andrew Jones Reviewed-by: Richard Henderson Reviewed-by: Yanan Wang Tested-by: Yanan Wang Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20211216132015.815493-8-philmd@redhat.com> --- ...smp-parse-Constify-some-pointer-stru.patch | 82 +++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 tests-unit-test-smp-parse-Constify-some-pointer-stru.patch diff --git a/tests-unit-test-smp-parse-Constify-some-pointer-stru.patch b/tests-unit-test-smp-parse-Constify-some-pointer-stru.patch new file mode 100644 index 0000000..62b6aab --- /dev/null +++ b/tests-unit-test-smp-parse-Constify-some-pointer-stru.patch @@ -0,0 +1,82 @@ +From bcf4b802bd8971c0c5a255e606b15900cd47c6b6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Thu, 11 Nov 2021 10:23:06 +0100 +Subject: [PATCH] tests/unit/test-smp-parse: Constify some pointer/struct +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Declare structures const when we don't need to modify +them at runtime. + +Reviewed-by: Andrew Jones +Reviewed-by: Richard Henderson +Reviewed-by: Yanan Wang +Tested-by: Yanan Wang +Signed-off-by: Philippe Mathieu-Daudé +Message-Id: <20211216132015.815493-8-philmd@redhat.com> +--- + tests/unit/test-smp-parse.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/tests/unit/test-smp-parse.c b/tests/unit/test-smp-parse.c +index 395929b66c..0f98c9509e 100644 +--- a/tests/unit/test-smp-parse.c ++++ b/tests/unit/test-smp-parse.c +@@ -83,7 +83,7 @@ typedef struct SMPTestData { + * then test the automatic calculation algorithm of the missing + * values in the parser. + */ +-static struct SMPTestData data_generic_valid[] = { ++static const struct SMPTestData data_generic_valid[] = { + { + /* config: no configuration provided + * expect: cpus=1,sockets=1,cores=1,threads=1,maxcpus=1 */ +@@ -285,7 +285,7 @@ static struct SMPTestData data_generic_valid[] = { + }, + }; + +-static struct SMPTestData data_generic_invalid[] = { ++static const struct SMPTestData data_generic_invalid[] = { + { + /* config: -smp 2,dies=2 */ + .config = SMP_CONFIG_WITH_DIES(T, 2, F, 0, T, 2, F, 0, F, 0, F, 0), +@@ -319,7 +319,7 @@ static struct SMPTestData data_generic_invalid[] = { + }, + }; + +-static struct SMPTestData data_with_dies_invalid[] = { ++static const struct SMPTestData data_with_dies_invalid[] = { + { + /* config: -smp 16,sockets=2,dies=2,cores=4,threads=2,maxcpus=16 */ + .config = SMP_CONFIG_WITH_DIES(T, 16, T, 2, T, 2, T, 4, T, 2, T, 16), +@@ -356,7 +356,7 @@ static char *smp_config_to_string(SMPConfiguration *config) + config->has_maxcpus ? "true" : "false", config->maxcpus); + } + +-static char *cpu_topology_to_string(CpuTopology *topo) ++static char *cpu_topology_to_string(const CpuTopology *topo) + { + return g_strdup_printf( + "(CpuTopology) {\n" +@@ -372,7 +372,7 @@ static char *cpu_topology_to_string(CpuTopology *topo) + } + + static void check_parse(MachineState *ms, SMPConfiguration *config, +- CpuTopology *expect_topo, const char *expect_err, ++ const CpuTopology *expect_topo, const char *expect_err, + bool is_valid) + { + g_autofree char *config_str = smp_config_to_string(config); +@@ -466,7 +466,7 @@ static void smp_parse_test(MachineState *ms, SMPTestData *data, bool is_valid) + } + + /* The parsed results of the unsupported parameters should be 1 */ +-static void unsupported_params_init(MachineClass *mc, SMPTestData *data) ++static void unsupported_params_init(const MachineClass *mc, SMPTestData *data) + { + if (!mc->smp_props.dies_supported) { + data->expect_prefer_sockets.dies = 1; +-- +2.27.0 + -- Gitee From e04938df751e344967fa62c4d58ffdd0babc8834 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Thu, 11 Nov 2021 10:21:23 +0100 Subject: [PATCH 09/54] hw/core: Rename smp_parse() -> machine_parse_smp_config() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All methods related to MachineState are prefixed with "machine_". smp_parse() does not need to be an exception. Rename it and const'ify the SMPConfiguration argument, since it doesn't need to be modified. Reviewed-by: Andrew Jones Reviewed-by: Richard Henderson Reviewed-by: Yanan Wang Tested-by: Yanan Wang Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20211216132015.815493-9-philmd@redhat.com> --- ...e-smp_parse-machine_parse_smp_config.patch | 113 ++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 hw-core-Rename-smp_parse-machine_parse_smp_config.patch diff --git a/hw-core-Rename-smp_parse-machine_parse_smp_config.patch b/hw-core-Rename-smp_parse-machine_parse_smp_config.patch new file mode 100644 index 0000000..4363db3 --- /dev/null +++ b/hw-core-Rename-smp_parse-machine_parse_smp_config.patch @@ -0,0 +1,113 @@ +From 2ce1daae407033e689a559b7346523b18651ee0a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Thu, 11 Nov 2021 10:21:23 +0100 +Subject: [PATCH] hw/core: Rename smp_parse() -> machine_parse_smp_config() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +All methods related to MachineState are prefixed with "machine_". +smp_parse() does not need to be an exception. Rename it and +const'ify the SMPConfiguration argument, since it doesn't need +to be modified. + +Reviewed-by: Andrew Jones +Reviewed-by: Richard Henderson +Reviewed-by: Yanan Wang +Tested-by: Yanan Wang +Signed-off-by: Philippe Mathieu-Daudé +Message-Id: <20211216132015.815493-9-philmd@redhat.com> +--- + hw/core/machine-smp.c | 6 ++++-- + hw/core/machine.c | 2 +- + include/hw/boards.h | 3 ++- + tests/unit/test-smp-parse.c | 8 ++++---- + 4 files changed, 11 insertions(+), 8 deletions(-) + +diff --git a/hw/core/machine-smp.c b/hw/core/machine-smp.c +index 116a0cbbfa..2cbfd57429 100644 +--- a/hw/core/machine-smp.c ++++ b/hw/core/machine-smp.c +@@ -44,7 +44,8 @@ static char *cpu_hierarchy_to_string(MachineState *ms) + } + + /* +- * smp_parse - Generic function used to parse the given SMP configuration ++ * machine_parse_smp_config: Generic function used to parse the given ++ * SMP configuration + * + * Any missing parameter in "cpus/maxcpus/sockets/cores/threads" will be + * automatically computed based on the provided ones. +@@ -63,7 +64,8 @@ static char *cpu_hierarchy_to_string(MachineState *ms) + * introduced topology members which are likely to be target specific should + * be directly set as 1 if they are omitted (e.g. dies for PC since 4.1). + */ +-void smp_parse(MachineState *ms, SMPConfiguration *config, Error **errp) ++void machine_parse_smp_config(MachineState *ms, ++ const SMPConfiguration *config, Error **errp) + { + MachineClass *mc = MACHINE_GET_CLASS(ms); + unsigned cpus = config->has_cpus ? config->cpus : 0; +diff --git a/hw/core/machine.c b/hw/core/machine.c +index 53a99abc56..3993c534b9 100644 +--- a/hw/core/machine.c ++++ b/hw/core/machine.c +@@ -761,7 +761,7 @@ static void machine_set_smp(Object *obj, Visitor *v, const char *name, + return; + } + +- smp_parse(ms, config, errp); ++ machine_parse_smp_config(ms, config, errp); + } + + static void machine_class_init(ObjectClass *oc, void *data) +diff --git a/include/hw/boards.h b/include/hw/boards.h +index 9c1c190104..7597cec440 100644 +--- a/include/hw/boards.h ++++ b/include/hw/boards.h +@@ -34,7 +34,8 @@ HotpluggableCPUList *machine_query_hotpluggable_cpus(MachineState *machine); + void machine_set_cpu_numa_node(MachineState *machine, + const CpuInstanceProperties *props, + Error **errp); +-void smp_parse(MachineState *ms, SMPConfiguration *config, Error **errp); ++void machine_parse_smp_config(MachineState *ms, ++ const SMPConfiguration *config, Error **errp); + + /** + * machine_class_allow_dynamic_sysbus_dev: Add type to list of valid devices +diff --git a/tests/unit/test-smp-parse.c b/tests/unit/test-smp-parse.c +index 0f98c9509e..b6df8137fc 100644 +--- a/tests/unit/test-smp-parse.c ++++ b/tests/unit/test-smp-parse.c +@@ -337,7 +337,7 @@ static const struct SMPTestData data_with_dies_invalid[] = { + }, + }; + +-static char *smp_config_to_string(SMPConfiguration *config) ++static char *smp_config_to_string(const SMPConfiguration *config) + { + return g_strdup_printf( + "(SMPConfiguration) {\n" +@@ -371,7 +371,7 @@ static char *cpu_topology_to_string(const CpuTopology *topo) + topo->cores, topo->threads, topo->max_cpus); + } + +-static void check_parse(MachineState *ms, SMPConfiguration *config, ++static void check_parse(MachineState *ms, const SMPConfiguration *config, + const CpuTopology *expect_topo, const char *expect_err, + bool is_valid) + { +@@ -380,8 +380,8 @@ static void check_parse(MachineState *ms, SMPConfiguration *config, + g_autofree char *output_topo_str = NULL; + Error *err = NULL; + +- /* call the generic parser smp_parse() */ +- smp_parse(ms, config, &err); ++ /* call the generic parser */ ++ machine_parse_smp_config(ms, config, &err); + + output_topo_str = cpu_topology_to_string(&ms->smp); + +-- +2.27.0 + -- Gitee From 1284ff3440c6f9c00d495359f92b83a4ad3e3e8b Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Tue, 28 Dec 2021 17:22:08 +0800 Subject: [PATCH 10/54] qemu-options: Improve readability of SMP related Docs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We have a description in qemu-options.hx for each CPU topology parameter to explain what it exactly means, and also an extra declaration for the target-specific one, e.g. "for PC only" when describing "dies", and "for PC, it's on one die" when describing "cores". Now we are going to introduce one more non-generic parameter "clusters", it will make the Doc less readable and if we still continue to use the legacy way to describe it. So let's at first make two tweaks of the Docs to improve the readability and also scalability: 1) In the -help text: Delete the extra specific declaration and describe each topology parameter level by level. Then add a note to declare that different machines may support different subsets and the actual meaning of the supported parameters will vary accordingly. 2) In the rST text: List all the sub-hierarchies currently supported in QEMU, and correspondingly give an example of -smp configuration for each of them. Signed-off-by: Yanan Wang Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20211228092221.21068-2-wangyanan55@huawei.com> Signed-off-by: Philippe Mathieu-Daudé --- ...rove-readability-of-SMP-related-Docs.patch | 146 ++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 qemu-options-Improve-readability-of-SMP-related-Docs.patch diff --git a/qemu-options-Improve-readability-of-SMP-related-Docs.patch b/qemu-options-Improve-readability-of-SMP-related-Docs.patch new file mode 100644 index 0000000..875624a --- /dev/null +++ b/qemu-options-Improve-readability-of-SMP-related-Docs.patch @@ -0,0 +1,146 @@ +From 07991b049fc9ebdb62c311eda1535ad4831625e5 Mon Sep 17 00:00:00 2001 +From: Yanan Wang +Date: Tue, 28 Dec 2021 17:22:08 +0800 +Subject: [PATCH] qemu-options: Improve readability of SMP related Docs +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +We have a description in qemu-options.hx for each CPU topology +parameter to explain what it exactly means, and also an extra +declaration for the target-specific one, e.g. "for PC only" +when describing "dies", and "for PC, it's on one die" when +describing "cores". + +Now we are going to introduce one more non-generic parameter +"clusters", it will make the Doc less readable and if we still +continue to use the legacy way to describe it. + +So let's at first make two tweaks of the Docs to improve the +readability and also scalability: +1) In the -help text: Delete the extra specific declaration and + describe each topology parameter level by level. Then add a + note to declare that different machines may support different + subsets and the actual meaning of the supported parameters + will vary accordingly. +2) In the rST text: List all the sub-hierarchies currently + supported in QEMU, and correspondingly give an example of + -smp configuration for each of them. + +Signed-off-by: Yanan Wang +Reviewed-by: Philippe Mathieu-Daudé +Message-Id: <20211228092221.21068-2-wangyanan55@huawei.com> +Signed-off-by: Philippe Mathieu-Daudé +--- + qemu-options.hx | 76 ++++++++++++++++++++++++++++++++++++++----------- + 1 file changed, 59 insertions(+), 17 deletions(-) + +diff --git a/qemu-options.hx b/qemu-options.hx +index ae2c6dbbfc..7a59db7764 100644 +--- a/qemu-options.hx ++++ b/qemu-options.hx +@@ -207,14 +207,26 @@ ERST + + DEF("smp", HAS_ARG, QEMU_OPTION_smp, + "-smp [[cpus=]n][,maxcpus=maxcpus][,sockets=sockets][,dies=dies][,cores=cores][,threads=threads]\n" +- " set the number of CPUs to 'n' [default=1]\n" ++ " set the number of initial CPUs to 'n' [default=1]\n" + " maxcpus= maximum number of total CPUs, including\n" + " offline CPUs for hotplug, etc\n" +- " sockets= number of discrete sockets in the system\n" +- " dies= number of CPU dies on one socket (for PC only)\n" +- " cores= number of CPU cores on one socket (for PC, it's on one die)\n" +- " threads= number of threads on one CPU core\n", +- QEMU_ARCH_ALL) ++ " sockets= number of sockets on the machine board\n" ++ " dies= number of dies in one socket\n" ++ " cores= number of cores in one die\n" ++ " threads= number of threads in one core\n" ++ "Note: Different machines may have different subsets of the CPU topology\n" ++ " parameters supported, so the actual meaning of the supported parameters\n" ++ " will vary accordingly. For example, for a machine type that supports a\n" ++ " three-level CPU hierarchy of sockets/cores/threads, the parameters will\n" ++ " sequentially mean as below:\n" ++ " sockets means the number of sockets on the machine board\n" ++ " cores means the number of cores in one socket\n" ++ " threads means the number of threads in one core\n" ++ " For a particular machine type board, an expected CPU topology hierarchy\n" ++ " can be defined through the supported sub-option. Unsupported parameters\n" ++ " can also be provided in addition to the sub-option, but their values\n" ++ " must be set as 1 in the purpose of correct parsing.\n", ++ QEMU_ARCH_ALL) + SRST + ``-smp [[cpus=]n][,maxcpus=maxcpus][,sockets=sockets][,dies=dies][,cores=cores][,threads=threads]`` + Simulate a SMP system with '\ ``n``\ ' CPUs initially present on +@@ -225,27 +237,57 @@ SRST + initial CPU count will match the maximum number. When only one of them + is given then the omitted one will be set to its counterpart's value. + Both parameters may be specified, but the maximum number of CPUs must +- be equal to or greater than the initial CPU count. Both parameters are +- subject to an upper limit that is determined by the specific machine +- type chosen. +- +- To control reporting of CPU topology information, the number of sockets, +- dies per socket, cores per die, and threads per core can be specified. +- The sum `` sockets * cores * dies * threads `` must be equal to the +- maximum CPU count. CPU targets may only support a subset of the topology +- parameters. Where a CPU target does not support use of a particular +- topology parameter, its value should be assumed to be 1 for the purpose +- of computing the CPU maximum count. ++ be equal to or greater than the initial CPU count. Product of the ++ CPU topology hierarchy must be equal to the maximum number of CPUs. ++ Both parameters are subject to an upper limit that is determined by ++ the specific machine type chosen. ++ ++ To control reporting of CPU topology information, values of the topology ++ parameters can be specified. Machines may only support a subset of the ++ parameters and different machines may have different subsets supported ++ which vary depending on capacity of the corresponding CPU targets. So ++ for a particular machine type board, an expected topology hierarchy can ++ be defined through the supported sub-option. Unsupported parameters can ++ also be provided in addition to the sub-option, but their values must be ++ set as 1 in the purpose of correct parsing. + + Either the initial CPU count, or at least one of the topology parameters + must be specified. The specified parameters must be greater than zero, + explicit configuration like "cpus=0" is not allowed. Values for any + omitted parameters will be computed from those which are given. ++ ++ For example, the following sub-option defines a CPU topology hierarchy ++ (2 sockets totally on the machine, 2 cores per socket, 2 threads per ++ core) for a machine that only supports sockets/cores/threads. ++ Some members of the option can be omitted but their values will be ++ automatically computed: ++ ++ :: ++ ++ -smp 8,sockets=2,cores=2,threads=2,maxcpus=8 ++ ++ The following sub-option defines a CPU topology hierarchy (2 sockets ++ totally on the machine, 2 dies per socket, 2 cores per die, 2 threads ++ per core) for PC machines which support sockets/dies/cores/threads. ++ Some members of the option can be omitted but their values will be ++ automatically computed: ++ ++ :: ++ ++ -smp 16,sockets=2,dies=2,cores=2,threads=2,maxcpus=16 ++ + Historically preference was given to the coarsest topology parameters + when computing missing values (ie sockets preferred over cores, which + were preferred over threads), however, this behaviour is considered + liable to change. Prior to 6.2 the preference was sockets over cores + over threads. Since 6.2 the preference is cores over sockets over threads. ++ ++ For example, the following option defines a machine board with 2 sockets ++ of 1 core before 6.2 and 1 socket of 2 cores after 6.2: ++ ++ :: ++ ++ -smp 2 + ERST + + DEF("numa", HAS_ARG, QEMU_OPTION_numa, +-- +2.27.0 + -- Gitee From 948c15f80f449baac73d422ee564127581feadbb Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Tue, 28 Dec 2021 17:22:09 +0800 Subject: [PATCH 11/54] hw/core/machine: Introduce CPU cluster topology support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The new Cluster-Aware Scheduling support has landed in Linux 5.16, which has been proved to benefit the scheduling performance (e.g. load balance and wake_affine strategy) on both x86_64 and AArch64. So now in Linux 5.16 we have four-level arch-neutral CPU topology definition like below and a new scheduler level for clusters. struct cpu_topology { int thread_id; int core_id; int cluster_id; int package_id; int llc_id; cpumask_t thread_sibling; cpumask_t core_sibling; cpumask_t cluster_sibling; cpumask_t llc_sibling; } A cluster generally means a group of CPU cores which share L2 cache or other mid-level resources, and it is the shared resources that is used to improve scheduler's behavior. From the point of view of the size range, it's between CPU die and CPU core. For example, on some ARM64 Kunpeng servers, we have 6 clusters in each NUMA node, and 4 CPU cores in each cluster. The 4 CPU cores share a separate L2 cache and a L3 cache tag, which brings cache affinity advantage. In virtualization, on the Hosts which have pClusters (physical clusters), if we can design a vCPU topology with cluster level for guest kernel and have a dedicated vCPU pinning. A Cluster-Aware Guest kernel can also make use of the cache affinity of CPU clusters to gain similar scheduling performance. This patch adds infrastructure for CPU cluster level topology configuration and parsing, so that the user can specify cluster parameter if their machines support it. Signed-off-by: Yanan Wang Message-Id: <20211228092221.21068-3-wangyanan55@huawei.com> Reviewed-by: Philippe Mathieu-Daudé [PMD: Added '(since 7.0)' to @clusters in qapi/machine.json] Signed-off-by: Philippe Mathieu-Daudé --- ...Introduce-CPU-cluster-topology-suppo.patch | 283 ++++++++++++++++++ 1 file changed, 283 insertions(+) create mode 100644 hw-core-machine-Introduce-CPU-cluster-topology-suppo.patch diff --git a/hw-core-machine-Introduce-CPU-cluster-topology-suppo.patch b/hw-core-machine-Introduce-CPU-cluster-topology-suppo.patch new file mode 100644 index 0000000..ed78241 --- /dev/null +++ b/hw-core-machine-Introduce-CPU-cluster-topology-suppo.patch @@ -0,0 +1,283 @@ +From bf4a20a82bd4804842dd2960db30e0be7ecb2d32 Mon Sep 17 00:00:00 2001 +From: Yanan Wang +Date: Tue, 28 Dec 2021 17:22:09 +0800 +Subject: [PATCH] hw/core/machine: Introduce CPU cluster topology support +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The new Cluster-Aware Scheduling support has landed in Linux 5.16, +which has been proved to benefit the scheduling performance (e.g. +load balance and wake_affine strategy) on both x86_64 and AArch64. + +So now in Linux 5.16 we have four-level arch-neutral CPU topology +definition like below and a new scheduler level for clusters. +struct cpu_topology { + int thread_id; + int core_id; + int cluster_id; + int package_id; + int llc_id; + cpumask_t thread_sibling; + cpumask_t core_sibling; + cpumask_t cluster_sibling; + cpumask_t llc_sibling; +} + +A cluster generally means a group of CPU cores which share L2 cache +or other mid-level resources, and it is the shared resources that +is used to improve scheduler's behavior. From the point of view of +the size range, it's between CPU die and CPU core. For example, on +some ARM64 Kunpeng servers, we have 6 clusters in each NUMA node, +and 4 CPU cores in each cluster. The 4 CPU cores share a separate +L2 cache and a L3 cache tag, which brings cache affinity advantage. + +In virtualization, on the Hosts which have pClusters (physical +clusters), if we can design a vCPU topology with cluster level for +guest kernel and have a dedicated vCPU pinning. A Cluster-Aware +Guest kernel can also make use of the cache affinity of CPU clusters +to gain similar scheduling performance. + +This patch adds infrastructure for CPU cluster level topology +configuration and parsing, so that the user can specify cluster +parameter if their machines support it. + +Signed-off-by: Yanan Wang +Message-Id: <20211228092221.21068-3-wangyanan55@huawei.com> +Reviewed-by: Philippe Mathieu-Daudé +[PMD: Added '(since 7.0)' to @clusters in qapi/machine.json] +Signed-off-by: Philippe Mathieu-Daudé +--- + hw/core/machine-smp.c | 26 +++++++++++++++++++------- + hw/core/machine.c | 3 +++ + include/hw/boards.h | 6 +++++- + qapi/machine.json | 5 ++++- + qemu-options.hx | 7 ++++--- + softmmu/vl.c | 3 +++ + 6 files changed, 38 insertions(+), 12 deletions(-) + +diff --git a/hw/core/machine-smp.c b/hw/core/machine-smp.c +index 2cbfd57429..b39ed21e65 100644 +--- a/hw/core/machine-smp.c ++++ b/hw/core/machine-smp.c +@@ -37,6 +37,10 @@ static char *cpu_hierarchy_to_string(MachineState *ms) + g_string_append_printf(s, " * dies (%u)", ms->smp.dies); + } + ++ if (mc->smp_props.clusters_supported) { ++ g_string_append_printf(s, " * clusters (%u)", ms->smp.clusters); ++ } ++ + g_string_append_printf(s, " * cores (%u)", ms->smp.cores); + g_string_append_printf(s, " * threads (%u)", ms->smp.threads); + +@@ -71,6 +75,7 @@ void machine_parse_smp_config(MachineState *ms, + unsigned cpus = config->has_cpus ? config->cpus : 0; + unsigned sockets = config->has_sockets ? config->sockets : 0; + unsigned dies = config->has_dies ? config->dies : 0; ++ unsigned clusters = config->has_clusters ? config->clusters : 0; + unsigned cores = config->has_cores ? config->cores : 0; + unsigned threads = config->has_threads ? config->threads : 0; + unsigned maxcpus = config->has_maxcpus ? config->maxcpus : 0; +@@ -82,6 +87,7 @@ void machine_parse_smp_config(MachineState *ms, + if ((config->has_cpus && config->cpus == 0) || + (config->has_sockets && config->sockets == 0) || + (config->has_dies && config->dies == 0) || ++ (config->has_clusters && config->clusters == 0) || + (config->has_cores && config->cores == 0) || + (config->has_threads && config->threads == 0) || + (config->has_maxcpus && config->maxcpus == 0)) { +@@ -97,8 +103,13 @@ void machine_parse_smp_config(MachineState *ms, + error_setg(errp, "dies not supported by this machine's CPU topology"); + return; + } ++ if (!mc->smp_props.clusters_supported && clusters > 1) { ++ error_setg(errp, "clusters not supported by this machine's CPU topology"); ++ return; ++ } + + dies = dies > 0 ? dies : 1; ++ clusters = clusters > 0 ? clusters : 1; + + /* compute missing values based on the provided ones */ + if (cpus == 0 && maxcpus == 0) { +@@ -113,41 +124,42 @@ void machine_parse_smp_config(MachineState *ms, + if (sockets == 0) { + cores = cores > 0 ? cores : 1; + threads = threads > 0 ? threads : 1; +- sockets = maxcpus / (dies * cores * threads); ++ sockets = maxcpus / (dies * clusters * cores * threads); + } else if (cores == 0) { + threads = threads > 0 ? threads : 1; +- cores = maxcpus / (sockets * dies * threads); ++ cores = maxcpus / (sockets * dies * clusters * threads); + } + } else { + /* prefer cores over sockets since 6.2 */ + if (cores == 0) { + sockets = sockets > 0 ? sockets : 1; + threads = threads > 0 ? threads : 1; +- cores = maxcpus / (sockets * dies * threads); ++ cores = maxcpus / (sockets * dies * clusters * threads); + } else if (sockets == 0) { + threads = threads > 0 ? threads : 1; +- sockets = maxcpus / (dies * cores * threads); ++ sockets = maxcpus / (dies * clusters * cores * threads); + } + } + + /* try to calculate omitted threads at last */ + if (threads == 0) { +- threads = maxcpus / (sockets * dies * cores); ++ threads = maxcpus / (sockets * dies * clusters * cores); + } + } + +- maxcpus = maxcpus > 0 ? maxcpus : sockets * dies * cores * threads; ++ maxcpus = maxcpus > 0 ? maxcpus : sockets * dies * clusters * cores * threads; + cpus = cpus > 0 ? cpus : maxcpus; + + ms->smp.cpus = cpus; + ms->smp.sockets = sockets; + ms->smp.dies = dies; ++ ms->smp.clusters = clusters; + ms->smp.cores = cores; + ms->smp.threads = threads; + ms->smp.max_cpus = maxcpus; + + /* sanity-check of the computed topology */ +- if (sockets * dies * cores * threads != maxcpus) { ++ if (sockets * dies * clusters * cores * threads != maxcpus) { + g_autofree char *topo_msg = cpu_hierarchy_to_string(ms); + error_setg(errp, "Invalid CPU topology: " + "product of the hierarchy must match maxcpus: " +diff --git a/hw/core/machine.c b/hw/core/machine.c +index 3993c534b9..a4a2df405f 100644 +--- a/hw/core/machine.c ++++ b/hw/core/machine.c +@@ -742,10 +742,12 @@ static void machine_get_smp(Object *obj, Visitor *v, const char *name, + .has_cpus = true, .cpus = ms->smp.cpus, + .has_sockets = true, .sockets = ms->smp.sockets, + .has_dies = true, .dies = ms->smp.dies, ++ .has_clusters = true, .clusters = ms->smp.clusters, + .has_cores = true, .cores = ms->smp.cores, + .has_threads = true, .threads = ms->smp.threads, + .has_maxcpus = true, .maxcpus = ms->smp.max_cpus, + }; ++ + if (!visit_type_SMPConfiguration(v, name, &config, &error_abort)) { + return; + } +@@ -932,6 +934,7 @@ static void machine_initfn(Object *obj) + ms->smp.max_cpus = mc->default_cpus; + ms->smp.sockets = 1; + ms->smp.dies = 1; ++ ms->smp.clusters = 1; + ms->smp.cores = 1; + ms->smp.threads = 1; + } +diff --git a/include/hw/boards.h b/include/hw/boards.h +index 7597cec440..f49a2578ea 100644 +--- a/include/hw/boards.h ++++ b/include/hw/boards.h +@@ -129,10 +129,12 @@ typedef struct { + * SMPCompatProps: + * @prefer_sockets - whether sockets are preferred over cores in smp parsing + * @dies_supported - whether dies are supported by the machine ++ * @clusters_supported - whether clusters are supported by the machine + */ + typedef struct { + bool prefer_sockets; + bool dies_supported; ++ bool clusters_supported; + } SMPCompatProps; + + /** +@@ -299,7 +301,8 @@ typedef struct DeviceMemoryState { + * @cpus: the number of present logical processors on the machine + * @sockets: the number of sockets on the machine + * @dies: the number of dies in one socket +- * @cores: the number of cores in one die ++ * @clusters: the number of clusters in one die ++ * @cores: the number of cores in one cluster + * @threads: the number of threads in one core + * @max_cpus: the maximum number of logical processors on the machine + */ +@@ -307,6 +310,7 @@ typedef struct CpuTopology { + unsigned int cpus; + unsigned int sockets; + unsigned int dies; ++ unsigned int clusters; + unsigned int cores; + unsigned int threads; + unsigned int max_cpus; +diff --git a/qapi/machine.json b/qapi/machine.json +index f1839acf20..8faa51074e 100644 +--- a/qapi/machine.json ++++ b/qapi/machine.json +@@ -1396,7 +1396,9 @@ + # + # @dies: number of dies per socket in the CPU topology + # +-# @cores: number of cores per die in the CPU topology ++# @clusters: number of clusters per die in the CPU topology (since 7.0) ++# ++# @cores: number of cores per cluster in the CPU topology + # + # @threads: number of threads per core in the CPU topology + # +@@ -1408,6 +1410,7 @@ + '*cpus': 'int', + '*sockets': 'int', + '*dies': 'int', ++ '*clusters': 'int', + '*cores': 'int', + '*threads': 'int', + '*maxcpus': 'int' } } +diff --git a/qemu-options.hx b/qemu-options.hx +index 7a59db7764..0f26f7dad7 100644 +--- a/qemu-options.hx ++++ b/qemu-options.hx +@@ -206,13 +206,14 @@ SRST + ERST + + DEF("smp", HAS_ARG, QEMU_OPTION_smp, +- "-smp [[cpus=]n][,maxcpus=maxcpus][,sockets=sockets][,dies=dies][,cores=cores][,threads=threads]\n" ++ "-smp [[cpus=]n][,maxcpus=maxcpus][,sockets=sockets][,dies=dies][,clusters=clusters][,cores=cores][,threads=threads]\n" + " set the number of initial CPUs to 'n' [default=1]\n" + " maxcpus= maximum number of total CPUs, including\n" + " offline CPUs for hotplug, etc\n" + " sockets= number of sockets on the machine board\n" + " dies= number of dies in one socket\n" +- " cores= number of cores in one die\n" ++ " clusters= number of clusters in one die\n" ++ " cores= number of cores in one cluster\n" + " threads= number of threads in one core\n" + "Note: Different machines may have different subsets of the CPU topology\n" + " parameters supported, so the actual meaning of the supported parameters\n" +@@ -228,7 +229,7 @@ DEF("smp", HAS_ARG, QEMU_OPTION_smp, + " must be set as 1 in the purpose of correct parsing.\n", + QEMU_ARCH_ALL) + SRST +-``-smp [[cpus=]n][,maxcpus=maxcpus][,sockets=sockets][,dies=dies][,cores=cores][,threads=threads]`` ++``-smp [[cpus=]n][,maxcpus=maxcpus][,sockets=sockets][,dies=dies][,clusters=clusters][,cores=cores][,threads=threads]`` + Simulate a SMP system with '\ ``n``\ ' CPUs initially present on + the machine type board. On boards supporting CPU hotplug, the optional + '\ ``maxcpus``\ ' parameter can be set to enable further CPUs to be +diff --git a/softmmu/vl.c b/softmmu/vl.c +index 620a1f1367..d9e4c619d3 100644 +--- a/softmmu/vl.c ++++ b/softmmu/vl.c +@@ -726,6 +726,9 @@ static QemuOptsList qemu_smp_opts = { + }, { + .name = "dies", + .type = QEMU_OPT_NUMBER, ++ }, { ++ .name = "clusters", ++ .type = QEMU_OPT_NUMBER, + }, { + .name = "cores", + .type = QEMU_OPT_NUMBER, +-- +2.27.0 + -- Gitee From 5f9bbb5f07a5a2aea3b0e52249910840fa6a7ac0 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Tue, 28 Dec 2021 17:22:11 +0800 Subject: [PATCH 12/54] tests/unit/test-smp-parse: Add testcases for CPU clusters MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add testcases for parsing of the four-level CPU topology hierarchy, ie sockets/clusters/cores/threads, which will be supported on ARM virt machines. Signed-off-by: Yanan Wang Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20211228092221.21068-5-wangyanan55@huawei.com> Signed-off-by: Philippe Mathieu-Daudé --- ...smp-parse-Add-testcases-for-CPU-clus.patch | 253 ++++++++++++++++++ 1 file changed, 253 insertions(+) create mode 100644 tests-unit-test-smp-parse-Add-testcases-for-CPU-clus.patch diff --git a/tests-unit-test-smp-parse-Add-testcases-for-CPU-clus.patch b/tests-unit-test-smp-parse-Add-testcases-for-CPU-clus.patch new file mode 100644 index 0000000..ced30b9 --- /dev/null +++ b/tests-unit-test-smp-parse-Add-testcases-for-CPU-clus.patch @@ -0,0 +1,253 @@ +From 5e8a39a560ea58308f66d47639c0d5d2e704997f Mon Sep 17 00:00:00 2001 +From: Yanan Wang +Date: Tue, 28 Dec 2021 17:22:11 +0800 +Subject: [PATCH] tests/unit/test-smp-parse: Add testcases for CPU clusters +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add testcases for parsing of the four-level CPU topology hierarchy, +ie sockets/clusters/cores/threads, which will be supported on ARM +virt machines. + +Signed-off-by: Yanan Wang +Reviewed-by: Philippe Mathieu-Daudé +Message-Id: <20211228092221.21068-5-wangyanan55@huawei.com> +Signed-off-by: Philippe Mathieu-Daudé +--- + tests/unit/test-smp-parse.c | 130 ++++++++++++++++++++++++++++++++++-- + 1 file changed, 123 insertions(+), 7 deletions(-) + +diff --git a/tests/unit/test-smp-parse.c b/tests/unit/test-smp-parse.c +index b6df8137fc..331719bbc4 100644 +--- a/tests/unit/test-smp-parse.c ++++ b/tests/unit/test-smp-parse.c +@@ -61,6 +61,20 @@ + .has_maxcpus = hf, .maxcpus = f, \ + } + ++/* ++ * Currently a 4-level topology hierarchy is supported on ARM virt machines ++ * -sockets/clusters/cores/threads ++ */ ++#define SMP_CONFIG_WITH_CLUSTERS(ha, a, hb, b, hc, c, hd, d, he, e, hf, f) \ ++ { \ ++ .has_cpus = ha, .cpus = a, \ ++ .has_sockets = hb, .sockets = b, \ ++ .has_clusters = hc, .clusters = c, \ ++ .has_cores = hd, .cores = d, \ ++ .has_threads = he, .threads = e, \ ++ .has_maxcpus = hf, .maxcpus = f, \ ++ } ++ + /** + * @config - the given SMP configuration + * @expect_prefer_sockets - the expected parsing result for the +@@ -290,6 +304,10 @@ static const struct SMPTestData data_generic_invalid[] = { + /* config: -smp 2,dies=2 */ + .config = SMP_CONFIG_WITH_DIES(T, 2, F, 0, T, 2, F, 0, F, 0, F, 0), + .expect_error = "dies not supported by this machine's CPU topology", ++ }, { ++ /* config: -smp 2,clusters=2 */ ++ .config = SMP_CONFIG_WITH_CLUSTERS(T, 2, F, 0, T, 2, F, 0, F, 0, F, 0), ++ .expect_error = "clusters not supported by this machine's CPU topology", + }, { + /* config: -smp 8,sockets=2,cores=4,threads=2,maxcpus=8 */ + .config = SMP_CONFIG_GENERIC(T, 8, T, 2, T, 4, T, 2, T, 8), +@@ -337,20 +355,40 @@ static const struct SMPTestData data_with_dies_invalid[] = { + }, + }; + ++static const struct SMPTestData data_with_clusters_invalid[] = { ++ { ++ /* config: -smp 16,sockets=2,clusters=2,cores=4,threads=2,maxcpus=16 */ ++ .config = SMP_CONFIG_WITH_CLUSTERS(T, 16, T, 2, T, 2, T, 4, T, 2, T, 16), ++ .expect_error = "Invalid CPU topology: " ++ "product of the hierarchy must match maxcpus: " ++ "sockets (2) * clusters (2) * cores (4) * threads (2) " ++ "!= maxcpus (16)", ++ }, { ++ /* config: -smp 34,sockets=2,clusters=2,cores=4,threads=2,maxcpus=32 */ ++ .config = SMP_CONFIG_WITH_CLUSTERS(T, 34, T, 2, T, 2, T, 4, T, 2, T, 32), ++ .expect_error = "Invalid CPU topology: " ++ "maxcpus must be equal to or greater than smp: " ++ "sockets (2) * clusters (2) * cores (4) * threads (2) " ++ "== maxcpus (32) < smp_cpus (34)", ++ }, ++}; ++ + static char *smp_config_to_string(const SMPConfiguration *config) + { + return g_strdup_printf( + "(SMPConfiguration) {\n" +- " .has_cpus = %5s, cpus = %" PRId64 ",\n" +- " .has_sockets = %5s, sockets = %" PRId64 ",\n" +- " .has_dies = %5s, dies = %" PRId64 ",\n" +- " .has_cores = %5s, cores = %" PRId64 ",\n" +- " .has_threads = %5s, threads = %" PRId64 ",\n" +- " .has_maxcpus = %5s, maxcpus = %" PRId64 ",\n" ++ " .has_cpus = %5s, cpus = %" PRId64 ",\n" ++ " .has_sockets = %5s, sockets = %" PRId64 ",\n" ++ " .has_dies = %5s, dies = %" PRId64 ",\n" ++ " .has_clusters = %5s, clusters = %" PRId64 ",\n" ++ " .has_cores = %5s, cores = %" PRId64 ",\n" ++ " .has_threads = %5s, threads = %" PRId64 ",\n" ++ " .has_maxcpus = %5s, maxcpus = %" PRId64 ",\n" + "}", + config->has_cpus ? "true" : "false", config->cpus, + config->has_sockets ? "true" : "false", config->sockets, + config->has_dies ? "true" : "false", config->dies, ++ config->has_clusters ? "true" : "false", config->clusters, + config->has_cores ? "true" : "false", config->cores, + config->has_threads ? "true" : "false", config->threads, + config->has_maxcpus ? "true" : "false", config->maxcpus); +@@ -363,11 +401,12 @@ static char *cpu_topology_to_string(const CpuTopology *topo) + " .cpus = %u,\n" + " .sockets = %u,\n" + " .dies = %u,\n" ++ " .clusters = %u,\n" + " .cores = %u,\n" + " .threads = %u,\n" + " .max_cpus = %u,\n" + "}", +- topo->cpus, topo->sockets, topo->dies, ++ topo->cpus, topo->sockets, topo->dies, topo->clusters, + topo->cores, topo->threads, topo->max_cpus); + } + +@@ -391,6 +430,7 @@ static void check_parse(MachineState *ms, const SMPConfiguration *config, + (ms->smp.cpus == expect_topo->cpus) && + (ms->smp.sockets == expect_topo->sockets) && + (ms->smp.dies == expect_topo->dies) && ++ (ms->smp.clusters == expect_topo->clusters) && + (ms->smp.cores == expect_topo->cores) && + (ms->smp.threads == expect_topo->threads) && + (ms->smp.max_cpus == expect_topo->max_cpus)) { +@@ -472,6 +512,11 @@ static void unsupported_params_init(const MachineClass *mc, SMPTestData *data) + data->expect_prefer_sockets.dies = 1; + data->expect_prefer_cores.dies = 1; + } ++ ++ if (!mc->smp_props.clusters_supported) { ++ data->expect_prefer_sockets.clusters = 1; ++ data->expect_prefer_cores.clusters = 1; ++ } + } + + static void machine_base_class_init(ObjectClass *oc, void *data) +@@ -491,6 +536,7 @@ static void machine_generic_valid_class_init(ObjectClass *oc, void *data) + mc->max_cpus = MAX_CPUS; + + mc->smp_props.dies_supported = false; ++ mc->smp_props.clusters_supported = false; + } + + static void machine_generic_invalid_class_init(ObjectClass *oc, void *data) +@@ -502,6 +548,7 @@ static void machine_generic_invalid_class_init(ObjectClass *oc, void *data) + mc->max_cpus = 511; + + mc->smp_props.dies_supported = false; ++ mc->smp_props.clusters_supported = false; + } + + static void machine_with_dies_class_init(ObjectClass *oc, void *data) +@@ -512,6 +559,18 @@ static void machine_with_dies_class_init(ObjectClass *oc, void *data) + mc->max_cpus = MAX_CPUS; + + mc->smp_props.dies_supported = true; ++ mc->smp_props.clusters_supported = false; ++} ++ ++static void machine_with_clusters_class_init(ObjectClass *oc, void *data) ++{ ++ MachineClass *mc = MACHINE_CLASS(oc); ++ ++ mc->min_cpus = MIN_CPUS; ++ mc->max_cpus = MAX_CPUS; ++ ++ mc->smp_props.clusters_supported = true; ++ mc->smp_props.dies_supported = false; + } + + static void test_generic_valid(const void *opaque) +@@ -607,6 +666,56 @@ static void test_with_dies(const void *opaque) + object_unref(obj); + } + ++static void test_with_clusters(const void *opaque) ++{ ++ const char *machine_type = opaque; ++ Object *obj = object_new(machine_type); ++ MachineState *ms = MACHINE(obj); ++ MachineClass *mc = MACHINE_GET_CLASS(obj); ++ SMPTestData data = {}; ++ unsigned int num_clusters = 2; ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(data_generic_valid); i++) { ++ data = data_generic_valid[i]; ++ unsupported_params_init(mc, &data); ++ ++ /* when clusters parameter is omitted, it will be set as 1 */ ++ data.expect_prefer_sockets.clusters = 1; ++ data.expect_prefer_cores.clusters = 1; ++ ++ smp_parse_test(ms, &data, true); ++ ++ /* when clusters parameter is specified */ ++ data.config.has_clusters = true; ++ data.config.clusters = num_clusters; ++ if (data.config.has_cpus) { ++ data.config.cpus *= num_clusters; ++ } ++ if (data.config.has_maxcpus) { ++ data.config.maxcpus *= num_clusters; ++ } ++ ++ data.expect_prefer_sockets.clusters = num_clusters; ++ data.expect_prefer_sockets.cpus *= num_clusters; ++ data.expect_prefer_sockets.max_cpus *= num_clusters; ++ data.expect_prefer_cores.clusters = num_clusters; ++ data.expect_prefer_cores.cpus *= num_clusters; ++ data.expect_prefer_cores.max_cpus *= num_clusters; ++ ++ smp_parse_test(ms, &data, true); ++ } ++ ++ for (i = 0; i < ARRAY_SIZE(data_with_clusters_invalid); i++) { ++ data = data_with_clusters_invalid[i]; ++ unsupported_params_init(mc, &data); ++ ++ smp_parse_test(ms, &data, false); ++ } ++ ++ object_unref(obj); ++} ++ + /* Type info of the tested machine */ + static const TypeInfo smp_machine_types[] = { + { +@@ -628,6 +737,10 @@ static const TypeInfo smp_machine_types[] = { + .name = MACHINE_TYPE_NAME("smp-with-dies"), + .parent = TYPE_MACHINE, + .class_init = machine_with_dies_class_init, ++ }, { ++ .name = MACHINE_TYPE_NAME("smp-with-clusters"), ++ .parent = TYPE_MACHINE, ++ .class_init = machine_with_clusters_class_init, + } + }; + +@@ -648,6 +761,9 @@ int main(int argc, char *argv[]) + g_test_add_data_func("/test-smp-parse/with_dies", + MACHINE_TYPE_NAME("smp-with-dies"), + test_with_dies); ++ g_test_add_data_func("/test-smp-parse/with_clusters", ++ MACHINE_TYPE_NAME("smp-with-clusters"), ++ test_with_clusters); + + g_test_run(); + +-- +2.27.0 + -- Gitee From b9bae00cae93262cb3f2d5cc438d267438584e1b Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Tue, 28 Dec 2021 17:22:12 +0800 Subject: [PATCH 13/54] tests/unit/test-smp-parse: No need to explicitly zero MachineClass members MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The default value of the MachineClass members is 0, which means we don't have to explicitly zero them. Also the value of "mc->smp_props.prefer_sockets" will be taken care of by smp_parse_test(), we don't necessarily need the statement in machine_base_class_init() either. Signed-off-by: Yanan Wang Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20211228092221.21068-6-wangyanan55@huawei.com> Signed-off-by: Philippe Mathieu-Daudé --- ...smp-parse-No-need-to-explicitly-zero.patch | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 tests-unit-test-smp-parse-No-need-to-explicitly-zero.patch diff --git a/tests-unit-test-smp-parse-No-need-to-explicitly-zero.patch b/tests-unit-test-smp-parse-No-need-to-explicitly-zero.patch new file mode 100644 index 0000000..3595f08 --- /dev/null +++ b/tests-unit-test-smp-parse-No-need-to-explicitly-zero.patch @@ -0,0 +1,75 @@ +From 77bca7d51e99f8ba4d11635ff9f51615739f4d55 Mon Sep 17 00:00:00 2001 +From: Yanan Wang +Date: Tue, 28 Dec 2021 17:22:12 +0800 +Subject: [PATCH] tests/unit/test-smp-parse: No need to explicitly zero + MachineClass members +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The default value of the MachineClass members is 0, which +means we don't have to explicitly zero them. Also the value +of "mc->smp_props.prefer_sockets" will be taken care of by +smp_parse_test(), we don't necessarily need the statement +in machine_base_class_init() either. + +Signed-off-by: Yanan Wang +Reviewed-by: Philippe Mathieu-Daudé +Message-Id: <20211228092221.21068-6-wangyanan55@huawei.com> +Signed-off-by: Philippe Mathieu-Daudé +--- + tests/unit/test-smp-parse.c | 10 ---------- + 1 file changed, 10 deletions(-) + +diff --git a/tests/unit/test-smp-parse.c b/tests/unit/test-smp-parse.c +index 331719bbc4..72d83d1bbc 100644 +--- a/tests/unit/test-smp-parse.c ++++ b/tests/unit/test-smp-parse.c +@@ -523,8 +523,6 @@ static void machine_base_class_init(ObjectClass *oc, void *data) + { + MachineClass *mc = MACHINE_CLASS(oc); + +- mc->smp_props.prefer_sockets = true; +- + mc->name = g_strdup(SMP_MACHINE_NAME); + } + +@@ -534,9 +532,6 @@ static void machine_generic_valid_class_init(ObjectClass *oc, void *data) + + mc->min_cpus = MIN_CPUS; + mc->max_cpus = MAX_CPUS; +- +- mc->smp_props.dies_supported = false; +- mc->smp_props.clusters_supported = false; + } + + static void machine_generic_invalid_class_init(ObjectClass *oc, void *data) +@@ -546,9 +541,6 @@ static void machine_generic_invalid_class_init(ObjectClass *oc, void *data) + /* Force invalid min CPUs and max CPUs */ + mc->min_cpus = 2; + mc->max_cpus = 511; +- +- mc->smp_props.dies_supported = false; +- mc->smp_props.clusters_supported = false; + } + + static void machine_with_dies_class_init(ObjectClass *oc, void *data) +@@ -559,7 +551,6 @@ static void machine_with_dies_class_init(ObjectClass *oc, void *data) + mc->max_cpus = MAX_CPUS; + + mc->smp_props.dies_supported = true; +- mc->smp_props.clusters_supported = false; + } + + static void machine_with_clusters_class_init(ObjectClass *oc, void *data) +@@ -570,7 +561,6 @@ static void machine_with_clusters_class_init(ObjectClass *oc, void *data) + mc->max_cpus = MAX_CPUS; + + mc->smp_props.clusters_supported = true; +- mc->smp_props.dies_supported = false; + } + + static void test_generic_valid(const void *opaque) +-- +2.27.0 + -- Gitee From bd2797ba46f20d41f2e26be502018fd3c983f1a7 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Tue, 28 Dec 2021 17:22:13 +0800 Subject: [PATCH 14/54] tests/unit/test-smp-parse: Keep default MIN/MAX CPUs in machine_base_class_init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Most machine types in test-smp-parse will be OK to have the default MIN/MAX CPUs except "smp-generic-invalid", let's keep the default values in machine_base_class_init which will be inherited. And if we hope a different value for a specific machine, modify it in its own initialization function. Signed-off-by: Yanan Wang Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20211228092221.21068-7-wangyanan55@huawei.com> Signed-off-by: Philippe Mathieu-Daudé --- ...smp-parse-Keep-default-MIN-MAX-CPUs-.patch | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 tests-unit-test-smp-parse-Keep-default-MIN-MAX-CPUs-.patch diff --git a/tests-unit-test-smp-parse-Keep-default-MIN-MAX-CPUs-.patch b/tests-unit-test-smp-parse-Keep-default-MIN-MAX-CPUs-.patch new file mode 100644 index 0000000..0ce47e2 --- /dev/null +++ b/tests-unit-test-smp-parse-Keep-default-MIN-MAX-CPUs-.patch @@ -0,0 +1,76 @@ +From 214511b1799b94cfd514a222d087bb888ed808ba Mon Sep 17 00:00:00 2001 +From: Yanan Wang +Date: Tue, 28 Dec 2021 17:22:13 +0800 +Subject: [PATCH] tests/unit/test-smp-parse: Keep default MIN/MAX CPUs in + machine_base_class_init +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Most machine types in test-smp-parse will be OK to have the default +MIN/MAX CPUs except "smp-generic-invalid", let's keep the default +values in machine_base_class_init which will be inherited. And if +we hope a different value for a specific machine, modify it in its +own initialization function. + +Signed-off-by: Yanan Wang +Reviewed-by: Philippe Mathieu-Daudé +Message-Id: <20211228092221.21068-7-wangyanan55@huawei.com> +Signed-off-by: Philippe Mathieu-Daudé +--- + tests/unit/test-smp-parse.c | 16 ++-------------- + 1 file changed, 2 insertions(+), 14 deletions(-) + +diff --git a/tests/unit/test-smp-parse.c b/tests/unit/test-smp-parse.c +index 72d83d1bbc..fdc39a846c 100644 +--- a/tests/unit/test-smp-parse.c ++++ b/tests/unit/test-smp-parse.c +@@ -523,15 +523,10 @@ static void machine_base_class_init(ObjectClass *oc, void *data) + { + MachineClass *mc = MACHINE_CLASS(oc); + +- mc->name = g_strdup(SMP_MACHINE_NAME); +-} +- +-static void machine_generic_valid_class_init(ObjectClass *oc, void *data) +-{ +- MachineClass *mc = MACHINE_CLASS(oc); +- + mc->min_cpus = MIN_CPUS; + mc->max_cpus = MAX_CPUS; ++ ++ mc->name = g_strdup(SMP_MACHINE_NAME); + } + + static void machine_generic_invalid_class_init(ObjectClass *oc, void *data) +@@ -547,9 +542,6 @@ static void machine_with_dies_class_init(ObjectClass *oc, void *data) + { + MachineClass *mc = MACHINE_CLASS(oc); + +- mc->min_cpus = MIN_CPUS; +- mc->max_cpus = MAX_CPUS; +- + mc->smp_props.dies_supported = true; + } + +@@ -557,9 +549,6 @@ static void machine_with_clusters_class_init(ObjectClass *oc, void *data) + { + MachineClass *mc = MACHINE_CLASS(oc); + +- mc->min_cpus = MIN_CPUS; +- mc->max_cpus = MAX_CPUS; +- + mc->smp_props.clusters_supported = true; + } + +@@ -718,7 +707,6 @@ static const TypeInfo smp_machine_types[] = { + }, { + .name = MACHINE_TYPE_NAME("smp-generic-valid"), + .parent = TYPE_MACHINE, +- .class_init = machine_generic_valid_class_init, + }, { + .name = MACHINE_TYPE_NAME("smp-generic-invalid"), + .parent = TYPE_MACHINE, +-- +2.27.0 + -- Gitee From a1135ec97b6a29c43124585eb3d01c60381624d8 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Fri, 7 Jan 2022 16:32:27 +0800 Subject: [PATCH 15/54] hw/arm/virt: Support CPU cluster on ARM virt machine ARM64 machines like Kunpeng Family Server Chips have a level of hardware topology in which a group of CPU cores share L3 cache tag or L2 cache. For example, Kunpeng 920 typically has 6 or 8 clusters in each NUMA node (also represent range of CPU die), and each cluster has 4 CPU cores. All clusters share L3 cache data, but CPU cores in each cluster share a local L3 tag. Running a guest kernel with Cluster-Aware Scheduling on the Hosts which have physical clusters, if we can design a vCPU topology with cluster level for guest kernel and then have a dedicated vCPU pinning, the guest will gain scheduling performance improvement from cache affinity of CPU cluster. So let's enable the support for this new parameter on ARM virt machines. After this patch, we can define a 4-level CPU hierarchy like: cpus=*,maxcpus=*,sockets=*,clusters=*, cores=*,threads=*. Signed-off-by: Yanan Wang Reviewed-by: Andrew Jones Message-id: 20220107083232.16256-2-wangyanan55@huawei.com Signed-off-by: Peter Maydell --- ...port-CPU-cluster-on-ARM-virt-machine.patch | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 hw-arm-virt-Support-CPU-cluster-on-ARM-virt-machine.patch diff --git a/hw-arm-virt-Support-CPU-cluster-on-ARM-virt-machine.patch b/hw-arm-virt-Support-CPU-cluster-on-ARM-virt-machine.patch new file mode 100644 index 0000000..61d312a --- /dev/null +++ b/hw-arm-virt-Support-CPU-cluster-on-ARM-virt-machine.patch @@ -0,0 +1,69 @@ +From 1fab7ee365c8daccedd19d3a1be56babe36afcc6 Mon Sep 17 00:00:00 2001 +From: Yanan Wang +Date: Fri, 7 Jan 2022 16:32:27 +0800 +Subject: [PATCH] hw/arm/virt: Support CPU cluster on ARM virt machine + +ARM64 machines like Kunpeng Family Server Chips have a level +of hardware topology in which a group of CPU cores share L3 +cache tag or L2 cache. For example, Kunpeng 920 typically +has 6 or 8 clusters in each NUMA node (also represent range +of CPU die), and each cluster has 4 CPU cores. All clusters +share L3 cache data, but CPU cores in each cluster share a +local L3 tag. + +Running a guest kernel with Cluster-Aware Scheduling on the +Hosts which have physical clusters, if we can design a vCPU +topology with cluster level for guest kernel and then have +a dedicated vCPU pinning, the guest will gain scheduling +performance improvement from cache affinity of CPU cluster. + +So let's enable the support for this new parameter on ARM +virt machines. After this patch, we can define a 4-level +CPU hierarchy like: cpus=*,maxcpus=*,sockets=*,clusters=*, +cores=*,threads=*. + +Signed-off-by: Yanan Wang +Reviewed-by: Andrew Jones +Message-id: 20220107083232.16256-2-wangyanan55@huawei.com +Signed-off-by: Peter Maydell +--- + hw/arm/virt.c | 1 + + qemu-options.hx | 10 ++++++++++ + 2 files changed, 11 insertions(+) + +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index 3c972fdab0..6ca9cbe2cf 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -2704,6 +2704,7 @@ static void virt_machine_class_init(ObjectClass *oc, void *data) + hc->unplug_request = virt_machine_device_unplug_request_cb; + hc->unplug = virt_machine_device_unplug_cb; + mc->nvdimm_supported = true; ++ mc->smp_props.clusters_supported = true; + mc->auto_enable_numa_with_memhp = true; + mc->auto_enable_numa_with_memdev = true; + mc->default_ram_id = "mach-virt.ram"; +diff --git a/qemu-options.hx b/qemu-options.hx +index 0f26f7dad7..74d335e4c3 100644 +--- a/qemu-options.hx ++++ b/qemu-options.hx +@@ -277,6 +277,16 @@ SRST + + -smp 16,sockets=2,dies=2,cores=2,threads=2,maxcpus=16 + ++ The following sub-option defines a CPU topology hierarchy (2 sockets ++ totally on the machine, 2 clusters per socket, 2 cores per cluster, ++ 2 threads per core) for ARM virt machines which support sockets/clusters ++ /cores/threads. Some members of the option can be omitted but their values ++ will be automatically computed: ++ ++ :: ++ ++ -smp 16,sockets=2,clusters=2,cores=2,threads=2,maxcpus=16 ++ + Historically preference was given to the coarsest topology parameters + when computing missing values (ie sockets preferred over cores, which + were preferred over threads), however, this behaviour is considered +-- +2.27.0 + -- Gitee From 1c523e3f5270251aeb70161c0e404271f6c0756d Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Fri, 7 Jan 2022 16:32:28 +0800 Subject: [PATCH 16/54] hw/arm/virt: Support cluster level in DT cpu-map Support one cluster level between core and physical package in the cpu-map of Arm/virt devicetree. This is also consistent with Linux Doc "Documentation/devicetree/bindings/cpu/cpu-topology.txt". Signed-off-by: Yanan Wang Reviewed-by: Andrew Jones Message-id: 20220107083232.16256-3-wangyanan55@huawei.com Signed-off-by: Peter Maydell --- ...-Support-cluster-level-in-DT-cpu-map.patch | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 hw-arm-virt-Support-cluster-level-in-DT-cpu-map.patch diff --git a/hw-arm-virt-Support-cluster-level-in-DT-cpu-map.patch b/hw-arm-virt-Support-cluster-level-in-DT-cpu-map.patch new file mode 100644 index 0000000..11e0e01 --- /dev/null +++ b/hw-arm-virt-Support-cluster-level-in-DT-cpu-map.patch @@ -0,0 +1,57 @@ +From 38d9ae59b9344f13198e6b4de03b04787bd6b89d Mon Sep 17 00:00:00 2001 +From: Yanan Wang +Date: Fri, 7 Jan 2022 16:32:28 +0800 +Subject: [PATCH] hw/arm/virt: Support cluster level in DT cpu-map + +Support one cluster level between core and physical package in the +cpu-map of Arm/virt devicetree. This is also consistent with Linux +Doc "Documentation/devicetree/bindings/cpu/cpu-topology.txt". + +Signed-off-by: Yanan Wang +Reviewed-by: Andrew Jones +Message-id: 20220107083232.16256-3-wangyanan55@huawei.com +Signed-off-by: Peter Maydell +--- + hw/arm/virt.c | 15 ++++++++------- + 1 file changed, 8 insertions(+), 7 deletions(-) + +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index 6ca9cbe2cf..ddcb73f714 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -434,9 +434,8 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms) + * can contain several layers of clustering within a single physical + * package and cluster nodes can be contained in parent cluster nodes. + * +- * Given that cluster is not yet supported in the vCPU topology, +- * we currently generate one cluster node within each socket node +- * by default. ++ * Note: currently we only support one layer of clustering within ++ * each physical package. + */ + qemu_fdt_add_subnode(ms->fdt, "/cpus/cpu-map"); + +@@ -446,14 +445,16 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms) + + if (ms->smp.threads > 1) { + map_path = g_strdup_printf( +- "/cpus/cpu-map/socket%d/cluster0/core%d/thread%d", +- cpu / (ms->smp.cores * ms->smp.threads), ++ "/cpus/cpu-map/socket%d/cluster%d/core%d/thread%d", ++ cpu / (ms->smp.clusters * ms->smp.cores * ms->smp.threads), ++ (cpu / (ms->smp.cores * ms->smp.threads)) % ms->smp.clusters, + (cpu / ms->smp.threads) % ms->smp.cores, + cpu % ms->smp.threads); + } else { + map_path = g_strdup_printf( +- "/cpus/cpu-map/socket%d/cluster0/core%d", +- cpu / ms->smp.cores, ++ "/cpus/cpu-map/socket%d/cluster%d/core%d", ++ cpu / (ms->smp.clusters * ms->smp.cores), ++ (cpu / ms->smp.cores) % ms->smp.clusters, + cpu % ms->smp.cores); + } + qemu_fdt_add_path(ms->fdt, map_path); +-- +2.27.0 + -- Gitee From 06075305df9daff8176d9d6d1fa480200edc7b62 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Fri, 7 Jan 2022 16:32:29 +0800 Subject: [PATCH 17/54] hw/acpi/aml-build: Improve scalability of PPTT generation Use g_queue APIs to reduce the nested loops and code indentation with the processor hierarchy levels increasing. Consenquently, it's more scalable to add new topology level to build_pptt. No functional change intended. Signed-off-by: Yanan Wang Reviewed-by: Andrew Jones Message-id: 20220107083232.16256-4-wangyanan55@huawei.com Signed-off-by: Peter Maydell --- ...d-Improve-scalability-of-PPTT-genera.patch | 112 ++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 hw-acpi-aml-build-Improve-scalability-of-PPTT-genera.patch diff --git a/hw-acpi-aml-build-Improve-scalability-of-PPTT-genera.patch b/hw-acpi-aml-build-Improve-scalability-of-PPTT-genera.patch new file mode 100644 index 0000000..0ef4217 --- /dev/null +++ b/hw-acpi-aml-build-Improve-scalability-of-PPTT-genera.patch @@ -0,0 +1,112 @@ +From 66c935b435d90ef9c1ae4446c5edc07cbd8ba0ed Mon Sep 17 00:00:00 2001 +From: Yanan Wang +Date: Fri, 7 Jan 2022 16:32:29 +0800 +Subject: [PATCH] hw/acpi/aml-build: Improve scalability of PPTT generation + +Use g_queue APIs to reduce the nested loops and code indentation +with the processor hierarchy levels increasing. Consenquently, +it's more scalable to add new topology level to build_pptt. + +No functional change intended. + +Signed-off-by: Yanan Wang +Reviewed-by: Andrew Jones +Message-id: 20220107083232.16256-4-wangyanan55@huawei.com +Signed-off-by: Peter Maydell +--- + hw/acpi/aml-build.c | 50 +++++++++++++++++++++++++++++---------------- + 1 file changed, 32 insertions(+), 18 deletions(-) + +diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c +index b3b3310df3..6aaedca2e5 100644 +--- a/hw/acpi/aml-build.c ++++ b/hw/acpi/aml-build.c +@@ -2001,7 +2001,10 @@ static void build_processor_hierarchy_node(GArray *tbl, uint32_t flags, + void build_pptt(GArray *table_data, BIOSLinker *linker, MachineState *ms, + const char *oem_id, const char *oem_table_id) + { +- int pptt_start = table_data->len; ++ GQueue *list = g_queue_new(); ++ guint pptt_start = table_data->len; ++ guint parent_offset; ++ guint length, i; + int uid = 0; + int socket; + AcpiTable table = { .sig = "PPTT", .rev = 2, +@@ -2010,9 +2013,8 @@ void build_pptt(GArray *table_data, BIOSLinker *linker, MachineState *ms, + acpi_table_begin(&table, table_data); + + for (socket = 0; socket < ms->smp.sockets; socket++) { +- uint32_t socket_offset = table_data->len - pptt_start; +- int core; +- ++ g_queue_push_tail(list, ++ GUINT_TO_POINTER(table_data->len - pptt_start)); + build_processor_hierarchy_node( + table_data, + /* +@@ -2021,35 +2023,47 @@ void build_pptt(GArray *table_data, BIOSLinker *linker, MachineState *ms, + */ + (1 << 0), + 0, socket, NULL, 0); ++ } + +- for (core = 0; core < ms->smp.cores; core++) { +- uint32_t core_offset = table_data->len - pptt_start; +- int thread; ++ length = g_queue_get_length(list); ++ for (i = 0; i < length; i++) { ++ int core; + ++ parent_offset = GPOINTER_TO_UINT(g_queue_pop_head(list)); ++ for (core = 0; core < ms->smp.cores; core++) { + if (ms->smp.threads > 1) { ++ g_queue_push_tail(list, ++ GUINT_TO_POINTER(table_data->len - pptt_start)); + build_processor_hierarchy_node( + table_data, + (0 << 0), /* not a physical package */ +- socket_offset, core, NULL, 0); +- +- for (thread = 0; thread < ms->smp.threads; thread++) { +- build_processor_hierarchy_node( +- table_data, +- (1 << 1) | /* ACPI Processor ID valid */ +- (1 << 2) | /* Processor is a Thread */ +- (1 << 3), /* Node is a Leaf */ +- core_offset, uid++, NULL, 0); +- } ++ parent_offset, core, NULL, 0); + } else { + build_processor_hierarchy_node( + table_data, + (1 << 1) | /* ACPI Processor ID valid */ + (1 << 3), /* Node is a Leaf */ +- socket_offset, uid++, NULL, 0); ++ parent_offset, uid++, NULL, 0); + } + } + } + ++ length = g_queue_get_length(list); ++ for (i = 0; i < length; i++) { ++ int thread; ++ ++ parent_offset = GPOINTER_TO_UINT(g_queue_pop_head(list)); ++ for (thread = 0; thread < ms->smp.threads; thread++) { ++ build_processor_hierarchy_node( ++ table_data, ++ (1 << 1) | /* ACPI Processor ID valid */ ++ (1 << 2) | /* Processor is a Thread */ ++ (1 << 3), /* Node is a Leaf */ ++ parent_offset, uid++, NULL, 0); ++ } ++ } ++ ++ g_queue_free(list); + acpi_table_end(linker, &table); + } + +-- +2.27.0 + -- Gitee From 46ad36d1ede2fd62c62ce03c0a6c3f240b6baac2 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Fri, 7 Jan 2022 16:32:30 +0800 Subject: [PATCH 18/54] tests/acpi/bios-tables-test: Allow changes to virt/PPTT file List test/data/acpi/virt/PPTT as the expected files allowed to be changed in tests/qtest/bios-tables-test-allowed-diff.h Signed-off-by: Yanan Wang Acked-by: Ani Sinha Message-id: 20220107083232.16256-5-wangyanan55@huawei.com Signed-off-by: Peter Maydell --- ...tables-test-Allow-changes-to-virt-PP.patch | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 tests-acpi-bios-tables-test-Allow-changes-to-virt-PP.patch diff --git a/tests-acpi-bios-tables-test-Allow-changes-to-virt-PP.patch b/tests-acpi-bios-tables-test-Allow-changes-to-virt-PP.patch new file mode 100644 index 0000000..6a29c21 --- /dev/null +++ b/tests-acpi-bios-tables-test-Allow-changes-to-virt-PP.patch @@ -0,0 +1,26 @@ +From 225034a72c803b8e3819cec22bc6fb8bfc9e7366 Mon Sep 17 00:00:00 2001 +From: Yanan Wang +Date: Fri, 7 Jan 2022 16:32:30 +0800 +Subject: [PATCH] tests/acpi/bios-tables-test: Allow changes to virt/PPTT file + +List test/data/acpi/virt/PPTT as the expected files allowed to +be changed in tests/qtest/bios-tables-test-allowed-diff.h + +Signed-off-by: Yanan Wang +Acked-by: Ani Sinha +Message-id: 20220107083232.16256-5-wangyanan55@huawei.com +Signed-off-by: Peter Maydell +--- + tests/qtest/bios-tables-test-allowed-diff.h | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h +index dfb8523c8b..cb143a55a6 100644 +--- a/tests/qtest/bios-tables-test-allowed-diff.h ++++ b/tests/qtest/bios-tables-test-allowed-diff.h +@@ -1 +1,2 @@ + /* List of comma-separated changed AML files to ignore */ ++"tests/data/acpi/virt/PPTT", +-- +2.27.0 + -- Gitee From a14f4012f98fbe01f0a08307601d85babde4bd4e Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Fri, 7 Jan 2022 16:32:31 +0800 Subject: [PATCH 19/54] hw/acpi/aml-build: Support cluster level in PPTT generation Support CPU cluster topology level in generation of ACPI Processor Properties Topology Table (PPTT). Signed-off-by: Yanan Wang Reviewed-by: Andrew Jones Message-id: 20220107083232.16256-6-wangyanan55@huawei.com Signed-off-by: Peter Maydell --- ...d-Support-cluster-level-in-PPTT-gene.patch | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 hw-acpi-aml-build-Support-cluster-level-in-PPTT-gene.patch diff --git a/hw-acpi-aml-build-Support-cluster-level-in-PPTT-gene.patch b/hw-acpi-aml-build-Support-cluster-level-in-PPTT-gene.patch new file mode 100644 index 0000000..3b22b26 --- /dev/null +++ b/hw-acpi-aml-build-Support-cluster-level-in-PPTT-gene.patch @@ -0,0 +1,55 @@ +From 9c16924ba0a77c34246b69e8b1faee219f266445 Mon Sep 17 00:00:00 2001 +From: Yanan Wang +Date: Fri, 7 Jan 2022 16:32:31 +0800 +Subject: [PATCH] hw/acpi/aml-build: Support cluster level in PPTT generation + +Support CPU cluster topology level in generation of ACPI +Processor Properties Topology Table (PPTT). + +Signed-off-by: Yanan Wang +Reviewed-by: Andrew Jones +Message-id: 20220107083232.16256-6-wangyanan55@huawei.com +Signed-off-by: Peter Maydell +--- + hw/acpi/aml-build.c | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c +index 6aaedca2e5..bb2cad63b5 100644 +--- a/hw/acpi/aml-build.c ++++ b/hw/acpi/aml-build.c +@@ -2001,6 +2001,7 @@ static void build_processor_hierarchy_node(GArray *tbl, uint32_t flags, + void build_pptt(GArray *table_data, BIOSLinker *linker, MachineState *ms, + const char *oem_id, const char *oem_table_id) + { ++ MachineClass *mc = MACHINE_GET_CLASS(ms); + GQueue *list = g_queue_new(); + guint pptt_start = table_data->len; + guint parent_offset; +@@ -2025,6 +2026,23 @@ void build_pptt(GArray *table_data, BIOSLinker *linker, MachineState *ms, + 0, socket, NULL, 0); + } + ++ if (mc->smp_props.clusters_supported) { ++ length = g_queue_get_length(list); ++ for (i = 0; i < length; i++) { ++ int cluster; ++ ++ parent_offset = GPOINTER_TO_UINT(g_queue_pop_head(list)); ++ for (cluster = 0; cluster < ms->smp.clusters; cluster++) { ++ g_queue_push_tail(list, ++ GUINT_TO_POINTER(table_data->len - pptt_start)); ++ build_processor_hierarchy_node( ++ table_data, ++ (0 << 0), /* not a physical package */ ++ parent_offset, cluster, NULL, 0); ++ } ++ } ++ } ++ + length = g_queue_get_length(list); + for (i = 0; i < length; i++) { + int core; +-- +2.27.0 + -- Gitee From 8e41f70e9422f7389eef7835805da44de8c0eb94 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Fri, 7 Jan 2022 16:32:32 +0800 Subject: [PATCH 20/54] tests/acpi/bios-table-test: Update expected virt/PPTT file Run ./tests/data/acpi/rebuild-expected-aml.sh from build directory to update PPTT binary. Also empty bios-tables-test-allowed-diff.h. The disassembled differences between actual and expected PPTT: /* * Intel ACPI Component Architecture * AML/ASL+ Disassembler version 20200528 (64-bit version) * Copyright (c) 2000 - 2020 Intel Corporation * - * Disassembly of tests/data/acpi/virt/PPTT, Tue Jan 4 12:51:11 2022 + * Disassembly of /tmp/aml-2ZGOF1, Tue Jan 4 12:51:11 2022 * * ACPI Data Table [PPTT] * * Format: [HexOffset DecimalOffset ByteLength] FieldName : FieldValue */ [000h 0000 4] Signature : "PPTT" [Processor Properties Topology Table] -[004h 0004 4] Table Length : 0000004C +[004h 0004 4] Table Length : 00000060 [008h 0008 1] Revision : 02 -[009h 0009 1] Checksum : A8 +[009h 0009 1] Checksum : 48 [00Ah 0010 6] Oem ID : "BOCHS " [010h 0016 8] Oem Table ID : "BXPC " [018h 0024 4] Oem Revision : 00000001 [01Ch 0028 4] Asl Compiler ID : "BXPC" [020h 0032 4] Asl Compiler Revision : 00000001 [024h 0036 1] Subtable Type : 00 [Processor Hierarchy Node] [025h 0037 1] Length : 14 [026h 0038 2] Reserved : 0000 [028h 0040 4] Flags (decoded below) : 00000001 Physical package : 1 ACPI Processor ID valid : 0 Processor is a thread : 0 Node is a leaf : 0 Identical Implementation : 0 [02Ch 0044 4] Parent : 00000000 [030h 0048 4] ACPI Processor ID : 00000000 [034h 0052 4] Private Resource Number : 00000000 [038h 0056 1] Subtable Type : 00 [Processor Hierarchy Node] [039h 0057 1] Length : 14 [03Ah 0058 2] Reserved : 0000 -[03Ch 0060 4] Flags (decoded below) : 0000000A +[03Ch 0060 4] Flags (decoded below) : 00000000 Physical package : 0 - ACPI Processor ID valid : 1 + ACPI Processor ID valid : 0 Processor is a thread : 0 - Node is a leaf : 1 + Node is a leaf : 0 Identical Implementation : 0 [040h 0064 4] Parent : 00000024 [044h 0068 4] ACPI Processor ID : 00000000 [048h 0072 4] Private Resource Number : 00000000 -Raw Table Data: Length 76 (0x4C) +[04Ch 0076 1] Subtable Type : 00 [Processor Hierarchy Node] +[04Dh 0077 1] Length : 14 +[04Eh 0078 2] Reserved : 0000 +[050h 0080 4] Flags (decoded below) : 0000000A + Physical package : 0 + ACPI Processor ID valid : 1 + Processor is a thread : 0 + Node is a leaf : 1 + Identical Implementation : 0 +[054h 0084 4] Parent : 00000038 +[058h 0088 4] ACPI Processor ID : 00000000 +[05Ch 0092 4] Private Resource Number : 00000000 + +Raw Table Data: Length 96 (0x60) - 0000: 50 50 54 54 4C 00 00 00 02 A8 42 4F 43 48 53 20 // PPTTL.....BOCHS + 0000: 50 50 54 54 60 00 00 00 02 48 42 4F 43 48 53 20 // PPTT`....HBOCHS 0010: 42 58 50 43 20 20 20 20 01 00 00 00 42 58 50 43 // BXPC ....BXPC 0020: 01 00 00 00 00 14 00 00 01 00 00 00 00 00 00 00 // ................ - 0030: 00 00 00 00 00 00 00 00 00 14 00 00 0A 00 00 00 // ................ - 0040: 24 00 00 00 00 00 00 00 00 00 00 00 // $........... + 0030: 00 00 00 00 00 00 00 00 00 14 00 00 00 00 00 00 // ................ + 0040: 24 00 00 00 00 00 00 00 00 00 00 00 00 14 00 00 // $............... + 0050: 0A 00 00 00 38 00 00 00 00 00 00 00 00 00 00 00 // ....8........... Signed-off-by: Yanan Wang Reviewed-by: Ani Sinha Message-id: 20220107083232.16256-7-wangyanan55@huawei.com Signed-off-by: Peter Maydell --- ...table-test-Update-expected-virt-PPTT.patch | 118 ++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 tests-acpi-bios-table-test-Update-expected-virt-PPTT.patch diff --git a/tests-acpi-bios-table-test-Update-expected-virt-PPTT.patch b/tests-acpi-bios-table-test-Update-expected-virt-PPTT.patch new file mode 100644 index 0000000..40a0be9 --- /dev/null +++ b/tests-acpi-bios-table-test-Update-expected-virt-PPTT.patch @@ -0,0 +1,118 @@ +From 6f89f06e686a61acf681038ac06732facc6e7b93 Mon Sep 17 00:00:00 2001 +From: Yanan Wang +Date: Fri, 7 Jan 2022 16:32:32 +0800 +Subject: [PATCH] tests/acpi/bios-table-test: Update expected virt/PPTT file + +Run ./tests/data/acpi/rebuild-expected-aml.sh from build directory +to update PPTT binary. Also empty bios-tables-test-allowed-diff.h. + +The disassembled differences between actual and expected PPTT: + + /* + * Intel ACPI Component Architecture + * AML/ASL+ Disassembler version 20200528 (64-bit version) + * Copyright (c) 2000 - 2020 Intel Corporation + * +- * Disassembly of tests/data/acpi/virt/PPTT, Tue Jan 4 12:51:11 2022 ++ * Disassembly of /tmp/aml-2ZGOF1, Tue Jan 4 12:51:11 2022 + * + * ACPI Data Table [PPTT] + * + * Format: [HexOffset DecimalOffset ByteLength] FieldName : FieldValue + */ + + [000h 0000 4] Signature : "PPTT" [Processor Properties Topology Table] +-[004h 0004 4] Table Length : 0000004C ++[004h 0004 4] Table Length : 00000060 + [008h 0008 1] Revision : 02 +-[009h 0009 1] Checksum : A8 ++[009h 0009 1] Checksum : 48 + [00Ah 0010 6] Oem ID : "BOCHS " + [010h 0016 8] Oem Table ID : "BXPC " + [018h 0024 4] Oem Revision : 00000001 + [01Ch 0028 4] Asl Compiler ID : "BXPC" + [020h 0032 4] Asl Compiler Revision : 00000001 + + [024h 0036 1] Subtable Type : 00 [Processor Hierarchy Node] + [025h 0037 1] Length : 14 + [026h 0038 2] Reserved : 0000 + [028h 0040 4] Flags (decoded below) : 00000001 + Physical package : 1 + ACPI Processor ID valid : 0 + Processor is a thread : 0 + Node is a leaf : 0 + Identical Implementation : 0 + [02Ch 0044 4] Parent : 00000000 + [030h 0048 4] ACPI Processor ID : 00000000 + [034h 0052 4] Private Resource Number : 00000000 + + [038h 0056 1] Subtable Type : 00 [Processor Hierarchy Node] + [039h 0057 1] Length : 14 + [03Ah 0058 2] Reserved : 0000 +-[03Ch 0060 4] Flags (decoded below) : 0000000A ++[03Ch 0060 4] Flags (decoded below) : 00000000 + Physical package : 0 +- ACPI Processor ID valid : 1 ++ ACPI Processor ID valid : 0 + Processor is a thread : 0 +- Node is a leaf : 1 ++ Node is a leaf : 0 + Identical Implementation : 0 + [040h 0064 4] Parent : 00000024 + [044h 0068 4] ACPI Processor ID : 00000000 + [048h 0072 4] Private Resource Number : 00000000 + +-Raw Table Data: Length 76 (0x4C) ++[04Ch 0076 1] Subtable Type : 00 [Processor Hierarchy Node] ++[04Dh 0077 1] Length : 14 ++[04Eh 0078 2] Reserved : 0000 ++[050h 0080 4] Flags (decoded below) : 0000000A ++ Physical package : 0 ++ ACPI Processor ID valid : 1 ++ Processor is a thread : 0 ++ Node is a leaf : 1 ++ Identical Implementation : 0 ++[054h 0084 4] Parent : 00000038 ++[058h 0088 4] ACPI Processor ID : 00000000 ++[05Ch 0092 4] Private Resource Number : 00000000 ++ ++Raw Table Data: Length 96 (0x60) + +- 0000: 50 50 54 54 4C 00 00 00 02 A8 42 4F 43 48 53 20 // PPTTL.....BOCHS ++ 0000: 50 50 54 54 60 00 00 00 02 48 42 4F 43 48 53 20 // PPTT`....HBOCHS + 0010: 42 58 50 43 20 20 20 20 01 00 00 00 42 58 50 43 // BXPC ....BXPC + 0020: 01 00 00 00 00 14 00 00 01 00 00 00 00 00 00 00 // ................ +- 0030: 00 00 00 00 00 00 00 00 00 14 00 00 0A 00 00 00 // ................ +- 0040: 24 00 00 00 00 00 00 00 00 00 00 00 // $........... ++ 0030: 00 00 00 00 00 00 00 00 00 14 00 00 00 00 00 00 // ................ ++ 0040: 24 00 00 00 00 00 00 00 00 00 00 00 00 14 00 00 // $............... ++ 0050: 0A 00 00 00 38 00 00 00 00 00 00 00 00 00 00 00 // ....8........... + +Signed-off-by: Yanan Wang +Reviewed-by: Ani Sinha +Message-id: 20220107083232.16256-7-wangyanan55@huawei.com +Signed-off-by: Peter Maydell +--- + tests/data/acpi/virt/PPTT | Bin 76 -> 96 bytes + tests/qtest/bios-tables-test-allowed-diff.h | 1 - + 2 files changed, 1 deletion(-) + +diff --git a/tests/data/acpi/virt/PPTT b/tests/data/acpi/virt/PPTT +index 7a1258ecf123555b24462c98ccbb76b4ac1d0c2b..f56ea63b369a604877374ad696c396e796ab1c83 100644 +GIT binary patch +delta 53 +pcmeZC;0g!`2}xjJU|{l?$YrDgWH5jU5Ca567#O&Klm(arApowi1QY-O + +delta 32 +fcmYfB;R*-{3GrcIU|?D?k;`ae01J-_kOKn%ZFdCM + +diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h +index cb143a55a6..dfb8523c8b 100644 +--- a/tests/qtest/bios-tables-test-allowed-diff.h ++++ b/tests/qtest/bios-tables-test-allowed-diff.h +@@ -1,2 +1 @@ + /* List of comma-separated changed AML files to ignore */ +-"tests/data/acpi/virt/PPTT", +-- +2.27.0 + -- Gitee From 465cafbfa038c3fb475113677996d00584692c03 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Fri, 7 Jan 2022 14:38:44 +0100 Subject: [PATCH 21/54] softmmu/device_tree: Silence compiler warning with --enable-sanitizers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If I configure my build with --enable-sanitizers, my GCC (v8.5.0) complains: .../softmmu/device_tree.c: In function ‘qemu_fdt_add_path’: .../softmmu/device_tree.c:560:18: error: ‘retval’ may be used uninitialized in this function [-Werror=maybe-uninitialized] int namelen, retval; ^~~~~~ It's a false warning since the while loop is always executed at least once (p has to be non-NULL, otherwise the derefence in the if-statement earlier will crash). Thus let's switch to a do-while loop here instead to make the compiler happy in all cases. Signed-off-by: Thomas Huth Reviewed-by: Andrew Jones Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Reviewed-by: Alistair Francis Reviewed-by: Yanan Wang Message-id: 20220107133844.145039-1-thuth@redhat.com Signed-off-by: Alistair Francis --- ...ree-Silence-compiler-warning-with-en.patch | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 softmmu-device_tree-Silence-compiler-warning-with-en.patch diff --git a/softmmu-device_tree-Silence-compiler-warning-with-en.patch b/softmmu-device_tree-Silence-compiler-warning-with-en.patch new file mode 100644 index 0000000..3e06882 --- /dev/null +++ b/softmmu-device_tree-Silence-compiler-warning-with-en.patch @@ -0,0 +1,60 @@ +From ecc0eb93e8856321ad940a85970f0db14ab9f146 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 7 Jan 2022 14:38:44 +0100 +Subject: [PATCH] softmmu/device_tree: Silence compiler warning with + --enable-sanitizers +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +If I configure my build with --enable-sanitizers, my GCC (v8.5.0) +complains: + +.../softmmu/device_tree.c: In function ‘qemu_fdt_add_path’: +.../softmmu/device_tree.c:560:18: error: ‘retval’ may be used uninitialized + in this function [-Werror=maybe-uninitialized] + int namelen, retval; + ^~~~~~ + +It's a false warning since the while loop is always executed at least +once (p has to be non-NULL, otherwise the derefence in the if-statement +earlier will crash). Thus let's switch to a do-while loop here instead +to make the compiler happy in all cases. + +Signed-off-by: Thomas Huth +Reviewed-by: Andrew Jones +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Richard Henderson +Reviewed-by: Alistair Francis +Reviewed-by: Yanan Wang +Message-id: 20220107133844.145039-1-thuth@redhat.com +Signed-off-by: Alistair Francis +--- + softmmu/device_tree.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/softmmu/device_tree.c b/softmmu/device_tree.c +index 3965c834ca..9e96f5ecd5 100644 +--- a/softmmu/device_tree.c ++++ b/softmmu/device_tree.c +@@ -564,7 +564,7 @@ int qemu_fdt_add_path(void *fdt, const char *path) + return -1; + } + +- while (p) { ++ do { + name = p + 1; + p = strchr(name, '/'); + namelen = p != NULL ? p - name : strlen(name); +@@ -584,7 +584,7 @@ int qemu_fdt_add_path(void *fdt, const char *path) + } + + parent = retval; +- } ++ } while (p); + + return retval; + } +-- +2.27.0 + -- Gitee From 987c79736a895b225d58b95f3602af7670bc1bc5 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Tue, 11 Jan 2022 11:27:58 +0800 Subject: [PATCH 22/54] softmmu/device_tree: Remove redundant pointer assignment The pointer assignment "const char *p = path;" in function qemu_fdt_add_path is unnecessary. Let's remove it and just use the "path" passed in. No functional change. Suggested-by: Richard Henderson Signed-off-by: Yanan Wang Reviewed-by: Andrew Jones Reviewed-by: Alistair Francis Reviewed-by: Thomas Huth Message-id: 20220111032758.27804-1-wangyanan55@huawei.com Signed-off-by: Alistair Francis --- ...ree-Remove-redundant-pointer-assignm.patch | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 softmmu-device_tree-Remove-redundant-pointer-assignm.patch diff --git a/softmmu-device_tree-Remove-redundant-pointer-assignm.patch b/softmmu-device_tree-Remove-redundant-pointer-assignm.patch new file mode 100644 index 0000000..232d7d1 --- /dev/null +++ b/softmmu-device_tree-Remove-redundant-pointer-assignm.patch @@ -0,0 +1,57 @@ +From ebf1ac6c0ead3d6fbc32466028c286588333c1ea Mon Sep 17 00:00:00 2001 +From: Yanan Wang +Date: Tue, 11 Jan 2022 11:27:58 +0800 +Subject: [PATCH] softmmu/device_tree: Remove redundant pointer assignment + +The pointer assignment "const char *p = path;" in function +qemu_fdt_add_path is unnecessary. Let's remove it and just +use the "path" passed in. No functional change. + +Suggested-by: Richard Henderson +Signed-off-by: Yanan Wang +Reviewed-by: Andrew Jones +Reviewed-by: Alistair Francis +Reviewed-by: Thomas Huth +Message-id: 20220111032758.27804-1-wangyanan55@huawei.com +Signed-off-by: Alistair Francis +--- + softmmu/device_tree.c | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +diff --git a/softmmu/device_tree.c b/softmmu/device_tree.c +index 9e96f5ecd5..8897c79ea4 100644 +--- a/softmmu/device_tree.c ++++ b/softmmu/device_tree.c +@@ -556,7 +556,6 @@ int qemu_fdt_add_subnode(void *fdt, const char *name) + int qemu_fdt_add_path(void *fdt, const char *path) + { + const char *name; +- const char *p = path; + int namelen, retval; + int parent = 0; + +@@ -565,9 +564,9 @@ int qemu_fdt_add_path(void *fdt, const char *path) + } + + do { +- name = p + 1; +- p = strchr(name, '/'); +- namelen = p != NULL ? p - name : strlen(name); ++ name = path + 1; ++ path = strchr(name, '/'); ++ namelen = path != NULL ? path - name : strlen(name); + + retval = fdt_subnode_offset_namelen(fdt, parent, name, namelen); + if (retval < 0 && retval != -FDT_ERR_NOTFOUND) { +@@ -584,7 +583,7 @@ int qemu_fdt_add_path(void *fdt, const char *path) + } + + parent = retval; +- } while (p); ++ } while (path); + + return retval; + } +-- +2.27.0 + -- Gitee From b796e0ddb0ea57e77c9c3fe7c3fbc0545aee03e7 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Tue, 8 Feb 2022 11:31:15 +0800 Subject: [PATCH 23/54] hw/arm64: add vcpu cache info support Support VCPU Cache info by dtb and PPTT table, including L1, L2 and L3 Cache. Signed-off-by: zhanghailiang Signed-off-by: Honghao Signed-off-by: Ying Fang Signed-off-by: Yanan Wang --- hw-arm64-add-vcpu-cache-info-support.patch | 364 +++++++++++++++++++++ 1 file changed, 364 insertions(+) create mode 100644 hw-arm64-add-vcpu-cache-info-support.patch diff --git a/hw-arm64-add-vcpu-cache-info-support.patch b/hw-arm64-add-vcpu-cache-info-support.patch new file mode 100644 index 0000000..30ddfc5 --- /dev/null +++ b/hw-arm64-add-vcpu-cache-info-support.patch @@ -0,0 +1,364 @@ +From c5cd762bb7513b6df07e26f4eb619dccbd1918b7 Mon Sep 17 00:00:00 2001 +From: Ying Fang +Date: Tue, 8 Feb 2022 11:31:15 +0800 +Subject: [PATCH] hw/arm64: add vcpu cache info support + +Support VCPU Cache info by dtb and PPTT table, including L1, L2 and L3 Cache. + +Signed-off-by: zhanghailiang +Signed-off-by: Honghao +Signed-off-by: Ying Fang +Signed-off-by: Yanan Wang +--- + hw/acpi/aml-build.c | 158 ++++++++++++++++++++++++++++++++++++ + hw/arm/virt.c | 72 ++++++++++++++++ + include/hw/acpi/aml-build.h | 47 +++++++++++ + tests/data/acpi/virt/PPTT | Bin 96 -> 208 bytes + 4 files changed, 277 insertions(+) + +diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c +index bb2cad63b5..bebf49622b 100644 +--- a/hw/acpi/aml-build.c ++++ b/hw/acpi/aml-build.c +@@ -1994,6 +1994,163 @@ static void build_processor_hierarchy_node(GArray *tbl, uint32_t flags, + } + } + ++#ifdef __aarch64__ ++/* ++ * ACPI spec, Revision 6.3 ++ * 5.2.29.2 Cache Type Structure (Type 1) ++ */ ++static void build_cache_hierarchy_node(GArray *tbl, uint32_t next_level, ++ uint32_t cache_type) ++{ ++ build_append_byte(tbl, 1); ++ build_append_byte(tbl, 24); ++ build_append_int_noprefix(tbl, 0, 2); ++ build_append_int_noprefix(tbl, 127, 4); ++ build_append_int_noprefix(tbl, next_level, 4); ++ ++ switch (cache_type) { ++ case ARM_L1D_CACHE: /* L1 dcache info */ ++ build_append_int_noprefix(tbl, ARM_L1DCACHE_SIZE, 4); ++ build_append_int_noprefix(tbl, ARM_L1DCACHE_SETS, 4); ++ build_append_byte(tbl, ARM_L1DCACHE_ASSOCIATIVITY); ++ build_append_byte(tbl, ARM_L1DCACHE_ATTRIBUTES); ++ build_append_int_noprefix(tbl, ARM_L1DCACHE_LINE_SIZE, 2); ++ break; ++ case ARM_L1I_CACHE: /* L1 icache info */ ++ build_append_int_noprefix(tbl, ARM_L1ICACHE_SIZE, 4); ++ build_append_int_noprefix(tbl, ARM_L1ICACHE_SETS, 4); ++ build_append_byte(tbl, ARM_L1ICACHE_ASSOCIATIVITY); ++ build_append_byte(tbl, ARM_L1ICACHE_ATTRIBUTES); ++ build_append_int_noprefix(tbl, ARM_L1ICACHE_LINE_SIZE, 2); ++ break; ++ case ARM_L2_CACHE: /* L2 cache info */ ++ build_append_int_noprefix(tbl, ARM_L2CACHE_SIZE, 4); ++ build_append_int_noprefix(tbl, ARM_L2CACHE_SETS, 4); ++ build_append_byte(tbl, ARM_L2CACHE_ASSOCIATIVITY); ++ build_append_byte(tbl, ARM_L2CACHE_ATTRIBUTES); ++ build_append_int_noprefix(tbl, ARM_L2CACHE_LINE_SIZE, 2); ++ break; ++ case ARM_L3_CACHE: /* L3 cache info */ ++ build_append_int_noprefix(tbl, ARM_L3CACHE_SIZE, 4); ++ build_append_int_noprefix(tbl, ARM_L3CACHE_SETS, 4); ++ build_append_byte(tbl, ARM_L3CACHE_ASSOCIATIVITY); ++ build_append_byte(tbl, ARM_L3CACHE_ATTRIBUTES); ++ build_append_int_noprefix(tbl, ARM_L3CACHE_LINE_SIZE, 2); ++ break; ++ default: ++ build_append_int_noprefix(tbl, 0, 4); ++ build_append_int_noprefix(tbl, 0, 4); ++ build_append_byte(tbl, 0); ++ build_append_byte(tbl, 0); ++ build_append_int_noprefix(tbl, 0, 2); ++ } ++} ++ ++/* ++ * ACPI spec, Revision 6.3 ++ * 5.2.29 Processor Properties Topology Table (PPTT) ++ */ ++void build_pptt(GArray *table_data, BIOSLinker *linker, MachineState *ms, ++ const char *oem_id, const char *oem_table_id) ++{ ++ MachineClass *mc = MACHINE_GET_CLASS(ms); ++ GQueue *list = g_queue_new(); ++ guint pptt_start = table_data->len; ++ guint parent_offset; ++ guint length, i; ++ int uid = 0; ++ int socket; ++ AcpiTable table = { .sig = "PPTT", .rev = 2, ++ .oem_id = oem_id, .oem_table_id = oem_table_id }; ++ ++ acpi_table_begin(&table, table_data); ++ ++ for (socket = 0; socket < ms->smp.sockets; socket++) { ++ uint32_t l3_cache_offset = table_data->len - pptt_start; ++ build_cache_hierarchy_node(table_data, 0, ARM_L3_CACHE); ++ ++ g_queue_push_tail(list, ++ GUINT_TO_POINTER(table_data->len - pptt_start)); ++ build_processor_hierarchy_node( ++ table_data, ++ /* ++ * Physical package - represents the boundary ++ * of a physical package ++ */ ++ (1 << 0), ++ 0, socket, &l3_cache_offset, 1); ++ } ++ ++ if (mc->smp_props.clusters_supported) { ++ length = g_queue_get_length(list); ++ for (i = 0; i < length; i++) { ++ int cluster; ++ ++ parent_offset = GPOINTER_TO_UINT(g_queue_pop_head(list)); ++ for (cluster = 0; cluster < ms->smp.clusters; cluster++) { ++ g_queue_push_tail(list, ++ GUINT_TO_POINTER(table_data->len - pptt_start)); ++ build_processor_hierarchy_node( ++ table_data, ++ (0 << 0), /* not a physical package */ ++ parent_offset, cluster, NULL, 0); ++ } ++ } ++ } ++ ++ length = g_queue_get_length(list); ++ for (i = 0; i < length; i++) { ++ int core; ++ ++ parent_offset = GPOINTER_TO_UINT(g_queue_pop_head(list)); ++ for (core = 0; core < ms->smp.cores; core++) { ++ uint32_t priv_rsrc[3] = {}; ++ priv_rsrc[0] = table_data->len - pptt_start; /* L2 cache offset */ ++ build_cache_hierarchy_node(table_data, 0, ARM_L2_CACHE); ++ ++ priv_rsrc[1] = table_data->len - pptt_start; /* L1 dcache offset */ ++ build_cache_hierarchy_node(table_data, priv_rsrc[0], ARM_L1D_CACHE); ++ ++ priv_rsrc[2] = table_data->len - pptt_start; /* L1 icache offset */ ++ build_cache_hierarchy_node(table_data, priv_rsrc[0], ARM_L1I_CACHE); ++ ++ if (ms->smp.threads > 1) { ++ g_queue_push_tail(list, ++ GUINT_TO_POINTER(table_data->len - pptt_start)); ++ build_processor_hierarchy_node( ++ table_data, ++ (0 << 0), /* not a physical package */ ++ parent_offset, core, priv_rsrc, 3); ++ } else { ++ build_processor_hierarchy_node( ++ table_data, ++ (1 << 1) | /* ACPI Processor ID valid */ ++ (1 << 3), /* Node is a Leaf */ ++ parent_offset, uid++, priv_rsrc, 3); ++ } ++ } ++ } ++ ++ length = g_queue_get_length(list); ++ for (i = 0; i < length; i++) { ++ int thread; ++ ++ parent_offset = GPOINTER_TO_UINT(g_queue_pop_head(list)); ++ for (thread = 0; thread < ms->smp.threads; thread++) { ++ build_processor_hierarchy_node( ++ table_data, ++ (1 << 1) | /* ACPI Processor ID valid */ ++ (1 << 2) | /* Processor is a Thread */ ++ (1 << 3), /* Node is a Leaf */ ++ parent_offset, uid++, NULL, 0); ++ } ++ } ++ ++ g_queue_free(list); ++ acpi_table_end(linker, &table); ++} ++ ++#else + /* + * ACPI spec, Revision 6.3 + * 5.2.29 Processor Properties Topology Table (PPTT) +@@ -2084,6 +2241,7 @@ void build_pptt(GArray *table_data, BIOSLinker *linker, MachineState *ms, + g_queue_free(list); + acpi_table_end(linker, &table); + } ++#endif + + /* build rev1/rev3/rev5.1 FADT */ + void build_fadt(GArray *tbl, BIOSLinker *linker, const AcpiFadtData *f, +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index ddcb73f714..529c0d38b6 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -350,6 +350,72 @@ static void fdt_add_timer_nodes(const VirtMachineState *vms) + GIC_FDT_IRQ_TYPE_PPI, ARCH_TIMER_NS_EL2_IRQ, irqflags); + } + ++static void fdt_add_l3cache_nodes(const VirtMachineState *vms) ++{ ++ int i; ++ const MachineState *ms = MACHINE(vms); ++ int cpus_per_socket = ms->smp.clusters * ms->smp.cores * ms->smp.threads; ++ int sockets = (ms->smp.cpus + cpus_per_socket - 1) / cpus_per_socket; ++ ++ for (i = 0; i < sockets; i++) { ++ char *nodename = g_strdup_printf("/cpus/l3-cache%d", i); ++ ++ qemu_fdt_add_subnode(ms->fdt, nodename); ++ qemu_fdt_setprop_string(ms->fdt, nodename, "compatible", "cache"); ++ qemu_fdt_setprop_string(ms->fdt, nodename, "cache-unified", "true"); ++ qemu_fdt_setprop_cell(ms->fdt, nodename, "cache-level", 3); ++ qemu_fdt_setprop_cell(ms->fdt, nodename, "cache-size", 0x2000000); ++ qemu_fdt_setprop_cell(ms->fdt, nodename, "cache-line-size", 128); ++ qemu_fdt_setprop_cell(ms->fdt, nodename, "cache-sets", 2048); ++ qemu_fdt_setprop_cell(ms->fdt, nodename, "phandle", ++ qemu_fdt_alloc_phandle(ms->fdt)); ++ g_free(nodename); ++ } ++} ++ ++static void fdt_add_l2cache_nodes(const VirtMachineState *vms) ++{ ++ const MachineState *ms = MACHINE(vms); ++ int cpus_per_socket = ms->smp.clusters * ms->smp.cores * ms->smp.threads; ++ int cpu; ++ ++ for (cpu = 0; cpu < ms->smp.cpus; cpu++) { ++ char *next_path = g_strdup_printf("/cpus/l3-cache%d", ++ cpu / cpus_per_socket); ++ char *nodename = g_strdup_printf("/cpus/l2-cache%d", cpu); ++ ++ qemu_fdt_add_subnode(ms->fdt, nodename); ++ qemu_fdt_setprop_string(ms->fdt, nodename, "compatible", "cache"); ++ qemu_fdt_setprop_cell(ms->fdt, nodename, "cache-size", 0x80000); ++ qemu_fdt_setprop_cell(ms->fdt, nodename, "cache-line-size", 64); ++ qemu_fdt_setprop_cell(ms->fdt, nodename, "cache-sets", 1024); ++ qemu_fdt_setprop_phandle(ms->fdt, nodename, "next-level-cache", ++ next_path); ++ qemu_fdt_setprop_cell(ms->fdt, nodename, "phandle", ++ qemu_fdt_alloc_phandle(ms->fdt)); ++ ++ g_free(next_path); ++ g_free(nodename); ++ } ++} ++ ++static void fdt_add_l1cache_prop(const VirtMachineState *vms, ++ char *nodename, int cpu) ++{ ++ const MachineState *ms = MACHINE(vms); ++ char *cachename = g_strdup_printf("/cpus/l2-cache%d", cpu); ++ ++ qemu_fdt_setprop_cell(ms->fdt, nodename, "d-cache-size", 0x10000); ++ qemu_fdt_setprop_cell(ms->fdt, nodename, "d-cache-line-size", 64); ++ qemu_fdt_setprop_cell(ms->fdt, nodename, "d-cache-sets", 256); ++ qemu_fdt_setprop_cell(ms->fdt, nodename, "i-cache-size", 0x10000); ++ qemu_fdt_setprop_cell(ms->fdt, nodename, "i-cache-line-size", 64); ++ qemu_fdt_setprop_cell(ms->fdt, nodename, "i-cache-sets", 256); ++ qemu_fdt_setprop_phandle(ms->fdt, nodename, "next-level-cache", ++ cachename); ++ g_free(cachename); ++} ++ + static void fdt_add_cpu_nodes(const VirtMachineState *vms) + { + int cpu; +@@ -384,6 +450,11 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms) + qemu_fdt_setprop_cell(ms->fdt, "/cpus", "#address-cells", addr_cells); + qemu_fdt_setprop_cell(ms->fdt, "/cpus", "#size-cells", 0x0); + ++ if (!vmc->no_cpu_topology) { ++ fdt_add_l3cache_nodes(vms); ++ fdt_add_l2cache_nodes(vms); ++ } ++ + for (cpu = smp_cpus - 1; cpu >= 0; cpu--) { + char *nodename = g_strdup_printf("/cpus/cpu@%d", cpu); + ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(cpu)); +@@ -413,6 +484,7 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms) + } + + if (!vmc->no_cpu_topology) { ++ fdt_add_l1cache_prop(vms, nodename, cpu); + qemu_fdt_setprop_cell(ms->fdt, nodename, "phandle", + qemu_fdt_alloc_phandle(ms->fdt)); + } +diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h +index 8346003a22..8e8ad8029e 100644 +--- a/include/hw/acpi/aml-build.h ++++ b/include/hw/acpi/aml-build.h +@@ -221,6 +221,53 @@ struct AcpiBuildTables { + BIOSLinker *linker; + } AcpiBuildTables; + ++#ifdef __aarch64__ ++/* Definitions of the hardcoded cache info*/ ++ ++typedef enum { ++ ARM_L1D_CACHE, ++ ARM_L1I_CACHE, ++ ARM_L2_CACHE, ++ ARM_L3_CACHE ++} ArmCacheType; ++ ++/* L1 data cache: */ ++#define ARM_L1DCACHE_SIZE 65536 ++#define ARM_L1DCACHE_SETS 256 ++#define ARM_L1DCACHE_ASSOCIATIVITY 4 ++#define ARM_L1DCACHE_ATTRIBUTES 2 ++#define ARM_L1DCACHE_LINE_SIZE 64 ++ ++/* L1 instruction cache: */ ++#define ARM_L1ICACHE_SIZE 65536 ++#define ARM_L1ICACHE_SETS 256 ++#define ARM_L1ICACHE_ASSOCIATIVITY 4 ++#define ARM_L1ICACHE_ATTRIBUTES 4 ++#define ARM_L1ICACHE_LINE_SIZE 64 ++ ++/* Level 2 unified cache: */ ++#define ARM_L2CACHE_SIZE 524288 ++#define ARM_L2CACHE_SETS 1024 ++#define ARM_L2CACHE_ASSOCIATIVITY 8 ++#define ARM_L2CACHE_ATTRIBUTES 10 ++#define ARM_L2CACHE_LINE_SIZE 64 ++ ++/* Level 3 unified cache: */ ++#define ARM_L3CACHE_SIZE 33554432 ++#define ARM_L3CACHE_SETS 2048 ++#define ARM_L3CACHE_ASSOCIATIVITY 15 ++#define ARM_L3CACHE_ATTRIBUTES 10 ++#define ARM_L3CACHE_LINE_SIZE 128 ++ ++struct offset_status { ++ uint32_t parent; ++ uint32_t l2_offset; ++ uint32_t l1d_offset; ++ uint32_t l1i_offset; ++}; ++ ++#endif ++ + typedef + struct CrsRangeEntry { + uint64_t base; +diff --git a/tests/data/acpi/virt/PPTT b/tests/data/acpi/virt/PPTT +index f56ea63b369a604877374ad696c396e796ab1c83..b89b2a9c71e0bc2713fc38f5de68fbc39b6302cb 100644 +GIT binary patch +literal 208 +zcmWFt2no5sz`($y>E!S15v<@85#X!<1dKp25F11@N-!|g18FE=V&Gt4;OA;!U;v7P +z1UT7A73xEDj6|3JeTfK(!%23G#4~^x046;S0RR91 + +literal 96 +zcmWFt2nk7GU|?YKaPoKd2v%^42yj*a0!E-1hz+6{L>L&rG>8oYKrs+dflv?b3 +ISs;l402v7f0RR91 + +-- +2.27.0 + -- Gitee From 00af29be99e2262844ed40148c675d2bae511c5c Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Tue, 8 Feb 2022 21:01:09 +0800 Subject: [PATCH 24/54] arm64: Add the cpufreq device to show cpufreq info to guest On ARM64 platform, cpu frequency is retrieved via ACPI CPPC. A virtual cpufreq device based on ACPI CPPC is created to present cpu frequency info to the guest. The default frequency is set to host cpu nominal frequency, which is obtained from the host CPPC sysfs. Other performance data are set to the same value, since we don't support guest performance scaling here. Performance counters are also not emulated and they simply return 1 if read, and guest should fallback to use desired performance value as the current performance. Guest kernel version above 4.18 is required to make it work. This series is backported from: https://patchwork.kernel.org/cover/11379943/ Signed-off-by: Ying Fang Signed-off-by: Yanan Wang --- ...ufreq-device-to-show-cpufreq-info-to.patch | 662 ++++++++++++++++++ 1 file changed, 662 insertions(+) create mode 100644 arm64-Add-the-cpufreq-device-to-show-cpufreq-info-to.patch diff --git a/arm64-Add-the-cpufreq-device-to-show-cpufreq-info-to.patch b/arm64-Add-the-cpufreq-device-to-show-cpufreq-info-to.patch new file mode 100644 index 0000000..851d429 --- /dev/null +++ b/arm64-Add-the-cpufreq-device-to-show-cpufreq-info-to.patch @@ -0,0 +1,662 @@ +From e7e28e79988eb671051d0d2af0eb010314c83d41 Mon Sep 17 00:00:00 2001 +From: Ying Fang +Date: Tue, 8 Feb 2022 21:01:09 +0800 +Subject: [PATCH] arm64: Add the cpufreq device to show cpufreq info to guest + +On ARM64 platform, cpu frequency is retrieved via ACPI CPPC. +A virtual cpufreq device based on ACPI CPPC is created to +present cpu frequency info to the guest. + +The default frequency is set to host cpu nominal frequency, +which is obtained from the host CPPC sysfs. Other performance +data are set to the same value, since we don't support guest +performance scaling here. + +Performance counters are also not emulated and they simply +return 1 if read, and guest should fallback to use desired +performance value as the current performance. + +Guest kernel version above 4.18 is required to make it work. + +This series is backported from: +https://patchwork.kernel.org/cover/11379943/ + +Signed-off-by: Ying Fang +Signed-off-by: Yanan Wang +--- + configs/devices/aarch64-softmmu/default.mak | 1 + + hw/acpi/aml-build.c | 22 ++ + hw/acpi/cpufreq.c | 283 ++++++++++++++++++++ + hw/acpi/meson.build | 1 + + hw/arm/virt-acpi-build.c | 77 +++++- + hw/arm/virt.c | 13 + + hw/char/Kconfig | 4 + + include/hw/acpi/acpi-defs.h | 38 +++ + include/hw/acpi/aml-build.h | 3 + + include/hw/arm/virt.h | 1 + + tests/data/acpi/virt/DSDT | Bin 5196 -> 5669 bytes + tests/data/acpi/virt/DSDT.memhp | Bin 6557 -> 7030 bytes + tests/data/acpi/virt/DSDT.numamem | Bin 5196 -> 5669 bytes + tests/data/acpi/virt/DSDT.pxb | Bin 7679 -> 8152 bytes + 14 files changed, 441 insertions(+), 2 deletions(-) + create mode 100644 hw/acpi/cpufreq.c + +diff --git a/configs/devices/aarch64-softmmu/default.mak b/configs/devices/aarch64-softmmu/default.mak +index cf43ac8da1..c7a710a0f1 100644 +--- a/configs/devices/aarch64-softmmu/default.mak ++++ b/configs/devices/aarch64-softmmu/default.mak +@@ -6,3 +6,4 @@ include ../arm-softmmu/default.mak + CONFIG_XLNX_ZYNQMP_ARM=y + CONFIG_XLNX_VERSAL=y + CONFIG_SBSA_REF=y ++CONFIG_CPUFREQ=y +diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c +index bebf49622b..c4edaafa4a 100644 +--- a/hw/acpi/aml-build.c ++++ b/hw/acpi/aml-build.c +@@ -1554,6 +1554,28 @@ Aml *aml_sleep(uint64_t msec) + return var; + } + ++/* ACPI 5.0b: 6.4.3.7 Generic Register Descriptor */ ++Aml *aml_generic_register(AmlRegionSpace rs, uint8_t reg_width, ++ uint8_t reg_offset, AmlAccessType type, uint64_t addr) ++{ ++ int i; ++ Aml *var = aml_alloc(); ++ build_append_byte(var->buf, 0x82); /* Generic Register Descriptor */ ++ build_append_byte(var->buf, 0x0C); /* Length, bits[7:0] value = 0x0C */ ++ build_append_byte(var->buf, 0); /* Length, bits[15:8] value = 0 */ ++ build_append_byte(var->buf, rs); /* Address Space ID */ ++ build_append_byte(var->buf, reg_width); /* Register Bit Width */ ++ build_append_byte(var->buf, reg_offset); /* Register Bit Offset */ ++ build_append_byte(var->buf, type); /* Access Size */ ++ ++ /* Register address */ ++ for (i = 0; i < 8; i++) { ++ build_append_byte(var->buf, extract64(addr, i * 8, 8)); ++ } ++ ++ return var; ++} ++ + static uint8_t Hex2Byte(const char *src) + { + int hi, lo; +diff --git a/hw/acpi/cpufreq.c b/hw/acpi/cpufreq.c +new file mode 100644 +index 0000000000..a84db490b3 +--- /dev/null ++++ b/hw/acpi/cpufreq.c +@@ -0,0 +1,283 @@ ++/* ++ * ACPI CPPC register device ++ * ++ * Support for showing CPU frequency in guest OS. ++ * ++ * Copyright (c) 2019 HUAWEI TECHNOLOGIES CO.,LTD. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, see . ++ */ ++ ++#include "qemu/osdep.h" ++#include "hw/sysbus.h" ++#include "chardev/char.h" ++#include "qemu/log.h" ++#include "trace.h" ++#include "qemu/option.h" ++#include "sysemu/sysemu.h" ++#include "hw/acpi/acpi-defs.h" ++#include "qemu/cutils.h" ++#include "qemu/error-report.h" ++#include "hw/boards.h" ++ ++#define TYPE_CPUFREQ "cpufreq" ++#define CPUFREQ(obj) OBJECT_CHECK(CpuhzState, (obj), TYPE_CPUFREQ) ++#define NOMINAL_FREQ_FILE "/sys/devices/system/cpu/cpu0/acpi_cppc/nominal_freq" ++#define CPU_MAX_FREQ_FILE "/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq" ++#define HZ_MAX_LENGTH 1024 ++#define MAX_SUPPORT_SPACE 0x10000 ++ ++/* ++ * Since Hi1616 will not support CPPC, we simply use its nominal frequency as ++ * the default. ++ */ ++#define DEFAULT_HZ 2400 ++ ++int cppc_regs_offset[CPPC_REG_COUNT] = { ++ [HIGHEST_PERF] = 0, ++ [NOMINAL_PERF] = 4, ++ [LOW_NON_LINEAR_PERF] = 8, ++ [LOWEST_PERF] = 12, ++ [GUARANTEED_PERF] = 16, ++ [DESIRED_PERF] = 20, ++ [MIN_PERF] = -1, ++ [MAX_PERF] = -1, ++ [PERF_REDUC_TOLERANCE] = -1, ++ [TIME_WINDOW] = -1, ++ [CTR_WRAP_TIME] = -1, ++ [REFERENCE_CTR] = 24, ++ [DELIVERED_CTR] = 32, ++ [PERF_LIMITED] = 40, ++ [ENABLE] = -1, ++ [AUTO_SEL_ENABLE] = -1, ++ [AUTO_ACT_WINDOW] = -1, ++ [ENERGY_PERF] = -1, ++ [REFERENCE_PERF] = -1, ++ [LOWEST_FREQ] = 44, ++ [NOMINAL_FREQ] = 48, ++}; ++ ++typedef struct CpuhzState { ++ SysBusDevice parent_obj; ++ ++ MemoryRegion iomem; ++ uint32_t HighestPerformance; ++ uint32_t NominalPerformance; ++ uint32_t LowestNonlinearPerformance; ++ uint32_t LowestPerformance; ++ uint32_t GuaranteedPerformance; ++ uint32_t DesiredPerformance; ++ uint64_t ReferencePerformanceCounter; ++ uint64_t DeliveredPerformanceCounter; ++ uint32_t PerformanceLimited; ++ uint32_t LowestFreq; ++ uint32_t NominalFreq; ++ uint32_t reg_size; ++} CpuhzState; ++ ++ ++static uint64_t cpufreq_read(void *opaque, hwaddr offset, unsigned size) ++{ ++ CpuhzState *s = (CpuhzState *)opaque; ++ uint64_t r; ++ uint64_t n; ++ ++ MachineState *ms = MACHINE(qdev_get_machine()); ++ unsigned int smp_cpus = ms->smp.cpus; ++ ++ if (offset >= smp_cpus * CPPC_REG_PER_CPU_STRIDE) { ++ warn_report("cpufreq_read: offset 0x%lx out of range", offset); ++ return 0; ++ } ++ ++ n = offset % CPPC_REG_PER_CPU_STRIDE; ++ switch (n) { ++ case 0: ++ r = s->HighestPerformance; ++ break; ++ case 4: ++ r = s->NominalPerformance; ++ break; ++ case 8: ++ r = s->LowestNonlinearPerformance; ++ break; ++ case 12: ++ r = s->LowestPerformance; ++ break; ++ case 16: ++ r = s->GuaranteedPerformance; ++ break; ++ case 20: ++ r = s->DesiredPerformance; ++ break; ++ /* ++ * We don't have real counters and it is hard to emulate, so always set the ++ * counter value to 1 to rely on Linux to use the DesiredPerformance value ++ * directly. ++ */ ++ case 24: ++ r = s->ReferencePerformanceCounter; ++ break; ++ /* ++ * Guest may still access the register by 32bit; add the process to ++ * eliminate unnecessary warnings. ++ */ ++ case 28: ++ r = s->ReferencePerformanceCounter >> 32; ++ break; ++ case 32: ++ r = s->DeliveredPerformanceCounter; ++ break; ++ case 36: ++ r = s->DeliveredPerformanceCounter >> 32; ++ break; ++ ++ case 40: ++ r = s->PerformanceLimited; ++ break; ++ case 44: ++ r = s->LowestFreq; ++ break; ++ case 48: ++ r = s->NominalFreq; ++ break; ++ default: ++ error_printf("cpufreq_read: Bad offset 0x%lx\n", offset); ++ r = 0; ++ break; ++ } ++ return r; ++} ++ ++static void cpufreq_write(void *opaque, hwaddr offset, ++ uint64_t value, unsigned size) ++{ ++ uint64_t n; ++ MachineState *ms = MACHINE(qdev_get_machine()); ++ unsigned int smp_cpus = ms->smp.cpus; ++ ++ if (offset >= smp_cpus * CPPC_REG_PER_CPU_STRIDE) { ++ error_printf("cpufreq_write: offset 0x%lx out of range", offset); ++ return; ++ } ++ ++ n = offset % CPPC_REG_PER_CPU_STRIDE; ++ ++ switch (n) { ++ case 20: ++ break; ++ default: ++ error_printf("cpufreq_write: Bad offset 0x%lx\n", offset); ++ } ++} ++ ++static uint32_t CPPC_Read(const char *hostpath) ++{ ++ int fd; ++ char buffer[HZ_MAX_LENGTH] = { 0 }; ++ uint64_t hz; ++ int len; ++ const char *endptr = NULL; ++ int ret; ++ ++ fd = qemu_open_old(hostpath, O_RDONLY); ++ if (fd < 0) { ++ return 0; ++ } ++ ++ len = read(fd, buffer, HZ_MAX_LENGTH); ++ qemu_close(fd); ++ if (len <= 0) { ++ return 0; ++ } ++ ret = qemu_strtoul(buffer, &endptr, 0, &hz); ++ if (ret < 0) { ++ return 0; ++ } ++ return (uint32_t)hz; ++} ++ ++static const MemoryRegionOps cpufreq_ops = { ++ .read = cpufreq_read, ++ .write = cpufreq_write, ++ .endianness = DEVICE_NATIVE_ENDIAN, ++}; ++ ++static void hz_init(CpuhzState *s) ++{ ++ uint32_t hz; ++ ++ hz = CPPC_Read(NOMINAL_FREQ_FILE); ++ if (hz == 0) { ++ hz = CPPC_Read(CPU_MAX_FREQ_FILE); ++ if (hz == 0) { ++ hz = DEFAULT_HZ; ++ } else { ++ /* Value in CpuMaxFrequency is in KHz unit; convert to MHz */ ++ hz = hz / 1000; ++ } ++ } ++ ++ s->HighestPerformance = hz; ++ s->NominalPerformance = hz; ++ s->LowestNonlinearPerformance = hz; ++ s->LowestPerformance = hz; ++ s->GuaranteedPerformance = hz; ++ s->DesiredPerformance = hz; ++ s->ReferencePerformanceCounter = 1; ++ s->DeliveredPerformanceCounter = 1; ++ s->PerformanceLimited = 0; ++ s->LowestFreq = hz; ++ s->NominalFreq = hz; ++} ++ ++static void cpufreq_init(Object *obj) ++{ ++ SysBusDevice *sbd = SYS_BUS_DEVICE(obj); ++ CpuhzState *s = CPUFREQ(obj); ++ ++ MachineState *ms = MACHINE(qdev_get_machine()); ++ unsigned int smp_cpus = ms->smp.cpus; ++ ++ s->reg_size = smp_cpus * CPPC_REG_PER_CPU_STRIDE; ++ if (s->reg_size > MAX_SUPPORT_SPACE) { ++ error_report("Required space 0x%x excesses the max support 0x%x", ++ s->reg_size, MAX_SUPPORT_SPACE); ++ goto err_end; ++ } ++ ++ memory_region_init_io(&s->iomem, OBJECT(s), &cpufreq_ops, s, "cpufreq", ++ s->reg_size); ++ sysbus_init_mmio(sbd, &s->iomem); ++ hz_init(s); ++ return; ++ ++err_end: ++ /* Set desired perf register offset to -1 to indicate no support for CPPC */ ++ cppc_regs_offset[DESIRED_PERF] = -1; ++} ++ ++static const TypeInfo cpufreq_arm_info = { ++ .name = TYPE_CPUFREQ, ++ .parent = TYPE_SYS_BUS_DEVICE, ++ .instance_size = sizeof(CpuhzState), ++ .instance_init = cpufreq_init, ++}; ++ ++static void cpufreq_register_types(void) ++{ ++ type_register_static(&cpufreq_arm_info); ++} ++ ++type_init(cpufreq_register_types) +diff --git a/hw/acpi/meson.build b/hw/acpi/meson.build +index adf6347bc4..448ea6afb4 100644 +--- a/hw/acpi/meson.build ++++ b/hw/acpi/meson.build +@@ -25,6 +25,7 @@ acpi_ss.add(when: 'CONFIG_ACPI_X86_ICH', if_true: files('ich9.c', 'tco.c')) + acpi_ss.add(when: 'CONFIG_IPMI', if_true: files('ipmi.c'), if_false: files('ipmi-stub.c')) + acpi_ss.add(when: 'CONFIG_PC', if_false: files('acpi-x86-stub.c')) + acpi_ss.add(when: 'CONFIG_TPM', if_true: files('tpm.c')) ++acpi_ss.add(when: 'CONFIG_CPUFREQ', if_true: files('cpufreq.c')) + softmmu_ss.add(when: 'CONFIG_ACPI', if_false: files('acpi-stub.c', 'aml-build-stub.c', 'ghes-stub.c')) + softmmu_ss.add_all(when: 'CONFIG_ACPI', if_true: acpi_ss) + softmmu_ss.add(when: 'CONFIG_ALL', if_true: files('acpi-stub.c', 'aml-build-stub.c', +diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c +index 674f902652..1ca705654b 100644 +--- a/hw/arm/virt-acpi-build.c ++++ b/hw/arm/virt-acpi-build.c +@@ -60,7 +60,68 @@ + + #define ACPI_BUILD_TABLE_SIZE 0x20000 + +-static void acpi_dsdt_add_cpus(Aml *scope, VirtMachineState *vms) ++static void acpi_dsdt_add_psd(Aml *dev, int cpus) ++{ ++ Aml *pkg; ++ Aml *sub; ++ ++ sub = aml_package(5); ++ aml_append(sub, aml_int(5)); ++ aml_append(sub, aml_int(0)); ++ /* Assume all vCPUs belong to the same domain */ ++ aml_append(sub, aml_int(0)); ++ /* SW_ANY: OSPM coordinate, initiate on any processor */ ++ aml_append(sub, aml_int(0xFD)); ++ aml_append(sub, aml_int(cpus)); ++ ++ pkg = aml_package(1); ++ aml_append(pkg, sub); ++ ++ aml_append(dev, aml_name_decl("_PSD", pkg)); ++} ++ ++static void acpi_dsdt_add_cppc(Aml *dev, uint64_t cpu_base, int *regs_offset) ++{ ++ Aml *cpc; ++ int i; ++ ++ /* Use version 3 of CPPC table from ACPI 6.3 */ ++ cpc = aml_package(23); ++ aml_append(cpc, aml_int(23)); ++ aml_append(cpc, aml_int(3)); ++ ++ for (i = 0; i < CPPC_REG_COUNT; i++) { ++ Aml *res; ++ uint8_t reg_width; ++ uint8_t acc_type; ++ uint64_t addr; ++ ++ if (regs_offset[i] == -1) { ++ reg_width = 0; ++ acc_type = AML_ANY_ACC; ++ addr = 0; ++ } else { ++ addr = cpu_base + regs_offset[i]; ++ if (i == REFERENCE_CTR || i == DELIVERED_CTR) { ++ reg_width = 64; ++ acc_type = AML_QWORD_ACC; ++ } else { ++ reg_width = 32; ++ acc_type = AML_DWORD_ACC; ++ } ++ } ++ ++ res = aml_resource_template(); ++ aml_append(res, aml_generic_register(AML_SYSTEM_MEMORY, reg_width, 0, ++ acc_type, addr)); ++ aml_append(cpc, res); ++ } ++ ++ aml_append(dev, aml_name_decl("_CPC", cpc)); ++} ++ ++static void acpi_dsdt_add_cpus(Aml *scope, VirtMachineState *vms, ++ const MemMapEntry *cppc_memmap) + { + MachineState *ms = MACHINE(vms); + uint16_t i; +@@ -69,6 +130,18 @@ static void acpi_dsdt_add_cpus(Aml *scope, VirtMachineState *vms) + Aml *dev = aml_device("C%.03X", i); + aml_append(dev, aml_name_decl("_HID", aml_string("ACPI0007"))); + aml_append(dev, aml_name_decl("_UID", aml_int(i))); ++ ++ /* ++ * Append _CPC and _PSD to support CPU frequence show ++ * Check CPPC available by DESIRED_PERF register ++ */ ++ if (cppc_regs_offset[DESIRED_PERF] != -1) { ++ acpi_dsdt_add_cppc(dev, ++ cppc_memmap->base + i * CPPC_REG_PER_CPU_STRIDE, ++ cppc_regs_offset); ++ acpi_dsdt_add_psd(dev, ms->smp.cpus); ++ } ++ + aml_append(scope, dev); + } + } +@@ -858,7 +931,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) + * the RTC ACPI device at all when using UEFI. + */ + scope = aml_scope("\\_SB"); +- acpi_dsdt_add_cpus(scope, vms); ++ acpi_dsdt_add_cpus(scope, vms, &memmap[VIRT_CPUFREQ]); + acpi_dsdt_add_uart(scope, &memmap[VIRT_UART], + (irqmap[VIRT_UART] + ARM_SPI_BASE)); + if (vmc->acpi_expose_flash) { +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index 529c0d38b6..0538d258fa 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -154,6 +154,7 @@ static const MemMapEntry base_memmap[] = { + [VIRT_PVTIME] = { 0x090a0000, 0x00010000 }, + [VIRT_SECURE_GPIO] = { 0x090b0000, 0x00001000 }, + [VIRT_MMIO] = { 0x0a000000, 0x00000200 }, ++ [VIRT_CPUFREQ] = { 0x0b000000, 0x00010000 }, + /* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */ + [VIRT_PLATFORM_BUS] = { 0x0c000000, 0x02000000 }, + [VIRT_SECURE_MEM] = { 0x0e000000, 0x01000000 }, +@@ -931,6 +932,16 @@ static void create_uart(const VirtMachineState *vms, int uart, + g_free(nodename); + } + ++static void create_cpufreq(const VirtMachineState *vms, MemoryRegion *mem) ++{ ++ hwaddr base = vms->memmap[VIRT_CPUFREQ].base; ++ DeviceState *dev = qdev_new("cpufreq"); ++ SysBusDevice *s = SYS_BUS_DEVICE(dev); ++ ++ sysbus_realize_and_unref(s, &error_fatal); ++ memory_region_add_subregion(mem, base, sysbus_mmio_get_region(s, 0)); ++} ++ + static void create_rtc(const VirtMachineState *vms) + { + char *nodename; +@@ -2190,6 +2201,8 @@ static void machvirt_init(MachineState *machine) + + create_uart(vms, VIRT_UART, sysmem, serial_hd(0)); + ++ create_cpufreq(vms, sysmem); ++ + if (vms->secure) { + create_secure_ram(vms, secure_sysmem, secure_tag_sysmem); + create_uart(vms, VIRT_SECURE_UART, secure_sysmem, serial_hd(1)); +diff --git a/hw/char/Kconfig b/hw/char/Kconfig +index 6b6cf2fc1d..335a60c2c1 100644 +--- a/hw/char/Kconfig ++++ b/hw/char/Kconfig +@@ -71,3 +71,7 @@ config GOLDFISH_TTY + + config SHAKTI_UART + bool ++ ++config CPUFREQ ++ bool ++ default y +diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h +index c97e8633ad..ab86583228 100644 +--- a/include/hw/acpi/acpi-defs.h ++++ b/include/hw/acpi/acpi-defs.h +@@ -92,4 +92,42 @@ typedef struct AcpiFadtData { + #define ACPI_FADT_ARM_PSCI_COMPLIANT (1 << 0) + #define ACPI_FADT_ARM_PSCI_USE_HVC (1 << 1) + ++/* ++ * CPPC register definition from kernel header ++ * include/acpi/cppc_acpi.h ++ * The last element is newly added for easy use ++ */ ++enum cppc_regs { ++ HIGHEST_PERF, ++ NOMINAL_PERF, ++ LOW_NON_LINEAR_PERF, ++ LOWEST_PERF, ++ GUARANTEED_PERF, ++ DESIRED_PERF, ++ MIN_PERF, ++ MAX_PERF, ++ PERF_REDUC_TOLERANCE, ++ TIME_WINDOW, ++ CTR_WRAP_TIME, ++ REFERENCE_CTR, ++ DELIVERED_CTR, ++ PERF_LIMITED, ++ ENABLE, ++ AUTO_SEL_ENABLE, ++ AUTO_ACT_WINDOW, ++ ENERGY_PERF, ++ REFERENCE_PERF, ++ LOWEST_FREQ, ++ NOMINAL_FREQ, ++ CPPC_REG_COUNT, ++}; ++ ++#define CPPC_REG_PER_CPU_STRIDE 0x40 ++ ++/* ++ * Offset for each CPPC register; -1 for unavailable ++ * The whole register space is unavailable if desired perf offset is -1. ++ */ ++extern int cppc_regs_offset[CPPC_REG_COUNT]; ++ + #endif +diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h +index 8e8ad8029e..2e00d2e208 100644 +--- a/include/hw/acpi/aml-build.h ++++ b/include/hw/acpi/aml-build.h +@@ -429,6 +429,9 @@ Aml *aml_dma(AmlDmaType typ, AmlDmaBusMaster bm, AmlTransferSize sz, + uint8_t channel); + Aml *aml_sleep(uint64_t msec); + Aml *aml_i2c_serial_bus_device(uint16_t address, const char *resource_source); ++Aml *aml_generic_register(AmlRegionSpace rs, uint8_t reg_width, ++ uint8_t reg_offset, AmlAccessType type, ++ uint64_t addr); + + /* Block AML object primitives */ + Aml *aml_scope(const char *name_format, ...) GCC_FMT_ATTR(1, 2); +diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h +index dc6b66ffc8..a4356cf736 100644 +--- a/include/hw/arm/virt.h ++++ b/include/hw/arm/virt.h +@@ -70,6 +70,7 @@ enum { + VIRT_GIC_REDIST, + VIRT_SMMU, + VIRT_UART, ++ VIRT_CPUFREQ, + VIRT_MMIO, + VIRT_RTC, + VIRT_FW_CFG, +diff --git a/tests/data/acpi/virt/DSDT b/tests/data/acpi/virt/DSDT +index c47503990715d389914fdf9c8bccb510761741ac..dd8573f0312918ea1ba17496e9f3a275e98ab214 100644 +GIT binary patch +delta 514 +zcmX@3u~di4CDC{9nX`Y4z#+dkEr}*e5XZeW+lJy+%&H>Is4l?3g;#|yv +zB3yz^JPZs949pA+4BSA>P|1KK$bwCf1Dhbw5KQd?n1b~T%pw?~AbX(zVLeO)NK;MF +zfuWv70>gR-1{MVjL12(*Uo4O*Pi7GSAkZ%L + +delta 38 +tcmZ3gb4G*9CD#+dkEr}*e5sfmV?o0XWDMF7oq3Hks4 + +diff --git a/tests/data/acpi/virt/DSDT.memhp b/tests/data/acpi/virt/DSDT.memhp +index bae36cdd397473afe3923c52f030641a5ab19d5d..d764481440adea59d928a1a48afe0ba1ce135597 100644 +GIT binary patch +delta 514 +zcmbPh{LPHZCDGeb|X`aTdj4|=SPVv!A&hirtBFt7`TC$p^^bfkOi9{2R1>VA(+|)Fa_%wm_;x|LH0rc!g`npkfxfT +z14BKF1cvnv3@i#5g1{irz!0R|P0=tT2>1zTy$*);KtThzAV+*au!|56qYx)67b^n; +L*I&kso*|L|A3`us + +delta 38 +ucmexnHrJTTCD8Drvuo#LaLq$V0lZdPInkpuwgSPN7D + +diff --git a/tests/data/acpi/virt/DSDT.numamem b/tests/data/acpi/virt/DSDT.numamem +index c47503990715d389914fdf9c8bccb510761741ac..dd8573f0312918ea1ba17496e9f3a275e98ab214 100644 +GIT binary patch +delta 514 +zcmX@3u~di4CDC{9nX`Y4z#+dkEr}*e5XZeW+lJy+%&H>Is4l?3g;#|yv +zB3yz^JPZs949pA+4BSA>P|1KK$bwCf1Dhbw5KQd?n1b~T%pw?~AbX(zVLeO)NK;MF +zfuWv70>gR-1{MVjL12(*Uo4O*Pi7GSAkZ%L + +delta 38 +tcmZ3gb4G*9CD#+dkEr}*e5sfmV?o0XWDMF7oq3Hks4 + +diff --git a/tests/data/acpi/virt/DSDT.pxb b/tests/data/acpi/virt/DSDT.pxb +index fbd78f44c4785d19759daea909fe6d6f9a6e6b01..9ff22b5ea465d2f678beb2ce9d905861d69a5b87 100644 +GIT binary patch +delta 514 +zcmexweZ!v1CD6}CMj=jCE>;Ex +MuD^^MJ-5jM0391Kw*UYD + +delta 38 +ucmca%|KFO+CD Date: Fri, 11 Feb 2022 16:42:15 +0800 Subject: [PATCH 25/54] spec: Update patch and changelog with !232 Introduce CPU cluster topo, cache topo and CPU frequency support to 6.2 baseline Merge pull request !232 from Yanan Wang/qemu-6.2.0 !232 qapi/machine.json: Fix incorrect description for die-id tests/unit/test-smp-parse: Pass machine type as argument to tests tests/unit/test-smp-parse: Split the 'generic' test in valid / invalid tests/unit/test-smp-parse: Add 'smp-with-dies' machine type tests/unit/test-smp-parse: Add 'smp-generic-invalid' machine type tests/unit/test-smp-parse: Add 'smp-generic-valid' machine type tests/unit/test-smp-parse: Simplify pointer to compound literal use tests/unit/test-smp-parse: Constify some pointer/struct hw/core: Rename smp_parse() -> machine_parse_smp_config() qemu-options: Improve readability of SMP related Docs hw/core/machine: Introduce CPU cluster topology support tests/unit/test-smp-parse: Add testcases for CPU clusters tests/unit/test-smp-parse: No need to explicitly zero MachineClass members tests/unit/test-smp-parse: Keep default MIN/MAX CPUs in machine_base_class_init hw/arm/virt: Support CPU cluster on ARM virt machine hw/arm/virt: Support cluster level in DT cpu-map hw/acpi/aml-build: Improve scalability of PPTT generation tests/acpi/bios-tables-test: Allow changes to virt/PPTT file hw/acpi/aml-build: Support cluster level in PPTT generation tests/acpi/bios-table-test: Update expected virt/PPTT file softmmu/device_tree: Silence compiler warning with --enable-sanitizers softmmu/device_tree: Remove redundant pointer assignment hw/arm64: add vcpu cache info support arm64: Add the cpufreq device to show cpufreq info to guest Signed-off-by: Chen Qun --- qemu.spec | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/qemu.spec b/qemu.spec index 396811d..ba4d295 100644 --- a/qemu.spec +++ b/qemu.spec @@ -32,6 +32,30 @@ Patch0019: doc-Update-multi-thread-compression-doc.patch Patch0020: Revert-cpu-parse-feature-to-avoid-failure.patch Patch0021: Revert-cpu-add-Cortex-A72-processor-kvm-target-suppo.patch Patch0022: 0003-cpu-add-Cortex-A72-processor-kvm-target-support.patch +Patch0023: qapi-machine.json-Fix-incorrect-description-for-die-.patch +Patch0024: tests-unit-test-smp-parse-Pass-machine-type-as-argum.patch +Patch0025: tests-unit-test-smp-parse-Split-the-generic-test-in-.patch +Patch0026: tests-unit-test-smp-parse-Add-smp-with-dies-machine-.patch +Patch0027: tests-unit-test-smp-parse-Add-smp-generic-invalid-ma.patch +Patch0028: tests-unit-test-smp-parse-Add-smp-generic-valid-mach.patch +Patch0029: tests-unit-test-smp-parse-Simplify-pointer-to-compou.patch +Patch0030: tests-unit-test-smp-parse-Constify-some-pointer-stru.patch +Patch0031: hw-core-Rename-smp_parse-machine_parse_smp_config.patch +Patch0032: qemu-options-Improve-readability-of-SMP-related-Docs.patch +Patch0033: hw-core-machine-Introduce-CPU-cluster-topology-suppo.patch +Patch0034: tests-unit-test-smp-parse-Add-testcases-for-CPU-clus.patch +Patch0035: tests-unit-test-smp-parse-No-need-to-explicitly-zero.patch +Patch0036: tests-unit-test-smp-parse-Keep-default-MIN-MAX-CPUs-.patch +Patch0037: hw-arm-virt-Support-CPU-cluster-on-ARM-virt-machine.patch +Patch0038: hw-arm-virt-Support-cluster-level-in-DT-cpu-map.patch +Patch0039: hw-acpi-aml-build-Improve-scalability-of-PPTT-genera.patch +Patch0040: tests-acpi-bios-tables-test-Allow-changes-to-virt-PP.patch +Patch0041: hw-acpi-aml-build-Support-cluster-level-in-PPTT-gene.patch +Patch0042: tests-acpi-bios-table-test-Update-expected-virt-PPTT.patch +Patch0043: softmmu-device_tree-Silence-compiler-warning-with-en.patch +Patch0044: softmmu-device_tree-Remove-redundant-pointer-assignm.patch +Patch0045: hw-arm64-add-vcpu-cache-info-support.patch +Patch0046: arm64-Add-the-cpufreq-device-to-show-cpufreq-info-to.patch BuildRequires: flex BuildRequires: gcc @@ -474,6 +498,32 @@ getent passwd qemu >/dev/null || \ %endif %changelog +* Fri Feb 11 2022 Chen Qun +- qapi/machine.json: Fix incorrect description for die-id +- tests/unit/test-smp-parse: Pass machine type as argument to tests +- tests/unit/test-smp-parse: Split the 'generic' test in valid / invalid +- tests/unit/test-smp-parse: Add 'smp-with-dies' machine type +- tests/unit/test-smp-parse: Add 'smp-generic-invalid' machine type +- tests/unit/test-smp-parse: Add 'smp-generic-valid' machine type +- tests/unit/test-smp-parse: Simplify pointer to compound literal use +- tests/unit/test-smp-parse: Constify some pointer/struct +- hw/core: Rename smp_parse() -> machine_parse_smp_config() +- qemu-options: Improve readability of SMP related Docs +- hw/core/machine: Introduce CPU cluster topology support +- tests/unit/test-smp-parse: Add testcases for CPU clusters +- tests/unit/test-smp-parse: No need to explicitly zero MachineClass members +- tests/unit/test-smp-parse: Keep default MIN/MAX CPUs in machine_base_class_init +- hw/arm/virt: Support CPU cluster on ARM virt machine +- hw/arm/virt: Support cluster level in DT cpu-map +- hw/acpi/aml-build: Improve scalability of PPTT generation +- tests/acpi/bios-tables-test: Allow changes to virt/PPTT file +- hw/acpi/aml-build: Support cluster level in PPTT generation +- tests/acpi/bios-table-test: Update expected virt/PPTT file +- softmmu/device_tree: Silence compiler warning with --enable-sanitizers +- softmmu/device_tree: Remove redundant pointer assignment +- hw/arm64: add vcpu cache info support +- arm64: Add the cpufreq device to show cpufreq info to guest + * Fri Feb 11 2022 imxcc - Revert "cpu: parse +/- feature to avoid failure" - Revert "cpu: add Cortex-A72 processor kvm target support" -- Gitee From 9333017e360d9c4226dcd999fee241a598e63d6a Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Wed, 9 Feb 2022 10:42:33 +0800 Subject: [PATCH 26/54] nbd/server.c: fix invalid read after client was already free In the process of NBD equipment pressurization, executing QEMU NBD will lead to the failure of IO distribution and go to NBD_ Out process of trip(). If two or more IO go to the out process, client NBD will release in nbd_request_put(). The user after free problem that is read again in close(). Through the NBD_ Save the value of client > closing before the out process in trip to solve the use after free problem. Signed-off-by: wangjian161 --- ...-invalid-read-after-client-was-alrea.patch | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 nbd-server.c-fix-invalid-read-after-client-was-alrea.patch diff --git a/nbd-server.c-fix-invalid-read-after-client-was-alrea.patch b/nbd-server.c-fix-invalid-read-after-client-was-alrea.patch new file mode 100644 index 0000000..b6ba4e4 --- /dev/null +++ b/nbd-server.c-fix-invalid-read-after-client-was-alrea.patch @@ -0,0 +1,45 @@ +From 4b156248776f734d63fe37629d56c40234fda9c0 Mon Sep 17 00:00:00 2001 +From: WangJian +Date: Wed, 9 Feb 2022 10:42:33 +0800 +Subject: [PATCH] nbd/server.c: fix invalid read after client was already free + +In the process of NBD equipment pressurization, executing QEMU NBD will +lead to the failure of IO distribution and go to NBD_ Out process of trip(). +If two or more IO go to the out process, client NBD will release in nbd_request_put(). +The user after free problem that is read again in close(). +Through the NBD_ Save the value of client > closing before the out process in trip +to solve the use after free problem. + +Signed-off-by: wangjian161 +--- + nbd/server.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/nbd/server.c b/nbd/server.c +index 4630dd7322..37515ed520 100644 +--- a/nbd/server.c ++++ b/nbd/server.c +@@ -2606,6 +2606,7 @@ static coroutine_fn void nbd_trip(void *opaque) + NBDRequestData *req; + NBDRequest request = { 0 }; /* GCC thinks it can be used uninitialized */ + int ret; ++ bool client_closing; + Error *local_err = NULL; + + trace_nbd_trip(); +@@ -2681,8 +2682,11 @@ disconnect: + if (local_err) { + error_reportf_err(local_err, "Disconnect client, due to: "); + } ++ client_closing = client->closing; + nbd_request_put(req); +- client_close(client, true); ++ if (!client_closing) { ++ client_close(client, true); ++ } + nbd_client_put(client); + } + +-- +2.27.0 + -- Gitee From 20cf0e4c0f13d8ead841d82ff591189e1ac3d602 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Wed, 9 Feb 2022 10:48:58 +0800 Subject: [PATCH 27/54] qemu-nbd: make native as the default aio mode When the file system is dealing with multithreading concurrent writing to a file, the performance will be degraded because of the lock. At present, the default AIO mode of QEMU NBD is threads. In the case of large blocks, because IO is divided into small pieces and multiple queues, it will become multithreading concurrent writing the same file. Due to the file system, the performance will be greatly reduced. If you change to native mode, this problem will not exist. Signed-off-by: wangjian161 --- ...-make-native-as-the-default-aio-mode.patch | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 qemu-nbd-make-native-as-the-default-aio-mode.patch diff --git a/qemu-nbd-make-native-as-the-default-aio-mode.patch b/qemu-nbd-make-native-as-the-default-aio-mode.patch new file mode 100644 index 0000000..c53f50a --- /dev/null +++ b/qemu-nbd-make-native-as-the-default-aio-mode.patch @@ -0,0 +1,35 @@ +From de6f3fb0cf92e04c0989a9065910158eecbe4304 Mon Sep 17 00:00:00 2001 +From: WangJian +Date: Wed, 9 Feb 2022 10:48:58 +0800 +Subject: [PATCH] qemu-nbd: make native as the default aio mode + +When the file system is dealing with multithreading concurrent writing to a file, +the performance will be degraded because of the lock. +At present, the default AIO mode of QEMU NBD is threads. In the case of large blocks, +because IO is divided into small pieces and multiple queues, it will become multithreading +concurrent writing the same file. Due to the file system, the performance will be greatly reduced. +If you change to native mode, this problem will not exist. + +Signed-off-by: wangjian161 +--- + qemu-nbd.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/qemu-nbd.c b/qemu-nbd.c +index c6c20df68a..15a4bc4018 100644 +--- a/qemu-nbd.c ++++ b/qemu-nbd.c +@@ -800,6 +800,10 @@ int main(int argc, char **argv) + trace_init_file(); + qemu_set_log(LOG_TRACE); + ++ if (!seen_aio && (flags & BDRV_O_NOCACHE)) { ++ flags |= BDRV_O_NATIVE_AIO; ++ } ++ + socket_activation = check_socket_activation(); + if (socket_activation == 0) { + setup_address_and_port(&bindto, &port); +-- +2.27.0 + -- Gitee From 9e9b40f0c29f67528c09ff385f7e2ce8e97df7a7 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Wed, 9 Feb 2022 10:55:08 +0800 Subject: [PATCH 28/54] qemu-nbd: set timeout to qemu-nbd socket In case of insufficient memory and kill-9, the NBD socket cannot be processed and stuck all the time. Signed-off-by: wangjian161 --- qemu-nbd-set-timeout-to-qemu-nbd-socket.patch | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 qemu-nbd-set-timeout-to-qemu-nbd-socket.patch diff --git a/qemu-nbd-set-timeout-to-qemu-nbd-socket.patch b/qemu-nbd-set-timeout-to-qemu-nbd-socket.patch new file mode 100644 index 0000000..3ef9b6a --- /dev/null +++ b/qemu-nbd-set-timeout-to-qemu-nbd-socket.patch @@ -0,0 +1,42 @@ +From f665f7836a019cc8bb8d46d076508afc761923f0 Mon Sep 17 00:00:00 2001 +From: WangJian +Date: Wed, 9 Feb 2022 10:55:08 +0800 +Subject: [PATCH] qemu-nbd: set timeout to qemu-nbd socket + +In case of insufficient memory and kill-9, +the NBD socket cannot be processed and stuck all the time. + +Signed-off-by: wangjian161 +--- + nbd/client.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/nbd/client.c b/nbd/client.c +index 30d5383cb1..8ed50140f2 100644 +--- a/nbd/client.c ++++ b/nbd/client.c +@@ -24,6 +24,8 @@ + #include "nbd-internal.h" + #include "qemu/cutils.h" + ++#define NBD_TIMEOUT_SECONDS 30 ++ + /* Definitions for opaque data types */ + + static QTAILQ_HEAD(, NBDExport) exports = QTAILQ_HEAD_INITIALIZER(exports); +@@ -1301,6 +1303,12 @@ int nbd_init(int fd, QIOChannelSocket *sioc, NBDExportInfo *info, + } + } + ++ if (ioctl(fd, NBD_SET_TIMEOUT, NBD_TIMEOUT_SECONDS) < 0) { ++ int serrno = errno; ++ error_setg(errp, "Failed setting timeout"); ++ return -serrno; ++ } ++ + trace_nbd_init_finish(); + + return 0; +-- +2.27.0 + -- Gitee From a860464faa48602a86f11e7b540bba87f9af34f7 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Wed, 9 Feb 2022 11:10:42 +0800 Subject: [PATCH 29/54] qemu-pr: fixed ioctl failed for multipath disk We use ioctl to detect multipath devices. However, we only set flags in struct dm_ioctl (the argument to ioctl) and left other fields in random, which may cause the failure of calling ioctl. Hence, we set other fields to 0 to avoid the failure. Signed-off-by: wangjian161 --- ...ixed-ioctl-failed-for-multipath-disk.patch | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 qemu-pr-fixed-ioctl-failed-for-multipath-disk.patch diff --git a/qemu-pr-fixed-ioctl-failed-for-multipath-disk.patch b/qemu-pr-fixed-ioctl-failed-for-multipath-disk.patch new file mode 100644 index 0000000..7985a92 --- /dev/null +++ b/qemu-pr-fixed-ioctl-failed-for-multipath-disk.patch @@ -0,0 +1,36 @@ +From 56f59125707c0222bbb5d7f820792aba17c3db08 Mon Sep 17 00:00:00 2001 +From: WangJian +Date: Wed, 9 Feb 2022 11:10:42 +0800 +Subject: [PATCH] qemu-pr: fixed ioctl failed for multipath disk + +We use ioctl to detect multipath devices. However, we only set flags in +struct dm_ioctl (the argument to ioctl) and left other fields in random, +which may cause the failure of calling ioctl. Hence, we set other +fields to 0 to avoid the failure. + +Signed-off-by: wangjian161 +--- + scsi/qemu-pr-helper.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/scsi/qemu-pr-helper.c b/scsi/qemu-pr-helper.c +index f281daeced..bbb9b57741 100644 +--- a/scsi/qemu-pr-helper.c ++++ b/scsi/qemu-pr-helper.c +@@ -288,9 +288,12 @@ static void multipath_pr_init(void) + + static int is_mpath(int fd) + { +- struct dm_ioctl dm = { .flags = DM_NOFLUSH_FLAG }; ++ struct dm_ioctl dm; + struct dm_target_spec *tgt; + ++ memset(&dm, 0, sizeof(struct dm_ioctl)); ++ dm.flags = DM_NOFLUSH_FLAG; ++ + tgt = dm_dev_ioctl(fd, DM_TABLE_STATUS, &dm); + if (!tgt) { + if (errno == ENXIO) { +-- +2.27.0 + -- Gitee From fc9da26bef6dc962ef666bd34ac21899cdafc31d Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Wed, 9 Feb 2022 11:18:21 +0800 Subject: [PATCH 30/54] block: enable cache mode of empty cdrom enable cache mode even if cdrom is empty Signed-off-by: wangjian161 --- block-enable-cache-mode-of-empty-cdrom.patch | 49 ++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 block-enable-cache-mode-of-empty-cdrom.patch diff --git a/block-enable-cache-mode-of-empty-cdrom.patch b/block-enable-cache-mode-of-empty-cdrom.patch new file mode 100644 index 0000000..3a5c0b1 --- /dev/null +++ b/block-enable-cache-mode-of-empty-cdrom.patch @@ -0,0 +1,49 @@ +From 21b172a3ce13c3b499e4265628f7d7c7e1189749 Mon Sep 17 00:00:00 2001 +From: WangJian +Date: Wed, 9 Feb 2022 11:18:21 +0800 +Subject: [PATCH] block: enable cache mode of empty cdrom + +enable cache mode even if cdrom is empty + +Signed-off-by: wangjian161 +--- + blockdev.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/blockdev.c b/blockdev.c +index 10a73fa423..37e3ee6f26 100644 +--- a/blockdev.c ++++ b/blockdev.c +@@ -492,6 +492,7 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts, + QDict *interval_dict = NULL; + QList *interval_list = NULL; + const char *id; ++ const char *cache; + BlockdevDetectZeroesOptions detect_zeroes = + BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF; + const char *throttling_group = NULL; +@@ -583,6 +584,21 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts, + + read_only = qemu_opt_get_bool(opts, BDRV_OPT_READ_ONLY, false); + ++ if (!file || !*file) { ++ cache = qdict_get_try_str(bs_opts, BDRV_OPT_CACHE_NO_FLUSH); ++ if (cache && !strcmp(cache, "on")) { ++ bdrv_flags |= BDRV_O_NO_FLUSH; ++ } ++ ++ cache = qdict_get_try_str(bs_opts, BDRV_OPT_CACHE_DIRECT); ++ if (cache && !strcmp(cache, "on")) { ++ bdrv_flags |= BDRV_O_NOCACHE; ++ } ++ ++ qdict_del(bs_opts, BDRV_OPT_CACHE_NO_FLUSH); ++ qdict_del(bs_opts, BDRV_OPT_CACHE_DIRECT); ++ } ++ + /* init */ + if ((!file || !*file) && !qdict_size(bs_opts)) { + BlockBackendRootState *blk_rs; +-- +2.27.0 + -- Gitee From 02e5d991c1e3cacb7e5fa0184530241e429fcf22 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Wed, 9 Feb 2022 11:29:15 +0800 Subject: [PATCH 31/54] block: disallow block jobs when there is a BDRV_O_INACTIVE flag Currently, migration will put a BDRV_O_INACTIVE flag on bs's open_flags until another resume being called. In that case, any IO from vm or block jobs will cause a qemu crash with an assert 'assert(!(bs->open_flags & BDRV_O_INACTIVE))' failure in bdrv_co_pwritev function. we hereby disallow block jobs by faking a blocker. Signed-off-by: wangjian161 --- ...lock-jobs-when-there-is-a-BDRV_O_INA.patch | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 block-disallow-block-jobs-when-there-is-a-BDRV_O_INA.patch diff --git a/block-disallow-block-jobs-when-there-is-a-BDRV_O_INA.patch b/block-disallow-block-jobs-when-there-is-a-BDRV_O_INA.patch new file mode 100644 index 0000000..f243df9 --- /dev/null +++ b/block-disallow-block-jobs-when-there-is-a-BDRV_O_INA.patch @@ -0,0 +1,47 @@ +From 0a2c96ee5a3463e82397afb9cb36f340a93264c2 Mon Sep 17 00:00:00 2001 +From: WangJian +Date: Wed, 9 Feb 2022 11:29:15 +0800 +Subject: [PATCH] block: disallow block jobs when there is a BDRV_O_INACTIVE + flag + +Currently, migration will put a BDRV_O_INACTIVE flag +on bs's open_flags until another resume being called. In that case, +any IO from vm or block jobs will cause a qemu crash with an assert +'assert(!(bs->open_flags & BDRV_O_INACTIVE))' failure in bdrv_co_pwritev +function. we hereby disallow block jobs by faking a blocker. + +Signed-off-by: wangjian161 +--- + block.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/block.c b/block.c +index 0ac5b163d2..26c3982567 100644 +--- a/block.c ++++ b/block.c +@@ -6692,6 +6692,22 @@ bool bdrv_op_is_blocked(BlockDriverState *bs, BlockOpType op, Error **errp) + bdrv_get_device_or_node_name(bs)); + return true; + } ++ ++ /* ++ * When migration puts a BDRV_O_INACTIVE flag on driver's open_flags, ++ * we fake a blocker that doesn't exist. From now on, block jobs ++ * will not be permitted. ++ */ ++ if ((op == BLOCK_OP_TYPE_RESIZE || op == BLOCK_OP_TYPE_COMMIT_SOURCE || ++ op == BLOCK_OP_TYPE_MIRROR_SOURCE || op == BLOCK_OP_TYPE_MIRROR_TARGET) && ++ (bs->open_flags & BDRV_O_INACTIVE)) { ++ if (errp) { ++ error_setg(errp, "block device is in use by migration with" ++ " a driver BDRV_O_INACTIVE flag setted"); ++ } ++ return true; ++ } ++ + return false; + } + +-- +2.27.0 + -- Gitee From 4d82db7c254b05981ee83a74ccf88caf1dce9c69 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Wed, 9 Feb 2022 11:42:47 +0800 Subject: [PATCH 32/54] scsi: cdrom: Fix crash after remote cdrom detached There is a small window between the twice blk_is_available in scsi_disk_emulate_command which would cause crash due to the later assertion if the remote cdrom is detached in this window. So this patch replaces assertions with return to avoid qemu crash. Signed-off-by: wangjian161 --- ...ix-crash-after-remote-cdrom-detached.patch | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 scsi-cdrom-Fix-crash-after-remote-cdrom-detached.patch diff --git a/scsi-cdrom-Fix-crash-after-remote-cdrom-detached.patch b/scsi-cdrom-Fix-crash-after-remote-cdrom-detached.patch new file mode 100644 index 0000000..d1147fc --- /dev/null +++ b/scsi-cdrom-Fix-crash-after-remote-cdrom-detached.patch @@ -0,0 +1,35 @@ +From 77496578b22e127eb50a5a8c463e92fb3245a7e0 Mon Sep 17 00:00:00 2001 +From: WangJian +Date: Wed, 9 Feb 2022 11:42:47 +0800 +Subject: [PATCH] scsi: cdrom: Fix crash after remote cdrom detached + +There is a small window between the twice blk_is_available in +scsi_disk_emulate_command which would cause crash due to the later +assertion if the remote cdrom is detached in this window. + +So this patch replaces assertions with return to avoid qemu crash. + +Signed-off-by: wangjian161 +--- + hw/scsi/scsi-disk.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c +index d4914178ea..a1053f4036 100644 +--- a/hw/scsi/scsi-disk.c ++++ b/hw/scsi/scsi-disk.c +@@ -1930,7 +1930,10 @@ static int32_t scsi_disk_emulate_command(SCSIRequest *req, uint8_t *buf) + memset(outbuf, 0, r->buflen); + switch (req->cmd.buf[0]) { + case TEST_UNIT_READY: +- assert(blk_is_available(s->qdev.conf.blk)); ++ if (!blk_is_available(s->qdev.conf.blk)) { ++ scsi_check_condition(r, SENSE_CODE(NO_MEDIUM)); ++ return 0; ++ } + break; + case INQUIRY: + buflen = scsi_disk_emulate_inquiry(req, outbuf); +-- +2.27.0 + -- Gitee From 0879f10dae9581817bb750c8118c5143b4859ee7 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Wed, 9 Feb 2022 11:51:43 +0800 Subject: [PATCH 33/54] block: bugfix: disable process AIO when attach scsi disk When initializing the virtio-scsi disk, hd_geometry_guess() will be called to process AIO. At this time, the scsi disk has not been fully initialized, and some fields in struct SCSIDiskState, such as vendor and version, are NULL. If processing AIO at this time, qemu may crash down. Add aio_disable_external() before hd_geometry_guess() to disable processing AIO at that time. Signed-off-by: wangjian161 --- ...able-process-AIO-when-attach-scsi-di.patch | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 block-bugfix-disable-process-AIO-when-attach-scsi-di.patch diff --git a/block-bugfix-disable-process-AIO-when-attach-scsi-di.patch b/block-bugfix-disable-process-AIO-when-attach-scsi-di.patch new file mode 100644 index 0000000..30a1bac --- /dev/null +++ b/block-bugfix-disable-process-AIO-when-attach-scsi-di.patch @@ -0,0 +1,43 @@ +From 87d8b7dcd880e0cef0c043dfef5ae649652cfe21 Mon Sep 17 00:00:00 2001 +From: WangJian +Date: Wed, 9 Feb 2022 11:51:43 +0800 +Subject: [PATCH] block: bugfix: disable process AIO when attach scsi disk + +When initializing the virtio-scsi disk, hd_geometry_guess() will +be called to process AIO. At this time, the scsi disk has not +been fully initialized, and some fields in struct SCSIDiskState, +such as vendor and version, are NULL. If processing AIO at this +time, qemu may crash down. + +Add aio_disable_external() before hd_geometry_guess() to disable +processing AIO at that time. + +Signed-off-by: wangjian161 +--- + hw/block/block.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/hw/block/block.c b/hw/block/block.c +index 26c0767552..2cfc93a68e 100644 +--- a/hw/block/block.c ++++ b/hw/block/block.c +@@ -224,9 +224,16 @@ bool blkconf_geometry(BlockConf *conf, int *ptrans, + Error **errp) + { + if (!conf->cyls && !conf->heads && !conf->secs) { ++ AioContext *ctx = blk_get_aio_context(conf->blk); ++ ++ /* Callers may not expect this function to dispatch aio handlers, so ++ * disable external aio such as guest device emulation. ++ */ ++ aio_disable_external(ctx); + hd_geometry_guess(conf->blk, + &conf->cyls, &conf->heads, &conf->secs, + ptrans); ++ aio_enable_external(ctx); + } else if (ptrans && *ptrans == BIOS_ATA_TRANSLATION_AUTO) { + *ptrans = hd_bios_chs_auto_trans(conf->cyls, conf->heads, conf->secs); + } +-- +2.27.0 + -- Gitee From 0c34d7175569902f2511e81f8ffc0d460933e87b Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Wed, 9 Feb 2022 16:10:22 +0800 Subject: [PATCH 34/54] block: bugfix: Don't pause vm when NOSPACE EIO happened When backend disk is FULL and disk IO type is 'dataplane', QEMU will pause the vm, and this may cause endless-loop in QEMU main thread if we do the snapshot merge now. When backend disk is FULL, only reporting an error rather than pausing the virtual machine. Signed-off-by: wangjian161 --- ...-t-pause-vm-when-NOSPACE-EIO-happene.patch | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 block-bugfix-Don-t-pause-vm-when-NOSPACE-EIO-happene.patch diff --git a/block-bugfix-Don-t-pause-vm-when-NOSPACE-EIO-happene.patch b/block-bugfix-Don-t-pause-vm-when-NOSPACE-EIO-happene.patch new file mode 100644 index 0000000..3d454ec --- /dev/null +++ b/block-bugfix-Don-t-pause-vm-when-NOSPACE-EIO-happene.patch @@ -0,0 +1,33 @@ +From d0586db311e8b78732923ce46f149fdf8251a59c Mon Sep 17 00:00:00 2001 +From: WangJian +Date: Wed, 9 Feb 2022 16:10:22 +0800 +Subject: [PATCH] block: bugfix: Don't pause vm when NOSPACE EIO happened + +When backend disk is FULL and disk IO type is 'dataplane', +QEMU will pause the vm, and this may cause endless-loop in +QEMU main thread if we do the snapshot merge now. + +When backend disk is FULL, only reporting an error rather +than pausing the virtual machine. + +Signed-off-by: wangjian161 +--- + blockdev.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/blockdev.c b/blockdev.c +index 37e3ee6f26..3ce294ec4a 100644 +--- a/blockdev.c ++++ b/blockdev.c +@@ -556,7 +556,7 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts, + qdict_put_str(bs_opts, "driver", buf); + } + +- on_write_error = BLOCKDEV_ON_ERROR_ENOSPC; ++ on_write_error = BLOCKDEV_ON_ERROR_REPORT; + if ((buf = qemu_opt_get(opts, "werror")) != NULL) { + on_write_error = parse_block_error_action(buf, 0, &error); + if (error) { +-- +2.27.0 + -- Gitee From 51b1b419c8a7ea45af8e51050639e634a3b61df1 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Wed, 9 Feb 2022 16:34:05 +0800 Subject: [PATCH 35/54] scsi: bugfix: fix division by zero Error of PRDM disk may cause divide by zero in scsi_read_complete(), so add LOG and assert(). Signed-off-by: wangjian161 --- scsi-bugfix-fix-division-by-zero.patch | 57 ++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 scsi-bugfix-fix-division-by-zero.patch diff --git a/scsi-bugfix-fix-division-by-zero.patch b/scsi-bugfix-fix-division-by-zero.patch new file mode 100644 index 0000000..685c8d5 --- /dev/null +++ b/scsi-bugfix-fix-division-by-zero.patch @@ -0,0 +1,57 @@ +From ba8fd8a3d11655da0b51148e69c01b78794a3f69 Mon Sep 17 00:00:00 2001 +From: WangJian +Date: Wed, 9 Feb 2022 16:34:05 +0800 +Subject: [PATCH] scsi: bugfix: fix division by zero + +Error of PRDM disk may cause divide by zero in +scsi_read_complete(), so add LOG and assert(). + +Signed-off-by: wangjian161 +--- + hw/scsi/scsi-generic.c | 20 ++++++++++++++++++-- + 1 file changed, 18 insertions(+), 2 deletions(-) + +diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c +index 0306ccc7b1..1f51586048 100644 +--- a/hw/scsi/scsi-generic.c ++++ b/hw/scsi/scsi-generic.c +@@ -179,6 +179,10 @@ static int scsi_handle_inquiry_reply(SCSIGenericReq *r, SCSIDevice *s, int len) + (r->req.cmd.buf[1] & 0x01)) { + page = r->req.cmd.buf[2]; + if (page == 0xb0) { ++ if (s->blocksize == 0) { ++ qemu_log("device blocksize is 0!\n"); ++ abort(); ++ } + uint64_t max_transfer = blk_get_max_hw_transfer(s->conf.blk); + uint32_t max_iov = blk_get_max_hw_iov(s->conf.blk); + +@@ -314,11 +318,23 @@ static void scsi_read_complete(void * opaque, int ret) + /* Snoop READ CAPACITY output to set the blocksize. */ + if (r->req.cmd.buf[0] == READ_CAPACITY_10 && + (ldl_be_p(&r->buf[0]) != 0xffffffffU || s->max_lba == 0)) { +- s->blocksize = ldl_be_p(&r->buf[4]); ++ int new_blocksize = ldl_be_p(&r->buf[4]); ++ if (s->blocksize != new_blocksize) { ++ qemu_log("device id=%s type=%d: blocksize %d change to %d\n", ++ s->qdev.id ? s->qdev.id : "null", s->type, ++ s->blocksize, new_blocksize); ++ } ++ s->blocksize = new_blocksize; + s->max_lba = ldl_be_p(&r->buf[0]) & 0xffffffffULL; + } else if (r->req.cmd.buf[0] == SERVICE_ACTION_IN_16 && + (r->req.cmd.buf[1] & 31) == SAI_READ_CAPACITY_16) { +- s->blocksize = ldl_be_p(&r->buf[8]); ++ int new_blocksize = ldl_be_p(&r->buf[8]); ++ if (s->blocksize != new_blocksize) { ++ qemu_log("device id=%s type=%d: blocksize %d change to %d\n", ++ s->qdev.id ? s->qdev.id : "null", s->type, ++ s->blocksize, new_blocksize); ++ } ++ s->blocksize = new_blocksize; + s->max_lba = ldq_be_p(&r->buf[0]); + } + blk_set_guest_block_size(s->conf.blk, s->blocksize); +-- +2.27.0 + -- Gitee From bf9f5f199940cd464504552cb23696e2bf8409b0 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Fri, 11 Feb 2022 16:42:25 +0800 Subject: [PATCH 36/54] =?UTF-8?q?spec:=20Update=20patch=20and=20changelog?= =?UTF-8?q?=20with=20!233=20=E3=80=906.2.0=E3=80=91IO=E8=A1=A5=E4=B8=81?= =?UTF-8?q?=E5=9B=9E=E5=90=88=20=20!233?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit nbd/server.c: fix invalid read after client was already free qemu-nbd: make native as the default aio mode qemu-nbd: set timeout to qemu-nbd socket qemu-pr: fixed ioctl failed for multipath disk block: enable cache mode of empty cdrom block: disallow block jobs when there is a BDRV_O_INACTIVE flag scsi: cdrom: Fix crash after remote cdrom detached block: bugfix: disable process AIO when attach scsi disk block: bugfix: Don't pause vm when NOSPACE EIO happened scsi: bugfix: fix division by zero Signed-off-by: Chen Qun --- qemu.spec | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/qemu.spec b/qemu.spec index ba4d295..73c14ef 100644 --- a/qemu.spec +++ b/qemu.spec @@ -56,6 +56,16 @@ Patch0043: softmmu-device_tree-Silence-compiler-warning-with-en.patch Patch0044: softmmu-device_tree-Remove-redundant-pointer-assignm.patch Patch0045: hw-arm64-add-vcpu-cache-info-support.patch Patch0046: arm64-Add-the-cpufreq-device-to-show-cpufreq-info-to.patch +Patch0047: nbd-server.c-fix-invalid-read-after-client-was-alrea.patch +Patch0048: qemu-nbd-make-native-as-the-default-aio-mode.patch +Patch0049: qemu-nbd-set-timeout-to-qemu-nbd-socket.patch +Patch0050: qemu-pr-fixed-ioctl-failed-for-multipath-disk.patch +Patch0051: block-enable-cache-mode-of-empty-cdrom.patch +Patch0052: block-disallow-block-jobs-when-there-is-a-BDRV_O_INA.patch +Patch0053: scsi-cdrom-Fix-crash-after-remote-cdrom-detached.patch +Patch0054: block-bugfix-disable-process-AIO-when-attach-scsi-di.patch +Patch0055: block-bugfix-Don-t-pause-vm-when-NOSPACE-EIO-happene.patch +Patch0056: scsi-bugfix-fix-division-by-zero.patch BuildRequires: flex BuildRequires: gcc @@ -498,6 +508,18 @@ getent passwd qemu >/dev/null || \ %endif %changelog +* Fri Feb 11 2022 Chen Qun +- nbd/server.c: fix invalid read after client was already free +- qemu-nbd: make native as the default aio mode +- qemu-nbd: set timeout to qemu-nbd socket +- qemu-pr: fixed ioctl failed for multipath disk +- block: enable cache mode of empty cdrom +- block: disallow block jobs when there is a BDRV_O_INACTIVE flag +- scsi: cdrom: Fix crash after remote cdrom detached +- block: bugfix: disable process AIO when attach scsi disk +- block: bugfix: Don't pause vm when NOSPACE EIO happened +- scsi: bugfix: fix division by zero + * Fri Feb 11 2022 Chen Qun - qapi/machine.json: Fix incorrect description for die-id - tests/unit/test-smp-parse: Pass machine type as argument to tests -- Gitee From 8ac56f469cfa2c3308caaf66b6d5e43fc7d9522f Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Thu, 10 Feb 2022 19:43:55 +0800 Subject: [PATCH 37/54] i386: cache passthrough: Update Intel CPUID4.EAX[25:14] based on vCPU topo On Intel target, when host cache passthrough is disabled we will emulate the guest caches with default values and initialize the shared cpu list of the caches based on vCPU topology. However when host cache passthrough is enabled, the shared cpu list is consistent with host regardless what the vCPU topology is. For example, when cache passthrough is enabled, running a guest with vThreads=1 on a host with pThreads=2, we will get that there are every *two* logical vCPUs sharing a L1/L2 cache, which is not consistent with the vCPU topology (vThreads=1). So let's reinitialize BITs[25:14] of Intel CPUID 4 based on the actual vCPU topology instead of host pCPU topology. Signed-off-by: Jian Wang Signed-off-by: Yanan Wang --- ...hrough-Update-Intel-CPUID4.EAX-25-14.patch | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 i386-cache-passthrough-Update-Intel-CPUID4.EAX-25-14.patch diff --git a/i386-cache-passthrough-Update-Intel-CPUID4.EAX-25-14.patch b/i386-cache-passthrough-Update-Intel-CPUID4.EAX-25-14.patch new file mode 100644 index 0000000..a0fc157 --- /dev/null +++ b/i386-cache-passthrough-Update-Intel-CPUID4.EAX-25-14.patch @@ -0,0 +1,88 @@ +From 3eaa433ca1cbee753698893b7732819ba2e31302 Mon Sep 17 00:00:00 2001 +From: Jian Wang +Date: Thu, 10 Feb 2022 19:43:55 +0800 +Subject: [PATCH] i386: cache passthrough: Update Intel CPUID4.EAX[25:14] based + on vCPU topo + +On Intel target, when host cache passthrough is disabled we will +emulate the guest caches with default values and initialize the +shared cpu list of the caches based on vCPU topology. However when +host cache passthrough is enabled, the shared cpu list is consistent +with host regardless what the vCPU topology is. + +For example, when cache passthrough is enabled, running a guest +with vThreads=1 on a host with pThreads=2, we will get that there +are every *two* logical vCPUs sharing a L1/L2 cache, which is not +consistent with the vCPU topology (vThreads=1). + +So let's reinitialize BITs[25:14] of Intel CPUID 4 based on the +actual vCPU topology instead of host pCPU topology. + +Signed-off-by: Jian Wang +Signed-off-by: Yanan Wang +--- + target/i386/cpu.c | 27 +++++++++++++++++++++++---- + 1 file changed, 23 insertions(+), 4 deletions(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 868cf3e7e8..c1fe2895fd 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -5196,7 +5196,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, + { + X86CPU *cpu = env_archcpu(env); + CPUState *cs = env_cpu(env); +- uint32_t die_offset; ++ uint32_t die_offset, smt_width; + uint32_t limit; + uint32_t signature[3]; + X86CPUTopoInfo topo_info; +@@ -5205,6 +5205,9 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, + topo_info.cores_per_die = cs->nr_cores; + topo_info.threads_per_core = cs->nr_threads; + ++ die_offset = apicid_die_offset(&topo_info); ++ smt_width = apicid_smt_width(&topo_info); ++ + /* Calculate & apply limits for different index ranges */ + if (index >= 0xC0000000) { + limit = env->cpuid_xlevel2; +@@ -5272,8 +5275,25 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, + /* cache info: needed for Core compatibility */ + if (cpu->cache_info_passthrough) { + host_cpuid(index, count, eax, ebx, ecx, edx); +- /* QEMU gives out its own APIC IDs, never pass down bits 31..26. */ +- *eax &= ~0xFC000000; ++ /* ++ * QEMU gives out its own APIC IDs, never pass down bits 31..26. ++ * Update the cache topo bits 25..14, according to the guest ++ * vCPU topology instead of the host pCPU topology. ++ */ ++ *eax &= ~0xFFFFC000; ++ switch (count) { ++ case 0: /* L1 dcache info */ ++ case 1: /* L1 icache info */ ++ case 2: /* L2 cache info */ ++ *eax |= ((1 << smt_width) - 1) << 14; ++ break; ++ case 3: /* L3 cache info */ ++ *eax |= ((1 << die_offset) - 1) << 14; ++ break; ++ default: /* end of info */ ++ *eax = *ebx = *ecx = *edx = 0; ++ break; ++ } + if ((*eax & 31) && cs->nr_cores > 1) { + *eax |= (cs->nr_cores - 1) << 26; + } +@@ -5298,7 +5318,6 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, + eax, ebx, ecx, edx); + break; + case 3: /* L3 cache info */ +- die_offset = apicid_die_offset(&topo_info); + if (cpu->enable_l3_cache) { + encode_cache_cpuid4(env->cache_info_cpuid4.l3_cache, + (1 << die_offset), cs->nr_cores, +-- +2.27.0 + -- Gitee From e08c7937cac3ea9390d2b27d217711399533ca11 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Thu, 10 Feb 2022 20:06:01 +0800 Subject: [PATCH 38/54] i386: cache passthrough: Update AMD 8000_001D.EAX[25:14] based on vCPU topo On AMD target, when host cache passthrough is disabled we will emulate the guest caches with default values and initialize the shared cpu list of the caches based on vCPU topology. However when host cache passthrough is enabled, the shared cpu list is consistent with host regardless what the vCPU topology is. For example, when cache passthrough is enabled, running a guest with vThreads=1 on a host with pThreads=2, we will get that there are every *two* logical vCPUs sharing a L1/L2 cache, which is not consistent with the vCPU topology (vThreads=1). So let's reinitialize BITs[25:14] of AMD CPUID 8000_001D.EAX based on the actual vCPU topology instead of host pCPU topology. Signed-off-by: Yanan Wang --- ...hrough-Update-AMD-8000_001D.EAX-25-1.patch | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 i386-cache-passthrough-Update-AMD-8000_001D.EAX-25-1.patch diff --git a/i386-cache-passthrough-Update-AMD-8000_001D.EAX-25-1.patch b/i386-cache-passthrough-Update-AMD-8000_001D.EAX-25-1.patch new file mode 100644 index 0000000..7ffe327 --- /dev/null +++ b/i386-cache-passthrough-Update-AMD-8000_001D.EAX-25-1.patch @@ -0,0 +1,64 @@ +From 475988057789a1f4dcd7354c8a07fd37dcbac79f Mon Sep 17 00:00:00 2001 +From: Yanan Wang +Date: Thu, 10 Feb 2022 20:06:01 +0800 +Subject: [PATCH] i386: cache passthrough: Update AMD 8000_001D.EAX[25:14] + based on vCPU topo + +On AMD target, when host cache passthrough is disabled we will +emulate the guest caches with default values and initialize the +shared cpu list of the caches based on vCPU topology. However +when host cache passthrough is enabled, the shared cpu list is +consistent with host regardless what the vCPU topology is. + +For example, when cache passthrough is enabled, running a guest +with vThreads=1 on a host with pThreads=2, we will get that there +are every *two* logical vCPUs sharing a L1/L2 cache, which is not +consistent with the vCPU topology (vThreads=1). + +So let's reinitialize BITs[25:14] of AMD CPUID 8000_001D.EAX +based on the actual vCPU topology instead of host pCPU topology. + +Signed-off-by: Yanan Wang +--- + target/i386/cpu.c | 22 ++++++++++++++++++++++ + 1 file changed, 22 insertions(+) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index c1fe2895fd..002e32650d 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -5724,9 +5724,31 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, + } + break; + case 0x8000001D: ++ /* Populate AMD Processor Cache Information */ + *eax = 0; + if (cpu->cache_info_passthrough) { + host_cpuid(index, count, eax, ebx, ecx, edx); ++ ++ /* ++ * Clear BITs[25:14] and then update them based on the guest ++ * vCPU topology, like what we do in encode_cache_cpuid8000001d ++ * when cache_info_passthrough is not enabled. ++ */ ++ *eax &= ~0x03FFC000; ++ switch (count) { ++ case 0: /* L1 dcache info */ ++ case 1: /* L1 icache info */ ++ case 2: /* L2 cache info */ ++ *eax |= ((topo_info.threads_per_core - 1) << 14); ++ break; ++ case 3: /* L3 cache info */ ++ *eax |= ((topo_info.cores_per_die * ++ topo_info.threads_per_core - 1) << 14); ++ break; ++ default: /* end of info */ ++ *eax = *ebx = *ecx = *edx = 0; ++ break; ++ } + break; + } + switch (count) { +-- +2.27.0 + -- Gitee From f71b2f6b430781aae0c8b79da361cfb2df0e297b Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Fri, 11 Feb 2022 16:42:34 +0800 Subject: [PATCH 39/54] =?UTF-8?q?spec:=20Update=20patch=20and=20changelog?= =?UTF-8?q?=20with=20!241=20x86=20cache=E9=80=8F=E4=BC=A0=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E8=A1=A5=E4=B8=81=E5=9B=9E=E5=90=88=20=20!241?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit i386: cache passthrough: Update Intel CPUID4.EAX[25:14] based on vCPU topo i386: cache passthrough: Update AMD 8000_001D.EAX[25:14] based on vCPU topo Signed-off-by: Chen Qun --- qemu.spec | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/qemu.spec b/qemu.spec index 73c14ef..255be52 100644 --- a/qemu.spec +++ b/qemu.spec @@ -66,6 +66,8 @@ Patch0053: scsi-cdrom-Fix-crash-after-remote-cdrom-detached.patch Patch0054: block-bugfix-disable-process-AIO-when-attach-scsi-di.patch Patch0055: block-bugfix-Don-t-pause-vm-when-NOSPACE-EIO-happene.patch Patch0056: scsi-bugfix-fix-division-by-zero.patch +Patch0057: i386-cache-passthrough-Update-Intel-CPUID4.EAX-25-14.patch +Patch0058: i386-cache-passthrough-Update-AMD-8000_001D.EAX-25-1.patch BuildRequires: flex BuildRequires: gcc @@ -508,6 +510,10 @@ getent passwd qemu >/dev/null || \ %endif %changelog +* Fri Feb 11 2022 Chen Qun +- i386: cache passthrough: Update Intel CPUID4.EAX[25:14] based on vCPU topo +- i386: cache passthrough: Update AMD 8000_001D.EAX[25:14] based on vCPU topo + * Fri Feb 11 2022 Chen Qun - nbd/server.c: fix invalid read after client was already free - qemu-nbd: make native as the default aio mode -- Gitee From 539c9995260eb49787fa1378c3e2968c86787705 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Thu, 6 Aug 2020 16:14:25 +0800 Subject: [PATCH 40/54] target/arm: convert isar regs to array The isar in ARMCPU is a struct, each field of which represents an ID register. It's not convenient for us to support CPU feature in AArch64. So let's change it to an array first and add an enum as the index of the array for convenience. Since we will never access high 32-bits of ID registers in AArch32, it's harmless to change the ID registers in AArch32 to 64-bits. Signed-off-by: zhanghailiang Signed-off-by: Peng Liang Signed-off-by: Dongxu Sun --- target-arm-convert-isar-regs-to-array.patch | 2781 +++++++++++++++++++ 1 file changed, 2781 insertions(+) create mode 100644 target-arm-convert-isar-regs-to-array.patch diff --git a/target-arm-convert-isar-regs-to-array.patch b/target-arm-convert-isar-regs-to-array.patch new file mode 100644 index 0000000..14e9a08 --- /dev/null +++ b/target-arm-convert-isar-regs-to-array.patch @@ -0,0 +1,2781 @@ +From bd8514594f0226b4599019ff123321138bb04d39 Mon Sep 17 00:00:00 2001 +From: Peng Liang +Date: Thu, 6 Aug 2020 16:14:25 +0800 +Subject: [PATCH] target/arm: convert isar regs to array + +The isar in ARMCPU is a struct, each field of which represents an ID +register. It's not convenient for us to support CPU feature in AArch64. +So let's change it to an array first and add an enum as the index of the +array for convenience. Since we will never access high 32-bits of ID +registers in AArch32, it's harmless to change the ID registers in +AArch32 to 64-bits. + +Signed-off-by: zhanghailiang +Signed-off-by: Peng Liang +Signed-off-by: Dongxu Sun +--- + hw/intc/armv7m_nvic.c | 32 +-- + target/arm/cpu.c | 105 ++++----- + target/arm/cpu.h | 298 ++++++++++++------------ + target/arm/cpu64.c | 234 +++++++++---------- + target/arm/cpu_tcg.c | 503 +++++++++++++++++++++-------------------- + target/arm/helper.c | 64 +++--- + target/arm/hvf/hvf.c | 20 +- + target/arm/internals.h | 14 +- + target/arm/kvm64.c | 81 +++---- + 9 files changed, 683 insertions(+), 668 deletions(-) + +diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c +index 13df002ce4..4b12b209b7 100644 +--- a/hw/intc/armv7m_nvic.c ++++ b/hw/intc/armv7m_nvic.c +@@ -1273,17 +1273,17 @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs) + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } +- return cpu->isar.id_pfr0; ++ return cpu->isar.regs[ID_PFR0]; + case 0xd44: /* PFR1. */ + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } +- return cpu->isar.id_pfr1; ++ return cpu->isar.regs[ID_PFR1]; + case 0xd48: /* DFR0. */ + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } +- return cpu->isar.id_dfr0; ++ return cpu->isar.regs[ID_DFR0]; + case 0xd4c: /* AFR0. */ + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; +@@ -1293,52 +1293,52 @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs) + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } +- return cpu->isar.id_mmfr0; ++ return cpu->isar.regs[ID_MMFR0]; + case 0xd54: /* MMFR1. */ + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } +- return cpu->isar.id_mmfr1; ++ return cpu->isar.regs[ID_MMFR1]; + case 0xd58: /* MMFR2. */ + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } +- return cpu->isar.id_mmfr2; ++ return cpu->isar.regs[ID_MMFR2]; + case 0xd5c: /* MMFR3. */ + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } +- return cpu->isar.id_mmfr3; ++ return cpu->isar.regs[ID_MMFR3]; + case 0xd60: /* ISAR0. */ + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } +- return cpu->isar.id_isar0; ++ return cpu->isar.regs[ID_ISAR0]; + case 0xd64: /* ISAR1. */ + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } +- return cpu->isar.id_isar1; ++ return cpu->isar.regs[ID_ISAR1]; + case 0xd68: /* ISAR2. */ + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } +- return cpu->isar.id_isar2; ++ return cpu->isar.regs[ID_ISAR2]; + case 0xd6c: /* ISAR3. */ + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } +- return cpu->isar.id_isar3; ++ return cpu->isar.regs[ID_ISAR3]; + case 0xd70: /* ISAR4. */ + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } +- return cpu->isar.id_isar4; ++ return cpu->isar.regs[ID_ISAR4]; + case 0xd74: /* ISAR5. */ + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } +- return cpu->isar.id_isar5; ++ return cpu->isar.regs[ID_ISAR5]; + case 0xd78: /* CLIDR */ + return cpu->clidr; + case 0xd7c: /* CTR */ +@@ -1548,11 +1548,11 @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs) + } + return cpu->env.v7m.fpdscr[attrs.secure]; + case 0xf40: /* MVFR0 */ +- return cpu->isar.mvfr0; ++ return cpu->isar.regs[MVFR0]; + case 0xf44: /* MVFR1 */ +- return cpu->isar.mvfr1; ++ return cpu->isar.regs[MVFR1]; + case 0xf48: /* MVFR2 */ +- return cpu->isar.mvfr2; ++ return cpu->isar.regs[MVFR2]; + default: + bad_offset: + qemu_log_mask(LOG_GUEST_ERROR, "NVIC: Bad read offset 0x%x\n", offset); +diff --git a/target/arm/cpu.c b/target/arm/cpu.c +index a211804fd3..f1ce0474a3 100644 +--- a/target/arm/cpu.c ++++ b/target/arm/cpu.c +@@ -176,9 +176,9 @@ static void arm_cpu_reset(DeviceState *dev) + g_hash_table_foreach(cpu->cp_regs, cp_reg_check_reset, cpu); + + env->vfp.xregs[ARM_VFP_FPSID] = cpu->reset_fpsid; +- env->vfp.xregs[ARM_VFP_MVFR0] = cpu->isar.mvfr0; +- env->vfp.xregs[ARM_VFP_MVFR1] = cpu->isar.mvfr1; +- env->vfp.xregs[ARM_VFP_MVFR2] = cpu->isar.mvfr2; ++ env->vfp.xregs[ARM_VFP_MVFR0] = cpu->isar.regs[MVFR0]; ++ env->vfp.xregs[ARM_VFP_MVFR1] = cpu->isar.regs[MVFR1]; ++ env->vfp.xregs[ARM_VFP_MVFR2] = cpu->isar.regs[MVFR2]; + + cpu->power_state = s->start_powered_off ? PSCI_OFF : PSCI_ON; + +@@ -1520,20 +1520,20 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) + uint64_t t; + uint32_t u; + +- t = cpu->isar.id_aa64isar1; ++ t = cpu->isar.regs[ID_AA64ISAR1]; + t = FIELD_DP64(t, ID_AA64ISAR1, JSCVT, 0); +- cpu->isar.id_aa64isar1 = t; ++ cpu->isar.regs[ID_AA64ISAR1] = t; + +- t = cpu->isar.id_aa64pfr0; ++ t = cpu->isar.regs[ID_AA64PFR0]; + t = FIELD_DP64(t, ID_AA64PFR0, FP, 0xf); +- cpu->isar.id_aa64pfr0 = t; ++ cpu->isar.regs[ID_AA64PFR0] = t; + +- u = cpu->isar.id_isar6; ++ u = cpu->isar.regs[ID_ISAR6]; + u = FIELD_DP32(u, ID_ISAR6, JSCVT, 0); + u = FIELD_DP32(u, ID_ISAR6, BF16, 0); +- cpu->isar.id_isar6 = u; ++ cpu->isar.regs[ID_ISAR6] = u; + +- u = cpu->isar.mvfr0; ++ u = cpu->isar.regs[MVFR0]; + u = FIELD_DP32(u, MVFR0, FPSP, 0); + u = FIELD_DP32(u, MVFR0, FPDP, 0); + u = FIELD_DP32(u, MVFR0, FPDIVIDE, 0); +@@ -1543,20 +1543,20 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) + u = FIELD_DP32(u, MVFR0, FPTRAP, 0); + u = FIELD_DP32(u, MVFR0, FPSHVEC, 0); + } +- cpu->isar.mvfr0 = u; ++ cpu->isar.regs[MVFR0] = u; + +- u = cpu->isar.mvfr1; ++ u = cpu->isar.regs[MVFR1]; + u = FIELD_DP32(u, MVFR1, FPFTZ, 0); + u = FIELD_DP32(u, MVFR1, FPDNAN, 0); + u = FIELD_DP32(u, MVFR1, FPHP, 0); + if (arm_feature(env, ARM_FEATURE_M)) { + u = FIELD_DP32(u, MVFR1, FP16, 0); + } +- cpu->isar.mvfr1 = u; ++ cpu->isar.regs[MVFR1] = u; + +- u = cpu->isar.mvfr2; ++ u = cpu->isar.regs[MVFR2]; + u = FIELD_DP32(u, MVFR2, FPMISC, 0); +- cpu->isar.mvfr2 = u; ++ cpu->isar.regs[MVFR2] = u; + } + + if (!cpu->has_neon) { +@@ -1565,43 +1565,43 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) + + unset_feature(env, ARM_FEATURE_NEON); + +- t = cpu->isar.id_aa64isar0; ++ t = cpu->isar.regs[ID_AA64ISAR0]; + t = FIELD_DP64(t, ID_AA64ISAR0, DP, 0); +- cpu->isar.id_aa64isar0 = t; ++ cpu->isar.regs[ID_AA64ISAR0] = t; + +- t = cpu->isar.id_aa64isar1; ++ t = cpu->isar.regs[ID_AA64ISAR1]; + t = FIELD_DP64(t, ID_AA64ISAR1, FCMA, 0); + t = FIELD_DP64(t, ID_AA64ISAR1, BF16, 0); + t = FIELD_DP64(t, ID_AA64ISAR1, I8MM, 0); +- cpu->isar.id_aa64isar1 = t; ++ cpu->isar.regs[ID_AA64ISAR1] = t; + +- t = cpu->isar.id_aa64pfr0; ++ t = cpu->isar.regs[ID_AA64PFR0]; + t = FIELD_DP64(t, ID_AA64PFR0, ADVSIMD, 0xf); +- cpu->isar.id_aa64pfr0 = t; ++ cpu->isar.regs[ID_AA64PFR0] = t; + +- u = cpu->isar.id_isar5; ++ u = cpu->isar.regs[ID_ISAR5]; + u = FIELD_DP32(u, ID_ISAR5, RDM, 0); + u = FIELD_DP32(u, ID_ISAR5, VCMA, 0); +- cpu->isar.id_isar5 = u; ++ cpu->isar.regs[ID_ISAR5] = u; + +- u = cpu->isar.id_isar6; ++ u = cpu->isar.regs[ID_ISAR6]; + u = FIELD_DP32(u, ID_ISAR6, DP, 0); + u = FIELD_DP32(u, ID_ISAR6, FHM, 0); + u = FIELD_DP32(u, ID_ISAR6, BF16, 0); + u = FIELD_DP32(u, ID_ISAR6, I8MM, 0); +- cpu->isar.id_isar6 = u; ++ cpu->isar.regs[ID_ISAR6] = u; + + if (!arm_feature(env, ARM_FEATURE_M)) { +- u = cpu->isar.mvfr1; ++ u = cpu->isar.regs[MVFR1]; + u = FIELD_DP32(u, MVFR1, SIMDLS, 0); + u = FIELD_DP32(u, MVFR1, SIMDINT, 0); + u = FIELD_DP32(u, MVFR1, SIMDSP, 0); + u = FIELD_DP32(u, MVFR1, SIMDHP, 0); +- cpu->isar.mvfr1 = u; ++ cpu->isar.regs[MVFR1] = u; + +- u = cpu->isar.mvfr2; ++ u = cpu->isar.regs[MVFR2]; + u = FIELD_DP32(u, MVFR2, SIMDMISC, 0); +- cpu->isar.mvfr2 = u; ++ cpu->isar.regs[MVFR2] = u; + } + } + +@@ -1609,22 +1609,22 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) + uint64_t t; + uint32_t u; + +- t = cpu->isar.id_aa64isar0; ++ t = cpu->isar.regs[ID_AA64ISAR0]; + t = FIELD_DP64(t, ID_AA64ISAR0, FHM, 0); +- cpu->isar.id_aa64isar0 = t; ++ cpu->isar.regs[ID_AA64ISAR0] = t; + +- t = cpu->isar.id_aa64isar1; ++ t = cpu->isar.regs[ID_AA64ISAR1]; + t = FIELD_DP64(t, ID_AA64ISAR1, FRINTTS, 0); +- cpu->isar.id_aa64isar1 = t; ++ cpu->isar.regs[ID_AA64ISAR1] = t; + +- u = cpu->isar.mvfr0; ++ u = cpu->isar.regs[MVFR0]; + u = FIELD_DP32(u, MVFR0, SIMDREG, 0); +- cpu->isar.mvfr0 = u; ++ cpu->isar.regs[MVFR0] = u; + + /* Despite the name, this field covers both VFP and Neon */ +- u = cpu->isar.mvfr1; ++ u = cpu->isar.regs[MVFR1]; + u = FIELD_DP32(u, MVFR1, SIMDFMAC, 0); +- cpu->isar.mvfr1 = u; ++ cpu->isar.regs[MVFR1] = u; + } + + if (arm_feature(env, ARM_FEATURE_M) && !cpu->has_dsp) { +@@ -1632,19 +1632,19 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) + + unset_feature(env, ARM_FEATURE_THUMB_DSP); + +- u = cpu->isar.id_isar1; ++ u = cpu->isar.regs[ID_ISAR1]; + u = FIELD_DP32(u, ID_ISAR1, EXTEND, 1); +- cpu->isar.id_isar1 = u; ++ cpu->isar.regs[ID_ISAR1] = u; + +- u = cpu->isar.id_isar2; ++ u = cpu->isar.regs[ID_ISAR2]; + u = FIELD_DP32(u, ID_ISAR2, MULTU, 1); + u = FIELD_DP32(u, ID_ISAR2, MULTS, 1); +- cpu->isar.id_isar2 = u; ++ cpu->isar.regs[ID_ISAR2] = u; + +- u = cpu->isar.id_isar3; ++ u = cpu->isar.regs[ID_ISAR3]; + u = FIELD_DP32(u, ID_ISAR3, SIMD, 1); + u = FIELD_DP32(u, ID_ISAR3, SATURATE, 0); +- cpu->isar.id_isar3 = u; ++ cpu->isar.regs[ID_ISAR3] = u; + } + + /* Some features automatically imply others: */ +@@ -1785,8 +1785,8 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) + /* Disable the security extension feature bits in the processor feature + * registers as well. These are id_pfr1[7:4] and id_aa64pfr0[15:12]. + */ +- cpu->isar.id_pfr1 &= ~0xf0; +- cpu->isar.id_aa64pfr0 &= ~0xf000; ++ cpu->isar.regs[ID_PFR1] &= ~0xf0; ++ cpu->isar.regs[ID_AA64PFR0] &= ~0xf000; + } + + if (!cpu->has_el2) { +@@ -1809,9 +1809,10 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) + cpu); + #endif + } else { +- cpu->isar.id_aa64dfr0 = +- FIELD_DP64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, PMUVER, 0); +- cpu->isar.id_dfr0 = FIELD_DP32(cpu->isar.id_dfr0, ID_DFR0, PERFMON, 0); ++ cpu->isar.regs[ID_AA64DFR0] = ++ FIELD_DP64(cpu->isar.regs[ID_AA64DFR0], ID_AA64DFR0, PMUVER, 0); ++ cpu->isar.regs[ID_DFR0] = FIELD_DP32(cpu->isar.regs[ID_DFR0], ID_DFR0, ++ PERFMON, 0); + cpu->pmceid0 = 0; + cpu->pmceid1 = 0; + } +@@ -1821,8 +1822,8 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) + * registers if we don't have EL2. These are id_pfr1[15:12] and + * id_aa64pfr0_el1[11:8]. + */ +- cpu->isar.id_aa64pfr0 &= ~0xf00; +- cpu->isar.id_pfr1 &= ~0xf000; ++ cpu->isar.regs[ID_AA64PFR0] &= ~0xf00; ++ cpu->isar.regs[ID_PFR1] &= ~0xf000; + } + + #ifndef CONFIG_USER_ONLY +@@ -1831,8 +1832,8 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) + * Disable the MTE feature bits if we do not have tag-memory + * provided by the machine. + */ +- cpu->isar.id_aa64pfr1 = +- FIELD_DP64(cpu->isar.id_aa64pfr1, ID_AA64PFR1, MTE, 0); ++ cpu->isar.regs[ID_AA64PFR1] = ++ FIELD_DP64(cpu->isar.regs[ID_AA64PFR1], ID_AA64PFR1, MTE, 0); + } + #endif + +diff --git a/target/arm/cpu.h b/target/arm/cpu.h +index e33f37b70a..3dda33f347 100644 +--- a/target/arm/cpu.h ++++ b/target/arm/cpu.h +@@ -69,6 +69,41 @@ + #define ARMV7M_EXCP_PENDSV 14 + #define ARMV7M_EXCP_SYSTICK 15 + ++typedef enum CPUIDReg { ++ MIDR_EL1, ++ ID_ISAR0, ++ ID_ISAR1, ++ ID_ISAR2, ++ ID_ISAR3, ++ ID_ISAR4, ++ ID_ISAR5, ++ ID_ISAR6, ++ ID_PFR0, ++ ID_PFR1, ++ ID_PFR2, ++ ID_MMFR0, ++ ID_MMFR1, ++ ID_MMFR2, ++ ID_MMFR3, ++ ID_MMFR4, ++ ID_AA64ISAR0, ++ ID_AA64ISAR1, ++ ID_AA64PFR0, ++ ID_AA64PFR1, ++ ID_AA64MMFR0, ++ ID_AA64MMFR1, ++ ID_AA64MMFR2, ++ ID_AA64DFR0, ++ ID_AA64DFR1, ++ ID_AA64ZFR0, ++ ID_DFR0, ++ MVFR0, ++ MVFR1, ++ MVFR2, ++ DBGDIDR, ++ ID_MAX, ++} CPUIDReg; ++ + /* For M profile, some registers are banked secure vs non-secure; + * these are represented as a 2-element array where the first element + * is the non-secure copy and the second is the secure copy. +@@ -922,36 +957,7 @@ struct ARMCPU { + * field by reading the value from the KVM vCPU. + */ + struct ARMISARegisters { +- uint32_t id_isar0; +- uint32_t id_isar1; +- uint32_t id_isar2; +- uint32_t id_isar3; +- uint32_t id_isar4; +- uint32_t id_isar5; +- uint32_t id_isar6; +- uint32_t id_mmfr0; +- uint32_t id_mmfr1; +- uint32_t id_mmfr2; +- uint32_t id_mmfr3; +- uint32_t id_mmfr4; +- uint32_t id_pfr0; +- uint32_t id_pfr1; +- uint32_t id_pfr2; +- uint32_t mvfr0; +- uint32_t mvfr1; +- uint32_t mvfr2; +- uint32_t id_dfr0; +- uint32_t dbgdidr; +- uint64_t id_aa64isar0; +- uint64_t id_aa64isar1; +- uint64_t id_aa64pfr0; +- uint64_t id_aa64pfr1; +- uint64_t id_aa64mmfr0; +- uint64_t id_aa64mmfr1; +- uint64_t id_aa64mmfr2; +- uint64_t id_aa64dfr0; +- uint64_t id_aa64dfr1; +- uint64_t id_aa64zfr0; ++ uint64_t regs[ID_MAX]; + } isar; + uint64_t midr; + uint32_t revidr; +@@ -3729,103 +3735,103 @@ static inline target_ulong cpu_untagged_addr(CPUState *cs, target_ulong x) + */ + static inline bool isar_feature_aa32_thumb_div(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_isar0, ID_ISAR0, DIVIDE) != 0; ++ return FIELD_EX32(id->regs[ID_ISAR0], ID_ISAR0, DIVIDE) != 0; + } + + static inline bool isar_feature_aa32_arm_div(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_isar0, ID_ISAR0, DIVIDE) > 1; ++ return FIELD_EX32(id->regs[ID_ISAR0], ID_ISAR0, DIVIDE) > 1; + } + + static inline bool isar_feature_aa32_lob(const ARMISARegisters *id) + { + /* (M-profile) low-overhead loops and branch future */ +- return FIELD_EX32(id->id_isar0, ID_ISAR0, CMPBRANCH) >= 3; ++ return FIELD_EX32(id->regs[ID_ISAR0], ID_ISAR0, CMPBRANCH) >= 3; + } + + static inline bool isar_feature_aa32_jazelle(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_isar1, ID_ISAR1, JAZELLE) != 0; ++ return FIELD_EX32(id->regs[ID_ISAR1], ID_ISAR1, JAZELLE) != 0; + } + + static inline bool isar_feature_aa32_aes(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_isar5, ID_ISAR5, AES) != 0; ++ return FIELD_EX32(id->regs[ID_ISAR5], ID_ISAR5, AES) != 0; + } + + static inline bool isar_feature_aa32_pmull(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_isar5, ID_ISAR5, AES) > 1; ++ return FIELD_EX32(id->regs[ID_ISAR5], ID_ISAR5, AES) > 1; + } + + static inline bool isar_feature_aa32_sha1(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_isar5, ID_ISAR5, SHA1) != 0; ++ return FIELD_EX32(id->regs[ID_ISAR5], ID_ISAR5, SHA1) != 0; + } + + static inline bool isar_feature_aa32_sha2(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_isar5, ID_ISAR5, SHA2) != 0; ++ return FIELD_EX32(id->regs[ID_ISAR5], ID_ISAR5, SHA2) != 0; + } + + static inline bool isar_feature_aa32_crc32(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_isar5, ID_ISAR5, CRC32) != 0; ++ return FIELD_EX32(id->regs[ID_ISAR5], ID_ISAR5, CRC32) != 0; + } + + static inline bool isar_feature_aa32_rdm(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_isar5, ID_ISAR5, RDM) != 0; ++ return FIELD_EX32(id->regs[ID_ISAR5], ID_ISAR5, RDM) != 0; + } + + static inline bool isar_feature_aa32_vcma(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_isar5, ID_ISAR5, VCMA) != 0; ++ return FIELD_EX32(id->regs[ID_ISAR5], ID_ISAR5, VCMA) != 0; + } + + static inline bool isar_feature_aa32_jscvt(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_isar6, ID_ISAR6, JSCVT) != 0; ++ return FIELD_EX32(id->regs[ID_ISAR6], ID_ISAR6, JSCVT) != 0; + } + + static inline bool isar_feature_aa32_dp(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_isar6, ID_ISAR6, DP) != 0; ++ return FIELD_EX32(id->regs[ID_ISAR6], ID_ISAR6, DP) != 0; + } + + static inline bool isar_feature_aa32_fhm(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_isar6, ID_ISAR6, FHM) != 0; ++ return FIELD_EX32(id->regs[ID_ISAR6], ID_ISAR6, FHM) != 0; + } + + static inline bool isar_feature_aa32_sb(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_isar6, ID_ISAR6, SB) != 0; ++ return FIELD_EX32(id->regs[ID_ISAR6], ID_ISAR6, SB) != 0; + } + + static inline bool isar_feature_aa32_predinv(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_isar6, ID_ISAR6, SPECRES) != 0; ++ return FIELD_EX32(id->regs[ID_ISAR6], ID_ISAR6, SPECRES) != 0; + } + + static inline bool isar_feature_aa32_bf16(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_isar6, ID_ISAR6, BF16) != 0; ++ return FIELD_EX32(id->regs[ID_ISAR6], ID_ISAR6, BF16) != 0; + } + + static inline bool isar_feature_aa32_i8mm(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_isar6, ID_ISAR6, I8MM) != 0; ++ return FIELD_EX32(id->regs[ID_ISAR6], ID_ISAR6, I8MM) != 0; + } + + static inline bool isar_feature_aa32_ras(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_pfr0, ID_PFR0, RAS) != 0; ++ return FIELD_EX32(id->regs[ID_PFR0], ID_PFR0, RAS) != 0; + } + + static inline bool isar_feature_aa32_mprofile(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_pfr1, ID_PFR1, MPROGMOD) != 0; ++ return FIELD_EX32(id->regs[ID_PFR1], ID_PFR1, MPROGMOD) != 0; + } + + static inline bool isar_feature_aa32_m_sec_state(const ARMISARegisters *id) +@@ -3834,16 +3840,16 @@ static inline bool isar_feature_aa32_m_sec_state(const ARMISARegisters *id) + * Return true if M-profile state handling insns + * (VSCCLRM, CLRM, FPCTX access insns) are implemented + */ +- return FIELD_EX32(id->id_pfr1, ID_PFR1, SECURITY) >= 3; ++ return FIELD_EX32(id->regs[ID_PFR1], ID_PFR1, SECURITY) >= 3; + } + + static inline bool isar_feature_aa32_fp16_arith(const ARMISARegisters *id) + { + /* Sadly this is encoded differently for A-profile and M-profile */ + if (isar_feature_aa32_mprofile(id)) { +- return FIELD_EX32(id->mvfr1, MVFR1, FP16) > 0; ++ return FIELD_EX32(id->regs[MVFR1], MVFR1, FP16) > 0; + } else { +- return FIELD_EX32(id->mvfr1, MVFR1, FPHP) >= 3; ++ return FIELD_EX32(id->regs[MVFR1], MVFR1, FPHP) >= 3; + } + } + +@@ -3855,7 +3861,7 @@ static inline bool isar_feature_aa32_mve(const ARMISARegisters *id) + * else for A-profile. + */ + return isar_feature_aa32_mprofile(id) && +- FIELD_EX32(id->mvfr1, MVFR1, MVE) > 0; ++ FIELD_EX32(id->regs[MVFR1], MVFR1, MVE) > 0; + } + + static inline bool isar_feature_aa32_mve_fp(const ARMISARegisters *id) +@@ -3866,7 +3872,7 @@ static inline bool isar_feature_aa32_mve_fp(const ARMISARegisters *id) + * else for A-profile. + */ + return isar_feature_aa32_mprofile(id) && +- FIELD_EX32(id->mvfr1, MVFR1, MVE) >= 2; ++ FIELD_EX32(id->regs[MVFR1], MVFR1, MVE) >= 2; + } + + static inline bool isar_feature_aa32_vfp_simd(const ARMISARegisters *id) +@@ -3875,42 +3881,42 @@ static inline bool isar_feature_aa32_vfp_simd(const ARMISARegisters *id) + * Return true if either VFP or SIMD is implemented. + * In this case, a minimum of VFP w/ D0-D15. + */ +- return FIELD_EX32(id->mvfr0, MVFR0, SIMDREG) > 0; ++ return FIELD_EX32(id->regs[MVFR0], MVFR0, SIMDREG) > 0; + } + + static inline bool isar_feature_aa32_simd_r32(const ARMISARegisters *id) + { + /* Return true if D16-D31 are implemented */ +- return FIELD_EX32(id->mvfr0, MVFR0, SIMDREG) >= 2; ++ return FIELD_EX32(id->regs[MVFR0], MVFR0, SIMDREG) >= 2; + } + + static inline bool isar_feature_aa32_fpshvec(const ARMISARegisters *id) + { +- return FIELD_EX32(id->mvfr0, MVFR0, FPSHVEC) > 0; ++ return FIELD_EX32(id->regs[MVFR0], MVFR0, FPSHVEC) > 0; + } + + static inline bool isar_feature_aa32_fpsp_v2(const ARMISARegisters *id) + { + /* Return true if CPU supports single precision floating point, VFPv2 */ +- return FIELD_EX32(id->mvfr0, MVFR0, FPSP) > 0; ++ return FIELD_EX32(id->regs[MVFR0], MVFR0, FPSP) > 0; + } + + static inline bool isar_feature_aa32_fpsp_v3(const ARMISARegisters *id) + { + /* Return true if CPU supports single precision floating point, VFPv3 */ +- return FIELD_EX32(id->mvfr0, MVFR0, FPSP) >= 2; ++ return FIELD_EX32(id->regs[MVFR0], MVFR0, FPSP) >= 2; + } + + static inline bool isar_feature_aa32_fpdp_v2(const ARMISARegisters *id) + { + /* Return true if CPU supports double precision floating point, VFPv2 */ +- return FIELD_EX32(id->mvfr0, MVFR0, FPDP) > 0; ++ return FIELD_EX32(id->regs[MVFR0], MVFR0, FPDP) > 0; + } + + static inline bool isar_feature_aa32_fpdp_v3(const ARMISARegisters *id) + { + /* Return true if CPU supports double precision floating point, VFPv3 */ +- return FIELD_EX32(id->mvfr0, MVFR0, FPDP) >= 2; ++ return FIELD_EX32(id->regs[MVFR0], MVFR0, FPDP) >= 2; + } + + static inline bool isar_feature_aa32_vfp(const ARMISARegisters *id) +@@ -3925,12 +3931,12 @@ static inline bool isar_feature_aa32_vfp(const ARMISARegisters *id) + */ + static inline bool isar_feature_aa32_fp16_spconv(const ARMISARegisters *id) + { +- return FIELD_EX32(id->mvfr1, MVFR1, FPHP) > 0; ++ return FIELD_EX32(id->regs[MVFR1], MVFR1, FPHP) > 0; + } + + static inline bool isar_feature_aa32_fp16_dpconv(const ARMISARegisters *id) + { +- return FIELD_EX32(id->mvfr1, MVFR1, FPHP) > 1; ++ return FIELD_EX32(id->regs[MVFR1], MVFR1, FPHP) > 1; + } + + /* +@@ -3942,86 +3948,86 @@ static inline bool isar_feature_aa32_fp16_dpconv(const ARMISARegisters *id) + */ + static inline bool isar_feature_aa32_simdfmac(const ARMISARegisters *id) + { +- return FIELD_EX32(id->mvfr1, MVFR1, SIMDFMAC) != 0; ++ return FIELD_EX32(id->regs[MVFR1], MVFR1, SIMDFMAC) != 0; + } + + static inline bool isar_feature_aa32_vsel(const ARMISARegisters *id) + { +- return FIELD_EX32(id->mvfr2, MVFR2, FPMISC) >= 1; ++ return FIELD_EX32(id->regs[MVFR2], MVFR2, FPMISC) >= 1; + } + + static inline bool isar_feature_aa32_vcvt_dr(const ARMISARegisters *id) + { +- return FIELD_EX32(id->mvfr2, MVFR2, FPMISC) >= 2; ++ return FIELD_EX32(id->regs[MVFR2], MVFR2, FPMISC) >= 2; + } + + static inline bool isar_feature_aa32_vrint(const ARMISARegisters *id) + { +- return FIELD_EX32(id->mvfr2, MVFR2, FPMISC) >= 3; ++ return FIELD_EX32(id->regs[MVFR2], MVFR2, FPMISC) >= 3; + } + + static inline bool isar_feature_aa32_vminmaxnm(const ARMISARegisters *id) + { +- return FIELD_EX32(id->mvfr2, MVFR2, FPMISC) >= 4; ++ return FIELD_EX32(id->regs[MVFR2], MVFR2, FPMISC) >= 4; + } + + static inline bool isar_feature_aa32_pxn(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_mmfr0, ID_MMFR0, VMSA) >= 4; ++ return FIELD_EX32(id->regs[ID_MMFR0], ID_MMFR0, VMSA) >= 4; + } + + static inline bool isar_feature_aa32_pan(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_mmfr3, ID_MMFR3, PAN) != 0; ++ return FIELD_EX32(id->regs[ID_MMFR3], ID_MMFR3, PAN) != 0; + } + + static inline bool isar_feature_aa32_ats1e1(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_mmfr3, ID_MMFR3, PAN) >= 2; ++ return FIELD_EX32(id->regs[ID_MMFR3], ID_MMFR3, PAN) >= 2; + } + + static inline bool isar_feature_aa32_pmu_8_1(const ARMISARegisters *id) + { + /* 0xf means "non-standard IMPDEF PMU" */ +- return FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) >= 4 && +- FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) != 0xf; ++ return FIELD_EX32(id->regs[ID_DFR0], ID_DFR0, PERFMON) >= 4 && ++ FIELD_EX32(id->regs[ID_DFR0], ID_DFR0, PERFMON) != 0xf; + } + + static inline bool isar_feature_aa32_pmu_8_4(const ARMISARegisters *id) + { + /* 0xf means "non-standard IMPDEF PMU" */ +- return FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) >= 5 && +- FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) != 0xf; ++ return FIELD_EX32(id->regs[ID_DFR0], ID_DFR0, PERFMON) >= 5 && ++ FIELD_EX32(id->regs[ID_DFR0], ID_DFR0, PERFMON) != 0xf; + } + + static inline bool isar_feature_aa32_hpd(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_mmfr4, ID_MMFR4, HPDS) != 0; ++ return FIELD_EX32(id->regs[ID_MMFR4], ID_MMFR4, HPDS) != 0; + } + + static inline bool isar_feature_aa32_ac2(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_mmfr4, ID_MMFR4, AC2) != 0; ++ return FIELD_EX32(id->regs[ID_MMFR4], ID_MMFR4, AC2) != 0; + } + + static inline bool isar_feature_aa32_ccidx(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_mmfr4, ID_MMFR4, CCIDX) != 0; ++ return FIELD_EX32(id->regs[ID_MMFR4], ID_MMFR4, CCIDX) != 0; + } + + static inline bool isar_feature_aa32_tts2uxn(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_mmfr4, ID_MMFR4, XNX) != 0; ++ return FIELD_EX32(id->regs[ID_MMFR4], ID_MMFR4, XNX) != 0; + } + + static inline bool isar_feature_aa32_dit(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_pfr0, ID_PFR0, DIT) != 0; ++ return FIELD_EX32(id->regs[ID_PFR0], ID_PFR0, DIT) != 0; + } + + static inline bool isar_feature_aa32_ssbs(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_pfr2, ID_PFR2, SSBS) != 0; ++ return FIELD_EX32(id->regs[ID_PFR2], ID_PFR2, SSBS) != 0; + } + + /* +@@ -4029,92 +4035,92 @@ static inline bool isar_feature_aa32_ssbs(const ARMISARegisters *id) + */ + static inline bool isar_feature_aa64_aes(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, AES) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ISAR0], ID_AA64ISAR0, AES) != 0; + } + + static inline bool isar_feature_aa64_pmull(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, AES) > 1; ++ return FIELD_EX64(id->regs[ID_AA64ISAR0], ID_AA64ISAR0, AES) > 1; + } + + static inline bool isar_feature_aa64_sha1(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, SHA1) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ISAR0], ID_AA64ISAR0, SHA1) != 0; + } + + static inline bool isar_feature_aa64_sha256(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, SHA2) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ISAR0], ID_AA64ISAR0, SHA2) != 0; + } + + static inline bool isar_feature_aa64_sha512(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, SHA2) > 1; ++ return FIELD_EX64(id->regs[ID_AA64ISAR0], ID_AA64ISAR0, SHA2) > 1; + } + + static inline bool isar_feature_aa64_crc32(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, CRC32) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ISAR0], ID_AA64ISAR0, CRC32) != 0; + } + + static inline bool isar_feature_aa64_atomics(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, ATOMIC) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ISAR0], ID_AA64ISAR0, ATOMIC) != 0; + } + + static inline bool isar_feature_aa64_rdm(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, RDM) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ISAR0], ID_AA64ISAR0, RDM) != 0; + } + + static inline bool isar_feature_aa64_sha3(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, SHA3) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ISAR0], ID_AA64ISAR0, SHA3) != 0; + } + + static inline bool isar_feature_aa64_sm3(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, SM3) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ISAR0], ID_AA64ISAR0, SM3) != 0; + } + + static inline bool isar_feature_aa64_sm4(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, SM4) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ISAR0], ID_AA64ISAR0, SM4) != 0; + } + + static inline bool isar_feature_aa64_dp(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, DP) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ISAR0], ID_AA64ISAR0, DP) != 0; + } + + static inline bool isar_feature_aa64_fhm(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, FHM) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ISAR0], ID_AA64ISAR0, FHM) != 0; + } + + static inline bool isar_feature_aa64_condm_4(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, TS) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ISAR0], ID_AA64ISAR0, TS) != 0; + } + + static inline bool isar_feature_aa64_condm_5(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, TS) >= 2; ++ return FIELD_EX64(id->regs[ID_AA64ISAR0], ID_AA64ISAR0, TS) >= 2; + } + + static inline bool isar_feature_aa64_rndr(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, RNDR) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ISAR0], ID_AA64ISAR0, RNDR) != 0; + } + + static inline bool isar_feature_aa64_jscvt(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, JSCVT) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ISAR1], ID_AA64ISAR1, JSCVT) != 0; + } + + static inline bool isar_feature_aa64_fcma(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, FCMA) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ISAR1], ID_AA64ISAR1, FCMA) != 0; + } + + static inline bool isar_feature_aa64_pauth(const ARMISARegisters *id) +@@ -4123,7 +4129,7 @@ static inline bool isar_feature_aa64_pauth(const ARMISARegisters *id) + * Return true if any form of pauth is enabled, as this + * predicate controls migration of the 128-bit keys. + */ +- return (id->id_aa64isar1 & ++ return (id->regs[ID_AA64ISAR1] & + (FIELD_DP64(0, ID_AA64ISAR1, APA, 0xf) | + FIELD_DP64(0, ID_AA64ISAR1, API, 0xf) | + FIELD_DP64(0, ID_AA64ISAR1, GPA, 0xf) | +@@ -4136,221 +4142,221 @@ static inline bool isar_feature_aa64_pauth_arch(const ARMISARegisters *id) + * Return true if pauth is enabled with the architected QARMA algorithm. + * QEMU will always set APA+GPA to the same value. + */ +- return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, APA) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ISAR1], ID_AA64ISAR1, APA) != 0; + } + + static inline bool isar_feature_aa64_tlbirange(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, TLB) == 2; ++ return FIELD_EX64(id->regs[ID_AA64ISAR0], ID_AA64ISAR0, TLB) == 2; + } + + static inline bool isar_feature_aa64_tlbios(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, TLB) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ISAR0], ID_AA64ISAR0, TLB) != 0; + } + + static inline bool isar_feature_aa64_sb(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, SB) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ISAR1], ID_AA64ISAR1, SB) != 0; + } + + static inline bool isar_feature_aa64_predinv(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, SPECRES) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ISAR1], ID_AA64ISAR1, SPECRES) != 0; + } + + static inline bool isar_feature_aa64_frint(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, FRINTTS) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ISAR1], ID_AA64ISAR1, FRINTTS) != 0; + } + + static inline bool isar_feature_aa64_dcpop(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, DPB) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ISAR1], ID_AA64ISAR1, DPB) != 0; + } + + static inline bool isar_feature_aa64_dcpodp(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, DPB) >= 2; ++ return FIELD_EX64(id->regs[ID_AA64ISAR1], ID_AA64ISAR1, DPB) >= 2; + } + + static inline bool isar_feature_aa64_bf16(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, BF16) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ISAR1], ID_AA64ISAR1, BF16) != 0; + } + + static inline bool isar_feature_aa64_fp_simd(const ARMISARegisters *id) + { + /* We always set the AdvSIMD and FP fields identically. */ +- return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, FP) != 0xf; ++ return FIELD_EX64(id->regs[ID_AA64PFR0], ID_AA64PFR0, FP) != 0xf; + } + + static inline bool isar_feature_aa64_fp16(const ARMISARegisters *id) + { + /* We always set the AdvSIMD and FP fields identically wrt FP16. */ +- return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, FP) == 1; ++ return FIELD_EX64(id->regs[ID_AA64PFR0], ID_AA64PFR0, FP) == 1; + } + + static inline bool isar_feature_aa64_aa32(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, EL0) >= 2; ++ return FIELD_EX64(id->regs[ID_AA64PFR0], ID_AA64PFR0, EL0) >= 2; + } + + static inline bool isar_feature_aa64_aa32_el1(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, EL1) >= 2; ++ return FIELD_EX64(id->regs[ID_AA64PFR0], ID_AA64PFR0, EL1) >= 2; + } + + static inline bool isar_feature_aa64_sve(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, SVE) != 0; ++ return FIELD_EX64(id->regs[ID_AA64PFR0], ID_AA64PFR0, SVE) != 0; + } + + static inline bool isar_feature_aa64_sel2(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, SEL2) != 0; ++ return FIELD_EX64(id->regs[ID_AA64PFR0], ID_AA64PFR0, SEL2) != 0; + } + + static inline bool isar_feature_aa64_vh(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, VH) != 0; ++ return FIELD_EX64(id->regs[ID_AA64MMFR1], ID_AA64MMFR1, VH) != 0; + } + + static inline bool isar_feature_aa64_lor(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, LO) != 0; ++ return FIELD_EX64(id->regs[ID_AA64MMFR1], ID_AA64MMFR1, LO) != 0; + } + + static inline bool isar_feature_aa64_pan(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, PAN) != 0; ++ return FIELD_EX64(id->regs[ID_AA64MMFR1], ID_AA64MMFR1, PAN) != 0; + } + + static inline bool isar_feature_aa64_ats1e1(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, PAN) >= 2; ++ return FIELD_EX64(id->regs[ID_AA64MMFR1], ID_AA64MMFR1, PAN) >= 2; + } + + static inline bool isar_feature_aa64_uao(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, UAO) != 0; ++ return FIELD_EX64(id->regs[ID_AA64MMFR2], ID_AA64MMFR2, UAO) != 0; + } + + static inline bool isar_feature_aa64_st(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, ST) != 0; ++ return FIELD_EX64(id->regs[ID_AA64MMFR2], ID_AA64MMFR2, ST) != 0; + } + + static inline bool isar_feature_aa64_bti(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, BT) != 0; ++ return FIELD_EX64(id->regs[ID_AA64PFR1], ID_AA64PFR1, BT) != 0; + } + + static inline bool isar_feature_aa64_mte_insn_reg(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, MTE) != 0; ++ return FIELD_EX64(id->regs[ID_AA64PFR1], ID_AA64PFR1, MTE) != 0; + } + + static inline bool isar_feature_aa64_mte(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, MTE) >= 2; ++ return FIELD_EX64(id->regs[ID_AA64PFR1], ID_AA64PFR1, MTE) >= 2; + } + + static inline bool isar_feature_aa64_pmu_8_1(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) >= 4 && +- FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) != 0xf; ++ return FIELD_EX64(id->regs[ID_AA64DFR0], ID_AA64DFR0, PMUVER) >= 4 && ++ FIELD_EX64(id->regs[ID_AA64DFR0], ID_AA64DFR0, PMUVER) != 0xf; + } + + static inline bool isar_feature_aa64_pmu_8_4(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) >= 5 && +- FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) != 0xf; ++ return FIELD_EX64(id->regs[ID_AA64DFR0], ID_AA64DFR0, PMUVER) >= 5 && ++ FIELD_EX64(id->regs[ID_AA64DFR0], ID_AA64DFR0, PMUVER) != 0xf; + } + + static inline bool isar_feature_aa64_rcpc_8_3(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, LRCPC) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ISAR1], ID_AA64ISAR1, LRCPC) != 0; + } + + static inline bool isar_feature_aa64_rcpc_8_4(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, LRCPC) >= 2; ++ return FIELD_EX64(id->regs[ID_AA64ISAR1], ID_AA64ISAR1, LRCPC) >= 2; + } + + static inline bool isar_feature_aa64_i8mm(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, I8MM) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ISAR1], ID_AA64ISAR1, I8MM) != 0; + } + + static inline bool isar_feature_aa64_ccidx(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, CCIDX) != 0; ++ return FIELD_EX64(id->regs[ID_AA64MMFR2], ID_AA64MMFR2, CCIDX) != 0; + } + + static inline bool isar_feature_aa64_tts2uxn(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, XNX) != 0; ++ return FIELD_EX64(id->regs[ID_AA64MMFR1], ID_AA64MMFR1, XNX) != 0; + } + + static inline bool isar_feature_aa64_dit(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, DIT) != 0; ++ return FIELD_EX64(id->regs[ID_AA64PFR0], ID_AA64PFR0, DIT) != 0; + } + + static inline bool isar_feature_aa64_ssbs(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, SSBS) != 0; ++ return FIELD_EX64(id->regs[ID_AA64PFR1], ID_AA64PFR1, SSBS) != 0; + } + + static inline bool isar_feature_aa64_sve2(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, SVEVER) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ZFR0], ID_AA64ZFR0, SVEVER) != 0; + } + + static inline bool isar_feature_aa64_sve2_aes(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, AES) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ZFR0], ID_AA64ZFR0, AES) != 0; + } + + static inline bool isar_feature_aa64_sve2_pmull128(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, AES) >= 2; ++ return FIELD_EX64(id->regs[ID_AA64ZFR0], ID_AA64ZFR0, AES) >= 2; + } + + static inline bool isar_feature_aa64_sve2_bitperm(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, BITPERM) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ZFR0], ID_AA64ZFR0, BITPERM) != 0; + } + + static inline bool isar_feature_aa64_sve_bf16(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, BFLOAT16) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ZFR0], ID_AA64ZFR0, BFLOAT16) != 0; + } + + static inline bool isar_feature_aa64_sve2_sha3(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, SHA3) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ZFR0], ID_AA64ZFR0, SHA3) != 0; + } + + static inline bool isar_feature_aa64_sve2_sm4(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, SM4) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ZFR0], ID_AA64ZFR0, SM4) != 0; + } + + static inline bool isar_feature_aa64_sve_i8mm(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, I8MM) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ZFR0], ID_AA64ZFR0, I8MM) != 0; + } + + static inline bool isar_feature_aa64_sve_f32mm(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, F32MM) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ZFR0], ID_AA64ZFR0, F32MM) != 0; + } + + static inline bool isar_feature_aa64_sve_f64mm(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, F64MM) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ZFR0], ID_AA64ZFR0, F64MM) != 0; + } + + /* +diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c +index 1b56261964..96a49a3158 100644 +--- a/target/arm/cpu64.c ++++ b/target/arm/cpu64.c +@@ -108,31 +108,31 @@ static void aarch64_a57_initfn(Object *obj) + cpu->midr = 0x411fd070; + cpu->revidr = 0x00000000; + cpu->reset_fpsid = 0x41034070; +- cpu->isar.mvfr0 = 0x10110222; +- cpu->isar.mvfr1 = 0x12111111; +- cpu->isar.mvfr2 = 0x00000043; ++ cpu->isar.regs[MVFR0] = 0x10110222; ++ cpu->isar.regs[MVFR1] = 0x12111111; ++ cpu->isar.regs[MVFR2] = 0x00000043; + cpu->ctr = 0x8444c004; + cpu->reset_sctlr = 0x00c50838; +- cpu->isar.id_pfr0 = 0x00000131; +- cpu->isar.id_pfr1 = 0x00011011; +- cpu->isar.id_dfr0 = 0x03010066; ++ cpu->isar.regs[ID_PFR0] = 0x00000131; ++ cpu->isar.regs[ID_PFR1] = 0x00011011; ++ cpu->isar.regs[ID_DFR0] = 0x03010066; + cpu->id_afr0 = 0x00000000; +- cpu->isar.id_mmfr0 = 0x10101105; +- cpu->isar.id_mmfr1 = 0x40000000; +- cpu->isar.id_mmfr2 = 0x01260000; +- cpu->isar.id_mmfr3 = 0x02102211; +- cpu->isar.id_isar0 = 0x02101110; +- cpu->isar.id_isar1 = 0x13112111; +- cpu->isar.id_isar2 = 0x21232042; +- cpu->isar.id_isar3 = 0x01112131; +- cpu->isar.id_isar4 = 0x00011142; +- cpu->isar.id_isar5 = 0x00011121; +- cpu->isar.id_isar6 = 0; +- cpu->isar.id_aa64pfr0 = 0x00002222; +- cpu->isar.id_aa64dfr0 = 0x10305106; +- cpu->isar.id_aa64isar0 = 0x00011120; +- cpu->isar.id_aa64mmfr0 = 0x00001124; +- cpu->isar.dbgdidr = 0x3516d000; ++ cpu->isar.regs[ID_MMFR0] = 0x10101105; ++ cpu->isar.regs[ID_MMFR1] = 0x40000000; ++ cpu->isar.regs[ID_MMFR2] = 0x01260000; ++ cpu->isar.regs[ID_MMFR3] = 0x02102211; ++ cpu->isar.regs[ID_ISAR0] = 0x02101110; ++ cpu->isar.regs[ID_ISAR1] = 0x13112111; ++ cpu->isar.regs[ID_ISAR2] = 0x21232042; ++ cpu->isar.regs[ID_ISAR3] = 0x01112131; ++ cpu->isar.regs[ID_ISAR4] = 0x00011142; ++ cpu->isar.regs[ID_ISAR5] = 0x00011121; ++ cpu->isar.regs[ID_ISAR6] = 0; ++ cpu->isar.regs[ID_AA64PFR0] = 0x00002222; ++ cpu->isar.regs[ID_AA64DFR0] = 0x10305106; ++ cpu->isar.regs[ID_AA64ISAR0] = 0x00011120; ++ cpu->isar.regs[ID_AA64MMFR0] = 0x00001124; ++ cpu->isar.regs[DBGDIDR] = 0x3516d000; + cpu->clidr = 0x0a200023; + cpu->ccsidr[0] = 0x701fe00a; /* 32KB L1 dcache */ + cpu->ccsidr[1] = 0x201fe012; /* 48KB L1 icache */ +@@ -161,31 +161,31 @@ static void aarch64_a53_initfn(Object *obj) + cpu->midr = 0x410fd034; + cpu->revidr = 0x00000000; + cpu->reset_fpsid = 0x41034070; +- cpu->isar.mvfr0 = 0x10110222; +- cpu->isar.mvfr1 = 0x12111111; +- cpu->isar.mvfr2 = 0x00000043; ++ cpu->isar.regs[MVFR0] = 0x10110222; ++ cpu->isar.regs[MVFR1] = 0x12111111; ++ cpu->isar.regs[MVFR2] = 0x00000043; + cpu->ctr = 0x84448004; /* L1Ip = VIPT */ + cpu->reset_sctlr = 0x00c50838; +- cpu->isar.id_pfr0 = 0x00000131; +- cpu->isar.id_pfr1 = 0x00011011; +- cpu->isar.id_dfr0 = 0x03010066; ++ cpu->isar.regs[ID_PFR0] = 0x00000131; ++ cpu->isar.regs[ID_PFR1] = 0x00011011; ++ cpu->isar.regs[ID_DFR0] = 0x03010066; + cpu->id_afr0 = 0x00000000; +- cpu->isar.id_mmfr0 = 0x10101105; +- cpu->isar.id_mmfr1 = 0x40000000; +- cpu->isar.id_mmfr2 = 0x01260000; +- cpu->isar.id_mmfr3 = 0x02102211; +- cpu->isar.id_isar0 = 0x02101110; +- cpu->isar.id_isar1 = 0x13112111; +- cpu->isar.id_isar2 = 0x21232042; +- cpu->isar.id_isar3 = 0x01112131; +- cpu->isar.id_isar4 = 0x00011142; +- cpu->isar.id_isar5 = 0x00011121; +- cpu->isar.id_isar6 = 0; +- cpu->isar.id_aa64pfr0 = 0x00002222; +- cpu->isar.id_aa64dfr0 = 0x10305106; +- cpu->isar.id_aa64isar0 = 0x00011120; +- cpu->isar.id_aa64mmfr0 = 0x00001122; /* 40 bit physical addr */ +- cpu->isar.dbgdidr = 0x3516d000; ++ cpu->isar.regs[ID_MMFR0] = 0x10101105; ++ cpu->isar.regs[ID_MMFR1] = 0x40000000; ++ cpu->isar.regs[ID_MMFR2] = 0x01260000; ++ cpu->isar.regs[ID_MMFR3] = 0x02102211; ++ cpu->isar.regs[ID_ISAR0] = 0x02101110; ++ cpu->isar.regs[ID_ISAR1] = 0x13112111; ++ cpu->isar.regs[ID_ISAR2] = 0x21232042; ++ cpu->isar.regs[ID_ISAR3] = 0x01112131; ++ cpu->isar.regs[ID_ISAR4] = 0x00011142; ++ cpu->isar.regs[ID_ISAR5] = 0x00011121; ++ cpu->isar.regs[ID_ISAR6] = 0; ++ cpu->isar.regs[ID_AA64PFR0] = 0x00002222; ++ cpu->isar.regs[ID_AA64DFR0] = 0x10305106; ++ cpu->isar.regs[ID_AA64ISAR0] = 0x00011120; ++ cpu->isar.regs[ID_AA64MMFR0] = 0x00001122; /* 40 bit physical addr */ ++ cpu->isar.regs[DBGDIDR] = 0x3516d000; + cpu->clidr = 0x0a200023; + cpu->ccsidr[0] = 0x700fe01a; /* 32KB L1 dcache */ + cpu->ccsidr[1] = 0x201fe00a; /* 32KB L1 icache */ +@@ -214,30 +214,30 @@ static void aarch64_a72_initfn(Object *obj) + cpu->midr = 0x410fd083; + cpu->revidr = 0x00000000; + cpu->reset_fpsid = 0x41034080; +- cpu->isar.mvfr0 = 0x10110222; +- cpu->isar.mvfr1 = 0x12111111; +- cpu->isar.mvfr2 = 0x00000043; ++ cpu->isar.regs[MVFR0] = 0x10110222; ++ cpu->isar.regs[MVFR1] = 0x12111111; ++ cpu->isar.regs[MVFR2] = 0x00000043; + cpu->ctr = 0x8444c004; + cpu->reset_sctlr = 0x00c50838; +- cpu->isar.id_pfr0 = 0x00000131; +- cpu->isar.id_pfr1 = 0x00011011; +- cpu->isar.id_dfr0 = 0x03010066; ++ cpu->isar.regs[ID_PFR0] = 0x00000131; ++ cpu->isar.regs[ID_PFR1] = 0x00011011; ++ cpu->isar.regs[ID_DFR0] = 0x03010066; + cpu->id_afr0 = 0x00000000; +- cpu->isar.id_mmfr0 = 0x10201105; +- cpu->isar.id_mmfr1 = 0x40000000; +- cpu->isar.id_mmfr2 = 0x01260000; +- cpu->isar.id_mmfr3 = 0x02102211; +- cpu->isar.id_isar0 = 0x02101110; +- cpu->isar.id_isar1 = 0x13112111; +- cpu->isar.id_isar2 = 0x21232042; +- cpu->isar.id_isar3 = 0x01112131; +- cpu->isar.id_isar4 = 0x00011142; +- cpu->isar.id_isar5 = 0x00011121; +- cpu->isar.id_aa64pfr0 = 0x00002222; +- cpu->isar.id_aa64dfr0 = 0x10305106; +- cpu->isar.id_aa64isar0 = 0x00011120; +- cpu->isar.id_aa64mmfr0 = 0x00001124; +- cpu->isar.dbgdidr = 0x3516d000; ++ cpu->isar.regs[ID_MMFR0] = 0x10201105; ++ cpu->isar.regs[ID_MMFR1] = 0x40000000; ++ cpu->isar.regs[ID_MMFR2] = 0x01260000; ++ cpu->isar.regs[ID_MMFR3] = 0x02102211; ++ cpu->isar.regs[ID_ISAR0] = 0x02101110; ++ cpu->isar.regs[ID_ISAR1] = 0x13112111; ++ cpu->isar.regs[ID_ISAR2] = 0x21232042; ++ cpu->isar.regs[ID_ISAR3] = 0x01112131; ++ cpu->isar.regs[ID_ISAR4] = 0x00011142; ++ cpu->isar.regs[ID_ISAR5] = 0x00011121; ++ cpu->isar.regs[ID_AA64PFR0] = 0x00002222; ++ cpu->isar.regs[ID_AA64DFR0] = 0x10305106; ++ cpu->isar.regs[ID_AA64ISAR0] = 0x00011120; ++ cpu->isar.regs[ID_AA64MMFR0] = 0x00001124; ++ cpu->isar.regs[DBGDIDR] = 0x3516d000; + cpu->clidr = 0x0a200023; + cpu->ccsidr[0] = 0x701fe00a; /* 32KB L1 dcache */ + cpu->ccsidr[1] = 0x201fe012; /* 48KB L1 icache */ +@@ -262,10 +262,10 @@ static void aarch64_kunpeng_920_initfn(Object *obj) + + cpu->midr = 0x480fd010; + cpu->ctr = 0x84448004; +- cpu->isar.id_aa64pfr0 = 0x11001111; +- cpu->isar.id_aa64dfr0 = 0x110305408; +- cpu->isar.id_aa64isar0 = 0x10211120; +- cpu->isar.id_aa64mmfr0 = 0x101125; ++ cpu->isar.regs[ID_AA64PFR0] = 0x11001111; ++ cpu->isar.regs[ID_AA64DFR0] = 0x110305408; ++ cpu->isar.regs[ID_AA64ISAR0] = 0x10211120; ++ cpu->isar.regs[ID_AA64MMFR0] = 0x101125; + } + + void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp) +@@ -566,9 +566,9 @@ static void cpu_arm_set_sve(Object *obj, bool value, Error **errp) + return; + } + +- t = cpu->isar.id_aa64pfr0; ++ t = cpu->isar.regs[ID_AA64PFR0]; + t = FIELD_DP64(t, ID_AA64PFR0, SVE, value); +- cpu->isar.id_aa64pfr0 = t; ++ cpu->isar.regs[ID_AA64PFR0] = t; + } + + #ifdef CONFIG_USER_ONLY +@@ -662,12 +662,12 @@ void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp) + error_append_hint(errp, "Add pauth=on to the CPU property list.\n"); + } + +- t = cpu->isar.id_aa64isar1; ++ t = cpu->isar.regs[ID_AA64ISAR1]; + t = FIELD_DP64(t, ID_AA64ISAR1, APA, arch_val); + t = FIELD_DP64(t, ID_AA64ISAR1, GPA, arch_val); + t = FIELD_DP64(t, ID_AA64ISAR1, API, impdef_val); + t = FIELD_DP64(t, ID_AA64ISAR1, GPI, impdef_val); +- cpu->isar.id_aa64isar1 = t; ++ cpu->isar.regs[ID_AA64ISAR1] = t; + } + + static Property arm_cpu_pauth_property = +@@ -736,7 +736,7 @@ static void aarch64_max_initfn(Object *obj) + t = FIELD_DP64(t, MIDR_EL1, REVISION, 0); + cpu->midr = t; + +- t = cpu->isar.id_aa64isar0; ++ t = cpu->isar.regs[ID_AA64ISAR0]; + t = FIELD_DP64(t, ID_AA64ISAR0, AES, 2); /* AES + PMULL */ + t = FIELD_DP64(t, ID_AA64ISAR0, SHA1, 1); + t = FIELD_DP64(t, ID_AA64ISAR0, SHA2, 2); /* SHA512 */ +@@ -751,9 +751,9 @@ static void aarch64_max_initfn(Object *obj) + t = FIELD_DP64(t, ID_AA64ISAR0, TS, 2); /* v8.5-CondM */ + t = FIELD_DP64(t, ID_AA64ISAR0, TLB, 2); /* FEAT_TLBIRANGE */ + t = FIELD_DP64(t, ID_AA64ISAR0, RNDR, 1); +- cpu->isar.id_aa64isar0 = t; ++ cpu->isar.regs[ID_AA64ISAR0] = t; + +- t = cpu->isar.id_aa64isar1; ++ t = cpu->isar.regs[ID_AA64ISAR1]; + t = FIELD_DP64(t, ID_AA64ISAR1, DPB, 2); + t = FIELD_DP64(t, ID_AA64ISAR1, JSCVT, 1); + t = FIELD_DP64(t, ID_AA64ISAR1, FCMA, 1); +@@ -763,17 +763,17 @@ static void aarch64_max_initfn(Object *obj) + t = FIELD_DP64(t, ID_AA64ISAR1, FRINTTS, 1); + t = FIELD_DP64(t, ID_AA64ISAR1, LRCPC, 2); /* ARMv8.4-RCPC */ + t = FIELD_DP64(t, ID_AA64ISAR1, I8MM, 1); +- cpu->isar.id_aa64isar1 = t; ++ cpu->isar.regs[ID_AA64ISAR1] = t; + +- t = cpu->isar.id_aa64pfr0; ++ t = cpu->isar.regs[ID_AA64PFR0]; + t = FIELD_DP64(t, ID_AA64PFR0, SVE, 1); + t = FIELD_DP64(t, ID_AA64PFR0, FP, 1); + t = FIELD_DP64(t, ID_AA64PFR0, ADVSIMD, 1); + t = FIELD_DP64(t, ID_AA64PFR0, SEL2, 1); + t = FIELD_DP64(t, ID_AA64PFR0, DIT, 1); +- cpu->isar.id_aa64pfr0 = t; ++ cpu->isar.regs[ID_AA64PFR0] = t; + +- t = cpu->isar.id_aa64pfr1; ++ t = cpu->isar.regs[ID_AA64PFR1]; + t = FIELD_DP64(t, ID_AA64PFR1, BT, 1); + t = FIELD_DP64(t, ID_AA64PFR1, SSBS, 2); + /* +@@ -782,28 +782,28 @@ static void aarch64_max_initfn(Object *obj) + * we do for EL2 with the virtualization=on property. + */ + t = FIELD_DP64(t, ID_AA64PFR1, MTE, 3); +- cpu->isar.id_aa64pfr1 = t; ++ cpu->isar.regs[ID_AA64PFR1] = t; + +- t = cpu->isar.id_aa64mmfr0; ++ t = cpu->isar.regs[ID_AA64MMFR0]; + t = FIELD_DP64(t, ID_AA64MMFR0, PARANGE, 5); /* PARange: 48 bits */ +- cpu->isar.id_aa64mmfr0 = t; ++ cpu->isar.regs[ID_AA64MMFR0] = t; + +- t = cpu->isar.id_aa64mmfr1; ++ t = cpu->isar.regs[ID_AA64MMFR1]; + t = FIELD_DP64(t, ID_AA64MMFR1, HPDS, 1); /* HPD */ + t = FIELD_DP64(t, ID_AA64MMFR1, LO, 1); + t = FIELD_DP64(t, ID_AA64MMFR1, VH, 1); + t = FIELD_DP64(t, ID_AA64MMFR1, PAN, 2); /* ATS1E1 */ + t = FIELD_DP64(t, ID_AA64MMFR1, VMIDBITS, 2); /* VMID16 */ + t = FIELD_DP64(t, ID_AA64MMFR1, XNX, 1); /* TTS2UXN */ +- cpu->isar.id_aa64mmfr1 = t; ++ cpu->isar.regs[ID_AA64MMFR1] = t; + +- t = cpu->isar.id_aa64mmfr2; ++ t = cpu->isar.regs[ID_AA64MMFR2]; + t = FIELD_DP64(t, ID_AA64MMFR2, UAO, 1); + t = FIELD_DP64(t, ID_AA64MMFR2, CNP, 1); /* TTCNP */ + t = FIELD_DP64(t, ID_AA64MMFR2, ST, 1); /* TTST */ +- cpu->isar.id_aa64mmfr2 = t; ++ cpu->isar.regs[ID_AA64MMFR2] = t; + +- t = cpu->isar.id_aa64zfr0; ++ t = cpu->isar.regs[ID_AA64ZFR0]; + t = FIELD_DP64(t, ID_AA64ZFR0, SVEVER, 1); + t = FIELD_DP64(t, ID_AA64ZFR0, AES, 2); /* PMULL */ + t = FIELD_DP64(t, ID_AA64ZFR0, BITPERM, 1); +@@ -813,19 +813,19 @@ static void aarch64_max_initfn(Object *obj) + t = FIELD_DP64(t, ID_AA64ZFR0, I8MM, 1); + t = FIELD_DP64(t, ID_AA64ZFR0, F32MM, 1); + t = FIELD_DP64(t, ID_AA64ZFR0, F64MM, 1); +- cpu->isar.id_aa64zfr0 = t; ++ cpu->isar.regs[ID_AA64ZFR0] = t; + + /* Replicate the same data to the 32-bit id registers. */ +- u = cpu->isar.id_isar5; ++ u = cpu->isar.regs[ID_ISAR5]; + u = FIELD_DP32(u, ID_ISAR5, AES, 2); /* AES + PMULL */ + u = FIELD_DP32(u, ID_ISAR5, SHA1, 1); + u = FIELD_DP32(u, ID_ISAR5, SHA2, 1); + u = FIELD_DP32(u, ID_ISAR5, CRC32, 1); + u = FIELD_DP32(u, ID_ISAR5, RDM, 1); + u = FIELD_DP32(u, ID_ISAR5, VCMA, 1); +- cpu->isar.id_isar5 = u; ++ cpu->isar.regs[ID_ISAR5] = u; + +- u = cpu->isar.id_isar6; ++ u = cpu->isar.regs[ID_ISAR6]; + u = FIELD_DP32(u, ID_ISAR6, JSCVT, 1); + u = FIELD_DP32(u, ID_ISAR6, DP, 1); + u = FIELD_DP32(u, ID_ISAR6, FHM, 1); +@@ -833,39 +833,39 @@ static void aarch64_max_initfn(Object *obj) + u = FIELD_DP32(u, ID_ISAR6, SPECRES, 1); + u = FIELD_DP32(u, ID_ISAR6, BF16, 1); + u = FIELD_DP32(u, ID_ISAR6, I8MM, 1); +- cpu->isar.id_isar6 = u; ++ cpu->isar.regs[ID_ISAR6] = u; + +- u = cpu->isar.id_pfr0; ++ u = cpu->isar.regs[ID_PFR0]; + u = FIELD_DP32(u, ID_PFR0, DIT, 1); +- cpu->isar.id_pfr0 = u; ++ cpu->isar.regs[ID_PFR0] = u; + +- u = cpu->isar.id_pfr2; ++ u = cpu->isar.regs[ID_PFR2]; + u = FIELD_DP32(u, ID_PFR2, SSBS, 1); +- cpu->isar.id_pfr2 = u; ++ cpu->isar.regs[ID_PFR2] = u; + +- u = cpu->isar.id_mmfr3; ++ u = cpu->isar.regs[ID_MMFR3]; + u = FIELD_DP32(u, ID_MMFR3, PAN, 2); /* ATS1E1 */ +- cpu->isar.id_mmfr3 = u; ++ cpu->isar.regs[ID_MMFR3] = u; + +- u = cpu->isar.id_mmfr4; ++ u = cpu->isar.regs[ID_MMFR4]; + u = FIELD_DP32(u, ID_MMFR4, HPDS, 1); /* AA32HPD */ + u = FIELD_DP32(u, ID_MMFR4, AC2, 1); /* ACTLR2, HACTLR2 */ + u = FIELD_DP32(u, ID_MMFR4, CNP, 1); /* TTCNP */ + u = FIELD_DP32(u, ID_MMFR4, XNX, 1); /* TTS2UXN */ +- cpu->isar.id_mmfr4 = u; ++ cpu->isar.regs[ID_MMFR4] = u; + +- t = cpu->isar.id_aa64dfr0; ++ t = cpu->isar.regs[ID_AA64DFR0]; + t = FIELD_DP64(t, ID_AA64DFR0, PMUVER, 5); /* v8.4-PMU */ +- cpu->isar.id_aa64dfr0 = t; ++ cpu->isar.regs[ID_AA64DFR0] = t; + +- u = cpu->isar.id_dfr0; ++ u = cpu->isar.regs[ID_DFR0]; + u = FIELD_DP32(u, ID_DFR0, PERFMON, 5); /* v8.4-PMU */ +- cpu->isar.id_dfr0 = u; ++ cpu->isar.regs[ID_DFR0] = u; + +- u = cpu->isar.mvfr1; ++ u = cpu->isar.regs[MVFR1]; + u = FIELD_DP32(u, MVFR1, FPHP, 3); /* v8.2-FP16 */ + u = FIELD_DP32(u, MVFR1, SIMDHP, 2); /* v8.2-FP16 */ +- cpu->isar.mvfr1 = u; ++ cpu->isar.regs[MVFR1] = u; + + #ifdef CONFIG_USER_ONLY + /* For usermode -cpu max we can use a larger and more efficient DCZ +@@ -903,18 +903,18 @@ static void aarch64_a64fx_initfn(Object *obj) + cpu->revidr = 0x00000000; + cpu->ctr = 0x86668006; + cpu->reset_sctlr = 0x30000180; +- cpu->isar.id_aa64pfr0 = 0x0000000101111111; /* No RAS Extensions */ +- cpu->isar.id_aa64pfr1 = 0x0000000000000000; +- cpu->isar.id_aa64dfr0 = 0x0000000010305408; +- cpu->isar.id_aa64dfr1 = 0x0000000000000000; ++ cpu->isar.regs[ID_AA64PFR0] = 0x0000000101111111; /* No RAS Extensions */ ++ cpu->isar.regs[ID_AA64PFR1] = 0x0000000000000000; ++ cpu->isar.regs[ID_AA64DFR0] = 0x0000000010305408; ++ cpu->isar.regs[ID_AA64DFR1] = 0x0000000000000000; + cpu->id_aa64afr0 = 0x0000000000000000; + cpu->id_aa64afr1 = 0x0000000000000000; +- cpu->isar.id_aa64mmfr0 = 0x0000000000001122; +- cpu->isar.id_aa64mmfr1 = 0x0000000011212100; +- cpu->isar.id_aa64mmfr2 = 0x0000000000001011; +- cpu->isar.id_aa64isar0 = 0x0000000010211120; +- cpu->isar.id_aa64isar1 = 0x0000000000010001; +- cpu->isar.id_aa64zfr0 = 0x0000000000000000; ++ cpu->isar.regs[ID_AA64MMFR0] = 0x0000000000001122; ++ cpu->isar.regs[ID_AA64MMFR1] = 0x0000000011212100; ++ cpu->isar.regs[ID_AA64MMFR2] = 0x0000000000001011; ++ cpu->isar.regs[ID_AA64ISAR0] = 0x0000000010211120; ++ cpu->isar.regs[ID_AA64ISAR1] = 0x0000000000010001; ++ cpu->isar.regs[ID_AA64ZFR0] = 0x0000000000000000; + cpu->clidr = 0x0000000080000023; + cpu->ccsidr[0] = 0x7007e01c; /* 64KB L1 dcache */ + cpu->ccsidr[1] = 0x2007e01c; /* 64KB L1 icache */ +diff --git a/target/arm/cpu_tcg.c b/target/arm/cpu_tcg.c +index 13d0e9b195..be9c3166fb 100644 +--- a/target/arm/cpu_tcg.c ++++ b/target/arm/cpu_tcg.c +@@ -65,14 +65,16 @@ static void arm926_initfn(Object *obj) + * ARMv5 does not have the ID_ISAR registers, but we can still + * set the field to indicate Jazelle support within QEMU. + */ +- cpu->isar.id_isar1 = FIELD_DP32(cpu->isar.id_isar1, ID_ISAR1, JAZELLE, 1); ++ cpu->isar.regs[ID_ISAR1] = FIELD_DP32(cpu->isar.regs[ID_ISAR1], ID_ISAR1, ++ JAZELLE, 1); + /* + * Similarly, we need to set MVFR0 fields to enable vfp and short vector + * support even though ARMv5 doesn't have this register. + */ +- cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSHVEC, 1); +- cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSP, 1); +- cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPDP, 1); ++ cpu->isar.regs[MVFR0] = FIELD_DP32(cpu->isar.regs[MVFR0], MVFR0, FPSHVEC, ++ 1); ++ cpu->isar.regs[MVFR0] = FIELD_DP32(cpu->isar.regs[MVFR0], MVFR0, FPSP, 1); ++ cpu->isar.regs[MVFR0] = FIELD_DP32(cpu->isar.regs[MVFR0], MVFR0, FPDP, 1); + } + + static void arm946_initfn(Object *obj) +@@ -107,14 +109,16 @@ static void arm1026_initfn(Object *obj) + * ARMv5 does not have the ID_ISAR registers, but we can still + * set the field to indicate Jazelle support within QEMU. + */ +- cpu->isar.id_isar1 = FIELD_DP32(cpu->isar.id_isar1, ID_ISAR1, JAZELLE, 1); ++ cpu->isar.regs[ID_ISAR1] = FIELD_DP32(cpu->isar.regs[ID_ISAR1], ID_ISAR1, ++ JAZELLE, 1); + /* + * Similarly, we need to set MVFR0 fields to enable vfp and short vector + * support even though ARMv5 doesn't have this register. + */ +- cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSHVEC, 1); +- cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSP, 1); +- cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPDP, 1); ++ cpu->isar.regs[MVFR0] = FIELD_DP32(cpu->isar.regs[MVFR0], MVFR0, FPSHVEC, ++ 1); ++ cpu->isar.regs[MVFR0] = FIELD_DP32(cpu->isar.regs[MVFR0], MVFR0, FPSP, 1); ++ cpu->isar.regs[MVFR0] = FIELD_DP32(cpu->isar.regs[MVFR0], MVFR0, FPDP, 1); + + { + /* The 1026 had an IFAR at c6,c0,0,1 rather than the ARMv6 c6,c0,0,2 */ +@@ -147,22 +151,22 @@ static void arm1136_r2_initfn(Object *obj) + set_feature(&cpu->env, ARM_FEATURE_CACHE_BLOCK_OPS); + cpu->midr = 0x4107b362; + cpu->reset_fpsid = 0x410120b4; +- cpu->isar.mvfr0 = 0x11111111; +- cpu->isar.mvfr1 = 0x00000000; ++ cpu->isar.regs[MVFR0] = 0x11111111; ++ cpu->isar.regs[MVFR1] = 0x00000000; + cpu->ctr = 0x1dd20d2; + cpu->reset_sctlr = 0x00050078; +- cpu->isar.id_pfr0 = 0x111; +- cpu->isar.id_pfr1 = 0x1; +- cpu->isar.id_dfr0 = 0x2; ++ cpu->isar.regs[ID_PFR0] = 0x111; ++ cpu->isar.regs[ID_PFR1] = 0x1; ++ cpu->isar.regs[ID_DFR0] = 0x2; + cpu->id_afr0 = 0x3; +- cpu->isar.id_mmfr0 = 0x01130003; +- cpu->isar.id_mmfr1 = 0x10030302; +- cpu->isar.id_mmfr2 = 0x01222110; +- cpu->isar.id_isar0 = 0x00140011; +- cpu->isar.id_isar1 = 0x12002111; +- cpu->isar.id_isar2 = 0x11231111; +- cpu->isar.id_isar3 = 0x01102131; +- cpu->isar.id_isar4 = 0x141; ++ cpu->isar.regs[ID_MMFR0] = 0x01130003; ++ cpu->isar.regs[ID_MMFR1] = 0x10030302; ++ cpu->isar.regs[ID_MMFR2] = 0x01222110; ++ cpu->isar.regs[ID_ISAR0] = 0x00140011; ++ cpu->isar.regs[ID_ISAR1] = 0x12002111; ++ cpu->isar.regs[ID_ISAR2] = 0x11231111; ++ cpu->isar.regs[ID_ISAR3] = 0x01102131; ++ cpu->isar.regs[ID_ISAR4] = 0x141; + cpu->reset_auxcr = 7; + } + +@@ -178,22 +182,22 @@ static void arm1136_initfn(Object *obj) + set_feature(&cpu->env, ARM_FEATURE_CACHE_BLOCK_OPS); + cpu->midr = 0x4117b363; + cpu->reset_fpsid = 0x410120b4; +- cpu->isar.mvfr0 = 0x11111111; +- cpu->isar.mvfr1 = 0x00000000; ++ cpu->isar.regs[MVFR0] = 0x11111111; ++ cpu->isar.regs[MVFR1] = 0x00000000; + cpu->ctr = 0x1dd20d2; + cpu->reset_sctlr = 0x00050078; +- cpu->isar.id_pfr0 = 0x111; +- cpu->isar.id_pfr1 = 0x1; +- cpu->isar.id_dfr0 = 0x2; ++ cpu->isar.regs[ID_PFR0] = 0x111; ++ cpu->isar.regs[ID_PFR1] = 0x1; ++ cpu->isar.regs[ID_DFR0] = 0x2; + cpu->id_afr0 = 0x3; +- cpu->isar.id_mmfr0 = 0x01130003; +- cpu->isar.id_mmfr1 = 0x10030302; +- cpu->isar.id_mmfr2 = 0x01222110; +- cpu->isar.id_isar0 = 0x00140011; +- cpu->isar.id_isar1 = 0x12002111; +- cpu->isar.id_isar2 = 0x11231111; +- cpu->isar.id_isar3 = 0x01102131; +- cpu->isar.id_isar4 = 0x141; ++ cpu->isar.regs[ID_MMFR0] = 0x01130003; ++ cpu->isar.regs[ID_MMFR1] = 0x10030302; ++ cpu->isar.regs[ID_MMFR2] = 0x01222110; ++ cpu->isar.regs[ID_ISAR0] = 0x00140011; ++ cpu->isar.regs[ID_ISAR1] = 0x12002111; ++ cpu->isar.regs[ID_ISAR2] = 0x11231111; ++ cpu->isar.regs[ID_ISAR3] = 0x01102131; ++ cpu->isar.regs[ID_ISAR4] = 0x141; + cpu->reset_auxcr = 7; + } + +@@ -210,22 +214,22 @@ static void arm1176_initfn(Object *obj) + set_feature(&cpu->env, ARM_FEATURE_EL3); + cpu->midr = 0x410fb767; + cpu->reset_fpsid = 0x410120b5; +- cpu->isar.mvfr0 = 0x11111111; +- cpu->isar.mvfr1 = 0x00000000; ++ cpu->isar.regs[MVFR0] = 0x11111111; ++ cpu->isar.regs[MVFR1] = 0x00000000; + cpu->ctr = 0x1dd20d2; + cpu->reset_sctlr = 0x00050078; +- cpu->isar.id_pfr0 = 0x111; +- cpu->isar.id_pfr1 = 0x11; +- cpu->isar.id_dfr0 = 0x33; ++ cpu->isar.regs[ID_PFR0] = 0x111; ++ cpu->isar.regs[ID_PFR1] = 0x11; ++ cpu->isar.regs[ID_DFR0] = 0x33; + cpu->id_afr0 = 0; +- cpu->isar.id_mmfr0 = 0x01130003; +- cpu->isar.id_mmfr1 = 0x10030302; +- cpu->isar.id_mmfr2 = 0x01222100; +- cpu->isar.id_isar0 = 0x0140011; +- cpu->isar.id_isar1 = 0x12002111; +- cpu->isar.id_isar2 = 0x11231121; +- cpu->isar.id_isar3 = 0x01102131; +- cpu->isar.id_isar4 = 0x01141; ++ cpu->isar.regs[ID_MMFR0] = 0x01130003; ++ cpu->isar.regs[ID_MMFR1] = 0x10030302; ++ cpu->isar.regs[ID_MMFR2] = 0x01222100; ++ cpu->isar.regs[ID_ISAR0] = 0x0140011; ++ cpu->isar.regs[ID_ISAR1] = 0x12002111; ++ cpu->isar.regs[ID_ISAR2] = 0x11231121; ++ cpu->isar.regs[ID_ISAR3] = 0x01102131; ++ cpu->isar.regs[ID_ISAR4] = 0x01141; + cpu->reset_auxcr = 7; + } + +@@ -240,21 +244,21 @@ static void arm11mpcore_initfn(Object *obj) + set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS); + cpu->midr = 0x410fb022; + cpu->reset_fpsid = 0x410120b4; +- cpu->isar.mvfr0 = 0x11111111; +- cpu->isar.mvfr1 = 0x00000000; ++ cpu->isar.regs[MVFR0] = 0x11111111; ++ cpu->isar.regs[MVFR1] = 0x00000000; + cpu->ctr = 0x1d192992; /* 32K icache 32K dcache */ +- cpu->isar.id_pfr0 = 0x111; +- cpu->isar.id_pfr1 = 0x1; +- cpu->isar.id_dfr0 = 0; ++ cpu->isar.regs[ID_PFR0] = 0x111; ++ cpu->isar.regs[ID_PFR1] = 0x1; ++ cpu->isar.regs[ID_DFR0] = 0; + cpu->id_afr0 = 0x2; +- cpu->isar.id_mmfr0 = 0x01100103; +- cpu->isar.id_mmfr1 = 0x10020302; +- cpu->isar.id_mmfr2 = 0x01222000; +- cpu->isar.id_isar0 = 0x00100011; +- cpu->isar.id_isar1 = 0x12002111; +- cpu->isar.id_isar2 = 0x11221011; +- cpu->isar.id_isar3 = 0x01102131; +- cpu->isar.id_isar4 = 0x141; ++ cpu->isar.regs[ID_MMFR0] = 0x01100103; ++ cpu->isar.regs[ID_MMFR1] = 0x10020302; ++ cpu->isar.regs[ID_MMFR2] = 0x01222000; ++ cpu->isar.regs[ID_ISAR0] = 0x00100011; ++ cpu->isar.regs[ID_ISAR1] = 0x12002111; ++ cpu->isar.regs[ID_ISAR2] = 0x11221011; ++ cpu->isar.regs[ID_ISAR3] = 0x01102131; ++ cpu->isar.regs[ID_ISAR4] = 0x141; + cpu->reset_auxcr = 1; + } + +@@ -278,24 +282,24 @@ static void cortex_a8_initfn(Object *obj) + set_feature(&cpu->env, ARM_FEATURE_EL3); + cpu->midr = 0x410fc080; + cpu->reset_fpsid = 0x410330c0; +- cpu->isar.mvfr0 = 0x11110222; +- cpu->isar.mvfr1 = 0x00011111; ++ cpu->isar.regs[MVFR0] = 0x11110222; ++ cpu->isar.regs[MVFR1] = 0x00011111; + cpu->ctr = 0x82048004; + cpu->reset_sctlr = 0x00c50078; +- cpu->isar.id_pfr0 = 0x1031; +- cpu->isar.id_pfr1 = 0x11; +- cpu->isar.id_dfr0 = 0x400; ++ cpu->isar.regs[ID_PFR0] = 0x1031; ++ cpu->isar.regs[ID_PFR1] = 0x11; ++ cpu->isar.regs[ID_DFR0] = 0x400; + cpu->id_afr0 = 0; +- cpu->isar.id_mmfr0 = 0x31100003; +- cpu->isar.id_mmfr1 = 0x20000000; +- cpu->isar.id_mmfr2 = 0x01202000; +- cpu->isar.id_mmfr3 = 0x11; +- cpu->isar.id_isar0 = 0x00101111; +- cpu->isar.id_isar1 = 0x12112111; +- cpu->isar.id_isar2 = 0x21232031; +- cpu->isar.id_isar3 = 0x11112131; +- cpu->isar.id_isar4 = 0x00111142; +- cpu->isar.dbgdidr = 0x15141000; ++ cpu->isar.regs[ID_MMFR0] = 0x31100003; ++ cpu->isar.regs[ID_MMFR1] = 0x20000000; ++ cpu->isar.regs[ID_MMFR2] = 0x01202000; ++ cpu->isar.regs[ID_MMFR3] = 0x11; ++ cpu->isar.regs[ID_ISAR0] = 0x00101111; ++ cpu->isar.regs[ID_ISAR1] = 0x12112111; ++ cpu->isar.regs[ID_ISAR2] = 0x21232031; ++ cpu->isar.regs[ID_ISAR3] = 0x11112131; ++ cpu->isar.regs[ID_ISAR4] = 0x00111142; ++ cpu->isar.regs[DBGDIDR] = 0x15141000; + cpu->clidr = (1 << 27) | (2 << 24) | 3; + cpu->ccsidr[0] = 0xe007e01a; /* 16k L1 dcache. */ + cpu->ccsidr[1] = 0x2007e01a; /* 16k L1 icache. */ +@@ -352,24 +356,24 @@ static void cortex_a9_initfn(Object *obj) + set_feature(&cpu->env, ARM_FEATURE_CBAR); + cpu->midr = 0x410fc090; + cpu->reset_fpsid = 0x41033090; +- cpu->isar.mvfr0 = 0x11110222; +- cpu->isar.mvfr1 = 0x01111111; ++ cpu->isar.regs[MVFR0] = 0x11110222; ++ cpu->isar.regs[MVFR1] = 0x01111111; + cpu->ctr = 0x80038003; + cpu->reset_sctlr = 0x00c50078; +- cpu->isar.id_pfr0 = 0x1031; +- cpu->isar.id_pfr1 = 0x11; +- cpu->isar.id_dfr0 = 0x000; ++ cpu->isar.regs[ID_PFR0] = 0x1031; ++ cpu->isar.regs[ID_PFR1] = 0x11; ++ cpu->isar.regs[ID_DFR0] = 0x000; + cpu->id_afr0 = 0; +- cpu->isar.id_mmfr0 = 0x00100103; +- cpu->isar.id_mmfr1 = 0x20000000; +- cpu->isar.id_mmfr2 = 0x01230000; +- cpu->isar.id_mmfr3 = 0x00002111; +- cpu->isar.id_isar0 = 0x00101111; +- cpu->isar.id_isar1 = 0x13112111; +- cpu->isar.id_isar2 = 0x21232041; +- cpu->isar.id_isar3 = 0x11112131; +- cpu->isar.id_isar4 = 0x00111142; +- cpu->isar.dbgdidr = 0x35141000; ++ cpu->isar.regs[ID_MMFR0] = 0x00100103; ++ cpu->isar.regs[ID_MMFR1] = 0x20000000; ++ cpu->isar.regs[ID_MMFR2] = 0x01230000; ++ cpu->isar.regs[ID_MMFR3] = 0x00002111; ++ cpu->isar.regs[ID_ISAR0] = 0x00101111; ++ cpu->isar.regs[ID_ISAR1] = 0x13112111; ++ cpu->isar.regs[ID_ISAR2] = 0x21232041; ++ cpu->isar.regs[ID_ISAR3] = 0x11112131; ++ cpu->isar.regs[ID_ISAR4] = 0x00111142; ++ cpu->isar.regs[DBGDIDR] = 0x35141000; + cpu->clidr = (1 << 27) | (1 << 24) | 3; + cpu->ccsidr[0] = 0xe00fe019; /* 16k L1 dcache. */ + cpu->ccsidr[1] = 0x200fe019; /* 16k L1 icache. */ +@@ -417,28 +421,28 @@ static void cortex_a7_initfn(Object *obj) + cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A7; + cpu->midr = 0x410fc075; + cpu->reset_fpsid = 0x41023075; +- cpu->isar.mvfr0 = 0x10110222; +- cpu->isar.mvfr1 = 0x11111111; ++ cpu->isar.regs[MVFR0] = 0x10110222; ++ cpu->isar.regs[MVFR1] = 0x11111111; + cpu->ctr = 0x84448003; + cpu->reset_sctlr = 0x00c50078; +- cpu->isar.id_pfr0 = 0x00001131; +- cpu->isar.id_pfr1 = 0x00011011; +- cpu->isar.id_dfr0 = 0x02010555; ++ cpu->isar.regs[ID_PFR0] = 0x00001131; ++ cpu->isar.regs[ID_PFR1] = 0x00011011; ++ cpu->isar.regs[ID_DFR0] = 0x02010555; + cpu->id_afr0 = 0x00000000; +- cpu->isar.id_mmfr0 = 0x10101105; +- cpu->isar.id_mmfr1 = 0x40000000; +- cpu->isar.id_mmfr2 = 0x01240000; +- cpu->isar.id_mmfr3 = 0x02102211; ++ cpu->isar.regs[ID_MMFR0] = 0x10101105; ++ cpu->isar.regs[ID_MMFR1] = 0x40000000; ++ cpu->isar.regs[ID_MMFR2] = 0x01240000; ++ cpu->isar.regs[ID_MMFR3] = 0x02102211; + /* + * a7_mpcore_r0p5_trm, page 4-4 gives 0x01101110; but + * table 4-41 gives 0x02101110, which includes the arm div insns. + */ +- cpu->isar.id_isar0 = 0x02101110; +- cpu->isar.id_isar1 = 0x13112111; +- cpu->isar.id_isar2 = 0x21232041; +- cpu->isar.id_isar3 = 0x11112131; +- cpu->isar.id_isar4 = 0x10011142; +- cpu->isar.dbgdidr = 0x3515f005; ++ cpu->isar.regs[ID_ISAR0] = 0x02101110; ++ cpu->isar.regs[ID_ISAR1] = 0x13112111; ++ cpu->isar.regs[ID_ISAR2] = 0x21232041; ++ cpu->isar.regs[ID_ISAR3] = 0x11112131; ++ cpu->isar.regs[ID_ISAR4] = 0x10011142; ++ cpu->isar.regs[DBGDIDR] = 0x3515f005; + cpu->clidr = 0x0a200023; + cpu->ccsidr[0] = 0x701fe00a; /* 32K L1 dcache */ + cpu->ccsidr[1] = 0x201fe00a; /* 32K L1 icache */ +@@ -463,24 +467,24 @@ static void cortex_a15_initfn(Object *obj) + cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A15; + cpu->midr = 0x412fc0f1; + cpu->reset_fpsid = 0x410430f0; +- cpu->isar.mvfr0 = 0x10110222; +- cpu->isar.mvfr1 = 0x11111111; ++ cpu->isar.regs[MVFR0] = 0x10110222; ++ cpu->isar.regs[MVFR1] = 0x11111111; + cpu->ctr = 0x8444c004; + cpu->reset_sctlr = 0x00c50078; +- cpu->isar.id_pfr0 = 0x00001131; +- cpu->isar.id_pfr1 = 0x00011011; +- cpu->isar.id_dfr0 = 0x02010555; ++ cpu->isar.regs[ID_PFR0] = 0x00001131; ++ cpu->isar.regs[ID_PFR1] = 0x00011011; ++ cpu->isar.regs[ID_DFR0] = 0x02010555; + cpu->id_afr0 = 0x00000000; +- cpu->isar.id_mmfr0 = 0x10201105; +- cpu->isar.id_mmfr1 = 0x20000000; +- cpu->isar.id_mmfr2 = 0x01240000; +- cpu->isar.id_mmfr3 = 0x02102211; +- cpu->isar.id_isar0 = 0x02101110; +- cpu->isar.id_isar1 = 0x13112111; +- cpu->isar.id_isar2 = 0x21232041; +- cpu->isar.id_isar3 = 0x11112131; +- cpu->isar.id_isar4 = 0x10011142; +- cpu->isar.dbgdidr = 0x3515f021; ++ cpu->isar.regs[ID_MMFR0] = 0x10201105; ++ cpu->isar.regs[ID_MMFR1] = 0x20000000; ++ cpu->isar.regs[ID_MMFR2] = 0x01240000; ++ cpu->isar.regs[ID_MMFR3] = 0x02102211; ++ cpu->isar.regs[ID_ISAR0] = 0x02101110; ++ cpu->isar.regs[ID_ISAR1] = 0x13112111; ++ cpu->isar.regs[ID_ISAR2] = 0x21232041; ++ cpu->isar.regs[ID_ISAR3] = 0x11112131; ++ cpu->isar.regs[ID_ISAR4] = 0x10011142; ++ cpu->isar.regs[DBGDIDR] = 0x3515f021; + cpu->clidr = 0x0a200023; + cpu->ccsidr[0] = 0x701fe00a; /* 32K L1 dcache */ + cpu->ccsidr[1] = 0x201fe00a; /* 32K L1 icache */ +@@ -504,21 +508,21 @@ static void cortex_m0_initfn(Object *obj) + * by looking at ID register fields. We use the same values as + * for the M3. + */ +- cpu->isar.id_pfr0 = 0x00000030; +- cpu->isar.id_pfr1 = 0x00000200; +- cpu->isar.id_dfr0 = 0x00100000; ++ cpu->isar.regs[ID_PFR0] = 0x00000030; ++ cpu->isar.regs[ID_PFR1] = 0x00000200; ++ cpu->isar.regs[ID_DFR0] = 0x00100000; + cpu->id_afr0 = 0x00000000; +- cpu->isar.id_mmfr0 = 0x00000030; +- cpu->isar.id_mmfr1 = 0x00000000; +- cpu->isar.id_mmfr2 = 0x00000000; +- cpu->isar.id_mmfr3 = 0x00000000; +- cpu->isar.id_isar0 = 0x01141110; +- cpu->isar.id_isar1 = 0x02111000; +- cpu->isar.id_isar2 = 0x21112231; +- cpu->isar.id_isar3 = 0x01111110; +- cpu->isar.id_isar4 = 0x01310102; +- cpu->isar.id_isar5 = 0x00000000; +- cpu->isar.id_isar6 = 0x00000000; ++ cpu->isar.regs[ID_MMFR0] = 0x00000030; ++ cpu->isar.regs[ID_MMFR1] = 0x00000000; ++ cpu->isar.regs[ID_MMFR2] = 0x00000000; ++ cpu->isar.regs[ID_MMFR3] = 0x00000000; ++ cpu->isar.regs[ID_ISAR0] = 0x01141110; ++ cpu->isar.regs[ID_ISAR1] = 0x02111000; ++ cpu->isar.regs[ID_ISAR2] = 0x21112231; ++ cpu->isar.regs[ID_ISAR3] = 0x01111110; ++ cpu->isar.regs[ID_ISAR4] = 0x01310102; ++ cpu->isar.regs[ID_ISAR5] = 0x00000000; ++ cpu->isar.regs[ID_ISAR6] = 0x00000000; + } + + static void cortex_m3_initfn(Object *obj) +@@ -529,21 +533,21 @@ static void cortex_m3_initfn(Object *obj) + set_feature(&cpu->env, ARM_FEATURE_M_MAIN); + cpu->midr = 0x410fc231; + cpu->pmsav7_dregion = 8; +- cpu->isar.id_pfr0 = 0x00000030; +- cpu->isar.id_pfr1 = 0x00000200; +- cpu->isar.id_dfr0 = 0x00100000; ++ cpu->isar.regs[ID_PFR0] = 0x00000030; ++ cpu->isar.regs[ID_PFR1] = 0x00000200; ++ cpu->isar.regs[ID_DFR0] = 0x00100000; + cpu->id_afr0 = 0x00000000; +- cpu->isar.id_mmfr0 = 0x00000030; +- cpu->isar.id_mmfr1 = 0x00000000; +- cpu->isar.id_mmfr2 = 0x00000000; +- cpu->isar.id_mmfr3 = 0x00000000; +- cpu->isar.id_isar0 = 0x01141110; +- cpu->isar.id_isar1 = 0x02111000; +- cpu->isar.id_isar2 = 0x21112231; +- cpu->isar.id_isar3 = 0x01111110; +- cpu->isar.id_isar4 = 0x01310102; +- cpu->isar.id_isar5 = 0x00000000; +- cpu->isar.id_isar6 = 0x00000000; ++ cpu->isar.regs[ID_MMFR0] = 0x00000030; ++ cpu->isar.regs[ID_MMFR1] = 0x00000000; ++ cpu->isar.regs[ID_MMFR2] = 0x00000000; ++ cpu->isar.regs[ID_MMFR3] = 0x00000000; ++ cpu->isar.regs[ID_ISAR0] = 0x01141110; ++ cpu->isar.regs[ID_ISAR1] = 0x02111000; ++ cpu->isar.regs[ID_ISAR2] = 0x21112231; ++ cpu->isar.regs[ID_ISAR3] = 0x01111110; ++ cpu->isar.regs[ID_ISAR4] = 0x01310102; ++ cpu->isar.regs[ID_ISAR5] = 0x00000000; ++ cpu->isar.regs[ID_ISAR6] = 0x00000000; + } + + static void cortex_m4_initfn(Object *obj) +@@ -556,24 +560,24 @@ static void cortex_m4_initfn(Object *obj) + set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP); + cpu->midr = 0x410fc240; /* r0p0 */ + cpu->pmsav7_dregion = 8; +- cpu->isar.mvfr0 = 0x10110021; +- cpu->isar.mvfr1 = 0x11000011; +- cpu->isar.mvfr2 = 0x00000000; +- cpu->isar.id_pfr0 = 0x00000030; +- cpu->isar.id_pfr1 = 0x00000200; +- cpu->isar.id_dfr0 = 0x00100000; ++ cpu->isar.regs[MVFR0] = 0x10110021; ++ cpu->isar.regs[MVFR1] = 0x11000011; ++ cpu->isar.regs[MVFR2] = 0x00000000; ++ cpu->isar.regs[ID_PFR0] = 0x00000030; ++ cpu->isar.regs[ID_PFR1] = 0x00000200; ++ cpu->isar.regs[ID_DFR0] = 0x00100000; + cpu->id_afr0 = 0x00000000; +- cpu->isar.id_mmfr0 = 0x00000030; +- cpu->isar.id_mmfr1 = 0x00000000; +- cpu->isar.id_mmfr2 = 0x00000000; +- cpu->isar.id_mmfr3 = 0x00000000; +- cpu->isar.id_isar0 = 0x01141110; +- cpu->isar.id_isar1 = 0x02111000; +- cpu->isar.id_isar2 = 0x21112231; +- cpu->isar.id_isar3 = 0x01111110; +- cpu->isar.id_isar4 = 0x01310102; +- cpu->isar.id_isar5 = 0x00000000; +- cpu->isar.id_isar6 = 0x00000000; ++ cpu->isar.regs[ID_MMFR0] = 0x00000030; ++ cpu->isar.regs[ID_MMFR1] = 0x00000000; ++ cpu->isar.regs[ID_MMFR2] = 0x00000000; ++ cpu->isar.regs[ID_MMFR3] = 0x00000000; ++ cpu->isar.regs[ID_ISAR0] = 0x01141110; ++ cpu->isar.regs[ID_ISAR1] = 0x02111000; ++ cpu->isar.regs[ID_ISAR2] = 0x21112231; ++ cpu->isar.regs[ID_ISAR3] = 0x01111110; ++ cpu->isar.regs[ID_ISAR4] = 0x01310102; ++ cpu->isar.regs[ID_ISAR5] = 0x00000000; ++ cpu->isar.regs[ID_ISAR6] = 0x00000000; + } + + static void cortex_m7_initfn(Object *obj) +@@ -586,24 +590,24 @@ static void cortex_m7_initfn(Object *obj) + set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP); + cpu->midr = 0x411fc272; /* r1p2 */ + cpu->pmsav7_dregion = 8; +- cpu->isar.mvfr0 = 0x10110221; +- cpu->isar.mvfr1 = 0x12000011; +- cpu->isar.mvfr2 = 0x00000040; +- cpu->isar.id_pfr0 = 0x00000030; +- cpu->isar.id_pfr1 = 0x00000200; +- cpu->isar.id_dfr0 = 0x00100000; ++ cpu->isar.regs[MVFR0] = 0x10110221; ++ cpu->isar.regs[MVFR1] = 0x12000011; ++ cpu->isar.regs[MVFR2] = 0x00000040; ++ cpu->isar.regs[ID_PFR0] = 0x00000030; ++ cpu->isar.regs[ID_PFR1] = 0x00000200; ++ cpu->isar.regs[ID_DFR0] = 0x00100000; + cpu->id_afr0 = 0x00000000; +- cpu->isar.id_mmfr0 = 0x00100030; +- cpu->isar.id_mmfr1 = 0x00000000; +- cpu->isar.id_mmfr2 = 0x01000000; +- cpu->isar.id_mmfr3 = 0x00000000; +- cpu->isar.id_isar0 = 0x01101110; +- cpu->isar.id_isar1 = 0x02112000; +- cpu->isar.id_isar2 = 0x20232231; +- cpu->isar.id_isar3 = 0x01111131; +- cpu->isar.id_isar4 = 0x01310132; +- cpu->isar.id_isar5 = 0x00000000; +- cpu->isar.id_isar6 = 0x00000000; ++ cpu->isar.regs[ID_MMFR0] = 0x00100030; ++ cpu->isar.regs[ID_MMFR1] = 0x00000000; ++ cpu->isar.regs[ID_MMFR2] = 0x01000000; ++ cpu->isar.regs[ID_MMFR3] = 0x00000000; ++ cpu->isar.regs[ID_ISAR0] = 0x01101110; ++ cpu->isar.regs[ID_ISAR1] = 0x02112000; ++ cpu->isar.regs[ID_ISAR2] = 0x20232231; ++ cpu->isar.regs[ID_ISAR3] = 0x01111131; ++ cpu->isar.regs[ID_ISAR4] = 0x01310132; ++ cpu->isar.regs[ID_ISAR5] = 0x00000000; ++ cpu->isar.regs[ID_ISAR6] = 0x00000000; + } + + static void cortex_m33_initfn(Object *obj) +@@ -618,24 +622,24 @@ static void cortex_m33_initfn(Object *obj) + cpu->midr = 0x410fd213; /* r0p3 */ + cpu->pmsav7_dregion = 16; + cpu->sau_sregion = 8; +- cpu->isar.mvfr0 = 0x10110021; +- cpu->isar.mvfr1 = 0x11000011; +- cpu->isar.mvfr2 = 0x00000040; +- cpu->isar.id_pfr0 = 0x00000030; +- cpu->isar.id_pfr1 = 0x00000210; +- cpu->isar.id_dfr0 = 0x00200000; ++ cpu->isar.regs[MVFR0] = 0x10110021; ++ cpu->isar.regs[MVFR1] = 0x11000011; ++ cpu->isar.regs[MVFR2] = 0x00000040; ++ cpu->isar.regs[ID_PFR0] = 0x00000030; ++ cpu->isar.regs[ID_PFR1] = 0x00000210; ++ cpu->isar.regs[ID_DFR0] = 0x00200000; + cpu->id_afr0 = 0x00000000; +- cpu->isar.id_mmfr0 = 0x00101F40; +- cpu->isar.id_mmfr1 = 0x00000000; +- cpu->isar.id_mmfr2 = 0x01000000; +- cpu->isar.id_mmfr3 = 0x00000000; +- cpu->isar.id_isar0 = 0x01101110; +- cpu->isar.id_isar1 = 0x02212000; +- cpu->isar.id_isar2 = 0x20232232; +- cpu->isar.id_isar3 = 0x01111131; +- cpu->isar.id_isar4 = 0x01310132; +- cpu->isar.id_isar5 = 0x00000000; +- cpu->isar.id_isar6 = 0x00000000; ++ cpu->isar.regs[ID_MMFR0] = 0x00101F40; ++ cpu->isar.regs[ID_MMFR1] = 0x00000000; ++ cpu->isar.regs[ID_MMFR2] = 0x01000000; ++ cpu->isar.regs[ID_MMFR3] = 0x00000000; ++ cpu->isar.regs[ID_ISAR0] = 0x01101110; ++ cpu->isar.regs[ID_ISAR1] = 0x02212000; ++ cpu->isar.regs[ID_ISAR2] = 0x20232232; ++ cpu->isar.regs[ID_ISAR3] = 0x01111131; ++ cpu->isar.regs[ID_ISAR4] = 0x01310132; ++ cpu->isar.regs[ID_ISAR5] = 0x00000000; ++ cpu->isar.regs[ID_ISAR6] = 0x00000000; + cpu->clidr = 0x00000000; + cpu->ctr = 0x8000c000; + } +@@ -655,24 +659,24 @@ static void cortex_m55_initfn(Object *obj) + cpu->pmsav7_dregion = 16; + cpu->sau_sregion = 8; + /* These are the MVFR* values for the FPU + full MVE configuration */ +- cpu->isar.mvfr0 = 0x10110221; +- cpu->isar.mvfr1 = 0x12100211; +- cpu->isar.mvfr2 = 0x00000040; +- cpu->isar.id_pfr0 = 0x20000030; +- cpu->isar.id_pfr1 = 0x00000230; +- cpu->isar.id_dfr0 = 0x10200000; ++ cpu->isar.regs[MVFR0] = 0x10110221; ++ cpu->isar.regs[MVFR1] = 0x12100211; ++ cpu->isar.regs[MVFR2] = 0x00000040; ++ cpu->isar.regs[ID_PFR0] = 0x20000030; ++ cpu->isar.regs[ID_PFR1] = 0x00000230; ++ cpu->isar.regs[ID_DFR0] = 0x10200000; + cpu->id_afr0 = 0x00000000; +- cpu->isar.id_mmfr0 = 0x00111040; +- cpu->isar.id_mmfr1 = 0x00000000; +- cpu->isar.id_mmfr2 = 0x01000000; +- cpu->isar.id_mmfr3 = 0x00000011; +- cpu->isar.id_isar0 = 0x01103110; +- cpu->isar.id_isar1 = 0x02212000; +- cpu->isar.id_isar2 = 0x20232232; +- cpu->isar.id_isar3 = 0x01111131; +- cpu->isar.id_isar4 = 0x01310132; +- cpu->isar.id_isar5 = 0x00000000; +- cpu->isar.id_isar6 = 0x00000000; ++ cpu->isar.regs[ID_MMFR0] = 0x00111040; ++ cpu->isar.regs[ID_MMFR1] = 0x00000000; ++ cpu->isar.regs[ID_MMFR2] = 0x01000000; ++ cpu->isar.regs[ID_MMFR3] = 0x00000011; ++ cpu->isar.regs[ID_ISAR0] = 0x01103110; ++ cpu->isar.regs[ID_ISAR1] = 0x02212000; ++ cpu->isar.regs[ID_ISAR2] = 0x20232232; ++ cpu->isar.regs[ID_ISAR3] = 0x01111131; ++ cpu->isar.regs[ID_ISAR4] = 0x01310132; ++ cpu->isar.regs[ID_ISAR5] = 0x00000000; ++ cpu->isar.regs[ID_ISAR6] = 0x00000000; + cpu->clidr = 0x00000000; /* caches not implemented */ + cpu->ctr = 0x8303c003; + } +@@ -697,21 +701,21 @@ static void cortex_r5_initfn(Object *obj) + set_feature(&cpu->env, ARM_FEATURE_PMSA); + set_feature(&cpu->env, ARM_FEATURE_PMU); + cpu->midr = 0x411fc153; /* r1p3 */ +- cpu->isar.id_pfr0 = 0x0131; +- cpu->isar.id_pfr1 = 0x001; +- cpu->isar.id_dfr0 = 0x010400; ++ cpu->isar.regs[ID_PFR0] = 0x0131; ++ cpu->isar.regs[ID_PFR1] = 0x001; ++ cpu->isar.regs[ID_DFR0] = 0x010400; + cpu->id_afr0 = 0x0; +- cpu->isar.id_mmfr0 = 0x0210030; +- cpu->isar.id_mmfr1 = 0x00000000; +- cpu->isar.id_mmfr2 = 0x01200000; +- cpu->isar.id_mmfr3 = 0x0211; +- cpu->isar.id_isar0 = 0x02101111; +- cpu->isar.id_isar1 = 0x13112111; +- cpu->isar.id_isar2 = 0x21232141; +- cpu->isar.id_isar3 = 0x01112131; +- cpu->isar.id_isar4 = 0x0010142; +- cpu->isar.id_isar5 = 0x0; +- cpu->isar.id_isar6 = 0x0; ++ cpu->isar.regs[ID_MMFR0] = 0x0210030; ++ cpu->isar.regs[ID_MMFR1] = 0x00000000; ++ cpu->isar.regs[ID_MMFR2] = 0x01200000; ++ cpu->isar.regs[ID_MMFR3] = 0x0211; ++ cpu->isar.regs[ID_ISAR0] = 0x02101111; ++ cpu->isar.regs[ID_ISAR1] = 0x13112111; ++ cpu->isar.regs[ID_ISAR2] = 0x21232141; ++ cpu->isar.regs[ID_ISAR3] = 0x01112131; ++ cpu->isar.regs[ID_ISAR4] = 0x0010142; ++ cpu->isar.regs[ID_ISAR5] = 0x0; ++ cpu->isar.regs[ID_ISAR6] = 0x0; + cpu->mp_is_up = true; + cpu->pmsav7_dregion = 16; + define_arm_cp_regs(cpu, cortexr5_cp_reginfo); +@@ -722,8 +726,8 @@ static void cortex_r5f_initfn(Object *obj) + ARMCPU *cpu = ARM_CPU(obj); + + cortex_r5_initfn(obj); +- cpu->isar.mvfr0 = 0x10110221; +- cpu->isar.mvfr1 = 0x00000011; ++ cpu->isar.regs[MVFR0] = 0x10110221; ++ cpu->isar.regs[MVFR1] = 0x00000011; + } + + static void ti925t_initfn(Object *obj) +@@ -942,7 +946,8 @@ static void arm_max_initfn(Object *obj) + cortex_a15_initfn(obj); + + /* old-style VFP short-vector support */ +- cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSHVEC, 1); ++ cpu->isar.regs[MVFR0] = FIELD_DP32(cpu->isar.regs[MVFR0], MVFR0, FPSHVEC, ++ 1); + + #ifdef CONFIG_USER_ONLY + /* +@@ -954,16 +959,16 @@ static void arm_max_initfn(Object *obj) + { + uint32_t t; + +- t = cpu->isar.id_isar5; ++ t = cpu->isar.regs[ID_ISAR5]; + t = FIELD_DP32(t, ID_ISAR5, AES, 2); + t = FIELD_DP32(t, ID_ISAR5, SHA1, 1); + t = FIELD_DP32(t, ID_ISAR5, SHA2, 1); + t = FIELD_DP32(t, ID_ISAR5, CRC32, 1); + t = FIELD_DP32(t, ID_ISAR5, RDM, 1); + t = FIELD_DP32(t, ID_ISAR5, VCMA, 1); +- cpu->isar.id_isar5 = t; ++ cpu->isar.regs[ID_ISAR5] = t; + +- t = cpu->isar.id_isar6; ++ t = cpu->isar.regs[ID_ISAR6]; + t = FIELD_DP32(t, ID_ISAR6, JSCVT, 1); + t = FIELD_DP32(t, ID_ISAR6, DP, 1); + t = FIELD_DP32(t, ID_ISAR6, FHM, 1); +@@ -971,36 +976,36 @@ static void arm_max_initfn(Object *obj) + t = FIELD_DP32(t, ID_ISAR6, SPECRES, 1); + t = FIELD_DP32(t, ID_ISAR6, BF16, 1); + t = FIELD_DP32(t, ID_ISAR6, I8MM, 1); +- cpu->isar.id_isar6 = t; ++ cpu->isar.regs[ID_ISAR6] = t; + +- t = cpu->isar.mvfr1; ++ t = cpu->isar.regs[MVFR1]; + t = FIELD_DP32(t, MVFR1, FPHP, 3); /* v8.2-FP16 */ + t = FIELD_DP32(t, MVFR1, SIMDHP, 2); /* v8.2-FP16 */ +- cpu->isar.mvfr1 = t; ++ cpu->isar.regs[MVFR1] = t; + +- t = cpu->isar.mvfr2; ++ t = cpu->isar.regs[MVFR2]; + t = FIELD_DP32(t, MVFR2, SIMDMISC, 3); /* SIMD MaxNum */ + t = FIELD_DP32(t, MVFR2, FPMISC, 4); /* FP MaxNum */ +- cpu->isar.mvfr2 = t; ++ cpu->isar.regs[MVFR2] = t; + +- t = cpu->isar.id_mmfr3; ++ t = cpu->isar.regs[ID_MMFR3]; + t = FIELD_DP32(t, ID_MMFR3, PAN, 2); /* ATS1E1 */ +- cpu->isar.id_mmfr3 = t; ++ cpu->isar.regs[ID_MMFR3] = t; + +- t = cpu->isar.id_mmfr4; ++ t = cpu->isar.regs[ID_MMFR4]; + t = FIELD_DP32(t, ID_MMFR4, HPDS, 1); /* AA32HPD */ + t = FIELD_DP32(t, ID_MMFR4, AC2, 1); /* ACTLR2, HACTLR2 */ + t = FIELD_DP32(t, ID_MMFR4, CNP, 1); /* TTCNP */ + t = FIELD_DP32(t, ID_MMFR4, XNX, 1); /* TTS2UXN */ +- cpu->isar.id_mmfr4 = t; ++ cpu->isar.regs[ID_MMFR4] = t; + +- t = cpu->isar.id_pfr0; ++ t = cpu->isar.regs[ID_PFR0]; + t = FIELD_DP32(t, ID_PFR0, DIT, 1); +- cpu->isar.id_pfr0 = t; ++ cpu->isar.regs[ID_PFR0] = t; + +- t = cpu->isar.id_pfr2; ++ t = cpu->isar.regs[ID_PFR2]; + t = FIELD_DP32(t, ID_PFR2, SSBS, 1); +- cpu->isar.id_pfr2 = t; ++ cpu->isar.regs[ID_PFR2] = t; + } + #endif /* CONFIG_USER_ONLY */ + } +diff --git a/target/arm/helper.c b/target/arm/helper.c +index 9b317899a6..b8ea1dc1f6 100644 +--- a/target/arm/helper.c ++++ b/target/arm/helper.c +@@ -6547,12 +6547,12 @@ static void define_debug_regs(ARMCPU *cpu) + * use AArch32. Given that bit 15 is RES1, if the value is 0 then + * the register must not exist for this cpu. + */ +- if (cpu->isar.dbgdidr != 0) { ++ if (cpu->isar.regs[DBGDIDR] != 0) { + ARMCPRegInfo dbgdidr = { + .name = "DBGDIDR", .cp = 14, .crn = 0, .crm = 0, + .opc1 = 0, .opc2 = 0, + .access = PL0_R, .accessfn = access_tda, +- .type = ARM_CP_CONST, .resetvalue = cpu->isar.dbgdidr, ++ .type = ARM_CP_CONST, .resetvalue = cpu->isar.regs[DBGDIDR], + }; + define_one_arm_cp_reg(cpu, &dbgdidr); + } +@@ -6707,7 +6707,7 @@ static void define_pmu_regs(ARMCPU *cpu) + static uint64_t id_pfr1_read(CPUARMState *env, const ARMCPRegInfo *ri) + { + ARMCPU *cpu = env_archcpu(env); +- uint64_t pfr1 = cpu->isar.id_pfr1; ++ uint64_t pfr1 = cpu->isar.regs[ID_PFR1]; + + if (env->gicv3state) { + pfr1 |= 1 << 28; +@@ -6719,7 +6719,7 @@ static uint64_t id_pfr1_read(CPUARMState *env, const ARMCPRegInfo *ri) + static uint64_t id_aa64pfr0_read(CPUARMState *env, const ARMCPRegInfo *ri) + { + ARMCPU *cpu = env_archcpu(env); +- uint64_t pfr0 = cpu->isar.id_aa64pfr0; ++ uint64_t pfr0 = cpu->isar.regs[ID_AA64PFR0]; + + if (env->gicv3state) { + pfr0 |= 1 << 24; +@@ -7501,7 +7501,7 @@ void register_cp_regs_for_features(ARMCPU *cpu) + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 0, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa32_tid3, +- .resetvalue = cpu->isar.id_pfr0 }, ++ .resetvalue = cpu->isar.regs[ID_PFR0] }, + /* ID_PFR1 is not a plain ARM_CP_CONST because we don't know + * the value of the GIC field until after we define these regs. + */ +@@ -7515,7 +7515,7 @@ void register_cp_regs_for_features(ARMCPU *cpu) + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 2, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa32_tid3, +- .resetvalue = cpu->isar.id_dfr0 }, ++ .resetvalue = cpu->isar.regs[ID_DFR0] }, + { .name = "ID_AFR0", .state = ARM_CP_STATE_BOTH, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 3, + .access = PL1_R, .type = ARM_CP_CONST, +@@ -7525,62 +7525,62 @@ void register_cp_regs_for_features(ARMCPU *cpu) + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 4, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa32_tid3, +- .resetvalue = cpu->isar.id_mmfr0 }, ++ .resetvalue = cpu->isar.regs[ID_MMFR0] }, + { .name = "ID_MMFR1", .state = ARM_CP_STATE_BOTH, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 5, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa32_tid3, +- .resetvalue = cpu->isar.id_mmfr1 }, ++ .resetvalue = cpu->isar.regs[ID_MMFR1] }, + { .name = "ID_MMFR2", .state = ARM_CP_STATE_BOTH, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 6, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa32_tid3, +- .resetvalue = cpu->isar.id_mmfr2 }, ++ .resetvalue = cpu->isar.regs[ID_MMFR2] }, + { .name = "ID_MMFR3", .state = ARM_CP_STATE_BOTH, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 7, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa32_tid3, +- .resetvalue = cpu->isar.id_mmfr3 }, ++ .resetvalue = cpu->isar.regs[ID_MMFR3] }, + { .name = "ID_ISAR0", .state = ARM_CP_STATE_BOTH, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 0, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa32_tid3, +- .resetvalue = cpu->isar.id_isar0 }, ++ .resetvalue = cpu->isar.regs[ID_ISAR0] }, + { .name = "ID_ISAR1", .state = ARM_CP_STATE_BOTH, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 1, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa32_tid3, +- .resetvalue = cpu->isar.id_isar1 }, ++ .resetvalue = cpu->isar.regs[ID_ISAR1] }, + { .name = "ID_ISAR2", .state = ARM_CP_STATE_BOTH, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 2, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa32_tid3, +- .resetvalue = cpu->isar.id_isar2 }, ++ .resetvalue = cpu->isar.regs[ID_ISAR2] }, + { .name = "ID_ISAR3", .state = ARM_CP_STATE_BOTH, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 3, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa32_tid3, +- .resetvalue = cpu->isar.id_isar3 }, ++ .resetvalue = cpu->isar.regs[ID_ISAR3] }, + { .name = "ID_ISAR4", .state = ARM_CP_STATE_BOTH, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 4, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa32_tid3, +- .resetvalue = cpu->isar.id_isar4 }, ++ .resetvalue = cpu->isar.regs[ID_ISAR4] }, + { .name = "ID_ISAR5", .state = ARM_CP_STATE_BOTH, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 5, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa32_tid3, +- .resetvalue = cpu->isar.id_isar5 }, ++ .resetvalue = cpu->isar.regs[ID_ISAR5] }, + { .name = "ID_MMFR4", .state = ARM_CP_STATE_BOTH, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 6, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa32_tid3, +- .resetvalue = cpu->isar.id_mmfr4 }, ++ .resetvalue = cpu->isar.regs[ID_MMFR4] }, + { .name = "ID_ISAR6", .state = ARM_CP_STATE_BOTH, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 7, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa32_tid3, +- .resetvalue = cpu->isar.id_isar6 }, ++ .resetvalue = cpu->isar.regs[ID_ISAR6] }, + REGINFO_SENTINEL + }; + define_arm_cp_regs(cpu, v6_idregs); +@@ -7630,7 +7630,7 @@ void register_cp_regs_for_features(ARMCPU *cpu) + .access = PL1_R, + #ifdef CONFIG_USER_ONLY + .type = ARM_CP_CONST, +- .resetvalue = cpu->isar.id_aa64pfr0 ++ .resetvalue = cpu->isar.regs[ID_AA64PFR0] + #else + .type = ARM_CP_NO_RAW, + .accessfn = access_aa64_tid3, +@@ -7642,7 +7642,7 @@ void register_cp_regs_for_features(ARMCPU *cpu) + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 1, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa64_tid3, +- .resetvalue = cpu->isar.id_aa64pfr1}, ++ .resetvalue = cpu->isar.regs[ID_AA64PFR1]}, + { .name = "ID_AA64PFR2_EL1_RESERVED", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 2, + .access = PL1_R, .type = ARM_CP_CONST, +@@ -7657,7 +7657,7 @@ void register_cp_regs_for_features(ARMCPU *cpu) + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 4, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa64_tid3, +- .resetvalue = cpu->isar.id_aa64zfr0 }, ++ .resetvalue = cpu->isar.regs[ID_AA64ZFR0] }, + { .name = "ID_AA64PFR5_EL1_RESERVED", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 5, + .access = PL1_R, .type = ARM_CP_CONST, +@@ -7677,12 +7677,12 @@ void register_cp_regs_for_features(ARMCPU *cpu) + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 5, .opc2 = 0, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa64_tid3, +- .resetvalue = cpu->isar.id_aa64dfr0 }, ++ .resetvalue = cpu->isar.regs[ID_AA64DFR0] }, + { .name = "ID_AA64DFR1_EL1", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 5, .opc2 = 1, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa64_tid3, +- .resetvalue = cpu->isar.id_aa64dfr1 }, ++ .resetvalue = cpu->isar.regs[ID_AA64DFR1] }, + { .name = "ID_AA64DFR2_EL1_RESERVED", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 5, .opc2 = 2, + .access = PL1_R, .type = ARM_CP_CONST, +@@ -7717,12 +7717,12 @@ void register_cp_regs_for_features(ARMCPU *cpu) + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 6, .opc2 = 0, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa64_tid3, +- .resetvalue = cpu->isar.id_aa64isar0 }, ++ .resetvalue = cpu->isar.regs[ID_AA64ISAR0] }, + { .name = "ID_AA64ISAR1_EL1", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 6, .opc2 = 1, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa64_tid3, +- .resetvalue = cpu->isar.id_aa64isar1 }, ++ .resetvalue = cpu->isar.regs[ID_AA64ISAR1] }, + { .name = "ID_AA64ISAR2_EL1_RESERVED", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 6, .opc2 = 2, + .access = PL1_R, .type = ARM_CP_CONST, +@@ -7757,17 +7757,17 @@ void register_cp_regs_for_features(ARMCPU *cpu) + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 0, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa64_tid3, +- .resetvalue = cpu->isar.id_aa64mmfr0 }, ++ .resetvalue = cpu->isar.regs[ID_AA64MMFR0] }, + { .name = "ID_AA64MMFR1_EL1", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 1, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa64_tid3, +- .resetvalue = cpu->isar.id_aa64mmfr1 }, ++ .resetvalue = cpu->isar.regs[ID_AA64MMFR1] }, + { .name = "ID_AA64MMFR2_EL1", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 2, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa64_tid3, +- .resetvalue = cpu->isar.id_aa64mmfr2 }, ++ .resetvalue = cpu->isar.regs[ID_AA64MMFR2] }, + { .name = "ID_AA64MMFR3_EL1_RESERVED", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 3, + .access = PL1_R, .type = ARM_CP_CONST, +@@ -7797,17 +7797,17 @@ void register_cp_regs_for_features(ARMCPU *cpu) + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 0, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa64_tid3, +- .resetvalue = cpu->isar.mvfr0 }, ++ .resetvalue = cpu->isar.regs[MVFR0] }, + { .name = "MVFR1_EL1", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 1, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa64_tid3, +- .resetvalue = cpu->isar.mvfr1 }, ++ .resetvalue = cpu->isar.regs[MVFR1] }, + { .name = "MVFR2_EL1", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 2, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa64_tid3, +- .resetvalue = cpu->isar.mvfr2 }, ++ .resetvalue = cpu->isar.regs[MVFR2] }, + { .name = "MVFR3_EL1_RESERVED", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 3, + .access = PL1_R, .type = ARM_CP_CONST, +@@ -7817,7 +7817,7 @@ void register_cp_regs_for_features(ARMCPU *cpu) + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 4, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa64_tid3, +- .resetvalue = cpu->isar.id_pfr2 }, ++ .resetvalue = cpu->isar.regs[ID_PFR2] }, + { .name = "MVFR5_EL1_RESERVED", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 5, + .access = PL1_R, .type = ARM_CP_CONST, +diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c +index 0dc96560d3..66ad698df1 100644 +--- a/target/arm/hvf/hvf.c ++++ b/target/arm/hvf/hvf.c +@@ -449,15 +449,15 @@ static bool hvf_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) + int reg; + uint64_t *val; + } regs[] = { +- { HV_SYS_REG_ID_AA64PFR0_EL1, &host_isar.id_aa64pfr0 }, +- { HV_SYS_REG_ID_AA64PFR1_EL1, &host_isar.id_aa64pfr1 }, +- { HV_SYS_REG_ID_AA64DFR0_EL1, &host_isar.id_aa64dfr0 }, +- { HV_SYS_REG_ID_AA64DFR1_EL1, &host_isar.id_aa64dfr1 }, +- { HV_SYS_REG_ID_AA64ISAR0_EL1, &host_isar.id_aa64isar0 }, +- { HV_SYS_REG_ID_AA64ISAR1_EL1, &host_isar.id_aa64isar1 }, +- { HV_SYS_REG_ID_AA64MMFR0_EL1, &host_isar.id_aa64mmfr0 }, +- { HV_SYS_REG_ID_AA64MMFR1_EL1, &host_isar.id_aa64mmfr1 }, +- { HV_SYS_REG_ID_AA64MMFR2_EL1, &host_isar.id_aa64mmfr2 }, ++ { HV_SYS_REG_ID_AA64PFR0_EL1, &host_isar.regs[ID_AA64PFR0] }, ++ { HV_SYS_REG_ID_AA64PFR1_EL1, &host_isar.regs[ID_AA64PFR1] }, ++ { HV_SYS_REG_ID_AA64DFR0_EL1, &host_isar.regs[ID_AA64DFR0] }, ++ { HV_SYS_REG_ID_AA64DFR1_EL1, &host_isar.regs[ID_AA64DFR1] }, ++ { HV_SYS_REG_ID_AA64ISAR0_EL1, &host_isar.regs[ID_AA64ISAR0] }, ++ { HV_SYS_REG_ID_AA64ISAR1_EL1, &host_isar.regs[ID_AA64ISAR1] }, ++ { HV_SYS_REG_ID_AA64MMFR0_EL1, &host_isar.regs[ID_AA64MMFR0] }, ++ { HV_SYS_REG_ID_AA64MMFR1_EL1, &host_isar.regs[ID_AA64MMFR1] }, ++ { HV_SYS_REG_ID_AA64MMFR2_EL1, &host_isar.regs[ID_AA64MMFR2] }, + }; + hv_vcpu_t fd; + hv_return_t r = HV_SUCCESS; +@@ -593,7 +593,7 @@ int hvf_arch_init_vcpu(CPUState *cpu) + + /* We're limited to underlying hardware caps, override internal versions */ + ret = hv_vcpu_get_sys_reg(cpu->hvf->fd, HV_SYS_REG_ID_AA64MMFR0_EL1, +- &arm_cpu->isar.id_aa64mmfr0); ++ &arm_cpu->isar.regs[ID_AA64MMFR0]); + assert_hvf_ok(ret); + + return 0; +diff --git a/target/arm/internals.h b/target/arm/internals.h +index 89f7610ebc..0ea225e480 100644 +--- a/target/arm/internals.h ++++ b/target/arm/internals.h +@@ -254,7 +254,7 @@ static inline unsigned int arm_pamax(ARMCPU *cpu) + [5] = 48, + }; + unsigned int parange = +- FIELD_EX64(cpu->isar.id_aa64mmfr0, ID_AA64MMFR0, PARANGE); ++ FIELD_EX64(cpu->isar.regs[ID_AA64MMFR0], ID_AA64MMFR0, PARANGE); + + /* id_aa64mmfr0 is a read-only register so values outside of the + * supported mappings can be considered an implementation error. */ +@@ -808,9 +808,9 @@ static inline uint32_t arm_debug_exception_fsr(CPUARMState *env) + static inline int arm_num_brps(ARMCPU *cpu) + { + if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) { +- return FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, BRPS) + 1; ++ return FIELD_EX64(cpu->isar.regs[ID_AA64DFR0], ID_AA64DFR0, BRPS) + 1; + } else { +- return FIELD_EX32(cpu->isar.dbgdidr, DBGDIDR, BRPS) + 1; ++ return FIELD_EX32(cpu->isar.regs[DBGDIDR], DBGDIDR, BRPS) + 1; + } + } + +@@ -822,9 +822,9 @@ static inline int arm_num_brps(ARMCPU *cpu) + static inline int arm_num_wrps(ARMCPU *cpu) + { + if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) { +- return FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, WRPS) + 1; ++ return FIELD_EX64(cpu->isar.regs[ID_AA64DFR0], ID_AA64DFR0, WRPS) + 1; + } else { +- return FIELD_EX32(cpu->isar.dbgdidr, DBGDIDR, WRPS) + 1; ++ return FIELD_EX32(cpu->isar.regs[DBGDIDR], DBGDIDR, WRPS) + 1; + } + } + +@@ -836,9 +836,9 @@ static inline int arm_num_wrps(ARMCPU *cpu) + static inline int arm_num_ctx_cmps(ARMCPU *cpu) + { + if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) { +- return FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, CTX_CMPS) + 1; ++ return FIELD_EX64(cpu->isar.regs[ID_AA64DFR0], ID_AA64DFR0, CTX_CMPS) + 1; + } else { +- return FIELD_EX32(cpu->isar.dbgdidr, DBGDIDR, CTX_CMPS) + 1; ++ return FIELD_EX32(cpu->isar.regs[DBGDIDR], DBGDIDR, CTX_CMPS) + 1; + } + } + +diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c +index e790d6c9a5..4f97e516c2 100644 +--- a/target/arm/kvm64.c ++++ b/target/arm/kvm64.c +@@ -468,7 +468,7 @@ void kvm_arm_pvtime_init(CPUState *cs, uint64_t ipa) + } + } + +-static int read_sys_reg32(int fd, uint32_t *pret, uint64_t id) ++static int read_sys_reg32(int fd, uint64_t *pret, uint64_t id) + { + uint64_t ret; + struct kvm_one_reg idreg = { .id = id, .addr = (uintptr_t)&ret }; +@@ -528,7 +528,7 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) + ahcf->target = init.target; + ahcf->dtb_compatible = "arm,arm-v8"; + +- err = read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64pfr0, ++ err = read_sys_reg64(fdarray[2], &ahcf->isar.regs[ID_AA64PFR0], + ARM64_SYS_REG(3, 0, 0, 4, 0)); + if (unlikely(err < 0)) { + /* +@@ -547,24 +547,24 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) + * ??? Either of these sounds like too much effort just + * to work around running a modern host kernel. + */ +- ahcf->isar.id_aa64pfr0 = 0x00000011; /* EL1&0, AArch64 only */ ++ ahcf->isar.regs[ID_AA64PFR0] = 0x00000011; /* EL1&0, AArch64 only */ + err = 0; + } else { +- err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64pfr1, ++ err |= read_sys_reg64(fdarray[2], &ahcf->isar.regs[ID_AA64PFR1], + ARM64_SYS_REG(3, 0, 0, 4, 1)); +- err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64dfr0, ++ err |= read_sys_reg64(fdarray[2], &ahcf->isar.regs[ID_AA64DFR0], + ARM64_SYS_REG(3, 0, 0, 5, 0)); +- err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64dfr1, ++ err |= read_sys_reg64(fdarray[2], &ahcf->isar.regs[ID_AA64DFR1], + ARM64_SYS_REG(3, 0, 0, 5, 1)); +- err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64isar0, ++ err |= read_sys_reg64(fdarray[2], &ahcf->isar.regs[ID_AA64ISAR0], + ARM64_SYS_REG(3, 0, 0, 6, 0)); +- err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64isar1, ++ err |= read_sys_reg64(fdarray[2], &ahcf->isar.regs[ID_AA64ISAR1], + ARM64_SYS_REG(3, 0, 0, 6, 1)); +- err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64mmfr0, ++ err |= read_sys_reg64(fdarray[2], &ahcf->isar.regs[ID_AA64MMFR0], + ARM64_SYS_REG(3, 0, 0, 7, 0)); +- err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64mmfr1, ++ err |= read_sys_reg64(fdarray[2], &ahcf->isar.regs[ID_AA64MMFR1], + ARM64_SYS_REG(3, 0, 0, 7, 1)); +- err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64mmfr2, ++ err |= read_sys_reg64(fdarray[2], &ahcf->isar.regs[ID_AA64MMFR2], + ARM64_SYS_REG(3, 0, 0, 7, 2)); + + /* +@@ -574,44 +574,44 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) + * than skipping the reads and leaving 0, as we must avoid + * considering the values in every case. + */ +- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_pfr0, ++ err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_PFR0], + ARM64_SYS_REG(3, 0, 0, 1, 0)); +- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_pfr1, ++ err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_PFR1], + ARM64_SYS_REG(3, 0, 0, 1, 1)); +- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_pfr2, ++ err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_PFR2], + ARM64_SYS_REG(3, 0, 0, 3, 4)); +- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_dfr0, ++ err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_DFR0], + ARM64_SYS_REG(3, 0, 0, 1, 2)); +- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr0, ++ err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_MMFR0], + ARM64_SYS_REG(3, 0, 0, 1, 4)); +- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr1, ++ err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_MMFR1], + ARM64_SYS_REG(3, 0, 0, 1, 5)); +- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr2, ++ err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_MMFR2], + ARM64_SYS_REG(3, 0, 0, 1, 6)); +- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr3, ++ err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_MMFR3], + ARM64_SYS_REG(3, 0, 0, 1, 7)); +- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar0, ++ err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_ISAR0], + ARM64_SYS_REG(3, 0, 0, 2, 0)); +- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar1, ++ err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_ISAR1], + ARM64_SYS_REG(3, 0, 0, 2, 1)); +- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar2, ++ err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_ISAR2], + ARM64_SYS_REG(3, 0, 0, 2, 2)); +- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar3, ++ err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_ISAR3], + ARM64_SYS_REG(3, 0, 0, 2, 3)); +- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar4, ++ err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_ISAR4], + ARM64_SYS_REG(3, 0, 0, 2, 4)); +- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar5, ++ err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_ISAR5], + ARM64_SYS_REG(3, 0, 0, 2, 5)); +- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr4, ++ err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_MMFR4], + ARM64_SYS_REG(3, 0, 0, 2, 6)); +- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar6, ++ err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_ISAR6], + ARM64_SYS_REG(3, 0, 0, 2, 7)); + +- err |= read_sys_reg32(fdarray[2], &ahcf->isar.mvfr0, ++ err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[MVFR0], + ARM64_SYS_REG(3, 0, 0, 3, 0)); +- err |= read_sys_reg32(fdarray[2], &ahcf->isar.mvfr1, ++ err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[MVFR1], + ARM64_SYS_REG(3, 0, 0, 3, 1)); +- err |= read_sys_reg32(fdarray[2], &ahcf->isar.mvfr2, ++ err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[MVFR2], + ARM64_SYS_REG(3, 0, 0, 3, 2)); + + /* +@@ -624,14 +624,17 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) + * arch/arm64/kvm/sys_regs.c:trap_dbgidr() does. + * We only do this if the CPU supports AArch32 at EL1. + */ +- if (FIELD_EX32(ahcf->isar.id_aa64pfr0, ID_AA64PFR0, EL1) >= 2) { +- int wrps = FIELD_EX64(ahcf->isar.id_aa64dfr0, ID_AA64DFR0, WRPS); +- int brps = FIELD_EX64(ahcf->isar.id_aa64dfr0, ID_AA64DFR0, BRPS); ++ if (FIELD_EX32(ahcf->isar.regs[ID_AA64PFR0], ID_AA64PFR0, EL1) >= 2) { ++ int wrps = FIELD_EX64(ahcf->isar.regs[ID_AA64DFR0], ID_AA64DFR0, ++ WRPS); ++ int brps = FIELD_EX64(ahcf->isar.regs[ID_AA64DFR0], ID_AA64DFR0, ++ BRPS); + int ctx_cmps = +- FIELD_EX64(ahcf->isar.id_aa64dfr0, ID_AA64DFR0, CTX_CMPS); ++ FIELD_EX64(ahcf->isar.regs[ID_AA64DFR0], ID_AA64DFR0, ++ CTX_CMPS); + int version = 6; /* ARMv8 debug architecture */ + bool has_el3 = +- !!FIELD_EX32(ahcf->isar.id_aa64pfr0, ID_AA64PFR0, EL3); ++ !!FIELD_EX32(ahcf->isar.regs[ID_AA64PFR0], ID_AA64PFR0, EL3); + uint32_t dbgdidr = 0; + + dbgdidr = FIELD_DP32(dbgdidr, DBGDIDR, WRPS, wrps); +@@ -641,7 +644,7 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) + dbgdidr = FIELD_DP32(dbgdidr, DBGDIDR, NSUHD_IMP, has_el3); + dbgdidr = FIELD_DP32(dbgdidr, DBGDIDR, SE_IMP, has_el3); + dbgdidr |= (1 << 15); /* RES1 bit */ +- ahcf->isar.dbgdidr = dbgdidr; ++ ahcf->isar.regs[DBGDIDR] = dbgdidr; + } + } + +@@ -649,9 +652,9 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) + + /* Add feature bits that can't appear until after VCPU init. */ + if (sve_supported) { +- t = ahcf->isar.id_aa64pfr0; ++ t = ahcf->isar.regs[ID_AA64PFR0]; + t = FIELD_DP64(t, ID_AA64PFR0, SVE, 1); +- ahcf->isar.id_aa64pfr0 = t; ++ ahcf->isar.regs[ID_AA64PFR0] = t; + + /* + * Before v5.1, KVM did not support SVE and did not expose +@@ -659,7 +662,7 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) + * not expose the register to "user" requests like this + * unless the host supports SVE. + */ +- err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64zfr0, ++ err |= read_sys_reg64(fdarray[2], &ahcf->isar.regs[ID_AA64ZFR0], + ARM64_SYS_REG(3, 0, 0, 4, 4)); + } + +-- +2.27.0 + -- Gitee From 93ece540f3788b194df31a6c0f0a8465ba77b0cf Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Thu, 6 Aug 2020 16:14:35 +0800 Subject: [PATCH 41/54] target/arm: parse cpu feature related options The implementation of CPUClass::parse_features only supports CPU features in "feature=value" format. However, libvirt maybe send us a CPU feature string in "+feature/-feature" format. Hence, we need to override CPUClass::parse_features to support CPU feature string in both "feature=value" and "+feature/-feature" format. The logic of AArch64CPUClass::parse_features is similar to that of X86CPUClass::parse_features. Signed-off-by: zhanghailiang Signed-off-by: Peng Liang Signed-off-by: Dongxu Sun --- ...rm-parse-cpu-feature-related-options.patch | 125 ++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 target-arm-parse-cpu-feature-related-options.patch diff --git a/target-arm-parse-cpu-feature-related-options.patch b/target-arm-parse-cpu-feature-related-options.patch new file mode 100644 index 0000000..b90027b --- /dev/null +++ b/target-arm-parse-cpu-feature-related-options.patch @@ -0,0 +1,125 @@ +From abd51f8d46b916efb37cb2c8face176bc83c0d5d Mon Sep 17 00:00:00 2001 +From: Peng Liang +Date: Thu, 6 Aug 2020 16:14:35 +0800 +Subject: [PATCH] target/arm: parse cpu feature related options + +The implementation of CPUClass::parse_features only supports CPU +features in "feature=value" format. However, libvirt maybe send us a +CPU feature string in "+feature/-feature" format. Hence, we need to +override CPUClass::parse_features to support CPU feature string in both +"feature=value" and "+feature/-feature" format. + +The logic of AArch64CPUClass::parse_features is similar to that of +X86CPUClass::parse_features. + +Signed-off-by: zhanghailiang +Signed-off-by: Peng Liang +Signed-off-by: Dongxu Sun +--- + target/arm/cpu64.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 83 insertions(+) + +diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c +index 96a49a3158..9e5179afbe 100644 +--- a/target/arm/cpu64.c ++++ b/target/arm/cpu64.c +@@ -982,6 +982,88 @@ static gchar *aarch64_gdb_arch_name(CPUState *cs) + return g_strdup("aarch64"); + } + ++static void ++cpu_add_feat_as_prop(const char *typename, const char *name, const char *val) ++{ ++ GlobalProperty *prop = g_new0(typeof(*prop), 1); ++ prop->driver = typename; ++ prop->property = g_strdup(name); ++ prop->value = g_strdup(val); ++ qdev_prop_register_global(prop); ++} ++ ++static gint compare_string(gconstpointer a, gconstpointer b) ++{ ++ return g_strcmp0(a, b); ++} ++ ++static GList *plus_features, *minus_features; ++ ++static void aarch64_cpu_parse_features(const char *typename, char *features, ++ Error **errp) ++{ ++ GList *l; ++ char *featurestr; /* Single 'key=value" string being parsed */ ++ static bool cpu_globals_initialized; ++ ++ if (cpu_globals_initialized) { ++ return; ++ } ++ cpu_globals_initialized = true; ++ ++ if (!features) { ++ return; ++ } ++ for (featurestr = strtok(features, ","); ++ featurestr; ++ featurestr = strtok(NULL, ",")) { ++ const char *name; ++ const char *val = NULL; ++ char *eq = NULL; ++ ++ /* Compatibility syntax: */ ++ if (featurestr[0] == '+') { ++ plus_features = g_list_append(plus_features, ++ g_strdup(featurestr + 1)); ++ continue; ++ } else if (featurestr[0] == '-') { ++ minus_features = g_list_append(minus_features, ++ g_strdup(featurestr + 1)); ++ continue; ++ } ++ ++ eq = strchr(featurestr, '='); ++ name = featurestr; ++ if (eq) { ++ *eq++ = 0; ++ val = eq; ++ } else { ++ error_setg(errp, "Unsupported property format: %s", name); ++ return; ++ } ++ ++ if (g_list_find_custom(plus_features, name, compare_string)) { ++ warn_report("Ambiguous CPU model string. " ++ "Don't mix both \"+%s\" and \"%s=%s\"", ++ name, name, val); ++ } ++ if (g_list_find_custom(minus_features, name, compare_string)) { ++ warn_report("Ambiguous CPU model string. " ++ "Don't mix both \"-%s\" and \"%s=%s\"", ++ name, name, val); ++ } ++ cpu_add_feat_as_prop(typename, name, val); ++ } ++ ++ for (l = plus_features; l; l = l->next) { ++ cpu_add_feat_as_prop(typename, l->data, "on"); ++ } ++ ++ for (l = minus_features; l; l = l->next) { ++ cpu_add_feat_as_prop(typename, l->data, "off"); ++ } ++} ++ + static void aarch64_cpu_class_init(ObjectClass *oc, void *data) + { + CPUClass *cc = CPU_CLASS(oc); +@@ -991,6 +1073,7 @@ static void aarch64_cpu_class_init(ObjectClass *oc, void *data) + cc->gdb_num_core_regs = 34; + cc->gdb_core_xml_file = "aarch64-core.xml"; + cc->gdb_arch_name = aarch64_gdb_arch_name; ++ cc->parse_features = aarch64_cpu_parse_features; + + object_class_property_add_bool(oc, "aarch64", aarch64_cpu_get_aarch64, + aarch64_cpu_set_aarch64); +-- +2.27.0 + -- Gitee From 43ec14943e377f9f99d0115077deb6ad6caea60a Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Thu, 6 Aug 2020 16:14:37 +0800 Subject: [PATCH 42/54] target/arm: register CPU features for property The Arm architecture specifies a number of ID registers that are characterized as comprising a set of 4-bit ID fields. Each ID field identifies the presence, and possibly the level of support for, a particular feature in an implementation of the architecture. [1] For most of the ID fields, there is a minimum presence value, equal to or higher than which means the corresponding CPU feature is implemented. Hence, we can use the minimum presence value to determine whether a CPU feature is enabled and enable a CPU feature. To disable a CPU feature, setting the corresponding ID field to 0x0/0xf (for unsigned/signed field) seems as a good idea. However, it maybe lead to some problems. For example, ID_AA64PFR0_EL1.FP is a signed ID field. ID_AA64PFR0_EL1.FP == 0x0 represents the implementation of FP (floating-point) and ID_AA64PFR0_EL1.FP == 0x1 represents the implementation of FPHP (half-precision floating-point). If ID_AA64PFR0_EL1.FP is set to 0xf when FPHP is disabled (which is also disable FP), guest kernel maybe stuck. Hence, we add a ni_value (means not-implemented value) to disable a CPU feature safely. [1] D13.1.3 Principles of the ID scheme for fields in ID registers in DDI.0487 Signed-off-by: zhanghailiang Signed-off-by: Peng Liang Signed-off-by: Dongxu Sun --- ...m-register-CPU-features-for-property.patch | 399 ++++++++++++++++++ 1 file changed, 399 insertions(+) create mode 100644 target-arm-register-CPU-features-for-property.patch diff --git a/target-arm-register-CPU-features-for-property.patch b/target-arm-register-CPU-features-for-property.patch new file mode 100644 index 0000000..3d60d68 --- /dev/null +++ b/target-arm-register-CPU-features-for-property.patch @@ -0,0 +1,399 @@ +From 9fd09aabba558b39ca949ef376d05bc0779fdda6 Mon Sep 17 00:00:00 2001 +From: Peng Liang +Date: Thu, 6 Aug 2020 16:14:37 +0800 +Subject: [PATCH] target/arm: register CPU features for property + +The Arm architecture specifies a number of ID registers that are +characterized as comprising a set of 4-bit ID fields. Each ID field +identifies the presence, and possibly the level of support for, a +particular feature in an implementation of the architecture. [1] + +For most of the ID fields, there is a minimum presence value, equal to +or higher than which means the corresponding CPU feature is implemented. +Hence, we can use the minimum presence value to determine whether a CPU +feature is enabled and enable a CPU feature. + +To disable a CPU feature, setting the corresponding ID field to 0x0/0xf +(for unsigned/signed field) seems as a good idea. However, it maybe +lead to some problems. For example, ID_AA64PFR0_EL1.FP is a signed ID +field. ID_AA64PFR0_EL1.FP == 0x0 represents the implementation of FP +(floating-point) and ID_AA64PFR0_EL1.FP == 0x1 represents the +implementation of FPHP (half-precision floating-point). If +ID_AA64PFR0_EL1.FP is set to 0xf when FPHP is disabled (which is also +disable FP), guest kernel maybe stuck. Hence, we add a ni_value (means +not-implemented value) to disable a CPU feature safely. + +[1] D13.1.3 Principles of the ID scheme for fields in ID registers in + DDI.0487 + +Signed-off-by: zhanghailiang +Signed-off-by: Peng Liang +Signed-off-by: Dongxu Sun +--- + target/arm/cpu.c | 343 +++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 343 insertions(+) + +diff --git a/target/arm/cpu.c b/target/arm/cpu.c +index f1ce0474a3..c081ecc12b 100644 +--- a/target/arm/cpu.c ++++ b/target/arm/cpu.c +@@ -1211,6 +1211,347 @@ unsigned int gt_cntfrq_period_ns(ARMCPU *cpu) + NANOSECONDS_PER_SECOND / cpu->gt_cntfrq_hz : 1; + } + ++/** ++ * CPUFeatureInfo: ++ * @reg: The ID register where the ID field is in. ++ * @name: The name of the CPU feature. ++ * @length: The bit length of the ID field. ++ * @shift: The bit shift of the ID field in the ID register. ++ * @min_value: The minimum value equal to or larger than which means the CPU ++ * feature is implemented. ++ * @ni_value: Not-implemented value. It will be set to the ID field when ++ * disabling the CPU feature. Usually, it's min_value - 1. ++ * @sign: Whether the ID field is signed. ++ * @is_32bit: Whether the CPU feature is for 32-bit. ++ * ++ * In ARM, a CPU feature is described by an ID field, which is a 4-bit field in ++ * an ID register. ++ */ ++typedef struct CPUFeatureInfo { ++ CPUIDReg reg; ++ const char *name; ++ int length; ++ int shift; ++ int min_value; ++ int ni_value; ++ bool sign; ++ bool is_32bit; ++} CPUFeatureInfo; ++ ++#define FIELD_INFO(feature_name, id_reg, field, s, min_val, ni_val, is32bit) { \ ++ .reg = id_reg, \ ++ .length = R_ ## id_reg ## _ ## field ## _LENGTH, \ ++ .shift = R_ ## id_reg ## _ ## field ## _SHIFT, \ ++ .sign = s, \ ++ .min_value = min_val, \ ++ .ni_value = ni_val, \ ++ .name = feature_name, \ ++ .is_32bit = is32bit, \ ++} ++ ++static struct CPUFeatureInfo cpu_features[] = { ++ FIELD_INFO("swap", ID_ISAR0, SWAP, false, 1, 0, true), ++ FIELD_INFO("bitcount", ID_ISAR0, BITCOUNT, false, 1, 0, true), ++ FIELD_INFO("bitfield", ID_ISAR0, BITFIELD, false, 1, 0, true), ++ FIELD_INFO("cmpbranch", ID_ISAR0, CMPBRANCH, false, 1, 0, true), ++ FIELD_INFO("coproc", ID_ISAR0, COPROC, false, 1, 0, true), ++ FIELD_INFO("debug", ID_ISAR0, DEBUG, false, 1, 0, true), ++ FIELD_INFO("device", ID_ISAR0, DIVIDE, false, 1, 0, true), ++ ++ FIELD_INFO("endian", ID_ISAR1, ENDIAN, false, 1, 0, true), ++ FIELD_INFO("except", ID_ISAR1, EXCEPT, false, 1, 0, true), ++ FIELD_INFO("except_ar", ID_ISAR1, EXCEPT_AR, false, 1, 0, true), ++ FIELD_INFO("extend", ID_ISAR1, EXTEND, false, 1, 0, true), ++ FIELD_INFO("ifthen", ID_ISAR1, IFTHEN, false, 1, 0, true), ++ FIELD_INFO("immediate", ID_ISAR1, IMMEDIATE, false, 1, 0, true), ++ FIELD_INFO("interwork", ID_ISAR1, INTERWORK, false, 1, 0, true), ++ FIELD_INFO("jazelle", ID_ISAR1, JAZELLE, false, 1, 0, true), ++ ++ FIELD_INFO("loadstore", ID_ISAR2, LOADSTORE, false, 1, 0, true), ++ FIELD_INFO("memhint", ID_ISAR2, MEMHINT, false, 1, 0, true), ++ FIELD_INFO("multiaccessint", ID_ISAR2, MULTIACCESSINT, false, 1, 0, true), ++ FIELD_INFO("mult", ID_ISAR2, MULT, false, 1, 0, true), ++ FIELD_INFO("mults", ID_ISAR2, MULTS, false, 1, 0, true), ++ FIELD_INFO("multu", ID_ISAR2, MULTU, false, 1, 0, true), ++ FIELD_INFO("psr_ar", ID_ISAR2, PSR_AR, false, 1, 0, true), ++ FIELD_INFO("reversal", ID_ISAR2, REVERSAL, false, 1, 0, true), ++ ++ FIELD_INFO("saturate", ID_ISAR3, SATURATE, false, 1, 0, true), ++ FIELD_INFO("simd", ID_ISAR3, SIMD, false, 1, 0, true), ++ FIELD_INFO("svc", ID_ISAR3, SVC, false, 1, 0, true), ++ FIELD_INFO("synchprim", ID_ISAR3, SYNCHPRIM, false, 1, 0, true), ++ FIELD_INFO("tabbranch", ID_ISAR3, TABBRANCH, false, 1, 0, true), ++ FIELD_INFO("t32copy", ID_ISAR3, T32COPY, false, 1, 0, true), ++ FIELD_INFO("truenop", ID_ISAR3, TRUENOP, false, 1, 0, true), ++ FIELD_INFO("t32ee", ID_ISAR3, T32EE, false, 1, 0, true), ++ ++ FIELD_INFO("unpriv", ID_ISAR4, UNPRIV, false, 1, 0, true), ++ FIELD_INFO("withshifts", ID_ISAR4, WITHSHIFTS, false, 1, 0, true), ++ FIELD_INFO("writeback", ID_ISAR4, WRITEBACK, false, 1, 0, true), ++ FIELD_INFO("smc", ID_ISAR4, SMC, false, 1, 0, true), ++ FIELD_INFO("barrier", ID_ISAR4, BARRIER, false, 1, 0, true), ++ FIELD_INFO("synchprim_frac", ID_ISAR4, SYNCHPRIM_FRAC, false, 1, 0, true), ++ FIELD_INFO("psr_m", ID_ISAR4, PSR_M, false, 1, 0, true), ++ FIELD_INFO("swp_frac", ID_ISAR4, SWP_FRAC, false, 1, 0, true), ++ ++ FIELD_INFO("sevl", ID_ISAR5, SEVL, false, 1, 0, true), ++ FIELD_INFO("aes", ID_ISAR5, AES, false, 1, 0, true), ++ FIELD_INFO("sha1", ID_ISAR5, SHA1, false, 1, 0, true), ++ FIELD_INFO("sha2", ID_ISAR5, SHA2, false, 1, 0, true), ++ FIELD_INFO("crc32", ID_ISAR5, CRC32, false, 1, 0, true), ++ FIELD_INFO("rdm", ID_ISAR5, RDM, false, 1, 0, true), ++ FIELD_INFO("vcma", ID_ISAR5, VCMA, false, 1, 0, true), ++ ++ FIELD_INFO("jscvt", ID_ISAR6, JSCVT, false, 1, 0, true), ++ FIELD_INFO("dp", ID_ISAR6, DP, false, 1, 0, true), ++ FIELD_INFO("fhm", ID_ISAR6, FHM, false, 1, 0, true), ++ FIELD_INFO("sb", ID_ISAR6, SB, false, 1, 0, true), ++ FIELD_INFO("specres", ID_ISAR6, SPECRES, false, 1, 0, true), ++ ++ FIELD_INFO("cmaintva", ID_MMFR3, CMAINTVA, false, 1, 0, true), ++ FIELD_INFO("cmaintsw", ID_MMFR3, CMAINTSW, false, 1, 0, true), ++ FIELD_INFO("bpmaint", ID_MMFR3, BPMAINT, false, 1, 0, true), ++ FIELD_INFO("maintbcst", ID_MMFR3, MAINTBCST, false, 1, 0, true), ++ FIELD_INFO("pan", ID_MMFR3, PAN, false, 1, 0, true), ++ FIELD_INFO("cohwalk", ID_MMFR3, COHWALK, false, 1, 0, true), ++ FIELD_INFO("cmemsz", ID_MMFR3, CMEMSZ, false, 1, 0, true), ++ FIELD_INFO("supersec", ID_MMFR3, SUPERSEC, false, 1, 0, true), ++ ++ FIELD_INFO("specsei", ID_MMFR4, SPECSEI, false, 1, 0, true), ++ FIELD_INFO("ac2", ID_MMFR4, AC2, false, 1, 0, true), ++ FIELD_INFO("xnx", ID_MMFR4, XNX, false, 1, 0, true), ++ FIELD_INFO("cnp", ID_MMFR4, CNP, false, 1, 0, true), ++ FIELD_INFO("hpds", ID_MMFR4, HPDS, false, 1, 0, true), ++ FIELD_INFO("lsm", ID_MMFR4, LSM, false, 1, 0, true), ++ FIELD_INFO("ccidx", ID_MMFR4, CCIDX, false, 1, 0, true), ++ FIELD_INFO("evt", ID_MMFR4, EVT, false, 1, 0, true), ++ ++ FIELD_INFO("simdreg", MVFR0, SIMDREG, false, 1, 0, true), ++ FIELD_INFO("fpsp", MVFR0, FPSP, false, 1, 0, true), ++ FIELD_INFO("fpdp", MVFR0, FPDP, false, 1, 0, true), ++ FIELD_INFO("fptrap", MVFR0, FPTRAP, false, 1, 0, true), ++ FIELD_INFO("fpdivide", MVFR0, FPDIVIDE, false, 1, 0, true), ++ FIELD_INFO("fpsqrt", MVFR0, FPSQRT, false, 1, 0, true), ++ FIELD_INFO("fpshvec", MVFR0, FPSHVEC, false, 1, 0, true), ++ FIELD_INFO("fpround", MVFR0, FPROUND, false, 1, 0, true), ++ ++ FIELD_INFO("fpftz", MVFR1, FPFTZ, false, 1, 0, true), ++ FIELD_INFO("fpdnan", MVFR1, FPDNAN, false, 1, 0, true), ++ FIELD_INFO("simdls", MVFR1, SIMDLS, false, 1, 0, true), ++ FIELD_INFO("simdint", MVFR1, SIMDINT, false, 1, 0, true), ++ FIELD_INFO("simdsp", MVFR1, SIMDSP, false, 1, 0, true), ++ FIELD_INFO("simdhp", MVFR1, SIMDHP, false, 1, 0, true), ++ FIELD_INFO("fphp", MVFR1, FPHP, false, 1, 0, true), ++ FIELD_INFO("simdfmac", MVFR1, SIMDFMAC, false, 1, 0, true), ++ ++ FIELD_INFO("simdmisc", MVFR2, SIMDMISC, false, 1, 0, true), ++ FIELD_INFO("fpmisc", MVFR2, FPMISC, false, 1, 0, true), ++ ++ FIELD_INFO("debugver", ID_AA64DFR0, DEBUGVER, false, 1, 0, false), ++ FIELD_INFO("tracever", ID_AA64DFR0, TRACEVER, false, 1, 0, false), ++ FIELD_INFO("pmuver", ID_AA64DFR0, PMUVER, false, 1, 0, false), ++ FIELD_INFO("brps", ID_AA64DFR0, BRPS, false, 1, 0, false), ++ FIELD_INFO("wrps", ID_AA64DFR0, WRPS, false, 1, 0, false), ++ FIELD_INFO("ctx_cmps", ID_AA64DFR0, CTX_CMPS, false, 1, 0, false), ++ FIELD_INFO("pmsver", ID_AA64DFR0, PMSVER, false, 1, 0, false), ++ FIELD_INFO("doublelock", ID_AA64DFR0, DOUBLELOCK, false, 1, 0, false), ++ FIELD_INFO("tracefilt", ID_AA64DFR0, TRACEFILT, false, 1, 0, false), ++ ++ FIELD_INFO("aes", ID_AA64ISAR0, AES, false, 1, 0, false), ++ FIELD_INFO("sha1", ID_AA64ISAR0, SHA1, false, 1, 0, false), ++ FIELD_INFO("sha2", ID_AA64ISAR0, SHA2, false, 1, 0, false), ++ FIELD_INFO("crc32", ID_AA64ISAR0, CRC32, false, 1, 0, false), ++ FIELD_INFO("atomics", ID_AA64ISAR0, ATOMIC, false, 1, 0, false), ++ FIELD_INFO("asimdrdm", ID_AA64ISAR0, RDM, false, 1, 0, false), ++ FIELD_INFO("sha3", ID_AA64ISAR0, SHA3, false, 1, 0, false), ++ FIELD_INFO("sm3", ID_AA64ISAR0, SM3, false, 1, 0, false), ++ FIELD_INFO("sm4", ID_AA64ISAR0, SM4, false, 1, 0, false), ++ FIELD_INFO("asimddp", ID_AA64ISAR0, DP, false, 1, 0, false), ++ FIELD_INFO("asimdfhm", ID_AA64ISAR0, FHM, false, 1, 0, false), ++ FIELD_INFO("flagm", ID_AA64ISAR0, TS, false, 1, 0, false), ++ FIELD_INFO("tlb", ID_AA64ISAR0, TLB, false, 1, 0, false), ++ FIELD_INFO("rng", ID_AA64ISAR0, RNDR, false, 1, 0, false), ++ ++ FIELD_INFO("dcpop", ID_AA64ISAR1, DPB, false, 1, 0, false), ++ FIELD_INFO("papa", ID_AA64ISAR1, APA, false, 1, 0, false), ++ FIELD_INFO("api", ID_AA64ISAR1, API, false, 1, 0, false), ++ FIELD_INFO("jscvt", ID_AA64ISAR1, JSCVT, false, 1, 0, false), ++ FIELD_INFO("fcma", ID_AA64ISAR1, FCMA, false, 1, 0, false), ++ FIELD_INFO("lrcpc", ID_AA64ISAR1, LRCPC, false, 1, 0, false), ++ FIELD_INFO("pacg", ID_AA64ISAR1, GPA, false, 1, 0, false), ++ FIELD_INFO("gpi", ID_AA64ISAR1, GPI, false, 1, 0, false), ++ FIELD_INFO("frint", ID_AA64ISAR1, FRINTTS, false, 1, 0, false), ++ FIELD_INFO("sb", ID_AA64ISAR1, SB, false, 1, 0, false), ++ FIELD_INFO("specres", ID_AA64ISAR1, SPECRES, false, 1, 0, false), ++ ++ FIELD_INFO("el0", ID_AA64PFR0, EL0, false, 1, 0, false), ++ FIELD_INFO("el1", ID_AA64PFR0, EL1, false, 1, 0, false), ++ FIELD_INFO("el2", ID_AA64PFR0, EL2, false, 1, 0, false), ++ FIELD_INFO("el3", ID_AA64PFR0, EL3, false, 1, 0, false), ++ FIELD_INFO("fp", ID_AA64PFR0, FP, true, 0, 0xf, false), ++ FIELD_INFO("asimd", ID_AA64PFR0, ADVSIMD, true, 0, 0xf, false), ++ FIELD_INFO("gic", ID_AA64PFR0, GIC, false, 1, 0, false), ++ FIELD_INFO("ras", ID_AA64PFR0, RAS, false, 1, 0, false), ++ FIELD_INFO("sve", ID_AA64PFR0, SVE, false, 1, 0, false), ++ ++ FIELD_INFO("bti", ID_AA64PFR1, BT, false, 1, 0, false), ++ FIELD_INFO("ssbs", ID_AA64PFR1, SSBS, false, 1, 0, false), ++ FIELD_INFO("mte", ID_AA64PFR1, MTE, false, 1, 0, false), ++ FIELD_INFO("ras_frac", ID_AA64PFR1, RAS_FRAC, false, 1, 0, false), ++ ++ FIELD_INFO("parange", ID_AA64MMFR0, PARANGE, false, 1, 0, false), ++ FIELD_INFO("asidbits", ID_AA64MMFR0, ASIDBITS, false, 1, 0, false), ++ FIELD_INFO("bigend", ID_AA64MMFR0, BIGEND, false, 1, 0, false), ++ FIELD_INFO("snsmem", ID_AA64MMFR0, SNSMEM, false, 1, 0, false), ++ FIELD_INFO("bigendel0", ID_AA64MMFR0, BIGENDEL0, false, 1, 0, false), ++ FIELD_INFO("tgran16", ID_AA64MMFR0, TGRAN16, false, 1, 0, false), ++ FIELD_INFO("tgran64", ID_AA64MMFR0, TGRAN64, false, 1, 0, false), ++ FIELD_INFO("tgran4", ID_AA64MMFR0, TGRAN4, false, 1, 0, false), ++ FIELD_INFO("tgran16_2", ID_AA64MMFR0, TGRAN16_2, false, 1, 0, false), ++ FIELD_INFO("tgran64_2", ID_AA64MMFR0, TGRAN64_2, false, 1, 0, false), ++ FIELD_INFO("tgran4_2", ID_AA64MMFR0, TGRAN4_2, false, 1, 0, false), ++ FIELD_INFO("exs", ID_AA64MMFR0, EXS, false, 1, 0, false), ++ ++ FIELD_INFO("hafdbs", ID_AA64MMFR1, HAFDBS, false, 1, 0, false), ++ FIELD_INFO("vmidbits", ID_AA64MMFR1, VMIDBITS, false, 1, 0, false), ++ FIELD_INFO("vh", ID_AA64MMFR1, VH, false, 1, 0, false), ++ FIELD_INFO("hpds", ID_AA64MMFR1, HPDS, false, 1, 0, false), ++ FIELD_INFO("lo", ID_AA64MMFR1, LO, false, 1, 0, false), ++ FIELD_INFO("pan", ID_AA64MMFR1, PAN, false, 1, 0, false), ++ FIELD_INFO("specsei", ID_AA64MMFR1, SPECSEI, false, 1, 0, false), ++ FIELD_INFO("xnx", ID_AA64MMFR1, XNX, false, 1, 0, false), ++ ++ FIELD_INFO("cnp", ID_AA64MMFR2, CNP, false, 1, 0, false), ++ FIELD_INFO("uao", ID_AA64MMFR2, UAO, false, 1, 0, false), ++ FIELD_INFO("lsm", ID_AA64MMFR2, LSM, false, 1, 0, false), ++ FIELD_INFO("iesb", ID_AA64MMFR2, IESB, false, 1, 0, false), ++ FIELD_INFO("varange", ID_AA64MMFR2, VARANGE, false, 1, 0, false), ++ FIELD_INFO("ccidx", ID_AA64MMFR2, CCIDX, false, 1, 0, false), ++ FIELD_INFO("nv", ID_AA64MMFR2, NV, false, 1, 0, false), ++ FIELD_INFO("st", ID_AA64MMFR2, ST, false, 1, 0, false), ++ FIELD_INFO("uscat", ID_AA64MMFR2, AT, false, 1, 0, false), ++ FIELD_INFO("ids", ID_AA64MMFR2, IDS, false, 1, 0, false), ++ FIELD_INFO("fwb", ID_AA64MMFR2, FWB, false, 1, 0, false), ++ FIELD_INFO("ttl", ID_AA64MMFR2, TTL, false, 1, 0, false), ++ FIELD_INFO("bbm", ID_AA64MMFR2, BBM, false, 1, 0, false), ++ FIELD_INFO("evt", ID_AA64MMFR2, EVT, false, 1, 0, false), ++ FIELD_INFO("e0pd", ID_AA64MMFR2, E0PD, false, 1, 0, false), ++ ++ FIELD_INFO("copdbg", ID_DFR0, COPDBG, false, 1, 0, false), ++ FIELD_INFO("copsdbg", ID_DFR0, COPSDBG, false, 1, 0, false), ++ FIELD_INFO("mmapdbg", ID_DFR0, MMAPDBG, false, 1, 0, false), ++ FIELD_INFO("coptrc", ID_DFR0, COPTRC, false, 1, 0, false), ++ FIELD_INFO("mmaptrc", ID_DFR0, MMAPTRC, false, 1, 0, false), ++ FIELD_INFO("mprofdbg", ID_DFR0, MPROFDBG, false, 1, 0, false), ++ FIELD_INFO("perfmon", ID_DFR0, PERFMON, false, 1, 0, false), ++ FIELD_INFO("tracefilt", ID_DFR0, TRACEFILT, false, 1, 0, false), ++ ++ { ++ .reg = ID_AA64PFR0, .length = R_ID_AA64PFR0_FP_LENGTH, ++ .shift = R_ID_AA64PFR0_FP_SHIFT, .sign = true, .min_value = 1, ++ .ni_value = 0, .name = "fphp", .is_32bit = false, ++ }, ++ { ++ .reg = ID_AA64PFR0, .length = R_ID_AA64PFR0_ADVSIMD_LENGTH, ++ .shift = R_ID_AA64PFR0_ADVSIMD_SHIFT, .sign = true, .min_value = 1, ++ .ni_value = 0, .name = "asimdhp", .is_32bit = false, ++ }, ++ { ++ .reg = ID_AA64ISAR0, .length = R_ID_AA64ISAR0_AES_LENGTH, ++ .shift = R_ID_AA64ISAR0_AES_SHIFT, .sign = false, .min_value = 2, ++ .ni_value = 1, .name = "pmull", .is_32bit = false, ++ }, ++ { ++ .reg = ID_AA64ISAR0, .length = R_ID_AA64ISAR0_SHA2_LENGTH, ++ .shift = R_ID_AA64ISAR0_SHA2_SHIFT, .sign = false, .min_value = 2, ++ .ni_value = 1, .name = "sha512", .is_32bit = false, ++ }, ++ { ++ .reg = ID_AA64ISAR0, .length = R_ID_AA64ISAR0_TS_LENGTH, ++ .shift = R_ID_AA64ISAR0_TS_SHIFT, .sign = false, .min_value = 2, ++ .ni_value = 1, .name = "flagm2", .is_32bit = false, ++ }, ++ { ++ .reg = ID_AA64ISAR1, .length = R_ID_AA64ISAR1_DPB_LENGTH, ++ .shift = R_ID_AA64ISAR1_DPB_SHIFT, .sign = false, .min_value = 2, ++ .ni_value = 1, .name = "dcpodp", .is_32bit = false, ++ }, ++ { ++ .reg = ID_AA64ISAR1, .length = R_ID_AA64ISAR1_LRCPC_LENGTH, ++ .shift = R_ID_AA64ISAR1_LRCPC_SHIFT, .sign = false, .min_value = 2, ++ .ni_value = 1, .name = "ilrcpc", .is_32bit = false, ++ }, ++}; ++ ++static void arm_cpu_get_bit_prop(Object *obj, Visitor *v, const char *name, ++ void *opaque, Error **errp) ++{ ++ ARMCPU *cpu = ARM_CPU(obj); ++ CPUFeatureInfo *feat = opaque; ++ int field_value = feat->sign ? sextract64(cpu->isar.regs[feat->reg], ++ feat->shift, feat->length) : ++ extract64(cpu->isar.regs[feat->reg], ++ feat->shift, feat->length); ++ bool value = field_value >= feat->min_value; ++ ++ visit_type_bool(v, name, &value, errp); ++} ++ ++static void arm_cpu_set_bit_prop(Object *obj, Visitor *v, const char *name, ++ void *opaque, Error **errp) ++{ ++ DeviceState *dev = DEVICE(obj); ++ ARMCPU *cpu = ARM_CPU(obj); ++ ARMISARegisters *isar = &cpu->isar; ++ CPUFeatureInfo *feat = opaque; ++ Error *local_err = NULL; ++ bool value; ++ ++ if (dev->realized) { ++ qdev_prop_set_after_realize(dev, name, errp); ++ return; ++ } ++ ++ visit_type_bool(v, name, &value, &local_err); ++ if (local_err) { ++ error_propagate(errp, local_err); ++ return; ++ } ++ ++ if (value) { ++ isar->regs[feat->reg] = deposit64(isar->regs[feat->reg], ++ feat->shift, feat->length, ++ feat->min_value); ++ } else { ++ isar->regs[feat->reg] = deposit64(isar->regs[feat->reg], ++ feat->shift, feat->length, ++ feat->ni_value); ++ } ++} ++ ++static void arm_cpu_register_feature_props(ARMCPU *cpu) ++{ ++ int i; ++ int num = ARRAY_SIZE(cpu_features); ++ ObjectProperty *op; ++ CPUARMState *env = &cpu->env; ++ ++ for (i = 0; i < num; i++) { ++ if ((arm_feature(env, ARM_FEATURE_AARCH64) && cpu_features[i].is_32bit) ++ || (!arm_feature(env, ARM_FEATURE_AARCH64) && ++ cpu_features[i].is_32bit)) { ++ continue; ++ } ++ op = object_property_find(OBJECT(cpu), cpu_features[i].name); ++ if (!op) { ++ object_property_add(OBJECT(cpu), cpu_features[i].name, "bool", ++ arm_cpu_get_bit_prop, ++ arm_cpu_set_bit_prop, ++ NULL, &cpu_features[i]); ++ } ++ } ++} ++ + void arm_cpu_post_init(Object *obj) + { + ARMCPU *cpu = ARM_CPU(obj); +@@ -1319,6 +1660,8 @@ void arm_cpu_post_init(Object *obj) + + qdev_property_add_static(DEVICE(obj), &arm_cpu_cfgend_property); + ++ arm_cpu_register_feature_props(cpu); ++ + if (arm_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER)) { + qdev_property_add_static(DEVICE(cpu), &arm_cpu_gt_cntfrq_property); + } +-- +2.27.0 + -- Gitee From 52b9da712cfb9a44fb1f6147727ff196a70592a8 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Thu, 6 Aug 2020 16:14:40 +0800 Subject: [PATCH 43/54] target/arm: Allow ID registers to synchronize to KVM There are 2 steps to synchronize the values of system registers from CPU state to KVM: 1. write to the values of system registers from CPU state to (index,value) list by write_cpustate_to_list; 2. write the values in (index,value) list to KVM by write_list_to_kvmstate; In step 1, the values of constant system registers are not allowed to write to (index,value) list. However, a constant system register is CONSTANT for guest but not for QEMU, which means, QEMU can set/modify the value of constant system registers that is different from phsical registers when startup. But if KVM is enabled, guest can not read the values of the system registers which QEMU set unless they can be written to (index,value) list. And why not try to write to KVM if kvm_sync is true? At the moment we call write_cpustate_to_list, all ID registers are contant, including ID_PFR1_EL1 and ID_AA64PFR0_EL1 because GIC has been initialized. Hence, let's give all ID registers a chance to write to KVM. If the write is successful, then write to (index,value) list. Signed-off-by: zhanghailiang Signed-off-by: Peng Liang Signed-off-by: Dongxu Sun --- ...w-ID-registers-to-synchronize-to-KVM.patch | 161 ++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 target-arm-Allow-ID-registers-to-synchronize-to-KVM.patch diff --git a/target-arm-Allow-ID-registers-to-synchronize-to-KVM.patch b/target-arm-Allow-ID-registers-to-synchronize-to-KVM.patch new file mode 100644 index 0000000..8464571 --- /dev/null +++ b/target-arm-Allow-ID-registers-to-synchronize-to-KVM.patch @@ -0,0 +1,161 @@ +From 0272c52e36ab95389e665ca19b129178b0b46eac Mon Sep 17 00:00:00 2001 +From: Peng Liang +Date: Thu, 6 Aug 2020 16:14:40 +0800 +Subject: [PATCH] target/arm: Allow ID registers to synchronize to KVM + +There are 2 steps to synchronize the values of system registers from +CPU state to KVM: +1. write to the values of system registers from CPU state to + (index,value) list by write_cpustate_to_list; +2. write the values in (index,value) list to KVM by + write_list_to_kvmstate; + +In step 1, the values of constant system registers are not allowed to +write to (index,value) list. However, a constant system register is +CONSTANT for guest but not for QEMU, which means, QEMU can set/modify +the value of constant system registers that is different from phsical +registers when startup. But if KVM is enabled, guest can not read the +values of the system registers which QEMU set unless they can be written +to (index,value) list. And why not try to write to KVM if kvm_sync is +true? + +At the moment we call write_cpustate_to_list, all ID registers are +contant, including ID_PFR1_EL1 and ID_AA64PFR0_EL1 because GIC has been +initialized. Hence, let's give all ID registers a chance to write to +KVM. If the write is successful, then write to (index,value) list. + +Signed-off-by: zhanghailiang +Signed-off-by: Peng Liang +Signed-off-by: Dongxu Sun +--- + target/arm/helper.c | 31 ++++++++++++++++++++----------- + target/arm/kvm.c | 38 ++++++++++++++++++++++++++++++++++++++ + target/arm/kvm_arm.h | 3 +++ + 3 files changed, 61 insertions(+), 11 deletions(-) + +diff --git a/target/arm/helper.c b/target/arm/helper.c +index b8ea1dc1f6..79f77705c3 100644 +--- a/target/arm/helper.c ++++ b/target/arm/helper.c +@@ -35,6 +35,7 @@ + #include "exec/cpu_ldst.h" + #include "semihosting/common-semi.h" + #endif ++#include "kvm_arm.h" + + #define ARM_CPU_FREQ 1000000000 /* FIXME: 1 GHz, should be configurable */ + #define PMCR_NUM_COUNTERS 4 /* QEMU IMPDEF choice */ +@@ -149,30 +150,38 @@ bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync) + ok = false; + continue; + } +- if (ri->type & ARM_CP_NO_RAW) { ++ /* ++ * (Op0, Op1, CRn, CRm, Op2) of ID registers is (3, 0, 0, crm, op2), ++ * where 1<=crm<8, 0<=op2<8. Let's give ID registers a chance to ++ * synchronize to kvm. ++ */ ++ if ((ri->type & ARM_CP_NO_RAW) && !(kvm_sync && ++ ri->opc0 == 3 && ri->opc1 == 0 && ri->crn == 0 && ri->crm > 0)) { + continue; + } + + newval = read_raw_cp_reg(&cpu->env, ri); + if (kvm_sync) { +- /* +- * Only sync if the previous list->cpustate sync succeeded. +- * Rather than tracking the success/failure state for every +- * item in the list, we just recheck "does the raw write we must +- * have made in write_list_to_cpustate() read back OK" here. +- */ +- uint64_t oldval = cpu->cpreg_values[i]; ++ /* Only sync if we can sync to KVM successfully. */ ++ uint64_t oldval; ++ uint64_t kvmval; + ++ if (kvm_arm_get_one_reg(cpu, cpu->cpreg_indexes[i], &oldval)) { ++ continue; ++ } + if (oldval == newval) { + continue; + } + +- write_raw_cp_reg(&cpu->env, ri, oldval); +- if (read_raw_cp_reg(&cpu->env, ri) != oldval) { ++ if (kvm_arm_set_one_reg(cpu, cpu->cpreg_indexes[i], &newval)) { ++ continue; ++ } ++ if (kvm_arm_get_one_reg(cpu, cpu->cpreg_indexes[i], &kvmval) || ++ kvmval != newval) { + continue; + } + +- write_raw_cp_reg(&cpu->env, ri, newval); ++ kvm_arm_set_one_reg(cpu, cpu->cpreg_indexes[i], &oldval); + } + cpu->cpreg_values[i] = newval; + } +diff --git a/target/arm/kvm.c b/target/arm/kvm.c +index bbf1ce7ba3..59d556724f 100644 +--- a/target/arm/kvm.c ++++ b/target/arm/kvm.c +@@ -514,6 +514,44 @@ out: + return ret; + } + ++int kvm_arm_get_one_reg(ARMCPU *cpu, uint64_t regidx, uint64_t *target) ++{ ++ uint32_t v32; ++ int ret; ++ ++ switch (regidx & KVM_REG_SIZE_MASK) { ++ case KVM_REG_SIZE_U32: ++ ret = kvm_get_one_reg(CPU(cpu), regidx, &v32); ++ if (ret == 0) { ++ *target = v32; ++ } ++ return ret; ++ case KVM_REG_SIZE_U64: ++ return kvm_get_one_reg(CPU(cpu), regidx, target); ++ default: ++ return -1; ++ } ++} ++ ++int kvm_arm_set_one_reg(ARMCPU *cpu, uint64_t regidx, uint64_t *source) ++{ ++ uint32_t v32; ++ ++ switch (regidx & KVM_REG_SIZE_MASK) { ++ case KVM_REG_SIZE_U32: ++ v32 = *source; ++ if (v32 != *source) { ++ error_report("the value of source is too large"); ++ return -1; ++ } ++ return kvm_set_one_reg(CPU(cpu), regidx, &v32); ++ case KVM_REG_SIZE_U64: ++ return kvm_set_one_reg(CPU(cpu), regidx, source); ++ default: ++ return -1; ++ } ++} ++ + bool write_kvmstate_to_list(ARMCPU *cpu) + { + CPUState *cs = CPU(cpu); +diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h +index b7f78b5215..f8e0e64363 100644 +--- a/target/arm/kvm_arm.h ++++ b/target/arm/kvm_arm.h +@@ -528,4 +528,7 @@ static inline const char *its_class_name(void) + } + } + ++int kvm_arm_get_one_reg(ARMCPU *cpu, uint64_t regidx, uint64_t *target); ++int kvm_arm_set_one_reg(ARMCPU *cpu, uint64_t regidx, uint64_t *source); ++ + #endif +-- +2.27.0 + -- Gitee From 7a54426f32574ce72d357ae6c22fc5e205c4353b Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Thu, 6 Aug 2020 16:14:46 +0800 Subject: [PATCH 44/54] target/arm: introduce CPU feature dependency mechanism Some CPU features are dependent on other CPU features. For example, ID_AA64PFR0_EL1.FP field and ID_AA64PFR0_EL1.AdvSIMD must have the same value, which means FP and ADVSIMD are dependent on each other, FPHP and ADVSIMDHP are dependent on each other. This commit introduces a mechanism for CPU feature dependency in AArch64. We build a directed graph from the CPU feature dependency relationship, each edge from->to means the `to` CPU feature is dependent on the `from` CPU feature. And we will automatically enable/disable CPU feature according to the directed graph. For example, a, b, and c CPU features are in relationship a->b->c, which means c is dependent on b and b is dependent on a. If c is enabled by user, then a and b is enabled automatically. And if a is disabled by user, then b and c is disabled automatically. Signed-off-by: zhanghailiang Signed-off-by: Peng Liang Signed-off-by: Dongxu Sun --- ...duce-CPU-feature-dependency-mechanis.patch | 185 ++++++++++++++++++ 1 file changed, 185 insertions(+) create mode 100644 target-arm-introduce-CPU-feature-dependency-mechanis.patch diff --git a/target-arm-introduce-CPU-feature-dependency-mechanis.patch b/target-arm-introduce-CPU-feature-dependency-mechanis.patch new file mode 100644 index 0000000..aecfbf8 --- /dev/null +++ b/target-arm-introduce-CPU-feature-dependency-mechanis.patch @@ -0,0 +1,185 @@ +From 632d58d1b908ee979074b589417f446c0a3be35d Mon Sep 17 00:00:00 2001 +From: Peng Liang +Date: Thu, 6 Aug 2020 16:14:46 +0800 +Subject: [PATCH] target/arm: introduce CPU feature dependency mechanism + +Some CPU features are dependent on other CPU features. For example, +ID_AA64PFR0_EL1.FP field and ID_AA64PFR0_EL1.AdvSIMD must have the same +value, which means FP and ADVSIMD are dependent on each other, FPHP and +ADVSIMDHP are dependent on each other. + +This commit introduces a mechanism for CPU feature dependency in +AArch64. We build a directed graph from the CPU feature dependency +relationship, each edge from->to means the `to` CPU feature is dependent +on the `from` CPU feature. And we will automatically enable/disable CPU +feature according to the directed graph. + +For example, a, b, and c CPU features are in relationship a->b->c, which +means c is dependent on b and b is dependent on a. If c is enabled by +user, then a and b is enabled automatically. And if a is disabled by +user, then b and c is disabled automatically. + +Signed-off-by: zhanghailiang +Signed-off-by: Peng Liang +Signed-off-by: Dongxu Sun +--- + target/arm/cpu.c | 129 +++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 129 insertions(+) + +diff --git a/target/arm/cpu.c b/target/arm/cpu.c +index c081ecc12b..ee09642dae 100644 +--- a/target/arm/cpu.c ++++ b/target/arm/cpu.c +@@ -1483,6 +1483,103 @@ static struct CPUFeatureInfo cpu_features[] = { + }, + }; + ++typedef struct CPUFeatureDep { ++ CPUFeatureInfo from, to; ++} CPUFeatureDep; ++ ++static const CPUFeatureDep feature_dependencies[] = { ++ { ++ .from = FIELD_INFO("fp", ID_AA64PFR0, FP, true, 0, 0xf, false), ++ .to = FIELD_INFO("asimd", ID_AA64PFR0, ADVSIMD, true, 0, 0xf, false), ++ }, ++ { ++ .from = FIELD_INFO("asimd", ID_AA64PFR0, ADVSIMD, true, 0, 0xf, false), ++ .to = FIELD_INFO("fp", ID_AA64PFR0, FP, true, 0, 0xf, false), ++ }, ++ { ++ .from = { ++ .reg = ID_AA64PFR0, .length = R_ID_AA64PFR0_FP_LENGTH, ++ .shift = R_ID_AA64PFR0_FP_SHIFT, .sign = true, .min_value = 1, ++ .ni_value = 0, .name = "fphp", .is_32bit = false, ++ }, ++ .to = { ++ .reg = ID_AA64PFR0, .length = R_ID_AA64PFR0_ADVSIMD_LENGTH, ++ .shift = R_ID_AA64PFR0_ADVSIMD_SHIFT, .sign = true, .min_value = 1, ++ .ni_value = 0, .name = "asimdhp", .is_32bit = false, ++ }, ++ }, ++ { ++ .from = { ++ .reg = ID_AA64PFR0, .length = R_ID_AA64PFR0_ADVSIMD_LENGTH, ++ .shift = R_ID_AA64PFR0_ADVSIMD_SHIFT, .sign = true, .min_value = 1, ++ .ni_value = 0, .name = "asimdhp", .is_32bit = false, ++ }, ++ .to = { ++ .reg = ID_AA64PFR0, .length = R_ID_AA64PFR0_FP_LENGTH, ++ .shift = R_ID_AA64PFR0_FP_SHIFT, .sign = true, .min_value = 1, ++ .ni_value = 0, .name = "fphp", .is_32bit = false, ++ }, ++ }, ++ { ++ ++ .from = FIELD_INFO("aes", ID_AA64ISAR0, AES, false, 1, 0, false), ++ .to = { ++ .reg = ID_AA64ISAR0, .length = R_ID_AA64ISAR0_AES_LENGTH, ++ .shift = R_ID_AA64ISAR0_AES_SHIFT, .sign = false, .min_value = 2, ++ .ni_value = 1, .name = "pmull", .is_32bit = false, ++ }, ++ }, ++ { ++ ++ .from = FIELD_INFO("sha2", ID_AA64ISAR0, SHA2, false, 1, 0, false), ++ .to = { ++ .reg = ID_AA64ISAR0, .length = R_ID_AA64ISAR0_SHA2_LENGTH, ++ .shift = R_ID_AA64ISAR0_SHA2_SHIFT, .sign = false, .min_value = 2, ++ .ni_value = 1, .name = "sha512", .is_32bit = false, ++ }, ++ }, ++ { ++ .from = FIELD_INFO("lrcpc", ID_AA64ISAR1, LRCPC, false, 1, 0, false), ++ .to = { ++ .reg = ID_AA64ISAR1, .length = R_ID_AA64ISAR1_LRCPC_LENGTH, ++ .shift = R_ID_AA64ISAR1_LRCPC_SHIFT, .sign = false, .min_value = 2, ++ .ni_value = 1, .name = "ilrcpc", .is_32bit = false, ++ }, ++ }, ++ { ++ .from = FIELD_INFO("sm3", ID_AA64ISAR0, SM3, false, 1, 0, false), ++ .to = FIELD_INFO("sm4", ID_AA64ISAR0, SM4, false, 1, 0, false), ++ }, ++ { ++ .from = FIELD_INFO("sm4", ID_AA64ISAR0, SM4, false, 1, 0, false), ++ .to = FIELD_INFO("sm3", ID_AA64ISAR0, SM3, false, 1, 0, false), ++ }, ++ { ++ .from = FIELD_INFO("sha1", ID_AA64ISAR0, SHA1, false, 1, 0, false), ++ .to = FIELD_INFO("sha2", ID_AA64ISAR0, SHA2, false, 1, 0, false), ++ }, ++ { ++ .from = FIELD_INFO("sha1", ID_AA64ISAR0, SHA1, false, 1, 0, false), ++ .to = FIELD_INFO("sha3", ID_AA64ISAR0, SHA3, false, 1, 0, false), ++ }, ++ { ++ .from = FIELD_INFO("sha3", ID_AA64ISAR0, SHA3, false, 1, 0, false), ++ .to = { ++ .reg = ID_AA64ISAR0, .length = R_ID_AA64ISAR0_SHA2_LENGTH, ++ .shift = R_ID_AA64ISAR0_SHA2_SHIFT, .sign = false, .min_value = 2, ++ .ni_value = 1, .name = "sha512", .is_32bit = false, ++ }, ++ }, ++ { ++ .from = { ++ .reg = ID_AA64ISAR0, .length = R_ID_AA64ISAR0_SHA2_LENGTH, ++ .shift = R_ID_AA64ISAR0_SHA2_SHIFT, .sign = false, .min_value = 2, ++ .ni_value = 1, .name = "sha512", .is_32bit = false, ++ }, ++ .to = FIELD_INFO("sha3", ID_AA64ISAR0, SHA3, false, 1, 0, false), ++ }, ++}; ++ + static void arm_cpu_get_bit_prop(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) + { +@@ -1519,13 +1616,45 @@ static void arm_cpu_set_bit_prop(Object *obj, Visitor *v, const char *name, + } + + if (value) { ++ if (object_property_get_bool(obj, feat->name, NULL)) { ++ return; ++ } + isar->regs[feat->reg] = deposit64(isar->regs[feat->reg], + feat->shift, feat->length, + feat->min_value); ++ /* Auto enable the features which current feature is dependent on. */ ++ for (int i = 0; i < ARRAY_SIZE(feature_dependencies); ++i) { ++ const CPUFeatureDep *d = &feature_dependencies[i]; ++ if (strcmp(d->to.name, feat->name) != 0) { ++ continue; ++ } ++ ++ object_property_set_bool(obj, d->from.name, true, &local_err); ++ if (local_err) { ++ error_propagate(errp, local_err); ++ return; ++ } ++ } + } else { ++ if (!object_property_get_bool(obj, feat->name, NULL)) { ++ return; ++ } + isar->regs[feat->reg] = deposit64(isar->regs[feat->reg], + feat->shift, feat->length, + feat->ni_value); ++ /* Auto disable the features which are dependent on current feature. */ ++ for (int i = 0; i < ARRAY_SIZE(feature_dependencies); ++i) { ++ const CPUFeatureDep *d = &feature_dependencies[i]; ++ if (strcmp(d->from.name, feat->name) != 0) { ++ continue; ++ } ++ ++ object_property_set_bool(obj, d->to.name, false, &local_err); ++ if (local_err) { ++ error_propagate(errp, local_err); ++ return; ++ } ++ } + } + } + +-- +2.27.0 + -- Gitee From b1b9df3181bac65387087aa978ba0f222fd9b1ba Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Thu, 6 Aug 2020 16:14:55 +0800 Subject: [PATCH 45/54] target/arm: introduce KVM_CAP_ARM_CPU_FEATURE Introduce KVM_CAP_ARM_CPU_FEATURE to check whether KVM supports to set CPU features in ARM. Signed-off-by: zhanghailiang Signed-off-by: Peng Liang Signed-off-by: Dongxu Sun --- ...rm-introduce-KVM_CAP_ARM_CPU_FEATURE.patch | 93 +++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 target-arm-introduce-KVM_CAP_ARM_CPU_FEATURE.patch diff --git a/target-arm-introduce-KVM_CAP_ARM_CPU_FEATURE.patch b/target-arm-introduce-KVM_CAP_ARM_CPU_FEATURE.patch new file mode 100644 index 0000000..d5bc0e8 --- /dev/null +++ b/target-arm-introduce-KVM_CAP_ARM_CPU_FEATURE.patch @@ -0,0 +1,93 @@ +From 536aa9ecc3cb25c81c2df56230c690257189d4ef Mon Sep 17 00:00:00 2001 +From: Peng Liang +Date: Thu, 6 Aug 2020 16:14:55 +0800 +Subject: [PATCH] target/arm: introduce KVM_CAP_ARM_CPU_FEATURE + +Introduce KVM_CAP_ARM_CPU_FEATURE to check whether KVM supports to set +CPU features in ARM. + +Signed-off-by: zhanghailiang +Signed-off-by: Peng Liang +Signed-off-by: Dongxu Sun +--- + linux-headers/linux/kvm.h | 2 ++ + target/arm/cpu.c | 5 +++++ + target/arm/kvm64.c | 14 ++++++++++++++ + target/arm/kvm_arm.h | 7 +++++++ + 4 files changed, 28 insertions(+) + +diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h +index bcaf66cc4d..5d8e42b8f8 100644 +--- a/linux-headers/linux/kvm.h ++++ b/linux-headers/linux/kvm.h +@@ -1113,6 +1113,8 @@ struct kvm_ppc_resize_hpt { + #define KVM_CAP_EXIT_ON_EMULATION_FAILURE 204 + #define KVM_CAP_ARM_MTE 205 + ++#define KVM_CAP_ARM_CPU_FEATURE 555 ++ + #ifdef KVM_CAP_IRQ_ROUTING + + struct kvm_irq_routing_irqchip { +diff --git a/target/arm/cpu.c b/target/arm/cpu.c +index ee09642dae..3024f4a3f5 100644 +--- a/target/arm/cpu.c ++++ b/target/arm/cpu.c +@@ -1604,6 +1604,11 @@ static void arm_cpu_set_bit_prop(Object *obj, Visitor *v, const char *name, + Error *local_err = NULL; + bool value; + ++ if (!kvm_arm_cpu_feature_supported()) { ++ warn_report("KVM doesn't support to set CPU feature in arm. " ++ "Setting to `%s` is ignored.", name); ++ return; ++ } + if (dev->realized) { + qdev_prop_set_after_realize(dev, name, errp); + return; +diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c +index 4f97e516c2..b34a87fd24 100644 +--- a/target/arm/kvm64.c ++++ b/target/arm/kvm64.c +@@ -827,6 +827,20 @@ static int kvm_arm_sve_set_vls(CPUState *cs) + return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); + } + ++bool kvm_arm_cpu_feature_supported(void) ++{ ++ static bool cpu_feature_initialized; ++ static bool cpu_feature_supported; ++ ++ if (!cpu_feature_initialized) { ++ cpu_feature_supported = kvm_check_extension(kvm_state, ++ KVM_CAP_ARM_CPU_FEATURE); ++ cpu_feature_initialized = true; ++ } ++ ++ return cpu_feature_supported; ++} ++ + #define ARM_CPU_ID_MPIDR 3, 0, 0, 0, 5 + + int kvm_arch_init_vcpu(CPUState *cs) +diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h +index f8e0e64363..82145607ec 100644 +--- a/target/arm/kvm_arm.h ++++ b/target/arm/kvm_arm.h +@@ -306,6 +306,13 @@ bool kvm_arm_pmu_supported(void); + */ + bool kvm_arm_sve_supported(void); + ++/** ++ * kvm_arm_cpu_feature_supported: ++ * ++ * Returns true if KVM can set CPU features and false otherwise. ++ */ ++bool kvm_arm_cpu_feature_supported(void); ++ + /** + * kvm_arm_get_max_vm_ipa_size: + * @ms: Machine state handle +-- +2.27.0 + -- Gitee From 4892d2c20e9b94c68d0d3477bb14442c0156b41f Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Thu, 6 Aug 2020 16:14:58 +0800 Subject: [PATCH 46/54] target/arm: Add CPU features to query-cpu-model-expansion Add CPU features to the result of query-cpu-model-expansion so that other applications (such as libvirt) can know the supported CPU features. Signed-off-by: zhanghailiang Signed-off-by: Peng Liang Signed-off-by: Dongxu Sun --- ...PU-features-to-query-cpu-model-expan.patch | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 target-arm-Add-CPU-features-to-query-cpu-model-expan.patch diff --git a/target-arm-Add-CPU-features-to-query-cpu-model-expan.patch b/target-arm-Add-CPU-features-to-query-cpu-model-expan.patch new file mode 100644 index 0000000..3bb8d6a --- /dev/null +++ b/target-arm-Add-CPU-features-to-query-cpu-model-expan.patch @@ -0,0 +1,90 @@ +From e6dd7faeea77206d7e6589cbb54ad43926457052 Mon Sep 17 00:00:00 2001 +From: Peng Liang +Date: Thu, 6 Aug 2020 16:14:58 +0800 +Subject: [PATCH] target/arm: Add CPU features to query-cpu-model-expansion + +Add CPU features to the result of query-cpu-model-expansion so that +other applications (such as libvirt) can know the supported CPU +features. + +Signed-off-by: zhanghailiang +Signed-off-by: Peng Liang +Signed-off-by: Dongxu Sun +--- + target/arm/cpu.c | 27 +++++++++++++++++++++++++++ + target/arm/cpu.h | 2 ++ + target/arm/monitor.c | 2 ++ + 3 files changed, 31 insertions(+) + +diff --git a/target/arm/cpu.c b/target/arm/cpu.c +index 3024f4a3f5..2d6a26336f 100644 +--- a/target/arm/cpu.c ++++ b/target/arm/cpu.c +@@ -25,6 +25,8 @@ + #include "qemu/module.h" + #include "qapi/error.h" + #include "qapi/visitor.h" ++#include "qapi/qmp/qdict.h" ++#include "qom/qom-qobject.h" + #include "cpu.h" + #ifdef CONFIG_TCG + #include "hw/core/tcg-cpu-ops.h" +@@ -1580,6 +1582,31 @@ static const CPUFeatureDep feature_dependencies[] = { + }, + }; + ++void arm_cpu_features_to_dict(ARMCPU *cpu, QDict *features) ++{ ++ Object *obj = OBJECT(cpu); ++ const char *name; ++ ObjectProperty *prop; ++ bool is_32bit = !arm_feature(&cpu->env, ARM_FEATURE_AARCH64); ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(cpu_features); ++i) { ++ if (is_32bit != cpu_features[i].is_32bit) { ++ continue; ++ } ++ ++ name = cpu_features[i].name; ++ prop = object_property_find(obj, name); ++ if (prop) { ++ QObject *value; ++ ++ assert(prop->get); ++ value = object_property_get_qobject(obj, name, &error_abort); ++ qdict_put_obj(features, name, value); ++ } ++ } ++} ++ + static void arm_cpu_get_bit_prop(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) + { +diff --git a/target/arm/cpu.h b/target/arm/cpu.h +index 3dda33f347..947897d5ac 100644 +--- a/target/arm/cpu.h ++++ b/target/arm/cpu.h +@@ -4398,4 +4398,6 @@ static inline bool isar_feature_any_tts2uxn(const ARMISARegisters *id) + #define cpu_isar_feature(name, cpu) \ + ({ ARMCPU *cpu_ = (cpu); isar_feature_##name(&cpu_->isar); }) + ++void arm_cpu_features_to_dict(ARMCPU *cpu, QDict *features); ++ + #endif +diff --git a/target/arm/monitor.c b/target/arm/monitor.c +index 80c64fa355..4c6f1181d9 100644 +--- a/target/arm/monitor.c ++++ b/target/arm/monitor.c +@@ -217,6 +217,8 @@ CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type, + } + } + ++ arm_cpu_features_to_dict(ARM_CPU(obj), qdict_out); ++ + if (!qdict_size(qdict_out)) { + qobject_unref(qdict_out); + } else { +-- +2.27.0 + -- Gitee From 3b1efe13022431c1013a071369a609bc06f2adc3 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Tue, 11 Aug 2020 10:28:10 +0800 Subject: [PATCH 47/54] target/arm: Add more CPU features Add i8mm, bf16, and dgh CPU features for AArch64. Signed-off-by: zhanghailiang Signed-off-by: Peng Liang Signed-off-by: Dongxu Sun --- target-arm-Add-more-CPU-features.patch | 31 ++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 target-arm-Add-more-CPU-features.patch diff --git a/target-arm-Add-more-CPU-features.patch b/target-arm-Add-more-CPU-features.patch new file mode 100644 index 0000000..4b8c01d --- /dev/null +++ b/target-arm-Add-more-CPU-features.patch @@ -0,0 +1,31 @@ +From 85d5b46d8225c5875b8b3ff68967d46bcde9a549 Mon Sep 17 00:00:00 2001 +From: Peng Liang +Date: Tue, 11 Aug 2020 10:28:10 +0800 +Subject: [PATCH] target/arm: Add more CPU features + +Add i8mm, bf16, and dgh CPU features for AArch64. + +Signed-off-by: zhanghailiang +Signed-off-by: Peng Liang +Signed-off-by: Dongxu Sun +--- + target/arm/cpu.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/target/arm/cpu.c b/target/arm/cpu.c +index 2d6a26336f..1c1647a0a8 100644 +--- a/target/arm/cpu.c ++++ b/target/arm/cpu.c +@@ -1309,6 +1309,9 @@ static struct CPUFeatureInfo cpu_features[] = { + FIELD_INFO("fhm", ID_ISAR6, FHM, false, 1, 0, true), + FIELD_INFO("sb", ID_ISAR6, SB, false, 1, 0, true), + FIELD_INFO("specres", ID_ISAR6, SPECRES, false, 1, 0, true), ++ FIELD_INFO("i8mm", ID_AA64ISAR1, I8MM, false, 1, 0, false), ++ FIELD_INFO("bf16", ID_AA64ISAR1, BF16, false, 1, 0, false), ++ FIELD_INFO("dgh", ID_AA64ISAR1, DGH, false, 1, 0, false), + + FIELD_INFO("cmaintva", ID_MMFR3, CMAINTVA, false, 1, 0, true), + FIELD_INFO("cmaintsw", ID_MMFR3, CMAINTSW, false, 1, 0, true), +-- +2.27.0 + -- Gitee From 89cd31a820ca4babf67498549d90ea770eebd228 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Mon, 7 Sep 2020 14:07:07 +0800 Subject: [PATCH 48/54] target/arm: ignore evtstrm and cpuid CPU features evtstrm and cpuid cann't be controlled by VMM: 1. evtstrm: The generic timer is configured to generate events at a frequency of approximately 100KHz. It's controlled by the linux kernel config CONFIG_ARM_ARCH_TIMER_EVTSTREAM. 2. cpuid: EL0 access to certain ID registers is available. It's always set by linux kernel after 77c97b4ee2129 ("arm64: cpufeature: Expose CPUID registers by emulation"). However, they are exposed by getauxval() and /proc/cpuinfo. Hence, let's report and ignore the CPU features if someone set them. Signed-off-by: Peng Liang Signed-off-by: Dongxu Sun --- ...gnore-evtstrm-and-cpuid-CPU-features.patch | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 target-arm-ignore-evtstrm-and-cpuid-CPU-features.patch diff --git a/target-arm-ignore-evtstrm-and-cpuid-CPU-features.patch b/target-arm-ignore-evtstrm-and-cpuid-CPU-features.patch new file mode 100644 index 0000000..edb4ea4 --- /dev/null +++ b/target-arm-ignore-evtstrm-and-cpuid-CPU-features.patch @@ -0,0 +1,67 @@ +From 4558dc5590b89b1252baea2734c2b3668566e5cb Mon Sep 17 00:00:00 2001 +From: Peng Liang +Date: Mon, 7 Sep 2020 14:07:07 +0800 +Subject: [PATCH] target/arm: ignore evtstrm and cpuid CPU features + +evtstrm and cpuid cann't be controlled by VMM: +1. evtstrm: The generic timer is configured to generate events at a + frequency of approximately 100KHz. It's controlled by the linux + kernel config CONFIG_ARM_ARCH_TIMER_EVTSTREAM. +2. cpuid: EL0 access to certain ID registers is available. It's always + set by linux kernel after 77c97b4ee2129 ("arm64: cpufeature: Expose + CPUID registers by emulation"). +However, they are exposed by getauxval() and /proc/cpuinfo. Hence, +let's report and ignore the CPU features if someone set them. + +Signed-off-by: Peng Liang +Signed-off-by: Dongxu Sun +--- + target/arm/cpu64.c | 29 ++++++++++++++++++++++++++++- + 1 file changed, 28 insertions(+), 1 deletion(-) + +diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c +index 9e5179afbe..287e7ac91c 100644 +--- a/target/arm/cpu64.c ++++ b/target/arm/cpu64.c +@@ -982,10 +982,37 @@ static gchar *aarch64_gdb_arch_name(CPUState *cs) + return g_strdup("aarch64"); + } + ++static const char *unconfigurable_feats[] = { ++ "evtstrm", ++ "cpuid", ++ NULL ++}; ++ ++static bool is_configurable_feat(const char *name) ++{ ++ int i; ++ ++ for (i = 0; unconfigurable_feats[i]; ++i) { ++ if (g_strcmp0(unconfigurable_feats[i], name) == 0) { ++ return false; ++ } ++ } ++ ++ return true; ++} ++ + static void + cpu_add_feat_as_prop(const char *typename, const char *name, const char *val) + { +- GlobalProperty *prop = g_new0(typeof(*prop), 1); ++ GlobalProperty *prop; ++ ++ if (!is_configurable_feat(name)) { ++ info_report("CPU feature '%s' is not configurable by QEMU. Ignore it.", ++ name); ++ return; ++ } ++ ++ prop = g_new0(typeof(*prop), 1); + prop->driver = typename; + prop->property = g_strdup(name); + prop->value = g_strdup(val); +-- +2.27.0 + -- Gitee From 75638a776eeaa299986617a36e144da7d9b9f93a Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Wed, 16 Sep 2020 19:40:28 +0800 Subject: [PATCH 49/54] target/arm: only set ID_PFR1_EL1.GIC for AArch32 guest Some AArch64 CPU doesn't support AArch32 mode, and the values of AArch32 registers are all 0. Hence, We'd better not to modify AArch32 registers in AArch64 mode. Signed-off-by: zhanghailiang Signed-off-by: Peng Liang Signed-off-by: Dongxu Sun --- ...set-ID_PFR1_EL1.GIC-for-AArch32-gues.patch | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 target-arm-only-set-ID_PFR1_EL1.GIC-for-AArch32-gues.patch diff --git a/target-arm-only-set-ID_PFR1_EL1.GIC-for-AArch32-gues.patch b/target-arm-only-set-ID_PFR1_EL1.GIC-for-AArch32-gues.patch new file mode 100644 index 0000000..a9be076 --- /dev/null +++ b/target-arm-only-set-ID_PFR1_EL1.GIC-for-AArch32-gues.patch @@ -0,0 +1,32 @@ +From 3371917ea92265377f87692a717397267416c4aa Mon Sep 17 00:00:00 2001 +From: Peng Liang +Date: Wed, 16 Sep 2020 19:40:28 +0800 +Subject: [PATCH] target/arm: only set ID_PFR1_EL1.GIC for AArch32 guest + +Some AArch64 CPU doesn't support AArch32 mode, and the values of AArch32 +registers are all 0. Hence, We'd better not to modify AArch32 registers +in AArch64 mode. + +Signed-off-by: zhanghailiang +Signed-off-by: Peng Liang +Signed-off-by: Dongxu Sun +--- + target/arm/helper.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/target/arm/helper.c b/target/arm/helper.c +index 79f77705c3..4c7b4cadfa 100644 +--- a/target/arm/helper.c ++++ b/target/arm/helper.c +@@ -6718,7 +6718,7 @@ static uint64_t id_pfr1_read(CPUARMState *env, const ARMCPRegInfo *ri) + ARMCPU *cpu = env_archcpu(env); + uint64_t pfr1 = cpu->isar.regs[ID_PFR1]; + +- if (env->gicv3state) { ++ if (!arm_feature(&cpu->env, ARM_FEATURE_AARCH64) && env->gicv3state) { + pfr1 |= 1 << 28; + } + return pfr1; +-- +2.27.0 + -- Gitee From 5879344ae6aa4685b1f91b579bb5d40d1a5e6aca Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Wed, 9 Dec 2020 19:35:08 +0800 Subject: [PATCH 50/54] target/arm: Fix write redundant values to kvm After modifying the value of a ID register, we'd better to try to write it to KVM so that we can known the value is acceptable for KVM. Because it may modify the registers' values of KVM, it's not suitable for other registers. (cherry-picked from a0d7a9de807639fcfcbe1fe037cb8772d459a9cf) Signed-off-by: Peng Liang Signed-off-by: Dongxu Sun --- ...rm-Fix-write-redundant-values-to-kvm.patch | 119 ++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 target-arm-Fix-write-redundant-values-to-kvm.patch diff --git a/target-arm-Fix-write-redundant-values-to-kvm.patch b/target-arm-Fix-write-redundant-values-to-kvm.patch new file mode 100644 index 0000000..db03f8b --- /dev/null +++ b/target-arm-Fix-write-redundant-values-to-kvm.patch @@ -0,0 +1,119 @@ +From 9680adfba5ca871f69a6fbd15b92571fc2a52d78 Mon Sep 17 00:00:00 2001 +From: Peng Liang +Date: Wed, 9 Dec 2020 19:35:08 +0800 +Subject: [PATCH] target/arm: Fix write redundant values to kvm + +After modifying the value of a ID register, we'd better to try to write +it to KVM so that we can known the value is acceptable for KVM. +Because it may modify the registers' values of KVM, it's not suitable +for other registers. + +(cherry-picked from a0d7a9de807639fcfcbe1fe037cb8772d459a9cf) +Signed-off-by: Peng Liang +Signed-off-by: Dongxu Sun +--- + target/arm/helper.c | 73 ++++++++++++++++++++++++++++++--------------- + 1 file changed, 49 insertions(+), 24 deletions(-) + +diff --git a/target/arm/helper.c b/target/arm/helper.c +index 4c7b4cadfa..1dd5d64d96 100644 +--- a/target/arm/helper.c ++++ b/target/arm/helper.c +@@ -134,6 +134,16 @@ static bool raw_accessors_invalid(const ARMCPRegInfo *ri) + return true; + } + ++static bool is_id_reg(const ARMCPRegInfo *ri) ++{ ++ /* ++ * (Op0, Op1, CRn, CRm, Op2) of ID registers is (3, 0, 0, crm, op2), ++ * where 1<=crm<8, 0<=op2<8. ++ */ ++ return ri->opc0 == 3 && ri->opc1 == 0 && ri->crn == 0 && ++ ri->crm > 0 && ri->crm < 8; ++} ++ + bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync) + { + /* Write the coprocessor state from cpu->env to the (index,value) list. */ +@@ -150,38 +160,53 @@ bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync) + ok = false; + continue; + } +- /* +- * (Op0, Op1, CRn, CRm, Op2) of ID registers is (3, 0, 0, crm, op2), +- * where 1<=crm<8, 0<=op2<8. Let's give ID registers a chance to +- * synchronize to kvm. +- */ +- if ((ri->type & ARM_CP_NO_RAW) && !(kvm_sync && +- ri->opc0 == 3 && ri->opc1 == 0 && ri->crn == 0 && ri->crm > 0)) { ++ if ((ri->type & ARM_CP_NO_RAW) && !(kvm_sync && is_id_reg(ri))) { + continue; + } + + newval = read_raw_cp_reg(&cpu->env, ri); + if (kvm_sync) { +- /* Only sync if we can sync to KVM successfully. */ +- uint64_t oldval; +- uint64_t kvmval; ++ if (is_id_reg(ri)) { ++ /* Only sync if we can sync to KVM successfully. */ ++ uint64_t oldval; ++ uint64_t kvmval; + +- if (kvm_arm_get_one_reg(cpu, cpu->cpreg_indexes[i], &oldval)) { +- continue; +- } +- if (oldval == newval) { +- continue; +- } ++ if (kvm_arm_get_one_reg(cpu, cpu->cpreg_indexes[i], &oldval)) { ++ continue; ++ } ++ if (oldval == newval) { ++ continue; ++ } + +- if (kvm_arm_set_one_reg(cpu, cpu->cpreg_indexes[i], &newval)) { +- continue; +- } +- if (kvm_arm_get_one_reg(cpu, cpu->cpreg_indexes[i], &kvmval) || +- kvmval != newval) { +- continue; +- } ++ if (kvm_arm_set_one_reg(cpu, cpu->cpreg_indexes[i], &newval)) { ++ continue; ++ } ++ if (kvm_arm_get_one_reg(cpu, cpu->cpreg_indexes[i], &kvmval) || ++ kvmval != newval) { ++ continue; ++ } ++ ++ kvm_arm_set_one_reg(cpu, cpu->cpreg_indexes[i], &oldval); ++ } else { ++ /* ++ * Only sync if the previous list->cpustate sync succeeded. ++ * Rather than tracking the success/failure state for every ++ * item in the list, we just recheck "does the raw write we must ++ * have made in write_list_to_cpustate() read back OK" here. ++ */ ++ uint64_t oldval = cpu->cpreg_values[i]; ++ ++ if (oldval == newval) { ++ continue; ++ } + +- kvm_arm_set_one_reg(cpu, cpu->cpreg_indexes[i], &oldval); ++ write_raw_cp_reg(&cpu->env, ri, oldval); ++ if (read_raw_cp_reg(&cpu->env, ri) != oldval) { ++ continue; ++ } ++ ++ write_raw_cp_reg(&cpu->env, ri, newval); ++ } + } + cpu->cpreg_values[i] = newval; + } +-- +2.27.0 + -- Gitee From c6ae5fb97d790b9e3f71dcaeed0fdfe1b5e69b8a Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Mon, 21 Sep 2020 22:14:20 +0800 Subject: [PATCH 51/54] target/arm: clear EL2 and EL3 only when kvm is not enabled When has_el2 and has_el3 are disabled, which is the default value for virt machine, QEMU will clear the corresponding field in ID_PFR1_EL1 and ID_AA64PFR0_EL1 to not expose EL3 and EL2 to guest. Because KVM doesn't support to emulate ID registers in AArch64 before, it will not take effect. Hence, clear EL2 and EL3 only when kvm is not enabled for backwards compatibility. Signed-off-by: Peng Liang Signed-off-by: Dongxu Sun --- ...-EL2-and-EL3-only-when-kvm-is-not-en.patch | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 target-arm-clear-EL2-and-EL3-only-when-kvm-is-not-en.patch diff --git a/target-arm-clear-EL2-and-EL3-only-when-kvm-is-not-en.patch b/target-arm-clear-EL2-and-EL3-only-when-kvm-is-not-en.patch new file mode 100644 index 0000000..a8d5ac0 --- /dev/null +++ b/target-arm-clear-EL2-and-EL3-only-when-kvm-is-not-en.patch @@ -0,0 +1,43 @@ +From 20bd52038a960e0c959af38a5d3d7a6601db8e8b Mon Sep 17 00:00:00 2001 +From: Peng Liang +Date: Mon, 21 Sep 2020 22:14:20 +0800 +Subject: [PATCH] target/arm: clear EL2 and EL3 only when kvm is not enabled + +When has_el2 and has_el3 are disabled, which is the default value for +virt machine, QEMU will clear the corresponding field in ID_PFR1_EL1 and +ID_AA64PFR0_EL1 to not expose EL3 and EL2 to guest. Because KVM doesn't +support to emulate ID registers in AArch64 before, it will not take +effect. Hence, clear EL2 and EL3 only when kvm is not enabled for +backwards compatibility. + +Signed-off-by: Peng Liang +Signed-off-by: Dongxu Sun +--- + target/arm/cpu.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/target/arm/cpu.c b/target/arm/cpu.c +index 1c1647a0a8..65163f5135 100644 +--- a/target/arm/cpu.c ++++ b/target/arm/cpu.c +@@ -2283,7 +2283,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) + } + } + +- if (!arm_feature(env, ARM_FEATURE_M) && !cpu->has_el3) { ++ if (!arm_feature(env, ARM_FEATURE_M) && !cpu->has_el3 && !kvm_enabled()) { + /* If the has_el3 CPU property is disabled then we need to disable the + * feature. + */ +@@ -2324,7 +2324,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) + cpu->pmceid1 = 0; + } + +- if (!arm_feature(env, ARM_FEATURE_EL2)) { ++ if (!arm_feature(env, ARM_FEATURE_EL2) && !kvm_enabled()) { + /* Disable the hypervisor feature bits in the processor feature + * registers if we don't have EL2. These are id_pfr1[15:12] and + * id_aa64pfr0_el1[11:8]. +-- +2.27.0 + -- Gitee From e3fb0ed2e66a8544b57a87c874423a75b4515f06 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Sat, 19 Sep 2020 09:04:45 +0800 Subject: [PATCH 52/54] target/arm: Update the ID registers of Kunpeng-920 The values of some ID registers in Kunpeng-920 are not exactly correct. Let's update them. The values are read from Kunpeng-920 by calling read_sysreg_s. Signed-off-by: Peng Liang Signed-off-by: Dongxu Sun --- ...date-the-ID-registers-of-Kunpeng-920.patch | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 target-arm-Update-the-ID-registers-of-Kunpeng-920.patch diff --git a/target-arm-Update-the-ID-registers-of-Kunpeng-920.patch b/target-arm-Update-the-ID-registers-of-Kunpeng-920.patch new file mode 100644 index 0000000..b632a31 --- /dev/null +++ b/target-arm-Update-the-ID-registers-of-Kunpeng-920.patch @@ -0,0 +1,58 @@ +From e2cb8b57278357c0a42cf7722b8c28b6f8d7585c Mon Sep 17 00:00:00 2001 +From: Peng Liang +Date: Sat, 19 Sep 2020 09:04:45 +0800 +Subject: [PATCH] target/arm: Update the ID registers of Kunpeng-920 + +The values of some ID registers in Kunpeng-920 are not exactly correct. +Let's update them. The values are read from Kunpeng-920 by calling +read_sysreg_s. + +Signed-off-by: Peng Liang +Signed-off-by: Dongxu Sun +--- + target/arm/cpu64.c | 27 +++++++++++++++++++++++++-- + 1 file changed, 25 insertions(+), 2 deletions(-) + +diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c +index 287e7ac91c..3ec788fc29 100644 +--- a/target/arm/cpu64.c ++++ b/target/arm/cpu64.c +@@ -262,10 +262,33 @@ static void aarch64_kunpeng_920_initfn(Object *obj) + + cpu->midr = 0x480fd010; + cpu->ctr = 0x84448004; +- cpu->isar.regs[ID_AA64PFR0] = 0x11001111; ++ cpu->isar.regs[ID_ISAR0] = 0; ++ cpu->isar.regs[ID_ISAR1] = 0; ++ cpu->isar.regs[ID_ISAR2] = 0; ++ cpu->isar.regs[ID_ISAR3] = 0; ++ cpu->isar.regs[ID_ISAR4] = 0; ++ cpu->isar.regs[ID_ISAR5] = 0; ++ cpu->isar.regs[ID_MMFR0] = 0; ++ cpu->isar.regs[ID_MMFR1] = 0; ++ cpu->isar.regs[ID_MMFR2] = 0; ++ cpu->isar.regs[ID_MMFR3] = 0; ++ cpu->isar.regs[ID_MMFR4] = 0; ++ cpu->isar.regs[MVFR0] = 0; ++ cpu->isar.regs[MVFR1] = 0; ++ cpu->isar.regs[MVFR2] = 0; ++ cpu->isar.regs[ID_DFR0] = 0; ++ cpu->isar.regs[MVFR2] = 0; ++ cpu->isar.regs[MVFR2] = 0; ++ cpu->isar.regs[MVFR2] = 0; ++ cpu->isar.regs[ID_PFR0] = 0; ++ cpu->isar.regs[ID_PFR1] = 0; ++ cpu->isar.regs[ID_AA64PFR0] = 0x0000010011111111; + cpu->isar.regs[ID_AA64DFR0] = 0x110305408; +- cpu->isar.regs[ID_AA64ISAR0] = 0x10211120; ++ cpu->isar.regs[ID_AA64ISAR0] = 0x0001100010211120; ++ cpu->isar.regs[ID_AA64ISAR1] = 0x00011001; + cpu->isar.regs[ID_AA64MMFR0] = 0x101125; ++ cpu->isar.regs[ID_AA64MMFR1] = 0x10211122; ++ cpu->isar.regs[ID_AA64MMFR2] = 0x00001011; + } + + void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp) +-- +2.27.0 + -- Gitee From c8f41b40588c7066d37a72a6aecfef6de2982669 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Fri, 11 Feb 2022 16:42:44 +0800 Subject: [PATCH 53/54] =?UTF-8?q?spec:=20Update=20patch=20and=20changelog?= =?UTF-8?q?=20with=20!240=20=E3=80=906.2.0=E3=80=91CPU=20ID=20=E5=91=88?= =?UTF-8?q?=E7=8E=B0=E8=A1=A5=E4=B8=81=E5=9B=9E=E5=90=88=20=20!240?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit target/arm: convert isar regs to array target/arm: parse cpu feature related options target/arm: register CPU features for property target/arm: Allow ID registers to synchronize to KVM target/arm: introduce CPU feature dependency mechanism target/arm: introduce KVM_CAP_ARM_CPU_FEATURE target/arm: Add CPU features to query-cpu-model-expansion target/arm: Add more CPU features target/arm: ignore evtstrm and cpuid CPU features target/arm: only set ID_PFR1_EL1.GIC for AArch32 guest target/arm: Fix write redundant values to kvm target/arm: clear EL2 and EL3 only when kvm is not enabled target/arm: Update the ID registers of Kunpeng-920 Signed-off-by: Chen Qun --- qemu.spec | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/qemu.spec b/qemu.spec index 255be52..6174a1a 100644 --- a/qemu.spec +++ b/qemu.spec @@ -68,6 +68,19 @@ Patch0055: block-bugfix-Don-t-pause-vm-when-NOSPACE-EIO-happene.patch Patch0056: scsi-bugfix-fix-division-by-zero.patch Patch0057: i386-cache-passthrough-Update-Intel-CPUID4.EAX-25-14.patch Patch0058: i386-cache-passthrough-Update-AMD-8000_001D.EAX-25-1.patch +Patch0059: target-arm-convert-isar-regs-to-array.patch +Patch0060: target-arm-parse-cpu-feature-related-options.patch +Patch0061: target-arm-register-CPU-features-for-property.patch +Patch0062: target-arm-Allow-ID-registers-to-synchronize-to-KVM.patch +Patch0063: target-arm-introduce-CPU-feature-dependency-mechanis.patch +Patch0064: target-arm-introduce-KVM_CAP_ARM_CPU_FEATURE.patch +Patch0065: target-arm-Add-CPU-features-to-query-cpu-model-expan.patch +Patch0066: target-arm-Add-more-CPU-features.patch +Patch0067: target-arm-ignore-evtstrm-and-cpuid-CPU-features.patch +Patch0068: target-arm-only-set-ID_PFR1_EL1.GIC-for-AArch32-gues.patch +Patch0069: target-arm-Fix-write-redundant-values-to-kvm.patch +Patch0070: target-arm-clear-EL2-and-EL3-only-when-kvm-is-not-en.patch +Patch0071: target-arm-Update-the-ID-registers-of-Kunpeng-920.patch BuildRequires: flex BuildRequires: gcc @@ -510,6 +523,21 @@ getent passwd qemu >/dev/null || \ %endif %changelog +* Fri Feb 11 2022 Chen Qun +- target/arm: convert isar regs to array +- target/arm: parse cpu feature related options +- target/arm: register CPU features for property +- target/arm: Allow ID registers to synchronize to KVM +- target/arm: introduce CPU feature dependency mechanism +- target/arm: introduce KVM_CAP_ARM_CPU_FEATURE +- target/arm: Add CPU features to query-cpu-model-expansion +- target/arm: Add more CPU features +- target/arm: ignore evtstrm and cpuid CPU features +- target/arm: only set ID_PFR1_EL1.GIC for AArch32 guest +- target/arm: Fix write redundant values to kvm +- target/arm: clear EL2 and EL3 only when kvm is not enabled +- target/arm: Update the ID registers of Kunpeng-920 + * Fri Feb 11 2022 Chen Qun - i386: cache passthrough: Update Intel CPUID4.EAX[25:14] based on vCPU topo - i386: cache passthrough: Update AMD 8000_001D.EAX[25:14] based on vCPU topo -- Gitee From 8107bf42a47ed24fa3e2d828f80b92f7d68f96d5 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Fri, 11 Feb 2022 16:42:51 +0800 Subject: [PATCH 54/54] spec: Update release version with !232 !233 !241 !240 increase release verison by one Signed-off-by: Chen Qun --- qemu.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qemu.spec b/qemu.spec index 6174a1a..909e699 100644 --- a/qemu.spec +++ b/qemu.spec @@ -1,6 +1,6 @@ Name: qemu Version: 6.2.0 -Release: 5 +Release: 6 Epoch: 2 Summary: QEMU is a generic and open source machine emulator and virtualizer License: GPLv2 and BSD and MIT and CC-BY-SA-4.0 -- Gitee