From 98d4783b7c47e540edeb8db60bb542243b04c547 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Wed, 9 Feb 2022 10:42:33 +0800 Subject: [PATCH 01/38] 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 464c10bc379d9148d05bdcae03a0d703163ddb57 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Wed, 9 Feb 2022 10:48:58 +0800 Subject: [PATCH 02/38] 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 1d3520429a075d1abf77b2347399dafa48dadd69 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Wed, 9 Feb 2022 10:55:08 +0800 Subject: [PATCH 03/38] 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 d1627e702f751202d4c2f5e90356b431b245654e Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Wed, 9 Feb 2022 11:10:42 +0800 Subject: [PATCH 04/38] 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 32c1488d40a5c4c5a1a8dbdb5ec44495088e4d9d Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Wed, 9 Feb 2022 11:18:21 +0800 Subject: [PATCH 05/38] 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 c26132dbeeff6d93927482b919e5e9c1f72d99f4 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Wed, 9 Feb 2022 11:29:15 +0800 Subject: [PATCH 06/38] 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 92557f0202505afcd10c4c4068691aeda923293e Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Wed, 9 Feb 2022 11:42:47 +0800 Subject: [PATCH 07/38] 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 d9f94e4ef952592932b7de5c02526cda88162e90 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Wed, 9 Feb 2022 11:51:43 +0800 Subject: [PATCH 08/38] 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 98cb422b0c4e3d5afd75ebb8044d6e4848474f00 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Wed, 9 Feb 2022 16:10:22 +0800 Subject: [PATCH 09/38] 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 52e02413d09e0003088bcea82c453e14ece0b11b Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Wed, 9 Feb 2022 16:34:05 +0800 Subject: [PATCH 10/38] 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 e07fca29185a1638c24a012ee72694dbcf9f9da8 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Fri, 11 Feb 2022 21:01:19 +0800 Subject: [PATCH 11/38] =?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 70eac66..f6a2c10 100644 --- a/qemu.spec +++ b/qemu.spec @@ -47,6 +47,16 @@ Patch0034: Currently-while-kvm-and-qemu-can-not-handle-some-kvm.patch Patch0035: cpu-features-fix-bug-for-memory-leakage.patch Patch0036: monitor-qmp-drop-inflight-rsp-if-qmp-client-broken.patch Patch0037: oslib-posix-optimise-vm-startup-time-for-1G-hugepage.patch +Patch0038: nbd-server.c-fix-invalid-read-after-client-was-alrea.patch +Patch0039: qemu-nbd-make-native-as-the-default-aio-mode.patch +Patch0040: qemu-nbd-set-timeout-to-qemu-nbd-socket.patch +Patch0041: qemu-pr-fixed-ioctl-failed-for-multipath-disk.patch +Patch0042: block-enable-cache-mode-of-empty-cdrom.patch +Patch0043: block-disallow-block-jobs-when-there-is-a-BDRV_O_INA.patch +Patch0044: scsi-cdrom-Fix-crash-after-remote-cdrom-detached.patch +Patch0045: block-bugfix-disable-process-AIO-when-attach-scsi-di.patch +Patch0046: block-bugfix-Don-t-pause-vm-when-NOSPACE-EIO-happene.patch +Patch0047: scsi-bugfix-fix-division-by-zero.patch BuildRequires: flex BuildRequires: gcc @@ -491,6 +501,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 imxcc - migration: skip cache_drop for bios bootloader and - ps2: fix oob in ps2 kbd -- Gitee From 05843bf6066368f903a48254f4d2f2f398fbec61 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Thu, 10 Feb 2022 19:43:55 +0800 Subject: [PATCH 12/38] 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 1600e7517db126e95e32b484ab1140d657ee8448 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Thu, 10 Feb 2022 20:06:01 +0800 Subject: [PATCH 13/38] 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 11e6dcffc34cb9bdefa9092370bd63e7fe0cf362 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Fri, 11 Feb 2022 21:01:22 +0800 Subject: [PATCH 14/38] =?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 f6a2c10..3c42ddb 100644 --- a/qemu.spec +++ b/qemu.spec @@ -57,6 +57,8 @@ Patch0044: scsi-cdrom-Fix-crash-after-remote-cdrom-detached.patch Patch0045: block-bugfix-disable-process-AIO-when-attach-scsi-di.patch Patch0046: block-bugfix-Don-t-pause-vm-when-NOSPACE-EIO-happene.patch Patch0047: scsi-bugfix-fix-division-by-zero.patch +Patch0048: i386-cache-passthrough-Update-Intel-CPUID4.EAX-25-14.patch +Patch0049: i386-cache-passthrough-Update-AMD-8000_001D.EAX-25-1.patch BuildRequires: flex BuildRequires: gcc @@ -501,6 +503,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 6b5d2bb96b1472455eea9c7d38722858e95e7f12 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Thu, 6 Aug 2020 16:14:25 +0800 Subject: [PATCH 15/38] 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 94c2a36e189c3605a5e67ae06b80def17dc37004 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Thu, 6 Aug 2020 16:14:35 +0800 Subject: [PATCH 16/38] 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 c0a3d4910f92d5b24df9220aa815ded073f80c98 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Thu, 6 Aug 2020 16:14:37 +0800 Subject: [PATCH 17/38] 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 2e5660962b4a89ca2682a30f0457af6ed61e2d21 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Thu, 6 Aug 2020 16:14:40 +0800 Subject: [PATCH 18/38] 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 5b74b1c2576629c757acef7dd5d3b8e3c856810f Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Thu, 6 Aug 2020 16:14:46 +0800 Subject: [PATCH 19/38] 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 c55bf1dfa8e442b1bc7029f21e0c3f46cf6e8824 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Thu, 6 Aug 2020 16:14:55 +0800 Subject: [PATCH 20/38] 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 c009675d45c750c0fd730763ee8fcce996a84b12 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Thu, 6 Aug 2020 16:14:58 +0800 Subject: [PATCH 21/38] 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 43f091caeb4c0c2e4dcb450d9f3030afbe05ce12 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Tue, 11 Aug 2020 10:28:10 +0800 Subject: [PATCH 22/38] 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 039b44f7b4be0f8a466a8b242374f21c48477397 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Mon, 7 Sep 2020 14:07:07 +0800 Subject: [PATCH 23/38] 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 6ac38c4e0f6062d21bab87fe70a20dc337f969ae Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Wed, 16 Sep 2020 19:40:28 +0800 Subject: [PATCH 24/38] 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 34cd14cf0ad683aba3288eff52f5677cb5510f57 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Wed, 9 Dec 2020 19:35:08 +0800 Subject: [PATCH 25/38] 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 9946bfa1ba16e4281e3065d8ec0f62eecc270b39 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Mon, 21 Sep 2020 22:14:20 +0800 Subject: [PATCH 26/38] 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 eefb44edacefa35aff650cb2f8d681f237b694df Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Sat, 19 Sep 2020 09:04:45 +0800 Subject: [PATCH 27/38] 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 37cb1224cb94a6076b01086888dd28a00d61ed2a Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Fri, 11 Feb 2022 21:01:26 +0800 Subject: [PATCH 28/38] =?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 3c42ddb..d698ab2 100644 --- a/qemu.spec +++ b/qemu.spec @@ -59,6 +59,19 @@ Patch0046: block-bugfix-Don-t-pause-vm-when-NOSPACE-EIO-happene.patch Patch0047: scsi-bugfix-fix-division-by-zero.patch Patch0048: i386-cache-passthrough-Update-Intel-CPUID4.EAX-25-14.patch Patch0049: i386-cache-passthrough-Update-AMD-8000_001D.EAX-25-1.patch +Patch0050: target-arm-convert-isar-regs-to-array.patch +Patch0051: target-arm-parse-cpu-feature-related-options.patch +Patch0052: target-arm-register-CPU-features-for-property.patch +Patch0053: target-arm-Allow-ID-registers-to-synchronize-to-KVM.patch +Patch0054: target-arm-introduce-CPU-feature-dependency-mechanis.patch +Patch0055: target-arm-introduce-KVM_CAP_ARM_CPU_FEATURE.patch +Patch0056: target-arm-Add-CPU-features-to-query-cpu-model-expan.patch +Patch0057: target-arm-Add-more-CPU-features.patch +Patch0058: target-arm-ignore-evtstrm-and-cpuid-CPU-features.patch +Patch0059: target-arm-only-set-ID_PFR1_EL1.GIC-for-AArch32-gues.patch +Patch0060: target-arm-Fix-write-redundant-values-to-kvm.patch +Patch0061: target-arm-clear-EL2-and-EL3-only-when-kvm-is-not-en.patch +Patch0062: target-arm-Update-the-ID-registers-of-Kunpeng-920.patch BuildRequires: flex BuildRequires: gcc @@ -503,6 +516,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 60fb65f37fba701170e663365aeac3309a137e08 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Thu, 10 Feb 2022 11:11:37 +0800 Subject: [PATCH 29/38] freeclock: add qmp command to get time offset of vm in seconds When setting the system time in VM, a RTC_CHANGE event will be reported. However, if libvirt is restarted while the event is be reporting, the event will be lost and we will get the old time (not the time we set in VM) after rebooting the VM. We save the delta time in QEMU and add a rtc-date-diff qmp to get the delta time so that libvirt can get the latest time in VM according to the qmp after libvirt is restarted. Signed-off-by: Peng Liang Signed-off-by: zhangxinhao --- ...p-command-to-get-time-offset-of-vm-i.patch | 125 ++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 freeclock-add-qmp-command-to-get-time-offset-of-vm-i.patch diff --git a/freeclock-add-qmp-command-to-get-time-offset-of-vm-i.patch b/freeclock-add-qmp-command-to-get-time-offset-of-vm-i.patch new file mode 100644 index 0000000..e16b514 --- /dev/null +++ b/freeclock-add-qmp-command-to-get-time-offset-of-vm-i.patch @@ -0,0 +1,125 @@ +From 124d427a1fdae2d1eeed433093ec4ab78b81237e Mon Sep 17 00:00:00 2001 +From: "shenghualong@huawei.com" +Date: Thu, 10 Feb 2022 11:11:37 +0800 +Subject: [PATCH] freeclock: add qmp command to get time offset of vm in + seconds + +When setting the system time in VM, a RTC_CHANGE event will be reported. +However, if libvirt is restarted while the event is be reporting, the +event will be lost and we will get the old time (not the time we set in +VM) after rebooting the VM. + +We save the delta time in QEMU and add a rtc-date-diff qmp to get the +delta time so that libvirt can get the latest time in VM according to +the qmp after libvirt is restarted. + +Signed-off-by: Peng Liang +Signed-off-by: zhangxinhao +--- + include/qemu-common.h | 4 +++- + monitor/qmp-cmds.c | 5 +++++ + qapi/misc.json | 9 +++++++++ + qapi/pragma.json | 3 ++- + softmmu/rtc.c | 13 ++++++++++++- + 5 files changed, 31 insertions(+), 3 deletions(-) + +diff --git a/include/qemu-common.h b/include/qemu-common.h +index 73bcf763ed..9ed8832152 100644 +--- a/include/qemu-common.h ++++ b/include/qemu-common.h +@@ -27,7 +27,9 @@ int qemu_main(int argc, char **argv, char **envp); + #endif + + void qemu_get_timedate(struct tm *tm, int offset); +-int qemu_timedate_diff(struct tm *tm); ++time_t qemu_timedate_diff(struct tm *tm); ++time_t get_rtc_date_diff(void); ++void set_rtc_date_diff(time_t diff); + + void *qemu_oom_check(void *ptr); + +diff --git a/monitor/qmp-cmds.c b/monitor/qmp-cmds.c +index 343353e27a..98868cee03 100644 +--- a/monitor/qmp-cmds.c ++++ b/monitor/qmp-cmds.c +@@ -466,3 +466,8 @@ HumanReadableText *qmp_x_query_irq(Error **errp) + + return human_readable_text_from_str(buf); + } ++ ++int64_t qmp_query_rtc_date_diff(Error **errp) ++{ ++ return get_rtc_date_diff(); ++} +diff --git a/qapi/misc.json b/qapi/misc.json +index 358548abe1..5b6d653682 100644 +--- a/qapi/misc.json ++++ b/qapi/misc.json +@@ -527,3 +527,12 @@ + 'data': { '*option': 'str' }, + 'returns': ['CommandLineOptionInfo'], + 'allow-preconfig': true } ++ ++## ++# @query-rtc-date-diff: ++# ++# get vm's time offset ++# ++# Since: 2.8 ++## ++{ 'command': 'query-rtc-date-diff', 'returns': 'int64' } +diff --git a/qapi/pragma.json b/qapi/pragma.json +index 3bc0335d1f..b37f6de445 100644 +--- a/qapi/pragma.json ++++ b/qapi/pragma.json +@@ -26,7 +26,8 @@ + 'qom-get', + 'query-tpm-models', + 'query-tpm-types', +- 'ringbuf-read' ], ++ 'ringbuf-read', ++ 'query-rtc-date-diff' ], + # Externally visible types whose member names may use uppercase + 'member-name-exceptions': [ # visible in: + 'ACPISlotType', # query-acpi-ospm-status +diff --git a/softmmu/rtc.c b/softmmu/rtc.c +index 5632684fc9..57bb8bba7c 100644 +--- a/softmmu/rtc.c ++++ b/softmmu/rtc.c +@@ -43,6 +43,7 @@ static time_t rtc_ref_start_datetime; + static int rtc_realtime_clock_offset; /* used only with QEMU_CLOCK_REALTIME */ + static int rtc_host_datetime_offset = -1; /* valid & used only with + RTC_BASE_DATETIME */ ++static time_t rtc_date_diff = 0; + QEMUClockType rtc_clock; + /***********************************************************/ + /* RTC reference time/date access */ +@@ -84,7 +85,7 @@ void qemu_get_timedate(struct tm *tm, int offset) + } + } + +-int qemu_timedate_diff(struct tm *tm) ++time_t qemu_timedate_diff(struct tm *tm) + { + time_t seconds; + +@@ -107,6 +108,16 @@ int qemu_timedate_diff(struct tm *tm) + return seconds - qemu_ref_timedate(QEMU_CLOCK_HOST); + } + ++time_t get_rtc_date_diff(void) ++{ ++ return rtc_date_diff; ++} ++ ++void set_rtc_date_diff(time_t diff) ++{ ++ rtc_date_diff = diff; ++} ++ + static void configure_rtc_base_datetime(const char *startdate) + { + time_t rtc_start_datetime; +-- +2.27.0 + -- Gitee From 791c80f032b87f3a7922aae9d7457996aa1e5049 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Thu, 10 Feb 2022 14:23:28 +0800 Subject: [PATCH 30/38] freeclock: set rtc_date_diff for arm Set rtc_date_diff in pl031. Signed-off-by: Peng Liang Signed-off-by: zhangxinhao --- freeclock-set-rtc_date_diff-for-arm.patch | 30 +++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 freeclock-set-rtc_date_diff-for-arm.patch diff --git a/freeclock-set-rtc_date_diff-for-arm.patch b/freeclock-set-rtc_date_diff-for-arm.patch new file mode 100644 index 0000000..6156fe1 --- /dev/null +++ b/freeclock-set-rtc_date_diff-for-arm.patch @@ -0,0 +1,30 @@ +From 1e6bae1d13302594b6e63d88e8627fa477966cf4 Mon Sep 17 00:00:00 2001 +From: "shenghualong@huawei.com" +Date: Thu, 10 Feb 2022 14:23:28 +0800 +Subject: [PATCH] freeclock: set rtc_date_diff for arm + +Set rtc_date_diff in pl031. + +Signed-off-by: Peng Liang +Signed-off-by: zhangxinhao +--- + hw/rtc/pl031.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/hw/rtc/pl031.c b/hw/rtc/pl031.c +index e7ced90b02..da8b061e91 100644 +--- a/hw/rtc/pl031.c ++++ b/hw/rtc/pl031.c +@@ -143,7 +143,8 @@ static void pl031_write(void * opaque, hwaddr offset, + s->tick_offset += value - pl031_get_count(s); + + qemu_get_timedate(&tm, s->tick_offset); +- qapi_event_send_rtc_change(qemu_timedate_diff(&tm)); ++ set_rtc_date_diff(qemu_timedate_diff(&tm)); ++ qapi_event_send_rtc_change(get_rtc_date_diff()); + + pl031_set_alarm(s); + break; +-- +2.27.0 + -- Gitee From 5e97b751f39f3d928de768e772d387db1227e2cd Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Thu, 10 Feb 2022 14:25:30 +0800 Subject: [PATCH 31/38] freeclock: set rtc_date_diff for X86 Set rtc_date_diff in mc146818rtc. Signed-off-by: l00500761 Signed-off-by: zhangxinhao --- freeclock-set-rtc_date_diff-for-X86.patch | 30 +++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 freeclock-set-rtc_date_diff-for-X86.patch diff --git a/freeclock-set-rtc_date_diff-for-X86.patch b/freeclock-set-rtc_date_diff-for-X86.patch new file mode 100644 index 0000000..bb81b33 --- /dev/null +++ b/freeclock-set-rtc_date_diff-for-X86.patch @@ -0,0 +1,30 @@ +From 3d0846d864384be3d08a54ca6e2ce247a5cee952 Mon Sep 17 00:00:00 2001 +From: l00500761 +Date: Thu, 10 Feb 2022 14:25:30 +0800 +Subject: [PATCH] freeclock: set rtc_date_diff for X86 + +Set rtc_date_diff in mc146818rtc. + +Signed-off-by: l00500761 +Signed-off-by: zhangxinhao +--- + hw/rtc/mc146818rtc.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/hw/rtc/mc146818rtc.c b/hw/rtc/mc146818rtc.c +index 4fbafddb22..af1df9aaeb 100644 +--- a/hw/rtc/mc146818rtc.c ++++ b/hw/rtc/mc146818rtc.c +@@ -616,7 +616,8 @@ static void rtc_set_time(RTCState *s) + s->base_rtc = mktimegm(&tm); + s->last_update = qemu_clock_get_ns(rtc_clock); + +- qapi_event_send_rtc_change(qemu_timedate_diff(&tm)); ++ set_rtc_date_diff(qemu_timedate_diff(&tm)); ++ qapi_event_send_rtc_change(get_rtc_date_diff()); + } + + static void rtc_set_cmos(RTCState *s, const struct tm *tm) +-- +2.27.0 + -- Gitee From b6d6b9e22bc91b18170a63a4ba59a41443b51b14 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Fri, 11 Feb 2022 21:01:30 +0800 Subject: [PATCH 32/38] =?UTF-8?q?spec:=20Update=20patch=20and=20changelog?= =?UTF-8?q?=20with=20!237=20=E3=80=906.2.0=E3=80=91=E8=87=AA=E7=94=B1?= =?UTF-8?q?=E6=97=B6=E9=92=9F=E8=A1=A5=E4=B8=81=E5=9B=9E=E5=90=88=20=20!23?= =?UTF-8?q?7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit freeclock: add qmp command to get time offset of vm in seconds freeclock: set rtc_date_diff for arm freeclock: set rtc_date_diff for X86 Signed-off-by: Chen Qun --- qemu.spec | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/qemu.spec b/qemu.spec index d698ab2..be0430f 100644 --- a/qemu.spec +++ b/qemu.spec @@ -72,6 +72,9 @@ Patch0059: target-arm-only-set-ID_PFR1_EL1.GIC-for-AArch32-gues.patch Patch0060: target-arm-Fix-write-redundant-values-to-kvm.patch Patch0061: target-arm-clear-EL2-and-EL3-only-when-kvm-is-not-en.patch Patch0062: target-arm-Update-the-ID-registers-of-Kunpeng-920.patch +Patch0063: freeclock-add-qmp-command-to-get-time-offset-of-vm-i.patch +Patch0064: freeclock-set-rtc_date_diff-for-arm.patch +Patch0065: freeclock-set-rtc_date_diff-for-X86.patch BuildRequires: flex BuildRequires: gcc @@ -516,6 +519,11 @@ getent passwd qemu >/dev/null || \ %endif %changelog +* Fri Feb 11 2022 Chen Qun +- freeclock: add qmp command to get time offset of vm in seconds +- freeclock: set rtc_date_diff for arm +- freeclock: set rtc_date_diff for X86 + * Fri Feb 11 2022 Chen Qun - target/arm: convert isar regs to array - target/arm: parse cpu feature related options -- Gitee From 2749ab614385e13006eb8b840bd995ea864f4557 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Tue, 8 Feb 2022 22:43:59 -0500 Subject: [PATCH 33/38] hw/usb: reduce the vpcu cost of UHCI when VNC disconnect Reduce the vpcu cost by set a lower FRAME_TIMER_FREQ of the UHCI when VNC client disconnected. This can reduce about 3% cost of vcpu thread. Signed-off-by: eillon --- ...e-vpcu-cost-of-UHCI-when-VNC-disconn.patch | 459 ++++++++++++++++++ 1 file changed, 459 insertions(+) create mode 100644 hw-usb-reduce-the-vpcu-cost-of-UHCI-when-VNC-disconn.patch diff --git a/hw-usb-reduce-the-vpcu-cost-of-UHCI-when-VNC-disconn.patch b/hw-usb-reduce-the-vpcu-cost-of-UHCI-when-VNC-disconn.patch new file mode 100644 index 0000000..ef734a6 --- /dev/null +++ b/hw-usb-reduce-the-vpcu-cost-of-UHCI-when-VNC-disconn.patch @@ -0,0 +1,459 @@ +From 93f01916f0c1e11f38edb8ccc4118c940d9c089f Mon Sep 17 00:00:00 2001 +From: eillon +Date: Tue, 8 Feb 2022 22:43:59 -0500 +Subject: [PATCH] hw/usb: reduce the vpcu cost of UHCI when VNC disconnect + +Reduce the vpcu cost by set a lower FRAME_TIMER_FREQ of the UHCI +when VNC client disconnected. This can reduce about 3% cost of +vcpu thread. + +Signed-off-by: eillon +--- + hw/usb/core.c | 5 ++-- + hw/usb/desc.c | 7 +++-- + hw/usb/dev-hid.c | 2 +- + hw/usb/hcd-uhci.c | 63 ++++++++++++++++++++++++++++++++++------ + hw/usb/hcd-uhci.h | 1 + + hw/usb/host-libusb.c | 32 ++++++++++++++++++++ + include/hw/usb.h | 1 + + include/qemu/timer.h | 28 ++++++++++++++++++ + ui/vnc.c | 4 +++ + util/qemu-timer.c | 69 ++++++++++++++++++++++++++++++++++++++++++++ + 10 files changed, 197 insertions(+), 15 deletions(-) + +diff --git a/hw/usb/core.c b/hw/usb/core.c +index 975f76250a..51b36126ca 100644 +--- a/hw/usb/core.c ++++ b/hw/usb/core.c +@@ -87,7 +87,7 @@ void usb_device_reset(USBDevice *dev) + return; + } + usb_device_handle_reset(dev); +- dev->remote_wakeup = 0; ++ dev->remote_wakeup &= ~USB_DEVICE_REMOTE_WAKEUP; + dev->addr = 0; + dev->state = USB_STATE_DEFAULT; + } +@@ -105,7 +105,8 @@ void usb_wakeup(USBEndpoint *ep, unsigned int stream) + */ + return; + } +- if (dev->remote_wakeup && dev->port && dev->port->ops->wakeup) { ++ if ((dev->remote_wakeup & USB_DEVICE_REMOTE_WAKEUP) ++ && dev->port && dev->port->ops->wakeup) { + dev->port->ops->wakeup(dev->port); + } + if (bus->ops->wakeup_endpoint) { +diff --git a/hw/usb/desc.c b/hw/usb/desc.c +index 8b6eaea407..78bbe74c71 100644 +--- a/hw/usb/desc.c ++++ b/hw/usb/desc.c +@@ -751,7 +751,7 @@ int usb_desc_handle_control(USBDevice *dev, USBPacket *p, + if (config->bmAttributes & USB_CFG_ATT_SELFPOWER) { + data[0] |= 1 << USB_DEVICE_SELF_POWERED; + } +- if (dev->remote_wakeup) { ++ if (dev->remote_wakeup & USB_DEVICE_REMOTE_WAKEUP) { + data[0] |= 1 << USB_DEVICE_REMOTE_WAKEUP; + } + data[1] = 0x00; +@@ -761,14 +761,15 @@ int usb_desc_handle_control(USBDevice *dev, USBPacket *p, + } + case DeviceOutRequest | USB_REQ_CLEAR_FEATURE: + if (value == USB_DEVICE_REMOTE_WAKEUP) { +- dev->remote_wakeup = 0; ++ dev->remote_wakeup &= ~USB_DEVICE_REMOTE_WAKEUP; + ret = 0; + } + trace_usb_clear_device_feature(dev->addr, value, ret); + break; + case DeviceOutRequest | USB_REQ_SET_FEATURE: ++ dev->remote_wakeup |= USB_DEVICE_REMOTE_WAKEUP_IS_SUPPORTED; + if (value == USB_DEVICE_REMOTE_WAKEUP) { +- dev->remote_wakeup = 1; ++ dev->remote_wakeup |= USB_DEVICE_REMOTE_WAKEUP; + ret = 0; + } + trace_usb_set_device_feature(dev->addr, value, ret); +diff --git a/hw/usb/dev-hid.c b/hw/usb/dev-hid.c +index 1c7ae97c30..9fb89f6955 100644 +--- a/hw/usb/dev-hid.c ++++ b/hw/usb/dev-hid.c +@@ -745,7 +745,7 @@ static int usb_ptr_post_load(void *opaque, int version_id) + { + USBHIDState *s = opaque; + +- if (s->dev.remote_wakeup) { ++ if (s->dev.remote_wakeup & USB_DEVICE_REMOTE_WAKEUP) { + hid_pointer_activate(&s->hid); + } + return 0; +diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c +index d1b5657d72..693c68f445 100644 +--- a/hw/usb/hcd-uhci.c ++++ b/hw/usb/hcd-uhci.c +@@ -44,6 +44,8 @@ + #include "hcd-uhci.h" + + #define FRAME_TIMER_FREQ 1000 ++#define FRAME_TIMER_FREQ_LAZY 10 ++#define USB_DEVICE_NEED_NORMAL_FREQ "QEMU USB Tablet" + + #define FRAME_MAX_LOOPS 256 + +@@ -111,6 +113,22 @@ static void uhci_async_cancel(UHCIAsync *async); + static void uhci_queue_fill(UHCIQueue *q, UHCI_TD *td); + static void uhci_resume(void *opaque); + ++static int64_t uhci_frame_timer_freq = FRAME_TIMER_FREQ_LAZY; ++ ++static void uhci_set_frame_freq(int freq) ++{ ++ if (freq <= 0) { ++ return; ++ } ++ ++ uhci_frame_timer_freq = freq; ++} ++ ++static qemu_usb_controller qemu_uhci = { ++ .name = "uhci", ++ .qemu_set_freq = uhci_set_frame_freq, ++}; ++ + static inline int32_t uhci_queue_token(UHCI_TD *td) + { + if ((td->token & (0xf << 15)) == 0) { +@@ -353,7 +371,7 @@ static int uhci_post_load(void *opaque, int version_id) + + if (version_id < 2) { + s->expire_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + +- (NANOSECONDS_PER_SECOND / FRAME_TIMER_FREQ); ++ (NANOSECONDS_PER_SECOND / uhci_frame_timer_freq); + } + return 0; + } +@@ -394,8 +412,29 @@ static void uhci_port_write(void *opaque, hwaddr addr, + if ((val & UHCI_CMD_RS) && !(s->cmd & UHCI_CMD_RS)) { + /* start frame processing */ + trace_usb_uhci_schedule_start(); +- s->expire_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + +- (NANOSECONDS_PER_SECOND / FRAME_TIMER_FREQ); ++ ++ /* ++ * If the frequency of frame_timer is too slow, Guest OS (Win2012) would become ++ * blue-screen after hotplugging some vcpus. ++ * If this USB device support the remote-wakeup, the UHCI controller ++ * will enter global suspend mode when there is no input for several seconds. ++ * In this case, Qemu will delete the frame_timer. Since the frame_timer has been deleted, ++ * there is no influence to the performance of Vms. So, we can change the frequency to 1000. ++ * After that the frequency will be safe when we trigger the frame_timer again. ++ * Excepting this, there are two ways to change the frequency: ++ * 1)VNC connect/disconnect;2)attach/detach USB device. ++ */ ++ if ((uhci_frame_timer_freq != FRAME_TIMER_FREQ) ++ && (s->ports[0].port.dev) ++ && (!memcmp(s->ports[0].port.dev->product_desc, ++ USB_DEVICE_NEED_NORMAL_FREQ, strlen(USB_DEVICE_NEED_NORMAL_FREQ))) ++ && (s->ports[0].port.dev->remote_wakeup & USB_DEVICE_REMOTE_WAKEUP_IS_SUPPORTED)) { ++ qemu_log("turn up the frequency of UHCI controller to %d\n", FRAME_TIMER_FREQ); ++ uhci_frame_timer_freq = FRAME_TIMER_FREQ; ++ } ++ ++ s->frame_time = NANOSECONDS_PER_SECOND / FRAME_TIMER_FREQ; ++ s->expire_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + s->frame_time; + timer_mod(s->frame_timer, s->expire_time); + s->status &= ~UHCI_STS_HCHALTED; + } else if (!(val & UHCI_CMD_RS)) { +@@ -1083,7 +1122,6 @@ static void uhci_frame_timer(void *opaque) + UHCIState *s = opaque; + uint64_t t_now, t_last_run; + int i, frames; +- const uint64_t frame_t = NANOSECONDS_PER_SECOND / FRAME_TIMER_FREQ; + + s->completions_only = false; + qemu_bh_cancel(s->bh); +@@ -1099,14 +1137,14 @@ static void uhci_frame_timer(void *opaque) + } + + /* We still store expire_time in our state, for migration */ +- t_last_run = s->expire_time - frame_t; ++ t_last_run = s->expire_time - s->frame_time; + t_now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + + /* Process up to MAX_FRAMES_PER_TICK frames */ +- frames = (t_now - t_last_run) / frame_t; ++ frames = (t_now - t_last_run) / s->frame_time; + if (frames > s->maxframes) { + int skipped = frames - s->maxframes; +- s->expire_time += skipped * frame_t; ++ s->expire_time += skipped * s->frame_time; + s->frnum = (s->frnum + skipped) & 0x7ff; + frames -= skipped; + } +@@ -1123,7 +1161,7 @@ static void uhci_frame_timer(void *opaque) + /* The spec says frnum is the frame currently being processed, and + * the guest must look at frnum - 1 on interrupt, so inc frnum now */ + s->frnum = (s->frnum + 1) & 0x7ff; +- s->expire_time += frame_t; ++ s->expire_time += s->frame_time; + } + + /* Complete the previous frame(s) */ +@@ -1134,7 +1172,12 @@ static void uhci_frame_timer(void *opaque) + } + s->pending_int_mask = 0; + +- timer_mod(s->frame_timer, t_now + frame_t); ++ /* expire_time is calculated from last frame_time, we should calculate it ++ * according to new frame_time which equals to ++ * NANOSECONDS_PER_SECOND / uhci_frame_timer_freq */ ++ s->expire_time -= s->frame_time - NANOSECONDS_PER_SECOND / uhci_frame_timer_freq; ++ s->frame_time = NANOSECONDS_PER_SECOND / uhci_frame_timer_freq; ++ timer_mod(s->frame_timer, t_now + s->frame_time); + } + + static const MemoryRegionOps uhci_ioport_ops = { +@@ -1196,8 +1239,10 @@ void usb_uhci_common_realize(PCIDevice *dev, Error **errp) + s->bh = qemu_bh_new(uhci_bh, s); + s->frame_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, uhci_frame_timer, s); + s->num_ports_vmstate = NB_PORTS; ++ s->frame_time = NANOSECONDS_PER_SECOND / uhci_frame_timer_freq; + QTAILQ_INIT(&s->queues); + ++ qemu_register_usb_controller(&qemu_uhci, QEMU_USB_CONTROLLER_UHCI); + memory_region_init_io(&s->io_bar, OBJECT(s), &uhci_ioport_ops, s, + "uhci", 0x20); + +diff --git a/hw/usb/hcd-uhci.h b/hw/usb/hcd-uhci.h +index c85ab7868e..5194d22ab4 100644 +--- a/hw/usb/hcd-uhci.h ++++ b/hw/usb/hcd-uhci.h +@@ -50,6 +50,7 @@ typedef struct UHCIState { + uint16_t status; + uint16_t intr; /* interrupt enable register */ + uint16_t frnum; /* frame number */ ++ uint64_t frame_time; /* frame time in ns */ + uint32_t fl_base_addr; /* frame list base address */ + uint8_t sof_timing; + uint8_t status2; /* bit 0 and 1 are used to generate UHCI_STS_USBINT */ +diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c +index d0d46dd0a4..8f521ad586 100644 +--- a/hw/usb/host-libusb.c ++++ b/hw/usb/host-libusb.c +@@ -945,6 +945,30 @@ static void usb_host_ep_update(USBHostDevice *s) + libusb_free_config_descriptor(conf); + } + ++static unsigned int usb_get_controller_type(int speed) ++{ ++ unsigned int type = MAX_USB_CONTROLLER_TYPES; ++ ++ switch (speed) { ++ case USB_SPEED_SUPER: ++ type = QEMU_USB_CONTROLLER_XHCI; ++ break; ++ case USB_SPEED_HIGH: ++ type = QEMU_USB_CONTROLLER_EHCI; ++ break; ++ case USB_SPEED_FULL: ++ type = QEMU_USB_CONTROLLER_UHCI; ++ break; ++ case USB_SPEED_LOW: ++ type = QEMU_USB_CONTROLLER_OHCI; ++ break; ++ default: ++ break; ++ } ++ ++ return type; ++} ++ + static int usb_host_open(USBHostDevice *s, libusb_device *dev, int hostfd) + { + USBDevice *udev = USB_DEVICE(s); +@@ -1054,6 +1078,12 @@ static int usb_host_open(USBHostDevice *s, libusb_device *dev, int hostfd) + } + + trace_usb_host_open_success(bus_num, addr); ++ ++ /* change ehci frame time freq when USB passthrough */ ++ qemu_log("usb host speed is %d\n", udev->speed); ++ qemu_timer_set_mode(QEMU_TIMER_USB_NORMAL_MODE, ++ usb_get_controller_type(udev->speed)); ++ + return 0; + + fail: +@@ -1129,6 +1159,8 @@ static int usb_host_close(USBHostDevice *s) + } + + usb_host_auto_check(NULL); ++ qemu_timer_set_mode(QEMU_TIMER_USB_LAZY_MODE, ++ usb_get_controller_type(udev->speed)); + return 0; + } + +diff --git a/include/hw/usb.h b/include/hw/usb.h +index 33668dd0a9..fa3a176159 100644 +--- a/include/hw/usb.h ++++ b/include/hw/usb.h +@@ -142,6 +142,7 @@ + + #define USB_DEVICE_SELF_POWERED 0 + #define USB_DEVICE_REMOTE_WAKEUP 1 ++#define USB_DEVICE_REMOTE_WAKEUP_IS_SUPPORTED 2 + + #define USB_DT_DEVICE 0x01 + #define USB_DT_CONFIG 0x02 +diff --git a/include/qemu/timer.h b/include/qemu/timer.h +index 88ef114689..d263fad9a4 100644 +--- a/include/qemu/timer.h ++++ b/include/qemu/timer.h +@@ -91,6 +91,34 @@ struct QEMUTimer { + int scale; + }; + ++#define QEMU_USB_NORMAL_FREQ 1000 ++#define QEMU_USB_LAZY_FREQ 10 ++#define MAX_USB_CONTROLLER_TYPES 4 ++#define QEMU_USB_CONTROLLER_OHCI 0 ++#define QEMU_USB_CONTROLLER_UHCI 1 ++#define QEMU_USB_CONTROLLER_EHCI 2 ++#define QEMU_USB_CONTROLLER_XHCI 3 ++ ++typedef void (*QEMUSetFreqHandler) (int freq); ++ ++typedef struct qemu_usb_controller { ++ const char *name; ++ QEMUSetFreqHandler qemu_set_freq; ++} qemu_usb_controller; ++ ++typedef qemu_usb_controller* qemu_usb_controller_ptr; ++ ++enum qemu_timer_mode { ++ QEMU_TIMER_USB_NORMAL_MODE = 1 << 0, /* Set when VNC connect or ++ * with usb dev passthrough ++ */ ++ QEMU_TIMER_USB_LAZY_MODE = 1 << 1, /* Set when VNC disconnect */ ++}; ++ ++int qemu_register_usb_controller(qemu_usb_controller_ptr controller, ++ unsigned int type); ++int qemu_timer_set_mode(enum qemu_timer_mode mode, unsigned int type); ++ + extern QEMUTimerListGroup main_loop_tlg; + + /* +diff --git a/ui/vnc.c b/ui/vnc.c +index af02522e84..bc86c20370 100644 +--- a/ui/vnc.c ++++ b/ui/vnc.c +@@ -1379,6 +1379,8 @@ void vnc_disconnect_finish(VncState *vs) + g_free(vs->zrle); + g_free(vs->tight); + g_free(vs); ++ ++ qemu_timer_set_mode(QEMU_TIMER_USB_LAZY_MODE, QEMU_USB_CONTROLLER_UHCI); + } + + size_t vnc_client_io_error(VncState *vs, ssize_t ret, Error *err) +@@ -3333,6 +3335,8 @@ static void vnc_connect(VncDisplay *vd, QIOChannelSocket *sioc, + } + } + } ++ ++ qemu_timer_set_mode(QEMU_TIMER_USB_NORMAL_MODE, QEMU_USB_CONTROLLER_UHCI); + } + + void vnc_start_protocol(VncState *vs) +diff --git a/util/qemu-timer.c b/util/qemu-timer.c +index f36c75e594..40e8c83722 100644 +--- a/util/qemu-timer.c ++++ b/util/qemu-timer.c +@@ -23,6 +23,7 @@ + */ + + #include "qemu/osdep.h" ++#include "qemu/log.h" + #include "qemu/main-loop.h" + #include "qemu/timer.h" + #include "qemu/lockable.h" +@@ -75,6 +76,74 @@ struct QEMUTimerList { + QemuEvent timers_done_ev; + }; + ++typedef struct qemu_controller_timer_state { ++ qemu_usb_controller_ptr controller; ++ int refs; ++} controller_timer_state; ++ ++typedef controller_timer_state* controller_timer_state_ptr; ++ ++static controller_timer_state uhci_timer_state = { ++ .controller = NULL, ++ .refs = 0, ++}; ++ ++static controller_timer_state_ptr \ ++ qemu_usb_controller_tab[MAX_USB_CONTROLLER_TYPES] = {NULL, ++ &uhci_timer_state, ++ NULL, NULL}; ++ ++int qemu_register_usb_controller(qemu_usb_controller_ptr controller, ++ unsigned int type) ++{ ++ if (type != QEMU_USB_CONTROLLER_UHCI) { ++ return 0; ++ } ++ ++ /* for companion EHCI controller will create three UHCI controllers, ++ * we init it only once. ++ */ ++ if (!qemu_usb_controller_tab[type]->controller) { ++ qemu_log("the usb controller (%d) registed frame handler\n", type); ++ qemu_usb_controller_tab[type]->controller = controller; ++ } ++ ++ return 0; ++} ++ ++int qemu_timer_set_mode(enum qemu_timer_mode mode, unsigned int type) ++{ ++ if (type != QEMU_USB_CONTROLLER_UHCI) { ++ qemu_log("the usb controller (%d) no need change frame frep\n", type); ++ return 0; ++ } ++ ++ if (!qemu_usb_controller_tab[type]->controller) { ++ qemu_log("the usb controller (%d) not registed yet\n", type); ++ return 0; ++ } ++ ++ if (mode == QEMU_TIMER_USB_NORMAL_MODE) { ++ if (qemu_usb_controller_tab[type]->refs++ > 0) { ++ return 0; ++ } ++ qemu_usb_controller_tab[type]->controller-> ++ qemu_set_freq(QEMU_USB_NORMAL_FREQ); ++ qemu_log("Set the controller (%d) of freq %d HZ,\n", ++ type, QEMU_USB_NORMAL_FREQ); ++ } else { ++ if (--qemu_usb_controller_tab[type]->refs > 0) { ++ return 0; ++ } ++ qemu_usb_controller_tab[type]->controller-> ++ qemu_set_freq(QEMU_USB_LAZY_FREQ); ++ qemu_log("Set the controller(type:%d) of freq %d HZ,\n", ++ type, QEMU_USB_LAZY_FREQ); ++ } ++ ++ return 0; ++} ++ + /** + * qemu_clock_ptr: + * @type: type of clock +-- +2.27.0 + -- Gitee From cb83365f6a26a00af355c7580dc104283e5b78dc Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Fri, 11 Feb 2022 21:01:33 +0800 Subject: [PATCH 34/38] =?UTF-8?q?spec:=20Update=20patch=20and=20changelog?= =?UTF-8?q?=20with=20!244=20usb=20uhci=E5=BC=80=E9=94=80=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E8=A1=A5=E4=B8=81=E5=9B=9E=E5=90=88=20=20!244?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit hw/usb: reduce the vpcu cost of UHCI when VNC disconnect Signed-off-by: Chen Qun --- qemu.spec | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/qemu.spec b/qemu.spec index be0430f..caeeba6 100644 --- a/qemu.spec +++ b/qemu.spec @@ -75,6 +75,7 @@ Patch0062: target-arm-Update-the-ID-registers-of-Kunpeng-920.patch Patch0063: freeclock-add-qmp-command-to-get-time-offset-of-vm-i.patch Patch0064: freeclock-set-rtc_date_diff-for-arm.patch Patch0065: freeclock-set-rtc_date_diff-for-X86.patch +Patch0066: hw-usb-reduce-the-vpcu-cost-of-UHCI-when-VNC-disconn.patch BuildRequires: flex BuildRequires: gcc @@ -519,6 +520,9 @@ getent passwd qemu >/dev/null || \ %endif %changelog +* Fri Feb 11 2022 Chen Qun +- hw/usb: reduce the vpcu cost of UHCI when VNC disconnect + * Fri Feb 11 2022 Chen Qun - freeclock: add qmp command to get time offset of vm in seconds - freeclock: set rtc_date_diff for arm -- Gitee From 5e301118b2c86246032f9570a59d4dcf713bc75e Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Thu, 10 Feb 2022 16:54:06 +0800 Subject: [PATCH 35/38] hw/net/rocker: fix security vulnerability fix security vulnerability Signed-off-by: Lichang zhao Signed-off-by: Jinhao Gao --- ...et-rocker-fix-security-vulnerability.patch | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 hw-net-rocker-fix-security-vulnerability.patch diff --git a/hw-net-rocker-fix-security-vulnerability.patch b/hw-net-rocker-fix-security-vulnerability.patch new file mode 100644 index 0000000..c841e97 --- /dev/null +++ b/hw-net-rocker-fix-security-vulnerability.patch @@ -0,0 +1,28 @@ +From 9a8de722b047ba66f70e87fb29b877935c187457 Mon Sep 17 00:00:00 2001 +From: Lichang Zhao +Date: Thu, 10 Feb 2022 16:54:06 +0800 +Subject: [PATCH] hw/net/rocker: fix security vulnerability + +fix security vulnerability + +Signed-off-by: Lichang zhao +Signed-off-by: Jinhao Gao +--- + hw/net/rocker/rocker_of_dpa.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/hw/net/rocker/rocker_of_dpa.c b/hw/net/rocker/rocker_of_dpa.c +index b3b8c5bb6d..8ac26e6beb 100644 +--- a/hw/net/rocker/rocker_of_dpa.c ++++ b/hw/net/rocker/rocker_of_dpa.c +@@ -2070,6 +2070,7 @@ static int of_dpa_cmd_add_l2_flood(OfDpa *of_dpa, OfDpaGroup *group, + err_out: + group->l2_flood.group_count = 0; + g_free(group->l2_flood.group_ids); ++ group->l2_flood.group_ids = NULL; + g_free(tlvs); + + return err; +-- +2.27.0 + -- Gitee From 9c61487beb118b761e5ec76465ae86340881fa12 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Thu, 10 Feb 2022 17:16:55 +0800 Subject: [PATCH 36/38] tests: Disable filemonitor testcase Since filemonitor testcase requires that host kernel being a LTS version, we cannot guarantee that on OBS system. Lets disable it by default. Signed-off-by: Ying Fang Signed-off-by: Jinhao Gao --- tests-Disable-filemonitor-testcase.patch | 31 ++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 tests-Disable-filemonitor-testcase.patch diff --git a/tests-Disable-filemonitor-testcase.patch b/tests-Disable-filemonitor-testcase.patch new file mode 100644 index 0000000..6d73236 --- /dev/null +++ b/tests-Disable-filemonitor-testcase.patch @@ -0,0 +1,31 @@ +From 4f09a1c2aa855aab666d729defce4c7f0466cb77 Mon Sep 17 00:00:00 2001 +From: Ying Fang +Date: Thu, 10 Feb 2022 17:16:55 +0800 +Subject: [PATCH] tests: Disable filemonitor testcase + +Since filemonitor testcase requires that host kernel being a LTS version, +we cannot guarantee that on OBS system. Lets disable it by default. + +Signed-off-by: Ying Fang +Signed-off-by: Jinhao Gao +--- + tests/unit/meson.build | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/tests/unit/meson.build b/tests/unit/meson.build +index acac3622ed..c21d817874 100644 +--- a/tests/unit/meson.build ++++ b/tests/unit/meson.build +@@ -129,9 +129,6 @@ if have_system + 'test-vmstate': [migration, io], + 'test-yank': ['socket-helpers.c', qom, io, chardev] + } +- if 'CONFIG_INOTIFY1' in config_host +- tests += {'test-util-filemonitor': []} +- endif + + # Some tests: test-char, test-qdev-global-props, and test-qga, + # are not runnable under TSan due to a known issue. +-- +2.27.0 + -- Gitee From c6f5c806144091a1fd0793902e35a5b980c2c622 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Fri, 11 Feb 2022 21:01:36 +0800 Subject: [PATCH 37/38] spec: Update patch and changelog with !234 [6.2.0] backport patches !234 hw/net/rocker: fix security vulnerability tests: Disable filemonitor testcase Signed-off-by: Chen Qun --- qemu.spec | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/qemu.spec b/qemu.spec index caeeba6..fd193af 100644 --- a/qemu.spec +++ b/qemu.spec @@ -76,6 +76,8 @@ Patch0063: freeclock-add-qmp-command-to-get-time-offset-of-vm-i.patch Patch0064: freeclock-set-rtc_date_diff-for-arm.patch Patch0065: freeclock-set-rtc_date_diff-for-X86.patch Patch0066: hw-usb-reduce-the-vpcu-cost-of-UHCI-when-VNC-disconn.patch +Patch0067: hw-net-rocker-fix-security-vulnerability.patch +Patch0068: tests-Disable-filemonitor-testcase.patch BuildRequires: flex BuildRequires: gcc @@ -520,6 +522,10 @@ getent passwd qemu >/dev/null || \ %endif %changelog +* Fri Feb 11 2022 Chen Qun +- hw/net/rocker: fix security vulnerability +- tests: Disable filemonitor testcase + * Fri Feb 11 2022 Chen Qun - hw/usb: reduce the vpcu cost of UHCI when VNC disconnect -- Gitee From 78d3a4fd2a44604b15b99c5905bb27329f999299 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Fri, 11 Feb 2022 21:01:42 +0800 Subject: [PATCH 38/38] spec: Update release version with !233 !241 !240 !237 !244 !234 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 fd193af..b52cf7b 100644 --- a/qemu.spec +++ b/qemu.spec @@ -1,6 +1,6 @@ Name: qemu Version: 6.2.0 -Release: 8 +Release: 9 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