From c76201483a4fed63fa658ae6614201ab01cf62da Mon Sep 17 00:00:00 2001 From: Renbo Date: Tue, 27 Dec 2022 17:48:45 +0800 Subject: [PATCH 1/3] update to qemu-kvm-6.2.0-20.module+el8.7.0+16905+efca5d32.2 Signed-off-by: Renbo --- 0001-Add-Acpi-support.patch | 1348 -- 0002-Support-rtc.patch | 370 - 0003-Add-loongarch-machine.patch | 5752 ------ 0004-Add-target-loongarch64.patch | 15918 ---------------- 0005-Add-linux-headers-and-linux-user.patch | 1663 -- 0006-Add-disas-gdb.patch | 3183 --- 0007-Modify-kvm-cpu-vga-qapi.patch | 480 - 0008-Modify-compile-script.patch | 36 - 0009-Add-loongarch64-rh-devices.mak.patch | 3227 ---- ...sync-missed-zero-copy-migration-stat.patch | 18 +- ...nd-invalid-CPUID-0xD-9-info-on-some-.patch | 109 + ...lags-on-io_writev-and-introduce-io_f.patch | 14 +- ...et-Add-support-for-MSG_ZEROCOPY-IPV6.patch | 14 +- ...-Fix-zero-copy-flush-returning-code-.patch | 14 +- ...-Fix-zero-copy-send-so-socket-flush-.patch | 14 +- ...-Implement-io_writev-zero-copy-flag-.patch | 14 +- ...-Introduce-assert-and-reduce-ifdefs-.patch | 14 +- ...packet-for-vhost-vsock-device-in-rhe.patch | 16 +- ...d-hw_compat_4_2_extra-and-apply-to-u.patch | 38 +- ...d-some-devices-for-exporting-upstrea.patch | 14 +- ...able-FDC-device-for-upstream-machine.patch | 38 +- ...pose-upstream-machines-pc-4.2-and-pc.patch | 37 +- ...acpi-fix-OEM-ID-OEM-Table-ID-padding.patch | 90 +- ...U-crash-when-started-with-SLIC-table.patch | 125 +- ...pcie-set-power-on-cap-on-parent-slot.patch | 94 +- ...ntext-for-drain_end-in-blockdev-reop.patch | 63 + ...ke-bdrv_refresh_limits-non-recursive.patch | 78 + ...er-fix-race-condition-in-qxl_cursor-.patch | 15 +- ...vent-end-of-track-overrun-CVE-2021-3.patch | 97 + ...3-Check-for-MEMTX_OK-instead-of-MEMT.patch | 13 +- ...ix-leak-of-host-notifier-memory-regi.patch | 82 +- ...-Server-v6-CPU-model-with-5-level-EP.patch | 27 +- ...msr_feature_control-first-thing-when.patch | 68 + ...eset-KVM-nested-state-upon-CPU-reset.patch | 95 + ...ent-BB-in-flight-counter-for-TRIM-BH.patch | 92 + ...08-Fix-when-missing-user_allow_other.patch | 12 +- ...-Test-new-refcount-rebuild-algorithm.patch | 12 +- ...iotests-Allow-using-QMP-with-the-QSD.patch | 99 + ...ckdev-reopen-with-iothreads-and-thro.patch | 106 + ...ests-graph-changes-while-io-New-test.patch | 153 + ...n-why-max-batch-is-checked-in-laio_i.patch | 10 +- ...balanced-plugged-counter-in-laio_io_.patch | 10 +- ...-headers-Update-headers-to-v5.17-rc1.patch | 1227 ++ ...rs-include-missing-changes-from-5.17.patch | 58 + kvm-linux-headers-update-to-5.16-rc1.patch | 725 + ...migration-Add-migrate_use_tls-helper.patch | 14 +- ...migration_incoming_transport_cleanup.patch | 102 + ...ro-copy-send-parameter-for-QMP-HMP-f.patch | 14 +- ...gration-All-this-fields-are-unsigned.patch | 14 +- ...migrate-recover-to-run-multiple-time.patch | 98 + ...false-positive-on-non-supported-scen.patch | 20 +- ...-zero_copy_send-from-migration-param.patch | 14 +- ...ration-Introduce-ram_transferred_add.patch | 14 +- ...ver-call-twice-qemu_target_page_size.patch | 14 +- ...pre-copy-downtime-and-post-copy-byte.patch | 18 +- ...maining-params-has_-true-in-migratio.patch | 20 +- ...d-Report-to-user-when-zerocopy-not-w.patch | 14 +- ...vm-multifd-Add-missing-documentation.patch | 15 +- ...-Fill-offset-and-block-for-reception.patch | 14 +- ...t-zero-copy-write-in-multifd-migrati.patch | 14 +- ...zlib-compression-method-not-use-iovs.patch | 14 +- kvm-multifd-Make-zlib-use-iov-s.patch | 14 +- ...zstd-compression-method-not-use-iovs.patch | 14 +- kvm-multifd-Make-zstd-use-iov-s.patch | 14 +- ...ultifd-Move-iov-from-pages-to-params.patch | 14 +- kvm-multifd-Remove-send_write-method.patch | 14 +- kvm-multifd-Rename-used-field-to-num.patch | 14 +- ...der-packet-without-flags-if-zero-cop.patch | 14 +- ...ariable-is-only-used-inside-the-loop.patch | 14 +- ...Use-a-single-writev-on-the-send-side.patch | 14 +- ...-normal-pages-array-on-the-send-side.patch | 14 +- ...send_sync_main-now-returns-negative-.patch | 14 +- ...sed-parameter-from-send_prepare-meth.patch | 14 +- ...sed-parameter-from-send_recv_pages-m.patch | 14 +- ...-Fix-booting-with-logical-block-size.patch | 63 + ...-Split-virtio-scsi-code-from-virtio_.patch | 180 + ...-bootmap-Improve-the-guessing-logic-.patch | 102 + ...-virtio-Beautify-the-code-for-readin.patch | 56 + ...-virtio-Introduce-a-macro-for-the-DA.patch | 63 + ...-virtio-Read-device-config-after-fea.patch | 67 + ...-virtio-Set-missing-status-bits-whil.patch | 93 + ...-virtio-blkdev-Remove-virtio_assume_.patch | 101 + ...-virtio-blkdev-Request-the-right-fea.patch | 63 + ...-virtio-blkdev-Simplify-fix-virtio_i.patch | 124 + ...-expose-TYPE_XIO3130_DOWNSTREAM-name.patch | 44 +- ...d-errp-to-rebuild_refcount_structure.patch | 12 +- ...mprove-refcount-structure-rebuilding.patch | 12 +- kvm-s390x-css-fix-PMCW-invalid-mask.patch | 58 + ...rt-extended-kernel-command-line-size.patch | 97 + ...c-Fix-emulated-block-limits-VPD-page.patch | 13 +- ...Introduce-MemTxAttrs-memory-field-an.patch | 13 +- ...Simplify-flatview_write-and-address_.patch | 13 +- ...do-not-access-uninitialized-variable.patch | 73 + ...get-i386-properly-reset-TSC-on-reset.patch | 12 +- ...ests-acpi-SLIC-update-expected-blobs.patch | 43 +- kvm-tests-acpi-add-SLIC-table-test.patch | 54 +- ...lly-pad-OEM_ID-OEM_TABLE_ID-for-test.patch | 52 +- ...short-OEM_ID-OEM_TABLE_ID-values-in-.patch | 58 +- kvm-tests-acpi-update-expected-blobs.patch | 65 +- ...list-expected-blobs-before-changing-.patch | 43 +- ...list-nvdimm-s-SSDT-and-FACP.slic-exp.patch | 66 +- ...test-Add-a-regression-test-for-CVE-2.patch | 120 + ...teger-overflow-in-cursor_alloc-CVE-2.patch | 18 +- ...-improper-cleanup-in-vhost_net_start.patch | 20 +- ...backend-feature-should-set-only-once.patch | 20 +- ...e-name-and-polarity-for-vhost_vdpa_o.patch | 23 +- ...mproper-cleanup-in-net_init_vhost_vd.patch | 20 +- ...ch-the-virqueue-element-in-case-of-e.patch | 16 +- kvm-virtio-gpu-do-not-byteswap-padding.patch | 48 + ...-ctrl_vq-index-for-non-mq-guest-for-.patch | 20 +- ...-handle-mq-request-in-userspace-hand.patch | 22 +- ...-map-leaking-on-error-during-receive.patch | 23 +- ...-vhost_dev-and-notifiers-for-cvq-onl.patch | 20 +- ...iofsd-Adjust-limit-for-minor-version.patch | 41 - ...eakage-due-to-fuse_init_in-size-chan.patch | 63 + ...date_time_get_microsecond-to-get-sub.patch | 61 + kvm-vmxcap-Add-5-level-EPT-bit.patch | 27 +- kvm-x86-Add-AMX-CPUIDs-enumeration.patch | 135 + ...MX-XTILECFG-and-XTILEDATA-components.patch | 112 + ...FD-faulting-bit-for-state-components.patch | 62 + ...yte-boundary-enumeration-for-extende.patch | 88 + kvm-x86-Grant-AMX-permission-for-guest.patch | 215 + ...ort-XFD-and-AMX-xsave-data-migration.patch | 178 + ...for-KVM_CAP_XSAVE2-and-AMX-state-mig.patch | 182 + loongarch_bios.bin | Bin 4190208 -> 0 bytes loongarch_vars.bin | Bin 389120 -> 0 bytes qemu-kvm.spec | 740 +- 127 files changed, 6996 insertions(+), 33195 deletions(-) delete mode 100644 0001-Add-Acpi-support.patch delete mode 100644 0002-Support-rtc.patch delete mode 100644 0003-Add-loongarch-machine.patch delete mode 100644 0004-Add-target-loongarch64.patch delete mode 100644 0005-Add-linux-headers-and-linux-user.patch delete mode 100644 0006-Add-disas-gdb.patch delete mode 100644 0007-Modify-kvm-cpu-vga-qapi.patch delete mode 100644 0008-Modify-compile-script.patch delete mode 100644 0009-Add-loongarch64-rh-devices.mak.patch create mode 100644 kvm-KVM-x86-workaround-invalid-CPUID-0xD-9-info-on-some-.patch create mode 100644 kvm-block-Lock-AioContext-for-drain_end-in-blockdev-reop.patch create mode 100644 kvm-block-Make-bdrv_refresh_limits-non-recursive.patch create mode 100644 kvm-hw-block-fdc-Prevent-end-of-track-overrun-CVE-2021-3.patch create mode 100644 kvm-i386-do-kvm_put_msr_feature_control-first-thing-when.patch create mode 100644 kvm-i386-reset-KVM-nested-state-upon-CPU-reset.patch create mode 100644 kvm-ide-Increment-BB-in-flight-counter-for-TRIM-BH.patch create mode 100644 kvm-iotests-Allow-using-QMP-with-the-QSD.patch create mode 100644 kvm-iotests-Test-blockdev-reopen-with-iothreads-and-thro.patch create mode 100644 kvm-iotests-graph-changes-while-io-New-test.patch create mode 100644 kvm-linux-headers-Update-headers-to-v5.17-rc1.patch create mode 100644 kvm-linux-headers-include-missing-changes-from-5.17.patch create mode 100644 kvm-linux-headers-update-to-5.16-rc1.patch create mode 100644 kvm-migration-Add-migration_incoming_transport_cleanup.patch create mode 100644 kvm-migration-Allow-migrate-recover-to-run-multiple-time.patch rename kvm-multifd-Add-missing-documention.patch => kvm-multifd-Add-missing-documentation.patch (88%) create mode 100644 kvm-pc-bios-s390-ccw-Fix-booting-with-logical-block-size.patch create mode 100644 kvm-pc-bios-s390-ccw-Split-virtio-scsi-code-from-virtio_.patch create mode 100644 kvm-pc-bios-s390-ccw-bootmap-Improve-the-guessing-logic-.patch create mode 100644 kvm-pc-bios-s390-ccw-virtio-Beautify-the-code-for-readin.patch create mode 100644 kvm-pc-bios-s390-ccw-virtio-Introduce-a-macro-for-the-DA.patch create mode 100644 kvm-pc-bios-s390-ccw-virtio-Read-device-config-after-fea.patch create mode 100644 kvm-pc-bios-s390-ccw-virtio-Set-missing-status-bits-whil.patch create mode 100644 kvm-pc-bios-s390-ccw-virtio-blkdev-Remove-virtio_assume_.patch create mode 100644 kvm-pc-bios-s390-ccw-virtio-blkdev-Request-the-right-fea.patch create mode 100644 kvm-pc-bios-s390-ccw-virtio-blkdev-Simplify-fix-virtio_i.patch create mode 100644 kvm-s390x-css-fix-PMCW-invalid-mask.patch create mode 100644 kvm-s390x-ipl-support-extended-kernel-command-line-size.patch create mode 100644 kvm-target-i386-kvm-do-not-access-uninitialized-variable.patch create mode 100644 kvm-tests-qtest-fdc-test-Add-a-regression-test-for-CVE-2.patch create mode 100644 kvm-virtio-gpu-do-not-byteswap-padding.patch delete mode 100644 kvm-virtiofsd-Adjust-limit-for-minor-version.patch create mode 100644 kvm-virtiofsd-Fix-breakage-due-to-fuse_init_in-size-chan.patch create mode 100644 kvm-virtiofsd-use-g_date_time_get_microsecond-to-get-sub.patch create mode 100644 kvm-x86-Add-AMX-CPUIDs-enumeration.patch create mode 100644 kvm-x86-Add-AMX-XTILECFG-and-XTILEDATA-components.patch create mode 100644 kvm-x86-Add-XFD-faulting-bit-for-state-components.patch create mode 100644 kvm-x86-Fix-the-64-byte-boundary-enumeration-for-extende.patch create mode 100644 kvm-x86-Grant-AMX-permission-for-guest.patch create mode 100644 kvm-x86-Support-XFD-and-AMX-xsave-data-migration.patch create mode 100644 kvm-x86-add-support-for-KVM_CAP_XSAVE2-and-AMX-state-mig.patch delete mode 100644 loongarch_bios.bin delete mode 100644 loongarch_vars.bin diff --git a/0001-Add-Acpi-support.patch b/0001-Add-Acpi-support.patch deleted file mode 100644 index 5b1561c..0000000 --- a/0001-Add-Acpi-support.patch +++ /dev/null @@ -1,1348 +0,0 @@ -From 612826687e639d007e4270b01a61f34f7fc1f813 Mon Sep 17 00:00:00 2001 -From: lixianglai -Date: Fri, 19 Aug 2022 23:11:23 -0400 -Subject: [PATCH 1/8] Add Acpi support. - -Change-Id: I208228b2178cddf365e97c6faf6111ef40e795eb -Signed-off-by: lixianglai ---- - hw/acpi/Kconfig | 8 + - hw/acpi/larch_7a.c | 600 +++++++++++++++++++++++++++++++++++++++++ - hw/acpi/ls7a.c | 598 ++++++++++++++++++++++++++++++++++++++++ - hw/acpi/meson.build | 1 + - include/hw/acpi/ls7a.h | 80 ++++++ - 5 files changed, 1287 insertions(+) - create mode 100644 hw/acpi/larch_7a.c - create mode 100644 hw/acpi/ls7a.c - create mode 100644 include/hw/acpi/ls7a.h - -diff --git a/hw/acpi/Kconfig b/hw/acpi/Kconfig -index 622b0b50b7..2f2fb33a7b 100644 ---- a/hw/acpi/Kconfig -+++ b/hw/acpi/Kconfig -@@ -15,6 +15,14 @@ config ACPI_X86_ICH - bool - select ACPI_X86 - -+config ACPI_LOONGARCH -+ bool -+ select ACPI -+ select ACPI_CPU_HOTPLUG -+ select ACPI_MEMORY_HOTPLUG -+ select ACPI_PIIX4 -+ select ACPI_PCIHP -+ - config ACPI_CPU_HOTPLUG - bool - -diff --git a/hw/acpi/larch_7a.c b/hw/acpi/larch_7a.c -new file mode 100644 -index 0000000000..35d4a75266 ---- /dev/null -+++ b/hw/acpi/larch_7a.c -@@ -0,0 +1,600 @@ -+#include "qemu/osdep.h" -+#include "sysemu/sysemu.h" -+#include "sysemu/runstate.h" -+#include "sysemu/reset.h" -+#include "hw/hw.h" -+#include "hw/irq.h" -+#include "hw/acpi/acpi.h" -+#include "hw/acpi/ls7a.h" -+#include "hw/nvram/fw_cfg.h" -+#include "qemu/config-file.h" -+#include "qapi/opts-visitor.h" -+#include "qapi/qapi-events-run-state.h" -+#include "qapi/error.h" -+#include "hw/loongarch/ls7a.h" -+#include "hw/mem/pc-dimm.h" -+#include "hw/mem/nvdimm.h" -+#include "migration/vmstate.h" -+ -+static void ls7a_pm_update_sci_fn(ACPIREGS *regs) -+{ -+ LS7APCIPMRegs *pm = container_of(regs, LS7APCIPMRegs, acpi_regs); -+ acpi_update_sci(&pm->acpi_regs, pm->irq); -+} -+ -+static uint64_t ls7a_gpe_readb(void *opaque, hwaddr addr, unsigned width) -+{ -+ LS7APCIPMRegs *pm = opaque; -+ return acpi_gpe_ioport_readb(&pm->acpi_regs, addr); -+} -+ -+static void ls7a_gpe_writeb(void *opaque, hwaddr addr, uint64_t val, -+ unsigned width) -+{ -+ LS7APCIPMRegs *pm = opaque; -+ acpi_gpe_ioport_writeb(&pm->acpi_regs, addr, val); -+ acpi_update_sci(&pm->acpi_regs, pm->irq); -+} -+ -+static const MemoryRegionOps ls7a_gpe_ops = { -+ .read = ls7a_gpe_readb, -+ .write = ls7a_gpe_writeb, -+ .valid.min_access_size = 1, -+ .valid.max_access_size = 8, -+ .impl.min_access_size = 1, -+ .impl.max_access_size = 1, -+ .endianness = DEVICE_LITTLE_ENDIAN, -+}; -+ -+#define VMSTATE_GPE_ARRAY(_field, _state) \ -+ { \ -+ .name = (stringify(_field)), \ -+ .version_id = 0, \ -+ .num = ACPI_GPE0_LEN, \ -+ .info = &vmstate_info_uint8, \ -+ .size = sizeof(uint8_t), \ -+ .flags = VMS_ARRAY | VMS_POINTER, \ -+ .offset = vmstate_offset_pointer(_state, _field, uint8_t), \ -+ } -+ -+static uint64_t ls7a_reset_readw(void *opaque, hwaddr addr, unsigned width) -+{ -+ return 0; -+} -+ -+static void ls7a_reset_writew(void *opaque, hwaddr addr, uint64_t val, -+ unsigned width) -+{ -+ if (val & 1) { -+ qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); -+ return; -+ } -+} -+ -+static const MemoryRegionOps ls7a_reset_ops = { -+ .read = ls7a_reset_readw, -+ .write = ls7a_reset_writew, -+ .valid.min_access_size = 4, -+ .valid.max_access_size = 4, -+ .endianness = DEVICE_LITTLE_ENDIAN, -+}; -+ -+static bool vmstate_test_use_memhp(void *opaque) -+{ -+ LS7APCIPMRegs *s = opaque; -+ return s->acpi_memory_hotplug.is_enabled; -+} -+ -+static const VMStateDescription vmstate_memhp_state = { -+ .name = "ls7a_pm/memhp", -+ .version_id = 1, -+ .minimum_version_id = 1, -+ .minimum_version_id_old = 1, -+ .needed = vmstate_test_use_memhp, -+ .fields = (VMStateField[]) { -+ VMSTATE_MEMORY_HOTPLUG(acpi_memory_hotplug, LS7APCIPMRegs), -+ VMSTATE_END_OF_LIST() -+ } -+}; -+ -+static const VMStateDescription vmstate_cpuhp_state = { -+ .name = "ls7a_pm/cpuhp", -+ .version_id = 1, -+ .minimum_version_id = 1, -+ .minimum_version_id_old = 1, -+ .fields = (VMStateField[]) { -+ VMSTATE_CPU_HOTPLUG(cpuhp_state, LS7APCIPMRegs), -+ VMSTATE_END_OF_LIST() -+ } -+}; -+ -+const VMStateDescription vmstate_ls7a_pm = { -+ .name = "ls7a_pm", -+ .version_id = 1, -+ .minimum_version_id = 1, -+ .fields = (VMStateField[]) { -+ VMSTATE_UINT16(acpi_regs.pm1.evt.sts, LS7APCIPMRegs), -+ VMSTATE_UINT16(acpi_regs.pm1.evt.en, LS7APCIPMRegs), -+ VMSTATE_UINT16(acpi_regs.pm1.cnt.cnt, LS7APCIPMRegs), -+ VMSTATE_TIMER_PTR(acpi_regs.tmr.timer, LS7APCIPMRegs), -+ VMSTATE_INT64(acpi_regs.tmr.overflow_time, LS7APCIPMRegs), -+ VMSTATE_GPE_ARRAY(acpi_regs.gpe.sts, LS7APCIPMRegs), -+ VMSTATE_GPE_ARRAY(acpi_regs.gpe.en, LS7APCIPMRegs), -+ VMSTATE_END_OF_LIST() -+ }, -+ .subsections = (const VMStateDescription * []) { -+ &vmstate_memhp_state, -+ &vmstate_cpuhp_state, -+ NULL -+ } -+}; -+ -+static inline int64_t acpi_pm_tmr_get_clock(void) -+{ -+ return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), PM_TIMER_FREQUENCY, -+ NANOSECONDS_PER_SECOND); -+} -+ -+static uint32_t acpi_pm_tmr_get(ACPIREGS *ar) -+{ -+ uint32_t d = acpi_pm_tmr_get_clock(); -+ return d & 0xffffff; -+} -+ -+static void acpi_pm_tmr_timer(void *opaque) -+{ -+ ACPIREGS *ar = opaque; -+ qemu_system_wakeup_request(QEMU_WAKEUP_REASON_PMTIMER, NULL); -+ ar->tmr.update_sci(ar); -+} -+ -+static uint64_t acpi_pm_tmr_read(void *opaque, hwaddr addr, unsigned width) -+{ -+ return acpi_pm_tmr_get(opaque); -+} -+ -+static void acpi_pm_tmr_write(void *opaque, hwaddr addr, uint64_t val, -+ unsigned width) -+{ -+ /* nothing */ -+} -+ -+static const MemoryRegionOps acpi_pm_tmr_ops = { -+ .read = acpi_pm_tmr_read, -+ .write = acpi_pm_tmr_write, -+ .valid.min_access_size = 4, -+ .valid.max_access_size = 4, -+ .endianness = DEVICE_LITTLE_ENDIAN, -+}; -+ -+static void ls7a_pm_tmr_init(ACPIREGS *ar, acpi_update_sci_fn update_sci, -+ MemoryRegion *parent, uint64_t offset) -+{ -+ ar->tmr.update_sci = update_sci; -+ ar->tmr.timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, acpi_pm_tmr_timer, ar); -+ memory_region_init_io(&ar->tmr.io, memory_region_owner(parent), -+ &acpi_pm_tmr_ops, ar, "acpi-tmr", 4); -+ memory_region_add_subregion(parent, offset, &ar->tmr.io); -+} -+ -+static void acpi_pm1_evt_write_sts(ACPIREGS *ar, uint16_t val) -+{ -+ uint16_t pm1_sts = acpi_pm1_evt_get_sts(ar); -+ if (pm1_sts & val & ACPI_BITMASK_TIMER_STATUS) { -+ /* if TMRSTS is reset, then compute the new overflow time */ -+ acpi_pm_tmr_calc_overflow_time(ar); -+ } -+ ar->pm1.evt.sts &= ~val; -+} -+ -+static uint64_t acpi_pm_evt_read(void *opaque, hwaddr addr, unsigned width) -+{ -+ ACPIREGS *ar = opaque; -+ switch (addr) { -+ case 0: -+ return acpi_pm1_evt_get_sts(ar); -+ case 4: -+ return ar->pm1.evt.en; -+ default: -+ return 0; -+ } -+} -+ -+static void acpi_pm1_evt_write_en(ACPIREGS *ar, uint16_t val) -+{ -+ ar->pm1.evt.en = val; -+ qemu_system_wakeup_enable(QEMU_WAKEUP_REASON_RTC, -+ val & ACPI_BITMASK_RT_CLOCK_ENABLE); -+ qemu_system_wakeup_enable(QEMU_WAKEUP_REASON_PMTIMER, -+ val & ACPI_BITMASK_TIMER_ENABLE); -+} -+ -+static void acpi_pm_evt_write(void *opaque, hwaddr addr, uint64_t val, -+ unsigned width) -+{ -+ ACPIREGS *ar = opaque; -+ switch (addr) { -+ case 0: -+ acpi_pm1_evt_write_sts(ar, val); -+ ar->pm1.evt.update_sci(ar); -+ break; -+ case 4: -+ acpi_pm1_evt_write_en(ar, val); -+ ar->pm1.evt.update_sci(ar); -+ break; -+ } -+} -+ -+static const MemoryRegionOps acpi_pm_evt_ops = { -+ .read = acpi_pm_evt_read, -+ .write = acpi_pm_evt_write, -+ .valid.min_access_size = 4, -+ .valid.max_access_size = 4, -+ .endianness = DEVICE_LITTLE_ENDIAN, -+}; -+ -+static void ls7a_pm1_evt_init(ACPIREGS *ar, acpi_update_sci_fn update_sci, -+ MemoryRegion *parent, uint64_t offset) -+{ -+ ar->pm1.evt.update_sci = update_sci; -+ memory_region_init_io(&ar->pm1.evt.io, memory_region_owner(parent), -+ &acpi_pm_evt_ops, ar, "acpi-evt", 8); -+ memory_region_add_subregion(parent, offset, &ar->pm1.evt.io); -+} -+ -+static uint64_t acpi_pm_cnt_read(void *opaque, hwaddr addr, unsigned width) -+{ -+ ACPIREGS *ar = opaque; -+ return ar->pm1.cnt.cnt; -+} -+ -+/* ACPI PM1aCNT */ -+static void acpi_pm1_cnt_write(ACPIREGS *ar, uint16_t val) -+{ -+ ar->pm1.cnt.cnt = val & ~(ACPI_BITMASK_SLEEP_ENABLE); -+ if (val & ACPI_BITMASK_SLEEP_ENABLE) { -+ /* change suspend type */ -+ uint16_t sus_typ = (val >> 10) & 7; -+ switch (sus_typ) { -+ /* s3,s4 not support */ -+ case 5: -+ case 6: -+ warn_report("acpi s3,s4 state not support"); -+ break; -+ /* s5: soft off */ -+ case 7: -+ qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); -+ break; -+ default: -+ break; -+ } -+ } -+} -+ -+static void acpi_pm_cnt_write(void *opaque, hwaddr addr, uint64_t val, -+ unsigned width) -+{ -+ acpi_pm1_cnt_write(opaque, val); -+} -+ -+static const MemoryRegionOps acpi_pm_cnt_ops = { -+ .read = acpi_pm_cnt_read, -+ .write = acpi_pm_cnt_write, -+ .valid.min_access_size = 4, -+ .valid.max_access_size = 4, -+ .endianness = DEVICE_LITTLE_ENDIAN, -+}; -+ -+static void acpi_notify_wakeup(Notifier *notifier, void *data) -+{ -+ ACPIREGS *ar = container_of(notifier, ACPIREGS, wakeup); -+ WakeupReason *reason = data; -+ -+ switch (*reason) { -+ case QEMU_WAKEUP_REASON_RTC: -+ ar->pm1.evt.sts |= -+ (ACPI_BITMASK_WAKE_STATUS | ACPI_BITMASK_RT_CLOCK_STATUS); -+ break; -+ case QEMU_WAKEUP_REASON_PMTIMER: -+ ar->pm1.evt.sts |= -+ (ACPI_BITMASK_WAKE_STATUS | ACPI_BITMASK_TIMER_STATUS); -+ break; -+ case QEMU_WAKEUP_REASON_OTHER: -+ /* ACPI_BITMASK_WAKE_STATUS should be set on resume. -+ * Pretend that resume was caused by power button */ -+ ar->pm1.evt.sts |= -+ (ACPI_BITMASK_WAKE_STATUS | ACPI_BITMASK_POWER_BUTTON_STATUS); -+ break; -+ default: -+ break; -+ } -+} -+ -+static void ls7a_pm1_cnt_init(ACPIREGS *ar, MemoryRegion *parent, -+ bool disable_s3, bool disable_s4, uint8_t s4_val, uint64_t offset) -+{ -+ FWCfgState *fw_cfg; -+ -+ ar->pm1.cnt.s4_val = s4_val; -+ ar->wakeup.notify = acpi_notify_wakeup; -+ qemu_register_wakeup_notifier(&ar->wakeup); -+ memory_region_init_io(&ar->pm1.cnt.io, memory_region_owner(parent), -+ &acpi_pm_cnt_ops, ar, "acpi-cnt", 4); -+ memory_region_add_subregion(parent, offset, &ar->pm1.cnt.io); -+ -+ fw_cfg = fw_cfg_find(); -+ if (fw_cfg) { -+ uint8_t suspend[6] = {128, 0, 0, 129, 128, 128}; -+ suspend[3] = 1 | ((!disable_s3) << 7); -+ suspend[4] = s4_val | ((!disable_s4) << 7); -+ fw_cfg_add_file(fw_cfg, "etc/system-states", g_memdup(suspend, 6), 6); -+ } -+} -+ -+static void ls7a_pm_reset(void *opaque) -+{ -+ LS7APCIPMRegs *pm = opaque; -+ -+ acpi_pm1_evt_reset(&pm->acpi_regs); -+ acpi_pm1_cnt_reset(&pm->acpi_regs); -+ acpi_pm_tmr_reset(&pm->acpi_regs); -+ acpi_gpe_reset(&pm->acpi_regs); -+ -+ acpi_update_sci(&pm->acpi_regs, pm->irq); -+} -+ -+static void pm_powerdown_req(Notifier *n, void *opaque) -+{ -+ LS7APCIPMRegs *pm = container_of(n, LS7APCIPMRegs, powerdown_notifier); -+ -+ acpi_pm1_evt_power_down(&pm->acpi_regs); -+} -+ -+void ls7a_pm_init(LS7APCIPMRegs *pm, qemu_irq *pic) -+{ -+ unsigned long base, gpe_len, acpi_aci_irq; -+ -+ /* ls7a board acpi hardware info, including -+ * acpi system io base address -+ * acpi gpe length -+ * acpi sci irq number -+ */ -+ base = ACPI_IO_BASE; -+ gpe_len = ACPI_GPE0_LEN; -+ acpi_aci_irq = ACPI_SCI_IRQ; -+ -+ pm->irq = pic[acpi_aci_irq - 64]; -+ memory_region_init(&pm->iomem, NULL, "ls7a_pm", ACPI_IO_SIZE); -+ memory_region_add_subregion(get_system_memory(), base, &pm->iomem); -+ -+ cpu_hotplug_hw_init(get_system_memory(), NULL, -+ &pm->cpuhp_state, CPU_HOTPLUG_BASE); -+ -+ ls7a_pm_tmr_init(&pm->acpi_regs, ls7a_pm_update_sci_fn, &pm->iomem, LS7A_PM_TMR_BLK); -+ ls7a_pm1_evt_init(&pm->acpi_regs, ls7a_pm_update_sci_fn, &pm->iomem, LS7A_PM_EVT_BLK); -+ ls7a_pm1_cnt_init(&pm->acpi_regs, &pm->iomem, false, false, 2, LS7A_PM_CNT_BLK); -+ -+ acpi_gpe_init(&pm->acpi_regs, gpe_len); -+ memory_region_init_io(&pm->iomem_gpe, NULL, &ls7a_gpe_ops, pm, -+ "acpi-gpe0", gpe_len); -+ memory_region_add_subregion(&pm->iomem, LS7A_GPE0_STS_REG, &pm->iomem_gpe); -+ -+ memory_region_init_io(&pm->iomem_reset, NULL, &ls7a_reset_ops, pm, -+ "acpi-reset", 4); -+ memory_region_add_subregion(&pm->iomem, LS7A_GPE0_RESET_REG, &pm->iomem_reset); -+ -+ qemu_register_reset(ls7a_pm_reset, pm); -+ -+ pm->powerdown_notifier.notify = pm_powerdown_req; -+ qemu_register_powerdown_notifier(&pm->powerdown_notifier); -+ -+ if (pm->acpi_memory_hotplug.is_enabled) { -+ acpi_memory_hotplug_init(get_system_memory(), NULL, -+ &pm->acpi_memory_hotplug, MEMORY_HOTPLUG_BASE); -+ } -+} -+ -+ -+static void ls7a_pm_get_gpe0_blk(Object *obj, Visitor *v, const char *name, -+ void *opaque, Error **errp) -+{ -+ uint64_t value = ACPI_IO_BASE + LS7A_GPE0_STS_REG; -+ -+ visit_type_uint64(v, name, &value, errp); -+} -+ -+static bool ls7a_pm_get_memory_hotplug_support(Object *obj, Error **errp) -+{ -+ LS7APCIState *ls7a = get_ls7a_type(obj); -+ -+ return ls7a->pm.acpi_memory_hotplug.is_enabled; -+} -+ -+static void ls7a_pm_set_memory_hotplug_support(Object *obj, bool value, -+ Error **errp) -+{ -+ LS7APCIState *ls7a = get_ls7a_type(obj); -+ -+ ls7a->pm.acpi_memory_hotplug.is_enabled = value; -+} -+ -+static void ls7a_pm_get_disable_s3(Object *obj, Visitor *v, const char *name, -+ void *opaque, Error **errp) -+{ -+ LS7APCIPMRegs *pm = opaque; -+ uint8_t value = pm->disable_s3; -+ -+ visit_type_uint8(v, name, &value, errp); -+} -+ -+static void ls7a_pm_set_disable_s3(Object *obj, Visitor *v, const char *name, -+ void *opaque, Error **errp) -+{ -+ LS7APCIPMRegs *pm = opaque; -+ Error *local_err = NULL; -+ uint8_t value; -+ -+ visit_type_uint8(v, name, &value, &local_err); -+ if (local_err) { -+ goto out; -+ } -+ pm->disable_s3 = value; -+out: -+ error_propagate(errp, local_err); -+} -+ -+static void ls7a_pm_get_disable_s4(Object *obj, Visitor *v, const char *name, -+ void *opaque, Error **errp) -+{ -+ LS7APCIPMRegs *pm = opaque; -+ uint8_t value = pm->disable_s4; -+ -+ visit_type_uint8(v, name, &value, errp); -+} -+ -+static void ls7a_pm_set_disable_s4(Object *obj, Visitor *v, const char *name, -+ void *opaque, Error **errp) -+{ -+ LS7APCIPMRegs *pm = opaque; -+ Error *local_err = NULL; -+ uint8_t value; -+ -+ visit_type_uint8(v, name, &value, &local_err); -+ if (local_err) { -+ goto out; -+ } -+ pm->disable_s4 = value; -+out: -+ error_propagate(errp, local_err); -+} -+ -+static void ls7a_pm_get_s4_val(Object *obj, Visitor *v, const char *name, -+ void *opaque, Error **errp) -+{ -+ LS7APCIPMRegs *pm = opaque; -+ uint8_t value = pm->s4_val; -+ -+ visit_type_uint8(v, name, &value, errp); -+} -+ -+static void ls7a_pm_set_s4_val(Object *obj, Visitor *v, const char *name, -+ void *opaque, Error **errp) -+{ -+ LS7APCIPMRegs *pm = opaque; -+ Error *local_err = NULL; -+ uint8_t value; -+ -+ visit_type_uint8(v, name, &value, &local_err); -+ if (local_err) { -+ goto out; -+ } -+ pm->s4_val = value; -+out: -+ error_propagate(errp, local_err); -+} -+ -+void ls7a_pm_add_properties(Object *obj, LS7APCIPMRegs *pm, Error **errp) -+{ -+ static const uint32_t gpe0_len = ACPI_GPE0_LEN; -+ pm->acpi_memory_hotplug.is_enabled = true; -+ pm->disable_s3 = 0; -+ pm->disable_s4 = 0; -+ pm->s4_val = 2; -+ -+ object_property_add_uint32_ptr(obj, ACPI_PM_PROP_PM_IO_BASE, -+ &pm->pm_io_base, OBJ_PROP_FLAG_READ); -+ object_property_add(obj, ACPI_PM_PROP_GPE0_BLK, "uint32", -+ ls7a_pm_get_gpe0_blk, -+ NULL, NULL, pm); -+ object_property_add_uint32_ptr(obj, ACPI_PM_PROP_GPE0_BLK_LEN, -+ &gpe0_len, OBJ_PROP_FLAG_READ); -+ object_property_add_bool(obj, "memory-hotplug-support", -+ ls7a_pm_get_memory_hotplug_support, -+ ls7a_pm_set_memory_hotplug_support); -+ object_property_add(obj, ACPI_PM_PROP_S3_DISABLED, "uint8", -+ ls7a_pm_get_disable_s3, -+ ls7a_pm_set_disable_s3, -+ NULL, pm); -+ object_property_add(obj, ACPI_PM_PROP_S4_DISABLED, "uint8", -+ ls7a_pm_get_disable_s4, -+ ls7a_pm_set_disable_s4, -+ NULL, pm); -+ object_property_add(obj, ACPI_PM_PROP_S4_VAL, "uint8", -+ ls7a_pm_get_s4_val, -+ ls7a_pm_set_s4_val, -+ NULL, pm); -+} -+ -+void ls7a_pm_device_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, -+ Error **errp) -+{ -+ LS7APCIState *ls7a = get_ls7a_type(OBJECT(hotplug_dev)); -+ -+ if (ls7a->pm.acpi_memory_hotplug.is_enabled && -+ object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { -+ if (object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM)) { -+ nvdimm_acpi_plug_cb(hotplug_dev, dev); -+ } else { -+ acpi_memory_plug_cb(hotplug_dev, &ls7a->pm.acpi_memory_hotplug, -+ dev, errp); -+ } -+ } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) { -+ acpi_cpu_plug_cb(hotplug_dev, &ls7a->pm.cpuhp_state, dev, errp); -+ } else { -+ error_setg(errp, "acpi: device plug request for not supported device" -+ " type: %s", object_get_typename(OBJECT(dev))); -+ } -+} -+ -+void ls7a_pm_device_unplug_request_cb(HotplugHandler *hotplug_dev, -+ DeviceState *dev, Error **errp) -+{ -+ LS7APCIState *ls7a = get_ls7a_type(OBJECT(hotplug_dev)); -+ -+ if (ls7a->pm.acpi_memory_hotplug.is_enabled && -+ object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { -+ acpi_memory_unplug_request_cb(hotplug_dev, -+ &ls7a->pm.acpi_memory_hotplug, dev, -+ errp); -+ } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) { -+ acpi_cpu_unplug_request_cb(hotplug_dev, &ls7a->pm.cpuhp_state, -+ dev, errp); -+ } else { -+ error_setg(errp, "acpi: device unplug request for not supported device" -+ " type: %s", object_get_typename(OBJECT(dev))); -+ } -+} -+ -+void ls7a_pm_device_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, -+ Error **errp) -+{ -+ LS7APCIState *ls7a = get_ls7a_type(OBJECT(hotplug_dev)); -+ -+ if (ls7a->pm.acpi_memory_hotplug.is_enabled && -+ object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { -+ acpi_memory_unplug_cb(&ls7a->pm.acpi_memory_hotplug, dev, errp); -+ } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) { -+ acpi_cpu_unplug_cb(&ls7a->pm.cpuhp_state, dev, errp); -+ } else { -+ error_setg(errp, "acpi: device unplug for not supported device" -+ " type: %s", object_get_typename(OBJECT(dev))); -+ } -+} -+ -+void ls7a_pm_ospm_status(AcpiDeviceIf *adev, ACPIOSTInfoList ***list) -+{ -+ LS7APCIState *ls7a = get_ls7a_type(OBJECT(adev)); -+ -+ acpi_memory_ospm_status(&ls7a->pm.acpi_memory_hotplug, list); -+ acpi_cpu_ospm_status(&ls7a->pm.cpuhp_state, list); -+} -+ -+void ls7a_send_gpe(AcpiDeviceIf *adev, AcpiEventStatusBits ev) -+{ -+ LS7APCIState *ls7a = get_ls7a_type(OBJECT(adev)); -+ -+ acpi_send_gpe_event(&ls7a->pm.acpi_regs, ls7a->pm.irq, ev); -+} -+ -+ -+ -diff --git a/hw/acpi/ls7a.c b/hw/acpi/ls7a.c -new file mode 100644 -index 0000000000..2de50ccb9c ---- /dev/null -+++ b/hw/acpi/ls7a.c -@@ -0,0 +1,598 @@ -+#include "qemu/osdep.h" -+#include "sysemu/sysemu.h" -+#include "hw/hw.h" -+#include "hw/irq.h" -+#include "hw/acpi/acpi.h" -+#include "hw/acpi/ls7a.h" -+#include "hw/nvram/fw_cfg.h" -+#include "qemu/config-file.h" -+#include "qapi/opts-visitor.h" -+#include "qapi/qapi-events-run-state.h" -+#include "qapi/error.h" -+#include "hw/mips/ls7a.h" -+#include "hw/mem/pc-dimm.h" -+#include "hw/mem/nvdimm.h" -+ -+static void ls7a_pm_update_sci_fn(ACPIREGS *regs) -+{ -+ LS7APCIPMRegs *pm = container_of(regs, LS7APCIPMRegs, acpi_regs); -+ acpi_update_sci(&pm->acpi_regs, pm->irq); -+} -+ -+static uint64_t ls7a_gpe_readb(void *opaque, hwaddr addr, unsigned width) -+{ -+ LS7APCIPMRegs *pm = opaque; -+ return acpi_gpe_ioport_readb(&pm->acpi_regs, addr); -+} -+ -+static void ls7a_gpe_writeb(void *opaque, hwaddr addr, uint64_t val, -+ unsigned width) -+{ -+ LS7APCIPMRegs *pm = opaque; -+ acpi_gpe_ioport_writeb(&pm->acpi_regs, addr, val); -+ acpi_update_sci(&pm->acpi_regs, pm->irq); -+} -+ -+static const MemoryRegionOps ls7a_gpe_ops = { -+ .read = ls7a_gpe_readb, -+ .write = ls7a_gpe_writeb, -+ .valid.min_access_size = 1, -+ .valid.max_access_size = 8, -+ .impl.min_access_size = 1, -+ .impl.max_access_size = 1, -+ .endianness = DEVICE_LITTLE_ENDIAN, -+}; -+ -+#define VMSTATE_GPE_ARRAY(_field, _state) \ -+ { \ -+ .name = (stringify(_field)), \ -+ .version_id = 0, \ -+ .num = ACPI_GPE0_LEN, \ -+ .info = &vmstate_info_uint8, \ -+ .size = sizeof(uint8_t), \ -+ .flags = VMS_ARRAY | VMS_POINTER, \ -+ .offset = vmstate_offset_pointer(_state, _field, uint8_t), \ -+ } -+ -+static uint64_t ls7a_reset_readw(void *opaque, hwaddr addr, unsigned width) -+{ -+ return 0; -+} -+ -+static void ls7a_reset_writew(void *opaque, hwaddr addr, uint64_t val, -+ unsigned width) -+{ -+ if (val & 1) { -+ qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); -+ return; -+ } -+} -+ -+static const MemoryRegionOps ls7a_reset_ops = { -+ .read = ls7a_reset_readw, -+ .write = ls7a_reset_writew, -+ .valid.min_access_size = 4, -+ .valid.max_access_size = 4, -+ .endianness = DEVICE_LITTLE_ENDIAN, -+}; -+ -+static bool vmstate_test_use_memhp(void *opaque) -+{ -+ LS7APCIPMRegs *s = opaque; -+ return s->acpi_memory_hotplug.is_enabled; -+} -+ -+static const VMStateDescription vmstate_memhp_state = { -+ .name = "ls7a_pm/memhp", -+ .version_id = 1, -+ .minimum_version_id = 1, -+ .minimum_version_id_old = 1, -+ .needed = vmstate_test_use_memhp, -+ .fields = (VMStateField[]) { -+ VMSTATE_MEMORY_HOTPLUG(acpi_memory_hotplug, LS7APCIPMRegs), -+ VMSTATE_END_OF_LIST() -+ } -+}; -+ -+static const VMStateDescription vmstate_cpuhp_state = { -+ .name = "ls7a_pm/cpuhp", -+ .version_id = 1, -+ .minimum_version_id = 1, -+ .minimum_version_id_old = 1, -+ .fields = (VMStateField[]) { -+ VMSTATE_CPU_HOTPLUG(cpuhp_state, LS7APCIPMRegs), -+ VMSTATE_END_OF_LIST() -+ } -+}; -+ -+const VMStateDescription vmstate_ls7a_pm = { -+ .name = "ls7a_pm", -+ .version_id = 1, -+ .minimum_version_id = 1, -+ .fields = (VMStateField[]) { -+ VMSTATE_UINT16(acpi_regs.pm1.evt.sts, LS7APCIPMRegs), -+ VMSTATE_UINT16(acpi_regs.pm1.evt.en, LS7APCIPMRegs), -+ VMSTATE_UINT16(acpi_regs.pm1.cnt.cnt, LS7APCIPMRegs), -+ VMSTATE_TIMER_PTR(acpi_regs.tmr.timer, LS7APCIPMRegs), -+ VMSTATE_INT64(acpi_regs.tmr.overflow_time, LS7APCIPMRegs), -+ VMSTATE_GPE_ARRAY(acpi_regs.gpe.sts, LS7APCIPMRegs), -+ VMSTATE_GPE_ARRAY(acpi_regs.gpe.en, LS7APCIPMRegs), -+ VMSTATE_END_OF_LIST() -+ }, -+ .subsections = (const VMStateDescription * []) { -+ &vmstate_memhp_state, -+ &vmstate_cpuhp_state, -+ NULL -+ } -+}; -+ -+static inline int64_t acpi_pm_tmr_get_clock(void) -+{ -+ return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), PM_TIMER_FREQUENCY, -+ NANOSECONDS_PER_SECOND); -+} -+ -+static uint32_t acpi_pm_tmr_get(ACPIREGS *ar) -+{ -+ uint32_t d = acpi_pm_tmr_get_clock(); -+ return d & 0xffffff; -+} -+ -+static void acpi_pm_tmr_timer(void *opaque) -+{ -+ ACPIREGS *ar = opaque; -+ qemu_system_wakeup_request(QEMU_WAKEUP_REASON_PMTIMER, NULL); -+ ar->tmr.update_sci(ar); -+} -+ -+static uint64_t acpi_pm_tmr_read(void *opaque, hwaddr addr, unsigned width) -+{ -+ return acpi_pm_tmr_get(opaque); -+} -+ -+static void acpi_pm_tmr_write(void *opaque, hwaddr addr, uint64_t val, -+ unsigned width) -+{ -+ /* nothing */ -+} -+ -+static const MemoryRegionOps acpi_pm_tmr_ops = { -+ .read = acpi_pm_tmr_read, -+ .write = acpi_pm_tmr_write, -+ .valid.min_access_size = 4, -+ .valid.max_access_size = 4, -+ .endianness = DEVICE_LITTLE_ENDIAN, -+}; -+ -+static void ls7a_pm_tmr_init(ACPIREGS *ar, acpi_update_sci_fn update_sci, -+ MemoryRegion *parent, uint64_t offset) -+{ -+ ar->tmr.update_sci = update_sci; -+ ar->tmr.timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, acpi_pm_tmr_timer, ar); -+ memory_region_init_io(&ar->tmr.io, memory_region_owner(parent), -+ &acpi_pm_tmr_ops, ar, "acpi-tmr", 4); -+ memory_region_add_subregion(parent, offset, &ar->tmr.io); -+} -+ -+static void acpi_pm1_evt_write_sts(ACPIREGS *ar, uint16_t val) -+{ -+ uint16_t pm1_sts = acpi_pm1_evt_get_sts(ar); -+ if (pm1_sts & val & ACPI_BITMASK_TIMER_STATUS) { -+ /* if TMRSTS is reset, then compute the new overflow time */ -+ acpi_pm_tmr_calc_overflow_time(ar); -+ } -+ ar->pm1.evt.sts &= ~val; -+} -+ -+static uint64_t acpi_pm_evt_read(void *opaque, hwaddr addr, unsigned width) -+{ -+ ACPIREGS *ar = opaque; -+ switch (addr) { -+ case 0: -+ return acpi_pm1_evt_get_sts(ar); -+ case 4: -+ return ar->pm1.evt.en; -+ default: -+ return 0; -+ } -+} -+ -+static void acpi_pm1_evt_write_en(ACPIREGS *ar, uint16_t val) -+{ -+ ar->pm1.evt.en = val; -+ qemu_system_wakeup_enable(QEMU_WAKEUP_REASON_RTC, -+ val & ACPI_BITMASK_RT_CLOCK_ENABLE); -+ qemu_system_wakeup_enable(QEMU_WAKEUP_REASON_PMTIMER, -+ val & ACPI_BITMASK_TIMER_ENABLE); -+} -+ -+static void acpi_pm_evt_write(void *opaque, hwaddr addr, uint64_t val, -+ unsigned width) -+{ -+ ACPIREGS *ar = opaque; -+ switch (addr) { -+ case 0: -+ acpi_pm1_evt_write_sts(ar, val); -+ ar->pm1.evt.update_sci(ar); -+ break; -+ case 4: -+ acpi_pm1_evt_write_en(ar, val); -+ ar->pm1.evt.update_sci(ar); -+ break; -+ } -+} -+ -+static const MemoryRegionOps acpi_pm_evt_ops = { -+ .read = acpi_pm_evt_read, -+ .write = acpi_pm_evt_write, -+ .valid.min_access_size = 4, -+ .valid.max_access_size = 4, -+ .endianness = DEVICE_LITTLE_ENDIAN, -+}; -+ -+static void ls7a_pm1_evt_init(ACPIREGS *ar, acpi_update_sci_fn update_sci, -+ MemoryRegion *parent, uint64_t offset) -+{ -+ ar->pm1.evt.update_sci = update_sci; -+ memory_region_init_io(&ar->pm1.evt.io, memory_region_owner(parent), -+ &acpi_pm_evt_ops, ar, "acpi-evt", 8); -+ memory_region_add_subregion(parent, offset, &ar->pm1.evt.io); -+} -+ -+static uint64_t acpi_pm_cnt_read(void *opaque, hwaddr addr, unsigned width) -+{ -+ ACPIREGS *ar = opaque; -+ return ar->pm1.cnt.cnt; -+} -+ -+/* ACPI PM1aCNT */ -+static void acpi_pm1_cnt_write(ACPIREGS *ar, uint16_t val) -+{ -+ ar->pm1.cnt.cnt = val & ~(ACPI_BITMASK_SLEEP_ENABLE); -+ -+ if (val & ACPI_BITMASK_SLEEP_ENABLE) { -+ /* change suspend type */ -+ uint16_t sus_typ = (val >> 10) & 7; -+ switch (sus_typ) { -+ case 0: /* soft power off */ -+ qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); -+ break; -+ case 1: -+ qemu_system_suspend_request(); -+ break; -+ default: -+ if (sus_typ == ar->pm1.cnt.s4_val) { /* S4 request */ -+ qapi_event_send_suspend_disk(); -+ qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); -+ } -+ break; -+ } -+ } -+} -+ -+static void acpi_pm_cnt_write(void *opaque, hwaddr addr, uint64_t val, -+ unsigned width) -+{ -+ acpi_pm1_cnt_write(opaque, val); -+} -+ -+static const MemoryRegionOps acpi_pm_cnt_ops = { -+ .read = acpi_pm_cnt_read, -+ .write = acpi_pm_cnt_write, -+ .valid.min_access_size = 4, -+ .valid.max_access_size = 4, -+ .endianness = DEVICE_LITTLE_ENDIAN, -+}; -+ -+static void acpi_notify_wakeup(Notifier *notifier, void *data) -+{ -+ ACPIREGS *ar = container_of(notifier, ACPIREGS, wakeup); -+ WakeupReason *reason = data; -+ -+ switch (*reason) { -+ case QEMU_WAKEUP_REASON_RTC: -+ ar->pm1.evt.sts |= -+ (ACPI_BITMASK_WAKE_STATUS | ACPI_BITMASK_RT_CLOCK_STATUS); -+ break; -+ case QEMU_WAKEUP_REASON_PMTIMER: -+ ar->pm1.evt.sts |= -+ (ACPI_BITMASK_WAKE_STATUS | ACPI_BITMASK_TIMER_STATUS); -+ break; -+ case QEMU_WAKEUP_REASON_OTHER: -+ /* ACPI_BITMASK_WAKE_STATUS should be set on resume. -+ * Pretend that resume was caused by power button */ -+ ar->pm1.evt.sts |= -+ (ACPI_BITMASK_WAKE_STATUS | ACPI_BITMASK_POWER_BUTTON_STATUS); -+ break; -+ default: -+ break; -+ } -+} -+ -+static void ls7a_pm1_cnt_init(ACPIREGS *ar, MemoryRegion *parent, -+ bool disable_s3, bool disable_s4, uint8_t s4_val, uint64_t offset) -+{ -+ FWCfgState *fw_cfg; -+ -+ ar->pm1.cnt.s4_val = s4_val; -+ ar->wakeup.notify = acpi_notify_wakeup; -+ qemu_register_wakeup_notifier(&ar->wakeup); -+ memory_region_init_io(&ar->pm1.cnt.io, memory_region_owner(parent), -+ &acpi_pm_cnt_ops, ar, "acpi-cnt", 4); -+ memory_region_add_subregion(parent, offset, &ar->pm1.cnt.io); -+ -+ fw_cfg = fw_cfg_find(); -+ if (fw_cfg) { -+ uint8_t suspend[6] = {128, 0, 0, 129, 128, 128}; -+ suspend[3] = 1 | ((!disable_s3) << 7); -+ suspend[4] = s4_val | ((!disable_s4) << 7); -+ fw_cfg_add_file(fw_cfg, "etc/system-states", g_memdup(suspend, 6), 6); -+ } -+} -+ -+static void ls7a_pm_reset(void *opaque) -+{ -+ LS7APCIPMRegs *pm = opaque; -+ -+ acpi_pm1_evt_reset(&pm->acpi_regs); -+ acpi_pm1_cnt_reset(&pm->acpi_regs); -+ acpi_pm_tmr_reset(&pm->acpi_regs); -+ acpi_gpe_reset(&pm->acpi_regs); -+ -+ acpi_update_sci(&pm->acpi_regs, pm->irq); -+} -+ -+static void pm_powerdown_req(Notifier *n, void *opaque) -+{ -+ LS7APCIPMRegs *pm = container_of(n, LS7APCIPMRegs, powerdown_notifier); -+ -+ acpi_pm1_evt_power_down(&pm->acpi_regs); -+} -+ -+void ls7a_pm_init(LS7APCIPMRegs *pm, qemu_irq *pic) -+{ -+ unsigned long base, gpe_len, acpi_aci_irq; -+ -+ /* ls7a board acpi hardware info, including -+ * acpi system io base address -+ * acpi gpe length -+ * acpi sci irq number -+ */ -+ base = ACPI_IO_BASE; -+ gpe_len = ACPI_GPE0_LEN; -+ acpi_aci_irq = ACPI_SCI_IRQ; -+ -+ pm->irq = pic[acpi_aci_irq - 64]; -+ memory_region_init(&pm->iomem, NULL, "ls7a_pm", ACPI_IO_SIZE); -+ memory_region_add_subregion(get_system_memory(), base, &pm->iomem); -+ -+ cpu_hotplug_hw_init(get_system_memory(), NULL, &pm->cpuhp_state, CPU_HOTPLUG_BASE); -+ -+ ls7a_pm_tmr_init(&pm->acpi_regs, ls7a_pm_update_sci_fn, &pm->iomem, LS7A_PM_TMR_BLK); -+ ls7a_pm1_evt_init(&pm->acpi_regs, ls7a_pm_update_sci_fn, &pm->iomem, LS7A_PM_EVT_BLK); -+ ls7a_pm1_cnt_init(&pm->acpi_regs, &pm->iomem, false, false, 2, LS7A_PM_CNT_BLK); -+ -+ acpi_gpe_init(&pm->acpi_regs, gpe_len); -+ memory_region_init_io(&pm->iomem_gpe, NULL, &ls7a_gpe_ops, pm, -+ "acpi-gpe0", gpe_len); -+ memory_region_add_subregion(&pm->iomem, LS7A_GPE0_STS_REG, &pm->iomem_gpe); -+ -+ memory_region_init_io(&pm->iomem_reset, NULL, &ls7a_reset_ops, pm, -+ "acpi-reset", 4); -+ memory_region_add_subregion(&pm->iomem, LS7A_GPE0_RESET_REG, &pm->iomem_reset); -+ -+ qemu_register_reset(ls7a_pm_reset, pm); -+ -+ pm->powerdown_notifier.notify = pm_powerdown_req; -+ qemu_register_powerdown_notifier(&pm->powerdown_notifier); -+ -+ if (pm->acpi_memory_hotplug.is_enabled) { -+ acpi_memory_hotplug_init(get_system_memory(), NULL, -+ &pm->acpi_memory_hotplug, MEMORY_HOTPLUG_BASE); -+ } -+} -+ -+ -+static void ls7a_pm_get_gpe0_blk(Object *obj, Visitor *v, const char *name, -+ void *opaque, Error **errp) -+{ -+ uint64_t value = ACPI_IO_BASE + LS7A_GPE0_STS_REG; -+ -+ visit_type_uint64(v, name, &value, errp); -+} -+ -+static bool ls7a_pm_get_memory_hotplug_support(Object *obj, Error **errp) -+{ -+ LS7APCIState *ls7a = get_ls7a_type(obj); -+ -+ return ls7a->pm.acpi_memory_hotplug.is_enabled; -+} -+ -+static void ls7a_pm_set_memory_hotplug_support(Object *obj, bool value, -+ Error **errp) -+{ -+ LS7APCIState *ls7a = get_ls7a_type(obj); -+ -+ ls7a->pm.acpi_memory_hotplug.is_enabled = value; -+} -+ -+static void ls7a_pm_get_disable_s3(Object *obj, Visitor *v, const char *name, -+ void *opaque, Error **errp) -+{ -+ LS7APCIPMRegs *pm = opaque; -+ uint8_t value = pm->disable_s3; -+ -+ visit_type_uint8(v, name, &value, errp); -+} -+ -+static void ls7a_pm_set_disable_s3(Object *obj, Visitor *v, const char *name, -+ void *opaque, Error **errp) -+{ -+ LS7APCIPMRegs *pm = opaque; -+ Error *local_err = NULL; -+ uint8_t value; -+ -+ visit_type_uint8(v, name, &value, &local_err); -+ if (local_err) { -+ goto out; -+ } -+ pm->disable_s3 = value; -+out: -+ error_propagate(errp, local_err); -+} -+ -+static void ls7a_pm_get_disable_s4(Object *obj, Visitor *v, const char *name, -+ void *opaque, Error **errp) -+{ -+ LS7APCIPMRegs *pm = opaque; -+ uint8_t value = pm->disable_s4; -+ -+ visit_type_uint8(v, name, &value, errp); -+} -+ -+static void ls7a_pm_set_disable_s4(Object *obj, Visitor *v, const char *name, -+ void *opaque, Error **errp) -+{ -+ LS7APCIPMRegs *pm = opaque; -+ Error *local_err = NULL; -+ uint8_t value; -+ -+ visit_type_uint8(v, name, &value, &local_err); -+ if (local_err) { -+ goto out; -+ } -+ pm->disable_s4 = value; -+out: -+ error_propagate(errp, local_err); -+} -+ -+static void ls7a_pm_get_s4_val(Object *obj, Visitor *v, const char *name, -+ void *opaque, Error **errp) -+{ -+ LS7APCIPMRegs *pm = opaque; -+ uint8_t value = pm->s4_val; -+ -+ visit_type_uint8(v, name, &value, errp); -+} -+ -+static void ls7a_pm_set_s4_val(Object *obj, Visitor *v, const char *name, -+ void *opaque, Error **errp) -+{ -+ LS7APCIPMRegs *pm = opaque; -+ Error *local_err = NULL; -+ uint8_t value; -+ -+ visit_type_uint8(v, name, &value, &local_err); -+ if (local_err) { -+ goto out; -+ } -+ pm->s4_val = value; -+out: -+ error_propagate(errp, local_err); -+} -+ -+void ls7a_pm_add_properties(Object *obj, LS7APCIPMRegs *pm, Error **errp) -+{ -+ static const uint32_t gpe0_len = ACPI_GPE0_LEN; -+ pm->acpi_memory_hotplug.is_enabled = true; -+ pm->disable_s3 = 0; -+ pm->disable_s4 = 0; -+ pm->s4_val = 2; -+ -+ object_property_add_uint32_ptr(obj, ACPI_PM_PROP_PM_IO_BASE, -+ &pm->pm_io_base, OBJ_PROP_FLAG_READ); -+ object_property_add(obj, ACPI_PM_PROP_GPE0_BLK, "uint32", -+ ls7a_pm_get_gpe0_blk, -+ NULL, NULL, pm); -+ object_property_add_uint32_ptr(obj, ACPI_PM_PROP_GPE0_BLK_LEN, -+ &gpe0_len, OBJ_PROP_FLAG_READ); -+ object_property_add_bool(obj, "memory-hotplug-support", -+ ls7a_pm_get_memory_hotplug_support, -+ ls7a_pm_set_memory_hotplug_support); -+ object_property_add(obj, ACPI_PM_PROP_S3_DISABLED, "uint8", -+ ls7a_pm_get_disable_s3, -+ ls7a_pm_set_disable_s3, -+ NULL, pm); -+ object_property_add(obj, ACPI_PM_PROP_S4_DISABLED, "uint8", -+ ls7a_pm_get_disable_s4, -+ ls7a_pm_set_disable_s4, -+ NULL, pm); -+ object_property_add(obj, ACPI_PM_PROP_S4_VAL, "uint8", -+ ls7a_pm_get_s4_val, -+ ls7a_pm_set_s4_val, -+ NULL, pm); -+} -+ -+void ls7a_pm_device_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, -+ Error **errp) -+{ -+ LS7APCIState *ls7a = get_ls7a_type(OBJECT(hotplug_dev)); -+ -+ if (ls7a->pm.acpi_memory_hotplug.is_enabled && -+ object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { -+ if (object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM)) { -+ nvdimm_acpi_plug_cb(hotplug_dev, dev); -+ } else { -+ acpi_memory_plug_cb(hotplug_dev, &ls7a->pm.acpi_memory_hotplug, -+ dev, errp); -+ } -+ } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) { -+ acpi_cpu_plug_cb(hotplug_dev, &ls7a->pm.cpuhp_state, dev, errp); -+ } else { -+ error_setg(errp, "acpi: device plug request for not supported device" -+ " type: %s", object_get_typename(OBJECT(dev))); -+ } -+} -+ -+void ls7a_pm_device_unplug_request_cb(HotplugHandler *hotplug_dev, -+ DeviceState *dev, Error **errp) -+{ -+ LS7APCIState *ls7a = get_ls7a_type(OBJECT(hotplug_dev)); -+ -+ if (ls7a->pm.acpi_memory_hotplug.is_enabled && -+ object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { -+ acpi_memory_unplug_request_cb(hotplug_dev, -+ &ls7a->pm.acpi_memory_hotplug, dev, -+ errp); -+ } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) { -+ acpi_cpu_unplug_request_cb(hotplug_dev, &ls7a->pm.cpuhp_state, -+ dev, errp); -+ } else { -+ error_setg(errp, "acpi: device unplug request for not supported device" -+ " type: %s", object_get_typename(OBJECT(dev))); -+ } -+} -+ -+void ls7a_pm_device_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, -+ Error **errp) -+{ -+ LS7APCIState *ls7a = get_ls7a_type(OBJECT(hotplug_dev)); -+ -+ if (ls7a->pm.acpi_memory_hotplug.is_enabled && -+ object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { -+ acpi_memory_unplug_cb(&ls7a->pm.acpi_memory_hotplug, dev, errp); -+ } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) { -+ acpi_cpu_unplug_cb(&ls7a->pm.cpuhp_state, dev, errp); -+ } else { -+ error_setg(errp, "acpi: device unplug for not supported device" -+ " type: %s", object_get_typename(OBJECT(dev))); -+ } -+} -+ -+void ls7a_pm_ospm_status(AcpiDeviceIf *adev, ACPIOSTInfoList ***list) -+{ -+ LS7APCIState *ls7a = get_ls7a_type(OBJECT(adev)); -+ -+ acpi_memory_ospm_status(&ls7a->pm.acpi_memory_hotplug, list); -+ acpi_cpu_ospm_status(&ls7a->pm.cpuhp_state, list); -+} -+ -+void ls7a_send_gpe(AcpiDeviceIf *adev, AcpiEventStatusBits ev) -+{ -+ LS7APCIState *ls7a = get_ls7a_type(OBJECT(adev)); -+ -+ acpi_send_gpe_event(&ls7a->pm.acpi_regs, ls7a->pm.irq, ev); -+} -+ -+ -+ -diff --git a/hw/acpi/meson.build b/hw/acpi/meson.build -index adf6347bc4..5fe4cfa4f1 100644 ---- a/hw/acpi/meson.build -+++ b/hw/acpi/meson.build -@@ -6,6 +6,7 @@ acpi_ss.add(files( - 'core.c', - 'utils.c', - )) -+acpi_ss.add(when: 'CONFIG_ACPI_LOONGARCH', if_true: files('larch_7a.c')) - acpi_ss.add(when: 'CONFIG_ACPI_CPU_HOTPLUG', if_true: files('cpu.c', 'cpu_hotplug.c')) - acpi_ss.add(when: 'CONFIG_ACPI_CPU_HOTPLUG', if_false: files('acpi-cpu-hotplug-stub.c')) - acpi_ss.add(when: 'CONFIG_ACPI_MEMORY_HOTPLUG', if_true: files('memory_hotplug.c')) -diff --git a/include/hw/acpi/ls7a.h b/include/hw/acpi/ls7a.h -new file mode 100644 -index 0000000000..4401515c7b ---- /dev/null -+++ b/include/hw/acpi/ls7a.h -@@ -0,0 +1,80 @@ -+/* -+ * QEMU GMCH/LS7A PCI PM Emulation -+ * -+ * Copyright (c) 2009 Isaku Yamahata -+ * VA Linux Systems Japan K.K. -+ * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2 of the License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library; if not, see -+ */ -+ -+#ifndef HW_ACPI_LS7A_H -+#define HW_ACPI_LS7A_H -+ -+#include "hw/acpi/acpi.h" -+#include "hw/acpi/cpu_hotplug.h" -+#include "hw/acpi/cpu.h" -+#include "hw/acpi/memory_hotplug.h" -+#include "hw/acpi/acpi_dev_interface.h" -+#include "hw/acpi/tco.h" -+ -+#define CPU_HOTPLUG_BASE 0x1e000000 -+#define MEMORY_HOTPLUG_BASE 0x1e00000c -+ -+typedef struct LS7APCIPMRegs { -+ /* -+ * In ls7a spec says that pm1_cnt register is 32bit width and -+ * that the upper 16bits are reserved and unused. -+ * PM1a_CNT_BLK = 2 in FADT so it is defined as uint16_t. -+ */ -+ ACPIREGS acpi_regs; -+ -+ MemoryRegion iomem; -+ MemoryRegion iomem_gpe; -+ MemoryRegion iomem_smi; -+ MemoryRegion iomem_reset; -+ -+ qemu_irq irq; /* SCI */ -+ -+ uint32_t pm_io_base; -+ Notifier powerdown_notifier; -+ -+ bool cpu_hotplug_legacy; -+ AcpiCpuHotplug gpe_cpu; -+ CPUHotplugState cpuhp_state; -+ -+ MemHotplugState acpi_memory_hotplug; -+ -+ uint8_t disable_s3; -+ uint8_t disable_s4; -+ uint8_t s4_val; -+} LS7APCIPMRegs; -+ -+void ls7a_pm_init(LS7APCIPMRegs *ls7a, qemu_irq *sci_irq); -+ -+void ls7a_pm_iospace_update(LS7APCIPMRegs *pm, uint32_t pm_io_base); -+extern const VMStateDescription vmstate_ls7a_pm; -+ -+void ls7a_pm_add_properties(Object *obj, LS7APCIPMRegs *pm, Error **errp); -+ -+void ls7a_pm_device_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, -+ Error **errp); -+void ls7a_pm_device_unplug_request_cb(HotplugHandler *hotplug_dev, -+ DeviceState *dev, Error **errp); -+void ls7a_pm_device_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, -+ Error **errp); -+ -+void ls7a_pm_ospm_status(AcpiDeviceIf *adev, ACPIOSTInfoList ***list); -+ -+void ls7a_send_gpe(AcpiDeviceIf *adev, AcpiEventStatusBits ev); -+#endif /* HW_ACPI_LS7A_H */ --- -2.27.0 - diff --git a/0002-Support-rtc.patch b/0002-Support-rtc.patch deleted file mode 100644 index 082fcdf..0000000 --- a/0002-Support-rtc.patch +++ /dev/null @@ -1,370 +0,0 @@ -From befa5ef7576fdbe2e729203538b066e5f87c3b8f Mon Sep 17 00:00:00 2001 -From: lixianglai -Date: Fri, 19 Aug 2022 23:15:49 -0400 -Subject: [PATCH 2/8] Support rtc. - -Change-Id: Idd50274dd2a6c00b21ec0cd099f8d115ab4fa449 -Signed-off-by: lixianglai ---- - hw/timer/Kconfig | 2 + - hw/timer/ls7a_rtc.c | 325 +++++++++++++++++++++++++++++++++++++++++++ - hw/timer/meson.build | 1 + - 3 files changed, 328 insertions(+) - create mode 100644 hw/timer/ls7a_rtc.c - -diff --git a/hw/timer/Kconfig b/hw/timer/Kconfig -index 010be7ed1f..b395c72d7d 100644 ---- a/hw/timer/Kconfig -+++ b/hw/timer/Kconfig -@@ -60,3 +60,5 @@ config STELLARIS_GPTM - - config AVR_TIMER16 - bool -+config LS7A_RTC -+ bool -diff --git a/hw/timer/ls7a_rtc.c b/hw/timer/ls7a_rtc.c -new file mode 100644 -index 0000000000..756f2fc9ce ---- /dev/null -+++ b/hw/timer/ls7a_rtc.c -@@ -0,0 +1,325 @@ -+#include "qemu/osdep.h" -+#include "hw/sysbus.h" -+#include "hw/irq.h" -+#include "include/hw/register.h" -+#include "qemu/timer.h" -+#include "sysemu/sysemu.h" -+#include "qemu/cutils.h" -+#include "qemu/log.h" -+#include "qemu-common.h" -+#include "migration/vmstate.h" -+ -+#ifdef DEBUG_LS7A_RTC -+#define DPRINTF (fmt, ...) \ -+do { printf("ls7a_rtc: " fmt , ## __VA_ARGS__); } while (0) -+#else -+#define DPRINTF (fmt, ...) do {} while (0) -+#endif -+ -+ -+#define SYS_TOYTRIM 0x20 -+#define SYS_TOYWRITE0 0x24 -+#define SYS_TOYWRITE1 0x28 -+#define SYS_TOYREAD0 0x2C -+#define SYS_TOYREAD1 0x30 -+#define SYS_TOYMATCH0 0x34 -+#define SYS_TOYMATCH1 0x38 -+#define SYS_TOYMATCH2 0x3C -+#define SYS_RTCCTRL 0x40 -+#define SYS_RTCTRIM 0x60 -+#define SYS_RTCWRTIE0 0x64 -+#define SYS_RTCREAD0 0x68 -+#define SYS_RTCMATCH0 0x6C -+#define SYS_RTCMATCH1 0x70 -+#define SYS_RTCMATCH2 0x74 -+ -+/** -+ ** shift bits and filed mask -+ **/ -+#define TOY_MON_MASK 0x3f -+#define TOY_DAY_MASK 0x1f -+#define TOY_HOUR_MASK 0x1f -+#define TOY_MIN_MASK 0x3f -+#define TOY_SEC_MASK 0x3f -+#define TOY_MSEC_MASK 0xf -+ -+#define TOY_MON_SHIFT 26 -+#define TOY_DAY_SHIFT 21 -+#define TOY_HOUR_SHIFT 16 -+#define TOY_MIN_SHIFT 10 -+#define TOY_SEC_SHIFT 4 -+#define TOY_MSEC_SHIFT 0 -+ -+#define TOY_MATCH_YEAR_MASK 0x3f -+#define TOY_MATCH_MON_MASK 0xf -+#define TOY_MATCH_DAY_MASK 0x1f -+#define TOY_MATCH_HOUR_MASK 0x1f -+#define TOY_MATCH_MIN_MASK 0x3f -+#define TOY_MATCH_SEC_MASK 0x3f -+ -+ -+#define TOY_MATCH_YEAR_SHIFT 26 -+#define TOY_MATCH_MON_SHIFT 22 -+#define TOY_MATCH_DAY_SHIFT 17 -+#define TOY_MATCH_HOUR_SHIFT 12 -+#define TOY_MATCH_MIN_SHIFT 6 -+#define TOY_MATCH_SEC_SHIFT 0 -+ -+#define TOY_ENABLE_BIT (1U << 11) -+ -+#define TYPE_LS7A_RTC "ls7a_rtc" -+#define LS7A_RTC(obj) OBJECT_CHECK(LS7A_RTCState, (obj), TYPE_LS7A_RTC) -+ -+typedef struct LS7A_RTCState { -+ SysBusDevice parent_obj; -+ -+ MemoryRegion iomem; -+ QEMUTimer *timer; -+ /* Needed to preserve the tick_count across migration, even if the -+ * absolute value of the rtc_clock is different on the source and -+ * destination. -+ */ -+ int64_t offset; -+ int64_t data; -+ int64_t save_alarm_offset; -+ int tidx; -+ uint32_t toymatch[3]; -+ uint32_t toytrim; -+ uint32_t cntrctl; -+ uint32_t rtctrim; -+ uint32_t rtccount; -+ uint32_t rtcmatch[3]; -+ qemu_irq toy_irq; -+} LS7A_RTCState; -+ -+enum { -+TOYEN = 1UL << 11, -+RTCEN = 1UL << 13, -+}; -+ -+static uint64_t ls7a_rtc_read(void *opaque, hwaddr addr, -+ unsigned size) -+{ -+ LS7A_RTCState *s = (LS7A_RTCState *)opaque; -+ struct tm tm; -+ unsigned int val; -+ -+ val = 0; -+ -+ switch (addr) { -+ case SYS_TOYREAD0: -+ qemu_get_timedate(&tm, s->offset); -+ val = (((tm.tm_mon + 1) & TOY_MON_MASK) << TOY_MON_SHIFT) -+ | (((tm.tm_mday) & TOY_DAY_MASK) << TOY_DAY_SHIFT) -+ | (((tm.tm_hour) & TOY_HOUR_MASK) << TOY_HOUR_SHIFT) -+ | (((tm.tm_min) & TOY_MIN_MASK) << TOY_MIN_SHIFT) -+ | (((tm.tm_sec) & TOY_SEC_MASK) << TOY_SEC_SHIFT) | 0x0; -+ break; -+ case SYS_TOYREAD1: -+ qemu_get_timedate(&tm, s->offset); -+ val = tm.tm_year; -+ break; -+ case SYS_TOYMATCH0: -+ val = s->toymatch[0]; -+ break; -+ case SYS_TOYMATCH1: -+ val = s->toymatch[1]; -+ break; -+ case SYS_TOYMATCH2: -+ val = s->toymatch[2]; -+ break; -+ case SYS_RTCCTRL: -+ val = s->cntrctl; -+ break; -+ case SYS_RTCREAD0: -+ val = s->rtccount; -+ break; -+ case SYS_RTCMATCH0: -+ val = s->rtcmatch[0]; -+ break; -+ case SYS_RTCMATCH1: -+ val = s->rtcmatch[1]; -+ break; -+ case SYS_RTCMATCH2: -+ val = s->rtcmatch[2]; -+ break; -+ default: -+ val = 0; -+ break; -+ } -+ return val; -+} -+ -+ -+static void ls7a_rtc_write(void *opaque, hwaddr addr, -+ uint64_t val, unsigned size) -+{ -+ LS7A_RTCState *s = (LS7A_RTCState *)opaque; -+ struct tm tm; -+ int64_t alarm_offset, year_diff, expire_time; -+ -+ switch (addr) { -+ case SYS_TOYWRITE0: -+ qemu_get_timedate(&tm, s->offset); -+ tm.tm_sec = (val >> TOY_SEC_SHIFT) & TOY_SEC_MASK; -+ tm.tm_min = (val >> TOY_MIN_SHIFT) & TOY_MIN_MASK; -+ tm.tm_hour = (val >> TOY_HOUR_SHIFT) & TOY_HOUR_MASK; -+ tm.tm_mday = ((val >> TOY_DAY_SHIFT) & TOY_DAY_MASK); -+ tm.tm_mon = ((val >> TOY_MON_SHIFT) & TOY_MON_MASK) - 1; -+ s->offset = qemu_timedate_diff(&tm); -+ break; -+ case SYS_TOYWRITE1: -+ qemu_get_timedate(&tm, s->offset); -+ tm.tm_year = val; -+ s->offset = qemu_timedate_diff(&tm); -+ break; -+ case SYS_TOYMATCH0: -+ s->toymatch[0] = val; -+ qemu_get_timedate(&tm, s->offset); -+ tm.tm_sec = (val >> TOY_MATCH_SEC_SHIFT) & TOY_MATCH_SEC_MASK; -+ tm.tm_min = (val >> TOY_MATCH_MIN_SHIFT) & TOY_MATCH_MIN_MASK; -+ tm.tm_hour = ((val >> TOY_MATCH_HOUR_SHIFT) & TOY_MATCH_HOUR_MASK); -+ tm.tm_mday = ((val >> TOY_MATCH_DAY_SHIFT) & TOY_MATCH_DAY_MASK); -+ tm.tm_mon = ((val >> TOY_MATCH_MON_SHIFT) & TOY_MATCH_MON_MASK) - 1; -+ year_diff = ((val >> TOY_MATCH_YEAR_SHIFT) & TOY_MATCH_YEAR_MASK); -+ year_diff = year_diff - (tm.tm_year & TOY_MATCH_YEAR_MASK); -+ tm.tm_year = tm.tm_year + year_diff; -+ alarm_offset = qemu_timedate_diff(&tm) - s->offset; -+ if ((alarm_offset < 0) && (alarm_offset > -5)) { -+ alarm_offset = 0; -+ } -+ expire_time = qemu_clock_get_ms(rtc_clock); -+ expire_time += ((alarm_offset * 1000) + 100); -+ timer_mod(s->timer, expire_time); -+ break; -+ case SYS_TOYMATCH1: -+ s->toymatch[1] = val; -+ break; -+ case SYS_TOYMATCH2: -+ s->toymatch[2] = val; -+ break; -+ case SYS_RTCCTRL: -+ s->cntrctl = val; -+ break; -+ case SYS_RTCWRTIE0: -+ s->rtccount = val; -+ break; -+ case SYS_RTCMATCH0: -+ s->rtcmatch[0] = val; -+ break; -+ case SYS_RTCMATCH1: -+ val = s->rtcmatch[1]; -+ break; -+ case SYS_RTCMATCH2: -+ val = s->rtcmatch[2]; -+ break; -+ default: -+ break; -+ } -+} -+ -+static const MemoryRegionOps ls7a_rtc_ops = { -+ .read = ls7a_rtc_read, -+ .write = ls7a_rtc_write, -+ .endianness = DEVICE_NATIVE_ENDIAN, -+ .valid = { -+ .min_access_size = 4, -+ .max_access_size = 4, -+ }, -+ -+}; -+ -+static void toy_timer(void *opaque) -+{ -+ LS7A_RTCState *s = (LS7A_RTCState *) opaque; -+ -+ if (s->cntrctl & TOY_ENABLE_BIT) { -+ qemu_irq_pulse(s->toy_irq); -+ } -+} -+ -+static void ls7a_rtc_realize(DeviceState *dev, Error **errp) -+{ -+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev); -+ LS7A_RTCState *d = LS7A_RTC(sbd); -+ memory_region_init_io(&d->iomem, NULL, &ls7a_rtc_ops, -+ (void *)d, "ls7a_rtc", 0x100); -+ -+ sysbus_init_irq(sbd, &d->toy_irq); -+ -+ sysbus_init_mmio(sbd, &d->iomem); -+ d->timer = timer_new_ms(rtc_clock, toy_timer, d); -+ timer_mod(d->timer, qemu_clock_get_ms(rtc_clock) + 100); -+ d->offset = 0; -+} -+ -+static int ls7a_rtc_pre_save(void *opaque) -+{ -+ LS7A_RTCState *s = (LS7A_RTCState *)opaque; -+ struct tm tm; -+ int64_t year_diff, value; -+ -+ value = s->toymatch[0]; -+ qemu_get_timedate(&tm, s->offset); -+ tm.tm_sec = (value >> TOY_MATCH_SEC_SHIFT) & TOY_MATCH_SEC_MASK; -+ tm.tm_min = (value >> TOY_MATCH_MIN_SHIFT) & TOY_MATCH_MIN_MASK; -+ tm.tm_hour = ((value >> TOY_MATCH_HOUR_SHIFT) & TOY_MATCH_HOUR_MASK); -+ tm.tm_mday = ((value >> TOY_MATCH_DAY_SHIFT) & TOY_MATCH_DAY_MASK); -+ tm.tm_mon = ((value >> TOY_MATCH_MON_SHIFT) & TOY_MATCH_MON_MASK) - 1; -+ year_diff = ((value >> TOY_MATCH_YEAR_SHIFT) & TOY_MATCH_YEAR_MASK); -+ year_diff = year_diff - (tm.tm_year & TOY_MATCH_YEAR_MASK); -+ tm.tm_year = tm.tm_year + year_diff; -+ s->save_alarm_offset = qemu_timedate_diff(&tm) - s->offset; -+ -+ return 0; -+} -+ -+ -+static int ls7a_rtc_post_load(void *opaque, int version_id) -+{ -+ LS7A_RTCState *s = (LS7A_RTCState *)opaque; -+ int64_t expire_time; -+ -+ expire_time = qemu_clock_get_ms(rtc_clock) + (s->save_alarm_offset * 1000); -+ timer_mod(s->timer, expire_time); -+ -+ return 0; -+} -+ -+static const VMStateDescription vmstate_ls7a_rtc = { -+ .name = "ls7a_rtc", -+ .version_id = 1, -+ .minimum_version_id = 1, -+ .pre_save = ls7a_rtc_pre_save, -+ .post_load = ls7a_rtc_post_load, -+ .fields = (VMStateField[]) { -+ VMSTATE_INT64(offset, LS7A_RTCState), -+ VMSTATE_INT64(save_alarm_offset, LS7A_RTCState), -+ VMSTATE_UINT32(toymatch[0], LS7A_RTCState), -+ VMSTATE_UINT32(cntrctl, LS7A_RTCState), -+ VMSTATE_END_OF_LIST() -+ } -+}; -+ -+ -+static void ls7a_rtc_class_init(ObjectClass *klass, void *data) -+{ -+ DeviceClass *dc = DEVICE_CLASS(klass); -+ dc->vmsd = &vmstate_ls7a_rtc; -+ dc->realize = ls7a_rtc_realize; -+ dc->desc = "ls7a rtc"; -+} -+ -+static const TypeInfo ls7a_rtc_info = { -+ .name = TYPE_LS7A_RTC, -+ .parent = TYPE_SYS_BUS_DEVICE, -+ .instance_size = sizeof(LS7A_RTCState), -+ .class_init = ls7a_rtc_class_init, -+}; -+ -+static void ls7a_rtc_register_types(void) -+{ -+ type_register_static(&ls7a_rtc_info); -+} -+ -+type_init(ls7a_rtc_register_types) -diff --git a/hw/timer/meson.build b/hw/timer/meson.build -index 03092e2ceb..e841a2f6ee 100644 ---- a/hw/timer/meson.build -+++ b/hw/timer/meson.build -@@ -16,6 +16,7 @@ softmmu_ss.add(when: 'CONFIG_EXYNOS4', if_true: files('exynos4210_mct.c')) - softmmu_ss.add(when: 'CONFIG_EXYNOS4', if_true: files('exynos4210_pwm.c')) - softmmu_ss.add(when: 'CONFIG_GRLIB', if_true: files('grlib_gptimer.c')) - softmmu_ss.add(when: 'CONFIG_HPET', if_true: files('hpet.c')) -+softmmu_ss.add(when: 'CONFIG_LS7A_RTC', if_true: files('ls7a_rtc.c')) - softmmu_ss.add(when: 'CONFIG_I8254', if_true: files('i8254_common.c', 'i8254.c')) - softmmu_ss.add(when: 'CONFIG_IMX', if_true: files('imx_epit.c')) - softmmu_ss.add(when: 'CONFIG_IMX', if_true: files('imx_gpt.c')) --- -2.27.0 - diff --git a/0003-Add-loongarch-machine.patch b/0003-Add-loongarch-machine.patch deleted file mode 100644 index c1617ba..0000000 --- a/0003-Add-loongarch-machine.patch +++ /dev/null @@ -1,5752 +0,0 @@ -From 2562504ad867de4a0539c261983c08cd5108bfe4 Mon Sep 17 00:00:00 2001 -From: lixianglai -Date: Fri, 19 Aug 2022 23:39:00 -0400 -Subject: [PATCH 3/8] Add loongarch machine. - -Change-Id: I7e31f874c676b740269945d5e19c6bc836de6a99 -Signed-off-by: lixianglai ---- - hw/loongarch/Kconfig | 17 + - hw/loongarch/acpi-build.c | 783 ++++++++++++ - hw/loongarch/acpi-build.h | 16 + - hw/loongarch/apic.c | 675 +++++++++++ - hw/loongarch/ioapic.c | 422 +++++++ - hw/loongarch/iocsr.c | 219 ++++ - hw/loongarch/ipi.c | 267 +++++ - hw/loongarch/larch_3a.c | 2026 ++++++++++++++++++++++++++++++++ - hw/loongarch/larch_hotplug.c | 355 ++++++ - hw/loongarch/larch_int.c | 91 ++ - hw/loongarch/ls7a_nb.c | 352 ++++++ - hw/loongarch/meson.build | 15 + - include/hw/loongarch/bios.h | 5 + - include/hw/loongarch/cpudevs.h | 53 + - include/hw/loongarch/larch.h | 163 +++ - include/hw/loongarch/ls7a.h | 152 +++ - 16 files changed, 5611 insertions(+) - create mode 100644 hw/loongarch/Kconfig - create mode 100644 hw/loongarch/acpi-build.c - create mode 100644 hw/loongarch/acpi-build.h - create mode 100644 hw/loongarch/apic.c - create mode 100644 hw/loongarch/ioapic.c - create mode 100644 hw/loongarch/iocsr.c - create mode 100644 hw/loongarch/ipi.c - create mode 100644 hw/loongarch/larch_3a.c - create mode 100644 hw/loongarch/larch_hotplug.c - create mode 100644 hw/loongarch/larch_int.c - create mode 100644 hw/loongarch/ls7a_nb.c - create mode 100644 hw/loongarch/meson.build - create mode 100644 include/hw/loongarch/bios.h - create mode 100644 include/hw/loongarch/cpudevs.h - create mode 100644 include/hw/loongarch/larch.h - create mode 100644 include/hw/loongarch/ls7a.h - -diff --git a/hw/loongarch/Kconfig b/hw/loongarch/Kconfig -new file mode 100644 -index 0000000000..3fe2677fda ---- /dev/null -+++ b/hw/loongarch/Kconfig -@@ -0,0 +1,17 @@ -+config LS7A_APIC -+ bool -+ -+config LS7A_RTC -+ bool -+ -+config LOONGSON3A -+ bool -+ -+config MEM_HOTPLUG -+ bool -+ -+config ACPI_LOONGARCH -+ bool -+ -+config E1000E_PCI -+ bool -diff --git a/hw/loongarch/acpi-build.c b/hw/loongarch/acpi-build.c -new file mode 100644 -index 0000000000..6ba637be53 ---- /dev/null -+++ b/hw/loongarch/acpi-build.c -@@ -0,0 +1,783 @@ -+/* Support for generating ACPI tables and passing them to Guests -+ * -+ * Copyright (C) 2008-2010 Kevin O'Connor -+ * Copyright (C) 2006 Fabrice Bellard -+ * Copyright (C) 2013 Red Hat Inc -+ * -+ * Author: Michael S. Tsirkin -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, see . -+ */ -+ -+#include "qemu/osdep.h" -+#include "qapi/error.h" -+#include "qapi/qmp/qnum.h" -+#include "acpi-build.h" -+#include "qemu-common.h" -+#include "qemu/bitmap.h" -+#include "qemu/error-report.h" -+#include "hw/pci/pci.h" -+#include "hw/boards.h" -+#include "hw/core/cpu.h" -+#include "target/loongarch64/cpu.h" -+#include "hw/misc/pvpanic.h" -+#include "hw/timer/hpet.h" -+#include "hw/acpi/acpi-defs.h" -+#include "hw/acpi/acpi.h" -+#include "hw/acpi/cpu.h" -+#include "hw/nvram/fw_cfg.h" -+#include "hw/acpi/bios-linker-loader.h" -+#include "hw/loader.h" -+#include "hw/isa/isa.h" -+#include "hw/block/fdc.h" -+#include "hw/acpi/memory_hotplug.h" -+#include "sysemu/tpm.h" -+#include "hw/acpi/tpm.h" -+#include "hw/acpi/vmgenid.h" -+#include "sysemu/tpm_backend.h" -+#include "hw/rtc/mc146818rtc_regs.h" -+#include "sysemu/numa.h" -+#include "sysemu/runstate.h" -+#include "sysemu/reset.h" -+#include "migration/vmstate.h" -+#include "hw/mem/memory-device.h" -+#include "hw/acpi/utils.h" -+#include "hw/acpi/pci.h" -+/* Supported chipsets: */ -+#include "hw/acpi/aml-build.h" -+#include "hw/loongarch/larch.h" -+#include "hw/loongarch/ls7a.h" -+ -+#include "hw/acpi/ipmi.h" -+#include "hw/acpi/ls7a.h" -+ -+/* These are used to size the ACPI tables for -M pc-i440fx-1.7 and -+ * -M pc-i440fx-2.0. Even if the actual amount of AML generated grows -+ * a little bit, there should be plenty of free space since the DSDT -+ * shrunk by ~1.5k between QEMU 2.0 and QEMU 2.1. -+ */ -+#define ACPI_BUILD_ALIGN_SIZE 0x1000 -+ -+#define ACPI_BUILD_TABLE_SIZE 0x20000 -+ -+/* #define DEBUG_ACPI_BUILD */ -+#ifdef DEBUG_ACPI_BUILD -+#define ACPI_BUILD_DPRINTF(fmt, ...) \ -+ do {printf("ACPI_BUILD: " fmt, ## __VA_ARGS__); } while (0) -+#else -+#define ACPI_BUILD_DPRINTF(fmt, ...) -+#endif -+ -+/* Default IOAPIC ID */ -+#define ACPI_BUILD_IOAPIC_ID 0x0 -+ -+/* PCI fw r3.0 MCFG table. */ -+/* Subtable */ -+ -+typedef struct AcpiMiscInfo { -+ bool is_piix4; -+ bool has_hpet; -+ TPMVersion tpm_version; -+ const unsigned char *dsdt_code; -+ unsigned dsdt_size; -+ uint16_t pvpanic_port; -+ uint16_t applesmc_io_base; -+} AcpiMiscInfo; -+ -+typedef struct AcpiBuildPciBusHotplugState { -+ GArray *device_table; -+ GArray *notify_table; -+ struct AcpiBuildPciBusHotplugState *parent; -+ bool pcihp_bridge_en; -+} AcpiBuildPciBusHotplugState; -+ -+static void init_common_fadt_data(AcpiFadtData *data) -+{ -+ AmlAddressSpace as = AML_AS_SYSTEM_MEMORY; -+ uint64_t base = LS7A_ACPI_REG_BASE; -+ AcpiFadtData fadt = { -+ .rev = 3, -+ .flags = -+ (1 << ACPI_FADT_F_WBINVD) | -+ (1 << ACPI_FADT_F_PROC_C1) | -+ (1 << ACPI_FADT_F_SLP_BUTTON) | -+ (1 << ACPI_FADT_F_TMR_VAL_EXT) | -+ (1 << ACPI_FADT_F_RESET_REG_SUP) , -+ .plvl2_lat = 0xfff /* C2 state not supported */, -+ .plvl3_lat = 0xfff /* C3 state not supported */, -+ .smi_cmd = 0x00, -+ .sci_int = ACPI_SCI_IRQ, -+ .acpi_enable_cmd = 0x00, -+ .acpi_disable_cmd = 0x00, -+ .pm1a_evt = { .space_id = as, .bit_width = 8 * 8, -+ .address = base + LS7A_PM_EVT_BLK }, -+ .pm1a_cnt = { .space_id = as, .bit_width = 4 * 8, -+ .address = base + LS7A_PM_CNT_BLK }, -+ .pm_tmr = { .space_id = as, .bit_width = 4 * 8, -+ .address = base + LS7A_PM_TMR_BLK }, -+ .gpe0_blk = { .space_id = as, .bit_width = 8 * 8, -+ .address = base + LS7A_GPE0_STS_REG}, -+ .reset_reg = { .space_id = as, .bit_width = 4 * 8, -+ .address = base + LS7A_GPE0_RESET_REG}, -+ .reset_val = 0x1, -+ }; -+ *data = fadt; -+} -+ -+static void acpi_align_size(GArray *blob, unsigned align) -+{ -+ /* Align size to multiple of given size. This reduces the chance -+ * we need to change size in the future (breaking cross version migration). -+ */ -+ g_array_set_size(blob, ROUND_UP(acpi_data_len(blob), align)); -+} -+ -+/* FACS */ -+static void -+build_facs(GArray *table_data) -+{ -+ const char *sig = "FACS"; -+ const uint8_t reserved[40] = {}; -+ -+ g_array_append_vals(table_data, sig, 4); /* Signature */ -+ build_append_int_noprefix(table_data, 64, 4); /* Length */ -+ build_append_int_noprefix(table_data, 0, 4); /* Hardware Signature */ -+ build_append_int_noprefix(table_data, 0, 4); /* Firmware Waking Vector */ -+ build_append_int_noprefix(table_data, 0, 4); /* Global Lock */ -+ build_append_int_noprefix(table_data, 0, 4); /* Flags */ -+ g_array_append_vals(table_data, reserved, 40); /* Reserved */ -+} -+ -+void ls7a_madt_cpu_entry(AcpiDeviceIf *adev, int uid, -+ const CPUArchIdList *apic_ids, GArray *entry, bool force_enabled) -+{ -+ uint32_t apic_id = apic_ids->cpus[uid].arch_id; -+ /* Flags – Local APIC Flags */ -+ uint32_t flags = apic_ids->cpus[uid].cpu != NULL || force_enabled ? -+ 1 /* Enabled */ : 0; -+ -+ /* Rev 1.0b, Table 5-13 Processor Local APIC Structure */ -+ build_append_int_noprefix(entry, 0, 1); /* Type */ -+ build_append_int_noprefix(entry, 8, 1); /* Length */ -+ build_append_int_noprefix(entry, uid, 1); /* ACPI Processor ID */ -+ build_append_int_noprefix(entry, apic_id, 1); /* APIC ID */ -+ build_append_int_noprefix(entry, flags, 4); /* Flags */ -+} -+static void build_ioapic(GArray *entry, uint8_t id, uint32_t addr, uint32_t irq) -+{ -+ /* Rev 1.0b, 5.2.8.2 IO APIC */ -+ build_append_int_noprefix(entry, 1, 1); /* Type */ -+ build_append_int_noprefix(entry, 12, 1); /* Length */ -+ build_append_int_noprefix(entry, id, 1); /* IO APIC ID */ -+ build_append_int_noprefix(entry, 0, 1); /* Reserved */ -+ build_append_int_noprefix(entry, addr, 4); /* IO APIC Address */ -+ build_append_int_noprefix(entry, irq, 4); /* System Vector Base */ -+} -+ -+static void -+build_madt(GArray *table_data, BIOSLinker *linker, LoongarchMachineState *lsms) -+{ -+ LoongarchMachineClass *lsmc = LoongarchMACHINE_GET_CLASS(lsms); -+ MachineClass *mc = MACHINE_GET_CLASS(lsms); -+ const CPUArchIdList *apic_ids = mc->possible_cpu_arch_ids(MACHINE(lsms)); -+ AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(lsms->acpi_dev); -+ AcpiDeviceIf *adev = ACPI_DEVICE_IF(lsms->acpi_dev); -+ int i; -+ AcpiTable table = { .sig = "APIC", .rev = 1, .oem_id = lsms->oem_id, -+ .oem_table_id = lsms->oem_table_id}; -+ -+ acpi_table_begin(&table, table_data); -+ -+ /* Local APIC Address */ -+ build_append_int_noprefix(table_data, 0, 4); -+ build_append_int_noprefix(table_data, 1 /* PCAT_COMPAT */, 4); /* Flags */ -+ -+ -+ for (i = 0; i < apic_ids->len; i++) { -+ adevc->madt_cpu(adev, i, apic_ids, table_data, false); -+ } -+ -+ -+ build_ioapic(table_data, ACPI_BUILD_IOAPIC_ID, lsmc->ls7a_ioapic_reg_base, LOONGARCH_PCH_IRQ_BASE); -+ -+ /* Rev 1.0b, 5.2.8.3.3 Local APIC NMI */ -+ build_append_int_noprefix(table_data, 3, 1); /* Type */ -+ build_append_int_noprefix(table_data, 6, 1); /* Length */ -+ /* ACPI Processor ID */ -+ build_append_int_noprefix(table_data, 0xFF /* all processors */, 1); -+ build_append_int_noprefix(table_data, 0, 2); /* Flags */ -+ /* Local APIC INTI# */ -+ build_append_int_noprefix(table_data, 1 /* ACPI_LINT1 */, 1); -+ -+ /* Rev 1.0b, 5.2.8.3.3 Local APIC NMI */ -+ build_append_int_noprefix(table_data, 4, 1); /* Type */ -+ build_append_int_noprefix(table_data, 6, 1); /* Length */ -+ /* ACPI Processor ID */ -+ build_append_int_noprefix(table_data, 0xFF /* all processors */, 1); -+ build_append_int_noprefix(table_data, 0, 2); /* Flags */ -+ /* Local APIC INTI# */ -+ build_append_int_noprefix(table_data, 1 /* ACPI_LINT1 */, 1); -+ -+ -+ acpi_table_end(linker, &table); -+} -+ -+static void -+build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine) -+{ -+ uint64_t i, mem_len, mem_base; -+ MachineClass *mc = MACHINE_GET_CLASS(machine); -+ LoongarchMachineState *lsms = LoongarchMACHINE(machine); -+ const CPUArchIdList *apic_ids = mc->possible_cpu_arch_ids(machine); -+ int nb_numa_nodes = machine->numa_state->num_nodes; -+ NodeInfo *numa_info = machine->numa_state->nodes; -+ AcpiTable table = { .sig = "SRAT", .rev = 1, .oem_id = lsms->oem_id, -+ .oem_table_id = lsms->oem_table_id}; -+ -+ acpi_table_begin(&table, table_data); -+ build_append_int_noprefix(table_data, 1, 4); /* Reserved */ -+ build_append_int_noprefix(table_data, 0, 8); /* Reserved */ -+ -+ for (i = 0; i < apic_ids->len; ++i) { -+ /* 5.2.15.1 Processor Local APIC/SAPIC Affinity Structure */ -+ build_append_int_noprefix(table_data, 0, 1); /* Type */ -+ build_append_int_noprefix(table_data, 16, 1); /* Length */ -+ /* Proximity Domain [7:0] */ -+ build_append_int_noprefix(table_data, apic_ids->cpus[i].props.node_id, 1); -+ build_append_int_noprefix(table_data, apic_ids->cpus[i].arch_id, 1); /* APIC ID */ -+ /* Flags, Table 5-36 */ -+ build_append_int_noprefix(table_data, 1, 4); -+ build_append_int_noprefix(table_data, 0, 1); /* Local SAPIC EID */ -+ /* Proximity Domain [31:8] */ -+ build_append_int_noprefix(table_data, 0, 3); -+ build_append_int_noprefix(table_data, 0, 4); /* Reserved */ -+ } -+ -+ /* node0 */ -+ mem_base = (uint64_t)0; -+ mem_len = 0x10000000; -+ build_srat_memory(table_data, mem_base, mem_len, -+ 0, MEM_AFFINITY_ENABLED); -+ mem_base = 0x90000000; -+ if (!nb_numa_nodes) { -+ mem_len = machine->ram_size - 0x10000000; -+ } else { -+ mem_len = numa_info[0].node_mem - 0x10000000; -+ } -+ -+ build_srat_memory(table_data, mem_base, mem_len, -+ 0, MEM_AFFINITY_ENABLED); -+ mem_base += mem_len; -+ -+ /* node1 ~ nodemax */ -+ for (i = 1; i < nb_numa_nodes; ++i) { -+ mem_len = numa_info[i].node_mem; -+ build_srat_memory(table_data, mem_base, mem_len, -+ i, MEM_AFFINITY_ENABLED); -+ mem_base += mem_len; -+ } -+ -+ if (lsms->hotplug_memory_size) { -+ build_srat_memory(table_data, machine->device_memory->base, -+ lsms->hotplug_memory_size, 0, -+ MEM_AFFINITY_HOTPLUGGABLE | MEM_AFFINITY_ENABLED); -+ } -+ -+ acpi_table_end(linker, &table); -+ -+} -+ -+typedef -+struct AcpiBuildState { -+ /* Copy of table in RAM (for patching). */ -+ MemoryRegion *table_mr; -+ /* Is table patched? */ -+ uint8_t patched; -+ void *rsdp; -+ MemoryRegion *rsdp_mr; -+ MemoryRegion *linker_mr; -+} AcpiBuildState; -+ -+static void build_ls7a_pci0_int(Aml *table) -+{ -+ Aml *sb_scope = aml_scope("_SB"); -+ Aml *pci0_scope = aml_scope("PCI0"); -+ Aml *prt_pkg = aml_varpackage(128); -+ int slot, pin; -+ -+ for (slot = 0; slot < PCI_SLOT_MAX; slot++) { -+ for (pin = 0; pin < PCI_NUM_PINS; pin++) { -+ Aml *pkg = aml_package(4); -+ aml_append(pkg, aml_int((slot << 16) | 0xFFFF)); -+ aml_append(pkg, aml_int(pin)); -+ aml_append(pkg, aml_int(0)); -+ aml_append(pkg, aml_int(LOONGARCH_PCH_IRQ_BASE + 16 + (slot * 4 + pin) % 16)); -+ aml_append(prt_pkg, pkg); -+ } -+ } -+ aml_append(pci0_scope, -+ aml_name_decl("_PRT", prt_pkg)); -+ -+ aml_append(sb_scope, pci0_scope); -+ -+ aml_append(table, sb_scope); -+} -+ -+static void build_dbg_aml(Aml *table) -+{ -+ Aml *field; -+ Aml *method; -+ Aml *while_ctx; -+ Aml *scope = aml_scope("\\"); -+ Aml *buf = aml_local(0); -+ Aml *len = aml_local(1); -+ Aml *idx = aml_local(2); -+ -+ aml_append(scope, -+ aml_operation_region("DBG", AML_SYSTEM_IO, aml_int(0x0402), 0x01)); -+ field = aml_field("DBG", AML_BYTE_ACC, AML_NOLOCK, AML_PRESERVE); -+ aml_append(field, aml_named_field("DBGB", 8)); -+ aml_append(scope, field); -+ -+ method = aml_method("DBUG", 1, AML_NOTSERIALIZED); -+ -+ aml_append(method, aml_to_hexstring(aml_arg(0), buf)); -+ aml_append(method, aml_to_buffer(buf, buf)); -+ aml_append(method, aml_subtract(aml_sizeof(buf), aml_int(1), len)); -+ aml_append(method, aml_store(aml_int(0), idx)); -+ -+ while_ctx = aml_while(aml_lless(idx, len)); -+ aml_append(while_ctx, -+ aml_store(aml_derefof(aml_index(buf, idx)), aml_name("DBGB"))); -+ aml_append(while_ctx, aml_increment(idx)); -+ aml_append(method, while_ctx); -+ -+ aml_append(method, aml_store(aml_int(0x0A), aml_name("DBGB"))); -+ aml_append(scope, method); -+ -+ aml_append(table, scope); -+} -+ -+static Aml *build_ls7a_osc_method(void) -+{ -+ Aml *if_ctx; -+ Aml *if_ctx2; -+ Aml *else_ctx; -+ Aml *method; -+ Aml *a_cwd1 = aml_name("CDW1"); -+ Aml *a_ctrl = aml_local(0); -+ -+ method = aml_method("_OSC", 4, AML_NOTSERIALIZED); -+ aml_append(method, aml_create_dword_field(aml_arg(3), aml_int(0), "CDW1")); -+ -+ if_ctx = aml_if(aml_equal( -+ aml_arg(0), aml_touuid("33DB4D5B-1FF7-401C-9657-7441C03DD766"))); -+ aml_append(if_ctx, aml_create_dword_field(aml_arg(3), aml_int(4), "CDW2")); -+ aml_append(if_ctx, aml_create_dword_field(aml_arg(3), aml_int(8), "CDW3")); -+ -+ aml_append(if_ctx, aml_store(aml_name("CDW3"), a_ctrl)); -+ -+ /* -+ * Always allow native PME, AER (no dependencies) -+ * Allow SHPC (PCI bridges can have SHPC controller) -+ */ -+ aml_append(if_ctx, aml_and(a_ctrl, aml_int(0x1F), a_ctrl)); -+ -+ if_ctx2 = aml_if(aml_lnot(aml_equal(aml_arg(1), aml_int(1)))); -+ /* Unknown revision */ -+ aml_append(if_ctx2, aml_or(a_cwd1, aml_int(0x08), a_cwd1)); -+ aml_append(if_ctx, if_ctx2); -+ -+ if_ctx2 = aml_if(aml_lnot(aml_equal(aml_name("CDW3"), a_ctrl))); -+ /* Capabilities bits were masked */ -+ aml_append(if_ctx2, aml_or(a_cwd1, aml_int(0x10), a_cwd1)); -+ aml_append(if_ctx, if_ctx2); -+ -+ /* Update DWORD3 in the buffer */ -+ aml_append(if_ctx, aml_store(a_ctrl, aml_name("CDW3"))); -+ aml_append(method, if_ctx); -+ -+ else_ctx = aml_else(); -+ /* Unrecognized UUID */ -+ aml_append(else_ctx, aml_or(a_cwd1, aml_int(4), a_cwd1)); -+ aml_append(method, else_ctx); -+ -+ aml_append(method, aml_return(aml_arg(3))); -+ return method; -+} -+ -+static void build_ls7a_rtc_device_aml(Aml *table) -+{ -+ Aml *dev; -+ Aml *crs; -+ uint32_t rtc_irq = LS7A_RTC_IRQ; -+ -+ Aml *scope = aml_scope("_SB"); -+ dev = aml_device("RTC"); -+ aml_append(dev, aml_name_decl("_HID", aml_string("LOON0001"))); -+ crs = aml_resource_template(); -+ aml_append(crs, -+ aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED, -+ AML_NON_CACHEABLE, AML_READ_WRITE, -+ 0, LS7A_RTC_REG_BASE, -+ LS7A_RTC_REG_BASE + LS7A_RTC_LEN - 1, 0, LS7A_RTC_LEN)); -+ aml_append(crs, aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH, -+ AML_EXCLUSIVE, &rtc_irq, 1)); -+ -+ aml_append(dev, aml_name_decl("_CRS", crs)); -+ aml_append(scope, dev); -+ aml_append(table, scope); -+} -+ -+static void build_ls7a_uart_device_aml(Aml *table) -+{ -+ Aml *dev; -+ Aml *crs; -+ Aml *pkg0, *pkg1, *pkg2; -+ uint32_t uart_irq = LS7A_UART_IRQ; -+ -+ Aml *scope = aml_scope("_SB"); -+ dev = aml_device("COMA"); -+ aml_append(dev, aml_name_decl("_HID", aml_string("PNP0501"))); -+ aml_append(dev, aml_name_decl("_UID", aml_int(0))); -+ aml_append(dev, aml_name_decl("_CCA", aml_int(1))); -+ crs = aml_resource_template(); -+ aml_append(crs, -+ aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED, -+ AML_NON_CACHEABLE, AML_READ_WRITE, -+ 0, LS7A_UART_BASE, LS7A_UART_BASE + LS7A_UART_LEN - 1, 0, 0x8)); -+ aml_append(crs, aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH, -+ AML_EXCLUSIVE, &uart_irq, 1)); -+ aml_append(dev, aml_name_decl("_CRS", crs)); -+ pkg0 = aml_package(0x2); -+ aml_append(pkg0, aml_int(0x01F78A40)); -+ aml_append(pkg0, aml_string("clock-frenquency")); -+ pkg1 = aml_package(0x1); -+ aml_append(pkg1, pkg0); -+ pkg2 = aml_package(0x2); -+ aml_append(pkg2, aml_touuid("DAFFD814-6EBA-4D8C-8A91-BC9BBF4AA301")); -+ aml_append(pkg2, pkg1); -+ -+ aml_append(dev, aml_name_decl("_DSD", pkg2)); -+ -+ aml_append(scope, dev); -+ aml_append(table, scope); -+} -+ -+static void -+build_dsdt(GArray *table_data, BIOSLinker *linker, MachineState *machine) -+{ -+ Aml *dsdt, *sb_scope, *scope, *dev, *crs, *pkg; -+ LoongarchMachineState *lsms = LoongarchMACHINE(machine); -+ uint32_t nr_mem = machine->ram_slots; -+ uint64_t base = LS7A_ACPI_REG_BASE; -+ int root_bus_limit = PCIE_MMCFG_BUS(LS_PCIECFG_SIZE - 1); -+ AcpiTable table = { .sig = "DSDT", .rev = 1, .oem_id = lsms->oem_id, -+ .oem_table_id = lsms->oem_table_id}; -+ -+ acpi_table_begin(&table, table_data); -+ dsdt = init_aml_allocator(); -+ -+ build_dbg_aml(dsdt); -+ -+ sb_scope = aml_scope("_SB"); -+ dev = aml_device("PCI0"); -+ aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A08"))); -+ aml_append(dev, aml_name_decl("_CID", aml_eisaid("PNP0A03"))); -+ aml_append(dev, aml_name_decl("_ADR", aml_int(0))); -+ aml_append(dev, aml_name_decl("_BBN", aml_int(0))); -+ aml_append(dev, aml_name_decl("_UID", aml_int(1))); -+ aml_append(dev, build_ls7a_osc_method()); -+ aml_append(sb_scope, dev); -+ aml_append(dsdt, sb_scope); -+ -+ build_ls7a_pci0_int(dsdt); -+ build_ls7a_rtc_device_aml(dsdt); -+ build_ls7a_uart_device_aml(dsdt); -+ -+ if (lsms->acpi_dev) { -+ CPUHotplugFeatures opts = { -+ .acpi_1_compatible = true, .has_legacy_cphp = false -+ }; -+ build_cpus_aml(dsdt, machine, opts, CPU_HOTPLUG_BASE, -+ "\\_SB.PCI0", "\\_GPE._E02"); -+ -+ build_memory_hotplug_aml(dsdt, nr_mem, "\\_SB.PCI0", -+ "\\_GPE._E03", AML_SYSTEM_MEMORY, -+ MEMORY_HOTPLUG_BASE); -+ } -+ -+ scope = aml_scope("_GPE"); -+ { -+ aml_append(scope, aml_name_decl("_HID", aml_string("ACPI0006"))); -+ } -+ aml_append(dsdt, scope); -+ -+ scope = aml_scope("\\_SB.PCI0"); -+ /* build PCI0._CRS */ -+ crs = aml_resource_template(); -+ aml_append(crs, -+ aml_word_bus_number(AML_MIN_FIXED, AML_MAX_FIXED, AML_POS_DECODE, -+ 0x0000, 0x0, root_bus_limit, -+ 0x0000, root_bus_limit + 1)); -+ aml_append(crs, -+ aml_word_io(AML_MIN_FIXED, AML_MAX_FIXED, -+ AML_POS_DECODE, AML_ENTIRE_RANGE, -+ 0x0000, 0x4000, 0xFFFF, 0x0000, 0xC000)); -+ aml_append(crs, -+ aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED, -+ AML_CACHEABLE, AML_READ_WRITE, -+ 0, 0x40000000, 0x7FFFFFFF, 0, 0x40000000)); -+ aml_append(scope, aml_name_decl("_CRS", crs)); -+ -+ /* reserve GPE0 block resources */ -+ dev = aml_device("GPE0"); -+ aml_append(dev, aml_name_decl("_HID", aml_string("PNP0A06"))); -+ aml_append(dev, aml_name_decl("_UID", aml_string("GPE0 resources"))); -+ /* device present, functioning, decoding, not shown in UI */ -+ aml_append(dev, aml_name_decl("_STA", aml_int(0xB))); -+ crs = aml_resource_template(); -+ aml_append(crs, -+ aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED, -+ AML_CACHEABLE, AML_READ_WRITE, -+ 0, base + LS7A_GPE0_STS_REG, -+ base + LS7A_GPE0_STS_REG + 0x3, 0, 0x4)); -+ aml_append(dev, aml_name_decl("_CRS", crs)); -+ aml_append(scope, dev); -+ aml_append(dsdt, scope); -+ -+ scope = aml_scope("\\"); -+ pkg = aml_package(4); -+ aml_append(pkg, aml_int(7)); /* PM1a_CNT.SLP_TYP */ -+ aml_append(pkg, aml_int(7)); /* PM1b_CNT.SLP_TYP not impl. */ -+ aml_append(pkg, aml_int(0)); /* reserved */ -+ aml_append(pkg, aml_int(0)); /* reserved */ -+ aml_append(scope, aml_name_decl("_S5", pkg)); -+ aml_append(dsdt, scope); -+ -+ /* copy AML table into ACPI tables blob and patch header there */ -+ g_array_append_vals(table_data, dsdt->buf->data, dsdt->buf->len); -+ acpi_table_end(linker, &table); -+ free_aml_allocator(); -+} -+ -+ -+static -+void acpi_build(AcpiBuildTables *tables, MachineState *machine) -+{ -+ LoongarchMachineState *lsms = LoongarchMACHINE(machine); -+ GArray *table_offsets; -+ AcpiFadtData fadt_data; -+ unsigned facs, rsdt, fadt, dsdt; -+ uint8_t *u; -+ size_t aml_len = 0; -+ GArray *tables_blob = tables->table_data; -+ -+ init_common_fadt_data(&fadt_data); -+ -+ table_offsets = g_array_new(false, true /* clear */, -+ sizeof(uint32_t)); -+ ACPI_BUILD_DPRINTF("init ACPI tables\n"); -+ -+ bios_linker_loader_alloc(tables->linker, -+ ACPI_BUILD_TABLE_FILE, tables_blob, -+ 64 /* Ensure FACS is aligned */, -+ false /* high memory */); -+ -+ /* -+ * FACS is pointed to by FADT. -+ * We place it first since it's the only table that has alignment -+ * requirements. -+ */ -+ facs = tables_blob->len; -+ build_facs(tables_blob); -+ -+ /* DSDT is pointed to by FADT */ -+ dsdt = tables_blob->len; -+ build_dsdt(tables_blob, tables->linker, MACHINE(qdev_get_machine())); -+ -+ /* Count the size of the DSDT and SSDT, we will need it for legacy -+ * sizing of ACPI tables. -+ */ -+ aml_len += tables_blob->len - dsdt; -+ -+ /* ACPI tables pointed to by RSDT */ -+ fadt = tables_blob->len; -+ acpi_add_table(table_offsets, tables_blob); -+ fadt_data.facs_tbl_offset = &facs; -+ fadt_data.dsdt_tbl_offset = &dsdt; -+ fadt_data.xdsdt_tbl_offset = &dsdt; -+ build_fadt(tables_blob, tables->linker, &fadt_data, -+ "LOONGS", "TP-R00"); -+ aml_len += tables_blob->len - fadt; -+ -+ acpi_add_table(table_offsets, tables_blob); -+ build_madt(tables_blob, tables->linker, lsms); -+ -+ acpi_add_table(table_offsets, tables_blob); -+ build_srat(tables_blob, tables->linker, machine); -+ if (machine->numa_state->have_numa_distance) { -+ acpi_add_table(table_offsets, tables_blob); -+ build_slit(tables_blob, tables->linker, machine, lsms->oem_id, -+ lsms->oem_table_id); -+ } -+ -+ /* Build mcfg */ -+ acpi_add_table(table_offsets, tables_blob); -+ { -+ AcpiMcfgInfo mcfg = { -+ .base = LS_PCIECFG_BASE, -+ .size = LS_PCIECFG_SIZE, -+ }; -+ build_mcfg(tables_blob, tables->linker, &mcfg, lsms->oem_id, -+ lsms->oem_table_id); -+ } -+ -+ /* Add tables supplied by user (if any) */ -+ for (u = acpi_table_first(); u; u = acpi_table_next(u)) { -+ unsigned len = acpi_table_len(u); -+ -+ acpi_add_table(table_offsets, tables_blob); -+ g_array_append_vals(tables_blob, u, len); -+ } -+ -+ /* RSDT is pointed to by RSDP */ -+ rsdt = tables_blob->len; -+ build_rsdt(tables_blob, tables->linker, table_offsets, -+ "LOONGS", "TP-R00"); -+ -+ /* RSDP is in FSEG memory, so allocate it separately */ -+ { -+ AcpiRsdpData rsdp_data = { -+ .revision = 0, -+ .oem_id = lsms->oem_id, -+ .xsdt_tbl_offset = NULL, -+ .rsdt_tbl_offset = &rsdt, -+ }; -+ build_rsdp(tables->rsdp, tables->linker, &rsdp_data); -+ } -+ acpi_align_size(tables->linker->cmd_blob, ACPI_BUILD_ALIGN_SIZE); -+ -+ /* Cleanup memory that's no longer used. */ -+ g_array_free(table_offsets, true); -+} -+ -+static void acpi_ram_update(MemoryRegion *mr, GArray *data) -+{ -+ uint32_t size = acpi_data_len(data); -+ -+ /* Make sure RAM size is correct - -+ in case it got changed e.g. by migration */ -+ memory_region_ram_resize(mr, size, &error_abort); -+ -+ memcpy(memory_region_get_ram_ptr(mr), data->data, size); -+ memory_region_set_dirty(mr, 0, size); -+} -+ -+static void acpi_build_update(void *build_opaque) -+{ -+ AcpiBuildState *build_state = build_opaque; -+ AcpiBuildTables tables; -+ -+ /* No state to update or already patched? Nothing to do. */ -+ if (!build_state || build_state->patched) { -+ return; -+ } -+ build_state->patched = 1; -+ -+ acpi_build_tables_init(&tables); -+ -+ acpi_build(&tables, MACHINE(qdev_get_machine())); -+ -+ acpi_ram_update(build_state->table_mr, tables.table_data); -+ -+ if (build_state->rsdp) { -+ memcpy(build_state->rsdp, tables.rsdp->data, -+ acpi_data_len(tables.rsdp)); -+ } else { -+ acpi_ram_update(build_state->rsdp_mr, tables.rsdp); -+ } -+ -+ acpi_ram_update(build_state->linker_mr, tables.linker->cmd_blob); -+ acpi_build_tables_cleanup(&tables, true); -+} -+ -+static void acpi_build_reset(void *build_opaque) -+{ -+ AcpiBuildState *build_state = build_opaque; -+ build_state->patched = 0; -+} -+ -+static const VMStateDescription vmstate_acpi_build = { -+ .name = "acpi_build", -+ .version_id = 1, -+ .minimum_version_id = 1, -+ .fields = (VMStateField[]) { -+ VMSTATE_UINT8(patched, AcpiBuildState), -+ VMSTATE_END_OF_LIST() -+ }, -+}; -+ -+void loongarch_acpi_setup(void) -+{ -+ LoongarchMachineState *lsms = LoongarchMACHINE(qdev_get_machine()); -+ AcpiBuildTables tables; -+ AcpiBuildState *build_state; -+ -+ if (!lsms->fw_cfg) { -+ ACPI_BUILD_DPRINTF("No fw cfg. Bailing out.\n"); -+ return; -+ } -+ -+ if (!lsms->acpi_build_enabled) { -+ ACPI_BUILD_DPRINTF("ACPI build disabled. Bailing out.\n"); -+ return; -+ } -+ -+ if (!loongarch_is_acpi_enabled(lsms)) { -+ ACPI_BUILD_DPRINTF("ACPI disabled. Bailing out.\n"); -+ return; -+ } -+ -+ build_state = g_malloc0(sizeof *build_state); -+ -+ acpi_build_tables_init(&tables); -+ acpi_build(&tables, MACHINE(lsms)); -+ -+ /* Now expose it all to Guest */ -+ build_state->table_mr = acpi_add_rom_blob(acpi_build_update, build_state, -+ tables.table_data, -+ ACPI_BUILD_TABLE_FILE); -+ assert(build_state->table_mr != NULL); -+ -+ build_state->linker_mr = -+ acpi_add_rom_blob(acpi_build_update, build_state, tables.linker->cmd_blob, -+ "etc/table-loader"); -+ -+ fw_cfg_add_file(lsms->fw_cfg, ACPI_BUILD_TPMLOG_FILE, -+ tables.tcpalog->data, acpi_data_len(tables.tcpalog)); -+ -+ build_state->rsdp = NULL; -+ build_state->rsdp_mr = acpi_add_rom_blob(acpi_build_update, build_state, tables.rsdp, -+ ACPI_BUILD_RSDP_FILE); -+ -+ qemu_register_reset(acpi_build_reset, build_state); -+ acpi_build_reset(build_state); -+ vmstate_register(NULL, 0, &vmstate_acpi_build, build_state); -+ -+ /* Cleanup tables but don't free the memory: we track it -+ * in build_state. -+ */ -+ acpi_build_tables_cleanup(&tables, false); -+} -diff --git a/hw/loongarch/acpi-build.h b/hw/loongarch/acpi-build.h -new file mode 100644 -index 0000000000..a914268bbe ---- /dev/null -+++ b/hw/loongarch/acpi-build.h -@@ -0,0 +1,16 @@ -+ -+#ifndef HW_LARCH_ACPI_BUILD_H -+#define HW_LARCH_ACPI_BUILD_H -+ -+#define EFI_ACPI_OEM_ID "LARCH" -+#define EFI_ACPI_OEM_TABLE_ID "LARCH" /* OEM table id 8 bytes long */ -+#define EFI_ACPI_OEM_REVISION 0x00000002 -+#define EFI_ACPI_CREATOR_ID "LINUX" -+#define EFI_ACPI_CREATOR_REVISION 0x01000013 -+ -+#define ACPI_COMPATIBLE_1_0 0 -+#define ACPI_COMPATIBLE_2_0 1 -+ -+void loongarch_acpi_setup(void); -+ -+#endif -diff --git a/hw/loongarch/apic.c b/hw/loongarch/apic.c -new file mode 100644 -index 0000000000..d6ba2a2cec ---- /dev/null -+++ b/hw/loongarch/apic.c -@@ -0,0 +1,675 @@ -+/* -+ * Loongarch 3A5000 interrupt controller emulation -+ * -+ * Copyright (C) 2020 Lu Zeng -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * for more details. -+ */ -+ -+#include "qemu/osdep.h" -+#include "qapi/error.h" -+#include "hw/boards.h" -+#include "hw/irq.h" -+#include "hw/loongarch/cpudevs.h" -+#include "hw/sysbus.h" -+#include "qemu/host-utils.h" -+#include "qemu/error-report.h" -+#include "sysemu/kvm.h" -+#include "hw/hw.h" -+#include "hw/irq.h" -+#include "target/loongarch64/cpu.h" -+#include "exec/address-spaces.h" -+#include "hw/loongarch/larch.h" -+#include "migration/vmstate.h" -+ -+#define DEBUG_APIC 0 -+ -+#define DPRINTF(fmt, ...) \ -+do { \ -+ if (DEBUG_APIC) { \ -+ fprintf(stderr, "APIC: " fmt , ## __VA_ARGS__); \ -+ } \ -+} while (0) -+ -+#define APIC_OFFSET 0x400 -+#define APIC_BASE (0x1f010000ULL) -+#define EXTIOI_NODETYPE_START (0x4a0 - APIC_OFFSET) -+#define EXTIOI_NODETYPE_END (0x4c0 - APIC_OFFSET) -+#define EXTIOI_IPMAP_START (0x4c0 - APIC_OFFSET) -+#define EXTIOI_IPMAP_END (0x4c8 - APIC_OFFSET) -+#define EXTIOI_ENABLE_START (0x600 - APIC_OFFSET) -+#define EXTIOI_ENABLE_END (0x620 - APIC_OFFSET) -+#define EXTIOI_BOUNCE_START (0x680 - APIC_OFFSET) -+#define EXTIOI_BOUNCE_END (0x6a0 - APIC_OFFSET) -+#define EXTIOI_ISR_START (0x700 - APIC_OFFSET) -+#define EXTIOI_ISR_END (0x720 - APIC_OFFSET) -+#define EXTIOI_COREMAP_START (0xC00 - APIC_OFFSET) -+#define EXTIOI_COREMAP_END (0xD00 - APIC_OFFSET) -+#define EXTIOI_COREISR_START (0x10000) -+#define EXTIOI_COREISR_END (EXTIOI_COREISR_START + 0x10000) -+ -+static int ext_irq_pre_save(void *opaque) -+{ -+#ifdef CONFIG_KVM -+ apicState *apic = opaque; -+ struct loongarch_kvm_irqchip *chip; -+ struct kvm_loongarch_ls3a_extirq_state *kstate; -+ int ret, length, i, vcpuid; -+#endif -+ if (!kvm_irqchip_in_kernel()) { -+ return 0; -+ } -+#ifdef CONFIG_KVM -+ length = sizeof(struct loongarch_kvm_irqchip) + -+ sizeof(struct kvm_loongarch_ls3a_extirq_state); -+ chip = g_malloc0(length); -+ memset(chip, 0, length); -+ chip->chip_id = KVM_IRQCHIP_LS3A_EXTIRQ; -+ chip->len = length; -+ -+ ret = kvm_vm_ioctl(kvm_state, KVM_GET_IRQCHIP, chip); -+ if (ret < 0) { -+ fprintf(stderr, "KVM_GET_IRQCHIP failed: %s\n", strerror(ret)); -+ abort(); -+ } -+ -+ kstate = (struct kvm_loongarch_ls3a_extirq_state *)chip->data; -+ for (i = 0; i < EXTIOI_IRQS_BITMAP_SIZE; i++) { -+ apic->ext_en[i] = kstate->ext_en_r.reg_u8[i]; -+ apic->ext_bounce[i] = kstate->bounce_r.reg_u8[i]; -+ apic->ext_isr[i] = kstate->ext_isr_r.reg_u8[i]; -+ for (vcpuid = 0; vcpuid < MAX_CORES; vcpuid++) { -+ apic->ext_coreisr[vcpuid][i] = kstate->ext_core_isr_r.reg_u8[vcpuid][i]; -+ } -+ } -+ for (i = 0; i < EXTIOI_IRQS_IPMAP_SIZE; i++) { -+ apic->ext_ipmap[i] = kstate->ip_map_r.reg_u8[i]; -+ } -+ for (i = 0; i < EXTIOI_IRQS; i++) { -+ apic->ext_coremap[i] = kstate->core_map_r.reg_u8[i];; -+ } -+ for (i = 0; i < 16; i++) { -+ apic->ext_nodetype[i] = kstate->node_type_r.reg_u16[i]; -+ } -+ g_free(chip); -+#endif -+ return 0; -+} -+ -+static int ext_irq_post_load(void *opaque, int version) -+{ -+#ifdef CONFIG_KVM -+ apicState *apic = opaque; -+ struct loongarch_kvm_irqchip *chip; -+ struct kvm_loongarch_ls3a_extirq_state *kstate; -+ int ret, length, i, vcpuid; -+#endif -+ if (!kvm_irqchip_in_kernel()) { -+ return 0; -+ } -+#ifdef CONFIG_KVM -+ length = sizeof(struct loongarch_kvm_irqchip) + -+ sizeof(struct kvm_loongarch_ls3a_extirq_state); -+ chip = g_malloc0(length); -+ -+ chip->chip_id = KVM_IRQCHIP_LS3A_EXTIRQ; -+ chip->len = length; -+ -+ kstate = (struct kvm_loongarch_ls3a_extirq_state *)chip->data; -+ for (i = 0; i < EXTIOI_IRQS_BITMAP_SIZE; i++) { -+ kstate->ext_en_r.reg_u8[i] = apic->ext_en[i]; -+ kstate->bounce_r.reg_u8[i] = apic->ext_bounce[i]; -+ kstate->ext_isr_r.reg_u8[i] = apic->ext_isr[i]; -+ for (vcpuid = 0; vcpuid < MAX_CORES; vcpuid++) { -+ kstate->ext_core_isr_r.reg_u8[vcpuid][i] = apic->ext_coreisr[vcpuid][i]; -+ } -+ } -+ for (i = 0; i < EXTIOI_IRQS_IPMAP_SIZE; i++) { -+ kstate->ip_map_r.reg_u8[i] = apic->ext_ipmap[i]; -+ } -+ for (i = 0; i < EXTIOI_IRQS; i++) { -+ kstate->core_map_r.reg_u8[i] = apic->ext_coremap[i]; -+ } -+ for (i = 0; i < 16; i++) { -+ kstate->node_type_r.reg_u16[i] = apic->ext_nodetype[i]; -+ } -+ -+ ret = kvm_vm_ioctl(kvm_state, KVM_SET_IRQCHIP, chip); -+ if (ret < 0) { -+ fprintf(stderr, "KVM_SET_IRQCHIP failed: %s\n", strerror(ret)); -+ abort(); -+ } -+ g_free(chip); -+#endif -+ return 0; -+} -+typedef struct nodeApicState { -+ unsigned long addr; -+ int nodeid; -+ apicState *apic; -+} nodeApicState; -+ -+static void ioapic_update_irq(void *opaque, int irq, int level) -+{ -+ apicState *s = opaque; -+ uint8_t ipnum, cpu, cpu_ipnum; -+ unsigned long found1, found2; -+ uint8_t reg_count, reg_bit; -+ -+ reg_count = irq / 32; -+ reg_bit = irq % 32; -+ -+ ipnum = s->ext_sw_ipmap[irq]; -+ cpu = s->ext_sw_coremap[irq]; -+ cpu_ipnum = cpu * LS3A_INTC_IP + ipnum; -+ if (level == 1) { -+ if (test_bit(reg_bit, ((void *)s->ext_en + 0x4 * reg_count)) == false) { -+ return; -+ } -+ -+ if (test_bit(reg_bit, ((void *)s->ext_isr + 0x4 * reg_count)) == false) { -+ return; -+ } -+ bitmap_set(((void *)s->ext_coreisr[cpu] + 0x4 * reg_count), reg_bit, 1); -+ found1 = find_next_bit(((void *)s->ext_ipisr[cpu_ipnum] + 0x4 * reg_count), -+ EXTIOI_IRQS, 0); -+ bitmap_set(((void *)s->ext_ipisr[cpu_ipnum] + 0x4 * reg_count), reg_bit, 1); -+ if (found1 >= EXTIOI_IRQS) { -+ qemu_set_irq(s->parent_irq[cpu][ipnum], level); -+ } -+ } else { -+ bitmap_clear(((void *)s->ext_isr + 0x4 * reg_count), reg_bit, 1); -+ bitmap_clear(((void *)s->ext_coreisr[cpu] + 0x4 * reg_count), reg_bit, 1); -+ found1 = find_next_bit(((void *)s->ext_ipisr[cpu_ipnum] + 0x4 * reg_count), -+ EXTIOI_IRQS, 0); -+ found1 += reg_count * 32; -+ bitmap_clear(((void *)s->ext_ipisr[cpu_ipnum] + 0x4 * reg_count), reg_bit, 1); -+ found2 = find_next_bit(((void *)s->ext_ipisr[cpu_ipnum] + 0x4 * reg_count), -+ EXTIOI_IRQS, 0); -+ if ((found1 < EXTIOI_IRQS) && (found2 >= EXTIOI_IRQS)) { -+ qemu_set_irq(s->parent_irq[cpu][ipnum], level); -+ } -+ } -+} -+ -+static void ioapic_setirq(void *opaque, int irq, int level) -+{ -+ apicState *s = opaque; -+ uint8_t reg_count, reg_bit; -+ -+ reg_count = irq / 32; -+ reg_bit = irq % 32; -+ -+ if (level) { -+ bitmap_set(((void *)s->ext_isr + 0x4 * reg_count), reg_bit, 1); -+ } else { -+ bitmap_clear(((void *)s->ext_isr + 0x4 * reg_count), reg_bit, 1); -+ } -+ -+ ioapic_update_irq(s, irq, level); -+} -+ -+static uint32_t apic_readb(void *opaque, hwaddr addr) -+{ -+ nodeApicState *node; -+ apicState *state; -+ unsigned long off; -+ uint8_t ret; -+ int cpu; -+ -+ node = (nodeApicState *)opaque; -+ state = node->apic; -+ off = addr & 0xfffff; -+ ret = 0; -+ if ((off >= EXTIOI_ENABLE_START) && (off < EXTIOI_ENABLE_END)) { -+ off -= EXTIOI_ENABLE_START; -+ ret = *(uint8_t *)((void *)state->ext_en + off); -+ } else if ((off >= EXTIOI_BOUNCE_START) && (off < EXTIOI_BOUNCE_END)) { -+ off -= EXTIOI_BOUNCE_START; -+ ret = *(uint8_t *)((void *)state->ext_bounce + off); -+ } else if ((off >= EXTIOI_ISR_START) && (off < EXTIOI_ISR_END)) { -+ off -= EXTIOI_ISR_START; -+ ret = *(uint8_t *)((void *)state->ext_isr + off); -+ } else if ((off >= EXTIOI_COREISR_START) && (off < EXTIOI_COREISR_END)) { -+ off -= EXTIOI_COREISR_START; -+ cpu = (off >> 8) & 0xff; -+ ret = *(uint8_t *)((void *)state->ext_coreisr[cpu] + (off & 0x1f)); -+ } else if ((off >= EXTIOI_IPMAP_START) && (off < EXTIOI_IPMAP_END)) { -+ off -= EXTIOI_IPMAP_START; -+ ret = *(uint8_t *)((void *)state->ext_ipmap + off); -+ } else if ((off >= EXTIOI_COREMAP_START) && (off < EXTIOI_COREMAP_END)) { -+ off -= EXTIOI_COREMAP_START; -+ ret = *(uint8_t *)((void *)state->ext_coremap + off); -+ } else if ((off >= EXTIOI_NODETYPE_START) && (off < EXTIOI_NODETYPE_END)) { -+ off -= EXTIOI_NODETYPE_START; -+ ret = *(uint8_t *)((void *)state->ext_nodetype + off); -+ } -+ -+ DPRINTF("readb reg 0x" TARGET_FMT_plx " = %x\n", node->addr + addr, ret); -+ return ret; -+} -+ -+static uint32_t apic_readw(void *opaque, hwaddr addr) -+{ -+ nodeApicState *node; -+ apicState *state; -+ unsigned long off; -+ uint16_t ret; -+ int cpu; -+ -+ node = (nodeApicState *)opaque; -+ state = node->apic; -+ off = addr & 0xfffff; -+ ret = 0; -+ if ((off >= EXTIOI_ENABLE_START) && (off < EXTIOI_ENABLE_END)) { -+ off -= EXTIOI_ENABLE_START; -+ ret = *(uint16_t *)((void *)state->ext_en + off); -+ } else if ((off >= EXTIOI_BOUNCE_START) && (off < EXTIOI_BOUNCE_END)) { -+ off -= EXTIOI_BOUNCE_START; -+ ret = *(uint16_t *)((void *)state->ext_bounce + off); -+ } else if ((off >= EXTIOI_ISR_START) && (off < EXTIOI_ISR_END)) { -+ off -= EXTIOI_ISR_START; -+ ret = *(uint16_t *)((void *)state->ext_isr + off); -+ } else if ((off >= EXTIOI_COREISR_START) && (off < EXTIOI_COREISR_END)) { -+ off -= EXTIOI_COREISR_START; -+ cpu = (off >> 8) & 0xff; -+ ret = *(uint16_t *)((void *)state->ext_coreisr[cpu] + (off & 0x1f)); -+ } else if ((off >= EXTIOI_IPMAP_START) && (off < EXTIOI_IPMAP_END)) { -+ off -= EXTIOI_IPMAP_START; -+ ret = *(uint16_t *)((void *)state->ext_ipmap + off); -+ } else if ((off >= EXTIOI_COREMAP_START) && (off < EXTIOI_COREMAP_END)) { -+ off -= EXTIOI_COREMAP_START; -+ ret = *(uint16_t *)((void *)state->ext_coremap + off); -+ } else if ((off >= EXTIOI_NODETYPE_START) && (off < EXTIOI_NODETYPE_END)) { -+ off -= EXTIOI_NODETYPE_START; -+ ret = *(uint16_t *)((void *)state->ext_nodetype + off); -+ } -+ -+ DPRINTF("readw reg 0x" TARGET_FMT_plx " = %x\n", node->addr + addr, ret); -+ return ret; -+} -+ -+static uint32_t apic_readl(void *opaque, hwaddr addr) -+{ -+ nodeApicState *node; -+ apicState *state; -+ unsigned long off; -+ uint32_t ret; -+ int cpu; -+ -+ node = (nodeApicState *)opaque; -+ state = node->apic; -+ off = addr & 0xfffff; -+ ret = 0; -+ if ((off >= EXTIOI_ENABLE_START) && (off < EXTIOI_ENABLE_END)) { -+ off -= EXTIOI_ENABLE_START; -+ ret = *(uint32_t *)((void *)state->ext_en + off); -+ } else if ((off >= EXTIOI_BOUNCE_START) && (off < EXTIOI_BOUNCE_END)) { -+ off -= EXTIOI_BOUNCE_START; -+ ret = *(uint32_t *)((void *)state->ext_bounce + off); -+ } else if ((off >= EXTIOI_ISR_START) && (off < EXTIOI_ISR_END)) { -+ off -= EXTIOI_ISR_START; -+ ret = *(uint32_t *)((void *)state->ext_isr + off); -+ } else if ((off >= EXTIOI_COREISR_START) && (off < EXTIOI_COREISR_END)) { -+ off -= EXTIOI_COREISR_START; -+ cpu = (off >> 8) & 0xff; -+ ret = *(uint32_t *)((void *)state->ext_coreisr[cpu] + (off & 0x1f)); -+ } else if ((off >= EXTIOI_IPMAP_START) && (off < EXTIOI_IPMAP_END)) { -+ off -= EXTIOI_IPMAP_START; -+ ret = *(uint32_t *)((void *)state->ext_ipmap + off); -+ } else if ((off >= EXTIOI_COREMAP_START) && (off < EXTIOI_COREMAP_END)) { -+ off -= EXTIOI_COREMAP_START; -+ ret = *(uint32_t *)((void *)state->ext_coremap + off); -+ } else if ((off >= EXTIOI_NODETYPE_START) && (off < EXTIOI_NODETYPE_END)) { -+ off -= EXTIOI_NODETYPE_START; -+ ret = *(uint32_t *)((void *)state->ext_nodetype + off); -+ } -+ -+ DPRINTF("readl reg 0x" TARGET_FMT_plx " = %x\n", node->addr + addr, ret); -+ return ret; -+ -+} -+ -+static void apic_writeb(void *opaque, hwaddr addr, uint32_t val) -+{ -+ nodeApicState *node; -+ apicState *state; -+ unsigned long off; -+ uint8_t old; -+ int cpu, i, ipnum, level, mask; -+ -+ node = (nodeApicState *)opaque; -+ state = node->apic; -+ off = addr & 0xfffff; -+ if ((off >= EXTIOI_ENABLE_START) && (off < EXTIOI_ENABLE_END)) { -+ off -= EXTIOI_ENABLE_START; -+ old = *(uint8_t *)((void *)state->ext_en + off); -+ if (old != val) { -+ *(uint8_t *)((void *)state->ext_en + off) = val; -+ old = old ^ val; -+ mask = 0x1; -+ for (i = 0; i < 8; i++) { -+ if (old & mask) { -+ level = !!(val & (0x1 << i)); -+ ioapic_update_irq(state, i + off * 8, level); -+ } -+ mask = mask << 1; -+ } -+ } -+ } else if ((off >= EXTIOI_BOUNCE_START) && (off < EXTIOI_BOUNCE_END)) { -+ off -= EXTIOI_BOUNCE_START; -+ *(uint8_t *)((void *)state->ext_bounce + off) = val; -+ } else if ((off >= EXTIOI_ISR_START) && (off < EXTIOI_ISR_END)) { -+ off -= EXTIOI_ISR_START; -+ old = *(uint8_t *)((void *)state->ext_isr + off); -+ *(uint8_t *)((void *)state->ext_isr + off) = old & ~val; -+ mask = 0x1; -+ for (i = 0; i < 8; i++) { -+ if ((old & mask) && (val & mask)) { -+ ioapic_update_irq(state, i + off * 8, 0); -+ } -+ mask = mask << 1; -+ } -+ } else if ((off >= EXTIOI_COREISR_START) && (off < EXTIOI_COREISR_END)) { -+ off -= EXTIOI_COREISR_START; -+ cpu = (off >> 8) & 0xff; -+ off = off & 0x1f; -+ old = *(uint8_t *)((void *)state->ext_coreisr[cpu] + off); -+ *(uint8_t *)((void *)state->ext_coreisr[cpu] + off) = old & ~val; -+ mask = 0x1; -+ for (i = 0; i < 8; i++) { -+ if ((old & mask) && (val & mask)) { -+ ioapic_update_irq(state, i + off * 8, 0); -+ } -+ mask = mask << 1; -+ } -+ } else if ((off >= EXTIOI_IPMAP_START) && (off < EXTIOI_IPMAP_END)) { -+ off -= EXTIOI_IPMAP_START; -+ val = val & 0xf; -+ *(uint8_t *)((void *)state->ext_ipmap + off) = val; -+ ipnum = 0; -+ for (i = 0; i < 4; i++) { -+ if (val & (0x1 << i)) { -+ ipnum = i; -+ break; -+ } -+ } -+ if (val) { -+ for (i = 0; i < 32; i++) { -+ cpu = off * 32 + i; -+ state->ext_sw_ipmap[cpu] = ipnum; -+ } -+ } -+ } else if ((off >= EXTIOI_COREMAP_START) && (off < EXTIOI_COREMAP_END)) { -+ off -= EXTIOI_COREMAP_START; -+ val = val & 0xff; -+ *(uint8_t *)((void *)state->ext_coremap + off) = val; -+ state->ext_sw_coremap[off] = val; -+ } else if ((off >= EXTIOI_NODETYPE_START) && (off < EXTIOI_NODETYPE_END)) { -+ off -= EXTIOI_NODETYPE_START; -+ *(uint8_t *)((void *)state->ext_nodetype + off) = val; -+ } -+ -+ DPRINTF("writeb reg 0x" TARGET_FMT_plx " = %x\n", node->addr + addr, val); -+} -+ -+static void apic_writew(void *opaque, hwaddr addr, uint32_t val) -+{ -+ nodeApicState *node; -+ apicState *state; -+ unsigned long off; -+ uint16_t old; -+ int cpu, i, level, mask; -+ -+ node = (nodeApicState *)opaque; -+ state = node->apic; -+ off = addr & 0xfffff; -+ if ((off >= EXTIOI_ENABLE_START) && (off < EXTIOI_ENABLE_END)) { -+ off -= EXTIOI_ENABLE_START; -+ old = *(uint16_t *)((void *)state->ext_en + off); -+ if (old != val) { -+ *(uint16_t *)((void *)state->ext_en + off) = val; -+ old = old ^ val; -+ mask = 0x1; -+ for (i = 0; i < 16; i++) { -+ if (old & mask) { -+ level = !!(val & (0x1 << i)); -+ ioapic_update_irq(state, i + off * 8, level); -+ } -+ mask = mask << 1; -+ } -+ } -+ } else if ((off >= EXTIOI_BOUNCE_START) && (off < EXTIOI_BOUNCE_END)) { -+ off -= EXTIOI_BOUNCE_START; -+ *(uint16_t *)((void *)state->ext_bounce + off) = val; -+ } else if ((off >= EXTIOI_ISR_START) && (off < EXTIOI_ISR_END)) { -+ off -= EXTIOI_ISR_START; -+ old = *(uint16_t *)((void *)state->ext_isr + off); -+ *(uint16_t *)((void *)state->ext_isr + off) = old & ~val; -+ mask = 0x1; -+ for (i = 0; i < 16; i++) { -+ if ((old & mask) && (val & mask)) { -+ ioapic_update_irq(state, i + off * 8, 0); -+ } -+ mask = mask << 1; -+ } -+ } else if ((off >= EXTIOI_COREISR_START) && (off < EXTIOI_COREISR_END)) { -+ off -= EXTIOI_COREISR_START; -+ cpu = (off >> 8) & 0xff; -+ off = off & 0x1f; -+ old = *(uint16_t *)((void *)state->ext_coreisr[cpu] + off); -+ *(uint16_t *)((void *)state->ext_coreisr[cpu] + off) = old & ~val; -+ mask = 0x1; -+ for (i = 0; i < 16; i++) { -+ if ((old & mask) && (val & mask)) { -+ ioapic_update_irq(state, i + off * 8, 0); -+ } -+ mask = mask << 1; -+ } -+ } else if ((off >= EXTIOI_IPMAP_START) && (off < EXTIOI_IPMAP_END)) { -+ apic_writeb(opaque, addr, val & 0xff); -+ apic_writeb(opaque, addr + 1, (val >> 8) & 0xff); -+ -+ } else if ((off >= EXTIOI_COREMAP_START) && (off < EXTIOI_COREMAP_END)) { -+ apic_writeb(opaque, addr, val & 0xff); -+ apic_writeb(opaque, addr + 1, (val >> 8) & 0xff); -+ -+ } else if ((off >= EXTIOI_NODETYPE_START) && (off < EXTIOI_NODETYPE_END)) { -+ off -= EXTIOI_NODETYPE_START; -+ *(uint16_t *)((void *)state->ext_nodetype + off) = val; -+ } -+ -+ DPRINTF("writew reg 0x" TARGET_FMT_plx " = %x\n", node->addr + addr, val); -+} -+ -+static void apic_writel(void *opaque, hwaddr addr, uint32_t val) -+{ -+ nodeApicState *node; -+ apicState *state; -+ unsigned long off; -+ uint32_t old; -+ int cpu, i, level, mask; -+ -+ node = (nodeApicState *)opaque; -+ state = node->apic; -+ off = addr & 0xfffff; -+ if ((off >= EXTIOI_ENABLE_START) && (off < EXTIOI_ENABLE_END)) { -+ off -= EXTIOI_ENABLE_START; -+ old = *(uint32_t *)((void *)state->ext_en + off); -+ if (old != val) { -+ *(uint32_t *)((void *)state->ext_en + off) = val; -+ old = old ^ val; -+ mask = 0x1; -+ for (i = 0; i < 32; i++) { -+ if (old & mask) { -+ level = !!(val & (0x1 << i)); -+ ioapic_update_irq(state, i + off * 8, level); -+ } -+ mask = mask << 1; -+ } -+ } -+ } else if ((off >= EXTIOI_BOUNCE_START) && (off < EXTIOI_BOUNCE_END)) { -+ off -= EXTIOI_BOUNCE_START; -+ *(uint32_t *)((void *)state->ext_bounce + off) = val; -+ } else if ((off >= EXTIOI_ISR_START) && (off < EXTIOI_ISR_END)) { -+ off -= EXTIOI_ISR_START; -+ old = *(uint32_t *)((void *)state->ext_isr + off); -+ *(uint32_t *)((void *)state->ext_isr + off) = old & ~val; -+ mask = 0x1; -+ for (i = 0; i < 32; i++) { -+ if ((old & mask) && (val & mask)) { -+ ioapic_update_irq(state, i + off * 8, 0); -+ } -+ mask = mask << 1; -+ } -+ } else if ((off >= EXTIOI_COREISR_START) && (off < EXTIOI_COREISR_END)) { -+ off -= EXTIOI_COREISR_START; -+ cpu = (off >> 8) & 0xff; -+ off = off & 0x1f; -+ old = *(uint32_t *)((void *)state->ext_coreisr[cpu] + off); -+ *(uint32_t *)((void *)state->ext_coreisr[cpu] + off) = old & ~val; -+ mask = 0x1; -+ for (i = 0; i < 32; i++) { -+ if ((old & mask) && (val & mask)) { -+ ioapic_update_irq(state, i + off * 8, 0); -+ } -+ mask = mask << 1; -+ } -+ } else if ((off >= EXTIOI_IPMAP_START) && (off < EXTIOI_IPMAP_END)) { -+ apic_writeb(opaque, addr, val & 0xff); -+ apic_writeb(opaque, addr + 1, (val >> 8) & 0xff); -+ apic_writeb(opaque, addr + 2, (val >> 16) & 0xff); -+ apic_writeb(opaque, addr + 3, (val >> 24) & 0xff); -+ -+ } else if ((off >= EXTIOI_COREMAP_START) && (off < EXTIOI_COREMAP_END)) { -+ apic_writeb(opaque, addr, val & 0xff); -+ apic_writeb(opaque, addr + 1, (val >> 8) & 0xff); -+ apic_writeb(opaque, addr + 2, (val >> 16) & 0xff); -+ apic_writeb(opaque, addr + 3, (val >> 24) & 0xff); -+ -+ } else if ((off >= EXTIOI_NODETYPE_START) && (off < EXTIOI_NODETYPE_END)) { -+ off -= EXTIOI_NODETYPE_START; -+ *(uint32_t *)((void *)state->ext_nodetype + off) = val; -+ } -+ -+ DPRINTF("writel reg 0x" TARGET_FMT_plx " = %x\n", node->addr + addr, val); -+} -+ -+static uint64_t apic_readfn(void *opaque, hwaddr addr, -+ unsigned size) -+{ -+ switch (size) { -+ case 1: -+ return apic_readb(opaque, addr); -+ case 2: -+ return apic_readw(opaque, addr); -+ case 4: -+ return apic_readl(opaque, addr); -+ default: -+ g_assert_not_reached(); -+ } -+} -+ -+static void apic_writefn(void *opaque, hwaddr addr, -+ uint64_t value, unsigned size) -+{ -+ switch (size) { -+ case 1: -+ apic_writeb(opaque, addr, value); -+ break; -+ case 2: -+ apic_writew(opaque, addr, value); -+ break; -+ case 4: -+ apic_writel(opaque, addr, value); -+ break; -+ default: -+ g_assert_not_reached(); -+ } -+} -+ -+static const VMStateDescription vmstate_apic = { -+ .name = "apic", -+ .version_id = 1, -+ .minimum_version_id = 1, -+ .pre_save = ext_irq_pre_save, -+ .post_load = ext_irq_post_load, -+ .fields = (VMStateField[]) { -+ VMSTATE_UINT8_ARRAY(ext_en, apicState, EXTIOI_IRQS_BITMAP_SIZE), -+ VMSTATE_UINT8_ARRAY(ext_bounce, apicState, EXTIOI_IRQS_BITMAP_SIZE), -+ VMSTATE_UINT8_ARRAY(ext_isr, apicState, EXTIOI_IRQS_BITMAP_SIZE), -+ VMSTATE_UINT8_2DARRAY(ext_coreisr, apicState, MAX_CORES, -+ EXTIOI_IRQS_BITMAP_SIZE), -+ VMSTATE_UINT8_ARRAY(ext_ipmap, apicState, EXTIOI_IRQS_IPMAP_SIZE), -+ VMSTATE_UINT8_ARRAY(ext_coremap, apicState, EXTIOI_IRQS), -+ VMSTATE_UINT16_ARRAY(ext_nodetype, apicState, 16), -+ VMSTATE_UINT64(ext_control, apicState), -+ VMSTATE_UINT8_ARRAY(ext_sw_ipmap, apicState, EXTIOI_IRQS), -+ VMSTATE_UINT8_ARRAY(ext_sw_coremap, apicState, EXTIOI_IRQS), -+ VMSTATE_UINT8_2DARRAY(ext_ipisr, apicState, MAX_CORES * LS3A_INTC_IP, -+ EXTIOI_IRQS_BITMAP_SIZE), -+ VMSTATE_END_OF_LIST() -+ } -+}; -+ -+static const MemoryRegionOps apic_ops = { -+ .read = apic_readfn, -+ .write = apic_writefn, -+ .impl.min_access_size = 1, -+ .impl.max_access_size = 4, -+ .valid.min_access_size = 1, -+ .valid.max_access_size = 4, -+ .endianness = DEVICE_NATIVE_ENDIAN, -+}; -+ -+int cpu_init_apic(LoongarchMachineState *ms, CPULOONGARCHState *env, int cpu) -+{ -+ apicState *apic; -+ nodeApicState *node; -+ MemoryRegion *iomem; -+ unsigned long base; -+ int pin; -+ char str[32]; -+ -+ if (ms->apic == NULL) { -+ apic = g_malloc0(sizeof(apicState)); -+ vmstate_register(NULL, 0, &vmstate_apic, apic); -+ apic->irq = qemu_allocate_irqs(ioapic_setirq, apic, EXTIOI_IRQS); -+ -+ for (pin = 0; pin < LS3A_INTC_IP; pin++) { -+ /* cpu_pin[9:2] <= intc_pin[7:0] */ -+ apic->parent_irq[cpu][pin] = env->irq[pin + 2]; -+ } -+ ms->apic = apic; -+ -+ if (cpu == 0) { -+ base = APIC_BASE; -+ node = g_malloc0(sizeof(nodeApicState)); -+ node->apic = ms->apic; -+ node->addr = base; -+ -+ iomem = g_new(MemoryRegion, 1); -+ sprintf(str, "apic%d", cpu); -+ /* extioi addr 0x1f010000~0x1f02ffff */ -+ memory_region_init_io(iomem, NULL, &apic_ops, node, str, 0x20000); -+ memory_region_add_subregion(get_system_memory(), base, iomem); -+ } -+ -+ } else { -+ if (cpu != 0) { -+ for (pin = 0; pin < LS3A_INTC_IP; pin++) { -+ ms->apic->parent_irq[cpu][pin] = env->irq[pin + 2]; -+ } -+ } -+ } -+ return 0; -+} -+ -diff --git a/hw/loongarch/ioapic.c b/hw/loongarch/ioapic.c -new file mode 100644 -index 0000000000..3de0ed88da ---- /dev/null -+++ b/hw/loongarch/ioapic.c -@@ -0,0 +1,422 @@ -+/* -+ * LS7A1000 Northbridge IOAPIC support -+ * -+ * Copyright (c) 2019 Loongarch Technology -+ * Authors: -+ * Zhu Chen -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a copy -+ * of this software and associated documentation files (the "Software"), to deal -+ * in the Software without restriction, including without limitation the rights -+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -+ * copies of the Software, and to permit persons to whom the Software is -+ * furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -+ * THE SOFTWARE. -+ */ -+ -+#include "qemu/osdep.h" -+#include "hw/sysbus.h" -+#include "hw/irq.h" -+#include "qemu/log.h" -+#include "sysemu/kvm.h" -+#include "linux/kvm.h" -+#include "migration/vmstate.h" -+ -+#define DEBUG_LS7A_APIC 0 -+ -+#define DPRINTF(fmt, ...) \ -+do { \ -+ if (DEBUG_LS7A_APIC) { \ -+ fprintf(stderr, "IOAPIC: " fmt , ## __VA_ARGS__); \ -+ } \ -+} while (0) -+ -+#define TYPE_LS7A_APIC "ioapic" -+#define LS7A_APIC(obj) OBJECT_CHECK(LS7AApicState, (obj), TYPE_LS7A_APIC) -+ -+#define LS7A_IOAPIC_ROUTE_ENTRY_OFFSET 0x100 -+#define LS7A_IOAPIC_INT_ID_OFFSET 0x00 -+#define LS7A_INT_ID_VAL 0x7000000UL -+#define LS7A_INT_ID_VER 0x1f0001UL -+#define LS7A_IOAPIC_INT_MASK_OFFSET 0x20 -+#define LS7A_IOAPIC_INT_EDGE_OFFSET 0x60 -+#define LS7A_IOAPIC_INT_CLEAR_OFFSET 0x80 -+#define LS7A_IOAPIC_INT_STATUS_OFFSET 0x3a0 -+#define LS7A_IOAPIC_INT_POL_OFFSET 0x3e0 -+#define LS7A_IOAPIC_HTMSI_EN_OFFSET 0x40 -+#define LS7A_IOAPIC_HTMSI_VEC_OFFSET 0x200 -+#define LS7A_AUTO_CTRL0_OFFSET 0xc0 -+#define LS7A_AUTO_CTRL1_OFFSET 0xe0 -+ -+typedef struct LS7AApicState { -+ SysBusDevice parent_obj; -+ qemu_irq parent_irq[257]; -+ uint64_t int_id; -+ uint64_t int_mask; /*0x020 interrupt mask register*/ -+ uint64_t htmsi_en;/*0x040 1=msi*/ -+ uint64_t intedge; /*0x060 edge=1 level =0*/ -+ uint64_t intclr; /*0x080 for clean edge int,set 1 clean,set 0 is noused*/ -+ uint64_t auto_crtl0; /*0x0c0*/ -+ uint64_t auto_crtl1; /*0x0e0*/ -+ uint8_t route_entry[64]; /*0x100 - 0x140*/ -+ uint8_t htmsi_vector[64]; /*0x200 - 0x240*/ -+ uint64_t intisr_chip0; /*0x300*/ -+ uint64_t intisr_chip1;/*0x320*/ -+ uint64_t last_intirr; /* edge detection */ -+ uint64_t intirr; /* 0x380 interrupt request register */ -+ uint64_t intisr; /* 0x3a0 interrupt service register */ -+ uint64_t int_polarity; /*0x3e0 interrupt level polarity -+ selection register 0 for high level tirgger*/ -+ MemoryRegion iomem; -+} LS7AApicState; -+ -+static void update_irq(LS7AApicState *s) -+{ -+ int i; -+ if ((s->intirr & (~s->int_mask)) & (~s->htmsi_en)) { -+ DPRINTF("7a update irqline up\n"); -+ s->intisr = (s->intirr & (~s->int_mask) & (~s->htmsi_en)); -+ qemu_set_irq(s->parent_irq[256], 1); -+ } else { -+ DPRINTF("7a update irqline down\n"); -+ s->intisr &= (~s->htmsi_en); -+ qemu_set_irq(s->parent_irq[256], 0); -+ } -+ if (s->htmsi_en) { -+ for (i = 0; i < 64; i++) { -+ if ((((~s->intisr) & s->intirr) & s->htmsi_en) & (1ULL << i)) { -+ s->intisr |= 1ULL << i; -+ qemu_set_irq(s->parent_irq[s->htmsi_vector[i]], 1); -+ } else if (((~(s->intisr | s->intirr)) & s->htmsi_en) & -+ (1ULL << i)) { -+ qemu_set_irq(s->parent_irq[s->htmsi_vector[i]], 0); -+ } -+ } -+ } -+} -+ -+static void irq_handler(void *opaque, int irq, int level) -+{ -+ LS7AApicState *s = opaque; -+ -+ assert(irq < 64); -+ uint64_t mask = 1ULL << irq; -+ DPRINTF("------ %s irq %d %d\n", __func__, irq, level); -+ -+ if (s->intedge & mask) { -+ /* edge triggered */ -+ /*TODO*/ -+ } else { -+ /* level triggered */ -+ if (level) { -+ s->intirr |= mask; -+ } else { -+ s->intirr &= ~mask; -+ } -+ -+ } -+ update_irq(s); -+ -+} -+ -+static uint64_t ls7a_apic_reg_read(void *opaque, hwaddr addr, unsigned size) -+{ -+ LS7AApicState *a = opaque; -+ uint64_t val = 0; -+ uint64_t offset; -+ int64_t offset_tmp; -+ offset = addr & 0xfff; -+ if (8 == size) { -+ switch (offset) { -+ case LS7A_IOAPIC_INT_ID_OFFSET: -+ val = LS7A_INT_ID_VER; -+ val = (val << 32) + LS7A_INT_ID_VAL; -+ break; -+ case LS7A_IOAPIC_INT_MASK_OFFSET: -+ val = a->int_mask; -+ break; -+ case LS7A_IOAPIC_INT_STATUS_OFFSET: -+ val = a->intisr & (~a->int_mask); -+ break; -+ case LS7A_IOAPIC_INT_EDGE_OFFSET: -+ val = a->intedge; -+ break; -+ case LS7A_IOAPIC_INT_POL_OFFSET: -+ val = a->int_polarity; -+ break; -+ case LS7A_IOAPIC_HTMSI_EN_OFFSET: -+ val = a->htmsi_en; -+ break; -+ case LS7A_AUTO_CTRL0_OFFSET: -+ case LS7A_AUTO_CTRL1_OFFSET: -+ break; -+ default: -+ break; -+ } -+ } else if (1 == size) { -+ if (offset >= LS7A_IOAPIC_HTMSI_VEC_OFFSET) { -+ offset_tmp = offset - LS7A_IOAPIC_HTMSI_VEC_OFFSET; -+ if (offset_tmp >= 0 && offset_tmp < 64) { -+ val = a->htmsi_vector[offset_tmp]; -+ } -+ } else if (offset >= LS7A_IOAPIC_ROUTE_ENTRY_OFFSET) { -+ offset_tmp = offset - LS7A_IOAPIC_ROUTE_ENTRY_OFFSET; -+ if (offset_tmp >= 0 && offset_tmp < 64) { -+ val = a->route_entry[offset_tmp]; -+ DPRINTF("addr %lx val %lx\n", addr, val); -+ } -+ } -+ } -+ DPRINTF(TARGET_FMT_plx" val %lx\n", addr, val); -+ return val; -+} -+ -+static void ls7a_apic_reg_write(void *opaque, hwaddr addr, uint64_t data, unsigned size) -+{ -+ LS7AApicState *a = opaque; -+ int64_t offset_tmp; -+ uint64_t offset; -+ offset = addr & 0xfff; -+ DPRINTF(TARGET_FMT_plx" size %d val %lx\n", addr, size, data); -+ if (8 == size) { -+ switch (offset) { -+ case LS7A_IOAPIC_INT_MASK_OFFSET: -+ a->int_mask = data; -+ update_irq(a); -+ break; -+ case LS7A_IOAPIC_INT_STATUS_OFFSET: -+ a->intisr = data; -+ break; -+ case LS7A_IOAPIC_INT_EDGE_OFFSET: -+ a->intedge = data; -+ break; -+ case LS7A_IOAPIC_INT_CLEAR_OFFSET: -+ a->intisr &= (~data); -+ update_irq(a); -+ break; -+ case LS7A_IOAPIC_INT_POL_OFFSET: -+ a->int_polarity = data; -+ break; -+ case LS7A_IOAPIC_HTMSI_EN_OFFSET: -+ a->htmsi_en = data; -+ break; -+ case LS7A_AUTO_CTRL0_OFFSET: -+ case LS7A_AUTO_CTRL1_OFFSET: -+ break; -+ default: -+ break; -+ } -+ } else if (1 == size) { -+ if (offset >= LS7A_IOAPIC_HTMSI_VEC_OFFSET) { -+ offset_tmp = offset - LS7A_IOAPIC_HTMSI_VEC_OFFSET; -+ if (offset_tmp >= 0 && offset_tmp < 64) { -+ a->htmsi_vector[offset_tmp] = (uint8_t)(data & 0xff); -+ } -+ } else if (offset >= LS7A_IOAPIC_ROUTE_ENTRY_OFFSET) { -+ offset_tmp = offset - LS7A_IOAPIC_ROUTE_ENTRY_OFFSET; -+ if (offset_tmp >= 0 && offset_tmp < 64) { -+ a->route_entry[offset_tmp] = (uint8_t)(data & 0xff); -+ } -+ } -+ } -+} -+ -+static const MemoryRegionOps ls7a_apic_ops = { -+ .read = ls7a_apic_reg_read, -+ .write = ls7a_apic_reg_write, -+ .valid = { -+ .min_access_size = 1, -+ .max_access_size = 8, -+ }, -+ .impl = { -+ .min_access_size = 1, -+ .max_access_size = 8, -+ }, -+ .endianness = DEVICE_NATIVE_ENDIAN, -+}; -+ -+static int kvm_ls7a_pre_save(void *opaque) -+{ -+#ifdef CONFIG_KVM -+ LS7AApicState *s = opaque; -+ struct loongarch_kvm_irqchip *chip; -+ struct ls7a_ioapic_state *state; -+ int ret, i, length; -+ -+ if (!kvm_irqchip_in_kernel()) { -+ return 0; -+ } -+ -+ length = sizeof(struct loongarch_kvm_irqchip) + sizeof(struct ls7a_ioapic_state); -+ chip = g_malloc0(length); -+ memset(chip, 0, length); -+ chip->chip_id = KVM_IRQCHIP_LS7A_IOAPIC; -+ chip->len = length; -+ ret = kvm_vm_ioctl(kvm_state, KVM_GET_IRQCHIP, chip); -+ if (ret < 0) { -+ fprintf(stderr, "KVM_GET_IRQCHIP failed: %s\n", strerror(ret)); -+ abort(); -+ } -+ state = (struct ls7a_ioapic_state *)chip->data; -+ s->int_id = state->int_id; -+ s->int_mask = state->int_mask; -+ s->htmsi_en = state->htmsi_en; -+ s->intedge = state->intedge; -+ s->intclr = state->intclr; -+ s->auto_crtl0 = state->auto_crtl0; -+ s->auto_crtl1 = state->auto_crtl1; -+ for (i = 0; i < 64; i++) { -+ s->route_entry[i] = state->route_entry[i]; -+ s->htmsi_vector[i] = state->htmsi_vector[i]; -+ } -+ s->intisr_chip0 = state->intisr_chip0; -+ s->intisr_chip1 = state->intisr_chip1; -+ s->intirr = state->intirr; -+ s->intisr = state->intisr; -+ s->int_polarity = state->int_polarity; -+ g_free(chip); -+#endif -+ return 0; -+} -+ -+static int kvm_ls7a_post_load(void *opaque, int version) -+{ -+#ifdef CONFIG_KVM -+ LS7AApicState *s = opaque; -+ struct loongarch_kvm_irqchip *chip; -+ struct ls7a_ioapic_state *state; -+ int ret, i, length; -+ -+ if (!kvm_irqchip_in_kernel()) { -+ return 0; -+ } -+ length = sizeof(struct loongarch_kvm_irqchip) + sizeof(struct ls7a_ioapic_state); -+ chip = g_malloc0(length); -+ memset(chip, 0, length); -+ chip->chip_id = KVM_IRQCHIP_LS7A_IOAPIC; -+ chip->len = length; -+ -+ state = (struct ls7a_ioapic_state *)chip->data; -+ state->int_id = s->int_id; -+ state->int_mask = s->int_mask; -+ state->htmsi_en = s->htmsi_en; -+ state->intedge = s->intedge; -+ state->intclr = s->intclr; -+ state->auto_crtl0 = s->auto_crtl0; -+ state->auto_crtl1 = s->auto_crtl1; -+ for (i = 0; i < 64; i++) { -+ state->route_entry[i] = s->route_entry[i]; -+ state->htmsi_vector[i] = s->htmsi_vector[i]; -+ } -+ state->intisr_chip0 = s->intisr_chip0; -+ state->intisr_chip1 = s->intisr_chip1; -+ state->last_intirr = 0; -+ state->intirr = s->intirr; -+ state->intisr = s->intisr; -+ state->int_polarity = s->int_polarity; -+ -+ ret = kvm_vm_ioctl(kvm_state, KVM_SET_IRQCHIP, chip); -+ if (ret < 0) { -+ fprintf(stderr, "KVM_GET_IRQCHIP failed: %s\n", strerror(ret)); -+ abort(); -+ } -+ g_free(chip); -+#endif -+ return 0; -+} -+ -+static void ls7a_apic_reset(DeviceState *d) -+{ -+ LS7AApicState *s = LS7A_APIC(d); -+ int i; -+ -+ s->int_id = 0x001f000107000000; -+ s->int_mask = 0xffffffffffffffff; -+ s->htmsi_en = 0x0; -+ s->intedge = 0x0; -+ s->intclr = 0x0; -+ s->auto_crtl0 = 0x0; -+ s->auto_crtl1 = 0x0; -+ for (i = 0; i < 64; i++) { -+ s->route_entry[i] = 0x1; -+ s->htmsi_vector[i] = 0x0; -+ } -+ s->intisr_chip0 = 0x0; -+ s->intisr_chip1 = 0x0; -+ s->intirr = 0x0; -+ s->intisr = 0x0; -+ s->int_polarity = 0x0; -+ kvm_ls7a_post_load(s, 0); -+} -+ -+static void ls7a_apic_init(Object *obj) -+{ -+ DeviceState *dev = DEVICE(obj); -+ LS7AApicState *s = LS7A_APIC(obj); -+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj); -+ int tmp; -+ memory_region_init_io(&s->iomem, obj, &ls7a_apic_ops, s, TYPE_LS7A_APIC, 0x1000); -+ sysbus_init_mmio(sbd, &s->iomem); -+ for (tmp = 0; tmp < 257; tmp++) { -+ sysbus_init_irq(sbd, &s->parent_irq[tmp]); -+ } -+ qdev_init_gpio_in(dev, irq_handler, 64); -+} -+ -+static const VMStateDescription vmstate_ls7a_apic = { -+ .name = TYPE_LS7A_APIC, -+ .version_id = 1, -+ .minimum_version_id = 1, -+ .pre_save = kvm_ls7a_pre_save, -+ .post_load = kvm_ls7a_post_load, -+ .fields = (VMStateField[]) { -+ VMSTATE_UINT64(int_mask, LS7AApicState), -+ VMSTATE_UINT64(htmsi_en, LS7AApicState), -+ VMSTATE_UINT64(intedge, LS7AApicState), -+ VMSTATE_UINT64(intclr, LS7AApicState), -+ VMSTATE_UINT64(auto_crtl0, LS7AApicState), -+ VMSTATE_UINT64(auto_crtl1, LS7AApicState), -+ VMSTATE_UINT8_ARRAY(route_entry, LS7AApicState, 64), -+ VMSTATE_UINT8_ARRAY(htmsi_vector, LS7AApicState, 64), -+ VMSTATE_UINT64(intisr_chip0, LS7AApicState), -+ VMSTATE_UINT64(intisr_chip1, LS7AApicState), -+ VMSTATE_UINT64(last_intirr, LS7AApicState), -+ VMSTATE_UINT64(intirr, LS7AApicState), -+ VMSTATE_UINT64(intisr, LS7AApicState), -+ VMSTATE_UINT64(int_polarity, LS7AApicState), -+ VMSTATE_END_OF_LIST() -+ } -+}; -+ -+static void ls7a_apic_class_init(ObjectClass *klass, void *data) -+{ -+ DeviceClass *dc = DEVICE_CLASS(klass); -+ -+ dc->reset = ls7a_apic_reset; -+ dc->vmsd = &vmstate_ls7a_apic; -+} -+ -+static const TypeInfo ls7a_apic_info = { -+ .name = TYPE_LS7A_APIC, -+ .parent = TYPE_SYS_BUS_DEVICE, -+ .instance_size = sizeof(LS7AApicState), -+ .instance_init = ls7a_apic_init, -+ .class_init = ls7a_apic_class_init, -+}; -+ -+static void ls7a_apic_register_types(void) -+{ -+ type_register_static(&ls7a_apic_info); -+} -+ -+type_init(ls7a_apic_register_types) -diff --git a/hw/loongarch/iocsr.c b/hw/loongarch/iocsr.c -new file mode 100644 -index 0000000000..14521c2d5c ---- /dev/null -+++ b/hw/loongarch/iocsr.c -@@ -0,0 +1,219 @@ -+/* -+ * LOONGARCH IOCSR support -+ * -+ * Copyright (c) 2021 Loongarch Technology -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a copy -+ * of this software and associated documentation files (the "Software"), to deal -+ * in the Software without restriction, including without limitation the rights -+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -+ * copies of the Software, and to permit persons to whom the Software is -+ * furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -+ * THE SOFTWARE. -+ */ -+ -+#include "qemu/osdep.h" -+#include "hw/sysbus.h" -+#include "qemu/log.h" -+#include "sysemu/kvm.h" -+#include "linux/kvm.h" -+#include "migration/vmstate.h" -+#include "hw/boards.h" -+#include "hw/loongarch/larch.h" -+ -+#define BIT_ULL(nr) (1ULL << (nr)) -+#define LOONGARCH_IOCSR_FEATURES 0x8 -+#define IOCSRF_TEMP BIT_ULL(0) -+#define IOCSRF_NODECNT BIT_ULL(1) -+#define IOCSRF_MSI BIT_ULL(2) -+#define IOCSRF_EXTIOI BIT_ULL(3) -+#define IOCSRF_CSRIPI BIT_ULL(4) -+#define IOCSRF_FREQCSR BIT_ULL(5) -+#define IOCSRF_FREQSCALE BIT_ULL(6) -+#define IOCSRF_DVFSV1 BIT_ULL(7) -+#define IOCSRF_GMOD BIT_ULL(9) -+#define IOCSRF_VM BIT_ULL(11) -+#define LOONGARCH_IOCSR_VENDOR 0x10 -+#define LOONGARCH_IOCSR_CPUNAME 0x20 -+#define LOONGARCH_IOCSR_NODECNT 0x408 -+#define LOONGARCH_IOCSR_MISC_FUNC 0x420 -+#define IOCSR_MISC_FUNC_TIMER_RESET BIT_ULL(21) -+#define IOCSR_MISC_FUNC_EXT_IOI_EN BIT_ULL(48) -+ -+enum { -+ IOCSR_FEATURES, -+ IOCSR_VENDOR, -+ IOCSR_CPUNAME, -+ IOCSR_NODECNT, -+ IOCSR_MISC_FUNC, -+ IOCSR_MAX -+}; -+ -+static uint32_t iocsr_array[IOCSR_MAX] = { -+ [IOCSR_FEATURES] = LOONGARCH_IOCSR_FEATURES, -+ [IOCSR_VENDOR] = LOONGARCH_IOCSR_VENDOR, -+ [IOCSR_CPUNAME] = LOONGARCH_IOCSR_CPUNAME, -+ [IOCSR_NODECNT] = LOONGARCH_IOCSR_NODECNT, -+ [IOCSR_MISC_FUNC] = LOONGARCH_IOCSR_MISC_FUNC, -+}; -+ -+ -+#define TYPE_IOCSR "iocsr" -+#define IOCSR(obj) OBJECT_CHECK(IOCSRState, (obj), TYPE_IOCSR) -+ -+typedef struct IOCSRState { -+ SysBusDevice parent_obj; -+ uint64_t iocsr_val[IOCSR_MAX]; -+} IOCSRState; -+ -+IOCSRState iocsr_init = { -+ .iocsr_val = { -+ IOCSRF_NODECNT | IOCSRF_MSI | IOCSRF_EXTIOI -+ | IOCSRF_CSRIPI | IOCSRF_GMOD | IOCSRF_VM, -+ 0x6e6f73676e6f6f4c, /* Loongson */ -+ 0x303030354133, /*3A5000*/ -+ 0x4, -+ 0x0, -+ } -+}; -+ -+static int kvm_iocsr_pre_save(void *opaque) -+{ -+#ifdef CONFIG_KVM -+ IOCSRState *s = opaque; -+ struct kvm_iocsr_entry entry; -+ int i = 0; -+ for (i = 0; i < IOCSR_MAX; i++) { -+ entry.addr = iocsr_array[i]; -+ kvm_vm_ioctl(kvm_state, KVM_LOONGARCH_GET_IOCSR, &entry); -+ s->iocsr_val[i] = entry.data; -+ } -+#endif -+ return 0; -+} -+ -+static int kvm_iocsr_post_load(void *opaque, int version) -+{ -+#ifdef CONFIG_KVM -+ IOCSRState *s = opaque; -+ struct kvm_iocsr_entry entry; -+ int i = 0; -+ -+ if (!kvm_enabled()) { -+ return 0; -+ } -+ -+ for (i = 0; i < IOCSR_MAX; i++) { -+ entry.addr = iocsr_array[i]; -+ entry.data = s->iocsr_val[i]; -+ kvm_vm_ioctl(kvm_state, KVM_LOONGARCH_SET_IOCSR, &entry); -+ } -+#endif -+ return 0; -+} -+ -+static void iocsr_reset(DeviceState *d) -+{ -+ IOCSRState *s = IOCSR(d); -+ int i; -+ -+ for (i = 0; i < IOCSR_MAX; i++) { -+ s->iocsr_val[i] = iocsr_init.iocsr_val[i]; -+ } -+ kvm_iocsr_post_load(s, 0); -+} -+static void init_vendor_cpuname(uint64_t *vendor, -+ uint64_t *cpu_name, char *cpuname) -+{ -+ int i = 0, len = 0; -+ char *index = NULL, *index_end = NULL; -+ char *vendor_c = (char *)vendor; -+ char *cpu_name_c = (char *)cpu_name; -+ -+ index = strstr(cpuname, "-"); -+ len = strlen(cpuname); -+ if ((index == NULL) || (len <= 0)) { -+ return ; -+ } -+ -+ *vendor = 0; -+ *cpu_name = 0; -+ index_end = cpuname + len; -+ -+ while (((cpuname + i) < index) && (i < sizeof(uint64_t))) { -+ vendor_c[i] = cpuname[i]; -+ i++; -+ } -+ -+ index += 1; -+ i = 0; -+ -+ while (((index + i) < index_end) && (i < sizeof(uint64_t))) { -+ cpu_name_c[i] = index[i]; -+ i++; -+ } -+ -+ return ; -+} -+ -+static void iocsr_instance_init(Object *obj) -+{ -+ IOCSRState *s = IOCSR(obj); -+ int i; -+ LoongarchMachineState *lsms = LoongarchMACHINE(qdev_get_machine()); -+ LoongarchMachineClass *lsmc = LoongarchMACHINE_GET_CLASS(lsms); -+ -+ init_vendor_cpuname((uint64_t *)&iocsr_init.iocsr_val[IOCSR_VENDOR], -+ (uint64_t *)&iocsr_init.iocsr_val[IOCSR_CPUNAME], -+ lsmc->cpu_name); -+ -+ for (i = 0; i < IOCSR_MAX; i++) { -+ s->iocsr_val[i] = iocsr_init.iocsr_val[i]; -+ } -+} -+ -+static const VMStateDescription vmstate_iocsr = { -+ .name = TYPE_IOCSR, -+ .version_id = 1, -+ .minimum_version_id = 1, -+ .pre_save = kvm_iocsr_pre_save, -+ .post_load = kvm_iocsr_post_load, -+ .fields = (VMStateField[]) { -+ VMSTATE_UINT64_ARRAY(iocsr_val, IOCSRState, IOCSR_MAX), -+ VMSTATE_END_OF_LIST() -+ } -+}; -+ -+static void iocsr_class_init(ObjectClass *klass, void *data) -+{ -+ DeviceClass *dc = DEVICE_CLASS(klass); -+ -+ dc->reset = iocsr_reset; -+ dc->vmsd = &vmstate_iocsr; -+ -+} -+ -+static const TypeInfo iocsr_info = { -+ .name = TYPE_IOCSR, -+ .parent = TYPE_SYS_BUS_DEVICE, -+ .instance_size = sizeof(IOCSRState), -+ .instance_init = iocsr_instance_init, -+ .class_init = iocsr_class_init, -+}; -+ -+static void iocsr_register_types(void) -+{ -+ type_register_static(&iocsr_info); -+} -+ -+type_init(iocsr_register_types) -diff --git a/hw/loongarch/ipi.c b/hw/loongarch/ipi.c -new file mode 100644 -index 0000000000..ade182abcc ---- /dev/null -+++ b/hw/loongarch/ipi.c -@@ -0,0 +1,267 @@ -+#include "qemu/osdep.h" -+#include "qemu/units.h" -+#include "qapi/error.h" -+#include "hw/hw.h" -+#include "hw/irq.h" -+#include "hw/loongarch/cpudevs.h" -+#include "sysemu/sysemu.h" -+#include "sysemu/cpus.h" -+#include "sysemu/kvm.h" -+#include "hw/core/cpu.h" -+#include "qemu/log.h" -+#include "hw/loongarch/bios.h" -+#include "elf.h" -+#include "linux/kvm.h" -+#include "hw/loongarch/larch.h" -+#include "hw/loongarch/ls7a.h" -+#include "migration/vmstate.h" -+ -+static int gipi_pre_save(void *opaque) -+{ -+#ifdef CONFIG_KVM -+ gipiState *state = opaque; -+ struct loongarch_gipiState *kstate; -+ struct loongarch_kvm_irqchip *chip; -+ int ret, i, j, length; -+#endif -+ -+ if (!kvm_irqchip_in_kernel()) { -+ return 0; -+ } -+ -+#ifdef CONFIG_KVM -+ length = sizeof(struct loongarch_kvm_irqchip) + sizeof(struct loongarch_gipiState); -+ chip = g_malloc0(length); -+ memset(chip, 0, length); -+ chip->chip_id = KVM_IRQCHIP_LS3A_GIPI; -+ chip->len = length; -+ ret = kvm_vm_ioctl(kvm_state, KVM_GET_IRQCHIP, chip); -+ if (ret < 0) { -+ fprintf(stderr, "KVM_GET_IRQCHIP failed: %s\n", strerror(ret)); -+ abort(); -+ } -+ -+ kstate = (struct loongarch_gipiState *)chip->data; -+ -+ for (i = 0; i < MAX_GIPI_CORE_NUM; i++) { -+ state->core[i].status = kstate->core[i].status; -+ state->core[i].en = kstate->core[i].en; -+ state->core[i].set = kstate->core[i].set; -+ state->core[i].clear = kstate->core[i].clear; -+ for (j = 0; j < MAX_GIPI_MBX_NUM; j++) { -+ state->core[i].buf[j] = kstate->core[i].buf[j]; -+ } -+ } -+ g_free(chip); -+#endif -+ -+ return 0; -+} -+ -+static int gipi_post_load(void *opaque, int version) -+{ -+#ifdef CONFIG_KVM -+ gipiState *state = opaque; -+ struct loongarch_gipiState *kstate; -+ struct loongarch_kvm_irqchip *chip; -+ int ret, i, j, length; -+#endif -+ -+ if (!kvm_irqchip_in_kernel()) { -+ return 0; -+ } -+ -+#ifdef CONFIG_KVM -+ length = sizeof(struct loongarch_kvm_irqchip) + sizeof(struct loongarch_gipiState); -+ chip = g_malloc0(length); -+ memset(chip, 0, length); -+ chip->chip_id = KVM_IRQCHIP_LS3A_GIPI; -+ chip->len = length; -+ kstate = (struct loongarch_gipiState *)chip->data; -+ -+ for (i = 0; i < MAX_GIPI_CORE_NUM; i++) { -+ kstate->core[i].status = state->core[i].status; -+ kstate->core[i].en = state->core[i].en; -+ kstate->core[i].set = state->core[i].set; -+ kstate->core[i].clear = state->core[i].clear; -+ for (j = 0; j < MAX_GIPI_MBX_NUM; j++) { -+ kstate->core[i].buf[j] = state->core[i].buf[j]; -+ } -+ } -+ -+ ret = kvm_vm_ioctl(kvm_state, KVM_SET_IRQCHIP, chip); -+ if (ret < 0) { -+ fprintf(stderr, "KVM_GET_IRQCHIP failed: %s\n", strerror(ret)); -+ abort(); -+ } -+ g_free(chip); -+#endif -+ -+ return 0; -+} -+ -+static const VMStateDescription vmstate_gipi_core = { -+ .name = "gipi-single", -+ .version_id = 0, -+ .minimum_version_id = 0, -+ .fields = (VMStateField[]) { -+ VMSTATE_UINT32(status, gipi_core), -+ VMSTATE_UINT32(en, gipi_core), -+ VMSTATE_UINT32(set, gipi_core), -+ VMSTATE_UINT32(clear, gipi_core), -+ VMSTATE_UINT64_ARRAY(buf, gipi_core, MAX_GIPI_MBX_NUM), -+ VMSTATE_END_OF_LIST() -+ } -+}; -+ -+static const VMStateDescription vmstate_gipi = { -+ .name = "gipi", -+ .pre_save = gipi_pre_save, -+ .post_load = gipi_post_load, -+ .version_id = 0, -+ .minimum_version_id = 0, -+ .fields = (VMStateField[]) { -+ VMSTATE_STRUCT_ARRAY(core, gipiState, MAX_GIPI_CORE_NUM, 0, -+ vmstate_gipi_core, gipi_core), -+ VMSTATE_END_OF_LIST() -+ } -+}; -+ -+ -+static void gipi_writel(void *opaque, hwaddr addr, uint64_t val, unsigned size) -+{ -+ gipi_core *s = opaque; -+ gipi_core *ss; -+ void *pbuf; -+ uint32_t cpu, action_data, mailaddr; -+ LoongarchMachineState *ms = LoongarchMACHINE(qdev_get_machine()); -+ -+ if ((size != 4) && (size != 8)) { -+ hw_error("size not 4 and not 8"); -+ } -+ addr &= 0xff; -+ switch (addr) { -+ case CORE0_STATUS_OFF: -+ hw_error("CORE0_STATUS_OFF Can't be write\n"); -+ break; -+ case CORE0_EN_OFF: -+ s->en = val; -+ break; -+ case CORE0_IPI_SEND: -+ cpu = (val >> 16) & 0x3ff; -+ action_data = 1UL << (val & 0x1f); -+ ss = &ms->gipi->core[cpu]; -+ ss->status |= action_data; -+ if (ss->status != 0) { -+ qemu_irq_raise(ss->irq); -+ } -+ break; -+ case CORE0_MAIL_SEND: -+ cpu = (val >> 16) & 0x3ff; -+ mailaddr = (val >> 2) & 0x7; -+ ss = &ms->gipi->core[cpu]; -+ pbuf = (void *)ss->buf + mailaddr * 4; -+ *(unsigned int *)pbuf = (val >> 32); -+ break; -+ case CORE0_SET_OFF: -+ hw_error("CORE0_SET_OFF Can't be write\n"); -+ break; -+ case CORE0_CLEAR_OFF: -+ s->status ^= val; -+ if (s->status == 0) { -+ qemu_irq_lower(s->irq); -+ } -+ break; -+ case 0x20 ... 0x3c: -+ pbuf = (void *)s->buf + (addr - 0x20); -+ if (size == 1) { -+ *(unsigned char *)pbuf = (unsigned char)val; -+ } else if (size == 2) { -+ *(unsigned short *)pbuf = (unsigned short)val; -+ } else if (size == 4) { -+ *(unsigned int *)pbuf = (unsigned int)val; -+ } else if (size == 8) { -+ *(unsigned long *)pbuf = (unsigned long)val; -+ } -+ break; -+ default: -+ break; -+ } -+} -+ -+static uint64_t gipi_readl(void *opaque, hwaddr addr, unsigned size) -+{ -+ gipi_core *s = opaque; -+ uint64_t ret = 0; -+ void *pbuf; -+ -+ addr &= 0xff; -+ if ((size != 4) && (size != 8)) { -+ hw_error("size not 4 and not 8 size:%d\n", size); -+ } -+ switch (addr) { -+ case CORE0_STATUS_OFF: -+ ret = s->status; -+ break; -+ case CORE0_EN_OFF: -+ ret = s->en; -+ break; -+ case CORE0_SET_OFF: -+ ret = 0; -+ break; -+ case CORE0_CLEAR_OFF: -+ ret = 0; -+ break; -+ case 0x20 ... 0x3c: -+ pbuf = (void *)s->buf + (addr - 0x20); -+ if (size == 1) { -+ ret = *(unsigned char *)pbuf; -+ } else if (size == 2) { -+ ret = *(unsigned short *)pbuf; -+ } else if (size == 4) { -+ ret = *(unsigned int *)pbuf; -+ } else if (size == 8) { -+ ret = *(unsigned long *)pbuf; -+ } -+ break; -+ default: -+ break; -+ } -+ -+ return ret; -+} -+ -+static const MemoryRegionOps gipi_ops = { -+ .read = gipi_readl, -+ .write = gipi_writel, -+ .valid = { -+ .min_access_size = 4, -+ .max_access_size = 8, -+ }, -+ .impl = { -+ .min_access_size = 4, -+ .max_access_size = 8, -+ }, -+ .endianness = DEVICE_NATIVE_ENDIAN, -+}; -+ -+int cpu_init_ipi(LoongarchMachineState *ms, qemu_irq parent, int cpu) -+{ -+ hwaddr addr; -+ MemoryRegion *region; -+ char str[32]; -+ -+ if (ms->gipi == NULL) { -+ ms->gipi = g_malloc0(sizeof(gipiState)); -+ vmstate_register(NULL, 0, &vmstate_gipi, ms->gipi); -+ } -+ -+ ms->gipi->core[cpu].irq = parent; -+ -+ addr = SMP_GIPI_MAILBOX | (cpu << 8); -+ region = g_new(MemoryRegion, 1); -+ sprintf(str, "gipi%d", cpu); -+ memory_region_init_io(region, NULL, &gipi_ops, &ms->gipi->core[cpu], str, 0x100); -+ memory_region_add_subregion(get_system_memory(), addr, region); -+ return 0; -+} -diff --git a/hw/loongarch/larch_3a.c b/hw/loongarch/larch_3a.c -new file mode 100644 -index 0000000000..3db269274f ---- /dev/null -+++ b/hw/loongarch/larch_3a.c -@@ -0,0 +1,2026 @@ -+/* -+ * QEMU loongarch 3a develop board emulation -+ * -+ * Copyright (C) 2013-2014 qiaochong -+ * Copyright (C) 2016-2017 zhangshuangshuang -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a copy -+ * of this software and associated documentation files (the "Software"), to deal -+ * in the Software without restriction, including without limitation the rights -+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -+ * copies of the Software, and to permit persons to whom the Software is -+ * furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -+ * THE SOFTWARE. -+ */ -+#include "qemu/osdep.h" -+#include "qemu/units.h" -+#include "qapi/error.h" -+#include "qemu/datadir.h" -+#include "hw/hw.h" -+#include "hw/loongarch/cpudevs.h" -+#include "hw/i386/pc.h" -+#include "hw/char/serial.h" -+#include "hw/isa/isa.h" -+#include "hw/qdev-core.h" -+#include "sysemu/sysemu.h" -+#include "sysemu/runstate.h" -+#include "sysemu/reset.h" -+#include "migration/vmstate.h" -+#include "sysemu/cpus.h" -+#include "hw/boards.h" -+#include "qemu/log.h" -+#include "hw/loongarch/bios.h" -+#include "hw/loader.h" -+#include "elf.h" -+#include "exec/address-spaces.h" -+#include "hw/ide.h" -+#include "hw/pci/pci_host.h" -+#include "hw/pci/msi.h" -+#include "linux/kvm.h" -+#include "sysemu/kvm.h" -+#include "sysemu/numa.h" -+#include "hw/rtc/mc146818rtc.h" -+#include "hw/irq.h" -+#include "net/net.h" -+#include "hw/timer/i8254.h" -+#include "hw/loongarch/larch.h" -+#include "hw/loongarch/ls7a.h" -+#include "hw/nvram/fw_cfg.h" -+#include "hw/firmware/smbios.h" -+#include "acpi-build.h" -+#include -+#include -+#include "sysemu/block-backend.h" -+#include "hw/block/flash.h" -+#include "sysemu/device_tree.h" -+#include "qapi/visitor.h" -+#include "qapi/qapi-visit-common.h" -+ -+#include -+ -+#define DMA64_SUPPORTED 0x2 -+#define MAX_IDE_BUS 2 -+ -+#define BOOTPARAM_PHYADDR 0x0ff00000ULL -+#define BOOTPARAM_ADDR (0x9000000000000000ULL + BOOTPARAM_PHYADDR) -+#define SMBIOS_PHYSICAL_ADDRESS 0x0fe00000 -+#define SMBIOS_SIZE_LIMIT 0x200000 -+#define RESERVED_SIZE_LIMIT 0x1100000 -+#define COMMAND_LINE_SIZE 4096 -+#define FW_CONF_ADDR 0x0fff0000 -+ -+#define PHYS_TO_VIRT(x) ((x) | 0x9000000000000000ULL) -+ -+#define TARGET_REALPAGE_MASK (TARGET_PAGE_MASK << 2) -+ -+#ifdef CONFIG_KVM -+#define LS_ISA_IO_SIZE 0x02000000 -+#define LS_ISA_MEM_SIZE 0x40000000 -+#else -+#define LS_ISA_IO_SIZE 0x00010000 -+#define LS_ISA_MEM_SIZE 0x01000000 -+#endif -+ -+#ifdef CONFIG_KVM -+#define align(x) (((x) + 63) & ~63) -+#else -+#define align(x) (((x) + 15) & ~15) -+#endif -+ -+#define DEBUG_LOONGARCH3A 0 -+#define FLASH_SECTOR_SIZE 4096 -+ -+#define DPRINTF(fmt, ...) \ -+ do { if (DEBUG_LOONGARCH3A) { fprintf(stderr, fmt, ## __VA_ARGS__); } } while (0) -+ -+#define DEFINE_LS3A5K_MACHINE(suffix, name, optionfn) \ -+ static void ls3a5k_init_##suffix(MachineState *machine) \ -+ { \ -+ ls3a5k_init(machine); \ -+ } \ -+ DEFINE_LOONGARCH_MACHINE(suffix, name, ls3a5k_init_##suffix, optionfn) -+ -+struct efi_memory_map_loongarch { -+ uint16_t vers; /* version of efi_memory_map */ -+ uint32_t nr_map; /* number of memory_maps */ -+ uint32_t mem_freq; /* memory frequence */ -+ struct mem_map { -+ uint32_t node_id; /* node_id which memory attached to */ -+ uint32_t mem_type; /* system memory, pci memory, pci io, etc. */ -+ uint64_t mem_start; /* memory map start address */ -+ uint32_t mem_size; /* each memory_map size, not the total size */ -+ } map[128]; -+} __attribute__((packed)); -+ -+enum loongarch_cpu_type { -+ Loongson3 = 0x1, -+ Loongson3_comp = 0x2 -+}; -+ -+struct GlobalProperty loongarch_compat[] = { -+ { -+ .driver = "rtl8139", -+ .property = "romfile", -+ .value = "", -+ },{ -+ .driver = "e1000", -+ .property = "romfile", -+ .value = "", -+ },{ -+ .driver = "virtio-net-pci", -+ .property = "romfile", -+ .value = "", -+ },{ -+ .driver = "qxl-vga", -+ .property = "romfile", -+ .value = "", -+ },{ -+ .driver = "VGA", -+ .property = "romfile", -+ .value = "", -+ },{ -+ .driver = "cirrus-vga", -+ .property = "romfile", -+ .value = "", -+ },{ -+ .driver = "virtio-vga", -+ .property = "romfile", -+ .value = "", -+ },{ -+ .driver = "vmware-svga", -+ .property = "romfile", -+ .value = "", -+ }, -+}; -+const size_t loongarch_compat_len = G_N_ELEMENTS(loongarch_compat); -+ -+/* -+ * Capability and feature descriptor structure for LOONGARCH CPU -+ */ -+struct efi_cpuinfo_loongarch { -+ uint16_t vers; /* version of efi_cpuinfo_loongarch */ -+ uint32_t processor_id; /* PRID, e.g. 6305, 6306 */ -+ enum loongarch_cpu_type cputype; /* 3A, 3B, etc. */ -+ uint32_t total_node; /* num of total numa nodes */ -+ uint16_t cpu_startup_core_id; /* Core id */ -+ uint16_t reserved_cores_mask; -+ uint32_t cpu_clock_freq; /* cpu_clock */ -+ uint32_t nr_cpus; -+} __attribute__((packed)); -+ -+#define MAX_UARTS 64 -+struct uart_device { -+ uint32_t iotype; /* see include/linux/serial_core.h */ -+ uint32_t uartclk; -+ uint32_t int_offset; -+ uint64_t uart_base; -+} __attribute__((packed)); -+ -+#define MAX_SENSORS 64 -+#define SENSOR_TEMPER 0x00000001 -+#define SENSOR_VOLTAGE 0x00000002 -+#define SENSOR_FAN 0x00000004 -+struct sensor_device { -+ char name[32]; /* a formal name */ -+ char label[64]; /* a flexible description */ -+ uint32_t type; /* SENSOR_* */ -+ uint32_t id; /* instance id of a sensor-class */ -+ uint32_t fan_policy; /* see arch/loongarch/include/ -+ asm/mach-loongarch/loongarch_hwmon.h */ -+ uint32_t fan_percent;/* only for constant speed policy */ -+ uint64_t base_addr; /* base address of device registers */ -+} __attribute__((packed)); -+ -+struct system_loongarch { -+ uint16_t vers; /* version of system_loongarch */ -+ uint32_t ccnuma_smp; /* 0: no numa; 1: has numa */ -+ uint32_t sing_double_channel;/* 1:single; 2:double */ -+ uint32_t nr_uarts; -+ struct uart_device uarts[MAX_UARTS]; -+ uint32_t nr_sensors; -+ struct sensor_device sensors[MAX_SENSORS]; -+ char has_ec; -+ char ec_name[32]; -+ uint64_t ec_base_addr; -+ char has_tcm; -+ char tcm_name[32]; -+ uint64_t tcm_base_addr; -+ uint64_t workarounds; /* see workarounds.h */ -+} __attribute__((packed)); -+ -+struct irq_source_routing_table { -+ uint16_t vers; -+ uint16_t size; -+ uint16_t rtr_bus; -+ uint16_t rtr_devfn; -+ uint32_t vendor; -+ uint32_t device; -+ uint32_t PIC_type; /* conform use HT or PCI to route to CPU-PIC */ -+ uint64_t ht_int_bit; /* 3A: 1<<24; 3B: 1<<16 */ -+ uint64_t ht_enable; /* irqs used in this PIC */ -+ uint32_t node_id; /* node id: 0x0-0; 0x1-1; 0x10-2; 0x11-3 */ -+ uint64_t pci_mem_start_addr; -+ uint64_t pci_mem_end_addr; -+ uint64_t pci_io_start_addr; -+ uint64_t pci_io_end_addr; -+ uint64_t pci_config_addr; -+ uint32_t dma_mask_bits; -+ uint16_t dma_noncoherent; -+} __attribute__((packed)); -+ -+struct interface_info { -+ uint16_t vers; /* version of the specificition */ -+ uint16_t size; -+ uint8_t flag; -+ char description[64]; -+} __attribute__((packed)); -+ -+#define MAX_RESOURCE_NUMBER 128 -+struct resource_loongarch { -+ uint64_t start; /* resource start address */ -+ uint64_t end; /* resource end address */ -+ char name[64]; -+ uint32_t flags; -+}; -+ -+struct archdev_data {}; /* arch specific additions */ -+ -+struct board_devices { -+ char name[64]; /* hold the device name */ -+ uint32_t num_resources; /* number of device_resource */ -+ /* for each device's resource */ -+ struct resource_loongarch resource[MAX_RESOURCE_NUMBER]; -+ /* arch specific additions */ -+ struct archdev_data archdata; -+}; -+ -+struct loongarch_special_attribute { -+ uint16_t vers; /* version of this special */ -+ char special_name[64]; /* special_atribute_name */ -+ uint32_t loongarch_special_type; /* type of special device */ -+ /* for each device's resource */ -+ struct resource_loongarch resource[MAX_RESOURCE_NUMBER]; -+}; -+ -+struct loongarch_params { -+ uint64_t memory_offset; /* efi_memory_map_loongarch struct offset */ -+ uint64_t cpu_offset; /* efi_cpuinfo_loongarch struct offset */ -+ uint64_t system_offset; /* system_loongarch struct offset */ -+ uint64_t irq_offset; /* irq_source_routing_table struct offset */ -+ uint64_t interface_offset; /* interface_info struct offset */ -+ uint64_t special_offset; /* loongarch_special_attribute struct offset */ -+ uint64_t boarddev_table_offset; /* board_devices offset */ -+}; -+ -+struct smbios_tables { -+ uint16_t vers; /* version of smbios */ -+ uint64_t vga_bios; /* vga_bios address */ -+ struct loongarch_params lp; -+}; -+ -+struct efi_reset_system_t { -+ uint64_t ResetCold; -+ uint64_t ResetWarm; -+ uint64_t ResetType; -+ uint64_t Shutdown; -+ uint64_t DoSuspend; /* NULL if not support */ -+}; -+ -+struct efi_loongarch { -+ uint64_t mps; /* MPS table */ -+ uint64_t acpi; /* ACPI table (IA64 ext 0.71) */ -+ uint64_t acpi20; /* ACPI table (ACPI 2.0) */ -+ struct smbios_tables smbios; /* SM BIOS table */ -+ uint64_t sal_systab; /* SAL system table */ -+ uint64_t boot_info; /* boot info table */ -+}; -+ -+struct boot_params { -+ struct efi_loongarch efi; -+ struct efi_reset_system_t reset_system; -+}; -+ -+static struct _loaderparams { -+ unsigned long ram_size; -+ const char *kernel_filename; -+ const char *kernel_cmdline; -+ const char *initrd_filename; -+ unsigned long a0, a1, a2; -+} loaderparams; -+ -+static struct _firmware_config { -+ unsigned long ram_size; -+ unsigned int mem_freq; -+ unsigned int cpu_nr; -+ unsigned int cpu_clock_freq; -+} fw_config; -+ -+struct la_memmap_entry { -+ uint64_t address; -+ uint64_t length; -+ uint32_t type; -+ uint32_t reserved; -+} ; -+ -+static void *boot_params_buf; -+static void *boot_params_p; -+static struct la_memmap_entry *la_memmap_table; -+static unsigned la_memmap_entries; -+ -+CPULOONGARCHState *cpu_states[LOONGARCH_MAX_VCPUS]; -+ -+struct kvm_cpucfg ls3a5k_cpucfgs = { -+ .cpucfg[LOONGARCH_CPUCFG0] = CPUCFG0_3A5000_PRID, -+ .cpucfg[LOONGARCH_CPUCFG1] = CPUCFG1_ISGR64 | CPUCFG1_PAGING | -+ CPUCFG1_IOCSR | CPUCFG1_PABITS | CPUCFG1_VABITS | CPUCFG1_UAL | -+ CPUCFG1_RI | CPUCFG1_XI | CPUCFG1_RPLV | CPUCFG1_HUGEPG | -+ CPUCFG1_IOCSRBRD, -+ .cpucfg[LOONGARCH_CPUCFG2] = CPUCFG2_FP | CPUCFG2_FPSP | CPUCFG2_FPDP | -+ CPUCFG2_FPVERS | CPUCFG2_LSX | CPUCFG2_LASX | CPUCFG2_COMPLEX | -+ CPUCFG2_CRYPTO | CPUCFG2_LLFTP | CPUCFG2_LLFTPREV | CPUCFG2_LSPW | -+ CPUCFG2_LAM, -+ .cpucfg[LOONGARCH_CPUCFG3] = CPUCFG3_CCDMA | CPUCFG3_SFB | CPUCFG3_UCACC | -+ CPUCFG3_LLEXC | CPUCFG3_SCDLY | CPUCFG3_LLDBAR | CPUCFG3_ITLBT | -+ CPUCFG3_ICACHET | CPUCFG3_SPW_LVL | CPUCFG3_SPW_HG_HF | CPUCFG3_RVA | -+ CPUCFG3_RVAMAX, -+ .cpucfg[LOONGARCH_CPUCFG4] = CCFREQ_100M, -+ .cpucfg[LOONGARCH_CPUCFG5] = CPUCFG5_CCMUL | CPUCFG5_CCDIV, -+ .cpucfg[LOONGARCH_CPUCFG6] = CPUCFG6_PMP | CPUCFG6_PAMVER | CPUCFG6_PMNUM | -+ CPUCFG6_PMBITS | CPUCFG6_UPM, -+ .cpucfg[LOONGARCH_CPUCFG16] = CPUCFG16_L1_IUPRE | CPUCFG16_L1_DPRE | -+ CPUCFG16_L2_IUPRE | CPUCFG16_L2_IUUNIFY | CPUCFG16_L2_IUPRIV | -+ CPUCFG16_L3_IUPRE | CPUCFG16_L3_IUUNIFY | CPUCFG16_L3_IUINCL, -+ .cpucfg[LOONGARCH_CPUCFG17] = CPUCFG17_L1I_WAYS_M | CPUCFG17_L1I_SETS_M | -+ CPUCFG17_L1I_SIZE_M, -+ .cpucfg[LOONGARCH_CPUCFG18] = CPUCFG18_L1D_WAYS_M | CPUCFG18_L1D_SETS_M | -+ CPUCFG18_L1D_SIZE_M, -+ .cpucfg[LOONGARCH_CPUCFG19] = CPUCFG19_L2_WAYS_M | CPUCFG19_L2_SETS_M | -+ CPUCFG19_L2_SIZE_M, -+ .cpucfg[LOONGARCH_CPUCFG20] = CPUCFG20_L3_WAYS_M | CPUCFG20_L3_SETS_M | -+ CPUCFG20_L3_SIZE_M, -+}; -+ -+bool loongarch_is_acpi_enabled(LoongarchMachineState *vms) -+{ -+ if (vms->acpi == ON_OFF_AUTO_OFF) { -+ return false; -+ } -+ return true; -+} -+static void loongarch_get_acpi(Object *obj, Visitor *v, const char *name, -+ void *opaque, Error **errp) -+{ -+ LoongarchMachineState *lsms = LoongarchMACHINE(obj); -+ OnOffAuto acpi = lsms->acpi; -+ -+ visit_type_OnOffAuto(v, name, &acpi, errp); -+} -+ -+static void loongarch_set_acpi(Object *obj, Visitor *v, const char *name, -+ void *opaque, Error **errp) -+{ -+ LoongarchMachineState *lsms = LoongarchMACHINE(obj); -+ -+ visit_type_OnOffAuto(v, name, &lsms->acpi, errp); -+} -+int la_memmap_add_entry(uint64_t address, uint64_t length, uint32_t type) -+{ -+ int i; -+ -+ for (i = 0; i < la_memmap_entries; i++) { -+ if (la_memmap_table[i].address == address) { -+ fprintf(stderr, "%s address:0x%lx length:0x%lx already exists\n", -+ __func__, address, length); -+ return 0; -+ } -+ } -+ -+ la_memmap_table = g_renew(struct la_memmap_entry, la_memmap_table, -+ la_memmap_entries + 1); -+ la_memmap_table[la_memmap_entries].address = cpu_to_le64(address); -+ la_memmap_table[la_memmap_entries].length = cpu_to_le64(length); -+ la_memmap_table[la_memmap_entries].type = cpu_to_le32(type); -+ la_memmap_entries++; -+ -+ return la_memmap_entries; -+} -+ -+static ram_addr_t get_hotplug_membase(ram_addr_t ram_size) -+{ -+ ram_addr_t sstart; -+ -+ if (ram_size <= 0x10000000) { -+ sstart = 0x90000000; -+ } else { -+ sstart = 0x90000000 + ROUND_UP((ram_size - 0x10000000), -+ LOONGARCH_HOTPLUG_MEM_ALIGN); -+ } -+ return sstart; -+} -+ -+static struct efi_memory_map_loongarch *init_memory_map(void *g_map) -+{ -+ struct efi_memory_map_loongarch *emap = g_map; -+ -+ emap->nr_map = 4; -+ emap->mem_freq = 266000000; -+ -+ emap->map[0].node_id = 0; -+ emap->map[0].mem_type = 1; -+ emap->map[0].mem_start = 0x0; -+#ifdef CONFIG_KVM -+ emap->map[0].mem_size = (loaderparams.ram_size > 0x10000000 -+ ? 256 : (loaderparams.ram_size >> 20)) - 18; -+#else -+ emap->map[0].mem_size = atoi(getenv("memsize")); -+#endif -+ -+ emap->map[1].node_id = 0; -+ emap->map[1].mem_type = 2; -+ emap->map[1].mem_start = 0x90000000; -+#ifdef CONFIG_KVM -+ emap->map[1].mem_size = (loaderparams.ram_size > 0x10000000 -+ ? (loaderparams.ram_size >> 20) - 256 : 0); -+#else -+ emap->map[1].mem_size = atoi(getenv("highmemsize")); -+#endif -+ -+ /* support for smbios */ -+ emap->map[2].node_id = 0; -+ emap->map[2].mem_type = 10; -+ emap->map[2].mem_start = SMBIOS_PHYSICAL_ADDRESS; -+ emap->map[2].mem_size = SMBIOS_SIZE_LIMIT >> 20; -+ -+ emap->map[3].node_id = 0; -+ emap->map[3].mem_type = 3; -+ emap->map[3].mem_start = 0xee00000; -+ emap->map[3].mem_size = RESERVED_SIZE_LIMIT >> 20; -+ -+ return emap; -+} -+ -+static uint64_t get_host_cpu_freq(void) -+{ -+ int fd = 0; -+ char buf[1024]; -+ uint64_t freq = 0, size = 0; -+ char *buf_p; -+ -+ fd = open("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq", O_RDONLY); -+ if (fd == -1) { -+ fprintf(stderr, "/sys/devices/system/cpu/cpu0/cpufreq/ \ -+ cpuinfo_max_freq not exist!\n"); -+ fprintf(stderr, "Trying /proc/cpuinfo...\n"); -+ } else { -+ size = read(fd, buf, 16); -+ if (size == -1) { -+ fprintf(stderr, "read err...\n"); -+ } -+ close(fd); -+ freq = (uint64_t)atoi(buf); -+ return freq * 1000; -+ } -+ -+ fd = open("/proc/cpuinfo", O_RDONLY); -+ if (fd == -1) { -+ fprintf(stderr, "Failed to open /proc/cpuinfo!\n"); -+ return 0; -+ } -+ -+ size = read(fd, buf, 1024); -+ if (size == -1) { -+ fprintf(stderr, "read err...\n"); -+ } -+ close(fd); -+ -+ buf_p = strstr(buf, "MHz"); -+ if (buf_p) { -+ while (*buf_p != ':') { -+ buf_p++; -+ } -+ buf_p += 2; -+ } else { -+ buf_p = strstr(buf, "name"); -+ while (*buf_p != '@') { -+ buf_p++; -+ } -+ buf_p += 2; -+ } -+ -+ memcpy(buf, buf_p, 12); -+ buf_p = buf; -+ while ((*buf_p >= '0') && (*buf_p <= '9')) { -+ buf_p++; -+ } -+ *buf_p = '\0'; -+ -+ freq = (uint64_t)atoi(buf); -+ return freq * 1000 * 1000; -+} -+ -+static char *get_host_cpu_model_name(void) -+{ -+ int fd = 0; -+ int size = 0; -+ static char buf[1024]; -+ char *buf_p; -+ -+ fd = open("/proc/cpuinfo", O_RDONLY); -+ if (fd == -1) { -+ fprintf(stderr, "Failed to open /proc/cpuinfo!\n"); -+ return 0; -+ } -+ -+ size = read(fd, buf, 1024); -+ if (size == -1) { -+ fprintf(stderr, "read err...\n"); -+ } -+ close(fd); -+ buf_p = strstr(buf, "name"); -+ -+ while (*buf_p != ':') { -+ buf_p++; -+ } -+ buf_p = buf_p + 2; -+ memcpy(buf, buf_p, 40); -+ buf_p = buf; -+ while (*buf_p != '\n') { -+ buf_p++; -+ } -+ -+ *(buf_p) = '\0'; -+ -+ return buf; -+} -+ -+static void fw_conf_init(unsigned long ramsize) -+{ -+ MachineState *ms = MACHINE(qdev_get_machine()); -+ int smp_cpus = ms->smp.cpus; -+ fw_config.ram_size = ramsize; -+ fw_config.mem_freq = 266000000; -+ fw_config.cpu_nr = smp_cpus ; -+ fw_config.cpu_clock_freq = get_host_cpu_freq(); -+} -+ -+static struct efi_cpuinfo_loongarch *init_cpu_info(void *g_cpuinfo_loongarch) -+{ -+ struct efi_cpuinfo_loongarch *c = g_cpuinfo_loongarch; -+ MachineState *ms = MACHINE(qdev_get_machine()); -+ int smp_cpus = ms->smp.cpus; -+ LoongarchMachineState *lsms = LoongarchMACHINE(qdev_get_machine()); -+ LoongarchMachineClass *lsmc = LoongarchMACHINE_GET_CLASS(lsms); -+ -+ if (strstr(lsmc->cpu_name, "5000")) { -+ c->processor_id = 0x14c010; -+ } -+ c->cputype = Loongson3_comp; -+ c->cpu_clock_freq = get_host_cpu_freq(); -+ if (!c->cpu_clock_freq) { -+ c->cpu_clock_freq = 200000000; -+ } -+ c->total_node = 1; -+ c->nr_cpus = smp_cpus; -+ c->cpu_startup_core_id = 0; -+ c->reserved_cores_mask = 0xffff & (0xffff << smp_cpus); -+ -+ return c; -+} -+ -+static struct system_loongarch *init_system_loongarch(void *g_sysitem) -+{ -+ struct system_loongarch *s = g_sysitem; -+ -+ s->ccnuma_smp = 1; -+ s->ccnuma_smp = 0; -+ s->sing_double_channel = 1; -+ -+ return s; -+} -+ -+enum loongarch_irq_source_enum { -+ HT, I8259, UNKNOWN -+}; -+ -+static struct irq_source_routing_table *init_irq_source(void *g_irq_source) -+{ -+ struct irq_source_routing_table *irq_info = g_irq_source; -+ LoongarchMachineState *lsms = LoongarchMACHINE(qdev_get_machine()); -+ LoongarchMachineClass *lsmc = LoongarchMACHINE_GET_CLASS(lsms); -+ -+ irq_info->PIC_type = HT; -+ irq_info->ht_int_bit = 1 << 24; -+ irq_info->ht_enable = 0x0000d17b; -+ irq_info->node_id = 0; -+ -+ irq_info->pci_mem_start_addr = LS_ISA_MEM_BASE; -+ irq_info->pci_mem_end_addr = irq_info->pci_mem_start_addr + LS_ISA_MEM_SIZE - 1; -+ -+ if (strstr(lsmc->cpu_name, "5000")) { -+ irq_info->pci_io_start_addr = LS3A5K_ISA_IO_BASE; -+ } -+ irq_info->dma_noncoherent = 1; -+ return irq_info; -+} -+ -+static struct interface_info *init_interface_info(void *g_interface) -+{ -+ struct interface_info *inter = g_interface; -+ int flashsize = 0x80000; -+ -+ inter->vers = 0x0001; -+ inter->size = flashsize / 0x400; -+ inter->flag = 1; -+ -+ strcpy(inter->description, "PMON_Version_v2.1"); -+ -+ return inter; -+} -+ -+static struct board_devices *board_devices_info(void *g_board) -+{ -+ struct board_devices *bd = g_board; -+ LoongarchMachineState *lsms = LoongarchMACHINE(qdev_get_machine()); -+ LoongarchMachineClass *lsmc = LoongarchMACHINE_GET_CLASS(lsms); -+ -+ if (!strcmp(lsmc->bridge_name, "ls7a")) { -+ strcpy(bd->name, "Loongarch-3A-7A-1w-V1.03-demo"); -+ } -+ bd->num_resources = 10; -+ -+ return bd; -+} -+ -+static struct loongarch_special_attribute *init_special_info(void *g_special) -+{ -+ struct loongarch_special_attribute *special = g_special; -+ char update[11] = "2013-01-01"; -+ int VRAM_SIZE = 0x20000; -+ -+ strcpy(special->special_name, update); -+ special->resource[0].flags = 0; -+ special->resource[0].start = 0; -+ special->resource[0].end = VRAM_SIZE; -+ strcpy(special->resource[0].name, "SPMODULE"); -+ special->resource[0].flags |= DMA64_SUPPORTED; -+ -+ return special; -+} -+ -+static void init_loongarch_params(struct loongarch_params *lp) -+{ -+ void *p = boot_params_p; -+ -+ lp->memory_offset = (unsigned long long)init_memory_map(p) -+ - (unsigned long long)lp; -+ p += align(sizeof(struct efi_memory_map_loongarch)); -+ -+ lp->cpu_offset = (unsigned long long)init_cpu_info(p) -+ - (unsigned long long)lp; -+ p += align(sizeof(struct efi_cpuinfo_loongarch)); -+ -+ lp->system_offset = (unsigned long long)init_system_loongarch(p) -+ - (unsigned long long)lp; -+ p += align(sizeof(struct system_loongarch)); -+ -+ lp->irq_offset = (unsigned long long)init_irq_source(p) -+ - (unsigned long long)lp; -+ p += align(sizeof(struct irq_source_routing_table)); -+ -+ lp->interface_offset = (unsigned long long)init_interface_info(p) -+ - (unsigned long long)lp; -+ p += align(sizeof(struct interface_info)); -+ -+ lp->boarddev_table_offset = (unsigned long long)board_devices_info(p) -+ - (unsigned long long)lp; -+ p += align(sizeof(struct board_devices)); -+ -+ lp->special_offset = (unsigned long long)init_special_info(p) -+ - (unsigned long long)lp; -+ p += align(sizeof(struct loongarch_special_attribute)); -+ -+ boot_params_p = p; -+} -+ -+static void init_smbios(struct smbios_tables *smbios) -+{ -+ smbios->vers = 1; -+ smbios->vga_bios = 1; -+ init_loongarch_params(&(smbios->lp)); -+} -+ -+static void init_efi(struct efi_loongarch *efi) -+{ -+ init_smbios(&(efi->smbios)); -+} -+ -+static int init_boot_param(struct boot_params *bp) -+{ -+ init_efi(&(bp->efi)); -+ -+ return 0; -+} -+ -+static unsigned int ls3a5k_aui_boot_code[] = { -+ 0x0380200d, /* ori $r13,$r0,0x8 */ -+ 0x0400002d, /* csrwr $r13,0x0 */ -+ 0x0401000e, /* csrrd $r14,0x40 */ -+ 0x0343fdce, /* andi $r14,$r14,0xff */ -+ 0x143fc02c, /* lu12i.w $r12,261889(0x1fe01) */ -+ 0x1600000c, /* lu32i.d $r12,0 */ -+ 0x0320018c, /* lu52i.d $r12,$r12,-1792(0x800) */ -+ 0x03400dcf, /* andi $r15,$r14,0x3 */ -+ 0x004121ef, /* slli.d $r15,$r15,0x8 */ -+ 0x00153d8c, /* or $r12,$r12,$r15 */ -+ 0x034031d0, /* andi $r16,$r14,0xc */ -+ 0x0041aa10, /* slli.d $r16,$r16,0x2a */ -+ 0x0015418c, /* or $r12,$r12,$r16 */ -+ 0x28808184, /* ld.w $r4,$r12,32(0x20) */ -+ 0x43fffc9f, /* beqz $r4,0 -4 */ -+ 0x28c08184, /* ld.d $r4,$r12,32(0x20) */ -+ 0x28c0a183, /* ld.d $r3,$r12,40(0x28) */ -+ 0x28c0c182, /* ld.d $r2,$r12,48(0x30) */ -+ 0x28c0e185, /* ld.d $r5,$r12,56(0x38) */ -+ 0x4c000080, /* jirl $r0,$r4,0 */ -+}; -+ -+static int set_bootparam_uefi(ram_addr_t initrd_offset, long initrd_size) -+{ -+ long params_size; -+ char memenv[32]; -+ char highmemenv[32]; -+ void *params_buf; -+ unsigned long *parg_env; -+ int ret = 0; -+ -+ /* Allocate params_buf for command line. */ -+ params_size = 0x100000; -+ params_buf = g_malloc0(params_size); -+ -+ /* -+ * Layout of params_buf looks like this: -+ * argv[0], argv[1], 0, env[0], env[1], ...env[i], 0, -+ * argv[0]'s data, argv[1]'s data, env[0]'data, ..., env[i]'s data, 0 -+ */ -+ parg_env = (void *)params_buf; -+ -+ ret = (3 + 1) * sizeof(target_ulong); -+ *parg_env++ = (BOOTPARAM_ADDR + ret); -+ ret += (1 + snprintf(params_buf + ret, COMMAND_LINE_SIZE - ret, "g")); -+ -+ /* argv1 */ -+ *parg_env++ = BOOTPARAM_ADDR + ret; -+ if (initrd_size > 0) -+ ret += (1 + snprintf(params_buf + ret, COMMAND_LINE_SIZE - ret, -+ "rd_start=0x%llx rd_size=%li %s", -+ PHYS_TO_VIRT((uint32_t)initrd_offset), -+ initrd_size, loaderparams.kernel_cmdline)); -+ else -+ ret += (1 + snprintf(params_buf + ret, COMMAND_LINE_SIZE - ret, "%s", -+ loaderparams.kernel_cmdline)); -+ -+ /* argv2 */ -+ *parg_env++ = 0; -+ -+ /* env */ -+ sprintf(memenv, "%lu", loaderparams.ram_size > 0x10000000 -+ ? 256 : (loaderparams.ram_size >> 20)); -+ sprintf(highmemenv, "%lu", loaderparams.ram_size > 0x10000000 -+ ? (loaderparams.ram_size >> 20) - 256 : 0); -+ -+ setenv("memsize", memenv, 1); -+ setenv("highmemsize", highmemenv, 1); -+ -+ ret = ((ret + 32) & ~31); -+ -+ boot_params_buf = (void *)(params_buf + ret); -+ boot_params_p = boot_params_buf + align(sizeof(struct boot_params)); -+ init_boot_param(boot_params_buf); -+ rom_add_blob_fixed("params", params_buf, params_size, -+ BOOTPARAM_PHYADDR); -+ loaderparams.a0 = 2; -+ loaderparams.a1 = BOOTPARAM_ADDR; -+ loaderparams.a2 = BOOTPARAM_ADDR + ret; -+ -+ return 0; -+} -+ -+static uint64_t cpu_loongarch_virt_to_phys(void *opaque, uint64_t addr) -+{ -+ return addr & 0x1fffffffll; -+} -+ -+static void fw_cfg_add_kernel_info(FWCfgState *fw_cfg, -+ uint64_t highram_size, -+ uint64_t phyAddr_initrd) -+{ -+ int64_t entry, kernel_low, kernel_high; -+ long initrd_size = 0; -+ uint64_t initrd_offset = 0; -+ void *cmdline_buf; -+ int ret = 0; -+ -+ ret = load_elf(loaderparams.kernel_filename, NULL, cpu_loongarch_virt_to_phys, NULL, -+ (uint64_t *)&entry, (uint64_t *)&kernel_low, -+ (uint64_t *)&kernel_high, NULL, 0, EM_LOONGARCH, 1, 0); -+ -+ if(0 > ret) { -+ error_report("kernel image load error"); -+ exit(1); -+ } -+ -+ fw_cfg_add_i64(fw_cfg, FW_CFG_KERNEL_ENTRY, entry); -+ -+ if (loaderparams.initrd_filename) { -+ initrd_size = get_image_size(loaderparams.initrd_filename); -+ if (0 < initrd_size) { -+ if (initrd_size > highram_size) { -+ error_report("initrd size is too big, should below %ld MB", -+ highram_size / S_1MiB); -+ /*prevent write io memory address space*/ -+ exit(1); -+ } -+ initrd_offset = (phyAddr_initrd - initrd_size) & TARGET_REALPAGE_MASK; -+ initrd_size = load_image_targphys(loaderparams.initrd_filename, -+ initrd_offset, -+ loaderparams.ram_size - initrd_offset); -+ fw_cfg_add_i64(fw_cfg, FW_CFG_INITRD_ADDR, initrd_offset); -+ fw_cfg_add_i64(fw_cfg, FW_CFG_INITRD_SIZE, initrd_size); -+ } else { -+ error_report("initrd image size is error"); -+ } -+ } -+ -+ cmdline_buf = g_malloc0(COMMAND_LINE_SIZE); -+ if (initrd_size > 0) -+ ret = (1 + snprintf(cmdline_buf, COMMAND_LINE_SIZE, -+ "rd_start=0x%llx rd_size=%li %s", -+ PHYS_TO_VIRT(initrd_offset), -+ initrd_size, loaderparams.kernel_cmdline)); -+ else -+ ret = (1 + snprintf(cmdline_buf, COMMAND_LINE_SIZE, "%s", -+ loaderparams.kernel_cmdline)); -+ -+ fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE, ret); -+ fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA, (const char *)cmdline_buf); -+ -+ return ; -+} -+ -+static int64_t load_kernel(void) -+{ -+ int64_t entry, kernel_low, kernel_high; -+ long initrd_size = 0; -+ ram_addr_t initrd_offset = 0; -+ -+ load_elf(loaderparams.kernel_filename, NULL, cpu_loongarch_virt_to_phys, NULL, -+ (uint64_t *)&entry, (uint64_t *)&kernel_low, -+ (uint64_t *)&kernel_high, NULL, 0, EM_LOONGARCH, 1, 0); -+ -+ if (loaderparams.initrd_filename) { -+ initrd_size = get_image_size(loaderparams.initrd_filename); -+ -+ if (initrd_size > 0) { -+ initrd_offset = (kernel_high * 4 + ~TARGET_REALPAGE_MASK) -+ & TARGET_REALPAGE_MASK; -+ initrd_size = load_image_targphys(loaderparams.initrd_filename, -+ initrd_offset, -+ loaderparams.ram_size - initrd_offset); -+ } -+ } -+ set_bootparam_uefi(initrd_offset, initrd_size); -+ -+ return entry; -+} -+ -+static void main_cpu_reset(void *opaque) -+{ -+ ResetData *s = (ResetData *)opaque; -+ CPULOONGARCHState *env = &s->cpu->env; -+ -+ cpu_reset(CPU(s->cpu)); -+ env->active_tc.PC = s->vector; -+ env->active_tc.gpr[4] = loaderparams.a0; -+ env->active_tc.gpr[5] = loaderparams.a1; -+ env->active_tc.gpr[6] = loaderparams.a2; -+} -+ -+void slave_cpu_reset(void *opaque) -+{ -+ ResetData *s = (ResetData *)opaque; -+ -+ cpu_reset(CPU(s->cpu)); -+} -+ -+ -+/* KVM_IRQ_LINE irq field index values */ -+#define KVM_LOONGARCH_IRQ_TYPE_SHIFT 24 -+#define KVM_LOONGARCH_IRQ_TYPE_MASK 0xff -+#define KVM_LOONGARCH_IRQ_VCPU_SHIFT 16 -+#define KVM_LOONGARCH_IRQ_VCPU_MASK 0xff -+#define KVM_LOONGARCH_IRQ_NUM_SHIFT 0 -+#define KVM_LOONGARCH_IRQ_NUM_MASK 0xffff -+ -+/* irq_type field */ -+#define KVM_LOONGARCH_IRQ_TYPE_CPU_IP 0 -+#define KVM_LOONGARCH_IRQ_TYPE_CPU_IO 1 -+#define KVM_LOONGARCH_IRQ_TYPE_HT 2 -+#define KVM_LOONGARCH_IRQ_TYPE_MSI 3 -+#define KVM_LOONGARCH_IRQ_TYPE_IOAPIC 4 -+ -+static void legacy_set_irq(void *opaque, int irq, int level) -+{ -+ qemu_irq *pic = opaque; -+ -+ qemu_set_irq(pic[irq], level); -+} -+ -+typedef struct ls3a_intctlstate { -+ uint8_t nodecounter_reg[0x100]; -+ uint8_t pm_reg[0x100]; -+ uint8_t msi_reg[0x8]; -+ CPULOONGARCHState **env; -+ DeviceState *apicdev; -+ qemu_irq *ioapic_irq; -+#ifdef CONFIG_KVM -+ struct loongarch_kvm_irqchip chip; -+#endif -+} ls3a_intctlstate; -+ -+typedef struct ls3a_func_args { -+ ls3a_intctlstate *state; -+ uint64_t base; -+ uint32_t mask; -+ uint8_t *mem; -+} ls3a_func_args; -+ -+static uint64_t ls3a_msi_mem_read(void *opaque, hwaddr addr, unsigned size) -+{ -+ return 0; -+} -+ -+static void ls3a_msi_mem_write(void *opaque, hwaddr addr, -+ uint64_t val, unsigned size) -+{ -+ struct kvm_msi msi; -+ apicState *apic; -+ -+ apic = (apicState *)opaque; -+ msi.address_lo = 0; -+ msi.address_hi = 0; -+ msi.data = val & 0xff; -+ msi.flags = 0; -+ memset(msi.pad, 0, sizeof(msi.pad)); -+ -+ if (kvm_irqchip_in_kernel()) { -+ kvm_vm_ioctl(kvm_state, KVM_SIGNAL_MSI, &msi); -+ } else { -+ qemu_set_irq(apic->irq[msi.data], 1); -+ } -+} -+ -+ -+static const MemoryRegionOps ls3a_msi_ops = { -+ .read = ls3a_msi_mem_read, -+ .write = ls3a_msi_mem_write, -+ .endianness = DEVICE_NATIVE_ENDIAN, -+}; -+ -+ -+static const VMStateDescription vmstate_ls3a_msi = { -+ .name = "ls3a-msi", -+ .version_id = 0, -+ .minimum_version_id = 0, -+ .fields = (VMStateField[]) { -+ VMSTATE_UINT8_ARRAY(msi_reg, ls3a_intctlstate, 0x8), -+ VMSTATE_END_OF_LIST() -+ } -+}; -+ -+static void ioapic_handler(void *opaque, int irq, int level) -+{ -+ apicState *apic; -+ int kvm_irq; -+ -+ apic = (apicState *)opaque; -+ -+ if (kvm_irqchip_in_kernel()) { -+ kvm_irq = (KVM_LOONGARCH_IRQ_TYPE_IOAPIC << KVM_LOONGARCH_IRQ_TYPE_SHIFT) -+ | (0 << KVM_LOONGARCH_IRQ_VCPU_SHIFT) | irq; -+ kvm_set_irq(kvm_state, kvm_irq, !!level); -+ } else { -+ qemu_set_irq(apic->irq[irq], level); -+ } -+} -+ -+static void *ls3a_intctl_init(MachineState *machine, CPULOONGARCHState *env[]) -+{ -+ qemu_irq *irqhandler; -+ ls3a_intctlstate *s; -+ LoongarchMachineState *lsms = LoongarchMACHINE(machine); -+ LoongarchMachineClass *mc = LoongarchMACHINE_GET_CLASS(lsms); -+ DeviceState *dev; -+ SysBusDevice *busdev; -+ MemoryRegion *address_space_mem = get_system_memory(); -+ MemoryRegion *iomem = NULL; -+ int i; -+ -+ s = g_malloc0(sizeof(ls3a_intctlstate)); -+ -+ if (!s) { -+ return NULL; -+ } -+ -+ /*Add MSI mmio memory*/ -+ iomem = g_new(MemoryRegion, 1); -+ memory_region_init_io(iomem, NULL, &ls3a_msi_ops, lsms->apic, -+ "ls3a_msi", 0x8); -+ memory_region_add_subregion(address_space_mem, -+ MSI_ADDR_LOW, iomem); -+ vmstate_register(NULL, 0, &vmstate_ls3a_msi, s); -+ -+ s->env = env; -+ -+ if (!strcmp(mc->bridge_name, "ls7a")) { -+ if (lsms->apic_xrupt_override) { -+ DPRINTF("irqchip in kernel %d\n", kvm_irqchip_in_kernel()); -+#ifdef CONFIG_KVM -+ if (kvm_has_gsi_routing()) { -+ for (i = 0; i < 32; ++i) { -+ kvm_irqchip_add_irq_route(kvm_state, i, 0, i); -+ } -+ kvm_gsi_routing_allowed = true; -+ } -+ kvm_msi_via_irqfd_allowed = kvm_irqfds_enabled(); -+#endif -+ } -+ -+ irqhandler = qemu_allocate_irqs(ioapic_handler, lsms->apic, 64); -+ dev = qdev_new("ioapic"); -+ busdev = SYS_BUS_DEVICE(dev); -+ sysbus_realize_and_unref(busdev, &error_fatal); -+ sysbus_mmio_map(busdev, 0, mc->ls7a_ioapic_reg_base); -+ s->ioapic_irq = irqhandler; -+ s->apicdev = dev; -+ return s->ioapic_irq; -+ } -+ return NULL; -+} -+ -+/* Network support */ -+static void network_init(PCIBus *pci_bus) -+{ -+ int i; -+ -+ for (i = 0; i < nb_nics; i++) { -+ NICInfo *nd = &nd_table[i]; -+ -+ if (!nd->model) { -+ nd->model = g_strdup("virtio-net-pci"); -+ } -+ -+ pci_nic_init_nofail(nd, pci_bus, nd->model, NULL); -+ } -+} -+ -+void loongarch_cpu_destroy(MachineState *machine, LOONGARCHCPU *cpu) -+{ -+ LoongarchMachineState *lsms = LoongarchMACHINE(machine); -+ unsigned int id; -+ int smp_cpus = machine->smp.cpus; -+ id = cpu->id; -+ qemu_unregister_reset(slave_cpu_reset, lsms->reset_info[id]); -+ g_free(lsms->reset_info[id]); -+ lsms->reset_info[id] = NULL; -+ -+ smp_cpus -= 1; -+ if (lsms->fw_cfg) { -+ fw_cfg_modify_i16(lsms->fw_cfg, FW_CFG_NB_CPUS, -+ (uint16_t)smp_cpus); -+ } -+ -+ qemu_del_vm_change_state_handler(cpu->cpuStateEntry); -+} -+ -+LOONGARCHCPU *loongarch_cpu_create(MachineState *machine, -+ LOONGARCHCPU *cpu, Error **errp) -+{ -+ CPULOONGARCHState *env; -+ unsigned int id; -+ LoongarchMachineState *lsms = LoongarchMACHINE(machine); -+ int smp_cpus = machine->smp.cpus; -+ id = cpu->id; -+ env = &cpu->env; -+ cpu_states[id] = env; -+ env->CSR_TMID |= id; -+ -+ lsms = LoongarchMACHINE(machine); -+ lsms->reset_info[id] = g_malloc0(sizeof(ResetData)); -+ lsms->reset_info[id]->cpu = cpu; -+ lsms->reset_info[id]->vector = env->active_tc.PC; -+ qemu_register_reset(slave_cpu_reset, lsms->reset_info[id]); -+ -+ /* Init CPU internal devices */ -+ cpu_init_irq(cpu); -+ cpu_loongarch_clock_init(cpu); -+ -+ smp_cpus += 1; -+ if (lsms->fw_cfg) { -+ fw_cfg_modify_i16(lsms->fw_cfg, FW_CFG_NB_CPUS, (uint16_t)smp_cpus); -+ } -+ cpu_init_ipi(lsms, env->irq[12], id); -+ cpu_init_apic(lsms, env, id); -+ -+ return cpu; -+} -+ -+static void fw_cfg_boot_set(void *opaque, const char *boot_device, -+ Error **errp) -+{ -+ fw_cfg_modify_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]); -+} -+ -+static FWCfgState *loongarch_fw_cfg_init(ram_addr_t ram_size, -+ LoongarchMachineState *lsms) -+{ -+ FWCfgState *fw_cfg; -+ uint64_t *numa_fw_cfg; -+ int i; -+ const CPUArchIdList *cpus; -+ MachineClass *mc = MACHINE_GET_CLASS(lsms); -+ MachineState *ms = MACHINE(OBJECT(lsms)); -+ int max_cpus = ms->smp.max_cpus; -+ int smp_cpus = ms->smp.cpus; -+ int nb_numa_nodes = ms->numa_state->num_nodes; -+ NodeInfo *numa_info = ms->numa_state->nodes; -+ -+ fw_cfg = fw_cfg_init_mem_wide(FW_CFG_ADDR + 8, FW_CFG_ADDR, 8, 0, NULL); -+ fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus); -+ fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size); -+ fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, (uint16_t)smp_cpus); -+ -+ /* allocate memory for the NUMA channel: one (64bit) word for the number -+ * of nodes, one word for each VCPU->node and one word for each node to -+ * hold the amount of memory. -+ */ -+ numa_fw_cfg = g_new0(uint64_t, 1 + max_cpus + nb_numa_nodes); -+ numa_fw_cfg[0] = cpu_to_le64(nb_numa_nodes); -+ cpus = mc->possible_cpu_arch_ids(MACHINE(lsms)); -+ for (i = 0; i < cpus->len; i++) { -+ unsigned int apic_id = cpus->cpus[i].arch_id; -+ assert(apic_id < max_cpus); -+ numa_fw_cfg[apic_id + 1] = cpu_to_le64(cpus->cpus[i].props.node_id); -+ } -+ for (i = 0; i < nb_numa_nodes; i++) { -+ numa_fw_cfg[max_cpus + 1 + i] = -+ cpu_to_le64(numa_info[i].node_mem); -+ } -+ fw_cfg_add_bytes(fw_cfg, FW_CFG_NUMA, numa_fw_cfg, -+ (1 + max_cpus + nb_numa_nodes) * -+ sizeof(*numa_fw_cfg)); -+ -+ qemu_register_boot_set(fw_cfg_boot_set, fw_cfg); -+ return fw_cfg; -+} -+ -+static void loongarch_build_smbios(LoongarchMachineState *lsms) -+{ -+ LoongarchMachineClass *lsmc = LoongarchMACHINE_GET_CLASS(lsms); -+ MachineState *ms = MACHINE(OBJECT(lsms)); -+ uint8_t *smbios_tables, *smbios_anchor; -+ size_t smbios_tables_len, smbios_anchor_len; -+ const char *product = "QEMU Virtual Machine"; -+ ms->smp.cores = 4; -+ -+ if (!lsms->fw_cfg) { -+ return; -+ } -+ -+ if (kvm_enabled()) { -+ if (strstr(lsmc->cpu_name, "5000")) { -+ product = "KVM"; -+ } -+ } else { -+ product = "Loongarch-3A5K-7A1000-TCG"; -+ } -+ -+ host_cpufreq = get_host_cpu_freq(); -+ -+ smbios_set_defaults("Loongson", product, lsmc->cpu_name, false, -+ true, NULL, NULL, SMBIOS_ENTRY_POINT_30); -+ -+ smbios_get_tables(ms, NULL, 0, &smbios_tables, &smbios_tables_len, -+ &smbios_anchor, &smbios_anchor_len, &error_fatal); -+ -+ if (smbios_anchor) { -+ fw_cfg_add_file(lsms->fw_cfg, "etc/smbios/smbios-tables", -+ smbios_tables, smbios_tables_len); -+ fw_cfg_add_file(lsms->fw_cfg, "etc/smbios/smbios-anchor", -+ smbios_anchor, smbios_anchor_len); -+ } -+} -+ -+static -+void loongarch_machine_done(Notifier *notifier, void *data) -+{ -+ LoongarchMachineState *lsms = container_of(notifier, -+ LoongarchMachineState, machine_done); -+ loongarch_acpi_setup(); -+ loongarch_build_smbios(lsms); -+} -+ -+#ifdef CONFIG_TCG -+#define FEATURE_REG 0x1fe00008 -+#define VENDOR_REG 0x1fe00010 -+#define CPUNAME_REG 0x1fe00020 -+#define OTHER_FUNC_REG 0x1fe00420 -+#define _str(x) #x -+#define str(x) _str(x) -+#define SIMPLE_OPS(ADDR, SIZE) \ -+({\ -+ MemoryRegion *iomem = g_new(MemoryRegion, 1);\ -+ memory_region_init_io(iomem, NULL, &loongarch_qemu_ops, \ -+ (void *)ADDR, str(ADDR) , SIZE);\ -+ memory_region_add_subregion_overlap(address_space_mem, ADDR, iomem, 1);\ -+}) -+ -+static int reg180; -+ -+static void loongarch_qemu_write(void *opaque, hwaddr addr, -+ uint64_t val, unsigned size) -+{ -+ addr = ((hwaddr)(long)opaque) + addr; -+ addr = addr & 0xffffffff; -+ switch (addr) { -+ case 0x1fe00180: -+ reg180 = val; -+ break; -+ } -+} -+ -+static uint64_t loongarch_qemu_read(void *opaque, hwaddr addr, unsigned size) -+{ -+ uint64_t feature = 0UL; -+ addr = ((hwaddr)(long)opaque) + addr; -+ addr = addr & 0xffffffff; -+ switch (addr) { -+ case 0x1fe00180: -+ return reg180; -+ case 0x1001041c: -+ return 0xa800; -+ case FEATURE_REG: -+ feature |= 1UL << 2 | 1UL << 3 | 1UL << 4 | 1UL << 11; -+ return feature ; -+ case VENDOR_REG: -+ return *(uint64_t *)"Loongson-3A5000"; -+ case CPUNAME_REG: -+ return *(uint64_t *)"3A5000"; -+ case 0x10013ffc: -+ return 0x80; -+ } -+ return 0; -+} -+ -+static const MemoryRegionOps loongarch_qemu_ops = { -+ .read = loongarch_qemu_read, -+ .write = loongarch_qemu_write, -+ .endianness = DEVICE_NATIVE_ENDIAN, -+ .valid = { -+ .min_access_size = 4, -+ .max_access_size = 8, -+ }, -+ .impl = { -+ .min_access_size = 4, -+ .max_access_size = 8, -+ }, -+}; -+#endif -+ -+ -+static void loongarch_system_flash_cleanup_unused(LoongarchMachineState *lsms) -+{ -+ char *prop_name; -+ int i; -+ Object *dev_obj; -+ -+ for (i = 0; i < ARRAY_SIZE(lsms->flash); i++) { -+ dev_obj = OBJECT(lsms->flash[i]); -+ if (!object_property_get_bool(dev_obj, "realized", &error_abort)) { -+ prop_name = g_strdup_printf("pflash%d", i); -+ object_property_del(OBJECT(lsms), prop_name); -+ g_free(prop_name); -+ object_unparent(dev_obj); -+ lsms->flash[i] = NULL; -+ } -+ } -+} -+ -+ -+static bool loongarch_system_flash_init( LoongarchMachineState *lsms) -+{ -+ int i = 0; -+ int64_t size = 0; -+ PFlashCFI01 *pflash = NULL; -+ BlockBackend *pflash_blk; -+ -+ for(i = 0; i < ARRAY_SIZE(lsms->flash); i++) { -+ pflash_blk = NULL; -+ pflash = NULL; -+ -+ pflash = lsms->flash[i]; -+ pflash_cfi01_legacy_drive(pflash, -+ drive_get(IF_PFLASH, 0, i)); -+ -+ pflash_blk = pflash_cfi01_get_blk(pflash); -+ /*The pflash0 must be exist, or not support boot by pflash*/ -+ if(pflash_blk == NULL) { -+ if(i == 0) { -+ return false; -+ } else { -+ break; -+ } -+ } -+ -+ size = blk_getlength(pflash_blk); -+ if (size == 0 || size % FLASH_SECTOR_SIZE != 0) { -+ error_report("system firmware block device %s has invalid size " -+ "%" PRId64, -+ blk_name(pflash_blk), size); -+ error_report("its size must be a non-zero multiple of 0x%x", -+ FLASH_SECTOR_SIZE); -+ exit(1); -+ } -+ qdev_prop_set_uint32(DEVICE(pflash), "num-blocks", -+ size / FLASH_SECTOR_SIZE); -+ sysbus_realize_and_unref(SYS_BUS_DEVICE(pflash), &error_fatal); -+ if(i == 0) { -+ sysbus_mmio_map(SYS_BUS_DEVICE(pflash), 0, LS_BIOS_BASE); -+ } else { -+ sysbus_mmio_map_overlap(SYS_BUS_DEVICE(pflash), 0, LS_BIOS_VAR_BASE, 1); -+ } -+ } -+ -+ return true; -+} -+static void ls3a5k_bios_init(LoongarchMachineState *lsms, -+ ram_addr_t ram_size, -+ uint64_t highram_size, -+ uint64_t phyAddr_initrd, -+ const char *kernel_filename, -+ const char *kernel_cmdline, -+ const char *initrd_filename) -+{ -+ MemoryRegion *bios; -+ bool fw_cfg_used = false; -+ LoongarchMachineClass *lsmc = LoongarchMACHINE_GET_CLASS(lsms); -+ char *filename; -+ int bios_size; -+ const char *bios_name; -+ -+ bios_name = MACHINE(lsms)->firmware; -+ if (kernel_filename) { -+ loaderparams.ram_size = ram_size; -+ loaderparams.kernel_filename = kernel_filename; -+ loaderparams.kernel_cmdline = kernel_cmdline; -+ loaderparams.initrd_filename = initrd_filename; -+ } -+ -+ if(loongarch_system_flash_init(lsms)) { -+ fw_cfg_used = true; -+ } else { -+ bios = g_new(MemoryRegion, 1); -+ memory_region_init_ram(bios, NULL, "loongarch.bios", LS_BIOS_SIZE, &error_fatal); -+ memory_region_set_readonly(bios, true); -+ memory_region_add_subregion(get_system_memory(), LS_BIOS_BASE, bios); -+ -+ /* BIOS load */ -+ if (bios_name) { -+ if (access(bios_name, R_OK) == 0) { -+ load_image_targphys(bios_name, LS_BIOS_BASE, LS_BIOS_SIZE); -+ } else { -+ filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); -+ load_image_targphys(filename, LS_BIOS_BASE, LS_BIOS_SIZE); -+ g_free(filename); -+ } -+ fw_cfg_used = true; -+ } else { -+ if (strstr(lsmc->cpu_name, "5000")) { -+ bios_size = sizeof(ls3a5k_aui_boot_code); -+ rom_add_blob_fixed("bios", ls3a5k_aui_boot_code, bios_size, LS_BIOS_BASE); -+ } -+ -+ if (kernel_filename) { -+ lsms->reset_info[0]->vector = load_kernel(); -+ } else { -+ error_report("Please specify at lease one of -bios and -kernel"); -+ exit(1); -+ } -+ } -+ } -+ -+ loongarch_system_flash_cleanup_unused(lsms); -+ -+ if (fw_cfg_used) { -+ lsms->fw_cfg = loongarch_fw_cfg_init(ram_size, lsms); -+ rom_set_fw(lsms->fw_cfg); -+ fw_conf_init(ram_size); -+ rom_add_blob_fixed("fw_conf", (void *)&fw_config, -+ sizeof(fw_config), FW_CONF_ADDR); -+ -+ if (kernel_filename) { -+ fw_cfg_add_kernel_info(lsms->fw_cfg, highram_size, phyAddr_initrd); -+ } -+ } -+ -+ if (lsms->fw_cfg != NULL) { -+ fw_cfg_add_file(lsms->fw_cfg, "etc/memmap", -+ la_memmap_table, -+ sizeof(struct la_memmap_entry) * (la_memmap_entries)); -+ } -+ -+ return ; -+} -+static void create_fdt(LoongarchMachineState *lsms) -+{ -+ lsms->fdt = create_device_tree(&lsms->fdt_size); -+ if (!lsms->fdt) { -+ error_report("create_device_tree() failed"); -+ exit(1); -+ } -+ -+ /* Header */ -+ qemu_fdt_setprop_string(lsms->fdt, "/", "compatible", -+ "linux,dummy-loongson3"); -+ qemu_fdt_setprop_cell(lsms->fdt, "/", "#address-cells", 0x2); -+ qemu_fdt_setprop_cell(lsms->fdt, "/", "#size-cells", 0x2); -+} -+ -+static void fdt_add_cpu_nodes(const LoongarchMachineState *lsms) -+{ -+ int num; -+ const MachineState *ms = MACHINE(lsms); -+ int smp_cpus = ms->smp.cpus; -+ -+ qemu_fdt_add_subnode(lsms->fdt, "/cpus"); -+ qemu_fdt_setprop_cell(lsms->fdt, "/cpus", "#address-cells", 0x1); -+ qemu_fdt_setprop_cell(lsms->fdt, "/cpus", "#size-cells", 0x0); -+ -+ /* cpu nodes */ -+ for (num = smp_cpus - 1; num >= 0; num--) { -+ char *nodename = g_strdup_printf("/cpus/cpu@%d", num); -+ LOONGARCHCPU *cpu = LOONGARCH_CPU(qemu_get_cpu(num)); -+ -+ qemu_fdt_add_subnode(lsms->fdt, nodename); -+ qemu_fdt_setprop_string(lsms->fdt, nodename, "device_type", "cpu"); -+ qemu_fdt_setprop_string(lsms->fdt, nodename, "compatible", -+ cpu->dtb_compatible); -+ qemu_fdt_setprop_cell(lsms->fdt, nodename, "reg", num); -+ qemu_fdt_setprop_cell(lsms->fdt, nodename, "phandle", -+ qemu_fdt_alloc_phandle(lsms->fdt)); -+ g_free(nodename); -+ } -+ -+ /*cpu map */ -+ qemu_fdt_add_subnode(lsms->fdt, "/cpus/cpu-map"); -+ -+ for (num = smp_cpus - 1; num >= 0; num--) { -+ char *cpu_path = g_strdup_printf("/cpus/cpu@%d", num); -+ char *map_path; -+ -+ if (ms->smp.threads > 1) { -+ map_path = g_strdup_printf( -+ "/cpus/cpu-map/socket%d/core%d/thread%d", -+ num / (ms->smp.cores * ms->smp.threads), -+ (num / ms->smp.threads) % ms->smp.cores, -+ num % ms->smp.threads); -+ } else { -+ map_path = g_strdup_printf( -+ "/cpus/cpu-map/socket%d/core%d", -+ num / ms->smp.cores, -+ num % ms->smp.cores); -+ } -+ qemu_fdt_add_path(lsms->fdt, map_path); -+ qemu_fdt_setprop_phandle(lsms->fdt, map_path, "cpu", cpu_path); -+ -+ g_free(map_path); -+ g_free(cpu_path); -+ } -+} -+ -+static void fdt_add_fw_cfg_node(const LoongarchMachineState *lsms) -+{ -+ char *nodename; -+ hwaddr base = FW_CFG_ADDR; -+ -+ nodename = g_strdup_printf("/fw_cfg@%" PRIx64, base); -+ qemu_fdt_add_subnode(lsms->fdt, nodename); -+ qemu_fdt_setprop_string(lsms->fdt, nodename, -+ "compatible", "qemu,fw-cfg-mmio"); -+ qemu_fdt_setprop_sized_cells(lsms->fdt, nodename, "reg", -+ 2, base, 2, 0x8); -+ qemu_fdt_setprop(lsms->fdt, nodename, "dma-coherent", NULL, 0); -+ g_free(nodename); -+} -+ -+static void fdt_add_pcie_node(const LoongarchMachineState *lsms) -+{ -+ char *nodename; -+ hwaddr base_mmio = LS_ISA_MEM_BASE; -+ hwaddr size_mmio = LS_ISA_MEM_SIZE; -+ hwaddr base_pio = LS3A5K_ISA_IO_BASE; -+ hwaddr size_pio = LS_ISA_IO_SIZE; -+ hwaddr base_pcie = LS_PCIECFG_BASE; -+ hwaddr size_pcie = LS_PCIECFG_SIZE; -+ hwaddr base = base_pcie; -+ -+ nodename = g_strdup_printf("/pcie@%" PRIx64, base); -+ qemu_fdt_add_subnode(lsms->fdt, nodename); -+ qemu_fdt_setprop_string(lsms->fdt, nodename, -+ "compatible", "pci-host-ecam-generic"); -+ qemu_fdt_setprop_string(lsms->fdt, nodename, "device_type", "pci"); -+ qemu_fdt_setprop_cell(lsms->fdt, nodename, "#address-cells", 3); -+ qemu_fdt_setprop_cell(lsms->fdt, nodename, "#size-cells", 2); -+ qemu_fdt_setprop_cell(lsms->fdt, nodename, "linux,pci-domain", 0); -+ qemu_fdt_setprop_cells(lsms->fdt, nodename, "bus-range", 0, -+ PCIE_MMCFG_BUS(LS_PCIECFG_SIZE - 1)); -+ qemu_fdt_setprop(lsms->fdt, nodename, "dma-coherent", NULL, 0); -+ qemu_fdt_setprop_sized_cells(lsms->fdt, nodename, "reg", -+ 2, base_pcie, 2, size_pcie); -+ qemu_fdt_setprop_sized_cells(lsms->fdt, nodename, "ranges", -+ 1, FDT_PCI_RANGE_IOPORT, 2, 0, -+ 2, base_pio, 2, size_pio, -+ 1, FDT_PCI_RANGE_MMIO, 2, base_mmio, -+ 2, base_mmio, 2, size_mmio); -+ g_free(nodename); -+ qemu_fdt_dumpdtb(lsms->fdt, lsms->fdt_size); -+} -+ -+static void ls3a5k_init(MachineState *args) -+{ -+ int i; -+ const char *cpu_model = args->cpu_type; -+ const char *kernel_filename = args->kernel_filename; -+ const char *kernel_cmdline = args->kernel_cmdline; -+ const char *initrd_filename = args->initrd_filename; -+ -+ ram_addr_t ram_size = args->ram_size; -+ MemoryRegion *address_space_mem = get_system_memory(); -+ ram_addr_t offset = 0; -+ MemoryRegion *isa_io = g_new(MemoryRegion, 1); -+ MemoryRegion *isa_mem = g_new(MemoryRegion, 1); -+ MachineState *machine = args; -+ MachineClass *mc = MACHINE_GET_CLASS(machine); -+ LoongarchMachineState *lsms = LoongarchMACHINE(machine); -+ LoongarchMachineClass *lsmc = LoongarchMACHINE_GET_CLASS(lsms); -+ int smp_cpus = machine->smp.cpus; -+ int nb_numa_nodes = machine->numa_state->num_nodes; -+ NodeInfo *numa_info = machine->numa_state->nodes; -+ LOONGARCHCPU *cpu; -+ CPULOONGARCHState *env; -+ qemu_irq *ls7a_apic = NULL; -+ qemu_irq *pirq = NULL; -+ PCIBus *pci_bus = NULL; -+ char *ramName = NULL; -+ uint64_t lowram_size = 0, highram_size = 0, phyAddr = 0, -+ memmap_size = 0, highram_end_addr = 0; -+ -+ CPUArchIdList *possible_cpus; -+ if (strstr(lsmc->cpu_name, "5000")) { -+ if (strcmp(cpu_model, LOONGARCH_CPU_TYPE_NAME("Loongson-3A5000")) && -+ strcmp(cpu_model, LOONGARCH_CPU_TYPE_NAME("host"))) { -+ error_report("machine type %s does not match cpu type %s", -+ lsmc->cpu_name, cpu_model); -+ exit(1); -+ } -+ if (kvm_enabled()) { -+ kvm_vm_ioctl(kvm_state, KVM_LARCH_SET_CPUCFG, ls3a5k_cpucfgs); -+ } -+ } -+ -+ create_fdt(lsms); -+ -+ DPRINTF("isa 0x%lx\n", lsmc->isa_io_base); -+ DPRINTF("ht1lo 0x%lx\n", lsmc->ht1lo_pcicfg_base); -+ DPRINTF("cpu_name %s bridge_name %s\n", -+ lsmc->cpu_name, lsmc->bridge_name); -+ -+ /* init CPUs */ -+ mc->possible_cpu_arch_ids(machine); -+ possible_cpus = machine->possible_cpus; -+ -+ for (i = 0; i < smp_cpus; i++) { -+ Object *obj = NULL; -+ Error *local_err = NULL; -+ -+ obj = object_new(possible_cpus->cpus[i].type); -+ -+ object_property_set_uint(obj, "id", possible_cpus->cpus[i].arch_id, -+ &local_err); -+ object_property_set_bool(obj, "realized", true, &local_err); -+ -+ object_unref(obj); -+ error_propagate(&error_fatal, local_err); -+ -+ cpu = LOONGARCH_CPU(CPU(obj)); -+ if (cpu == NULL) { -+ fprintf(stderr, "Unable to find CPU definition\n"); -+ exit(1); -+ } -+ -+ env = &cpu->env; -+ cpu_states[i] = env; -+ env->CSR_TMID |= i; -+ -+ lsms->reset_info[i] = g_malloc0(sizeof(ResetData)); -+ lsms->reset_info[i]->cpu = cpu; -+ lsms->reset_info[i]->vector = env->active_tc.PC; -+ if (i == 0) { -+ qemu_register_reset(main_cpu_reset, lsms->reset_info[i]); -+ } else { -+ qemu_register_reset(slave_cpu_reset, lsms->reset_info[i]); -+ } -+ -+ /* Init CPU internal devices */ -+ cpu_init_irq(cpu); -+ cpu_loongarch_clock_init(cpu); -+ cpu_init_ipi(lsms, env->irq[12], i); -+ cpu_init_apic(lsms, env, i); -+ } -+ -+ lsms->hotpluged_cpu_num = 0; -+ fdt_add_cpu_nodes(lsms); -+ env = cpu_states[0]; -+ -+ /* node0 mem*/ -+ phyAddr = (uint64_t)0; -+ MemoryRegion *lowmem = g_new(MemoryRegion, 1); -+ ramName = g_strdup_printf("loongarch_ls3a.node%d.lowram", 0); -+ -+ lowram_size = MIN(ram_size, 256 * 0x100000); -+ memory_region_init_alias(lowmem, NULL, ramName, machine->ram, 0, lowram_size); -+ memory_region_add_subregion(address_space_mem, phyAddr, lowmem); -+ -+ offset += lowram_size; -+ if (nb_numa_nodes > 0) { -+ highram_size = numa_info[0].node_mem - S_256MiB; -+ if (numa_info[0].node_mem > S_1GiB) { -+ memmap_size = numa_info[0].node_mem - S_1GiB; -+ la_memmap_add_entry(0xc0000000ULL, memmap_size, SYSTEM_RAM); -+ } -+ } else { -+ highram_size = ram_size - S_256MiB; -+ if (ram_size > S_1GiB) { -+ memmap_size = ram_size - S_1GiB; -+ la_memmap_add_entry(0xc0000000ULL, memmap_size, SYSTEM_RAM); -+ } -+ } -+ -+ phyAddr = (uint64_t)0x90000000; -+ MemoryRegion *highmem = g_new(MemoryRegion, 1); -+ ramName = g_strdup_printf("loongarch_ls3a.node%d.highram", 0); -+ memory_region_init_alias(highmem, NULL, ramName, -+ machine->ram, offset, highram_size); -+ memory_region_add_subregion(address_space_mem, -+ phyAddr, highmem); -+ offset += highram_size; -+ phyAddr += highram_size; -+ -+ /* initrd address use high mem from high to low */ -+ highram_end_addr = phyAddr; -+ /* node1~ nodemax */ -+ for (i = 1; i < nb_numa_nodes; i++) { -+ MemoryRegion *nodemem = g_new(MemoryRegion, 1); -+ ramName = g_strdup_printf("loongarch_ls3a.node%d.ram", i); -+ memory_region_init_alias(nodemem, NULL, ramName, -+ machine->ram, offset, numa_info[i].node_mem); -+ memory_region_add_subregion(address_space_mem, -+ phyAddr, nodemem); -+ la_memmap_add_entry(phyAddr, numa_info[i].node_mem, SYSTEM_RAM); -+ offset += numa_info[i].node_mem; -+ phyAddr += numa_info[i].node_mem; -+ } -+ -+ fdt_add_fw_cfg_node(lsms); -+ ls3a5k_bios_init(lsms, ram_size, highram_size, highram_end_addr, -+ kernel_filename, kernel_cmdline, initrd_filename); -+ -+ lsms->machine_done.notify = loongarch_machine_done; -+ qemu_add_machine_init_done_notifier(&lsms->machine_done); -+ /*vmstate_register_ram_global(bios);*/ -+ -+ /* initialize hotplug memory address space */ -+ lsms->hotplug_memory_size = 0; -+ -+ /* always allocate the device memory information */ -+ machine->device_memory = g_malloc0(sizeof(*machine->device_memory)); -+ if (machine->ram_size < machine->maxram_size) { -+ int max_memslots; -+ -+ lsms->hotplug_memory_size = machine->maxram_size - machine->ram_size; -+ /* -+ * Limit the number of hotpluggable memory slots to half the number -+ * slots that KVM supports, leaving the other half for PCI and other -+ * devices. However ensure that number of slots doesn't drop below 32. -+ */ -+ max_memslots = LOONGARCH_MAX_RAM_SLOTS; -+ if (kvm_enabled()) { -+ max_memslots = kvm_get_max_memslots() / 2 ; -+ } -+ -+ if (machine->ram_slots == 0) -+ machine->ram_slots = lsms->hotplug_memory_size / -+ LOONGARCH_HOTPLUG_MEM_ALIGN; -+ -+ if (machine->ram_slots > max_memslots) { -+ error_report("Specified number of memory slots %" -+ PRIu64" exceeds max supported %d", -+ machine->ram_slots, max_memslots); -+ exit(1); -+ } -+ -+ lsms->ram_slots = machine->ram_slots; -+ -+ machine->device_memory->base = get_hotplug_membase(machine->ram_size); -+ memory_region_init(&machine->device_memory->mr, OBJECT(lsms), -+ "device-memory", lsms->hotplug_memory_size); -+ memory_region_add_subregion(get_system_memory(), -+ machine->device_memory->base, -+ &machine->device_memory->mr); -+ } -+ -+ memory_region_init_alias(isa_io, NULL, "isa-io", -+ get_system_io(), 0, LS_ISA_IO_SIZE); -+ memory_region_init(isa_mem, NULL, "isa-mem", LS_ISA_MEM_SIZE); -+ memory_region_add_subregion(get_system_memory(), lsmc->isa_io_base, isa_io); -+ memory_region_add_subregion(get_system_memory(), LS_ISA_MEM_BASE, isa_mem); -+ -+ if (!strcmp(lsmc->bridge_name, "ls7a")) { -+ /*Initialize the 7A IO interrupt subsystem*/ -+ DeviceState *ls7a_dev; -+ lsms->apic_xrupt_override = kvm_irqchip_in_kernel(); -+ ls7a_apic = ls3a_intctl_init(machine, cpu_states); -+ if (!ls7a_apic) { -+ perror("Init 7A APIC failed\n"); -+ exit(1); -+ } -+ pci_bus = ls7a_init(machine, ls7a_apic, &ls7a_dev); -+ -+ object_property_add_link(OBJECT(machine), -+ LOONGARCH_MACHINE_ACPI_DEVICE_PROP, -+ TYPE_HOTPLUG_HANDLER, -+ (Object **)&lsms->acpi_dev, -+ object_property_allow_set_link, -+ OBJ_PROP_LINK_STRONG); -+ object_property_set_link(OBJECT(machine), LOONGARCH_MACHINE_ACPI_DEVICE_PROP, -+ OBJECT(ls7a_dev), &error_abort); -+ -+#ifdef CONFIG_KVM -+ if (kvm_enabled()) { -+ kvm_direct_msi_allowed = (kvm_check_extension(kvm_state, -+ KVM_CAP_SIGNAL_MSI) > 0); -+ } else { -+ kvm_direct_msi_allowed = 0; -+ } -+ msi_nonbroken = kvm_direct_msi_allowed; -+#else -+ msi_nonbroken = true; -+#endif -+ sysbus_create_simple("ls7a_rtc", LS7A_RTC_REG_BASE, -+ ls7a_apic[LS7A_RTC_IRQ - LOONGARCH_PCH_IRQ_BASE]); -+ } -+ -+ /*Initialize the CPU serial device*/ -+ -+ if (serial_hd(0)) { -+ pirq = qemu_allocate_irqs(legacy_set_irq, ls7a_apic + -+ (LS7A_UART_IRQ - LOONGARCH_PCH_IRQ_BASE), 1); -+ serial_mm_init(address_space_mem, LS7A_UART_BASE, 0, pirq[0], -+ 115200, serial_hd(0), DEVICE_NATIVE_ENDIAN); -+ } -+ -+ /*network card*/ -+ network_init(pci_bus); -+ /* VGA setup. Don't bother loading the bios. */ -+ pci_vga_init(pci_bus); -+ -+ sysbus_realize_and_unref(SYS_BUS_DEVICE(qdev_new("iocsr")), &error_fatal); -+ -+#ifdef CONFIG_TCG -+ int nb_nodes = (smp_cpus - 1) / 4; -+ for (i = 0; i <= nb_nodes; i++) { -+ uint64_t off = (uint64_t)i << 44; -+ SIMPLE_OPS(((hwaddr)0x1fe00180 | off), 0x8); -+ SIMPLE_OPS(((hwaddr)0x1fe0019c | off), 0x8); -+ SIMPLE_OPS(((hwaddr)0x1fe001d0 | off), 0x8); -+ SIMPLE_OPS(((hwaddr)FEATURE_REG | off), 0x8); -+ SIMPLE_OPS(((hwaddr)VENDOR_REG | off), 0x8); -+ SIMPLE_OPS(((hwaddr)CPUNAME_REG | off), 0x8); -+ SIMPLE_OPS(((hwaddr)OTHER_FUNC_REG | off), 0x8); -+ } -+ -+ SIMPLE_OPS(0x1001041c, 0x4); -+ SIMPLE_OPS(0x10002000, 0x14); -+ SIMPLE_OPS(0x10013ffc, 0x4); -+#endif -+ -+ fdt_add_pcie_node(lsms); -+ -+ /* load fdt */ -+ MemoryRegion *fdt_rom = g_new(MemoryRegion, 1); -+ memory_region_init_rom(fdt_rom, NULL, "fdt", LS_FDT_SIZE, &error_fatal); -+ memory_region_add_subregion(get_system_memory(), LS_FDT_BASE, fdt_rom); -+ rom_add_blob_fixed("fdt", lsms->fdt, lsms->fdt_size, LS_FDT_BASE); -+} -+ -+static const CPUArchIdList *loongarch_possible_cpu_arch_ids(MachineState *ms) -+{ -+ int i; -+ int max_cpus = ms->smp.max_cpus; -+ -+ if (ms->possible_cpus) { -+ /* -+ * make sure that max_cpus hasn't changed since the first use, i.e. -+ * -smp hasn't been parsed after it -+ */ -+ assert(ms->possible_cpus->len == max_cpus); -+ return ms->possible_cpus; -+ } -+ -+ ms->possible_cpus = g_malloc0(sizeof(CPUArchIdList) + -+ sizeof(CPUArchId) * max_cpus); -+ ms->possible_cpus->len = max_cpus; -+ for (i = 0; i < ms->possible_cpus->len; i++) { -+ ms->possible_cpus->cpus[i].type = ms->cpu_type; -+ ms->possible_cpus->cpus[i].vcpus_count = 1; -+ ms->possible_cpus->cpus[i].props.has_core_id = true; -+ ms->possible_cpus->cpus[i].props.core_id = i; -+ ms->possible_cpus->cpus[i].arch_id = i; -+ } -+ return ms->possible_cpus; -+ -+} -+ -+static PFlashCFI01 *loongarch_pflash_create(LoongarchMachineState *lsms, -+ const char *name, -+ const char *alias_prop_name) -+{ -+ DeviceState *dev = qdev_new(TYPE_PFLASH_CFI01); -+ -+ qdev_prop_set_uint64(dev, "sector-length", FLASH_SECTOR_SIZE); -+ qdev_prop_set_uint8(dev, "width", 1); -+ qdev_prop_set_string(dev, "name", name); -+ object_property_add_child(OBJECT(lsms), name, OBJECT(dev)); -+ object_property_add_alias(OBJECT(lsms), alias_prop_name, -+ OBJECT(dev), "drive"); -+ return PFLASH_CFI01(dev); -+} -+ -+ -+static void loongarch_system_flash_create(LoongarchMachineState *lsms) -+{ -+ lsms->flash[0] = loongarch_pflash_create(lsms, "system.flash0", -+ "pflash0"); -+ lsms->flash[1] = loongarch_pflash_create(lsms, "system.flash1", -+ "pflash1"); -+} -+ -+static void loongarch_machine_initfn(Object *obj) -+{ -+ LoongarchMachineState *lsms = LoongarchMACHINE(obj); -+ LoongarchMachineClass *lsmc = LoongarchMACHINE_GET_CLASS(lsms); -+ lsms->acpi_build_enabled = lsmc->has_acpi_build; -+ loongarch_system_flash_create(lsms); -+ lsms->oem_id = g_strndup(EFI_ACPI_OEM_ID, 6); -+ lsms->oem_table_id = g_strndup(EFI_ACPI_OEM_TABLE_ID, 6); -+} -+ -+static void ls3a5k_ls7a_machine_options(MachineClass *m) -+{ -+ char *cpu_name = get_host_cpu_model_name(); -+ LoongarchMachineClass *lsmc = LoongarchMACHINE_CLASS(m); -+ m->desc = "Loongarch3a5k LS7A1000 machine"; -+ m->max_cpus = LOONGARCH_MAX_VCPUS; -+ m->alias = "loongson7a"; -+ m->is_default = 1; -+ lsmc->isa_io_base = LS3A5K_ISA_IO_BASE; -+ lsmc->ht1lo_pcicfg_base = LS3A5K_HT1LO_PCICFG_BASE; -+ lsmc->pciecfg_base = LS_PCIECFG_BASE; -+ lsmc->ls7a_ioapic_reg_base = LS3A5K_LS7A_IOAPIC_REG_BASE; -+ lsmc->node_shift = 44; -+ strncpy(lsmc->cpu_name, cpu_name, sizeof(lsmc->cpu_name) - 1); -+ lsmc->cpu_name[sizeof(lsmc->cpu_name) - 1] = 0; -+ strncpy(lsmc->bridge_name, "ls7a", sizeof(lsmc->bridge_name) - 1); -+ lsmc->bridge_name[sizeof(lsmc->bridge_name) - 1] = 0; -+ compat_props_add(m->compat_props, loongarch_compat, loongarch_compat_len); -+} -+ -+static void ls3a_board_reset(MachineState *ms) -+{ -+ qemu_devices_reset(); -+#ifdef CONFIG_KVM -+ struct loongarch_kvm_irqchip *chip; -+ int length; -+ -+ if (!kvm_enabled()) { -+ return; -+ } -+ length = sizeof(struct loongarch_kvm_irqchip) + -+ sizeof(struct loongarch_gipiState); -+ chip = g_malloc0(length); -+ memset(chip, 0, length); -+ chip->chip_id = KVM_IRQCHIP_LS3A_GIPI; -+ chip->len = length; -+ kvm_vm_ioctl(kvm_state, KVM_SET_IRQCHIP, chip); -+ -+ length = sizeof(struct loongarch_kvm_irqchip) + sizeof(struct ls7a_ioapic_state); -+ chip = g_realloc(chip, length); -+ memset(chip, 0, length); -+ chip->chip_id = KVM_IRQCHIP_LS7A_IOAPIC; -+ chip->len = length; -+ kvm_vm_ioctl(kvm_state, KVM_SET_IRQCHIP, chip); -+ -+ g_free(chip); -+#endif -+} -+ -+static CpuInstanceProperties ls3a_cpu_index_to_props(MachineState *ms, unsigned cpu_index) -+{ -+ MachineClass *mc = MACHINE_GET_CLASS(ms); -+ const CPUArchIdList *possible_cpus = mc->possible_cpu_arch_ids(ms); -+ -+ assert(cpu_index < possible_cpus->len); -+ return possible_cpus->cpus[cpu_index].props; -+} -+ -+static int64_t ls3a_get_default_cpu_node_id(const MachineState *ms, int idx) -+{ -+ int nb_numa_nodes = ms->numa_state->num_nodes; -+ int smp_cores = ms->smp.cores; -+ return idx / smp_cores % nb_numa_nodes; -+} -+ -+static void loongarch_class_init(ObjectClass *oc, void *data) -+{ -+ MachineClass *mc = MACHINE_CLASS(oc); -+ HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc); -+ LoongarchMachineClass *lsmc = LoongarchMACHINE_CLASS(oc); -+ -+ lsmc->get_hotplug_handler = mc->get_hotplug_handler; -+ lsmc->has_acpi_build = true; -+ mc->get_hotplug_handler = loongarch_get_hotpug_handler; -+ mc->has_hotpluggable_cpus = true; -+ mc->cpu_index_to_instance_props = ls3a_cpu_index_to_props; -+ mc->possible_cpu_arch_ids = loongarch_possible_cpu_arch_ids; -+ mc->get_default_cpu_node_id = ls3a_get_default_cpu_node_id; -+ mc->default_ram_size = 1 * GiB; -+ mc->default_cpu_type = LOONGARCH_CPU_TYPE_NAME("Loongson-3A5000"); -+ mc->default_ram_id = "loongarch_ls3a.ram"; -+ -+ mc->reset = ls3a_board_reset; -+ mc->max_cpus = LOONGARCH_MAX_VCPUS; -+ hc->pre_plug = loongarch_machine_device_pre_plug; -+ hc->plug = loongarch_machine_device_plug; -+ hc->unplug = longson_machine_device_unplug; -+ hc->unplug_request = loongarch_machine_device_unplug_request; -+ -+ object_class_property_add(oc, "acpi", "OnOffAuto", -+ loongarch_get_acpi, loongarch_set_acpi, -+ NULL, NULL); -+ object_class_property_set_description(oc, "acpi", -+ "Enable ACPI"); -+} -+ -+static const TypeInfo loongarch_info = { -+ .name = TYPE_LOONGARCH_MACHINE, -+ .parent = TYPE_MACHINE, -+ .abstract = true, -+ .instance_size = sizeof(LoongarchMachineState), -+ .instance_init = loongarch_machine_initfn, -+ .class_size = sizeof(LoongarchMachineClass), -+ .class_init = loongarch_class_init, -+ .interfaces = (InterfaceInfo[]) { -+ { TYPE_HOTPLUG_HANDLER }, -+ { } -+ }, -+ -+}; -+ -+static void loongarch_machine_register_types(void) -+{ -+ type_register_static(&loongarch_info); -+} -+ -+type_init(loongarch_machine_register_types) -+ -+DEFINE_LS3A5K_MACHINE(loongson7a_v1_0, "loongson7a_v1.0", -+ ls3a5k_ls7a_machine_options); -diff --git a/hw/loongarch/larch_hotplug.c b/hw/loongarch/larch_hotplug.c -new file mode 100644 -index 0000000000..7bce957124 ---- /dev/null -+++ b/hw/loongarch/larch_hotplug.c -@@ -0,0 +1,355 @@ -+/* -+ * Hotplug emulation on Loongarch system. -+ * -+ * Copyright (c) 2018 Loongarch Inc. -+ * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2 of the License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library; if not, see . -+ */ -+ -+#include "qemu/osdep.h" -+#include "qapi/error.h" -+#include "qemu-common.h" -+#include "qemu/queue.h" -+#include "qemu/units.h" -+#include "qemu/cutils.h" -+#include "qemu/bcd.h" -+#include "hw/hotplug.h" -+#include "hw/loongarch/cpudevs.h" -+#include "hw/mem/memory-device.h" -+#include "sysemu/numa.h" -+#include "sysemu/cpus.h" -+#include "hw/loongarch/larch.h" -+#include "hw/cpu/core.h" -+#include "hw/nvram/fw_cfg.h" -+ -+/* find cpu slot in machine->possible_cpus by core_id */ -+static CPUArchId *loongarch_find_cpu_slot(MachineState *ms, uint32_t id, -+ int *idx) -+{ -+ int index = id; -+ -+ if (index >= ms->possible_cpus->len) { -+ return NULL; -+ } -+ if (idx) { -+ *idx = index; -+ } -+ return &ms->possible_cpus->cpus[index]; -+} -+ -+static void loongarch_memory_plug(HotplugHandler *hotplug_dev, -+ DeviceState *dev, Error **errp) -+{ -+ Error *local_err = NULL; -+ LoongarchMachineState *lsms = LoongarchMACHINE(hotplug_dev); -+ HotplugHandlerClass *hhc; -+ uint64_t size; -+ -+ size = memory_device_get_region_size(MEMORY_DEVICE(dev), &error_abort); -+ if (size % LOONGARCH_HOTPLUG_MEM_ALIGN) { -+ error_setg(&local_err, "Hotplugged memory size must be a multiple of " -+ "%lld MB", LOONGARCH_HOTPLUG_MEM_ALIGN / MiB); -+ goto out; -+ } -+ -+ pc_dimm_plug(PC_DIMM(dev), MACHINE(lsms)); -+ -+ hhc = HOTPLUG_HANDLER_GET_CLASS(lsms->acpi_dev); -+ hhc->plug(HOTPLUG_HANDLER(lsms->acpi_dev), dev, &error_abort); -+out: -+ error_propagate(errp, local_err); -+} -+ -+static void loongarch_memory_unplug_request(HotplugHandler *hotplug_dev, -+ DeviceState *dev, Error **errp) -+{ -+ Error *local_err = NULL; -+ HotplugHandlerClass *hhc; -+ LoongarchMachineState *lsms = LoongarchMACHINE(hotplug_dev); -+ -+ if (!lsms->acpi_dev || !loongarch_is_acpi_enabled(lsms)) { -+ error_setg(&local_err, -+ "memory hotplug is not enabled: missing acpi device or acpi disabled"); -+ goto out; -+ } -+ hhc = HOTPLUG_HANDLER_GET_CLASS(lsms->acpi_dev); -+ hhc->unplug_request(HOTPLUG_HANDLER(lsms->acpi_dev), dev, &local_err); -+ -+out: -+ error_propagate(errp, local_err); -+} -+ -+static void loongarch_cpu_unplug(HotplugHandler *hotplug_dev, -+ DeviceState *dev, Error **errp) -+{ -+ CPUArchId *found_cpu; -+ HotplugHandlerClass *hhc; -+ Error *local_err = NULL; -+ LOONGARCHCPU *cpu = LOONGARCH_CPU(dev); -+ MachineState *machine = MACHINE(OBJECT(hotplug_dev)); -+ LoongarchMachineState *lsms = LoongarchMACHINE(machine); -+ -+ hhc = HOTPLUG_HANDLER_GET_CLASS(lsms->acpi_dev); -+ hhc->unplug(HOTPLUG_HANDLER(lsms->acpi_dev), dev, &local_err); -+ -+ if (local_err) { -+ goto out; -+ } -+ -+ loongarch_cpu_destroy(machine, cpu); -+ -+ found_cpu = loongarch_find_cpu_slot(MACHINE(lsms), cpu->id, NULL); -+ found_cpu->cpu = NULL; -+ object_unparent(OBJECT(dev)); -+ lsms->hotpluged_cpu_num -= 1; -+out: -+ error_propagate(errp, local_err); -+} -+ -+static void loongarch_memory_unplug(HotplugHandler *hotplug_dev, -+ DeviceState *dev, Error **errp) -+{ -+ Error *local_err = NULL; -+ HotplugHandlerClass *hhc; -+ LoongarchMachineState *lsms = LoongarchMACHINE(hotplug_dev); -+ -+ hhc = HOTPLUG_HANDLER_GET_CLASS(lsms->acpi_dev); -+ hhc->unplug(HOTPLUG_HANDLER(lsms->acpi_dev), dev, &local_err); -+ -+ if (local_err) { -+ goto out; -+ } -+ -+ pc_dimm_unplug(PC_DIMM(dev), MACHINE(hotplug_dev)); -+ object_unparent(OBJECT(dev)); -+ -+out: -+ error_propagate(errp, local_err); -+} -+ -+static void loongarch_cpu_pre_plug(HotplugHandler *hotplug_dev, -+ DeviceState *dev, Error **errp) -+{ -+ MachineState *ms = MACHINE(OBJECT(hotplug_dev)); -+ MachineClass *mc = MACHINE_GET_CLASS(hotplug_dev); -+ LoongarchMachineState *lsms = LoongarchMACHINE(ms); -+ LOONGARCHCPU *cpu = LOONGARCH_CPU(dev); -+ CPUArchId *cpu_slot; -+ Error *local_err = NULL; -+ int index; -+ int free_index = lsms->hotpluged_cpu_num + ms->smp.cpus; -+ int max_cpus = ms->smp.max_cpus; -+ -+ if (dev->hotplugged && !mc->has_hotpluggable_cpus) { -+ error_setg(&local_err, "CPU hotplug not supported for this machine"); -+ goto out; -+ } -+ -+ if (!object_dynamic_cast(OBJECT(cpu), ms->cpu_type)) { -+ error_setg(errp, "Invalid CPU type, expected cpu type: '%s'", -+ ms->cpu_type); -+ return; -+ } -+ -+ /* if ID is not set, set it based on core properties */ -+ if (cpu->id == UNASSIGNED_CPU_ID) { -+ if ((cpu->core_id) > (max_cpus - 1)) { -+ error_setg(errp, "Invalid CPU core-id: %u must be in range 0:%u", -+ cpu->core_id, max_cpus - 1); -+ return; -+ } -+ -+ if (free_index > (max_cpus - 1)) { -+ error_setg(errp, "The maximum number of CPUs cannot exceed %u.", -+ max_cpus); -+ return; -+ } -+ -+ if (cpu->core_id != free_index) { -+ error_setg(errp, "Invalid CPU core-id: %u must be :%u", -+ cpu->core_id, free_index); -+ return; -+ } -+ -+ cpu->id = cpu->core_id; -+ } -+ -+ cpu_slot = loongarch_find_cpu_slot(MACHINE(hotplug_dev), cpu->id, &index); -+ if (!cpu_slot) { -+ error_setg(&local_err, "core id %d out of range", cpu->id); -+ goto out; -+ } -+ -+ if (cpu_slot->cpu) { -+ error_setg(&local_err, "core %d already populated", cpu->id); -+ goto out; -+ } -+ -+ numa_cpu_pre_plug(cpu_slot, dev, &local_err); -+ -+ return ; -+out: -+ error_propagate(errp, local_err); -+} -+ -+static void loongarch_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, -+ Error **errp) -+{ -+ MachineState *machine = MACHINE(OBJECT(hotplug_dev)); -+ LoongarchMachineState *lsms = LoongarchMACHINE(machine); -+ PCDIMMDevice *dimm = PC_DIMM(dev); -+ Error *local_err = NULL; -+ uint64_t size; -+ -+ if (!lsms->acpi_dev || !loongarch_is_acpi_enabled(lsms)) { -+ error_setg(errp, -+ "memory hotplug is not enabled: missing acpi device or acpi disabled"); -+ return; -+ } -+ -+ size = memory_device_get_region_size(MEMORY_DEVICE(dimm), &local_err); -+ if (local_err) { -+ error_propagate(errp, local_err); -+ return; -+ } -+ -+ if (size % LOONGARCH_HOTPLUG_MEM_ALIGN) { -+ error_setg(errp, "Hotplugged memory size must be a multiple of " -+ "%lld MB", LOONGARCH_HOTPLUG_MEM_ALIGN / MiB); -+ return; -+ } -+ -+ pc_dimm_pre_plug(dimm, MACHINE(hotplug_dev), NULL, errp); -+} -+ -+static void loongarch_cpu_plug(HotplugHandler *hotplug_dev, -+ DeviceState *dev, Error **errp) -+{ -+ CPUArchId *found_cpu; -+ HotplugHandlerClass *hhc; -+ Error *local_err = NULL; -+ MachineState *machine = MACHINE(OBJECT(hotplug_dev)); -+ LoongarchMachineState *lsms = LoongarchMACHINE(machine); -+ LOONGARCHCPU *cpu = LOONGARCH_CPU(dev); -+ -+ if (lsms->acpi_dev) { -+ loongarch_cpu_create(machine, cpu, errp); -+ hhc = HOTPLUG_HANDLER_GET_CLASS(lsms->acpi_dev); -+ hhc->plug(HOTPLUG_HANDLER(lsms->acpi_dev), dev, &local_err); -+ if (local_err) { -+ goto out; -+ } -+ } -+ -+ found_cpu = loongarch_find_cpu_slot(MACHINE(lsms), cpu->id, NULL); -+ found_cpu->cpu = OBJECT(dev); -+ lsms->hotpluged_cpu_num += 1; -+out: -+ error_propagate(errp, local_err); -+} -+ -+static void loongarch_cpu_unplug_request(HotplugHandler *hotplug_dev, -+ DeviceState *dev, Error **errp) -+{ -+ MachineState *machine = MACHINE(OBJECT(hotplug_dev)); -+ LoongarchMachineState *lsms = LoongarchMACHINE(machine); -+ LOONGARCHCPU *cpu = LOONGARCH_CPU(dev); -+ Error *local_err = NULL; -+ HotplugHandlerClass *hhc; -+ int idx = -1; -+ -+ if (!lsms->acpi_dev) { -+ error_setg(&local_err, "CPU hot unplug not supported without ACPI"); -+ goto out; -+ } -+ -+ loongarch_find_cpu_slot(MACHINE(lsms), cpu->id, &idx); -+ assert(idx != -1); -+ if (idx == 0) { -+ error_setg(&local_err, "Boot CPU is unpluggable"); -+ goto out; -+ } -+ -+ hhc = HOTPLUG_HANDLER_GET_CLASS(lsms->acpi_dev); -+ hhc->unplug_request(HOTPLUG_HANDLER(lsms->acpi_dev), dev, &local_err); -+ -+ if (local_err) { -+ goto out; -+ } -+ -+ out: -+ error_propagate(errp, local_err); -+} -+ -+void longson_machine_device_unplug(HotplugHandler *hotplug_dev, -+ DeviceState *dev, Error **errp) -+{ -+ MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine()); -+ -+ if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { -+ loongarch_memory_unplug(hotplug_dev, dev, errp); -+ } else if (object_dynamic_cast(OBJECT(dev), TYPE_LOONGARCH_CPU)) { -+ if (!mc->has_hotpluggable_cpus) { -+ error_setg(errp, "CPU hot unplug not supported on this machine"); -+ return; -+ } -+ loongarch_cpu_unplug(hotplug_dev, dev, errp); -+ } else { -+ error_setg(errp, "acpi: device unplug for not supported device" -+ " type: %s", object_get_typename(OBJECT(dev))); -+ } -+ -+ return; -+} -+ -+void loongarch_machine_device_unplug_request(HotplugHandler *hotplug_dev, -+ DeviceState *dev, Error **errp) -+{ -+ if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { -+ loongarch_memory_unplug_request(hotplug_dev, dev, errp); -+ } else if (object_dynamic_cast(OBJECT(dev), TYPE_LOONGARCH_CPU)) { -+ loongarch_cpu_unplug_request(hotplug_dev, dev, errp); -+ } -+} -+ -+HotplugHandler *loongarch_get_hotpug_handler(MachineState *machine, -+ DeviceState *dev) -+{ -+ if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) || -+ object_dynamic_cast(OBJECT(dev), TYPE_LOONGARCH_CPU)) { -+ return HOTPLUG_HANDLER(machine); -+ } -+ return NULL; -+} -+ -+void loongarch_machine_device_pre_plug(HotplugHandler *hotplug_dev, -+ DeviceState *dev, Error **errp) -+{ -+ if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { -+ loongarch_memory_pre_plug(hotplug_dev, dev, errp); -+ } else if (object_dynamic_cast(OBJECT(dev), TYPE_LOONGARCH_CPU)) { -+ loongarch_cpu_pre_plug(hotplug_dev, dev, errp); -+ } -+} -+ -+void loongarch_machine_device_plug(HotplugHandler *hotplug_dev, -+ DeviceState *dev, Error **errp) -+{ -+ if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { -+ loongarch_memory_plug(hotplug_dev, dev, errp); -+ } else if (object_dynamic_cast(OBJECT(dev), TYPE_LOONGARCH_CPU)) { -+ loongarch_cpu_plug(hotplug_dev, dev, errp); -+ } -+} -+ -diff --git a/hw/loongarch/larch_int.c b/hw/loongarch/larch_int.c -new file mode 100644 -index 0000000000..ca073a19cf ---- /dev/null -+++ b/hw/loongarch/larch_int.c -@@ -0,0 +1,91 @@ -+/* -+ * QEMU LOONGARCH interrupt support -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a copy -+ * of this software and associated documentation files (the "Software"), to deal -+ * in the Software without restriction, including without limitation the rights -+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -+ * copies of the Software, and to permit persons to whom the Software is -+ * furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -+ * THE SOFTWARE. -+ */ -+ -+#include "qemu/osdep.h" -+#include "qemu/main-loop.h" -+#include "hw/hw.h" -+#include "hw/irq.h" -+#include "hw/loongarch/cpudevs.h" -+#include "cpu.h" -+#include "sysemu/kvm.h" -+#include "kvm_larch.h" -+#ifdef CONFIG_KVM -+#include -+#endif -+ -+static void cpu_irq_request(void *opaque, int irq, int level) -+{ -+ LOONGARCHCPU *cpu = opaque; -+ CPULOONGARCHState *env = &cpu->env; -+ CPUState *cs = CPU(cpu); -+ bool locked = false; -+ -+ if (irq < 0 || irq > 13) { -+ return; -+ } -+ -+ /* Make sure locking works even if BQL is already held by the caller */ -+ if (!qemu_mutex_iothread_locked()) { -+ locked = true; -+ qemu_mutex_lock_iothread(); -+ } -+ -+ if (level) { -+ env->CSR_ESTAT |= 1 << irq; -+ } else { -+ env->CSR_ESTAT &= ~(1 << irq); -+ } -+ -+ if (kvm_enabled()) { -+ if (irq == 2) { -+ kvm_loongarch_set_interrupt(cpu, irq, level); -+ } else if (irq == 3) { -+ kvm_loongarch_set_interrupt(cpu, irq, level); -+ } else if (irq == 12) { -+ kvm_loongarch_set_ipi_interrupt(cpu, irq, level); -+ } -+ } -+ -+ if (env->CSR_ESTAT & CSR_ESTAT_IPMASK) { -+ cpu_interrupt(cs, CPU_INTERRUPT_HARD); -+ } else { -+ cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD); -+ } -+ -+ if (locked) { -+ qemu_mutex_unlock_iothread(); -+ } -+} -+ -+void cpu_init_irq(LOONGARCHCPU *cpu) -+{ -+ CPULOONGARCHState *env = &cpu->env; -+ qemu_irq *qi; -+ int i; -+ -+ qi = qemu_allocate_irqs(cpu_irq_request, loongarch_env_get_cpu(env), N_IRQS); -+ for (i = 0; i < N_IRQS; i++) { -+ env->irq[i] = qi[i]; -+ } -+} -+ -+ -diff --git a/hw/loongarch/ls7a_nb.c b/hw/loongarch/ls7a_nb.c -new file mode 100644 -index 0000000000..5a500fbd5a ---- /dev/null -+++ b/hw/loongarch/ls7a_nb.c -@@ -0,0 +1,352 @@ -+/* -+ * Loongarch 7A1000 north bridge support -+ * -+ * Copyright (c) 2019 Loongarch Technology -+ * Authors: -+ * Zhu Chen -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a copy -+ * of this software and associated documentation files (the "Software"), to deal -+ * in the Software without restriction, including without limitation the rights -+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -+ * copies of the Software, and to permit persons to whom the Software is -+ * furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -+ * THE SOFTWARE. -+ */ -+ -+#include "qemu/osdep.h" -+ -+#include "hw/hw.h" -+#include "hw/irq.h" -+#include "hw/sysbus.h" -+#include "hw/pci/pci.h" -+#include "hw/i386/pc.h" -+#include "hw/pci/pci_host.h" -+#include "hw/pci/pcie_host.h" -+#include "sysemu/sysemu.h" -+#include "exec/address-spaces.h" -+#include "qapi/error.h" -+#include "hw/loongarch/cpudevs.h" -+#include "hw/acpi/ls7a.h" -+#include "hw/i386/pc.h" -+#include "hw/isa/isa.h" -+#include "hw/boards.h" -+#include "qemu/log.h" -+#include "hw/loongarch/bios.h" -+#include "hw/loader.h" -+#include "elf.h" -+#include "exec/address-spaces.h" -+#include "exec/memory.h" -+#include "hw/pci/pci_bridge.h" -+#include "hw/pci/pci_bus.h" -+#include "linux/kvm.h" -+#include "sysemu/kvm.h" -+#include "sysemu/runstate.h" -+#include "sysemu/reset.h" -+#include "migration/vmstate.h" -+#include "hw/loongarch/larch.h" -+#include "hw/loongarch/ls7a.h" -+ -+#undef DEBUG_LS7A -+ -+#ifdef DEBUG_LS7A -+#define DPRINTF(fmt, ...) fprintf(stderr, "%s: " fmt, __func__, ##__VA_ARGS__) -+#else -+#define DPRINTF(fmt, ...) -+#endif -+ -+static void ls7a_reset(void *opaque) -+{ -+ uint64_t wmask; -+ wmask = ~(-1); -+ -+ PCIDevice *dev = opaque; -+ pci_set_word(dev->config + PCI_VENDOR_ID, 0x0014); -+ pci_set_word(dev->wmask + PCI_VENDOR_ID, wmask & 0xffff); -+ pci_set_word(dev->cmask + PCI_VENDOR_ID, 0xffff); -+ pci_set_word(dev->config + PCI_DEVICE_ID, 0x7a00); -+ pci_set_word(dev->wmask + PCI_DEVICE_ID, wmask & 0xffff); -+ pci_set_word(dev->cmask + PCI_DEVICE_ID, 0xffff); -+ pci_set_word(dev->config + 0x4, 0x0000); -+ pci_set_word(dev->config + PCI_STATUS, 0x0010); -+ pci_set_word(dev->wmask + PCI_STATUS, wmask & 0xffff); -+ pci_set_word(dev->cmask + PCI_STATUS, 0xffff); -+ pci_set_byte(dev->config + PCI_REVISION_ID, 0x0); -+ pci_set_byte(dev->wmask + PCI_REVISION_ID, wmask & 0xff); -+ pci_set_byte(dev->cmask + PCI_REVISION_ID, 0xff); -+ pci_set_byte(dev->config + 0x9, 0x00); -+ pci_set_byte(dev->wmask + 0x9, wmask & 0xff); -+ pci_set_byte(dev->cmask + 0x9, 0xff); -+ pci_set_byte(dev->config + 0xa, 0x00); -+ pci_set_byte(dev->wmask + 0xa, wmask & 0xff); -+ pci_set_byte(dev->cmask + 0xa, 0xff); -+ pci_set_byte(dev->config + 0xb, 0x06); -+ pci_set_byte(dev->wmask + 0xb, wmask & 0xff); -+ pci_set_byte(dev->cmask + 0xb, 0xff); -+ pci_set_byte(dev->config + 0xc, 0x00); -+ pci_set_byte(dev->wmask + 0xc, wmask & 0xff); -+ pci_set_byte(dev->cmask + 0xc, 0xff); -+ pci_set_byte(dev->config + 0xe, 0x80); -+ pci_set_byte(dev->wmask + 0xe, wmask & 0xff); -+ pci_set_byte(dev->cmask + 0xe, 0xff); -+} -+ -+static const VMStateDescription vmstate_ls7a_pcie = { -+ .name = "LS7A_PCIE", -+ .version_id = 1, -+ .minimum_version_id = 1, -+ .fields = (VMStateField[]) { -+ VMSTATE_PCI_DEVICE(dev, LS7APCIState), -+ VMSTATE_STRUCT(pm, LS7APCIState, 0, vmstate_ls7a_pm, LS7APCIPMRegs), -+ VMSTATE_UINT32_ARRAY(regs, LS7APCIState, LS7A_REGS), -+ VMSTATE_END_OF_LIST() -+ } -+}; -+ -+static PCIINTxRoute ls7a_route_intx_pin_to_irq(void *opaque, int pin) -+{ -+ PCIINTxRoute route; -+ -+ route.irq = pin; -+ route.mode = PCI_INTX_ENABLED; -+ return route; -+} -+ -+static int pci_ls7a_map_irq(PCIDevice *d, int irq_num) -+{ -+ int irq; -+ -+ irq = 16 + ((PCI_SLOT(d->devfn) * 4 + irq_num) & 0xf); -+ return irq; -+} -+ -+static void pci_ls7a_set_irq(void *opaque, int irq_num, int level) -+{ -+ qemu_irq *pic = opaque; -+ DPRINTF("------ %s irq %d %d\n", __func__, irq_num, level); -+ qemu_set_irq(pic[irq_num], level); -+} -+ -+/* -+static int ls7a_pciehost_initfn(SysBusDevice *dev) -+{ -+ return 0; -+}*/ -+ -+static void ls7a_pcie_realize(PCIDevice *dev, Error **errp) -+{ -+ LS7APCIState *s = PCIE_LS7A(dev); -+ /* Ls7a North Bridge, built on FPGA, VENDOR_ID/DEVICE_ID are "undefined" */ -+ pci_config_set_prog_interface(dev->config, 0x00); -+ -+ /* set the default value of north bridge pci config */ -+ qemu_register_reset(ls7a_reset, s); -+} -+ -+static void pci_ls7a_config_write(void *opaque, hwaddr addr, -+ uint64_t val, unsigned size) -+{ -+ hwaddr tmp_addr; -+ tmp_addr = addr & 0xffffff; -+ -+ pci_data_write(opaque, tmp_addr, val, size); -+} -+ -+static uint64_t pci_ls7a_config_read(void *opaque, -+ hwaddr addr, unsigned size) -+{ -+ uint64_t val; -+ hwaddr tmp_addr; -+ -+ tmp_addr = addr & 0xffffff; -+ val = pci_data_read(opaque, tmp_addr, size); -+ -+ if (addr & 0x3c) { -+ DPRINTF(TARGET_FMT_plx" val %lx\n", addr, val); -+ } -+ return val; -+} -+ -+static const MemoryRegionOps pci_ls7a_config_ops = { -+ .read = pci_ls7a_config_read, -+ .write = pci_ls7a_config_write, -+ /* Set to access 64bits data, because default to 32bits*/ -+ .valid = { -+ .min_access_size = 1, -+ .max_access_size = 4, -+ }, -+ /* Set to access 64bits data, because default to 32bits*/ -+ .impl = { -+ .min_access_size = 1, -+ .max_access_size = 4, -+ }, -+ .endianness = DEVICE_NATIVE_ENDIAN, -+ -+}; -+ -+static AddressSpace *ls7a_pci_dma_iommu(PCIBus *bus, void *opaque, int devfn) -+{ -+ return &address_space_memory; -+} -+ -+static PCIBus *pci_ls7a_init(MachineState *machine, DeviceState *dev, -+ qemu_irq *pic) -+{ -+ LoongarchMachineState *lsms = LoongarchMACHINE(machine); -+ LoongarchMachineClass *lsmc = LoongarchMACHINE_GET_CLASS(lsms); -+ PCIExpressHost *e; -+ SysBusDevice *sysbus; -+ MemoryRegion *iomem = g_new(MemoryRegion, 1); -+ PCIHostState *phb; -+ -+ e = PCIE_HOST_BRIDGE(dev); -+ sysbus = SYS_BUS_DEVICE(e); -+ phb = PCI_HOST_BRIDGE(e); -+ phb->bus = pci_register_root_bus(dev, "pcie.0", pci_ls7a_set_irq, -+ pci_ls7a_map_irq, pic, -+ get_system_memory(), get_system_io(), -+ (1 << 3), 128, TYPE_PCIE_BUS); -+ pcie_host_mmcfg_update(e, true, lsmc->pciecfg_base, LS_PCIECFG_SIZE); -+ DPRINTF("------ %d\n", __LINE__); -+ -+ pci_bus_set_route_irq_fn(phb->bus, ls7a_route_intx_pin_to_irq); -+ memory_region_init_io(iomem, NULL, &pci_ls7a_config_ops, phb->bus, -+ "ls7a_pci_conf", HT1LO_PCICFG_SIZE); -+ sysbus_init_mmio(sysbus, iomem); -+ sysbus_mmio_map(sysbus, 0, lsmc->ht1lo_pcicfg_base); -+ -+ return phb->bus; -+} -+ -+PCIBus *ls7a_init(MachineState *machine, qemu_irq *pic, DeviceState **ls7a_dev) -+{ -+ DeviceState *dev; -+ PCIHostState *phb; -+ LS7APCIState *pbs; -+ PCIDevice *pcid; -+ PCIBus *pci_bus; -+ PCIExpressHost *e; -+ -+ /*1. init the HT PCI CFG*/ -+ DPRINTF("------ %d\n", __LINE__); -+ dev = qdev_new(TYPE_LS7A_PCIE_HOST_BRIDGE); -+ e = PCIE_HOST_BRIDGE(dev); -+ phb = PCI_HOST_BRIDGE(e); -+ -+ DPRINTF("------ %d\n", __LINE__); -+ pci_bus = pci_ls7a_init(machine, dev, pic); -+ sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); -+ phb->bus = pci_bus; -+ /* set the pcihost pointer after rs780_pcihost_initfn is called */ -+ DPRINTF("------ %d\n", __LINE__); -+ pcid = pci_new(PCI_DEVFN(0, 0), TYPE_PCIE_LS7A); -+ pbs = PCIE_LS7A(pcid); -+ pbs->pciehost = LS7A_PCIE_HOST_BRIDGE(dev); -+ pbs->pciehost->pci_dev = pbs; -+ -+ if (ls7a_dev) { -+ *ls7a_dev = DEVICE(pcid); -+ } -+ -+ pci_realize_and_unref(pcid, phb->bus, &error_fatal); -+ -+ /* IOMMU */ -+ pci_setup_iommu(phb->bus, ls7a_pci_dma_iommu, NULL); -+ -+ ls7a_pm_init(&pbs->pm, pic); -+ DPRINTF("------ %d\n", __LINE__); -+ /*3. init the north bridge VGA,not do now*/ -+ return pci_bus; -+} -+ -+LS7APCIState *get_ls7a_type(Object *obj) -+{ -+ LS7APCIState *pbs; -+ -+ pbs = PCIE_LS7A(obj); -+ return pbs; -+} -+ -+static void ls7a_pcie_class_init(ObjectClass *klass, void *data) -+{ -+ DeviceClass *dc = DEVICE_CLASS(klass); -+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); -+ HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass); -+ AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_CLASS(klass); -+ -+ k->realize = ls7a_pcie_realize; -+ k->vendor_id = 0x0014; -+ k->device_id = 0x7a00; -+ k->revision = 0x00; -+ k->class_id = PCI_CLASS_BRIDGE_HOST; -+ dc->desc = "LS7A1000 PCIE Host bridge"; -+ dc->vmsd = &vmstate_ls7a_pcie; -+ /* -+ * PCI-facing part of the host bridge, not usable without the -+ * host-facing part, which can't be device_add'ed, yet. -+ */ -+ dc->user_creatable = false; -+ hc->plug = ls7a_pm_device_plug_cb; -+ hc->unplug_request = ls7a_pm_device_unplug_request_cb; -+ hc->unplug = ls7a_pm_device_unplug_cb; -+ adevc->ospm_status = ls7a_pm_ospm_status; -+ adevc->send_event = ls7a_send_gpe; -+ adevc->madt_cpu = ls7a_madt_cpu_entry; -+} -+ -+static void ls7a_pci_add_properties(LS7APCIState *ls7a) -+{ -+ ls7a_pm_add_properties(OBJECT(ls7a), &ls7a->pm, NULL); -+} -+ -+static void ls7a_pci_initfn(Object *obj) -+{ -+ LS7APCIState *ls7a = get_ls7a_type(obj); -+ -+ ls7a_pci_add_properties(ls7a); -+} -+ -+static const TypeInfo ls7a_pcie_device_info = { -+ .name = TYPE_PCIE_LS7A, -+ .parent = TYPE_PCI_DEVICE, -+ .instance_size = sizeof(LS7APCIState), -+ .class_init = ls7a_pcie_class_init, -+ .instance_init = ls7a_pci_initfn, -+ .interfaces = (InterfaceInfo[]) { -+ { TYPE_HOTPLUG_HANDLER }, -+ { TYPE_ACPI_DEVICE_IF }, -+ { INTERFACE_CONVENTIONAL_PCI_DEVICE }, -+ { }, -+ }, -+}; -+ -+static void ls7a_pciehost_class_init(ObjectClass *klass, void *data) -+{ -+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); -+ k->parent_class.fw_name = "pci"; -+} -+ -+static const TypeInfo ls7a_pciehost_info = { -+ .name = TYPE_LS7A_PCIE_HOST_BRIDGE, -+ .parent = TYPE_PCIE_HOST_BRIDGE, -+ .instance_size = sizeof(LS7APCIEHost), -+ .class_init = ls7a_pciehost_class_init, -+}; -+ -+static void ls7a_register_types(void) -+{ -+ type_register_static(&ls7a_pciehost_info); -+ type_register_static(&ls7a_pcie_device_info); -+} -+ -+type_init(ls7a_register_types) -diff --git a/hw/loongarch/meson.build b/hw/loongarch/meson.build -new file mode 100644 -index 0000000000..81ee99a028 ---- /dev/null -+++ b/hw/loongarch/meson.build -@@ -0,0 +1,15 @@ -+loongarch_ss = ss.source_set() -+loongarch_ss.add(files('larch_3a.c'), fdt) -+loongarch_ss.add(files( -+ 'larch_int.c', -+ 'larch_hotplug.c', -+ 'ls7a_nb.c', -+ 'ioapic.c', -+ 'acpi-build.c', -+ 'ipi.c', -+ 'apic.c', -+ 'iocsr.c', -+)) -+ -+hw_arch += {'loongarch64': loongarch_ss} -+ -diff --git a/include/hw/loongarch/bios.h b/include/hw/loongarch/bios.h -new file mode 100644 -index 0000000000..3677303bfa ---- /dev/null -+++ b/include/hw/loongarch/bios.h -@@ -0,0 +1,5 @@ -+#include "qemu/units.h" -+#include "cpu.h" -+ -+#define BIOS_SIZE (4 * MiB) -+#define BIOS_FILENAME "loongarch_bios.bin" -diff --git a/include/hw/loongarch/cpudevs.h b/include/hw/loongarch/cpudevs.h -new file mode 100644 -index 0000000000..c05ae7a7fc ---- /dev/null -+++ b/include/hw/loongarch/cpudevs.h -@@ -0,0 +1,53 @@ -+#ifndef HW_LOONGARCH_CPUDEVS_H -+#define HW_LOONGARCH_CPUDEVS_H -+ -+#include "target/loongarch64/cpu-qom.h" -+ -+/* Definitions for LOONGARCH CPU internal devices. */ -+#define MAX_GIPI_CORE_NUM 256 -+#define MAX_GIPI_MBX_NUM 4 -+ -+#define LS3A_INTC_IP 8 -+#define MAX_CORES 256 -+#define EXTIOI_IRQS (256) -+#define EXTIOI_IRQS_BITMAP_SIZE (256 / 8) -+/* map to ipnum per 32 irqs */ -+#define EXTIOI_IRQS_IPMAP_SIZE (256 / 32) -+ -+typedef struct gipi_core { -+ uint32_t status; -+ uint32_t en; -+ uint32_t set; -+ uint32_t clear; -+ uint64_t buf[MAX_GIPI_MBX_NUM]; -+ qemu_irq irq; -+} gipi_core; -+ -+typedef struct gipiState { -+ gipi_core core[MAX_GIPI_CORE_NUM]; -+} gipiState; -+ -+typedef struct apicState { -+ /* hardware state */ -+ uint8_t ext_en[EXTIOI_IRQS_BITMAP_SIZE]; -+ uint8_t ext_bounce[EXTIOI_IRQS_BITMAP_SIZE]; -+ uint8_t ext_isr[EXTIOI_IRQS_BITMAP_SIZE]; -+ uint8_t ext_coreisr[MAX_CORES][EXTIOI_IRQS_BITMAP_SIZE]; -+ uint8_t ext_ipmap[EXTIOI_IRQS_IPMAP_SIZE]; -+ uint8_t ext_coremap[EXTIOI_IRQS]; -+ uint16_t ext_nodetype[16]; -+ uint64_t ext_control; -+ -+ /* software state */ -+ uint8_t ext_sw_ipmap[EXTIOI_IRQS]; -+ uint8_t ext_sw_coremap[EXTIOI_IRQS]; -+ uint8_t ext_ipisr[MAX_CORES * LS3A_INTC_IP][EXTIOI_IRQS_BITMAP_SIZE]; -+ -+ qemu_irq parent_irq[MAX_CORES][LS3A_INTC_IP]; -+ qemu_irq *irq; -+} apicState; -+ -+void cpu_init_irq(LOONGARCHCPU *cpu); -+void cpu_loongarch_clock_init(LOONGARCHCPU *cpu); -+ -+#endif -diff --git a/include/hw/loongarch/larch.h b/include/hw/loongarch/larch.h -new file mode 100644 -index 0000000000..0886ed52af ---- /dev/null -+++ b/include/hw/loongarch/larch.h -@@ -0,0 +1,163 @@ -+/* -+ * Hotplug emulation on Loongarch system. -+ * -+ * Copyright (c) 2018 Loongarch Inc. -+ * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2 of the License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library; if not, see . -+ */ -+ -+#ifndef HW_LOONGARCH_H -+#define HW_LOONGARCH_H -+ -+#include "target/loongarch64/cpu.h" -+#include "qemu-common.h" -+#include "exec/memory.h" -+#include "hw/mem/pc-dimm.h" -+#include "hw/hotplug.h" -+#include "hw/boards.h" -+#include "hw/acpi/acpi.h" -+#include "qemu/notify.h" -+#include "qemu/error-report.h" -+#include "qemu/queue.h" -+#include "hw/acpi/memory_hotplug.h" -+#include "hw/loongarch/cpudevs.h" -+#include "hw/block/flash.h" -+ -+#define LOONGARCH_MAX_VCPUS 256 -+#define LOONGARCH_MAX_PFLASH 2 -+/* 256MB alignment for hotplug memory region */ -+#define LOONGARCH_HOTPLUG_MEM_ALIGN (1ULL << 28) -+#define LOONGARCH_MAX_RAM_SLOTS 10 -+ -+/* Memory types: */ -+#define SYSTEM_RAM 1 -+#define SYSTEM_RAM_RESERVED 2 -+#define ACPI_TABLE 3 -+#define ACPI_NVS 4 -+#define SYSTEM_PMEM 5 -+ -+#define MAX_MEM_MAP 128 -+ -+typedef struct LoongarchMachineClass { -+ /*< private >*/ -+ MachineClass parent_class; -+ -+ /* Methods: */ -+ HotplugHandler *(*get_hotplug_handler)(MachineState *machine, -+ DeviceState *dev); -+ -+ bool has_acpi_build; -+ -+ /* save different cpu address*/ -+ uint64_t isa_io_base; -+ uint64_t ht_control_regs_base; -+ uint64_t hpet_mmio_addr; -+ uint64_t smbus_cfg_base; -+ uint64_t ht1lo_pcicfg_base; -+ uint64_t pciecfg_base; -+ uint64_t ls7a_ioapic_reg_base; -+ uint32_t node_shift; -+ char cpu_name[40]; -+ char bridge_name[16]; -+ -+} LoongarchMachineClass; -+ -+typedef struct ResetData { -+ LOONGARCHCPU *cpu; -+ uint64_t vector; -+} ResetData; -+ -+typedef struct LoongarchMachineState { -+ /*< private >*/ -+ MachineState parent_obj; -+ -+ /* */ -+ ram_addr_t hotplug_memory_size; -+ -+ /* State for other subsystems/APIs: */ -+ Notifier machine_done; -+ /* Pointers to devices and objects: */ -+ HotplugHandler *acpi_dev; -+ int ram_slots; -+ ResetData *reset_info[LOONGARCH_MAX_VCPUS]; -+ DeviceState *rtc; -+ gipiState *gipi; -+ apicState *apic; -+ -+ FWCfgState *fw_cfg; -+ bool acpi_build_enabled; -+ bool apic_xrupt_override; -+ CPUArchIdList *possible_cpus; -+ PFlashCFI01 *flash[LOONGARCH_MAX_PFLASH]; -+ void *fdt; -+ int fdt_size; -+ unsigned int hotpluged_cpu_num; -+ OnOffAuto acpi; -+ char *oem_id; -+ char *oem_table_id; -+} LoongarchMachineState; -+ -+#define LOONGARCH_MACHINE_ACPI_DEVICE_PROP "loongarch-acpi-device" -+#define TYPE_LOONGARCH_MACHINE "loongarch-machine" -+ -+#define LoongarchMACHINE(obj) \ -+ OBJECT_CHECK(LoongarchMachineState, (obj), TYPE_LOONGARCH_MACHINE) -+#define LoongarchMACHINE_GET_CLASS(obj) \ -+ OBJECT_GET_CLASS(LoongarchMachineClass, (obj), TYPE_LOONGARCH_MACHINE) -+#define LoongarchMACHINE_CLASS(klass) \ -+ OBJECT_CLASS_CHECK(LoongarchMachineClass, (klass), TYPE_LOONGARCH_MACHINE) -+ -+#define DEFINE_LOONGARCH_MACHINE(suffix, namestr, initfn, optsfn) \ -+ static void loongarch_machine_##suffix##_class_init(ObjectClass *oc, void *data) \ -+ { \ -+ MachineClass *mc = MACHINE_CLASS(oc); \ -+ optsfn(mc); \ -+ mc->init = initfn; \ -+ } \ -+ static const TypeInfo loongarch_machine_type_##suffix = { \ -+ .name = namestr TYPE_MACHINE_SUFFIX, \ -+ .parent = TYPE_LOONGARCH_MACHINE, \ -+ .class_init = loongarch_machine_##suffix##_class_init, \ -+ }; \ -+ static void loongarch_machine_init_##suffix(void) \ -+ { \ -+ type_register(&loongarch_machine_type_##suffix); \ -+ } \ -+ type_init(loongarch_machine_init_##suffix) -+ -+void loongarch_machine_device_unplug_request(HotplugHandler *hotplug_dev, -+ DeviceState *dev, Error **errp); -+void longson_machine_device_unplug(HotplugHandler *hotplug_dev, -+ DeviceState *dev, Error **errp); -+HotplugHandler *loongarch_get_hotpug_handler(MachineState *machine, -+ DeviceState *dev); -+void loongarch_machine_device_pre_plug(HotplugHandler *hotplug_dev, -+ DeviceState *dev, Error **errp); -+void loongarch_machine_device_plug(HotplugHandler *hotplug_dev, -+ DeviceState *dev, Error **errp); -+ -+LOONGARCHCPU *loongarch_cpu_create(MachineState *machine, LOONGARCHCPU *cpu, -+ Error **errp); -+void loongarch_cpu_destroy(MachineState *machine, LOONGARCHCPU *cpu); -+int cpu_init_ipi(LoongarchMachineState *ms, qemu_irq parent, int cpu); -+int cpu_init_apic(LoongarchMachineState *ms, CPULOONGARCHState *env, int cpu); -+int la_memmap_add_entry(uint64_t address, uint64_t length, uint32_t type); -+bool loongarch_is_acpi_enabled(LoongarchMachineState *vms); -+ -+/* acpi-build.c */ -+void ls7a_madt_cpu_entry(AcpiDeviceIf *adev, int uid, -+ const CPUArchIdList *apic_ids, GArray *entry, bool force_enabled); -+void slave_cpu_reset(void *opaque); -+extern uint64_t host_cpufreq; -+#endif -diff --git a/include/hw/loongarch/ls7a.h b/include/hw/loongarch/ls7a.h -new file mode 100644 -index 0000000000..686af763a0 ---- /dev/null -+++ b/include/hw/loongarch/ls7a.h -@@ -0,0 +1,152 @@ -+#ifndef HW_LS7A_H -+#define HW_LS7A_H -+ -+#include "hw/hw.h" -+#include "hw/isa/isa.h" -+#include "hw/sysbus.h" -+#include "hw/isa/apm.h" -+#include "hw/pci/pci.h" -+#include "hw/pci/pcie_host.h" -+#include "hw/pci/pci_bridge.h" -+#include "hw/acpi/acpi.h" -+#include "hw/acpi/ls7a.h" -+#include "hw/pci/pci_bus.h" -+ -+/* LS7A PCH Registers (Misc, Confreg) */ -+#define LS7A_PCH_REG_BASE 0x10000000UL -+#define LS3A5K_LS7A_IOAPIC_REG_BASE (LS7A_PCH_REG_BASE) -+#define LS7A_MISC_REG_BASE (LS7A_PCH_REG_BASE + 0x00080000) -+#define LS7A_ACPI_REG_BASE (LS7A_MISC_REG_BASE + 0x00050000) -+ -+#define LOONGARCH_PCH_IRQ_BASE 64 -+#define LS7A_UART_IRQ (LOONGARCH_PCH_IRQ_BASE + 2) -+#define LS7A_RTC_IRQ (LOONGARCH_PCH_IRQ_BASE + 3) -+#define LS7A_SCI_IRQ (LOONGARCH_PCH_IRQ_BASE + 4) -+#define LS7A_ACPI_IO_BASE 0x800 -+#define LS7A_ACPI_IO_SIZE 0x100 -+#define LS7A_PM_EVT_BLK (0x0C) /* 4 bytes */ -+#define LS7A_PM_CNT_BLK (0x14) /* 2 bytes */ -+#define LS7A_GPE0_STS_REG (0x28) /* 4 bytes */ -+#define LS7A_GPE0_ENA_REG (0x2C) /* 4 bytes */ -+#define LS7A_GPE0_RESET_REG (0x30) /* 4 bytes */ -+#define LS7A_PM_TMR_BLK (0x18) /* 4 bytes */ -+#define LS7A_GPE0_LEN (8) -+#define LS7A_RTC_REG_BASE (LS7A_MISC_REG_BASE + 0x00050100) -+#define LS7A_RTC_LEN (0x100) -+ -+#define ACPI_IO_BASE (LS7A_ACPI_REG_BASE) -+#define ACPI_GPE0_LEN (LS7A_GPE0_LEN) -+#define ACPI_IO_SIZE (LS7A_ACPI_IO_SIZE) -+#define ACPI_SCI_IRQ (LS7A_SCI_IRQ) -+ -+#define LS3A5K_ISA_IO_BASE 0x18000000UL -+#define LS_ISA_MEM_BASE 0x40000000 -+#define LS3A5K_HT1LO_PCICFG_BASE 0x1a000000 -+#define HT1LO_PCICFG_SIZE 0x02000000 -+#define LS_BIOS_BASE 0x1c000000 -+#define LS_BIOS_VAR_BASE 0x1c3a0000 -+#define LS_BIOS_SIZE (4 * 1024 * 1024) -+ -+#define FW_CFG_ADDR 0x1e020000 -+#define LS7A_REG_BASE 0x1FE00000 -+#define LS7A_PCICONFIG_BASE (LS7A_REG_BASE + 0x30) -+#define LS7A_PCICONFIG_SIZE (0x100) -+#define LS7A_INTERNAL_REG_BASE (LS7A_REG_BASE + 0x100) -+#define LS7A_INTERNAL_REG_SIZE (0xE0) -+#define LS7A_REGS (0xE0 >> 2) -+#define LS7A_UART_BASE 0x1fe001e0 -+#define LS7A_UART_LEN 0x8 -+ -+#define LS_FDT_BASE 0x1c400000 -+#define LS_FDT_SIZE 0x100000 -+ -+#define LS_PCIECFG_BASE 0x20000000 -+#define LS_PCIECFG_SIZE 0x08000000 -+#define MSI_ADDR_LOW 0x2FF00000 -+#define MSI_ADDR_HI 0x0 -+ -+#define SMP_GIPI_MAILBOX 0x1f000000ULL -+#define CORE0_STATUS_OFF 0x000 -+#define CORE0_EN_OFF 0x004 -+#define CORE0_SET_OFF 0x008 -+#define CORE0_CLEAR_OFF 0x00c -+#define CORE0_BUF_20 0x020 -+#define CORE0_BUF_28 0x028 -+#define CORE0_BUF_30 0x030 -+#define CORE0_BUF_38 0x038 -+#define CORE0_IPI_SEND 0x040 -+#define CORE0_MAIL_SEND 0x048 -+ -+#define INT_ROUTER_REGS_BASE 0x1fe01400UL -+#define INT_ROUTER_REGS_SIZE 0x100 -+#define INT_ROUTER_REGS_SYS_INT0 0x00 -+#define INT_ROUTER_REGS_SYS_INT1 0x01 -+#define INT_ROUTER_REGS_SYS_INT2 0x02 -+#define INT_ROUTER_REGS_SYS_INT3 0x03 -+#define INT_ROUTER_REGS_PCI_INT0 0x04 -+#define INT_ROUTER_REGS_PCI_INT1 0x05 -+#define INT_ROUTER_REGS_PCI_INT2 0x06 -+#define INT_ROUTER_REGS_PCI_INT3 0x07 -+#define INT_ROUTER_REGS_MATRIX_INT0 0x08 -+#define INT_ROUTER_REGS_MATRIX_INT1 0x09 -+#define INT_ROUTER_REGS_LPC_INT 0x0a -+#define INT_ROUTER_REGS_MC0 0x0b -+#define INT_ROUTER_REGS_MC1 0x0c -+#define INT_ROUTER_REGS_BARRIER 0x0d -+#define INT_ROUTER_REGS_THSENS_INT 0x0e -+#define INT_ROUTER_REGS_PCI_PERR 0x0f -+#define INT_ROUTER_REGS_HT0_INT0 0x10 -+#define INT_ROUTER_REGS_HT0_INT1 0x11 -+#define INT_ROUTER_REGS_HT0_INT2 0x12 -+#define INT_ROUTER_REGS_HT0_INT3 0x13 -+#define INT_ROUTER_REGS_HT0_INT4 0x14 -+#define INT_ROUTER_REGS_HT0_INT5 0x15 -+#define INT_ROUTER_REGS_HT0_INT6 0x16 -+#define INT_ROUTER_REGS_HT0_INT7 0x17 -+#define INT_ROUTER_REGS_HT1_INT0 0x18 -+#define INT_ROUTER_REGS_HT1_INT1 0x19 -+#define INT_ROUTER_REGS_HT1_INT2 0x1a -+#define INT_ROUTER_REGS_HT1_INT3 0x1b -+#define INT_ROUTER_REGS_HT1_INT4 0x1c -+#define INT_ROUTER_REGS_HT1_INT5 0x1d -+#define INT_ROUTER_REGS_HT1_INT6 0x1e -+#define INT_ROUTER_REGS_HT1_INT7 0x1f -+#define INT_ROUTER_REGS_ISR 0x20 -+#define INT_ROUTER_REGS_EN 0x24 -+#define INT_ROUTER_REGS_EN_SET 0x28 -+#define INT_ROUTER_REGS_EN_CLR 0x2c -+#define INT_ROUTER_REGS_EDGE 0x38 -+#define INT_ROUTER_REGS_CORE0_INTISR 0x40 -+#define INT_ROUTER_REGS_CORE1_INTISR 0x48 -+#define INT_ROUTER_REGS_CORE2_INTISR 0x50 -+#define INT_ROUTER_REGS_CORE3_INTISR 0x58 -+ -+typedef struct LS7APCIState LS7APCIState; -+typedef struct LS7APCIEHost { -+ PCIExpressHost parent_obj; -+ LS7APCIState *pci_dev; -+} LS7APCIEHost; -+ -+struct LS7APCIState { -+ PCIDevice dev; -+ -+ LS7APCIEHost *pciehost; -+ uint32_t regs[LS7A_REGS]; -+ -+ /* LS7A registers */ -+ MemoryRegion iomem; -+ LS7APCIPMRegs pm; -+}; -+ -+#define TYPE_LS7A_PCIE_HOST_BRIDGE "ls7a1000-pciehost" -+#define LS7A_PCIE_HOST_BRIDGE(obj) \ -+ OBJECT_CHECK(LS7APCIEHost, (obj), TYPE_LS7A_PCIE_HOST_BRIDGE) -+ -+#define TYPE_PCIE_LS7A "ls7a1000_pcie" -+#define PCIE_LS7A(obj) \ -+ OBJECT_CHECK(LS7APCIState, (obj), TYPE_PCIE_LS7A) -+ -+PCIBus *ls7a_init(MachineState *machine, qemu_irq *irq, DeviceState **ls7a_dev); -+LS7APCIState *get_ls7a_type(Object *obj); -+ -+#endif /* HW_LS7A_H */ --- -2.27.0 - diff --git a/0004-Add-target-loongarch64.patch b/0004-Add-target-loongarch64.patch deleted file mode 100644 index 38e74c2..0000000 --- a/0004-Add-target-loongarch64.patch +++ /dev/null @@ -1,15918 +0,0 @@ -From 441bbe9ec5021bf56a929134a71cd85815ec3956 Mon Sep 17 00:00:00 2001 -From: lixianglai -Date: Fri, 19 Aug 2022 23:44:33 -0400 -Subject: [PATCH 4/8] Add target/loongarch64. - -Change-Id: Idd3ed114968c4a1f1be5fe19dc279028775eb89d -Signed-off-by: lixianglai ---- - target/Kconfig | 1 + - target/loongarch64/Kconfig | 2 + - target/loongarch64/arch_dump.c | 175 ++ - target/loongarch64/cpu-csr.h | 869 ++++++++ - target/loongarch64/cpu-param.h | 30 + - target/loongarch64/cpu-qom.h | 54 + - target/loongarch64/cpu.c | 576 +++++ - target/loongarch64/cpu.h | 326 +++ - target/loongarch64/csr_helper.c | 704 ++++++ - target/loongarch64/fpu.c | 28 + - target/loongarch64/fpu_helper.c | 952 ++++++++ - target/loongarch64/fpu_helper.h | 129 ++ - target/loongarch64/gdbstub.c | 109 + - target/loongarch64/helper.c | 727 +++++++ - target/loongarch64/helper.h | 168 ++ - target/loongarch64/insn.decode | 514 +++++ - target/loongarch64/instmap.h | 216 ++ - target/loongarch64/internal.h | 184 ++ - target/loongarch64/kvm.c | 1622 ++++++++++++++ - target/loongarch64/kvm_larch.h | 41 + - target/loongarch64/larch-defs.h | 27 + - target/loongarch64/machine.c | 416 ++++ - target/loongarch64/meson.build | 35 + - target/loongarch64/op_helper.c | 533 +++++ - target/loongarch64/stabletimer.c | 122 ++ - target/loongarch64/tlb_helper.c | 729 +++++++ - target/loongarch64/trace-events | 3 + - target/loongarch64/trans.inc.c | 3472 ++++++++++++++++++++++++++++++ - target/loongarch64/translate.c | 2892 +++++++++++++++++++++++++ - target/meson.build | 1 + - 30 files changed, 15657 insertions(+) - create mode 100644 target/loongarch64/Kconfig - create mode 100644 target/loongarch64/arch_dump.c - create mode 100644 target/loongarch64/cpu-csr.h - create mode 100644 target/loongarch64/cpu-param.h - create mode 100644 target/loongarch64/cpu-qom.h - create mode 100644 target/loongarch64/cpu.c - create mode 100644 target/loongarch64/cpu.h - create mode 100644 target/loongarch64/csr_helper.c - create mode 100644 target/loongarch64/fpu.c - create mode 100644 target/loongarch64/fpu_helper.c - create mode 100644 target/loongarch64/fpu_helper.h - create mode 100644 target/loongarch64/gdbstub.c - create mode 100644 target/loongarch64/helper.c - create mode 100644 target/loongarch64/helper.h - create mode 100644 target/loongarch64/insn.decode - create mode 100644 target/loongarch64/instmap.h - create mode 100644 target/loongarch64/internal.h - create mode 100644 target/loongarch64/kvm.c - create mode 100644 target/loongarch64/kvm_larch.h - create mode 100644 target/loongarch64/larch-defs.h - create mode 100644 target/loongarch64/machine.c - create mode 100644 target/loongarch64/meson.build - create mode 100644 target/loongarch64/op_helper.c - create mode 100644 target/loongarch64/stabletimer.c - create mode 100644 target/loongarch64/tlb_helper.c - create mode 100644 target/loongarch64/trace-events - create mode 100644 target/loongarch64/trans.inc.c - create mode 100644 target/loongarch64/translate.c - -diff --git a/target/Kconfig b/target/Kconfig -index ae7f24fc66..50b46d0487 100644 ---- a/target/Kconfig -+++ b/target/Kconfig -@@ -4,6 +4,7 @@ source avr/Kconfig - source cris/Kconfig - source hppa/Kconfig - source i386/Kconfig -+source loongarch64/Kconfig - source m68k/Kconfig - source microblaze/Kconfig - source mips/Kconfig -diff --git a/target/loongarch64/Kconfig b/target/loongarch64/Kconfig -new file mode 100644 -index 0000000000..46b26b1a85 ---- /dev/null -+++ b/target/loongarch64/Kconfig -@@ -0,0 +1,2 @@ -+config LOONGARCH64 -+ bool -diff --git a/target/loongarch64/arch_dump.c b/target/loongarch64/arch_dump.c -new file mode 100644 -index 0000000000..9fb43b33d2 ---- /dev/null -+++ b/target/loongarch64/arch_dump.c -@@ -0,0 +1,175 @@ -+/* Support for writing ELF notes for RM architectures -+ * -+ * Copyright (C) 2015 Red Hat Inc. -+ * -+ * Author: Andrew Jones -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, see . -+ */ -+ -+#include "qemu/osdep.h" -+#include "cpu.h" -+#include "elf.h" -+#include "sysemu/dump.h" -+#include "internal.h" -+ -+/* struct user_pt_regs from arch/loongarch/include/uapi/asm/ptrace.h */ -+struct loongarch_user_regs { -+ uint64_t gpr[32]; -+ uint64_t lo; -+ uint64_t hi; -+ uint64_t csr_era; -+ uint64_t csr_badvaddr; -+ uint64_t csr_crmd; -+ uint64_t csr_ecfg; -+ uint64_t pad[7]; -+} QEMU_PACKED; -+ -+QEMU_BUILD_BUG_ON(sizeof(struct loongarch_user_regs) != 360); -+ -+/* struct elf_prstatus from include/uapi/linux/elfcore.h */ -+struct loongarch_elf_prstatus { -+ char pad1[32]; /* 32 == offsetof(struct elf_prstatus, pr_pid) */ -+ uint32_t pr_pid; -+ char pad2[76]; /* 76 == offsetof(struct elf_prstatus, pr_reg) - -+ offsetof(struct elf_prstatus, pr_ppid) */ -+ struct loongarch_user_regs pr_reg; -+ uint32_t pr_fpvalid; -+ char pad3[4]; -+} QEMU_PACKED; -+ -+QEMU_BUILD_BUG_ON(sizeof(struct loongarch_elf_prstatus) != 480); -+ -+/* struct user_fpsimd_state from arch/arm64/include/uapi/asm/ptrace.h -+ * -+ * While the vregs member of user_fpsimd_state is of type __uint128_t, -+ * QEMU uses an array of uint64_t, where the high half of the 128-bit -+ * value is always in the 2n+1'th index. Thus we also break the 128- -+ * bit values into two halves in this reproduction of user_fpsimd_state. -+ */ -+ -+struct loongarch_fpu_struct { -+ uint64_t fpr[32]; -+ unsigned int fir; -+ unsigned int fcsr; -+} QEMU_PACKED; -+ -+QEMU_BUILD_BUG_ON(sizeof(struct loongarch_fpu_struct) != 264); -+ -+struct loongarch_note { -+ Elf64_Nhdr hdr; -+ char name[8]; /* align_up(sizeof("CORE"), 4) */ -+ union { -+ struct loongarch_elf_prstatus prstatus; -+ struct loongarch_fpu_struct fpu; -+ }; -+} QEMU_PACKED; -+ -+#define LOONGARCH_NOTE_HEADER_SIZE offsetof(struct loongarch_note, prstatus) -+#define LOONGARCH_PRSTATUS_NOTE_SIZE (LOONGARCH_NOTE_HEADER_SIZE + \ -+ sizeof(struct loongarch_elf_prstatus)) -+#define LOONGARCH_PRFPREG_NOTE_SIZE (LOONGARCH_NOTE_HEADER_SIZE + \ -+ sizeof(struct loongarch_fpu_struct)) -+ -+static void loongarch_note_init(struct loongarch_note *note, DumpState *s, -+ const char *name, Elf64_Word namesz, -+ Elf64_Word type, Elf64_Word descsz) -+{ -+ memset(note, 0, sizeof(*note)); -+ -+ note->hdr.n_namesz = cpu_to_dump32(s, namesz); -+ note->hdr.n_descsz = cpu_to_dump32(s, descsz); -+ note->hdr.n_type = cpu_to_dump32(s, type); -+ -+ memcpy(note->name, name, namesz); -+} -+ -+static int loongarch_write_elf64_fprpreg(WriteCoreDumpFunction f, -+ CPULOONGARCHState *env, int cpuid, -+ DumpState *s) -+{ -+ struct loongarch_note note; -+ int ret, i; -+ -+ loongarch_note_init(¬e, s, "CORE", 5, NT_PRFPREG, sizeof(note.fpu)); -+ -+ note.fpu.fcsr = cpu_to_dump64(s, env->active_fpu.fcsr0); -+ -+ for (i = 0; i < 32; ++i) { -+ note.fpu.fpr[i] = cpu_to_dump64(s, env->active_fpu.fpr[i].fd); -+ } -+ -+ ret = f(¬e, LOONGARCH_PRFPREG_NOTE_SIZE, s); -+ if (ret < 0) { -+ return -1; -+ } -+ -+ return 0; -+} -+ -+int loongarch_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs, -+ int cpuid, void *opaque) -+{ -+ struct loongarch_note note; -+ CPULOONGARCHState *env = &LOONGARCH_CPU(cs)->env; -+ DumpState *s = opaque; -+ int ret, i; -+ -+ loongarch_note_init(¬e, s, "CORE", 5, NT_PRSTATUS, sizeof(note.prstatus)); -+ -+ note.prstatus.pr_pid = cpu_to_dump32(s, cpuid); -+ note.prstatus.pr_fpvalid = cpu_to_dump32(s, 1); -+ -+ for (i = 0; i < 32; ++i) { -+ note.prstatus.pr_reg.gpr[i] = cpu_to_dump64(s, env->active_tc.gpr[i]); -+ } -+ note.prstatus.pr_reg.csr_era = cpu_to_dump64(s, env->CSR_ERA); -+ note.prstatus.pr_reg.csr_badvaddr = cpu_to_dump64(s, env->CSR_BADV); -+ note.prstatus.pr_reg.csr_crmd = cpu_to_dump64(s, env->CSR_CRMD); -+ note.prstatus.pr_reg.csr_ecfg = cpu_to_dump64(s, env->CSR_ECFG); -+ -+ ret = f(¬e, LOONGARCH_PRSTATUS_NOTE_SIZE, s); -+ if (ret < 0) { -+ return -1; -+ } -+ -+ ret = loongarch_write_elf64_fprpreg(f, env, cpuid, s); -+ if (ret < 0) { -+ return -1; -+ } -+ -+ return ret; -+} -+ -+int cpu_get_dump_info(ArchDumpInfo *info, -+ const GuestPhysBlockList *guest_phys_blocks) -+{ -+ info->d_machine = EM_LOONGARCH; -+ info->d_endian = ELFDATA2LSB; -+ info->d_class = ELFCLASS64; -+ -+ return 0; -+} -+ -+ssize_t cpu_get_note_size(int class, int machine, int nr_cpus) -+{ -+ size_t note_size = 0; -+ -+ if (class == ELFCLASS64) { -+ note_size = LOONGARCH_PRSTATUS_NOTE_SIZE + LOONGARCH_PRFPREG_NOTE_SIZE; -+ } -+ -+ return note_size * nr_cpus; -+} -+ -diff --git a/target/loongarch64/cpu-csr.h b/target/loongarch64/cpu-csr.h -new file mode 100644 -index 0000000000..e549bb46b6 ---- /dev/null -+++ b/target/loongarch64/cpu-csr.h -@@ -0,0 +1,869 @@ -+#ifndef _CPU_CSR_H_ -+#define _CPU_CSR_H_ -+ -+/* basic CSR register */ -+#define LOONGARCH_CSR_CRMD 0x0 /* 32 current mode info */ -+#define CSR_CRMD_DACM_SHIFT 7 -+#define CSR_CRMD_DACM_WIDTH 2 -+#define CSR_CRMD_DACM (0x3UL << CSR_CRMD_DACM_SHIFT) -+#define CSR_CRMD_DACF_SHIFT 5 -+#define CSR_CRMD_DACF_WIDTH 2 -+#define CSR_CRMD_DACF (0x3UL << CSR_CRMD_DACF_SHIFT) -+#define CSR_CRMD_PG_SHIFT 4 -+#define CSR_CRMD_PG (0x1UL << CSR_CRMD_PG_SHIFT) -+#define CSR_CRMD_DA_SHIFT 3 -+#define CSR_CRMD_DA (0x1UL << CSR_CRMD_DA_SHIFT) -+#define CSR_CRMD_IE_SHIFT 2 -+#define CSR_CRMD_IE (0x1UL << CSR_CRMD_IE_SHIFT) -+#define CSR_CRMD_PLV_SHIFT 0 -+#define CSR_CRMD_PLV_WIDTH 2 -+#define CSR_CRMD_PLV (0x3UL << CSR_CRMD_PLV_SHIFT) -+ -+#define PLV_USER 3 -+#define PLV_KERN 0 -+#define PLV_MASK 0x3 -+ -+#define LOONGARCH_CSR_PRMD 0x1 /* 32 prev-exception mode info */ -+#define CSR_PRMD_PIE_SHIFT 2 -+#define CSR_PRMD_PIE (0x1UL << CSR_PRMD_PIE_SHIFT) -+#define CSR_PRMD_PPLV_SHIFT 0 -+#define CSR_PRMD_PPLV_WIDTH 2 -+#define CSR_PRMD_PPLV (0x3UL << CSR_PRMD_PPLV_SHIFT) -+ -+#define LOONGARCH_CSR_EUEN 0x2 /* 32 coprocessor enable */ -+#define CSR_EUEN_LBTEN_SHIFT 3 -+#define CSR_EUEN_LBTEN (0x1UL << CSR_EUEN_LBTEN_SHIFT) -+#define CSR_EUEN_LASXEN_SHIFT 2 -+#define CSR_EUEN_LASXEN (0x1UL << CSR_EUEN_LASXEN_SHIFT) -+#define CSR_EUEN_LSXEN_SHIFT 1 -+#define CSR_EUEN_LSXEN (0x1UL << CSR_EUEN_LSXEN_SHIFT) -+#define CSR_EUEN_FPEN_SHIFT 0 -+#define CSR_EUEN_FPEN (0x1UL << CSR_EUEN_FPEN_SHIFT) -+ -+#define LOONGARCH_CSR_MISC 0x3 /* 32 misc config */ -+ -+#define LOONGARCH_CSR_ECFG 0x4 /* 32 exception config */ -+#define CSR_ECFG_VS_SHIFT 16 -+#define CSR_ECFG_VS_WIDTH 3 -+#define CSR_ECFG_VS (0x7UL << CSR_ECFG_VS_SHIFT) -+#define CSR_ECFG_IM_SHIFT 0 -+#define CSR_ECFG_IM_WIDTH 13 -+#define CSR_ECFG_IM (0x1fffUL << CSR_ECFG_IM_SHIFT) -+ -+#define CSR_ECFG_IPMASK 0x00001fff -+ -+#define LOONGARCH_CSR_ESTAT 0x5 /* Exception status */ -+#define CSR_ESTAT_ESUBCODE_SHIFT 22 -+#define CSR_ESTAT_ESUBCODE_WIDTH 9 -+#define CSR_ESTAT_ESUBCODE (0x1ffULL << CSR_ESTAT_ESUBCODE_SHIFT) -+#define CSR_ESTAT_EXC_SH 16 -+#define CSR_ESTAT_EXC_WIDTH 5 -+#define CSR_ESTAT_EXC (0x1fULL << CSR_ESTAT_EXC_SH) -+#define CSR_ESTAT_IS_SHIFT 0 -+#define CSR_ESTAT_IS_WIDTH 15 -+#define CSR_ESTAT_IS (0x7fffULL << CSR_ESTAT_IS_SHIFT) -+ -+#define CSR_ESTAT_IPMASK 0x00001fff -+ -+#define EXCODE_IP 64 -+#define EXCCODE_RSV 0 -+#define EXCCODE_TLBL 1 -+#define EXCCODE_TLBS 2 -+#define EXCCODE_TLBI 3 -+#define EXCCODE_MOD 4 -+#define EXCCODE_TLBRI 5 -+#define EXCCODE_TLBXI 6 -+#define EXCCODE_TLBPE 7 -+#define EXCCODE_ADE 8 -+#define EXCCODE_UNALIGN 9 -+#define EXCCODE_OOB 10 -+#define EXCCODE_SYS 11 -+#define EXCCODE_BP 12 -+#define EXCCODE_RI 13 -+#define EXCCODE_IPE 14 -+#define EXCCODE_FPDIS 15 -+#define EXCCODE_LSXDIS 16 -+#define EXCCODE_LASXDIS 17 -+#define EXCCODE_FPE 18 -+#define EXCCODE_WATCH 19 -+#define EXCCODE_BTDIS 20 -+#define EXCCODE_BTE 21 -+#define EXCCODE_PSI 22 -+#define EXCCODE_HYP 23 -+#define EXCCODE_FC 24 -+#define EXCCODE_SE 25 -+ -+#define LOONGARCH_CSR_ERA 0x6 /* 64 error PC */ -+ -+#define LOONGARCH_CSR_BADV 0x7 /* 64 bad virtual address */ -+ -+#define LOONGARCH_CSR_BADI 0x8 /* 32 bad instruction */ -+ -+#define LOONGARCH_CSR_EEPN 0xc /* 64 exception enter base address */ -+#define LOONGARCH_EEPN_CPUID (0x3ffULL << 0) -+ -+#define CU_FPE 1 -+#define CU_LSXE (1 << 1) -+#define CU_LASXE (1 << 2) -+#define CU_LBTE (1 << 3) -+ -+/* TLB related CSR register : start with TLB if no pagewalk */ -+/* 32 TLB Index, EHINV, PageSize, is_gtlb */ -+#define LOONGARCH_CSR_TLBIDX 0x10 -+#define CSR_TLBIDX_EHINV_SHIFT 31 -+#define CSR_TLBIDX_EHINV (0x1ULL << CSR_TLBIDX_EHINV_SHIFT) -+#define CSR_TLBIDX_PS_SHIFT 24 -+#define CSR_TLBIDX_PS_WIDTH 6 -+#define CSR_TLBIDX_PS (0x3fULL << CSR_TLBIDX_PS_SHIFT) -+#define CSR_TLBIDX_IDX_SHIFT 0 -+#define CSR_TLBIDX_IDX_WIDTH 12 -+#define CSR_TLBIDX_IDX (0xfffULL << CSR_TLBIDX_IDX_SHIFT) -+#define CSR_TLBIDX_SIZEM 0x3f000000 -+#define CSR_TLBIDX_SIZE CSR_TLBIDX_PS_SHIFT -+#define CSR_TLBIDX_IDXM 0xfff -+ -+#define LOONGARCH_CSR_TLBEHI 0x11 /* 64 TLB EntryHi without ASID */ -+ -+#define LOONGARCH_CSR_TLBELO0 0x12 /* 64 TLB EntryLo0 */ -+#define CSR_TLBLO0_RPLV_SHIFT 63 -+#define CSR_TLBLO0_RPLV (0x1ULL << CSR_TLBLO0_RPLV_SHIFT) -+#define CSR_TLBLO0_XI_SHIFT 62 -+#define CSR_TLBLO0_XI (0x1ULL << CSR_TLBLO0_XI_SHIFT) -+#define CSR_TLBLO0_RI_SHIFT 61 -+#define CSR_TLBLO0_RI (0x1ULL << CSR_TLBLO0_RI_SHIFT) -+#define CSR_TLBLO0_PPN_SHIFT 12 -+#define CSR_TLBLO0_PPN_WIDTH 36 /* ignore lower 12bits */ -+#define CSR_TLBLO0_PPN (0xfffffffffULL << CSR_TLBLO0_PPN_SHIFT) -+#define CSR_TLBLO0_GLOBAL_SHIFT 6 -+#define CSR_TLBLO0_GLOBAL (0x1ULL << CSR_TLBLO0_GLOBAL_SHIFT) -+#define CSR_TLBLO0_CCA_SHIFT 4 -+#define CSR_TLBLO0_CCA_WIDTH 2 -+#define CSR_TLBLO0_CCA (0x3ULL << CSR_TLBLO0_CCA_SHIFT) -+#define CSR_TLBLO0_PLV_SHIFT 2 -+#define CSR_TLBLO0_PLV_WIDTH 2 -+#define CSR_TLBLO0_PLV (0x3ULL << CSR_TLBLO0_PLV_SHIFT) -+#define CSR_TLBLO0_WE_SHIFT 1 -+#define CSR_TLBLO0_WE (0x1ULL << CSR_TLBLO0_WE_SHIFT) -+#define CSR_TLBLO0_V_SHIFT 0 -+#define CSR_TLBLO0_V (0x1ULL << CSR_TLBLO0_V_SHIFT) -+ -+#define LOONGARCH_CSR_TLBELO1 0x13 /* 64 TLB EntryLo1 */ -+#define CSR_TLBLO1_RPLV_SHIFT 63 -+#define CSR_TLBLO1_RPLV (0x1ULL << CSR_TLBLO1_RPLV_SHIFT) -+#define CSR_TLBLO1_XI_SHIFT 62 -+#define CSR_TLBLO1_XI (0x1ULL << CSR_TLBLO1_XI_SHIFT) -+#define CSR_TLBLO1_RI_SHIFT 61 -+#define CSR_TLBLO1_RI (0x1ULL << CSR_TLBLO1_RI_SHIFT) -+#define CSR_TLBLO1_PPN_SHIFT 12 -+#define CSR_TLBLO1_PPN_WIDTH 36 /* ignore lower 12bits */ -+#define CSR_TLBLO1_PPN (0xfffffffffULL << CSR_TLBLO1_PPN_SHIFT) -+#define CSR_TLBLO1_GLOBAL_SHIFT 6 -+#define CSR_TLBLO1_GLOBAL (0x1ULL << CSR_TLBLO1_GLOBAL_SHIFT) -+#define CSR_TLBLO1_CCA_SHIFT 4 -+#define CSR_TLBLO1_CCA_WIDTH 2 -+#define CSR_TLBLO1_CCA (0x3ULL << CSR_TLBLO1_CCA_SHIFT) -+#define CSR_TLBLO1_PLV_SHIFT 2 -+#define CSR_TLBLO1_PLV_WIDTH 2 -+#define CSR_TLBLO1_PLV (0x3ULL << CSR_TLBLO1_PLV_SHIFT) -+#define CSR_TLBLO1_WE_SHIFT 1 -+#define CSR_TLBLO1_WE (0x1ULL << CSR_TLBLO1_WE_SHIFT) -+#define CSR_TLBLO1_V_SHIFT 0 -+#define CSR_TLBLO1_V (0x1ULL << CSR_TLBLO1_V_SHIFT) -+ -+#define LOONGARCH_ENTRYLO_RI (1ULL << 61) -+#define LOONGARCH_ENTRYLO_XI (1ULL << 62) -+ -+#define LOONGARCH_CSR_TLBWIRED 0x14 /* 32 TLB wired */ -+#define LOONGARCH_CSR_GTLBC 0x15 /* guest-related TLB */ -+#define CSR_GTLBC_RID_SHIFT 16 -+#define CSR_GTLBC_RID_WIDTH 8 -+#define CSR_GTLBC_RID (0xffULL << CSR_GTLBC_RID_SHIFT) -+#define CSR_GTLBC_TOTI_SHIFT 13 -+#define CSR_GTLBC_TOTI (0x1ULL << CSR_GTLBC_TOTI_SHIFT) -+#define CSR_GTLBC_USERID_SHIFT 12 -+#define CSR_GTLBC_USERID (0x1ULL << CSR_GTLBC_USERID_SHIFT) -+#define CSR_GTLBC_GMTLBSZ_SHIFT 0 -+#define CSR_GTLBC_GMTLBSZ_WIDTH 6 -+#define CSR_GTLBC_GMTLBSZ (0x3fULL << CSR_GTLBC_GVTLBSZ_SHIFT) -+ -+#define LOONGARCH_CSR_TRGP 0x16 /* guest-related TLB */ -+#define CSR_TRGP_RID_SHIFT 16 -+#define CSR_TRGP_RID_WIDTH 8 -+#define CSR_TRGP_RID (0xffULL << CSR_TRGP_RID_SHIFT) -+#define CSR_TRGP_GTLB_SHIFT 0 -+#define CSR_TRGP_GTLB (1 << CSR_TRGP_GTLB_SHIFT) -+ -+#define LOONGARCH_CSR_ASID 0x18 /* 64 ASID */ -+#define CSR_ASID_BIT_SHIFT 16 /* ASIDBits */ -+#define CSR_ASID_BIT_WIDTH 8 -+#define CSR_ASID_BIT (0xffULL << CSR_ASID_BIT_SHIFT) -+#define CSR_ASID_ASID_SHIFT 0 -+#define CSR_ASID_ASID_WIDTH 10 -+#define CSR_ASID_ASID (0x3ffULL << CSR_ASID_ASID_SHIFT) -+ -+/* 64 page table base address when badv[47] = 0 */ -+#define LOONGARCH_CSR_PGDL 0x19 -+/* 64 page table base address when badv[47] = 1 */ -+#define LOONGARCH_CSR_PGDH 0x1a -+ -+#define LOONGARCH_CSR_PGD 0x1b /* 64 page table base */ -+ -+#define LOONGARCH_CSR_PWCTL0 0x1c /* 64 PWCtl0 */ -+#define CSR_PWCTL0_PTEW_SHIFT 30 -+#define CSR_PWCTL0_PTEW_WIDTH 2 -+#define CSR_PWCTL0_PTEW (0x3ULL << CSR_PWCTL0_PTEW_SHIFT) -+#define CSR_PWCTL0_DIR1WIDTH_SHIFT 25 -+#define CSR_PWCTL0_DIR1WIDTH_WIDTH 5 -+#define CSR_PWCTL0_DIR1WIDTH (0x1fULL << CSR_PWCTL0_DIR1WIDTH_SHIFT) -+#define CSR_PWCTL0_DIR1BASE_SHIFT 20 -+#define CSR_PWCTL0_DIR1BASE_WIDTH 5 -+#define CSR_PWCTL0_DIR1BASE (0x1fULL << CSR_PWCTL0_DIR1BASE_SHIFT) -+#define CSR_PWCTL0_DIR0WIDTH_SHIFT 15 -+#define CSR_PWCTL0_DIR0WIDTH_WIDTH 5 -+#define CSR_PWCTL0_DIR0WIDTH (0x1fULL << CSR_PWCTL0_DIR0WIDTH_SHIFT) -+#define CSR_PWCTL0_DIR0BASE_SHIFT 10 -+#define CSR_PWCTL0_DIR0BASE_WIDTH 5 -+#define CSR_PWCTL0_DIR0BASE (0x1fULL << CSR_PWCTL0_DIR0BASE_SHIFT) -+#define CSR_PWCTL0_PTWIDTH_SHIFT 5 -+#define CSR_PWCTL0_PTWIDTH_WIDTH 5 -+#define CSR_PWCTL0_PTWIDTH (0x1fULL << CSR_PWCTL0_PTWIDTH_SHIFT) -+#define CSR_PWCTL0_PTBASE_SHIFT 0 -+#define CSR_PWCTL0_PTBASE_WIDTH 5 -+#define CSR_PWCTL0_PTBASE (0x1fULL << CSR_PWCTL0_PTBASE_SHIFT) -+ -+#define LOONGARCH_CSR_PWCTL1 0x1d /* 64 PWCtl1 */ -+#define CSR_PWCTL1_DIR3WIDTH_SHIFT 18 -+#define CSR_PWCTL1_DIR3WIDTH_WIDTH 5 -+#define CSR_PWCTL1_DIR3WIDTH (0x1fULL << CSR_PWCTL1_DIR3WIDTH_SHIFT) -+#define CSR_PWCTL1_DIR3BASE_SHIFT 12 -+#define CSR_PWCTL1_DIR3BASE_WIDTH 5 -+#define CSR_PWCTL1_DIR3BASE (0x1fULL << CSR_PWCTL0_DIR3BASE_SHIFT) -+#define CSR_PWCTL1_DIR2WIDTH_SHIFT 6 -+#define CSR_PWCTL1_DIR2WIDTH_WIDTH 5 -+#define CSR_PWCTL1_DIR2WIDTH (0x1fULL << CSR_PWCTL1_DIR2WIDTH_SHIFT) -+#define CSR_PWCTL1_DIR2BASE_SHIFT 0 -+#define CSR_PWCTL1_DIR2BASE_WIDTH 5 -+#define CSR_PWCTL1_DIR2BASE (0x1fULL << CSR_PWCTL0_DIR2BASE_SHIFT) -+ -+#define LOONGARCH_CSR_STLBPGSIZE 0x1e /* 64 */ -+#define CSR_STLBPGSIZE_PS_WIDTH 6 -+#define CSR_STLBPGSIZE_PS (0x3f) -+ -+#define LOONGARCH_CSR_RVACFG 0x1f -+#define CSR_RVACFG_RDVA_WIDTH 4 -+#define CSR_RVACFG_RDVA (0xf) -+ -+/* read only CSR register : start with CPU */ -+#define LOONGARCH_CSR_CPUID 0x20 /* 32 CPU core number */ -+#define CSR_CPUID_CID_WIDTH 9 -+#define CSR_CPUID_CID (0x1ff) -+ -+#define LOONGARCH_CSR_PRCFG1 0x21 /* 32 CPU info */ -+#define CSR_CONF1_VSMAX_SHIFT 12 -+#define CSR_CONF1_VSMAX_WIDTH 3 -+#define CSR_CONF1_VSMAX (7ULL << CSR_CONF1_VSMAX_SHIFT) -+/* stable timer bits - 1, 0x2f = 47*/ -+#define CSR_CONF1_TMRBITS_SHIFT 4 -+#define CSR_CONF1_TMRBITS_WIDTH 8 -+#define CSR_CONF1_TMRBITS (0xffULL << CSR_CONF1_TMRBITS_SHIFT) -+#define CSR_CONF1_KSNUM_SHIFT 0 -+#define CSR_CONF1_KSNUM_WIDTH 4 -+#define CSR_CONF1_KSNUM (0x8) -+ -+#define LOONGARCH_CSR_PRCFG2 0x22 -+#define CSR_CONF2_PGMASK_SUPP 0x3ffff000 -+ -+#define LOONGARCH_CSR_PRCFG3 0x23 -+#define CSR_CONF3_STLBIDX_SHIFT 20 -+#define CSR_CONF3_STLBIDX_WIDTH 6 -+#define CSR_CONF3_STLBIDX (0x3fULL << CSR_CONF3_STLBIDX_SHIFT) -+#define CSR_STLB_SETS 256 -+#define CSR_CONF3_STLBWAYS_SHIFT 12 -+#define CSR_CONF3_STLBWAYS_WIDTH 8 -+#define CSR_CONF3_STLBWAYS (0xffULL << CSR_CONF3_STLBWAYS_SHIFT) -+#define CSR_STLBWAYS_SIZE 8 -+#define CSR_CONF3_MTLBSIZE_SHIFT 4 -+#define CSR_CONF3_MTLBSIZE_WIDTH 8 -+#define CSR_CONF3_MTLBSIZE (0xffULL << CSR_CONF3_MTLBSIZE_SHIFT) -+/* mean VTLB 64 index */ -+#define CSR_MTLB_SIZE 64 -+#define CSR_CONF3_TLBORG_SHIFT 0 -+#define CSR_CONF3_TLBORG_WIDTH 4 -+#define CSR_CONF3_TLBORG (0xfULL << CSR_CONF3_TLBORG_SHIFT) -+/* mean use MTLB+STLB */ -+#define TLB_ORG 2 -+ -+/* Kscratch : start with KS */ -+#define LOONGARCH_CSR_KS0 0x30 /* 64 */ -+#define LOONGARCH_CSR_KS1 0x31 /* 64 */ -+#define LOONGARCH_CSR_KS2 0x32 /* 64 */ -+#define LOONGARCH_CSR_KS3 0x33 /* 64 */ -+#define LOONGARCH_CSR_KS4 0x34 /* 64 */ -+#define LOONGARCH_CSR_KS5 0x35 /* 64 */ -+#define LOONGARCH_CSR_KS6 0x36 /* 64 */ -+#define LOONGARCH_CSR_KS7 0x37 /* 64 */ -+#define LOONGARCH_CSR_KS8 0x38 /* 64 */ -+ -+/* timer : start with TM */ -+#define LOONGARCH_CSR_TMID 0x40 /* 32 timer ID */ -+ -+#define LOONGARCH_CSR_TCFG 0x41 /* 64 timer config */ -+#define CSR_TCFG_VAL_SHIFT 2 -+#define CSR_TCFG_VAL_WIDTH 48 -+#define CSR_TCFG_VAL (0x3fffffffffffULL << CSR_TCFG_VAL_SHIFT) -+#define CSR_TCFG_PERIOD_SHIFT 1 -+#define CSR_TCFG_PERIOD (0x1ULL << CSR_TCFG_PERIOD_SHIFT) -+#define CSR_TCFG_EN (0x1) -+ -+#define LOONGARCH_CSR_TVAL 0x42 /* 64 timer ticks remain */ -+ -+#define LOONGARCH_CSR_CNTC 0x43 /* 64 timer offset */ -+ -+#define LOONGARCH_CSR_TINTCLR 0x44 /* 64 timer interrupt clear */ -+#define CSR_TINTCLR_TI_SHIFT 0 -+#define CSR_TINTCLR_TI (1 << CSR_TINTCLR_TI_SHIFT) -+ -+/* guest : start with GST */ -+#define LOONGARCH_CSR_GSTAT 0x50 /* 32 basic guest info */ -+#define CSR_GSTAT_GID_SHIFT 16 -+#define CSR_GSTAT_GID_WIDTH 8 -+#define CSR_GSTAT_GID (0xffULL << CSR_GSTAT_GID_SHIFT) -+#define CSR_GSTAT_GIDBIT_SHIFT 4 -+#define CSR_GSTAT_GIDBIT_WIDTH 6 -+#define CSR_GSTAT_GIDBIT (0x3fULL << CSR_GSTAT_GIDBIT_SHIFT) -+#define CSR_GSTAT_PVM_SHIFT 1 -+#define CSR_GSTAT_PVM (0x1ULL << CSR_GSTAT_PVM_SHIFT) -+#define CSR_GSTAT_VM_SHIFT 0 -+#define CSR_GSTAT_VM (0x1ULL << CSR_GSTAT_VM_SHIFT) -+ -+#define LOONGARCH_CSR_GCFG 0x51 /* 32 guest config */ -+#define CSR_GCFG_GPERF_SHIFT 24 -+#define CSR_GCFG_GPERF_WIDTH 3 -+#define CSR_GCFG_GPERF (0x7ULL << CSR_GCFG_GPERF_SHIFT) -+#define CSR_GCFG_GCI_SHIFT 20 -+#define CSR_GCFG_GCI_WIDTH 2 -+#define CSR_GCFG_GCI (0x3ULL << CSR_GCFG_GCI_SHIFT) -+#define CSR_GCFG_GCI_ALL (0x0ULL << CSR_GCFG_GCI_SHIFT) -+#define CSR_GCFG_GCI_HIT (0x1ULL << CSR_GCFG_GCI_SHIFT) -+#define CSR_GCFG_GCI_SECURE (0x2ULL << CSR_GCFG_GCI_SHIFT) -+#define CSR_GCFG_GCIP_SHIFT 16 -+#define CSR_GCFG_GCIP (0xfULL << CSR_GCFG_GCIP_SHIFT) -+#define CSR_GCFG_GCIP_ALL (0x1ULL << CSR_GCFG_GCIP_SHIFT) -+#define CSR_GCFG_GCIP_HIT (0x1ULL << (CSR_GCFG_GCIP_SHIFT + 1)) -+#define CSR_GCFG_GCIP_SECURE (0x1ULL << (CSR_GCFG_GCIP_SHIFT + 2)) -+#define CSR_GCFG_TORU_SHIFT 15 -+#define CSR_GCFG_TORU (0x1ULL << CSR_GCFG_TORU_SHIFT) -+#define CSR_GCFG_TORUP_SHIFT 14 -+#define CSR_GCFG_TORUP (0x1ULL << CSR_GCFG_TORUP_SHIFT) -+#define CSR_GCFG_TOP_SHIFT 13 -+#define CSR_GCFG_TOP (0x1ULL << CSR_GCFG_TOP_SHIFT) -+#define CSR_GCFG_TOPP_SHIFT 12 -+#define CSR_GCFG_TOPP (0x1ULL << CSR_GCFG_TOPP_SHIFT) -+#define CSR_GCFG_TOE_SHIFT 11 -+#define CSR_GCFG_TOE (0x1ULL << CSR_GCFG_TOE_SHIFT) -+#define CSR_GCFG_TOEP_SHIFT 10 -+#define CSR_GCFG_TOEP (0x1ULL << CSR_GCFG_TOEP_SHIFT) -+#define CSR_GCFG_TIT_SHIFT 9 -+#define CSR_GCFG_TIT (0x1ULL << CSR_GCFG_TIT_SHIFT) -+#define CSR_GCFG_TITP_SHIFT 8 -+#define CSR_GCFG_TITP (0x1ULL << CSR_GCFG_TITP_SHIFT) -+#define CSR_GCFG_SIT_SHIFT 7 -+#define CSR_GCFG_SIT (0x1ULL << CSR_GCFG_SIT_SHIFT) -+#define CSR_GCFG_SITP_SHIFT 6 -+#define CSR_GCFG_SITP (0x1ULL << CSR_GCFG_SITP_SHIFT) -+#define CSR_GCFG_CACTRL_SHIFT 4 -+#define CSR_GCFG_CACTRL_WIDTH 2 -+#define CSR_GCFG_CACTRL (0x3ULL << CSR_GCFG_CACTRL_SHIFT) -+#define CSR_GCFG_CACTRL_GUEST (0x0ULL << CSR_GCFG_CACTRL_SHIFT) -+#define CSR_GCFG_CACTRL_ROOT (0x1ULL << CSR_GCFG_CACTRL_SHIFT) -+#define CSR_GCFG_CACTRL_NEST (0x2ULL << CSR_GCFG_CACTRL_SHIFT) -+#define CSR_GCFG_CCCP_WIDTH 4 -+#define CSR_GCFG_CCCP (0xf) -+#define CSR_GCFG_CCCP_GUEST (0x1ULL << 0) -+#define CSR_GCFG_CCCP_ROOT (0x1ULL << 1) -+#define CSR_GCFG_CCCP_NEST (0x1ULL << 2) -+ -+#define LOONGARCH_CSR_GINTC 0x52 /* 64 guest exception control */ -+#define CSR_GINTC_HC_SHIFT 16 -+#define CSR_GINTC_HC_WIDTH 8 -+#define CSR_GINTC_HC (0xffULL << CSR_GINTC_HC_SHIFT) -+#define CSR_GINTC_PIP_SHIFT 8 -+#define CSR_GINTC_PIP_WIDTH 8 -+#define CSR_GINTC_PIP (0xffULL << CSR_GINTC_PIP_SHIFT) -+#define CSR_GINTC_VIP_SHIFT 0 -+#define CSR_GINTC_VIP_WIDTH 8 -+#define CSR_GINTC_VIP (0xff) -+ -+#define LOONGARCH_CSR_GCNTC 0x53 /* 64 guest timer offset */ -+ -+/* LLBCTL */ -+#define LOONGARCH_CSR_LLBCTL 0x60 /* 32 csr number to be changed */ -+#define CSR_LLBCTL_ROLLB_SHIFT 0 -+#define CSR_LLBCTL_ROLLB (1ULL << CSR_LLBCTL_ROLLB_SHIFT) -+#define CSR_LLBCTL_WCLLB_SHIFT 1 -+#define CSR_LLBCTL_WCLLB (1ULL << CSR_LLBCTL_WCLLB_SHIFT) -+#define CSR_LLBCTL_KLO_SHIFT 2 -+#define CSR_LLBCTL_KLO (1ULL << CSR_LLBCTL_KLO_SHIFT) -+ -+/* implement dependent */ -+#define LOONGARCH_CSR_IMPCTL1 0x80 /* 32 loongarch config */ -+#define CSR_MISPEC_SHIFT 20 -+#define CSR_MISPEC_WIDTH 8 -+#define CSR_MISPEC (0xffULL << CSR_MISPEC_SHIFT) -+#define CSR_SSEN_SHIFT 18 -+#define CSR_SSEN (1ULL << CSR_SSEN_SHIFT) -+#define CSR_SCRAND_SHIFT 17 -+#define CSR_SCRAND (1ULL << CSR_SCRAND_SHIFT) -+#define CSR_LLEXCL_SHIFT 16 -+#define CSR_LLEXCL (1ULL << CSR_LLEXCL_SHIFT) -+#define CSR_DISVC_SHIFT 15 -+#define CSR_DISVC (1ULL << CSR_DISVC_SHIFT) -+#define CSR_VCLRU_SHIFT 14 -+#define CSR_VCLRU (1ULL << CSR_VCLRU_SHIFT) -+#define CSR_DCLRU_SHIFT 13 -+#define CSR_DCLRU (1ULL << CSR_DCLRU_SHIFT) -+#define CSR_FASTLDQ_SHIFT 12 -+#define CSR_FASTLDQ (1ULL << CSR_FASTLDQ_SHIFT) -+#define CSR_USERCAC_SHIFT 11 -+#define CSR_USERCAC (1ULL << CSR_USERCAC_SHIFT) -+#define CSR_ANTI_MISPEC_SHIFT 10 -+#define CSR_ANTI_MISPEC (1ULL << CSR_ANTI_MISPEC_SHIFT) -+#define CSR_ANTI_FLUSHSFB_SHIFT 9 -+#define CSR_ANTI_FLUSHSFB (1ULL << CSR_ANTI_FLUSHSFB_SHIFT) -+#define CSR_STFILL_SHIFT 8 -+#define CSR_STFILL (1ULL << CSR_STFILL_SHIFT) -+#define CSR_LIFEP_SHIFT 7 -+#define CSR_LIFEP (1ULL << CSR_LIFEP_SHIFT) -+#define CSR_LLSYNC_SHIFT 6 -+#define CSR_LLSYNC (1ULL << CSR_LLSYNC_SHIFT) -+#define CSR_BRBTDIS_SHIFT 5 -+#define CSR_BRBTDIS (1ULL << CSR_BRBTDIS_SHIFT) -+#define CSR_RASDIS_SHIFT 4 -+#define CSR_RASDIS (1ULL << CSR_RASDIS_SHIFT) -+#define CSR_STPRE_SHIFT 2 -+#define CSR_STPRE_WIDTH 2 -+#define CSR_STPRE (3ULL << CSR_STPRE_SHIFT) -+#define CSR_INSTPRE_SHIFT 1 -+#define CSR_INSTPRE (1ULL << CSR_INSTPRE_SHIFT) -+#define CSR_DATAPRE_SHIFT 0 -+#define CSR_DATAPRE (1ULL << CSR_DATAPRE_SHIFT) -+ -+#define LOONGARCH_CSR_IMPCTL2 0x81 /* 32 Flush */ -+#define CSR_IMPCTL2_MTLB_SHIFT 0 -+#define CSR_IMPCTL2_MTLB (1ULL << CSR_IMPCTL2_MTLB_SHIFT) -+#define CSR_IMPCTL2_STLB_SHIFT 1 -+#define CSR_IMPCTL2_STLB (1ULL << CSR_IMPCTL2_STLB_SHIFT) -+#define CSR_IMPCTL2_DTLB_SHIFT 2 -+#define CSR_IMPCTL2_DTLB (1ULL << CSR_IMPCTL2_DTLB_SHIFT) -+#define CSR_IMPCTL2_ITLB_SHIFT 3 -+#define CSR_IMPCTL2_ITLB (1ULL << CSR_IMPCTL2_ITLB_SHIFT) -+#define CSR_IMPCTL2_BTAC_SHIFT 4 -+#define CSR_IMPCTL2_BTAC (1ULL << CSR_IMPCTL2_BTAC_SHIFT) -+ -+#define LOONGARCH_FLUSH_VTLB 1 -+#define LOONGARCH_FLUSH_FTLB (1 << 1) -+#define LOONGARCH_FLUSH_DTLB (1 << 2) -+#define LOONGARCH_FLUSH_ITLB (1 << 3) -+#define LOONGARCH_FLUSH_BTAC (1 << 4) -+ -+#define LOONGARCH_CSR_GNMI 0x82 -+ -+/* TLB Refill Only */ -+#define LOONGARCH_CSR_TLBRENT 0x88 /* 64 TLB refill exception address */ -+#define LOONGARCH_CSR_TLBRBADV 0x89 /* 64 TLB refill badvaddr */ -+#define LOONGARCH_CSR_TLBRERA 0x8a /* 64 TLB refill ERA */ -+#define LOONGARCH_CSR_TLBRSAVE 0x8b /* 64 KScratch for TLB refill */ -+#define LOONGARCH_CSR_TLBRELO0 0x8c /* 64 TLB refill entrylo0 */ -+#define LOONGARCH_CSR_TLBRELO1 0x8d /* 64 TLB refill entrylo1 */ -+#define LOONGARCH_CSR_TLBREHI 0x8e /* 64 TLB refill entryhi */ -+#define LOONGARCH_CSR_TLBRPRMD 0x8f /* 64 TLB refill mode info */ -+ -+/* error related */ -+#define LOONGARCH_CSR_ERRCTL 0x90 /* 32 ERRCTL */ -+#define LOONGARCH_CSR_ERRINFO 0x91 -+#define LOONGARCH_CSR_ERRINFO1 0x92 -+#define LOONGARCH_CSR_ERRENT 0x93 /* 64 error exception base */ -+#define LOONGARCH_CSR_ERRERA 0x94 /* 64 error exception PC */ -+#define LOONGARCH_CSR_ERRSAVE 0x95 /* 64 KScratch for error exception */ -+ -+#define LOONGARCH_CSR_CTAG 0x98 /* 64 TagLo + TagHi */ -+ -+/* direct map windows */ -+#define LOONGARCH_CSR_DMWIN0 0x180 /* 64 direct map win0: MEM & IF */ -+#define LOONGARCH_CSR_DMWIN1 0x181 /* 64 direct map win1: MEM & IF */ -+#define LOONGARCH_CSR_DMWIN2 0x182 /* 64 direct map win2: MEM */ -+#define LOONGARCH_CSR_DMWIN3 0x183 /* 64 direct map win3: MEM */ -+#define CSR_DMW_PLV0 0x1 -+#define CSR_DMW_PLV1 0x2 -+#define CSR_DMW_PLV2 0x4 -+#define CSR_DMW_PLV3 0x8 -+#define CSR_DMW_BASE_SH 48 -+#define dmwin_va2pa(va) \ -+ (va & (((unsigned long)1 << CSR_DMW_BASE_SH) - 1)) -+ -+/* performance counter */ -+#define LOONGARCH_CSR_PERFCTRL0 0x200 /* 32 perf event 0 config */ -+#define LOONGARCH_CSR_PERFCNTR0 0x201 /* 64 perf event 0 count value */ -+#define LOONGARCH_CSR_PERFCTRL1 0x202 /* 32 perf event 1 config */ -+#define LOONGARCH_CSR_PERFCNTR1 0x203 /* 64 perf event 1 count value */ -+#define LOONGARCH_CSR_PERFCTRL2 0x204 /* 32 perf event 2 config */ -+#define LOONGARCH_CSR_PERFCNTR2 0x205 /* 64 perf event 2 count value */ -+#define LOONGARCH_CSR_PERFCTRL3 0x206 /* 32 perf event 3 config */ -+#define LOONGARCH_CSR_PERFCNTR3 0x207 /* 64 perf event 3 count value */ -+#define CSR_PERFCTRL_PLV0 (1ULL << 16) -+#define CSR_PERFCTRL_PLV1 (1ULL << 17) -+#define CSR_PERFCTRL_PLV2 (1ULL << 18) -+#define CSR_PERFCTRL_PLV3 (1ULL << 19) -+#define CSR_PERFCTRL_IE (1ULL << 20) -+#define CSR_PERFCTRL_EVENT 0x3ff -+ -+/* debug */ -+#define LOONGARCH_CSR_MWPC 0x300 /* data breakpoint config */ -+#define LOONGARCH_CSR_MWPS 0x301 /* data breakpoint status */ -+ -+#define LOONGARCH_CSR_DB0ADDR 0x310 /* data breakpoint 0 address */ -+#define LOONGARCH_CSR_DB0MASK 0x311 /* data breakpoint 0 mask */ -+#define LOONGARCH_CSR_DB0CTL 0x312 /* data breakpoint 0 control */ -+#define LOONGARCH_CSR_DB0ASID 0x313 /* data breakpoint 0 asid */ -+ -+#define LOONGARCH_CSR_DB1ADDR 0x318 /* data breakpoint 1 address */ -+#define LOONGARCH_CSR_DB1MASK 0x319 /* data breakpoint 1 mask */ -+#define LOONGARCH_CSR_DB1CTL 0x31a /* data breakpoint 1 control */ -+#define LOONGARCH_CSR_DB1ASID 0x31b /* data breakpoint 1 asid */ -+ -+#define LOONGARCH_CSR_DB2ADDR 0x320 /* data breakpoint 2 address */ -+#define LOONGARCH_CSR_DB2MASK 0x321 /* data breakpoint 2 mask */ -+#define LOONGARCH_CSR_DB2CTL 0x322 /* data breakpoint 2 control */ -+#define LOONGARCH_CSR_DB2ASID 0x323 /* data breakpoint 2 asid */ -+ -+#define LOONGARCH_CSR_DB3ADDR 0x328 /* data breakpoint 3 address */ -+#define LOONGARCH_CSR_DB3MASK 0x329 /* data breakpoint 3 mask */ -+#define LOONGARCH_CSR_DB3CTL 0x32a /* data breakpoint 3 control */ -+#define LOONGARCH_CSR_DB3ASID 0x32b /* data breakpoint 3 asid */ -+ -+#define LOONGARCH_CSR_FWPC 0x380 /* instruction breakpoint config */ -+#define LOONGARCH_CSR_FWPS 0x381 /* instruction breakpoint status */ -+ -+#define LOONGARCH_CSR_IB0ADDR 0x390 /* inst breakpoint 0 address */ -+#define LOONGARCH_CSR_IB0MASK 0x391 /* inst breakpoint 0 mask */ -+#define LOONGARCH_CSR_IB0CTL 0x392 /* inst breakpoint 0 control */ -+#define LOONGARCH_CSR_IB0ASID 0x393 /* inst breakpoint 0 asid */ -+#define LOONGARCH_CSR_IB1ADDR 0x398 /* inst breakpoint 1 address */ -+#define LOONGARCH_CSR_IB1MASK 0x399 /* inst breakpoint 1 mask */ -+#define LOONGARCH_CSR_IB1CTL 0x39a /* inst breakpoint 1 control */ -+#define LOONGARCH_CSR_IB1ASID 0x39b /* inst breakpoint 1 asid */ -+ -+#define LOONGARCH_CSR_IB2ADDR 0x3a0 /* inst breakpoint 2 address */ -+#define LOONGARCH_CSR_IB2MASK 0x3a1 /* inst breakpoint 2 mask */ -+#define LOONGARCH_CSR_IB2CTL 0x3a2 /* inst breakpoint 2 control */ -+#define LOONGARCH_CSR_IB2ASID 0x3a3 /* inst breakpoint 2 asid */ -+ -+#define LOONGARCH_CSR_IB3ADDR 0x3a8 /* inst breakpoint 3 address */ -+#define LOONGARCH_CSR_IB3MASK 0x3a9 /* inst breakpoint 3 mask */ -+#define LOONGARCH_CSR_IB3CTL 0x3aa /* inst breakpoint 3 control */ -+#define LOONGARCH_CSR_IB3ASID 0x3ab /* inst breakpoint 3 asid */ -+ -+#define LOONGARCH_CSR_IB4ADDR 0x3b0 /* inst breakpoint 4 address */ -+#define LOONGARCH_CSR_IB4MASK 0x3b1 /* inst breakpoint 4 mask */ -+#define LOONGARCH_CSR_IB4CTL 0x3b2 /* inst breakpoint 4 control */ -+#define LOONGARCH_CSR_IB4ASID 0x3b3 /* inst breakpoint 4 asid */ -+ -+#define LOONGARCH_CSR_IB5ADDR 0x3b8 /* inst breakpoint 5 address */ -+#define LOONGARCH_CSR_IB5MASK 0x3b9 /* inst breakpoint 5 mask */ -+#define LOONGARCH_CSR_IB5CTL 0x3ba /* inst breakpoint 5 control */ -+#define LOONGARCH_CSR_IB5ASID 0x3bb /* inst breakpoint 5 asid */ -+ -+#define LOONGARCH_CSR_IB6ADDR 0x3c0 /* inst breakpoint 6 address */ -+#define LOONGARCH_CSR_IB6MASK 0x3c1 /* inst breakpoint 6 mask */ -+#define LOONGARCH_CSR_IB6CTL 0x3c2 /* inst breakpoint 6 control */ -+#define LOONGARCH_CSR_IB6ASID 0x3c3 /* inst breakpoint 6 asid */ -+ -+#define LOONGARCH_CSR_IB7ADDR 0x3c8 /* inst breakpoint 7 address */ -+#define LOONGARCH_CSR_IB7MASK 0x3c9 /* inst breakpoint 7 mask */ -+#define LOONGARCH_CSR_IB7CTL 0x3ca /* inst breakpoint 7 control */ -+#define LOONGARCH_CSR_IB7ASID 0x3cb /* inst breakpoint 7 asid */ -+ -+#define LOONGARCH_CSR_DEBUG 0x500 /* debug config */ -+#define CSR_DEBUG_DM 0 -+#define CSR_DEBUG_DMVER 1 -+#define CSR_DEBUG_DINT 8 -+#define CSR_DEBUG_DBP 9 -+#define CSR_DEBUG_DIB 10 -+#define CSR_DEBUG_DDB 11 -+ -+#define LOONGARCH_CSR_DERA 0x501 /* debug era */ -+#define LOONGARCH_CSR_DESAVE 0x502 /* debug save */ -+ -+#define LOONGARCH_CSR_PRID 0xc0 /* 32 LOONGARCH CP0 PRID */ -+ -+#define LOONGARCH_CPUCFG0 0x0 -+#define CPUCFG0_3A5000_PRID 0x0014c010 -+ -+#define LOONGARCH_CPUCFG1 0x1 -+#define CPUCFG1_ISGR32 BIT(0) -+#define CPUCFG1_ISGR64 BIT(1) -+#define CPUCFG1_PAGING BIT(2) -+#define CPUCFG1_IOCSR BIT(3) -+#define CPUCFG1_PABITS (47 << 4) -+#define CPUCFG1_VABITS (47 << 12) -+#define CPUCFG1_UAL BIT(20) -+#define CPUCFG1_RI BIT(21) -+#define CPUCFG1_XI BIT(22) -+#define CPUCFG1_RPLV BIT(23) -+#define CPUCFG1_HUGEPG BIT(24) -+#define CPUCFG1_IOCSRBRD BIT(25) -+#define CPUCFG1_MSGINT BIT(26) -+ -+#define LOONGARCH_CPUCFG2 0x2 -+#define CPUCFG2_FP BIT(0) -+#define CPUCFG2_FPSP BIT(1) -+#define CPUCFG2_FPDP BIT(2) -+#define CPUCFG2_FPVERS (0 << 3) -+#define CPUCFG2_LSX BIT(6) -+#define CPUCFG2_LASX BIT(7) -+#define CPUCFG2_COMPLEX BIT(8) -+#define CPUCFG2_CRYPTO BIT(9) -+#define CPUCFG2_LVZP BIT(10) -+#define CPUCFG2_LVZVER (0 << 11) -+#define CPUCFG2_LLFTP BIT(14) -+#define CPUCFG2_LLFTPREV (1 << 15) -+#define CPUCFG2_X86BT BIT(18) -+#define CPUCFG2_ARMBT BIT(19) -+#define CPUCFG2_MIPSBT BIT(20) -+#define CPUCFG2_LSPW BIT(21) -+#define CPUCFG2_LAM BIT(22) -+ -+#define LOONGARCH_CPUCFG3 0x3 -+#define CPUCFG3_CCDMA BIT(0) -+#define CPUCFG3_SFB BIT(1) -+#define CPUCFG3_UCACC BIT(2) -+#define CPUCFG3_LLEXC BIT(3) -+#define CPUCFG3_SCDLY BIT(4) -+#define CPUCFG3_LLDBAR BIT(5) -+#define CPUCFG3_ITLBT BIT(6) -+#define CPUCFG3_ICACHET BIT(7) -+#define CPUCFG3_SPW_LVL (4 << 8) -+#define CPUCFG3_SPW_HG_HF BIT(11) -+#define CPUCFG3_RVA BIT(12) -+#define CPUCFG3_RVAMAX (7 << 13) -+ -+#define LOONGARCH_CPUCFG4 0x4 -+#define CCFREQ_100M 100000000 /* 100M */ -+ -+#define LOONGARCH_CPUCFG5 0x5 -+#define CPUCFG5_CCMUL 1 -+#define CPUCFG5_CCDIV (1 << 16) -+ -+#define LOONGARCH_CPUCFG6 0x6 -+#define CPUCFG6_PMP BIT(0) -+#define CPUCFG6_PAMVER (1 << 1) -+#define CPUCFG6_PMNUM (3 << 4) -+#define CPUCFG6_PMBITS (63 << 8) -+#define CPUCFG6_UPM BIT(14) -+ -+#define LOONGARCH_CPUCFG16 0x10 -+#define CPUCFG16_L1_IUPRE BIT(0) -+#define CPUCFG16_L1_UNIFY BIT(1) -+#define CPUCFG16_L1_DPRE BIT(2) -+#define CPUCFG16_L2_IUPRE BIT(3) -+#define CPUCFG16_L2_IUUNIFY BIT(4) -+#define CPUCFG16_L2_IUPRIV BIT(5) -+#define CPUCFG16_L2_IUINCL BIT(6) -+#define CPUCFG16_L2_DPRE BIT(7) -+#define CPUCFG16_L2_DPRIV BIT(8) -+#define CPUCFG16_L2_DINCL BIT(9) -+#define CPUCFG16_L3_IUPRE BIT(10) -+#define CPUCFG16_L3_IUUNIFY BIT(11) -+#define CPUCFG16_L3_IUPRIV BIT(12) -+#define CPUCFG16_L3_IUINCL BIT(13) -+#define CPUCFG16_L3_DPRE BIT(14) -+#define CPUCFG16_L3_DPRIV BIT(15) -+#define CPUCFG16_L3_DINCL BIT(16) -+ -+#define LOONGARCH_CPUCFG17 0x11 -+#define CPUCFG17_L1I_WAYS_M (3 << 0) -+#define CPUCFG17_L1I_SETS_M (8 << 16) -+#define CPUCFG17_L1I_SIZE_M (6 << 24) -+ -+#define LOONGARCH_CPUCFG18 0x12 -+#define CPUCFG18_L1D_WAYS_M (3 << 0) -+#define CPUCFG18_L1D_SETS_M (8 << 16) -+#define CPUCFG18_L1D_SIZE_M (6 << 24) -+ -+#define LOONGARCH_CPUCFG19 0x13 -+#define CPUCFG19_L2_WAYS_M (0xf << 0) -+#define CPUCFG19_L2_SETS_M (8 << 16) -+#define CPUCFG19_L2_SIZE_M (6 << 24) -+ -+#define LOONGARCH_CPUCFG20 0x14 -+#define CPUCFG20_L3_WAYS_M (0xf << 0) -+#define CPUCFG20_L3_SETS_M (0xe << 16) -+#define CPUCFG20_L3_SIZE_M (0x6 << 24) -+ -+#define LOONGARCH_PAGE_HUGE 0x40 -+#define LOONGARCH_HUGE_GLOBAL 0x1000 -+#define LOONGARCH_HUGE_GLOBAL_SH 12 -+ -+/* All CSR register -+ * -+ * default value in target/loongarch/cpu.c -+ * reset function in target/loongarch/translate.c:cpu_state_reset() -+ * -+ * This macro will be used only twice. -+ * > In target/loongarch/cpu.h:CPULOONGARCHState -+ * > In target/loongarch/internal.h:loongarch_def_t -+ * -+ * helper_function to rd/wr: -+ * > declare in target/loongarch/helper.h -+ * > realize in target/loongarch/op_helper.c -+ * -+ * during translate: -+ * > gen_csr_rdl() -+ * > gen_csr_wrl() -+ * > gen_csr_rdq() -+ * > gen_csr_wrq() -+ */ -+#define CPU_LOONGARCH_CSR \ -+ uint64_t CSR_CRMD; \ -+ uint64_t CSR_PRMD; \ -+ uint64_t CSR_EUEN; \ -+ uint64_t CSR_MISC; \ -+ uint64_t CSR_ECFG; \ -+ uint64_t CSR_ESTAT; \ -+ uint64_t CSR_ERA; \ -+ uint64_t CSR_BADV; \ -+ uint64_t CSR_BADI; \ -+ uint64_t CSR_EEPN; \ -+ uint64_t CSR_TLBIDX; \ -+ uint64_t CSR_TLBEHI; \ -+ uint64_t CSR_TLBELO0; \ -+ uint64_t CSR_TLBELO1; \ -+ uint64_t CSR_TLBWIRED; \ -+ uint64_t CSR_GTLBC; \ -+ uint64_t CSR_TRGP; \ -+ uint64_t CSR_ASID; \ -+ uint64_t CSR_PGDL; \ -+ uint64_t CSR_PGDH; \ -+ uint64_t CSR_PGD; \ -+ uint64_t CSR_PWCTL0; \ -+ uint64_t CSR_PWCTL1; \ -+ uint64_t CSR_STLBPGSIZE; \ -+ uint64_t CSR_RVACFG; \ -+ uint64_t CSR_CPUID; \ -+ uint64_t CSR_PRCFG1; \ -+ uint64_t CSR_PRCFG2; \ -+ uint64_t CSR_PRCFG3; \ -+ uint64_t CSR_KS0; \ -+ uint64_t CSR_KS1; \ -+ uint64_t CSR_KS2; \ -+ uint64_t CSR_KS3; \ -+ uint64_t CSR_KS4; \ -+ uint64_t CSR_KS5; \ -+ uint64_t CSR_KS6; \ -+ uint64_t CSR_KS7; \ -+ uint64_t CSR_KS8; \ -+ uint64_t CSR_TMID; \ -+ uint64_t CSR_TCFG; \ -+ uint64_t CSR_TVAL; \ -+ uint64_t CSR_CNTC; \ -+ uint64_t CSR_TINTCLR; \ -+ uint64_t CSR_GSTAT; \ -+ uint64_t CSR_GCFG; \ -+ uint64_t CSR_GINTC; \ -+ uint64_t CSR_GCNTC; \ -+ uint64_t CSR_LLBCTL; \ -+ uint64_t CSR_IMPCTL1; \ -+ uint64_t CSR_IMPCTL2; \ -+ uint64_t CSR_GNMI; \ -+ uint64_t CSR_TLBRENT; \ -+ uint64_t CSR_TLBRBADV; \ -+ uint64_t CSR_TLBRERA; \ -+ uint64_t CSR_TLBRSAVE; \ -+ uint64_t CSR_TLBRELO0; \ -+ uint64_t CSR_TLBRELO1; \ -+ uint64_t CSR_TLBREHI; \ -+ uint64_t CSR_TLBRPRMD; \ -+ uint64_t CSR_ERRCTL; \ -+ uint64_t CSR_ERRINFO; \ -+ uint64_t CSR_ERRINFO1; \ -+ uint64_t CSR_ERRENT; \ -+ uint64_t CSR_ERRERA; \ -+ uint64_t CSR_ERRSAVE; \ -+ uint64_t CSR_CTAG; \ -+ uint64_t CSR_DMWIN0; \ -+ uint64_t CSR_DMWIN1; \ -+ uint64_t CSR_DMWIN2; \ -+ uint64_t CSR_DMWIN3; \ -+ uint64_t CSR_PERFCTRL0; \ -+ uint64_t CSR_PERFCNTR0; \ -+ uint64_t CSR_PERFCTRL1; \ -+ uint64_t CSR_PERFCNTR1; \ -+ uint64_t CSR_PERFCTRL2; \ -+ uint64_t CSR_PERFCNTR2; \ -+ uint64_t CSR_PERFCTRL3; \ -+ uint64_t CSR_PERFCNTR3; \ -+ uint64_t CSR_MWPC; \ -+ uint64_t CSR_MWPS; \ -+ uint64_t CSR_DB0ADDR; \ -+ uint64_t CSR_DB0MASK; \ -+ uint64_t CSR_DB0CTL; \ -+ uint64_t CSR_DB0ASID; \ -+ uint64_t CSR_DB1ADDR; \ -+ uint64_t CSR_DB1MASK; \ -+ uint64_t CSR_DB1CTL; \ -+ uint64_t CSR_DB1ASID; \ -+ uint64_t CSR_DB2ADDR; \ -+ uint64_t CSR_DB2MASK; \ -+ uint64_t CSR_DB2CTL; \ -+ uint64_t CSR_DB2ASID; \ -+ uint64_t CSR_DB3ADDR; \ -+ uint64_t CSR_DB3MASK; \ -+ uint64_t CSR_DB3CTL; \ -+ uint64_t CSR_DB3ASID; \ -+ uint64_t CSR_FWPC; \ -+ uint64_t CSR_FWPS; \ -+ uint64_t CSR_IB0ADDR; \ -+ uint64_t CSR_IB0MASK; \ -+ uint64_t CSR_IB0CTL; \ -+ uint64_t CSR_IB0ASID; \ -+ uint64_t CSR_IB1ADDR; \ -+ uint64_t CSR_IB1MASK; \ -+ uint64_t CSR_IB1CTL; \ -+ uint64_t CSR_IB1ASID; \ -+ uint64_t CSR_IB2ADDR; \ -+ uint64_t CSR_IB2MASK; \ -+ uint64_t CSR_IB2CTL; \ -+ uint64_t CSR_IB2ASID; \ -+ uint64_t CSR_IB3ADDR; \ -+ uint64_t CSR_IB3MASK; \ -+ uint64_t CSR_IB3CTL; \ -+ uint64_t CSR_IB3ASID; \ -+ uint64_t CSR_IB4ADDR; \ -+ uint64_t CSR_IB4MASK; \ -+ uint64_t CSR_IB4CTL; \ -+ uint64_t CSR_IB4ASID; \ -+ uint64_t CSR_IB5ADDR; \ -+ uint64_t CSR_IB5MASK; \ -+ uint64_t CSR_IB5CTL; \ -+ uint64_t CSR_IB5ASID; \ -+ uint64_t CSR_IB6ADDR; \ -+ uint64_t CSR_IB6MASK; \ -+ uint64_t CSR_IB6CTL; \ -+ uint64_t CSR_IB6ASID; \ -+ uint64_t CSR_IB7ADDR; \ -+ uint64_t CSR_IB7MASK; \ -+ uint64_t CSR_IB7CTL; \ -+ uint64_t CSR_IB7ASID; \ -+ uint64_t CSR_DEBUG; \ -+ uint64_t CSR_DERA; \ -+ uint64_t CSR_DESAVE; \ -+ -+#define LOONGARCH_CSR_32(_R, _S) \ -+ (KVM_REG_LOONGARCH_CSR | KVM_REG_SIZE_U32 | (8 * (_R) + (_S))) -+ -+#define LOONGARCH_CSR_64(_R, _S) \ -+ (KVM_REG_LOONGARCH_CSR | KVM_REG_SIZE_U64 | (8 * (_R) + (_S))) -+ -+#define KVM_IOC_CSRID(id) LOONGARCH_CSR_64(id, 0) -+ -+#endif -diff --git a/target/loongarch64/cpu-param.h b/target/loongarch64/cpu-param.h -new file mode 100644 -index 0000000000..24ca458af0 ---- /dev/null -+++ b/target/loongarch64/cpu-param.h -@@ -0,0 +1,30 @@ -+#ifndef CPU_PARAM_H -+#define CPU_PARAM_H -+ -+/* If we want to use host float regs... */ -+/* #define USE_HOST_FLOAT_REGS */ -+ -+/* Real pages are variable size... */ -+#define TARGET_PAGE_BITS 14 -+ -+#define LOONGARCH_TLB_MAX 2112 -+ -+#define TARGET_LONG_BITS 64 -+#define TARGET_PHYS_ADDR_SPACE_BITS 48 -+#define TARGET_VIRT_ADDR_SPACE_BITS 48 -+ -+/* -+ * bit definitions for insn_flags (ISAs/ASEs flags) -+ * ------------------------------------------------ -+ */ -+#define ISA_LARCH32 0x00000001ULL -+#define ISA_LARCH64 0x00000002ULL -+#define INSN_LOONGARCH 0x00010000ULL -+ -+#define CPU_LARCH32 (ISA_LARCH32) -+#define CPU_LARCH64 (ISA_LARCH32 | ISA_LARCH64) -+ -+#define NB_MMU_MODES 4 -+ -+#endif /* QEMU_LOONGARCH_DEFS_H */ -+ -diff --git a/target/loongarch64/cpu-qom.h b/target/loongarch64/cpu-qom.h -new file mode 100644 -index 0000000000..ee9c1de571 ---- /dev/null -+++ b/target/loongarch64/cpu-qom.h -@@ -0,0 +1,54 @@ -+/* -+ * QEMU LOONGARCH CPU -+ * -+ * Copyright (c) 2012 SUSE LINUX Products GmbH -+ * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library; if not, see -+ * -+ */ -+#ifndef QEMU_LOONGARCH_CPU_QOM_H -+#define QEMU_LOONGARCH_CPU_QOM_H -+ -+#include "hw/core/cpu.h" -+ -+#define TYPE_LOONGARCH_CPU "loongarch-cpu" -+ -+#define LOONGARCH_CPU_CLASS(klass) \ -+ OBJECT_CLASS_CHECK(LOONGARCHCPUClass, (klass), TYPE_LOONGARCH_CPU) -+#define LOONGARCH_CPU(obj) \ -+ OBJECT_CHECK(LOONGARCHCPU, (obj), TYPE_LOONGARCH_CPU) -+#define LOONGARCH_CPU_GET_CLASS(obj) \ -+ OBJECT_GET_CLASS(LOONGARCHCPUClass, (obj), TYPE_LOONGARCH_CPU) -+ -+/** -+ * LOONGARCHCPUClass: -+ * @parent_realize: The parent class' realize handler. -+ * @parent_reset: The parent class' reset handler. -+ * -+ * A LOONGARCH CPU model. -+ */ -+typedef struct LOONGARCHCPUClass { -+ /*< private >*/ -+ CPUClass parent_class; -+ /*< public >*/ -+ -+ DeviceRealize parent_realize; -+ DeviceUnrealize parent_unrealize; -+ DeviceReset parent_reset; -+ const struct loongarch_def_t *cpu_def; -+} LOONGARCHCPUClass; -+ -+typedef struct LOONGARCHCPU LOONGARCHCPU; -+ -+#endif -diff --git a/target/loongarch64/cpu.c b/target/loongarch64/cpu.c -new file mode 100644 -index 0000000000..a4535d34a6 ---- /dev/null -+++ b/target/loongarch64/cpu.c -@@ -0,0 +1,576 @@ -+/* -+ * QEMU LOONGARCH CPU -+ * -+ * Copyright (c) 2012 SUSE LINUX Products GmbH -+ * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library; if not, see -+ * -+ */ -+ -+#include "qemu/osdep.h" -+#include "qapi/error.h" -+#include "qapi/visitor.h" -+#include "cpu.h" -+#include "internal.h" -+#include "kvm_larch.h" -+#include "qemu-common.h" -+#include "hw/qdev-properties.h" -+#include "sysemu/kvm.h" -+#include "exec/exec-all.h" -+#include "sysemu/arch_init.h" -+#include "cpu-csr.h" -+#include "qemu/qemu-print.h" -+#include "qapi/qapi-commands-machine-target.h" -+#ifdef CONFIG_TCG -+#include "hw/core/tcg-cpu-ops.h" -+#endif /* CONFIG_TCG */ -+ -+#define LOONGARCH_CONFIG1 \ -+((0x8 << CSR_CONF1_KSNUM_SHIFT) | (0x2f << CSR_CONF1_TMRBITS_SHIFT) | \ -+ (0x7 << CSR_CONF1_VSMAX_SHIFT)) -+ -+#define LOONGARCH_CONFIG3 \ -+((0x2 << CSR_CONF3_TLBORG_SHIFT) | (0x3f << CSR_CONF3_MTLBSIZE_SHIFT) | \ -+ (0x7 << CSR_CONF3_STLBWAYS_SHIFT) | (0x8 << CSR_CONF3_STLBIDX_SHIFT)) -+ -+/*****************************************************************************/ -+/* LOONGARCH CPU definitions */ -+const loongarch_def_t loongarch_defs[] = { -+ { -+ .name = "Loongson-3A5000", -+ -+ /* for LoongISA CSR */ -+ .CSR_PRCFG1 = LOONGARCH_CONFIG1, -+ .CSR_PRCFG2 = 0x3ffff000, -+ .CSR_PRCFG3 = LOONGARCH_CONFIG3, -+ .CSR_CRMD = (0 << CSR_CRMD_PLV_SHIFT) | (0 << CSR_CRMD_IE_SHIFT) | -+ (1 << CSR_CRMD_DA_SHIFT) | (0 << CSR_CRMD_PG_SHIFT) | -+ (1 << CSR_CRMD_DACF_SHIFT) | (1 << CSR_CRMD_DACM_SHIFT) , -+ .CSR_ECFG = 0x7 << 16, -+ .CSR_STLBPGSIZE = 0xe, -+ .CSR_RVACFG = 0x0, -+ .CSR_ASID = 0xa0000, -+ .FCSR0 = 0x0, -+ .FCSR0_rw_bitmask = 0x1f1f03df, -+ .PABITS = 48, -+ .insn_flags = CPU_LARCH64 | INSN_LOONGARCH, -+ .mmu_type = MMU_TYPE_LS3A5K, -+ }, -+ { -+ .name = "host", -+ -+ /* for LoongISA CSR */ -+ .CSR_PRCFG1 = LOONGARCH_CONFIG1, -+ .CSR_PRCFG2 = 0x3ffff000, -+ .CSR_PRCFG3 = LOONGARCH_CONFIG3, -+ .CSR_CRMD = (0 << CSR_CRMD_PLV_SHIFT) | (0 << CSR_CRMD_IE_SHIFT) | -+ (1 << CSR_CRMD_DA_SHIFT) | (0 << CSR_CRMD_PG_SHIFT) | -+ (1 << CSR_CRMD_DACF_SHIFT) | (1 << CSR_CRMD_DACM_SHIFT) , -+ .CSR_ECFG = 0x7 << 16, -+ .CSR_STLBPGSIZE = 0xe, -+ .CSR_RVACFG = 0x0, -+ .FCSR0 = 0x0, -+ .FCSR0_rw_bitmask = 0x1f1f03df, -+ .PABITS = 48, -+ .insn_flags = CPU_LARCH64 | INSN_LOONGARCH, -+ .mmu_type = MMU_TYPE_LS3A5K, -+ }, -+}; -+const int loongarch_defs_number = ARRAY_SIZE(loongarch_defs); -+ -+void loongarch_cpu_list(void) -+{ -+ int i; -+ -+ for (i = 0; i < ARRAY_SIZE(loongarch_defs); i++) { -+ qemu_printf("LOONGARCH '%s'\n", -+ loongarch_defs[i].name); -+ } -+} -+ -+CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp) -+{ -+ CpuDefinitionInfoList *cpu_list = NULL; -+ const loongarch_def_t *def; -+ int i; -+ -+ for (i = 0; i < ARRAY_SIZE(loongarch_defs); i++) { -+ CpuDefinitionInfoList *entry; -+ CpuDefinitionInfo *info; -+ -+ def = &loongarch_defs[i]; -+ info = g_malloc0(sizeof(*info)); -+ info->name = g_strdup(def->name); -+ -+ entry = g_malloc0(sizeof(*entry)); -+ entry->value = info; -+ entry->next = cpu_list; -+ cpu_list = entry; -+ } -+ -+ return cpu_list; -+} -+ -+static void loongarch_cpu_set_pc(CPUState *cs, vaddr value) -+{ -+ LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); -+ CPULOONGARCHState *env = &cpu->env; -+ -+ env->active_tc.PC = value & ~(target_ulong)1; -+} -+ -+static bool loongarch_cpu_has_work(CPUState *cs) -+{ -+ LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); -+ CPULOONGARCHState *env = &cpu->env; -+ bool has_work = false; -+ -+ /* It is implementation dependent if non-enabled -+ interrupts wake-up the CPU, however most of the implementations only -+ check for interrupts that can be taken. */ -+ if ((cs->interrupt_request & CPU_INTERRUPT_HARD) && -+ cpu_loongarch_hw_interrupts_pending(env)) { -+ has_work = true; -+ } -+ -+ return has_work; -+} -+ -+const char * const regnames[] = { -+ "r0", "ra", "tp", "sp", "a0", "a1", "a2", "a3", -+ "a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3", -+ "t4", "t5", "t6", "t7", "t8", "x0", "fp", "s0", -+ "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", -+}; -+ -+const char * const fregnames[] = { -+ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", -+ "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", -+ "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", -+ "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", -+}; -+ -+static void fpu_dump_state(CPULOONGARCHState *env, FILE *f, -+ fprintf_function fpu_fprintf, int flags) -+{ -+ int i; -+ int is_fpu64 = 1; -+ -+#define printfpr(fp) \ -+ do { \ -+ if (is_fpu64) \ -+ fpu_fprintf(f, "w:%08x d:%016" PRIx64 \ -+ " fd:%13g fs:%13g psu: %13g\n", \ -+ (fp)->w[FP_ENDIAN_IDX], (fp)->d, \ -+ (double)(fp)->fd, \ -+ (double)(fp)->fs[FP_ENDIAN_IDX], \ -+ (double)(fp)->fs[!FP_ENDIAN_IDX]); \ -+ else { \ -+ fpr_t tmp; \ -+ tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \ -+ tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \ -+ fpu_fprintf(f, "w:%08x d:%016" PRIx64 \ -+ " fd:%13g fs:%13g psu:%13g\n", \ -+ tmp.w[FP_ENDIAN_IDX], tmp.d, \ -+ (double)tmp.fd, \ -+ (double)tmp.fs[FP_ENDIAN_IDX], \ -+ (double)tmp.fs[!FP_ENDIAN_IDX]); \ -+ } \ -+ } while (0) -+ -+ -+ fpu_fprintf(f, "FCSR0 0x%08x SR.FR %d fp_status 0x%02x\n", -+ env->active_fpu.fcsr0, is_fpu64, -+ get_float_exception_flags(&env->active_fpu.fp_status)); -+ for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) { -+ fpu_fprintf(f, "%3s: ", fregnames[i]); -+ printfpr(&env->active_fpu.fpr[i]); -+ } -+ -+#undef printfpr -+} -+ -+void loongarch_cpu_dump_state(CPUState *cs, FILE *f, int flags) -+{ -+ LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); -+ CPULOONGARCHState *env = &cpu->env; -+ int i; -+ -+ qemu_fprintf(f, "pc:\t %lx\n", env->active_tc.PC); -+ for (i = 0; i < 32; i++) { -+ if ((i & 3) == 0) { -+ qemu_fprintf(f, "GPR%02d:", i); -+ } -+ qemu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], -+ env->active_tc.gpr[i]); -+ if ((i & 3) == 3) { -+ qemu_fprintf(f, "\n"); -+ } -+ } -+ qemu_fprintf(f, "EUEN 0x%lx\n", env->CSR_EUEN); -+ qemu_fprintf(f, "ESTAT 0x%lx\n", env->CSR_ESTAT); -+ qemu_fprintf(f, "ERA 0x%lx\n", env->CSR_ERA); -+ qemu_fprintf(f, "CRMD 0x%lx\n", env->CSR_CRMD); -+ qemu_fprintf(f, "PRMD 0x%lx\n", env->CSR_PRMD); -+ qemu_fprintf(f, "BadVAddr 0x%lx\n", env->CSR_BADV); -+ qemu_fprintf(f, "TLB refill ERA 0x%lx\n", env->CSR_TLBRERA); -+ qemu_fprintf(f, "TLB refill BadV 0x%lx\n", env->CSR_TLBRBADV); -+ qemu_fprintf(f, "EEPN 0x%lx\n", env->CSR_EEPN); -+ qemu_fprintf(f, "BadInstr 0x%lx\n", env->CSR_BADI); -+ qemu_fprintf(f, "PRCFG1 0x%lx\nPRCFG2 0x%lx\nPRCFG3 0x%lx\n", -+ env->CSR_PRCFG1, env->CSR_PRCFG3, env->CSR_PRCFG3); -+ if ((flags & CPU_DUMP_FPU) && (env->hflags & LARCH_HFLAG_FPU)) { -+ fpu_dump_state(env, f, qemu_fprintf, flags); -+ } -+} -+ -+void cpu_state_reset(CPULOONGARCHState *env) -+{ -+ LOONGARCHCPU *cpu = loongarch_env_get_cpu(env); -+ CPUState *cs = CPU(cpu); -+ -+ /* Reset registers to their default values */ -+ env->CSR_PRCFG1 = env->cpu_model->CSR_PRCFG1; -+ env->CSR_PRCFG2 = env->cpu_model->CSR_PRCFG2; -+ env->CSR_PRCFG3 = env->cpu_model->CSR_PRCFG3; -+ env->CSR_CRMD = env->cpu_model->CSR_CRMD; -+ env->CSR_ECFG = env->cpu_model->CSR_ECFG; -+ env->CSR_STLBPGSIZE = env->cpu_model->CSR_STLBPGSIZE; -+ env->CSR_RVACFG = env->cpu_model->CSR_RVACFG; -+ env->CSR_ASID = env->cpu_model->CSR_ASID; -+ -+ env->current_tc = 0; -+ env->active_fpu.fcsr0_rw_bitmask = env->cpu_model->FCSR0_rw_bitmask; -+ env->active_fpu.fcsr0 = env->cpu_model->FCSR0; -+ env->insn_flags = env->cpu_model->insn_flags; -+ -+#if !defined(CONFIG_USER_ONLY) -+ env->CSR_ERA = env->active_tc.PC; -+ env->active_tc.PC = env->exception_base; -+#ifdef CONFIG_TCG -+ env->tlb->tlb_in_use = env->tlb->nb_tlb; -+#endif -+ env->CSR_TLBWIRED = 0; -+ env->CSR_TMID = cs->cpu_index; -+ env->CSR_CPUID = (cs->cpu_index & 0x1ff); -+ env->CSR_EEPN |= (uint64_t)0x80000000; -+ env->CSR_TLBRENT |= (uint64_t)0x80000000; -+#endif -+ -+ /* Count register increments in debug mode, EJTAG version 1 */ -+ env->CSR_DEBUG = (1 << CSR_DEBUG_DINT) | (0x1 << CSR_DEBUG_DMVER); -+ -+ compute_hflags(env); -+ restore_fp_status(env); -+ cs->exception_index = EXCP_NONE; -+} -+ -+/* CPUClass::reset() */ -+static void loongarch_cpu_reset(DeviceState *dev) -+{ -+ CPUState *s = CPU(dev); -+ LOONGARCHCPU *cpu = LOONGARCH_CPU(s); -+ LOONGARCHCPUClass *mcc = LOONGARCH_CPU_GET_CLASS(cpu); -+ CPULOONGARCHState *env = &cpu->env; -+ -+ mcc->parent_reset(dev); -+ -+ memset(env, 0, offsetof(CPULOONGARCHState, end_reset_fields)); -+ -+ cpu_state_reset(env); -+ -+#ifndef CONFIG_USER_ONLY -+ if (kvm_enabled()) { -+ kvm_loongarch_reset_vcpu(cpu); -+ } -+#endif -+} -+ -+static void loongarch_cpu_disas_set_info(CPUState *s, disassemble_info *info) -+{ -+ info->print_insn = print_insn_loongarch; -+} -+ -+static void fpu_init(CPULOONGARCHState *env, const loongarch_def_t *def) -+{ -+ memcpy(&env->active_fpu, &env->fpus[0], sizeof(env->active_fpu)); -+} -+ -+void cpu_loongarch_realize_env(CPULOONGARCHState *env) -+{ -+ env->exception_base = 0x1C000000; -+ -+#ifdef CONFIG_TCG -+#ifndef CONFIG_USER_ONLY -+ mmu_init(env, env->cpu_model); -+#endif -+#endif -+ fpu_init(env, env->cpu_model); -+} -+ -+static void loongarch_cpu_realizefn(DeviceState *dev, Error **errp) -+{ -+ CPUState *cs = CPU(dev); -+ LOONGARCHCPU *cpu = LOONGARCH_CPU(dev); -+ LOONGARCHCPUClass *mcc = LOONGARCH_CPU_GET_CLASS(dev); -+ Error *local_err = NULL; -+ -+ cpu_exec_realizefn(cs, &local_err); -+ if (local_err != NULL) { -+ error_propagate(errp, local_err); -+ return; -+ } -+ -+ cpu_loongarch_realize_env(&cpu->env); -+ -+ loongarch_cpu_register_gdb_regs_for_features(cs); -+ -+ cpu_reset(cs); -+ qemu_init_vcpu(cs); -+ -+ mcc->parent_realize(dev, errp); -+ cpu->hotplugged = 1; -+} -+ -+static void loongarch_cpu_unrealizefn(DeviceState *dev) -+{ -+ LOONGARCHCPUClass *mcc = LOONGARCH_CPU_GET_CLASS(dev); -+ -+#ifndef CONFIG_USER_ONLY -+ cpu_remove_sync(CPU(dev)); -+#endif -+ -+ mcc->parent_unrealize(dev); -+} -+static void loongarch_cpu_initfn(Object *obj) -+{ -+ CPUState *cs = CPU(obj); -+ LOONGARCHCPU *cpu = LOONGARCH_CPU(obj); -+ CPULOONGARCHState *env = &cpu->env; -+ LOONGARCHCPUClass *mcc = LOONGARCH_CPU_GET_CLASS(obj); -+ cpu_set_cpustate_pointers(cpu); -+ cs->env_ptr = env; -+ env->cpu_model = mcc->cpu_def; -+ cs->halted = 1; -+ cpu->dtb_compatible = "loongarch,Loongson-3A5000"; -+} -+ -+static char *loongarch_cpu_type_name(const char *cpu_model) -+{ -+ return g_strdup_printf(LOONGARCH_CPU_TYPE_NAME("%s"), cpu_model); -+} -+ -+static ObjectClass *loongarch_cpu_class_by_name(const char *cpu_model) -+{ -+ ObjectClass *oc; -+ char *typename; -+ -+ typename = loongarch_cpu_type_name(cpu_model); -+ oc = object_class_by_name(typename); -+ g_free(typename); -+ return oc; -+} -+ -+static int64_t loongarch_cpu_get_arch_id(CPUState *cs) -+{ -+ LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); -+ -+ return cpu->id; -+} -+ -+static Property loongarch_cpu_properties[] = { -+ DEFINE_PROP_INT32("core-id", LOONGARCHCPU, core_id, -1), -+ DEFINE_PROP_INT32("id", LOONGARCHCPU, id, UNASSIGNED_CPU_ID), -+ DEFINE_PROP_INT32("node-id", LOONGARCHCPU, node_id, CPU_UNSET_NUMA_NODE_ID), -+ -+ DEFINE_PROP_END_OF_LIST() -+}; -+ -+#ifdef CONFIG_TCG -+static void loongarch_cpu_synchronize_from_tb(CPUState *cs,const TranslationBlock *tb) -+{ -+ LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); -+ CPULOONGARCHState *env = &cpu->env; -+ -+ env->active_tc.PC = tb->pc; -+ env->hflags &= ~LARCH_HFLAG_BMASK; -+ env->hflags |= tb->flags & LARCH_HFLAG_BMASK; -+} -+ -+static const struct TCGCPUOps loongarch_tcg_ops = { -+ .initialize = loongarch_tcg_init, -+ .synchronize_from_tb = loongarch_cpu_synchronize_from_tb, -+ -+ .tlb_fill = loongarch_cpu_tlb_fill, -+ .cpu_exec_interrupt = loongarch_cpu_exec_interrupt, -+ .do_interrupt = loongarch_cpu_do_interrupt, -+ -+#ifndef CONFIG_USER_ONLY -+ .do_unaligned_access = loongarch_cpu_do_unaligned_access, -+#endif /* !CONFIG_USER_ONLY */ -+}; -+#endif /* CONFIG_TCG */ -+ -+ -+#if !defined(CONFIG_USER_ONLY) -+static int get_physical_address(CPULOONGARCHState *env, hwaddr *physical, -+ int *prot, target_ulong real_address, -+ int rw, int access_type, int mmu_idx) -+{ -+ int user_mode = mmu_idx == LARCH_HFLAG_UM; -+ int kernel_mode = !user_mode; -+ unsigned plv, base_c, base_v, tmp; -+ -+ /* effective address (modified for KVM T&E kernel segments) */ -+ target_ulong address = real_address; -+ -+ /* Check PG */ -+ if (!(env->CSR_CRMD & CSR_CRMD_PG)) { -+ /* DA mode */ -+ *physical = address & 0xffffffffffffUL; -+ *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; -+ return TLBRET_MATCH; -+ } -+ -+ plv = kernel_mode | (user_mode << 3); -+ base_v = address >> CSR_DMW_BASE_SH; -+ /* Check direct map window 0 */ -+ base_c = env->CSR_DMWIN0 >> CSR_DMW_BASE_SH; -+ if ((plv & env->CSR_DMWIN0) && (base_c == base_v)) { -+ *physical = dmwin_va2pa(address); -+ *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; -+ return TLBRET_MATCH; -+ } -+ /* Check direct map window 1 */ -+ base_c = env->CSR_DMWIN1 >> CSR_DMW_BASE_SH; -+ if ((plv & env->CSR_DMWIN1) && (base_c == base_v)) { -+ *physical = dmwin_va2pa(address); -+ *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; -+ return TLBRET_MATCH; -+ } -+ /* Check valid extension */ -+ tmp = address >> 47; -+ if (!(tmp == 0 || tmp == 0x1ffff)) { -+ return TLBRET_BADADDR; -+ } -+ /* mapped address */ -+ return env->tlb->map_address(env, physical, prot, real_address, rw, -+ access_type); -+} -+ -+hwaddr loongarch_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) -+{ -+ LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); -+ CPULOONGARCHState *env = &cpu->env; -+ hwaddr phys_addr; -+ int prot; -+ -+ if (get_physical_address(env, &phys_addr, &prot, addr, 0, ACCESS_INT, -+ cpu_mmu_index(env, false)) != 0) { -+ return -1; -+ } -+ return phys_addr; -+} -+#endif -+ -+ -+#ifndef CONFIG_USER_ONLY -+#include "hw/core/sysemu-cpu-ops.h" -+ -+static const struct SysemuCPUOps loongarch_sysemu_ops = { -+ .write_elf64_note = loongarch_cpu_write_elf64_note, -+ .get_phys_page_debug = loongarch_cpu_get_phys_page_debug, -+ .legacy_vmsd = &vmstate_loongarch_cpu, -+}; -+#endif -+ -+ -+static void loongarch_cpu_class_init(ObjectClass *c, void *data) -+{ -+ LOONGARCHCPUClass *mcc = LOONGARCH_CPU_CLASS(c); -+ CPUClass *cc = CPU_CLASS(c); -+ DeviceClass *dc = DEVICE_CLASS(c); -+ -+ device_class_set_props(dc, loongarch_cpu_properties); -+ device_class_set_parent_realize(dc, loongarch_cpu_realizefn, -+ &mcc->parent_realize); -+ -+ device_class_set_parent_unrealize(dc, loongarch_cpu_unrealizefn, -+ &mcc->parent_unrealize); -+ -+ device_class_set_parent_reset(dc, loongarch_cpu_reset, &mcc->parent_reset); -+ cc->get_arch_id = loongarch_cpu_get_arch_id; -+ -+ cc->class_by_name = loongarch_cpu_class_by_name; -+ cc->has_work = loongarch_cpu_has_work; -+ cc->dump_state = loongarch_cpu_dump_state; -+ cc->set_pc = loongarch_cpu_set_pc; -+ cc->gdb_read_register = loongarch_cpu_gdb_read_register; -+ cc->gdb_write_register = loongarch_cpu_gdb_write_register; -+ cc->disas_set_info = loongarch_cpu_disas_set_info; -+#ifndef CONFIG_USER_ONLY -+ cc->sysemu_ops = &loongarch_sysemu_ops; -+#endif /* !CONFIG_USER_ONLY */ -+ -+ cc->gdb_num_core_regs = 33; -+ cc->gdb_core_xml_file = "loongarch-base64.xml"; -+ cc->gdb_stop_before_watchpoint = true; -+ -+ dc->user_creatable = true; -+#ifdef CONFIG_TCG -+ cc->tcg_ops = &loongarch_tcg_ops; -+#endif /* CONFIG_TCG */ -+} -+ -+static const TypeInfo loongarch_cpu_type_info = { -+ .name = TYPE_LOONGARCH_CPU, -+ .parent = TYPE_CPU, -+ .instance_size = sizeof(LOONGARCHCPU), -+ .instance_init = loongarch_cpu_initfn, -+ .abstract = true, -+ .class_size = sizeof(LOONGARCHCPUClass), -+ .class_init = loongarch_cpu_class_init, -+}; -+ -+static void loongarch_cpu_cpudef_class_init(ObjectClass *oc, void *data) -+{ -+ LOONGARCHCPUClass *mcc = LOONGARCH_CPU_CLASS(oc); -+ mcc->cpu_def = data; -+} -+ -+static void loongarch_register_cpudef_type(const struct loongarch_def_t *def) -+{ -+ char *typename = loongarch_cpu_type_name(def->name); -+ TypeInfo ti = { -+ .name = typename, -+ .parent = TYPE_LOONGARCH_CPU, -+ .class_init = loongarch_cpu_cpudef_class_init, -+ .class_data = (void *)def, -+ }; -+ -+ type_register(&ti); -+ g_free(typename); -+} -+ -+static void loongarch_cpu_register_types(void) -+{ -+ int i; -+ -+ type_register_static(&loongarch_cpu_type_info); -+ for (i = 0; i < loongarch_defs_number; i++) { -+ loongarch_register_cpudef_type(&loongarch_defs[i]); -+ } -+} -+ -+type_init(loongarch_cpu_register_types) -diff --git a/target/loongarch64/cpu.h b/target/loongarch64/cpu.h -new file mode 100644 -index 0000000000..10facb3b73 ---- /dev/null -+++ b/target/loongarch64/cpu.h -@@ -0,0 +1,326 @@ -+#ifndef LOONGARCH_CPU_H -+#define LOONGARCH_CPU_H -+ -+ -+#define CPUArchState struct CPULOONGARCHState -+ -+#include "qemu-common.h" -+#include "cpu-qom.h" -+#include "larch-defs.h" -+#include "exec/cpu-defs.h" -+#include "fpu/softfloat.h" -+#include "sysemu/sysemu.h" -+#include "cpu-csr.h" -+ -+#define TCG_GUEST_DEFAULT_MO (0) -+ -+struct CPULOONGARCHState; -+typedef LOONGARCHCPU ArchCPU; -+typedef struct CPULOONGARCHTLBContext CPULOONGARCHTLBContext; -+ -+#define LASX_REG_WIDTH (256) -+typedef union lasx_reg_t lasx_reg_t; -+union lasx_reg_t { -+ int64_t val64[LASX_REG_WIDTH / 64]; -+}; -+ -+typedef union fpr_t fpr_t; -+union fpr_t { -+ float64 fd; /* ieee double precision */ -+ float32 fs[2];/* ieee single precision */ -+ uint64_t d; /* binary double fixed-point */ -+ uint32_t w[2]; /* binary single fixed-point */ -+/* FPU/LASX register mapping is not tested on big-endian hosts. */ -+ lasx_reg_t lasx; /* vector data */ -+}; -+/* define FP_ENDIAN_IDX to access the same location -+ * in the fpr_t union regardless of the host endianness -+ */ -+#if defined(HOST_WORDS_BIGENDIAN) -+# define FP_ENDIAN_IDX 1 -+#else -+# define FP_ENDIAN_IDX 0 -+#endif -+ -+typedef struct CPULOONGARCHFPUContext { -+ /* Floating point registers */ -+ fpr_t fpr[32]; -+ float_status fp_status; -+ -+ bool cf[8]; -+ /* fcsr0 -+ * 31:29 |28:24 |23:21 |20:16 |15:10 |9:8 |7 |6 |5 |4:0 -+ * Cause Flags RM DAE TM Enables -+ */ -+ uint32_t fcsr0; -+ uint32_t fcsr0_rw_bitmask; -+ uint32_t vcsr16; -+} CPULOONGARCHFPUContext; -+ -+/* fp control and status register definition */ -+#define FCSR0_M1 0xdf /* DAE, TM and Enables */ -+#define FCSR0_M2 0x1f1f0000 /* Cause and Flags */ -+#define FCSR0_M3 0x300 /* Round Mode */ -+#define FCSR0_RM 8 /* Round Mode bit num on fcsr0 */ -+#define GET_FP_CAUSE(reg) (((reg) >> 24) & 0x1f) -+#define GET_FP_ENABLE(reg) (((reg) >> 0) & 0x1f) -+#define GET_FP_FLAGS(reg) (((reg) >> 16) & 0x1f) -+#define SET_FP_CAUSE(reg, v) do { (reg) = ((reg) & ~(0x1f << 24)) | \ -+ ((v & 0x1f) << 24); \ -+ } while (0) -+#define SET_FP_ENABLE(reg, v) do { (reg) = ((reg) & ~(0x1f << 0)) | \ -+ ((v & 0x1f) << 0); \ -+ } while (0) -+#define SET_FP_FLAGS(reg, v) do { (reg) = ((reg) & ~(0x1f << 16)) | \ -+ ((v & 0x1f) << 16); \ -+ } while (0) -+#define UPDATE_FP_FLAGS(reg, v) do { (reg) |= ((v & 0x1f) << 16); } while (0) -+#define FP_INEXACT 1 -+#define FP_UNDERFLOW 2 -+#define FP_OVERFLOW 4 -+#define FP_DIV0 8 -+#define FP_INVALID 16 -+ -+#define TARGET_INSN_START_EXTRA_WORDS 2 -+ -+typedef struct loongarch_def_t loongarch_def_t; -+ -+#define LOONGARCH_FPU_MAX 1 -+#define LOONGARCH_KSCRATCH_NUM 8 -+ -+typedef struct TCState TCState; -+struct TCState { -+ target_ulong gpr[32]; -+ target_ulong PC; -+}; -+ -+#define N_IRQS 14 -+#define IRQ_TIMER 11 -+#define IRQ_IPI 12 -+#define IRQ_UART 2 -+ -+typedef struct CPULOONGARCHState CPULOONGARCHState; -+struct CPULOONGARCHState { -+ TCState active_tc; -+ CPULOONGARCHFPUContext active_fpu; -+ -+ uint32_t current_tc; -+ uint64_t scr[4]; -+ uint32_t PABITS; -+ -+ /* LoongISA CSR register */ -+ CPU_LOONGARCH_CSR -+ uint64_t lladdr; -+ target_ulong llval; -+ uint64_t llval_wp; -+ uint32_t llnewval_wp; -+ -+ CPULOONGARCHFPUContext fpus[LOONGARCH_FPU_MAX]; -+ /* QEMU */ -+ int error_code; -+#define EXCP_TLB_NOMATCH 0x1 -+#define EXCP_INST_NOTAVAIL 0x2 /* No valid instruction word for BadInstr */ -+ uint32_t hflags; /* CPU State */ -+ /* TMASK defines different execution modes */ -+#define LARCH_HFLAG_TMASK 0x5F5807FF -+ /* -+ * The KSU flags must be the lowest bits in hflags. The flag order -+ * must be the same as defined for CP0 Status. This allows to use -+ * the bits as the value of mmu_idx. -+ */ -+#define LARCH_HFLAG_KSU 0x00003 /* kernel/user mode mask */ -+#define LARCH_HFLAG_UM 0x00003 /* user mode flag */ -+#define LARCH_HFLAG_KM 0x00000 /* kernel mode flag */ -+#define LARCH_HFLAG_64 0x00008 /* 64-bit instructions enabled */ -+#define LARCH_HFLAG_FPU 0x00020 /* FPU enabled */ -+#define LARCH_HFLAG_AWRAP 0x00200 /* 32-bit compatibility address wrapping */ -+ /* If translation is interrupted between the branch instruction and -+ * the delay slot, record what type of branch it is so that we can -+ * resume translation properly. It might be possible to reduce -+ * this from three bits to two. */ -+#define LARCH_HFLAG_BMASK 0x03800 -+#define LARCH_HFLAG_B 0x00800 /* Unconditional branch */ -+#define LARCH_HFLAG_BC 0x01000 /* Conditional branch */ -+#define LARCH_HFLAG_BR 0x02000 /* branch to register (can't link TB) */ -+#define LARCH_HFLAG_LSX 0x1000000 -+#define LARCH_HFLAG_LASX 0x2000000 -+#define LARCH_HFLAG_LBT 0x40000000 -+ target_ulong btarget; /* Jump / branch target */ -+ target_ulong bcond; /* Branch condition (if needed) */ -+ -+ uint64_t insn_flags; /* Supported instruction set */ -+ int cpu_cfg[64]; -+ -+ /* Fields up to this point are cleared by a CPU reset */ -+ struct {} end_reset_fields; -+ -+ /* Fields from here on are preserved across CPU reset. */ -+#if !defined(CONFIG_USER_ONLY) -+ CPULOONGARCHTLBContext *tlb; -+#endif -+ -+ const loongarch_def_t *cpu_model; -+ void *irq[N_IRQS]; -+ QEMUTimer *timer; /* Internal timer */ -+ MemoryRegion *itc_tag; /* ITC Configuration Tags */ -+ target_ulong exception_base; /* ExceptionBase input to the core */ -+ struct { -+ uint64_t guest_addr; -+ } st; -+}; -+ -+ -+/* CPU can't have 0xFFFFFFFF APIC ID, use that value to distinguish -+ * that ID hasn't been set yet -+ */ -+#define UNASSIGNED_CPU_ID 0xFFFFFFFF -+ -+/** -+ * LOONGARCHCPU: -+ * @env: #CPULOONGARCHState -+ * -+ * A LOONGARCH CPU. -+ */ -+struct LOONGARCHCPU { -+ /*< private >*/ -+ CPUState parent_obj; -+ /*< public >*/ -+ CPUNegativeOffsetState neg; -+ CPULOONGARCHState env; -+ int32_t id; -+ int hotplugged; -+ uint8_t online_vcpus; -+ uint8_t is_migrate; -+ uint64_t counter_value; -+ uint32_t cpu_freq; -+ uint32_t count_ctl; -+ uint64_t pending_exceptions; -+ uint64_t pending_exceptions_clr; -+ uint64_t core_ext_ioisr[4]; -+ VMChangeStateEntry *cpuStateEntry; -+ int32_t node_id; /* NUMA node this CPU belongs to */ -+ int32_t core_id; -+ struct kvm_msrs *kvm_msr_buf; -+ /* 'compatible' string for this CPU for Linux device trees */ -+ const char *dtb_compatible; -+}; -+ -+static inline LOONGARCHCPU *loongarch_env_get_cpu(CPULOONGARCHState *env) -+{ -+ return container_of(env, LOONGARCHCPU, env); -+} -+ -+#define ENV_GET_CPU(e) CPU(loongarch_env_get_cpu(e)) -+ -+#define ENV_OFFSET offsetof(LOONGARCHCPU, env) -+ -+void loongarch_cpu_list(void); -+ -+#define cpu_signal_handler cpu_loongarch_signal_handler -+#define cpu_list loongarch_cpu_list -+ -+/* MMU modes definitions. We carefully match the indices with our -+ hflags layout. */ -+#define MMU_MODE0_SUFFIX _kernel -+#define MMU_MODE1_SUFFIX _super -+#define MMU_MODE2_SUFFIX _user -+#define MMU_MODE3_SUFFIX _error -+#define MMU_USER_IDX 3 -+ -+static inline int hflags_mmu_index(uint32_t hflags) -+{ -+ return hflags & LARCH_HFLAG_KSU; -+} -+ -+static inline int cpu_mmu_index(CPULOONGARCHState *env, bool ifetch) -+{ -+ return hflags_mmu_index(env->hflags); -+} -+ -+#include "exec/cpu-all.h" -+ -+/* Memory access type : -+ * may be needed for precise access rights control and precise exceptions. -+ */ -+enum { -+ /* 1 bit to define user level / supervisor access */ -+ ACCESS_USER = 0x00, -+ ACCESS_SUPER = 0x01, -+ /* 1 bit to indicate direction */ -+ ACCESS_STORE = 0x02, -+ /* Type of instruction that generated the access */ -+ ACCESS_CODE = 0x10, /* Code fetch access */ -+ ACCESS_INT = 0x20, /* Integer load/store access */ -+ ACCESS_FLOAT = 0x30, /* floating point load/store access */ -+}; -+ -+/* Exceptions */ -+enum { -+ EXCP_NONE = -1, -+ EXCP_RESET = 0, -+ EXCP_SRESET, -+ EXCP_DINT, -+ EXCP_NMI, -+ EXCP_EXT_INTERRUPT, /* 7 */ -+ EXCP_AdEL, -+ EXCP_AdES, -+ EXCP_TLBF, -+ EXCP_IBE, -+ EXCP_SYSCALL, -+ EXCP_BREAK, -+ EXCP_FPDIS, -+ EXCP_LSXDIS, -+ EXCP_LASXDIS, -+ EXCP_RI, -+ EXCP_OVERFLOW, -+ EXCP_TRAP, -+ EXCP_FPE, -+ EXCP_LTLBL, -+ EXCP_TLBL, -+ EXCP_TLBS, -+ EXCP_DBE, -+ EXCP_TLBXI, -+ EXCP_TLBRI, -+ EXCP_TLBPE, -+ EXCP_BTDIS, -+ -+ EXCP_LAST = EXCP_BTDIS, -+}; -+ -+/* -+ * This is an internally generated WAKE request line. -+ * It is driven by the CPU itself. Raised when the MT -+ * block wants to wake a VPE from an inactive state and -+ * cleared when VPE goes from active to inactive. -+ */ -+#define CPU_INTERRUPT_WAKE CPU_INTERRUPT_TGT_INT_0 -+ -+int cpu_loongarch_signal_handler(int host_signum, void *pinfo, void *puc); -+ -+#define LOONGARCH_CPU_TYPE_SUFFIX "-" TYPE_LOONGARCH_CPU -+#define LOONGARCH_CPU_TYPE_NAME(model) model LOONGARCH_CPU_TYPE_SUFFIX -+#define CPU_RESOLVING_TYPE TYPE_LOONGARCH_CPU -+ -+/* helper.c */ -+target_ulong exception_resume_pc(CPULOONGARCHState *env); -+ -+/* gdbstub.c */ -+void loongarch_cpu_register_gdb_regs_for_features(CPUState *cs); -+void mmu_init(CPULOONGARCHState *env, const loongarch_def_t *def); -+ -+static inline void cpu_get_tb_cpu_state(CPULOONGARCHState *env, target_ulong *pc, -+ target_ulong *cs_base, uint32_t *flags) -+{ -+ *pc = env->active_tc.PC; -+ *cs_base = 0; -+ *flags = env->hflags & (LARCH_HFLAG_TMASK | LARCH_HFLAG_BMASK); -+} -+ -+static inline bool cpu_refill_state(CPULOONGARCHState *env) -+{ -+ return env->CSR_TLBRERA & 0x1; -+} -+ -+extern const char * const regnames[]; -+extern const char * const fregnames[]; -+#endif /* LOONGARCH_CPU_H */ -diff --git a/target/loongarch64/csr_helper.c b/target/loongarch64/csr_helper.c -new file mode 100644 -index 0000000000..182e59e925 ---- /dev/null -+++ b/target/loongarch64/csr_helper.c -@@ -0,0 +1,704 @@ -+/* -+ * loongarch tlb emulation helpers for qemu. -+ * -+ * Copyright (c) 2020 - 2021 -+ * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2 of the License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library; if not, see . -+ */ -+ -+#include "qemu/osdep.h" -+#include "qemu/main-loop.h" -+#include "cpu.h" -+#include "internal.h" -+#include "qemu/host-utils.h" -+#include "exec/helper-proto.h" -+#include "exec/exec-all.h" -+#include "exec/cpu_ldst.h" -+#include "sysemu/kvm.h" -+#include "hw/irq.h" -+#include "cpu-csr.h" -+#include "instmap.h" -+ -+#ifndef CONFIG_USER_ONLY -+target_ulong helper_csr_rdq(CPULOONGARCHState *env, uint64_t csr) -+{ -+ int64_t v; -+ -+#define CASE_CSR_RDQ(csr) \ -+ case LOONGARCH_CSR_ ## csr: \ -+ { \ -+ v = env->CSR_ ## csr; \ -+ break; \ -+ }; \ -+ -+ switch (csr) { -+ CASE_CSR_RDQ(CRMD) -+ CASE_CSR_RDQ(PRMD) -+ CASE_CSR_RDQ(EUEN) -+ CASE_CSR_RDQ(MISC) -+ CASE_CSR_RDQ(ECFG) -+ CASE_CSR_RDQ(ESTAT) -+ CASE_CSR_RDQ(ERA) -+ CASE_CSR_RDQ(BADV) -+ CASE_CSR_RDQ(BADI) -+ CASE_CSR_RDQ(EEPN) -+ CASE_CSR_RDQ(TLBIDX) -+ CASE_CSR_RDQ(TLBEHI) -+ CASE_CSR_RDQ(TLBELO0) -+ CASE_CSR_RDQ(TLBELO1) -+ CASE_CSR_RDQ(TLBWIRED) -+ CASE_CSR_RDQ(GTLBC) -+ CASE_CSR_RDQ(TRGP) -+ CASE_CSR_RDQ(ASID) -+ CASE_CSR_RDQ(PGDL) -+ CASE_CSR_RDQ(PGDH) -+ CASE_CSR_RDQ(PGD) -+ CASE_CSR_RDQ(PWCTL0) -+ CASE_CSR_RDQ(PWCTL1) -+ CASE_CSR_RDQ(STLBPGSIZE) -+ CASE_CSR_RDQ(RVACFG) -+ CASE_CSR_RDQ(CPUID) -+ CASE_CSR_RDQ(PRCFG1) -+ CASE_CSR_RDQ(PRCFG2) -+ CASE_CSR_RDQ(PRCFG3) -+ CASE_CSR_RDQ(KS0) -+ CASE_CSR_RDQ(KS1) -+ CASE_CSR_RDQ(KS2) -+ CASE_CSR_RDQ(KS3) -+ CASE_CSR_RDQ(KS4) -+ CASE_CSR_RDQ(KS5) -+ CASE_CSR_RDQ(KS6) -+ CASE_CSR_RDQ(KS7) -+ CASE_CSR_RDQ(KS8) -+ CASE_CSR_RDQ(TMID) -+ CASE_CSR_RDQ(TCFG) -+ case LOONGARCH_CSR_TVAL: -+ v = cpu_loongarch_get_stable_timer_ticks(env); -+ break; -+ CASE_CSR_RDQ(CNTC) -+ CASE_CSR_RDQ(TINTCLR) -+ CASE_CSR_RDQ(GSTAT) -+ CASE_CSR_RDQ(GCFG) -+ CASE_CSR_RDQ(GINTC) -+ CASE_CSR_RDQ(GCNTC) -+ CASE_CSR_RDQ(LLBCTL) -+ CASE_CSR_RDQ(IMPCTL1) -+ CASE_CSR_RDQ(IMPCTL2) -+ CASE_CSR_RDQ(GNMI) -+ CASE_CSR_RDQ(TLBRENT) -+ CASE_CSR_RDQ(TLBRBADV) -+ CASE_CSR_RDQ(TLBRERA) -+ CASE_CSR_RDQ(TLBRSAVE) -+ CASE_CSR_RDQ(TLBRELO0) -+ CASE_CSR_RDQ(TLBRELO1) -+ CASE_CSR_RDQ(TLBREHI) -+ CASE_CSR_RDQ(TLBRPRMD) -+ CASE_CSR_RDQ(ERRCTL) -+ CASE_CSR_RDQ(ERRINFO) -+ CASE_CSR_RDQ(ERRINFO1) -+ CASE_CSR_RDQ(ERRENT) -+ CASE_CSR_RDQ(ERRERA) -+ CASE_CSR_RDQ(ERRSAVE) -+ CASE_CSR_RDQ(CTAG) -+ CASE_CSR_RDQ(DMWIN0) -+ CASE_CSR_RDQ(DMWIN1) -+ CASE_CSR_RDQ(DMWIN2) -+ CASE_CSR_RDQ(DMWIN3) -+ CASE_CSR_RDQ(PERFCTRL0) -+ CASE_CSR_RDQ(PERFCNTR0) -+ CASE_CSR_RDQ(PERFCTRL1) -+ CASE_CSR_RDQ(PERFCNTR1) -+ CASE_CSR_RDQ(PERFCTRL2) -+ CASE_CSR_RDQ(PERFCNTR2) -+ CASE_CSR_RDQ(PERFCTRL3) -+ CASE_CSR_RDQ(PERFCNTR3) -+ /* debug */ -+ CASE_CSR_RDQ(MWPC) -+ CASE_CSR_RDQ(MWPS) -+ CASE_CSR_RDQ(DB0ADDR) -+ CASE_CSR_RDQ(DB0MASK) -+ CASE_CSR_RDQ(DB0CTL) -+ CASE_CSR_RDQ(DB0ASID) -+ CASE_CSR_RDQ(DB1ADDR) -+ CASE_CSR_RDQ(DB1MASK) -+ CASE_CSR_RDQ(DB1CTL) -+ CASE_CSR_RDQ(DB1ASID) -+ CASE_CSR_RDQ(DB2ADDR) -+ CASE_CSR_RDQ(DB2MASK) -+ CASE_CSR_RDQ(DB2CTL) -+ CASE_CSR_RDQ(DB2ASID) -+ CASE_CSR_RDQ(DB3ADDR) -+ CASE_CSR_RDQ(DB3MASK) -+ CASE_CSR_RDQ(DB3CTL) -+ CASE_CSR_RDQ(DB3ASID) -+ CASE_CSR_RDQ(FWPC) -+ CASE_CSR_RDQ(FWPS) -+ CASE_CSR_RDQ(IB0ADDR) -+ CASE_CSR_RDQ(IB0MASK) -+ CASE_CSR_RDQ(IB0CTL) -+ CASE_CSR_RDQ(IB0ASID) -+ CASE_CSR_RDQ(IB1ADDR) -+ CASE_CSR_RDQ(IB1MASK) -+ CASE_CSR_RDQ(IB1CTL) -+ CASE_CSR_RDQ(IB1ASID) -+ CASE_CSR_RDQ(IB2ADDR) -+ CASE_CSR_RDQ(IB2MASK) -+ CASE_CSR_RDQ(IB2CTL) -+ CASE_CSR_RDQ(IB2ASID) -+ CASE_CSR_RDQ(IB3ADDR) -+ CASE_CSR_RDQ(IB3MASK) -+ CASE_CSR_RDQ(IB3CTL) -+ CASE_CSR_RDQ(IB3ASID) -+ CASE_CSR_RDQ(IB4ADDR) -+ CASE_CSR_RDQ(IB4MASK) -+ CASE_CSR_RDQ(IB4CTL) -+ CASE_CSR_RDQ(IB4ASID) -+ CASE_CSR_RDQ(IB5ADDR) -+ CASE_CSR_RDQ(IB5MASK) -+ CASE_CSR_RDQ(IB5CTL) -+ CASE_CSR_RDQ(IB5ASID) -+ CASE_CSR_RDQ(IB6ADDR) -+ CASE_CSR_RDQ(IB6MASK) -+ CASE_CSR_RDQ(IB6CTL) -+ CASE_CSR_RDQ(IB6ASID) -+ CASE_CSR_RDQ(IB7ADDR) -+ CASE_CSR_RDQ(IB7MASK) -+ CASE_CSR_RDQ(IB7CTL) -+ CASE_CSR_RDQ(IB7ASID) -+ CASE_CSR_RDQ(DEBUG) -+ CASE_CSR_RDQ(DERA) -+ CASE_CSR_RDQ(DESAVE) -+ default : -+ assert(0); -+ } -+ -+#undef CASE_CSR_RDQ -+ compute_hflags(env); -+ return v; -+} -+ -+target_ulong helper_csr_wrq(CPULOONGARCHState *env, target_ulong val, -+ uint64_t csr) -+{ -+ int64_t old_v, v; -+ old_v = -1; -+ v = val; -+ -+#define CASE_CSR_WRQ(csr) \ -+ case LOONGARCH_CSR_ ## csr: \ -+ { \ -+ old_v = env->CSR_ ## csr; \ -+ env->CSR_ ## csr = v; \ -+ break; \ -+ }; \ -+ -+ switch (csr) { -+ CASE_CSR_WRQ(CRMD) -+ CASE_CSR_WRQ(PRMD) -+ CASE_CSR_WRQ(EUEN) -+ CASE_CSR_WRQ(MISC) -+ CASE_CSR_WRQ(ECFG) -+ CASE_CSR_WRQ(ESTAT) -+ CASE_CSR_WRQ(ERA) -+ CASE_CSR_WRQ(BADV) -+ CASE_CSR_WRQ(BADI) -+ CASE_CSR_WRQ(EEPN) -+ CASE_CSR_WRQ(TLBIDX) -+ CASE_CSR_WRQ(TLBEHI) -+ CASE_CSR_WRQ(TLBELO0) -+ CASE_CSR_WRQ(TLBELO1) -+ CASE_CSR_WRQ(TLBWIRED) -+ CASE_CSR_WRQ(GTLBC) -+ CASE_CSR_WRQ(TRGP) -+ CASE_CSR_WRQ(ASID) -+ CASE_CSR_WRQ(PGDL) -+ CASE_CSR_WRQ(PGDH) -+ CASE_CSR_WRQ(PGD) -+ CASE_CSR_WRQ(PWCTL0) -+ CASE_CSR_WRQ(PWCTL1) -+ CASE_CSR_WRQ(STLBPGSIZE) -+ CASE_CSR_WRQ(RVACFG) -+ CASE_CSR_WRQ(CPUID) -+ CASE_CSR_WRQ(PRCFG1) -+ CASE_CSR_WRQ(PRCFG2) -+ CASE_CSR_WRQ(PRCFG3) -+ CASE_CSR_WRQ(KS0) -+ CASE_CSR_WRQ(KS1) -+ CASE_CSR_WRQ(KS2) -+ CASE_CSR_WRQ(KS3) -+ CASE_CSR_WRQ(KS4) -+ CASE_CSR_WRQ(KS5) -+ CASE_CSR_WRQ(KS6) -+ CASE_CSR_WRQ(KS7) -+ CASE_CSR_WRQ(KS8) -+ CASE_CSR_WRQ(TMID) -+ case LOONGARCH_CSR_TCFG: -+ old_v = env->CSR_TCFG; -+ cpu_loongarch_store_stable_timer_config(env, v); -+ break; -+ CASE_CSR_WRQ(TVAL) -+ CASE_CSR_WRQ(CNTC) -+ case LOONGARCH_CSR_TINTCLR: -+ old_v = 0; -+ qemu_irq_lower(env->irq[IRQ_TIMER]); -+ break; -+ CASE_CSR_WRQ(GSTAT) -+ CASE_CSR_WRQ(GCFG) -+ CASE_CSR_WRQ(GINTC) -+ CASE_CSR_WRQ(GCNTC) -+ CASE_CSR_WRQ(LLBCTL) -+ CASE_CSR_WRQ(IMPCTL1) -+ case LOONGARCH_CSR_IMPCTL2: -+ if (v & CSR_IMPCTL2_MTLB) { -+ ls3a5k_flush_vtlb(env); -+ } -+ if (v & CSR_IMPCTL2_STLB) { -+ ls3a5k_flush_ftlb(env); -+ } -+ break; -+ CASE_CSR_WRQ(GNMI) -+ CASE_CSR_WRQ(TLBRENT) -+ CASE_CSR_WRQ(TLBRBADV) -+ CASE_CSR_WRQ(TLBRERA) -+ CASE_CSR_WRQ(TLBRSAVE) -+ CASE_CSR_WRQ(TLBRELO0) -+ CASE_CSR_WRQ(TLBRELO1) -+ CASE_CSR_WRQ(TLBREHI) -+ CASE_CSR_WRQ(TLBRPRMD) -+ CASE_CSR_WRQ(ERRCTL) -+ CASE_CSR_WRQ(ERRINFO) -+ CASE_CSR_WRQ(ERRINFO1) -+ CASE_CSR_WRQ(ERRENT) -+ CASE_CSR_WRQ(ERRERA) -+ CASE_CSR_WRQ(ERRSAVE) -+ CASE_CSR_WRQ(CTAG) -+ CASE_CSR_WRQ(DMWIN0) -+ CASE_CSR_WRQ(DMWIN1) -+ CASE_CSR_WRQ(DMWIN2) -+ CASE_CSR_WRQ(DMWIN3) -+ CASE_CSR_WRQ(PERFCTRL0) -+ CASE_CSR_WRQ(PERFCNTR0) -+ CASE_CSR_WRQ(PERFCTRL1) -+ CASE_CSR_WRQ(PERFCNTR1) -+ CASE_CSR_WRQ(PERFCTRL2) -+ CASE_CSR_WRQ(PERFCNTR2) -+ CASE_CSR_WRQ(PERFCTRL3) -+ CASE_CSR_WRQ(PERFCNTR3) -+ /* debug */ -+ CASE_CSR_WRQ(MWPC) -+ CASE_CSR_WRQ(MWPS) -+ CASE_CSR_WRQ(DB0ADDR) -+ CASE_CSR_WRQ(DB0MASK) -+ CASE_CSR_WRQ(DB0CTL) -+ CASE_CSR_WRQ(DB0ASID) -+ CASE_CSR_WRQ(DB1ADDR) -+ CASE_CSR_WRQ(DB1MASK) -+ CASE_CSR_WRQ(DB1CTL) -+ CASE_CSR_WRQ(DB1ASID) -+ CASE_CSR_WRQ(DB2ADDR) -+ CASE_CSR_WRQ(DB2MASK) -+ CASE_CSR_WRQ(DB2CTL) -+ CASE_CSR_WRQ(DB2ASID) -+ CASE_CSR_WRQ(DB3ADDR) -+ CASE_CSR_WRQ(DB3MASK) -+ CASE_CSR_WRQ(DB3CTL) -+ CASE_CSR_WRQ(DB3ASID) -+ CASE_CSR_WRQ(FWPC) -+ CASE_CSR_WRQ(FWPS) -+ CASE_CSR_WRQ(IB0ADDR) -+ CASE_CSR_WRQ(IB0MASK) -+ CASE_CSR_WRQ(IB0CTL) -+ CASE_CSR_WRQ(IB0ASID) -+ CASE_CSR_WRQ(IB1ADDR) -+ CASE_CSR_WRQ(IB1MASK) -+ CASE_CSR_WRQ(IB1CTL) -+ CASE_CSR_WRQ(IB1ASID) -+ CASE_CSR_WRQ(IB2ADDR) -+ CASE_CSR_WRQ(IB2MASK) -+ CASE_CSR_WRQ(IB2CTL) -+ CASE_CSR_WRQ(IB2ASID) -+ CASE_CSR_WRQ(IB3ADDR) -+ CASE_CSR_WRQ(IB3MASK) -+ CASE_CSR_WRQ(IB3CTL) -+ CASE_CSR_WRQ(IB3ASID) -+ CASE_CSR_WRQ(IB4ADDR) -+ CASE_CSR_WRQ(IB4MASK) -+ CASE_CSR_WRQ(IB4CTL) -+ CASE_CSR_WRQ(IB4ASID) -+ CASE_CSR_WRQ(IB5ADDR) -+ CASE_CSR_WRQ(IB5MASK) -+ CASE_CSR_WRQ(IB5CTL) -+ CASE_CSR_WRQ(IB5ASID) -+ CASE_CSR_WRQ(IB6ADDR) -+ CASE_CSR_WRQ(IB6MASK) -+ CASE_CSR_WRQ(IB6CTL) -+ CASE_CSR_WRQ(IB6ASID) -+ CASE_CSR_WRQ(IB7ADDR) -+ CASE_CSR_WRQ(IB7MASK) -+ CASE_CSR_WRQ(IB7CTL) -+ CASE_CSR_WRQ(IB7ASID) -+ CASE_CSR_WRQ(DEBUG) -+ CASE_CSR_WRQ(DERA) -+ CASE_CSR_WRQ(DESAVE) -+ default : -+ assert(0); -+ } -+ -+ if (csr == LOONGARCH_CSR_ASID) { -+ if (old_v != v) { -+ tlb_flush(CPU(loongarch_env_get_cpu(env))); -+ } -+ } -+ -+#undef CASE_CSR_WRQ -+ compute_hflags(env); -+ return old_v; -+} -+ -+target_ulong helper_csr_xchgq(CPULOONGARCHState *env, target_ulong val, -+ target_ulong mask, uint64_t csr) -+{ -+ target_ulong v, tmp; -+ v = val & mask; -+ -+#define CASE_CSR_XCHGQ(csr) \ -+ case LOONGARCH_CSR_ ## csr: \ -+ { \ -+ val = env->CSR_ ## csr; \ -+ env->CSR_ ## csr = (env->CSR_ ## csr) & (~mask); \ -+ env->CSR_ ## csr = (env->CSR_ ## csr) | v; \ -+ break; \ -+ }; \ -+ -+ switch (csr) { -+ CASE_CSR_XCHGQ(CRMD) -+ CASE_CSR_XCHGQ(PRMD) -+ CASE_CSR_XCHGQ(EUEN) -+ CASE_CSR_XCHGQ(MISC) -+ CASE_CSR_XCHGQ(ECFG) -+ case LOONGARCH_CSR_ESTAT: -+ val = env->CSR_ESTAT; -+ qatomic_and(&env->CSR_ESTAT, ~mask); -+ qatomic_or(&env->CSR_ESTAT, v); -+ break; -+ CASE_CSR_XCHGQ(ERA) -+ CASE_CSR_XCHGQ(BADV) -+ CASE_CSR_XCHGQ(BADI) -+ CASE_CSR_XCHGQ(EEPN) -+ CASE_CSR_XCHGQ(TLBIDX) -+ CASE_CSR_XCHGQ(TLBEHI) -+ CASE_CSR_XCHGQ(TLBELO0) -+ CASE_CSR_XCHGQ(TLBELO1) -+ CASE_CSR_XCHGQ(TLBWIRED) -+ CASE_CSR_XCHGQ(GTLBC) -+ CASE_CSR_XCHGQ(TRGP) -+ CASE_CSR_XCHGQ(ASID) -+ CASE_CSR_XCHGQ(PGDL) -+ CASE_CSR_XCHGQ(PGDH) -+ CASE_CSR_XCHGQ(PGD) -+ CASE_CSR_XCHGQ(PWCTL0) -+ CASE_CSR_XCHGQ(PWCTL1) -+ CASE_CSR_XCHGQ(STLBPGSIZE) -+ CASE_CSR_XCHGQ(RVACFG) -+ CASE_CSR_XCHGQ(CPUID) -+ CASE_CSR_XCHGQ(PRCFG1) -+ CASE_CSR_XCHGQ(PRCFG2) -+ CASE_CSR_XCHGQ(PRCFG3) -+ CASE_CSR_XCHGQ(KS0) -+ CASE_CSR_XCHGQ(KS1) -+ CASE_CSR_XCHGQ(KS2) -+ CASE_CSR_XCHGQ(KS3) -+ CASE_CSR_XCHGQ(KS4) -+ CASE_CSR_XCHGQ(KS5) -+ CASE_CSR_XCHGQ(KS6) -+ CASE_CSR_XCHGQ(KS7) -+ CASE_CSR_XCHGQ(KS8) -+ CASE_CSR_XCHGQ(TMID) -+ case LOONGARCH_CSR_TCFG: -+ val = env->CSR_TCFG; -+ tmp = val & ~mask; -+ tmp |= v; -+ cpu_loongarch_store_stable_timer_config(env, tmp); -+ break; -+ CASE_CSR_XCHGQ(TVAL) -+ CASE_CSR_XCHGQ(CNTC) -+ CASE_CSR_XCHGQ(TINTCLR) -+ CASE_CSR_XCHGQ(GSTAT) -+ CASE_CSR_XCHGQ(GCFG) -+ CASE_CSR_XCHGQ(GINTC) -+ CASE_CSR_XCHGQ(GCNTC) -+ CASE_CSR_XCHGQ(LLBCTL) -+ CASE_CSR_XCHGQ(IMPCTL1) -+ CASE_CSR_XCHGQ(IMPCTL2) -+ CASE_CSR_XCHGQ(GNMI) -+ CASE_CSR_XCHGQ(TLBRENT) -+ CASE_CSR_XCHGQ(TLBRBADV) -+ CASE_CSR_XCHGQ(TLBRERA) -+ CASE_CSR_XCHGQ(TLBRSAVE) -+ CASE_CSR_XCHGQ(TLBRELO0) -+ CASE_CSR_XCHGQ(TLBRELO1) -+ CASE_CSR_XCHGQ(TLBREHI) -+ CASE_CSR_XCHGQ(TLBRPRMD) -+ CASE_CSR_XCHGQ(ERRCTL) -+ CASE_CSR_XCHGQ(ERRINFO) -+ CASE_CSR_XCHGQ(ERRINFO1) -+ CASE_CSR_XCHGQ(ERRENT) -+ CASE_CSR_XCHGQ(ERRERA) -+ CASE_CSR_XCHGQ(ERRSAVE) -+ CASE_CSR_XCHGQ(CTAG) -+ CASE_CSR_XCHGQ(DMWIN0) -+ CASE_CSR_XCHGQ(DMWIN1) -+ CASE_CSR_XCHGQ(DMWIN2) -+ CASE_CSR_XCHGQ(DMWIN3) -+ CASE_CSR_XCHGQ(PERFCTRL0) -+ CASE_CSR_XCHGQ(PERFCNTR0) -+ CASE_CSR_XCHGQ(PERFCTRL1) -+ CASE_CSR_XCHGQ(PERFCNTR1) -+ CASE_CSR_XCHGQ(PERFCTRL2) -+ CASE_CSR_XCHGQ(PERFCNTR2) -+ CASE_CSR_XCHGQ(PERFCTRL3) -+ CASE_CSR_XCHGQ(PERFCNTR3) -+ /* debug */ -+ CASE_CSR_XCHGQ(MWPC) -+ CASE_CSR_XCHGQ(MWPS) -+ CASE_CSR_XCHGQ(DB0ADDR) -+ CASE_CSR_XCHGQ(DB0MASK) -+ CASE_CSR_XCHGQ(DB0CTL) -+ CASE_CSR_XCHGQ(DB0ASID) -+ CASE_CSR_XCHGQ(DB1ADDR) -+ CASE_CSR_XCHGQ(DB1MASK) -+ CASE_CSR_XCHGQ(DB1CTL) -+ CASE_CSR_XCHGQ(DB1ASID) -+ CASE_CSR_XCHGQ(DB2ADDR) -+ CASE_CSR_XCHGQ(DB2MASK) -+ CASE_CSR_XCHGQ(DB2CTL) -+ CASE_CSR_XCHGQ(DB2ASID) -+ CASE_CSR_XCHGQ(DB3ADDR) -+ CASE_CSR_XCHGQ(DB3MASK) -+ CASE_CSR_XCHGQ(DB3CTL) -+ CASE_CSR_XCHGQ(DB3ASID) -+ CASE_CSR_XCHGQ(FWPC) -+ CASE_CSR_XCHGQ(FWPS) -+ CASE_CSR_XCHGQ(IB0ADDR) -+ CASE_CSR_XCHGQ(IB0MASK) -+ CASE_CSR_XCHGQ(IB0CTL) -+ CASE_CSR_XCHGQ(IB0ASID) -+ CASE_CSR_XCHGQ(IB1ADDR) -+ CASE_CSR_XCHGQ(IB1MASK) -+ CASE_CSR_XCHGQ(IB1CTL) -+ CASE_CSR_XCHGQ(IB1ASID) -+ CASE_CSR_XCHGQ(IB2ADDR) -+ CASE_CSR_XCHGQ(IB2MASK) -+ CASE_CSR_XCHGQ(IB2CTL) -+ CASE_CSR_XCHGQ(IB2ASID) -+ CASE_CSR_XCHGQ(IB3ADDR) -+ CASE_CSR_XCHGQ(IB3MASK) -+ CASE_CSR_XCHGQ(IB3CTL) -+ CASE_CSR_XCHGQ(IB3ASID) -+ CASE_CSR_XCHGQ(IB4ADDR) -+ CASE_CSR_XCHGQ(IB4MASK) -+ CASE_CSR_XCHGQ(IB4CTL) -+ CASE_CSR_XCHGQ(IB4ASID) -+ CASE_CSR_XCHGQ(IB5ADDR) -+ CASE_CSR_XCHGQ(IB5MASK) -+ CASE_CSR_XCHGQ(IB5CTL) -+ CASE_CSR_XCHGQ(IB5ASID) -+ CASE_CSR_XCHGQ(IB6ADDR) -+ CASE_CSR_XCHGQ(IB6MASK) -+ CASE_CSR_XCHGQ(IB6CTL) -+ CASE_CSR_XCHGQ(IB6ASID) -+ CASE_CSR_XCHGQ(IB7ADDR) -+ CASE_CSR_XCHGQ(IB7MASK) -+ CASE_CSR_XCHGQ(IB7CTL) -+ CASE_CSR_XCHGQ(IB7ASID) -+ CASE_CSR_XCHGQ(DEBUG) -+ CASE_CSR_XCHGQ(DERA) -+ CASE_CSR_XCHGQ(DESAVE) -+ default : -+ assert(0); -+ } -+ -+#undef CASE_CSR_XCHGQ -+ compute_hflags(env); -+ return val; -+} -+ -+static target_ulong confbus_addr(CPULOONGARCHState *env, int cpuid, -+ target_ulong csr_addr) -+{ -+ target_ulong addr; -+ target_ulong node_addr; -+ int cores_per_node = ((0x60018 >> 3) & 0xff) + 1; -+ -+ switch (cores_per_node) { -+ case 4: -+ assert(cpuid < 64); -+ node_addr = ((target_ulong)(cpuid & 0x3c) << 42); -+ break; -+ case 8: -+ assert(cpuid < 128); -+ node_addr = ((target_ulong)(cpuid & 0x78) << 41) + -+ ((target_ulong)(cpuid & 0x4) << 14); -+ break; -+ case 16: -+ assert(cpuid < 256); -+ node_addr = ((target_ulong)(cpuid & 0xf0) << 40) + -+ ((target_ulong)(cpuid & 0xc) << 14); -+ break; -+ default: -+ assert(0); -+ break; -+ } -+ -+ /* -+ * per core address -+ *0x10xx => ipi -+ * 0x18xx => extioi isr -+ */ -+ if (((csr_addr & 0xff00) == 0x1000)) { -+ addr = (csr_addr & 0xff) + (target_ulong)(cpuid << 8); -+ addr = 0x800000001f000000UL + addr; -+ return addr; -+ } else if ((csr_addr & 0xff00) == 0x1800) { -+ addr = (csr_addr & 0xff) + ((target_ulong)(cpuid << 8)); -+ addr = 0x800000001f020000UL + addr; -+ return addr; -+ } else if ((csr_addr & 0xff00) >= 0x1400 && (csr_addr & 0xff00) < 0x1d00) { -+ addr = 0x800000001f010000UL + ((csr_addr & 0xfff) - 0x400); -+ return addr; -+ } else if (csr_addr == 0x408) { -+ addr = csr_addr; -+ } else { -+ addr = csr_addr + node_addr; -+ } -+ -+ addr = 0x800000001fe00000UL + addr; -+ return addr; -+} -+ -+void helper_iocsr(CPULOONGARCHState *env, target_ulong r_addr, -+ target_ulong r_val, uint32_t op) -+{ -+ target_ulong addr; -+ target_ulong val = env->active_tc.gpr[r_val]; -+ int mask; -+ -+ addr = confbus_addr(env, CPU(loongarch_env_get_cpu(env))->cpu_index, -+ env->active_tc.gpr[r_addr]); -+ -+ switch (env->active_tc.gpr[r_addr]) { -+ /* IPI send */ -+ case 0x1040: -+ if (op != OPC_LARCH_ST_W) { -+ return; -+ } -+ op = OPC_LARCH_ST_W; -+ break; -+ -+ /* Mail send */ -+ case 0x1048: -+ if (op != OPC_LARCH_ST_D) { -+ return; -+ } -+ op = OPC_LARCH_ST_D; -+ break; -+ -+ /* ANY send */ -+ case 0x1158: -+ if (op != OPC_LARCH_ST_D) { -+ return; -+ } -+ addr = confbus_addr(env, (val >> 16) & 0x3ff, val & 0xffff); -+ mask = (val >> 27) & 0xf; -+ val = (val >> 32); -+ switch (mask) { -+ case 0: -+ op = OPC_LARCH_ST_W; -+ break; -+ case 0x7: -+ op = OPC_LARCH_ST_B; -+ addr += 3; -+ val >>= 24; -+ break; -+ case 0xb: -+ op = OPC_LARCH_ST_B; -+ addr += 2; -+ val >>= 16; -+ break; -+ case 0xd: -+ op = OPC_LARCH_ST_B; -+ addr += 1; -+ val >>= 8; -+ break; -+ case 0xe: -+ op = OPC_LARCH_ST_B; -+ break; -+ case 0xc: -+ op = OPC_LARCH_ST_H; -+ break; -+ case 0x3: -+ op = OPC_LARCH_ST_H; -+ addr += 2; -+ val >>= 16; -+ break; -+ default: -+ qemu_log("Unsupported any_send mask0x%x\n", mask); -+ break; -+ } -+ break; -+ -+ default: -+ break; -+ } -+ -+ switch (op) { -+ case OPC_LARCH_LD_D: -+ env->active_tc.gpr[r_val] = cpu_ldq_data_ra(env, addr, -+ GETPC()); -+ break; -+ case OPC_LARCH_LD_W: -+ env->active_tc.gpr[r_val] = cpu_ldl_data_ra(env, addr, -+ GETPC()); -+ break; -+ case OPC_LARCH_LD_H: -+ assert(0); -+ break; -+ case OPC_LARCH_LD_B: -+ assert(0); -+ break; -+ case OPC_LARCH_ST_D: -+ cpu_stq_data_ra(env, addr, val, GETPC()); -+ break; -+ case OPC_LARCH_ST_W: -+ cpu_stl_data_ra(env, addr, val, GETPC()); -+ break; -+ case OPC_LARCH_ST_H: -+ cpu_stb_data_ra(env, addr, val, GETPC()); -+ break; -+ case OPC_LARCH_ST_B: -+ cpu_stb_data_ra(env, addr, val, GETPC()); -+ break; -+ default: -+ qemu_log("Unknown op 0x%x", op); -+ assert(0); -+ } -+} -+#endif -+ -+target_ulong helper_cpucfg(CPULOONGARCHState *env, target_ulong rj) -+{ -+ return 0; -+} -+ -+ -diff --git a/target/loongarch64/fpu.c b/target/loongarch64/fpu.c -new file mode 100644 -index 0000000000..795458205b ---- /dev/null -+++ b/target/loongarch64/fpu.c -@@ -0,0 +1,28 @@ -+/* -+ * loongarch float point emulation helpers for qemu. -+ * -+ * Copyright (c) 2020-2021 -+ * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2 of the License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library; if not, see . -+ */ -+#include "qemu/osdep.h" -+#include "fpu/softfloat.h" -+ -+/* convert loongarch rounding mode in fcsr0 to IEEE library */ -+unsigned int ieee_rm[] = { -+ float_round_nearest_even, -+ float_round_to_zero, -+ float_round_up, -+ float_round_down -+}; -diff --git a/target/loongarch64/fpu_helper.c b/target/loongarch64/fpu_helper.c -new file mode 100644 -index 0000000000..42d7f05ca2 ---- /dev/null -+++ b/target/loongarch64/fpu_helper.c -@@ -0,0 +1,952 @@ -+/* -+ * loongarch float point emulation helpers for qemu. -+ * -+ * Copyright (c) 2020-2021 -+ * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2 of the License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library; if not, see . -+ */ -+#include "qemu/osdep.h" -+#include "cpu.h" -+#include "internal.h" -+#include "qemu/host-utils.h" -+#include "exec/helper-proto.h" -+#include "exec/exec-all.h" -+#include "fpu/softfloat.h" -+ -+#define FP_TO_INT32_OVERFLOW 0x7fffffff -+#define FP_TO_INT64_OVERFLOW 0x7fffffffffffffffULL -+ -+#define FLOAT_CLASS_SIGNALING_NAN 0x001 -+#define FLOAT_CLASS_QUIET_NAN 0x002 -+#define FLOAT_CLASS_NEGATIVE_INFINITY 0x004 -+#define FLOAT_CLASS_NEGATIVE_NORMAL 0x008 -+#define FLOAT_CLASS_NEGATIVE_SUBNORMAL 0x010 -+#define FLOAT_CLASS_NEGATIVE_ZERO 0x020 -+#define FLOAT_CLASS_POSITIVE_INFINITY 0x040 -+#define FLOAT_CLASS_POSITIVE_NORMAL 0x080 -+#define FLOAT_CLASS_POSITIVE_SUBNORMAL 0x100 -+#define FLOAT_CLASS_POSITIVE_ZERO 0x200 -+ -+target_ulong helper_movfcsr2gr(CPULOONGARCHState *env, uint32_t reg) -+{ -+ target_ulong r = 0; -+ -+ switch (reg) { -+ case 0: -+ r = (uint32_t)env->active_fpu.fcsr0; -+ break; -+ case 1: -+ r = (env->active_fpu.fcsr0 & FCSR0_M1); -+ break; -+ case 2: -+ r = (env->active_fpu.fcsr0 & FCSR0_M2); -+ break; -+ case 3: -+ r = (env->active_fpu.fcsr0 & FCSR0_M3); -+ break; -+ case 16: -+ r = (uint32_t)env->active_fpu.vcsr16; -+ break; -+ default: -+ printf("%s: warning, fcsr '%d' not supported\n", __func__, reg); -+ assert(0); -+ break; -+ } -+ -+ return r; -+} -+ -+void helper_movgr2fcsr(CPULOONGARCHState *env, target_ulong arg1, -+ uint32_t fcsr, uint32_t rj) -+{ -+ switch (fcsr) { -+ case 0: -+ env->active_fpu.fcsr0 = arg1; -+ break; -+ case 1: -+ env->active_fpu.fcsr0 = (arg1 & FCSR0_M1) | -+ (env->active_fpu.fcsr0 & ~FCSR0_M1); -+ break; -+ case 2: -+ env->active_fpu.fcsr0 = (arg1 & FCSR0_M2) | -+ (env->active_fpu.fcsr0 & ~FCSR0_M2); -+ break; -+ case 3: -+ env->active_fpu.fcsr0 = (arg1 & FCSR0_M3) | -+ (env->active_fpu.fcsr0 & ~FCSR0_M3); -+ break; -+ case 16: -+ env->active_fpu.vcsr16 = arg1; -+ break; -+ default: -+ printf("%s: warning, fcsr '%d' not supported\n", __func__, fcsr); -+ assert(0); -+ break; -+ } -+ restore_fp_status(env); -+ set_float_exception_flags(0, &env->active_fpu.fp_status); -+} -+ -+void helper_movreg2cf(CPULOONGARCHState *env, uint32_t cd, target_ulong src) -+{ -+ env->active_fpu.cf[cd & 0x7] = src & 0x1; -+} -+ -+void helper_movreg2cf_i32(CPULOONGARCHState *env, uint32_t cd, uint32_t src) -+{ -+ env->active_fpu.cf[cd & 0x7] = src & 0x1; -+} -+ -+void helper_movreg2cf_i64(CPULOONGARCHState *env, uint32_t cd, uint64_t src) -+{ -+ env->active_fpu.cf[cd & 0x7] = src & 0x1; -+} -+ -+target_ulong helper_movcf2reg(CPULOONGARCHState *env, uint32_t cj) -+{ -+ return (target_ulong)env->active_fpu.cf[cj & 0x7]; -+} -+ -+int ieee_ex_to_loongarch(int xcpt) -+{ -+ int ret = 0; -+ if (xcpt) { -+ if (xcpt & float_flag_invalid) { -+ ret |= FP_INVALID; -+ } -+ if (xcpt & float_flag_overflow) { -+ ret |= FP_OVERFLOW; -+ } -+ if (xcpt & float_flag_underflow) { -+ ret |= FP_UNDERFLOW; -+ } -+ if (xcpt & float_flag_divbyzero) { -+ ret |= FP_DIV0; -+ } -+ if (xcpt & float_flag_inexact) { -+ ret |= FP_INEXACT; -+ } -+ } -+ return ret; -+} -+ -+static inline void update_fcsr0(CPULOONGARCHState *env, uintptr_t pc) -+{ -+ int tmp = ieee_ex_to_loongarch(get_float_exception_flags( -+ &env->active_fpu.fp_status)); -+ -+ SET_FP_CAUSE(env->active_fpu.fcsr0, tmp); -+ if (tmp) { -+ set_float_exception_flags(0, &env->active_fpu.fp_status); -+ -+ if (GET_FP_ENABLE(env->active_fpu.fcsr0) & tmp) { -+ do_raise_exception(env, EXCP_FPE, pc); -+ } else { -+ UPDATE_FP_FLAGS(env->active_fpu.fcsr0, tmp); -+ } -+ } -+} -+ -+/* unary operations, modifying fp status */ -+uint64_t helper_float_sqrt_d(CPULOONGARCHState *env, uint64_t fdt0) -+{ -+ fdt0 = float64_sqrt(fdt0, &env->active_fpu.fp_status); -+ update_fcsr0(env, GETPC()); -+ return fdt0; -+} -+ -+uint32_t helper_float_sqrt_s(CPULOONGARCHState *env, uint32_t fst0) -+{ -+ fst0 = float32_sqrt(fst0, &env->active_fpu.fp_status); -+ update_fcsr0(env, GETPC()); -+ return fst0; -+} -+ -+uint64_t helper_float_cvtd_s(CPULOONGARCHState *env, uint32_t fst0) -+{ -+ uint64_t fdt2; -+ -+ fdt2 = float32_to_float64(fst0, &env->active_fpu.fp_status); -+ update_fcsr0(env, GETPC()); -+ return fdt2; -+} -+ -+uint64_t helper_float_cvtd_w(CPULOONGARCHState *env, uint32_t wt0) -+{ -+ uint64_t fdt2; -+ -+ fdt2 = int32_to_float64(wt0, &env->active_fpu.fp_status); -+ update_fcsr0(env, GETPC()); -+ return fdt2; -+} -+ -+uint64_t helper_float_cvtd_l(CPULOONGARCHState *env, uint64_t dt0) -+{ -+ uint64_t fdt2; -+ -+ fdt2 = int64_to_float64(dt0, &env->active_fpu.fp_status); -+ update_fcsr0(env, GETPC()); -+ return fdt2; -+} -+ -+uint64_t helper_float_cvt_l_d(CPULOONGARCHState *env, uint64_t fdt0) -+{ -+ uint64_t dt2; -+ -+ dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status); -+ if (get_float_exception_flags(&env->active_fpu.fp_status) -+ & (float_flag_invalid | float_flag_overflow)) { -+ dt2 = FP_TO_INT64_OVERFLOW; -+ } -+ update_fcsr0(env, GETPC()); -+ return dt2; -+} -+ -+uint64_t helper_float_cvt_l_s(CPULOONGARCHState *env, uint32_t fst0) -+{ -+ uint64_t dt2; -+ -+ dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status); -+ if (get_float_exception_flags(&env->active_fpu.fp_status) -+ & (float_flag_invalid | float_flag_overflow)) { -+ dt2 = FP_TO_INT64_OVERFLOW; -+ } -+ update_fcsr0(env, GETPC()); -+ return dt2; -+} -+ -+uint32_t helper_float_cvts_d(CPULOONGARCHState *env, uint64_t fdt0) -+{ -+ uint32_t fst2; -+ -+ fst2 = float64_to_float32(fdt0, &env->active_fpu.fp_status); -+ update_fcsr0(env, GETPC()); -+ return fst2; -+} -+ -+uint32_t helper_float_cvts_w(CPULOONGARCHState *env, uint32_t wt0) -+{ -+ uint32_t fst2; -+ -+ fst2 = int32_to_float32(wt0, &env->active_fpu.fp_status); -+ update_fcsr0(env, GETPC()); -+ return fst2; -+} -+ -+uint32_t helper_float_cvts_l(CPULOONGARCHState *env, uint64_t dt0) -+{ -+ uint32_t fst2; -+ -+ fst2 = int64_to_float32(dt0, &env->active_fpu.fp_status); -+ update_fcsr0(env, GETPC()); -+ return fst2; -+} -+ -+uint32_t helper_float_cvt_w_s(CPULOONGARCHState *env, uint32_t fst0) -+{ -+ uint32_t wt2; -+ -+ wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status); -+ if (get_float_exception_flags(&env->active_fpu.fp_status) -+ & (float_flag_invalid | float_flag_overflow)) { -+ wt2 = FP_TO_INT32_OVERFLOW; -+ } -+ update_fcsr0(env, GETPC()); -+ return wt2; -+} -+ -+uint32_t helper_float_cvt_w_d(CPULOONGARCHState *env, uint64_t fdt0) -+{ -+ uint32_t wt2; -+ -+ wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status); -+ if (get_float_exception_flags(&env->active_fpu.fp_status) -+ & (float_flag_invalid | float_flag_overflow)) { -+ wt2 = FP_TO_INT32_OVERFLOW; -+ } -+ update_fcsr0(env, GETPC()); -+ return wt2; -+} -+ -+uint64_t helper_float_round_l_d(CPULOONGARCHState *env, uint64_t fdt0) -+{ -+ uint64_t dt2; -+ -+ set_float_rounding_mode(float_round_nearest_even, -+ &env->active_fpu.fp_status); -+ dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status); -+ restore_rounding_mode(env); -+ if (get_float_exception_flags(&env->active_fpu.fp_status) -+ & (float_flag_invalid | float_flag_overflow)) { -+ dt2 = FP_TO_INT64_OVERFLOW; -+ } -+ update_fcsr0(env, GETPC()); -+ return dt2; -+} -+ -+uint64_t helper_float_round_l_s(CPULOONGARCHState *env, uint32_t fst0) -+{ -+ uint64_t dt2; -+ -+ set_float_rounding_mode(float_round_nearest_even, -+ &env->active_fpu.fp_status); -+ dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status); -+ restore_rounding_mode(env); -+ if (get_float_exception_flags(&env->active_fpu.fp_status) -+ & (float_flag_invalid | float_flag_overflow)) { -+ dt2 = FP_TO_INT64_OVERFLOW; -+ } -+ update_fcsr0(env, GETPC()); -+ return dt2; -+} -+ -+uint32_t helper_float_round_w_d(CPULOONGARCHState *env, uint64_t fdt0) -+{ -+ uint32_t wt2; -+ -+ set_float_rounding_mode(float_round_nearest_even, -+ &env->active_fpu.fp_status); -+ wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status); -+ restore_rounding_mode(env); -+ if (get_float_exception_flags(&env->active_fpu.fp_status) -+ & (float_flag_invalid | float_flag_overflow)) { -+ wt2 = FP_TO_INT32_OVERFLOW; -+ } -+ update_fcsr0(env, GETPC()); -+ return wt2; -+} -+ -+uint32_t helper_float_round_w_s(CPULOONGARCHState *env, uint32_t fst0) -+{ -+ uint32_t wt2; -+ -+ set_float_rounding_mode(float_round_nearest_even, -+ &env->active_fpu.fp_status); -+ wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status); -+ restore_rounding_mode(env); -+ if (get_float_exception_flags(&env->active_fpu.fp_status) -+ & (float_flag_invalid | float_flag_overflow)) { -+ wt2 = FP_TO_INT32_OVERFLOW; -+ } -+ update_fcsr0(env, GETPC()); -+ return wt2; -+} -+ -+uint64_t helper_float_trunc_l_d(CPULOONGARCHState *env, uint64_t fdt0) -+{ -+ uint64_t dt2; -+ -+ dt2 = float64_to_int64_round_to_zero(fdt0, -+ &env->active_fpu.fp_status); -+ if (get_float_exception_flags(&env->active_fpu.fp_status) -+ & (float_flag_invalid | float_flag_overflow)) { -+ dt2 = FP_TO_INT64_OVERFLOW; -+ } -+ update_fcsr0(env, GETPC()); -+ return dt2; -+} -+ -+uint64_t helper_float_trunc_l_s(CPULOONGARCHState *env, uint32_t fst0) -+{ -+ uint64_t dt2; -+ -+ dt2 = float32_to_int64_round_to_zero(fst0, &env->active_fpu.fp_status); -+ if (get_float_exception_flags(&env->active_fpu.fp_status) -+ & (float_flag_invalid | float_flag_overflow)) { -+ dt2 = FP_TO_INT64_OVERFLOW; -+ } -+ update_fcsr0(env, GETPC()); -+ return dt2; -+} -+ -+uint32_t helper_float_trunc_w_d(CPULOONGARCHState *env, uint64_t fdt0) -+{ -+ uint32_t wt2; -+ -+ wt2 = float64_to_int32_round_to_zero(fdt0, &env->active_fpu.fp_status); -+ if (get_float_exception_flags(&env->active_fpu.fp_status) -+ & (float_flag_invalid | float_flag_overflow)) { -+ wt2 = FP_TO_INT32_OVERFLOW; -+ } -+ update_fcsr0(env, GETPC()); -+ return wt2; -+} -+ -+uint32_t helper_float_trunc_w_s(CPULOONGARCHState *env, uint32_t fst0) -+{ -+ uint32_t wt2; -+ -+ wt2 = float32_to_int32_round_to_zero(fst0, &env->active_fpu.fp_status); -+ if (get_float_exception_flags(&env->active_fpu.fp_status) -+ & (float_flag_invalid | float_flag_overflow)) { -+ wt2 = FP_TO_INT32_OVERFLOW; -+ } -+ update_fcsr0(env, GETPC()); -+ return wt2; -+} -+ -+uint64_t helper_float_ceil_l_d(CPULOONGARCHState *env, uint64_t fdt0) -+{ -+ uint64_t dt2; -+ -+ set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status); -+ dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status); -+ restore_rounding_mode(env); -+ if (get_float_exception_flags(&env->active_fpu.fp_status) -+ & (float_flag_invalid | float_flag_overflow)) { -+ dt2 = FP_TO_INT64_OVERFLOW; -+ } -+ update_fcsr0(env, GETPC()); -+ return dt2; -+} -+ -+uint64_t helper_float_ceil_l_s(CPULOONGARCHState *env, uint32_t fst0) -+{ -+ uint64_t dt2; -+ -+ set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status); -+ dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status); -+ restore_rounding_mode(env); -+ if (get_float_exception_flags(&env->active_fpu.fp_status) -+ & (float_flag_invalid | float_flag_overflow)) { -+ dt2 = FP_TO_INT64_OVERFLOW; -+ } -+ update_fcsr0(env, GETPC()); -+ return dt2; -+} -+ -+uint32_t helper_float_ceil_w_d(CPULOONGARCHState *env, uint64_t fdt0) -+{ -+ uint32_t wt2; -+ -+ set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status); -+ wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status); -+ restore_rounding_mode(env); -+ if (get_float_exception_flags(&env->active_fpu.fp_status) -+ & (float_flag_invalid | float_flag_overflow)) { -+ wt2 = FP_TO_INT32_OVERFLOW; -+ } -+ update_fcsr0(env, GETPC()); -+ return wt2; -+} -+ -+uint32_t helper_float_ceil_w_s(CPULOONGARCHState *env, uint32_t fst0) -+{ -+ uint32_t wt2; -+ -+ set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status); -+ wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status); -+ restore_rounding_mode(env); -+ if (get_float_exception_flags(&env->active_fpu.fp_status) -+ & (float_flag_invalid | float_flag_overflow)) { -+ wt2 = FP_TO_INT32_OVERFLOW; -+ } -+ update_fcsr0(env, GETPC()); -+ return wt2; -+} -+ -+uint64_t helper_float_floor_l_d(CPULOONGARCHState *env, uint64_t fdt0) -+{ -+ uint64_t dt2; -+ -+ set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status); -+ dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status); -+ restore_rounding_mode(env); -+ if (get_float_exception_flags(&env->active_fpu.fp_status) -+ & (float_flag_invalid | float_flag_overflow)) { -+ dt2 = FP_TO_INT64_OVERFLOW; -+ } -+ update_fcsr0(env, GETPC()); -+ return dt2; -+} -+ -+uint64_t helper_float_floor_l_s(CPULOONGARCHState *env, uint32_t fst0) -+{ -+ uint64_t dt2; -+ -+ set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status); -+ dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status); -+ restore_rounding_mode(env); -+ if (get_float_exception_flags(&env->active_fpu.fp_status) -+ & (float_flag_invalid | float_flag_overflow)) { -+ dt2 = FP_TO_INT64_OVERFLOW; -+ } -+ update_fcsr0(env, GETPC()); -+ return dt2; -+} -+ -+uint32_t helper_float_floor_w_d(CPULOONGARCHState *env, uint64_t fdt0) -+{ -+ uint32_t wt2; -+ -+ set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status); -+ wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status); -+ restore_rounding_mode(env); -+ if (get_float_exception_flags(&env->active_fpu.fp_status) -+ & (float_flag_invalid | float_flag_overflow)) { -+ wt2 = FP_TO_INT32_OVERFLOW; -+ } -+ update_fcsr0(env, GETPC()); -+ return wt2; -+} -+ -+uint32_t helper_float_floor_w_s(CPULOONGARCHState *env, uint32_t fst0) -+{ -+ uint32_t wt2; -+ -+ set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status); -+ wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status); -+ restore_rounding_mode(env); -+ if (get_float_exception_flags(&env->active_fpu.fp_status) -+ & (float_flag_invalid | float_flag_overflow)) { -+ wt2 = FP_TO_INT32_OVERFLOW; -+ } -+ update_fcsr0(env, GETPC()); -+ return wt2; -+} -+ -+/* unary operations, not modifying fp status */ -+#define FLOAT_UNOP(name) \ -+uint64_t helper_float_ ## name ## _d(uint64_t fdt0) \ -+{ \ -+ return float64_ ## name(fdt0); \ -+} \ -+uint32_t helper_float_ ## name ## _s(uint32_t fst0) \ -+{ \ -+ return float32_ ## name(fst0); \ -+} -+ -+FLOAT_UNOP(abs) -+FLOAT_UNOP(chs) -+#undef FLOAT_UNOP -+ -+uint64_t helper_float_recip_d(CPULOONGARCHState *env, uint64_t fdt0) -+{ -+ uint64_t fdt2; -+ -+ fdt2 = float64_div(float64_one, fdt0, &env->active_fpu.fp_status); -+ update_fcsr0(env, GETPC()); -+ return fdt2; -+} -+ -+uint32_t helper_float_recip_s(CPULOONGARCHState *env, uint32_t fst0) -+{ -+ uint32_t fst2; -+ -+ fst2 = float32_div(float32_one, fst0, &env->active_fpu.fp_status); -+ update_fcsr0(env, GETPC()); -+ return fst2; -+} -+ -+uint64_t helper_float_rsqrt_d(CPULOONGARCHState *env, uint64_t fdt0) -+{ -+ uint64_t fdt2; -+ -+ fdt2 = float64_sqrt(fdt0, &env->active_fpu.fp_status); -+ fdt2 = float64_div(float64_one, fdt2, &env->active_fpu.fp_status); -+ update_fcsr0(env, GETPC()); -+ return fdt2; -+} -+ -+uint32_t helper_float_rsqrt_s(CPULOONGARCHState *env, uint32_t fst0) -+{ -+ uint32_t fst2; -+ -+ fst2 = float32_sqrt(fst0, &env->active_fpu.fp_status); -+ fst2 = float32_div(float32_one, fst2, &env->active_fpu.fp_status); -+ update_fcsr0(env, GETPC()); -+ return fst2; -+} -+ -+uint32_t helper_float_rint_s(CPULOONGARCHState *env, uint32_t fs) -+{ -+ uint32_t fdret; -+ -+ fdret = float32_round_to_int(fs, &env->active_fpu.fp_status); -+ update_fcsr0(env, GETPC()); -+ return fdret; -+} -+ -+uint64_t helper_float_rint_d(CPULOONGARCHState *env, uint64_t fs) -+{ -+ uint64_t fdret; -+ -+ fdret = float64_round_to_int(fs, &env->active_fpu.fp_status); -+ update_fcsr0(env, GETPC()); -+ return fdret; -+} -+ -+#define FLOAT_CLASS(name, bits) \ -+uint ## bits ## _t float_ ## name(uint ## bits ## _t arg, \ -+ float_status *status) \ -+{ \ -+ if (float ## bits ## _is_signaling_nan(arg, status)) { \ -+ return FLOAT_CLASS_SIGNALING_NAN; \ -+ } else if (float ## bits ## _is_quiet_nan(arg, status)) { \ -+ return FLOAT_CLASS_QUIET_NAN; \ -+ } else if (float ## bits ## _is_neg(arg)) { \ -+ if (float ## bits ## _is_infinity(arg)) { \ -+ return FLOAT_CLASS_NEGATIVE_INFINITY; \ -+ } else if (float ## bits ## _is_zero(arg)) { \ -+ return FLOAT_CLASS_NEGATIVE_ZERO; \ -+ } else if (float ## bits ## _is_zero_or_denormal(arg)) { \ -+ return FLOAT_CLASS_NEGATIVE_SUBNORMAL; \ -+ } else { \ -+ return FLOAT_CLASS_NEGATIVE_NORMAL; \ -+ } \ -+ } else { \ -+ if (float ## bits ## _is_infinity(arg)) { \ -+ return FLOAT_CLASS_POSITIVE_INFINITY; \ -+ } else if (float ## bits ## _is_zero(arg)) { \ -+ return FLOAT_CLASS_POSITIVE_ZERO; \ -+ } else if (float ## bits ## _is_zero_or_denormal(arg)) { \ -+ return FLOAT_CLASS_POSITIVE_SUBNORMAL; \ -+ } else { \ -+ return FLOAT_CLASS_POSITIVE_NORMAL; \ -+ } \ -+ } \ -+} \ -+ \ -+uint ## bits ## _t helper_float_ ## name(CPULOONGARCHState *env, \ -+ uint ## bits ## _t arg) \ -+{ \ -+ return float_ ## name(arg, &env->active_fpu.fp_status); \ -+} -+ -+FLOAT_CLASS(class_s, 32) -+FLOAT_CLASS(class_d, 64) -+#undef FLOAT_CLASS -+ -+/* binary operations */ -+#define FLOAT_BINOP(name) \ -+uint64_t helper_float_ ## name ## _d(CPULOONGARCHState *env, \ -+ uint64_t fdt0, uint64_t fdt1) \ -+{ \ -+ uint64_t dt2; \ -+ \ -+ dt2 = float64_ ## name(fdt0, fdt1, &env->active_fpu.fp_status);\ -+ update_fcsr0(env, GETPC()); \ -+ return dt2; \ -+} \ -+ \ -+uint32_t helper_float_ ## name ## _s(CPULOONGARCHState *env, \ -+ uint32_t fst0, uint32_t fst1) \ -+{ \ -+ uint32_t wt2; \ -+ \ -+ wt2 = float32_ ## name(fst0, fst1, &env->active_fpu.fp_status);\ -+ update_fcsr0(env, GETPC()); \ -+ return wt2; \ -+} -+ -+FLOAT_BINOP(add) -+FLOAT_BINOP(sub) -+FLOAT_BINOP(mul) -+FLOAT_BINOP(div) -+#undef FLOAT_BINOP -+ -+uint64_t helper_float_exp2_d(CPULOONGARCHState *env, -+ uint64_t fdt0, uint64_t fdt1) -+{ -+ uint64_t dt2; -+ int64_t n = (int64_t)fdt1; -+ -+ dt2 = float64_scalbn(fdt0, -+ n > 0x1000 ? 0x1000 : -+ n < -0x1000 ? -0x1000 : n, -+ &env->active_fpu.fp_status); -+ update_fcsr0(env, GETPC()); -+ return dt2; -+} -+ -+uint32_t helper_float_exp2_s(CPULOONGARCHState *env, -+ uint32_t fst0, uint32_t fst1) -+{ -+ uint32_t wt2; -+ int32_t n = (int32_t)fst1; -+ -+ wt2 = float32_scalbn(fst0, -+ n > 0x200 ? 0x200 : -+ n < -0x200 ? -0x200 : n, -+ &env->active_fpu.fp_status); -+ update_fcsr0(env, GETPC()); -+ return wt2; -+} -+ -+#define FLOAT_MINMAX(name, bits, minmaxfunc) \ -+uint ## bits ## _t helper_float_ ## name(CPULOONGARCHState *env, \ -+ uint ## bits ## _t fs, \ -+ uint ## bits ## _t ft) \ -+{ \ -+ uint ## bits ## _t fdret; \ -+ \ -+ fdret = float ## bits ## _ ## minmaxfunc(fs, ft, \ -+ &env->active_fpu.fp_status); \ -+ update_fcsr0(env, GETPC()); \ -+ return fdret; \ -+} -+ -+FLOAT_MINMAX(max_s, 32, maxnum) -+FLOAT_MINMAX(max_d, 64, maxnum) -+FLOAT_MINMAX(maxa_s, 32, maxnummag) -+FLOAT_MINMAX(maxa_d, 64, maxnummag) -+ -+FLOAT_MINMAX(min_s, 32, minnum) -+FLOAT_MINMAX(min_d, 64, minnum) -+FLOAT_MINMAX(mina_s, 32, minnummag) -+FLOAT_MINMAX(mina_d, 64, minnummag) -+#undef FLOAT_MINMAX -+ -+#define FLOAT_FMADDSUB(name, bits, muladd_arg) \ -+uint ## bits ## _t helper_float_ ## name(CPULOONGARCHState *env, \ -+ uint ## bits ## _t fs, \ -+ uint ## bits ## _t ft, \ -+ uint ## bits ## _t fd) \ -+{ \ -+ uint ## bits ## _t fdret; \ -+ \ -+ fdret = float ## bits ## _muladd(fs, ft, fd, muladd_arg, \ -+ &env->active_fpu.fp_status); \ -+ update_fcsr0(env, GETPC()); \ -+ return fdret; \ -+} -+ -+FLOAT_FMADDSUB(maddf_s, 32, 0) -+FLOAT_FMADDSUB(maddf_d, 64, 0) -+FLOAT_FMADDSUB(msubf_s, 32, float_muladd_negate_c) -+FLOAT_FMADDSUB(msubf_d, 64, float_muladd_negate_c) -+FLOAT_FMADDSUB(nmaddf_s, 32, float_muladd_negate_result) -+FLOAT_FMADDSUB(nmaddf_d, 64, float_muladd_negate_result) -+FLOAT_FMADDSUB(nmsubf_s, 32, float_muladd_negate_result | float_muladd_negate_c) -+FLOAT_FMADDSUB(nmsubf_d, 64, float_muladd_negate_result | float_muladd_negate_c) -+#undef FLOAT_FMADDSUB -+ -+/* compare operations */ -+#define FOP_CONDN_D(op, cond) \ -+uint64_t helper_cmp_d_ ## op(CPULOONGARCHState *env, uint64_t fdt0, \ -+ uint64_t fdt1) \ -+{ \ -+ uint64_t c; \ -+ c = cond; \ -+ update_fcsr0(env, GETPC()); \ -+ if (c) { \ -+ return -1; \ -+ } else { \ -+ return 0; \ -+ } \ -+} -+ -+/* -+ * NOTE: the comma operator will make "cond" to eval to false, -+ * but float64_unordered_quiet() is still called. -+ */ -+FOP_CONDN_D(af, (float64_unordered_quiet(fdt1, fdt0, -+ &env->active_fpu.fp_status), 0)) -+FOP_CONDN_D(un, (float64_unordered_quiet(fdt1, fdt0, -+ &env->active_fpu.fp_status))) -+FOP_CONDN_D(eq, (float64_eq_quiet(fdt0, fdt1, -+ &env->active_fpu.fp_status))) -+FOP_CONDN_D(ueq, (float64_unordered_quiet(fdt1, fdt0, -+ &env->active_fpu.fp_status) -+ || float64_eq_quiet(fdt0, fdt1, -+ &env->active_fpu.fp_status))) -+FOP_CONDN_D(lt, (float64_lt_quiet(fdt0, fdt1, -+ &env->active_fpu.fp_status))) -+FOP_CONDN_D(ult, (float64_unordered_quiet(fdt1, fdt0, -+ &env->active_fpu.fp_status) -+ || float64_lt_quiet(fdt0, fdt1, -+ &env->active_fpu.fp_status))) -+FOP_CONDN_D(le, (float64_le_quiet(fdt0, fdt1, -+ &env->active_fpu.fp_status))) -+FOP_CONDN_D(ule, (float64_unordered_quiet(fdt1, fdt0, -+ &env->active_fpu.fp_status) -+ || float64_le_quiet(fdt0, fdt1, -+ &env->active_fpu.fp_status))) -+/* -+ * NOTE: the comma operator will make "cond" to eval to false, -+ * but float64_unordered() is still called. -+ */ -+FOP_CONDN_D(saf, (float64_unordered(fdt1, fdt0, -+ &env->active_fpu.fp_status), 0)) -+FOP_CONDN_D(sun, (float64_unordered(fdt1, fdt0, -+ &env->active_fpu.fp_status))) -+FOP_CONDN_D(seq, (float64_eq(fdt0, fdt1, -+ &env->active_fpu.fp_status))) -+FOP_CONDN_D(sueq, (float64_unordered(fdt1, fdt0, -+ &env->active_fpu.fp_status) -+ || float64_eq(fdt0, fdt1, -+ &env->active_fpu.fp_status))) -+FOP_CONDN_D(slt, (float64_lt(fdt0, fdt1, -+ &env->active_fpu.fp_status))) -+FOP_CONDN_D(sult, (float64_unordered(fdt1, fdt0, -+ &env->active_fpu.fp_status) -+ || float64_lt(fdt0, fdt1, -+ &env->active_fpu.fp_status))) -+FOP_CONDN_D(sle, (float64_le(fdt0, fdt1, -+ &env->active_fpu.fp_status))) -+FOP_CONDN_D(sule, (float64_unordered(fdt1, fdt0, -+ &env->active_fpu.fp_status) -+ || float64_le(fdt0, fdt1, -+ &env->active_fpu.fp_status))) -+FOP_CONDN_D(or, (float64_le_quiet(fdt1, fdt0, -+ &env->active_fpu.fp_status) -+ || float64_le_quiet(fdt0, fdt1, -+ &env->active_fpu.fp_status))) -+FOP_CONDN_D(une, (float64_unordered_quiet(fdt1, fdt0, -+ &env->active_fpu.fp_status) -+ || float64_lt_quiet(fdt1, fdt0, -+ &env->active_fpu.fp_status) -+ || float64_lt_quiet(fdt0, fdt1, -+ &env->active_fpu.fp_status))) -+FOP_CONDN_D(ne, (float64_lt_quiet(fdt1, fdt0, -+ &env->active_fpu.fp_status) -+ || float64_lt_quiet(fdt0, fdt1, -+ &env->active_fpu.fp_status))) -+FOP_CONDN_D(sor, (float64_le(fdt1, fdt0, -+ &env->active_fpu.fp_status) -+ || float64_le(fdt0, fdt1, -+ &env->active_fpu.fp_status))) -+FOP_CONDN_D(sune, (float64_unordered(fdt1, fdt0, -+ &env->active_fpu.fp_status) -+ || float64_lt(fdt1, fdt0, -+ &env->active_fpu.fp_status) -+ || float64_lt(fdt0, fdt1, -+ &env->active_fpu.fp_status))) -+FOP_CONDN_D(sne, (float64_lt(fdt1, fdt0, -+ &env->active_fpu.fp_status) -+ || float64_lt(fdt0, fdt1, -+ &env->active_fpu.fp_status))) -+ -+#define FOP_CONDN_S(op, cond) \ -+uint32_t helper_cmp_s_ ## op(CPULOONGARCHState *env, uint32_t fst0, \ -+ uint32_t fst1) \ -+{ \ -+ uint64_t c; \ -+ c = cond; \ -+ update_fcsr0(env, GETPC()); \ -+ if (c) { \ -+ return -1; \ -+ } else { \ -+ return 0; \ -+ } \ -+} -+ -+/* -+ * NOTE: the comma operator will make "cond" to eval to false, -+ * but float32_unordered_quiet() is still called. -+ */ -+FOP_CONDN_S(af, (float32_unordered_quiet(fst1, fst0, -+ &env->active_fpu.fp_status), 0)) -+FOP_CONDN_S(un, (float32_unordered_quiet(fst1, fst0, -+ &env->active_fpu.fp_status))) -+FOP_CONDN_S(eq, (float32_eq_quiet(fst0, fst1, -+ &env->active_fpu.fp_status))) -+FOP_CONDN_S(ueq, (float32_unordered_quiet(fst1, fst0, -+ &env->active_fpu.fp_status) -+ || float32_eq_quiet(fst0, fst1, -+ &env->active_fpu.fp_status))) -+FOP_CONDN_S(lt, (float32_lt_quiet(fst0, fst1, -+ &env->active_fpu.fp_status))) -+FOP_CONDN_S(ult, (float32_unordered_quiet(fst1, fst0, -+ &env->active_fpu.fp_status) -+ || float32_lt_quiet(fst0, fst1, -+ &env->active_fpu.fp_status))) -+FOP_CONDN_S(le, (float32_le_quiet(fst0, fst1, -+ &env->active_fpu.fp_status))) -+FOP_CONDN_S(ule, (float32_unordered_quiet(fst1, fst0, -+ &env->active_fpu.fp_status) -+ || float32_le_quiet(fst0, fst1, -+ &env->active_fpu.fp_status))) -+/* -+ * NOTE: the comma operator will make "cond" to eval to false, -+ * but float32_unordered() is still called. -+ */ -+FOP_CONDN_S(saf, (float32_unordered(fst1, fst0, -+ &env->active_fpu.fp_status), 0)) -+FOP_CONDN_S(sun, (float32_unordered(fst1, fst0, -+ &env->active_fpu.fp_status))) -+FOP_CONDN_S(seq, (float32_eq(fst0, fst1, -+ &env->active_fpu.fp_status))) -+FOP_CONDN_S(sueq, (float32_unordered(fst1, fst0, -+ &env->active_fpu.fp_status) -+ || float32_eq(fst0, fst1, -+ &env->active_fpu.fp_status))) -+FOP_CONDN_S(slt, (float32_lt(fst0, fst1, -+ &env->active_fpu.fp_status))) -+FOP_CONDN_S(sult, (float32_unordered(fst1, fst0, -+ &env->active_fpu.fp_status) -+ || float32_lt(fst0, fst1, -+ &env->active_fpu.fp_status))) -+FOP_CONDN_S(sle, (float32_le(fst0, fst1, -+ &env->active_fpu.fp_status))) -+FOP_CONDN_S(sule, (float32_unordered(fst1, fst0, -+ &env->active_fpu.fp_status) -+ || float32_le(fst0, fst1, -+ &env->active_fpu.fp_status))) -+FOP_CONDN_S(or, (float32_le_quiet(fst1, fst0, -+ &env->active_fpu.fp_status) -+ || float32_le_quiet(fst0, fst1, -+ &env->active_fpu.fp_status))) -+FOP_CONDN_S(une, (float32_unordered_quiet(fst1, fst0, -+ &env->active_fpu.fp_status) -+ || float32_lt_quiet(fst1, fst0, -+ &env->active_fpu.fp_status) -+ || float32_lt_quiet(fst0, fst1, -+ &env->active_fpu.fp_status))) -+FOP_CONDN_S(ne, (float32_lt_quiet(fst1, fst0, -+ &env->active_fpu.fp_status) -+ || float32_lt_quiet(fst0, fst1, -+ &env->active_fpu.fp_status))) -+FOP_CONDN_S(sor, (float32_le(fst1, fst0, -+ &env->active_fpu.fp_status) -+ || float32_le(fst0, fst1, -+ &env->active_fpu.fp_status))) -+FOP_CONDN_S(sune, (float32_unordered(fst1, fst0, -+ &env->active_fpu.fp_status) -+ || float32_lt(fst1, fst0, -+ &env->active_fpu.fp_status) -+ || float32_lt(fst0, fst1, -+ &env->active_fpu.fp_status))) -+FOP_CONDN_S(sne, (float32_lt(fst1, fst0, -+ &env->active_fpu.fp_status) -+ || float32_lt(fst0, fst1, -+ &env->active_fpu.fp_status))) -+ -+uint32_t helper_float_logb_s(CPULOONGARCHState *env, uint32_t fst0) -+{ -+ uint32_t wt2; -+ -+ wt2 = float32_log2(fst0, &env->active_fpu.fp_status); -+ update_fcsr0(env, GETPC()); -+ return wt2; -+} -+ -+uint64_t helper_float_logb_d(CPULOONGARCHState *env, uint64_t fdt0) -+{ -+ uint64_t dt2; -+ -+ dt2 = float64_log2(fdt0, &env->active_fpu.fp_status); -+ update_fcsr0(env, GETPC()); -+ return dt2; -+} -+ -+target_ulong helper_fsel(CPULOONGARCHState *env, target_ulong fj, -+ target_ulong fk, uint32_t ca) -+{ -+ if (env->active_fpu.cf[ca & 0x7]) { -+ return fk; -+ } else { -+ return fj; -+ } -+} -diff --git a/target/loongarch64/fpu_helper.h b/target/loongarch64/fpu_helper.h -new file mode 100644 -index 0000000000..b6898c2e91 ---- /dev/null -+++ b/target/loongarch64/fpu_helper.h -@@ -0,0 +1,129 @@ -+/* loongarch internal definitions and helpers -+ * -+ * This work is licensed under the terms of the GNU GPL, version 2 or later. -+ * See the COPYING file in the top-level directory. -+ */ -+ -+#ifndef LOONGARCH_FPU_H -+#define LOONGARCH_FPU_H -+ -+#include "cpu-csr.h" -+ -+ -+extern const struct loongarch_def_t loongarch_defs[]; -+extern const int loongarch_defs_number; -+ -+enum CPULSXDataFormat { -+ DF_BYTE = 0, -+ DF_HALF, -+ DF_WORD, -+ DF_DOUBLE, -+ DF_QUAD -+}; -+ -+void loongarch_cpu_do_interrupt(CPUState *cpu); -+bool loongarch_cpu_exec_interrupt(CPUState *cpu, int int_req); -+void loongarch_cpu_do_unaligned_access(CPUState *cpu, vaddr addr, -+ MMUAccessType access_type, -+ int mmu_idx, uintptr_t retaddr) QEMU_NORETURN; -+ -+#if !defined(CONFIG_USER_ONLY) -+ -+typedef struct r4k_tlb_t r4k_tlb_t; -+struct r4k_tlb_t { -+ target_ulong VPN; -+ uint32_t PageMask; -+ uint16_t ASID; -+ unsigned int G:1; -+ unsigned int C0:3; -+ unsigned int C1:3; -+ unsigned int V0:1; -+ unsigned int V1:1; -+ unsigned int D0:1; -+ unsigned int D1:1; -+ unsigned int XI0:1; -+ unsigned int XI1:1; -+ unsigned int RI0:1; -+ unsigned int RI1:1; -+ unsigned int EHINV:1; -+ uint64_t PPN[2]; -+}; -+ -+int no_mmu_map_address(CPULOONGARCHState *env, hwaddr *physical, int *prot, -+ target_ulong address, int rw, int access_type); -+int fixed_mmu_map_address(CPULOONGARCHState *env, hwaddr *physical, int *prot, -+ target_ulong address, int rw, int access_type); -+int r4k_map_address(CPULOONGARCHState *env, hwaddr *physical, int *prot, -+ target_ulong address, int rw, int access_type); -+ -+/* loongarch 3a5000 tlb helper function : lisa csr */ -+int ls3a5k_map_address(CPULOONGARCHState *env, hwaddr *physical, -+ int *prot, target_ulong address, -+ int rw, int access_type); -+void ls3a5k_helper_tlbwr(CPULOONGARCHState *env); -+void ls3a5k_helper_tlbfill(CPULOONGARCHState *env); -+void ls3a5k_helper_tlbsrch(CPULOONGARCHState *env); -+void ls3a5k_helper_tlbrd(CPULOONGARCHState *env); -+void ls3a5k_helper_tlbclr(CPULOONGARCHState *env); -+void ls3a5k_helper_tlbflush(CPULOONGARCHState *env); -+void ls3a5k_invalidate_tlb(CPULOONGARCHState *env, int idx); -+void ls3a5k_helper_invtlb(CPULOONGARCHState *env, target_ulong addr, -+ target_ulong info, int op); -+void ls3a5k_flush_vtlb(CPULOONGARCHState *env); -+void ls3a5k_flush_ftlb(CPULOONGARCHState *env); -+/*void loongarch_cpu_unassigned_access(CPUState *cpu, hwaddr addr, -+ bool is_write, bool is_exec, int unused, -+ unsigned size); -+*/ -+hwaddr cpu_loongarch_translate_address(CPULOONGARCHState *env, target_ulong address, -+ int rw); -+#endif -+ -+#define cpu_signal_handler cpu_loongarch_signal_handler -+ -+ -+static inline bool cpu_loongarch_hw_interrupts_enabled(CPULOONGARCHState *env) -+{ -+ bool ret = 0; -+ -+ ret = env->CSR_CRMD & (1 << CSR_CRMD_IE_SHIFT); -+ -+ return ret; -+} -+ -+ -+void loongarch_tcg_init(void); -+ -+ -+/* helper.c */ -+bool loongarch_cpu_tlb_fill(CPUState *cs, vaddr address, int size, -+ MMUAccessType access_type, int mmu_idx, -+ bool probe, uintptr_t retaddr); -+ -+/* op_helper.c */ -+uint32_t float_class_s(uint32_t arg, float_status *fst); -+uint64_t float_class_d(uint64_t arg, float_status *fst); -+ -+int ieee_ex_to_loongarch(int xcpt); -+void update_pagemask(CPULOONGARCHState *env, target_ulong arg1, int32_t *pagemask); -+ -+void cpu_loongarch_tlb_flush(CPULOONGARCHState *env); -+void sync_c0_status(CPULOONGARCHState *env, CPULOONGARCHState *cpu, int tc); -+ -+void QEMU_NORETURN do_raise_exception_err(CPULOONGARCHState *env, uint32_t exception, -+ int error_code, uintptr_t pc); -+int loongarch_read_qxfer(CPUState *cs, const char *annex, -+ uint8_t *read_buf, -+ unsigned long offset, unsigned long len); -+int loongarch_write_qxfer(CPUState *cs, const char *annex, -+ const uint8_t *write_buf, -+ unsigned long offset, unsigned long len); -+ -+static inline void QEMU_NORETURN do_raise_exception(CPULOONGARCHState *env, -+ uint32_t exception, -+ uintptr_t pc) -+{ -+ do_raise_exception_err(env, exception, 0, pc); -+} -+ -+#endif -diff --git a/target/loongarch64/gdbstub.c b/target/loongarch64/gdbstub.c -new file mode 100644 -index 0000000000..4013178f45 ---- /dev/null -+++ b/target/loongarch64/gdbstub.c -@@ -0,0 +1,109 @@ -+/* -+ * LOONGARCH gdb server stub -+ * -+ * Copyright (c) 2003-2005 Fabrice Bellard -+ * Copyright (c) 2013 SUSE LINUX Products GmbH -+ * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2 of the License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library; if not, see . -+ */ -+#include "qemu/osdep.h" -+#include "qemu-common.h" -+#include "cpu.h" -+#include "internal.h" -+#include "exec/gdbstub.h" -+#ifdef CONFIG_TCG -+#include "exec/helper-proto.h" -+#endif -+int loongarch_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n) -+{ -+ LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); -+ CPULOONGARCHState *env = &cpu->env; -+ -+ if (0 <= n && n < 32) { -+ return gdb_get_regl(mem_buf, env->active_tc.gpr[n]); -+ } else if (n == 32) { -+ return gdb_get_regl(mem_buf, env->active_tc.PC); -+ } -+ return 0; -+} -+ -+int loongarch_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) -+{ -+ LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); -+ CPULOONGARCHState *env = &cpu->env; -+ target_ulong tmp = ldtul_p(mem_buf); -+ -+ if (0 <= n && n < 32) { -+ return env->active_tc.gpr[n] = tmp, sizeof(target_ulong); -+ } else if (n == 32) { -+ return env->active_tc.PC = tmp, sizeof(target_ulong); -+ } -+ return 0; -+} -+ -+static int loongarch_gdb_get_fpu(CPULOONGARCHState *env, GByteArray *mem_buf, int n) -+{ -+ if (0 <= n && n < 32) { -+ return gdb_get_reg64(mem_buf, env->active_fpu.fpr[n].d); -+ } else if (32 <= n && n < 40) { -+ return gdb_get_reg8(mem_buf, env->active_fpu.cf[n - 32]); -+ } else if (n == 40) { -+ return gdb_get_reg32(mem_buf, env->active_fpu.fcsr0); -+ } -+ return 0; -+} -+ -+static int loongarch_gdb_set_fpu(CPULOONGARCHState *env, uint8_t *mem_buf, int n) -+{ -+ if (0 <= n && n < 32) { -+ return env->active_fpu.fpr[n].d = ldq_p(mem_buf), 8; -+ } else if (32 <= n && n < 40) { -+ return env->active_fpu.cf[n - 32] = ldub_p(mem_buf), 1; -+ } else if (n == 40) { -+ return env->active_fpu.fcsr0 = ldl_p(mem_buf), 4; -+ } -+ return 0; -+} -+ -+void loongarch_cpu_register_gdb_regs_for_features(CPUState *cs) -+{ -+ gdb_register_coprocessor(cs, loongarch_gdb_get_fpu, loongarch_gdb_set_fpu, -+ 41, "loongarch-fpu64.xml", 0); -+} -+ -+#ifdef CONFIG_TCG -+int loongarch_read_qxfer(CPUState *cs, const char *annex, uint8_t *read_buf, -+ unsigned long offset, unsigned long len) -+{ -+ if (strncmp(annex, "cpucfg", sizeof("cpucfg") - 1) == 0) { -+ if (offset % 4 != 0 || len % 4 != 0) { -+ return 0; -+ } -+ -+ size_t i; -+ for (i = offset; i < offset + len; i += 4) -+ ((uint32_t *)read_buf)[(i - offset) / 4] = -+ helper_cpucfg(&(LOONGARCH_CPU(cs)->env), i / 4); -+ return 32 * 4; -+ } -+ return 0; -+} -+ -+int loongarch_write_qxfer(CPUState *cs, const char *annex, -+ const uint8_t *write_buf, unsigned long offset, -+ unsigned long len) -+{ -+ return 0; -+} -+#endif -diff --git a/target/loongarch64/helper.c b/target/loongarch64/helper.c -new file mode 100644 -index 0000000000..841240e57b ---- /dev/null -+++ b/target/loongarch64/helper.c -@@ -0,0 +1,727 @@ -+/* -+ * LOONGARCH emulation helpers for qemu. -+ * -+ * Copyright (c) 2004-2005 Jocelyn Mayer -+ * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2 of the License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library; if not, see . -+ */ -+#include "qemu/osdep.h" -+#include "cpu.h" -+#include "internal.h" -+#include "exec/exec-all.h" -+#include "exec/cpu_ldst.h" -+#include "exec/log.h" -+#include "hw/loongarch/cpudevs.h" -+ -+ -+#if !defined(CONFIG_USER_ONLY) -+ -+static int ls3a5k_map_address_tlb_entry( -+ CPULOONGARCHState *env, -+ hwaddr *physical, -+ int *prot, -+ target_ulong address, -+ int rw, -+ int access_type, -+ ls3a5k_tlb_t *tlb) -+{ -+ uint64_t mask = tlb->PageMask; -+ int n = !!(address & mask & ~(mask >> 1)); -+ uint32_t plv = env->CSR_CRMD & CSR_CRMD_PLV; -+ -+ /* Check access rights */ -+ if (!(n ? tlb->V1 : tlb->V0)) { -+ return TLBRET_INVALID; -+ } -+ -+ if (rw == MMU_INST_FETCH && (n ? tlb->XI1 : tlb->XI0)) { -+ return TLBRET_XI; -+ } -+ -+ if (rw == MMU_DATA_LOAD && (n ? tlb->RI1 : tlb->RI0)) { -+ return TLBRET_RI; -+ } -+ -+ if (plv > (n ? tlb->PLV1 : tlb->PLV0)) { -+ return TLBRET_PE; -+ } -+ -+ if (rw != MMU_DATA_STORE || (n ? tlb->WE1 : tlb->WE0)) { -+ /* PPN address -+ * 4 KB: [47:13] [12;0] -+ * 16 KB: [47:15] [14:0] -+ */ -+ if (n) { -+ *physical = tlb->PPN1 | (address & (mask >> 1)); -+ } else { -+ *physical = tlb->PPN0 | (address & (mask >> 1)); -+ } -+ *prot = PAGE_READ; -+ if (n ? tlb->WE1 : tlb->WE0) { -+ *prot |= PAGE_WRITE; -+ } -+ if (!(n ? tlb->XI1 : tlb->XI0)) { -+ *prot |= PAGE_EXEC; -+ } -+ return TLBRET_MATCH; -+ } -+ -+ return TLBRET_DIRTY; -+} -+ -+/* Loongarch 3A5K -style MMU emulation */ -+int ls3a5k_map_address(CPULOONGARCHState *env, hwaddr *physical, int *prot, -+ target_ulong address, int rw, int access_type) -+{ -+ uint16_t asid = env->CSR_ASID & 0x3ff; -+ int i; -+ ls3a5k_tlb_t *tlb; -+ -+ int ftlb_size = env->tlb->mmu.ls3a5k.ftlb_size; -+ int vtlb_size = env->tlb->mmu.ls3a5k.vtlb_size; -+ -+ int ftlb_idx; -+ -+ uint64_t mask; -+ uint64_t vpn; /* address to map */ -+ uint64_t tag; /* address in TLB entry */ -+ -+ /* search VTLB */ -+ for (i = ftlb_size; i < ftlb_size + vtlb_size; ++i) { -+ tlb = &env->tlb->mmu.ls3a5k.tlb[i]; -+ mask = tlb->PageMask; -+ -+ vpn = address & 0xffffffffe000 & ~mask; -+ tag = tlb->VPN & ~mask; -+ -+ if ((tlb->G == 1 || tlb->ASID == asid) -+ && vpn == tag -+ && tlb->EHINV != 1) -+ { -+ return ls3a5k_map_address_tlb_entry(env, physical, prot, -+ address, rw, access_type, tlb); -+ } -+ } -+ -+ if (ftlb_size == 0) { -+ return TLBRET_NOMATCH; -+ } -+ -+ /* search FTLB */ -+ mask = env->tlb->mmu.ls3a5k.ftlb_mask; -+ vpn = address & 0xffffffffe000 & ~mask; -+ -+ ftlb_idx = (address & 0xffffffffc000) >> 15; /* 16 KB */ -+ ftlb_idx = ftlb_idx & 0xff; /* [0,255] */ -+ -+ for (i = 0; i < 8; ++i) { -+ /* ---------- set 0 1 2 ... 7 -+ * ftlb_idx ----------------------------------- -+ * 0 | 0 1 2 ... 7 -+ * 1 | 8 9 10 ... 15 -+ * 2 | 16 17 18 ... 23 -+ * ... | -+ * 255 | 2040 2041 2042 ... 2047 -+ */ -+ tlb = &env->tlb->mmu.ls3a5k.tlb[ftlb_idx * 8 + i]; -+ tag = tlb->VPN & ~mask; -+ -+ if ((tlb->G == 1 || tlb->ASID == asid) -+ && vpn == tag -+ && tlb->EHINV != 1) -+ { -+ return ls3a5k_map_address_tlb_entry(env, physical, prot, -+ address, rw, access_type, tlb); -+ } -+ } -+ -+ return TLBRET_NOMATCH; -+} -+ -+static int get_physical_address(CPULOONGARCHState *env, hwaddr *physical, -+ int *prot, target_ulong real_address, -+ int rw, int access_type, int mmu_idx) -+{ -+ int user_mode = mmu_idx == LARCH_HFLAG_UM; -+ int kernel_mode = !user_mode; -+ unsigned plv, base_c, base_v, tmp; -+ -+ /* effective address (modified for KVM T&E kernel segments) */ -+ target_ulong address = real_address; -+ -+ /* Check PG */ -+ if (!(env->CSR_CRMD & CSR_CRMD_PG)) { -+ /* DA mode */ -+ *physical = address & 0xffffffffffffUL; -+ *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; -+ return TLBRET_MATCH; -+ } -+ -+ plv = kernel_mode | (user_mode << 3); -+ base_v = address >> CSR_DMW_BASE_SH; -+ /* Check direct map window 0 */ -+ base_c = env->CSR_DMWIN0 >> CSR_DMW_BASE_SH; -+ if ((plv & env->CSR_DMWIN0) && (base_c == base_v)) { -+ *physical = dmwin_va2pa(address); -+ *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; -+ return TLBRET_MATCH; -+ } -+ /* Check direct map window 1 */ -+ base_c = env->CSR_DMWIN1 >> CSR_DMW_BASE_SH; -+ if ((plv & env->CSR_DMWIN1) && (base_c == base_v)) { -+ *physical = dmwin_va2pa(address); -+ *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; -+ return TLBRET_MATCH; -+ } -+ /* Check valid extension */ -+ tmp = address >> 47; -+ if (!(tmp == 0 || tmp == 0x1ffff)) { -+ return TLBRET_BADADDR; -+ } -+ /* mapped address */ -+ return env->tlb->map_address(env, physical, prot, real_address, rw, -+ access_type); -+} -+ -+void cpu_loongarch_tlb_flush(CPULOONGARCHState *env) -+{ -+ LOONGARCHCPU *cpu = loongarch_env_get_cpu(env); -+ -+ /* Flush qemu's TLB and discard all shadowed entries. */ -+ tlb_flush(CPU(cpu)); -+ env->tlb->tlb_in_use = env->tlb->nb_tlb; -+} -+#endif -+ -+static void raise_mmu_exception(CPULOONGARCHState *env, target_ulong address, -+ int rw, int tlb_error) -+{ -+ CPUState *cs = CPU(loongarch_env_get_cpu(env)); -+ int exception = 0, error_code = 0; -+ -+ if (rw == MMU_INST_FETCH) { -+ error_code |= EXCP_INST_NOTAVAIL; -+ } -+ -+ switch (tlb_error) { -+ default: -+ case TLBRET_BADADDR: -+ /* Reference to kernel address from user mode or supervisor mode */ -+ /* Reference to supervisor address from user mode */ -+ if (rw == MMU_DATA_STORE) { -+ exception = EXCP_AdES; -+ } else { -+ exception = EXCP_AdEL; -+ } -+ break; -+ case TLBRET_NOMATCH: -+ /* No TLB match for a mapped address */ -+ if (rw == MMU_DATA_STORE) { -+ exception = EXCP_TLBS; -+ } else { -+ exception = EXCP_TLBL; -+ } -+ error_code |= EXCP_TLB_NOMATCH; -+ break; -+ case TLBRET_INVALID: -+ /* TLB match with no valid bit */ -+ if (rw == MMU_DATA_STORE) { -+ exception = EXCP_TLBS; -+ } else { -+ exception = EXCP_TLBL; -+ } -+ break; -+ case TLBRET_DIRTY: -+ /* TLB match but 'D' bit is cleared */ -+ exception = EXCP_LTLBL; -+ break; -+ case TLBRET_XI: -+ /* Execute-Inhibit Exception */ -+ exception = EXCP_TLBXI; -+ break; -+ case TLBRET_RI: -+ /* Read-Inhibit Exception */ -+ exception = EXCP_TLBRI; -+ break; -+ case TLBRET_PE: -+ /* Privileged Exception */ -+ exception = EXCP_TLBPE; -+ break; -+ } -+ -+ if (env->insn_flags & INSN_LOONGARCH) { -+ if (tlb_error == TLBRET_NOMATCH) { -+ env->CSR_TLBRBADV = address; -+ env->CSR_TLBREHI = address & (TARGET_PAGE_MASK << 1); -+ cs->exception_index = exception; -+ env->error_code = error_code; -+ return; -+ } -+ } -+ -+ /* Raise exception */ -+ env->CSR_BADV = address; -+ cs->exception_index = exception; -+ env->error_code = error_code; -+ -+ if (env->insn_flags & INSN_LOONGARCH) { -+ env->CSR_TLBEHI = address & (TARGET_PAGE_MASK << 1); -+ } -+} -+ -+bool loongarch_cpu_tlb_fill(CPUState *cs, vaddr address, int size, -+ MMUAccessType access_type, int mmu_idx, -+ bool probe, uintptr_t retaddr) -+{ -+ LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); -+ CPULOONGARCHState *env = &cpu->env; -+#if !defined(CONFIG_USER_ONLY) -+ hwaddr physical; -+ int prot; -+ int loongarch_access_type; -+#endif -+ int ret = TLBRET_BADADDR; -+ -+ qemu_log_mask(CPU_LOG_MMU, -+ "%s pc " TARGET_FMT_lx " ad %" VADDR_PRIx " mmu_idx %d\n", -+ __func__, env->active_tc.PC, address, mmu_idx); -+ -+ /* data access */ -+#if !defined(CONFIG_USER_ONLY) -+ /* XXX: put correct access by using cpu_restore_state() correctly */ -+ loongarch_access_type = ACCESS_INT; -+ ret = get_physical_address(env, &physical, &prot, address, -+ access_type, loongarch_access_type, mmu_idx); -+ switch (ret) { -+ case TLBRET_MATCH: -+ qemu_log_mask(CPU_LOG_MMU, -+ "%s address=%" VADDR_PRIx " physical " TARGET_FMT_plx -+ " prot %d asid %ld pc 0x%lx\n", -+ __func__, address, physical, prot, -+ env->CSR_ASID, env->active_tc.PC); -+ break; -+ default: -+ qemu_log_mask(CPU_LOG_MMU, -+ "%s address=%" VADDR_PRIx " ret %d asid %ld pc 0x%lx\n", -+ __func__, address, ret, env->CSR_ASID, env->active_tc.PC); -+ break; -+ } -+ if (ret == TLBRET_MATCH) { -+ tlb_set_page(cs, address & TARGET_PAGE_MASK, -+ physical & TARGET_PAGE_MASK, prot | PAGE_EXEC, -+ mmu_idx, TARGET_PAGE_SIZE); -+ ret = true; -+ } -+ if (probe) { -+ return false; -+ } -+#endif -+ -+ raise_mmu_exception(env, address, access_type, ret); -+ do_raise_exception_err(env, cs->exception_index, env->error_code, retaddr); -+} -+ -+#if !defined(CONFIG_USER_ONLY) -+hwaddr cpu_loongarch_translate_address(CPULOONGARCHState *env, -+ target_ulong address, int rw) -+{ -+ hwaddr physical; -+ int prot; -+ int access_type; -+ int ret = 0; -+ -+ /* data access */ -+ access_type = ACCESS_INT; -+ ret = get_physical_address(env, &physical, &prot, address, rw, access_type, -+ cpu_mmu_index(env, false)); -+ if (ret != TLBRET_MATCH) { -+ raise_mmu_exception(env, address, rw, ret); -+ return -1LL; -+ } else { -+ return physical; -+ } -+} -+ -+static const char * const excp_names[EXCP_LAST + 1] = { -+ [EXCP_RESET] = "reset", -+ [EXCP_SRESET] = "soft reset", -+ [EXCP_NMI] = "non-maskable interrupt", -+ [EXCP_EXT_INTERRUPT] = "interrupt", -+ [EXCP_AdEL] = "address error load", -+ [EXCP_AdES] = "address error store", -+ [EXCP_TLBF] = "TLB refill", -+ [EXCP_IBE] = "instruction bus error", -+ [EXCP_SYSCALL] = "syscall", -+ [EXCP_BREAK] = "break", -+ [EXCP_FPDIS] = "float unit unusable", -+ [EXCP_LSXDIS] = "vector128 unusable", -+ [EXCP_LASXDIS] = "vector256 unusable", -+ [EXCP_RI] = "reserved instruction", -+ [EXCP_OVERFLOW] = "arithmetic overflow", -+ [EXCP_TRAP] = "trap", -+ [EXCP_FPE] = "floating point", -+ [EXCP_LTLBL] = "TLB modify", -+ [EXCP_TLBL] = "TLB load", -+ [EXCP_TLBS] = "TLB store", -+ [EXCP_DBE] = "data bus error", -+ [EXCP_TLBXI] = "TLB execute-inhibit", -+ [EXCP_TLBRI] = "TLB read-inhibit", -+ [EXCP_TLBPE] = "TLB priviledged error", -+}; -+#endif -+ -+target_ulong exception_resume_pc(CPULOONGARCHState *env) -+{ -+ target_ulong bad_pc; -+ -+ bad_pc = env->active_tc.PC; -+ if (env->hflags & LARCH_HFLAG_BMASK) { -+ /* If the exception was raised from a delay slot, come back to -+ the jump. */ -+ bad_pc -= 4; -+ } -+ -+ return bad_pc; -+} -+ -+#if !defined(CONFIG_USER_ONLY) -+static void set_hflags_for_handler (CPULOONGARCHState *env) -+{ -+ /* Exception handlers are entered in 32-bit mode. */ -+} -+ -+static inline void set_badinstr_registers(CPULOONGARCHState *env) -+{ -+ if ((env->insn_flags & INSN_LOONGARCH)) { -+ env->CSR_BADI = cpu_ldl_code(env, env->active_tc.PC); -+ return; -+ } -+} -+#endif -+ -+static inline unsigned int get_vint_size(CPULOONGARCHState *env) -+{ -+ unsigned int size = 0; -+ -+ switch ((env->CSR_ECFG >> 16) & 0x7) { -+ case 0: -+ break; -+ case 1: -+ size = 2 * 4; /* #Insts * inst_size */ -+ break; -+ case 2: -+ size = 4 * 4; -+ break; -+ case 3: -+ size = 8 * 4; -+ break; -+ case 4: -+ size = 16 * 4; -+ break; -+ case 5: -+ size = 32 * 4; -+ break; -+ case 6: -+ size = 64 * 4; -+ break; -+ case 7: -+ size = 128 * 4; -+ break; -+ default: -+ printf("%s: unexpected value", __func__); -+ assert(0); -+ } -+ -+ return size; -+} -+ -+#define is_refill(cs, env) (((cs->exception_index == EXCP_TLBL) \ -+ || (cs->exception_index == EXCP_TLBS)) \ -+ && (env->error_code & EXCP_TLB_NOMATCH)) -+ -+void loongarch_cpu_do_interrupt(CPUState *cs) -+{ -+#if !defined(CONFIG_USER_ONLY) -+ LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); -+ CPULOONGARCHState *env = &cpu->env; -+ bool update_badinstr = 0; -+ int cause = -1; -+ const char *name; -+ -+ if (qemu_loglevel_mask(CPU_LOG_INT) -+ && cs->exception_index != EXCP_EXT_INTERRUPT) { -+ if (cs->exception_index < 0 || cs->exception_index > EXCP_LAST) { -+ name = "unknown"; -+ } else { -+ name = excp_names[cs->exception_index]; -+ } -+ -+ qemu_log("%s enter: PC " TARGET_FMT_lx " ERA " TARGET_FMT_lx -+ " TLBRERA 0x%016lx" " %s exception\n", __func__, -+ env->active_tc.PC, env->CSR_ERA, env->CSR_TLBRERA, name); -+ } -+ -+ switch (cs->exception_index) { -+ case EXCP_RESET: -+ cpu_reset(CPU(cpu)); -+ break; -+ case EXCP_NMI: -+ env->CSR_ERRERA = exception_resume_pc(env); -+ env->hflags &= ~LARCH_HFLAG_BMASK; -+ env->hflags |= LARCH_HFLAG_64; -+ env->hflags &= ~LARCH_HFLAG_AWRAP; -+ env->hflags &= ~(LARCH_HFLAG_KSU); -+ env->active_tc.PC = env->exception_base; -+ set_hflags_for_handler(env); -+ break; -+ case EXCP_EXT_INTERRUPT: -+ cause = 0; -+ goto set_ERA; -+ case EXCP_LTLBL: -+ cause = 1; -+ update_badinstr = !(env->error_code & EXCP_INST_NOTAVAIL); -+ goto set_ERA; -+ case EXCP_TLBL: -+ cause = 2; -+ update_badinstr = !(env->error_code & EXCP_INST_NOTAVAIL); -+ goto set_ERA; -+ case EXCP_TLBS: -+ cause = 3; -+ update_badinstr = 1; -+ goto set_ERA; -+ case EXCP_AdEL: -+ cause = 4; -+ update_badinstr = !(env->error_code & EXCP_INST_NOTAVAIL); -+ goto set_ERA; -+ case EXCP_AdES: -+ cause = 5; -+ update_badinstr = 1; -+ goto set_ERA; -+ case EXCP_IBE: -+ cause = 6; -+ goto set_ERA; -+ case EXCP_DBE: -+ cause = 7; -+ goto set_ERA; -+ case EXCP_SYSCALL: -+ cause = 8; -+ update_badinstr = 1; -+ goto set_ERA; -+ case EXCP_BREAK: -+ cause = 9; -+ update_badinstr = 1; -+ goto set_ERA; -+ case EXCP_RI: -+ cause = 10; -+ update_badinstr = 1; -+ goto set_ERA; -+ case EXCP_FPDIS: -+ case EXCP_LSXDIS: -+ case EXCP_LASXDIS: -+ cause = 11; -+ update_badinstr = 1; -+ goto set_ERA; -+ case EXCP_OVERFLOW: -+ cause = 12; -+ update_badinstr = 1; -+ goto set_ERA; -+ case EXCP_TRAP: -+ cause = 13; -+ update_badinstr = 1; -+ goto set_ERA; -+ case EXCP_FPE: -+ cause = 15; -+ update_badinstr = 1; -+ goto set_ERA; -+ case EXCP_TLBRI: -+ cause = 19; -+ update_badinstr = 1; -+ goto set_ERA; -+ case EXCP_TLBXI: -+ case EXCP_TLBPE: -+ cause = 20; -+ goto set_ERA; -+ set_ERA: -+ if (is_refill(cs, env)) { -+ env->CSR_TLBRERA = exception_resume_pc(env); -+ env->CSR_TLBRERA |= 1; -+ } else { -+ env->CSR_ERA = exception_resume_pc(env); -+ } -+ -+ if (update_badinstr) { -+ set_badinstr_registers(env); -+ } -+ env->hflags &= ~(LARCH_HFLAG_KSU); -+ -+ env->hflags &= ~LARCH_HFLAG_BMASK; -+ if (env->insn_flags & INSN_LOONGARCH) { -+ /* save PLV and IE */ -+ if (is_refill(cs, env)) { -+ env->CSR_TLBRPRMD &= (~0x7); -+ env->CSR_TLBRPRMD |= (env->CSR_CRMD & 0x7); -+ } else { -+ env->CSR_PRMD &= (~0x7); -+ env->CSR_PRMD |= (env->CSR_CRMD & 0x7); -+ } -+ -+ env->CSR_CRMD &= ~(0x7); -+ -+ switch (cs->exception_index) { -+ case EXCP_EXT_INTERRUPT: -+ break; -+ case EXCP_TLBL: -+ if (env->error_code & EXCP_INST_NOTAVAIL) { -+ cause = EXCCODE_TLBI; -+ } else { -+ cause = EXCCODE_TLBL; -+ } -+ break; -+ case EXCP_TLBS: -+ cause = EXCCODE_TLBS; -+ break; -+ case EXCP_LTLBL: -+ cause = EXCCODE_MOD; -+ break; -+ case EXCP_TLBRI: -+ cause = EXCCODE_TLBRI; -+ break; -+ case EXCP_TLBXI: -+ cause = EXCCODE_TLBXI; -+ break; -+ case EXCP_TLBPE: -+ cause = EXCCODE_TLBPE; -+ break; -+ case EXCP_AdEL: -+ case EXCP_AdES: -+ case EXCP_IBE: -+ case EXCP_DBE: -+ cause = EXCCODE_ADE; -+ break; -+ case EXCP_SYSCALL: -+ cause = EXCCODE_SYS; -+ break; -+ case EXCP_BREAK: -+ cause = EXCCODE_BP; -+ break; -+ case EXCP_RI: -+ cause = EXCCODE_RI; -+ break; -+ case EXCP_FPDIS: -+ cause = EXCCODE_FPDIS; -+ break; -+ case EXCP_LSXDIS: -+ cause = EXCCODE_LSXDIS; -+ break; -+ case EXCP_LASXDIS: -+ cause = EXCCODE_LASXDIS; -+ break; -+ case EXCP_FPE: -+ cause = EXCCODE_FPE; -+ break; -+ default: -+ printf("Error: exception(%d) '%s' has not been supported\n", -+ cs->exception_index, excp_names[cs->exception_index]); -+ abort(); -+ } -+ -+ uint32_t vec_size = get_vint_size(env); -+ env->active_tc.PC = env->CSR_EEPN; -+ env->active_tc.PC += cause * vec_size; -+ if (is_refill(cs, env)) { -+ /* TLB Refill */ -+ env->active_tc.PC = env->CSR_TLBRENT; -+ break; /* Do not modify excode */ -+ } -+ if (cs->exception_index == EXCP_EXT_INTERRUPT) { -+ /* Interrupt */ -+ uint32_t vector = 0; -+ uint32_t pending = env->CSR_ESTAT & CSR_ESTAT_IPMASK; -+ pending &= env->CSR_ECFG & CSR_ECFG_IPMASK; -+ -+ /* Find the highest-priority interrupt. */ -+ while (pending >>= 1) { -+ vector++; -+ } -+ env->active_tc.PC = env->CSR_EEPN + -+ (EXCODE_IP + vector) * vec_size; -+ if (qemu_loglevel_mask(CPU_LOG_INT)) { -+ qemu_log("%s: PC " TARGET_FMT_lx " ERA " TARGET_FMT_lx -+ " cause %d\n" " A " TARGET_FMT_lx " D " -+ TARGET_FMT_lx " vector = %d ExC %08lx ExS %08lx\n", -+ __func__, env->active_tc.PC, env->CSR_ERA, -+ cause, env->CSR_BADV, env->CSR_DERA, vector, -+ env->CSR_ECFG, env->CSR_ESTAT); -+ } -+ } -+ /* Excode */ -+ env->CSR_ESTAT = (env->CSR_ESTAT & ~(0x1f << CSR_ESTAT_EXC_SH)) | -+ (cause << CSR_ESTAT_EXC_SH); -+ } -+ set_hflags_for_handler(env); -+ break; -+ default: -+ abort(); -+ } -+ if (qemu_loglevel_mask(CPU_LOG_INT) -+ && cs->exception_index != EXCP_EXT_INTERRUPT) { -+ qemu_log("%s: PC " TARGET_FMT_lx " ERA 0x%08lx" " cause %d%s\n" -+ " ESTAT %08lx EXCFG 0x%08lx BADVA 0x%08lx BADI 0x%08lx \ -+ SYS_NUM %lu cpu %d asid 0x%lx" "\n", -+ __func__, env->active_tc.PC, -+ is_refill(cs, env) ? env->CSR_TLBRERA : env->CSR_ERA, -+ cause, -+ is_refill(cs, env) ? "(refill)" : "", -+ env->CSR_ESTAT, env->CSR_ECFG, -+ is_refill(cs, env) ? env->CSR_TLBRBADV : env->CSR_BADV, -+ env->CSR_BADI, env->active_tc.gpr[11], cs->cpu_index, -+ env->CSR_ASID -+ ); -+ } -+#endif -+ cs->exception_index = EXCP_NONE; -+} -+ -+bool loongarch_cpu_exec_interrupt(CPUState *cs, int interrupt_request) -+{ -+ if (interrupt_request & CPU_INTERRUPT_HARD) { -+ LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); -+ CPULOONGARCHState *env = &cpu->env; -+ -+ if (cpu_loongarch_hw_interrupts_enabled(env) && -+ cpu_loongarch_hw_interrupts_pending(env)) { -+ /* Raise it */ -+ cs->exception_index = EXCP_EXT_INTERRUPT; -+ env->error_code = 0; -+ loongarch_cpu_do_interrupt(cs); -+ return true; -+ } -+ } -+ return false; -+} -+ -+void QEMU_NORETURN do_raise_exception_err(CPULOONGARCHState *env, -+ uint32_t exception, -+ int error_code, -+ uintptr_t pc) -+{ -+ CPUState *cs = CPU(loongarch_env_get_cpu(env)); -+ -+ qemu_log_mask(CPU_LOG_INT, "%s: %d %d\n", -+ __func__, exception, error_code); -+ cs->exception_index = exception; -+ env->error_code = error_code; -+ -+ cpu_loop_exit_restore(cs, pc); -+} -diff --git a/target/loongarch64/helper.h b/target/loongarch64/helper.h -new file mode 100644 -index 0000000000..ff2026ed82 ---- /dev/null -+++ b/target/loongarch64/helper.h -@@ -0,0 +1,168 @@ -+DEF_HELPER_3(raise_exception_err, noreturn, env, i32, int) -+DEF_HELPER_2(raise_exception, noreturn, env, i32) -+DEF_HELPER_1(raise_exception_debug, noreturn, env) -+ -+#if 0 -+#ifndef CONFIG_USER_ONLY -+DEF_HELPER_3(ll, tl, env, tl, int) -+DEF_HELPER_3(lld, tl, env, tl, int) -+#endif -+#endif -+ -+DEF_HELPER_FLAGS_1(bitswap, TCG_CALL_NO_RWG_SE, tl, tl) -+DEF_HELPER_FLAGS_1(dbitswap, TCG_CALL_NO_RWG_SE, tl, tl) -+ -+DEF_HELPER_3(crc32, tl, tl, tl, i32) -+DEF_HELPER_3(crc32c, tl, tl, tl, i32) -+ -+#ifndef CONFIG_USER_ONLY -+/* LoongISA CSR register */ -+DEF_HELPER_2(csr_rdq, tl, env, i64) -+DEF_HELPER_3(csr_wrq, tl, env, tl, i64) -+DEF_HELPER_4(csr_xchgq, tl, env, tl, tl, i64) -+ -+#endif /* !CONFIG_USER_ONLY */ -+ -+/* CP1 functions */ -+DEF_HELPER_2(movfcsr2gr, tl, env, i32) -+DEF_HELPER_4(movgr2fcsr, void, env, tl, i32, i32) -+ -+DEF_HELPER_2(float_cvtd_s, i64, env, i32) -+DEF_HELPER_2(float_cvtd_w, i64, env, i32) -+DEF_HELPER_2(float_cvtd_l, i64, env, i64) -+DEF_HELPER_2(float_cvts_d, i32, env, i64) -+DEF_HELPER_2(float_cvts_w, i32, env, i32) -+DEF_HELPER_2(float_cvts_l, i32, env, i64) -+ -+DEF_HELPER_FLAGS_2(float_class_s, TCG_CALL_NO_RWG_SE, i32, env, i32) -+DEF_HELPER_FLAGS_2(float_class_d, TCG_CALL_NO_RWG_SE, i64, env, i64) -+ -+#define FOP_PROTO(op) \ -+DEF_HELPER_4(float_ ## op ## _s, i32, env, i32, i32, i32) \ -+DEF_HELPER_4(float_ ## op ## _d, i64, env, i64, i64, i64) -+FOP_PROTO(maddf) -+FOP_PROTO(msubf) -+FOP_PROTO(nmaddf) -+FOP_PROTO(nmsubf) -+#undef FOP_PROTO -+ -+#define FOP_PROTO(op) \ -+DEF_HELPER_3(float_ ## op ## _s, i32, env, i32, i32) \ -+DEF_HELPER_3(float_ ## op ## _d, i64, env, i64, i64) -+FOP_PROTO(max) -+FOP_PROTO(maxa) -+FOP_PROTO(min) -+FOP_PROTO(mina) -+#undef FOP_PROTO -+ -+#define FOP_PROTO(op) \ -+DEF_HELPER_2(float_ ## op ## _l_s, i64, env, i32) \ -+DEF_HELPER_2(float_ ## op ## _l_d, i64, env, i64) \ -+DEF_HELPER_2(float_ ## op ## _w_s, i32, env, i32) \ -+DEF_HELPER_2(float_ ## op ## _w_d, i32, env, i64) -+FOP_PROTO(cvt) -+FOP_PROTO(round) -+FOP_PROTO(trunc) -+FOP_PROTO(ceil) -+FOP_PROTO(floor) -+#undef FOP_PROTO -+ -+#define FOP_PROTO(op) \ -+DEF_HELPER_2(float_ ## op ## _s, i32, env, i32) \ -+DEF_HELPER_2(float_ ## op ## _d, i64, env, i64) -+FOP_PROTO(sqrt) -+FOP_PROTO(rsqrt) -+FOP_PROTO(recip) -+FOP_PROTO(rint) -+#undef FOP_PROTO -+ -+#define FOP_PROTO(op) \ -+DEF_HELPER_1(float_ ## op ## _s, i32, i32) \ -+DEF_HELPER_1(float_ ## op ## _d, i64, i64) -+FOP_PROTO(abs) -+FOP_PROTO(chs) -+#undef FOP_PROTO -+ -+#define FOP_PROTO(op) \ -+DEF_HELPER_3(float_ ## op ## _s, i32, env, i32, i32) \ -+DEF_HELPER_3(float_ ## op ## _d, i64, env, i64, i64) -+FOP_PROTO(add) -+FOP_PROTO(sub) -+FOP_PROTO(mul) -+FOP_PROTO(div) -+#undef FOP_PROTO -+ -+#define FOP_PROTO(op) \ -+DEF_HELPER_3(cmp_d_ ## op, i64, env, i64, i64) \ -+DEF_HELPER_3(cmp_s_ ## op, i32, env, i32, i32) -+FOP_PROTO(af) -+FOP_PROTO(un) -+FOP_PROTO(eq) -+FOP_PROTO(ueq) -+FOP_PROTO(lt) -+FOP_PROTO(ult) -+FOP_PROTO(le) -+FOP_PROTO(ule) -+FOP_PROTO(saf) -+FOP_PROTO(sun) -+FOP_PROTO(seq) -+FOP_PROTO(sueq) -+FOP_PROTO(slt) -+FOP_PROTO(sult) -+FOP_PROTO(sle) -+FOP_PROTO(sule) -+FOP_PROTO(or) -+FOP_PROTO(une) -+FOP_PROTO(ne) -+FOP_PROTO(sor) -+FOP_PROTO(sune) -+FOP_PROTO(sne) -+#undef FOP_PROTO -+ -+/* Special functions */ -+#ifndef CONFIG_USER_ONLY -+DEF_HELPER_1(tlbwr, void, env) -+DEF_HELPER_1(tlbfill, void, env) -+DEF_HELPER_1(tlbsrch, void, env) -+DEF_HELPER_1(tlbrd, void, env) -+DEF_HELPER_1(tlbclr, void, env) -+DEF_HELPER_1(tlbflush, void, env) -+DEF_HELPER_4(invtlb, void, env, tl, tl, tl) -+DEF_HELPER_1(ertn, void, env) -+DEF_HELPER_5(lddir, void, env, tl, tl, tl, i32) -+DEF_HELPER_4(ldpte, void, env, tl, tl, i32) -+DEF_HELPER_3(drdtime, void, env, tl, tl) -+DEF_HELPER_1(read_pgd, tl, env) -+#endif /* !CONFIG_USER_ONLY */ -+DEF_HELPER_2(cpucfg, tl, env, tl) -+DEF_HELPER_1(idle, void, env) -+ -+DEF_HELPER_3(float_exp2_s, i32, env, i32, i32) -+DEF_HELPER_3(float_exp2_d, i64, env, i64, i64) -+DEF_HELPER_2(float_logb_s, i32, env, i32) -+DEF_HELPER_2(float_logb_d, i64, env, i64) -+DEF_HELPER_3(movreg2cf, void, env, i32, tl) -+DEF_HELPER_2(movcf2reg, tl, env, i32) -+DEF_HELPER_3(movreg2cf_i32, void, env, i32, i32) -+DEF_HELPER_3(movreg2cf_i64, void, env, i32, i64) -+ -+DEF_HELPER_2(cto_w, tl, env, tl) -+DEF_HELPER_2(ctz_w, tl, env, tl) -+DEF_HELPER_2(cto_d, tl, env, tl) -+DEF_HELPER_2(ctz_d, tl, env, tl) -+DEF_HELPER_2(bitrev_w, tl, env, tl) -+DEF_HELPER_2(bitrev_d, tl, env, tl) -+ -+DEF_HELPER_2(load_scr, i64, env, i32) -+DEF_HELPER_3(store_scr, void, env, i32, i64) -+ -+DEF_HELPER_3(asrtle_d, void, env, tl, tl) -+DEF_HELPER_3(asrtgt_d, void, env, tl, tl) -+ -+DEF_HELPER_4(fsel, i64, env, i64, i64, i32) -+ -+#ifndef CONFIG_USER_ONLY -+DEF_HELPER_4(iocsr, void, env, tl, tl, i32) -+#endif -+DEF_HELPER_3(memtrace_addr, void, env, tl, i32) -+DEF_HELPER_2(memtrace_val, void, env, tl) -diff --git a/target/loongarch64/insn.decode b/target/loongarch64/insn.decode -new file mode 100644 -index 0000000000..f194f70116 ---- /dev/null -+++ b/target/loongarch64/insn.decode -@@ -0,0 +1,514 @@ -+# Fields -+%sd 0:2 -+%rj 5:5 -+%rd 0:5 -+%sj 5:2 -+%ptr 5:3 -+%rk 10:5 -+%sa2 15:2 -+%sa3 15:3 -+%si5 10:s5 -+%code 0:15 -+%cond 10:4 -+%cond2 0:4 -+%ui5 10:5 -+%ui6 10:6 -+%ui3 10:3 -+%ui4 10:4 -+%op 5:5 -+%ui8 10:8 -+%msbw 16:5 -+%lsbw 10:5 -+%msbd 16:6 -+%lsbd 10:6 -+%fd 0:5 -+%fj 5:5 -+%fk 10:5 -+%fcsrd 0:5 -+%fcsrs 5:5 -+%cd 0:3 -+%cj 5:3 -+%si12 10:s12 -+%ui12 10:12 -+%csr 10:14 -+%cop 0:5 -+%level 10:8 -+%seq 10:8 -+%whint 0:15 -+%addr 10:5 -+%info 5:5 -+%invop 0:5 -+%fa 15:5 -+%vd 0:5 -+%vj 5:5 -+%vk 10:5 -+%va 15:5 -+%xd 0:5 -+%xj 5:5 -+%xk 10:5 -+%xa 15:5 -+%fcond 15:5 -+%ca 15:3 -+%vui5 15:5 -+%si16 10:s16 -+%si20 5:s20 -+%si14 10:s14 -+%hint 0:5 -+%si9 10:s9 -+%si10 10:s10 -+%si11 10:s11 -+%si8 10:s8 -+%idx1 18:1 -+%idx2 18:2 -+%idx3 18:3 -+%idx4 18:4 -+%idx 18:5 -+%offs21 0:s5 10:16 -+%offs16 10:s16 -+%offs 0:s10 10:16 -+%mode 5:5 -+%ui2 10:2 -+%ui1 10:1 -+%ui7 10:7 -+%i13 5:13 -+ -+# Argument sets -+&fmt_sdrj sd rj -+&fmt_rdsj rd sj -+&fmt_rdrj rd rj -+&fmt_empty -+&fmt_rjrk rj rk -+&fmt_rdrjrksa2 rd rj rk sa2 -+&fmt_rdrjrksa3 rd rj rk sa3 -+&fmt_rdrjrk rd rj rk -+&fmt_code code -+&fmt_rdrjui5 rd rj ui5 -+&fmt_rdrjui6 rd rj ui6 -+&fmt_rdrjmsbwlsbw rd rj msbw lsbw -+&fmt_rdrjmsbdlsbd rd rj msbd lsbd -+&fmt_fdfjfk fd fj fk -+&fmt_fdfj fd fj -+&fmt_fdrj fd rj -+&fmt_rdfj rd fj -+&fmt_fcsrdrj fcsrd rj -+&fmt_rdfcsrs rd fcsrs -+&fmt_cdfj cd fj -+&fmt_fdcj fd cj -+&fmt_cdrj cd rj -+&fmt_rdcj rd cj -+&fmt_rdrjsi12 rd rj si12 -+&fmt_rdrjui12 rd rj ui12 -+&fmt_rdrjcsr rd rj csr -+&fmt_coprjsi12 cop rj si12 -+&fmt_rdrjlevel rd rj level -+&fmt_rjseq rj seq -+&fmt_whint whint -+&fmt_invtlb addr info invop -+&fmt_fdfjfkfa fd fj fk fa -+&fmt_cdfjfkfcond cd fj fk fcond -+&fmt_fdfjfkca fd fj fk ca -+&fmt_rdrjsi16 rd rj si16 -+&fmt_rdsi20 rd si20 -+&fmt_rdrjsi14 rd rj si14 -+&fmt_hintrjsi12 hint rj si12 -+&fmt_fdrjsi12 fd rj si12 -+&fmt_fdrjrk fd rj rk -+&fmt_rjoffs21 rj offs21 -+&fmt_cjoffs21 cj offs21 -+&fmt_rdrjoffs16 rd rj offs16 -+&fmt_offs offs -+&fmt_rjrdoffs16 rj rd offs16 -+ -+# Formats -+@fmt_sdrj .... ........ ..... ..... ..... ... .. &fmt_sdrj %sd %rj -+@fmt_rdsj .... ........ ..... ..... ... .. ..... &fmt_rdsj %rd %sj -+@fmt_rdrj .... ........ ..... ..... ..... ..... &fmt_rdrj %rd %rj -+@fmt_empty .... ........ ..... ..... ..... ..... &fmt_empty -+@fmt_rjrk .... ........ ..... ..... ..... ..... &fmt_rjrk %rj %rk -+@fmt_rdrjrksa2 .... ........ ... .. ..... ..... ..... &fmt_rdrjrksa2 %rd %rj %rk %sa2 -+@fmt_rdrjrksa3 .... ........ .. ... ..... ..... ..... &fmt_rdrjrksa3 %rd %rj %rk %sa3 -+@fmt_rdrjrk .... ........ ..... ..... ..... ..... &fmt_rdrjrk %rd %rj %rk -+@fmt_code .... ........ ..... ............... &fmt_code %code -+@fmt_rdrjui5 .... ........ ..... ..... ..... ..... &fmt_rdrjui5 %rd %rj %ui5 -+@fmt_rdrjui6 .... ........ .... ...... ..... ..... &fmt_rdrjui6 %rd %rj %ui6 -+@fmt_rdrjmsbwlsbw .... ....... ..... . ..... ..... ..... &fmt_rdrjmsbwlsbw %rd %rj %msbw %lsbw -+@fmt_rdrjmsbdlsbd .... ...... ...... ...... ..... ..... &fmt_rdrjmsbdlsbd %rd %rj %msbd %lsbd -+@fmt_fdfjfk .... ........ ..... ..... ..... ..... &fmt_fdfjfk %fd %fj %fk -+@fmt_fdfj .... ........ ..... ..... ..... ..... &fmt_fdfj %fd %fj -+@fmt_fdrj .... ........ ..... ..... ..... ..... &fmt_fdrj %fd %rj -+@fmt_rdfj .... ........ ..... ..... ..... ..... &fmt_rdfj %rd %fj -+@fmt_fcsrdrj .... ........ ..... ..... ..... ..... &fmt_fcsrdrj %fcsrd %rj -+@fmt_rdfcsrs .... ........ ..... ..... ..... ..... &fmt_rdfcsrs %rd %fcsrs -+@fmt_cdfj .... ........ ..... ..... ..... .. ... &fmt_cdfj %cd %fj -+@fmt_fdcj .... ........ ..... ..... .. ... ..... &fmt_fdcj %fd %cj -+@fmt_cdrj .... ........ ..... ..... ..... .. ... &fmt_cdrj %cd %rj -+@fmt_rdcj .... ........ ..... ..... .. ... ..... &fmt_rdcj %rd %cj -+@fmt_rdrjsi12 .... ...... ............ ..... ..... &fmt_rdrjsi12 %rd %rj %si12 -+@fmt_rdrjui12 .... ...... ............ ..... ..... &fmt_rdrjui12 %rd %rj %ui12 -+@fmt_rdrjcsr .... .... .............. ..... ..... &fmt_rdrjcsr %rd %rj %csr -+@fmt_coprjsi12 .... ...... ............ ..... ..... &fmt_coprjsi12 %cop %rj %si12 -+@fmt_rdrjlevel .... ........ .. ........ ..... ..... &fmt_rdrjlevel %rd %rj %level -+@fmt_rjseq .... ........ .. ........ ..... ..... &fmt_rjseq %rj %seq -+@fmt_whint .... ........ ..... ............... &fmt_whint %whint -+@fmt_invtlb ...... ...... ..... ..... ..... ..... &fmt_invtlb %addr %info %invop -+@fmt_fdfjfkfa .... ........ ..... ..... ..... ..... &fmt_fdfjfkfa %fd %fj %fk %fa -+@fmt_cdfjfkfcond .... ........ ..... ..... ..... .. ... &fmt_cdfjfkfcond %cd %fj %fk %fcond -+@fmt_fdfjfkca .... ........ .. ... ..... ..... ..... &fmt_fdfjfkca %fd %fj %fk %ca -+@fmt_rdrjsi16 .... .. ................ ..... ..... &fmt_rdrjsi16 %rd %rj %si16 -+@fmt_rdsi20 .... ... .................... ..... &fmt_rdsi20 %rd %si20 -+@fmt_rdrjsi14 .... .... .............. ..... ..... &fmt_rdrjsi14 %rd %rj %si14 -+@fmt_hintrjsi12 .... ...... ............ ..... ..... &fmt_hintrjsi12 %hint %rj %si12 -+@fmt_fdrjsi12 .... ...... ............ ..... ..... &fmt_fdrjsi12 %fd %rj %si12 -+@fmt_fdrjrk .... ........ ..... ..... ..... ..... &fmt_fdrjrk %fd %rj %rk -+@fmt_rjoffs21 .... .. ................ ..... ..... &fmt_rjoffs21 %rj %offs21 -+@fmt_cjoffs21 .... .. ................ .. ... ..... &fmt_cjoffs21 %cj %offs21 -+@fmt_rdrjoffs16 .... .. ................ ..... ..... &fmt_rdrjoffs16 %rd %rj %offs16 -+@fmt_offs .... .. .......................... &fmt_offs %offs -+@fmt_rjrdoffs16 .... .. ................ ..... ..... &fmt_rjrdoffs16 %rj %rd %offs16 -+ -+# Instructions -+ -+# Fiexd point arithmetic Instructions -+gr2scr 0000 00000000 00000 00010 ..... 000 .. @fmt_sdrj -+scr2gr 0000 00000000 00000 00011 000 .. ..... @fmt_rdsj -+clo_w 0000 00000000 00000 00100 ..... ..... @fmt_rdrj -+clz_w 0000 00000000 00000 00101 ..... ..... @fmt_rdrj -+cto_w 0000 00000000 00000 00110 ..... ..... @fmt_rdrj -+ctz_w 0000 00000000 00000 00111 ..... ..... @fmt_rdrj -+clo_d 0000 00000000 00000 01000 ..... ..... @fmt_rdrj -+clz_d 0000 00000000 00000 01001 ..... ..... @fmt_rdrj -+cto_d 0000 00000000 00000 01010 ..... ..... @fmt_rdrj -+ctz_d 0000 00000000 00000 01011 ..... ..... @fmt_rdrj -+revb_2h 0000 00000000 00000 01100 ..... ..... @fmt_rdrj -+revb_4h 0000 00000000 00000 01101 ..... ..... @fmt_rdrj -+revb_2w 0000 00000000 00000 01110 ..... ..... @fmt_rdrj -+revb_d 0000 00000000 00000 01111 ..... ..... @fmt_rdrj -+revh_2w 0000 00000000 00000 10000 ..... ..... @fmt_rdrj -+revh_d 0000 00000000 00000 10001 ..... ..... @fmt_rdrj -+bitrev_4b 0000 00000000 00000 10010 ..... ..... @fmt_rdrj -+bitrev_8b 0000 00000000 00000 10011 ..... ..... @fmt_rdrj -+bitrev_w 0000 00000000 00000 10100 ..... ..... @fmt_rdrj -+bitrev_d 0000 00000000 00000 10101 ..... ..... @fmt_rdrj -+ext_w_h 0000 00000000 00000 10110 ..... ..... @fmt_rdrj -+ext_w_b 0000 00000000 00000 10111 ..... ..... @fmt_rdrj -+rdtime_d 0000 00000000 00000 11010 ..... ..... @fmt_rdrj -+cpucfg 0000 00000000 00000 11011 ..... ..... @fmt_rdrj -+asrtle_d 0000 00000000 00010 ..... ..... 00000 @fmt_rjrk -+asrtgt_d 0000 00000000 00011 ..... ..... 00000 @fmt_rjrk -+alsl_w 0000 00000000 010 .. ..... ..... ..... @fmt_rdrjrksa2 -+alsl_wu 0000 00000000 011 .. ..... ..... ..... @fmt_rdrjrksa2 -+bytepick_w 0000 00000000 100 .. ..... ..... ..... @fmt_rdrjrksa2 -+bytepick_d 0000 00000000 11 ... ..... ..... ..... @fmt_rdrjrksa3 -+add_w 0000 00000001 00000 ..... ..... ..... @fmt_rdrjrk -+add_d 0000 00000001 00001 ..... ..... ..... @fmt_rdrjrk -+sub_w 0000 00000001 00010 ..... ..... ..... @fmt_rdrjrk -+sub_d 0000 00000001 00011 ..... ..... ..... @fmt_rdrjrk -+slt 0000 00000001 00100 ..... ..... ..... @fmt_rdrjrk -+sltu 0000 00000001 00101 ..... ..... ..... @fmt_rdrjrk -+maskeqz 0000 00000001 00110 ..... ..... ..... @fmt_rdrjrk -+masknez 0000 00000001 00111 ..... ..... ..... @fmt_rdrjrk -+nor 0000 00000001 01000 ..... ..... ..... @fmt_rdrjrk -+and 0000 00000001 01001 ..... ..... ..... @fmt_rdrjrk -+or 0000 00000001 01010 ..... ..... ..... @fmt_rdrjrk -+xor 0000 00000001 01011 ..... ..... ..... @fmt_rdrjrk -+orn 0000 00000001 01100 ..... ..... ..... @fmt_rdrjrk -+andn 0000 00000001 01101 ..... ..... ..... @fmt_rdrjrk -+sll_w 0000 00000001 01110 ..... ..... ..... @fmt_rdrjrk -+srl_w 0000 00000001 01111 ..... ..... ..... @fmt_rdrjrk -+sra_w 0000 00000001 10000 ..... ..... ..... @fmt_rdrjrk -+sll_d 0000 00000001 10001 ..... ..... ..... @fmt_rdrjrk -+srl_d 0000 00000001 10010 ..... ..... ..... @fmt_rdrjrk -+sra_d 0000 00000001 10011 ..... ..... ..... @fmt_rdrjrk -+rotr_w 0000 00000001 10110 ..... ..... ..... @fmt_rdrjrk -+rotr_d 0000 00000001 10111 ..... ..... ..... @fmt_rdrjrk -+mul_w 0000 00000001 11000 ..... ..... ..... @fmt_rdrjrk -+mulh_w 0000 00000001 11001 ..... ..... ..... @fmt_rdrjrk -+mulh_wu 0000 00000001 11010 ..... ..... ..... @fmt_rdrjrk -+mul_d 0000 00000001 11011 ..... ..... ..... @fmt_rdrjrk -+mulh_d 0000 00000001 11100 ..... ..... ..... @fmt_rdrjrk -+mulh_du 0000 00000001 11101 ..... ..... ..... @fmt_rdrjrk -+mulw_d_w 0000 00000001 11110 ..... ..... ..... @fmt_rdrjrk -+mulw_d_wu 0000 00000001 11111 ..... ..... ..... @fmt_rdrjrk -+div_w 0000 00000010 00000 ..... ..... ..... @fmt_rdrjrk -+mod_w 0000 00000010 00001 ..... ..... ..... @fmt_rdrjrk -+div_wu 0000 00000010 00010 ..... ..... ..... @fmt_rdrjrk -+mod_wu 0000 00000010 00011 ..... ..... ..... @fmt_rdrjrk -+div_d 0000 00000010 00100 ..... ..... ..... @fmt_rdrjrk -+mod_d 0000 00000010 00101 ..... ..... ..... @fmt_rdrjrk -+div_du 0000 00000010 00110 ..... ..... ..... @fmt_rdrjrk -+mod_du 0000 00000010 00111 ..... ..... ..... @fmt_rdrjrk -+crc_w_b_w 0000 00000010 01000 ..... ..... ..... @fmt_rdrjrk -+crc_w_h_w 0000 00000010 01001 ..... ..... ..... @fmt_rdrjrk -+crc_w_w_w 0000 00000010 01010 ..... ..... ..... @fmt_rdrjrk -+crc_w_d_w 0000 00000010 01011 ..... ..... ..... @fmt_rdrjrk -+crcc_w_b_w 0000 00000010 01100 ..... ..... ..... @fmt_rdrjrk -+crcc_w_h_w 0000 00000010 01101 ..... ..... ..... @fmt_rdrjrk -+crcc_w_w_w 0000 00000010 01110 ..... ..... ..... @fmt_rdrjrk -+crcc_w_d_w 0000 00000010 01111 ..... ..... ..... @fmt_rdrjrk -+break 0000 00000010 10100 ............... @fmt_code -+dbcl 0000 00000010 10101 ............... @fmt_code -+syscall 0000 00000010 10110 ............... @fmt_code -+alsl_d 0000 00000010 110 .. ..... ..... ..... @fmt_rdrjrksa2 -+slli_w 0000 00000100 00001 ..... ..... ..... @fmt_rdrjui5 -+slli_d 0000 00000100 0001 ...... ..... ..... @fmt_rdrjui6 -+srli_w 0000 00000100 01001 ..... ..... ..... @fmt_rdrjui5 -+srli_d 0000 00000100 0101 ...... ..... ..... @fmt_rdrjui6 -+srai_w 0000 00000100 10001 ..... ..... ..... @fmt_rdrjui5 -+srai_d 0000 00000100 1001 ...... ..... ..... @fmt_rdrjui6 -+rotri_w 0000 00000100 11001 ..... ..... ..... @fmt_rdrjui5 -+rotri_d 0000 00000100 1101 ...... ..... ..... @fmt_rdrjui6 -+bstrins_w 0000 0000011 ..... 0 ..... ..... ..... @fmt_rdrjmsbwlsbw -+bstrpick_w 0000 0000011 ..... 1 ..... ..... ..... @fmt_rdrjmsbwlsbw -+bstrins_d 0000 000010 ...... ...... ..... ..... @fmt_rdrjmsbdlsbd -+bstrpick_d 0000 000011 ...... ...... ..... ..... @fmt_rdrjmsbdlsbd -+ -+# float Instructions -+fadd_s 0000 00010000 00001 ..... ..... ..... @fmt_fdfjfk -+fadd_d 0000 00010000 00010 ..... ..... ..... @fmt_fdfjfk -+fsub_s 0000 00010000 00101 ..... ..... ..... @fmt_fdfjfk -+fsub_d 0000 00010000 00110 ..... ..... ..... @fmt_fdfjfk -+fmul_s 0000 00010000 01001 ..... ..... ..... @fmt_fdfjfk -+fmul_d 0000 00010000 01010 ..... ..... ..... @fmt_fdfjfk -+fdiv_s 0000 00010000 01101 ..... ..... ..... @fmt_fdfjfk -+fdiv_d 0000 00010000 01110 ..... ..... ..... @fmt_fdfjfk -+fmax_s 0000 00010000 10001 ..... ..... ..... @fmt_fdfjfk -+fmax_d 0000 00010000 10010 ..... ..... ..... @fmt_fdfjfk -+fmin_s 0000 00010000 10101 ..... ..... ..... @fmt_fdfjfk -+fmin_d 0000 00010000 10110 ..... ..... ..... @fmt_fdfjfk -+fmaxa_s 0000 00010000 11001 ..... ..... ..... @fmt_fdfjfk -+fmaxa_d 0000 00010000 11010 ..... ..... ..... @fmt_fdfjfk -+fmina_s 0000 00010000 11101 ..... ..... ..... @fmt_fdfjfk -+fmina_d 0000 00010000 11110 ..... ..... ..... @fmt_fdfjfk -+fscaleb_s 0000 00010001 00001 ..... ..... ..... @fmt_fdfjfk -+fscaleb_d 0000 00010001 00010 ..... ..... ..... @fmt_fdfjfk -+fcopysign_s 0000 00010001 00101 ..... ..... ..... @fmt_fdfjfk -+fcopysign_d 0000 00010001 00110 ..... ..... ..... @fmt_fdfjfk -+fabs_s 0000 00010001 01000 00001 ..... ..... @fmt_fdfj -+fabs_d 0000 00010001 01000 00010 ..... ..... @fmt_fdfj -+fneg_s 0000 00010001 01000 00101 ..... ..... @fmt_fdfj -+fneg_d 0000 00010001 01000 00110 ..... ..... @fmt_fdfj -+flogb_s 0000 00010001 01000 01001 ..... ..... @fmt_fdfj -+flogb_d 0000 00010001 01000 01010 ..... ..... @fmt_fdfj -+fclass_s 0000 00010001 01000 01101 ..... ..... @fmt_fdfj -+fclass_d 0000 00010001 01000 01110 ..... ..... @fmt_fdfj -+fsqrt_s 0000 00010001 01000 10001 ..... ..... @fmt_fdfj -+fsqrt_d 0000 00010001 01000 10010 ..... ..... @fmt_fdfj -+frecip_s 0000 00010001 01000 10101 ..... ..... @fmt_fdfj -+frecip_d 0000 00010001 01000 10110 ..... ..... @fmt_fdfj -+frsqrt_s 0000 00010001 01000 11001 ..... ..... @fmt_fdfj -+frsqrt_d 0000 00010001 01000 11010 ..... ..... @fmt_fdfj -+fmov_s 0000 00010001 01001 00101 ..... ..... @fmt_fdfj -+fmov_d 0000 00010001 01001 00110 ..... ..... @fmt_fdfj -+movgr2fr_w 0000 00010001 01001 01001 ..... ..... @fmt_fdrj -+movgr2fr_d 0000 00010001 01001 01010 ..... ..... @fmt_fdrj -+movgr2frh_w 0000 00010001 01001 01011 ..... ..... @fmt_fdrj -+movfr2gr_s 0000 00010001 01001 01101 ..... ..... @fmt_rdfj -+movfr2gr_d 0000 00010001 01001 01110 ..... ..... @fmt_rdfj -+movfrh2gr_s 0000 00010001 01001 01111 ..... ..... @fmt_rdfj -+movgr2fcsr 0000 00010001 01001 10000 ..... ..... @fmt_fcsrdrj -+movfcsr2gr 0000 00010001 01001 10010 ..... ..... @fmt_rdfcsrs -+movfr2cf 0000 00010001 01001 10100 ..... 00 ... @fmt_cdfj -+movcf2fr 0000 00010001 01001 10101 00 ... ..... @fmt_fdcj -+movgr2cf 0000 00010001 01001 10110 ..... 00 ... @fmt_cdrj -+movcf2gr 0000 00010001 01001 10111 00 ... ..... @fmt_rdcj -+fcvt_s_d 0000 00010001 10010 00110 ..... ..... @fmt_fdfj -+fcvt_d_s 0000 00010001 10010 01001 ..... ..... @fmt_fdfj -+ftintrm_w_s 0000 00010001 10100 00001 ..... ..... @fmt_fdfj -+ftintrm_w_d 0000 00010001 10100 00010 ..... ..... @fmt_fdfj -+ftintrm_l_s 0000 00010001 10100 01001 ..... ..... @fmt_fdfj -+ftintrm_l_d 0000 00010001 10100 01010 ..... ..... @fmt_fdfj -+ftintrp_w_s 0000 00010001 10100 10001 ..... ..... @fmt_fdfj -+ftintrp_w_d 0000 00010001 10100 10010 ..... ..... @fmt_fdfj -+ftintrp_l_s 0000 00010001 10100 11001 ..... ..... @fmt_fdfj -+ftintrp_l_d 0000 00010001 10100 11010 ..... ..... @fmt_fdfj -+ftintrz_w_s 0000 00010001 10101 00001 ..... ..... @fmt_fdfj -+ftintrz_w_d 0000 00010001 10101 00010 ..... ..... @fmt_fdfj -+ftintrz_l_s 0000 00010001 10101 01001 ..... ..... @fmt_fdfj -+ftintrz_l_d 0000 00010001 10101 01010 ..... ..... @fmt_fdfj -+ftintrne_w_s 0000 00010001 10101 10001 ..... ..... @fmt_fdfj -+ftintrne_w_d 0000 00010001 10101 10010 ..... ..... @fmt_fdfj -+ftintrne_l_s 0000 00010001 10101 11001 ..... ..... @fmt_fdfj -+ftintrne_l_d 0000 00010001 10101 11010 ..... ..... @fmt_fdfj -+ftint_w_s 0000 00010001 10110 00001 ..... ..... @fmt_fdfj -+ftint_w_d 0000 00010001 10110 00010 ..... ..... @fmt_fdfj -+ftint_l_s 0000 00010001 10110 01001 ..... ..... @fmt_fdfj -+ftint_l_d 0000 00010001 10110 01010 ..... ..... @fmt_fdfj -+ffint_s_w 0000 00010001 11010 00100 ..... ..... @fmt_fdfj -+ffint_s_l 0000 00010001 11010 00110 ..... ..... @fmt_fdfj -+ffint_d_w 0000 00010001 11010 01000 ..... ..... @fmt_fdfj -+ffint_d_l 0000 00010001 11010 01010 ..... ..... @fmt_fdfj -+frint_s 0000 00010001 11100 10001 ..... ..... @fmt_fdfj -+frint_d 0000 00010001 11100 10010 ..... ..... @fmt_fdfj -+ -+# 12 bit immediate Instructions -+slti 0000 001000 ............ ..... ..... @fmt_rdrjsi12 -+sltui 0000 001001 ............ ..... ..... @fmt_rdrjsi12 -+addi_w 0000 001010 ............ ..... ..... @fmt_rdrjsi12 -+addi_d 0000 001011 ............ ..... ..... @fmt_rdrjsi12 -+lu52i_d 0000 001100 ............ ..... ..... @fmt_rdrjsi12 -+andi 0000 001101 ............ ..... ..... @fmt_rdrjui12 -+ori 0000 001110 ............ ..... ..... @fmt_rdrjui12 -+xori 0000 001111 ............ ..... ..... @fmt_rdrjui12 -+ -+# core Instructions -+csrxchg 0000 0100 .............. ..... ..... @fmt_rdrjcsr -+cacop 0000 011000 ............ ..... ..... @fmt_coprjsi12 -+lddir 0000 01100100 00 ........ ..... ..... @fmt_rdrjlevel -+ldpte 0000 01100100 01 ........ ..... 00000 @fmt_rjseq -+iocsrrd_b 0000 01100100 10000 00000 ..... ..... @fmt_rdrj -+iocsrrd_h 0000 01100100 10000 00001 ..... ..... @fmt_rdrj -+iocsrrd_w 0000 01100100 10000 00010 ..... ..... @fmt_rdrj -+iocsrrd_d 0000 01100100 10000 00011 ..... ..... @fmt_rdrj -+iocsrwr_b 0000 01100100 10000 00100 ..... ..... @fmt_rdrj -+iocsrwr_h 0000 01100100 10000 00101 ..... ..... @fmt_rdrj -+iocsrwr_w 0000 01100100 10000 00110 ..... ..... @fmt_rdrj -+iocsrwr_d 0000 01100100 10000 00111 ..... ..... @fmt_rdrj -+tlbclr 0000 01100100 10000 01000 00000 00000 @fmt_empty -+tlbflush 0000 01100100 10000 01001 00000 00000 @fmt_empty -+tlbsrch 0000 01100100 10000 01010 00000 00000 @fmt_empty -+tlbrd 0000 01100100 10000 01011 00000 00000 @fmt_empty -+tlbwr 0000 01100100 10000 01100 00000 00000 @fmt_empty -+tlbfill 0000 01100100 10000 01101 00000 00000 @fmt_empty -+ertn 0000 01100100 10000 01110 00000 00000 @fmt_empty -+idle 0000 01100100 10001 ............... @fmt_whint -+invtlb 0000 01100100 10011 ..... ..... ..... @fmt_invtlb -+ -+# foure Op Instructions -+fmadd_s 0000 10000001 ..... ..... ..... ..... @fmt_fdfjfkfa -+fmadd_d 0000 10000010 ..... ..... ..... ..... @fmt_fdfjfkfa -+fmsub_s 0000 10000101 ..... ..... ..... ..... @fmt_fdfjfkfa -+fmsub_d 0000 10000110 ..... ..... ..... ..... @fmt_fdfjfkfa -+fnmadd_s 0000 10001001 ..... ..... ..... ..... @fmt_fdfjfkfa -+fnmadd_d 0000 10001010 ..... ..... ..... ..... @fmt_fdfjfkfa -+fnmsub_s 0000 10001101 ..... ..... ..... ..... @fmt_fdfjfkfa -+fnmsub_d 0000 10001110 ..... ..... ..... ..... @fmt_fdfjfkfa -+fcmp_cond_s 0000 11000001 ..... ..... ..... 00 ... @fmt_cdfjfkfcond -+fcmp_cond_d 0000 11000010 ..... ..... ..... 00 ... @fmt_cdfjfkfcond -+fsel 0000 11010000 00 ... ..... ..... ..... @fmt_fdfjfkca -+ -+# loog immediate Instructions -+addu16i_d 0001 00 ................ ..... ..... @fmt_rdrjsi16 -+lu12i_w 0001 010 .................... ..... @fmt_rdsi20 -+lu32i_d 0001 011 .................... ..... @fmt_rdsi20 -+pcaddi 0001 100 .................... ..... @fmt_rdsi20 -+pcalau12i 0001 101 .................... ..... @fmt_rdsi20 -+pcaddu12i 0001 110 .................... ..... @fmt_rdsi20 -+pcaddu18i 0001 111 .................... ..... @fmt_rdsi20 -+ -+# load/store Instructions -+ll_w 0010 0000 .............. ..... ..... @fmt_rdrjsi14 -+sc_w 0010 0001 .............. ..... ..... @fmt_rdrjsi14 -+ll_d 0010 0010 .............. ..... ..... @fmt_rdrjsi14 -+sc_d 0010 0011 .............. ..... ..... @fmt_rdrjsi14 -+ldptr_w 0010 0100 .............. ..... ..... @fmt_rdrjsi14 -+stptr_w 0010 0101 .............. ..... ..... @fmt_rdrjsi14 -+ldptr_d 0010 0110 .............. ..... ..... @fmt_rdrjsi14 -+stptr_d 0010 0111 .............. ..... ..... @fmt_rdrjsi14 -+ld_b 0010 100000 ............ ..... ..... @fmt_rdrjsi12 -+ld_h 0010 100001 ............ ..... ..... @fmt_rdrjsi12 -+ld_w 0010 100010 ............ ..... ..... @fmt_rdrjsi12 -+ld_d 0010 100011 ............ ..... ..... @fmt_rdrjsi12 -+st_b 0010 100100 ............ ..... ..... @fmt_rdrjsi12 -+st_h 0010 100101 ............ ..... ..... @fmt_rdrjsi12 -+st_w 0010 100110 ............ ..... ..... @fmt_rdrjsi12 -+st_d 0010 100111 ............ ..... ..... @fmt_rdrjsi12 -+ld_bu 0010 101000 ............ ..... ..... @fmt_rdrjsi12 -+ld_hu 0010 101001 ............ ..... ..... @fmt_rdrjsi12 -+ld_wu 0010 101010 ............ ..... ..... @fmt_rdrjsi12 -+preld 0010 101011 ............ ..... ..... @fmt_hintrjsi12 -+fld_s 0010 101100 ............ ..... ..... @fmt_fdrjsi12 -+fst_s 0010 101101 ............ ..... ..... @fmt_fdrjsi12 -+fld_d 0010 101110 ............ ..... ..... @fmt_fdrjsi12 -+fst_d 0010 101111 ............ ..... ..... @fmt_fdrjsi12 -+ldx_b 0011 10000000 00000 ..... ..... ..... @fmt_rdrjrk -+ldx_h 0011 10000000 01000 ..... ..... ..... @fmt_rdrjrk -+ldx_w 0011 10000000 10000 ..... ..... ..... @fmt_rdrjrk -+ldx_d 0011 10000000 11000 ..... ..... ..... @fmt_rdrjrk -+stx_b 0011 10000001 00000 ..... ..... ..... @fmt_rdrjrk -+stx_h 0011 10000001 01000 ..... ..... ..... @fmt_rdrjrk -+stx_w 0011 10000001 10000 ..... ..... ..... @fmt_rdrjrk -+stx_d 0011 10000001 11000 ..... ..... ..... @fmt_rdrjrk -+ldx_bu 0011 10000010 00000 ..... ..... ..... @fmt_rdrjrk -+ldx_hu 0011 10000010 01000 ..... ..... ..... @fmt_rdrjrk -+ldx_wu 0011 10000010 10000 ..... ..... ..... @fmt_rdrjrk -+fldx_s 0011 10000011 00000 ..... ..... ..... @fmt_fdrjrk -+fldx_d 0011 10000011 01000 ..... ..... ..... @fmt_fdrjrk -+fstx_s 0011 10000011 10000 ..... ..... ..... @fmt_fdrjrk -+fstx_d 0011 10000011 11000 ..... ..... ..... @fmt_fdrjrk -+amswap_w 0011 10000110 00000 ..... ..... ..... @fmt_rdrjrk -+amswap_d 0011 10000110 00001 ..... ..... ..... @fmt_rdrjrk -+amadd_w 0011 10000110 00010 ..... ..... ..... @fmt_rdrjrk -+amadd_d 0011 10000110 00011 ..... ..... ..... @fmt_rdrjrk -+amand_w 0011 10000110 00100 ..... ..... ..... @fmt_rdrjrk -+amand_d 0011 10000110 00101 ..... ..... ..... @fmt_rdrjrk -+amor_w 0011 10000110 00110 ..... ..... ..... @fmt_rdrjrk -+amor_d 0011 10000110 00111 ..... ..... ..... @fmt_rdrjrk -+amxor_w 0011 10000110 01000 ..... ..... ..... @fmt_rdrjrk -+amxor_d 0011 10000110 01001 ..... ..... ..... @fmt_rdrjrk -+ammax_w 0011 10000110 01010 ..... ..... ..... @fmt_rdrjrk -+ammax_d 0011 10000110 01011 ..... ..... ..... @fmt_rdrjrk -+ammin_w 0011 10000110 01100 ..... ..... ..... @fmt_rdrjrk -+ammin_d 0011 10000110 01101 ..... ..... ..... @fmt_rdrjrk -+ammax_wu 0011 10000110 01110 ..... ..... ..... @fmt_rdrjrk -+ammax_du 0011 10000110 01111 ..... ..... ..... @fmt_rdrjrk -+ammin_wu 0011 10000110 10000 ..... ..... ..... @fmt_rdrjrk -+ammin_du 0011 10000110 10001 ..... ..... ..... @fmt_rdrjrk -+amswap_db_w 0011 10000110 10010 ..... ..... ..... @fmt_rdrjrk -+amswap_db_d 0011 10000110 10011 ..... ..... ..... @fmt_rdrjrk -+amadd_db_w 0011 10000110 10100 ..... ..... ..... @fmt_rdrjrk -+amadd_db_d 0011 10000110 10101 ..... ..... ..... @fmt_rdrjrk -+amand_db_w 0011 10000110 10110 ..... ..... ..... @fmt_rdrjrk -+amand_db_d 0011 10000110 10111 ..... ..... ..... @fmt_rdrjrk -+amor_db_w 0011 10000110 11000 ..... ..... ..... @fmt_rdrjrk -+amor_db_d 0011 10000110 11001 ..... ..... ..... @fmt_rdrjrk -+amxor_db_w 0011 10000110 11010 ..... ..... ..... @fmt_rdrjrk -+amxor_db_d 0011 10000110 11011 ..... ..... ..... @fmt_rdrjrk -+ammax_db_w 0011 10000110 11100 ..... ..... ..... @fmt_rdrjrk -+ammax_db_d 0011 10000110 11101 ..... ..... ..... @fmt_rdrjrk -+ammin_db_w 0011 10000110 11110 ..... ..... ..... @fmt_rdrjrk -+ammin_db_d 0011 10000110 11111 ..... ..... ..... @fmt_rdrjrk -+ammax_db_wu 0011 10000111 00000 ..... ..... ..... @fmt_rdrjrk -+ammax_db_du 0011 10000111 00001 ..... ..... ..... @fmt_rdrjrk -+ammin_db_wu 0011 10000111 00010 ..... ..... ..... @fmt_rdrjrk -+ammin_db_du 0011 10000111 00011 ..... ..... ..... @fmt_rdrjrk -+dbar 0011 10000111 00100 ............... @fmt_whint -+ibar 0011 10000111 00101 ............... @fmt_whint -+fldgt_s 0011 10000111 01000 ..... ..... ..... @fmt_fdrjrk -+fldgt_d 0011 10000111 01001 ..... ..... ..... @fmt_fdrjrk -+fldle_s 0011 10000111 01010 ..... ..... ..... @fmt_fdrjrk -+fldle_d 0011 10000111 01011 ..... ..... ..... @fmt_fdrjrk -+fstgt_s 0011 10000111 01100 ..... ..... ..... @fmt_fdrjrk -+fstgt_d 0011 10000111 01101 ..... ..... ..... @fmt_fdrjrk -+fstle_s 0011 10000111 01110 ..... ..... ..... @fmt_fdrjrk -+fstle_d 0011 10000111 01111 ..... ..... ..... @fmt_fdrjrk -+ldgt_b 0011 10000111 10000 ..... ..... ..... @fmt_rdrjrk -+ldgt_h 0011 10000111 10001 ..... ..... ..... @fmt_rdrjrk -+ldgt_w 0011 10000111 10010 ..... ..... ..... @fmt_rdrjrk -+ldgt_d 0011 10000111 10011 ..... ..... ..... @fmt_rdrjrk -+ldle_b 0011 10000111 10100 ..... ..... ..... @fmt_rdrjrk -+ldle_h 0011 10000111 10101 ..... ..... ..... @fmt_rdrjrk -+ldle_w 0011 10000111 10110 ..... ..... ..... @fmt_rdrjrk -+ldle_d 0011 10000111 10111 ..... ..... ..... @fmt_rdrjrk -+stgt_b 0011 10000111 11000 ..... ..... ..... @fmt_rdrjrk -+stgt_h 0011 10000111 11001 ..... ..... ..... @fmt_rdrjrk -+stgt_w 0011 10000111 11010 ..... ..... ..... @fmt_rdrjrk -+stgt_d 0011 10000111 11011 ..... ..... ..... @fmt_rdrjrk -+stle_b 0011 10000111 11100 ..... ..... ..... @fmt_rdrjrk -+stle_h 0011 10000111 11101 ..... ..... ..... @fmt_rdrjrk -+stle_w 0011 10000111 11110 ..... ..... ..... @fmt_rdrjrk -+stle_d 0011 10000111 11111 ..... ..... ..... @fmt_rdrjrk -+ -+# jump Instructions -+beqz 0100 00 ................ ..... ..... @fmt_rjoffs21 -+bnez 0100 01 ................ ..... ..... @fmt_rjoffs21 -+bceqz 0100 10 ................ 00 ... ..... @fmt_cjoffs21 -+bcnez 0100 10 ................ 01 ... ..... @fmt_cjoffs21 -+jirl 0100 11 ................ ..... ..... @fmt_rdrjoffs16 -+b 0101 00 .......................... @fmt_offs -+bl 0101 01 .......................... @fmt_offs -+beq 0101 10 ................ ..... ..... @fmt_rjrdoffs16 -+bne 0101 11 ................ ..... ..... @fmt_rjrdoffs16 -+blt 0110 00 ................ ..... ..... @fmt_rjrdoffs16 -+bge 0110 01 ................ ..... ..... @fmt_rjrdoffs16 -+bltu 0110 10 ................ ..... ..... @fmt_rjrdoffs16 -+bgeu 0110 11 ................ ..... ..... @fmt_rjrdoffs16 -diff --git a/target/loongarch64/instmap.h b/target/loongarch64/instmap.h -new file mode 100644 -index 0000000000..6e85847f8a ---- /dev/null -+++ b/target/loongarch64/instmap.h -@@ -0,0 +1,216 @@ -+/* -+ * Loongarch emulation for qemu: instruction opcode -+ * -+ * Copyright (c) 2020-2021 -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2 or later, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program. If not, see . -+ */ -+ -+#ifndef TARGET_LARCH_INSTMAP_H -+#define TARGET_LARCH_INSTMAP_H -+ -+enum { -+ /* fix opcodes */ -+ OPC_LARCH_CLO_W = (0x000004 << 10), -+ OPC_LARCH_CLZ_W = (0x000005 << 10), -+ OPC_LARCH_CLO_D = (0x000008 << 10), -+ OPC_LARCH_CLZ_D = (0x000009 << 10), -+ OPC_LARCH_REVB_2H = (0x00000C << 10), -+ OPC_LARCH_REVB_4H = (0x00000D << 10), -+ OPC_LARCH_REVH_D = (0x000011 << 10), -+ OPC_LARCH_BREV_4B = (0x000012 << 10), -+ OPC_LARCH_BREV_8B = (0x000013 << 10), -+ OPC_LARCH_EXT_WH = (0x000016 << 10), -+ OPC_LARCH_EXT_WB = (0x000017 << 10), -+ -+ OPC_LARCH_ADD_W = (0x00020 << 15), -+ OPC_LARCH_ADD_D = (0x00021 << 15), -+ OPC_LARCH_SUB_W = (0x00022 << 15), -+ OPC_LARCH_SUB_D = (0x00023 << 15), -+ OPC_LARCH_SLT = (0x00024 << 15), -+ OPC_LARCH_SLTU = (0x00025 << 15), -+ OPC_LARCH_MASKEQZ = (0x00026 << 15), -+ OPC_LARCH_MASKNEZ = (0x00027 << 15), -+ OPC_LARCH_NOR = (0x00028 << 15), -+ OPC_LARCH_AND = (0x00029 << 15), -+ OPC_LARCH_OR = (0x0002A << 15), -+ OPC_LARCH_XOR = (0x0002B << 15), -+ OPC_LARCH_SLL_W = (0x0002E << 15), -+ OPC_LARCH_SRL_W = (0x0002F << 15), -+ OPC_LARCH_SRA_W = (0x00030 << 15), -+ OPC_LARCH_SLL_D = (0x00031 << 15), -+ OPC_LARCH_SRL_D = (0x00032 << 15), -+ OPC_LARCH_SRA_D = (0x00033 << 15), -+ OPC_LARCH_ROTR_W = (0x00036 << 15), -+ OPC_LARCH_ROTR_D = (0x00037 << 15), -+ OPC_LARCH_MUL_W = (0x00038 << 15), -+ OPC_LARCH_MULH_W = (0x00039 << 15), -+ OPC_LARCH_MULH_WU = (0x0003A << 15), -+ OPC_LARCH_MUL_D = (0x0003B << 15), -+ OPC_LARCH_MULH_D = (0x0003C << 15), -+ OPC_LARCH_MULH_DU = (0x0003D << 15), -+ OPC_LARCH_DIV_W = (0x00040 << 15), -+ OPC_LARCH_MOD_W = (0x00041 << 15), -+ OPC_LARCH_DIV_WU = (0x00042 << 15), -+ OPC_LARCH_MOD_WU = (0x00043 << 15), -+ OPC_LARCH_DIV_D = (0x00044 << 15), -+ OPC_LARCH_MOD_D = (0x00045 << 15), -+ OPC_LARCH_DIV_DU = (0x00046 << 15), -+ OPC_LARCH_MOD_DU = (0x00047 << 15), -+ OPC_LARCH_SRLI_W = (0x00089 << 15), -+ OPC_LARCH_SRAI_W = (0x00091 << 15), -+ OPC_LARCH_ROTRI_W = (0x00099 << 15), -+ -+ OPC_LARCH_ALSL_W = (0x0002 << 17), -+ OPC_LARCH_ALSL_D = (0x0016 << 17), -+ -+ OPC_LARCH_TRINS_W = (0x003 << 21) | (0x0 << 15), -+ OPC_LARCH_TRPICK_W = (0x003 << 21) | (0x1 << 15), -+}; -+ -+enum { -+ /* float opcodes */ -+ OPC_LARCH_FABS_S = (0x004501 << 10), -+ OPC_LARCH_FABS_D = (0x004502 << 10), -+ OPC_LARCH_FNEG_S = (0x004505 << 10), -+ OPC_LARCH_FNEG_D = (0x004506 << 10), -+ OPC_LARCH_FCLASS_S = (0x00450D << 10), -+ OPC_LARCH_FCLASS_D = (0x00450E << 10), -+ OPC_LARCH_FSQRT_S = (0x004511 << 10), -+ OPC_LARCH_FSQRT_D = (0x004512 << 10), -+ OPC_LARCH_FRECIP_S = (0x004515 << 10), -+ OPC_LARCH_FRECIP_D = (0x004516 << 10), -+ OPC_LARCH_FRSQRT_S = (0x004519 << 10), -+ OPC_LARCH_FRSQRT_D = (0x00451A << 10), -+ OPC_LARCH_FMOV_S = (0x004525 << 10), -+ OPC_LARCH_FMOV_D = (0x004526 << 10), -+ OPC_LARCH_GR2FR_W = (0x004529 << 10), -+ OPC_LARCH_GR2FR_D = (0x00452A << 10), -+ OPC_LARCH_GR2FRH_W = (0x00452B << 10), -+ OPC_LARCH_FR2GR_S = (0x00452D << 10), -+ OPC_LARCH_FR2GR_D = (0x00452E << 10), -+ OPC_LARCH_FRH2GR_S = (0x00452F << 10), -+ -+ OPC_LARCH_FCVT_S_D = (0x004646 << 10), -+ OPC_LARCH_FCVT_D_S = (0x004649 << 10), -+ OPC_LARCH_FTINTRM_W_S = (0x004681 << 10), -+ OPC_LARCH_FTINTRM_W_D = (0x004682 << 10), -+ OPC_LARCH_FTINTRM_L_S = (0x004689 << 10), -+ OPC_LARCH_FTINTRM_L_D = (0x00468A << 10), -+ OPC_LARCH_FTINTRP_W_S = (0x004691 << 10), -+ OPC_LARCH_FTINTRP_W_D = (0x004692 << 10), -+ OPC_LARCH_FTINTRP_L_S = (0x004699 << 10), -+ OPC_LARCH_FTINTRP_L_D = (0x00469A << 10), -+ OPC_LARCH_FTINTRZ_W_S = (0x0046A1 << 10), -+ OPC_LARCH_FTINTRZ_W_D = (0x0046A2 << 10), -+ OPC_LARCH_FTINTRZ_L_S = (0x0046A9 << 10), -+ OPC_LARCH_FTINTRZ_L_D = (0x0046AA << 10), -+ OPC_LARCH_FTINTRNE_W_S = (0x0046B1 << 10), -+ OPC_LARCH_FTINTRNE_W_D = (0x0046B2 << 10), -+ OPC_LARCH_FTINTRNE_L_S = (0x0046B9 << 10), -+ OPC_LARCH_FTINTRNE_L_D = (0x0046BA << 10), -+ OPC_LARCH_FTINT_W_S = (0x0046C1 << 10), -+ OPC_LARCH_FTINT_W_D = (0x0046C2 << 10), -+ OPC_LARCH_FTINT_L_S = (0x0046C9 << 10), -+ OPC_LARCH_FTINT_L_D = (0x0046CA << 10), -+ OPC_LARCH_FFINT_S_W = (0x004744 << 10), -+ OPC_LARCH_FFINT_S_L = (0x004746 << 10), -+ OPC_LARCH_FFINT_D_W = (0x004748 << 10), -+ OPC_LARCH_FFINT_D_L = (0x00474A << 10), -+ OPC_LARCH_FRINT_S = (0x004791 << 10), -+ OPC_LARCH_FRINT_D = (0x004792 << 10), -+ -+ OPC_LARCH_FADD_S = (0x00201 << 15), -+ OPC_LARCH_FADD_D = (0x00202 << 15), -+ OPC_LARCH_FSUB_S = (0x00205 << 15), -+ OPC_LARCH_FSUB_D = (0x00206 << 15), -+ OPC_LARCH_FMUL_S = (0x00209 << 15), -+ OPC_LARCH_FMUL_D = (0x0020A << 15), -+ OPC_LARCH_FDIV_S = (0x0020D << 15), -+ OPC_LARCH_FDIV_D = (0x0020E << 15), -+ OPC_LARCH_FMAX_S = (0x00211 << 15), -+ OPC_LARCH_FMAX_D = (0x00212 << 15), -+ OPC_LARCH_FMIN_S = (0x00215 << 15), -+ OPC_LARCH_FMIN_D = (0x00216 << 15), -+ OPC_LARCH_FMAXA_S = (0x00219 << 15), -+ OPC_LARCH_FMAXA_D = (0x0021A << 15), -+ OPC_LARCH_FMINA_S = (0x0021D << 15), -+ OPC_LARCH_FMINA_D = (0x0021E << 15), -+}; -+ -+enum { -+ /* 12 bit immediate opcodes */ -+ OPC_LARCH_SLTI = (0x008 << 22), -+ OPC_LARCH_SLTIU = (0x009 << 22), -+ OPC_LARCH_ADDI_W = (0x00A << 22), -+ OPC_LARCH_ADDI_D = (0x00B << 22), -+ OPC_LARCH_ANDI = (0x00D << 22), -+ OPC_LARCH_ORI = (0x00E << 22), -+ OPC_LARCH_XORI = (0x00F << 22), -+}; -+ -+enum { -+ /* load/store opcodes */ -+ OPC_LARCH_FLDX_S = (0x07060 << 15), -+ OPC_LARCH_FLDX_D = (0x07068 << 15), -+ OPC_LARCH_FSTX_S = (0x07070 << 15), -+ OPC_LARCH_FSTX_D = (0x07078 << 15), -+ OPC_LARCH_FLDGT_S = (0x070E8 << 15), -+ OPC_LARCH_FLDGT_D = (0x070E9 << 15), -+ OPC_LARCH_FLDLE_S = (0x070EA << 15), -+ OPC_LARCH_FLDLE_D = (0x070EB << 15), -+ OPC_LARCH_FSTGT_S = (0x070EC << 15), -+ OPC_LARCH_FSTGT_D = (0x070ED << 15), -+ OPC_LARCH_FSTLE_S = (0x070EE << 15), -+ OPC_LARCH_FSTLE_D = (0x070EF << 15), -+ -+ OPC_LARCH_LD_B = (0x0A0 << 22), -+ OPC_LARCH_LD_H = (0x0A1 << 22), -+ OPC_LARCH_LD_W = (0x0A2 << 22), -+ OPC_LARCH_LD_D = (0x0A3 << 22), -+ OPC_LARCH_ST_B = (0x0A4 << 22), -+ OPC_LARCH_ST_H = (0x0A5 << 22), -+ OPC_LARCH_ST_W = (0x0A6 << 22), -+ OPC_LARCH_ST_D = (0x0A7 << 22), -+ OPC_LARCH_LD_BU = (0x0A8 << 22), -+ OPC_LARCH_LD_HU = (0x0A9 << 22), -+ OPC_LARCH_LD_WU = (0x0AA << 22), -+ OPC_LARCH_FLD_S = (0x0AC << 22), -+ OPC_LARCH_FST_S = (0x0AD << 22), -+ OPC_LARCH_FLD_D = (0x0AE << 22), -+ OPC_LARCH_FST_D = (0x0AF << 22), -+ -+ OPC_LARCH_LL_W = (0x20 << 24), -+ OPC_LARCH_SC_W = (0x21 << 24), -+ OPC_LARCH_LL_D = (0x22 << 24), -+ OPC_LARCH_SC_D = (0x23 << 24), -+ OPC_LARCH_LDPTR_W = (0x24 << 24), -+ OPC_LARCH_STPTR_W = (0x25 << 24), -+ OPC_LARCH_LDPTR_D = (0x26 << 24), -+ OPC_LARCH_STPTR_D = (0x27 << 24), -+}; -+ -+enum { -+ /* jump opcodes */ -+ OPC_LARCH_BEQZ = (0x10 << 26), -+ OPC_LARCH_BNEZ = (0x11 << 26), -+ OPC_LARCH_B = (0x14 << 26), -+ OPC_LARCH_BEQ = (0x16 << 26), -+ OPC_LARCH_BNE = (0x17 << 26), -+ OPC_LARCH_BLT = (0x18 << 26), -+ OPC_LARCH_BGE = (0x19 << 26), -+ OPC_LARCH_BLTU = (0x1A << 26), -+ OPC_LARCH_BGEU = (0x1B << 26), -+}; -+ -+#endif -diff --git a/target/loongarch64/internal.h b/target/loongarch64/internal.h -new file mode 100644 -index 0000000000..79a70e9d26 ---- /dev/null -+++ b/target/loongarch64/internal.h -@@ -0,0 +1,184 @@ -+#ifndef LOONGARCH_INTERNAL_H -+#define LOONGARCH_INTERNAL_H -+ -+#include "cpu-csr.h" -+ -+/* MMU types, the first four entries have the same layout as the -+ CP0C0_MT field. */ -+enum loongarch_mmu_types { -+ MMU_TYPE_NONE, -+ MMU_TYPE_LS3A5K, /* LISA CSR */ -+}; -+ -+ -+ -+struct loongarch_def_t { -+ const char *name; -+ int32_t CSR_PRid; -+ int32_t FCSR0; -+ int32_t FCSR0_rw_bitmask; -+ int32_t PABITS; -+ CPU_LOONGARCH_CSR -+ uint64_t insn_flags; -+ enum loongarch_mmu_types mmu_type; -+ int cpu_cfg[64]; -+}; -+ -+/* loongarch 3a5000 TLB entry */ -+struct ls3a5k_tlb_t { -+ target_ulong VPN; -+ uint64_t PageMask; /* CSR_TLBIDX[29:24] */ -+ uint32_t PageSize; -+ uint16_t ASID; -+ unsigned int G:1; /* CSR_TLBLO[6] */ -+ -+ unsigned int C0:3; /* CSR_TLBLO[5:4] */ -+ unsigned int C1:3; -+ -+ unsigned int V0:1; /* CSR_TLBLO[0] */ -+ unsigned int V1:1; -+ -+ unsigned int WE0:1; /* CSR_TLBLO[1] */ -+ unsigned int WE1:1; -+ -+ unsigned int XI0:1; /* CSR_TLBLO[62] */ -+ unsigned int XI1:1; -+ -+ unsigned int RI0:1; /* CSR_TLBLO[61] */ -+ unsigned int RI1:1; -+ -+ unsigned int EHINV:1;/* CSR_TLBIDX[31] */ -+ -+ unsigned int PLV0:2; /* CSR_TLBLO[3:2] */ -+ unsigned int PLV1:2; -+ -+ unsigned int RPLV0:1; -+ unsigned int RPLV1:1; /* CSR_TLBLO[63] */ -+ -+ uint64_t PPN0; /* CSR_TLBLO[47:12] */ -+ uint64_t PPN1; /* CSR_TLBLO[47:12] */ -+}; -+typedef struct ls3a5k_tlb_t ls3a5k_tlb_t; -+ -+ -+struct CPULOONGARCHTLBContext { -+ uint32_t nb_tlb; -+ uint32_t tlb_in_use; -+ int (*map_address)(struct CPULOONGARCHState *env, hwaddr *physical, int *prot, -+ target_ulong address, int rw, int access_type); -+ void (*helper_tlbwr)(struct CPULOONGARCHState *env); -+ void (*helper_tlbfill)(struct CPULOONGARCHState *env); -+ void (*helper_tlbsrch)(struct CPULOONGARCHState *env); -+ void (*helper_tlbrd)(struct CPULOONGARCHState *env); -+ void (*helper_tlbclr)(struct CPULOONGARCHState *env); -+ void (*helper_tlbflush)(struct CPULOONGARCHState *env); -+ void (*helper_invtlb)(struct CPULOONGARCHState *env, target_ulong addr, -+ target_ulong info, int op); -+ union { -+ struct { -+ uint64_t ftlb_mask; -+ uint32_t ftlb_size; /* at most : 8 * 256 = 2048 */ -+ uint32_t vtlb_size; /* at most : 64 */ -+ ls3a5k_tlb_t tlb[2048 + 64]; /* at most : 2048 FTLB + 64 VTLB */ -+ } ls3a5k; -+ } mmu; -+}; -+ -+enum { -+ TLBRET_PE = -7, -+ TLBRET_XI = -6, -+ TLBRET_RI = -5, -+ TLBRET_DIRTY = -4, -+ TLBRET_INVALID = -3, -+ TLBRET_NOMATCH = -2, -+ TLBRET_BADADDR = -1, -+ TLBRET_MATCH = 0 -+}; -+ -+ -+extern unsigned int ieee_rm[]; -+ -+static inline void restore_rounding_mode(CPULOONGARCHState *env) -+{ -+ set_float_rounding_mode(ieee_rm[(env->active_fpu.fcsr0 >> FCSR0_RM) & 0x3], -+ &env->active_fpu.fp_status); -+} -+ -+static inline void restore_flush_mode(CPULOONGARCHState *env) -+{ -+ set_flush_to_zero(0, &env->active_fpu.fp_status); -+} -+ -+static inline void restore_fp_status(CPULOONGARCHState *env) -+{ -+ restore_rounding_mode(env); -+ restore_flush_mode(env); -+} -+static inline void compute_hflags(CPULOONGARCHState *env) -+{ -+ env->hflags &= ~(LARCH_HFLAG_64 | LARCH_HFLAG_FPU | LARCH_HFLAG_KSU | -+ LARCH_HFLAG_AWRAP | LARCH_HFLAG_LSX | LARCH_HFLAG_LASX); -+ -+ env->hflags |= (env->CSR_CRMD & CSR_CRMD_PLV); -+ env->hflags |= LARCH_HFLAG_64; -+ -+ if (env->CSR_EUEN & CSR_EUEN_FPEN) { -+ env->hflags |= LARCH_HFLAG_FPU; -+ } -+ if (env->CSR_EUEN & CSR_EUEN_LSXEN) { -+ env->hflags |= LARCH_HFLAG_LSX; -+ } -+ if (env->CSR_EUEN & CSR_EUEN_LASXEN) { -+ env->hflags |= LARCH_HFLAG_LASX; -+ } -+ if (env->CSR_EUEN & CSR_EUEN_LBTEN) { -+ env->hflags |= LARCH_HFLAG_LBT; -+ } -+} -+ -+/* Check if there is pending and not masked out interrupt */ -+static inline bool cpu_loongarch_hw_interrupts_pending(CPULOONGARCHState *env) -+{ -+ int32_t pending; -+ int32_t status; -+ bool r; -+ -+ pending = env->CSR_ESTAT & CSR_ESTAT_IPMASK; -+ status = env->CSR_ECFG & CSR_ECFG_IPMASK; -+ -+ /* Configured with compatibility or VInt (Vectored Interrupts) -+ treats the pending lines as individual interrupt lines, the status -+ lines are individual masks. */ -+ r = (pending & status) != 0; -+ -+ return r; -+} -+ -+ -+/* stabletimer.c */ -+uint32_t cpu_loongarch_get_random_ls3a5k_tlb(uint32_t low, uint32_t high); -+uint64_t cpu_loongarch_get_stable_counter(CPULOONGARCHState *env); -+uint64_t cpu_loongarch_get_stable_timer_ticks(CPULOONGARCHState *env); -+void cpu_loongarch_store_stable_timer_config(CPULOONGARCHState *env, uint64_t value); -+int loongarch_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cpu, -+ int cpuid, void *opaque); -+ -+void loongarch_cpu_dump_state(CPUState *cpu, FILE *f, int flags); -+ -+/* TODO QOM'ify CPU reset and remove */ -+void cpu_state_reset(CPULOONGARCHState *s); -+void cpu_loongarch_realize_env(CPULOONGARCHState *env); -+ -+int loongarch_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n); -+int loongarch_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg); -+ -+#ifdef CONFIG_TCG -+#include "fpu_helper.h" -+#endif -+ -+#ifndef CONFIG_USER_ONLY -+extern const struct VMStateDescription vmstate_loongarch_cpu; -+hwaddr loongarch_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr); -+#endif -+ -+#endif -diff --git a/target/loongarch64/kvm.c b/target/loongarch64/kvm.c -new file mode 100644 -index 0000000000..404a605eb6 ---- /dev/null -+++ b/target/loongarch64/kvm.c -@@ -0,0 +1,1622 @@ -+/* -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file "COPYING" in the main directory of this archive -+ * for more details. -+ * -+ * KVM/LOONGARCH: LOONGARCH specific KVM APIs -+ * -+ * Copyright (C) 2012-2014 Imagination Technologies Ltd. -+ * Authors: Sanjay Lal -+*/ -+ -+#include "qemu/osdep.h" -+#include -+ -+#include -+ -+#include "qemu-common.h" -+#include "cpu.h" -+#include "internal.h" -+#include "qemu/error-report.h" -+#include "qemu/timer.h" -+#include "qemu/main-loop.h" -+#include "sysemu/sysemu.h" -+#include "sysemu/kvm.h" -+#include "sysemu/runstate.h" -+#include "sysemu/cpus.h" -+#include "kvm_larch.h" -+#include "exec/memattrs.h" -+#include "exec/gdbstub.h" -+ -+#define DEBUG_KVM 0 -+/* A 16384-byte buffer can hold the 8-byte kvm_msrs header, plus -+ * 2047 kvm_msr_entry structs */ -+#define MSR_BUF_SIZE 16384 -+ -+#define DPRINTF(fmt, ...) \ -+ do { if (DEBUG_KVM) { fprintf(stderr, fmt, ## __VA_ARGS__); } } while (0) -+ -+/* -+ * Define loongarch kvm version. -+ * Add version number when -+ * qemu/kvm interface changed -+ */ -+#define KVM_LOONGARCH_VERSION 1 -+ -+static struct { -+ target_ulong addr; -+ int len; -+ int type; -+} inst_breakpoint[8], data_breakpoint[8]; -+ -+int nb_data_breakpoint = 0, nb_inst_breakpoint = 0; -+static int kvm_loongarch_version_cap; -+ -+/* Hardware breakpoint control register -+ * 4:1 plv0-plv3 enable -+ * 6:5 config virtualization mode -+ * 9:8 load store */ -+static const int type_code[] = { -+ [GDB_BREAKPOINT_HW] = 0x5e, -+ [GDB_WATCHPOINT_READ] = (0x5e | 1 << 8), -+ [GDB_WATCHPOINT_WRITE] = (0x5e | 1 << 9), -+ [GDB_WATCHPOINT_ACCESS] = (0x5e | 1 << 8 | 1 << 9) -+}; -+ -+const KVMCapabilityInfo kvm_arch_required_capabilities[] = { -+ KVM_CAP_LAST_INFO -+}; -+ -+static void kvm_loongarch_update_state(void *opaque, bool running, RunState state); -+static inline int kvm_larch_putq(CPUState *cs, uint64_t reg_id, uint64_t *addr); -+ -+unsigned long kvm_arch_vcpu_id(CPUState *cs) -+{ -+ return cs->cpu_index; -+} -+ -+int kvm_arch_init(MachineState *ms, KVMState *s) -+{ -+ /* LOONGARCH has 128 signals */ -+ kvm_set_sigmask_len(s, 16); -+ -+ kvm_loongarch_version_cap = kvm_check_extension(s, KVM_CAP_LOONGARCH_VZ); -+ -+ if (kvm_loongarch_version_cap != KVM_LOONGARCH_VERSION) { -+ warn_report("QEMU/KVM version not match, qemu_la_version: lvz-%d,\ -+ kvm_la_version: lvz-%d \n", -+ KVM_LOONGARCH_VERSION, kvm_loongarch_version_cap); -+ } -+ return 0; -+} -+ -+int kvm_arch_irqchip_create(KVMState *s) -+{ -+ return 0; -+} -+ -+int kvm_arch_init_vcpu(CPUState *cs) -+{ -+ LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); -+ int ret = 0; -+ -+ cpu->cpuStateEntry = qemu_add_vm_change_state_handler(kvm_loongarch_update_state, cs); -+ cpu->kvm_msr_buf = g_malloc0(MSR_BUF_SIZE); -+ DPRINTF("%s\n", __func__); -+ return ret; -+} -+ -+int kvm_arch_destroy_vcpu(CPUState *cs) -+{ -+ return 0; -+} -+ -+static void kvm_msr_buf_reset(LOONGARCHCPU *cpu) -+{ -+ memset(cpu->kvm_msr_buf, 0, MSR_BUF_SIZE); -+} -+ -+static void kvm_msr_entry_add(LOONGARCHCPU *cpu, uint32_t index, uint64_t value) -+{ -+ struct kvm_msrs *msrs = cpu->kvm_msr_buf; -+ void *limit = ((void *)msrs) + MSR_BUF_SIZE; -+ struct kvm_csr_entry *entry = &msrs->entries[msrs->ncsrs]; -+ -+ assert((void *)(entry + 1) <= limit); -+ -+ entry->index = index; -+ entry->reserved = 0; -+ entry->data = value; -+ msrs->ncsrs++; -+} -+ -+void kvm_loongarch_reset_vcpu(LOONGARCHCPU *cpu) -+{ -+ int ret = 0; -+ uint64_t reset = 1; -+ -+ if (CPU(cpu)->kvm_fd > 0) { -+ ret = kvm_larch_putq(CPU(cpu), KVM_REG_LOONGARCH_VCPU_RESET, &reset); -+ if (ret < 0) { -+ error_report("%s reset vcpu failed:%d", __func__, ret); -+ } -+ } -+ -+ DPRINTF("%s\n", __func__); -+} -+ -+void kvm_arch_update_guest_debug(CPUState *cpu, struct kvm_guest_debug *dbg) -+{ -+ int n; -+ if (kvm_sw_breakpoints_active(cpu)) { -+ dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP; -+ } -+ if (nb_data_breakpoint > 0) { -+ dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_HW_BP; -+ for (n = 0; n < nb_data_breakpoint; n++) { -+ dbg->arch.data_breakpoint[n].addr = data_breakpoint[n].addr; -+ dbg->arch.data_breakpoint[n].mask = 0; -+ dbg->arch.data_breakpoint[n].asid = 0; -+ dbg->arch.data_breakpoint[n].ctrl = type_code[data_breakpoint[n].type]; -+ } -+ dbg->arch.data_bp_nums = nb_data_breakpoint; -+ } else { -+ dbg->arch.data_bp_nums = 0; -+ } -+ if (nb_inst_breakpoint > 0) { -+ dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_HW_BP; -+ for (n = 0; n < nb_inst_breakpoint; n++) { -+ dbg->arch.inst_breakpoint[n].addr = inst_breakpoint[n].addr; -+ dbg->arch.inst_breakpoint[n].mask = 0; -+ dbg->arch.inst_breakpoint[n].asid = 0; -+ dbg->arch.inst_breakpoint[n].ctrl = type_code[inst_breakpoint[n].type]; -+ } -+ dbg->arch.inst_bp_nums = nb_inst_breakpoint; -+ } else { -+ dbg->arch.inst_bp_nums = 0; -+ } -+} -+ -+static const unsigned int brk_insn = 0x002b8005; -+ -+int kvm_arch_insert_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp) -+{ -+ DPRINTF("%s\n", __func__); -+ if (cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&bp->saved_insn, 4, 0) || -+ cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&brk_insn, 4, 1)) { -+ error_report("%s failed", __func__); -+ return -EINVAL; -+ } -+ return 0; -+} -+ -+int kvm_arch_remove_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp) -+{ -+ static uint32_t brk; -+ -+ DPRINTF("%s\n", __func__); -+ if (cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&brk, 4, 0) || -+ brk != brk_insn || -+ cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&bp->saved_insn, 4, 1)) { -+ error_report("%s failed", __func__); -+ return -EINVAL; -+ } -+ return 0; -+} -+ -+static int find_hw_breakpoint(uint64_t addr, int len, int type) -+{ -+ int n; -+ switch (type) { -+ case GDB_BREAKPOINT_HW: -+ if (nb_inst_breakpoint == 0) { -+ return -1; -+ } -+ for (n = 0; n < nb_inst_breakpoint; n++) { -+ if (inst_breakpoint[n].addr == addr && inst_breakpoint[n].type == type) { -+ return n; -+ } -+ } -+ break; -+ case GDB_WATCHPOINT_WRITE: -+ case GDB_WATCHPOINT_READ: -+ case GDB_WATCHPOINT_ACCESS: -+ if (nb_data_breakpoint == 0) { -+ return -1; -+ } -+ for (n = 0; n < nb_data_breakpoint; n++) { -+ if (data_breakpoint[n].addr == addr && data_breakpoint[n].type == type && -+ data_breakpoint[n].len == len) { -+ return n; -+ } -+ } -+ break; -+ default: -+ return -1; -+ } -+ return -1; -+} -+ -+int kvm_arch_insert_hw_breakpoint(target_ulong addr, -+ target_ulong len, int type) -+{ -+ switch (type) { -+ case GDB_BREAKPOINT_HW: -+ len = 1; -+ if (nb_inst_breakpoint == 8) { -+ return -ENOBUFS; -+ } -+ if (find_hw_breakpoint(addr, len, type) >= 0) { -+ return -EEXIST; -+ } -+ inst_breakpoint[nb_inst_breakpoint].addr = addr; -+ inst_breakpoint[nb_inst_breakpoint].len = len; -+ inst_breakpoint[nb_inst_breakpoint].type = type; -+ nb_inst_breakpoint++; -+ break; -+ case GDB_WATCHPOINT_WRITE: -+ case GDB_WATCHPOINT_READ: -+ case GDB_WATCHPOINT_ACCESS: -+ switch (len) { -+ case 1: -+ case 2: -+ case 4: -+ case 8: -+ if (addr & (len - 1)) { -+ return -EINVAL; -+ } -+ if (nb_data_breakpoint == 8) { -+ return -ENOBUFS; -+ } -+ if (find_hw_breakpoint(addr, len, type) >= 0) { -+ return -EEXIST; -+ } -+ data_breakpoint[nb_data_breakpoint].addr = addr; -+ data_breakpoint[nb_data_breakpoint].len = len; -+ data_breakpoint[nb_data_breakpoint].type = type; -+ nb_data_breakpoint++; -+ break; -+ default: -+ return -EINVAL; -+ } -+ break; -+ default: -+ return -ENOSYS; -+ } -+ return 0; -+} -+ -+int kvm_arch_remove_hw_breakpoint(target_ulong addr, -+ target_ulong len, int type) -+{ -+ int n; -+ n = find_hw_breakpoint(addr, (type == GDB_BREAKPOINT_HW) ? 1 : len, type); -+ if (n < 0) { -+ printf("err not find remove target\n"); -+ return -ENOENT; -+ } -+ switch (type) { -+ case GDB_BREAKPOINT_HW: -+ nb_inst_breakpoint--; -+ inst_breakpoint[n] = inst_breakpoint[nb_inst_breakpoint]; -+ break; -+ case GDB_WATCHPOINT_WRITE: -+ case GDB_WATCHPOINT_READ: -+ case GDB_WATCHPOINT_ACCESS: -+ nb_data_breakpoint--; -+ data_breakpoint[n] = data_breakpoint[nb_data_breakpoint]; -+ break; -+ default: -+ return -1; -+ } -+ return 0; -+} -+ -+void kvm_arch_remove_all_hw_breakpoints(void) -+{ -+ DPRINTF("%s\n", __func__); -+ nb_data_breakpoint = 0; -+ nb_inst_breakpoint = 0; -+} -+ -+static inline int cpu_loongarch_io_interrupts_pending(LOONGARCHCPU *cpu) -+{ -+ CPULOONGARCHState *env = &cpu->env; -+ -+ return env->CSR_ESTAT & (0x1 << 2); -+} -+ -+void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run) -+{ -+ LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); -+ int r; -+ struct kvm_loongarch_interrupt intr; -+ -+ qemu_mutex_lock_iothread(); -+ -+ if ((cs->interrupt_request & CPU_INTERRUPT_HARD) && -+ cpu_loongarch_io_interrupts_pending(cpu)) { -+ intr.cpu = -1; -+ intr.irq = 2; -+ r = kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &intr); -+ if (r < 0) { -+ error_report("%s: cpu %d: failed to inject IRQ %x", -+ __func__, cs->cpu_index, intr.irq); -+ } -+ } -+ -+ qemu_mutex_unlock_iothread(); -+} -+ -+MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run) -+{ -+ return MEMTXATTRS_UNSPECIFIED; -+} -+ -+int kvm_arch_process_async_events(CPUState *cs) -+{ -+ return cs->halted; -+} -+ -+static CPUWatchpoint hw_watchpoint; -+ -+static bool kvm_loongarch_handle_debug(CPUState *cs, struct kvm_run *run) -+{ -+ LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); -+ CPULOONGARCHState *env = &cpu->env; -+ int i; -+ bool ret = false; -+ kvm_cpu_synchronize_state(cs); -+ if (cs->singlestep_enabled) { -+ return true; -+ } -+ if (kvm_find_sw_breakpoint(cs, env->active_tc.PC)) { -+ return true; -+ } -+ /* hw breakpoint */ -+ if (run->debug.arch.exception == EXCCODE_WATCH) { -+ for (i = 0; i < 8; i++) { -+ if (run->debug.arch.fwps & (1 << i)) { -+ ret = true; -+ break; -+ } -+ } -+ for (i = 0; i < 8; i++) { -+ if (run->debug.arch.mwps & (1 << i)) { -+ cs->watchpoint_hit = &hw_watchpoint; -+ hw_watchpoint.vaddr = data_breakpoint[i].addr; -+ switch (data_breakpoint[i].type) { -+ case GDB_WATCHPOINT_READ: -+ ret = true; -+ hw_watchpoint.flags = BP_MEM_READ; -+ break; -+ case GDB_WATCHPOINT_WRITE: -+ ret = true; -+ hw_watchpoint.flags = BP_MEM_WRITE; -+ break; -+ case GDB_WATCHPOINT_ACCESS: -+ ret = true; -+ hw_watchpoint.flags = BP_MEM_ACCESS; -+ break; -+ } -+ } -+ } -+ run->debug.arch.exception = 0; -+ run->debug.arch.fwps = 0; -+ run->debug.arch.mwps = 0; -+ } -+ return ret; -+} -+ -+int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) -+{ -+ int ret; -+ -+ DPRINTF("%s\n", __func__); -+ switch (run->exit_reason) { -+ case KVM_EXIT_HYPERCALL: -+ DPRINTF("handle LOONGARCH hypercall\n"); -+ ret = 0; -+ run->hypercall.ret = ret; -+ break; -+ -+ case KVM_EXIT_DEBUG: -+ ret = 0; -+ if (kvm_loongarch_handle_debug(cs, run)) { -+ ret = EXCP_DEBUG; -+ } -+ break; -+ default: -+ error_report("%s: unknown exit reason %d", -+ __func__, run->exit_reason); -+ ret = -1; -+ break; -+ } -+ -+ return ret; -+} -+ -+bool kvm_arch_stop_on_emulation_error(CPUState *cs) -+{ -+ DPRINTF("%s\n", __func__); -+ return true; -+} -+/* -+#if 0 -+int kvmloongarch_load_kernel(CPUState *env, void *ram_base) -+{ -+ int ret; -+ -+ ret = kvm_vcpu_ioctl(env, KVM_LOAD_KERNEL, ram_base); -+ -+ return ret; -+} -+#endif -+*/ -+void kvm_arch_init_irq_routing(KVMState *s) -+{ -+} -+ -+int kvm_loongarch_set_interrupt(LOONGARCHCPU *cpu, int irq, int level) -+{ -+ CPUState *cs = CPU(cpu); -+ struct kvm_loongarch_interrupt intr; -+ -+ if (!kvm_enabled()) { -+ return 0; -+ } -+ -+ intr.cpu = -1; -+ -+ if (level) { -+ intr.irq = irq; -+ } else { -+ intr.irq = -irq; -+ } -+ -+ kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &intr); -+ -+ return 0; -+} -+ -+int kvm_loongarch_set_ipi_interrupt(LOONGARCHCPU *cpu, int irq, int level) -+{ -+ CPUState *cs = current_cpu; -+ CPUState *dest_cs = CPU(cpu); -+ struct kvm_loongarch_interrupt intr; -+ -+ if (!kvm_enabled()) { -+ return 0; -+ } -+ -+ intr.cpu = dest_cs->cpu_index; -+ -+ if (level) { -+ intr.irq = irq; -+ } else { -+ intr.irq = -irq; -+ } -+ -+ DPRINTF("%s: IRQ: %d\n", __func__, intr.irq); -+ if (!current_cpu) { -+ cs = dest_cs; -+ } -+ kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &intr); -+ -+ return 0; -+} -+ -+static inline int kvm_loongarch_put_one_reg(CPUState *cs, uint64_t reg_id, -+ int32_t *addr) -+{ -+ struct kvm_one_reg csrreg = { -+ .id = reg_id, -+ .addr = (uintptr_t)addr -+ }; -+ -+ return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &csrreg); -+} -+ -+static inline int kvm_loongarch_put_one_ureg(CPUState *cs, uint64_t reg_id, -+ uint32_t *addr) -+{ -+ struct kvm_one_reg csrreg = { -+ .id = reg_id, -+ .addr = (uintptr_t)addr -+ }; -+ -+ return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &csrreg); -+} -+ -+static inline int kvm_loongarch_put_one_ulreg(CPUState *cs, uint64_t reg_id, -+ target_ulong *addr) -+{ -+ uint64_t val64 = *addr; -+ struct kvm_one_reg csrreg = { -+ .id = reg_id, -+ .addr = (uintptr_t)&val64 -+ }; -+ -+ return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &csrreg); -+} -+ -+static inline int kvm_loongarch_put_one_reg64(CPUState *cs, int64_t reg_id, -+ int64_t *addr) -+{ -+ struct kvm_one_reg csrreg = { -+ .id = reg_id, -+ .addr = (uintptr_t)addr -+ }; -+ -+ return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &csrreg); -+} -+ -+static inline int kvm_larch_putq(CPUState *cs, uint64_t reg_id, -+ uint64_t *addr) -+{ -+ struct kvm_one_reg csrreg = { -+ .id = reg_id, -+ .addr = (uintptr_t)addr -+ }; -+ -+ return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &csrreg); -+} -+ -+static inline int kvm_loongarch_get_one_reg(CPUState *cs, uint64_t reg_id, -+ int32_t *addr) -+{ -+ struct kvm_one_reg csrreg = { -+ .id = reg_id, -+ .addr = (uintptr_t)addr -+ }; -+ -+ return kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &csrreg); -+} -+ -+static inline int kvm_loongarch_get_one_ureg(CPUState *cs, uint64_t reg_id, -+ uint32_t *addr) -+{ -+ struct kvm_one_reg csrreg = { -+ .id = reg_id, -+ .addr = (uintptr_t)addr -+ }; -+ -+ return kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &csrreg); -+} -+ -+static inline int kvm_loongarch_get_one_ulreg(CPUState *cs, uint64_t reg_id, -+ target_ulong *addr) -+{ -+ int ret; -+ uint64_t val64 = 0; -+ struct kvm_one_reg csrreg = { -+ .id = reg_id, -+ .addr = (uintptr_t)&val64 -+ }; -+ -+ ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &csrreg); -+ if (ret >= 0) { -+ *addr = val64; -+ } -+ return ret; -+} -+ -+static inline int kvm_loongarch_get_one_reg64(CPUState *cs, int64_t reg_id, -+ int64_t *addr) -+{ -+ struct kvm_one_reg csrreg = { -+ .id = reg_id, -+ .addr = (uintptr_t)addr -+ }; -+ -+ return kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &csrreg); -+} -+ -+static inline int kvm_larch_getq(CPUState *cs, uint64_t reg_id, -+ uint64_t *addr) -+{ -+ struct kvm_one_reg csrreg = { -+ .id = reg_id, -+ .addr = (uintptr_t)addr -+ }; -+ -+ return kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &csrreg); -+} -+ -+static inline int kvm_loongarch_change_one_reg(CPUState *cs, uint64_t reg_id, -+ int32_t *addr, int32_t mask) -+{ -+ int err; -+ int32_t tmp, change; -+ -+ err = kvm_loongarch_get_one_reg(cs, reg_id, &tmp); -+ if (err < 0) { -+ return err; -+ } -+ -+ /* only change bits in mask */ -+ change = (*addr ^ tmp) & mask; -+ if (!change) { -+ return 0; -+ } -+ -+ tmp = tmp ^ change; -+ return kvm_loongarch_put_one_reg(cs, reg_id, &tmp); -+} -+ -+static inline int kvm_loongarch_change_one_reg64(CPUState *cs, uint64_t reg_id, -+ int64_t *addr, int64_t mask) -+{ -+ int err; -+ int64_t tmp, change; -+ -+ err = kvm_loongarch_get_one_reg64(cs, reg_id, &tmp); -+ if (err < 0) { -+ DPRINTF("%s: Failed to get CSR_CONFIG7 (%d)\n", __func__, err); -+ return err; -+ } -+ -+ /* only change bits in mask */ -+ change = (*addr ^ tmp) & mask; -+ if (!change) { -+ return 0; -+ } -+ -+ tmp = tmp ^ change; -+ return kvm_loongarch_put_one_reg64(cs, reg_id, &tmp); -+} -+/* -+ * Handle the VM clock being started or stopped -+ */ -+static void kvm_loongarch_update_state(void *opaque, bool running, RunState state) -+{ -+ CPUState *cs = opaque; -+ int ret; -+ LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); -+ -+ /* -+ * If state is already dirty (synced to QEMU) then the KVM timer state is -+ * already saved and can be restored when it is synced back to KVM. -+ */ -+ if (!running) { -+ ret = kvm_larch_getq(cs, -+ KVM_REG_LOONGARCH_COUNTER, &cpu->counter_value); -+ if (ret < 0) { -+ printf("%s: Failed to get counter_value (%d)\n", __func__, ret); -+ } -+ -+ } else { -+ ret = kvm_larch_putq(cs, KVM_REG_LOONGARCH_COUNTER, -+ &(LOONGARCH_CPU(cs))->counter_value); -+ if (ret < 0) { -+ printf("%s: Failed to put counter_value (%d)\n", __func__, ret); -+ } -+ } -+} -+ -+static int kvm_loongarch_put_fpu_registers(CPUState *cs, int level) -+{ -+ LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); -+ CPULOONGARCHState *env = &cpu->env; -+ int err, ret = 0; -+ unsigned int i; -+ struct kvm_fpu fpu; -+ -+ fpu.fcsr = env->active_fpu.fcsr0; -+ for (i = 0; i < 32; i++) { -+ memcpy(&fpu.fpr[i], &env->active_fpu.fpr[i], sizeof(struct kvm_fpureg)); -+ } -+ for (i = 0; i < 8; i++) { -+ ((char *)&fpu.fcc)[i] = env->active_fpu.cf[i]; -+ } -+ fpu.vcsr = env->active_fpu.vcsr16; -+ -+ err = kvm_vcpu_ioctl(cs, KVM_SET_FPU, &fpu); -+ if (err < 0) { -+ DPRINTF("%s: Failed to get FPU (%d)\n", __func__, err); -+ ret = err; -+ } -+ -+ return ret; -+} -+ -+static int kvm_loongarch_get_fpu_registers(CPUState *cs) -+{ -+ LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); -+ CPULOONGARCHState *env = &cpu->env; -+ int err, ret = 0; -+ unsigned int i; -+ struct kvm_fpu fpu; -+ -+ err = kvm_vcpu_ioctl(cs, KVM_GET_FPU, &fpu); -+ if (err < 0) { -+ DPRINTF("%s: Failed to get FPU (%d)\n", __func__, err); -+ ret = err; -+ } else { -+ env->active_fpu.fcsr0 = fpu.fcsr; -+ for (i = 0; i < 32; i++) { -+ memcpy(&env->active_fpu.fpr[i], &fpu.fpr[i], sizeof(struct kvm_fpureg)); -+ } -+ for (i = 0; i < 8; i++) { -+ env->active_fpu.cf[i] = ((char *)&fpu.fcc)[i]; -+ } -+ env->active_fpu.vcsr16 = fpu.vcsr; -+ } -+ -+ return ret; -+} -+ -+#define KVM_PUT_ONE_UREG64(cs, regidx, addr) \ -+ ({ \ -+ int err; \ -+ uint64_t csrid = 0; \ -+ csrid = (KVM_IOC_CSRID(regidx)); \ -+ err = kvm_larch_putq(cs, csrid, addr); \ -+ if (err < 0) { \ -+ DPRINTF("%s: Failed to put regidx 0x%x err:%d\n", __func__, regidx, err); \ -+ } \ -+ err; \ -+ }) -+ -+ -+static int kvm_loongarch_put_csr_registers(CPUState *cs, int level) -+{ -+ LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); -+ CPULOONGARCHState *env = &cpu->env; -+ int ret = 0; -+ -+ (void)level; -+ -+ kvm_msr_buf_reset(cpu); -+ -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_CRMD, env->CSR_CRMD); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PRMD, env->CSR_PRMD); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_EUEN, env->CSR_EUEN); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_MISC, env->CSR_MISC); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_ECFG, env->CSR_ECFG); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_ESTAT, env->CSR_ESTAT); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_ERA, env->CSR_ERA); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_BADV, env->CSR_BADV); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_BADI, env->CSR_BADI); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_EEPN, env->CSR_EEPN); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBIDX, env->CSR_TLBIDX); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBEHI, env->CSR_TLBEHI); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBELO0, env->CSR_TLBELO0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBELO1, env->CSR_TLBELO1); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_GTLBC, env->CSR_GTLBC); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_TRGP, env->CSR_TRGP); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_ASID, env->CSR_ASID); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PGDL, env->CSR_PGDL); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PGDH, env->CSR_PGDH); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PGD, env->CSR_PGD); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PWCTL0, env->CSR_PWCTL0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PWCTL1, env->CSR_PWCTL1); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_STLBPGSIZE, env->CSR_STLBPGSIZE); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_RVACFG, env->CSR_RVACFG); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_CPUID, env->CSR_CPUID); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PRCFG1, env->CSR_PRCFG1); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PRCFG2, env->CSR_PRCFG2); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PRCFG3, env->CSR_PRCFG3); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS0, env->CSR_KS0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS1, env->CSR_KS1); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS2, env->CSR_KS2); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS3, env->CSR_KS3); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS4, env->CSR_KS4); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS5, env->CSR_KS5); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS6, env->CSR_KS6); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS7, env->CSR_KS7); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_TMID, env->CSR_TMID); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_CNTC, env->CSR_CNTC); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_TINTCLR, env->CSR_TINTCLR); -+ -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_GSTAT, env->CSR_GSTAT); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_GCFG, env->CSR_GCFG); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_GINTC, env->CSR_GINTC); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_GCNTC, env->CSR_GCNTC); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_LLBCTL, env->CSR_LLBCTL); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IMPCTL1, env->CSR_IMPCTL1); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IMPCTL2, env->CSR_IMPCTL2); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_GNMI, env->CSR_GNMI); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBRENT, env->CSR_TLBRENT); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBRBADV, env->CSR_TLBRBADV); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBRERA, env->CSR_TLBRERA); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBRSAVE, env->CSR_TLBRSAVE); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBRELO0, env->CSR_TLBRELO0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBRELO1, env->CSR_TLBRELO1); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBREHI, env->CSR_TLBREHI); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBRPRMD, env->CSR_TLBRPRMD); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_ERRCTL, env->CSR_ERRCTL); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_ERRINFO, env->CSR_ERRINFO); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_ERRINFO1, env->CSR_ERRINFO1); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_ERRENT, env->CSR_ERRENT); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_ERRERA, env->CSR_ERRERA); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_ERRSAVE, env->CSR_ERRSAVE); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_CTAG, env->CSR_CTAG); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DMWIN0, env->CSR_DMWIN0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DMWIN1, env->CSR_DMWIN1); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DMWIN2, env->CSR_DMWIN2); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DMWIN3, env->CSR_DMWIN3); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCTRL0, env->CSR_PERFCTRL0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCNTR0, env->CSR_PERFCNTR0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCTRL1, env->CSR_PERFCTRL1); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCNTR1, env->CSR_PERFCNTR1); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCTRL2, env->CSR_PERFCTRL2); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCNTR2, env->CSR_PERFCNTR2); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCTRL3, env->CSR_PERFCTRL3); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCNTR3, env->CSR_PERFCNTR3); -+ -+ /* debug */ -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_MWPC, env->CSR_MWPC); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_MWPS, env->CSR_MWPS); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB0ADDR, env->CSR_DB0ADDR); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB0MASK, env->CSR_DB0MASK); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB0CTL, env->CSR_DB0CTL); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB0ASID, env->CSR_DB0ASID); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB1ADDR, env->CSR_DB1ADDR); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB1MASK, env->CSR_DB1MASK); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB1CTL, env->CSR_DB1CTL); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB1ASID, env->CSR_DB1ASID); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB2ADDR, env->CSR_DB2ADDR); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB2MASK, env->CSR_DB2MASK); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB2CTL, env->CSR_DB2CTL); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB2ASID, env->CSR_DB2ASID); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB3ADDR, env->CSR_DB3ADDR); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB3MASK, env->CSR_DB3MASK); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB3CTL, env->CSR_DB3CTL); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB3ASID, env->CSR_DB3ASID); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_FWPC, env->CSR_FWPC); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_FWPS, env->CSR_FWPS); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB0ADDR, env->CSR_IB0ADDR); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB0MASK, env->CSR_IB0MASK); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB0CTL, env->CSR_IB0CTL); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB0ASID, env->CSR_IB0ASID); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB1ADDR, env->CSR_IB1ADDR); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB1MASK, env->CSR_IB1MASK); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB1CTL, env->CSR_IB1CTL); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB1ASID, env->CSR_IB1ASID); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB2ADDR, env->CSR_IB2ADDR); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB2MASK, env->CSR_IB2MASK); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB2CTL, env->CSR_IB2CTL); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB2ASID, env->CSR_IB2ASID); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB3ADDR, env->CSR_IB3ADDR); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB3MASK, env->CSR_IB3MASK); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB3CTL, env->CSR_IB3CTL); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB3ASID, env->CSR_IB3ASID); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB4ADDR, env->CSR_IB4ADDR); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB4MASK, env->CSR_IB4MASK); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB4CTL, env->CSR_IB4CTL); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB4ASID, env->CSR_IB4ASID); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB5ADDR, env->CSR_IB5ADDR); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB5MASK, env->CSR_IB5MASK); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB5CTL, env->CSR_IB5CTL); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB5ASID, env->CSR_IB5ASID); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB6ADDR, env->CSR_IB6ADDR); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB6MASK, env->CSR_IB6MASK); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB6CTL, env->CSR_IB6CTL); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB6ASID, env->CSR_IB6ASID); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB7ADDR, env->CSR_IB7ADDR); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB7MASK, env->CSR_IB7MASK); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB7CTL, env->CSR_IB7CTL); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB7ASID, env->CSR_IB7ASID); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DEBUG, env->CSR_DEBUG); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DERA, env->CSR_DERA); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DESAVE, env->CSR_DESAVE); -+ -+ ret = kvm_vcpu_ioctl(cs, KVM_SET_MSRS, cpu->kvm_msr_buf); -+ if (ret < cpu->kvm_msr_buf->ncsrs) { -+ struct kvm_csr_entry *e = &cpu->kvm_msr_buf->entries[ret]; -+ printf("error: failed to set CSR 0x%" PRIx32 " to 0x%" PRIx64"\n", -+ (uint32_t)e->index, (uint64_t)e->data); -+ } -+ -+ /* -+ * timer cfg must be put at last since it is used to enable -+ * guest timer -+ */ -+ ret |= KVM_PUT_ONE_UREG64(cs, LOONGARCH_CSR_TVAL, &env->CSR_TVAL); -+ ret |= KVM_PUT_ONE_UREG64(cs, LOONGARCH_CSR_TCFG, &env->CSR_TCFG); -+ return ret; -+} -+ -+#define KVM_GET_ONE_UREG64(cs, regidx, addr) \ -+ ({ \ -+ int err; \ -+ uint64_t csrid = 0; \ -+ csrid = (KVM_IOC_CSRID(regidx)); \ -+ err = kvm_larch_getq(cs, csrid, addr); \ -+ if (err < 0) { \ -+ DPRINTF("%s: Failed to put regidx 0x%x err:%d\n", __func__, regidx, err); \ -+ } \ -+ err; \ -+ }) -+ -+static int kvm_loongarch_get_csr_registers(CPUState *cs) -+{ -+ LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); -+ CPULOONGARCHState *env = &cpu->env; -+ int ret = 0, i; -+ struct kvm_csr_entry *csrs = cpu->kvm_msr_buf->entries; -+ -+ kvm_msr_buf_reset(cpu); -+ -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_CRMD, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PRMD, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_EUEN, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_MISC, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_ECFG, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_ESTAT, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_ERA, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_BADV, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_BADI, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_EEPN, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBIDX, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBEHI, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBELO0, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBELO1, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_GTLBC, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_TRGP, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_ASID, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PGDL, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PGDH, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PGD, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PWCTL0, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PWCTL1, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_STLBPGSIZE, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_RVACFG, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_CPUID, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PRCFG1, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PRCFG2, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PRCFG3, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS0, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS1, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS2, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS3, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS4, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS5, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS6, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS7, 0); -+ -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_TMID, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_CNTC, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_TINTCLR, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_GSTAT, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_GCFG, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_GINTC, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_GCNTC, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_LLBCTL, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IMPCTL1, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IMPCTL2, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_GNMI, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBRENT, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBRBADV, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBRERA, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBRSAVE, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBRELO0, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBRELO1, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBREHI, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBRPRMD, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_ERRCTL, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_ERRINFO, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_ERRINFO1, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_ERRENT, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_ERRERA, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_ERRSAVE, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_CTAG, 0); -+ -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DMWIN0, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DMWIN1, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DMWIN2, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DMWIN3, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCTRL0, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCNTR0, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCTRL1, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCNTR1, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCTRL2, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCNTR2, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCTRL3, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCNTR3, 0); -+ -+ /* debug */ -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_MWPC, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_MWPS, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB0ADDR, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB0MASK, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB0CTL, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB0ASID, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB1ADDR, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB1MASK, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB1CTL, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB1ASID, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB2ADDR, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB2MASK, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB2CTL, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB2ASID, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB3ADDR, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB3MASK, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB3CTL, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB3ASID, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_FWPC, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_FWPS, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB0ADDR, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB0MASK, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB0CTL, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB0ASID, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB1ADDR, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB1MASK, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB1CTL, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB1ASID, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB2ADDR, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB2MASK, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB2CTL, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB2ASID, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB3ADDR, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB3MASK, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB3CTL, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB3ASID, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB4ADDR, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB4MASK, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB4CTL, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB4ASID, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB5ADDR, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB5MASK, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB5CTL, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB5ASID, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB6ADDR, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB6MASK, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB6CTL, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB6ASID, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB7ADDR, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB7MASK, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB7CTL, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB7ASID, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DEBUG, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DERA, 0); -+ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DESAVE, 0); -+ -+ ret = kvm_vcpu_ioctl(cs, KVM_GET_MSRS, cpu->kvm_msr_buf); -+ if (ret < cpu->kvm_msr_buf->ncsrs) { -+ struct kvm_csr_entry *e = &cpu->kvm_msr_buf->entries[ret]; -+ printf("error: failed to get CSR 0x%" PRIx32"\n", -+ (uint32_t)e->index); -+ } -+ -+ for (i = 0; i < ret; i++) { -+ uint32_t index = csrs[i].index; -+ -+ switch (index) { -+ case LOONGARCH_CSR_CRMD: -+ env->CSR_CRMD = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_PRMD: -+ env->CSR_PRMD = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_EUEN: -+ env->CSR_EUEN = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_MISC: -+ env->CSR_MISC = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_ECFG: -+ env->CSR_ECFG = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_ESTAT: -+ env->CSR_ESTAT = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_ERA: -+ env->CSR_ERA = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_BADV: -+ env->CSR_BADV = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_BADI: -+ env->CSR_BADI = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_EEPN: -+ env->CSR_EEPN = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_TLBIDX: -+ env->CSR_TLBIDX = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_TLBEHI: -+ env->CSR_TLBEHI = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_TLBELO0: -+ env->CSR_TLBELO0 = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_TLBELO1: -+ env->CSR_TLBELO1 = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_GTLBC: -+ env->CSR_GTLBC = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_TRGP: -+ env->CSR_TRGP = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_ASID: -+ env->CSR_ASID = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_PGDL: -+ env->CSR_PGDL = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_PGDH: -+ env->CSR_PGDH = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_PGD: -+ env->CSR_PGD = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_PWCTL0: -+ env->CSR_PWCTL0 = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_PWCTL1: -+ env->CSR_PWCTL1 = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_STLBPGSIZE: -+ env->CSR_STLBPGSIZE = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_RVACFG: -+ env->CSR_RVACFG = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_CPUID: -+ env->CSR_CPUID = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_PRCFG1: -+ env->CSR_PRCFG1 = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_PRCFG2: -+ env->CSR_PRCFG2 = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_PRCFG3: -+ env->CSR_PRCFG3 = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_KS0: -+ env->CSR_KS0 = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_KS1: -+ env->CSR_KS1 = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_KS2: -+ env->CSR_KS2 = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_KS3: -+ env->CSR_KS3 = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_KS4: -+ env->CSR_KS4 = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_KS5: -+ env->CSR_KS5 = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_KS6: -+ env->CSR_KS6 = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_KS7: -+ env->CSR_KS7 = csrs[i].data; -+ break; -+ -+ case LOONGARCH_CSR_TMID: -+ env->CSR_TMID = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_CNTC: -+ env->CSR_CNTC = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_TINTCLR: -+ env->CSR_TINTCLR = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_GSTAT: -+ env->CSR_GSTAT = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_GCFG: -+ env->CSR_GCFG = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_GINTC: -+ env->CSR_GINTC = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_GCNTC: -+ env->CSR_GCNTC = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_LLBCTL: -+ env->CSR_LLBCTL = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_IMPCTL1: -+ env->CSR_IMPCTL1 = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_IMPCTL2: -+ env->CSR_IMPCTL2 = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_GNMI: -+ env->CSR_GNMI = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_TLBRENT: -+ env->CSR_TLBRENT = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_TLBRBADV: -+ env->CSR_TLBRBADV = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_TLBRERA: -+ env->CSR_TLBRERA = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_TLBRSAVE: -+ env->CSR_TLBRSAVE = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_TLBRELO0: -+ env->CSR_TLBRELO0 = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_TLBRELO1: -+ env->CSR_TLBRELO1 = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_TLBREHI: -+ env->CSR_TLBREHI = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_TLBRPRMD: -+ env->CSR_TLBRPRMD = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_ERRCTL: -+ env->CSR_ERRCTL = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_ERRINFO: -+ env->CSR_ERRINFO = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_ERRINFO1: -+ env->CSR_ERRINFO1 = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_ERRENT: -+ env->CSR_ERRENT = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_ERRERA: -+ env->CSR_ERRERA = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_ERRSAVE: -+ env->CSR_ERRSAVE = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_CTAG: -+ env->CSR_CTAG = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_DMWIN0: -+ env->CSR_DMWIN0 = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_DMWIN1: -+ env->CSR_DMWIN1 = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_DMWIN2: -+ env->CSR_DMWIN2 = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_DMWIN3: -+ env->CSR_DMWIN3 = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_PERFCTRL0: -+ env->CSR_PERFCTRL0 = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_PERFCNTR0: -+ env->CSR_PERFCNTR0 = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_PERFCTRL1: -+ env->CSR_PERFCTRL1 = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_PERFCNTR1: -+ env->CSR_PERFCNTR1 = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_PERFCTRL2: -+ env->CSR_PERFCTRL2 = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_PERFCNTR2: -+ env->CSR_PERFCNTR2 = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_PERFCTRL3: -+ env->CSR_PERFCTRL3 = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_PERFCNTR3: -+ env->CSR_PERFCNTR3 = csrs[i].data; -+ break; -+ -+ case LOONGARCH_CSR_MWPC: -+ env->CSR_MWPC = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_MWPS: -+ env->CSR_MWPS = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_DB0ADDR: -+ env->CSR_DB0ADDR = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_DB0MASK: -+ env->CSR_DB0MASK = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_DB0CTL: -+ env->CSR_DB0CTL = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_DB0ASID: -+ env->CSR_DB0ASID = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_DB1ADDR: -+ env->CSR_DB1ADDR = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_DB1MASK: -+ env->CSR_DB1MASK = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_DB1CTL: -+ env->CSR_DB1CTL = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_DB1ASID: -+ env->CSR_DB1ASID = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_DB2ADDR: -+ env->CSR_DB2ADDR = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_DB2MASK: -+ env->CSR_DB2MASK = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_DB2CTL: -+ env->CSR_DB2CTL = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_DB2ASID: -+ env->CSR_DB2ASID = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_DB3ADDR: -+ env->CSR_DB3ADDR = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_DB3MASK: -+ env->CSR_DB3MASK = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_DB3CTL: -+ env->CSR_DB3CTL = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_DB3ASID: -+ env->CSR_DB3ASID = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_FWPC: -+ env->CSR_FWPC = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_FWPS: -+ env->CSR_FWPS = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_IB0ADDR: -+ env->CSR_IB0ADDR = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_IB0MASK: -+ env->CSR_IB0MASK = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_IB0CTL: -+ env->CSR_IB0CTL = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_IB0ASID: -+ env->CSR_IB0ASID = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_IB1ADDR: -+ env->CSR_IB1ADDR = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_IB1MASK: -+ env->CSR_IB1MASK = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_IB1CTL: -+ env->CSR_IB1CTL = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_IB1ASID: -+ env->CSR_IB1ASID = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_IB2ADDR: -+ env->CSR_IB2ADDR = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_IB2MASK: -+ env->CSR_IB2MASK = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_IB2CTL: -+ env->CSR_IB2CTL = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_IB2ASID: -+ env->CSR_IB2ASID = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_IB3ADDR: -+ env->CSR_IB3ADDR = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_IB3MASK: -+ env->CSR_IB3MASK = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_IB3CTL: -+ env->CSR_IB3CTL = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_IB3ASID: -+ env->CSR_IB3ASID = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_IB4ADDR: -+ env->CSR_IB4ADDR = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_IB4MASK: -+ env->CSR_IB4MASK = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_IB4CTL: -+ env->CSR_IB4CTL = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_IB4ASID: -+ env->CSR_IB4ASID = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_IB5ADDR: -+ env->CSR_IB5ADDR = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_IB5MASK: -+ env->CSR_IB5MASK = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_IB5CTL: -+ env->CSR_IB5CTL = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_IB5ASID: -+ env->CSR_IB5ASID = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_IB6ADDR: -+ env->CSR_IB6ADDR = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_IB6MASK: -+ env->CSR_IB6MASK = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_IB6CTL: -+ env->CSR_IB6CTL = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_IB6ASID: -+ env->CSR_IB6ASID = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_IB7ADDR: -+ env->CSR_IB7ADDR = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_IB7MASK: -+ env->CSR_IB7MASK = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_IB7CTL: -+ env->CSR_IB7CTL = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_IB7ASID: -+ env->CSR_IB7ASID = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_DEBUG: -+ env->CSR_DEBUG = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_DERA: -+ env->CSR_DERA = csrs[i].data; -+ break; -+ case LOONGARCH_CSR_DESAVE: -+ env->CSR_DESAVE = csrs[i].data; -+ break; -+ default: -+ break; -+ } -+ } -+ -+ ret |= KVM_GET_ONE_UREG64(cs, LOONGARCH_CSR_TVAL, &env->CSR_TVAL); -+ ret |= KVM_GET_ONE_UREG64(cs, LOONGARCH_CSR_TCFG, &env->CSR_TCFG); -+ return ret; -+} -+ -+int kvm_loongarch_put_pvtime(LOONGARCHCPU *cpu) -+{ -+ CPULOONGARCHState *env = &cpu->env; -+ int err; -+ struct kvm_device_attr attr = { -+ .group = KVM_LARCH_VCPU_PVTIME_CTRL, -+ .attr = KVM_LARCH_VCPU_PVTIME_IPA, -+ .addr = (uint64_t)&env->st.guest_addr, -+ }; -+ -+ err = kvm_vcpu_ioctl(CPU(cpu), KVM_HAS_DEVICE_ATTR, attr); -+ if (err != 0) { -+ /* It's ok even though kvm has not such attr */ -+ return 0; -+ } -+ -+ err = kvm_vcpu_ioctl(CPU(cpu), KVM_SET_DEVICE_ATTR, attr); -+ if (err != 0) { -+ error_report("PVTIME IPA: KVM_SET_DEVICE_ATTR: %s", strerror(-err)); -+ return err; -+ } -+ -+ return 0; -+} -+ -+int kvm_loongarch_get_pvtime(LOONGARCHCPU *cpu) -+{ -+ CPULOONGARCHState *env = &cpu->env; -+ int err; -+ struct kvm_device_attr attr = { -+ .group = KVM_LARCH_VCPU_PVTIME_CTRL, -+ .attr = KVM_LARCH_VCPU_PVTIME_IPA, -+ .addr = (uint64_t)&env->st.guest_addr, -+ }; -+ -+ err = kvm_vcpu_ioctl(CPU(cpu), KVM_HAS_DEVICE_ATTR, attr); -+ if (err != 0) { -+ /* It's ok even though kvm has not such attr */ -+ return 0; -+ } -+ -+ err = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_DEVICE_ATTR, attr); -+ if (err != 0) { -+ error_report("PVTIME IPA: KVM_GET_DEVICE_ATTR: %s", strerror(-err)); -+ return err; -+ } -+ -+ return 0; -+} -+ -+int kvm_arch_put_registers(CPUState *cs, int level) -+{ -+ LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); -+ CPULOONGARCHState *env = &cpu->env; -+ struct kvm_regs regs; -+ int ret; -+ int i; -+ -+ /* Set the registers based on QEMU's view of things */ -+ for (i = 0; i < 32; i++) { -+ regs.gpr[i] = (int64_t)(target_long)env->active_tc.gpr[i]; -+ } -+ -+ regs.pc = (int64_t)(target_long)env->active_tc.PC; -+ -+ ret = kvm_vcpu_ioctl(cs, KVM_SET_REGS, ®s); -+ -+ if (ret < 0) { -+ return ret; -+ } -+ -+ ret = kvm_loongarch_put_csr_registers(cs, level); -+ if (ret < 0) { -+ return ret; -+ } -+ -+ ret = kvm_loongarch_put_fpu_registers(cs, level); -+ if (ret < 0) { -+ return ret; -+ } -+ -+ return ret; -+} -+ -+int kvm_arch_get_registers(CPUState *cs) -+{ -+ LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); -+ CPULOONGARCHState *env = &cpu->env; -+ int ret = 0; -+ struct kvm_regs regs; -+ int i; -+ -+ /* Get the current register set as KVM seems it */ -+ ret = kvm_vcpu_ioctl(cs, KVM_GET_REGS, ®s); -+ -+ if (ret < 0) { -+ return ret; -+ } -+ -+ for (i = 0; i < 32; i++) { -+ env->active_tc.gpr[i] = regs.gpr[i]; -+ } -+ -+ env->active_tc.PC = regs.pc; -+ -+ kvm_loongarch_get_csr_registers(cs); -+ kvm_loongarch_get_fpu_registers(cs); -+ -+ return ret; -+} -+ -+int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, -+ uint64_t address, uint32_t data, PCIDevice *dev) -+{ -+ return 0; -+} -+ -+int kvm_arch_add_msi_route_post(struct kvm_irq_routing_entry *route, -+ int vector, PCIDevice *dev) -+{ -+ return 0; -+} -+ -+bool kvm_arch_cpu_check_are_resettable(void) -+{ -+ return true; -+} -+ -+int kvm_arch_release_virq_post(int virq) -+{ -+ return 0; -+} -+ -+int kvm_arch_msi_data_to_gsi(uint32_t data) -+{ -+ abort(); -+} -diff --git a/target/loongarch64/kvm_larch.h b/target/loongarch64/kvm_larch.h -new file mode 100644 -index 0000000000..a56026d10c ---- /dev/null -+++ b/target/loongarch64/kvm_larch.h -@@ -0,0 +1,41 @@ -+/* -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file "COPYING" in the main directory of this archive -+ * for more details. -+ * -+ * KVM/LOONGARCH: LOONGARCH specific KVM APIs -+ * -+ * Copyright (C) 2012-2014 Imagination Technologies Ltd. -+ * Authors: Sanjay Lal -+*/ -+ -+#ifndef KVM_LOONGARCH_H -+#define KVM_LOONGARCH_H -+ -+/** -+ * kvm_loongarch_reset_vcpu: -+ * @cpu: LOONGARCHCPU -+ * -+ * Called at reset time to set kernel registers to their initial values. -+ */ -+void kvm_loongarch_reset_vcpu(LOONGARCHCPU *cpu); -+ -+int kvm_loongarch_set_interrupt(LOONGARCHCPU *cpu, int irq, int level); -+int kvm_loongarch_set_ipi_interrupt(LOONGARCHCPU *cpu, int irq, int level); -+ -+int kvm_loongarch_put_pvtime(LOONGARCHCPU *cpu); -+int kvm_loongarch_get_pvtime(LOONGARCHCPU *cpu); -+ -+#ifndef KVM_INTERRUPT_SET -+#define KVM_INTERRUPT_SET -1 -+#endif -+ -+#ifndef KVM_INTERRUPT_UNSET -+#define KVM_INTERRUPT_UNSET -2 -+#endif -+ -+#ifndef KVM_INTERRUPT_SET_LEVEL -+#define KVM_INTERRUPT_SET_LEVEL -3 -+#endif -+ -+#endif /* KVM_LOONGARCH_H */ -diff --git a/target/loongarch64/larch-defs.h b/target/loongarch64/larch-defs.h -new file mode 100644 -index 0000000000..d3a61cf255 ---- /dev/null -+++ b/target/loongarch64/larch-defs.h -@@ -0,0 +1,27 @@ -+#ifndef QEMU_LOONGARCH_DEFS_H -+#define QEMU_LOONGARCH_DEFS_H -+ -+/* If we want to use host float regs... */ -+/* #define USE_HOST_FLOAT_REGS */ -+ -+/* Real pages are variable size... */ -+#define TARGET_PAGE_BITS 14 -+ -+#define LOONGARCH_TLB_MAX 2112 -+ -+#define TARGET_LONG_BITS 64 -+#define TARGET_PHYS_ADDR_SPACE_BITS 48 -+#define TARGET_VIRT_ADDR_SPACE_BITS 48 -+ -+/* -+ * bit definitions for insn_flags (ISAs/ASEs flags) -+ * ------------------------------------------------ -+ */ -+#define ISA_LARCH32 0x00000001ULL -+#define ISA_LARCH64 0x00000002ULL -+#define INSN_LOONGARCH 0x00010000ULL -+ -+#define CPU_LARCH32 (ISA_LARCH32) -+#define CPU_LARCH64 (ISA_LARCH32 | ISA_LARCH64) -+ -+#endif /* QEMU_LOONGARCH_DEFS_H */ -diff --git a/target/loongarch64/machine.c b/target/loongarch64/machine.c -new file mode 100644 -index 0000000000..b69bca6a9b ---- /dev/null -+++ b/target/loongarch64/machine.c -@@ -0,0 +1,416 @@ -+#include "qemu/osdep.h" -+#include "qemu-common.h" -+#include "cpu.h" -+#include "internal.h" -+#include "hw/hw.h" -+#include "kvm_larch.h" -+#include "migration/cpu.h" -+#include "linux/kvm.h" -+#include "sysemu/kvm.h" -+#include "qemu/error-report.h" -+ -+static int cpu_post_load(void *opaque, int version_id) -+{ -+ LOONGARCHCPU *cpu = opaque; -+ CPULOONGARCHState *env = &cpu->env; -+ int r = 0; -+ -+#ifdef CONFIG_KVM -+ struct kvm_loongarch_vcpu_state vcpu_state; -+ int i; -+ -+ vcpu_state.online_vcpus = cpu->online_vcpus; -+ vcpu_state.is_migrate = cpu->is_migrate; -+ vcpu_state.cpu_freq = cpu->cpu_freq; -+ vcpu_state.count_ctl = cpu->count_ctl; -+ vcpu_state.pending_exceptions = cpu->pending_exceptions; -+ vcpu_state.pending_exceptions_clr = cpu->pending_exceptions_clr; -+ for (i = 0; i < 4; i++) { -+ vcpu_state.core_ext_ioisr[i] = cpu->core_ext_ioisr[i]; -+ } -+ r = kvm_vcpu_ioctl(CPU(cpu), KVM_LARCH_SET_VCPU_STATE, &vcpu_state); -+ if (r) { -+ error_report("set vcpu state failed %d", r); -+ } -+ -+ kvm_loongarch_put_pvtime(cpu); -+#endif -+ -+ restore_fp_status(env); -+ compute_hflags(env); -+ -+ return r; -+} -+ -+static int cpu_pre_save(void *opaque) -+{ -+#ifdef CONFIG_KVM -+ LOONGARCHCPU *cpu = opaque; -+ struct kvm_loongarch_vcpu_state vcpu_state; -+ int i, r = 0; -+ -+ r = kvm_vcpu_ioctl(CPU(cpu), KVM_LARCH_GET_VCPU_STATE, &vcpu_state); -+ if (r < 0) { -+ error_report("get vcpu state failed %d", r); -+ return r; -+ } -+ -+ cpu->online_vcpus = vcpu_state.online_vcpus; -+ cpu->is_migrate = vcpu_state.is_migrate; -+ cpu->cpu_freq = vcpu_state.cpu_freq; -+ cpu->count_ctl = vcpu_state.count_ctl; -+ cpu->pending_exceptions = vcpu_state.pending_exceptions; -+ cpu->pending_exceptions_clr = vcpu_state.pending_exceptions_clr; -+ for (i = 0; i < 4; i++) { -+ cpu->core_ext_ioisr[i] = vcpu_state.core_ext_ioisr[i]; -+ } -+ -+ kvm_loongarch_get_pvtime(cpu); -+#endif -+ return 0; -+} -+ -+/* FPU state */ -+ -+static int get_fpr(QEMUFile *f, void *pv, size_t size, -+ const VMStateField *field) -+{ -+ fpr_t *v = pv; -+ qemu_get_be64s(f, &v->d); -+ return 0; -+} -+ -+static int put_fpr(QEMUFile *f, void *pv, size_t size, -+ const VMStateField *field, JSONWriter *vmdesc) -+{ -+ fpr_t *v = pv; -+ qemu_put_be64s(f, &v->d); -+ return 0; -+} -+ -+const VMStateInfo vmstate_info_fpr = { -+ .name = "fpr", -+ .get = get_fpr, -+ .put = put_fpr, -+}; -+ -+#define VMSTATE_FPR_ARRAY_V(_f, _s, _n, _v) \ -+ VMSTATE_ARRAY(_f, _s, _n, _v, vmstate_info_fpr, fpr_t) -+ -+#define VMSTATE_FPR_ARRAY(_f, _s, _n) \ -+ VMSTATE_FPR_ARRAY_V(_f, _s, _n, 0) -+ -+static VMStateField vmstate_fpu_fields[] = { -+ VMSTATE_FPR_ARRAY(fpr, CPULOONGARCHFPUContext, 32), -+ VMSTATE_UINT32(fcsr0, CPULOONGARCHFPUContext), -+ VMSTATE_END_OF_LIST() -+}; -+ -+const VMStateDescription vmstate_fpu = { -+ .name = "cpu/fpu", -+ .version_id = 1, -+ .minimum_version_id = 1, -+ .fields = vmstate_fpu_fields -+}; -+ -+const VMStateDescription vmstate_inactive_fpu = { -+ .name = "cpu/inactive_fpu", -+ .version_id = 1, -+ .minimum_version_id = 1, -+ .fields = vmstate_fpu_fields -+}; -+ -+/* TC state */ -+ -+static VMStateField vmstate_tc_fields[] = { -+ VMSTATE_UINTTL_ARRAY(gpr, TCState, 32), -+ VMSTATE_UINTTL(PC, TCState), -+ VMSTATE_END_OF_LIST() -+}; -+ -+const VMStateDescription vmstate_tc = { -+ .name = "cpu/tc", -+ .version_id = 1, -+ .minimum_version_id = 1, -+ .fields = vmstate_tc_fields -+}; -+ -+const VMStateDescription vmstate_inactive_tc = { -+ .name = "cpu/inactive_tc", -+ .version_id = 1, -+ .minimum_version_id = 1, -+ .fields = vmstate_tc_fields -+}; -+ -+/* TLB state */ -+ -+static int get_tlb(QEMUFile *f, void *pv, size_t size, -+ const VMStateField *field) -+{ -+ ls3a5k_tlb_t *v = pv; -+ uint32_t flags; -+ -+ qemu_get_betls(f, &v->VPN); -+ qemu_get_be64s(f, &v->PageMask); -+ qemu_get_be32s(f, &v->PageSize); -+ qemu_get_be16s(f, &v->ASID); -+ qemu_get_be32s(f, &flags); -+ v->RPLV1 = (flags >> 21) & 1; -+ v->RPLV0 = (flags >> 20) & 1; -+ v->PLV1 = (flags >> 18) & 3; -+ v->PLV0 = (flags >> 16) & 3; -+ v->EHINV = (flags >> 15) & 1; -+ v->RI1 = (flags >> 14) & 1; -+ v->RI0 = (flags >> 13) & 1; -+ v->XI1 = (flags >> 12) & 1; -+ v->XI0 = (flags >> 11) & 1; -+ v->WE1 = (flags >> 10) & 1; -+ v->WE0 = (flags >> 9) & 1; -+ v->V1 = (flags >> 8) & 1; -+ v->V0 = (flags >> 7) & 1; -+ v->C1 = (flags >> 4) & 7; -+ v->C0 = (flags >> 1) & 7; -+ v->G = (flags >> 0) & 1; -+ qemu_get_be64s(f, &v->PPN0); -+ qemu_get_be64s(f, &v->PPN1); -+ -+ return 0; -+} -+ -+static int put_tlb(QEMUFile *f, void *pv, size_t size, -+ const VMStateField *field, JSONWriter *vmdesc) -+{ -+ ls3a5k_tlb_t *v = pv; -+ -+ uint16_t asid = v->ASID; -+ uint32_t flags = ((v->RPLV1 << 21) | -+ (v->RPLV0 << 20) | -+ (v->PLV1 << 18) | -+ (v->PLV0 << 16) | -+ (v->EHINV << 15) | -+ (v->RI1 << 14) | -+ (v->RI0 << 13) | -+ (v->XI1 << 12) | -+ (v->XI0 << 11) | -+ (v->WE1 << 10) | -+ (v->WE0 << 9) | -+ (v->V1 << 8) | -+ (v->V0 << 7) | -+ (v->C1 << 4) | -+ (v->C0 << 1) | -+ (v->G << 0)); -+ -+ qemu_put_betls(f, &v->VPN); -+ qemu_put_be64s(f, &v->PageMask); -+ qemu_put_be32s(f, &v->PageSize); -+ qemu_put_be16s(f, &asid); -+ qemu_put_be32s(f, &flags); -+ qemu_put_be64s(f, &v->PPN0); -+ qemu_put_be64s(f, &v->PPN1); -+ -+ return 0; -+} -+ -+const VMStateInfo vmstate_info_tlb = { -+ .name = "tlb_entry", -+ .get = get_tlb, -+ .put = put_tlb, -+}; -+ -+#define VMSTATE_TLB_ARRAY_V(_f, _s, _n, _v) \ -+ VMSTATE_ARRAY(_f, _s, _n, _v, vmstate_info_tlb, ls3a5k_tlb_t) -+ -+#define VMSTATE_TLB_ARRAY(_f, _s, _n) \ -+ VMSTATE_TLB_ARRAY_V(_f, _s, _n, 0) -+ -+const VMStateDescription vmstate_tlb = { -+ .name = "cpu/tlb", -+ .version_id = 2, -+ .minimum_version_id = 2, -+ .fields = (VMStateField[]) { -+ VMSTATE_UINT32(nb_tlb, CPULOONGARCHTLBContext), -+ VMSTATE_UINT32(tlb_in_use, CPULOONGARCHTLBContext), -+ VMSTATE_TLB_ARRAY(mmu.ls3a5k.tlb, CPULOONGARCHTLBContext, LOONGARCH_TLB_MAX), -+ VMSTATE_END_OF_LIST() -+ } -+}; -+ -+/* LOONGARCH CPU state */ -+ -+const VMStateDescription vmstate_loongarch_cpu = { -+ .name = "cpu", -+ .version_id = 15, -+ .minimum_version_id = 15, -+ .post_load = cpu_post_load, -+ .pre_save = cpu_pre_save, -+ .fields = (VMStateField[]) { -+ /* Active TC */ -+ VMSTATE_STRUCT(env.active_tc, LOONGARCHCPU, 1, vmstate_tc, TCState), -+ -+ /* Active FPU */ -+ VMSTATE_STRUCT(env.active_fpu, LOONGARCHCPU, 1, vmstate_fpu, -+ CPULOONGARCHFPUContext), -+ -+ /* TLB */ -+ VMSTATE_STRUCT_POINTER(env.tlb, LOONGARCHCPU, vmstate_tlb, -+ CPULOONGARCHTLBContext), -+ /* CPU metastate */ -+ VMSTATE_UINT32(env.current_tc, LOONGARCHCPU), -+ VMSTATE_INT32(env.error_code, LOONGARCHCPU), -+ VMSTATE_UINTTL(env.btarget, LOONGARCHCPU), -+ VMSTATE_UINTTL(env.bcond, LOONGARCHCPU), -+ -+ VMSTATE_UINT64(env.lladdr, LOONGARCHCPU), -+ -+ /* PV time */ -+ VMSTATE_UINT64(env.st.guest_addr, LOONGARCHCPU), -+ -+ /* Remaining CSR registers */ -+ VMSTATE_UINT64(env.CSR_CRMD, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_PRMD, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_EUEN, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_MISC, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_ECFG, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_ESTAT, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_ERA, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_BADV, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_BADI, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_EEPN, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_TLBIDX, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_TLBEHI, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_TLBELO0, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_TLBELO1, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_TLBWIRED, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_GTLBC, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_TRGP, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_ASID, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_PGDL, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_PGDH, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_PGD, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_PWCTL0, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_PWCTL1, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_STLBPGSIZE, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_RVACFG, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_CPUID, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_PRCFG1, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_PRCFG2, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_PRCFG3, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_KS0, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_KS1, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_KS2, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_KS3, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_KS4, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_KS5, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_KS6, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_KS7, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_TMID, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_TCFG, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_TVAL, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_CNTC, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_TINTCLR, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_GSTAT, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_GCFG, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_GINTC, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_GCNTC, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_LLBCTL, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_IMPCTL1, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_IMPCTL2, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_GNMI, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_TLBRENT, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_TLBRBADV, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_TLBRERA, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_TLBRSAVE, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_TLBRELO0, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_TLBRELO1, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_TLBREHI, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_TLBRPRMD, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_ERRCTL, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_ERRINFO, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_ERRINFO1, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_ERRENT, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_ERRERA, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_ERRSAVE, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_CTAG, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_DMWIN0, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_DMWIN1, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_DMWIN2, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_DMWIN3, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_PERFCTRL0, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_PERFCNTR0, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_PERFCTRL1, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_PERFCNTR1, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_PERFCTRL2, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_PERFCNTR2, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_PERFCTRL3, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_PERFCNTR3, LOONGARCHCPU), -+ /* debug */ -+ VMSTATE_UINT64(env.CSR_MWPC, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_MWPS, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_DB0ADDR, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_DB0MASK, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_DB0CTL, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_DB0ASID, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_DB1ADDR, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_DB1MASK, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_DB1CTL, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_DB1ASID, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_DB2ADDR, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_DB2MASK, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_DB2CTL, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_DB2ASID, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_DB3ADDR, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_DB3MASK, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_DB3CTL, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_DB3ASID, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_FWPC, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_FWPS, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_IB0ADDR, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_IB0MASK, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_IB0CTL, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_IB0ASID, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_IB1ADDR, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_IB1MASK, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_IB1CTL, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_IB1ASID, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_IB2ADDR, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_IB2MASK, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_IB2CTL, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_IB2ASID, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_IB3ADDR, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_IB3MASK, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_IB3CTL, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_IB3ASID, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_IB4ADDR, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_IB4MASK, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_IB4CTL, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_IB4ASID, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_IB5ADDR, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_IB5MASK, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_IB5CTL, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_IB5ASID, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_IB6ADDR, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_IB6MASK, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_IB6CTL, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_IB6ASID, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_IB7ADDR, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_IB7MASK, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_IB7CTL, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_IB7ASID, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_DEBUG, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_DERA, LOONGARCHCPU), -+ VMSTATE_UINT64(env.CSR_DESAVE, LOONGARCHCPU), -+ -+ VMSTATE_STRUCT_ARRAY(env.fpus, LOONGARCHCPU, LOONGARCH_FPU_MAX, 1, -+ vmstate_inactive_fpu, CPULOONGARCHFPUContext), -+ VMSTATE_UINT8(online_vcpus, LOONGARCHCPU), -+ VMSTATE_UINT8(is_migrate, LOONGARCHCPU), -+ VMSTATE_UINT64(counter_value, LOONGARCHCPU), -+ VMSTATE_UINT32(cpu_freq, LOONGARCHCPU), -+ VMSTATE_UINT32(count_ctl, LOONGARCHCPU), -+ VMSTATE_UINT64(pending_exceptions, LOONGARCHCPU), -+ VMSTATE_UINT64(pending_exceptions_clr, LOONGARCHCPU), -+ VMSTATE_UINT64_ARRAY(core_ext_ioisr, LOONGARCHCPU, 4), -+ -+ VMSTATE_END_OF_LIST() -+ }, -+}; -diff --git a/target/loongarch64/meson.build b/target/loongarch64/meson.build -new file mode 100644 -index 0000000000..6badf4484e ---- /dev/null -+++ b/target/loongarch64/meson.build -@@ -0,0 +1,35 @@ -+loongarch_user_ss = ss.source_set() -+loongarch_softmmu_ss = ss.source_set() -+loongarch_ss = ss.source_set() -+loongarch_ss.add(files( -+ 'cpu.c', -+ 'fpu.c', -+ 'gdbstub.c', -+)) -+ -+gen = [ -+ decodetree.process('insn.decode', extra_args: [ '--decode', 'decode_insn', -+ '--insnwidth', '32' ]) -+] -+ -+loongarch_ss.add(gen) -+loongarch_ss.add(when: 'CONFIG_TCG', if_true: files( -+ 'helper.c', -+ 'translate.c', -+ 'op_helper.c', -+ 'fpu_helper.c', -+ 'tlb_helper.c', -+ 'csr_helper.c', -+)) -+ -+loongarch_softmmu_ss.add(when: 'CONFIG_SOFTMMU', if_true: files( -+ 'machine.c', -+ 'stabletimer.c', -+ 'arch_dump.c', -+)) -+ -+loongarch_softmmu_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c')) -+ -+target_arch += {'loongarch64': loongarch_ss} -+target_softmmu_arch += {'loongarch64': loongarch_softmmu_ss} -+target_user_arch += {'loongarch64': loongarch_user_ss} -diff --git a/target/loongarch64/op_helper.c b/target/loongarch64/op_helper.c -new file mode 100644 -index 0000000000..9a34c0d25e ---- /dev/null -+++ b/target/loongarch64/op_helper.c -@@ -0,0 +1,533 @@ -+/* -+ * LOONGARCH emulation helpers for qemu. -+ * -+ * Copyright (c) 2004-2005 Jocelyn Mayer -+ * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2 of the License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library; if not, see . -+ */ -+#include "qemu/osdep.h" -+#include "qemu/main-loop.h" -+#include "cpu.h" -+#include "internal.h" -+#include "qemu/host-utils.h" -+#include "exec/helper-proto.h" -+#include "exec/exec-all.h" -+#include "exec/cpu_ldst.h" -+#include "sysemu/kvm.h" -+#include "qemu/crc32c.h" -+#include -+#include "hw/irq.h" -+#include "hw/core/cpu.h" -+#include "instmap.h" -+ -+/*****************************************************************************/ -+/* Exceptions processing helpers */ -+ -+void helper_raise_exception_err(CPULOONGARCHState *env, uint32_t exception, -+ int error_code) -+{ -+ do_raise_exception_err(env, exception, error_code, 0); -+} -+ -+void helper_raise_exception(CPULOONGARCHState *env, uint32_t exception) -+{ -+ do_raise_exception(env, exception, GETPC()); -+} -+ -+void helper_raise_exception_debug(CPULOONGARCHState *env) -+{ -+ do_raise_exception(env, EXCP_DEBUG, 0); -+} -+ -+static void raise_exception(CPULOONGARCHState *env, uint32_t exception) -+{ -+ do_raise_exception(env, exception, 0); -+} -+ -+#if defined(CONFIG_USER_ONLY) -+#define HELPER_LD(name, insn, type) \ -+static inline type do_##name(CPULOONGARCHState *env, target_ulong addr, \ -+ int mem_idx, uintptr_t retaddr) \ -+{ \ -+ return (type) cpu_##insn##_data_ra(env, addr, retaddr); \ -+} -+#else -+ -+#define HF_SMAP_SHIFT 23 /* CR4.SMAP */ -+#define HF_SMAP_MASK (1 << HF_SMAP_SHIFT) -+#define MMU_KNOSMAP_IDX 2 -+#define HF_CPL_SHIFT 0 -+#define HF_CPL_MASK (3 << HF_CPL_SHIFT) -+#define AC_MASK 0x00040000 -+#define MMU_KSMAP_IDX 0 -+static inline int cpu_mmu_index_kernel(CPULOONGARCHState *env) -+{ -+ return !(env->hflags & HF_SMAP_MASK) ? MMU_KNOSMAP_IDX : -+ ((env->hflags & HF_CPL_MASK) < 3 && (env->hflags & AC_MASK)) -+ ? MMU_KNOSMAP_IDX : MMU_KSMAP_IDX; -+} -+ -+#define cpu_ldl_kernel_ra(e, p, r) \ -+ cpu_ldl_mmuidx_ra(e, p, cpu_mmu_index_kernel(e), r) -+ -+#define HELPER_LD(name, insn, type) \ -+static inline type do_##name(CPULOONGARCHState *env, target_ulong addr, \ -+ int mem_idx, uintptr_t retaddr) \ -+{ \ -+/* \ -+ switch (mem_idx) { \ -+ case 0: return (type) cpu_##insn##_kernel_ra(env, addr, retaddr); \ -+ case 1: return (type) cpu_##insn##_super_ra(env, addr, retaddr); \ -+ default: \ -+ case 2: return (type) cpu_##insn##_user_ra(env, addr, retaddr); \ -+ case 3: return (type) cpu_##insn##_error_ra(env, addr, retaddr); \ -+ } \ -+*/ \ -+} -+#endif -+#if 0 -+HELPER_LD(lw, ldl, int32_t) -+HELPER_LD(ld, ldq, int64_t) -+#endif -+#undef HELPER_LD -+ -+#if defined(CONFIG_USER_ONLY) -+#define HELPER_ST(name, insn, type) \ -+static inline void do_##name(CPULOONGARCHState *env, target_ulong addr, \ -+ type val, int mem_idx, uintptr_t retaddr) \ -+{ \ -+/* \ -+ cpu_##insn##_data_ra(env, addr, val, retaddr); \ -+*/ \ -+} -+#else -+#define HELPER_ST(name, insn, type) \ -+static inline void do_##name(CPULOONGARCHState *env, target_ulong addr, \ -+ type val, int mem_idx, uintptr_t retaddr) \ -+{ \ -+/* \ -+ switch (mem_idx) { \ -+ case 0: \ -+ cpu_##insn##_kernel_ra(env, addr, val, retaddr); \ -+ break; \ -+ case 1: \ -+ cpu_##insn##_super_ra(env, addr, val, retaddr); \ -+ break; \ -+ default: \ -+ case 2: \ -+ cpu_##insn##_user_ra(env, addr, val, retaddr); \ -+ break; \ -+ case 3: \ -+ cpu_##insn##_error_ra(env, addr, val, retaddr); \ -+ break; \ -+ } \ -+*/ \ -+} -+#endif -+#if 0 -+HELPER_ST(sb, stb, uint8_t) -+HELPER_ST(sw, stl, uint32_t) -+HELPER_ST(sd, stq, uint64_t) -+#endif -+#undef HELPER_ST -+ -+static inline target_ulong bitswap(target_ulong v) -+{ -+ v = ((v >> 1) & (target_ulong)0x5555555555555555ULL) | -+ ((v & (target_ulong)0x5555555555555555ULL) << 1); -+ v = ((v >> 2) & (target_ulong)0x3333333333333333ULL) | -+ ((v & (target_ulong)0x3333333333333333ULL) << 2); -+ v = ((v >> 4) & (target_ulong)0x0F0F0F0F0F0F0F0FULL) | -+ ((v & (target_ulong)0x0F0F0F0F0F0F0F0FULL) << 4); -+ return v; -+} -+ -+target_ulong helper_dbitswap(target_ulong rt) -+{ -+ return bitswap(rt); -+} -+ -+target_ulong helper_bitswap(target_ulong rt) -+{ -+ return (int32_t)bitswap(rt); -+} -+ -+/* these crc32 functions are based on target/arm/helper-a64.c */ -+target_ulong helper_crc32(target_ulong val, target_ulong m, uint32_t sz) -+{ -+ uint8_t buf[8]; -+ target_ulong mask = ((sz * 8) == 64) ? -1ULL : ((1ULL << (sz * 8)) - 1); -+ -+ m &= mask; -+ stq_le_p(buf, m); -+ return (int32_t) (crc32(val ^ 0xffffffff, buf, sz) ^ 0xffffffff); -+} -+ -+target_ulong helper_crc32c(target_ulong val, target_ulong m, uint32_t sz) -+{ -+ uint8_t buf[8]; -+ target_ulong mask = ((sz * 8) == 64) ? -1ULL : ((1ULL << (sz * 8)) - 1); -+ m &= mask; -+ stq_le_p(buf, m); -+ return (int32_t) (crc32c(val, buf, sz) ^ 0xffffffff); -+} -+ -+#ifndef CONFIG_USER_ONLY -+ -+#define HELPER_LD_ATOMIC(name, insn, almask) \ -+target_ulong helper_##name(CPULOONGARCHState *env, target_ulong arg, int mem_idx) \ -+{ \ -+/* \ -+ if (arg & almask) { \ -+ env->CSR_BADV = arg; \ -+ do_raise_exception(env, EXCP_AdEL, GETPC()); \ -+ } \ -+ env->lladdr = arg; \ -+ env->llval = do_##insn(env, arg, mem_idx, GETPC()); \ -+ return env->llval; \ -+*/ \ -+} -+#if 0 -+HELPER_LD_ATOMIC(ll, lw, 0x3) -+HELPER_LD_ATOMIC(lld, ld, 0x7) -+#endif -+#undef HELPER_LD_ATOMIC -+#endif -+ -+#ifndef CONFIG_USER_ONLY -+void helper_drdtime(CPULOONGARCHState *env, target_ulong rd, target_ulong rs) -+{ -+ env->active_tc.gpr[rd] = cpu_loongarch_get_stable_counter(env); -+ env->active_tc.gpr[rs] = env->CSR_TMID; -+} -+#endif -+ -+#ifndef CONFIG_USER_ONLY -+static void debug_pre_ertn(CPULOONGARCHState *env) -+{ -+ if (qemu_loglevel_mask(CPU_LOG_EXEC)) { -+ qemu_log("ERTN: PC " TARGET_FMT_lx " ERA " TARGET_FMT_lx, -+ env->active_tc.PC, env->CSR_ERA); -+ qemu_log("\n"); -+ } -+} -+ -+static void debug_post_ertn(CPULOONGARCHState *env) -+{ -+ if (qemu_loglevel_mask(CPU_LOG_EXEC)) { -+ qemu_log("ERTN: PC " TARGET_FMT_lx " ERA " TARGET_FMT_lx, -+ env->active_tc.PC, env->CSR_ERA); -+ } -+} -+ -+static void set_pc(CPULOONGARCHState *env, target_ulong error_pc) -+{ -+ env->active_tc.PC = error_pc & ~(target_ulong)1; -+} -+ -+static inline void exception_return(CPULOONGARCHState *env) -+{ -+ debug_pre_ertn(env); -+ -+ if (cpu_refill_state(env)) { -+ env->CSR_CRMD &= (~0x7); -+ env->CSR_CRMD |= (env->CSR_TLBRPRMD & 0x7); -+ /* Clear Refill flag and set pc */ -+ env->CSR_TLBRERA &= (~0x1); -+ set_pc(env, env->CSR_TLBRERA); -+ if (qemu_loglevel_mask(CPU_LOG_INT)) { -+ qemu_log("%s: TLBRERA 0x%lx\n", __func__, env->CSR_TLBRERA); -+ } -+ } else { -+ env->CSR_CRMD &= (~0x7); -+ env->CSR_CRMD |= (env->CSR_PRMD & 0x7); -+ /* Clear Refill flag and set pc*/ -+ set_pc(env, env->CSR_ERA); -+ if (qemu_loglevel_mask(CPU_LOG_INT)) { -+ qemu_log("%s: ERA 0x%lx\n", __func__, env->CSR_ERA); -+ } -+ } -+ -+ compute_hflags(env); -+ debug_post_ertn(env); -+} -+ -+void helper_ertn(CPULOONGARCHState *env) -+{ -+ exception_return(env); -+ env->lladdr = 1; -+} -+ -+#endif /* !CONFIG_USER_ONLY */ -+ -+void helper_idle(CPULOONGARCHState *env) -+{ -+ CPUState *cs = CPU(loongarch_env_get_cpu(env)); -+ -+ cs->halted = 1; -+ cpu_reset_interrupt(cs, CPU_INTERRUPT_WAKE); -+ /* Last instruction in the block, PC was updated before -+ - no need to recover PC and icount */ -+ raise_exception(env, EXCP_HLT); -+} -+ -+#if !defined(CONFIG_USER_ONLY) -+ -+void loongarch_cpu_do_unaligned_access(CPUState *cs, vaddr addr, -+ MMUAccessType access_type, -+ int mmu_idx, uintptr_t retaddr) -+{ -+ while(1); -+} -+ -+#endif /* !CONFIG_USER_ONLY */ -+ -+void helper_store_scr(CPULOONGARCHState *env, uint32_t n, target_ulong val) -+{ -+ env->scr[n & 0x3] = val; -+} -+ -+target_ulong helper_load_scr(CPULOONGARCHState *env, uint32_t n) -+{ -+ return env->scr[n & 0x3]; -+} -+ -+/* loongarch assert op */ -+void helper_asrtle_d(CPULOONGARCHState *env, target_ulong rs, target_ulong rt) -+{ -+ if (rs > rt) { -+ do_raise_exception(env, EXCP_AdEL, GETPC()); -+ } -+} -+ -+void helper_asrtgt_d(CPULOONGARCHState *env, target_ulong rs, target_ulong rt) -+{ -+ if (rs <= rt) { -+ do_raise_exception(env, EXCP_AdEL, GETPC()); -+ } -+} -+ -+target_ulong helper_cto_w(CPULOONGARCHState *env, target_ulong a0) -+{ -+ uint32_t v = (uint32_t)a0; -+ int temp = 0; -+ -+ while ((v & 0x1) == 1) { -+ temp++; -+ v = v >> 1; -+ } -+ -+ return (target_ulong)temp; -+} -+ -+target_ulong helper_ctz_w(CPULOONGARCHState *env, target_ulong a0) -+{ -+ uint32_t v = (uint32_t)a0; -+ -+ if (v == 0) { -+ return 32; -+ } -+ -+ int temp = 0; -+ while ((v & 0x1) == 0) { -+ temp++; -+ v = v >> 1; -+ } -+ -+ return (target_ulong)temp; -+} -+ -+target_ulong helper_cto_d(CPULOONGARCHState *env, target_ulong a0) -+{ -+ uint64_t v = a0; -+ int temp = 0; -+ -+ while ((v & 0x1) == 1) { -+ temp++; -+ v = v >> 1; -+ } -+ -+ return (target_ulong)temp; -+} -+ -+target_ulong helper_ctz_d(CPULOONGARCHState *env, target_ulong a0) -+{ -+ uint64_t v = a0; -+ -+ if (v == 0) { -+ return 64; -+ } -+ -+ int temp = 0; -+ while ((v & 0x1) == 0) { -+ temp++; -+ v = v >> 1; -+ } -+ -+ return (target_ulong)temp; -+} -+ -+target_ulong helper_bitrev_w(CPULOONGARCHState *env, target_ulong a0) -+{ -+ int32_t v = (int32_t)a0; -+ const int SIZE = 32; -+ uint8_t bytes[SIZE]; -+ -+ int i; -+ for (i = 0; i < SIZE; i++) { -+ bytes[i] = v & 0x1; -+ v = v >> 1; -+ } -+ /* v == 0 */ -+ for (i = 0; i < SIZE; i++) { -+ v = v | ((uint32_t)bytes[i] << (SIZE - 1 - i)); -+ } -+ -+ return (target_ulong)(int32_t)v; -+} -+ -+target_ulong helper_bitrev_d(CPULOONGARCHState *env, target_ulong a0) -+{ -+ uint64_t v = a0; -+ const int SIZE = 64; -+ uint8_t bytes[SIZE]; -+ -+ int i; -+ for (i = 0; i < SIZE; i++) { -+ bytes[i] = v & 0x1; -+ v = v >> 1; -+ } -+ /* v == 0 */ -+ for (i = 0; i < SIZE; i++) { -+ v = v | ((uint64_t)bytes[i] << (SIZE - 1 - i)); -+ } -+ -+ return (target_ulong)v; -+} -+ -+void helper_memtrace_addr(CPULOONGARCHState *env, -+ target_ulong address, uint32_t op) -+{ -+ qemu_log("[cpu %d asid 0x%lx pc 0x%lx] addr 0x%lx op", -+ CPU(loongarch_env_get_cpu(env))->cpu_index, -+ env->CSR_ASID, env->active_tc.PC, address); -+ switch (op) { -+ case OPC_LARCH_LDPTR_D: -+ qemu_log("OPC_LARCH_LDPTR_D"); -+ break; -+ case OPC_LARCH_LD_D: -+ qemu_log("OPC_LARCH_LD_D"); -+ break; -+ case OPC_LARCH_LDPTR_W: -+ qemu_log("OPC_LARCH_LDPTR_W"); -+ break; -+ case OPC_LARCH_LD_W: -+ qemu_log("OPC_LARCH_LD_W"); -+ break; -+ case OPC_LARCH_LD_H: -+ qemu_log("OPC_LARCH_LD_H"); -+ break; -+ case OPC_LARCH_LD_B: -+ qemu_log("OPC_LARCH_LD_B"); -+ break; -+ case OPC_LARCH_LD_WU: -+ qemu_log("OPC_LARCH_LD_WU"); -+ break; -+ case OPC_LARCH_LD_HU: -+ qemu_log("OPC_LARCH_LD_HU"); -+ break; -+ case OPC_LARCH_LD_BU: -+ qemu_log("OPC_LARCH_LD_BU"); -+ break; -+ case OPC_LARCH_STPTR_D: -+ qemu_log("OPC_LARCH_STPTR_D"); -+ break; -+ case OPC_LARCH_ST_D: -+ qemu_log("OPC_LARCH_ST_D"); -+ break; -+ case OPC_LARCH_STPTR_W: -+ qemu_log("OPC_LARCH_STPTR_W"); -+ break; -+ case OPC_LARCH_ST_W: -+ qemu_log("OPC_LARCH_ST_W"); -+ break; -+ case OPC_LARCH_ST_H: -+ qemu_log("OPC_LARCH_ST_H"); -+ break; -+ case OPC_LARCH_ST_B: -+ qemu_log("OPC_LARCH_ST_B"); -+ break; -+ case OPC_LARCH_FLD_S: -+ qemu_log("OPC_LARCH_FLD_S"); -+ break; -+ case OPC_LARCH_FLD_D: -+ qemu_log("OPC_LARCH_FLD_D"); -+ break; -+ case OPC_LARCH_FST_S: -+ qemu_log("OPC_LARCH_FST_S"); -+ break; -+ case OPC_LARCH_FST_D: -+ qemu_log("OPC_LARCH_FST_D"); -+ break; -+ case OPC_LARCH_FLDX_S: -+ qemu_log("OPC_LARCH_FLDX_S"); -+ break; -+ case OPC_LARCH_FLDGT_S: -+ qemu_log("OPC_LARCH_FLDGT_S"); -+ break; -+ case OPC_LARCH_FLDLE_S: -+ qemu_log("OPC_LARCH_FLDLE_S"); -+ break;; -+ case OPC_LARCH_FSTX_S: -+ qemu_log("OPC_LARCH_FSTX_S"); -+ break; -+ case OPC_LARCH_FSTGT_S: -+ qemu_log("OPC_LARCH_FSTGT_S"); -+ break; -+ case OPC_LARCH_FSTLE_S: -+ qemu_log("OPC_LARCH_FSTLE_S"); -+ break; -+ case OPC_LARCH_FLDX_D: -+ qemu_log("OPC_LARCH_FLDX_D"); -+ break; -+ case OPC_LARCH_FLDGT_D: -+ qemu_log("OPC_LARCH_FLDGT_D"); -+ break; -+ case OPC_LARCH_FLDLE_D: -+ qemu_log("OPC_LARCH_FLDLE_D"); -+ break;; -+ case OPC_LARCH_FSTX_D: -+ qemu_log("OPC_LARCH_FSTX_D"); -+ break; -+ case OPC_LARCH_FSTGT_D: -+ qemu_log("OPC_LARCH_FSTGT_D"); -+ break; -+ case OPC_LARCH_FSTLE_D: -+ qemu_log("OPC_LARCH_FSTLE_D"); -+ break; -+ case OPC_LARCH_LL_W: -+ qemu_log("OPC_LARCH_LL_W"); -+ break; -+ case OPC_LARCH_LL_D: -+ qemu_log("OPC_LARCH_LL_D"); -+ break; -+ default: -+ qemu_log("0x%x", op); -+ } -+} -+ -+void helper_memtrace_val(CPULOONGARCHState *env, target_ulong val) -+{ -+ qemu_log("val 0x%lx\n", val); -+} -diff --git a/target/loongarch64/stabletimer.c b/target/loongarch64/stabletimer.c -new file mode 100644 -index 0000000000..b86fecf899 ---- /dev/null -+++ b/target/loongarch64/stabletimer.c -@@ -0,0 +1,122 @@ -+/* -+ * QEMU LOONGARCH timer support -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a copy -+ * of this software and associated documentation files (the "Software"), to deal -+ * in the Software without restriction, including without limitation the rights -+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -+ * copies of the Software, and to permit persons to whom the Software is -+ * furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -+ * THE SOFTWARE. -+ */ -+ -+#include "qemu/osdep.h" -+#include "hw/loongarch/cpudevs.h" -+#include "qemu/timer.h" -+#include "sysemu/kvm.h" -+#include "internal.h" -+#include "hw/irq.h" -+ -+ -+#ifdef DEBUG_TIMER -+#define debug_timer(fmt, args...) printf("%s(%d)-%s -> " #fmt "\n", \ -+ __FILE__, __LINE__, __func__, ##args); -+#else -+#define debug_timer(fmt, args...) -+#endif -+ -+#define TIMER_PERIOD 10 /* 10 ns period for 100 Mhz frequency */ -+#define STABLETIMER_TICK_MASK 0xfffffffffffcUL -+#define STABLETIMER_ENABLE 0x1UL -+#define STABLETIMER_PERIOD 0x2UL -+ -+/* return random value in [low, high] */ -+uint32_t cpu_loongarch_get_random_ls3a5k_tlb(uint32_t low, uint32_t high) -+{ -+ static uint32_t seed = 5; -+ static uint32_t prev_idx; -+ uint32_t idx; -+ uint32_t nb_rand_tlb = high - low + 1; -+ -+ do { -+ seed = 1103515245 * seed + 12345; -+ idx = (seed >> 16) % nb_rand_tlb + low; -+ } while (idx == prev_idx); -+ prev_idx = idx; -+ -+ return idx; -+} -+ -+/* LOONGARCH timer */ -+uint64_t cpu_loongarch_get_stable_counter(CPULOONGARCHState *env) -+{ -+ return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / TIMER_PERIOD; -+} -+ -+uint64_t cpu_loongarch_get_stable_timer_ticks(CPULOONGARCHState *env) -+{ -+ uint64_t now, expire; -+ -+ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); -+ expire = timer_expire_time_ns(env->timer); -+ -+ return (expire - now) / TIMER_PERIOD; -+} -+ -+void cpu_loongarch_store_stable_timer_config(CPULOONGARCHState *env, -+ uint64_t value) -+{ -+ uint64_t now, next; -+ -+ env->CSR_TCFG = value; -+ if (value & STABLETIMER_ENABLE) { -+ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); -+ next = now + (value & STABLETIMER_TICK_MASK) * TIMER_PERIOD; -+ timer_mod(env->timer, next); -+ } -+ debug_timer("0x%lx 0x%lx now 0x%lx, next 0x%lx", -+ value, env->CSR_TCFG, now, next); -+} -+ -+static void loongarch_stable_timer_cb(void *opaque) -+{ -+ CPULOONGARCHState *env; -+ uint64_t now, next; -+ -+ env = opaque; -+ debug_timer(); -+ if (env->CSR_TCFG & STABLETIMER_PERIOD) { -+ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); -+ next = now + (env->CSR_TCFG & STABLETIMER_TICK_MASK) * TIMER_PERIOD; -+ timer_mod(env->timer, next); -+ } else { -+ env->CSR_TCFG &= ~STABLETIMER_ENABLE; -+ } -+ -+ qemu_irq_raise(env->irq[IRQ_TIMER]); -+ -+} -+ -+void cpu_loongarch_clock_init(LOONGARCHCPU *cpu) -+{ -+ CPULOONGARCHState *env = &cpu->env; -+ -+ /* -+ * If we're in KVM mode, don't create the periodic timer, that is handled in -+ * kernel. -+ */ -+ if (!kvm_enabled()) { -+ env->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, -+ &loongarch_stable_timer_cb, env); -+ } -+} -diff --git a/target/loongarch64/tlb_helper.c b/target/loongarch64/tlb_helper.c -new file mode 100644 -index 0000000000..f5e68349a9 ---- /dev/null -+++ b/target/loongarch64/tlb_helper.c -@@ -0,0 +1,729 @@ -+/* -+ * loongarch tlb emulation helpers for qemu. -+ * -+ * Copyright (c) 2020 -+ * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2 of the License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library; if not, see . -+ */ -+#include "qemu/osdep.h" -+#include "qemu/main-loop.h" -+#include "cpu.h" -+#include "internal.h" -+#include "qemu/host-utils.h" -+#include "exec/helper-proto.h" -+#include "exec/exec-all.h" -+#include "exec/cpu_ldst.h" -+ -+#ifndef CONFIG_USER_ONLY -+ -+#define HELPER_LD(name, insn, type) \ -+static inline type do_##name(CPULOONGARCHState *env, target_ulong addr, \ -+ int mem_idx, uintptr_t retaddr) \ -+{ \ -+/* \ -+ switch (mem_idx) { \ -+ case 0: return (type) cpu_##insn##_kernel_ra(env, addr, retaddr); \ -+ case 1: return (type) cpu_##insn##_super_ra(env, addr, retaddr); \ -+ default: \ -+ case 2: return (type) cpu_##insn##_user_ra(env, addr, retaddr); \ -+ case 3: return (type) cpu_##insn##_error_ra(env, addr, retaddr); \ -+ } \ -+*/ \ -+} -+#if 0 -+HELPER_LD(lw, ldl, int32_t) -+HELPER_LD(ld, ldq, int64_t) -+#endif -+ -+void helper_lddir(CPULOONGARCHState *env, target_ulong base, target_ulong rt, -+ target_ulong level, uint32_t mem_idx) -+{ -+#if 0 -+ target_ulong pointer = env->active_tc.gpr[base]; -+ target_ulong badvaddr; -+ target_ulong index; -+ target_ulong vaddr; -+ int shift; -+ -+ badvaddr = env->CSR_TLBRBADV; -+ -+ /* 0:8B, 1:16B, 2:32B, 3:64B */ -+ shift = (env->CSR_PWCTL0 >> 30) & 0x3; -+ shift = (shift + 1) * 3; -+ -+ switch (level) { -+ case 1: -+ index = (badvaddr >> ((env->CSR_PWCTL0 >> 10) & 0x1f)) & \ -+ ((1 << ((env->CSR_PWCTL0 >> 15) & 0x1f)) - 1); -+ break; -+ case 3: -+ index = (badvaddr >> ((env->CSR_PWCTL1 >> 0) & 0x3f)) & \ -+ ((1 << ((env->CSR_PWCTL1 >> 6) & 0x3f)) - 1); -+ break; -+ default: -+ do_raise_exception(env, EXCP_RI, GETPC()); -+ return; -+ } -+ -+ vaddr = pointer | index << shift; -+ env->active_tc.gpr[rt] = do_ld(env, vaddr, mem_idx, GETPC()); -+ return; -+#endif -+} -+ -+void helper_ldpte(CPULOONGARCHState *env, target_ulong base, target_ulong odd, -+ uint32_t mem_idx) -+{ -+#if 0 -+ target_ulong pointer = env->active_tc.gpr[base]; -+ target_ulong vaddr; -+ target_ulong tmp0 = 1; -+ target_ulong ptindex, ptoffset0, ptoffset1; -+ target_ulong pagesize; -+ target_ulong badv; -+ int shift; -+ bool huge = pointer & LOONGARCH_PAGE_HUGE; -+ -+ if (huge) { -+ /* Huge Page. pointer is paddr */ -+ tmp0 = pointer ^ LOONGARCH_PAGE_HUGE; -+ /* move Global bit */ -+ tmp0 |= ((tmp0 & LOONGARCH_HUGE_GLOBAL) -+ >> (LOONGARCH_HUGE_GLOBAL_SH - CSR_TLBLO0_GLOBAL_SHIFT)); -+ pagesize = (env->CSR_PWCTL0 & 0x1f) + -+ ((env->CSR_PWCTL0 >> 5) & 0x1f) - 1; -+ if (odd) { -+ tmp0 += (1 << pagesize); -+ } -+ } else { -+ /* 0:8B, 1:16B, 2:32B, 3:64B */ -+ shift = (env->CSR_PWCTL0 >> 30) & 0x3; -+ shift = (shift + 1) * 3; -+ badv = env->CSR_TLBRBADV; -+ -+ ptindex = (badv >> (env->CSR_PWCTL0 & 0x1f)) & -+ ((1 << ((env->CSR_PWCTL0 >> 5) & 0x1f)) - 1); -+ ptindex = ptindex & ~0x1; /* clear bit 0 */ -+ ptoffset0 = ptindex << shift; -+ ptoffset1 = (ptindex + 1) << shift; -+ -+ vaddr = pointer | (odd ? ptoffset1 : ptoffset0); -+ tmp0 = do_ld(env, vaddr, mem_idx, GETPC()); -+ pagesize = (env->CSR_PWCTL0 & 0x1f); -+ } -+ if (odd) { -+ env->CSR_TLBRELO1 = tmp0; -+ } else { -+ env->CSR_TLBRELO0 = tmp0; -+ } -+ env->CSR_TLBREHI = env->CSR_TLBREHI & (~0x3f); -+ env->CSR_TLBREHI = env->CSR_TLBREHI | pagesize; -+#endif -+ return; -+} -+ -+target_ulong helper_read_pgd(CPULOONGARCHState *env) -+{ -+ uint64_t badv; -+ -+ assert(env->CSR_TLBRERA & 0x1); -+ -+ if (env->CSR_TLBRERA & 0x1) { -+ badv = env->CSR_TLBRBADV; -+ } else { -+ badv = env->CSR_BADV; -+ } -+ -+ if ((badv >> 63) & 0x1) { -+ return env->CSR_PGDH; -+ } else { -+ return env->CSR_PGDL; -+ } -+} -+ -+/* TLB management */ -+static uint64_t ls3a5k_pagesize_to_mask(int pagesize) -+{ -+ /* 4KB - 1GB */ -+ if (pagesize < 12 && pagesize > 30) { -+ printf("[ERROR] unsupported page size %d\n", pagesize); -+ exit(-1); -+ } -+ -+ return (1 << (pagesize + 1)) - 1; -+} -+ -+static void ls3a5k_fill_tlb_entry(CPULOONGARCHState *env, -+ ls3a5k_tlb_t *tlb, int is_ftlb) -+{ -+ uint64_t page_mask; /* 0000...00001111...1111 */ -+ uint32_t page_size; -+ uint64_t entryhi; -+ uint64_t lo0, lo1; -+ -+ if (env->CSR_TLBRERA & 0x1) { -+ page_size = env->CSR_TLBREHI & 0x3f; -+ entryhi = env->CSR_TLBREHI; -+ lo0 = env->CSR_TLBRELO0; -+ lo1 = env->CSR_TLBRELO1; -+ } else { -+ page_size = (env->CSR_TLBIDX >> CSR_TLBIDX_PS_SHIFT) & 0x3f; -+ entryhi = env->CSR_TLBEHI; -+ lo0 = env->CSR_TLBELO0; -+ lo1 = env->CSR_TLBELO1; -+ } -+ -+ if (page_size == 0) { -+ printf("Warning: page_size is 0\n"); -+ } -+ -+ /* 15-12 11-8 7-4 3-0 -+ * 4KB: 0001 1111 1111 1111 // double 4KB mask [12:0] -+ * 16KB: 0111 1111 1111 1111 // double 16KB mask [14:0] -+ */ -+ if (is_ftlb) { -+ page_mask = env->tlb->mmu.ls3a5k.ftlb_mask; -+ } else { -+ page_mask = ls3a5k_pagesize_to_mask(page_size); -+ } -+ -+ tlb->VPN = entryhi & 0xffffffffe000 & ~page_mask; -+ -+ tlb->ASID = env->CSR_ASID & 0x3ff; /* CSR_ASID[9:0] */ -+ tlb->EHINV = 0; -+ tlb->G = (lo0 >> CSR_TLBLO0_GLOBAL_SHIFT) & /* CSR_TLBLO[6] */ -+ (lo1 >> CSR_TLBLO1_GLOBAL_SHIFT) & 1; -+ -+ tlb->PageMask = page_mask; -+ tlb->PageSize = page_size; -+ -+ tlb->V0 = (lo0 >> CSR_TLBLO0_V_SHIFT) & 0x1; /* [0] */ -+ tlb->WE0 = (lo0 >> CSR_TLBLO0_WE_SHIFT) & 0x1; /* [1] */ -+ tlb->PLV0 = (lo0 >> CSR_TLBLO0_PLV_SHIFT) & 0x3; /* [3:2] */ -+ tlb->C0 = (lo0 >> CSR_TLBLO0_CCA_SHIFT) & 0x3; /* [5:4] */ -+ tlb->PPN0 = (lo0 & 0xfffffffff000 & ~(page_mask >> 1)); -+ tlb->RI0 = (lo0 >> CSR_TLBLO0_RI_SHIFT) & 0x1; /* [61] */ -+ tlb->XI0 = (lo0 >> CSR_TLBLO0_XI_SHIFT) & 0x1; /* [62] */ -+ tlb->RPLV0 = (lo0 >> CSR_TLBLO0_RPLV_SHIFT) & 0x1; /* [63] */ -+ -+ tlb->V1 = (lo1 >> CSR_TLBLO1_V_SHIFT) & 0x1; /* [0] */ -+ tlb->WE1 = (lo1 >> CSR_TLBLO1_WE_SHIFT) & 0x1; /* [1] */ -+ tlb->PLV1 = (lo1 >> CSR_TLBLO1_PLV_SHIFT) & 0x3; /* [3:2] */ -+ tlb->C1 = (lo1 >> CSR_TLBLO1_CCA_SHIFT) & 0x3; /* [5:4] */ -+ tlb->PPN1 = (lo1 & 0xfffffffff000 & ~(page_mask >> 1)); -+ tlb->RI1 = (lo1 >> CSR_TLBLO1_RI_SHIFT) & 0x1; /* [61] */ -+ tlb->XI1 = (lo1 >> CSR_TLBLO1_XI_SHIFT) & 0x1; /* [62] */ -+ tlb->RPLV1 = (lo1 >> CSR_TLBLO1_RPLV_SHIFT) & 0x1; /* [63] */ -+} -+ -+static void ls3a5k_fill_tlb(CPULOONGARCHState *env, int idx, bool tlbwr) -+{ -+ ls3a5k_tlb_t *tlb; -+ -+ tlb = &env->tlb->mmu.ls3a5k.tlb[idx]; -+ if (tlbwr) { -+ if ((env->CSR_TLBIDX >> CSR_TLBIDX_EHINV_SHIFT) & 0x1) { -+ tlb->EHINV = 1; -+ return; -+ } -+ } -+ -+ if (idx < 2048) { -+ ls3a5k_fill_tlb_entry(env, tlb, 1); -+ } else { -+ ls3a5k_fill_tlb_entry(env, tlb, 0); -+ } -+} -+ -+void ls3a5k_flush_vtlb(CPULOONGARCHState *env) -+{ -+ uint32_t ftlb_size = env->tlb->mmu.ls3a5k.ftlb_size; -+ uint32_t vtlb_size = env->tlb->mmu.ls3a5k.vtlb_size; -+ int i; -+ -+ ls3a5k_tlb_t *tlb; -+ -+ for (i = ftlb_size; i < ftlb_size + vtlb_size; ++i) { -+ tlb = &env->tlb->mmu.ls3a5k.tlb[i]; -+ tlb->EHINV = 1; -+ } -+ -+ cpu_loongarch_tlb_flush(env); -+} -+ -+void ls3a5k_flush_ftlb(CPULOONGARCHState *env) -+{ -+ uint32_t ftlb_size = env->tlb->mmu.ls3a5k.ftlb_size; -+ int i; -+ -+ ls3a5k_tlb_t *tlb; -+ -+ for (i = 0; i < ftlb_size; ++i) { -+ tlb = &env->tlb->mmu.ls3a5k.tlb[i]; -+ tlb->EHINV = 1; -+ } -+ -+ cpu_loongarch_tlb_flush(env); -+} -+ -+void ls3a5k_helper_tlbclr(CPULOONGARCHState *env) -+{ -+ int i; -+ uint16_t asid; -+ int vsize, fsize, index; -+ int start = 0, end = -1; -+ -+ asid = env->CSR_ASID & 0x3ff; -+ vsize = env->tlb->mmu.ls3a5k.vtlb_size; -+ fsize = env->tlb->mmu.ls3a5k.ftlb_size; -+ index = env->CSR_TLBIDX & CSR_TLBIDX_IDX; -+ -+ if (index < fsize) { -+ /* FTLB. One line per operation */ -+ int set = index % 256; -+ start = set * 8; -+ end = start + 7; -+ } else if (index < (fsize + vsize)) { -+ /* VTLB. All entries */ -+ start = fsize; -+ end = fsize + vsize - 1; -+ } else { -+ /* Ignore */ -+ } -+ -+ for (i = start; i <= end; i++) { -+ ls3a5k_tlb_t *tlb; -+ tlb = &env->tlb->mmu.ls3a5k.tlb[i]; -+ if (!tlb->G && tlb->ASID == asid) { -+ tlb->EHINV = 1; -+ } -+ } -+ -+ cpu_loongarch_tlb_flush(env); -+} -+ -+void ls3a5k_helper_tlbflush(CPULOONGARCHState *env) -+{ -+ int i; -+ int vsize, fsize, index; -+ int start = 0, end = -1; -+ -+ vsize = env->tlb->mmu.ls3a5k.vtlb_size; -+ fsize = env->tlb->mmu.ls3a5k.ftlb_size; -+ index = env->CSR_TLBIDX & CSR_TLBIDX_IDX; -+ -+ if (index < fsize) { -+ /* FTLB. One line per operation */ -+ int set = index % 256; -+ start = set * 8; -+ end = start + 7; -+ } else if (index < (fsize + vsize)) { -+ /* VTLB. All entries */ -+ start = fsize; -+ end = fsize + vsize - 1; -+ } else { -+ /* Ignore */ -+ } -+ -+ for (i = start; i <= end; i++) { -+ env->tlb->mmu.ls3a5k.tlb[i].EHINV = 1; -+ } -+ -+ cpu_loongarch_tlb_flush(env); -+} -+ -+void ls3a5k_helper_invtlb(CPULOONGARCHState *env, target_ulong addr, -+ target_ulong info, int op) -+{ -+ uint32_t asid = info & 0x3ff; -+ int i; -+ -+ switch (op) { -+ case 0: -+ case 1: -+ for (i = 0; i < env->tlb->nb_tlb; i++) { -+ env->tlb->mmu.ls3a5k.tlb[i].EHINV = 1; -+ } -+ break; -+ case 4: { -+ int i; -+ for (i = 0; i < env->tlb->nb_tlb; i++) { -+ struct ls3a5k_tlb_t *tlb = &env->tlb->mmu.ls3a5k.tlb[i]; -+ -+ if (!tlb->G && tlb->ASID == asid) { -+ tlb->EHINV = 1; -+ } -+ } -+ break; -+ } -+ -+ case 5: { -+ int i; -+ for (i = 0; i < env->tlb->nb_tlb; i++) { -+ struct ls3a5k_tlb_t *tlb = &env->tlb->mmu.ls3a5k.tlb[i]; -+ uint64_t vpn = addr & 0xffffffffe000 & ~tlb->PageMask; -+ -+ if (!tlb->G && tlb->ASID == asid && vpn == tlb->VPN) { -+ tlb->EHINV = 1; -+ } -+ } -+ break; -+ } -+ case 6: { -+ int i; -+ for (i = 0; i < env->tlb->nb_tlb; i++) { -+ struct ls3a5k_tlb_t *tlb = &env->tlb->mmu.ls3a5k.tlb[i]; -+ uint64_t vpn = addr & 0xffffffffe000 & ~tlb->PageMask; -+ -+ if ((tlb->G || tlb->ASID == asid) && vpn == tlb->VPN) { -+ tlb->EHINV = 1; -+ } -+ } -+ break; -+ } -+ default: -+ helper_raise_exception(env, EXCP_RI); -+ } -+ -+ cpu_loongarch_tlb_flush(env); -+} -+ -+static void ls3a5k_invalidate_tlb_entry(CPULOONGARCHState *env, -+ ls3a5k_tlb_t *tlb) -+{ -+ LOONGARCHCPU *cpu = loongarch_env_get_cpu(env); -+ CPUState *cs = CPU(cpu); -+ target_ulong addr; -+ target_ulong end; -+ target_ulong mask; -+ -+ mask = tlb->PageMask; /* 000...000111...111 */ -+ -+ if (tlb->V0) { -+ addr = tlb->VPN & ~mask; /* xxx...xxx[0]000..0000 */ -+ end = addr | (mask >> 1); /* xxx...xxx[0]111..1111 */ -+ while (addr < end) { -+ tlb_flush_page(cs, addr); -+ addr += TARGET_PAGE_SIZE; -+ } -+ } -+ -+ if (tlb->V1) { -+ /* xxx...xxx[1]000..0000 */ -+ addr = (tlb->VPN & ~mask) | ((mask >> 1) + 1); -+ end = addr | mask; /* xxx...xxx[1]111..1111 */ -+ while (addr - 1 < end) { -+ tlb_flush_page(cs, addr); -+ addr += TARGET_PAGE_SIZE; -+ } -+ } -+} -+ -+void ls3a5k_invalidate_tlb(CPULOONGARCHState *env, int idx) -+{ -+ ls3a5k_tlb_t *tlb; -+ int asid = env->CSR_ASID & 0x3ff; -+ tlb = &env->tlb->mmu.ls3a5k.tlb[idx]; -+ if (tlb->G == 0 && tlb->ASID != asid) { -+ return; -+ } -+ ls3a5k_invalidate_tlb_entry(env, tlb); -+} -+ -+void ls3a5k_helper_tlbwr(CPULOONGARCHState *env) -+{ -+ int idx = env->CSR_TLBIDX & CSR_TLBIDX_IDX; /* [11:0] */ -+ -+ /* Convert idx if in FTLB */ -+ if (idx < env->tlb->mmu.ls3a5k.ftlb_size) { -+ /* -+ * 0 3 6 0 1 2 -+ * 1 4 7 => 3 4 5 -+ * 2 5 8 6 7 8 -+ */ -+ int set = idx % 256; -+ int way = idx / 256; -+ idx = set * 8 + way; -+ } -+ ls3a5k_invalidate_tlb(env, idx); -+ ls3a5k_fill_tlb(env, idx, true); -+} -+ -+void ls3a5k_helper_tlbfill(CPULOONGARCHState *env) -+{ -+ uint64_t mask; -+ uint64_t address; -+ int idx; -+ int set, ftlb_idx; -+ -+ uint64_t entryhi; -+ uint32_t pagesize; -+ -+ if (env->CSR_TLBRERA & 0x1) { -+ entryhi = env->CSR_TLBREHI & ~0x3f; -+ pagesize = env->CSR_TLBREHI & 0x3f; -+ } else { -+ entryhi = env->CSR_TLBEHI; -+ pagesize = (env->CSR_TLBIDX >> CSR_TLBIDX_PS_SHIFT) & 0x3f; -+ } -+ -+ uint32_t ftlb_size = env->tlb->mmu.ls3a5k.ftlb_size; -+ uint32_t vtlb_size = env->tlb->mmu.ls3a5k.vtlb_size; -+ -+ mask = ls3a5k_pagesize_to_mask(pagesize); -+ -+ if (mask == env->tlb->mmu.ls3a5k.ftlb_mask && -+ env->tlb->mmu.ls3a5k.ftlb_size > 0) { -+ /* only write into FTLB */ -+ address = entryhi & 0xffffffffe000; /* [47:13] */ -+ -+ /* choose one set ramdomly */ -+ set = cpu_loongarch_get_random_ls3a5k_tlb(0, 7); -+ -+ /* index in one set */ -+ ftlb_idx = (address >> 15) & 0xff; /* [0,255] */ -+ -+ /* final idx */ -+ idx = ftlb_idx * 8 + set; /* max is 7 + 8 * 255 = 2047 */ -+ } else { -+ /* only write into VTLB */ -+ int wired_nr = env->CSR_TLBWIRED & 0x3f; -+ idx = cpu_loongarch_get_random_ls3a5k_tlb( -+ ftlb_size + wired_nr, ftlb_size + vtlb_size - 1); -+ } -+ -+ ls3a5k_invalidate_tlb(env, idx); -+ ls3a5k_fill_tlb(env, idx, false); -+} -+ -+void ls3a5k_helper_tlbsrch(CPULOONGARCHState *env) -+{ -+ uint64_t mask; -+ uint64_t vpn; -+ uint64_t tag; -+ uint16_t asid; -+ -+ int ftlb_size = env->tlb->mmu.ls3a5k.ftlb_size; -+ int vtlb_size = env->tlb->mmu.ls3a5k.vtlb_size; -+ int i; -+ int ftlb_idx; /* [0,255] 2^8 0xff */ -+ -+ ls3a5k_tlb_t *tlb; -+ -+ asid = env->CSR_ASID & 0x3ff; -+ -+ /* search VTLB */ -+ for (i = ftlb_size; i < ftlb_size + vtlb_size; ++i) { -+ tlb = &env->tlb->mmu.ls3a5k.tlb[i]; -+ mask = tlb->PageMask; -+ -+ vpn = env->CSR_TLBEHI & 0xffffffffe000 & ~mask; -+ tag = tlb->VPN & ~mask; -+ -+ if ((tlb->G == 1 || tlb->ASID == asid) && vpn == tag && tlb->EHINV != 1) -+ { -+ env->CSR_TLBIDX = (i & 0xfff) | -+ ((tlb->PageSize & 0x3f) << CSR_TLBIDX_PS_SHIFT); -+ goto _MATCH_OUT_; -+ } -+ } -+ -+ if (ftlb_size == 0) { -+ goto _NO_MATCH_OUT_; -+ } -+ -+ /* search FTLB */ -+ mask = env->tlb->mmu.ls3a5k.ftlb_mask; -+ vpn = env->CSR_TLBEHI & 0xffffffffe000 & ~mask; -+ -+ ftlb_idx = (env->CSR_TLBEHI & 0xffffffffe000) >> 15; /* 16 KB */ -+ ftlb_idx = ftlb_idx & 0xff; /* [0,255] */ -+ -+ for (i = 0; i < 8; ++i) { -+ tlb = &env->tlb->mmu.ls3a5k.tlb[ftlb_idx * 8 + i]; -+ tag = tlb->VPN & ~mask; -+ -+ if ((tlb->G == 1 || tlb->ASID == asid) && vpn == tag && tlb->EHINV != 1) -+ { -+ env->CSR_TLBIDX = ((i * 256 + ftlb_idx) & 0xfff) | -+ ((tlb->PageSize & 0x3f) << CSR_TLBIDX_PS_SHIFT); -+ goto _MATCH_OUT_; -+ } -+ } -+ -+_NO_MATCH_OUT_: -+ env->CSR_TLBIDX = 1 << CSR_TLBIDX_EHINV_SHIFT; -+_MATCH_OUT_: -+ return; -+} -+ -+void ls3a5k_helper_tlbrd(CPULOONGARCHState *env) -+{ -+ ls3a5k_tlb_t *tlb; -+ int idx; -+ uint16_t asid; -+ -+ idx = env->CSR_TLBIDX & CSR_TLBIDX_IDX; -+ if (idx < env->tlb->mmu.ls3a5k.ftlb_size) { -+ int set = idx % 256; -+ int way = idx / 256; -+ idx = set * 8 + way; -+ } -+ -+ tlb = &env->tlb->mmu.ls3a5k.tlb[idx]; -+ -+ asid = env->CSR_ASID & 0x3ff; -+ -+ if (asid != tlb->ASID) { -+ cpu_loongarch_tlb_flush(env); -+ } -+ -+ if (tlb->EHINV) { -+ /* invalid TLB entry */ -+ env->CSR_TLBIDX = 1 << CSR_TLBIDX_EHINV_SHIFT; -+ env->CSR_TLBEHI = 0; -+ env->CSR_TLBELO0 = 0; -+ env->CSR_TLBELO1 = 0; -+ } else { -+ /* valid TLB entry */ -+ env->CSR_TLBIDX = (env->CSR_TLBIDX & 0xfff) | -+ ((tlb->PageSize & 0x3f) << CSR_TLBIDX_PS_SHIFT); -+ env->CSR_TLBEHI = tlb->VPN; -+ env->CSR_TLBELO0 = (tlb->V0 << CSR_TLBLO0_V_SHIFT) | -+ (tlb->WE0 << CSR_TLBLO0_WE_SHIFT) | -+ (tlb->PLV0 << CSR_TLBLO0_PLV_SHIFT) | -+ (tlb->C0 << CSR_TLBLO0_CCA_SHIFT) | -+ (tlb->G << CSR_TLBLO0_GLOBAL_SHIFT) | -+ (tlb->PPN0 & 0xfffffffff000) | -+ ((uint64_t)tlb->RI0 << CSR_TLBLO0_RI_SHIFT) | -+ ((uint64_t)tlb->XI0 << CSR_TLBLO0_XI_SHIFT) | -+ ((uint64_t)tlb->RPLV0 << CSR_TLBLO0_RPLV_SHIFT); -+ env->CSR_TLBELO1 = (tlb->V1 << CSR_TLBLO1_V_SHIFT) | -+ (tlb->WE1 << CSR_TLBLO1_WE_SHIFT) | -+ (tlb->PLV1 << CSR_TLBLO1_PLV_SHIFT) | -+ (tlb->C1 << CSR_TLBLO1_CCA_SHIFT) | -+ (tlb->G << CSR_TLBLO0_GLOBAL_SHIFT) | -+ (tlb->PPN1 & 0xfffffffff000) | -+ ((uint64_t)tlb->RI1 << CSR_TLBLO1_RI_SHIFT) | -+ ((uint64_t)tlb->XI1 << CSR_TLBLO1_XI_SHIFT) | -+ ((uint64_t)tlb->RPLV1 << CSR_TLBLO1_RPLV_SHIFT); -+ env->CSR_ASID = (tlb->ASID << CSR_ASID_ASID_SHIFT) | -+ (env->CSR_ASID & 0xff0000); -+ } -+} -+ -+void helper_tlbwr(CPULOONGARCHState *env) -+{ -+ env->tlb->helper_tlbwr(env); -+} -+ -+void helper_tlbfill(CPULOONGARCHState *env) -+{ -+ env->tlb->helper_tlbfill(env); -+} -+ -+void helper_tlbsrch(CPULOONGARCHState *env) -+{ -+ env->tlb->helper_tlbsrch(env); -+} -+ -+void helper_tlbrd(CPULOONGARCHState *env) -+{ -+ env->tlb->helper_tlbrd(env); -+} -+ -+void helper_tlbclr(CPULOONGARCHState *env) -+{ -+ env->tlb->helper_tlbclr(env); -+} -+ -+void helper_tlbflush(CPULOONGARCHState *env) -+{ -+ env->tlb->helper_tlbflush(env); -+} -+ -+void helper_invtlb(CPULOONGARCHState *env, target_ulong addr, target_ulong info, -+ target_ulong op) -+{ -+ env->tlb->helper_invtlb(env, addr, info, op); -+} -+ -+static void ls3a5k_mmu_init(CPULOONGARCHState *env, const loongarch_def_t *def) -+{ -+ /* number of VTLB */ -+ env->tlb->nb_tlb = 64; -+ env->tlb->mmu.ls3a5k.vtlb_size = 64; -+ -+ /* number of FTLB */ -+ env->tlb->nb_tlb += 2048; -+ env->tlb->mmu.ls3a5k.ftlb_size = 2048; -+ env->tlb->mmu.ls3a5k.ftlb_mask = (1 << 15) - 1; /* 16 KB */ -+ /* -+ * page_size | ftlb_mask | party field -+ * ---------------------------------------------------------------- -+ * 4 KB = 12 | ( 1 << 13 ) - 1 = [12:0] | [12] -+ * 16 KB = 14 | ( 1 << 15 ) - 1 = [14:0] | [14] -+ * 64 KB = 16 | ( 1 << 17 ) - 1 = [16:0] | [16] -+ * 256 KB = 18 | ( 1 << 19 ) - 1 = [18:0] | [18] -+ * 1 MB = 20 | ( 1 << 21 ) - 1 = [20:0] | [20] -+ * 4 MB = 22 | ( 1 << 23 ) - 1 = [22:0] | [22] -+ * 16 MB = 24 | ( 1 << 25 ) - 1 = [24:0] | [24] -+ * 64 MB = 26 | ( 1 << 27 ) - 1 = [26:0] | [26] -+ * 256 MB = 28 | ( 1 << 29 ) - 1 = [28:0] | [28] -+ * 1 GB = 30 | ( 1 << 31 ) - 1 = [30:0] | [30] -+ * ---------------------------------------------------------------- -+ * take party field index as @n. eg. For 16 KB, n = 14 -+ * ---------------------------------------------------------------- -+ * tlb->VPN = TLBEHI & 0xffffffffe000[47:13] & ~mask = [47:n+1] -+ * tlb->PPN = TLBLO0 & 0xffffffffe000[47:13] & ~mask = [47:n+1] -+ * tlb->PPN = TLBLO1 & 0xffffffffe000[47:13] & ~mask = [47:n+1] -+ * ---------------------------------------------------------------- -+ * On mapping : -+ * > vpn = address & 0xffffffffe000[47:13] & ~mask = [47:n+1] -+ * > tag = tlb->VPN & ~mask = [47:n+1] -+ * ---------------------------------------------------------------- -+ * physical address = [47:n+1] | [n:0] -+ * physical address = tlb->PPN0 | (address & mask) -+ * physical address = tlb->PPN1 | (address & mask) -+ */ -+ -+ int i; -+ for (i = 0; i < env->tlb->nb_tlb; i++) { -+ env->tlb->mmu.ls3a5k.tlb[i].EHINV = 1; -+ } -+ -+ /* TLB's helper functions */ -+ env->tlb->map_address = &ls3a5k_map_address; -+ env->tlb->helper_tlbwr = ls3a5k_helper_tlbwr; -+ env->tlb->helper_tlbfill = ls3a5k_helper_tlbfill; -+ env->tlb->helper_tlbsrch = ls3a5k_helper_tlbsrch; -+ env->tlb->helper_tlbrd = ls3a5k_helper_tlbrd; -+ env->tlb->helper_tlbclr = ls3a5k_helper_tlbclr; -+ env->tlb->helper_tlbflush = ls3a5k_helper_tlbflush; -+ env->tlb->helper_invtlb = ls3a5k_helper_invtlb; -+} -+ -+void mmu_init(CPULOONGARCHState *env, const loongarch_def_t *def) -+{ -+ env->tlb = g_malloc0(sizeof(CPULOONGARCHTLBContext)); -+ -+ switch (def->mmu_type) { -+ case MMU_TYPE_LS3A5K: -+ ls3a5k_mmu_init(env, def); -+ break; -+ default: -+ cpu_abort(CPU(loongarch_env_get_cpu(env)), "MMU type not supported\n"); -+ } -+} -+#endif /* !CONFIG_USER_ONLY */ -diff --git a/target/loongarch64/trace-events b/target/loongarch64/trace-events -new file mode 100644 -index 0000000000..e0bca4f82e ---- /dev/null -+++ b/target/loongarch64/trace-events -@@ -0,0 +1,3 @@ -+# See docs/devel/tracing.txt for syntax documentation. -+ -+# target/loongarch/translate.c -diff --git a/target/loongarch64/trans.inc.c b/target/loongarch64/trans.inc.c -new file mode 100644 -index 0000000000..e50670be47 ---- /dev/null -+++ b/target/loongarch64/trans.inc.c -@@ -0,0 +1,3472 @@ -+static bool trans_syscall(DisasContext *ctx, arg_syscall *a) -+{ -+ generate_exception_end(ctx, EXCP_SYSCALL); -+ return true; -+} -+ -+static bool trans_break(DisasContext *ctx, arg_break *a) -+{ -+ generate_exception_end(ctx, EXCP_BREAK); -+ return true; -+} -+ -+static bool trans_dbcl(DisasContext *ctx, arg_dbcl *a) -+{ -+ /* -+ * dbcl instruction is not support in tcg -+ */ -+ generate_exception_end(ctx, EXCP_RI); -+ return true; -+} -+ -+static bool trans_addi_w(DisasContext *ctx, arg_addi_w *a) -+{ -+ gen_arith_imm(ctx, OPC_LARCH_ADDI_W, a->rd, a->rj, a->si12); -+ return true; -+} -+ -+static bool trans_addi_d(DisasContext *ctx, arg_addi_d *a) -+{ -+ gen_arith_imm(ctx, OPC_LARCH_ADDI_D, a->rd, a->rj, a->si12); -+ return true; -+} -+ -+static bool trans_slli_d(DisasContext *ctx, arg_slli_d *a) -+{ -+ if (a->rd == 0) { -+ /* Nop */ -+ return true; -+ } -+ -+ TCGv t0 = tcg_temp_new(); -+ -+ gen_load_gpr(t0, a->rj); -+ tcg_gen_shli_tl(cpu_gpr[a->rd], t0, a->ui6); -+ -+ tcg_temp_free(t0); -+ return true; -+} -+ -+static bool trans_andi(DisasContext *ctx, arg_andi *a) -+{ -+ gen_logic_imm(ctx, OPC_LARCH_ANDI, a->rd, a->rj, a->ui12); -+ return true; -+} -+ -+static bool trans_srli_d(DisasContext *ctx, arg_srli_d *a) -+{ -+ TCGv t0 = tcg_temp_new(); -+ -+ gen_load_gpr(t0, a->rj); -+ tcg_gen_shri_tl(cpu_gpr[a->rd], t0, a->ui6); -+ -+ tcg_temp_free(t0); -+ return true; -+} -+ -+static bool trans_slli_w(DisasContext *ctx, arg_slli_w *a) -+{ -+ if (a->rd == 0) { -+ /* Nop */ -+ return true; -+ } -+ -+ TCGv t0 = tcg_temp_new(); -+ -+ gen_load_gpr(t0, a->rj); -+ tcg_gen_shli_tl(t0, t0, a->ui5); -+ tcg_gen_ext32s_tl(cpu_gpr[a->rd], t0); -+ -+ tcg_temp_free(t0); -+ return true; -+} -+ -+static bool trans_addu16i_d(DisasContext *ctx, arg_addu16i_d *a) -+{ -+ if (a->rj != 0) { -+ tcg_gen_addi_tl(cpu_gpr[a->rd], cpu_gpr[a->rj], a->si16 << 16); -+ } else { -+ tcg_gen_movi_tl(cpu_gpr[a->rd], a->si16 << 16); -+ } -+ return true; -+} -+ -+static bool trans_lu12i_w(DisasContext *ctx, arg_lu12i_w *a) -+{ -+ tcg_gen_movi_tl(cpu_gpr[a->rd], a->si20 << 12); -+ return true; -+} -+ -+static bool trans_lu32i_d(DisasContext *ctx, arg_lu32i_d *a) -+{ -+ TCGv_i64 t0, t1; -+ t0 = tcg_temp_new_i64(); -+ t1 = tcg_temp_new_i64(); -+ -+ tcg_gen_movi_tl(t0, a->si20); -+ tcg_gen_concat_tl_i64(t1, cpu_gpr[a->rd], t0); -+ gen_store_gpr(t1, a->rd); -+ -+ tcg_temp_free(t0); -+ tcg_temp_free(t1); -+ return true; -+} -+ -+static bool trans_pcaddi(DisasContext *ctx, arg_pcaddi *a) -+{ -+ target_ulong pc = ctx->base.pc_next; -+ target_ulong addr = pc + (a->si20 << 2); -+ tcg_gen_movi_tl(cpu_gpr[a->rd], addr); -+ return true; -+} -+ -+static bool trans_pcalau12i(DisasContext *ctx, arg_pcalau12i *a) -+{ -+ target_ulong pc = ctx->base.pc_next; -+ target_ulong addr = (pc + (a->si20 << 12)) & ~0xfff; -+ tcg_gen_movi_tl(cpu_gpr[a->rd], addr); -+ return true; -+} -+ -+static bool trans_pcaddu12i(DisasContext *ctx, arg_pcaddu12i *a) -+{ -+ target_ulong pc = ctx->base.pc_next; -+ target_ulong addr = pc + (a->si20 << 12); -+ tcg_gen_movi_tl(cpu_gpr[a->rd], addr); -+ return true; -+} -+ -+static bool trans_pcaddu18i(DisasContext *ctx, arg_pcaddu18i *a) -+{ -+ target_ulong pc = ctx->base.pc_next; -+ target_ulong addr = pc + ((target_ulong)(a->si20) << 18); -+ tcg_gen_movi_tl(cpu_gpr[a->rd], addr); -+ return true; -+} -+ -+static bool trans_slti(DisasContext *ctx, arg_slti *a) -+{ -+ gen_slt_imm(ctx, OPC_LARCH_SLTI, a->rd, a->rj, a->si12); -+ return true; -+} -+ -+static bool trans_sltui(DisasContext *ctx, arg_sltui *a) -+{ -+ gen_slt_imm(ctx, OPC_LARCH_SLTIU, a->rd, a->rj, a->si12); -+ return true; -+} -+ -+static bool trans_lu52i_d(DisasContext *ctx, arg_lu52i_d *a) -+{ -+ TCGv t0 = tcg_temp_new(); -+ TCGv t1 = tcg_temp_new(); -+ -+ gen_load_gpr(t1, a->rj); -+ -+ tcg_gen_movi_tl(t0, a->si12); -+ tcg_gen_shli_tl(t0, t0, 52); -+ tcg_gen_andi_tl(t1, t1, 0xfffffffffffffU); -+ tcg_gen_or_tl(cpu_gpr[a->rd], t0, t1); -+ -+ tcg_temp_free(t0); -+ tcg_temp_free(t1); -+ return true; -+} -+ -+static bool trans_ori(DisasContext *ctx, arg_ori *a) -+{ -+ gen_logic_imm(ctx, OPC_LARCH_ORI, a->rd, a->rj, a->ui12); -+ return true; -+} -+ -+static bool trans_xori(DisasContext *ctx, arg_xori *a) -+{ -+ gen_logic_imm(ctx, OPC_LARCH_XORI, a->rd, a->rj, a->ui12); -+ return true; -+} -+ -+static bool trans_bstrins_d(DisasContext *ctx, arg_bstrins_d *a) -+{ -+ int lsb = a->lsbd; -+ int msb = a->msbd; -+ TCGv t0 = tcg_temp_new(); -+ TCGv t1 = tcg_temp_new(); -+ -+ if (lsb > msb) { -+ return false; -+ } -+ -+ gen_load_gpr(t1, a->rj); -+ gen_load_gpr(t0, a->rd); -+ tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1); -+ gen_store_gpr(t0, a->rd); -+ -+ tcg_temp_free(t0); -+ tcg_temp_free(t1); -+ return true; -+} -+ -+static bool trans_bstrpick_d(DisasContext *ctx, arg_bstrpick_d *a) -+{ -+ int lsb = a->lsbd; -+ int msb = a->msbd; -+ TCGv t0 = tcg_temp_new(); -+ TCGv t1 = tcg_temp_new(); -+ -+ if (lsb > msb) { -+ return false; -+ } -+ -+ gen_load_gpr(t1, a->rj); -+ gen_load_gpr(t0, a->rd); -+ tcg_gen_extract_tl(t0, t1, lsb, msb - lsb + 1); -+ gen_store_gpr(t0, a->rd); -+ -+ tcg_temp_free(t0); -+ tcg_temp_free(t1); -+ return true; -+} -+ -+static bool trans_bstrins_w(DisasContext *ctx, arg_bstrins_w *a) -+{ -+ gen_bitops(ctx, OPC_LARCH_TRINS_W, a->rd, a->rj, a->lsbw, a->msbw); -+ return true; -+} -+ -+static bool trans_bstrpick_w(DisasContext *ctx, arg_bstrpick_w *a) -+{ -+ if (a->lsbw > a->msbw) { -+ return false; -+ } -+ gen_bitops(ctx, OPC_LARCH_TRPICK_W, -+ a->rd, a->rj, a->lsbw, a->msbw - a->lsbw); -+ return true; -+} -+ -+static bool trans_ldptr_w(DisasContext *ctx, arg_ldptr_w *a) -+{ -+ gen_ld(ctx, OPC_LARCH_LDPTR_W, a->rd, a->rj, a->si14 << 2); -+ return true; -+} -+ -+static bool trans_stptr_w(DisasContext *ctx, arg_stptr_w *a) -+{ -+ gen_st(ctx, OPC_LARCH_STPTR_W, a->rd, a->rj, a->si14 << 2); -+ return true; -+} -+ -+static bool trans_ldptr_d(DisasContext *ctx, arg_ldptr_d *a) -+{ -+ gen_ld(ctx, OPC_LARCH_LDPTR_D, a->rd, a->rj, a->si14 << 2); -+ return true; -+} -+ -+static bool trans_stptr_d(DisasContext *ctx, arg_stptr_d *a) -+{ -+ gen_st(ctx, OPC_LARCH_STPTR_D, a->rd, a->rj, a->si14 << 2); -+ return true; -+} -+ -+static bool trans_ld_b(DisasContext *ctx, arg_ld_b *a) -+{ -+ gen_ld(ctx, OPC_LARCH_LD_B, a->rd, a->rj, a->si12); -+ return true; -+} -+ -+static bool trans_ld_h(DisasContext *ctx, arg_ld_h *a) -+{ -+ gen_ld(ctx, OPC_LARCH_LD_H, a->rd, a->rj, a->si12); -+ return true; -+} -+ -+static bool trans_ld_w(DisasContext *ctx, arg_ld_w *a) -+{ -+ gen_ld(ctx, OPC_LARCH_LD_W, a->rd, a->rj, a->si12); -+ return true; -+} -+ -+static bool trans_ld_d(DisasContext *ctx, arg_ld_d *a) -+{ -+ gen_ld(ctx, OPC_LARCH_LD_D, a->rd, a->rj, a->si12); -+ return true; -+} -+ -+static bool trans_st_b(DisasContext *ctx, arg_st_b *a) -+{ -+ gen_st(ctx, OPC_LARCH_ST_B, a->rd, a->rj, a->si12); -+ return true; -+} -+ -+static bool trans_st_h(DisasContext *ctx, arg_st_h *a) -+{ -+ gen_st(ctx, OPC_LARCH_ST_H, a->rd, a->rj, a->si12); -+ return true; -+} -+ -+static bool trans_st_w(DisasContext *ctx, arg_st_w *a) -+{ -+ gen_st(ctx, OPC_LARCH_ST_W, a->rd, a->rj, a->si12); -+ return true; -+} -+ -+static bool trans_st_d(DisasContext *ctx, arg_st_d *a) -+{ -+ gen_st(ctx, OPC_LARCH_ST_D, a->rd, a->rj, a->si12); -+ return true; -+} -+ -+static bool trans_ld_bu(DisasContext *ctx, arg_ld_bu *a) -+{ -+ gen_ld(ctx, OPC_LARCH_LD_BU, a->rd, a->rj, a->si12); -+ return true; -+} -+ -+static bool trans_ld_hu(DisasContext *ctx, arg_ld_hu *a) -+{ -+ gen_ld(ctx, OPC_LARCH_LD_HU, a->rd, a->rj, a->si12); -+ return true; -+} -+ -+static bool trans_ld_wu(DisasContext *ctx, arg_ld_wu *a) -+{ -+ gen_ld(ctx, OPC_LARCH_LD_WU, a->rd, a->rj, a->si12); -+ return true; -+} -+ -+static bool trans_preld(DisasContext *ctx, arg_preld *a) -+{ -+ /* Treat as NOP. */ -+ return true; -+} -+ -+static bool trans_ll_w(DisasContext *ctx, arg_ll_w *a) -+{ -+ gen_ld(ctx, OPC_LARCH_LL_W, a->rd, a->rj, a->si14 << 2); -+ return true; -+} -+ -+static bool trans_sc_w(DisasContext *ctx, arg_sc_w *a) -+{ -+ gen_st_cond(ctx, a->rd, a->rj, a->si14 << 2, MO_TESL, false); -+ return true; -+} -+ -+static bool trans_ll_d(DisasContext *ctx, arg_ll_d *a) -+{ -+ gen_ld(ctx, OPC_LARCH_LL_D, a->rd, a->rj, a->si14 << 2); -+ return true; -+} -+ -+static bool trans_sc_d(DisasContext *ctx, arg_sc_d *a) -+{ -+ gen_st_cond(ctx, a->rd, a->rj, a->si14 << 2, MO_TEQ, false); -+ return true; -+} -+ -+static bool trans_fld_s(DisasContext *ctx, arg_fld_s *a) -+{ -+ gen_fp_ldst(ctx, OPC_LARCH_FLD_S, a->fd, a->rj, a->si12); -+ return true; -+} -+ -+static bool trans_fst_s(DisasContext *ctx, arg_fst_s *a) -+{ -+ gen_fp_ldst(ctx, OPC_LARCH_FST_S, a->fd, a->rj, a->si12); -+ return true; -+} -+ -+static bool trans_fld_d(DisasContext *ctx, arg_fld_d *a) -+{ -+ gen_fp_ldst(ctx, OPC_LARCH_FLD_D, a->fd, a->rj, a->si12); -+ return true; -+} -+ -+static bool trans_fst_d(DisasContext *ctx, arg_fst_d *a) -+{ -+ gen_fp_ldst(ctx, OPC_LARCH_FST_D, a->fd, a->rj, a->si12); -+ return true; -+} -+ -+static bool trans_ldx_b(DisasContext *ctx, arg_ldx_b *a) -+{ -+ TCGv t0 = tcg_temp_new(); -+ TCGv t1 = tcg_temp_new(); -+ int mem_idx = ctx->mem_idx; -+ -+ gen_op_addr_add(ctx, t0, cpu_gpr[a->rj], cpu_gpr[a->rk]); -+ tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_SB); -+ gen_store_gpr(t1, a->rd); -+ tcg_temp_free(t0); -+ tcg_temp_free(t1); -+ return true; -+} -+ -+static bool trans_ldx_h(DisasContext *ctx, arg_ldx_h *a) -+{ -+ TCGv t0 = tcg_temp_new(); -+ TCGv t1 = tcg_temp_new(); -+ int mem_idx = ctx->mem_idx; -+ -+ gen_op_addr_add(ctx, t0, cpu_gpr[a->rj], cpu_gpr[a->rk]); -+ tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_TESW | ctx->default_tcg_memop_mask); -+ gen_store_gpr(t1, a->rd); -+ tcg_temp_free(t0); -+ tcg_temp_free(t1); -+ return true; -+} -+ -+static bool trans_ldx_w(DisasContext *ctx, arg_ldx_w *a) -+{ -+ TCGv t0 = tcg_temp_new(); -+ TCGv t1 = tcg_temp_new(); -+ int mem_idx = ctx->mem_idx; -+ -+ gen_op_addr_add(ctx, t0, cpu_gpr[a->rj], cpu_gpr[a->rk]); -+ tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_TESL | ctx->default_tcg_memop_mask); -+ gen_store_gpr(t1, a->rd); -+ tcg_temp_free(t0); -+ return true; -+} -+ -+static bool trans_ldx_d(DisasContext *ctx, arg_ldx_d *a) -+{ -+ TCGv t0 = tcg_temp_new(); -+ TCGv t1 = tcg_temp_new(); -+ int mem_idx = ctx->mem_idx; -+ -+ gen_op_addr_add(ctx, t0, cpu_gpr[a->rj], cpu_gpr[a->rk]); -+ tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_TEQ | ctx->default_tcg_memop_mask); -+ gen_store_gpr(t1, a->rd); -+ tcg_temp_free(t1); -+ return true; -+} -+ -+static bool trans_stx_b(DisasContext *ctx, arg_stx_b *a) -+{ -+ TCGv t0 = tcg_temp_new(); -+ TCGv t1 = tcg_temp_new(); -+ int mem_idx = ctx->mem_idx; -+ -+ gen_op_addr_add(ctx, t0, cpu_gpr[a->rj], cpu_gpr[a->rk]); -+ gen_load_gpr(t1, a->rd); -+ tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_8); -+ tcg_temp_free(t0); -+ tcg_temp_free(t1); -+ return true; -+} -+ -+static bool trans_stx_h(DisasContext *ctx, arg_stx_h *a) -+{ -+ TCGv t0 = tcg_temp_new(); -+ TCGv t1 = tcg_temp_new(); -+ int mem_idx = ctx->mem_idx; -+ -+ gen_op_addr_add(ctx, t0, cpu_gpr[a->rj], cpu_gpr[a->rk]); -+ gen_load_gpr(t1, a->rd); -+ tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUW | -+ ctx->default_tcg_memop_mask); -+ tcg_temp_free(t0); -+ tcg_temp_free(t1); -+ return true; -+} -+ -+static bool trans_stx_w(DisasContext *ctx, arg_stx_w *a) -+{ -+ TCGv t0 = tcg_temp_new(); -+ TCGv t1 = tcg_temp_new(); -+ int mem_idx = ctx->mem_idx; -+ -+ gen_op_addr_add(ctx, t0, cpu_gpr[a->rj], cpu_gpr[a->rk]); -+ gen_load_gpr(t1, a->rd); -+ tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUL | -+ ctx->default_tcg_memop_mask); -+ tcg_temp_free(t0); -+ tcg_temp_free(t1); -+ return true; -+} -+ -+static bool trans_stx_d(DisasContext *ctx, arg_stx_d *a) -+{ -+ TCGv t0 = tcg_temp_new(); -+ TCGv t1 = tcg_temp_new(); -+ int mem_idx = ctx->mem_idx; -+ -+ gen_op_addr_add(ctx, t0, cpu_gpr[a->rj], cpu_gpr[a->rk]); -+ gen_load_gpr(t1, a->rd); -+ tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEQ | -+ ctx->default_tcg_memop_mask); -+ tcg_temp_free(t0); -+ tcg_temp_free(t1); -+ return true; -+} -+ -+static bool trans_ldx_bu(DisasContext *ctx, arg_ldx_bu *a) -+{ -+ TCGv t0 = tcg_temp_new(); -+ TCGv t1 = tcg_temp_new(); -+ int mem_idx = ctx->mem_idx; -+ -+ gen_op_addr_add(ctx, t0, cpu_gpr[a->rj], cpu_gpr[a->rk]); -+ tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB); -+ gen_store_gpr(t1, a->rd); -+ tcg_temp_free(t0); -+ tcg_temp_free(t1); -+ return true; -+} -+ -+static bool trans_ldx_hu(DisasContext *ctx, arg_ldx_hu *a) -+{ -+ TCGv t0 = tcg_temp_new(); -+ TCGv t1 = tcg_temp_new(); -+ int mem_idx = ctx->mem_idx; -+ -+ gen_op_addr_add(ctx, t0, cpu_gpr[a->rj], cpu_gpr[a->rk]); -+ tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_TEUW | -+ ctx->default_tcg_memop_mask); -+ gen_store_gpr(t1, a->rd); -+ tcg_temp_free(t0); -+ tcg_temp_free(t1); -+ return true; -+} -+ -+static bool trans_ldx_wu(DisasContext *ctx, arg_ldx_wu *a) -+{ -+ TCGv t0 = tcg_temp_new(); -+ TCGv t1 = tcg_temp_new(); -+ int mem_idx = ctx->mem_idx; -+ -+ gen_op_addr_add(ctx, t0, cpu_gpr[a->rj], cpu_gpr[a->rk]); -+ tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_TEUL | -+ ctx->default_tcg_memop_mask); -+ gen_store_gpr(t1, a->rd); -+ tcg_temp_free(t0); -+ tcg_temp_free(t1); -+ return true; -+} -+ -+static bool trans_fldx_s(DisasContext *ctx, arg_fldx_s *a) -+{ -+ gen_flt3_ldst(ctx, OPC_LARCH_FLDX_S, a->fd, 0, a->rj, a->rk); -+ return true; -+} -+ -+static bool trans_fldx_d(DisasContext *ctx, arg_fldx_d *a) -+{ -+ gen_flt3_ldst(ctx, OPC_LARCH_FLDX_D, a->fd, 0, a->rj, a->rk); -+ return true; -+} -+ -+static bool trans_fstx_s(DisasContext *ctx, arg_fstx_s *a) -+{ -+ gen_flt3_ldst(ctx, OPC_LARCH_FSTX_S, 0, a->fd, a->rj, a->rk); -+ return true; -+} -+ -+static bool trans_fstx_d(DisasContext *ctx, arg_fstx_d *a) -+{ -+ gen_flt3_ldst(ctx, OPC_LARCH_FSTX_D, 0, a->fd, a->rj, a->rk); -+ return true; -+} -+ -+#define TRANS_AM_W(name, op) \ -+static bool trans_ ## name(DisasContext *ctx, arg_ ## name * a) \ -+{ \ -+ if ((a->rd != 0) && ((a->rj == a->rd) || (a->rk == a->rd))) { \ -+ printf("%s: warning, register equal\n", __func__); \ -+ return false; \ -+ } \ -+ int mem_idx = ctx->mem_idx; \ -+ TCGv addr = tcg_temp_new(); \ -+ TCGv val = tcg_temp_new(); \ -+ TCGv ret = tcg_temp_new(); \ -+\ -+ gen_load_gpr(addr, a->rj); \ -+ gen_load_gpr(val, a->rk); \ -+ tcg_gen_atomic_##op##_tl(ret, addr, val, mem_idx, MO_TESL | \ -+ ctx->default_tcg_memop_mask); \ -+ gen_store_gpr(ret, a->rd); \ -+\ -+ tcg_temp_free(addr); \ -+ tcg_temp_free(val); \ -+ tcg_temp_free(ret); \ -+ return true; \ -+} -+#define TRANS_AM_D(name, op) \ -+static bool trans_ ## name(DisasContext *ctx, arg_ ## name * a) \ -+{ \ -+ if ((a->rd != 0) && ((a->rj == a->rd) || (a->rk == a->rd))) { \ -+ printf("%s: warning, register equal\n", __func__); \ -+ return false; \ -+ } \ -+ int mem_idx = ctx->mem_idx; \ -+ TCGv addr = tcg_temp_new(); \ -+ TCGv val = tcg_temp_new(); \ -+ TCGv ret = tcg_temp_new(); \ -+\ -+ gen_load_gpr(addr, a->rj); \ -+ gen_load_gpr(val, a->rk); \ -+ tcg_gen_atomic_##op##_tl(ret, addr, val, mem_idx, MO_TEQ | \ -+ ctx->default_tcg_memop_mask); \ -+ gen_store_gpr(ret, a->rd); \ -+\ -+ tcg_temp_free(addr); \ -+ tcg_temp_free(val); \ -+ tcg_temp_free(ret); \ -+ return true; \ -+} -+#define TRANS_AM(name, op) \ -+ TRANS_AM_W(name##_w, op) \ -+ TRANS_AM_D(name##_d, op) -+TRANS_AM(amswap, xchg) /* trans_amswap_w, trans_amswap_d */ -+TRANS_AM(amadd, fetch_add) /* trans_amadd_w, trans_amadd_d */ -+TRANS_AM(amand, fetch_and) /* trans_amand_w, trans_amand_d */ -+TRANS_AM(amor, fetch_or) /* trans_amor_w, trans_amor_d */ -+TRANS_AM(amxor, fetch_xor) /* trans_amxor_w, trans_amxor_d */ -+TRANS_AM(ammax, fetch_smax) /* trans_ammax_w, trans_ammax_d */ -+TRANS_AM(ammin, fetch_smin) /* trans_ammin_w, trans_ammin_d */ -+TRANS_AM_W(ammax_wu, fetch_umax) /* trans_ammax_wu */ -+TRANS_AM_D(ammax_du, fetch_umax) /* trans_ammax_du */ -+TRANS_AM_W(ammin_wu, fetch_umin) /* trans_ammin_wu */ -+TRANS_AM_D(ammin_du, fetch_umin) /* trans_ammin_du */ -+#undef TRANS_AM -+#undef TRANS_AM_W -+#undef TRANS_AM_D -+ -+#define TRANS_AM_DB_W(name, op) \ -+static bool trans_ ## name(DisasContext *ctx, arg_ ## name * a) \ -+{ \ -+ if ((a->rd != 0) && ((a->rj == a->rd) || (a->rk == a->rd))) { \ -+ printf("%s: warning, register equal\n", __func__); \ -+ return false; \ -+ } \ -+ int mem_idx = ctx->mem_idx; \ -+ TCGv addr = tcg_temp_new(); \ -+ TCGv val = tcg_temp_new(); \ -+ TCGv ret = tcg_temp_new(); \ -+\ -+ gen_sync(0x10); /* TCG_MO_ALL */ \ -+ gen_load_gpr(addr, a->rj); \ -+ gen_load_gpr(val, a->rk); \ -+ tcg_gen_atomic_##op##_tl(ret, addr, val, mem_idx, MO_TESL | \ -+ ctx->default_tcg_memop_mask); \ -+ gen_store_gpr(ret, a->rd); \ -+\ -+ tcg_temp_free(addr); \ -+ tcg_temp_free(val); \ -+ tcg_temp_free(ret); \ -+ return true; \ -+} -+#define TRANS_AM_DB_D(name, op) \ -+static bool trans_ ## name(DisasContext *ctx, arg_ ## name * a) \ -+{ \ -+ if ((a->rd != 0) && ((a->rj == a->rd) || (a->rk == a->rd))) { \ -+ printf("%s: warning, register equal\n", __func__); \ -+ return false; \ -+ } \ -+ int mem_idx = ctx->mem_idx; \ -+ TCGv addr = tcg_temp_new(); \ -+ TCGv val = tcg_temp_new(); \ -+ TCGv ret = tcg_temp_new(); \ -+\ -+ gen_sync(0x10); /* TCG_MO_ALL */ \ -+ gen_load_gpr(addr, a->rj); \ -+ gen_load_gpr(val, a->rk); \ -+ tcg_gen_atomic_##op##_tl(ret, addr, val, mem_idx, MO_TEQ | \ -+ ctx->default_tcg_memop_mask); \ -+ gen_store_gpr(ret, a->rd); \ -+\ -+ tcg_temp_free(addr); \ -+ tcg_temp_free(val); \ -+ tcg_temp_free(ret); \ -+ return true; \ -+} -+#define TRANS_AM_DB(name, op) \ -+ TRANS_AM_DB_W(name##_db_w, op) \ -+ TRANS_AM_DB_D(name##_db_d, op) -+TRANS_AM_DB(amswap, xchg) /* trans_amswap_db_w, trans_amswap_db_d */ -+TRANS_AM_DB(amadd, fetch_add) /* trans_amadd_db_w, trans_amadd_db_d */ -+TRANS_AM_DB(amand, fetch_and) /* trans_amand_db_w, trans_amand_db_d */ -+TRANS_AM_DB(amor, fetch_or) /* trans_amor_db_w, trans_amor_db_d */ -+TRANS_AM_DB(amxor, fetch_xor) /* trans_amxor_db_w, trans_amxor_db_d */ -+TRANS_AM_DB(ammax, fetch_smax) /* trans_ammax_db_w, trans_ammax_db_d */ -+TRANS_AM_DB(ammin, fetch_smin) /* trans_ammin_db_w, trans_ammin_db_d */ -+TRANS_AM_DB_W(ammax_db_wu, fetch_umax) /* trans_ammax_db_wu */ -+TRANS_AM_DB_D(ammax_db_du, fetch_umax) /* trans_ammax_db_du */ -+TRANS_AM_DB_W(ammin_db_wu, fetch_umin) /* trans_ammin_db_wu */ -+TRANS_AM_DB_D(ammin_db_du, fetch_umin) /* trans_ammin_db_du */ -+#undef TRANS_AM_DB -+#undef TRANS_AM_DB_W -+#undef TRANS_AM_DB_D -+ -+static bool trans_dbar(DisasContext *ctx, arg_dbar * a) -+{ -+ gen_sync(a->whint); -+ return true; -+} -+ -+static bool trans_ibar(DisasContext *ctx, arg_ibar *a) -+{ -+ /* -+ * FENCE_I is a no-op in QEMU, -+ * however we need to end the translation block -+ */ -+ ctx->base.is_jmp = DISAS_STOP; -+ return true; -+} -+ -+#define ASRTGT \ -+do { \ -+ TCGv t1 = tcg_temp_new(); \ -+ TCGv t2 = tcg_temp_new(); \ -+ gen_load_gpr(t1, a->rj); \ -+ gen_load_gpr(t2, a->rk); \ -+ gen_helper_asrtgt_d(cpu_env, t1, t2); \ -+ tcg_temp_free(t1); \ -+ tcg_temp_free(t2); \ -+} while (0) -+ -+#define ASRTLE \ -+do {\ -+ TCGv t1 = tcg_temp_new(); \ -+ TCGv t2 = tcg_temp_new(); \ -+ gen_load_gpr(t1, a->rj); \ -+ gen_load_gpr(t2, a->rk); \ -+ gen_helper_asrtle_d(cpu_env, t1, t2); \ -+ tcg_temp_free(t1); \ -+ tcg_temp_free(t2); \ -+} while (0) -+ -+static bool trans_fldgt_s(DisasContext *ctx, arg_fldgt_s *a) -+{ -+ ASRTGT; -+ gen_flt3_ldst(ctx, OPC_LARCH_FLDGT_S, a->fd, 0, a->rj, a->rk); -+ return true; -+} -+ -+static bool trans_fldgt_d(DisasContext *ctx, arg_fldgt_d *a) -+{ -+ ASRTGT; -+ gen_flt3_ldst(ctx, OPC_LARCH_FLDGT_D, a->fd, 0, a->rj, a->rk); -+ return true; -+} -+ -+static bool trans_fldle_s(DisasContext *ctx, arg_fldle_s *a) -+{ -+ ASRTLE; -+ gen_flt3_ldst(ctx, OPC_LARCH_FLDLE_S, a->fd, 0, a->rj, a->rk); -+ return true; -+} -+ -+static bool trans_fldle_d(DisasContext *ctx, arg_fldle_d *a) -+{ -+ ASRTLE; -+ gen_flt3_ldst(ctx, OPC_LARCH_FLDLE_D, a->fd, 0, a->rj, a->rk); -+ return true; -+} -+ -+static bool trans_fstgt_s(DisasContext *ctx, arg_fstgt_s *a) -+{ -+ ASRTGT; -+ gen_flt3_ldst(ctx, OPC_LARCH_FSTGT_S, 0, a->fd, a->rj, a->rk); -+ return true; -+} -+ -+static bool trans_fstgt_d(DisasContext *ctx, arg_fstgt_d *a) -+{ -+ ASRTGT; -+ gen_flt3_ldst(ctx, OPC_LARCH_FSTGT_D, 0, a->fd, a->rj, a->rk); -+ return true; -+} -+ -+static bool trans_fstle_s(DisasContext *ctx, arg_fstle_s *a) -+{ -+ ASRTLE; -+ gen_flt3_ldst(ctx, OPC_LARCH_FSTLE_S, 0, a->fd, a->rj, a->rk); -+ return true; -+} -+ -+static bool trans_fstle_d(DisasContext *ctx, arg_fstle_d *a) -+{ -+ ASRTLE; -+ gen_flt3_ldst(ctx, OPC_LARCH_FSTLE_D, 0, a->fd, a->rj, a->rk); -+ return true; -+} -+ -+#define DECL_ARG(name) \ -+ arg_ ## name arg = { \ -+ .rd = a->rd, \ -+ .rj = a->rj, \ -+ .rk = a->rk, \ -+ }; -+ -+static bool trans_ldgt_b(DisasContext *ctx, arg_ldgt_b *a) -+{ -+ ASRTGT; -+ DECL_ARG(ldx_b) -+ trans_ldx_b(ctx, &arg); -+ return true; -+} -+ -+static bool trans_ldgt_h(DisasContext *ctx, arg_ldgt_h *a) -+{ -+ ASRTGT; -+ DECL_ARG(ldx_h) -+ trans_ldx_h(ctx, &arg); -+ return true; -+} -+ -+static bool trans_ldgt_w(DisasContext *ctx, arg_ldgt_w *a) -+{ -+ ASRTGT; -+ DECL_ARG(ldx_w) -+ trans_ldx_w(ctx, &arg); -+ return true; -+} -+ -+static bool trans_ldgt_d(DisasContext *ctx, arg_ldgt_d *a) -+{ -+ ASRTGT; -+ DECL_ARG(ldx_d) -+ trans_ldx_d(ctx, &arg); -+ return true; -+} -+ -+static bool trans_ldle_b(DisasContext *ctx, arg_ldle_b *a) -+{ -+ ASRTLE; -+ DECL_ARG(ldx_b) -+ trans_ldx_b(ctx, &arg); -+ return true; -+} -+ -+static bool trans_ldle_h(DisasContext *ctx, arg_ldle_h *a) -+{ -+ ASRTLE; -+ DECL_ARG(ldx_h) -+ trans_ldx_h(ctx, &arg); -+ return true; -+} -+ -+static bool trans_ldle_w(DisasContext *ctx, arg_ldle_w *a) -+{ -+ ASRTLE; -+ DECL_ARG(ldx_w) -+ trans_ldx_w(ctx, &arg); -+ return true; -+} -+ -+static bool trans_ldle_d(DisasContext *ctx, arg_ldle_d *a) -+{ -+ ASRTLE; -+ DECL_ARG(ldx_d) -+ trans_ldx_d(ctx, &arg); -+ return true; -+} -+ -+static bool trans_stgt_b(DisasContext *ctx, arg_stgt_b *a) -+{ -+ ASRTGT; -+ DECL_ARG(stx_b) -+ trans_stx_b(ctx, &arg); -+ return true; -+} -+ -+static bool trans_stgt_h(DisasContext *ctx, arg_stgt_h *a) -+{ -+ ASRTGT; -+ DECL_ARG(stx_h) -+ trans_stx_h(ctx, &arg); -+ return true; -+} -+ -+static bool trans_stgt_w(DisasContext *ctx, arg_stgt_w *a) -+{ -+ ASRTGT; -+ DECL_ARG(stx_w) -+ trans_stx_w(ctx, &arg); -+ return true; -+} -+ -+static bool trans_stgt_d(DisasContext *ctx, arg_stgt_d *a) -+{ -+ ASRTGT; -+ DECL_ARG(stx_d) -+ trans_stx_d(ctx, &arg); -+ return true; -+} -+ -+static bool trans_stle_b(DisasContext *ctx, arg_stle_b *a) -+{ -+ ASRTLE; -+ DECL_ARG(stx_b) -+ trans_stx_b(ctx, &arg); -+ return true; -+} -+ -+static bool trans_stle_h(DisasContext *ctx, arg_stle_h *a) -+{ -+ ASRTLE; -+ DECL_ARG(stx_h) -+ trans_stx_h(ctx, &arg); -+ return true; -+} -+ -+static bool trans_stle_w(DisasContext *ctx, arg_stle_w *a) -+{ -+ ASRTLE; -+ DECL_ARG(stx_w) -+ trans_stx_w(ctx, &arg); -+ return true; -+} -+ -+static bool trans_stle_d(DisasContext *ctx, arg_stle_d *a) -+{ -+ ASRTLE; -+ DECL_ARG(stx_d) -+ trans_stx_d(ctx, &arg); -+ return true; -+} -+ -+#undef ASRTGT -+#undef ASRTLE -+#undef DECL_ARG -+ -+static bool trans_beqz(DisasContext *ctx, arg_beqz *a) -+{ -+ gen_compute_branch(ctx, OPC_LARCH_BEQZ, 4, a->rj, 0, a->offs21 << 2); -+ return true; -+} -+ -+static bool trans_bnez(DisasContext *ctx, arg_bnez *a) -+{ -+ gen_compute_branch(ctx, OPC_LARCH_BNEZ, 4, a->rj, 0, a->offs21 << 2); -+ return true; -+} -+ -+static bool trans_bceqz(DisasContext *ctx, arg_bceqz *a) -+{ -+ TCGv_i32 cj = tcg_const_i32(a->cj); -+ TCGv v0 = tcg_temp_new(); -+ TCGv v1 = tcg_const_i64(0); -+ -+ gen_helper_movcf2reg(v0, cpu_env, cj); -+ tcg_gen_setcond_tl(TCG_COND_EQ, bcond, v0, v1); -+ ctx->hflags |= LARCH_HFLAG_BC; -+ ctx->btarget = ctx->base.pc_next + (a->offs21 << 2); -+ -+ tcg_temp_free_i32(cj); -+ tcg_temp_free(v0); -+ tcg_temp_free(v1); -+ return true; -+} -+ -+static bool trans_bcnez(DisasContext *ctx, arg_bcnez *a) -+{ -+ TCGv_i32 cj = tcg_const_i32(a->cj); -+ TCGv v0 = tcg_temp_new(); -+ TCGv v1 = tcg_const_i64(0); -+ -+ gen_helper_movcf2reg(v0, cpu_env, cj); -+ tcg_gen_setcond_tl(TCG_COND_NE, bcond, v0, v1); -+ ctx->hflags |= LARCH_HFLAG_BC; -+ ctx->btarget = ctx->base.pc_next + (a->offs21 << 2); -+ -+ tcg_temp_free_i32(cj); -+ tcg_temp_free(v0); -+ tcg_temp_free(v1); -+ return true; -+} -+ -+static bool trans_b(DisasContext *ctx, arg_b *a) -+{ -+ gen_compute_branch(ctx, OPC_LARCH_B, 4, 0, 0, a->offs << 2); -+ return true; -+} -+ -+static bool trans_bl(DisasContext *ctx, arg_bl *a) -+{ -+ ctx->btarget = ctx->base.pc_next + (a->offs << 2); -+ tcg_gen_movi_tl(cpu_gpr[1], ctx->base.pc_next + 4); -+ ctx->hflags |= LARCH_HFLAG_B; -+ gen_branch(ctx, 4); -+ return true; -+} -+ -+static bool trans_blt(DisasContext *ctx, arg_blt *a) -+{ -+ gen_compute_branch(ctx, OPC_LARCH_BLT, 4, a->rj, a->rd, a->offs16 << 2); -+ return true; -+} -+ -+static bool trans_bge(DisasContext *ctx, arg_bge *a) -+{ -+ gen_compute_branch(ctx, OPC_LARCH_BGE, 4, a->rj, a->rd, a->offs16 << 2); -+ return true; -+} -+ -+static bool trans_bltu(DisasContext *ctx, arg_bltu *a) -+{ -+ gen_compute_branch(ctx, OPC_LARCH_BLTU, 4, a->rj, a->rd, a->offs16 << 2); -+ return true; -+} -+ -+static bool trans_bgeu(DisasContext *ctx, arg_bgeu *a) -+{ -+ gen_compute_branch(ctx, OPC_LARCH_BGEU, 4, a->rj, a->rd, a->offs16 << 2); -+ return true; -+} -+ -+static bool trans_beq(DisasContext *ctx, arg_beq *a) -+{ -+ gen_compute_branch(ctx, OPC_LARCH_BEQ, 4, a->rj, a->rd, a->offs16 << 2); -+ return true; -+} -+ -+static bool trans_bne(DisasContext *ctx, arg_bne *a) -+{ -+ gen_compute_branch(ctx, OPC_LARCH_BNE, 4, a->rj, a->rd, a->offs16 << 2); -+ return true; -+} -+ -+static bool trans_jirl(DisasContext *ctx, arg_jirl *a) -+{ -+ gen_base_offset_addr(ctx, btarget, a->rj, a->offs16 << 2); -+ if (a->rd != 0) { -+ tcg_gen_movi_tl(cpu_gpr[a->rd], ctx->base.pc_next + 4); -+ } -+ ctx->hflags |= LARCH_HFLAG_BR; -+ gen_branch(ctx, 4); -+ -+ return true; -+} -+ -+#define TRANS_F4FR(name, fmt, op, bits) \ -+static bool trans_ ## name ## _ ## fmt(DisasContext *ctx, \ -+ arg_##name##_##fmt * a) \ -+{ \ -+ check_cp1_enabled(ctx); \ -+ TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \ -+ TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \ -+ TCGv_i ## bits fp2 = tcg_temp_new_i ## bits(); \ -+ TCGv_i ## bits fp3 = tcg_temp_new_i ## bits(); \ -+ check_cp1_enabled(ctx); \ -+ gen_load_fpr ## bits(ctx, fp0, a->fj); \ -+ gen_load_fpr ## bits(ctx, fp1, a->fk); \ -+ gen_load_fpr ## bits(ctx, fp2, a->fa); \ -+ gen_helper_float_ ## op ## _ ## fmt(fp3, \ -+ cpu_env, fp0, fp1, fp2); \ -+ gen_store_fpr ## bits(ctx, fp3, a->fd); \ -+ tcg_temp_free_i ## bits(fp3); \ -+ tcg_temp_free_i ## bits(fp2); \ -+ tcg_temp_free_i ## bits(fp1); \ -+ tcg_temp_free_i ## bits(fp0); \ -+ return true; \ -+} -+ -+TRANS_F4FR(fmadd , s, maddf , 32) /* trans_fmadd_s */ -+TRANS_F4FR(fmadd , d, maddf , 64) /* trans_fmadd_d */ -+TRANS_F4FR(fmsub , s, msubf , 32) /* trans_fmsub_s */ -+TRANS_F4FR(fmsub , d, msubf , 64) /* trans_fmsub_d */ -+TRANS_F4FR(fnmadd, s, nmaddf, 32) /* trans_fnmadd_s */ -+TRANS_F4FR(fnmadd, d, nmaddf, 64) /* trans_fnmadd_d */ -+TRANS_F4FR(fnmsub, s, nmsubf, 32) /* trans_fnmsub_s */ -+TRANS_F4FR(fnmsub, d, nmsubf, 64) /* trans_fnmsub_d */ -+#undef TRANS_F4FR -+ -+static bool trans_fadd_s(DisasContext *ctx, arg_fadd_s * a) -+{ -+ gen_farith(ctx, OPC_LARCH_FADD_S, a->fk, a->fj, a->fd, 0); -+ return true; -+} -+ -+static bool trans_fadd_d(DisasContext *ctx, arg_fadd_d *a) -+{ -+ gen_farith(ctx, OPC_LARCH_FADD_D, a->fk, a->fj, a->fd, 0); -+ return true; -+} -+ -+static bool trans_fsub_s(DisasContext *ctx, arg_fsub_s *a) -+{ -+ gen_farith(ctx, OPC_LARCH_FSUB_S, a->fk, a->fj, a->fd, 0); -+ return true; -+} -+ -+static bool trans_fsub_d(DisasContext *ctx, arg_fsub_d *a) -+{ -+ gen_farith(ctx, OPC_LARCH_FSUB_D, a->fk, a->fj, a->fd, 0); -+ return true; -+} -+ -+static bool trans_fmul_s(DisasContext *ctx, arg_fmul_s *a) -+{ -+ gen_farith(ctx, OPC_LARCH_FMUL_S, a->fk, a->fj, a->fd, 0); -+ return true; -+} -+ -+static bool trans_fmul_d(DisasContext *ctx, arg_fmul_d *a) -+{ -+ gen_farith(ctx, OPC_LARCH_FMUL_D, a->fk, a->fj, a->fd, 0); -+ return true; -+} -+ -+static bool trans_fdiv_s(DisasContext *ctx, arg_fdiv_s *a) -+{ -+ gen_farith(ctx, OPC_LARCH_FDIV_S, a->fk, a->fj, a->fd, 0); -+ return true; -+} -+ -+static bool trans_fdiv_d(DisasContext *ctx, arg_fdiv_d *a) -+{ -+ gen_farith(ctx, OPC_LARCH_FDIV_D, a->fk, a->fj, a->fd, 0); -+ return true; -+} -+ -+static bool trans_fmax_s(DisasContext *ctx, arg_fmax_s *a) -+{ -+ gen_farith(ctx, OPC_LARCH_FMAX_S, a->fk, a->fj, a->fd, 0); -+ return true; -+} -+ -+static bool trans_fmax_d(DisasContext *ctx, arg_fmax_d *a) -+{ -+ gen_farith(ctx, OPC_LARCH_FMAX_D, a->fk, a->fj, a->fd, 0); -+ return true; -+} -+ -+static bool trans_fmin_s(DisasContext *ctx, arg_fmin_s *a) -+{ -+ gen_farith(ctx, OPC_LARCH_FMIN_S, a->fk, a->fj, a->fd, 0); -+ return true; -+} -+ -+static bool trans_fmin_d(DisasContext *ctx, arg_fmin_d *a) -+{ -+ gen_farith(ctx, OPC_LARCH_FMIN_D, a->fk, a->fj, a->fd, 0); -+ return true; -+} -+ -+static bool trans_fmaxa_s(DisasContext *ctx, arg_fmaxa_s *a) -+{ -+ gen_farith(ctx, OPC_LARCH_FMAXA_S, a->fk, a->fj, a->fd, 0); -+ return true; -+} -+ -+static bool trans_fmaxa_d(DisasContext *ctx, arg_fmaxa_d *a) -+{ -+ gen_farith(ctx, OPC_LARCH_FMAXA_D, a->fk, a->fj, a->fd, 0); -+ return true; -+} -+ -+static bool trans_fmina_s(DisasContext *ctx, arg_fmina_s *a) -+{ -+ gen_farith(ctx, OPC_LARCH_FMINA_S, a->fk, a->fj, a->fd, 0); -+ return true; -+} -+ -+static bool trans_fmina_d(DisasContext *ctx, arg_fmina_d *a) -+{ -+ gen_farith(ctx, OPC_LARCH_FMINA_D, a->fk, a->fj, a->fd, 0); -+ return true; -+} -+ -+static bool trans_fscaleb_s(DisasContext *ctx, arg_fscaleb_s *a) -+{ -+ TCGv_i32 fp0 = tcg_temp_new_i32(); -+ TCGv_i32 fp1 = tcg_temp_new_i32(); -+ -+ check_cp1_enabled(ctx); -+ gen_load_fpr32(ctx, fp0, a->fj); -+ gen_load_fpr32(ctx, fp1, a->fk); -+ gen_helper_float_exp2_s(fp0, cpu_env, fp0, fp1); -+ tcg_temp_free_i32(fp1); -+ gen_store_fpr32(ctx, fp0, a->fd); -+ tcg_temp_free_i32(fp0); -+ return true; -+} -+ -+static bool trans_fscaleb_d(DisasContext *ctx, arg_fscaleb_d *a) -+{ -+ TCGv_i64 fp0 = tcg_temp_new_i64(); -+ TCGv_i64 fp1 = tcg_temp_new_i64(); -+ -+ check_cp1_enabled(ctx); -+ gen_load_fpr64(ctx, fp0, a->fj); -+ gen_load_fpr64(ctx, fp1, a->fk); -+ gen_helper_float_exp2_d(fp0, cpu_env, fp0, fp1); -+ tcg_temp_free_i64(fp1); -+ gen_store_fpr64(ctx, fp0, a->fd); -+ tcg_temp_free_i64(fp0); -+ return true; -+} -+ -+static bool trans_fcopysign_s(DisasContext *ctx, arg_fcopysign_s *a) -+{ -+ TCGv_i32 fp0 = tcg_temp_new_i32(); -+ TCGv_i32 fp1 = tcg_temp_new_i32(); -+ TCGv_i32 fp2 = tcg_temp_new_i32(); -+ -+ check_cp1_enabled(ctx); -+ gen_load_fpr32(ctx, fp0, a->fj); -+ gen_load_fpr32(ctx, fp1, a->fk); -+ tcg_gen_deposit_i32(fp2, fp1, fp0, 0, 31); -+ gen_store_fpr32(ctx, fp2, a->fd); -+ -+ tcg_temp_free_i32(fp2); -+ tcg_temp_free_i32(fp1); -+ tcg_temp_free_i32(fp0); -+ return true; -+} -+ -+static bool trans_fcopysign_d(DisasContext *ctx, arg_fcopysign_d *a) -+{ -+ TCGv_i64 fp0 = tcg_temp_new_i64(); -+ TCGv_i64 fp1 = tcg_temp_new_i64(); -+ TCGv_i64 fp2 = tcg_temp_new_i64(); -+ -+ check_cp1_enabled(ctx); -+ gen_load_fpr64(ctx, fp0, a->fj); -+ gen_load_fpr64(ctx, fp1, a->fk); -+ tcg_gen_deposit_i64(fp2, fp1, fp0, 0, 63); -+ gen_store_fpr64(ctx, fp2, a->fd); -+ -+ tcg_temp_free_i64(fp2); -+ tcg_temp_free_i64(fp1); -+ tcg_temp_free_i64(fp0); -+ return true; -+} -+ -+static bool trans_fabs_s(DisasContext *ctx, arg_fabs_s *a) -+{ -+ gen_farith(ctx, OPC_LARCH_FABS_S, 0, a->fj, a->fd, 0); -+ return true; -+} -+ -+static bool trans_fabs_d(DisasContext *ctx, arg_fabs_d *a) -+{ -+ gen_farith(ctx, OPC_LARCH_FABS_D, 0, a->fj, a->fd, 0); -+ return true; -+} -+ -+static bool trans_fneg_s(DisasContext *ctx, arg_fneg_s *a) -+{ -+ gen_farith(ctx, OPC_LARCH_FNEG_S, 0, a->fj, a->fd, 0); -+ return true; -+} -+ -+static bool trans_fneg_d(DisasContext *ctx, arg_fneg_d *a) -+{ -+ gen_farith(ctx, OPC_LARCH_FNEG_D, 0, a->fj, a->fd, 0); -+ return true; -+} -+ -+static bool trans_flogb_s(DisasContext *ctx, arg_flogb_s *a) -+{ -+ TCGv_i32 fp0 = tcg_temp_new_i32(); -+ TCGv_i32 fp1 = tcg_temp_new_i32(); -+ -+ check_cp1_enabled(ctx); -+ gen_load_fpr32(ctx, fp0, a->fj); -+ gen_helper_float_logb_s(fp1, cpu_env, fp0); -+ gen_store_fpr32(ctx, fp1, a->fd); -+ -+ tcg_temp_free_i32(fp0); -+ tcg_temp_free_i32(fp1); -+ return true; -+} -+ -+static bool trans_flogb_d(DisasContext *ctx, arg_flogb_d *a) -+{ -+ TCGv_i64 fp0 = tcg_temp_new_i64(); -+ TCGv_i64 fp1 = tcg_temp_new_i64(); -+ -+ check_cp1_enabled(ctx); -+ gen_load_fpr64(ctx, fp0, a->fj); -+ gen_helper_float_logb_d(fp1, cpu_env, fp0); -+ gen_store_fpr64(ctx, fp1, a->fd); -+ -+ tcg_temp_free_i64(fp0); -+ tcg_temp_free_i64(fp1); -+ return true; -+} -+ -+static bool trans_fclass_s(DisasContext *ctx, arg_fclass_s *a) -+{ -+ gen_farith(ctx, OPC_LARCH_FCLASS_S, 0, a->fj, a->fd, 0); -+ return true; -+} -+ -+static bool trans_fclass_d(DisasContext *ctx, arg_fclass_d *a) -+{ -+ gen_farith(ctx, OPC_LARCH_FCLASS_D, 0, a->fj, a->fd, 0); -+ return true; -+} -+ -+static bool trans_fsqrt_s(DisasContext *ctx, arg_fsqrt_s *a) -+{ -+ gen_farith(ctx, OPC_LARCH_FSQRT_S, 0, a->fj, a->fd, 0); -+ return true; -+} -+ -+static bool trans_fsqrt_d(DisasContext *ctx, arg_fsqrt_d *a) -+{ -+ gen_farith(ctx, OPC_LARCH_FSQRT_D, 0, a->fj, a->fd, 0); -+ return true; -+} -+ -+static bool trans_frecip_s(DisasContext *ctx, arg_frecip_s *a) -+{ -+ gen_farith(ctx, OPC_LARCH_FRECIP_S, 0, a->fj, a->fd, 0); -+ return true; -+} -+ -+static bool trans_frecip_d(DisasContext *ctx, arg_frecip_d *a) -+{ -+ gen_farith(ctx, OPC_LARCH_FRECIP_D, 0, a->fj, a->fd, 0); -+ return true; -+} -+ -+static bool trans_frsqrt_s(DisasContext *ctx, arg_frsqrt_s *a) -+{ -+ gen_farith(ctx, OPC_LARCH_FRSQRT_S, 0, a->fj, a->fd, 0); -+ return true; -+} -+ -+static bool trans_frsqrt_d(DisasContext *ctx, arg_frsqrt_d *a) -+{ -+ gen_farith(ctx, OPC_LARCH_FRSQRT_D, 0, a->fj, a->fd, 0); -+ return true; -+} -+ -+static bool trans_fmov_s(DisasContext *ctx, arg_fmov_s *a) -+{ -+ gen_farith(ctx, OPC_LARCH_FMOV_S, 0, a->fj, a->fd, 0); -+ return true; -+} -+ -+static bool trans_fmov_d(DisasContext *ctx, arg_fmov_d *a) -+{ -+ gen_farith(ctx, OPC_LARCH_FMOV_D, 0, a->fj, a->fd, 0); -+ return true; -+} -+ -+static bool trans_movgr2fr_w(DisasContext *ctx, arg_movgr2fr_w *a) -+{ -+ gen_cp1(ctx, OPC_LARCH_GR2FR_W, a->rj, a->fd); -+ return true; -+} -+ -+static bool trans_movgr2fr_d(DisasContext *ctx, arg_movgr2fr_d *a) -+{ -+ gen_cp1(ctx, OPC_LARCH_GR2FR_D, a->rj, a->fd); -+ return true; -+} -+ -+static bool trans_movgr2frh_w(DisasContext *ctx, arg_movgr2frh_w *a) -+{ -+ gen_cp1(ctx, OPC_LARCH_GR2FRH_W, a->rj, a->fd); -+ return true; -+} -+ -+static bool trans_movfr2gr_s(DisasContext *ctx, arg_movfr2gr_s *a) -+{ -+ gen_cp1(ctx, OPC_LARCH_FR2GR_S, a->rd, a->fj); -+ return true; -+} -+ -+static bool trans_movfr2gr_d(DisasContext *ctx, arg_movfr2gr_d *a) -+{ -+ gen_cp1(ctx, OPC_LARCH_FR2GR_D, a->rd, a->fj); -+ return true; -+} -+ -+static bool trans_movfrh2gr_s(DisasContext *ctx, arg_movfrh2gr_s *a) -+{ -+ gen_cp1(ctx, OPC_LARCH_FRH2GR_S, a->rd, a->fj); -+ return true; -+} -+ -+static bool trans_movgr2fcsr(DisasContext *ctx, arg_movgr2fcsr *a) -+{ -+ TCGv t0 = tcg_temp_new(); -+ -+ check_cp1_enabled(ctx); -+ gen_load_gpr(t0, a->rj); -+ save_cpu_state(ctx, 0); -+ { -+ TCGv_i32 fs_tmp = tcg_const_i32(a->fcsrd); -+ gen_helper_0e2i(movgr2fcsr, t0, fs_tmp, a->rj); -+ tcg_temp_free_i32(fs_tmp); -+ } -+ /* Stop translation as we may have changed hflags */ -+ ctx->base.is_jmp = DISAS_STOP; -+ -+ tcg_temp_free(t0); -+ return true; -+} -+ -+static bool trans_movfcsr2gr(DisasContext *ctx, arg_movfcsr2gr *a) -+{ -+ TCGv t0 = tcg_temp_new(); -+ gen_helper_1e0i(movfcsr2gr, t0, a->fcsrs); -+ gen_store_gpr(t0, a->rd); -+ tcg_temp_free(t0); -+ return true; -+} -+ -+static bool trans_movfr2cf(DisasContext *ctx, arg_movfr2cf *a) -+{ -+ TCGv_i64 fp0 = tcg_temp_new_i64(); -+ TCGv_i32 cd = tcg_const_i32(a->cd); -+ -+ check_cp1_enabled(ctx); -+ gen_load_fpr64(ctx, fp0, a->fj); -+ gen_helper_movreg2cf(cpu_env, cd, fp0); -+ -+ tcg_temp_free_i64(fp0); -+ tcg_temp_free_i32(cd); -+ return true; -+} -+ -+static bool trans_movcf2fr(DisasContext *ctx, arg_movcf2fr *a) -+{ -+ TCGv t0 = tcg_temp_new(); -+ TCGv_i32 cj = tcg_const_i32(a->cj); -+ -+ check_cp1_enabled(ctx); -+ gen_helper_movcf2reg(t0, cpu_env, cj); -+ gen_store_fpr64(ctx, t0, a->fd); -+ -+ tcg_temp_free(t0); -+ return true; -+} -+ -+static bool trans_movgr2cf(DisasContext *ctx, arg_movgr2cf *a) -+{ -+ TCGv t0 = tcg_temp_new(); -+ TCGv_i32 cd = tcg_const_i32(a->cd); -+ -+ check_cp1_enabled(ctx); -+ gen_load_gpr(t0, a->rj); -+ gen_helper_movreg2cf(cpu_env, cd, t0); -+ -+ tcg_temp_free(t0); -+ tcg_temp_free_i32(cd); -+ return true; -+} -+ -+static bool trans_movcf2gr(DisasContext *ctx, arg_movcf2gr *a) -+{ -+ TCGv_i32 cj = tcg_const_i32(a->cj); -+ -+ check_cp1_enabled(ctx); -+ gen_helper_movcf2reg(cpu_gpr[a->rd], cpu_env, cj); -+ -+ tcg_temp_free_i32(cj); -+ return true; -+} -+ -+static bool trans_fcvt_s_d(DisasContext *ctx, arg_fcvt_s_d *a) -+{ -+ gen_farith(ctx, OPC_LARCH_FCVT_S_D, 0, a->fj, a->fd, 0); -+ return true; -+} -+ -+static bool trans_fcvt_d_s(DisasContext *ctx, arg_fcvt_d_s *a) -+{ -+ gen_farith(ctx, OPC_LARCH_FCVT_D_S, 0, a->fj, a->fd, 0); -+ return true; -+} -+ -+static bool trans_ftintrm_w_s(DisasContext *ctx, arg_ftintrm_l_s *a) -+{ -+ gen_farith(ctx, OPC_LARCH_FTINTRM_W_S, 0, a->fj, a->fd, 0); -+ return true; -+} -+ -+static bool trans_ftintrm_w_d(DisasContext *ctx, arg_ftintrm_l_d *a) -+{ -+ gen_farith(ctx, OPC_LARCH_FTINTRM_W_D, 0, a->fj, a->fd, 0); -+ return true; -+} -+ -+static bool trans_ftintrm_l_s(DisasContext *ctx, arg_ftintrm_l_s *a) -+{ -+ gen_farith(ctx, OPC_LARCH_FTINTRM_L_S, 0, a->fj, a->fd, 0); -+ return true; -+} -+ -+static bool trans_ftintrm_l_d(DisasContext *ctx, arg_ftintrm_l_d *a) -+{ -+ gen_farith(ctx, OPC_LARCH_FTINTRM_L_D, 0, a->fj, a->fd, 0); -+ return true; -+} -+ -+static bool trans_ftintrp_w_s(DisasContext *ctx, arg_ftintrp_w_s *a) -+{ -+ gen_farith(ctx, OPC_LARCH_FTINTRP_W_S, 0, a->fj, a->fd, 0); -+ return true; -+} -+ -+static bool trans_ftintrp_w_d(DisasContext *ctx, arg_ftintrp_w_d *a) -+{ -+ gen_farith(ctx, OPC_LARCH_FTINTRP_W_D, 0, a->fj, a->fd, 0); -+ return true; -+} -+ -+static bool trans_ftintrp_l_s(DisasContext *ctx, arg_ftintrp_l_s *a) -+{ -+ gen_farith(ctx, OPC_LARCH_FTINTRP_L_S, 0, a->fj, a->fd, 0); -+ return true; -+} -+ -+static bool trans_ftintrp_l_d(DisasContext *ctx, arg_ftintrp_l_d *a) -+{ -+ gen_farith(ctx, OPC_LARCH_FTINTRP_L_D, 0, a->fj, a->fd, 0); -+ return true; -+} -+ -+static bool trans_ftintrz_w_s(DisasContext *ctx, arg_ftintrz_w_s *a) -+{ -+ gen_farith(ctx, OPC_LARCH_FTINTRZ_W_S, 0, a->fj, a->fd, 0); -+ return true; -+} -+ -+static bool trans_ftintrz_w_d(DisasContext *ctx, arg_ftintrz_w_d *a) -+{ -+ gen_farith(ctx, OPC_LARCH_FTINTRZ_W_D, 0, a->fj, a->fd, 0); -+ return true; -+} -+ -+static bool trans_ftintrz_l_s(DisasContext *ctx, arg_ftintrz_l_s *a) -+{ -+ gen_farith(ctx, OPC_LARCH_FTINTRZ_L_S, 0, a->fj, a->fd, 0); -+ return true; -+} -+ -+static bool trans_ftintrz_l_d(DisasContext *ctx, arg_ftintrz_l_d *a) -+{ -+ gen_farith(ctx, OPC_LARCH_FTINTRZ_L_D, 0, a->fj, a->fd, 0); -+ return true; -+} -+ -+static bool trans_ftintrne_w_s(DisasContext *ctx, arg_ftintrne_w_s *a) -+{ -+ gen_farith(ctx, OPC_LARCH_FTINTRNE_W_S, 0, a->fj, a->fd, 0); -+ return true; -+} -+ -+static bool trans_ftintrne_w_d(DisasContext *ctx, arg_ftintrne_w_d *a) -+{ -+ gen_farith(ctx, OPC_LARCH_FTINTRNE_W_D, 0, a->fj, a->fd, 0); -+ return true; -+} -+ -+static bool trans_ftintrne_l_s(DisasContext *ctx, arg_ftintrne_l_s *a) -+{ -+ gen_farith(ctx, OPC_LARCH_FTINTRNE_L_S, 0, a->fj, a->fd, 0); -+ return true; -+} -+ -+static bool trans_ftintrne_l_d(DisasContext *ctx, arg_ftintrne_l_d *a) -+{ -+ gen_farith(ctx, OPC_LARCH_FTINTRNE_L_D, 0, a->fj, a->fd, 0); -+ return true; -+} -+ -+static bool trans_ftint_w_s(DisasContext *ctx, arg_ftint_w_s *a) -+{ -+ gen_farith(ctx, OPC_LARCH_FTINT_W_S, 0, a->fj, a->fd, 0); -+ return true; -+} -+ -+static bool trans_ftint_w_d(DisasContext *ctx, arg_ftint_w_d *a) -+{ -+ gen_farith(ctx, OPC_LARCH_FTINT_W_D, 0, a->fj, a->fd, 0); -+ return true; -+} -+ -+static bool trans_ftint_l_s(DisasContext *ctx, arg_ftint_l_s *a) -+{ -+ gen_farith(ctx, OPC_LARCH_FTINT_L_S, 0, a->fj, a->fd, 0); -+ return true; -+} -+ -+static bool trans_ftint_l_d(DisasContext *ctx, arg_ftint_l_d *a) -+{ -+ gen_farith(ctx, OPC_LARCH_FTINT_L_D, 0, a->fj, a->fd, 0); -+ return true; -+} -+ -+static bool trans_ffint_s_w(DisasContext *ctx, arg_ffint_s_w *a) -+{ -+ gen_farith(ctx, OPC_LARCH_FFINT_S_W, 0, a->fj, a->fd, 0); -+ return true; -+} -+ -+static bool trans_ffint_s_l(DisasContext *ctx, arg_ffint_s_l *a) -+{ -+ gen_farith(ctx, OPC_LARCH_FFINT_S_L, 0, a->fj, a->fd, 0); -+ return true; -+} -+ -+static bool trans_ffint_d_w(DisasContext *ctx, arg_ffint_d_w *a) -+{ -+ gen_farith(ctx, OPC_LARCH_FFINT_D_W, 0, a->fj, a->fd, 0); -+ return true; -+} -+ -+static bool trans_ffint_d_l(DisasContext *ctx, arg_ffint_d_l *a) -+{ -+ gen_farith(ctx, OPC_LARCH_FFINT_D_L, 0, a->fj, a->fd, 0); -+ return true; -+} -+ -+static bool trans_frint_s(DisasContext *ctx, arg_frint_s *a) -+{ -+ gen_farith(ctx, OPC_LARCH_FRINT_S, 0, a->fj, a->fd, 0); -+ return true; -+} -+ -+static bool trans_frint_d(DisasContext *ctx, arg_frint_d *a) -+{ -+ gen_farith(ctx, OPC_LARCH_FRINT_D, 0, a->fj, a->fd, 0); -+ return true; -+} -+ -+static bool trans_alsl_w(DisasContext *ctx, arg_alsl_w *a) -+{ -+ gen_lsa(ctx, OPC_LARCH_ALSL_W, a->rd, a->rj, a->rk, a->sa2); -+ return true; -+} -+ -+static bool trans_alsl_wu(DisasContext *ctx, arg_alsl_wu *a) -+{ -+ TCGv t0, t1; -+ t0 = tcg_temp_new(); -+ t1 = tcg_temp_new(); -+ gen_load_gpr(t0, a->rj); -+ gen_load_gpr(t1, a->rk); -+ tcg_gen_shli_tl(t0, t0, a->sa2 + 1); -+ tcg_gen_add_tl(t0, t0, t1); -+ tcg_gen_ext32u_tl(cpu_gpr[a->rd], t0); -+ tcg_temp_free(t0); -+ tcg_temp_free(t1); -+ -+ return true; -+} -+ -+static bool trans_alsl_d(DisasContext *ctx, arg_alsl_d *a) -+{ -+ check_larch_64(ctx); -+ gen_lsa(ctx, OPC_LARCH_ALSL_D, a->rd, a->rj, a->rk, a->sa2); -+ return true; -+} -+ -+static bool trans_bytepick_w(DisasContext *ctx, arg_bytepick_w *a) -+{ -+ gen_align(ctx, 32, a->rd, a->rj, a->rk, a->sa2); -+ return true; -+} -+ -+static bool trans_bytepick_d(DisasContext *ctx, arg_bytepick_d *a) -+{ -+ check_larch_64(ctx); -+ gen_align(ctx, 64, a->rd, a->rj, a->rk, a->sa3); -+ return true; -+} -+ -+static bool trans_add_w(DisasContext *ctx, arg_add_w *a) -+{ -+ gen_arith(ctx, OPC_LARCH_ADD_W, a->rd, a->rj, a->rk); -+ return true; -+} -+ -+static bool trans_sub_w(DisasContext *ctx, arg_sub_w *a) -+{ -+ gen_arith(ctx, OPC_LARCH_SUB_W, a->rd, a->rj, a->rk); -+ return true; -+} -+ -+static bool trans_add_d(DisasContext *ctx, arg_add_d *a) -+{ -+ gen_arith(ctx, OPC_LARCH_ADD_D, a->rd, a->rj, a->rk); -+ return true; -+} -+ -+static bool trans_sub_d(DisasContext *ctx, arg_sub_d *a) -+{ -+ check_larch_64(ctx); -+ gen_arith(ctx, OPC_LARCH_SUB_D, a->rd, a->rj, a->rk); -+ return true; -+} -+ -+static bool trans_slt(DisasContext *ctx, arg_slt *a) -+{ -+ gen_slt(ctx, OPC_LARCH_SLT, a->rd, a->rj, a->rk); -+ return true; -+} -+ -+static bool trans_sltu(DisasContext *ctx, arg_sltu *a) -+{ -+ gen_slt(ctx, OPC_LARCH_SLTU, a->rd, a->rj, a->rk); -+ return true; -+} -+ -+static bool trans_maskeqz(DisasContext *ctx, arg_maskeqz *a) -+{ -+ gen_cond_move(ctx, OPC_LARCH_MASKEQZ, a->rd, a->rj, a->rk); -+ return true; -+} -+ -+static bool trans_masknez(DisasContext *ctx, arg_masknez *a) -+{ -+ gen_cond_move(ctx, OPC_LARCH_MASKNEZ, a->rd, a->rj, a->rk); -+ return true; -+} -+ -+static bool trans_nor(DisasContext *ctx, arg_nor *a) -+{ -+ gen_logic(ctx, OPC_LARCH_NOR, a->rd, a->rj, a->rk); -+ return true; -+} -+ -+static bool trans_and(DisasContext *ctx, arg_and *a) -+{ -+ gen_logic(ctx, OPC_LARCH_AND, a->rd, a->rj, a->rk); -+ return true; -+} -+ -+static bool trans_or(DisasContext *ctx, arg_or *a) -+{ -+ gen_logic(ctx, OPC_LARCH_OR, a->rd, a->rj, a->rk); -+ return true; -+} -+ -+static bool trans_xor(DisasContext *ctx, arg_xor *a) -+{ -+ gen_logic(ctx, OPC_LARCH_XOR, a->rd, a->rj, a->rk); -+ return true; -+} -+ -+static bool trans_orn(DisasContext *ctx, arg_orn *a) -+{ -+ TCGv t0 = tcg_temp_new(); -+ gen_load_gpr(t0, a->rk); -+ tcg_gen_not_tl(t0, t0); -+ tcg_gen_or_tl(cpu_gpr[a->rd], cpu_gpr[a->rj], t0); -+ tcg_temp_free(t0); -+ return true; -+} -+ -+static bool trans_andn(DisasContext *ctx, arg_andn *a) -+{ -+ TCGv t0, t1; -+ t0 = tcg_temp_new(); -+ t1 = tcg_temp_new(); -+ gen_load_gpr(t0, a->rk); -+ gen_load_gpr(t1, a->rj); -+ tcg_gen_not_tl(t0, t0); -+ tcg_gen_and_tl(cpu_gpr[a->rd], t1, t0); -+ tcg_temp_free(t0); -+ tcg_temp_free(t1); -+ return true; -+} -+ -+static bool trans_sll_w(DisasContext *ctx, arg_sll_w *a) -+{ -+ gen_shift(ctx, OPC_LARCH_SLL_W, a->rd, a->rk, a->rj); -+ return true; -+} -+ -+static bool trans_srl_w(DisasContext *ctx, arg_srl_w *a) -+{ -+ gen_shift(ctx, OPC_LARCH_SRL_W, a->rd, a->rk, a->rj); -+ return true; -+} -+ -+static bool trans_sra_w(DisasContext *ctx, arg_sra_w *a) -+{ -+ gen_shift(ctx, OPC_LARCH_SRA_W, a->rd, a->rk, a->rj); -+ return true; -+} -+ -+static bool trans_sll_d(DisasContext *ctx, arg_sll_d *a) -+{ -+ check_larch_64(ctx); -+ gen_shift(ctx, OPC_LARCH_SLL_D, a->rd, a->rk, a->rj); -+ return true; -+} -+ -+static bool trans_srl_d(DisasContext *ctx, arg_srl_d *a) -+{ -+ check_larch_64(ctx); -+ gen_shift(ctx, OPC_LARCH_SRL_D, a->rd, a->rk, a->rj); -+ return true; -+} -+ -+static bool trans_sra_d(DisasContext *ctx, arg_sra_d *a) -+{ -+ check_larch_64(ctx); -+ gen_shift(ctx, OPC_LARCH_SRA_D, a->rd, a->rk, a->rj); -+ return true; -+} -+ -+static bool trans_rotr_w(DisasContext *ctx, arg_rotr_w *a) -+{ -+ gen_shift(ctx, OPC_LARCH_ROTR_W, a->rd, a->rk, a->rj); -+ return true; -+} -+ -+static bool trans_rotr_d(DisasContext *ctx, arg_rotr_d *a) -+{ -+ check_larch_64(ctx); -+ gen_shift(ctx, OPC_LARCH_ROTR_D, a->rd, a->rk, a->rj); -+ return true; -+} -+ -+static bool trans_crc_w_b_w(DisasContext *ctx, arg_crc_w_b_w *a) -+{ -+ gen_crc32(ctx, a->rd, a->rj, a->rk, 1, 0); -+ return true; -+} -+ -+static bool trans_crc_w_h_w(DisasContext *ctx, arg_crc_w_h_w *a) -+{ -+ gen_crc32(ctx, a->rd, a->rj, a->rk, 2, 0); -+ return true; -+} -+ -+static bool trans_crc_w_w_w(DisasContext *ctx, arg_crc_w_w_w *a) -+{ -+ gen_crc32(ctx, a->rd, a->rj, a->rk, 4, 0); -+ return true; -+} -+ -+static bool trans_crc_w_d_w(DisasContext *ctx, arg_crc_w_d_w *a) -+{ -+ gen_crc32(ctx, a->rd, a->rj, a->rk, 8, 0); -+ return true; -+} -+ -+static bool trans_crcc_w_b_w(DisasContext *ctx, arg_crcc_w_b_w *a) -+{ -+ gen_crc32(ctx, a->rd, a->rj, a->rk, 1, 1); -+ return true; -+} -+ -+static bool trans_crcc_w_h_w(DisasContext *ctx, arg_crcc_w_h_w *a) -+{ -+ gen_crc32(ctx, a->rd, a->rj, a->rk, 2, 1); -+ return true; -+} -+ -+static bool trans_crcc_w_w_w(DisasContext *ctx, arg_crcc_w_w_w *a) -+{ -+ gen_crc32(ctx, a->rd, a->rj, a->rk, 4, 1); -+ return true; -+} -+ -+static bool trans_crcc_w_d_w(DisasContext *ctx, arg_crcc_w_d_w *a) -+{ -+ gen_crc32(ctx, a->rd, a->rj, a->rk, 8, 1); -+ return true; -+} -+ -+static bool trans_mul_w(DisasContext *ctx, arg_mul_w *a) -+{ -+ gen_r6_muldiv(ctx, OPC_LARCH_MUL_W, a->rd, a->rj, a->rk); -+ return true; -+} -+ -+static bool trans_mulh_w(DisasContext *ctx, arg_mulh_w *a) -+{ -+ gen_r6_muldiv(ctx, OPC_LARCH_MULH_W, a->rd, a->rj, a->rk); -+ return true; -+} -+ -+static bool trans_mulh_wu(DisasContext *ctx, arg_mulh_wu *a) -+{ -+ gen_r6_muldiv(ctx, OPC_LARCH_MULH_WU, a->rd, a->rj, a->rk); -+ return true; -+} -+ -+static bool trans_mul_d(DisasContext *ctx, arg_mul_d *a) -+{ -+ check_larch_64(ctx); -+ gen_r6_muldiv(ctx, OPC_LARCH_MUL_D, a->rd, a->rj, a->rk); -+ return true; -+} -+ -+static bool trans_mulh_d(DisasContext *ctx, arg_mulh_d *a) -+{ -+ check_larch_64(ctx); -+ gen_r6_muldiv(ctx, OPC_LARCH_MULH_D, a->rd, a->rj, a->rk); -+ return true; -+} -+ -+static bool trans_mulh_du(DisasContext *ctx, arg_mulh_du *a) -+{ -+ check_larch_64(ctx); -+ gen_r6_muldiv(ctx, OPC_LARCH_MULH_DU, a->rd, a->rj, a->rk); -+ return true; -+} -+ -+static bool trans_mulw_d_w(DisasContext *ctx, arg_mulw_d_w *a) -+{ -+ TCGv_i64 t0 = tcg_temp_new_i64(); -+ TCGv_i64 t1 = tcg_temp_new_i64(); -+ TCGv_i64 t2 = tcg_temp_new_i64(); -+ gen_load_gpr(t0, a->rj); -+ gen_load_gpr(t1, a->rk); -+ tcg_gen_ext32s_i64(t0, t0); -+ tcg_gen_ext32s_i64(t1, t1); -+ tcg_gen_mul_i64(t2, t0, t1); -+ gen_store_gpr(t2, a->rd); -+ tcg_temp_free_i64(t0); -+ tcg_temp_free_i64(t1); -+ tcg_temp_free_i64(t2); -+ return true; -+} -+ -+static bool trans_mulw_d_wu(DisasContext *ctx, arg_mulw_d_wu *a) -+{ -+ TCGv_i64 t0 = tcg_temp_new_i64(); -+ TCGv_i64 t1 = tcg_temp_new_i64(); -+ TCGv_i64 t2 = tcg_temp_new_i64(); -+ gen_load_gpr(t0, a->rj); -+ gen_load_gpr(t1, a->rk); -+ tcg_gen_ext32u_i64(t0, t0); -+ tcg_gen_ext32u_i64(t1, t1); -+ tcg_gen_mul_i64(t2, t0, t1); -+ gen_store_gpr(t2, a->rd); -+ tcg_temp_free_i64(t0); -+ tcg_temp_free_i64(t1); -+ tcg_temp_free_i64(t2); -+ return true; -+} -+ -+static bool trans_div_w(DisasContext *ctx, arg_div_w *a) -+{ -+ gen_r6_muldiv(ctx, OPC_LARCH_DIV_W, a->rd, a->rj, a->rk); -+ return true; -+} -+ -+static bool trans_mod_w(DisasContext *ctx, arg_mod_w *a) -+{ -+ gen_r6_muldiv(ctx, OPC_LARCH_MOD_W, a->rd, a->rj, a->rk); -+ return true; -+} -+ -+static bool trans_div_wu(DisasContext *ctx, arg_div_wu *a) -+{ -+ gen_r6_muldiv(ctx, OPC_LARCH_DIV_WU, a->rd, a->rj, a->rk); -+ return true; -+} -+ -+static bool trans_mod_wu(DisasContext *ctx, arg_mod_wu *a) -+{ -+ gen_r6_muldiv(ctx, OPC_LARCH_MOD_WU, a->rd, a->rj, a->rk); -+ return true; -+} -+ -+static bool trans_div_d(DisasContext *ctx, arg_div_d *a) -+{ -+ check_larch_64(ctx); -+ gen_r6_muldiv(ctx, OPC_LARCH_DIV_D, a->rd, a->rj, a->rk); -+ return true; -+} -+ -+static bool trans_mod_d(DisasContext *ctx, arg_mod_d *a) -+{ -+ check_larch_64(ctx); -+ gen_r6_muldiv(ctx, OPC_LARCH_MOD_D, a->rd, a->rj, a->rk); -+ return true; -+} -+ -+static bool trans_div_du(DisasContext *ctx, arg_div_du *a) -+{ -+ check_larch_64(ctx); -+ gen_r6_muldiv(ctx, OPC_LARCH_DIV_DU, a->rd, a->rj, a->rk); -+ return true; -+} -+ -+static bool trans_mod_du(DisasContext *ctx, arg_mod_du *a) -+{ -+ check_larch_64(ctx); -+ gen_r6_muldiv(ctx, OPC_LARCH_MOD_DU, a->rd, a->rj, a->rk); -+ return true; -+} -+ -+/* do not update CP0.BadVaddr */ -+static bool trans_asrtle_d(DisasContext *ctx, arg_asrtle_d * a) -+{ -+ TCGv t1 = tcg_temp_new(); -+ TCGv t2 = tcg_temp_new(); -+ gen_load_gpr(t1, a->rj); -+ gen_load_gpr(t2, a->rk); -+ gen_helper_asrtle_d(cpu_env, t1, t2); -+ tcg_temp_free(t1); -+ tcg_temp_free(t2); -+ return true; -+} -+ -+/* do not update CP0.BadVaddr */ -+static bool trans_asrtgt_d(DisasContext *ctx, arg_asrtgt_d * a) -+{ -+ TCGv t1 = tcg_temp_new(); -+ TCGv t2 = tcg_temp_new(); -+ gen_load_gpr(t1, a->rj); -+ gen_load_gpr(t2, a->rk); -+ gen_helper_asrtgt_d(cpu_env, t1, t2); -+ tcg_temp_free(t1); -+ tcg_temp_free(t2); -+ return true; -+} -+ -+#ifdef CONFIG_USER_ONLY -+static bool trans_gr2scr(DisasContext *ctx, arg_gr2scr *a) -+{ -+ return false; -+} -+ -+static bool trans_scr2gr(DisasContext *ctx, arg_scr2gr *a) -+{ -+ return false; -+} -+#else -+static bool trans_gr2scr(DisasContext *ctx, arg_gr2scr *a) -+{ -+ TCGv_i32 sd = tcg_const_i32(a->sd); -+ TCGv val = tcg_temp_new(); -+ check_lbt_enabled(ctx); -+ gen_load_gpr(val, a->rj); -+ gen_helper_store_scr(cpu_env, sd, val); -+ tcg_temp_free_i32(sd); -+ tcg_temp_free(val); -+ return true; -+} -+ -+static bool trans_scr2gr(DisasContext *ctx, arg_scr2gr *a) -+{ -+ if (a->rd == 0) { -+ /* Nop */ -+ return true; -+ } -+ -+ TCGv_i32 tsj = tcg_const_i32(a->sj); -+ check_lbt_enabled(ctx); -+ gen_helper_load_scr(cpu_gpr[a->rd], cpu_env, tsj); -+ tcg_temp_free_i32(tsj); -+ return true; -+} -+#endif -+ -+static bool trans_clo_w(DisasContext *ctx, arg_clo_w *a) -+{ -+ gen_cl(ctx, OPC_LARCH_CLO_W, a->rd, a->rj); -+ return true; -+} -+ -+static bool trans_clz_w(DisasContext *ctx, arg_clz_w *a) -+{ -+ gen_cl(ctx, OPC_LARCH_CLZ_W, a->rd, a->rj); -+ return true; -+} -+ -+static bool trans_cto_w(DisasContext *ctx, arg_cto_w *a) -+{ -+ TCGv t0 = tcg_temp_new(); -+ -+ gen_load_gpr(t0, a->rj); -+ gen_helper_cto_w(cpu_gpr[a->rd], cpu_env, t0); -+ -+ tcg_temp_free(t0); -+ return true; -+} -+ -+static bool trans_ctz_w(DisasContext *ctx, arg_ctz_w *a) -+{ -+ TCGv t0 = tcg_temp_new(); -+ -+ gen_load_gpr(t0, a->rj); -+ gen_helper_ctz_w(cpu_gpr[a->rd], cpu_env, t0); -+ -+ tcg_temp_free(t0); -+ return true; -+} -+ -+static bool trans_clo_d(DisasContext *ctx, arg_clo_d *a) -+{ -+ check_larch_64(ctx); -+ gen_cl(ctx, OPC_LARCH_CLO_D, a->rd, a->rj); -+ return true; -+} -+ -+static bool trans_clz_d(DisasContext *ctx, arg_clz_d *a) -+{ -+ check_larch_64(ctx); -+ gen_cl(ctx, OPC_LARCH_CLZ_D, a->rd, a->rj); -+ return true; -+} -+ -+static bool trans_cto_d(DisasContext *ctx, arg_cto_d *a) -+{ -+ TCGv t0 = tcg_temp_new(); -+ -+ gen_load_gpr(t0, a->rj); -+ gen_helper_cto_d(cpu_gpr[a->rd], cpu_env, t0); -+ -+ tcg_temp_free(t0); -+ return true; -+} -+ -+static bool trans_ctz_d(DisasContext *ctx, arg_ctz_d *a) -+{ -+ TCGv t0 = tcg_temp_new(); -+ -+ gen_load_gpr(t0, a->rj); -+ gen_helper_ctz_d(cpu_gpr[a->rd], cpu_env, t0); -+ -+ tcg_temp_free(t0); -+ return true; -+} -+ -+static bool trans_revb_2h(DisasContext *ctx, arg_revb_2h *a) -+{ -+ gen_bshfl(ctx, OPC_LARCH_REVB_2H, a->rj, a->rd); -+ return true; -+} -+ -+static bool trans_revb_4h(DisasContext *ctx, arg_revb_4h *a) -+{ -+ check_larch_64(ctx); -+ gen_bshfl(ctx, OPC_LARCH_REVB_4H, a->rj, a->rd); -+ return true; -+} -+ -+static bool trans_revb_2w(DisasContext *ctx, arg_revb_2w *a) -+{ -+ handle_rev32(ctx, a->rj, a->rd); -+ return true; -+} -+ -+static bool trans_revb_d(DisasContext *ctx, arg_revb_d *a) -+{ -+ handle_rev64(ctx, a->rj, a->rd); -+ return true; -+} -+ -+static bool trans_revh_2w(DisasContext *ctx, arg_revh_2w *a) -+{ -+ handle_rev16(ctx, a->rj, a->rd); -+ return true; -+} -+ -+static bool trans_revh_d(DisasContext *ctx, arg_revh_d *a) -+{ -+ check_larch_64(ctx); -+ gen_bshfl(ctx, OPC_LARCH_REVH_D, a->rj, a->rd); -+ return true; -+} -+ -+static bool trans_bitrev_4b(DisasContext *ctx, arg_bitrev_4b *a) -+{ -+ gen_bitswap(ctx, OPC_LARCH_BREV_4B, a->rd, a->rj); -+ return true; -+} -+ -+static bool trans_bitrev_8b(DisasContext *ctx, arg_bitrev_8b *a) -+{ -+ check_larch_64(ctx); -+ gen_bitswap(ctx, OPC_LARCH_BREV_8B, a->rd, a->rj); -+ return true; -+} -+ -+static bool trans_bitrev_w(DisasContext *ctx, arg_bitrev_w *a) -+{ -+ TCGv t0 = tcg_temp_new(); -+ gen_load_gpr(t0, a->rj); -+ gen_helper_bitrev_w(cpu_gpr[a->rd], cpu_env, t0); -+ tcg_temp_free(t0); -+ return true; -+} -+ -+static bool trans_bitrev_d(DisasContext *ctx, arg_bitrev_d *a) -+{ -+ TCGv t0 = tcg_temp_new(); -+ gen_load_gpr(t0, a->rj); -+ gen_helper_bitrev_d(cpu_gpr[a->rd], cpu_env, t0); -+ tcg_temp_free(t0); -+ return true; -+} -+ -+static bool trans_ext_w_h(DisasContext *ctx, arg_ext_w_h *a) -+{ -+ gen_bshfl(ctx, OPC_LARCH_EXT_WH, a->rj, a->rd); -+ return true; -+} -+ -+static bool trans_ext_w_b(DisasContext *ctx, arg_ext_w_b *a) -+{ -+ gen_bshfl(ctx, OPC_LARCH_EXT_WB, a->rj, a->rd); -+ return true; -+} -+ -+static bool trans_srli_w(DisasContext *ctx, arg_srli_w *a) -+{ -+ gen_shift_imm(ctx, OPC_LARCH_SRLI_W, a->rd, a->rj, a->ui5); -+ return true; -+} -+ -+static bool trans_srai_w(DisasContext *ctx, arg_srai_w *a) -+{ -+ gen_shift_imm(ctx, OPC_LARCH_SRAI_W, a->rd, a->rj, a->ui5); -+ return true; -+} -+ -+static bool trans_srai_d(DisasContext *ctx, arg_srai_d *a) -+{ -+ TCGv t0; -+ check_larch_64(ctx); -+ t0 = tcg_temp_new(); -+ gen_load_gpr(t0, a->rj); -+ tcg_gen_sari_tl(cpu_gpr[a->rd], t0, a->ui6); -+ tcg_temp_free(t0); -+ return true; -+} -+ -+static bool trans_rotri_w(DisasContext *ctx, arg_rotri_w *a) -+{ -+ gen_shift_imm(ctx, OPC_LARCH_ROTRI_W, a->rd, a->rj, a->ui5); -+ return true; -+} -+ -+static bool trans_rotri_d(DisasContext *ctx, arg_rotri_d *a) -+{ -+ TCGv t0; -+ check_larch_64(ctx); -+ t0 = tcg_temp_new(); -+ gen_load_gpr(t0, a->rj); -+ tcg_gen_rotri_tl(cpu_gpr[a->rd], t0, a->ui6); -+ tcg_temp_free(t0); -+ return true; -+} -+ -+static bool trans_fcmp_cond_s(DisasContext *ctx, arg_fcmp_cond_s *a) -+{ -+ check_cp1_enabled(ctx); -+ gen_fcmp_s(ctx, a->fcond, a->fk, a->fj, a->cd); -+ return true; -+} -+ -+static bool trans_fcmp_cond_d(DisasContext *ctx, arg_fcmp_cond_d *a) -+{ -+ check_cp1_enabled(ctx); -+ gen_fcmp_d(ctx, a->fcond, a->fk, a->fj, a->cd); -+ return true; -+} -+ -+static bool trans_fsel(DisasContext *ctx, arg_fsel *a) -+{ -+ TCGv_i64 fj = tcg_temp_new_i64(); -+ TCGv_i64 fk = tcg_temp_new_i64(); -+ TCGv_i64 fd = tcg_temp_new_i64(); -+ TCGv_i32 ca = tcg_const_i32(a->ca); -+ check_cp1_enabled(ctx); -+ gen_load_fpr64(ctx, fj, a->fj); -+ gen_load_fpr64(ctx, fk, a->fk); -+ gen_helper_fsel(fd, cpu_env, fj, fk, ca); -+ gen_store_fpr64(ctx, fd, a->fd); -+ tcg_temp_free_i64(fj); -+ tcg_temp_free_i64(fk); -+ tcg_temp_free_i64(fd); -+ tcg_temp_free_i32(ca); -+ return true; -+} -+ -+#include "cpu-csr.h" -+ -+#ifdef CONFIG_USER_ONLY -+ -+static bool trans_csrxchg(DisasContext *ctx, arg_csrxchg *a) -+{ -+ return false; -+} -+ -+#else -+ -+ -+#define GEN_CSRRQ_CASE(name) \ -+ do { \ -+ case LOONGARCH_CSR_ ## name: \ -+ gen_csr_rdq(ctx, cpu_gpr[rd], LOONGARCH_CSR_ ## name);\ -+ } while (0) -+ -+static bool trans_csrrd(DisasContext *ctx, unsigned rd, unsigned csr) -+{ -+ switch (csr) { -+ GEN_CSRRQ_CASE(CRMD); -+ break; -+ GEN_CSRRQ_CASE(PRMD); -+ break; -+ GEN_CSRRQ_CASE(EUEN); -+ break; -+ GEN_CSRRQ_CASE(MISC); -+ break; -+ GEN_CSRRQ_CASE(ECFG); -+ break; -+ GEN_CSRRQ_CASE(ESTAT); -+ break; -+ GEN_CSRRQ_CASE(ERA); -+ break; -+ GEN_CSRRQ_CASE(BADV); -+ break; -+ GEN_CSRRQ_CASE(BADI); -+ break; -+ GEN_CSRRQ_CASE(EEPN); -+ break; -+ GEN_CSRRQ_CASE(TLBIDX); -+ break; -+ GEN_CSRRQ_CASE(TLBEHI); -+ break; -+ GEN_CSRRQ_CASE(TLBELO0); -+ break; -+ GEN_CSRRQ_CASE(TLBELO1); -+ break; -+ GEN_CSRRQ_CASE(TLBWIRED); -+ break; -+ GEN_CSRRQ_CASE(GTLBC); -+ break; -+ GEN_CSRRQ_CASE(TRGP); -+ break; -+ GEN_CSRRQ_CASE(ASID); -+ break; -+ GEN_CSRRQ_CASE(PGDL); -+ break; -+ GEN_CSRRQ_CASE(PGDH); -+ break; -+ case LOONGARCH_CSR_PGD: -+ gen_helper_read_pgd(cpu_gpr[rd], cpu_env); -+ break; -+ GEN_CSRRQ_CASE(PWCTL0); -+ break; -+ GEN_CSRRQ_CASE(PWCTL1); -+ break; -+ GEN_CSRRQ_CASE(STLBPGSIZE); -+ break; -+ GEN_CSRRQ_CASE(RVACFG); -+ break; -+ GEN_CSRRQ_CASE(CPUID); -+ break; -+ GEN_CSRRQ_CASE(PRCFG1); -+ break; -+ GEN_CSRRQ_CASE(PRCFG2); -+ break; -+ GEN_CSRRQ_CASE(PRCFG3); -+ break; -+ GEN_CSRRQ_CASE(KS0); -+ break; -+ GEN_CSRRQ_CASE(KS1); -+ break; -+ GEN_CSRRQ_CASE(KS2); -+ break; -+ GEN_CSRRQ_CASE(KS3); -+ break; -+ GEN_CSRRQ_CASE(KS4); -+ break; -+ GEN_CSRRQ_CASE(KS5); -+ break; -+ GEN_CSRRQ_CASE(KS6); -+ break; -+ GEN_CSRRQ_CASE(KS7); -+ break; -+ GEN_CSRRQ_CASE(KS8); -+ break; -+ GEN_CSRRQ_CASE(TMID); -+ break; -+ GEN_CSRRQ_CASE(TCFG); -+ break; -+ GEN_CSRRQ_CASE(TVAL); -+ break; -+ GEN_CSRRQ_CASE(CNTC); -+ break; -+ GEN_CSRRQ_CASE(TINTCLR); -+ break; -+ GEN_CSRRQ_CASE(GSTAT); -+ break; -+ GEN_CSRRQ_CASE(GCFG); -+ break; -+ GEN_CSRRQ_CASE(GINTC); -+ break; -+ GEN_CSRRQ_CASE(GCNTC); -+ break; -+ GEN_CSRRQ_CASE(LLBCTL); -+ break; -+ GEN_CSRRQ_CASE(IMPCTL1); -+ break; -+ GEN_CSRRQ_CASE(IMPCTL2); -+ break; -+ GEN_CSRRQ_CASE(GNMI); -+ break; -+ GEN_CSRRQ_CASE(TLBRENT); -+ break; -+ GEN_CSRRQ_CASE(TLBRBADV); -+ break; -+ GEN_CSRRQ_CASE(TLBRERA); -+ break; -+ GEN_CSRRQ_CASE(TLBRSAVE); -+ break; -+ GEN_CSRRQ_CASE(TLBRELO0); -+ break; -+ GEN_CSRRQ_CASE(TLBRELO1); -+ break; -+ GEN_CSRRQ_CASE(TLBREHI); -+ break; -+ GEN_CSRRQ_CASE(TLBRPRMD); -+ break; -+ GEN_CSRRQ_CASE(ERRCTL); -+ break; -+ GEN_CSRRQ_CASE(ERRINFO); -+ break; -+ GEN_CSRRQ_CASE(ERRINFO1); -+ break; -+ GEN_CSRRQ_CASE(ERRENT); -+ break; -+ GEN_CSRRQ_CASE(ERRERA); -+ break; -+ GEN_CSRRQ_CASE(ERRSAVE); -+ break; -+ GEN_CSRRQ_CASE(CTAG); -+ break; -+ GEN_CSRRQ_CASE(DMWIN0); -+ break; -+ GEN_CSRRQ_CASE(DMWIN1); -+ break; -+ GEN_CSRRQ_CASE(DMWIN2); -+ break; -+ GEN_CSRRQ_CASE(DMWIN3); -+ break; -+ GEN_CSRRQ_CASE(PERFCTRL0); -+ break; -+ GEN_CSRRQ_CASE(PERFCNTR0); -+ break; -+ GEN_CSRRQ_CASE(PERFCTRL1); -+ break; -+ GEN_CSRRQ_CASE(PERFCNTR1); -+ break; -+ GEN_CSRRQ_CASE(PERFCTRL2); -+ break; -+ GEN_CSRRQ_CASE(PERFCNTR2); -+ break; -+ GEN_CSRRQ_CASE(PERFCTRL3); -+ break; -+ GEN_CSRRQ_CASE(PERFCNTR3); -+ break; -+ /* debug */ -+ GEN_CSRRQ_CASE(MWPC); -+ break; -+ GEN_CSRRQ_CASE(MWPS); -+ break; -+ GEN_CSRRQ_CASE(DB0ADDR); -+ break; -+ GEN_CSRRQ_CASE(DB0MASK); -+ break; -+ GEN_CSRRQ_CASE(DB0CTL); -+ break; -+ GEN_CSRRQ_CASE(DB0ASID); -+ break; -+ GEN_CSRRQ_CASE(DB1ADDR); -+ break; -+ GEN_CSRRQ_CASE(DB1MASK); -+ break; -+ GEN_CSRRQ_CASE(DB1CTL); -+ break; -+ GEN_CSRRQ_CASE(DB1ASID); -+ break; -+ GEN_CSRRQ_CASE(DB2ADDR); -+ break; -+ GEN_CSRRQ_CASE(DB2MASK); -+ break; -+ GEN_CSRRQ_CASE(DB2CTL); -+ break; -+ GEN_CSRRQ_CASE(DB2ASID); -+ break; -+ GEN_CSRRQ_CASE(DB3ADDR); -+ break; -+ GEN_CSRRQ_CASE(DB3MASK); -+ break; -+ GEN_CSRRQ_CASE(DB3CTL); -+ break; -+ GEN_CSRRQ_CASE(DB3ASID); -+ break; -+ GEN_CSRRQ_CASE(FWPC); -+ break; -+ GEN_CSRRQ_CASE(FWPS); -+ break; -+ GEN_CSRRQ_CASE(IB0ADDR); -+ break; -+ GEN_CSRRQ_CASE(IB0MASK); -+ break; -+ GEN_CSRRQ_CASE(IB0CTL); -+ break; -+ GEN_CSRRQ_CASE(IB0ASID); -+ break; -+ GEN_CSRRQ_CASE(IB1ADDR); -+ break; -+ GEN_CSRRQ_CASE(IB1MASK); -+ break; -+ GEN_CSRRQ_CASE(IB1CTL); -+ break; -+ GEN_CSRRQ_CASE(IB1ASID); -+ break; -+ GEN_CSRRQ_CASE(IB2ADDR); -+ break; -+ GEN_CSRRQ_CASE(IB2MASK); -+ break; -+ GEN_CSRRQ_CASE(IB2CTL); -+ break; -+ GEN_CSRRQ_CASE(IB2ASID); -+ break; -+ GEN_CSRRQ_CASE(IB3ADDR); -+ break; -+ GEN_CSRRQ_CASE(IB3MASK); -+ break; -+ GEN_CSRRQ_CASE(IB3CTL); -+ break; -+ GEN_CSRRQ_CASE(IB3ASID); -+ break; -+ GEN_CSRRQ_CASE(IB4ADDR); -+ break; -+ GEN_CSRRQ_CASE(IB4MASK); -+ break; -+ GEN_CSRRQ_CASE(IB4CTL); -+ break; -+ GEN_CSRRQ_CASE(IB4ASID); -+ break; -+ GEN_CSRRQ_CASE(IB5ADDR); -+ break; -+ GEN_CSRRQ_CASE(IB5MASK); -+ break; -+ GEN_CSRRQ_CASE(IB5CTL); -+ break; -+ GEN_CSRRQ_CASE(IB5ASID); -+ break; -+ GEN_CSRRQ_CASE(IB6ADDR); -+ break; -+ GEN_CSRRQ_CASE(IB6MASK); -+ break; -+ GEN_CSRRQ_CASE(IB6CTL); -+ break; -+ GEN_CSRRQ_CASE(IB6ASID); -+ break; -+ GEN_CSRRQ_CASE(IB7ADDR); -+ break; -+ GEN_CSRRQ_CASE(IB7MASK); -+ break; -+ GEN_CSRRQ_CASE(IB7CTL); -+ break; -+ GEN_CSRRQ_CASE(IB7ASID); -+ break; -+ GEN_CSRRQ_CASE(DEBUG); -+ break; -+ GEN_CSRRQ_CASE(DERA); -+ break; -+ GEN_CSRRQ_CASE(DESAVE); -+ break; -+ default: -+ return false; -+ } -+ -+ #undef GEN_CSRRQ_CASE -+ -+ return true; -+} -+ -+#define GEN_CSRWQ_CASE(name) \ -+do { \ -+ case LOONGARCH_CSR_ ## name: \ -+ gen_csr_wrq(ctx, cpu_gpr[rd], LOONGARCH_CSR_ ## name); \ -+} while (0) -+ -+static bool trans_csrwr(DisasContext *ctx, unsigned rd, unsigned csr) -+{ -+ -+ switch (csr) { -+ case LOONGARCH_CSR_CRMD: -+ save_cpu_state(ctx, 1); -+ gen_csr_wrq(ctx, cpu_gpr[rd], LOONGARCH_CSR_CRMD); -+ gen_save_pc(ctx->base.pc_next + 4); -+ ctx->base.is_jmp = DISAS_EXIT; -+ break; -+ GEN_CSRWQ_CASE(PRMD); -+ break; -+ case LOONGARCH_CSR_EUEN: -+ gen_csr_wrq(ctx, cpu_gpr[rd], LOONGARCH_CSR_EUEN); -+ /* Stop translation */ -+ gen_save_pc(ctx->base.pc_next + 4); -+ ctx->base.is_jmp = DISAS_EXIT; -+ break; -+ GEN_CSRWQ_CASE(MISC); -+ break; -+ GEN_CSRWQ_CASE(ECFG); -+ break; -+ GEN_CSRWQ_CASE(ESTAT); -+ break; -+ GEN_CSRWQ_CASE(ERA); -+ break; -+ GEN_CSRWQ_CASE(BADV); -+ break; -+ GEN_CSRWQ_CASE(BADI); -+ break; -+ GEN_CSRWQ_CASE(EEPN); -+ break; -+ GEN_CSRWQ_CASE(TLBIDX); -+ break; -+ GEN_CSRWQ_CASE(TLBEHI); -+ break; -+ GEN_CSRWQ_CASE(TLBELO0); -+ break; -+ GEN_CSRWQ_CASE(TLBELO1); -+ break; -+ GEN_CSRWQ_CASE(TLBWIRED); -+ break; -+ GEN_CSRWQ_CASE(GTLBC); -+ break; -+ GEN_CSRWQ_CASE(TRGP); -+ break; -+ GEN_CSRWQ_CASE(ASID); -+ break; -+ GEN_CSRWQ_CASE(PGDL); -+ break; -+ GEN_CSRWQ_CASE(PGDH); -+ break; -+ GEN_CSRWQ_CASE(PGD); -+ break; -+ GEN_CSRWQ_CASE(PWCTL0); -+ break; -+ GEN_CSRWQ_CASE(PWCTL1); -+ break; -+ GEN_CSRWQ_CASE(STLBPGSIZE); -+ break; -+ GEN_CSRWQ_CASE(RVACFG); -+ break; -+ GEN_CSRWQ_CASE(CPUID); -+ break; -+ GEN_CSRWQ_CASE(PRCFG1); -+ break; -+ GEN_CSRWQ_CASE(PRCFG2); -+ break; -+ GEN_CSRWQ_CASE(PRCFG3); -+ break; -+ GEN_CSRWQ_CASE(KS0); -+ break; -+ GEN_CSRWQ_CASE(KS1); -+ break; -+ GEN_CSRWQ_CASE(KS2); -+ break; -+ GEN_CSRWQ_CASE(KS3); -+ break; -+ GEN_CSRWQ_CASE(KS4); -+ break; -+ GEN_CSRWQ_CASE(KS5); -+ break; -+ GEN_CSRWQ_CASE(KS6); -+ break; -+ GEN_CSRWQ_CASE(KS7); -+ break; -+ GEN_CSRWQ_CASE(KS8); -+ break; -+ GEN_CSRWQ_CASE(TMID); -+ break; -+ GEN_CSRWQ_CASE(TCFG); -+ break; -+ GEN_CSRWQ_CASE(TVAL); -+ break; -+ GEN_CSRWQ_CASE(CNTC); -+ break; -+ GEN_CSRWQ_CASE(TINTCLR); -+ break; -+ GEN_CSRWQ_CASE(GSTAT); -+ break; -+ GEN_CSRWQ_CASE(GCFG); -+ break; -+ GEN_CSRWQ_CASE(GINTC); -+ break; -+ GEN_CSRWQ_CASE(GCNTC); -+ break; -+ GEN_CSRWQ_CASE(LLBCTL); -+ break; -+ GEN_CSRWQ_CASE(IMPCTL1); -+ break; -+ GEN_CSRWQ_CASE(IMPCTL2); -+ break; -+ GEN_CSRWQ_CASE(GNMI); -+ break; -+ GEN_CSRWQ_CASE(TLBRENT); -+ break; -+ GEN_CSRWQ_CASE(TLBRBADV); -+ break; -+ GEN_CSRWQ_CASE(TLBRERA); -+ break; -+ GEN_CSRWQ_CASE(TLBRSAVE); -+ break; -+ GEN_CSRWQ_CASE(TLBRELO0); -+ break; -+ GEN_CSRWQ_CASE(TLBRELO1); -+ break; -+ GEN_CSRWQ_CASE(TLBREHI); -+ break; -+ GEN_CSRWQ_CASE(TLBRPRMD); -+ break; -+ GEN_CSRWQ_CASE(ERRCTL); -+ break; -+ GEN_CSRWQ_CASE(ERRINFO); -+ break; -+ GEN_CSRWQ_CASE(ERRINFO1); -+ break; -+ GEN_CSRWQ_CASE(ERRENT); -+ break; -+ GEN_CSRWQ_CASE(ERRERA); -+ break; -+ GEN_CSRWQ_CASE(ERRSAVE); -+ break; -+ GEN_CSRWQ_CASE(CTAG); -+ break; -+ GEN_CSRWQ_CASE(DMWIN0); -+ break; -+ GEN_CSRWQ_CASE(DMWIN1); -+ break; -+ GEN_CSRWQ_CASE(DMWIN2); -+ break; -+ GEN_CSRWQ_CASE(DMWIN3); -+ break; -+ GEN_CSRWQ_CASE(PERFCTRL0); -+ break; -+ GEN_CSRWQ_CASE(PERFCNTR0); -+ break; -+ GEN_CSRWQ_CASE(PERFCTRL1); -+ break; -+ GEN_CSRWQ_CASE(PERFCNTR1); -+ break; -+ GEN_CSRWQ_CASE(PERFCTRL2); -+ break; -+ GEN_CSRWQ_CASE(PERFCNTR2); -+ break; -+ GEN_CSRWQ_CASE(PERFCTRL3); -+ break; -+ GEN_CSRWQ_CASE(PERFCNTR3); -+ break; -+ /* debug */ -+ GEN_CSRWQ_CASE(MWPC); -+ break; -+ GEN_CSRWQ_CASE(MWPS); -+ break; -+ GEN_CSRWQ_CASE(DB0ADDR); -+ break; -+ GEN_CSRWQ_CASE(DB0MASK); -+ break; -+ GEN_CSRWQ_CASE(DB0CTL); -+ break; -+ GEN_CSRWQ_CASE(DB0ASID); -+ break; -+ GEN_CSRWQ_CASE(DB1ADDR); -+ break; -+ GEN_CSRWQ_CASE(DB1MASK); -+ break; -+ GEN_CSRWQ_CASE(DB1CTL); -+ break; -+ GEN_CSRWQ_CASE(DB1ASID); -+ break; -+ GEN_CSRWQ_CASE(DB2ADDR); -+ break; -+ GEN_CSRWQ_CASE(DB2MASK); -+ break; -+ GEN_CSRWQ_CASE(DB2CTL); -+ break; -+ GEN_CSRWQ_CASE(DB2ASID); -+ break; -+ GEN_CSRWQ_CASE(DB3ADDR); -+ break; -+ GEN_CSRWQ_CASE(DB3MASK); -+ break; -+ GEN_CSRWQ_CASE(DB3CTL); -+ break; -+ GEN_CSRWQ_CASE(DB3ASID); -+ break; -+ GEN_CSRWQ_CASE(FWPC); -+ break; -+ GEN_CSRWQ_CASE(FWPS); -+ break; -+ GEN_CSRWQ_CASE(IB0ADDR); -+ break; -+ GEN_CSRWQ_CASE(IB0MASK); -+ break; -+ GEN_CSRWQ_CASE(IB0CTL); -+ break; -+ GEN_CSRWQ_CASE(IB0ASID); -+ break; -+ GEN_CSRWQ_CASE(IB1ADDR); -+ break; -+ GEN_CSRWQ_CASE(IB1MASK); -+ break; -+ GEN_CSRWQ_CASE(IB1CTL); -+ break; -+ GEN_CSRWQ_CASE(IB1ASID); -+ break; -+ GEN_CSRWQ_CASE(IB2ADDR); -+ break; -+ GEN_CSRWQ_CASE(IB2MASK); -+ break; -+ GEN_CSRWQ_CASE(IB2CTL); -+ break; -+ GEN_CSRWQ_CASE(IB2ASID); -+ break; -+ GEN_CSRWQ_CASE(IB3ADDR); -+ break; -+ GEN_CSRWQ_CASE(IB3MASK); -+ break; -+ GEN_CSRWQ_CASE(IB3CTL); -+ break; -+ GEN_CSRWQ_CASE(IB3ASID); -+ break; -+ GEN_CSRWQ_CASE(IB4ADDR); -+ break; -+ GEN_CSRWQ_CASE(IB4MASK); -+ break; -+ GEN_CSRWQ_CASE(IB4CTL); -+ break; -+ GEN_CSRWQ_CASE(IB4ASID); -+ break; -+ GEN_CSRWQ_CASE(IB5ADDR); -+ break; -+ GEN_CSRWQ_CASE(IB5MASK); -+ break; -+ GEN_CSRWQ_CASE(IB5CTL); -+ break; -+ GEN_CSRWQ_CASE(IB5ASID); -+ break; -+ GEN_CSRWQ_CASE(IB6ADDR); -+ break; -+ GEN_CSRWQ_CASE(IB6MASK); -+ break; -+ GEN_CSRWQ_CASE(IB6CTL); -+ break; -+ GEN_CSRWQ_CASE(IB6ASID); -+ break; -+ GEN_CSRWQ_CASE(IB7ADDR); -+ break; -+ GEN_CSRWQ_CASE(IB7MASK); -+ break; -+ GEN_CSRWQ_CASE(IB7CTL); -+ break; -+ GEN_CSRWQ_CASE(IB7ASID); -+ break; -+ GEN_CSRWQ_CASE(DEBUG); -+ break; -+ GEN_CSRWQ_CASE(DERA); -+ break; -+ GEN_CSRWQ_CASE(DESAVE); -+ break; -+ default: -+ return false; -+ } -+ -+ #undef GEN_CSRWQ_CASE -+ -+ return true; -+} -+ -+#define GEN_CSRXQ_CASE(name) \ -+do { \ -+ case LOONGARCH_CSR_ ## name: \ -+ if (rd == 0) { \ -+ gen_csr_xchgq(ctx, zero, cpu_gpr[rj], \ -+ LOONGARCH_CSR_ ## name); \ -+ } else { \ -+ gen_csr_xchgq(ctx, cpu_gpr[rd], cpu_gpr[rj], \ -+ LOONGARCH_CSR_ ## name); \ -+ } \ -+} while (0) -+ -+static bool trans_csrxchg(DisasContext *ctx, arg_csrxchg *a) -+{ -+ unsigned rd, rj, csr; -+ TCGv zero = tcg_const_tl(0); -+ rd = a->rd; -+ rj = a->rj; -+ csr = a->csr; -+ -+ if (rj == 0) { -+ return trans_csrrd(ctx, rd, csr); -+ } else if (rj == 1) { -+ return trans_csrwr(ctx, rd, csr); -+ } -+ -+ switch (csr) { -+ case LOONGARCH_CSR_CRMD: -+ save_cpu_state(ctx, 1); -+ if (rd == 0) { -+ gen_csr_xchgq(ctx, zero, cpu_gpr[rj], LOONGARCH_CSR_CRMD); -+ } else { -+ gen_csr_xchgq(ctx, cpu_gpr[rd], cpu_gpr[rj], LOONGARCH_CSR_CRMD); -+ } -+ gen_save_pc(ctx->base.pc_next + 4); -+ ctx->base.is_jmp = DISAS_EXIT; -+ break; -+ -+ GEN_CSRXQ_CASE(PRMD); -+ break; -+ case LOONGARCH_CSR_EUEN: -+ if (rd == 0) { -+ gen_csr_xchgq(ctx, zero, cpu_gpr[rj], LOONGARCH_CSR_EUEN); -+ } else { -+ gen_csr_xchgq(ctx, cpu_gpr[rd], cpu_gpr[rj], LOONGARCH_CSR_EUEN); -+ } -+ /* Stop translation */ -+ gen_save_pc(ctx->base.pc_next + 4); -+ ctx->base.is_jmp = DISAS_EXIT; -+ break; -+ GEN_CSRXQ_CASE(MISC); -+ break; -+ GEN_CSRXQ_CASE(ECFG); -+ break; -+ GEN_CSRXQ_CASE(ESTAT); -+ break; -+ GEN_CSRXQ_CASE(ERA); -+ break; -+ GEN_CSRXQ_CASE(BADV); -+ break; -+ GEN_CSRXQ_CASE(BADI); -+ break; -+ GEN_CSRXQ_CASE(EEPN); -+ break; -+ GEN_CSRXQ_CASE(TLBIDX); -+ break; -+ GEN_CSRXQ_CASE(TLBEHI); -+ break; -+ GEN_CSRXQ_CASE(TLBELO0); -+ break; -+ GEN_CSRXQ_CASE(TLBELO1); -+ break; -+ GEN_CSRXQ_CASE(TLBWIRED); -+ break; -+ GEN_CSRXQ_CASE(GTLBC); -+ break; -+ GEN_CSRXQ_CASE(TRGP); -+ break; -+ GEN_CSRXQ_CASE(ASID); -+ break; -+ GEN_CSRXQ_CASE(PGDL); -+ break; -+ GEN_CSRXQ_CASE(PGDH); -+ break; -+ GEN_CSRXQ_CASE(PGD); -+ break; -+ GEN_CSRXQ_CASE(PWCTL0); -+ break; -+ GEN_CSRXQ_CASE(PWCTL1); -+ break; -+ GEN_CSRXQ_CASE(STLBPGSIZE); -+ break; -+ GEN_CSRXQ_CASE(RVACFG); -+ break; -+ GEN_CSRXQ_CASE(CPUID); -+ break; -+ GEN_CSRXQ_CASE(PRCFG1); -+ break; -+ GEN_CSRXQ_CASE(PRCFG2); -+ break; -+ GEN_CSRXQ_CASE(PRCFG3); -+ break; -+ GEN_CSRXQ_CASE(KS0); -+ break; -+ GEN_CSRXQ_CASE(KS1); -+ break; -+ GEN_CSRXQ_CASE(KS2); -+ break; -+ GEN_CSRXQ_CASE(KS3); -+ break; -+ GEN_CSRXQ_CASE(KS4); -+ break; -+ GEN_CSRXQ_CASE(KS5); -+ break; -+ GEN_CSRXQ_CASE(KS6); -+ break; -+ GEN_CSRXQ_CASE(KS7); -+ break; -+ GEN_CSRXQ_CASE(KS8); -+ break; -+ GEN_CSRXQ_CASE(TMID); -+ break; -+ GEN_CSRXQ_CASE(TCFG); -+ break; -+ GEN_CSRXQ_CASE(TVAL); -+ break; -+ GEN_CSRXQ_CASE(CNTC); -+ break; -+ GEN_CSRXQ_CASE(TINTCLR); -+ break; -+ GEN_CSRXQ_CASE(GSTAT); -+ break; -+ GEN_CSRXQ_CASE(GCFG); -+ break; -+ GEN_CSRXQ_CASE(GINTC); -+ break; -+ GEN_CSRXQ_CASE(GCNTC); -+ break; -+ GEN_CSRXQ_CASE(LLBCTL); -+ break; -+ GEN_CSRXQ_CASE(IMPCTL1); -+ break; -+ GEN_CSRXQ_CASE(IMPCTL2); -+ break; -+ GEN_CSRXQ_CASE(GNMI); -+ break; -+ GEN_CSRXQ_CASE(TLBRENT); -+ break; -+ GEN_CSRXQ_CASE(TLBRBADV); -+ break; -+ GEN_CSRXQ_CASE(TLBRERA); -+ break; -+ GEN_CSRXQ_CASE(TLBRSAVE); -+ break; -+ GEN_CSRXQ_CASE(TLBRELO0); -+ break; -+ GEN_CSRXQ_CASE(TLBRELO1); -+ break; -+ GEN_CSRXQ_CASE(TLBREHI); -+ break; -+ GEN_CSRXQ_CASE(TLBRPRMD); -+ break; -+ GEN_CSRXQ_CASE(ERRCTL); -+ break; -+ GEN_CSRXQ_CASE(ERRINFO); -+ break; -+ GEN_CSRXQ_CASE(ERRINFO1); -+ break; -+ GEN_CSRXQ_CASE(ERRENT); -+ break; -+ GEN_CSRXQ_CASE(ERRERA); -+ break; -+ GEN_CSRXQ_CASE(ERRSAVE); -+ break; -+ GEN_CSRXQ_CASE(CTAG); -+ break; -+ GEN_CSRXQ_CASE(DMWIN0); -+ break; -+ GEN_CSRXQ_CASE(DMWIN1); -+ break; -+ GEN_CSRXQ_CASE(DMWIN2); -+ break; -+ GEN_CSRXQ_CASE(DMWIN3); -+ break; -+ GEN_CSRXQ_CASE(PERFCTRL0); -+ break; -+ GEN_CSRXQ_CASE(PERFCNTR0); -+ break; -+ GEN_CSRXQ_CASE(PERFCTRL1); -+ break; -+ GEN_CSRXQ_CASE(PERFCNTR1); -+ break; -+ GEN_CSRXQ_CASE(PERFCTRL2); -+ break; -+ GEN_CSRXQ_CASE(PERFCNTR2); -+ break; -+ GEN_CSRXQ_CASE(PERFCTRL3); -+ break; -+ GEN_CSRXQ_CASE(PERFCNTR3); -+ break; -+ /* debug */ -+ GEN_CSRXQ_CASE(MWPC); -+ break; -+ GEN_CSRXQ_CASE(MWPS); -+ break; -+ GEN_CSRXQ_CASE(DB0ADDR); -+ break; -+ GEN_CSRXQ_CASE(DB0MASK); -+ break; -+ GEN_CSRXQ_CASE(DB0CTL); -+ break; -+ GEN_CSRXQ_CASE(DB0ASID); -+ break; -+ GEN_CSRXQ_CASE(DB1ADDR); -+ break; -+ GEN_CSRXQ_CASE(DB1MASK); -+ break; -+ GEN_CSRXQ_CASE(DB1CTL); -+ break; -+ GEN_CSRXQ_CASE(DB1ASID); -+ break; -+ GEN_CSRXQ_CASE(DB2ADDR); -+ break; -+ GEN_CSRXQ_CASE(DB2MASK); -+ break; -+ GEN_CSRXQ_CASE(DB2CTL); -+ break; -+ GEN_CSRXQ_CASE(DB2ASID); -+ break; -+ GEN_CSRXQ_CASE(DB3ADDR); -+ break; -+ GEN_CSRXQ_CASE(DB3MASK); -+ break; -+ GEN_CSRXQ_CASE(DB3CTL); -+ break; -+ GEN_CSRXQ_CASE(DB3ASID); -+ break; -+ GEN_CSRXQ_CASE(FWPC); -+ break; -+ GEN_CSRXQ_CASE(FWPS); -+ break; -+ GEN_CSRXQ_CASE(IB0ADDR); -+ break; -+ GEN_CSRXQ_CASE(IB0MASK); -+ break; -+ GEN_CSRXQ_CASE(IB0CTL); -+ break; -+ GEN_CSRXQ_CASE(IB0ASID); -+ break; -+ GEN_CSRXQ_CASE(IB1ADDR); -+ break; -+ GEN_CSRXQ_CASE(IB1MASK); -+ break; -+ GEN_CSRXQ_CASE(IB1CTL); -+ break; -+ GEN_CSRXQ_CASE(IB1ASID); -+ break; -+ GEN_CSRXQ_CASE(IB2ADDR); -+ break; -+ GEN_CSRXQ_CASE(IB2MASK); -+ break; -+ GEN_CSRXQ_CASE(IB2CTL); -+ break; -+ GEN_CSRXQ_CASE(IB2ASID); -+ break; -+ GEN_CSRXQ_CASE(IB3ADDR); -+ break; -+ GEN_CSRXQ_CASE(IB3MASK); -+ break; -+ GEN_CSRXQ_CASE(IB3CTL); -+ break; -+ GEN_CSRXQ_CASE(IB3ASID); -+ break; -+ GEN_CSRXQ_CASE(IB4ADDR); -+ break; -+ GEN_CSRXQ_CASE(IB4MASK); -+ break; -+ GEN_CSRXQ_CASE(IB4CTL); -+ break; -+ GEN_CSRXQ_CASE(IB4ASID); -+ break; -+ GEN_CSRXQ_CASE(IB5ADDR); -+ break; -+ GEN_CSRXQ_CASE(IB5MASK); -+ break; -+ GEN_CSRXQ_CASE(IB5CTL); -+ break; -+ GEN_CSRXQ_CASE(IB5ASID); -+ break; -+ GEN_CSRXQ_CASE(IB6ADDR); -+ break; -+ GEN_CSRXQ_CASE(IB6MASK); -+ break; -+ GEN_CSRXQ_CASE(IB6CTL); -+ break; -+ GEN_CSRXQ_CASE(IB6ASID); -+ break; -+ GEN_CSRXQ_CASE(IB7ADDR); -+ break; -+ GEN_CSRXQ_CASE(IB7MASK); -+ break; -+ GEN_CSRXQ_CASE(IB7CTL); -+ break; -+ GEN_CSRXQ_CASE(IB7ASID); -+ break; -+ GEN_CSRXQ_CASE(DEBUG); -+ break; -+ GEN_CSRXQ_CASE(DERA); -+ break; -+ GEN_CSRXQ_CASE(DESAVE); -+ break; -+ default: -+ return false; -+ } -+ -+ #undef GEN_CSRXQ_CASE -+ tcg_temp_free(zero); -+ return true; -+} -+ -+#endif -+ -+static bool trans_cacop(DisasContext *ctx, arg_cacop *a) -+{ -+ /* Treat as NOP. */ -+ return true; -+} -+ -+#ifdef CONFIG_USER_ONLY -+ -+static bool trans_ldpte(DisasContext *ctx, arg_ldpte *a) -+{ -+ return false; -+} -+ -+static bool trans_lddir(DisasContext *ctx, arg_lddir *a) -+{ -+ return false; -+} -+ -+static bool trans_iocsrrd_b(DisasContext *ctx, arg_iocsrrd_b *a) -+{ -+ return false; -+} -+ -+static bool trans_iocsrrd_h(DisasContext *ctx, arg_iocsrrd_h *a) -+{ -+ return false; -+} -+ -+static bool trans_iocsrrd_w(DisasContext *ctx, arg_iocsrrd_w *a) -+{ -+ return false; -+} -+ -+static bool trans_iocsrrd_d(DisasContext *ctx, arg_iocsrrd_d *a) -+{ -+ return false; -+} -+ -+static bool trans_iocsrwr_b(DisasContext *ctx, arg_iocsrwr_b *a) -+{ -+ return false; -+} -+ -+static bool trans_iocsrwr_h(DisasContext *ctx, arg_iocsrwr_h *a) -+{ -+ return false; -+} -+ -+static bool trans_iocsrwr_w(DisasContext *ctx, arg_iocsrwr_w *a) -+{ -+ return false; -+} -+ -+static bool trans_iocsrwr_d(DisasContext *ctx, arg_iocsrwr_d *a) -+{ -+ return false; -+} -+#else -+ -+static bool trans_ldpte(DisasContext *ctx, arg_ldpte *a) -+{ -+ TCGv t0, t1; -+ TCGv_i32 t2; -+ t0 = tcg_const_tl(a->rj); -+ t1 = tcg_const_tl(a->seq); -+ t2 = tcg_const_i32(ctx->mem_idx); -+ gen_helper_ldpte(cpu_env, t0, t1, t2); -+ -+ return true; -+} -+ -+static bool trans_lddir(DisasContext *ctx, arg_lddir *a) -+{ -+ TCGv t0, t1, t2; -+ TCGv_i32 t3; -+ t0 = tcg_const_tl(a->rj); -+ t1 = tcg_const_tl(a->rd); -+ t2 = tcg_const_tl(a->level); -+ t3 = tcg_const_i32(ctx->mem_idx); -+ gen_helper_lddir(cpu_env, t0, t1, t2, t3); -+ -+ return true; -+} -+ -+static bool trans_iocsrrd_b(DisasContext *ctx, arg_iocsrrd_b *a) -+{ -+ return false; -+} -+ -+static bool trans_iocsrrd_h(DisasContext *ctx, arg_iocsrrd_h *a) -+{ -+ return false; -+} -+ -+static bool trans_iocsrrd_w(DisasContext *ctx, arg_iocsrrd_w *a) -+{ -+ TCGv_i32 iocsr_op = tcg_const_i32(OPC_LARCH_LD_W); -+ TCGv t0, t1; -+ t0 = tcg_const_tl(a->rj); -+ t1 = tcg_const_tl(a->rd); -+ gen_helper_iocsr(cpu_env, t0, t1, iocsr_op); -+ return true; -+} -+ -+static bool trans_iocsrrd_d(DisasContext *ctx, arg_iocsrrd_d *a) -+{ -+ TCGv_i32 iocsr_op = tcg_const_i32(OPC_LARCH_LD_D); -+ TCGv t0, t1; -+ t0 = tcg_const_tl(a->rj); -+ t1 = tcg_const_tl(a->rd); -+ gen_helper_iocsr(cpu_env, t0, t1, iocsr_op); -+ return true; -+} -+ -+static bool trans_iocsrwr_b(DisasContext *ctx, arg_iocsrwr_b *a) -+{ -+ TCGv_i32 iocsr_op = tcg_const_i32(OPC_LARCH_ST_B); -+ TCGv t0, t1; -+ t0 = tcg_const_tl(a->rj); -+ t1 = tcg_const_tl(a->rd); -+ gen_helper_iocsr(cpu_env, t0, t1, iocsr_op); -+ return true; -+} -+ -+static bool trans_iocsrwr_h(DisasContext *ctx, arg_iocsrwr_h *a) -+{ -+ return false; -+} -+ -+static bool trans_iocsrwr_w(DisasContext *ctx, arg_iocsrwr_w *a) -+{ -+ TCGv_i32 iocsr_op = tcg_const_i32(OPC_LARCH_ST_W); -+ TCGv t0, t1; -+ t0 = tcg_const_tl(a->rj); -+ t1 = tcg_const_tl(a->rd); -+ gen_helper_iocsr(cpu_env, t0, t1, iocsr_op); -+ return true; -+} -+ -+static bool trans_iocsrwr_d(DisasContext *ctx, arg_iocsrwr_d *a) -+{ -+ TCGv_i32 iocsr_op = tcg_const_i32(OPC_LARCH_ST_D); -+ TCGv t0, t1; -+ t0 = tcg_const_tl(a->rj); -+ t1 = tcg_const_tl(a->rd); -+ gen_helper_iocsr(cpu_env, t0, t1, iocsr_op); -+ return true; -+} -+#endif /* !CONFIG_USER_ONLY */ -+ -+ -+#ifdef CONFIG_USER_ONLY -+ -+#define GEN_FALSE_TRANS(name) \ -+static bool trans_##name(DisasContext *ctx, arg_##name * a) \ -+{ \ -+ return false; \ -+} -+ -+GEN_FALSE_TRANS(tlbclr) -+GEN_FALSE_TRANS(invtlb) -+GEN_FALSE_TRANS(tlbflush) -+GEN_FALSE_TRANS(tlbsrch) -+GEN_FALSE_TRANS(tlbrd) -+GEN_FALSE_TRANS(tlbwr) -+GEN_FALSE_TRANS(tlbfill) -+GEN_FALSE_TRANS(ertn) -+ -+#else -+ -+static bool trans_tlbclr(DisasContext *ctx, arg_tlbclr *a) -+{ -+ gen_helper_tlbclr(cpu_env); -+ return true; -+} -+ -+static bool trans_tlbflush(DisasContext *ctx, arg_tlbflush *a) -+{ -+ gen_helper_tlbflush(cpu_env); -+ return true; -+} -+ -+static bool trans_invtlb(DisasContext *ctx, arg_invtlb *a) -+{ -+ TCGv addr = tcg_temp_new(); -+ TCGv info = tcg_temp_new(); -+ TCGv op = tcg_const_tl(a->invop); -+ -+ gen_load_gpr(addr, a->addr); -+ gen_load_gpr(info, a->info); -+ gen_helper_invtlb(cpu_env, addr, info, op); -+ -+ tcg_temp_free(addr); -+ tcg_temp_free(info); -+ tcg_temp_free(op); -+ return true; -+} -+ -+static bool trans_tlbsrch(DisasContext *ctx, arg_tlbsrch *a) -+{ -+ gen_helper_tlbsrch(cpu_env); -+ return true; -+} -+ -+static bool trans_tlbrd(DisasContext *ctx, arg_tlbrd *a) -+{ -+ gen_helper_tlbrd(cpu_env); -+ return true; -+} -+ -+static bool trans_tlbwr(DisasContext *ctx, arg_tlbwr *a) -+{ -+ gen_helper_tlbwr(cpu_env); -+ return true; -+} -+ -+static bool trans_tlbfill(DisasContext *ctx, arg_tlbfill *a) -+{ -+ gen_helper_tlbfill(cpu_env); -+ return true; -+} -+ -+static bool trans_ertn(DisasContext *ctx, arg_ertn *a) -+{ -+ gen_helper_ertn(cpu_env); -+ ctx->base.is_jmp = DISAS_EXIT; -+ return true; -+} -+ -+#endif /* CONFIG_USER_ONLY */ -+ -+static bool trans_idle(DisasContext *ctx, arg_idle *a) -+{ -+ ctx->base.pc_next += 4; -+ save_cpu_state(ctx, 1); -+ ctx->base.pc_next -= 4; -+ gen_helper_idle(cpu_env); -+ ctx->base.is_jmp = DISAS_NORETURN; -+ return true; -+} -+ -+#ifdef CONFIG_USER_ONLY -+ -+static bool trans_rdtime_d(DisasContext *ctx, arg_rdtime_d *a) -+{ -+ /* Nop */ -+ return true; -+} -+ -+#else -+ -+static bool trans_rdtime_d(DisasContext *ctx, arg_rdtime_d *a) -+{ -+ TCGv t0, t1; -+ t0 = tcg_const_tl(a->rd); -+ t1 = tcg_const_tl(a->rj); -+ gen_helper_drdtime(cpu_env, t0, t1); -+ tcg_temp_free(t0); -+ tcg_temp_free(t1); -+ return true; -+} -+ -+#endif -+ -+static bool trans_cpucfg(DisasContext *ctx, arg_cpucfg *a) -+{ -+ TCGv t0 = tcg_temp_new(); -+ gen_load_gpr(t0, a->rj); -+ gen_helper_cpucfg(cpu_gpr[a->rd], cpu_env, t0); -+ tcg_temp_free(t0); -+ return true; -+} -diff --git a/target/loongarch64/translate.c b/target/loongarch64/translate.c -new file mode 100644 -index 0000000000..fe122e4c31 ---- /dev/null -+++ b/target/loongarch64/translate.c -@@ -0,0 +1,2892 @@ -+/* -+ * LOONGARCH emulation for QEMU - main translation routines -+ * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2 of the License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library; if not, see . -+ */ -+ -+#include "qemu/osdep.h" -+#include "cpu.h" -+#include "internal.h" -+#include "disas/disas.h" -+#include "exec/exec-all.h" -+#include "tcg/tcg-op.h" -+#include "exec/cpu_ldst.h" -+#include "hw/loongarch/cpudevs.h" -+ -+#include "exec/helper-proto.h" -+#include "exec/helper-gen.h" -+#include "semihosting/semihost.h" -+ -+#include "trace-tcg.h" -+#include "exec/translator.h" -+#include "exec/log.h" -+ -+#include "instmap.h" -+ -+#define LARCH_DEBUG_DISAS 0 -+ -+/* Values for the fmt field in FP instructions */ -+enum { -+ /* 0 - 15 are reserved */ -+ FMT_S = 16, /* single fp */ -+ FMT_D = 17, /* double fp */ -+}; -+ -+/* global register indices */ -+static TCGv cpu_gpr[32], cpu_PC; -+static TCGv btarget, bcond; -+static TCGv cpu_lladdr, cpu_llval; -+static TCGv_i32 hflags; -+static TCGv_i32 fpu_fcsr0; -+static TCGv_i64 fpu_f64[32]; -+ -+#include "exec/gen-icount.h" -+ -+#define gen_helper_0e0i(name, arg) do { \ -+ TCGv_i32 helper_tmp = tcg_const_i32(arg); \ -+ gen_helper_##name(cpu_env, helper_tmp); \ -+ tcg_temp_free_i32(helper_tmp); \ -+ } while (0) -+ -+#define gen_helper_0e1i(name, arg1, arg2) do { \ -+ TCGv_i32 helper_tmp = tcg_const_i32(arg2); \ -+ gen_helper_##name(cpu_env, arg1, helper_tmp); \ -+ tcg_temp_free_i32(helper_tmp); \ -+ } while (0) -+ -+#define gen_helper_1e0i(name, ret, arg1) do { \ -+ TCGv_i32 helper_tmp = tcg_const_i32(arg1); \ -+ gen_helper_##name(ret, cpu_env, helper_tmp); \ -+ tcg_temp_free_i32(helper_tmp); \ -+ } while (0) -+ -+#define gen_helper_1e1i(name, ret, arg1, arg2) do { \ -+ TCGv_i32 helper_tmp = tcg_const_i32(arg2); \ -+ gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \ -+ tcg_temp_free_i32(helper_tmp); \ -+ } while (0) -+ -+#define gen_helper_0e2i(name, arg1, arg2, arg3) do { \ -+ TCGv_i32 helper_tmp = tcg_const_i32(arg3); \ -+ gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \ -+ tcg_temp_free_i32(helper_tmp); \ -+ } while (0) -+ -+#define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \ -+ TCGv_i32 helper_tmp = tcg_const_i32(arg3); \ -+ gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \ -+ tcg_temp_free_i32(helper_tmp); \ -+ } while (0) -+ -+#define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \ -+ TCGv_i32 helper_tmp = tcg_const_i32(arg4); \ -+ gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \ -+ tcg_temp_free_i32(helper_tmp); \ -+ } while (0) -+ -+typedef struct DisasContext { -+ DisasContextBase base; -+ target_ulong saved_pc; -+ target_ulong page_start; -+ uint32_t opcode; -+ uint64_t insn_flags; -+ /* Routine used to access memory */ -+ int mem_idx; -+ MemOp default_tcg_memop_mask; -+ uint32_t hflags, saved_hflags; -+ target_ulong btarget; -+} DisasContext; -+ -+#define DISAS_STOP DISAS_TARGET_0 -+#define DISAS_EXIT DISAS_TARGET_1 -+ -+#define LOG_DISAS(...) \ -+ do { \ -+ if (LARCH_DEBUG_DISAS) { \ -+ qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \ -+ } \ -+ } while (0) -+ -+#define LARCH_INVAL(op) \ -+ do { \ -+ if (LARCH_DEBUG_DISAS) { \ -+ qemu_log_mask(CPU_LOG_TB_IN_ASM, \ -+ TARGET_FMT_lx ": %08x Invalid %s %03x %03x %03x\n", \ -+ ctx->base.pc_next, ctx->opcode, op, \ -+ ctx->opcode >> 26, ctx->opcode & 0x3F, \ -+ ((ctx->opcode >> 16) & 0x1F)); \ -+ } \ -+ } while (0) -+ -+/* General purpose registers moves. */ -+static inline void gen_load_gpr(TCGv t, int reg) -+{ -+ if (reg == 0) { -+ tcg_gen_movi_tl(t, 0); -+ } else { -+ tcg_gen_mov_tl(t, cpu_gpr[reg]); -+ } -+} -+ -+static inline void gen_store_gpr(TCGv t, int reg) -+{ -+ if (reg != 0) { -+ tcg_gen_mov_tl(cpu_gpr[reg], t); -+ } -+} -+ -+/* Moves to/from shadow registers. */ -+/* Tests */ -+static inline void gen_save_pc(target_ulong pc) -+{ -+ tcg_gen_movi_tl(cpu_PC, pc); -+} -+ -+static inline void save_cpu_state(DisasContext *ctx, int do_save_pc) -+{ -+ LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags); -+ if (do_save_pc && ctx->base.pc_next != ctx->saved_pc) { -+ gen_save_pc(ctx->base.pc_next); -+ ctx->saved_pc = ctx->base.pc_next; -+ } -+ if (ctx->hflags != ctx->saved_hflags) { -+ tcg_gen_movi_i32(hflags, ctx->hflags); -+ ctx->saved_hflags = ctx->hflags; -+ switch (ctx->hflags & LARCH_HFLAG_BMASK) { -+ case LARCH_HFLAG_BR: -+ break; -+ case LARCH_HFLAG_BC: -+ case LARCH_HFLAG_B: -+ tcg_gen_movi_tl(btarget, ctx->btarget); -+ break; -+ } -+ } -+} -+ -+static inline void restore_cpu_state(CPULOONGARCHState *env, DisasContext *ctx) -+{ -+ ctx->saved_hflags = ctx->hflags; -+ switch (ctx->hflags & LARCH_HFLAG_BMASK) { -+ case LARCH_HFLAG_BR: -+ break; -+ case LARCH_HFLAG_BC: -+ case LARCH_HFLAG_B: -+ ctx->btarget = env->btarget; -+ break; -+ } -+} -+ -+static inline void generate_exception_err(DisasContext *ctx, int excp, int err) -+{ -+ TCGv_i32 texcp = tcg_const_i32(excp); -+ TCGv_i32 terr = tcg_const_i32(err); -+ save_cpu_state(ctx, 1); -+ gen_helper_raise_exception_err(cpu_env, texcp, terr); -+ tcg_temp_free_i32(terr); -+ tcg_temp_free_i32(texcp); -+ ctx->base.is_jmp = DISAS_NORETURN; -+} -+ -+static inline void generate_exception_end(DisasContext *ctx, int excp) -+{ -+ generate_exception_err(ctx, excp, 0); -+} -+ -+/* Floating point register moves. */ -+static void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg) -+{ -+ tcg_gen_extrl_i64_i32(t, fpu_f64[reg]); -+} -+ -+static void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg) -+{ -+ TCGv_i64 t64; -+ t64 = tcg_temp_new_i64(); -+ tcg_gen_extu_i32_i64(t64, t); -+ tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32); -+ tcg_temp_free_i64(t64); -+} -+ -+static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg) -+{ -+ tcg_gen_extrh_i64_i32(t, fpu_f64[reg]); -+} -+ -+static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg) -+{ -+ TCGv_i64 t64 = tcg_temp_new_i64(); -+ tcg_gen_extu_i32_i64(t64, t); -+ tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32); -+ tcg_temp_free_i64(t64); -+} -+ -+static void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg) -+{ -+ tcg_gen_mov_i64(t, fpu_f64[reg]); -+} -+ -+static void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg) -+{ -+ tcg_gen_mov_i64(fpu_f64[reg], t); -+} -+ -+static inline int get_fp_bit(int cc) -+{ -+ if (cc) { -+ return 24 + cc; -+ } else { -+ return 23; -+ } -+} -+ -+/* Addresses computation */ -+static inline void gen_op_addr_add(DisasContext *ctx, -+ TCGv ret, TCGv arg0, TCGv arg1) -+{ -+ tcg_gen_add_tl(ret, arg0, arg1); -+ -+ if (ctx->hflags & LARCH_HFLAG_AWRAP) { -+ tcg_gen_ext32s_i64(ret, ret); -+ } -+} -+ -+static inline void gen_op_addr_addi(DisasContext *ctx, TCGv ret, TCGv base, -+ target_long ofs) -+{ -+ tcg_gen_addi_tl(ret, base, ofs); -+ -+ if (ctx->hflags & LARCH_HFLAG_AWRAP) { -+ tcg_gen_ext32s_i64(ret, ret); -+ } -+} -+ -+/* Sign-extract the low 32-bits to a target_long. */ -+static inline void gen_move_low32(TCGv ret, TCGv_i64 arg) -+{ -+ tcg_gen_ext32s_i64(ret, arg); -+} -+ -+/* Sign-extract the high 32-bits to a target_long. */ -+static inline void gen_move_high32(TCGv ret, TCGv_i64 arg) -+{ -+ tcg_gen_sari_i64(ret, arg, 32); -+} -+ -+static inline void check_cp1_enabled(DisasContext *ctx) -+{ -+#ifndef CONFIG_USER_ONLY -+ if (unlikely(!(ctx->hflags & LARCH_HFLAG_FPU))) { -+ generate_exception_err(ctx, EXCP_FPDIS, 1); -+ } -+#endif -+} -+ -+static inline void check_lsx_enabled(DisasContext *ctx) -+{ -+#ifndef CONFIG_USER_ONLY -+ if (unlikely(!(ctx->hflags & LARCH_HFLAG_LSX))) { -+ generate_exception_err(ctx, EXCP_LSXDIS, 1); -+ } -+#endif -+} -+ -+static inline void check_lasx_enabled(DisasContext *ctx) -+{ -+#ifndef CONFIG_USER_ONLY -+ if (unlikely(!(ctx->hflags & LARCH_HFLAG_LASX))) { -+ generate_exception_err(ctx, EXCP_LASXDIS, 1); -+ } -+#endif -+} -+ -+static inline void check_lbt_enabled(DisasContext *ctx) -+{ -+#ifndef CONFIG_USER_ONLY -+ if (unlikely(!(ctx->hflags & LARCH_HFLAG_LBT))) { -+ generate_exception_err(ctx, EXCP_BTDIS, 1); -+ } -+#endif -+} -+ -+/* This code generates a "reserved instruction" exception if the -+ CPU does not support the instruction set corresponding to flags. */ -+static inline void check_insn(DisasContext *ctx, uint64_t flags) -+{ -+ if (unlikely(!(ctx->insn_flags & flags))) { -+ generate_exception_end(ctx, EXCP_RI); -+ } -+} -+ -+/* This code generates a "reserved instruction" exception if the -+ CPU has corresponding flag set which indicates that the instruction -+ has been removed. */ -+static inline void check_insn_opc_removed(DisasContext *ctx, uint64_t flags) -+{ -+ if (unlikely(ctx->insn_flags & flags)) { -+ generate_exception_end(ctx, EXCP_RI); -+ } -+} -+ -+/* -+ * The Linux kernel traps certain reserved instruction exceptions to -+ * emulate the corresponding instructions. QEMU is the kernel in user -+ * mode, so those traps are emulated by accepting the instructions. -+ * -+ * A reserved instruction exception is generated for flagged CPUs if -+ * QEMU runs in system mode. -+ */ -+static inline void check_insn_opc_user_only(DisasContext *ctx, uint64_t flags) -+{ -+#ifndef CONFIG_USER_ONLY -+ check_insn_opc_removed(ctx, flags); -+#endif -+} -+ -+/* This code generates a "reserved instruction" exception if 64-bit -+ instructions are not enabled. */ -+static inline void check_larch_64(DisasContext *ctx) -+{ -+ if (unlikely(!(ctx->hflags & LARCH_HFLAG_64))) { -+ generate_exception_end(ctx, EXCP_RI); -+ } -+} -+ -+/* Define small wrappers for gen_load_fpr* so that we have a uniform -+ calling interface for 32 and 64-bit FPRs. No sense in changing -+ all callers for gen_load_fpr32 when we need the CTX parameter for -+ this one use. */ -+#define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y) -+#define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y) -+#define FCOP_CONDNS(fmt, ifmt, bits, STORE) \ -+static inline void gen_fcmp_ ## fmt(DisasContext *ctx, int n, \ -+ int ft, int fs, int cd) \ -+{ \ -+ TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \ -+ TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \ -+ TCGv_i32 fcc = tcg_const_i32(cd); \ -+ check_cp1_enabled(ctx); \ -+ gen_ldcmp_fpr ## bits(ctx, fp0, fs); \ -+ gen_ldcmp_fpr ## bits(ctx, fp1, ft); \ -+ switch (n) { \ -+ case 0: \ -+ gen_helper_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \ -+ break; \ -+ case 1: \ -+ gen_helper_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \ -+ break; \ -+ case 2: \ -+ gen_helper_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \ -+ break; \ -+ case 3: \ -+ gen_helper_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \ -+ break; \ -+ case 4: \ -+ gen_helper_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \ -+ break; \ -+ case 5: \ -+ gen_helper_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \ -+ break; \ -+ case 6: \ -+ gen_helper_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \ -+ break; \ -+ case 7: \ -+ gen_helper_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \ -+ break; \ -+ case 8: \ -+ gen_helper_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \ -+ break; \ -+ case 9: \ -+ gen_helper_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \ -+ break; \ -+ case 10: \ -+ gen_helper_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \ -+ break; \ -+ case 11: \ -+ gen_helper_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \ -+ break; \ -+ case 12: \ -+ gen_helper_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \ -+ break; \ -+ case 13: \ -+ gen_helper_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \ -+ break; \ -+ case 14: \ -+ gen_helper_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \ -+ break; \ -+ case 15: \ -+ gen_helper_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \ -+ break; \ -+ case 16: \ -+ gen_helper_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \ -+ break; \ -+ case 17: \ -+ gen_helper_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \ -+ break; \ -+ case 20: \ -+ gen_helper_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \ -+ break; \ -+ case 21: \ -+ gen_helper_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \ -+ break; \ -+ case 24: \ -+ gen_helper_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \ -+ break; \ -+ case 25: \ -+ gen_helper_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \ -+ break; \ -+ default: \ -+ abort(); \ -+ } \ -+ STORE; \ -+ tcg_temp_free_i ## bits(fp0); \ -+ tcg_temp_free_i ## bits(fp1); \ -+ tcg_temp_free_i32(fcc); \ -+} -+ -+FCOP_CONDNS(d, FMT_D, 64, gen_helper_movreg2cf_i64(cpu_env, fcc, fp0)) -+FCOP_CONDNS(s, FMT_S, 32, gen_helper_movreg2cf_i32(cpu_env, fcc, fp0)) -+#undef FCOP_CONDNS -+#undef gen_ldcmp_fpr32 -+#undef gen_ldcmp_fpr64 -+ -+/* load/store instructions. */ -+#ifdef CONFIG_USER_ONLY -+#define OP_LD_ATOMIC(insn, fname) \ -+static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \ -+ DisasContext *ctx) \ -+{ \ -+ TCGv t0 = tcg_temp_new(); \ -+ tcg_gen_mov_tl(t0, arg1); \ -+ tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \ -+ tcg_gen_st_tl(t0, cpu_env, \ -+ offsetof(CPULOONGARCHState, lladdr)); \ -+ tcg_gen_st_tl(ret, cpu_env, \ -+ offsetof(CPULOONGARCHState, llval)); \ -+ tcg_temp_free(t0); \ -+} -+#else -+#define OP_LD_ATOMIC(insn, fname) \ -+static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \ -+ DisasContext *ctx) \ -+{ \ -+ gen_helper_1e1i(insn, ret, arg1, mem_idx); \ -+} -+#endif -+#if 0 -+OP_LD_ATOMIC(ll, ld32s); -+OP_LD_ATOMIC(lld, ld64); -+#endif -+#undef OP_LD_ATOMIC -+ -+static void gen_base_offset_addr(DisasContext *ctx, TCGv addr, -+ int base, int offset) -+{ -+ if (base == 0) { -+ tcg_gen_movi_tl(addr, offset); -+ } else if (offset == 0) { -+ gen_load_gpr(addr, base); -+ } else { -+ tcg_gen_movi_tl(addr, offset); -+ gen_op_addr_add(ctx, addr, cpu_gpr[base], addr); -+ } -+} -+ -+/* Load */ -+static void gen_ld(DisasContext *ctx, uint32_t opc, -+ int rt, int base, int offset) -+{ -+ TCGv t0; -+ int mem_idx = ctx->mem_idx; -+ -+ t0 = tcg_temp_new(); -+ gen_base_offset_addr(ctx, t0, base, offset); -+ -+ switch (opc) { -+ case OPC_LARCH_LD_WU: -+ tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL | -+ ctx->default_tcg_memop_mask); -+ gen_store_gpr(t0, rt); -+ break; -+ case OPC_LARCH_LDPTR_D: -+ case OPC_LARCH_LD_D: -+ tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ | -+ ctx->default_tcg_memop_mask); -+ gen_store_gpr(t0, rt); -+ break; -+ case OPC_LARCH_LL_D: -+#if 0 -+ op_ld_lld(t0, t0, mem_idx, ctx); -+#endif -+ gen_store_gpr(t0, rt); -+ break; -+ case OPC_LARCH_LDPTR_W: -+ case OPC_LARCH_LD_W: -+ tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL | -+ ctx->default_tcg_memop_mask); -+ gen_store_gpr(t0, rt); -+ break; -+ case OPC_LARCH_LD_H: -+ tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESW | -+ ctx->default_tcg_memop_mask); -+ gen_store_gpr(t0, rt); -+ break; -+ case OPC_LARCH_LD_HU: -+ tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUW | -+ ctx->default_tcg_memop_mask); -+ gen_store_gpr(t0, rt); -+ break; -+ case OPC_LARCH_LD_B: -+ tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_SB); -+ gen_store_gpr(t0, rt); -+ break; -+ case OPC_LARCH_LD_BU: -+ tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_UB); -+ gen_store_gpr(t0, rt); -+ break; -+ case OPC_LARCH_LL_W: -+#if 0 -+ op_ld_ll(t0, t0, mem_idx, ctx); -+#endif -+ gen_store_gpr(t0, rt); -+ break; -+ } -+ -+ tcg_temp_free(t0); -+} -+ -+/* Store */ -+static void gen_st(DisasContext *ctx, uint32_t opc, int rt, -+ int base, int offset) -+{ -+ TCGv t0 = tcg_temp_new(); -+ TCGv t1 = tcg_temp_new(); -+ int mem_idx = ctx->mem_idx; -+ -+ gen_base_offset_addr(ctx, t0, base, offset); -+ gen_load_gpr(t1, rt); -+ -+ switch (opc) { -+ case OPC_LARCH_STPTR_D: -+ case OPC_LARCH_ST_D: -+ tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEQ | -+ ctx->default_tcg_memop_mask); -+ break; -+ case OPC_LARCH_STPTR_W: -+ case OPC_LARCH_ST_W: -+ tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUL | -+ ctx->default_tcg_memop_mask); -+ break; -+ case OPC_LARCH_ST_H: -+ tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUW | -+ ctx->default_tcg_memop_mask); -+ break; -+ case OPC_LARCH_ST_B: -+ tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_8); -+ break; -+ } -+ tcg_temp_free(t0); -+ tcg_temp_free(t1); -+} -+ -+/* Store conditional */ -+static void gen_st_cond(DisasContext *ctx, int rt, int base, int offset, -+ MemOp tcg_mo, bool eva) -+{ -+ TCGv addr, t0, val; -+ TCGLabel *l1 = gen_new_label(); -+ TCGLabel *done = gen_new_label(); -+ -+ t0 = tcg_temp_new(); -+ addr = tcg_temp_new(); -+ /* compare the address against that of the preceeding LL */ -+ gen_base_offset_addr(ctx, addr, base, offset); -+ tcg_gen_brcond_tl(TCG_COND_EQ, addr, cpu_lladdr, l1); -+ tcg_temp_free(addr); -+ tcg_gen_movi_tl(t0, 0); -+ gen_store_gpr(t0, rt); -+ tcg_gen_br(done); -+ -+ gen_set_label(l1); -+ /* generate cmpxchg */ -+ val = tcg_temp_new(); -+ gen_load_gpr(val, rt); -+ tcg_gen_atomic_cmpxchg_tl(t0, cpu_lladdr, cpu_llval, val, -+ eva ? LARCH_HFLAG_UM : ctx->mem_idx, tcg_mo); -+ tcg_gen_setcond_tl(TCG_COND_EQ, t0, t0, cpu_llval); -+ gen_store_gpr(t0, rt); -+ tcg_temp_free(val); -+ -+ gen_set_label(done); -+ tcg_temp_free(t0); -+} -+ -+/* Load and store */ -+static void gen_flt_ldst(DisasContext *ctx, uint32_t opc, int ft, -+ TCGv t0) -+{ -+ /* Don't do NOP if destination is zero: we must perform the actual -+ memory access. */ -+ switch (opc) { -+ case OPC_LARCH_FLD_S: -+ { -+ TCGv_i32 fp0 = tcg_temp_new_i32(); -+ tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL | -+ ctx->default_tcg_memop_mask); -+ gen_store_fpr32(ctx, fp0, ft); -+ tcg_temp_free_i32(fp0); -+ } -+ break; -+ case OPC_LARCH_FST_S: -+ { -+ TCGv_i32 fp0 = tcg_temp_new_i32(); -+ gen_load_fpr32(ctx, fp0, ft); -+ tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL | -+ ctx->default_tcg_memop_mask); -+ tcg_temp_free_i32(fp0); -+ } -+ break; -+ case OPC_LARCH_FLD_D: -+ { -+ TCGv_i64 fp0 = tcg_temp_new_i64(); -+ tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ | -+ ctx->default_tcg_memop_mask); -+ gen_store_fpr64(ctx, fp0, ft); -+ tcg_temp_free_i64(fp0); -+ } -+ break; -+ case OPC_LARCH_FST_D: -+ { -+ TCGv_i64 fp0 = tcg_temp_new_i64(); -+ gen_load_fpr64(ctx, fp0, ft); -+ tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ | -+ ctx->default_tcg_memop_mask); -+ tcg_temp_free_i64(fp0); -+ } -+ break; -+ default: -+ LARCH_INVAL("flt_ldst"); -+ generate_exception_end(ctx, EXCP_RI); -+ break; -+ } -+} -+ -+static void gen_fp_ldst(DisasContext *ctx, uint32_t op, int rt, -+ int rs, int16_t imm) -+{ -+ TCGv t0 = tcg_temp_new(); -+ -+ check_cp1_enabled(ctx); -+ gen_base_offset_addr(ctx, t0, rs, imm); -+ gen_flt_ldst(ctx, op, rt, t0); -+ tcg_temp_free(t0); -+} -+ -+/* Arithmetic with immediate operand */ -+static void gen_arith_imm(DisasContext *ctx, uint32_t opc, -+ int rt, int rs, int imm) -+{ -+ target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */ -+ -+ if (rt == 0) { -+ /* If no destination, treat it as a NOP. -+ For addi, we must generate the overflow exception when needed. */ -+ return; -+ } -+ switch (opc) { -+ case OPC_LARCH_ADDI_W: -+ if (rs != 0) { -+ tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm); -+ tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]); -+ } else { -+ tcg_gen_movi_tl(cpu_gpr[rt], uimm); -+ } -+ break; -+ case OPC_LARCH_ADDI_D: -+ if (rs != 0) { -+ tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm); -+ } else { -+ tcg_gen_movi_tl(cpu_gpr[rt], uimm); -+ } -+ break; -+ } -+} -+ -+/* Logic with immediate operand */ -+static void gen_logic_imm(DisasContext *ctx, uint32_t opc, -+ int rt, int rs, int16_t imm) -+{ -+ target_ulong uimm; -+ -+ if (rt == 0) { -+ /* If no destination, treat it as a NOP. */ -+ return; -+ } -+ uimm = (uint16_t)imm; -+ switch (opc) { -+ case OPC_LARCH_ANDI: -+ if (likely(rs != 0)) { -+ tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm); -+ } else { -+ tcg_gen_movi_tl(cpu_gpr[rt], 0); -+ } -+ break; -+ case OPC_LARCH_ORI: -+ if (rs != 0) { -+ tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm); -+ } else { -+ tcg_gen_movi_tl(cpu_gpr[rt], uimm); -+ } -+ break; -+ case OPC_LARCH_XORI: -+ if (likely(rs != 0)) { -+ tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm); -+ } else { -+ tcg_gen_movi_tl(cpu_gpr[rt], uimm); -+ } -+ break; -+ default: -+ break; -+ } -+} -+ -+/* Set on less than with immediate operand */ -+static void gen_slt_imm(DisasContext *ctx, uint32_t opc, -+ int rt, int rs, int16_t imm) -+{ -+ target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */ -+ TCGv t0; -+ -+ if (rt == 0) { -+ /* If no destination, treat it as a NOP. */ -+ return; -+ } -+ t0 = tcg_temp_new(); -+ gen_load_gpr(t0, rs); -+ switch (opc) { -+ case OPC_LARCH_SLTI: -+ tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm); -+ break; -+ case OPC_LARCH_SLTIU: -+ tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm); -+ break; -+ } -+ tcg_temp_free(t0); -+} -+ -+/* Shifts with immediate operand */ -+static void gen_shift_imm(DisasContext *ctx, uint32_t opc, -+ int rt, int rs, int16_t imm) -+{ -+ target_ulong uimm = ((uint16_t)imm) & 0x1f; -+ TCGv t0; -+ -+ if (rt == 0) { -+ /* If no destination, treat it as a NOP. */ -+ return; -+ } -+ -+ t0 = tcg_temp_new(); -+ gen_load_gpr(t0, rs); -+ switch (opc) { -+ case OPC_LARCH_SRAI_W: -+ tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm); -+ break; -+ case OPC_LARCH_SRLI_W: -+ if (uimm != 0) { -+ tcg_gen_ext32u_tl(t0, t0); -+ tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm); -+ } else { -+ tcg_gen_ext32s_tl(cpu_gpr[rt], t0); -+ } -+ break; -+ case OPC_LARCH_ROTRI_W: -+ if (uimm != 0) { -+ TCGv_i32 t1 = tcg_temp_new_i32(); -+ -+ tcg_gen_trunc_tl_i32(t1, t0); -+ tcg_gen_rotri_i32(t1, t1, uimm); -+ tcg_gen_ext_i32_tl(cpu_gpr[rt], t1); -+ tcg_temp_free_i32(t1); -+ } else { -+ tcg_gen_ext32s_tl(cpu_gpr[rt], t0); -+ } -+ break; -+ } -+ tcg_temp_free(t0); -+} -+ -+/* Arithmetic */ -+static void gen_arith(DisasContext *ctx, uint32_t opc, -+ int rd, int rs, int rt) -+{ -+ if (rd == 0) { -+ /* If no destination, treat it as a NOP. -+ For add & sub, we must generate the -+ overflow exception when needed. */ -+ return; -+ } -+ -+ switch (opc) { -+ case OPC_LARCH_ADD_W: -+ if (rs != 0 && rt != 0) { -+ tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]); -+ tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]); -+ } else if (rs == 0 && rt != 0) { -+ tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]); -+ } else if (rs != 0 && rt == 0) { -+ tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]); -+ } else { -+ tcg_gen_movi_tl(cpu_gpr[rd], 0); -+ } -+ break; -+ case OPC_LARCH_SUB_W: -+ if (rs != 0 && rt != 0) { -+ tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]); -+ tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]); -+ } else if (rs == 0 && rt != 0) { -+ tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]); -+ tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]); -+ } else if (rs != 0 && rt == 0) { -+ tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]); -+ } else { -+ tcg_gen_movi_tl(cpu_gpr[rd], 0); -+ } -+ break; -+ case OPC_LARCH_ADD_D: -+ if (rs != 0 && rt != 0) { -+ tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]); -+ } else if (rs == 0 && rt != 0) { -+ tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]); -+ } else if (rs != 0 && rt == 0) { -+ tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]); -+ } else { -+ tcg_gen_movi_tl(cpu_gpr[rd], 0); -+ } -+ break; -+ case OPC_LARCH_SUB_D: -+ if (rs != 0 && rt != 0) { -+ tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]); -+ } else if (rs == 0 && rt != 0) { -+ tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]); -+ } else if (rs != 0 && rt == 0) { -+ tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]); -+ } else { -+ tcg_gen_movi_tl(cpu_gpr[rd], 0); -+ } -+ break; -+ } -+} -+ -+/* Conditional move */ -+static void gen_cond_move(DisasContext *ctx, uint32_t opc, -+ int rd, int rs, int rt) -+{ -+ TCGv t0, t1, t2; -+ -+ if (rd == 0) { -+ /* If no destination, treat it as a NOP. */ -+ return; -+ } -+ -+ t0 = tcg_temp_new(); -+ gen_load_gpr(t0, rt); -+ t1 = tcg_const_tl(0); -+ t2 = tcg_temp_new(); -+ gen_load_gpr(t2, rs); -+ switch (opc) { -+ case OPC_LARCH_MASKEQZ: -+ tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1); -+ break; -+ case OPC_LARCH_MASKNEZ: -+ tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1); -+ break; -+ } -+ tcg_temp_free(t2); -+ tcg_temp_free(t1); -+ tcg_temp_free(t0); -+} -+ -+/* Logic */ -+static void gen_logic(DisasContext *ctx, uint32_t opc, -+ int rd, int rs, int rt) -+{ -+ if (rd == 0) { -+ /* If no destination, treat it as a NOP. */ -+ return; -+ } -+ -+ switch (opc) { -+ case OPC_LARCH_AND: -+ if (likely(rs != 0 && rt != 0)) { -+ tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]); -+ } else { -+ tcg_gen_movi_tl(cpu_gpr[rd], 0); -+ } -+ break; -+ case OPC_LARCH_NOR: -+ if (rs != 0 && rt != 0) { -+ tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]); -+ } else if (rs == 0 && rt != 0) { -+ tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]); -+ } else if (rs != 0 && rt == 0) { -+ tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]); -+ } else { -+ tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0)); -+ } -+ break; -+ case OPC_LARCH_OR: -+ if (likely(rs != 0 && rt != 0)) { -+ tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]); -+ } else if (rs == 0 && rt != 0) { -+ tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]); -+ } else if (rs != 0 && rt == 0) { -+ tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]); -+ } else { -+ tcg_gen_movi_tl(cpu_gpr[rd], 0); -+ } -+ break; -+ case OPC_LARCH_XOR: -+ if (likely(rs != 0 && rt != 0)) { -+ tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]); -+ } else if (rs == 0 && rt != 0) { -+ tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]); -+ } else if (rs != 0 && rt == 0) { -+ tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]); -+ } else { -+ tcg_gen_movi_tl(cpu_gpr[rd], 0); -+ } -+ break; -+ } -+} -+ -+/* Set on lower than */ -+static void gen_slt(DisasContext *ctx, uint32_t opc, -+ int rd, int rs, int rt) -+{ -+ TCGv t0, t1; -+ -+ if (rd == 0) { -+ /* If no destination, treat it as a NOP. */ -+ return; -+ } -+ -+ t0 = tcg_temp_new(); -+ t1 = tcg_temp_new(); -+ gen_load_gpr(t0, rs); -+ gen_load_gpr(t1, rt); -+ switch (opc) { -+ case OPC_LARCH_SLT: -+ tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1); -+ break; -+ case OPC_LARCH_SLTU: -+ tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1); -+ break; -+ } -+ tcg_temp_free(t0); -+ tcg_temp_free(t1); -+} -+ -+/* Shifts */ -+static void gen_shift(DisasContext *ctx, uint32_t opc, -+ int rd, int rs, int rt) -+{ -+ TCGv t0, t1; -+ -+ if (rd == 0) { -+ /* If no destination, treat it as a NOP. -+ For add & sub, we must generate the -+ overflow exception when needed. */ -+ return; -+ } -+ -+ t0 = tcg_temp_new(); -+ t1 = tcg_temp_new(); -+ gen_load_gpr(t0, rs); -+ gen_load_gpr(t1, rt); -+ switch (opc) { -+ case OPC_LARCH_SLL_W: -+ tcg_gen_andi_tl(t0, t0, 0x1f); -+ tcg_gen_shl_tl(t0, t1, t0); -+ tcg_gen_ext32s_tl(cpu_gpr[rd], t0); -+ break; -+ case OPC_LARCH_SRA_W: -+ tcg_gen_andi_tl(t0, t0, 0x1f); -+ tcg_gen_sar_tl(cpu_gpr[rd], t1, t0); -+ break; -+ case OPC_LARCH_SRL_W: -+ tcg_gen_ext32u_tl(t1, t1); -+ tcg_gen_andi_tl(t0, t0, 0x1f); -+ tcg_gen_shr_tl(t0, t1, t0); -+ tcg_gen_ext32s_tl(cpu_gpr[rd], t0); -+ break; -+ case OPC_LARCH_ROTR_W: -+ { -+ TCGv_i32 t2 = tcg_temp_new_i32(); -+ TCGv_i32 t3 = tcg_temp_new_i32(); -+ -+ tcg_gen_trunc_tl_i32(t2, t0); -+ tcg_gen_trunc_tl_i32(t3, t1); -+ tcg_gen_andi_i32(t2, t2, 0x1f); -+ tcg_gen_rotr_i32(t2, t3, t2); -+ tcg_gen_ext_i32_tl(cpu_gpr[rd], t2); -+ tcg_temp_free_i32(t2); -+ tcg_temp_free_i32(t3); -+ } -+ break; -+ case OPC_LARCH_SLL_D: -+ tcg_gen_andi_tl(t0, t0, 0x3f); -+ tcg_gen_shl_tl(cpu_gpr[rd], t1, t0); -+ break; -+ case OPC_LARCH_SRA_D: -+ tcg_gen_andi_tl(t0, t0, 0x3f); -+ tcg_gen_sar_tl(cpu_gpr[rd], t1, t0); -+ break; -+ case OPC_LARCH_SRL_D: -+ tcg_gen_andi_tl(t0, t0, 0x3f); -+ tcg_gen_shr_tl(cpu_gpr[rd], t1, t0); -+ break; -+ case OPC_LARCH_ROTR_D: -+ tcg_gen_andi_tl(t0, t0, 0x3f); -+ tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0); -+ break; -+ } -+ tcg_temp_free(t0); -+ tcg_temp_free(t1); -+} -+ -+static inline void gen_r6_ld(target_long addr, int reg, int memidx, -+ MemOp memop) -+{ -+ TCGv t0 = tcg_const_tl(addr); -+ tcg_gen_qemu_ld_tl(t0, t0, memidx, memop); -+ gen_store_gpr(t0, reg); -+ tcg_temp_free(t0); -+} -+ -+static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt) -+{ -+ TCGv t0, t1; -+ -+ if (rd == 0) { -+ /* Treat as NOP. */ -+ return; -+ } -+ -+ t0 = tcg_temp_new(); -+ t1 = tcg_temp_new(); -+ -+ gen_load_gpr(t0, rs); -+ gen_load_gpr(t1, rt); -+ -+ switch (opc) { -+ case OPC_LARCH_DIV_W: -+ { -+ TCGv t2 = tcg_temp_new(); -+ TCGv t3 = tcg_temp_new(); -+ tcg_gen_ext32s_tl(t0, t0); -+ tcg_gen_ext32s_tl(t1, t1); -+ tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN); -+ tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1); -+ tcg_gen_and_tl(t2, t2, t3); -+ tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0); -+ tcg_gen_or_tl(t2, t2, t3); -+ tcg_gen_movi_tl(t3, 0); -+ tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1); -+ tcg_gen_div_tl(cpu_gpr[rd], t0, t1); -+ tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]); -+ tcg_temp_free(t3); -+ tcg_temp_free(t2); -+ } -+ break; -+ case OPC_LARCH_MOD_W: -+ { -+ TCGv t2 = tcg_temp_new(); -+ TCGv t3 = tcg_temp_new(); -+ tcg_gen_ext32s_tl(t0, t0); -+ tcg_gen_ext32s_tl(t1, t1); -+ tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN); -+ tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1); -+ tcg_gen_and_tl(t2, t2, t3); -+ tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0); -+ tcg_gen_or_tl(t2, t2, t3); -+ tcg_gen_movi_tl(t3, 0); -+ tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1); -+ tcg_gen_rem_tl(cpu_gpr[rd], t0, t1); -+ tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]); -+ tcg_temp_free(t3); -+ tcg_temp_free(t2); -+ } -+ break; -+ case OPC_LARCH_DIV_WU: -+ { -+ TCGv t2 = tcg_const_tl(0); -+ TCGv t3 = tcg_const_tl(1); -+ tcg_gen_ext32u_tl(t0, t0); -+ tcg_gen_ext32u_tl(t1, t1); -+ tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1); -+ tcg_gen_divu_tl(cpu_gpr[rd], t0, t1); -+ tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]); -+ tcg_temp_free(t3); -+ tcg_temp_free(t2); -+ } -+ break; -+ case OPC_LARCH_MOD_WU: -+ { -+ TCGv t2 = tcg_const_tl(0); -+ TCGv t3 = tcg_const_tl(1); -+ tcg_gen_ext32u_tl(t0, t0); -+ tcg_gen_ext32u_tl(t1, t1); -+ tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1); -+ tcg_gen_remu_tl(cpu_gpr[rd], t0, t1); -+ tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]); -+ tcg_temp_free(t3); -+ tcg_temp_free(t2); -+ } -+ break; -+ case OPC_LARCH_MUL_W: -+ { -+ TCGv_i32 t2 = tcg_temp_new_i32(); -+ TCGv_i32 t3 = tcg_temp_new_i32(); -+ tcg_gen_trunc_tl_i32(t2, t0); -+ tcg_gen_trunc_tl_i32(t3, t1); -+ tcg_gen_mul_i32(t2, t2, t3); -+ tcg_gen_ext_i32_tl(cpu_gpr[rd], t2); -+ tcg_temp_free_i32(t2); -+ tcg_temp_free_i32(t3); -+ } -+ break; -+ case OPC_LARCH_MULH_W: -+ { -+ TCGv_i32 t2 = tcg_temp_new_i32(); -+ TCGv_i32 t3 = tcg_temp_new_i32(); -+ tcg_gen_trunc_tl_i32(t2, t0); -+ tcg_gen_trunc_tl_i32(t3, t1); -+ tcg_gen_muls2_i32(t2, t3, t2, t3); -+ tcg_gen_ext_i32_tl(cpu_gpr[rd], t3); -+ tcg_temp_free_i32(t2); -+ tcg_temp_free_i32(t3); -+ } -+ break; -+ case OPC_LARCH_MULH_WU: -+ { -+ TCGv_i32 t2 = tcg_temp_new_i32(); -+ TCGv_i32 t3 = tcg_temp_new_i32(); -+ tcg_gen_trunc_tl_i32(t2, t0); -+ tcg_gen_trunc_tl_i32(t3, t1); -+ tcg_gen_mulu2_i32(t2, t3, t2, t3); -+ tcg_gen_ext_i32_tl(cpu_gpr[rd], t3); -+ tcg_temp_free_i32(t2); -+ tcg_temp_free_i32(t3); -+ } -+ break; -+ case OPC_LARCH_DIV_D: -+ { -+ TCGv t2 = tcg_temp_new(); -+ TCGv t3 = tcg_temp_new(); -+ tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63); -+ tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL); -+ tcg_gen_and_tl(t2, t2, t3); -+ tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0); -+ tcg_gen_or_tl(t2, t2, t3); -+ tcg_gen_movi_tl(t3, 0); -+ tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1); -+ tcg_gen_div_tl(cpu_gpr[rd], t0, t1); -+ tcg_temp_free(t3); -+ tcg_temp_free(t2); -+ } -+ break; -+ case OPC_LARCH_MOD_D: -+ { -+ TCGv t2 = tcg_temp_new(); -+ TCGv t3 = tcg_temp_new(); -+ tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63); -+ tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL); -+ tcg_gen_and_tl(t2, t2, t3); -+ tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0); -+ tcg_gen_or_tl(t2, t2, t3); -+ tcg_gen_movi_tl(t3, 0); -+ tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1); -+ tcg_gen_rem_tl(cpu_gpr[rd], t0, t1); -+ tcg_temp_free(t3); -+ tcg_temp_free(t2); -+ } -+ break; -+ case OPC_LARCH_DIV_DU: -+ { -+ TCGv t2 = tcg_const_tl(0); -+ TCGv t3 = tcg_const_tl(1); -+ tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1); -+ tcg_gen_divu_i64(cpu_gpr[rd], t0, t1); -+ tcg_temp_free(t3); -+ tcg_temp_free(t2); -+ } -+ break; -+ case OPC_LARCH_MOD_DU: -+ { -+ TCGv t2 = tcg_const_tl(0); -+ TCGv t3 = tcg_const_tl(1); -+ tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1); -+ tcg_gen_remu_i64(cpu_gpr[rd], t0, t1); -+ tcg_temp_free(t3); -+ tcg_temp_free(t2); -+ } -+ break; -+ case OPC_LARCH_MUL_D: -+ tcg_gen_mul_i64(cpu_gpr[rd], t0, t1); -+ break; -+ case OPC_LARCH_MULH_D: -+ { -+ TCGv t2 = tcg_temp_new(); -+ tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1); -+ tcg_temp_free(t2); -+ } -+ break; -+ case OPC_LARCH_MULH_DU: -+ { -+ TCGv t2 = tcg_temp_new(); -+ tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1); -+ tcg_temp_free(t2); -+ } -+ break; -+ default: -+ LARCH_INVAL("r6 mul/div"); -+ generate_exception_end(ctx, EXCP_RI); -+ goto out; -+ } -+ out: -+ tcg_temp_free(t0); -+ tcg_temp_free(t1); -+} -+ -+static void gen_cl(DisasContext *ctx, uint32_t opc, -+ int rd, int rs) -+{ -+ TCGv t0; -+ -+ if (rd == 0) { -+ /* Treat as NOP. */ -+ return; -+ } -+ t0 = cpu_gpr[rd]; -+ gen_load_gpr(t0, rs); -+ -+ switch (opc) { -+ case OPC_LARCH_CLO_W: -+ case OPC_LARCH_CLO_D: -+ tcg_gen_not_tl(t0, t0); -+ break; -+ } -+ -+ switch (opc) { -+ case OPC_LARCH_CLO_W: -+ case OPC_LARCH_CLZ_W: -+ tcg_gen_ext32u_tl(t0, t0); -+ tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS); -+ tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32); -+ break; -+ case OPC_LARCH_CLO_D: -+ case OPC_LARCH_CLZ_D: -+ tcg_gen_clzi_i64(t0, t0, 64); -+ break; -+ } -+} -+ -+static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest) -+{ -+ if (unlikely(ctx->base.singlestep_enabled)) { -+ return false; -+ } -+ -+#ifndef CONFIG_USER_ONLY -+ return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK); -+#else -+ return true; -+#endif -+} -+ -+static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest) -+{ -+ if (use_goto_tb(ctx, dest)) { -+ tcg_gen_goto_tb(n); -+ gen_save_pc(dest); -+ tcg_gen_exit_tb(ctx->base.tb, n); -+ } else { -+ gen_save_pc(dest); -+ if (ctx->base.singlestep_enabled) { -+ save_cpu_state(ctx, 0); -+ gen_helper_raise_exception_debug(cpu_env); -+ } -+ tcg_gen_lookup_and_goto_ptr(); -+ } -+} -+ -+/* Branches */ -+static void gen_compute_branch(DisasContext *ctx, uint32_t opc, -+ int insn_bytes, -+ int rs, int rt, int32_t offset) -+{ -+ target_ulong btgt = -1; -+ int bcond_compute = 0; -+ TCGv t0 = tcg_temp_new(); -+ TCGv t1 = tcg_temp_new(); -+ -+ if (ctx->hflags & LARCH_HFLAG_BMASK) { -+#ifdef LARCH_DEBUG_DISAS -+ LOG_DISAS("Branch at PC 0x" -+ TARGET_FMT_lx "\n", ctx->base.pc_next); -+#endif -+ generate_exception_end(ctx, EXCP_RI); -+ goto out; -+ } -+ -+ /* Load needed operands */ -+ switch (opc) { -+ case OPC_LARCH_BLT: -+ case OPC_LARCH_BGE: -+ case OPC_LARCH_BLTU: -+ case OPC_LARCH_BGEU: -+ gen_load_gpr(t0, rs); -+ gen_load_gpr(t1, rt); -+ bcond_compute = 1; -+ btgt = ctx->base.pc_next + offset; -+ break; -+ case OPC_LARCH_BEQZ: -+ case OPC_LARCH_B: -+ case OPC_LARCH_BEQ: -+ case OPC_LARCH_BNEZ: -+ case OPC_LARCH_BNE: -+ /* Compare two registers */ -+ if (rs != rt) { -+ gen_load_gpr(t0, rs); -+ gen_load_gpr(t1, rt); -+ bcond_compute = 1; -+ } -+ btgt = ctx->base.pc_next + offset; -+ break; -+ default: -+ LARCH_INVAL("branch/jump"); -+ generate_exception_end(ctx, EXCP_RI); -+ goto out; -+ } -+ if (bcond_compute == 0) { -+ /* No condition to be computed */ -+ switch (opc) { -+ case OPC_LARCH_BEQZ: /* rx == rx */ -+ case OPC_LARCH_B: -+ case OPC_LARCH_BEQ: -+ /* Always take */ -+ ctx->hflags |= LARCH_HFLAG_B; -+ break; -+ case OPC_LARCH_BNEZ: -+ case OPC_LARCH_BNE: -+ /* Treat as NOP. */ -+ goto out; -+ default: -+ LARCH_INVAL("branch/jump"); -+ generate_exception_end(ctx, EXCP_RI); -+ goto out; -+ } -+ } else { -+ switch (opc) { -+ case OPC_LARCH_BLT: -+ tcg_gen_setcond_tl(TCG_COND_LT, bcond, t0, t1); -+ goto not_likely; -+ case OPC_LARCH_BGE: -+ tcg_gen_setcond_tl(TCG_COND_GE, bcond, t0, t1); -+ goto not_likely; -+ case OPC_LARCH_BLTU: -+ tcg_gen_setcond_tl(TCG_COND_LTU, bcond, t0, t1); -+ goto not_likely; -+ case OPC_LARCH_BGEU: -+ tcg_gen_setcond_tl(TCG_COND_GEU, bcond, t0, t1); -+ goto not_likely; -+ case OPC_LARCH_BEQZ: -+ case OPC_LARCH_B: -+ case OPC_LARCH_BEQ: -+ tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1); -+ goto not_likely; -+ case OPC_LARCH_BNEZ: -+ case OPC_LARCH_BNE: -+ tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1); -+ goto not_likely; -+ not_likely: -+ ctx->hflags |= LARCH_HFLAG_BC; -+ break; -+ default: -+ LARCH_INVAL("conditional branch/jump"); -+ generate_exception_end(ctx, EXCP_RI); -+ goto out; -+ } -+ } -+ -+ ctx->btarget = btgt; -+ -+ out: -+ tcg_temp_free(t0); -+ tcg_temp_free(t1); -+} -+ -+/* special3 bitfield operations */ -+static void gen_bitops(DisasContext *ctx, uint32_t opc, int rt, -+ int rs, int lsb, int msb) -+{ -+ TCGv t0 = tcg_temp_new(); -+ TCGv t1 = tcg_temp_new(); -+ -+ gen_load_gpr(t1, rs); -+ switch (opc) { -+ case OPC_LARCH_TRPICK_W: -+ if (lsb + msb > 31) { -+ goto fail; -+ } -+ if (msb != 31) { -+ tcg_gen_extract_tl(t0, t1, lsb, msb + 1); -+ } else { -+ /* -+ * The two checks together imply that lsb == 0, -+ * so this is a simple sign-extension. -+ */ -+ tcg_gen_ext32s_tl(t0, t1); -+ } -+ break; -+ case OPC_LARCH_TRINS_W: -+ if (lsb > msb) { -+ goto fail; -+ } -+ gen_load_gpr(t0, rt); -+ tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1); -+ tcg_gen_ext32s_tl(t0, t0); -+ break; -+ default: -+fail: -+ LARCH_INVAL("bitops"); -+ generate_exception_end(ctx, EXCP_RI); -+ tcg_temp_free(t0); -+ tcg_temp_free(t1); -+ return; -+ } -+ gen_store_gpr(t0, rt); -+ tcg_temp_free(t0); -+ tcg_temp_free(t1); -+} -+ -+static void gen_bshfl(DisasContext *ctx, uint32_t op2, int rt, int rd) -+{ -+ TCGv t0; -+ -+ if (rd == 0) { -+ /* If no destination, treat it as a NOP. */ -+ return; -+ } -+ -+ t0 = tcg_temp_new(); -+ gen_load_gpr(t0, rt); -+ switch (op2) { -+ case OPC_LARCH_REVB_2H: -+ { -+ TCGv t1 = tcg_temp_new(); -+ TCGv t2 = tcg_const_tl(0x00FF00FF); -+ -+ tcg_gen_shri_tl(t1, t0, 8); -+ tcg_gen_and_tl(t1, t1, t2); -+ tcg_gen_and_tl(t0, t0, t2); -+ tcg_gen_shli_tl(t0, t0, 8); -+ tcg_gen_or_tl(t0, t0, t1); -+ tcg_temp_free(t2); -+ tcg_temp_free(t1); -+ tcg_gen_ext32s_tl(cpu_gpr[rd], t0); -+ } -+ break; -+ case OPC_LARCH_EXT_WB: -+ tcg_gen_ext8s_tl(cpu_gpr[rd], t0); -+ break; -+ case OPC_LARCH_EXT_WH: -+ tcg_gen_ext16s_tl(cpu_gpr[rd], t0); -+ break; -+ case OPC_LARCH_REVB_4H: -+ { -+ TCGv t1 = tcg_temp_new(); -+ TCGv t2 = tcg_const_tl(0x00FF00FF00FF00FFULL); -+ -+ tcg_gen_shri_tl(t1, t0, 8); -+ tcg_gen_and_tl(t1, t1, t2); -+ tcg_gen_and_tl(t0, t0, t2); -+ tcg_gen_shli_tl(t0, t0, 8); -+ tcg_gen_or_tl(cpu_gpr[rd], t0, t1); -+ tcg_temp_free(t2); -+ tcg_temp_free(t1); -+ } -+ break; -+ case OPC_LARCH_REVH_D: -+ { -+ TCGv t1 = tcg_temp_new(); -+ TCGv t2 = tcg_const_tl(0x0000FFFF0000FFFFULL); -+ -+ tcg_gen_shri_tl(t1, t0, 16); -+ tcg_gen_and_tl(t1, t1, t2); -+ tcg_gen_and_tl(t0, t0, t2); -+ tcg_gen_shli_tl(t0, t0, 16); -+ tcg_gen_or_tl(t0, t0, t1); -+ tcg_gen_shri_tl(t1, t0, 32); -+ tcg_gen_shli_tl(t0, t0, 32); -+ tcg_gen_or_tl(cpu_gpr[rd], t0, t1); -+ tcg_temp_free(t2); -+ tcg_temp_free(t1); -+ } -+ break; -+ default: -+ LARCH_INVAL("bsfhl"); -+ generate_exception_end(ctx, EXCP_RI); -+ tcg_temp_free(t0); -+ return; -+ } -+ tcg_temp_free(t0); -+} -+ -+/* REV with sf==1, opcode==3 ("REV64") */ -+static void handle_rev64(DisasContext *ctx, -+ unsigned int rn, unsigned int rd) -+{ -+ tcg_gen_bswap64_i64(cpu_gpr[rd], cpu_gpr[rn]); -+} -+ -+/* REV with sf==0, opcode==2 -+ * REV32 (sf==1, opcode==2) -+ */ -+static void handle_rev32(DisasContext *ctx, -+ unsigned int rn, unsigned int rd) -+{ -+ TCGv_i64 tcg_rd = tcg_temp_new_i64(); -+ gen_load_gpr(tcg_rd, rd); -+ -+ TCGv_i64 tcg_tmp = tcg_temp_new_i64(); -+ TCGv_i64 tcg_rn = tcg_temp_new_i64(); -+ gen_load_gpr(tcg_rn, rn); -+ -+ /* bswap32_i64 requires zero high word */ -+ tcg_gen_ext32u_i64(tcg_tmp, tcg_rn); -+ tcg_gen_bswap32_i64(tcg_rd, tcg_tmp, TCG_BSWAP_OZ); -+ tcg_gen_shri_i64(tcg_tmp, tcg_rn, 32); -+ tcg_gen_bswap32_i64(tcg_tmp, tcg_tmp, TCG_BSWAP_OZ); -+ tcg_gen_concat32_i64(cpu_gpr[rd], tcg_rd, tcg_tmp); -+ -+ tcg_temp_free_i64(tcg_tmp); -+ tcg_temp_free_i64(tcg_rd); -+ tcg_temp_free_i64(tcg_rn); -+} -+ -+/* REV16 */ -+static void handle_rev16(DisasContext *ctx, unsigned int rn, unsigned int rd) -+{ -+ TCGv_i64 tcg_rd = tcg_temp_new_i64(); -+ TCGv_i64 tcg_rn = tcg_temp_new_i64(); -+ gen_load_gpr(tcg_rd, rd); -+ gen_load_gpr(tcg_rn, rn); -+ TCGv_i64 tcg_tmp = tcg_temp_new_i64(); -+ TCGv_i64 mask = tcg_const_i64(0x0000ffff0000ffffull); -+ -+ tcg_gen_shri_i64(tcg_tmp, tcg_rn, 16); -+ tcg_gen_and_i64(tcg_rd, tcg_rn, mask); -+ tcg_gen_and_i64(tcg_tmp, tcg_tmp, mask); -+ tcg_gen_shli_i64(tcg_rd, tcg_rd, 16); -+ tcg_gen_or_i64(cpu_gpr[rd], tcg_rd, tcg_tmp); -+ -+ tcg_temp_free_i64(mask); -+ tcg_temp_free_i64(tcg_tmp); -+ tcg_temp_free_i64(tcg_rd); -+ tcg_temp_free_i64(tcg_rn); -+} -+ -+static void gen_lsa(DisasContext *ctx, int opc, int rd, int rs, int rt, -+ int imm2) -+{ -+ TCGv t0; -+ TCGv t1; -+ if (rd == 0) { -+ /* Treat as NOP. */ -+ return; -+ } -+ t0 = tcg_temp_new(); -+ t1 = tcg_temp_new(); -+ gen_load_gpr(t0, rs); -+ gen_load_gpr(t1, rt); -+ tcg_gen_shli_tl(t0, t0, imm2 + 1); -+ tcg_gen_add_tl(cpu_gpr[rd], t0, t1); -+ if (opc == OPC_LARCH_ALSL_W) { -+ tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]); -+ } -+ -+ tcg_temp_free(t1); -+ tcg_temp_free(t0); -+ -+ return; -+} -+ -+static void gen_align_bits(DisasContext *ctx, int wordsz, int rd, int rs, -+ int rt, int bits) -+{ -+ TCGv t0; -+ if (rd == 0) { -+ /* Treat as NOP. */ -+ return; -+ } -+ t0 = tcg_temp_new(); -+ if (bits == 0 || bits == wordsz) { -+ if (bits == 0) { -+ gen_load_gpr(t0, rt); -+ } else { -+ gen_load_gpr(t0, rs); -+ } -+ switch (wordsz) { -+ case 32: -+ tcg_gen_ext32s_tl(cpu_gpr[rd], t0); -+ break; -+ case 64: -+ tcg_gen_mov_tl(cpu_gpr[rd], t0); -+ break; -+ } -+ } else { -+ TCGv t1 = tcg_temp_new(); -+ gen_load_gpr(t0, rt); -+ gen_load_gpr(t1, rs); -+ switch (wordsz) { -+ case 32: -+ { -+ TCGv_i64 t2 = tcg_temp_new_i64(); -+ tcg_gen_concat_tl_i64(t2, t1, t0); -+ tcg_gen_shri_i64(t2, t2, 32 - bits); -+ gen_move_low32(cpu_gpr[rd], t2); -+ tcg_temp_free_i64(t2); -+ } -+ break; -+ case 64: -+ tcg_gen_shli_tl(t0, t0, bits); -+ tcg_gen_shri_tl(t1, t1, 64 - bits); -+ tcg_gen_or_tl(cpu_gpr[rd], t1, t0); -+ break; -+ } -+ tcg_temp_free(t1); -+ } -+ -+ tcg_temp_free(t0); -+} -+ -+static void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt, -+ int bp) -+{ -+ gen_align_bits(ctx, wordsz, rd, rs, rt, bp * 8); -+} -+ -+static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt) -+{ -+ TCGv t0; -+ if (rd == 0) { -+ /* Treat as NOP. */ -+ return; -+ } -+ t0 = tcg_temp_new(); -+ gen_load_gpr(t0, rt); -+ switch (opc) { -+ case OPC_LARCH_BREV_4B: -+ gen_helper_bitswap(cpu_gpr[rd], t0); -+ break; -+ case OPC_LARCH_BREV_8B: -+ gen_helper_dbitswap(cpu_gpr[rd], t0); -+ break; -+ } -+ tcg_temp_free(t0); -+} -+ -+static void gen_cp1(DisasContext *ctx, uint32_t opc, int rt, int fs) -+{ -+ TCGv t0 = tcg_temp_new(); -+ check_cp1_enabled(ctx); -+ -+ switch (opc) { -+ case OPC_LARCH_FR2GR_S: -+ { -+ TCGv_i32 fp0 = tcg_temp_new_i32(); -+ -+ gen_load_fpr32(ctx, fp0, fs); -+ tcg_gen_ext_i32_tl(t0, fp0); -+ tcg_temp_free_i32(fp0); -+ } -+ gen_store_gpr(t0, rt); -+ break; -+ case OPC_LARCH_GR2FR_W: -+ gen_load_gpr(t0, rt); -+ { -+ TCGv_i32 fp0 = tcg_temp_new_i32(); -+ -+ tcg_gen_trunc_tl_i32(fp0, t0); -+ gen_store_fpr32(ctx, fp0, fs); -+ tcg_temp_free_i32(fp0); -+ } -+ break; -+ case OPC_LARCH_FR2GR_D: -+ gen_load_fpr64(ctx, t0, fs); -+ gen_store_gpr(t0, rt); -+ break; -+ case OPC_LARCH_GR2FR_D: -+ gen_load_gpr(t0, rt); -+ gen_store_fpr64(ctx, t0, fs); -+ break; -+ case OPC_LARCH_FRH2GR_S: -+ { -+ TCGv_i32 fp0 = tcg_temp_new_i32(); -+ -+ gen_load_fpr32h(ctx, fp0, fs); -+ tcg_gen_ext_i32_tl(t0, fp0); -+ tcg_temp_free_i32(fp0); -+ } -+ gen_store_gpr(t0, rt); -+ break; -+ case OPC_LARCH_GR2FRH_W: -+ gen_load_gpr(t0, rt); -+ { -+ TCGv_i32 fp0 = tcg_temp_new_i32(); -+ -+ tcg_gen_trunc_tl_i32(fp0, t0); -+ gen_store_fpr32h(ctx, fp0, fs); -+ tcg_temp_free_i32(fp0); -+ } -+ break; -+ default: -+ LARCH_INVAL("cp1 move"); -+ generate_exception_end(ctx, EXCP_RI); -+ goto out; -+ } -+ -+ out: -+ tcg_temp_free(t0); -+} -+ -+static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd, -+ int cc, int tf) -+{ -+ int cond; -+ TCGv_i32 t0 = tcg_temp_new_i32(); -+ TCGLabel *l1 = gen_new_label(); -+ TCGLabel *l2 = gen_new_label(); -+ -+ if (tf) { -+ cond = TCG_COND_EQ; -+ } else { -+ cond = TCG_COND_NE; -+ } -+ -+ tcg_gen_andi_i32(t0, fpu_fcsr0, 1 << get_fp_bit(cc)); -+ tcg_gen_brcondi_i32(cond, t0, 0, l1); -+ gen_load_fpr32(ctx, t0, fs); -+ gen_store_fpr32(ctx, t0, fd); -+ gen_set_label(l1); -+ -+ tcg_gen_andi_i32(t0, fpu_fcsr0, 1 << get_fp_bit(cc + 1)); -+ tcg_gen_brcondi_i32(cond, t0, 0, l2); -+ gen_load_fpr32h(ctx, t0, fs); -+ gen_store_fpr32h(ctx, t0, fd); -+ tcg_temp_free_i32(t0); -+ gen_set_label(l2); -+} -+ -+static void gen_farith(DisasContext *ctx, uint32_t opc, -+ int ft, int fs, int fd, int cc) -+{ -+ check_cp1_enabled(ctx); -+ switch (opc) { -+ case OPC_LARCH_FADD_S: -+ { -+ TCGv_i32 fp0 = tcg_temp_new_i32(); -+ TCGv_i32 fp1 = tcg_temp_new_i32(); -+ -+ gen_load_fpr32(ctx, fp0, fs); -+ gen_load_fpr32(ctx, fp1, ft); -+ gen_helper_float_add_s(fp0, cpu_env, fp0, fp1); -+ tcg_temp_free_i32(fp1); -+ gen_store_fpr32(ctx, fp0, fd); -+ tcg_temp_free_i32(fp0); -+ } -+ break; -+ case OPC_LARCH_FSUB_S: -+ { -+ TCGv_i32 fp0 = tcg_temp_new_i32(); -+ TCGv_i32 fp1 = tcg_temp_new_i32(); -+ -+ gen_load_fpr32(ctx, fp0, fs); -+ gen_load_fpr32(ctx, fp1, ft); -+ gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1); -+ tcg_temp_free_i32(fp1); -+ gen_store_fpr32(ctx, fp0, fd); -+ tcg_temp_free_i32(fp0); -+ } -+ break; -+ case OPC_LARCH_FMUL_S: -+ { -+ TCGv_i32 fp0 = tcg_temp_new_i32(); -+ TCGv_i32 fp1 = tcg_temp_new_i32(); -+ -+ gen_load_fpr32(ctx, fp0, fs); -+ gen_load_fpr32(ctx, fp1, ft); -+ gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1); -+ tcg_temp_free_i32(fp1); -+ gen_store_fpr32(ctx, fp0, fd); -+ tcg_temp_free_i32(fp0); -+ } -+ break; -+ case OPC_LARCH_FDIV_S: -+ { -+ TCGv_i32 fp0 = tcg_temp_new_i32(); -+ TCGv_i32 fp1 = tcg_temp_new_i32(); -+ -+ gen_load_fpr32(ctx, fp0, fs); -+ gen_load_fpr32(ctx, fp1, ft); -+ gen_helper_float_div_s(fp0, cpu_env, fp0, fp1); -+ tcg_temp_free_i32(fp1); -+ gen_store_fpr32(ctx, fp0, fd); -+ tcg_temp_free_i32(fp0); -+ } -+ break; -+ case OPC_LARCH_FSQRT_S: -+ { -+ TCGv_i32 fp0 = tcg_temp_new_i32(); -+ -+ gen_load_fpr32(ctx, fp0, fs); -+ gen_helper_float_sqrt_s(fp0, cpu_env, fp0); -+ gen_store_fpr32(ctx, fp0, fd); -+ tcg_temp_free_i32(fp0); -+ } -+ break; -+ case OPC_LARCH_FABS_S: -+ { -+ TCGv_i32 fp0 = tcg_temp_new_i32(); -+ -+ gen_load_fpr32(ctx, fp0, fs); -+ gen_helper_float_abs_s(fp0, fp0); -+ gen_store_fpr32(ctx, fp0, fd); -+ tcg_temp_free_i32(fp0); -+ } -+ break; -+ case OPC_LARCH_FMOV_S: -+ { -+ TCGv_i32 fp0 = tcg_temp_new_i32(); -+ -+ gen_load_fpr32(ctx, fp0, fs); -+ gen_store_fpr32(ctx, fp0, fd); -+ tcg_temp_free_i32(fp0); -+ } -+ break; -+ case OPC_LARCH_FNEG_S: -+ { -+ TCGv_i32 fp0 = tcg_temp_new_i32(); -+ -+ gen_load_fpr32(ctx, fp0, fs); -+ gen_helper_float_chs_s(fp0, fp0); -+ gen_store_fpr32(ctx, fp0, fd); -+ tcg_temp_free_i32(fp0); -+ } -+ break; -+ case OPC_LARCH_FTINTRNE_L_S: -+ { -+ TCGv_i32 fp32 = tcg_temp_new_i32(); -+ TCGv_i64 fp64 = tcg_temp_new_i64(); -+ -+ gen_load_fpr32(ctx, fp32, fs); -+ gen_helper_float_round_l_s(fp64, cpu_env, fp32); -+ tcg_temp_free_i32(fp32); -+ gen_store_fpr64(ctx, fp64, fd); -+ tcg_temp_free_i64(fp64); -+ } -+ break; -+ case OPC_LARCH_FTINTRZ_L_S: -+ { -+ TCGv_i32 fp32 = tcg_temp_new_i32(); -+ TCGv_i64 fp64 = tcg_temp_new_i64(); -+ -+ gen_load_fpr32(ctx, fp32, fs); -+ gen_helper_float_trunc_l_s(fp64, cpu_env, fp32); -+ tcg_temp_free_i32(fp32); -+ gen_store_fpr64(ctx, fp64, fd); -+ tcg_temp_free_i64(fp64); -+ } -+ break; -+ case OPC_LARCH_FTINTRP_L_S: -+ { -+ TCGv_i32 fp32 = tcg_temp_new_i32(); -+ TCGv_i64 fp64 = tcg_temp_new_i64(); -+ -+ gen_load_fpr32(ctx, fp32, fs); -+ gen_helper_float_ceil_l_s(fp64, cpu_env, fp32); -+ tcg_temp_free_i32(fp32); -+ gen_store_fpr64(ctx, fp64, fd); -+ tcg_temp_free_i64(fp64); -+ } -+ break; -+ case OPC_LARCH_FTINTRM_L_S: -+ { -+ TCGv_i32 fp32 = tcg_temp_new_i32(); -+ TCGv_i64 fp64 = tcg_temp_new_i64(); -+ -+ gen_load_fpr32(ctx, fp32, fs); -+ gen_helper_float_floor_l_s(fp64, cpu_env, fp32); -+ tcg_temp_free_i32(fp32); -+ gen_store_fpr64(ctx, fp64, fd); -+ tcg_temp_free_i64(fp64); -+ } -+ break; -+ case OPC_LARCH_FTINTRNE_W_S: -+ { -+ TCGv_i32 fp0 = tcg_temp_new_i32(); -+ -+ gen_load_fpr32(ctx, fp0, fs); -+ gen_helper_float_round_w_s(fp0, cpu_env, fp0); -+ gen_store_fpr32(ctx, fp0, fd); -+ tcg_temp_free_i32(fp0); -+ } -+ break; -+ case OPC_LARCH_FTINTRZ_W_S: -+ { -+ TCGv_i32 fp0 = tcg_temp_new_i32(); -+ -+ gen_load_fpr32(ctx, fp0, fs); -+ gen_helper_float_trunc_w_s(fp0, cpu_env, fp0); -+ gen_store_fpr32(ctx, fp0, fd); -+ tcg_temp_free_i32(fp0); -+ } -+ break; -+ case OPC_LARCH_FTINTRP_W_S: -+ { -+ TCGv_i32 fp0 = tcg_temp_new_i32(); -+ -+ gen_load_fpr32(ctx, fp0, fs); -+ gen_helper_float_ceil_w_s(fp0, cpu_env, fp0); -+ gen_store_fpr32(ctx, fp0, fd); -+ tcg_temp_free_i32(fp0); -+ } -+ break; -+ case OPC_LARCH_FTINTRM_W_S: -+ { -+ TCGv_i32 fp0 = tcg_temp_new_i32(); -+ -+ gen_load_fpr32(ctx, fp0, fs); -+ gen_helper_float_floor_w_s(fp0, cpu_env, fp0); -+ gen_store_fpr32(ctx, fp0, fd); -+ tcg_temp_free_i32(fp0); -+ } -+ break; -+ case OPC_LARCH_FRECIP_S: -+ { -+ TCGv_i32 fp0 = tcg_temp_new_i32(); -+ -+ gen_load_fpr32(ctx, fp0, fs); -+ gen_helper_float_recip_s(fp0, cpu_env, fp0); -+ gen_store_fpr32(ctx, fp0, fd); -+ tcg_temp_free_i32(fp0); -+ } -+ break; -+ case OPC_LARCH_FRSQRT_S: -+ { -+ TCGv_i32 fp0 = tcg_temp_new_i32(); -+ -+ gen_load_fpr32(ctx, fp0, fs); -+ gen_helper_float_rsqrt_s(fp0, cpu_env, fp0); -+ gen_store_fpr32(ctx, fp0, fd); -+ tcg_temp_free_i32(fp0); -+ } -+ break; -+ case OPC_LARCH_FRINT_S: -+ { -+ TCGv_i32 fp0 = tcg_temp_new_i32(); -+ gen_load_fpr32(ctx, fp0, fs); -+ gen_helper_float_rint_s(fp0, cpu_env, fp0); -+ gen_store_fpr32(ctx, fp0, fd); -+ tcg_temp_free_i32(fp0); -+ } -+ break; -+ case OPC_LARCH_FCLASS_S: -+ { -+ TCGv_i32 fp0 = tcg_temp_new_i32(); -+ gen_load_fpr32(ctx, fp0, fs); -+ gen_helper_float_class_s(fp0, cpu_env, fp0); -+ gen_store_fpr32(ctx, fp0, fd); -+ tcg_temp_free_i32(fp0); -+ } -+ break; -+ case OPC_LARCH_FMIN_S: -+ { -+ TCGv_i32 fp0 = tcg_temp_new_i32(); -+ TCGv_i32 fp1 = tcg_temp_new_i32(); -+ TCGv_i32 fp2 = tcg_temp_new_i32(); -+ gen_load_fpr32(ctx, fp0, fs); -+ gen_load_fpr32(ctx, fp1, ft); -+ gen_helper_float_min_s(fp2, cpu_env, fp0, fp1); -+ gen_store_fpr32(ctx, fp2, fd); -+ tcg_temp_free_i32(fp2); -+ tcg_temp_free_i32(fp1); -+ tcg_temp_free_i32(fp0); -+ } -+ break; -+ case OPC_LARCH_FMINA_S: -+ { -+ TCGv_i32 fp0 = tcg_temp_new_i32(); -+ TCGv_i32 fp1 = tcg_temp_new_i32(); -+ TCGv_i32 fp2 = tcg_temp_new_i32(); -+ gen_load_fpr32(ctx, fp0, fs); -+ gen_load_fpr32(ctx, fp1, ft); -+ gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1); -+ gen_store_fpr32(ctx, fp2, fd); -+ tcg_temp_free_i32(fp2); -+ tcg_temp_free_i32(fp1); -+ tcg_temp_free_i32(fp0); -+ } -+ break; -+ case OPC_LARCH_FMAX_S: -+ { -+ TCGv_i32 fp0 = tcg_temp_new_i32(); -+ TCGv_i32 fp1 = tcg_temp_new_i32(); -+ gen_load_fpr32(ctx, fp0, fs); -+ gen_load_fpr32(ctx, fp1, ft); -+ gen_helper_float_max_s(fp1, cpu_env, fp0, fp1); -+ gen_store_fpr32(ctx, fp1, fd); -+ tcg_temp_free_i32(fp1); -+ tcg_temp_free_i32(fp0); -+ } -+ break; -+ case OPC_LARCH_FMAXA_S: -+ { -+ TCGv_i32 fp0 = tcg_temp_new_i32(); -+ TCGv_i32 fp1 = tcg_temp_new_i32(); -+ gen_load_fpr32(ctx, fp0, fs); -+ gen_load_fpr32(ctx, fp1, ft); -+ gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1); -+ gen_store_fpr32(ctx, fp1, fd); -+ tcg_temp_free_i32(fp1); -+ tcg_temp_free_i32(fp0); -+ } -+ break; -+ case OPC_LARCH_FCVT_D_S: -+ { -+ TCGv_i32 fp32 = tcg_temp_new_i32(); -+ TCGv_i64 fp64 = tcg_temp_new_i64(); -+ -+ gen_load_fpr32(ctx, fp32, fs); -+ gen_helper_float_cvtd_s(fp64, cpu_env, fp32); -+ tcg_temp_free_i32(fp32); -+ gen_store_fpr64(ctx, fp64, fd); -+ tcg_temp_free_i64(fp64); -+ } -+ break; -+ case OPC_LARCH_FTINT_W_S: -+ { -+ TCGv_i32 fp0 = tcg_temp_new_i32(); -+ -+ gen_load_fpr32(ctx, fp0, fs); -+ gen_helper_float_cvt_w_s(fp0, cpu_env, fp0); -+ gen_store_fpr32(ctx, fp0, fd); -+ tcg_temp_free_i32(fp0); -+ } -+ break; -+ case OPC_LARCH_FTINT_L_S: -+ { -+ TCGv_i32 fp32 = tcg_temp_new_i32(); -+ TCGv_i64 fp64 = tcg_temp_new_i64(); -+ -+ gen_load_fpr32(ctx, fp32, fs); -+ gen_helper_float_cvt_l_s(fp64, cpu_env, fp32); -+ tcg_temp_free_i32(fp32); -+ gen_store_fpr64(ctx, fp64, fd); -+ tcg_temp_free_i64(fp64); -+ } -+ break; -+ case OPC_LARCH_FADD_D: -+ { -+ TCGv_i64 fp0 = tcg_temp_new_i64(); -+ TCGv_i64 fp1 = tcg_temp_new_i64(); -+ -+ gen_load_fpr64(ctx, fp0, fs); -+ gen_load_fpr64(ctx, fp1, ft); -+ gen_helper_float_add_d(fp0, cpu_env, fp0, fp1); -+ tcg_temp_free_i64(fp1); -+ gen_store_fpr64(ctx, fp0, fd); -+ tcg_temp_free_i64(fp0); -+ } -+ break; -+ case OPC_LARCH_FSUB_D: -+ { -+ TCGv_i64 fp0 = tcg_temp_new_i64(); -+ TCGv_i64 fp1 = tcg_temp_new_i64(); -+ -+ gen_load_fpr64(ctx, fp0, fs); -+ gen_load_fpr64(ctx, fp1, ft); -+ gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1); -+ tcg_temp_free_i64(fp1); -+ gen_store_fpr64(ctx, fp0, fd); -+ tcg_temp_free_i64(fp0); -+ } -+ break; -+ case OPC_LARCH_FMUL_D: -+ { -+ TCGv_i64 fp0 = tcg_temp_new_i64(); -+ TCGv_i64 fp1 = tcg_temp_new_i64(); -+ -+ gen_load_fpr64(ctx, fp0, fs); -+ gen_load_fpr64(ctx, fp1, ft); -+ gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1); -+ tcg_temp_free_i64(fp1); -+ gen_store_fpr64(ctx, fp0, fd); -+ tcg_temp_free_i64(fp0); -+ } -+ break; -+ case OPC_LARCH_FDIV_D: -+ { -+ TCGv_i64 fp0 = tcg_temp_new_i64(); -+ TCGv_i64 fp1 = tcg_temp_new_i64(); -+ -+ gen_load_fpr64(ctx, fp0, fs); -+ gen_load_fpr64(ctx, fp1, ft); -+ gen_helper_float_div_d(fp0, cpu_env, fp0, fp1); -+ tcg_temp_free_i64(fp1); -+ gen_store_fpr64(ctx, fp0, fd); -+ tcg_temp_free_i64(fp0); -+ } -+ break; -+ case OPC_LARCH_FSQRT_D: -+ { -+ TCGv_i64 fp0 = tcg_temp_new_i64(); -+ -+ gen_load_fpr64(ctx, fp0, fs); -+ gen_helper_float_sqrt_d(fp0, cpu_env, fp0); -+ gen_store_fpr64(ctx, fp0, fd); -+ tcg_temp_free_i64(fp0); -+ } -+ break; -+ case OPC_LARCH_FABS_D: -+ { -+ TCGv_i64 fp0 = tcg_temp_new_i64(); -+ -+ gen_load_fpr64(ctx, fp0, fs); -+ gen_helper_float_abs_d(fp0, fp0); -+ gen_store_fpr64(ctx, fp0, fd); -+ tcg_temp_free_i64(fp0); -+ } -+ break; -+ case OPC_LARCH_FMOV_D: -+ { -+ TCGv_i64 fp0 = tcg_temp_new_i64(); -+ -+ gen_load_fpr64(ctx, fp0, fs); -+ gen_store_fpr64(ctx, fp0, fd); -+ tcg_temp_free_i64(fp0); -+ } -+ break; -+ case OPC_LARCH_FNEG_D: -+ { -+ TCGv_i64 fp0 = tcg_temp_new_i64(); -+ -+ gen_load_fpr64(ctx, fp0, fs); -+ gen_helper_float_chs_d(fp0, fp0); -+ gen_store_fpr64(ctx, fp0, fd); -+ tcg_temp_free_i64(fp0); -+ } -+ break; -+ case OPC_LARCH_FTINTRNE_L_D: -+ { -+ TCGv_i64 fp0 = tcg_temp_new_i64(); -+ -+ gen_load_fpr64(ctx, fp0, fs); -+ gen_helper_float_round_l_d(fp0, cpu_env, fp0); -+ gen_store_fpr64(ctx, fp0, fd); -+ tcg_temp_free_i64(fp0); -+ } -+ break; -+ case OPC_LARCH_FTINTRZ_L_D: -+ { -+ TCGv_i64 fp0 = tcg_temp_new_i64(); -+ -+ gen_load_fpr64(ctx, fp0, fs); -+ gen_helper_float_trunc_l_d(fp0, cpu_env, fp0); -+ gen_store_fpr64(ctx, fp0, fd); -+ tcg_temp_free_i64(fp0); -+ } -+ break; -+ case OPC_LARCH_FTINTRP_L_D: -+ { -+ TCGv_i64 fp0 = tcg_temp_new_i64(); -+ -+ gen_load_fpr64(ctx, fp0, fs); -+ gen_helper_float_ceil_l_d(fp0, cpu_env, fp0); -+ gen_store_fpr64(ctx, fp0, fd); -+ tcg_temp_free_i64(fp0); -+ } -+ break; -+ case OPC_LARCH_FTINTRM_L_D: -+ { -+ TCGv_i64 fp0 = tcg_temp_new_i64(); -+ -+ gen_load_fpr64(ctx, fp0, fs); -+ gen_helper_float_floor_l_d(fp0, cpu_env, fp0); -+ gen_store_fpr64(ctx, fp0, fd); -+ tcg_temp_free_i64(fp0); -+ } -+ break; -+ case OPC_LARCH_FTINTRNE_W_D: -+ { -+ TCGv_i32 fp32 = tcg_temp_new_i32(); -+ TCGv_i64 fp64 = tcg_temp_new_i64(); -+ -+ gen_load_fpr64(ctx, fp64, fs); -+ gen_helper_float_round_w_d(fp32, cpu_env, fp64); -+ tcg_temp_free_i64(fp64); -+ gen_store_fpr32(ctx, fp32, fd); -+ tcg_temp_free_i32(fp32); -+ } -+ break; -+ case OPC_LARCH_FTINTRZ_W_D: -+ { -+ TCGv_i32 fp32 = tcg_temp_new_i32(); -+ TCGv_i64 fp64 = tcg_temp_new_i64(); -+ -+ gen_load_fpr64(ctx, fp64, fs); -+ gen_helper_float_trunc_w_d(fp32, cpu_env, fp64); -+ tcg_temp_free_i64(fp64); -+ gen_store_fpr32(ctx, fp32, fd); -+ tcg_temp_free_i32(fp32); -+ } -+ break; -+ case OPC_LARCH_FTINTRP_W_D: -+ { -+ TCGv_i32 fp32 = tcg_temp_new_i32(); -+ TCGv_i64 fp64 = tcg_temp_new_i64(); -+ -+ gen_load_fpr64(ctx, fp64, fs); -+ gen_helper_float_ceil_w_d(fp32, cpu_env, fp64); -+ tcg_temp_free_i64(fp64); -+ gen_store_fpr32(ctx, fp32, fd); -+ tcg_temp_free_i32(fp32); -+ } -+ break; -+ case OPC_LARCH_FTINTRM_W_D: -+ { -+ TCGv_i32 fp32 = tcg_temp_new_i32(); -+ TCGv_i64 fp64 = tcg_temp_new_i64(); -+ -+ gen_load_fpr64(ctx, fp64, fs); -+ gen_helper_float_floor_w_d(fp32, cpu_env, fp64); -+ tcg_temp_free_i64(fp64); -+ gen_store_fpr32(ctx, fp32, fd); -+ tcg_temp_free_i32(fp32); -+ } -+ break; -+ case OPC_LARCH_FRECIP_D: -+ { -+ TCGv_i64 fp0 = tcg_temp_new_i64(); -+ -+ gen_load_fpr64(ctx, fp0, fs); -+ gen_helper_float_recip_d(fp0, cpu_env, fp0); -+ gen_store_fpr64(ctx, fp0, fd); -+ tcg_temp_free_i64(fp0); -+ } -+ break; -+ case OPC_LARCH_FRSQRT_D: -+ { -+ TCGv_i64 fp0 = tcg_temp_new_i64(); -+ -+ gen_load_fpr64(ctx, fp0, fs); -+ gen_helper_float_rsqrt_d(fp0, cpu_env, fp0); -+ gen_store_fpr64(ctx, fp0, fd); -+ tcg_temp_free_i64(fp0); -+ } -+ break; -+ case OPC_LARCH_FRINT_D: -+ { -+ TCGv_i64 fp0 = tcg_temp_new_i64(); -+ gen_load_fpr64(ctx, fp0, fs); -+ gen_helper_float_rint_d(fp0, cpu_env, fp0); -+ gen_store_fpr64(ctx, fp0, fd); -+ tcg_temp_free_i64(fp0); -+ } -+ break; -+ case OPC_LARCH_FCLASS_D: -+ { -+ TCGv_i64 fp0 = tcg_temp_new_i64(); -+ gen_load_fpr64(ctx, fp0, fs); -+ gen_helper_float_class_d(fp0, cpu_env, fp0); -+ gen_store_fpr64(ctx, fp0, fd); -+ tcg_temp_free_i64(fp0); -+ } -+ break; -+ case OPC_LARCH_FMIN_D: -+ { -+ TCGv_i64 fp0 = tcg_temp_new_i64(); -+ TCGv_i64 fp1 = tcg_temp_new_i64(); -+ gen_load_fpr64(ctx, fp0, fs); -+ gen_load_fpr64(ctx, fp1, ft); -+ gen_helper_float_min_d(fp1, cpu_env, fp0, fp1); -+ gen_store_fpr64(ctx, fp1, fd); -+ tcg_temp_free_i64(fp1); -+ tcg_temp_free_i64(fp0); -+ } -+ break; -+ case OPC_LARCH_FMINA_D: -+ { -+ TCGv_i64 fp0 = tcg_temp_new_i64(); -+ TCGv_i64 fp1 = tcg_temp_new_i64(); -+ gen_load_fpr64(ctx, fp0, fs); -+ gen_load_fpr64(ctx, fp1, ft); -+ gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1); -+ gen_store_fpr64(ctx, fp1, fd); -+ tcg_temp_free_i64(fp1); -+ tcg_temp_free_i64(fp0); -+ } -+ break; -+ case OPC_LARCH_FMAX_D: -+ { -+ TCGv_i64 fp0 = tcg_temp_new_i64(); -+ TCGv_i64 fp1 = tcg_temp_new_i64(); -+ gen_load_fpr64(ctx, fp0, fs); -+ gen_load_fpr64(ctx, fp1, ft); -+ gen_helper_float_max_d(fp1, cpu_env, fp0, fp1); -+ gen_store_fpr64(ctx, fp1, fd); -+ tcg_temp_free_i64(fp1); -+ tcg_temp_free_i64(fp0); -+ } -+ break; -+ case OPC_LARCH_FMAXA_D: -+ { -+ TCGv_i64 fp0 = tcg_temp_new_i64(); -+ TCGv_i64 fp1 = tcg_temp_new_i64(); -+ gen_load_fpr64(ctx, fp0, fs); -+ gen_load_fpr64(ctx, fp1, ft); -+ gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1); -+ gen_store_fpr64(ctx, fp1, fd); -+ tcg_temp_free_i64(fp1); -+ tcg_temp_free_i64(fp0); -+ } -+ break; -+ case OPC_LARCH_FCVT_S_D: -+ { -+ TCGv_i32 fp32 = tcg_temp_new_i32(); -+ TCGv_i64 fp64 = tcg_temp_new_i64(); -+ -+ gen_load_fpr64(ctx, fp64, fs); -+ gen_helper_float_cvts_d(fp32, cpu_env, fp64); -+ tcg_temp_free_i64(fp64); -+ gen_store_fpr32(ctx, fp32, fd); -+ tcg_temp_free_i32(fp32); -+ } -+ break; -+ case OPC_LARCH_FTINT_W_D: -+ { -+ TCGv_i32 fp32 = tcg_temp_new_i32(); -+ TCGv_i64 fp64 = tcg_temp_new_i64(); -+ -+ gen_load_fpr64(ctx, fp64, fs); -+ gen_helper_float_cvt_w_d(fp32, cpu_env, fp64); -+ tcg_temp_free_i64(fp64); -+ gen_store_fpr32(ctx, fp32, fd); -+ tcg_temp_free_i32(fp32); -+ } -+ break; -+ case OPC_LARCH_FTINT_L_D: -+ { -+ TCGv_i64 fp0 = tcg_temp_new_i64(); -+ -+ gen_load_fpr64(ctx, fp0, fs); -+ gen_helper_float_cvt_l_d(fp0, cpu_env, fp0); -+ gen_store_fpr64(ctx, fp0, fd); -+ tcg_temp_free_i64(fp0); -+ } -+ break; -+ case OPC_LARCH_FFINT_S_W: -+ { -+ TCGv_i32 fp0 = tcg_temp_new_i32(); -+ -+ gen_load_fpr32(ctx, fp0, fs); -+ gen_helper_float_cvts_w(fp0, cpu_env, fp0); -+ gen_store_fpr32(ctx, fp0, fd); -+ tcg_temp_free_i32(fp0); -+ } -+ break; -+ case OPC_LARCH_FFINT_D_W: -+ { -+ TCGv_i32 fp32 = tcg_temp_new_i32(); -+ TCGv_i64 fp64 = tcg_temp_new_i64(); -+ -+ gen_load_fpr32(ctx, fp32, fs); -+ gen_helper_float_cvtd_w(fp64, cpu_env, fp32); -+ tcg_temp_free_i32(fp32); -+ gen_store_fpr64(ctx, fp64, fd); -+ tcg_temp_free_i64(fp64); -+ } -+ break; -+ case OPC_LARCH_FFINT_S_L: -+ { -+ TCGv_i32 fp32 = tcg_temp_new_i32(); -+ TCGv_i64 fp64 = tcg_temp_new_i64(); -+ -+ gen_load_fpr64(ctx, fp64, fs); -+ gen_helper_float_cvts_l(fp32, cpu_env, fp64); -+ tcg_temp_free_i64(fp64); -+ gen_store_fpr32(ctx, fp32, fd); -+ tcg_temp_free_i32(fp32); -+ } -+ break; -+ case OPC_LARCH_FFINT_D_L: -+ { -+ TCGv_i64 fp0 = tcg_temp_new_i64(); -+ -+ gen_load_fpr64(ctx, fp0, fs); -+ gen_helper_float_cvtd_l(fp0, cpu_env, fp0); -+ gen_store_fpr64(ctx, fp0, fd); -+ tcg_temp_free_i64(fp0); -+ } -+ break; -+ default: -+ LARCH_INVAL("farith"); -+ generate_exception_end(ctx, EXCP_RI); -+ return; -+ } -+} -+ -+/* Coprocessor 3 (FPU) */ -+static void gen_flt3_ldst(DisasContext *ctx, uint32_t opc, -+ int fd, int fs, int base, int index) -+{ -+ TCGv t0 = tcg_temp_new(); -+ -+ check_cp1_enabled(ctx); -+ if (base == 0) { -+ gen_load_gpr(t0, index); -+ } else if (index == 0) { -+ gen_load_gpr(t0, base); -+ } else { -+ gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]); -+ } -+ -+ /* -+ * Don't do NOP if destination is zero: we must perform the actual -+ * memory access. -+ */ -+ switch (opc) { -+ case OPC_LARCH_FLDX_S: -+ case OPC_LARCH_FLDGT_S: -+ case OPC_LARCH_FLDLE_S: -+ { -+ TCGv_i32 fp0 = tcg_temp_new_i32(); -+ -+ tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL); -+ tcg_gen_trunc_tl_i32(fp0, t0); -+ gen_store_fpr32(ctx, fp0, fd); -+ tcg_temp_free_i32(fp0); -+ } -+ break; -+ case OPC_LARCH_FLDX_D: -+ case OPC_LARCH_FLDGT_D: -+ case OPC_LARCH_FLDLE_D: -+ { -+ TCGv_i64 fp0 = tcg_temp_new_i64(); -+ tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ); -+ gen_store_fpr64(ctx, fp0, fd); -+ tcg_temp_free_i64(fp0); -+ } -+ break; -+ case OPC_LARCH_FSTX_S: -+ case OPC_LARCH_FSTGT_S: -+ case OPC_LARCH_FSTLE_S: -+ { -+ TCGv_i32 fp0 = tcg_temp_new_i32(); -+ gen_load_fpr32(ctx, fp0, fs); -+ tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL); -+ tcg_temp_free_i32(fp0); -+ } -+ break; -+ case OPC_LARCH_FSTX_D: -+ case OPC_LARCH_FSTGT_D: -+ case OPC_LARCH_FSTLE_D: -+ { -+ TCGv_i64 fp0 = tcg_temp_new_i64(); -+ gen_load_fpr64(ctx, fp0, fs); -+ tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ); -+ tcg_temp_free_i64(fp0); -+ } -+ break; -+ } -+ tcg_temp_free(t0); -+} -+ -+static inline void clear_branch_hflags(DisasContext *ctx) -+{ -+ ctx->hflags &= ~LARCH_HFLAG_BMASK; -+ if (ctx->base.is_jmp == DISAS_NEXT) { -+ save_cpu_state(ctx, 0); -+ } else { -+ /* -+ * It is not safe to save ctx->hflags as hflags may be changed -+ * in execution time. -+ */ -+ tcg_gen_andi_i32(hflags, hflags, ~LARCH_HFLAG_BMASK); -+ } -+} -+ -+static void gen_branch(DisasContext *ctx, int insn_bytes) -+{ -+ if (ctx->hflags & LARCH_HFLAG_BMASK) { -+ int proc_hflags = ctx->hflags & LARCH_HFLAG_BMASK; -+ /* Branches completion */ -+ clear_branch_hflags(ctx); -+ ctx->base.is_jmp = DISAS_NORETURN; -+ /* FIXME: Need to clear can_do_io. */ -+ switch (proc_hflags & LARCH_HFLAG_BMASK) { -+ case LARCH_HFLAG_B: -+ /* unconditional branch */ -+ gen_goto_tb(ctx, 0, ctx->btarget); -+ break; -+ case LARCH_HFLAG_BC: -+ /* Conditional branch */ -+ { -+ TCGLabel *l1 = gen_new_label(); -+ -+ tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1); -+ gen_goto_tb(ctx, 1, ctx->base.pc_next + insn_bytes); -+ gen_set_label(l1); -+ gen_goto_tb(ctx, 0, ctx->btarget); -+ } -+ break; -+ case LARCH_HFLAG_BR: -+ /* unconditional branch to register */ -+ tcg_gen_mov_tl(cpu_PC, btarget); -+ if (ctx->base.singlestep_enabled) { -+ save_cpu_state(ctx, 0); -+ gen_helper_raise_exception_debug(cpu_env); -+ } -+ tcg_gen_lookup_and_goto_ptr(); -+ break; -+ default: -+ fprintf(stderr, "unknown branch 0x%x\n", proc_hflags); -+ abort(); -+ } -+ } -+} -+ -+/* Signed immediate */ -+#define SIMM(op, start, width) \ -+ ((int32_t)(((op >> start) & ((~0U) >> (32 - width))) \ -+ << (32 - width)) \ -+ >> (32 - width)) -+/* Zero-extended immediate */ -+#define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32 - width))) -+ -+static void gen_sync(int stype) -+{ -+ TCGBar tcg_mo = TCG_BAR_SC; -+ -+ switch (stype) { -+ case 0x4: /* SYNC_WMB */ -+ tcg_mo |= TCG_MO_ST_ST; -+ break; -+ case 0x10: /* SYNC_MB */ -+ tcg_mo |= TCG_MO_ALL; -+ break; -+ case 0x11: /* SYNC_ACQUIRE */ -+ tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST; -+ break; -+ case 0x12: /* SYNC_RELEASE */ -+ tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST; -+ break; -+ case 0x13: /* SYNC_RMB */ -+ tcg_mo |= TCG_MO_LD_LD; -+ break; -+ default: -+ tcg_mo |= TCG_MO_ALL; -+ break; -+ } -+ -+ tcg_gen_mb(tcg_mo); -+} -+ -+static void gen_crc32(DisasContext *ctx, int rd, int rs, int rt, int sz, -+ int crc32c) -+{ -+ TCGv t0; -+ TCGv t1; -+ TCGv_i32 tsz = tcg_const_i32(1 << sz); -+ if (rd == 0) { -+ /* Treat as NOP. */ -+ return; -+ } -+ t0 = tcg_temp_new(); -+ t1 = tcg_temp_new(); -+ -+ gen_load_gpr(t0, rt); -+ gen_load_gpr(t1, rs); -+ -+ if (crc32c) { -+ gen_helper_crc32c(cpu_gpr[rd], t0, t1, tsz); -+ } else { -+ gen_helper_crc32(cpu_gpr[rd], t0, t1, tsz); -+ } -+ -+ tcg_temp_free(t0); -+ tcg_temp_free(t1); -+ tcg_temp_free_i32(tsz); -+} -+ -+#include "cpu-csr.h" -+ -+#ifndef CONFIG_USER_ONLY -+ -+/* -+ * 64-bit CSR read -+ * -+ * @arg : GPR to store the value of CSR register -+ * @csr : CSR register number -+ */ -+static void gen_csr_rdq(DisasContext *ctx, TCGv rd, int64_t a1) -+{ -+ TCGv_i64 csr = tcg_const_i64(a1); -+ gen_helper_csr_rdq(rd, cpu_env, csr); -+} -+ -+/* -+ * 64-bit CSR write -+ * -+ * @arg : GPR that stores the new value of CSR register -+ * @csr : CSR register number -+ */ -+static void gen_csr_wrq(DisasContext *ctx, TCGv val, int64_t a1) -+{ -+ TCGv_i64 csr = tcg_const_i64(a1); -+ gen_helper_csr_wrq(val, cpu_env, val, csr); -+} -+ -+/* -+ * 64-bit CSR exchange -+ * -+ * @arg : GPR that stores the new value of CSR register -+ * @csr : CSR register number -+ */ -+static void gen_csr_xchgq(DisasContext *ctx, TCGv val, TCGv mask, int64_t a1) -+{ -+ TCGv_i64 csr = tcg_const_i64(a1); -+ gen_helper_csr_xchgq(val, cpu_env, val, mask, csr); -+} -+#endif /* !CONFIG_USER_ONLY */ -+ -+static void loongarch_tr_init_disas_context(DisasContextBase *dcbase, -+ CPUState *cs) -+{ -+ DisasContext *ctx = container_of(dcbase, DisasContext, base); -+ CPULOONGARCHState *env = cs->env_ptr; -+ -+ ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK; -+ ctx->saved_pc = -1; -+ ctx->insn_flags = env->insn_flags; -+ ctx->btarget = 0; -+ /* Restore state from the tb context. */ -+ ctx->hflags = (uint32_t)ctx->base.tb->flags; /* FIXME: maybe use 64 bits? */ -+ restore_cpu_state(env, ctx); -+#ifdef CONFIG_USER_ONLY -+ ctx->mem_idx = LARCH_HFLAG_UM; -+#else -+ ctx->mem_idx = hflags_mmu_index(ctx->hflags); -+#endif -+ ctx->default_tcg_memop_mask = MO_ALIGN; -+ -+ LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx, -+ ctx->hflags); -+} -+ -+static void loongarch_tr_tb_start(DisasContextBase *dcbase, CPUState *cs) -+{ -+} -+ -+static void loongarch_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) -+{ -+ DisasContext *ctx = container_of(dcbase, DisasContext, base); -+ -+ tcg_gen_insn_start(ctx->base.pc_next, ctx->hflags & LARCH_HFLAG_BMASK, -+ ctx->btarget); -+} -+#if 0 -+static bool loongarch_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs, -+ const CPUBreakpoint *bp) -+{ -+ DisasContext *ctx = container_of(dcbase, DisasContext, base); -+ -+ save_cpu_state(ctx, 1); -+ ctx->base.is_jmp = DISAS_NORETURN; -+ gen_helper_raise_exception_debug(cpu_env); -+ /* The address covered by the breakpoint must be included in -+ [tb->pc, tb->pc + tb->size) in order to for it to be -+ properly cleared -- thus we increment the PC here so that -+ the logic setting tb->size below does the right thing. */ -+ ctx->base.pc_next += 4; -+ return true; -+} -+#endif -+/* 128 and 256 lsx vector instructions are not supported yet */ -+static bool decode_vector_lsx(uint32_t opcode) -+{ -+ uint32_t value = (opcode & 0xff000000); -+ -+ if ((opcode & 0xf0000000) == 0x70000000) { -+ return true; -+ } else if ((opcode & 0xfff00000) == 0x38400000) { -+ return true; -+ } else { -+ switch (value) { -+ case 0x09000000: -+ case 0x0a000000: -+ case 0x0e000000: -+ case 0x0f000000: -+ case 0x2c000000: -+ case 0x30000000: -+ case 0x31000000: -+ case 0x32000000: -+ case 0x33000000: -+ return true; -+ } -+ } -+ return false; -+} -+ -+static bool decode_insn(DisasContext *ctx, uint32_t insn); -+#include "decode-insn.c.inc" -+#include "trans.inc.c" -+ -+static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) -+{ -+ CPULOONGARCHState *env = cs->env_ptr; -+ DisasContext *ctx = container_of(dcbase, DisasContext, base); -+ int insn_bytes = 4; -+ -+ ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next); -+ -+ if (!decode_insn(ctx, ctx->opcode)) { -+ if (decode_vector_lsx(ctx->opcode)) { -+ generate_exception_end(ctx, EXCP_RI); -+ } else { -+ fprintf(stderr, "Error: unkown opcode. 0x%lx: 0x%x\n", -+ ctx->base.pc_next, ctx->opcode); -+ generate_exception_end(ctx, EXCP_RI); -+ } -+ } -+ -+ if (ctx->hflags & LARCH_HFLAG_BMASK) { -+ gen_branch(ctx, insn_bytes); -+ } -+ ctx->base.pc_next += insn_bytes; -+} -+ -+static void loongarch_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs) -+{ -+ DisasContext *ctx = container_of(dcbase, DisasContext, base); -+ -+ if (ctx->base.singlestep_enabled && ctx->base.is_jmp != DISAS_NORETURN) { -+ save_cpu_state(ctx, ctx->base.is_jmp != DISAS_EXIT); -+ gen_helper_raise_exception_debug(cpu_env); -+ } else { -+ switch (ctx->base.is_jmp) { -+ case DISAS_STOP: -+ gen_save_pc(ctx->base.pc_next); -+ tcg_gen_lookup_and_goto_ptr(); -+ break; -+ case DISAS_NEXT: -+ case DISAS_TOO_MANY: -+ save_cpu_state(ctx, 0); -+ gen_goto_tb(ctx, 0, ctx->base.pc_next); -+ break; -+ case DISAS_EXIT: -+ tcg_gen_exit_tb(NULL, 0); -+ break; -+ case DISAS_NORETURN: -+ break; -+ default: -+ g_assert_not_reached(); -+ } -+ } -+} -+ -+static void loongarch_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs) -+{ -+ qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first)); -+ log_target_disas(cs, dcbase->pc_first, dcbase->tb->size); -+} -+ -+static const TranslatorOps loongarch_tr_ops = { -+ .init_disas_context = loongarch_tr_init_disas_context, -+ .tb_start = loongarch_tr_tb_start, -+ .insn_start = loongarch_tr_insn_start, -+#if 0 -+ .breakpoint_check = loongarch_tr_breakpoint_check, -+#endif -+ .translate_insn = loongarch_tr_translate_insn, -+ .tb_stop = loongarch_tr_tb_stop, -+ .disas_log = loongarch_tr_disas_log, -+}; -+ -+void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb, int max_insns) -+{ -+ DisasContext ctx; -+ -+ translator_loop(&loongarch_tr_ops, &ctx.base, cs, tb, max_insns); -+} -+ -+void loongarch_tcg_init(void) -+{ -+ int i; -+ -+ for (i = 0; i < 32; i++) -+ cpu_gpr[i] = tcg_global_mem_new(cpu_env, -+ offsetof(CPULOONGARCHState, -+ active_tc.gpr[i]), -+ regnames[i]); -+ -+ for (i = 0; i < 32; i++) { -+ int off = offsetof(CPULOONGARCHState, active_fpu.fpr[i].d); -+ fpu_f64[i] = tcg_global_mem_new_i64(cpu_env, off, fregnames[i]); -+ } -+ -+ cpu_PC = tcg_global_mem_new(cpu_env, -+ offsetof(CPULOONGARCHState, active_tc.PC), "PC"); -+ bcond = tcg_global_mem_new(cpu_env, -+ offsetof(CPULOONGARCHState, bcond), "bcond"); -+ btarget = tcg_global_mem_new(cpu_env, -+ offsetof(CPULOONGARCHState, btarget), "btarget"); -+ hflags = tcg_global_mem_new_i32(cpu_env, -+ offsetof(CPULOONGARCHState, hflags), "hflags"); -+ fpu_fcsr0 = tcg_global_mem_new_i32(cpu_env, -+ offsetof(CPULOONGARCHState, active_fpu.fcsr0), -+ "fcsr0"); -+ cpu_lladdr = tcg_global_mem_new(cpu_env, -+ offsetof(CPULOONGARCHState, lladdr), -+ "lladdr"); -+ cpu_llval = tcg_global_mem_new(cpu_env, offsetof(CPULOONGARCHState, llval), -+ "llval"); -+} -+ -+void restore_state_to_opc(CPULOONGARCHState *env, TranslationBlock *tb, -+ target_ulong *data) -+{ -+ env->active_tc.PC = data[0]; -+ env->hflags &= ~LARCH_HFLAG_BMASK; -+ env->hflags |= data[1]; -+ switch (env->hflags & LARCH_HFLAG_BMASK) { -+ case LARCH_HFLAG_BR: -+ break; -+ case LARCH_HFLAG_BC: -+ case LARCH_HFLAG_B: -+ env->btarget = data[2]; -+ break; -+ } -+} -diff --git a/target/meson.build b/target/meson.build -index 2f6940255e..ac0ce618b7 100644 ---- a/target/meson.build -+++ b/target/meson.build -@@ -5,6 +5,7 @@ subdir('cris') - subdir('hexagon') - subdir('hppa') - subdir('i386') -+subdir('loongarch64') - subdir('m68k') - subdir('microblaze') - subdir('mips') --- -2.27.0 - diff --git a/0005-Add-linux-headers-and-linux-user.patch b/0005-Add-linux-headers-and-linux-user.patch deleted file mode 100644 index 93ba8ed..0000000 --- a/0005-Add-linux-headers-and-linux-user.patch +++ /dev/null @@ -1,1663 +0,0 @@ -From 0d21e423fc15e8e2e2fdc910a7e94e051427f230 Mon Sep 17 00:00:00 2001 -From: lixianglai -Date: Fri, 19 Aug 2022 23:47:06 -0400 -Subject: [PATCH 5/8] Add linux-headers and linux-user. - -Change-Id: If052442a981fed87c03ca431c010629dc8e872ca -Signed-off-by: lixianglai ---- - linux-headers/asm-loongarch64/bitsperlong.h | 9 + - linux-headers/asm-loongarch64/kvm.h | 346 ++++++++++++++++++++ - linux-headers/asm-loongarch64/sgidefs.h | 20 ++ - linux-headers/asm-loongarch64/unistd.h | 23 ++ - linux-user/loongarch64/cpu_loop.c | 193 +++++++++++ - linux-user/loongarch64/meson.build | 6 + - linux-user/loongarch64/signal.c | 212 ++++++++++++ - linux-user/loongarch64/sockbits.h | 1 + - linux-user/loongarch64/syscall_nr.h | 287 ++++++++++++++++ - linux-user/loongarch64/target_cpu.h | 45 +++ - linux-user/loongarch64/target_elf.h | 14 + - linux-user/loongarch64/target_fcntl.h | 13 + - linux-user/loongarch64/target_signal.h | 23 ++ - linux-user/loongarch64/target_structs.h | 62 ++++ - linux-user/loongarch64/target_syscall.h | 44 +++ - linux-user/loongarch64/termbits.h | 224 +++++++++++++ - 16 files changed, 1522 insertions(+) - create mode 100644 linux-headers/asm-loongarch64/bitsperlong.h - create mode 100644 linux-headers/asm-loongarch64/kvm.h - create mode 100644 linux-headers/asm-loongarch64/sgidefs.h - create mode 100644 linux-headers/asm-loongarch64/unistd.h - create mode 100644 linux-user/loongarch64/cpu_loop.c - create mode 100644 linux-user/loongarch64/meson.build - create mode 100644 linux-user/loongarch64/signal.c - create mode 100644 linux-user/loongarch64/sockbits.h - create mode 100644 linux-user/loongarch64/syscall_nr.h - create mode 100644 linux-user/loongarch64/target_cpu.h - create mode 100644 linux-user/loongarch64/target_elf.h - create mode 100644 linux-user/loongarch64/target_fcntl.h - create mode 100644 linux-user/loongarch64/target_signal.h - create mode 100644 linux-user/loongarch64/target_structs.h - create mode 100644 linux-user/loongarch64/target_syscall.h - create mode 100644 linux-user/loongarch64/termbits.h - -diff --git a/linux-headers/asm-loongarch64/bitsperlong.h b/linux-headers/asm-loongarch64/bitsperlong.h -new file mode 100644 -index 0000000000..5c2c8779a6 ---- /dev/null -+++ b/linux-headers/asm-loongarch64/bitsperlong.h -@@ -0,0 +1,9 @@ -+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -+#ifndef __ASM_LOONGARCH_BITSPERLONG_H -+#define __ASM_LOONGARCH_BITSPERLONG_H -+ -+#define __BITS_PER_LONG _LOONGARCH_SZLONG -+ -+#include -+ -+#endif /* __ASM_LOONGARCH_BITSPERLONG_H */ -diff --git a/linux-headers/asm-loongarch64/kvm.h b/linux-headers/asm-loongarch64/kvm.h -new file mode 100644 -index 0000000000..a24375ee59 ---- /dev/null -+++ b/linux-headers/asm-loongarch64/kvm.h -@@ -0,0 +1,346 @@ -+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -+/* -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file "COPYING" in the main directory of this archive -+ * for more details. -+ * -+ * Copyright (C) 2020 Loongson Technologies, Inc. All rights reserved. -+ * Authors: Sanjay Lal -+ * Authors: Xing Li -+ */ -+ -+#ifndef __LINUX_KVM_LOONGARCH_H -+#define __LINUX_KVM_LOONGARCH_H -+ -+#include -+ -+#define __KVM_HAVE_GUEST_DEBUG -+#define KVM_GUESTDBG_USE_SW_BP 0x00010000 -+#define KVM_GUESTDBG_USE_HW_BP 0x00020000 -+#define KVM_DATA_HW_BREAKPOINT_NUM 8 -+#define KVM_INST_HW_BREAKPOINT_NUM 8 -+ -+/* -+ * KVM Loongarch specific structures and definitions. -+ * -+ * Some parts derived from the x86 version of this file. -+ */ -+ -+#define __KVM_HAVE_READONLY_MEM -+ -+#define KVM_COALESCED_MMIO_PAGE_OFFSET 1 -+ -+#define KVM_LARCH_VCPU_PVTIME_CTRL 2 -+#define KVM_LARCH_VCPU_PVTIME_IPA 0 -+ -+/* -+ * for KVM_GET_REGS and KVM_SET_REGS -+ */ -+struct kvm_regs { -+ /* out (KVM_GET_REGS) / in (KVM_SET_REGS) */ -+ __u64 gpr[32]; -+ __u64 pc; -+}; -+ -+/* -+ * for KVM_GET_CPUCFG -+ */ -+struct kvm_cpucfg { -+ /* out (KVM_GET_CPUCFG) */ -+ __u32 cpucfg[64]; -+}; -+ -+/* -+ * for KVM_GET_FPU and KVM_SET_FPU -+ */ -+struct kvm_fpu { -+ __u32 fcsr; -+ __u32 vcsr; -+ __u64 fcc; /* 8x8 */ -+ struct kvm_fpureg { -+ __u64 val64[4]; //support max 256 bits -+ }fpr[32]; -+}; -+ -+/* -+ * For LOONGARCH, we use KVM_SET_ONE_REG and KVM_GET_ONE_REG to access various -+ * registers. The id field is broken down as follows: -+ * -+ * bits[63..52] - As per linux/kvm.h -+ * bits[51..32] - Must be zero. -+ * bits[31..16] - Register set. -+ * -+ * Register set = 0: GP registers from kvm_regs (see definitions below). -+ * -+ * Register set = 1: CP0 registers. -+ * bits[15..8] - COP0 register set. -+ * -+ * COP0 register set = 0: Main CP0 registers. -+ * bits[7..3] - Register 'rd' index. -+ * bits[2..0] - Register 'sel' index. -+ * -+ * COP0 register set = 1: MAARs. -+ * bits[7..0] - MAAR index. -+ * -+ * Register set = 2: KVM specific registers (see definitions below). -+ * -+ * Register set = 3: FPU / MSA registers (see definitions below). -+ * -+ * Other sets registers may be added in the future. Each set would -+ * have its own identifier in bits[31..16]. -+ */ -+ -+#define KVM_REG_LOONGARCH_GP (KVM_REG_LOONGARCH | 0x0000000000000000ULL) -+#define KVM_REG_LOONGARCH_CSR (KVM_REG_LOONGARCH | 0x0000000000010000ULL) -+#define KVM_REG_LOONGARCH_KVM (KVM_REG_LOONGARCH | 0x0000000000020000ULL) -+#define KVM_REG_LOONGARCH_FPU (KVM_REG_LOONGARCH | 0x0000000000030000ULL) -+ -+ -+/* -+ * KVM_REG_LOONGARCH_GP - General purpose registers from kvm_regs. -+ */ -+ -+#define KVM_REG_LOONGARCH_R0 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 0) -+#define KVM_REG_LOONGARCH_R1 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 1) -+#define KVM_REG_LOONGARCH_R2 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 2) -+#define KVM_REG_LOONGARCH_R3 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 3) -+#define KVM_REG_LOONGARCH_R4 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 4) -+#define KVM_REG_LOONGARCH_R5 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 5) -+#define KVM_REG_LOONGARCH_R6 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 6) -+#define KVM_REG_LOONGARCH_R7 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 7) -+#define KVM_REG_LOONGARCH_R8 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 8) -+#define KVM_REG_LOONGARCH_R9 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 9) -+#define KVM_REG_LOONGARCH_R10 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 10) -+#define KVM_REG_LOONGARCH_R11 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 11) -+#define KVM_REG_LOONGARCH_R12 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 12) -+#define KVM_REG_LOONGARCH_R13 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 13) -+#define KVM_REG_LOONGARCH_R14 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 14) -+#define KVM_REG_LOONGARCH_R15 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 15) -+#define KVM_REG_LOONGARCH_R16 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 16) -+#define KVM_REG_LOONGARCH_R17 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 17) -+#define KVM_REG_LOONGARCH_R18 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 18) -+#define KVM_REG_LOONGARCH_R19 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 19) -+#define KVM_REG_LOONGARCH_R20 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 20) -+#define KVM_REG_LOONGARCH_R21 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 21) -+#define KVM_REG_LOONGARCH_R22 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 22) -+#define KVM_REG_LOONGARCH_R23 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 23) -+#define KVM_REG_LOONGARCH_R24 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 24) -+#define KVM_REG_LOONGARCH_R25 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 25) -+#define KVM_REG_LOONGARCH_R26 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 26) -+#define KVM_REG_LOONGARCH_R27 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 27) -+#define KVM_REG_LOONGARCH_R28 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 28) -+#define KVM_REG_LOONGARCH_R29 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 29) -+#define KVM_REG_LOONGARCH_R30 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 30) -+#define KVM_REG_LOONGARCH_R31 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 31) -+ -+#define KVM_REG_LOONGARCH_HI (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 32) -+#define KVM_REG_LOONGARCH_LO (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 33) -+#define KVM_REG_LOONGARCH_PC (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 34) -+ -+ -+/* -+ * KVM_REG_LOONGARCH_KVM - KVM specific control registers. -+ */ -+ -+/* -+ * CP0_Count control -+ * DC: Set 0: Master disable CP0_Count and set COUNT_RESUME to now -+ * Set 1: Master re-enable CP0_Count with unchanged bias, handling timer -+ * interrupts since COUNT_RESUME -+ * This can be used to freeze the timer to get a consistent snapshot of -+ * the CP0_Count and timer interrupt pending state, while also resuming -+ * safely without losing time or guest timer interrupts. -+ * Other: Reserved, do not change. -+ */ -+#define KVM_REG_LOONGARCH_COUNT_CTL (KVM_REG_LOONGARCH_KVM | KVM_REG_SIZE_U64 | 0) -+#define KVM_REG_LOONGARCH_COUNT_CTL_DC 0x00000001 -+ -+/* -+ * CP0_Count resume monotonic nanoseconds -+ * The monotonic nanosecond time of the last set of COUNT_CTL.DC (master -+ * disable). Any reads and writes of Count related registers while -+ * COUNT_CTL.DC=1 will appear to occur at this time. When COUNT_CTL.DC is -+ * cleared again (master enable) any timer interrupts since this time will be -+ * emulated. -+ * Modifications to times in the future are rejected. -+ */ -+#define KVM_REG_LOONGARCH_COUNT_RESUME (KVM_REG_LOONGARCH_KVM | KVM_REG_SIZE_U64 | 1) -+/* -+ * CP0_Count rate in Hz -+ * Specifies the rate of the CP0_Count timer in Hz. Modifications occur without -+ * discontinuities in CP0_Count. -+ */ -+#define KVM_REG_LOONGARCH_COUNT_HZ (KVM_REG_LOONGARCH_KVM | KVM_REG_SIZE_U64 | 2) -+ -+#define KVM_REG_LOONGARCH_COUNTER (KVM_REG_LOONGARCH_KVM | KVM_REG_SIZE_U64 | 3) -+ -+#define KVM_REG_LOONGARCH_VCPU_RESET (KVM_REG_LOONGARCH_KVM | KVM_REG_SIZE_U64 | 4) -+ -+struct kvm_iocsr_entry { -+ __u32 addr; -+ __u32 pad; -+ __u64 data; -+}; -+ -+struct kvm_csr_entry { -+ __u32 index; -+ __u32 reserved; -+ __u64 data; -+}; -+ -+/* for KVM_GET_MSRS and KVM_SET_MSRS */ -+struct kvm_msrs { -+ __u32 ncsrs; /* number of msrs in entries */ -+ __u32 pad; -+ struct kvm_csr_entry entries[0]; -+}; -+ -+#define __KVM_HAVE_IRQ_LINE -+ -+struct kvm_debug_exit_arch { -+ __u64 epc; -+ __u32 fwps; -+ __u32 mwps; -+ __u32 exception; -+}; -+ -+/* for KVM_SET_GUEST_DEBUG */ -+struct hw_breakpoint { -+ __u64 addr; -+ __u64 mask; -+ __u32 asid; -+ __u32 ctrl; -+}; -+ -+struct kvm_guest_debug_arch { -+ struct hw_breakpoint data_breakpoint[KVM_DATA_HW_BREAKPOINT_NUM]; -+ struct hw_breakpoint inst_breakpoint[KVM_INST_HW_BREAKPOINT_NUM]; -+ int inst_bp_nums, data_bp_nums; -+}; -+ -+/* definition of registers in kvm_run */ -+struct kvm_sync_regs { -+}; -+ -+/* dummy definition */ -+struct kvm_sregs { -+}; -+ -+struct kvm_loongarch_interrupt { -+ /* in */ -+ __u32 cpu; -+ __u32 irq; -+}; -+ -+#define KVM_IRQCHIP_LS7A_IOAPIC 0x0 -+#define KVM_IRQCHIP_LS3A_GIPI 0x1 -+#define KVM_IRQCHIP_LS3A_HT_IRQ 0x2 -+#define KVM_IRQCHIP_LS3A_ROUTE 0x3 -+#define KVM_IRQCHIP_LS3A_EXTIRQ 0x4 -+#define KVM_IRQCHIP_LS3A_IPMASK 0x5 -+#define KVM_NR_IRQCHIPS 1 -+#define KVM_IRQCHIP_NUM_PINS 64 -+ -+#define KVM_MAX_CORES 256 -+#define KVM_EXTIOI_IRQS (256) -+#define KVM_EXTIOI_IRQS_BITMAP_SIZE (KVM_EXTIOI_IRQS / 8) -+/* map to ipnum per 32 irqs */ -+#define KVM_EXTIOI_IRQS_IPMAP_SIZE (KVM_EXTIOI_IRQS / 32) -+#define KVM_EXTIOI_IRQS_PER_GROUP 32 -+#define KVM_EXTIOI_IRQS_COREMAP_SIZE (KVM_EXTIOI_IRQS) -+#define KVM_EXTIOI_IRQS_NODETYPE_SIZE 16 -+ -+struct ls7a_ioapic_state { -+ __u64 int_id; -+ /* 0x020 interrupt mask register */ -+ __u64 int_mask; -+ /* 0x040 1=msi */ -+ __u64 htmsi_en; -+ /* 0x060 edge=1 level =0 */ -+ __u64 intedge; -+ /* 0x080 for clean edge int,set 1 clean,set 0 is noused */ -+ __u64 intclr; -+ /* 0x0c0 */ -+ __u64 auto_crtl0; -+ /* 0x0e0 */ -+ __u64 auto_crtl1; -+ /* 0x100 - 0x140 */ -+ __u8 route_entry[64]; -+ /* 0x200 - 0x240 */ -+ __u8 htmsi_vector[64]; -+ /* 0x300 */ -+ __u64 intisr_chip0; -+ /* 0x320 */ -+ __u64 intisr_chip1; -+ /* edge detection */ -+ __u64 last_intirr; -+ /* 0x380 interrupt request register */ -+ __u64 intirr; -+ /* 0x3a0 interrupt service register */ -+ __u64 intisr; -+ /* 0x3e0 interrupt level polarity selection register, -+ * 0 for high level tirgger -+ */ -+ __u64 int_polarity; -+}; -+ -+struct loongarch_gipi_single { -+ __u32 status; -+ __u32 en; -+ __u32 set; -+ __u32 clear; -+ __u64 buf[4]; -+}; -+ -+struct loongarch_gipiState { -+ struct loongarch_gipi_single core[KVM_MAX_CORES]; -+}; -+ -+struct kvm_loongarch_ls3a_extirq_state { -+ union ext_en_r { -+ uint64_t reg_u64[KVM_EXTIOI_IRQS_BITMAP_SIZE / 8]; -+ uint32_t reg_u32[KVM_EXTIOI_IRQS_BITMAP_SIZE / 4]; -+ uint8_t reg_u8[KVM_EXTIOI_IRQS_BITMAP_SIZE]; -+ } ext_en_r; -+ union bounce_r { -+ uint64_t reg_u64[KVM_EXTIOI_IRQS_BITMAP_SIZE / 8]; -+ uint32_t reg_u32[KVM_EXTIOI_IRQS_BITMAP_SIZE / 4]; -+ uint8_t reg_u8[KVM_EXTIOI_IRQS_BITMAP_SIZE]; -+ } bounce_r; -+ union ext_isr_r { -+ uint64_t reg_u64[KVM_EXTIOI_IRQS_BITMAP_SIZE / 8]; -+ uint32_t reg_u32[KVM_EXTIOI_IRQS_BITMAP_SIZE / 4]; -+ uint8_t reg_u8[KVM_EXTIOI_IRQS_BITMAP_SIZE]; -+ } ext_isr_r; -+ union ext_core_isr_r { -+ uint64_t reg_u64[KVM_MAX_CORES][KVM_EXTIOI_IRQS_BITMAP_SIZE / 8]; -+ uint32_t reg_u32[KVM_MAX_CORES][KVM_EXTIOI_IRQS_BITMAP_SIZE / 4]; -+ uint8_t reg_u8[KVM_MAX_CORES][KVM_EXTIOI_IRQS_BITMAP_SIZE]; -+ } ext_core_isr_r; -+ union ip_map_r { -+ uint64_t reg_u64; -+ uint32_t reg_u32[KVM_EXTIOI_IRQS_IPMAP_SIZE / 4]; -+ uint8_t reg_u8[KVM_EXTIOI_IRQS_IPMAP_SIZE]; -+ } ip_map_r; -+ union core_map_r { -+ uint64_t reg_u64[KVM_EXTIOI_IRQS_COREMAP_SIZE / 8]; -+ uint32_t reg_u32[KVM_EXTIOI_IRQS_COREMAP_SIZE / 4]; -+ uint8_t reg_u8[KVM_EXTIOI_IRQS_COREMAP_SIZE]; -+ } core_map_r; -+ union node_type_r { -+ uint64_t reg_u64[KVM_EXTIOI_IRQS_NODETYPE_SIZE / 4]; -+ uint32_t reg_u32[KVM_EXTIOI_IRQS_NODETYPE_SIZE / 2]; -+ uint16_t reg_u16[KVM_EXTIOI_IRQS_NODETYPE_SIZE]; -+ uint8_t reg_u8[KVM_EXTIOI_IRQS_NODETYPE_SIZE * 2]; -+ } node_type_r; -+}; -+ -+struct loongarch_kvm_irqchip { -+ __u16 chip_id; -+ __u16 len; -+ __u16 vcpu_id; -+ __u16 reserved; -+ char data[0]; -+}; -+ -+#endif /* __LINUX_KVM_LOONGARCH_H */ -diff --git a/linux-headers/asm-loongarch64/sgidefs.h b/linux-headers/asm-loongarch64/sgidefs.h -new file mode 100644 -index 0000000000..b809608349 ---- /dev/null -+++ b/linux-headers/asm-loongarch64/sgidefs.h -@@ -0,0 +1,20 @@ -+/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ -+/* -+* Copyright (C) 2020 Loongson Technology Corporation Limited -+* -+* Author: Hanlu Li -+*/ -+#ifndef __ASM_SGIDEFS_H -+#define __ASM_SGIDEFS_H -+ -+#define _LOONGARCH_ISA_LOONGARCH32 6 -+#define _LOONGARCH_ISA_LOONGARCH64 7 -+ -+/* -+ * Subprogram calling convention -+ */ -+#define _LOONGARCH_SIM_ABILP32 1 -+#define _LOONGARCH_SIM_ABILPX32 2 -+#define _LOONGARCH_SIM_ABILP64 3 -+ -+#endif /* __ASM_SGIDEFS_H */ -diff --git a/linux-headers/asm-loongarch64/unistd.h b/linux-headers/asm-loongarch64/unistd.h -new file mode 100644 -index 0000000000..2a6014562a ---- /dev/null -+++ b/linux-headers/asm-loongarch64/unistd.h -@@ -0,0 +1,23 @@ -+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -+/* -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ * -+ * Copyright (C) 2020 Loongson Technologies, Inc. -+ * Authors: Jun Yi -+ */ -+ -+#ifdef __LP64__ -+#define __ARCH_WANT_NEW_STAT -+#endif /* __LP64__ */ -+ -+#include -diff --git a/linux-user/loongarch64/cpu_loop.c b/linux-user/loongarch64/cpu_loop.c -new file mode 100644 -index 0000000000..6d4093e1d7 ---- /dev/null -+++ b/linux-user/loongarch64/cpu_loop.c -@@ -0,0 +1,193 @@ -+/* -+ * qemu user cpu loop -+ * -+ * Copyright (c) 2003-2008 Fabrice Bellard -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, see . -+ */ -+ -+#include "qemu/osdep.h" -+#include "qemu.h" -+#include "cpu_loop-common.h" -+#include "elf.h" -+ -+/* Break codes */ -+enum { -+ BRK_OVERFLOW = 6, -+ BRK_DIVZERO = 7 -+}; -+ -+static int do_break(CPULOONGARCHState *env, target_siginfo_t *info, -+ unsigned int code) -+{ -+ int ret = -1; -+ -+ switch (code) { -+ case BRK_OVERFLOW: -+ case BRK_DIVZERO: -+ info->si_signo = TARGET_SIGFPE; -+ info->si_errno = 0; -+ info->si_code = (code == BRK_OVERFLOW) ? FPE_INTOVF : FPE_INTDIV; -+ queue_signal(env, info->si_signo, QEMU_SI_FAULT, &*info); -+ ret = 0; -+ break; -+ default: -+ info->si_signo = TARGET_SIGTRAP; -+ info->si_errno = 0; -+ queue_signal(env, info->si_signo, QEMU_SI_FAULT, &*info); -+ ret = 0; -+ break; -+ } -+ -+ return ret; -+} -+ -+void cpu_loop(CPULOONGARCHState *env) -+{ -+ CPUState *cs = CPU(loongarch_env_get_cpu(env)); -+ target_siginfo_t info; -+ int trapnr; -+ abi_long ret; -+ -+ for (;;) { -+ cpu_exec_start(cs); -+ trapnr = cpu_exec(cs); -+ cpu_exec_end(cs); -+ process_queued_cpu_work(cs); -+ -+ switch (trapnr) { -+ case EXCP_SYSCALL: -+ env->active_tc.PC += 4; -+ ret = do_syscall(env, env->active_tc.gpr[11], -+ env->active_tc.gpr[4], env->active_tc.gpr[5], -+ env->active_tc.gpr[6], env->active_tc.gpr[7], -+ env->active_tc.gpr[8], env->active_tc.gpr[9], -+ -1, -1); -+ if (ret == -TARGET_ERESTARTSYS) { -+ env->active_tc.PC -= 4; -+ break; -+ } -+ if (ret == -TARGET_QEMU_ESIGRETURN) { -+ /* Returning from a successful sigreturn syscall. -+ Avoid clobbering register state. */ -+ break; -+ } -+ env->active_tc.gpr[4] = ret; -+ break; -+ case EXCP_TLBL: -+ case EXCP_TLBS: -+ case EXCP_AdEL: -+ case EXCP_AdES: -+ info.si_signo = TARGET_SIGSEGV; -+ info.si_errno = 0; -+ /* XXX: check env->error_code */ -+ info.si_code = TARGET_SEGV_MAPERR; -+ info._sifields._sigfault._addr = env->CSR_BADV; -+ queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); -+ break; -+ case EXCP_FPDIS: -+ case EXCP_LSXDIS: -+ case EXCP_LASXDIS: -+ case EXCP_RI: -+ info.si_signo = TARGET_SIGILL; -+ info.si_errno = 0; -+ info.si_code = 0; -+ queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); -+ break; -+ case EXCP_INTERRUPT: -+ /* just indicate that signals should be handled asap */ -+ break; -+ case EXCP_DEBUG: -+ info.si_signo = TARGET_SIGTRAP; -+ info.si_errno = 0; -+ info.si_code = TARGET_TRAP_BRKPT; -+ queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); -+ break; -+ case EXCP_FPE: -+ info.si_signo = TARGET_SIGFPE; -+ info.si_errno = 0; -+ info.si_code = TARGET_FPE_FLTUNK; -+ if (GET_FP_CAUSE(env->active_fpu.fcsr0) & FP_INVALID) { -+ info.si_code = TARGET_FPE_FLTINV; -+ } else if (GET_FP_CAUSE(env->active_fpu.fcsr0) & FP_DIV0) { -+ info.si_code = TARGET_FPE_FLTDIV; -+ } else if (GET_FP_CAUSE(env->active_fpu.fcsr0) & FP_OVERFLOW) { -+ info.si_code = TARGET_FPE_FLTOVF; -+ } else if (GET_FP_CAUSE(env->active_fpu.fcsr0) & FP_UNDERFLOW) { -+ info.si_code = TARGET_FPE_FLTUND; -+ } else if (GET_FP_CAUSE(env->active_fpu.fcsr0) & FP_INEXACT) { -+ info.si_code = TARGET_FPE_FLTRES; -+ } -+ queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); -+ break; -+ case EXCP_BREAK: -+ { -+ abi_ulong trap_instr; -+ unsigned int code; -+ -+ ret = get_user_u32(trap_instr, env->active_tc.PC); -+ if (ret != 0) { -+ goto error; -+ } -+ -+ code = trap_instr & 0x7fff; -+ -+ if (do_break(env, &info, code) != 0) { -+ goto error; -+ } -+ } -+ break; -+ case EXCP_TRAP: -+ { -+ abi_ulong trap_instr; -+ unsigned int code = 0; -+ -+ ret = get_user_u32(trap_instr, env->active_tc.PC); -+ -+ if (ret != 0) { -+ goto error; -+ } -+ -+ /* The immediate versions don't provide a code. */ -+ if (!(trap_instr & 0xFC000000)) { -+ code = ((trap_instr >> 6) & ((1 << 10) - 1)); -+ } -+ -+ if (do_break(env, &info, code) != 0) { -+ goto error; -+ } -+ } -+ break; -+ case EXCP_ATOMIC: -+ cpu_exec_step_atomic(cs); -+ break; -+ default: -+error: -+ printf("111111\n"); -+ EXCP_DUMP(env, "qemu: unhandled CPU exception 0x%x - aborting\n", trapnr); -+ abort(); -+ } -+ process_pending_signals(env); -+ } -+} -+ -+void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs) -+{ -+ int i; -+ -+ for (i = 0; i < 32; i++) { -+ env->active_tc.gpr[i] = regs->regs[i]; -+ } -+ env->active_tc.PC = regs->csr_era & ~(target_ulong)1; -+} -diff --git a/linux-user/loongarch64/meson.build b/linux-user/loongarch64/meson.build -new file mode 100644 -index 0000000000..c4c0b4d701 ---- /dev/null -+++ b/linux-user/loongarch64/meson.build -@@ -0,0 +1,6 @@ -+syscall_nr_generators += { -+ 'loongarch64': generator(sh, -+ arguments: [ meson.current_source_dir() / 'syscallhdr.sh', '@INPUT@', '@OUTPUT@', '@EXTRA_ARGS@', -+ '', 'TARGET_SYSCALL_OFFSET' ], -+ output: '@BASENAME@_nr.h') -+} -diff --git a/linux-user/loongarch64/signal.c b/linux-user/loongarch64/signal.c -new file mode 100644 -index 0000000000..6fe6852758 ---- /dev/null -+++ b/linux-user/loongarch64/signal.c -@@ -0,0 +1,212 @@ -+/* -+ * Emulation of Linux signals -+ * -+ * Copyright (c) 2003 Fabrice Bellard -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, see . -+ */ -+#include "qemu/osdep.h" -+#include "qemu.h" -+#include "signal-common.h" -+#include "linux-user/trace.h" -+ -+#define FPU_REG_WIDTH 256 -+union fpureg { -+ uint32_t val32[FPU_REG_WIDTH / 32]; -+ uint64_t val64[FPU_REG_WIDTH / 64]; -+}; -+ -+struct target_sigcontext { -+ uint64_t sc_pc; -+ uint64_t sc_regs[32]; -+ uint32_t sc_flags; -+ -+ uint32_t sc_fcsr; -+ uint32_t sc_vcsr; -+ uint64_t sc_fcc; -+ union fpureg sc_fpregs[32] __attribute__((aligned(32))); -+ -+ uint32_t sc_reserved; -+ -+}; -+ -+struct sigframe { -+ uint32_t sf_ass[4]; /* argument save space for o32 */ -+ uint32_t sf_code[2]; /* signal trampoline */ -+ struct target_sigcontext sf_sc; -+ target_sigset_t sf_mask; -+}; -+ -+struct target_ucontext { -+ target_ulong tuc_flags; -+ target_ulong tuc_link; -+ target_stack_t tuc_stack; -+ target_ulong pad0; -+ struct target_sigcontext tuc_mcontext; -+ target_sigset_t tuc_sigmask; -+}; -+ -+struct target_rt_sigframe { -+ uint32_t rs_ass[4]; /* argument save space for o32 */ -+ uint32_t rs_code[2]; /* signal trampoline */ -+ struct target_siginfo rs_info; -+ struct target_ucontext rs_uc; -+}; -+ -+static inline void setup_sigcontext(CPULOONGARCHState *regs, -+ struct target_sigcontext *sc) -+{ -+ int i; -+ -+ __put_user(exception_resume_pc(regs), &sc->sc_pc); -+ regs->hflags &= ~LARCH_HFLAG_BMASK; -+ -+ __put_user(0, &sc->sc_regs[0]); -+ for (i = 1; i < 32; ++i) { -+ __put_user(regs->active_tc.gpr[i], &sc->sc_regs[i]); -+ } -+ -+ for (i = 0; i < 32; ++i) { -+ __put_user(regs->active_fpu.fpr[i].d, &sc->sc_fpregs[i].val64[0]); -+ } -+} -+ -+static inline void -+restore_sigcontext(CPULOONGARCHState *regs, struct target_sigcontext *sc) -+{ -+ int i; -+ -+ __get_user(regs->CSR_ERA, &sc->sc_pc); -+ -+ for (i = 1; i < 32; ++i) { -+ __get_user(regs->active_tc.gpr[i], &sc->sc_regs[i]); -+ } -+ -+ for (i = 0; i < 32; ++i) { -+ __get_user(regs->active_fpu.fpr[i].d, &sc->sc_fpregs[i].val64[0]); -+ } -+} -+ -+/* -+ * Determine which stack to use.. -+ */ -+static inline abi_ulong -+get_sigframe(struct target_sigaction *ka, CPULOONGARCHState *regs, -+ size_t frame_size) -+{ -+ unsigned long sp; -+ -+ /* -+ * FPU emulator may have its own trampoline active just -+ * above the user stack, 16-bytes before the next lowest -+ * 16 byte boundary. Try to avoid trashing it. -+ */ -+ sp = target_sigsp(get_sp_from_cpustate(regs) - 32, ka); -+ -+ return (sp - frame_size) & ~7; -+} -+ -+void setup_rt_frame(int sig, struct target_sigaction *ka, -+ target_siginfo_t *info, -+ target_sigset_t *set, CPULOONGARCHState *env) -+{ -+ struct target_rt_sigframe *frame; -+ abi_ulong frame_addr; -+ int i; -+ -+ frame_addr = get_sigframe(ka, env, sizeof(*frame)); -+ trace_user_setup_rt_frame(env, frame_addr); -+ if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) { -+ goto give_sigsegv; -+ } -+ -+ /* ori a7, $r0, TARGET_NR_rt_sigreturn */ -+ /* syscall 0 */ -+ __put_user(0x0380000b + (TARGET_NR_rt_sigreturn << 10), &frame->rs_code[0]); -+ __put_user(0x002b0000, &frame->rs_code[1]); -+ -+ tswap_siginfo(&frame->rs_info, info); -+ -+ __put_user(0, &frame->rs_uc.tuc_flags); -+ __put_user(0, &frame->rs_uc.tuc_link); -+ target_save_altstack(&frame->rs_uc.tuc_stack, env); -+ -+ setup_sigcontext(env, &frame->rs_uc.tuc_mcontext); -+ -+ for (i = 0; i < TARGET_NSIG_WORDS; i++) { -+ __put_user(set->sig[i], &frame->rs_uc.tuc_sigmask.sig[i]); -+ } -+ -+ /* -+ * Arguments to signal handler: -+ * -+ * a0 = signal number -+ * a1 = pointer to siginfo_t -+ * a2 = pointer to ucontext_t -+ * -+ * $25 and PC point to the signal handler, $29 points to the -+ * struct sigframe. -+ */ -+ env->active_tc.gpr[4] = sig; -+ env->active_tc.gpr[5] = frame_addr -+ + offsetof(struct target_rt_sigframe, rs_info); -+ env->active_tc.gpr[6] = frame_addr -+ + offsetof(struct target_rt_sigframe, rs_uc); -+ env->active_tc.gpr[3] = frame_addr; -+ env->active_tc.gpr[1] = frame_addr -+ + offsetof(struct target_rt_sigframe, rs_code); -+ /* The original kernel code sets CP0_ERA to the handler -+ * since it returns to userland using ertn -+ * we cannot do this here, and we must set PC directly */ -+ env->active_tc.PC = env->active_tc.gpr[20] = ka->_sa_handler; -+ unlock_user_struct(frame, frame_addr, 1); -+ return; -+ -+give_sigsegv: -+ unlock_user_struct(frame, frame_addr, 1); -+ force_sigsegv(sig); -+} -+ -+long do_rt_sigreturn(CPULOONGARCHState *env) -+{ -+ struct target_rt_sigframe *frame; -+ abi_ulong frame_addr; -+ sigset_t blocked; -+ -+ frame_addr = env->active_tc.gpr[3]; -+ trace_user_do_rt_sigreturn(env, frame_addr); -+ if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) { -+ goto badframe; -+ } -+ -+ target_to_host_sigset(&blocked, &frame->rs_uc.tuc_sigmask); -+ set_sigmask(&blocked); -+ -+ restore_sigcontext(env, &frame->rs_uc.tuc_mcontext); -+ -+ if (do_sigaltstack(frame_addr + -+ offsetof(struct target_rt_sigframe, rs_uc.tuc_stack), -+ 0, get_sp_from_cpustate(env)) == -EFAULT) -+ goto badframe; -+ -+ env->active_tc.PC = env->CSR_ERA; -+ /* I am not sure this is right, but it seems to work -+ * maybe a problem with nested signals ? */ -+ env->CSR_ERA = 0; -+ return -TARGET_QEMU_ESIGRETURN; -+ -+badframe: -+ force_sig(TARGET_SIGSEGV); -+ return -TARGET_QEMU_ESIGRETURN; -+} -diff --git a/linux-user/loongarch64/sockbits.h b/linux-user/loongarch64/sockbits.h -new file mode 100644 -index 0000000000..0e4c8f012d ---- /dev/null -+++ b/linux-user/loongarch64/sockbits.h -@@ -0,0 +1 @@ -+#include "../generic/sockbits.h" -diff --git a/linux-user/loongarch64/syscall_nr.h b/linux-user/loongarch64/syscall_nr.h -new file mode 100644 -index 0000000000..a30aca8d8e ---- /dev/null -+++ b/linux-user/loongarch64/syscall_nr.h -@@ -0,0 +1,287 @@ -+#ifndef LINUX_USER_LOONGARCH_SYSCALL_NR_H -+#define LINUX_USER_LOONGARCH_SYSCALL_NR_H -+ -+#define TARGET_NR_io_setup 0 -+#define TARGET_NR_io_destroy 1 -+#define TARGET_NR_io_submit 2 -+#define TARGET_NR_io_cancel 3 -+#define TARGET_NR_io_getevents 4 -+#define TARGET_NR_setxattr 5 -+#define TARGET_NR_lsetxattr 6 -+#define TARGET_NR_fsetxattr 7 -+#define TARGET_NR_getxattr 8 -+#define TARGET_NR_lgetxattr 9 -+#define TARGET_NR_fgetxattr 10 -+#define TARGET_NR_listxattr 11 -+#define TARGET_NR_llistxattr 12 -+#define TARGET_NR_flistxattr 13 -+#define TARGET_NR_removexattr 14 -+#define TARGET_NR_lremovexattr 15 -+#define TARGET_NR_fremovexattr 16 -+#define TARGET_NR_getcwd 17 -+#define TARGET_NR_lookup_dcookie 18 -+#define TARGET_NR_eventfd2 19 -+#define TARGET_NR_epoll_create1 20 -+#define TARGET_NR_epoll_ctl 21 -+#define TARGET_NR_epoll_pwait 22 -+#define TARGET_NR_dup 23 -+#define TARGET_NR_dup3 24 -+#define TARGET_NR_fcntl 25 -+#define TARGET_NR_inotify_init1 26 -+#define TARGET_NR_inotify_add_watch 27 -+#define TARGET_NR_inotify_rm_watch 28 -+#define TARGET_NR_ioctl 29 -+#define TARGET_NR_ioprio_set 30 -+#define TARGET_NR_ioprio_get 31 -+#define TARGET_NR_flock 32 -+#define TARGET_NR_mknodat 33 -+#define TARGET_NR_mkdirat 34 -+#define TARGET_NR_unlinkat 35 -+#define TARGET_NR_symlinkat 36 -+#define TARGET_NR_linkat 37 -+#define TARGET_NR_renameat 38 -+#define TARGET_NR_umount2 39 -+#define TARGET_NR_mount 40 -+#define TARGET_NR_pivot_root 41 -+#define TARGET_NR_nfsservctl 42 -+#define TARGET_NR_statfs 43 -+#define TARGET_NR_fstatfs 44 -+#define TARGET_NR_truncate 45 -+#define TARGET_NR_ftruncate 46 -+#define TARGET_NR_fallocate 47 -+#define TARGET_NR_faccessat 48 -+#define TARGET_NR_chdir 49 -+#define TARGET_NR_fchdir 50 -+#define TARGET_NR_chroot 51 -+#define TARGET_NR_fchmod 52 -+#define TARGET_NR_fchmodat 53 -+#define TARGET_NR_fchownat 54 -+#define TARGET_NR_fchown 55 -+#define TARGET_NR_openat 56 -+#define TARGET_NR_close 57 -+#define TARGET_NR_vhangup 58 -+#define TARGET_NR_pipe2 59 -+#define TARGET_NR_quotactl 60 -+#define TARGET_NR_getdents64 61 -+#define TARGET_NR_lseek 62 -+#define TARGET_NR_read 63 -+#define TARGET_NR_write 64 -+#define TARGET_NR_readv 65 -+#define TARGET_NR_writev 66 -+#define TARGET_NR_pread64 67 -+#define TARGET_NR_pwrite64 68 -+#define TARGET_NR_preadv 69 -+#define TARGET_NR_pwritev 70 -+#define TARGET_NR_sendfile 71 -+#define TARGET_NR_pselect6 72 -+#define TARGET_NR_ppoll 73 -+#define TARGET_NR_signalfd4 74 -+#define TARGET_NR_vmsplice 75 -+#define TARGET_NR_splice 76 -+#define TARGET_NR_tee 77 -+#define TARGET_NR_readlinkat 78 -+#define TARGET_NR_newfstatat 79 -+#define TARGET_NR_fstat 80 -+#define TARGET_NR_sync 81 -+#define TARGET_NR_fsync 82 -+#define TARGET_NR_fdatasync 83 -+#define TARGET_NR_sync_file_range 84 -+#define TARGET_NR_timerfd_create 85 -+#define TARGET_NR_timerfd_settime 86 -+#define TARGET_NR_timerfd_gettime 87 -+#define TARGET_NR_utimensat 88 -+#define TARGET_NR_acct 89 -+#define TARGET_NR_capget 90 -+#define TARGET_NR_capset 91 -+#define TARGET_NR_personality 92 -+#define TARGET_NR_exit 93 -+#define TARGET_NR_exit_group 94 -+#define TARGET_NR_waitid 95 -+#define TARGET_NR_set_tid_address 96 -+#define TARGET_NR_unshare 97 -+#define TARGET_NR_futex 98 -+#define TARGET_NR_set_robust_list 99 -+#define TARGET_NR_get_robust_list 100 -+#define TARGET_NR_nanosleep 101 -+#define TARGET_NR_getitimer 102 -+#define TARGET_NR_setitimer 103 -+#define TARGET_NR_kexec_load 104 -+#define TARGET_NR_init_module 105 -+#define TARGET_NR_delete_module 106 -+#define TARGET_NR_timer_create 107 -+#define TARGET_NR_timer_gettime 108 -+#define TARGET_NR_timer_getoverrun 109 -+#define TARGET_NR_timer_settime 110 -+#define TARGET_NR_timer_delete 111 -+#define TARGET_NR_clock_settime 112 -+#define TARGET_NR_clock_gettime 113 -+#define TARGET_NR_clock_getres 114 -+#define TARGET_NR_clock_nanosleep 115 -+#define TARGET_NR_syslog 116 -+#define TARGET_NR_ptrace 117 -+#define TARGET_NR_sched_setparam 118 -+#define TARGET_NR_sched_setscheduler 119 -+#define TARGET_NR_sched_getscheduler 120 -+#define TARGET_NR_sched_getparam 121 -+#define TARGET_NR_sched_setaffinity 122 -+#define TARGET_NR_sched_getaffinity 123 -+#define TARGET_NR_sched_yield 124 -+#define TARGET_NR_sched_get_priority_max 125 -+#define TARGET_NR_sched_get_priority_min 126 -+#define TARGET_NR_sched_rr_get_interval 127 -+#define TARGET_NR_restart_syscall 128 -+#define TARGET_NR_kill 129 -+#define TARGET_NR_tkill 130 -+#define TARGET_NR_tgkill 131 -+#define TARGET_NR_sigaltstack 132 -+#define TARGET_NR_rt_sigsuspend 133 -+#define TARGET_NR_rt_sigaction 134 -+#define TARGET_NR_rt_sigprocmask 135 -+#define TARGET_NR_rt_sigpending 136 -+#define TARGET_NR_rt_sigtimedwait 137 -+#define TARGET_NR_rt_sigqueueinfo 138 -+#define TARGET_NR_rt_sigreturn 139 -+#define TARGET_NR_setpriority 140 -+#define TARGET_NR_getpriority 141 -+#define TARGET_NR_reboot 142 -+#define TARGET_NR_setregid 143 -+#define TARGET_NR_setgid 144 -+#define TARGET_NR_setreuid 145 -+#define TARGET_NR_setuid 146 -+#define TARGET_NR_setresuid 147 -+#define TARGET_NR_getresuid 148 -+#define TARGET_NR_setresgid 149 -+#define TARGET_NR_getresgid 150 -+#define TARGET_NR_setfsuid 151 -+#define TARGET_NR_setfsgid 152 -+#define TARGET_NR_times 153 -+#define TARGET_NR_setpgid 154 -+#define TARGET_NR_getpgid 155 -+#define TARGET_NR_getsid 156 -+#define TARGET_NR_setsid 157 -+#define TARGET_NR_getgroups 158 -+#define TARGET_NR_setgroups 159 -+#define TARGET_NR_uname 160 -+#define TARGET_NR_sethostname 161 -+#define TARGET_NR_setdomainname 162 -+#define TARGET_NR_getrlimit 163 -+#define TARGET_NR_setrlimit 164 -+#define TARGET_NR_getrusage 165 -+#define TARGET_NR_umask 166 -+#define TARGET_NR_prctl 167 -+#define TARGET_NR_getcpu 168 -+#define TARGET_NR_gettimeofday 169 -+#define TARGET_NR_settimeofday 170 -+#define TARGET_NR_adjtimex 171 -+#define TARGET_NR_getpid 172 -+#define TARGET_NR_getppid 173 -+#define TARGET_NR_getuid 174 -+#define TARGET_NR_geteuid 175 -+#define TARGET_NR_getgid 176 -+#define TARGET_NR_getegid 177 -+#define TARGET_NR_gettid 178 -+#define TARGET_NR_sysinfo 179 -+#define TARGET_NR_mq_open 180 -+#define TARGET_NR_mq_unlink 181 -+#define TARGET_NR_mq_timedsend 182 -+#define TARGET_NR_mq_timedreceive 183 -+#define TARGET_NR_mq_notify 184 -+#define TARGET_NR_mq_getsetattr 185 -+#define TARGET_NR_msgget 186 -+#define TARGET_NR_msgctl 187 -+#define TARGET_NR_msgrcv 188 -+#define TARGET_NR_msgsnd 189 -+#define TARGET_NR_semget 190 -+#define TARGET_NR_semctl 191 -+#define TARGET_NR_semtimedop 192 -+#define TARGET_NR_semop 193 -+#define TARGET_NR_shmget 194 -+#define TARGET_NR_shmctl 195 -+#define TARGET_NR_shmat 196 -+#define TARGET_NR_shmdt 197 -+#define TARGET_NR_socket 198 -+#define TARGET_NR_socketpair 199 -+#define TARGET_NR_bind 200 -+#define TARGET_NR_listen 201 -+#define TARGET_NR_accept 202 -+#define TARGET_NR_connect 203 -+#define TARGET_NR_getsockname 204 -+#define TARGET_NR_getpeername 205 -+#define TARGET_NR_sendto 206 -+#define TARGET_NR_recvfrom 207 -+#define TARGET_NR_setsockopt 208 -+#define TARGET_NR_getsockopt 209 -+#define TARGET_NR_shutdown 210 -+#define TARGET_NR_sendmsg 211 -+#define TARGET_NR_recvmsg 212 -+#define TARGET_NR_readahead 213 -+#define TARGET_NR_brk 214 -+#define TARGET_NR_munmap 215 -+#define TARGET_NR_mremap 216 -+#define TARGET_NR_add_key 217 -+#define TARGET_NR_request_key 218 -+#define TARGET_NR_keyctl 219 -+#define TARGET_NR_clone 220 -+#define TARGET_NR_execve 221 -+#define TARGET_NR_mmap 222 -+#define TARGET_NR_fadvise64 223 -+#define TARGET_NR_swapon 224 -+#define TARGET_NR_swapoff 225 -+#define TARGET_NR_mprotect 226 -+#define TARGET_NR_msync 227 -+#define TARGET_NR_mlock 228 -+#define TARGET_NR_munlock 229 -+#define TARGET_NR_mlockall 230 -+#define TARGET_NR_munlockall 231 -+#define TARGET_NR_mincore 232 -+#define TARGET_NR_madvise 233 -+#define TARGET_NR_remap_file_pages 234 -+#define TARGET_NR_mbind 235 -+#define TARGET_NR_get_mempolicy 236 -+#define TARGET_NR_set_mempolicy 237 -+#define TARGET_NR_migrate_pages 238 -+#define TARGET_NR_move_pages 239 -+#define TARGET_NR_rt_tgsigqueueinfo 240 -+#define TARGET_NR_perf_event_open 241 -+#define TARGET_NR_accept4 242 -+#define TARGET_NR_recvmmsg 243 -+#define TARGET_NR_arch_specific_syscall 244 -+#define TARGET_NR_wait4 260 -+#define TARGET_NR_prlimit64 261 -+#define TARGET_NR_fanotify_init 262 -+#define TARGET_NR_fanotify_mark 263 -+#define TARGET_NR_name_to_handle_at 264 -+#define TARGET_NR_open_by_handle_at 265 -+#define TARGET_NR_clock_adjtime 266 -+#define TARGET_NR_syncfs 267 -+#define TARGET_NR_setns 268 -+#define TARGET_NR_sendmmsg 269 -+#define TARGET_NR_process_vm_readv 270 -+#define TARGET_NR_process_vm_writev 271 -+#define TARGET_NR_kcmp 272 -+#define TARGET_NR_finit_module 273 -+#define TARGET_NR_sched_setattr 274 -+#define TARGET_NR_sched_getattr 275 -+#define TARGET_NR_renameat2 276 -+#define TARGET_NR_seccomp 277 -+#define TARGET_NR_getrandom 278 -+#define TARGET_NR_memfd_create 279 -+#define TARGET_NR_bpf 280 -+#define TARGET_NR_execveat 281 -+#define TARGET_NR_userfaultfd 282 -+#define TARGET_NR_membarrier 283 -+#define TARGET_NR_mlock2 284 -+#define TARGET_NR_copy_file_range 285 -+#define TARGET_NR_preadv2 286 -+#define TARGET_NR_pwritev2 287 -+#define TARGET_NR_pkey_mprotect 288 -+#define TARGET_NR_pkey_alloc 289 -+#define TARGET_NR_pkey_free 290 -+#define TARGET_NR_statx 291 -+#define TARGET_NR_io_pgetevents 292 -+#define TARGET_NR_rseq 293 -+#define TARGET_NR_kexec_file_load 294 -+ -+#define TARGET_NR_syscalls (TARGET_NR_kexec_file_load + 1) -+ -+#endif -diff --git a/linux-user/loongarch64/target_cpu.h b/linux-user/loongarch64/target_cpu.h -new file mode 100644 -index 0000000000..0f6845737f ---- /dev/null -+++ b/linux-user/loongarch64/target_cpu.h -@@ -0,0 +1,45 @@ -+/* -+ * MIPS specific CPU ABI and functions for linux-user -+ * -+ * Copyright (c) 2004-2005 Jocelyn Mayer -+ * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2 of the License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library; if not, see . -+ */ -+#ifndef LOONGARCH_TARGET_CPU_H -+#define LOONGARCH_TARGET_CPU_H -+ -+static inline void cpu_clone_regs_child(CPULOONGARCHState *env, target_ulong newsp, -+ unsigned flags) -+{ -+ if (newsp) { -+ env->active_tc.gpr[3] = newsp; -+ } -+ env->active_tc.gpr[7] = 0; -+ env->active_tc.gpr[4] = 0; -+} -+ -+static inline void cpu_clone_regs_parent(CPULOONGARCHState *env, unsigned flags) -+{ -+} -+ -+static inline void cpu_set_tls(CPULOONGARCHState *env, target_ulong newtls) -+{ -+ env->active_tc.gpr[2] = newtls; -+} -+ -+static inline abi_ulong get_sp_from_cpustate(CPULOONGARCHState *state) -+{ -+ return state->active_tc.gpr[3]; -+} -+#endif -diff --git a/linux-user/loongarch64/target_elf.h b/linux-user/loongarch64/target_elf.h -new file mode 100644 -index 0000000000..6c153d12c4 ---- /dev/null -+++ b/linux-user/loongarch64/target_elf.h -@@ -0,0 +1,14 @@ -+/* -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation, or (at your option) any -+ * later version. See the COPYING file in the top-level directory. -+ */ -+ -+#ifndef LOONGARCH_TARGET_ELF_H -+#define LOONGARCH_TARGET_ELF_H -+static inline const char *cpu_get_model(uint32_t eflags) -+{ -+ return "Loongson-3A5000"; -+} -+#endif -diff --git a/linux-user/loongarch64/target_fcntl.h b/linux-user/loongarch64/target_fcntl.h -new file mode 100644 -index 0000000000..a3d7b46062 ---- /dev/null -+++ b/linux-user/loongarch64/target_fcntl.h -@@ -0,0 +1,13 @@ -+/* -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation, or (at your option) any -+ * later version. See the COPYING file in the top-level directory. -+ */ -+ -+#ifndef LOONGARCH_TARGET_FCNTL_H -+#define LOONGARCH_TARGET_FCNTL_H -+ -+#include "../generic/fcntl.h" -+ -+#endif /* LOONGARCH_TARGET_FCNTL_H */ -diff --git a/linux-user/loongarch64/target_signal.h b/linux-user/loongarch64/target_signal.h -new file mode 100644 -index 0000000000..e418c8e8f5 ---- /dev/null -+++ b/linux-user/loongarch64/target_signal.h -@@ -0,0 +1,23 @@ -+#ifndef LOONGARCH_TARGET_SIGNAL_H -+#define LOONGARCH_TARGET_SIGNAL_H -+ -+/* this struct defines a stack used during syscall handling */ -+ -+typedef struct target_sigaltstack { -+ abi_long ss_sp; -+ abi_int ss_flags; -+ abi_ulong ss_size; -+} target_stack_t; -+ -+/* -+ * sigaltstack controls -+ */ -+#define TARGET_SS_ONSTACK 1 -+#define TARGET_SS_DISABLE 2 -+ -+#define TARGET_MINSIGSTKSZ 2048 -+#define TARGET_SIGSTKSZ 8192 -+ -+#include "../generic/signal.h" -+ -+#endif /* LOONGARCH_TARGET_SIGNAL_H */ -diff --git a/linux-user/loongarch64/target_structs.h b/linux-user/loongarch64/target_structs.h -new file mode 100644 -index 0000000000..280acd0971 ---- /dev/null -+++ b/linux-user/loongarch64/target_structs.h -@@ -0,0 +1,62 @@ -+/* -+ * LOONGARCH specific structures for linux-user -+ * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2 of the License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library; if not, see . -+ */ -+#ifndef LOONGARCH_TARGET_STRUCTS_H -+#define LOONGARCH_TARGET_STRUCTS_H -+ -+struct target_ipc_perm { -+ abi_int __key; /* Key. */ -+ abi_uint uid; /* Owner's user ID. */ -+ abi_uint gid; /* Owner's group ID. */ -+ abi_uint cuid; /* Creator's user ID. */ -+ abi_uint cgid; /* Creator's group ID. */ -+ abi_uint mode; /* Read/write permission. */ -+ abi_ushort __seq; /* Sequence number. */ -+ abi_ushort __pad1; -+ abi_ulong __unused1; -+ abi_ulong __unused2; -+}; -+ -+struct target_shmid_ds { -+ struct target_ipc_perm shm_perm; /* operation permission struct */ -+ abi_long shm_segsz; /* size of segment in bytes */ -+ abi_ulong shm_atime; /* time of last shmat() */ -+ abi_ulong shm_dtime; /* time of last shmdt() */ -+ abi_ulong shm_ctime; /* time of last change by shmctl() */ -+ abi_int shm_cpid; /* pid of creator */ -+ abi_int shm_lpid; /* pid of last shmop */ -+ abi_ulong shm_nattch; /* number of current attaches */ -+ abi_ulong __unused1; -+ abi_ulong __unused2; -+}; -+ -+#define TARGET_SEMID64_DS -+ -+/* -+ * The semid64_ds structure for the MIPS architecture. -+ * Note extra padding because this structure is passed back and forth -+ * between kernel and user space. -+ */ -+struct target_semid64_ds { -+ struct target_ipc_perm sem_perm; -+ abi_ulong sem_otime; -+ abi_ulong sem_ctime; -+ abi_ulong sem_nsems; -+ abi_ulong __unused1; -+ abi_ulong __unused2; -+}; -+ -+#endif -diff --git a/linux-user/loongarch64/target_syscall.h b/linux-user/loongarch64/target_syscall.h -new file mode 100644 -index 0000000000..cb77f07080 ---- /dev/null -+++ b/linux-user/loongarch64/target_syscall.h -@@ -0,0 +1,44 @@ -+#ifndef LOONGARCH_TARGET_SYSCALL_H -+#define LOONGARCH_TARGET_SYSCALL_H -+ -+/* this struct defines the way the registers are stored on the -+ stack during a system call. */ -+ -+struct target_pt_regs { -+ /* Saved main processor registers. */ -+ target_ulong regs[32]; -+ -+ /* Saved special registers. */ -+ /* Saved special registers. */ -+ target_ulong csr_crmd; -+ target_ulong csr_prmd; -+ target_ulong csr_euen; -+ target_ulong csr_ecfg; -+ target_ulong csr_estat; -+ target_ulong csr_era; -+ target_ulong csr_badvaddr; -+ target_ulong orig_a0; -+ target_ulong __last[0]; -+}; -+ -+#define UNAME_MACHINE "loongarch" -+#define UNAME_MINIMUM_RELEASE "2.6.32" -+ -+#define TARGET_CLONE_BACKWARDS -+#define TARGET_MINSIGSTKSZ 2048 -+#define TARGET_MLOCKALL_MCL_CURRENT 1 -+#define TARGET_MLOCKALL_MCL_FUTURE 2 -+ -+#define TARGET_FORCE_SHMLBA -+ -+static inline abi_ulong target_shmlba(CPULOONGARCHState *env) -+{ -+ return 0x40000; -+} -+ -+#define TARGET_PR_SET_FP_MODE 45 -+#define TARGET_PR_GET_FP_MODE 46 -+#define TARGET_PR_FP_MODE_FR (1 << 0) -+#define TARGET_PR_FP_MODE_FRE (1 << 1) -+ -+#endif /* LOONGARCH_TARGET_SYSCALL_H */ -diff --git a/linux-user/loongarch64/termbits.h b/linux-user/loongarch64/termbits.h -new file mode 100644 -index 0000000000..6c613a1973 ---- /dev/null -+++ b/linux-user/loongarch64/termbits.h -@@ -0,0 +1,224 @@ -+#ifndef LINUX_USER_LOONGARCH_TERMBITS_H -+#define LINUX_USER_LOONGARCH_TERMBITS_H -+ -+#define TARGET_NCCS 19 -+ -+struct target_termios { -+ unsigned int c_iflag; /* input mode flags */ -+ unsigned int c_oflag; /* output mode flags */ -+ unsigned int c_cflag; /* control mode flags */ -+ unsigned int c_lflag; /* local mode flags */ -+ unsigned char c_line; /* line discipline */ -+ unsigned char c_cc[TARGET_NCCS]; /* control characters */ -+}; -+ -+/* c_iflag bits */ -+#define TARGET_IGNBRK 0000001 -+#define TARGET_BRKINT 0000002 -+#define TARGET_IGNPAR 0000004 -+#define TARGET_PARMRK 0000010 -+#define TARGET_INPCK 0000020 -+#define TARGET_ISTRIP 0000040 -+#define TARGET_INLCR 0000100 -+#define TARGET_IGNCR 0000200 -+#define TARGET_ICRNL 0000400 -+#define TARGET_IUCLC 0001000 -+#define TARGET_IXON 0002000 -+#define TARGET_IXANY 0004000 -+#define TARGET_IXOFF 0010000 -+#define TARGET_IMAXBEL 0020000 -+#define TARGET_IUTF8 0040000 -+ -+/* c_oflag bits */ -+#define TARGET_OPOST 0000001 -+#define TARGET_OLCUC 0000002 -+#define TARGET_ONLCR 0000004 -+#define TARGET_OCRNL 0000010 -+#define TARGET_ONOCR 0000020 -+#define TARGET_ONLRET 0000040 -+#define TARGET_OFILL 0000100 -+#define TARGET_OFDEL 0000200 -+#define TARGET_NLDLY 0000400 -+#define TARGET_NL0 0000000 -+#define TARGET_NL1 0000400 -+#define TARGET_CRDLY 0003000 -+#define TARGET_CR0 0000000 -+#define TARGET_CR1 0001000 -+#define TARGET_CR2 0002000 -+#define TARGET_CR3 0003000 -+#define TARGET_TABDLY 0014000 -+#define TARGET_TAB0 0000000 -+#define TARGET_TAB1 0004000 -+#define TARGET_TAB2 0010000 -+#define TARGET_TAB3 0014000 -+#define TARGET_XTABS 0014000 -+#define TARGET_BSDLY 0020000 -+#define TARGET_BS0 0000000 -+#define TARGET_BS1 0020000 -+#define TARGET_VTDLY 0040000 -+#define TARGET_VT0 0000000 -+#define TARGET_VT1 0040000 -+#define TARGET_FFDLY 0100000 -+#define TARGET_FF0 0000000 -+#define TARGET_FF1 0100000 -+ -+/* c_cflag bit meaning */ -+#define TARGET_CBAUD 0010017 -+#define TARGET_B0 0000000 /* hang up */ -+#define TARGET_B50 0000001 -+#define TARGET_B75 0000002 -+#define TARGET_B110 0000003 -+#define TARGET_B134 0000004 -+#define TARGET_B150 0000005 -+#define TARGET_B200 0000006 -+#define TARGET_B300 0000007 -+#define TARGET_B600 0000010 -+#define TARGET_B1200 0000011 -+#define TARGET_B1800 0000012 -+#define TARGET_B2400 0000013 -+#define TARGET_B4800 0000014 -+#define TARGET_B9600 0000015 -+#define TARGET_B19200 0000016 -+#define TARGET_B38400 0000017 -+#define TARGET_EXTA B19200 -+#define TARGET_EXTB B38400 -+#define TARGET_CSIZE 0000060 -+#define TARGET_CS5 0000000 -+#define TARGET_CS6 0000020 -+#define TARGET_CS7 0000040 -+#define TARGET_CS8 0000060 -+#define TARGET_CSTOPB 0000100 -+#define TARGET_CREAD 0000200 -+#define TARGET_PARENB 0000400 -+#define TARGET_PARODD 0001000 -+#define TARGET_HUPCL 0002000 -+#define TARGET_CLOCAL 0004000 -+#define TARGET_CBAUDEX 0010000 -+#define TARGET_B57600 0010001 -+#define TARGET_B115200 0010002 -+#define TARGET_B230400 0010003 -+#define TARGET_B460800 0010004 -+#define TARGET_CIBAUD 002003600000 /* input baud rate (not used) */ -+#define TARGET_CMSPAR 010000000000 /* mark or space (stick) parity */ -+#define TARGET_CRTSCTS 020000000000 /* flow control */ -+ -+/* c_lflag bits */ -+#define TARGET_ISIG 0000001 -+#define TARGET_ICANON 0000002 -+#define TARGET_XCASE 0000004 -+#define TARGET_ECHO 0000010 -+#define TARGET_ECHOE 0000020 -+#define TARGET_ECHOK 0000040 -+#define TARGET_ECHONL 0000100 -+#define TARGET_NOFLSH 0000200 -+#define TARGET_TOSTOP 0000400 -+#define TARGET_ECHOCTL 0001000 -+#define TARGET_ECHOPRT 0002000 -+#define TARGET_ECHOKE 0004000 -+#define TARGET_FLUSHO 0010000 -+#define TARGET_PENDIN 0040000 -+#define TARGET_IEXTEN 0100000 -+ -+/* c_cc character offsets */ -+#define TARGET_VINTR 0 -+#define TARGET_VQUIT 1 -+#define TARGET_VERASE 2 -+#define TARGET_VKILL 3 -+#define TARGET_VEOF 4 -+#define TARGET_VTIME 5 -+#define TARGET_VMIN 6 -+#define TARGET_VSWTC 7 -+#define TARGET_VSTART 8 -+#define TARGET_VSTOP 9 -+#define TARGET_VSUSP 10 -+#define TARGET_VEOL 11 -+#define TARGET_VREPRINT 12 -+#define TARGET_VDISCARD 13 -+#define TARGET_VWERASE 14 -+#define TARGET_VLNEXT 15 -+#define TARGET_VEOL2 16 -+ -+/* ioctls */ -+ -+#define TARGET_TCGETS 0x5401 -+#define TARGET_TCSETS 0x5402 -+#define TARGET_TCSETSW 0x5403 -+#define TARGET_TCSETSF 0x5404 -+#define TARGET_TCGETA 0x5405 -+#define TARGET_TCSETA 0x5406 -+#define TARGET_TCSETAW 0x5407 -+#define TARGET_TCSETAF 0x5408 -+#define TARGET_TCSBRK 0x5409 -+#define TARGET_TCXONC 0x540A -+#define TARGET_TCFLSH 0x540B -+ -+#define TARGET_TIOCEXCL 0x540C -+#define TARGET_TIOCNXCL 0x540D -+#define TARGET_TIOCSCTTY 0x540E -+#define TARGET_TIOCGPGRP 0x540F -+#define TARGET_TIOCSPGRP 0x5410 -+#define TARGET_TIOCOUTQ 0x5411 -+#define TARGET_TIOCSTI 0x5412 -+#define TARGET_TIOCGWINSZ 0x5413 -+#define TARGET_TIOCSWINSZ 0x5414 -+#define TARGET_TIOCMGET 0x5415 -+#define TARGET_TIOCMBIS 0x5416 -+#define TARGET_TIOCMBIC 0x5417 -+#define TARGET_TIOCMSET 0x5418 -+#define TARGET_TIOCGSOFTCAR 0x5419 -+#define TARGET_TIOCSSOFTCAR 0x541A -+#define TARGET_FIONREAD 0x541B -+#define TARGET_TIOCINQ TARGET_FIONREAD -+#define TARGET_TIOCLINUX 0x541C -+#define TARGET_TIOCCONS 0x541D -+#define TARGET_TIOCGSERIAL 0x541E -+#define TARGET_TIOCSSERIAL 0x541F -+#define TARGET_TIOCPKT 0x5420 -+#define TARGET_FIONBIO 0x5421 -+#define TARGET_TIOCNOTTY 0x5422 -+#define TARGET_TIOCSETD 0x5423 -+#define TARGET_TIOCGETD 0x5424 -+#define TARGET_TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */ -+#define TARGET_TIOCTTYGSTRUCT 0x5426 /* For debugging only */ -+#define TARGET_TIOCSBRK 0x5427 /* BSD compatibility */ -+#define TARGET_TIOCCBRK 0x5428 /* BSD compatibility */ -+#define TARGET_TIOCGSID 0x5429 /* Return the session ID of FD */ -+#define TARGET_TIOCGPTN TARGET_IOR('T', 0x30, unsigned int) -+ /* Get Pty Number (of pty-mux device) */ -+#define TARGET_TIOCSPTLCK TARGET_IOW('T', 0x31, int) -+ /* Lock/unlock Pty */ -+#define TARGET_TIOCGPTPEER TARGET_IO('T', 0x41) -+ /* Safely open the slave */ -+ -+#define TARGET_FIONCLEX 0x5450 /* these numbers need to be adjusted. */ -+#define TARGET_FIOCLEX 0x5451 -+#define TARGET_FIOASYNC 0x5452 -+#define TARGET_TIOCSERCONFIG 0x5453 -+#define TARGET_TIOCSERGWILD 0x5454 -+#define TARGET_TIOCSERSWILD 0x5455 -+#define TARGET_TIOCGLCKTRMIOS 0x5456 -+#define TARGET_TIOCSLCKTRMIOS 0x5457 -+#define TARGET_TIOCSERGSTRUCT 0x5458 /* For debugging only */ -+#define TARGET_TIOCSERGETLSR 0x5459 /* Get line status register */ -+#define TARGET_TIOCSERGETMULTI 0x545A /* Get multiport config */ -+#define TARGET_TIOCSERSETMULTI 0x545B /* Set multiport config */ -+ -+#define TARGET_TIOCMIWAIT 0x545C -+ /* wait for a change on serial input line(s) */ -+#define TARGET_TIOCGICOUNT 0x545D -+ /* read serial port inline interrupt counts */ -+#define TARGET_TIOCGHAYESESP 0x545E /* Get Hayes ESP configuration */ -+#define TARGET_TIOCSHAYESESP 0x545F /* Set Hayes ESP configuration */ -+ -+/* Used for packet mode */ -+#define TARGET_TIOCPKT_DATA 0 -+#define TARGET_TIOCPKT_FLUSHREAD 1 -+#define TARGET_TIOCPKT_FLUSHWRITE 2 -+#define TARGET_TIOCPKT_STOP 4 -+#define TARGET_TIOCPKT_START 8 -+#define TARGET_TIOCPKT_NOSTOP 16 -+#define TARGET_TIOCPKT_DOSTOP 32 -+ -+#define TARGET_TIOCSER_TEMT 0x01 /* Transmitter physically empty */ -+ -+#endif --- -2.27.0 - diff --git a/0006-Add-disas-gdb.patch b/0006-Add-disas-gdb.patch deleted file mode 100644 index 00d9b5e..0000000 --- a/0006-Add-disas-gdb.patch +++ /dev/null @@ -1,3183 +0,0 @@ -From 0789663b3a2ad105a209c7aa36d102a5b05f1397 Mon Sep 17 00:00:00 2001 -From: lixianglai -Date: Fri, 19 Aug 2022 23:51:12 -0400 -Subject: [PATCH 6/8] Add disas gdb. - -Change-Id: If41c0fc8aa128796e342319c7673fab3ccbf3913 -Signed-off-by: lixianglai ---- - .../devices/loongarch64-softmmu/default.mak | 154 + - configs/targets/loongarch64-softmmu.mak | 4 + - disas/loongarch.c | 2748 +++++++++++++++++ - disas/meson.build | 1 + - gdb-xml/loongarch-base32.xml | 43 + - gdb-xml/loongarch-base64.xml | 43 + - gdb-xml/loongarch-fpu32.xml | 52 + - gdb-xml/loongarch-fpu64.xml | 57 + - 8 files changed, 3102 insertions(+) - create mode 100644 configs/devices/loongarch64-softmmu/default.mak - create mode 100644 configs/targets/loongarch64-softmmu.mak - create mode 100644 disas/loongarch.c - create mode 100644 gdb-xml/loongarch-base32.xml - create mode 100644 gdb-xml/loongarch-base64.xml - create mode 100644 gdb-xml/loongarch-fpu32.xml - create mode 100644 gdb-xml/loongarch-fpu64.xml - -diff --git a/configs/devices/loongarch64-softmmu/default.mak b/configs/devices/loongarch64-softmmu/default.mak -new file mode 100644 -index 0000000000..fcb7e45dd2 ---- /dev/null -+++ b/configs/devices/loongarch64-softmmu/default.mak -@@ -0,0 +1,154 @@ -+# Default configuration for loongarch-softmmu -+ -+CONFIG_PCI=y -+CONFIG_ACPI_PCI=y -+# For now, CONFIG_IDE_CORE requires ISA, so we enable it here -+CONFIG_ISA_BUS=y -+CONFIG_VIRTIO_PCI=y -+ -+CONFIG_VGA_PCI=y -+CONFIG_ACPI_SMBUS=y -+#CONFIG_VHOST_USER_SCSI=$(call land,$(CONFIG_VHOST_USER),$(CONFIG_LINUX)) -+CONFIG_VHOST_USER_SCSI=y -+#CONFIG_VHOST_USER_BLK=$(call land,$(CONFIG_VHOST_USER),$(CONFIG_LINUX)) -+CONFIG_VHOST_USER_BLK=y -+CONFIG_VIRTIO=y -+CONFIG_VIRTIO_BALLOON=y -+CONFIG_VIRTIO_BLK=y -+CONFIG_VIRTIO_CRYPTO=y -+CONFIG_VIRTIO_GPU=y -+CONFIG_VIRTIO_INPUT=y -+CONFIG_VIRTIO_NET=y -+CONFIG_VIRTIO_RNG=y -+CONFIG_SCSI=y -+CONFIG_VIRTIO_SCSI=y -+CONFIG_VIRTIO_SERIAL=y -+ -+CONFIG_USB_UHCI=y -+CONFIG_USB_OHCI=y -+CONFIG_USB_OHCI_PCI=y -+CONFIG_USB_XHCI=y -+CONFIG_USB_XHCI_NEC=y -+CONFIG_NE2000_PCI=y -+CONFIG_EEPRO100_PCI=y -+CONFIG_PCNET_PCI=y -+CONFIG_PCNET_COMMON=y -+CONFIG_AC97=y -+CONFIG_HDA=y -+CONFIG_ES1370=y -+CONFIG_SCSI=y -+CONFIG_LSI_SCSI_PCI=y -+CONFIG_VMW_PVSCSI_SCSI_PCI=y -+CONFIG_MEGASAS_SCSI_PCI=y -+CONFIG_MPTSAS_SCSI_PCI=y -+CONFIG_RTL8139_PCI=y -+CONFIG_E1000_PCI=y -+CONFIG_IDE_CORE=y -+CONFIG_IDE_QDEV=y -+CONFIG_IDE_PCI=y -+CONFIG_AHCI=y -+CONFIG_AHCI_ICH9=y -+CONFIG_ESP=y -+CONFIG_ESP_PCI=y -+CONFIG_SERIAL=y -+CONFIG_SERIAL_ISA=y -+CONFIG_SERIAL_PCI=y -+CONFIG_CAN_BUS=y -+CONFIG_CAN_SJA1000=y -+CONFIG_CAN_PCI=y -+CONFIG_USB_UHCI=y -+CONFIG_USB_OHCI=y -+CONFIG_USB_XHCI=y -+CONFIG_USB_XHCI_NEC=y -+CONFIG_NE2000_PCI=y -+CONFIG_EEPRO100_PCI=y -+CONFIG_PCNET_PCI=y -+CONFIG_PCNET_COMMON=y -+CONFIG_AC97=y -+CONFIG_HDA=y -+CONFIG_ES1370=y -+CONFIG_SCSI=y -+CONFIG_LSI_SCSI_PCI=y -+CONFIG_VMW_PVSCSI_SCSI_PCI=y -+CONFIG_MEGASAS_SCSI_PCI=y -+CONFIG_MPTSAS_SCSI_PCI=y -+CONFIG_RTL8139_PCI=y -+CONFIG_E1000_PCI=y -+CONFIG_IDE_CORE=y -+CONFIG_IDE_QDEV=y -+CONFIG_IDE_PCI=y -+CONFIG_AHCI=y -+CONFIG_ESP=y -+CONFIG_ESP_PCI=y -+CONFIG_SERIAL=y -+CONFIG_SERIAL_ISA=y -+CONFIG_SERIAL_PCI=y -+CONFIG_CAN_BUS=y -+CONFIG_CAN_SJA1000=y -+CONFIG_CAN_PCI=y -+ -+CONFIG_SPICE=y -+CONFIG_QXL=y -+CONFIG_ESP=y -+CONFIG_SCSI=y -+CONFIG_VGA_ISA=y -+CONFIG_VGA_ISA_MM=y -+CONFIG_VGA_CIRRUS=y -+CONFIG_VMWARE_VGA=y -+CONFIG_VIRTIO_VGA=y -+CONFIG_SERIAL=y -+CONFIG_SERIAL_ISA=y -+CONFIG_PARALLEL=y -+CONFIG_I8254=y -+CONFIG_PCSPK=y -+CONFIG_PCKBD=y -+CONFIG_FDC=y -+CONFIG_ACPI=y -+CONFIG_ACPI_MEMORY_HOTPLUG=y -+CONFIG_ACPI_NVDIMM=y -+CONFIG_ACPI_CPU_HOTPLUG=y -+CONFIG_APM=y -+CONFIG_I8257=y -+CONFIG_PIIX4=y -+CONFIG_IDE_ISA=y -+CONFIG_IDE_PIIX=y -+#CONFIG_NE2000_ISA=y -+CONFIG_MIPSNET=y -+CONFIG_PFLASH_CFI01=y -+CONFIG_I8259=y -+CONFIG_MC146818RTC=y -+CONFIG_ISA_TESTDEV=y -+CONFIG_EMPTY_SLOT=y -+CONFIG_I2C=y -+CONFIG_DIMM=y -+CONFIG_MEM_DEVICE=y -+ -+# Arch Specified CONFIG defines -+CONFIG_IDE_VIA=y -+CONFIG_VT82C686=y -+CONFIG_RC4030=y -+CONFIG_DP8393X=y -+CONFIG_DS1225Y=y -+CONFIG_FITLOADER=y -+CONFIG_SMBIOS=y -+ -+CONFIG_PCIE_PORT=y -+CONFIG_I82801B11=y -+CONFIG_XIO3130=y -+CONFIG_PCI_EXPRESS=y -+CONFIG_MSI_NONBROKEN=y -+CONFIG_IOH3420=y -+CONFIG_SD=y -+CONFIG_SDHCI=y -+CONFIG_VIRTFS=y -+CONFIG_VIRTIO_9P=y -+CONFIG_USB_EHCI=y -+CONFIG_USB_EHCI_PCI=y -+CONFIG_USB_EHCI_SYSBUS=y -+CONFIG_USB_STORAGE_BOT=y -+CONFIG_TPM_EMULATOR=y -+CONFIG_TPM_TIS=y -+CONFIG_PLATFORM_BUS=y -+CONFIG_TPM_TIS_SYSBUS=y -+CONFIG_ACPI_LOONGARCH=y -+CONFIG_LS7A_RTC=y -diff --git a/configs/targets/loongarch64-softmmu.mak b/configs/targets/loongarch64-softmmu.mak -new file mode 100644 -index 0000000000..dc5ab39661 ---- /dev/null -+++ b/configs/targets/loongarch64-softmmu.mak -@@ -0,0 +1,4 @@ -+TARGET_ARCH=loongarch64 -+TARGET_SUPPORTS_MTTCG=y -+TARGET_XML_FILES= gdb-xml/loongarch-base64.xml gdb-xml/loongarch-fpu64.xml -+ -diff --git a/disas/loongarch.c b/disas/loongarch.c -new file mode 100644 -index 0000000000..14dd131e2e ---- /dev/null -+++ b/disas/loongarch.c -@@ -0,0 +1,2748 @@ -+/* -+ * QEMU Loongarch Disassembler -+ * -+ * Copyright (c) 2020-2021. -+ * Author: Song Gao, gaosong@loongson.cn -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2 or later, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program. If not, see . -+ */ -+ -+#include "qemu/osdep.h" -+#include "disas/dis-asm.h" -+ -+#define INSNLEN 4 -+ -+/* types */ -+ -+typedef uint16_t la_opcode; -+ -+/* enums */ -+ -+typedef enum { -+ la_op_illegal = 0, -+ la_op_gr2scr = 1, -+ la_op_scr2gr = 2, -+ la_op_clo_w = 3, -+ la_op_clz_w = 4, -+ la_op_cto_w = 5, -+ la_op_ctz_w = 6, -+ la_op_clo_d = 7, -+ la_op_clz_d = 8, -+ la_op_cto_d = 9, -+ la_op_ctz_d = 10, -+ la_op_revb_2h = 11, -+ la_op_revb_4h = 12, -+ la_op_revb_2w = 13, -+ la_op_revb_d = 14, -+ la_op_revh_2w = 15, -+ la_op_revh_d = 16, -+ la_op_bitrev_4b = 17, -+ la_op_bitrev_8b = 18, -+ la_op_bitrev_w = 19, -+ la_op_bitrev_d = 20, -+ la_op_ext_w_h = 21, -+ la_op_ext_w_b = 22, -+ la_op_rdtime_d = 23, -+ la_op_cpucfg = 24, -+ la_op_asrtle_d = 25, -+ la_op_asrtgt_d = 26, -+ la_op_alsl_w = 27, -+ la_op_alsl_wu = 28, -+ la_op_bytepick_w = 29, -+ la_op_bytepick_d = 30, -+ la_op_add_w = 31, -+ la_op_add_d = 32, -+ la_op_sub_w = 33, -+ la_op_sub_d = 34, -+ la_op_slt = 35, -+ la_op_sltu = 36, -+ la_op_maskeqz = 37, -+ la_op_masknez = 38, -+ la_op_nor = 39, -+ la_op_and = 40, -+ la_op_or = 41, -+ la_op_xor = 42, -+ la_op_orn = 43, -+ la_op_andn = 44, -+ la_op_sll_w = 45, -+ la_op_srl_w = 46, -+ la_op_sra_w = 47, -+ la_op_sll_d = 48, -+ la_op_srl_d = 49, -+ la_op_sra_d = 50, -+ la_op_rotr_w = 51, -+ la_op_rotr_d = 52, -+ la_op_mul_w = 53, -+ la_op_mulh_w = 54, -+ la_op_mulh_wu = 55, -+ la_op_mul_d = 56, -+ la_op_mulh_d = 57, -+ la_op_mulh_du = 58, -+ la_op_mulw_d_w = 59, -+ la_op_mulw_d_wu = 60, -+ la_op_div_w = 61, -+ la_op_mod_w = 62, -+ la_op_div_wu = 63, -+ la_op_mod_wu = 64, -+ la_op_div_d = 65, -+ la_op_mod_d = 66, -+ la_op_div_du = 67, -+ la_op_mod_du = 68, -+ la_op_crc_w_b_w = 69, -+ la_op_crc_w_h_w = 70, -+ la_op_crc_w_w_w = 71, -+ la_op_crc_w_d_w = 72, -+ la_op_crcc_w_b_w = 73, -+ la_op_crcc_w_h_w = 74, -+ la_op_crcc_w_w_w = 75, -+ la_op_crcc_w_d_w = 76, -+ la_op_break = 77, -+ la_op_dbcl = 78, -+ la_op_syscall = 79, -+ la_op_alsl_d = 80, -+ la_op_slli_w = 81, -+ la_op_slli_d = 82, -+ la_op_srli_w = 83, -+ la_op_srli_d = 84, -+ la_op_srai_w = 85, -+ la_op_srai_d = 86, -+ la_op_rotri_w = 87, -+ la_op_rotri_d = 88, -+ la_op_bstrins_w = 89, -+ la_op_bstrpick_w = 90, -+ la_op_bstrins_d = 91, -+ la_op_bstrpick_d = 92, -+ la_op_fadd_s = 93, -+ la_op_fadd_d = 94, -+ la_op_fsub_s = 95, -+ la_op_fsub_d = 96, -+ la_op_fmul_s = 97, -+ la_op_fmul_d = 98, -+ la_op_fdiv_s = 99, -+ la_op_fdiv_d = 100, -+ la_op_fmax_s = 101, -+ la_op_fmax_d = 102, -+ la_op_fmin_s = 103, -+ la_op_fmin_d = 104, -+ la_op_fmaxa_s = 105, -+ la_op_fmaxa_d = 106, -+ la_op_fmina_s = 107, -+ la_op_fmina_d = 108, -+ la_op_fscaleb_s = 109, -+ la_op_fscaleb_d = 110, -+ la_op_fcopysign_s = 111, -+ la_op_fcopysign_d = 112, -+ la_op_fabs_s = 113, -+ la_op_fabs_d = 114, -+ la_op_fneg_s = 115, -+ la_op_fneg_d = 116, -+ la_op_flogb_s = 117, -+ la_op_flogb_d = 118, -+ la_op_fclass_s = 119, -+ la_op_fclass_d = 120, -+ la_op_fsqrt_s = 121, -+ la_op_fsqrt_d = 122, -+ la_op_frecip_s = 123, -+ la_op_frecip_d = 124, -+ la_op_frsqrt_s = 125, -+ la_op_frsqrt_d = 126, -+ la_op_fmov_s = 127, -+ la_op_fmov_d = 128, -+ la_op_movgr2fr_w = 129, -+ la_op_movgr2fr_d = 130, -+ la_op_movgr2frh_w = 131, -+ la_op_movfr2gr_s = 132, -+ la_op_movfr2gr_d = 133, -+ la_op_movfrh2gr_s = 134, -+ la_op_movgr2fcsr = 135, -+ la_op_movfcsr2gr = 136, -+ la_op_movfr2cf = 137, -+ la_op_movcf2fr = 138, -+ la_op_movgr2cf = 139, -+ la_op_movcf2gr = 140, -+ la_op_fcvt_s_d = 141, -+ la_op_fcvt_d_s = 142, -+ -+ la_op_ftintrm_w_s = 143, -+ la_op_ftintrm_w_d = 144, -+ la_op_ftintrm_l_s = 145, -+ la_op_ftintrm_l_d = 146, -+ la_op_ftintrp_w_s = 147, -+ la_op_ftintrp_w_d = 148, -+ la_op_ftintrp_l_s = 149, -+ la_op_ftintrp_l_d = 150, -+ la_op_ftintrz_w_s = 151, -+ la_op_ftintrz_w_d = 152, -+ la_op_ftintrz_l_s = 153, -+ la_op_ftintrz_l_d = 154, -+ la_op_ftintrne_w_s = 155, -+ la_op_ftintrne_w_d = 156, -+ la_op_ftintrne_l_s = 157, -+ la_op_ftintrne_l_d = 158, -+ la_op_ftint_w_s = 159, -+ la_op_ftint_w_d = 160, -+ la_op_ftint_l_s = 161, -+ la_op_ftint_l_d = 162, -+ la_op_ffint_s_w = 163, -+ la_op_ffint_s_l = 164, -+ la_op_ffint_d_w = 165, -+ la_op_ffint_d_l = 166, -+ la_op_frint_s = 167, -+ la_op_frint_d = 168, -+ -+ la_op_slti = 169, -+ la_op_sltui = 170, -+ la_op_addi_w = 171, -+ la_op_addi_d = 172, -+ la_op_lu52i_d = 173, -+ la_op_addi = 174, -+ la_op_ori = 175, -+ la_op_xori = 176, -+ -+ la_op_csrxchg = 177, -+ la_op_cacop = 178, -+ la_op_lddir = 179, -+ la_op_ldpte = 180, -+ la_op_iocsrrd_b = 181, -+ la_op_iocsrrd_h = 182, -+ la_op_iocsrrd_w = 183, -+ la_op_iocsrrd_d = 184, -+ la_op_iocsrwr_b = 185, -+ la_op_iocsrwr_h = 186, -+ la_op_iocsrwr_w = 187, -+ la_op_iocsrwr_d = 188, -+ la_op_tlbclr = 189, -+ la_op_tlbflush = 190, -+ la_op_tlbsrch = 191, -+ la_op_tlbrd = 192, -+ la_op_tlbwr = 193, -+ la_op_tlbfill = 194, -+ la_op_ertn = 195, -+ la_op_idle = 196, -+ la_op_invtlb = 197, -+ -+ la_op_fmadd_s = 198, -+ la_op_fmadd_d = 199, -+ la_op_fmsub_s = 200, -+ la_op_fmsub_d = 201, -+ la_op_fnmadd_s = 202, -+ la_op_fnmadd_d = 203, -+ la_op_fnmsub_s = 204, -+ la_op_fnmsub_d = 205, -+ la_op_fcmp_cond_s = 206, -+ la_op_fcmp_cond_d = 207, -+ la_op_fsel = 208, -+ la_op_addu16i_d = 209, -+ la_op_lu12i_w = 210, -+ la_op_lu32i_d = 211, -+ la_op_pcaddi = 212, -+ la_op_pcalau12i = 213, -+ la_op_pcaddu12i = 214, -+ la_op_pcaddu18i = 215, -+ -+ la_op_ll_w = 216, -+ la_op_sc_w = 217, -+ la_op_ll_d = 218, -+ la_op_sc_d = 219, -+ la_op_ldptr_w = 220, -+ la_op_stptr_w = 221, -+ la_op_ldptr_d = 222, -+ la_op_stptr_d = 223, -+ la_op_ld_b = 224, -+ la_op_ld_h = 225, -+ la_op_ld_w = 226, -+ la_op_ld_d = 227, -+ la_op_st_b = 228, -+ la_op_st_h = 229, -+ la_op_st_w = 230, -+ la_op_st_d = 231, -+ la_op_ld_bu = 232, -+ la_op_ld_hu = 233, -+ la_op_ld_wu = 234, -+ la_op_preld = 235, -+ la_op_fld_s = 236, -+ la_op_fst_s = 237, -+ la_op_fld_d = 238, -+ la_op_fst_d = 239, -+ la_op_ldl_w = 240, -+ la_op_ldr_w = 241, -+ la_op_ldl_d = 242, -+ la_op_ldr_d = 243, -+ la_op_stl_d = 244, -+ la_op_str_d = 245, -+ la_op_ldx_b = 246, -+ la_op_ldx_h = 247, -+ la_op_ldx_w = 248, -+ la_op_ldx_d = 249, -+ la_op_stx_b = 250, -+ la_op_stx_h = 251, -+ la_op_stx_w = 252, -+ la_op_stx_d = 253, -+ la_op_ldx_bu = 254, -+ la_op_ldx_hu = 255, -+ la_op_ldx_wu = 256, -+ la_op_fldx_s = 257, -+ la_op_fldx_d = 258, -+ la_op_fstx_s = 259, -+ la_op_fstx_d = 260, -+ -+ la_op_amswap_w = 261, -+ la_op_amswap_d = 262, -+ la_op_amadd_w = 263, -+ la_op_amadd_d = 264, -+ la_op_amand_w = 265, -+ la_op_amand_d = 266, -+ la_op_amor_w = 267, -+ la_op_amor_d = 268, -+ la_op_amxor_w = 269, -+ la_op_amxor_d = 270, -+ la_op_ammax_w = 271, -+ la_op_ammax_d = 272, -+ la_op_ammin_w = 273, -+ la_op_ammin_d = 274, -+ la_op_ammax_wu = 275, -+ la_op_ammax_du = 276, -+ la_op_ammin_wu = 277, -+ la_op_ammin_du = 278, -+ la_op_amswap_db_w = 279, -+ la_op_amswap_db_d = 280, -+ la_op_amadd_db_w = 281, -+ la_op_amadd_db_d = 282, -+ la_op_amand_db_w = 283, -+ la_op_amand_db_d = 284, -+ la_op_amor_db_w = 285, -+ la_op_amor_db_d = 286, -+ la_op_amxor_db_w = 287, -+ la_op_amxor_db_d = 288, -+ la_op_ammax_db_w = 289, -+ la_op_ammax_db_d = 290, -+ la_op_ammin_db_w = 291, -+ la_op_ammin_db_d = 292, -+ la_op_ammax_db_wu = 293, -+ la_op_ammax_db_du = 294, -+ la_op_ammin_db_wu = 295, -+ la_op_ammin_db_du = 296, -+ la_op_dbar = 297, -+ la_op_ibar = 298, -+ la_op_fldgt_s = 299, -+ la_op_fldgt_d = 300, -+ la_op_fldle_s = 301, -+ la_op_fldle_d = 302, -+ la_op_fstgt_s = 303, -+ la_op_fstgt_d = 304, -+ ls_op_fstle_s = 305, -+ la_op_fstle_d = 306, -+ la_op_ldgt_b = 307, -+ la_op_ldgt_h = 308, -+ la_op_ldgt_w = 309, -+ la_op_ldgt_d = 310, -+ la_op_ldle_b = 311, -+ la_op_ldle_h = 312, -+ la_op_ldle_w = 313, -+ la_op_ldle_d = 314, -+ la_op_stgt_b = 315, -+ la_op_stgt_h = 316, -+ la_op_stgt_w = 317, -+ la_op_stgt_d = 318, -+ la_op_stle_b = 319, -+ la_op_stle_h = 320, -+ la_op_stle_w = 321, -+ la_op_stle_d = 322, -+ la_op_beqz = 323, -+ la_op_bnez = 324, -+ la_op_bceqz = 325, -+ la_op_bcnez = 326, -+ la_op_jirl = 327, -+ la_op_b = 328, -+ la_op_bl = 329, -+ la_op_beq = 330, -+ la_op_bne = 331, -+ la_op_blt = 332, -+ la_op_bge = 333, -+ la_op_bltu = 334, -+ la_op_bgeu = 335, -+ -+ /* vz insn */ -+ la_op_hvcl = 336, -+ -+} la_op; -+ -+typedef enum { -+ la_codec_illegal, -+ la_codec_empty, -+ la_codec_2r, -+ la_codec_2r_u5, -+ la_codec_2r_u6, -+ la_codec_2r_2bw, -+ la_codec_2r_2bd, -+ la_codec_3r, -+ la_codec_3r_rd0, -+ la_codec_3r_sa2, -+ la_codec_3r_sa3, -+ la_codec_4r, -+ la_codec_r_im20, -+ la_codec_2r_im16, -+ la_codec_2r_im14, -+ la_codec_2r_im12, -+ la_codec_im5_r_im12, -+ la_codec_2r_im8, -+ la_codec_r_sd, -+ la_codec_r_sj, -+ la_codec_r_cd, -+ la_codec_r_cj, -+ la_codec_r_seq, -+ la_codec_code, -+ la_codec_whint, -+ la_codec_invtlb, -+ la_codec_r_ofs21, -+ la_codec_cj_ofs21, -+ la_codec_ofs26, -+ la_codec_cond, -+ la_codec_sel, -+ -+} la_codec; -+ -+#define la_fmt_illegal "nte" -+#define la_fmt_empty "nt" -+#define la_fmt_sd_rj "ntA,1" -+#define la_fmt_rd_sj "nt0,B" -+#define la_fmt_rd_rj "nt0,1" -+#define la_fmt_rj_rk "nt1,2" -+#define la_fmt_rj_seq "nt1,x" -+#define la_fmt_rd_si20 "nt0,i(x)" -+#define la_fmt_rd_rj_ui5 "nt0,1,C" -+#define la_fmt_rd_rj_ui6 "nt0,1.C" -+#define la_fmt_rd_rj_level "nt0,1,x" -+#define la_fmt_rd_rj_msbw_lsbw "nt0,1,C,D" -+#define la_fmt_rd_rj_msbd_lsbd "nt0,1,C,D" -+#define la_fmt_rd_rj_si12 "nt0,1,i(x)" -+#define la_fmt_hint_rj_si12 "ntE,1,i(x)" -+#define la_fmt_rd_rj_csr "nt0,1,x" -+#define la_fmt_rd_rj_si14 "nt0,1,i(x)" -+#define la_fmt_rd_rj_si16 "nt0,1,i(x)" -+#define la_fmt_rd_rj_rk "nt0,1,2" -+#define la_fmt_fd_rj_rk "nt3,1,2" -+#define la_fmt_rd_rj_rk_sa2 "nt0,1,2,D" -+#define la_fmt_rd_rj_rk_sa3 "nt0,1,2,D" -+#define la_fmt_fd_rj "nt3,1" -+#define la_fmt_rd_fj "nt0,4" -+#define la_fmt_fd_fj "nt3,4" -+#define la_fmt_fd_fj_si12 "nt3,4,i(x)" -+#define la_fmt_fcsrd_rj "ntF,1" -+#define la_fmt_rd_fcsrs "nt0,G" -+#define la_fmt_cd_fj "ntH,4" -+#define la_fmt_fd_cj "nt3,I" -+#define la_fmt_fd_fj_fk "nt3,4,5" -+#define la_fmt_code "ntJ" -+#define la_fmt_whint "ntx" -+#define la_fmt_invtlb "ntx,1,2" /* op,rj,rk */ -+#define la_fmt_offs26 "nto(X)p" -+#define la_fmt_rj_offs21 "nt1,o(X)p" -+#define la_fmt_cj_offs21 "ntQ,o(X)p" -+#define la_fmt_rd_rj_offs16 "nt0,1,o(X)" -+#define la_fmt_rj_rd_offs16 "nt1,0,o(X)p" -+#define la_fmt_s_cd_fj_fk "K.stH,4,5" -+#define la_fmt_d_cd_fj_fk "K.dtH,4,5" -+#define la_fmt_fd_fj_fk_fa "nt3,4,5,6" -+#define la_fmt_fd_fj_fk_ca "nt3,4,5,L" -+#define la_fmt_cop_rj_si12 "ntM,1,i(x)" -+ -+/* structures */ -+ -+typedef struct { -+ uint32_t pc; -+ uint32_t insn; -+ int32_t imm; -+ int32_t imm2; -+ uint16_t op; -+ uint16_t code; -+ uint8_t codec; -+ uint8_t r1; -+ uint8_t r2; -+ uint8_t r3; -+ uint8_t r4; -+ uint8_t bit; -+} la_decode; -+ -+typedef struct { -+ const char * const name; -+ const la_codec codec; -+ const char * const format; -+} la_opcode_data; -+ -+/* reg names */ -+ -+const char * const loongarch_r_normal_name[32] = { -+ "$r0", "$r1", "$r2", "$r3", "$r4", "$r5", "$r6", "$r7", -+ "$r8", "$r9", "$r10", "$r11", "$r12", "$r13", "$r14", "$r15", -+ "$r16", "$r17", "$r18", "$r19", "$r20", "$r21", "$r22", "$r23", -+ "$r24", "$r25", "$r26", "$r27", "$r28", "$r29", "$r30", "$r31", -+}; -+ -+const char * const loongarch_f_normal_name[32] = { -+ "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7", -+ "$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15", -+ "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23", -+ "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31", -+}; -+ -+const char * const loongarch_cr_normal_name[4] = { -+ "$scr0", "$scr1", "$scr2", "$scr3", -+}; -+ -+const char * const loongarch_c_normal_name[8] = { -+ "$fcc0", "$fcc1", "$fcc2", "$fcc3", "$fcc4", "$fcc5", "$fcc6", "$fcc7", -+}; -+ -+/* instruction data */ -+ -+const la_opcode_data opcode_data[] = { -+ { "illegal", la_codec_illegal, la_fmt_illegal }, -+ { "gr2scr", la_codec_r_sd, la_fmt_sd_rj }, -+ { "scr2gr", la_codec_r_sj, la_fmt_rd_sj }, -+ { "clo.w", la_codec_2r, la_fmt_rd_rj }, -+ { "clz.w", la_codec_2r, la_fmt_rd_rj }, -+ { "cto.w", la_codec_2r, la_fmt_rd_rj }, -+ { "ctz.w", la_codec_2r, la_fmt_rd_rj }, -+ { "clo.d", la_codec_2r, la_fmt_rd_rj }, -+ { "clz.d", la_codec_2r, la_fmt_rd_rj }, -+ { "cto.d", la_codec_2r, la_fmt_rd_rj }, -+ { "ctz_d", la_codec_2r, la_fmt_rd_rj }, -+ { "revb.2h", la_codec_2r, la_fmt_rd_rj }, -+ { "revb.4h", la_codec_2r, la_fmt_rd_rj }, -+ { "revb.2w", la_codec_2r, la_fmt_rd_rj }, -+ { "revb.d", la_codec_2r, la_fmt_rd_rj }, -+ { "revh.2w", la_codec_2r, la_fmt_rd_rj }, -+ { "revh.d", la_codec_2r, la_fmt_rd_rj }, -+ { "bitrev.4b", la_codec_2r, la_fmt_rd_rj }, -+ { "bitrev.8b", la_codec_2r, la_fmt_rd_rj }, -+ { "bitrev.w", la_codec_2r, la_fmt_rd_rj }, -+ { "bitrev.d", la_codec_2r, la_fmt_rd_rj }, -+ { "ext.w.h", la_codec_2r, la_fmt_rd_rj }, -+ { "ext.w.b", la_codec_2r, la_fmt_rd_rj }, -+ { "rdtime.d", la_codec_2r, la_fmt_rd_rj }, -+ { "cpucfg", la_codec_2r, la_fmt_rd_rj }, -+ { "asrtle.d", la_codec_3r_rd0, la_fmt_rj_rk }, -+ { "asrtgt.d", la_codec_3r_rd0, la_fmt_rj_rk }, -+ { "alsl.w", la_codec_3r_sa2, la_fmt_rd_rj_rk_sa2 }, -+ { "alsl.wu", la_codec_3r_sa2, la_fmt_rd_rj_rk_sa2 }, -+ { "bytepick.w", la_codec_3r_sa2, la_fmt_rd_rj_rk_sa2 }, -+ { "bytepick.d", la_codec_3r_sa3, la_fmt_rd_rj_rk_sa3 }, -+ { "add.w", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "add.d", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "sub.w", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "sub.d", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "slt", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "sltu", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "maskeqz", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "masknez", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "nor", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "and", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "or", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "xor", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "orn", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "andn", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "sll.w", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "srl.w", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "sra.w", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "sll.d", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "srl.d", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "sra.d", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "rotr.w", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "rotr.d", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "mul.w", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "mulh.w", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "mulh.wu", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "mul.d", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "mulh.d", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "mulh.du", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "mulw.d.w", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "mulw.d.wu", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "div.w", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "mod.w", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "div.wu", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "mod.wu", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "div.d", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "mod.d", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "div.du", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "mod.du", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "crc.w.b.w", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "crc.w.h.w", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "crc.w.w.w", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "crc.w.d.w", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "crcc.w.b.w", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "crcc.w.h.w", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "crcc.w.w.w", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "crcc.w.d.w", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "break", la_codec_code, la_fmt_code }, -+ { "dbcl", la_codec_code, la_fmt_code }, -+ { "syscall", la_codec_code, la_fmt_code }, -+ { "alsl.d", la_codec_3r_sa2, la_fmt_rd_rj_rk_sa2 }, -+ { "slli.w", la_codec_2r_u5, la_fmt_rd_rj_ui5 }, -+ { "slli.d", la_codec_2r_u6, la_fmt_rd_rj_ui6 }, -+ { "srli.w", la_codec_2r_u5, la_fmt_rd_rj_ui5 }, -+ { "srli.d", la_codec_2r_u6, la_fmt_rd_rj_ui6 }, -+ { "srai.w", la_codec_2r_u5, la_fmt_rd_rj_ui5 }, -+ { "srai.d", la_codec_2r_u6, la_fmt_rd_rj_ui6 }, -+ { "rotri.w", la_codec_2r_u5, la_fmt_rd_rj_ui5 }, -+ { "rotri.d", la_codec_2r_u6, la_fmt_rd_rj_ui6 }, -+ { "bstrins.w", la_codec_2r_2bw, la_fmt_rd_rj_msbw_lsbw }, -+ { "bstrpick.w", la_codec_2r_2bw, la_fmt_rd_rj_msbw_lsbw }, -+ { "bstrins.d", la_codec_2r_2bd, la_fmt_rd_rj_msbd_lsbd }, -+ { "bstrpick.d", la_codec_2r_2bd, la_fmt_rd_rj_msbd_lsbd }, -+ { "fadd.s", la_codec_3r, la_fmt_fd_fj_fk }, -+ { "fadd.d", la_codec_3r, la_fmt_fd_fj_fk }, -+ { "fsub.s", la_codec_3r, la_fmt_fd_fj_fk }, -+ { "fsub.d", la_codec_3r, la_fmt_fd_fj_fk }, -+ { "fmul.s", la_codec_3r, la_fmt_fd_fj_fk }, -+ { "fmul.d", la_codec_3r, la_fmt_fd_fj_fk }, -+ { "fdiv.s", la_codec_3r, la_fmt_fd_fj_fk }, -+ { "fdiv.d", la_codec_3r, la_fmt_fd_fj_fk }, -+ { "fmax.s", la_codec_3r, la_fmt_fd_fj_fk }, -+ { "fmax.d", la_codec_3r, la_fmt_fd_fj_fk }, -+ { "fmin.s", la_codec_3r, la_fmt_fd_fj_fk }, -+ { "fmin.d", la_codec_3r, la_fmt_fd_fj_fk }, -+ { "fmaxa.s", la_codec_3r, la_fmt_fd_fj_fk }, -+ { "fmaxa.d", la_codec_3r, la_fmt_fd_fj_fk }, -+ { "fmina.s", la_codec_3r, la_fmt_fd_fj_fk }, -+ { "fmina.d", la_codec_3r, la_fmt_fd_fj_fk }, -+ { "fscaleb.s", la_codec_3r, la_fmt_fd_fj_fk }, -+ { "fscaleb.d", la_codec_3r, la_fmt_fd_fj_fk }, -+ { "fcopysign.s", la_codec_3r, la_fmt_fd_fj_fk }, -+ { "fcopysign.d", la_codec_3r, la_fmt_fd_fj_fk }, -+ { "fabs.s", la_codec_2r, la_fmt_fd_fj }, -+ { "fabs.d", la_codec_2r, la_fmt_fd_fj }, -+ { "fneg.s", la_codec_2r, la_fmt_fd_fj }, -+ { "fneg.d", la_codec_2r, la_fmt_fd_fj }, -+ { "flogb.s", la_codec_2r, la_fmt_fd_fj }, -+ { "flogb.d", la_codec_2r, la_fmt_fd_fj }, -+ { "fclass.s", la_codec_2r, la_fmt_fd_fj }, -+ { "fclass.d", la_codec_2r, la_fmt_fd_fj }, -+ { "fsqrt.s", la_codec_2r, la_fmt_fd_fj }, -+ { "fsqrt.d", la_codec_2r, la_fmt_fd_fj }, -+ { "frecip.s", la_codec_2r, la_fmt_fd_fj }, -+ { "frecip.d", la_codec_2r, la_fmt_fd_fj }, -+ { "frsqrt.s", la_codec_2r, la_fmt_fd_fj }, -+ { "frsqrt.d", la_codec_2r, la_fmt_fd_fj }, -+ { "fmov.s", la_codec_2r, la_fmt_fd_fj }, -+ { "fmov.d", la_codec_2r, la_fmt_fd_fj }, -+ { "movgr2fr.w", la_codec_2r, la_fmt_fd_rj }, -+ { "movgr2fr.d", la_codec_2r, la_fmt_fd_rj }, -+ { "movgr2frh.w", la_codec_2r, la_fmt_fd_rj }, -+ { "movfr2gr.s", la_codec_2r, la_fmt_rd_fj }, -+ { "movfr2gr.d", la_codec_2r, la_fmt_rd_fj }, -+ { "movfrh2gr.s", la_codec_2r, la_fmt_rd_fj }, -+ { "movgr2fcsr", la_codec_2r, la_fmt_fcsrd_rj }, -+ { "movfcsr2gr", la_codec_2r, la_fmt_rd_fcsrs }, -+ { "movfr2cf", la_codec_r_cd, la_fmt_cd_fj }, -+ { "movcf2fr", la_codec_r_cj, la_fmt_fd_cj }, -+ { "movgr2cf", la_codec_r_cd, la_fmt_cd_fj }, -+ { "movcf2gr", la_codec_r_cj, la_fmt_fd_cj }, -+ { "fcvt.s.d", la_codec_2r, la_fmt_fd_fj }, -+ { "fcvt.d.s", la_codec_2r, la_fmt_fd_fj }, -+ { "ftintrm.w.s", la_codec_2r, la_fmt_fd_fj }, -+ { "ftintrm.w.d", la_codec_2r, la_fmt_fd_fj }, -+ { "ftintrm.l.s", la_codec_2r, la_fmt_fd_fj }, -+ { "ftintrm.l.d", la_codec_2r, la_fmt_fd_fj }, -+ { "ftintrp.w.s", la_codec_2r, la_fmt_fd_fj }, -+ { "ftintrp.w.d", la_codec_2r, la_fmt_fd_fj }, -+ { "ftintrp.l.s", la_codec_2r, la_fmt_fd_fj }, -+ { "ftintrp.l.d", la_codec_2r, la_fmt_fd_fj }, -+ { "ftintrz.w.s", la_codec_2r, la_fmt_fd_fj }, -+ { "ftintrz.w.d", la_codec_2r, la_fmt_fd_fj }, -+ { "ftintrz.l.s", la_codec_2r, la_fmt_fd_fj }, -+ { "ftintrz.l.d", la_codec_2r, la_fmt_fd_fj }, -+ { "ftintrne.w.s", la_codec_2r, la_fmt_fd_fj }, -+ { "ftintrne.w.d", la_codec_2r, la_fmt_fd_fj }, -+ { "ftintrne.l.s", la_codec_2r, la_fmt_fd_fj }, -+ { "ftintrne.l.d", la_codec_2r, la_fmt_fd_fj }, -+ { "ftint.w.s", la_codec_2r, la_fmt_fd_fj }, -+ { "ftint.w.d", la_codec_2r, la_fmt_fd_fj }, -+ { "ftint.l.s", la_codec_2r, la_fmt_fd_fj }, -+ { "ftint.l.d", la_codec_2r, la_fmt_fd_fj }, -+ { "ffint.s.w", la_codec_2r, la_fmt_fd_fj }, -+ { "ffint.s.l", la_codec_2r, la_fmt_fd_fj }, -+ { "ffint.d.w", la_codec_2r, la_fmt_fd_fj }, -+ { "ffint.d.l", la_codec_2r, la_fmt_fd_fj }, -+ { "frint.s", la_codec_2r, la_fmt_fd_fj }, -+ { "frint.d", la_codec_2r, la_fmt_fd_fj }, -+ { "slti", la_codec_2r_im12, la_fmt_rd_rj_si12 }, -+ { "sltui", la_codec_2r_im12, la_fmt_rd_rj_si12 }, -+ { "addi.w", la_codec_2r_im12, la_fmt_rd_rj_si12 }, -+ { "addi.d", la_codec_2r_im12, la_fmt_rd_rj_si12 }, -+ { "lu52i.d", la_codec_2r_im12, la_fmt_rd_rj_si12 }, -+ { "addi", la_codec_2r_im12, la_fmt_rd_rj_si12 }, -+ { "ori", la_codec_2r_im12, la_fmt_rd_rj_si12 }, -+ { "xori", la_codec_2r_im12, la_fmt_rd_rj_si12 }, -+ { "csrxchg", la_codec_2r_im14, la_fmt_rd_rj_csr }, -+ { "cacop", la_codec_im5_r_im12, la_fmt_cop_rj_si12 }, -+ { "lddir", la_codec_2r_im8, la_fmt_rd_rj_level }, -+ { "ldpte", la_codec_r_seq, la_fmt_rj_seq }, -+ { "iocsrrd.b", la_codec_2r, la_fmt_rd_rj }, -+ { "iocsrrd.h", la_codec_2r, la_fmt_rd_rj }, -+ { "iocsrrd.w", la_codec_2r, la_fmt_rd_rj }, -+ { "iocsrrd.d", la_codec_2r, la_fmt_rd_rj }, -+ { "iocsrwr.b", la_codec_2r, la_fmt_rd_rj }, -+ { "iocsrwr.h", la_codec_2r, la_fmt_rd_rj }, -+ { "iocsrwr.w", la_codec_2r, la_fmt_rd_rj }, -+ { "iocsrwr.d", la_codec_2r, la_fmt_rd_rj }, -+ { "tlbclr", la_codec_empty, la_fmt_empty }, -+ { "tlbflush", la_codec_empty, la_fmt_empty }, -+ { "tlbsrch", la_codec_empty, la_fmt_empty }, -+ { "tlbrd", la_codec_empty, la_fmt_empty }, -+ { "tlbwr", la_codec_empty, la_fmt_empty }, -+ { "tlbfill", la_codec_empty, la_fmt_empty }, -+ { "ertn", la_codec_empty, la_fmt_empty }, -+ { "idle", la_codec_whint, la_fmt_whint }, -+ { "invtlb", la_codec_invtlb, la_fmt_invtlb }, -+ { "fmadd.s", la_codec_4r, la_fmt_fd_fj_fk_fa }, -+ { "fmadd.d", la_codec_4r, la_fmt_fd_fj_fk_fa }, -+ { "fmsub.s", la_codec_4r, la_fmt_fd_fj_fk_fa }, -+ { "fmsub.d", la_codec_4r, la_fmt_fd_fj_fk_fa }, -+ { "fnmadd.s", la_codec_4r, la_fmt_fd_fj_fk_fa }, -+ { "fnmadd.d", la_codec_4r, la_fmt_fd_fj_fk_fa }, -+ { "fnmsub.s", la_codec_4r, la_fmt_fd_fj_fk_fa }, -+ { "fnmsub.d", la_codec_4r, la_fmt_fd_fj_fk_fa }, -+ { "fcmp.cond.s", la_codec_cond, la_fmt_s_cd_fj_fk }, -+ { "fcmp.cond.d", la_codec_cond, la_fmt_d_cd_fj_fk }, -+ { "fsel", la_codec_sel, la_fmt_fd_fj_fk_ca }, -+ { "addu16i.d", la_codec_2r_im16, la_fmt_rd_rj_si16 }, -+ { "lu12i.w", la_codec_r_im20, la_fmt_rd_si20 }, -+ { "lu32i.d", la_codec_r_im20, la_fmt_rd_si20 }, -+ { "pcaddi", la_codec_r_im20, la_fmt_rd_si20 }, -+ { "pcalau12i", la_codec_r_im20, la_fmt_rd_si20 }, -+ { "pcaddu12i", la_codec_r_im20, la_fmt_rd_si20 }, -+ { "pcaddu18i", la_codec_r_im20, la_fmt_rd_si20 }, -+ { "ll.w", la_codec_2r_im14, la_fmt_rd_rj_si14 }, -+ { "sc.w", la_codec_2r_im14, la_fmt_rd_rj_si14 }, -+ { "ll.d", la_codec_2r_im14, la_fmt_rd_rj_si14 }, -+ { "sc.d", la_codec_2r_im14, la_fmt_rd_rj_si14 }, -+ { "ldptr.w", la_codec_2r_im14, la_fmt_rd_rj_si14 }, -+ { "stptr.w", la_codec_2r_im14, la_fmt_rd_rj_si14 }, -+ { "ldptr.d", la_codec_2r_im14, la_fmt_rd_rj_si14 }, -+ { "stptr.d", la_codec_2r_im14, la_fmt_rd_rj_si14 }, -+ { "ld.b", la_codec_2r_im12, la_fmt_rd_rj_si12 }, -+ { "ld.h", la_codec_2r_im12, la_fmt_rd_rj_si12 }, -+ { "ld.w", la_codec_2r_im12, la_fmt_rd_rj_si12 }, -+ { "ld.d", la_codec_2r_im12, la_fmt_rd_rj_si12 }, -+ { "st.b", la_codec_2r_im12, la_fmt_rd_rj_si12 }, -+ { "st.h", la_codec_2r_im12, la_fmt_rd_rj_si12 }, -+ { "st.w", la_codec_2r_im12, la_fmt_rd_rj_si12 }, -+ { "st.d", la_codec_2r_im12, la_fmt_rd_rj_si12 }, -+ { "ld.bu", la_codec_2r_im12, la_fmt_rd_rj_si12 }, -+ { "ld.hu", la_codec_2r_im12, la_fmt_rd_rj_si12 }, -+ { "ld.wu", la_codec_2r_im12, la_fmt_rd_rj_si12 }, -+ { "preld", la_codec_2r_im12, la_fmt_hint_rj_si12 }, -+ { "fld.s", la_codec_2r_im12, la_fmt_fd_fj_si12 }, -+ { "fst.s", la_codec_2r_im12, la_fmt_fd_fj_si12 }, -+ { "fld.d", la_codec_2r_im12, la_fmt_fd_fj_si12 }, -+ { "fst.d", la_codec_2r_im12, la_fmt_fd_fj_si12 }, -+ { "ldl.w", la_codec_2r_im12, la_fmt_rd_rj_si12 }, -+ { "ldr.w", la_codec_2r_im12, la_fmt_rd_rj_si12 }, -+ { "ldl.d", la_codec_2r_im12, la_fmt_rd_rj_si12 }, -+ { "ldr.d", la_codec_2r_im12, la_fmt_rd_rj_si12 }, -+ { "stl.d", la_codec_2r_im12, la_fmt_rd_rj_si12 }, -+ { "str.d", la_codec_2r_im12, la_fmt_rd_rj_si12 }, -+ { "ldx.b", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "ldx.h", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "ldx.w", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "ldx.d", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "stx.b", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "stx.h", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "stx.w", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "stx.d", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "ldx.bu", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "ldx.hu", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "ldx.wu", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "fldx.s", la_codec_3r, la_fmt_fd_rj_rk }, -+ { "fldx.d", la_codec_3r, la_fmt_fd_rj_rk }, -+ { "fstx.s", la_codec_3r, la_fmt_fd_rj_rk }, -+ { "fstx.d", la_codec_3r, la_fmt_fd_rj_rk }, -+ { "amswap.w", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "amswap.d", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "amadd.w", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "amadd.d", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "amand.w", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "amand.d", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "amor.w", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "amor.d", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "amxor.w", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "amxor.d", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "ammax.w", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "ammax.d", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "ammin.w", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "ammin.d", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "ammax.wu", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "ammax.du", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "ammin.wu", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "ammin.du", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "amswap.db.w", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "amswap.db.d", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "amadd.db.w", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "amadd.db.d", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "amand.db.w", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "amand.db.d", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "amor.db.w", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "amor.db.d", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "amxor.db.w", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "amxor.db.d", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "ammax.db.w", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "ammax.db.d", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "ammin.db.w", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "ammin.db.d", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "ammax.db.wu", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "ammax.db.du", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "ammin.db.wu", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "ammin.db.du", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "dbar", la_codec_whint, la_fmt_whint }, -+ { "ibar", la_codec_whint, la_fmt_whint }, -+ { "fldgt.s", la_codec_3r, la_fmt_fd_rj_rk }, -+ { "fldgt.d", la_codec_3r, la_fmt_fd_rj_rk }, -+ { "fldle.s", la_codec_3r, la_fmt_fd_rj_rk }, -+ { "fldle.d", la_codec_3r, la_fmt_fd_rj_rk }, -+ { "fstgt.s", la_codec_3r, la_fmt_fd_rj_rk }, -+ { "fstgt.d", la_codec_3r, la_fmt_fd_rj_rk }, -+ { "fstle.s", la_codec_3r, la_fmt_fd_rj_rk }, -+ { "fstle.d", la_codec_3r, la_fmt_fd_rj_rk }, -+ { "ldgt.b", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "ldgt.h", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "ldgt.w", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "ldgt.d", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "ldle.b", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "ldle.h", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "ldle.w", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "ldle.d", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "stgt.b", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "stgt.h", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "stgt.w", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "stgt.d", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "stle.b", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "stle.h", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "stle.w", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "stle.d", la_codec_3r, la_fmt_rd_rj_rk }, -+ { "beqz", la_codec_r_ofs21, la_fmt_rj_offs21 }, -+ { "bnez", la_codec_r_ofs21, la_fmt_rj_offs21 }, -+ { "bceqz", la_codec_cj_ofs21, la_fmt_cj_offs21 }, -+ { "bcnez", la_codec_cj_ofs21, la_fmt_cj_offs21 }, -+ { "jirl", la_codec_2r_im16, la_fmt_rd_rj_offs16 }, -+ { "b", la_codec_ofs26, la_fmt_offs26 }, -+ { "bl", la_codec_ofs26, la_fmt_offs26 }, -+ { "beq", la_codec_2r_im16, la_fmt_rj_rd_offs16 }, -+ { "bne", la_codec_2r_im16, la_fmt_rj_rd_offs16 }, -+ { "blt", la_codec_2r_im16, la_fmt_rj_rd_offs16 }, -+ { "bge", la_codec_2r_im16, la_fmt_rj_rd_offs16 }, -+ { "bltu", la_codec_2r_im16, la_fmt_rj_rd_offs16 }, -+ { "bgeu", la_codec_2r_im16, la_fmt_rj_rd_offs16 }, -+ -+ /* vz insn */ -+ { "hvcl", la_codec_code, la_fmt_code }, -+ -+}; -+ -+ -+/* decode opcode */ -+ -+static void decode_insn_opcode(la_decode *dec) -+{ -+ uint32_t insn = dec->insn; -+ uint16_t op = la_op_illegal; -+ switch ((insn >> 26) & 0x3f) { -+ case 0x0: -+ switch ((insn >> 22) & 0xf) { -+ case 0x0: -+ switch ((insn >> 18) & 0xf) { -+ case 0x0: -+ switch ((insn >> 15) & 0x7) { -+ case 0x0: -+ switch ((insn >> 10) & 0x1f) { -+ case 0x2: -+ switch ((insn >> 2) & 0x7) { -+ case 0x0: -+ op = la_op_gr2scr; -+ break; -+ } -+ break; -+ case 0x3: -+ switch ((insn >> 7) & 0x7) { -+ case 0x0: -+ op = la_op_scr2gr; -+ break; -+ } -+ break; -+ case 0x4: -+ op = la_op_clo_w; -+ break; -+ case 0x5: -+ op = la_op_clz_w; -+ break; -+ case 0x6: -+ op = la_op_cto_w; -+ break; -+ case 0x7: -+ op = la_op_ctz_w; -+ break; -+ case 0x8: -+ op = la_op_clo_d; -+ break; -+ case 0x9: -+ op = la_op_clz_d; -+ break; -+ case 0xa: -+ op = la_op_cto_d; -+ break; -+ case 0xb: -+ op = la_op_ctz_d; -+ break; -+ case 0xc: -+ op = la_op_revb_2h; -+ break; -+ case 0xd: -+ op = la_op_revb_4h; -+ break; -+ case 0xe: -+ op = la_op_revb_2w; -+ break; -+ case 0xf: -+ op = la_op_revb_d; -+ break; -+ case 0x10: -+ op = la_op_revh_2w; -+ break; -+ case 0x11: -+ op = la_op_revh_d; -+ break; -+ case 0x12: -+ op = la_op_bitrev_4b; -+ break; -+ case 0x13: -+ op = la_op_bitrev_8b; -+ break; -+ case 0x14: -+ op = la_op_bitrev_w; -+ break; -+ case 0x15: -+ op = la_op_bitrev_d; -+ break; -+ case 0x16: -+ op = la_op_ext_w_h; -+ break; -+ case 0x17: -+ op = la_op_ext_w_b; -+ break; -+ case 0x1a: -+ op = la_op_rdtime_d; -+ break; -+ case 0x1b: -+ op = la_op_cpucfg; -+ break; -+ } -+ break; -+ case 0x2: -+ switch (insn & 0x0000001f) { -+ case 0x00000000: -+ op = la_op_asrtle_d; -+ break; -+ } -+ break; -+ case 0x3: -+ switch (insn & 0x0000001f) { -+ case 0x00000000: -+ op = la_op_asrtgt_d; -+ break; -+ } -+ break; -+ } -+ break; -+ case 0x1: -+ switch ((insn >> 17) & 0x1) { -+ case 0x0: -+ op = la_op_alsl_w; -+ break; -+ case 0x1: -+ op = la_op_alsl_wu; -+ break; -+ } -+ break; -+ case 0x2: -+ switch ((insn >> 17) & 0x1) { -+ case 0x0: -+ op = la_op_bytepick_w; -+ break; -+ } -+ break; -+ case 0x3: -+ op = la_op_bytepick_d; -+ break; -+ case 0x4: -+ switch ((insn >> 15) & 0x7) { -+ case 0x0: -+ op = la_op_add_w; -+ break; -+ case 0x1: -+ op = la_op_add_d; -+ break; -+ case 0x2: -+ op = la_op_sub_w; -+ break; -+ case 0x3: -+ op = la_op_sub_d; -+ break; -+ case 0x4: -+ op = la_op_slt; -+ break; -+ case 0x5: -+ op = la_op_sltu; -+ break; -+ case 0x6: -+ op = la_op_maskeqz; -+ break; -+ case 0x7: -+ op = la_op_masknez; -+ break; -+ } -+ break; -+ case 0x5: -+ switch ((insn >> 15) & 0x7) { -+ case 0x0: -+ op = la_op_nor; -+ break; -+ case 0x1: -+ op = la_op_and; -+ break; -+ case 0x2: -+ op = la_op_or; -+ break; -+ case 0x3: -+ op = la_op_xor; -+ break; -+ case 0x4: -+ op = la_op_orn; -+ break; -+ case 0x5: -+ op = la_op_andn; -+ break; -+ case 0x6: -+ op = la_op_sll_w; -+ break; -+ case 0x7: -+ op = la_op_srl_w; -+ break; -+ } -+ break; -+ case 0x6: -+ switch ((insn >> 15) & 0x7) { -+ case 0x0: -+ op = la_op_sra_w; -+ break; -+ case 0x1: -+ op = la_op_sll_d; -+ break; -+ case 0x2: -+ op = la_op_srl_d; -+ break; -+ case 0x3: -+ op = la_op_sra_d; -+ break; -+ case 0x6: -+ op = la_op_rotr_w; -+ break; -+ case 0x7: -+ op = la_op_rotr_d; -+ break; -+ } -+ break; -+ case 0x7: -+ switch ((insn >> 15) & 0x7) { -+ case 0x0: -+ op = la_op_mul_w; -+ break; -+ case 0x1: -+ op = la_op_mulh_w; -+ break; -+ case 0x2: -+ op = la_op_mulh_wu; -+ break; -+ case 0x3: -+ op = la_op_mul_d; -+ break; -+ case 0x4: -+ op = la_op_mulh_d; -+ break; -+ case 0x5: -+ op = la_op_mulh_du; -+ break; -+ case 0x6: -+ op = la_op_mulw_d_w; -+ break; -+ case 0x7: -+ op = la_op_mulw_d_wu; -+ break; -+ } -+ break; -+ case 0x8: -+ switch ((insn >> 15) & 0x7) { -+ case 0x0: -+ op = la_op_div_w; -+ break; -+ case 0x1: -+ op = la_op_mod_w; -+ break; -+ case 0x2: -+ op = la_op_div_wu; -+ break; -+ case 0x3: -+ op = la_op_mod_wu; -+ break; -+ case 0x4: -+ op = la_op_div_d; -+ break; -+ case 0x5: -+ op = la_op_mod_d; -+ break; -+ case 0x6: -+ op = la_op_div_du; -+ break; -+ case 0x7: -+ op = la_op_mod_du; -+ break; -+ } -+ break; -+ case 0x9: -+ switch ((insn >> 15) & 0x7) { -+ case 0x0: -+ op = la_op_crc_w_b_w; -+ break; -+ case 0x1: -+ op = la_op_crc_w_h_w; -+ break; -+ case 0x2: -+ op = la_op_crc_w_w_w; -+ break; -+ case 0x3: -+ op = la_op_crc_w_d_w; -+ break; -+ case 0x4: -+ op = la_op_crcc_w_b_w; -+ break; -+ case 0x5: -+ op = la_op_crcc_w_h_w; -+ break; -+ case 0x6: -+ op = la_op_crcc_w_w_w; -+ break; -+ case 0x7: -+ op = la_op_crcc_w_d_w; -+ break; -+ } -+ break; -+ case 0xa: -+ switch ((insn >> 15) & 0x7) { -+ case 0x4: -+ op = la_op_break; -+ break; -+ case 0x5: -+ op = la_op_dbcl; -+ break; -+ case 0x6: -+ op = la_op_syscall; -+ break; -+ case 0x7: -+ op = la_op_hvcl; -+ break; -+ } -+ break; -+ case 0xb: -+ switch ((insn >> 17) & 0x1) { -+ case 0x0: -+ op = la_op_alsl_d; -+ break; -+ } -+ break; -+ } -+ break; -+ case 0x1: -+ switch ((insn >> 21) & 0x1) { -+ case 0x0: -+ switch ((insn >> 16) & 0x1f) { -+ case 0x0: -+ switch ((insn >> 15) & 0x1) { -+ case 0x1: -+ op = la_op_slli_w; -+ break; -+ } -+ break; -+ case 0x1: -+ op = la_op_slli_d; -+ break; -+ case 0x4: -+ switch ((insn >> 15) & 0x1) { -+ case 0x1: -+ op = la_op_srli_w; -+ break; -+ } -+ break; -+ case 0x5: -+ op = la_op_srli_d; -+ break; -+ case 0x8: -+ switch ((insn >> 15) & 0x1) { -+ case 0x1: -+ op = la_op_srai_w; -+ break; -+ } -+ break; -+ case 0x9: -+ op = la_op_srai_d; -+ break; -+ case 0xc: -+ switch ((insn >> 15) & 0x1) { -+ case 0x1: -+ op = la_op_rotri_w; -+ break; -+ } -+ break; -+ case 0xd: -+ op = la_op_rotri_d; -+ break; -+ } -+ break; -+ case 0x1: -+ switch ((insn >> 15) & 0x1) { -+ case 0x0: -+ op = la_op_bstrins_w; -+ break; -+ case 0x1: -+ op = la_op_bstrpick_w; -+ break; -+ } -+ break; -+ } -+ break; -+ case 0x2: -+ op = la_op_bstrins_d; -+ break; -+ case 0x3: -+ op = la_op_bstrpick_d; -+ break; -+ case 0x4: -+ switch ((insn >> 15) & 0x7f) { -+ case 0x1: -+ op = la_op_fadd_s; -+ break; -+ case 0x2: -+ op = la_op_fadd_d; -+ break; -+ case 0x5: -+ op = la_op_fsub_s; -+ break; -+ case 0x6: -+ op = la_op_fsub_d; -+ break; -+ case 0x9: -+ op = la_op_fmul_s; -+ break; -+ case 0xa: -+ op = la_op_fmul_d; -+ break; -+ case 0xd: -+ op = la_op_fdiv_s; -+ break; -+ case 0xe: -+ op = la_op_fdiv_d; -+ break; -+ case 0x11: -+ op = la_op_fmax_s; -+ break; -+ case 0x12: -+ op = la_op_fmax_d; -+ break; -+ case 0x15: -+ op = la_op_fmin_s; -+ break; -+ case 0x16: -+ op = la_op_fmin_d; -+ break; -+ case 0x19: -+ op = la_op_fmaxa_s; -+ break; -+ case 0x1a: -+ op = la_op_fmaxa_d; -+ break; -+ case 0x1d: -+ op = la_op_fmina_s; -+ break; -+ case 0x1e: -+ op = la_op_fmina_d; -+ break; -+ case 0x21: -+ op = la_op_fscaleb_s; -+ break; -+ case 0x22: -+ op = la_op_fscaleb_d; -+ break; -+ case 0x25: -+ op = la_op_fcopysign_s; -+ break; -+ case 0x26: -+ op = la_op_fcopysign_d; -+ break; -+ case 0x28: -+ switch ((insn >> 10) & 0x1f) { -+ case 0x1: -+ op = la_op_fabs_s; -+ break; -+ case 0x2: -+ op = la_op_fabs_d; -+ break; -+ case 0x5: -+ op = la_op_fneg_s; -+ break; -+ case 0x6: -+ op = la_op_fneg_d; -+ break; -+ case 0x9: -+ op = la_op_flogb_s; -+ break; -+ case 0xa: -+ op = la_op_flogb_d; -+ break; -+ case 0xd: -+ op = la_op_fclass_s; -+ break; -+ case 0xe: -+ op = la_op_fclass_d; -+ break; -+ case 0x11: -+ op = la_op_fsqrt_s; -+ break; -+ case 0x12: -+ op = la_op_fsqrt_d; -+ break; -+ case 0x15: -+ op = la_op_frecip_s; -+ break; -+ case 0x16: -+ op = la_op_frecip_d; -+ break; -+ case 0x19: -+ op = la_op_frsqrt_s; -+ break; -+ case 0x1a: -+ op = la_op_frsqrt_d; -+ break; -+ } -+ break; -+ case 0x29: -+ switch ((insn >> 10) & 0x1f) { -+ case 0x5: -+ op = la_op_fmov_s; -+ break; -+ case 0x6: -+ op = la_op_fmov_d; -+ break; -+ case 0x9: -+ op = la_op_movgr2fr_w; -+ break; -+ case 0xa: -+ op = la_op_movgr2fr_d; -+ break; -+ case 0xb: -+ op = la_op_movgr2frh_w; -+ break; -+ case 0xd: -+ op = la_op_movfr2gr_s; -+ break; -+ case 0xe: -+ op = la_op_movfr2gr_d; -+ break; -+ case 0xf: -+ op = la_op_movfrh2gr_s; -+ break; -+ case 0x10: -+ op = la_op_movgr2fcsr; -+ break; -+ case 0x12: -+ op = la_op_movfcsr2gr; -+ break; -+ case 0x14: -+ switch ((insn >> 3) & 0x3) { -+ case 0x0: -+ op = la_op_movfr2cf; -+ break; -+ } -+ break; -+ case 0x15: -+ switch ((insn >> 8) & 0x3) { -+ case 0x0: -+ op = la_op_movcf2fr; -+ break; -+ } -+ break; -+ case 0x16: -+ switch ((insn >> 3) & 0x3) { -+ case 0x0: -+ op = la_op_movgr2cf; -+ break; -+ } -+ break; -+ case 0x17: -+ switch ((insn >> 8) & 0x3) { -+ case 0x0: -+ op = la_op_movcf2gr; -+ break; -+ } -+ break; -+ } -+ break; -+ case 0x32: -+ switch ((insn >> 10) & 0x1f) { -+ case 0x6: -+ op = la_op_fcvt_s_d; -+ break; -+ case 0x9: -+ op = la_op_fcvt_d_s; -+ break; -+ } -+ break; -+ case 0x34: -+ switch ((insn >> 10) & 0x1f) { -+ case 0x1: -+ op = la_op_ftintrm_w_s; -+ break; -+ case 0x2: -+ op = la_op_ftintrm_w_d; -+ break; -+ case 0x9: -+ op = la_op_ftintrm_l_s; -+ break; -+ case 0xa: -+ op = la_op_ftintrm_l_d; -+ break; -+ case 0x11: -+ op = la_op_ftintrp_w_s; -+ break; -+ case 0x12: -+ op = la_op_ftintrp_w_d; -+ break; -+ case 0x19: -+ op = la_op_ftintrp_l_s; -+ break; -+ case 0x1a: -+ op = la_op_ftintrp_l_d; -+ break; -+ } -+ break; -+ case 0x35: -+ switch ((insn >> 10) & 0x1f) { -+ case 0x1: -+ op = la_op_ftintrz_w_s; -+ break; -+ case 0x2: -+ op = la_op_ftintrz_w_d; -+ break; -+ case 0x9: -+ op = la_op_ftintrz_l_s; -+ break; -+ case 0xa: -+ op = la_op_ftintrz_l_d; -+ break; -+ case 0x11: -+ op = la_op_ftintrne_w_s; -+ break; -+ case 0x12: -+ op = la_op_ftintrne_w_d; -+ break; -+ case 0x19: -+ op = la_op_ftintrne_l_s; -+ break; -+ case 0x1a: -+ op = la_op_ftintrne_l_d; -+ break; -+ } -+ break; -+ case 0x36: -+ switch ((insn >> 10) & 0x1f) { -+ case 0x1: -+ op = la_op_ftint_w_s; -+ break; -+ case 0x2: -+ op = la_op_ftint_w_d; -+ break; -+ case 0x9: -+ op = la_op_ftint_l_s; -+ break; -+ case 0xa: -+ op = la_op_ftint_l_d; -+ break; -+ } -+ break; -+ case 0x3a: -+ switch ((insn >> 10) & 0x1f) { -+ case 0x4: -+ op = la_op_ffint_s_w; -+ break; -+ case 0x6: -+ op = la_op_ffint_s_l; -+ break; -+ case 0x8: -+ op = la_op_ffint_d_w; -+ break; -+ case 0xa: -+ op = la_op_ffint_d_l; -+ break; -+ } -+ break; -+ case 0x3c: -+ switch ((insn >> 10) & 0x1f) { -+ case 0x11: -+ op = la_op_frint_s; -+ break; -+ case 0x12: -+ op = la_op_frint_d; -+ break; -+ } -+ break; -+ } -+ break; -+ case 0x8: -+ op = la_op_slti; -+ break; -+ case 0x9: -+ op = la_op_sltui; -+ break; -+ case 0xa: -+ op = la_op_addi_w; -+ break; -+ case 0xb: -+ op = la_op_addi_d; -+ break; -+ case 0xc: -+ op = la_op_lu52i_d; -+ break; -+ case 0xd: -+ op = la_op_addi; -+ break; -+ case 0xe: -+ op = la_op_ori; -+ break; -+ case 0xf: -+ op = la_op_xori; -+ break; -+ } -+ break; -+ case 0x1: -+ switch ((insn >> 24) & 0x3) { -+ case 0x0: -+ op = la_op_csrxchg; -+ break; -+ case 0x2: -+ switch ((insn >> 22) & 0x3) { -+ case 0x0: -+ op = la_op_cacop; -+ break; -+ case 0x1: -+ switch ((insn >> 18) & 0xf) { -+ case 0x0: -+ op = la_op_lddir; -+ break; -+ case 0x1: -+ switch (insn & 0x0000001f) { -+ case 0x00000000: -+ op = la_op_ldpte; -+ break; -+ } -+ break; -+ case 0x2: -+ switch ((insn >> 15) & 0x7) { -+ case 0x0: -+ switch ((insn >> 10) & 0x1f) { -+ case 0x0: -+ op = la_op_iocsrrd_b; -+ break; -+ case 0x1: -+ op = la_op_iocsrrd_h; -+ break; -+ case 0x2: -+ op = la_op_iocsrrd_w; -+ break; -+ case 0x3: -+ op = la_op_iocsrrd_d; -+ break; -+ case 0x4: -+ op = la_op_iocsrwr_b; -+ break; -+ case 0x5: -+ op = la_op_iocsrwr_h; -+ break; -+ case 0x6: -+ op = la_op_iocsrwr_w; -+ break; -+ case 0x7: -+ op = la_op_iocsrwr_d; -+ break; -+ case 0x8: -+ switch (insn & 0x000003ff) { -+ case 0x00000000: -+ op = la_op_tlbclr; -+ break; -+ } -+ break; -+ case 0x9: -+ switch (insn & 0x000003ff) { -+ case 0x00000000: -+ op = la_op_tlbflush; -+ break; -+ } -+ break; -+ case 0xa: -+ switch (insn & 0x000003ff) { -+ case 0x00000000: -+ op = la_op_tlbsrch; -+ break; -+ } -+ break; -+ case 0xb: -+ switch (insn & 0x000003ff) { -+ case 0x00000000: -+ op = la_op_tlbrd; -+ break; -+ } -+ break; -+ case 0xc: -+ switch (insn & 0x000003ff) { -+ case 0x00000000: -+ op = la_op_tlbwr; -+ break; -+ } -+ break; -+ case 0xd: -+ switch (insn & 0x000003ff) { -+ case 0x00000000: -+ op = la_op_tlbfill; -+ break; -+ } -+ break; -+ case 0xe: -+ switch (insn & 0x000003ff) { -+ case 0x00000000: -+ op = la_op_ertn; -+ break; -+ } -+ break; -+ } -+ break; -+ case 0x1: -+ op = la_op_idle; -+ break; -+ case 0x3: -+ op = la_op_invtlb; -+ break; -+ } -+ break; -+ } -+ break; -+ } -+ break; -+ } -+ break; -+ case 0x2: -+ switch ((insn >> 20) & 0x3f) { -+ case 0x1: -+ op = la_op_fmadd_s; -+ break; -+ case 0x2: -+ op = la_op_fmadd_d; -+ break; -+ case 0x5: -+ op = la_op_fmsub_s; -+ break; -+ case 0x6: -+ op = la_op_fmsub_d; -+ break; -+ case 0x9: -+ op = la_op_fnmadd_s; -+ break; -+ case 0xa: -+ op = la_op_fnmadd_d; -+ break; -+ case 0xd: -+ op = la_op_fnmsub_s; -+ break; -+ case 0xe: -+ op = la_op_fnmsub_d; -+ break; -+ } -+ break; -+ case 0x3: -+ switch ((insn >> 20) & 0x3f) { -+ case 0x1: -+ switch ((insn >> 3) & 0x3) { -+ case 0x0: -+ op = la_op_fcmp_cond_s; -+ break; -+ } -+ break; -+ case 0x2: -+ switch ((insn >> 3) & 0x3) { -+ case 0x0: -+ op = la_op_fcmp_cond_d; -+ break; -+ } -+ break; -+ case 0x10: -+ switch ((insn >> 18) & 0x3) { -+ case 0x0: -+ op = la_op_fsel; -+ break; -+ } -+ break; -+ } -+ break; -+ case 0x4: -+ op = la_op_addu16i_d; -+ break; -+ case 0x5: -+ switch ((insn >> 25) & 0x1) { -+ case 0x0: -+ op = la_op_lu12i_w; -+ break; -+ case 0x1: -+ op = la_op_lu32i_d; -+ break; -+ } -+ break; -+ case 0x6: -+ switch ((insn >> 25) & 0x1) { -+ case 0x0: -+ op = la_op_pcaddi; -+ break; -+ case 0x1: -+ op = la_op_pcalau12i; -+ break; -+ } -+ break; -+ case 0x7: -+ switch ((insn >> 25) & 0x1) { -+ case 0x0: -+ op = la_op_pcaddu12i; -+ break; -+ case 0x1: -+ op = la_op_pcaddu18i; -+ break; -+ } -+ break; -+ case 0x8: -+ switch ((insn >> 24) & 0x3) { -+ case 0x0: -+ op = la_op_ll_w; -+ break; -+ case 0x1: -+ op = la_op_sc_w; -+ break; -+ case 0x2: -+ op = la_op_ll_d; -+ break; -+ case 0x3: -+ op = la_op_sc_d; -+ break; -+ } -+ break; -+ case 0x9: -+ switch ((insn >> 24) & 0x3) { -+ case 0x0: -+ op = la_op_ldptr_w; -+ break; -+ case 0x1: -+ op = la_op_stptr_w; -+ break; -+ case 0x2: -+ op = la_op_ldptr_d; -+ break; -+ case 0x3: -+ op = la_op_stptr_d; -+ break; -+ } -+ break; -+ case 0xa: -+ switch ((insn >> 22) & 0xf) { -+ case 0x0: -+ op = la_op_ld_b; -+ break; -+ case 0x1: -+ op = la_op_ld_h; -+ break; -+ case 0x2: -+ op = la_op_ld_w; -+ break; -+ case 0x3: -+ op = la_op_ld_d; -+ break; -+ case 0x4: -+ op = la_op_st_b; -+ break; -+ case 0x5: -+ op = la_op_st_h; -+ break; -+ case 0x6: -+ op = la_op_st_w; -+ break; -+ case 0x7: -+ op = la_op_st_d; -+ break; -+ case 0x8: -+ op = la_op_ld_bu; -+ break; -+ case 0x9: -+ op = la_op_ld_hu; -+ break; -+ case 0xa: -+ op = la_op_ld_wu; -+ break; -+ case 0xb: -+ op = la_op_preld; -+ break; -+ case 0xc: -+ op = la_op_fld_s; -+ break; -+ case 0xd: -+ op = la_op_fst_s; -+ break; -+ case 0xe: -+ op = la_op_fld_d; -+ break; -+ case 0xf: -+ op = la_op_fst_d; -+ break; -+ } -+ break; -+ case 0xb: -+ switch ((insn >> 22) & 0xf) { -+ case 0x8: -+ op = la_op_ldl_w; -+ break; -+ case 0x9: -+ op = la_op_ldr_w; -+ break; -+ case 0xa: -+ op = la_op_ldl_d; -+ break; -+ case 0xb: -+ op = la_op_ldr_d; -+ break; -+ case 0xe: -+ op = la_op_stl_d; -+ break; -+ case 0xf: -+ op = la_op_str_d; -+ break; -+ } -+ break; -+ case 0xe: -+ switch ((insn >> 15) & 0x7ff) { -+ case 0x0: -+ op = la_op_ldx_b; -+ break; -+ case 0x8: -+ op = la_op_ldx_h; -+ break; -+ case 0x10: -+ op = la_op_ldx_w; -+ break; -+ case 0x18: -+ op = la_op_ldx_d; -+ break; -+ case 0x20: -+ op = la_op_stx_b; -+ break; -+ case 0x28: -+ op = la_op_stx_h; -+ break; -+ case 0x30: -+ op = la_op_stx_w; -+ break; -+ case 0x38: -+ op = la_op_stx_d; -+ break; -+ case 0x40: -+ op = la_op_ldx_bu; -+ break; -+ case 0x48: -+ op = la_op_ldx_hu; -+ break; -+ case 0x50: -+ op = la_op_ldx_wu; -+ break; -+ case 0x60: -+ op = la_op_fldx_s; -+ break; -+ case 0x68: -+ op = la_op_fldx_d; -+ break; -+ case 0x70: -+ op = la_op_fstx_s; -+ break; -+ case 0x78: -+ op = la_op_fstx_d; -+ break; -+ case 0xc0: -+ op = la_op_amswap_w; -+ break; -+ case 0xc1: -+ op = la_op_amswap_d; -+ break; -+ case 0xc2: -+ op = la_op_amadd_w; -+ break; -+ case 0xc3: -+ op = la_op_amadd_d; -+ break; -+ case 0xc4: -+ op = la_op_amand_w; -+ break; -+ case 0xc5: -+ op = la_op_amand_d; -+ break; -+ case 0xc6: -+ op = la_op_amor_w; -+ break; -+ case 0xc7: -+ op = la_op_amor_d; -+ break; -+ case 0xc8: -+ op = la_op_amxor_w; -+ break; -+ case 0xc9: -+ op = la_op_amxor_d; -+ break; -+ case 0xca: -+ op = la_op_ammax_w; -+ break; -+ case 0xcb: -+ op = la_op_ammax_d; -+ break; -+ case 0xcc: -+ op = la_op_ammin_w; -+ break; -+ case 0xcd: -+ op = la_op_ammin_d; -+ break; -+ case 0xce: -+ op = la_op_ammax_wu; -+ break; -+ case 0xcf: -+ op = la_op_ammax_du; -+ break; -+ case 0xd0: -+ op = la_op_ammin_wu; -+ break; -+ case 0xd1: -+ op = la_op_ammin_du; -+ break; -+ case 0xd2: -+ op = la_op_amswap_db_w; -+ break; -+ case 0xd3: -+ op = la_op_amswap_db_d; -+ break; -+ case 0xd4: -+ op = la_op_amadd_db_w; -+ break; -+ case 0xd5: -+ op = la_op_amadd_db_d; -+ break; -+ case 0xd6: -+ op = la_op_amand_db_w; -+ break; -+ case 0xd7: -+ op = la_op_amand_db_d; -+ break; -+ case 0xd8: -+ op = la_op_amor_db_w; -+ break; -+ case 0xd9: -+ op = la_op_amor_db_d; -+ break; -+ case 0xda: -+ op = la_op_amxor_db_w; -+ break; -+ case 0xdb: -+ op = la_op_amxor_db_d; -+ break; -+ case 0xdc: -+ op = la_op_ammax_db_w; -+ break; -+ case 0xdd: -+ op = la_op_ammax_db_d; -+ break; -+ case 0xde: -+ op = la_op_ammin_db_w; -+ break; -+ case 0xdf: -+ op = la_op_ammin_db_d; -+ break; -+ case 0xe0: -+ op = la_op_ammax_db_wu; -+ break; -+ case 0xe1: -+ op = la_op_ammax_db_du; -+ break; -+ case 0xe2: -+ op = la_op_ammin_db_wu; -+ break; -+ case 0xe3: -+ op = la_op_ammin_db_du; -+ break; -+ case 0xe4: -+ op = la_op_dbar; -+ break; -+ case 0xe5: -+ op = la_op_ibar; -+ break; -+ case 0xe8: -+ op = la_op_fldgt_s; -+ break; -+ case 0xe9: -+ op = la_op_fldgt_d; -+ break; -+ case 0xea: -+ op = la_op_fldle_s; -+ break; -+ case 0xeb: -+ op = la_op_fldle_d; -+ break; -+ case 0xec: -+ op = la_op_fstgt_s; -+ break; -+ case 0xed: -+ op = la_op_fstgt_d; -+ break; -+ case 0xee: -+ op = ls_op_fstle_s; -+ break; -+ case 0xef: -+ op = la_op_fstle_d; -+ break; -+ case 0xf0: -+ op = la_op_ldgt_b; -+ break; -+ case 0xf1: -+ op = la_op_ldgt_h; -+ break; -+ case 0xf2: -+ op = la_op_ldgt_w; -+ break; -+ case 0xf3: -+ op = la_op_ldgt_d; -+ break; -+ case 0xf4: -+ op = la_op_ldle_b; -+ break; -+ case 0xf5: -+ op = la_op_ldle_h; -+ break; -+ case 0xf6: -+ op = la_op_ldle_w; -+ break; -+ case 0xf7: -+ op = la_op_ldle_d; -+ break; -+ case 0xf8: -+ op = la_op_stgt_b; -+ break; -+ case 0xf9: -+ op = la_op_stgt_h; -+ break; -+ case 0xfa: -+ op = la_op_stgt_w; -+ break; -+ case 0xfb: -+ op = la_op_stgt_d; -+ break; -+ case 0xfc: -+ op = la_op_stle_b; -+ break; -+ case 0xfd: -+ op = la_op_stle_h; -+ break; -+ case 0xfe: -+ op = la_op_stle_w; -+ break; -+ case 0xff: -+ op = la_op_stle_d; -+ break; -+ } -+ break; -+ case 0x10: -+ op = la_op_beqz; -+ break; -+ case 0x11: -+ op = la_op_bnez; -+ break; -+ case 0x12: -+ switch ((insn >> 8) & 0x3) { -+ case 0x0: -+ op = la_op_bceqz; -+ break; -+ case 0x1: -+ op = la_op_bcnez; -+ break; -+ } -+ break; -+ case 0x13: -+ op = la_op_jirl; -+ break; -+ case 0x14: -+ op = la_op_b; -+ break; -+ case 0x15: -+ op = la_op_bl; -+ break; -+ case 0x16: -+ op = la_op_beq; -+ break; -+ case 0x17: -+ op = la_op_bne; -+ break; -+ case 0x18: -+ op = la_op_blt; -+ break; -+ case 0x19: -+ op = la_op_bge; -+ break; -+ case 0x1a: -+ op = la_op_bltu; -+ break; -+ case 0x1b: -+ op = la_op_bgeu; -+ break; -+ default: -+ op = la_op_illegal; -+ break; -+ } -+ dec->op = op; -+} -+ -+/* operand extractors */ -+ -+#define IM_5 5 -+#define IM_8 8 -+#define IM_12 12 -+#define IM_14 14 -+#define IM_15 15 -+#define IM_16 16 -+#define IM_20 20 -+#define IM_21 21 -+#define IM_26 26 -+ -+static uint32_t operand_r1(uint32_t insn) -+{ -+ return insn & 0x1f; -+} -+ -+static uint32_t operand_r2(uint32_t insn) -+{ -+ return (insn >> 5) & 0x1f; -+} -+ -+static uint32_t operand_r3(uint32_t insn) -+{ -+ return (insn >> 10) & 0x1f; -+} -+ -+static uint32_t operand_r4(uint32_t insn) -+{ -+ return (insn >> 15) & 0x1f; -+} -+ -+static uint32_t operand_u6(uint32_t insn) -+{ -+ return (insn >> 10) & 0x3f; -+} -+ -+static uint32_t operand_bw1(uint32_t insn) -+{ -+ return (insn >> 10) & 0x1f; -+} -+ -+static uint32_t operand_bw2(uint32_t insn) -+{ -+ return (insn >> 16) & 0x1f; -+} -+ -+static uint32_t operand_bd1(uint32_t insn) -+{ -+ return (insn >> 10) & 0x3f; -+} -+ -+static uint32_t operand_bd2(uint32_t insn) -+{ -+ return (insn >> 16) & 0x3f; -+} -+ -+static uint32_t operand_sa2(uint32_t insn) -+{ -+ return (insn >> 15) & 0x3; -+} -+ -+static uint32_t operand_sa3(uint32_t insn) -+{ -+ return (insn >> 15) & 0x3; -+} -+ -+static int32_t operand_im20(uint32_t insn) -+{ -+ int32_t imm = (int32_t)((insn >> 5) & 0xfffff); -+ return imm > (1 << 19) ? imm - (1 << 20) : imm; -+} -+ -+static int32_t operand_im16(uint32_t insn) -+{ -+ int32_t imm = (int32_t)((insn >> 10) & 0xffff); -+ return imm > (1 << 15) ? imm - (1 << 16) : imm; -+} -+ -+static int32_t operand_im14(uint32_t insn) -+{ -+ int32_t imm = (int32_t)((insn >> 10) & 0x3fff); -+ return imm > (1 << 13) ? imm - (1 << 14) : imm; -+} -+ -+static int32_t operand_im12(uint32_t insn) -+{ -+ int32_t imm = (int32_t)((insn >> 10) & 0xfff); -+ return imm > (1 << 11) ? imm - (1 << 12) : imm; -+} -+ -+static int32_t operand_im8(uint32_t insn) -+{ -+ int32_t imm = (int32_t)((insn >> 10) & 0xff); -+ return imm > (1 << 7) ? imm - (1 << 8) : imm; -+} -+ -+static uint32_t operand_sd(uint32_t insn) -+{ -+ return insn & 0x3; -+} -+ -+static uint32_t operand_sj(uint32_t insn) -+{ -+ return (insn >> 5) & 0x3; -+} -+ -+static uint32_t operand_cd(uint32_t insn) -+{ -+ return insn & 0x7; -+} -+ -+static uint32_t operand_cj(uint32_t insn) -+{ -+ return (insn >> 5) & 0x7; -+} -+ -+static uint32_t operand_code(uint32_t insn) -+{ -+ return insn & 0x7fff; -+} -+ -+static int32_t operand_whint(uint32_t insn) -+{ -+ int32_t imm = (int32_t)(insn & 0x7fff); -+ return imm > (1 << 14) ? imm - (1 << 15) : imm; -+} -+ -+static int32_t operand_invop(uint32_t insn) -+{ -+ int32_t imm = (int32_t)(insn & 0x1f); -+ return imm > (1 << 4) ? imm - (1 << 5) : imm; -+} -+ -+static int32_t operand_ofs21(uint32_t insn) -+{ -+ int32_t imm = (((int32_t)insn & 0x1f) << 16) | -+ ((insn >> 10) & 0xffff); -+ return imm > (1 << 20) ? imm - (1 << 21) : imm; -+} -+ -+static int32_t operand_ofs26(uint32_t insn) -+{ -+ int32_t imm = (((int32_t)insn & 0x3ff) << 16) | -+ ((insn >> 10) & 0xffff); -+ return imm > (1 << 25) ? imm - (1 << 26) : imm; -+} -+ -+static uint32_t operand_fcond(uint32_t insn) -+{ -+ return (insn >> 15) & 0x1f; -+} -+ -+static uint32_t operand_sel(uint32_t insn) -+{ -+ return (insn >> 15) & 0x7; -+} -+ -+/* decode operands */ -+ -+static void decode_insn_operands(la_decode *dec) -+{ -+ uint32_t insn = dec->insn; -+ dec->codec = opcode_data[dec->op].codec; -+ switch (dec->codec) { -+ case la_codec_illegal: -+ case la_codec_empty: -+ break; -+ case la_codec_2r: -+ dec->r1 = operand_r1(insn); -+ dec->r2 = operand_r2(insn); -+ break; -+ case la_codec_2r_u5: -+ dec->r1 = operand_r1(insn); -+ dec->r2 = operand_r2(insn); -+ dec->r3 = operand_r3(insn); -+ break; -+ case la_codec_2r_u6: -+ dec->r1 = operand_r1(insn); -+ dec->r2 = operand_r2(insn); -+ dec->r3 = operand_u6(insn); -+ break; -+ case la_codec_2r_2bw: -+ dec->r1 = operand_r1(insn); -+ dec->r2 = operand_r2(insn); -+ dec->r3 = operand_bw1(insn); -+ dec->r4 = operand_bw2(insn); -+ break; -+ case la_codec_2r_2bd: -+ dec->r1 = operand_r1(insn); -+ dec->r2 = operand_r2(insn); -+ dec->r3 = operand_bd1(insn); -+ dec->r4 = operand_bd2(insn); -+ break; -+ case la_codec_3r: -+ dec->r1 = operand_r1(insn); -+ dec->r2 = operand_r2(insn); -+ dec->r3 = operand_r3(insn); -+ break; -+ case la_codec_3r_rd0: -+ dec->r1 = 0; -+ dec->r2 = operand_r2(insn); -+ dec->r3 = operand_r3(insn); -+ break; -+ case la_codec_3r_sa2: -+ dec->r1 = operand_r1(insn); -+ dec->r2 = operand_r2(insn); -+ dec->r3 = operand_r3(insn); -+ dec->r4 = operand_sa2(insn); -+ break; -+ case la_codec_3r_sa3: -+ dec->r1 = operand_r1(insn); -+ dec->r2 = operand_r2(insn); -+ dec->r3 = operand_r3(insn); -+ dec->r4 = operand_sa3(insn); -+ break; -+ case la_codec_4r: -+ dec->r1 = operand_r1(insn); -+ dec->r2 = operand_r2(insn); -+ dec->r3 = operand_r3(insn); -+ dec->r4 = operand_r4(insn); -+ break; -+ case la_codec_r_im20: -+ dec->r1 = operand_r1(insn); -+ dec->imm = operand_im20(insn); -+ dec->bit = IM_20; -+ break; -+ case la_codec_2r_im16: -+ dec->r1 = operand_r1(insn); -+ dec->r2 = operand_r2(insn); -+ dec->imm = operand_im16(insn); -+ dec->bit = IM_16; -+ break; -+ case la_codec_2r_im14: -+ dec->r1 = operand_r1(insn); -+ dec->r2 = operand_r2(insn); -+ dec->imm = operand_im14(insn); -+ dec->bit = IM_14; -+ break; -+ case la_codec_im5_r_im12: -+ dec->imm2 = operand_r1(insn); -+ dec->r2 = operand_r2(insn); -+ dec->imm = operand_im12(insn); -+ dec->bit = IM_12; -+ break; -+ case la_codec_2r_im12: -+ dec->r1 = operand_r1(insn); -+ dec->r2 = operand_r2(insn); -+ dec->imm = operand_im12(insn); -+ dec->bit = IM_12; -+ break; -+ case la_codec_2r_im8: -+ dec->r1 = operand_r1(insn); -+ dec->r2 = operand_r2(insn); -+ dec->imm = operand_im8(insn); -+ dec->bit = IM_8; -+ break; -+ case la_codec_r_sd: -+ dec->r1 = operand_sd(insn); -+ dec->r2 = operand_r2(insn); -+ break; -+ case la_codec_r_sj: -+ dec->r1 = operand_r1(insn); -+ dec->r2 = operand_sj(insn); -+ break; -+ case la_codec_r_cd: -+ dec->r1 = operand_cd(insn); -+ dec->r2 = operand_r2(insn); -+ break; -+ case la_codec_r_cj: -+ dec->r1 = operand_r1(insn); -+ dec->r2 = operand_cj(insn); -+ break; -+ case la_codec_r_seq: -+ dec->r1 = 0; -+ dec->r2 = operand_r1(insn); -+ dec->imm = operand_im8(insn); -+ dec->bit = IM_8; -+ break; -+ case la_codec_code: -+ dec->code = operand_code(insn); -+ break; -+ case la_codec_whint: -+ dec->imm = operand_whint(insn); -+ dec->bit = IM_15; -+ break; -+ case la_codec_invtlb: -+ dec->imm = operand_invop(insn); -+ dec->bit = IM_5; -+ dec->r2 = operand_r2(insn); -+ dec->r3 = operand_r3(insn); -+ break; -+ case la_codec_r_ofs21: -+ dec->imm = operand_ofs21(insn); -+ dec->bit = IM_21; -+ dec->r2 = operand_r2(insn); -+ break; -+ case la_codec_cj_ofs21: -+ dec->imm = operand_ofs21(insn); -+ dec->bit = IM_21; -+ dec->r2 = operand_cj(insn); -+ break; -+ case la_codec_ofs26: -+ dec->imm = operand_ofs26(insn); -+ dec->bit = IM_26; -+ break; -+ case la_codec_cond: -+ dec->r1 = operand_cd(insn); -+ dec->r2 = operand_r2(insn); -+ dec->r3 = operand_r3(insn); -+ dec->r4 = operand_fcond(insn); -+ break; -+ case la_codec_sel: -+ dec->r1 = operand_r1(insn); -+ dec->r2 = operand_r2(insn); -+ dec->r3 = operand_r3(insn); -+ dec->r4 = operand_sel(insn); -+ break; -+ } -+} -+ -+/* format instruction */ -+ -+static void append(char *s1, const char *s2, size_t n) -+{ -+ size_t l1 = strlen(s1); -+ if (n - l1 - 1 > 0) { -+ strncat(s1, s2, n - l1); -+ } -+} -+ -+static void format_insn(char *buf, size_t buflen, size_t tab, la_decode *dec) -+{ -+ char tmp[16]; -+ const char *fmt; -+ -+ fmt = opcode_data[dec->op].format; -+ while (*fmt) { -+ switch (*fmt) { -+ case 'n': /* name */ -+ append(buf, opcode_data[dec->op].name, buflen); -+ break; -+ case 's': -+ append(buf, "s", buflen); -+ break; -+ case 'd': -+ append(buf, "d", buflen); -+ break; -+ case 'e': /* illegal */ -+ snprintf(tmp, sizeof(tmp), "%x", dec->insn); -+ append(buf, tmp, buflen); -+ break; -+ case 't': -+ while (strlen(buf) < tab) { -+ append(buf, " ", buflen); -+ } -+ break; -+ case '(': -+ append(buf, "(", buflen); -+ break; -+ case ',': -+ append(buf, ",", buflen); -+ break; -+ case '.': -+ append(buf, ".", buflen); -+ break; -+ case ')': -+ append(buf, ")", buflen); -+ break; -+ case '0': /* rd */ -+ append(buf, loongarch_r_normal_name[dec->r1], buflen); -+ break; -+ case '1': /* rj */ -+ append(buf, loongarch_r_normal_name[dec->r2], buflen); -+ break; -+ case '2': /* rk */ -+ append(buf, loongarch_r_normal_name[dec->r3], buflen); -+ break; -+ case '3': /* fd */ -+ append(buf, loongarch_f_normal_name[dec->r1], buflen); -+ break; -+ case '4': /* fj */ -+ append(buf, loongarch_f_normal_name[dec->r2], buflen); -+ break; -+ case '5': /* fk */ -+ append(buf, loongarch_f_normal_name[dec->r3], buflen); -+ break; -+ case '6': /* fa */ -+ append(buf, loongarch_f_normal_name[dec->r4], buflen); -+ break; -+ case 'A': /* sd */ -+ append(buf, loongarch_cr_normal_name[dec->r1], buflen); -+ break; -+ case 'B': /* sj */ -+ append(buf, loongarch_cr_normal_name[dec->r2], buflen); -+ break; -+ case 'C': /* r3 */ -+ snprintf(tmp, sizeof(tmp), "%x", dec->r3); -+ append(buf, tmp, buflen); -+ break; -+ case 'D': /* r4 */ -+ snprintf(tmp, sizeof(tmp), "%x", dec->r4); -+ append(buf, tmp, buflen); -+ break; -+ case 'E': /* r1 */ -+ snprintf(tmp, sizeof(tmp), "%x", dec->r1); -+ append(buf, tmp, buflen); -+ break; -+ case 'F': /* fcsrd */ -+ append(buf, loongarch_r_normal_name[dec->r1], buflen); -+ break; -+ case 'G': /* fcsrs */ -+ append(buf, loongarch_r_normal_name[dec->r2], buflen); -+ break; -+ case 'H': /* cd */ -+ append(buf, loongarch_c_normal_name[dec->r1], buflen); -+ break; -+ case 'I': /* cj */ -+ append(buf, loongarch_c_normal_name[dec->r2], buflen); -+ break; -+ case 'J': /* code */ -+ snprintf(tmp, sizeof(tmp), "0x%x", dec->code); -+ append(buf, tmp, buflen); -+ break; -+ case 'K': /* cond */ -+ switch (dec->r4) { -+ case 0x0: -+ append(buf, "caf", buflen); -+ break; -+ case 0x1: -+ append(buf, "saf", buflen); -+ break; -+ case 0x2: -+ append(buf, "clt", buflen); -+ break; -+ case 0x3: -+ append(buf, "slt", buflen); -+ break; -+ case 0x4: -+ append(buf, "ceq", buflen); -+ break; -+ case 0x5: -+ append(buf, "seq", buflen); -+ break; -+ case 0x6: -+ append(buf, "cle", buflen); -+ break; -+ case 0x7: -+ append(buf, "sle", buflen); -+ break; -+ case 0x8: -+ append(buf, "cun", buflen); -+ break; -+ case 0x9: -+ append(buf, "sun", buflen); -+ break; -+ case 0xA: -+ append(buf, "cult", buflen); -+ break; -+ case 0xB: -+ append(buf, "sult", buflen); -+ break; -+ case 0xC: -+ append(buf, "cueq", buflen); -+ break; -+ case 0xD: -+ append(buf, "sueq", buflen); -+ break; -+ case 0xE: -+ append(buf, "cule", buflen); -+ break; -+ case 0xF: -+ append(buf, "sule", buflen); -+ break; -+ case 0x10: -+ append(buf, "cne", buflen); -+ break; -+ case 0x11: -+ append(buf, "sne", buflen); -+ break; -+ case 0x14: -+ append(buf, "cor", buflen); -+ break; -+ case 0x15: -+ append(buf, "sor", buflen); -+ break; -+ case 0x18: -+ append(buf, "cune", buflen); -+ break; -+ case 0x19: -+ append(buf, "sune", buflen); -+ break; -+ } -+ break; -+ case 'L': /* ca */ -+ append(buf, loongarch_c_normal_name[dec->r4], buflen); -+ break; -+ case 'M': /* cop */ -+ snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm2) & 0x1f); -+ append(buf, tmp, buflen); -+ break; -+ case 'i': /* sixx d */ -+ snprintf(tmp, sizeof(tmp), "%d", dec->imm); -+ append(buf, tmp, buflen); -+ break; -+ case 'o': /* offset */ -+ snprintf(tmp, sizeof(tmp), "%d", (dec->imm) << 2); -+ append(buf, tmp, buflen); -+ break; -+ case 'x': /* sixx x */ -+ switch (dec->bit) { -+ case IM_5: -+ snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm) & 0x1f); -+ append(buf, tmp, buflen); -+ break; -+ case IM_8: -+ snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm) & 0xff); -+ append(buf, tmp, buflen); -+ break; -+ case IM_12: -+ snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm) & 0xfff); -+ append(buf, tmp, buflen); -+ break; -+ case IM_14: -+ snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm) & 0x3fff); -+ append(buf, tmp, buflen); -+ break; -+ case IM_15: -+ snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm) & 0x7fff); -+ append(buf, tmp, buflen); -+ break; -+ case IM_16: -+ snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm) & 0xffff); -+ append(buf, tmp, buflen); -+ break; -+ case IM_20: -+ snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm) & 0xfffff); -+ append(buf, tmp, buflen); -+ break; -+ default: -+ snprintf(tmp, sizeof(tmp), "0x%x", dec->imm); -+ append(buf, tmp, buflen); -+ break; -+ } -+ break; -+ case 'X': /* offset x*/ -+ switch (dec->bit) { -+ case IM_16: -+ snprintf(tmp, sizeof(tmp), "0x%x", -+ ((dec->imm) << 2) & 0xffff); -+ append(buf, tmp, buflen); -+ break; -+ case IM_21: -+ snprintf(tmp, sizeof(tmp), "0x%x", -+ ((dec->imm) << 2) & 0x1fffff); -+ append(buf, tmp, buflen); -+ break; -+ case IM_26: -+ snprintf(tmp, sizeof(tmp), "0x%x", -+ ((dec->imm) << 2) & 0x3ffffff); -+ append(buf, tmp, buflen); -+ break; -+ default: -+ snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm) << 2); -+ append(buf, tmp, buflen); -+ break; -+ } -+ break; -+ case 'p': /* pc */ -+ snprintf(tmp, sizeof(tmp), " # 0x%"PRIx32"", -+ dec->pc + ((dec->imm) << 2)); -+ append(buf, tmp, buflen); -+ break; -+ default: -+ break; -+ } -+ fmt++; -+ } -+} -+ -+ -+/* disassemble instruction */ -+ -+static void -+disasm_insn(char *buf, size_t buflen, bfd_vma pc, unsigned long int insn) -+{ -+ la_decode dec = { 0 }; -+ dec.pc = pc; -+ dec.insn = insn; -+ decode_insn_opcode(&dec); -+ decode_insn_operands(&dec); -+ format_insn(buf, buflen, 16, &dec); -+} -+ -+int -+print_insn_loongarch(bfd_vma memaddr, struct disassemble_info *info) -+{ -+ char buf[128] = { 0 }; -+ bfd_byte buffer[INSNLEN]; -+ unsigned long insn; -+ int status; -+ -+ status = (*info->read_memory_func)(memaddr, buffer, INSNLEN, info); -+ if (status == 0) { -+ insn = (uint32_t) bfd_getl32(buffer); -+ (*info->fprintf_func)(info->stream, "%08" PRIx64 " ", insn); -+ } else { -+ (*info->memory_error_func)(status, memaddr, info); -+ return -1; -+ } -+ disasm_insn(buf, sizeof(buf), memaddr, insn); -+ (*info->fprintf_func)(info->stream, "\t%s", buf); -+ return INSNLEN; -+} -diff --git a/disas/meson.build b/disas/meson.build -index 449f99e1de..06a69d9d72 100644 ---- a/disas/meson.build -+++ b/disas/meson.build -@@ -12,6 +12,7 @@ common_ss.add(when: 'CONFIG_I386_DIS', if_true: files('i386.c')) - common_ss.add(when: 'CONFIG_M68K_DIS', if_true: files('m68k.c')) - common_ss.add(when: 'CONFIG_MICROBLAZE_DIS', if_true: files('microblaze.c')) - common_ss.add(when: 'CONFIG_MIPS_DIS', if_true: files('mips.c')) -+common_ss.add(when: 'CONFIG_LOONGARCH_DIS', if_true: files('loongarch.c')) - common_ss.add(when: 'CONFIG_NANOMIPS_DIS', if_true: files('nanomips.cpp')) - common_ss.add(when: 'CONFIG_NIOS2_DIS', if_true: files('nios2.c')) - common_ss.add(when: 'CONFIG_PPC_DIS', if_true: files('ppc.c')) -diff --git a/gdb-xml/loongarch-base32.xml b/gdb-xml/loongarch-base32.xml -new file mode 100644 -index 0000000000..04891e023f ---- /dev/null -+++ b/gdb-xml/loongarch-base32.xml -@@ -0,0 +1,43 @@ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -diff --git a/gdb-xml/loongarch-base64.xml b/gdb-xml/loongarch-base64.xml -new file mode 100644 -index 0000000000..6308fb6ecb ---- /dev/null -+++ b/gdb-xml/loongarch-base64.xml -@@ -0,0 +1,43 @@ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -diff --git a/gdb-xml/loongarch-fpu32.xml b/gdb-xml/loongarch-fpu32.xml -new file mode 100644 -index 0000000000..a5b4d80e6c ---- /dev/null -+++ b/gdb-xml/loongarch-fpu32.xml -@@ -0,0 +1,52 @@ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -diff --git a/gdb-xml/loongarch-fpu64.xml b/gdb-xml/loongarch-fpu64.xml -new file mode 100644 -index 0000000000..74ab55a015 ---- /dev/null -+++ b/gdb-xml/loongarch-fpu64.xml -@@ -0,0 +1,57 @@ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ --- -2.27.0 - diff --git a/0007-Modify-kvm-cpu-vga-qapi.patch b/0007-Modify-kvm-cpu-vga-qapi.patch deleted file mode 100644 index 72fe897..0000000 --- a/0007-Modify-kvm-cpu-vga-qapi.patch +++ /dev/null @@ -1,480 +0,0 @@ -From 6e52e755bd54efb15afa052dac6dd0c7f696e366 Mon Sep 17 00:00:00 2001 -From: lixianglai -Date: Sat, 20 Aug 2022 02:18:41 -0400 -Subject: [PATCH 7/8] Modify kvm cpu vga qapi. - -Change-Id: I7923af804bdbe6d44d3f521df1859aa081afceba -Signed-off-by: lixianglai -Signed-off-by: Mao Bibo ---- - hw/acpi/cpu.c | 11 ++++++ - hw/loongarch/iocsr.c | 2 ++ - hw/loongarch/larch_3a.c | 18 +++++----- - hw/meson.build | 1 + - include/disas/dis-asm.h | 1 + - include/elf.h | 2 ++ - include/hw/loongarch/larch.h | 1 - - include/qemu/osdep.h | 3 ++ - include/sysemu/arch_init.h | 1 + - linux-headers/linux/kvm.h | 23 ++++++++++++ - linux-user/elfload.c | 67 +++++++++++++++++++++++++++++++++++ - linux-user/meson.build | 1 + - linux-user/qemu.h | 2 +- - linux-user/syscall.c | 3 ++ - linux-user/syscall_defs.h | 9 ++--- - meson.build | 1 + - pc-bios/loongarch_bios.bin | Bin 0 -> 4190208 bytes - pc-bios/meson.build | 1 + - qapi/machine-target.json | 6 ++-- - qapi/machine.json | 2 +- - qapi/misc-target.json | 1 + - 21 files changed, 138 insertions(+), 18 deletions(-) - create mode 100644 pc-bios/loongarch_bios.bin - -diff --git a/hw/acpi/cpu.c b/hw/acpi/cpu.c -index b20903ea30..cd73fab65b 100644 ---- a/hw/acpi/cpu.c -+++ b/hw/acpi/cpu.c -@@ -371,14 +371,25 @@ void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts, - aml_append(cpu_ctrl_dev, aml_mutex(CPU_LOCK, 0)); - - crs = aml_resource_template(); -+#ifdef __loongarch__ -+ aml_append(crs, aml_memory32_fixed(io_base, -+ ACPI_CPU_HOTPLUG_REG_LEN, AML_READ_WRITE)); -+#else - aml_append(crs, aml_io(AML_DECODE16, io_base, io_base, 1, - ACPI_CPU_HOTPLUG_REG_LEN)); -+#endif - aml_append(cpu_ctrl_dev, aml_name_decl("_CRS", crs)); - - /* declare CPU hotplug MMIO region with related access fields */ -+#ifdef __loongarch__ -+ aml_append(cpu_ctrl_dev, -+ aml_operation_region("PRST", AML_SYSTEM_MEMORY, aml_int(io_base), -+ ACPI_CPU_HOTPLUG_REG_LEN)); -+#else - aml_append(cpu_ctrl_dev, - aml_operation_region("PRST", AML_SYSTEM_IO, aml_int(io_base), - ACPI_CPU_HOTPLUG_REG_LEN)); -+#endif - - field = aml_field("PRST", AML_BYTE_ACC, AML_NOLOCK, - AML_WRITE_AS_ZEROS); -diff --git a/hw/loongarch/iocsr.c b/hw/loongarch/iocsr.c -index 14521c2d5c..60daafd6e1 100644 ---- a/hw/loongarch/iocsr.c -+++ b/hw/loongarch/iocsr.c -@@ -59,6 +59,7 @@ enum { - IOCSR_MAX - }; - -+#ifdef CONFIG_KVM - static uint32_t iocsr_array[IOCSR_MAX] = { - [IOCSR_FEATURES] = LOONGARCH_IOCSR_FEATURES, - [IOCSR_VENDOR] = LOONGARCH_IOCSR_VENDOR, -@@ -66,6 +67,7 @@ static uint32_t iocsr_array[IOCSR_MAX] = { - [IOCSR_NODECNT] = LOONGARCH_IOCSR_NODECNT, - [IOCSR_MISC_FUNC] = LOONGARCH_IOCSR_MISC_FUNC, - }; -+#endif - - - #define TYPE_IOCSR "iocsr" -diff --git a/hw/loongarch/larch_3a.c b/hw/loongarch/larch_3a.c -index 3db269274f..3194a822cc 100644 ---- a/hw/loongarch/larch_3a.c -+++ b/hw/loongarch/larch_3a.c -@@ -846,7 +846,7 @@ static void fw_cfg_add_kernel_info(FWCfgState *fw_cfg, - if (0 < initrd_size) { - if (initrd_size > highram_size) { - error_report("initrd size is too big, should below %ld MB", -- highram_size / S_1MiB); -+ highram_size / MiB); - /*prevent write io memory address space*/ - exit(1); - } -@@ -1033,7 +1033,9 @@ static void *ls3a_intctl_init(MachineState *machine, CPULOONGARCHState *env[]) - SysBusDevice *busdev; - MemoryRegion *address_space_mem = get_system_memory(); - MemoryRegion *iomem = NULL; -+#ifdef CONFIG_KVM - int i; -+#endif - - s = g_malloc0(sizeof(ls3a_intctlstate)); - -@@ -1214,8 +1216,6 @@ static void loongarch_build_smbios(LoongarchMachineState *lsms) - product = "Loongarch-3A5K-7A1000-TCG"; - } - -- host_cpufreq = get_host_cpu_freq(); -- - smbios_set_defaults("Loongson", product, lsmc->cpu_name, false, - true, NULL, NULL, SMBIOS_ENTRY_POINT_30); - -@@ -1672,15 +1672,15 @@ static void ls3a5k_init(MachineState *args) - - offset += lowram_size; - if (nb_numa_nodes > 0) { -- highram_size = numa_info[0].node_mem - S_256MiB; -- if (numa_info[0].node_mem > S_1GiB) { -- memmap_size = numa_info[0].node_mem - S_1GiB; -+ highram_size = numa_info[0].node_mem - 256 * MiB; -+ if (numa_info[0].node_mem > GiB) { -+ memmap_size = numa_info[0].node_mem - GiB; - la_memmap_add_entry(0xc0000000ULL, memmap_size, SYSTEM_RAM); - } - } else { -- highram_size = ram_size - S_256MiB; -- if (ram_size > S_1GiB) { -- memmap_size = ram_size - S_1GiB; -+ highram_size = ram_size - 256 * MiB; -+ if (ram_size > GiB) { -+ memmap_size = ram_size - GiB; - la_memmap_add_entry(0xc0000000ULL, memmap_size, SYSTEM_RAM); - } - } -diff --git a/hw/meson.build b/hw/meson.build -index b3366c888e..f224f8ad28 100644 ---- a/hw/meson.build -+++ b/hw/meson.build -@@ -17,6 +17,7 @@ subdir('intc') - subdir('ipack') - subdir('ipmi') - subdir('isa') -+subdir('loongarch') - subdir('mem') - subdir('misc') - subdir('net') -diff --git a/include/disas/dis-asm.h b/include/disas/dis-asm.h -index 08e1beec85..95b93f1002 100644 ---- a/include/disas/dis-asm.h -+++ b/include/disas/dis-asm.h -@@ -461,6 +461,7 @@ int print_insn_riscv32 (bfd_vma, disassemble_info*); - int print_insn_riscv64 (bfd_vma, disassemble_info*); - int print_insn_rx(bfd_vma, disassemble_info *); - int print_insn_hexagon(bfd_vma, disassemble_info *); -+int print_insn_loongarch (bfd_vma, disassemble_info*); - - #ifdef CONFIG_CAPSTONE - bool cap_disas_target(disassemble_info *info, uint64_t pc, size_t size); -diff --git a/include/elf.h b/include/elf.h -index 811bf4a1cb..66030f4906 100644 ---- a/include/elf.h -+++ b/include/elf.h -@@ -182,6 +182,8 @@ typedef struct mips_elf_abiflags_v0 { - - #define EM_NANOMIPS 249 /* Wave Computing nanoMIPS */ - -+#define EM_LOONGARCH 258 /* Loongarch */ -+ - /* - * This is an interim value that we will use until the committee comes - * up with a final number. -diff --git a/include/hw/loongarch/larch.h b/include/hw/loongarch/larch.h -index 0886ed52af..62e2830e27 100644 ---- a/include/hw/loongarch/larch.h -+++ b/include/hw/loongarch/larch.h -@@ -159,5 +159,4 @@ bool loongarch_is_acpi_enabled(LoongarchMachineState *vms); - void ls7a_madt_cpu_entry(AcpiDeviceIf *adev, int uid, - const CPUArchIdList *apic_ids, GArray *entry, bool force_enabled); - void slave_cpu_reset(void *opaque); --extern uint64_t host_cpufreq; - #endif -diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h -index 60718fc342..903475bb21 100644 ---- a/include/qemu/osdep.h -+++ b/include/qemu/osdep.h -@@ -533,6 +533,9 @@ static inline void qemu_cleanup_generic_vfree(void *p) - Valgrind does not support alignments larger than 1 MiB, - therefore we need special code which handles running on Valgrind. */ - # define QEMU_VMALLOC_ALIGN (512 * 4096) -+#elif defined(__linux__) && defined(__loongarch__) -+ /* Use 32 MiB alignment so transparent hugepages can be used by KVM. */ -+# define QEMU_VMALLOC_ALIGN (qemu_real_host_page_size * qemu_real_host_page_size / 8) - #elif defined(__linux__) && defined(__s390x__) - /* Use 1 MiB (segment size) alignment so gmap can be used by KVM. */ - # define QEMU_VMALLOC_ALIGN (256 * 4096) -diff --git a/include/sysemu/arch_init.h b/include/sysemu/arch_init.h -index 70c579560a..62d1a4b92d 100644 ---- a/include/sysemu/arch_init.h -+++ b/include/sysemu/arch_init.h -@@ -24,6 +24,7 @@ enum { - QEMU_ARCH_RX = (1 << 20), - QEMU_ARCH_AVR = (1 << 21), - QEMU_ARCH_HEXAGON = (1 << 22), -+ QEMU_ARCH_LOONGARCH64 = (1 << 23), - }; - - extern const uint32_t arch_type; -diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h -index bcaf66cc4d..20b90426f5 100644 ---- a/linux-headers/linux/kvm.h -+++ b/linux-headers/linux/kvm.h -@@ -2002,6 +2002,29 @@ struct kvm_stats_desc { - char name[]; - }; - -+#ifdef __loongarch__ -+struct kvm_loongarch_vcpu_state { -+ __u8 online_vcpus; -+ __u8 is_migrate; -+ __u32 cpu_freq; -+ __u32 count_ctl; -+ __u64 pending_exceptions; -+ __u64 pending_exceptions_clr; -+ __u64 core_ext_ioisr[4]; -+}; -+ -+#define KVM_CAP_LOONGARCH_FPU 165 -+#define KVM_CAP_LOONGARCH_LSX 166 -+#define KVM_CAP_LOONGARCH_VZ 167 -+#define KVM_REG_LOONGARCH 0x8000000000000000ULL -+#define KVM_LARCH_GET_VCPU_STATE _IOR(KVMIO, 0xc0, struct kvm_loongarch_vcpu_state) -+#define KVM_LARCH_SET_VCPU_STATE _IOW(KVMIO, 0xc1, struct kvm_loongarch_vcpu_state) -+#define KVM_LARCH_GET_CPUCFG _IOR(KVMIO, 0xc2, struct kvm_cpucfg) -+#define KVM_LOONGARCH_GET_IOCSR _IOR(KVMIO, 0xc3, struct kvm_iocsr_entry) -+#define KVM_LOONGARCH_SET_IOCSR _IOW(KVMIO, 0xc4, struct kvm_iocsr_entry) -+#define KVM_LARCH_SET_CPUCFG _IOR(KVMIO, 0xc5, struct kvm_cpucfg) -+#endif -+ - #define KVM_GET_STATS_FD _IO(KVMIO, 0xce) - - #endif /* __LINUX_KVM_H */ -diff --git a/linux-user/elfload.c b/linux-user/elfload.c -index 767f54c76d..9fb632780a 100644 ---- a/linux-user/elfload.c -+++ b/linux-user/elfload.c -@@ -1041,6 +1041,73 @@ static uint32_t get_elf_hwcap(void) - - #endif /* TARGET_MIPS */ - -+#ifdef TARGET_LOONGARCH64 -+ -+#define ELF_START_MMAP 0x80000000 -+ -+#define ELF_CLASS ELFCLASS64 -+#define ELF_ARCH EM_LOONGARCH -+ -+#define elf_check_arch(x) ((x) == EM_LOONGARCH) -+ -+static inline void init_thread(struct target_pt_regs *regs, -+ struct image_info *infop) -+{ -+ regs->csr_crmd = 2 << 3; -+ regs->csr_era = infop->entry; -+ regs->regs[3] = infop->start_stack; -+} -+ -+/* See linux kernel: arch/mips/include/asm/elf.h. */ -+#define ELF_NREG 45 -+typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; -+ -+/* See linux kernel: arch/loongarch/include/uapi/asm/reg.h */ -+enum { -+ TARGET_EF_R0 = 0, -+ TARGET_EF_R26 = TARGET_EF_R0 + 26, -+ TARGET_EF_R27 = TARGET_EF_R0 + 27, -+ TARGET_EF_CSR_ERA = TARGET_EF_R0 + 32, -+ TARGET_EF_CSR_BADV = TARGET_EF_R0 + 33, -+ TARGET_EF_CSR_CRMD = TARGET_EF_R0 + 34, -+ TARGET_EF_CSR_ESTAT = TARGET_EF_R0 + 38 -+}; -+ -+/* See linux kernel: arch/loongarch/kernel/process.c:elf_dump_regs. */ -+static void elf_core_copy_regs(target_elf_gregset_t *regs, -+ const CPULOONGARCHState *env) -+{ -+ int i; -+ -+ for (i = 0; i < TARGET_EF_R0; i++) { -+ (*regs)[i] = 0; -+ } -+ (*regs)[TARGET_EF_R0] = 0; -+ -+ for (i = 1; i < ARRAY_SIZE(env->active_tc.gpr); i++) { -+ (*regs)[TARGET_EF_R0 + i] = tswapreg(env->active_tc.gpr[i]); -+ } -+ -+ (*regs)[TARGET_EF_R26] = 0; -+ (*regs)[TARGET_EF_R27] = 0; -+ (*regs)[TARGET_EF_CSR_ERA] = tswapreg(env->active_tc.PC); -+ (*regs)[TARGET_EF_CSR_BADV] = tswapreg(env->CSR_BADV); -+ (*regs)[TARGET_EF_CSR_CRMD] = tswapreg(env->CSR_CRMD); -+ (*regs)[TARGET_EF_CSR_ESTAT] = tswapreg(env->CSR_ESTAT); -+} -+ -+#define USE_ELF_CORE_DUMP -+#define ELF_EXEC_PAGESIZE 4096 -+ -+#define ELF_HWCAP get_elf_hwcap() -+ -+static uint32_t get_elf_hwcap(void) -+{ -+ return 0; -+} -+ -+#endif /* TARGET_LOONGARCH64 */ -+ - #ifdef TARGET_MICROBLAZE - - #define ELF_START_MMAP 0x80000000 -diff --git a/linux-user/meson.build b/linux-user/meson.build -index bf62c13e37..195f9e83ac 100644 ---- a/linux-user/meson.build -+++ b/linux-user/meson.build -@@ -39,3 +39,4 @@ subdir('sh4') - subdir('sparc') - subdir('x86_64') - subdir('xtensa') -+subdir('loongarch64') -diff --git a/linux-user/qemu.h b/linux-user/qemu.h -index 5c713fa8ab..66ddb25d1c 100644 ---- a/linux-user/qemu.h -+++ b/linux-user/qemu.h -@@ -61,7 +61,7 @@ struct image_info { - /* For target-specific processing of NT_GNU_PROPERTY_TYPE_0. */ - uint32_t note_flags; - --#ifdef TARGET_MIPS -+#if defined(TARGET_MIPS) || defined(TARGET_LOONGARCH64) - int fp_abi; - int interp_fp_abi; - #endif -diff --git a/linux-user/syscall.c b/linux-user/syscall.c -index f1cfcc8104..729131ecd0 100644 ---- a/linux-user/syscall.c -+++ b/linux-user/syscall.c -@@ -1614,6 +1614,9 @@ static abi_long do_pipe(void *cpu_env, abi_ulong pipedes, - #elif defined(TARGET_MIPS) - ((CPUMIPSState*)cpu_env)->active_tc.gpr[3] = host_pipe[1]; - return host_pipe[0]; -+#elif defined(TARGET_LOONGARCH64) -+ ((CPULOONGARCHState *)cpu_env)->active_tc.gpr[5] = host_pipe[1]; -+ return host_pipe[0]; - #elif defined(TARGET_SH4) - ((CPUSH4State*)cpu_env)->gregs[1] = host_pipe[1]; - return host_pipe[0]; -diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h -index 0b13975937..7e2915d53e 100644 ---- a/linux-user/syscall_defs.h -+++ b/linux-user/syscall_defs.h -@@ -74,7 +74,7 @@ - || defined(TARGET_M68K) || defined(TARGET_CRIS) \ - || defined(TARGET_S390X) || defined(TARGET_OPENRISC) \ - || defined(TARGET_NIOS2) || defined(TARGET_RISCV) \ -- || defined(TARGET_XTENSA) -+ || defined(TARGET_XTENSA) || defined(TARGET_LOONGARCH64) - - #define TARGET_IOC_SIZEBITS 14 - #define TARGET_IOC_DIRBITS 2 -@@ -450,7 +450,7 @@ struct target_dirent64 { - #define TARGET_SIG_IGN ((abi_long)1) /* ignore signal */ - #define TARGET_SIG_ERR ((abi_long)-1) /* error return from signal */ - --#ifdef TARGET_MIPS -+#if defined(TARGET_MIPS) || defined(TARGET_LOONGARCH64) - #define TARGET_NSIG 128 - #else - #define TARGET_NSIG 64 -@@ -2133,7 +2133,7 @@ struct target_stat64 { - abi_ulong __unused5; - }; - --#elif defined(TARGET_OPENRISC) || defined(TARGET_NIOS2) || defined(TARGET_RISCV) -+#elif defined(TARGET_OPENRISC) || defined(TARGET_NIOS2) || defined(TARGET_RISCV) || defined(TARGET_LOONGARCH64) - - /* These are the asm-generic versions of the stat and stat64 structures */ - -@@ -2161,7 +2161,7 @@ struct target_stat { - unsigned int __unused5; - }; - --#if !defined(TARGET_RISCV64) -+#if !(defined(TARGET_RISCV64) || defined(TARGET_LOONGARCH64)) - #define TARGET_HAS_STRUCT_STAT64 - struct target_stat64 { - uint64_t st_dev; -@@ -2331,6 +2331,7 @@ struct target_statfs64 { - }; - #elif (defined(TARGET_PPC64) || defined(TARGET_X86_64) || \ - defined(TARGET_SPARC64) || defined(TARGET_AARCH64) || \ -+ defined(TARGET_LOONGARCH64) || \ - defined(TARGET_RISCV)) && !defined(TARGET_ABI32) - struct target_statfs { - abi_long f_type; -diff --git a/meson.build b/meson.build -index 5f6ba86dbb..fc2dc58f33 100644 ---- a/meson.build -+++ b/meson.build -@@ -1814,6 +1814,7 @@ disassemblers = { - 'sh4' : ['CONFIG_SH4_DIS'], - 'sparc' : ['CONFIG_SPARC_DIS'], - 'xtensa' : ['CONFIG_XTENSA_DIS'], -+ 'loongarch64' : ['CONFIG_LOONGARCH_DIS'], - } - if link_language == 'cpp' - disassemblers += { - -diff --git a/pc-bios/meson.build b/pc-bios/meson.build -index b40ff3f2bd..a09ca4d03c 100644 ---- a/pc-bios/meson.build -+++ b/pc-bios/meson.build -@@ -83,6 +83,7 @@ blobs = files( - 'opensbi-riscv32-generic-fw_dynamic.elf', - 'opensbi-riscv64-generic-fw_dynamic.elf', - 'npcm7xx_bootrom.bin', -+ 'loongarch_bios.bin', - ) - - if get_option('install_blobs') -diff --git a/qapi/machine-target.json b/qapi/machine-target.json -index f5ec4bc172..682dc86b42 100644 ---- a/qapi/machine-target.json -+++ b/qapi/machine-target.json -@@ -324,7 +324,8 @@ - 'TARGET_ARM', - 'TARGET_I386', - 'TARGET_S390X', -- 'TARGET_MIPS' ] } } -+ 'TARGET_MIPS', -+ 'TARGET_LOONGARCH64' ] } } - - ## - # @query-cpu-definitions: -@@ -340,4 +341,5 @@ - 'TARGET_ARM', - 'TARGET_I386', - 'TARGET_S390X', -- 'TARGET_MIPS' ] } } -+ 'TARGET_MIPS', -+ 'TARGET_LOONGARCH64' ] } } -diff --git a/qapi/machine.json b/qapi/machine.json -index a9f33d0f27..cd47b8d6bc 100644 ---- a/qapi/machine.json -+++ b/qapi/machine.json -@@ -34,7 +34,7 @@ - 'mips64el', 'mipsel', 'nios2', 'or1k', 'ppc', - 'ppc64', 'riscv32', 'riscv64', 'rx', 's390x', 'sh4', - 'sh4eb', 'sparc', 'sparc64', 'tricore', -- 'x86_64', 'xtensa', 'xtensaeb' ] } -+ 'x86_64', 'xtensa', 'xtensaeb', 'loongarch64' ] } - - ## - # @CpuS390State: -diff --git a/qapi/misc-target.json b/qapi/misc-target.json -index 4bc45d2474..63cebef573 100644 ---- a/qapi/misc-target.json -+++ b/qapi/misc-target.json -@@ -33,6 +33,7 @@ - 'TARGET_PPC64', - 'TARGET_S390X', - 'TARGET_SH4', -+ 'TARGET_LOONGARCH64', - 'TARGET_SPARC' ] } } - - ## --- -2.27.0 - diff --git a/0008-Modify-compile-script.patch b/0008-Modify-compile-script.patch deleted file mode 100644 index 87054ee..0000000 --- a/0008-Modify-compile-script.patch +++ /dev/null @@ -1,36 +0,0 @@ -From b051f9fdabc2cd49c1c80ef50bbee276b6946609 Mon Sep 17 00:00:00 2001 -From: lixianglai -Date: Mon, 22 Aug 2022 08:22:03 -0400 -Subject: [PATCH 08/10] Modify compile script. - -Change-Id: I8573477d64f5974092001869d7aa9bb093f347e8 -Signed-off-by: lixianglai ---- - meson.build | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/meson.build b/meson.build -index fc2dc58f33..c0fb5788f7 100644 ---- a/meson.build -+++ b/meson.build -@@ -56,7 +56,7 @@ python = import('python').find_installation() - - supported_oses = ['windows', 'freebsd', 'netbsd', 'openbsd', 'darwin', 'sunos', 'linux'] - supported_cpus = ['ppc', 'ppc64', 's390x', 'riscv', 'x86', 'x86_64', -- 'arm', 'aarch64', 'mips', 'mips64', 'sparc', 'sparc64'] -+ 'arm', 'aarch64', 'mips', 'mips64', 'sparc', 'sparc64', 'loongarch64'] - - cpu = host_machine.cpu_family() - -@@ -77,6 +77,8 @@ elif cpu in ['ppc', 'ppc64'] - kvm_targets = ['ppc-softmmu', 'ppc64-softmmu'] - elif cpu in ['mips', 'mips64'] - kvm_targets = ['mips-softmmu', 'mipsel-softmmu', 'mips64-softmmu', 'mips64el-softmmu'] -+elif cpu == 'loongarch64' -+ kvm_targets = ['loongarch64-softmmu'] - else - kvm_targets = [] - endif --- -2.27.0 - diff --git a/0009-Add-loongarch64-rh-devices.mak.patch b/0009-Add-loongarch64-rh-devices.mak.patch deleted file mode 100644 index ef7533d..0000000 --- a/0009-Add-loongarch64-rh-devices.mak.patch +++ /dev/null @@ -1,3227 +0,0 @@ -From d2163a939cd14d3d9a8a4afb9d9eacbb71b61517 Mon Sep 17 00:00:00 2001 -From: lixianglai -Date: Wed, 24 Aug 2022 22:56:29 -0400 -Subject: [PATCH 09/10] Add loongarch64-rh-devices.mak. - -Change-Id: I375face82c0aa68c053254b879267830d6981756 -Signed-off-by: lixianglai ---- - .../loongarch64-rh-devices.mak | 155 ++ - configure | 5 + - meson.build | 2 + - pc-bios/meson.build | 1 + - tcg/loongarch64/tcg-insn-defs.c.inc | 979 +++++++++ - tcg/loongarch64/tcg-target-con-set.h | 31 + - tcg/loongarch64/tcg-target-con-str.h | 28 + - tcg/loongarch64/tcg-target.c.inc | 1744 +++++++++++++++++ - tcg/loongarch64/tcg-target.h | 178 ++ - 9 files changed, 3123 insertions(+) - create mode 100644 configs/devices/loongarch64-softmmu/loongarch64-rh-devices.mak - create mode 100644 tcg/loongarch64/tcg-insn-defs.c.inc - create mode 100644 tcg/loongarch64/tcg-target-con-set.h - create mode 100644 tcg/loongarch64/tcg-target-con-str.h - create mode 100644 tcg/loongarch64/tcg-target.c.inc - create mode 100644 tcg/loongarch64/tcg-target.h - -diff --git a/configs/devices/loongarch64-softmmu/loongarch64-rh-devices.mak b/configs/devices/loongarch64-softmmu/loongarch64-rh-devices.mak -new file mode 100644 -index 0000000000..e7b5bdc8e9 ---- /dev/null -+++ b/configs/devices/loongarch64-softmmu/loongarch64-rh-devices.mak -@@ -0,0 +1,155 @@ -+ -+include ../rh-virtio.mak -+# Default configuration for loongarch-softmmu -+ -+CONFIG_PCI=y -+CONFIG_ACPI_PCI=y -+# For now, CONFIG_IDE_CORE requires ISA, so we enable it here -+CONFIG_ISA_BUS=y -+CONFIG_VIRTIO_PCI=y -+ -+CONFIG_VGA_PCI=y -+CONFIG_ACPI_SMBUS=y -+#CONFIG_VHOST_USER_SCSI=$(call land,$(CONFIG_VHOST_USER),$(CONFIG_LINUX)) -+CONFIG_VHOST_USER_SCSI=y -+#CONFIG_VHOST_USER_BLK=$(call land,$(CONFIG_VHOST_USER),$(CONFIG_LINUX)) -+CONFIG_VHOST_USER_BLK=y -+CONFIG_VIRTIO=y -+CONFIG_VIRTIO_BALLOON=y -+CONFIG_VIRTIO_BLK=y -+CONFIG_VIRTIO_CRYPTO=y -+CONFIG_VIRTIO_GPU=y -+CONFIG_VIRTIO_INPUT=y -+CONFIG_VIRTIO_NET=y -+CONFIG_VIRTIO_RNG=y -+CONFIG_SCSI=y -+CONFIG_VIRTIO_SCSI=y -+CONFIG_VIRTIO_SERIAL=y -+ -+CONFIG_USB_UHCI=y -+CONFIG_USB_OHCI=y -+CONFIG_USB_OHCI_PCI=y -+CONFIG_USB_XHCI=y -+CONFIG_USB_XHCI_NEC=y -+CONFIG_NE2000_PCI=y -+CONFIG_EEPRO100_PCI=y -+CONFIG_PCNET_PCI=y -+CONFIG_PCNET_COMMON=y -+CONFIG_AC97=y -+CONFIG_HDA=y -+CONFIG_ES1370=y -+CONFIG_SCSI=y -+CONFIG_LSI_SCSI_PCI=y -+CONFIG_VMW_PVSCSI_SCSI_PCI=y -+CONFIG_MEGASAS_SCSI_PCI=y -+CONFIG_MPTSAS_SCSI_PCI=y -+CONFIG_RTL8139_PCI=y -+CONFIG_E1000_PCI=y -+CONFIG_IDE_CORE=y -+CONFIG_IDE_QDEV=y -+CONFIG_IDE_PCI=y -+CONFIG_AHCI=y -+CONFIG_AHCI_ICH9=y -+CONFIG_ESP=y -+CONFIG_ESP_PCI=y -+CONFIG_SERIAL=y -+CONFIG_SERIAL_ISA=y -+CONFIG_SERIAL_PCI=y -+CONFIG_CAN_BUS=y -+CONFIG_CAN_SJA1000=y -+CONFIG_CAN_PCI=y -+CONFIG_USB_UHCI=y -+CONFIG_USB_OHCI=y -+CONFIG_USB_XHCI=y -+CONFIG_USB_XHCI_NEC=y -+CONFIG_NE2000_PCI=y -+CONFIG_EEPRO100_PCI=y -+CONFIG_PCNET_PCI=y -+CONFIG_PCNET_COMMON=y -+CONFIG_AC97=y -+CONFIG_HDA=y -+CONFIG_ES1370=y -+CONFIG_SCSI=y -+CONFIG_LSI_SCSI_PCI=y -+CONFIG_VMW_PVSCSI_SCSI_PCI=y -+CONFIG_MEGASAS_SCSI_PCI=y -+CONFIG_MPTSAS_SCSI_PCI=y -+CONFIG_RTL8139_PCI=y -+CONFIG_E1000_PCI=y -+CONFIG_IDE_CORE=y -+CONFIG_IDE_QDEV=y -+CONFIG_IDE_PCI=y -+CONFIG_AHCI=y -+CONFIG_ESP=y -+CONFIG_ESP_PCI=y -+CONFIG_SERIAL=y -+CONFIG_SERIAL_ISA=y -+CONFIG_SERIAL_PCI=y -+CONFIG_CAN_BUS=y -+CONFIG_CAN_SJA1000=y -+CONFIG_CAN_PCI=y -+ -+CONFIG_SPICE=y -+CONFIG_QXL=y -+CONFIG_ESP=y -+CONFIG_SCSI=y -+CONFIG_VGA_ISA=y -+CONFIG_VGA_ISA_MM=y -+CONFIG_VGA_CIRRUS=y -+CONFIG_VMWARE_VGA=y -+CONFIG_VIRTIO_VGA=y -+CONFIG_SERIAL_ISA=y -+CONFIG_PARALLEL=y -+CONFIG_I8254=y -+CONFIG_PCSPK=y -+CONFIG_PCKBD=y -+CONFIG_FDC=y -+CONFIG_ACPI=y -+CONFIG_ACPI_MEMORY_HOTPLUG=y -+CONFIG_ACPI_NVDIMM=y -+CONFIG_ACPI_CPU_HOTPLUG=y -+CONFIG_APM=y -+CONFIG_I8257=y -+CONFIG_PIIX4=y -+CONFIG_IDE_ISA=y -+CONFIG_IDE_PIIX=y -+#CONFIG_NE2000_ISA=y -+CONFIG_MIPSNET=y -+CONFIG_PFLASH_CFI01=y -+CONFIG_I8259=y -+CONFIG_MC146818RTC=y -+CONFIG_ISA_TESTDEV=y -+CONFIG_EMPTY_SLOT=y -+CONFIG_I2C=y -+CONFIG_DIMM=y -+CONFIG_MEM_DEVICE=y -+ -+# Arch Specified CONFIG defines -+CONFIG_IDE_VIA=y -+CONFIG_VT82C686=y -+CONFIG_RC4030=y -+CONFIG_DP8393X=y -+CONFIG_DS1225Y=y -+CONFIG_FITLOADER=y -+CONFIG_SMBIOS=y -+ -+CONFIG_PCIE_PORT=y -+CONFIG_I82801B11=y -+CONFIG_XIO3130=y -+CONFIG_PCI_EXPRESS=y -+CONFIG_MSI_NONBROKEN=y -+CONFIG_IOH3420=y -+CONFIG_SD=y -+CONFIG_SDHCI=y -+CONFIG_VIRTFS=y -+CONFIG_VIRTIO_9P=y -+CONFIG_USB_EHCI=y -+CONFIG_USB_EHCI_PCI=y -+CONFIG_USB_EHCI_SYSBUS=y -+CONFIG_USB_STORAGE_BOT=y -+CONFIG_TPM_EMULATOR=y -+CONFIG_TPM_TIS=y -+CONFIG_PLATFORM_BUS=y -+CONFIG_TPM_TIS_SYSBUS=y -+CONFIG_ACPI_LOONGARCH=y -+CONFIG_LS7A_RTC=y -diff --git a/configure b/configure -index 48c21775f3..1f932f7eeb 100755 ---- a/configure -+++ b/configure -@@ -581,6 +581,8 @@ elif check_define __arm__ ; then - cpu="arm" - elif check_define __aarch64__ ; then - cpu="aarch64" -+elif check_define __loongarch__ ; then -+ cpu="loongarch64" - else - cpu=$(uname -m) - fi -@@ -606,6 +608,9 @@ case "$cpu" in - aarch64) - cpu="aarch64" - ;; -+ loongarch64) -+ cpu="loongarch64" -+ ;; - mips*) - cpu="mips" - ;; -diff --git a/meson.build b/meson.build -index c0fb5788f7..c5fdb78569 100644 ---- a/meson.build -+++ b/meson.build -@@ -361,6 +361,8 @@ if not get_option('tcg').disabled() - tcg_arch = 'i386' - elif config_host['ARCH'] == 'ppc64' - tcg_arch = 'ppc' -+ elif config_host['ARCH'] == 'loongarch64' -+ tcg_arch = 'loongarch64' - endif - add_project_arguments('-iquote', meson.current_source_dir() / 'tcg' / tcg_arch, - language: ['c', 'cpp', 'objc']) -diff --git a/pc-bios/meson.build b/pc-bios/meson.build -index a09ca4d03c..60009bd89e 100644 ---- a/pc-bios/meson.build -+++ b/pc-bios/meson.build -@@ -84,6 +84,7 @@ blobs = files( - 'opensbi-riscv64-generic-fw_dynamic.elf', - 'npcm7xx_bootrom.bin', - 'loongarch_bios.bin', -+ 'loongarch_vars.bin', - ) - - if get_option('install_blobs') -diff --git a/tcg/loongarch64/tcg-insn-defs.c.inc b/tcg/loongarch64/tcg-insn-defs.c.inc -new file mode 100644 -index 0000000000..d162571856 ---- /dev/null -+++ b/tcg/loongarch64/tcg-insn-defs.c.inc -@@ -0,0 +1,979 @@ -+/* SPDX-License-Identifier: MIT */ -+/* -+ * LoongArch instruction formats, opcodes, and encoders for TCG use. -+ * -+ * This file is auto-generated by genqemutcgdefs from -+ * https://github.com/loongson-community/loongarch-opcodes, -+ * from commit 961f0c60f5b63e574d785995600c71ad5413fdc4. -+ * DO NOT EDIT. -+ */ -+ -+typedef enum { -+ OPC_CLZ_W = 0x00001400, -+ OPC_CTZ_W = 0x00001c00, -+ OPC_CLZ_D = 0x00002400, -+ OPC_CTZ_D = 0x00002c00, -+ OPC_REVB_2H = 0x00003000, -+ OPC_REVB_2W = 0x00003800, -+ OPC_REVB_D = 0x00003c00, -+ OPC_SEXT_H = 0x00005800, -+ OPC_SEXT_B = 0x00005c00, -+ OPC_ADD_W = 0x00100000, -+ OPC_ADD_D = 0x00108000, -+ OPC_SUB_W = 0x00110000, -+ OPC_SUB_D = 0x00118000, -+ OPC_SLT = 0x00120000, -+ OPC_SLTU = 0x00128000, -+ OPC_MASKEQZ = 0x00130000, -+ OPC_MASKNEZ = 0x00138000, -+ OPC_NOR = 0x00140000, -+ OPC_AND = 0x00148000, -+ OPC_OR = 0x00150000, -+ OPC_XOR = 0x00158000, -+ OPC_ORN = 0x00160000, -+ OPC_ANDN = 0x00168000, -+ OPC_SLL_W = 0x00170000, -+ OPC_SRL_W = 0x00178000, -+ OPC_SRA_W = 0x00180000, -+ OPC_SLL_D = 0x00188000, -+ OPC_SRL_D = 0x00190000, -+ OPC_SRA_D = 0x00198000, -+ OPC_ROTR_W = 0x001b0000, -+ OPC_ROTR_D = 0x001b8000, -+ OPC_MUL_W = 0x001c0000, -+ OPC_MULH_W = 0x001c8000, -+ OPC_MULH_WU = 0x001d0000, -+ OPC_MUL_D = 0x001d8000, -+ OPC_MULH_D = 0x001e0000, -+ OPC_MULH_DU = 0x001e8000, -+ OPC_DIV_W = 0x00200000, -+ OPC_MOD_W = 0x00208000, -+ OPC_DIV_WU = 0x00210000, -+ OPC_MOD_WU = 0x00218000, -+ OPC_DIV_D = 0x00220000, -+ OPC_MOD_D = 0x00228000, -+ OPC_DIV_DU = 0x00230000, -+ OPC_MOD_DU = 0x00238000, -+ OPC_SLLI_W = 0x00408000, -+ OPC_SLLI_D = 0x00410000, -+ OPC_SRLI_W = 0x00448000, -+ OPC_SRLI_D = 0x00450000, -+ OPC_SRAI_W = 0x00488000, -+ OPC_SRAI_D = 0x00490000, -+ OPC_ROTRI_W = 0x004c8000, -+ OPC_ROTRI_D = 0x004d0000, -+ OPC_BSTRINS_W = 0x00600000, -+ OPC_BSTRPICK_W = 0x00608000, -+ OPC_BSTRINS_D = 0x00800000, -+ OPC_BSTRPICK_D = 0x00c00000, -+ OPC_SLTI = 0x02000000, -+ OPC_SLTUI = 0x02400000, -+ OPC_ADDI_W = 0x02800000, -+ OPC_ADDI_D = 0x02c00000, -+ OPC_CU52I_D = 0x03000000, -+ OPC_ANDI = 0x03400000, -+ OPC_ORI = 0x03800000, -+ OPC_XORI = 0x03c00000, -+ OPC_LU12I_W = 0x14000000, -+ OPC_CU32I_D = 0x16000000, -+ OPC_PCADDU2I = 0x18000000, -+ OPC_PCALAU12I = 0x1a000000, -+ OPC_PCADDU12I = 0x1c000000, -+ OPC_PCADDU18I = 0x1e000000, -+ OPC_LD_B = 0x28000000, -+ OPC_LD_H = 0x28400000, -+ OPC_LD_W = 0x28800000, -+ OPC_LD_D = 0x28c00000, -+ OPC_ST_B = 0x29000000, -+ OPC_ST_H = 0x29400000, -+ OPC_ST_W = 0x29800000, -+ OPC_ST_D = 0x29c00000, -+ OPC_LD_BU = 0x2a000000, -+ OPC_LD_HU = 0x2a400000, -+ OPC_LD_WU = 0x2a800000, -+ OPC_LDX_B = 0x38000000, -+ OPC_LDX_H = 0x38040000, -+ OPC_LDX_W = 0x38080000, -+ OPC_LDX_D = 0x380c0000, -+ OPC_STX_B = 0x38100000, -+ OPC_STX_H = 0x38140000, -+ OPC_STX_W = 0x38180000, -+ OPC_STX_D = 0x381c0000, -+ OPC_LDX_BU = 0x38200000, -+ OPC_LDX_HU = 0x38240000, -+ OPC_LDX_WU = 0x38280000, -+ OPC_DBAR = 0x38720000, -+ OPC_JIRL = 0x4c000000, -+ OPC_B = 0x50000000, -+ OPC_BL = 0x54000000, -+ OPC_BEQ = 0x58000000, -+ OPC_BNE = 0x5c000000, -+ OPC_BGT = 0x60000000, -+ OPC_BLE = 0x64000000, -+ OPC_BGTU = 0x68000000, -+ OPC_BLEU = 0x6c000000, -+} LoongArchInsn; -+ -+static int32_t __attribute__((unused)) -+encode_d_slot(LoongArchInsn opc, uint32_t d) -+{ -+ return opc | d; -+} -+ -+static int32_t __attribute__((unused)) -+encode_dj_slots(LoongArchInsn opc, uint32_t d, uint32_t j) -+{ -+ return opc | d | j << 5; -+} -+ -+static int32_t __attribute__((unused)) -+encode_djk_slots(LoongArchInsn opc, uint32_t d, uint32_t j, uint32_t k) -+{ -+ return opc | d | j << 5 | k << 10; -+} -+ -+static int32_t __attribute__((unused)) -+encode_djkm_slots(LoongArchInsn opc, uint32_t d, uint32_t j, uint32_t k, -+ uint32_t m) -+{ -+ return opc | d | j << 5 | k << 10 | m << 16; -+} -+ -+static int32_t __attribute__((unused)) -+encode_dk_slots(LoongArchInsn opc, uint32_t d, uint32_t k) -+{ -+ return opc | d | k << 10; -+} -+ -+static int32_t __attribute__((unused)) -+encode_dj_insn(LoongArchInsn opc, TCGReg d, TCGReg j) -+{ -+ tcg_debug_assert(d >= 0 && d <= 0x1f); -+ tcg_debug_assert(j >= 0 && j <= 0x1f); -+ return encode_dj_slots(opc, d, j); -+} -+ -+static int32_t __attribute__((unused)) -+encode_djk_insn(LoongArchInsn opc, TCGReg d, TCGReg j, TCGReg k) -+{ -+ tcg_debug_assert(d >= 0 && d <= 0x1f); -+ tcg_debug_assert(j >= 0 && j <= 0x1f); -+ tcg_debug_assert(k >= 0 && k <= 0x1f); -+ return encode_djk_slots(opc, d, j, k); -+} -+ -+static int32_t __attribute__((unused)) -+encode_djsk12_insn(LoongArchInsn opc, TCGReg d, TCGReg j, int32_t sk12) -+{ -+ tcg_debug_assert(d >= 0 && d <= 0x1f); -+ tcg_debug_assert(j >= 0 && j <= 0x1f); -+ tcg_debug_assert(sk12 >= -0x800 && sk12 <= 0x7ff); -+ return encode_djk_slots(opc, d, j, sk12 & 0xfff); -+} -+ -+static int32_t __attribute__((unused)) -+encode_djsk16_insn(LoongArchInsn opc, TCGReg d, TCGReg j, int32_t sk16) -+{ -+ tcg_debug_assert(d >= 0 && d <= 0x1f); -+ tcg_debug_assert(j >= 0 && j <= 0x1f); -+ tcg_debug_assert(sk16 >= -0x8000 && sk16 <= 0x7fff); -+ return encode_djk_slots(opc, d, j, sk16 & 0xffff); -+} -+ -+static int32_t __attribute__((unused)) -+encode_djuk12_insn(LoongArchInsn opc, TCGReg d, TCGReg j, uint32_t uk12) -+{ -+ tcg_debug_assert(d >= 0 && d <= 0x1f); -+ tcg_debug_assert(j >= 0 && j <= 0x1f); -+ tcg_debug_assert(uk12 <= 0xfff); -+ return encode_djk_slots(opc, d, j, uk12); -+} -+ -+static int32_t __attribute__((unused)) -+encode_djuk5_insn(LoongArchInsn opc, TCGReg d, TCGReg j, uint32_t uk5) -+{ -+ tcg_debug_assert(d >= 0 && d <= 0x1f); -+ tcg_debug_assert(j >= 0 && j <= 0x1f); -+ tcg_debug_assert(uk5 <= 0x1f); -+ return encode_djk_slots(opc, d, j, uk5); -+} -+ -+static int32_t __attribute__((unused)) -+encode_djuk5um5_insn(LoongArchInsn opc, TCGReg d, TCGReg j, uint32_t uk5, -+ uint32_t um5) -+{ -+ tcg_debug_assert(d >= 0 && d <= 0x1f); -+ tcg_debug_assert(j >= 0 && j <= 0x1f); -+ tcg_debug_assert(uk5 <= 0x1f); -+ tcg_debug_assert(um5 <= 0x1f); -+ return encode_djkm_slots(opc, d, j, uk5, um5); -+} -+ -+static int32_t __attribute__((unused)) -+encode_djuk6_insn(LoongArchInsn opc, TCGReg d, TCGReg j, uint32_t uk6) -+{ -+ tcg_debug_assert(d >= 0 && d <= 0x1f); -+ tcg_debug_assert(j >= 0 && j <= 0x1f); -+ tcg_debug_assert(uk6 <= 0x3f); -+ return encode_djk_slots(opc, d, j, uk6); -+} -+ -+static int32_t __attribute__((unused)) -+encode_djuk6um6_insn(LoongArchInsn opc, TCGReg d, TCGReg j, uint32_t uk6, -+ uint32_t um6) -+{ -+ tcg_debug_assert(d >= 0 && d <= 0x1f); -+ tcg_debug_assert(j >= 0 && j <= 0x1f); -+ tcg_debug_assert(uk6 <= 0x3f); -+ tcg_debug_assert(um6 <= 0x3f); -+ return encode_djkm_slots(opc, d, j, uk6, um6); -+} -+ -+static int32_t __attribute__((unused)) -+encode_dsj20_insn(LoongArchInsn opc, TCGReg d, int32_t sj20) -+{ -+ tcg_debug_assert(d >= 0 && d <= 0x1f); -+ tcg_debug_assert(sj20 >= -0x80000 && sj20 <= 0x7ffff); -+ return encode_dj_slots(opc, d, sj20 & 0xfffff); -+} -+ -+static int32_t __attribute__((unused)) -+encode_sd10k16_insn(LoongArchInsn opc, int32_t sd10k16) -+{ -+ tcg_debug_assert(sd10k16 >= -0x2000000 && sd10k16 <= 0x1ffffff); -+ return encode_dk_slots(opc, (sd10k16 >> 16) & 0x3ff, sd10k16 & 0xffff); -+} -+ -+static int32_t __attribute__((unused)) -+encode_ud15_insn(LoongArchInsn opc, uint32_t ud15) -+{ -+ tcg_debug_assert(ud15 <= 0x7fff); -+ return encode_d_slot(opc, ud15); -+} -+ -+/* Emits the `clz.w d, j` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_clz_w(TCGContext *s, TCGReg d, TCGReg j) -+{ -+ tcg_out32(s, encode_dj_insn(OPC_CLZ_W, d, j)); -+} -+ -+/* Emits the `ctz.w d, j` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_ctz_w(TCGContext *s, TCGReg d, TCGReg j) -+{ -+ tcg_out32(s, encode_dj_insn(OPC_CTZ_W, d, j)); -+} -+ -+/* Emits the `clz.d d, j` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_clz_d(TCGContext *s, TCGReg d, TCGReg j) -+{ -+ tcg_out32(s, encode_dj_insn(OPC_CLZ_D, d, j)); -+} -+ -+/* Emits the `ctz.d d, j` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_ctz_d(TCGContext *s, TCGReg d, TCGReg j) -+{ -+ tcg_out32(s, encode_dj_insn(OPC_CTZ_D, d, j)); -+} -+ -+/* Emits the `revb.2h d, j` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_revb_2h(TCGContext *s, TCGReg d, TCGReg j) -+{ -+ tcg_out32(s, encode_dj_insn(OPC_REVB_2H, d, j)); -+} -+ -+/* Emits the `revb.2w d, j` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_revb_2w(TCGContext *s, TCGReg d, TCGReg j) -+{ -+ tcg_out32(s, encode_dj_insn(OPC_REVB_2W, d, j)); -+} -+ -+/* Emits the `revb.d d, j` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_revb_d(TCGContext *s, TCGReg d, TCGReg j) -+{ -+ tcg_out32(s, encode_dj_insn(OPC_REVB_D, d, j)); -+} -+ -+/* Emits the `sext.h d, j` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_sext_h(TCGContext *s, TCGReg d, TCGReg j) -+{ -+ tcg_out32(s, encode_dj_insn(OPC_SEXT_H, d, j)); -+} -+ -+/* Emits the `sext.b d, j` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_sext_b(TCGContext *s, TCGReg d, TCGReg j) -+{ -+ tcg_out32(s, encode_dj_insn(OPC_SEXT_B, d, j)); -+} -+ -+/* Emits the `add.w d, j, k` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_add_w(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) -+{ -+ tcg_out32(s, encode_djk_insn(OPC_ADD_W, d, j, k)); -+} -+ -+/* Emits the `add.d d, j, k` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_add_d(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) -+{ -+ tcg_out32(s, encode_djk_insn(OPC_ADD_D, d, j, k)); -+} -+ -+/* Emits the `sub.w d, j, k` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_sub_w(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) -+{ -+ tcg_out32(s, encode_djk_insn(OPC_SUB_W, d, j, k)); -+} -+ -+/* Emits the `sub.d d, j, k` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_sub_d(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) -+{ -+ tcg_out32(s, encode_djk_insn(OPC_SUB_D, d, j, k)); -+} -+ -+/* Emits the `slt d, j, k` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_slt(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) -+{ -+ tcg_out32(s, encode_djk_insn(OPC_SLT, d, j, k)); -+} -+ -+/* Emits the `sltu d, j, k` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_sltu(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) -+{ -+ tcg_out32(s, encode_djk_insn(OPC_SLTU, d, j, k)); -+} -+ -+/* Emits the `maskeqz d, j, k` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_maskeqz(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) -+{ -+ tcg_out32(s, encode_djk_insn(OPC_MASKEQZ, d, j, k)); -+} -+ -+/* Emits the `masknez d, j, k` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_masknez(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) -+{ -+ tcg_out32(s, encode_djk_insn(OPC_MASKNEZ, d, j, k)); -+} -+ -+/* Emits the `nor d, j, k` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_nor(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) -+{ -+ tcg_out32(s, encode_djk_insn(OPC_NOR, d, j, k)); -+} -+ -+/* Emits the `and d, j, k` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_and(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) -+{ -+ tcg_out32(s, encode_djk_insn(OPC_AND, d, j, k)); -+} -+ -+/* Emits the `or d, j, k` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_or(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) -+{ -+ tcg_out32(s, encode_djk_insn(OPC_OR, d, j, k)); -+} -+ -+/* Emits the `xor d, j, k` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_xor(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) -+{ -+ tcg_out32(s, encode_djk_insn(OPC_XOR, d, j, k)); -+} -+ -+/* Emits the `orn d, j, k` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_orn(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) -+{ -+ tcg_out32(s, encode_djk_insn(OPC_ORN, d, j, k)); -+} -+ -+/* Emits the `andn d, j, k` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_andn(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) -+{ -+ tcg_out32(s, encode_djk_insn(OPC_ANDN, d, j, k)); -+} -+ -+/* Emits the `sll.w d, j, k` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_sll_w(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) -+{ -+ tcg_out32(s, encode_djk_insn(OPC_SLL_W, d, j, k)); -+} -+ -+/* Emits the `srl.w d, j, k` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_srl_w(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) -+{ -+ tcg_out32(s, encode_djk_insn(OPC_SRL_W, d, j, k)); -+} -+ -+/* Emits the `sra.w d, j, k` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_sra_w(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) -+{ -+ tcg_out32(s, encode_djk_insn(OPC_SRA_W, d, j, k)); -+} -+ -+/* Emits the `sll.d d, j, k` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_sll_d(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) -+{ -+ tcg_out32(s, encode_djk_insn(OPC_SLL_D, d, j, k)); -+} -+ -+/* Emits the `srl.d d, j, k` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_srl_d(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) -+{ -+ tcg_out32(s, encode_djk_insn(OPC_SRL_D, d, j, k)); -+} -+ -+/* Emits the `sra.d d, j, k` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_sra_d(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) -+{ -+ tcg_out32(s, encode_djk_insn(OPC_SRA_D, d, j, k)); -+} -+ -+/* Emits the `rotr.w d, j, k` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_rotr_w(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) -+{ -+ tcg_out32(s, encode_djk_insn(OPC_ROTR_W, d, j, k)); -+} -+ -+/* Emits the `rotr.d d, j, k` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_rotr_d(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) -+{ -+ tcg_out32(s, encode_djk_insn(OPC_ROTR_D, d, j, k)); -+} -+ -+/* Emits the `mul.w d, j, k` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_mul_w(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) -+{ -+ tcg_out32(s, encode_djk_insn(OPC_MUL_W, d, j, k)); -+} -+ -+/* Emits the `mulh.w d, j, k` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_mulh_w(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) -+{ -+ tcg_out32(s, encode_djk_insn(OPC_MULH_W, d, j, k)); -+} -+ -+/* Emits the `mulh.wu d, j, k` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_mulh_wu(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) -+{ -+ tcg_out32(s, encode_djk_insn(OPC_MULH_WU, d, j, k)); -+} -+ -+/* Emits the `mul.d d, j, k` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_mul_d(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) -+{ -+ tcg_out32(s, encode_djk_insn(OPC_MUL_D, d, j, k)); -+} -+ -+/* Emits the `mulh.d d, j, k` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_mulh_d(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) -+{ -+ tcg_out32(s, encode_djk_insn(OPC_MULH_D, d, j, k)); -+} -+ -+/* Emits the `mulh.du d, j, k` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_mulh_du(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) -+{ -+ tcg_out32(s, encode_djk_insn(OPC_MULH_DU, d, j, k)); -+} -+ -+/* Emits the `div.w d, j, k` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_div_w(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) -+{ -+ tcg_out32(s, encode_djk_insn(OPC_DIV_W, d, j, k)); -+} -+ -+/* Emits the `mod.w d, j, k` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_mod_w(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) -+{ -+ tcg_out32(s, encode_djk_insn(OPC_MOD_W, d, j, k)); -+} -+ -+/* Emits the `div.wu d, j, k` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_div_wu(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) -+{ -+ tcg_out32(s, encode_djk_insn(OPC_DIV_WU, d, j, k)); -+} -+ -+/* Emits the `mod.wu d, j, k` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_mod_wu(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) -+{ -+ tcg_out32(s, encode_djk_insn(OPC_MOD_WU, d, j, k)); -+} -+ -+/* Emits the `div.d d, j, k` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_div_d(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) -+{ -+ tcg_out32(s, encode_djk_insn(OPC_DIV_D, d, j, k)); -+} -+ -+/* Emits the `mod.d d, j, k` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_mod_d(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) -+{ -+ tcg_out32(s, encode_djk_insn(OPC_MOD_D, d, j, k)); -+} -+ -+/* Emits the `div.du d, j, k` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_div_du(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) -+{ -+ tcg_out32(s, encode_djk_insn(OPC_DIV_DU, d, j, k)); -+} -+ -+/* Emits the `mod.du d, j, k` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_mod_du(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) -+{ -+ tcg_out32(s, encode_djk_insn(OPC_MOD_DU, d, j, k)); -+} -+ -+/* Emits the `slli.w d, j, uk5` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_slli_w(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk5) -+{ -+ tcg_out32(s, encode_djuk5_insn(OPC_SLLI_W, d, j, uk5)); -+} -+ -+/* Emits the `slli.d d, j, uk6` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_slli_d(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk6) -+{ -+ tcg_out32(s, encode_djuk6_insn(OPC_SLLI_D, d, j, uk6)); -+} -+ -+/* Emits the `srli.w d, j, uk5` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_srli_w(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk5) -+{ -+ tcg_out32(s, encode_djuk5_insn(OPC_SRLI_W, d, j, uk5)); -+} -+ -+/* Emits the `srli.d d, j, uk6` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_srli_d(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk6) -+{ -+ tcg_out32(s, encode_djuk6_insn(OPC_SRLI_D, d, j, uk6)); -+} -+ -+/* Emits the `srai.w d, j, uk5` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_srai_w(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk5) -+{ -+ tcg_out32(s, encode_djuk5_insn(OPC_SRAI_W, d, j, uk5)); -+} -+ -+/* Emits the `srai.d d, j, uk6` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_srai_d(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk6) -+{ -+ tcg_out32(s, encode_djuk6_insn(OPC_SRAI_D, d, j, uk6)); -+} -+ -+/* Emits the `rotri.w d, j, uk5` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_rotri_w(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk5) -+{ -+ tcg_out32(s, encode_djuk5_insn(OPC_ROTRI_W, d, j, uk5)); -+} -+ -+/* Emits the `rotri.d d, j, uk6` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_rotri_d(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk6) -+{ -+ tcg_out32(s, encode_djuk6_insn(OPC_ROTRI_D, d, j, uk6)); -+} -+ -+/* Emits the `bstrins.w d, j, uk5, um5` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_bstrins_w(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk5, -+ uint32_t um5) -+{ -+ tcg_out32(s, encode_djuk5um5_insn(OPC_BSTRINS_W, d, j, uk5, um5)); -+} -+ -+/* Emits the `bstrpick.w d, j, uk5, um5` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_bstrpick_w(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk5, -+ uint32_t um5) -+{ -+ tcg_out32(s, encode_djuk5um5_insn(OPC_BSTRPICK_W, d, j, uk5, um5)); -+} -+ -+/* Emits the `bstrins.d d, j, uk6, um6` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_bstrins_d(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk6, -+ uint32_t um6) -+{ -+ tcg_out32(s, encode_djuk6um6_insn(OPC_BSTRINS_D, d, j, uk6, um6)); -+} -+ -+/* Emits the `bstrpick.d d, j, uk6, um6` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_bstrpick_d(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk6, -+ uint32_t um6) -+{ -+ tcg_out32(s, encode_djuk6um6_insn(OPC_BSTRPICK_D, d, j, uk6, um6)); -+} -+ -+/* Emits the `slti d, j, sk12` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_slti(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) -+{ -+ tcg_out32(s, encode_djsk12_insn(OPC_SLTI, d, j, sk12)); -+} -+ -+/* Emits the `sltui d, j, sk12` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_sltui(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) -+{ -+ tcg_out32(s, encode_djsk12_insn(OPC_SLTUI, d, j, sk12)); -+} -+ -+/* Emits the `addi.w d, j, sk12` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_addi_w(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) -+{ -+ tcg_out32(s, encode_djsk12_insn(OPC_ADDI_W, d, j, sk12)); -+} -+ -+/* Emits the `addi.d d, j, sk12` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_addi_d(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) -+{ -+ tcg_out32(s, encode_djsk12_insn(OPC_ADDI_D, d, j, sk12)); -+} -+ -+/* Emits the `cu52i.d d, j, sk12` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_cu52i_d(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) -+{ -+ tcg_out32(s, encode_djsk12_insn(OPC_CU52I_D, d, j, sk12)); -+} -+ -+/* Emits the `andi d, j, uk12` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_andi(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk12) -+{ -+ tcg_out32(s, encode_djuk12_insn(OPC_ANDI, d, j, uk12)); -+} -+ -+/* Emits the `ori d, j, uk12` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_ori(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk12) -+{ -+ tcg_out32(s, encode_djuk12_insn(OPC_ORI, d, j, uk12)); -+} -+ -+/* Emits the `xori d, j, uk12` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_xori(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk12) -+{ -+ tcg_out32(s, encode_djuk12_insn(OPC_XORI, d, j, uk12)); -+} -+ -+/* Emits the `lu12i.w d, sj20` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_lu12i_w(TCGContext *s, TCGReg d, int32_t sj20) -+{ -+ tcg_out32(s, encode_dsj20_insn(OPC_LU12I_W, d, sj20)); -+} -+ -+/* Emits the `cu32i.d d, sj20` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_cu32i_d(TCGContext *s, TCGReg d, int32_t sj20) -+{ -+ tcg_out32(s, encode_dsj20_insn(OPC_CU32I_D, d, sj20)); -+} -+ -+/* Emits the `pcaddu2i d, sj20` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_pcaddu2i(TCGContext *s, TCGReg d, int32_t sj20) -+{ -+ tcg_out32(s, encode_dsj20_insn(OPC_PCADDU2I, d, sj20)); -+} -+ -+/* Emits the `pcalau12i d, sj20` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_pcalau12i(TCGContext *s, TCGReg d, int32_t sj20) -+{ -+ tcg_out32(s, encode_dsj20_insn(OPC_PCALAU12I, d, sj20)); -+} -+ -+/* Emits the `pcaddu12i d, sj20` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_pcaddu12i(TCGContext *s, TCGReg d, int32_t sj20) -+{ -+ tcg_out32(s, encode_dsj20_insn(OPC_PCADDU12I, d, sj20)); -+} -+ -+/* Emits the `pcaddu18i d, sj20` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_pcaddu18i(TCGContext *s, TCGReg d, int32_t sj20) -+{ -+ tcg_out32(s, encode_dsj20_insn(OPC_PCADDU18I, d, sj20)); -+} -+ -+/* Emits the `ld.b d, j, sk12` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_ld_b(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) -+{ -+ tcg_out32(s, encode_djsk12_insn(OPC_LD_B, d, j, sk12)); -+} -+ -+/* Emits the `ld.h d, j, sk12` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_ld_h(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) -+{ -+ tcg_out32(s, encode_djsk12_insn(OPC_LD_H, d, j, sk12)); -+} -+ -+/* Emits the `ld.w d, j, sk12` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_ld_w(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) -+{ -+ tcg_out32(s, encode_djsk12_insn(OPC_LD_W, d, j, sk12)); -+} -+ -+/* Emits the `ld.d d, j, sk12` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_ld_d(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) -+{ -+ tcg_out32(s, encode_djsk12_insn(OPC_LD_D, d, j, sk12)); -+} -+ -+/* Emits the `st.b d, j, sk12` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_st_b(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) -+{ -+ tcg_out32(s, encode_djsk12_insn(OPC_ST_B, d, j, sk12)); -+} -+ -+/* Emits the `st.h d, j, sk12` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_st_h(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) -+{ -+ tcg_out32(s, encode_djsk12_insn(OPC_ST_H, d, j, sk12)); -+} -+ -+/* Emits the `st.w d, j, sk12` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_st_w(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) -+{ -+ tcg_out32(s, encode_djsk12_insn(OPC_ST_W, d, j, sk12)); -+} -+ -+/* Emits the `st.d d, j, sk12` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_st_d(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) -+{ -+ tcg_out32(s, encode_djsk12_insn(OPC_ST_D, d, j, sk12)); -+} -+ -+/* Emits the `ld.bu d, j, sk12` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_ld_bu(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) -+{ -+ tcg_out32(s, encode_djsk12_insn(OPC_LD_BU, d, j, sk12)); -+} -+ -+/* Emits the `ld.hu d, j, sk12` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_ld_hu(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) -+{ -+ tcg_out32(s, encode_djsk12_insn(OPC_LD_HU, d, j, sk12)); -+} -+ -+/* Emits the `ld.wu d, j, sk12` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_ld_wu(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) -+{ -+ tcg_out32(s, encode_djsk12_insn(OPC_LD_WU, d, j, sk12)); -+} -+ -+/* Emits the `ldx.b d, j, k` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_ldx_b(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) -+{ -+ tcg_out32(s, encode_djk_insn(OPC_LDX_B, d, j, k)); -+} -+ -+/* Emits the `ldx.h d, j, k` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_ldx_h(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) -+{ -+ tcg_out32(s, encode_djk_insn(OPC_LDX_H, d, j, k)); -+} -+ -+/* Emits the `ldx.w d, j, k` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_ldx_w(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) -+{ -+ tcg_out32(s, encode_djk_insn(OPC_LDX_W, d, j, k)); -+} -+ -+/* Emits the `ldx.d d, j, k` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_ldx_d(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) -+{ -+ tcg_out32(s, encode_djk_insn(OPC_LDX_D, d, j, k)); -+} -+ -+/* Emits the `stx.b d, j, k` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_stx_b(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) -+{ -+ tcg_out32(s, encode_djk_insn(OPC_STX_B, d, j, k)); -+} -+ -+/* Emits the `stx.h d, j, k` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_stx_h(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) -+{ -+ tcg_out32(s, encode_djk_insn(OPC_STX_H, d, j, k)); -+} -+ -+/* Emits the `stx.w d, j, k` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_stx_w(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) -+{ -+ tcg_out32(s, encode_djk_insn(OPC_STX_W, d, j, k)); -+} -+ -+/* Emits the `stx.d d, j, k` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_stx_d(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) -+{ -+ tcg_out32(s, encode_djk_insn(OPC_STX_D, d, j, k)); -+} -+ -+/* Emits the `ldx.bu d, j, k` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_ldx_bu(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) -+{ -+ tcg_out32(s, encode_djk_insn(OPC_LDX_BU, d, j, k)); -+} -+ -+/* Emits the `ldx.hu d, j, k` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_ldx_hu(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) -+{ -+ tcg_out32(s, encode_djk_insn(OPC_LDX_HU, d, j, k)); -+} -+ -+/* Emits the `ldx.wu d, j, k` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_ldx_wu(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) -+{ -+ tcg_out32(s, encode_djk_insn(OPC_LDX_WU, d, j, k)); -+} -+ -+/* Emits the `dbar ud15` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_dbar(TCGContext *s, uint32_t ud15) -+{ -+ tcg_out32(s, encode_ud15_insn(OPC_DBAR, ud15)); -+} -+ -+/* Emits the `jirl d, j, sk16` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_jirl(TCGContext *s, TCGReg d, TCGReg j, int32_t sk16) -+{ -+ tcg_out32(s, encode_djsk16_insn(OPC_JIRL, d, j, sk16)); -+} -+ -+/* Emits the `b sd10k16` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_b(TCGContext *s, int32_t sd10k16) -+{ -+ tcg_out32(s, encode_sd10k16_insn(OPC_B, sd10k16)); -+} -+ -+/* Emits the `bl sd10k16` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_bl(TCGContext *s, int32_t sd10k16) -+{ -+ tcg_out32(s, encode_sd10k16_insn(OPC_BL, sd10k16)); -+} -+ -+/* Emits the `beq d, j, sk16` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_beq(TCGContext *s, TCGReg d, TCGReg j, int32_t sk16) -+{ -+ tcg_out32(s, encode_djsk16_insn(OPC_BEQ, d, j, sk16)); -+} -+ -+/* Emits the `bne d, j, sk16` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_bne(TCGContext *s, TCGReg d, TCGReg j, int32_t sk16) -+{ -+ tcg_out32(s, encode_djsk16_insn(OPC_BNE, d, j, sk16)); -+} -+ -+/* Emits the `bgt d, j, sk16` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_bgt(TCGContext *s, TCGReg d, TCGReg j, int32_t sk16) -+{ -+ tcg_out32(s, encode_djsk16_insn(OPC_BGT, d, j, sk16)); -+} -+ -+/* Emits the `ble d, j, sk16` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_ble(TCGContext *s, TCGReg d, TCGReg j, int32_t sk16) -+{ -+ tcg_out32(s, encode_djsk16_insn(OPC_BLE, d, j, sk16)); -+} -+ -+/* Emits the `bgtu d, j, sk16` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_bgtu(TCGContext *s, TCGReg d, TCGReg j, int32_t sk16) -+{ -+ tcg_out32(s, encode_djsk16_insn(OPC_BGTU, d, j, sk16)); -+} -+ -+/* Emits the `bleu d, j, sk16` instruction. */ -+static void __attribute__((unused)) -+tcg_out_opc_bleu(TCGContext *s, TCGReg d, TCGReg j, int32_t sk16) -+{ -+ tcg_out32(s, encode_djsk16_insn(OPC_BLEU, d, j, sk16)); -+} -+ -+/* End of generated code. */ -diff --git a/tcg/loongarch64/tcg-target-con-set.h b/tcg/loongarch64/tcg-target-con-set.h -new file mode 100644 -index 0000000000..349c672687 ---- /dev/null -+++ b/tcg/loongarch64/tcg-target-con-set.h -@@ -0,0 +1,31 @@ -+/* SPDX-License-Identifier: MIT */ -+/* -+ * Define LoongArch target-specific constraint sets. -+ * -+ * Copyright (c) 2021 WANG Xuerui -+ * -+ * Based on tcg/riscv/tcg-target-con-set.h -+ * -+ * Copyright (c) 2021 Linaro -+ */ -+ -+/* -+ * C_On_Im(...) defines a constraint set with outputs and inputs. -+ * Each operand should be a sequence of constraint letters as defined by -+ * tcg-target-con-str.h; the constraint combination is inclusive or. -+ */ -+C_O0_I1(r) -+C_O0_I2(rZ, r) -+C_O0_I2(rZ, rZ) -+C_O0_I2(LZ, L) -+C_O1_I1(r, r) -+C_O1_I1(r, L) -+C_O1_I2(r, r, rC) -+C_O1_I2(r, r, ri) -+C_O1_I2(r, r, rI) -+C_O1_I2(r, r, rU) -+C_O1_I2(r, r, rW) -+C_O1_I2(r, r, rZ) -+C_O1_I2(r, 0, rZ) -+C_O1_I2(r, rZ, rN) -+C_O1_I2(r, rZ, rZ) -diff --git a/tcg/loongarch64/tcg-target-con-str.h b/tcg/loongarch64/tcg-target-con-str.h -new file mode 100644 -index 0000000000..c3986a4fd4 ---- /dev/null -+++ b/tcg/loongarch64/tcg-target-con-str.h -@@ -0,0 +1,28 @@ -+/* SPDX-License-Identifier: MIT */ -+/* -+ * Define LoongArch target-specific operand constraints. -+ * -+ * Copyright (c) 2021 WANG Xuerui -+ * -+ * Based on tcg/riscv/tcg-target-con-str.h -+ * -+ * Copyright (c) 2021 Linaro -+ */ -+ -+/* -+ * Define constraint letters for register sets: -+ * REGS(letter, register_mask) -+ */ -+REGS('r', ALL_GENERAL_REGS) -+REGS('L', ALL_GENERAL_REGS & ~SOFTMMU_RESERVE_REGS) -+ -+/* -+ * Define constraint letters for constants: -+ * CONST(letter, TCG_CT_CONST_* bit set) -+ */ -+CONST('I', TCG_CT_CONST_S12) -+CONST('N', TCG_CT_CONST_N12) -+CONST('U', TCG_CT_CONST_U12) -+CONST('Z', TCG_CT_CONST_ZERO) -+CONST('C', TCG_CT_CONST_C12) -+CONST('W', TCG_CT_CONST_WSZ) -diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc -new file mode 100644 -index 0000000000..9b53549edb ---- /dev/null -+++ b/tcg/loongarch64/tcg-target.c.inc -@@ -0,0 +1,1744 @@ -+/* -+ * Tiny Code Generator for QEMU -+ * -+ * Copyright (c) 2021 WANG Xuerui -+ * -+ * Based on tcg/riscv/tcg-target.c.inc -+ * -+ * Copyright (c) 2018 SiFive, Inc -+ * Copyright (c) 2008-2009 Arnaud Patard -+ * Copyright (c) 2009 Aurelien Jarno -+ * Copyright (c) 2008 Fabrice Bellard -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a copy -+ * of this software and associated documentation files (the "Software"), to deal -+ * in the Software without restriction, including without limitation the rights -+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -+ * copies of the Software, and to permit persons to whom the Software is -+ * furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -+ * THE SOFTWARE. -+ */ -+ -+#include "../tcg-ldst.c.inc" -+ -+#ifdef CONFIG_DEBUG_TCG -+static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = { -+ "zero", -+ "ra", -+ "tp", -+ "sp", -+ "a0", -+ "a1", -+ "a2", -+ "a3", -+ "a4", -+ "a5", -+ "a6", -+ "a7", -+ "t0", -+ "t1", -+ "t2", -+ "t3", -+ "t4", -+ "t5", -+ "t6", -+ "t7", -+ "t8", -+ "r21", /* reserved in the LP64* ABI, hence no ABI name */ -+ "s9", -+ "s0", -+ "s1", -+ "s2", -+ "s3", -+ "s4", -+ "s5", -+ "s6", -+ "s7", -+ "s8" -+}; -+#endif -+ -+static const int tcg_target_reg_alloc_order[] = { -+ /* Registers preserved across calls */ -+ /* TCG_REG_S0 reserved for TCG_AREG0 */ -+ TCG_REG_S1, -+ TCG_REG_S2, -+ TCG_REG_S3, -+ TCG_REG_S4, -+ TCG_REG_S5, -+ TCG_REG_S6, -+ TCG_REG_S7, -+ TCG_REG_S8, -+ TCG_REG_S9, -+ -+ /* Registers (potentially) clobbered across calls */ -+ TCG_REG_T0, -+ TCG_REG_T1, -+ TCG_REG_T2, -+ TCG_REG_T3, -+ TCG_REG_T4, -+ TCG_REG_T5, -+ TCG_REG_T6, -+ TCG_REG_T7, -+ TCG_REG_T8, -+ -+ /* Argument registers, opposite order of allocation. */ -+ TCG_REG_A7, -+ TCG_REG_A6, -+ TCG_REG_A5, -+ TCG_REG_A4, -+ TCG_REG_A3, -+ TCG_REG_A2, -+ TCG_REG_A1, -+ TCG_REG_A0, -+}; -+ -+static const int tcg_target_call_iarg_regs[] = { -+ TCG_REG_A0, -+ TCG_REG_A1, -+ TCG_REG_A2, -+ TCG_REG_A3, -+ TCG_REG_A4, -+ TCG_REG_A5, -+ TCG_REG_A6, -+ TCG_REG_A7, -+}; -+ -+static const int tcg_target_call_oarg_regs[] = { -+ TCG_REG_A0, -+ TCG_REG_A1, -+}; -+ -+#ifndef CONFIG_SOFTMMU -+#define USE_GUEST_BASE (guest_base != 0) -+#define TCG_GUEST_BASE_REG TCG_REG_S1 -+#endif -+ -+#define TCG_CT_CONST_ZERO 0x100 -+#define TCG_CT_CONST_S12 0x200 -+#define TCG_CT_CONST_N12 0x400 -+#define TCG_CT_CONST_U12 0x800 -+#define TCG_CT_CONST_C12 0x1000 -+#define TCG_CT_CONST_WSZ 0x2000 -+ -+#define ALL_GENERAL_REGS MAKE_64BIT_MASK(0, 32) -+/* -+ * For softmmu, we need to avoid conflicts with the first 5 -+ * argument registers to call the helper. Some of these are -+ * also used for the tlb lookup. -+ */ -+#ifdef CONFIG_SOFTMMU -+#define SOFTMMU_RESERVE_REGS MAKE_64BIT_MASK(TCG_REG_A0, 5) -+#else -+#define SOFTMMU_RESERVE_REGS 0 -+#endif -+ -+ -+static inline tcg_target_long sextreg(tcg_target_long val, int pos, int len) -+{ -+ return sextract64(val, pos, len); -+} -+ -+/* test if a constant matches the constraint */ -+static bool tcg_target_const_match(int64_t val, TCGType type, int ct) -+{ -+ if (ct & TCG_CT_CONST) { -+ return true; -+ } -+ if ((ct & TCG_CT_CONST_ZERO) && val == 0) { -+ return true; -+ } -+ if ((ct & TCG_CT_CONST_S12) && val == sextreg(val, 0, 12)) { -+ return true; -+ } -+ if ((ct & TCG_CT_CONST_N12) && -val == sextreg(-val, 0, 12)) { -+ return true; -+ } -+ if ((ct & TCG_CT_CONST_U12) && val >= 0 && val <= 0xfff) { -+ return true; -+ } -+ if ((ct & TCG_CT_CONST_C12) && ~val >= 0 && ~val <= 0xfff) { -+ return true; -+ } -+ if ((ct & TCG_CT_CONST_WSZ) && val == (type == TCG_TYPE_I32 ? 32 : 64)) { -+ return true; -+ } -+ return false; -+} -+ -+/* -+ * Relocations -+ */ -+ -+/* -+ * Relocation records defined in LoongArch ELF psABI v1.00 is way too -+ * complicated; a whopping stack machine is needed to stuff the fields, at -+ * the very least one SOP_PUSH and one SOP_POP (of the correct format) are -+ * needed. -+ * -+ * Hence, define our own simpler relocation types. Numbers are chosen as to -+ * not collide with potential future additions to the true ELF relocation -+ * type enum. -+ */ -+ -+/* Field Sk16, shifted right by 2; suitable for conditional jumps */ -+#define R_LOONGARCH_BR_SK16 256 -+/* Field Sd10k16, shifted right by 2; suitable for B and BL */ -+#define R_LOONGARCH_BR_SD10K16 257 -+ -+static bool reloc_br_sk16(tcg_insn_unit *src_rw, const tcg_insn_unit *target) -+{ -+ const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw); -+ intptr_t offset = (intptr_t)target - (intptr_t)src_rx; -+ -+ tcg_debug_assert((offset & 3) == 0); -+ offset >>= 2; -+ if (offset == sextreg(offset, 0, 16)) { -+ *src_rw = deposit64(*src_rw, 10, 16, offset); -+ return true; -+ } -+ -+ return false; -+} -+ -+static bool reloc_br_sd10k16(tcg_insn_unit *src_rw, -+ const tcg_insn_unit *target) -+{ -+ const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw); -+ intptr_t offset = (intptr_t)target - (intptr_t)src_rx; -+ -+ tcg_debug_assert((offset & 3) == 0); -+ offset >>= 2; -+ if (offset == sextreg(offset, 0, 26)) { -+ *src_rw = deposit64(*src_rw, 0, 10, offset >> 16); /* slot d10 */ -+ *src_rw = deposit64(*src_rw, 10, 16, offset); /* slot k16 */ -+ return true; -+ } -+ -+ return false; -+} -+ -+static bool patch_reloc(tcg_insn_unit *code_ptr, int type, -+ intptr_t value, intptr_t addend) -+{ -+ tcg_debug_assert(addend == 0); -+ switch (type) { -+ case R_LOONGARCH_BR_SK16: -+ return reloc_br_sk16(code_ptr, (tcg_insn_unit *)value); -+ case R_LOONGARCH_BR_SD10K16: -+ return reloc_br_sd10k16(code_ptr, (tcg_insn_unit *)value); -+ default: -+ g_assert_not_reached(); -+ } -+} -+ -+#include "tcg-insn-defs.c.inc" -+ -+/* -+ * TCG intrinsics -+ */ -+ -+static void tcg_out_mb(TCGContext *s, TCGArg a0) -+{ -+ /* Baseline LoongArch only has the full barrier, unfortunately. */ -+ tcg_out_opc_dbar(s, 0); -+} -+ -+static bool tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg) -+{ -+ if (ret == arg) { -+ return true; -+ } -+ switch (type) { -+ case TCG_TYPE_I32: -+ case TCG_TYPE_I64: -+ /* -+ * Conventional register-register move used in LoongArch is -+ * `or dst, src, zero`. -+ */ -+ tcg_out_opc_or(s, ret, arg, TCG_REG_ZERO); -+ break; -+ default: -+ g_assert_not_reached(); -+ } -+ return true; -+} -+ -+static bool imm_part_needs_loading(bool high_bits_are_ones, -+ tcg_target_long part) -+{ -+ if (high_bits_are_ones) { -+ return part != -1; -+ } else { -+ return part != 0; -+ } -+} -+ -+/* Loads a 32-bit immediate into rd, sign-extended. */ -+static void tcg_out_movi_i32(TCGContext *s, TCGReg rd, int32_t val) -+{ -+ tcg_target_long lo = sextreg(val, 0, 12); -+ tcg_target_long hi12 = sextreg(val, 12, 20); -+ -+ /* Single-instruction cases. */ -+ if (lo == val) { -+ /* val fits in simm12: addi.w rd, zero, val */ -+ tcg_out_opc_addi_w(s, rd, TCG_REG_ZERO, val); -+ return; -+ } -+ if (0x800 <= val && val <= 0xfff) { -+ /* val fits in uimm12: ori rd, zero, val */ -+ tcg_out_opc_ori(s, rd, TCG_REG_ZERO, val); -+ return; -+ } -+ -+ /* High bits must be set; load with lu12i.w + optional ori. */ -+ tcg_out_opc_lu12i_w(s, rd, hi12); -+ if (lo != 0) { -+ tcg_out_opc_ori(s, rd, rd, lo & 0xfff); -+ } -+} -+ -+static void tcg_out_movi(TCGContext *s, TCGType type, TCGReg rd, -+ tcg_target_long val) -+{ -+ /* -+ * LoongArch conventionally loads 64-bit immediates in at most 4 steps, -+ * with dedicated instructions for filling the respective bitfields -+ * below: -+ * -+ * 6 5 4 3 -+ * 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 -+ * +-----------------------+---------------------------------------+... -+ * | hi52 | hi32 | -+ * +-----------------------+---------------------------------------+... -+ * 3 2 1 -+ * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 -+ * ...+-------------------------------------+-------------------------+ -+ * | hi12 | lo | -+ * ...+-------------------------------------+-------------------------+ -+ * -+ * Check if val belong to one of the several fast cases, before falling -+ * back to the slow path. -+ */ -+ -+ intptr_t pc_offset; -+ tcg_target_long val_lo, val_hi, pc_hi, offset_hi; -+ tcg_target_long hi32, hi52; -+ bool rd_high_bits_are_ones; -+ -+ /* Value fits in signed i32. */ -+ if (type == TCG_TYPE_I32 || val == (int32_t)val) { -+ tcg_out_movi_i32(s, rd, val); -+ return; -+ } -+ -+ /* PC-relative cases. */ -+ pc_offset = tcg_pcrel_diff(s, (void *)val); -+ if (pc_offset == sextreg(pc_offset, 0, 22) && (pc_offset & 3) == 0) { -+ /* Single pcaddu2i. */ -+ tcg_out_opc_pcaddu2i(s, rd, pc_offset >> 2); -+ return; -+ } -+ -+ if (pc_offset == (int32_t)pc_offset) { -+ /* Offset within 32 bits; load with pcalau12i + ori. */ -+ val_lo = sextreg(val, 0, 12); -+ val_hi = val >> 12; -+ pc_hi = (val - pc_offset) >> 12; -+ offset_hi = val_hi - pc_hi; -+ -+ tcg_debug_assert(offset_hi == sextreg(offset_hi, 0, 20)); -+ tcg_out_opc_pcalau12i(s, rd, offset_hi); -+ if (val_lo != 0) { -+ tcg_out_opc_ori(s, rd, rd, val_lo & 0xfff); -+ } -+ return; -+ } -+ -+ hi32 = sextreg(val, 32, 20); -+ hi52 = sextreg(val, 52, 12); -+ -+ /* Single cu52i.d case. */ -+ if (ctz64(val) >= 52) { -+ tcg_out_opc_cu52i_d(s, rd, TCG_REG_ZERO, hi52); -+ return; -+ } -+ -+ /* Slow path. Initialize the low 32 bits, then concat high bits. */ -+ tcg_out_movi_i32(s, rd, val); -+ rd_high_bits_are_ones = (int32_t)val < 0; -+ -+ if (imm_part_needs_loading(rd_high_bits_are_ones, hi32)) { -+ tcg_out_opc_cu32i_d(s, rd, hi32); -+ rd_high_bits_are_ones = hi32 < 0; -+ } -+ -+ if (imm_part_needs_loading(rd_high_bits_are_ones, hi52)) { -+ tcg_out_opc_cu52i_d(s, rd, rd, hi52); -+ } -+} -+ -+static void tcg_out_ext8u(TCGContext *s, TCGReg ret, TCGReg arg) -+{ -+ tcg_out_opc_andi(s, ret, arg, 0xff); -+} -+ -+static void tcg_out_ext16u(TCGContext *s, TCGReg ret, TCGReg arg) -+{ -+ tcg_out_opc_bstrpick_w(s, ret, arg, 0, 15); -+} -+ -+static void tcg_out_ext32u(TCGContext *s, TCGReg ret, TCGReg arg) -+{ -+ tcg_out_opc_bstrpick_d(s, ret, arg, 0, 31); -+} -+ -+static void tcg_out_ext8s(TCGContext *s, TCGReg ret, TCGReg arg) -+{ -+ tcg_out_opc_sext_b(s, ret, arg); -+} -+ -+static void tcg_out_ext16s(TCGContext *s, TCGReg ret, TCGReg arg) -+{ -+ tcg_out_opc_sext_h(s, ret, arg); -+} -+ -+static void tcg_out_ext32s(TCGContext *s, TCGReg ret, TCGReg arg) -+{ -+ tcg_out_opc_addi_w(s, ret, arg, 0); -+} -+ -+static void tcg_out_clzctz(TCGContext *s, LoongArchInsn opc, -+ TCGReg a0, TCGReg a1, TCGReg a2, -+ bool c2, bool is_32bit) -+{ -+ if (c2) { -+ /* -+ * Fast path: semantics already satisfied due to constraint and -+ * insn behavior, single instruction is enough. -+ */ -+ tcg_debug_assert(a2 == (is_32bit ? 32 : 64)); -+ /* all clz/ctz insns belong to DJ-format */ -+ tcg_out32(s, encode_dj_insn(opc, a0, a1)); -+ return; -+ } -+ -+ tcg_out32(s, encode_dj_insn(opc, TCG_REG_TMP0, a1)); -+ /* a0 = a1 ? REG_TMP0 : a2 */ -+ tcg_out_opc_maskeqz(s, TCG_REG_TMP0, TCG_REG_TMP0, a1); -+ tcg_out_opc_masknez(s, a0, a2, a1); -+ tcg_out_opc_or(s, a0, TCG_REG_TMP0, a0); -+} -+ -+static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret, -+ TCGReg arg1, TCGReg arg2, bool c2) -+{ -+ TCGReg tmp; -+ -+ if (c2) { -+ tcg_debug_assert(arg2 == 0); -+ } -+ -+ switch (cond) { -+ case TCG_COND_EQ: -+ if (c2) { -+ tmp = arg1; -+ } else { -+ tcg_out_opc_sub_d(s, ret, arg1, arg2); -+ tmp = ret; -+ } -+ tcg_out_opc_sltui(s, ret, tmp, 1); -+ break; -+ case TCG_COND_NE: -+ if (c2) { -+ tmp = arg1; -+ } else { -+ tcg_out_opc_sub_d(s, ret, arg1, arg2); -+ tmp = ret; -+ } -+ tcg_out_opc_sltu(s, ret, TCG_REG_ZERO, tmp); -+ break; -+ case TCG_COND_LT: -+ tcg_out_opc_slt(s, ret, arg1, arg2); -+ break; -+ case TCG_COND_GE: -+ tcg_out_opc_slt(s, ret, arg1, arg2); -+ tcg_out_opc_xori(s, ret, ret, 1); -+ break; -+ case TCG_COND_LE: -+ tcg_out_setcond(s, TCG_COND_GE, ret, arg2, arg1, false); -+ break; -+ case TCG_COND_GT: -+ tcg_out_setcond(s, TCG_COND_LT, ret, arg2, arg1, false); -+ break; -+ case TCG_COND_LTU: -+ tcg_out_opc_sltu(s, ret, arg1, arg2); -+ break; -+ case TCG_COND_GEU: -+ tcg_out_opc_sltu(s, ret, arg1, arg2); -+ tcg_out_opc_xori(s, ret, ret, 1); -+ break; -+ case TCG_COND_LEU: -+ tcg_out_setcond(s, TCG_COND_GEU, ret, arg2, arg1, false); -+ break; -+ case TCG_COND_GTU: -+ tcg_out_setcond(s, TCG_COND_LTU, ret, arg2, arg1, false); -+ break; -+ default: -+ g_assert_not_reached(); -+ break; -+ } -+} -+ -+/* -+ * Branch helpers -+ */ -+ -+static const struct { -+ LoongArchInsn op; -+ bool swap; -+} tcg_brcond_to_loongarch[] = { -+ [TCG_COND_EQ] = { OPC_BEQ, false }, -+ [TCG_COND_NE] = { OPC_BNE, false }, -+ [TCG_COND_LT] = { OPC_BGT, true }, -+ [TCG_COND_GE] = { OPC_BLE, true }, -+ [TCG_COND_LE] = { OPC_BLE, false }, -+ [TCG_COND_GT] = { OPC_BGT, false }, -+ [TCG_COND_LTU] = { OPC_BGTU, true }, -+ [TCG_COND_GEU] = { OPC_BLEU, true }, -+ [TCG_COND_LEU] = { OPC_BLEU, false }, -+ [TCG_COND_GTU] = { OPC_BGTU, false } -+}; -+ -+static void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGReg arg1, -+ TCGReg arg2, TCGLabel *l) -+{ -+ LoongArchInsn op = tcg_brcond_to_loongarch[cond].op; -+ -+ tcg_debug_assert(op != 0); -+ -+ if (tcg_brcond_to_loongarch[cond].swap) { -+ TCGReg t = arg1; -+ arg1 = arg2; -+ arg2 = t; -+ } -+ -+ /* all conditional branch insns belong to DJSk16-format */ -+ tcg_out_reloc(s, s->code_ptr, R_LOONGARCH_BR_SK16, l, 0); -+ tcg_out32(s, encode_djsk16_insn(op, arg1, arg2, 0)); -+} -+ -+static void tcg_out_call_int(TCGContext *s, const tcg_insn_unit *arg, bool tail) -+{ -+ TCGReg link = tail ? TCG_REG_ZERO : TCG_REG_RA; -+ ptrdiff_t offset = tcg_pcrel_diff(s, arg); -+ -+ tcg_debug_assert((offset & 3) == 0); -+ if (offset == sextreg(offset, 0, 28)) { -+ /* short jump: +/- 256MiB */ -+ if (tail) { -+ tcg_out_opc_b(s, offset >> 2); -+ } else { -+ tcg_out_opc_bl(s, offset >> 2); -+ } -+ } else if (offset == sextreg(offset, 0, 38)) { -+ /* long jump: +/- 256GiB */ -+ tcg_target_long lo = sextreg(offset, 0, 18); -+ tcg_target_long hi = offset - lo; -+ tcg_out_opc_pcaddu18i(s, TCG_REG_TMP0, hi >> 18); -+ tcg_out_opc_jirl(s, link, TCG_REG_TMP0, lo >> 2); -+ } else { -+ /* far jump: 64-bit */ -+ tcg_target_long lo = sextreg((tcg_target_long)arg, 0, 18); -+ tcg_target_long hi = (tcg_target_long)arg - lo; -+ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP0, hi); -+ tcg_out_opc_jirl(s, link, TCG_REG_TMP0, lo >> 2); -+ } -+} -+ -+static void tcg_out_call(TCGContext *s, const tcg_insn_unit *arg) -+{ -+ tcg_out_call_int(s, arg, false); -+} -+ -+/* -+ * Load/store helpers -+ */ -+ -+static void tcg_out_ldst(TCGContext *s, LoongArchInsn opc, TCGReg data, -+ TCGReg addr, intptr_t offset) -+{ -+ intptr_t imm12 = sextreg(offset, 0, 12); -+ -+ if (offset != imm12) { -+ intptr_t diff = offset - (uintptr_t)s->code_ptr; -+ -+ if (addr == TCG_REG_ZERO && diff == (int32_t)diff) { -+ imm12 = sextreg(diff, 0, 12); -+ tcg_out_opc_pcaddu12i(s, TCG_REG_TMP2, (diff - imm12) >> 12); -+ } else { -+ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP2, offset - imm12); -+ if (addr != TCG_REG_ZERO) { -+ tcg_out_opc_add_d(s, TCG_REG_TMP2, TCG_REG_TMP2, addr); -+ } -+ } -+ addr = TCG_REG_TMP2; -+ } -+ -+ switch (opc) { -+ case OPC_LD_B: -+ case OPC_LD_BU: -+ case OPC_LD_H: -+ case OPC_LD_HU: -+ case OPC_LD_W: -+ case OPC_LD_WU: -+ case OPC_LD_D: -+ case OPC_ST_B: -+ case OPC_ST_H: -+ case OPC_ST_W: -+ case OPC_ST_D: -+ tcg_out32(s, encode_djsk12_insn(opc, data, addr, imm12)); -+ break; -+ default: -+ g_assert_not_reached(); -+ } -+} -+ -+static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg, -+ TCGReg arg1, intptr_t arg2) -+{ -+ bool is_32bit = type == TCG_TYPE_I32; -+ tcg_out_ldst(s, is_32bit ? OPC_LD_W : OPC_LD_D, arg, arg1, arg2); -+} -+ -+static void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, -+ TCGReg arg1, intptr_t arg2) -+{ -+ bool is_32bit = type == TCG_TYPE_I32; -+ tcg_out_ldst(s, is_32bit ? OPC_ST_W : OPC_ST_D, arg, arg1, arg2); -+} -+ -+static bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val, -+ TCGReg base, intptr_t ofs) -+{ -+ if (val == 0) { -+ tcg_out_st(s, type, TCG_REG_ZERO, base, ofs); -+ return true; -+ } -+ return false; -+} -+ -+/* -+ * Load/store helpers for SoftMMU, and qemu_ld/st implementations -+ */ -+ -+#if defined(CONFIG_SOFTMMU) -+/* -+ * helper signature: helper_ret_ld_mmu(CPUState *env, target_ulong addr, -+ * MemOpIdx oi, uintptr_t ra) -+ */ -+static void * const qemu_ld_helpers[4] = { -+ [MO_8] = helper_ret_ldub_mmu, -+ [MO_16] = helper_le_lduw_mmu, -+ [MO_32] = helper_le_ldul_mmu, -+ [MO_64] = helper_le_ldq_mmu, -+}; -+ -+/* -+ * helper signature: helper_ret_st_mmu(CPUState *env, target_ulong addr, -+ * uintxx_t val, MemOpIdx oi, -+ * uintptr_t ra) -+ */ -+static void * const qemu_st_helpers[4] = { -+ [MO_8] = helper_ret_stb_mmu, -+ [MO_16] = helper_le_stw_mmu, -+ [MO_32] = helper_le_stl_mmu, -+ [MO_64] = helper_le_stq_mmu, -+}; -+ -+/* We expect to use a 12-bit negative offset from ENV. */ -+QEMU_BUILD_BUG_ON(TLB_MASK_TABLE_OFS(0) > 0); -+QEMU_BUILD_BUG_ON(TLB_MASK_TABLE_OFS(0) < -(1 << 11)); -+ -+static bool tcg_out_goto(TCGContext *s, const tcg_insn_unit *target) -+{ -+ tcg_out_opc_b(s, 0); -+ return reloc_br_sd10k16(s->code_ptr - 1, target); -+} -+ -+/* -+ * Emits common code for TLB addend lookup, that eventually loads the -+ * addend in TCG_REG_TMP2. -+ */ -+static void tcg_out_tlb_load(TCGContext *s, TCGReg addrl, MemOpIdx oi, -+ tcg_insn_unit **label_ptr, bool is_load) -+{ -+ MemOp opc = get_memop(oi); -+ unsigned s_bits = opc & MO_SIZE; -+ unsigned a_bits = get_alignment_bits(opc); -+ tcg_target_long compare_mask; -+ int mem_index = get_mmuidx(oi); -+ int fast_ofs = TLB_MASK_TABLE_OFS(mem_index); -+ int mask_ofs = fast_ofs + offsetof(CPUTLBDescFast, mask); -+ int table_ofs = fast_ofs + offsetof(CPUTLBDescFast, table); -+ -+ tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, TCG_AREG0, mask_ofs); -+ tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP1, TCG_AREG0, table_ofs); -+ -+ tcg_out_opc_srli_d(s, TCG_REG_TMP2, addrl, -+ TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS); -+ tcg_out_opc_and(s, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP0); -+ tcg_out_opc_add_d(s, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP1); -+ -+ /* Load the tlb comparator and the addend. */ -+ tcg_out_ld(s, TCG_TYPE_TL, TCG_REG_TMP0, TCG_REG_TMP2, -+ is_load ? offsetof(CPUTLBEntry, addr_read) -+ : offsetof(CPUTLBEntry, addr_write)); -+ tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP2, TCG_REG_TMP2, -+ offsetof(CPUTLBEntry, addend)); -+ -+ /* We don't support unaligned accesses. */ -+ if (a_bits < s_bits) { -+ a_bits = s_bits; -+ } -+ /* Clear the non-page, non-alignment bits from the address. */ -+ compare_mask = (tcg_target_long)TARGET_PAGE_MASK | ((1 << a_bits) - 1); -+ tcg_out_movi(s, TCG_TYPE_TL, TCG_REG_TMP1, compare_mask); -+ tcg_out_opc_and(s, TCG_REG_TMP1, TCG_REG_TMP1, addrl); -+ -+ /* Compare masked address with the TLB entry. */ -+ label_ptr[0] = s->code_ptr; -+ tcg_out_opc_bne(s, TCG_REG_TMP0, TCG_REG_TMP1, 0); -+ -+ /* TLB Hit - addend in TCG_REG_TMP2, ready for use. */ -+} -+ -+static void add_qemu_ldst_label(TCGContext *s, int is_ld, MemOpIdx oi, -+ TCGType type, -+ TCGReg datalo, TCGReg addrlo, -+ void *raddr, tcg_insn_unit **label_ptr) -+{ -+ TCGLabelQemuLdst *label = new_ldst_label(s); -+ -+ label->is_ld = is_ld; -+ label->oi = oi; -+ label->type = type; -+ label->datalo_reg = datalo; -+ label->datahi_reg = 0; /* unused */ -+ label->addrlo_reg = addrlo; -+ label->addrhi_reg = 0; /* unused */ -+ label->raddr = tcg_splitwx_to_rx(raddr); -+ label->label_ptr[0] = label_ptr[0]; -+} -+ -+static bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l) -+{ -+ MemOpIdx oi = l->oi; -+ MemOp opc = get_memop(oi); -+ MemOp size = opc & MO_SIZE; -+ TCGType type = l->type; -+ -+ /* resolve label address */ -+ if (!reloc_br_sk16(l->label_ptr[0], tcg_splitwx_to_rx(s->code_ptr))) { -+ return false; -+ } -+ -+ /* call load helper */ -+ tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_A0, TCG_AREG0); -+ tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_A1, l->addrlo_reg); -+ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A2, oi); -+ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A3, (tcg_target_long)l->raddr); -+ -+ tcg_out_call(s, qemu_ld_helpers[size]); -+ -+ switch (opc & MO_SSIZE) { -+ case MO_SB: -+ tcg_out_ext8s(s, l->datalo_reg, TCG_REG_A0); -+ break; -+ case MO_SW: -+ tcg_out_ext16s(s, l->datalo_reg, TCG_REG_A0); -+ break; -+ case MO_SL: -+ tcg_out_ext32s(s, l->datalo_reg, TCG_REG_A0); -+ break; -+ case MO_UL: -+ if (type == TCG_TYPE_I32) { -+ /* MO_UL loads of i32 should be sign-extended too */ -+ tcg_out_ext32s(s, l->datalo_reg, TCG_REG_A0); -+ break; -+ } -+ /* fallthrough */ -+ default: -+ tcg_out_mov(s, type, l->datalo_reg, TCG_REG_A0); -+ break; -+ } -+ -+ return tcg_out_goto(s, l->raddr); -+} -+ -+static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l) -+{ -+ MemOpIdx oi = l->oi; -+ MemOp opc = get_memop(oi); -+ MemOp size = opc & MO_SIZE; -+ -+ /* resolve label address */ -+ if (!reloc_br_sk16(l->label_ptr[0], tcg_splitwx_to_rx(s->code_ptr))) { -+ return false; -+ } -+ -+ /* call store helper */ -+ tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_A0, TCG_AREG0); -+ tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_A1, l->addrlo_reg); -+ switch (size) { -+ case MO_8: -+ tcg_out_ext8u(s, TCG_REG_A2, l->datalo_reg); -+ break; -+ case MO_16: -+ tcg_out_ext16u(s, TCG_REG_A2, l->datalo_reg); -+ break; -+ case MO_32: -+ tcg_out_ext32u(s, TCG_REG_A2, l->datalo_reg); -+ break; -+ case MO_64: -+ tcg_out_mov(s, TCG_TYPE_I64, TCG_REG_A2, l->datalo_reg); -+ break; -+ default: -+ g_assert_not_reached(); -+ break; -+ } -+ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A3, oi); -+ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A4, (tcg_target_long)l->raddr); -+ -+ tcg_out_call(s, qemu_st_helpers[size]); -+ -+ return tcg_out_goto(s, l->raddr); -+} -+#else -+ -+/* -+ * Alignment helpers for user-mode emulation -+ */ -+ -+static void tcg_out_test_alignment(TCGContext *s, bool is_ld, TCGReg addr_reg, -+ unsigned a_bits) -+{ -+ TCGLabelQemuLdst *l = new_ldst_label(s); -+ -+ l->is_ld = is_ld; -+ l->addrlo_reg = addr_reg; -+ -+ /* -+ * Without micro-architecture details, we don't know which of bstrpick or -+ * andi is faster, so use bstrpick as it's not constrained by imm field -+ * width. (Not to say alignments >= 2^12 are going to happen any time -+ * soon, though) -+ */ -+ tcg_out_opc_bstrpick_d(s, TCG_REG_TMP1, addr_reg, 0, a_bits - 1); -+ -+ l->label_ptr[0] = s->code_ptr; -+ tcg_out_opc_bne(s, TCG_REG_TMP1, TCG_REG_ZERO, 0); -+ -+ l->raddr = tcg_splitwx_to_rx(s->code_ptr); -+} -+ -+static bool tcg_out_fail_alignment(TCGContext *s, TCGLabelQemuLdst *l) -+{ -+ /* resolve label address */ -+ if (!reloc_br_sk16(l->label_ptr[0], tcg_splitwx_to_rx(s->code_ptr))) { -+ return false; -+ } -+ -+ tcg_out_mov(s, TCG_TYPE_TL, TCG_REG_A1, l->addrlo_reg); -+ tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_A0, TCG_AREG0); -+ -+ /* tail call, with the return address back inline. */ -+ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_RA, (uintptr_t)l->raddr); -+ tcg_out_call_int(s, (const void *)(l->is_ld ? helper_unaligned_ld -+ : helper_unaligned_st), true); -+ return true; -+} -+ -+static bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l) -+{ -+ return tcg_out_fail_alignment(s, l); -+} -+ -+static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l) -+{ -+ return tcg_out_fail_alignment(s, l); -+} -+ -+#endif /* CONFIG_SOFTMMU */ -+ -+/* -+ * `ext32u` the address register into the temp register given, -+ * if target is 32-bit, no-op otherwise. -+ * -+ * Returns the address register ready for use with TLB addend. -+ */ -+static TCGReg tcg_out_zext_addr_if_32_bit(TCGContext *s, -+ TCGReg addr, TCGReg tmp) -+{ -+ if (TARGET_LONG_BITS == 32) { -+ tcg_out_ext32u(s, tmp, addr); -+ return tmp; -+ } -+ return addr; -+} -+ -+static void tcg_out_qemu_ld_indexed(TCGContext *s, TCGReg rd, TCGReg rj, -+ TCGReg rk, MemOp opc, TCGType type) -+{ -+ /* Byte swapping is left to middle-end expansion. */ -+ tcg_debug_assert((opc & MO_BSWAP) == 0); -+ -+ switch (opc & MO_SSIZE) { -+ case MO_UB: -+ tcg_out_opc_ldx_bu(s, rd, rj, rk); -+ break; -+ case MO_SB: -+ tcg_out_opc_ldx_b(s, rd, rj, rk); -+ break; -+ case MO_UW: -+ tcg_out_opc_ldx_hu(s, rd, rj, rk); -+ break; -+ case MO_SW: -+ tcg_out_opc_ldx_h(s, rd, rj, rk); -+ break; -+ case MO_UL: -+ if (type == TCG_TYPE_I64) { -+ tcg_out_opc_ldx_wu(s, rd, rj, rk); -+ break; -+ } -+ /* fallthrough */ -+ case MO_SL: -+ tcg_out_opc_ldx_w(s, rd, rj, rk); -+ break; -+ case MO_Q: -+ tcg_out_opc_ldx_d(s, rd, rj, rk); -+ break; -+ default: -+ g_assert_not_reached(); -+ } -+} -+ -+static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, TCGType type) -+{ -+ TCGReg addr_regl; -+ TCGReg data_regl; -+ MemOpIdx oi; -+ MemOp opc; -+#if defined(CONFIG_SOFTMMU) -+ tcg_insn_unit *label_ptr[1]; -+#else -+ unsigned a_bits; -+#endif -+ TCGReg base; -+ -+ data_regl = *args++; -+ addr_regl = *args++; -+ oi = *args++; -+ opc = get_memop(oi); -+ -+#if defined(CONFIG_SOFTMMU) -+ tcg_out_tlb_load(s, addr_regl, oi, label_ptr, 1); -+ base = tcg_out_zext_addr_if_32_bit(s, addr_regl, TCG_REG_TMP0); -+ tcg_out_qemu_ld_indexed(s, data_regl, base, TCG_REG_TMP2, opc, type); -+ add_qemu_ldst_label(s, 1, oi, type, -+ data_regl, addr_regl, -+ s->code_ptr, label_ptr); -+#else -+ a_bits = get_alignment_bits(opc); -+ if (a_bits) { -+ tcg_out_test_alignment(s, true, addr_regl, a_bits); -+ } -+ base = tcg_out_zext_addr_if_32_bit(s, addr_regl, TCG_REG_TMP0); -+ TCGReg guest_base_reg = USE_GUEST_BASE ? TCG_GUEST_BASE_REG : TCG_REG_ZERO; -+ tcg_out_qemu_ld_indexed(s, data_regl, base, guest_base_reg, opc, type); -+#endif -+} -+ -+static void tcg_out_qemu_st_indexed(TCGContext *s, TCGReg data, -+ TCGReg rj, TCGReg rk, MemOp opc) -+{ -+ /* Byte swapping is left to middle-end expansion. */ -+ tcg_debug_assert((opc & MO_BSWAP) == 0); -+ -+ switch (opc & MO_SIZE) { -+ case MO_8: -+ tcg_out_opc_stx_b(s, data, rj, rk); -+ break; -+ case MO_16: -+ tcg_out_opc_stx_h(s, data, rj, rk); -+ break; -+ case MO_32: -+ tcg_out_opc_stx_w(s, data, rj, rk); -+ break; -+ case MO_64: -+ tcg_out_opc_stx_d(s, data, rj, rk); -+ break; -+ default: -+ g_assert_not_reached(); -+ } -+} -+ -+static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args) -+{ -+ TCGReg addr_regl; -+ TCGReg data_regl; -+ MemOpIdx oi; -+ MemOp opc; -+#if defined(CONFIG_SOFTMMU) -+ tcg_insn_unit *label_ptr[1]; -+#else -+ unsigned a_bits; -+#endif -+ TCGReg base; -+ -+ data_regl = *args++; -+ addr_regl = *args++; -+ oi = *args++; -+ opc = get_memop(oi); -+ -+#if defined(CONFIG_SOFTMMU) -+ tcg_out_tlb_load(s, addr_regl, oi, label_ptr, 0); -+ base = tcg_out_zext_addr_if_32_bit(s, addr_regl, TCG_REG_TMP0); -+ tcg_out_qemu_st_indexed(s, data_regl, base, TCG_REG_TMP2, opc); -+ add_qemu_ldst_label(s, 0, oi, -+ 0, /* type param is unused for stores */ -+ data_regl, addr_regl, -+ s->code_ptr, label_ptr); -+#else -+ a_bits = get_alignment_bits(opc); -+ if (a_bits) { -+ tcg_out_test_alignment(s, false, addr_regl, a_bits); -+ } -+ base = tcg_out_zext_addr_if_32_bit(s, addr_regl, TCG_REG_TMP0); -+ TCGReg guest_base_reg = USE_GUEST_BASE ? TCG_GUEST_BASE_REG : TCG_REG_ZERO; -+ tcg_out_qemu_st_indexed(s, data_regl, base, guest_base_reg, opc); -+#endif -+} -+ -+/* -+ * Entry-points -+ */ -+ -+static const tcg_insn_unit *tb_ret_addr; -+ -+static void tcg_out_op(TCGContext *s, TCGOpcode opc, -+ const TCGArg args[TCG_MAX_OP_ARGS], -+ const int const_args[TCG_MAX_OP_ARGS]) -+{ -+ TCGArg a0 = args[0]; -+ TCGArg a1 = args[1]; -+ TCGArg a2 = args[2]; -+ int c2 = const_args[2]; -+ -+ switch (opc) { -+ case INDEX_op_exit_tb: -+ /* Reuse the zeroing that exists for goto_ptr. */ -+ if (a0 == 0) { -+ tcg_out_call_int(s, tcg_code_gen_epilogue, true); -+ } else { -+ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A0, a0); -+ tcg_out_call_int(s, tb_ret_addr, true); -+ } -+ break; -+ -+ case INDEX_op_goto_tb: -+ assert(s->tb_jmp_insn_offset == 0); -+ /* indirect jump method */ -+ tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, TCG_REG_ZERO, -+ (uintptr_t)(s->tb_jmp_target_addr + a0)); -+ tcg_out_opc_jirl(s, TCG_REG_ZERO, TCG_REG_TMP0, 0); -+ set_jmp_reset_offset(s, a0); -+ break; -+ -+ case INDEX_op_mb: -+ tcg_out_mb(s, a0); -+ break; -+ -+ case INDEX_op_goto_ptr: -+ tcg_out_opc_jirl(s, TCG_REG_ZERO, a0, 0); -+ break; -+ -+ case INDEX_op_br: -+ tcg_out_reloc(s, s->code_ptr, R_LOONGARCH_BR_SD10K16, arg_label(a0), -+ 0); -+ tcg_out_opc_b(s, 0); -+ break; -+ -+ case INDEX_op_brcond_i32: -+ case INDEX_op_brcond_i64: -+ tcg_out_brcond(s, a2, a0, a1, arg_label(args[3])); -+ break; -+ -+ case INDEX_op_ext8s_i32: -+ case INDEX_op_ext8s_i64: -+ tcg_out_ext8s(s, a0, a1); -+ break; -+ -+ case INDEX_op_ext8u_i32: -+ case INDEX_op_ext8u_i64: -+ tcg_out_ext8u(s, a0, a1); -+ break; -+ -+ case INDEX_op_ext16s_i32: -+ case INDEX_op_ext16s_i64: -+ tcg_out_ext16s(s, a0, a1); -+ break; -+ -+ case INDEX_op_ext16u_i32: -+ case INDEX_op_ext16u_i64: -+ tcg_out_ext16u(s, a0, a1); -+ break; -+ -+ case INDEX_op_ext32u_i64: -+ case INDEX_op_extu_i32_i64: -+ tcg_out_ext32u(s, a0, a1); -+ break; -+ -+ case INDEX_op_ext32s_i64: -+ case INDEX_op_extrl_i64_i32: -+ case INDEX_op_ext_i32_i64: -+ tcg_out_ext32s(s, a0, a1); -+ break; -+ -+ case INDEX_op_extrh_i64_i32: -+ tcg_out_opc_srai_d(s, a0, a1, 32); -+ break; -+ -+ case INDEX_op_not_i32: -+ case INDEX_op_not_i64: -+ tcg_out_opc_nor(s, a0, a1, TCG_REG_ZERO); -+ break; -+ -+ case INDEX_op_nor_i32: -+ case INDEX_op_nor_i64: -+ if (c2) { -+ tcg_out_opc_ori(s, a0, a1, a2); -+ tcg_out_opc_nor(s, a0, a0, TCG_REG_ZERO); -+ } else { -+ tcg_out_opc_nor(s, a0, a1, a2); -+ } -+ break; -+ -+ case INDEX_op_andc_i32: -+ case INDEX_op_andc_i64: -+ if (c2) { -+ /* guaranteed to fit due to constraint */ -+ tcg_out_opc_andi(s, a0, a1, ~a2); -+ } else { -+ tcg_out_opc_andn(s, a0, a1, a2); -+ } -+ break; -+ -+ case INDEX_op_orc_i32: -+ case INDEX_op_orc_i64: -+ if (c2) { -+ /* guaranteed to fit due to constraint */ -+ tcg_out_opc_ori(s, a0, a1, ~a2); -+ } else { -+ tcg_out_opc_orn(s, a0, a1, a2); -+ } -+ break; -+ -+ case INDEX_op_and_i32: -+ case INDEX_op_and_i64: -+ if (c2) { -+ tcg_out_opc_andi(s, a0, a1, a2); -+ } else { -+ tcg_out_opc_and(s, a0, a1, a2); -+ } -+ break; -+ -+ case INDEX_op_or_i32: -+ case INDEX_op_or_i64: -+ if (c2) { -+ tcg_out_opc_ori(s, a0, a1, a2); -+ } else { -+ tcg_out_opc_or(s, a0, a1, a2); -+ } -+ break; -+ -+ case INDEX_op_xor_i32: -+ case INDEX_op_xor_i64: -+ if (c2) { -+ tcg_out_opc_xori(s, a0, a1, a2); -+ } else { -+ tcg_out_opc_xor(s, a0, a1, a2); -+ } -+ break; -+ -+ case INDEX_op_extract_i32: -+ tcg_out_opc_bstrpick_w(s, a0, a1, a2, a2 + args[3] - 1); -+ break; -+ case INDEX_op_extract_i64: -+ tcg_out_opc_bstrpick_d(s, a0, a1, a2, a2 + args[3] - 1); -+ break; -+ -+ case INDEX_op_deposit_i32: -+ tcg_out_opc_bstrins_w(s, a0, a2, args[3], args[3] + args[4] - 1); -+ break; -+ case INDEX_op_deposit_i64: -+ tcg_out_opc_bstrins_d(s, a0, a2, args[3], args[3] + args[4] - 1); -+ break; -+ -+ case INDEX_op_bswap16_i32: -+ case INDEX_op_bswap16_i64: -+ tcg_out_opc_revb_2h(s, a0, a1); -+ if (a2 & TCG_BSWAP_OS) { -+ tcg_out_ext16s(s, a0, a0); -+ } else if ((a2 & (TCG_BSWAP_IZ | TCG_BSWAP_OZ)) == TCG_BSWAP_OZ) { -+ tcg_out_ext16u(s, a0, a0); -+ } -+ break; -+ -+ case INDEX_op_bswap32_i32: -+ /* All 32-bit values are computed sign-extended in the register. */ -+ a2 = TCG_BSWAP_OS; -+ /* fallthrough */ -+ case INDEX_op_bswap32_i64: -+ tcg_out_opc_revb_2w(s, a0, a1); -+ if (a2 & TCG_BSWAP_OS) { -+ tcg_out_ext32s(s, a0, a0); -+ } else if ((a2 & (TCG_BSWAP_IZ | TCG_BSWAP_OZ)) == TCG_BSWAP_OZ) { -+ tcg_out_ext32u(s, a0, a0); -+ } -+ break; -+ -+ case INDEX_op_bswap64_i64: -+ tcg_out_opc_revb_d(s, a0, a1); -+ break; -+ -+ case INDEX_op_clz_i32: -+ tcg_out_clzctz(s, OPC_CLZ_W, a0, a1, a2, c2, true); -+ break; -+ case INDEX_op_clz_i64: -+ tcg_out_clzctz(s, OPC_CLZ_D, a0, a1, a2, c2, false); -+ break; -+ -+ case INDEX_op_ctz_i32: -+ tcg_out_clzctz(s, OPC_CTZ_W, a0, a1, a2, c2, true); -+ break; -+ case INDEX_op_ctz_i64: -+ tcg_out_clzctz(s, OPC_CTZ_D, a0, a1, a2, c2, false); -+ break; -+ -+ case INDEX_op_shl_i32: -+ if (c2) { -+ tcg_out_opc_slli_w(s, a0, a1, a2 & 0x1f); -+ } else { -+ tcg_out_opc_sll_w(s, a0, a1, a2); -+ } -+ break; -+ case INDEX_op_shl_i64: -+ if (c2) { -+ tcg_out_opc_slli_d(s, a0, a1, a2 & 0x3f); -+ } else { -+ tcg_out_opc_sll_d(s, a0, a1, a2); -+ } -+ break; -+ -+ case INDEX_op_shr_i32: -+ if (c2) { -+ tcg_out_opc_srli_w(s, a0, a1, a2 & 0x1f); -+ } else { -+ tcg_out_opc_srl_w(s, a0, a1, a2); -+ } -+ break; -+ case INDEX_op_shr_i64: -+ if (c2) { -+ tcg_out_opc_srli_d(s, a0, a1, a2 & 0x3f); -+ } else { -+ tcg_out_opc_srl_d(s, a0, a1, a2); -+ } -+ break; -+ -+ case INDEX_op_sar_i32: -+ if (c2) { -+ tcg_out_opc_srai_w(s, a0, a1, a2 & 0x1f); -+ } else { -+ tcg_out_opc_sra_w(s, a0, a1, a2); -+ } -+ break; -+ case INDEX_op_sar_i64: -+ if (c2) { -+ tcg_out_opc_srai_d(s, a0, a1, a2 & 0x3f); -+ } else { -+ tcg_out_opc_sra_d(s, a0, a1, a2); -+ } -+ break; -+ -+ case INDEX_op_rotl_i32: -+ /* transform into equivalent rotr/rotri */ -+ if (c2) { -+ tcg_out_opc_rotri_w(s, a0, a1, (32 - a2) & 0x1f); -+ } else { -+ tcg_out_opc_sub_w(s, TCG_REG_TMP0, TCG_REG_ZERO, a2); -+ tcg_out_opc_rotr_w(s, a0, a1, TCG_REG_TMP0); -+ } -+ break; -+ case INDEX_op_rotl_i64: -+ /* transform into equivalent rotr/rotri */ -+ if (c2) { -+ tcg_out_opc_rotri_d(s, a0, a1, (64 - a2) & 0x3f); -+ } else { -+ tcg_out_opc_sub_w(s, TCG_REG_TMP0, TCG_REG_ZERO, a2); -+ tcg_out_opc_rotr_d(s, a0, a1, TCG_REG_TMP0); -+ } -+ break; -+ -+ case INDEX_op_rotr_i32: -+ if (c2) { -+ tcg_out_opc_rotri_w(s, a0, a1, a2 & 0x1f); -+ } else { -+ tcg_out_opc_rotr_w(s, a0, a1, a2); -+ } -+ break; -+ case INDEX_op_rotr_i64: -+ if (c2) { -+ tcg_out_opc_rotri_d(s, a0, a1, a2 & 0x3f); -+ } else { -+ tcg_out_opc_rotr_d(s, a0, a1, a2); -+ } -+ break; -+ -+ case INDEX_op_add_i32: -+ if (c2) { -+ tcg_out_opc_addi_w(s, a0, a1, a2); -+ } else { -+ tcg_out_opc_add_w(s, a0, a1, a2); -+ } -+ break; -+ case INDEX_op_add_i64: -+ if (c2) { -+ tcg_out_opc_addi_d(s, a0, a1, a2); -+ } else { -+ tcg_out_opc_add_d(s, a0, a1, a2); -+ } -+ break; -+ -+ case INDEX_op_sub_i32: -+ if (c2) { -+ tcg_out_opc_addi_w(s, a0, a1, -a2); -+ } else { -+ tcg_out_opc_sub_w(s, a0, a1, a2); -+ } -+ break; -+ case INDEX_op_sub_i64: -+ if (c2) { -+ tcg_out_opc_addi_d(s, a0, a1, -a2); -+ } else { -+ tcg_out_opc_sub_d(s, a0, a1, a2); -+ } -+ break; -+ -+ case INDEX_op_mul_i32: -+ tcg_out_opc_mul_w(s, a0, a1, a2); -+ break; -+ case INDEX_op_mul_i64: -+ tcg_out_opc_mul_d(s, a0, a1, a2); -+ break; -+ -+ case INDEX_op_mulsh_i32: -+ tcg_out_opc_mulh_w(s, a0, a1, a2); -+ break; -+ case INDEX_op_mulsh_i64: -+ tcg_out_opc_mulh_d(s, a0, a1, a2); -+ break; -+ -+ case INDEX_op_muluh_i32: -+ tcg_out_opc_mulh_wu(s, a0, a1, a2); -+ break; -+ case INDEX_op_muluh_i64: -+ tcg_out_opc_mulh_du(s, a0, a1, a2); -+ break; -+ -+ case INDEX_op_div_i32: -+ tcg_out_opc_div_w(s, a0, a1, a2); -+ break; -+ case INDEX_op_div_i64: -+ tcg_out_opc_div_d(s, a0, a1, a2); -+ break; -+ -+ case INDEX_op_divu_i32: -+ tcg_out_opc_div_wu(s, a0, a1, a2); -+ break; -+ case INDEX_op_divu_i64: -+ tcg_out_opc_div_du(s, a0, a1, a2); -+ break; -+ -+ case INDEX_op_rem_i32: -+ tcg_out_opc_mod_w(s, a0, a1, a2); -+ break; -+ case INDEX_op_rem_i64: -+ tcg_out_opc_mod_d(s, a0, a1, a2); -+ break; -+ -+ case INDEX_op_remu_i32: -+ tcg_out_opc_mod_wu(s, a0, a1, a2); -+ break; -+ case INDEX_op_remu_i64: -+ tcg_out_opc_mod_du(s, a0, a1, a2); -+ break; -+ -+ case INDEX_op_setcond_i32: -+ case INDEX_op_setcond_i64: -+ tcg_out_setcond(s, args[3], a0, a1, a2, c2); -+ break; -+ -+ case INDEX_op_ld8s_i32: -+ case INDEX_op_ld8s_i64: -+ tcg_out_ldst(s, OPC_LD_B, a0, a1, a2); -+ break; -+ case INDEX_op_ld8u_i32: -+ case INDEX_op_ld8u_i64: -+ tcg_out_ldst(s, OPC_LD_BU, a0, a1, a2); -+ break; -+ case INDEX_op_ld16s_i32: -+ case INDEX_op_ld16s_i64: -+ tcg_out_ldst(s, OPC_LD_H, a0, a1, a2); -+ break; -+ case INDEX_op_ld16u_i32: -+ case INDEX_op_ld16u_i64: -+ tcg_out_ldst(s, OPC_LD_HU, a0, a1, a2); -+ break; -+ case INDEX_op_ld_i32: -+ case INDEX_op_ld32s_i64: -+ tcg_out_ldst(s, OPC_LD_W, a0, a1, a2); -+ break; -+ case INDEX_op_ld32u_i64: -+ tcg_out_ldst(s, OPC_LD_WU, a0, a1, a2); -+ break; -+ case INDEX_op_ld_i64: -+ tcg_out_ldst(s, OPC_LD_D, a0, a1, a2); -+ break; -+ -+ case INDEX_op_st8_i32: -+ case INDEX_op_st8_i64: -+ tcg_out_ldst(s, OPC_ST_B, a0, a1, a2); -+ break; -+ case INDEX_op_st16_i32: -+ case INDEX_op_st16_i64: -+ tcg_out_ldst(s, OPC_ST_H, a0, a1, a2); -+ break; -+ case INDEX_op_st_i32: -+ case INDEX_op_st32_i64: -+ tcg_out_ldst(s, OPC_ST_W, a0, a1, a2); -+ break; -+ case INDEX_op_st_i64: -+ tcg_out_ldst(s, OPC_ST_D, a0, a1, a2); -+ break; -+ -+ case INDEX_op_qemu_ld_i32: -+ tcg_out_qemu_ld(s, args, TCG_TYPE_I32); -+ break; -+ case INDEX_op_qemu_ld_i64: -+ tcg_out_qemu_ld(s, args, TCG_TYPE_I64); -+ break; -+ case INDEX_op_qemu_st_i32: -+ tcg_out_qemu_st(s, args); -+ break; -+ case INDEX_op_qemu_st_i64: -+ tcg_out_qemu_st(s, args); -+ break; -+ -+ case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */ -+ case INDEX_op_mov_i64: -+ case INDEX_op_call: /* Always emitted via tcg_out_call. */ -+ default: -+ g_assert_not_reached(); -+ } -+} -+ -+static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) -+{ -+ switch (op) { -+ case INDEX_op_goto_ptr: -+ return C_O0_I1(r); -+ -+ case INDEX_op_st8_i32: -+ case INDEX_op_st8_i64: -+ case INDEX_op_st16_i32: -+ case INDEX_op_st16_i64: -+ case INDEX_op_st32_i64: -+ case INDEX_op_st_i32: -+ case INDEX_op_st_i64: -+ return C_O0_I2(rZ, r); -+ -+ case INDEX_op_brcond_i32: -+ case INDEX_op_brcond_i64: -+ return C_O0_I2(rZ, rZ); -+ -+ case INDEX_op_qemu_st_i32: -+ case INDEX_op_qemu_st_i64: -+ return C_O0_I2(LZ, L); -+ -+ case INDEX_op_ext8s_i32: -+ case INDEX_op_ext8s_i64: -+ case INDEX_op_ext8u_i32: -+ case INDEX_op_ext8u_i64: -+ case INDEX_op_ext16s_i32: -+ case INDEX_op_ext16s_i64: -+ case INDEX_op_ext16u_i32: -+ case INDEX_op_ext16u_i64: -+ case INDEX_op_ext32s_i64: -+ case INDEX_op_ext32u_i64: -+ case INDEX_op_extu_i32_i64: -+ case INDEX_op_extrl_i64_i32: -+ case INDEX_op_extrh_i64_i32: -+ case INDEX_op_ext_i32_i64: -+ case INDEX_op_not_i32: -+ case INDEX_op_not_i64: -+ case INDEX_op_extract_i32: -+ case INDEX_op_extract_i64: -+ case INDEX_op_bswap16_i32: -+ case INDEX_op_bswap16_i64: -+ case INDEX_op_bswap32_i32: -+ case INDEX_op_bswap32_i64: -+ case INDEX_op_bswap64_i64: -+ case INDEX_op_ld8s_i32: -+ case INDEX_op_ld8s_i64: -+ case INDEX_op_ld8u_i32: -+ case INDEX_op_ld8u_i64: -+ case INDEX_op_ld16s_i32: -+ case INDEX_op_ld16s_i64: -+ case INDEX_op_ld16u_i32: -+ case INDEX_op_ld16u_i64: -+ case INDEX_op_ld32s_i64: -+ case INDEX_op_ld32u_i64: -+ case INDEX_op_ld_i32: -+ case INDEX_op_ld_i64: -+ return C_O1_I1(r, r); -+ -+ case INDEX_op_qemu_ld_i32: -+ case INDEX_op_qemu_ld_i64: -+ return C_O1_I1(r, L); -+ -+ case INDEX_op_andc_i32: -+ case INDEX_op_andc_i64: -+ case INDEX_op_orc_i32: -+ case INDEX_op_orc_i64: -+ /* -+ * LoongArch insns for these ops don't have reg-imm forms, but we -+ * can express using andi/ori if ~constant satisfies -+ * TCG_CT_CONST_U12. -+ */ -+ return C_O1_I2(r, r, rC); -+ -+ case INDEX_op_shl_i32: -+ case INDEX_op_shl_i64: -+ case INDEX_op_shr_i32: -+ case INDEX_op_shr_i64: -+ case INDEX_op_sar_i32: -+ case INDEX_op_sar_i64: -+ case INDEX_op_rotl_i32: -+ case INDEX_op_rotl_i64: -+ case INDEX_op_rotr_i32: -+ case INDEX_op_rotr_i64: -+ return C_O1_I2(r, r, ri); -+ -+ case INDEX_op_add_i32: -+ case INDEX_op_add_i64: -+ return C_O1_I2(r, r, rI); -+ -+ case INDEX_op_and_i32: -+ case INDEX_op_and_i64: -+ case INDEX_op_nor_i32: -+ case INDEX_op_nor_i64: -+ case INDEX_op_or_i32: -+ case INDEX_op_or_i64: -+ case INDEX_op_xor_i32: -+ case INDEX_op_xor_i64: -+ /* LoongArch reg-imm bitops have their imms ZERO-extended */ -+ return C_O1_I2(r, r, rU); -+ -+ case INDEX_op_clz_i32: -+ case INDEX_op_clz_i64: -+ case INDEX_op_ctz_i32: -+ case INDEX_op_ctz_i64: -+ return C_O1_I2(r, r, rW); -+ -+ case INDEX_op_setcond_i32: -+ case INDEX_op_setcond_i64: -+ return C_O1_I2(r, r, rZ); -+ -+ case INDEX_op_deposit_i32: -+ case INDEX_op_deposit_i64: -+ /* Must deposit into the same register as input */ -+ return C_O1_I2(r, 0, rZ); -+ -+ case INDEX_op_sub_i32: -+ case INDEX_op_sub_i64: -+ return C_O1_I2(r, rZ, rN); -+ -+ case INDEX_op_mul_i32: -+ case INDEX_op_mul_i64: -+ case INDEX_op_mulsh_i32: -+ case INDEX_op_mulsh_i64: -+ case INDEX_op_muluh_i32: -+ case INDEX_op_muluh_i64: -+ case INDEX_op_div_i32: -+ case INDEX_op_div_i64: -+ case INDEX_op_divu_i32: -+ case INDEX_op_divu_i64: -+ case INDEX_op_rem_i32: -+ case INDEX_op_rem_i64: -+ case INDEX_op_remu_i32: -+ case INDEX_op_remu_i64: -+ return C_O1_I2(r, rZ, rZ); -+ -+ default: -+ g_assert_not_reached(); -+ } -+} -+ -+static const int tcg_target_callee_save_regs[] = { -+ TCG_REG_S0, /* used for the global env (TCG_AREG0) */ -+ TCG_REG_S1, -+ TCG_REG_S2, -+ TCG_REG_S3, -+ TCG_REG_S4, -+ TCG_REG_S5, -+ TCG_REG_S6, -+ TCG_REG_S7, -+ TCG_REG_S8, -+ TCG_REG_S9, -+ TCG_REG_RA, /* should be last for ABI compliance */ -+}; -+ -+/* Stack frame parameters. */ -+#define REG_SIZE (TCG_TARGET_REG_BITS / 8) -+#define SAVE_SIZE ((int)ARRAY_SIZE(tcg_target_callee_save_regs) * REG_SIZE) -+#define TEMP_SIZE (CPU_TEMP_BUF_NLONGS * (int)sizeof(long)) -+#define FRAME_SIZE ((TCG_STATIC_CALL_ARGS_SIZE + TEMP_SIZE + SAVE_SIZE \ -+ + TCG_TARGET_STACK_ALIGN - 1) \ -+ & -TCG_TARGET_STACK_ALIGN) -+#define SAVE_OFS (TCG_STATIC_CALL_ARGS_SIZE + TEMP_SIZE) -+ -+/* We're expecting to be able to use an immediate for frame allocation. */ -+QEMU_BUILD_BUG_ON(FRAME_SIZE > 0x7ff); -+ -+/* Generate global QEMU prologue and epilogue code */ -+static void tcg_target_qemu_prologue(TCGContext *s) -+{ -+ int i; -+ -+ tcg_set_frame(s, TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE, TEMP_SIZE); -+ -+ /* TB prologue */ -+ tcg_out_opc_addi_d(s, TCG_REG_SP, TCG_REG_SP, -FRAME_SIZE); -+ for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) { -+ tcg_out_st(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i], -+ TCG_REG_SP, SAVE_OFS + i * REG_SIZE); -+ } -+ -+#if !defined(CONFIG_SOFTMMU) -+ if (USE_GUEST_BASE) { -+ tcg_out_movi(s, TCG_TYPE_PTR, TCG_GUEST_BASE_REG, guest_base); -+ tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG); -+ } -+#endif -+ -+ /* Call generated code */ -+ tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]); -+ tcg_out_opc_jirl(s, TCG_REG_ZERO, tcg_target_call_iarg_regs[1], 0); -+ -+ /* Return path for goto_ptr. Set return value to 0 */ -+ tcg_code_gen_epilogue = tcg_splitwx_to_rx(s->code_ptr); -+ tcg_out_mov(s, TCG_TYPE_REG, TCG_REG_A0, TCG_REG_ZERO); -+ -+ /* TB epilogue */ -+ tb_ret_addr = tcg_splitwx_to_rx(s->code_ptr); -+ for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) { -+ tcg_out_ld(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i], -+ TCG_REG_SP, SAVE_OFS + i * REG_SIZE); -+ } -+ -+ tcg_out_opc_addi_d(s, TCG_REG_SP, TCG_REG_SP, FRAME_SIZE); -+ tcg_out_opc_jirl(s, TCG_REG_ZERO, TCG_REG_RA, 0); -+} -+ -+static void tcg_target_init(TCGContext *s) -+{ -+ tcg_target_available_regs[TCG_TYPE_I32] = ALL_GENERAL_REGS; -+ tcg_target_available_regs[TCG_TYPE_I64] = ALL_GENERAL_REGS; -+ -+ tcg_target_call_clobber_regs = ALL_GENERAL_REGS; -+ tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S0); -+ tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S1); -+ tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S2); -+ tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S3); -+ tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S4); -+ tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S5); -+ tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S6); -+ tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S7); -+ tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S8); -+ tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S9); -+ -+ s->reserved_regs = 0; -+ tcg_regset_set_reg(s->reserved_regs, TCG_REG_ZERO); -+ tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP0); -+ tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP1); -+ tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP2); -+ tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP); -+ tcg_regset_set_reg(s->reserved_regs, TCG_REG_TP); -+ tcg_regset_set_reg(s->reserved_regs, TCG_REG_RESERVED); -+} -+ -+typedef struct { -+ DebugFrameHeader h; -+ uint8_t fde_def_cfa[4]; -+ uint8_t fde_reg_ofs[ARRAY_SIZE(tcg_target_callee_save_regs) * 2]; -+} DebugFrame; -+ -+#define ELF_HOST_MACHINE EM_LOONGARCH -+ -+static const DebugFrame debug_frame = { -+ .h.cie.len = sizeof(DebugFrameCIE) - 4, /* length after .len member */ -+ .h.cie.id = -1, -+ .h.cie.version = 1, -+ .h.cie.code_align = 1, -+ .h.cie.data_align = -(TCG_TARGET_REG_BITS / 8) & 0x7f, /* sleb128 */ -+ .h.cie.return_column = TCG_REG_RA, -+ -+ /* Total FDE size does not include the "len" member. */ -+ .h.fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, h.fde.cie_offset), -+ -+ .fde_def_cfa = { -+ 12, TCG_REG_SP, /* DW_CFA_def_cfa sp, ... */ -+ (FRAME_SIZE & 0x7f) | 0x80, /* ... uleb128 FRAME_SIZE */ -+ (FRAME_SIZE >> 7) -+ }, -+ .fde_reg_ofs = { -+ 0x80 + 23, 11, /* DW_CFA_offset, s0, -88 */ -+ 0x80 + 24, 10, /* DW_CFA_offset, s1, -80 */ -+ 0x80 + 25, 9, /* DW_CFA_offset, s2, -72 */ -+ 0x80 + 26, 8, /* DW_CFA_offset, s3, -64 */ -+ 0x80 + 27, 7, /* DW_CFA_offset, s4, -56 */ -+ 0x80 + 28, 6, /* DW_CFA_offset, s5, -48 */ -+ 0x80 + 29, 5, /* DW_CFA_offset, s6, -40 */ -+ 0x80 + 30, 4, /* DW_CFA_offset, s7, -32 */ -+ 0x80 + 31, 3, /* DW_CFA_offset, s8, -24 */ -+ 0x80 + 22, 2, /* DW_CFA_offset, s9, -16 */ -+ 0x80 + 1 , 1, /* DW_CFA_offset, ra, -8 */ -+ } -+}; -+ -+void tcg_register_jit(const void *buf, size_t buf_size) -+{ -+ tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame)); -+} -diff --git a/tcg/loongarch64/tcg-target.h b/tcg/loongarch64/tcg-target.h -new file mode 100644 -index 0000000000..d58a6162f2 ---- /dev/null -+++ b/tcg/loongarch64/tcg-target.h -@@ -0,0 +1,178 @@ -+/* -+ * Tiny Code Generator for QEMU -+ * -+ * Copyright (c) 2021 WANG Xuerui -+ * -+ * Based on tcg/riscv/tcg-target.h -+ * -+ * Copyright (c) 2018 SiFive, Inc -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a copy -+ * of this software and associated documentation files (the "Software"), to deal -+ * in the Software without restriction, including without limitation the rights -+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -+ * copies of the Software, and to permit persons to whom the Software is -+ * furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -+ * THE SOFTWARE. -+ */ -+ -+#ifndef LOONGARCH_TCG_TARGET_H -+#define LOONGARCH_TCG_TARGET_H -+ -+/* -+ * Loongson removed the (incomplete) 32-bit support from kernel and toolchain -+ * for the initial upstreaming of this architecture, so don't bother and just -+ * support the LP64* ABI for now. -+ */ -+#if defined(__loongarch64) -+# define TCG_TARGET_REG_BITS 64 -+#else -+# error unsupported LoongArch register size -+#endif -+ -+#define TCG_TARGET_INSN_UNIT_SIZE 4 -+#define TCG_TARGET_NB_REGS 32 -+#define MAX_CODE_GEN_BUFFER_SIZE SIZE_MAX -+ -+typedef enum { -+ TCG_REG_ZERO, -+ TCG_REG_RA, -+ TCG_REG_TP, -+ TCG_REG_SP, -+ TCG_REG_A0, -+ TCG_REG_A1, -+ TCG_REG_A2, -+ TCG_REG_A3, -+ TCG_REG_A4, -+ TCG_REG_A5, -+ TCG_REG_A6, -+ TCG_REG_A7, -+ TCG_REG_T0, -+ TCG_REG_T1, -+ TCG_REG_T2, -+ TCG_REG_T3, -+ TCG_REG_T4, -+ TCG_REG_T5, -+ TCG_REG_T6, -+ TCG_REG_T7, -+ TCG_REG_T8, -+ TCG_REG_RESERVED, -+ TCG_REG_S9, -+ TCG_REG_S0, -+ TCG_REG_S1, -+ TCG_REG_S2, -+ TCG_REG_S3, -+ TCG_REG_S4, -+ TCG_REG_S5, -+ TCG_REG_S6, -+ TCG_REG_S7, -+ TCG_REG_S8, -+ -+ /* aliases */ -+ TCG_AREG0 = TCG_REG_S0, -+ TCG_REG_TMP0 = TCG_REG_T8, -+ TCG_REG_TMP1 = TCG_REG_T7, -+ TCG_REG_TMP2 = TCG_REG_T6, -+} TCGReg; -+ -+/* used for function call generation */ -+#define TCG_REG_CALL_STACK TCG_REG_SP -+#define TCG_TARGET_STACK_ALIGN 16 -+#define TCG_TARGET_CALL_ALIGN_ARGS 1 -+#define TCG_TARGET_CALL_STACK_OFFSET 0 -+ -+/* optional instructions */ -+#define TCG_TARGET_HAS_movcond_i32 0 -+#define TCG_TARGET_HAS_div_i32 1 -+#define TCG_TARGET_HAS_rem_i32 1 -+#define TCG_TARGET_HAS_div2_i32 0 -+#define TCG_TARGET_HAS_rot_i32 1 -+#define TCG_TARGET_HAS_deposit_i32 1 -+#define TCG_TARGET_HAS_extract_i32 1 -+#define TCG_TARGET_HAS_sextract_i32 0 -+#define TCG_TARGET_HAS_extract2_i32 0 -+#define TCG_TARGET_HAS_add2_i32 0 -+#define TCG_TARGET_HAS_sub2_i32 0 -+#define TCG_TARGET_HAS_mulu2_i32 0 -+#define TCG_TARGET_HAS_muls2_i32 0 -+#define TCG_TARGET_HAS_muluh_i32 1 -+#define TCG_TARGET_HAS_mulsh_i32 1 -+#define TCG_TARGET_HAS_ext8s_i32 1 -+#define TCG_TARGET_HAS_ext16s_i32 1 -+#define TCG_TARGET_HAS_ext8u_i32 1 -+#define TCG_TARGET_HAS_ext16u_i32 1 -+#define TCG_TARGET_HAS_bswap16_i32 1 -+#define TCG_TARGET_HAS_bswap32_i32 1 -+#define TCG_TARGET_HAS_not_i32 1 -+#define TCG_TARGET_HAS_neg_i32 0 -+#define TCG_TARGET_HAS_andc_i32 1 -+#define TCG_TARGET_HAS_orc_i32 1 -+#define TCG_TARGET_HAS_eqv_i32 0 -+#define TCG_TARGET_HAS_nand_i32 0 -+#define TCG_TARGET_HAS_nor_i32 1 -+#define TCG_TARGET_HAS_clz_i32 1 -+#define TCG_TARGET_HAS_ctz_i32 1 -+#define TCG_TARGET_HAS_ctpop_i32 0 -+#define TCG_TARGET_HAS_direct_jump 0 -+#define TCG_TARGET_HAS_brcond2 0 -+#define TCG_TARGET_HAS_setcond2 0 -+#define TCG_TARGET_HAS_qemu_st8_i32 0 -+ -+/* 64-bit operations */ -+#define TCG_TARGET_HAS_movcond_i64 0 -+#define TCG_TARGET_HAS_div_i64 1 -+#define TCG_TARGET_HAS_rem_i64 1 -+#define TCG_TARGET_HAS_div2_i64 0 -+#define TCG_TARGET_HAS_rot_i64 1 -+#define TCG_TARGET_HAS_deposit_i64 1 -+#define TCG_TARGET_HAS_extract_i64 1 -+#define TCG_TARGET_HAS_sextract_i64 0 -+#define TCG_TARGET_HAS_extract2_i64 0 -+#define TCG_TARGET_HAS_extrl_i64_i32 1 -+#define TCG_TARGET_HAS_extrh_i64_i32 1 -+#define TCG_TARGET_HAS_ext8s_i64 1 -+#define TCG_TARGET_HAS_ext16s_i64 1 -+#define TCG_TARGET_HAS_ext32s_i64 1 -+#define TCG_TARGET_HAS_ext8u_i64 1 -+#define TCG_TARGET_HAS_ext16u_i64 1 -+#define TCG_TARGET_HAS_ext32u_i64 1 -+#define TCG_TARGET_HAS_bswap16_i64 1 -+#define TCG_TARGET_HAS_bswap32_i64 1 -+#define TCG_TARGET_HAS_bswap64_i64 1 -+#define TCG_TARGET_HAS_not_i64 1 -+#define TCG_TARGET_HAS_neg_i64 0 -+#define TCG_TARGET_HAS_andc_i64 1 -+#define TCG_TARGET_HAS_orc_i64 1 -+#define TCG_TARGET_HAS_eqv_i64 0 -+#define TCG_TARGET_HAS_nand_i64 0 -+#define TCG_TARGET_HAS_nor_i64 1 -+#define TCG_TARGET_HAS_clz_i64 1 -+#define TCG_TARGET_HAS_ctz_i64 1 -+#define TCG_TARGET_HAS_ctpop_i64 0 -+#define TCG_TARGET_HAS_add2_i64 0 -+#define TCG_TARGET_HAS_sub2_i64 0 -+#define TCG_TARGET_HAS_mulu2_i64 0 -+#define TCG_TARGET_HAS_muls2_i64 0 -+#define TCG_TARGET_HAS_muluh_i64 1 -+#define TCG_TARGET_HAS_mulsh_i64 1 -+ -+/* not defined -- call should be eliminated at compile time */ -+void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t, uintptr_t); -+ -+#define TCG_TARGET_DEFAULT_MO (0) -+ -+#define TCG_TARGET_NEED_LDST_LABELS -+ -+#define TCG_TARGET_HAS_MEMORY_BSWAP 0 -+ -+#endif /* LOONGARCH_TCG_TARGET_H */ --- -2.27.0 - diff --git a/kvm-Add-dirty-sync-missed-zero-copy-migration-stat.patch b/kvm-Add-dirty-sync-missed-zero-copy-migration-stat.patch index fb67d64..ad2b261 100644 --- a/kvm-Add-dirty-sync-missed-zero-copy-migration-stat.patch +++ b/kvm-Add-dirty-sync-missed-zero-copy-migration-stat.patch @@ -1,18 +1,18 @@ -From aba4d52b3c06aaf5a7553db6dadcb02645e153f1 Mon Sep 17 00:00:00 2001 +From cd49a32e9c9e33efc51652b68180a07683814b4d Mon Sep 17 00:00:00 2001 From: Leonardo Bras Date: Mon, 11 Jul 2022 18:11:12 -0300 -Subject: [PATCH 30/34] Add dirty-sync-missed-zero-copy migration stat +Subject: [PATCH 4/9] Add dirty-sync-missed-zero-copy migration stat MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RH-Author: Leonardo Brás -RH-MergeRequest: 185: MSG_ZEROCOPY + Multifd @ rhel8.6 -RH-Commit: [30/34] 95d0255ea03cb7c986dc64645e95e10a5fbe0f9a -RH-Bugzilla: 2117252 -RH-Acked-by: quintela1 +RH-MergeRequest: 201: Zero-copy-send fixes + improvements +RH-Commit: [4/8] 56cce61cf95aafc8dafae7531b43c166084abfec +RH-Bugzilla: 2110203 RH-Acked-by: Dr. David Alan Gilbert RH-Acked-by: Peter Xu +RH-Acked-by: Miroslav Rezanina Signed-off-by: Leonardo Bras Acked-by: Markus Armbruster @@ -29,10 +29,10 @@ Signed-off-by: Leonardo Bras 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/migration/migration.c b/migration/migration.c -index 87b4a6c3f9..a3e0ac954c 100644 +index e100b30f00..952a26c5c2 100644 --- a/migration/migration.c +++ b/migration/migration.c -@@ -1006,6 +1006,8 @@ static void populate_ram_info(MigrationInfo *info, MigrationState *s) +@@ -1012,6 +1012,8 @@ static void populate_ram_info(MigrationInfo *info, MigrationState *s) info->ram->normal_bytes = ram_counters.normal * page_size; info->ram->mbps = s->mbps; info->ram->dirty_sync_count = ram_counters.dirty_sync_count; @@ -83,5 +83,5 @@ index c8ec260ab0..94bc5c69db 100644 ## # @XBZRLECacheStats: -- -2.35.3 +2.31.1 diff --git a/kvm-KVM-x86-workaround-invalid-CPUID-0xD-9-info-on-some-.patch b/kvm-KVM-x86-workaround-invalid-CPUID-0xD-9-info-on-some-.patch new file mode 100644 index 0000000..1a0beb2 --- /dev/null +++ b/kvm-KVM-x86-workaround-invalid-CPUID-0xD-9-info-on-some-.patch @@ -0,0 +1,109 @@ +From ea5299b5dde7d0b6b2f93cb646e6a24c9f105466 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Wed, 23 Mar 2022 12:33:25 +0100 +Subject: [PATCH 13/24] KVM: x86: workaround invalid CPUID[0xD,9] info on some + AMD processors +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Paul Lai +RH-MergeRequest: 176: Enable KVM AMX support +RH-Commit: [13/13] 38f147c911258e84e01336271ebd23a1c24371fc +RH-Bugzilla: 1916415 +RH-Acked-by: Cornelia Huck +RH-Acked-by: Igor Mammedov +RH-Acked-by: Paolo Bonzini + +Some AMD processors expose the PKRU extended save state even if they do not have +the related PKU feature in CPUID. Worse, when they do they report a size of +64, whereas the expected size of the PKRU extended save state is 8, therefore +the esa->size == eax assertion does not hold. + +The state is already ignored by KVM_GET_SUPPORTED_CPUID because it +was not enabled in the host XCR0. However, QEMU kvm_cpu_xsave_init() +runs before QEMU invokes arch_prctl() to enable dynamically-enabled +save states such as XTILEDATA, and KVM_GET_SUPPORTED_CPUID hides save +states that have yet to be enabled. Therefore, kvm_cpu_xsave_init() +needs to consult the host CPUID instead of KVM_GET_SUPPORTED_CPUID, +and dies with an assertion failure. + +When setting up the ExtSaveArea array to match the host, ignore features that +KVM does not report as supported. This will cause QEMU to skip the incorrect +CPUID leaf instead of tripping the assertion. + +Closes: https://gitlab.com/qemu-project/qemu/-/issues/916 +Reported-by: Daniel P. Berrangé +Analyzed-by: Yang Zhong +Reported-by: Peter Krempa +Tested-by: Daniel P. Berrangé +Signed-off-by: Paolo Bonzini +(cherry picked from commit 58f7db26f21c690cf9a669c314cfd7371506084a) +Signed-off-by: Paul Lai +--- + target/i386/cpu.c | 4 ++-- + target/i386/cpu.h | 2 ++ + target/i386/kvm/kvm-cpu.c | 19 ++++++++++++------- + 3 files changed, 16 insertions(+), 9 deletions(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 09e08f7f38..0543b846ff 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -4980,8 +4980,8 @@ CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp) + return cpu_list; + } + +-static uint64_t x86_cpu_get_supported_feature_word(FeatureWord w, +- bool migratable_only) ++uint64_t x86_cpu_get_supported_feature_word(FeatureWord w, ++ bool migratable_only) + { + FeatureWordInfo *wi = &feature_word_info[w]; + uint64_t r = 0; +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index 8ab2a4042a..006b735fe4 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -604,6 +604,8 @@ typedef enum FeatureWord { + } FeatureWord; + + typedef uint64_t FeatureWordArray[FEATURE_WORDS]; ++uint64_t x86_cpu_get_supported_feature_word(FeatureWord w, ++ bool migratable_only); + + /* cpuid_features bits */ + #define CPUID_FP87 (1U << 0) +diff --git a/target/i386/kvm/kvm-cpu.c b/target/i386/kvm/kvm-cpu.c +index bdc967c484..74c1396a93 100644 +--- a/target/i386/kvm/kvm-cpu.c ++++ b/target/i386/kvm/kvm-cpu.c +@@ -99,13 +99,18 @@ static void kvm_cpu_xsave_init(void) + for (i = XSTATE_SSE_BIT + 1; i < XSAVE_STATE_AREA_COUNT; i++) { + ExtSaveArea *esa = &x86_ext_save_areas[i]; + +- if (esa->size) { +- host_cpuid(0xd, i, &eax, &ebx, &ecx, &edx); +- if (eax != 0) { +- assert(esa->size == eax); +- esa->offset = ebx; +- esa->ecx = ecx; +- } ++ if (!esa->size) { ++ continue; ++ } ++ if ((x86_cpu_get_supported_feature_word(esa->feature, false) & esa->bits) ++ != esa->bits) { ++ continue; ++ } ++ host_cpuid(0xd, i, &eax, &ebx, &ecx, &edx); ++ if (eax != 0) { ++ assert(esa->size == eax); ++ esa->offset = ebx; ++ esa->ecx = ecx; + } + } + } +-- +2.35.3 + diff --git a/kvm-QIOChannel-Add-flags-on-io_writev-and-introduce-io_f.patch b/kvm-QIOChannel-Add-flags-on-io_writev-and-introduce-io_f.patch index b0f1766..81ae532 100644 --- a/kvm-QIOChannel-Add-flags-on-io_writev-and-introduce-io_f.patch +++ b/kvm-QIOChannel-Add-flags-on-io_writev-and-introduce-io_f.patch @@ -1,19 +1,19 @@ -From dc840cee933cfc1790b7624c88052f6deb43101d Mon Sep 17 00:00:00 2001 +From 7eeec7c008e947bc3e1fed682791092b408852c6 Mon Sep 17 00:00:00 2001 From: Leonardo Bras Date: Wed, 18 May 2022 02:52:24 -0300 -Subject: [PATCH 17/34] QIOChannel: Add flags on io_writev and introduce +Subject: [PATCH 17/37] QIOChannel: Add flags on io_writev and introduce io_flush callback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RH-Author: Leonardo Brás -RH-MergeRequest: 185: MSG_ZEROCOPY + Multifd @ rhel8.6 -RH-Commit: [17/34] 8ebb6301a83816937d7b87709cf906e1a9c16b01 -RH-Bugzilla: 2117252 -RH-Acked-by: quintela1 -RH-Acked-by: Dr. David Alan Gilbert +RH-MergeRequest: 191: MSG_ZEROCOPY + Multifd @ rhel8.7 +RH-Commit: [17/26] 7bde4e79fd3f76a6cc84d9cacf50420584ddd35c +RH-Bugzilla: 2072049 RH-Acked-by: Peter Xu +RH-Acked-by: Daniel P. Berrangé +RH-Acked-by: Dr. David Alan Gilbert Add flags to io_writev and introduce io_flush as optional callback to QIOChannelClass, allowing the implementation of zero copy writes by diff --git a/kvm-QIOChannelSocket-Add-support-for-MSG_ZEROCOPY-IPV6.patch b/kvm-QIOChannelSocket-Add-support-for-MSG_ZEROCOPY-IPV6.patch index 0dd4a82..98f1ac4 100644 --- a/kvm-QIOChannelSocket-Add-support-for-MSG_ZEROCOPY-IPV6.patch +++ b/kvm-QIOChannelSocket-Add-support-for-MSG_ZEROCOPY-IPV6.patch @@ -1,18 +1,18 @@ -From f81698b323294b330a5dfb7b9eabff025596bbde Mon Sep 17 00:00:00 2001 +From a6c4aed18a027ce8e107fdf9184e9ea43a86f843 Mon Sep 17 00:00:00 2001 From: Leonardo Bras Date: Thu, 4 Aug 2022 04:10:43 -0300 -Subject: [PATCH 34/34] QIOChannelSocket: Add support for MSG_ZEROCOPY + IPV6 +Subject: [PATCH 8/9] QIOChannelSocket: Add support for MSG_ZEROCOPY + IPV6 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RH-Author: Leonardo Brás -RH-MergeRequest: 185: MSG_ZEROCOPY + Multifd @ rhel8.6 -RH-Commit: [34/34] 549d876ec7108bd11d01754bd1b893ba3e79deb9 -RH-Bugzilla: 2117252 -RH-Acked-by: quintela1 +RH-MergeRequest: 201: Zero-copy-send fixes + improvements +RH-Commit: [8/8] 6e26ee7c9ebaedb07623313cb0678816867751dd +RH-Bugzilla: 2110203 RH-Acked-by: Dr. David Alan Gilbert RH-Acked-by: Peter Xu +RH-Acked-by: Miroslav Rezanina For using MSG_ZEROCOPY, there are two steps: 1 - io_writev() the packet, which enqueues the packet for sending, and @@ -52,5 +52,5 @@ index cf0d67c51b..6010ad7017 100644 "Wrong cmsg in errqueue"); return -1; -- -2.35.3 +2.31.1 diff --git a/kvm-QIOChannelSocket-Fix-zero-copy-flush-returning-code-.patch b/kvm-QIOChannelSocket-Fix-zero-copy-flush-returning-code-.patch index 4c25590..5806062 100644 --- a/kvm-QIOChannelSocket-Fix-zero-copy-flush-returning-code-.patch +++ b/kvm-QIOChannelSocket-Fix-zero-copy-flush-returning-code-.patch @@ -1,19 +1,19 @@ -From 9995a5367d511f8597e4006841853eb9b5888065 Mon Sep 17 00:00:00 2001 +From 905cc8032fc63619efb3f0a8c9754b7190bcc43a Mon Sep 17 00:00:00 2001 From: Leonardo Bras Date: Mon, 11 Jul 2022 18:11:11 -0300 -Subject: [PATCH 29/34] QIOChannelSocket: Fix zero-copy flush returning code 1 +Subject: [PATCH 3/9] QIOChannelSocket: Fix zero-copy flush returning code 1 when nothing sent MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RH-Author: Leonardo Brás -RH-MergeRequest: 185: MSG_ZEROCOPY + Multifd @ rhel8.6 -RH-Commit: [29/34] d383ee721a8b57a4c3b70e1307cbf7db9e22d395 -RH-Bugzilla: 2117252 -RH-Acked-by: quintela1 +RH-MergeRequest: 201: Zero-copy-send fixes + improvements +RH-Commit: [3/8] 1ad707702fa26cd4d0fa1870c21f5f26ae93ff97 +RH-Bugzilla: 2110203 RH-Acked-by: Dr. David Alan Gilbert RH-Acked-by: Peter Xu +RH-Acked-by: Miroslav Rezanina If flush is called when no buffer was sent with MSG_ZEROCOPY, it currently returns 1. This return code should be used only when Linux fails to use @@ -61,5 +61,5 @@ index df858da924..cf0d67c51b 100644 received = recvmsg(sioc->fd, &msg, MSG_ERRQUEUE); if (received < 0) { -- -2.35.3 +2.31.1 diff --git a/kvm-QIOChannelSocket-Fix-zero-copy-send-so-socket-flush-.patch b/kvm-QIOChannelSocket-Fix-zero-copy-send-so-socket-flush-.patch index cab53b4..685478f 100644 --- a/kvm-QIOChannelSocket-Fix-zero-copy-send-so-socket-flush-.patch +++ b/kvm-QIOChannelSocket-Fix-zero-copy-send-so-socket-flush-.patch @@ -1,19 +1,19 @@ -From 9a4ecf0b3cfccd31a1d41716e3a4249a1d53455c Mon Sep 17 00:00:00 2001 +From c1fd32d93ae42fcf3c1a25f4d56e669f251087d8 Mon Sep 17 00:00:00 2001 From: Leonardo Bras Date: Mon, 20 Jun 2022 02:39:43 -0300 -Subject: [PATCH 25/34] QIOChannelSocket: Fix zero-copy send so socket flush +Subject: [PATCH 25/37] QIOChannelSocket: Fix zero-copy send so socket flush works MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RH-Author: Leonardo Brás -RH-MergeRequest: 185: MSG_ZEROCOPY + Multifd @ rhel8.6 -RH-Commit: [25/34] cf8dc62075bc8b9aa2621315842a2b2458e9cd82 -RH-Bugzilla: 2117252 -RH-Acked-by: quintela1 -RH-Acked-by: Dr. David Alan Gilbert +RH-MergeRequest: 191: MSG_ZEROCOPY + Multifd @ rhel8.7 +RH-Commit: [25/26] 3ede94f3269e21c3ace073ed1a6f24696315bcbb +RH-Bugzilla: 2072049 RH-Acked-by: Peter Xu +RH-Acked-by: Daniel P. Berrangé +RH-Acked-by: Dr. David Alan Gilbert Somewhere between v6 and v7 the of the zero-copy-send patchset a crucial part of the flushing mechanism got missing: incrementing zero_copy_queued. diff --git a/kvm-QIOChannelSocket-Implement-io_writev-zero-copy-flag-.patch b/kvm-QIOChannelSocket-Implement-io_writev-zero-copy-flag-.patch index a86096d..4b272ee 100644 --- a/kvm-QIOChannelSocket-Implement-io_writev-zero-copy-flag-.patch +++ b/kvm-QIOChannelSocket-Implement-io_writev-zero-copy-flag-.patch @@ -1,19 +1,19 @@ -From 118f6f61c9ca27bb112d1e39367510d2a45a72fb Mon Sep 17 00:00:00 2001 +From 5fd7af93a06adaddbae719aabbaf912159f4fb28 Mon Sep 17 00:00:00 2001 From: Leonardo Bras Date: Wed, 18 May 2022 02:52:25 -0300 -Subject: [PATCH 18/34] QIOChannelSocket: Implement io_writev zero copy flag & +Subject: [PATCH 18/37] QIOChannelSocket: Implement io_writev zero copy flag & io_flush for CONFIG_LINUX MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RH-Author: Leonardo Brás -RH-MergeRequest: 185: MSG_ZEROCOPY + Multifd @ rhel8.6 -RH-Commit: [18/34] b7f50e8485dc5e01c69b2070915592b28bdafde6 -RH-Bugzilla: 2117252 -RH-Acked-by: quintela1 -RH-Acked-by: Dr. David Alan Gilbert +RH-MergeRequest: 191: MSG_ZEROCOPY + Multifd @ rhel8.7 +RH-Commit: [18/26] 6f65c8c879a5df57213b541d58285b65178f8547 +RH-Bugzilla: 2072049 RH-Acked-by: Peter Xu +RH-Acked-by: Daniel P. Berrangé +RH-Acked-by: Dr. David Alan Gilbert For CONFIG_LINUX, implement the new zero copy flag and the optional callback io_flush on QIOChannelSocket, but enables it only when MSG_ZEROCOPY diff --git a/kvm-QIOChannelSocket-Introduce-assert-and-reduce-ifdefs-.patch b/kvm-QIOChannelSocket-Introduce-assert-and-reduce-ifdefs-.patch index a63f0ee..2575f64 100644 --- a/kvm-QIOChannelSocket-Introduce-assert-and-reduce-ifdefs-.patch +++ b/kvm-QIOChannelSocket-Introduce-assert-and-reduce-ifdefs-.patch @@ -1,19 +1,19 @@ -From f1e21f3d46e1481a5cdd2f297831742b5b2d8ecf Mon Sep 17 00:00:00 2001 +From cbfaf86331c2b2e01a2083303b7554672bf991b7 Mon Sep 17 00:00:00 2001 From: Leonardo Bras Date: Mon, 20 Jun 2022 02:39:42 -0300 -Subject: [PATCH 24/34] QIOChannelSocket: Introduce assert and reduce ifdefs to +Subject: [PATCH 24/37] QIOChannelSocket: Introduce assert and reduce ifdefs to improve readability MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RH-Author: Leonardo Brás -RH-MergeRequest: 185: MSG_ZEROCOPY + Multifd @ rhel8.6 -RH-Commit: [24/34] 0dcd79e1e89c881e56c3ef2e421910176b03d881 -RH-Bugzilla: 2117252 -RH-Acked-by: quintela1 -RH-Acked-by: Dr. David Alan Gilbert +RH-MergeRequest: 191: MSG_ZEROCOPY + Multifd @ rhel8.7 +RH-Commit: [24/26] b50e2e65307149f247155a7f7a032dc99e57718d +RH-Bugzilla: 2072049 RH-Acked-by: Peter Xu +RH-Acked-by: Daniel P. Berrangé +RH-Acked-by: Dr. David Alan Gilbert During implementation of MSG_ZEROCOPY feature, a lot of #ifdefs were introduced, particularly at qio_channel_socket_writev(). diff --git a/kvm-RHEL-disable-seqpacket-for-vhost-vsock-device-in-rhe.patch b/kvm-RHEL-disable-seqpacket-for-vhost-vsock-device-in-rhe.patch index c2df0b1..27cc557 100644 --- a/kvm-RHEL-disable-seqpacket-for-vhost-vsock-device-in-rhe.patch +++ b/kvm-RHEL-disable-seqpacket-for-vhost-vsock-device-in-rhe.patch @@ -1,20 +1,20 @@ -From fb23aa4bc1842bb78e270ee7c4fdd663e45e2317 Mon Sep 17 00:00:00 2001 +From e0e4f01c6f4fb5881960f72ae4e80951b711131e Mon Sep 17 00:00:00 2001 From: Stefano Garzarella Date: Thu, 24 Mar 2022 16:04:57 +0100 -Subject: [PATCH 01/11] RHEL: disable "seqpacket" for "vhost-vsock-device" in +Subject: [PATCH 1/5] RHEL: disable "seqpacket" for "vhost-vsock-device" in rhel8.6.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RH-Author: Stefano Garzarella -RH-MergeRequest: 146: RHEL: disable "seqpacket" for "vhost-vsock-device" in rhel8.6.0 [rhel-8.6.0.z] -RH-Commit: [1/1] 516ee668b84252528de6f4946298089b153846f1 -RH-Bugzilla: 2071103 -RH-Acked-by: Jason Wang -RH-Acked-by: Stefan Hajnoczi -RH-Acked-by: Eugenio Pérez +RH-MergeRequest: 136: RHEL: disable "seqpacket" for "vhost-vsock-device" in rhel8.6.0 [rhel-8.7.0] +RH-Commit: [1/1] d82ea09e123679521503689f7d9af1c03dc71bfc +RH-Bugzilla: 2068202 +RH-Acked-by: Jason Wang +RH-Acked-by: Eugenio Pérez RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Stefan Hajnoczi vhost-vsock device in RHEL 8 kernels doesn't support seqpacket. To avoid problems when migrating a VM from RHEL 9 host, we need to diff --git a/kvm-Revert-redhat-Add-hw_compat_4_2_extra-and-apply-to-u.patch b/kvm-Revert-redhat-Add-hw_compat_4_2_extra-and-apply-to-u.patch index 6ad2776..56af50f 100644 --- a/kvm-Revert-redhat-Add-hw_compat_4_2_extra-and-apply-to-u.patch +++ b/kvm-Revert-redhat-Add-hw_compat_4_2_extra-and-apply-to-u.patch @@ -1,21 +1,33 @@ -From dc2e9ec1e014950c7918e23a3e9b0096b34a4a92 Mon Sep 17 00:00:00 2001 -From: "Dr. David Alan Gilbert" -Date: Wed, 9 Mar 2022 10:31:53 +0000 -Subject: [PATCH 1/6] Revert "redhat: Add hw_compat_4_2_extra and apply to +From e626dc16d130c724c400b99a93daad0a9abeae59 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Tue, 22 Mar 2022 19:23:36 -0400 +Subject: [PATCH 01/18] Revert "redhat: Add hw_compat_4_2_extra and apply to upstream machines" -RH-Author: Dr. David Alan Gilbert -RH-MergeRequest: 121: x86: Remove upstream compat machines -RH-Commit: [1/3] 7a3e416b5a464a2a7892337289443268189baf44 -RH-Bugzilla: 2061856 -RH-Acked-by: Stephen Tweedie -RH-Acked-by: quintela1 +RH-Author: Jon Maloy +RH-MergeRequest: 131: Revert "redhat: Add hw_compat_4_2_extra and apply to upstream machines" +RH-Commit: [1/3] 47b7d9e5062f5e215d5ed1a3ecdc1a87ac3fa630 (jmaloy/qemu-kvm) +RH-Bugzilla: 2062613 RH-Acked-by: Peter Xu +RH-Acked-by: Dr. David Alan Gilbert -This reverts commit 66882f9a3230246409f3918424aca26add5c034a. -We no longer need these compat machines it was added for. +BZ: https://bugzilla.redhat.com/2062613 +UPSTREAM: no +BREW: https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=44038000 -Signed-off-by: Dr. David Alan Gilbert +commit dc2e9ec1e014950c7918e23a3e9b0096b34a4a92 +Author: Dr. David Alan Gilbert +Date: Wed Mar 9 10:31:53 2022 +0000 + + Revert "redhat: Add hw_compat_4_2_extra and apply to upstream machines" + + This reverts commit 66882f9a3230246409f3918424aca26add5c034a. + We no longer need these compat machines it was added for. + + Signed-off-by: Dr. David Alan Gilbert + +(cherry picked from commit dc2e9ec1e014950c7918e23a3e9b0096b34a4a92) +Signed-off-by: Jon Maloy --- hw/i386/pc.c | 12 ------------ hw/i386/pc_piix.c | 6 ------ diff --git a/kvm-Revert-redhat-Add-some-devices-for-exporting-upstrea.patch b/kvm-Revert-redhat-Add-some-devices-for-exporting-upstrea.patch index 3aac284..2aaef33 100644 --- a/kvm-Revert-redhat-Add-some-devices-for-exporting-upstrea.patch +++ b/kvm-Revert-redhat-Add-some-devices-for-exporting-upstrea.patch @@ -1,18 +1,18 @@ -From 27fbe5c920c6680f9dbe994963183ee515f40c12 Mon Sep 17 00:00:00 2001 +From 96edd15df257f1d1496397a6fac24b4316570d7e Mon Sep 17 00:00:00 2001 From: Jon Maloy Date: Thu, 14 Apr 2022 16:45:30 -0400 -Subject: [PATCH 1/2] Revert redhat: Add some devices for exporting upstream +Subject: [PATCH 1/3] Revert redhat: Add some devices for exporting upstream machine types RH-Author: Jon Maloy -RH-MergeRequest: 177: Revert redhat: Add some devices for exporting upstream machine types -RH-Commit: [1/1] 9e5dd81cc2e2c8f1df76de9f75d815c91c250c69 (jmaloy/qemu-kvm) -RH-Bugzilla: 2077928 +RH-MergeRequest: 156: Revert redhat: Add some devices for exporting upstream machine types +RH-Commit: [1/1] f25d0da3a181136917ead82f5a5c59efe3fa445a (jmaloy/qemu-kvm) +RH-Bugzilla: 2065043 RH-Acked-by: Miroslav Rezanina RH-Acked-by: Thomas Huth RH-Acked-by: Peter Xu -Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2077928 +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2065043 Upstream: no Manual revert of commit 70d3924521c9bfd912bcf1a1fc76f49eb377de46, since @@ -124,5 +124,5 @@ index 202e032524..9520471be2 100644 warn_report("Hpet's intcap not initialized"); } -- -2.35.3 +2.35.1 diff --git a/kvm-Revert-redhat-Enable-FDC-device-for-upstream-machine.patch b/kvm-Revert-redhat-Enable-FDC-device-for-upstream-machine.patch index 11a4719..1b2051a 100644 --- a/kvm-Revert-redhat-Enable-FDC-device-for-upstream-machine.patch +++ b/kvm-Revert-redhat-Enable-FDC-device-for-upstream-machine.patch @@ -1,21 +1,33 @@ -From 597cb6ca1da4a3eea77c1e4928f55203a1d5c70c Mon Sep 17 00:00:00 2001 -From: "Dr. David Alan Gilbert" -Date: Wed, 9 Mar 2022 10:32:39 +0000 -Subject: [PATCH 2/6] Revert "redhat: Enable FDC device for upstream machines +From 5bf8f1d69fea1225e927fbb3efe549a2a9d47d92 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Tue, 22 Mar 2022 19:23:36 -0400 +Subject: [PATCH 02/18] Revert "redhat: Enable FDC device for upstream machines too" -RH-Author: Dr. David Alan Gilbert -RH-MergeRequest: 121: x86: Remove upstream compat machines -RH-Commit: [2/3] 1d4d284babe8fe5b25ccb4ca85daf6f8c6cedcc2 -RH-Bugzilla: 2061856 -RH-Acked-by: Stephen Tweedie -RH-Acked-by: quintela1 +RH-Author: Jon Maloy +RH-MergeRequest: 131: Revert "redhat: Add hw_compat_4_2_extra and apply to upstream machines" +RH-Commit: [2/3] 4e3c945e3de9bb9d9a6d24115f0719168c9669fe (jmaloy/qemu-kvm) +RH-Bugzilla: 2062613 RH-Acked-by: Peter Xu +RH-Acked-by: Dr. David Alan Gilbert -This reverts commit c4d1aa8bf21fe98da94a9cff30b7c25bed12c17f. -We no longer need these compat machines it was added for. +BZ: https://bugzilla.redhat.com/2062613 +UPSTREAM: no +BREW: https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=44038000 -Signed-off-by: Dr. David Alan Gilbert +commit 597cb6ca1da4a3eea77c1e4928f55203a1d5c70c +Author: Dr. David Alan Gilbert +Date: Wed Mar 9 10:32:39 2022 +0000 + + Revert "redhat: Enable FDC device for upstream machines too" + + This reverts commit c4d1aa8bf21fe98da94a9cff30b7c25bed12c17f. + We no longer need these compat machines it was added for. + + Signed-off-by: Dr. David Alan Gilbert + +(cherry picked from commit 597cb6ca1da4a3eea77c1e4928f55203a1d5c70c) +Signed-off-by: Jon Maloy --- hw/block/fdc.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/kvm-Revert-redhat-Expose-upstream-machines-pc-4.2-and-pc.patch b/kvm-Revert-redhat-Expose-upstream-machines-pc-4.2-and-pc.patch index f2d98fd..27e3dc9 100644 --- a/kvm-Revert-redhat-Expose-upstream-machines-pc-4.2-and-pc.patch +++ b/kvm-Revert-redhat-Expose-upstream-machines-pc-4.2-and-pc.patch @@ -1,21 +1,32 @@ -From f3b50d6d4ae0be9e64aafe6a15f5423bab4899e9 Mon Sep 17 00:00:00 2001 -From: "Dr. David Alan Gilbert" -Date: Wed, 9 Mar 2022 10:34:58 +0000 -Subject: [PATCH 3/6] Revert "redhat: Expose upstream machines pc-4.2 and +From ee3cae3bb349469edcf725a1c5161521e95dcb9f Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Tue, 22 Mar 2022 19:23:36 -0400 +Subject: [PATCH 03/18] Revert "redhat: Expose upstream machines pc-4.2 and pc-2.11" -RH-Author: Dr. David Alan Gilbert -RH-MergeRequest: 121: x86: Remove upstream compat machines -RH-Commit: [3/3] 9aef91a363110034776c8d6b3013fc06aec9c674 -RH-Bugzilla: 2061856 -RH-Acked-by: Stephen Tweedie -RH-Acked-by: quintela1 +RH-Author: Jon Maloy +RH-MergeRequest: 131: Revert "redhat: Add hw_compat_4_2_extra and apply to upstream machines" +RH-Commit: [3/3] 35cee68034580f81b3aa916921eecd2fdfa7dd15 (jmaloy/qemu-kvm) +RH-Bugzilla: 2062613 RH-Acked-by: Peter Xu +RH-Acked-by: Dr. David Alan Gilbert -This reverts commit 618e2424edba499d52cd26cf8363bc2dd85ef149. -We no longer need these compat machines. +BZ: https://bugzilla.redhat.com/2062613 +UPSTREAM: no +BREW: https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=44038000 -Signed-off-by: Dr. David Alan Gilbert +commit f3b50d6d4ae0be9e64aafe6a15f5423bab4899e9 +Author: Dr. David Alan Gilbert +Date: Wed Mar 9 10:34:58 2022 +0000 + + Revert "redhat: Expose upstream machines pc-4.2 and pc-2.11" + This reverts commit 618e2424edba499d52cd26cf8363bc2dd85ef149. + We no longer need these compat machines. + + Signed-off-by: Dr. David Alan Gilbert + +(cherry picked from commit f3b50d6d4ae0be9e64aafe6a15f5423bab4899e9) +Signed-off-by: Jon Maloy --- hw/i386/pc_piix.c | 37 ------------------------------------- 1 file changed, 37 deletions(-) diff --git a/kvm-acpi-fix-OEM-ID-OEM-Table-ID-padding.patch b/kvm-acpi-fix-OEM-ID-OEM-Table-ID-padding.patch index 9699b3e..9d2594f 100644 --- a/kvm-acpi-fix-OEM-ID-OEM-Table-ID-padding.patch +++ b/kvm-acpi-fix-OEM-ID-OEM-Table-ID-padding.patch @@ -1,50 +1,58 @@ -From 5294117078691549e84e26a96a2d647debabf7db Mon Sep 17 00:00:00 2001 -From: Igor Mammedov -Date: Wed, 12 Jan 2022 08:03:31 -0500 -Subject: [PATCH 09/12] acpi: fix OEM ID/OEM Table ID padding +From af082f3499de265d123157d097b5c84981e0aa63 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Wed, 30 Mar 2022 14:52:34 -0400 +Subject: [PATCH 15/18] acpi: fix OEM ID/OEM Table ID padding -RH-Author: Igor Mammedov -RH-MergeRequest: 129: acpi: fix QEMU crash when started with SLIC table -RH-Commit: [7/10] 3404492ef0094c8d5d2db0c82f1159705f9de7c7 -RH-Bugzilla: 2059311 -RH-Acked-by: Jon Maloy -RH-Acked-by: Gerd Hoffmann -RH-Acked-by: MST +RH-Author: Jon Maloy +RH-MergeRequest: 141: acpi: fix QEMU crash when started with SLIC table +RH-Commit: [7/10] 51ea859cbe12b5a902d529ab589d18757d98f71d (jmaloy/qemu-kvm) +RH-Bugzilla: 2062611 +RH-Acked-by: Igor Mammedov -Commit [2] broke original '\0' padding of OEM ID and OEM Table ID -fields in headers of ACPI tables. While it doesn't have impact on -default values since QEMU uses 6 and 8 characters long values -respectively, it broke usecase where IDs are provided on QEMU CLI. -It shouldn't affect guest (but may cause licensing verification -issues in guest OS). -One of the broken usecases is user supplied SLIC table with IDs -shorter than max possible length, where [2] mangles IDs with extra -spaces in RSDT and FADT tables whereas guest OS expects those to -mirror the respective values of the used SLIC table. +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2062611 +Upstream: Merged -Fix it by replacing whitespace padding with '\0' padding in -accordance with [1] and expectations of guest OS +commit 748c030f360a940fe0c9382c8ca1649096c3a80d +Author: Igor Mammedov +Date: Wed Jan 12 08:03:31 2022 -0500 -1) ACPI spec, v2.0b - 17.2 AML Grammar Definition - ... - //OEM ID of up to 6 characters. If the OEM ID is - //shorter than 6 characters, it can be terminated - //with a NULL character. + acpi: fix OEM ID/OEM Table ID padding + + Commit [2] broke original '\0' padding of OEM ID and OEM Table ID + fields in headers of ACPI tables. While it doesn't have impact on + default values since QEMU uses 6 and 8 characters long values + respectively, it broke usecase where IDs are provided on QEMU CLI. + It shouldn't affect guest (but may cause licensing verification + issues in guest OS). + One of the broken usecases is user supplied SLIC table with IDs + shorter than max possible length, where [2] mangles IDs with extra + spaces in RSDT and FADT tables whereas guest OS expects those to + mirror the respective values of the used SLIC table. + + Fix it by replacing whitespace padding with '\0' padding in + accordance with [1] and expectations of guest OS + + 1) ACPI spec, v2.0b + 17.2 AML Grammar Definition + ... + //OEM ID of up to 6 characters. If the OEM ID is + //shorter than 6 characters, it can be terminated + //with a NULL character. + + 2) + Fixes: 602b458201 ("acpi: Permit OEM ID and OEM table ID fields to be changed") + Resolves: https://gitlab.com/qemu-project/qemu/-/issues/707 + Reported-by: Dmitry V. Orekhov + Signed-off-by: Igor Mammedov + Cc: qemu-stable@nongnu.org + Message-Id: <20220112130332.1648664-4-imammedo@redhat.com> + Reviewed-by: Michael S. Tsirkin + Signed-off-by: Michael S. Tsirkin + Reviewed-by: Ani Sinha + Tested-by: Dmitry V. Orekhov dima.orekhov@gmail.com -2) -Fixes: 602b458201 ("acpi: Permit OEM ID and OEM table ID fields to be changed") -Resolves: https://gitlab.com/qemu-project/qemu/-/issues/707 -Reported-by: Dmitry V. Orekhov -Signed-off-by: Igor Mammedov -Cc: qemu-stable@nongnu.org -Message-Id: <20220112130332.1648664-4-imammedo@redhat.com> -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Michael S. Tsirkin -Reviewed-by: Ani Sinha -Tested-by: Dmitry V. Orekhov dima.orekhov@gmail.com (cherry picked from commit 748c030f360a940fe0c9382c8ca1649096c3a80d) -Signed-off-by: Igor Mammedov +Signed-off-by: Jon Maloy --- hw/acpi/aml-build.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kvm-acpi-fix-QEMU-crash-when-started-with-SLIC-table.patch b/kvm-acpi-fix-QEMU-crash-when-started-with-SLIC-table.patch index c55cb9b..a6b1151 100644 --- a/kvm-acpi-fix-QEMU-crash-when-started-with-SLIC-table.patch +++ b/kvm-acpi-fix-QEMU-crash-when-started-with-SLIC-table.patch @@ -1,66 +1,75 @@ -From 2596689db79a5710fdfdb1f0d5bfe02557bb30e5 Mon Sep 17 00:00:00 2001 -From: Igor Mammedov -Date: Mon, 27 Dec 2021 14:31:17 -0500 -Subject: [PATCH 03/12] acpi: fix QEMU crash when started with SLIC table +From 4e8fb957a349558648d5cddb80a89460bc97439e Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Wed, 30 Mar 2022 14:52:34 -0400 +Subject: [PATCH 09/18] acpi: fix QEMU crash when started with SLIC table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit -RH-Author: Igor Mammedov -RH-MergeRequest: 129: acpi: fix QEMU crash when started with SLIC table -RH-Commit: [1/10] da8a19a574ce0c8862c84173434fa186aaddc855 -RH-Bugzilla: 2059311 -RH-Acked-by: Jon Maloy -RH-Acked-by: Gerd Hoffmann -RH-Acked-by: MST - -if QEMU is started with used provided SLIC table blob, - - -acpitable sig=SLIC,oem_id='CRASH ',oem_table_id="ME",oem_rev=00002210,asl_compiler_id="",asl_compiler_rev=00000000,data=/dev/null -it will assert with: - - hw/acpi/aml-build.c:61:build_append_padded_str: assertion failed: (len <= maxlen) - -and following backtrace: - - ... - build_append_padded_str (array=0x555556afe320, str=0x555556afdb2e "CRASH ME", maxlen=0x6, pad=0x20) at hw/acpi/aml-build.c:61 - acpi_table_begin (desc=0x7fffffffd1b0, array=0x555556afe320) at hw/acpi/aml-build.c:1727 - build_fadt (tbl=0x555556afe320, linker=0x555557ca3830, f=0x7fffffffd318, oem_id=0x555556afdb2e "CRASH ME", oem_table_id=0x555556afdb34 "ME") at hw/acpi/aml-build.c:2064 - ... - -which happens due to acpi_table_begin() expecting NULL terminated -oem_id and oem_table_id strings, which is normally the case, but -in case of user provided SLIC table, oem_id points to table's blob -directly and as result oem_id became longer than expected. - -Fix issue by handling oem_id consistently and make acpi_get_slic_oem() -return NULL terminated strings. - -PS: -After [1] refactoring, oem_id semantics became inconsistent, where -NULL terminated string was coming from machine and old way pointer -into byte array coming from -acpitable option. That used to work -since build_header() wasn't expecting NULL terminated string and -blindly copied the 1st 6 bytes only. - -However commit [2] broke that by replacing build_header() with -acpi_table_begin(), which was expecting NULL terminated string -and was checking oem_id size. - -1) 602b45820 ("acpi: Permit OEM ID and OEM table ID fields to be changed") -2) -Fixes: 4b56e1e4eb08 ("acpi: build_fadt: use acpi_table_begin()/acpi_table_end() instead of build_header()") -Resolves: https://gitlab.com/qemu-project/qemu/-/issues/786 -Signed-off-by: Igor Mammedov -Message-Id: <20211227193120.1084176-2-imammedo@redhat.com> -Reviewed-by: Philippe Mathieu-Daudé -Tested-by: Denis Lisov -Tested-by: Alexander Tsoy -Cc: qemu-stable@nongnu.org -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Michael S. Tsirkin +RH-Author: Jon Maloy +RH-MergeRequest: 141: acpi: fix QEMU crash when started with SLIC table +RH-Commit: [1/10] 0c34e80346c33da4f220d9c486b120c35005144e (jmaloy/qemu-kvm) +RH-Bugzilla: 2062611 +RH-Acked-by: Igor Mammedov + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2062611 +Upstream: Merged + +commit 8cdb99af45365727ac17f45239a9b8c1d5155c6d) +Author: Igor Mammedov +Date: Mon Dec 27 14:31:17 2021 -0500 + + acpi: fix QEMU crash when started with SLIC table + + if QEMU is started with used provided SLIC table blob, + + -acpitable sig=SLIC,oem_id='CRASH ',oem_table_id="ME",oem_rev=00002210,asl_compiler_id="",asl_compiler_rev=00000000,data=/dev/null + it will assert with: + + hw/acpi/aml-build.c:61:build_append_padded_str: assertion failed: (len <= maxlen) + + and following backtrace: + + ... + build_append_padded_str (array=0x555556afe320, str=0x555556afdb2e "CRASH ME", maxlen=0x6, pad=0x20) at hw/acpi/aml-build.c:61 + acpi_table_begin (desc=0x7fffffffd1b0, array=0x555556afe320) at hw/acpi/aml-build.c:1727 + build_fadt (tbl=0x555556afe320, linker=0x555557ca3830, f=0x7fffffffd318, oem_id=0x555556afdb2e "CRASH ME", oem_table_id=0x555556afdb34 "ME") at hw/acpi/aml-build.c:2064 + ... + + which happens due to acpi_table_begin() expecting NULL terminated + oem_id and oem_table_id strings, which is normally the case, but + in case of user provided SLIC table, oem_id points to table's blob + directly and as result oem_id became longer than expected. + + Fix issue by handling oem_id consistently and make acpi_get_slic_oem() + return NULL terminated strings. + + PS: + After [1] refactoring, oem_id semantics became inconsistent, where + NULL terminated string was coming from machine and old way pointer + into byte array coming from -acpitable option. That used to work + since build_header() wasn't expecting NULL terminated string and + blindly copied the 1st 6 bytes only. + + However commit [2] broke that by replacing build_header() with + acpi_table_begin(), which was expecting NULL terminated string + and was checking oem_id size. + + 1) 602b45820 ("acpi: Permit OEM ID and OEM table ID fields to be changed") + 2) + Fixes: 4b56e1e4eb08 ("acpi: build_fadt: use acpi_table_begin()/acpi_table_end() instead of build_header()") + Resolves: https://gitlab.com/qemu-project/qemu/-/issues/786 + Signed-off-by: Igor Mammedov + Message-Id: <20211227193120.1084176-2-imammedo@redhat.com> + Reviewed-by: Philippe Mathieu-Daudé + Tested-by: Denis Lisov + Tested-by: Alexander Tsoy + Cc: qemu-stable@nongnu.org + Reviewed-by: Michael S. Tsirkin + Signed-off-by: Michael S. Tsirkin + (cherry picked from commit 8cdb99af45365727ac17f45239a9b8c1d5155c6d) +Signed-off-by: Jon Maloy --- hw/acpi/core.c | 4 ++-- hw/i386/acpi-build.c | 2 ++ diff --git a/kvm-acpi-pcihp-pcie-set-power-on-cap-on-parent-slot.patch b/kvm-acpi-pcihp-pcie-set-power-on-cap-on-parent-slot.patch index 36c2ed4..2be41b6 100644 --- a/kvm-acpi-pcihp-pcie-set-power-on-cap-on-parent-slot.patch +++ b/kvm-acpi-pcihp-pcie-set-power-on-cap-on-parent-slot.patch @@ -1,53 +1,63 @@ -From c655f89956c69dc4bb3c3c74515c6c04bd0195bb Mon Sep 17 00:00:00 2001 -From: Igor Mammedov -Date: Tue, 1 Mar 2022 10:11:59 -0500 -Subject: [PATCH 6/6] acpi: pcihp: pcie: set power on cap on parent slot +From c9ceb175667cdeead59384a97a812367ae19c570 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Wed, 23 Mar 2022 13:21:40 -0400 +Subject: [PATCH 06/18] acpi: pcihp: pcie: set power on cap on parent slot -RH-Author: Igor Mammedov -RH-MergeRequest: 125: RHEL-8.6 Fix broken PCIe device after migration -RH-Commit: [2/2] effbd75b9d495c88dd4d910b547154849fb1e821 -RH-Bugzilla: 2054597 -RH-Acked-by: Jon Maloy +RH-Author: Jon Maloy +RH-MergeRequest: 134: pci: expose TYPE_XIO3130_DOWNSTREAM name +RH-Commit: [2/2] d883872647a6e90ec573140b2c171f3f53b600ab (jmaloy/qemu-kvm) +RH-Bugzilla: 2062610 +RH-Acked-by: Igor Mammedov RH-Acked-by: Gerd Hoffmann -RH-Acked-by: MST -on creation a PCIDevice has power turned on at the end of pci_qdev_realize() -however later on if PCIe slot isn't populated with any children -it's power is turned off. It's fine if native hotplug is used -as plug callback will power slot on among other things. -However when ACPI hotplug is enabled it replaces native PCIe plug -callbacks with ACPI specific ones (acpi_pcihp_device_*plug_cb) and -as result slot stays powered off. It works fine as ACPI hotplug -on guest side takes care of enumerating/initializing hotplugged -device. But when later guest is migrated, call chain introduced by] -commit d5daff7d312 (pcie: implement slot power control for pcie root ports) +BZ: https://bugzilla.redhat.com/2062610 +UPSTREAM: merged +BREW: https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=44038138 - pcie_cap_slot_post_load() - -> pcie_cap_update_power() - -> pcie_set_power_device() - -> pci_set_power() - -> pci_update_mappings() +commit 6b0969f1ec825984cd74619f0730be421b0c46fb +Author: Igor Mammedov +Date: Tue Mar 1 10:11:59 2022 -0500 -will disable earlier initialized BARs for the hotplugged device -in powered off slot due to commit 23786d13441 (pci: implement power state) -which disables BARs if power is off. + acpi: pcihp: pcie: set power on cap on parent slot -Fix it by setting PCI_EXP_SLTCTL_PCC to PCI_EXP_SLTCTL_PWR_ON -on slot (root port/downstream port) at the time a device -hotplugged into it. As result PCI_EXP_SLTCTL_PWR_ON is migrated -to target and above call chain keeps device plugged into it -powered on. + on creation a PCIDevice has power turned on at the end of pci_qdev_realize() + however later on if PCIe slot isn't populated with any children + it's power is turned off. It's fine if native hotplug is used + as plug callback will power slot on among other things. + However when ACPI hotplug is enabled it replaces native PCIe plug + callbacks with ACPI specific ones (acpi_pcihp_device_*plug_cb) and + as result slot stays powered off. It works fine as ACPI hotplug + on guest side takes care of enumerating/initializing hotplugged + device. But when later guest is migrated, call chain introduced by] + commit d5daff7d312 (pcie: implement slot power control for pcie root ports) + + pcie_cap_slot_post_load() + -> pcie_cap_update_power() + -> pcie_set_power_device() + -> pci_set_power() + -> pci_update_mappings() + + will disable earlier initialized BARs for the hotplugged device + in powered off slot due to commit 23786d13441 (pci: implement power state) + which disables BARs if power is off. + + Fix it by setting PCI_EXP_SLTCTL_PCC to PCI_EXP_SLTCTL_PWR_ON + on slot (root port/downstream port) at the time a device + hotplugged into it. As result PCI_EXP_SLTCTL_PWR_ON is migrated + to target and above call chain keeps device plugged into it + powered on. + + Fixes: d5daff7d312 ("pcie: implement slot power control for pcie root ports") + Fixes: 23786d13441 ("pci: implement power state") + Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=2053584 + Suggested-by: "Michael S. Tsirkin" + Signed-off-by: Igor Mammedov + Message-Id: <20220301151200.3507298-3-imammedo@redhat.com> + Reviewed-by: Michael S. Tsirkin + Signed-off-by: Michael S. Tsirkin -Fixes: d5daff7d312 ("pcie: implement slot power control for pcie root ports") -Fixes: 23786d13441 ("pci: implement power state") -Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=2053584 -Suggested-by: "Michael S. Tsirkin" -Signed-off-by: Igor Mammedov -Message-Id: <20220301151200.3507298-3-imammedo@redhat.com> -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Michael S. Tsirkin (cherry picked from commit 6b0969f1ec825984cd74619f0730be421b0c46fb) -Signed-off-by: Igor Mammedov +Signed-off-by: Jon Maloy --- hw/acpi/pcihp.c | 12 +++++++++++- hw/pci/pcie.c | 11 +++++++++++ diff --git a/kvm-block-Lock-AioContext-for-drain_end-in-blockdev-reop.patch b/kvm-block-Lock-AioContext-for-drain_end-in-blockdev-reop.patch new file mode 100644 index 0000000..eb0f3cf --- /dev/null +++ b/kvm-block-Lock-AioContext-for-drain_end-in-blockdev-reop.patch @@ -0,0 +1,63 @@ +From b21fa5ecd9acf2b91839a2915fb4bb39dac4c803 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Thu, 3 Feb 2022 15:05:33 +0100 +Subject: [PATCH 2/5] block: Lock AioContext for drain_end in blockdev-reopen + +RH-Author: Kevin Wolf +RH-MergeRequest: 142: block: Lock AioContext for drain_end in blockdev-reopen +RH-Commit: [1/2] 98de3b5987f88ea6b4b503f623d6c4475574e037 +RH-Bugzilla: 2067118 +RH-Acked-by: Emanuele Giuseppe Esposito +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Hanna Reitz + +bdrv_subtree_drained_end() requires the caller to hold the AioContext +lock for the drained node. Not doing this for nodes outside of the main +AioContext leads to crashes when AIO_WAIT_WHILE() needs to wait and +tries to temporarily release the lock. + +Fixes: 3908b7a8994fa5ef7a89aa58cd5a02fc58141592 +Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2046659 +Reported-by: Qing Wang +Signed-off-by: Kevin Wolf +Message-Id: <20220203140534.36522-2-kwolf@redhat.com> +Reviewed-by: Hanna Reitz +Signed-off-by: Kevin Wolf +(cherry picked from commit aba8205be0707b9d108e32254e186ba88107a869) +Signed-off-by: Kevin Wolf +--- + blockdev.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/blockdev.c b/blockdev.c +index b35072644e..565f6a81fd 100644 +--- a/blockdev.c ++++ b/blockdev.c +@@ -3562,6 +3562,7 @@ void qmp_blockdev_reopen(BlockdevOptionsList *reopen_list, Error **errp) + { + BlockReopenQueue *queue = NULL; + GSList *drained = NULL; ++ GSList *p; + + /* Add each one of the BDS that we want to reopen to the queue */ + for (; reopen_list != NULL; reopen_list = reopen_list->next) { +@@ -3611,7 +3612,15 @@ void qmp_blockdev_reopen(BlockdevOptionsList *reopen_list, Error **errp) + + fail: + bdrv_reopen_queue_free(queue); +- g_slist_free_full(drained, (GDestroyNotify) bdrv_subtree_drained_end); ++ for (p = drained; p; p = p->next) { ++ BlockDriverState *bs = p->data; ++ AioContext *ctx = bdrv_get_aio_context(bs); ++ ++ aio_context_acquire(ctx); ++ bdrv_subtree_drained_end(bs); ++ aio_context_release(ctx); ++ } ++ g_slist_free(drained); + } + + void qmp_blockdev_del(const char *node_name, Error **errp) +-- +2.27.0 + diff --git a/kvm-block-Make-bdrv_refresh_limits-non-recursive.patch b/kvm-block-Make-bdrv_refresh_limits-non-recursive.patch new file mode 100644 index 0000000..7ff8e7e --- /dev/null +++ b/kvm-block-Make-bdrv_refresh_limits-non-recursive.patch @@ -0,0 +1,78 @@ +From 6348063b91b2370cc27153fd58fd11a6681631f6 Mon Sep 17 00:00:00 2001 +From: Hanna Reitz +Date: Wed, 16 Feb 2022 11:53:53 +0100 +Subject: [PATCH 22/24] block: Make bdrv_refresh_limits() non-recursive +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Hanna Reitz +RH-MergeRequest: 189: block: Make bdrv_refresh_limits() non-recursive +RH-Commit: [1/3] 1a1fe37f8d8f0344dd8639d6cc9d884d1aff9096 +RH-Bugzilla: 2072932 +RH-Acked-by: Eric Blake +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Kevin Wolf + +bdrv_refresh_limits() recurses down to the node's children. That does +not seem necessary: When we refresh limits on some node, and then +recurse down and were to change one of its children's BlockLimits, then +that would mean we noticed the changed limits by pure chance. The fact +that we refresh the parent's limits has nothing to do with it, so the +reason for the change probably happened before this point in time, and +we should have refreshed the limits then. + +Consequently, we should actually propagate block limits changes upwards, +not downwards.  That is a separate and pre-existing issue, though, and +so will not be addressed in this patch. + +The problem with recursing is that bdrv_refresh_limits() is not atomic. +It begins with zeroing BDS.bl, and only then sets proper, valid limits. +If we do not drain all nodes whose limits are refreshed, then concurrent +I/O requests can encounter invalid request_alignment values and crash +qemu. Therefore, a recursing bdrv_refresh_limits() requires the whole +subtree to be drained, which is currently not ensured by most callers. + +A non-recursive bdrv_refresh_limits() only requires the node in question +to not receive I/O requests, and this is done by most callers in some +way or another: +- bdrv_open_driver() deals with a new node with no parents yet +- bdrv_set_file_or_backing_noperm() acts on a drained node +- bdrv_reopen_commit() acts only on drained nodes +- bdrv_append() should in theory require the node to be drained; in + practice most callers just lock the AioContext, which should at least + be enough to prevent concurrent I/O requests from accessing invalid + limits + +So we can resolve the bug by making bdrv_refresh_limits() non-recursive. + +Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=1879437 +Signed-off-by: Hanna Reitz +Reviewed-by: Eric Blake +Message-Id: <20220216105355.30729-2-hreitz@redhat.com> +Reviewed-by: Stefan Hajnoczi +Signed-off-by: Kevin Wolf +(cherry picked from commit 4d378bbd831bdd2f6e6adcd4ea5b77b6effaa627) +Signed-off-by: Hanna Reitz +--- + block/io.c | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/block/io.c b/block/io.c +index 4e4cb556c5..c3e7301613 100644 +--- a/block/io.c ++++ b/block/io.c +@@ -189,10 +189,6 @@ void bdrv_refresh_limits(BlockDriverState *bs, Transaction *tran, Error **errp) + QLIST_FOREACH(c, &bs->children, next) { + if (c->role & (BDRV_CHILD_DATA | BDRV_CHILD_FILTERED | BDRV_CHILD_COW)) + { +- bdrv_refresh_limits(c->bs, tran, errp); +- if (*errp) { +- return; +- } + bdrv_merge_limits(&bs->bl, &c->bs->bl); + have_limits = true; + } +-- +2.35.3 + diff --git a/kvm-display-qxl-render-fix-race-condition-in-qxl_cursor-.patch b/kvm-display-qxl-render-fix-race-condition-in-qxl_cursor-.patch index c933542..040cfe1 100644 --- a/kvm-display-qxl-render-fix-race-condition-in-qxl_cursor-.patch +++ b/kvm-display-qxl-render-fix-race-condition-in-qxl_cursor-.patch @@ -1,21 +1,20 @@ -From 08103b26cb393920410e0a943d35e79bbd9f5ce0 Mon Sep 17 00:00:00 2001 +From abd84f26e0fe0bc9952d91fbd35fb3a7253cfecf Mon Sep 17 00:00:00 2001 From: Jon Maloy Date: Wed, 13 Apr 2022 20:54:45 -0400 -Subject: [PATCH 05/11] display/qxl-render: fix race condition in qxl_cursor +Subject: [PATCH 1/2] display/qxl-render: fix race condition in qxl_cursor (CVE-2021-4207) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RH-Author: Jon Maloy -RH-MergeRequest: 162: display/qxl-render: fix race condition in qxl_cursor (CVE-2021-4207) -RH-Commit: [1/1] 055c5a8345ad434a723b8106ba0a7b85fe117547 (jmaloy/qemu-kvm) -RH-Bugzilla: 2075683 -RH-Acked-by: Miroslav Rezanina -RH-Acked-by: Marc-André Lureau +RH-MergeRequest: 152: display/qxl-render: fix race condition in qxl_cursor (CVE-2021-4207) +RH-Commit: [1/1] f05b9a956f2e0ca522b5be127beff813d04b5588 (jmaloy/qemu-kvm) +RH-Bugzilla: 2040738 +RH-Acked-by: Gerd Hoffmann RH-Acked-by: Mauro Matteo Cascella -Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2075683 +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2040738 Upstream: Merged CVE: CVE-2021-4207 diff --git a/kvm-hw-block-fdc-Prevent-end-of-track-overrun-CVE-2021-3.patch b/kvm-hw-block-fdc-Prevent-end-of-track-overrun-CVE-2021-3.patch new file mode 100644 index 0000000..01e4097 --- /dev/null +++ b/kvm-hw-block-fdc-Prevent-end-of-track-overrun-CVE-2021-3.patch @@ -0,0 +1,97 @@ +From fe4abbda80eea7f65b6b5cc544a806fb6e064917 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Thu, 18 Nov 2021 12:57:32 +0100 +Subject: [PATCH 2/3] hw/block/fdc: Prevent end-of-track overrun + (CVE-2021-3507) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Jon Maloy +RH-MergeRequest: 194: hw/block/fdc: Prevent end-of-track overrun (CVE-2021-3507) +RH-Commit: [1/2] 31fa0351382b4ca5bd989b09e4d811ae73040673 (jmaloy/qemu-kvm) +RH-Bugzilla: 1951521 +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Thomas Huth +RH-Acked-by: Hanna Reitz + +Per the 82078 datasheet, if the end-of-track (EOT byte in +the FIFO) is more than the number of sectors per side, the +command is terminated unsuccessfully: + +* 5.2.5 DATA TRANSFER TERMINATION + + The 82078 supports terminal count explicitly through + the TC pin and implicitly through the underrun/over- + run and end-of-track (EOT) functions. For full sector + transfers, the EOT parameter can define the last + sector to be transferred in a single or multisector + transfer. If the last sector to be transferred is a par- + tial sector, the host can stop transferring the data in + mid-sector, and the 82078 will continue to complete + the sector as if a hardware TC was received. The + only difference between these implicit functions and + TC is that they return "abnormal termination" result + status. Such status indications can be ignored if they + were expected. + +* 6.1.3 READ TRACK + + This command terminates when the EOT specified + number of sectors have been read. If the 82078 + does not find an I D Address Mark on the diskette + after the second· occurrence of a pulse on the + INDX# pin, then it sets the IC code in Status Regis- + ter 0 to "01" (Abnormal termination), sets the MA bit + in Status Register 1 to "1", and terminates the com- + mand. + +* 6.1.6 VERIFY + + Refer to Table 6-6 and Table 6-7 for information + concerning the values of MT and EC versus SC and + EOT value. + +* Table 6·6. Result Phase Table + +* Table 6-7. Verify Command Result Phase Table + +Fix by aborting the transfer when EOT > # Sectors Per Side. + +Cc: qemu-stable@nongnu.org +Cc: Hervé Poussineau +Fixes: baca51faff0 ("floppy driver: disk geometry auto detect") +Reported-by: Alexander Bulekov +Resolves: https://gitlab.com/qemu-project/qemu/-/issues/339 +Signed-off-by: Philippe Mathieu-Daudé +Message-Id: <20211118115733.4038610-2-philmd@redhat.com> +Reviewed-by: Hanna Reitz +Signed-off-by: Kevin Wolf +(cherry picked from commit defac5e2fbddf8423a354ff0454283a2115e1367) +Signed-off-by: Jon Maloy +--- + hw/block/fdc.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/hw/block/fdc.c b/hw/block/fdc.c +index 97fa6de423..755a26c114 100644 +--- a/hw/block/fdc.c ++++ b/hw/block/fdc.c +@@ -1531,6 +1531,14 @@ static void fdctrl_start_transfer(FDCtrl *fdctrl, int direction) + int tmp; + fdctrl->data_len = 128 << (fdctrl->fifo[5] > 7 ? 7 : fdctrl->fifo[5]); + tmp = (fdctrl->fifo[6] - ks + 1); ++ if (tmp < 0) { ++ FLOPPY_DPRINTF("invalid EOT: %d\n", tmp); ++ fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, FD_SR1_MA, 0x00); ++ fdctrl->fifo[3] = kt; ++ fdctrl->fifo[4] = kh; ++ fdctrl->fifo[5] = ks; ++ return; ++ } + if (fdctrl->fifo[0] & 0x80) + tmp += fdctrl->fifo[6]; + fdctrl->data_len *= tmp; +-- +2.35.3 + diff --git a/kvm-hw-intc-arm_gicv3-Check-for-MEMTX_OK-instead-of-MEMT.patch b/kvm-hw-intc-arm_gicv3-Check-for-MEMTX_OK-instead-of-MEMT.patch index 4f7455b..eea6fa2 100644 --- a/kvm-hw-intc-arm_gicv3-Check-for-MEMTX_OK-instead-of-MEMT.patch +++ b/kvm-hw-intc-arm_gicv3-Check-for-MEMTX_OK-instead-of-MEMT.patch @@ -1,21 +1,20 @@ -From ef311c8ca284d11dc812a1004de52125fc9eb194 Mon Sep 17 00:00:00 2001 +From 2db3d0de1be018f14cb91fdd4a368996b09d8bec Mon Sep 17 00:00:00 2001 From: Jon Maloy Date: Wed, 13 Apr 2022 14:51:06 -0400 -Subject: [PATCH 02/11] hw/intc/arm_gicv3: Check for !MEMTX_OK instead of +Subject: [PATCH 1/3] hw/intc/arm_gicv3: Check for !MEMTX_OK instead of MEMTX_ERROR MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RH-Author: Jon Maloy -RH-MergeRequest: 158: hw/intc/arm_gicv3: Check for !MEMTX_OK instead of MEMTX_ERROR -RH-Commit: [1/3] ebfd87ea3a2de51c6961569861d5f4fba25890cc (jmaloy/qemu-kvm) -RH-Bugzilla: 2075686 -RH-Acked-by: Miroslav Rezanina +RH-MergeRequest: 151: hw/intc/arm_gicv3: Check for !MEMTX_OK instead of MEMTX_ERROR +RH-Commit: [1/3] 561c9c2b1249f07d33013040b1c495ed1fbf825b (jmaloy/qemu-kvm) +RH-Bugzilla: 1999236 RH-Acked-by: Stefan Hajnoczi RH-Acked-by: Peter Xu -Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2075686 +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1999236 Upstream: Merged CVE: CVE-2021-3750 diff --git a/kvm-hw-virtio-vdpa-Fix-leak-of-host-notifier-memory-regi.patch b/kvm-hw-virtio-vdpa-Fix-leak-of-host-notifier-memory-regi.patch index 4a88ae4..bb42634 100644 --- a/kvm-hw-virtio-vdpa-Fix-leak-of-host-notifier-memory-regi.patch +++ b/kvm-hw-virtio-vdpa-Fix-leak-of-host-notifier-memory-regi.patch @@ -1,44 +1,50 @@ -From 6f84eb3889a7035c07eeb2d337d2c3b06a6777f0 Mon Sep 17 00:00:00 2001 -From: Laurent Vivier -Date: Fri, 11 Feb 2022 18:02:59 +0100 -Subject: [PATCH 4/6] hw/virtio: vdpa: Fix leak of host-notifier memory-region - -RH-Author: Laurent Vivier -RH-MergeRequest: 122: hw/virtio: vdpa: Fix leak of host-notifier memory-region -RH-Commit: [1/1] cd8719f57b2eb398cce108e191c7155a112f4fc8 -RH-Bugzilla: 2027208 -RH-Acked-by: Jason Wang -RH-Acked-by: Cindy Lu -RH-Acked-by: MST +From f0115d856f46e65e3b62896f84fe1902a958bf79 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Tue, 22 Mar 2022 19:23:36 -0400 +Subject: [PATCH 04/18] hw/virtio: vdpa: Fix leak of host-notifier + memory-region + +RH-Author: Jon Maloy +RH-MergeRequest: 132: hw/virtio: vdpa: Fix leak of host-notifier memory-region +RH-Commit: [1/1] b3cec35d185e3b9844a458f5c51c5d5ef7e3d8f1 (jmaloy/qemu-kvm) +RH-Bugzilla: 2060843 RH-Acked-by: Stefano Garzarella +RH-Acked-by: Laurent Vivier +RH-Acked-by: Igor Mammedov + +BZ: https://bugzilla.redhat.com/2060843 +UPSTREAM: no +BREW: https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=44038138 + +commit 98f7607ecda00dea3cbb2ed7b4427c96846efb83 +Author: Laurent Vivier +Date: Fri Feb 11 18:02:59 2022 +0100 + + hw/virtio: vdpa: Fix leak of host-notifier memory-region + + If call virtio_queue_set_host_notifier_mr fails, should free + host-notifier memory-region. + + This problem can trigger a coredump with some vDPA drivers (mlx5, + but not with the vdpasim), if we unplug the virtio-net card from + the guest after a stop/start. + + The same fix has been done for vhost-user: + 1f89d3b91e3e ("hw/virtio: Fix leak of host-notifier memory-region") + + Fixes: d0416d487bd5 ("vhost-vdpa: map virtqueue notification area if possible") + Cc: jasowang@redhat.com + Resolves: https://bugzilla.redhat.com/2027208 + Signed-off-by: Laurent Vivier + Message-Id: <20220211170259.1388734-1-lvivier@redhat.com> + Cc: qemu-stable@nongnu.org + Acked-by: Jason Wang + Reviewed-by: Stefano Garzarella + Reviewed-by: Michael S. Tsirkin + Signed-off-by: Michael S. Tsirkin -BZ: https://bugzilla.redhat.com/2027208 -BRANCH: rhel-8.6.0 -UPSTREAM: Merged -BREW: https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=43682903 - -If call virtio_queue_set_host_notifier_mr fails, should free -host-notifier memory-region. - -This problem can trigger a coredump with some vDPA drivers (mlx5, -but not with the vdpasim), if we unplug the virtio-net card from -the guest after a stop/start. - -The same fix has been done for vhost-user: - 1f89d3b91e3e ("hw/virtio: Fix leak of host-notifier memory-region") - -Fixes: d0416d487bd5 ("vhost-vdpa: map virtqueue notification area if possible") -Cc: jasowang@redhat.com -Resolves: https://bugzilla.redhat.com/2027208 -Signed-off-by: Laurent Vivier -Message-Id: <20220211170259.1388734-1-lvivier@redhat.com> -Cc: qemu-stable@nongnu.org -Acked-by: Jason Wang -Reviewed-by: Stefano Garzarella -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Michael S. Tsirkin (cherry picked from commit 98f7607ecda00dea3cbb2ed7b4427c96846efb83) -Signed-off-by: Laurent Vivier +Signed-off-by: Jon Maloy --- hw/virtio/vhost-vdpa.c | 1 + 1 file changed, 1 insertion(+) diff --git a/kvm-i386-Add-Icelake-Server-v6-CPU-model-with-5-level-EP.patch b/kvm-i386-Add-Icelake-Server-v6-CPU-model-with-5-level-EP.patch index 23a9904..540f721 100644 --- a/kvm-i386-Add-Icelake-Server-v6-CPU-model-with-5-level-EP.patch +++ b/kvm-i386-Add-Icelake-Server-v6-CPU-model-with-5-level-EP.patch @@ -1,21 +1,19 @@ -From f2578175ee0e0b0a7a99118e5fdf23ec0ad29ff4 Mon Sep 17 00:00:00 2001 -From: Vitaly Kuznetsov -Date: Wed, 16 Mar 2022 09:48:04 +0100 -Subject: [PATCH 02/12] i386: Add Icelake-Server-v6 CPU model with 5-level EPT +From ccaa1135bd1aa90c94f0e8b5417bd2a420134e6c Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Wed, 30 Mar 2022 14:52:34 -0400 +Subject: [PATCH 08/18] i386: Add Icelake-Server-v6 CPU model with 5-level EPT support -RH-Author: Vitaly Kuznetsov -RH-MergeRequest: 127: i386: Add Icelake-Server-v6 CPU model with 5-level EPT support -RH-Commit: [2/2] 72eaf5608490f5b1fb94b6decb95d4092c57dd85 -RH-Bugzilla: 2056986 +RH-Author: Jon Maloy +RH-MergeRequest: 139: vmxcap: Add 5-level EPT bit +RH-Commit: [2/2] e913746b2df9cbd0308014ab5cc72577458857fa (jmaloy/qemu-kvm) +RH-Bugzilla: 2065207 RH-Acked-by: Paolo Bonzini -RH-Acked-by: Igor Mammedov -RH-Acked-by: Cornelia Huck -Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2056986 -Brew: https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=43862707 +BZ: https://bugzilla.redhat.com/show_bug.cgi?id=2065207 +UPSTREAM: Merged -commit 12cab535db6440af41ed8dfefe908a594321b6ce +commit: 12cab535db6440af41ed8dfefe908a594321b6ce Author: Vitaly Kuznetsov Date: Mon Feb 21 15:53:15 2022 +0100 @@ -31,7 +29,8 @@ Date: Mon Feb 21 15:53:15 2022 +0100 Message-Id: <20220221145316.576138-1-vkuznets@redhat.com> Signed-off-by: Paolo Bonzini -Signed-off-by: Vitaly Kuznetsov +(cherry picked from commit 12cab535db6440af41ed8dfefe908a594321b6ce) +Signed-off-by: Jon Maloy --- target/i386/cpu.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/kvm-i386-do-kvm_put_msr_feature_control-first-thing-when.patch b/kvm-i386-do-kvm_put_msr_feature_control-first-thing-when.patch new file mode 100644 index 0000000..1c2094e --- /dev/null +++ b/kvm-i386-do-kvm_put_msr_feature_control-first-thing-when.patch @@ -0,0 +1,68 @@ +From 1bd939d374ec2e994ff47c84e16fa3bc1323a0fd Mon Sep 17 00:00:00 2001 +From: Vitaly Kuznetsov +Date: Thu, 18 Aug 2022 17:01:13 +0200 +Subject: [PATCH 2/2] i386: do kvm_put_msr_feature_control() first thing when + vCPU is reset + +RH-Author: Vitaly Kuznetsov +RH-MergeRequest: 216: i386: fix 'system_reset' when the VM is in VMX root operation +RH-Bugzilla: 2116743 +RH-Acked-by: Emanuele Giuseppe Esposito +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Peter Xu +RH-Commit: [2/2] f838a57f74487eb394794de00006d5d2b9e84344 + +kvm_put_sregs2() fails to reset 'locked' CR4/CR0 bits upon vCPU reset when +it is in VMX root operation. Do kvm_put_msr_feature_control() before +kvm_put_sregs2() to (possibly) kick vCPU out of VMX root operation. It also +seems logical to do kvm_put_msr_feature_control() before +kvm_put_nested_state() and not after it, especially when 'real' nested +state is set. + +Signed-off-by: Vitaly Kuznetsov +Message-Id: <20220818150113.479917-3-vkuznets@redhat.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit 45ed68a1a3a19754ade954d75a3c9d13ff560e5c) +Signed-off-by: Vitaly Kuznetsov +--- + target/i386/kvm/kvm.c | 17 ++++++++++++----- + 1 file changed, 12 insertions(+), 5 deletions(-) + +diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c +index 81d729dc40..a06221d3e5 100644 +--- a/target/i386/kvm/kvm.c ++++ b/target/i386/kvm/kvm.c +@@ -4255,6 +4255,18 @@ int kvm_arch_put_registers(CPUState *cpu, int level) + + assert(cpu_is_stopped(cpu) || qemu_cpu_is_self(cpu)); + ++ /* ++ * Put MSR_IA32_FEATURE_CONTROL first, this ensures the VM gets out of VMX ++ * root operation upon vCPU reset. kvm_put_msr_feature_control() should also ++ * preceed kvm_put_nested_state() when 'real' nested state is set. ++ */ ++ if (level >= KVM_PUT_RESET_STATE) { ++ ret = kvm_put_msr_feature_control(x86_cpu); ++ if (ret < 0) { ++ return ret; ++ } ++ } ++ + /* must be before kvm_put_nested_state so that EFER.SVME is set */ + ret = kvm_put_sregs(x86_cpu); + if (ret < 0) { +@@ -4266,11 +4278,6 @@ int kvm_arch_put_registers(CPUState *cpu, int level) + if (ret < 0) { + return ret; + } +- +- ret = kvm_put_msr_feature_control(x86_cpu); +- if (ret < 0) { +- return ret; +- } + } + + if (level == KVM_PUT_FULL_STATE) { +-- +2.31.1 + diff --git a/kvm-i386-reset-KVM-nested-state-upon-CPU-reset.patch b/kvm-i386-reset-KVM-nested-state-upon-CPU-reset.patch new file mode 100644 index 0000000..ac5b579 --- /dev/null +++ b/kvm-i386-reset-KVM-nested-state-upon-CPU-reset.patch @@ -0,0 +1,95 @@ +From 4ad00e318f8afbee0e455cfbb6bc693c808d87f3 Mon Sep 17 00:00:00 2001 +From: Vitaly Kuznetsov +Date: Thu, 18 Aug 2022 17:01:12 +0200 +Subject: [PATCH 1/2] i386: reset KVM nested state upon CPU reset + +RH-Author: Vitaly Kuznetsov +RH-MergeRequest: 216: i386: fix 'system_reset' when the VM is in VMX root operation +RH-Bugzilla: 2116743 +RH-Acked-by: Emanuele Giuseppe Esposito +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Peter Xu +RH-Commit: [1/2] 20d2dabeda74b8cd5135228980a2414e66dc64f3 + +Make sure env->nested_state is cleaned up when a vCPU is reset, it may +be stale after an incoming migration, kvm_arch_put_registers() may +end up failing or putting vCPU in a weird state. + +Reviewed-by: Maxim Levitsky +Signed-off-by: Vitaly Kuznetsov +Message-Id: <20220818150113.479917-2-vkuznets@redhat.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit 3cafdb67504a34a0305260f0c86a73d5a3fb000b) +Signed-off-by: Vitaly Kuznetsov +--- + target/i386/kvm/kvm.c | 37 +++++++++++++++++++++++++++---------- + 1 file changed, 27 insertions(+), 10 deletions(-) + +diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c +index bd439e56ad..81d729dc40 100644 +--- a/target/i386/kvm/kvm.c ++++ b/target/i386/kvm/kvm.c +@@ -1615,6 +1615,30 @@ static void kvm_init_xsave(CPUX86State *env) + env->xsave_buf_len); + } + ++static void kvm_init_nested_state(CPUX86State *env) ++{ ++ struct kvm_vmx_nested_state_hdr *vmx_hdr; ++ uint32_t size; ++ ++ if (!env->nested_state) { ++ return; ++ } ++ ++ size = env->nested_state->size; ++ ++ memset(env->nested_state, 0, size); ++ env->nested_state->size = size; ++ ++ if (cpu_has_vmx(env)) { ++ env->nested_state->format = KVM_STATE_NESTED_FORMAT_VMX; ++ vmx_hdr = &env->nested_state->hdr.vmx; ++ vmx_hdr->vmxon_pa = -1ull; ++ vmx_hdr->vmcs12_pa = -1ull; ++ } else if (cpu_has_svm(env)) { ++ env->nested_state->format = KVM_STATE_NESTED_FORMAT_SVM; ++ } ++} ++ + int kvm_arch_init_vcpu(CPUState *cs) + { + struct { +@@ -2042,19 +2066,10 @@ int kvm_arch_init_vcpu(CPUState *cs) + assert(max_nested_state_len >= offsetof(struct kvm_nested_state, data)); + + if (cpu_has_vmx(env) || cpu_has_svm(env)) { +- struct kvm_vmx_nested_state_hdr *vmx_hdr; +- + env->nested_state = g_malloc0(max_nested_state_len); + env->nested_state->size = max_nested_state_len; + +- if (cpu_has_vmx(env)) { +- env->nested_state->format = KVM_STATE_NESTED_FORMAT_VMX; +- vmx_hdr = &env->nested_state->hdr.vmx; +- vmx_hdr->vmxon_pa = -1ull; +- vmx_hdr->vmcs12_pa = -1ull; +- } else { +- env->nested_state->format = KVM_STATE_NESTED_FORMAT_SVM; +- } ++ kvm_init_nested_state(env); + } + } + +@@ -2117,6 +2132,8 @@ void kvm_arch_reset_vcpu(X86CPU *cpu) + /* enabled by default */ + env->poll_control_msr = 1; + ++ kvm_init_nested_state(env); ++ + sev_es_set_reset_vector(CPU(cpu)); + } + +-- +2.31.1 + diff --git a/kvm-ide-Increment-BB-in-flight-counter-for-TRIM-BH.patch b/kvm-ide-Increment-BB-in-flight-counter-for-TRIM-BH.patch new file mode 100644 index 0000000..6af2a9f --- /dev/null +++ b/kvm-ide-Increment-BB-in-flight-counter-for-TRIM-BH.patch @@ -0,0 +1,92 @@ +From eaade87072e903cf550dfdb8ed1480dddc6bb0e3 Mon Sep 17 00:00:00 2001 +From: Hanna Reitz +Date: Thu, 20 Jan 2022 15:22:59 +0100 +Subject: [PATCH 21/24] ide: Increment BB in-flight counter for TRIM BH +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Hanna Reitz +RH-MergeRequest: 188: ide: Increment BB in-flight counter for TRIM BH +RH-Commit: [1/1] 1e702e735ff63f2b8b69c20cac1b309dd085cd62 +RH-Bugzilla: 2029980 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Kevin Wolf +RH-Acked-by: Paolo Bonzini + +When we still have an AIOCB registered for DMA operations, we try to +settle the respective operation by draining the BlockBackend associated +with the IDE device. + +However, this assumes that every DMA operation is associated with an +increment of the BlockBackend’s in-flight counter (e.g. through some +ongoing I/O operation), so that draining the BB until its in-flight +counter reaches 0 will settle all DMA operations. That is not the case: +For TRIM, the guest can issue a zero-length operation that will not +result in any I/O operation forwarded to the BlockBackend, and also not +increment the in-flight counter in any other way. In such a case, +blk_drain() will be a no-op if no other operations are in flight. + +It is clear that if blk_drain() is a no-op, the value of +s->bus->dma->aiocb will not change between checking it in the `if` +condition and asserting that it is NULL after blk_drain(). + +The particular problem is that ide_issue_trim() creates a BH +(ide_trim_bh_cb()) to settle the TRIM request: iocb->common.cb() is +ide_dma_cb(), which will either create a new request, or find the +transfer to be done and call ide_set_inactive(), which clears +s->bus->dma->aiocb. Therefore, the blk_drain() must wait for +ide_trim_bh_cb() to run, which currently it will not always do. + +To fix this issue, we increment the BlockBackend's in-flight counter +when the TRIM operation begins (in ide_issue_trim(), when the +ide_trim_bh_cb() BH is created) and decrement it when ide_trim_bh_cb() +is done. + +Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=2029980 +Suggested-by: Paolo Bonzini +Signed-off-by: Hanna Reitz +Message-Id: <20220120142259.120189-1-hreitz@redhat.com> +Reviewed-by: Paolo Bonzini +Reviewed-by: John Snow +Tested-by: John Snow +(cherry picked from commit 7e5cdb345f77d76cb4877fe6230c4e17a7d0d0ca) +Signed-off-by: Hanna Reitz +--- + hw/ide/core.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/hw/ide/core.c b/hw/ide/core.c +index e28f8aad61..15138225be 100644 +--- a/hw/ide/core.c ++++ b/hw/ide/core.c +@@ -433,12 +433,16 @@ static const AIOCBInfo trim_aiocb_info = { + static void ide_trim_bh_cb(void *opaque) + { + TrimAIOCB *iocb = opaque; ++ BlockBackend *blk = iocb->s->blk; + + iocb->common.cb(iocb->common.opaque, iocb->ret); + + qemu_bh_delete(iocb->bh); + iocb->bh = NULL; + qemu_aio_unref(iocb); ++ ++ /* Paired with an increment in ide_issue_trim() */ ++ blk_dec_in_flight(blk); + } + + static void ide_issue_trim_cb(void *opaque, int ret) +@@ -508,6 +512,9 @@ BlockAIOCB *ide_issue_trim( + IDEState *s = opaque; + TrimAIOCB *iocb; + ++ /* Paired with a decrement in ide_trim_bh_cb() */ ++ blk_inc_in_flight(s->blk); ++ + iocb = blk_aio_get(&trim_aiocb_info, s->blk, cb, cb_opaque); + iocb->s = s; + iocb->bh = qemu_bh_new(ide_trim_bh_cb, iocb); +-- +2.35.3 + diff --git a/kvm-iotests-108-Fix-when-missing-user_allow_other.patch b/kvm-iotests-108-Fix-when-missing-user_allow_other.patch index f50104d..0d652dd 100644 --- a/kvm-iotests-108-Fix-when-missing-user_allow_other.patch +++ b/kvm-iotests-108-Fix-when-missing-user_allow_other.patch @@ -1,15 +1,15 @@ -From f663b951b87735bee6b5a4d75b726f609e557f8c Mon Sep 17 00:00:00 2001 +From 676e19198916d7631ba1367646dd08dc72079f88 Mon Sep 17 00:00:00 2001 From: Hanna Reitz Date: Thu, 21 Apr 2022 16:24:35 +0200 -Subject: [PATCH 11/11] iotests/108: Fix when missing user_allow_other +Subject: [PATCH 6/6] iotests/108: Fix when missing user_allow_other RH-Author: Hanna Reitz -RH-MergeRequest: 173: qcow2: Improve refcount structure rebuilding -RH-Commit: [4/4] cea00f9cb38639d4c51fab13c20311d1737d5ca3 -RH-Bugzilla: 2072242 +RH-MergeRequest: 171: qcow2: Improve refcount structure rebuilding +RH-Commit: [4/4] 36b70b5378ae7c8084b9e847706f00003abe9c11 +RH-Bugzilla: 1519071 RH-Acked-by: Miroslav Rezanina -RH-Acked-by: Eric Blake RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Eric Blake FUSE exports' allow-other option defaults to "auto", which means that it will try passing allow_other as a mount option, and fall back to not diff --git a/kvm-iotests-108-Test-new-refcount-rebuild-algorithm.patch b/kvm-iotests-108-Test-new-refcount-rebuild-algorithm.patch index 288557c..cc67d7c 100644 --- a/kvm-iotests-108-Test-new-refcount-rebuild-algorithm.patch +++ b/kvm-iotests-108-Test-new-refcount-rebuild-algorithm.patch @@ -1,15 +1,15 @@ -From a5cc7f98669fbde7290fc363cb61dc7bd41718f3 Mon Sep 17 00:00:00 2001 +From d638552d76db0db9e2b6ae90a35f0b451b0cbaf8 Mon Sep 17 00:00:00 2001 From: Hanna Reitz Date: Tue, 5 Apr 2022 15:46:51 +0200 -Subject: [PATCH 09/11] iotests/108: Test new refcount rebuild algorithm +Subject: [PATCH 4/6] iotests/108: Test new refcount rebuild algorithm RH-Author: Hanna Reitz -RH-MergeRequest: 173: qcow2: Improve refcount structure rebuilding -RH-Commit: [2/4] db808dcc1c5ee9fd901c0800b3fac1348fab246f -RH-Bugzilla: 2072242 +RH-MergeRequest: 171: qcow2: Improve refcount structure rebuilding +RH-Commit: [2/4] 2aa8c383f0c88c414f10ade8bd2e8af07c35f35b +RH-Bugzilla: 1519071 RH-Acked-by: Miroslav Rezanina -RH-Acked-by: Eric Blake RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Eric Blake One clear problem with how qcow2's refcount structure rebuild algorithm used to be before "qcow2: Improve refcount structure rebuilding" was diff --git a/kvm-iotests-Allow-using-QMP-with-the-QSD.patch b/kvm-iotests-Allow-using-QMP-with-the-QSD.patch new file mode 100644 index 0000000..5d45438 --- /dev/null +++ b/kvm-iotests-Allow-using-QMP-with-the-QSD.patch @@ -0,0 +1,99 @@ +From 12f596b66d577eb92f154fadf734d058dd0756d6 Mon Sep 17 00:00:00 2001 +From: Hanna Reitz +Date: Wed, 16 Feb 2022 11:53:54 +0100 +Subject: [PATCH 23/24] iotests: Allow using QMP with the QSD + +RH-Author: Hanna Reitz +RH-MergeRequest: 189: block: Make bdrv_refresh_limits() non-recursive +RH-Commit: [2/3] 55bee4690a2e02d3be9f2bd68f2d244d0a36743b +RH-Bugzilla: 2072932 +RH-Acked-by: Eric Blake +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Kevin Wolf + +Add a parameter to optionally open a QMP connection when creating a +QemuStorageDaemon instance. + +Signed-off-by: Hanna Reitz +Message-Id: <20220216105355.30729-3-hreitz@redhat.com> +Reviewed-by: Eric Blake +Reviewed-by: Stefan Hajnoczi +Signed-off-by: Kevin Wolf +(cherry picked from commit ec88eed8d14088b36a3495710368b8d1a3c33420) +Signed-off-by: Hanna Reitz +--- + tests/qemu-iotests/iotests.py | 32 +++++++++++++++++++++++++++++++- + 1 file changed, 31 insertions(+), 1 deletion(-) + +diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py +index a51b5ce8cd..2ef493755c 100644 +--- a/tests/qemu-iotests/iotests.py ++++ b/tests/qemu-iotests/iotests.py +@@ -38,6 +38,7 @@ + + from qemu.machine import qtest + from qemu.qmp import QMPMessage ++from qemu.aqmp.legacy import QEMUMonitorProtocol + + # Use this logger for logging messages directly from the iotests module + logger = logging.getLogger('qemu.iotests') +@@ -315,14 +316,30 @@ def cmd(self, cmd): + + + class QemuStorageDaemon: +- def __init__(self, *args: str, instance_id: str = 'a'): ++ _qmp: Optional[QEMUMonitorProtocol] = None ++ _qmpsock: Optional[str] = None ++ # Python < 3.8 would complain if this type were not a string literal ++ # (importing `annotations` from `__future__` would work; but not on <= 3.6) ++ _p: 'Optional[subprocess.Popen[bytes]]' = None ++ ++ def __init__(self, *args: str, instance_id: str = 'a', qmp: bool = False): + assert '--pidfile' not in args + self.pidfile = os.path.join(test_dir, f'qsd-{instance_id}-pid') + all_args = [qsd_prog] + list(args) + ['--pidfile', self.pidfile] + ++ if qmp: ++ self._qmpsock = os.path.join(sock_dir, f'qsd-{instance_id}.sock') ++ all_args += ['--chardev', ++ f'socket,id=qmp-sock,path={self._qmpsock}', ++ '--monitor', 'qmp-sock'] ++ ++ self._qmp = QEMUMonitorProtocol(self._qmpsock, server=True) ++ + # Cannot use with here, we want the subprocess to stay around + # pylint: disable=consider-using-with + self._p = subprocess.Popen(all_args) ++ if self._qmp is not None: ++ self._qmp.accept() + while not os.path.exists(self.pidfile): + if self._p.poll() is not None: + cmd = ' '.join(all_args) +@@ -337,11 +354,24 @@ def __init__(self, *args: str, instance_id: str = 'a'): + + assert self._pid == self._p.pid + ++ def qmp(self, cmd: str, args: Optional[Dict[str, object]] = None) \ ++ -> QMPMessage: ++ assert self._qmp is not None ++ return self._qmp.cmd(cmd, args) ++ + def stop(self, kill_signal=15): + self._p.send_signal(kill_signal) + self._p.wait() + self._p = None + ++ if self._qmp: ++ self._qmp.close() ++ ++ if self._qmpsock is not None: ++ try: ++ os.remove(self._qmpsock) ++ except OSError: ++ pass + try: + os.remove(self.pidfile) + except OSError: +-- +2.35.3 + diff --git a/kvm-iotests-Test-blockdev-reopen-with-iothreads-and-thro.patch b/kvm-iotests-Test-blockdev-reopen-with-iothreads-and-thro.patch new file mode 100644 index 0000000..1caf73c --- /dev/null +++ b/kvm-iotests-Test-blockdev-reopen-with-iothreads-and-thro.patch @@ -0,0 +1,106 @@ +From ea4d8424fb2053b1cbb9538190b2b06351054125 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Thu, 3 Feb 2022 15:05:34 +0100 +Subject: [PATCH 3/5] iotests: Test blockdev-reopen with iothreads and + throttling + +RH-Author: Kevin Wolf +RH-MergeRequest: 142: block: Lock AioContext for drain_end in blockdev-reopen +RH-Commit: [2/2] 91d365864c391ca7db7db13260913fb61987b833 +RH-Bugzilla: 2067118 +RH-Acked-by: Emanuele Giuseppe Esposito +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Hanna Reitz + +The 'throttle' block driver implements .bdrv_co_drain_end, so +blockdev-reopen will have to wait for it to complete in the polling +loop at the end of qmp_blockdev_reopen(). This makes AIO_WAIT_WHILE() +release the AioContext lock, which causes a crash if the lock hasn't +correctly been taken. + +Signed-off-by: Kevin Wolf +Message-Id: <20220203140534.36522-3-kwolf@redhat.com> +Reviewed-by: Hanna Reitz +Signed-off-by: Kevin Wolf +(cherry picked from commit ee810602376125ca0e0afd6b7c715e13740978ea) +Signed-off-by: Kevin Wolf +--- + tests/qemu-iotests/245 | 36 +++++++++++++++++++++++++++++++++--- + tests/qemu-iotests/245.out | 4 ++-- + 2 files changed, 35 insertions(+), 5 deletions(-) + +diff --git a/tests/qemu-iotests/245 b/tests/qemu-iotests/245 +index 24ac43f70e..8cbed7821b 100755 +--- a/tests/qemu-iotests/245 ++++ b/tests/qemu-iotests/245 +@@ -1138,12 +1138,13 @@ class TestBlockdevReopen(iotests.QMPTestCase): + self.assertEqual(self.get_node('hd1'), None) + self.assert_qmp(self.get_node('hd2'), 'ro', True) + +- def run_test_iothreads(self, iothread_a, iothread_b, errmsg = None): +- opts = hd_opts(0) ++ def run_test_iothreads(self, iothread_a, iothread_b, errmsg = None, ++ opts_a = None, opts_b = None): ++ opts = opts_a or hd_opts(0) + result = self.vm.qmp('blockdev-add', conv_keys = False, **opts) + self.assert_qmp(result, 'return', {}) + +- opts2 = hd_opts(2) ++ opts2 = opts_b or hd_opts(2) + result = self.vm.qmp('blockdev-add', conv_keys = False, **opts2) + self.assert_qmp(result, 'return', {}) + +@@ -1194,6 +1195,35 @@ class TestBlockdevReopen(iotests.QMPTestCase): + def test_iothreads_switch_overlay(self): + self.run_test_iothreads('', 'iothread0') + ++ def test_iothreads_with_throttling(self): ++ # Create a throttle-group object ++ opts = { 'qom-type': 'throttle-group', 'id': 'group0', ++ 'limits': { 'iops-total': 1000 } } ++ result = self.vm.qmp('object-add', conv_keys = False, **opts) ++ self.assert_qmp(result, 'return', {}) ++ ++ # Options with a throttle filter between format and protocol ++ opts = [ ++ { ++ 'driver': iotests.imgfmt, ++ 'node-name': f'hd{idx}', ++ 'file' : { ++ 'node-name': f'hd{idx}-throttle', ++ 'driver': 'throttle', ++ 'throttle-group': 'group0', ++ 'file': { ++ 'driver': 'file', ++ 'node-name': f'hd{idx}-file', ++ 'filename': hd_path[idx], ++ }, ++ }, ++ } ++ for idx in (0, 2) ++ ] ++ ++ self.run_test_iothreads('iothread0', 'iothread0', None, ++ opts[0], opts[1]) ++ + if __name__ == '__main__': + iotests.activate_logging() + iotests.main(supported_fmts=["qcow2"], +diff --git a/tests/qemu-iotests/245.out b/tests/qemu-iotests/245.out +index 4eced19294..a4e04a3266 100644 +--- a/tests/qemu-iotests/245.out ++++ b/tests/qemu-iotests/245.out +@@ -17,8 +17,8 @@ read 1/1 bytes at offset 262152 + read 1/1 bytes at offset 262160 + 1 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +-............... ++................ + ---------------------------------------------------------------------- +-Ran 25 tests ++Ran 26 tests + + OK +-- +2.27.0 + diff --git a/kvm-iotests-graph-changes-while-io-New-test.patch b/kvm-iotests-graph-changes-while-io-New-test.patch new file mode 100644 index 0000000..d40e25e --- /dev/null +++ b/kvm-iotests-graph-changes-while-io-New-test.patch @@ -0,0 +1,153 @@ +From 27042ff7aca4366c50e8ed66b47487d46774d16a Mon Sep 17 00:00:00 2001 +From: Hanna Reitz +Date: Wed, 16 Feb 2022 11:53:55 +0100 +Subject: [PATCH 24/24] iotests/graph-changes-while-io: New test + +RH-Author: Hanna Reitz +RH-MergeRequest: 189: block: Make bdrv_refresh_limits() non-recursive +RH-Commit: [3/3] b9dffe09bef6cf9b2f0aad69b327ea1df92e847a +RH-Bugzilla: 2072932 +RH-Acked-by: Eric Blake +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Kevin Wolf + +Test the following scenario: +1. Some block node (null-co) attached to a user (here: NBD server) that + performs I/O and keeps the node in an I/O thread +2. Repeatedly run blockdev-add/blockdev-del to add/remove an overlay + to/from that node + +Each blockdev-add triggers bdrv_refresh_limits(), and because +blockdev-add runs in the main thread, it does not stop the I/O requests. +I/O can thus happen while the limits are refreshed, and when such a +request sees a temporarily invalid block limit (e.g. alignment is 0), +this may easily crash qemu (or the storage daemon in this case). + +The block layer needs to ensure that I/O requests to a node are paused +while that node's BlockLimits are refreshed. + +Signed-off-by: Hanna Reitz +Reviewed-by: Eric Blake +Message-Id: <20220216105355.30729-4-hreitz@redhat.com> +Reviewed-by: Stefan Hajnoczi +Signed-off-by: Kevin Wolf +(cherry picked from commit 971bea8089531af56b1bbd9ce62e756bdf006711) +Signed-off-by: Hanna Reitz +--- + .../qemu-iotests/tests/graph-changes-while-io | 91 +++++++++++++++++++ + .../tests/graph-changes-while-io.out | 5 + + 2 files changed, 96 insertions(+) + create mode 100755 tests/qemu-iotests/tests/graph-changes-while-io + create mode 100644 tests/qemu-iotests/tests/graph-changes-while-io.out + +diff --git a/tests/qemu-iotests/tests/graph-changes-while-io b/tests/qemu-iotests/tests/graph-changes-while-io +new file mode 100755 +index 0000000000..567e8cf21e +--- /dev/null ++++ b/tests/qemu-iotests/tests/graph-changes-while-io +@@ -0,0 +1,91 @@ ++#!/usr/bin/env python3 ++# group: rw ++# ++# Test graph changes while I/O is happening ++# ++# Copyright (C) 2022 Red Hat, Inc. ++# ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 2 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see . ++# ++ ++import os ++from threading import Thread ++import iotests ++from iotests import imgfmt, qemu_img, qemu_img_create, QMPTestCase, \ ++ QemuStorageDaemon ++ ++ ++top = os.path.join(iotests.test_dir, 'top.img') ++nbd_sock = os.path.join(iotests.sock_dir, 'nbd.sock') ++ ++ ++def do_qemu_img_bench() -> None: ++ """ ++ Do some I/O requests on `nbd_sock`. ++ """ ++ assert qemu_img('bench', '-f', 'raw', '-c', '2000000', ++ f'nbd+unix:///node0?socket={nbd_sock}') == 0 ++ ++ ++class TestGraphChangesWhileIO(QMPTestCase): ++ def setUp(self) -> None: ++ # Create an overlay that can be added at runtime on top of the ++ # null-co block node that will receive I/O ++ assert qemu_img_create('-f', imgfmt, '-F', 'raw', '-b', 'null-co://', ++ top) == 0 ++ ++ # QSD instance with a null-co block node in an I/O thread, ++ # exported over NBD (on `nbd_sock`, export name "node0") ++ self.qsd = QemuStorageDaemon( ++ '--object', 'iothread,id=iothread0', ++ '--blockdev', 'null-co,node-name=node0,read-zeroes=true', ++ '--nbd-server', f'addr.type=unix,addr.path={nbd_sock}', ++ '--export', 'nbd,id=exp0,node-name=node0,iothread=iothread0,' + ++ 'fixed-iothread=true,writable=true', ++ qmp=True ++ ) ++ ++ def tearDown(self) -> None: ++ self.qsd.stop() ++ ++ def test_blockdev_add_while_io(self) -> None: ++ # Run qemu-img bench in the background ++ bench_thr = Thread(target=do_qemu_img_bench) ++ bench_thr.start() ++ ++ # While qemu-img bench is running, repeatedly add and remove an ++ # overlay to/from node0 ++ while bench_thr.is_alive(): ++ result = self.qsd.qmp('blockdev-add', { ++ 'driver': imgfmt, ++ 'node-name': 'overlay', ++ 'backing': 'node0', ++ 'file': { ++ 'driver': 'file', ++ 'filename': top ++ } ++ }) ++ self.assert_qmp(result, 'return', {}) ++ ++ result = self.qsd.qmp('blockdev-del', { ++ 'node-name': 'overlay' ++ }) ++ self.assert_qmp(result, 'return', {}) ++ ++ bench_thr.join() ++ ++if __name__ == '__main__': ++ # Format must support raw backing files ++ iotests.main(supported_fmts=['qcow', 'qcow2', 'qed'], ++ supported_protocols=['file']) +diff --git a/tests/qemu-iotests/tests/graph-changes-while-io.out b/tests/qemu-iotests/tests/graph-changes-while-io.out +new file mode 100644 +index 0000000000..ae1213e6f8 +--- /dev/null ++++ b/tests/qemu-iotests/tests/graph-changes-while-io.out +@@ -0,0 +1,5 @@ ++. ++---------------------------------------------------------------------- ++Ran 1 tests ++ ++OK +-- +2.35.3 + diff --git a/kvm-linux-aio-explain-why-max-batch-is-checked-in-laio_i.patch b/kvm-linux-aio-explain-why-max-batch-is-checked-in-laio_i.patch index 1266128..7c1fcc4 100644 --- a/kvm-linux-aio-explain-why-max-batch-is-checked-in-laio_i.patch +++ b/kvm-linux-aio-explain-why-max-batch-is-checked-in-laio_i.patch @@ -1,15 +1,15 @@ -From 286d9e4512a3b7ab6e2a1ce6b4a872e5defb0ffe Mon Sep 17 00:00:00 2001 +From 99d33621440fd30e0da2974dafb0cd372334305a Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Thu, 9 Jun 2022 17:47:12 +0100 Subject: [PATCH 2/2] linux-aio: explain why max batch is checked in laio_io_unplug() RH-Author: Stefan Hajnoczi -RH-MergeRequest: 209: linux-aio: fix unbalanced plugged counter in laio_io_unplug() -RH-Commit: [2/2] c6194a9929e7e3807c5402b5364ab9dc2edf420c -RH-Bugzilla: 2109570 +RH-MergeRequest: 199: linux-aio: fix unbalanced plugged counter in laio_io_unplug() +RH-Commit: [2/2] 8617870ed70e3a57269f06eeb242d0fab79a66fb +RH-Bugzilla: 2105410 +RH-Acked-by: Miroslav Rezanina RH-Acked-by: Hanna Reitz -RH-Acked-by: Kevin Wolf RH-Acked-by: Stefano Garzarella It may not be obvious why laio_io_unplug() checks max batch. I discussed diff --git a/kvm-linux-aio-fix-unbalanced-plugged-counter-in-laio_io_.patch b/kvm-linux-aio-fix-unbalanced-plugged-counter-in-laio_io_.patch index d01fe33..c89fc72 100644 --- a/kvm-linux-aio-fix-unbalanced-plugged-counter-in-laio_io_.patch +++ b/kvm-linux-aio-fix-unbalanced-plugged-counter-in-laio_io_.patch @@ -1,15 +1,15 @@ -From ad1844e7e2294fa71bc07f9d1da6d10150ba9607 Mon Sep 17 00:00:00 2001 +From 0fbb0c87628bef2cb4d1b7748d67020dde50cdef Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Thu, 9 Jun 2022 17:47:11 +0100 Subject: [PATCH 1/2] linux-aio: fix unbalanced plugged counter in laio_io_unplug() RH-Author: Stefan Hajnoczi -RH-MergeRequest: 209: linux-aio: fix unbalanced plugged counter in laio_io_unplug() -RH-Commit: [1/2] 3a73bdb8237cf99c5264a6e1caac632494412953 -RH-Bugzilla: 2109570 +RH-MergeRequest: 199: linux-aio: fix unbalanced plugged counter in laio_io_unplug() +RH-Commit: [1/2] f518df755090289905898a36922992288688e338 +RH-Bugzilla: 2105410 +RH-Acked-by: Miroslav Rezanina RH-Acked-by: Hanna Reitz -RH-Acked-by: Kevin Wolf RH-Acked-by: Stefano Garzarella Every laio_io_plug() call has a matching laio_io_unplug() call. There is diff --git a/kvm-linux-headers-Update-headers-to-v5.17-rc1.patch b/kvm-linux-headers-Update-headers-to-v5.17-rc1.patch new file mode 100644 index 0000000..90adb5c --- /dev/null +++ b/kvm-linux-headers-Update-headers-to-v5.17-rc1.patch @@ -0,0 +1,1227 @@ +From e9ecd7543fa8d3e9fe80f4144e4c0461f783fc37 Mon Sep 17 00:00:00 2001 +From: Vivek Goyal +Date: Tue, 8 Feb 2022 15:48:05 -0500 +Subject: [PATCH 03/24] linux-headers: Update headers to v5.17-rc1 + +RH-Author: Paul Lai +RH-MergeRequest: 176: Enable KVM AMX support +RH-Commit: [3/13] 63593c2431eabf02222f37467736b580022b94c8 +RH-Bugzilla: 1916415 +RH-Acked-by: Cornelia Huck +RH-Acked-by: Igor Mammedov +RH-Acked-by: Paolo Bonzini + +Update headers to 5.17-rc1. I need latest fuse changes. + +Reviewed-by: Dr. David Alan Gilbert +Signed-off-by: Vivek Goyal +Message-Id: <20220208204813.682906-3-vgoyal@redhat.com> +Signed-off-by: Dr. David Alan Gilbert +(cherry picked from commit ef17dd6a8e6b6e3aeb29233996d44dfcb736d515) +Signed-off-by: Paul Lai +--- + include/standard-headers/asm-x86/kvm_para.h | 1 + + include/standard-headers/drm/drm_fourcc.h | 11 ++ + include/standard-headers/linux/ethtool.h | 1 + + include/standard-headers/linux/fuse.h | 60 +++++++- + include/standard-headers/linux/pci_regs.h | 142 +++++++++--------- + include/standard-headers/linux/virtio_gpio.h | 72 +++++++++ + include/standard-headers/linux/virtio_i2c.h | 47 ++++++ + include/standard-headers/linux/virtio_iommu.h | 8 +- + .../standard-headers/linux/virtio_pcidev.h | 65 ++++++++ + include/standard-headers/linux/virtio_scmi.h | 24 +++ + linux-headers/asm-generic/unistd.h | 5 +- + linux-headers/asm-mips/unistd_n32.h | 2 + + linux-headers/asm-mips/unistd_n64.h | 2 + + linux-headers/asm-mips/unistd_o32.h | 2 + + linux-headers/asm-powerpc/unistd_32.h | 2 + + linux-headers/asm-powerpc/unistd_64.h | 2 + + linux-headers/asm-riscv/bitsperlong.h | 14 ++ + linux-headers/asm-riscv/mman.h | 1 + + linux-headers/asm-riscv/unistd.h | 44 ++++++ + linux-headers/asm-s390/unistd_32.h | 2 + + linux-headers/asm-s390/unistd_64.h | 2 + + linux-headers/asm-x86/kvm.h | 16 +- + linux-headers/asm-x86/unistd_32.h | 1 + + linux-headers/asm-x86/unistd_64.h | 1 + + linux-headers/asm-x86/unistd_x32.h | 1 + + linux-headers/linux/kvm.h | 17 +++ + 26 files changed, 469 insertions(+), 76 deletions(-) + create mode 100644 include/standard-headers/linux/virtio_gpio.h + create mode 100644 include/standard-headers/linux/virtio_i2c.h + create mode 100644 include/standard-headers/linux/virtio_pcidev.h + create mode 100644 include/standard-headers/linux/virtio_scmi.h + create mode 100644 linux-headers/asm-riscv/bitsperlong.h + create mode 100644 linux-headers/asm-riscv/mman.h + create mode 100644 linux-headers/asm-riscv/unistd.h + +diff --git a/include/standard-headers/asm-x86/kvm_para.h b/include/standard-headers/asm-x86/kvm_para.h +index 204cfb8640..f0235e58a1 100644 +--- a/include/standard-headers/asm-x86/kvm_para.h ++++ b/include/standard-headers/asm-x86/kvm_para.h +@@ -8,6 +8,7 @@ + * should be used to determine that a VM is running under KVM. + */ + #define KVM_CPUID_SIGNATURE 0x40000000 ++#define KVM_SIGNATURE "KVMKVMKVM\0\0\0" + + /* This CPUID returns two feature bitmaps in eax, edx. Before enabling + * a particular paravirtualization, the appropriate feature bit should +diff --git a/include/standard-headers/drm/drm_fourcc.h b/include/standard-headers/drm/drm_fourcc.h +index 2c025cb4fe..4888f85f69 100644 +--- a/include/standard-headers/drm/drm_fourcc.h ++++ b/include/standard-headers/drm/drm_fourcc.h +@@ -313,6 +313,13 @@ extern "C" { + */ + #define DRM_FORMAT_P016 fourcc_code('P', '0', '1', '6') /* 2x2 subsampled Cr:Cb plane 16 bits per channel */ + ++/* 2 plane YCbCr420. ++ * 3 10 bit components and 2 padding bits packed into 4 bytes. ++ * index 0 = Y plane, [31:0] x:Y2:Y1:Y0 2:10:10:10 little endian ++ * index 1 = Cr:Cb plane, [63:0] x:Cr2:Cb2:Cr1:x:Cb1:Cr0:Cb0 [2:10:10:10:2:10:10:10] little endian ++ */ ++#define DRM_FORMAT_P030 fourcc_code('P', '0', '3', '0') /* 2x2 subsampled Cr:Cb plane 10 bits per channel packed */ ++ + /* 3 plane non-subsampled (444) YCbCr + * 16 bits per component, but only 10 bits are used and 6 bits are padded + * index 0: Y plane, [15:0] Y:x [10:6] little endian +@@ -853,6 +860,10 @@ drm_fourcc_canonicalize_nvidia_format_mod(uint64_t modifier) + * and UV. Some SAND-using hardware stores UV in a separate tiled + * image from Y to reduce the column height, which is not supported + * with these modifiers. ++ * ++ * The DRM_FORMAT_MOD_BROADCOM_SAND128_COL_HEIGHT modifier is also ++ * supported for DRM_FORMAT_P030 where the columns remain as 128 bytes ++ * wide, but as this is a 10 bpp format that translates to 96 pixels. + */ + + #define DRM_FORMAT_MOD_BROADCOM_SAND32_COL_HEIGHT(v) \ +diff --git a/include/standard-headers/linux/ethtool.h b/include/standard-headers/linux/ethtool.h +index 688eb8dc39..38d5a4cd6e 100644 +--- a/include/standard-headers/linux/ethtool.h ++++ b/include/standard-headers/linux/ethtool.h +@@ -231,6 +231,7 @@ enum tunable_id { + ETHTOOL_RX_COPYBREAK, + ETHTOOL_TX_COPYBREAK, + ETHTOOL_PFC_PREVENTION_TOUT, /* timeout in msecs */ ++ ETHTOOL_TX_COPYBREAK_BUF_SIZE, + /* + * Add your fresh new tunable attribute above and remember to update + * tunable_strings[] in net/ethtool/common.c +diff --git a/include/standard-headers/linux/fuse.h b/include/standard-headers/linux/fuse.h +index 23ea31708b..bda06258be 100644 +--- a/include/standard-headers/linux/fuse.h ++++ b/include/standard-headers/linux/fuse.h +@@ -184,6 +184,16 @@ + * + * 7.34 + * - add FUSE_SYNCFS ++ * ++ * 7.35 ++ * - add FOPEN_NOFLUSH ++ * ++ * 7.36 ++ * - extend fuse_init_in with reserved fields, add FUSE_INIT_EXT init flag ++ * - add flags2 to fuse_init_in and fuse_init_out ++ * - add FUSE_SECURITY_CTX init flag ++ * - add security context to create, mkdir, symlink, and mknod requests ++ * - add FUSE_HAS_INODE_DAX, FUSE_ATTR_DAX + */ + + #ifndef _LINUX_FUSE_H +@@ -215,7 +225,7 @@ + #define FUSE_KERNEL_VERSION 7 + + /** Minor version number of this interface */ +-#define FUSE_KERNEL_MINOR_VERSION 34 ++#define FUSE_KERNEL_MINOR_VERSION 36 + + /** The node ID of the root inode */ + #define FUSE_ROOT_ID 1 +@@ -286,12 +296,14 @@ struct fuse_file_lock { + * FOPEN_NONSEEKABLE: the file is not seekable + * FOPEN_CACHE_DIR: allow caching this directory + * FOPEN_STREAM: the file is stream-like (no file position at all) ++ * FOPEN_NOFLUSH: don't flush data cache on close (unless FUSE_WRITEBACK_CACHE) + */ + #define FOPEN_DIRECT_IO (1 << 0) + #define FOPEN_KEEP_CACHE (1 << 1) + #define FOPEN_NONSEEKABLE (1 << 2) + #define FOPEN_CACHE_DIR (1 << 3) + #define FOPEN_STREAM (1 << 4) ++#define FOPEN_NOFLUSH (1 << 5) + + /** + * INIT request/reply flags +@@ -332,6 +344,11 @@ struct fuse_file_lock { + * write/truncate sgid is killed only if file has group + * execute permission. (Same as Linux VFS behavior). + * FUSE_SETXATTR_EXT: Server supports extended struct fuse_setxattr_in ++ * FUSE_INIT_EXT: extended fuse_init_in request ++ * FUSE_INIT_RESERVED: reserved, do not use ++ * FUSE_SECURITY_CTX: add security context to create, mkdir, symlink, and ++ * mknod ++ * FUSE_HAS_INODE_DAX: use per inode DAX + */ + #define FUSE_ASYNC_READ (1 << 0) + #define FUSE_POSIX_LOCKS (1 << 1) +@@ -363,6 +380,11 @@ struct fuse_file_lock { + #define FUSE_SUBMOUNTS (1 << 27) + #define FUSE_HANDLE_KILLPRIV_V2 (1 << 28) + #define FUSE_SETXATTR_EXT (1 << 29) ++#define FUSE_INIT_EXT (1 << 30) ++#define FUSE_INIT_RESERVED (1 << 31) ++/* bits 32..63 get shifted down 32 bits into the flags2 field */ ++#define FUSE_SECURITY_CTX (1ULL << 32) ++#define FUSE_HAS_INODE_DAX (1ULL << 33) + + /** + * CUSE INIT request/reply flags +@@ -445,8 +467,10 @@ struct fuse_file_lock { + * fuse_attr flags + * + * FUSE_ATTR_SUBMOUNT: Object is a submount root ++ * FUSE_ATTR_DAX: Enable DAX for this file in per inode DAX mode + */ + #define FUSE_ATTR_SUBMOUNT (1 << 0) ++#define FUSE_ATTR_DAX (1 << 1) + + /** + * Open flags +@@ -732,6 +756,8 @@ struct fuse_init_in { + uint32_t minor; + uint32_t max_readahead; + uint32_t flags; ++ uint32_t flags2; ++ uint32_t unused[11]; + }; + + #define FUSE_COMPAT_INIT_OUT_SIZE 8 +@@ -748,7 +774,8 @@ struct fuse_init_out { + uint32_t time_gran; + uint16_t max_pages; + uint16_t map_alignment; +- uint32_t unused[8]; ++ uint32_t flags2; ++ uint32_t unused[7]; + }; + + #define CUSE_INIT_INFO_MAX 4096 +@@ -856,9 +883,12 @@ struct fuse_dirent { + char name[]; + }; + +-#define FUSE_NAME_OFFSET offsetof(struct fuse_dirent, name) +-#define FUSE_DIRENT_ALIGN(x) \ ++/* Align variable length records to 64bit boundary */ ++#define FUSE_REC_ALIGN(x) \ + (((x) + sizeof(uint64_t) - 1) & ~(sizeof(uint64_t) - 1)) ++ ++#define FUSE_NAME_OFFSET offsetof(struct fuse_dirent, name) ++#define FUSE_DIRENT_ALIGN(x) FUSE_REC_ALIGN(x) + #define FUSE_DIRENT_SIZE(d) \ + FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET + (d)->namelen) + +@@ -975,4 +1005,26 @@ struct fuse_syncfs_in { + uint64_t padding; + }; + ++/* ++ * For each security context, send fuse_secctx with size of security context ++ * fuse_secctx will be followed by security context name and this in turn ++ * will be followed by actual context label. ++ * fuse_secctx, name, context ++ */ ++struct fuse_secctx { ++ uint32_t size; ++ uint32_t padding; ++}; ++ ++/* ++ * Contains the information about how many fuse_secctx structures are being ++ * sent and what's the total size of all security contexts (including ++ * size of fuse_secctx_header). ++ * ++ */ ++struct fuse_secctx_header { ++ uint32_t size; ++ uint32_t nr_secctx; ++}; ++ + #endif /* _LINUX_FUSE_H */ +diff --git a/include/standard-headers/linux/pci_regs.h b/include/standard-headers/linux/pci_regs.h +index ff6ccbc6ef..bee1a9ed6e 100644 +--- a/include/standard-headers/linux/pci_regs.h ++++ b/include/standard-headers/linux/pci_regs.h +@@ -301,23 +301,23 @@ + #define PCI_SID_ESR_FIC 0x20 /* First In Chassis Flag */ + #define PCI_SID_CHASSIS_NR 3 /* Chassis Number */ + +-/* Message Signalled Interrupt registers */ ++/* Message Signaled Interrupt registers */ + +-#define PCI_MSI_FLAGS 2 /* Message Control */ ++#define PCI_MSI_FLAGS 0x02 /* Message Control */ + #define PCI_MSI_FLAGS_ENABLE 0x0001 /* MSI feature enabled */ + #define PCI_MSI_FLAGS_QMASK 0x000e /* Maximum queue size available */ + #define PCI_MSI_FLAGS_QSIZE 0x0070 /* Message queue size configured */ + #define PCI_MSI_FLAGS_64BIT 0x0080 /* 64-bit addresses allowed */ + #define PCI_MSI_FLAGS_MASKBIT 0x0100 /* Per-vector masking capable */ + #define PCI_MSI_RFU 3 /* Rest of capability flags */ +-#define PCI_MSI_ADDRESS_LO 4 /* Lower 32 bits */ +-#define PCI_MSI_ADDRESS_HI 8 /* Upper 32 bits (if PCI_MSI_FLAGS_64BIT set) */ +-#define PCI_MSI_DATA_32 8 /* 16 bits of data for 32-bit devices */ +-#define PCI_MSI_MASK_32 12 /* Mask bits register for 32-bit devices */ +-#define PCI_MSI_PENDING_32 16 /* Pending intrs for 32-bit devices */ +-#define PCI_MSI_DATA_64 12 /* 16 bits of data for 64-bit devices */ +-#define PCI_MSI_MASK_64 16 /* Mask bits register for 64-bit devices */ +-#define PCI_MSI_PENDING_64 20 /* Pending intrs for 64-bit devices */ ++#define PCI_MSI_ADDRESS_LO 0x04 /* Lower 32 bits */ ++#define PCI_MSI_ADDRESS_HI 0x08 /* Upper 32 bits (if PCI_MSI_FLAGS_64BIT set) */ ++#define PCI_MSI_DATA_32 0x08 /* 16 bits of data for 32-bit devices */ ++#define PCI_MSI_MASK_32 0x0c /* Mask bits register for 32-bit devices */ ++#define PCI_MSI_PENDING_32 0x10 /* Pending intrs for 32-bit devices */ ++#define PCI_MSI_DATA_64 0x0c /* 16 bits of data for 64-bit devices */ ++#define PCI_MSI_MASK_64 0x10 /* Mask bits register for 64-bit devices */ ++#define PCI_MSI_PENDING_64 0x14 /* Pending intrs for 64-bit devices */ + + /* MSI-X registers (in MSI-X capability) */ + #define PCI_MSIX_FLAGS 2 /* Message Control */ +@@ -335,10 +335,10 @@ + + /* MSI-X Table entry format (in memory mapped by a BAR) */ + #define PCI_MSIX_ENTRY_SIZE 16 +-#define PCI_MSIX_ENTRY_LOWER_ADDR 0 /* Message Address */ +-#define PCI_MSIX_ENTRY_UPPER_ADDR 4 /* Message Upper Address */ +-#define PCI_MSIX_ENTRY_DATA 8 /* Message Data */ +-#define PCI_MSIX_ENTRY_VECTOR_CTRL 12 /* Vector Control */ ++#define PCI_MSIX_ENTRY_LOWER_ADDR 0x0 /* Message Address */ ++#define PCI_MSIX_ENTRY_UPPER_ADDR 0x4 /* Message Upper Address */ ++#define PCI_MSIX_ENTRY_DATA 0x8 /* Message Data */ ++#define PCI_MSIX_ENTRY_VECTOR_CTRL 0xc /* Vector Control */ + #define PCI_MSIX_ENTRY_CTRL_MASKBIT 0x00000001 + + /* CompactPCI Hotswap Register */ +@@ -470,7 +470,7 @@ + + /* PCI Express capability registers */ + +-#define PCI_EXP_FLAGS 2 /* Capabilities register */ ++#define PCI_EXP_FLAGS 0x02 /* Capabilities register */ + #define PCI_EXP_FLAGS_VERS 0x000f /* Capability version */ + #define PCI_EXP_FLAGS_TYPE 0x00f0 /* Device/Port type */ + #define PCI_EXP_TYPE_ENDPOINT 0x0 /* Express Endpoint */ +@@ -484,7 +484,7 @@ + #define PCI_EXP_TYPE_RC_EC 0xa /* Root Complex Event Collector */ + #define PCI_EXP_FLAGS_SLOT 0x0100 /* Slot implemented */ + #define PCI_EXP_FLAGS_IRQ 0x3e00 /* Interrupt message number */ +-#define PCI_EXP_DEVCAP 4 /* Device capabilities */ ++#define PCI_EXP_DEVCAP 0x04 /* Device capabilities */ + #define PCI_EXP_DEVCAP_PAYLOAD 0x00000007 /* Max_Payload_Size */ + #define PCI_EXP_DEVCAP_PHANTOM 0x00000018 /* Phantom functions */ + #define PCI_EXP_DEVCAP_EXT_TAG 0x00000020 /* Extended tags */ +@@ -497,7 +497,7 @@ + #define PCI_EXP_DEVCAP_PWR_VAL 0x03fc0000 /* Slot Power Limit Value */ + #define PCI_EXP_DEVCAP_PWR_SCL 0x0c000000 /* Slot Power Limit Scale */ + #define PCI_EXP_DEVCAP_FLR 0x10000000 /* Function Level Reset */ +-#define PCI_EXP_DEVCTL 8 /* Device Control */ ++#define PCI_EXP_DEVCTL 0x08 /* Device Control */ + #define PCI_EXP_DEVCTL_CERE 0x0001 /* Correctable Error Reporting En. */ + #define PCI_EXP_DEVCTL_NFERE 0x0002 /* Non-Fatal Error Reporting Enable */ + #define PCI_EXP_DEVCTL_FERE 0x0004 /* Fatal Error Reporting Enable */ +@@ -522,7 +522,7 @@ + #define PCI_EXP_DEVCTL_READRQ_2048B 0x4000 /* 2048 Bytes */ + #define PCI_EXP_DEVCTL_READRQ_4096B 0x5000 /* 4096 Bytes */ + #define PCI_EXP_DEVCTL_BCR_FLR 0x8000 /* Bridge Configuration Retry / FLR */ +-#define PCI_EXP_DEVSTA 10 /* Device Status */ ++#define PCI_EXP_DEVSTA 0x0a /* Device Status */ + #define PCI_EXP_DEVSTA_CED 0x0001 /* Correctable Error Detected */ + #define PCI_EXP_DEVSTA_NFED 0x0002 /* Non-Fatal Error Detected */ + #define PCI_EXP_DEVSTA_FED 0x0004 /* Fatal Error Detected */ +@@ -530,7 +530,7 @@ + #define PCI_EXP_DEVSTA_AUXPD 0x0010 /* AUX Power Detected */ + #define PCI_EXP_DEVSTA_TRPND 0x0020 /* Transactions Pending */ + #define PCI_CAP_EXP_RC_ENDPOINT_SIZEOF_V1 12 /* v1 endpoints without link end here */ +-#define PCI_EXP_LNKCAP 12 /* Link Capabilities */ ++#define PCI_EXP_LNKCAP 0x0c /* Link Capabilities */ + #define PCI_EXP_LNKCAP_SLS 0x0000000f /* Supported Link Speeds */ + #define PCI_EXP_LNKCAP_SLS_2_5GB 0x00000001 /* LNKCAP2 SLS Vector bit 0 */ + #define PCI_EXP_LNKCAP_SLS_5_0GB 0x00000002 /* LNKCAP2 SLS Vector bit 1 */ +@@ -549,7 +549,7 @@ + #define PCI_EXP_LNKCAP_DLLLARC 0x00100000 /* Data Link Layer Link Active Reporting Capable */ + #define PCI_EXP_LNKCAP_LBNC 0x00200000 /* Link Bandwidth Notification Capability */ + #define PCI_EXP_LNKCAP_PN 0xff000000 /* Port Number */ +-#define PCI_EXP_LNKCTL 16 /* Link Control */ ++#define PCI_EXP_LNKCTL 0x10 /* Link Control */ + #define PCI_EXP_LNKCTL_ASPMC 0x0003 /* ASPM Control */ + #define PCI_EXP_LNKCTL_ASPM_L0S 0x0001 /* L0s Enable */ + #define PCI_EXP_LNKCTL_ASPM_L1 0x0002 /* L1 Enable */ +@@ -562,7 +562,7 @@ + #define PCI_EXP_LNKCTL_HAWD 0x0200 /* Hardware Autonomous Width Disable */ + #define PCI_EXP_LNKCTL_LBMIE 0x0400 /* Link Bandwidth Management Interrupt Enable */ + #define PCI_EXP_LNKCTL_LABIE 0x0800 /* Link Autonomous Bandwidth Interrupt Enable */ +-#define PCI_EXP_LNKSTA 18 /* Link Status */ ++#define PCI_EXP_LNKSTA 0x12 /* Link Status */ + #define PCI_EXP_LNKSTA_CLS 0x000f /* Current Link Speed */ + #define PCI_EXP_LNKSTA_CLS_2_5GB 0x0001 /* Current Link Speed 2.5GT/s */ + #define PCI_EXP_LNKSTA_CLS_5_0GB 0x0002 /* Current Link Speed 5.0GT/s */ +@@ -582,7 +582,7 @@ + #define PCI_EXP_LNKSTA_LBMS 0x4000 /* Link Bandwidth Management Status */ + #define PCI_EXP_LNKSTA_LABS 0x8000 /* Link Autonomous Bandwidth Status */ + #define PCI_CAP_EXP_ENDPOINT_SIZEOF_V1 20 /* v1 endpoints with link end here */ +-#define PCI_EXP_SLTCAP 20 /* Slot Capabilities */ ++#define PCI_EXP_SLTCAP 0x14 /* Slot Capabilities */ + #define PCI_EXP_SLTCAP_ABP 0x00000001 /* Attention Button Present */ + #define PCI_EXP_SLTCAP_PCP 0x00000002 /* Power Controller Present */ + #define PCI_EXP_SLTCAP_MRLSP 0x00000004 /* MRL Sensor Present */ +@@ -595,7 +595,7 @@ + #define PCI_EXP_SLTCAP_EIP 0x00020000 /* Electromechanical Interlock Present */ + #define PCI_EXP_SLTCAP_NCCS 0x00040000 /* No Command Completed Support */ + #define PCI_EXP_SLTCAP_PSN 0xfff80000 /* Physical Slot Number */ +-#define PCI_EXP_SLTCTL 24 /* Slot Control */ ++#define PCI_EXP_SLTCTL 0x18 /* Slot Control */ + #define PCI_EXP_SLTCTL_ABPE 0x0001 /* Attention Button Pressed Enable */ + #define PCI_EXP_SLTCTL_PFDE 0x0002 /* Power Fault Detected Enable */ + #define PCI_EXP_SLTCTL_MRLSCE 0x0004 /* MRL Sensor Changed Enable */ +@@ -617,7 +617,7 @@ + #define PCI_EXP_SLTCTL_EIC 0x0800 /* Electromechanical Interlock Control */ + #define PCI_EXP_SLTCTL_DLLSCE 0x1000 /* Data Link Layer State Changed Enable */ + #define PCI_EXP_SLTCTL_IBPD_DISABLE 0x4000 /* In-band PD disable */ +-#define PCI_EXP_SLTSTA 26 /* Slot Status */ ++#define PCI_EXP_SLTSTA 0x1a /* Slot Status */ + #define PCI_EXP_SLTSTA_ABP 0x0001 /* Attention Button Pressed */ + #define PCI_EXP_SLTSTA_PFD 0x0002 /* Power Fault Detected */ + #define PCI_EXP_SLTSTA_MRLSC 0x0004 /* MRL Sensor Changed */ +@@ -627,15 +627,15 @@ + #define PCI_EXP_SLTSTA_PDS 0x0040 /* Presence Detect State */ + #define PCI_EXP_SLTSTA_EIS 0x0080 /* Electromechanical Interlock Status */ + #define PCI_EXP_SLTSTA_DLLSC 0x0100 /* Data Link Layer State Changed */ +-#define PCI_EXP_RTCTL 28 /* Root Control */ ++#define PCI_EXP_RTCTL 0x1c /* Root Control */ + #define PCI_EXP_RTCTL_SECEE 0x0001 /* System Error on Correctable Error */ + #define PCI_EXP_RTCTL_SENFEE 0x0002 /* System Error on Non-Fatal Error */ + #define PCI_EXP_RTCTL_SEFEE 0x0004 /* System Error on Fatal Error */ + #define PCI_EXP_RTCTL_PMEIE 0x0008 /* PME Interrupt Enable */ + #define PCI_EXP_RTCTL_CRSSVE 0x0010 /* CRS Software Visibility Enable */ +-#define PCI_EXP_RTCAP 30 /* Root Capabilities */ ++#define PCI_EXP_RTCAP 0x1e /* Root Capabilities */ + #define PCI_EXP_RTCAP_CRSVIS 0x0001 /* CRS Software Visibility capability */ +-#define PCI_EXP_RTSTA 32 /* Root Status */ ++#define PCI_EXP_RTSTA 0x20 /* Root Status */ + #define PCI_EXP_RTSTA_PME 0x00010000 /* PME status */ + #define PCI_EXP_RTSTA_PENDING 0x00020000 /* PME pending */ + /* +@@ -646,7 +646,7 @@ + * Use pcie_capability_read_word() and similar interfaces to use them + * safely. + */ +-#define PCI_EXP_DEVCAP2 36 /* Device Capabilities 2 */ ++#define PCI_EXP_DEVCAP2 0x24 /* Device Capabilities 2 */ + #define PCI_EXP_DEVCAP2_COMP_TMOUT_DIS 0x00000010 /* Completion Timeout Disable supported */ + #define PCI_EXP_DEVCAP2_ARI 0x00000020 /* Alternative Routing-ID */ + #define PCI_EXP_DEVCAP2_ATOMIC_ROUTE 0x00000040 /* Atomic Op routing */ +@@ -658,7 +658,7 @@ + #define PCI_EXP_DEVCAP2_OBFF_MSG 0x00040000 /* New message signaling */ + #define PCI_EXP_DEVCAP2_OBFF_WAKE 0x00080000 /* Re-use WAKE# for OBFF */ + #define PCI_EXP_DEVCAP2_EE_PREFIX 0x00200000 /* End-End TLP Prefix */ +-#define PCI_EXP_DEVCTL2 40 /* Device Control 2 */ ++#define PCI_EXP_DEVCTL2 0x28 /* Device Control 2 */ + #define PCI_EXP_DEVCTL2_COMP_TIMEOUT 0x000f /* Completion Timeout Value */ + #define PCI_EXP_DEVCTL2_COMP_TMOUT_DIS 0x0010 /* Completion Timeout Disable */ + #define PCI_EXP_DEVCTL2_ARI 0x0020 /* Alternative Routing-ID */ +@@ -670,9 +670,9 @@ + #define PCI_EXP_DEVCTL2_OBFF_MSGA_EN 0x2000 /* Enable OBFF Message type A */ + #define PCI_EXP_DEVCTL2_OBFF_MSGB_EN 0x4000 /* Enable OBFF Message type B */ + #define PCI_EXP_DEVCTL2_OBFF_WAKE_EN 0x6000 /* OBFF using WAKE# signaling */ +-#define PCI_EXP_DEVSTA2 42 /* Device Status 2 */ +-#define PCI_CAP_EXP_RC_ENDPOINT_SIZEOF_V2 44 /* v2 endpoints without link end here */ +-#define PCI_EXP_LNKCAP2 44 /* Link Capabilities 2 */ ++#define PCI_EXP_DEVSTA2 0x2a /* Device Status 2 */ ++#define PCI_CAP_EXP_RC_ENDPOINT_SIZEOF_V2 0x2c /* end of v2 EPs w/o link */ ++#define PCI_EXP_LNKCAP2 0x2c /* Link Capabilities 2 */ + #define PCI_EXP_LNKCAP2_SLS_2_5GB 0x00000002 /* Supported Speed 2.5GT/s */ + #define PCI_EXP_LNKCAP2_SLS_5_0GB 0x00000004 /* Supported Speed 5GT/s */ + #define PCI_EXP_LNKCAP2_SLS_8_0GB 0x00000008 /* Supported Speed 8GT/s */ +@@ -680,7 +680,7 @@ + #define PCI_EXP_LNKCAP2_SLS_32_0GB 0x00000020 /* Supported Speed 32GT/s */ + #define PCI_EXP_LNKCAP2_SLS_64_0GB 0x00000040 /* Supported Speed 64GT/s */ + #define PCI_EXP_LNKCAP2_CROSSLINK 0x00000100 /* Crosslink supported */ +-#define PCI_EXP_LNKCTL2 48 /* Link Control 2 */ ++#define PCI_EXP_LNKCTL2 0x30 /* Link Control 2 */ + #define PCI_EXP_LNKCTL2_TLS 0x000f + #define PCI_EXP_LNKCTL2_TLS_2_5GT 0x0001 /* Supported Speed 2.5GT/s */ + #define PCI_EXP_LNKCTL2_TLS_5_0GT 0x0002 /* Supported Speed 5GT/s */ +@@ -691,12 +691,12 @@ + #define PCI_EXP_LNKCTL2_ENTER_COMP 0x0010 /* Enter Compliance */ + #define PCI_EXP_LNKCTL2_TX_MARGIN 0x0380 /* Transmit Margin */ + #define PCI_EXP_LNKCTL2_HASD 0x0020 /* HW Autonomous Speed Disable */ +-#define PCI_EXP_LNKSTA2 50 /* Link Status 2 */ +-#define PCI_CAP_EXP_ENDPOINT_SIZEOF_V2 52 /* v2 endpoints with link end here */ +-#define PCI_EXP_SLTCAP2 52 /* Slot Capabilities 2 */ ++#define PCI_EXP_LNKSTA2 0x32 /* Link Status 2 */ ++#define PCI_CAP_EXP_ENDPOINT_SIZEOF_V2 0x32 /* end of v2 EPs w/ link */ ++#define PCI_EXP_SLTCAP2 0x34 /* Slot Capabilities 2 */ + #define PCI_EXP_SLTCAP2_IBPD 0x00000001 /* In-band PD Disable Supported */ +-#define PCI_EXP_SLTCTL2 56 /* Slot Control 2 */ +-#define PCI_EXP_SLTSTA2 58 /* Slot Status 2 */ ++#define PCI_EXP_SLTCTL2 0x38 /* Slot Control 2 */ ++#define PCI_EXP_SLTSTA2 0x3a /* Slot Status 2 */ + + /* Extended Capabilities (PCI-X 2.0 and Express) */ + #define PCI_EXT_CAP_ID(header) (header & 0x0000ffff) +@@ -742,7 +742,7 @@ + #define PCI_EXT_CAP_MCAST_ENDPOINT_SIZEOF 40 + + /* Advanced Error Reporting */ +-#define PCI_ERR_UNCOR_STATUS 4 /* Uncorrectable Error Status */ ++#define PCI_ERR_UNCOR_STATUS 0x04 /* Uncorrectable Error Status */ + #define PCI_ERR_UNC_UND 0x00000001 /* Undefined */ + #define PCI_ERR_UNC_DLP 0x00000010 /* Data Link Protocol */ + #define PCI_ERR_UNC_SURPDN 0x00000020 /* Surprise Down */ +@@ -760,11 +760,11 @@ + #define PCI_ERR_UNC_MCBTLP 0x00800000 /* MC blocked TLP */ + #define PCI_ERR_UNC_ATOMEG 0x01000000 /* Atomic egress blocked */ + #define PCI_ERR_UNC_TLPPRE 0x02000000 /* TLP prefix blocked */ +-#define PCI_ERR_UNCOR_MASK 8 /* Uncorrectable Error Mask */ ++#define PCI_ERR_UNCOR_MASK 0x08 /* Uncorrectable Error Mask */ + /* Same bits as above */ +-#define PCI_ERR_UNCOR_SEVER 12 /* Uncorrectable Error Severity */ ++#define PCI_ERR_UNCOR_SEVER 0x0c /* Uncorrectable Error Severity */ + /* Same bits as above */ +-#define PCI_ERR_COR_STATUS 16 /* Correctable Error Status */ ++#define PCI_ERR_COR_STATUS 0x10 /* Correctable Error Status */ + #define PCI_ERR_COR_RCVR 0x00000001 /* Receiver Error Status */ + #define PCI_ERR_COR_BAD_TLP 0x00000040 /* Bad TLP Status */ + #define PCI_ERR_COR_BAD_DLLP 0x00000080 /* Bad DLLP Status */ +@@ -773,20 +773,20 @@ + #define PCI_ERR_COR_ADV_NFAT 0x00002000 /* Advisory Non-Fatal */ + #define PCI_ERR_COR_INTERNAL 0x00004000 /* Corrected Internal */ + #define PCI_ERR_COR_LOG_OVER 0x00008000 /* Header Log Overflow */ +-#define PCI_ERR_COR_MASK 20 /* Correctable Error Mask */ ++#define PCI_ERR_COR_MASK 0x14 /* Correctable Error Mask */ + /* Same bits as above */ +-#define PCI_ERR_CAP 24 /* Advanced Error Capabilities */ +-#define PCI_ERR_CAP_FEP(x) ((x) & 31) /* First Error Pointer */ ++#define PCI_ERR_CAP 0x18 /* Advanced Error Capabilities & Ctrl*/ ++#define PCI_ERR_CAP_FEP(x) ((x) & 0x1f) /* First Error Pointer */ + #define PCI_ERR_CAP_ECRC_GENC 0x00000020 /* ECRC Generation Capable */ + #define PCI_ERR_CAP_ECRC_GENE 0x00000040 /* ECRC Generation Enable */ + #define PCI_ERR_CAP_ECRC_CHKC 0x00000080 /* ECRC Check Capable */ + #define PCI_ERR_CAP_ECRC_CHKE 0x00000100 /* ECRC Check Enable */ +-#define PCI_ERR_HEADER_LOG 28 /* Header Log Register (16 bytes) */ +-#define PCI_ERR_ROOT_COMMAND 44 /* Root Error Command */ ++#define PCI_ERR_HEADER_LOG 0x1c /* Header Log Register (16 bytes) */ ++#define PCI_ERR_ROOT_COMMAND 0x2c /* Root Error Command */ + #define PCI_ERR_ROOT_CMD_COR_EN 0x00000001 /* Correctable Err Reporting Enable */ + #define PCI_ERR_ROOT_CMD_NONFATAL_EN 0x00000002 /* Non-Fatal Err Reporting Enable */ + #define PCI_ERR_ROOT_CMD_FATAL_EN 0x00000004 /* Fatal Err Reporting Enable */ +-#define PCI_ERR_ROOT_STATUS 48 ++#define PCI_ERR_ROOT_STATUS 0x30 + #define PCI_ERR_ROOT_COR_RCV 0x00000001 /* ERR_COR Received */ + #define PCI_ERR_ROOT_MULTI_COR_RCV 0x00000002 /* Multiple ERR_COR */ + #define PCI_ERR_ROOT_UNCOR_RCV 0x00000004 /* ERR_FATAL/NONFATAL */ +@@ -795,52 +795,52 @@ + #define PCI_ERR_ROOT_NONFATAL_RCV 0x00000020 /* Non-Fatal Received */ + #define PCI_ERR_ROOT_FATAL_RCV 0x00000040 /* Fatal Received */ + #define PCI_ERR_ROOT_AER_IRQ 0xf8000000 /* Advanced Error Interrupt Message Number */ +-#define PCI_ERR_ROOT_ERR_SRC 52 /* Error Source Identification */ ++#define PCI_ERR_ROOT_ERR_SRC 0x34 /* Error Source Identification */ + + /* Virtual Channel */ +-#define PCI_VC_PORT_CAP1 4 ++#define PCI_VC_PORT_CAP1 0x04 + #define PCI_VC_CAP1_EVCC 0x00000007 /* extended VC count */ + #define PCI_VC_CAP1_LPEVCC 0x00000070 /* low prio extended VC count */ + #define PCI_VC_CAP1_ARB_SIZE 0x00000c00 +-#define PCI_VC_PORT_CAP2 8 ++#define PCI_VC_PORT_CAP2 0x08 + #define PCI_VC_CAP2_32_PHASE 0x00000002 + #define PCI_VC_CAP2_64_PHASE 0x00000004 + #define PCI_VC_CAP2_128_PHASE 0x00000008 + #define PCI_VC_CAP2_ARB_OFF 0xff000000 +-#define PCI_VC_PORT_CTRL 12 ++#define PCI_VC_PORT_CTRL 0x0c + #define PCI_VC_PORT_CTRL_LOAD_TABLE 0x00000001 +-#define PCI_VC_PORT_STATUS 14 ++#define PCI_VC_PORT_STATUS 0x0e + #define PCI_VC_PORT_STATUS_TABLE 0x00000001 +-#define PCI_VC_RES_CAP 16 ++#define PCI_VC_RES_CAP 0x10 + #define PCI_VC_RES_CAP_32_PHASE 0x00000002 + #define PCI_VC_RES_CAP_64_PHASE 0x00000004 + #define PCI_VC_RES_CAP_128_PHASE 0x00000008 + #define PCI_VC_RES_CAP_128_PHASE_TB 0x00000010 + #define PCI_VC_RES_CAP_256_PHASE 0x00000020 + #define PCI_VC_RES_CAP_ARB_OFF 0xff000000 +-#define PCI_VC_RES_CTRL 20 ++#define PCI_VC_RES_CTRL 0x14 + #define PCI_VC_RES_CTRL_LOAD_TABLE 0x00010000 + #define PCI_VC_RES_CTRL_ARB_SELECT 0x000e0000 + #define PCI_VC_RES_CTRL_ID 0x07000000 + #define PCI_VC_RES_CTRL_ENABLE 0x80000000 +-#define PCI_VC_RES_STATUS 26 ++#define PCI_VC_RES_STATUS 0x1a + #define PCI_VC_RES_STATUS_TABLE 0x00000001 + #define PCI_VC_RES_STATUS_NEGO 0x00000002 + #define PCI_CAP_VC_BASE_SIZEOF 0x10 +-#define PCI_CAP_VC_PER_VC_SIZEOF 0x0C ++#define PCI_CAP_VC_PER_VC_SIZEOF 0x0c + + /* Power Budgeting */ +-#define PCI_PWR_DSR 4 /* Data Select Register */ +-#define PCI_PWR_DATA 8 /* Data Register */ ++#define PCI_PWR_DSR 0x04 /* Data Select Register */ ++#define PCI_PWR_DATA 0x08 /* Data Register */ + #define PCI_PWR_DATA_BASE(x) ((x) & 0xff) /* Base Power */ + #define PCI_PWR_DATA_SCALE(x) (((x) >> 8) & 3) /* Data Scale */ + #define PCI_PWR_DATA_PM_SUB(x) (((x) >> 10) & 7) /* PM Sub State */ + #define PCI_PWR_DATA_PM_STATE(x) (((x) >> 13) & 3) /* PM State */ + #define PCI_PWR_DATA_TYPE(x) (((x) >> 15) & 7) /* Type */ + #define PCI_PWR_DATA_RAIL(x) (((x) >> 18) & 7) /* Power Rail */ +-#define PCI_PWR_CAP 12 /* Capability */ ++#define PCI_PWR_CAP 0x0c /* Capability */ + #define PCI_PWR_CAP_BUDGET(x) ((x) & 1) /* Included in system budget */ +-#define PCI_EXT_CAP_PWR_SIZEOF 16 ++#define PCI_EXT_CAP_PWR_SIZEOF 0x10 + + /* Root Complex Event Collector Endpoint Association */ + #define PCI_RCEC_RCIEP_BITMAP 4 /* Associated Bitmap for RCiEPs */ +@@ -964,7 +964,7 @@ + #define PCI_SRIOV_VFM_MI 0x1 /* Dormant.MigrateIn */ + #define PCI_SRIOV_VFM_MO 0x2 /* Active.MigrateOut */ + #define PCI_SRIOV_VFM_AV 0x3 /* Active.Available */ +-#define PCI_EXT_CAP_SRIOV_SIZEOF 64 ++#define PCI_EXT_CAP_SRIOV_SIZEOF 0x40 + + #define PCI_LTR_MAX_SNOOP_LAT 0x4 + #define PCI_LTR_MAX_NOSNOOP_LAT 0x6 +@@ -1017,12 +1017,12 @@ + #define PCI_TPH_LOC_NONE 0x000 /* no location */ + #define PCI_TPH_LOC_CAP 0x200 /* in capability */ + #define PCI_TPH_LOC_MSIX 0x400 /* in MSI-X */ +-#define PCI_TPH_CAP_ST_MASK 0x07FF0000 /* st table mask */ +-#define PCI_TPH_CAP_ST_SHIFT 16 /* st table shift */ +-#define PCI_TPH_BASE_SIZEOF 12 /* size with no st table */ ++#define PCI_TPH_CAP_ST_MASK 0x07FF0000 /* ST table mask */ ++#define PCI_TPH_CAP_ST_SHIFT 16 /* ST table shift */ ++#define PCI_TPH_BASE_SIZEOF 0xc /* size with no ST table */ + + /* Downstream Port Containment */ +-#define PCI_EXP_DPC_CAP 4 /* DPC Capability */ ++#define PCI_EXP_DPC_CAP 0x04 /* DPC Capability */ + #define PCI_EXP_DPC_IRQ 0x001F /* Interrupt Message Number */ + #define PCI_EXP_DPC_CAP_RP_EXT 0x0020 /* Root Port Extensions */ + #define PCI_EXP_DPC_CAP_POISONED_TLP 0x0040 /* Poisoned TLP Egress Blocking Supported */ +@@ -1030,19 +1030,19 @@ + #define PCI_EXP_DPC_RP_PIO_LOG_SIZE 0x0F00 /* RP PIO Log Size */ + #define PCI_EXP_DPC_CAP_DL_ACTIVE 0x1000 /* ERR_COR signal on DL_Active supported */ + +-#define PCI_EXP_DPC_CTL 6 /* DPC control */ ++#define PCI_EXP_DPC_CTL 0x06 /* DPC control */ + #define PCI_EXP_DPC_CTL_EN_FATAL 0x0001 /* Enable trigger on ERR_FATAL message */ + #define PCI_EXP_DPC_CTL_EN_NONFATAL 0x0002 /* Enable trigger on ERR_NONFATAL message */ + #define PCI_EXP_DPC_CTL_INT_EN 0x0008 /* DPC Interrupt Enable */ + +-#define PCI_EXP_DPC_STATUS 8 /* DPC Status */ ++#define PCI_EXP_DPC_STATUS 0x08 /* DPC Status */ + #define PCI_EXP_DPC_STATUS_TRIGGER 0x0001 /* Trigger Status */ + #define PCI_EXP_DPC_STATUS_TRIGGER_RSN 0x0006 /* Trigger Reason */ + #define PCI_EXP_DPC_STATUS_INTERRUPT 0x0008 /* Interrupt Status */ + #define PCI_EXP_DPC_RP_BUSY 0x0010 /* Root Port Busy */ + #define PCI_EXP_DPC_STATUS_TRIGGER_RSN_EXT 0x0060 /* Trig Reason Extension */ + +-#define PCI_EXP_DPC_SOURCE_ID 10 /* DPC Source Identifier */ ++#define PCI_EXP_DPC_SOURCE_ID 0x0A /* DPC Source Identifier */ + + #define PCI_EXP_DPC_RP_PIO_STATUS 0x0C /* RP PIO Status */ + #define PCI_EXP_DPC_RP_PIO_MASK 0x10 /* RP PIO Mask */ +@@ -1086,7 +1086,11 @@ + + /* Designated Vendor-Specific (DVSEC, PCI_EXT_CAP_ID_DVSEC) */ + #define PCI_DVSEC_HEADER1 0x4 /* Designated Vendor-Specific Header1 */ ++#define PCI_DVSEC_HEADER1_VID(x) ((x) & 0xffff) ++#define PCI_DVSEC_HEADER1_REV(x) (((x) >> 16) & 0xf) ++#define PCI_DVSEC_HEADER1_LEN(x) (((x) >> 20) & 0xfff) + #define PCI_DVSEC_HEADER2 0x8 /* Designated Vendor-Specific Header2 */ ++#define PCI_DVSEC_HEADER2_ID(x) ((x) & 0xffff) + + /* Data Link Feature */ + #define PCI_DLF_CAP 0x04 /* Capabilities Register */ +diff --git a/include/standard-headers/linux/virtio_gpio.h b/include/standard-headers/linux/virtio_gpio.h +new file mode 100644 +index 0000000000..2b5cf06349 +--- /dev/null ++++ b/include/standard-headers/linux/virtio_gpio.h +@@ -0,0 +1,72 @@ ++/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ ++ ++#ifndef _LINUX_VIRTIO_GPIO_H ++#define _LINUX_VIRTIO_GPIO_H ++ ++#include "standard-headers/linux/types.h" ++ ++/* Virtio GPIO Feature bits */ ++#define VIRTIO_GPIO_F_IRQ 0 ++ ++/* Virtio GPIO request types */ ++#define VIRTIO_GPIO_MSG_GET_NAMES 0x0001 ++#define VIRTIO_GPIO_MSG_GET_DIRECTION 0x0002 ++#define VIRTIO_GPIO_MSG_SET_DIRECTION 0x0003 ++#define VIRTIO_GPIO_MSG_GET_VALUE 0x0004 ++#define VIRTIO_GPIO_MSG_SET_VALUE 0x0005 ++#define VIRTIO_GPIO_MSG_IRQ_TYPE 0x0006 ++ ++/* Possible values of the status field */ ++#define VIRTIO_GPIO_STATUS_OK 0x0 ++#define VIRTIO_GPIO_STATUS_ERR 0x1 ++ ++/* Direction types */ ++#define VIRTIO_GPIO_DIRECTION_NONE 0x00 ++#define VIRTIO_GPIO_DIRECTION_OUT 0x01 ++#define VIRTIO_GPIO_DIRECTION_IN 0x02 ++ ++/* Virtio GPIO IRQ types */ ++#define VIRTIO_GPIO_IRQ_TYPE_NONE 0x00 ++#define VIRTIO_GPIO_IRQ_TYPE_EDGE_RISING 0x01 ++#define VIRTIO_GPIO_IRQ_TYPE_EDGE_FALLING 0x02 ++#define VIRTIO_GPIO_IRQ_TYPE_EDGE_BOTH 0x03 ++#define VIRTIO_GPIO_IRQ_TYPE_LEVEL_HIGH 0x04 ++#define VIRTIO_GPIO_IRQ_TYPE_LEVEL_LOW 0x08 ++ ++struct virtio_gpio_config { ++ uint16_t ngpio; ++ uint8_t padding[2]; ++ uint32_t gpio_names_size; ++}; ++ ++/* Virtio GPIO Request / Response */ ++struct virtio_gpio_request { ++ uint16_t type; ++ uint16_t gpio; ++ uint32_t value; ++}; ++ ++struct virtio_gpio_response { ++ uint8_t status; ++ uint8_t value; ++}; ++ ++struct virtio_gpio_response_get_names { ++ uint8_t status; ++ uint8_t value[]; ++}; ++ ++/* Virtio GPIO IRQ Request / Response */ ++struct virtio_gpio_irq_request { ++ uint16_t gpio; ++}; ++ ++struct virtio_gpio_irq_response { ++ uint8_t status; ++}; ++ ++/* Possible values of the interrupt status field */ ++#define VIRTIO_GPIO_IRQ_STATUS_INVALID 0x0 ++#define VIRTIO_GPIO_IRQ_STATUS_VALID 0x1 ++ ++#endif /* _LINUX_VIRTIO_GPIO_H */ +diff --git a/include/standard-headers/linux/virtio_i2c.h b/include/standard-headers/linux/virtio_i2c.h +new file mode 100644 +index 0000000000..09fa907793 +--- /dev/null ++++ b/include/standard-headers/linux/virtio_i2c.h +@@ -0,0 +1,47 @@ ++/* SPDX-License-Identifier: GPL-2.0-or-later WITH Linux-syscall-note */ ++/* ++ * Definitions for virtio I2C Adpter ++ * ++ * Copyright (c) 2021 Intel Corporation. All rights reserved. ++ */ ++ ++#ifndef _LINUX_VIRTIO_I2C_H ++#define _LINUX_VIRTIO_I2C_H ++ ++#include "standard-headers/linux/const.h" ++#include "standard-headers/linux/types.h" ++ ++/* Virtio I2C Feature bits */ ++#define VIRTIO_I2C_F_ZERO_LENGTH_REQUEST 0 ++ ++/* The bit 0 of the @virtio_i2c_out_hdr.@flags, used to group the requests */ ++#define VIRTIO_I2C_FLAGS_FAIL_NEXT _BITUL(0) ++ ++/* The bit 1 of the @virtio_i2c_out_hdr.@flags, used to mark a buffer as read */ ++#define VIRTIO_I2C_FLAGS_M_RD _BITUL(1) ++ ++/** ++ * struct virtio_i2c_out_hdr - the virtio I2C message OUT header ++ * @addr: the controlled device address ++ * @padding: used to pad to full dword ++ * @flags: used for feature extensibility ++ */ ++struct virtio_i2c_out_hdr { ++ uint16_t addr; ++ uint16_t padding; ++ uint32_t flags; ++}; ++ ++/** ++ * struct virtio_i2c_in_hdr - the virtio I2C message IN header ++ * @status: the processing result from the backend ++ */ ++struct virtio_i2c_in_hdr { ++ uint8_t status; ++}; ++ ++/* The final status written by the device */ ++#define VIRTIO_I2C_MSG_OK 0 ++#define VIRTIO_I2C_MSG_ERR 1 ++ ++#endif /* _LINUX_VIRTIO_I2C_H */ +diff --git a/include/standard-headers/linux/virtio_iommu.h b/include/standard-headers/linux/virtio_iommu.h +index b9443b83a1..366379c2f0 100644 +--- a/include/standard-headers/linux/virtio_iommu.h ++++ b/include/standard-headers/linux/virtio_iommu.h +@@ -16,6 +16,7 @@ + #define VIRTIO_IOMMU_F_BYPASS 3 + #define VIRTIO_IOMMU_F_PROBE 4 + #define VIRTIO_IOMMU_F_MMIO 5 ++#define VIRTIO_IOMMU_F_BYPASS_CONFIG 6 + + struct virtio_iommu_range_64 { + uint64_t start; +@@ -36,6 +37,8 @@ struct virtio_iommu_config { + struct virtio_iommu_range_32 domain_range; + /* Probe buffer size */ + uint32_t probe_size; ++ uint8_t bypass; ++ uint8_t reserved[3]; + }; + + /* Request types */ +@@ -66,11 +69,14 @@ struct virtio_iommu_req_tail { + uint8_t reserved[3]; + }; + ++#define VIRTIO_IOMMU_ATTACH_F_BYPASS (1 << 0) ++ + struct virtio_iommu_req_attach { + struct virtio_iommu_req_head head; + uint32_t domain; + uint32_t endpoint; +- uint8_t reserved[8]; ++ uint32_t flags; ++ uint8_t reserved[4]; + struct virtio_iommu_req_tail tail; + }; + +diff --git a/include/standard-headers/linux/virtio_pcidev.h b/include/standard-headers/linux/virtio_pcidev.h +new file mode 100644 +index 0000000000..bdf1d062da +--- /dev/null ++++ b/include/standard-headers/linux/virtio_pcidev.h +@@ -0,0 +1,65 @@ ++/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */ ++/* ++ * Copyright (C) 2021 Intel Corporation ++ * Author: Johannes Berg ++ */ ++#ifndef _LINUX_VIRTIO_PCIDEV_H ++#define _LINUX_VIRTIO_PCIDEV_H ++#include "standard-headers/linux/types.h" ++ ++/** ++ * enum virtio_pcidev_ops - virtual PCI device operations ++ * @VIRTIO_PCIDEV_OP_RESERVED: reserved to catch errors ++ * @VIRTIO_PCIDEV_OP_CFG_READ: read config space, size is 1, 2, 4 or 8; ++ * the @data field should be filled in by the device (in little endian). ++ * @VIRTIO_PCIDEV_OP_CFG_WRITE: write config space, size is 1, 2, 4 or 8; ++ * the @data field contains the data to write (in little endian). ++ * @VIRTIO_PCIDEV_OP_MMIO_READ: read BAR mem/pio, size can be variable; ++ * the @data field should be filled in by the device (in little endian). ++ * @VIRTIO_PCIDEV_OP_MMIO_WRITE: write BAR mem/pio, size can be variable; ++ * the @data field contains the data to write (in little endian). ++ * @VIRTIO_PCIDEV_OP_MMIO_MEMSET: memset MMIO, size is variable but ++ * the @data field only has one byte (unlike @VIRTIO_PCIDEV_OP_MMIO_WRITE) ++ * @VIRTIO_PCIDEV_OP_INT: legacy INTx# pin interrupt, the addr field is 1-4 for ++ * the number ++ * @VIRTIO_PCIDEV_OP_MSI: MSI(-X) interrupt, this message basically transports ++ * the 16- or 32-bit write that would otherwise be done into memory, ++ * analogous to the write messages (@VIRTIO_PCIDEV_OP_MMIO_WRITE) above ++ * @VIRTIO_PCIDEV_OP_PME: Dummy message whose content is ignored (and should be ++ * all zeroes) to signal the PME# pin. ++ */ ++enum virtio_pcidev_ops { ++ VIRTIO_PCIDEV_OP_RESERVED = 0, ++ VIRTIO_PCIDEV_OP_CFG_READ, ++ VIRTIO_PCIDEV_OP_CFG_WRITE, ++ VIRTIO_PCIDEV_OP_MMIO_READ, ++ VIRTIO_PCIDEV_OP_MMIO_WRITE, ++ VIRTIO_PCIDEV_OP_MMIO_MEMSET, ++ VIRTIO_PCIDEV_OP_INT, ++ VIRTIO_PCIDEV_OP_MSI, ++ VIRTIO_PCIDEV_OP_PME, ++}; ++ ++/** ++ * struct virtio_pcidev_msg - virtio PCI device operation ++ * @op: the operation to do ++ * @bar: the bar (only with BAR read/write messages) ++ * @reserved: reserved ++ * @size: the size of the read/write (in bytes) ++ * @addr: the address to read/write ++ * @data: the data, normally @size long, but just one byte for ++ * %VIRTIO_PCIDEV_OP_MMIO_MEMSET ++ * ++ * Note: the fields are all in native (CPU) endian, however, the ++ * @data values will often be in little endian (see the ops above.) ++ */ ++struct virtio_pcidev_msg { ++ uint8_t op; ++ uint8_t bar; ++ uint16_t reserved; ++ uint32_t size; ++ uint64_t addr; ++ uint8_t data[]; ++}; ++ ++#endif /* _LINUX_VIRTIO_PCIDEV_H */ +diff --git a/include/standard-headers/linux/virtio_scmi.h b/include/standard-headers/linux/virtio_scmi.h +new file mode 100644 +index 0000000000..8f2c305aea +--- /dev/null ++++ b/include/standard-headers/linux/virtio_scmi.h +@@ -0,0 +1,24 @@ ++/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */ ++/* ++ * Copyright (C) 2020-2021 OpenSynergy GmbH ++ * Copyright (C) 2021 ARM Ltd. ++ */ ++ ++#ifndef _LINUX_VIRTIO_SCMI_H ++#define _LINUX_VIRTIO_SCMI_H ++ ++#include "standard-headers/linux/virtio_types.h" ++ ++/* Device implements some SCMI notifications, or delayed responses. */ ++#define VIRTIO_SCMI_F_P2A_CHANNELS 0 ++ ++/* Device implements any SCMI statistics shared memory region */ ++#define VIRTIO_SCMI_F_SHARED_MEMORY 1 ++ ++/* Virtqueues */ ++ ++#define VIRTIO_SCMI_VQ_TX 0 /* cmdq */ ++#define VIRTIO_SCMI_VQ_RX 1 /* eventq */ ++#define VIRTIO_SCMI_VQ_MAX_CNT 2 ++ ++#endif /* _LINUX_VIRTIO_SCMI_H */ +diff --git a/linux-headers/asm-generic/unistd.h b/linux-headers/asm-generic/unistd.h +index 4557a8b608..1c48b0ae3b 100644 +--- a/linux-headers/asm-generic/unistd.h ++++ b/linux-headers/asm-generic/unistd.h +@@ -883,8 +883,11 @@ __SYSCALL(__NR_process_mrelease, sys_process_mrelease) + #define __NR_futex_waitv 449 + __SYSCALL(__NR_futex_waitv, sys_futex_waitv) + ++#define __NR_set_mempolicy_home_node 450 ++__SYSCALL(__NR_set_mempolicy_home_node, sys_set_mempolicy_home_node) ++ + #undef __NR_syscalls +-#define __NR_syscalls 450 ++#define __NR_syscalls 451 + + /* + * 32 bit systems traditionally used different +diff --git a/linux-headers/asm-mips/unistd_n32.h b/linux-headers/asm-mips/unistd_n32.h +index 4b3e7ad1ec..1f14a6fad3 100644 +--- a/linux-headers/asm-mips/unistd_n32.h ++++ b/linux-headers/asm-mips/unistd_n32.h +@@ -377,5 +377,7 @@ + #define __NR_landlock_add_rule (__NR_Linux + 445) + #define __NR_landlock_restrict_self (__NR_Linux + 446) + #define __NR_process_mrelease (__NR_Linux + 448) ++#define __NR_futex_waitv (__NR_Linux + 449) ++#define __NR_set_mempolicy_home_node (__NR_Linux + 450) + + #endif /* _ASM_UNISTD_N32_H */ +diff --git a/linux-headers/asm-mips/unistd_n64.h b/linux-headers/asm-mips/unistd_n64.h +index 488d9298d9..e5a8ebec78 100644 +--- a/linux-headers/asm-mips/unistd_n64.h ++++ b/linux-headers/asm-mips/unistd_n64.h +@@ -353,5 +353,7 @@ + #define __NR_landlock_add_rule (__NR_Linux + 445) + #define __NR_landlock_restrict_self (__NR_Linux + 446) + #define __NR_process_mrelease (__NR_Linux + 448) ++#define __NR_futex_waitv (__NR_Linux + 449) ++#define __NR_set_mempolicy_home_node (__NR_Linux + 450) + + #endif /* _ASM_UNISTD_N64_H */ +diff --git a/linux-headers/asm-mips/unistd_o32.h b/linux-headers/asm-mips/unistd_o32.h +index f47399870a..871d57168f 100644 +--- a/linux-headers/asm-mips/unistd_o32.h ++++ b/linux-headers/asm-mips/unistd_o32.h +@@ -423,5 +423,7 @@ + #define __NR_landlock_add_rule (__NR_Linux + 445) + #define __NR_landlock_restrict_self (__NR_Linux + 446) + #define __NR_process_mrelease (__NR_Linux + 448) ++#define __NR_futex_waitv (__NR_Linux + 449) ++#define __NR_set_mempolicy_home_node (__NR_Linux + 450) + + #endif /* _ASM_UNISTD_O32_H */ +diff --git a/linux-headers/asm-powerpc/unistd_32.h b/linux-headers/asm-powerpc/unistd_32.h +index 11d54696dc..585c7fefbc 100644 +--- a/linux-headers/asm-powerpc/unistd_32.h ++++ b/linux-headers/asm-powerpc/unistd_32.h +@@ -430,6 +430,8 @@ + #define __NR_landlock_add_rule 445 + #define __NR_landlock_restrict_self 446 + #define __NR_process_mrelease 448 ++#define __NR_futex_waitv 449 ++#define __NR_set_mempolicy_home_node 450 + + + #endif /* _ASM_UNISTD_32_H */ +diff --git a/linux-headers/asm-powerpc/unistd_64.h b/linux-headers/asm-powerpc/unistd_64.h +index cf740bab13..350f7ec0ac 100644 +--- a/linux-headers/asm-powerpc/unistd_64.h ++++ b/linux-headers/asm-powerpc/unistd_64.h +@@ -402,6 +402,8 @@ + #define __NR_landlock_add_rule 445 + #define __NR_landlock_restrict_self 446 + #define __NR_process_mrelease 448 ++#define __NR_futex_waitv 449 ++#define __NR_set_mempolicy_home_node 450 + + + #endif /* _ASM_UNISTD_64_H */ +diff --git a/linux-headers/asm-riscv/bitsperlong.h b/linux-headers/asm-riscv/bitsperlong.h +new file mode 100644 +index 0000000000..cc5c45a9ce +--- /dev/null ++++ b/linux-headers/asm-riscv/bitsperlong.h +@@ -0,0 +1,14 @@ ++/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ ++/* ++ * Copyright (C) 2012 ARM Ltd. ++ * Copyright (C) 2015 Regents of the University of California ++ */ ++ ++#ifndef _ASM_RISCV_BITSPERLONG_H ++#define _ASM_RISCV_BITSPERLONG_H ++ ++#define __BITS_PER_LONG (__SIZEOF_POINTER__ * 8) ++ ++#include ++ ++#endif /* _ASM_RISCV_BITSPERLONG_H */ +diff --git a/linux-headers/asm-riscv/mman.h b/linux-headers/asm-riscv/mman.h +new file mode 100644 +index 0000000000..8eebf89f5a +--- /dev/null ++++ b/linux-headers/asm-riscv/mman.h +@@ -0,0 +1 @@ ++#include +diff --git a/linux-headers/asm-riscv/unistd.h b/linux-headers/asm-riscv/unistd.h +new file mode 100644 +index 0000000000..8062996c2d +--- /dev/null ++++ b/linux-headers/asm-riscv/unistd.h +@@ -0,0 +1,44 @@ ++/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ ++/* ++ * Copyright (C) 2018 David Abdurachmanov ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ */ ++ ++#ifdef __LP64__ ++#define __ARCH_WANT_NEW_STAT ++#define __ARCH_WANT_SET_GET_RLIMIT ++#endif /* __LP64__ */ ++ ++#define __ARCH_WANT_SYS_CLONE3 ++ ++#include ++ ++/* ++ * Allows the instruction cache to be flushed from userspace. Despite RISC-V ++ * having a direct 'fence.i' instruction available to userspace (which we ++ * can't trap!), that's not actually viable when running on Linux because the ++ * kernel might schedule a process on another hart. There is no way for ++ * userspace to handle this without invoking the kernel (as it doesn't know the ++ * thread->hart mappings), so we've defined a RISC-V specific system call to ++ * flush the instruction cache. ++ * ++ * __NR_riscv_flush_icache is defined to flush the instruction cache over an ++ * address range, with the flush applying to either all threads or just the ++ * caller. We don't currently do anything with the address range, that's just ++ * in there for forwards compatibility. ++ */ ++#ifndef __NR_riscv_flush_icache ++#define __NR_riscv_flush_icache (__NR_arch_specific_syscall + 15) ++#endif ++__SYSCALL(__NR_riscv_flush_icache, sys_riscv_flush_icache) +diff --git a/linux-headers/asm-s390/unistd_32.h b/linux-headers/asm-s390/unistd_32.h +index 8f97d98128..8e644d65f5 100644 +--- a/linux-headers/asm-s390/unistd_32.h ++++ b/linux-headers/asm-s390/unistd_32.h +@@ -420,5 +420,7 @@ + #define __NR_landlock_add_rule 445 + #define __NR_landlock_restrict_self 446 + #define __NR_process_mrelease 448 ++#define __NR_futex_waitv 449 ++#define __NR_set_mempolicy_home_node 450 + + #endif /* _ASM_S390_UNISTD_32_H */ +diff --git a/linux-headers/asm-s390/unistd_64.h b/linux-headers/asm-s390/unistd_64.h +index 021ffc30e6..51da542fec 100644 +--- a/linux-headers/asm-s390/unistd_64.h ++++ b/linux-headers/asm-s390/unistd_64.h +@@ -368,5 +368,7 @@ + #define __NR_landlock_add_rule 445 + #define __NR_landlock_restrict_self 446 + #define __NR_process_mrelease 448 ++#define __NR_futex_waitv 449 ++#define __NR_set_mempolicy_home_node 450 + + #endif /* _ASM_S390_UNISTD_64_H */ +diff --git a/linux-headers/asm-x86/kvm.h b/linux-headers/asm-x86/kvm.h +index 5a776a08f7..2da3316bb5 100644 +--- a/linux-headers/asm-x86/kvm.h ++++ b/linux-headers/asm-x86/kvm.h +@@ -373,9 +373,23 @@ struct kvm_debugregs { + __u64 reserved[9]; + }; + +-/* for KVM_CAP_XSAVE */ ++/* for KVM_CAP_XSAVE and KVM_CAP_XSAVE2 */ + struct kvm_xsave { ++ /* ++ * KVM_GET_XSAVE2 and KVM_SET_XSAVE write and read as many bytes ++ * as are returned by KVM_CHECK_EXTENSION(KVM_CAP_XSAVE2) ++ * respectively, when invoked on the vm file descriptor. ++ * ++ * The size value returned by KVM_CHECK_EXTENSION(KVM_CAP_XSAVE2) ++ * will always be at least 4096. Currently, it is only greater ++ * than 4096 if a dynamic feature has been enabled with ++ * ``arch_prctl()``, but this may change in the future. ++ * ++ * The offsets of the state save areas in struct kvm_xsave follow ++ * the contents of CPUID leaf 0xD on the host. ++ */ + __u32 region[1024]; ++ __u32 extra[0]; + }; + + #define KVM_MAX_XCRS 16 +diff --git a/linux-headers/asm-x86/unistd_32.h b/linux-headers/asm-x86/unistd_32.h +index 9c9ffe312b..87e1e977af 100644 +--- a/linux-headers/asm-x86/unistd_32.h ++++ b/linux-headers/asm-x86/unistd_32.h +@@ -440,6 +440,7 @@ + #define __NR_memfd_secret 447 + #define __NR_process_mrelease 448 + #define __NR_futex_waitv 449 ++#define __NR_set_mempolicy_home_node 450 + + + #endif /* _ASM_UNISTD_32_H */ +diff --git a/linux-headers/asm-x86/unistd_64.h b/linux-headers/asm-x86/unistd_64.h +index 084f1eef9c..147a78d623 100644 +--- a/linux-headers/asm-x86/unistd_64.h ++++ b/linux-headers/asm-x86/unistd_64.h +@@ -362,6 +362,7 @@ + #define __NR_memfd_secret 447 + #define __NR_process_mrelease 448 + #define __NR_futex_waitv 449 ++#define __NR_set_mempolicy_home_node 450 + + + #endif /* _ASM_UNISTD_64_H */ +diff --git a/linux-headers/asm-x86/unistd_x32.h b/linux-headers/asm-x86/unistd_x32.h +index a2441affc2..27098db7fb 100644 +--- a/linux-headers/asm-x86/unistd_x32.h ++++ b/linux-headers/asm-x86/unistd_x32.h +@@ -315,6 +315,7 @@ + #define __NR_memfd_secret (__X32_SYSCALL_BIT + 447) + #define __NR_process_mrelease (__X32_SYSCALL_BIT + 448) + #define __NR_futex_waitv (__X32_SYSCALL_BIT + 449) ++#define __NR_set_mempolicy_home_node (__X32_SYSCALL_BIT + 450) + #define __NR_rt_sigaction (__X32_SYSCALL_BIT + 512) + #define __NR_rt_sigreturn (__X32_SYSCALL_BIT + 513) + #define __NR_ioctl (__X32_SYSCALL_BIT + 514) +diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h +index 02c5e7b7bb..00af3bc333 100644 +--- a/linux-headers/linux/kvm.h ++++ b/linux-headers/linux/kvm.h +@@ -1130,6 +1130,9 @@ struct kvm_ppc_resize_hpt { + #define KVM_CAP_BINARY_STATS_FD 203 + #define KVM_CAP_EXIT_ON_EMULATION_FAILURE 204 + #define KVM_CAP_ARM_MTE 205 ++#define KVM_CAP_VM_MOVE_ENC_CONTEXT_FROM 206 ++#define KVM_CAP_VM_GPA_BITS 207 ++#define KVM_CAP_XSAVE2 208 + + #ifdef KVM_CAP_IRQ_ROUTING + +@@ -1161,11 +1164,20 @@ struct kvm_irq_routing_hv_sint { + __u32 sint; + }; + ++struct kvm_irq_routing_xen_evtchn { ++ __u32 port; ++ __u32 vcpu; ++ __u32 priority; ++}; ++ ++#define KVM_IRQ_ROUTING_XEN_EVTCHN_PRIO_2LEVEL ((__u32)(-1)) ++ + /* gsi routing entry types */ + #define KVM_IRQ_ROUTING_IRQCHIP 1 + #define KVM_IRQ_ROUTING_MSI 2 + #define KVM_IRQ_ROUTING_S390_ADAPTER 3 + #define KVM_IRQ_ROUTING_HV_SINT 4 ++#define KVM_IRQ_ROUTING_XEN_EVTCHN 5 + + struct kvm_irq_routing_entry { + __u32 gsi; +@@ -1177,6 +1189,7 @@ struct kvm_irq_routing_entry { + struct kvm_irq_routing_msi msi; + struct kvm_irq_routing_s390_adapter adapter; + struct kvm_irq_routing_hv_sint hv_sint; ++ struct kvm_irq_routing_xen_evtchn xen_evtchn; + __u32 pad[8]; + } u; + }; +@@ -1207,6 +1220,7 @@ struct kvm_x86_mce { + #define KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL (1 << 1) + #define KVM_XEN_HVM_CONFIG_SHARED_INFO (1 << 2) + #define KVM_XEN_HVM_CONFIG_RUNSTATE (1 << 3) ++#define KVM_XEN_HVM_CONFIG_EVTCHN_2LEVEL (1 << 4) + + struct kvm_xen_hvm_config { + __u32 flags; +@@ -1609,6 +1623,9 @@ struct kvm_enc_region { + #define KVM_S390_NORMAL_RESET _IO(KVMIO, 0xc3) + #define KVM_S390_CLEAR_RESET _IO(KVMIO, 0xc4) + ++/* Available with KVM_CAP_XSAVE2 */ ++#define KVM_GET_XSAVE2 _IOR(KVMIO, 0xcf, struct kvm_xsave) ++ + struct kvm_s390_pv_sec_parm { + __u64 origin; + __u64 length; +-- +2.35.3 + diff --git a/kvm-linux-headers-include-missing-changes-from-5.17.patch b/kvm-linux-headers-include-missing-changes-from-5.17.patch new file mode 100644 index 0000000..1319926 --- /dev/null +++ b/kvm-linux-headers-include-missing-changes-from-5.17.patch @@ -0,0 +1,58 @@ +From aa6181d87e2b4ef1a70be002881908d2df5548a9 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Tue, 22 Feb 2022 17:58:11 +0100 +Subject: [PATCH 04/24] linux-headers: include missing changes from 5.17 + +RH-Author: Paul Lai +RH-MergeRequest: 176: Enable KVM AMX support +RH-Commit: [4/13] 2ed7cbc07e63d85cda916ef44d1e82b1fba7fdf4 +RH-Bugzilla: 1916415 +RH-Acked-by: Cornelia Huck +RH-Acked-by: Igor Mammedov +RH-Acked-by: Paolo Bonzini + +Signed-off-by: Paolo Bonzini +(cherry picked from commit 1ea5208febcc068449b63282d72bb719ab67a466) +Signed-off-by: Paul Lai +--- + linux-headers/asm-x86/kvm.h | 3 +++ + linux-headers/linux/kvm.h | 4 ++++ + 2 files changed, 7 insertions(+) + +diff --git a/linux-headers/asm-x86/kvm.h b/linux-headers/asm-x86/kvm.h +index 2da3316bb5..bf6e96011d 100644 +--- a/linux-headers/asm-x86/kvm.h ++++ b/linux-headers/asm-x86/kvm.h +@@ -452,6 +452,9 @@ struct kvm_sync_regs { + + #define KVM_STATE_VMX_PREEMPTION_TIMER_DEADLINE 0x00000001 + ++/* attributes for system fd (group 0) */ ++#define KVM_X86_XCOMP_GUEST_SUPP 0 ++ + struct kvm_vmx_nested_state_data { + __u8 vmcs12[KVM_STATE_NESTED_VMX_VMCS_SIZE]; + __u8 shadow_vmcs12[KVM_STATE_NESTED_VMX_VMCS_SIZE]; +diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h +index 00af3bc333..d232feaae9 100644 +--- a/linux-headers/linux/kvm.h ++++ b/linux-headers/linux/kvm.h +@@ -1133,6 +1133,7 @@ struct kvm_ppc_resize_hpt { + #define KVM_CAP_VM_MOVE_ENC_CONTEXT_FROM 206 + #define KVM_CAP_VM_GPA_BITS 207 + #define KVM_CAP_XSAVE2 208 ++#define KVM_CAP_SYS_ATTRIBUTES 209 + + #ifdef KVM_CAP_IRQ_ROUTING + +@@ -2047,4 +2048,7 @@ struct kvm_stats_desc { + + #define KVM_GET_STATS_FD _IO(KVMIO, 0xce) + ++/* Available with KVM_CAP_XSAVE2 */ ++#define KVM_GET_XSAVE2 _IOR(KVMIO, 0xcf, struct kvm_xsave) ++ + #endif /* __LINUX_KVM_H */ +-- +2.35.3 + diff --git a/kvm-linux-headers-update-to-5.16-rc1.patch b/kvm-linux-headers-update-to-5.16-rc1.patch new file mode 100644 index 0000000..1ad047b --- /dev/null +++ b/kvm-linux-headers-update-to-5.16-rc1.patch @@ -0,0 +1,725 @@ +From 64808db4a14867ad774b5e7535972a886e20a156 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Thu, 11 Nov 2021 12:06:01 +0100 +Subject: [PATCH 02/24] linux-headers: update to 5.16-rc1 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Paul Lai +RH-MergeRequest: 176: Enable KVM AMX support +RH-Commit: [2/13] 4af2f4942db029b81890e3862793fb54b62791cc +RH-Bugzilla: 1916415 +RH-Acked-by: Cornelia Huck +RH-Acked-by: Igor Mammedov +RH-Acked-by: Paolo Bonzini + +Signed-off-by: Paolo Bonzini +Acked-by: Cornelia Huck +Reviewed-by: Alex Bennée +Message-Id: <20211111110604.207376-3-pbonzini@redhat.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit 43709a0ca3b09e952bde3f38112f1d7fbf7c65b1) +Signed-off-by: Paul Lai +--- + include/standard-headers/drm/drm_fourcc.h | 121 +++++++++++++++++- + include/standard-headers/linux/ethtool.h | 31 +++++ + include/standard-headers/linux/fuse.h | 10 +- + include/standard-headers/linux/pci_regs.h | 6 + + include/standard-headers/linux/virtio_gpu.h | 18 ++- + include/standard-headers/linux/virtio_ids.h | 24 ++++ + include/standard-headers/linux/virtio_vsock.h | 3 +- + linux-headers/asm-arm64/unistd.h | 1 + + linux-headers/asm-generic/unistd.h | 22 +++- + linux-headers/asm-mips/unistd_n32.h | 1 + + linux-headers/asm-mips/unistd_n64.h | 1 + + linux-headers/asm-mips/unistd_o32.h | 1 + + linux-headers/asm-powerpc/unistd_32.h | 1 + + linux-headers/asm-powerpc/unistd_64.h | 1 + + linux-headers/asm-s390/unistd_32.h | 1 + + linux-headers/asm-s390/unistd_64.h | 1 + + linux-headers/asm-x86/kvm.h | 5 + + linux-headers/asm-x86/unistd_32.h | 3 + + linux-headers/asm-x86/unistd_64.h | 3 + + linux-headers/asm-x86/unistd_x32.h | 3 + + linux-headers/linux/kvm.h | 40 +++++- + 21 files changed, 276 insertions(+), 21 deletions(-) + +diff --git a/include/standard-headers/drm/drm_fourcc.h b/include/standard-headers/drm/drm_fourcc.h +index 352b51fd0a..2c025cb4fe 100644 +--- a/include/standard-headers/drm/drm_fourcc.h ++++ b/include/standard-headers/drm/drm_fourcc.h +@@ -103,6 +103,12 @@ extern "C" { + /* 8 bpp Red */ + #define DRM_FORMAT_R8 fourcc_code('R', '8', ' ', ' ') /* [7:0] R */ + ++/* 10 bpp Red */ ++#define DRM_FORMAT_R10 fourcc_code('R', '1', '0', ' ') /* [15:0] x:R 6:10 little endian */ ++ ++/* 12 bpp Red */ ++#define DRM_FORMAT_R12 fourcc_code('R', '1', '2', ' ') /* [15:0] x:R 4:12 little endian */ ++ + /* 16 bpp Red */ + #define DRM_FORMAT_R16 fourcc_code('R', '1', '6', ' ') /* [15:0] R little endian */ + +@@ -372,6 +378,12 @@ extern "C" { + + #define DRM_FORMAT_RESERVED ((1ULL << 56) - 1) + ++#define fourcc_mod_get_vendor(modifier) \ ++ (((modifier) >> 56) & 0xff) ++ ++#define fourcc_mod_is_vendor(modifier, vendor) \ ++ (fourcc_mod_get_vendor(modifier) == DRM_FORMAT_MOD_VENDOR_## vendor) ++ + #define fourcc_mod_code(vendor, val) \ + ((((uint64_t)DRM_FORMAT_MOD_VENDOR_## vendor) << 56) | ((val) & 0x00ffffffffffffffULL)) + +@@ -899,9 +911,9 @@ drm_fourcc_canonicalize_nvidia_format_mod(uint64_t modifier) + + /* + * The top 4 bits (out of the 56 bits alloted for specifying vendor specific +- * modifiers) denote the category for modifiers. Currently we have only two +- * categories of modifiers ie AFBC and MISC. We can have a maximum of sixteen +- * different categories. ++ * modifiers) denote the category for modifiers. Currently we have three ++ * categories of modifiers ie AFBC, MISC and AFRC. We can have a maximum of ++ * sixteen different categories. + */ + #define DRM_FORMAT_MOD_ARM_CODE(__type, __val) \ + fourcc_mod_code(ARM, ((uint64_t)(__type) << 52) | ((__val) & 0x000fffffffffffffULL)) +@@ -1016,6 +1028,109 @@ drm_fourcc_canonicalize_nvidia_format_mod(uint64_t modifier) + */ + #define AFBC_FORMAT_MOD_USM (1ULL << 12) + ++/* ++ * Arm Fixed-Rate Compression (AFRC) modifiers ++ * ++ * AFRC is a proprietary fixed rate image compression protocol and format, ++ * designed to provide guaranteed bandwidth and memory footprint ++ * reductions in graphics and media use-cases. ++ * ++ * AFRC buffers consist of one or more planes, with the same components ++ * and meaning as an uncompressed buffer using the same pixel format. ++ * ++ * Within each plane, the pixel/luma/chroma values are grouped into ++ * "coding unit" blocks which are individually compressed to a ++ * fixed size (in bytes). All coding units within a given plane of a buffer ++ * store the same number of values, and have the same compressed size. ++ * ++ * The coding unit size is configurable, allowing different rates of compression. ++ * ++ * The start of each AFRC buffer plane must be aligned to an alignment granule which ++ * depends on the coding unit size. ++ * ++ * Coding Unit Size Plane Alignment ++ * ---------------- --------------- ++ * 16 bytes 1024 bytes ++ * 24 bytes 512 bytes ++ * 32 bytes 2048 bytes ++ * ++ * Coding units are grouped into paging tiles. AFRC buffer dimensions must be aligned ++ * to a multiple of the paging tile dimensions. ++ * The dimensions of each paging tile depend on whether the buffer is optimised for ++ * scanline (SCAN layout) or rotated (ROT layout) access. ++ * ++ * Layout Paging Tile Width Paging Tile Height ++ * ------ ----------------- ------------------ ++ * SCAN 16 coding units 4 coding units ++ * ROT 8 coding units 8 coding units ++ * ++ * The dimensions of each coding unit depend on the number of components ++ * in the compressed plane and whether the buffer is optimised for ++ * scanline (SCAN layout) or rotated (ROT layout) access. ++ * ++ * Number of Components in Plane Layout Coding Unit Width Coding Unit Height ++ * ----------------------------- --------- ----------------- ------------------ ++ * 1 SCAN 16 samples 4 samples ++ * Example: 16x4 luma samples in a 'Y' plane ++ * 16x4 chroma 'V' values, in the 'V' plane of a fully-planar YUV buffer ++ * ----------------------------- --------- ----------------- ------------------ ++ * 1 ROT 8 samples 8 samples ++ * Example: 8x8 luma samples in a 'Y' plane ++ * 8x8 chroma 'V' values, in the 'V' plane of a fully-planar YUV buffer ++ * ----------------------------- --------- ----------------- ------------------ ++ * 2 DONT CARE 8 samples 4 samples ++ * Example: 8x4 chroma pairs in the 'UV' plane of a semi-planar YUV buffer ++ * ----------------------------- --------- ----------------- ------------------ ++ * 3 DONT CARE 4 samples 4 samples ++ * Example: 4x4 pixels in an RGB buffer without alpha ++ * ----------------------------- --------- ----------------- ------------------ ++ * 4 DONT CARE 4 samples 4 samples ++ * Example: 4x4 pixels in an RGB buffer with alpha ++ */ ++ ++#define DRM_FORMAT_MOD_ARM_TYPE_AFRC 0x02 ++ ++#define DRM_FORMAT_MOD_ARM_AFRC(__afrc_mode) \ ++ DRM_FORMAT_MOD_ARM_CODE(DRM_FORMAT_MOD_ARM_TYPE_AFRC, __afrc_mode) ++ ++/* ++ * AFRC coding unit size modifier. ++ * ++ * Indicates the number of bytes used to store each compressed coding unit for ++ * one or more planes in an AFRC encoded buffer. The coding unit size for chrominance ++ * is the same for both Cb and Cr, which may be stored in separate planes. ++ * ++ * AFRC_FORMAT_MOD_CU_SIZE_P0 indicates the number of bytes used to store ++ * each compressed coding unit in the first plane of the buffer. For RGBA buffers ++ * this is the only plane, while for semi-planar and fully-planar YUV buffers, ++ * this corresponds to the luma plane. ++ * ++ * AFRC_FORMAT_MOD_CU_SIZE_P12 indicates the number of bytes used to store ++ * each compressed coding unit in the second and third planes in the buffer. ++ * For semi-planar and fully-planar YUV buffers, this corresponds to the chroma plane(s). ++ * ++ * For single-plane buffers, AFRC_FORMAT_MOD_CU_SIZE_P0 must be specified ++ * and AFRC_FORMAT_MOD_CU_SIZE_P12 must be zero. ++ * For semi-planar and fully-planar buffers, both AFRC_FORMAT_MOD_CU_SIZE_P0 and ++ * AFRC_FORMAT_MOD_CU_SIZE_P12 must be specified. ++ */ ++#define AFRC_FORMAT_MOD_CU_SIZE_MASK 0xf ++#define AFRC_FORMAT_MOD_CU_SIZE_16 (1ULL) ++#define AFRC_FORMAT_MOD_CU_SIZE_24 (2ULL) ++#define AFRC_FORMAT_MOD_CU_SIZE_32 (3ULL) ++ ++#define AFRC_FORMAT_MOD_CU_SIZE_P0(__afrc_cu_size) (__afrc_cu_size) ++#define AFRC_FORMAT_MOD_CU_SIZE_P12(__afrc_cu_size) ((__afrc_cu_size) << 4) ++ ++/* ++ * AFRC scanline memory layout. ++ * ++ * Indicates if the buffer uses the scanline-optimised layout ++ * for an AFRC encoded buffer, otherwise, it uses the rotation-optimised layout. ++ * The memory layout is the same for all planes. ++ */ ++#define AFRC_FORMAT_MOD_LAYOUT_SCAN (1ULL << 8) ++ + /* + * Arm 16x16 Block U-Interleaved modifier + * +diff --git a/include/standard-headers/linux/ethtool.h b/include/standard-headers/linux/ethtool.h +index 053d3fafdf..688eb8dc39 100644 +--- a/include/standard-headers/linux/ethtool.h ++++ b/include/standard-headers/linux/ethtool.h +@@ -603,6 +603,7 @@ enum ethtool_link_ext_state { + ETHTOOL_LINK_EXT_STATE_CALIBRATION_FAILURE, + ETHTOOL_LINK_EXT_STATE_POWER_BUDGET_EXCEEDED, + ETHTOOL_LINK_EXT_STATE_OVERHEAT, ++ ETHTOOL_LINK_EXT_STATE_MODULE, + }; + + /* More information in addition to ETHTOOL_LINK_EXT_STATE_AUTONEG. */ +@@ -639,6 +640,8 @@ enum ethtool_link_ext_substate_link_logical_mismatch { + enum ethtool_link_ext_substate_bad_signal_integrity { + ETHTOOL_LINK_EXT_SUBSTATE_BSI_LARGE_NUMBER_OF_PHYSICAL_ERRORS = 1, + ETHTOOL_LINK_EXT_SUBSTATE_BSI_UNSUPPORTED_RATE, ++ ETHTOOL_LINK_EXT_SUBSTATE_BSI_SERDES_REFERENCE_CLOCK_LOST, ++ ETHTOOL_LINK_EXT_SUBSTATE_BSI_SERDES_ALOS, + }; + + /* More information in addition to ETHTOOL_LINK_EXT_STATE_CABLE_ISSUE. */ +@@ -647,6 +650,11 @@ enum ethtool_link_ext_substate_cable_issue { + ETHTOOL_LINK_EXT_SUBSTATE_CI_CABLE_TEST_FAILURE, + }; + ++/* More information in addition to ETHTOOL_LINK_EXT_STATE_MODULE. */ ++enum ethtool_link_ext_substate_module { ++ ETHTOOL_LINK_EXT_SUBSTATE_MODULE_CMIS_NOT_READY = 1, ++}; ++ + #define ETH_GSTRING_LEN 32 + + /** +@@ -704,6 +712,29 @@ enum ethtool_stringset { + ETH_SS_COUNT + }; + ++/** ++ * enum ethtool_module_power_mode_policy - plug-in module power mode policy ++ * @ETHTOOL_MODULE_POWER_MODE_POLICY_HIGH: Module is always in high power mode. ++ * @ETHTOOL_MODULE_POWER_MODE_POLICY_AUTO: Module is transitioned by the host ++ * to high power mode when the first port using it is put administratively ++ * up and to low power mode when the last port using it is put ++ * administratively down. ++ */ ++enum ethtool_module_power_mode_policy { ++ ETHTOOL_MODULE_POWER_MODE_POLICY_HIGH = 1, ++ ETHTOOL_MODULE_POWER_MODE_POLICY_AUTO, ++}; ++ ++/** ++ * enum ethtool_module_power_mode - plug-in module power mode ++ * @ETHTOOL_MODULE_POWER_MODE_LOW: Module is in low power mode. ++ * @ETHTOOL_MODULE_POWER_MODE_HIGH: Module is in high power mode. ++ */ ++enum ethtool_module_power_mode { ++ ETHTOOL_MODULE_POWER_MODE_LOW = 1, ++ ETHTOOL_MODULE_POWER_MODE_HIGH, ++}; ++ + /** + * struct ethtool_gstrings - string set for data tagging + * @cmd: Command number = %ETHTOOL_GSTRINGS +diff --git a/include/standard-headers/linux/fuse.h b/include/standard-headers/linux/fuse.h +index cce105bfba..23ea31708b 100644 +--- a/include/standard-headers/linux/fuse.h ++++ b/include/standard-headers/linux/fuse.h +@@ -181,6 +181,9 @@ + * - add FUSE_OPEN_KILL_SUIDGID + * - extend fuse_setxattr_in, add FUSE_SETXATTR_EXT + * - add FUSE_SETXATTR_ACL_KILL_SGID ++ * ++ * 7.34 ++ * - add FUSE_SYNCFS + */ + + #ifndef _LINUX_FUSE_H +@@ -212,7 +215,7 @@ + #define FUSE_KERNEL_VERSION 7 + + /** Minor version number of this interface */ +-#define FUSE_KERNEL_MINOR_VERSION 33 ++#define FUSE_KERNEL_MINOR_VERSION 34 + + /** The node ID of the root inode */ + #define FUSE_ROOT_ID 1 +@@ -505,6 +508,7 @@ enum fuse_opcode { + FUSE_COPY_FILE_RANGE = 47, + FUSE_SETUPMAPPING = 48, + FUSE_REMOVEMAPPING = 49, ++ FUSE_SYNCFS = 50, + + /* CUSE specific operations */ + CUSE_INIT = 4096, +@@ -967,4 +971,8 @@ struct fuse_removemapping_one { + #define FUSE_REMOVEMAPPING_MAX_ENTRY \ + (PAGE_SIZE / sizeof(struct fuse_removemapping_one)) + ++struct fuse_syncfs_in { ++ uint64_t padding; ++}; ++ + #endif /* _LINUX_FUSE_H */ +diff --git a/include/standard-headers/linux/pci_regs.h b/include/standard-headers/linux/pci_regs.h +index e709ae8235..ff6ccbc6ef 100644 +--- a/include/standard-headers/linux/pci_regs.h ++++ b/include/standard-headers/linux/pci_regs.h +@@ -504,6 +504,12 @@ + #define PCI_EXP_DEVCTL_URRE 0x0008 /* Unsupported Request Reporting En. */ + #define PCI_EXP_DEVCTL_RELAX_EN 0x0010 /* Enable relaxed ordering */ + #define PCI_EXP_DEVCTL_PAYLOAD 0x00e0 /* Max_Payload_Size */ ++#define PCI_EXP_DEVCTL_PAYLOAD_128B 0x0000 /* 128 Bytes */ ++#define PCI_EXP_DEVCTL_PAYLOAD_256B 0x0020 /* 256 Bytes */ ++#define PCI_EXP_DEVCTL_PAYLOAD_512B 0x0040 /* 512 Bytes */ ++#define PCI_EXP_DEVCTL_PAYLOAD_1024B 0x0060 /* 1024 Bytes */ ++#define PCI_EXP_DEVCTL_PAYLOAD_2048B 0x0080 /* 2048 Bytes */ ++#define PCI_EXP_DEVCTL_PAYLOAD_4096B 0x00a0 /* 4096 Bytes */ + #define PCI_EXP_DEVCTL_EXT_TAG 0x0100 /* Extended Tag Field Enable */ + #define PCI_EXP_DEVCTL_PHANTOM 0x0200 /* Phantom Functions Enable */ + #define PCI_EXP_DEVCTL_AUX_PME 0x0400 /* Auxiliary Power PM Enable */ +diff --git a/include/standard-headers/linux/virtio_gpu.h b/include/standard-headers/linux/virtio_gpu.h +index 1357e4774e..2da48d3d4c 100644 +--- a/include/standard-headers/linux/virtio_gpu.h ++++ b/include/standard-headers/linux/virtio_gpu.h +@@ -59,6 +59,11 @@ + * VIRTIO_GPU_CMD_RESOURCE_CREATE_BLOB + */ + #define VIRTIO_GPU_F_RESOURCE_BLOB 3 ++/* ++ * VIRTIO_GPU_CMD_CREATE_CONTEXT with ++ * context_init and multiple timelines ++ */ ++#define VIRTIO_GPU_F_CONTEXT_INIT 4 + + enum virtio_gpu_ctrl_type { + VIRTIO_GPU_UNDEFINED = 0, +@@ -122,14 +127,20 @@ enum virtio_gpu_shm_id { + VIRTIO_GPU_SHM_ID_HOST_VISIBLE = 1 + }; + +-#define VIRTIO_GPU_FLAG_FENCE (1 << 0) ++#define VIRTIO_GPU_FLAG_FENCE (1 << 0) ++/* ++ * If the following flag is set, then ring_idx contains the index ++ * of the command ring that needs to used when creating the fence ++ */ ++#define VIRTIO_GPU_FLAG_INFO_RING_IDX (1 << 1) + + struct virtio_gpu_ctrl_hdr { + uint32_t type; + uint32_t flags; + uint64_t fence_id; + uint32_t ctx_id; +- uint32_t padding; ++ uint8_t ring_idx; ++ uint8_t padding[3]; + }; + + /* data passed in the cursor vq */ +@@ -269,10 +280,11 @@ struct virtio_gpu_resource_create_3d { + }; + + /* VIRTIO_GPU_CMD_CTX_CREATE */ ++#define VIRTIO_GPU_CONTEXT_INIT_CAPSET_ID_MASK 0x000000ff + struct virtio_gpu_ctx_create { + struct virtio_gpu_ctrl_hdr hdr; + uint32_t nlen; +- uint32_t padding; ++ uint32_t context_init; + char debug_name[64]; + }; + +diff --git a/include/standard-headers/linux/virtio_ids.h b/include/standard-headers/linux/virtio_ids.h +index 4fe842c3a3..80d76b75bc 100644 +--- a/include/standard-headers/linux/virtio_ids.h ++++ b/include/standard-headers/linux/virtio_ids.h +@@ -54,7 +54,31 @@ + #define VIRTIO_ID_SOUND 25 /* virtio sound */ + #define VIRTIO_ID_FS 26 /* virtio filesystem */ + #define VIRTIO_ID_PMEM 27 /* virtio pmem */ ++#define VIRTIO_ID_RPMB 28 /* virtio rpmb */ + #define VIRTIO_ID_MAC80211_HWSIM 29 /* virtio mac80211-hwsim */ ++#define VIRTIO_ID_VIDEO_ENCODER 30 /* virtio video encoder */ ++#define VIRTIO_ID_VIDEO_DECODER 31 /* virtio video decoder */ ++#define VIRTIO_ID_SCMI 32 /* virtio SCMI */ ++#define VIRTIO_ID_NITRO_SEC_MOD 33 /* virtio nitro secure module*/ ++#define VIRTIO_ID_I2C_ADAPTER 34 /* virtio i2c adapter */ ++#define VIRTIO_ID_WATCHDOG 35 /* virtio watchdog */ ++#define VIRTIO_ID_CAN 36 /* virtio can */ ++#define VIRTIO_ID_DMABUF 37 /* virtio dmabuf */ ++#define VIRTIO_ID_PARAM_SERV 38 /* virtio parameter server */ ++#define VIRTIO_ID_AUDIO_POLICY 39 /* virtio audio policy */ + #define VIRTIO_ID_BT 40 /* virtio bluetooth */ ++#define VIRTIO_ID_GPIO 41 /* virtio gpio */ ++ ++/* ++ * Virtio Transitional IDs ++ */ ++ ++#define VIRTIO_TRANS_ID_NET 1000 /* transitional virtio net */ ++#define VIRTIO_TRANS_ID_BLOCK 1001 /* transitional virtio block */ ++#define VIRTIO_TRANS_ID_BALLOON 1002 /* transitional virtio balloon */ ++#define VIRTIO_TRANS_ID_CONSOLE 1003 /* transitional virtio console */ ++#define VIRTIO_TRANS_ID_SCSI 1004 /* transitional virtio SCSI */ ++#define VIRTIO_TRANS_ID_RNG 1005 /* transitional virtio rng */ ++#define VIRTIO_TRANS_ID_9P 1009 /* transitional virtio 9p console */ + + #endif /* _LINUX_VIRTIO_IDS_H */ +diff --git a/include/standard-headers/linux/virtio_vsock.h b/include/standard-headers/linux/virtio_vsock.h +index 3a23488e42..467e751b17 100644 +--- a/include/standard-headers/linux/virtio_vsock.h ++++ b/include/standard-headers/linux/virtio_vsock.h +@@ -97,7 +97,8 @@ enum virtio_vsock_shutdown { + + /* VIRTIO_VSOCK_OP_RW flags values */ + enum virtio_vsock_rw { +- VIRTIO_VSOCK_SEQ_EOR = 1, ++ VIRTIO_VSOCK_SEQ_EOM = 1, ++ VIRTIO_VSOCK_SEQ_EOR = 2, + }; + + #endif /* _LINUX_VIRTIO_VSOCK_H */ +diff --git a/linux-headers/asm-arm64/unistd.h b/linux-headers/asm-arm64/unistd.h +index f83a70e07d..ce2ee8f1e3 100644 +--- a/linux-headers/asm-arm64/unistd.h ++++ b/linux-headers/asm-arm64/unistd.h +@@ -20,5 +20,6 @@ + #define __ARCH_WANT_SET_GET_RLIMIT + #define __ARCH_WANT_TIME32_SYSCALLS + #define __ARCH_WANT_SYS_CLONE3 ++#define __ARCH_WANT_MEMFD_SECRET + + #include +diff --git a/linux-headers/asm-generic/unistd.h b/linux-headers/asm-generic/unistd.h +index f211961ce1..4557a8b608 100644 +--- a/linux-headers/asm-generic/unistd.h ++++ b/linux-headers/asm-generic/unistd.h +@@ -673,15 +673,15 @@ __SYSCALL(__NR_madvise, sys_madvise) + #define __NR_remap_file_pages 234 + __SYSCALL(__NR_remap_file_pages, sys_remap_file_pages) + #define __NR_mbind 235 +-__SC_COMP(__NR_mbind, sys_mbind, compat_sys_mbind) ++__SYSCALL(__NR_mbind, sys_mbind) + #define __NR_get_mempolicy 236 +-__SC_COMP(__NR_get_mempolicy, sys_get_mempolicy, compat_sys_get_mempolicy) ++__SYSCALL(__NR_get_mempolicy, sys_get_mempolicy) + #define __NR_set_mempolicy 237 +-__SC_COMP(__NR_set_mempolicy, sys_set_mempolicy, compat_sys_set_mempolicy) ++__SYSCALL(__NR_set_mempolicy, sys_set_mempolicy) + #define __NR_migrate_pages 238 +-__SC_COMP(__NR_migrate_pages, sys_migrate_pages, compat_sys_migrate_pages) ++__SYSCALL(__NR_migrate_pages, sys_migrate_pages) + #define __NR_move_pages 239 +-__SC_COMP(__NR_move_pages, sys_move_pages, compat_sys_move_pages) ++__SYSCALL(__NR_move_pages, sys_move_pages) + #endif + + #define __NR_rt_tgsigqueueinfo 240 +@@ -873,8 +873,18 @@ __SYSCALL(__NR_landlock_add_rule, sys_landlock_add_rule) + #define __NR_landlock_restrict_self 446 + __SYSCALL(__NR_landlock_restrict_self, sys_landlock_restrict_self) + ++#ifdef __ARCH_WANT_MEMFD_SECRET ++#define __NR_memfd_secret 447 ++__SYSCALL(__NR_memfd_secret, sys_memfd_secret) ++#endif ++#define __NR_process_mrelease 448 ++__SYSCALL(__NR_process_mrelease, sys_process_mrelease) ++ ++#define __NR_futex_waitv 449 ++__SYSCALL(__NR_futex_waitv, sys_futex_waitv) ++ + #undef __NR_syscalls +-#define __NR_syscalls 447 ++#define __NR_syscalls 450 + + /* + * 32 bit systems traditionally used different +diff --git a/linux-headers/asm-mips/unistd_n32.h b/linux-headers/asm-mips/unistd_n32.h +index 09cd297698..4b3e7ad1ec 100644 +--- a/linux-headers/asm-mips/unistd_n32.h ++++ b/linux-headers/asm-mips/unistd_n32.h +@@ -376,5 +376,6 @@ + #define __NR_landlock_create_ruleset (__NR_Linux + 444) + #define __NR_landlock_add_rule (__NR_Linux + 445) + #define __NR_landlock_restrict_self (__NR_Linux + 446) ++#define __NR_process_mrelease (__NR_Linux + 448) + + #endif /* _ASM_UNISTD_N32_H */ +diff --git a/linux-headers/asm-mips/unistd_n64.h b/linux-headers/asm-mips/unistd_n64.h +index 780e0cead6..488d9298d9 100644 +--- a/linux-headers/asm-mips/unistd_n64.h ++++ b/linux-headers/asm-mips/unistd_n64.h +@@ -352,5 +352,6 @@ + #define __NR_landlock_create_ruleset (__NR_Linux + 444) + #define __NR_landlock_add_rule (__NR_Linux + 445) + #define __NR_landlock_restrict_self (__NR_Linux + 446) ++#define __NR_process_mrelease (__NR_Linux + 448) + + #endif /* _ASM_UNISTD_N64_H */ +diff --git a/linux-headers/asm-mips/unistd_o32.h b/linux-headers/asm-mips/unistd_o32.h +index 06a2b3b55e..f47399870a 100644 +--- a/linux-headers/asm-mips/unistd_o32.h ++++ b/linux-headers/asm-mips/unistd_o32.h +@@ -422,5 +422,6 @@ + #define __NR_landlock_create_ruleset (__NR_Linux + 444) + #define __NR_landlock_add_rule (__NR_Linux + 445) + #define __NR_landlock_restrict_self (__NR_Linux + 446) ++#define __NR_process_mrelease (__NR_Linux + 448) + + #endif /* _ASM_UNISTD_O32_H */ +diff --git a/linux-headers/asm-powerpc/unistd_32.h b/linux-headers/asm-powerpc/unistd_32.h +index cd5a8a41b2..11d54696dc 100644 +--- a/linux-headers/asm-powerpc/unistd_32.h ++++ b/linux-headers/asm-powerpc/unistd_32.h +@@ -429,6 +429,7 @@ + #define __NR_landlock_create_ruleset 444 + #define __NR_landlock_add_rule 445 + #define __NR_landlock_restrict_self 446 ++#define __NR_process_mrelease 448 + + + #endif /* _ASM_UNISTD_32_H */ +diff --git a/linux-headers/asm-powerpc/unistd_64.h b/linux-headers/asm-powerpc/unistd_64.h +index 8458effa8d..cf740bab13 100644 +--- a/linux-headers/asm-powerpc/unistd_64.h ++++ b/linux-headers/asm-powerpc/unistd_64.h +@@ -401,6 +401,7 @@ + #define __NR_landlock_create_ruleset 444 + #define __NR_landlock_add_rule 445 + #define __NR_landlock_restrict_self 446 ++#define __NR_process_mrelease 448 + + + #endif /* _ASM_UNISTD_64_H */ +diff --git a/linux-headers/asm-s390/unistd_32.h b/linux-headers/asm-s390/unistd_32.h +index 0c3cd299e4..8f97d98128 100644 +--- a/linux-headers/asm-s390/unistd_32.h ++++ b/linux-headers/asm-s390/unistd_32.h +@@ -419,5 +419,6 @@ + #define __NR_landlock_create_ruleset 444 + #define __NR_landlock_add_rule 445 + #define __NR_landlock_restrict_self 446 ++#define __NR_process_mrelease 448 + + #endif /* _ASM_S390_UNISTD_32_H */ +diff --git a/linux-headers/asm-s390/unistd_64.h b/linux-headers/asm-s390/unistd_64.h +index 8dfc08b5e6..021ffc30e6 100644 +--- a/linux-headers/asm-s390/unistd_64.h ++++ b/linux-headers/asm-s390/unistd_64.h +@@ -367,5 +367,6 @@ + #define __NR_landlock_create_ruleset 444 + #define __NR_landlock_add_rule 445 + #define __NR_landlock_restrict_self 446 ++#define __NR_process_mrelease 448 + + #endif /* _ASM_S390_UNISTD_64_H */ +diff --git a/linux-headers/asm-x86/kvm.h b/linux-headers/asm-x86/kvm.h +index a6c327f8ad..5a776a08f7 100644 +--- a/linux-headers/asm-x86/kvm.h ++++ b/linux-headers/asm-x86/kvm.h +@@ -295,6 +295,7 @@ struct kvm_debug_exit_arch { + #define KVM_GUESTDBG_USE_HW_BP 0x00020000 + #define KVM_GUESTDBG_INJECT_DB 0x00040000 + #define KVM_GUESTDBG_INJECT_BP 0x00080000 ++#define KVM_GUESTDBG_BLOCKIRQ 0x00100000 + + /* for KVM_SET_GUEST_DEBUG */ + struct kvm_guest_debug_arch { +@@ -503,4 +504,8 @@ struct kvm_pmu_event_filter { + #define KVM_PMU_EVENT_ALLOW 0 + #define KVM_PMU_EVENT_DENY 1 + ++/* for KVM_{GET,SET,HAS}_DEVICE_ATTR */ ++#define KVM_VCPU_TSC_CTRL 0 /* control group for the timestamp counter (TSC) */ ++#define KVM_VCPU_TSC_OFFSET 0 /* attribute for the TSC offset */ ++ + #endif /* _ASM_X86_KVM_H */ +diff --git a/linux-headers/asm-x86/unistd_32.h b/linux-headers/asm-x86/unistd_32.h +index 66e96c0c68..9c9ffe312b 100644 +--- a/linux-headers/asm-x86/unistd_32.h ++++ b/linux-headers/asm-x86/unistd_32.h +@@ -437,6 +437,9 @@ + #define __NR_landlock_create_ruleset 444 + #define __NR_landlock_add_rule 445 + #define __NR_landlock_restrict_self 446 ++#define __NR_memfd_secret 447 ++#define __NR_process_mrelease 448 ++#define __NR_futex_waitv 449 + + + #endif /* _ASM_UNISTD_32_H */ +diff --git a/linux-headers/asm-x86/unistd_64.h b/linux-headers/asm-x86/unistd_64.h +index b8ff6f14ee..084f1eef9c 100644 +--- a/linux-headers/asm-x86/unistd_64.h ++++ b/linux-headers/asm-x86/unistd_64.h +@@ -359,6 +359,9 @@ + #define __NR_landlock_create_ruleset 444 + #define __NR_landlock_add_rule 445 + #define __NR_landlock_restrict_self 446 ++#define __NR_memfd_secret 447 ++#define __NR_process_mrelease 448 ++#define __NR_futex_waitv 449 + + + #endif /* _ASM_UNISTD_64_H */ +diff --git a/linux-headers/asm-x86/unistd_x32.h b/linux-headers/asm-x86/unistd_x32.h +index 06a1097c15..a2441affc2 100644 +--- a/linux-headers/asm-x86/unistd_x32.h ++++ b/linux-headers/asm-x86/unistd_x32.h +@@ -312,6 +312,9 @@ + #define __NR_landlock_create_ruleset (__X32_SYSCALL_BIT + 444) + #define __NR_landlock_add_rule (__X32_SYSCALL_BIT + 445) + #define __NR_landlock_restrict_self (__X32_SYSCALL_BIT + 446) ++#define __NR_memfd_secret (__X32_SYSCALL_BIT + 447) ++#define __NR_process_mrelease (__X32_SYSCALL_BIT + 448) ++#define __NR_futex_waitv (__X32_SYSCALL_BIT + 449) + #define __NR_rt_sigaction (__X32_SYSCALL_BIT + 512) + #define __NR_rt_sigreturn (__X32_SYSCALL_BIT + 513) + #define __NR_ioctl (__X32_SYSCALL_BIT + 514) +diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h +index bcaf66cc4d..02c5e7b7bb 100644 +--- a/linux-headers/linux/kvm.h ++++ b/linux-headers/linux/kvm.h +@@ -269,6 +269,7 @@ struct kvm_xen_exit { + #define KVM_EXIT_AP_RESET_HOLD 32 + #define KVM_EXIT_X86_BUS_LOCK 33 + #define KVM_EXIT_XEN 34 ++#define KVM_EXIT_RISCV_SBI 35 + + /* For KVM_EXIT_INTERNAL_ERROR */ + /* Emulate instruction failed. */ +@@ -397,13 +398,23 @@ struct kvm_run { + * "ndata" is correct, that new fields are enumerated in "flags", + * and that each flag enumerates fields that are 64-bit aligned + * and sized (so that ndata+internal.data[] is valid/accurate). ++ * ++ * Space beyond the defined fields may be used to store arbitrary ++ * debug information relating to the emulation failure. It is ++ * accounted for in "ndata" but the format is unspecified and is ++ * not represented in "flags". Any such information is *not* ABI! + */ + struct { + __u32 suberror; + __u32 ndata; + __u64 flags; +- __u8 insn_size; +- __u8 insn_bytes[15]; ++ union { ++ struct { ++ __u8 insn_size; ++ __u8 insn_bytes[15]; ++ }; ++ }; ++ /* Arbitrary debug data may follow. */ + } emulation_failure; + /* KVM_EXIT_OSI */ + struct { +@@ -469,6 +480,13 @@ struct kvm_run { + } msr; + /* KVM_EXIT_XEN */ + struct kvm_xen_exit xen; ++ /* KVM_EXIT_RISCV_SBI */ ++ struct { ++ unsigned long extension_id; ++ unsigned long function_id; ++ unsigned long args[6]; ++ unsigned long ret[2]; ++ } riscv_sbi; + /* Fix the size of the union. */ + char padding[256]; + }; +@@ -1223,11 +1241,16 @@ struct kvm_irqfd { + + /* Do not use 1, KVM_CHECK_EXTENSION returned it before we had flags. */ + #define KVM_CLOCK_TSC_STABLE 2 ++#define KVM_CLOCK_REALTIME (1 << 2) ++#define KVM_CLOCK_HOST_TSC (1 << 3) + + struct kvm_clock_data { + __u64 clock; + __u32 flags; +- __u32 pad[9]; ++ __u32 pad0; ++ __u64 realtime; ++ __u64 host_tsc; ++ __u32 pad[4]; + }; + + /* For KVM_CAP_SW_TLB */ +@@ -1965,7 +1988,9 @@ struct kvm_stats_header { + #define KVM_STATS_TYPE_CUMULATIVE (0x0 << KVM_STATS_TYPE_SHIFT) + #define KVM_STATS_TYPE_INSTANT (0x1 << KVM_STATS_TYPE_SHIFT) + #define KVM_STATS_TYPE_PEAK (0x2 << KVM_STATS_TYPE_SHIFT) +-#define KVM_STATS_TYPE_MAX KVM_STATS_TYPE_PEAK ++#define KVM_STATS_TYPE_LINEAR_HIST (0x3 << KVM_STATS_TYPE_SHIFT) ++#define KVM_STATS_TYPE_LOG_HIST (0x4 << KVM_STATS_TYPE_SHIFT) ++#define KVM_STATS_TYPE_MAX KVM_STATS_TYPE_LOG_HIST + + #define KVM_STATS_UNIT_SHIFT 4 + #define KVM_STATS_UNIT_MASK (0xF << KVM_STATS_UNIT_SHIFT) +@@ -1988,8 +2013,9 @@ struct kvm_stats_header { + * @size: The number of data items for this stats. + * Every data item is of type __u64. + * @offset: The offset of the stats to the start of stat structure in +- * struture kvm or kvm_vcpu. +- * @unused: Unused field for future usage. Always 0 for now. ++ * structure kvm or kvm_vcpu. ++ * @bucket_size: A parameter value used for histogram stats. It is only used ++ * for linear histogram stats, specifying the size of the bucket; + * @name: The name string for the stats. Its size is indicated by the + * &kvm_stats_header->name_size. + */ +@@ -1998,7 +2024,7 @@ struct kvm_stats_desc { + __s16 exponent; + __u16 size; + __u32 offset; +- __u32 unused; ++ __u32 bucket_size; + char name[]; + }; + +-- +2.35.3 + diff --git a/kvm-migration-Add-migrate_use_tls-helper.patch b/kvm-migration-Add-migrate_use_tls-helper.patch index 338ddb8..8fdfe68 100644 --- a/kvm-migration-Add-migrate_use_tls-helper.patch +++ b/kvm-migration-Add-migrate_use_tls-helper.patch @@ -1,18 +1,18 @@ -From c7ff8b8916f28928185bbe937a5701e1770ab5f4 Mon Sep 17 00:00:00 2001 +From a7c6bc008fe006f005d5c15d3f883572ad5defc5 Mon Sep 17 00:00:00 2001 From: Leonardo Bras Date: Wed, 18 May 2022 02:52:25 -0300 -Subject: [PATCH 20/34] migration: Add migrate_use_tls() helper +Subject: [PATCH 20/37] migration: Add migrate_use_tls() helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RH-Author: Leonardo Brás -RH-MergeRequest: 185: MSG_ZEROCOPY + Multifd @ rhel8.6 -RH-Commit: [20/34] 41a1ec2f4ef5c873ed80cf055bb5a582e2273495 -RH-Bugzilla: 2117252 -RH-Acked-by: quintela1 -RH-Acked-by: Dr. David Alan Gilbert +RH-MergeRequest: 191: MSG_ZEROCOPY + Multifd @ rhel8.7 +RH-Commit: [20/26] 02afc2e60f1abbf6db45d83e54a18b66dad52426 +RH-Bugzilla: 2072049 RH-Acked-by: Peter Xu +RH-Acked-by: Daniel P. Berrangé +RH-Acked-by: Dr. David Alan Gilbert A lot of places check parameters.tls_creds in order to evaluate if TLS is in use, and sometimes call migrate_get_current() just for that test. diff --git a/kvm-migration-Add-migration_incoming_transport_cleanup.patch b/kvm-migration-Add-migration_incoming_transport_cleanup.patch new file mode 100644 index 0000000..985bbe2 --- /dev/null +++ b/kvm-migration-Add-migration_incoming_transport_cleanup.patch @@ -0,0 +1,102 @@ +From 02eab793d82cd3c82d31f1e1f34d16fcc30caf0e Mon Sep 17 00:00:00 2001 +From: Peter Xu +Date: Tue, 1 Mar 2022 16:39:14 +0800 +Subject: [PATCH 27/37] migration: Add migration_incoming_transport_cleanup() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Peter Xu +RH-MergeRequest: 195: migration: Allow migrate-recover to run multiple times +RH-Commit: [1/2] 57b2a9a165ee7cb2d01519bd54eb8dc4185815e0 +RH-Bugzilla: 2097652 +RH-Acked-by: Leonardo Brás +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Hanna Reitz + +Add a helper to cleanup the transport listener. + +When do it, we should also null-ify the cleanup hook and the data, then it's +even safe to call it multiple times. + +Move the socket_address_list cleanup altogether, because that's a mirror of the +listener channels and only for the purpose of query-migrate. Hence when +someone wants to cleanup the listener transport, it should also want to cleanup +the socket list too, always. + +No functional change intended. + +Reviewed-by: Dr. David Alan Gilbert +Signed-off-by: Peter Xu +Message-Id: <20220301083925.33483-15-peterx@redhat.com> +Signed-off-by: Dr. David Alan Gilbert +(cherry picked from commit e031149c78489413038e934eec9f54ac699cf322) +Signed-off-by: Peter Xu +--- + migration/migration.c | 22 ++++++++++++++-------- + migration/migration.h | 1 + + 2 files changed, 15 insertions(+), 8 deletions(-) + +diff --git a/migration/migration.c b/migration/migration.c +index c8aa55d2fe..b787a36789 100644 +--- a/migration/migration.c ++++ b/migration/migration.c +@@ -263,6 +263,19 @@ MigrationIncomingState *migration_incoming_get_current(void) + return current_incoming; + } + ++void migration_incoming_transport_cleanup(MigrationIncomingState *mis) ++{ ++ if (mis->socket_address_list) { ++ qapi_free_SocketAddressList(mis->socket_address_list); ++ mis->socket_address_list = NULL; ++ } ++ ++ if (mis->transport_cleanup) { ++ mis->transport_cleanup(mis->transport_data); ++ mis->transport_data = mis->transport_cleanup = NULL; ++ } ++} ++ + void migration_incoming_state_destroy(void) + { + struct MigrationIncomingState *mis = migration_incoming_get_current(); +@@ -283,10 +296,8 @@ void migration_incoming_state_destroy(void) + g_array_free(mis->postcopy_remote_fds, TRUE); + mis->postcopy_remote_fds = NULL; + } +- if (mis->transport_cleanup) { +- mis->transport_cleanup(mis->transport_data); +- } + ++ migration_incoming_transport_cleanup(mis); + qemu_event_reset(&mis->main_thread_load_event); + + if (mis->page_requested) { +@@ -294,11 +305,6 @@ void migration_incoming_state_destroy(void) + mis->page_requested = NULL; + } + +- if (mis->socket_address_list) { +- qapi_free_SocketAddressList(mis->socket_address_list); +- mis->socket_address_list = NULL; +- } +- + yank_unregister_instance(MIGRATION_YANK_INSTANCE); + } + +diff --git a/migration/migration.h b/migration/migration.h +index 9396b7e90a..243898e3be 100644 +--- a/migration/migration.h ++++ b/migration/migration.h +@@ -130,6 +130,7 @@ struct MigrationIncomingState { + + MigrationIncomingState *migration_incoming_get_current(void); + void migration_incoming_state_destroy(void); ++void migration_incoming_transport_cleanup(MigrationIncomingState *mis); + /* + * Functions to work with blocktime context + */ +-- +2.35.3 + diff --git a/kvm-migration-Add-zero-copy-send-parameter-for-QMP-HMP-f.patch b/kvm-migration-Add-zero-copy-send-parameter-for-QMP-HMP-f.patch index bae187a..63e67c6 100644 --- a/kvm-migration-Add-zero-copy-send-parameter-for-QMP-HMP-f.patch +++ b/kvm-migration-Add-zero-copy-send-parameter-for-QMP-HMP-f.patch @@ -1,19 +1,19 @@ -From c71da4b1c1c4cf089f74394ffc596d0fd0235800 Mon Sep 17 00:00:00 2001 +From 2a84bf822cae38f67458043cd379a22e0fd22485 Mon Sep 17 00:00:00 2001 From: Leonardo Bras Date: Wed, 18 May 2022 02:52:25 -0300 -Subject: [PATCH 19/34] migration: Add zero-copy-send parameter for QMP/HMP for +Subject: [PATCH 19/37] migration: Add zero-copy-send parameter for QMP/HMP for Linux MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RH-Author: Leonardo Brás -RH-MergeRequest: 185: MSG_ZEROCOPY + Multifd @ rhel8.6 -RH-Commit: [19/34] 96e64f4beb41ffc6cf34341114666598d3d53aeb -RH-Bugzilla: 2117252 -RH-Acked-by: quintela1 -RH-Acked-by: Dr. David Alan Gilbert +RH-MergeRequest: 191: MSG_ZEROCOPY + Multifd @ rhel8.7 +RH-Commit: [19/26] 44ec703088cad75fd6e504958527e81d3261c9df +RH-Bugzilla: 2072049 RH-Acked-by: Peter Xu +RH-Acked-by: Daniel P. Berrangé +RH-Acked-by: Dr. David Alan Gilbert Add property that allows zero-copy migration of memory pages on the sending side, and also includes a helper function diff --git a/kvm-migration-All-this-fields-are-unsigned.patch b/kvm-migration-All-this-fields-are-unsigned.patch index 390ab62..245e2b4 100644 --- a/kvm-migration-All-this-fields-are-unsigned.patch +++ b/kvm-migration-All-this-fields-are-unsigned.patch @@ -1,18 +1,18 @@ -From 4fead335ef5aca7c70296c082b0abc872e053d30 Mon Sep 17 00:00:00 2001 +From b21f18afceba8231c78d29e66f58516e12c28d22 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 18 May 2022 02:52:23 -0300 -Subject: [PATCH 10/34] migration: All this fields are unsigned +Subject: [PATCH 10/37] migration: All this fields are unsigned MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RH-Author: Leonardo Brás -RH-MergeRequest: 185: MSG_ZEROCOPY + Multifd @ rhel8.6 -RH-Commit: [10/34] 59e3378a852a31a9942d1dd8255a9c08e442f53b -RH-Bugzilla: 2117252 -RH-Acked-by: quintela1 -RH-Acked-by: Dr. David Alan Gilbert +RH-MergeRequest: 191: MSG_ZEROCOPY + Multifd @ rhel8.7 +RH-Commit: [10/26] 2c3ee27aae334db3b283ab7ef580f58e396e569d +RH-Bugzilla: 2072049 RH-Acked-by: Peter Xu +RH-Acked-by: Daniel P. Berrangé +RH-Acked-by: Dr. David Alan Gilbert So printing it as %d is wrong. Notice that for the channel id, that is an uint8_t, but I changed it anyways for consistency. diff --git a/kvm-migration-Allow-migrate-recover-to-run-multiple-time.patch b/kvm-migration-Allow-migrate-recover-to-run-multiple-time.patch new file mode 100644 index 0000000..b4f1e68 --- /dev/null +++ b/kvm-migration-Allow-migrate-recover-to-run-multiple-time.patch @@ -0,0 +1,98 @@ +From f5be3d8a5944679c1239b974e0f910f1afe4f532 Mon Sep 17 00:00:00 2001 +From: Peter Xu +Date: Thu, 31 Mar 2022 11:08:45 -0400 +Subject: [PATCH 28/37] migration: Allow migrate-recover to run multiple times +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Peter Xu +RH-MergeRequest: 195: migration: Allow migrate-recover to run multiple times +RH-Commit: [2/2] a2e6b02007a06c9c7f5237289095811c7d7ca1f1 +RH-Bugzilla: 2097652 +RH-Acked-by: Leonardo Brás +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Hanna Reitz + +Previously migration didn't have an easy way to cleanup the listening +transport, migrate recovery only allows to execute once. That's done with a +trick flag in postcopy_recover_triggered. + +Now the facility is already there. + +Drop postcopy_recover_triggered and instead allows a new migrate-recover to +release the previous listener transport. + +Reviewed-by: Dr. David Alan Gilbert +Signed-off-by: Peter Xu +Message-Id: <20220331150857.74406-8-peterx@redhat.com> +Reviewed-by: Daniel P. Berrangé +Signed-off-by: Dr. David Alan Gilbert +(cherry picked from commit 08401c0426bc1a5ce4609afd1cda5dd39abbf9fa) +Signed-off-by: Peter Xu +--- + migration/migration.c | 13 ++----------- + migration/migration.h | 1 - + migration/savevm.c | 3 --- + 3 files changed, 2 insertions(+), 15 deletions(-) + +diff --git a/migration/migration.c b/migration/migration.c +index b787a36789..616c3ff32e 100644 +--- a/migration/migration.c ++++ b/migration/migration.c +@@ -2158,11 +2158,8 @@ void qmp_migrate_recover(const char *uri, Error **errp) + return; + } + +- if (qatomic_cmpxchg(&mis->postcopy_recover_triggered, +- false, true) == true) { +- error_setg(errp, "Migrate recovery is triggered already"); +- return; +- } ++ /* If there's an existing transport, release it */ ++ migration_incoming_transport_cleanup(mis); + + /* + * Note that this call will never start a real migration; it will +@@ -2170,12 +2167,6 @@ void qmp_migrate_recover(const char *uri, Error **errp) + * to continue using that newly established channel. + */ + qemu_start_incoming_migration(uri, errp); +- +- /* Safe to dereference with the assert above */ +- if (*errp) { +- /* Reset the flag so user could still retry */ +- qatomic_set(&mis->postcopy_recover_triggered, false); +- } + } + + void qmp_migrate_pause(Error **errp) +diff --git a/migration/migration.h b/migration/migration.h +index 243898e3be..0ae2133326 100644 +--- a/migration/migration.h ++++ b/migration/migration.h +@@ -103,7 +103,6 @@ struct MigrationIncomingState { + struct PostcopyBlocktimeContext *blocktime_ctx; + + /* notify PAUSED postcopy incoming migrations to try to continue */ +- bool postcopy_recover_triggered; + QemuSemaphore postcopy_pause_sem_dst; + QemuSemaphore postcopy_pause_sem_fault; + +diff --git a/migration/savevm.c b/migration/savevm.c +index 0bef031acb..b8382aaa64 100644 +--- a/migration/savevm.c ++++ b/migration/savevm.c +@@ -2568,9 +2568,6 @@ static bool postcopy_pause_incoming(MigrationIncomingState *mis) + + assert(migrate_postcopy_ram()); + +- /* Clear the triggered bit to allow one recovery */ +- mis->postcopy_recover_triggered = false; +- + /* + * Unregister yank with either from/to src would work, since ioc behind it + * is the same +-- +2.35.3 + diff --git a/kvm-migration-Avoid-false-positive-on-non-supported-scen.patch b/kvm-migration-Avoid-false-positive-on-non-supported-scen.patch index c69a941..f1a7d49 100644 --- a/kvm-migration-Avoid-false-positive-on-non-supported-scen.patch +++ b/kvm-migration-Avoid-false-positive-on-non-supported-scen.patch @@ -1,19 +1,19 @@ -From cfcde3507dd742c0e17cdfe3ac3bf076cc131a84 Mon Sep 17 00:00:00 2001 +From 097f72427f4f5da4fdcdbeee52aea0c1f67d54dc Mon Sep 17 00:00:00 2001 From: Leonardo Bras Date: Tue, 19 Jul 2022 09:23:45 -0300 -Subject: [PATCH 32/34] migration: Avoid false-positive on non-supported +Subject: [PATCH 6/9] migration: Avoid false-positive on non-supported scenarios for zero-copy-send MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RH-Author: Leonardo Brás -RH-MergeRequest: 185: MSG_ZEROCOPY + Multifd @ rhel8.6 -RH-Commit: [32/34] 409d9f974c5d69cdb4df8ef44f45c6cb25638144 -RH-Bugzilla: 2117252 -RH-Acked-by: quintela1 +RH-MergeRequest: 201: Zero-copy-send fixes + improvements +RH-Commit: [6/8] f23195f3ab4f6eba0463f38e5971ccaccdac2cfd +RH-Bugzilla: 2110203 RH-Acked-by: Dr. David Alan Gilbert RH-Acked-by: Peter Xu +RH-Acked-by: Miroslav Rezanina Migration with zero-copy-send currently has it's limitations, as it can't be used with TLS nor any kind of compression. In such scenarios, it should @@ -56,10 +56,10 @@ Signed-off-by: Leonardo Bras 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/migration/migration.c b/migration/migration.c -index a3e0ac954c..b1fe50a749 100644 +index 952a26c5c2..35b3197eff 100644 --- a/migration/migration.c +++ b/migration/migration.c -@@ -1254,7 +1254,9 @@ static bool migrate_caps_check(bool *cap_list, +@@ -1260,7 +1260,9 @@ static bool migrate_caps_check(bool *cap_list, #ifdef CONFIG_LINUX if (cap_list[MIGRATION_CAPABILITY_ZERO_COPY_SEND] && (!cap_list[MIGRATION_CAPABILITY_MULTIFD] || @@ -70,7 +70,7 @@ index a3e0ac954c..b1fe50a749 100644 migrate_use_tls())) { error_setg(errp, "Zero copy only available for non-compressed non-TLS multifd migration"); -@@ -1491,6 +1493,17 @@ static bool migrate_params_check(MigrationParameters *params, Error **errp) +@@ -1497,6 +1499,17 @@ static bool migrate_params_check(MigrationParameters *params, Error **errp) error_prepend(errp, "Invalid mapping given for block-bitmap-mapping: "); return false; } @@ -89,5 +89,5 @@ index a3e0ac954c..b1fe50a749 100644 } -- -2.35.3 +2.31.1 diff --git a/kvm-migration-Change-zero_copy_send-from-migration-param.patch b/kvm-migration-Change-zero_copy_send-from-migration-param.patch index 35a8958..b1f576d 100644 --- a/kvm-migration-Change-zero_copy_send-from-migration-param.patch +++ b/kvm-migration-Change-zero_copy_send-from-migration-param.patch @@ -1,19 +1,19 @@ -From a1853831de58b56278ef02964fd8c86ed19c2007 Mon Sep 17 00:00:00 2001 +From 70108ff9ffe77062116e47670c0e0c2396529f88 Mon Sep 17 00:00:00 2001 From: Leonardo Bras Date: Mon, 20 Jun 2022 02:39:45 -0300 -Subject: [PATCH 26/34] migration: Change zero_copy_send from migration +Subject: [PATCH 26/37] migration: Change zero_copy_send from migration parameter to migration capability MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RH-Author: Leonardo Brás -RH-MergeRequest: 185: MSG_ZEROCOPY + Multifd @ rhel8.6 -RH-Commit: [26/34] 249c0aaac45b33db0ba2f6d2010d61947d4e96f9 -RH-Bugzilla: 2117252 -RH-Acked-by: quintela1 -RH-Acked-by: Dr. David Alan Gilbert +RH-MergeRequest: 191: MSG_ZEROCOPY + Multifd @ rhel8.7 +RH-Commit: [26/26] ea61e6cbdbe47611bd22d18988e1c4c4e8357cc3 +RH-Bugzilla: 2072049 RH-Acked-by: Peter Xu +RH-Acked-by: Daniel P. Berrangé +RH-Acked-by: Dr. David Alan Gilbert When originally implemented, zero_copy_send was designed as a Migration paramenter. diff --git a/kvm-migration-Introduce-ram_transferred_add.patch b/kvm-migration-Introduce-ram_transferred_add.patch index 1339e20..561e231 100644 --- a/kvm-migration-Introduce-ram_transferred_add.patch +++ b/kvm-migration-Introduce-ram_transferred_add.patch @@ -1,18 +1,18 @@ -From be7a79cd5eb65f9835593f353220a3fe4fa7f30c Mon Sep 17 00:00:00 2001 +From 030b54f5a2b2c8976370c962e9847af4746ac2c2 Mon Sep 17 00:00:00 2001 From: David Edmondson Date: Tue, 21 Dec 2021 09:34:40 +0000 -Subject: [PATCH 27/34] migration: Introduce ram_transferred_add() +Subject: [PATCH 1/9] migration: Introduce ram_transferred_add() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RH-Author: Leonardo Brás -RH-MergeRequest: 185: MSG_ZEROCOPY + Multifd @ rhel8.6 -RH-Commit: [27/34] fdc6eea0f4cf5ace0a71d981218ce150e98654ff -RH-Bugzilla: 2117252 -RH-Acked-by: quintela1 +RH-MergeRequest: 201: Zero-copy-send fixes + improvements +RH-Commit: [1/8] a6545760b0de13d533f6164be0545a6720bb42c7 +RH-Bugzilla: 2110203 RH-Acked-by: Dr. David Alan Gilbert RH-Acked-by: Peter Xu +RH-Acked-by: Miroslav Rezanina Replace direct manipulation of ram_counters.transferred with a function. @@ -118,5 +118,5 @@ index 3e208efca7..3e82c4ff46 100644 ret = qemu_file_get_error(f); } -- -2.35.3 +2.31.1 diff --git a/kvm-migration-Never-call-twice-qemu_target_page_size.patch b/kvm-migration-Never-call-twice-qemu_target_page_size.patch index 45d143c..d956712 100644 --- a/kvm-migration-Never-call-twice-qemu_target_page_size.patch +++ b/kvm-migration-Never-call-twice-qemu_target_page_size.patch @@ -1,18 +1,18 @@ -From 2bde4dfec804afa72a3b18e41798612256fe1722 Mon Sep 17 00:00:00 2001 +From 6a9a5a2809cbbe2982df156722b88efeec998e3d Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 18 May 2022 02:52:22 -0300 -Subject: [PATCH 01/34] migration: Never call twice qemu_target_page_size() +Subject: [PATCH 01/37] migration: Never call twice qemu_target_page_size() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RH-Author: Leonardo Brás -RH-MergeRequest: 185: MSG_ZEROCOPY + Multifd @ rhel8.6 -RH-Commit: [1/34] 0c99a1b9648103cfba65e724578e922ab05cce78 -RH-Bugzilla: 2117252 -RH-Acked-by: quintela1 -RH-Acked-by: Dr. David Alan Gilbert +RH-MergeRequest: 191: MSG_ZEROCOPY + Multifd @ rhel8.7 +RH-Commit: [1/26] 809ca84dec80bafc1959df8c9e57f482ee752a97 +RH-Bugzilla: 2072049 RH-Acked-by: Peter Xu +RH-Acked-by: Daniel P. Berrangé +RH-Acked-by: Dr. David Alan Gilbert Signed-off-by: Juan Quintela Reviewed-by: Dr. David Alan Gilbert diff --git a/kvm-migration-Tally-pre-copy-downtime-and-post-copy-byte.patch b/kvm-migration-Tally-pre-copy-downtime-and-post-copy-byte.patch index c9ff787..1cf4724 100644 --- a/kvm-migration-Tally-pre-copy-downtime-and-post-copy-byte.patch +++ b/kvm-migration-Tally-pre-copy-downtime-and-post-copy-byte.patch @@ -1,19 +1,19 @@ -From 849a82a35629d480cdfa451310b77edd5ee00aa4 Mon Sep 17 00:00:00 2001 +From 82637509cc9197ad9d1e1b286a608bf0da04b7b3 Mon Sep 17 00:00:00 2001 From: David Edmondson Date: Tue, 21 Dec 2021 09:34:41 +0000 -Subject: [PATCH 28/34] migration: Tally pre-copy, downtime and post-copy bytes +Subject: [PATCH 2/9] migration: Tally pre-copy, downtime and post-copy bytes independently MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RH-Author: Leonardo Brás -RH-MergeRequest: 185: MSG_ZEROCOPY + Multifd @ rhel8.6 -RH-Commit: [28/34] a6e61ae2f016d020b2456be6087aeb7d4b9f9387 -RH-Bugzilla: 2117252 -RH-Acked-by: quintela1 +RH-MergeRequest: 201: Zero-copy-send fixes + improvements +RH-Commit: [2/8] 7d1bf37a3d93da88da6525d70fc1fce1abb92b83 +RH-Bugzilla: 2110203 RH-Acked-by: Dr. David Alan Gilbert RH-Acked-by: Peter Xu +RH-Acked-by: Miroslav Rezanina Provide information on the number of bytes copied in the pre-copy, downtime and post-copy phases of migration. @@ -32,10 +32,10 @@ Signed-off-by: Leonardo Bras 4 files changed, 34 insertions(+), 1 deletion(-) diff --git a/migration/migration.c b/migration/migration.c -index c8aa55d2fe..87b4a6c3f9 100644 +index 616c3ff32e..e100b30f00 100644 --- a/migration/migration.c +++ b/migration/migration.c -@@ -1010,6 +1010,9 @@ static void populate_ram_info(MigrationInfo *info, MigrationState *s) +@@ -1016,6 +1016,9 @@ static void populate_ram_info(MigrationInfo *info, MigrationState *s) info->ram->page_size = page_size; info->ram->multifd_bytes = ram_counters.multifd_bytes; info->ram->pages_per_second = s->pages_per_second; @@ -118,5 +118,5 @@ index fe70a0c4b2..c8ec260ab0 100644 ## # @XBZRLECacheStats: -- -2.35.3 +2.31.1 diff --git a/kvm-migration-add-remaining-params-has_-true-in-migratio.patch b/kvm-migration-add-remaining-params-has_-true-in-migratio.patch index a985c87..73011b3 100644 --- a/kvm-migration-add-remaining-params-has_-true-in-migratio.patch +++ b/kvm-migration-add-remaining-params-has_-true-in-migratio.patch @@ -1,19 +1,19 @@ -From d40f63360fc8677ac2ac3a679bab4c1e3dbe334f Mon Sep 17 00:00:00 2001 +From 8aecb49fdd771c5819fccc9e750b2e9cd4e94b58 Mon Sep 17 00:00:00 2001 From: Leonardo Bras Date: Mon, 25 Jul 2022 22:02:35 -0300 -Subject: [PATCH 33/34] migration: add remaining params->has_* = true in +Subject: [PATCH 7/9] migration: add remaining params->has_* = true in migration_instance_init() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RH-Author: Leonardo Brás -RH-MergeRequest: 185: MSG_ZEROCOPY + Multifd @ rhel8.6 -RH-Commit: [33/34] cc70a134ae27296e8a07dffd4dfccf1a329f27f1 -RH-Bugzilla: 2117252 -RH-Acked-by: quintela1 +RH-MergeRequest: 201: Zero-copy-send fixes + improvements +RH-Commit: [7/8] fb622e5b88e14eb859d4903d9c088ba6ca63fc81 +RH-Bugzilla: 2110203 RH-Acked-by: Dr. David Alan Gilbert RH-Acked-by: Peter Xu +RH-Acked-by: Miroslav Rezanina Some of params->has_* = true are missing in migration_instance_init, this causes migrate_params_check() to skip some tests, allowing some @@ -36,10 +36,10 @@ Signed-off-by: Leonardo Bras 1 file changed, 4 insertions(+) diff --git a/migration/migration.c b/migration/migration.c -index b1fe50a749..02f962ead0 100644 +index 35b3197eff..51e6726dac 100644 --- a/migration/migration.c +++ b/migration/migration.c -@@ -4337,6 +4337,7 @@ static void migration_instance_init(Object *obj) +@@ -4334,6 +4334,7 @@ static void migration_instance_init(Object *obj) /* Set has_* up only for parameter checks */ params->has_compress_level = true; params->has_compress_threads = true; @@ -47,7 +47,7 @@ index b1fe50a749..02f962ead0 100644 params->has_decompress_threads = true; params->has_throttle_trigger_threshold = true; params->has_cpu_throttle_initial = true; -@@ -4357,6 +4358,9 @@ static void migration_instance_init(Object *obj) +@@ -4354,6 +4355,9 @@ static void migration_instance_init(Object *obj) params->has_announce_max = true; params->has_announce_rounds = true; params->has_announce_step = true; @@ -58,5 +58,5 @@ index b1fe50a749..02f962ead0 100644 qemu_sem_init(&ms->postcopy_pause_sem, 0); qemu_sem_init(&ms->postcopy_pause_rp_sem, 0); -- -2.35.3 +2.31.1 diff --git a/kvm-migration-multifd-Report-to-user-when-zerocopy-not-w.patch b/kvm-migration-multifd-Report-to-user-when-zerocopy-not-w.patch index c155736..5008e15 100644 --- a/kvm-migration-multifd-Report-to-user-when-zerocopy-not-w.patch +++ b/kvm-migration-multifd-Report-to-user-when-zerocopy-not-w.patch @@ -1,19 +1,19 @@ -From e7497ea1a0fa4d4a10fb76f3a274df29e487a277 Mon Sep 17 00:00:00 2001 +From 2516a21205e67078cb735e9fd47ba50156c166b7 Mon Sep 17 00:00:00 2001 From: Leonardo Bras Date: Mon, 11 Jul 2022 18:11:13 -0300 -Subject: [PATCH 31/34] migration/multifd: Report to user when zerocopy not +Subject: [PATCH 5/9] migration/multifd: Report to user when zerocopy not working MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RH-Author: Leonardo Brás -RH-MergeRequest: 185: MSG_ZEROCOPY + Multifd @ rhel8.6 -RH-Commit: [31/34] 5aa1b4e6cfc23dd8474844ef8ffa9eb996355e20 -RH-Bugzilla: 2117252 -RH-Acked-by: quintela1 +RH-MergeRequest: 201: Zero-copy-send fixes + improvements +RH-Commit: [5/8] 0b2e23b7f8ae72936e11369cd44ba474ef3b9e8c +RH-Bugzilla: 2110203 RH-Acked-by: Dr. David Alan Gilbert RH-Acked-by: Peter Xu +RH-Acked-by: Miroslav Rezanina Some errors, like the lack of Scatter-Gather support by the network interface(NETIF_F_SG) may cause sendmsg(...,MSG_ZEROCOPY) to fail on using @@ -79,5 +79,5 @@ index c515396a9a..69c3ccb26a 100644 + #endif -- -2.35.3 +2.31.1 diff --git a/kvm-multifd-Add-missing-documention.patch b/kvm-multifd-Add-missing-documentation.patch similarity index 88% rename from kvm-multifd-Add-missing-documention.patch rename to kvm-multifd-Add-missing-documentation.patch index a4efe49..361f0c1 100644 --- a/kvm-multifd-Add-missing-documention.patch +++ b/kvm-multifd-Add-missing-documentation.patch @@ -1,22 +1,23 @@ -From a5a03cd1ffc772c9d2bbf8e97e971b0cb8daa617 Mon Sep 17 00:00:00 2001 +From 3b567f762cbd8d4ffaf717b0baba9cf9fe9614c2 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 18 May 2022 02:52:23 -0300 -Subject: [PATCH 03/34] multifd: Add missing documention +Subject: [PATCH 03/37] multifd: Add missing documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RH-Author: Leonardo Brás -RH-MergeRequest: 185: MSG_ZEROCOPY + Multifd @ rhel8.6 -RH-Commit: [3/34] 3f73bc1414f80a3611c7a807671a04ddb16ec7da -RH-Bugzilla: 2117252 -RH-Acked-by: quintela1 -RH-Acked-by: Dr. David Alan Gilbert +RH-MergeRequest: 191: MSG_ZEROCOPY + Multifd @ rhel8.7 +RH-Commit: [3/26] 924fca4305ebd8669955d456fc1c515f509e6026 +RH-Bugzilla: 2072049 RH-Acked-by: Peter Xu +RH-Acked-by: Daniel P. Berrangé +RH-Acked-by: Dr. David Alan Gilbert Signed-off-by: Juan Quintela Reviewed-by: Dr. David Alan Gilbert (cherry picked from commit 18ede636bc29fd8bda628fe3e5c593f8c1b734f4) +(fixed typo in commit message) Signed-off-by: Leonardo Bras --- migration/multifd-zlib.c | 2 ++ diff --git a/kvm-multifd-Fill-offset-and-block-for-reception.patch b/kvm-multifd-Fill-offset-and-block-for-reception.patch index 41ef14c..7996f87 100644 --- a/kvm-multifd-Fill-offset-and-block-for-reception.patch +++ b/kvm-multifd-Fill-offset-and-block-for-reception.patch @@ -1,18 +1,18 @@ -From ff3315e41f6e33e2ef7d764e064be60b3b7670e4 Mon Sep 17 00:00:00 2001 +From 8c1edb1889ff44506f35fa185d6569b0dd9d7260 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 18 May 2022 02:52:23 -0300 -Subject: [PATCH 07/34] multifd: Fill offset and block for reception +Subject: [PATCH 07/37] multifd: Fill offset and block for reception MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RH-Author: Leonardo Brás -RH-MergeRequest: 185: MSG_ZEROCOPY + Multifd @ rhel8.6 -RH-Commit: [7/34] e1c460e910a7de2bbe21221b4c54da0bbc09b4c0 -RH-Bugzilla: 2117252 -RH-Acked-by: quintela1 -RH-Acked-by: Dr. David Alan Gilbert +RH-MergeRequest: 191: MSG_ZEROCOPY + Multifd @ rhel8.7 +RH-Commit: [7/26] 51a9e6b76af956d63fc735172211d9bf6f0f6f80 +RH-Bugzilla: 2072049 RH-Acked-by: Peter Xu +RH-Acked-by: Daniel P. Berrangé +RH-Acked-by: Dr. David Alan Gilbert We were using the iov directly, but we will need this info on the following patch. diff --git a/kvm-multifd-Implement-zero-copy-write-in-multifd-migrati.patch b/kvm-multifd-Implement-zero-copy-write-in-multifd-migrati.patch index 3243f19..dccdf1f 100644 --- a/kvm-multifd-Implement-zero-copy-write-in-multifd-migrati.patch +++ b/kvm-multifd-Implement-zero-copy-write-in-multifd-migrati.patch @@ -1,19 +1,19 @@ -From fb4bec0c863fb397078ab6086e95d5401be04ef2 Mon Sep 17 00:00:00 2001 +From 7a7e2191f1ac4114380248cbd3c6ab7425250747 Mon Sep 17 00:00:00 2001 From: Leonardo Bras Date: Wed, 18 May 2022 02:52:25 -0300 -Subject: [PATCH 23/34] multifd: Implement zero copy write in multifd migration +Subject: [PATCH 23/37] multifd: Implement zero copy write in multifd migration (multifd-zero-copy) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RH-Author: Leonardo Brás -RH-MergeRequest: 185: MSG_ZEROCOPY + Multifd @ rhel8.6 -RH-Commit: [23/34] ef7e8d02dde6570dc8cdf232f7ea03c997ee2e40 -RH-Bugzilla: 2117252 -RH-Acked-by: quintela1 -RH-Acked-by: Dr. David Alan Gilbert +RH-MergeRequest: 191: MSG_ZEROCOPY + Multifd @ rhel8.7 +RH-Commit: [23/26] 904ce3909cfef62dd84cc7d3c6a3482e7e6f28e9 +RH-Bugzilla: 2072049 RH-Acked-by: Peter Xu +RH-Acked-by: Daniel P. Berrangé +RH-Acked-by: Dr. David Alan Gilbert Implement zero copy send on nocomp_send_write(), by making use of QIOChannel writev + flags & flush interface. diff --git a/kvm-multifd-Make-zlib-compression-method-not-use-iovs.patch b/kvm-multifd-Make-zlib-compression-method-not-use-iovs.patch index 817f0de..e23d35d 100644 --- a/kvm-multifd-Make-zlib-compression-method-not-use-iovs.patch +++ b/kvm-multifd-Make-zlib-compression-method-not-use-iovs.patch @@ -1,18 +1,18 @@ -From e74b927853e84b44f8047718020593939ad125ec Mon Sep 17 00:00:00 2001 +From 75cd92cb7cff055f46163e64d66ba3f685f9ac04 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 18 May 2022 02:52:23 -0300 -Subject: [PATCH 09/34] multifd: Make zlib compression method not use iovs +Subject: [PATCH 09/37] multifd: Make zlib compression method not use iovs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RH-Author: Leonardo Brás -RH-MergeRequest: 185: MSG_ZEROCOPY + Multifd @ rhel8.6 -RH-Commit: [9/34] 37d70e2163ed982e2d8343c4ec1061fc59677688 -RH-Bugzilla: 2117252 -RH-Acked-by: quintela1 -RH-Acked-by: Dr. David Alan Gilbert +RH-MergeRequest: 191: MSG_ZEROCOPY + Multifd @ rhel8.7 +RH-Commit: [9/26] d33dd62b833d50fee989a195aebcc8d5e7d43181 +RH-Bugzilla: 2072049 RH-Acked-by: Peter Xu +RH-Acked-by: Daniel P. Berrangé +RH-Acked-by: Dr. David Alan Gilbert Signed-off-by: Juan Quintela Reviewed-by: Dr. David Alan Gilbert diff --git a/kvm-multifd-Make-zlib-use-iov-s.patch b/kvm-multifd-Make-zlib-use-iov-s.patch index 7c0cc8e..6310738 100644 --- a/kvm-multifd-Make-zlib-use-iov-s.patch +++ b/kvm-multifd-Make-zlib-use-iov-s.patch @@ -1,18 +1,18 @@ -From 9cc84ed4e52807912598f3cdef3ad08e9166cdea Mon Sep 17 00:00:00 2001 +From 1cdab9cadef1ed84ec34651a1edbffa36c1e67d0 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 18 May 2022 02:52:24 -0300 -Subject: [PATCH 12/34] multifd: Make zlib use iov's +Subject: [PATCH 12/37] multifd: Make zlib use iov's MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RH-Author: Leonardo Brás -RH-MergeRequest: 185: MSG_ZEROCOPY + Multifd @ rhel8.6 -RH-Commit: [12/34] 7cca02fb1706db0b1336d43ef4b1b6a16acf21a1 -RH-Bugzilla: 2117252 -RH-Acked-by: quintela1 -RH-Acked-by: Dr. David Alan Gilbert +RH-MergeRequest: 191: MSG_ZEROCOPY + Multifd @ rhel8.7 +RH-Commit: [12/26] 58630452e14802e71a9eadb17cfe4964ebf8e091 +RH-Bugzilla: 2072049 RH-Acked-by: Peter Xu +RH-Acked-by: Daniel P. Berrangé +RH-Acked-by: Dr. David Alan Gilbert Signed-off-by: Juan Quintela Reviewed-by: Dr. David Alan Gilbert diff --git a/kvm-multifd-Make-zstd-compression-method-not-use-iovs.patch b/kvm-multifd-Make-zstd-compression-method-not-use-iovs.patch index 12d56a7..3a10280 100644 --- a/kvm-multifd-Make-zstd-compression-method-not-use-iovs.patch +++ b/kvm-multifd-Make-zstd-compression-method-not-use-iovs.patch @@ -1,18 +1,18 @@ -From dc083c2407de0a668573e549b8357f451554e376 Mon Sep 17 00:00:00 2001 +From ab6262bd4829e3bd6437fe32737209df2af2d141 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 18 May 2022 02:52:23 -0300 -Subject: [PATCH 08/34] multifd: Make zstd compression method not use iovs +Subject: [PATCH 08/37] multifd: Make zstd compression method not use iovs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RH-Author: Leonardo Brás -RH-MergeRequest: 185: MSG_ZEROCOPY + Multifd @ rhel8.6 -RH-Commit: [8/34] 953059f89f3b79f4c515c16877052522c3104753 -RH-Bugzilla: 2117252 -RH-Acked-by: quintela1 -RH-Acked-by: Dr. David Alan Gilbert +RH-MergeRequest: 191: MSG_ZEROCOPY + Multifd @ rhel8.7 +RH-Commit: [8/26] 010579fa73b5a4c6fd631dc9fbaf6f974974bc99 +RH-Bugzilla: 2072049 RH-Acked-by: Peter Xu +RH-Acked-by: Daniel P. Berrangé +RH-Acked-by: Dr. David Alan Gilbert Signed-off-by: Juan Quintela Reviewed-by: Dr. David Alan Gilbert diff --git a/kvm-multifd-Make-zstd-use-iov-s.patch b/kvm-multifd-Make-zstd-use-iov-s.patch index 16dece0..af3e7fb 100644 --- a/kvm-multifd-Make-zstd-use-iov-s.patch +++ b/kvm-multifd-Make-zstd-use-iov-s.patch @@ -1,18 +1,18 @@ -From a451644d96f572f5845d3ee523e54486da55d9ae Mon Sep 17 00:00:00 2001 +From bac5ce0b4d3552d6056045f201b4e50dd6204b31 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 18 May 2022 02:52:24 -0300 -Subject: [PATCH 13/34] multifd: Make zstd use iov's +Subject: [PATCH 13/37] multifd: Make zstd use iov's MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RH-Author: Leonardo Brás -RH-MergeRequest: 185: MSG_ZEROCOPY + Multifd @ rhel8.6 -RH-Commit: [13/34] 37929ac695c7bdfe6e2f798d4f5e43a5e7525acb -RH-Bugzilla: 2117252 -RH-Acked-by: quintela1 -RH-Acked-by: Dr. David Alan Gilbert +RH-MergeRequest: 191: MSG_ZEROCOPY + Multifd @ rhel8.7 +RH-Commit: [13/26] 4d7036fb32efdf088d23737b9710e6ad1a4654aa +RH-Bugzilla: 2072049 RH-Acked-by: Peter Xu +RH-Acked-by: Daniel P. Berrangé +RH-Acked-by: Dr. David Alan Gilbert Signed-off-by: Juan Quintela Reviewed-by: Dr. David Alan Gilbert diff --git a/kvm-multifd-Move-iov-from-pages-to-params.patch b/kvm-multifd-Move-iov-from-pages-to-params.patch index 8c014a3..6a59707 100644 --- a/kvm-multifd-Move-iov-from-pages-to-params.patch +++ b/kvm-multifd-Move-iov-from-pages-to-params.patch @@ -1,18 +1,18 @@ -From faae5f3dd29a25607f34466b9cd11d17ff6a0db6 Mon Sep 17 00:00:00 2001 +From 1181a9cbcaf37a82aa7bf117ef209f554b8c4a71 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 18 May 2022 02:52:24 -0300 -Subject: [PATCH 11/34] multifd: Move iov from pages to params +Subject: [PATCH 11/37] multifd: Move iov from pages to params MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RH-Author: Leonardo Brás -RH-MergeRequest: 185: MSG_ZEROCOPY + Multifd @ rhel8.6 -RH-Commit: [11/34] 382f1d5db714944bd12f264db9ad0e37ddb2cfeb -RH-Bugzilla: 2117252 -RH-Acked-by: quintela1 -RH-Acked-by: Dr. David Alan Gilbert +RH-MergeRequest: 191: MSG_ZEROCOPY + Multifd @ rhel8.7 +RH-Commit: [11/26] 24dff3ef68cf3327811242193502319ed3e3940a +RH-Bugzilla: 2072049 RH-Acked-by: Peter Xu +RH-Acked-by: Daniel P. Berrangé +RH-Acked-by: Dr. David Alan Gilbert This will allow us to reduce the number of system calls on the next patch. diff --git a/kvm-multifd-Remove-send_write-method.patch b/kvm-multifd-Remove-send_write-method.patch index c37ef79..79fc649 100644 --- a/kvm-multifd-Remove-send_write-method.patch +++ b/kvm-multifd-Remove-send_write-method.patch @@ -1,18 +1,18 @@ -From e93de1066dde56befa50d1466955c7b7432604d1 Mon Sep 17 00:00:00 2001 +From 2952487c7e5ed14796fbffae0b964a35790d6850 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 18 May 2022 02:52:24 -0300 -Subject: [PATCH 14/34] multifd: Remove send_write() method +Subject: [PATCH 14/37] multifd: Remove send_write() method MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RH-Author: Leonardo Brás -RH-MergeRequest: 185: MSG_ZEROCOPY + Multifd @ rhel8.6 -RH-Commit: [14/34] 483abd10c7cf11f27599ebcfb0586eb91b6519c1 -RH-Bugzilla: 2117252 -RH-Acked-by: quintela1 -RH-Acked-by: Dr. David Alan Gilbert +RH-MergeRequest: 191: MSG_ZEROCOPY + Multifd @ rhel8.7 +RH-Commit: [14/26] 5fa59ffa09099fbc6da84e9a192ca71af52cc98f +RH-Bugzilla: 2072049 RH-Acked-by: Peter Xu +RH-Acked-by: Daniel P. Berrangé +RH-Acked-by: Dr. David Alan Gilbert Everything use now iov's. diff --git a/kvm-multifd-Rename-used-field-to-num.patch b/kvm-multifd-Rename-used-field-to-num.patch index 51bbfbe..24bdd8c 100644 --- a/kvm-multifd-Rename-used-field-to-num.patch +++ b/kvm-multifd-Rename-used-field-to-num.patch @@ -1,18 +1,18 @@ -From 030004b805604114aeaf8b9344b496332f433f71 Mon Sep 17 00:00:00 2001 +From 003ef20d11b33a7139fae6fbcf170188a07afc43 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 18 May 2022 02:52:22 -0300 -Subject: [PATCH 02/34] multifd: Rename used field to num +Subject: [PATCH 02/37] multifd: Rename used field to num MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RH-Author: Leonardo Brás -RH-MergeRequest: 185: MSG_ZEROCOPY + Multifd @ rhel8.6 -RH-Commit: [2/34] 5e411060b289cdabdf66c0774a55e109c0ef2906 -RH-Bugzilla: 2117252 -RH-Acked-by: quintela1 -RH-Acked-by: Dr. David Alan Gilbert +RH-MergeRequest: 191: MSG_ZEROCOPY + Multifd @ rhel8.7 +RH-Commit: [2/26] 952283197ef89be4d61c7690bb6c3194e5c67217 +RH-Bugzilla: 2072049 RH-Acked-by: Peter Xu +RH-Acked-by: Daniel P. Berrangé +RH-Acked-by: Dr. David Alan Gilbert We will need to split it later in zero_num (number of zero pages) and normal_num (number of normal pages). This name is better. diff --git a/kvm-multifd-Send-header-packet-without-flags-if-zero-cop.patch b/kvm-multifd-Send-header-packet-without-flags-if-zero-cop.patch index cb12219..d54cce8 100644 --- a/kvm-multifd-Send-header-packet-without-flags-if-zero-cop.patch +++ b/kvm-multifd-Send-header-packet-without-flags-if-zero-cop.patch @@ -1,19 +1,19 @@ -From 8a1b74503b17a1f48283eeec547579aad5bdb8f9 Mon Sep 17 00:00:00 2001 +From 33a38fef5e889b45571228bde519746fd90d8877 Mon Sep 17 00:00:00 2001 From: Leonardo Bras Date: Wed, 18 May 2022 02:52:25 -0300 -Subject: [PATCH 22/34] multifd: Send header packet without flags if +Subject: [PATCH 22/37] multifd: Send header packet without flags if zero-copy-send is enabled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RH-Author: Leonardo Brás -RH-MergeRequest: 185: MSG_ZEROCOPY + Multifd @ rhel8.6 -RH-Commit: [22/34] f8ea6e11134afe5291b6f404dc9b59557fbf1030 -RH-Bugzilla: 2117252 -RH-Acked-by: quintela1 -RH-Acked-by: Dr. David Alan Gilbert +RH-MergeRequest: 191: MSG_ZEROCOPY + Multifd @ rhel8.7 +RH-Commit: [22/26] 9abfee42b72f11911cf128519826d09cbd2f5bc3 +RH-Bugzilla: 2072049 RH-Acked-by: Peter Xu +RH-Acked-by: Daniel P. Berrangé +RH-Acked-by: Dr. David Alan Gilbert Since d48c3a0445 ("multifd: Use a single writev on the send side"), sending the header packet and the memory pages happens in the same diff --git a/kvm-multifd-The-variable-is-only-used-inside-the-loop.patch b/kvm-multifd-The-variable-is-only-used-inside-the-loop.patch index 5f03ced..ef5e6d2 100644 --- a/kvm-multifd-The-variable-is-only-used-inside-the-loop.patch +++ b/kvm-multifd-The-variable-is-only-used-inside-the-loop.patch @@ -1,18 +1,18 @@ -From 8814fdd9eba7a69c2b5f7df8a8db49d7c2ac8378 Mon Sep 17 00:00:00 2001 +From 56cd14fc23c58707b9184da11f36d777bba6ce78 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 18 May 2022 02:52:23 -0300 -Subject: [PATCH 04/34] multifd: The variable is only used inside the loop +Subject: [PATCH 04/37] multifd: The variable is only used inside the loop MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RH-Author: Leonardo Brás -RH-MergeRequest: 185: MSG_ZEROCOPY + Multifd @ rhel8.6 -RH-Commit: [4/34] ea2b915fa5e795d88edaa3e0cf39a9f2c3cc2050 -RH-Bugzilla: 2117252 -RH-Acked-by: quintela1 -RH-Acked-by: Dr. David Alan Gilbert +RH-MergeRequest: 191: MSG_ZEROCOPY + Multifd @ rhel8.7 +RH-Commit: [4/26] 45d8bbde75ebbef6329c41ddb56db4526739f94f +RH-Bugzilla: 2072049 RH-Acked-by: Peter Xu +RH-Acked-by: Daniel P. Berrangé +RH-Acked-by: Dr. David Alan Gilbert Signed-off-by: Juan Quintela Reviewed-by: Dr. David Alan Gilbert diff --git a/kvm-multifd-Use-a-single-writev-on-the-send-side.patch b/kvm-multifd-Use-a-single-writev-on-the-send-side.patch index 495e201..b4f3036 100644 --- a/kvm-multifd-Use-a-single-writev-on-the-send-side.patch +++ b/kvm-multifd-Use-a-single-writev-on-the-send-side.patch @@ -1,18 +1,18 @@ -From ef864989dbe480e952bb3c5ea3cd9dfcf97bd455 Mon Sep 17 00:00:00 2001 +From 4051de396e02ea2c1911c842426318bcd97f93c7 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 18 May 2022 02:52:24 -0300 -Subject: [PATCH 15/34] multifd: Use a single writev on the send side +Subject: [PATCH 15/37] multifd: Use a single writev on the send side MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RH-Author: Leonardo Brás -RH-MergeRequest: 185: MSG_ZEROCOPY + Multifd @ rhel8.6 -RH-Commit: [15/34] 3e421f67a5f69231280ed748318c0317da31ae95 -RH-Bugzilla: 2117252 -RH-Acked-by: quintela1 -RH-Acked-by: Dr. David Alan Gilbert +RH-MergeRequest: 191: MSG_ZEROCOPY + Multifd @ rhel8.7 +RH-Commit: [15/26] c37063c813fc0ba695072117f272360e5c413803 +RH-Bugzilla: 2072049 RH-Acked-by: Peter Xu +RH-Acked-by: Daniel P. Berrangé +RH-Acked-by: Dr. David Alan Gilbert Until now, we wrote the packet header with write(), and the rest of the pages with writev(). Just increase the size of the iovec and do a diff --git a/kvm-multifd-Use-normal-pages-array-on-the-send-side.patch b/kvm-multifd-Use-normal-pages-array-on-the-send-side.patch index 2bd055b..032dac2 100644 --- a/kvm-multifd-Use-normal-pages-array-on-the-send-side.patch +++ b/kvm-multifd-Use-normal-pages-array-on-the-send-side.patch @@ -1,18 +1,18 @@ -From c70c97cd59fd22de0957ea1c0a655fb5ef270f1e Mon Sep 17 00:00:00 2001 +From 3b57c876e1eaca34fb5bd9067553de945013d4be Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 18 May 2022 02:52:24 -0300 -Subject: [PATCH 16/34] multifd: Use normal pages array on the send side +Subject: [PATCH 16/37] multifd: Use normal pages array on the send side MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RH-Author: Leonardo Brás -RH-MergeRequest: 185: MSG_ZEROCOPY + Multifd @ rhel8.6 -RH-Commit: [16/34] 24f4ea3248f6ce883d57344600c8adbf51bd7d8c -RH-Bugzilla: 2117252 -RH-Acked-by: quintela1 -RH-Acked-by: Dr. David Alan Gilbert +RH-MergeRequest: 191: MSG_ZEROCOPY + Multifd @ rhel8.7 +RH-Commit: [16/26] 1c48806474daf48fe93920ac361311af95c6a6f3 +RH-Bugzilla: 2072049 RH-Acked-by: Peter Xu +RH-Acked-by: Daniel P. Berrangé +RH-Acked-by: Dr. David Alan Gilbert We are only sending normal pages through multifd channels. Later on this series, we are going to also send zero pages. diff --git a/kvm-multifd-multifd_send_sync_main-now-returns-negative-.patch b/kvm-multifd-multifd_send_sync_main-now-returns-negative-.patch index a5b3747..7912266 100644 --- a/kvm-multifd-multifd_send_sync_main-now-returns-negative-.patch +++ b/kvm-multifd-multifd_send_sync_main-now-returns-negative-.patch @@ -1,19 +1,19 @@ -From 9d8968ae10e1724198c493646e2bdcd55f205e5e Mon Sep 17 00:00:00 2001 +From fce933410a5068220a5f29011a6d1a647e357a62 Mon Sep 17 00:00:00 2001 From: Leonardo Bras Date: Wed, 18 May 2022 02:52:25 -0300 -Subject: [PATCH 21/34] multifd: multifd_send_sync_main now returns negative on +Subject: [PATCH 21/37] multifd: multifd_send_sync_main now returns negative on error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RH-Author: Leonardo Brás -RH-MergeRequest: 185: MSG_ZEROCOPY + Multifd @ rhel8.6 -RH-Commit: [21/34] bef7acbe751fc4871a9ece72ab58b195658d6328 -RH-Bugzilla: 2117252 -RH-Acked-by: quintela1 -RH-Acked-by: Dr. David Alan Gilbert +RH-MergeRequest: 191: MSG_ZEROCOPY + Multifd @ rhel8.7 +RH-Commit: [21/26] b4e4f3663576aa87f3b2f66f1d38bad4f50bd4ac +RH-Bugzilla: 2072049 RH-Acked-by: Peter Xu +RH-Acked-by: Daniel P. Berrangé +RH-Acked-by: Dr. David Alan Gilbert Even though multifd_send_sync_main() currently emits error_reports, it's callers don't really check it before continuing. diff --git a/kvm-multifd-remove-used-parameter-from-send_prepare-meth.patch b/kvm-multifd-remove-used-parameter-from-send_prepare-meth.patch index a3b973d..3f3b923 100644 --- a/kvm-multifd-remove-used-parameter-from-send_prepare-meth.patch +++ b/kvm-multifd-remove-used-parameter-from-send_prepare-meth.patch @@ -1,19 +1,19 @@ -From 46c902b006cbf52341804e85f9246bdc8afc8611 Mon Sep 17 00:00:00 2001 +From 5f53448092c944857a2b89138f22c5ab335d8250 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 18 May 2022 02:52:23 -0300 -Subject: [PATCH 05/34] multifd: remove used parameter from send_prepare() +Subject: [PATCH 05/37] multifd: remove used parameter from send_prepare() method MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RH-Author: Leonardo Brás -RH-MergeRequest: 185: MSG_ZEROCOPY + Multifd @ rhel8.6 -RH-Commit: [5/34] b4f1c9540bddd137756cab4bde4ba5d8eac09ab9 -RH-Bugzilla: 2117252 -RH-Acked-by: quintela1 -RH-Acked-by: Dr. David Alan Gilbert +RH-MergeRequest: 191: MSG_ZEROCOPY + Multifd @ rhel8.7 +RH-Commit: [5/26] ad6360d19d65e8c332dcdc3d3234478639e03db8 +RH-Bugzilla: 2072049 RH-Acked-by: Peter Xu +RH-Acked-by: Daniel P. Berrangé +RH-Acked-by: Dr. David Alan Gilbert It is already there as p->pages->num. diff --git a/kvm-multifd-remove-used-parameter-from-send_recv_pages-m.patch b/kvm-multifd-remove-used-parameter-from-send_recv_pages-m.patch index d019cf5..02c5918 100644 --- a/kvm-multifd-remove-used-parameter-from-send_recv_pages-m.patch +++ b/kvm-multifd-remove-used-parameter-from-send_recv_pages-m.patch @@ -1,19 +1,19 @@ -From 75ef79011b75d1024dc50a999d03ab90570e6533 Mon Sep 17 00:00:00 2001 +From 8cdedf86dc193673ea24516e7b44f8b4da5dd713 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 18 May 2022 02:52:23 -0300 -Subject: [PATCH 06/34] multifd: remove used parameter from send_recv_pages() +Subject: [PATCH 06/37] multifd: remove used parameter from send_recv_pages() method MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RH-Author: Leonardo Brás -RH-MergeRequest: 185: MSG_ZEROCOPY + Multifd @ rhel8.6 -RH-Commit: [6/34] fe59a7c794dd707cf71b2dc6104a0a89e2ac7d50 -RH-Bugzilla: 2117252 -RH-Acked-by: quintela1 -RH-Acked-by: Dr. David Alan Gilbert +RH-MergeRequest: 191: MSG_ZEROCOPY + Multifd @ rhel8.7 +RH-Commit: [6/26] 5c1a506e4178501a0894ea4e7ac919e1d4d4cc32 +RH-Bugzilla: 2072049 RH-Acked-by: Peter Xu +RH-Acked-by: Daniel P. Berrangé +RH-Acked-by: Dr. David Alan Gilbert It is already there as p->pages->num. diff --git a/kvm-pc-bios-s390-ccw-Fix-booting-with-logical-block-size.patch b/kvm-pc-bios-s390-ccw-Fix-booting-with-logical-block-size.patch new file mode 100644 index 0000000..83fe9af --- /dev/null +++ b/kvm-pc-bios-s390-ccw-Fix-booting-with-logical-block-size.patch @@ -0,0 +1,63 @@ +From 115507e5e8b97993b50ea7b39d6d4bb493973e46 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 5 Aug 2022 11:42:14 +0200 +Subject: [PATCH 9/9] pc-bios/s390-ccw: Fix booting with logical block size < + physical block size + +RH-Author: Thomas Huth +RH-MergeRequest: 207: pc-bios/s390-ccw: Fix booting with logical block size < physical block size +RH-Commit: [1/1] ab22832592e0a48277bf7aca1b941a1be79aeab6 +RH-Bugzilla: 2112296 +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand +RH-Acked-by: Claudio Imbrenda + +For accessing single blocks during boot, it's the logical block size that +matters. (Physical block sizes are rather interesting e.g. for creating +file systems with the correct alignment for speed reasons etc.). +So the s390-ccw bios has to use the logical block size for calculating +sector numbers during the boot phase, the "physical_block_exp" shift +value must not be taken into account. This change fixes the boot process +when the guest hast been installed on a disk where the logical block size +differs from the physical one, e.g. if the guest has been installed +like this: + + qemu-system-s390x -nographic -accel kvm -m 2G \ + -drive if=none,id=d1,file=fedora.iso,format=raw,media=cdrom \ + -device virtio-scsi -device scsi-cd,drive=d1 \ + -drive if=none,id=d2,file=test.qcow2,format=qcow2 + -device virtio-blk,drive=d2,physical_block_size=4096,logical_block_size=512 + +Linux correctly uses the logical block size of 512 for the installation, +but the s390-ccw bios tries to boot from a disk with 4096 block size so +far, as long as this patch has not been applied yet (well, it used to work +by accident in the past due to the virtio_assume_scsi() hack that used to +enforce 512 byte sectors on all virtio-block disks, but that hack has been +well removed in commit 5447de2619050a0a4d to fix other scenarios). + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2112296 +Message-Id: <20220805094214.285223-1-thuth@redhat.com> +Reviewed-by: Cornelia Huck +Reviewed-by: Eric Farman +Signed-off-by: Thomas Huth +(cherry picked from commit 393296de19650e1400ca265914cfdeb313725363) +--- + pc-bios/s390-ccw/virtio-blkdev.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/pc-bios/s390-ccw/virtio-blkdev.c b/pc-bios/s390-ccw/virtio-blkdev.c +index 8271c47296..794f99b42c 100644 +--- a/pc-bios/s390-ccw/virtio-blkdev.c ++++ b/pc-bios/s390-ccw/virtio-blkdev.c +@@ -173,7 +173,7 @@ int virtio_get_block_size(void) + + switch (vdev->senseid.cu_model) { + case VIRTIO_ID_BLOCK: +- return vdev->config.blk.blk_size << vdev->config.blk.physical_block_exp; ++ return vdev->config.blk.blk_size; + case VIRTIO_ID_SCSI: + return vdev->scsi_block_size; + } +-- +2.31.1 + diff --git a/kvm-pc-bios-s390-ccw-Split-virtio-scsi-code-from-virtio_.patch b/kvm-pc-bios-s390-ccw-Split-virtio-scsi-code-from-virtio_.patch new file mode 100644 index 0000000..89d8a91 --- /dev/null +++ b/kvm-pc-bios-s390-ccw-Split-virtio-scsi-code-from-virtio_.patch @@ -0,0 +1,180 @@ +From 0e7b71a3f0b3a2e1dba54f02efc15b02f337e031 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 8 Jul 2022 12:29:50 +0200 +Subject: [PATCH 36/37] pc-bios/s390-ccw: Split virtio-scsi code from + virtio_blk_setup_device() + +RH-Author: Thomas Huth +RH-MergeRequest: 198: pc-bios/s390-ccw: Fix boot from disks with 4k sectors that do not have the typical DASD geometry +RH-Commit: [8/9] 8e24806a91c91b2e3603da88e5a22d96a91e8686 +RH-Bugzilla: 2098076 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: David Hildenbrand +RH-Acked-by: Cornelia Huck + +Bugzilla: http://bugzilla.redhat.com/2098076 + +commit cf30b7c4a9b2c64518be8037c2e6670aacdb00b9 +Author: Thomas Huth +Date: Mon Jul 4 13:19:00 2022 +0200 + + pc-bios/s390-ccw: Split virtio-scsi code from virtio_blk_setup_device() + + The next patch is going to add more virtio-block specific code to + virtio_blk_setup_device(), and if the virtio-scsi code is also in + there, this is more cumbersome. And the calling function virtio_setup() + in main.c looks at the device type already anyway, so it's more + logical to separate the virtio-scsi stuff into a new function in + virtio-scsi.c instead. + + Message-Id: <20220704111903.62400-10-thuth@redhat.com> + Reviewed-by: Eric Farman + Signed-off-by: Thomas Huth + +Signed-off-by: Thomas Huth +--- + pc-bios/s390-ccw/main.c | 24 +++++++++++++++++------- + pc-bios/s390-ccw/virtio-blkdev.c | 20 ++------------------ + pc-bios/s390-ccw/virtio-scsi.c | 19 ++++++++++++++++++- + pc-bios/s390-ccw/virtio-scsi.h | 2 +- + 4 files changed, 38 insertions(+), 27 deletions(-) + +diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c +index 5d2b7ba94d..13e1d8fdf7 100644 +--- a/pc-bios/s390-ccw/main.c ++++ b/pc-bios/s390-ccw/main.c +@@ -14,6 +14,7 @@ + #include "s390-ccw.h" + #include "cio.h" + #include "virtio.h" ++#include "virtio-scsi.h" + #include "dasd-ipl.h" + + char stack[PAGE_SIZE * 8] __attribute__((__aligned__(PAGE_SIZE))); +@@ -218,6 +219,7 @@ static int virtio_setup(void) + { + VDev *vdev = virtio_get_device(); + QemuIplParameters *early_qipl = (QemuIplParameters *)QIPL_ADDRESS; ++ int ret; + + memcpy(&qipl, early_qipl, sizeof(QemuIplParameters)); + +@@ -225,18 +227,26 @@ static int virtio_setup(void) + menu_setup(); + } + +- if (virtio_get_device_type() == VIRTIO_ID_NET) { ++ switch (vdev->senseid.cu_model) { ++ case VIRTIO_ID_NET: + sclp_print("Network boot device detected\n"); + vdev->netboot_start_addr = qipl.netboot_start_addr; +- } else { +- int ret = virtio_blk_setup_device(blk_schid); +- if (ret) { +- return ret; +- } ++ return 0; ++ case VIRTIO_ID_BLOCK: ++ ret = virtio_blk_setup_device(blk_schid); ++ break; ++ case VIRTIO_ID_SCSI: ++ ret = virtio_scsi_setup_device(blk_schid); ++ break; ++ default: ++ panic("\n! No IPL device available !\n"); ++ } ++ ++ if (!ret) { + IPL_assert(virtio_ipl_disk_is_valid(), "No valid IPL device detected"); + } + +- return 0; ++ return ret; + } + + static void ipl_boot_device(void) +diff --git a/pc-bios/s390-ccw/virtio-blkdev.c b/pc-bios/s390-ccw/virtio-blkdev.c +index db1f7f44aa..c175b66a47 100644 +--- a/pc-bios/s390-ccw/virtio-blkdev.c ++++ b/pc-bios/s390-ccw/virtio-blkdev.c +@@ -222,27 +222,11 @@ uint64_t virtio_get_blocks(void) + int virtio_blk_setup_device(SubChannelId schid) + { + VDev *vdev = virtio_get_device(); +- int ret = 0; + + vdev->schid = schid; + virtio_setup_ccw(vdev); + +- switch (vdev->senseid.cu_model) { +- case VIRTIO_ID_BLOCK: +- sclp_print("Using virtio-blk.\n"); +- break; +- case VIRTIO_ID_SCSI: +- IPL_assert(vdev->config.scsi.sense_size == VIRTIO_SCSI_SENSE_SIZE, +- "Config: sense size mismatch"); +- IPL_assert(vdev->config.scsi.cdb_size == VIRTIO_SCSI_CDB_SIZE, +- "Config: CDB size mismatch"); ++ sclp_print("Using virtio-blk.\n"); + +- sclp_print("Using virtio-scsi.\n"); +- ret = virtio_scsi_setup(vdev); +- break; +- default: +- panic("\n! No IPL device available !\n"); +- } +- +- return ret; ++ return 0; + } +diff --git a/pc-bios/s390-ccw/virtio-scsi.c b/pc-bios/s390-ccw/virtio-scsi.c +index 2c8d0f3097..3b7069270c 100644 +--- a/pc-bios/s390-ccw/virtio-scsi.c ++++ b/pc-bios/s390-ccw/virtio-scsi.c +@@ -329,7 +329,7 @@ static void scsi_parse_capacity_report(void *data, + } + } + +-int virtio_scsi_setup(VDev *vdev) ++static int virtio_scsi_setup(VDev *vdev) + { + int retry_test_unit_ready = 3; + uint8_t data[256]; +@@ -430,3 +430,20 @@ int virtio_scsi_setup(VDev *vdev) + + return 0; + } ++ ++int virtio_scsi_setup_device(SubChannelId schid) ++{ ++ VDev *vdev = virtio_get_device(); ++ ++ vdev->schid = schid; ++ virtio_setup_ccw(vdev); ++ ++ IPL_assert(vdev->config.scsi.sense_size == VIRTIO_SCSI_SENSE_SIZE, ++ "Config: sense size mismatch"); ++ IPL_assert(vdev->config.scsi.cdb_size == VIRTIO_SCSI_CDB_SIZE, ++ "Config: CDB size mismatch"); ++ ++ sclp_print("Using virtio-scsi.\n"); ++ ++ return virtio_scsi_setup(vdev); ++} +diff --git a/pc-bios/s390-ccw/virtio-scsi.h b/pc-bios/s390-ccw/virtio-scsi.h +index 4b14c2c2f9..e6b6cd4815 100644 +--- a/pc-bios/s390-ccw/virtio-scsi.h ++++ b/pc-bios/s390-ccw/virtio-scsi.h +@@ -67,8 +67,8 @@ static inline bool virtio_scsi_response_ok(const VirtioScsiCmdResp *r) + return r->response == VIRTIO_SCSI_S_OK && r->status == CDB_STATUS_GOOD; + } + +-int virtio_scsi_setup(VDev *vdev); + int virtio_scsi_read_many(VDev *vdev, + ulong sector, void *load_addr, int sec_num); ++int virtio_scsi_setup_device(SubChannelId schid); + + #endif /* VIRTIO_SCSI_H */ +-- +2.35.3 + diff --git a/kvm-pc-bios-s390-ccw-bootmap-Improve-the-guessing-logic-.patch b/kvm-pc-bios-s390-ccw-bootmap-Improve-the-guessing-logic-.patch new file mode 100644 index 0000000..fd34b3d --- /dev/null +++ b/kvm-pc-bios-s390-ccw-bootmap-Improve-the-guessing-logic-.patch @@ -0,0 +1,102 @@ +From 8433b2ba40d0618c7086da87685e1c51b6da3b11 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 8 Jul 2022 12:29:50 +0200 +Subject: [PATCH 30/37] pc-bios/s390-ccw/bootmap: Improve the guessing logic in + zipl_load_vblk() + +RH-Author: Thomas Huth +RH-MergeRequest: 198: pc-bios/s390-ccw: Fix boot from disks with 4k sectors that do not have the typical DASD geometry +RH-Commit: [2/9] db1d2e7929352bec0e1a5d4cf3fb385bbe02304b +RH-Bugzilla: 2098076 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: David Hildenbrand +RH-Acked-by: Cornelia Huck + +Bugzilla: http://bugzilla.redhat.com/2098076 + +commit 422865f6672ee1482b98d18321b55c1ecfb06c82 +Author: Thomas Huth +Date: Mon Jul 4 13:18:54 2022 +0200 + + pc-bios/s390-ccw/bootmap: Improve the guessing logic in zipl_load_vblk() + + The logic of trying an final ISO or ECKD boot on virtio-block devices is + very weird: Since the geometry hardly ever matches in virtio_disk_is_scsi(), + virtio_blk_setup_device() always sets a "guessed" disk geometry via + virtio_assume_scsi() (which is certainly also wrong in a lot of cases). + + zipl_load_vblk() then sees that there's been a "virtio_guessed_disk_nature" + and tries to fix up the geometry again via virtio_assume_iso9660() before + always trying to do ipl_iso_el_torito(). That's a very brain-twisting + way of attempting to boot from ISO images, which won't work anymore after + the following patches that will clean up the virtio_assume_scsi() mess + (and thus get rid of the "virtio_guessed_disk_nature" here). + + Let's try a better approach instead: ISO files always have a magic + string "CD001" at offset 0x8001 (see e.g. the ECMA-119 specification) + which we can use to decide whether we should try to boot in ISO 9660 + mode (which we should also try if we see a sector size of 2048). + + And if we were not able to boot in ISO mode here, the final boot attempt + before panicking is to boot in ECKD mode. Since this is our last boot + attempt anyway, simply always assume the ECKD geometry here (if the sector + size was not 4096 yet), so that we also do not depend on the guessed disk + geometry from virtio_blk_setup_device() here anymore. + + Message-Id: <20220704111903.62400-4-thuth@redhat.com> + Signed-off-by: Thomas Huth + +Signed-off-by: Thomas Huth +--- + pc-bios/s390-ccw/bootmap.c | 27 +++++++++++++++++++++++---- + 1 file changed, 23 insertions(+), 4 deletions(-) + +diff --git a/pc-bios/s390-ccw/bootmap.c b/pc-bios/s390-ccw/bootmap.c +index 56411ab3b6..994e59c0b0 100644 +--- a/pc-bios/s390-ccw/bootmap.c ++++ b/pc-bios/s390-ccw/bootmap.c +@@ -780,18 +780,37 @@ static void ipl_iso_el_torito(void) + } + } + ++/** ++ * Detect whether we're trying to boot from an .ISO image. ++ * These always have a signature string "CD001" at offset 0x8001. ++ */ ++static bool has_iso_signature(void) ++{ ++ int blksize = virtio_get_block_size(); ++ ++ if (!blksize || virtio_read(0x8000 / blksize, sec)) { ++ return false; ++ } ++ ++ return !memcmp("CD001", &sec[1], 5); ++} ++ + /*********************************************************************** + * Bus specific IPL sequences + */ + + static void zipl_load_vblk(void) + { +- if (virtio_guessed_disk_nature()) { +- virtio_assume_iso9660(); ++ int blksize = virtio_get_block_size(); ++ ++ if (blksize == VIRTIO_ISO_BLOCK_SIZE || has_iso_signature()) { ++ if (blksize != VIRTIO_ISO_BLOCK_SIZE) { ++ virtio_assume_iso9660(); ++ } ++ ipl_iso_el_torito(); + } +- ipl_iso_el_torito(); + +- if (virtio_guessed_disk_nature()) { ++ if (blksize != VIRTIO_DASD_DEFAULT_BLOCK_SIZE) { + sclp_print("Using guessed DASD geometry.\n"); + virtio_assume_eckd(); + } +-- +2.35.3 + diff --git a/kvm-pc-bios-s390-ccw-virtio-Beautify-the-code-for-readin.patch b/kvm-pc-bios-s390-ccw-virtio-Beautify-the-code-for-readin.patch new file mode 100644 index 0000000..84bf0ce --- /dev/null +++ b/kvm-pc-bios-s390-ccw-virtio-Beautify-the-code-for-readin.patch @@ -0,0 +1,56 @@ +From 8b05a4aa32e5ae6cdbc16a5350f6df35d2d79efc Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 8 Jul 2022 12:29:50 +0200 +Subject: [PATCH 35/37] pc-bios/s390-ccw/virtio: Beautify the code for reading + virtqueue configuration + +RH-Author: Thomas Huth +RH-MergeRequest: 198: pc-bios/s390-ccw: Fix boot from disks with 4k sectors that do not have the typical DASD geometry +RH-Commit: [7/9] 52fb7fee7d7c46397f32e35bd5f92f82616dfb5c +RH-Bugzilla: 2098076 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: David Hildenbrand +RH-Acked-by: Cornelia Huck + +Bugzilla: http://bugzilla.redhat.com/2098076 + +commit 070824885741f5d2a66626d3c4ecb2773c8e0552 +Author: Thomas Huth +Date: Mon Jul 4 13:18:59 2022 +0200 + + pc-bios/s390-ccw/virtio: Beautify the code for reading virtqueue configuration + + It looks nicer if we separate the run_ccw() from the IPL_assert() + statement, and the error message should talk about "virtio device" + instead of "block device", since this code is nowadays used for + non-block (i.e. network) devices, too. + + Message-Id: <20220704111903.62400-9-thuth@redhat.com> + Reviewed-by: Cornelia Huck + Reviewed-by: Eric Farman + Signed-off-by: Thomas Huth + +Signed-off-by: Thomas Huth +--- + pc-bios/s390-ccw/virtio.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/pc-bios/s390-ccw/virtio.c b/pc-bios/s390-ccw/virtio.c +index d8c2b52710..f37510f312 100644 +--- a/pc-bios/s390-ccw/virtio.c ++++ b/pc-bios/s390-ccw/virtio.c +@@ -289,9 +289,8 @@ void virtio_setup_ccw(VDev *vdev) + .num = 0, + }; + +- IPL_assert( +- run_ccw(vdev, CCW_CMD_READ_VQ_CONF, &config, sizeof(config), false) == 0, +- "Could not get block device VQ configuration"); ++ rc = run_ccw(vdev, CCW_CMD_READ_VQ_CONF, &config, sizeof(config), false); ++ IPL_assert(rc == 0, "Could not get virtio device VQ configuration"); + info.num = config.num; + vring_init(&vdev->vrings[i], &info); + vdev->vrings[i].schid = vdev->schid; +-- +2.35.3 + diff --git a/kvm-pc-bios-s390-ccw-virtio-Introduce-a-macro-for-the-DA.patch b/kvm-pc-bios-s390-ccw-virtio-Introduce-a-macro-for-the-DA.patch new file mode 100644 index 0000000..9e9d8e6 --- /dev/null +++ b/kvm-pc-bios-s390-ccw-virtio-Introduce-a-macro-for-the-DA.patch @@ -0,0 +1,63 @@ +From 511d05f31824b375057ba8dea3f0343ce6e1c1e8 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 8 Jul 2022 12:29:50 +0200 +Subject: [PATCH 29/37] pc-bios/s390-ccw/virtio: Introduce a macro for the DASD + block size + +RH-Author: Thomas Huth +RH-MergeRequest: 198: pc-bios/s390-ccw: Fix boot from disks with 4k sectors that do not have the typical DASD geometry +RH-Commit: [1/9] 1053101fd5fb591131c567ff98c7d92b63a9dfa9 +RH-Bugzilla: 2098076 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: David Hildenbrand +RH-Acked-by: Cornelia Huck + +Bugzilla: http://bugzilla.redhat.com/2098076 + +commit 1f2c2ee48e87ea743f8e23cc7569dd26c4cf9623 +Author: Thomas Huth +Date: Mon Jul 4 13:18:53 2022 +0200 + + pc-bios/s390-ccw/virtio: Introduce a macro for the DASD block size + + Use VIRTIO_DASD_DEFAULT_BLOCK_SIZE instead of the magic value 4096. + + Message-Id: <20220704111903.62400-3-thuth@redhat.com> + Reviewed-by: Eric Farman + Reviewed-by: Cornelia Huck + Signed-off-by: Thomas Huth + +Signed-off-by: Thomas Huth +--- + pc-bios/s390-ccw/virtio-blkdev.c | 2 +- + pc-bios/s390-ccw/virtio.h | 1 + + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/pc-bios/s390-ccw/virtio-blkdev.c b/pc-bios/s390-ccw/virtio-blkdev.c +index 7d35050292..6483307630 100644 +--- a/pc-bios/s390-ccw/virtio-blkdev.c ++++ b/pc-bios/s390-ccw/virtio-blkdev.c +@@ -155,7 +155,7 @@ void virtio_assume_eckd(void) + vdev->config.blk.physical_block_exp = 0; + switch (vdev->senseid.cu_model) { + case VIRTIO_ID_BLOCK: +- vdev->config.blk.blk_size = 4096; ++ vdev->config.blk.blk_size = VIRTIO_DASD_DEFAULT_BLOCK_SIZE; + break; + case VIRTIO_ID_SCSI: + vdev->config.blk.blk_size = vdev->scsi_block_size; +diff --git a/pc-bios/s390-ccw/virtio.h b/pc-bios/s390-ccw/virtio.h +index 19fceb6495..9e410bde6f 100644 +--- a/pc-bios/s390-ccw/virtio.h ++++ b/pc-bios/s390-ccw/virtio.h +@@ -198,6 +198,7 @@ extern int virtio_read_many(ulong sector, void *load_addr, int sec_num); + #define VIRTIO_SECTOR_SIZE 512 + #define VIRTIO_ISO_BLOCK_SIZE 2048 + #define VIRTIO_SCSI_BLOCK_SIZE 512 ++#define VIRTIO_DASD_DEFAULT_BLOCK_SIZE 4096 + + static inline ulong virtio_sector_adjust(ulong sector) + { +-- +2.35.3 + diff --git a/kvm-pc-bios-s390-ccw-virtio-Read-device-config-after-fea.patch b/kvm-pc-bios-s390-ccw-virtio-Read-device-config-after-fea.patch new file mode 100644 index 0000000..53f125a --- /dev/null +++ b/kvm-pc-bios-s390-ccw-virtio-Read-device-config-after-fea.patch @@ -0,0 +1,67 @@ +From a60940fb7ef026f3aa968e77389efa51ea648ddf Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 8 Jul 2022 12:29:50 +0200 +Subject: [PATCH 34/37] pc-bios/s390-ccw/virtio: Read device config after + feature negotiation + +RH-Author: Thomas Huth +RH-MergeRequest: 198: pc-bios/s390-ccw: Fix boot from disks with 4k sectors that do not have the typical DASD geometry +RH-Commit: [6/9] 99ed8765d614207db19ded75d62c65171674d982 +RH-Bugzilla: 2098076 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: David Hildenbrand +RH-Acked-by: Cornelia Huck + +Bugzilla: http://bugzilla.redhat.com/2098076 + +commit aa5c69ce99411c4886bcd051f288afc02b6d968d +Author: Thomas Huth +Date: Mon Jul 4 13:18:58 2022 +0200 + + pc-bios/s390-ccw/virtio: Read device config after feature negotiation + + Feature negotiation should be done first, since some fields in the + config area can depend on the negotiated features and thus should + rather be read afterwards. + + While we're at it, also adjust the error message here a little bit + (the code is nowadays used for non-block virtio devices, too). + + Message-Id: <20220704111903.62400-8-thuth@redhat.com> + Reviewed-by: Eric Farman + Reviewed-by: Cornelia Huck + Signed-off-by: Thomas Huth + +Signed-off-by: Thomas Huth +--- + pc-bios/s390-ccw/virtio.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +diff --git a/pc-bios/s390-ccw/virtio.c b/pc-bios/s390-ccw/virtio.c +index 4e85a2eb82..d8c2b52710 100644 +--- a/pc-bios/s390-ccw/virtio.c ++++ b/pc-bios/s390-ccw/virtio.c +@@ -262,10 +262,6 @@ void virtio_setup_ccw(VDev *vdev) + rc = run_ccw(vdev, CCW_CMD_WRITE_STATUS, &status, sizeof(status), false); + IPL_assert(rc == 0, "Could not write DRIVER status to host"); + +- IPL_assert( +- run_ccw(vdev, CCW_CMD_READ_CONF, &vdev->config, cfg_size, false) == 0, +- "Could not get block device configuration"); +- + /* Feature negotiation */ + for (i = 0; i < ARRAY_SIZE(vdev->guest_features); i++) { + feats.features = 0; +@@ -278,6 +274,9 @@ void virtio_setup_ccw(VDev *vdev) + IPL_assert(rc == 0, "Could not set features bits"); + } + ++ rc = run_ccw(vdev, CCW_CMD_READ_CONF, &vdev->config, cfg_size, false); ++ IPL_assert(rc == 0, "Could not get virtio device configuration"); ++ + for (i = 0; i < vdev->nr_vqs; i++) { + VqInfo info = { + .queue = (unsigned long long) ring_area + (i * VIRTIO_RING_SIZE), +-- +2.35.3 + diff --git a/kvm-pc-bios-s390-ccw-virtio-Set-missing-status-bits-whil.patch b/kvm-pc-bios-s390-ccw-virtio-Set-missing-status-bits-whil.patch new file mode 100644 index 0000000..b25a352 --- /dev/null +++ b/kvm-pc-bios-s390-ccw-virtio-Set-missing-status-bits-whil.patch @@ -0,0 +1,93 @@ +From 5cf01cccb7501c801fa9f21a021bc9e7d1fc56e3 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 8 Jul 2022 12:29:50 +0200 +Subject: [PATCH 33/37] pc-bios/s390-ccw/virtio: Set missing status bits while + initializing + +RH-Author: Thomas Huth +RH-MergeRequest: 198: pc-bios/s390-ccw: Fix boot from disks with 4k sectors that do not have the typical DASD geometry +RH-Commit: [5/9] 6072245f49c229518246b4a0d1be360331305bfa +RH-Bugzilla: 2098076 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: David Hildenbrand +RH-Acked-by: Cornelia Huck + +Bugzilla: http://bugzilla.redhat.com/2098076 + +commit 175aa06a152ef6b58ba9b2e47a1296b024dea70c +Author: Thomas Huth +Date: Mon Jul 4 13:18:57 2022 +0200 + + pc-bios/s390-ccw/virtio: Set missing status bits while initializing + + According chapter "3.1.1 Driver Requirements: Device Initialization" + of the Virtio specification (v1.1), a driver for a device has to set + the ACKNOWLEDGE and DRIVER bits in the status field after resetting + the device. The s390-ccw bios skipped these steps so far and seems + like QEMU never cared. Anyway, it's better to follow the spec, so + let's set these bits now in the right spots, too. + + Message-Id: <20220704111903.62400-7-thuth@redhat.com> + Acked-by: Christian Borntraeger + Reviewed-by: Cornelia Huck + Reviewed-by: Eric Farman + Signed-off-by: Thomas Huth + +Signed-off-by: Thomas Huth +--- + pc-bios/s390-ccw/virtio.c | 18 ++++++++++++++---- + 1 file changed, 14 insertions(+), 4 deletions(-) + +diff --git a/pc-bios/s390-ccw/virtio.c b/pc-bios/s390-ccw/virtio.c +index 5d2c6e3381..4e85a2eb82 100644 +--- a/pc-bios/s390-ccw/virtio.c ++++ b/pc-bios/s390-ccw/virtio.c +@@ -220,7 +220,7 @@ int virtio_run(VDev *vdev, int vqid, VirtioCmd *cmd) + void virtio_setup_ccw(VDev *vdev) + { + int i, rc, cfg_size = 0; +- unsigned char status = VIRTIO_CONFIG_S_DRIVER_OK; ++ uint8_t status; + struct VirtioFeatureDesc { + uint32_t features; + uint8_t index; +@@ -234,6 +234,10 @@ void virtio_setup_ccw(VDev *vdev) + + run_ccw(vdev, CCW_CMD_VDEV_RESET, NULL, 0, false); + ++ status = VIRTIO_CONFIG_S_ACKNOWLEDGE; ++ rc = run_ccw(vdev, CCW_CMD_WRITE_STATUS, &status, sizeof(status), false); ++ IPL_assert(rc == 0, "Could not write ACKNOWLEDGE status to host"); ++ + switch (vdev->senseid.cu_model) { + case VIRTIO_ID_NET: + vdev->nr_vqs = 2; +@@ -253,6 +257,11 @@ void virtio_setup_ccw(VDev *vdev) + default: + panic("Unsupported virtio device\n"); + } ++ ++ status |= VIRTIO_CONFIG_S_DRIVER; ++ rc = run_ccw(vdev, CCW_CMD_WRITE_STATUS, &status, sizeof(status), false); ++ IPL_assert(rc == 0, "Could not write DRIVER status to host"); ++ + IPL_assert( + run_ccw(vdev, CCW_CMD_READ_CONF, &vdev->config, cfg_size, false) == 0, + "Could not get block device configuration"); +@@ -291,9 +300,10 @@ void virtio_setup_ccw(VDev *vdev) + run_ccw(vdev, CCW_CMD_SET_VQ, &info, sizeof(info), false) == 0, + "Cannot set VQ info"); + } +- IPL_assert( +- run_ccw(vdev, CCW_CMD_WRITE_STATUS, &status, sizeof(status), false) == 0, +- "Could not write status to host"); ++ ++ status |= VIRTIO_CONFIG_S_DRIVER_OK; ++ rc = run_ccw(vdev, CCW_CMD_WRITE_STATUS, &status, sizeof(status), false); ++ IPL_assert(rc == 0, "Could not write DRIVER_OK status to host"); + } + + bool virtio_is_supported(SubChannelId schid) +-- +2.35.3 + diff --git a/kvm-pc-bios-s390-ccw-virtio-blkdev-Remove-virtio_assume_.patch b/kvm-pc-bios-s390-ccw-virtio-blkdev-Remove-virtio_assume_.patch new file mode 100644 index 0000000..ff8aab3 --- /dev/null +++ b/kvm-pc-bios-s390-ccw-virtio-blkdev-Remove-virtio_assume_.patch @@ -0,0 +1,101 @@ +From 5b3548c50e35729d724403b83e26579d31621367 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 8 Jul 2022 12:29:50 +0200 +Subject: [PATCH 32/37] pc-bios/s390-ccw/virtio-blkdev: Remove + virtio_assume_scsi() + +RH-Author: Thomas Huth +RH-MergeRequest: 198: pc-bios/s390-ccw: Fix boot from disks with 4k sectors that do not have the typical DASD geometry +RH-Commit: [4/9] 5256c4e6f4d5c5aedf1bad3fee30dd3ad230a3dd +RH-Bugzilla: 2098076 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: David Hildenbrand +RH-Acked-by: Cornelia Huck + +Bugzilla: http://bugzilla.redhat.com/2098076 + +commit 5447de2619050a0a4dd480b97f88a9b58da360d1 +Author: Thomas Huth +Date: Mon Jul 4 13:18:56 2022 +0200 + + pc-bios/s390-ccw/virtio-blkdev: Remove virtio_assume_scsi() + + The virtio_assume_scsi() function is very questionable: First, it + is only called for virtio-blk, and not for virtio-scsi, so the naming + is already quite confusing. Second, it is called if we detected a + "invalid" IPL disk, trying to fix it by blindly setting a sector + size of 512. This of course won't work in most cases since disks + might have a different sector size for a reason. + + Thus let's remove this strange function now. The calling code can + also be removed completely, since there is another spot in main.c + that does "IPL_assert(virtio_ipl_disk_is_valid(), ...)" to make + sure that we do not try to IPL from an invalid device. + + Message-Id: <20220704111903.62400-6-thuth@redhat.com> + Reviewed-by: Eric Farman + Signed-off-by: Thomas Huth + +Signed-off-by: Thomas Huth +--- + pc-bios/s390-ccw/virtio-blkdev.c | 24 ------------------------ + pc-bios/s390-ccw/virtio.h | 1 - + 2 files changed, 25 deletions(-) + +diff --git a/pc-bios/s390-ccw/virtio-blkdev.c b/pc-bios/s390-ccw/virtio-blkdev.c +index 7e13155589..db1f7f44aa 100644 +--- a/pc-bios/s390-ccw/virtio-blkdev.c ++++ b/pc-bios/s390-ccw/virtio-blkdev.c +@@ -112,23 +112,6 @@ VirtioGDN virtio_guessed_disk_nature(void) + return virtio_get_device()->guessed_disk_nature; + } + +-void virtio_assume_scsi(void) +-{ +- VDev *vdev = virtio_get_device(); +- +- switch (vdev->senseid.cu_model) { +- case VIRTIO_ID_BLOCK: +- vdev->guessed_disk_nature = VIRTIO_GDN_SCSI; +- vdev->config.blk.blk_size = VIRTIO_SCSI_BLOCK_SIZE; +- vdev->config.blk.physical_block_exp = 0; +- vdev->blk_factor = 1; +- break; +- case VIRTIO_ID_SCSI: +- vdev->scsi_block_size = VIRTIO_SCSI_BLOCK_SIZE; +- break; +- } +-} +- + void virtio_assume_iso9660(void) + { + VDev *vdev = virtio_get_device(); +@@ -247,13 +230,6 @@ int virtio_blk_setup_device(SubChannelId schid) + switch (vdev->senseid.cu_model) { + case VIRTIO_ID_BLOCK: + sclp_print("Using virtio-blk.\n"); +- if (!virtio_ipl_disk_is_valid()) { +- /* make sure all getters but blocksize return 0 for +- * invalid IPL disk +- */ +- memset(&vdev->config.blk, 0, sizeof(vdev->config.blk)); +- virtio_assume_scsi(); +- } + break; + case VIRTIO_ID_SCSI: + IPL_assert(vdev->config.scsi.sense_size == VIRTIO_SCSI_SENSE_SIZE, +diff --git a/pc-bios/s390-ccw/virtio.h b/pc-bios/s390-ccw/virtio.h +index 241730effe..600ba5052b 100644 +--- a/pc-bios/s390-ccw/virtio.h ++++ b/pc-bios/s390-ccw/virtio.h +@@ -182,7 +182,6 @@ enum guessed_disk_nature_type { + typedef enum guessed_disk_nature_type VirtioGDN; + + VirtioGDN virtio_guessed_disk_nature(void); +-void virtio_assume_scsi(void); + void virtio_assume_eckd(void); + void virtio_assume_iso9660(void); + +-- +2.35.3 + diff --git a/kvm-pc-bios-s390-ccw-virtio-blkdev-Request-the-right-fea.patch b/kvm-pc-bios-s390-ccw-virtio-blkdev-Request-the-right-fea.patch new file mode 100644 index 0000000..ade5ff2 --- /dev/null +++ b/kvm-pc-bios-s390-ccw-virtio-blkdev-Request-the-right-fea.patch @@ -0,0 +1,63 @@ +From 042e966a70789bd3ed450fa4f57016129a34672e Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 8 Jul 2022 12:29:50 +0200 +Subject: [PATCH 37/37] pc-bios/s390-ccw/virtio-blkdev: Request the right + feature bits + +RH-Author: Thomas Huth +RH-MergeRequest: 198: pc-bios/s390-ccw: Fix boot from disks with 4k sectors that do not have the typical DASD geometry +RH-Commit: [9/9] f04835423d648b04f2187ef9890f2d1689e2b57e +RH-Bugzilla: 2098076 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: David Hildenbrand +RH-Acked-by: Cornelia Huck + +Bugzilla: http://bugzilla.redhat.com/2098076 + +commit 9125a314cca4a1838b09305a87d8efb98f80ab67 +Author: Thomas Huth +Date: Mon Jul 4 13:19:01 2022 +0200 + + pc-bios/s390-ccw/virtio-blkdev: Request the right feature bits + + The virtio-blk code uses the block size and geometry fields in the + config area. According to the virtio-spec, these have to be negotiated + with the right feature bits during initialization, otherwise they + might not be available. QEMU is so far very forgiving and always + provides them, but we should not rely on this behavior, so let's + better request them properly via the VIRTIO_BLK_F_GEOMETRY and + VIRTIO_BLK_F_BLK_SIZE feature bits. + + Message-Id: <20220704111903.62400-11-thuth@redhat.com> + Signed-off-by: Thomas Huth + +Signed-off-by: Thomas Huth +--- + pc-bios/s390-ccw/virtio-blkdev.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/pc-bios/s390-ccw/virtio-blkdev.c b/pc-bios/s390-ccw/virtio-blkdev.c +index c175b66a47..8271c47296 100644 +--- a/pc-bios/s390-ccw/virtio-blkdev.c ++++ b/pc-bios/s390-ccw/virtio-blkdev.c +@@ -13,6 +13,9 @@ + #include "virtio.h" + #include "virtio-scsi.h" + ++#define VIRTIO_BLK_F_GEOMETRY (1 << 4) ++#define VIRTIO_BLK_F_BLK_SIZE (1 << 6) ++ + static int virtio_blk_read_many(VDev *vdev, ulong sector, void *load_addr, + int sec_num) + { +@@ -223,6 +226,7 @@ int virtio_blk_setup_device(SubChannelId schid) + { + VDev *vdev = virtio_get_device(); + ++ vdev->guest_features[0] = VIRTIO_BLK_F_GEOMETRY | VIRTIO_BLK_F_BLK_SIZE; + vdev->schid = schid; + virtio_setup_ccw(vdev); + +-- +2.35.3 + diff --git a/kvm-pc-bios-s390-ccw-virtio-blkdev-Simplify-fix-virtio_i.patch b/kvm-pc-bios-s390-ccw-virtio-blkdev-Simplify-fix-virtio_i.patch new file mode 100644 index 0000000..1730dd3 --- /dev/null +++ b/kvm-pc-bios-s390-ccw-virtio-blkdev-Simplify-fix-virtio_i.patch @@ -0,0 +1,124 @@ +From f09f2f12133073d6ccab3b2bd95717d435adc442 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 8 Jul 2022 12:29:50 +0200 +Subject: [PATCH 31/37] pc-bios/s390-ccw/virtio-blkdev: Simplify/fix + virtio_ipl_disk_is_valid() + +RH-Author: Thomas Huth +RH-MergeRequest: 198: pc-bios/s390-ccw: Fix boot from disks with 4k sectors that do not have the typical DASD geometry +RH-Commit: [3/9] ca0b836a417ce5bbd26e489551f573d6b2fc9e94 +RH-Bugzilla: 2098076 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: David Hildenbrand +RH-Acked-by: Cornelia Huck + +Bugzilla: http://bugzilla.redhat.com/2098076 + +commit bbf615f7b707f009ef8e757d170902ad33b90644 +Author: Thomas Huth +Date: Mon Jul 4 13:18:55 2022 +0200 + + pc-bios/s390-ccw/virtio-blkdev: Simplify/fix virtio_ipl_disk_is_valid() + + The s390-ccw bios fails to boot if the boot disk is a virtio-blk + disk with a sector size of 4096. For example: + + dasdfmt -b 4096 -d cdl -y -p -M quick /dev/dasdX + fdasd -a /dev/dasdX + install a guest onto /dev/dasdX1 using virtio-blk + qemu-system-s390x -nographic -hda /dev/dasdX1 + + The bios then bails out with: + + ! Cannot read block 0 ! + + Looking at virtio_ipl_disk_is_valid() and especially the function + virtio_disk_is_scsi(), it does not really make sense that we expect + only such a limited disk geometry (like a block size of 512) for + our boot disks. Let's relax the check and allow everything that + remotely looks like a sane disk. + + Message-Id: <20220704111903.62400-5-thuth@redhat.com> + Reviewed-by: Eric Farman + Signed-off-by: Thomas Huth + +Signed-off-by: Thomas Huth +--- + pc-bios/s390-ccw/virtio-blkdev.c | 41 ++++++-------------------------- + pc-bios/s390-ccw/virtio.h | 2 -- + 2 files changed, 7 insertions(+), 36 deletions(-) + +diff --git a/pc-bios/s390-ccw/virtio-blkdev.c b/pc-bios/s390-ccw/virtio-blkdev.c +index 6483307630..7e13155589 100644 +--- a/pc-bios/s390-ccw/virtio-blkdev.c ++++ b/pc-bios/s390-ccw/virtio-blkdev.c +@@ -166,46 +166,19 @@ void virtio_assume_eckd(void) + virtio_eckd_sectors_for_block_size(vdev->config.blk.blk_size); + } + +-bool virtio_disk_is_scsi(void) +-{ +- VDev *vdev = virtio_get_device(); +- +- if (vdev->guessed_disk_nature == VIRTIO_GDN_SCSI) { +- return true; +- } +- switch (vdev->senseid.cu_model) { +- case VIRTIO_ID_BLOCK: +- return (vdev->config.blk.geometry.heads == 255) +- && (vdev->config.blk.geometry.sectors == 63) +- && (virtio_get_block_size() == VIRTIO_SCSI_BLOCK_SIZE); +- case VIRTIO_ID_SCSI: +- return true; +- } +- return false; +-} +- +-bool virtio_disk_is_eckd(void) ++bool virtio_ipl_disk_is_valid(void) + { ++ int blksize = virtio_get_block_size(); + VDev *vdev = virtio_get_device(); +- const int block_size = virtio_get_block_size(); + +- if (vdev->guessed_disk_nature == VIRTIO_GDN_DASD) { ++ if (vdev->guessed_disk_nature == VIRTIO_GDN_SCSI || ++ vdev->guessed_disk_nature == VIRTIO_GDN_DASD) { + return true; + } +- switch (vdev->senseid.cu_model) { +- case VIRTIO_ID_BLOCK: +- return (vdev->config.blk.geometry.heads == 15) +- && (vdev->config.blk.geometry.sectors == +- virtio_eckd_sectors_for_block_size(block_size)); +- case VIRTIO_ID_SCSI: +- return false; +- } +- return false; +-} + +-bool virtio_ipl_disk_is_valid(void) +-{ +- return virtio_disk_is_scsi() || virtio_disk_is_eckd(); ++ return (vdev->senseid.cu_model == VIRTIO_ID_BLOCK || ++ vdev->senseid.cu_model == VIRTIO_ID_SCSI) && ++ blksize >= 512 && blksize <= 4096; + } + + int virtio_get_block_size(void) +diff --git a/pc-bios/s390-ccw/virtio.h b/pc-bios/s390-ccw/virtio.h +index 9e410bde6f..241730effe 100644 +--- a/pc-bios/s390-ccw/virtio.h ++++ b/pc-bios/s390-ccw/virtio.h +@@ -186,8 +186,6 @@ void virtio_assume_scsi(void); + void virtio_assume_eckd(void); + void virtio_assume_iso9660(void); + +-extern bool virtio_disk_is_scsi(void); +-extern bool virtio_disk_is_eckd(void); + extern bool virtio_ipl_disk_is_valid(void); + extern int virtio_get_block_size(void); + extern uint8_t virtio_get_heads(void); +-- +2.35.3 + diff --git a/kvm-pci-expose-TYPE_XIO3130_DOWNSTREAM-name.patch b/kvm-pci-expose-TYPE_XIO3130_DOWNSTREAM-name.patch index dee75d2..817f0ab 100644 --- a/kvm-pci-expose-TYPE_XIO3130_DOWNSTREAM-name.patch +++ b/kvm-pci-expose-TYPE_XIO3130_DOWNSTREAM-name.patch @@ -1,25 +1,35 @@ -From 5f5208c1d41477645b2707cfac206d24d86b9254 Mon Sep 17 00:00:00 2001 -From: Igor Mammedov -Date: Tue, 1 Mar 2022 10:11:58 -0500 -Subject: [PATCH 5/6] pci: expose TYPE_XIO3130_DOWNSTREAM name +From 7998e8aa78caa35c2ab2da44f9e29e21d7548c61 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Wed, 23 Mar 2022 13:21:40 -0400 +Subject: [PATCH 05/18] pci: expose TYPE_XIO3130_DOWNSTREAM name -RH-Author: Igor Mammedov -RH-MergeRequest: 125: RHEL-8.6 Fix broken PCIe device after migration -RH-Commit: [1/2] 703782ce00f067c811056d5765a8b2094e585b4f -RH-Bugzilla: 2054597 -RH-Acked-by: Jon Maloy +RH-Author: Jon Maloy +RH-MergeRequest: 134: pci: expose TYPE_XIO3130_DOWNSTREAM name +RH-Commit: [1/2] f09ddcaf686f22b545bf269f87787ebfc33fccda (jmaloy/qemu-kvm) +RH-Bugzilla: 2062610 +RH-Acked-by: Igor Mammedov RH-Acked-by: Gerd Hoffmann -RH-Acked-by: MST -Type name will be used in followup patch for cast check -in pcihp code. +BZ: https://bugzilla.redhat.com/2062610 +UPSTREAM: merged +BREW: https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=44038138 + +commit c41481af9a5d0d463607cc45b45c510875570817 +Author: Igor Mammedov +Date: Tue Mar 1 10:11:58 2022 -0500 + + pci: expose TYPE_XIO3130_DOWNSTREAM name + + Type name will be used in followup patch for cast check + in pcihp code. + + Signed-off-by: Igor Mammedov + Message-Id: <20220301151200.3507298-2-imammedo@redhat.com> + Reviewed-by: Michael S. Tsirkin + Signed-off-by: Michael S. Tsirkin -Signed-off-by: Igor Mammedov -Message-Id: <20220301151200.3507298-2-imammedo@redhat.com> -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Michael S. Tsirkin (cherry picked from commit c41481af9a5d0d463607cc45b45c510875570817) -Signed-off-by: Igor Mammedov +Signed-off-by: Jon Maloy --- hw/pci-bridge/xio3130_downstream.c | 3 ++- include/hw/pci-bridge/xio3130_downstream.h | 15 +++++++++++++++ diff --git a/kvm-qcow2-Add-errp-to-rebuild_refcount_structure.patch b/kvm-qcow2-Add-errp-to-rebuild_refcount_structure.patch index 6cd88e8..8ed0d2e 100644 --- a/kvm-qcow2-Add-errp-to-rebuild_refcount_structure.patch +++ b/kvm-qcow2-Add-errp-to-rebuild_refcount_structure.patch @@ -1,15 +1,15 @@ -From 6c475f4bc2c323d75d40eb37386fbb86819791ec Mon Sep 17 00:00:00 2001 +From 552e7c8ae2c6e281a72791aefa1729be86f96642 Mon Sep 17 00:00:00 2001 From: Hanna Reitz Date: Tue, 5 Apr 2022 15:46:52 +0200 -Subject: [PATCH 10/11] qcow2: Add errp to rebuild_refcount_structure() +Subject: [PATCH 5/6] qcow2: Add errp to rebuild_refcount_structure() RH-Author: Hanna Reitz -RH-MergeRequest: 173: qcow2: Improve refcount structure rebuilding -RH-Commit: [3/4] 95a6b7bb558a9ed35afae3fa9fefd761312ecb3b -RH-Bugzilla: 2072242 +RH-MergeRequest: 171: qcow2: Improve refcount structure rebuilding +RH-Commit: [3/4] 9dddd1d21383c4cbd528e5a0d42b0c2a7d87c8f6 +RH-Bugzilla: 1519071 RH-Acked-by: Miroslav Rezanina -RH-Acked-by: Eric Blake RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Eric Blake Instead of fprint()-ing error messages in rebuild_refcount_structure() and its rebuild_refcounts_write_refblocks() helper, pass them through an diff --git a/kvm-qcow2-Improve-refcount-structure-rebuilding.patch b/kvm-qcow2-Improve-refcount-structure-rebuilding.patch index b7cab6f..efae75f 100644 --- a/kvm-qcow2-Improve-refcount-structure-rebuilding.patch +++ b/kvm-qcow2-Improve-refcount-structure-rebuilding.patch @@ -1,15 +1,15 @@ -From 3daca05a8f845d2a389a6cf767314bcb72109578 Mon Sep 17 00:00:00 2001 +From be54c6206b0f0a19e0ffe6a058f4f97277027a17 Mon Sep 17 00:00:00 2001 From: Hanna Reitz Date: Tue, 5 Apr 2022 15:46:50 +0200 -Subject: [PATCH 08/11] qcow2: Improve refcount structure rebuilding +Subject: [PATCH 3/6] qcow2: Improve refcount structure rebuilding RH-Author: Hanna Reitz -RH-MergeRequest: 173: qcow2: Improve refcount structure rebuilding -RH-Commit: [1/4] 586e7a0fc3cb7cc2296b544ffcef34d8395fa74c -RH-Bugzilla: 2072242 +RH-MergeRequest: 171: qcow2: Improve refcount structure rebuilding +RH-Commit: [1/4] 0bb78f7735a0730204670ae5ec2e040ad1d23942 +RH-Bugzilla: 1519071 RH-Acked-by: Miroslav Rezanina -RH-Acked-by: Eric Blake RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Eric Blake When rebuilding the refcount structures (when qemu-img check -r found errors with refcount = 0, but reference count > 0), the new refcount diff --git a/kvm-s390x-css-fix-PMCW-invalid-mask.patch b/kvm-s390x-css-fix-PMCW-invalid-mask.patch new file mode 100644 index 0000000..959eea9 --- /dev/null +++ b/kvm-s390x-css-fix-PMCW-invalid-mask.patch @@ -0,0 +1,58 @@ +From f3125f6379cbc070e9acaf58d0ec37972992744b Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Wed, 6 Apr 2022 10:56:26 +0200 +Subject: [PATCH 4/5] s390x/css: fix PMCW invalid mask + +RH-Author: Thomas Huth +RH-MergeRequest: 145: s390x/css: fix PMCW invalid mask +RH-Commit: [1/1] fbf192f651aa668af56ca5c77455595fcdb19508 +RH-Bugzilla: 2071070 +RH-Acked-by: Jon Maloy +RH-Acked-by: David Hildenbrand +RH-Acked-by: Cornelia Huck + +Bugzilla: http://bugzilla.redhat.com/2071070 + +commit 2df59b73e0864f021f6179f32f7ed364f6d4f38d +Author: Nico Boehr +Date: Thu Dec 16 14:16:57 2021 +0100 + + s390x/css: fix PMCW invalid mask + + Previously, we required bits 5, 6 and 7 to be zero (0x07 == 0b111). But, + as per the principles of operation, bit 5 is ignored in MSCH and bits 0, + 1, 6 and 7 need to be zero. + + As both PMCW_FLAGS_MASK_INVALID and ioinst_schib_valid() are only used + by ioinst_handle_msch(), adjust the mask accordingly. + + Fixes: db1c8f53bfb1 ("s390: Channel I/O basic definitions.") + Signed-off-by: Nico Boehr + Reviewed-by: Pierre Morel + Reviewed-by: Halil Pasic + Reviewed-by: Janosch Frank + Reviewed-by: Cornelia Huck + Message-Id: <20211216131657.1057978-1-nrb@linux.ibm.com> + Signed-off-by: Thomas Huth + +Signed-off-by: Thomas Huth +--- + include/hw/s390x/ioinst.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/include/hw/s390x/ioinst.h b/include/hw/s390x/ioinst.h +index 3771fff9d4..ea8d0f2444 100644 +--- a/include/hw/s390x/ioinst.h ++++ b/include/hw/s390x/ioinst.h +@@ -107,7 +107,7 @@ QEMU_BUILD_BUG_MSG(sizeof(PMCW) != 28, "size of PMCW is wrong"); + #define PMCW_FLAGS_MASK_MP 0x0004 + #define PMCW_FLAGS_MASK_TF 0x0002 + #define PMCW_FLAGS_MASK_DNV 0x0001 +-#define PMCW_FLAGS_MASK_INVALID 0x0700 ++#define PMCW_FLAGS_MASK_INVALID 0xc300 + + #define PMCW_CHARS_MASK_ST 0x00e00000 + #define PMCW_CHARS_MASK_MBFC 0x00000004 +-- +2.27.0 + diff --git a/kvm-s390x-ipl-support-extended-kernel-command-line-size.patch b/kvm-s390x-ipl-support-extended-kernel-command-line-size.patch new file mode 100644 index 0000000..d62a45a --- /dev/null +++ b/kvm-s390x-ipl-support-extended-kernel-command-line-size.patch @@ -0,0 +1,97 @@ +From ddfee9d393af322938e4df466cd01b8f9570a1c9 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Tue, 5 Apr 2022 10:20:59 +0200 +Subject: [PATCH 1/6] s390x/ipl: support extended kernel command line size + +RH-Author: Thomas Huth +RH-MergeRequest: 144: s390x/ipl: support extended kernel command line size +RH-Commit: [1/1] be227e50af5dbe7802605f873db29ac5358aa196 +RH-Bugzilla: 2043830 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand + +Bugzilla: http://bugzilla.redhat.com/2043830 + +commit b2173046a64beed76715f310f98538f159276af1 +Author: Marc Hartmayer +Date: Mon Nov 22 12:29:09 2021 +0100 + + s390x/ipl: support extended kernel command line size + + In the past s390 used a fixed command line length of 896 bytes. This has changed + with the Linux commit 5ecb2da660ab ("s390: support command lines longer than 896 + bytes"). There is now a parm area indicating the maximum command line size. This + parm area has always been initialized to zero, so with older kernels this field + would read zero and we must then assume that only 896 bytes are available. + + Signed-off-by: Marc Hartmayer + Reviewed-by: David Hildenbrand + Reviewed-by: Christian Borntraeger + Acked-by: Viktor Mihajlovski + Message-Id: <20211122112909.18138-1-mhartmay@linux.ibm.com> + [thuth: Cosmetic fixes, and use PRIu64 instead of %lu] + Signed-off-by: Thomas Huth + +Signed-off-by: Thomas Huth +--- + hw/s390x/ipl.c | 27 +++++++++++++++++++++++---- + 1 file changed, 23 insertions(+), 4 deletions(-) + +diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c +index 7ddca0127f..eb7fc4c4ae 100644 +--- a/hw/s390x/ipl.c ++++ b/hw/s390x/ipl.c +@@ -37,8 +37,9 @@ + + #define KERN_IMAGE_START 0x010000UL + #define LINUX_MAGIC_ADDR 0x010008UL ++#define KERN_PARM_AREA_SIZE_ADDR 0x010430UL + #define KERN_PARM_AREA 0x010480UL +-#define KERN_PARM_AREA_SIZE 0x000380UL ++#define LEGACY_KERN_PARM_AREA_SIZE 0x000380UL + #define INITRD_START 0x800000UL + #define INITRD_PARM_START 0x010408UL + #define PARMFILE_START 0x001000UL +@@ -110,6 +111,21 @@ static uint64_t bios_translate_addr(void *opaque, uint64_t srcaddr) + return srcaddr + dstaddr; + } + ++static uint64_t get_max_kernel_cmdline_size(void) ++{ ++ uint64_t *size_ptr = rom_ptr(KERN_PARM_AREA_SIZE_ADDR, sizeof(*size_ptr)); ++ ++ if (size_ptr) { ++ uint64_t size; ++ ++ size = be64_to_cpu(*size_ptr); ++ if (size) { ++ return size; ++ } ++ } ++ return LEGACY_KERN_PARM_AREA_SIZE; ++} ++ + static void s390_ipl_realize(DeviceState *dev, Error **errp) + { + MachineState *ms = MACHINE(qdev_get_machine()); +@@ -197,10 +213,13 @@ static void s390_ipl_realize(DeviceState *dev, Error **errp) + ipl->start_addr = KERN_IMAGE_START; + /* Overwrite parameters in the kernel image, which are "rom" */ + if (parm_area) { +- if (cmdline_size > KERN_PARM_AREA_SIZE) { ++ uint64_t max_cmdline_size = get_max_kernel_cmdline_size(); ++ ++ if (cmdline_size > max_cmdline_size) { + error_setg(errp, +- "kernel command line exceeds maximum size: %zu > %lu", +- cmdline_size, KERN_PARM_AREA_SIZE); ++ "kernel command line exceeds maximum size:" ++ " %zu > %" PRIu64, ++ cmdline_size, max_cmdline_size); + return; + } + +-- +2.27.0 + diff --git a/kvm-scsi-generic-Fix-emulated-block-limits-VPD-page.patch b/kvm-scsi-generic-Fix-emulated-block-limits-VPD-page.patch index ed6a00d..0fc1a71 100644 --- a/kvm-scsi-generic-Fix-emulated-block-limits-VPD-page.patch +++ b/kvm-scsi-generic-Fix-emulated-block-limits-VPD-page.patch @@ -1,15 +1,16 @@ -From 2fdce42dabea90646371c4cc19bfca1db666aaea Mon Sep 17 00:00:00 2001 +From a9a4dfdd6312e192e9134d46edfac4c1b1bfa63d Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Mon, 22 Aug 2022 14:53:20 +0200 Subject: [PATCH] scsi-generic: Fix emulated block limits VPD page RH-Author: Kevin Wolf -RH-MergeRequest: 214: scsi-generic: Fix emulated block limits VPD page -RH-Commit: [1/1] 6f980d29b849a7b5cea894aefed5f0b6502c6298 -RH-Bugzilla: 2121783 +RH-MergeRequest: 212: scsi-generic: Fix emulated block limits VPD page +RH-Commit: [1/1] d3ba6b2e03039043716ddc6b7d4a424d92249081 +RH-Bugzilla: 2120279 +RH-Acked-by: Emanuele Giuseppe Esposito RH-Acked-by: Hanna Reitz +RH-Acked-by: Paolo Bonzini RH-Acked-by: Stefan Hajnoczi -RH-Acked-by: Miroslav Rezanina Commits 01ef8185b80 amd 24b36e9813e updated the way that the maximum transfer length is calculated for patching block limits VPD page in an @@ -92,5 +93,5 @@ index 0306ccc7b1..3742899839 100644 memset(r->buf, 0, r->buflen); -- -2.27.0 +2.35.3 diff --git a/kvm-softmmu-physmem-Introduce-MemTxAttrs-memory-field-an.patch b/kvm-softmmu-physmem-Introduce-MemTxAttrs-memory-field-an.patch index 8a9d7b4..519c48d 100644 --- a/kvm-softmmu-physmem-Introduce-MemTxAttrs-memory-field-an.patch +++ b/kvm-softmmu-physmem-Introduce-MemTxAttrs-memory-field-an.patch @@ -1,21 +1,20 @@ -From b1eae36683cdfe63af5749b5fe86b1c08fc0f63e Mon Sep 17 00:00:00 2001 +From fe4e22b9ccf2eb55d61eccf5050fb7aeafb5fe20 Mon Sep 17 00:00:00 2001 From: Jon Maloy Date: Wed, 13 Apr 2022 14:51:06 -0400 -Subject: [PATCH 04/11] softmmu/physmem: Introduce MemTxAttrs::memory field and +Subject: [PATCH 3/3] softmmu/physmem: Introduce MemTxAttrs::memory field and MEMTX_ACCESS_ERROR MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RH-Author: Jon Maloy -RH-MergeRequest: 158: hw/intc/arm_gicv3: Check for !MEMTX_OK instead of MEMTX_ERROR -RH-Commit: [3/3] 84d64fe85a106f8faf579e43266d4349fc8e65b4 (jmaloy/qemu-kvm) -RH-Bugzilla: 2075686 -RH-Acked-by: Miroslav Rezanina +RH-MergeRequest: 151: hw/intc/arm_gicv3: Check for !MEMTX_OK instead of MEMTX_ERROR +RH-Commit: [3/3] b1ebc1e99f21ba0b9eccb284e260b56c7a8e64d8 (jmaloy/qemu-kvm) +RH-Bugzilla: 1999236 RH-Acked-by: Stefan Hajnoczi RH-Acked-by: Peter Xu -Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2075686 +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1999236 Upstream: Merged CVE: CVE-2021-3750 Conflicts: memalign.h has not been introduced in this version. Instead, diff --git a/kvm-softmmu-physmem-Simplify-flatview_write-and-address_.patch b/kvm-softmmu-physmem-Simplify-flatview_write-and-address_.patch index d554db2..62f7037 100644 --- a/kvm-softmmu-physmem-Simplify-flatview_write-and-address_.patch +++ b/kvm-softmmu-physmem-Simplify-flatview_write-and-address_.patch @@ -1,21 +1,20 @@ -From b570eb3a78a3096af55979ce63d96f5fc012f9e5 Mon Sep 17 00:00:00 2001 +From 916423392b46167c6683b0240610bb5a745590da Mon Sep 17 00:00:00 2001 From: Jon Maloy Date: Wed, 13 Apr 2022 14:51:06 -0400 -Subject: [PATCH 03/11] softmmu/physmem: Simplify flatview_write and +Subject: [PATCH 2/3] softmmu/physmem: Simplify flatview_write and address_space_access_valid MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RH-Author: Jon Maloy -RH-MergeRequest: 158: hw/intc/arm_gicv3: Check for !MEMTX_OK instead of MEMTX_ERROR -RH-Commit: [2/3] 66281d1c439be549c7890a662a817dd1b9367ef2 (jmaloy/qemu-kvm) -RH-Bugzilla: 2075686 -RH-Acked-by: Miroslav Rezanina +RH-MergeRequest: 151: hw/intc/arm_gicv3: Check for !MEMTX_OK instead of MEMTX_ERROR +RH-Commit: [2/3] daabe41eefd5c519def592e374fa368e32a680d3 (jmaloy/qemu-kvm) +RH-Bugzilla: 1999236 RH-Acked-by: Stefan Hajnoczi RH-Acked-by: Peter Xu -Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2075686 +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1999236 Upstream: Merged CVE: CVE-2021-3750 diff --git a/kvm-target-i386-kvm-do-not-access-uninitialized-variable.patch b/kvm-target-i386-kvm-do-not-access-uninitialized-variable.patch new file mode 100644 index 0000000..04db85f --- /dev/null +++ b/kvm-target-i386-kvm-do-not-access-uninitialized-variable.patch @@ -0,0 +1,73 @@ +From 688c9f386635544dbc468171a32fbc84f0c9224e Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Fri, 18 Mar 2022 16:23:47 +0100 +Subject: [PATCH 12/24] target/i386: kvm: do not access uninitialized variable + on older kernels + +RH-Author: Paul Lai +RH-MergeRequest: 176: Enable KVM AMX support +RH-Commit: [12/13] 776fac1e7d1aa16ec5f4d99ddad3039eab8212af +RH-Bugzilla: 1916415 +RH-Acked-by: Cornelia Huck +RH-Acked-by: Igor Mammedov +RH-Acked-by: Paolo Bonzini + +KVM support for AMX includes a new system attribute, KVM_X86_XCOMP_GUEST_SUPP. +Commit 19db68ca68 ("x86: Grant AMX permission for guest", 2022-03-15) however +did not fully consider the behavior on older kernels. First, it warns +too aggressively. Second, it invokes the KVM_GET_DEVICE_ATTR ioctl +unconditionally and then uses the "bitmask" variable, which remains +uninitialized if the ioctl fails. Third, kvm_ioctl returns -errno rather +than -1 on errors. + +While at it, explain why the ioctl is needed and KVM_GET_SUPPORTED_CPUID +is not enough. + +Signed-off-by: Paolo Bonzini +(cherry picked from commit 3ec5ad40081b14af28496198b4d08dbe13386790) +Signed-off-by: Paul Lai +--- + target/i386/kvm/kvm.c | 17 +++++++++++++---- + 1 file changed, 13 insertions(+), 4 deletions(-) + +diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c +index b1128b0e07..bd439e56ad 100644 +--- a/target/i386/kvm/kvm.c ++++ b/target/i386/kvm/kvm.c +@@ -409,6 +409,12 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function, + } + } else if (function == 0xd && index == 0 && + (reg == R_EAX || reg == R_EDX)) { ++ /* ++ * The value returned by KVM_GET_SUPPORTED_CPUID does not include ++ * features that still have to be enabled with the arch_prctl ++ * system call. QEMU needs the full value, which is retrieved ++ * with KVM_GET_DEVICE_ATTR. ++ */ + struct kvm_device_attr attr = { + .group = 0, + .attr = KVM_X86_XCOMP_GUEST_SUPP, +@@ -417,13 +423,16 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function, + + bool sys_attr = kvm_check_extension(s, KVM_CAP_SYS_ATTRIBUTES); + if (!sys_attr) { +- warn_report("cannot get sys attribute capabilities %d", sys_attr); ++ return ret; + } + + int rc = kvm_ioctl(s, KVM_GET_DEVICE_ATTR, &attr); +- if (rc == -1 && (errno == ENXIO || errno == EINVAL)) { +- warn_report("KVM_GET_DEVICE_ATTR(0, KVM_X86_XCOMP_GUEST_SUPP) " +- "error: %d", rc); ++ if (rc < 0) { ++ if (rc != -ENXIO) { ++ warn_report("KVM_GET_DEVICE_ATTR(0, KVM_X86_XCOMP_GUEST_SUPP) " ++ "error: %d", rc); ++ } ++ return ret; + } + ret = (reg == R_EAX) ? bitmask : bitmask >> 32; + } else if (function == 0x80000001 && reg == R_ECX) { +-- +2.35.3 + diff --git a/kvm-target-i386-properly-reset-TSC-on-reset.patch b/kvm-target-i386-properly-reset-TSC-on-reset.patch index 9bb8b03..47ce2af 100644 --- a/kvm-target-i386-properly-reset-TSC-on-reset.patch +++ b/kvm-target-i386-properly-reset-TSC-on-reset.patch @@ -1,12 +1,12 @@ -From 83642c73e127b895f91dcd409c4468c953488117 Mon Sep 17 00:00:00 2001 +From 416de21d11540a927cceb533bf54ce28ffa15ad6 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 24 Mar 2022 09:21:41 +0100 -Subject: [PATCH] target/i386: properly reset TSC on reset +Subject: [PATCH 2/3] target/i386: properly reset TSC on reset RH-Author: Paolo Bonzini -RH-MergeRequest: 137: target/i386: properly reset TSC on reset -RH-Commit: [1/1] 5032ac138bf965c0536c2c9feb3dd4d4123c9f9d -RH-Bugzilla: 1975840 +RH-MergeRequest: 172: target/i386: properly reset TSC on reset +RH-Commit: [1/1] 7008bc5d02ad0a2d8b78259459d22d8f0986c989 +RH-Bugzilla: 2070417 RH-Acked-by: Marcelo Tosatti RH-Acked-by: Igor Mammedov RH-Acked-by: Vitaly Kuznetsov @@ -79,5 +79,5 @@ index 04f2b790c9..c6a6c871f1 100644 void *xsave_buf; uint32_t xsave_buf_len; -- -2.27.0 +2.35.1 diff --git a/kvm-tests-acpi-SLIC-update-expected-blobs.patch b/kvm-tests-acpi-SLIC-update-expected-blobs.patch index 7cea26a..4d5fc35 100644 --- a/kvm-tests-acpi-SLIC-update-expected-blobs.patch +++ b/kvm-tests-acpi-SLIC-update-expected-blobs.patch @@ -1,21 +1,30 @@ -From 577d4682757e8a26f2eedfc866be09dbd7d37e5b Mon Sep 17 00:00:00 2001 -From: Igor Mammedov -Date: Mon, 27 Dec 2021 14:31:20 -0500 -Subject: [PATCH 06/12] tests: acpi: SLIC: update expected blobs - -RH-Author: Igor Mammedov -RH-MergeRequest: 129: acpi: fix QEMU crash when started with SLIC table -RH-Commit: [4/10] 4bef84bbff835d39d3a07f102c650d645f18f8c8 -RH-Bugzilla: 2059311 -RH-Acked-by: Jon Maloy -RH-Acked-by: Gerd Hoffmann -RH-Acked-by: MST - -Signed-off-by: Igor Mammedov -Message-Id: <20211227193120.1084176-5-imammedo@redhat.com> -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Michael S. Tsirkin +From 0f5984bd89d481bf2494d4b3c36ef80350f44811 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Wed, 30 Mar 2022 14:52:34 -0400 +Subject: [PATCH 12/18] tests: acpi: SLIC: update expected blobs + +RH-Author: Jon Maloy +RH-MergeRequest: 141: acpi: fix QEMU crash when started with SLIC table +RH-Commit: [4/10] ca28e5c57f9eb432e5ad6b1cb7ef646a86890dd5 (jmaloy/qemu-kvm) +RH-Bugzilla: 2062611 +RH-Acked-by: Igor Mammedov + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2062611 +Upstream: Merged + +commit c8adb4d222c42951a9d0367e5f5d4e1f5e2c9ad7 +Author: Igor Mammedov +Date: Mon Dec 27 14:31:20 2021 -0500 + + tests: acpi: SLIC: update expected blobs + + Signed-off-by: Igor Mammedov + Message-Id: <20211227193120.1084176-5-imammedo@redhat.com> + Reviewed-by: Michael S. Tsirkin + Signed-off-by: Michael S. Tsirkin + (cherry picked from commit c8adb4d222c42951a9d0367e5f5d4e1f5e2c9ad7) +Signed-off-by: Jon Maloy --- tests/data/acpi/q35/FACP.slic | Bin 244 -> 244 bytes tests/data/acpi/q35/SLIC.slic | Bin 0 -> 36 bytes diff --git a/kvm-tests-acpi-add-SLIC-table-test.patch b/kvm-tests-acpi-add-SLIC-table-test.patch index fc5cd0a..9e54a7f 100644 --- a/kvm-tests-acpi-add-SLIC-table-test.patch +++ b/kvm-tests-acpi-add-SLIC-table-test.patch @@ -1,31 +1,39 @@ -From b3d5600c6bb4b2092f9f61eab0b7fc61226b888e Mon Sep 17 00:00:00 2001 -From: Igor Mammedov -Date: Mon, 27 Dec 2021 14:31:19 -0500 -Subject: [PATCH 05/12] tests: acpi: add SLIC table test +From 341715473c2a71f11a3888420a0caecf27ed4eb5 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Wed, 30 Mar 2022 14:52:34 -0400 +Subject: [PATCH 11/18] tests: acpi: add SLIC table test -RH-Author: Igor Mammedov -RH-MergeRequest: 129: acpi: fix QEMU crash when started with SLIC table -RH-Commit: [3/10] c27a8c69ef8054631a5551521b2debb67eed3c6b -RH-Bugzilla: 2059311 -RH-Acked-by: Jon Maloy -RH-Acked-by: Gerd Hoffmann -RH-Acked-by: MST +RH-Author: Jon Maloy +RH-MergeRequest: 141: acpi: fix QEMU crash when started with SLIC table +RH-Commit: [3/10] baac9b82c16a50eb4640fd7146775c9d507c7b21 (jmaloy/qemu-kvm) +RH-Bugzilla: 2062611 +RH-Acked-by: Igor Mammedov -When user uses '-acpitable' to add SLIC table, some ACPI -tables (FADT) will change its 'Oem ID'/'Oem Table ID' fields to -match that of SLIC. Test makes sure thati QEMU handles -those fields correctly when SLIC table is added with -'-acpitable' option. +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2062611 +Upstream: Merged -Conflicts: tests/qtest/bios-tables-test.c - due to missing 39d7554b2009 ("tests/acpi: add test case for VIOT") +commit 11edfabee443b149468a82b5efc88c96d1d259ec +Author: Igor Mammedov +Date: Mon Dec 27 14:31:19 2021 -0500 + + tests: acpi: add SLIC table test + + When user uses '-acpitable' to add SLIC table, some ACPI + tables (FADT) will change its 'Oem ID'/'Oem Table ID' fields to + match that of SLIC. Test makes sure thati QEMU handles + those fields correctly when SLIC table is added with + '-acpitable' option. + + Conflicts: tests/qtest/bios-tables-test.c + due to missing 39d7554b2009 ("tests/acpi: add test case for VIOT") + + Signed-off-by: Igor Mammedov + Message-Id: <20211227193120.1084176-4-imammedo@redhat.com> + Reviewed-by: Michael S. Tsirkin + Signed-off-by: Michael S. Tsirkin -Signed-off-by: Igor Mammedov -Message-Id: <20211227193120.1084176-4-imammedo@redhat.com> -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Michael S. Tsirkin (cherry picked from commit 11edfabee443b149468a82b5efc88c96d1d259ec) -Signed-off-by: Igor Mammedov +Signed-off-by: Jon Maloy --- tests/qtest/bios-tables-test.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/kvm-tests-acpi-manually-pad-OEM_ID-OEM_TABLE_ID-for-test.patch b/kvm-tests-acpi-manually-pad-OEM_ID-OEM_TABLE_ID-for-test.patch index 326ccc7..05a6838 100644 --- a/kvm-tests-acpi-manually-pad-OEM_ID-OEM_TABLE_ID-for-test.patch +++ b/kvm-tests-acpi-manually-pad-OEM_ID-OEM_TABLE_ID-for-test.patch @@ -1,31 +1,39 @@ -From 42554e549e4843f4611be3b48101985adb5f52de Mon Sep 17 00:00:00 2001 -From: Igor Mammedov -Date: Wed, 12 Jan 2022 08:03:29 -0500 -Subject: [PATCH 07/12] tests: acpi: manually pad OEM_ID/OEM_TABLE_ID for +From d94b3278c84cf7451489631d804a6b5cbd28a59d Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Wed, 30 Mar 2022 14:52:34 -0400 +Subject: [PATCH 13/18] tests: acpi: manually pad OEM_ID/OEM_TABLE_ID for test_oem_fields() test -RH-Author: Igor Mammedov -RH-MergeRequest: 129: acpi: fix QEMU crash when started with SLIC table -RH-Commit: [5/10] eabc0211172d707e50564cc43060c3c383cdcac2 -RH-Bugzilla: 2059311 -RH-Acked-by: Jon Maloy -RH-Acked-by: Gerd Hoffmann -RH-Acked-by: MST +RH-Author: Jon Maloy +RH-MergeRequest: 141: acpi: fix QEMU crash when started with SLIC table +RH-Commit: [5/10] 4ec8c738acec178c2f005f189b0c2a77a7af4088 (jmaloy/qemu-kvm) +RH-Bugzilla: 2062611 +RH-Acked-by: Igor Mammedov -The next commit will revert OEM fields padding with whitespace to -padding with '\0' as it was before [1]. As result test_oem_fields() will -fail due to unexpectedly smaller ID sizes read from QEMU ACPI tables. +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2062611 +Upstream: Merged -Pad OEM_ID/OEM_TABLE_ID manually with spaces so that values the test -puts on QEMU CLI and expected values match. +commit a849522f726767022203ef2b6c395ea19facb866 +Author: Igor Mammedov +Date: Wed Jan 12 08:03:29 2022 -0500 + + tests: acpi: manually pad OEM_ID/OEM_TABLE_ID for test_oem_fields() test + + The next commit will revert OEM fields padding with whitespace to + padding with '\0' as it was before [1]. As result test_oem_fields() will + fail due to unexpectedly smaller ID sizes read from QEMU ACPI tables. + + Pad OEM_ID/OEM_TABLE_ID manually with spaces so that values the test + puts on QEMU CLI and expected values match. + + 1) 602b458201 ("acpi: Permit OEM ID and OEM table ID fields to be changed") + Signed-off-by: Igor Mammedov + Message-Id: <20220112130332.1648664-2-imammedo@redhat.com> + Reviewed-by: Michael S. Tsirkin + Signed-off-by: Michael S. Tsirkin -1) 602b458201 ("acpi: Permit OEM ID and OEM table ID fields to be changed") -Signed-off-by: Igor Mammedov -Message-Id: <20220112130332.1648664-2-imammedo@redhat.com> -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Michael S. Tsirkin (cherry picked from commit a849522f726767022203ef2b6c395ea19facb866) -Signed-off-by: Igor Mammedov +Signed-off-by: Jon Maloy --- tests/qtest/bios-tables-test.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/kvm-tests-acpi-test-short-OEM_ID-OEM_TABLE_ID-values-in-.patch b/kvm-tests-acpi-test-short-OEM_ID-OEM_TABLE_ID-values-in-.patch index cf8c452..66d62e5 100644 --- a/kvm-tests-acpi-test-short-OEM_ID-OEM_TABLE_ID-values-in-.patch +++ b/kvm-tests-acpi-test-short-OEM_ID-OEM_TABLE_ID-values-in-.patch @@ -1,35 +1,43 @@ -From 466d5a7fca84f2932a0b3262f9c62b42d6fb300e Mon Sep 17 00:00:00 2001 -From: Igor Mammedov -Date: Fri, 14 Jan 2022 09:26:41 -0500 -Subject: [PATCH 11/12] tests: acpi: test short OEM_ID/OEM_TABLE_ID values in +From 485bf2eb8edabd4553d995d5e32224df1e510aa2 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Wed, 30 Mar 2022 14:52:34 -0400 +Subject: [PATCH 17/18] tests: acpi: test short OEM_ID/OEM_TABLE_ID values in test_oem_fields() -RH-Author: Igor Mammedov -RH-MergeRequest: 129: acpi: fix QEMU crash when started with SLIC table -RH-Commit: [9/10] 9daf8f8c63f513372f81268016885b71f5f89cf3 -RH-Bugzilla: 2059311 -RH-Acked-by: Jon Maloy -RH-Acked-by: Gerd Hoffmann -RH-Acked-by: MST +RH-Author: Jon Maloy +RH-MergeRequest: 141: acpi: fix QEMU crash when started with SLIC table +RH-Commit: [9/10] 31339223fb6c6cc32185b9fdaac76f2709b17ad6 (jmaloy/qemu-kvm) +RH-Bugzilla: 2062611 +RH-Acked-by: Igor Mammedov -Previous patch [1] added explicit whitespace padding to OEM_ID/OEM_TABLE_ID -values used in test_oem_fields() testcase to avoid false positive and -bisection issues when QEMU is switched to \0' padding. As result -testcase ceased to test values that were shorter than max possible -length values. +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2062611 +Upstream: Merged -Update testcase to make sure that it's testing shorter IDs like it -used to before [2]. +commit 408ca92634770de5eac7965ed97c6260e770f2e7 +Author: Igor Mammedov +Date: Fri Jan 14 09:26:41 2022 -0500 -1) "tests: acpi: manually pad OEM_ID/OEM_TABLE_ID for test_oem_fields() test" -2) 602b458201 ("acpi: Permit OEM ID and OEM table ID fields to be changed") + tests: acpi: test short OEM_ID/OEM_TABLE_ID values in test_oem_fields() + + Previous patch [1] added explicit whitespace padding to OEM_ID/OEM_TABLE_ID + values used in test_oem_fields() testcase to avoid false positive and + bisection issues when QEMU is switched to \0' padding. As result + testcase ceased to test values that were shorter than max possible + length values. + + Update testcase to make sure that it's testing shorter IDs like it + used to before [2]. + + 1) "tests: acpi: manually pad OEM_ID/OEM_TABLE_ID for test_oem_fields() test" + 2) 602b458201 ("acpi: Permit OEM ID and OEM table ID fields to be changed") + + Signed-off-by: Igor Mammedov + Message-Id: <20220114142641.1727679-1-imammedo@redhat.com> + Reviewed-by: Michael S. Tsirkin + Signed-off-by: Michael S. Tsirkin -Signed-off-by: Igor Mammedov -Message-Id: <20220114142641.1727679-1-imammedo@redhat.com> -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Michael S. Tsirkin (cherry picked from commit 408ca92634770de5eac7965ed97c6260e770f2e7) -Signed-off-by: Igor Mammedov +Signed-off-by: Jon Maloy --- tests/qtest/bios-tables-test.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/kvm-tests-acpi-update-expected-blobs.patch b/kvm-tests-acpi-update-expected-blobs.patch index 210f116..8f300c4 100644 --- a/kvm-tests-acpi-update-expected-blobs.patch +++ b/kvm-tests-acpi-update-expected-blobs.patch @@ -1,32 +1,40 @@ -From 6072c9986ebe95feceadcf0d75d8a6b1ed919414 Mon Sep 17 00:00:00 2001 -From: Igor Mammedov -Date: Wed, 12 Jan 2022 08:03:32 -0500 -Subject: [PATCH 10/12] tests: acpi: update expected blobs - -RH-Author: Igor Mammedov -RH-MergeRequest: 129: acpi: fix QEMU crash when started with SLIC table -RH-Commit: [8/10] a4ba098c69a8a2911143ba6e74ed3a61640e02f8 -RH-Bugzilla: 2059311 -RH-Acked-by: Jon Maloy -RH-Acked-by: Gerd Hoffmann -RH-Acked-by: MST - -Expected changes caused by previous commit: - -nvdimm ssdt (q35/pc/virt): - - * OEM Table ID "NVDIMM " - + * OEM Table ID "NVDIMM" - -SLIC test FADT (tests/data/acpi/q35/FACP.slic): - -[010h 0016 8] Oem Table ID : "ME " - +[010h 0016 8] Oem Table ID : "ME" - -Signed-off-by: Igor Mammedov -Message-Id: <20220112130332.1648664-5-imammedo@redhat.com> -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Michael S. Tsirkin +From 4785d2a77fbea681975e5c48ae6a1be49058e089 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Wed, 30 Mar 2022 14:52:34 -0400 +Subject: [PATCH 16/18] tests: acpi: update expected blobs + +RH-Author: Jon Maloy +RH-MergeRequest: 141: acpi: fix QEMU crash when started with SLIC table +RH-Commit: [8/10] e069c5de88f34393d65d32b60380865832820302 (jmaloy/qemu-kvm) +RH-Bugzilla: 2062611 +RH-Acked-by: Igor Mammedov + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2062611 +Upstream: Merged + +commit 5adc3aba875416b0e077d8a29ddd0357883746f4 +Author: Igor Mammedov +Date: Wed Jan 12 08:03:32 2022 -0500 + + tests: acpi: update expected blobs + + Expected changes caused by previous commit: + + nvdimm ssdt (q35/pc/virt): + - * OEM Table ID "NVDIMM " + + * OEM Table ID "NVDIMM" + + SLIC test FADT (tests/data/acpi/q35/FACP.slic): + -[010h 0016 8] Oem Table ID : "ME " + +[010h 0016 8] Oem Table ID : "ME" + + Signed-off-by: Igor Mammedov + Message-Id: <20220112130332.1648664-5-imammedo@redhat.com> + Reviewed-by: Michael S. Tsirkin + Signed-off-by: Michael S. Tsirkin + (cherry picked from commit 5adc3aba875416b0e077d8a29ddd0357883746f4) -Signed-off-by: Igor Mammedov +Signed-off-by: Jon Maloy --- tests/data/acpi/pc/SSDT.dimmpxm | Bin 734 -> 734 bytes tests/data/acpi/q35/FACP.slic | Bin 244 -> 244 bytes @@ -35,7 +43,6 @@ Signed-off-by: Igor Mammedov tests/qtest/bios-tables-test-allowed-diff.h | 4 ---- 5 files changed, 4 deletions(-) - diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h index 7faa8f53be..dfb8523c8b 100644 --- a/tests/qtest/bios-tables-test-allowed-diff.h diff --git a/kvm-tests-acpi-whitelist-expected-blobs-before-changing-.patch b/kvm-tests-acpi-whitelist-expected-blobs-before-changing-.patch index 2d6a6a2..4a1b350 100644 --- a/kvm-tests-acpi-whitelist-expected-blobs-before-changing-.patch +++ b/kvm-tests-acpi-whitelist-expected-blobs-before-changing-.patch @@ -1,22 +1,31 @@ -From 8ffeee963539987cada8999acb9438fab6969851 Mon Sep 17 00:00:00 2001 -From: Igor Mammedov -Date: Mon, 27 Dec 2021 14:31:18 -0500 -Subject: [PATCH 04/12] tests: acpi: whitelist expected blobs before changing +From 4e6482073df85db5982aa03ab0355e632b7157fc Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Wed, 30 Mar 2022 14:52:34 -0400 +Subject: [PATCH 10/18] tests: acpi: whitelist expected blobs before changing them -RH-Author: Igor Mammedov -RH-MergeRequest: 129: acpi: fix QEMU crash when started with SLIC table -RH-Commit: [2/10] f25d60661656d4ebc14b9baebfb15bb140651011 -RH-Bugzilla: 2059311 -RH-Acked-by: Jon Maloy -RH-Acked-by: Gerd Hoffmann -RH-Acked-by: MST - -Signed-off-by: Igor Mammedov -Message-Id: <20211227193120.1084176-3-imammedo@redhat.com> -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Michael S. Tsirkin +RH-Author: Jon Maloy +RH-MergeRequest: 141: acpi: fix QEMU crash when started with SLIC table +RH-Commit: [2/10] c664ecad30ca9c13025a63bb31ae7b80fd63e4df (jmaloy/qemu-kvm) +RH-Bugzilla: 2062611 +RH-Acked-by: Igor Mammedov + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2062611 +Upstream: Merged + +commit e71f6ab9d93a7d01e833647e7010c1079c4cef30 +Author: Igor Mammedov +Date: Mon Dec 27 14:31:18 2021 -0500 + + tests: acpi: whitelist expected blobs before changing them + + Signed-off-by: Igor Mammedov + Message-Id: <20211227193120.1084176-3-imammedo@redhat.com> + Reviewed-by: Michael S. Tsirkin + Signed-off-by: Michael S. Tsirkin + (cherry picked from commit e71f6ab9d93a7d01e833647e7010c1079c4cef30) +Signed-off-by: Jon Maloy --- tests/data/acpi/q35/FACP.slic | Bin 0 -> 244 bytes tests/data/acpi/q35/SLIC.slic | 0 @@ -25,8 +34,6 @@ Signed-off-by: Michael S. Tsirkin create mode 100644 tests/data/acpi/q35/FACP.slic create mode 100644 tests/data/acpi/q35/SLIC.slic - - diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h index dfb8523c8b..49dbf8fa3e 100644 --- a/tests/qtest/bios-tables-test-allowed-diff.h diff --git a/kvm-tests-acpi-whitelist-nvdimm-s-SSDT-and-FACP.slic-exp.patch b/kvm-tests-acpi-whitelist-nvdimm-s-SSDT-and-FACP.slic-exp.patch index 4d05044..30289c7 100644 --- a/kvm-tests-acpi-whitelist-nvdimm-s-SSDT-and-FACP.slic-exp.patch +++ b/kvm-tests-acpi-whitelist-nvdimm-s-SSDT-and-FACP.slic-exp.patch @@ -1,35 +1,43 @@ -From 12fc404b1ecf76e69c309b65ead86298a2606051 Mon Sep 17 00:00:00 2001 -From: Igor Mammedov -Date: Wed, 12 Jan 2022 08:03:30 -0500 -Subject: [PATCH 08/12] tests: acpi: whitelist nvdimm's SSDT and FACP.slic +From a132a22e316121cf00ff733afb1ad1dc313e14b3 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Wed, 30 Mar 2022 14:52:34 -0400 +Subject: [PATCH 14/18] tests: acpi: whitelist nvdimm's SSDT and FACP.slic expected blobs -RH-Author: Igor Mammedov -RH-MergeRequest: 129: acpi: fix QEMU crash when started with SLIC table -RH-Commit: [6/10] 2e82d4c0184d499f449dc24a8bd6991273ad2db9 -RH-Bugzilla: 2059311 -RH-Acked-by: Jon Maloy -RH-Acked-by: Gerd Hoffmann -RH-Acked-by: MST - -The next commit will revert OEM fields whitespace padding to -padding with '\0' as it was before [1]. That will change OEM -Table ID for: - * SSDT.*: where it was padded from 6 characters to 8 - * FACP.slic: where it was padded from 2 characters to 8 -after reverting whitespace padding, it will be replaced with -'\0' which effectively will shorten OEM table ID to 6 and 2 -characters. - -Whitelist affected tables before introducing the change. - -1) 602b458201 ("acpi: Permit OEM ID and OEM table ID fields to be changed") -Signed-off-by: Igor Mammedov -Message-Id: <20220112130332.1648664-3-imammedo@redhat.com> -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Michael S. Tsirkin +RH-Author: Jon Maloy +RH-MergeRequest: 141: acpi: fix QEMU crash when started with SLIC table +RH-Commit: [6/10] 3f3a929cde82f228da1e4bc66e4c869467c0289c (jmaloy/qemu-kvm) +RH-Bugzilla: 2062611 +RH-Acked-by: Igor Mammedov + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2062611 +Upstream: Merged + +commit d1e4a4654154925eddf0fc449fa9c92b806b9c8c +Author: Igor Mammedov +Date: Wed Jan 12 08:03:30 2022 -0500 + + tests: acpi: whitelist nvdimm's SSDT and FACP.slic expected blobs + + The next commit will revert OEM fields whitespace padding to + padding with '\0' as it was before [1]. That will change OEM + Table ID for: + * SSDT.*: where it was padded from 6 characters to 8 + * FACP.slic: where it was padded from 2 characters to 8 + after reverting whitespace padding, it will be replaced with + '\0' which effectively will shorten OEM table ID to 6 and 2 + characters. + + Whitelist affected tables before introducing the change. + + 1) 602b458201 ("acpi: Permit OEM ID and OEM table ID fields to be changed") + Signed-off-by: Igor Mammedov + Message-Id: <20220112130332.1648664-3-imammedo@redhat.com> + Reviewed-by: Michael S. Tsirkin + Signed-off-by: Michael S. Tsirkin + (cherry picked from commit d1e4a4654154925eddf0fc449fa9c92b806b9c8c) -Signed-off-by: Igor Mammedov +Signed-off-by: Jon Maloy --- tests/qtest/bios-tables-test-allowed-diff.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/kvm-tests-qtest-fdc-test-Add-a-regression-test-for-CVE-2.patch b/kvm-tests-qtest-fdc-test-Add-a-regression-test-for-CVE-2.patch new file mode 100644 index 0000000..4c04458 --- /dev/null +++ b/kvm-tests-qtest-fdc-test-Add-a-regression-test-for-CVE-2.patch @@ -0,0 +1,120 @@ +From 24af433728429578e586d179e27451b7d4a46cba Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Thu, 18 Nov 2021 12:57:33 +0100 +Subject: [PATCH 3/3] tests/qtest/fdc-test: Add a regression test for + CVE-2021-3507 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Jon Maloy +RH-MergeRequest: 194: hw/block/fdc: Prevent end-of-track overrun (CVE-2021-3507) +RH-Commit: [2/2] 31ec71276b521b06d4142fffa88a3fa4d1494d92 (jmaloy/qemu-kvm) +RH-Bugzilla: 1951521 +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Thomas Huth +RH-Acked-by: Hanna Reitz + +Add the reproducer from https://gitlab.com/qemu-project/qemu/-/issues/339 + +Without the previous commit, when running 'make check-qtest-i386' +with QEMU configured with '--enable-sanitizers' we get: + + ==4028352==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x619000062a00 at pc 0x5626d03c491a bp 0x7ffdb4199410 sp 0x7ffdb4198bc0 + READ of size 786432 at 0x619000062a00 thread T0 + #0 0x5626d03c4919 in __asan_memcpy (qemu-system-i386+0x1e65919) + #1 0x5626d1c023cc in flatview_write_continue softmmu/physmem.c:2787:13 + #2 0x5626d1bf0c0f in flatview_write softmmu/physmem.c:2822:14 + #3 0x5626d1bf0798 in address_space_write softmmu/physmem.c:2914:18 + #4 0x5626d1bf0f37 in address_space_rw softmmu/physmem.c:2924:16 + #5 0x5626d1bf14c8 in cpu_physical_memory_rw softmmu/physmem.c:2933:5 + #6 0x5626d0bd5649 in cpu_physical_memory_write include/exec/cpu-common.h:82:5 + #7 0x5626d0bd0a07 in i8257_dma_write_memory hw/dma/i8257.c:452:9 + #8 0x5626d09f825d in fdctrl_transfer_handler hw/block/fdc.c:1616:13 + #9 0x5626d0a048b4 in fdctrl_start_transfer hw/block/fdc.c:1539:13 + #10 0x5626d09f4c3e in fdctrl_write_data hw/block/fdc.c:2266:13 + #11 0x5626d09f22f7 in fdctrl_write hw/block/fdc.c:829:9 + #12 0x5626d1c20bc5 in portio_write softmmu/ioport.c:207:17 + + 0x619000062a00 is located 0 bytes to the right of 512-byte region [0x619000062800,0x619000062a00) + allocated by thread T0 here: + #0 0x5626d03c66ec in posix_memalign (qemu-system-i386+0x1e676ec) + #1 0x5626d2b988d4 in qemu_try_memalign util/oslib-posix.c:210:11 + #2 0x5626d2b98b0c in qemu_memalign util/oslib-posix.c:226:27 + #3 0x5626d09fbaf0 in fdctrl_realize_common hw/block/fdc.c:2341:20 + #4 0x5626d0a150ed in isabus_fdc_realize hw/block/fdc-isa.c:113:5 + #5 0x5626d2367935 in device_set_realized hw/core/qdev.c:531:13 + + SUMMARY: AddressSanitizer: heap-buffer-overflow (qemu-system-i386+0x1e65919) in __asan_memcpy + Shadow bytes around the buggy address: + 0x0c32800044f0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa + 0x0c3280004500: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x0c3280004510: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x0c3280004520: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x0c3280004530: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + =>0x0c3280004540:[fa]fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa + 0x0c3280004550: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa + 0x0c3280004560: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa + 0x0c3280004570: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa + 0x0c3280004580: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa + 0x0c3280004590: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd + Shadow byte legend (one shadow byte represents 8 application bytes): + Addressable: 00 + Heap left redzone: fa + Freed heap region: fd + ==4028352==ABORTING + +[ kwolf: Added snapshot=on to prevent write file lock failure ] + +Reported-by: Alexander Bulekov +Signed-off-by: Philippe Mathieu-Daudé +Reviewed-by: Alexander Bulekov +Signed-off-by: Kevin Wolf +(cherry picked from commit 46609b90d9e3a6304def11038a76b58ff43f77bc) +Signed-off-by: Jon Maloy +--- + tests/qtest/fdc-test.c | 21 +++++++++++++++++++++ + 1 file changed, 21 insertions(+) + +diff --git a/tests/qtest/fdc-test.c b/tests/qtest/fdc-test.c +index 8f6eee84a4..6f5850354f 100644 +--- a/tests/qtest/fdc-test.c ++++ b/tests/qtest/fdc-test.c +@@ -583,6 +583,26 @@ static void test_cve_2021_20196(void) + qtest_quit(s); + } + ++static void test_cve_2021_3507(void) ++{ ++ QTestState *s; ++ ++ s = qtest_initf("-nographic -m 32M -nodefaults " ++ "-drive file=%s,format=raw,if=floppy,snapshot=on", ++ test_image); ++ qtest_outl(s, 0x9, 0x0a0206); ++ qtest_outw(s, 0x3f4, 0x1600); ++ qtest_outw(s, 0x3f4, 0x0000); ++ qtest_outw(s, 0x3f4, 0x0000); ++ qtest_outw(s, 0x3f4, 0x0000); ++ qtest_outw(s, 0x3f4, 0x0200); ++ qtest_outw(s, 0x3f4, 0x0200); ++ qtest_outw(s, 0x3f4, 0x0000); ++ qtest_outw(s, 0x3f4, 0x0000); ++ qtest_outw(s, 0x3f4, 0x0000); ++ qtest_quit(s); ++} ++ + int main(int argc, char **argv) + { + int fd; +@@ -614,6 +634,7 @@ int main(int argc, char **argv) + qtest_add_func("/fdc/read_no_dma_19", test_read_no_dma_19); + qtest_add_func("/fdc/fuzz-registers", fuzz_registers); + qtest_add_func("/fdc/fuzz/cve_2021_20196", test_cve_2021_20196); ++ qtest_add_func("/fdc/fuzz/cve_2021_3507", test_cve_2021_3507); + + ret = g_test_run(); + +-- +2.35.3 + diff --git a/kvm-ui-cursor-fix-integer-overflow-in-cursor_alloc-CVE-2.patch b/kvm-ui-cursor-fix-integer-overflow-in-cursor_alloc-CVE-2.patch index cdff4fb..813d0ca 100644 --- a/kvm-ui-cursor-fix-integer-overflow-in-cursor_alloc-CVE-2.patch +++ b/kvm-ui-cursor-fix-integer-overflow-in-cursor_alloc-CVE-2.patch @@ -1,21 +1,21 @@ -From 0a493615833edbe6448bc639200b4a5fa7d492e3 Mon Sep 17 00:00:00 2001 +From 87a318f0b8758f940a316831a77b6ebebca42b19 Mon Sep 17 00:00:00 2001 From: Jon Maloy Date: Wed, 4 May 2022 10:35:17 -0400 -Subject: [PATCH 2/2] ui/cursor: fix integer overflow in cursor_alloc +Subject: [PATCH 3/3] ui/cursor: fix integer overflow in cursor_alloc (CVE-2021-4206) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RH-Author: Jon Maloy -RH-MergeRequest: 190: ui/cursor: fix integer overflow in cursor_alloc (CVE-2021-4206) -RH-Commit: [1/1] 80588f646942c345a2491812cb41aacd4c0805ff (jmaloy/qemu-kvm) -RH-Bugzilla: 2082622 -RH-Acked-by: Miroslav Rezanina -RH-Acked-by: Marc-André Lureau +RH-MergeRequest: 180: ui/cursor: fix integer overflow in cursor_alloc (CVE-2021-4206) +RH-Commit: [1/1] 7ad711347bc6248dc5aefa45401ca74448dee5e5 (jmaloy/qemu-kvm) +RH-Bugzilla: 2040734 +RH-Acked-by: Dr. David Alan Gilbert RH-Acked-by: Mauro Matteo Cascella +RH-Acked-by: Gerd Hoffmann -BZ: https://bugzilla.redhat.com/show_bug.cgi?id=2082622 +BZ: https://bugzilla.redhat.com/show_bug.cgi?id=2040734 Upstream: Merged CVE: CVE-2021-4206 @@ -101,5 +101,5 @@ index 1d62ddd4d0..835f0802f9 100644 c = g_malloc0(sizeof(QEMUCursor) + datasize); c->width = width; -- -2.35.3 +2.35.1 diff --git a/kvm-vhost-net-fix-improper-cleanup-in-vhost_net_start.patch b/kvm-vhost-net-fix-improper-cleanup-in-vhost_net_start.patch index e736ac4..c3dbcf9 100644 --- a/kvm-vhost-net-fix-improper-cleanup-in-vhost_net_start.patch +++ b/kvm-vhost-net-fix-improper-cleanup-in-vhost_net_start.patch @@ -1,18 +1,18 @@ -From 2206114457f3c575b2cf148ff643f78d5e67e8d2 Mon Sep 17 00:00:00 2001 +From 9a62319b973ec33f9ccbeeae7f2f3b4b31db0c26 Mon Sep 17 00:00:00 2001 From: Si-Wei Liu Date: Fri, 6 May 2022 19:28:15 -0700 -Subject: [PATCH 4/7] vhost-net: fix improper cleanup in vhost_net_start +Subject: [PATCH 17/24] vhost-net: fix improper cleanup in vhost_net_start MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit -RH-Author: Cindy Lu -RH-MergeRequest: 203: vdpa :sync the Multiqueue fixes for vhost-vDPA -RH-Commit: [4/7] b09e0785b6e1c46da3ff59a8e4f4dea7d86e4f0b -RH-Bugzilla: 2095794 -RH-Acked-by: MST +RH-Author: Jason Wang +RH-MergeRequest: 187: Multiqueue fixes for vhost-vDPA +RH-Commit: [4/7] bebe7990a12e901fbb84e5e4b7a62744d75c9d9e +RH-Bugzilla: 2069946 RH-Acked-by: Eugenio Pérez -RH-Acked-by: Jason Wang +RH-Acked-by: Cindy Lu +RH-Acked-by: Laurent Vivier vhost_net_start() missed a corresponding stop_one() upon error from vhost_set_vring_enable(). While at it, make the error handling for @@ -24,7 +24,7 @@ Message-Id: <1651890498-24478-5-git-send-email-si-wei.liu@oracle.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin (cherry picked from commit 6f3910b5eee00b8cc959e94659c0d524c482a418) -Signed-off-by: Cindy Lu +Signed-off-by: Jason Wang --- hw/net/vhost_net.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) @@ -52,5 +52,5 @@ index 30379d2ca4..d6d7c51f62 100644 } e = k->set_guest_notifiers(qbus->parent, total_notifiers, false); -- -2.31.1 +2.35.3 diff --git a/kvm-vhost-vdpa-backend-feature-should-set-only-once.patch b/kvm-vhost-vdpa-backend-feature-should-set-only-once.patch index b4e1fd6..ef700fd 100644 --- a/kvm-vhost-vdpa-backend-feature-should-set-only-once.patch +++ b/kvm-vhost-vdpa-backend-feature-should-set-only-once.patch @@ -1,18 +1,18 @@ -From 975046c44909eef91e8b3cfafe1c0dd55151937b Mon Sep 17 00:00:00 2001 +From 01270bb66a4f7897a4fd06ba248eeeb41dc47571 Mon Sep 17 00:00:00 2001 From: Si-Wei Liu Date: Fri, 6 May 2022 19:28:16 -0700 -Subject: [PATCH 5/7] vhost-vdpa: backend feature should set only once +Subject: [PATCH 18/24] vhost-vdpa: backend feature should set only once MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit -RH-Author: Cindy Lu -RH-MergeRequest: 203: vdpa :sync the Multiqueue fixes for vhost-vDPA -RH-Commit: [5/7] 8db716cb0cec794861c7a63c0b33ab7f8367232d -RH-Bugzilla: 2095794 -RH-Acked-by: MST +RH-Author: Jason Wang +RH-MergeRequest: 187: Multiqueue fixes for vhost-vDPA +RH-Commit: [5/7] 0ab13542cf25c129dc403db95c7db12cdb012744 +RH-Bugzilla: 2069946 RH-Acked-by: Eugenio Pérez -RH-Acked-by: Jason Wang +RH-Acked-by: Cindy Lu +RH-Acked-by: Laurent Vivier The vhost_vdpa_one_time_request() branch in vhost_vdpa_set_backend_cap() incorrectly sends down @@ -35,7 +35,7 @@ Message-Id: <1651890498-24478-6-git-send-email-si-wei.liu@oracle.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin (cherry picked from commit 6aee7e4233f6467f69531fcd352adff028f3f5ea) -Signed-off-by: Cindy Lu +Signed-off-by: Jason Wang --- hw/virtio/vhost-vdpa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) @@ -54,5 +54,5 @@ index 78da48a333..a9be24776a 100644 if (r) { return -EFAULT; -- -2.31.1 +2.35.3 diff --git a/kvm-vhost-vdpa-change-name-and-polarity-for-vhost_vdpa_o.patch b/kvm-vhost-vdpa-change-name-and-polarity-for-vhost_vdpa_o.patch index 9912a5f..bbc1c85 100644 --- a/kvm-vhost-vdpa-change-name-and-polarity-for-vhost_vdpa_o.patch +++ b/kvm-vhost-vdpa-change-name-and-polarity-for-vhost_vdpa_o.patch @@ -1,19 +1,19 @@ -From 073595e503c4f13a7e598bdb83b2ea724d169cbf Mon Sep 17 00:00:00 2001 +From c8cb46fa93a3ccad6f3e183045b270f28eed7b12 Mon Sep 17 00:00:00 2001 From: Si-Wei Liu Date: Fri, 6 May 2022 19:28:17 -0700 -Subject: [PATCH 6/7] vhost-vdpa: change name and polarity for +Subject: [PATCH 19/24] vhost-vdpa: change name and polarity for vhost_vdpa_one_time_request() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit -RH-Author: Cindy Lu -RH-MergeRequest: 203: vdpa :sync the Multiqueue fixes for vhost-vDPA -RH-Commit: [6/7] 9ab7ee150e1876a170b56db36e94a5b3bbf09535 -RH-Bugzilla: 2095794 -RH-Acked-by: MST +RH-Author: Jason Wang +RH-MergeRequest: 187: Multiqueue fixes for vhost-vDPA +RH-Commit: [6/7] 727ab0bb813f073e8cd2f7e68a9acda60c2cb33d +RH-Bugzilla: 2069946 RH-Acked-by: Eugenio Pérez -RH-Acked-by: Jason Wang +RH-Acked-by: Cindy Lu +RH-Acked-by: Laurent Vivier The name vhost_vdpa_one_time_request() was confusing. No matter whatever it returns, its typical occurrence had @@ -27,6 +27,9 @@ This call is applicable to request which performs operation only once, before queues are set up, and usually at the beginning of the caller function. Document the requirement for it in place. +Conflicts: hw/virtio/vhost-vdpa.c since we don't have shadow virtqueue +suport. + Signed-off-by: Si-Wei Liu Message-Id: <1651890498-24478-7-git-send-email-si-wei.liu@oracle.com> Reviewed-by: Michael S. Tsirkin @@ -34,7 +37,7 @@ Signed-off-by: Michael S. Tsirkin Reviewed-by: Stefano Garzarella Acked-by: Jason Wang (cherry picked from commit d71b0609fc04217e28d17009f04d74b08be6f466) -Signed-off-by: Cindy Lu +Signed-off-by: Jason Wang --- hw/virtio/vhost-vdpa.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) @@ -119,5 +122,5 @@ index a9be24776a..38bbcb3c18 100644 } -- -2.31.1 +2.35.3 diff --git a/kvm-vhost-vdpa-fix-improper-cleanup-in-net_init_vhost_vd.patch b/kvm-vhost-vdpa-fix-improper-cleanup-in-net_init_vhost_vd.patch index f258121..68c7d5f 100644 --- a/kvm-vhost-vdpa-fix-improper-cleanup-in-net_init_vhost_vd.patch +++ b/kvm-vhost-vdpa-fix-improper-cleanup-in-net_init_vhost_vd.patch @@ -1,18 +1,18 @@ -From 004f7409312c45f17eaaceac697637d3da257964 Mon Sep 17 00:00:00 2001 +From c10ef6f79d4a4c8ccc5901b25234501c621e4e04 Mon Sep 17 00:00:00 2001 From: Si-Wei Liu Date: Fri, 6 May 2022 19:28:14 -0700 -Subject: [PATCH 3/7] vhost-vdpa: fix improper cleanup in net_init_vhost_vdpa +Subject: [PATCH 16/24] vhost-vdpa: fix improper cleanup in net_init_vhost_vdpa MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit -RH-Author: Cindy Lu -RH-MergeRequest: 203: vdpa :sync the Multiqueue fixes for vhost-vDPA -RH-Commit: [3/7] 5f5e7577818744305f811667461e530acd9977d1 -RH-Bugzilla: 2095794 -RH-Acked-by: MST +RH-Author: Jason Wang +RH-MergeRequest: 187: Multiqueue fixes for vhost-vDPA +RH-Commit: [3/7] b3b658dcb4695defe1fdb199570fb984291e8e21 +RH-Bugzilla: 2069946 RH-Acked-by: Eugenio Pérez -RH-Acked-by: Jason Wang +RH-Acked-by: Cindy Lu +RH-Acked-by: Laurent Vivier ... such that no memory leaks on dangling net clients in case of error. @@ -23,7 +23,7 @@ Message-Id: <1651890498-24478-4-git-send-email-si-wei.liu@oracle.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin (cherry picked from commit 9bd055073e375c8a0d7ebce925e05d914d69fc7f) -Signed-off-by: Cindy Lu +Signed-off-by: Jason Wang --- net/vhost-vdpa.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) @@ -44,5 +44,5 @@ index 25dd6dd975..814f704687 100644 qemu_close(vdpa_device_fd); g_free(ncs); -- -2.31.1 +2.35.3 diff --git a/kvm-vhost-vsock-detach-the-virqueue-element-in-case-of-e.patch b/kvm-vhost-vsock-detach-the-virqueue-element-in-case-of-e.patch index 9378e84..50013c9 100644 --- a/kvm-vhost-vsock-detach-the-virqueue-element-in-case-of-e.patch +++ b/kvm-vhost-vsock-detach-the-virqueue-element-in-case-of-e.patch @@ -1,18 +1,16 @@ -From 2abf617accf878bec7f1c0419d5b85c93b0aa426 Mon Sep 17 00:00:00 2001 +From ff4e95d8652dadfed09913c7968514a2a7f36591 Mon Sep 17 00:00:00 2001 From: Jon Maloy Date: Thu, 14 Apr 2022 10:38:26 -0400 -Subject: [PATCH 07/11] vhost-vsock: detach the virqueue element in case of - error +Subject: [PATCH 2/2] vhost-vsock: detach the virqueue element in case of error RH-Author: Jon Maloy -RH-MergeRequest: 168: vhost-vsock: detach the virqueue element in case of error -RH-Commit: [1/1] f81a39d26a7165f8b717fdeeb9526081cb73129b (jmaloy/qemu-kvm) -RH-Bugzilla: 2075639 -RH-Acked-by: Stefano Garzarella -RH-Acked-by: Jason Wang +RH-MergeRequest: 153: vhost-vsock: detach the virqueue element in case of error +RH-Commit: [1/1] 024dbc9073fddbe89a8ae8eb201f5bc674bffb64 (jmaloy/qemu-kvm) +RH-Bugzilla: 2063262 RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Stefano Garzarella -Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2075639 +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2063262 Upstream: Merged CVE: CVE-2022-26354 diff --git a/kvm-virtio-gpu-do-not-byteswap-padding.patch b/kvm-virtio-gpu-do-not-byteswap-padding.patch new file mode 100644 index 0000000..dc723bd --- /dev/null +++ b/kvm-virtio-gpu-do-not-byteswap-padding.patch @@ -0,0 +1,48 @@ +From e118a451dc1ed68f1371a5d8e042120542be6d31 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Thu, 11 Nov 2021 12:06:00 +0100 +Subject: [PATCH 01/24] virtio-gpu: do not byteswap padding +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Paul Lai +RH-MergeRequest: 176: Enable KVM AMX support +RH-Commit: [1/13] 12714f53820b7632e7fc0a8a3bf8eb4a64f41750 +RH-Bugzilla: 1916415 +RH-Acked-by: Cornelia Huck +RH-Acked-by: Igor Mammedov +RH-Acked-by: Paolo Bonzini + +In Linux 5.16, the padding of struct virtio_gpu_ctrl_hdr has become a +single-byte field followed by a uint8_t[3] array of padding bytes, +and virtio_gpu_ctrl_hdr_bswap does not compile anymore. + +Signed-off-by: Paolo Bonzini +Acked-by: Cornelia Huck +Reviewed-by: Alex Bennée +Reviewed-by: Michael S. Tsirkin +Reviewed-by: Philippe Mathieu-Daudé +Message-Id: <20211111110604.207376-2-pbonzini@redhat.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit a4663f1a5506626175fc64c86e52135587c36872) +Signed-off-by: Paul Lai +--- + include/hw/virtio/virtio-gpu-bswap.h | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/include/hw/virtio/virtio-gpu-bswap.h b/include/hw/virtio/virtio-gpu-bswap.h +index e2bee8f595..5faac0d8d5 100644 +--- a/include/hw/virtio/virtio-gpu-bswap.h ++++ b/include/hw/virtio/virtio-gpu-bswap.h +@@ -24,7 +24,6 @@ virtio_gpu_ctrl_hdr_bswap(struct virtio_gpu_ctrl_hdr *hdr) + le32_to_cpus(&hdr->flags); + le64_to_cpus(&hdr->fence_id); + le32_to_cpus(&hdr->ctx_id); +- le32_to_cpus(&hdr->padding); + } + + static inline void +-- +2.35.3 + diff --git a/kvm-virtio-net-align-ctrl_vq-index-for-non-mq-guest-for-.patch b/kvm-virtio-net-align-ctrl_vq-index-for-non-mq-guest-for-.patch index d454622..f23f38c 100644 --- a/kvm-virtio-net-align-ctrl_vq-index-for-non-mq-guest-for-.patch +++ b/kvm-virtio-net-align-ctrl_vq-index-for-non-mq-guest-for-.patch @@ -1,19 +1,19 @@ -From e1ff655fb1ca5812d0456e2054a5a9ab755d399b Mon Sep 17 00:00:00 2001 +From 39cdd781c885b0695f8830a33420caa9e9b0bd50 Mon Sep 17 00:00:00 2001 From: Si-Wei Liu Date: Fri, 6 May 2022 19:28:13 -0700 -Subject: [PATCH 2/7] virtio-net: align ctrl_vq index for non-mq guest for +Subject: [PATCH 15/24] virtio-net: align ctrl_vq index for non-mq guest for vhost_vdpa MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit -RH-Author: Cindy Lu -RH-MergeRequest: 203: vdpa :sync the Multiqueue fixes for vhost-vDPA -RH-Commit: [2/7] bc60c58d6e36ea0698a72d806ac930e5cca199c7 -RH-Bugzilla: 2095794 -RH-Acked-by: MST +RH-Author: Jason Wang +RH-MergeRequest: 187: Multiqueue fixes for vhost-vDPA +RH-Commit: [2/7] 2647cf59f3dd1e3d8af2d12c01e06ae26fbc1dc2 +RH-Bugzilla: 2069946 RH-Acked-by: Eugenio Pérez -RH-Acked-by: Jason Wang +RH-Acked-by: Cindy Lu +RH-Acked-by: Laurent Vivier With MQ enabled vdpa device and non-MQ supporting guest e.g. booting vdpa with mq=on over OVMF of single vqp, below assert @@ -73,7 +73,7 @@ Message-Id: <1651890498-24478-3-git-send-email-si-wei.liu@oracle.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin (cherry picked from commit 68b0a6395f36a8f48f56f46d05f30be2067598b0) -Signed-off-by: Cindy Lu +Signed-off-by: Jason Wang --- hw/net/virtio-net.c | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) @@ -139,5 +139,5 @@ index ec045c3f41..f118379bb4 100644 vdev, idx, mask); } -- -2.31.1 +2.35.3 diff --git a/kvm-virtio-net-don-t-handle-mq-request-in-userspace-hand.patch b/kvm-virtio-net-don-t-handle-mq-request-in-userspace-hand.patch index 42d8939..25c1aa9 100644 --- a/kvm-virtio-net-don-t-handle-mq-request-in-userspace-hand.patch +++ b/kvm-virtio-net-don-t-handle-mq-request-in-userspace-hand.patch @@ -1,19 +1,19 @@ -From 3cd90463553c2e0915940b17d9955b4b0cf5ed11 Mon Sep 17 00:00:00 2001 +From c9b51d54530c526f14ca0f3b9fc0bfa0b60d45ee Mon Sep 17 00:00:00 2001 From: Si-Wei Liu Date: Fri, 6 May 2022 19:28:18 -0700 -Subject: [PATCH 7/7] virtio-net: don't handle mq request in userspace handler - for vhost-vdpa +Subject: [PATCH 20/24] virtio-net: don't handle mq request in userspace + handler for vhost-vdpa MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit -RH-Author: Cindy Lu -RH-MergeRequest: 203: vdpa :sync the Multiqueue fixes for vhost-vDPA -RH-Commit: [7/7] fc6f4e145f2d6abf96e75dd0d76ed04660a1f20a -RH-Bugzilla: 2095794 -RH-Acked-by: MST +RH-Author: Jason Wang +RH-MergeRequest: 187: Multiqueue fixes for vhost-vDPA +RH-Commit: [7/7] 0e6684d12e42752deae8f5ebc56456fed174e0ed +RH-Bugzilla: 2069946 RH-Acked-by: Eugenio Pérez -RH-Acked-by: Jason Wang +RH-Acked-by: Cindy Lu +RH-Acked-by: Laurent Vivier virtio_queue_host_notifier_read() tends to read pending event left behind on ioeventfd in the vhost_net_stop() path, and @@ -68,7 +68,7 @@ Message-Id: <1651890498-24478-8-git-send-email-si-wei.liu@oracle.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin (cherry picked from commit 2a7888cc3aa31faee839fa5dddad354ff8941f4c) -Signed-off-by: Cindy Lu +Signed-off-by: Jason Wang --- hw/net/virtio-net.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) @@ -105,5 +105,5 @@ index f118379bb4..7e172ef829 100644 /* stop the backend before changing the number of queue_pairs to avoid handling a * disabled queue */ -- -2.31.1 +2.35.3 diff --git a/kvm-virtio-net-fix-map-leaking-on-error-during-receive.patch b/kvm-virtio-net-fix-map-leaking-on-error-during-receive.patch index 494365a..4855e59 100644 --- a/kvm-virtio-net-fix-map-leaking-on-error-during-receive.patch +++ b/kvm-virtio-net-fix-map-leaking-on-error-during-receive.patch @@ -1,20 +1,17 @@ -From ba9806fd38f113deb452156fdc644407f061311c Mon Sep 17 00:00:00 2001 +From 10b3a7b56dc9b4c88e503c36c1b13d80bcb7b066 Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Tue, 8 Mar 2022 10:42:51 +0800 -Subject: [PATCH 06/11] virtio-net: fix map leaking on error during receive -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit +Subject: [PATCH 2/6] virtio-net: fix map leaking on error during receive RH-Author: Jon Maloy -RH-MergeRequest: 165: virtio-net: fix map leaking on error during receive -RH-Commit: [1/1] f0546c74a5bfd37de473703f6a7c6f8f29fb0831 (jmaloy/qemu-kvm) -RH-Bugzilla: 2075637 -RH-Acked-by: Mauro Matteo Cascella -RH-Acked-by: Marc-André Lureau -RH-Acked-by: Gerd Hoffmann - -Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2075637 +RH-MergeRequest: 154: virtio-net: fix map leaking on error during receive +RH-Commit: [1/1] 7178b0cd5ce7c89fe476f2e199c9212c8b89327a (jmaloy/qemu-kvm) +RH-Bugzilla: 2063206 +RH-Acked-by: Jason Wang +RH-Acked-by: Kevin Wolf +RH-Acked-by: Laurent Vivier + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2063206 Upstream: Merged CVE: CVE-2022-26353 diff --git a/kvm-virtio-net-setup-vhost_dev-and-notifiers-for-cvq-onl.patch b/kvm-virtio-net-setup-vhost_dev-and-notifiers-for-cvq-onl.patch index 12b119f..2e46cff 100644 --- a/kvm-virtio-net-setup-vhost_dev-and-notifiers-for-cvq-onl.patch +++ b/kvm-virtio-net-setup-vhost_dev-and-notifiers-for-cvq-onl.patch @@ -1,19 +1,19 @@ -From 60224ca528f32d3f8e7a5ec65c1851c9b698dfb6 Mon Sep 17 00:00:00 2001 +From bc307149fe4e3fe2a3e0ac52534383c955051e7e Mon Sep 17 00:00:00 2001 From: Si-Wei Liu Date: Fri, 6 May 2022 19:28:12 -0700 -Subject: [PATCH 1/7] virtio-net: setup vhost_dev and notifiers for cvq only +Subject: [PATCH 14/24] virtio-net: setup vhost_dev and notifiers for cvq only when feature is negotiated MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit -RH-Author: Cindy Lu -RH-MergeRequest: 203: vdpa :sync the Multiqueue fixes for vhost-vDPA -RH-Commit: [1/7] fe2e27958344b5d5089b383f36c5d9e08472a591 -RH-Bugzilla: 2095794 -RH-Acked-by: MST +RH-Author: Jason Wang +RH-MergeRequest: 187: Multiqueue fixes for vhost-vDPA +RH-Commit: [1/7] 38bcfaa661f437b3dfa6b6f152dffd60073dc054 +RH-Bugzilla: 2069946 RH-Acked-by: Eugenio Pérez -RH-Acked-by: Jason Wang +RH-Acked-by: Cindy Lu +RH-Acked-by: Laurent Vivier When the control virtqueue feature is absent or not negotiated, vhost_net_start() still tries to set up vhost_dev and install @@ -28,7 +28,7 @@ Message-Id: <1651890498-24478-2-git-send-email-si-wei.liu@oracle.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin (cherry picked from commit aa8581945a13712ff3eed0ad3ba7a9664fc1604b) -Signed-off-by: Cindy Lu +Signed-off-by: Jason Wang --- hw/net/virtio-net.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) @@ -48,5 +48,5 @@ index e1f4748831..ec045c3f41 100644 if (!get_vhost_net(nc->peer)) { return; -- -2.31.1 +2.35.3 diff --git a/kvm-virtiofsd-Adjust-limit-for-minor-version.patch b/kvm-virtiofsd-Adjust-limit-for-minor-version.patch deleted file mode 100644 index 30ec553..0000000 --- a/kvm-virtiofsd-Adjust-limit-for-minor-version.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 3b7200134925fcf5ae99b5c3b34465456d3bc002 Mon Sep 17 00:00:00 2001 -From: Jacob Wang -Date: Mon, 2 Aug 2021 01:16:05 +0800 -Subject: [PATCH 1/1] virtiofsd: Adjust limit for minor version - -Upstream virtiofsd only supports fuse >= 7.31 -(https://github.com/qemu/qemu/commit/72c42e2d65510e073cf78fdc924d121c77fa0080), -while Cloud Kernel has fuse version 7.27, which causes virtiofs fails to run -due to version mismatch. This limitation is unnecessary in Cloud Kernel because -we have already backported mandatory fuse patches to support virtofs -frontend in Kernel. Hence, adjust the minor version limit to 7.27 to -suppress the limitation. - -Note that current fuse implementation in Cloud Kernel might lack of some -certain capabilities in fuse 7.28 ~ 7.31, which may cause unexpected results, -this patch is merely a workaround to enable virtiofs in guest kernel side and -further action is ongoing to make sure fuse APIs in both sides are 100% -compatible. - -Signed-off-by: Jacob Wang -Acked-by: Caspar Zhang ---- - tools/virtiofsd/fuse_lowlevel.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/tools/virtiofsd/fuse_lowlevel.c b/tools/virtiofsd/fuse_lowlevel.c -index 2dd36ec..2bb4318 100644 ---- a/tools/virtiofsd/fuse_lowlevel.c -+++ b/tools/virtiofsd/fuse_lowlevel.c -@@ -1917,7 +1917,7 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, - outarg.major = FUSE_KERNEL_VERSION; - outarg.minor = FUSE_KERNEL_MINOR_VERSION; - -- if (arg->major < 7 || (arg->major == 7 && arg->minor < 31)) { -+ if (arg->major < 7 || (arg->major == 7 && arg->minor < 27)) { - fuse_log(FUSE_LOG_ERR, "fuse: unsupported protocol version: %u.%u\n", - arg->major, arg->minor); - fuse_reply_err(req, EPROTO); --- -1.8.3.1 - diff --git a/kvm-virtiofsd-Fix-breakage-due-to-fuse_init_in-size-chan.patch b/kvm-virtiofsd-Fix-breakage-due-to-fuse_init_in-size-chan.patch new file mode 100644 index 0000000..7ee71ae --- /dev/null +++ b/kvm-virtiofsd-Fix-breakage-due-to-fuse_init_in-size-chan.patch @@ -0,0 +1,63 @@ +From 1da951c4c3b4e403a6c1668a54e6264381c0003d Mon Sep 17 00:00:00 2001 +From: Vivek Goyal +Date: Tue, 8 Feb 2022 15:48:04 -0500 +Subject: [PATCH 1/3] virtiofsd: Fix breakage due to fuse_init_in size change + +RH-Author: Dr. David Alan Gilbert +RH-MergeRequest: 193: virtiofsd: Fix breakage due to fuse_init_in size change +RH-Commit: [1/1] 5809db034f9361fb462181d71e7cdde1324f8e54 +RH-Bugzilla: 2097209 +RH-Acked-by: German Maglione +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Vivek Goyal +RH-Acked-by: Stefan Hajnoczi + +Kernel version 5.17 has increased the size of "struct fuse_init_in" struct. +Previously this struct was 16 bytes and now it has been extended to +64 bytes in size. + +Once qemu headers are updated to latest, it will expect to receive 64 byte +size struct (for protocol version major 7 and minor > 6). But if guest is +booting older kernel (older than 5.17), then it still sends older +fuse_init_in of size 16 bytes. And do_init() fails. It is expecting +64 byte struct. And this results in mount of virtiofs failing. + +Fix this by parsing 16 bytes only for now. Separate patches will be +posted which will parse rest of the bytes and enable new functionality. +Right now we don't support any of the new functionality, so we don't +lose anything by not parsing bytes beyond 16. + +Reviewed-by: Dr. David Alan Gilbert +Signed-off-by: Vivek Goyal +Message-Id: <20220208204813.682906-2-vgoyal@redhat.com> +Signed-off-by: Dr. David Alan Gilbert +(cherry picked from commit a086d54c6ffa38f7e71f182b63a25315304a3392) +--- + tools/virtiofsd/fuse_lowlevel.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/tools/virtiofsd/fuse_lowlevel.c b/tools/virtiofsd/fuse_lowlevel.c +index e4679c73ab..5d431a7038 100644 +--- a/tools/virtiofsd/fuse_lowlevel.c ++++ b/tools/virtiofsd/fuse_lowlevel.c +@@ -1880,6 +1880,8 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, + struct fuse_mbuf_iter *iter) + { + size_t compat_size = offsetof(struct fuse_init_in, max_readahead); ++ size_t compat2_size = offsetof(struct fuse_init_in, flags) + ++ sizeof(uint32_t); + struct fuse_init_in *arg; + struct fuse_init_out outarg; + struct fuse_session *se = req->se; +@@ -1897,7 +1899,7 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, + + /* ...and now consume the new fields. */ + if (arg->major == 7 && arg->minor >= 6) { +- if (!fuse_mbuf_iter_advance(iter, sizeof(*arg) - compat_size)) { ++ if (!fuse_mbuf_iter_advance(iter, compat2_size - compat_size)) { + fuse_reply_err(req, EINVAL); + return; + } +-- +2.35.3 + diff --git a/kvm-virtiofsd-use-g_date_time_get_microsecond-to-get-sub.patch b/kvm-virtiofsd-use-g_date_time_get_microsecond-to-get-sub.patch new file mode 100644 index 0000000..9047a1e --- /dev/null +++ b/kvm-virtiofsd-use-g_date_time_get_microsecond-to-get-sub.patch @@ -0,0 +1,61 @@ +From c4cc9d30f656acb7fcdc4d3a4b4a9bb0a34aaf7d Mon Sep 17 00:00:00 2001 +From: Yusuke Okada +Date: Thu, 18 Aug 2022 14:46:19 -0400 +Subject: [PATCH] virtiofsd: use g_date_time_get_microsecond to get subsecond + +RH-Author: Dr. David Alan Gilbert +RH-MergeRequest: 223: 8.7.z: virtiofsd: use g_date_time_get_microsecond to get subsecond +RH-Bugzilla: 2132391 +RH-Acked-by: German Maglione +RH-Acked-by: Jano Tomko +RH-Acked-by: Stefan Hajnoczi +RH-Commit: [1/1] bf1fe2785996ee9799ae23cc117598517749336c + +The "%f" specifier in g_date_time_format() is only available in glib +2.65.2 or later. If combined with older glib, the function returns null +and the timestamp displayed as "(null)". + +For backward compatibility, g_date_time_get_microsecond should be used +to retrieve subsecond. + +In this patch the g_date_time_format() leaves subsecond field as "%06d" +and let next snprintf to format with g_date_time_get_microsecond. + +Signed-off-by: Yusuke Okada +Reviewed-by: Dr. David Alan Gilbert +Message-id: 20220818184618.2205172-1-yokada.996@gmail.com +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit f16d15c9276bd8f501f861c39cbd4adc812d0c1d) +--- + tools/virtiofsd/passthrough_ll.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c +index b3d0674f6d..523d8fbe1e 100644 +--- a/tools/virtiofsd/passthrough_ll.c ++++ b/tools/virtiofsd/passthrough_ll.c +@@ -3791,6 +3791,7 @@ static void setup_nofile_rlimit(unsigned long rlimit_nofile) + static void log_func(enum fuse_log_level level, const char *fmt, va_list ap) + { + g_autofree char *localfmt = NULL; ++ char buf[64]; + + if (current_log_level < level) { + return; +@@ -3803,9 +3804,11 @@ static void log_func(enum fuse_log_level level, const char *fmt, va_list ap) + fmt); + } else { + g_autoptr(GDateTime) now = g_date_time_new_now_utc(); +- g_autofree char *nowstr = g_date_time_format(now, "%Y-%m-%d %H:%M:%S.%f%z"); ++ g_autofree char *nowstr = g_date_time_format(now, ++ "%Y-%m-%d %H:%M:%S.%%06d%z"); ++ snprintf(buf, 64, nowstr, g_date_time_get_microsecond(now)); + localfmt = g_strdup_printf("[%s] [ID: %08ld] %s", +- nowstr, syscall(__NR_gettid), fmt); ++ buf, syscall(__NR_gettid), fmt); + } + fmt = localfmt; + } +-- +2.31.1 + diff --git a/kvm-vmxcap-Add-5-level-EPT-bit.patch b/kvm-vmxcap-Add-5-level-EPT-bit.patch index e52d7ac..8cdb980 100644 --- a/kvm-vmxcap-Add-5-level-EPT-bit.patch +++ b/kvm-vmxcap-Add-5-level-EPT-bit.patch @@ -1,18 +1,16 @@ -From 51246c7571ba4cac7bd08ad318abe135a9ca7aa5 Mon Sep 17 00:00:00 2001 -From: Vitaly Kuznetsov -Date: Wed, 16 Mar 2022 09:47:32 +0100 -Subject: [PATCH 01/12] vmxcap: Add 5-level EPT bit - -RH-Author: Vitaly Kuznetsov -RH-MergeRequest: 127: i386: Add Icelake-Server-v6 CPU model with 5-level EPT support -RH-Commit: [1/2] e05cbbd3e6544fc86f2cfa86a097cbd11a91a68e -RH-Bugzilla: 2056986 +From f0f87dcea3fe14b20b8599cda9b1151ca2490d0c Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Wed, 30 Mar 2022 14:52:34 -0400 +Subject: [PATCH 07/18] vmxcap: Add 5-level EPT bit + +RH-Author: Jon Maloy +RH-MergeRequest: 139: vmxcap: Add 5-level EPT bit +RH-Commit: [1/2] 4c098f551f1ed8e2a5582f466afda35b28d97055 (jmaloy/qemu-kvm) +RH-Bugzilla: 2065207 RH-Acked-by: Paolo Bonzini -RH-Acked-by: Igor Mammedov -RH-Acked-by: Cornelia Huck -Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2056986 -Brew: https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=43862707 +BZ: https://bugzilla.redhat.com/show_bug.cgi?id=2065207 +UPSTREAM: Merged commit d312378e59658473aa91aa15c67ec6200d92e5ff Author: Vitaly Kuznetsov @@ -27,7 +25,8 @@ Date: Mon Feb 21 15:53:16 2022 +0100 Message-Id: <20220221145316.576138-2-vkuznets@redhat.com> Signed-off-by: Paolo Bonzini -Signed-off-by: Vitaly Kuznetsov +(cherry picked from commit d312378e59658473aa91aa15c67ec6200d92e5ff) +Signed-off-by: Jon Maloy --- scripts/kvm/vmxcap | 1 + 1 file changed, 1 insertion(+) diff --git a/kvm-x86-Add-AMX-CPUIDs-enumeration.patch b/kvm-x86-Add-AMX-CPUIDs-enumeration.patch new file mode 100644 index 0000000..d61e4cf --- /dev/null +++ b/kvm-x86-Add-AMX-CPUIDs-enumeration.patch @@ -0,0 +1,135 @@ +From d0826a8c2c3c389eeeed1014d7e316f39f083971 Mon Sep 17 00:00:00 2001 +From: Jing Liu +Date: Wed, 16 Feb 2022 22:04:31 -0800 +Subject: [PATCH 09/24] x86: Add AMX CPUIDs enumeration + +RH-Author: Paul Lai +RH-MergeRequest: 176: Enable KVM AMX support +RH-Commit: [9/13] fab147992ad927c9538529f018f06e2f48546c5b +RH-Bugzilla: 1916415 +RH-Acked-by: Cornelia Huck +RH-Acked-by: Igor Mammedov +RH-Acked-by: Paolo Bonzini + +Add AMX primary feature bits XFD and AMX_TILE to +enumerate the CPU's AMX capability. Meanwhile, add +AMX TILE and TMUL CPUID leaf and subleaves which +exist when AMX TILE is present to provide the maximum +capability of TILE and TMUL. + +Signed-off-by: Jing Liu +Signed-off-by: Yang Zhong +Message-Id: <20220217060434.52460-6-yang.zhong@intel.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit f21a48171cf3fa39532fc8553fd82e81b88b6474) +Signed-off-by: Paul Lai +--- + target/i386/cpu.c | 55 ++++++++++++++++++++++++++++++++++++++++--- + target/i386/kvm/kvm.c | 4 +++- + 2 files changed, 55 insertions(+), 4 deletions(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index cd27c0eb81..09e08f7f38 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -574,6 +574,18 @@ static CPUCacheInfo legacy_l3_cache = { + #define INTEL_PT_CYCLE_BITMAP 0x1fff /* Support 0,2^(0~11) */ + #define INTEL_PT_PSB_BITMAP (0x003f << 16) /* Support 2K,4K,8K,16K,32K,64K */ + ++/* CPUID Leaf 0x1D constants: */ ++#define INTEL_AMX_TILE_MAX_SUBLEAF 0x1 ++#define INTEL_AMX_TOTAL_TILE_BYTES 0x2000 ++#define INTEL_AMX_BYTES_PER_TILE 0x400 ++#define INTEL_AMX_BYTES_PER_ROW 0x40 ++#define INTEL_AMX_TILE_MAX_NAMES 0x8 ++#define INTEL_AMX_TILE_MAX_ROWS 0x10 ++ ++/* CPUID Leaf 0x1E constants: */ ++#define INTEL_AMX_TMUL_MAX_K 0x10 ++#define INTEL_AMX_TMUL_MAX_N 0x40 ++ + void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1, + uint32_t vendor2, uint32_t vendor3) + { +@@ -843,8 +855,8 @@ FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + "avx512-vp2intersect", NULL, "md-clear", NULL, + NULL, NULL, "serialize", NULL, + "tsx-ldtrk", NULL, NULL /* pconfig */, NULL, +- NULL, NULL, NULL, "avx512-fp16", +- NULL, NULL, "spec-ctrl", "stibp", ++ NULL, NULL, "amx-bf16", "avx512-fp16", ++ "amx-tile", "amx-int8", "spec-ctrl", "stibp", + NULL, "arch-capabilities", "core-capability", "ssbd", + }, + .cpuid = { +@@ -909,7 +921,7 @@ FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + .type = CPUID_FEATURE_WORD, + .feat_names = { + "xsaveopt", "xsavec", "xgetbv1", "xsaves", +- NULL, NULL, NULL, NULL, ++ "xfd", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, +@@ -5593,6 +5605,43 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, + } + break; + } ++ case 0x1D: { ++ /* AMX TILE */ ++ *eax = 0; ++ *ebx = 0; ++ *ecx = 0; ++ *edx = 0; ++ if (!(env->features[FEAT_7_0_EDX] & CPUID_7_0_EDX_AMX_TILE)) { ++ break; ++ } ++ ++ if (count == 0) { ++ /* Highest numbered palette subleaf */ ++ *eax = INTEL_AMX_TILE_MAX_SUBLEAF; ++ } else if (count == 1) { ++ *eax = INTEL_AMX_TOTAL_TILE_BYTES | ++ (INTEL_AMX_BYTES_PER_TILE << 16); ++ *ebx = INTEL_AMX_BYTES_PER_ROW | (INTEL_AMX_TILE_MAX_NAMES << 16); ++ *ecx = INTEL_AMX_TILE_MAX_ROWS; ++ } ++ break; ++ } ++ case 0x1E: { ++ /* AMX TMUL */ ++ *eax = 0; ++ *ebx = 0; ++ *ecx = 0; ++ *edx = 0; ++ if (!(env->features[FEAT_7_0_EDX] & CPUID_7_0_EDX_AMX_TILE)) { ++ break; ++ } ++ ++ if (count == 0) { ++ /* Highest numbered palette subleaf */ ++ *ebx = INTEL_AMX_TMUL_MAX_K | (INTEL_AMX_TMUL_MAX_N << 8); ++ } ++ break; ++ } + case 0x40000000: + /* + * CPUID code in kvm_arch_init_vcpu() ignores stuff +diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c +index b5d98c4361..a64a79d870 100644 +--- a/target/i386/kvm/kvm.c ++++ b/target/i386/kvm/kvm.c +@@ -1779,7 +1779,9 @@ int kvm_arch_init_vcpu(CPUState *cs) + c = &cpuid_data.entries[cpuid_i++]; + } + break; +- case 0x14: { ++ case 0x14: ++ case 0x1d: ++ case 0x1e: { + uint32_t times; + + c->function = i; +-- +2.35.3 + diff --git a/kvm-x86-Add-AMX-XTILECFG-and-XTILEDATA-components.patch b/kvm-x86-Add-AMX-XTILECFG-and-XTILEDATA-components.patch new file mode 100644 index 0000000..064b124 --- /dev/null +++ b/kvm-x86-Add-AMX-XTILECFG-and-XTILEDATA-components.patch @@ -0,0 +1,112 @@ +From 3ba6092159b6e3b25505af2a49c0f6ac99043db9 Mon Sep 17 00:00:00 2001 +From: Jing Liu +Date: Wed, 16 Feb 2022 22:04:28 -0800 +Subject: [PATCH 06/24] x86: Add AMX XTILECFG and XTILEDATA components + +RH-Author: Paul Lai +RH-MergeRequest: 176: Enable KVM AMX support +RH-Commit: [6/13] 95229f87b4494631d57232f374a174f7bc95843a +RH-Bugzilla: 1916415 +RH-Acked-by: Cornelia Huck +RH-Acked-by: Igor Mammedov +RH-Acked-by: Paolo Bonzini + +The AMX TILECFG register and the TMMx tile data registers are +saved/restored via XSAVE, respectively in state component 17 +(64 bytes) and state component 18 (8192 bytes). + +Add AMX feature bits to x86_ext_save_areas array to set +up AMX components. Add structs that define the layout of +AMX XSAVE areas and use QEMU_BUILD_BUG_ON to validate the +structs sizes. + +Signed-off-by: Jing Liu +Signed-off-by: Yang Zhong +Message-Id: <20220217060434.52460-3-yang.zhong@intel.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit 1f16764f7d4515bfd5e4ae0aae814fa280a7d0c8) +Signed-off-by: Paul Lai +--- + target/i386/cpu.c | 8 ++++++++ + target/i386/cpu.h | 18 +++++++++++++++++- + 2 files changed, 25 insertions(+), 1 deletion(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index f44fad3a2a..0453c27c9d 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -1401,6 +1401,14 @@ ExtSaveArea x86_ext_save_areas[XSAVE_STATE_AREA_COUNT] = { + [XSTATE_PKRU_BIT] = + { .feature = FEAT_7_0_ECX, .bits = CPUID_7_0_ECX_PKU, + .size = sizeof(XSavePKRU) }, ++ [XSTATE_XTILE_CFG_BIT] = { ++ .feature = FEAT_7_0_EDX, .bits = CPUID_7_0_EDX_AMX_TILE, ++ .size = sizeof(XSaveXTILECFG), ++ }, ++ [XSTATE_XTILE_DATA_BIT] = { ++ .feature = FEAT_7_0_EDX, .bits = CPUID_7_0_EDX_AMX_TILE, ++ .size = sizeof(XSaveXTILEDATA) ++ }, + }; + + static uint32_t xsave_area_size(uint64_t mask) +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index 5d9702a991..e1dd8b9555 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -537,6 +537,8 @@ typedef enum X86Seg { + #define XSTATE_ZMM_Hi256_BIT 6 + #define XSTATE_Hi16_ZMM_BIT 7 + #define XSTATE_PKRU_BIT 9 ++#define XSTATE_XTILE_CFG_BIT 17 ++#define XSTATE_XTILE_DATA_BIT 18 + + #define XSTATE_FP_MASK (1ULL << XSTATE_FP_BIT) + #define XSTATE_SSE_MASK (1ULL << XSTATE_SSE_BIT) +@@ -845,6 +847,8 @@ typedef uint64_t FeatureWordArray[FEATURE_WORDS]; + #define CPUID_7_0_EDX_TSX_LDTRK (1U << 16) + /* AVX512_FP16 instruction */ + #define CPUID_7_0_EDX_AVX512_FP16 (1U << 23) ++/* AMX tile (two-dimensional register) */ ++#define CPUID_7_0_EDX_AMX_TILE (1U << 24) + /* Speculation Control */ + #define CPUID_7_0_EDX_SPEC_CTRL (1U << 26) + /* Single Thread Indirect Branch Predictors */ +@@ -1348,6 +1352,16 @@ typedef struct XSavePKRU { + uint32_t padding; + } XSavePKRU; + ++/* Ext. save area 17: AMX XTILECFG state */ ++typedef struct XSaveXTILECFG { ++ uint8_t xtilecfg[64]; ++} XSaveXTILECFG; ++ ++/* Ext. save area 18: AMX XTILEDATA state */ ++typedef struct XSaveXTILEDATA { ++ uint8_t xtiledata[8][1024]; ++} XSaveXTILEDATA; ++ + QEMU_BUILD_BUG_ON(sizeof(XSaveAVX) != 0x100); + QEMU_BUILD_BUG_ON(sizeof(XSaveBNDREG) != 0x40); + QEMU_BUILD_BUG_ON(sizeof(XSaveBNDCSR) != 0x40); +@@ -1355,6 +1369,8 @@ QEMU_BUILD_BUG_ON(sizeof(XSaveOpmask) != 0x40); + QEMU_BUILD_BUG_ON(sizeof(XSaveZMM_Hi256) != 0x200); + QEMU_BUILD_BUG_ON(sizeof(XSaveHi16_ZMM) != 0x400); + QEMU_BUILD_BUG_ON(sizeof(XSavePKRU) != 0x8); ++QEMU_BUILD_BUG_ON(sizeof(XSaveXTILECFG) != 0x40); ++QEMU_BUILD_BUG_ON(sizeof(XSaveXTILEDATA) != 0x2000); + + typedef struct ExtSaveArea { + uint32_t feature, bits; +@@ -1362,7 +1378,7 @@ typedef struct ExtSaveArea { + uint32_t ecx; + } ExtSaveArea; + +-#define XSAVE_STATE_AREA_COUNT (XSTATE_PKRU_BIT + 1) ++#define XSAVE_STATE_AREA_COUNT (XSTATE_XTILE_DATA_BIT + 1) + + extern ExtSaveArea x86_ext_save_areas[XSAVE_STATE_AREA_COUNT]; + +-- +2.35.3 + diff --git a/kvm-x86-Add-XFD-faulting-bit-for-state-components.patch b/kvm-x86-Add-XFD-faulting-bit-for-state-components.patch new file mode 100644 index 0000000..5c0fd0a --- /dev/null +++ b/kvm-x86-Add-XFD-faulting-bit-for-state-components.patch @@ -0,0 +1,62 @@ +From 098d6a965ada02f5897b73f0489413a050a176bb Mon Sep 17 00:00:00 2001 +From: Jing Liu +Date: Wed, 16 Feb 2022 22:04:30 -0800 +Subject: [PATCH 08/24] x86: Add XFD faulting bit for state components + +RH-Author: Paul Lai +RH-MergeRequest: 176: Enable KVM AMX support +RH-Commit: [8/13] 0b1b46c5d075655ab94bc79e042b187c5dc55551 +RH-Bugzilla: 1916415 +RH-Acked-by: Cornelia Huck +RH-Acked-by: Igor Mammedov +RH-Acked-by: Paolo Bonzini + +Intel introduces XFD faulting mechanism for extended +XSAVE features to dynamically enable the features in +runtime. If CPUID (EAX=0Dh, ECX=n, n>1).ECX[2] is set +as 1, it indicates support for XFD faulting of this +state component. + +Signed-off-by: Jing Liu +Signed-off-by: Yang Zhong +Message-Id: <20220217060434.52460-5-yang.zhong@intel.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit 0f17f6b30f3b051f0f96ccc98c9f7f395713699f) +Signed-off-by: Paul Lai +--- + target/i386/cpu.c | 3 ++- + target/i386/cpu.h | 2 ++ + 2 files changed, 4 insertions(+), 1 deletion(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index c19b51ea32..cd27c0eb81 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -5503,7 +5503,8 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, + const ExtSaveArea *esa = &x86_ext_save_areas[count]; + *eax = esa->size; + *ebx = esa->offset; +- *ecx = esa->ecx & ESA_FEATURE_ALIGN64_MASK; ++ *ecx = esa->ecx & ++ (ESA_FEATURE_ALIGN64_MASK | ESA_FEATURE_XFD_MASK); + } + } + break; +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index 58676390e6..f2bdef9c26 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -555,8 +555,10 @@ typedef enum X86Seg { + #define XSTATE_DYNAMIC_MASK (XSTATE_XTILE_DATA_MASK) + + #define ESA_FEATURE_ALIGN64_BIT 1 ++#define ESA_FEATURE_XFD_BIT 2 + + #define ESA_FEATURE_ALIGN64_MASK (1U << ESA_FEATURE_ALIGN64_BIT) ++#define ESA_FEATURE_XFD_MASK (1U << ESA_FEATURE_XFD_BIT) + + + /* CPUID feature words */ +-- +2.35.3 + diff --git a/kvm-x86-Fix-the-64-byte-boundary-enumeration-for-extende.patch b/kvm-x86-Fix-the-64-byte-boundary-enumeration-for-extende.patch new file mode 100644 index 0000000..2db4c60 --- /dev/null +++ b/kvm-x86-Fix-the-64-byte-boundary-enumeration-for-extende.patch @@ -0,0 +1,88 @@ +From 6eae12166341c236da023e5117b64b842ae72083 Mon Sep 17 00:00:00 2001 +From: Jing Liu +Date: Wed, 16 Feb 2022 22:04:27 -0800 +Subject: [PATCH 05/24] x86: Fix the 64-byte boundary enumeration for extended + state + +RH-Author: Paul Lai +RH-MergeRequest: 176: Enable KVM AMX support +RH-Commit: [5/13] 64fc93e3b0ad0fc56da9d71b33d9eefd3cbba1d7 +RH-Bugzilla: 1916415 +RH-Acked-by: Cornelia Huck +RH-Acked-by: Igor Mammedov +RH-Acked-by: Paolo Bonzini + +The extended state subleaves (EAX=0Dh, ECX=n, n>1).ECX[1] +indicate whether the extended state component locates +on the next 64-byte boundary following the preceding state +component when the compacted format of an XSAVE area is +used. + +Right now, they are all zero because no supported component +needed the bit to be set, but the upcoming AMX feature will +use it. Fix the subleaves value according to KVM's supported +cpuid. + +Signed-off-by: Jing Liu +Signed-off-by: Yang Zhong +Message-Id: <20220217060434.52460-2-yang.zhong@intel.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit 131266b7565bd437127bd231563572696bb27235) +Signed-off-by: Paul Lai +--- + target/i386/cpu.c | 1 + + target/i386/cpu.h | 6 ++++++ + target/i386/kvm/kvm-cpu.c | 1 + + 3 files changed, 8 insertions(+) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index dd6935b1dd..f44fad3a2a 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -5495,6 +5495,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, + const ExtSaveArea *esa = &x86_ext_save_areas[count]; + *eax = esa->size; + *ebx = esa->offset; ++ *ecx = esa->ecx & ESA_FEATURE_ALIGN64_MASK; + } + } + break; +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index c6a6c871f1..5d9702a991 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -548,6 +548,11 @@ typedef enum X86Seg { + #define XSTATE_Hi16_ZMM_MASK (1ULL << XSTATE_Hi16_ZMM_BIT) + #define XSTATE_PKRU_MASK (1ULL << XSTATE_PKRU_BIT) + ++#define ESA_FEATURE_ALIGN64_BIT 1 ++ ++#define ESA_FEATURE_ALIGN64_MASK (1U << ESA_FEATURE_ALIGN64_BIT) ++ ++ + /* CPUID feature words */ + typedef enum FeatureWord { + FEAT_1_EDX, /* CPUID[1].EDX */ +@@ -1354,6 +1359,7 @@ QEMU_BUILD_BUG_ON(sizeof(XSavePKRU) != 0x8); + typedef struct ExtSaveArea { + uint32_t feature, bits; + uint32_t offset, size; ++ uint32_t ecx; + } ExtSaveArea; + + #define XSAVE_STATE_AREA_COUNT (XSTATE_PKRU_BIT + 1) +diff --git a/target/i386/kvm/kvm-cpu.c b/target/i386/kvm/kvm-cpu.c +index 7b004065ae..86ef7b2712 100644 +--- a/target/i386/kvm/kvm-cpu.c ++++ b/target/i386/kvm/kvm-cpu.c +@@ -104,6 +104,7 @@ static void kvm_cpu_xsave_init(void) + if (sz != 0) { + assert(esa->size == sz); + esa->offset = kvm_arch_get_supported_cpuid(s, 0xd, i, R_EBX); ++ esa->ecx = kvm_arch_get_supported_cpuid(s, 0xd, i, R_ECX); + } + } + } +-- +2.35.3 + diff --git a/kvm-x86-Grant-AMX-permission-for-guest.patch b/kvm-x86-Grant-AMX-permission-for-guest.patch new file mode 100644 index 0000000..c2ab95d --- /dev/null +++ b/kvm-x86-Grant-AMX-permission-for-guest.patch @@ -0,0 +1,215 @@ +From 50840e01d05a466a1dfbc219e49233834e5d7ed0 Mon Sep 17 00:00:00 2001 +From: Yang Zhong +Date: Wed, 16 Feb 2022 22:04:29 -0800 +Subject: [PATCH 07/24] x86: Grant AMX permission for guest + +RH-Author: Paul Lai +RH-MergeRequest: 176: Enable KVM AMX support +RH-Commit: [7/13] 437578191f61139ca710cc7045ab38eb0d05eae2 +RH-Bugzilla: 1916415 +RH-Acked-by: Cornelia Huck +RH-Acked-by: Igor Mammedov +RH-Acked-by: Paolo Bonzini + +Kernel allocates 4K xstate buffer by default. For XSAVE features +which require large state component (e.g. AMX), Linux kernel +dynamically expands the xstate buffer only after the process has +acquired the necessary permissions. Those are called dynamically- +enabled XSAVE features (or dynamic xfeatures). + +There are separate permissions for native tasks and guests. + +Qemu should request the guest permissions for dynamic xfeatures +which will be exposed to the guest. This only needs to be done +once before the first vcpu is created. + +KVM implemented one new ARCH_GET_XCOMP_SUPP system attribute API to +get host side supported_xcr0 and Qemu can decide if it can request +dynamically enabled XSAVE features permission. +https://lore.kernel.org/all/20220126152210.3044876-1-pbonzini@redhat.com/ + +Suggested-by: Paolo Bonzini +Signed-off-by: Yang Zhong +Signed-off-by: Jing Liu +Message-Id: <20220217060434.52460-4-yang.zhong@intel.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit 19db68ca68a78fa033a21d419036b6e416554564) +Signed-off-by: Paul Lai +--- + target/i386/cpu.c | 7 +++++ + target/i386/cpu.h | 4 +++ + target/i386/kvm/kvm-cpu.c | 12 ++++---- + target/i386/kvm/kvm.c | 57 ++++++++++++++++++++++++++++++++++++++ + target/i386/kvm/kvm_i386.h | 1 + + 5 files changed, 75 insertions(+), 6 deletions(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 0453c27c9d..c19b51ea32 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -6027,6 +6027,7 @@ static void x86_cpu_enable_xsave_components(X86CPU *cpu) + CPUX86State *env = &cpu->env; + int i; + uint64_t mask; ++ static bool request_perm; + + if (!(env->features[FEAT_1_ECX] & CPUID_EXT_XSAVE)) { + env->features[FEAT_XSAVE_COMP_LO] = 0; +@@ -6042,6 +6043,12 @@ static void x86_cpu_enable_xsave_components(X86CPU *cpu) + } + } + ++ /* Only request permission for first vcpu */ ++ if (kvm_enabled() && !request_perm) { ++ kvm_request_xsave_components(cpu, mask); ++ request_perm = true; ++ } ++ + env->features[FEAT_XSAVE_COMP_LO] = mask; + env->features[FEAT_XSAVE_COMP_HI] = mask >> 32; + } +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index e1dd8b9555..58676390e6 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -549,6 +549,10 @@ typedef enum X86Seg { + #define XSTATE_ZMM_Hi256_MASK (1ULL << XSTATE_ZMM_Hi256_BIT) + #define XSTATE_Hi16_ZMM_MASK (1ULL << XSTATE_Hi16_ZMM_BIT) + #define XSTATE_PKRU_MASK (1ULL << XSTATE_PKRU_BIT) ++#define XSTATE_XTILE_CFG_MASK (1ULL << XSTATE_XTILE_CFG_BIT) ++#define XSTATE_XTILE_DATA_MASK (1ULL << XSTATE_XTILE_DATA_BIT) ++ ++#define XSTATE_DYNAMIC_MASK (XSTATE_XTILE_DATA_MASK) + + #define ESA_FEATURE_ALIGN64_BIT 1 + +diff --git a/target/i386/kvm/kvm-cpu.c b/target/i386/kvm/kvm-cpu.c +index 86ef7b2712..bdc967c484 100644 +--- a/target/i386/kvm/kvm-cpu.c ++++ b/target/i386/kvm/kvm-cpu.c +@@ -84,7 +84,7 @@ static void kvm_cpu_max_instance_init(X86CPU *cpu) + static void kvm_cpu_xsave_init(void) + { + static bool first = true; +- KVMState *s = kvm_state; ++ uint32_t eax, ebx, ecx, edx; + int i; + + if (!first) { +@@ -100,11 +100,11 @@ static void kvm_cpu_xsave_init(void) + ExtSaveArea *esa = &x86_ext_save_areas[i]; + + if (esa->size) { +- int sz = kvm_arch_get_supported_cpuid(s, 0xd, i, R_EAX); +- if (sz != 0) { +- assert(esa->size == sz); +- esa->offset = kvm_arch_get_supported_cpuid(s, 0xd, i, R_EBX); +- esa->ecx = kvm_arch_get_supported_cpuid(s, 0xd, i, R_ECX); ++ host_cpuid(0xd, i, &eax, &ebx, &ecx, &edx); ++ if (eax != 0) { ++ assert(esa->size == eax); ++ esa->offset = ebx; ++ esa->ecx = ecx; + } + } + } +diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c +index a668f521ac..b5d98c4361 100644 +--- a/target/i386/kvm/kvm.c ++++ b/target/i386/kvm/kvm.c +@@ -17,6 +17,7 @@ + #include "qapi/error.h" + #include + #include ++#include + + #include + #include "standard-headers/asm-x86/kvm_para.h" +@@ -347,6 +348,7 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function, + struct kvm_cpuid2 *cpuid; + uint32_t ret = 0; + uint32_t cpuid_1_edx; ++ uint64_t bitmask; + + cpuid = get_supported_cpuid(s); + +@@ -404,6 +406,25 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function, + if (!has_msr_arch_capabs) { + ret &= ~CPUID_7_0_EDX_ARCH_CAPABILITIES; + } ++ } else if (function == 0xd && index == 0 && ++ (reg == R_EAX || reg == R_EDX)) { ++ struct kvm_device_attr attr = { ++ .group = 0, ++ .attr = KVM_X86_XCOMP_GUEST_SUPP, ++ .addr = (unsigned long) &bitmask ++ }; ++ ++ bool sys_attr = kvm_check_extension(s, KVM_CAP_SYS_ATTRIBUTES); ++ if (!sys_attr) { ++ warn_report("cannot get sys attribute capabilities %d", sys_attr); ++ } ++ ++ int rc = kvm_ioctl(s, KVM_GET_DEVICE_ATTR, &attr); ++ if (rc == -1 && (errno == ENXIO || errno == EINVAL)) { ++ warn_report("KVM_GET_DEVICE_ATTR(0, KVM_X86_XCOMP_GUEST_SUPP) " ++ "error: %d", rc); ++ } ++ ret = (reg == R_EAX) ? bitmask : bitmask >> 32; + } else if (function == 0x80000001 && reg == R_ECX) { + /* + * It's safe to enable TOPOEXT even if it's not returned by +@@ -5054,3 +5075,39 @@ bool kvm_arch_cpu_check_are_resettable(void) + { + return !sev_es_enabled(); + } ++ ++#define ARCH_REQ_XCOMP_GUEST_PERM 0x1025 ++ ++void kvm_request_xsave_components(X86CPU *cpu, uint64_t mask) ++{ ++ KVMState *s = kvm_state; ++ uint64_t supported; ++ ++ mask &= XSTATE_DYNAMIC_MASK; ++ if (!mask) { ++ return; ++ } ++ /* ++ * Just ignore bits that are not in CPUID[EAX=0xD,ECX=0]. ++ * ARCH_REQ_XCOMP_GUEST_PERM would fail, and QEMU has warned ++ * about them already because they are not supported features. ++ */ ++ supported = kvm_arch_get_supported_cpuid(s, 0xd, 0, R_EAX); ++ supported |= (uint64_t)kvm_arch_get_supported_cpuid(s, 0xd, 0, R_EDX) << 32; ++ mask &= supported; ++ ++ while (mask) { ++ int bit = ctz64(mask); ++ int rc = syscall(SYS_arch_prctl, ARCH_REQ_XCOMP_GUEST_PERM, bit); ++ if (rc) { ++ /* ++ * Older kernel version (<5.17) do not support ++ * ARCH_REQ_XCOMP_GUEST_PERM, but also do not return ++ * any dynamic feature from kvm_arch_get_supported_cpuid. ++ */ ++ warn_report("prctl(ARCH_REQ_XCOMP_GUEST_PERM) failure " ++ "for feature bit %d", bit); ++ } ++ mask &= ~BIT_ULL(bit); ++ } ++} +diff --git a/target/i386/kvm/kvm_i386.h b/target/i386/kvm/kvm_i386.h +index a978509d50..4124912c20 100644 +--- a/target/i386/kvm/kvm_i386.h ++++ b/target/i386/kvm/kvm_i386.h +@@ -52,5 +52,6 @@ bool kvm_hyperv_expand_features(X86CPU *cpu, Error **errp); + uint64_t kvm_swizzle_msi_ext_dest_id(uint64_t address); + + bool kvm_enable_sgx_provisioning(KVMState *s); ++void kvm_request_xsave_components(X86CPU *cpu, uint64_t mask); + + #endif +-- +2.35.3 + diff --git a/kvm-x86-Support-XFD-and-AMX-xsave-data-migration.patch b/kvm-x86-Support-XFD-and-AMX-xsave-data-migration.patch new file mode 100644 index 0000000..e4846b3 --- /dev/null +++ b/kvm-x86-Support-XFD-and-AMX-xsave-data-migration.patch @@ -0,0 +1,178 @@ +From 90a276ed72deab84f3fdd4b57e9ccfc6514934fb Mon Sep 17 00:00:00 2001 +From: Zeng Guang +Date: Wed, 16 Feb 2022 22:04:33 -0800 +Subject: [PATCH 11/24] x86: Support XFD and AMX xsave data migration + +RH-Author: Paul Lai +RH-MergeRequest: 176: Enable KVM AMX support +RH-Commit: [11/13] 4ff6e5544ffdac4e6d2f568f7f63b937502ca6c5 +RH-Bugzilla: 1916415 +RH-Acked-by: Cornelia Huck +RH-Acked-by: Igor Mammedov +RH-Acked-by: Paolo Bonzini + +XFD(eXtended Feature Disable) allows to enable a +feature on xsave state while preventing specific +user threads from using the feature. + +Support save and restore XFD MSRs if CPUID.D.1.EAX[4] +enumerate to be valid. Likewise migrate the MSRs and +related xsave state necessarily. + +Signed-off-by: Zeng Guang +Signed-off-by: Wei Wang +Signed-off-by: Yang Zhong +Message-Id: <20220217060434.52460-8-yang.zhong@intel.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit cdec2b753b487d9e8aab028231c35d87789ea083) +Signed-off-by: Paul Lai +--- + target/i386/cpu.h | 9 +++++++++ + target/i386/kvm/kvm.c | 18 +++++++++++++++++ + target/i386/machine.c | 46 +++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 73 insertions(+) + +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index 14a3501b87..8ab2a4042a 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -505,6 +505,9 @@ typedef enum X86Seg { + + #define MSR_VM_HSAVE_PA 0xc0010117 + ++#define MSR_IA32_XFD 0x000001c4 ++#define MSR_IA32_XFD_ERR 0x000001c5 ++ + #define MSR_IA32_BNDCFGS 0x00000d90 + #define MSR_IA32_XSS 0x00000da0 + #define MSR_IA32_UMWAIT_CONTROL 0xe1 +@@ -870,6 +873,8 @@ typedef uint64_t FeatureWordArray[FEATURE_WORDS]; + #define CPUID_7_1_EAX_AVX_VNNI (1U << 4) + /* AVX512 BFloat16 Instruction */ + #define CPUID_7_1_EAX_AVX512_BF16 (1U << 5) ++/* XFD Extend Feature Disabled */ ++#define CPUID_D_1_EAX_XFD (1U << 4) + + /* Packets which contain IP payload have LIP values */ + #define CPUID_14_0_ECX_LIP (1U << 31) +@@ -1610,6 +1615,10 @@ typedef struct CPUX86State { + uint64_t msr_rtit_cr3_match; + uint64_t msr_rtit_addrs[MAX_RTIT_ADDRS]; + ++ /* Per-VCPU XFD MSRs */ ++ uint64_t msr_xfd; ++ uint64_t msr_xfd_err; ++ + /* exception/interrupt handling */ + int error_code; + int exception_is_int; +diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c +index d3d476df27..b1128b0e07 100644 +--- a/target/i386/kvm/kvm.c ++++ b/target/i386/kvm/kvm.c +@@ -3219,6 +3219,13 @@ static int kvm_put_msrs(X86CPU *cpu, int level) + env->msr_ia32_sgxlepubkeyhash[3]); + } + ++ if (env->features[FEAT_XSAVE] & CPUID_D_1_EAX_XFD) { ++ kvm_msr_entry_add(cpu, MSR_IA32_XFD, ++ env->msr_xfd); ++ kvm_msr_entry_add(cpu, MSR_IA32_XFD_ERR, ++ env->msr_xfd_err); ++ } ++ + /* Note: MSR_IA32_FEATURE_CONTROL is written separately, see + * kvm_put_msr_feature_control. */ + } +@@ -3571,6 +3578,11 @@ static int kvm_get_msrs(X86CPU *cpu) + kvm_msr_entry_add(cpu, MSR_IA32_SGXLEPUBKEYHASH3, 0); + } + ++ if (env->features[FEAT_XSAVE] & CPUID_D_1_EAX_XFD) { ++ kvm_msr_entry_add(cpu, MSR_IA32_XFD, 0); ++ kvm_msr_entry_add(cpu, MSR_IA32_XFD_ERR, 0); ++ } ++ + ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_MSRS, cpu->kvm_msr_buf); + if (ret < 0) { + return ret; +@@ -3870,6 +3882,12 @@ static int kvm_get_msrs(X86CPU *cpu) + env->msr_ia32_sgxlepubkeyhash[index - MSR_IA32_SGXLEPUBKEYHASH0] = + msrs[i].data; + break; ++ case MSR_IA32_XFD: ++ env->msr_xfd = msrs[i].data; ++ break; ++ case MSR_IA32_XFD_ERR: ++ env->msr_xfd_err = msrs[i].data; ++ break; + } + } + +diff --git a/target/i386/machine.c b/target/i386/machine.c +index 83c2b91529..3977e9d8f8 100644 +--- a/target/i386/machine.c ++++ b/target/i386/machine.c +@@ -1455,6 +1455,48 @@ static const VMStateDescription vmstate_msr_intel_sgx = { + } + }; + ++static bool xfd_msrs_needed(void *opaque) ++{ ++ X86CPU *cpu = opaque; ++ CPUX86State *env = &cpu->env; ++ ++ return !!(env->features[FEAT_XSAVE] & CPUID_D_1_EAX_XFD); ++} ++ ++static const VMStateDescription vmstate_msr_xfd = { ++ .name = "cpu/msr_xfd", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .needed = xfd_msrs_needed, ++ .fields = (VMStateField[]) { ++ VMSTATE_UINT64(env.msr_xfd, X86CPU), ++ VMSTATE_UINT64(env.msr_xfd_err, X86CPU), ++ VMSTATE_END_OF_LIST() ++ } ++}; ++ ++#ifdef TARGET_X86_64 ++static bool amx_xtile_needed(void *opaque) ++{ ++ X86CPU *cpu = opaque; ++ CPUX86State *env = &cpu->env; ++ ++ return !!(env->features[FEAT_7_0_EDX] & CPUID_7_0_EDX_AMX_TILE); ++} ++ ++static const VMStateDescription vmstate_amx_xtile = { ++ .name = "cpu/intel_amx_xtile", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .needed = amx_xtile_needed, ++ .fields = (VMStateField[]) { ++ VMSTATE_UINT8_ARRAY(env.xtilecfg, X86CPU, 64), ++ VMSTATE_UINT8_ARRAY(env.xtiledata, X86CPU, 8192), ++ VMSTATE_END_OF_LIST() ++ } ++}; ++#endif ++ + const VMStateDescription vmstate_x86_cpu = { + .name = "cpu", + .version_id = 12, +@@ -1593,6 +1635,10 @@ const VMStateDescription vmstate_x86_cpu = { + #endif + &vmstate_msr_tsx_ctrl, + &vmstate_msr_intel_sgx, ++ &vmstate_msr_xfd, ++#ifdef TARGET_X86_64 ++ &vmstate_amx_xtile, ++#endif + NULL + } + }; +-- +2.35.3 + diff --git a/kvm-x86-add-support-for-KVM_CAP_XSAVE2-and-AMX-state-mig.patch b/kvm-x86-add-support-for-KVM_CAP_XSAVE2-and-AMX-state-mig.patch new file mode 100644 index 0000000..13566b1 --- /dev/null +++ b/kvm-x86-add-support-for-KVM_CAP_XSAVE2-and-AMX-state-mig.patch @@ -0,0 +1,182 @@ +From 28cf1b55f346a9f56e84fa57921f5a28a99cd59b Mon Sep 17 00:00:00 2001 +From: Jing Liu +Date: Wed, 16 Feb 2022 22:04:32 -0800 +Subject: [PATCH 10/24] x86: add support for KVM_CAP_XSAVE2 and AMX state + migration + +RH-Author: Paul Lai +RH-MergeRequest: 176: Enable KVM AMX support +RH-Commit: [10/13] d584f455ba1ecd8a4a87f3470e6aac24ba9a1f5a +RH-Bugzilla: 1916415 +RH-Acked-by: Cornelia Huck +RH-Acked-by: Igor Mammedov +RH-Acked-by: Paolo Bonzini + +When dynamic xfeatures (e.g. AMX) are used by the guest, the xsave +area would be larger than 4KB. KVM_GET_XSAVE2 and KVM_SET_XSAVE +under KVM_CAP_XSAVE2 works with a xsave buffer larger than 4KB. +Always use the new ioctls under KVM_CAP_XSAVE2 when KVM supports it. + +Signed-off-by: Jing Liu +Signed-off-by: Zeng Guang +Signed-off-by: Wei Wang +Signed-off-by: Yang Zhong +Message-Id: <20220217060434.52460-7-yang.zhong@intel.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit e56dd3c70abb31893c61ac834109fa7a38841330) +Signed-off-by: Paul Lai +--- + target/i386/cpu.h | 4 ++++ + target/i386/kvm/kvm.c | 42 ++++++++++++++++++++++++-------------- + target/i386/xsave_helper.c | 28 +++++++++++++++++++++++++ + 3 files changed, 59 insertions(+), 15 deletions(-) + +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index f2bdef9c26..14a3501b87 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -1522,6 +1522,10 @@ typedef struct CPUX86State { + uint64_t opmask_regs[NB_OPMASK_REGS]; + YMMReg zmmh_regs[CPU_NB_REGS]; + ZMMReg hi16_zmm_regs[CPU_NB_REGS]; ++#ifdef TARGET_X86_64 ++ uint8_t xtilecfg[64]; ++ uint8_t xtiledata[8192]; ++#endif + + /* sysenter registers */ + uint32_t sysenter_cs; +diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c +index a64a79d870..d3d476df27 100644 +--- a/target/i386/kvm/kvm.c ++++ b/target/i386/kvm/kvm.c +@@ -123,6 +123,7 @@ static uint32_t num_architectural_pmu_gp_counters; + static uint32_t num_architectural_pmu_fixed_counters; + + static int has_xsave; ++static int has_xsave2; + static int has_xcrs; + static int has_pit_state2; + static int has_exception_payload; +@@ -1585,6 +1586,26 @@ static Error *invtsc_mig_blocker; + + #define KVM_MAX_CPUID_ENTRIES 100 + ++static void kvm_init_xsave(CPUX86State *env) ++{ ++ if (has_xsave2) { ++ env->xsave_buf_len = QEMU_ALIGN_UP(has_xsave2, 4096); ++ } else if (has_xsave) { ++ env->xsave_buf_len = sizeof(struct kvm_xsave); ++ } else { ++ return; ++ } ++ ++ env->xsave_buf = qemu_memalign(4096, env->xsave_buf_len); ++ memset(env->xsave_buf, 0, env->xsave_buf_len); ++ /* ++ * The allocated storage must be large enough for all of the ++ * possible XSAVE state components. ++ */ ++ assert(kvm_arch_get_supported_cpuid(kvm_state, 0xd, 0, R_ECX) <= ++ env->xsave_buf_len); ++} ++ + int kvm_arch_init_vcpu(CPUState *cs) + { + struct { +@@ -1614,6 +1635,8 @@ int kvm_arch_init_vcpu(CPUState *cs) + + cpuid_i = 0; + ++ has_xsave2 = kvm_check_extension(cs->kvm_state, KVM_CAP_XSAVE2); ++ + r = kvm_arch_set_tsc_khz(cs); + if (r < 0) { + return r; +@@ -2003,19 +2026,7 @@ int kvm_arch_init_vcpu(CPUState *cs) + if (r) { + goto fail; + } +- +- if (has_xsave) { +- env->xsave_buf_len = sizeof(struct kvm_xsave); +- env->xsave_buf = qemu_memalign(4096, env->xsave_buf_len); +- memset(env->xsave_buf, 0, env->xsave_buf_len); +- +- /* +- * The allocated storage must be large enough for all of the +- * possible XSAVE state components. +- */ +- assert(kvm_arch_get_supported_cpuid(kvm_state, 0xd, 0, R_ECX) +- <= env->xsave_buf_len); +- } ++ kvm_init_xsave(env); + + max_nested_state_len = kvm_max_nested_state_length(); + if (max_nested_state_len > 0) { +@@ -3263,13 +3274,14 @@ static int kvm_get_xsave(X86CPU *cpu) + { + CPUX86State *env = &cpu->env; + void *xsave = env->xsave_buf; +- int ret; ++ int type, ret; + + if (!has_xsave) { + return kvm_get_fpu(cpu); + } + +- ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_XSAVE, xsave); ++ type = has_xsave2 ? KVM_GET_XSAVE2 : KVM_GET_XSAVE; ++ ret = kvm_vcpu_ioctl(CPU(cpu), type, xsave); + if (ret < 0) { + return ret; + } +diff --git a/target/i386/xsave_helper.c b/target/i386/xsave_helper.c +index ac61a96344..996e9f3bfe 100644 +--- a/target/i386/xsave_helper.c ++++ b/target/i386/xsave_helper.c +@@ -126,6 +126,20 @@ void x86_cpu_xsave_all_areas(X86CPU *cpu, void *buf, uint32_t buflen) + + memcpy(pkru, &env->pkru, sizeof(env->pkru)); + } ++ ++ e = &x86_ext_save_areas[XSTATE_XTILE_CFG_BIT]; ++ if (e->size && e->offset) { ++ XSaveXTILECFG *tilecfg = buf + e->offset; ++ ++ memcpy(tilecfg, &env->xtilecfg, sizeof(env->xtilecfg)); ++ } ++ ++ e = &x86_ext_save_areas[XSTATE_XTILE_DATA_BIT]; ++ if (e->size && e->offset && buflen >= e->size + e->offset) { ++ XSaveXTILEDATA *tiledata = buf + e->offset; ++ ++ memcpy(tiledata, &env->xtiledata, sizeof(env->xtiledata)); ++ } + #endif + } + +@@ -247,5 +261,19 @@ void x86_cpu_xrstor_all_areas(X86CPU *cpu, const void *buf, uint32_t buflen) + pkru = buf + e->offset; + memcpy(&env->pkru, pkru, sizeof(env->pkru)); + } ++ ++ e = &x86_ext_save_areas[XSTATE_XTILE_CFG_BIT]; ++ if (e->size && e->offset) { ++ const XSaveXTILECFG *tilecfg = buf + e->offset; ++ ++ memcpy(&env->xtilecfg, tilecfg, sizeof(env->xtilecfg)); ++ } ++ ++ e = &x86_ext_save_areas[XSTATE_XTILE_DATA_BIT]; ++ if (e->size && e->offset && buflen >= e->size + e->offset) { ++ const XSaveXTILEDATA *tiledata = buf + e->offset; ++ ++ memcpy(&env->xtiledata, tiledata, sizeof(env->xtiledata)); ++ } + #endif + } +-- +2.35.3 + diff --git a/loongarch_bios.bin b/loongarch_bios.bin deleted file mode 100644 index 3aa4f36a853b0d605d6a6dd61d933fa43084c580..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4190208 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�`g?nIrVio3c^K4|e-Jn(WOFsaNIT$_= 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

`M8>h>T9UpW70pJ}{!e1h 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

hI^)cd=(ja+ZLc@t_so-0Z{BH9 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%0Dx>I}JdaouZ^+8ouz)5DddnTkZnR*QwPRO>E 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

    qCaZ_BO#EJE}oFo(?Z|w&f0H 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 diff --git a/loongarch_vars.bin b/loongarch_vars.bin deleted file mode 100644 index 65bdb77af90b92dc268c0c5c70c054dee71599f4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 389120 zcmeIuze+*@6bInbA98VUkd`K=h`TvRs~}|{)D)pZ4GBR@OHRsd5rT-OqN!Saf#@mf z2?AfC2k2hCx%LF|{e}bQoay(ily|GOxLK=3bfQv?`{XBo8r*dz B3V{Fs diff --git a/qemu-kvm.spec b/qemu-kvm.spec index 9743d6e..19bae57 100644 --- a/qemu-kvm.spec +++ b/qemu-kvm.spec @@ -1,4 +1,3 @@ -%define anolis_release .0.1 %global SLOF_gittagdate 20191022 %global SLOF_gittagcommit 899d9883 @@ -55,11 +54,7 @@ %ifarch aarch64 %global kvm_target aarch64 %endif -%ifarch loongarch64 - %global kvm_target loongarch64 - %global have_spice 1 - %global have_usbredir 1 -%endif + #Versions of various parts: %global requires_all_modules \ @@ -88,13 +83,13 @@ Obsoletes: %1-rhev <= %{epoch}:%{version}-%{release} Summary: QEMU is a machine emulator and virtualizer Name: qemu-kvm Version: 6.2.0 -Release: 11%{?rcrel}%{anolis_release}%{?dist}.6 +Release: 20%{?rcrel}%{?dist}.2 # Epoch because we pushed a qemu-1.0 package. AIUI this can't ever be dropped Epoch: 15 License: GPLv2 and GPLv2+ and CC-BY Group: Development/Tools URL: http://www.qemu.org/ -ExclusiveArch: x86_64 %{power64} aarch64 s390x loongarch64 +ExclusiveArch: x86_64 %{power64} aarch64 s390x Source0: http://wiki.qemu.org/download/qemu-6.2.0.tar.xz @@ -127,9 +122,6 @@ Source37: tests_data_acpi_pc_SSDT.dimmpxm Source38: tests_data_acpi_q35_FACP.slic Source39: tests_data_acpi_q35_SSDT.dimmpxm Source40: tests_data_acpi_virt_SSDT.memhp -Source41: loongarch_bios.bin -Source42: loongarch_vars.bin - Patch0001: 0001-redhat-Adding-slirp-to-the-exploded-tree.patch Patch0005: 0005-Initial-redhat-build.patch @@ -213,169 +205,234 @@ Patch52: kvm-iotests-281-Test-lingering-timers.patch Patch53: kvm-block-nbd-Move-s-ioc-on-AioContext-change.patch # For bz#2035185 - Qemu core dump when start guest with nbd node or do block jobs to nbd node Patch54: kvm-iotests-281-Let-NBD-connection-yield-in-iothread.patch -# For bz#2061856 - Revert IBM-specific Ubuntu-compatibility machine type for 8.6-AV GA +# For bz#2062613 - Revert IBM-specific Ubuntu-compatibility machine type for 8.6-AV GA [rhel-8.7.0] Patch55: kvm-Revert-redhat-Add-hw_compat_4_2_extra-and-apply-to-u.patch -# For bz#2061856 - Revert IBM-specific Ubuntu-compatibility machine type for 8.6-AV GA +# For bz#2062613 - Revert IBM-specific Ubuntu-compatibility machine type for 8.6-AV GA [rhel-8.7.0] Patch56: kvm-Revert-redhat-Enable-FDC-device-for-upstream-machine.patch -# For bz#2061856 - Revert IBM-specific Ubuntu-compatibility machine type for 8.6-AV GA +# For bz#2062613 - Revert IBM-specific Ubuntu-compatibility machine type for 8.6-AV GA [rhel-8.7.0] Patch57: kvm-Revert-redhat-Expose-upstream-machines-pc-4.2-and-pc.patch -# For bz#2027208 - [virtual network][vDPA] qemu crash after hot unplug vdpa device +# For bz#2060843 - [virtual network][vDPA] qemu crash after hot unplug vdpa device [rhel-8.7.0] Patch58: kvm-hw-virtio-vdpa-Fix-leak-of-host-notifier-memory-regi.patch -# For bz#2054597 - Do operation to disk will hang in the guest of target host after hotplugging and migrating +# For bz#2062610 - Do operation to disk will hang in the guest of target host after hotplugging and migrating [rhel-8.7.0] Patch59: kvm-pci-expose-TYPE_XIO3130_DOWNSTREAM-name.patch -# For bz#2054597 - Do operation to disk will hang in the guest of target host after hotplugging and migrating +# For bz#2062610 - Do operation to disk will hang in the guest of target host after hotplugging and migrating [rhel-8.7.0] Patch60: kvm-acpi-pcihp-pcie-set-power-on-cap-on-parent-slot.patch -# For bz#2056986 - Win11 (q35+edk2) guest broke after install wsl2 through 'wsl --install -d Ubuntu-20.04' +# For bz#2065207 - Win11 (q35+edk2) guest broke after install wsl2 through 'wsl --install -d Ubuntu-20.04' [rhel-8.7.0] Patch61: kvm-vmxcap-Add-5-level-EPT-bit.patch -# For bz#2056986 - Win11 (q35+edk2) guest broke after install wsl2 through 'wsl --install -d Ubuntu-20.04' +# For bz#2065207 - Win11 (q35+edk2) guest broke after install wsl2 through 'wsl --install -d Ubuntu-20.04' [rhel-8.7.0] Patch62: kvm-i386-Add-Icelake-Server-v6-CPU-model-with-5-level-EP.patch -# For bz#2059311 - Guest can not start with SLIC acpi table +# For bz#2062611 - Guest can not start with SLIC acpi table [rhel-8.7.0] Patch63: kvm-acpi-fix-QEMU-crash-when-started-with-SLIC-table.patch -# For bz#2059311 - Guest can not start with SLIC acpi table +# For bz#2062611 - Guest can not start with SLIC acpi table [rhel-8.7.0] Patch64: kvm-tests-acpi-whitelist-expected-blobs-before-changing-.patch -# For bz#2059311 - Guest can not start with SLIC acpi table +# For bz#2062611 - Guest can not start with SLIC acpi table [rhel-8.7.0] Patch65: kvm-tests-acpi-add-SLIC-table-test.patch -# For bz#2059311 - Guest can not start with SLIC acpi table +# For bz#2062611 - Guest can not start with SLIC acpi table [rhel-8.7.0] Patch66: kvm-tests-acpi-SLIC-update-expected-blobs.patch -# For bz#2059311 - Guest can not start with SLIC acpi table +# For bz#2062611 - Guest can not start with SLIC acpi table [rhel-8.7.0] Patch67: kvm-tests-acpi-manually-pad-OEM_ID-OEM_TABLE_ID-for-test.patch -# For bz#2059311 - Guest can not start with SLIC acpi table +# For bz#2062611 - Guest can not start with SLIC acpi table [rhel-8.7.0] Patch68: kvm-tests-acpi-whitelist-nvdimm-s-SSDT-and-FACP.slic-exp.patch -# For bz#2059311 - Guest can not start with SLIC acpi table +# For bz#2062611 - Guest can not start with SLIC acpi table [rhel-8.7.0] Patch69: kvm-acpi-fix-OEM-ID-OEM-Table-ID-padding.patch -# For bz#2059311 - Guest can not start with SLIC acpi table +# For bz#2062611 - Guest can not start with SLIC acpi table [rhel-8.7.0] Patch70: kvm-tests-acpi-update-expected-blobs.patch -# For bz#2059311 - Guest can not start with SLIC acpi table +# For bz#2062611 - Guest can not start with SLIC acpi table [rhel-8.7.0] Patch71: kvm-tests-acpi-test-short-OEM_ID-OEM_TABLE_ID-values-in-.patch -# For bz#1975840 - Windows guest hangs after updating and restarting from the guest OS -Patch72: kvm-target-i386-properly-reset-TSC-on-reset.patch -# For bz#2071103 - RHEL 9.0 guest with vsock device migration failed from RHEL 9.0 > RHEL 8.6 [rhel-8.6.0.z] -Patch73: kvm-RHEL-disable-seqpacket-for-vhost-vsock-device-in-rhe.patch -# For bz#2075686 - CVE-2021-3750 virt:rhel/qemu-kvm: QEMU: hcd-ehci: DMA reentrancy issue leads to use-after-free [rhel-8] [rhel-8.6.0.z] -Patch74: kvm-hw-intc-arm_gicv3-Check-for-MEMTX_OK-instead-of-MEMT.patch -# For bz#2075686 - CVE-2021-3750 virt:rhel/qemu-kvm: QEMU: hcd-ehci: DMA reentrancy issue leads to use-after-free [rhel-8] [rhel-8.6.0.z] -Patch75: kvm-softmmu-physmem-Simplify-flatview_write-and-address_.patch -# For bz#2075686 - CVE-2021-3750 virt:rhel/qemu-kvm: QEMU: hcd-ehci: DMA reentrancy issue leads to use-after-free [rhel-8] [rhel-8.6.0.z] -Patch76: kvm-softmmu-physmem-Introduce-MemTxAttrs-memory-field-an.patch -# For bz#2075683 - CVE-2021-4207 virt:rhel/qemu-kvm: QEMU: QXL: double fetch in qxl_cursor() can lead to heap buffer overflow [rhel-8] [rhel-8.6.0.z] -Patch77: kvm-display-qxl-render-fix-race-condition-in-qxl_cursor-.patch -# For bz#2075637 - CVE-2022-26353 virt:rhel/qemu-kvm: QEMU: virtio-net: map leaking on error during receive [rhel-8] [rhel-8.6.0.z] -Patch78: kvm-virtio-net-fix-map-leaking-on-error-during-receive.patch -# For bz#2075639 - CVE-2022-26354 virt:rhel/qemu-kvm: QEMU: vhost-vsock: missing virtqueue detach on error can lead to memory leak [rhel-8] [rhel-8.6.0.z] -Patch79: kvm-vhost-vsock-detach-the-virqueue-element-in-case-of-e.patch -# For bz#2072242 - Fail to rebuild the reference count tables of qcow2 image on host block devices (e.g. LVs) [rhel-8.6.0.z] -Patch80: kvm-qcow2-Improve-refcount-structure-rebuilding.patch -# For bz#2072242 - Fail to rebuild the reference count tables of qcow2 image on host block devices (e.g. LVs) [rhel-8.6.0.z] -Patch81: kvm-iotests-108-Test-new-refcount-rebuild-algorithm.patch -# For bz#2072242 - Fail to rebuild the reference count tables of qcow2 image on host block devices (e.g. LVs) [rhel-8.6.0.z] -Patch82: kvm-qcow2-Add-errp-to-rebuild_refcount_structure.patch -# For bz#2072242 - Fail to rebuild the reference count tables of qcow2 image on host block devices (e.g. LVs) [rhel-8.6.0.z] -Patch83: kvm-iotests-108-Fix-when-missing-user_allow_other.patch -# For bz#2077928 - Remove upstream-only devices from the qemu-kvm binary [rhel-8.6.0.z] -Patch84: kvm-Revert-redhat-Add-some-devices-for-exporting-upstrea.patch -# For bz#2082622 - CVE-2021-4206 virt:rhel/qemu-kvm: QEMU: QXL: integer overflow in cursor_alloc() can lead to heap buffer overflow [rhel-8.6.0.z] -Patch85: kvm-ui-cursor-fix-integer-overflow-in-cursor_alloc-CVE-2.patch -# For bz#2095794 - PXE boot crash qemu when using multiqueue vDPA [rhel-8.6.0.z] -Patch86: kvm-virtio-net-setup-vhost_dev-and-notifiers-for-cvq-onl.patch -# For bz#2095794 - PXE boot crash qemu when using multiqueue vDPA [rhel-8.6.0.z] -Patch87: kvm-virtio-net-align-ctrl_vq-index-for-non-mq-guest-for-.patch -# For bz#2095794 - PXE boot crash qemu when using multiqueue vDPA [rhel-8.6.0.z] -Patch88: kvm-vhost-vdpa-fix-improper-cleanup-in-net_init_vhost_vd.patch -# For bz#2095794 - PXE boot crash qemu when using multiqueue vDPA [rhel-8.6.0.z] -Patch89: kvm-vhost-net-fix-improper-cleanup-in-vhost_net_start.patch -# For bz#2095794 - PXE boot crash qemu when using multiqueue vDPA [rhel-8.6.0.z] -Patch90: kvm-vhost-vdpa-backend-feature-should-set-only-once.patch -# For bz#2095794 - PXE boot crash qemu when using multiqueue vDPA [rhel-8.6.0.z] -Patch91: kvm-vhost-vdpa-change-name-and-polarity-for-vhost_vdpa_o.patch -# For bz#2095794 - PXE boot crash qemu when using multiqueue vDPA [rhel-8.6.0.z] -Patch92: kvm-virtio-net-don-t-handle-mq-request-in-userspace-hand.patch -# For bz#2117252 - Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8 [rhel-8.6.0.z] -Patch93: kvm-migration-Never-call-twice-qemu_target_page_size.patch -# For bz#2117252 - Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8 [rhel-8.6.0.z] -Patch94: kvm-multifd-Rename-used-field-to-num.patch -# For bz#2117252 - Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8 [rhel-8.6.0.z] -Patch95: kvm-multifd-Add-missing-documention.patch -# For bz#2117252 - Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8 [rhel-8.6.0.z] -Patch96: kvm-multifd-The-variable-is-only-used-inside-the-loop.patch -# For bz#2117252 - Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8 [rhel-8.6.0.z] -Patch97: kvm-multifd-remove-used-parameter-from-send_prepare-meth.patch -# For bz#2117252 - Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8 [rhel-8.6.0.z] -Patch98: kvm-multifd-remove-used-parameter-from-send_recv_pages-m.patch -# For bz#2117252 - Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8 [rhel-8.6.0.z] -Patch99: kvm-multifd-Fill-offset-and-block-for-reception.patch -# For bz#2117252 - Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8 [rhel-8.6.0.z] -Patch100: kvm-multifd-Make-zstd-compression-method-not-use-iovs.patch -# For bz#2117252 - Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8 [rhel-8.6.0.z] -Patch101: kvm-multifd-Make-zlib-compression-method-not-use-iovs.patch -# For bz#2117252 - Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8 [rhel-8.6.0.z] -Patch102: kvm-migration-All-this-fields-are-unsigned.patch -# For bz#2117252 - Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8 [rhel-8.6.0.z] -Patch103: kvm-multifd-Move-iov-from-pages-to-params.patch -# For bz#2117252 - Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8 [rhel-8.6.0.z] -Patch104: kvm-multifd-Make-zlib-use-iov-s.patch -# For bz#2117252 - Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8 [rhel-8.6.0.z] -Patch105: kvm-multifd-Make-zstd-use-iov-s.patch -# For bz#2117252 - Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8 [rhel-8.6.0.z] -Patch106: kvm-multifd-Remove-send_write-method.patch -# For bz#2117252 - Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8 [rhel-8.6.0.z] -Patch107: kvm-multifd-Use-a-single-writev-on-the-send-side.patch -# For bz#2117252 - Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8 [rhel-8.6.0.z] -Patch108: kvm-multifd-Use-normal-pages-array-on-the-send-side.patch -# For bz#2117252 - Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8 [rhel-8.6.0.z] -Patch109: kvm-QIOChannel-Add-flags-on-io_writev-and-introduce-io_f.patch -# For bz#2117252 - Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8 [rhel-8.6.0.z] -Patch110: kvm-QIOChannelSocket-Implement-io_writev-zero-copy-flag-.patch -# For bz#2117252 - Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8 [rhel-8.6.0.z] -Patch111: kvm-migration-Add-zero-copy-send-parameter-for-QMP-HMP-f.patch -# For bz#2117252 - Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8 [rhel-8.6.0.z] -Patch112: kvm-migration-Add-migrate_use_tls-helper.patch -# For bz#2117252 - Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8 [rhel-8.6.0.z] -Patch113: kvm-multifd-multifd_send_sync_main-now-returns-negative-.patch -# For bz#2117252 - Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8 [rhel-8.6.0.z] -Patch114: kvm-multifd-Send-header-packet-without-flags-if-zero-cop.patch -# For bz#2117252 - Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8 [rhel-8.6.0.z] -Patch115: kvm-multifd-Implement-zero-copy-write-in-multifd-migrati.patch -# For bz#2117252 - Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8 [rhel-8.6.0.z] -Patch116: kvm-QIOChannelSocket-Introduce-assert-and-reduce-ifdefs-.patch -# For bz#2117252 - Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8 [rhel-8.6.0.z] -Patch117: kvm-QIOChannelSocket-Fix-zero-copy-send-so-socket-flush-.patch -# For bz#2117252 - Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8 [rhel-8.6.0.z] -Patch118: kvm-migration-Change-zero_copy_send-from-migration-param.patch -# For bz#2117252 - Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8 [rhel-8.6.0.z] -Patch119: kvm-migration-Introduce-ram_transferred_add.patch -# For bz#2117252 - Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8 [rhel-8.6.0.z] -Patch120: kvm-migration-Tally-pre-copy-downtime-and-post-copy-byte.patch -# For bz#2117252 - Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8 [rhel-8.6.0.z] -Patch121: kvm-QIOChannelSocket-Fix-zero-copy-flush-returning-code-.patch -# For bz#2117252 - Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8 [rhel-8.6.0.z] -Patch122: kvm-Add-dirty-sync-missed-zero-copy-migration-stat.patch -# For bz#2117252 - Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8 [rhel-8.6.0.z] -Patch123: kvm-migration-multifd-Report-to-user-when-zerocopy-not-w.patch -# For bz#2117252 - Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8 [rhel-8.6.0.z] -Patch124: kvm-migration-Avoid-false-positive-on-non-supported-scen.patch -# For bz#2117252 - Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8 [rhel-8.6.0.z] -Patch125: kvm-migration-add-remaining-params-has_-true-in-migratio.patch -# For bz#2117252 - Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8 [rhel-8.6.0.z] -Patch126: kvm-QIOChannelSocket-Add-support-for-MSG_ZEROCOPY-IPV6.patch -# For bz#2109570 - Stalled IO Operations in VM [rhel-8.6.0.z] -Patch127: kvm-linux-aio-fix-unbalanced-plugged-counter-in-laio_io_.patch -# For bz#2109570 - Stalled IO Operations in VM [rhel-8.6.0.z] -Patch128: kvm-linux-aio-explain-why-max-batch-is-checked-in-laio_i.patch -# For bz#2121783 - Wrong max_sectors_kb and Maximum transfer length on the pass-through device [rhel-8.7] [rhel-8.6.0.z] -Patch129: kvm-scsi-generic-Fix-emulated-block-limits-VPD-page.patch - - -Patch1000: kvm-virtiofsd-Adjust-limit-for-minor-version.patch - -Patch1001: 0001-Add-Acpi-support.patch -Patch1002: 0002-Support-rtc.patch -Patch1003: 0003-Add-loongarch-machine.patch -Patch1004: 0004-Add-target-loongarch64.patch -Patch1005: 0005-Add-linux-headers-and-linux-user.patch -Patch1006: 0006-Add-disas-gdb.patch -Patch1007: 0007-Modify-kvm-cpu-vga-qapi.patch -Patch1008: 0008-Modify-compile-script.patch -Patch1009: 0009-Add-loongarch64-rh-devices.mak.patch +# For bz#2068202 - RHEL 9.0 guest with vsock device migration failed from RHEL 9.0 > RHEL 8.6 [rhel-8.7.0] +Patch72: kvm-RHEL-disable-seqpacket-for-vhost-vsock-device-in-rhe.patch +# For bz#2067118 - qemu crash after execute blockdev-reopen with iothread +Patch73: kvm-block-Lock-AioContext-for-drain_end-in-blockdev-reop.patch +# For bz#2067118 - qemu crash after execute blockdev-reopen with iothread +Patch74: kvm-iotests-Test-blockdev-reopen-with-iothreads-and-thro.patch +# For bz#2071070 - s390x/css: fix PMCW invalid mask +Patch75: kvm-s390x-css-fix-PMCW-invalid-mask.patch +# For bz#1999236 - CVE-2021-3750 virt:rhel/qemu-kvm: QEMU: hcd-ehci: DMA reentrancy issue leads to use-after-free [rhel-8] +Patch76: kvm-hw-intc-arm_gicv3-Check-for-MEMTX_OK-instead-of-MEMT.patch +# For bz#1999236 - CVE-2021-3750 virt:rhel/qemu-kvm: QEMU: hcd-ehci: DMA reentrancy issue leads to use-after-free [rhel-8] +Patch77: kvm-softmmu-physmem-Simplify-flatview_write-and-address_.patch +# For bz#1999236 - CVE-2021-3750 virt:rhel/qemu-kvm: QEMU: hcd-ehci: DMA reentrancy issue leads to use-after-free [rhel-8] +Patch78: kvm-softmmu-physmem-Introduce-MemTxAttrs-memory-field-an.patch +# For bz#2040738 - CVE-2021-4207 virt:rhel/qemu-kvm: QEMU: QXL: double fetch in qxl_cursor() can lead to heap buffer overflow [rhel-8] +Patch79: kvm-display-qxl-render-fix-race-condition-in-qxl_cursor-.patch +# For bz#2063262 - CVE-2022-26354 virt:rhel/qemu-kvm: QEMU: vhost-vsock: missing virtqueue detach on error can lead to memory leak [rhel-8] +Patch80: kvm-vhost-vsock-detach-the-virqueue-element-in-case-of-e.patch +# For bz#2043830 - [IBM 8.7 FEAT] KVM: Allow long kernel command lines for QEMU +Patch81: kvm-s390x-ipl-support-extended-kernel-command-line-size.patch +# For bz#2063206 - CVE-2022-26353 virt:rhel/qemu-kvm: QEMU: virtio-net: map leaking on error during receive [rhel-8] +Patch82: kvm-virtio-net-fix-map-leaking-on-error-during-receive.patch +# For bz#1519071 - Fail to rebuild the reference count tables of qcow2 image on host block devices (e.g. LVs) +Patch83: kvm-qcow2-Improve-refcount-structure-rebuilding.patch +# For bz#1519071 - Fail to rebuild the reference count tables of qcow2 image on host block devices (e.g. LVs) +Patch84: kvm-iotests-108-Test-new-refcount-rebuild-algorithm.patch +# For bz#1519071 - Fail to rebuild the reference count tables of qcow2 image on host block devices (e.g. LVs) +Patch85: kvm-qcow2-Add-errp-to-rebuild_refcount_structure.patch +# For bz#1519071 - Fail to rebuild the reference count tables of qcow2 image on host block devices (e.g. LVs) +Patch86: kvm-iotests-108-Fix-when-missing-user_allow_other.patch +# For bz#2065043 - Remove upstream-only devices from the qemu-kvm binary +Patch87: kvm-Revert-redhat-Add-some-devices-for-exporting-upstrea.patch +# For bz#2070417 - Windows guest hangs after updating and restarting from the guest OS [rhel-8.7.0] +Patch88: kvm-target-i386-properly-reset-TSC-on-reset.patch +# For bz#2040734 - CVE-2021-4206 virt:rhel/qemu-kvm: QEMU: QXL: integer overflow in cursor_alloc() can lead to heap buffer overflow [rhel-8.7] +Patch89: kvm-ui-cursor-fix-integer-overflow-in-cursor_alloc-CVE-2.patch +# For bz#1916415 - [Intel 8.7 FEAT] qemu-kvm Sapphire Rapids (SPR) AMX Instructions +Patch90: kvm-virtio-gpu-do-not-byteswap-padding.patch +# For bz#1916415 - [Intel 8.7 FEAT] qemu-kvm Sapphire Rapids (SPR) AMX Instructions +Patch91: kvm-linux-headers-update-to-5.16-rc1.patch +# For bz#1916415 - [Intel 8.7 FEAT] qemu-kvm Sapphire Rapids (SPR) AMX Instructions +Patch92: kvm-linux-headers-Update-headers-to-v5.17-rc1.patch +# For bz#1916415 - [Intel 8.7 FEAT] qemu-kvm Sapphire Rapids (SPR) AMX Instructions +Patch93: kvm-linux-headers-include-missing-changes-from-5.17.patch +# For bz#1916415 - [Intel 8.7 FEAT] qemu-kvm Sapphire Rapids (SPR) AMX Instructions +Patch94: kvm-x86-Fix-the-64-byte-boundary-enumeration-for-extende.patch +# For bz#1916415 - [Intel 8.7 FEAT] qemu-kvm Sapphire Rapids (SPR) AMX Instructions +Patch95: kvm-x86-Add-AMX-XTILECFG-and-XTILEDATA-components.patch +# For bz#1916415 - [Intel 8.7 FEAT] qemu-kvm Sapphire Rapids (SPR) AMX Instructions +Patch96: kvm-x86-Grant-AMX-permission-for-guest.patch +# For bz#1916415 - [Intel 8.7 FEAT] qemu-kvm Sapphire Rapids (SPR) AMX Instructions +Patch97: kvm-x86-Add-XFD-faulting-bit-for-state-components.patch +# For bz#1916415 - [Intel 8.7 FEAT] qemu-kvm Sapphire Rapids (SPR) AMX Instructions +Patch98: kvm-x86-Add-AMX-CPUIDs-enumeration.patch +# For bz#1916415 - [Intel 8.7 FEAT] qemu-kvm Sapphire Rapids (SPR) AMX Instructions +Patch99: kvm-x86-add-support-for-KVM_CAP_XSAVE2-and-AMX-state-mig.patch +# For bz#1916415 - [Intel 8.7 FEAT] qemu-kvm Sapphire Rapids (SPR) AMX Instructions +Patch100: kvm-x86-Support-XFD-and-AMX-xsave-data-migration.patch +# For bz#1916415 - [Intel 8.7 FEAT] qemu-kvm Sapphire Rapids (SPR) AMX Instructions +Patch101: kvm-target-i386-kvm-do-not-access-uninitialized-variable.patch +# For bz#1916415 - [Intel 8.7 FEAT] qemu-kvm Sapphire Rapids (SPR) AMX Instructions +Patch102: kvm-KVM-x86-workaround-invalid-CPUID-0xD-9-info-on-some-.patch +# For bz#2069946 - PXE boot crash qemu when using multiqueue vDPA +Patch103: kvm-virtio-net-setup-vhost_dev-and-notifiers-for-cvq-onl.patch +# For bz#2069946 - PXE boot crash qemu when using multiqueue vDPA +Patch104: kvm-virtio-net-align-ctrl_vq-index-for-non-mq-guest-for-.patch +# For bz#2069946 - PXE boot crash qemu when using multiqueue vDPA +Patch105: kvm-vhost-vdpa-fix-improper-cleanup-in-net_init_vhost_vd.patch +# For bz#2069946 - PXE boot crash qemu when using multiqueue vDPA +Patch106: kvm-vhost-net-fix-improper-cleanup-in-vhost_net_start.patch +# For bz#2069946 - PXE boot crash qemu when using multiqueue vDPA +Patch107: kvm-vhost-vdpa-backend-feature-should-set-only-once.patch +# For bz#2069946 - PXE boot crash qemu when using multiqueue vDPA +Patch108: kvm-vhost-vdpa-change-name-and-polarity-for-vhost_vdpa_o.patch +# For bz#2069946 - PXE boot crash qemu when using multiqueue vDPA +Patch109: kvm-virtio-net-don-t-handle-mq-request-in-userspace-hand.patch +# For bz#2029980 - Failed assertion in IDE emulation with Ceph backend +Patch110: kvm-ide-Increment-BB-in-flight-counter-for-TRIM-BH.patch +# For bz#2072932 - Qemu coredump when refreshing block limits on an actively used iothread block device [rhel.8.7] +Patch111: kvm-block-Make-bdrv_refresh_limits-non-recursive.patch +# For bz#2072932 - Qemu coredump when refreshing block limits on an actively used iothread block device [rhel.8.7] +Patch112: kvm-iotests-Allow-using-QMP-with-the-QSD.patch +# For bz#2072932 - Qemu coredump when refreshing block limits on an actively used iothread block device [rhel.8.7] +Patch113: kvm-iotests-graph-changes-while-io-New-test.patch +# For bz#2097209 - [virtiofs] mount virtiofs failed: SELinux: (dev virtiofs, type virtiofs) getxattr errno 111 +Patch114: kvm-virtiofsd-Fix-breakage-due-to-fuse_init_in-size-chan.patch +# For bz#1951521 - CVE-2021-3507 virt:rhel/qemu-kvm: QEMU: fdc: heap buffer overflow in DMA read data transfers [rhel-8] +Patch115: kvm-hw-block-fdc-Prevent-end-of-track-overrun-CVE-2021-3.patch +# For bz#1951521 - CVE-2021-3507 virt:rhel/qemu-kvm: QEMU: fdc: heap buffer overflow in DMA read data transfers [rhel-8] +Patch116: kvm-tests-qtest-fdc-test-Add-a-regression-test-for-CVE-2.patch +# For bz#2072049 - Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8 +Patch117: kvm-migration-Never-call-twice-qemu_target_page_size.patch +# For bz#2072049 - Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8 +Patch118: kvm-multifd-Rename-used-field-to-num.patch +# For bz#2072049 - Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8 +Patch119: kvm-multifd-Add-missing-documentation.patch +# For bz#2072049 - Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8 +Patch120: kvm-multifd-The-variable-is-only-used-inside-the-loop.patch +# For bz#2072049 - Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8 +Patch121: kvm-multifd-remove-used-parameter-from-send_prepare-meth.patch +# For bz#2072049 - Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8 +Patch122: kvm-multifd-remove-used-parameter-from-send_recv_pages-m.patch +# For bz#2072049 - Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8 +Patch123: kvm-multifd-Fill-offset-and-block-for-reception.patch +# For bz#2072049 - Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8 +Patch124: kvm-multifd-Make-zstd-compression-method-not-use-iovs.patch +# For bz#2072049 - Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8 +Patch125: kvm-multifd-Make-zlib-compression-method-not-use-iovs.patch +# For bz#2072049 - Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8 +Patch126: kvm-migration-All-this-fields-are-unsigned.patch +# For bz#2072049 - Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8 +Patch127: kvm-multifd-Move-iov-from-pages-to-params.patch +# For bz#2072049 - Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8 +Patch128: kvm-multifd-Make-zlib-use-iov-s.patch +# For bz#2072049 - Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8 +Patch129: kvm-multifd-Make-zstd-use-iov-s.patch +# For bz#2072049 - Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8 +Patch130: kvm-multifd-Remove-send_write-method.patch +# For bz#2072049 - Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8 +Patch131: kvm-multifd-Use-a-single-writev-on-the-send-side.patch +# For bz#2072049 - Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8 +Patch132: kvm-multifd-Use-normal-pages-array-on-the-send-side.patch +# For bz#2072049 - Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8 +Patch133: kvm-QIOChannel-Add-flags-on-io_writev-and-introduce-io_f.patch +# For bz#2072049 - Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8 +Patch134: kvm-QIOChannelSocket-Implement-io_writev-zero-copy-flag-.patch +# For bz#2072049 - Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8 +Patch135: kvm-migration-Add-zero-copy-send-parameter-for-QMP-HMP-f.patch +# For bz#2072049 - Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8 +Patch136: kvm-migration-Add-migrate_use_tls-helper.patch +# For bz#2072049 - Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8 +Patch137: kvm-multifd-multifd_send_sync_main-now-returns-negative-.patch +# For bz#2072049 - Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8 +Patch138: kvm-multifd-Send-header-packet-without-flags-if-zero-cop.patch +# For bz#2072049 - Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8 +Patch139: kvm-multifd-Implement-zero-copy-write-in-multifd-migrati.patch +# For bz#2072049 - Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8 +Patch140: kvm-QIOChannelSocket-Introduce-assert-and-reduce-ifdefs-.patch +# For bz#2072049 - Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8 +Patch141: kvm-QIOChannelSocket-Fix-zero-copy-send-so-socket-flush-.patch +# For bz#2072049 - Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8 +Patch142: kvm-migration-Change-zero_copy_send-from-migration-param.patch +# For bz#2097652 - The migration port is not released if use it again for recovering postcopy migration +Patch143: kvm-migration-Add-migration_incoming_transport_cleanup.patch +# For bz#2097652 - The migration port is not released if use it again for recovering postcopy migration +Patch144: kvm-migration-Allow-migrate-recover-to-run-multiple-time.patch +# For bz#2098076 - virtio-blk: Can't boot fresh installation from used virtio-blk dasd disk under certain conditions +Patch145: kvm-pc-bios-s390-ccw-virtio-Introduce-a-macro-for-the-DA.patch +# For bz#2098076 - virtio-blk: Can't boot fresh installation from used virtio-blk dasd disk under certain conditions +Patch146: kvm-pc-bios-s390-ccw-bootmap-Improve-the-guessing-logic-.patch +# For bz#2098076 - virtio-blk: Can't boot fresh installation from used virtio-blk dasd disk under certain conditions +Patch147: kvm-pc-bios-s390-ccw-virtio-blkdev-Simplify-fix-virtio_i.patch +# For bz#2098076 - virtio-blk: Can't boot fresh installation from used virtio-blk dasd disk under certain conditions +Patch148: kvm-pc-bios-s390-ccw-virtio-blkdev-Remove-virtio_assume_.patch +# For bz#2098076 - virtio-blk: Can't boot fresh installation from used virtio-blk dasd disk under certain conditions +Patch149: kvm-pc-bios-s390-ccw-virtio-Set-missing-status-bits-whil.patch +# For bz#2098076 - virtio-blk: Can't boot fresh installation from used virtio-blk dasd disk under certain conditions +Patch150: kvm-pc-bios-s390-ccw-virtio-Read-device-config-after-fea.patch +# For bz#2098076 - virtio-blk: Can't boot fresh installation from used virtio-blk dasd disk under certain conditions +Patch151: kvm-pc-bios-s390-ccw-virtio-Beautify-the-code-for-readin.patch +# For bz#2098076 - virtio-blk: Can't boot fresh installation from used virtio-blk dasd disk under certain conditions +Patch152: kvm-pc-bios-s390-ccw-Split-virtio-scsi-code-from-virtio_.patch +# For bz#2098076 - virtio-blk: Can't boot fresh installation from used virtio-blk dasd disk under certain conditions +Patch153: kvm-pc-bios-s390-ccw-virtio-blkdev-Request-the-right-fea.patch +# For bz#2105410 - Stalled IO Operations in VM +Patch154: kvm-linux-aio-fix-unbalanced-plugged-counter-in-laio_io_.patch +# For bz#2105410 - Stalled IO Operations in VM +Patch155: kvm-linux-aio-explain-why-max-batch-is-checked-in-laio_i.patch +# For bz#2110203 - zerocopy capability can be enabled when set migrate capabilities with multifd and compress/xbzrle together +Patch156: kvm-migration-Introduce-ram_transferred_add.patch +# For bz#2110203 - zerocopy capability can be enabled when set migrate capabilities with multifd and compress/xbzrle together +Patch157: kvm-migration-Tally-pre-copy-downtime-and-post-copy-byte.patch +# For bz#2110203 - zerocopy capability can be enabled when set migrate capabilities with multifd and compress/xbzrle together +Patch158: kvm-QIOChannelSocket-Fix-zero-copy-flush-returning-code-.patch +# For bz#2110203 - zerocopy capability can be enabled when set migrate capabilities with multifd and compress/xbzrle together +Patch159: kvm-Add-dirty-sync-missed-zero-copy-migration-stat.patch +# For bz#2110203 - zerocopy capability can be enabled when set migrate capabilities with multifd and compress/xbzrle together +Patch160: kvm-migration-multifd-Report-to-user-when-zerocopy-not-w.patch +# For bz#2110203 - zerocopy capability can be enabled when set migrate capabilities with multifd and compress/xbzrle together +Patch161: kvm-migration-Avoid-false-positive-on-non-supported-scen.patch +# For bz#2110203 - zerocopy capability can be enabled when set migrate capabilities with multifd and compress/xbzrle together +Patch162: kvm-migration-add-remaining-params-has_-true-in-migratio.patch +# For bz#2110203 - zerocopy capability can be enabled when set migrate capabilities with multifd and compress/xbzrle together +Patch163: kvm-QIOChannelSocket-Add-support-for-MSG_ZEROCOPY-IPV6.patch +# For bz#2112296 - virtio-blk: Can't boot fresh installation from used 512 cluster_size image under certain conditions +Patch164: kvm-pc-bios-s390-ccw-Fix-booting-with-logical-block-size.patch +# For bz#2120279 - Wrong max_sectors_kb and Maximum transfer length on the pass-through device [rhel-8.7] +Patch165: kvm-scsi-generic-Fix-emulated-block-limits-VPD-page.patch +# For bz#2116743 - [RHEL8.7] Guests in VMX root operation fail to reboot with QEMU's 'system_reset' command +Patch166: kvm-i386-reset-KVM-nested-state-upon-CPU-reset.patch +# For bz#2116743 - [RHEL8.7] Guests in VMX root operation fail to reboot with QEMU's 'system_reset' command +Patch167: kvm-i386-do-kvm_put_msr_feature_control-first-thing-when.patch +# For bz#2132391 - [virtiofs] virtiofsd debug log's timestamp is NULL [rhel-8.7.0.z] +Patch168: kvm-virtiofsd-use-g_date_time_get_microsecond-to-get-sub.patch BuildRequires: wget BuildRequires: rpm-build @@ -565,7 +622,7 @@ Requires(postun): systemd-units Requires: seabios-bin >= 1.10.2-1 Requires: sgabios-bin %endif -%ifnarch aarch64 s390x loongarch64 +%ifnarch aarch64 s390x Requires: seavgabios-bin >= 1.12.0-3 Requires: ipxe-roms-qemu >= 20170123-1 %endif @@ -704,11 +761,9 @@ rm -fr slirp mkdir slirp %autopatch -p1 -cp %{SOURCE41} ./pc-bios/ -f -cp %{SOURCE42} ./pc-bios/ -f - %global qemu_kvm_build qemu_kvm_build mkdir -p %{qemu_kvm_build} + cp -f %{SOURCE37} tests/data/acpi/pc/SSDT.dimmpxm cp -f %{SOURCE38} tests/data/acpi/q35/FACP.slic cp -f %{SOURCE39} tests/data/acpi/q35/SSDT.dimmpxm @@ -1035,7 +1090,7 @@ cp -R tests/avocado/* $RPM_BUILD_ROOT%{testsdir}/tests/avocado/ # Install qemu.py and qmp/ scripts required to run avocado_qemu tests cp -R python/qemu $RPM_BUILD_ROOT%{testsdir}/python cp -R scripts/qmp/* $RPM_BUILD_ROOT%{testsdir}/scripts/qmp -install -p -m 0755 ../tests/Makefile.include $RPM_BUILD_ROOT%{testsdir}/tests/ +install -p -m 0644 ../tests/Makefile.include $RPM_BUILD_ROOT%{testsdir}/tests/ # Install qemu-iotests cp -R ../tests/qemu-iotests/* $RPM_BUILD_ROOT%{testsdir}/tests/qemu-iotests/ @@ -1134,7 +1189,7 @@ install -D -p -m 0644 ../qemu.sasl $RPM_BUILD_ROOT%{_sysconfdir}/sasl2/%{name}.c # Install keymaps pushd pc-bios/keymaps for kmp in *; do - install $kmp ${RPM_BUILD_ROOT}%{_datadir}/%{name}/keymaps/ + install -m 0644 $kmp ${RPM_BUILD_ROOT}%{_datadir}/%{name}/keymaps/ done rm -f ${RPM_BUILD_ROOT}%{_datadir}/%{name}/keymaps/*.stamp popd @@ -1175,8 +1230,6 @@ rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{name}/opensbi-riscv64-virt-fw_jump.bin rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{name}/opensbi-riscv64-generic-fw_dynamic.* rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{name}/qemu-nsis.bmp rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{name}/npcm7xx_bootrom.bin -rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{name}/loongarch_bios.bin -rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{name}/loongarch_vars.bin rm -rf ${RPM_BUILD_ROOT}%{_libdir}/qemu-kvm/ui-spice-app.so @@ -1192,11 +1245,6 @@ rm -rf ${RPM_BUILD_ROOT}%{_mandir}/man1/virtfs-proxy-helper* rm -rf ${RPM_BUILD_ROOT}%{_libdir}/qemu-kvm/hw-s390x-virtio-gpu-ccw.so %endif -%ifarch loongarch64 - install -m 0644 pc-bios/loongarch_bios.bin $RPM_BUILD_ROOT%{_datadir}/%{name}/ - install -m 0644 pc-bios/loongarch_vars.bin $RPM_BUILD_ROOT%{_datadir}/%{name}/ -%endif - %ifnarch x86_64 rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{name}/kvmvapic.bin rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{name}/linuxboot.bin @@ -1298,12 +1346,10 @@ rm -rf $RPM_BUILD_ROOT%{qemudocdir}/specs popd %check -%ifnarch loongarch64 pushd %{qemu_kvm_build} echo "Testing qemu-kvm-build" export DIFF=diff; make check V=1 popd -%endif %post -n qemu-kvm-common %systemd_post ksm.service @@ -1424,10 +1470,6 @@ sh %{_sysconfdir}/sysconfig/modules/kvm.modules &> /dev/null || : %{_datadir}/%{name}/s390-ccw.img %{_datadir}/%{name}/s390-netboot.img %endif -%ifarch loongarch64 - %{_datadir}/%{name}/loongarch_bios.bin - %{_datadir}/%{name}/loongarch_vars.bin -%endif %ifnarch aarch64 s390x %{_datadir}/%{name}/vgabios.bin %{_datadir}/%{name}/vgabios-cirrus.bin @@ -1449,7 +1491,7 @@ sh %{_sysconfdir}/sysconfig/modules/kvm.modules &> /dev/null || : %ifnarch s390x %{_libdir}/%{name}/hw-display-virtio-gpu-pci-gl.so %endif -%ifarch x86_64 %{power64} loongarch64 +%ifarch x86_64 %{power64} %{_libdir}/%{name}/hw-display-virtio-vga-gl.so %endif %{_libdir}/%{name}/accel-qtest-%{kvm_target}.so @@ -1542,7 +1584,7 @@ sh %{_sysconfdir}/sysconfig/modules/kvm.modules &> /dev/null || : %{_libdir}/qemu-kvm/audio-spice.so %{_libdir}/qemu-kvm/ui-spice-core.so %{_libdir}/qemu-kvm/chardev-spice.so -%ifarch x86_64 loongarch64 +%ifarch x86_64 %{_libdir}/qemu-kvm/hw-display-qxl.so %endif %endif @@ -1560,139 +1602,215 @@ sh %{_sysconfdir}/sysconfig/modules/kvm.modules &> /dev/null || : %changelog -* Fri Oct 28 2022 Bo Ren - 6.2.0-11.0.1.6 -- Adjust limit for virtiofsd minor version (jacob.wang@openanolis.org) -- Add loongarch supporti (lixianglai@loongson.cn) - -* Thu Sep 01 2022 Jon Maloy - 6.2.0-11.el8_6.6 -- kvm-scsi-generic-Fix-emulated-block-limits-VPD-page.patch [bz#2121783] -- Resolves: bz#2121783 - (Wrong max_sectors_kb and Maximum transfer length on the pass-through device [rhel-8.7] [rhel-8.6.0.z]) - -* Mon Aug 29 2022 Jon Maloy - 6.2.0-11.el8_6.5 -- kvm-linux-aio-fix-unbalanced-plugged-counter-in-laio_io_.patch [bz#2109570] -- kvm-linux-aio-explain-why-max-batch-is-checked-in-laio_i.patch [bz#2109570] -- Resolves: bz#2109570 - (Stalled IO Operations in VM [rhel-8.6.0.z]) - -* Tue Aug 16 2022 Jon Maloy - 6.2.0-11.el8_6.4 -- kvm-migration-Never-call-twice-qemu_target_page_size.patch [bz#2117252] -- kvm-multifd-Rename-used-field-to-num.patch [bz#2117252] -- kvm-multifd-Add-missing-documention.patch [bz#2117252] -- kvm-multifd-The-variable-is-only-used-inside-the-loop.patch [bz#2117252] -- kvm-multifd-remove-used-parameter-from-send_prepare-meth.patch [bz#2117252] -- kvm-multifd-remove-used-parameter-from-send_recv_pages-m.patch [bz#2117252] -- kvm-multifd-Fill-offset-and-block-for-reception.patch [bz#2117252] -- kvm-multifd-Make-zstd-compression-method-not-use-iovs.patch [bz#2117252] -- kvm-multifd-Make-zlib-compression-method-not-use-iovs.patch [bz#2117252] -- kvm-migration-All-this-fields-are-unsigned.patch [bz#2117252] -- kvm-multifd-Move-iov-from-pages-to-params.patch [bz#2117252] -- kvm-multifd-Make-zlib-use-iov-s.patch [bz#2117252] -- kvm-multifd-Make-zstd-use-iov-s.patch [bz#2117252] -- kvm-multifd-Remove-send_write-method.patch [bz#2117252] -- kvm-multifd-Use-a-single-writev-on-the-send-side.patch [bz#2117252] -- kvm-multifd-Use-normal-pages-array-on-the-send-side.patch [bz#2117252] -- kvm-QIOChannel-Add-flags-on-io_writev-and-introduce-io_f.patch [bz#2117252] -- kvm-QIOChannelSocket-Implement-io_writev-zero-copy-flag-.patch [bz#2117252] -- kvm-migration-Add-zero-copy-send-parameter-for-QMP-HMP-f.patch [bz#2117252] -- kvm-migration-Add-migrate_use_tls-helper.patch [bz#2117252] -- kvm-multifd-multifd_send_sync_main-now-returns-negative-.patch [bz#2117252] -- kvm-multifd-Send-header-packet-without-flags-if-zero-cop.patch [bz#2117252] -- kvm-multifd-Implement-zero-copy-write-in-multifd-migrati.patch [bz#2117252] -- kvm-QIOChannelSocket-Introduce-assert-and-reduce-ifdefs-.patch [bz#2117252] -- kvm-QIOChannelSocket-Fix-zero-copy-send-so-socket-flush-.patch [bz#2117252] -- kvm-migration-Change-zero_copy_send-from-migration-param.patch [bz#2117252] -- kvm-migration-Introduce-ram_transferred_add.patch [bz#2117252] -- kvm-migration-Tally-pre-copy-downtime-and-post-copy-byte.patch [bz#2117252] -- kvm-QIOChannelSocket-Fix-zero-copy-flush-returning-code-.patch [bz#2117252] -- kvm-Add-dirty-sync-missed-zero-copy-migration-stat.patch [bz#2117252] -- kvm-migration-multifd-Report-to-user-when-zerocopy-not-w.patch [bz#2117252] -- kvm-migration-Avoid-false-positive-on-non-supported-scen.patch [bz#2117252] -- kvm-migration-add-remaining-params-has_-true-in-migratio.patch [bz#2117252] -- kvm-QIOChannelSocket-Add-support-for-MSG_ZEROCOPY-IPV6.patch [bz#2117252] -- Resolves: bz#2117252 - (Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8 [rhel-8.6.0.z]) - -* Mon Aug 08 2022 Miroslav Rezanina - 6.2.0-11.el8_6.3 -- kvm-virtio-net-setup-vhost_dev-and-notifiers-for-cvq-onl.patch [bz#2095794] -- kvm-virtio-net-align-ctrl_vq-index-for-non-mq-guest-for-.patch [bz#2095794] -- kvm-vhost-vdpa-fix-improper-cleanup-in-net_init_vhost_vd.patch [bz#2095794] -- kvm-vhost-net-fix-improper-cleanup-in-vhost_net_start.patch [bz#2095794] -- kvm-vhost-vdpa-backend-feature-should-set-only-once.patch [bz#2095794] -- kvm-vhost-vdpa-change-name-and-polarity-for-vhost_vdpa_o.patch [bz#2095794] -- kvm-virtio-net-don-t-handle-mq-request-in-userspace-hand.patch [bz#2095794] -- Resolves: bz#2095794 - (PXE boot crash qemu when using multiqueue vDPA [rhel-8.6.0.z]) - -* Wed Jun 15 2022 Jon Maloy - 6.2.0-11.el8_6.2 -- kvm-Revert-redhat-Add-some-devices-for-exporting-upstrea.patch [bz#2077928] -- kvm-ui-cursor-fix-integer-overflow-in-cursor_alloc-CVE-2.patch [bz#2082622] -- Resolves: bz#2077928 - (Remove upstream-only devices from the qemu-kvm binary [rhel-8.6.0.z]) -- Resolves: bz#2082622 - (CVE-2021-4206 virt:rhel/qemu-kvm: QEMU: QXL: integer overflow in cursor_alloc() can lead to heap buffer overflow [rhel-8.6.0.z]) - -* Wed May 25 2022 Jon Maloy - 6.2.0-11.el8_6.1 -- kvm-RHEL-disable-seqpacket-for-vhost-vsock-device-in-rhe.patch [bz#2071103] -- kvm-hw-intc-arm_gicv3-Check-for-MEMTX_OK-instead-of-MEMT.patch [bz#2075686] -- kvm-softmmu-physmem-Simplify-flatview_write-and-address_.patch [bz#2075686] -- kvm-softmmu-physmem-Introduce-MemTxAttrs-memory-field-an.patch [bz#2075686] -- kvm-display-qxl-render-fix-race-condition-in-qxl_cursor-.patch [bz#2075683] -- kvm-virtio-net-fix-map-leaking-on-error-during-receive.patch [bz#2075637] -- kvm-vhost-vsock-detach-the-virqueue-element-in-case-of-e.patch [bz#2075639] -- kvm-qcow2-Improve-refcount-structure-rebuilding.patch [bz#2072242] -- kvm-iotests-108-Test-new-refcount-rebuild-algorithm.patch [bz#2072242] -- kvm-qcow2-Add-errp-to-rebuild_refcount_structure.patch [bz#2072242] -- kvm-iotests-108-Fix-when-missing-user_allow_other.patch [bz#2072242] -- Resolves: bz#2071103 - (RHEL 9.0 guest with vsock device migration failed from RHEL 9.0 > RHEL 8.6 [rhel-8.6.0.z]) -- Resolves: bz#2075686 - (CVE-2021-3750 virt:rhel/qemu-kvm: QEMU: hcd-ehci: DMA reentrancy issue leads to use-after-free [rhel-8] [rhel-8.6.0.z]) -- Resolves: bz#2075683 - (CVE-2021-4207 virt:rhel/qemu-kvm: QEMU: QXL: double fetch in qxl_cursor() can lead to heap buffer overflow [rhel-8] [rhel-8.6.0.z]) -- Resolves: bz#2075637 - (CVE-2022-26353 virt:rhel/qemu-kvm: QEMU: virtio-net: map leaking on error during receive [rhel-8] [rhel-8.6.0.z]) -- Resolves: bz#2075639 - (CVE-2022-26354 virt:rhel/qemu-kvm: QEMU: vhost-vsock: missing virtqueue detach on error can lead to memory leak [rhel-8] [rhel-8.6.0.z]) -- Resolves: bz#2072242 - (Fail to rebuild the reference count tables of qcow2 image on host block devices (e.g. LVs) [rhel-8.6.0.z]) - -* Tue Apr 05 2022 Jon Maloy - 6.2.0-11 -- kvm-target-i386-properly-reset-TSC-on-reset.patch [bz#1975840] -- Resolves: bz#1975840 - (Windows guest hangs after updating and restarting from the guest OS) - -* Mon Mar 21 2022 Jon Maloy - 6.2.0-10 -- kvm-vmxcap-Add-5-level-EPT-bit.patch [bz#2056986] -- kvm-i386-Add-Icelake-Server-v6-CPU-model-with-5-level-EP.patch [bz#2056986] -- kvm-acpi-fix-QEMU-crash-when-started-with-SLIC-table.patch [bz#2059311] -- kvm-tests-acpi-whitelist-expected-blobs-before-changing-.patch [bz#2059311] -- kvm-tests-acpi-add-SLIC-table-test.patch [bz#2059311] -- kvm-tests-acpi-SLIC-update-expected-blobs.patch [bz#2059311] -- kvm-tests-acpi-manually-pad-OEM_ID-OEM_TABLE_ID-for-test.patch [bz#2059311] -- kvm-tests-acpi-whitelist-nvdimm-s-SSDT-and-FACP.slic-exp.patch [bz#2059311] -- kvm-acpi-fix-OEM-ID-OEM-Table-ID-padding.patch [bz#2059311] -- kvm-tests-acpi-update-expected-blobs.patch [bz#2059311] -- kvm-tests-acpi-test-short-OEM_ID-OEM_TABLE_ID-values-in-.patch [bz#2059311] -- kvm-rhel-workaround-for-lack-of-binary-patches-in-SRPM.patch [bz#2059311] -- Resolves: bz#2056986 - (Win11 (q35+edk2) guest broke after install wsl2 through 'wsl --install -d Ubuntu-20.04') -- Resolves: bz#2059311 - (Guest can not start with SLIC acpi table) - -* Sat Mar 12 2022 Jon Maloy - 6.2.0-9 -- kvm-Revert-redhat-Add-hw_compat_4_2_extra-and-apply-to-u.patch [bz#2061856] -- kvm-Revert-redhat-Enable-FDC-device-for-upstream-machine.patch [bz#2061856] -- kvm-Revert-redhat-Expose-upstream-machines-pc-4.2-and-pc.patch [bz#2061856] -- kvm-hw-virtio-vdpa-Fix-leak-of-host-notifier-memory-regi.patch [bz#2027208] -- kvm-pci-expose-TYPE_XIO3130_DOWNSTREAM-name.patch [bz#2054597] -- kvm-acpi-pcihp-pcie-set-power-on-cap-on-parent-slot.patch [bz#2054597] -- Resolves: bz#2061856 - (Revert IBM-specific Ubuntu-compatibility machine type for 8.6-AV GA) -- Resolves: bz#2027208 - ([virtual network][vDPA] qemu crash after hot unplug vdpa device) -- Resolves: bz#2054597 - (Do operation to disk will hang in the guest of target host after hotplugging and migrating) +* Wed Oct 12 2022 Miroslav Rezanina - 6.2.0-20.el8_7.2 +- kvm-virtiofsd-use-g_date_time_get_microsecond-to-get-sub.patch [bz#2132391] +- Resolves: bz#2132391 + ([virtiofs] virtiofsd debug log's timestamp is NULL [rhel-8.7.0.z]) + +* Wed Sep 14 2022 Miroslav Rezanina - 6.2.0-20.el8.1 +- kvm-i386-reset-KVM-nested-state-upon-CPU-reset.patch [bz#2116743] +- kvm-i386-do-kvm_put_msr_feature_control-first-thing-when.patch [bz#2116743] +- Resolves: bz#2116743 + ([RHEL8.7] Guests in VMX root operation fail to reboot with QEMU's 'system_reset' command) + +* Fri Aug 26 2022 Jon Maloy - 6.2.0-20 +- kvm-scsi-generic-Fix-emulated-block-limits-VPD-page.patch [bz#2120279] +- Resolves: bz#2120279 + (Wrong max_sectors_kb and Maximum transfer length on the pass-through device [rhel-8.7]) + +* Tue Aug 16 2022 Miroslav Rezanina - 6.2.0-19 +- kvm-migration-Introduce-ram_transferred_add.patch [bz#2110203] +- kvm-migration-Tally-pre-copy-downtime-and-post-copy-byte.patch [bz#2110203] +- kvm-QIOChannelSocket-Fix-zero-copy-flush-returning-code-.patch [bz#2110203] +- kvm-Add-dirty-sync-missed-zero-copy-migration-stat.patch [bz#2110203] +- kvm-migration-multifd-Report-to-user-when-zerocopy-not-w.patch [bz#2110203] +- kvm-migration-Avoid-false-positive-on-non-supported-scen.patch [bz#2110203] +- kvm-migration-add-remaining-params-has_-true-in-migratio.patch [bz#2110203] +- kvm-QIOChannelSocket-Add-support-for-MSG_ZEROCOPY-IPV6.patch [bz#2110203] +- kvm-pc-bios-s390-ccw-Fix-booting-with-logical-block-size.patch [bz#2112296] +- Resolves: bz#2110203 + (zerocopy capability can be enabled when set migrate capabilities with multifd and compress/xbzrle together) +- Resolves: bz#2112296 + (virtio-blk: Can't boot fresh installation from used 512 cluster_size image under certain conditions) + +* Tue Jul 19 2022 Camilla Conte - 6.2.0-18 +- kvm-linux-aio-fix-unbalanced-plugged-counter-in-laio_io_.patch [bz#2105410] +- kvm-linux-aio-explain-why-max-batch-is-checked-in-laio_i.patch [bz#2105410] +- Resolves: bz#2105410 + (Stalled IO Operations in VM) + +* Tue Jul 12 2022 Camilla Conte - 6.2.0-17 +- kvm-migration-Never-call-twice-qemu_target_page_size.patch [bz#2072049] +- kvm-multifd-Rename-used-field-to-num.patch [bz#2072049] +- kvm-multifd-Add-missing-documentation.patch [bz#2072049] +- kvm-multifd-The-variable-is-only-used-inside-the-loop.patch [bz#2072049] +- kvm-multifd-remove-used-parameter-from-send_prepare-meth.patch [bz#2072049] +- kvm-multifd-remove-used-parameter-from-send_recv_pages-m.patch [bz#2072049] +- kvm-multifd-Fill-offset-and-block-for-reception.patch [bz#2072049] +- kvm-multifd-Make-zstd-compression-method-not-use-iovs.patch [bz#2072049] +- kvm-multifd-Make-zlib-compression-method-not-use-iovs.patch [bz#2072049] +- kvm-migration-All-this-fields-are-unsigned.patch [bz#2072049] +- kvm-multifd-Move-iov-from-pages-to-params.patch [bz#2072049] +- kvm-multifd-Make-zlib-use-iov-s.patch [bz#2072049] +- kvm-multifd-Make-zstd-use-iov-s.patch [bz#2072049] +- kvm-multifd-Remove-send_write-method.patch [bz#2072049] +- kvm-multifd-Use-a-single-writev-on-the-send-side.patch [bz#2072049] +- kvm-multifd-Use-normal-pages-array-on-the-send-side.patch [bz#2072049] +- kvm-QIOChannel-Add-flags-on-io_writev-and-introduce-io_f.patch [bz#2072049] +- kvm-QIOChannelSocket-Implement-io_writev-zero-copy-flag-.patch [bz#2072049] +- kvm-migration-Add-zero-copy-send-parameter-for-QMP-HMP-f.patch [bz#2072049] +- kvm-migration-Add-migrate_use_tls-helper.patch [bz#2072049] +- kvm-multifd-multifd_send_sync_main-now-returns-negative-.patch [bz#2072049] +- kvm-multifd-Send-header-packet-without-flags-if-zero-cop.patch [bz#2072049] +- kvm-multifd-Implement-zero-copy-write-in-multifd-migrati.patch [bz#2072049] +- kvm-QIOChannelSocket-Introduce-assert-and-reduce-ifdefs-.patch [bz#2072049] +- kvm-QIOChannelSocket-Fix-zero-copy-send-so-socket-flush-.patch [bz#2072049] +- kvm-migration-Change-zero_copy_send-from-migration-param.patch [bz#2072049] +- kvm-migration-Add-migration_incoming_transport_cleanup.patch [bz#2097652] +- kvm-migration-Allow-migrate-recover-to-run-multiple-time.patch [bz#2097652] +- kvm-pc-bios-s390-ccw-virtio-Introduce-a-macro-for-the-DA.patch [bz#2098076] +- kvm-pc-bios-s390-ccw-bootmap-Improve-the-guessing-logic-.patch [bz#2098076] +- kvm-pc-bios-s390-ccw-virtio-blkdev-Simplify-fix-virtio_i.patch [bz#2098076] +- kvm-pc-bios-s390-ccw-virtio-blkdev-Remove-virtio_assume_.patch [bz#2098076] +- kvm-pc-bios-s390-ccw-virtio-Set-missing-status-bits-whil.patch [bz#2098076] +- kvm-pc-bios-s390-ccw-virtio-Read-device-config-after-fea.patch [bz#2098076] +- kvm-pc-bios-s390-ccw-virtio-Beautify-the-code-for-readin.patch [bz#2098076] +- kvm-pc-bios-s390-ccw-Split-virtio-scsi-code-from-virtio_.patch [bz#2098076] +- kvm-pc-bios-s390-ccw-virtio-blkdev-Request-the-right-fea.patch [bz#2098076] +- Resolves: bz#2072049 + (Pull MSG_ZEROCOPY on QEMU Live Migration Patches into RHEL 8) +- Resolves: bz#2097652 + (The migration port is not released if use it again for recovering postcopy migration) +- Resolves: bz#2098076 + (virtio-blk: Can't boot fresh installation from used virtio-blk dasd disk under certain conditions) + +* Thu Jun 23 2022 Jon Maloy - 6.2.0-16 +- kvm-virtiofsd-Fix-breakage-due-to-fuse_init_in-size-chan.patch [bz#2097209] +- kvm-hw-block-fdc-Prevent-end-of-track-overrun-CVE-2021-3.patch [bz#1951521] +- kvm-tests-qtest-fdc-test-Add-a-regression-test-for-CVE-2.patch [bz#1951521] +- Resolves: bz#2097209 + ([virtiofs] mount virtiofs failed: SELinux: (dev virtiofs, type virtiofs) getxattr errno 111) +- Resolves: bz#1951521 + (CVE-2021-3507 virt:rhel/qemu-kvm: QEMU: fdc: heap buffer overflow in DMA read data transfers [rhel-8]) + +* Tue Jun 14 2022 Jon Maloy - 6.2.0-15 +- kvm-virtio-gpu-do-not-byteswap-padding.patch [bz#1916415] +- kvm-linux-headers-update-to-5.16-rc1.patch [bz#1916415] +- kvm-linux-headers-Update-headers-to-v5.17-rc1.patch [bz#1916415] +- kvm-linux-headers-include-missing-changes-from-5.17.patch [bz#1916415] +- kvm-x86-Fix-the-64-byte-boundary-enumeration-for-extende.patch [bz#1916415] +- kvm-x86-Add-AMX-XTILECFG-and-XTILEDATA-components.patch [bz#1916415] +- kvm-x86-Grant-AMX-permission-for-guest.patch [bz#1916415] +- kvm-x86-Add-XFD-faulting-bit-for-state-components.patch [bz#1916415] +- kvm-x86-Add-AMX-CPUIDs-enumeration.patch [bz#1916415] +- kvm-x86-add-support-for-KVM_CAP_XSAVE2-and-AMX-state-mig.patch [bz#1916415] +- kvm-x86-Support-XFD-and-AMX-xsave-data-migration.patch [bz#1916415] +- kvm-target-i386-kvm-do-not-access-uninitialized-variable.patch [bz#1916415] +- kvm-KVM-x86-workaround-invalid-CPUID-0xD-9-info-on-some-.patch [bz#1916415] +- kvm-virtio-net-setup-vhost_dev-and-notifiers-for-cvq-onl.patch [bz#2069946] +- kvm-virtio-net-align-ctrl_vq-index-for-non-mq-guest-for-.patch [bz#2069946] +- kvm-vhost-vdpa-fix-improper-cleanup-in-net_init_vhost_vd.patch [bz#2069946] +- kvm-vhost-net-fix-improper-cleanup-in-vhost_net_start.patch [bz#2069946] +- kvm-vhost-vdpa-backend-feature-should-set-only-once.patch [bz#2069946] +- kvm-vhost-vdpa-change-name-and-polarity-for-vhost_vdpa_o.patch [bz#2069946] +- kvm-virtio-net-don-t-handle-mq-request-in-userspace-hand.patch [bz#2069946] +- kvm-ide-Increment-BB-in-flight-counter-for-TRIM-BH.patch [bz#2029980] +- kvm-block-Make-bdrv_refresh_limits-non-recursive.patch [bz#2072932] +- kvm-iotests-Allow-using-QMP-with-the-QSD.patch [bz#2072932] +- kvm-iotests-graph-changes-while-io-New-test.patch [bz#2072932] +- Resolves: bz#1916415 + ([Intel 8.7 FEAT] qemu-kvm Sapphire Rapids (SPR) AMX Instructions) +- Resolves: bz#2069946 + (PXE boot crash qemu when using multiqueue vDPA) +- Resolves: bz#2029980 + (Failed assertion in IDE emulation with Ceph backend) +- Resolves: bz#2072932 + (Qemu coredump when refreshing block limits on an actively used iothread block device [rhel.8.7]) + +* Thu May 19 2022 Jon Maloy - 6.2.0-14 +- kvm-Revert-redhat-Add-some-devices-for-exporting-upstrea.patch [bz#2065043] +- kvm-target-i386-properly-reset-TSC-on-reset.patch [bz#2070417] +- kvm-ui-cursor-fix-integer-overflow-in-cursor_alloc-CVE-2.patch [bz#2040734] +- Resolves: bz#2065043 + (Remove upstream-only devices from the qemu-kvm binary) +- Resolves: bz#2070417 + (Windows guest hangs after updating and restarting from the guest OS [rhel-8.7.0]) +- Resolves: bz#2040734 + (CVE-2021-4206 virt:rhel/qemu-kvm: QEMU: QXL: integer overflow in cursor_alloc() can lead to heap buffer overflow [rhel-8.7]) + +* Tue May 03 2022 Jon Maloy - 6.2.0-13 +- kvm-s390x-ipl-support-extended-kernel-command-line-size.patch [bz#2043830] +- kvm-virtio-net-fix-map-leaking-on-error-during-receive.patch [bz#2063206] +- kvm-qcow2-Improve-refcount-structure-rebuilding.patch [bz#1519071] +- kvm-iotests-108-Test-new-refcount-rebuild-algorithm.patch [bz#1519071] +- kvm-qcow2-Add-errp-to-rebuild_refcount_structure.patch [bz#1519071] +- kvm-iotests-108-Fix-when-missing-user_allow_other.patch [bz#1519071] +- Resolves: bz#2043830 + ([IBM 8.7 FEAT] KVM: Allow long kernel command lines for QEMU) +- Resolves: bz#2063206 + (CVE-2022-26353 virt:rhel/qemu-kvm: QEMU: virtio-net: map leaking on error during receive [rhel-8]) +- Resolves: bz#1519071 + (Fail to rebuild the reference count tables of qcow2 image on host block devices (e.g. LVs)) + +* Thu Apr 21 2022 Jon Maloy - 6.2.0-12 +- kvm-display-qxl-render-fix-race-condition-in-qxl_cursor-.patch [bz#2040738] +- kvm-vhost-vsock-detach-the-virqueue-element-in-case-of-e.patch [bz#2063262] +- Resolves: bz#2040738 + (CVE-2021-4207 virt:rhel/qemu-kvm: QEMU: QXL: double fetch in qxl_cursor() can lead to heap buffer overflow [rhel-8]) +- Resolves: bz#2063262 + (CVE-2022-26354 virt:rhel/qemu-kvm: QEMU: vhost-vsock: missing virtqueue detach on error can lead to memory leak [rhel-8]) + +* Thu Apr 21 2022 Jon Maloy - 6.2.0-11 +- kvm-hw-intc-arm_gicv3-Check-for-MEMTX_OK-instead-of-MEMT.patch [bz#1999236] +- kvm-softmmu-physmem-Simplify-flatview_write-and-address_.patch [bz#1999236] +- kvm-softmmu-physmem-Introduce-MemTxAttrs-memory-field-an.patch [bz#1999236] +- Resolves: bz#1999236 + (CVE-2021-3750 virt:rhel/qemu-kvm: QEMU: hcd-ehci: DMA reentrancy issue leads to use-after-free [rhel-8]) + +* Thu Apr 21 2022 Jon Maloy - 6.2.0-10 +- kvm-RHEL-disable-seqpacket-for-vhost-vsock-device-in-rhe.patch [bz#2068202] +- kvm-block-Lock-AioContext-for-drain_end-in-blockdev-reop.patch [bz#2067118] +- kvm-iotests-Test-blockdev-reopen-with-iothreads-and-thro.patch [bz#2067118] +- kvm-s390x-css-fix-PMCW-invalid-mask.patch [bz#2071070] +- kvm-Set-permission-on-installing-files.patch [bz#2072377] +- Resolves: bz#2068202 + (RHEL 9.0 guest with vsock device migration failed from RHEL 9.0 > RHEL 8.6 [rhel-8.7.0]) +- Resolves: bz#2067118 + (qemu crash after execute blockdev-reopen with iothread) +- Resolves: bz#2071070 + (s390x/css: fix PMCW invalid mask) +- Resolves: bz#2072377 + (Fix build warnings that occur when installing the keymap files) + +* Wed Apr 06 2022 Jon Maloy - 6.2.0-9 +- kvm-Revert-redhat-Add-hw_compat_4_2_extra-and-apply-to-u.patch [bz#2062613] +- kvm-Revert-redhat-Enable-FDC-device-for-upstream-machine.patch [bz#2062613] +- kvm-Revert-redhat-Expose-upstream-machines-pc-4.2-and-pc.patch [bz#2062613] +- kvm-hw-virtio-vdpa-Fix-leak-of-host-notifier-memory-regi.patch [bz#2060843] +- kvm-pci-expose-TYPE_XIO3130_DOWNSTREAM-name.patch [bz#2062610] +- kvm-acpi-pcihp-pcie-set-power-on-cap-on-parent-slot.patch [bz#2062610] +- kvm-vmxcap-Add-5-level-EPT-bit.patch [bz#2065207] +- kvm-i386-Add-Icelake-Server-v6-CPU-model-with-5-level-EP.patch [bz#2065207] +- kvm-acpi-fix-QEMU-crash-when-started-with-SLIC-table.patch [bz#2062611] +- kvm-tests-acpi-whitelist-expected-blobs-before-changing-.patch [bz#2062611] +- kvm-tests-acpi-add-SLIC-table-test.patch [bz#2062611] +- kvm-tests-acpi-SLIC-update-expected-blobs.patch [bz#2062611] +- kvm-tests-acpi-manually-pad-OEM_ID-OEM_TABLE_ID-for-test.patch [bz#2062611] +- kvm-tests-acpi-whitelist-nvdimm-s-SSDT-and-FACP.slic-exp.patch [bz#2062611] +- kvm-acpi-fix-OEM-ID-OEM-Table-ID-padding.patch [bz#2062611] +- kvm-tests-acpi-update-expected-blobs.patch [bz#2062611] +- kvm-tests-acpi-test-short-OEM_ID-OEM_TABLE_ID-values-in-.patch [bz#2062611] +- kvm-rhel-workaround-for-lack-of-binary-patches-in-SRPM.patch [bz#2062611] +- Resolves: bz#2062613 + (Revert IBM-specific Ubuntu-compatibility machine type for 8.6-AV GA [rhel-8.7.0]) +- Resolves: bz#2060843 + ([virtual network][vDPA] qemu crash after hot unplug vdpa device [rhel-8.7.0]) +- Resolves: bz#2062610 + (Do operation to disk will hang in the guest of target host after hotplugging and migrating [rhel-8.7.0]) +- Resolves: bz#2065207 + (Win11 (q35+edk2) guest broke after install wsl2 through 'wsl --install -d Ubuntu-20.04' [rhel-8.7.0]) +- Resolves: bz#2062611 + (Guest can not start with SLIC acpi table [rhel-8.7.0]) * Tue Feb 22 2022 Jon Maloy - 6.2.0-8 - kvm-block-nbd-Delete-reconnect-delay-timer-when-done.patch [bz#2035185] -- Gitee From 2e2a44789d3823325e09be5a2495c541cf991591 Mon Sep 17 00:00:00 2001 From: Jacob Wang Date: Sun, 1 Aug 2021 13:37:55 +0800 Subject: [PATCH 2/3] Adjust to support virtiofsd minor > 27 Signed-off-by: Jacob Wang --- ...iofsd-Adjust-limit-for-minor-version.patch | 41 +++++++++++++++++++ qemu-kvm.spec | 8 +++- 2 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 kvm-virtiofsd-Adjust-limit-for-minor-version.patch diff --git a/kvm-virtiofsd-Adjust-limit-for-minor-version.patch b/kvm-virtiofsd-Adjust-limit-for-minor-version.patch new file mode 100644 index 0000000..30ec553 --- /dev/null +++ b/kvm-virtiofsd-Adjust-limit-for-minor-version.patch @@ -0,0 +1,41 @@ +From 3b7200134925fcf5ae99b5c3b34465456d3bc002 Mon Sep 17 00:00:00 2001 +From: Jacob Wang +Date: Mon, 2 Aug 2021 01:16:05 +0800 +Subject: [PATCH 1/1] virtiofsd: Adjust limit for minor version + +Upstream virtiofsd only supports fuse >= 7.31 +(https://github.com/qemu/qemu/commit/72c42e2d65510e073cf78fdc924d121c77fa0080), +while Cloud Kernel has fuse version 7.27, which causes virtiofs fails to run +due to version mismatch. This limitation is unnecessary in Cloud Kernel because +we have already backported mandatory fuse patches to support virtofs +frontend in Kernel. Hence, adjust the minor version limit to 7.27 to +suppress the limitation. + +Note that current fuse implementation in Cloud Kernel might lack of some +certain capabilities in fuse 7.28 ~ 7.31, which may cause unexpected results, +this patch is merely a workaround to enable virtiofs in guest kernel side and +further action is ongoing to make sure fuse APIs in both sides are 100% +compatible. + +Signed-off-by: Jacob Wang +Acked-by: Caspar Zhang +--- + tools/virtiofsd/fuse_lowlevel.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/virtiofsd/fuse_lowlevel.c b/tools/virtiofsd/fuse_lowlevel.c +index 2dd36ec..2bb4318 100644 +--- a/tools/virtiofsd/fuse_lowlevel.c ++++ b/tools/virtiofsd/fuse_lowlevel.c +@@ -1917,7 +1917,7 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, + outarg.major = FUSE_KERNEL_VERSION; + outarg.minor = FUSE_KERNEL_MINOR_VERSION; + +- if (arg->major < 7 || (arg->major == 7 && arg->minor < 31)) { ++ if (arg->major < 7 || (arg->major == 7 && arg->minor < 27)) { + fuse_log(FUSE_LOG_ERR, "fuse: unsupported protocol version: %u.%u\n", + arg->major, arg->minor); + fuse_reply_err(req, EPROTO); +-- +1.8.3.1 + diff --git a/qemu-kvm.spec b/qemu-kvm.spec index 19bae57..8325347 100644 --- a/qemu-kvm.spec +++ b/qemu-kvm.spec @@ -1,3 +1,4 @@ +%define anolis_release .0.1 %global SLOF_gittagdate 20191022 %global SLOF_gittagcommit 899d9883 @@ -83,7 +84,7 @@ Obsoletes: %1-rhev <= %{epoch}:%{version}-%{release} Summary: QEMU is a machine emulator and virtualizer Name: qemu-kvm Version: 6.2.0 -Release: 20%{?rcrel}%{?dist}.2 +Release: 20%{?rcrel}%{anolis_release}%{?dist}.2 # Epoch because we pushed a qemu-1.0 package. AIUI this can't ever be dropped Epoch: 15 License: GPLv2 and GPLv2+ and CC-BY @@ -434,6 +435,8 @@ Patch167: kvm-i386-do-kvm_put_msr_feature_control-first-thing-when.patch # For bz#2132391 - [virtiofs] virtiofsd debug log's timestamp is NULL [rhel-8.7.0.z] Patch168: kvm-virtiofsd-use-g_date_time_get_microsecond-to-get-sub.patch +Patch1000: kvm-virtiofsd-Adjust-limit-for-minor-version.patch + BuildRequires: wget BuildRequires: rpm-build BuildRequires: ninja-build @@ -1602,6 +1605,9 @@ sh %{_sysconfdir}/sysconfig/modules/kvm.modules &> /dev/null || : %changelog +* Tue Dec 27 2022 Jacob Wang - 6.2.0-20.0.1.2 +- Adjust limit for virtiofsd minor version + * Wed Oct 12 2022 Miroslav Rezanina - 6.2.0-20.el8_7.2 - kvm-virtiofsd-use-g_date_time_get_microsecond-to-get-sub.patch [bz#2132391] - Resolves: bz#2132391 -- Gitee From d5b1499daeebf3b2b072b4d23b654c150b0d773e Mon Sep 17 00:00:00 2001 From: lixianglai Date: Thu, 25 Aug 2022 05:55:22 -0400 Subject: [PATCH 3/3] Support loongarch. Signed-off-by: lixianglai --- 0001-Add-Acpi-support.patch | 1348 ++ 0002-Support-rtc.patch | 370 + 0003-Add-loongarch-machine.patch | 5752 +++++++ 0004-Add-target-loongarch64.patch | 15918 ++++++++++++++++++ 0005-Add-linux-headers-and-linux-user.patch | 1663 ++ 0006-Add-disas-gdb.patch | 3183 ++++ 0007-Modify-kvm-cpu-vga-qapi.patch | 480 + 0008-Modify-compile-script.patch | 36 + 0009-Add-loongarch64-rh-devices.mak.patch | 3227 ++++ loongarch_bios.bin | Bin 0 -> 4190208 bytes loongarch_vars.bin | Bin 0 -> 389120 bytes qemu-kvm.spec | 43 +- 12 files changed, 32015 insertions(+), 5 deletions(-) create mode 100644 0001-Add-Acpi-support.patch create mode 100644 0002-Support-rtc.patch create mode 100644 0003-Add-loongarch-machine.patch create mode 100644 0004-Add-target-loongarch64.patch create mode 100644 0005-Add-linux-headers-and-linux-user.patch create mode 100644 0006-Add-disas-gdb.patch create mode 100644 0007-Modify-kvm-cpu-vga-qapi.patch create mode 100644 0008-Modify-compile-script.patch create mode 100644 0009-Add-loongarch64-rh-devices.mak.patch create mode 100644 loongarch_bios.bin create mode 100644 loongarch_vars.bin diff --git a/0001-Add-Acpi-support.patch b/0001-Add-Acpi-support.patch new file mode 100644 index 0000000..5b1561c --- /dev/null +++ b/0001-Add-Acpi-support.patch @@ -0,0 +1,1348 @@ +From 612826687e639d007e4270b01a61f34f7fc1f813 Mon Sep 17 00:00:00 2001 +From: lixianglai +Date: Fri, 19 Aug 2022 23:11:23 -0400 +Subject: [PATCH 1/8] Add Acpi support. + +Change-Id: I208228b2178cddf365e97c6faf6111ef40e795eb +Signed-off-by: lixianglai +--- + hw/acpi/Kconfig | 8 + + hw/acpi/larch_7a.c | 600 +++++++++++++++++++++++++++++++++++++++++ + hw/acpi/ls7a.c | 598 ++++++++++++++++++++++++++++++++++++++++ + hw/acpi/meson.build | 1 + + include/hw/acpi/ls7a.h | 80 ++++++ + 5 files changed, 1287 insertions(+) + create mode 100644 hw/acpi/larch_7a.c + create mode 100644 hw/acpi/ls7a.c + create mode 100644 include/hw/acpi/ls7a.h + +diff --git a/hw/acpi/Kconfig b/hw/acpi/Kconfig +index 622b0b50b7..2f2fb33a7b 100644 +--- a/hw/acpi/Kconfig ++++ b/hw/acpi/Kconfig +@@ -15,6 +15,14 @@ config ACPI_X86_ICH + bool + select ACPI_X86 + ++config ACPI_LOONGARCH ++ bool ++ select ACPI ++ select ACPI_CPU_HOTPLUG ++ select ACPI_MEMORY_HOTPLUG ++ select ACPI_PIIX4 ++ select ACPI_PCIHP ++ + config ACPI_CPU_HOTPLUG + bool + +diff --git a/hw/acpi/larch_7a.c b/hw/acpi/larch_7a.c +new file mode 100644 +index 0000000000..35d4a75266 +--- /dev/null ++++ b/hw/acpi/larch_7a.c +@@ -0,0 +1,600 @@ ++#include "qemu/osdep.h" ++#include "sysemu/sysemu.h" ++#include "sysemu/runstate.h" ++#include "sysemu/reset.h" ++#include "hw/hw.h" ++#include "hw/irq.h" ++#include "hw/acpi/acpi.h" ++#include "hw/acpi/ls7a.h" ++#include "hw/nvram/fw_cfg.h" ++#include "qemu/config-file.h" ++#include "qapi/opts-visitor.h" ++#include "qapi/qapi-events-run-state.h" ++#include "qapi/error.h" ++#include "hw/loongarch/ls7a.h" ++#include "hw/mem/pc-dimm.h" ++#include "hw/mem/nvdimm.h" ++#include "migration/vmstate.h" ++ ++static void ls7a_pm_update_sci_fn(ACPIREGS *regs) ++{ ++ LS7APCIPMRegs *pm = container_of(regs, LS7APCIPMRegs, acpi_regs); ++ acpi_update_sci(&pm->acpi_regs, pm->irq); ++} ++ ++static uint64_t ls7a_gpe_readb(void *opaque, hwaddr addr, unsigned width) ++{ ++ LS7APCIPMRegs *pm = opaque; ++ return acpi_gpe_ioport_readb(&pm->acpi_regs, addr); ++} ++ ++static void ls7a_gpe_writeb(void *opaque, hwaddr addr, uint64_t val, ++ unsigned width) ++{ ++ LS7APCIPMRegs *pm = opaque; ++ acpi_gpe_ioport_writeb(&pm->acpi_regs, addr, val); ++ acpi_update_sci(&pm->acpi_regs, pm->irq); ++} ++ ++static const MemoryRegionOps ls7a_gpe_ops = { ++ .read = ls7a_gpe_readb, ++ .write = ls7a_gpe_writeb, ++ .valid.min_access_size = 1, ++ .valid.max_access_size = 8, ++ .impl.min_access_size = 1, ++ .impl.max_access_size = 1, ++ .endianness = DEVICE_LITTLE_ENDIAN, ++}; ++ ++#define VMSTATE_GPE_ARRAY(_field, _state) \ ++ { \ ++ .name = (stringify(_field)), \ ++ .version_id = 0, \ ++ .num = ACPI_GPE0_LEN, \ ++ .info = &vmstate_info_uint8, \ ++ .size = sizeof(uint8_t), \ ++ .flags = VMS_ARRAY | VMS_POINTER, \ ++ .offset = vmstate_offset_pointer(_state, _field, uint8_t), \ ++ } ++ ++static uint64_t ls7a_reset_readw(void *opaque, hwaddr addr, unsigned width) ++{ ++ return 0; ++} ++ ++static void ls7a_reset_writew(void *opaque, hwaddr addr, uint64_t val, ++ unsigned width) ++{ ++ if (val & 1) { ++ qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); ++ return; ++ } ++} ++ ++static const MemoryRegionOps ls7a_reset_ops = { ++ .read = ls7a_reset_readw, ++ .write = ls7a_reset_writew, ++ .valid.min_access_size = 4, ++ .valid.max_access_size = 4, ++ .endianness = DEVICE_LITTLE_ENDIAN, ++}; ++ ++static bool vmstate_test_use_memhp(void *opaque) ++{ ++ LS7APCIPMRegs *s = opaque; ++ return s->acpi_memory_hotplug.is_enabled; ++} ++ ++static const VMStateDescription vmstate_memhp_state = { ++ .name = "ls7a_pm/memhp", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .minimum_version_id_old = 1, ++ .needed = vmstate_test_use_memhp, ++ .fields = (VMStateField[]) { ++ VMSTATE_MEMORY_HOTPLUG(acpi_memory_hotplug, LS7APCIPMRegs), ++ VMSTATE_END_OF_LIST() ++ } ++}; ++ ++static const VMStateDescription vmstate_cpuhp_state = { ++ .name = "ls7a_pm/cpuhp", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .minimum_version_id_old = 1, ++ .fields = (VMStateField[]) { ++ VMSTATE_CPU_HOTPLUG(cpuhp_state, LS7APCIPMRegs), ++ VMSTATE_END_OF_LIST() ++ } ++}; ++ ++const VMStateDescription vmstate_ls7a_pm = { ++ .name = "ls7a_pm", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .fields = (VMStateField[]) { ++ VMSTATE_UINT16(acpi_regs.pm1.evt.sts, LS7APCIPMRegs), ++ VMSTATE_UINT16(acpi_regs.pm1.evt.en, LS7APCIPMRegs), ++ VMSTATE_UINT16(acpi_regs.pm1.cnt.cnt, LS7APCIPMRegs), ++ VMSTATE_TIMER_PTR(acpi_regs.tmr.timer, LS7APCIPMRegs), ++ VMSTATE_INT64(acpi_regs.tmr.overflow_time, LS7APCIPMRegs), ++ VMSTATE_GPE_ARRAY(acpi_regs.gpe.sts, LS7APCIPMRegs), ++ VMSTATE_GPE_ARRAY(acpi_regs.gpe.en, LS7APCIPMRegs), ++ VMSTATE_END_OF_LIST() ++ }, ++ .subsections = (const VMStateDescription * []) { ++ &vmstate_memhp_state, ++ &vmstate_cpuhp_state, ++ NULL ++ } ++}; ++ ++static inline int64_t acpi_pm_tmr_get_clock(void) ++{ ++ return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), PM_TIMER_FREQUENCY, ++ NANOSECONDS_PER_SECOND); ++} ++ ++static uint32_t acpi_pm_tmr_get(ACPIREGS *ar) ++{ ++ uint32_t d = acpi_pm_tmr_get_clock(); ++ return d & 0xffffff; ++} ++ ++static void acpi_pm_tmr_timer(void *opaque) ++{ ++ ACPIREGS *ar = opaque; ++ qemu_system_wakeup_request(QEMU_WAKEUP_REASON_PMTIMER, NULL); ++ ar->tmr.update_sci(ar); ++} ++ ++static uint64_t acpi_pm_tmr_read(void *opaque, hwaddr addr, unsigned width) ++{ ++ return acpi_pm_tmr_get(opaque); ++} ++ ++static void acpi_pm_tmr_write(void *opaque, hwaddr addr, uint64_t val, ++ unsigned width) ++{ ++ /* nothing */ ++} ++ ++static const MemoryRegionOps acpi_pm_tmr_ops = { ++ .read = acpi_pm_tmr_read, ++ .write = acpi_pm_tmr_write, ++ .valid.min_access_size = 4, ++ .valid.max_access_size = 4, ++ .endianness = DEVICE_LITTLE_ENDIAN, ++}; ++ ++static void ls7a_pm_tmr_init(ACPIREGS *ar, acpi_update_sci_fn update_sci, ++ MemoryRegion *parent, uint64_t offset) ++{ ++ ar->tmr.update_sci = update_sci; ++ ar->tmr.timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, acpi_pm_tmr_timer, ar); ++ memory_region_init_io(&ar->tmr.io, memory_region_owner(parent), ++ &acpi_pm_tmr_ops, ar, "acpi-tmr", 4); ++ memory_region_add_subregion(parent, offset, &ar->tmr.io); ++} ++ ++static void acpi_pm1_evt_write_sts(ACPIREGS *ar, uint16_t val) ++{ ++ uint16_t pm1_sts = acpi_pm1_evt_get_sts(ar); ++ if (pm1_sts & val & ACPI_BITMASK_TIMER_STATUS) { ++ /* if TMRSTS is reset, then compute the new overflow time */ ++ acpi_pm_tmr_calc_overflow_time(ar); ++ } ++ ar->pm1.evt.sts &= ~val; ++} ++ ++static uint64_t acpi_pm_evt_read(void *opaque, hwaddr addr, unsigned width) ++{ ++ ACPIREGS *ar = opaque; ++ switch (addr) { ++ case 0: ++ return acpi_pm1_evt_get_sts(ar); ++ case 4: ++ return ar->pm1.evt.en; ++ default: ++ return 0; ++ } ++} ++ ++static void acpi_pm1_evt_write_en(ACPIREGS *ar, uint16_t val) ++{ ++ ar->pm1.evt.en = val; ++ qemu_system_wakeup_enable(QEMU_WAKEUP_REASON_RTC, ++ val & ACPI_BITMASK_RT_CLOCK_ENABLE); ++ qemu_system_wakeup_enable(QEMU_WAKEUP_REASON_PMTIMER, ++ val & ACPI_BITMASK_TIMER_ENABLE); ++} ++ ++static void acpi_pm_evt_write(void *opaque, hwaddr addr, uint64_t val, ++ unsigned width) ++{ ++ ACPIREGS *ar = opaque; ++ switch (addr) { ++ case 0: ++ acpi_pm1_evt_write_sts(ar, val); ++ ar->pm1.evt.update_sci(ar); ++ break; ++ case 4: ++ acpi_pm1_evt_write_en(ar, val); ++ ar->pm1.evt.update_sci(ar); ++ break; ++ } ++} ++ ++static const MemoryRegionOps acpi_pm_evt_ops = { ++ .read = acpi_pm_evt_read, ++ .write = acpi_pm_evt_write, ++ .valid.min_access_size = 4, ++ .valid.max_access_size = 4, ++ .endianness = DEVICE_LITTLE_ENDIAN, ++}; ++ ++static void ls7a_pm1_evt_init(ACPIREGS *ar, acpi_update_sci_fn update_sci, ++ MemoryRegion *parent, uint64_t offset) ++{ ++ ar->pm1.evt.update_sci = update_sci; ++ memory_region_init_io(&ar->pm1.evt.io, memory_region_owner(parent), ++ &acpi_pm_evt_ops, ar, "acpi-evt", 8); ++ memory_region_add_subregion(parent, offset, &ar->pm1.evt.io); ++} ++ ++static uint64_t acpi_pm_cnt_read(void *opaque, hwaddr addr, unsigned width) ++{ ++ ACPIREGS *ar = opaque; ++ return ar->pm1.cnt.cnt; ++} ++ ++/* ACPI PM1aCNT */ ++static void acpi_pm1_cnt_write(ACPIREGS *ar, uint16_t val) ++{ ++ ar->pm1.cnt.cnt = val & ~(ACPI_BITMASK_SLEEP_ENABLE); ++ if (val & ACPI_BITMASK_SLEEP_ENABLE) { ++ /* change suspend type */ ++ uint16_t sus_typ = (val >> 10) & 7; ++ switch (sus_typ) { ++ /* s3,s4 not support */ ++ case 5: ++ case 6: ++ warn_report("acpi s3,s4 state not support"); ++ break; ++ /* s5: soft off */ ++ case 7: ++ qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); ++ break; ++ default: ++ break; ++ } ++ } ++} ++ ++static void acpi_pm_cnt_write(void *opaque, hwaddr addr, uint64_t val, ++ unsigned width) ++{ ++ acpi_pm1_cnt_write(opaque, val); ++} ++ ++static const MemoryRegionOps acpi_pm_cnt_ops = { ++ .read = acpi_pm_cnt_read, ++ .write = acpi_pm_cnt_write, ++ .valid.min_access_size = 4, ++ .valid.max_access_size = 4, ++ .endianness = DEVICE_LITTLE_ENDIAN, ++}; ++ ++static void acpi_notify_wakeup(Notifier *notifier, void *data) ++{ ++ ACPIREGS *ar = container_of(notifier, ACPIREGS, wakeup); ++ WakeupReason *reason = data; ++ ++ switch (*reason) { ++ case QEMU_WAKEUP_REASON_RTC: ++ ar->pm1.evt.sts |= ++ (ACPI_BITMASK_WAKE_STATUS | ACPI_BITMASK_RT_CLOCK_STATUS); ++ break; ++ case QEMU_WAKEUP_REASON_PMTIMER: ++ ar->pm1.evt.sts |= ++ (ACPI_BITMASK_WAKE_STATUS | ACPI_BITMASK_TIMER_STATUS); ++ break; ++ case QEMU_WAKEUP_REASON_OTHER: ++ /* ACPI_BITMASK_WAKE_STATUS should be set on resume. ++ * Pretend that resume was caused by power button */ ++ ar->pm1.evt.sts |= ++ (ACPI_BITMASK_WAKE_STATUS | ACPI_BITMASK_POWER_BUTTON_STATUS); ++ break; ++ default: ++ break; ++ } ++} ++ ++static void ls7a_pm1_cnt_init(ACPIREGS *ar, MemoryRegion *parent, ++ bool disable_s3, bool disable_s4, uint8_t s4_val, uint64_t offset) ++{ ++ FWCfgState *fw_cfg; ++ ++ ar->pm1.cnt.s4_val = s4_val; ++ ar->wakeup.notify = acpi_notify_wakeup; ++ qemu_register_wakeup_notifier(&ar->wakeup); ++ memory_region_init_io(&ar->pm1.cnt.io, memory_region_owner(parent), ++ &acpi_pm_cnt_ops, ar, "acpi-cnt", 4); ++ memory_region_add_subregion(parent, offset, &ar->pm1.cnt.io); ++ ++ fw_cfg = fw_cfg_find(); ++ if (fw_cfg) { ++ uint8_t suspend[6] = {128, 0, 0, 129, 128, 128}; ++ suspend[3] = 1 | ((!disable_s3) << 7); ++ suspend[4] = s4_val | ((!disable_s4) << 7); ++ fw_cfg_add_file(fw_cfg, "etc/system-states", g_memdup(suspend, 6), 6); ++ } ++} ++ ++static void ls7a_pm_reset(void *opaque) ++{ ++ LS7APCIPMRegs *pm = opaque; ++ ++ acpi_pm1_evt_reset(&pm->acpi_regs); ++ acpi_pm1_cnt_reset(&pm->acpi_regs); ++ acpi_pm_tmr_reset(&pm->acpi_regs); ++ acpi_gpe_reset(&pm->acpi_regs); ++ ++ acpi_update_sci(&pm->acpi_regs, pm->irq); ++} ++ ++static void pm_powerdown_req(Notifier *n, void *opaque) ++{ ++ LS7APCIPMRegs *pm = container_of(n, LS7APCIPMRegs, powerdown_notifier); ++ ++ acpi_pm1_evt_power_down(&pm->acpi_regs); ++} ++ ++void ls7a_pm_init(LS7APCIPMRegs *pm, qemu_irq *pic) ++{ ++ unsigned long base, gpe_len, acpi_aci_irq; ++ ++ /* ls7a board acpi hardware info, including ++ * acpi system io base address ++ * acpi gpe length ++ * acpi sci irq number ++ */ ++ base = ACPI_IO_BASE; ++ gpe_len = ACPI_GPE0_LEN; ++ acpi_aci_irq = ACPI_SCI_IRQ; ++ ++ pm->irq = pic[acpi_aci_irq - 64]; ++ memory_region_init(&pm->iomem, NULL, "ls7a_pm", ACPI_IO_SIZE); ++ memory_region_add_subregion(get_system_memory(), base, &pm->iomem); ++ ++ cpu_hotplug_hw_init(get_system_memory(), NULL, ++ &pm->cpuhp_state, CPU_HOTPLUG_BASE); ++ ++ ls7a_pm_tmr_init(&pm->acpi_regs, ls7a_pm_update_sci_fn, &pm->iomem, LS7A_PM_TMR_BLK); ++ ls7a_pm1_evt_init(&pm->acpi_regs, ls7a_pm_update_sci_fn, &pm->iomem, LS7A_PM_EVT_BLK); ++ ls7a_pm1_cnt_init(&pm->acpi_regs, &pm->iomem, false, false, 2, LS7A_PM_CNT_BLK); ++ ++ acpi_gpe_init(&pm->acpi_regs, gpe_len); ++ memory_region_init_io(&pm->iomem_gpe, NULL, &ls7a_gpe_ops, pm, ++ "acpi-gpe0", gpe_len); ++ memory_region_add_subregion(&pm->iomem, LS7A_GPE0_STS_REG, &pm->iomem_gpe); ++ ++ memory_region_init_io(&pm->iomem_reset, NULL, &ls7a_reset_ops, pm, ++ "acpi-reset", 4); ++ memory_region_add_subregion(&pm->iomem, LS7A_GPE0_RESET_REG, &pm->iomem_reset); ++ ++ qemu_register_reset(ls7a_pm_reset, pm); ++ ++ pm->powerdown_notifier.notify = pm_powerdown_req; ++ qemu_register_powerdown_notifier(&pm->powerdown_notifier); ++ ++ if (pm->acpi_memory_hotplug.is_enabled) { ++ acpi_memory_hotplug_init(get_system_memory(), NULL, ++ &pm->acpi_memory_hotplug, MEMORY_HOTPLUG_BASE); ++ } ++} ++ ++ ++static void ls7a_pm_get_gpe0_blk(Object *obj, Visitor *v, const char *name, ++ void *opaque, Error **errp) ++{ ++ uint64_t value = ACPI_IO_BASE + LS7A_GPE0_STS_REG; ++ ++ visit_type_uint64(v, name, &value, errp); ++} ++ ++static bool ls7a_pm_get_memory_hotplug_support(Object *obj, Error **errp) ++{ ++ LS7APCIState *ls7a = get_ls7a_type(obj); ++ ++ return ls7a->pm.acpi_memory_hotplug.is_enabled; ++} ++ ++static void ls7a_pm_set_memory_hotplug_support(Object *obj, bool value, ++ Error **errp) ++{ ++ LS7APCIState *ls7a = get_ls7a_type(obj); ++ ++ ls7a->pm.acpi_memory_hotplug.is_enabled = value; ++} ++ ++static void ls7a_pm_get_disable_s3(Object *obj, Visitor *v, const char *name, ++ void *opaque, Error **errp) ++{ ++ LS7APCIPMRegs *pm = opaque; ++ uint8_t value = pm->disable_s3; ++ ++ visit_type_uint8(v, name, &value, errp); ++} ++ ++static void ls7a_pm_set_disable_s3(Object *obj, Visitor *v, const char *name, ++ void *opaque, Error **errp) ++{ ++ LS7APCIPMRegs *pm = opaque; ++ Error *local_err = NULL; ++ uint8_t value; ++ ++ visit_type_uint8(v, name, &value, &local_err); ++ if (local_err) { ++ goto out; ++ } ++ pm->disable_s3 = value; ++out: ++ error_propagate(errp, local_err); ++} ++ ++static void ls7a_pm_get_disable_s4(Object *obj, Visitor *v, const char *name, ++ void *opaque, Error **errp) ++{ ++ LS7APCIPMRegs *pm = opaque; ++ uint8_t value = pm->disable_s4; ++ ++ visit_type_uint8(v, name, &value, errp); ++} ++ ++static void ls7a_pm_set_disable_s4(Object *obj, Visitor *v, const char *name, ++ void *opaque, Error **errp) ++{ ++ LS7APCIPMRegs *pm = opaque; ++ Error *local_err = NULL; ++ uint8_t value; ++ ++ visit_type_uint8(v, name, &value, &local_err); ++ if (local_err) { ++ goto out; ++ } ++ pm->disable_s4 = value; ++out: ++ error_propagate(errp, local_err); ++} ++ ++static void ls7a_pm_get_s4_val(Object *obj, Visitor *v, const char *name, ++ void *opaque, Error **errp) ++{ ++ LS7APCIPMRegs *pm = opaque; ++ uint8_t value = pm->s4_val; ++ ++ visit_type_uint8(v, name, &value, errp); ++} ++ ++static void ls7a_pm_set_s4_val(Object *obj, Visitor *v, const char *name, ++ void *opaque, Error **errp) ++{ ++ LS7APCIPMRegs *pm = opaque; ++ Error *local_err = NULL; ++ uint8_t value; ++ ++ visit_type_uint8(v, name, &value, &local_err); ++ if (local_err) { ++ goto out; ++ } ++ pm->s4_val = value; ++out: ++ error_propagate(errp, local_err); ++} ++ ++void ls7a_pm_add_properties(Object *obj, LS7APCIPMRegs *pm, Error **errp) ++{ ++ static const uint32_t gpe0_len = ACPI_GPE0_LEN; ++ pm->acpi_memory_hotplug.is_enabled = true; ++ pm->disable_s3 = 0; ++ pm->disable_s4 = 0; ++ pm->s4_val = 2; ++ ++ object_property_add_uint32_ptr(obj, ACPI_PM_PROP_PM_IO_BASE, ++ &pm->pm_io_base, OBJ_PROP_FLAG_READ); ++ object_property_add(obj, ACPI_PM_PROP_GPE0_BLK, "uint32", ++ ls7a_pm_get_gpe0_blk, ++ NULL, NULL, pm); ++ object_property_add_uint32_ptr(obj, ACPI_PM_PROP_GPE0_BLK_LEN, ++ &gpe0_len, OBJ_PROP_FLAG_READ); ++ object_property_add_bool(obj, "memory-hotplug-support", ++ ls7a_pm_get_memory_hotplug_support, ++ ls7a_pm_set_memory_hotplug_support); ++ object_property_add(obj, ACPI_PM_PROP_S3_DISABLED, "uint8", ++ ls7a_pm_get_disable_s3, ++ ls7a_pm_set_disable_s3, ++ NULL, pm); ++ object_property_add(obj, ACPI_PM_PROP_S4_DISABLED, "uint8", ++ ls7a_pm_get_disable_s4, ++ ls7a_pm_set_disable_s4, ++ NULL, pm); ++ object_property_add(obj, ACPI_PM_PROP_S4_VAL, "uint8", ++ ls7a_pm_get_s4_val, ++ ls7a_pm_set_s4_val, ++ NULL, pm); ++} ++ ++void ls7a_pm_device_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, ++ Error **errp) ++{ ++ LS7APCIState *ls7a = get_ls7a_type(OBJECT(hotplug_dev)); ++ ++ if (ls7a->pm.acpi_memory_hotplug.is_enabled && ++ object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { ++ if (object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM)) { ++ nvdimm_acpi_plug_cb(hotplug_dev, dev); ++ } else { ++ acpi_memory_plug_cb(hotplug_dev, &ls7a->pm.acpi_memory_hotplug, ++ dev, errp); ++ } ++ } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) { ++ acpi_cpu_plug_cb(hotplug_dev, &ls7a->pm.cpuhp_state, dev, errp); ++ } else { ++ error_setg(errp, "acpi: device plug request for not supported device" ++ " type: %s", object_get_typename(OBJECT(dev))); ++ } ++} ++ ++void ls7a_pm_device_unplug_request_cb(HotplugHandler *hotplug_dev, ++ DeviceState *dev, Error **errp) ++{ ++ LS7APCIState *ls7a = get_ls7a_type(OBJECT(hotplug_dev)); ++ ++ if (ls7a->pm.acpi_memory_hotplug.is_enabled && ++ object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { ++ acpi_memory_unplug_request_cb(hotplug_dev, ++ &ls7a->pm.acpi_memory_hotplug, dev, ++ errp); ++ } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) { ++ acpi_cpu_unplug_request_cb(hotplug_dev, &ls7a->pm.cpuhp_state, ++ dev, errp); ++ } else { ++ error_setg(errp, "acpi: device unplug request for not supported device" ++ " type: %s", object_get_typename(OBJECT(dev))); ++ } ++} ++ ++void ls7a_pm_device_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, ++ Error **errp) ++{ ++ LS7APCIState *ls7a = get_ls7a_type(OBJECT(hotplug_dev)); ++ ++ if (ls7a->pm.acpi_memory_hotplug.is_enabled && ++ object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { ++ acpi_memory_unplug_cb(&ls7a->pm.acpi_memory_hotplug, dev, errp); ++ } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) { ++ acpi_cpu_unplug_cb(&ls7a->pm.cpuhp_state, dev, errp); ++ } else { ++ error_setg(errp, "acpi: device unplug for not supported device" ++ " type: %s", object_get_typename(OBJECT(dev))); ++ } ++} ++ ++void ls7a_pm_ospm_status(AcpiDeviceIf *adev, ACPIOSTInfoList ***list) ++{ ++ LS7APCIState *ls7a = get_ls7a_type(OBJECT(adev)); ++ ++ acpi_memory_ospm_status(&ls7a->pm.acpi_memory_hotplug, list); ++ acpi_cpu_ospm_status(&ls7a->pm.cpuhp_state, list); ++} ++ ++void ls7a_send_gpe(AcpiDeviceIf *adev, AcpiEventStatusBits ev) ++{ ++ LS7APCIState *ls7a = get_ls7a_type(OBJECT(adev)); ++ ++ acpi_send_gpe_event(&ls7a->pm.acpi_regs, ls7a->pm.irq, ev); ++} ++ ++ ++ +diff --git a/hw/acpi/ls7a.c b/hw/acpi/ls7a.c +new file mode 100644 +index 0000000000..2de50ccb9c +--- /dev/null ++++ b/hw/acpi/ls7a.c +@@ -0,0 +1,598 @@ ++#include "qemu/osdep.h" ++#include "sysemu/sysemu.h" ++#include "hw/hw.h" ++#include "hw/irq.h" ++#include "hw/acpi/acpi.h" ++#include "hw/acpi/ls7a.h" ++#include "hw/nvram/fw_cfg.h" ++#include "qemu/config-file.h" ++#include "qapi/opts-visitor.h" ++#include "qapi/qapi-events-run-state.h" ++#include "qapi/error.h" ++#include "hw/mips/ls7a.h" ++#include "hw/mem/pc-dimm.h" ++#include "hw/mem/nvdimm.h" ++ ++static void ls7a_pm_update_sci_fn(ACPIREGS *regs) ++{ ++ LS7APCIPMRegs *pm = container_of(regs, LS7APCIPMRegs, acpi_regs); ++ acpi_update_sci(&pm->acpi_regs, pm->irq); ++} ++ ++static uint64_t ls7a_gpe_readb(void *opaque, hwaddr addr, unsigned width) ++{ ++ LS7APCIPMRegs *pm = opaque; ++ return acpi_gpe_ioport_readb(&pm->acpi_regs, addr); ++} ++ ++static void ls7a_gpe_writeb(void *opaque, hwaddr addr, uint64_t val, ++ unsigned width) ++{ ++ LS7APCIPMRegs *pm = opaque; ++ acpi_gpe_ioport_writeb(&pm->acpi_regs, addr, val); ++ acpi_update_sci(&pm->acpi_regs, pm->irq); ++} ++ ++static const MemoryRegionOps ls7a_gpe_ops = { ++ .read = ls7a_gpe_readb, ++ .write = ls7a_gpe_writeb, ++ .valid.min_access_size = 1, ++ .valid.max_access_size = 8, ++ .impl.min_access_size = 1, ++ .impl.max_access_size = 1, ++ .endianness = DEVICE_LITTLE_ENDIAN, ++}; ++ ++#define VMSTATE_GPE_ARRAY(_field, _state) \ ++ { \ ++ .name = (stringify(_field)), \ ++ .version_id = 0, \ ++ .num = ACPI_GPE0_LEN, \ ++ .info = &vmstate_info_uint8, \ ++ .size = sizeof(uint8_t), \ ++ .flags = VMS_ARRAY | VMS_POINTER, \ ++ .offset = vmstate_offset_pointer(_state, _field, uint8_t), \ ++ } ++ ++static uint64_t ls7a_reset_readw(void *opaque, hwaddr addr, unsigned width) ++{ ++ return 0; ++} ++ ++static void ls7a_reset_writew(void *opaque, hwaddr addr, uint64_t val, ++ unsigned width) ++{ ++ if (val & 1) { ++ qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); ++ return; ++ } ++} ++ ++static const MemoryRegionOps ls7a_reset_ops = { ++ .read = ls7a_reset_readw, ++ .write = ls7a_reset_writew, ++ .valid.min_access_size = 4, ++ .valid.max_access_size = 4, ++ .endianness = DEVICE_LITTLE_ENDIAN, ++}; ++ ++static bool vmstate_test_use_memhp(void *opaque) ++{ ++ LS7APCIPMRegs *s = opaque; ++ return s->acpi_memory_hotplug.is_enabled; ++} ++ ++static const VMStateDescription vmstate_memhp_state = { ++ .name = "ls7a_pm/memhp", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .minimum_version_id_old = 1, ++ .needed = vmstate_test_use_memhp, ++ .fields = (VMStateField[]) { ++ VMSTATE_MEMORY_HOTPLUG(acpi_memory_hotplug, LS7APCIPMRegs), ++ VMSTATE_END_OF_LIST() ++ } ++}; ++ ++static const VMStateDescription vmstate_cpuhp_state = { ++ .name = "ls7a_pm/cpuhp", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .minimum_version_id_old = 1, ++ .fields = (VMStateField[]) { ++ VMSTATE_CPU_HOTPLUG(cpuhp_state, LS7APCIPMRegs), ++ VMSTATE_END_OF_LIST() ++ } ++}; ++ ++const VMStateDescription vmstate_ls7a_pm = { ++ .name = "ls7a_pm", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .fields = (VMStateField[]) { ++ VMSTATE_UINT16(acpi_regs.pm1.evt.sts, LS7APCIPMRegs), ++ VMSTATE_UINT16(acpi_regs.pm1.evt.en, LS7APCIPMRegs), ++ VMSTATE_UINT16(acpi_regs.pm1.cnt.cnt, LS7APCIPMRegs), ++ VMSTATE_TIMER_PTR(acpi_regs.tmr.timer, LS7APCIPMRegs), ++ VMSTATE_INT64(acpi_regs.tmr.overflow_time, LS7APCIPMRegs), ++ VMSTATE_GPE_ARRAY(acpi_regs.gpe.sts, LS7APCIPMRegs), ++ VMSTATE_GPE_ARRAY(acpi_regs.gpe.en, LS7APCIPMRegs), ++ VMSTATE_END_OF_LIST() ++ }, ++ .subsections = (const VMStateDescription * []) { ++ &vmstate_memhp_state, ++ &vmstate_cpuhp_state, ++ NULL ++ } ++}; ++ ++static inline int64_t acpi_pm_tmr_get_clock(void) ++{ ++ return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), PM_TIMER_FREQUENCY, ++ NANOSECONDS_PER_SECOND); ++} ++ ++static uint32_t acpi_pm_tmr_get(ACPIREGS *ar) ++{ ++ uint32_t d = acpi_pm_tmr_get_clock(); ++ return d & 0xffffff; ++} ++ ++static void acpi_pm_tmr_timer(void *opaque) ++{ ++ ACPIREGS *ar = opaque; ++ qemu_system_wakeup_request(QEMU_WAKEUP_REASON_PMTIMER, NULL); ++ ar->tmr.update_sci(ar); ++} ++ ++static uint64_t acpi_pm_tmr_read(void *opaque, hwaddr addr, unsigned width) ++{ ++ return acpi_pm_tmr_get(opaque); ++} ++ ++static void acpi_pm_tmr_write(void *opaque, hwaddr addr, uint64_t val, ++ unsigned width) ++{ ++ /* nothing */ ++} ++ ++static const MemoryRegionOps acpi_pm_tmr_ops = { ++ .read = acpi_pm_tmr_read, ++ .write = acpi_pm_tmr_write, ++ .valid.min_access_size = 4, ++ .valid.max_access_size = 4, ++ .endianness = DEVICE_LITTLE_ENDIAN, ++}; ++ ++static void ls7a_pm_tmr_init(ACPIREGS *ar, acpi_update_sci_fn update_sci, ++ MemoryRegion *parent, uint64_t offset) ++{ ++ ar->tmr.update_sci = update_sci; ++ ar->tmr.timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, acpi_pm_tmr_timer, ar); ++ memory_region_init_io(&ar->tmr.io, memory_region_owner(parent), ++ &acpi_pm_tmr_ops, ar, "acpi-tmr", 4); ++ memory_region_add_subregion(parent, offset, &ar->tmr.io); ++} ++ ++static void acpi_pm1_evt_write_sts(ACPIREGS *ar, uint16_t val) ++{ ++ uint16_t pm1_sts = acpi_pm1_evt_get_sts(ar); ++ if (pm1_sts & val & ACPI_BITMASK_TIMER_STATUS) { ++ /* if TMRSTS is reset, then compute the new overflow time */ ++ acpi_pm_tmr_calc_overflow_time(ar); ++ } ++ ar->pm1.evt.sts &= ~val; ++} ++ ++static uint64_t acpi_pm_evt_read(void *opaque, hwaddr addr, unsigned width) ++{ ++ ACPIREGS *ar = opaque; ++ switch (addr) { ++ case 0: ++ return acpi_pm1_evt_get_sts(ar); ++ case 4: ++ return ar->pm1.evt.en; ++ default: ++ return 0; ++ } ++} ++ ++static void acpi_pm1_evt_write_en(ACPIREGS *ar, uint16_t val) ++{ ++ ar->pm1.evt.en = val; ++ qemu_system_wakeup_enable(QEMU_WAKEUP_REASON_RTC, ++ val & ACPI_BITMASK_RT_CLOCK_ENABLE); ++ qemu_system_wakeup_enable(QEMU_WAKEUP_REASON_PMTIMER, ++ val & ACPI_BITMASK_TIMER_ENABLE); ++} ++ ++static void acpi_pm_evt_write(void *opaque, hwaddr addr, uint64_t val, ++ unsigned width) ++{ ++ ACPIREGS *ar = opaque; ++ switch (addr) { ++ case 0: ++ acpi_pm1_evt_write_sts(ar, val); ++ ar->pm1.evt.update_sci(ar); ++ break; ++ case 4: ++ acpi_pm1_evt_write_en(ar, val); ++ ar->pm1.evt.update_sci(ar); ++ break; ++ } ++} ++ ++static const MemoryRegionOps acpi_pm_evt_ops = { ++ .read = acpi_pm_evt_read, ++ .write = acpi_pm_evt_write, ++ .valid.min_access_size = 4, ++ .valid.max_access_size = 4, ++ .endianness = DEVICE_LITTLE_ENDIAN, ++}; ++ ++static void ls7a_pm1_evt_init(ACPIREGS *ar, acpi_update_sci_fn update_sci, ++ MemoryRegion *parent, uint64_t offset) ++{ ++ ar->pm1.evt.update_sci = update_sci; ++ memory_region_init_io(&ar->pm1.evt.io, memory_region_owner(parent), ++ &acpi_pm_evt_ops, ar, "acpi-evt", 8); ++ memory_region_add_subregion(parent, offset, &ar->pm1.evt.io); ++} ++ ++static uint64_t acpi_pm_cnt_read(void *opaque, hwaddr addr, unsigned width) ++{ ++ ACPIREGS *ar = opaque; ++ return ar->pm1.cnt.cnt; ++} ++ ++/* ACPI PM1aCNT */ ++static void acpi_pm1_cnt_write(ACPIREGS *ar, uint16_t val) ++{ ++ ar->pm1.cnt.cnt = val & ~(ACPI_BITMASK_SLEEP_ENABLE); ++ ++ if (val & ACPI_BITMASK_SLEEP_ENABLE) { ++ /* change suspend type */ ++ uint16_t sus_typ = (val >> 10) & 7; ++ switch (sus_typ) { ++ case 0: /* soft power off */ ++ qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); ++ break; ++ case 1: ++ qemu_system_suspend_request(); ++ break; ++ default: ++ if (sus_typ == ar->pm1.cnt.s4_val) { /* S4 request */ ++ qapi_event_send_suspend_disk(); ++ qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); ++ } ++ break; ++ } ++ } ++} ++ ++static void acpi_pm_cnt_write(void *opaque, hwaddr addr, uint64_t val, ++ unsigned width) ++{ ++ acpi_pm1_cnt_write(opaque, val); ++} ++ ++static const MemoryRegionOps acpi_pm_cnt_ops = { ++ .read = acpi_pm_cnt_read, ++ .write = acpi_pm_cnt_write, ++ .valid.min_access_size = 4, ++ .valid.max_access_size = 4, ++ .endianness = DEVICE_LITTLE_ENDIAN, ++}; ++ ++static void acpi_notify_wakeup(Notifier *notifier, void *data) ++{ ++ ACPIREGS *ar = container_of(notifier, ACPIREGS, wakeup); ++ WakeupReason *reason = data; ++ ++ switch (*reason) { ++ case QEMU_WAKEUP_REASON_RTC: ++ ar->pm1.evt.sts |= ++ (ACPI_BITMASK_WAKE_STATUS | ACPI_BITMASK_RT_CLOCK_STATUS); ++ break; ++ case QEMU_WAKEUP_REASON_PMTIMER: ++ ar->pm1.evt.sts |= ++ (ACPI_BITMASK_WAKE_STATUS | ACPI_BITMASK_TIMER_STATUS); ++ break; ++ case QEMU_WAKEUP_REASON_OTHER: ++ /* ACPI_BITMASK_WAKE_STATUS should be set on resume. ++ * Pretend that resume was caused by power button */ ++ ar->pm1.evt.sts |= ++ (ACPI_BITMASK_WAKE_STATUS | ACPI_BITMASK_POWER_BUTTON_STATUS); ++ break; ++ default: ++ break; ++ } ++} ++ ++static void ls7a_pm1_cnt_init(ACPIREGS *ar, MemoryRegion *parent, ++ bool disable_s3, bool disable_s4, uint8_t s4_val, uint64_t offset) ++{ ++ FWCfgState *fw_cfg; ++ ++ ar->pm1.cnt.s4_val = s4_val; ++ ar->wakeup.notify = acpi_notify_wakeup; ++ qemu_register_wakeup_notifier(&ar->wakeup); ++ memory_region_init_io(&ar->pm1.cnt.io, memory_region_owner(parent), ++ &acpi_pm_cnt_ops, ar, "acpi-cnt", 4); ++ memory_region_add_subregion(parent, offset, &ar->pm1.cnt.io); ++ ++ fw_cfg = fw_cfg_find(); ++ if (fw_cfg) { ++ uint8_t suspend[6] = {128, 0, 0, 129, 128, 128}; ++ suspend[3] = 1 | ((!disable_s3) << 7); ++ suspend[4] = s4_val | ((!disable_s4) << 7); ++ fw_cfg_add_file(fw_cfg, "etc/system-states", g_memdup(suspend, 6), 6); ++ } ++} ++ ++static void ls7a_pm_reset(void *opaque) ++{ ++ LS7APCIPMRegs *pm = opaque; ++ ++ acpi_pm1_evt_reset(&pm->acpi_regs); ++ acpi_pm1_cnt_reset(&pm->acpi_regs); ++ acpi_pm_tmr_reset(&pm->acpi_regs); ++ acpi_gpe_reset(&pm->acpi_regs); ++ ++ acpi_update_sci(&pm->acpi_regs, pm->irq); ++} ++ ++static void pm_powerdown_req(Notifier *n, void *opaque) ++{ ++ LS7APCIPMRegs *pm = container_of(n, LS7APCIPMRegs, powerdown_notifier); ++ ++ acpi_pm1_evt_power_down(&pm->acpi_regs); ++} ++ ++void ls7a_pm_init(LS7APCIPMRegs *pm, qemu_irq *pic) ++{ ++ unsigned long base, gpe_len, acpi_aci_irq; ++ ++ /* ls7a board acpi hardware info, including ++ * acpi system io base address ++ * acpi gpe length ++ * acpi sci irq number ++ */ ++ base = ACPI_IO_BASE; ++ gpe_len = ACPI_GPE0_LEN; ++ acpi_aci_irq = ACPI_SCI_IRQ; ++ ++ pm->irq = pic[acpi_aci_irq - 64]; ++ memory_region_init(&pm->iomem, NULL, "ls7a_pm", ACPI_IO_SIZE); ++ memory_region_add_subregion(get_system_memory(), base, &pm->iomem); ++ ++ cpu_hotplug_hw_init(get_system_memory(), NULL, &pm->cpuhp_state, CPU_HOTPLUG_BASE); ++ ++ ls7a_pm_tmr_init(&pm->acpi_regs, ls7a_pm_update_sci_fn, &pm->iomem, LS7A_PM_TMR_BLK); ++ ls7a_pm1_evt_init(&pm->acpi_regs, ls7a_pm_update_sci_fn, &pm->iomem, LS7A_PM_EVT_BLK); ++ ls7a_pm1_cnt_init(&pm->acpi_regs, &pm->iomem, false, false, 2, LS7A_PM_CNT_BLK); ++ ++ acpi_gpe_init(&pm->acpi_regs, gpe_len); ++ memory_region_init_io(&pm->iomem_gpe, NULL, &ls7a_gpe_ops, pm, ++ "acpi-gpe0", gpe_len); ++ memory_region_add_subregion(&pm->iomem, LS7A_GPE0_STS_REG, &pm->iomem_gpe); ++ ++ memory_region_init_io(&pm->iomem_reset, NULL, &ls7a_reset_ops, pm, ++ "acpi-reset", 4); ++ memory_region_add_subregion(&pm->iomem, LS7A_GPE0_RESET_REG, &pm->iomem_reset); ++ ++ qemu_register_reset(ls7a_pm_reset, pm); ++ ++ pm->powerdown_notifier.notify = pm_powerdown_req; ++ qemu_register_powerdown_notifier(&pm->powerdown_notifier); ++ ++ if (pm->acpi_memory_hotplug.is_enabled) { ++ acpi_memory_hotplug_init(get_system_memory(), NULL, ++ &pm->acpi_memory_hotplug, MEMORY_HOTPLUG_BASE); ++ } ++} ++ ++ ++static void ls7a_pm_get_gpe0_blk(Object *obj, Visitor *v, const char *name, ++ void *opaque, Error **errp) ++{ ++ uint64_t value = ACPI_IO_BASE + LS7A_GPE0_STS_REG; ++ ++ visit_type_uint64(v, name, &value, errp); ++} ++ ++static bool ls7a_pm_get_memory_hotplug_support(Object *obj, Error **errp) ++{ ++ LS7APCIState *ls7a = get_ls7a_type(obj); ++ ++ return ls7a->pm.acpi_memory_hotplug.is_enabled; ++} ++ ++static void ls7a_pm_set_memory_hotplug_support(Object *obj, bool value, ++ Error **errp) ++{ ++ LS7APCIState *ls7a = get_ls7a_type(obj); ++ ++ ls7a->pm.acpi_memory_hotplug.is_enabled = value; ++} ++ ++static void ls7a_pm_get_disable_s3(Object *obj, Visitor *v, const char *name, ++ void *opaque, Error **errp) ++{ ++ LS7APCIPMRegs *pm = opaque; ++ uint8_t value = pm->disable_s3; ++ ++ visit_type_uint8(v, name, &value, errp); ++} ++ ++static void ls7a_pm_set_disable_s3(Object *obj, Visitor *v, const char *name, ++ void *opaque, Error **errp) ++{ ++ LS7APCIPMRegs *pm = opaque; ++ Error *local_err = NULL; ++ uint8_t value; ++ ++ visit_type_uint8(v, name, &value, &local_err); ++ if (local_err) { ++ goto out; ++ } ++ pm->disable_s3 = value; ++out: ++ error_propagate(errp, local_err); ++} ++ ++static void ls7a_pm_get_disable_s4(Object *obj, Visitor *v, const char *name, ++ void *opaque, Error **errp) ++{ ++ LS7APCIPMRegs *pm = opaque; ++ uint8_t value = pm->disable_s4; ++ ++ visit_type_uint8(v, name, &value, errp); ++} ++ ++static void ls7a_pm_set_disable_s4(Object *obj, Visitor *v, const char *name, ++ void *opaque, Error **errp) ++{ ++ LS7APCIPMRegs *pm = opaque; ++ Error *local_err = NULL; ++ uint8_t value; ++ ++ visit_type_uint8(v, name, &value, &local_err); ++ if (local_err) { ++ goto out; ++ } ++ pm->disable_s4 = value; ++out: ++ error_propagate(errp, local_err); ++} ++ ++static void ls7a_pm_get_s4_val(Object *obj, Visitor *v, const char *name, ++ void *opaque, Error **errp) ++{ ++ LS7APCIPMRegs *pm = opaque; ++ uint8_t value = pm->s4_val; ++ ++ visit_type_uint8(v, name, &value, errp); ++} ++ ++static void ls7a_pm_set_s4_val(Object *obj, Visitor *v, const char *name, ++ void *opaque, Error **errp) ++{ ++ LS7APCIPMRegs *pm = opaque; ++ Error *local_err = NULL; ++ uint8_t value; ++ ++ visit_type_uint8(v, name, &value, &local_err); ++ if (local_err) { ++ goto out; ++ } ++ pm->s4_val = value; ++out: ++ error_propagate(errp, local_err); ++} ++ ++void ls7a_pm_add_properties(Object *obj, LS7APCIPMRegs *pm, Error **errp) ++{ ++ static const uint32_t gpe0_len = ACPI_GPE0_LEN; ++ pm->acpi_memory_hotplug.is_enabled = true; ++ pm->disable_s3 = 0; ++ pm->disable_s4 = 0; ++ pm->s4_val = 2; ++ ++ object_property_add_uint32_ptr(obj, ACPI_PM_PROP_PM_IO_BASE, ++ &pm->pm_io_base, OBJ_PROP_FLAG_READ); ++ object_property_add(obj, ACPI_PM_PROP_GPE0_BLK, "uint32", ++ ls7a_pm_get_gpe0_blk, ++ NULL, NULL, pm); ++ object_property_add_uint32_ptr(obj, ACPI_PM_PROP_GPE0_BLK_LEN, ++ &gpe0_len, OBJ_PROP_FLAG_READ); ++ object_property_add_bool(obj, "memory-hotplug-support", ++ ls7a_pm_get_memory_hotplug_support, ++ ls7a_pm_set_memory_hotplug_support); ++ object_property_add(obj, ACPI_PM_PROP_S3_DISABLED, "uint8", ++ ls7a_pm_get_disable_s3, ++ ls7a_pm_set_disable_s3, ++ NULL, pm); ++ object_property_add(obj, ACPI_PM_PROP_S4_DISABLED, "uint8", ++ ls7a_pm_get_disable_s4, ++ ls7a_pm_set_disable_s4, ++ NULL, pm); ++ object_property_add(obj, ACPI_PM_PROP_S4_VAL, "uint8", ++ ls7a_pm_get_s4_val, ++ ls7a_pm_set_s4_val, ++ NULL, pm); ++} ++ ++void ls7a_pm_device_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, ++ Error **errp) ++{ ++ LS7APCIState *ls7a = get_ls7a_type(OBJECT(hotplug_dev)); ++ ++ if (ls7a->pm.acpi_memory_hotplug.is_enabled && ++ object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { ++ if (object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM)) { ++ nvdimm_acpi_plug_cb(hotplug_dev, dev); ++ } else { ++ acpi_memory_plug_cb(hotplug_dev, &ls7a->pm.acpi_memory_hotplug, ++ dev, errp); ++ } ++ } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) { ++ acpi_cpu_plug_cb(hotplug_dev, &ls7a->pm.cpuhp_state, dev, errp); ++ } else { ++ error_setg(errp, "acpi: device plug request for not supported device" ++ " type: %s", object_get_typename(OBJECT(dev))); ++ } ++} ++ ++void ls7a_pm_device_unplug_request_cb(HotplugHandler *hotplug_dev, ++ DeviceState *dev, Error **errp) ++{ ++ LS7APCIState *ls7a = get_ls7a_type(OBJECT(hotplug_dev)); ++ ++ if (ls7a->pm.acpi_memory_hotplug.is_enabled && ++ object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { ++ acpi_memory_unplug_request_cb(hotplug_dev, ++ &ls7a->pm.acpi_memory_hotplug, dev, ++ errp); ++ } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) { ++ acpi_cpu_unplug_request_cb(hotplug_dev, &ls7a->pm.cpuhp_state, ++ dev, errp); ++ } else { ++ error_setg(errp, "acpi: device unplug request for not supported device" ++ " type: %s", object_get_typename(OBJECT(dev))); ++ } ++} ++ ++void ls7a_pm_device_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, ++ Error **errp) ++{ ++ LS7APCIState *ls7a = get_ls7a_type(OBJECT(hotplug_dev)); ++ ++ if (ls7a->pm.acpi_memory_hotplug.is_enabled && ++ object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { ++ acpi_memory_unplug_cb(&ls7a->pm.acpi_memory_hotplug, dev, errp); ++ } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) { ++ acpi_cpu_unplug_cb(&ls7a->pm.cpuhp_state, dev, errp); ++ } else { ++ error_setg(errp, "acpi: device unplug for not supported device" ++ " type: %s", object_get_typename(OBJECT(dev))); ++ } ++} ++ ++void ls7a_pm_ospm_status(AcpiDeviceIf *adev, ACPIOSTInfoList ***list) ++{ ++ LS7APCIState *ls7a = get_ls7a_type(OBJECT(adev)); ++ ++ acpi_memory_ospm_status(&ls7a->pm.acpi_memory_hotplug, list); ++ acpi_cpu_ospm_status(&ls7a->pm.cpuhp_state, list); ++} ++ ++void ls7a_send_gpe(AcpiDeviceIf *adev, AcpiEventStatusBits ev) ++{ ++ LS7APCIState *ls7a = get_ls7a_type(OBJECT(adev)); ++ ++ acpi_send_gpe_event(&ls7a->pm.acpi_regs, ls7a->pm.irq, ev); ++} ++ ++ ++ +diff --git a/hw/acpi/meson.build b/hw/acpi/meson.build +index adf6347bc4..5fe4cfa4f1 100644 +--- a/hw/acpi/meson.build ++++ b/hw/acpi/meson.build +@@ -6,6 +6,7 @@ acpi_ss.add(files( + 'core.c', + 'utils.c', + )) ++acpi_ss.add(when: 'CONFIG_ACPI_LOONGARCH', if_true: files('larch_7a.c')) + acpi_ss.add(when: 'CONFIG_ACPI_CPU_HOTPLUG', if_true: files('cpu.c', 'cpu_hotplug.c')) + acpi_ss.add(when: 'CONFIG_ACPI_CPU_HOTPLUG', if_false: files('acpi-cpu-hotplug-stub.c')) + acpi_ss.add(when: 'CONFIG_ACPI_MEMORY_HOTPLUG', if_true: files('memory_hotplug.c')) +diff --git a/include/hw/acpi/ls7a.h b/include/hw/acpi/ls7a.h +new file mode 100644 +index 0000000000..4401515c7b +--- /dev/null ++++ b/include/hw/acpi/ls7a.h +@@ -0,0 +1,80 @@ ++/* ++ * QEMU GMCH/LS7A PCI PM Emulation ++ * ++ * Copyright (c) 2009 Isaku Yamahata ++ * VA Linux Systems Japan K.K. ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, see ++ */ ++ ++#ifndef HW_ACPI_LS7A_H ++#define HW_ACPI_LS7A_H ++ ++#include "hw/acpi/acpi.h" ++#include "hw/acpi/cpu_hotplug.h" ++#include "hw/acpi/cpu.h" ++#include "hw/acpi/memory_hotplug.h" ++#include "hw/acpi/acpi_dev_interface.h" ++#include "hw/acpi/tco.h" ++ ++#define CPU_HOTPLUG_BASE 0x1e000000 ++#define MEMORY_HOTPLUG_BASE 0x1e00000c ++ ++typedef struct LS7APCIPMRegs { ++ /* ++ * In ls7a spec says that pm1_cnt register is 32bit width and ++ * that the upper 16bits are reserved and unused. ++ * PM1a_CNT_BLK = 2 in FADT so it is defined as uint16_t. ++ */ ++ ACPIREGS acpi_regs; ++ ++ MemoryRegion iomem; ++ MemoryRegion iomem_gpe; ++ MemoryRegion iomem_smi; ++ MemoryRegion iomem_reset; ++ ++ qemu_irq irq; /* SCI */ ++ ++ uint32_t pm_io_base; ++ Notifier powerdown_notifier; ++ ++ bool cpu_hotplug_legacy; ++ AcpiCpuHotplug gpe_cpu; ++ CPUHotplugState cpuhp_state; ++ ++ MemHotplugState acpi_memory_hotplug; ++ ++ uint8_t disable_s3; ++ uint8_t disable_s4; ++ uint8_t s4_val; ++} LS7APCIPMRegs; ++ ++void ls7a_pm_init(LS7APCIPMRegs *ls7a, qemu_irq *sci_irq); ++ ++void ls7a_pm_iospace_update(LS7APCIPMRegs *pm, uint32_t pm_io_base); ++extern const VMStateDescription vmstate_ls7a_pm; ++ ++void ls7a_pm_add_properties(Object *obj, LS7APCIPMRegs *pm, Error **errp); ++ ++void ls7a_pm_device_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, ++ Error **errp); ++void ls7a_pm_device_unplug_request_cb(HotplugHandler *hotplug_dev, ++ DeviceState *dev, Error **errp); ++void ls7a_pm_device_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, ++ Error **errp); ++ ++void ls7a_pm_ospm_status(AcpiDeviceIf *adev, ACPIOSTInfoList ***list); ++ ++void ls7a_send_gpe(AcpiDeviceIf *adev, AcpiEventStatusBits ev); ++#endif /* HW_ACPI_LS7A_H */ +-- +2.27.0 + diff --git a/0002-Support-rtc.patch b/0002-Support-rtc.patch new file mode 100644 index 0000000..082fcdf --- /dev/null +++ b/0002-Support-rtc.patch @@ -0,0 +1,370 @@ +From befa5ef7576fdbe2e729203538b066e5f87c3b8f Mon Sep 17 00:00:00 2001 +From: lixianglai +Date: Fri, 19 Aug 2022 23:15:49 -0400 +Subject: [PATCH 2/8] Support rtc. + +Change-Id: Idd50274dd2a6c00b21ec0cd099f8d115ab4fa449 +Signed-off-by: lixianglai +--- + hw/timer/Kconfig | 2 + + hw/timer/ls7a_rtc.c | 325 +++++++++++++++++++++++++++++++++++++++++++ + hw/timer/meson.build | 1 + + 3 files changed, 328 insertions(+) + create mode 100644 hw/timer/ls7a_rtc.c + +diff --git a/hw/timer/Kconfig b/hw/timer/Kconfig +index 010be7ed1f..b395c72d7d 100644 +--- a/hw/timer/Kconfig ++++ b/hw/timer/Kconfig +@@ -60,3 +60,5 @@ config STELLARIS_GPTM + + config AVR_TIMER16 + bool ++config LS7A_RTC ++ bool +diff --git a/hw/timer/ls7a_rtc.c b/hw/timer/ls7a_rtc.c +new file mode 100644 +index 0000000000..756f2fc9ce +--- /dev/null ++++ b/hw/timer/ls7a_rtc.c +@@ -0,0 +1,325 @@ ++#include "qemu/osdep.h" ++#include "hw/sysbus.h" ++#include "hw/irq.h" ++#include "include/hw/register.h" ++#include "qemu/timer.h" ++#include "sysemu/sysemu.h" ++#include "qemu/cutils.h" ++#include "qemu/log.h" ++#include "qemu-common.h" ++#include "migration/vmstate.h" ++ ++#ifdef DEBUG_LS7A_RTC ++#define DPRINTF (fmt, ...) \ ++do { printf("ls7a_rtc: " fmt , ## __VA_ARGS__); } while (0) ++#else ++#define DPRINTF (fmt, ...) do {} while (0) ++#endif ++ ++ ++#define SYS_TOYTRIM 0x20 ++#define SYS_TOYWRITE0 0x24 ++#define SYS_TOYWRITE1 0x28 ++#define SYS_TOYREAD0 0x2C ++#define SYS_TOYREAD1 0x30 ++#define SYS_TOYMATCH0 0x34 ++#define SYS_TOYMATCH1 0x38 ++#define SYS_TOYMATCH2 0x3C ++#define SYS_RTCCTRL 0x40 ++#define SYS_RTCTRIM 0x60 ++#define SYS_RTCWRTIE0 0x64 ++#define SYS_RTCREAD0 0x68 ++#define SYS_RTCMATCH0 0x6C ++#define SYS_RTCMATCH1 0x70 ++#define SYS_RTCMATCH2 0x74 ++ ++/** ++ ** shift bits and filed mask ++ **/ ++#define TOY_MON_MASK 0x3f ++#define TOY_DAY_MASK 0x1f ++#define TOY_HOUR_MASK 0x1f ++#define TOY_MIN_MASK 0x3f ++#define TOY_SEC_MASK 0x3f ++#define TOY_MSEC_MASK 0xf ++ ++#define TOY_MON_SHIFT 26 ++#define TOY_DAY_SHIFT 21 ++#define TOY_HOUR_SHIFT 16 ++#define TOY_MIN_SHIFT 10 ++#define TOY_SEC_SHIFT 4 ++#define TOY_MSEC_SHIFT 0 ++ ++#define TOY_MATCH_YEAR_MASK 0x3f ++#define TOY_MATCH_MON_MASK 0xf ++#define TOY_MATCH_DAY_MASK 0x1f ++#define TOY_MATCH_HOUR_MASK 0x1f ++#define TOY_MATCH_MIN_MASK 0x3f ++#define TOY_MATCH_SEC_MASK 0x3f ++ ++ ++#define TOY_MATCH_YEAR_SHIFT 26 ++#define TOY_MATCH_MON_SHIFT 22 ++#define TOY_MATCH_DAY_SHIFT 17 ++#define TOY_MATCH_HOUR_SHIFT 12 ++#define TOY_MATCH_MIN_SHIFT 6 ++#define TOY_MATCH_SEC_SHIFT 0 ++ ++#define TOY_ENABLE_BIT (1U << 11) ++ ++#define TYPE_LS7A_RTC "ls7a_rtc" ++#define LS7A_RTC(obj) OBJECT_CHECK(LS7A_RTCState, (obj), TYPE_LS7A_RTC) ++ ++typedef struct LS7A_RTCState { ++ SysBusDevice parent_obj; ++ ++ MemoryRegion iomem; ++ QEMUTimer *timer; ++ /* Needed to preserve the tick_count across migration, even if the ++ * absolute value of the rtc_clock is different on the source and ++ * destination. ++ */ ++ int64_t offset; ++ int64_t data; ++ int64_t save_alarm_offset; ++ int tidx; ++ uint32_t toymatch[3]; ++ uint32_t toytrim; ++ uint32_t cntrctl; ++ uint32_t rtctrim; ++ uint32_t rtccount; ++ uint32_t rtcmatch[3]; ++ qemu_irq toy_irq; ++} LS7A_RTCState; ++ ++enum { ++TOYEN = 1UL << 11, ++RTCEN = 1UL << 13, ++}; ++ ++static uint64_t ls7a_rtc_read(void *opaque, hwaddr addr, ++ unsigned size) ++{ ++ LS7A_RTCState *s = (LS7A_RTCState *)opaque; ++ struct tm tm; ++ unsigned int val; ++ ++ val = 0; ++ ++ switch (addr) { ++ case SYS_TOYREAD0: ++ qemu_get_timedate(&tm, s->offset); ++ val = (((tm.tm_mon + 1) & TOY_MON_MASK) << TOY_MON_SHIFT) ++ | (((tm.tm_mday) & TOY_DAY_MASK) << TOY_DAY_SHIFT) ++ | (((tm.tm_hour) & TOY_HOUR_MASK) << TOY_HOUR_SHIFT) ++ | (((tm.tm_min) & TOY_MIN_MASK) << TOY_MIN_SHIFT) ++ | (((tm.tm_sec) & TOY_SEC_MASK) << TOY_SEC_SHIFT) | 0x0; ++ break; ++ case SYS_TOYREAD1: ++ qemu_get_timedate(&tm, s->offset); ++ val = tm.tm_year; ++ break; ++ case SYS_TOYMATCH0: ++ val = s->toymatch[0]; ++ break; ++ case SYS_TOYMATCH1: ++ val = s->toymatch[1]; ++ break; ++ case SYS_TOYMATCH2: ++ val = s->toymatch[2]; ++ break; ++ case SYS_RTCCTRL: ++ val = s->cntrctl; ++ break; ++ case SYS_RTCREAD0: ++ val = s->rtccount; ++ break; ++ case SYS_RTCMATCH0: ++ val = s->rtcmatch[0]; ++ break; ++ case SYS_RTCMATCH1: ++ val = s->rtcmatch[1]; ++ break; ++ case SYS_RTCMATCH2: ++ val = s->rtcmatch[2]; ++ break; ++ default: ++ val = 0; ++ break; ++ } ++ return val; ++} ++ ++ ++static void ls7a_rtc_write(void *opaque, hwaddr addr, ++ uint64_t val, unsigned size) ++{ ++ LS7A_RTCState *s = (LS7A_RTCState *)opaque; ++ struct tm tm; ++ int64_t alarm_offset, year_diff, expire_time; ++ ++ switch (addr) { ++ case SYS_TOYWRITE0: ++ qemu_get_timedate(&tm, s->offset); ++ tm.tm_sec = (val >> TOY_SEC_SHIFT) & TOY_SEC_MASK; ++ tm.tm_min = (val >> TOY_MIN_SHIFT) & TOY_MIN_MASK; ++ tm.tm_hour = (val >> TOY_HOUR_SHIFT) & TOY_HOUR_MASK; ++ tm.tm_mday = ((val >> TOY_DAY_SHIFT) & TOY_DAY_MASK); ++ tm.tm_mon = ((val >> TOY_MON_SHIFT) & TOY_MON_MASK) - 1; ++ s->offset = qemu_timedate_diff(&tm); ++ break; ++ case SYS_TOYWRITE1: ++ qemu_get_timedate(&tm, s->offset); ++ tm.tm_year = val; ++ s->offset = qemu_timedate_diff(&tm); ++ break; ++ case SYS_TOYMATCH0: ++ s->toymatch[0] = val; ++ qemu_get_timedate(&tm, s->offset); ++ tm.tm_sec = (val >> TOY_MATCH_SEC_SHIFT) & TOY_MATCH_SEC_MASK; ++ tm.tm_min = (val >> TOY_MATCH_MIN_SHIFT) & TOY_MATCH_MIN_MASK; ++ tm.tm_hour = ((val >> TOY_MATCH_HOUR_SHIFT) & TOY_MATCH_HOUR_MASK); ++ tm.tm_mday = ((val >> TOY_MATCH_DAY_SHIFT) & TOY_MATCH_DAY_MASK); ++ tm.tm_mon = ((val >> TOY_MATCH_MON_SHIFT) & TOY_MATCH_MON_MASK) - 1; ++ year_diff = ((val >> TOY_MATCH_YEAR_SHIFT) & TOY_MATCH_YEAR_MASK); ++ year_diff = year_diff - (tm.tm_year & TOY_MATCH_YEAR_MASK); ++ tm.tm_year = tm.tm_year + year_diff; ++ alarm_offset = qemu_timedate_diff(&tm) - s->offset; ++ if ((alarm_offset < 0) && (alarm_offset > -5)) { ++ alarm_offset = 0; ++ } ++ expire_time = qemu_clock_get_ms(rtc_clock); ++ expire_time += ((alarm_offset * 1000) + 100); ++ timer_mod(s->timer, expire_time); ++ break; ++ case SYS_TOYMATCH1: ++ s->toymatch[1] = val; ++ break; ++ case SYS_TOYMATCH2: ++ s->toymatch[2] = val; ++ break; ++ case SYS_RTCCTRL: ++ s->cntrctl = val; ++ break; ++ case SYS_RTCWRTIE0: ++ s->rtccount = val; ++ break; ++ case SYS_RTCMATCH0: ++ s->rtcmatch[0] = val; ++ break; ++ case SYS_RTCMATCH1: ++ val = s->rtcmatch[1]; ++ break; ++ case SYS_RTCMATCH2: ++ val = s->rtcmatch[2]; ++ break; ++ default: ++ break; ++ } ++} ++ ++static const MemoryRegionOps ls7a_rtc_ops = { ++ .read = ls7a_rtc_read, ++ .write = ls7a_rtc_write, ++ .endianness = DEVICE_NATIVE_ENDIAN, ++ .valid = { ++ .min_access_size = 4, ++ .max_access_size = 4, ++ }, ++ ++}; ++ ++static void toy_timer(void *opaque) ++{ ++ LS7A_RTCState *s = (LS7A_RTCState *) opaque; ++ ++ if (s->cntrctl & TOY_ENABLE_BIT) { ++ qemu_irq_pulse(s->toy_irq); ++ } ++} ++ ++static void ls7a_rtc_realize(DeviceState *dev, Error **errp) ++{ ++ SysBusDevice *sbd = SYS_BUS_DEVICE(dev); ++ LS7A_RTCState *d = LS7A_RTC(sbd); ++ memory_region_init_io(&d->iomem, NULL, &ls7a_rtc_ops, ++ (void *)d, "ls7a_rtc", 0x100); ++ ++ sysbus_init_irq(sbd, &d->toy_irq); ++ ++ sysbus_init_mmio(sbd, &d->iomem); ++ d->timer = timer_new_ms(rtc_clock, toy_timer, d); ++ timer_mod(d->timer, qemu_clock_get_ms(rtc_clock) + 100); ++ d->offset = 0; ++} ++ ++static int ls7a_rtc_pre_save(void *opaque) ++{ ++ LS7A_RTCState *s = (LS7A_RTCState *)opaque; ++ struct tm tm; ++ int64_t year_diff, value; ++ ++ value = s->toymatch[0]; ++ qemu_get_timedate(&tm, s->offset); ++ tm.tm_sec = (value >> TOY_MATCH_SEC_SHIFT) & TOY_MATCH_SEC_MASK; ++ tm.tm_min = (value >> TOY_MATCH_MIN_SHIFT) & TOY_MATCH_MIN_MASK; ++ tm.tm_hour = ((value >> TOY_MATCH_HOUR_SHIFT) & TOY_MATCH_HOUR_MASK); ++ tm.tm_mday = ((value >> TOY_MATCH_DAY_SHIFT) & TOY_MATCH_DAY_MASK); ++ tm.tm_mon = ((value >> TOY_MATCH_MON_SHIFT) & TOY_MATCH_MON_MASK) - 1; ++ year_diff = ((value >> TOY_MATCH_YEAR_SHIFT) & TOY_MATCH_YEAR_MASK); ++ year_diff = year_diff - (tm.tm_year & TOY_MATCH_YEAR_MASK); ++ tm.tm_year = tm.tm_year + year_diff; ++ s->save_alarm_offset = qemu_timedate_diff(&tm) - s->offset; ++ ++ return 0; ++} ++ ++ ++static int ls7a_rtc_post_load(void *opaque, int version_id) ++{ ++ LS7A_RTCState *s = (LS7A_RTCState *)opaque; ++ int64_t expire_time; ++ ++ expire_time = qemu_clock_get_ms(rtc_clock) + (s->save_alarm_offset * 1000); ++ timer_mod(s->timer, expire_time); ++ ++ return 0; ++} ++ ++static const VMStateDescription vmstate_ls7a_rtc = { ++ .name = "ls7a_rtc", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .pre_save = ls7a_rtc_pre_save, ++ .post_load = ls7a_rtc_post_load, ++ .fields = (VMStateField[]) { ++ VMSTATE_INT64(offset, LS7A_RTCState), ++ VMSTATE_INT64(save_alarm_offset, LS7A_RTCState), ++ VMSTATE_UINT32(toymatch[0], LS7A_RTCState), ++ VMSTATE_UINT32(cntrctl, LS7A_RTCState), ++ VMSTATE_END_OF_LIST() ++ } ++}; ++ ++ ++static void ls7a_rtc_class_init(ObjectClass *klass, void *data) ++{ ++ DeviceClass *dc = DEVICE_CLASS(klass); ++ dc->vmsd = &vmstate_ls7a_rtc; ++ dc->realize = ls7a_rtc_realize; ++ dc->desc = "ls7a rtc"; ++} ++ ++static const TypeInfo ls7a_rtc_info = { ++ .name = TYPE_LS7A_RTC, ++ .parent = TYPE_SYS_BUS_DEVICE, ++ .instance_size = sizeof(LS7A_RTCState), ++ .class_init = ls7a_rtc_class_init, ++}; ++ ++static void ls7a_rtc_register_types(void) ++{ ++ type_register_static(&ls7a_rtc_info); ++} ++ ++type_init(ls7a_rtc_register_types) +diff --git a/hw/timer/meson.build b/hw/timer/meson.build +index 03092e2ceb..e841a2f6ee 100644 +--- a/hw/timer/meson.build ++++ b/hw/timer/meson.build +@@ -16,6 +16,7 @@ softmmu_ss.add(when: 'CONFIG_EXYNOS4', if_true: files('exynos4210_mct.c')) + softmmu_ss.add(when: 'CONFIG_EXYNOS4', if_true: files('exynos4210_pwm.c')) + softmmu_ss.add(when: 'CONFIG_GRLIB', if_true: files('grlib_gptimer.c')) + softmmu_ss.add(when: 'CONFIG_HPET', if_true: files('hpet.c')) ++softmmu_ss.add(when: 'CONFIG_LS7A_RTC', if_true: files('ls7a_rtc.c')) + softmmu_ss.add(when: 'CONFIG_I8254', if_true: files('i8254_common.c', 'i8254.c')) + softmmu_ss.add(when: 'CONFIG_IMX', if_true: files('imx_epit.c')) + softmmu_ss.add(when: 'CONFIG_IMX', if_true: files('imx_gpt.c')) +-- +2.27.0 + diff --git a/0003-Add-loongarch-machine.patch b/0003-Add-loongarch-machine.patch new file mode 100644 index 0000000..c1617ba --- /dev/null +++ b/0003-Add-loongarch-machine.patch @@ -0,0 +1,5752 @@ +From 2562504ad867de4a0539c261983c08cd5108bfe4 Mon Sep 17 00:00:00 2001 +From: lixianglai +Date: Fri, 19 Aug 2022 23:39:00 -0400 +Subject: [PATCH 3/8] Add loongarch machine. + +Change-Id: I7e31f874c676b740269945d5e19c6bc836de6a99 +Signed-off-by: lixianglai +--- + hw/loongarch/Kconfig | 17 + + hw/loongarch/acpi-build.c | 783 ++++++++++++ + hw/loongarch/acpi-build.h | 16 + + hw/loongarch/apic.c | 675 +++++++++++ + hw/loongarch/ioapic.c | 422 +++++++ + hw/loongarch/iocsr.c | 219 ++++ + hw/loongarch/ipi.c | 267 +++++ + hw/loongarch/larch_3a.c | 2026 ++++++++++++++++++++++++++++++++ + hw/loongarch/larch_hotplug.c | 355 ++++++ + hw/loongarch/larch_int.c | 91 ++ + hw/loongarch/ls7a_nb.c | 352 ++++++ + hw/loongarch/meson.build | 15 + + include/hw/loongarch/bios.h | 5 + + include/hw/loongarch/cpudevs.h | 53 + + include/hw/loongarch/larch.h | 163 +++ + include/hw/loongarch/ls7a.h | 152 +++ + 16 files changed, 5611 insertions(+) + create mode 100644 hw/loongarch/Kconfig + create mode 100644 hw/loongarch/acpi-build.c + create mode 100644 hw/loongarch/acpi-build.h + create mode 100644 hw/loongarch/apic.c + create mode 100644 hw/loongarch/ioapic.c + create mode 100644 hw/loongarch/iocsr.c + create mode 100644 hw/loongarch/ipi.c + create mode 100644 hw/loongarch/larch_3a.c + create mode 100644 hw/loongarch/larch_hotplug.c + create mode 100644 hw/loongarch/larch_int.c + create mode 100644 hw/loongarch/ls7a_nb.c + create mode 100644 hw/loongarch/meson.build + create mode 100644 include/hw/loongarch/bios.h + create mode 100644 include/hw/loongarch/cpudevs.h + create mode 100644 include/hw/loongarch/larch.h + create mode 100644 include/hw/loongarch/ls7a.h + +diff --git a/hw/loongarch/Kconfig b/hw/loongarch/Kconfig +new file mode 100644 +index 0000000000..3fe2677fda +--- /dev/null ++++ b/hw/loongarch/Kconfig +@@ -0,0 +1,17 @@ ++config LS7A_APIC ++ bool ++ ++config LS7A_RTC ++ bool ++ ++config LOONGSON3A ++ bool ++ ++config MEM_HOTPLUG ++ bool ++ ++config ACPI_LOONGARCH ++ bool ++ ++config E1000E_PCI ++ bool +diff --git a/hw/loongarch/acpi-build.c b/hw/loongarch/acpi-build.c +new file mode 100644 +index 0000000000..6ba637be53 +--- /dev/null ++++ b/hw/loongarch/acpi-build.c +@@ -0,0 +1,783 @@ ++/* Support for generating ACPI tables and passing them to Guests ++ * ++ * Copyright (C) 2008-2010 Kevin O'Connor ++ * Copyright (C) 2006 Fabrice Bellard ++ * Copyright (C) 2013 Red Hat Inc ++ * ++ * Author: Michael S. Tsirkin ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, see . ++ */ ++ ++#include "qemu/osdep.h" ++#include "qapi/error.h" ++#include "qapi/qmp/qnum.h" ++#include "acpi-build.h" ++#include "qemu-common.h" ++#include "qemu/bitmap.h" ++#include "qemu/error-report.h" ++#include "hw/pci/pci.h" ++#include "hw/boards.h" ++#include "hw/core/cpu.h" ++#include "target/loongarch64/cpu.h" ++#include "hw/misc/pvpanic.h" ++#include "hw/timer/hpet.h" ++#include "hw/acpi/acpi-defs.h" ++#include "hw/acpi/acpi.h" ++#include "hw/acpi/cpu.h" ++#include "hw/nvram/fw_cfg.h" ++#include "hw/acpi/bios-linker-loader.h" ++#include "hw/loader.h" ++#include "hw/isa/isa.h" ++#include "hw/block/fdc.h" ++#include "hw/acpi/memory_hotplug.h" ++#include "sysemu/tpm.h" ++#include "hw/acpi/tpm.h" ++#include "hw/acpi/vmgenid.h" ++#include "sysemu/tpm_backend.h" ++#include "hw/rtc/mc146818rtc_regs.h" ++#include "sysemu/numa.h" ++#include "sysemu/runstate.h" ++#include "sysemu/reset.h" ++#include "migration/vmstate.h" ++#include "hw/mem/memory-device.h" ++#include "hw/acpi/utils.h" ++#include "hw/acpi/pci.h" ++/* Supported chipsets: */ ++#include "hw/acpi/aml-build.h" ++#include "hw/loongarch/larch.h" ++#include "hw/loongarch/ls7a.h" ++ ++#include "hw/acpi/ipmi.h" ++#include "hw/acpi/ls7a.h" ++ ++/* These are used to size the ACPI tables for -M pc-i440fx-1.7 and ++ * -M pc-i440fx-2.0. Even if the actual amount of AML generated grows ++ * a little bit, there should be plenty of free space since the DSDT ++ * shrunk by ~1.5k between QEMU 2.0 and QEMU 2.1. ++ */ ++#define ACPI_BUILD_ALIGN_SIZE 0x1000 ++ ++#define ACPI_BUILD_TABLE_SIZE 0x20000 ++ ++/* #define DEBUG_ACPI_BUILD */ ++#ifdef DEBUG_ACPI_BUILD ++#define ACPI_BUILD_DPRINTF(fmt, ...) \ ++ do {printf("ACPI_BUILD: " fmt, ## __VA_ARGS__); } while (0) ++#else ++#define ACPI_BUILD_DPRINTF(fmt, ...) ++#endif ++ ++/* Default IOAPIC ID */ ++#define ACPI_BUILD_IOAPIC_ID 0x0 ++ ++/* PCI fw r3.0 MCFG table. */ ++/* Subtable */ ++ ++typedef struct AcpiMiscInfo { ++ bool is_piix4; ++ bool has_hpet; ++ TPMVersion tpm_version; ++ const unsigned char *dsdt_code; ++ unsigned dsdt_size; ++ uint16_t pvpanic_port; ++ uint16_t applesmc_io_base; ++} AcpiMiscInfo; ++ ++typedef struct AcpiBuildPciBusHotplugState { ++ GArray *device_table; ++ GArray *notify_table; ++ struct AcpiBuildPciBusHotplugState *parent; ++ bool pcihp_bridge_en; ++} AcpiBuildPciBusHotplugState; ++ ++static void init_common_fadt_data(AcpiFadtData *data) ++{ ++ AmlAddressSpace as = AML_AS_SYSTEM_MEMORY; ++ uint64_t base = LS7A_ACPI_REG_BASE; ++ AcpiFadtData fadt = { ++ .rev = 3, ++ .flags = ++ (1 << ACPI_FADT_F_WBINVD) | ++ (1 << ACPI_FADT_F_PROC_C1) | ++ (1 << ACPI_FADT_F_SLP_BUTTON) | ++ (1 << ACPI_FADT_F_TMR_VAL_EXT) | ++ (1 << ACPI_FADT_F_RESET_REG_SUP) , ++ .plvl2_lat = 0xfff /* C2 state not supported */, ++ .plvl3_lat = 0xfff /* C3 state not supported */, ++ .smi_cmd = 0x00, ++ .sci_int = ACPI_SCI_IRQ, ++ .acpi_enable_cmd = 0x00, ++ .acpi_disable_cmd = 0x00, ++ .pm1a_evt = { .space_id = as, .bit_width = 8 * 8, ++ .address = base + LS7A_PM_EVT_BLK }, ++ .pm1a_cnt = { .space_id = as, .bit_width = 4 * 8, ++ .address = base + LS7A_PM_CNT_BLK }, ++ .pm_tmr = { .space_id = as, .bit_width = 4 * 8, ++ .address = base + LS7A_PM_TMR_BLK }, ++ .gpe0_blk = { .space_id = as, .bit_width = 8 * 8, ++ .address = base + LS7A_GPE0_STS_REG}, ++ .reset_reg = { .space_id = as, .bit_width = 4 * 8, ++ .address = base + LS7A_GPE0_RESET_REG}, ++ .reset_val = 0x1, ++ }; ++ *data = fadt; ++} ++ ++static void acpi_align_size(GArray *blob, unsigned align) ++{ ++ /* Align size to multiple of given size. This reduces the chance ++ * we need to change size in the future (breaking cross version migration). ++ */ ++ g_array_set_size(blob, ROUND_UP(acpi_data_len(blob), align)); ++} ++ ++/* FACS */ ++static void ++build_facs(GArray *table_data) ++{ ++ const char *sig = "FACS"; ++ const uint8_t reserved[40] = {}; ++ ++ g_array_append_vals(table_data, sig, 4); /* Signature */ ++ build_append_int_noprefix(table_data, 64, 4); /* Length */ ++ build_append_int_noprefix(table_data, 0, 4); /* Hardware Signature */ ++ build_append_int_noprefix(table_data, 0, 4); /* Firmware Waking Vector */ ++ build_append_int_noprefix(table_data, 0, 4); /* Global Lock */ ++ build_append_int_noprefix(table_data, 0, 4); /* Flags */ ++ g_array_append_vals(table_data, reserved, 40); /* Reserved */ ++} ++ ++void ls7a_madt_cpu_entry(AcpiDeviceIf *adev, int uid, ++ const CPUArchIdList *apic_ids, GArray *entry, bool force_enabled) ++{ ++ uint32_t apic_id = apic_ids->cpus[uid].arch_id; ++ /* Flags – Local APIC Flags */ ++ uint32_t flags = apic_ids->cpus[uid].cpu != NULL || force_enabled ? ++ 1 /* Enabled */ : 0; ++ ++ /* Rev 1.0b, Table 5-13 Processor Local APIC Structure */ ++ build_append_int_noprefix(entry, 0, 1); /* Type */ ++ build_append_int_noprefix(entry, 8, 1); /* Length */ ++ build_append_int_noprefix(entry, uid, 1); /* ACPI Processor ID */ ++ build_append_int_noprefix(entry, apic_id, 1); /* APIC ID */ ++ build_append_int_noprefix(entry, flags, 4); /* Flags */ ++} ++static void build_ioapic(GArray *entry, uint8_t id, uint32_t addr, uint32_t irq) ++{ ++ /* Rev 1.0b, 5.2.8.2 IO APIC */ ++ build_append_int_noprefix(entry, 1, 1); /* Type */ ++ build_append_int_noprefix(entry, 12, 1); /* Length */ ++ build_append_int_noprefix(entry, id, 1); /* IO APIC ID */ ++ build_append_int_noprefix(entry, 0, 1); /* Reserved */ ++ build_append_int_noprefix(entry, addr, 4); /* IO APIC Address */ ++ build_append_int_noprefix(entry, irq, 4); /* System Vector Base */ ++} ++ ++static void ++build_madt(GArray *table_data, BIOSLinker *linker, LoongarchMachineState *lsms) ++{ ++ LoongarchMachineClass *lsmc = LoongarchMACHINE_GET_CLASS(lsms); ++ MachineClass *mc = MACHINE_GET_CLASS(lsms); ++ const CPUArchIdList *apic_ids = mc->possible_cpu_arch_ids(MACHINE(lsms)); ++ AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(lsms->acpi_dev); ++ AcpiDeviceIf *adev = ACPI_DEVICE_IF(lsms->acpi_dev); ++ int i; ++ AcpiTable table = { .sig = "APIC", .rev = 1, .oem_id = lsms->oem_id, ++ .oem_table_id = lsms->oem_table_id}; ++ ++ acpi_table_begin(&table, table_data); ++ ++ /* Local APIC Address */ ++ build_append_int_noprefix(table_data, 0, 4); ++ build_append_int_noprefix(table_data, 1 /* PCAT_COMPAT */, 4); /* Flags */ ++ ++ ++ for (i = 0; i < apic_ids->len; i++) { ++ adevc->madt_cpu(adev, i, apic_ids, table_data, false); ++ } ++ ++ ++ build_ioapic(table_data, ACPI_BUILD_IOAPIC_ID, lsmc->ls7a_ioapic_reg_base, LOONGARCH_PCH_IRQ_BASE); ++ ++ /* Rev 1.0b, 5.2.8.3.3 Local APIC NMI */ ++ build_append_int_noprefix(table_data, 3, 1); /* Type */ ++ build_append_int_noprefix(table_data, 6, 1); /* Length */ ++ /* ACPI Processor ID */ ++ build_append_int_noprefix(table_data, 0xFF /* all processors */, 1); ++ build_append_int_noprefix(table_data, 0, 2); /* Flags */ ++ /* Local APIC INTI# */ ++ build_append_int_noprefix(table_data, 1 /* ACPI_LINT1 */, 1); ++ ++ /* Rev 1.0b, 5.2.8.3.3 Local APIC NMI */ ++ build_append_int_noprefix(table_data, 4, 1); /* Type */ ++ build_append_int_noprefix(table_data, 6, 1); /* Length */ ++ /* ACPI Processor ID */ ++ build_append_int_noprefix(table_data, 0xFF /* all processors */, 1); ++ build_append_int_noprefix(table_data, 0, 2); /* Flags */ ++ /* Local APIC INTI# */ ++ build_append_int_noprefix(table_data, 1 /* ACPI_LINT1 */, 1); ++ ++ ++ acpi_table_end(linker, &table); ++} ++ ++static void ++build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine) ++{ ++ uint64_t i, mem_len, mem_base; ++ MachineClass *mc = MACHINE_GET_CLASS(machine); ++ LoongarchMachineState *lsms = LoongarchMACHINE(machine); ++ const CPUArchIdList *apic_ids = mc->possible_cpu_arch_ids(machine); ++ int nb_numa_nodes = machine->numa_state->num_nodes; ++ NodeInfo *numa_info = machine->numa_state->nodes; ++ AcpiTable table = { .sig = "SRAT", .rev = 1, .oem_id = lsms->oem_id, ++ .oem_table_id = lsms->oem_table_id}; ++ ++ acpi_table_begin(&table, table_data); ++ build_append_int_noprefix(table_data, 1, 4); /* Reserved */ ++ build_append_int_noprefix(table_data, 0, 8); /* Reserved */ ++ ++ for (i = 0; i < apic_ids->len; ++i) { ++ /* 5.2.15.1 Processor Local APIC/SAPIC Affinity Structure */ ++ build_append_int_noprefix(table_data, 0, 1); /* Type */ ++ build_append_int_noprefix(table_data, 16, 1); /* Length */ ++ /* Proximity Domain [7:0] */ ++ build_append_int_noprefix(table_data, apic_ids->cpus[i].props.node_id, 1); ++ build_append_int_noprefix(table_data, apic_ids->cpus[i].arch_id, 1); /* APIC ID */ ++ /* Flags, Table 5-36 */ ++ build_append_int_noprefix(table_data, 1, 4); ++ build_append_int_noprefix(table_data, 0, 1); /* Local SAPIC EID */ ++ /* Proximity Domain [31:8] */ ++ build_append_int_noprefix(table_data, 0, 3); ++ build_append_int_noprefix(table_data, 0, 4); /* Reserved */ ++ } ++ ++ /* node0 */ ++ mem_base = (uint64_t)0; ++ mem_len = 0x10000000; ++ build_srat_memory(table_data, mem_base, mem_len, ++ 0, MEM_AFFINITY_ENABLED); ++ mem_base = 0x90000000; ++ if (!nb_numa_nodes) { ++ mem_len = machine->ram_size - 0x10000000; ++ } else { ++ mem_len = numa_info[0].node_mem - 0x10000000; ++ } ++ ++ build_srat_memory(table_data, mem_base, mem_len, ++ 0, MEM_AFFINITY_ENABLED); ++ mem_base += mem_len; ++ ++ /* node1 ~ nodemax */ ++ for (i = 1; i < nb_numa_nodes; ++i) { ++ mem_len = numa_info[i].node_mem; ++ build_srat_memory(table_data, mem_base, mem_len, ++ i, MEM_AFFINITY_ENABLED); ++ mem_base += mem_len; ++ } ++ ++ if (lsms->hotplug_memory_size) { ++ build_srat_memory(table_data, machine->device_memory->base, ++ lsms->hotplug_memory_size, 0, ++ MEM_AFFINITY_HOTPLUGGABLE | MEM_AFFINITY_ENABLED); ++ } ++ ++ acpi_table_end(linker, &table); ++ ++} ++ ++typedef ++struct AcpiBuildState { ++ /* Copy of table in RAM (for patching). */ ++ MemoryRegion *table_mr; ++ /* Is table patched? */ ++ uint8_t patched; ++ void *rsdp; ++ MemoryRegion *rsdp_mr; ++ MemoryRegion *linker_mr; ++} AcpiBuildState; ++ ++static void build_ls7a_pci0_int(Aml *table) ++{ ++ Aml *sb_scope = aml_scope("_SB"); ++ Aml *pci0_scope = aml_scope("PCI0"); ++ Aml *prt_pkg = aml_varpackage(128); ++ int slot, pin; ++ ++ for (slot = 0; slot < PCI_SLOT_MAX; slot++) { ++ for (pin = 0; pin < PCI_NUM_PINS; pin++) { ++ Aml *pkg = aml_package(4); ++ aml_append(pkg, aml_int((slot << 16) | 0xFFFF)); ++ aml_append(pkg, aml_int(pin)); ++ aml_append(pkg, aml_int(0)); ++ aml_append(pkg, aml_int(LOONGARCH_PCH_IRQ_BASE + 16 + (slot * 4 + pin) % 16)); ++ aml_append(prt_pkg, pkg); ++ } ++ } ++ aml_append(pci0_scope, ++ aml_name_decl("_PRT", prt_pkg)); ++ ++ aml_append(sb_scope, pci0_scope); ++ ++ aml_append(table, sb_scope); ++} ++ ++static void build_dbg_aml(Aml *table) ++{ ++ Aml *field; ++ Aml *method; ++ Aml *while_ctx; ++ Aml *scope = aml_scope("\\"); ++ Aml *buf = aml_local(0); ++ Aml *len = aml_local(1); ++ Aml *idx = aml_local(2); ++ ++ aml_append(scope, ++ aml_operation_region("DBG", AML_SYSTEM_IO, aml_int(0x0402), 0x01)); ++ field = aml_field("DBG", AML_BYTE_ACC, AML_NOLOCK, AML_PRESERVE); ++ aml_append(field, aml_named_field("DBGB", 8)); ++ aml_append(scope, field); ++ ++ method = aml_method("DBUG", 1, AML_NOTSERIALIZED); ++ ++ aml_append(method, aml_to_hexstring(aml_arg(0), buf)); ++ aml_append(method, aml_to_buffer(buf, buf)); ++ aml_append(method, aml_subtract(aml_sizeof(buf), aml_int(1), len)); ++ aml_append(method, aml_store(aml_int(0), idx)); ++ ++ while_ctx = aml_while(aml_lless(idx, len)); ++ aml_append(while_ctx, ++ aml_store(aml_derefof(aml_index(buf, idx)), aml_name("DBGB"))); ++ aml_append(while_ctx, aml_increment(idx)); ++ aml_append(method, while_ctx); ++ ++ aml_append(method, aml_store(aml_int(0x0A), aml_name("DBGB"))); ++ aml_append(scope, method); ++ ++ aml_append(table, scope); ++} ++ ++static Aml *build_ls7a_osc_method(void) ++{ ++ Aml *if_ctx; ++ Aml *if_ctx2; ++ Aml *else_ctx; ++ Aml *method; ++ Aml *a_cwd1 = aml_name("CDW1"); ++ Aml *a_ctrl = aml_local(0); ++ ++ method = aml_method("_OSC", 4, AML_NOTSERIALIZED); ++ aml_append(method, aml_create_dword_field(aml_arg(3), aml_int(0), "CDW1")); ++ ++ if_ctx = aml_if(aml_equal( ++ aml_arg(0), aml_touuid("33DB4D5B-1FF7-401C-9657-7441C03DD766"))); ++ aml_append(if_ctx, aml_create_dword_field(aml_arg(3), aml_int(4), "CDW2")); ++ aml_append(if_ctx, aml_create_dword_field(aml_arg(3), aml_int(8), "CDW3")); ++ ++ aml_append(if_ctx, aml_store(aml_name("CDW3"), a_ctrl)); ++ ++ /* ++ * Always allow native PME, AER (no dependencies) ++ * Allow SHPC (PCI bridges can have SHPC controller) ++ */ ++ aml_append(if_ctx, aml_and(a_ctrl, aml_int(0x1F), a_ctrl)); ++ ++ if_ctx2 = aml_if(aml_lnot(aml_equal(aml_arg(1), aml_int(1)))); ++ /* Unknown revision */ ++ aml_append(if_ctx2, aml_or(a_cwd1, aml_int(0x08), a_cwd1)); ++ aml_append(if_ctx, if_ctx2); ++ ++ if_ctx2 = aml_if(aml_lnot(aml_equal(aml_name("CDW3"), a_ctrl))); ++ /* Capabilities bits were masked */ ++ aml_append(if_ctx2, aml_or(a_cwd1, aml_int(0x10), a_cwd1)); ++ aml_append(if_ctx, if_ctx2); ++ ++ /* Update DWORD3 in the buffer */ ++ aml_append(if_ctx, aml_store(a_ctrl, aml_name("CDW3"))); ++ aml_append(method, if_ctx); ++ ++ else_ctx = aml_else(); ++ /* Unrecognized UUID */ ++ aml_append(else_ctx, aml_or(a_cwd1, aml_int(4), a_cwd1)); ++ aml_append(method, else_ctx); ++ ++ aml_append(method, aml_return(aml_arg(3))); ++ return method; ++} ++ ++static void build_ls7a_rtc_device_aml(Aml *table) ++{ ++ Aml *dev; ++ Aml *crs; ++ uint32_t rtc_irq = LS7A_RTC_IRQ; ++ ++ Aml *scope = aml_scope("_SB"); ++ dev = aml_device("RTC"); ++ aml_append(dev, aml_name_decl("_HID", aml_string("LOON0001"))); ++ crs = aml_resource_template(); ++ aml_append(crs, ++ aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED, ++ AML_NON_CACHEABLE, AML_READ_WRITE, ++ 0, LS7A_RTC_REG_BASE, ++ LS7A_RTC_REG_BASE + LS7A_RTC_LEN - 1, 0, LS7A_RTC_LEN)); ++ aml_append(crs, aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH, ++ AML_EXCLUSIVE, &rtc_irq, 1)); ++ ++ aml_append(dev, aml_name_decl("_CRS", crs)); ++ aml_append(scope, dev); ++ aml_append(table, scope); ++} ++ ++static void build_ls7a_uart_device_aml(Aml *table) ++{ ++ Aml *dev; ++ Aml *crs; ++ Aml *pkg0, *pkg1, *pkg2; ++ uint32_t uart_irq = LS7A_UART_IRQ; ++ ++ Aml *scope = aml_scope("_SB"); ++ dev = aml_device("COMA"); ++ aml_append(dev, aml_name_decl("_HID", aml_string("PNP0501"))); ++ aml_append(dev, aml_name_decl("_UID", aml_int(0))); ++ aml_append(dev, aml_name_decl("_CCA", aml_int(1))); ++ crs = aml_resource_template(); ++ aml_append(crs, ++ aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED, ++ AML_NON_CACHEABLE, AML_READ_WRITE, ++ 0, LS7A_UART_BASE, LS7A_UART_BASE + LS7A_UART_LEN - 1, 0, 0x8)); ++ aml_append(crs, aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH, ++ AML_EXCLUSIVE, &uart_irq, 1)); ++ aml_append(dev, aml_name_decl("_CRS", crs)); ++ pkg0 = aml_package(0x2); ++ aml_append(pkg0, aml_int(0x01F78A40)); ++ aml_append(pkg0, aml_string("clock-frenquency")); ++ pkg1 = aml_package(0x1); ++ aml_append(pkg1, pkg0); ++ pkg2 = aml_package(0x2); ++ aml_append(pkg2, aml_touuid("DAFFD814-6EBA-4D8C-8A91-BC9BBF4AA301")); ++ aml_append(pkg2, pkg1); ++ ++ aml_append(dev, aml_name_decl("_DSD", pkg2)); ++ ++ aml_append(scope, dev); ++ aml_append(table, scope); ++} ++ ++static void ++build_dsdt(GArray *table_data, BIOSLinker *linker, MachineState *machine) ++{ ++ Aml *dsdt, *sb_scope, *scope, *dev, *crs, *pkg; ++ LoongarchMachineState *lsms = LoongarchMACHINE(machine); ++ uint32_t nr_mem = machine->ram_slots; ++ uint64_t base = LS7A_ACPI_REG_BASE; ++ int root_bus_limit = PCIE_MMCFG_BUS(LS_PCIECFG_SIZE - 1); ++ AcpiTable table = { .sig = "DSDT", .rev = 1, .oem_id = lsms->oem_id, ++ .oem_table_id = lsms->oem_table_id}; ++ ++ acpi_table_begin(&table, table_data); ++ dsdt = init_aml_allocator(); ++ ++ build_dbg_aml(dsdt); ++ ++ sb_scope = aml_scope("_SB"); ++ dev = aml_device("PCI0"); ++ aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A08"))); ++ aml_append(dev, aml_name_decl("_CID", aml_eisaid("PNP0A03"))); ++ aml_append(dev, aml_name_decl("_ADR", aml_int(0))); ++ aml_append(dev, aml_name_decl("_BBN", aml_int(0))); ++ aml_append(dev, aml_name_decl("_UID", aml_int(1))); ++ aml_append(dev, build_ls7a_osc_method()); ++ aml_append(sb_scope, dev); ++ aml_append(dsdt, sb_scope); ++ ++ build_ls7a_pci0_int(dsdt); ++ build_ls7a_rtc_device_aml(dsdt); ++ build_ls7a_uart_device_aml(dsdt); ++ ++ if (lsms->acpi_dev) { ++ CPUHotplugFeatures opts = { ++ .acpi_1_compatible = true, .has_legacy_cphp = false ++ }; ++ build_cpus_aml(dsdt, machine, opts, CPU_HOTPLUG_BASE, ++ "\\_SB.PCI0", "\\_GPE._E02"); ++ ++ build_memory_hotplug_aml(dsdt, nr_mem, "\\_SB.PCI0", ++ "\\_GPE._E03", AML_SYSTEM_MEMORY, ++ MEMORY_HOTPLUG_BASE); ++ } ++ ++ scope = aml_scope("_GPE"); ++ { ++ aml_append(scope, aml_name_decl("_HID", aml_string("ACPI0006"))); ++ } ++ aml_append(dsdt, scope); ++ ++ scope = aml_scope("\\_SB.PCI0"); ++ /* build PCI0._CRS */ ++ crs = aml_resource_template(); ++ aml_append(crs, ++ aml_word_bus_number(AML_MIN_FIXED, AML_MAX_FIXED, AML_POS_DECODE, ++ 0x0000, 0x0, root_bus_limit, ++ 0x0000, root_bus_limit + 1)); ++ aml_append(crs, ++ aml_word_io(AML_MIN_FIXED, AML_MAX_FIXED, ++ AML_POS_DECODE, AML_ENTIRE_RANGE, ++ 0x0000, 0x4000, 0xFFFF, 0x0000, 0xC000)); ++ aml_append(crs, ++ aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED, ++ AML_CACHEABLE, AML_READ_WRITE, ++ 0, 0x40000000, 0x7FFFFFFF, 0, 0x40000000)); ++ aml_append(scope, aml_name_decl("_CRS", crs)); ++ ++ /* reserve GPE0 block resources */ ++ dev = aml_device("GPE0"); ++ aml_append(dev, aml_name_decl("_HID", aml_string("PNP0A06"))); ++ aml_append(dev, aml_name_decl("_UID", aml_string("GPE0 resources"))); ++ /* device present, functioning, decoding, not shown in UI */ ++ aml_append(dev, aml_name_decl("_STA", aml_int(0xB))); ++ crs = aml_resource_template(); ++ aml_append(crs, ++ aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED, ++ AML_CACHEABLE, AML_READ_WRITE, ++ 0, base + LS7A_GPE0_STS_REG, ++ base + LS7A_GPE0_STS_REG + 0x3, 0, 0x4)); ++ aml_append(dev, aml_name_decl("_CRS", crs)); ++ aml_append(scope, dev); ++ aml_append(dsdt, scope); ++ ++ scope = aml_scope("\\"); ++ pkg = aml_package(4); ++ aml_append(pkg, aml_int(7)); /* PM1a_CNT.SLP_TYP */ ++ aml_append(pkg, aml_int(7)); /* PM1b_CNT.SLP_TYP not impl. */ ++ aml_append(pkg, aml_int(0)); /* reserved */ ++ aml_append(pkg, aml_int(0)); /* reserved */ ++ aml_append(scope, aml_name_decl("_S5", pkg)); ++ aml_append(dsdt, scope); ++ ++ /* copy AML table into ACPI tables blob and patch header there */ ++ g_array_append_vals(table_data, dsdt->buf->data, dsdt->buf->len); ++ acpi_table_end(linker, &table); ++ free_aml_allocator(); ++} ++ ++ ++static ++void acpi_build(AcpiBuildTables *tables, MachineState *machine) ++{ ++ LoongarchMachineState *lsms = LoongarchMACHINE(machine); ++ GArray *table_offsets; ++ AcpiFadtData fadt_data; ++ unsigned facs, rsdt, fadt, dsdt; ++ uint8_t *u; ++ size_t aml_len = 0; ++ GArray *tables_blob = tables->table_data; ++ ++ init_common_fadt_data(&fadt_data); ++ ++ table_offsets = g_array_new(false, true /* clear */, ++ sizeof(uint32_t)); ++ ACPI_BUILD_DPRINTF("init ACPI tables\n"); ++ ++ bios_linker_loader_alloc(tables->linker, ++ ACPI_BUILD_TABLE_FILE, tables_blob, ++ 64 /* Ensure FACS is aligned */, ++ false /* high memory */); ++ ++ /* ++ * FACS is pointed to by FADT. ++ * We place it first since it's the only table that has alignment ++ * requirements. ++ */ ++ facs = tables_blob->len; ++ build_facs(tables_blob); ++ ++ /* DSDT is pointed to by FADT */ ++ dsdt = tables_blob->len; ++ build_dsdt(tables_blob, tables->linker, MACHINE(qdev_get_machine())); ++ ++ /* Count the size of the DSDT and SSDT, we will need it for legacy ++ * sizing of ACPI tables. ++ */ ++ aml_len += tables_blob->len - dsdt; ++ ++ /* ACPI tables pointed to by RSDT */ ++ fadt = tables_blob->len; ++ acpi_add_table(table_offsets, tables_blob); ++ fadt_data.facs_tbl_offset = &facs; ++ fadt_data.dsdt_tbl_offset = &dsdt; ++ fadt_data.xdsdt_tbl_offset = &dsdt; ++ build_fadt(tables_blob, tables->linker, &fadt_data, ++ "LOONGS", "TP-R00"); ++ aml_len += tables_blob->len - fadt; ++ ++ acpi_add_table(table_offsets, tables_blob); ++ build_madt(tables_blob, tables->linker, lsms); ++ ++ acpi_add_table(table_offsets, tables_blob); ++ build_srat(tables_blob, tables->linker, machine); ++ if (machine->numa_state->have_numa_distance) { ++ acpi_add_table(table_offsets, tables_blob); ++ build_slit(tables_blob, tables->linker, machine, lsms->oem_id, ++ lsms->oem_table_id); ++ } ++ ++ /* Build mcfg */ ++ acpi_add_table(table_offsets, tables_blob); ++ { ++ AcpiMcfgInfo mcfg = { ++ .base = LS_PCIECFG_BASE, ++ .size = LS_PCIECFG_SIZE, ++ }; ++ build_mcfg(tables_blob, tables->linker, &mcfg, lsms->oem_id, ++ lsms->oem_table_id); ++ } ++ ++ /* Add tables supplied by user (if any) */ ++ for (u = acpi_table_first(); u; u = acpi_table_next(u)) { ++ unsigned len = acpi_table_len(u); ++ ++ acpi_add_table(table_offsets, tables_blob); ++ g_array_append_vals(tables_blob, u, len); ++ } ++ ++ /* RSDT is pointed to by RSDP */ ++ rsdt = tables_blob->len; ++ build_rsdt(tables_blob, tables->linker, table_offsets, ++ "LOONGS", "TP-R00"); ++ ++ /* RSDP is in FSEG memory, so allocate it separately */ ++ { ++ AcpiRsdpData rsdp_data = { ++ .revision = 0, ++ .oem_id = lsms->oem_id, ++ .xsdt_tbl_offset = NULL, ++ .rsdt_tbl_offset = &rsdt, ++ }; ++ build_rsdp(tables->rsdp, tables->linker, &rsdp_data); ++ } ++ acpi_align_size(tables->linker->cmd_blob, ACPI_BUILD_ALIGN_SIZE); ++ ++ /* Cleanup memory that's no longer used. */ ++ g_array_free(table_offsets, true); ++} ++ ++static void acpi_ram_update(MemoryRegion *mr, GArray *data) ++{ ++ uint32_t size = acpi_data_len(data); ++ ++ /* Make sure RAM size is correct - ++ in case it got changed e.g. by migration */ ++ memory_region_ram_resize(mr, size, &error_abort); ++ ++ memcpy(memory_region_get_ram_ptr(mr), data->data, size); ++ memory_region_set_dirty(mr, 0, size); ++} ++ ++static void acpi_build_update(void *build_opaque) ++{ ++ AcpiBuildState *build_state = build_opaque; ++ AcpiBuildTables tables; ++ ++ /* No state to update or already patched? Nothing to do. */ ++ if (!build_state || build_state->patched) { ++ return; ++ } ++ build_state->patched = 1; ++ ++ acpi_build_tables_init(&tables); ++ ++ acpi_build(&tables, MACHINE(qdev_get_machine())); ++ ++ acpi_ram_update(build_state->table_mr, tables.table_data); ++ ++ if (build_state->rsdp) { ++ memcpy(build_state->rsdp, tables.rsdp->data, ++ acpi_data_len(tables.rsdp)); ++ } else { ++ acpi_ram_update(build_state->rsdp_mr, tables.rsdp); ++ } ++ ++ acpi_ram_update(build_state->linker_mr, tables.linker->cmd_blob); ++ acpi_build_tables_cleanup(&tables, true); ++} ++ ++static void acpi_build_reset(void *build_opaque) ++{ ++ AcpiBuildState *build_state = build_opaque; ++ build_state->patched = 0; ++} ++ ++static const VMStateDescription vmstate_acpi_build = { ++ .name = "acpi_build", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .fields = (VMStateField[]) { ++ VMSTATE_UINT8(patched, AcpiBuildState), ++ VMSTATE_END_OF_LIST() ++ }, ++}; ++ ++void loongarch_acpi_setup(void) ++{ ++ LoongarchMachineState *lsms = LoongarchMACHINE(qdev_get_machine()); ++ AcpiBuildTables tables; ++ AcpiBuildState *build_state; ++ ++ if (!lsms->fw_cfg) { ++ ACPI_BUILD_DPRINTF("No fw cfg. Bailing out.\n"); ++ return; ++ } ++ ++ if (!lsms->acpi_build_enabled) { ++ ACPI_BUILD_DPRINTF("ACPI build disabled. Bailing out.\n"); ++ return; ++ } ++ ++ if (!loongarch_is_acpi_enabled(lsms)) { ++ ACPI_BUILD_DPRINTF("ACPI disabled. Bailing out.\n"); ++ return; ++ } ++ ++ build_state = g_malloc0(sizeof *build_state); ++ ++ acpi_build_tables_init(&tables); ++ acpi_build(&tables, MACHINE(lsms)); ++ ++ /* Now expose it all to Guest */ ++ build_state->table_mr = acpi_add_rom_blob(acpi_build_update, build_state, ++ tables.table_data, ++ ACPI_BUILD_TABLE_FILE); ++ assert(build_state->table_mr != NULL); ++ ++ build_state->linker_mr = ++ acpi_add_rom_blob(acpi_build_update, build_state, tables.linker->cmd_blob, ++ "etc/table-loader"); ++ ++ fw_cfg_add_file(lsms->fw_cfg, ACPI_BUILD_TPMLOG_FILE, ++ tables.tcpalog->data, acpi_data_len(tables.tcpalog)); ++ ++ build_state->rsdp = NULL; ++ build_state->rsdp_mr = acpi_add_rom_blob(acpi_build_update, build_state, tables.rsdp, ++ ACPI_BUILD_RSDP_FILE); ++ ++ qemu_register_reset(acpi_build_reset, build_state); ++ acpi_build_reset(build_state); ++ vmstate_register(NULL, 0, &vmstate_acpi_build, build_state); ++ ++ /* Cleanup tables but don't free the memory: we track it ++ * in build_state. ++ */ ++ acpi_build_tables_cleanup(&tables, false); ++} +diff --git a/hw/loongarch/acpi-build.h b/hw/loongarch/acpi-build.h +new file mode 100644 +index 0000000000..a914268bbe +--- /dev/null ++++ b/hw/loongarch/acpi-build.h +@@ -0,0 +1,16 @@ ++ ++#ifndef HW_LARCH_ACPI_BUILD_H ++#define HW_LARCH_ACPI_BUILD_H ++ ++#define EFI_ACPI_OEM_ID "LARCH" ++#define EFI_ACPI_OEM_TABLE_ID "LARCH" /* OEM table id 8 bytes long */ ++#define EFI_ACPI_OEM_REVISION 0x00000002 ++#define EFI_ACPI_CREATOR_ID "LINUX" ++#define EFI_ACPI_CREATOR_REVISION 0x01000013 ++ ++#define ACPI_COMPATIBLE_1_0 0 ++#define ACPI_COMPATIBLE_2_0 1 ++ ++void loongarch_acpi_setup(void); ++ ++#endif +diff --git a/hw/loongarch/apic.c b/hw/loongarch/apic.c +new file mode 100644 +index 0000000000..d6ba2a2cec +--- /dev/null ++++ b/hw/loongarch/apic.c +@@ -0,0 +1,675 @@ ++/* ++ * Loongarch 3A5000 interrupt controller emulation ++ * ++ * Copyright (C) 2020 Lu Zeng ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ */ ++ ++#include "qemu/osdep.h" ++#include "qapi/error.h" ++#include "hw/boards.h" ++#include "hw/irq.h" ++#include "hw/loongarch/cpudevs.h" ++#include "hw/sysbus.h" ++#include "qemu/host-utils.h" ++#include "qemu/error-report.h" ++#include "sysemu/kvm.h" ++#include "hw/hw.h" ++#include "hw/irq.h" ++#include "target/loongarch64/cpu.h" ++#include "exec/address-spaces.h" ++#include "hw/loongarch/larch.h" ++#include "migration/vmstate.h" ++ ++#define DEBUG_APIC 0 ++ ++#define DPRINTF(fmt, ...) \ ++do { \ ++ if (DEBUG_APIC) { \ ++ fprintf(stderr, "APIC: " fmt , ## __VA_ARGS__); \ ++ } \ ++} while (0) ++ ++#define APIC_OFFSET 0x400 ++#define APIC_BASE (0x1f010000ULL) ++#define EXTIOI_NODETYPE_START (0x4a0 - APIC_OFFSET) ++#define EXTIOI_NODETYPE_END (0x4c0 - APIC_OFFSET) ++#define EXTIOI_IPMAP_START (0x4c0 - APIC_OFFSET) ++#define EXTIOI_IPMAP_END (0x4c8 - APIC_OFFSET) ++#define EXTIOI_ENABLE_START (0x600 - APIC_OFFSET) ++#define EXTIOI_ENABLE_END (0x620 - APIC_OFFSET) ++#define EXTIOI_BOUNCE_START (0x680 - APIC_OFFSET) ++#define EXTIOI_BOUNCE_END (0x6a0 - APIC_OFFSET) ++#define EXTIOI_ISR_START (0x700 - APIC_OFFSET) ++#define EXTIOI_ISR_END (0x720 - APIC_OFFSET) ++#define EXTIOI_COREMAP_START (0xC00 - APIC_OFFSET) ++#define EXTIOI_COREMAP_END (0xD00 - APIC_OFFSET) ++#define EXTIOI_COREISR_START (0x10000) ++#define EXTIOI_COREISR_END (EXTIOI_COREISR_START + 0x10000) ++ ++static int ext_irq_pre_save(void *opaque) ++{ ++#ifdef CONFIG_KVM ++ apicState *apic = opaque; ++ struct loongarch_kvm_irqchip *chip; ++ struct kvm_loongarch_ls3a_extirq_state *kstate; ++ int ret, length, i, vcpuid; ++#endif ++ if (!kvm_irqchip_in_kernel()) { ++ return 0; ++ } ++#ifdef CONFIG_KVM ++ length = sizeof(struct loongarch_kvm_irqchip) + ++ sizeof(struct kvm_loongarch_ls3a_extirq_state); ++ chip = g_malloc0(length); ++ memset(chip, 0, length); ++ chip->chip_id = KVM_IRQCHIP_LS3A_EXTIRQ; ++ chip->len = length; ++ ++ ret = kvm_vm_ioctl(kvm_state, KVM_GET_IRQCHIP, chip); ++ if (ret < 0) { ++ fprintf(stderr, "KVM_GET_IRQCHIP failed: %s\n", strerror(ret)); ++ abort(); ++ } ++ ++ kstate = (struct kvm_loongarch_ls3a_extirq_state *)chip->data; ++ for (i = 0; i < EXTIOI_IRQS_BITMAP_SIZE; i++) { ++ apic->ext_en[i] = kstate->ext_en_r.reg_u8[i]; ++ apic->ext_bounce[i] = kstate->bounce_r.reg_u8[i]; ++ apic->ext_isr[i] = kstate->ext_isr_r.reg_u8[i]; ++ for (vcpuid = 0; vcpuid < MAX_CORES; vcpuid++) { ++ apic->ext_coreisr[vcpuid][i] = kstate->ext_core_isr_r.reg_u8[vcpuid][i]; ++ } ++ } ++ for (i = 0; i < EXTIOI_IRQS_IPMAP_SIZE; i++) { ++ apic->ext_ipmap[i] = kstate->ip_map_r.reg_u8[i]; ++ } ++ for (i = 0; i < EXTIOI_IRQS; i++) { ++ apic->ext_coremap[i] = kstate->core_map_r.reg_u8[i];; ++ } ++ for (i = 0; i < 16; i++) { ++ apic->ext_nodetype[i] = kstate->node_type_r.reg_u16[i]; ++ } ++ g_free(chip); ++#endif ++ return 0; ++} ++ ++static int ext_irq_post_load(void *opaque, int version) ++{ ++#ifdef CONFIG_KVM ++ apicState *apic = opaque; ++ struct loongarch_kvm_irqchip *chip; ++ struct kvm_loongarch_ls3a_extirq_state *kstate; ++ int ret, length, i, vcpuid; ++#endif ++ if (!kvm_irqchip_in_kernel()) { ++ return 0; ++ } ++#ifdef CONFIG_KVM ++ length = sizeof(struct loongarch_kvm_irqchip) + ++ sizeof(struct kvm_loongarch_ls3a_extirq_state); ++ chip = g_malloc0(length); ++ ++ chip->chip_id = KVM_IRQCHIP_LS3A_EXTIRQ; ++ chip->len = length; ++ ++ kstate = (struct kvm_loongarch_ls3a_extirq_state *)chip->data; ++ for (i = 0; i < EXTIOI_IRQS_BITMAP_SIZE; i++) { ++ kstate->ext_en_r.reg_u8[i] = apic->ext_en[i]; ++ kstate->bounce_r.reg_u8[i] = apic->ext_bounce[i]; ++ kstate->ext_isr_r.reg_u8[i] = apic->ext_isr[i]; ++ for (vcpuid = 0; vcpuid < MAX_CORES; vcpuid++) { ++ kstate->ext_core_isr_r.reg_u8[vcpuid][i] = apic->ext_coreisr[vcpuid][i]; ++ } ++ } ++ for (i = 0; i < EXTIOI_IRQS_IPMAP_SIZE; i++) { ++ kstate->ip_map_r.reg_u8[i] = apic->ext_ipmap[i]; ++ } ++ for (i = 0; i < EXTIOI_IRQS; i++) { ++ kstate->core_map_r.reg_u8[i] = apic->ext_coremap[i]; ++ } ++ for (i = 0; i < 16; i++) { ++ kstate->node_type_r.reg_u16[i] = apic->ext_nodetype[i]; ++ } ++ ++ ret = kvm_vm_ioctl(kvm_state, KVM_SET_IRQCHIP, chip); ++ if (ret < 0) { ++ fprintf(stderr, "KVM_SET_IRQCHIP failed: %s\n", strerror(ret)); ++ abort(); ++ } ++ g_free(chip); ++#endif ++ return 0; ++} ++typedef struct nodeApicState { ++ unsigned long addr; ++ int nodeid; ++ apicState *apic; ++} nodeApicState; ++ ++static void ioapic_update_irq(void *opaque, int irq, int level) ++{ ++ apicState *s = opaque; ++ uint8_t ipnum, cpu, cpu_ipnum; ++ unsigned long found1, found2; ++ uint8_t reg_count, reg_bit; ++ ++ reg_count = irq / 32; ++ reg_bit = irq % 32; ++ ++ ipnum = s->ext_sw_ipmap[irq]; ++ cpu = s->ext_sw_coremap[irq]; ++ cpu_ipnum = cpu * LS3A_INTC_IP + ipnum; ++ if (level == 1) { ++ if (test_bit(reg_bit, ((void *)s->ext_en + 0x4 * reg_count)) == false) { ++ return; ++ } ++ ++ if (test_bit(reg_bit, ((void *)s->ext_isr + 0x4 * reg_count)) == false) { ++ return; ++ } ++ bitmap_set(((void *)s->ext_coreisr[cpu] + 0x4 * reg_count), reg_bit, 1); ++ found1 = find_next_bit(((void *)s->ext_ipisr[cpu_ipnum] + 0x4 * reg_count), ++ EXTIOI_IRQS, 0); ++ bitmap_set(((void *)s->ext_ipisr[cpu_ipnum] + 0x4 * reg_count), reg_bit, 1); ++ if (found1 >= EXTIOI_IRQS) { ++ qemu_set_irq(s->parent_irq[cpu][ipnum], level); ++ } ++ } else { ++ bitmap_clear(((void *)s->ext_isr + 0x4 * reg_count), reg_bit, 1); ++ bitmap_clear(((void *)s->ext_coreisr[cpu] + 0x4 * reg_count), reg_bit, 1); ++ found1 = find_next_bit(((void *)s->ext_ipisr[cpu_ipnum] + 0x4 * reg_count), ++ EXTIOI_IRQS, 0); ++ found1 += reg_count * 32; ++ bitmap_clear(((void *)s->ext_ipisr[cpu_ipnum] + 0x4 * reg_count), reg_bit, 1); ++ found2 = find_next_bit(((void *)s->ext_ipisr[cpu_ipnum] + 0x4 * reg_count), ++ EXTIOI_IRQS, 0); ++ if ((found1 < EXTIOI_IRQS) && (found2 >= EXTIOI_IRQS)) { ++ qemu_set_irq(s->parent_irq[cpu][ipnum], level); ++ } ++ } ++} ++ ++static void ioapic_setirq(void *opaque, int irq, int level) ++{ ++ apicState *s = opaque; ++ uint8_t reg_count, reg_bit; ++ ++ reg_count = irq / 32; ++ reg_bit = irq % 32; ++ ++ if (level) { ++ bitmap_set(((void *)s->ext_isr + 0x4 * reg_count), reg_bit, 1); ++ } else { ++ bitmap_clear(((void *)s->ext_isr + 0x4 * reg_count), reg_bit, 1); ++ } ++ ++ ioapic_update_irq(s, irq, level); ++} ++ ++static uint32_t apic_readb(void *opaque, hwaddr addr) ++{ ++ nodeApicState *node; ++ apicState *state; ++ unsigned long off; ++ uint8_t ret; ++ int cpu; ++ ++ node = (nodeApicState *)opaque; ++ state = node->apic; ++ off = addr & 0xfffff; ++ ret = 0; ++ if ((off >= EXTIOI_ENABLE_START) && (off < EXTIOI_ENABLE_END)) { ++ off -= EXTIOI_ENABLE_START; ++ ret = *(uint8_t *)((void *)state->ext_en + off); ++ } else if ((off >= EXTIOI_BOUNCE_START) && (off < EXTIOI_BOUNCE_END)) { ++ off -= EXTIOI_BOUNCE_START; ++ ret = *(uint8_t *)((void *)state->ext_bounce + off); ++ } else if ((off >= EXTIOI_ISR_START) && (off < EXTIOI_ISR_END)) { ++ off -= EXTIOI_ISR_START; ++ ret = *(uint8_t *)((void *)state->ext_isr + off); ++ } else if ((off >= EXTIOI_COREISR_START) && (off < EXTIOI_COREISR_END)) { ++ off -= EXTIOI_COREISR_START; ++ cpu = (off >> 8) & 0xff; ++ ret = *(uint8_t *)((void *)state->ext_coreisr[cpu] + (off & 0x1f)); ++ } else if ((off >= EXTIOI_IPMAP_START) && (off < EXTIOI_IPMAP_END)) { ++ off -= EXTIOI_IPMAP_START; ++ ret = *(uint8_t *)((void *)state->ext_ipmap + off); ++ } else if ((off >= EXTIOI_COREMAP_START) && (off < EXTIOI_COREMAP_END)) { ++ off -= EXTIOI_COREMAP_START; ++ ret = *(uint8_t *)((void *)state->ext_coremap + off); ++ } else if ((off >= EXTIOI_NODETYPE_START) && (off < EXTIOI_NODETYPE_END)) { ++ off -= EXTIOI_NODETYPE_START; ++ ret = *(uint8_t *)((void *)state->ext_nodetype + off); ++ } ++ ++ DPRINTF("readb reg 0x" TARGET_FMT_plx " = %x\n", node->addr + addr, ret); ++ return ret; ++} ++ ++static uint32_t apic_readw(void *opaque, hwaddr addr) ++{ ++ nodeApicState *node; ++ apicState *state; ++ unsigned long off; ++ uint16_t ret; ++ int cpu; ++ ++ node = (nodeApicState *)opaque; ++ state = node->apic; ++ off = addr & 0xfffff; ++ ret = 0; ++ if ((off >= EXTIOI_ENABLE_START) && (off < EXTIOI_ENABLE_END)) { ++ off -= EXTIOI_ENABLE_START; ++ ret = *(uint16_t *)((void *)state->ext_en + off); ++ } else if ((off >= EXTIOI_BOUNCE_START) && (off < EXTIOI_BOUNCE_END)) { ++ off -= EXTIOI_BOUNCE_START; ++ ret = *(uint16_t *)((void *)state->ext_bounce + off); ++ } else if ((off >= EXTIOI_ISR_START) && (off < EXTIOI_ISR_END)) { ++ off -= EXTIOI_ISR_START; ++ ret = *(uint16_t *)((void *)state->ext_isr + off); ++ } else if ((off >= EXTIOI_COREISR_START) && (off < EXTIOI_COREISR_END)) { ++ off -= EXTIOI_COREISR_START; ++ cpu = (off >> 8) & 0xff; ++ ret = *(uint16_t *)((void *)state->ext_coreisr[cpu] + (off & 0x1f)); ++ } else if ((off >= EXTIOI_IPMAP_START) && (off < EXTIOI_IPMAP_END)) { ++ off -= EXTIOI_IPMAP_START; ++ ret = *(uint16_t *)((void *)state->ext_ipmap + off); ++ } else if ((off >= EXTIOI_COREMAP_START) && (off < EXTIOI_COREMAP_END)) { ++ off -= EXTIOI_COREMAP_START; ++ ret = *(uint16_t *)((void *)state->ext_coremap + off); ++ } else if ((off >= EXTIOI_NODETYPE_START) && (off < EXTIOI_NODETYPE_END)) { ++ off -= EXTIOI_NODETYPE_START; ++ ret = *(uint16_t *)((void *)state->ext_nodetype + off); ++ } ++ ++ DPRINTF("readw reg 0x" TARGET_FMT_plx " = %x\n", node->addr + addr, ret); ++ return ret; ++} ++ ++static uint32_t apic_readl(void *opaque, hwaddr addr) ++{ ++ nodeApicState *node; ++ apicState *state; ++ unsigned long off; ++ uint32_t ret; ++ int cpu; ++ ++ node = (nodeApicState *)opaque; ++ state = node->apic; ++ off = addr & 0xfffff; ++ ret = 0; ++ if ((off >= EXTIOI_ENABLE_START) && (off < EXTIOI_ENABLE_END)) { ++ off -= EXTIOI_ENABLE_START; ++ ret = *(uint32_t *)((void *)state->ext_en + off); ++ } else if ((off >= EXTIOI_BOUNCE_START) && (off < EXTIOI_BOUNCE_END)) { ++ off -= EXTIOI_BOUNCE_START; ++ ret = *(uint32_t *)((void *)state->ext_bounce + off); ++ } else if ((off >= EXTIOI_ISR_START) && (off < EXTIOI_ISR_END)) { ++ off -= EXTIOI_ISR_START; ++ ret = *(uint32_t *)((void *)state->ext_isr + off); ++ } else if ((off >= EXTIOI_COREISR_START) && (off < EXTIOI_COREISR_END)) { ++ off -= EXTIOI_COREISR_START; ++ cpu = (off >> 8) & 0xff; ++ ret = *(uint32_t *)((void *)state->ext_coreisr[cpu] + (off & 0x1f)); ++ } else if ((off >= EXTIOI_IPMAP_START) && (off < EXTIOI_IPMAP_END)) { ++ off -= EXTIOI_IPMAP_START; ++ ret = *(uint32_t *)((void *)state->ext_ipmap + off); ++ } else if ((off >= EXTIOI_COREMAP_START) && (off < EXTIOI_COREMAP_END)) { ++ off -= EXTIOI_COREMAP_START; ++ ret = *(uint32_t *)((void *)state->ext_coremap + off); ++ } else if ((off >= EXTIOI_NODETYPE_START) && (off < EXTIOI_NODETYPE_END)) { ++ off -= EXTIOI_NODETYPE_START; ++ ret = *(uint32_t *)((void *)state->ext_nodetype + off); ++ } ++ ++ DPRINTF("readl reg 0x" TARGET_FMT_plx " = %x\n", node->addr + addr, ret); ++ return ret; ++ ++} ++ ++static void apic_writeb(void *opaque, hwaddr addr, uint32_t val) ++{ ++ nodeApicState *node; ++ apicState *state; ++ unsigned long off; ++ uint8_t old; ++ int cpu, i, ipnum, level, mask; ++ ++ node = (nodeApicState *)opaque; ++ state = node->apic; ++ off = addr & 0xfffff; ++ if ((off >= EXTIOI_ENABLE_START) && (off < EXTIOI_ENABLE_END)) { ++ off -= EXTIOI_ENABLE_START; ++ old = *(uint8_t *)((void *)state->ext_en + off); ++ if (old != val) { ++ *(uint8_t *)((void *)state->ext_en + off) = val; ++ old = old ^ val; ++ mask = 0x1; ++ for (i = 0; i < 8; i++) { ++ if (old & mask) { ++ level = !!(val & (0x1 << i)); ++ ioapic_update_irq(state, i + off * 8, level); ++ } ++ mask = mask << 1; ++ } ++ } ++ } else if ((off >= EXTIOI_BOUNCE_START) && (off < EXTIOI_BOUNCE_END)) { ++ off -= EXTIOI_BOUNCE_START; ++ *(uint8_t *)((void *)state->ext_bounce + off) = val; ++ } else if ((off >= EXTIOI_ISR_START) && (off < EXTIOI_ISR_END)) { ++ off -= EXTIOI_ISR_START; ++ old = *(uint8_t *)((void *)state->ext_isr + off); ++ *(uint8_t *)((void *)state->ext_isr + off) = old & ~val; ++ mask = 0x1; ++ for (i = 0; i < 8; i++) { ++ if ((old & mask) && (val & mask)) { ++ ioapic_update_irq(state, i + off * 8, 0); ++ } ++ mask = mask << 1; ++ } ++ } else if ((off >= EXTIOI_COREISR_START) && (off < EXTIOI_COREISR_END)) { ++ off -= EXTIOI_COREISR_START; ++ cpu = (off >> 8) & 0xff; ++ off = off & 0x1f; ++ old = *(uint8_t *)((void *)state->ext_coreisr[cpu] + off); ++ *(uint8_t *)((void *)state->ext_coreisr[cpu] + off) = old & ~val; ++ mask = 0x1; ++ for (i = 0; i < 8; i++) { ++ if ((old & mask) && (val & mask)) { ++ ioapic_update_irq(state, i + off * 8, 0); ++ } ++ mask = mask << 1; ++ } ++ } else if ((off >= EXTIOI_IPMAP_START) && (off < EXTIOI_IPMAP_END)) { ++ off -= EXTIOI_IPMAP_START; ++ val = val & 0xf; ++ *(uint8_t *)((void *)state->ext_ipmap + off) = val; ++ ipnum = 0; ++ for (i = 0; i < 4; i++) { ++ if (val & (0x1 << i)) { ++ ipnum = i; ++ break; ++ } ++ } ++ if (val) { ++ for (i = 0; i < 32; i++) { ++ cpu = off * 32 + i; ++ state->ext_sw_ipmap[cpu] = ipnum; ++ } ++ } ++ } else if ((off >= EXTIOI_COREMAP_START) && (off < EXTIOI_COREMAP_END)) { ++ off -= EXTIOI_COREMAP_START; ++ val = val & 0xff; ++ *(uint8_t *)((void *)state->ext_coremap + off) = val; ++ state->ext_sw_coremap[off] = val; ++ } else if ((off >= EXTIOI_NODETYPE_START) && (off < EXTIOI_NODETYPE_END)) { ++ off -= EXTIOI_NODETYPE_START; ++ *(uint8_t *)((void *)state->ext_nodetype + off) = val; ++ } ++ ++ DPRINTF("writeb reg 0x" TARGET_FMT_plx " = %x\n", node->addr + addr, val); ++} ++ ++static void apic_writew(void *opaque, hwaddr addr, uint32_t val) ++{ ++ nodeApicState *node; ++ apicState *state; ++ unsigned long off; ++ uint16_t old; ++ int cpu, i, level, mask; ++ ++ node = (nodeApicState *)opaque; ++ state = node->apic; ++ off = addr & 0xfffff; ++ if ((off >= EXTIOI_ENABLE_START) && (off < EXTIOI_ENABLE_END)) { ++ off -= EXTIOI_ENABLE_START; ++ old = *(uint16_t *)((void *)state->ext_en + off); ++ if (old != val) { ++ *(uint16_t *)((void *)state->ext_en + off) = val; ++ old = old ^ val; ++ mask = 0x1; ++ for (i = 0; i < 16; i++) { ++ if (old & mask) { ++ level = !!(val & (0x1 << i)); ++ ioapic_update_irq(state, i + off * 8, level); ++ } ++ mask = mask << 1; ++ } ++ } ++ } else if ((off >= EXTIOI_BOUNCE_START) && (off < EXTIOI_BOUNCE_END)) { ++ off -= EXTIOI_BOUNCE_START; ++ *(uint16_t *)((void *)state->ext_bounce + off) = val; ++ } else if ((off >= EXTIOI_ISR_START) && (off < EXTIOI_ISR_END)) { ++ off -= EXTIOI_ISR_START; ++ old = *(uint16_t *)((void *)state->ext_isr + off); ++ *(uint16_t *)((void *)state->ext_isr + off) = old & ~val; ++ mask = 0x1; ++ for (i = 0; i < 16; i++) { ++ if ((old & mask) && (val & mask)) { ++ ioapic_update_irq(state, i + off * 8, 0); ++ } ++ mask = mask << 1; ++ } ++ } else if ((off >= EXTIOI_COREISR_START) && (off < EXTIOI_COREISR_END)) { ++ off -= EXTIOI_COREISR_START; ++ cpu = (off >> 8) & 0xff; ++ off = off & 0x1f; ++ old = *(uint16_t *)((void *)state->ext_coreisr[cpu] + off); ++ *(uint16_t *)((void *)state->ext_coreisr[cpu] + off) = old & ~val; ++ mask = 0x1; ++ for (i = 0; i < 16; i++) { ++ if ((old & mask) && (val & mask)) { ++ ioapic_update_irq(state, i + off * 8, 0); ++ } ++ mask = mask << 1; ++ } ++ } else if ((off >= EXTIOI_IPMAP_START) && (off < EXTIOI_IPMAP_END)) { ++ apic_writeb(opaque, addr, val & 0xff); ++ apic_writeb(opaque, addr + 1, (val >> 8) & 0xff); ++ ++ } else if ((off >= EXTIOI_COREMAP_START) && (off < EXTIOI_COREMAP_END)) { ++ apic_writeb(opaque, addr, val & 0xff); ++ apic_writeb(opaque, addr + 1, (val >> 8) & 0xff); ++ ++ } else if ((off >= EXTIOI_NODETYPE_START) && (off < EXTIOI_NODETYPE_END)) { ++ off -= EXTIOI_NODETYPE_START; ++ *(uint16_t *)((void *)state->ext_nodetype + off) = val; ++ } ++ ++ DPRINTF("writew reg 0x" TARGET_FMT_plx " = %x\n", node->addr + addr, val); ++} ++ ++static void apic_writel(void *opaque, hwaddr addr, uint32_t val) ++{ ++ nodeApicState *node; ++ apicState *state; ++ unsigned long off; ++ uint32_t old; ++ int cpu, i, level, mask; ++ ++ node = (nodeApicState *)opaque; ++ state = node->apic; ++ off = addr & 0xfffff; ++ if ((off >= EXTIOI_ENABLE_START) && (off < EXTIOI_ENABLE_END)) { ++ off -= EXTIOI_ENABLE_START; ++ old = *(uint32_t *)((void *)state->ext_en + off); ++ if (old != val) { ++ *(uint32_t *)((void *)state->ext_en + off) = val; ++ old = old ^ val; ++ mask = 0x1; ++ for (i = 0; i < 32; i++) { ++ if (old & mask) { ++ level = !!(val & (0x1 << i)); ++ ioapic_update_irq(state, i + off * 8, level); ++ } ++ mask = mask << 1; ++ } ++ } ++ } else if ((off >= EXTIOI_BOUNCE_START) && (off < EXTIOI_BOUNCE_END)) { ++ off -= EXTIOI_BOUNCE_START; ++ *(uint32_t *)((void *)state->ext_bounce + off) = val; ++ } else if ((off >= EXTIOI_ISR_START) && (off < EXTIOI_ISR_END)) { ++ off -= EXTIOI_ISR_START; ++ old = *(uint32_t *)((void *)state->ext_isr + off); ++ *(uint32_t *)((void *)state->ext_isr + off) = old & ~val; ++ mask = 0x1; ++ for (i = 0; i < 32; i++) { ++ if ((old & mask) && (val & mask)) { ++ ioapic_update_irq(state, i + off * 8, 0); ++ } ++ mask = mask << 1; ++ } ++ } else if ((off >= EXTIOI_COREISR_START) && (off < EXTIOI_COREISR_END)) { ++ off -= EXTIOI_COREISR_START; ++ cpu = (off >> 8) & 0xff; ++ off = off & 0x1f; ++ old = *(uint32_t *)((void *)state->ext_coreisr[cpu] + off); ++ *(uint32_t *)((void *)state->ext_coreisr[cpu] + off) = old & ~val; ++ mask = 0x1; ++ for (i = 0; i < 32; i++) { ++ if ((old & mask) && (val & mask)) { ++ ioapic_update_irq(state, i + off * 8, 0); ++ } ++ mask = mask << 1; ++ } ++ } else if ((off >= EXTIOI_IPMAP_START) && (off < EXTIOI_IPMAP_END)) { ++ apic_writeb(opaque, addr, val & 0xff); ++ apic_writeb(opaque, addr + 1, (val >> 8) & 0xff); ++ apic_writeb(opaque, addr + 2, (val >> 16) & 0xff); ++ apic_writeb(opaque, addr + 3, (val >> 24) & 0xff); ++ ++ } else if ((off >= EXTIOI_COREMAP_START) && (off < EXTIOI_COREMAP_END)) { ++ apic_writeb(opaque, addr, val & 0xff); ++ apic_writeb(opaque, addr + 1, (val >> 8) & 0xff); ++ apic_writeb(opaque, addr + 2, (val >> 16) & 0xff); ++ apic_writeb(opaque, addr + 3, (val >> 24) & 0xff); ++ ++ } else if ((off >= EXTIOI_NODETYPE_START) && (off < EXTIOI_NODETYPE_END)) { ++ off -= EXTIOI_NODETYPE_START; ++ *(uint32_t *)((void *)state->ext_nodetype + off) = val; ++ } ++ ++ DPRINTF("writel reg 0x" TARGET_FMT_plx " = %x\n", node->addr + addr, val); ++} ++ ++static uint64_t apic_readfn(void *opaque, hwaddr addr, ++ unsigned size) ++{ ++ switch (size) { ++ case 1: ++ return apic_readb(opaque, addr); ++ case 2: ++ return apic_readw(opaque, addr); ++ case 4: ++ return apic_readl(opaque, addr); ++ default: ++ g_assert_not_reached(); ++ } ++} ++ ++static void apic_writefn(void *opaque, hwaddr addr, ++ uint64_t value, unsigned size) ++{ ++ switch (size) { ++ case 1: ++ apic_writeb(opaque, addr, value); ++ break; ++ case 2: ++ apic_writew(opaque, addr, value); ++ break; ++ case 4: ++ apic_writel(opaque, addr, value); ++ break; ++ default: ++ g_assert_not_reached(); ++ } ++} ++ ++static const VMStateDescription vmstate_apic = { ++ .name = "apic", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .pre_save = ext_irq_pre_save, ++ .post_load = ext_irq_post_load, ++ .fields = (VMStateField[]) { ++ VMSTATE_UINT8_ARRAY(ext_en, apicState, EXTIOI_IRQS_BITMAP_SIZE), ++ VMSTATE_UINT8_ARRAY(ext_bounce, apicState, EXTIOI_IRQS_BITMAP_SIZE), ++ VMSTATE_UINT8_ARRAY(ext_isr, apicState, EXTIOI_IRQS_BITMAP_SIZE), ++ VMSTATE_UINT8_2DARRAY(ext_coreisr, apicState, MAX_CORES, ++ EXTIOI_IRQS_BITMAP_SIZE), ++ VMSTATE_UINT8_ARRAY(ext_ipmap, apicState, EXTIOI_IRQS_IPMAP_SIZE), ++ VMSTATE_UINT8_ARRAY(ext_coremap, apicState, EXTIOI_IRQS), ++ VMSTATE_UINT16_ARRAY(ext_nodetype, apicState, 16), ++ VMSTATE_UINT64(ext_control, apicState), ++ VMSTATE_UINT8_ARRAY(ext_sw_ipmap, apicState, EXTIOI_IRQS), ++ VMSTATE_UINT8_ARRAY(ext_sw_coremap, apicState, EXTIOI_IRQS), ++ VMSTATE_UINT8_2DARRAY(ext_ipisr, apicState, MAX_CORES * LS3A_INTC_IP, ++ EXTIOI_IRQS_BITMAP_SIZE), ++ VMSTATE_END_OF_LIST() ++ } ++}; ++ ++static const MemoryRegionOps apic_ops = { ++ .read = apic_readfn, ++ .write = apic_writefn, ++ .impl.min_access_size = 1, ++ .impl.max_access_size = 4, ++ .valid.min_access_size = 1, ++ .valid.max_access_size = 4, ++ .endianness = DEVICE_NATIVE_ENDIAN, ++}; ++ ++int cpu_init_apic(LoongarchMachineState *ms, CPULOONGARCHState *env, int cpu) ++{ ++ apicState *apic; ++ nodeApicState *node; ++ MemoryRegion *iomem; ++ unsigned long base; ++ int pin; ++ char str[32]; ++ ++ if (ms->apic == NULL) { ++ apic = g_malloc0(sizeof(apicState)); ++ vmstate_register(NULL, 0, &vmstate_apic, apic); ++ apic->irq = qemu_allocate_irqs(ioapic_setirq, apic, EXTIOI_IRQS); ++ ++ for (pin = 0; pin < LS3A_INTC_IP; pin++) { ++ /* cpu_pin[9:2] <= intc_pin[7:0] */ ++ apic->parent_irq[cpu][pin] = env->irq[pin + 2]; ++ } ++ ms->apic = apic; ++ ++ if (cpu == 0) { ++ base = APIC_BASE; ++ node = g_malloc0(sizeof(nodeApicState)); ++ node->apic = ms->apic; ++ node->addr = base; ++ ++ iomem = g_new(MemoryRegion, 1); ++ sprintf(str, "apic%d", cpu); ++ /* extioi addr 0x1f010000~0x1f02ffff */ ++ memory_region_init_io(iomem, NULL, &apic_ops, node, str, 0x20000); ++ memory_region_add_subregion(get_system_memory(), base, iomem); ++ } ++ ++ } else { ++ if (cpu != 0) { ++ for (pin = 0; pin < LS3A_INTC_IP; pin++) { ++ ms->apic->parent_irq[cpu][pin] = env->irq[pin + 2]; ++ } ++ } ++ } ++ return 0; ++} ++ +diff --git a/hw/loongarch/ioapic.c b/hw/loongarch/ioapic.c +new file mode 100644 +index 0000000000..3de0ed88da +--- /dev/null ++++ b/hw/loongarch/ioapic.c +@@ -0,0 +1,422 @@ ++/* ++ * LS7A1000 Northbridge IOAPIC support ++ * ++ * Copyright (c) 2019 Loongarch Technology ++ * Authors: ++ * Zhu Chen ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ++ * THE SOFTWARE. ++ */ ++ ++#include "qemu/osdep.h" ++#include "hw/sysbus.h" ++#include "hw/irq.h" ++#include "qemu/log.h" ++#include "sysemu/kvm.h" ++#include "linux/kvm.h" ++#include "migration/vmstate.h" ++ ++#define DEBUG_LS7A_APIC 0 ++ ++#define DPRINTF(fmt, ...) \ ++do { \ ++ if (DEBUG_LS7A_APIC) { \ ++ fprintf(stderr, "IOAPIC: " fmt , ## __VA_ARGS__); \ ++ } \ ++} while (0) ++ ++#define TYPE_LS7A_APIC "ioapic" ++#define LS7A_APIC(obj) OBJECT_CHECK(LS7AApicState, (obj), TYPE_LS7A_APIC) ++ ++#define LS7A_IOAPIC_ROUTE_ENTRY_OFFSET 0x100 ++#define LS7A_IOAPIC_INT_ID_OFFSET 0x00 ++#define LS7A_INT_ID_VAL 0x7000000UL ++#define LS7A_INT_ID_VER 0x1f0001UL ++#define LS7A_IOAPIC_INT_MASK_OFFSET 0x20 ++#define LS7A_IOAPIC_INT_EDGE_OFFSET 0x60 ++#define LS7A_IOAPIC_INT_CLEAR_OFFSET 0x80 ++#define LS7A_IOAPIC_INT_STATUS_OFFSET 0x3a0 ++#define LS7A_IOAPIC_INT_POL_OFFSET 0x3e0 ++#define LS7A_IOAPIC_HTMSI_EN_OFFSET 0x40 ++#define LS7A_IOAPIC_HTMSI_VEC_OFFSET 0x200 ++#define LS7A_AUTO_CTRL0_OFFSET 0xc0 ++#define LS7A_AUTO_CTRL1_OFFSET 0xe0 ++ ++typedef struct LS7AApicState { ++ SysBusDevice parent_obj; ++ qemu_irq parent_irq[257]; ++ uint64_t int_id; ++ uint64_t int_mask; /*0x020 interrupt mask register*/ ++ uint64_t htmsi_en;/*0x040 1=msi*/ ++ uint64_t intedge; /*0x060 edge=1 level =0*/ ++ uint64_t intclr; /*0x080 for clean edge int,set 1 clean,set 0 is noused*/ ++ uint64_t auto_crtl0; /*0x0c0*/ ++ uint64_t auto_crtl1; /*0x0e0*/ ++ uint8_t route_entry[64]; /*0x100 - 0x140*/ ++ uint8_t htmsi_vector[64]; /*0x200 - 0x240*/ ++ uint64_t intisr_chip0; /*0x300*/ ++ uint64_t intisr_chip1;/*0x320*/ ++ uint64_t last_intirr; /* edge detection */ ++ uint64_t intirr; /* 0x380 interrupt request register */ ++ uint64_t intisr; /* 0x3a0 interrupt service register */ ++ uint64_t int_polarity; /*0x3e0 interrupt level polarity ++ selection register 0 for high level tirgger*/ ++ MemoryRegion iomem; ++} LS7AApicState; ++ ++static void update_irq(LS7AApicState *s) ++{ ++ int i; ++ if ((s->intirr & (~s->int_mask)) & (~s->htmsi_en)) { ++ DPRINTF("7a update irqline up\n"); ++ s->intisr = (s->intirr & (~s->int_mask) & (~s->htmsi_en)); ++ qemu_set_irq(s->parent_irq[256], 1); ++ } else { ++ DPRINTF("7a update irqline down\n"); ++ s->intisr &= (~s->htmsi_en); ++ qemu_set_irq(s->parent_irq[256], 0); ++ } ++ if (s->htmsi_en) { ++ for (i = 0; i < 64; i++) { ++ if ((((~s->intisr) & s->intirr) & s->htmsi_en) & (1ULL << i)) { ++ s->intisr |= 1ULL << i; ++ qemu_set_irq(s->parent_irq[s->htmsi_vector[i]], 1); ++ } else if (((~(s->intisr | s->intirr)) & s->htmsi_en) & ++ (1ULL << i)) { ++ qemu_set_irq(s->parent_irq[s->htmsi_vector[i]], 0); ++ } ++ } ++ } ++} ++ ++static void irq_handler(void *opaque, int irq, int level) ++{ ++ LS7AApicState *s = opaque; ++ ++ assert(irq < 64); ++ uint64_t mask = 1ULL << irq; ++ DPRINTF("------ %s irq %d %d\n", __func__, irq, level); ++ ++ if (s->intedge & mask) { ++ /* edge triggered */ ++ /*TODO*/ ++ } else { ++ /* level triggered */ ++ if (level) { ++ s->intirr |= mask; ++ } else { ++ s->intirr &= ~mask; ++ } ++ ++ } ++ update_irq(s); ++ ++} ++ ++static uint64_t ls7a_apic_reg_read(void *opaque, hwaddr addr, unsigned size) ++{ ++ LS7AApicState *a = opaque; ++ uint64_t val = 0; ++ uint64_t offset; ++ int64_t offset_tmp; ++ offset = addr & 0xfff; ++ if (8 == size) { ++ switch (offset) { ++ case LS7A_IOAPIC_INT_ID_OFFSET: ++ val = LS7A_INT_ID_VER; ++ val = (val << 32) + LS7A_INT_ID_VAL; ++ break; ++ case LS7A_IOAPIC_INT_MASK_OFFSET: ++ val = a->int_mask; ++ break; ++ case LS7A_IOAPIC_INT_STATUS_OFFSET: ++ val = a->intisr & (~a->int_mask); ++ break; ++ case LS7A_IOAPIC_INT_EDGE_OFFSET: ++ val = a->intedge; ++ break; ++ case LS7A_IOAPIC_INT_POL_OFFSET: ++ val = a->int_polarity; ++ break; ++ case LS7A_IOAPIC_HTMSI_EN_OFFSET: ++ val = a->htmsi_en; ++ break; ++ case LS7A_AUTO_CTRL0_OFFSET: ++ case LS7A_AUTO_CTRL1_OFFSET: ++ break; ++ default: ++ break; ++ } ++ } else if (1 == size) { ++ if (offset >= LS7A_IOAPIC_HTMSI_VEC_OFFSET) { ++ offset_tmp = offset - LS7A_IOAPIC_HTMSI_VEC_OFFSET; ++ if (offset_tmp >= 0 && offset_tmp < 64) { ++ val = a->htmsi_vector[offset_tmp]; ++ } ++ } else if (offset >= LS7A_IOAPIC_ROUTE_ENTRY_OFFSET) { ++ offset_tmp = offset - LS7A_IOAPIC_ROUTE_ENTRY_OFFSET; ++ if (offset_tmp >= 0 && offset_tmp < 64) { ++ val = a->route_entry[offset_tmp]; ++ DPRINTF("addr %lx val %lx\n", addr, val); ++ } ++ } ++ } ++ DPRINTF(TARGET_FMT_plx" val %lx\n", addr, val); ++ return val; ++} ++ ++static void ls7a_apic_reg_write(void *opaque, hwaddr addr, uint64_t data, unsigned size) ++{ ++ LS7AApicState *a = opaque; ++ int64_t offset_tmp; ++ uint64_t offset; ++ offset = addr & 0xfff; ++ DPRINTF(TARGET_FMT_plx" size %d val %lx\n", addr, size, data); ++ if (8 == size) { ++ switch (offset) { ++ case LS7A_IOAPIC_INT_MASK_OFFSET: ++ a->int_mask = data; ++ update_irq(a); ++ break; ++ case LS7A_IOAPIC_INT_STATUS_OFFSET: ++ a->intisr = data; ++ break; ++ case LS7A_IOAPIC_INT_EDGE_OFFSET: ++ a->intedge = data; ++ break; ++ case LS7A_IOAPIC_INT_CLEAR_OFFSET: ++ a->intisr &= (~data); ++ update_irq(a); ++ break; ++ case LS7A_IOAPIC_INT_POL_OFFSET: ++ a->int_polarity = data; ++ break; ++ case LS7A_IOAPIC_HTMSI_EN_OFFSET: ++ a->htmsi_en = data; ++ break; ++ case LS7A_AUTO_CTRL0_OFFSET: ++ case LS7A_AUTO_CTRL1_OFFSET: ++ break; ++ default: ++ break; ++ } ++ } else if (1 == size) { ++ if (offset >= LS7A_IOAPIC_HTMSI_VEC_OFFSET) { ++ offset_tmp = offset - LS7A_IOAPIC_HTMSI_VEC_OFFSET; ++ if (offset_tmp >= 0 && offset_tmp < 64) { ++ a->htmsi_vector[offset_tmp] = (uint8_t)(data & 0xff); ++ } ++ } else if (offset >= LS7A_IOAPIC_ROUTE_ENTRY_OFFSET) { ++ offset_tmp = offset - LS7A_IOAPIC_ROUTE_ENTRY_OFFSET; ++ if (offset_tmp >= 0 && offset_tmp < 64) { ++ a->route_entry[offset_tmp] = (uint8_t)(data & 0xff); ++ } ++ } ++ } ++} ++ ++static const MemoryRegionOps ls7a_apic_ops = { ++ .read = ls7a_apic_reg_read, ++ .write = ls7a_apic_reg_write, ++ .valid = { ++ .min_access_size = 1, ++ .max_access_size = 8, ++ }, ++ .impl = { ++ .min_access_size = 1, ++ .max_access_size = 8, ++ }, ++ .endianness = DEVICE_NATIVE_ENDIAN, ++}; ++ ++static int kvm_ls7a_pre_save(void *opaque) ++{ ++#ifdef CONFIG_KVM ++ LS7AApicState *s = opaque; ++ struct loongarch_kvm_irqchip *chip; ++ struct ls7a_ioapic_state *state; ++ int ret, i, length; ++ ++ if (!kvm_irqchip_in_kernel()) { ++ return 0; ++ } ++ ++ length = sizeof(struct loongarch_kvm_irqchip) + sizeof(struct ls7a_ioapic_state); ++ chip = g_malloc0(length); ++ memset(chip, 0, length); ++ chip->chip_id = KVM_IRQCHIP_LS7A_IOAPIC; ++ chip->len = length; ++ ret = kvm_vm_ioctl(kvm_state, KVM_GET_IRQCHIP, chip); ++ if (ret < 0) { ++ fprintf(stderr, "KVM_GET_IRQCHIP failed: %s\n", strerror(ret)); ++ abort(); ++ } ++ state = (struct ls7a_ioapic_state *)chip->data; ++ s->int_id = state->int_id; ++ s->int_mask = state->int_mask; ++ s->htmsi_en = state->htmsi_en; ++ s->intedge = state->intedge; ++ s->intclr = state->intclr; ++ s->auto_crtl0 = state->auto_crtl0; ++ s->auto_crtl1 = state->auto_crtl1; ++ for (i = 0; i < 64; i++) { ++ s->route_entry[i] = state->route_entry[i]; ++ s->htmsi_vector[i] = state->htmsi_vector[i]; ++ } ++ s->intisr_chip0 = state->intisr_chip0; ++ s->intisr_chip1 = state->intisr_chip1; ++ s->intirr = state->intirr; ++ s->intisr = state->intisr; ++ s->int_polarity = state->int_polarity; ++ g_free(chip); ++#endif ++ return 0; ++} ++ ++static int kvm_ls7a_post_load(void *opaque, int version) ++{ ++#ifdef CONFIG_KVM ++ LS7AApicState *s = opaque; ++ struct loongarch_kvm_irqchip *chip; ++ struct ls7a_ioapic_state *state; ++ int ret, i, length; ++ ++ if (!kvm_irqchip_in_kernel()) { ++ return 0; ++ } ++ length = sizeof(struct loongarch_kvm_irqchip) + sizeof(struct ls7a_ioapic_state); ++ chip = g_malloc0(length); ++ memset(chip, 0, length); ++ chip->chip_id = KVM_IRQCHIP_LS7A_IOAPIC; ++ chip->len = length; ++ ++ state = (struct ls7a_ioapic_state *)chip->data; ++ state->int_id = s->int_id; ++ state->int_mask = s->int_mask; ++ state->htmsi_en = s->htmsi_en; ++ state->intedge = s->intedge; ++ state->intclr = s->intclr; ++ state->auto_crtl0 = s->auto_crtl0; ++ state->auto_crtl1 = s->auto_crtl1; ++ for (i = 0; i < 64; i++) { ++ state->route_entry[i] = s->route_entry[i]; ++ state->htmsi_vector[i] = s->htmsi_vector[i]; ++ } ++ state->intisr_chip0 = s->intisr_chip0; ++ state->intisr_chip1 = s->intisr_chip1; ++ state->last_intirr = 0; ++ state->intirr = s->intirr; ++ state->intisr = s->intisr; ++ state->int_polarity = s->int_polarity; ++ ++ ret = kvm_vm_ioctl(kvm_state, KVM_SET_IRQCHIP, chip); ++ if (ret < 0) { ++ fprintf(stderr, "KVM_GET_IRQCHIP failed: %s\n", strerror(ret)); ++ abort(); ++ } ++ g_free(chip); ++#endif ++ return 0; ++} ++ ++static void ls7a_apic_reset(DeviceState *d) ++{ ++ LS7AApicState *s = LS7A_APIC(d); ++ int i; ++ ++ s->int_id = 0x001f000107000000; ++ s->int_mask = 0xffffffffffffffff; ++ s->htmsi_en = 0x0; ++ s->intedge = 0x0; ++ s->intclr = 0x0; ++ s->auto_crtl0 = 0x0; ++ s->auto_crtl1 = 0x0; ++ for (i = 0; i < 64; i++) { ++ s->route_entry[i] = 0x1; ++ s->htmsi_vector[i] = 0x0; ++ } ++ s->intisr_chip0 = 0x0; ++ s->intisr_chip1 = 0x0; ++ s->intirr = 0x0; ++ s->intisr = 0x0; ++ s->int_polarity = 0x0; ++ kvm_ls7a_post_load(s, 0); ++} ++ ++static void ls7a_apic_init(Object *obj) ++{ ++ DeviceState *dev = DEVICE(obj); ++ LS7AApicState *s = LS7A_APIC(obj); ++ SysBusDevice *sbd = SYS_BUS_DEVICE(obj); ++ int tmp; ++ memory_region_init_io(&s->iomem, obj, &ls7a_apic_ops, s, TYPE_LS7A_APIC, 0x1000); ++ sysbus_init_mmio(sbd, &s->iomem); ++ for (tmp = 0; tmp < 257; tmp++) { ++ sysbus_init_irq(sbd, &s->parent_irq[tmp]); ++ } ++ qdev_init_gpio_in(dev, irq_handler, 64); ++} ++ ++static const VMStateDescription vmstate_ls7a_apic = { ++ .name = TYPE_LS7A_APIC, ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .pre_save = kvm_ls7a_pre_save, ++ .post_load = kvm_ls7a_post_load, ++ .fields = (VMStateField[]) { ++ VMSTATE_UINT64(int_mask, LS7AApicState), ++ VMSTATE_UINT64(htmsi_en, LS7AApicState), ++ VMSTATE_UINT64(intedge, LS7AApicState), ++ VMSTATE_UINT64(intclr, LS7AApicState), ++ VMSTATE_UINT64(auto_crtl0, LS7AApicState), ++ VMSTATE_UINT64(auto_crtl1, LS7AApicState), ++ VMSTATE_UINT8_ARRAY(route_entry, LS7AApicState, 64), ++ VMSTATE_UINT8_ARRAY(htmsi_vector, LS7AApicState, 64), ++ VMSTATE_UINT64(intisr_chip0, LS7AApicState), ++ VMSTATE_UINT64(intisr_chip1, LS7AApicState), ++ VMSTATE_UINT64(last_intirr, LS7AApicState), ++ VMSTATE_UINT64(intirr, LS7AApicState), ++ VMSTATE_UINT64(intisr, LS7AApicState), ++ VMSTATE_UINT64(int_polarity, LS7AApicState), ++ VMSTATE_END_OF_LIST() ++ } ++}; ++ ++static void ls7a_apic_class_init(ObjectClass *klass, void *data) ++{ ++ DeviceClass *dc = DEVICE_CLASS(klass); ++ ++ dc->reset = ls7a_apic_reset; ++ dc->vmsd = &vmstate_ls7a_apic; ++} ++ ++static const TypeInfo ls7a_apic_info = { ++ .name = TYPE_LS7A_APIC, ++ .parent = TYPE_SYS_BUS_DEVICE, ++ .instance_size = sizeof(LS7AApicState), ++ .instance_init = ls7a_apic_init, ++ .class_init = ls7a_apic_class_init, ++}; ++ ++static void ls7a_apic_register_types(void) ++{ ++ type_register_static(&ls7a_apic_info); ++} ++ ++type_init(ls7a_apic_register_types) +diff --git a/hw/loongarch/iocsr.c b/hw/loongarch/iocsr.c +new file mode 100644 +index 0000000000..14521c2d5c +--- /dev/null ++++ b/hw/loongarch/iocsr.c +@@ -0,0 +1,219 @@ ++/* ++ * LOONGARCH IOCSR support ++ * ++ * Copyright (c) 2021 Loongarch Technology ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ++ * THE SOFTWARE. ++ */ ++ ++#include "qemu/osdep.h" ++#include "hw/sysbus.h" ++#include "qemu/log.h" ++#include "sysemu/kvm.h" ++#include "linux/kvm.h" ++#include "migration/vmstate.h" ++#include "hw/boards.h" ++#include "hw/loongarch/larch.h" ++ ++#define BIT_ULL(nr) (1ULL << (nr)) ++#define LOONGARCH_IOCSR_FEATURES 0x8 ++#define IOCSRF_TEMP BIT_ULL(0) ++#define IOCSRF_NODECNT BIT_ULL(1) ++#define IOCSRF_MSI BIT_ULL(2) ++#define IOCSRF_EXTIOI BIT_ULL(3) ++#define IOCSRF_CSRIPI BIT_ULL(4) ++#define IOCSRF_FREQCSR BIT_ULL(5) ++#define IOCSRF_FREQSCALE BIT_ULL(6) ++#define IOCSRF_DVFSV1 BIT_ULL(7) ++#define IOCSRF_GMOD BIT_ULL(9) ++#define IOCSRF_VM BIT_ULL(11) ++#define LOONGARCH_IOCSR_VENDOR 0x10 ++#define LOONGARCH_IOCSR_CPUNAME 0x20 ++#define LOONGARCH_IOCSR_NODECNT 0x408 ++#define LOONGARCH_IOCSR_MISC_FUNC 0x420 ++#define IOCSR_MISC_FUNC_TIMER_RESET BIT_ULL(21) ++#define IOCSR_MISC_FUNC_EXT_IOI_EN BIT_ULL(48) ++ ++enum { ++ IOCSR_FEATURES, ++ IOCSR_VENDOR, ++ IOCSR_CPUNAME, ++ IOCSR_NODECNT, ++ IOCSR_MISC_FUNC, ++ IOCSR_MAX ++}; ++ ++static uint32_t iocsr_array[IOCSR_MAX] = { ++ [IOCSR_FEATURES] = LOONGARCH_IOCSR_FEATURES, ++ [IOCSR_VENDOR] = LOONGARCH_IOCSR_VENDOR, ++ [IOCSR_CPUNAME] = LOONGARCH_IOCSR_CPUNAME, ++ [IOCSR_NODECNT] = LOONGARCH_IOCSR_NODECNT, ++ [IOCSR_MISC_FUNC] = LOONGARCH_IOCSR_MISC_FUNC, ++}; ++ ++ ++#define TYPE_IOCSR "iocsr" ++#define IOCSR(obj) OBJECT_CHECK(IOCSRState, (obj), TYPE_IOCSR) ++ ++typedef struct IOCSRState { ++ SysBusDevice parent_obj; ++ uint64_t iocsr_val[IOCSR_MAX]; ++} IOCSRState; ++ ++IOCSRState iocsr_init = { ++ .iocsr_val = { ++ IOCSRF_NODECNT | IOCSRF_MSI | IOCSRF_EXTIOI ++ | IOCSRF_CSRIPI | IOCSRF_GMOD | IOCSRF_VM, ++ 0x6e6f73676e6f6f4c, /* Loongson */ ++ 0x303030354133, /*3A5000*/ ++ 0x4, ++ 0x0, ++ } ++}; ++ ++static int kvm_iocsr_pre_save(void *opaque) ++{ ++#ifdef CONFIG_KVM ++ IOCSRState *s = opaque; ++ struct kvm_iocsr_entry entry; ++ int i = 0; ++ for (i = 0; i < IOCSR_MAX; i++) { ++ entry.addr = iocsr_array[i]; ++ kvm_vm_ioctl(kvm_state, KVM_LOONGARCH_GET_IOCSR, &entry); ++ s->iocsr_val[i] = entry.data; ++ } ++#endif ++ return 0; ++} ++ ++static int kvm_iocsr_post_load(void *opaque, int version) ++{ ++#ifdef CONFIG_KVM ++ IOCSRState *s = opaque; ++ struct kvm_iocsr_entry entry; ++ int i = 0; ++ ++ if (!kvm_enabled()) { ++ return 0; ++ } ++ ++ for (i = 0; i < IOCSR_MAX; i++) { ++ entry.addr = iocsr_array[i]; ++ entry.data = s->iocsr_val[i]; ++ kvm_vm_ioctl(kvm_state, KVM_LOONGARCH_SET_IOCSR, &entry); ++ } ++#endif ++ return 0; ++} ++ ++static void iocsr_reset(DeviceState *d) ++{ ++ IOCSRState *s = IOCSR(d); ++ int i; ++ ++ for (i = 0; i < IOCSR_MAX; i++) { ++ s->iocsr_val[i] = iocsr_init.iocsr_val[i]; ++ } ++ kvm_iocsr_post_load(s, 0); ++} ++static void init_vendor_cpuname(uint64_t *vendor, ++ uint64_t *cpu_name, char *cpuname) ++{ ++ int i = 0, len = 0; ++ char *index = NULL, *index_end = NULL; ++ char *vendor_c = (char *)vendor; ++ char *cpu_name_c = (char *)cpu_name; ++ ++ index = strstr(cpuname, "-"); ++ len = strlen(cpuname); ++ if ((index == NULL) || (len <= 0)) { ++ return ; ++ } ++ ++ *vendor = 0; ++ *cpu_name = 0; ++ index_end = cpuname + len; ++ ++ while (((cpuname + i) < index) && (i < sizeof(uint64_t))) { ++ vendor_c[i] = cpuname[i]; ++ i++; ++ } ++ ++ index += 1; ++ i = 0; ++ ++ while (((index + i) < index_end) && (i < sizeof(uint64_t))) { ++ cpu_name_c[i] = index[i]; ++ i++; ++ } ++ ++ return ; ++} ++ ++static void iocsr_instance_init(Object *obj) ++{ ++ IOCSRState *s = IOCSR(obj); ++ int i; ++ LoongarchMachineState *lsms = LoongarchMACHINE(qdev_get_machine()); ++ LoongarchMachineClass *lsmc = LoongarchMACHINE_GET_CLASS(lsms); ++ ++ init_vendor_cpuname((uint64_t *)&iocsr_init.iocsr_val[IOCSR_VENDOR], ++ (uint64_t *)&iocsr_init.iocsr_val[IOCSR_CPUNAME], ++ lsmc->cpu_name); ++ ++ for (i = 0; i < IOCSR_MAX; i++) { ++ s->iocsr_val[i] = iocsr_init.iocsr_val[i]; ++ } ++} ++ ++static const VMStateDescription vmstate_iocsr = { ++ .name = TYPE_IOCSR, ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .pre_save = kvm_iocsr_pre_save, ++ .post_load = kvm_iocsr_post_load, ++ .fields = (VMStateField[]) { ++ VMSTATE_UINT64_ARRAY(iocsr_val, IOCSRState, IOCSR_MAX), ++ VMSTATE_END_OF_LIST() ++ } ++}; ++ ++static void iocsr_class_init(ObjectClass *klass, void *data) ++{ ++ DeviceClass *dc = DEVICE_CLASS(klass); ++ ++ dc->reset = iocsr_reset; ++ dc->vmsd = &vmstate_iocsr; ++ ++} ++ ++static const TypeInfo iocsr_info = { ++ .name = TYPE_IOCSR, ++ .parent = TYPE_SYS_BUS_DEVICE, ++ .instance_size = sizeof(IOCSRState), ++ .instance_init = iocsr_instance_init, ++ .class_init = iocsr_class_init, ++}; ++ ++static void iocsr_register_types(void) ++{ ++ type_register_static(&iocsr_info); ++} ++ ++type_init(iocsr_register_types) +diff --git a/hw/loongarch/ipi.c b/hw/loongarch/ipi.c +new file mode 100644 +index 0000000000..ade182abcc +--- /dev/null ++++ b/hw/loongarch/ipi.c +@@ -0,0 +1,267 @@ ++#include "qemu/osdep.h" ++#include "qemu/units.h" ++#include "qapi/error.h" ++#include "hw/hw.h" ++#include "hw/irq.h" ++#include "hw/loongarch/cpudevs.h" ++#include "sysemu/sysemu.h" ++#include "sysemu/cpus.h" ++#include "sysemu/kvm.h" ++#include "hw/core/cpu.h" ++#include "qemu/log.h" ++#include "hw/loongarch/bios.h" ++#include "elf.h" ++#include "linux/kvm.h" ++#include "hw/loongarch/larch.h" ++#include "hw/loongarch/ls7a.h" ++#include "migration/vmstate.h" ++ ++static int gipi_pre_save(void *opaque) ++{ ++#ifdef CONFIG_KVM ++ gipiState *state = opaque; ++ struct loongarch_gipiState *kstate; ++ struct loongarch_kvm_irqchip *chip; ++ int ret, i, j, length; ++#endif ++ ++ if (!kvm_irqchip_in_kernel()) { ++ return 0; ++ } ++ ++#ifdef CONFIG_KVM ++ length = sizeof(struct loongarch_kvm_irqchip) + sizeof(struct loongarch_gipiState); ++ chip = g_malloc0(length); ++ memset(chip, 0, length); ++ chip->chip_id = KVM_IRQCHIP_LS3A_GIPI; ++ chip->len = length; ++ ret = kvm_vm_ioctl(kvm_state, KVM_GET_IRQCHIP, chip); ++ if (ret < 0) { ++ fprintf(stderr, "KVM_GET_IRQCHIP failed: %s\n", strerror(ret)); ++ abort(); ++ } ++ ++ kstate = (struct loongarch_gipiState *)chip->data; ++ ++ for (i = 0; i < MAX_GIPI_CORE_NUM; i++) { ++ state->core[i].status = kstate->core[i].status; ++ state->core[i].en = kstate->core[i].en; ++ state->core[i].set = kstate->core[i].set; ++ state->core[i].clear = kstate->core[i].clear; ++ for (j = 0; j < MAX_GIPI_MBX_NUM; j++) { ++ state->core[i].buf[j] = kstate->core[i].buf[j]; ++ } ++ } ++ g_free(chip); ++#endif ++ ++ return 0; ++} ++ ++static int gipi_post_load(void *opaque, int version) ++{ ++#ifdef CONFIG_KVM ++ gipiState *state = opaque; ++ struct loongarch_gipiState *kstate; ++ struct loongarch_kvm_irqchip *chip; ++ int ret, i, j, length; ++#endif ++ ++ if (!kvm_irqchip_in_kernel()) { ++ return 0; ++ } ++ ++#ifdef CONFIG_KVM ++ length = sizeof(struct loongarch_kvm_irqchip) + sizeof(struct loongarch_gipiState); ++ chip = g_malloc0(length); ++ memset(chip, 0, length); ++ chip->chip_id = KVM_IRQCHIP_LS3A_GIPI; ++ chip->len = length; ++ kstate = (struct loongarch_gipiState *)chip->data; ++ ++ for (i = 0; i < MAX_GIPI_CORE_NUM; i++) { ++ kstate->core[i].status = state->core[i].status; ++ kstate->core[i].en = state->core[i].en; ++ kstate->core[i].set = state->core[i].set; ++ kstate->core[i].clear = state->core[i].clear; ++ for (j = 0; j < MAX_GIPI_MBX_NUM; j++) { ++ kstate->core[i].buf[j] = state->core[i].buf[j]; ++ } ++ } ++ ++ ret = kvm_vm_ioctl(kvm_state, KVM_SET_IRQCHIP, chip); ++ if (ret < 0) { ++ fprintf(stderr, "KVM_GET_IRQCHIP failed: %s\n", strerror(ret)); ++ abort(); ++ } ++ g_free(chip); ++#endif ++ ++ return 0; ++} ++ ++static const VMStateDescription vmstate_gipi_core = { ++ .name = "gipi-single", ++ .version_id = 0, ++ .minimum_version_id = 0, ++ .fields = (VMStateField[]) { ++ VMSTATE_UINT32(status, gipi_core), ++ VMSTATE_UINT32(en, gipi_core), ++ VMSTATE_UINT32(set, gipi_core), ++ VMSTATE_UINT32(clear, gipi_core), ++ VMSTATE_UINT64_ARRAY(buf, gipi_core, MAX_GIPI_MBX_NUM), ++ VMSTATE_END_OF_LIST() ++ } ++}; ++ ++static const VMStateDescription vmstate_gipi = { ++ .name = "gipi", ++ .pre_save = gipi_pre_save, ++ .post_load = gipi_post_load, ++ .version_id = 0, ++ .minimum_version_id = 0, ++ .fields = (VMStateField[]) { ++ VMSTATE_STRUCT_ARRAY(core, gipiState, MAX_GIPI_CORE_NUM, 0, ++ vmstate_gipi_core, gipi_core), ++ VMSTATE_END_OF_LIST() ++ } ++}; ++ ++ ++static void gipi_writel(void *opaque, hwaddr addr, uint64_t val, unsigned size) ++{ ++ gipi_core *s = opaque; ++ gipi_core *ss; ++ void *pbuf; ++ uint32_t cpu, action_data, mailaddr; ++ LoongarchMachineState *ms = LoongarchMACHINE(qdev_get_machine()); ++ ++ if ((size != 4) && (size != 8)) { ++ hw_error("size not 4 and not 8"); ++ } ++ addr &= 0xff; ++ switch (addr) { ++ case CORE0_STATUS_OFF: ++ hw_error("CORE0_STATUS_OFF Can't be write\n"); ++ break; ++ case CORE0_EN_OFF: ++ s->en = val; ++ break; ++ case CORE0_IPI_SEND: ++ cpu = (val >> 16) & 0x3ff; ++ action_data = 1UL << (val & 0x1f); ++ ss = &ms->gipi->core[cpu]; ++ ss->status |= action_data; ++ if (ss->status != 0) { ++ qemu_irq_raise(ss->irq); ++ } ++ break; ++ case CORE0_MAIL_SEND: ++ cpu = (val >> 16) & 0x3ff; ++ mailaddr = (val >> 2) & 0x7; ++ ss = &ms->gipi->core[cpu]; ++ pbuf = (void *)ss->buf + mailaddr * 4; ++ *(unsigned int *)pbuf = (val >> 32); ++ break; ++ case CORE0_SET_OFF: ++ hw_error("CORE0_SET_OFF Can't be write\n"); ++ break; ++ case CORE0_CLEAR_OFF: ++ s->status ^= val; ++ if (s->status == 0) { ++ qemu_irq_lower(s->irq); ++ } ++ break; ++ case 0x20 ... 0x3c: ++ pbuf = (void *)s->buf + (addr - 0x20); ++ if (size == 1) { ++ *(unsigned char *)pbuf = (unsigned char)val; ++ } else if (size == 2) { ++ *(unsigned short *)pbuf = (unsigned short)val; ++ } else if (size == 4) { ++ *(unsigned int *)pbuf = (unsigned int)val; ++ } else if (size == 8) { ++ *(unsigned long *)pbuf = (unsigned long)val; ++ } ++ break; ++ default: ++ break; ++ } ++} ++ ++static uint64_t gipi_readl(void *opaque, hwaddr addr, unsigned size) ++{ ++ gipi_core *s = opaque; ++ uint64_t ret = 0; ++ void *pbuf; ++ ++ addr &= 0xff; ++ if ((size != 4) && (size != 8)) { ++ hw_error("size not 4 and not 8 size:%d\n", size); ++ } ++ switch (addr) { ++ case CORE0_STATUS_OFF: ++ ret = s->status; ++ break; ++ case CORE0_EN_OFF: ++ ret = s->en; ++ break; ++ case CORE0_SET_OFF: ++ ret = 0; ++ break; ++ case CORE0_CLEAR_OFF: ++ ret = 0; ++ break; ++ case 0x20 ... 0x3c: ++ pbuf = (void *)s->buf + (addr - 0x20); ++ if (size == 1) { ++ ret = *(unsigned char *)pbuf; ++ } else if (size == 2) { ++ ret = *(unsigned short *)pbuf; ++ } else if (size == 4) { ++ ret = *(unsigned int *)pbuf; ++ } else if (size == 8) { ++ ret = *(unsigned long *)pbuf; ++ } ++ break; ++ default: ++ break; ++ } ++ ++ return ret; ++} ++ ++static const MemoryRegionOps gipi_ops = { ++ .read = gipi_readl, ++ .write = gipi_writel, ++ .valid = { ++ .min_access_size = 4, ++ .max_access_size = 8, ++ }, ++ .impl = { ++ .min_access_size = 4, ++ .max_access_size = 8, ++ }, ++ .endianness = DEVICE_NATIVE_ENDIAN, ++}; ++ ++int cpu_init_ipi(LoongarchMachineState *ms, qemu_irq parent, int cpu) ++{ ++ hwaddr addr; ++ MemoryRegion *region; ++ char str[32]; ++ ++ if (ms->gipi == NULL) { ++ ms->gipi = g_malloc0(sizeof(gipiState)); ++ vmstate_register(NULL, 0, &vmstate_gipi, ms->gipi); ++ } ++ ++ ms->gipi->core[cpu].irq = parent; ++ ++ addr = SMP_GIPI_MAILBOX | (cpu << 8); ++ region = g_new(MemoryRegion, 1); ++ sprintf(str, "gipi%d", cpu); ++ memory_region_init_io(region, NULL, &gipi_ops, &ms->gipi->core[cpu], str, 0x100); ++ memory_region_add_subregion(get_system_memory(), addr, region); ++ return 0; ++} +diff --git a/hw/loongarch/larch_3a.c b/hw/loongarch/larch_3a.c +new file mode 100644 +index 0000000000..3db269274f +--- /dev/null ++++ b/hw/loongarch/larch_3a.c +@@ -0,0 +1,2026 @@ ++/* ++ * QEMU loongarch 3a develop board emulation ++ * ++ * Copyright (C) 2013-2014 qiaochong ++ * Copyright (C) 2016-2017 zhangshuangshuang ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ++ * THE SOFTWARE. ++ */ ++#include "qemu/osdep.h" ++#include "qemu/units.h" ++#include "qapi/error.h" ++#include "qemu/datadir.h" ++#include "hw/hw.h" ++#include "hw/loongarch/cpudevs.h" ++#include "hw/i386/pc.h" ++#include "hw/char/serial.h" ++#include "hw/isa/isa.h" ++#include "hw/qdev-core.h" ++#include "sysemu/sysemu.h" ++#include "sysemu/runstate.h" ++#include "sysemu/reset.h" ++#include "migration/vmstate.h" ++#include "sysemu/cpus.h" ++#include "hw/boards.h" ++#include "qemu/log.h" ++#include "hw/loongarch/bios.h" ++#include "hw/loader.h" ++#include "elf.h" ++#include "exec/address-spaces.h" ++#include "hw/ide.h" ++#include "hw/pci/pci_host.h" ++#include "hw/pci/msi.h" ++#include "linux/kvm.h" ++#include "sysemu/kvm.h" ++#include "sysemu/numa.h" ++#include "hw/rtc/mc146818rtc.h" ++#include "hw/irq.h" ++#include "net/net.h" ++#include "hw/timer/i8254.h" ++#include "hw/loongarch/larch.h" ++#include "hw/loongarch/ls7a.h" ++#include "hw/nvram/fw_cfg.h" ++#include "hw/firmware/smbios.h" ++#include "acpi-build.h" ++#include ++#include ++#include "sysemu/block-backend.h" ++#include "hw/block/flash.h" ++#include "sysemu/device_tree.h" ++#include "qapi/visitor.h" ++#include "qapi/qapi-visit-common.h" ++ ++#include ++ ++#define DMA64_SUPPORTED 0x2 ++#define MAX_IDE_BUS 2 ++ ++#define BOOTPARAM_PHYADDR 0x0ff00000ULL ++#define BOOTPARAM_ADDR (0x9000000000000000ULL + BOOTPARAM_PHYADDR) ++#define SMBIOS_PHYSICAL_ADDRESS 0x0fe00000 ++#define SMBIOS_SIZE_LIMIT 0x200000 ++#define RESERVED_SIZE_LIMIT 0x1100000 ++#define COMMAND_LINE_SIZE 4096 ++#define FW_CONF_ADDR 0x0fff0000 ++ ++#define PHYS_TO_VIRT(x) ((x) | 0x9000000000000000ULL) ++ ++#define TARGET_REALPAGE_MASK (TARGET_PAGE_MASK << 2) ++ ++#ifdef CONFIG_KVM ++#define LS_ISA_IO_SIZE 0x02000000 ++#define LS_ISA_MEM_SIZE 0x40000000 ++#else ++#define LS_ISA_IO_SIZE 0x00010000 ++#define LS_ISA_MEM_SIZE 0x01000000 ++#endif ++ ++#ifdef CONFIG_KVM ++#define align(x) (((x) + 63) & ~63) ++#else ++#define align(x) (((x) + 15) & ~15) ++#endif ++ ++#define DEBUG_LOONGARCH3A 0 ++#define FLASH_SECTOR_SIZE 4096 ++ ++#define DPRINTF(fmt, ...) \ ++ do { if (DEBUG_LOONGARCH3A) { fprintf(stderr, fmt, ## __VA_ARGS__); } } while (0) ++ ++#define DEFINE_LS3A5K_MACHINE(suffix, name, optionfn) \ ++ static void ls3a5k_init_##suffix(MachineState *machine) \ ++ { \ ++ ls3a5k_init(machine); \ ++ } \ ++ DEFINE_LOONGARCH_MACHINE(suffix, name, ls3a5k_init_##suffix, optionfn) ++ ++struct efi_memory_map_loongarch { ++ uint16_t vers; /* version of efi_memory_map */ ++ uint32_t nr_map; /* number of memory_maps */ ++ uint32_t mem_freq; /* memory frequence */ ++ struct mem_map { ++ uint32_t node_id; /* node_id which memory attached to */ ++ uint32_t mem_type; /* system memory, pci memory, pci io, etc. */ ++ uint64_t mem_start; /* memory map start address */ ++ uint32_t mem_size; /* each memory_map size, not the total size */ ++ } map[128]; ++} __attribute__((packed)); ++ ++enum loongarch_cpu_type { ++ Loongson3 = 0x1, ++ Loongson3_comp = 0x2 ++}; ++ ++struct GlobalProperty loongarch_compat[] = { ++ { ++ .driver = "rtl8139", ++ .property = "romfile", ++ .value = "", ++ },{ ++ .driver = "e1000", ++ .property = "romfile", ++ .value = "", ++ },{ ++ .driver = "virtio-net-pci", ++ .property = "romfile", ++ .value = "", ++ },{ ++ .driver = "qxl-vga", ++ .property = "romfile", ++ .value = "", ++ },{ ++ .driver = "VGA", ++ .property = "romfile", ++ .value = "", ++ },{ ++ .driver = "cirrus-vga", ++ .property = "romfile", ++ .value = "", ++ },{ ++ .driver = "virtio-vga", ++ .property = "romfile", ++ .value = "", ++ },{ ++ .driver = "vmware-svga", ++ .property = "romfile", ++ .value = "", ++ }, ++}; ++const size_t loongarch_compat_len = G_N_ELEMENTS(loongarch_compat); ++ ++/* ++ * Capability and feature descriptor structure for LOONGARCH CPU ++ */ ++struct efi_cpuinfo_loongarch { ++ uint16_t vers; /* version of efi_cpuinfo_loongarch */ ++ uint32_t processor_id; /* PRID, e.g. 6305, 6306 */ ++ enum loongarch_cpu_type cputype; /* 3A, 3B, etc. */ ++ uint32_t total_node; /* num of total numa nodes */ ++ uint16_t cpu_startup_core_id; /* Core id */ ++ uint16_t reserved_cores_mask; ++ uint32_t cpu_clock_freq; /* cpu_clock */ ++ uint32_t nr_cpus; ++} __attribute__((packed)); ++ ++#define MAX_UARTS 64 ++struct uart_device { ++ uint32_t iotype; /* see include/linux/serial_core.h */ ++ uint32_t uartclk; ++ uint32_t int_offset; ++ uint64_t uart_base; ++} __attribute__((packed)); ++ ++#define MAX_SENSORS 64 ++#define SENSOR_TEMPER 0x00000001 ++#define SENSOR_VOLTAGE 0x00000002 ++#define SENSOR_FAN 0x00000004 ++struct sensor_device { ++ char name[32]; /* a formal name */ ++ char label[64]; /* a flexible description */ ++ uint32_t type; /* SENSOR_* */ ++ uint32_t id; /* instance id of a sensor-class */ ++ uint32_t fan_policy; /* see arch/loongarch/include/ ++ asm/mach-loongarch/loongarch_hwmon.h */ ++ uint32_t fan_percent;/* only for constant speed policy */ ++ uint64_t base_addr; /* base address of device registers */ ++} __attribute__((packed)); ++ ++struct system_loongarch { ++ uint16_t vers; /* version of system_loongarch */ ++ uint32_t ccnuma_smp; /* 0: no numa; 1: has numa */ ++ uint32_t sing_double_channel;/* 1:single; 2:double */ ++ uint32_t nr_uarts; ++ struct uart_device uarts[MAX_UARTS]; ++ uint32_t nr_sensors; ++ struct sensor_device sensors[MAX_SENSORS]; ++ char has_ec; ++ char ec_name[32]; ++ uint64_t ec_base_addr; ++ char has_tcm; ++ char tcm_name[32]; ++ uint64_t tcm_base_addr; ++ uint64_t workarounds; /* see workarounds.h */ ++} __attribute__((packed)); ++ ++struct irq_source_routing_table { ++ uint16_t vers; ++ uint16_t size; ++ uint16_t rtr_bus; ++ uint16_t rtr_devfn; ++ uint32_t vendor; ++ uint32_t device; ++ uint32_t PIC_type; /* conform use HT or PCI to route to CPU-PIC */ ++ uint64_t ht_int_bit; /* 3A: 1<<24; 3B: 1<<16 */ ++ uint64_t ht_enable; /* irqs used in this PIC */ ++ uint32_t node_id; /* node id: 0x0-0; 0x1-1; 0x10-2; 0x11-3 */ ++ uint64_t pci_mem_start_addr; ++ uint64_t pci_mem_end_addr; ++ uint64_t pci_io_start_addr; ++ uint64_t pci_io_end_addr; ++ uint64_t pci_config_addr; ++ uint32_t dma_mask_bits; ++ uint16_t dma_noncoherent; ++} __attribute__((packed)); ++ ++struct interface_info { ++ uint16_t vers; /* version of the specificition */ ++ uint16_t size; ++ uint8_t flag; ++ char description[64]; ++} __attribute__((packed)); ++ ++#define MAX_RESOURCE_NUMBER 128 ++struct resource_loongarch { ++ uint64_t start; /* resource start address */ ++ uint64_t end; /* resource end address */ ++ char name[64]; ++ uint32_t flags; ++}; ++ ++struct archdev_data {}; /* arch specific additions */ ++ ++struct board_devices { ++ char name[64]; /* hold the device name */ ++ uint32_t num_resources; /* number of device_resource */ ++ /* for each device's resource */ ++ struct resource_loongarch resource[MAX_RESOURCE_NUMBER]; ++ /* arch specific additions */ ++ struct archdev_data archdata; ++}; ++ ++struct loongarch_special_attribute { ++ uint16_t vers; /* version of this special */ ++ char special_name[64]; /* special_atribute_name */ ++ uint32_t loongarch_special_type; /* type of special device */ ++ /* for each device's resource */ ++ struct resource_loongarch resource[MAX_RESOURCE_NUMBER]; ++}; ++ ++struct loongarch_params { ++ uint64_t memory_offset; /* efi_memory_map_loongarch struct offset */ ++ uint64_t cpu_offset; /* efi_cpuinfo_loongarch struct offset */ ++ uint64_t system_offset; /* system_loongarch struct offset */ ++ uint64_t irq_offset; /* irq_source_routing_table struct offset */ ++ uint64_t interface_offset; /* interface_info struct offset */ ++ uint64_t special_offset; /* loongarch_special_attribute struct offset */ ++ uint64_t boarddev_table_offset; /* board_devices offset */ ++}; ++ ++struct smbios_tables { ++ uint16_t vers; /* version of smbios */ ++ uint64_t vga_bios; /* vga_bios address */ ++ struct loongarch_params lp; ++}; ++ ++struct efi_reset_system_t { ++ uint64_t ResetCold; ++ uint64_t ResetWarm; ++ uint64_t ResetType; ++ uint64_t Shutdown; ++ uint64_t DoSuspend; /* NULL if not support */ ++}; ++ ++struct efi_loongarch { ++ uint64_t mps; /* MPS table */ ++ uint64_t acpi; /* ACPI table (IA64 ext 0.71) */ ++ uint64_t acpi20; /* ACPI table (ACPI 2.0) */ ++ struct smbios_tables smbios; /* SM BIOS table */ ++ uint64_t sal_systab; /* SAL system table */ ++ uint64_t boot_info; /* boot info table */ ++}; ++ ++struct boot_params { ++ struct efi_loongarch efi; ++ struct efi_reset_system_t reset_system; ++}; ++ ++static struct _loaderparams { ++ unsigned long ram_size; ++ const char *kernel_filename; ++ const char *kernel_cmdline; ++ const char *initrd_filename; ++ unsigned long a0, a1, a2; ++} loaderparams; ++ ++static struct _firmware_config { ++ unsigned long ram_size; ++ unsigned int mem_freq; ++ unsigned int cpu_nr; ++ unsigned int cpu_clock_freq; ++} fw_config; ++ ++struct la_memmap_entry { ++ uint64_t address; ++ uint64_t length; ++ uint32_t type; ++ uint32_t reserved; ++} ; ++ ++static void *boot_params_buf; ++static void *boot_params_p; ++static struct la_memmap_entry *la_memmap_table; ++static unsigned la_memmap_entries; ++ ++CPULOONGARCHState *cpu_states[LOONGARCH_MAX_VCPUS]; ++ ++struct kvm_cpucfg ls3a5k_cpucfgs = { ++ .cpucfg[LOONGARCH_CPUCFG0] = CPUCFG0_3A5000_PRID, ++ .cpucfg[LOONGARCH_CPUCFG1] = CPUCFG1_ISGR64 | CPUCFG1_PAGING | ++ CPUCFG1_IOCSR | CPUCFG1_PABITS | CPUCFG1_VABITS | CPUCFG1_UAL | ++ CPUCFG1_RI | CPUCFG1_XI | CPUCFG1_RPLV | CPUCFG1_HUGEPG | ++ CPUCFG1_IOCSRBRD, ++ .cpucfg[LOONGARCH_CPUCFG2] = CPUCFG2_FP | CPUCFG2_FPSP | CPUCFG2_FPDP | ++ CPUCFG2_FPVERS | CPUCFG2_LSX | CPUCFG2_LASX | CPUCFG2_COMPLEX | ++ CPUCFG2_CRYPTO | CPUCFG2_LLFTP | CPUCFG2_LLFTPREV | CPUCFG2_LSPW | ++ CPUCFG2_LAM, ++ .cpucfg[LOONGARCH_CPUCFG3] = CPUCFG3_CCDMA | CPUCFG3_SFB | CPUCFG3_UCACC | ++ CPUCFG3_LLEXC | CPUCFG3_SCDLY | CPUCFG3_LLDBAR | CPUCFG3_ITLBT | ++ CPUCFG3_ICACHET | CPUCFG3_SPW_LVL | CPUCFG3_SPW_HG_HF | CPUCFG3_RVA | ++ CPUCFG3_RVAMAX, ++ .cpucfg[LOONGARCH_CPUCFG4] = CCFREQ_100M, ++ .cpucfg[LOONGARCH_CPUCFG5] = CPUCFG5_CCMUL | CPUCFG5_CCDIV, ++ .cpucfg[LOONGARCH_CPUCFG6] = CPUCFG6_PMP | CPUCFG6_PAMVER | CPUCFG6_PMNUM | ++ CPUCFG6_PMBITS | CPUCFG6_UPM, ++ .cpucfg[LOONGARCH_CPUCFG16] = CPUCFG16_L1_IUPRE | CPUCFG16_L1_DPRE | ++ CPUCFG16_L2_IUPRE | CPUCFG16_L2_IUUNIFY | CPUCFG16_L2_IUPRIV | ++ CPUCFG16_L3_IUPRE | CPUCFG16_L3_IUUNIFY | CPUCFG16_L3_IUINCL, ++ .cpucfg[LOONGARCH_CPUCFG17] = CPUCFG17_L1I_WAYS_M | CPUCFG17_L1I_SETS_M | ++ CPUCFG17_L1I_SIZE_M, ++ .cpucfg[LOONGARCH_CPUCFG18] = CPUCFG18_L1D_WAYS_M | CPUCFG18_L1D_SETS_M | ++ CPUCFG18_L1D_SIZE_M, ++ .cpucfg[LOONGARCH_CPUCFG19] = CPUCFG19_L2_WAYS_M | CPUCFG19_L2_SETS_M | ++ CPUCFG19_L2_SIZE_M, ++ .cpucfg[LOONGARCH_CPUCFG20] = CPUCFG20_L3_WAYS_M | CPUCFG20_L3_SETS_M | ++ CPUCFG20_L3_SIZE_M, ++}; ++ ++bool loongarch_is_acpi_enabled(LoongarchMachineState *vms) ++{ ++ if (vms->acpi == ON_OFF_AUTO_OFF) { ++ return false; ++ } ++ return true; ++} ++static void loongarch_get_acpi(Object *obj, Visitor *v, const char *name, ++ void *opaque, Error **errp) ++{ ++ LoongarchMachineState *lsms = LoongarchMACHINE(obj); ++ OnOffAuto acpi = lsms->acpi; ++ ++ visit_type_OnOffAuto(v, name, &acpi, errp); ++} ++ ++static void loongarch_set_acpi(Object *obj, Visitor *v, const char *name, ++ void *opaque, Error **errp) ++{ ++ LoongarchMachineState *lsms = LoongarchMACHINE(obj); ++ ++ visit_type_OnOffAuto(v, name, &lsms->acpi, errp); ++} ++int la_memmap_add_entry(uint64_t address, uint64_t length, uint32_t type) ++{ ++ int i; ++ ++ for (i = 0; i < la_memmap_entries; i++) { ++ if (la_memmap_table[i].address == address) { ++ fprintf(stderr, "%s address:0x%lx length:0x%lx already exists\n", ++ __func__, address, length); ++ return 0; ++ } ++ } ++ ++ la_memmap_table = g_renew(struct la_memmap_entry, la_memmap_table, ++ la_memmap_entries + 1); ++ la_memmap_table[la_memmap_entries].address = cpu_to_le64(address); ++ la_memmap_table[la_memmap_entries].length = cpu_to_le64(length); ++ la_memmap_table[la_memmap_entries].type = cpu_to_le32(type); ++ la_memmap_entries++; ++ ++ return la_memmap_entries; ++} ++ ++static ram_addr_t get_hotplug_membase(ram_addr_t ram_size) ++{ ++ ram_addr_t sstart; ++ ++ if (ram_size <= 0x10000000) { ++ sstart = 0x90000000; ++ } else { ++ sstart = 0x90000000 + ROUND_UP((ram_size - 0x10000000), ++ LOONGARCH_HOTPLUG_MEM_ALIGN); ++ } ++ return sstart; ++} ++ ++static struct efi_memory_map_loongarch *init_memory_map(void *g_map) ++{ ++ struct efi_memory_map_loongarch *emap = g_map; ++ ++ emap->nr_map = 4; ++ emap->mem_freq = 266000000; ++ ++ emap->map[0].node_id = 0; ++ emap->map[0].mem_type = 1; ++ emap->map[0].mem_start = 0x0; ++#ifdef CONFIG_KVM ++ emap->map[0].mem_size = (loaderparams.ram_size > 0x10000000 ++ ? 256 : (loaderparams.ram_size >> 20)) - 18; ++#else ++ emap->map[0].mem_size = atoi(getenv("memsize")); ++#endif ++ ++ emap->map[1].node_id = 0; ++ emap->map[1].mem_type = 2; ++ emap->map[1].mem_start = 0x90000000; ++#ifdef CONFIG_KVM ++ emap->map[1].mem_size = (loaderparams.ram_size > 0x10000000 ++ ? (loaderparams.ram_size >> 20) - 256 : 0); ++#else ++ emap->map[1].mem_size = atoi(getenv("highmemsize")); ++#endif ++ ++ /* support for smbios */ ++ emap->map[2].node_id = 0; ++ emap->map[2].mem_type = 10; ++ emap->map[2].mem_start = SMBIOS_PHYSICAL_ADDRESS; ++ emap->map[2].mem_size = SMBIOS_SIZE_LIMIT >> 20; ++ ++ emap->map[3].node_id = 0; ++ emap->map[3].mem_type = 3; ++ emap->map[3].mem_start = 0xee00000; ++ emap->map[3].mem_size = RESERVED_SIZE_LIMIT >> 20; ++ ++ return emap; ++} ++ ++static uint64_t get_host_cpu_freq(void) ++{ ++ int fd = 0; ++ char buf[1024]; ++ uint64_t freq = 0, size = 0; ++ char *buf_p; ++ ++ fd = open("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq", O_RDONLY); ++ if (fd == -1) { ++ fprintf(stderr, "/sys/devices/system/cpu/cpu0/cpufreq/ \ ++ cpuinfo_max_freq not exist!\n"); ++ fprintf(stderr, "Trying /proc/cpuinfo...\n"); ++ } else { ++ size = read(fd, buf, 16); ++ if (size == -1) { ++ fprintf(stderr, "read err...\n"); ++ } ++ close(fd); ++ freq = (uint64_t)atoi(buf); ++ return freq * 1000; ++ } ++ ++ fd = open("/proc/cpuinfo", O_RDONLY); ++ if (fd == -1) { ++ fprintf(stderr, "Failed to open /proc/cpuinfo!\n"); ++ return 0; ++ } ++ ++ size = read(fd, buf, 1024); ++ if (size == -1) { ++ fprintf(stderr, "read err...\n"); ++ } ++ close(fd); ++ ++ buf_p = strstr(buf, "MHz"); ++ if (buf_p) { ++ while (*buf_p != ':') { ++ buf_p++; ++ } ++ buf_p += 2; ++ } else { ++ buf_p = strstr(buf, "name"); ++ while (*buf_p != '@') { ++ buf_p++; ++ } ++ buf_p += 2; ++ } ++ ++ memcpy(buf, buf_p, 12); ++ buf_p = buf; ++ while ((*buf_p >= '0') && (*buf_p <= '9')) { ++ buf_p++; ++ } ++ *buf_p = '\0'; ++ ++ freq = (uint64_t)atoi(buf); ++ return freq * 1000 * 1000; ++} ++ ++static char *get_host_cpu_model_name(void) ++{ ++ int fd = 0; ++ int size = 0; ++ static char buf[1024]; ++ char *buf_p; ++ ++ fd = open("/proc/cpuinfo", O_RDONLY); ++ if (fd == -1) { ++ fprintf(stderr, "Failed to open /proc/cpuinfo!\n"); ++ return 0; ++ } ++ ++ size = read(fd, buf, 1024); ++ if (size == -1) { ++ fprintf(stderr, "read err...\n"); ++ } ++ close(fd); ++ buf_p = strstr(buf, "name"); ++ ++ while (*buf_p != ':') { ++ buf_p++; ++ } ++ buf_p = buf_p + 2; ++ memcpy(buf, buf_p, 40); ++ buf_p = buf; ++ while (*buf_p != '\n') { ++ buf_p++; ++ } ++ ++ *(buf_p) = '\0'; ++ ++ return buf; ++} ++ ++static void fw_conf_init(unsigned long ramsize) ++{ ++ MachineState *ms = MACHINE(qdev_get_machine()); ++ int smp_cpus = ms->smp.cpus; ++ fw_config.ram_size = ramsize; ++ fw_config.mem_freq = 266000000; ++ fw_config.cpu_nr = smp_cpus ; ++ fw_config.cpu_clock_freq = get_host_cpu_freq(); ++} ++ ++static struct efi_cpuinfo_loongarch *init_cpu_info(void *g_cpuinfo_loongarch) ++{ ++ struct efi_cpuinfo_loongarch *c = g_cpuinfo_loongarch; ++ MachineState *ms = MACHINE(qdev_get_machine()); ++ int smp_cpus = ms->smp.cpus; ++ LoongarchMachineState *lsms = LoongarchMACHINE(qdev_get_machine()); ++ LoongarchMachineClass *lsmc = LoongarchMACHINE_GET_CLASS(lsms); ++ ++ if (strstr(lsmc->cpu_name, "5000")) { ++ c->processor_id = 0x14c010; ++ } ++ c->cputype = Loongson3_comp; ++ c->cpu_clock_freq = get_host_cpu_freq(); ++ if (!c->cpu_clock_freq) { ++ c->cpu_clock_freq = 200000000; ++ } ++ c->total_node = 1; ++ c->nr_cpus = smp_cpus; ++ c->cpu_startup_core_id = 0; ++ c->reserved_cores_mask = 0xffff & (0xffff << smp_cpus); ++ ++ return c; ++} ++ ++static struct system_loongarch *init_system_loongarch(void *g_sysitem) ++{ ++ struct system_loongarch *s = g_sysitem; ++ ++ s->ccnuma_smp = 1; ++ s->ccnuma_smp = 0; ++ s->sing_double_channel = 1; ++ ++ return s; ++} ++ ++enum loongarch_irq_source_enum { ++ HT, I8259, UNKNOWN ++}; ++ ++static struct irq_source_routing_table *init_irq_source(void *g_irq_source) ++{ ++ struct irq_source_routing_table *irq_info = g_irq_source; ++ LoongarchMachineState *lsms = LoongarchMACHINE(qdev_get_machine()); ++ LoongarchMachineClass *lsmc = LoongarchMACHINE_GET_CLASS(lsms); ++ ++ irq_info->PIC_type = HT; ++ irq_info->ht_int_bit = 1 << 24; ++ irq_info->ht_enable = 0x0000d17b; ++ irq_info->node_id = 0; ++ ++ irq_info->pci_mem_start_addr = LS_ISA_MEM_BASE; ++ irq_info->pci_mem_end_addr = irq_info->pci_mem_start_addr + LS_ISA_MEM_SIZE - 1; ++ ++ if (strstr(lsmc->cpu_name, "5000")) { ++ irq_info->pci_io_start_addr = LS3A5K_ISA_IO_BASE; ++ } ++ irq_info->dma_noncoherent = 1; ++ return irq_info; ++} ++ ++static struct interface_info *init_interface_info(void *g_interface) ++{ ++ struct interface_info *inter = g_interface; ++ int flashsize = 0x80000; ++ ++ inter->vers = 0x0001; ++ inter->size = flashsize / 0x400; ++ inter->flag = 1; ++ ++ strcpy(inter->description, "PMON_Version_v2.1"); ++ ++ return inter; ++} ++ ++static struct board_devices *board_devices_info(void *g_board) ++{ ++ struct board_devices *bd = g_board; ++ LoongarchMachineState *lsms = LoongarchMACHINE(qdev_get_machine()); ++ LoongarchMachineClass *lsmc = LoongarchMACHINE_GET_CLASS(lsms); ++ ++ if (!strcmp(lsmc->bridge_name, "ls7a")) { ++ strcpy(bd->name, "Loongarch-3A-7A-1w-V1.03-demo"); ++ } ++ bd->num_resources = 10; ++ ++ return bd; ++} ++ ++static struct loongarch_special_attribute *init_special_info(void *g_special) ++{ ++ struct loongarch_special_attribute *special = g_special; ++ char update[11] = "2013-01-01"; ++ int VRAM_SIZE = 0x20000; ++ ++ strcpy(special->special_name, update); ++ special->resource[0].flags = 0; ++ special->resource[0].start = 0; ++ special->resource[0].end = VRAM_SIZE; ++ strcpy(special->resource[0].name, "SPMODULE"); ++ special->resource[0].flags |= DMA64_SUPPORTED; ++ ++ return special; ++} ++ ++static void init_loongarch_params(struct loongarch_params *lp) ++{ ++ void *p = boot_params_p; ++ ++ lp->memory_offset = (unsigned long long)init_memory_map(p) ++ - (unsigned long long)lp; ++ p += align(sizeof(struct efi_memory_map_loongarch)); ++ ++ lp->cpu_offset = (unsigned long long)init_cpu_info(p) ++ - (unsigned long long)lp; ++ p += align(sizeof(struct efi_cpuinfo_loongarch)); ++ ++ lp->system_offset = (unsigned long long)init_system_loongarch(p) ++ - (unsigned long long)lp; ++ p += align(sizeof(struct system_loongarch)); ++ ++ lp->irq_offset = (unsigned long long)init_irq_source(p) ++ - (unsigned long long)lp; ++ p += align(sizeof(struct irq_source_routing_table)); ++ ++ lp->interface_offset = (unsigned long long)init_interface_info(p) ++ - (unsigned long long)lp; ++ p += align(sizeof(struct interface_info)); ++ ++ lp->boarddev_table_offset = (unsigned long long)board_devices_info(p) ++ - (unsigned long long)lp; ++ p += align(sizeof(struct board_devices)); ++ ++ lp->special_offset = (unsigned long long)init_special_info(p) ++ - (unsigned long long)lp; ++ p += align(sizeof(struct loongarch_special_attribute)); ++ ++ boot_params_p = p; ++} ++ ++static void init_smbios(struct smbios_tables *smbios) ++{ ++ smbios->vers = 1; ++ smbios->vga_bios = 1; ++ init_loongarch_params(&(smbios->lp)); ++} ++ ++static void init_efi(struct efi_loongarch *efi) ++{ ++ init_smbios(&(efi->smbios)); ++} ++ ++static int init_boot_param(struct boot_params *bp) ++{ ++ init_efi(&(bp->efi)); ++ ++ return 0; ++} ++ ++static unsigned int ls3a5k_aui_boot_code[] = { ++ 0x0380200d, /* ori $r13,$r0,0x8 */ ++ 0x0400002d, /* csrwr $r13,0x0 */ ++ 0x0401000e, /* csrrd $r14,0x40 */ ++ 0x0343fdce, /* andi $r14,$r14,0xff */ ++ 0x143fc02c, /* lu12i.w $r12,261889(0x1fe01) */ ++ 0x1600000c, /* lu32i.d $r12,0 */ ++ 0x0320018c, /* lu52i.d $r12,$r12,-1792(0x800) */ ++ 0x03400dcf, /* andi $r15,$r14,0x3 */ ++ 0x004121ef, /* slli.d $r15,$r15,0x8 */ ++ 0x00153d8c, /* or $r12,$r12,$r15 */ ++ 0x034031d0, /* andi $r16,$r14,0xc */ ++ 0x0041aa10, /* slli.d $r16,$r16,0x2a */ ++ 0x0015418c, /* or $r12,$r12,$r16 */ ++ 0x28808184, /* ld.w $r4,$r12,32(0x20) */ ++ 0x43fffc9f, /* beqz $r4,0 -4 */ ++ 0x28c08184, /* ld.d $r4,$r12,32(0x20) */ ++ 0x28c0a183, /* ld.d $r3,$r12,40(0x28) */ ++ 0x28c0c182, /* ld.d $r2,$r12,48(0x30) */ ++ 0x28c0e185, /* ld.d $r5,$r12,56(0x38) */ ++ 0x4c000080, /* jirl $r0,$r4,0 */ ++}; ++ ++static int set_bootparam_uefi(ram_addr_t initrd_offset, long initrd_size) ++{ ++ long params_size; ++ char memenv[32]; ++ char highmemenv[32]; ++ void *params_buf; ++ unsigned long *parg_env; ++ int ret = 0; ++ ++ /* Allocate params_buf for command line. */ ++ params_size = 0x100000; ++ params_buf = g_malloc0(params_size); ++ ++ /* ++ * Layout of params_buf looks like this: ++ * argv[0], argv[1], 0, env[0], env[1], ...env[i], 0, ++ * argv[0]'s data, argv[1]'s data, env[0]'data, ..., env[i]'s data, 0 ++ */ ++ parg_env = (void *)params_buf; ++ ++ ret = (3 + 1) * sizeof(target_ulong); ++ *parg_env++ = (BOOTPARAM_ADDR + ret); ++ ret += (1 + snprintf(params_buf + ret, COMMAND_LINE_SIZE - ret, "g")); ++ ++ /* argv1 */ ++ *parg_env++ = BOOTPARAM_ADDR + ret; ++ if (initrd_size > 0) ++ ret += (1 + snprintf(params_buf + ret, COMMAND_LINE_SIZE - ret, ++ "rd_start=0x%llx rd_size=%li %s", ++ PHYS_TO_VIRT((uint32_t)initrd_offset), ++ initrd_size, loaderparams.kernel_cmdline)); ++ else ++ ret += (1 + snprintf(params_buf + ret, COMMAND_LINE_SIZE - ret, "%s", ++ loaderparams.kernel_cmdline)); ++ ++ /* argv2 */ ++ *parg_env++ = 0; ++ ++ /* env */ ++ sprintf(memenv, "%lu", loaderparams.ram_size > 0x10000000 ++ ? 256 : (loaderparams.ram_size >> 20)); ++ sprintf(highmemenv, "%lu", loaderparams.ram_size > 0x10000000 ++ ? (loaderparams.ram_size >> 20) - 256 : 0); ++ ++ setenv("memsize", memenv, 1); ++ setenv("highmemsize", highmemenv, 1); ++ ++ ret = ((ret + 32) & ~31); ++ ++ boot_params_buf = (void *)(params_buf + ret); ++ boot_params_p = boot_params_buf + align(sizeof(struct boot_params)); ++ init_boot_param(boot_params_buf); ++ rom_add_blob_fixed("params", params_buf, params_size, ++ BOOTPARAM_PHYADDR); ++ loaderparams.a0 = 2; ++ loaderparams.a1 = BOOTPARAM_ADDR; ++ loaderparams.a2 = BOOTPARAM_ADDR + ret; ++ ++ return 0; ++} ++ ++static uint64_t cpu_loongarch_virt_to_phys(void *opaque, uint64_t addr) ++{ ++ return addr & 0x1fffffffll; ++} ++ ++static void fw_cfg_add_kernel_info(FWCfgState *fw_cfg, ++ uint64_t highram_size, ++ uint64_t phyAddr_initrd) ++{ ++ int64_t entry, kernel_low, kernel_high; ++ long initrd_size = 0; ++ uint64_t initrd_offset = 0; ++ void *cmdline_buf; ++ int ret = 0; ++ ++ ret = load_elf(loaderparams.kernel_filename, NULL, cpu_loongarch_virt_to_phys, NULL, ++ (uint64_t *)&entry, (uint64_t *)&kernel_low, ++ (uint64_t *)&kernel_high, NULL, 0, EM_LOONGARCH, 1, 0); ++ ++ if(0 > ret) { ++ error_report("kernel image load error"); ++ exit(1); ++ } ++ ++ fw_cfg_add_i64(fw_cfg, FW_CFG_KERNEL_ENTRY, entry); ++ ++ if (loaderparams.initrd_filename) { ++ initrd_size = get_image_size(loaderparams.initrd_filename); ++ if (0 < initrd_size) { ++ if (initrd_size > highram_size) { ++ error_report("initrd size is too big, should below %ld MB", ++ highram_size / S_1MiB); ++ /*prevent write io memory address space*/ ++ exit(1); ++ } ++ initrd_offset = (phyAddr_initrd - initrd_size) & TARGET_REALPAGE_MASK; ++ initrd_size = load_image_targphys(loaderparams.initrd_filename, ++ initrd_offset, ++ loaderparams.ram_size - initrd_offset); ++ fw_cfg_add_i64(fw_cfg, FW_CFG_INITRD_ADDR, initrd_offset); ++ fw_cfg_add_i64(fw_cfg, FW_CFG_INITRD_SIZE, initrd_size); ++ } else { ++ error_report("initrd image size is error"); ++ } ++ } ++ ++ cmdline_buf = g_malloc0(COMMAND_LINE_SIZE); ++ if (initrd_size > 0) ++ ret = (1 + snprintf(cmdline_buf, COMMAND_LINE_SIZE, ++ "rd_start=0x%llx rd_size=%li %s", ++ PHYS_TO_VIRT(initrd_offset), ++ initrd_size, loaderparams.kernel_cmdline)); ++ else ++ ret = (1 + snprintf(cmdline_buf, COMMAND_LINE_SIZE, "%s", ++ loaderparams.kernel_cmdline)); ++ ++ fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE, ret); ++ fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA, (const char *)cmdline_buf); ++ ++ return ; ++} ++ ++static int64_t load_kernel(void) ++{ ++ int64_t entry, kernel_low, kernel_high; ++ long initrd_size = 0; ++ ram_addr_t initrd_offset = 0; ++ ++ load_elf(loaderparams.kernel_filename, NULL, cpu_loongarch_virt_to_phys, NULL, ++ (uint64_t *)&entry, (uint64_t *)&kernel_low, ++ (uint64_t *)&kernel_high, NULL, 0, EM_LOONGARCH, 1, 0); ++ ++ if (loaderparams.initrd_filename) { ++ initrd_size = get_image_size(loaderparams.initrd_filename); ++ ++ if (initrd_size > 0) { ++ initrd_offset = (kernel_high * 4 + ~TARGET_REALPAGE_MASK) ++ & TARGET_REALPAGE_MASK; ++ initrd_size = load_image_targphys(loaderparams.initrd_filename, ++ initrd_offset, ++ loaderparams.ram_size - initrd_offset); ++ } ++ } ++ set_bootparam_uefi(initrd_offset, initrd_size); ++ ++ return entry; ++} ++ ++static void main_cpu_reset(void *opaque) ++{ ++ ResetData *s = (ResetData *)opaque; ++ CPULOONGARCHState *env = &s->cpu->env; ++ ++ cpu_reset(CPU(s->cpu)); ++ env->active_tc.PC = s->vector; ++ env->active_tc.gpr[4] = loaderparams.a0; ++ env->active_tc.gpr[5] = loaderparams.a1; ++ env->active_tc.gpr[6] = loaderparams.a2; ++} ++ ++void slave_cpu_reset(void *opaque) ++{ ++ ResetData *s = (ResetData *)opaque; ++ ++ cpu_reset(CPU(s->cpu)); ++} ++ ++ ++/* KVM_IRQ_LINE irq field index values */ ++#define KVM_LOONGARCH_IRQ_TYPE_SHIFT 24 ++#define KVM_LOONGARCH_IRQ_TYPE_MASK 0xff ++#define KVM_LOONGARCH_IRQ_VCPU_SHIFT 16 ++#define KVM_LOONGARCH_IRQ_VCPU_MASK 0xff ++#define KVM_LOONGARCH_IRQ_NUM_SHIFT 0 ++#define KVM_LOONGARCH_IRQ_NUM_MASK 0xffff ++ ++/* irq_type field */ ++#define KVM_LOONGARCH_IRQ_TYPE_CPU_IP 0 ++#define KVM_LOONGARCH_IRQ_TYPE_CPU_IO 1 ++#define KVM_LOONGARCH_IRQ_TYPE_HT 2 ++#define KVM_LOONGARCH_IRQ_TYPE_MSI 3 ++#define KVM_LOONGARCH_IRQ_TYPE_IOAPIC 4 ++ ++static void legacy_set_irq(void *opaque, int irq, int level) ++{ ++ qemu_irq *pic = opaque; ++ ++ qemu_set_irq(pic[irq], level); ++} ++ ++typedef struct ls3a_intctlstate { ++ uint8_t nodecounter_reg[0x100]; ++ uint8_t pm_reg[0x100]; ++ uint8_t msi_reg[0x8]; ++ CPULOONGARCHState **env; ++ DeviceState *apicdev; ++ qemu_irq *ioapic_irq; ++#ifdef CONFIG_KVM ++ struct loongarch_kvm_irqchip chip; ++#endif ++} ls3a_intctlstate; ++ ++typedef struct ls3a_func_args { ++ ls3a_intctlstate *state; ++ uint64_t base; ++ uint32_t mask; ++ uint8_t *mem; ++} ls3a_func_args; ++ ++static uint64_t ls3a_msi_mem_read(void *opaque, hwaddr addr, unsigned size) ++{ ++ return 0; ++} ++ ++static void ls3a_msi_mem_write(void *opaque, hwaddr addr, ++ uint64_t val, unsigned size) ++{ ++ struct kvm_msi msi; ++ apicState *apic; ++ ++ apic = (apicState *)opaque; ++ msi.address_lo = 0; ++ msi.address_hi = 0; ++ msi.data = val & 0xff; ++ msi.flags = 0; ++ memset(msi.pad, 0, sizeof(msi.pad)); ++ ++ if (kvm_irqchip_in_kernel()) { ++ kvm_vm_ioctl(kvm_state, KVM_SIGNAL_MSI, &msi); ++ } else { ++ qemu_set_irq(apic->irq[msi.data], 1); ++ } ++} ++ ++ ++static const MemoryRegionOps ls3a_msi_ops = { ++ .read = ls3a_msi_mem_read, ++ .write = ls3a_msi_mem_write, ++ .endianness = DEVICE_NATIVE_ENDIAN, ++}; ++ ++ ++static const VMStateDescription vmstate_ls3a_msi = { ++ .name = "ls3a-msi", ++ .version_id = 0, ++ .minimum_version_id = 0, ++ .fields = (VMStateField[]) { ++ VMSTATE_UINT8_ARRAY(msi_reg, ls3a_intctlstate, 0x8), ++ VMSTATE_END_OF_LIST() ++ } ++}; ++ ++static void ioapic_handler(void *opaque, int irq, int level) ++{ ++ apicState *apic; ++ int kvm_irq; ++ ++ apic = (apicState *)opaque; ++ ++ if (kvm_irqchip_in_kernel()) { ++ kvm_irq = (KVM_LOONGARCH_IRQ_TYPE_IOAPIC << KVM_LOONGARCH_IRQ_TYPE_SHIFT) ++ | (0 << KVM_LOONGARCH_IRQ_VCPU_SHIFT) | irq; ++ kvm_set_irq(kvm_state, kvm_irq, !!level); ++ } else { ++ qemu_set_irq(apic->irq[irq], level); ++ } ++} ++ ++static void *ls3a_intctl_init(MachineState *machine, CPULOONGARCHState *env[]) ++{ ++ qemu_irq *irqhandler; ++ ls3a_intctlstate *s; ++ LoongarchMachineState *lsms = LoongarchMACHINE(machine); ++ LoongarchMachineClass *mc = LoongarchMACHINE_GET_CLASS(lsms); ++ DeviceState *dev; ++ SysBusDevice *busdev; ++ MemoryRegion *address_space_mem = get_system_memory(); ++ MemoryRegion *iomem = NULL; ++ int i; ++ ++ s = g_malloc0(sizeof(ls3a_intctlstate)); ++ ++ if (!s) { ++ return NULL; ++ } ++ ++ /*Add MSI mmio memory*/ ++ iomem = g_new(MemoryRegion, 1); ++ memory_region_init_io(iomem, NULL, &ls3a_msi_ops, lsms->apic, ++ "ls3a_msi", 0x8); ++ memory_region_add_subregion(address_space_mem, ++ MSI_ADDR_LOW, iomem); ++ vmstate_register(NULL, 0, &vmstate_ls3a_msi, s); ++ ++ s->env = env; ++ ++ if (!strcmp(mc->bridge_name, "ls7a")) { ++ if (lsms->apic_xrupt_override) { ++ DPRINTF("irqchip in kernel %d\n", kvm_irqchip_in_kernel()); ++#ifdef CONFIG_KVM ++ if (kvm_has_gsi_routing()) { ++ for (i = 0; i < 32; ++i) { ++ kvm_irqchip_add_irq_route(kvm_state, i, 0, i); ++ } ++ kvm_gsi_routing_allowed = true; ++ } ++ kvm_msi_via_irqfd_allowed = kvm_irqfds_enabled(); ++#endif ++ } ++ ++ irqhandler = qemu_allocate_irqs(ioapic_handler, lsms->apic, 64); ++ dev = qdev_new("ioapic"); ++ busdev = SYS_BUS_DEVICE(dev); ++ sysbus_realize_and_unref(busdev, &error_fatal); ++ sysbus_mmio_map(busdev, 0, mc->ls7a_ioapic_reg_base); ++ s->ioapic_irq = irqhandler; ++ s->apicdev = dev; ++ return s->ioapic_irq; ++ } ++ return NULL; ++} ++ ++/* Network support */ ++static void network_init(PCIBus *pci_bus) ++{ ++ int i; ++ ++ for (i = 0; i < nb_nics; i++) { ++ NICInfo *nd = &nd_table[i]; ++ ++ if (!nd->model) { ++ nd->model = g_strdup("virtio-net-pci"); ++ } ++ ++ pci_nic_init_nofail(nd, pci_bus, nd->model, NULL); ++ } ++} ++ ++void loongarch_cpu_destroy(MachineState *machine, LOONGARCHCPU *cpu) ++{ ++ LoongarchMachineState *lsms = LoongarchMACHINE(machine); ++ unsigned int id; ++ int smp_cpus = machine->smp.cpus; ++ id = cpu->id; ++ qemu_unregister_reset(slave_cpu_reset, lsms->reset_info[id]); ++ g_free(lsms->reset_info[id]); ++ lsms->reset_info[id] = NULL; ++ ++ smp_cpus -= 1; ++ if (lsms->fw_cfg) { ++ fw_cfg_modify_i16(lsms->fw_cfg, FW_CFG_NB_CPUS, ++ (uint16_t)smp_cpus); ++ } ++ ++ qemu_del_vm_change_state_handler(cpu->cpuStateEntry); ++} ++ ++LOONGARCHCPU *loongarch_cpu_create(MachineState *machine, ++ LOONGARCHCPU *cpu, Error **errp) ++{ ++ CPULOONGARCHState *env; ++ unsigned int id; ++ LoongarchMachineState *lsms = LoongarchMACHINE(machine); ++ int smp_cpus = machine->smp.cpus; ++ id = cpu->id; ++ env = &cpu->env; ++ cpu_states[id] = env; ++ env->CSR_TMID |= id; ++ ++ lsms = LoongarchMACHINE(machine); ++ lsms->reset_info[id] = g_malloc0(sizeof(ResetData)); ++ lsms->reset_info[id]->cpu = cpu; ++ lsms->reset_info[id]->vector = env->active_tc.PC; ++ qemu_register_reset(slave_cpu_reset, lsms->reset_info[id]); ++ ++ /* Init CPU internal devices */ ++ cpu_init_irq(cpu); ++ cpu_loongarch_clock_init(cpu); ++ ++ smp_cpus += 1; ++ if (lsms->fw_cfg) { ++ fw_cfg_modify_i16(lsms->fw_cfg, FW_CFG_NB_CPUS, (uint16_t)smp_cpus); ++ } ++ cpu_init_ipi(lsms, env->irq[12], id); ++ cpu_init_apic(lsms, env, id); ++ ++ return cpu; ++} ++ ++static void fw_cfg_boot_set(void *opaque, const char *boot_device, ++ Error **errp) ++{ ++ fw_cfg_modify_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]); ++} ++ ++static FWCfgState *loongarch_fw_cfg_init(ram_addr_t ram_size, ++ LoongarchMachineState *lsms) ++{ ++ FWCfgState *fw_cfg; ++ uint64_t *numa_fw_cfg; ++ int i; ++ const CPUArchIdList *cpus; ++ MachineClass *mc = MACHINE_GET_CLASS(lsms); ++ MachineState *ms = MACHINE(OBJECT(lsms)); ++ int max_cpus = ms->smp.max_cpus; ++ int smp_cpus = ms->smp.cpus; ++ int nb_numa_nodes = ms->numa_state->num_nodes; ++ NodeInfo *numa_info = ms->numa_state->nodes; ++ ++ fw_cfg = fw_cfg_init_mem_wide(FW_CFG_ADDR + 8, FW_CFG_ADDR, 8, 0, NULL); ++ fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus); ++ fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size); ++ fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, (uint16_t)smp_cpus); ++ ++ /* allocate memory for the NUMA channel: one (64bit) word for the number ++ * of nodes, one word for each VCPU->node and one word for each node to ++ * hold the amount of memory. ++ */ ++ numa_fw_cfg = g_new0(uint64_t, 1 + max_cpus + nb_numa_nodes); ++ numa_fw_cfg[0] = cpu_to_le64(nb_numa_nodes); ++ cpus = mc->possible_cpu_arch_ids(MACHINE(lsms)); ++ for (i = 0; i < cpus->len; i++) { ++ unsigned int apic_id = cpus->cpus[i].arch_id; ++ assert(apic_id < max_cpus); ++ numa_fw_cfg[apic_id + 1] = cpu_to_le64(cpus->cpus[i].props.node_id); ++ } ++ for (i = 0; i < nb_numa_nodes; i++) { ++ numa_fw_cfg[max_cpus + 1 + i] = ++ cpu_to_le64(numa_info[i].node_mem); ++ } ++ fw_cfg_add_bytes(fw_cfg, FW_CFG_NUMA, numa_fw_cfg, ++ (1 + max_cpus + nb_numa_nodes) * ++ sizeof(*numa_fw_cfg)); ++ ++ qemu_register_boot_set(fw_cfg_boot_set, fw_cfg); ++ return fw_cfg; ++} ++ ++static void loongarch_build_smbios(LoongarchMachineState *lsms) ++{ ++ LoongarchMachineClass *lsmc = LoongarchMACHINE_GET_CLASS(lsms); ++ MachineState *ms = MACHINE(OBJECT(lsms)); ++ uint8_t *smbios_tables, *smbios_anchor; ++ size_t smbios_tables_len, smbios_anchor_len; ++ const char *product = "QEMU Virtual Machine"; ++ ms->smp.cores = 4; ++ ++ if (!lsms->fw_cfg) { ++ return; ++ } ++ ++ if (kvm_enabled()) { ++ if (strstr(lsmc->cpu_name, "5000")) { ++ product = "KVM"; ++ } ++ } else { ++ product = "Loongarch-3A5K-7A1000-TCG"; ++ } ++ ++ host_cpufreq = get_host_cpu_freq(); ++ ++ smbios_set_defaults("Loongson", product, lsmc->cpu_name, false, ++ true, NULL, NULL, SMBIOS_ENTRY_POINT_30); ++ ++ smbios_get_tables(ms, NULL, 0, &smbios_tables, &smbios_tables_len, ++ &smbios_anchor, &smbios_anchor_len, &error_fatal); ++ ++ if (smbios_anchor) { ++ fw_cfg_add_file(lsms->fw_cfg, "etc/smbios/smbios-tables", ++ smbios_tables, smbios_tables_len); ++ fw_cfg_add_file(lsms->fw_cfg, "etc/smbios/smbios-anchor", ++ smbios_anchor, smbios_anchor_len); ++ } ++} ++ ++static ++void loongarch_machine_done(Notifier *notifier, void *data) ++{ ++ LoongarchMachineState *lsms = container_of(notifier, ++ LoongarchMachineState, machine_done); ++ loongarch_acpi_setup(); ++ loongarch_build_smbios(lsms); ++} ++ ++#ifdef CONFIG_TCG ++#define FEATURE_REG 0x1fe00008 ++#define VENDOR_REG 0x1fe00010 ++#define CPUNAME_REG 0x1fe00020 ++#define OTHER_FUNC_REG 0x1fe00420 ++#define _str(x) #x ++#define str(x) _str(x) ++#define SIMPLE_OPS(ADDR, SIZE) \ ++({\ ++ MemoryRegion *iomem = g_new(MemoryRegion, 1);\ ++ memory_region_init_io(iomem, NULL, &loongarch_qemu_ops, \ ++ (void *)ADDR, str(ADDR) , SIZE);\ ++ memory_region_add_subregion_overlap(address_space_mem, ADDR, iomem, 1);\ ++}) ++ ++static int reg180; ++ ++static void loongarch_qemu_write(void *opaque, hwaddr addr, ++ uint64_t val, unsigned size) ++{ ++ addr = ((hwaddr)(long)opaque) + addr; ++ addr = addr & 0xffffffff; ++ switch (addr) { ++ case 0x1fe00180: ++ reg180 = val; ++ break; ++ } ++} ++ ++static uint64_t loongarch_qemu_read(void *opaque, hwaddr addr, unsigned size) ++{ ++ uint64_t feature = 0UL; ++ addr = ((hwaddr)(long)opaque) + addr; ++ addr = addr & 0xffffffff; ++ switch (addr) { ++ case 0x1fe00180: ++ return reg180; ++ case 0x1001041c: ++ return 0xa800; ++ case FEATURE_REG: ++ feature |= 1UL << 2 | 1UL << 3 | 1UL << 4 | 1UL << 11; ++ return feature ; ++ case VENDOR_REG: ++ return *(uint64_t *)"Loongson-3A5000"; ++ case CPUNAME_REG: ++ return *(uint64_t *)"3A5000"; ++ case 0x10013ffc: ++ return 0x80; ++ } ++ return 0; ++} ++ ++static const MemoryRegionOps loongarch_qemu_ops = { ++ .read = loongarch_qemu_read, ++ .write = loongarch_qemu_write, ++ .endianness = DEVICE_NATIVE_ENDIAN, ++ .valid = { ++ .min_access_size = 4, ++ .max_access_size = 8, ++ }, ++ .impl = { ++ .min_access_size = 4, ++ .max_access_size = 8, ++ }, ++}; ++#endif ++ ++ ++static void loongarch_system_flash_cleanup_unused(LoongarchMachineState *lsms) ++{ ++ char *prop_name; ++ int i; ++ Object *dev_obj; ++ ++ for (i = 0; i < ARRAY_SIZE(lsms->flash); i++) { ++ dev_obj = OBJECT(lsms->flash[i]); ++ if (!object_property_get_bool(dev_obj, "realized", &error_abort)) { ++ prop_name = g_strdup_printf("pflash%d", i); ++ object_property_del(OBJECT(lsms), prop_name); ++ g_free(prop_name); ++ object_unparent(dev_obj); ++ lsms->flash[i] = NULL; ++ } ++ } ++} ++ ++ ++static bool loongarch_system_flash_init( LoongarchMachineState *lsms) ++{ ++ int i = 0; ++ int64_t size = 0; ++ PFlashCFI01 *pflash = NULL; ++ BlockBackend *pflash_blk; ++ ++ for(i = 0; i < ARRAY_SIZE(lsms->flash); i++) { ++ pflash_blk = NULL; ++ pflash = NULL; ++ ++ pflash = lsms->flash[i]; ++ pflash_cfi01_legacy_drive(pflash, ++ drive_get(IF_PFLASH, 0, i)); ++ ++ pflash_blk = pflash_cfi01_get_blk(pflash); ++ /*The pflash0 must be exist, or not support boot by pflash*/ ++ if(pflash_blk == NULL) { ++ if(i == 0) { ++ return false; ++ } else { ++ break; ++ } ++ } ++ ++ size = blk_getlength(pflash_blk); ++ if (size == 0 || size % FLASH_SECTOR_SIZE != 0) { ++ error_report("system firmware block device %s has invalid size " ++ "%" PRId64, ++ blk_name(pflash_blk), size); ++ error_report("its size must be a non-zero multiple of 0x%x", ++ FLASH_SECTOR_SIZE); ++ exit(1); ++ } ++ qdev_prop_set_uint32(DEVICE(pflash), "num-blocks", ++ size / FLASH_SECTOR_SIZE); ++ sysbus_realize_and_unref(SYS_BUS_DEVICE(pflash), &error_fatal); ++ if(i == 0) { ++ sysbus_mmio_map(SYS_BUS_DEVICE(pflash), 0, LS_BIOS_BASE); ++ } else { ++ sysbus_mmio_map_overlap(SYS_BUS_DEVICE(pflash), 0, LS_BIOS_VAR_BASE, 1); ++ } ++ } ++ ++ return true; ++} ++static void ls3a5k_bios_init(LoongarchMachineState *lsms, ++ ram_addr_t ram_size, ++ uint64_t highram_size, ++ uint64_t phyAddr_initrd, ++ const char *kernel_filename, ++ const char *kernel_cmdline, ++ const char *initrd_filename) ++{ ++ MemoryRegion *bios; ++ bool fw_cfg_used = false; ++ LoongarchMachineClass *lsmc = LoongarchMACHINE_GET_CLASS(lsms); ++ char *filename; ++ int bios_size; ++ const char *bios_name; ++ ++ bios_name = MACHINE(lsms)->firmware; ++ if (kernel_filename) { ++ loaderparams.ram_size = ram_size; ++ loaderparams.kernel_filename = kernel_filename; ++ loaderparams.kernel_cmdline = kernel_cmdline; ++ loaderparams.initrd_filename = initrd_filename; ++ } ++ ++ if(loongarch_system_flash_init(lsms)) { ++ fw_cfg_used = true; ++ } else { ++ bios = g_new(MemoryRegion, 1); ++ memory_region_init_ram(bios, NULL, "loongarch.bios", LS_BIOS_SIZE, &error_fatal); ++ memory_region_set_readonly(bios, true); ++ memory_region_add_subregion(get_system_memory(), LS_BIOS_BASE, bios); ++ ++ /* BIOS load */ ++ if (bios_name) { ++ if (access(bios_name, R_OK) == 0) { ++ load_image_targphys(bios_name, LS_BIOS_BASE, LS_BIOS_SIZE); ++ } else { ++ filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); ++ load_image_targphys(filename, LS_BIOS_BASE, LS_BIOS_SIZE); ++ g_free(filename); ++ } ++ fw_cfg_used = true; ++ } else { ++ if (strstr(lsmc->cpu_name, "5000")) { ++ bios_size = sizeof(ls3a5k_aui_boot_code); ++ rom_add_blob_fixed("bios", ls3a5k_aui_boot_code, bios_size, LS_BIOS_BASE); ++ } ++ ++ if (kernel_filename) { ++ lsms->reset_info[0]->vector = load_kernel(); ++ } else { ++ error_report("Please specify at lease one of -bios and -kernel"); ++ exit(1); ++ } ++ } ++ } ++ ++ loongarch_system_flash_cleanup_unused(lsms); ++ ++ if (fw_cfg_used) { ++ lsms->fw_cfg = loongarch_fw_cfg_init(ram_size, lsms); ++ rom_set_fw(lsms->fw_cfg); ++ fw_conf_init(ram_size); ++ rom_add_blob_fixed("fw_conf", (void *)&fw_config, ++ sizeof(fw_config), FW_CONF_ADDR); ++ ++ if (kernel_filename) { ++ fw_cfg_add_kernel_info(lsms->fw_cfg, highram_size, phyAddr_initrd); ++ } ++ } ++ ++ if (lsms->fw_cfg != NULL) { ++ fw_cfg_add_file(lsms->fw_cfg, "etc/memmap", ++ la_memmap_table, ++ sizeof(struct la_memmap_entry) * (la_memmap_entries)); ++ } ++ ++ return ; ++} ++static void create_fdt(LoongarchMachineState *lsms) ++{ ++ lsms->fdt = create_device_tree(&lsms->fdt_size); ++ if (!lsms->fdt) { ++ error_report("create_device_tree() failed"); ++ exit(1); ++ } ++ ++ /* Header */ ++ qemu_fdt_setprop_string(lsms->fdt, "/", "compatible", ++ "linux,dummy-loongson3"); ++ qemu_fdt_setprop_cell(lsms->fdt, "/", "#address-cells", 0x2); ++ qemu_fdt_setprop_cell(lsms->fdt, "/", "#size-cells", 0x2); ++} ++ ++static void fdt_add_cpu_nodes(const LoongarchMachineState *lsms) ++{ ++ int num; ++ const MachineState *ms = MACHINE(lsms); ++ int smp_cpus = ms->smp.cpus; ++ ++ qemu_fdt_add_subnode(lsms->fdt, "/cpus"); ++ qemu_fdt_setprop_cell(lsms->fdt, "/cpus", "#address-cells", 0x1); ++ qemu_fdt_setprop_cell(lsms->fdt, "/cpus", "#size-cells", 0x0); ++ ++ /* cpu nodes */ ++ for (num = smp_cpus - 1; num >= 0; num--) { ++ char *nodename = g_strdup_printf("/cpus/cpu@%d", num); ++ LOONGARCHCPU *cpu = LOONGARCH_CPU(qemu_get_cpu(num)); ++ ++ qemu_fdt_add_subnode(lsms->fdt, nodename); ++ qemu_fdt_setprop_string(lsms->fdt, nodename, "device_type", "cpu"); ++ qemu_fdt_setprop_string(lsms->fdt, nodename, "compatible", ++ cpu->dtb_compatible); ++ qemu_fdt_setprop_cell(lsms->fdt, nodename, "reg", num); ++ qemu_fdt_setprop_cell(lsms->fdt, nodename, "phandle", ++ qemu_fdt_alloc_phandle(lsms->fdt)); ++ g_free(nodename); ++ } ++ ++ /*cpu map */ ++ qemu_fdt_add_subnode(lsms->fdt, "/cpus/cpu-map"); ++ ++ for (num = smp_cpus - 1; num >= 0; num--) { ++ char *cpu_path = g_strdup_printf("/cpus/cpu@%d", num); ++ char *map_path; ++ ++ if (ms->smp.threads > 1) { ++ map_path = g_strdup_printf( ++ "/cpus/cpu-map/socket%d/core%d/thread%d", ++ num / (ms->smp.cores * ms->smp.threads), ++ (num / ms->smp.threads) % ms->smp.cores, ++ num % ms->smp.threads); ++ } else { ++ map_path = g_strdup_printf( ++ "/cpus/cpu-map/socket%d/core%d", ++ num / ms->smp.cores, ++ num % ms->smp.cores); ++ } ++ qemu_fdt_add_path(lsms->fdt, map_path); ++ qemu_fdt_setprop_phandle(lsms->fdt, map_path, "cpu", cpu_path); ++ ++ g_free(map_path); ++ g_free(cpu_path); ++ } ++} ++ ++static void fdt_add_fw_cfg_node(const LoongarchMachineState *lsms) ++{ ++ char *nodename; ++ hwaddr base = FW_CFG_ADDR; ++ ++ nodename = g_strdup_printf("/fw_cfg@%" PRIx64, base); ++ qemu_fdt_add_subnode(lsms->fdt, nodename); ++ qemu_fdt_setprop_string(lsms->fdt, nodename, ++ "compatible", "qemu,fw-cfg-mmio"); ++ qemu_fdt_setprop_sized_cells(lsms->fdt, nodename, "reg", ++ 2, base, 2, 0x8); ++ qemu_fdt_setprop(lsms->fdt, nodename, "dma-coherent", NULL, 0); ++ g_free(nodename); ++} ++ ++static void fdt_add_pcie_node(const LoongarchMachineState *lsms) ++{ ++ char *nodename; ++ hwaddr base_mmio = LS_ISA_MEM_BASE; ++ hwaddr size_mmio = LS_ISA_MEM_SIZE; ++ hwaddr base_pio = LS3A5K_ISA_IO_BASE; ++ hwaddr size_pio = LS_ISA_IO_SIZE; ++ hwaddr base_pcie = LS_PCIECFG_BASE; ++ hwaddr size_pcie = LS_PCIECFG_SIZE; ++ hwaddr base = base_pcie; ++ ++ nodename = g_strdup_printf("/pcie@%" PRIx64, base); ++ qemu_fdt_add_subnode(lsms->fdt, nodename); ++ qemu_fdt_setprop_string(lsms->fdt, nodename, ++ "compatible", "pci-host-ecam-generic"); ++ qemu_fdt_setprop_string(lsms->fdt, nodename, "device_type", "pci"); ++ qemu_fdt_setprop_cell(lsms->fdt, nodename, "#address-cells", 3); ++ qemu_fdt_setprop_cell(lsms->fdt, nodename, "#size-cells", 2); ++ qemu_fdt_setprop_cell(lsms->fdt, nodename, "linux,pci-domain", 0); ++ qemu_fdt_setprop_cells(lsms->fdt, nodename, "bus-range", 0, ++ PCIE_MMCFG_BUS(LS_PCIECFG_SIZE - 1)); ++ qemu_fdt_setprop(lsms->fdt, nodename, "dma-coherent", NULL, 0); ++ qemu_fdt_setprop_sized_cells(lsms->fdt, nodename, "reg", ++ 2, base_pcie, 2, size_pcie); ++ qemu_fdt_setprop_sized_cells(lsms->fdt, nodename, "ranges", ++ 1, FDT_PCI_RANGE_IOPORT, 2, 0, ++ 2, base_pio, 2, size_pio, ++ 1, FDT_PCI_RANGE_MMIO, 2, base_mmio, ++ 2, base_mmio, 2, size_mmio); ++ g_free(nodename); ++ qemu_fdt_dumpdtb(lsms->fdt, lsms->fdt_size); ++} ++ ++static void ls3a5k_init(MachineState *args) ++{ ++ int i; ++ const char *cpu_model = args->cpu_type; ++ const char *kernel_filename = args->kernel_filename; ++ const char *kernel_cmdline = args->kernel_cmdline; ++ const char *initrd_filename = args->initrd_filename; ++ ++ ram_addr_t ram_size = args->ram_size; ++ MemoryRegion *address_space_mem = get_system_memory(); ++ ram_addr_t offset = 0; ++ MemoryRegion *isa_io = g_new(MemoryRegion, 1); ++ MemoryRegion *isa_mem = g_new(MemoryRegion, 1); ++ MachineState *machine = args; ++ MachineClass *mc = MACHINE_GET_CLASS(machine); ++ LoongarchMachineState *lsms = LoongarchMACHINE(machine); ++ LoongarchMachineClass *lsmc = LoongarchMACHINE_GET_CLASS(lsms); ++ int smp_cpus = machine->smp.cpus; ++ int nb_numa_nodes = machine->numa_state->num_nodes; ++ NodeInfo *numa_info = machine->numa_state->nodes; ++ LOONGARCHCPU *cpu; ++ CPULOONGARCHState *env; ++ qemu_irq *ls7a_apic = NULL; ++ qemu_irq *pirq = NULL; ++ PCIBus *pci_bus = NULL; ++ char *ramName = NULL; ++ uint64_t lowram_size = 0, highram_size = 0, phyAddr = 0, ++ memmap_size = 0, highram_end_addr = 0; ++ ++ CPUArchIdList *possible_cpus; ++ if (strstr(lsmc->cpu_name, "5000")) { ++ if (strcmp(cpu_model, LOONGARCH_CPU_TYPE_NAME("Loongson-3A5000")) && ++ strcmp(cpu_model, LOONGARCH_CPU_TYPE_NAME("host"))) { ++ error_report("machine type %s does not match cpu type %s", ++ lsmc->cpu_name, cpu_model); ++ exit(1); ++ } ++ if (kvm_enabled()) { ++ kvm_vm_ioctl(kvm_state, KVM_LARCH_SET_CPUCFG, ls3a5k_cpucfgs); ++ } ++ } ++ ++ create_fdt(lsms); ++ ++ DPRINTF("isa 0x%lx\n", lsmc->isa_io_base); ++ DPRINTF("ht1lo 0x%lx\n", lsmc->ht1lo_pcicfg_base); ++ DPRINTF("cpu_name %s bridge_name %s\n", ++ lsmc->cpu_name, lsmc->bridge_name); ++ ++ /* init CPUs */ ++ mc->possible_cpu_arch_ids(machine); ++ possible_cpus = machine->possible_cpus; ++ ++ for (i = 0; i < smp_cpus; i++) { ++ Object *obj = NULL; ++ Error *local_err = NULL; ++ ++ obj = object_new(possible_cpus->cpus[i].type); ++ ++ object_property_set_uint(obj, "id", possible_cpus->cpus[i].arch_id, ++ &local_err); ++ object_property_set_bool(obj, "realized", true, &local_err); ++ ++ object_unref(obj); ++ error_propagate(&error_fatal, local_err); ++ ++ cpu = LOONGARCH_CPU(CPU(obj)); ++ if (cpu == NULL) { ++ fprintf(stderr, "Unable to find CPU definition\n"); ++ exit(1); ++ } ++ ++ env = &cpu->env; ++ cpu_states[i] = env; ++ env->CSR_TMID |= i; ++ ++ lsms->reset_info[i] = g_malloc0(sizeof(ResetData)); ++ lsms->reset_info[i]->cpu = cpu; ++ lsms->reset_info[i]->vector = env->active_tc.PC; ++ if (i == 0) { ++ qemu_register_reset(main_cpu_reset, lsms->reset_info[i]); ++ } else { ++ qemu_register_reset(slave_cpu_reset, lsms->reset_info[i]); ++ } ++ ++ /* Init CPU internal devices */ ++ cpu_init_irq(cpu); ++ cpu_loongarch_clock_init(cpu); ++ cpu_init_ipi(lsms, env->irq[12], i); ++ cpu_init_apic(lsms, env, i); ++ } ++ ++ lsms->hotpluged_cpu_num = 0; ++ fdt_add_cpu_nodes(lsms); ++ env = cpu_states[0]; ++ ++ /* node0 mem*/ ++ phyAddr = (uint64_t)0; ++ MemoryRegion *lowmem = g_new(MemoryRegion, 1); ++ ramName = g_strdup_printf("loongarch_ls3a.node%d.lowram", 0); ++ ++ lowram_size = MIN(ram_size, 256 * 0x100000); ++ memory_region_init_alias(lowmem, NULL, ramName, machine->ram, 0, lowram_size); ++ memory_region_add_subregion(address_space_mem, phyAddr, lowmem); ++ ++ offset += lowram_size; ++ if (nb_numa_nodes > 0) { ++ highram_size = numa_info[0].node_mem - S_256MiB; ++ if (numa_info[0].node_mem > S_1GiB) { ++ memmap_size = numa_info[0].node_mem - S_1GiB; ++ la_memmap_add_entry(0xc0000000ULL, memmap_size, SYSTEM_RAM); ++ } ++ } else { ++ highram_size = ram_size - S_256MiB; ++ if (ram_size > S_1GiB) { ++ memmap_size = ram_size - S_1GiB; ++ la_memmap_add_entry(0xc0000000ULL, memmap_size, SYSTEM_RAM); ++ } ++ } ++ ++ phyAddr = (uint64_t)0x90000000; ++ MemoryRegion *highmem = g_new(MemoryRegion, 1); ++ ramName = g_strdup_printf("loongarch_ls3a.node%d.highram", 0); ++ memory_region_init_alias(highmem, NULL, ramName, ++ machine->ram, offset, highram_size); ++ memory_region_add_subregion(address_space_mem, ++ phyAddr, highmem); ++ offset += highram_size; ++ phyAddr += highram_size; ++ ++ /* initrd address use high mem from high to low */ ++ highram_end_addr = phyAddr; ++ /* node1~ nodemax */ ++ for (i = 1; i < nb_numa_nodes; i++) { ++ MemoryRegion *nodemem = g_new(MemoryRegion, 1); ++ ramName = g_strdup_printf("loongarch_ls3a.node%d.ram", i); ++ memory_region_init_alias(nodemem, NULL, ramName, ++ machine->ram, offset, numa_info[i].node_mem); ++ memory_region_add_subregion(address_space_mem, ++ phyAddr, nodemem); ++ la_memmap_add_entry(phyAddr, numa_info[i].node_mem, SYSTEM_RAM); ++ offset += numa_info[i].node_mem; ++ phyAddr += numa_info[i].node_mem; ++ } ++ ++ fdt_add_fw_cfg_node(lsms); ++ ls3a5k_bios_init(lsms, ram_size, highram_size, highram_end_addr, ++ kernel_filename, kernel_cmdline, initrd_filename); ++ ++ lsms->machine_done.notify = loongarch_machine_done; ++ qemu_add_machine_init_done_notifier(&lsms->machine_done); ++ /*vmstate_register_ram_global(bios);*/ ++ ++ /* initialize hotplug memory address space */ ++ lsms->hotplug_memory_size = 0; ++ ++ /* always allocate the device memory information */ ++ machine->device_memory = g_malloc0(sizeof(*machine->device_memory)); ++ if (machine->ram_size < machine->maxram_size) { ++ int max_memslots; ++ ++ lsms->hotplug_memory_size = machine->maxram_size - machine->ram_size; ++ /* ++ * Limit the number of hotpluggable memory slots to half the number ++ * slots that KVM supports, leaving the other half for PCI and other ++ * devices. However ensure that number of slots doesn't drop below 32. ++ */ ++ max_memslots = LOONGARCH_MAX_RAM_SLOTS; ++ if (kvm_enabled()) { ++ max_memslots = kvm_get_max_memslots() / 2 ; ++ } ++ ++ if (machine->ram_slots == 0) ++ machine->ram_slots = lsms->hotplug_memory_size / ++ LOONGARCH_HOTPLUG_MEM_ALIGN; ++ ++ if (machine->ram_slots > max_memslots) { ++ error_report("Specified number of memory slots %" ++ PRIu64" exceeds max supported %d", ++ machine->ram_slots, max_memslots); ++ exit(1); ++ } ++ ++ lsms->ram_slots = machine->ram_slots; ++ ++ machine->device_memory->base = get_hotplug_membase(machine->ram_size); ++ memory_region_init(&machine->device_memory->mr, OBJECT(lsms), ++ "device-memory", lsms->hotplug_memory_size); ++ memory_region_add_subregion(get_system_memory(), ++ machine->device_memory->base, ++ &machine->device_memory->mr); ++ } ++ ++ memory_region_init_alias(isa_io, NULL, "isa-io", ++ get_system_io(), 0, LS_ISA_IO_SIZE); ++ memory_region_init(isa_mem, NULL, "isa-mem", LS_ISA_MEM_SIZE); ++ memory_region_add_subregion(get_system_memory(), lsmc->isa_io_base, isa_io); ++ memory_region_add_subregion(get_system_memory(), LS_ISA_MEM_BASE, isa_mem); ++ ++ if (!strcmp(lsmc->bridge_name, "ls7a")) { ++ /*Initialize the 7A IO interrupt subsystem*/ ++ DeviceState *ls7a_dev; ++ lsms->apic_xrupt_override = kvm_irqchip_in_kernel(); ++ ls7a_apic = ls3a_intctl_init(machine, cpu_states); ++ if (!ls7a_apic) { ++ perror("Init 7A APIC failed\n"); ++ exit(1); ++ } ++ pci_bus = ls7a_init(machine, ls7a_apic, &ls7a_dev); ++ ++ object_property_add_link(OBJECT(machine), ++ LOONGARCH_MACHINE_ACPI_DEVICE_PROP, ++ TYPE_HOTPLUG_HANDLER, ++ (Object **)&lsms->acpi_dev, ++ object_property_allow_set_link, ++ OBJ_PROP_LINK_STRONG); ++ object_property_set_link(OBJECT(machine), LOONGARCH_MACHINE_ACPI_DEVICE_PROP, ++ OBJECT(ls7a_dev), &error_abort); ++ ++#ifdef CONFIG_KVM ++ if (kvm_enabled()) { ++ kvm_direct_msi_allowed = (kvm_check_extension(kvm_state, ++ KVM_CAP_SIGNAL_MSI) > 0); ++ } else { ++ kvm_direct_msi_allowed = 0; ++ } ++ msi_nonbroken = kvm_direct_msi_allowed; ++#else ++ msi_nonbroken = true; ++#endif ++ sysbus_create_simple("ls7a_rtc", LS7A_RTC_REG_BASE, ++ ls7a_apic[LS7A_RTC_IRQ - LOONGARCH_PCH_IRQ_BASE]); ++ } ++ ++ /*Initialize the CPU serial device*/ ++ ++ if (serial_hd(0)) { ++ pirq = qemu_allocate_irqs(legacy_set_irq, ls7a_apic + ++ (LS7A_UART_IRQ - LOONGARCH_PCH_IRQ_BASE), 1); ++ serial_mm_init(address_space_mem, LS7A_UART_BASE, 0, pirq[0], ++ 115200, serial_hd(0), DEVICE_NATIVE_ENDIAN); ++ } ++ ++ /*network card*/ ++ network_init(pci_bus); ++ /* VGA setup. Don't bother loading the bios. */ ++ pci_vga_init(pci_bus); ++ ++ sysbus_realize_and_unref(SYS_BUS_DEVICE(qdev_new("iocsr")), &error_fatal); ++ ++#ifdef CONFIG_TCG ++ int nb_nodes = (smp_cpus - 1) / 4; ++ for (i = 0; i <= nb_nodes; i++) { ++ uint64_t off = (uint64_t)i << 44; ++ SIMPLE_OPS(((hwaddr)0x1fe00180 | off), 0x8); ++ SIMPLE_OPS(((hwaddr)0x1fe0019c | off), 0x8); ++ SIMPLE_OPS(((hwaddr)0x1fe001d0 | off), 0x8); ++ SIMPLE_OPS(((hwaddr)FEATURE_REG | off), 0x8); ++ SIMPLE_OPS(((hwaddr)VENDOR_REG | off), 0x8); ++ SIMPLE_OPS(((hwaddr)CPUNAME_REG | off), 0x8); ++ SIMPLE_OPS(((hwaddr)OTHER_FUNC_REG | off), 0x8); ++ } ++ ++ SIMPLE_OPS(0x1001041c, 0x4); ++ SIMPLE_OPS(0x10002000, 0x14); ++ SIMPLE_OPS(0x10013ffc, 0x4); ++#endif ++ ++ fdt_add_pcie_node(lsms); ++ ++ /* load fdt */ ++ MemoryRegion *fdt_rom = g_new(MemoryRegion, 1); ++ memory_region_init_rom(fdt_rom, NULL, "fdt", LS_FDT_SIZE, &error_fatal); ++ memory_region_add_subregion(get_system_memory(), LS_FDT_BASE, fdt_rom); ++ rom_add_blob_fixed("fdt", lsms->fdt, lsms->fdt_size, LS_FDT_BASE); ++} ++ ++static const CPUArchIdList *loongarch_possible_cpu_arch_ids(MachineState *ms) ++{ ++ int i; ++ int max_cpus = ms->smp.max_cpus; ++ ++ if (ms->possible_cpus) { ++ /* ++ * make sure that max_cpus hasn't changed since the first use, i.e. ++ * -smp hasn't been parsed after it ++ */ ++ assert(ms->possible_cpus->len == max_cpus); ++ return ms->possible_cpus; ++ } ++ ++ ms->possible_cpus = g_malloc0(sizeof(CPUArchIdList) + ++ sizeof(CPUArchId) * max_cpus); ++ ms->possible_cpus->len = max_cpus; ++ for (i = 0; i < ms->possible_cpus->len; i++) { ++ ms->possible_cpus->cpus[i].type = ms->cpu_type; ++ ms->possible_cpus->cpus[i].vcpus_count = 1; ++ ms->possible_cpus->cpus[i].props.has_core_id = true; ++ ms->possible_cpus->cpus[i].props.core_id = i; ++ ms->possible_cpus->cpus[i].arch_id = i; ++ } ++ return ms->possible_cpus; ++ ++} ++ ++static PFlashCFI01 *loongarch_pflash_create(LoongarchMachineState *lsms, ++ const char *name, ++ const char *alias_prop_name) ++{ ++ DeviceState *dev = qdev_new(TYPE_PFLASH_CFI01); ++ ++ qdev_prop_set_uint64(dev, "sector-length", FLASH_SECTOR_SIZE); ++ qdev_prop_set_uint8(dev, "width", 1); ++ qdev_prop_set_string(dev, "name", name); ++ object_property_add_child(OBJECT(lsms), name, OBJECT(dev)); ++ object_property_add_alias(OBJECT(lsms), alias_prop_name, ++ OBJECT(dev), "drive"); ++ return PFLASH_CFI01(dev); ++} ++ ++ ++static void loongarch_system_flash_create(LoongarchMachineState *lsms) ++{ ++ lsms->flash[0] = loongarch_pflash_create(lsms, "system.flash0", ++ "pflash0"); ++ lsms->flash[1] = loongarch_pflash_create(lsms, "system.flash1", ++ "pflash1"); ++} ++ ++static void loongarch_machine_initfn(Object *obj) ++{ ++ LoongarchMachineState *lsms = LoongarchMACHINE(obj); ++ LoongarchMachineClass *lsmc = LoongarchMACHINE_GET_CLASS(lsms); ++ lsms->acpi_build_enabled = lsmc->has_acpi_build; ++ loongarch_system_flash_create(lsms); ++ lsms->oem_id = g_strndup(EFI_ACPI_OEM_ID, 6); ++ lsms->oem_table_id = g_strndup(EFI_ACPI_OEM_TABLE_ID, 6); ++} ++ ++static void ls3a5k_ls7a_machine_options(MachineClass *m) ++{ ++ char *cpu_name = get_host_cpu_model_name(); ++ LoongarchMachineClass *lsmc = LoongarchMACHINE_CLASS(m); ++ m->desc = "Loongarch3a5k LS7A1000 machine"; ++ m->max_cpus = LOONGARCH_MAX_VCPUS; ++ m->alias = "loongson7a"; ++ m->is_default = 1; ++ lsmc->isa_io_base = LS3A5K_ISA_IO_BASE; ++ lsmc->ht1lo_pcicfg_base = LS3A5K_HT1LO_PCICFG_BASE; ++ lsmc->pciecfg_base = LS_PCIECFG_BASE; ++ lsmc->ls7a_ioapic_reg_base = LS3A5K_LS7A_IOAPIC_REG_BASE; ++ lsmc->node_shift = 44; ++ strncpy(lsmc->cpu_name, cpu_name, sizeof(lsmc->cpu_name) - 1); ++ lsmc->cpu_name[sizeof(lsmc->cpu_name) - 1] = 0; ++ strncpy(lsmc->bridge_name, "ls7a", sizeof(lsmc->bridge_name) - 1); ++ lsmc->bridge_name[sizeof(lsmc->bridge_name) - 1] = 0; ++ compat_props_add(m->compat_props, loongarch_compat, loongarch_compat_len); ++} ++ ++static void ls3a_board_reset(MachineState *ms) ++{ ++ qemu_devices_reset(); ++#ifdef CONFIG_KVM ++ struct loongarch_kvm_irqchip *chip; ++ int length; ++ ++ if (!kvm_enabled()) { ++ return; ++ } ++ length = sizeof(struct loongarch_kvm_irqchip) + ++ sizeof(struct loongarch_gipiState); ++ chip = g_malloc0(length); ++ memset(chip, 0, length); ++ chip->chip_id = KVM_IRQCHIP_LS3A_GIPI; ++ chip->len = length; ++ kvm_vm_ioctl(kvm_state, KVM_SET_IRQCHIP, chip); ++ ++ length = sizeof(struct loongarch_kvm_irqchip) + sizeof(struct ls7a_ioapic_state); ++ chip = g_realloc(chip, length); ++ memset(chip, 0, length); ++ chip->chip_id = KVM_IRQCHIP_LS7A_IOAPIC; ++ chip->len = length; ++ kvm_vm_ioctl(kvm_state, KVM_SET_IRQCHIP, chip); ++ ++ g_free(chip); ++#endif ++} ++ ++static CpuInstanceProperties ls3a_cpu_index_to_props(MachineState *ms, unsigned cpu_index) ++{ ++ MachineClass *mc = MACHINE_GET_CLASS(ms); ++ const CPUArchIdList *possible_cpus = mc->possible_cpu_arch_ids(ms); ++ ++ assert(cpu_index < possible_cpus->len); ++ return possible_cpus->cpus[cpu_index].props; ++} ++ ++static int64_t ls3a_get_default_cpu_node_id(const MachineState *ms, int idx) ++{ ++ int nb_numa_nodes = ms->numa_state->num_nodes; ++ int smp_cores = ms->smp.cores; ++ return idx / smp_cores % nb_numa_nodes; ++} ++ ++static void loongarch_class_init(ObjectClass *oc, void *data) ++{ ++ MachineClass *mc = MACHINE_CLASS(oc); ++ HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc); ++ LoongarchMachineClass *lsmc = LoongarchMACHINE_CLASS(oc); ++ ++ lsmc->get_hotplug_handler = mc->get_hotplug_handler; ++ lsmc->has_acpi_build = true; ++ mc->get_hotplug_handler = loongarch_get_hotpug_handler; ++ mc->has_hotpluggable_cpus = true; ++ mc->cpu_index_to_instance_props = ls3a_cpu_index_to_props; ++ mc->possible_cpu_arch_ids = loongarch_possible_cpu_arch_ids; ++ mc->get_default_cpu_node_id = ls3a_get_default_cpu_node_id; ++ mc->default_ram_size = 1 * GiB; ++ mc->default_cpu_type = LOONGARCH_CPU_TYPE_NAME("Loongson-3A5000"); ++ mc->default_ram_id = "loongarch_ls3a.ram"; ++ ++ mc->reset = ls3a_board_reset; ++ mc->max_cpus = LOONGARCH_MAX_VCPUS; ++ hc->pre_plug = loongarch_machine_device_pre_plug; ++ hc->plug = loongarch_machine_device_plug; ++ hc->unplug = longson_machine_device_unplug; ++ hc->unplug_request = loongarch_machine_device_unplug_request; ++ ++ object_class_property_add(oc, "acpi", "OnOffAuto", ++ loongarch_get_acpi, loongarch_set_acpi, ++ NULL, NULL); ++ object_class_property_set_description(oc, "acpi", ++ "Enable ACPI"); ++} ++ ++static const TypeInfo loongarch_info = { ++ .name = TYPE_LOONGARCH_MACHINE, ++ .parent = TYPE_MACHINE, ++ .abstract = true, ++ .instance_size = sizeof(LoongarchMachineState), ++ .instance_init = loongarch_machine_initfn, ++ .class_size = sizeof(LoongarchMachineClass), ++ .class_init = loongarch_class_init, ++ .interfaces = (InterfaceInfo[]) { ++ { TYPE_HOTPLUG_HANDLER }, ++ { } ++ }, ++ ++}; ++ ++static void loongarch_machine_register_types(void) ++{ ++ type_register_static(&loongarch_info); ++} ++ ++type_init(loongarch_machine_register_types) ++ ++DEFINE_LS3A5K_MACHINE(loongson7a_v1_0, "loongson7a_v1.0", ++ ls3a5k_ls7a_machine_options); +diff --git a/hw/loongarch/larch_hotplug.c b/hw/loongarch/larch_hotplug.c +new file mode 100644 +index 0000000000..7bce957124 +--- /dev/null ++++ b/hw/loongarch/larch_hotplug.c +@@ -0,0 +1,355 @@ ++/* ++ * Hotplug emulation on Loongarch system. ++ * ++ * Copyright (c) 2018 Loongarch Inc. ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, see . ++ */ ++ ++#include "qemu/osdep.h" ++#include "qapi/error.h" ++#include "qemu-common.h" ++#include "qemu/queue.h" ++#include "qemu/units.h" ++#include "qemu/cutils.h" ++#include "qemu/bcd.h" ++#include "hw/hotplug.h" ++#include "hw/loongarch/cpudevs.h" ++#include "hw/mem/memory-device.h" ++#include "sysemu/numa.h" ++#include "sysemu/cpus.h" ++#include "hw/loongarch/larch.h" ++#include "hw/cpu/core.h" ++#include "hw/nvram/fw_cfg.h" ++ ++/* find cpu slot in machine->possible_cpus by core_id */ ++static CPUArchId *loongarch_find_cpu_slot(MachineState *ms, uint32_t id, ++ int *idx) ++{ ++ int index = id; ++ ++ if (index >= ms->possible_cpus->len) { ++ return NULL; ++ } ++ if (idx) { ++ *idx = index; ++ } ++ return &ms->possible_cpus->cpus[index]; ++} ++ ++static void loongarch_memory_plug(HotplugHandler *hotplug_dev, ++ DeviceState *dev, Error **errp) ++{ ++ Error *local_err = NULL; ++ LoongarchMachineState *lsms = LoongarchMACHINE(hotplug_dev); ++ HotplugHandlerClass *hhc; ++ uint64_t size; ++ ++ size = memory_device_get_region_size(MEMORY_DEVICE(dev), &error_abort); ++ if (size % LOONGARCH_HOTPLUG_MEM_ALIGN) { ++ error_setg(&local_err, "Hotplugged memory size must be a multiple of " ++ "%lld MB", LOONGARCH_HOTPLUG_MEM_ALIGN / MiB); ++ goto out; ++ } ++ ++ pc_dimm_plug(PC_DIMM(dev), MACHINE(lsms)); ++ ++ hhc = HOTPLUG_HANDLER_GET_CLASS(lsms->acpi_dev); ++ hhc->plug(HOTPLUG_HANDLER(lsms->acpi_dev), dev, &error_abort); ++out: ++ error_propagate(errp, local_err); ++} ++ ++static void loongarch_memory_unplug_request(HotplugHandler *hotplug_dev, ++ DeviceState *dev, Error **errp) ++{ ++ Error *local_err = NULL; ++ HotplugHandlerClass *hhc; ++ LoongarchMachineState *lsms = LoongarchMACHINE(hotplug_dev); ++ ++ if (!lsms->acpi_dev || !loongarch_is_acpi_enabled(lsms)) { ++ error_setg(&local_err, ++ "memory hotplug is not enabled: missing acpi device or acpi disabled"); ++ goto out; ++ } ++ hhc = HOTPLUG_HANDLER_GET_CLASS(lsms->acpi_dev); ++ hhc->unplug_request(HOTPLUG_HANDLER(lsms->acpi_dev), dev, &local_err); ++ ++out: ++ error_propagate(errp, local_err); ++} ++ ++static void loongarch_cpu_unplug(HotplugHandler *hotplug_dev, ++ DeviceState *dev, Error **errp) ++{ ++ CPUArchId *found_cpu; ++ HotplugHandlerClass *hhc; ++ Error *local_err = NULL; ++ LOONGARCHCPU *cpu = LOONGARCH_CPU(dev); ++ MachineState *machine = MACHINE(OBJECT(hotplug_dev)); ++ LoongarchMachineState *lsms = LoongarchMACHINE(machine); ++ ++ hhc = HOTPLUG_HANDLER_GET_CLASS(lsms->acpi_dev); ++ hhc->unplug(HOTPLUG_HANDLER(lsms->acpi_dev), dev, &local_err); ++ ++ if (local_err) { ++ goto out; ++ } ++ ++ loongarch_cpu_destroy(machine, cpu); ++ ++ found_cpu = loongarch_find_cpu_slot(MACHINE(lsms), cpu->id, NULL); ++ found_cpu->cpu = NULL; ++ object_unparent(OBJECT(dev)); ++ lsms->hotpluged_cpu_num -= 1; ++out: ++ error_propagate(errp, local_err); ++} ++ ++static void loongarch_memory_unplug(HotplugHandler *hotplug_dev, ++ DeviceState *dev, Error **errp) ++{ ++ Error *local_err = NULL; ++ HotplugHandlerClass *hhc; ++ LoongarchMachineState *lsms = LoongarchMACHINE(hotplug_dev); ++ ++ hhc = HOTPLUG_HANDLER_GET_CLASS(lsms->acpi_dev); ++ hhc->unplug(HOTPLUG_HANDLER(lsms->acpi_dev), dev, &local_err); ++ ++ if (local_err) { ++ goto out; ++ } ++ ++ pc_dimm_unplug(PC_DIMM(dev), MACHINE(hotplug_dev)); ++ object_unparent(OBJECT(dev)); ++ ++out: ++ error_propagate(errp, local_err); ++} ++ ++static void loongarch_cpu_pre_plug(HotplugHandler *hotplug_dev, ++ DeviceState *dev, Error **errp) ++{ ++ MachineState *ms = MACHINE(OBJECT(hotplug_dev)); ++ MachineClass *mc = MACHINE_GET_CLASS(hotplug_dev); ++ LoongarchMachineState *lsms = LoongarchMACHINE(ms); ++ LOONGARCHCPU *cpu = LOONGARCH_CPU(dev); ++ CPUArchId *cpu_slot; ++ Error *local_err = NULL; ++ int index; ++ int free_index = lsms->hotpluged_cpu_num + ms->smp.cpus; ++ int max_cpus = ms->smp.max_cpus; ++ ++ if (dev->hotplugged && !mc->has_hotpluggable_cpus) { ++ error_setg(&local_err, "CPU hotplug not supported for this machine"); ++ goto out; ++ } ++ ++ if (!object_dynamic_cast(OBJECT(cpu), ms->cpu_type)) { ++ error_setg(errp, "Invalid CPU type, expected cpu type: '%s'", ++ ms->cpu_type); ++ return; ++ } ++ ++ /* if ID is not set, set it based on core properties */ ++ if (cpu->id == UNASSIGNED_CPU_ID) { ++ if ((cpu->core_id) > (max_cpus - 1)) { ++ error_setg(errp, "Invalid CPU core-id: %u must be in range 0:%u", ++ cpu->core_id, max_cpus - 1); ++ return; ++ } ++ ++ if (free_index > (max_cpus - 1)) { ++ error_setg(errp, "The maximum number of CPUs cannot exceed %u.", ++ max_cpus); ++ return; ++ } ++ ++ if (cpu->core_id != free_index) { ++ error_setg(errp, "Invalid CPU core-id: %u must be :%u", ++ cpu->core_id, free_index); ++ return; ++ } ++ ++ cpu->id = cpu->core_id; ++ } ++ ++ cpu_slot = loongarch_find_cpu_slot(MACHINE(hotplug_dev), cpu->id, &index); ++ if (!cpu_slot) { ++ error_setg(&local_err, "core id %d out of range", cpu->id); ++ goto out; ++ } ++ ++ if (cpu_slot->cpu) { ++ error_setg(&local_err, "core %d already populated", cpu->id); ++ goto out; ++ } ++ ++ numa_cpu_pre_plug(cpu_slot, dev, &local_err); ++ ++ return ; ++out: ++ error_propagate(errp, local_err); ++} ++ ++static void loongarch_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, ++ Error **errp) ++{ ++ MachineState *machine = MACHINE(OBJECT(hotplug_dev)); ++ LoongarchMachineState *lsms = LoongarchMACHINE(machine); ++ PCDIMMDevice *dimm = PC_DIMM(dev); ++ Error *local_err = NULL; ++ uint64_t size; ++ ++ if (!lsms->acpi_dev || !loongarch_is_acpi_enabled(lsms)) { ++ error_setg(errp, ++ "memory hotplug is not enabled: missing acpi device or acpi disabled"); ++ return; ++ } ++ ++ size = memory_device_get_region_size(MEMORY_DEVICE(dimm), &local_err); ++ if (local_err) { ++ error_propagate(errp, local_err); ++ return; ++ } ++ ++ if (size % LOONGARCH_HOTPLUG_MEM_ALIGN) { ++ error_setg(errp, "Hotplugged memory size must be a multiple of " ++ "%lld MB", LOONGARCH_HOTPLUG_MEM_ALIGN / MiB); ++ return; ++ } ++ ++ pc_dimm_pre_plug(dimm, MACHINE(hotplug_dev), NULL, errp); ++} ++ ++static void loongarch_cpu_plug(HotplugHandler *hotplug_dev, ++ DeviceState *dev, Error **errp) ++{ ++ CPUArchId *found_cpu; ++ HotplugHandlerClass *hhc; ++ Error *local_err = NULL; ++ MachineState *machine = MACHINE(OBJECT(hotplug_dev)); ++ LoongarchMachineState *lsms = LoongarchMACHINE(machine); ++ LOONGARCHCPU *cpu = LOONGARCH_CPU(dev); ++ ++ if (lsms->acpi_dev) { ++ loongarch_cpu_create(machine, cpu, errp); ++ hhc = HOTPLUG_HANDLER_GET_CLASS(lsms->acpi_dev); ++ hhc->plug(HOTPLUG_HANDLER(lsms->acpi_dev), dev, &local_err); ++ if (local_err) { ++ goto out; ++ } ++ } ++ ++ found_cpu = loongarch_find_cpu_slot(MACHINE(lsms), cpu->id, NULL); ++ found_cpu->cpu = OBJECT(dev); ++ lsms->hotpluged_cpu_num += 1; ++out: ++ error_propagate(errp, local_err); ++} ++ ++static void loongarch_cpu_unplug_request(HotplugHandler *hotplug_dev, ++ DeviceState *dev, Error **errp) ++{ ++ MachineState *machine = MACHINE(OBJECT(hotplug_dev)); ++ LoongarchMachineState *lsms = LoongarchMACHINE(machine); ++ LOONGARCHCPU *cpu = LOONGARCH_CPU(dev); ++ Error *local_err = NULL; ++ HotplugHandlerClass *hhc; ++ int idx = -1; ++ ++ if (!lsms->acpi_dev) { ++ error_setg(&local_err, "CPU hot unplug not supported without ACPI"); ++ goto out; ++ } ++ ++ loongarch_find_cpu_slot(MACHINE(lsms), cpu->id, &idx); ++ assert(idx != -1); ++ if (idx == 0) { ++ error_setg(&local_err, "Boot CPU is unpluggable"); ++ goto out; ++ } ++ ++ hhc = HOTPLUG_HANDLER_GET_CLASS(lsms->acpi_dev); ++ hhc->unplug_request(HOTPLUG_HANDLER(lsms->acpi_dev), dev, &local_err); ++ ++ if (local_err) { ++ goto out; ++ } ++ ++ out: ++ error_propagate(errp, local_err); ++} ++ ++void longson_machine_device_unplug(HotplugHandler *hotplug_dev, ++ DeviceState *dev, Error **errp) ++{ ++ MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine()); ++ ++ if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { ++ loongarch_memory_unplug(hotplug_dev, dev, errp); ++ } else if (object_dynamic_cast(OBJECT(dev), TYPE_LOONGARCH_CPU)) { ++ if (!mc->has_hotpluggable_cpus) { ++ error_setg(errp, "CPU hot unplug not supported on this machine"); ++ return; ++ } ++ loongarch_cpu_unplug(hotplug_dev, dev, errp); ++ } else { ++ error_setg(errp, "acpi: device unplug for not supported device" ++ " type: %s", object_get_typename(OBJECT(dev))); ++ } ++ ++ return; ++} ++ ++void loongarch_machine_device_unplug_request(HotplugHandler *hotplug_dev, ++ DeviceState *dev, Error **errp) ++{ ++ if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { ++ loongarch_memory_unplug_request(hotplug_dev, dev, errp); ++ } else if (object_dynamic_cast(OBJECT(dev), TYPE_LOONGARCH_CPU)) { ++ loongarch_cpu_unplug_request(hotplug_dev, dev, errp); ++ } ++} ++ ++HotplugHandler *loongarch_get_hotpug_handler(MachineState *machine, ++ DeviceState *dev) ++{ ++ if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) || ++ object_dynamic_cast(OBJECT(dev), TYPE_LOONGARCH_CPU)) { ++ return HOTPLUG_HANDLER(machine); ++ } ++ return NULL; ++} ++ ++void loongarch_machine_device_pre_plug(HotplugHandler *hotplug_dev, ++ DeviceState *dev, Error **errp) ++{ ++ if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { ++ loongarch_memory_pre_plug(hotplug_dev, dev, errp); ++ } else if (object_dynamic_cast(OBJECT(dev), TYPE_LOONGARCH_CPU)) { ++ loongarch_cpu_pre_plug(hotplug_dev, dev, errp); ++ } ++} ++ ++void loongarch_machine_device_plug(HotplugHandler *hotplug_dev, ++ DeviceState *dev, Error **errp) ++{ ++ if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { ++ loongarch_memory_plug(hotplug_dev, dev, errp); ++ } else if (object_dynamic_cast(OBJECT(dev), TYPE_LOONGARCH_CPU)) { ++ loongarch_cpu_plug(hotplug_dev, dev, errp); ++ } ++} ++ +diff --git a/hw/loongarch/larch_int.c b/hw/loongarch/larch_int.c +new file mode 100644 +index 0000000000..ca073a19cf +--- /dev/null ++++ b/hw/loongarch/larch_int.c +@@ -0,0 +1,91 @@ ++/* ++ * QEMU LOONGARCH interrupt support ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ++ * THE SOFTWARE. ++ */ ++ ++#include "qemu/osdep.h" ++#include "qemu/main-loop.h" ++#include "hw/hw.h" ++#include "hw/irq.h" ++#include "hw/loongarch/cpudevs.h" ++#include "cpu.h" ++#include "sysemu/kvm.h" ++#include "kvm_larch.h" ++#ifdef CONFIG_KVM ++#include ++#endif ++ ++static void cpu_irq_request(void *opaque, int irq, int level) ++{ ++ LOONGARCHCPU *cpu = opaque; ++ CPULOONGARCHState *env = &cpu->env; ++ CPUState *cs = CPU(cpu); ++ bool locked = false; ++ ++ if (irq < 0 || irq > 13) { ++ return; ++ } ++ ++ /* Make sure locking works even if BQL is already held by the caller */ ++ if (!qemu_mutex_iothread_locked()) { ++ locked = true; ++ qemu_mutex_lock_iothread(); ++ } ++ ++ if (level) { ++ env->CSR_ESTAT |= 1 << irq; ++ } else { ++ env->CSR_ESTAT &= ~(1 << irq); ++ } ++ ++ if (kvm_enabled()) { ++ if (irq == 2) { ++ kvm_loongarch_set_interrupt(cpu, irq, level); ++ } else if (irq == 3) { ++ kvm_loongarch_set_interrupt(cpu, irq, level); ++ } else if (irq == 12) { ++ kvm_loongarch_set_ipi_interrupt(cpu, irq, level); ++ } ++ } ++ ++ if (env->CSR_ESTAT & CSR_ESTAT_IPMASK) { ++ cpu_interrupt(cs, CPU_INTERRUPT_HARD); ++ } else { ++ cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD); ++ } ++ ++ if (locked) { ++ qemu_mutex_unlock_iothread(); ++ } ++} ++ ++void cpu_init_irq(LOONGARCHCPU *cpu) ++{ ++ CPULOONGARCHState *env = &cpu->env; ++ qemu_irq *qi; ++ int i; ++ ++ qi = qemu_allocate_irqs(cpu_irq_request, loongarch_env_get_cpu(env), N_IRQS); ++ for (i = 0; i < N_IRQS; i++) { ++ env->irq[i] = qi[i]; ++ } ++} ++ ++ +diff --git a/hw/loongarch/ls7a_nb.c b/hw/loongarch/ls7a_nb.c +new file mode 100644 +index 0000000000..5a500fbd5a +--- /dev/null ++++ b/hw/loongarch/ls7a_nb.c +@@ -0,0 +1,352 @@ ++/* ++ * Loongarch 7A1000 north bridge support ++ * ++ * Copyright (c) 2019 Loongarch Technology ++ * Authors: ++ * Zhu Chen ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ++ * THE SOFTWARE. ++ */ ++ ++#include "qemu/osdep.h" ++ ++#include "hw/hw.h" ++#include "hw/irq.h" ++#include "hw/sysbus.h" ++#include "hw/pci/pci.h" ++#include "hw/i386/pc.h" ++#include "hw/pci/pci_host.h" ++#include "hw/pci/pcie_host.h" ++#include "sysemu/sysemu.h" ++#include "exec/address-spaces.h" ++#include "qapi/error.h" ++#include "hw/loongarch/cpudevs.h" ++#include "hw/acpi/ls7a.h" ++#include "hw/i386/pc.h" ++#include "hw/isa/isa.h" ++#include "hw/boards.h" ++#include "qemu/log.h" ++#include "hw/loongarch/bios.h" ++#include "hw/loader.h" ++#include "elf.h" ++#include "exec/address-spaces.h" ++#include "exec/memory.h" ++#include "hw/pci/pci_bridge.h" ++#include "hw/pci/pci_bus.h" ++#include "linux/kvm.h" ++#include "sysemu/kvm.h" ++#include "sysemu/runstate.h" ++#include "sysemu/reset.h" ++#include "migration/vmstate.h" ++#include "hw/loongarch/larch.h" ++#include "hw/loongarch/ls7a.h" ++ ++#undef DEBUG_LS7A ++ ++#ifdef DEBUG_LS7A ++#define DPRINTF(fmt, ...) fprintf(stderr, "%s: " fmt, __func__, ##__VA_ARGS__) ++#else ++#define DPRINTF(fmt, ...) ++#endif ++ ++static void ls7a_reset(void *opaque) ++{ ++ uint64_t wmask; ++ wmask = ~(-1); ++ ++ PCIDevice *dev = opaque; ++ pci_set_word(dev->config + PCI_VENDOR_ID, 0x0014); ++ pci_set_word(dev->wmask + PCI_VENDOR_ID, wmask & 0xffff); ++ pci_set_word(dev->cmask + PCI_VENDOR_ID, 0xffff); ++ pci_set_word(dev->config + PCI_DEVICE_ID, 0x7a00); ++ pci_set_word(dev->wmask + PCI_DEVICE_ID, wmask & 0xffff); ++ pci_set_word(dev->cmask + PCI_DEVICE_ID, 0xffff); ++ pci_set_word(dev->config + 0x4, 0x0000); ++ pci_set_word(dev->config + PCI_STATUS, 0x0010); ++ pci_set_word(dev->wmask + PCI_STATUS, wmask & 0xffff); ++ pci_set_word(dev->cmask + PCI_STATUS, 0xffff); ++ pci_set_byte(dev->config + PCI_REVISION_ID, 0x0); ++ pci_set_byte(dev->wmask + PCI_REVISION_ID, wmask & 0xff); ++ pci_set_byte(dev->cmask + PCI_REVISION_ID, 0xff); ++ pci_set_byte(dev->config + 0x9, 0x00); ++ pci_set_byte(dev->wmask + 0x9, wmask & 0xff); ++ pci_set_byte(dev->cmask + 0x9, 0xff); ++ pci_set_byte(dev->config + 0xa, 0x00); ++ pci_set_byte(dev->wmask + 0xa, wmask & 0xff); ++ pci_set_byte(dev->cmask + 0xa, 0xff); ++ pci_set_byte(dev->config + 0xb, 0x06); ++ pci_set_byte(dev->wmask + 0xb, wmask & 0xff); ++ pci_set_byte(dev->cmask + 0xb, 0xff); ++ pci_set_byte(dev->config + 0xc, 0x00); ++ pci_set_byte(dev->wmask + 0xc, wmask & 0xff); ++ pci_set_byte(dev->cmask + 0xc, 0xff); ++ pci_set_byte(dev->config + 0xe, 0x80); ++ pci_set_byte(dev->wmask + 0xe, wmask & 0xff); ++ pci_set_byte(dev->cmask + 0xe, 0xff); ++} ++ ++static const VMStateDescription vmstate_ls7a_pcie = { ++ .name = "LS7A_PCIE", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .fields = (VMStateField[]) { ++ VMSTATE_PCI_DEVICE(dev, LS7APCIState), ++ VMSTATE_STRUCT(pm, LS7APCIState, 0, vmstate_ls7a_pm, LS7APCIPMRegs), ++ VMSTATE_UINT32_ARRAY(regs, LS7APCIState, LS7A_REGS), ++ VMSTATE_END_OF_LIST() ++ } ++}; ++ ++static PCIINTxRoute ls7a_route_intx_pin_to_irq(void *opaque, int pin) ++{ ++ PCIINTxRoute route; ++ ++ route.irq = pin; ++ route.mode = PCI_INTX_ENABLED; ++ return route; ++} ++ ++static int pci_ls7a_map_irq(PCIDevice *d, int irq_num) ++{ ++ int irq; ++ ++ irq = 16 + ((PCI_SLOT(d->devfn) * 4 + irq_num) & 0xf); ++ return irq; ++} ++ ++static void pci_ls7a_set_irq(void *opaque, int irq_num, int level) ++{ ++ qemu_irq *pic = opaque; ++ DPRINTF("------ %s irq %d %d\n", __func__, irq_num, level); ++ qemu_set_irq(pic[irq_num], level); ++} ++ ++/* ++static int ls7a_pciehost_initfn(SysBusDevice *dev) ++{ ++ return 0; ++}*/ ++ ++static void ls7a_pcie_realize(PCIDevice *dev, Error **errp) ++{ ++ LS7APCIState *s = PCIE_LS7A(dev); ++ /* Ls7a North Bridge, built on FPGA, VENDOR_ID/DEVICE_ID are "undefined" */ ++ pci_config_set_prog_interface(dev->config, 0x00); ++ ++ /* set the default value of north bridge pci config */ ++ qemu_register_reset(ls7a_reset, s); ++} ++ ++static void pci_ls7a_config_write(void *opaque, hwaddr addr, ++ uint64_t val, unsigned size) ++{ ++ hwaddr tmp_addr; ++ tmp_addr = addr & 0xffffff; ++ ++ pci_data_write(opaque, tmp_addr, val, size); ++} ++ ++static uint64_t pci_ls7a_config_read(void *opaque, ++ hwaddr addr, unsigned size) ++{ ++ uint64_t val; ++ hwaddr tmp_addr; ++ ++ tmp_addr = addr & 0xffffff; ++ val = pci_data_read(opaque, tmp_addr, size); ++ ++ if (addr & 0x3c) { ++ DPRINTF(TARGET_FMT_plx" val %lx\n", addr, val); ++ } ++ return val; ++} ++ ++static const MemoryRegionOps pci_ls7a_config_ops = { ++ .read = pci_ls7a_config_read, ++ .write = pci_ls7a_config_write, ++ /* Set to access 64bits data, because default to 32bits*/ ++ .valid = { ++ .min_access_size = 1, ++ .max_access_size = 4, ++ }, ++ /* Set to access 64bits data, because default to 32bits*/ ++ .impl = { ++ .min_access_size = 1, ++ .max_access_size = 4, ++ }, ++ .endianness = DEVICE_NATIVE_ENDIAN, ++ ++}; ++ ++static AddressSpace *ls7a_pci_dma_iommu(PCIBus *bus, void *opaque, int devfn) ++{ ++ return &address_space_memory; ++} ++ ++static PCIBus *pci_ls7a_init(MachineState *machine, DeviceState *dev, ++ qemu_irq *pic) ++{ ++ LoongarchMachineState *lsms = LoongarchMACHINE(machine); ++ LoongarchMachineClass *lsmc = LoongarchMACHINE_GET_CLASS(lsms); ++ PCIExpressHost *e; ++ SysBusDevice *sysbus; ++ MemoryRegion *iomem = g_new(MemoryRegion, 1); ++ PCIHostState *phb; ++ ++ e = PCIE_HOST_BRIDGE(dev); ++ sysbus = SYS_BUS_DEVICE(e); ++ phb = PCI_HOST_BRIDGE(e); ++ phb->bus = pci_register_root_bus(dev, "pcie.0", pci_ls7a_set_irq, ++ pci_ls7a_map_irq, pic, ++ get_system_memory(), get_system_io(), ++ (1 << 3), 128, TYPE_PCIE_BUS); ++ pcie_host_mmcfg_update(e, true, lsmc->pciecfg_base, LS_PCIECFG_SIZE); ++ DPRINTF("------ %d\n", __LINE__); ++ ++ pci_bus_set_route_irq_fn(phb->bus, ls7a_route_intx_pin_to_irq); ++ memory_region_init_io(iomem, NULL, &pci_ls7a_config_ops, phb->bus, ++ "ls7a_pci_conf", HT1LO_PCICFG_SIZE); ++ sysbus_init_mmio(sysbus, iomem); ++ sysbus_mmio_map(sysbus, 0, lsmc->ht1lo_pcicfg_base); ++ ++ return phb->bus; ++} ++ ++PCIBus *ls7a_init(MachineState *machine, qemu_irq *pic, DeviceState **ls7a_dev) ++{ ++ DeviceState *dev; ++ PCIHostState *phb; ++ LS7APCIState *pbs; ++ PCIDevice *pcid; ++ PCIBus *pci_bus; ++ PCIExpressHost *e; ++ ++ /*1. init the HT PCI CFG*/ ++ DPRINTF("------ %d\n", __LINE__); ++ dev = qdev_new(TYPE_LS7A_PCIE_HOST_BRIDGE); ++ e = PCIE_HOST_BRIDGE(dev); ++ phb = PCI_HOST_BRIDGE(e); ++ ++ DPRINTF("------ %d\n", __LINE__); ++ pci_bus = pci_ls7a_init(machine, dev, pic); ++ sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); ++ phb->bus = pci_bus; ++ /* set the pcihost pointer after rs780_pcihost_initfn is called */ ++ DPRINTF("------ %d\n", __LINE__); ++ pcid = pci_new(PCI_DEVFN(0, 0), TYPE_PCIE_LS7A); ++ pbs = PCIE_LS7A(pcid); ++ pbs->pciehost = LS7A_PCIE_HOST_BRIDGE(dev); ++ pbs->pciehost->pci_dev = pbs; ++ ++ if (ls7a_dev) { ++ *ls7a_dev = DEVICE(pcid); ++ } ++ ++ pci_realize_and_unref(pcid, phb->bus, &error_fatal); ++ ++ /* IOMMU */ ++ pci_setup_iommu(phb->bus, ls7a_pci_dma_iommu, NULL); ++ ++ ls7a_pm_init(&pbs->pm, pic); ++ DPRINTF("------ %d\n", __LINE__); ++ /*3. init the north bridge VGA,not do now*/ ++ return pci_bus; ++} ++ ++LS7APCIState *get_ls7a_type(Object *obj) ++{ ++ LS7APCIState *pbs; ++ ++ pbs = PCIE_LS7A(obj); ++ return pbs; ++} ++ ++static void ls7a_pcie_class_init(ObjectClass *klass, void *data) ++{ ++ DeviceClass *dc = DEVICE_CLASS(klass); ++ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); ++ HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass); ++ AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_CLASS(klass); ++ ++ k->realize = ls7a_pcie_realize; ++ k->vendor_id = 0x0014; ++ k->device_id = 0x7a00; ++ k->revision = 0x00; ++ k->class_id = PCI_CLASS_BRIDGE_HOST; ++ dc->desc = "LS7A1000 PCIE Host bridge"; ++ dc->vmsd = &vmstate_ls7a_pcie; ++ /* ++ * PCI-facing part of the host bridge, not usable without the ++ * host-facing part, which can't be device_add'ed, yet. ++ */ ++ dc->user_creatable = false; ++ hc->plug = ls7a_pm_device_plug_cb; ++ hc->unplug_request = ls7a_pm_device_unplug_request_cb; ++ hc->unplug = ls7a_pm_device_unplug_cb; ++ adevc->ospm_status = ls7a_pm_ospm_status; ++ adevc->send_event = ls7a_send_gpe; ++ adevc->madt_cpu = ls7a_madt_cpu_entry; ++} ++ ++static void ls7a_pci_add_properties(LS7APCIState *ls7a) ++{ ++ ls7a_pm_add_properties(OBJECT(ls7a), &ls7a->pm, NULL); ++} ++ ++static void ls7a_pci_initfn(Object *obj) ++{ ++ LS7APCIState *ls7a = get_ls7a_type(obj); ++ ++ ls7a_pci_add_properties(ls7a); ++} ++ ++static const TypeInfo ls7a_pcie_device_info = { ++ .name = TYPE_PCIE_LS7A, ++ .parent = TYPE_PCI_DEVICE, ++ .instance_size = sizeof(LS7APCIState), ++ .class_init = ls7a_pcie_class_init, ++ .instance_init = ls7a_pci_initfn, ++ .interfaces = (InterfaceInfo[]) { ++ { TYPE_HOTPLUG_HANDLER }, ++ { TYPE_ACPI_DEVICE_IF }, ++ { INTERFACE_CONVENTIONAL_PCI_DEVICE }, ++ { }, ++ }, ++}; ++ ++static void ls7a_pciehost_class_init(ObjectClass *klass, void *data) ++{ ++ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); ++ k->parent_class.fw_name = "pci"; ++} ++ ++static const TypeInfo ls7a_pciehost_info = { ++ .name = TYPE_LS7A_PCIE_HOST_BRIDGE, ++ .parent = TYPE_PCIE_HOST_BRIDGE, ++ .instance_size = sizeof(LS7APCIEHost), ++ .class_init = ls7a_pciehost_class_init, ++}; ++ ++static void ls7a_register_types(void) ++{ ++ type_register_static(&ls7a_pciehost_info); ++ type_register_static(&ls7a_pcie_device_info); ++} ++ ++type_init(ls7a_register_types) +diff --git a/hw/loongarch/meson.build b/hw/loongarch/meson.build +new file mode 100644 +index 0000000000..81ee99a028 +--- /dev/null ++++ b/hw/loongarch/meson.build +@@ -0,0 +1,15 @@ ++loongarch_ss = ss.source_set() ++loongarch_ss.add(files('larch_3a.c'), fdt) ++loongarch_ss.add(files( ++ 'larch_int.c', ++ 'larch_hotplug.c', ++ 'ls7a_nb.c', ++ 'ioapic.c', ++ 'acpi-build.c', ++ 'ipi.c', ++ 'apic.c', ++ 'iocsr.c', ++)) ++ ++hw_arch += {'loongarch64': loongarch_ss} ++ +diff --git a/include/hw/loongarch/bios.h b/include/hw/loongarch/bios.h +new file mode 100644 +index 0000000000..3677303bfa +--- /dev/null ++++ b/include/hw/loongarch/bios.h +@@ -0,0 +1,5 @@ ++#include "qemu/units.h" ++#include "cpu.h" ++ ++#define BIOS_SIZE (4 * MiB) ++#define BIOS_FILENAME "loongarch_bios.bin" +diff --git a/include/hw/loongarch/cpudevs.h b/include/hw/loongarch/cpudevs.h +new file mode 100644 +index 0000000000..c05ae7a7fc +--- /dev/null ++++ b/include/hw/loongarch/cpudevs.h +@@ -0,0 +1,53 @@ ++#ifndef HW_LOONGARCH_CPUDEVS_H ++#define HW_LOONGARCH_CPUDEVS_H ++ ++#include "target/loongarch64/cpu-qom.h" ++ ++/* Definitions for LOONGARCH CPU internal devices. */ ++#define MAX_GIPI_CORE_NUM 256 ++#define MAX_GIPI_MBX_NUM 4 ++ ++#define LS3A_INTC_IP 8 ++#define MAX_CORES 256 ++#define EXTIOI_IRQS (256) ++#define EXTIOI_IRQS_BITMAP_SIZE (256 / 8) ++/* map to ipnum per 32 irqs */ ++#define EXTIOI_IRQS_IPMAP_SIZE (256 / 32) ++ ++typedef struct gipi_core { ++ uint32_t status; ++ uint32_t en; ++ uint32_t set; ++ uint32_t clear; ++ uint64_t buf[MAX_GIPI_MBX_NUM]; ++ qemu_irq irq; ++} gipi_core; ++ ++typedef struct gipiState { ++ gipi_core core[MAX_GIPI_CORE_NUM]; ++} gipiState; ++ ++typedef struct apicState { ++ /* hardware state */ ++ uint8_t ext_en[EXTIOI_IRQS_BITMAP_SIZE]; ++ uint8_t ext_bounce[EXTIOI_IRQS_BITMAP_SIZE]; ++ uint8_t ext_isr[EXTIOI_IRQS_BITMAP_SIZE]; ++ uint8_t ext_coreisr[MAX_CORES][EXTIOI_IRQS_BITMAP_SIZE]; ++ uint8_t ext_ipmap[EXTIOI_IRQS_IPMAP_SIZE]; ++ uint8_t ext_coremap[EXTIOI_IRQS]; ++ uint16_t ext_nodetype[16]; ++ uint64_t ext_control; ++ ++ /* software state */ ++ uint8_t ext_sw_ipmap[EXTIOI_IRQS]; ++ uint8_t ext_sw_coremap[EXTIOI_IRQS]; ++ uint8_t ext_ipisr[MAX_CORES * LS3A_INTC_IP][EXTIOI_IRQS_BITMAP_SIZE]; ++ ++ qemu_irq parent_irq[MAX_CORES][LS3A_INTC_IP]; ++ qemu_irq *irq; ++} apicState; ++ ++void cpu_init_irq(LOONGARCHCPU *cpu); ++void cpu_loongarch_clock_init(LOONGARCHCPU *cpu); ++ ++#endif +diff --git a/include/hw/loongarch/larch.h b/include/hw/loongarch/larch.h +new file mode 100644 +index 0000000000..0886ed52af +--- /dev/null ++++ b/include/hw/loongarch/larch.h +@@ -0,0 +1,163 @@ ++/* ++ * Hotplug emulation on Loongarch system. ++ * ++ * Copyright (c) 2018 Loongarch Inc. ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, see . ++ */ ++ ++#ifndef HW_LOONGARCH_H ++#define HW_LOONGARCH_H ++ ++#include "target/loongarch64/cpu.h" ++#include "qemu-common.h" ++#include "exec/memory.h" ++#include "hw/mem/pc-dimm.h" ++#include "hw/hotplug.h" ++#include "hw/boards.h" ++#include "hw/acpi/acpi.h" ++#include "qemu/notify.h" ++#include "qemu/error-report.h" ++#include "qemu/queue.h" ++#include "hw/acpi/memory_hotplug.h" ++#include "hw/loongarch/cpudevs.h" ++#include "hw/block/flash.h" ++ ++#define LOONGARCH_MAX_VCPUS 256 ++#define LOONGARCH_MAX_PFLASH 2 ++/* 256MB alignment for hotplug memory region */ ++#define LOONGARCH_HOTPLUG_MEM_ALIGN (1ULL << 28) ++#define LOONGARCH_MAX_RAM_SLOTS 10 ++ ++/* Memory types: */ ++#define SYSTEM_RAM 1 ++#define SYSTEM_RAM_RESERVED 2 ++#define ACPI_TABLE 3 ++#define ACPI_NVS 4 ++#define SYSTEM_PMEM 5 ++ ++#define MAX_MEM_MAP 128 ++ ++typedef struct LoongarchMachineClass { ++ /*< private >*/ ++ MachineClass parent_class; ++ ++ /* Methods: */ ++ HotplugHandler *(*get_hotplug_handler)(MachineState *machine, ++ DeviceState *dev); ++ ++ bool has_acpi_build; ++ ++ /* save different cpu address*/ ++ uint64_t isa_io_base; ++ uint64_t ht_control_regs_base; ++ uint64_t hpet_mmio_addr; ++ uint64_t smbus_cfg_base; ++ uint64_t ht1lo_pcicfg_base; ++ uint64_t pciecfg_base; ++ uint64_t ls7a_ioapic_reg_base; ++ uint32_t node_shift; ++ char cpu_name[40]; ++ char bridge_name[16]; ++ ++} LoongarchMachineClass; ++ ++typedef struct ResetData { ++ LOONGARCHCPU *cpu; ++ uint64_t vector; ++} ResetData; ++ ++typedef struct LoongarchMachineState { ++ /*< private >*/ ++ MachineState parent_obj; ++ ++ /* */ ++ ram_addr_t hotplug_memory_size; ++ ++ /* State for other subsystems/APIs: */ ++ Notifier machine_done; ++ /* Pointers to devices and objects: */ ++ HotplugHandler *acpi_dev; ++ int ram_slots; ++ ResetData *reset_info[LOONGARCH_MAX_VCPUS]; ++ DeviceState *rtc; ++ gipiState *gipi; ++ apicState *apic; ++ ++ FWCfgState *fw_cfg; ++ bool acpi_build_enabled; ++ bool apic_xrupt_override; ++ CPUArchIdList *possible_cpus; ++ PFlashCFI01 *flash[LOONGARCH_MAX_PFLASH]; ++ void *fdt; ++ int fdt_size; ++ unsigned int hotpluged_cpu_num; ++ OnOffAuto acpi; ++ char *oem_id; ++ char *oem_table_id; ++} LoongarchMachineState; ++ ++#define LOONGARCH_MACHINE_ACPI_DEVICE_PROP "loongarch-acpi-device" ++#define TYPE_LOONGARCH_MACHINE "loongarch-machine" ++ ++#define LoongarchMACHINE(obj) \ ++ OBJECT_CHECK(LoongarchMachineState, (obj), TYPE_LOONGARCH_MACHINE) ++#define LoongarchMACHINE_GET_CLASS(obj) \ ++ OBJECT_GET_CLASS(LoongarchMachineClass, (obj), TYPE_LOONGARCH_MACHINE) ++#define LoongarchMACHINE_CLASS(klass) \ ++ OBJECT_CLASS_CHECK(LoongarchMachineClass, (klass), TYPE_LOONGARCH_MACHINE) ++ ++#define DEFINE_LOONGARCH_MACHINE(suffix, namestr, initfn, optsfn) \ ++ static void loongarch_machine_##suffix##_class_init(ObjectClass *oc, void *data) \ ++ { \ ++ MachineClass *mc = MACHINE_CLASS(oc); \ ++ optsfn(mc); \ ++ mc->init = initfn; \ ++ } \ ++ static const TypeInfo loongarch_machine_type_##suffix = { \ ++ .name = namestr TYPE_MACHINE_SUFFIX, \ ++ .parent = TYPE_LOONGARCH_MACHINE, \ ++ .class_init = loongarch_machine_##suffix##_class_init, \ ++ }; \ ++ static void loongarch_machine_init_##suffix(void) \ ++ { \ ++ type_register(&loongarch_machine_type_##suffix); \ ++ } \ ++ type_init(loongarch_machine_init_##suffix) ++ ++void loongarch_machine_device_unplug_request(HotplugHandler *hotplug_dev, ++ DeviceState *dev, Error **errp); ++void longson_machine_device_unplug(HotplugHandler *hotplug_dev, ++ DeviceState *dev, Error **errp); ++HotplugHandler *loongarch_get_hotpug_handler(MachineState *machine, ++ DeviceState *dev); ++void loongarch_machine_device_pre_plug(HotplugHandler *hotplug_dev, ++ DeviceState *dev, Error **errp); ++void loongarch_machine_device_plug(HotplugHandler *hotplug_dev, ++ DeviceState *dev, Error **errp); ++ ++LOONGARCHCPU *loongarch_cpu_create(MachineState *machine, LOONGARCHCPU *cpu, ++ Error **errp); ++void loongarch_cpu_destroy(MachineState *machine, LOONGARCHCPU *cpu); ++int cpu_init_ipi(LoongarchMachineState *ms, qemu_irq parent, int cpu); ++int cpu_init_apic(LoongarchMachineState *ms, CPULOONGARCHState *env, int cpu); ++int la_memmap_add_entry(uint64_t address, uint64_t length, uint32_t type); ++bool loongarch_is_acpi_enabled(LoongarchMachineState *vms); ++ ++/* acpi-build.c */ ++void ls7a_madt_cpu_entry(AcpiDeviceIf *adev, int uid, ++ const CPUArchIdList *apic_ids, GArray *entry, bool force_enabled); ++void slave_cpu_reset(void *opaque); ++extern uint64_t host_cpufreq; ++#endif +diff --git a/include/hw/loongarch/ls7a.h b/include/hw/loongarch/ls7a.h +new file mode 100644 +index 0000000000..686af763a0 +--- /dev/null ++++ b/include/hw/loongarch/ls7a.h +@@ -0,0 +1,152 @@ ++#ifndef HW_LS7A_H ++#define HW_LS7A_H ++ ++#include "hw/hw.h" ++#include "hw/isa/isa.h" ++#include "hw/sysbus.h" ++#include "hw/isa/apm.h" ++#include "hw/pci/pci.h" ++#include "hw/pci/pcie_host.h" ++#include "hw/pci/pci_bridge.h" ++#include "hw/acpi/acpi.h" ++#include "hw/acpi/ls7a.h" ++#include "hw/pci/pci_bus.h" ++ ++/* LS7A PCH Registers (Misc, Confreg) */ ++#define LS7A_PCH_REG_BASE 0x10000000UL ++#define LS3A5K_LS7A_IOAPIC_REG_BASE (LS7A_PCH_REG_BASE) ++#define LS7A_MISC_REG_BASE (LS7A_PCH_REG_BASE + 0x00080000) ++#define LS7A_ACPI_REG_BASE (LS7A_MISC_REG_BASE + 0x00050000) ++ ++#define LOONGARCH_PCH_IRQ_BASE 64 ++#define LS7A_UART_IRQ (LOONGARCH_PCH_IRQ_BASE + 2) ++#define LS7A_RTC_IRQ (LOONGARCH_PCH_IRQ_BASE + 3) ++#define LS7A_SCI_IRQ (LOONGARCH_PCH_IRQ_BASE + 4) ++#define LS7A_ACPI_IO_BASE 0x800 ++#define LS7A_ACPI_IO_SIZE 0x100 ++#define LS7A_PM_EVT_BLK (0x0C) /* 4 bytes */ ++#define LS7A_PM_CNT_BLK (0x14) /* 2 bytes */ ++#define LS7A_GPE0_STS_REG (0x28) /* 4 bytes */ ++#define LS7A_GPE0_ENA_REG (0x2C) /* 4 bytes */ ++#define LS7A_GPE0_RESET_REG (0x30) /* 4 bytes */ ++#define LS7A_PM_TMR_BLK (0x18) /* 4 bytes */ ++#define LS7A_GPE0_LEN (8) ++#define LS7A_RTC_REG_BASE (LS7A_MISC_REG_BASE + 0x00050100) ++#define LS7A_RTC_LEN (0x100) ++ ++#define ACPI_IO_BASE (LS7A_ACPI_REG_BASE) ++#define ACPI_GPE0_LEN (LS7A_GPE0_LEN) ++#define ACPI_IO_SIZE (LS7A_ACPI_IO_SIZE) ++#define ACPI_SCI_IRQ (LS7A_SCI_IRQ) ++ ++#define LS3A5K_ISA_IO_BASE 0x18000000UL ++#define LS_ISA_MEM_BASE 0x40000000 ++#define LS3A5K_HT1LO_PCICFG_BASE 0x1a000000 ++#define HT1LO_PCICFG_SIZE 0x02000000 ++#define LS_BIOS_BASE 0x1c000000 ++#define LS_BIOS_VAR_BASE 0x1c3a0000 ++#define LS_BIOS_SIZE (4 * 1024 * 1024) ++ ++#define FW_CFG_ADDR 0x1e020000 ++#define LS7A_REG_BASE 0x1FE00000 ++#define LS7A_PCICONFIG_BASE (LS7A_REG_BASE + 0x30) ++#define LS7A_PCICONFIG_SIZE (0x100) ++#define LS7A_INTERNAL_REG_BASE (LS7A_REG_BASE + 0x100) ++#define LS7A_INTERNAL_REG_SIZE (0xE0) ++#define LS7A_REGS (0xE0 >> 2) ++#define LS7A_UART_BASE 0x1fe001e0 ++#define LS7A_UART_LEN 0x8 ++ ++#define LS_FDT_BASE 0x1c400000 ++#define LS_FDT_SIZE 0x100000 ++ ++#define LS_PCIECFG_BASE 0x20000000 ++#define LS_PCIECFG_SIZE 0x08000000 ++#define MSI_ADDR_LOW 0x2FF00000 ++#define MSI_ADDR_HI 0x0 ++ ++#define SMP_GIPI_MAILBOX 0x1f000000ULL ++#define CORE0_STATUS_OFF 0x000 ++#define CORE0_EN_OFF 0x004 ++#define CORE0_SET_OFF 0x008 ++#define CORE0_CLEAR_OFF 0x00c ++#define CORE0_BUF_20 0x020 ++#define CORE0_BUF_28 0x028 ++#define CORE0_BUF_30 0x030 ++#define CORE0_BUF_38 0x038 ++#define CORE0_IPI_SEND 0x040 ++#define CORE0_MAIL_SEND 0x048 ++ ++#define INT_ROUTER_REGS_BASE 0x1fe01400UL ++#define INT_ROUTER_REGS_SIZE 0x100 ++#define INT_ROUTER_REGS_SYS_INT0 0x00 ++#define INT_ROUTER_REGS_SYS_INT1 0x01 ++#define INT_ROUTER_REGS_SYS_INT2 0x02 ++#define INT_ROUTER_REGS_SYS_INT3 0x03 ++#define INT_ROUTER_REGS_PCI_INT0 0x04 ++#define INT_ROUTER_REGS_PCI_INT1 0x05 ++#define INT_ROUTER_REGS_PCI_INT2 0x06 ++#define INT_ROUTER_REGS_PCI_INT3 0x07 ++#define INT_ROUTER_REGS_MATRIX_INT0 0x08 ++#define INT_ROUTER_REGS_MATRIX_INT1 0x09 ++#define INT_ROUTER_REGS_LPC_INT 0x0a ++#define INT_ROUTER_REGS_MC0 0x0b ++#define INT_ROUTER_REGS_MC1 0x0c ++#define INT_ROUTER_REGS_BARRIER 0x0d ++#define INT_ROUTER_REGS_THSENS_INT 0x0e ++#define INT_ROUTER_REGS_PCI_PERR 0x0f ++#define INT_ROUTER_REGS_HT0_INT0 0x10 ++#define INT_ROUTER_REGS_HT0_INT1 0x11 ++#define INT_ROUTER_REGS_HT0_INT2 0x12 ++#define INT_ROUTER_REGS_HT0_INT3 0x13 ++#define INT_ROUTER_REGS_HT0_INT4 0x14 ++#define INT_ROUTER_REGS_HT0_INT5 0x15 ++#define INT_ROUTER_REGS_HT0_INT6 0x16 ++#define INT_ROUTER_REGS_HT0_INT7 0x17 ++#define INT_ROUTER_REGS_HT1_INT0 0x18 ++#define INT_ROUTER_REGS_HT1_INT1 0x19 ++#define INT_ROUTER_REGS_HT1_INT2 0x1a ++#define INT_ROUTER_REGS_HT1_INT3 0x1b ++#define INT_ROUTER_REGS_HT1_INT4 0x1c ++#define INT_ROUTER_REGS_HT1_INT5 0x1d ++#define INT_ROUTER_REGS_HT1_INT6 0x1e ++#define INT_ROUTER_REGS_HT1_INT7 0x1f ++#define INT_ROUTER_REGS_ISR 0x20 ++#define INT_ROUTER_REGS_EN 0x24 ++#define INT_ROUTER_REGS_EN_SET 0x28 ++#define INT_ROUTER_REGS_EN_CLR 0x2c ++#define INT_ROUTER_REGS_EDGE 0x38 ++#define INT_ROUTER_REGS_CORE0_INTISR 0x40 ++#define INT_ROUTER_REGS_CORE1_INTISR 0x48 ++#define INT_ROUTER_REGS_CORE2_INTISR 0x50 ++#define INT_ROUTER_REGS_CORE3_INTISR 0x58 ++ ++typedef struct LS7APCIState LS7APCIState; ++typedef struct LS7APCIEHost { ++ PCIExpressHost parent_obj; ++ LS7APCIState *pci_dev; ++} LS7APCIEHost; ++ ++struct LS7APCIState { ++ PCIDevice dev; ++ ++ LS7APCIEHost *pciehost; ++ uint32_t regs[LS7A_REGS]; ++ ++ /* LS7A registers */ ++ MemoryRegion iomem; ++ LS7APCIPMRegs pm; ++}; ++ ++#define TYPE_LS7A_PCIE_HOST_BRIDGE "ls7a1000-pciehost" ++#define LS7A_PCIE_HOST_BRIDGE(obj) \ ++ OBJECT_CHECK(LS7APCIEHost, (obj), TYPE_LS7A_PCIE_HOST_BRIDGE) ++ ++#define TYPE_PCIE_LS7A "ls7a1000_pcie" ++#define PCIE_LS7A(obj) \ ++ OBJECT_CHECK(LS7APCIState, (obj), TYPE_PCIE_LS7A) ++ ++PCIBus *ls7a_init(MachineState *machine, qemu_irq *irq, DeviceState **ls7a_dev); ++LS7APCIState *get_ls7a_type(Object *obj); ++ ++#endif /* HW_LS7A_H */ +-- +2.27.0 + diff --git a/0004-Add-target-loongarch64.patch b/0004-Add-target-loongarch64.patch new file mode 100644 index 0000000..38e74c2 --- /dev/null +++ b/0004-Add-target-loongarch64.patch @@ -0,0 +1,15918 @@ +From 441bbe9ec5021bf56a929134a71cd85815ec3956 Mon Sep 17 00:00:00 2001 +From: lixianglai +Date: Fri, 19 Aug 2022 23:44:33 -0400 +Subject: [PATCH 4/8] Add target/loongarch64. + +Change-Id: Idd3ed114968c4a1f1be5fe19dc279028775eb89d +Signed-off-by: lixianglai +--- + target/Kconfig | 1 + + target/loongarch64/Kconfig | 2 + + target/loongarch64/arch_dump.c | 175 ++ + target/loongarch64/cpu-csr.h | 869 ++++++++ + target/loongarch64/cpu-param.h | 30 + + target/loongarch64/cpu-qom.h | 54 + + target/loongarch64/cpu.c | 576 +++++ + target/loongarch64/cpu.h | 326 +++ + target/loongarch64/csr_helper.c | 704 ++++++ + target/loongarch64/fpu.c | 28 + + target/loongarch64/fpu_helper.c | 952 ++++++++ + target/loongarch64/fpu_helper.h | 129 ++ + target/loongarch64/gdbstub.c | 109 + + target/loongarch64/helper.c | 727 +++++++ + target/loongarch64/helper.h | 168 ++ + target/loongarch64/insn.decode | 514 +++++ + target/loongarch64/instmap.h | 216 ++ + target/loongarch64/internal.h | 184 ++ + target/loongarch64/kvm.c | 1622 ++++++++++++++ + target/loongarch64/kvm_larch.h | 41 + + target/loongarch64/larch-defs.h | 27 + + target/loongarch64/machine.c | 416 ++++ + target/loongarch64/meson.build | 35 + + target/loongarch64/op_helper.c | 533 +++++ + target/loongarch64/stabletimer.c | 122 ++ + target/loongarch64/tlb_helper.c | 729 +++++++ + target/loongarch64/trace-events | 3 + + target/loongarch64/trans.inc.c | 3472 ++++++++++++++++++++++++++++++ + target/loongarch64/translate.c | 2892 +++++++++++++++++++++++++ + target/meson.build | 1 + + 30 files changed, 15657 insertions(+) + create mode 100644 target/loongarch64/Kconfig + create mode 100644 target/loongarch64/arch_dump.c + create mode 100644 target/loongarch64/cpu-csr.h + create mode 100644 target/loongarch64/cpu-param.h + create mode 100644 target/loongarch64/cpu-qom.h + create mode 100644 target/loongarch64/cpu.c + create mode 100644 target/loongarch64/cpu.h + create mode 100644 target/loongarch64/csr_helper.c + create mode 100644 target/loongarch64/fpu.c + create mode 100644 target/loongarch64/fpu_helper.c + create mode 100644 target/loongarch64/fpu_helper.h + create mode 100644 target/loongarch64/gdbstub.c + create mode 100644 target/loongarch64/helper.c + create mode 100644 target/loongarch64/helper.h + create mode 100644 target/loongarch64/insn.decode + create mode 100644 target/loongarch64/instmap.h + create mode 100644 target/loongarch64/internal.h + create mode 100644 target/loongarch64/kvm.c + create mode 100644 target/loongarch64/kvm_larch.h + create mode 100644 target/loongarch64/larch-defs.h + create mode 100644 target/loongarch64/machine.c + create mode 100644 target/loongarch64/meson.build + create mode 100644 target/loongarch64/op_helper.c + create mode 100644 target/loongarch64/stabletimer.c + create mode 100644 target/loongarch64/tlb_helper.c + create mode 100644 target/loongarch64/trace-events + create mode 100644 target/loongarch64/trans.inc.c + create mode 100644 target/loongarch64/translate.c + +diff --git a/target/Kconfig b/target/Kconfig +index ae7f24fc66..50b46d0487 100644 +--- a/target/Kconfig ++++ b/target/Kconfig +@@ -4,6 +4,7 @@ source avr/Kconfig + source cris/Kconfig + source hppa/Kconfig + source i386/Kconfig ++source loongarch64/Kconfig + source m68k/Kconfig + source microblaze/Kconfig + source mips/Kconfig +diff --git a/target/loongarch64/Kconfig b/target/loongarch64/Kconfig +new file mode 100644 +index 0000000000..46b26b1a85 +--- /dev/null ++++ b/target/loongarch64/Kconfig +@@ -0,0 +1,2 @@ ++config LOONGARCH64 ++ bool +diff --git a/target/loongarch64/arch_dump.c b/target/loongarch64/arch_dump.c +new file mode 100644 +index 0000000000..9fb43b33d2 +--- /dev/null ++++ b/target/loongarch64/arch_dump.c +@@ -0,0 +1,175 @@ ++/* Support for writing ELF notes for RM architectures ++ * ++ * Copyright (C) 2015 Red Hat Inc. ++ * ++ * Author: Andrew Jones ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, see . ++ */ ++ ++#include "qemu/osdep.h" ++#include "cpu.h" ++#include "elf.h" ++#include "sysemu/dump.h" ++#include "internal.h" ++ ++/* struct user_pt_regs from arch/loongarch/include/uapi/asm/ptrace.h */ ++struct loongarch_user_regs { ++ uint64_t gpr[32]; ++ uint64_t lo; ++ uint64_t hi; ++ uint64_t csr_era; ++ uint64_t csr_badvaddr; ++ uint64_t csr_crmd; ++ uint64_t csr_ecfg; ++ uint64_t pad[7]; ++} QEMU_PACKED; ++ ++QEMU_BUILD_BUG_ON(sizeof(struct loongarch_user_regs) != 360); ++ ++/* struct elf_prstatus from include/uapi/linux/elfcore.h */ ++struct loongarch_elf_prstatus { ++ char pad1[32]; /* 32 == offsetof(struct elf_prstatus, pr_pid) */ ++ uint32_t pr_pid; ++ char pad2[76]; /* 76 == offsetof(struct elf_prstatus, pr_reg) - ++ offsetof(struct elf_prstatus, pr_ppid) */ ++ struct loongarch_user_regs pr_reg; ++ uint32_t pr_fpvalid; ++ char pad3[4]; ++} QEMU_PACKED; ++ ++QEMU_BUILD_BUG_ON(sizeof(struct loongarch_elf_prstatus) != 480); ++ ++/* struct user_fpsimd_state from arch/arm64/include/uapi/asm/ptrace.h ++ * ++ * While the vregs member of user_fpsimd_state is of type __uint128_t, ++ * QEMU uses an array of uint64_t, where the high half of the 128-bit ++ * value is always in the 2n+1'th index. Thus we also break the 128- ++ * bit values into two halves in this reproduction of user_fpsimd_state. ++ */ ++ ++struct loongarch_fpu_struct { ++ uint64_t fpr[32]; ++ unsigned int fir; ++ unsigned int fcsr; ++} QEMU_PACKED; ++ ++QEMU_BUILD_BUG_ON(sizeof(struct loongarch_fpu_struct) != 264); ++ ++struct loongarch_note { ++ Elf64_Nhdr hdr; ++ char name[8]; /* align_up(sizeof("CORE"), 4) */ ++ union { ++ struct loongarch_elf_prstatus prstatus; ++ struct loongarch_fpu_struct fpu; ++ }; ++} QEMU_PACKED; ++ ++#define LOONGARCH_NOTE_HEADER_SIZE offsetof(struct loongarch_note, prstatus) ++#define LOONGARCH_PRSTATUS_NOTE_SIZE (LOONGARCH_NOTE_HEADER_SIZE + \ ++ sizeof(struct loongarch_elf_prstatus)) ++#define LOONGARCH_PRFPREG_NOTE_SIZE (LOONGARCH_NOTE_HEADER_SIZE + \ ++ sizeof(struct loongarch_fpu_struct)) ++ ++static void loongarch_note_init(struct loongarch_note *note, DumpState *s, ++ const char *name, Elf64_Word namesz, ++ Elf64_Word type, Elf64_Word descsz) ++{ ++ memset(note, 0, sizeof(*note)); ++ ++ note->hdr.n_namesz = cpu_to_dump32(s, namesz); ++ note->hdr.n_descsz = cpu_to_dump32(s, descsz); ++ note->hdr.n_type = cpu_to_dump32(s, type); ++ ++ memcpy(note->name, name, namesz); ++} ++ ++static int loongarch_write_elf64_fprpreg(WriteCoreDumpFunction f, ++ CPULOONGARCHState *env, int cpuid, ++ DumpState *s) ++{ ++ struct loongarch_note note; ++ int ret, i; ++ ++ loongarch_note_init(¬e, s, "CORE", 5, NT_PRFPREG, sizeof(note.fpu)); ++ ++ note.fpu.fcsr = cpu_to_dump64(s, env->active_fpu.fcsr0); ++ ++ for (i = 0; i < 32; ++i) { ++ note.fpu.fpr[i] = cpu_to_dump64(s, env->active_fpu.fpr[i].fd); ++ } ++ ++ ret = f(¬e, LOONGARCH_PRFPREG_NOTE_SIZE, s); ++ if (ret < 0) { ++ return -1; ++ } ++ ++ return 0; ++} ++ ++int loongarch_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs, ++ int cpuid, void *opaque) ++{ ++ struct loongarch_note note; ++ CPULOONGARCHState *env = &LOONGARCH_CPU(cs)->env; ++ DumpState *s = opaque; ++ int ret, i; ++ ++ loongarch_note_init(¬e, s, "CORE", 5, NT_PRSTATUS, sizeof(note.prstatus)); ++ ++ note.prstatus.pr_pid = cpu_to_dump32(s, cpuid); ++ note.prstatus.pr_fpvalid = cpu_to_dump32(s, 1); ++ ++ for (i = 0; i < 32; ++i) { ++ note.prstatus.pr_reg.gpr[i] = cpu_to_dump64(s, env->active_tc.gpr[i]); ++ } ++ note.prstatus.pr_reg.csr_era = cpu_to_dump64(s, env->CSR_ERA); ++ note.prstatus.pr_reg.csr_badvaddr = cpu_to_dump64(s, env->CSR_BADV); ++ note.prstatus.pr_reg.csr_crmd = cpu_to_dump64(s, env->CSR_CRMD); ++ note.prstatus.pr_reg.csr_ecfg = cpu_to_dump64(s, env->CSR_ECFG); ++ ++ ret = f(¬e, LOONGARCH_PRSTATUS_NOTE_SIZE, s); ++ if (ret < 0) { ++ return -1; ++ } ++ ++ ret = loongarch_write_elf64_fprpreg(f, env, cpuid, s); ++ if (ret < 0) { ++ return -1; ++ } ++ ++ return ret; ++} ++ ++int cpu_get_dump_info(ArchDumpInfo *info, ++ const GuestPhysBlockList *guest_phys_blocks) ++{ ++ info->d_machine = EM_LOONGARCH; ++ info->d_endian = ELFDATA2LSB; ++ info->d_class = ELFCLASS64; ++ ++ return 0; ++} ++ ++ssize_t cpu_get_note_size(int class, int machine, int nr_cpus) ++{ ++ size_t note_size = 0; ++ ++ if (class == ELFCLASS64) { ++ note_size = LOONGARCH_PRSTATUS_NOTE_SIZE + LOONGARCH_PRFPREG_NOTE_SIZE; ++ } ++ ++ return note_size * nr_cpus; ++} ++ +diff --git a/target/loongarch64/cpu-csr.h b/target/loongarch64/cpu-csr.h +new file mode 100644 +index 0000000000..e549bb46b6 +--- /dev/null ++++ b/target/loongarch64/cpu-csr.h +@@ -0,0 +1,869 @@ ++#ifndef _CPU_CSR_H_ ++#define _CPU_CSR_H_ ++ ++/* basic CSR register */ ++#define LOONGARCH_CSR_CRMD 0x0 /* 32 current mode info */ ++#define CSR_CRMD_DACM_SHIFT 7 ++#define CSR_CRMD_DACM_WIDTH 2 ++#define CSR_CRMD_DACM (0x3UL << CSR_CRMD_DACM_SHIFT) ++#define CSR_CRMD_DACF_SHIFT 5 ++#define CSR_CRMD_DACF_WIDTH 2 ++#define CSR_CRMD_DACF (0x3UL << CSR_CRMD_DACF_SHIFT) ++#define CSR_CRMD_PG_SHIFT 4 ++#define CSR_CRMD_PG (0x1UL << CSR_CRMD_PG_SHIFT) ++#define CSR_CRMD_DA_SHIFT 3 ++#define CSR_CRMD_DA (0x1UL << CSR_CRMD_DA_SHIFT) ++#define CSR_CRMD_IE_SHIFT 2 ++#define CSR_CRMD_IE (0x1UL << CSR_CRMD_IE_SHIFT) ++#define CSR_CRMD_PLV_SHIFT 0 ++#define CSR_CRMD_PLV_WIDTH 2 ++#define CSR_CRMD_PLV (0x3UL << CSR_CRMD_PLV_SHIFT) ++ ++#define PLV_USER 3 ++#define PLV_KERN 0 ++#define PLV_MASK 0x3 ++ ++#define LOONGARCH_CSR_PRMD 0x1 /* 32 prev-exception mode info */ ++#define CSR_PRMD_PIE_SHIFT 2 ++#define CSR_PRMD_PIE (0x1UL << CSR_PRMD_PIE_SHIFT) ++#define CSR_PRMD_PPLV_SHIFT 0 ++#define CSR_PRMD_PPLV_WIDTH 2 ++#define CSR_PRMD_PPLV (0x3UL << CSR_PRMD_PPLV_SHIFT) ++ ++#define LOONGARCH_CSR_EUEN 0x2 /* 32 coprocessor enable */ ++#define CSR_EUEN_LBTEN_SHIFT 3 ++#define CSR_EUEN_LBTEN (0x1UL << CSR_EUEN_LBTEN_SHIFT) ++#define CSR_EUEN_LASXEN_SHIFT 2 ++#define CSR_EUEN_LASXEN (0x1UL << CSR_EUEN_LASXEN_SHIFT) ++#define CSR_EUEN_LSXEN_SHIFT 1 ++#define CSR_EUEN_LSXEN (0x1UL << CSR_EUEN_LSXEN_SHIFT) ++#define CSR_EUEN_FPEN_SHIFT 0 ++#define CSR_EUEN_FPEN (0x1UL << CSR_EUEN_FPEN_SHIFT) ++ ++#define LOONGARCH_CSR_MISC 0x3 /* 32 misc config */ ++ ++#define LOONGARCH_CSR_ECFG 0x4 /* 32 exception config */ ++#define CSR_ECFG_VS_SHIFT 16 ++#define CSR_ECFG_VS_WIDTH 3 ++#define CSR_ECFG_VS (0x7UL << CSR_ECFG_VS_SHIFT) ++#define CSR_ECFG_IM_SHIFT 0 ++#define CSR_ECFG_IM_WIDTH 13 ++#define CSR_ECFG_IM (0x1fffUL << CSR_ECFG_IM_SHIFT) ++ ++#define CSR_ECFG_IPMASK 0x00001fff ++ ++#define LOONGARCH_CSR_ESTAT 0x5 /* Exception status */ ++#define CSR_ESTAT_ESUBCODE_SHIFT 22 ++#define CSR_ESTAT_ESUBCODE_WIDTH 9 ++#define CSR_ESTAT_ESUBCODE (0x1ffULL << CSR_ESTAT_ESUBCODE_SHIFT) ++#define CSR_ESTAT_EXC_SH 16 ++#define CSR_ESTAT_EXC_WIDTH 5 ++#define CSR_ESTAT_EXC (0x1fULL << CSR_ESTAT_EXC_SH) ++#define CSR_ESTAT_IS_SHIFT 0 ++#define CSR_ESTAT_IS_WIDTH 15 ++#define CSR_ESTAT_IS (0x7fffULL << CSR_ESTAT_IS_SHIFT) ++ ++#define CSR_ESTAT_IPMASK 0x00001fff ++ ++#define EXCODE_IP 64 ++#define EXCCODE_RSV 0 ++#define EXCCODE_TLBL 1 ++#define EXCCODE_TLBS 2 ++#define EXCCODE_TLBI 3 ++#define EXCCODE_MOD 4 ++#define EXCCODE_TLBRI 5 ++#define EXCCODE_TLBXI 6 ++#define EXCCODE_TLBPE 7 ++#define EXCCODE_ADE 8 ++#define EXCCODE_UNALIGN 9 ++#define EXCCODE_OOB 10 ++#define EXCCODE_SYS 11 ++#define EXCCODE_BP 12 ++#define EXCCODE_RI 13 ++#define EXCCODE_IPE 14 ++#define EXCCODE_FPDIS 15 ++#define EXCCODE_LSXDIS 16 ++#define EXCCODE_LASXDIS 17 ++#define EXCCODE_FPE 18 ++#define EXCCODE_WATCH 19 ++#define EXCCODE_BTDIS 20 ++#define EXCCODE_BTE 21 ++#define EXCCODE_PSI 22 ++#define EXCCODE_HYP 23 ++#define EXCCODE_FC 24 ++#define EXCCODE_SE 25 ++ ++#define LOONGARCH_CSR_ERA 0x6 /* 64 error PC */ ++ ++#define LOONGARCH_CSR_BADV 0x7 /* 64 bad virtual address */ ++ ++#define LOONGARCH_CSR_BADI 0x8 /* 32 bad instruction */ ++ ++#define LOONGARCH_CSR_EEPN 0xc /* 64 exception enter base address */ ++#define LOONGARCH_EEPN_CPUID (0x3ffULL << 0) ++ ++#define CU_FPE 1 ++#define CU_LSXE (1 << 1) ++#define CU_LASXE (1 << 2) ++#define CU_LBTE (1 << 3) ++ ++/* TLB related CSR register : start with TLB if no pagewalk */ ++/* 32 TLB Index, EHINV, PageSize, is_gtlb */ ++#define LOONGARCH_CSR_TLBIDX 0x10 ++#define CSR_TLBIDX_EHINV_SHIFT 31 ++#define CSR_TLBIDX_EHINV (0x1ULL << CSR_TLBIDX_EHINV_SHIFT) ++#define CSR_TLBIDX_PS_SHIFT 24 ++#define CSR_TLBIDX_PS_WIDTH 6 ++#define CSR_TLBIDX_PS (0x3fULL << CSR_TLBIDX_PS_SHIFT) ++#define CSR_TLBIDX_IDX_SHIFT 0 ++#define CSR_TLBIDX_IDX_WIDTH 12 ++#define CSR_TLBIDX_IDX (0xfffULL << CSR_TLBIDX_IDX_SHIFT) ++#define CSR_TLBIDX_SIZEM 0x3f000000 ++#define CSR_TLBIDX_SIZE CSR_TLBIDX_PS_SHIFT ++#define CSR_TLBIDX_IDXM 0xfff ++ ++#define LOONGARCH_CSR_TLBEHI 0x11 /* 64 TLB EntryHi without ASID */ ++ ++#define LOONGARCH_CSR_TLBELO0 0x12 /* 64 TLB EntryLo0 */ ++#define CSR_TLBLO0_RPLV_SHIFT 63 ++#define CSR_TLBLO0_RPLV (0x1ULL << CSR_TLBLO0_RPLV_SHIFT) ++#define CSR_TLBLO0_XI_SHIFT 62 ++#define CSR_TLBLO0_XI (0x1ULL << CSR_TLBLO0_XI_SHIFT) ++#define CSR_TLBLO0_RI_SHIFT 61 ++#define CSR_TLBLO0_RI (0x1ULL << CSR_TLBLO0_RI_SHIFT) ++#define CSR_TLBLO0_PPN_SHIFT 12 ++#define CSR_TLBLO0_PPN_WIDTH 36 /* ignore lower 12bits */ ++#define CSR_TLBLO0_PPN (0xfffffffffULL << CSR_TLBLO0_PPN_SHIFT) ++#define CSR_TLBLO0_GLOBAL_SHIFT 6 ++#define CSR_TLBLO0_GLOBAL (0x1ULL << CSR_TLBLO0_GLOBAL_SHIFT) ++#define CSR_TLBLO0_CCA_SHIFT 4 ++#define CSR_TLBLO0_CCA_WIDTH 2 ++#define CSR_TLBLO0_CCA (0x3ULL << CSR_TLBLO0_CCA_SHIFT) ++#define CSR_TLBLO0_PLV_SHIFT 2 ++#define CSR_TLBLO0_PLV_WIDTH 2 ++#define CSR_TLBLO0_PLV (0x3ULL << CSR_TLBLO0_PLV_SHIFT) ++#define CSR_TLBLO0_WE_SHIFT 1 ++#define CSR_TLBLO0_WE (0x1ULL << CSR_TLBLO0_WE_SHIFT) ++#define CSR_TLBLO0_V_SHIFT 0 ++#define CSR_TLBLO0_V (0x1ULL << CSR_TLBLO0_V_SHIFT) ++ ++#define LOONGARCH_CSR_TLBELO1 0x13 /* 64 TLB EntryLo1 */ ++#define CSR_TLBLO1_RPLV_SHIFT 63 ++#define CSR_TLBLO1_RPLV (0x1ULL << CSR_TLBLO1_RPLV_SHIFT) ++#define CSR_TLBLO1_XI_SHIFT 62 ++#define CSR_TLBLO1_XI (0x1ULL << CSR_TLBLO1_XI_SHIFT) ++#define CSR_TLBLO1_RI_SHIFT 61 ++#define CSR_TLBLO1_RI (0x1ULL << CSR_TLBLO1_RI_SHIFT) ++#define CSR_TLBLO1_PPN_SHIFT 12 ++#define CSR_TLBLO1_PPN_WIDTH 36 /* ignore lower 12bits */ ++#define CSR_TLBLO1_PPN (0xfffffffffULL << CSR_TLBLO1_PPN_SHIFT) ++#define CSR_TLBLO1_GLOBAL_SHIFT 6 ++#define CSR_TLBLO1_GLOBAL (0x1ULL << CSR_TLBLO1_GLOBAL_SHIFT) ++#define CSR_TLBLO1_CCA_SHIFT 4 ++#define CSR_TLBLO1_CCA_WIDTH 2 ++#define CSR_TLBLO1_CCA (0x3ULL << CSR_TLBLO1_CCA_SHIFT) ++#define CSR_TLBLO1_PLV_SHIFT 2 ++#define CSR_TLBLO1_PLV_WIDTH 2 ++#define CSR_TLBLO1_PLV (0x3ULL << CSR_TLBLO1_PLV_SHIFT) ++#define CSR_TLBLO1_WE_SHIFT 1 ++#define CSR_TLBLO1_WE (0x1ULL << CSR_TLBLO1_WE_SHIFT) ++#define CSR_TLBLO1_V_SHIFT 0 ++#define CSR_TLBLO1_V (0x1ULL << CSR_TLBLO1_V_SHIFT) ++ ++#define LOONGARCH_ENTRYLO_RI (1ULL << 61) ++#define LOONGARCH_ENTRYLO_XI (1ULL << 62) ++ ++#define LOONGARCH_CSR_TLBWIRED 0x14 /* 32 TLB wired */ ++#define LOONGARCH_CSR_GTLBC 0x15 /* guest-related TLB */ ++#define CSR_GTLBC_RID_SHIFT 16 ++#define CSR_GTLBC_RID_WIDTH 8 ++#define CSR_GTLBC_RID (0xffULL << CSR_GTLBC_RID_SHIFT) ++#define CSR_GTLBC_TOTI_SHIFT 13 ++#define CSR_GTLBC_TOTI (0x1ULL << CSR_GTLBC_TOTI_SHIFT) ++#define CSR_GTLBC_USERID_SHIFT 12 ++#define CSR_GTLBC_USERID (0x1ULL << CSR_GTLBC_USERID_SHIFT) ++#define CSR_GTLBC_GMTLBSZ_SHIFT 0 ++#define CSR_GTLBC_GMTLBSZ_WIDTH 6 ++#define CSR_GTLBC_GMTLBSZ (0x3fULL << CSR_GTLBC_GVTLBSZ_SHIFT) ++ ++#define LOONGARCH_CSR_TRGP 0x16 /* guest-related TLB */ ++#define CSR_TRGP_RID_SHIFT 16 ++#define CSR_TRGP_RID_WIDTH 8 ++#define CSR_TRGP_RID (0xffULL << CSR_TRGP_RID_SHIFT) ++#define CSR_TRGP_GTLB_SHIFT 0 ++#define CSR_TRGP_GTLB (1 << CSR_TRGP_GTLB_SHIFT) ++ ++#define LOONGARCH_CSR_ASID 0x18 /* 64 ASID */ ++#define CSR_ASID_BIT_SHIFT 16 /* ASIDBits */ ++#define CSR_ASID_BIT_WIDTH 8 ++#define CSR_ASID_BIT (0xffULL << CSR_ASID_BIT_SHIFT) ++#define CSR_ASID_ASID_SHIFT 0 ++#define CSR_ASID_ASID_WIDTH 10 ++#define CSR_ASID_ASID (0x3ffULL << CSR_ASID_ASID_SHIFT) ++ ++/* 64 page table base address when badv[47] = 0 */ ++#define LOONGARCH_CSR_PGDL 0x19 ++/* 64 page table base address when badv[47] = 1 */ ++#define LOONGARCH_CSR_PGDH 0x1a ++ ++#define LOONGARCH_CSR_PGD 0x1b /* 64 page table base */ ++ ++#define LOONGARCH_CSR_PWCTL0 0x1c /* 64 PWCtl0 */ ++#define CSR_PWCTL0_PTEW_SHIFT 30 ++#define CSR_PWCTL0_PTEW_WIDTH 2 ++#define CSR_PWCTL0_PTEW (0x3ULL << CSR_PWCTL0_PTEW_SHIFT) ++#define CSR_PWCTL0_DIR1WIDTH_SHIFT 25 ++#define CSR_PWCTL0_DIR1WIDTH_WIDTH 5 ++#define CSR_PWCTL0_DIR1WIDTH (0x1fULL << CSR_PWCTL0_DIR1WIDTH_SHIFT) ++#define CSR_PWCTL0_DIR1BASE_SHIFT 20 ++#define CSR_PWCTL0_DIR1BASE_WIDTH 5 ++#define CSR_PWCTL0_DIR1BASE (0x1fULL << CSR_PWCTL0_DIR1BASE_SHIFT) ++#define CSR_PWCTL0_DIR0WIDTH_SHIFT 15 ++#define CSR_PWCTL0_DIR0WIDTH_WIDTH 5 ++#define CSR_PWCTL0_DIR0WIDTH (0x1fULL << CSR_PWCTL0_DIR0WIDTH_SHIFT) ++#define CSR_PWCTL0_DIR0BASE_SHIFT 10 ++#define CSR_PWCTL0_DIR0BASE_WIDTH 5 ++#define CSR_PWCTL0_DIR0BASE (0x1fULL << CSR_PWCTL0_DIR0BASE_SHIFT) ++#define CSR_PWCTL0_PTWIDTH_SHIFT 5 ++#define CSR_PWCTL0_PTWIDTH_WIDTH 5 ++#define CSR_PWCTL0_PTWIDTH (0x1fULL << CSR_PWCTL0_PTWIDTH_SHIFT) ++#define CSR_PWCTL0_PTBASE_SHIFT 0 ++#define CSR_PWCTL0_PTBASE_WIDTH 5 ++#define CSR_PWCTL0_PTBASE (0x1fULL << CSR_PWCTL0_PTBASE_SHIFT) ++ ++#define LOONGARCH_CSR_PWCTL1 0x1d /* 64 PWCtl1 */ ++#define CSR_PWCTL1_DIR3WIDTH_SHIFT 18 ++#define CSR_PWCTL1_DIR3WIDTH_WIDTH 5 ++#define CSR_PWCTL1_DIR3WIDTH (0x1fULL << CSR_PWCTL1_DIR3WIDTH_SHIFT) ++#define CSR_PWCTL1_DIR3BASE_SHIFT 12 ++#define CSR_PWCTL1_DIR3BASE_WIDTH 5 ++#define CSR_PWCTL1_DIR3BASE (0x1fULL << CSR_PWCTL0_DIR3BASE_SHIFT) ++#define CSR_PWCTL1_DIR2WIDTH_SHIFT 6 ++#define CSR_PWCTL1_DIR2WIDTH_WIDTH 5 ++#define CSR_PWCTL1_DIR2WIDTH (0x1fULL << CSR_PWCTL1_DIR2WIDTH_SHIFT) ++#define CSR_PWCTL1_DIR2BASE_SHIFT 0 ++#define CSR_PWCTL1_DIR2BASE_WIDTH 5 ++#define CSR_PWCTL1_DIR2BASE (0x1fULL << CSR_PWCTL0_DIR2BASE_SHIFT) ++ ++#define LOONGARCH_CSR_STLBPGSIZE 0x1e /* 64 */ ++#define CSR_STLBPGSIZE_PS_WIDTH 6 ++#define CSR_STLBPGSIZE_PS (0x3f) ++ ++#define LOONGARCH_CSR_RVACFG 0x1f ++#define CSR_RVACFG_RDVA_WIDTH 4 ++#define CSR_RVACFG_RDVA (0xf) ++ ++/* read only CSR register : start with CPU */ ++#define LOONGARCH_CSR_CPUID 0x20 /* 32 CPU core number */ ++#define CSR_CPUID_CID_WIDTH 9 ++#define CSR_CPUID_CID (0x1ff) ++ ++#define LOONGARCH_CSR_PRCFG1 0x21 /* 32 CPU info */ ++#define CSR_CONF1_VSMAX_SHIFT 12 ++#define CSR_CONF1_VSMAX_WIDTH 3 ++#define CSR_CONF1_VSMAX (7ULL << CSR_CONF1_VSMAX_SHIFT) ++/* stable timer bits - 1, 0x2f = 47*/ ++#define CSR_CONF1_TMRBITS_SHIFT 4 ++#define CSR_CONF1_TMRBITS_WIDTH 8 ++#define CSR_CONF1_TMRBITS (0xffULL << CSR_CONF1_TMRBITS_SHIFT) ++#define CSR_CONF1_KSNUM_SHIFT 0 ++#define CSR_CONF1_KSNUM_WIDTH 4 ++#define CSR_CONF1_KSNUM (0x8) ++ ++#define LOONGARCH_CSR_PRCFG2 0x22 ++#define CSR_CONF2_PGMASK_SUPP 0x3ffff000 ++ ++#define LOONGARCH_CSR_PRCFG3 0x23 ++#define CSR_CONF3_STLBIDX_SHIFT 20 ++#define CSR_CONF3_STLBIDX_WIDTH 6 ++#define CSR_CONF3_STLBIDX (0x3fULL << CSR_CONF3_STLBIDX_SHIFT) ++#define CSR_STLB_SETS 256 ++#define CSR_CONF3_STLBWAYS_SHIFT 12 ++#define CSR_CONF3_STLBWAYS_WIDTH 8 ++#define CSR_CONF3_STLBWAYS (0xffULL << CSR_CONF3_STLBWAYS_SHIFT) ++#define CSR_STLBWAYS_SIZE 8 ++#define CSR_CONF3_MTLBSIZE_SHIFT 4 ++#define CSR_CONF3_MTLBSIZE_WIDTH 8 ++#define CSR_CONF3_MTLBSIZE (0xffULL << CSR_CONF3_MTLBSIZE_SHIFT) ++/* mean VTLB 64 index */ ++#define CSR_MTLB_SIZE 64 ++#define CSR_CONF3_TLBORG_SHIFT 0 ++#define CSR_CONF3_TLBORG_WIDTH 4 ++#define CSR_CONF3_TLBORG (0xfULL << CSR_CONF3_TLBORG_SHIFT) ++/* mean use MTLB+STLB */ ++#define TLB_ORG 2 ++ ++/* Kscratch : start with KS */ ++#define LOONGARCH_CSR_KS0 0x30 /* 64 */ ++#define LOONGARCH_CSR_KS1 0x31 /* 64 */ ++#define LOONGARCH_CSR_KS2 0x32 /* 64 */ ++#define LOONGARCH_CSR_KS3 0x33 /* 64 */ ++#define LOONGARCH_CSR_KS4 0x34 /* 64 */ ++#define LOONGARCH_CSR_KS5 0x35 /* 64 */ ++#define LOONGARCH_CSR_KS6 0x36 /* 64 */ ++#define LOONGARCH_CSR_KS7 0x37 /* 64 */ ++#define LOONGARCH_CSR_KS8 0x38 /* 64 */ ++ ++/* timer : start with TM */ ++#define LOONGARCH_CSR_TMID 0x40 /* 32 timer ID */ ++ ++#define LOONGARCH_CSR_TCFG 0x41 /* 64 timer config */ ++#define CSR_TCFG_VAL_SHIFT 2 ++#define CSR_TCFG_VAL_WIDTH 48 ++#define CSR_TCFG_VAL (0x3fffffffffffULL << CSR_TCFG_VAL_SHIFT) ++#define CSR_TCFG_PERIOD_SHIFT 1 ++#define CSR_TCFG_PERIOD (0x1ULL << CSR_TCFG_PERIOD_SHIFT) ++#define CSR_TCFG_EN (0x1) ++ ++#define LOONGARCH_CSR_TVAL 0x42 /* 64 timer ticks remain */ ++ ++#define LOONGARCH_CSR_CNTC 0x43 /* 64 timer offset */ ++ ++#define LOONGARCH_CSR_TINTCLR 0x44 /* 64 timer interrupt clear */ ++#define CSR_TINTCLR_TI_SHIFT 0 ++#define CSR_TINTCLR_TI (1 << CSR_TINTCLR_TI_SHIFT) ++ ++/* guest : start with GST */ ++#define LOONGARCH_CSR_GSTAT 0x50 /* 32 basic guest info */ ++#define CSR_GSTAT_GID_SHIFT 16 ++#define CSR_GSTAT_GID_WIDTH 8 ++#define CSR_GSTAT_GID (0xffULL << CSR_GSTAT_GID_SHIFT) ++#define CSR_GSTAT_GIDBIT_SHIFT 4 ++#define CSR_GSTAT_GIDBIT_WIDTH 6 ++#define CSR_GSTAT_GIDBIT (0x3fULL << CSR_GSTAT_GIDBIT_SHIFT) ++#define CSR_GSTAT_PVM_SHIFT 1 ++#define CSR_GSTAT_PVM (0x1ULL << CSR_GSTAT_PVM_SHIFT) ++#define CSR_GSTAT_VM_SHIFT 0 ++#define CSR_GSTAT_VM (0x1ULL << CSR_GSTAT_VM_SHIFT) ++ ++#define LOONGARCH_CSR_GCFG 0x51 /* 32 guest config */ ++#define CSR_GCFG_GPERF_SHIFT 24 ++#define CSR_GCFG_GPERF_WIDTH 3 ++#define CSR_GCFG_GPERF (0x7ULL << CSR_GCFG_GPERF_SHIFT) ++#define CSR_GCFG_GCI_SHIFT 20 ++#define CSR_GCFG_GCI_WIDTH 2 ++#define CSR_GCFG_GCI (0x3ULL << CSR_GCFG_GCI_SHIFT) ++#define CSR_GCFG_GCI_ALL (0x0ULL << CSR_GCFG_GCI_SHIFT) ++#define CSR_GCFG_GCI_HIT (0x1ULL << CSR_GCFG_GCI_SHIFT) ++#define CSR_GCFG_GCI_SECURE (0x2ULL << CSR_GCFG_GCI_SHIFT) ++#define CSR_GCFG_GCIP_SHIFT 16 ++#define CSR_GCFG_GCIP (0xfULL << CSR_GCFG_GCIP_SHIFT) ++#define CSR_GCFG_GCIP_ALL (0x1ULL << CSR_GCFG_GCIP_SHIFT) ++#define CSR_GCFG_GCIP_HIT (0x1ULL << (CSR_GCFG_GCIP_SHIFT + 1)) ++#define CSR_GCFG_GCIP_SECURE (0x1ULL << (CSR_GCFG_GCIP_SHIFT + 2)) ++#define CSR_GCFG_TORU_SHIFT 15 ++#define CSR_GCFG_TORU (0x1ULL << CSR_GCFG_TORU_SHIFT) ++#define CSR_GCFG_TORUP_SHIFT 14 ++#define CSR_GCFG_TORUP (0x1ULL << CSR_GCFG_TORUP_SHIFT) ++#define CSR_GCFG_TOP_SHIFT 13 ++#define CSR_GCFG_TOP (0x1ULL << CSR_GCFG_TOP_SHIFT) ++#define CSR_GCFG_TOPP_SHIFT 12 ++#define CSR_GCFG_TOPP (0x1ULL << CSR_GCFG_TOPP_SHIFT) ++#define CSR_GCFG_TOE_SHIFT 11 ++#define CSR_GCFG_TOE (0x1ULL << CSR_GCFG_TOE_SHIFT) ++#define CSR_GCFG_TOEP_SHIFT 10 ++#define CSR_GCFG_TOEP (0x1ULL << CSR_GCFG_TOEP_SHIFT) ++#define CSR_GCFG_TIT_SHIFT 9 ++#define CSR_GCFG_TIT (0x1ULL << CSR_GCFG_TIT_SHIFT) ++#define CSR_GCFG_TITP_SHIFT 8 ++#define CSR_GCFG_TITP (0x1ULL << CSR_GCFG_TITP_SHIFT) ++#define CSR_GCFG_SIT_SHIFT 7 ++#define CSR_GCFG_SIT (0x1ULL << CSR_GCFG_SIT_SHIFT) ++#define CSR_GCFG_SITP_SHIFT 6 ++#define CSR_GCFG_SITP (0x1ULL << CSR_GCFG_SITP_SHIFT) ++#define CSR_GCFG_CACTRL_SHIFT 4 ++#define CSR_GCFG_CACTRL_WIDTH 2 ++#define CSR_GCFG_CACTRL (0x3ULL << CSR_GCFG_CACTRL_SHIFT) ++#define CSR_GCFG_CACTRL_GUEST (0x0ULL << CSR_GCFG_CACTRL_SHIFT) ++#define CSR_GCFG_CACTRL_ROOT (0x1ULL << CSR_GCFG_CACTRL_SHIFT) ++#define CSR_GCFG_CACTRL_NEST (0x2ULL << CSR_GCFG_CACTRL_SHIFT) ++#define CSR_GCFG_CCCP_WIDTH 4 ++#define CSR_GCFG_CCCP (0xf) ++#define CSR_GCFG_CCCP_GUEST (0x1ULL << 0) ++#define CSR_GCFG_CCCP_ROOT (0x1ULL << 1) ++#define CSR_GCFG_CCCP_NEST (0x1ULL << 2) ++ ++#define LOONGARCH_CSR_GINTC 0x52 /* 64 guest exception control */ ++#define CSR_GINTC_HC_SHIFT 16 ++#define CSR_GINTC_HC_WIDTH 8 ++#define CSR_GINTC_HC (0xffULL << CSR_GINTC_HC_SHIFT) ++#define CSR_GINTC_PIP_SHIFT 8 ++#define CSR_GINTC_PIP_WIDTH 8 ++#define CSR_GINTC_PIP (0xffULL << CSR_GINTC_PIP_SHIFT) ++#define CSR_GINTC_VIP_SHIFT 0 ++#define CSR_GINTC_VIP_WIDTH 8 ++#define CSR_GINTC_VIP (0xff) ++ ++#define LOONGARCH_CSR_GCNTC 0x53 /* 64 guest timer offset */ ++ ++/* LLBCTL */ ++#define LOONGARCH_CSR_LLBCTL 0x60 /* 32 csr number to be changed */ ++#define CSR_LLBCTL_ROLLB_SHIFT 0 ++#define CSR_LLBCTL_ROLLB (1ULL << CSR_LLBCTL_ROLLB_SHIFT) ++#define CSR_LLBCTL_WCLLB_SHIFT 1 ++#define CSR_LLBCTL_WCLLB (1ULL << CSR_LLBCTL_WCLLB_SHIFT) ++#define CSR_LLBCTL_KLO_SHIFT 2 ++#define CSR_LLBCTL_KLO (1ULL << CSR_LLBCTL_KLO_SHIFT) ++ ++/* implement dependent */ ++#define LOONGARCH_CSR_IMPCTL1 0x80 /* 32 loongarch config */ ++#define CSR_MISPEC_SHIFT 20 ++#define CSR_MISPEC_WIDTH 8 ++#define CSR_MISPEC (0xffULL << CSR_MISPEC_SHIFT) ++#define CSR_SSEN_SHIFT 18 ++#define CSR_SSEN (1ULL << CSR_SSEN_SHIFT) ++#define CSR_SCRAND_SHIFT 17 ++#define CSR_SCRAND (1ULL << CSR_SCRAND_SHIFT) ++#define CSR_LLEXCL_SHIFT 16 ++#define CSR_LLEXCL (1ULL << CSR_LLEXCL_SHIFT) ++#define CSR_DISVC_SHIFT 15 ++#define CSR_DISVC (1ULL << CSR_DISVC_SHIFT) ++#define CSR_VCLRU_SHIFT 14 ++#define CSR_VCLRU (1ULL << CSR_VCLRU_SHIFT) ++#define CSR_DCLRU_SHIFT 13 ++#define CSR_DCLRU (1ULL << CSR_DCLRU_SHIFT) ++#define CSR_FASTLDQ_SHIFT 12 ++#define CSR_FASTLDQ (1ULL << CSR_FASTLDQ_SHIFT) ++#define CSR_USERCAC_SHIFT 11 ++#define CSR_USERCAC (1ULL << CSR_USERCAC_SHIFT) ++#define CSR_ANTI_MISPEC_SHIFT 10 ++#define CSR_ANTI_MISPEC (1ULL << CSR_ANTI_MISPEC_SHIFT) ++#define CSR_ANTI_FLUSHSFB_SHIFT 9 ++#define CSR_ANTI_FLUSHSFB (1ULL << CSR_ANTI_FLUSHSFB_SHIFT) ++#define CSR_STFILL_SHIFT 8 ++#define CSR_STFILL (1ULL << CSR_STFILL_SHIFT) ++#define CSR_LIFEP_SHIFT 7 ++#define CSR_LIFEP (1ULL << CSR_LIFEP_SHIFT) ++#define CSR_LLSYNC_SHIFT 6 ++#define CSR_LLSYNC (1ULL << CSR_LLSYNC_SHIFT) ++#define CSR_BRBTDIS_SHIFT 5 ++#define CSR_BRBTDIS (1ULL << CSR_BRBTDIS_SHIFT) ++#define CSR_RASDIS_SHIFT 4 ++#define CSR_RASDIS (1ULL << CSR_RASDIS_SHIFT) ++#define CSR_STPRE_SHIFT 2 ++#define CSR_STPRE_WIDTH 2 ++#define CSR_STPRE (3ULL << CSR_STPRE_SHIFT) ++#define CSR_INSTPRE_SHIFT 1 ++#define CSR_INSTPRE (1ULL << CSR_INSTPRE_SHIFT) ++#define CSR_DATAPRE_SHIFT 0 ++#define CSR_DATAPRE (1ULL << CSR_DATAPRE_SHIFT) ++ ++#define LOONGARCH_CSR_IMPCTL2 0x81 /* 32 Flush */ ++#define CSR_IMPCTL2_MTLB_SHIFT 0 ++#define CSR_IMPCTL2_MTLB (1ULL << CSR_IMPCTL2_MTLB_SHIFT) ++#define CSR_IMPCTL2_STLB_SHIFT 1 ++#define CSR_IMPCTL2_STLB (1ULL << CSR_IMPCTL2_STLB_SHIFT) ++#define CSR_IMPCTL2_DTLB_SHIFT 2 ++#define CSR_IMPCTL2_DTLB (1ULL << CSR_IMPCTL2_DTLB_SHIFT) ++#define CSR_IMPCTL2_ITLB_SHIFT 3 ++#define CSR_IMPCTL2_ITLB (1ULL << CSR_IMPCTL2_ITLB_SHIFT) ++#define CSR_IMPCTL2_BTAC_SHIFT 4 ++#define CSR_IMPCTL2_BTAC (1ULL << CSR_IMPCTL2_BTAC_SHIFT) ++ ++#define LOONGARCH_FLUSH_VTLB 1 ++#define LOONGARCH_FLUSH_FTLB (1 << 1) ++#define LOONGARCH_FLUSH_DTLB (1 << 2) ++#define LOONGARCH_FLUSH_ITLB (1 << 3) ++#define LOONGARCH_FLUSH_BTAC (1 << 4) ++ ++#define LOONGARCH_CSR_GNMI 0x82 ++ ++/* TLB Refill Only */ ++#define LOONGARCH_CSR_TLBRENT 0x88 /* 64 TLB refill exception address */ ++#define LOONGARCH_CSR_TLBRBADV 0x89 /* 64 TLB refill badvaddr */ ++#define LOONGARCH_CSR_TLBRERA 0x8a /* 64 TLB refill ERA */ ++#define LOONGARCH_CSR_TLBRSAVE 0x8b /* 64 KScratch for TLB refill */ ++#define LOONGARCH_CSR_TLBRELO0 0x8c /* 64 TLB refill entrylo0 */ ++#define LOONGARCH_CSR_TLBRELO1 0x8d /* 64 TLB refill entrylo1 */ ++#define LOONGARCH_CSR_TLBREHI 0x8e /* 64 TLB refill entryhi */ ++#define LOONGARCH_CSR_TLBRPRMD 0x8f /* 64 TLB refill mode info */ ++ ++/* error related */ ++#define LOONGARCH_CSR_ERRCTL 0x90 /* 32 ERRCTL */ ++#define LOONGARCH_CSR_ERRINFO 0x91 ++#define LOONGARCH_CSR_ERRINFO1 0x92 ++#define LOONGARCH_CSR_ERRENT 0x93 /* 64 error exception base */ ++#define LOONGARCH_CSR_ERRERA 0x94 /* 64 error exception PC */ ++#define LOONGARCH_CSR_ERRSAVE 0x95 /* 64 KScratch for error exception */ ++ ++#define LOONGARCH_CSR_CTAG 0x98 /* 64 TagLo + TagHi */ ++ ++/* direct map windows */ ++#define LOONGARCH_CSR_DMWIN0 0x180 /* 64 direct map win0: MEM & IF */ ++#define LOONGARCH_CSR_DMWIN1 0x181 /* 64 direct map win1: MEM & IF */ ++#define LOONGARCH_CSR_DMWIN2 0x182 /* 64 direct map win2: MEM */ ++#define LOONGARCH_CSR_DMWIN3 0x183 /* 64 direct map win3: MEM */ ++#define CSR_DMW_PLV0 0x1 ++#define CSR_DMW_PLV1 0x2 ++#define CSR_DMW_PLV2 0x4 ++#define CSR_DMW_PLV3 0x8 ++#define CSR_DMW_BASE_SH 48 ++#define dmwin_va2pa(va) \ ++ (va & (((unsigned long)1 << CSR_DMW_BASE_SH) - 1)) ++ ++/* performance counter */ ++#define LOONGARCH_CSR_PERFCTRL0 0x200 /* 32 perf event 0 config */ ++#define LOONGARCH_CSR_PERFCNTR0 0x201 /* 64 perf event 0 count value */ ++#define LOONGARCH_CSR_PERFCTRL1 0x202 /* 32 perf event 1 config */ ++#define LOONGARCH_CSR_PERFCNTR1 0x203 /* 64 perf event 1 count value */ ++#define LOONGARCH_CSR_PERFCTRL2 0x204 /* 32 perf event 2 config */ ++#define LOONGARCH_CSR_PERFCNTR2 0x205 /* 64 perf event 2 count value */ ++#define LOONGARCH_CSR_PERFCTRL3 0x206 /* 32 perf event 3 config */ ++#define LOONGARCH_CSR_PERFCNTR3 0x207 /* 64 perf event 3 count value */ ++#define CSR_PERFCTRL_PLV0 (1ULL << 16) ++#define CSR_PERFCTRL_PLV1 (1ULL << 17) ++#define CSR_PERFCTRL_PLV2 (1ULL << 18) ++#define CSR_PERFCTRL_PLV3 (1ULL << 19) ++#define CSR_PERFCTRL_IE (1ULL << 20) ++#define CSR_PERFCTRL_EVENT 0x3ff ++ ++/* debug */ ++#define LOONGARCH_CSR_MWPC 0x300 /* data breakpoint config */ ++#define LOONGARCH_CSR_MWPS 0x301 /* data breakpoint status */ ++ ++#define LOONGARCH_CSR_DB0ADDR 0x310 /* data breakpoint 0 address */ ++#define LOONGARCH_CSR_DB0MASK 0x311 /* data breakpoint 0 mask */ ++#define LOONGARCH_CSR_DB0CTL 0x312 /* data breakpoint 0 control */ ++#define LOONGARCH_CSR_DB0ASID 0x313 /* data breakpoint 0 asid */ ++ ++#define LOONGARCH_CSR_DB1ADDR 0x318 /* data breakpoint 1 address */ ++#define LOONGARCH_CSR_DB1MASK 0x319 /* data breakpoint 1 mask */ ++#define LOONGARCH_CSR_DB1CTL 0x31a /* data breakpoint 1 control */ ++#define LOONGARCH_CSR_DB1ASID 0x31b /* data breakpoint 1 asid */ ++ ++#define LOONGARCH_CSR_DB2ADDR 0x320 /* data breakpoint 2 address */ ++#define LOONGARCH_CSR_DB2MASK 0x321 /* data breakpoint 2 mask */ ++#define LOONGARCH_CSR_DB2CTL 0x322 /* data breakpoint 2 control */ ++#define LOONGARCH_CSR_DB2ASID 0x323 /* data breakpoint 2 asid */ ++ ++#define LOONGARCH_CSR_DB3ADDR 0x328 /* data breakpoint 3 address */ ++#define LOONGARCH_CSR_DB3MASK 0x329 /* data breakpoint 3 mask */ ++#define LOONGARCH_CSR_DB3CTL 0x32a /* data breakpoint 3 control */ ++#define LOONGARCH_CSR_DB3ASID 0x32b /* data breakpoint 3 asid */ ++ ++#define LOONGARCH_CSR_FWPC 0x380 /* instruction breakpoint config */ ++#define LOONGARCH_CSR_FWPS 0x381 /* instruction breakpoint status */ ++ ++#define LOONGARCH_CSR_IB0ADDR 0x390 /* inst breakpoint 0 address */ ++#define LOONGARCH_CSR_IB0MASK 0x391 /* inst breakpoint 0 mask */ ++#define LOONGARCH_CSR_IB0CTL 0x392 /* inst breakpoint 0 control */ ++#define LOONGARCH_CSR_IB0ASID 0x393 /* inst breakpoint 0 asid */ ++#define LOONGARCH_CSR_IB1ADDR 0x398 /* inst breakpoint 1 address */ ++#define LOONGARCH_CSR_IB1MASK 0x399 /* inst breakpoint 1 mask */ ++#define LOONGARCH_CSR_IB1CTL 0x39a /* inst breakpoint 1 control */ ++#define LOONGARCH_CSR_IB1ASID 0x39b /* inst breakpoint 1 asid */ ++ ++#define LOONGARCH_CSR_IB2ADDR 0x3a0 /* inst breakpoint 2 address */ ++#define LOONGARCH_CSR_IB2MASK 0x3a1 /* inst breakpoint 2 mask */ ++#define LOONGARCH_CSR_IB2CTL 0x3a2 /* inst breakpoint 2 control */ ++#define LOONGARCH_CSR_IB2ASID 0x3a3 /* inst breakpoint 2 asid */ ++ ++#define LOONGARCH_CSR_IB3ADDR 0x3a8 /* inst breakpoint 3 address */ ++#define LOONGARCH_CSR_IB3MASK 0x3a9 /* inst breakpoint 3 mask */ ++#define LOONGARCH_CSR_IB3CTL 0x3aa /* inst breakpoint 3 control */ ++#define LOONGARCH_CSR_IB3ASID 0x3ab /* inst breakpoint 3 asid */ ++ ++#define LOONGARCH_CSR_IB4ADDR 0x3b0 /* inst breakpoint 4 address */ ++#define LOONGARCH_CSR_IB4MASK 0x3b1 /* inst breakpoint 4 mask */ ++#define LOONGARCH_CSR_IB4CTL 0x3b2 /* inst breakpoint 4 control */ ++#define LOONGARCH_CSR_IB4ASID 0x3b3 /* inst breakpoint 4 asid */ ++ ++#define LOONGARCH_CSR_IB5ADDR 0x3b8 /* inst breakpoint 5 address */ ++#define LOONGARCH_CSR_IB5MASK 0x3b9 /* inst breakpoint 5 mask */ ++#define LOONGARCH_CSR_IB5CTL 0x3ba /* inst breakpoint 5 control */ ++#define LOONGARCH_CSR_IB5ASID 0x3bb /* inst breakpoint 5 asid */ ++ ++#define LOONGARCH_CSR_IB6ADDR 0x3c0 /* inst breakpoint 6 address */ ++#define LOONGARCH_CSR_IB6MASK 0x3c1 /* inst breakpoint 6 mask */ ++#define LOONGARCH_CSR_IB6CTL 0x3c2 /* inst breakpoint 6 control */ ++#define LOONGARCH_CSR_IB6ASID 0x3c3 /* inst breakpoint 6 asid */ ++ ++#define LOONGARCH_CSR_IB7ADDR 0x3c8 /* inst breakpoint 7 address */ ++#define LOONGARCH_CSR_IB7MASK 0x3c9 /* inst breakpoint 7 mask */ ++#define LOONGARCH_CSR_IB7CTL 0x3ca /* inst breakpoint 7 control */ ++#define LOONGARCH_CSR_IB7ASID 0x3cb /* inst breakpoint 7 asid */ ++ ++#define LOONGARCH_CSR_DEBUG 0x500 /* debug config */ ++#define CSR_DEBUG_DM 0 ++#define CSR_DEBUG_DMVER 1 ++#define CSR_DEBUG_DINT 8 ++#define CSR_DEBUG_DBP 9 ++#define CSR_DEBUG_DIB 10 ++#define CSR_DEBUG_DDB 11 ++ ++#define LOONGARCH_CSR_DERA 0x501 /* debug era */ ++#define LOONGARCH_CSR_DESAVE 0x502 /* debug save */ ++ ++#define LOONGARCH_CSR_PRID 0xc0 /* 32 LOONGARCH CP0 PRID */ ++ ++#define LOONGARCH_CPUCFG0 0x0 ++#define CPUCFG0_3A5000_PRID 0x0014c010 ++ ++#define LOONGARCH_CPUCFG1 0x1 ++#define CPUCFG1_ISGR32 BIT(0) ++#define CPUCFG1_ISGR64 BIT(1) ++#define CPUCFG1_PAGING BIT(2) ++#define CPUCFG1_IOCSR BIT(3) ++#define CPUCFG1_PABITS (47 << 4) ++#define CPUCFG1_VABITS (47 << 12) ++#define CPUCFG1_UAL BIT(20) ++#define CPUCFG1_RI BIT(21) ++#define CPUCFG1_XI BIT(22) ++#define CPUCFG1_RPLV BIT(23) ++#define CPUCFG1_HUGEPG BIT(24) ++#define CPUCFG1_IOCSRBRD BIT(25) ++#define CPUCFG1_MSGINT BIT(26) ++ ++#define LOONGARCH_CPUCFG2 0x2 ++#define CPUCFG2_FP BIT(0) ++#define CPUCFG2_FPSP BIT(1) ++#define CPUCFG2_FPDP BIT(2) ++#define CPUCFG2_FPVERS (0 << 3) ++#define CPUCFG2_LSX BIT(6) ++#define CPUCFG2_LASX BIT(7) ++#define CPUCFG2_COMPLEX BIT(8) ++#define CPUCFG2_CRYPTO BIT(9) ++#define CPUCFG2_LVZP BIT(10) ++#define CPUCFG2_LVZVER (0 << 11) ++#define CPUCFG2_LLFTP BIT(14) ++#define CPUCFG2_LLFTPREV (1 << 15) ++#define CPUCFG2_X86BT BIT(18) ++#define CPUCFG2_ARMBT BIT(19) ++#define CPUCFG2_MIPSBT BIT(20) ++#define CPUCFG2_LSPW BIT(21) ++#define CPUCFG2_LAM BIT(22) ++ ++#define LOONGARCH_CPUCFG3 0x3 ++#define CPUCFG3_CCDMA BIT(0) ++#define CPUCFG3_SFB BIT(1) ++#define CPUCFG3_UCACC BIT(2) ++#define CPUCFG3_LLEXC BIT(3) ++#define CPUCFG3_SCDLY BIT(4) ++#define CPUCFG3_LLDBAR BIT(5) ++#define CPUCFG3_ITLBT BIT(6) ++#define CPUCFG3_ICACHET BIT(7) ++#define CPUCFG3_SPW_LVL (4 << 8) ++#define CPUCFG3_SPW_HG_HF BIT(11) ++#define CPUCFG3_RVA BIT(12) ++#define CPUCFG3_RVAMAX (7 << 13) ++ ++#define LOONGARCH_CPUCFG4 0x4 ++#define CCFREQ_100M 100000000 /* 100M */ ++ ++#define LOONGARCH_CPUCFG5 0x5 ++#define CPUCFG5_CCMUL 1 ++#define CPUCFG5_CCDIV (1 << 16) ++ ++#define LOONGARCH_CPUCFG6 0x6 ++#define CPUCFG6_PMP BIT(0) ++#define CPUCFG6_PAMVER (1 << 1) ++#define CPUCFG6_PMNUM (3 << 4) ++#define CPUCFG6_PMBITS (63 << 8) ++#define CPUCFG6_UPM BIT(14) ++ ++#define LOONGARCH_CPUCFG16 0x10 ++#define CPUCFG16_L1_IUPRE BIT(0) ++#define CPUCFG16_L1_UNIFY BIT(1) ++#define CPUCFG16_L1_DPRE BIT(2) ++#define CPUCFG16_L2_IUPRE BIT(3) ++#define CPUCFG16_L2_IUUNIFY BIT(4) ++#define CPUCFG16_L2_IUPRIV BIT(5) ++#define CPUCFG16_L2_IUINCL BIT(6) ++#define CPUCFG16_L2_DPRE BIT(7) ++#define CPUCFG16_L2_DPRIV BIT(8) ++#define CPUCFG16_L2_DINCL BIT(9) ++#define CPUCFG16_L3_IUPRE BIT(10) ++#define CPUCFG16_L3_IUUNIFY BIT(11) ++#define CPUCFG16_L3_IUPRIV BIT(12) ++#define CPUCFG16_L3_IUINCL BIT(13) ++#define CPUCFG16_L3_DPRE BIT(14) ++#define CPUCFG16_L3_DPRIV BIT(15) ++#define CPUCFG16_L3_DINCL BIT(16) ++ ++#define LOONGARCH_CPUCFG17 0x11 ++#define CPUCFG17_L1I_WAYS_M (3 << 0) ++#define CPUCFG17_L1I_SETS_M (8 << 16) ++#define CPUCFG17_L1I_SIZE_M (6 << 24) ++ ++#define LOONGARCH_CPUCFG18 0x12 ++#define CPUCFG18_L1D_WAYS_M (3 << 0) ++#define CPUCFG18_L1D_SETS_M (8 << 16) ++#define CPUCFG18_L1D_SIZE_M (6 << 24) ++ ++#define LOONGARCH_CPUCFG19 0x13 ++#define CPUCFG19_L2_WAYS_M (0xf << 0) ++#define CPUCFG19_L2_SETS_M (8 << 16) ++#define CPUCFG19_L2_SIZE_M (6 << 24) ++ ++#define LOONGARCH_CPUCFG20 0x14 ++#define CPUCFG20_L3_WAYS_M (0xf << 0) ++#define CPUCFG20_L3_SETS_M (0xe << 16) ++#define CPUCFG20_L3_SIZE_M (0x6 << 24) ++ ++#define LOONGARCH_PAGE_HUGE 0x40 ++#define LOONGARCH_HUGE_GLOBAL 0x1000 ++#define LOONGARCH_HUGE_GLOBAL_SH 12 ++ ++/* All CSR register ++ * ++ * default value in target/loongarch/cpu.c ++ * reset function in target/loongarch/translate.c:cpu_state_reset() ++ * ++ * This macro will be used only twice. ++ * > In target/loongarch/cpu.h:CPULOONGARCHState ++ * > In target/loongarch/internal.h:loongarch_def_t ++ * ++ * helper_function to rd/wr: ++ * > declare in target/loongarch/helper.h ++ * > realize in target/loongarch/op_helper.c ++ * ++ * during translate: ++ * > gen_csr_rdl() ++ * > gen_csr_wrl() ++ * > gen_csr_rdq() ++ * > gen_csr_wrq() ++ */ ++#define CPU_LOONGARCH_CSR \ ++ uint64_t CSR_CRMD; \ ++ uint64_t CSR_PRMD; \ ++ uint64_t CSR_EUEN; \ ++ uint64_t CSR_MISC; \ ++ uint64_t CSR_ECFG; \ ++ uint64_t CSR_ESTAT; \ ++ uint64_t CSR_ERA; \ ++ uint64_t CSR_BADV; \ ++ uint64_t CSR_BADI; \ ++ uint64_t CSR_EEPN; \ ++ uint64_t CSR_TLBIDX; \ ++ uint64_t CSR_TLBEHI; \ ++ uint64_t CSR_TLBELO0; \ ++ uint64_t CSR_TLBELO1; \ ++ uint64_t CSR_TLBWIRED; \ ++ uint64_t CSR_GTLBC; \ ++ uint64_t CSR_TRGP; \ ++ uint64_t CSR_ASID; \ ++ uint64_t CSR_PGDL; \ ++ uint64_t CSR_PGDH; \ ++ uint64_t CSR_PGD; \ ++ uint64_t CSR_PWCTL0; \ ++ uint64_t CSR_PWCTL1; \ ++ uint64_t CSR_STLBPGSIZE; \ ++ uint64_t CSR_RVACFG; \ ++ uint64_t CSR_CPUID; \ ++ uint64_t CSR_PRCFG1; \ ++ uint64_t CSR_PRCFG2; \ ++ uint64_t CSR_PRCFG3; \ ++ uint64_t CSR_KS0; \ ++ uint64_t CSR_KS1; \ ++ uint64_t CSR_KS2; \ ++ uint64_t CSR_KS3; \ ++ uint64_t CSR_KS4; \ ++ uint64_t CSR_KS5; \ ++ uint64_t CSR_KS6; \ ++ uint64_t CSR_KS7; \ ++ uint64_t CSR_KS8; \ ++ uint64_t CSR_TMID; \ ++ uint64_t CSR_TCFG; \ ++ uint64_t CSR_TVAL; \ ++ uint64_t CSR_CNTC; \ ++ uint64_t CSR_TINTCLR; \ ++ uint64_t CSR_GSTAT; \ ++ uint64_t CSR_GCFG; \ ++ uint64_t CSR_GINTC; \ ++ uint64_t CSR_GCNTC; \ ++ uint64_t CSR_LLBCTL; \ ++ uint64_t CSR_IMPCTL1; \ ++ uint64_t CSR_IMPCTL2; \ ++ uint64_t CSR_GNMI; \ ++ uint64_t CSR_TLBRENT; \ ++ uint64_t CSR_TLBRBADV; \ ++ uint64_t CSR_TLBRERA; \ ++ uint64_t CSR_TLBRSAVE; \ ++ uint64_t CSR_TLBRELO0; \ ++ uint64_t CSR_TLBRELO1; \ ++ uint64_t CSR_TLBREHI; \ ++ uint64_t CSR_TLBRPRMD; \ ++ uint64_t CSR_ERRCTL; \ ++ uint64_t CSR_ERRINFO; \ ++ uint64_t CSR_ERRINFO1; \ ++ uint64_t CSR_ERRENT; \ ++ uint64_t CSR_ERRERA; \ ++ uint64_t CSR_ERRSAVE; \ ++ uint64_t CSR_CTAG; \ ++ uint64_t CSR_DMWIN0; \ ++ uint64_t CSR_DMWIN1; \ ++ uint64_t CSR_DMWIN2; \ ++ uint64_t CSR_DMWIN3; \ ++ uint64_t CSR_PERFCTRL0; \ ++ uint64_t CSR_PERFCNTR0; \ ++ uint64_t CSR_PERFCTRL1; \ ++ uint64_t CSR_PERFCNTR1; \ ++ uint64_t CSR_PERFCTRL2; \ ++ uint64_t CSR_PERFCNTR2; \ ++ uint64_t CSR_PERFCTRL3; \ ++ uint64_t CSR_PERFCNTR3; \ ++ uint64_t CSR_MWPC; \ ++ uint64_t CSR_MWPS; \ ++ uint64_t CSR_DB0ADDR; \ ++ uint64_t CSR_DB0MASK; \ ++ uint64_t CSR_DB0CTL; \ ++ uint64_t CSR_DB0ASID; \ ++ uint64_t CSR_DB1ADDR; \ ++ uint64_t CSR_DB1MASK; \ ++ uint64_t CSR_DB1CTL; \ ++ uint64_t CSR_DB1ASID; \ ++ uint64_t CSR_DB2ADDR; \ ++ uint64_t CSR_DB2MASK; \ ++ uint64_t CSR_DB2CTL; \ ++ uint64_t CSR_DB2ASID; \ ++ uint64_t CSR_DB3ADDR; \ ++ uint64_t CSR_DB3MASK; \ ++ uint64_t CSR_DB3CTL; \ ++ uint64_t CSR_DB3ASID; \ ++ uint64_t CSR_FWPC; \ ++ uint64_t CSR_FWPS; \ ++ uint64_t CSR_IB0ADDR; \ ++ uint64_t CSR_IB0MASK; \ ++ uint64_t CSR_IB0CTL; \ ++ uint64_t CSR_IB0ASID; \ ++ uint64_t CSR_IB1ADDR; \ ++ uint64_t CSR_IB1MASK; \ ++ uint64_t CSR_IB1CTL; \ ++ uint64_t CSR_IB1ASID; \ ++ uint64_t CSR_IB2ADDR; \ ++ uint64_t CSR_IB2MASK; \ ++ uint64_t CSR_IB2CTL; \ ++ uint64_t CSR_IB2ASID; \ ++ uint64_t CSR_IB3ADDR; \ ++ uint64_t CSR_IB3MASK; \ ++ uint64_t CSR_IB3CTL; \ ++ uint64_t CSR_IB3ASID; \ ++ uint64_t CSR_IB4ADDR; \ ++ uint64_t CSR_IB4MASK; \ ++ uint64_t CSR_IB4CTL; \ ++ uint64_t CSR_IB4ASID; \ ++ uint64_t CSR_IB5ADDR; \ ++ uint64_t CSR_IB5MASK; \ ++ uint64_t CSR_IB5CTL; \ ++ uint64_t CSR_IB5ASID; \ ++ uint64_t CSR_IB6ADDR; \ ++ uint64_t CSR_IB6MASK; \ ++ uint64_t CSR_IB6CTL; \ ++ uint64_t CSR_IB6ASID; \ ++ uint64_t CSR_IB7ADDR; \ ++ uint64_t CSR_IB7MASK; \ ++ uint64_t CSR_IB7CTL; \ ++ uint64_t CSR_IB7ASID; \ ++ uint64_t CSR_DEBUG; \ ++ uint64_t CSR_DERA; \ ++ uint64_t CSR_DESAVE; \ ++ ++#define LOONGARCH_CSR_32(_R, _S) \ ++ (KVM_REG_LOONGARCH_CSR | KVM_REG_SIZE_U32 | (8 * (_R) + (_S))) ++ ++#define LOONGARCH_CSR_64(_R, _S) \ ++ (KVM_REG_LOONGARCH_CSR | KVM_REG_SIZE_U64 | (8 * (_R) + (_S))) ++ ++#define KVM_IOC_CSRID(id) LOONGARCH_CSR_64(id, 0) ++ ++#endif +diff --git a/target/loongarch64/cpu-param.h b/target/loongarch64/cpu-param.h +new file mode 100644 +index 0000000000..24ca458af0 +--- /dev/null ++++ b/target/loongarch64/cpu-param.h +@@ -0,0 +1,30 @@ ++#ifndef CPU_PARAM_H ++#define CPU_PARAM_H ++ ++/* If we want to use host float regs... */ ++/* #define USE_HOST_FLOAT_REGS */ ++ ++/* Real pages are variable size... */ ++#define TARGET_PAGE_BITS 14 ++ ++#define LOONGARCH_TLB_MAX 2112 ++ ++#define TARGET_LONG_BITS 64 ++#define TARGET_PHYS_ADDR_SPACE_BITS 48 ++#define TARGET_VIRT_ADDR_SPACE_BITS 48 ++ ++/* ++ * bit definitions for insn_flags (ISAs/ASEs flags) ++ * ------------------------------------------------ ++ */ ++#define ISA_LARCH32 0x00000001ULL ++#define ISA_LARCH64 0x00000002ULL ++#define INSN_LOONGARCH 0x00010000ULL ++ ++#define CPU_LARCH32 (ISA_LARCH32) ++#define CPU_LARCH64 (ISA_LARCH32 | ISA_LARCH64) ++ ++#define NB_MMU_MODES 4 ++ ++#endif /* QEMU_LOONGARCH_DEFS_H */ ++ +diff --git a/target/loongarch64/cpu-qom.h b/target/loongarch64/cpu-qom.h +new file mode 100644 +index 0000000000..ee9c1de571 +--- /dev/null ++++ b/target/loongarch64/cpu-qom.h +@@ -0,0 +1,54 @@ ++/* ++ * QEMU LOONGARCH CPU ++ * ++ * Copyright (c) 2012 SUSE LINUX Products GmbH ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, see ++ * ++ */ ++#ifndef QEMU_LOONGARCH_CPU_QOM_H ++#define QEMU_LOONGARCH_CPU_QOM_H ++ ++#include "hw/core/cpu.h" ++ ++#define TYPE_LOONGARCH_CPU "loongarch-cpu" ++ ++#define LOONGARCH_CPU_CLASS(klass) \ ++ OBJECT_CLASS_CHECK(LOONGARCHCPUClass, (klass), TYPE_LOONGARCH_CPU) ++#define LOONGARCH_CPU(obj) \ ++ OBJECT_CHECK(LOONGARCHCPU, (obj), TYPE_LOONGARCH_CPU) ++#define LOONGARCH_CPU_GET_CLASS(obj) \ ++ OBJECT_GET_CLASS(LOONGARCHCPUClass, (obj), TYPE_LOONGARCH_CPU) ++ ++/** ++ * LOONGARCHCPUClass: ++ * @parent_realize: The parent class' realize handler. ++ * @parent_reset: The parent class' reset handler. ++ * ++ * A LOONGARCH CPU model. ++ */ ++typedef struct LOONGARCHCPUClass { ++ /*< private >*/ ++ CPUClass parent_class; ++ /*< public >*/ ++ ++ DeviceRealize parent_realize; ++ DeviceUnrealize parent_unrealize; ++ DeviceReset parent_reset; ++ const struct loongarch_def_t *cpu_def; ++} LOONGARCHCPUClass; ++ ++typedef struct LOONGARCHCPU LOONGARCHCPU; ++ ++#endif +diff --git a/target/loongarch64/cpu.c b/target/loongarch64/cpu.c +new file mode 100644 +index 0000000000..a4535d34a6 +--- /dev/null ++++ b/target/loongarch64/cpu.c +@@ -0,0 +1,576 @@ ++/* ++ * QEMU LOONGARCH CPU ++ * ++ * Copyright (c) 2012 SUSE LINUX Products GmbH ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, see ++ * ++ */ ++ ++#include "qemu/osdep.h" ++#include "qapi/error.h" ++#include "qapi/visitor.h" ++#include "cpu.h" ++#include "internal.h" ++#include "kvm_larch.h" ++#include "qemu-common.h" ++#include "hw/qdev-properties.h" ++#include "sysemu/kvm.h" ++#include "exec/exec-all.h" ++#include "sysemu/arch_init.h" ++#include "cpu-csr.h" ++#include "qemu/qemu-print.h" ++#include "qapi/qapi-commands-machine-target.h" ++#ifdef CONFIG_TCG ++#include "hw/core/tcg-cpu-ops.h" ++#endif /* CONFIG_TCG */ ++ ++#define LOONGARCH_CONFIG1 \ ++((0x8 << CSR_CONF1_KSNUM_SHIFT) | (0x2f << CSR_CONF1_TMRBITS_SHIFT) | \ ++ (0x7 << CSR_CONF1_VSMAX_SHIFT)) ++ ++#define LOONGARCH_CONFIG3 \ ++((0x2 << CSR_CONF3_TLBORG_SHIFT) | (0x3f << CSR_CONF3_MTLBSIZE_SHIFT) | \ ++ (0x7 << CSR_CONF3_STLBWAYS_SHIFT) | (0x8 << CSR_CONF3_STLBIDX_SHIFT)) ++ ++/*****************************************************************************/ ++/* LOONGARCH CPU definitions */ ++const loongarch_def_t loongarch_defs[] = { ++ { ++ .name = "Loongson-3A5000", ++ ++ /* for LoongISA CSR */ ++ .CSR_PRCFG1 = LOONGARCH_CONFIG1, ++ .CSR_PRCFG2 = 0x3ffff000, ++ .CSR_PRCFG3 = LOONGARCH_CONFIG3, ++ .CSR_CRMD = (0 << CSR_CRMD_PLV_SHIFT) | (0 << CSR_CRMD_IE_SHIFT) | ++ (1 << CSR_CRMD_DA_SHIFT) | (0 << CSR_CRMD_PG_SHIFT) | ++ (1 << CSR_CRMD_DACF_SHIFT) | (1 << CSR_CRMD_DACM_SHIFT) , ++ .CSR_ECFG = 0x7 << 16, ++ .CSR_STLBPGSIZE = 0xe, ++ .CSR_RVACFG = 0x0, ++ .CSR_ASID = 0xa0000, ++ .FCSR0 = 0x0, ++ .FCSR0_rw_bitmask = 0x1f1f03df, ++ .PABITS = 48, ++ .insn_flags = CPU_LARCH64 | INSN_LOONGARCH, ++ .mmu_type = MMU_TYPE_LS3A5K, ++ }, ++ { ++ .name = "host", ++ ++ /* for LoongISA CSR */ ++ .CSR_PRCFG1 = LOONGARCH_CONFIG1, ++ .CSR_PRCFG2 = 0x3ffff000, ++ .CSR_PRCFG3 = LOONGARCH_CONFIG3, ++ .CSR_CRMD = (0 << CSR_CRMD_PLV_SHIFT) | (0 << CSR_CRMD_IE_SHIFT) | ++ (1 << CSR_CRMD_DA_SHIFT) | (0 << CSR_CRMD_PG_SHIFT) | ++ (1 << CSR_CRMD_DACF_SHIFT) | (1 << CSR_CRMD_DACM_SHIFT) , ++ .CSR_ECFG = 0x7 << 16, ++ .CSR_STLBPGSIZE = 0xe, ++ .CSR_RVACFG = 0x0, ++ .FCSR0 = 0x0, ++ .FCSR0_rw_bitmask = 0x1f1f03df, ++ .PABITS = 48, ++ .insn_flags = CPU_LARCH64 | INSN_LOONGARCH, ++ .mmu_type = MMU_TYPE_LS3A5K, ++ }, ++}; ++const int loongarch_defs_number = ARRAY_SIZE(loongarch_defs); ++ ++void loongarch_cpu_list(void) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(loongarch_defs); i++) { ++ qemu_printf("LOONGARCH '%s'\n", ++ loongarch_defs[i].name); ++ } ++} ++ ++CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp) ++{ ++ CpuDefinitionInfoList *cpu_list = NULL; ++ const loongarch_def_t *def; ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(loongarch_defs); i++) { ++ CpuDefinitionInfoList *entry; ++ CpuDefinitionInfo *info; ++ ++ def = &loongarch_defs[i]; ++ info = g_malloc0(sizeof(*info)); ++ info->name = g_strdup(def->name); ++ ++ entry = g_malloc0(sizeof(*entry)); ++ entry->value = info; ++ entry->next = cpu_list; ++ cpu_list = entry; ++ } ++ ++ return cpu_list; ++} ++ ++static void loongarch_cpu_set_pc(CPUState *cs, vaddr value) ++{ ++ LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); ++ CPULOONGARCHState *env = &cpu->env; ++ ++ env->active_tc.PC = value & ~(target_ulong)1; ++} ++ ++static bool loongarch_cpu_has_work(CPUState *cs) ++{ ++ LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); ++ CPULOONGARCHState *env = &cpu->env; ++ bool has_work = false; ++ ++ /* It is implementation dependent if non-enabled ++ interrupts wake-up the CPU, however most of the implementations only ++ check for interrupts that can be taken. */ ++ if ((cs->interrupt_request & CPU_INTERRUPT_HARD) && ++ cpu_loongarch_hw_interrupts_pending(env)) { ++ has_work = true; ++ } ++ ++ return has_work; ++} ++ ++const char * const regnames[] = { ++ "r0", "ra", "tp", "sp", "a0", "a1", "a2", "a3", ++ "a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3", ++ "t4", "t5", "t6", "t7", "t8", "x0", "fp", "s0", ++ "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", ++}; ++ ++const char * const fregnames[] = { ++ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", ++ "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", ++ "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", ++ "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", ++}; ++ ++static void fpu_dump_state(CPULOONGARCHState *env, FILE *f, ++ fprintf_function fpu_fprintf, int flags) ++{ ++ int i; ++ int is_fpu64 = 1; ++ ++#define printfpr(fp) \ ++ do { \ ++ if (is_fpu64) \ ++ fpu_fprintf(f, "w:%08x d:%016" PRIx64 \ ++ " fd:%13g fs:%13g psu: %13g\n", \ ++ (fp)->w[FP_ENDIAN_IDX], (fp)->d, \ ++ (double)(fp)->fd, \ ++ (double)(fp)->fs[FP_ENDIAN_IDX], \ ++ (double)(fp)->fs[!FP_ENDIAN_IDX]); \ ++ else { \ ++ fpr_t tmp; \ ++ tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \ ++ tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \ ++ fpu_fprintf(f, "w:%08x d:%016" PRIx64 \ ++ " fd:%13g fs:%13g psu:%13g\n", \ ++ tmp.w[FP_ENDIAN_IDX], tmp.d, \ ++ (double)tmp.fd, \ ++ (double)tmp.fs[FP_ENDIAN_IDX], \ ++ (double)tmp.fs[!FP_ENDIAN_IDX]); \ ++ } \ ++ } while (0) ++ ++ ++ fpu_fprintf(f, "FCSR0 0x%08x SR.FR %d fp_status 0x%02x\n", ++ env->active_fpu.fcsr0, is_fpu64, ++ get_float_exception_flags(&env->active_fpu.fp_status)); ++ for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) { ++ fpu_fprintf(f, "%3s: ", fregnames[i]); ++ printfpr(&env->active_fpu.fpr[i]); ++ } ++ ++#undef printfpr ++} ++ ++void loongarch_cpu_dump_state(CPUState *cs, FILE *f, int flags) ++{ ++ LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); ++ CPULOONGARCHState *env = &cpu->env; ++ int i; ++ ++ qemu_fprintf(f, "pc:\t %lx\n", env->active_tc.PC); ++ for (i = 0; i < 32; i++) { ++ if ((i & 3) == 0) { ++ qemu_fprintf(f, "GPR%02d:", i); ++ } ++ qemu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], ++ env->active_tc.gpr[i]); ++ if ((i & 3) == 3) { ++ qemu_fprintf(f, "\n"); ++ } ++ } ++ qemu_fprintf(f, "EUEN 0x%lx\n", env->CSR_EUEN); ++ qemu_fprintf(f, "ESTAT 0x%lx\n", env->CSR_ESTAT); ++ qemu_fprintf(f, "ERA 0x%lx\n", env->CSR_ERA); ++ qemu_fprintf(f, "CRMD 0x%lx\n", env->CSR_CRMD); ++ qemu_fprintf(f, "PRMD 0x%lx\n", env->CSR_PRMD); ++ qemu_fprintf(f, "BadVAddr 0x%lx\n", env->CSR_BADV); ++ qemu_fprintf(f, "TLB refill ERA 0x%lx\n", env->CSR_TLBRERA); ++ qemu_fprintf(f, "TLB refill BadV 0x%lx\n", env->CSR_TLBRBADV); ++ qemu_fprintf(f, "EEPN 0x%lx\n", env->CSR_EEPN); ++ qemu_fprintf(f, "BadInstr 0x%lx\n", env->CSR_BADI); ++ qemu_fprintf(f, "PRCFG1 0x%lx\nPRCFG2 0x%lx\nPRCFG3 0x%lx\n", ++ env->CSR_PRCFG1, env->CSR_PRCFG3, env->CSR_PRCFG3); ++ if ((flags & CPU_DUMP_FPU) && (env->hflags & LARCH_HFLAG_FPU)) { ++ fpu_dump_state(env, f, qemu_fprintf, flags); ++ } ++} ++ ++void cpu_state_reset(CPULOONGARCHState *env) ++{ ++ LOONGARCHCPU *cpu = loongarch_env_get_cpu(env); ++ CPUState *cs = CPU(cpu); ++ ++ /* Reset registers to their default values */ ++ env->CSR_PRCFG1 = env->cpu_model->CSR_PRCFG1; ++ env->CSR_PRCFG2 = env->cpu_model->CSR_PRCFG2; ++ env->CSR_PRCFG3 = env->cpu_model->CSR_PRCFG3; ++ env->CSR_CRMD = env->cpu_model->CSR_CRMD; ++ env->CSR_ECFG = env->cpu_model->CSR_ECFG; ++ env->CSR_STLBPGSIZE = env->cpu_model->CSR_STLBPGSIZE; ++ env->CSR_RVACFG = env->cpu_model->CSR_RVACFG; ++ env->CSR_ASID = env->cpu_model->CSR_ASID; ++ ++ env->current_tc = 0; ++ env->active_fpu.fcsr0_rw_bitmask = env->cpu_model->FCSR0_rw_bitmask; ++ env->active_fpu.fcsr0 = env->cpu_model->FCSR0; ++ env->insn_flags = env->cpu_model->insn_flags; ++ ++#if !defined(CONFIG_USER_ONLY) ++ env->CSR_ERA = env->active_tc.PC; ++ env->active_tc.PC = env->exception_base; ++#ifdef CONFIG_TCG ++ env->tlb->tlb_in_use = env->tlb->nb_tlb; ++#endif ++ env->CSR_TLBWIRED = 0; ++ env->CSR_TMID = cs->cpu_index; ++ env->CSR_CPUID = (cs->cpu_index & 0x1ff); ++ env->CSR_EEPN |= (uint64_t)0x80000000; ++ env->CSR_TLBRENT |= (uint64_t)0x80000000; ++#endif ++ ++ /* Count register increments in debug mode, EJTAG version 1 */ ++ env->CSR_DEBUG = (1 << CSR_DEBUG_DINT) | (0x1 << CSR_DEBUG_DMVER); ++ ++ compute_hflags(env); ++ restore_fp_status(env); ++ cs->exception_index = EXCP_NONE; ++} ++ ++/* CPUClass::reset() */ ++static void loongarch_cpu_reset(DeviceState *dev) ++{ ++ CPUState *s = CPU(dev); ++ LOONGARCHCPU *cpu = LOONGARCH_CPU(s); ++ LOONGARCHCPUClass *mcc = LOONGARCH_CPU_GET_CLASS(cpu); ++ CPULOONGARCHState *env = &cpu->env; ++ ++ mcc->parent_reset(dev); ++ ++ memset(env, 0, offsetof(CPULOONGARCHState, end_reset_fields)); ++ ++ cpu_state_reset(env); ++ ++#ifndef CONFIG_USER_ONLY ++ if (kvm_enabled()) { ++ kvm_loongarch_reset_vcpu(cpu); ++ } ++#endif ++} ++ ++static void loongarch_cpu_disas_set_info(CPUState *s, disassemble_info *info) ++{ ++ info->print_insn = print_insn_loongarch; ++} ++ ++static void fpu_init(CPULOONGARCHState *env, const loongarch_def_t *def) ++{ ++ memcpy(&env->active_fpu, &env->fpus[0], sizeof(env->active_fpu)); ++} ++ ++void cpu_loongarch_realize_env(CPULOONGARCHState *env) ++{ ++ env->exception_base = 0x1C000000; ++ ++#ifdef CONFIG_TCG ++#ifndef CONFIG_USER_ONLY ++ mmu_init(env, env->cpu_model); ++#endif ++#endif ++ fpu_init(env, env->cpu_model); ++} ++ ++static void loongarch_cpu_realizefn(DeviceState *dev, Error **errp) ++{ ++ CPUState *cs = CPU(dev); ++ LOONGARCHCPU *cpu = LOONGARCH_CPU(dev); ++ LOONGARCHCPUClass *mcc = LOONGARCH_CPU_GET_CLASS(dev); ++ Error *local_err = NULL; ++ ++ cpu_exec_realizefn(cs, &local_err); ++ if (local_err != NULL) { ++ error_propagate(errp, local_err); ++ return; ++ } ++ ++ cpu_loongarch_realize_env(&cpu->env); ++ ++ loongarch_cpu_register_gdb_regs_for_features(cs); ++ ++ cpu_reset(cs); ++ qemu_init_vcpu(cs); ++ ++ mcc->parent_realize(dev, errp); ++ cpu->hotplugged = 1; ++} ++ ++static void loongarch_cpu_unrealizefn(DeviceState *dev) ++{ ++ LOONGARCHCPUClass *mcc = LOONGARCH_CPU_GET_CLASS(dev); ++ ++#ifndef CONFIG_USER_ONLY ++ cpu_remove_sync(CPU(dev)); ++#endif ++ ++ mcc->parent_unrealize(dev); ++} ++static void loongarch_cpu_initfn(Object *obj) ++{ ++ CPUState *cs = CPU(obj); ++ LOONGARCHCPU *cpu = LOONGARCH_CPU(obj); ++ CPULOONGARCHState *env = &cpu->env; ++ LOONGARCHCPUClass *mcc = LOONGARCH_CPU_GET_CLASS(obj); ++ cpu_set_cpustate_pointers(cpu); ++ cs->env_ptr = env; ++ env->cpu_model = mcc->cpu_def; ++ cs->halted = 1; ++ cpu->dtb_compatible = "loongarch,Loongson-3A5000"; ++} ++ ++static char *loongarch_cpu_type_name(const char *cpu_model) ++{ ++ return g_strdup_printf(LOONGARCH_CPU_TYPE_NAME("%s"), cpu_model); ++} ++ ++static ObjectClass *loongarch_cpu_class_by_name(const char *cpu_model) ++{ ++ ObjectClass *oc; ++ char *typename; ++ ++ typename = loongarch_cpu_type_name(cpu_model); ++ oc = object_class_by_name(typename); ++ g_free(typename); ++ return oc; ++} ++ ++static int64_t loongarch_cpu_get_arch_id(CPUState *cs) ++{ ++ LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); ++ ++ return cpu->id; ++} ++ ++static Property loongarch_cpu_properties[] = { ++ DEFINE_PROP_INT32("core-id", LOONGARCHCPU, core_id, -1), ++ DEFINE_PROP_INT32("id", LOONGARCHCPU, id, UNASSIGNED_CPU_ID), ++ DEFINE_PROP_INT32("node-id", LOONGARCHCPU, node_id, CPU_UNSET_NUMA_NODE_ID), ++ ++ DEFINE_PROP_END_OF_LIST() ++}; ++ ++#ifdef CONFIG_TCG ++static void loongarch_cpu_synchronize_from_tb(CPUState *cs,const TranslationBlock *tb) ++{ ++ LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); ++ CPULOONGARCHState *env = &cpu->env; ++ ++ env->active_tc.PC = tb->pc; ++ env->hflags &= ~LARCH_HFLAG_BMASK; ++ env->hflags |= tb->flags & LARCH_HFLAG_BMASK; ++} ++ ++static const struct TCGCPUOps loongarch_tcg_ops = { ++ .initialize = loongarch_tcg_init, ++ .synchronize_from_tb = loongarch_cpu_synchronize_from_tb, ++ ++ .tlb_fill = loongarch_cpu_tlb_fill, ++ .cpu_exec_interrupt = loongarch_cpu_exec_interrupt, ++ .do_interrupt = loongarch_cpu_do_interrupt, ++ ++#ifndef CONFIG_USER_ONLY ++ .do_unaligned_access = loongarch_cpu_do_unaligned_access, ++#endif /* !CONFIG_USER_ONLY */ ++}; ++#endif /* CONFIG_TCG */ ++ ++ ++#if !defined(CONFIG_USER_ONLY) ++static int get_physical_address(CPULOONGARCHState *env, hwaddr *physical, ++ int *prot, target_ulong real_address, ++ int rw, int access_type, int mmu_idx) ++{ ++ int user_mode = mmu_idx == LARCH_HFLAG_UM; ++ int kernel_mode = !user_mode; ++ unsigned plv, base_c, base_v, tmp; ++ ++ /* effective address (modified for KVM T&E kernel segments) */ ++ target_ulong address = real_address; ++ ++ /* Check PG */ ++ if (!(env->CSR_CRMD & CSR_CRMD_PG)) { ++ /* DA mode */ ++ *physical = address & 0xffffffffffffUL; ++ *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; ++ return TLBRET_MATCH; ++ } ++ ++ plv = kernel_mode | (user_mode << 3); ++ base_v = address >> CSR_DMW_BASE_SH; ++ /* Check direct map window 0 */ ++ base_c = env->CSR_DMWIN0 >> CSR_DMW_BASE_SH; ++ if ((plv & env->CSR_DMWIN0) && (base_c == base_v)) { ++ *physical = dmwin_va2pa(address); ++ *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; ++ return TLBRET_MATCH; ++ } ++ /* Check direct map window 1 */ ++ base_c = env->CSR_DMWIN1 >> CSR_DMW_BASE_SH; ++ if ((plv & env->CSR_DMWIN1) && (base_c == base_v)) { ++ *physical = dmwin_va2pa(address); ++ *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; ++ return TLBRET_MATCH; ++ } ++ /* Check valid extension */ ++ tmp = address >> 47; ++ if (!(tmp == 0 || tmp == 0x1ffff)) { ++ return TLBRET_BADADDR; ++ } ++ /* mapped address */ ++ return env->tlb->map_address(env, physical, prot, real_address, rw, ++ access_type); ++} ++ ++hwaddr loongarch_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) ++{ ++ LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); ++ CPULOONGARCHState *env = &cpu->env; ++ hwaddr phys_addr; ++ int prot; ++ ++ if (get_physical_address(env, &phys_addr, &prot, addr, 0, ACCESS_INT, ++ cpu_mmu_index(env, false)) != 0) { ++ return -1; ++ } ++ return phys_addr; ++} ++#endif ++ ++ ++#ifndef CONFIG_USER_ONLY ++#include "hw/core/sysemu-cpu-ops.h" ++ ++static const struct SysemuCPUOps loongarch_sysemu_ops = { ++ .write_elf64_note = loongarch_cpu_write_elf64_note, ++ .get_phys_page_debug = loongarch_cpu_get_phys_page_debug, ++ .legacy_vmsd = &vmstate_loongarch_cpu, ++}; ++#endif ++ ++ ++static void loongarch_cpu_class_init(ObjectClass *c, void *data) ++{ ++ LOONGARCHCPUClass *mcc = LOONGARCH_CPU_CLASS(c); ++ CPUClass *cc = CPU_CLASS(c); ++ DeviceClass *dc = DEVICE_CLASS(c); ++ ++ device_class_set_props(dc, loongarch_cpu_properties); ++ device_class_set_parent_realize(dc, loongarch_cpu_realizefn, ++ &mcc->parent_realize); ++ ++ device_class_set_parent_unrealize(dc, loongarch_cpu_unrealizefn, ++ &mcc->parent_unrealize); ++ ++ device_class_set_parent_reset(dc, loongarch_cpu_reset, &mcc->parent_reset); ++ cc->get_arch_id = loongarch_cpu_get_arch_id; ++ ++ cc->class_by_name = loongarch_cpu_class_by_name; ++ cc->has_work = loongarch_cpu_has_work; ++ cc->dump_state = loongarch_cpu_dump_state; ++ cc->set_pc = loongarch_cpu_set_pc; ++ cc->gdb_read_register = loongarch_cpu_gdb_read_register; ++ cc->gdb_write_register = loongarch_cpu_gdb_write_register; ++ cc->disas_set_info = loongarch_cpu_disas_set_info; ++#ifndef CONFIG_USER_ONLY ++ cc->sysemu_ops = &loongarch_sysemu_ops; ++#endif /* !CONFIG_USER_ONLY */ ++ ++ cc->gdb_num_core_regs = 33; ++ cc->gdb_core_xml_file = "loongarch-base64.xml"; ++ cc->gdb_stop_before_watchpoint = true; ++ ++ dc->user_creatable = true; ++#ifdef CONFIG_TCG ++ cc->tcg_ops = &loongarch_tcg_ops; ++#endif /* CONFIG_TCG */ ++} ++ ++static const TypeInfo loongarch_cpu_type_info = { ++ .name = TYPE_LOONGARCH_CPU, ++ .parent = TYPE_CPU, ++ .instance_size = sizeof(LOONGARCHCPU), ++ .instance_init = loongarch_cpu_initfn, ++ .abstract = true, ++ .class_size = sizeof(LOONGARCHCPUClass), ++ .class_init = loongarch_cpu_class_init, ++}; ++ ++static void loongarch_cpu_cpudef_class_init(ObjectClass *oc, void *data) ++{ ++ LOONGARCHCPUClass *mcc = LOONGARCH_CPU_CLASS(oc); ++ mcc->cpu_def = data; ++} ++ ++static void loongarch_register_cpudef_type(const struct loongarch_def_t *def) ++{ ++ char *typename = loongarch_cpu_type_name(def->name); ++ TypeInfo ti = { ++ .name = typename, ++ .parent = TYPE_LOONGARCH_CPU, ++ .class_init = loongarch_cpu_cpudef_class_init, ++ .class_data = (void *)def, ++ }; ++ ++ type_register(&ti); ++ g_free(typename); ++} ++ ++static void loongarch_cpu_register_types(void) ++{ ++ int i; ++ ++ type_register_static(&loongarch_cpu_type_info); ++ for (i = 0; i < loongarch_defs_number; i++) { ++ loongarch_register_cpudef_type(&loongarch_defs[i]); ++ } ++} ++ ++type_init(loongarch_cpu_register_types) +diff --git a/target/loongarch64/cpu.h b/target/loongarch64/cpu.h +new file mode 100644 +index 0000000000..10facb3b73 +--- /dev/null ++++ b/target/loongarch64/cpu.h +@@ -0,0 +1,326 @@ ++#ifndef LOONGARCH_CPU_H ++#define LOONGARCH_CPU_H ++ ++ ++#define CPUArchState struct CPULOONGARCHState ++ ++#include "qemu-common.h" ++#include "cpu-qom.h" ++#include "larch-defs.h" ++#include "exec/cpu-defs.h" ++#include "fpu/softfloat.h" ++#include "sysemu/sysemu.h" ++#include "cpu-csr.h" ++ ++#define TCG_GUEST_DEFAULT_MO (0) ++ ++struct CPULOONGARCHState; ++typedef LOONGARCHCPU ArchCPU; ++typedef struct CPULOONGARCHTLBContext CPULOONGARCHTLBContext; ++ ++#define LASX_REG_WIDTH (256) ++typedef union lasx_reg_t lasx_reg_t; ++union lasx_reg_t { ++ int64_t val64[LASX_REG_WIDTH / 64]; ++}; ++ ++typedef union fpr_t fpr_t; ++union fpr_t { ++ float64 fd; /* ieee double precision */ ++ float32 fs[2];/* ieee single precision */ ++ uint64_t d; /* binary double fixed-point */ ++ uint32_t w[2]; /* binary single fixed-point */ ++/* FPU/LASX register mapping is not tested on big-endian hosts. */ ++ lasx_reg_t lasx; /* vector data */ ++}; ++/* define FP_ENDIAN_IDX to access the same location ++ * in the fpr_t union regardless of the host endianness ++ */ ++#if defined(HOST_WORDS_BIGENDIAN) ++# define FP_ENDIAN_IDX 1 ++#else ++# define FP_ENDIAN_IDX 0 ++#endif ++ ++typedef struct CPULOONGARCHFPUContext { ++ /* Floating point registers */ ++ fpr_t fpr[32]; ++ float_status fp_status; ++ ++ bool cf[8]; ++ /* fcsr0 ++ * 31:29 |28:24 |23:21 |20:16 |15:10 |9:8 |7 |6 |5 |4:0 ++ * Cause Flags RM DAE TM Enables ++ */ ++ uint32_t fcsr0; ++ uint32_t fcsr0_rw_bitmask; ++ uint32_t vcsr16; ++} CPULOONGARCHFPUContext; ++ ++/* fp control and status register definition */ ++#define FCSR0_M1 0xdf /* DAE, TM and Enables */ ++#define FCSR0_M2 0x1f1f0000 /* Cause and Flags */ ++#define FCSR0_M3 0x300 /* Round Mode */ ++#define FCSR0_RM 8 /* Round Mode bit num on fcsr0 */ ++#define GET_FP_CAUSE(reg) (((reg) >> 24) & 0x1f) ++#define GET_FP_ENABLE(reg) (((reg) >> 0) & 0x1f) ++#define GET_FP_FLAGS(reg) (((reg) >> 16) & 0x1f) ++#define SET_FP_CAUSE(reg, v) do { (reg) = ((reg) & ~(0x1f << 24)) | \ ++ ((v & 0x1f) << 24); \ ++ } while (0) ++#define SET_FP_ENABLE(reg, v) do { (reg) = ((reg) & ~(0x1f << 0)) | \ ++ ((v & 0x1f) << 0); \ ++ } while (0) ++#define SET_FP_FLAGS(reg, v) do { (reg) = ((reg) & ~(0x1f << 16)) | \ ++ ((v & 0x1f) << 16); \ ++ } while (0) ++#define UPDATE_FP_FLAGS(reg, v) do { (reg) |= ((v & 0x1f) << 16); } while (0) ++#define FP_INEXACT 1 ++#define FP_UNDERFLOW 2 ++#define FP_OVERFLOW 4 ++#define FP_DIV0 8 ++#define FP_INVALID 16 ++ ++#define TARGET_INSN_START_EXTRA_WORDS 2 ++ ++typedef struct loongarch_def_t loongarch_def_t; ++ ++#define LOONGARCH_FPU_MAX 1 ++#define LOONGARCH_KSCRATCH_NUM 8 ++ ++typedef struct TCState TCState; ++struct TCState { ++ target_ulong gpr[32]; ++ target_ulong PC; ++}; ++ ++#define N_IRQS 14 ++#define IRQ_TIMER 11 ++#define IRQ_IPI 12 ++#define IRQ_UART 2 ++ ++typedef struct CPULOONGARCHState CPULOONGARCHState; ++struct CPULOONGARCHState { ++ TCState active_tc; ++ CPULOONGARCHFPUContext active_fpu; ++ ++ uint32_t current_tc; ++ uint64_t scr[4]; ++ uint32_t PABITS; ++ ++ /* LoongISA CSR register */ ++ CPU_LOONGARCH_CSR ++ uint64_t lladdr; ++ target_ulong llval; ++ uint64_t llval_wp; ++ uint32_t llnewval_wp; ++ ++ CPULOONGARCHFPUContext fpus[LOONGARCH_FPU_MAX]; ++ /* QEMU */ ++ int error_code; ++#define EXCP_TLB_NOMATCH 0x1 ++#define EXCP_INST_NOTAVAIL 0x2 /* No valid instruction word for BadInstr */ ++ uint32_t hflags; /* CPU State */ ++ /* TMASK defines different execution modes */ ++#define LARCH_HFLAG_TMASK 0x5F5807FF ++ /* ++ * The KSU flags must be the lowest bits in hflags. The flag order ++ * must be the same as defined for CP0 Status. This allows to use ++ * the bits as the value of mmu_idx. ++ */ ++#define LARCH_HFLAG_KSU 0x00003 /* kernel/user mode mask */ ++#define LARCH_HFLAG_UM 0x00003 /* user mode flag */ ++#define LARCH_HFLAG_KM 0x00000 /* kernel mode flag */ ++#define LARCH_HFLAG_64 0x00008 /* 64-bit instructions enabled */ ++#define LARCH_HFLAG_FPU 0x00020 /* FPU enabled */ ++#define LARCH_HFLAG_AWRAP 0x00200 /* 32-bit compatibility address wrapping */ ++ /* If translation is interrupted between the branch instruction and ++ * the delay slot, record what type of branch it is so that we can ++ * resume translation properly. It might be possible to reduce ++ * this from three bits to two. */ ++#define LARCH_HFLAG_BMASK 0x03800 ++#define LARCH_HFLAG_B 0x00800 /* Unconditional branch */ ++#define LARCH_HFLAG_BC 0x01000 /* Conditional branch */ ++#define LARCH_HFLAG_BR 0x02000 /* branch to register (can't link TB) */ ++#define LARCH_HFLAG_LSX 0x1000000 ++#define LARCH_HFLAG_LASX 0x2000000 ++#define LARCH_HFLAG_LBT 0x40000000 ++ target_ulong btarget; /* Jump / branch target */ ++ target_ulong bcond; /* Branch condition (if needed) */ ++ ++ uint64_t insn_flags; /* Supported instruction set */ ++ int cpu_cfg[64]; ++ ++ /* Fields up to this point are cleared by a CPU reset */ ++ struct {} end_reset_fields; ++ ++ /* Fields from here on are preserved across CPU reset. */ ++#if !defined(CONFIG_USER_ONLY) ++ CPULOONGARCHTLBContext *tlb; ++#endif ++ ++ const loongarch_def_t *cpu_model; ++ void *irq[N_IRQS]; ++ QEMUTimer *timer; /* Internal timer */ ++ MemoryRegion *itc_tag; /* ITC Configuration Tags */ ++ target_ulong exception_base; /* ExceptionBase input to the core */ ++ struct { ++ uint64_t guest_addr; ++ } st; ++}; ++ ++ ++/* CPU can't have 0xFFFFFFFF APIC ID, use that value to distinguish ++ * that ID hasn't been set yet ++ */ ++#define UNASSIGNED_CPU_ID 0xFFFFFFFF ++ ++/** ++ * LOONGARCHCPU: ++ * @env: #CPULOONGARCHState ++ * ++ * A LOONGARCH CPU. ++ */ ++struct LOONGARCHCPU { ++ /*< private >*/ ++ CPUState parent_obj; ++ /*< public >*/ ++ CPUNegativeOffsetState neg; ++ CPULOONGARCHState env; ++ int32_t id; ++ int hotplugged; ++ uint8_t online_vcpus; ++ uint8_t is_migrate; ++ uint64_t counter_value; ++ uint32_t cpu_freq; ++ uint32_t count_ctl; ++ uint64_t pending_exceptions; ++ uint64_t pending_exceptions_clr; ++ uint64_t core_ext_ioisr[4]; ++ VMChangeStateEntry *cpuStateEntry; ++ int32_t node_id; /* NUMA node this CPU belongs to */ ++ int32_t core_id; ++ struct kvm_msrs *kvm_msr_buf; ++ /* 'compatible' string for this CPU for Linux device trees */ ++ const char *dtb_compatible; ++}; ++ ++static inline LOONGARCHCPU *loongarch_env_get_cpu(CPULOONGARCHState *env) ++{ ++ return container_of(env, LOONGARCHCPU, env); ++} ++ ++#define ENV_GET_CPU(e) CPU(loongarch_env_get_cpu(e)) ++ ++#define ENV_OFFSET offsetof(LOONGARCHCPU, env) ++ ++void loongarch_cpu_list(void); ++ ++#define cpu_signal_handler cpu_loongarch_signal_handler ++#define cpu_list loongarch_cpu_list ++ ++/* MMU modes definitions. We carefully match the indices with our ++ hflags layout. */ ++#define MMU_MODE0_SUFFIX _kernel ++#define MMU_MODE1_SUFFIX _super ++#define MMU_MODE2_SUFFIX _user ++#define MMU_MODE3_SUFFIX _error ++#define MMU_USER_IDX 3 ++ ++static inline int hflags_mmu_index(uint32_t hflags) ++{ ++ return hflags & LARCH_HFLAG_KSU; ++} ++ ++static inline int cpu_mmu_index(CPULOONGARCHState *env, bool ifetch) ++{ ++ return hflags_mmu_index(env->hflags); ++} ++ ++#include "exec/cpu-all.h" ++ ++/* Memory access type : ++ * may be needed for precise access rights control and precise exceptions. ++ */ ++enum { ++ /* 1 bit to define user level / supervisor access */ ++ ACCESS_USER = 0x00, ++ ACCESS_SUPER = 0x01, ++ /* 1 bit to indicate direction */ ++ ACCESS_STORE = 0x02, ++ /* Type of instruction that generated the access */ ++ ACCESS_CODE = 0x10, /* Code fetch access */ ++ ACCESS_INT = 0x20, /* Integer load/store access */ ++ ACCESS_FLOAT = 0x30, /* floating point load/store access */ ++}; ++ ++/* Exceptions */ ++enum { ++ EXCP_NONE = -1, ++ EXCP_RESET = 0, ++ EXCP_SRESET, ++ EXCP_DINT, ++ EXCP_NMI, ++ EXCP_EXT_INTERRUPT, /* 7 */ ++ EXCP_AdEL, ++ EXCP_AdES, ++ EXCP_TLBF, ++ EXCP_IBE, ++ EXCP_SYSCALL, ++ EXCP_BREAK, ++ EXCP_FPDIS, ++ EXCP_LSXDIS, ++ EXCP_LASXDIS, ++ EXCP_RI, ++ EXCP_OVERFLOW, ++ EXCP_TRAP, ++ EXCP_FPE, ++ EXCP_LTLBL, ++ EXCP_TLBL, ++ EXCP_TLBS, ++ EXCP_DBE, ++ EXCP_TLBXI, ++ EXCP_TLBRI, ++ EXCP_TLBPE, ++ EXCP_BTDIS, ++ ++ EXCP_LAST = EXCP_BTDIS, ++}; ++ ++/* ++ * This is an internally generated WAKE request line. ++ * It is driven by the CPU itself. Raised when the MT ++ * block wants to wake a VPE from an inactive state and ++ * cleared when VPE goes from active to inactive. ++ */ ++#define CPU_INTERRUPT_WAKE CPU_INTERRUPT_TGT_INT_0 ++ ++int cpu_loongarch_signal_handler(int host_signum, void *pinfo, void *puc); ++ ++#define LOONGARCH_CPU_TYPE_SUFFIX "-" TYPE_LOONGARCH_CPU ++#define LOONGARCH_CPU_TYPE_NAME(model) model LOONGARCH_CPU_TYPE_SUFFIX ++#define CPU_RESOLVING_TYPE TYPE_LOONGARCH_CPU ++ ++/* helper.c */ ++target_ulong exception_resume_pc(CPULOONGARCHState *env); ++ ++/* gdbstub.c */ ++void loongarch_cpu_register_gdb_regs_for_features(CPUState *cs); ++void mmu_init(CPULOONGARCHState *env, const loongarch_def_t *def); ++ ++static inline void cpu_get_tb_cpu_state(CPULOONGARCHState *env, target_ulong *pc, ++ target_ulong *cs_base, uint32_t *flags) ++{ ++ *pc = env->active_tc.PC; ++ *cs_base = 0; ++ *flags = env->hflags & (LARCH_HFLAG_TMASK | LARCH_HFLAG_BMASK); ++} ++ ++static inline bool cpu_refill_state(CPULOONGARCHState *env) ++{ ++ return env->CSR_TLBRERA & 0x1; ++} ++ ++extern const char * const regnames[]; ++extern const char * const fregnames[]; ++#endif /* LOONGARCH_CPU_H */ +diff --git a/target/loongarch64/csr_helper.c b/target/loongarch64/csr_helper.c +new file mode 100644 +index 0000000000..182e59e925 +--- /dev/null ++++ b/target/loongarch64/csr_helper.c +@@ -0,0 +1,704 @@ ++/* ++ * loongarch tlb emulation helpers for qemu. ++ * ++ * Copyright (c) 2020 - 2021 ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, see . ++ */ ++ ++#include "qemu/osdep.h" ++#include "qemu/main-loop.h" ++#include "cpu.h" ++#include "internal.h" ++#include "qemu/host-utils.h" ++#include "exec/helper-proto.h" ++#include "exec/exec-all.h" ++#include "exec/cpu_ldst.h" ++#include "sysemu/kvm.h" ++#include "hw/irq.h" ++#include "cpu-csr.h" ++#include "instmap.h" ++ ++#ifndef CONFIG_USER_ONLY ++target_ulong helper_csr_rdq(CPULOONGARCHState *env, uint64_t csr) ++{ ++ int64_t v; ++ ++#define CASE_CSR_RDQ(csr) \ ++ case LOONGARCH_CSR_ ## csr: \ ++ { \ ++ v = env->CSR_ ## csr; \ ++ break; \ ++ }; \ ++ ++ switch (csr) { ++ CASE_CSR_RDQ(CRMD) ++ CASE_CSR_RDQ(PRMD) ++ CASE_CSR_RDQ(EUEN) ++ CASE_CSR_RDQ(MISC) ++ CASE_CSR_RDQ(ECFG) ++ CASE_CSR_RDQ(ESTAT) ++ CASE_CSR_RDQ(ERA) ++ CASE_CSR_RDQ(BADV) ++ CASE_CSR_RDQ(BADI) ++ CASE_CSR_RDQ(EEPN) ++ CASE_CSR_RDQ(TLBIDX) ++ CASE_CSR_RDQ(TLBEHI) ++ CASE_CSR_RDQ(TLBELO0) ++ CASE_CSR_RDQ(TLBELO1) ++ CASE_CSR_RDQ(TLBWIRED) ++ CASE_CSR_RDQ(GTLBC) ++ CASE_CSR_RDQ(TRGP) ++ CASE_CSR_RDQ(ASID) ++ CASE_CSR_RDQ(PGDL) ++ CASE_CSR_RDQ(PGDH) ++ CASE_CSR_RDQ(PGD) ++ CASE_CSR_RDQ(PWCTL0) ++ CASE_CSR_RDQ(PWCTL1) ++ CASE_CSR_RDQ(STLBPGSIZE) ++ CASE_CSR_RDQ(RVACFG) ++ CASE_CSR_RDQ(CPUID) ++ CASE_CSR_RDQ(PRCFG1) ++ CASE_CSR_RDQ(PRCFG2) ++ CASE_CSR_RDQ(PRCFG3) ++ CASE_CSR_RDQ(KS0) ++ CASE_CSR_RDQ(KS1) ++ CASE_CSR_RDQ(KS2) ++ CASE_CSR_RDQ(KS3) ++ CASE_CSR_RDQ(KS4) ++ CASE_CSR_RDQ(KS5) ++ CASE_CSR_RDQ(KS6) ++ CASE_CSR_RDQ(KS7) ++ CASE_CSR_RDQ(KS8) ++ CASE_CSR_RDQ(TMID) ++ CASE_CSR_RDQ(TCFG) ++ case LOONGARCH_CSR_TVAL: ++ v = cpu_loongarch_get_stable_timer_ticks(env); ++ break; ++ CASE_CSR_RDQ(CNTC) ++ CASE_CSR_RDQ(TINTCLR) ++ CASE_CSR_RDQ(GSTAT) ++ CASE_CSR_RDQ(GCFG) ++ CASE_CSR_RDQ(GINTC) ++ CASE_CSR_RDQ(GCNTC) ++ CASE_CSR_RDQ(LLBCTL) ++ CASE_CSR_RDQ(IMPCTL1) ++ CASE_CSR_RDQ(IMPCTL2) ++ CASE_CSR_RDQ(GNMI) ++ CASE_CSR_RDQ(TLBRENT) ++ CASE_CSR_RDQ(TLBRBADV) ++ CASE_CSR_RDQ(TLBRERA) ++ CASE_CSR_RDQ(TLBRSAVE) ++ CASE_CSR_RDQ(TLBRELO0) ++ CASE_CSR_RDQ(TLBRELO1) ++ CASE_CSR_RDQ(TLBREHI) ++ CASE_CSR_RDQ(TLBRPRMD) ++ CASE_CSR_RDQ(ERRCTL) ++ CASE_CSR_RDQ(ERRINFO) ++ CASE_CSR_RDQ(ERRINFO1) ++ CASE_CSR_RDQ(ERRENT) ++ CASE_CSR_RDQ(ERRERA) ++ CASE_CSR_RDQ(ERRSAVE) ++ CASE_CSR_RDQ(CTAG) ++ CASE_CSR_RDQ(DMWIN0) ++ CASE_CSR_RDQ(DMWIN1) ++ CASE_CSR_RDQ(DMWIN2) ++ CASE_CSR_RDQ(DMWIN3) ++ CASE_CSR_RDQ(PERFCTRL0) ++ CASE_CSR_RDQ(PERFCNTR0) ++ CASE_CSR_RDQ(PERFCTRL1) ++ CASE_CSR_RDQ(PERFCNTR1) ++ CASE_CSR_RDQ(PERFCTRL2) ++ CASE_CSR_RDQ(PERFCNTR2) ++ CASE_CSR_RDQ(PERFCTRL3) ++ CASE_CSR_RDQ(PERFCNTR3) ++ /* debug */ ++ CASE_CSR_RDQ(MWPC) ++ CASE_CSR_RDQ(MWPS) ++ CASE_CSR_RDQ(DB0ADDR) ++ CASE_CSR_RDQ(DB0MASK) ++ CASE_CSR_RDQ(DB0CTL) ++ CASE_CSR_RDQ(DB0ASID) ++ CASE_CSR_RDQ(DB1ADDR) ++ CASE_CSR_RDQ(DB1MASK) ++ CASE_CSR_RDQ(DB1CTL) ++ CASE_CSR_RDQ(DB1ASID) ++ CASE_CSR_RDQ(DB2ADDR) ++ CASE_CSR_RDQ(DB2MASK) ++ CASE_CSR_RDQ(DB2CTL) ++ CASE_CSR_RDQ(DB2ASID) ++ CASE_CSR_RDQ(DB3ADDR) ++ CASE_CSR_RDQ(DB3MASK) ++ CASE_CSR_RDQ(DB3CTL) ++ CASE_CSR_RDQ(DB3ASID) ++ CASE_CSR_RDQ(FWPC) ++ CASE_CSR_RDQ(FWPS) ++ CASE_CSR_RDQ(IB0ADDR) ++ CASE_CSR_RDQ(IB0MASK) ++ CASE_CSR_RDQ(IB0CTL) ++ CASE_CSR_RDQ(IB0ASID) ++ CASE_CSR_RDQ(IB1ADDR) ++ CASE_CSR_RDQ(IB1MASK) ++ CASE_CSR_RDQ(IB1CTL) ++ CASE_CSR_RDQ(IB1ASID) ++ CASE_CSR_RDQ(IB2ADDR) ++ CASE_CSR_RDQ(IB2MASK) ++ CASE_CSR_RDQ(IB2CTL) ++ CASE_CSR_RDQ(IB2ASID) ++ CASE_CSR_RDQ(IB3ADDR) ++ CASE_CSR_RDQ(IB3MASK) ++ CASE_CSR_RDQ(IB3CTL) ++ CASE_CSR_RDQ(IB3ASID) ++ CASE_CSR_RDQ(IB4ADDR) ++ CASE_CSR_RDQ(IB4MASK) ++ CASE_CSR_RDQ(IB4CTL) ++ CASE_CSR_RDQ(IB4ASID) ++ CASE_CSR_RDQ(IB5ADDR) ++ CASE_CSR_RDQ(IB5MASK) ++ CASE_CSR_RDQ(IB5CTL) ++ CASE_CSR_RDQ(IB5ASID) ++ CASE_CSR_RDQ(IB6ADDR) ++ CASE_CSR_RDQ(IB6MASK) ++ CASE_CSR_RDQ(IB6CTL) ++ CASE_CSR_RDQ(IB6ASID) ++ CASE_CSR_RDQ(IB7ADDR) ++ CASE_CSR_RDQ(IB7MASK) ++ CASE_CSR_RDQ(IB7CTL) ++ CASE_CSR_RDQ(IB7ASID) ++ CASE_CSR_RDQ(DEBUG) ++ CASE_CSR_RDQ(DERA) ++ CASE_CSR_RDQ(DESAVE) ++ default : ++ assert(0); ++ } ++ ++#undef CASE_CSR_RDQ ++ compute_hflags(env); ++ return v; ++} ++ ++target_ulong helper_csr_wrq(CPULOONGARCHState *env, target_ulong val, ++ uint64_t csr) ++{ ++ int64_t old_v, v; ++ old_v = -1; ++ v = val; ++ ++#define CASE_CSR_WRQ(csr) \ ++ case LOONGARCH_CSR_ ## csr: \ ++ { \ ++ old_v = env->CSR_ ## csr; \ ++ env->CSR_ ## csr = v; \ ++ break; \ ++ }; \ ++ ++ switch (csr) { ++ CASE_CSR_WRQ(CRMD) ++ CASE_CSR_WRQ(PRMD) ++ CASE_CSR_WRQ(EUEN) ++ CASE_CSR_WRQ(MISC) ++ CASE_CSR_WRQ(ECFG) ++ CASE_CSR_WRQ(ESTAT) ++ CASE_CSR_WRQ(ERA) ++ CASE_CSR_WRQ(BADV) ++ CASE_CSR_WRQ(BADI) ++ CASE_CSR_WRQ(EEPN) ++ CASE_CSR_WRQ(TLBIDX) ++ CASE_CSR_WRQ(TLBEHI) ++ CASE_CSR_WRQ(TLBELO0) ++ CASE_CSR_WRQ(TLBELO1) ++ CASE_CSR_WRQ(TLBWIRED) ++ CASE_CSR_WRQ(GTLBC) ++ CASE_CSR_WRQ(TRGP) ++ CASE_CSR_WRQ(ASID) ++ CASE_CSR_WRQ(PGDL) ++ CASE_CSR_WRQ(PGDH) ++ CASE_CSR_WRQ(PGD) ++ CASE_CSR_WRQ(PWCTL0) ++ CASE_CSR_WRQ(PWCTL1) ++ CASE_CSR_WRQ(STLBPGSIZE) ++ CASE_CSR_WRQ(RVACFG) ++ CASE_CSR_WRQ(CPUID) ++ CASE_CSR_WRQ(PRCFG1) ++ CASE_CSR_WRQ(PRCFG2) ++ CASE_CSR_WRQ(PRCFG3) ++ CASE_CSR_WRQ(KS0) ++ CASE_CSR_WRQ(KS1) ++ CASE_CSR_WRQ(KS2) ++ CASE_CSR_WRQ(KS3) ++ CASE_CSR_WRQ(KS4) ++ CASE_CSR_WRQ(KS5) ++ CASE_CSR_WRQ(KS6) ++ CASE_CSR_WRQ(KS7) ++ CASE_CSR_WRQ(KS8) ++ CASE_CSR_WRQ(TMID) ++ case LOONGARCH_CSR_TCFG: ++ old_v = env->CSR_TCFG; ++ cpu_loongarch_store_stable_timer_config(env, v); ++ break; ++ CASE_CSR_WRQ(TVAL) ++ CASE_CSR_WRQ(CNTC) ++ case LOONGARCH_CSR_TINTCLR: ++ old_v = 0; ++ qemu_irq_lower(env->irq[IRQ_TIMER]); ++ break; ++ CASE_CSR_WRQ(GSTAT) ++ CASE_CSR_WRQ(GCFG) ++ CASE_CSR_WRQ(GINTC) ++ CASE_CSR_WRQ(GCNTC) ++ CASE_CSR_WRQ(LLBCTL) ++ CASE_CSR_WRQ(IMPCTL1) ++ case LOONGARCH_CSR_IMPCTL2: ++ if (v & CSR_IMPCTL2_MTLB) { ++ ls3a5k_flush_vtlb(env); ++ } ++ if (v & CSR_IMPCTL2_STLB) { ++ ls3a5k_flush_ftlb(env); ++ } ++ break; ++ CASE_CSR_WRQ(GNMI) ++ CASE_CSR_WRQ(TLBRENT) ++ CASE_CSR_WRQ(TLBRBADV) ++ CASE_CSR_WRQ(TLBRERA) ++ CASE_CSR_WRQ(TLBRSAVE) ++ CASE_CSR_WRQ(TLBRELO0) ++ CASE_CSR_WRQ(TLBRELO1) ++ CASE_CSR_WRQ(TLBREHI) ++ CASE_CSR_WRQ(TLBRPRMD) ++ CASE_CSR_WRQ(ERRCTL) ++ CASE_CSR_WRQ(ERRINFO) ++ CASE_CSR_WRQ(ERRINFO1) ++ CASE_CSR_WRQ(ERRENT) ++ CASE_CSR_WRQ(ERRERA) ++ CASE_CSR_WRQ(ERRSAVE) ++ CASE_CSR_WRQ(CTAG) ++ CASE_CSR_WRQ(DMWIN0) ++ CASE_CSR_WRQ(DMWIN1) ++ CASE_CSR_WRQ(DMWIN2) ++ CASE_CSR_WRQ(DMWIN3) ++ CASE_CSR_WRQ(PERFCTRL0) ++ CASE_CSR_WRQ(PERFCNTR0) ++ CASE_CSR_WRQ(PERFCTRL1) ++ CASE_CSR_WRQ(PERFCNTR1) ++ CASE_CSR_WRQ(PERFCTRL2) ++ CASE_CSR_WRQ(PERFCNTR2) ++ CASE_CSR_WRQ(PERFCTRL3) ++ CASE_CSR_WRQ(PERFCNTR3) ++ /* debug */ ++ CASE_CSR_WRQ(MWPC) ++ CASE_CSR_WRQ(MWPS) ++ CASE_CSR_WRQ(DB0ADDR) ++ CASE_CSR_WRQ(DB0MASK) ++ CASE_CSR_WRQ(DB0CTL) ++ CASE_CSR_WRQ(DB0ASID) ++ CASE_CSR_WRQ(DB1ADDR) ++ CASE_CSR_WRQ(DB1MASK) ++ CASE_CSR_WRQ(DB1CTL) ++ CASE_CSR_WRQ(DB1ASID) ++ CASE_CSR_WRQ(DB2ADDR) ++ CASE_CSR_WRQ(DB2MASK) ++ CASE_CSR_WRQ(DB2CTL) ++ CASE_CSR_WRQ(DB2ASID) ++ CASE_CSR_WRQ(DB3ADDR) ++ CASE_CSR_WRQ(DB3MASK) ++ CASE_CSR_WRQ(DB3CTL) ++ CASE_CSR_WRQ(DB3ASID) ++ CASE_CSR_WRQ(FWPC) ++ CASE_CSR_WRQ(FWPS) ++ CASE_CSR_WRQ(IB0ADDR) ++ CASE_CSR_WRQ(IB0MASK) ++ CASE_CSR_WRQ(IB0CTL) ++ CASE_CSR_WRQ(IB0ASID) ++ CASE_CSR_WRQ(IB1ADDR) ++ CASE_CSR_WRQ(IB1MASK) ++ CASE_CSR_WRQ(IB1CTL) ++ CASE_CSR_WRQ(IB1ASID) ++ CASE_CSR_WRQ(IB2ADDR) ++ CASE_CSR_WRQ(IB2MASK) ++ CASE_CSR_WRQ(IB2CTL) ++ CASE_CSR_WRQ(IB2ASID) ++ CASE_CSR_WRQ(IB3ADDR) ++ CASE_CSR_WRQ(IB3MASK) ++ CASE_CSR_WRQ(IB3CTL) ++ CASE_CSR_WRQ(IB3ASID) ++ CASE_CSR_WRQ(IB4ADDR) ++ CASE_CSR_WRQ(IB4MASK) ++ CASE_CSR_WRQ(IB4CTL) ++ CASE_CSR_WRQ(IB4ASID) ++ CASE_CSR_WRQ(IB5ADDR) ++ CASE_CSR_WRQ(IB5MASK) ++ CASE_CSR_WRQ(IB5CTL) ++ CASE_CSR_WRQ(IB5ASID) ++ CASE_CSR_WRQ(IB6ADDR) ++ CASE_CSR_WRQ(IB6MASK) ++ CASE_CSR_WRQ(IB6CTL) ++ CASE_CSR_WRQ(IB6ASID) ++ CASE_CSR_WRQ(IB7ADDR) ++ CASE_CSR_WRQ(IB7MASK) ++ CASE_CSR_WRQ(IB7CTL) ++ CASE_CSR_WRQ(IB7ASID) ++ CASE_CSR_WRQ(DEBUG) ++ CASE_CSR_WRQ(DERA) ++ CASE_CSR_WRQ(DESAVE) ++ default : ++ assert(0); ++ } ++ ++ if (csr == LOONGARCH_CSR_ASID) { ++ if (old_v != v) { ++ tlb_flush(CPU(loongarch_env_get_cpu(env))); ++ } ++ } ++ ++#undef CASE_CSR_WRQ ++ compute_hflags(env); ++ return old_v; ++} ++ ++target_ulong helper_csr_xchgq(CPULOONGARCHState *env, target_ulong val, ++ target_ulong mask, uint64_t csr) ++{ ++ target_ulong v, tmp; ++ v = val & mask; ++ ++#define CASE_CSR_XCHGQ(csr) \ ++ case LOONGARCH_CSR_ ## csr: \ ++ { \ ++ val = env->CSR_ ## csr; \ ++ env->CSR_ ## csr = (env->CSR_ ## csr) & (~mask); \ ++ env->CSR_ ## csr = (env->CSR_ ## csr) | v; \ ++ break; \ ++ }; \ ++ ++ switch (csr) { ++ CASE_CSR_XCHGQ(CRMD) ++ CASE_CSR_XCHGQ(PRMD) ++ CASE_CSR_XCHGQ(EUEN) ++ CASE_CSR_XCHGQ(MISC) ++ CASE_CSR_XCHGQ(ECFG) ++ case LOONGARCH_CSR_ESTAT: ++ val = env->CSR_ESTAT; ++ qatomic_and(&env->CSR_ESTAT, ~mask); ++ qatomic_or(&env->CSR_ESTAT, v); ++ break; ++ CASE_CSR_XCHGQ(ERA) ++ CASE_CSR_XCHGQ(BADV) ++ CASE_CSR_XCHGQ(BADI) ++ CASE_CSR_XCHGQ(EEPN) ++ CASE_CSR_XCHGQ(TLBIDX) ++ CASE_CSR_XCHGQ(TLBEHI) ++ CASE_CSR_XCHGQ(TLBELO0) ++ CASE_CSR_XCHGQ(TLBELO1) ++ CASE_CSR_XCHGQ(TLBWIRED) ++ CASE_CSR_XCHGQ(GTLBC) ++ CASE_CSR_XCHGQ(TRGP) ++ CASE_CSR_XCHGQ(ASID) ++ CASE_CSR_XCHGQ(PGDL) ++ CASE_CSR_XCHGQ(PGDH) ++ CASE_CSR_XCHGQ(PGD) ++ CASE_CSR_XCHGQ(PWCTL0) ++ CASE_CSR_XCHGQ(PWCTL1) ++ CASE_CSR_XCHGQ(STLBPGSIZE) ++ CASE_CSR_XCHGQ(RVACFG) ++ CASE_CSR_XCHGQ(CPUID) ++ CASE_CSR_XCHGQ(PRCFG1) ++ CASE_CSR_XCHGQ(PRCFG2) ++ CASE_CSR_XCHGQ(PRCFG3) ++ CASE_CSR_XCHGQ(KS0) ++ CASE_CSR_XCHGQ(KS1) ++ CASE_CSR_XCHGQ(KS2) ++ CASE_CSR_XCHGQ(KS3) ++ CASE_CSR_XCHGQ(KS4) ++ CASE_CSR_XCHGQ(KS5) ++ CASE_CSR_XCHGQ(KS6) ++ CASE_CSR_XCHGQ(KS7) ++ CASE_CSR_XCHGQ(KS8) ++ CASE_CSR_XCHGQ(TMID) ++ case LOONGARCH_CSR_TCFG: ++ val = env->CSR_TCFG; ++ tmp = val & ~mask; ++ tmp |= v; ++ cpu_loongarch_store_stable_timer_config(env, tmp); ++ break; ++ CASE_CSR_XCHGQ(TVAL) ++ CASE_CSR_XCHGQ(CNTC) ++ CASE_CSR_XCHGQ(TINTCLR) ++ CASE_CSR_XCHGQ(GSTAT) ++ CASE_CSR_XCHGQ(GCFG) ++ CASE_CSR_XCHGQ(GINTC) ++ CASE_CSR_XCHGQ(GCNTC) ++ CASE_CSR_XCHGQ(LLBCTL) ++ CASE_CSR_XCHGQ(IMPCTL1) ++ CASE_CSR_XCHGQ(IMPCTL2) ++ CASE_CSR_XCHGQ(GNMI) ++ CASE_CSR_XCHGQ(TLBRENT) ++ CASE_CSR_XCHGQ(TLBRBADV) ++ CASE_CSR_XCHGQ(TLBRERA) ++ CASE_CSR_XCHGQ(TLBRSAVE) ++ CASE_CSR_XCHGQ(TLBRELO0) ++ CASE_CSR_XCHGQ(TLBRELO1) ++ CASE_CSR_XCHGQ(TLBREHI) ++ CASE_CSR_XCHGQ(TLBRPRMD) ++ CASE_CSR_XCHGQ(ERRCTL) ++ CASE_CSR_XCHGQ(ERRINFO) ++ CASE_CSR_XCHGQ(ERRINFO1) ++ CASE_CSR_XCHGQ(ERRENT) ++ CASE_CSR_XCHGQ(ERRERA) ++ CASE_CSR_XCHGQ(ERRSAVE) ++ CASE_CSR_XCHGQ(CTAG) ++ CASE_CSR_XCHGQ(DMWIN0) ++ CASE_CSR_XCHGQ(DMWIN1) ++ CASE_CSR_XCHGQ(DMWIN2) ++ CASE_CSR_XCHGQ(DMWIN3) ++ CASE_CSR_XCHGQ(PERFCTRL0) ++ CASE_CSR_XCHGQ(PERFCNTR0) ++ CASE_CSR_XCHGQ(PERFCTRL1) ++ CASE_CSR_XCHGQ(PERFCNTR1) ++ CASE_CSR_XCHGQ(PERFCTRL2) ++ CASE_CSR_XCHGQ(PERFCNTR2) ++ CASE_CSR_XCHGQ(PERFCTRL3) ++ CASE_CSR_XCHGQ(PERFCNTR3) ++ /* debug */ ++ CASE_CSR_XCHGQ(MWPC) ++ CASE_CSR_XCHGQ(MWPS) ++ CASE_CSR_XCHGQ(DB0ADDR) ++ CASE_CSR_XCHGQ(DB0MASK) ++ CASE_CSR_XCHGQ(DB0CTL) ++ CASE_CSR_XCHGQ(DB0ASID) ++ CASE_CSR_XCHGQ(DB1ADDR) ++ CASE_CSR_XCHGQ(DB1MASK) ++ CASE_CSR_XCHGQ(DB1CTL) ++ CASE_CSR_XCHGQ(DB1ASID) ++ CASE_CSR_XCHGQ(DB2ADDR) ++ CASE_CSR_XCHGQ(DB2MASK) ++ CASE_CSR_XCHGQ(DB2CTL) ++ CASE_CSR_XCHGQ(DB2ASID) ++ CASE_CSR_XCHGQ(DB3ADDR) ++ CASE_CSR_XCHGQ(DB3MASK) ++ CASE_CSR_XCHGQ(DB3CTL) ++ CASE_CSR_XCHGQ(DB3ASID) ++ CASE_CSR_XCHGQ(FWPC) ++ CASE_CSR_XCHGQ(FWPS) ++ CASE_CSR_XCHGQ(IB0ADDR) ++ CASE_CSR_XCHGQ(IB0MASK) ++ CASE_CSR_XCHGQ(IB0CTL) ++ CASE_CSR_XCHGQ(IB0ASID) ++ CASE_CSR_XCHGQ(IB1ADDR) ++ CASE_CSR_XCHGQ(IB1MASK) ++ CASE_CSR_XCHGQ(IB1CTL) ++ CASE_CSR_XCHGQ(IB1ASID) ++ CASE_CSR_XCHGQ(IB2ADDR) ++ CASE_CSR_XCHGQ(IB2MASK) ++ CASE_CSR_XCHGQ(IB2CTL) ++ CASE_CSR_XCHGQ(IB2ASID) ++ CASE_CSR_XCHGQ(IB3ADDR) ++ CASE_CSR_XCHGQ(IB3MASK) ++ CASE_CSR_XCHGQ(IB3CTL) ++ CASE_CSR_XCHGQ(IB3ASID) ++ CASE_CSR_XCHGQ(IB4ADDR) ++ CASE_CSR_XCHGQ(IB4MASK) ++ CASE_CSR_XCHGQ(IB4CTL) ++ CASE_CSR_XCHGQ(IB4ASID) ++ CASE_CSR_XCHGQ(IB5ADDR) ++ CASE_CSR_XCHGQ(IB5MASK) ++ CASE_CSR_XCHGQ(IB5CTL) ++ CASE_CSR_XCHGQ(IB5ASID) ++ CASE_CSR_XCHGQ(IB6ADDR) ++ CASE_CSR_XCHGQ(IB6MASK) ++ CASE_CSR_XCHGQ(IB6CTL) ++ CASE_CSR_XCHGQ(IB6ASID) ++ CASE_CSR_XCHGQ(IB7ADDR) ++ CASE_CSR_XCHGQ(IB7MASK) ++ CASE_CSR_XCHGQ(IB7CTL) ++ CASE_CSR_XCHGQ(IB7ASID) ++ CASE_CSR_XCHGQ(DEBUG) ++ CASE_CSR_XCHGQ(DERA) ++ CASE_CSR_XCHGQ(DESAVE) ++ default : ++ assert(0); ++ } ++ ++#undef CASE_CSR_XCHGQ ++ compute_hflags(env); ++ return val; ++} ++ ++static target_ulong confbus_addr(CPULOONGARCHState *env, int cpuid, ++ target_ulong csr_addr) ++{ ++ target_ulong addr; ++ target_ulong node_addr; ++ int cores_per_node = ((0x60018 >> 3) & 0xff) + 1; ++ ++ switch (cores_per_node) { ++ case 4: ++ assert(cpuid < 64); ++ node_addr = ((target_ulong)(cpuid & 0x3c) << 42); ++ break; ++ case 8: ++ assert(cpuid < 128); ++ node_addr = ((target_ulong)(cpuid & 0x78) << 41) + ++ ((target_ulong)(cpuid & 0x4) << 14); ++ break; ++ case 16: ++ assert(cpuid < 256); ++ node_addr = ((target_ulong)(cpuid & 0xf0) << 40) + ++ ((target_ulong)(cpuid & 0xc) << 14); ++ break; ++ default: ++ assert(0); ++ break; ++ } ++ ++ /* ++ * per core address ++ *0x10xx => ipi ++ * 0x18xx => extioi isr ++ */ ++ if (((csr_addr & 0xff00) == 0x1000)) { ++ addr = (csr_addr & 0xff) + (target_ulong)(cpuid << 8); ++ addr = 0x800000001f000000UL + addr; ++ return addr; ++ } else if ((csr_addr & 0xff00) == 0x1800) { ++ addr = (csr_addr & 0xff) + ((target_ulong)(cpuid << 8)); ++ addr = 0x800000001f020000UL + addr; ++ return addr; ++ } else if ((csr_addr & 0xff00) >= 0x1400 && (csr_addr & 0xff00) < 0x1d00) { ++ addr = 0x800000001f010000UL + ((csr_addr & 0xfff) - 0x400); ++ return addr; ++ } else if (csr_addr == 0x408) { ++ addr = csr_addr; ++ } else { ++ addr = csr_addr + node_addr; ++ } ++ ++ addr = 0x800000001fe00000UL + addr; ++ return addr; ++} ++ ++void helper_iocsr(CPULOONGARCHState *env, target_ulong r_addr, ++ target_ulong r_val, uint32_t op) ++{ ++ target_ulong addr; ++ target_ulong val = env->active_tc.gpr[r_val]; ++ int mask; ++ ++ addr = confbus_addr(env, CPU(loongarch_env_get_cpu(env))->cpu_index, ++ env->active_tc.gpr[r_addr]); ++ ++ switch (env->active_tc.gpr[r_addr]) { ++ /* IPI send */ ++ case 0x1040: ++ if (op != OPC_LARCH_ST_W) { ++ return; ++ } ++ op = OPC_LARCH_ST_W; ++ break; ++ ++ /* Mail send */ ++ case 0x1048: ++ if (op != OPC_LARCH_ST_D) { ++ return; ++ } ++ op = OPC_LARCH_ST_D; ++ break; ++ ++ /* ANY send */ ++ case 0x1158: ++ if (op != OPC_LARCH_ST_D) { ++ return; ++ } ++ addr = confbus_addr(env, (val >> 16) & 0x3ff, val & 0xffff); ++ mask = (val >> 27) & 0xf; ++ val = (val >> 32); ++ switch (mask) { ++ case 0: ++ op = OPC_LARCH_ST_W; ++ break; ++ case 0x7: ++ op = OPC_LARCH_ST_B; ++ addr += 3; ++ val >>= 24; ++ break; ++ case 0xb: ++ op = OPC_LARCH_ST_B; ++ addr += 2; ++ val >>= 16; ++ break; ++ case 0xd: ++ op = OPC_LARCH_ST_B; ++ addr += 1; ++ val >>= 8; ++ break; ++ case 0xe: ++ op = OPC_LARCH_ST_B; ++ break; ++ case 0xc: ++ op = OPC_LARCH_ST_H; ++ break; ++ case 0x3: ++ op = OPC_LARCH_ST_H; ++ addr += 2; ++ val >>= 16; ++ break; ++ default: ++ qemu_log("Unsupported any_send mask0x%x\n", mask); ++ break; ++ } ++ break; ++ ++ default: ++ break; ++ } ++ ++ switch (op) { ++ case OPC_LARCH_LD_D: ++ env->active_tc.gpr[r_val] = cpu_ldq_data_ra(env, addr, ++ GETPC()); ++ break; ++ case OPC_LARCH_LD_W: ++ env->active_tc.gpr[r_val] = cpu_ldl_data_ra(env, addr, ++ GETPC()); ++ break; ++ case OPC_LARCH_LD_H: ++ assert(0); ++ break; ++ case OPC_LARCH_LD_B: ++ assert(0); ++ break; ++ case OPC_LARCH_ST_D: ++ cpu_stq_data_ra(env, addr, val, GETPC()); ++ break; ++ case OPC_LARCH_ST_W: ++ cpu_stl_data_ra(env, addr, val, GETPC()); ++ break; ++ case OPC_LARCH_ST_H: ++ cpu_stb_data_ra(env, addr, val, GETPC()); ++ break; ++ case OPC_LARCH_ST_B: ++ cpu_stb_data_ra(env, addr, val, GETPC()); ++ break; ++ default: ++ qemu_log("Unknown op 0x%x", op); ++ assert(0); ++ } ++} ++#endif ++ ++target_ulong helper_cpucfg(CPULOONGARCHState *env, target_ulong rj) ++{ ++ return 0; ++} ++ ++ +diff --git a/target/loongarch64/fpu.c b/target/loongarch64/fpu.c +new file mode 100644 +index 0000000000..795458205b +--- /dev/null ++++ b/target/loongarch64/fpu.c +@@ -0,0 +1,28 @@ ++/* ++ * loongarch float point emulation helpers for qemu. ++ * ++ * Copyright (c) 2020-2021 ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, see . ++ */ ++#include "qemu/osdep.h" ++#include "fpu/softfloat.h" ++ ++/* convert loongarch rounding mode in fcsr0 to IEEE library */ ++unsigned int ieee_rm[] = { ++ float_round_nearest_even, ++ float_round_to_zero, ++ float_round_up, ++ float_round_down ++}; +diff --git a/target/loongarch64/fpu_helper.c b/target/loongarch64/fpu_helper.c +new file mode 100644 +index 0000000000..42d7f05ca2 +--- /dev/null ++++ b/target/loongarch64/fpu_helper.c +@@ -0,0 +1,952 @@ ++/* ++ * loongarch float point emulation helpers for qemu. ++ * ++ * Copyright (c) 2020-2021 ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, see . ++ */ ++#include "qemu/osdep.h" ++#include "cpu.h" ++#include "internal.h" ++#include "qemu/host-utils.h" ++#include "exec/helper-proto.h" ++#include "exec/exec-all.h" ++#include "fpu/softfloat.h" ++ ++#define FP_TO_INT32_OVERFLOW 0x7fffffff ++#define FP_TO_INT64_OVERFLOW 0x7fffffffffffffffULL ++ ++#define FLOAT_CLASS_SIGNALING_NAN 0x001 ++#define FLOAT_CLASS_QUIET_NAN 0x002 ++#define FLOAT_CLASS_NEGATIVE_INFINITY 0x004 ++#define FLOAT_CLASS_NEGATIVE_NORMAL 0x008 ++#define FLOAT_CLASS_NEGATIVE_SUBNORMAL 0x010 ++#define FLOAT_CLASS_NEGATIVE_ZERO 0x020 ++#define FLOAT_CLASS_POSITIVE_INFINITY 0x040 ++#define FLOAT_CLASS_POSITIVE_NORMAL 0x080 ++#define FLOAT_CLASS_POSITIVE_SUBNORMAL 0x100 ++#define FLOAT_CLASS_POSITIVE_ZERO 0x200 ++ ++target_ulong helper_movfcsr2gr(CPULOONGARCHState *env, uint32_t reg) ++{ ++ target_ulong r = 0; ++ ++ switch (reg) { ++ case 0: ++ r = (uint32_t)env->active_fpu.fcsr0; ++ break; ++ case 1: ++ r = (env->active_fpu.fcsr0 & FCSR0_M1); ++ break; ++ case 2: ++ r = (env->active_fpu.fcsr0 & FCSR0_M2); ++ break; ++ case 3: ++ r = (env->active_fpu.fcsr0 & FCSR0_M3); ++ break; ++ case 16: ++ r = (uint32_t)env->active_fpu.vcsr16; ++ break; ++ default: ++ printf("%s: warning, fcsr '%d' not supported\n", __func__, reg); ++ assert(0); ++ break; ++ } ++ ++ return r; ++} ++ ++void helper_movgr2fcsr(CPULOONGARCHState *env, target_ulong arg1, ++ uint32_t fcsr, uint32_t rj) ++{ ++ switch (fcsr) { ++ case 0: ++ env->active_fpu.fcsr0 = arg1; ++ break; ++ case 1: ++ env->active_fpu.fcsr0 = (arg1 & FCSR0_M1) | ++ (env->active_fpu.fcsr0 & ~FCSR0_M1); ++ break; ++ case 2: ++ env->active_fpu.fcsr0 = (arg1 & FCSR0_M2) | ++ (env->active_fpu.fcsr0 & ~FCSR0_M2); ++ break; ++ case 3: ++ env->active_fpu.fcsr0 = (arg1 & FCSR0_M3) | ++ (env->active_fpu.fcsr0 & ~FCSR0_M3); ++ break; ++ case 16: ++ env->active_fpu.vcsr16 = arg1; ++ break; ++ default: ++ printf("%s: warning, fcsr '%d' not supported\n", __func__, fcsr); ++ assert(0); ++ break; ++ } ++ restore_fp_status(env); ++ set_float_exception_flags(0, &env->active_fpu.fp_status); ++} ++ ++void helper_movreg2cf(CPULOONGARCHState *env, uint32_t cd, target_ulong src) ++{ ++ env->active_fpu.cf[cd & 0x7] = src & 0x1; ++} ++ ++void helper_movreg2cf_i32(CPULOONGARCHState *env, uint32_t cd, uint32_t src) ++{ ++ env->active_fpu.cf[cd & 0x7] = src & 0x1; ++} ++ ++void helper_movreg2cf_i64(CPULOONGARCHState *env, uint32_t cd, uint64_t src) ++{ ++ env->active_fpu.cf[cd & 0x7] = src & 0x1; ++} ++ ++target_ulong helper_movcf2reg(CPULOONGARCHState *env, uint32_t cj) ++{ ++ return (target_ulong)env->active_fpu.cf[cj & 0x7]; ++} ++ ++int ieee_ex_to_loongarch(int xcpt) ++{ ++ int ret = 0; ++ if (xcpt) { ++ if (xcpt & float_flag_invalid) { ++ ret |= FP_INVALID; ++ } ++ if (xcpt & float_flag_overflow) { ++ ret |= FP_OVERFLOW; ++ } ++ if (xcpt & float_flag_underflow) { ++ ret |= FP_UNDERFLOW; ++ } ++ if (xcpt & float_flag_divbyzero) { ++ ret |= FP_DIV0; ++ } ++ if (xcpt & float_flag_inexact) { ++ ret |= FP_INEXACT; ++ } ++ } ++ return ret; ++} ++ ++static inline void update_fcsr0(CPULOONGARCHState *env, uintptr_t pc) ++{ ++ int tmp = ieee_ex_to_loongarch(get_float_exception_flags( ++ &env->active_fpu.fp_status)); ++ ++ SET_FP_CAUSE(env->active_fpu.fcsr0, tmp); ++ if (tmp) { ++ set_float_exception_flags(0, &env->active_fpu.fp_status); ++ ++ if (GET_FP_ENABLE(env->active_fpu.fcsr0) & tmp) { ++ do_raise_exception(env, EXCP_FPE, pc); ++ } else { ++ UPDATE_FP_FLAGS(env->active_fpu.fcsr0, tmp); ++ } ++ } ++} ++ ++/* unary operations, modifying fp status */ ++uint64_t helper_float_sqrt_d(CPULOONGARCHState *env, uint64_t fdt0) ++{ ++ fdt0 = float64_sqrt(fdt0, &env->active_fpu.fp_status); ++ update_fcsr0(env, GETPC()); ++ return fdt0; ++} ++ ++uint32_t helper_float_sqrt_s(CPULOONGARCHState *env, uint32_t fst0) ++{ ++ fst0 = float32_sqrt(fst0, &env->active_fpu.fp_status); ++ update_fcsr0(env, GETPC()); ++ return fst0; ++} ++ ++uint64_t helper_float_cvtd_s(CPULOONGARCHState *env, uint32_t fst0) ++{ ++ uint64_t fdt2; ++ ++ fdt2 = float32_to_float64(fst0, &env->active_fpu.fp_status); ++ update_fcsr0(env, GETPC()); ++ return fdt2; ++} ++ ++uint64_t helper_float_cvtd_w(CPULOONGARCHState *env, uint32_t wt0) ++{ ++ uint64_t fdt2; ++ ++ fdt2 = int32_to_float64(wt0, &env->active_fpu.fp_status); ++ update_fcsr0(env, GETPC()); ++ return fdt2; ++} ++ ++uint64_t helper_float_cvtd_l(CPULOONGARCHState *env, uint64_t dt0) ++{ ++ uint64_t fdt2; ++ ++ fdt2 = int64_to_float64(dt0, &env->active_fpu.fp_status); ++ update_fcsr0(env, GETPC()); ++ return fdt2; ++} ++ ++uint64_t helper_float_cvt_l_d(CPULOONGARCHState *env, uint64_t fdt0) ++{ ++ uint64_t dt2; ++ ++ dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status); ++ if (get_float_exception_flags(&env->active_fpu.fp_status) ++ & (float_flag_invalid | float_flag_overflow)) { ++ dt2 = FP_TO_INT64_OVERFLOW; ++ } ++ update_fcsr0(env, GETPC()); ++ return dt2; ++} ++ ++uint64_t helper_float_cvt_l_s(CPULOONGARCHState *env, uint32_t fst0) ++{ ++ uint64_t dt2; ++ ++ dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status); ++ if (get_float_exception_flags(&env->active_fpu.fp_status) ++ & (float_flag_invalid | float_flag_overflow)) { ++ dt2 = FP_TO_INT64_OVERFLOW; ++ } ++ update_fcsr0(env, GETPC()); ++ return dt2; ++} ++ ++uint32_t helper_float_cvts_d(CPULOONGARCHState *env, uint64_t fdt0) ++{ ++ uint32_t fst2; ++ ++ fst2 = float64_to_float32(fdt0, &env->active_fpu.fp_status); ++ update_fcsr0(env, GETPC()); ++ return fst2; ++} ++ ++uint32_t helper_float_cvts_w(CPULOONGARCHState *env, uint32_t wt0) ++{ ++ uint32_t fst2; ++ ++ fst2 = int32_to_float32(wt0, &env->active_fpu.fp_status); ++ update_fcsr0(env, GETPC()); ++ return fst2; ++} ++ ++uint32_t helper_float_cvts_l(CPULOONGARCHState *env, uint64_t dt0) ++{ ++ uint32_t fst2; ++ ++ fst2 = int64_to_float32(dt0, &env->active_fpu.fp_status); ++ update_fcsr0(env, GETPC()); ++ return fst2; ++} ++ ++uint32_t helper_float_cvt_w_s(CPULOONGARCHState *env, uint32_t fst0) ++{ ++ uint32_t wt2; ++ ++ wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status); ++ if (get_float_exception_flags(&env->active_fpu.fp_status) ++ & (float_flag_invalid | float_flag_overflow)) { ++ wt2 = FP_TO_INT32_OVERFLOW; ++ } ++ update_fcsr0(env, GETPC()); ++ return wt2; ++} ++ ++uint32_t helper_float_cvt_w_d(CPULOONGARCHState *env, uint64_t fdt0) ++{ ++ uint32_t wt2; ++ ++ wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status); ++ if (get_float_exception_flags(&env->active_fpu.fp_status) ++ & (float_flag_invalid | float_flag_overflow)) { ++ wt2 = FP_TO_INT32_OVERFLOW; ++ } ++ update_fcsr0(env, GETPC()); ++ return wt2; ++} ++ ++uint64_t helper_float_round_l_d(CPULOONGARCHState *env, uint64_t fdt0) ++{ ++ uint64_t dt2; ++ ++ set_float_rounding_mode(float_round_nearest_even, ++ &env->active_fpu.fp_status); ++ dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status); ++ restore_rounding_mode(env); ++ if (get_float_exception_flags(&env->active_fpu.fp_status) ++ & (float_flag_invalid | float_flag_overflow)) { ++ dt2 = FP_TO_INT64_OVERFLOW; ++ } ++ update_fcsr0(env, GETPC()); ++ return dt2; ++} ++ ++uint64_t helper_float_round_l_s(CPULOONGARCHState *env, uint32_t fst0) ++{ ++ uint64_t dt2; ++ ++ set_float_rounding_mode(float_round_nearest_even, ++ &env->active_fpu.fp_status); ++ dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status); ++ restore_rounding_mode(env); ++ if (get_float_exception_flags(&env->active_fpu.fp_status) ++ & (float_flag_invalid | float_flag_overflow)) { ++ dt2 = FP_TO_INT64_OVERFLOW; ++ } ++ update_fcsr0(env, GETPC()); ++ return dt2; ++} ++ ++uint32_t helper_float_round_w_d(CPULOONGARCHState *env, uint64_t fdt0) ++{ ++ uint32_t wt2; ++ ++ set_float_rounding_mode(float_round_nearest_even, ++ &env->active_fpu.fp_status); ++ wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status); ++ restore_rounding_mode(env); ++ if (get_float_exception_flags(&env->active_fpu.fp_status) ++ & (float_flag_invalid | float_flag_overflow)) { ++ wt2 = FP_TO_INT32_OVERFLOW; ++ } ++ update_fcsr0(env, GETPC()); ++ return wt2; ++} ++ ++uint32_t helper_float_round_w_s(CPULOONGARCHState *env, uint32_t fst0) ++{ ++ uint32_t wt2; ++ ++ set_float_rounding_mode(float_round_nearest_even, ++ &env->active_fpu.fp_status); ++ wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status); ++ restore_rounding_mode(env); ++ if (get_float_exception_flags(&env->active_fpu.fp_status) ++ & (float_flag_invalid | float_flag_overflow)) { ++ wt2 = FP_TO_INT32_OVERFLOW; ++ } ++ update_fcsr0(env, GETPC()); ++ return wt2; ++} ++ ++uint64_t helper_float_trunc_l_d(CPULOONGARCHState *env, uint64_t fdt0) ++{ ++ uint64_t dt2; ++ ++ dt2 = float64_to_int64_round_to_zero(fdt0, ++ &env->active_fpu.fp_status); ++ if (get_float_exception_flags(&env->active_fpu.fp_status) ++ & (float_flag_invalid | float_flag_overflow)) { ++ dt2 = FP_TO_INT64_OVERFLOW; ++ } ++ update_fcsr0(env, GETPC()); ++ return dt2; ++} ++ ++uint64_t helper_float_trunc_l_s(CPULOONGARCHState *env, uint32_t fst0) ++{ ++ uint64_t dt2; ++ ++ dt2 = float32_to_int64_round_to_zero(fst0, &env->active_fpu.fp_status); ++ if (get_float_exception_flags(&env->active_fpu.fp_status) ++ & (float_flag_invalid | float_flag_overflow)) { ++ dt2 = FP_TO_INT64_OVERFLOW; ++ } ++ update_fcsr0(env, GETPC()); ++ return dt2; ++} ++ ++uint32_t helper_float_trunc_w_d(CPULOONGARCHState *env, uint64_t fdt0) ++{ ++ uint32_t wt2; ++ ++ wt2 = float64_to_int32_round_to_zero(fdt0, &env->active_fpu.fp_status); ++ if (get_float_exception_flags(&env->active_fpu.fp_status) ++ & (float_flag_invalid | float_flag_overflow)) { ++ wt2 = FP_TO_INT32_OVERFLOW; ++ } ++ update_fcsr0(env, GETPC()); ++ return wt2; ++} ++ ++uint32_t helper_float_trunc_w_s(CPULOONGARCHState *env, uint32_t fst0) ++{ ++ uint32_t wt2; ++ ++ wt2 = float32_to_int32_round_to_zero(fst0, &env->active_fpu.fp_status); ++ if (get_float_exception_flags(&env->active_fpu.fp_status) ++ & (float_flag_invalid | float_flag_overflow)) { ++ wt2 = FP_TO_INT32_OVERFLOW; ++ } ++ update_fcsr0(env, GETPC()); ++ return wt2; ++} ++ ++uint64_t helper_float_ceil_l_d(CPULOONGARCHState *env, uint64_t fdt0) ++{ ++ uint64_t dt2; ++ ++ set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status); ++ dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status); ++ restore_rounding_mode(env); ++ if (get_float_exception_flags(&env->active_fpu.fp_status) ++ & (float_flag_invalid | float_flag_overflow)) { ++ dt2 = FP_TO_INT64_OVERFLOW; ++ } ++ update_fcsr0(env, GETPC()); ++ return dt2; ++} ++ ++uint64_t helper_float_ceil_l_s(CPULOONGARCHState *env, uint32_t fst0) ++{ ++ uint64_t dt2; ++ ++ set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status); ++ dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status); ++ restore_rounding_mode(env); ++ if (get_float_exception_flags(&env->active_fpu.fp_status) ++ & (float_flag_invalid | float_flag_overflow)) { ++ dt2 = FP_TO_INT64_OVERFLOW; ++ } ++ update_fcsr0(env, GETPC()); ++ return dt2; ++} ++ ++uint32_t helper_float_ceil_w_d(CPULOONGARCHState *env, uint64_t fdt0) ++{ ++ uint32_t wt2; ++ ++ set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status); ++ wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status); ++ restore_rounding_mode(env); ++ if (get_float_exception_flags(&env->active_fpu.fp_status) ++ & (float_flag_invalid | float_flag_overflow)) { ++ wt2 = FP_TO_INT32_OVERFLOW; ++ } ++ update_fcsr0(env, GETPC()); ++ return wt2; ++} ++ ++uint32_t helper_float_ceil_w_s(CPULOONGARCHState *env, uint32_t fst0) ++{ ++ uint32_t wt2; ++ ++ set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status); ++ wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status); ++ restore_rounding_mode(env); ++ if (get_float_exception_flags(&env->active_fpu.fp_status) ++ & (float_flag_invalid | float_flag_overflow)) { ++ wt2 = FP_TO_INT32_OVERFLOW; ++ } ++ update_fcsr0(env, GETPC()); ++ return wt2; ++} ++ ++uint64_t helper_float_floor_l_d(CPULOONGARCHState *env, uint64_t fdt0) ++{ ++ uint64_t dt2; ++ ++ set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status); ++ dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status); ++ restore_rounding_mode(env); ++ if (get_float_exception_flags(&env->active_fpu.fp_status) ++ & (float_flag_invalid | float_flag_overflow)) { ++ dt2 = FP_TO_INT64_OVERFLOW; ++ } ++ update_fcsr0(env, GETPC()); ++ return dt2; ++} ++ ++uint64_t helper_float_floor_l_s(CPULOONGARCHState *env, uint32_t fst0) ++{ ++ uint64_t dt2; ++ ++ set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status); ++ dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status); ++ restore_rounding_mode(env); ++ if (get_float_exception_flags(&env->active_fpu.fp_status) ++ & (float_flag_invalid | float_flag_overflow)) { ++ dt2 = FP_TO_INT64_OVERFLOW; ++ } ++ update_fcsr0(env, GETPC()); ++ return dt2; ++} ++ ++uint32_t helper_float_floor_w_d(CPULOONGARCHState *env, uint64_t fdt0) ++{ ++ uint32_t wt2; ++ ++ set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status); ++ wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status); ++ restore_rounding_mode(env); ++ if (get_float_exception_flags(&env->active_fpu.fp_status) ++ & (float_flag_invalid | float_flag_overflow)) { ++ wt2 = FP_TO_INT32_OVERFLOW; ++ } ++ update_fcsr0(env, GETPC()); ++ return wt2; ++} ++ ++uint32_t helper_float_floor_w_s(CPULOONGARCHState *env, uint32_t fst0) ++{ ++ uint32_t wt2; ++ ++ set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status); ++ wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status); ++ restore_rounding_mode(env); ++ if (get_float_exception_flags(&env->active_fpu.fp_status) ++ & (float_flag_invalid | float_flag_overflow)) { ++ wt2 = FP_TO_INT32_OVERFLOW; ++ } ++ update_fcsr0(env, GETPC()); ++ return wt2; ++} ++ ++/* unary operations, not modifying fp status */ ++#define FLOAT_UNOP(name) \ ++uint64_t helper_float_ ## name ## _d(uint64_t fdt0) \ ++{ \ ++ return float64_ ## name(fdt0); \ ++} \ ++uint32_t helper_float_ ## name ## _s(uint32_t fst0) \ ++{ \ ++ return float32_ ## name(fst0); \ ++} ++ ++FLOAT_UNOP(abs) ++FLOAT_UNOP(chs) ++#undef FLOAT_UNOP ++ ++uint64_t helper_float_recip_d(CPULOONGARCHState *env, uint64_t fdt0) ++{ ++ uint64_t fdt2; ++ ++ fdt2 = float64_div(float64_one, fdt0, &env->active_fpu.fp_status); ++ update_fcsr0(env, GETPC()); ++ return fdt2; ++} ++ ++uint32_t helper_float_recip_s(CPULOONGARCHState *env, uint32_t fst0) ++{ ++ uint32_t fst2; ++ ++ fst2 = float32_div(float32_one, fst0, &env->active_fpu.fp_status); ++ update_fcsr0(env, GETPC()); ++ return fst2; ++} ++ ++uint64_t helper_float_rsqrt_d(CPULOONGARCHState *env, uint64_t fdt0) ++{ ++ uint64_t fdt2; ++ ++ fdt2 = float64_sqrt(fdt0, &env->active_fpu.fp_status); ++ fdt2 = float64_div(float64_one, fdt2, &env->active_fpu.fp_status); ++ update_fcsr0(env, GETPC()); ++ return fdt2; ++} ++ ++uint32_t helper_float_rsqrt_s(CPULOONGARCHState *env, uint32_t fst0) ++{ ++ uint32_t fst2; ++ ++ fst2 = float32_sqrt(fst0, &env->active_fpu.fp_status); ++ fst2 = float32_div(float32_one, fst2, &env->active_fpu.fp_status); ++ update_fcsr0(env, GETPC()); ++ return fst2; ++} ++ ++uint32_t helper_float_rint_s(CPULOONGARCHState *env, uint32_t fs) ++{ ++ uint32_t fdret; ++ ++ fdret = float32_round_to_int(fs, &env->active_fpu.fp_status); ++ update_fcsr0(env, GETPC()); ++ return fdret; ++} ++ ++uint64_t helper_float_rint_d(CPULOONGARCHState *env, uint64_t fs) ++{ ++ uint64_t fdret; ++ ++ fdret = float64_round_to_int(fs, &env->active_fpu.fp_status); ++ update_fcsr0(env, GETPC()); ++ return fdret; ++} ++ ++#define FLOAT_CLASS(name, bits) \ ++uint ## bits ## _t float_ ## name(uint ## bits ## _t arg, \ ++ float_status *status) \ ++{ \ ++ if (float ## bits ## _is_signaling_nan(arg, status)) { \ ++ return FLOAT_CLASS_SIGNALING_NAN; \ ++ } else if (float ## bits ## _is_quiet_nan(arg, status)) { \ ++ return FLOAT_CLASS_QUIET_NAN; \ ++ } else if (float ## bits ## _is_neg(arg)) { \ ++ if (float ## bits ## _is_infinity(arg)) { \ ++ return FLOAT_CLASS_NEGATIVE_INFINITY; \ ++ } else if (float ## bits ## _is_zero(arg)) { \ ++ return FLOAT_CLASS_NEGATIVE_ZERO; \ ++ } else if (float ## bits ## _is_zero_or_denormal(arg)) { \ ++ return FLOAT_CLASS_NEGATIVE_SUBNORMAL; \ ++ } else { \ ++ return FLOAT_CLASS_NEGATIVE_NORMAL; \ ++ } \ ++ } else { \ ++ if (float ## bits ## _is_infinity(arg)) { \ ++ return FLOAT_CLASS_POSITIVE_INFINITY; \ ++ } else if (float ## bits ## _is_zero(arg)) { \ ++ return FLOAT_CLASS_POSITIVE_ZERO; \ ++ } else if (float ## bits ## _is_zero_or_denormal(arg)) { \ ++ return FLOAT_CLASS_POSITIVE_SUBNORMAL; \ ++ } else { \ ++ return FLOAT_CLASS_POSITIVE_NORMAL; \ ++ } \ ++ } \ ++} \ ++ \ ++uint ## bits ## _t helper_float_ ## name(CPULOONGARCHState *env, \ ++ uint ## bits ## _t arg) \ ++{ \ ++ return float_ ## name(arg, &env->active_fpu.fp_status); \ ++} ++ ++FLOAT_CLASS(class_s, 32) ++FLOAT_CLASS(class_d, 64) ++#undef FLOAT_CLASS ++ ++/* binary operations */ ++#define FLOAT_BINOP(name) \ ++uint64_t helper_float_ ## name ## _d(CPULOONGARCHState *env, \ ++ uint64_t fdt0, uint64_t fdt1) \ ++{ \ ++ uint64_t dt2; \ ++ \ ++ dt2 = float64_ ## name(fdt0, fdt1, &env->active_fpu.fp_status);\ ++ update_fcsr0(env, GETPC()); \ ++ return dt2; \ ++} \ ++ \ ++uint32_t helper_float_ ## name ## _s(CPULOONGARCHState *env, \ ++ uint32_t fst0, uint32_t fst1) \ ++{ \ ++ uint32_t wt2; \ ++ \ ++ wt2 = float32_ ## name(fst0, fst1, &env->active_fpu.fp_status);\ ++ update_fcsr0(env, GETPC()); \ ++ return wt2; \ ++} ++ ++FLOAT_BINOP(add) ++FLOAT_BINOP(sub) ++FLOAT_BINOP(mul) ++FLOAT_BINOP(div) ++#undef FLOAT_BINOP ++ ++uint64_t helper_float_exp2_d(CPULOONGARCHState *env, ++ uint64_t fdt0, uint64_t fdt1) ++{ ++ uint64_t dt2; ++ int64_t n = (int64_t)fdt1; ++ ++ dt2 = float64_scalbn(fdt0, ++ n > 0x1000 ? 0x1000 : ++ n < -0x1000 ? -0x1000 : n, ++ &env->active_fpu.fp_status); ++ update_fcsr0(env, GETPC()); ++ return dt2; ++} ++ ++uint32_t helper_float_exp2_s(CPULOONGARCHState *env, ++ uint32_t fst0, uint32_t fst1) ++{ ++ uint32_t wt2; ++ int32_t n = (int32_t)fst1; ++ ++ wt2 = float32_scalbn(fst0, ++ n > 0x200 ? 0x200 : ++ n < -0x200 ? -0x200 : n, ++ &env->active_fpu.fp_status); ++ update_fcsr0(env, GETPC()); ++ return wt2; ++} ++ ++#define FLOAT_MINMAX(name, bits, minmaxfunc) \ ++uint ## bits ## _t helper_float_ ## name(CPULOONGARCHState *env, \ ++ uint ## bits ## _t fs, \ ++ uint ## bits ## _t ft) \ ++{ \ ++ uint ## bits ## _t fdret; \ ++ \ ++ fdret = float ## bits ## _ ## minmaxfunc(fs, ft, \ ++ &env->active_fpu.fp_status); \ ++ update_fcsr0(env, GETPC()); \ ++ return fdret; \ ++} ++ ++FLOAT_MINMAX(max_s, 32, maxnum) ++FLOAT_MINMAX(max_d, 64, maxnum) ++FLOAT_MINMAX(maxa_s, 32, maxnummag) ++FLOAT_MINMAX(maxa_d, 64, maxnummag) ++ ++FLOAT_MINMAX(min_s, 32, minnum) ++FLOAT_MINMAX(min_d, 64, minnum) ++FLOAT_MINMAX(mina_s, 32, minnummag) ++FLOAT_MINMAX(mina_d, 64, minnummag) ++#undef FLOAT_MINMAX ++ ++#define FLOAT_FMADDSUB(name, bits, muladd_arg) \ ++uint ## bits ## _t helper_float_ ## name(CPULOONGARCHState *env, \ ++ uint ## bits ## _t fs, \ ++ uint ## bits ## _t ft, \ ++ uint ## bits ## _t fd) \ ++{ \ ++ uint ## bits ## _t fdret; \ ++ \ ++ fdret = float ## bits ## _muladd(fs, ft, fd, muladd_arg, \ ++ &env->active_fpu.fp_status); \ ++ update_fcsr0(env, GETPC()); \ ++ return fdret; \ ++} ++ ++FLOAT_FMADDSUB(maddf_s, 32, 0) ++FLOAT_FMADDSUB(maddf_d, 64, 0) ++FLOAT_FMADDSUB(msubf_s, 32, float_muladd_negate_c) ++FLOAT_FMADDSUB(msubf_d, 64, float_muladd_negate_c) ++FLOAT_FMADDSUB(nmaddf_s, 32, float_muladd_negate_result) ++FLOAT_FMADDSUB(nmaddf_d, 64, float_muladd_negate_result) ++FLOAT_FMADDSUB(nmsubf_s, 32, float_muladd_negate_result | float_muladd_negate_c) ++FLOAT_FMADDSUB(nmsubf_d, 64, float_muladd_negate_result | float_muladd_negate_c) ++#undef FLOAT_FMADDSUB ++ ++/* compare operations */ ++#define FOP_CONDN_D(op, cond) \ ++uint64_t helper_cmp_d_ ## op(CPULOONGARCHState *env, uint64_t fdt0, \ ++ uint64_t fdt1) \ ++{ \ ++ uint64_t c; \ ++ c = cond; \ ++ update_fcsr0(env, GETPC()); \ ++ if (c) { \ ++ return -1; \ ++ } else { \ ++ return 0; \ ++ } \ ++} ++ ++/* ++ * NOTE: the comma operator will make "cond" to eval to false, ++ * but float64_unordered_quiet() is still called. ++ */ ++FOP_CONDN_D(af, (float64_unordered_quiet(fdt1, fdt0, ++ &env->active_fpu.fp_status), 0)) ++FOP_CONDN_D(un, (float64_unordered_quiet(fdt1, fdt0, ++ &env->active_fpu.fp_status))) ++FOP_CONDN_D(eq, (float64_eq_quiet(fdt0, fdt1, ++ &env->active_fpu.fp_status))) ++FOP_CONDN_D(ueq, (float64_unordered_quiet(fdt1, fdt0, ++ &env->active_fpu.fp_status) ++ || float64_eq_quiet(fdt0, fdt1, ++ &env->active_fpu.fp_status))) ++FOP_CONDN_D(lt, (float64_lt_quiet(fdt0, fdt1, ++ &env->active_fpu.fp_status))) ++FOP_CONDN_D(ult, (float64_unordered_quiet(fdt1, fdt0, ++ &env->active_fpu.fp_status) ++ || float64_lt_quiet(fdt0, fdt1, ++ &env->active_fpu.fp_status))) ++FOP_CONDN_D(le, (float64_le_quiet(fdt0, fdt1, ++ &env->active_fpu.fp_status))) ++FOP_CONDN_D(ule, (float64_unordered_quiet(fdt1, fdt0, ++ &env->active_fpu.fp_status) ++ || float64_le_quiet(fdt0, fdt1, ++ &env->active_fpu.fp_status))) ++/* ++ * NOTE: the comma operator will make "cond" to eval to false, ++ * but float64_unordered() is still called. ++ */ ++FOP_CONDN_D(saf, (float64_unordered(fdt1, fdt0, ++ &env->active_fpu.fp_status), 0)) ++FOP_CONDN_D(sun, (float64_unordered(fdt1, fdt0, ++ &env->active_fpu.fp_status))) ++FOP_CONDN_D(seq, (float64_eq(fdt0, fdt1, ++ &env->active_fpu.fp_status))) ++FOP_CONDN_D(sueq, (float64_unordered(fdt1, fdt0, ++ &env->active_fpu.fp_status) ++ || float64_eq(fdt0, fdt1, ++ &env->active_fpu.fp_status))) ++FOP_CONDN_D(slt, (float64_lt(fdt0, fdt1, ++ &env->active_fpu.fp_status))) ++FOP_CONDN_D(sult, (float64_unordered(fdt1, fdt0, ++ &env->active_fpu.fp_status) ++ || float64_lt(fdt0, fdt1, ++ &env->active_fpu.fp_status))) ++FOP_CONDN_D(sle, (float64_le(fdt0, fdt1, ++ &env->active_fpu.fp_status))) ++FOP_CONDN_D(sule, (float64_unordered(fdt1, fdt0, ++ &env->active_fpu.fp_status) ++ || float64_le(fdt0, fdt1, ++ &env->active_fpu.fp_status))) ++FOP_CONDN_D(or, (float64_le_quiet(fdt1, fdt0, ++ &env->active_fpu.fp_status) ++ || float64_le_quiet(fdt0, fdt1, ++ &env->active_fpu.fp_status))) ++FOP_CONDN_D(une, (float64_unordered_quiet(fdt1, fdt0, ++ &env->active_fpu.fp_status) ++ || float64_lt_quiet(fdt1, fdt0, ++ &env->active_fpu.fp_status) ++ || float64_lt_quiet(fdt0, fdt1, ++ &env->active_fpu.fp_status))) ++FOP_CONDN_D(ne, (float64_lt_quiet(fdt1, fdt0, ++ &env->active_fpu.fp_status) ++ || float64_lt_quiet(fdt0, fdt1, ++ &env->active_fpu.fp_status))) ++FOP_CONDN_D(sor, (float64_le(fdt1, fdt0, ++ &env->active_fpu.fp_status) ++ || float64_le(fdt0, fdt1, ++ &env->active_fpu.fp_status))) ++FOP_CONDN_D(sune, (float64_unordered(fdt1, fdt0, ++ &env->active_fpu.fp_status) ++ || float64_lt(fdt1, fdt0, ++ &env->active_fpu.fp_status) ++ || float64_lt(fdt0, fdt1, ++ &env->active_fpu.fp_status))) ++FOP_CONDN_D(sne, (float64_lt(fdt1, fdt0, ++ &env->active_fpu.fp_status) ++ || float64_lt(fdt0, fdt1, ++ &env->active_fpu.fp_status))) ++ ++#define FOP_CONDN_S(op, cond) \ ++uint32_t helper_cmp_s_ ## op(CPULOONGARCHState *env, uint32_t fst0, \ ++ uint32_t fst1) \ ++{ \ ++ uint64_t c; \ ++ c = cond; \ ++ update_fcsr0(env, GETPC()); \ ++ if (c) { \ ++ return -1; \ ++ } else { \ ++ return 0; \ ++ } \ ++} ++ ++/* ++ * NOTE: the comma operator will make "cond" to eval to false, ++ * but float32_unordered_quiet() is still called. ++ */ ++FOP_CONDN_S(af, (float32_unordered_quiet(fst1, fst0, ++ &env->active_fpu.fp_status), 0)) ++FOP_CONDN_S(un, (float32_unordered_quiet(fst1, fst0, ++ &env->active_fpu.fp_status))) ++FOP_CONDN_S(eq, (float32_eq_quiet(fst0, fst1, ++ &env->active_fpu.fp_status))) ++FOP_CONDN_S(ueq, (float32_unordered_quiet(fst1, fst0, ++ &env->active_fpu.fp_status) ++ || float32_eq_quiet(fst0, fst1, ++ &env->active_fpu.fp_status))) ++FOP_CONDN_S(lt, (float32_lt_quiet(fst0, fst1, ++ &env->active_fpu.fp_status))) ++FOP_CONDN_S(ult, (float32_unordered_quiet(fst1, fst0, ++ &env->active_fpu.fp_status) ++ || float32_lt_quiet(fst0, fst1, ++ &env->active_fpu.fp_status))) ++FOP_CONDN_S(le, (float32_le_quiet(fst0, fst1, ++ &env->active_fpu.fp_status))) ++FOP_CONDN_S(ule, (float32_unordered_quiet(fst1, fst0, ++ &env->active_fpu.fp_status) ++ || float32_le_quiet(fst0, fst1, ++ &env->active_fpu.fp_status))) ++/* ++ * NOTE: the comma operator will make "cond" to eval to false, ++ * but float32_unordered() is still called. ++ */ ++FOP_CONDN_S(saf, (float32_unordered(fst1, fst0, ++ &env->active_fpu.fp_status), 0)) ++FOP_CONDN_S(sun, (float32_unordered(fst1, fst0, ++ &env->active_fpu.fp_status))) ++FOP_CONDN_S(seq, (float32_eq(fst0, fst1, ++ &env->active_fpu.fp_status))) ++FOP_CONDN_S(sueq, (float32_unordered(fst1, fst0, ++ &env->active_fpu.fp_status) ++ || float32_eq(fst0, fst1, ++ &env->active_fpu.fp_status))) ++FOP_CONDN_S(slt, (float32_lt(fst0, fst1, ++ &env->active_fpu.fp_status))) ++FOP_CONDN_S(sult, (float32_unordered(fst1, fst0, ++ &env->active_fpu.fp_status) ++ || float32_lt(fst0, fst1, ++ &env->active_fpu.fp_status))) ++FOP_CONDN_S(sle, (float32_le(fst0, fst1, ++ &env->active_fpu.fp_status))) ++FOP_CONDN_S(sule, (float32_unordered(fst1, fst0, ++ &env->active_fpu.fp_status) ++ || float32_le(fst0, fst1, ++ &env->active_fpu.fp_status))) ++FOP_CONDN_S(or, (float32_le_quiet(fst1, fst0, ++ &env->active_fpu.fp_status) ++ || float32_le_quiet(fst0, fst1, ++ &env->active_fpu.fp_status))) ++FOP_CONDN_S(une, (float32_unordered_quiet(fst1, fst0, ++ &env->active_fpu.fp_status) ++ || float32_lt_quiet(fst1, fst0, ++ &env->active_fpu.fp_status) ++ || float32_lt_quiet(fst0, fst1, ++ &env->active_fpu.fp_status))) ++FOP_CONDN_S(ne, (float32_lt_quiet(fst1, fst0, ++ &env->active_fpu.fp_status) ++ || float32_lt_quiet(fst0, fst1, ++ &env->active_fpu.fp_status))) ++FOP_CONDN_S(sor, (float32_le(fst1, fst0, ++ &env->active_fpu.fp_status) ++ || float32_le(fst0, fst1, ++ &env->active_fpu.fp_status))) ++FOP_CONDN_S(sune, (float32_unordered(fst1, fst0, ++ &env->active_fpu.fp_status) ++ || float32_lt(fst1, fst0, ++ &env->active_fpu.fp_status) ++ || float32_lt(fst0, fst1, ++ &env->active_fpu.fp_status))) ++FOP_CONDN_S(sne, (float32_lt(fst1, fst0, ++ &env->active_fpu.fp_status) ++ || float32_lt(fst0, fst1, ++ &env->active_fpu.fp_status))) ++ ++uint32_t helper_float_logb_s(CPULOONGARCHState *env, uint32_t fst0) ++{ ++ uint32_t wt2; ++ ++ wt2 = float32_log2(fst0, &env->active_fpu.fp_status); ++ update_fcsr0(env, GETPC()); ++ return wt2; ++} ++ ++uint64_t helper_float_logb_d(CPULOONGARCHState *env, uint64_t fdt0) ++{ ++ uint64_t dt2; ++ ++ dt2 = float64_log2(fdt0, &env->active_fpu.fp_status); ++ update_fcsr0(env, GETPC()); ++ return dt2; ++} ++ ++target_ulong helper_fsel(CPULOONGARCHState *env, target_ulong fj, ++ target_ulong fk, uint32_t ca) ++{ ++ if (env->active_fpu.cf[ca & 0x7]) { ++ return fk; ++ } else { ++ return fj; ++ } ++} +diff --git a/target/loongarch64/fpu_helper.h b/target/loongarch64/fpu_helper.h +new file mode 100644 +index 0000000000..b6898c2e91 +--- /dev/null ++++ b/target/loongarch64/fpu_helper.h +@@ -0,0 +1,129 @@ ++/* loongarch internal definitions and helpers ++ * ++ * This work is licensed under the terms of the GNU GPL, version 2 or later. ++ * See the COPYING file in the top-level directory. ++ */ ++ ++#ifndef LOONGARCH_FPU_H ++#define LOONGARCH_FPU_H ++ ++#include "cpu-csr.h" ++ ++ ++extern const struct loongarch_def_t loongarch_defs[]; ++extern const int loongarch_defs_number; ++ ++enum CPULSXDataFormat { ++ DF_BYTE = 0, ++ DF_HALF, ++ DF_WORD, ++ DF_DOUBLE, ++ DF_QUAD ++}; ++ ++void loongarch_cpu_do_interrupt(CPUState *cpu); ++bool loongarch_cpu_exec_interrupt(CPUState *cpu, int int_req); ++void loongarch_cpu_do_unaligned_access(CPUState *cpu, vaddr addr, ++ MMUAccessType access_type, ++ int mmu_idx, uintptr_t retaddr) QEMU_NORETURN; ++ ++#if !defined(CONFIG_USER_ONLY) ++ ++typedef struct r4k_tlb_t r4k_tlb_t; ++struct r4k_tlb_t { ++ target_ulong VPN; ++ uint32_t PageMask; ++ uint16_t ASID; ++ unsigned int G:1; ++ unsigned int C0:3; ++ unsigned int C1:3; ++ unsigned int V0:1; ++ unsigned int V1:1; ++ unsigned int D0:1; ++ unsigned int D1:1; ++ unsigned int XI0:1; ++ unsigned int XI1:1; ++ unsigned int RI0:1; ++ unsigned int RI1:1; ++ unsigned int EHINV:1; ++ uint64_t PPN[2]; ++}; ++ ++int no_mmu_map_address(CPULOONGARCHState *env, hwaddr *physical, int *prot, ++ target_ulong address, int rw, int access_type); ++int fixed_mmu_map_address(CPULOONGARCHState *env, hwaddr *physical, int *prot, ++ target_ulong address, int rw, int access_type); ++int r4k_map_address(CPULOONGARCHState *env, hwaddr *physical, int *prot, ++ target_ulong address, int rw, int access_type); ++ ++/* loongarch 3a5000 tlb helper function : lisa csr */ ++int ls3a5k_map_address(CPULOONGARCHState *env, hwaddr *physical, ++ int *prot, target_ulong address, ++ int rw, int access_type); ++void ls3a5k_helper_tlbwr(CPULOONGARCHState *env); ++void ls3a5k_helper_tlbfill(CPULOONGARCHState *env); ++void ls3a5k_helper_tlbsrch(CPULOONGARCHState *env); ++void ls3a5k_helper_tlbrd(CPULOONGARCHState *env); ++void ls3a5k_helper_tlbclr(CPULOONGARCHState *env); ++void ls3a5k_helper_tlbflush(CPULOONGARCHState *env); ++void ls3a5k_invalidate_tlb(CPULOONGARCHState *env, int idx); ++void ls3a5k_helper_invtlb(CPULOONGARCHState *env, target_ulong addr, ++ target_ulong info, int op); ++void ls3a5k_flush_vtlb(CPULOONGARCHState *env); ++void ls3a5k_flush_ftlb(CPULOONGARCHState *env); ++/*void loongarch_cpu_unassigned_access(CPUState *cpu, hwaddr addr, ++ bool is_write, bool is_exec, int unused, ++ unsigned size); ++*/ ++hwaddr cpu_loongarch_translate_address(CPULOONGARCHState *env, target_ulong address, ++ int rw); ++#endif ++ ++#define cpu_signal_handler cpu_loongarch_signal_handler ++ ++ ++static inline bool cpu_loongarch_hw_interrupts_enabled(CPULOONGARCHState *env) ++{ ++ bool ret = 0; ++ ++ ret = env->CSR_CRMD & (1 << CSR_CRMD_IE_SHIFT); ++ ++ return ret; ++} ++ ++ ++void loongarch_tcg_init(void); ++ ++ ++/* helper.c */ ++bool loongarch_cpu_tlb_fill(CPUState *cs, vaddr address, int size, ++ MMUAccessType access_type, int mmu_idx, ++ bool probe, uintptr_t retaddr); ++ ++/* op_helper.c */ ++uint32_t float_class_s(uint32_t arg, float_status *fst); ++uint64_t float_class_d(uint64_t arg, float_status *fst); ++ ++int ieee_ex_to_loongarch(int xcpt); ++void update_pagemask(CPULOONGARCHState *env, target_ulong arg1, int32_t *pagemask); ++ ++void cpu_loongarch_tlb_flush(CPULOONGARCHState *env); ++void sync_c0_status(CPULOONGARCHState *env, CPULOONGARCHState *cpu, int tc); ++ ++void QEMU_NORETURN do_raise_exception_err(CPULOONGARCHState *env, uint32_t exception, ++ int error_code, uintptr_t pc); ++int loongarch_read_qxfer(CPUState *cs, const char *annex, ++ uint8_t *read_buf, ++ unsigned long offset, unsigned long len); ++int loongarch_write_qxfer(CPUState *cs, const char *annex, ++ const uint8_t *write_buf, ++ unsigned long offset, unsigned long len); ++ ++static inline void QEMU_NORETURN do_raise_exception(CPULOONGARCHState *env, ++ uint32_t exception, ++ uintptr_t pc) ++{ ++ do_raise_exception_err(env, exception, 0, pc); ++} ++ ++#endif +diff --git a/target/loongarch64/gdbstub.c b/target/loongarch64/gdbstub.c +new file mode 100644 +index 0000000000..4013178f45 +--- /dev/null ++++ b/target/loongarch64/gdbstub.c +@@ -0,0 +1,109 @@ ++/* ++ * LOONGARCH gdb server stub ++ * ++ * Copyright (c) 2003-2005 Fabrice Bellard ++ * Copyright (c) 2013 SUSE LINUX Products GmbH ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, see . ++ */ ++#include "qemu/osdep.h" ++#include "qemu-common.h" ++#include "cpu.h" ++#include "internal.h" ++#include "exec/gdbstub.h" ++#ifdef CONFIG_TCG ++#include "exec/helper-proto.h" ++#endif ++int loongarch_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n) ++{ ++ LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); ++ CPULOONGARCHState *env = &cpu->env; ++ ++ if (0 <= n && n < 32) { ++ return gdb_get_regl(mem_buf, env->active_tc.gpr[n]); ++ } else if (n == 32) { ++ return gdb_get_regl(mem_buf, env->active_tc.PC); ++ } ++ return 0; ++} ++ ++int loongarch_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) ++{ ++ LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); ++ CPULOONGARCHState *env = &cpu->env; ++ target_ulong tmp = ldtul_p(mem_buf); ++ ++ if (0 <= n && n < 32) { ++ return env->active_tc.gpr[n] = tmp, sizeof(target_ulong); ++ } else if (n == 32) { ++ return env->active_tc.PC = tmp, sizeof(target_ulong); ++ } ++ return 0; ++} ++ ++static int loongarch_gdb_get_fpu(CPULOONGARCHState *env, GByteArray *mem_buf, int n) ++{ ++ if (0 <= n && n < 32) { ++ return gdb_get_reg64(mem_buf, env->active_fpu.fpr[n].d); ++ } else if (32 <= n && n < 40) { ++ return gdb_get_reg8(mem_buf, env->active_fpu.cf[n - 32]); ++ } else if (n == 40) { ++ return gdb_get_reg32(mem_buf, env->active_fpu.fcsr0); ++ } ++ return 0; ++} ++ ++static int loongarch_gdb_set_fpu(CPULOONGARCHState *env, uint8_t *mem_buf, int n) ++{ ++ if (0 <= n && n < 32) { ++ return env->active_fpu.fpr[n].d = ldq_p(mem_buf), 8; ++ } else if (32 <= n && n < 40) { ++ return env->active_fpu.cf[n - 32] = ldub_p(mem_buf), 1; ++ } else if (n == 40) { ++ return env->active_fpu.fcsr0 = ldl_p(mem_buf), 4; ++ } ++ return 0; ++} ++ ++void loongarch_cpu_register_gdb_regs_for_features(CPUState *cs) ++{ ++ gdb_register_coprocessor(cs, loongarch_gdb_get_fpu, loongarch_gdb_set_fpu, ++ 41, "loongarch-fpu64.xml", 0); ++} ++ ++#ifdef CONFIG_TCG ++int loongarch_read_qxfer(CPUState *cs, const char *annex, uint8_t *read_buf, ++ unsigned long offset, unsigned long len) ++{ ++ if (strncmp(annex, "cpucfg", sizeof("cpucfg") - 1) == 0) { ++ if (offset % 4 != 0 || len % 4 != 0) { ++ return 0; ++ } ++ ++ size_t i; ++ for (i = offset; i < offset + len; i += 4) ++ ((uint32_t *)read_buf)[(i - offset) / 4] = ++ helper_cpucfg(&(LOONGARCH_CPU(cs)->env), i / 4); ++ return 32 * 4; ++ } ++ return 0; ++} ++ ++int loongarch_write_qxfer(CPUState *cs, const char *annex, ++ const uint8_t *write_buf, unsigned long offset, ++ unsigned long len) ++{ ++ return 0; ++} ++#endif +diff --git a/target/loongarch64/helper.c b/target/loongarch64/helper.c +new file mode 100644 +index 0000000000..841240e57b +--- /dev/null ++++ b/target/loongarch64/helper.c +@@ -0,0 +1,727 @@ ++/* ++ * LOONGARCH emulation helpers for qemu. ++ * ++ * Copyright (c) 2004-2005 Jocelyn Mayer ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, see . ++ */ ++#include "qemu/osdep.h" ++#include "cpu.h" ++#include "internal.h" ++#include "exec/exec-all.h" ++#include "exec/cpu_ldst.h" ++#include "exec/log.h" ++#include "hw/loongarch/cpudevs.h" ++ ++ ++#if !defined(CONFIG_USER_ONLY) ++ ++static int ls3a5k_map_address_tlb_entry( ++ CPULOONGARCHState *env, ++ hwaddr *physical, ++ int *prot, ++ target_ulong address, ++ int rw, ++ int access_type, ++ ls3a5k_tlb_t *tlb) ++{ ++ uint64_t mask = tlb->PageMask; ++ int n = !!(address & mask & ~(mask >> 1)); ++ uint32_t plv = env->CSR_CRMD & CSR_CRMD_PLV; ++ ++ /* Check access rights */ ++ if (!(n ? tlb->V1 : tlb->V0)) { ++ return TLBRET_INVALID; ++ } ++ ++ if (rw == MMU_INST_FETCH && (n ? tlb->XI1 : tlb->XI0)) { ++ return TLBRET_XI; ++ } ++ ++ if (rw == MMU_DATA_LOAD && (n ? tlb->RI1 : tlb->RI0)) { ++ return TLBRET_RI; ++ } ++ ++ if (plv > (n ? tlb->PLV1 : tlb->PLV0)) { ++ return TLBRET_PE; ++ } ++ ++ if (rw != MMU_DATA_STORE || (n ? tlb->WE1 : tlb->WE0)) { ++ /* PPN address ++ * 4 KB: [47:13] [12;0] ++ * 16 KB: [47:15] [14:0] ++ */ ++ if (n) { ++ *physical = tlb->PPN1 | (address & (mask >> 1)); ++ } else { ++ *physical = tlb->PPN0 | (address & (mask >> 1)); ++ } ++ *prot = PAGE_READ; ++ if (n ? tlb->WE1 : tlb->WE0) { ++ *prot |= PAGE_WRITE; ++ } ++ if (!(n ? tlb->XI1 : tlb->XI0)) { ++ *prot |= PAGE_EXEC; ++ } ++ return TLBRET_MATCH; ++ } ++ ++ return TLBRET_DIRTY; ++} ++ ++/* Loongarch 3A5K -style MMU emulation */ ++int ls3a5k_map_address(CPULOONGARCHState *env, hwaddr *physical, int *prot, ++ target_ulong address, int rw, int access_type) ++{ ++ uint16_t asid = env->CSR_ASID & 0x3ff; ++ int i; ++ ls3a5k_tlb_t *tlb; ++ ++ int ftlb_size = env->tlb->mmu.ls3a5k.ftlb_size; ++ int vtlb_size = env->tlb->mmu.ls3a5k.vtlb_size; ++ ++ int ftlb_idx; ++ ++ uint64_t mask; ++ uint64_t vpn; /* address to map */ ++ uint64_t tag; /* address in TLB entry */ ++ ++ /* search VTLB */ ++ for (i = ftlb_size; i < ftlb_size + vtlb_size; ++i) { ++ tlb = &env->tlb->mmu.ls3a5k.tlb[i]; ++ mask = tlb->PageMask; ++ ++ vpn = address & 0xffffffffe000 & ~mask; ++ tag = tlb->VPN & ~mask; ++ ++ if ((tlb->G == 1 || tlb->ASID == asid) ++ && vpn == tag ++ && tlb->EHINV != 1) ++ { ++ return ls3a5k_map_address_tlb_entry(env, physical, prot, ++ address, rw, access_type, tlb); ++ } ++ } ++ ++ if (ftlb_size == 0) { ++ return TLBRET_NOMATCH; ++ } ++ ++ /* search FTLB */ ++ mask = env->tlb->mmu.ls3a5k.ftlb_mask; ++ vpn = address & 0xffffffffe000 & ~mask; ++ ++ ftlb_idx = (address & 0xffffffffc000) >> 15; /* 16 KB */ ++ ftlb_idx = ftlb_idx & 0xff; /* [0,255] */ ++ ++ for (i = 0; i < 8; ++i) { ++ /* ---------- set 0 1 2 ... 7 ++ * ftlb_idx ----------------------------------- ++ * 0 | 0 1 2 ... 7 ++ * 1 | 8 9 10 ... 15 ++ * 2 | 16 17 18 ... 23 ++ * ... | ++ * 255 | 2040 2041 2042 ... 2047 ++ */ ++ tlb = &env->tlb->mmu.ls3a5k.tlb[ftlb_idx * 8 + i]; ++ tag = tlb->VPN & ~mask; ++ ++ if ((tlb->G == 1 || tlb->ASID == asid) ++ && vpn == tag ++ && tlb->EHINV != 1) ++ { ++ return ls3a5k_map_address_tlb_entry(env, physical, prot, ++ address, rw, access_type, tlb); ++ } ++ } ++ ++ return TLBRET_NOMATCH; ++} ++ ++static int get_physical_address(CPULOONGARCHState *env, hwaddr *physical, ++ int *prot, target_ulong real_address, ++ int rw, int access_type, int mmu_idx) ++{ ++ int user_mode = mmu_idx == LARCH_HFLAG_UM; ++ int kernel_mode = !user_mode; ++ unsigned plv, base_c, base_v, tmp; ++ ++ /* effective address (modified for KVM T&E kernel segments) */ ++ target_ulong address = real_address; ++ ++ /* Check PG */ ++ if (!(env->CSR_CRMD & CSR_CRMD_PG)) { ++ /* DA mode */ ++ *physical = address & 0xffffffffffffUL; ++ *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; ++ return TLBRET_MATCH; ++ } ++ ++ plv = kernel_mode | (user_mode << 3); ++ base_v = address >> CSR_DMW_BASE_SH; ++ /* Check direct map window 0 */ ++ base_c = env->CSR_DMWIN0 >> CSR_DMW_BASE_SH; ++ if ((plv & env->CSR_DMWIN0) && (base_c == base_v)) { ++ *physical = dmwin_va2pa(address); ++ *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; ++ return TLBRET_MATCH; ++ } ++ /* Check direct map window 1 */ ++ base_c = env->CSR_DMWIN1 >> CSR_DMW_BASE_SH; ++ if ((plv & env->CSR_DMWIN1) && (base_c == base_v)) { ++ *physical = dmwin_va2pa(address); ++ *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; ++ return TLBRET_MATCH; ++ } ++ /* Check valid extension */ ++ tmp = address >> 47; ++ if (!(tmp == 0 || tmp == 0x1ffff)) { ++ return TLBRET_BADADDR; ++ } ++ /* mapped address */ ++ return env->tlb->map_address(env, physical, prot, real_address, rw, ++ access_type); ++} ++ ++void cpu_loongarch_tlb_flush(CPULOONGARCHState *env) ++{ ++ LOONGARCHCPU *cpu = loongarch_env_get_cpu(env); ++ ++ /* Flush qemu's TLB and discard all shadowed entries. */ ++ tlb_flush(CPU(cpu)); ++ env->tlb->tlb_in_use = env->tlb->nb_tlb; ++} ++#endif ++ ++static void raise_mmu_exception(CPULOONGARCHState *env, target_ulong address, ++ int rw, int tlb_error) ++{ ++ CPUState *cs = CPU(loongarch_env_get_cpu(env)); ++ int exception = 0, error_code = 0; ++ ++ if (rw == MMU_INST_FETCH) { ++ error_code |= EXCP_INST_NOTAVAIL; ++ } ++ ++ switch (tlb_error) { ++ default: ++ case TLBRET_BADADDR: ++ /* Reference to kernel address from user mode or supervisor mode */ ++ /* Reference to supervisor address from user mode */ ++ if (rw == MMU_DATA_STORE) { ++ exception = EXCP_AdES; ++ } else { ++ exception = EXCP_AdEL; ++ } ++ break; ++ case TLBRET_NOMATCH: ++ /* No TLB match for a mapped address */ ++ if (rw == MMU_DATA_STORE) { ++ exception = EXCP_TLBS; ++ } else { ++ exception = EXCP_TLBL; ++ } ++ error_code |= EXCP_TLB_NOMATCH; ++ break; ++ case TLBRET_INVALID: ++ /* TLB match with no valid bit */ ++ if (rw == MMU_DATA_STORE) { ++ exception = EXCP_TLBS; ++ } else { ++ exception = EXCP_TLBL; ++ } ++ break; ++ case TLBRET_DIRTY: ++ /* TLB match but 'D' bit is cleared */ ++ exception = EXCP_LTLBL; ++ break; ++ case TLBRET_XI: ++ /* Execute-Inhibit Exception */ ++ exception = EXCP_TLBXI; ++ break; ++ case TLBRET_RI: ++ /* Read-Inhibit Exception */ ++ exception = EXCP_TLBRI; ++ break; ++ case TLBRET_PE: ++ /* Privileged Exception */ ++ exception = EXCP_TLBPE; ++ break; ++ } ++ ++ if (env->insn_flags & INSN_LOONGARCH) { ++ if (tlb_error == TLBRET_NOMATCH) { ++ env->CSR_TLBRBADV = address; ++ env->CSR_TLBREHI = address & (TARGET_PAGE_MASK << 1); ++ cs->exception_index = exception; ++ env->error_code = error_code; ++ return; ++ } ++ } ++ ++ /* Raise exception */ ++ env->CSR_BADV = address; ++ cs->exception_index = exception; ++ env->error_code = error_code; ++ ++ if (env->insn_flags & INSN_LOONGARCH) { ++ env->CSR_TLBEHI = address & (TARGET_PAGE_MASK << 1); ++ } ++} ++ ++bool loongarch_cpu_tlb_fill(CPUState *cs, vaddr address, int size, ++ MMUAccessType access_type, int mmu_idx, ++ bool probe, uintptr_t retaddr) ++{ ++ LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); ++ CPULOONGARCHState *env = &cpu->env; ++#if !defined(CONFIG_USER_ONLY) ++ hwaddr physical; ++ int prot; ++ int loongarch_access_type; ++#endif ++ int ret = TLBRET_BADADDR; ++ ++ qemu_log_mask(CPU_LOG_MMU, ++ "%s pc " TARGET_FMT_lx " ad %" VADDR_PRIx " mmu_idx %d\n", ++ __func__, env->active_tc.PC, address, mmu_idx); ++ ++ /* data access */ ++#if !defined(CONFIG_USER_ONLY) ++ /* XXX: put correct access by using cpu_restore_state() correctly */ ++ loongarch_access_type = ACCESS_INT; ++ ret = get_physical_address(env, &physical, &prot, address, ++ access_type, loongarch_access_type, mmu_idx); ++ switch (ret) { ++ case TLBRET_MATCH: ++ qemu_log_mask(CPU_LOG_MMU, ++ "%s address=%" VADDR_PRIx " physical " TARGET_FMT_plx ++ " prot %d asid %ld pc 0x%lx\n", ++ __func__, address, physical, prot, ++ env->CSR_ASID, env->active_tc.PC); ++ break; ++ default: ++ qemu_log_mask(CPU_LOG_MMU, ++ "%s address=%" VADDR_PRIx " ret %d asid %ld pc 0x%lx\n", ++ __func__, address, ret, env->CSR_ASID, env->active_tc.PC); ++ break; ++ } ++ if (ret == TLBRET_MATCH) { ++ tlb_set_page(cs, address & TARGET_PAGE_MASK, ++ physical & TARGET_PAGE_MASK, prot | PAGE_EXEC, ++ mmu_idx, TARGET_PAGE_SIZE); ++ ret = true; ++ } ++ if (probe) { ++ return false; ++ } ++#endif ++ ++ raise_mmu_exception(env, address, access_type, ret); ++ do_raise_exception_err(env, cs->exception_index, env->error_code, retaddr); ++} ++ ++#if !defined(CONFIG_USER_ONLY) ++hwaddr cpu_loongarch_translate_address(CPULOONGARCHState *env, ++ target_ulong address, int rw) ++{ ++ hwaddr physical; ++ int prot; ++ int access_type; ++ int ret = 0; ++ ++ /* data access */ ++ access_type = ACCESS_INT; ++ ret = get_physical_address(env, &physical, &prot, address, rw, access_type, ++ cpu_mmu_index(env, false)); ++ if (ret != TLBRET_MATCH) { ++ raise_mmu_exception(env, address, rw, ret); ++ return -1LL; ++ } else { ++ return physical; ++ } ++} ++ ++static const char * const excp_names[EXCP_LAST + 1] = { ++ [EXCP_RESET] = "reset", ++ [EXCP_SRESET] = "soft reset", ++ [EXCP_NMI] = "non-maskable interrupt", ++ [EXCP_EXT_INTERRUPT] = "interrupt", ++ [EXCP_AdEL] = "address error load", ++ [EXCP_AdES] = "address error store", ++ [EXCP_TLBF] = "TLB refill", ++ [EXCP_IBE] = "instruction bus error", ++ [EXCP_SYSCALL] = "syscall", ++ [EXCP_BREAK] = "break", ++ [EXCP_FPDIS] = "float unit unusable", ++ [EXCP_LSXDIS] = "vector128 unusable", ++ [EXCP_LASXDIS] = "vector256 unusable", ++ [EXCP_RI] = "reserved instruction", ++ [EXCP_OVERFLOW] = "arithmetic overflow", ++ [EXCP_TRAP] = "trap", ++ [EXCP_FPE] = "floating point", ++ [EXCP_LTLBL] = "TLB modify", ++ [EXCP_TLBL] = "TLB load", ++ [EXCP_TLBS] = "TLB store", ++ [EXCP_DBE] = "data bus error", ++ [EXCP_TLBXI] = "TLB execute-inhibit", ++ [EXCP_TLBRI] = "TLB read-inhibit", ++ [EXCP_TLBPE] = "TLB priviledged error", ++}; ++#endif ++ ++target_ulong exception_resume_pc(CPULOONGARCHState *env) ++{ ++ target_ulong bad_pc; ++ ++ bad_pc = env->active_tc.PC; ++ if (env->hflags & LARCH_HFLAG_BMASK) { ++ /* If the exception was raised from a delay slot, come back to ++ the jump. */ ++ bad_pc -= 4; ++ } ++ ++ return bad_pc; ++} ++ ++#if !defined(CONFIG_USER_ONLY) ++static void set_hflags_for_handler (CPULOONGARCHState *env) ++{ ++ /* Exception handlers are entered in 32-bit mode. */ ++} ++ ++static inline void set_badinstr_registers(CPULOONGARCHState *env) ++{ ++ if ((env->insn_flags & INSN_LOONGARCH)) { ++ env->CSR_BADI = cpu_ldl_code(env, env->active_tc.PC); ++ return; ++ } ++} ++#endif ++ ++static inline unsigned int get_vint_size(CPULOONGARCHState *env) ++{ ++ unsigned int size = 0; ++ ++ switch ((env->CSR_ECFG >> 16) & 0x7) { ++ case 0: ++ break; ++ case 1: ++ size = 2 * 4; /* #Insts * inst_size */ ++ break; ++ case 2: ++ size = 4 * 4; ++ break; ++ case 3: ++ size = 8 * 4; ++ break; ++ case 4: ++ size = 16 * 4; ++ break; ++ case 5: ++ size = 32 * 4; ++ break; ++ case 6: ++ size = 64 * 4; ++ break; ++ case 7: ++ size = 128 * 4; ++ break; ++ default: ++ printf("%s: unexpected value", __func__); ++ assert(0); ++ } ++ ++ return size; ++} ++ ++#define is_refill(cs, env) (((cs->exception_index == EXCP_TLBL) \ ++ || (cs->exception_index == EXCP_TLBS)) \ ++ && (env->error_code & EXCP_TLB_NOMATCH)) ++ ++void loongarch_cpu_do_interrupt(CPUState *cs) ++{ ++#if !defined(CONFIG_USER_ONLY) ++ LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); ++ CPULOONGARCHState *env = &cpu->env; ++ bool update_badinstr = 0; ++ int cause = -1; ++ const char *name; ++ ++ if (qemu_loglevel_mask(CPU_LOG_INT) ++ && cs->exception_index != EXCP_EXT_INTERRUPT) { ++ if (cs->exception_index < 0 || cs->exception_index > EXCP_LAST) { ++ name = "unknown"; ++ } else { ++ name = excp_names[cs->exception_index]; ++ } ++ ++ qemu_log("%s enter: PC " TARGET_FMT_lx " ERA " TARGET_FMT_lx ++ " TLBRERA 0x%016lx" " %s exception\n", __func__, ++ env->active_tc.PC, env->CSR_ERA, env->CSR_TLBRERA, name); ++ } ++ ++ switch (cs->exception_index) { ++ case EXCP_RESET: ++ cpu_reset(CPU(cpu)); ++ break; ++ case EXCP_NMI: ++ env->CSR_ERRERA = exception_resume_pc(env); ++ env->hflags &= ~LARCH_HFLAG_BMASK; ++ env->hflags |= LARCH_HFLAG_64; ++ env->hflags &= ~LARCH_HFLAG_AWRAP; ++ env->hflags &= ~(LARCH_HFLAG_KSU); ++ env->active_tc.PC = env->exception_base; ++ set_hflags_for_handler(env); ++ break; ++ case EXCP_EXT_INTERRUPT: ++ cause = 0; ++ goto set_ERA; ++ case EXCP_LTLBL: ++ cause = 1; ++ update_badinstr = !(env->error_code & EXCP_INST_NOTAVAIL); ++ goto set_ERA; ++ case EXCP_TLBL: ++ cause = 2; ++ update_badinstr = !(env->error_code & EXCP_INST_NOTAVAIL); ++ goto set_ERA; ++ case EXCP_TLBS: ++ cause = 3; ++ update_badinstr = 1; ++ goto set_ERA; ++ case EXCP_AdEL: ++ cause = 4; ++ update_badinstr = !(env->error_code & EXCP_INST_NOTAVAIL); ++ goto set_ERA; ++ case EXCP_AdES: ++ cause = 5; ++ update_badinstr = 1; ++ goto set_ERA; ++ case EXCP_IBE: ++ cause = 6; ++ goto set_ERA; ++ case EXCP_DBE: ++ cause = 7; ++ goto set_ERA; ++ case EXCP_SYSCALL: ++ cause = 8; ++ update_badinstr = 1; ++ goto set_ERA; ++ case EXCP_BREAK: ++ cause = 9; ++ update_badinstr = 1; ++ goto set_ERA; ++ case EXCP_RI: ++ cause = 10; ++ update_badinstr = 1; ++ goto set_ERA; ++ case EXCP_FPDIS: ++ case EXCP_LSXDIS: ++ case EXCP_LASXDIS: ++ cause = 11; ++ update_badinstr = 1; ++ goto set_ERA; ++ case EXCP_OVERFLOW: ++ cause = 12; ++ update_badinstr = 1; ++ goto set_ERA; ++ case EXCP_TRAP: ++ cause = 13; ++ update_badinstr = 1; ++ goto set_ERA; ++ case EXCP_FPE: ++ cause = 15; ++ update_badinstr = 1; ++ goto set_ERA; ++ case EXCP_TLBRI: ++ cause = 19; ++ update_badinstr = 1; ++ goto set_ERA; ++ case EXCP_TLBXI: ++ case EXCP_TLBPE: ++ cause = 20; ++ goto set_ERA; ++ set_ERA: ++ if (is_refill(cs, env)) { ++ env->CSR_TLBRERA = exception_resume_pc(env); ++ env->CSR_TLBRERA |= 1; ++ } else { ++ env->CSR_ERA = exception_resume_pc(env); ++ } ++ ++ if (update_badinstr) { ++ set_badinstr_registers(env); ++ } ++ env->hflags &= ~(LARCH_HFLAG_KSU); ++ ++ env->hflags &= ~LARCH_HFLAG_BMASK; ++ if (env->insn_flags & INSN_LOONGARCH) { ++ /* save PLV and IE */ ++ if (is_refill(cs, env)) { ++ env->CSR_TLBRPRMD &= (~0x7); ++ env->CSR_TLBRPRMD |= (env->CSR_CRMD & 0x7); ++ } else { ++ env->CSR_PRMD &= (~0x7); ++ env->CSR_PRMD |= (env->CSR_CRMD & 0x7); ++ } ++ ++ env->CSR_CRMD &= ~(0x7); ++ ++ switch (cs->exception_index) { ++ case EXCP_EXT_INTERRUPT: ++ break; ++ case EXCP_TLBL: ++ if (env->error_code & EXCP_INST_NOTAVAIL) { ++ cause = EXCCODE_TLBI; ++ } else { ++ cause = EXCCODE_TLBL; ++ } ++ break; ++ case EXCP_TLBS: ++ cause = EXCCODE_TLBS; ++ break; ++ case EXCP_LTLBL: ++ cause = EXCCODE_MOD; ++ break; ++ case EXCP_TLBRI: ++ cause = EXCCODE_TLBRI; ++ break; ++ case EXCP_TLBXI: ++ cause = EXCCODE_TLBXI; ++ break; ++ case EXCP_TLBPE: ++ cause = EXCCODE_TLBPE; ++ break; ++ case EXCP_AdEL: ++ case EXCP_AdES: ++ case EXCP_IBE: ++ case EXCP_DBE: ++ cause = EXCCODE_ADE; ++ break; ++ case EXCP_SYSCALL: ++ cause = EXCCODE_SYS; ++ break; ++ case EXCP_BREAK: ++ cause = EXCCODE_BP; ++ break; ++ case EXCP_RI: ++ cause = EXCCODE_RI; ++ break; ++ case EXCP_FPDIS: ++ cause = EXCCODE_FPDIS; ++ break; ++ case EXCP_LSXDIS: ++ cause = EXCCODE_LSXDIS; ++ break; ++ case EXCP_LASXDIS: ++ cause = EXCCODE_LASXDIS; ++ break; ++ case EXCP_FPE: ++ cause = EXCCODE_FPE; ++ break; ++ default: ++ printf("Error: exception(%d) '%s' has not been supported\n", ++ cs->exception_index, excp_names[cs->exception_index]); ++ abort(); ++ } ++ ++ uint32_t vec_size = get_vint_size(env); ++ env->active_tc.PC = env->CSR_EEPN; ++ env->active_tc.PC += cause * vec_size; ++ if (is_refill(cs, env)) { ++ /* TLB Refill */ ++ env->active_tc.PC = env->CSR_TLBRENT; ++ break; /* Do not modify excode */ ++ } ++ if (cs->exception_index == EXCP_EXT_INTERRUPT) { ++ /* Interrupt */ ++ uint32_t vector = 0; ++ uint32_t pending = env->CSR_ESTAT & CSR_ESTAT_IPMASK; ++ pending &= env->CSR_ECFG & CSR_ECFG_IPMASK; ++ ++ /* Find the highest-priority interrupt. */ ++ while (pending >>= 1) { ++ vector++; ++ } ++ env->active_tc.PC = env->CSR_EEPN + ++ (EXCODE_IP + vector) * vec_size; ++ if (qemu_loglevel_mask(CPU_LOG_INT)) { ++ qemu_log("%s: PC " TARGET_FMT_lx " ERA " TARGET_FMT_lx ++ " cause %d\n" " A " TARGET_FMT_lx " D " ++ TARGET_FMT_lx " vector = %d ExC %08lx ExS %08lx\n", ++ __func__, env->active_tc.PC, env->CSR_ERA, ++ cause, env->CSR_BADV, env->CSR_DERA, vector, ++ env->CSR_ECFG, env->CSR_ESTAT); ++ } ++ } ++ /* Excode */ ++ env->CSR_ESTAT = (env->CSR_ESTAT & ~(0x1f << CSR_ESTAT_EXC_SH)) | ++ (cause << CSR_ESTAT_EXC_SH); ++ } ++ set_hflags_for_handler(env); ++ break; ++ default: ++ abort(); ++ } ++ if (qemu_loglevel_mask(CPU_LOG_INT) ++ && cs->exception_index != EXCP_EXT_INTERRUPT) { ++ qemu_log("%s: PC " TARGET_FMT_lx " ERA 0x%08lx" " cause %d%s\n" ++ " ESTAT %08lx EXCFG 0x%08lx BADVA 0x%08lx BADI 0x%08lx \ ++ SYS_NUM %lu cpu %d asid 0x%lx" "\n", ++ __func__, env->active_tc.PC, ++ is_refill(cs, env) ? env->CSR_TLBRERA : env->CSR_ERA, ++ cause, ++ is_refill(cs, env) ? "(refill)" : "", ++ env->CSR_ESTAT, env->CSR_ECFG, ++ is_refill(cs, env) ? env->CSR_TLBRBADV : env->CSR_BADV, ++ env->CSR_BADI, env->active_tc.gpr[11], cs->cpu_index, ++ env->CSR_ASID ++ ); ++ } ++#endif ++ cs->exception_index = EXCP_NONE; ++} ++ ++bool loongarch_cpu_exec_interrupt(CPUState *cs, int interrupt_request) ++{ ++ if (interrupt_request & CPU_INTERRUPT_HARD) { ++ LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); ++ CPULOONGARCHState *env = &cpu->env; ++ ++ if (cpu_loongarch_hw_interrupts_enabled(env) && ++ cpu_loongarch_hw_interrupts_pending(env)) { ++ /* Raise it */ ++ cs->exception_index = EXCP_EXT_INTERRUPT; ++ env->error_code = 0; ++ loongarch_cpu_do_interrupt(cs); ++ return true; ++ } ++ } ++ return false; ++} ++ ++void QEMU_NORETURN do_raise_exception_err(CPULOONGARCHState *env, ++ uint32_t exception, ++ int error_code, ++ uintptr_t pc) ++{ ++ CPUState *cs = CPU(loongarch_env_get_cpu(env)); ++ ++ qemu_log_mask(CPU_LOG_INT, "%s: %d %d\n", ++ __func__, exception, error_code); ++ cs->exception_index = exception; ++ env->error_code = error_code; ++ ++ cpu_loop_exit_restore(cs, pc); ++} +diff --git a/target/loongarch64/helper.h b/target/loongarch64/helper.h +new file mode 100644 +index 0000000000..ff2026ed82 +--- /dev/null ++++ b/target/loongarch64/helper.h +@@ -0,0 +1,168 @@ ++DEF_HELPER_3(raise_exception_err, noreturn, env, i32, int) ++DEF_HELPER_2(raise_exception, noreturn, env, i32) ++DEF_HELPER_1(raise_exception_debug, noreturn, env) ++ ++#if 0 ++#ifndef CONFIG_USER_ONLY ++DEF_HELPER_3(ll, tl, env, tl, int) ++DEF_HELPER_3(lld, tl, env, tl, int) ++#endif ++#endif ++ ++DEF_HELPER_FLAGS_1(bitswap, TCG_CALL_NO_RWG_SE, tl, tl) ++DEF_HELPER_FLAGS_1(dbitswap, TCG_CALL_NO_RWG_SE, tl, tl) ++ ++DEF_HELPER_3(crc32, tl, tl, tl, i32) ++DEF_HELPER_3(crc32c, tl, tl, tl, i32) ++ ++#ifndef CONFIG_USER_ONLY ++/* LoongISA CSR register */ ++DEF_HELPER_2(csr_rdq, tl, env, i64) ++DEF_HELPER_3(csr_wrq, tl, env, tl, i64) ++DEF_HELPER_4(csr_xchgq, tl, env, tl, tl, i64) ++ ++#endif /* !CONFIG_USER_ONLY */ ++ ++/* CP1 functions */ ++DEF_HELPER_2(movfcsr2gr, tl, env, i32) ++DEF_HELPER_4(movgr2fcsr, void, env, tl, i32, i32) ++ ++DEF_HELPER_2(float_cvtd_s, i64, env, i32) ++DEF_HELPER_2(float_cvtd_w, i64, env, i32) ++DEF_HELPER_2(float_cvtd_l, i64, env, i64) ++DEF_HELPER_2(float_cvts_d, i32, env, i64) ++DEF_HELPER_2(float_cvts_w, i32, env, i32) ++DEF_HELPER_2(float_cvts_l, i32, env, i64) ++ ++DEF_HELPER_FLAGS_2(float_class_s, TCG_CALL_NO_RWG_SE, i32, env, i32) ++DEF_HELPER_FLAGS_2(float_class_d, TCG_CALL_NO_RWG_SE, i64, env, i64) ++ ++#define FOP_PROTO(op) \ ++DEF_HELPER_4(float_ ## op ## _s, i32, env, i32, i32, i32) \ ++DEF_HELPER_4(float_ ## op ## _d, i64, env, i64, i64, i64) ++FOP_PROTO(maddf) ++FOP_PROTO(msubf) ++FOP_PROTO(nmaddf) ++FOP_PROTO(nmsubf) ++#undef FOP_PROTO ++ ++#define FOP_PROTO(op) \ ++DEF_HELPER_3(float_ ## op ## _s, i32, env, i32, i32) \ ++DEF_HELPER_3(float_ ## op ## _d, i64, env, i64, i64) ++FOP_PROTO(max) ++FOP_PROTO(maxa) ++FOP_PROTO(min) ++FOP_PROTO(mina) ++#undef FOP_PROTO ++ ++#define FOP_PROTO(op) \ ++DEF_HELPER_2(float_ ## op ## _l_s, i64, env, i32) \ ++DEF_HELPER_2(float_ ## op ## _l_d, i64, env, i64) \ ++DEF_HELPER_2(float_ ## op ## _w_s, i32, env, i32) \ ++DEF_HELPER_2(float_ ## op ## _w_d, i32, env, i64) ++FOP_PROTO(cvt) ++FOP_PROTO(round) ++FOP_PROTO(trunc) ++FOP_PROTO(ceil) ++FOP_PROTO(floor) ++#undef FOP_PROTO ++ ++#define FOP_PROTO(op) \ ++DEF_HELPER_2(float_ ## op ## _s, i32, env, i32) \ ++DEF_HELPER_2(float_ ## op ## _d, i64, env, i64) ++FOP_PROTO(sqrt) ++FOP_PROTO(rsqrt) ++FOP_PROTO(recip) ++FOP_PROTO(rint) ++#undef FOP_PROTO ++ ++#define FOP_PROTO(op) \ ++DEF_HELPER_1(float_ ## op ## _s, i32, i32) \ ++DEF_HELPER_1(float_ ## op ## _d, i64, i64) ++FOP_PROTO(abs) ++FOP_PROTO(chs) ++#undef FOP_PROTO ++ ++#define FOP_PROTO(op) \ ++DEF_HELPER_3(float_ ## op ## _s, i32, env, i32, i32) \ ++DEF_HELPER_3(float_ ## op ## _d, i64, env, i64, i64) ++FOP_PROTO(add) ++FOP_PROTO(sub) ++FOP_PROTO(mul) ++FOP_PROTO(div) ++#undef FOP_PROTO ++ ++#define FOP_PROTO(op) \ ++DEF_HELPER_3(cmp_d_ ## op, i64, env, i64, i64) \ ++DEF_HELPER_3(cmp_s_ ## op, i32, env, i32, i32) ++FOP_PROTO(af) ++FOP_PROTO(un) ++FOP_PROTO(eq) ++FOP_PROTO(ueq) ++FOP_PROTO(lt) ++FOP_PROTO(ult) ++FOP_PROTO(le) ++FOP_PROTO(ule) ++FOP_PROTO(saf) ++FOP_PROTO(sun) ++FOP_PROTO(seq) ++FOP_PROTO(sueq) ++FOP_PROTO(slt) ++FOP_PROTO(sult) ++FOP_PROTO(sle) ++FOP_PROTO(sule) ++FOP_PROTO(or) ++FOP_PROTO(une) ++FOP_PROTO(ne) ++FOP_PROTO(sor) ++FOP_PROTO(sune) ++FOP_PROTO(sne) ++#undef FOP_PROTO ++ ++/* Special functions */ ++#ifndef CONFIG_USER_ONLY ++DEF_HELPER_1(tlbwr, void, env) ++DEF_HELPER_1(tlbfill, void, env) ++DEF_HELPER_1(tlbsrch, void, env) ++DEF_HELPER_1(tlbrd, void, env) ++DEF_HELPER_1(tlbclr, void, env) ++DEF_HELPER_1(tlbflush, void, env) ++DEF_HELPER_4(invtlb, void, env, tl, tl, tl) ++DEF_HELPER_1(ertn, void, env) ++DEF_HELPER_5(lddir, void, env, tl, tl, tl, i32) ++DEF_HELPER_4(ldpte, void, env, tl, tl, i32) ++DEF_HELPER_3(drdtime, void, env, tl, tl) ++DEF_HELPER_1(read_pgd, tl, env) ++#endif /* !CONFIG_USER_ONLY */ ++DEF_HELPER_2(cpucfg, tl, env, tl) ++DEF_HELPER_1(idle, void, env) ++ ++DEF_HELPER_3(float_exp2_s, i32, env, i32, i32) ++DEF_HELPER_3(float_exp2_d, i64, env, i64, i64) ++DEF_HELPER_2(float_logb_s, i32, env, i32) ++DEF_HELPER_2(float_logb_d, i64, env, i64) ++DEF_HELPER_3(movreg2cf, void, env, i32, tl) ++DEF_HELPER_2(movcf2reg, tl, env, i32) ++DEF_HELPER_3(movreg2cf_i32, void, env, i32, i32) ++DEF_HELPER_3(movreg2cf_i64, void, env, i32, i64) ++ ++DEF_HELPER_2(cto_w, tl, env, tl) ++DEF_HELPER_2(ctz_w, tl, env, tl) ++DEF_HELPER_2(cto_d, tl, env, tl) ++DEF_HELPER_2(ctz_d, tl, env, tl) ++DEF_HELPER_2(bitrev_w, tl, env, tl) ++DEF_HELPER_2(bitrev_d, tl, env, tl) ++ ++DEF_HELPER_2(load_scr, i64, env, i32) ++DEF_HELPER_3(store_scr, void, env, i32, i64) ++ ++DEF_HELPER_3(asrtle_d, void, env, tl, tl) ++DEF_HELPER_3(asrtgt_d, void, env, tl, tl) ++ ++DEF_HELPER_4(fsel, i64, env, i64, i64, i32) ++ ++#ifndef CONFIG_USER_ONLY ++DEF_HELPER_4(iocsr, void, env, tl, tl, i32) ++#endif ++DEF_HELPER_3(memtrace_addr, void, env, tl, i32) ++DEF_HELPER_2(memtrace_val, void, env, tl) +diff --git a/target/loongarch64/insn.decode b/target/loongarch64/insn.decode +new file mode 100644 +index 0000000000..f194f70116 +--- /dev/null ++++ b/target/loongarch64/insn.decode +@@ -0,0 +1,514 @@ ++# Fields ++%sd 0:2 ++%rj 5:5 ++%rd 0:5 ++%sj 5:2 ++%ptr 5:3 ++%rk 10:5 ++%sa2 15:2 ++%sa3 15:3 ++%si5 10:s5 ++%code 0:15 ++%cond 10:4 ++%cond2 0:4 ++%ui5 10:5 ++%ui6 10:6 ++%ui3 10:3 ++%ui4 10:4 ++%op 5:5 ++%ui8 10:8 ++%msbw 16:5 ++%lsbw 10:5 ++%msbd 16:6 ++%lsbd 10:6 ++%fd 0:5 ++%fj 5:5 ++%fk 10:5 ++%fcsrd 0:5 ++%fcsrs 5:5 ++%cd 0:3 ++%cj 5:3 ++%si12 10:s12 ++%ui12 10:12 ++%csr 10:14 ++%cop 0:5 ++%level 10:8 ++%seq 10:8 ++%whint 0:15 ++%addr 10:5 ++%info 5:5 ++%invop 0:5 ++%fa 15:5 ++%vd 0:5 ++%vj 5:5 ++%vk 10:5 ++%va 15:5 ++%xd 0:5 ++%xj 5:5 ++%xk 10:5 ++%xa 15:5 ++%fcond 15:5 ++%ca 15:3 ++%vui5 15:5 ++%si16 10:s16 ++%si20 5:s20 ++%si14 10:s14 ++%hint 0:5 ++%si9 10:s9 ++%si10 10:s10 ++%si11 10:s11 ++%si8 10:s8 ++%idx1 18:1 ++%idx2 18:2 ++%idx3 18:3 ++%idx4 18:4 ++%idx 18:5 ++%offs21 0:s5 10:16 ++%offs16 10:s16 ++%offs 0:s10 10:16 ++%mode 5:5 ++%ui2 10:2 ++%ui1 10:1 ++%ui7 10:7 ++%i13 5:13 ++ ++# Argument sets ++&fmt_sdrj sd rj ++&fmt_rdsj rd sj ++&fmt_rdrj rd rj ++&fmt_empty ++&fmt_rjrk rj rk ++&fmt_rdrjrksa2 rd rj rk sa2 ++&fmt_rdrjrksa3 rd rj rk sa3 ++&fmt_rdrjrk rd rj rk ++&fmt_code code ++&fmt_rdrjui5 rd rj ui5 ++&fmt_rdrjui6 rd rj ui6 ++&fmt_rdrjmsbwlsbw rd rj msbw lsbw ++&fmt_rdrjmsbdlsbd rd rj msbd lsbd ++&fmt_fdfjfk fd fj fk ++&fmt_fdfj fd fj ++&fmt_fdrj fd rj ++&fmt_rdfj rd fj ++&fmt_fcsrdrj fcsrd rj ++&fmt_rdfcsrs rd fcsrs ++&fmt_cdfj cd fj ++&fmt_fdcj fd cj ++&fmt_cdrj cd rj ++&fmt_rdcj rd cj ++&fmt_rdrjsi12 rd rj si12 ++&fmt_rdrjui12 rd rj ui12 ++&fmt_rdrjcsr rd rj csr ++&fmt_coprjsi12 cop rj si12 ++&fmt_rdrjlevel rd rj level ++&fmt_rjseq rj seq ++&fmt_whint whint ++&fmt_invtlb addr info invop ++&fmt_fdfjfkfa fd fj fk fa ++&fmt_cdfjfkfcond cd fj fk fcond ++&fmt_fdfjfkca fd fj fk ca ++&fmt_rdrjsi16 rd rj si16 ++&fmt_rdsi20 rd si20 ++&fmt_rdrjsi14 rd rj si14 ++&fmt_hintrjsi12 hint rj si12 ++&fmt_fdrjsi12 fd rj si12 ++&fmt_fdrjrk fd rj rk ++&fmt_rjoffs21 rj offs21 ++&fmt_cjoffs21 cj offs21 ++&fmt_rdrjoffs16 rd rj offs16 ++&fmt_offs offs ++&fmt_rjrdoffs16 rj rd offs16 ++ ++# Formats ++@fmt_sdrj .... ........ ..... ..... ..... ... .. &fmt_sdrj %sd %rj ++@fmt_rdsj .... ........ ..... ..... ... .. ..... &fmt_rdsj %rd %sj ++@fmt_rdrj .... ........ ..... ..... ..... ..... &fmt_rdrj %rd %rj ++@fmt_empty .... ........ ..... ..... ..... ..... &fmt_empty ++@fmt_rjrk .... ........ ..... ..... ..... ..... &fmt_rjrk %rj %rk ++@fmt_rdrjrksa2 .... ........ ... .. ..... ..... ..... &fmt_rdrjrksa2 %rd %rj %rk %sa2 ++@fmt_rdrjrksa3 .... ........ .. ... ..... ..... ..... &fmt_rdrjrksa3 %rd %rj %rk %sa3 ++@fmt_rdrjrk .... ........ ..... ..... ..... ..... &fmt_rdrjrk %rd %rj %rk ++@fmt_code .... ........ ..... ............... &fmt_code %code ++@fmt_rdrjui5 .... ........ ..... ..... ..... ..... &fmt_rdrjui5 %rd %rj %ui5 ++@fmt_rdrjui6 .... ........ .... ...... ..... ..... &fmt_rdrjui6 %rd %rj %ui6 ++@fmt_rdrjmsbwlsbw .... ....... ..... . ..... ..... ..... &fmt_rdrjmsbwlsbw %rd %rj %msbw %lsbw ++@fmt_rdrjmsbdlsbd .... ...... ...... ...... ..... ..... &fmt_rdrjmsbdlsbd %rd %rj %msbd %lsbd ++@fmt_fdfjfk .... ........ ..... ..... ..... ..... &fmt_fdfjfk %fd %fj %fk ++@fmt_fdfj .... ........ ..... ..... ..... ..... &fmt_fdfj %fd %fj ++@fmt_fdrj .... ........ ..... ..... ..... ..... &fmt_fdrj %fd %rj ++@fmt_rdfj .... ........ ..... ..... ..... ..... &fmt_rdfj %rd %fj ++@fmt_fcsrdrj .... ........ ..... ..... ..... ..... &fmt_fcsrdrj %fcsrd %rj ++@fmt_rdfcsrs .... ........ ..... ..... ..... ..... &fmt_rdfcsrs %rd %fcsrs ++@fmt_cdfj .... ........ ..... ..... ..... .. ... &fmt_cdfj %cd %fj ++@fmt_fdcj .... ........ ..... ..... .. ... ..... &fmt_fdcj %fd %cj ++@fmt_cdrj .... ........ ..... ..... ..... .. ... &fmt_cdrj %cd %rj ++@fmt_rdcj .... ........ ..... ..... .. ... ..... &fmt_rdcj %rd %cj ++@fmt_rdrjsi12 .... ...... ............ ..... ..... &fmt_rdrjsi12 %rd %rj %si12 ++@fmt_rdrjui12 .... ...... ............ ..... ..... &fmt_rdrjui12 %rd %rj %ui12 ++@fmt_rdrjcsr .... .... .............. ..... ..... &fmt_rdrjcsr %rd %rj %csr ++@fmt_coprjsi12 .... ...... ............ ..... ..... &fmt_coprjsi12 %cop %rj %si12 ++@fmt_rdrjlevel .... ........ .. ........ ..... ..... &fmt_rdrjlevel %rd %rj %level ++@fmt_rjseq .... ........ .. ........ ..... ..... &fmt_rjseq %rj %seq ++@fmt_whint .... ........ ..... ............... &fmt_whint %whint ++@fmt_invtlb ...... ...... ..... ..... ..... ..... &fmt_invtlb %addr %info %invop ++@fmt_fdfjfkfa .... ........ ..... ..... ..... ..... &fmt_fdfjfkfa %fd %fj %fk %fa ++@fmt_cdfjfkfcond .... ........ ..... ..... ..... .. ... &fmt_cdfjfkfcond %cd %fj %fk %fcond ++@fmt_fdfjfkca .... ........ .. ... ..... ..... ..... &fmt_fdfjfkca %fd %fj %fk %ca ++@fmt_rdrjsi16 .... .. ................ ..... ..... &fmt_rdrjsi16 %rd %rj %si16 ++@fmt_rdsi20 .... ... .................... ..... &fmt_rdsi20 %rd %si20 ++@fmt_rdrjsi14 .... .... .............. ..... ..... &fmt_rdrjsi14 %rd %rj %si14 ++@fmt_hintrjsi12 .... ...... ............ ..... ..... &fmt_hintrjsi12 %hint %rj %si12 ++@fmt_fdrjsi12 .... ...... ............ ..... ..... &fmt_fdrjsi12 %fd %rj %si12 ++@fmt_fdrjrk .... ........ ..... ..... ..... ..... &fmt_fdrjrk %fd %rj %rk ++@fmt_rjoffs21 .... .. ................ ..... ..... &fmt_rjoffs21 %rj %offs21 ++@fmt_cjoffs21 .... .. ................ .. ... ..... &fmt_cjoffs21 %cj %offs21 ++@fmt_rdrjoffs16 .... .. ................ ..... ..... &fmt_rdrjoffs16 %rd %rj %offs16 ++@fmt_offs .... .. .......................... &fmt_offs %offs ++@fmt_rjrdoffs16 .... .. ................ ..... ..... &fmt_rjrdoffs16 %rj %rd %offs16 ++ ++# Instructions ++ ++# Fiexd point arithmetic Instructions ++gr2scr 0000 00000000 00000 00010 ..... 000 .. @fmt_sdrj ++scr2gr 0000 00000000 00000 00011 000 .. ..... @fmt_rdsj ++clo_w 0000 00000000 00000 00100 ..... ..... @fmt_rdrj ++clz_w 0000 00000000 00000 00101 ..... ..... @fmt_rdrj ++cto_w 0000 00000000 00000 00110 ..... ..... @fmt_rdrj ++ctz_w 0000 00000000 00000 00111 ..... ..... @fmt_rdrj ++clo_d 0000 00000000 00000 01000 ..... ..... @fmt_rdrj ++clz_d 0000 00000000 00000 01001 ..... ..... @fmt_rdrj ++cto_d 0000 00000000 00000 01010 ..... ..... @fmt_rdrj ++ctz_d 0000 00000000 00000 01011 ..... ..... @fmt_rdrj ++revb_2h 0000 00000000 00000 01100 ..... ..... @fmt_rdrj ++revb_4h 0000 00000000 00000 01101 ..... ..... @fmt_rdrj ++revb_2w 0000 00000000 00000 01110 ..... ..... @fmt_rdrj ++revb_d 0000 00000000 00000 01111 ..... ..... @fmt_rdrj ++revh_2w 0000 00000000 00000 10000 ..... ..... @fmt_rdrj ++revh_d 0000 00000000 00000 10001 ..... ..... @fmt_rdrj ++bitrev_4b 0000 00000000 00000 10010 ..... ..... @fmt_rdrj ++bitrev_8b 0000 00000000 00000 10011 ..... ..... @fmt_rdrj ++bitrev_w 0000 00000000 00000 10100 ..... ..... @fmt_rdrj ++bitrev_d 0000 00000000 00000 10101 ..... ..... @fmt_rdrj ++ext_w_h 0000 00000000 00000 10110 ..... ..... @fmt_rdrj ++ext_w_b 0000 00000000 00000 10111 ..... ..... @fmt_rdrj ++rdtime_d 0000 00000000 00000 11010 ..... ..... @fmt_rdrj ++cpucfg 0000 00000000 00000 11011 ..... ..... @fmt_rdrj ++asrtle_d 0000 00000000 00010 ..... ..... 00000 @fmt_rjrk ++asrtgt_d 0000 00000000 00011 ..... ..... 00000 @fmt_rjrk ++alsl_w 0000 00000000 010 .. ..... ..... ..... @fmt_rdrjrksa2 ++alsl_wu 0000 00000000 011 .. ..... ..... ..... @fmt_rdrjrksa2 ++bytepick_w 0000 00000000 100 .. ..... ..... ..... @fmt_rdrjrksa2 ++bytepick_d 0000 00000000 11 ... ..... ..... ..... @fmt_rdrjrksa3 ++add_w 0000 00000001 00000 ..... ..... ..... @fmt_rdrjrk ++add_d 0000 00000001 00001 ..... ..... ..... @fmt_rdrjrk ++sub_w 0000 00000001 00010 ..... ..... ..... @fmt_rdrjrk ++sub_d 0000 00000001 00011 ..... ..... ..... @fmt_rdrjrk ++slt 0000 00000001 00100 ..... ..... ..... @fmt_rdrjrk ++sltu 0000 00000001 00101 ..... ..... ..... @fmt_rdrjrk ++maskeqz 0000 00000001 00110 ..... ..... ..... @fmt_rdrjrk ++masknez 0000 00000001 00111 ..... ..... ..... @fmt_rdrjrk ++nor 0000 00000001 01000 ..... ..... ..... @fmt_rdrjrk ++and 0000 00000001 01001 ..... ..... ..... @fmt_rdrjrk ++or 0000 00000001 01010 ..... ..... ..... @fmt_rdrjrk ++xor 0000 00000001 01011 ..... ..... ..... @fmt_rdrjrk ++orn 0000 00000001 01100 ..... ..... ..... @fmt_rdrjrk ++andn 0000 00000001 01101 ..... ..... ..... @fmt_rdrjrk ++sll_w 0000 00000001 01110 ..... ..... ..... @fmt_rdrjrk ++srl_w 0000 00000001 01111 ..... ..... ..... @fmt_rdrjrk ++sra_w 0000 00000001 10000 ..... ..... ..... @fmt_rdrjrk ++sll_d 0000 00000001 10001 ..... ..... ..... @fmt_rdrjrk ++srl_d 0000 00000001 10010 ..... ..... ..... @fmt_rdrjrk ++sra_d 0000 00000001 10011 ..... ..... ..... @fmt_rdrjrk ++rotr_w 0000 00000001 10110 ..... ..... ..... @fmt_rdrjrk ++rotr_d 0000 00000001 10111 ..... ..... ..... @fmt_rdrjrk ++mul_w 0000 00000001 11000 ..... ..... ..... @fmt_rdrjrk ++mulh_w 0000 00000001 11001 ..... ..... ..... @fmt_rdrjrk ++mulh_wu 0000 00000001 11010 ..... ..... ..... @fmt_rdrjrk ++mul_d 0000 00000001 11011 ..... ..... ..... @fmt_rdrjrk ++mulh_d 0000 00000001 11100 ..... ..... ..... @fmt_rdrjrk ++mulh_du 0000 00000001 11101 ..... ..... ..... @fmt_rdrjrk ++mulw_d_w 0000 00000001 11110 ..... ..... ..... @fmt_rdrjrk ++mulw_d_wu 0000 00000001 11111 ..... ..... ..... @fmt_rdrjrk ++div_w 0000 00000010 00000 ..... ..... ..... @fmt_rdrjrk ++mod_w 0000 00000010 00001 ..... ..... ..... @fmt_rdrjrk ++div_wu 0000 00000010 00010 ..... ..... ..... @fmt_rdrjrk ++mod_wu 0000 00000010 00011 ..... ..... ..... @fmt_rdrjrk ++div_d 0000 00000010 00100 ..... ..... ..... @fmt_rdrjrk ++mod_d 0000 00000010 00101 ..... ..... ..... @fmt_rdrjrk ++div_du 0000 00000010 00110 ..... ..... ..... @fmt_rdrjrk ++mod_du 0000 00000010 00111 ..... ..... ..... @fmt_rdrjrk ++crc_w_b_w 0000 00000010 01000 ..... ..... ..... @fmt_rdrjrk ++crc_w_h_w 0000 00000010 01001 ..... ..... ..... @fmt_rdrjrk ++crc_w_w_w 0000 00000010 01010 ..... ..... ..... @fmt_rdrjrk ++crc_w_d_w 0000 00000010 01011 ..... ..... ..... @fmt_rdrjrk ++crcc_w_b_w 0000 00000010 01100 ..... ..... ..... @fmt_rdrjrk ++crcc_w_h_w 0000 00000010 01101 ..... ..... ..... @fmt_rdrjrk ++crcc_w_w_w 0000 00000010 01110 ..... ..... ..... @fmt_rdrjrk ++crcc_w_d_w 0000 00000010 01111 ..... ..... ..... @fmt_rdrjrk ++break 0000 00000010 10100 ............... @fmt_code ++dbcl 0000 00000010 10101 ............... @fmt_code ++syscall 0000 00000010 10110 ............... @fmt_code ++alsl_d 0000 00000010 110 .. ..... ..... ..... @fmt_rdrjrksa2 ++slli_w 0000 00000100 00001 ..... ..... ..... @fmt_rdrjui5 ++slli_d 0000 00000100 0001 ...... ..... ..... @fmt_rdrjui6 ++srli_w 0000 00000100 01001 ..... ..... ..... @fmt_rdrjui5 ++srli_d 0000 00000100 0101 ...... ..... ..... @fmt_rdrjui6 ++srai_w 0000 00000100 10001 ..... ..... ..... @fmt_rdrjui5 ++srai_d 0000 00000100 1001 ...... ..... ..... @fmt_rdrjui6 ++rotri_w 0000 00000100 11001 ..... ..... ..... @fmt_rdrjui5 ++rotri_d 0000 00000100 1101 ...... ..... ..... @fmt_rdrjui6 ++bstrins_w 0000 0000011 ..... 0 ..... ..... ..... @fmt_rdrjmsbwlsbw ++bstrpick_w 0000 0000011 ..... 1 ..... ..... ..... @fmt_rdrjmsbwlsbw ++bstrins_d 0000 000010 ...... ...... ..... ..... @fmt_rdrjmsbdlsbd ++bstrpick_d 0000 000011 ...... ...... ..... ..... @fmt_rdrjmsbdlsbd ++ ++# float Instructions ++fadd_s 0000 00010000 00001 ..... ..... ..... @fmt_fdfjfk ++fadd_d 0000 00010000 00010 ..... ..... ..... @fmt_fdfjfk ++fsub_s 0000 00010000 00101 ..... ..... ..... @fmt_fdfjfk ++fsub_d 0000 00010000 00110 ..... ..... ..... @fmt_fdfjfk ++fmul_s 0000 00010000 01001 ..... ..... ..... @fmt_fdfjfk ++fmul_d 0000 00010000 01010 ..... ..... ..... @fmt_fdfjfk ++fdiv_s 0000 00010000 01101 ..... ..... ..... @fmt_fdfjfk ++fdiv_d 0000 00010000 01110 ..... ..... ..... @fmt_fdfjfk ++fmax_s 0000 00010000 10001 ..... ..... ..... @fmt_fdfjfk ++fmax_d 0000 00010000 10010 ..... ..... ..... @fmt_fdfjfk ++fmin_s 0000 00010000 10101 ..... ..... ..... @fmt_fdfjfk ++fmin_d 0000 00010000 10110 ..... ..... ..... @fmt_fdfjfk ++fmaxa_s 0000 00010000 11001 ..... ..... ..... @fmt_fdfjfk ++fmaxa_d 0000 00010000 11010 ..... ..... ..... @fmt_fdfjfk ++fmina_s 0000 00010000 11101 ..... ..... ..... @fmt_fdfjfk ++fmina_d 0000 00010000 11110 ..... ..... ..... @fmt_fdfjfk ++fscaleb_s 0000 00010001 00001 ..... ..... ..... @fmt_fdfjfk ++fscaleb_d 0000 00010001 00010 ..... ..... ..... @fmt_fdfjfk ++fcopysign_s 0000 00010001 00101 ..... ..... ..... @fmt_fdfjfk ++fcopysign_d 0000 00010001 00110 ..... ..... ..... @fmt_fdfjfk ++fabs_s 0000 00010001 01000 00001 ..... ..... @fmt_fdfj ++fabs_d 0000 00010001 01000 00010 ..... ..... @fmt_fdfj ++fneg_s 0000 00010001 01000 00101 ..... ..... @fmt_fdfj ++fneg_d 0000 00010001 01000 00110 ..... ..... @fmt_fdfj ++flogb_s 0000 00010001 01000 01001 ..... ..... @fmt_fdfj ++flogb_d 0000 00010001 01000 01010 ..... ..... @fmt_fdfj ++fclass_s 0000 00010001 01000 01101 ..... ..... @fmt_fdfj ++fclass_d 0000 00010001 01000 01110 ..... ..... @fmt_fdfj ++fsqrt_s 0000 00010001 01000 10001 ..... ..... @fmt_fdfj ++fsqrt_d 0000 00010001 01000 10010 ..... ..... @fmt_fdfj ++frecip_s 0000 00010001 01000 10101 ..... ..... @fmt_fdfj ++frecip_d 0000 00010001 01000 10110 ..... ..... @fmt_fdfj ++frsqrt_s 0000 00010001 01000 11001 ..... ..... @fmt_fdfj ++frsqrt_d 0000 00010001 01000 11010 ..... ..... @fmt_fdfj ++fmov_s 0000 00010001 01001 00101 ..... ..... @fmt_fdfj ++fmov_d 0000 00010001 01001 00110 ..... ..... @fmt_fdfj ++movgr2fr_w 0000 00010001 01001 01001 ..... ..... @fmt_fdrj ++movgr2fr_d 0000 00010001 01001 01010 ..... ..... @fmt_fdrj ++movgr2frh_w 0000 00010001 01001 01011 ..... ..... @fmt_fdrj ++movfr2gr_s 0000 00010001 01001 01101 ..... ..... @fmt_rdfj ++movfr2gr_d 0000 00010001 01001 01110 ..... ..... @fmt_rdfj ++movfrh2gr_s 0000 00010001 01001 01111 ..... ..... @fmt_rdfj ++movgr2fcsr 0000 00010001 01001 10000 ..... ..... @fmt_fcsrdrj ++movfcsr2gr 0000 00010001 01001 10010 ..... ..... @fmt_rdfcsrs ++movfr2cf 0000 00010001 01001 10100 ..... 00 ... @fmt_cdfj ++movcf2fr 0000 00010001 01001 10101 00 ... ..... @fmt_fdcj ++movgr2cf 0000 00010001 01001 10110 ..... 00 ... @fmt_cdrj ++movcf2gr 0000 00010001 01001 10111 00 ... ..... @fmt_rdcj ++fcvt_s_d 0000 00010001 10010 00110 ..... ..... @fmt_fdfj ++fcvt_d_s 0000 00010001 10010 01001 ..... ..... @fmt_fdfj ++ftintrm_w_s 0000 00010001 10100 00001 ..... ..... @fmt_fdfj ++ftintrm_w_d 0000 00010001 10100 00010 ..... ..... @fmt_fdfj ++ftintrm_l_s 0000 00010001 10100 01001 ..... ..... @fmt_fdfj ++ftintrm_l_d 0000 00010001 10100 01010 ..... ..... @fmt_fdfj ++ftintrp_w_s 0000 00010001 10100 10001 ..... ..... @fmt_fdfj ++ftintrp_w_d 0000 00010001 10100 10010 ..... ..... @fmt_fdfj ++ftintrp_l_s 0000 00010001 10100 11001 ..... ..... @fmt_fdfj ++ftintrp_l_d 0000 00010001 10100 11010 ..... ..... @fmt_fdfj ++ftintrz_w_s 0000 00010001 10101 00001 ..... ..... @fmt_fdfj ++ftintrz_w_d 0000 00010001 10101 00010 ..... ..... @fmt_fdfj ++ftintrz_l_s 0000 00010001 10101 01001 ..... ..... @fmt_fdfj ++ftintrz_l_d 0000 00010001 10101 01010 ..... ..... @fmt_fdfj ++ftintrne_w_s 0000 00010001 10101 10001 ..... ..... @fmt_fdfj ++ftintrne_w_d 0000 00010001 10101 10010 ..... ..... @fmt_fdfj ++ftintrne_l_s 0000 00010001 10101 11001 ..... ..... @fmt_fdfj ++ftintrne_l_d 0000 00010001 10101 11010 ..... ..... @fmt_fdfj ++ftint_w_s 0000 00010001 10110 00001 ..... ..... @fmt_fdfj ++ftint_w_d 0000 00010001 10110 00010 ..... ..... @fmt_fdfj ++ftint_l_s 0000 00010001 10110 01001 ..... ..... @fmt_fdfj ++ftint_l_d 0000 00010001 10110 01010 ..... ..... @fmt_fdfj ++ffint_s_w 0000 00010001 11010 00100 ..... ..... @fmt_fdfj ++ffint_s_l 0000 00010001 11010 00110 ..... ..... @fmt_fdfj ++ffint_d_w 0000 00010001 11010 01000 ..... ..... @fmt_fdfj ++ffint_d_l 0000 00010001 11010 01010 ..... ..... @fmt_fdfj ++frint_s 0000 00010001 11100 10001 ..... ..... @fmt_fdfj ++frint_d 0000 00010001 11100 10010 ..... ..... @fmt_fdfj ++ ++# 12 bit immediate Instructions ++slti 0000 001000 ............ ..... ..... @fmt_rdrjsi12 ++sltui 0000 001001 ............ ..... ..... @fmt_rdrjsi12 ++addi_w 0000 001010 ............ ..... ..... @fmt_rdrjsi12 ++addi_d 0000 001011 ............ ..... ..... @fmt_rdrjsi12 ++lu52i_d 0000 001100 ............ ..... ..... @fmt_rdrjsi12 ++andi 0000 001101 ............ ..... ..... @fmt_rdrjui12 ++ori 0000 001110 ............ ..... ..... @fmt_rdrjui12 ++xori 0000 001111 ............ ..... ..... @fmt_rdrjui12 ++ ++# core Instructions ++csrxchg 0000 0100 .............. ..... ..... @fmt_rdrjcsr ++cacop 0000 011000 ............ ..... ..... @fmt_coprjsi12 ++lddir 0000 01100100 00 ........ ..... ..... @fmt_rdrjlevel ++ldpte 0000 01100100 01 ........ ..... 00000 @fmt_rjseq ++iocsrrd_b 0000 01100100 10000 00000 ..... ..... @fmt_rdrj ++iocsrrd_h 0000 01100100 10000 00001 ..... ..... @fmt_rdrj ++iocsrrd_w 0000 01100100 10000 00010 ..... ..... @fmt_rdrj ++iocsrrd_d 0000 01100100 10000 00011 ..... ..... @fmt_rdrj ++iocsrwr_b 0000 01100100 10000 00100 ..... ..... @fmt_rdrj ++iocsrwr_h 0000 01100100 10000 00101 ..... ..... @fmt_rdrj ++iocsrwr_w 0000 01100100 10000 00110 ..... ..... @fmt_rdrj ++iocsrwr_d 0000 01100100 10000 00111 ..... ..... @fmt_rdrj ++tlbclr 0000 01100100 10000 01000 00000 00000 @fmt_empty ++tlbflush 0000 01100100 10000 01001 00000 00000 @fmt_empty ++tlbsrch 0000 01100100 10000 01010 00000 00000 @fmt_empty ++tlbrd 0000 01100100 10000 01011 00000 00000 @fmt_empty ++tlbwr 0000 01100100 10000 01100 00000 00000 @fmt_empty ++tlbfill 0000 01100100 10000 01101 00000 00000 @fmt_empty ++ertn 0000 01100100 10000 01110 00000 00000 @fmt_empty ++idle 0000 01100100 10001 ............... @fmt_whint ++invtlb 0000 01100100 10011 ..... ..... ..... @fmt_invtlb ++ ++# foure Op Instructions ++fmadd_s 0000 10000001 ..... ..... ..... ..... @fmt_fdfjfkfa ++fmadd_d 0000 10000010 ..... ..... ..... ..... @fmt_fdfjfkfa ++fmsub_s 0000 10000101 ..... ..... ..... ..... @fmt_fdfjfkfa ++fmsub_d 0000 10000110 ..... ..... ..... ..... @fmt_fdfjfkfa ++fnmadd_s 0000 10001001 ..... ..... ..... ..... @fmt_fdfjfkfa ++fnmadd_d 0000 10001010 ..... ..... ..... ..... @fmt_fdfjfkfa ++fnmsub_s 0000 10001101 ..... ..... ..... ..... @fmt_fdfjfkfa ++fnmsub_d 0000 10001110 ..... ..... ..... ..... @fmt_fdfjfkfa ++fcmp_cond_s 0000 11000001 ..... ..... ..... 00 ... @fmt_cdfjfkfcond ++fcmp_cond_d 0000 11000010 ..... ..... ..... 00 ... @fmt_cdfjfkfcond ++fsel 0000 11010000 00 ... ..... ..... ..... @fmt_fdfjfkca ++ ++# loog immediate Instructions ++addu16i_d 0001 00 ................ ..... ..... @fmt_rdrjsi16 ++lu12i_w 0001 010 .................... ..... @fmt_rdsi20 ++lu32i_d 0001 011 .................... ..... @fmt_rdsi20 ++pcaddi 0001 100 .................... ..... @fmt_rdsi20 ++pcalau12i 0001 101 .................... ..... @fmt_rdsi20 ++pcaddu12i 0001 110 .................... ..... @fmt_rdsi20 ++pcaddu18i 0001 111 .................... ..... @fmt_rdsi20 ++ ++# load/store Instructions ++ll_w 0010 0000 .............. ..... ..... @fmt_rdrjsi14 ++sc_w 0010 0001 .............. ..... ..... @fmt_rdrjsi14 ++ll_d 0010 0010 .............. ..... ..... @fmt_rdrjsi14 ++sc_d 0010 0011 .............. ..... ..... @fmt_rdrjsi14 ++ldptr_w 0010 0100 .............. ..... ..... @fmt_rdrjsi14 ++stptr_w 0010 0101 .............. ..... ..... @fmt_rdrjsi14 ++ldptr_d 0010 0110 .............. ..... ..... @fmt_rdrjsi14 ++stptr_d 0010 0111 .............. ..... ..... @fmt_rdrjsi14 ++ld_b 0010 100000 ............ ..... ..... @fmt_rdrjsi12 ++ld_h 0010 100001 ............ ..... ..... @fmt_rdrjsi12 ++ld_w 0010 100010 ............ ..... ..... @fmt_rdrjsi12 ++ld_d 0010 100011 ............ ..... ..... @fmt_rdrjsi12 ++st_b 0010 100100 ............ ..... ..... @fmt_rdrjsi12 ++st_h 0010 100101 ............ ..... ..... @fmt_rdrjsi12 ++st_w 0010 100110 ............ ..... ..... @fmt_rdrjsi12 ++st_d 0010 100111 ............ ..... ..... @fmt_rdrjsi12 ++ld_bu 0010 101000 ............ ..... ..... @fmt_rdrjsi12 ++ld_hu 0010 101001 ............ ..... ..... @fmt_rdrjsi12 ++ld_wu 0010 101010 ............ ..... ..... @fmt_rdrjsi12 ++preld 0010 101011 ............ ..... ..... @fmt_hintrjsi12 ++fld_s 0010 101100 ............ ..... ..... @fmt_fdrjsi12 ++fst_s 0010 101101 ............ ..... ..... @fmt_fdrjsi12 ++fld_d 0010 101110 ............ ..... ..... @fmt_fdrjsi12 ++fst_d 0010 101111 ............ ..... ..... @fmt_fdrjsi12 ++ldx_b 0011 10000000 00000 ..... ..... ..... @fmt_rdrjrk ++ldx_h 0011 10000000 01000 ..... ..... ..... @fmt_rdrjrk ++ldx_w 0011 10000000 10000 ..... ..... ..... @fmt_rdrjrk ++ldx_d 0011 10000000 11000 ..... ..... ..... @fmt_rdrjrk ++stx_b 0011 10000001 00000 ..... ..... ..... @fmt_rdrjrk ++stx_h 0011 10000001 01000 ..... ..... ..... @fmt_rdrjrk ++stx_w 0011 10000001 10000 ..... ..... ..... @fmt_rdrjrk ++stx_d 0011 10000001 11000 ..... ..... ..... @fmt_rdrjrk ++ldx_bu 0011 10000010 00000 ..... ..... ..... @fmt_rdrjrk ++ldx_hu 0011 10000010 01000 ..... ..... ..... @fmt_rdrjrk ++ldx_wu 0011 10000010 10000 ..... ..... ..... @fmt_rdrjrk ++fldx_s 0011 10000011 00000 ..... ..... ..... @fmt_fdrjrk ++fldx_d 0011 10000011 01000 ..... ..... ..... @fmt_fdrjrk ++fstx_s 0011 10000011 10000 ..... ..... ..... @fmt_fdrjrk ++fstx_d 0011 10000011 11000 ..... ..... ..... @fmt_fdrjrk ++amswap_w 0011 10000110 00000 ..... ..... ..... @fmt_rdrjrk ++amswap_d 0011 10000110 00001 ..... ..... ..... @fmt_rdrjrk ++amadd_w 0011 10000110 00010 ..... ..... ..... @fmt_rdrjrk ++amadd_d 0011 10000110 00011 ..... ..... ..... @fmt_rdrjrk ++amand_w 0011 10000110 00100 ..... ..... ..... @fmt_rdrjrk ++amand_d 0011 10000110 00101 ..... ..... ..... @fmt_rdrjrk ++amor_w 0011 10000110 00110 ..... ..... ..... @fmt_rdrjrk ++amor_d 0011 10000110 00111 ..... ..... ..... @fmt_rdrjrk ++amxor_w 0011 10000110 01000 ..... ..... ..... @fmt_rdrjrk ++amxor_d 0011 10000110 01001 ..... ..... ..... @fmt_rdrjrk ++ammax_w 0011 10000110 01010 ..... ..... ..... @fmt_rdrjrk ++ammax_d 0011 10000110 01011 ..... ..... ..... @fmt_rdrjrk ++ammin_w 0011 10000110 01100 ..... ..... ..... @fmt_rdrjrk ++ammin_d 0011 10000110 01101 ..... ..... ..... @fmt_rdrjrk ++ammax_wu 0011 10000110 01110 ..... ..... ..... @fmt_rdrjrk ++ammax_du 0011 10000110 01111 ..... ..... ..... @fmt_rdrjrk ++ammin_wu 0011 10000110 10000 ..... ..... ..... @fmt_rdrjrk ++ammin_du 0011 10000110 10001 ..... ..... ..... @fmt_rdrjrk ++amswap_db_w 0011 10000110 10010 ..... ..... ..... @fmt_rdrjrk ++amswap_db_d 0011 10000110 10011 ..... ..... ..... @fmt_rdrjrk ++amadd_db_w 0011 10000110 10100 ..... ..... ..... @fmt_rdrjrk ++amadd_db_d 0011 10000110 10101 ..... ..... ..... @fmt_rdrjrk ++amand_db_w 0011 10000110 10110 ..... ..... ..... @fmt_rdrjrk ++amand_db_d 0011 10000110 10111 ..... ..... ..... @fmt_rdrjrk ++amor_db_w 0011 10000110 11000 ..... ..... ..... @fmt_rdrjrk ++amor_db_d 0011 10000110 11001 ..... ..... ..... @fmt_rdrjrk ++amxor_db_w 0011 10000110 11010 ..... ..... ..... @fmt_rdrjrk ++amxor_db_d 0011 10000110 11011 ..... ..... ..... @fmt_rdrjrk ++ammax_db_w 0011 10000110 11100 ..... ..... ..... @fmt_rdrjrk ++ammax_db_d 0011 10000110 11101 ..... ..... ..... @fmt_rdrjrk ++ammin_db_w 0011 10000110 11110 ..... ..... ..... @fmt_rdrjrk ++ammin_db_d 0011 10000110 11111 ..... ..... ..... @fmt_rdrjrk ++ammax_db_wu 0011 10000111 00000 ..... ..... ..... @fmt_rdrjrk ++ammax_db_du 0011 10000111 00001 ..... ..... ..... @fmt_rdrjrk ++ammin_db_wu 0011 10000111 00010 ..... ..... ..... @fmt_rdrjrk ++ammin_db_du 0011 10000111 00011 ..... ..... ..... @fmt_rdrjrk ++dbar 0011 10000111 00100 ............... @fmt_whint ++ibar 0011 10000111 00101 ............... @fmt_whint ++fldgt_s 0011 10000111 01000 ..... ..... ..... @fmt_fdrjrk ++fldgt_d 0011 10000111 01001 ..... ..... ..... @fmt_fdrjrk ++fldle_s 0011 10000111 01010 ..... ..... ..... @fmt_fdrjrk ++fldle_d 0011 10000111 01011 ..... ..... ..... @fmt_fdrjrk ++fstgt_s 0011 10000111 01100 ..... ..... ..... @fmt_fdrjrk ++fstgt_d 0011 10000111 01101 ..... ..... ..... @fmt_fdrjrk ++fstle_s 0011 10000111 01110 ..... ..... ..... @fmt_fdrjrk ++fstle_d 0011 10000111 01111 ..... ..... ..... @fmt_fdrjrk ++ldgt_b 0011 10000111 10000 ..... ..... ..... @fmt_rdrjrk ++ldgt_h 0011 10000111 10001 ..... ..... ..... @fmt_rdrjrk ++ldgt_w 0011 10000111 10010 ..... ..... ..... @fmt_rdrjrk ++ldgt_d 0011 10000111 10011 ..... ..... ..... @fmt_rdrjrk ++ldle_b 0011 10000111 10100 ..... ..... ..... @fmt_rdrjrk ++ldle_h 0011 10000111 10101 ..... ..... ..... @fmt_rdrjrk ++ldle_w 0011 10000111 10110 ..... ..... ..... @fmt_rdrjrk ++ldle_d 0011 10000111 10111 ..... ..... ..... @fmt_rdrjrk ++stgt_b 0011 10000111 11000 ..... ..... ..... @fmt_rdrjrk ++stgt_h 0011 10000111 11001 ..... ..... ..... @fmt_rdrjrk ++stgt_w 0011 10000111 11010 ..... ..... ..... @fmt_rdrjrk ++stgt_d 0011 10000111 11011 ..... ..... ..... @fmt_rdrjrk ++stle_b 0011 10000111 11100 ..... ..... ..... @fmt_rdrjrk ++stle_h 0011 10000111 11101 ..... ..... ..... @fmt_rdrjrk ++stle_w 0011 10000111 11110 ..... ..... ..... @fmt_rdrjrk ++stle_d 0011 10000111 11111 ..... ..... ..... @fmt_rdrjrk ++ ++# jump Instructions ++beqz 0100 00 ................ ..... ..... @fmt_rjoffs21 ++bnez 0100 01 ................ ..... ..... @fmt_rjoffs21 ++bceqz 0100 10 ................ 00 ... ..... @fmt_cjoffs21 ++bcnez 0100 10 ................ 01 ... ..... @fmt_cjoffs21 ++jirl 0100 11 ................ ..... ..... @fmt_rdrjoffs16 ++b 0101 00 .......................... @fmt_offs ++bl 0101 01 .......................... @fmt_offs ++beq 0101 10 ................ ..... ..... @fmt_rjrdoffs16 ++bne 0101 11 ................ ..... ..... @fmt_rjrdoffs16 ++blt 0110 00 ................ ..... ..... @fmt_rjrdoffs16 ++bge 0110 01 ................ ..... ..... @fmt_rjrdoffs16 ++bltu 0110 10 ................ ..... ..... @fmt_rjrdoffs16 ++bgeu 0110 11 ................ ..... ..... @fmt_rjrdoffs16 +diff --git a/target/loongarch64/instmap.h b/target/loongarch64/instmap.h +new file mode 100644 +index 0000000000..6e85847f8a +--- /dev/null ++++ b/target/loongarch64/instmap.h +@@ -0,0 +1,216 @@ ++/* ++ * Loongarch emulation for qemu: instruction opcode ++ * ++ * Copyright (c) 2020-2021 ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms and conditions of the GNU General Public License, ++ * version 2 or later, as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program. If not, see . ++ */ ++ ++#ifndef TARGET_LARCH_INSTMAP_H ++#define TARGET_LARCH_INSTMAP_H ++ ++enum { ++ /* fix opcodes */ ++ OPC_LARCH_CLO_W = (0x000004 << 10), ++ OPC_LARCH_CLZ_W = (0x000005 << 10), ++ OPC_LARCH_CLO_D = (0x000008 << 10), ++ OPC_LARCH_CLZ_D = (0x000009 << 10), ++ OPC_LARCH_REVB_2H = (0x00000C << 10), ++ OPC_LARCH_REVB_4H = (0x00000D << 10), ++ OPC_LARCH_REVH_D = (0x000011 << 10), ++ OPC_LARCH_BREV_4B = (0x000012 << 10), ++ OPC_LARCH_BREV_8B = (0x000013 << 10), ++ OPC_LARCH_EXT_WH = (0x000016 << 10), ++ OPC_LARCH_EXT_WB = (0x000017 << 10), ++ ++ OPC_LARCH_ADD_W = (0x00020 << 15), ++ OPC_LARCH_ADD_D = (0x00021 << 15), ++ OPC_LARCH_SUB_W = (0x00022 << 15), ++ OPC_LARCH_SUB_D = (0x00023 << 15), ++ OPC_LARCH_SLT = (0x00024 << 15), ++ OPC_LARCH_SLTU = (0x00025 << 15), ++ OPC_LARCH_MASKEQZ = (0x00026 << 15), ++ OPC_LARCH_MASKNEZ = (0x00027 << 15), ++ OPC_LARCH_NOR = (0x00028 << 15), ++ OPC_LARCH_AND = (0x00029 << 15), ++ OPC_LARCH_OR = (0x0002A << 15), ++ OPC_LARCH_XOR = (0x0002B << 15), ++ OPC_LARCH_SLL_W = (0x0002E << 15), ++ OPC_LARCH_SRL_W = (0x0002F << 15), ++ OPC_LARCH_SRA_W = (0x00030 << 15), ++ OPC_LARCH_SLL_D = (0x00031 << 15), ++ OPC_LARCH_SRL_D = (0x00032 << 15), ++ OPC_LARCH_SRA_D = (0x00033 << 15), ++ OPC_LARCH_ROTR_W = (0x00036 << 15), ++ OPC_LARCH_ROTR_D = (0x00037 << 15), ++ OPC_LARCH_MUL_W = (0x00038 << 15), ++ OPC_LARCH_MULH_W = (0x00039 << 15), ++ OPC_LARCH_MULH_WU = (0x0003A << 15), ++ OPC_LARCH_MUL_D = (0x0003B << 15), ++ OPC_LARCH_MULH_D = (0x0003C << 15), ++ OPC_LARCH_MULH_DU = (0x0003D << 15), ++ OPC_LARCH_DIV_W = (0x00040 << 15), ++ OPC_LARCH_MOD_W = (0x00041 << 15), ++ OPC_LARCH_DIV_WU = (0x00042 << 15), ++ OPC_LARCH_MOD_WU = (0x00043 << 15), ++ OPC_LARCH_DIV_D = (0x00044 << 15), ++ OPC_LARCH_MOD_D = (0x00045 << 15), ++ OPC_LARCH_DIV_DU = (0x00046 << 15), ++ OPC_LARCH_MOD_DU = (0x00047 << 15), ++ OPC_LARCH_SRLI_W = (0x00089 << 15), ++ OPC_LARCH_SRAI_W = (0x00091 << 15), ++ OPC_LARCH_ROTRI_W = (0x00099 << 15), ++ ++ OPC_LARCH_ALSL_W = (0x0002 << 17), ++ OPC_LARCH_ALSL_D = (0x0016 << 17), ++ ++ OPC_LARCH_TRINS_W = (0x003 << 21) | (0x0 << 15), ++ OPC_LARCH_TRPICK_W = (0x003 << 21) | (0x1 << 15), ++}; ++ ++enum { ++ /* float opcodes */ ++ OPC_LARCH_FABS_S = (0x004501 << 10), ++ OPC_LARCH_FABS_D = (0x004502 << 10), ++ OPC_LARCH_FNEG_S = (0x004505 << 10), ++ OPC_LARCH_FNEG_D = (0x004506 << 10), ++ OPC_LARCH_FCLASS_S = (0x00450D << 10), ++ OPC_LARCH_FCLASS_D = (0x00450E << 10), ++ OPC_LARCH_FSQRT_S = (0x004511 << 10), ++ OPC_LARCH_FSQRT_D = (0x004512 << 10), ++ OPC_LARCH_FRECIP_S = (0x004515 << 10), ++ OPC_LARCH_FRECIP_D = (0x004516 << 10), ++ OPC_LARCH_FRSQRT_S = (0x004519 << 10), ++ OPC_LARCH_FRSQRT_D = (0x00451A << 10), ++ OPC_LARCH_FMOV_S = (0x004525 << 10), ++ OPC_LARCH_FMOV_D = (0x004526 << 10), ++ OPC_LARCH_GR2FR_W = (0x004529 << 10), ++ OPC_LARCH_GR2FR_D = (0x00452A << 10), ++ OPC_LARCH_GR2FRH_W = (0x00452B << 10), ++ OPC_LARCH_FR2GR_S = (0x00452D << 10), ++ OPC_LARCH_FR2GR_D = (0x00452E << 10), ++ OPC_LARCH_FRH2GR_S = (0x00452F << 10), ++ ++ OPC_LARCH_FCVT_S_D = (0x004646 << 10), ++ OPC_LARCH_FCVT_D_S = (0x004649 << 10), ++ OPC_LARCH_FTINTRM_W_S = (0x004681 << 10), ++ OPC_LARCH_FTINTRM_W_D = (0x004682 << 10), ++ OPC_LARCH_FTINTRM_L_S = (0x004689 << 10), ++ OPC_LARCH_FTINTRM_L_D = (0x00468A << 10), ++ OPC_LARCH_FTINTRP_W_S = (0x004691 << 10), ++ OPC_LARCH_FTINTRP_W_D = (0x004692 << 10), ++ OPC_LARCH_FTINTRP_L_S = (0x004699 << 10), ++ OPC_LARCH_FTINTRP_L_D = (0x00469A << 10), ++ OPC_LARCH_FTINTRZ_W_S = (0x0046A1 << 10), ++ OPC_LARCH_FTINTRZ_W_D = (0x0046A2 << 10), ++ OPC_LARCH_FTINTRZ_L_S = (0x0046A9 << 10), ++ OPC_LARCH_FTINTRZ_L_D = (0x0046AA << 10), ++ OPC_LARCH_FTINTRNE_W_S = (0x0046B1 << 10), ++ OPC_LARCH_FTINTRNE_W_D = (0x0046B2 << 10), ++ OPC_LARCH_FTINTRNE_L_S = (0x0046B9 << 10), ++ OPC_LARCH_FTINTRNE_L_D = (0x0046BA << 10), ++ OPC_LARCH_FTINT_W_S = (0x0046C1 << 10), ++ OPC_LARCH_FTINT_W_D = (0x0046C2 << 10), ++ OPC_LARCH_FTINT_L_S = (0x0046C9 << 10), ++ OPC_LARCH_FTINT_L_D = (0x0046CA << 10), ++ OPC_LARCH_FFINT_S_W = (0x004744 << 10), ++ OPC_LARCH_FFINT_S_L = (0x004746 << 10), ++ OPC_LARCH_FFINT_D_W = (0x004748 << 10), ++ OPC_LARCH_FFINT_D_L = (0x00474A << 10), ++ OPC_LARCH_FRINT_S = (0x004791 << 10), ++ OPC_LARCH_FRINT_D = (0x004792 << 10), ++ ++ OPC_LARCH_FADD_S = (0x00201 << 15), ++ OPC_LARCH_FADD_D = (0x00202 << 15), ++ OPC_LARCH_FSUB_S = (0x00205 << 15), ++ OPC_LARCH_FSUB_D = (0x00206 << 15), ++ OPC_LARCH_FMUL_S = (0x00209 << 15), ++ OPC_LARCH_FMUL_D = (0x0020A << 15), ++ OPC_LARCH_FDIV_S = (0x0020D << 15), ++ OPC_LARCH_FDIV_D = (0x0020E << 15), ++ OPC_LARCH_FMAX_S = (0x00211 << 15), ++ OPC_LARCH_FMAX_D = (0x00212 << 15), ++ OPC_LARCH_FMIN_S = (0x00215 << 15), ++ OPC_LARCH_FMIN_D = (0x00216 << 15), ++ OPC_LARCH_FMAXA_S = (0x00219 << 15), ++ OPC_LARCH_FMAXA_D = (0x0021A << 15), ++ OPC_LARCH_FMINA_S = (0x0021D << 15), ++ OPC_LARCH_FMINA_D = (0x0021E << 15), ++}; ++ ++enum { ++ /* 12 bit immediate opcodes */ ++ OPC_LARCH_SLTI = (0x008 << 22), ++ OPC_LARCH_SLTIU = (0x009 << 22), ++ OPC_LARCH_ADDI_W = (0x00A << 22), ++ OPC_LARCH_ADDI_D = (0x00B << 22), ++ OPC_LARCH_ANDI = (0x00D << 22), ++ OPC_LARCH_ORI = (0x00E << 22), ++ OPC_LARCH_XORI = (0x00F << 22), ++}; ++ ++enum { ++ /* load/store opcodes */ ++ OPC_LARCH_FLDX_S = (0x07060 << 15), ++ OPC_LARCH_FLDX_D = (0x07068 << 15), ++ OPC_LARCH_FSTX_S = (0x07070 << 15), ++ OPC_LARCH_FSTX_D = (0x07078 << 15), ++ OPC_LARCH_FLDGT_S = (0x070E8 << 15), ++ OPC_LARCH_FLDGT_D = (0x070E9 << 15), ++ OPC_LARCH_FLDLE_S = (0x070EA << 15), ++ OPC_LARCH_FLDLE_D = (0x070EB << 15), ++ OPC_LARCH_FSTGT_S = (0x070EC << 15), ++ OPC_LARCH_FSTGT_D = (0x070ED << 15), ++ OPC_LARCH_FSTLE_S = (0x070EE << 15), ++ OPC_LARCH_FSTLE_D = (0x070EF << 15), ++ ++ OPC_LARCH_LD_B = (0x0A0 << 22), ++ OPC_LARCH_LD_H = (0x0A1 << 22), ++ OPC_LARCH_LD_W = (0x0A2 << 22), ++ OPC_LARCH_LD_D = (0x0A3 << 22), ++ OPC_LARCH_ST_B = (0x0A4 << 22), ++ OPC_LARCH_ST_H = (0x0A5 << 22), ++ OPC_LARCH_ST_W = (0x0A6 << 22), ++ OPC_LARCH_ST_D = (0x0A7 << 22), ++ OPC_LARCH_LD_BU = (0x0A8 << 22), ++ OPC_LARCH_LD_HU = (0x0A9 << 22), ++ OPC_LARCH_LD_WU = (0x0AA << 22), ++ OPC_LARCH_FLD_S = (0x0AC << 22), ++ OPC_LARCH_FST_S = (0x0AD << 22), ++ OPC_LARCH_FLD_D = (0x0AE << 22), ++ OPC_LARCH_FST_D = (0x0AF << 22), ++ ++ OPC_LARCH_LL_W = (0x20 << 24), ++ OPC_LARCH_SC_W = (0x21 << 24), ++ OPC_LARCH_LL_D = (0x22 << 24), ++ OPC_LARCH_SC_D = (0x23 << 24), ++ OPC_LARCH_LDPTR_W = (0x24 << 24), ++ OPC_LARCH_STPTR_W = (0x25 << 24), ++ OPC_LARCH_LDPTR_D = (0x26 << 24), ++ OPC_LARCH_STPTR_D = (0x27 << 24), ++}; ++ ++enum { ++ /* jump opcodes */ ++ OPC_LARCH_BEQZ = (0x10 << 26), ++ OPC_LARCH_BNEZ = (0x11 << 26), ++ OPC_LARCH_B = (0x14 << 26), ++ OPC_LARCH_BEQ = (0x16 << 26), ++ OPC_LARCH_BNE = (0x17 << 26), ++ OPC_LARCH_BLT = (0x18 << 26), ++ OPC_LARCH_BGE = (0x19 << 26), ++ OPC_LARCH_BLTU = (0x1A << 26), ++ OPC_LARCH_BGEU = (0x1B << 26), ++}; ++ ++#endif +diff --git a/target/loongarch64/internal.h b/target/loongarch64/internal.h +new file mode 100644 +index 0000000000..79a70e9d26 +--- /dev/null ++++ b/target/loongarch64/internal.h +@@ -0,0 +1,184 @@ ++#ifndef LOONGARCH_INTERNAL_H ++#define LOONGARCH_INTERNAL_H ++ ++#include "cpu-csr.h" ++ ++/* MMU types, the first four entries have the same layout as the ++ CP0C0_MT field. */ ++enum loongarch_mmu_types { ++ MMU_TYPE_NONE, ++ MMU_TYPE_LS3A5K, /* LISA CSR */ ++}; ++ ++ ++ ++struct loongarch_def_t { ++ const char *name; ++ int32_t CSR_PRid; ++ int32_t FCSR0; ++ int32_t FCSR0_rw_bitmask; ++ int32_t PABITS; ++ CPU_LOONGARCH_CSR ++ uint64_t insn_flags; ++ enum loongarch_mmu_types mmu_type; ++ int cpu_cfg[64]; ++}; ++ ++/* loongarch 3a5000 TLB entry */ ++struct ls3a5k_tlb_t { ++ target_ulong VPN; ++ uint64_t PageMask; /* CSR_TLBIDX[29:24] */ ++ uint32_t PageSize; ++ uint16_t ASID; ++ unsigned int G:1; /* CSR_TLBLO[6] */ ++ ++ unsigned int C0:3; /* CSR_TLBLO[5:4] */ ++ unsigned int C1:3; ++ ++ unsigned int V0:1; /* CSR_TLBLO[0] */ ++ unsigned int V1:1; ++ ++ unsigned int WE0:1; /* CSR_TLBLO[1] */ ++ unsigned int WE1:1; ++ ++ unsigned int XI0:1; /* CSR_TLBLO[62] */ ++ unsigned int XI1:1; ++ ++ unsigned int RI0:1; /* CSR_TLBLO[61] */ ++ unsigned int RI1:1; ++ ++ unsigned int EHINV:1;/* CSR_TLBIDX[31] */ ++ ++ unsigned int PLV0:2; /* CSR_TLBLO[3:2] */ ++ unsigned int PLV1:2; ++ ++ unsigned int RPLV0:1; ++ unsigned int RPLV1:1; /* CSR_TLBLO[63] */ ++ ++ uint64_t PPN0; /* CSR_TLBLO[47:12] */ ++ uint64_t PPN1; /* CSR_TLBLO[47:12] */ ++}; ++typedef struct ls3a5k_tlb_t ls3a5k_tlb_t; ++ ++ ++struct CPULOONGARCHTLBContext { ++ uint32_t nb_tlb; ++ uint32_t tlb_in_use; ++ int (*map_address)(struct CPULOONGARCHState *env, hwaddr *physical, int *prot, ++ target_ulong address, int rw, int access_type); ++ void (*helper_tlbwr)(struct CPULOONGARCHState *env); ++ void (*helper_tlbfill)(struct CPULOONGARCHState *env); ++ void (*helper_tlbsrch)(struct CPULOONGARCHState *env); ++ void (*helper_tlbrd)(struct CPULOONGARCHState *env); ++ void (*helper_tlbclr)(struct CPULOONGARCHState *env); ++ void (*helper_tlbflush)(struct CPULOONGARCHState *env); ++ void (*helper_invtlb)(struct CPULOONGARCHState *env, target_ulong addr, ++ target_ulong info, int op); ++ union { ++ struct { ++ uint64_t ftlb_mask; ++ uint32_t ftlb_size; /* at most : 8 * 256 = 2048 */ ++ uint32_t vtlb_size; /* at most : 64 */ ++ ls3a5k_tlb_t tlb[2048 + 64]; /* at most : 2048 FTLB + 64 VTLB */ ++ } ls3a5k; ++ } mmu; ++}; ++ ++enum { ++ TLBRET_PE = -7, ++ TLBRET_XI = -6, ++ TLBRET_RI = -5, ++ TLBRET_DIRTY = -4, ++ TLBRET_INVALID = -3, ++ TLBRET_NOMATCH = -2, ++ TLBRET_BADADDR = -1, ++ TLBRET_MATCH = 0 ++}; ++ ++ ++extern unsigned int ieee_rm[]; ++ ++static inline void restore_rounding_mode(CPULOONGARCHState *env) ++{ ++ set_float_rounding_mode(ieee_rm[(env->active_fpu.fcsr0 >> FCSR0_RM) & 0x3], ++ &env->active_fpu.fp_status); ++} ++ ++static inline void restore_flush_mode(CPULOONGARCHState *env) ++{ ++ set_flush_to_zero(0, &env->active_fpu.fp_status); ++} ++ ++static inline void restore_fp_status(CPULOONGARCHState *env) ++{ ++ restore_rounding_mode(env); ++ restore_flush_mode(env); ++} ++static inline void compute_hflags(CPULOONGARCHState *env) ++{ ++ env->hflags &= ~(LARCH_HFLAG_64 | LARCH_HFLAG_FPU | LARCH_HFLAG_KSU | ++ LARCH_HFLAG_AWRAP | LARCH_HFLAG_LSX | LARCH_HFLAG_LASX); ++ ++ env->hflags |= (env->CSR_CRMD & CSR_CRMD_PLV); ++ env->hflags |= LARCH_HFLAG_64; ++ ++ if (env->CSR_EUEN & CSR_EUEN_FPEN) { ++ env->hflags |= LARCH_HFLAG_FPU; ++ } ++ if (env->CSR_EUEN & CSR_EUEN_LSXEN) { ++ env->hflags |= LARCH_HFLAG_LSX; ++ } ++ if (env->CSR_EUEN & CSR_EUEN_LASXEN) { ++ env->hflags |= LARCH_HFLAG_LASX; ++ } ++ if (env->CSR_EUEN & CSR_EUEN_LBTEN) { ++ env->hflags |= LARCH_HFLAG_LBT; ++ } ++} ++ ++/* Check if there is pending and not masked out interrupt */ ++static inline bool cpu_loongarch_hw_interrupts_pending(CPULOONGARCHState *env) ++{ ++ int32_t pending; ++ int32_t status; ++ bool r; ++ ++ pending = env->CSR_ESTAT & CSR_ESTAT_IPMASK; ++ status = env->CSR_ECFG & CSR_ECFG_IPMASK; ++ ++ /* Configured with compatibility or VInt (Vectored Interrupts) ++ treats the pending lines as individual interrupt lines, the status ++ lines are individual masks. */ ++ r = (pending & status) != 0; ++ ++ return r; ++} ++ ++ ++/* stabletimer.c */ ++uint32_t cpu_loongarch_get_random_ls3a5k_tlb(uint32_t low, uint32_t high); ++uint64_t cpu_loongarch_get_stable_counter(CPULOONGARCHState *env); ++uint64_t cpu_loongarch_get_stable_timer_ticks(CPULOONGARCHState *env); ++void cpu_loongarch_store_stable_timer_config(CPULOONGARCHState *env, uint64_t value); ++int loongarch_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cpu, ++ int cpuid, void *opaque); ++ ++void loongarch_cpu_dump_state(CPUState *cpu, FILE *f, int flags); ++ ++/* TODO QOM'ify CPU reset and remove */ ++void cpu_state_reset(CPULOONGARCHState *s); ++void cpu_loongarch_realize_env(CPULOONGARCHState *env); ++ ++int loongarch_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n); ++int loongarch_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg); ++ ++#ifdef CONFIG_TCG ++#include "fpu_helper.h" ++#endif ++ ++#ifndef CONFIG_USER_ONLY ++extern const struct VMStateDescription vmstate_loongarch_cpu; ++hwaddr loongarch_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr); ++#endif ++ ++#endif +diff --git a/target/loongarch64/kvm.c b/target/loongarch64/kvm.c +new file mode 100644 +index 0000000000..404a605eb6 +--- /dev/null ++++ b/target/loongarch64/kvm.c +@@ -0,0 +1,1622 @@ ++/* ++ * This file is subject to the terms and conditions of the GNU General Public ++ * License. See the file "COPYING" in the main directory of this archive ++ * for more details. ++ * ++ * KVM/LOONGARCH: LOONGARCH specific KVM APIs ++ * ++ * Copyright (C) 2012-2014 Imagination Technologies Ltd. ++ * Authors: Sanjay Lal ++*/ ++ ++#include "qemu/osdep.h" ++#include ++ ++#include ++ ++#include "qemu-common.h" ++#include "cpu.h" ++#include "internal.h" ++#include "qemu/error-report.h" ++#include "qemu/timer.h" ++#include "qemu/main-loop.h" ++#include "sysemu/sysemu.h" ++#include "sysemu/kvm.h" ++#include "sysemu/runstate.h" ++#include "sysemu/cpus.h" ++#include "kvm_larch.h" ++#include "exec/memattrs.h" ++#include "exec/gdbstub.h" ++ ++#define DEBUG_KVM 0 ++/* A 16384-byte buffer can hold the 8-byte kvm_msrs header, plus ++ * 2047 kvm_msr_entry structs */ ++#define MSR_BUF_SIZE 16384 ++ ++#define DPRINTF(fmt, ...) \ ++ do { if (DEBUG_KVM) { fprintf(stderr, fmt, ## __VA_ARGS__); } } while (0) ++ ++/* ++ * Define loongarch kvm version. ++ * Add version number when ++ * qemu/kvm interface changed ++ */ ++#define KVM_LOONGARCH_VERSION 1 ++ ++static struct { ++ target_ulong addr; ++ int len; ++ int type; ++} inst_breakpoint[8], data_breakpoint[8]; ++ ++int nb_data_breakpoint = 0, nb_inst_breakpoint = 0; ++static int kvm_loongarch_version_cap; ++ ++/* Hardware breakpoint control register ++ * 4:1 plv0-plv3 enable ++ * 6:5 config virtualization mode ++ * 9:8 load store */ ++static const int type_code[] = { ++ [GDB_BREAKPOINT_HW] = 0x5e, ++ [GDB_WATCHPOINT_READ] = (0x5e | 1 << 8), ++ [GDB_WATCHPOINT_WRITE] = (0x5e | 1 << 9), ++ [GDB_WATCHPOINT_ACCESS] = (0x5e | 1 << 8 | 1 << 9) ++}; ++ ++const KVMCapabilityInfo kvm_arch_required_capabilities[] = { ++ KVM_CAP_LAST_INFO ++}; ++ ++static void kvm_loongarch_update_state(void *opaque, bool running, RunState state); ++static inline int kvm_larch_putq(CPUState *cs, uint64_t reg_id, uint64_t *addr); ++ ++unsigned long kvm_arch_vcpu_id(CPUState *cs) ++{ ++ return cs->cpu_index; ++} ++ ++int kvm_arch_init(MachineState *ms, KVMState *s) ++{ ++ /* LOONGARCH has 128 signals */ ++ kvm_set_sigmask_len(s, 16); ++ ++ kvm_loongarch_version_cap = kvm_check_extension(s, KVM_CAP_LOONGARCH_VZ); ++ ++ if (kvm_loongarch_version_cap != KVM_LOONGARCH_VERSION) { ++ warn_report("QEMU/KVM version not match, qemu_la_version: lvz-%d,\ ++ kvm_la_version: lvz-%d \n", ++ KVM_LOONGARCH_VERSION, kvm_loongarch_version_cap); ++ } ++ return 0; ++} ++ ++int kvm_arch_irqchip_create(KVMState *s) ++{ ++ return 0; ++} ++ ++int kvm_arch_init_vcpu(CPUState *cs) ++{ ++ LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); ++ int ret = 0; ++ ++ cpu->cpuStateEntry = qemu_add_vm_change_state_handler(kvm_loongarch_update_state, cs); ++ cpu->kvm_msr_buf = g_malloc0(MSR_BUF_SIZE); ++ DPRINTF("%s\n", __func__); ++ return ret; ++} ++ ++int kvm_arch_destroy_vcpu(CPUState *cs) ++{ ++ return 0; ++} ++ ++static void kvm_msr_buf_reset(LOONGARCHCPU *cpu) ++{ ++ memset(cpu->kvm_msr_buf, 0, MSR_BUF_SIZE); ++} ++ ++static void kvm_msr_entry_add(LOONGARCHCPU *cpu, uint32_t index, uint64_t value) ++{ ++ struct kvm_msrs *msrs = cpu->kvm_msr_buf; ++ void *limit = ((void *)msrs) + MSR_BUF_SIZE; ++ struct kvm_csr_entry *entry = &msrs->entries[msrs->ncsrs]; ++ ++ assert((void *)(entry + 1) <= limit); ++ ++ entry->index = index; ++ entry->reserved = 0; ++ entry->data = value; ++ msrs->ncsrs++; ++} ++ ++void kvm_loongarch_reset_vcpu(LOONGARCHCPU *cpu) ++{ ++ int ret = 0; ++ uint64_t reset = 1; ++ ++ if (CPU(cpu)->kvm_fd > 0) { ++ ret = kvm_larch_putq(CPU(cpu), KVM_REG_LOONGARCH_VCPU_RESET, &reset); ++ if (ret < 0) { ++ error_report("%s reset vcpu failed:%d", __func__, ret); ++ } ++ } ++ ++ DPRINTF("%s\n", __func__); ++} ++ ++void kvm_arch_update_guest_debug(CPUState *cpu, struct kvm_guest_debug *dbg) ++{ ++ int n; ++ if (kvm_sw_breakpoints_active(cpu)) { ++ dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP; ++ } ++ if (nb_data_breakpoint > 0) { ++ dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_HW_BP; ++ for (n = 0; n < nb_data_breakpoint; n++) { ++ dbg->arch.data_breakpoint[n].addr = data_breakpoint[n].addr; ++ dbg->arch.data_breakpoint[n].mask = 0; ++ dbg->arch.data_breakpoint[n].asid = 0; ++ dbg->arch.data_breakpoint[n].ctrl = type_code[data_breakpoint[n].type]; ++ } ++ dbg->arch.data_bp_nums = nb_data_breakpoint; ++ } else { ++ dbg->arch.data_bp_nums = 0; ++ } ++ if (nb_inst_breakpoint > 0) { ++ dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_HW_BP; ++ for (n = 0; n < nb_inst_breakpoint; n++) { ++ dbg->arch.inst_breakpoint[n].addr = inst_breakpoint[n].addr; ++ dbg->arch.inst_breakpoint[n].mask = 0; ++ dbg->arch.inst_breakpoint[n].asid = 0; ++ dbg->arch.inst_breakpoint[n].ctrl = type_code[inst_breakpoint[n].type]; ++ } ++ dbg->arch.inst_bp_nums = nb_inst_breakpoint; ++ } else { ++ dbg->arch.inst_bp_nums = 0; ++ } ++} ++ ++static const unsigned int brk_insn = 0x002b8005; ++ ++int kvm_arch_insert_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp) ++{ ++ DPRINTF("%s\n", __func__); ++ if (cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&bp->saved_insn, 4, 0) || ++ cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&brk_insn, 4, 1)) { ++ error_report("%s failed", __func__); ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++int kvm_arch_remove_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp) ++{ ++ static uint32_t brk; ++ ++ DPRINTF("%s\n", __func__); ++ if (cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&brk, 4, 0) || ++ brk != brk_insn || ++ cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&bp->saved_insn, 4, 1)) { ++ error_report("%s failed", __func__); ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++static int find_hw_breakpoint(uint64_t addr, int len, int type) ++{ ++ int n; ++ switch (type) { ++ case GDB_BREAKPOINT_HW: ++ if (nb_inst_breakpoint == 0) { ++ return -1; ++ } ++ for (n = 0; n < nb_inst_breakpoint; n++) { ++ if (inst_breakpoint[n].addr == addr && inst_breakpoint[n].type == type) { ++ return n; ++ } ++ } ++ break; ++ case GDB_WATCHPOINT_WRITE: ++ case GDB_WATCHPOINT_READ: ++ case GDB_WATCHPOINT_ACCESS: ++ if (nb_data_breakpoint == 0) { ++ return -1; ++ } ++ for (n = 0; n < nb_data_breakpoint; n++) { ++ if (data_breakpoint[n].addr == addr && data_breakpoint[n].type == type && ++ data_breakpoint[n].len == len) { ++ return n; ++ } ++ } ++ break; ++ default: ++ return -1; ++ } ++ return -1; ++} ++ ++int kvm_arch_insert_hw_breakpoint(target_ulong addr, ++ target_ulong len, int type) ++{ ++ switch (type) { ++ case GDB_BREAKPOINT_HW: ++ len = 1; ++ if (nb_inst_breakpoint == 8) { ++ return -ENOBUFS; ++ } ++ if (find_hw_breakpoint(addr, len, type) >= 0) { ++ return -EEXIST; ++ } ++ inst_breakpoint[nb_inst_breakpoint].addr = addr; ++ inst_breakpoint[nb_inst_breakpoint].len = len; ++ inst_breakpoint[nb_inst_breakpoint].type = type; ++ nb_inst_breakpoint++; ++ break; ++ case GDB_WATCHPOINT_WRITE: ++ case GDB_WATCHPOINT_READ: ++ case GDB_WATCHPOINT_ACCESS: ++ switch (len) { ++ case 1: ++ case 2: ++ case 4: ++ case 8: ++ if (addr & (len - 1)) { ++ return -EINVAL; ++ } ++ if (nb_data_breakpoint == 8) { ++ return -ENOBUFS; ++ } ++ if (find_hw_breakpoint(addr, len, type) >= 0) { ++ return -EEXIST; ++ } ++ data_breakpoint[nb_data_breakpoint].addr = addr; ++ data_breakpoint[nb_data_breakpoint].len = len; ++ data_breakpoint[nb_data_breakpoint].type = type; ++ nb_data_breakpoint++; ++ break; ++ default: ++ return -EINVAL; ++ } ++ break; ++ default: ++ return -ENOSYS; ++ } ++ return 0; ++} ++ ++int kvm_arch_remove_hw_breakpoint(target_ulong addr, ++ target_ulong len, int type) ++{ ++ int n; ++ n = find_hw_breakpoint(addr, (type == GDB_BREAKPOINT_HW) ? 1 : len, type); ++ if (n < 0) { ++ printf("err not find remove target\n"); ++ return -ENOENT; ++ } ++ switch (type) { ++ case GDB_BREAKPOINT_HW: ++ nb_inst_breakpoint--; ++ inst_breakpoint[n] = inst_breakpoint[nb_inst_breakpoint]; ++ break; ++ case GDB_WATCHPOINT_WRITE: ++ case GDB_WATCHPOINT_READ: ++ case GDB_WATCHPOINT_ACCESS: ++ nb_data_breakpoint--; ++ data_breakpoint[n] = data_breakpoint[nb_data_breakpoint]; ++ break; ++ default: ++ return -1; ++ } ++ return 0; ++} ++ ++void kvm_arch_remove_all_hw_breakpoints(void) ++{ ++ DPRINTF("%s\n", __func__); ++ nb_data_breakpoint = 0; ++ nb_inst_breakpoint = 0; ++} ++ ++static inline int cpu_loongarch_io_interrupts_pending(LOONGARCHCPU *cpu) ++{ ++ CPULOONGARCHState *env = &cpu->env; ++ ++ return env->CSR_ESTAT & (0x1 << 2); ++} ++ ++void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run) ++{ ++ LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); ++ int r; ++ struct kvm_loongarch_interrupt intr; ++ ++ qemu_mutex_lock_iothread(); ++ ++ if ((cs->interrupt_request & CPU_INTERRUPT_HARD) && ++ cpu_loongarch_io_interrupts_pending(cpu)) { ++ intr.cpu = -1; ++ intr.irq = 2; ++ r = kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &intr); ++ if (r < 0) { ++ error_report("%s: cpu %d: failed to inject IRQ %x", ++ __func__, cs->cpu_index, intr.irq); ++ } ++ } ++ ++ qemu_mutex_unlock_iothread(); ++} ++ ++MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run) ++{ ++ return MEMTXATTRS_UNSPECIFIED; ++} ++ ++int kvm_arch_process_async_events(CPUState *cs) ++{ ++ return cs->halted; ++} ++ ++static CPUWatchpoint hw_watchpoint; ++ ++static bool kvm_loongarch_handle_debug(CPUState *cs, struct kvm_run *run) ++{ ++ LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); ++ CPULOONGARCHState *env = &cpu->env; ++ int i; ++ bool ret = false; ++ kvm_cpu_synchronize_state(cs); ++ if (cs->singlestep_enabled) { ++ return true; ++ } ++ if (kvm_find_sw_breakpoint(cs, env->active_tc.PC)) { ++ return true; ++ } ++ /* hw breakpoint */ ++ if (run->debug.arch.exception == EXCCODE_WATCH) { ++ for (i = 0; i < 8; i++) { ++ if (run->debug.arch.fwps & (1 << i)) { ++ ret = true; ++ break; ++ } ++ } ++ for (i = 0; i < 8; i++) { ++ if (run->debug.arch.mwps & (1 << i)) { ++ cs->watchpoint_hit = &hw_watchpoint; ++ hw_watchpoint.vaddr = data_breakpoint[i].addr; ++ switch (data_breakpoint[i].type) { ++ case GDB_WATCHPOINT_READ: ++ ret = true; ++ hw_watchpoint.flags = BP_MEM_READ; ++ break; ++ case GDB_WATCHPOINT_WRITE: ++ ret = true; ++ hw_watchpoint.flags = BP_MEM_WRITE; ++ break; ++ case GDB_WATCHPOINT_ACCESS: ++ ret = true; ++ hw_watchpoint.flags = BP_MEM_ACCESS; ++ break; ++ } ++ } ++ } ++ run->debug.arch.exception = 0; ++ run->debug.arch.fwps = 0; ++ run->debug.arch.mwps = 0; ++ } ++ return ret; ++} ++ ++int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) ++{ ++ int ret; ++ ++ DPRINTF("%s\n", __func__); ++ switch (run->exit_reason) { ++ case KVM_EXIT_HYPERCALL: ++ DPRINTF("handle LOONGARCH hypercall\n"); ++ ret = 0; ++ run->hypercall.ret = ret; ++ break; ++ ++ case KVM_EXIT_DEBUG: ++ ret = 0; ++ if (kvm_loongarch_handle_debug(cs, run)) { ++ ret = EXCP_DEBUG; ++ } ++ break; ++ default: ++ error_report("%s: unknown exit reason %d", ++ __func__, run->exit_reason); ++ ret = -1; ++ break; ++ } ++ ++ return ret; ++} ++ ++bool kvm_arch_stop_on_emulation_error(CPUState *cs) ++{ ++ DPRINTF("%s\n", __func__); ++ return true; ++} ++/* ++#if 0 ++int kvmloongarch_load_kernel(CPUState *env, void *ram_base) ++{ ++ int ret; ++ ++ ret = kvm_vcpu_ioctl(env, KVM_LOAD_KERNEL, ram_base); ++ ++ return ret; ++} ++#endif ++*/ ++void kvm_arch_init_irq_routing(KVMState *s) ++{ ++} ++ ++int kvm_loongarch_set_interrupt(LOONGARCHCPU *cpu, int irq, int level) ++{ ++ CPUState *cs = CPU(cpu); ++ struct kvm_loongarch_interrupt intr; ++ ++ if (!kvm_enabled()) { ++ return 0; ++ } ++ ++ intr.cpu = -1; ++ ++ if (level) { ++ intr.irq = irq; ++ } else { ++ intr.irq = -irq; ++ } ++ ++ kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &intr); ++ ++ return 0; ++} ++ ++int kvm_loongarch_set_ipi_interrupt(LOONGARCHCPU *cpu, int irq, int level) ++{ ++ CPUState *cs = current_cpu; ++ CPUState *dest_cs = CPU(cpu); ++ struct kvm_loongarch_interrupt intr; ++ ++ if (!kvm_enabled()) { ++ return 0; ++ } ++ ++ intr.cpu = dest_cs->cpu_index; ++ ++ if (level) { ++ intr.irq = irq; ++ } else { ++ intr.irq = -irq; ++ } ++ ++ DPRINTF("%s: IRQ: %d\n", __func__, intr.irq); ++ if (!current_cpu) { ++ cs = dest_cs; ++ } ++ kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &intr); ++ ++ return 0; ++} ++ ++static inline int kvm_loongarch_put_one_reg(CPUState *cs, uint64_t reg_id, ++ int32_t *addr) ++{ ++ struct kvm_one_reg csrreg = { ++ .id = reg_id, ++ .addr = (uintptr_t)addr ++ }; ++ ++ return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &csrreg); ++} ++ ++static inline int kvm_loongarch_put_one_ureg(CPUState *cs, uint64_t reg_id, ++ uint32_t *addr) ++{ ++ struct kvm_one_reg csrreg = { ++ .id = reg_id, ++ .addr = (uintptr_t)addr ++ }; ++ ++ return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &csrreg); ++} ++ ++static inline int kvm_loongarch_put_one_ulreg(CPUState *cs, uint64_t reg_id, ++ target_ulong *addr) ++{ ++ uint64_t val64 = *addr; ++ struct kvm_one_reg csrreg = { ++ .id = reg_id, ++ .addr = (uintptr_t)&val64 ++ }; ++ ++ return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &csrreg); ++} ++ ++static inline int kvm_loongarch_put_one_reg64(CPUState *cs, int64_t reg_id, ++ int64_t *addr) ++{ ++ struct kvm_one_reg csrreg = { ++ .id = reg_id, ++ .addr = (uintptr_t)addr ++ }; ++ ++ return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &csrreg); ++} ++ ++static inline int kvm_larch_putq(CPUState *cs, uint64_t reg_id, ++ uint64_t *addr) ++{ ++ struct kvm_one_reg csrreg = { ++ .id = reg_id, ++ .addr = (uintptr_t)addr ++ }; ++ ++ return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &csrreg); ++} ++ ++static inline int kvm_loongarch_get_one_reg(CPUState *cs, uint64_t reg_id, ++ int32_t *addr) ++{ ++ struct kvm_one_reg csrreg = { ++ .id = reg_id, ++ .addr = (uintptr_t)addr ++ }; ++ ++ return kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &csrreg); ++} ++ ++static inline int kvm_loongarch_get_one_ureg(CPUState *cs, uint64_t reg_id, ++ uint32_t *addr) ++{ ++ struct kvm_one_reg csrreg = { ++ .id = reg_id, ++ .addr = (uintptr_t)addr ++ }; ++ ++ return kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &csrreg); ++} ++ ++static inline int kvm_loongarch_get_one_ulreg(CPUState *cs, uint64_t reg_id, ++ target_ulong *addr) ++{ ++ int ret; ++ uint64_t val64 = 0; ++ struct kvm_one_reg csrreg = { ++ .id = reg_id, ++ .addr = (uintptr_t)&val64 ++ }; ++ ++ ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &csrreg); ++ if (ret >= 0) { ++ *addr = val64; ++ } ++ return ret; ++} ++ ++static inline int kvm_loongarch_get_one_reg64(CPUState *cs, int64_t reg_id, ++ int64_t *addr) ++{ ++ struct kvm_one_reg csrreg = { ++ .id = reg_id, ++ .addr = (uintptr_t)addr ++ }; ++ ++ return kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &csrreg); ++} ++ ++static inline int kvm_larch_getq(CPUState *cs, uint64_t reg_id, ++ uint64_t *addr) ++{ ++ struct kvm_one_reg csrreg = { ++ .id = reg_id, ++ .addr = (uintptr_t)addr ++ }; ++ ++ return kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &csrreg); ++} ++ ++static inline int kvm_loongarch_change_one_reg(CPUState *cs, uint64_t reg_id, ++ int32_t *addr, int32_t mask) ++{ ++ int err; ++ int32_t tmp, change; ++ ++ err = kvm_loongarch_get_one_reg(cs, reg_id, &tmp); ++ if (err < 0) { ++ return err; ++ } ++ ++ /* only change bits in mask */ ++ change = (*addr ^ tmp) & mask; ++ if (!change) { ++ return 0; ++ } ++ ++ tmp = tmp ^ change; ++ return kvm_loongarch_put_one_reg(cs, reg_id, &tmp); ++} ++ ++static inline int kvm_loongarch_change_one_reg64(CPUState *cs, uint64_t reg_id, ++ int64_t *addr, int64_t mask) ++{ ++ int err; ++ int64_t tmp, change; ++ ++ err = kvm_loongarch_get_one_reg64(cs, reg_id, &tmp); ++ if (err < 0) { ++ DPRINTF("%s: Failed to get CSR_CONFIG7 (%d)\n", __func__, err); ++ return err; ++ } ++ ++ /* only change bits in mask */ ++ change = (*addr ^ tmp) & mask; ++ if (!change) { ++ return 0; ++ } ++ ++ tmp = tmp ^ change; ++ return kvm_loongarch_put_one_reg64(cs, reg_id, &tmp); ++} ++/* ++ * Handle the VM clock being started or stopped ++ */ ++static void kvm_loongarch_update_state(void *opaque, bool running, RunState state) ++{ ++ CPUState *cs = opaque; ++ int ret; ++ LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); ++ ++ /* ++ * If state is already dirty (synced to QEMU) then the KVM timer state is ++ * already saved and can be restored when it is synced back to KVM. ++ */ ++ if (!running) { ++ ret = kvm_larch_getq(cs, ++ KVM_REG_LOONGARCH_COUNTER, &cpu->counter_value); ++ if (ret < 0) { ++ printf("%s: Failed to get counter_value (%d)\n", __func__, ret); ++ } ++ ++ } else { ++ ret = kvm_larch_putq(cs, KVM_REG_LOONGARCH_COUNTER, ++ &(LOONGARCH_CPU(cs))->counter_value); ++ if (ret < 0) { ++ printf("%s: Failed to put counter_value (%d)\n", __func__, ret); ++ } ++ } ++} ++ ++static int kvm_loongarch_put_fpu_registers(CPUState *cs, int level) ++{ ++ LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); ++ CPULOONGARCHState *env = &cpu->env; ++ int err, ret = 0; ++ unsigned int i; ++ struct kvm_fpu fpu; ++ ++ fpu.fcsr = env->active_fpu.fcsr0; ++ for (i = 0; i < 32; i++) { ++ memcpy(&fpu.fpr[i], &env->active_fpu.fpr[i], sizeof(struct kvm_fpureg)); ++ } ++ for (i = 0; i < 8; i++) { ++ ((char *)&fpu.fcc)[i] = env->active_fpu.cf[i]; ++ } ++ fpu.vcsr = env->active_fpu.vcsr16; ++ ++ err = kvm_vcpu_ioctl(cs, KVM_SET_FPU, &fpu); ++ if (err < 0) { ++ DPRINTF("%s: Failed to get FPU (%d)\n", __func__, err); ++ ret = err; ++ } ++ ++ return ret; ++} ++ ++static int kvm_loongarch_get_fpu_registers(CPUState *cs) ++{ ++ LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); ++ CPULOONGARCHState *env = &cpu->env; ++ int err, ret = 0; ++ unsigned int i; ++ struct kvm_fpu fpu; ++ ++ err = kvm_vcpu_ioctl(cs, KVM_GET_FPU, &fpu); ++ if (err < 0) { ++ DPRINTF("%s: Failed to get FPU (%d)\n", __func__, err); ++ ret = err; ++ } else { ++ env->active_fpu.fcsr0 = fpu.fcsr; ++ for (i = 0; i < 32; i++) { ++ memcpy(&env->active_fpu.fpr[i], &fpu.fpr[i], sizeof(struct kvm_fpureg)); ++ } ++ for (i = 0; i < 8; i++) { ++ env->active_fpu.cf[i] = ((char *)&fpu.fcc)[i]; ++ } ++ env->active_fpu.vcsr16 = fpu.vcsr; ++ } ++ ++ return ret; ++} ++ ++#define KVM_PUT_ONE_UREG64(cs, regidx, addr) \ ++ ({ \ ++ int err; \ ++ uint64_t csrid = 0; \ ++ csrid = (KVM_IOC_CSRID(regidx)); \ ++ err = kvm_larch_putq(cs, csrid, addr); \ ++ if (err < 0) { \ ++ DPRINTF("%s: Failed to put regidx 0x%x err:%d\n", __func__, regidx, err); \ ++ } \ ++ err; \ ++ }) ++ ++ ++static int kvm_loongarch_put_csr_registers(CPUState *cs, int level) ++{ ++ LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); ++ CPULOONGARCHState *env = &cpu->env; ++ int ret = 0; ++ ++ (void)level; ++ ++ kvm_msr_buf_reset(cpu); ++ ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_CRMD, env->CSR_CRMD); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PRMD, env->CSR_PRMD); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_EUEN, env->CSR_EUEN); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_MISC, env->CSR_MISC); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_ECFG, env->CSR_ECFG); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_ESTAT, env->CSR_ESTAT); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_ERA, env->CSR_ERA); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_BADV, env->CSR_BADV); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_BADI, env->CSR_BADI); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_EEPN, env->CSR_EEPN); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBIDX, env->CSR_TLBIDX); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBEHI, env->CSR_TLBEHI); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBELO0, env->CSR_TLBELO0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBELO1, env->CSR_TLBELO1); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_GTLBC, env->CSR_GTLBC); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_TRGP, env->CSR_TRGP); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_ASID, env->CSR_ASID); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PGDL, env->CSR_PGDL); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PGDH, env->CSR_PGDH); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PGD, env->CSR_PGD); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PWCTL0, env->CSR_PWCTL0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PWCTL1, env->CSR_PWCTL1); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_STLBPGSIZE, env->CSR_STLBPGSIZE); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_RVACFG, env->CSR_RVACFG); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_CPUID, env->CSR_CPUID); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PRCFG1, env->CSR_PRCFG1); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PRCFG2, env->CSR_PRCFG2); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PRCFG3, env->CSR_PRCFG3); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS0, env->CSR_KS0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS1, env->CSR_KS1); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS2, env->CSR_KS2); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS3, env->CSR_KS3); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS4, env->CSR_KS4); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS5, env->CSR_KS5); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS6, env->CSR_KS6); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS7, env->CSR_KS7); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_TMID, env->CSR_TMID); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_CNTC, env->CSR_CNTC); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_TINTCLR, env->CSR_TINTCLR); ++ ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_GSTAT, env->CSR_GSTAT); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_GCFG, env->CSR_GCFG); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_GINTC, env->CSR_GINTC); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_GCNTC, env->CSR_GCNTC); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_LLBCTL, env->CSR_LLBCTL); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IMPCTL1, env->CSR_IMPCTL1); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IMPCTL2, env->CSR_IMPCTL2); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_GNMI, env->CSR_GNMI); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBRENT, env->CSR_TLBRENT); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBRBADV, env->CSR_TLBRBADV); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBRERA, env->CSR_TLBRERA); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBRSAVE, env->CSR_TLBRSAVE); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBRELO0, env->CSR_TLBRELO0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBRELO1, env->CSR_TLBRELO1); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBREHI, env->CSR_TLBREHI); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBRPRMD, env->CSR_TLBRPRMD); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_ERRCTL, env->CSR_ERRCTL); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_ERRINFO, env->CSR_ERRINFO); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_ERRINFO1, env->CSR_ERRINFO1); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_ERRENT, env->CSR_ERRENT); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_ERRERA, env->CSR_ERRERA); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_ERRSAVE, env->CSR_ERRSAVE); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_CTAG, env->CSR_CTAG); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DMWIN0, env->CSR_DMWIN0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DMWIN1, env->CSR_DMWIN1); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DMWIN2, env->CSR_DMWIN2); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DMWIN3, env->CSR_DMWIN3); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCTRL0, env->CSR_PERFCTRL0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCNTR0, env->CSR_PERFCNTR0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCTRL1, env->CSR_PERFCTRL1); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCNTR1, env->CSR_PERFCNTR1); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCTRL2, env->CSR_PERFCTRL2); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCNTR2, env->CSR_PERFCNTR2); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCTRL3, env->CSR_PERFCTRL3); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCNTR3, env->CSR_PERFCNTR3); ++ ++ /* debug */ ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_MWPC, env->CSR_MWPC); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_MWPS, env->CSR_MWPS); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB0ADDR, env->CSR_DB0ADDR); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB0MASK, env->CSR_DB0MASK); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB0CTL, env->CSR_DB0CTL); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB0ASID, env->CSR_DB0ASID); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB1ADDR, env->CSR_DB1ADDR); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB1MASK, env->CSR_DB1MASK); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB1CTL, env->CSR_DB1CTL); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB1ASID, env->CSR_DB1ASID); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB2ADDR, env->CSR_DB2ADDR); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB2MASK, env->CSR_DB2MASK); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB2CTL, env->CSR_DB2CTL); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB2ASID, env->CSR_DB2ASID); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB3ADDR, env->CSR_DB3ADDR); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB3MASK, env->CSR_DB3MASK); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB3CTL, env->CSR_DB3CTL); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB3ASID, env->CSR_DB3ASID); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_FWPC, env->CSR_FWPC); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_FWPS, env->CSR_FWPS); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB0ADDR, env->CSR_IB0ADDR); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB0MASK, env->CSR_IB0MASK); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB0CTL, env->CSR_IB0CTL); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB0ASID, env->CSR_IB0ASID); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB1ADDR, env->CSR_IB1ADDR); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB1MASK, env->CSR_IB1MASK); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB1CTL, env->CSR_IB1CTL); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB1ASID, env->CSR_IB1ASID); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB2ADDR, env->CSR_IB2ADDR); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB2MASK, env->CSR_IB2MASK); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB2CTL, env->CSR_IB2CTL); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB2ASID, env->CSR_IB2ASID); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB3ADDR, env->CSR_IB3ADDR); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB3MASK, env->CSR_IB3MASK); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB3CTL, env->CSR_IB3CTL); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB3ASID, env->CSR_IB3ASID); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB4ADDR, env->CSR_IB4ADDR); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB4MASK, env->CSR_IB4MASK); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB4CTL, env->CSR_IB4CTL); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB4ASID, env->CSR_IB4ASID); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB5ADDR, env->CSR_IB5ADDR); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB5MASK, env->CSR_IB5MASK); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB5CTL, env->CSR_IB5CTL); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB5ASID, env->CSR_IB5ASID); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB6ADDR, env->CSR_IB6ADDR); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB6MASK, env->CSR_IB6MASK); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB6CTL, env->CSR_IB6CTL); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB6ASID, env->CSR_IB6ASID); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB7ADDR, env->CSR_IB7ADDR); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB7MASK, env->CSR_IB7MASK); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB7CTL, env->CSR_IB7CTL); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB7ASID, env->CSR_IB7ASID); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DEBUG, env->CSR_DEBUG); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DERA, env->CSR_DERA); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DESAVE, env->CSR_DESAVE); ++ ++ ret = kvm_vcpu_ioctl(cs, KVM_SET_MSRS, cpu->kvm_msr_buf); ++ if (ret < cpu->kvm_msr_buf->ncsrs) { ++ struct kvm_csr_entry *e = &cpu->kvm_msr_buf->entries[ret]; ++ printf("error: failed to set CSR 0x%" PRIx32 " to 0x%" PRIx64"\n", ++ (uint32_t)e->index, (uint64_t)e->data); ++ } ++ ++ /* ++ * timer cfg must be put at last since it is used to enable ++ * guest timer ++ */ ++ ret |= KVM_PUT_ONE_UREG64(cs, LOONGARCH_CSR_TVAL, &env->CSR_TVAL); ++ ret |= KVM_PUT_ONE_UREG64(cs, LOONGARCH_CSR_TCFG, &env->CSR_TCFG); ++ return ret; ++} ++ ++#define KVM_GET_ONE_UREG64(cs, regidx, addr) \ ++ ({ \ ++ int err; \ ++ uint64_t csrid = 0; \ ++ csrid = (KVM_IOC_CSRID(regidx)); \ ++ err = kvm_larch_getq(cs, csrid, addr); \ ++ if (err < 0) { \ ++ DPRINTF("%s: Failed to put regidx 0x%x err:%d\n", __func__, regidx, err); \ ++ } \ ++ err; \ ++ }) ++ ++static int kvm_loongarch_get_csr_registers(CPUState *cs) ++{ ++ LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); ++ CPULOONGARCHState *env = &cpu->env; ++ int ret = 0, i; ++ struct kvm_csr_entry *csrs = cpu->kvm_msr_buf->entries; ++ ++ kvm_msr_buf_reset(cpu); ++ ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_CRMD, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PRMD, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_EUEN, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_MISC, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_ECFG, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_ESTAT, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_ERA, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_BADV, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_BADI, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_EEPN, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBIDX, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBEHI, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBELO0, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBELO1, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_GTLBC, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_TRGP, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_ASID, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PGDL, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PGDH, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PGD, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PWCTL0, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PWCTL1, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_STLBPGSIZE, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_RVACFG, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_CPUID, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PRCFG1, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PRCFG2, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PRCFG3, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS0, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS1, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS2, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS3, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS4, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS5, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS6, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS7, 0); ++ ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_TMID, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_CNTC, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_TINTCLR, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_GSTAT, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_GCFG, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_GINTC, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_GCNTC, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_LLBCTL, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IMPCTL1, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IMPCTL2, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_GNMI, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBRENT, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBRBADV, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBRERA, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBRSAVE, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBRELO0, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBRELO1, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBREHI, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBRPRMD, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_ERRCTL, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_ERRINFO, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_ERRINFO1, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_ERRENT, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_ERRERA, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_ERRSAVE, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_CTAG, 0); ++ ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DMWIN0, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DMWIN1, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DMWIN2, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DMWIN3, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCTRL0, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCNTR0, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCTRL1, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCNTR1, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCTRL2, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCNTR2, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCTRL3, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCNTR3, 0); ++ ++ /* debug */ ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_MWPC, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_MWPS, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB0ADDR, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB0MASK, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB0CTL, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB0ASID, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB1ADDR, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB1MASK, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB1CTL, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB1ASID, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB2ADDR, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB2MASK, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB2CTL, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB2ASID, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB3ADDR, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB3MASK, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB3CTL, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB3ASID, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_FWPC, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_FWPS, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB0ADDR, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB0MASK, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB0CTL, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB0ASID, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB1ADDR, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB1MASK, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB1CTL, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB1ASID, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB2ADDR, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB2MASK, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB2CTL, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB2ASID, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB3ADDR, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB3MASK, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB3CTL, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB3ASID, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB4ADDR, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB4MASK, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB4CTL, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB4ASID, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB5ADDR, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB5MASK, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB5CTL, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB5ASID, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB6ADDR, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB6MASK, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB6CTL, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB6ASID, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB7ADDR, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB7MASK, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB7CTL, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB7ASID, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DEBUG, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DERA, 0); ++ kvm_msr_entry_add(cpu, LOONGARCH_CSR_DESAVE, 0); ++ ++ ret = kvm_vcpu_ioctl(cs, KVM_GET_MSRS, cpu->kvm_msr_buf); ++ if (ret < cpu->kvm_msr_buf->ncsrs) { ++ struct kvm_csr_entry *e = &cpu->kvm_msr_buf->entries[ret]; ++ printf("error: failed to get CSR 0x%" PRIx32"\n", ++ (uint32_t)e->index); ++ } ++ ++ for (i = 0; i < ret; i++) { ++ uint32_t index = csrs[i].index; ++ ++ switch (index) { ++ case LOONGARCH_CSR_CRMD: ++ env->CSR_CRMD = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_PRMD: ++ env->CSR_PRMD = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_EUEN: ++ env->CSR_EUEN = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_MISC: ++ env->CSR_MISC = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_ECFG: ++ env->CSR_ECFG = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_ESTAT: ++ env->CSR_ESTAT = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_ERA: ++ env->CSR_ERA = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_BADV: ++ env->CSR_BADV = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_BADI: ++ env->CSR_BADI = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_EEPN: ++ env->CSR_EEPN = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_TLBIDX: ++ env->CSR_TLBIDX = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_TLBEHI: ++ env->CSR_TLBEHI = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_TLBELO0: ++ env->CSR_TLBELO0 = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_TLBELO1: ++ env->CSR_TLBELO1 = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_GTLBC: ++ env->CSR_GTLBC = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_TRGP: ++ env->CSR_TRGP = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_ASID: ++ env->CSR_ASID = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_PGDL: ++ env->CSR_PGDL = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_PGDH: ++ env->CSR_PGDH = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_PGD: ++ env->CSR_PGD = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_PWCTL0: ++ env->CSR_PWCTL0 = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_PWCTL1: ++ env->CSR_PWCTL1 = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_STLBPGSIZE: ++ env->CSR_STLBPGSIZE = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_RVACFG: ++ env->CSR_RVACFG = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_CPUID: ++ env->CSR_CPUID = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_PRCFG1: ++ env->CSR_PRCFG1 = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_PRCFG2: ++ env->CSR_PRCFG2 = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_PRCFG3: ++ env->CSR_PRCFG3 = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_KS0: ++ env->CSR_KS0 = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_KS1: ++ env->CSR_KS1 = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_KS2: ++ env->CSR_KS2 = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_KS3: ++ env->CSR_KS3 = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_KS4: ++ env->CSR_KS4 = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_KS5: ++ env->CSR_KS5 = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_KS6: ++ env->CSR_KS6 = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_KS7: ++ env->CSR_KS7 = csrs[i].data; ++ break; ++ ++ case LOONGARCH_CSR_TMID: ++ env->CSR_TMID = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_CNTC: ++ env->CSR_CNTC = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_TINTCLR: ++ env->CSR_TINTCLR = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_GSTAT: ++ env->CSR_GSTAT = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_GCFG: ++ env->CSR_GCFG = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_GINTC: ++ env->CSR_GINTC = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_GCNTC: ++ env->CSR_GCNTC = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_LLBCTL: ++ env->CSR_LLBCTL = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_IMPCTL1: ++ env->CSR_IMPCTL1 = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_IMPCTL2: ++ env->CSR_IMPCTL2 = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_GNMI: ++ env->CSR_GNMI = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_TLBRENT: ++ env->CSR_TLBRENT = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_TLBRBADV: ++ env->CSR_TLBRBADV = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_TLBRERA: ++ env->CSR_TLBRERA = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_TLBRSAVE: ++ env->CSR_TLBRSAVE = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_TLBRELO0: ++ env->CSR_TLBRELO0 = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_TLBRELO1: ++ env->CSR_TLBRELO1 = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_TLBREHI: ++ env->CSR_TLBREHI = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_TLBRPRMD: ++ env->CSR_TLBRPRMD = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_ERRCTL: ++ env->CSR_ERRCTL = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_ERRINFO: ++ env->CSR_ERRINFO = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_ERRINFO1: ++ env->CSR_ERRINFO1 = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_ERRENT: ++ env->CSR_ERRENT = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_ERRERA: ++ env->CSR_ERRERA = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_ERRSAVE: ++ env->CSR_ERRSAVE = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_CTAG: ++ env->CSR_CTAG = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_DMWIN0: ++ env->CSR_DMWIN0 = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_DMWIN1: ++ env->CSR_DMWIN1 = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_DMWIN2: ++ env->CSR_DMWIN2 = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_DMWIN3: ++ env->CSR_DMWIN3 = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_PERFCTRL0: ++ env->CSR_PERFCTRL0 = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_PERFCNTR0: ++ env->CSR_PERFCNTR0 = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_PERFCTRL1: ++ env->CSR_PERFCTRL1 = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_PERFCNTR1: ++ env->CSR_PERFCNTR1 = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_PERFCTRL2: ++ env->CSR_PERFCTRL2 = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_PERFCNTR2: ++ env->CSR_PERFCNTR2 = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_PERFCTRL3: ++ env->CSR_PERFCTRL3 = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_PERFCNTR3: ++ env->CSR_PERFCNTR3 = csrs[i].data; ++ break; ++ ++ case LOONGARCH_CSR_MWPC: ++ env->CSR_MWPC = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_MWPS: ++ env->CSR_MWPS = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_DB0ADDR: ++ env->CSR_DB0ADDR = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_DB0MASK: ++ env->CSR_DB0MASK = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_DB0CTL: ++ env->CSR_DB0CTL = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_DB0ASID: ++ env->CSR_DB0ASID = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_DB1ADDR: ++ env->CSR_DB1ADDR = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_DB1MASK: ++ env->CSR_DB1MASK = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_DB1CTL: ++ env->CSR_DB1CTL = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_DB1ASID: ++ env->CSR_DB1ASID = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_DB2ADDR: ++ env->CSR_DB2ADDR = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_DB2MASK: ++ env->CSR_DB2MASK = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_DB2CTL: ++ env->CSR_DB2CTL = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_DB2ASID: ++ env->CSR_DB2ASID = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_DB3ADDR: ++ env->CSR_DB3ADDR = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_DB3MASK: ++ env->CSR_DB3MASK = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_DB3CTL: ++ env->CSR_DB3CTL = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_DB3ASID: ++ env->CSR_DB3ASID = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_FWPC: ++ env->CSR_FWPC = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_FWPS: ++ env->CSR_FWPS = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_IB0ADDR: ++ env->CSR_IB0ADDR = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_IB0MASK: ++ env->CSR_IB0MASK = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_IB0CTL: ++ env->CSR_IB0CTL = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_IB0ASID: ++ env->CSR_IB0ASID = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_IB1ADDR: ++ env->CSR_IB1ADDR = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_IB1MASK: ++ env->CSR_IB1MASK = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_IB1CTL: ++ env->CSR_IB1CTL = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_IB1ASID: ++ env->CSR_IB1ASID = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_IB2ADDR: ++ env->CSR_IB2ADDR = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_IB2MASK: ++ env->CSR_IB2MASK = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_IB2CTL: ++ env->CSR_IB2CTL = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_IB2ASID: ++ env->CSR_IB2ASID = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_IB3ADDR: ++ env->CSR_IB3ADDR = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_IB3MASK: ++ env->CSR_IB3MASK = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_IB3CTL: ++ env->CSR_IB3CTL = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_IB3ASID: ++ env->CSR_IB3ASID = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_IB4ADDR: ++ env->CSR_IB4ADDR = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_IB4MASK: ++ env->CSR_IB4MASK = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_IB4CTL: ++ env->CSR_IB4CTL = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_IB4ASID: ++ env->CSR_IB4ASID = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_IB5ADDR: ++ env->CSR_IB5ADDR = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_IB5MASK: ++ env->CSR_IB5MASK = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_IB5CTL: ++ env->CSR_IB5CTL = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_IB5ASID: ++ env->CSR_IB5ASID = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_IB6ADDR: ++ env->CSR_IB6ADDR = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_IB6MASK: ++ env->CSR_IB6MASK = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_IB6CTL: ++ env->CSR_IB6CTL = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_IB6ASID: ++ env->CSR_IB6ASID = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_IB7ADDR: ++ env->CSR_IB7ADDR = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_IB7MASK: ++ env->CSR_IB7MASK = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_IB7CTL: ++ env->CSR_IB7CTL = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_IB7ASID: ++ env->CSR_IB7ASID = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_DEBUG: ++ env->CSR_DEBUG = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_DERA: ++ env->CSR_DERA = csrs[i].data; ++ break; ++ case LOONGARCH_CSR_DESAVE: ++ env->CSR_DESAVE = csrs[i].data; ++ break; ++ default: ++ break; ++ } ++ } ++ ++ ret |= KVM_GET_ONE_UREG64(cs, LOONGARCH_CSR_TVAL, &env->CSR_TVAL); ++ ret |= KVM_GET_ONE_UREG64(cs, LOONGARCH_CSR_TCFG, &env->CSR_TCFG); ++ return ret; ++} ++ ++int kvm_loongarch_put_pvtime(LOONGARCHCPU *cpu) ++{ ++ CPULOONGARCHState *env = &cpu->env; ++ int err; ++ struct kvm_device_attr attr = { ++ .group = KVM_LARCH_VCPU_PVTIME_CTRL, ++ .attr = KVM_LARCH_VCPU_PVTIME_IPA, ++ .addr = (uint64_t)&env->st.guest_addr, ++ }; ++ ++ err = kvm_vcpu_ioctl(CPU(cpu), KVM_HAS_DEVICE_ATTR, attr); ++ if (err != 0) { ++ /* It's ok even though kvm has not such attr */ ++ return 0; ++ } ++ ++ err = kvm_vcpu_ioctl(CPU(cpu), KVM_SET_DEVICE_ATTR, attr); ++ if (err != 0) { ++ error_report("PVTIME IPA: KVM_SET_DEVICE_ATTR: %s", strerror(-err)); ++ return err; ++ } ++ ++ return 0; ++} ++ ++int kvm_loongarch_get_pvtime(LOONGARCHCPU *cpu) ++{ ++ CPULOONGARCHState *env = &cpu->env; ++ int err; ++ struct kvm_device_attr attr = { ++ .group = KVM_LARCH_VCPU_PVTIME_CTRL, ++ .attr = KVM_LARCH_VCPU_PVTIME_IPA, ++ .addr = (uint64_t)&env->st.guest_addr, ++ }; ++ ++ err = kvm_vcpu_ioctl(CPU(cpu), KVM_HAS_DEVICE_ATTR, attr); ++ if (err != 0) { ++ /* It's ok even though kvm has not such attr */ ++ return 0; ++ } ++ ++ err = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_DEVICE_ATTR, attr); ++ if (err != 0) { ++ error_report("PVTIME IPA: KVM_GET_DEVICE_ATTR: %s", strerror(-err)); ++ return err; ++ } ++ ++ return 0; ++} ++ ++int kvm_arch_put_registers(CPUState *cs, int level) ++{ ++ LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); ++ CPULOONGARCHState *env = &cpu->env; ++ struct kvm_regs regs; ++ int ret; ++ int i; ++ ++ /* Set the registers based on QEMU's view of things */ ++ for (i = 0; i < 32; i++) { ++ regs.gpr[i] = (int64_t)(target_long)env->active_tc.gpr[i]; ++ } ++ ++ regs.pc = (int64_t)(target_long)env->active_tc.PC; ++ ++ ret = kvm_vcpu_ioctl(cs, KVM_SET_REGS, ®s); ++ ++ if (ret < 0) { ++ return ret; ++ } ++ ++ ret = kvm_loongarch_put_csr_registers(cs, level); ++ if (ret < 0) { ++ return ret; ++ } ++ ++ ret = kvm_loongarch_put_fpu_registers(cs, level); ++ if (ret < 0) { ++ return ret; ++ } ++ ++ return ret; ++} ++ ++int kvm_arch_get_registers(CPUState *cs) ++{ ++ LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); ++ CPULOONGARCHState *env = &cpu->env; ++ int ret = 0; ++ struct kvm_regs regs; ++ int i; ++ ++ /* Get the current register set as KVM seems it */ ++ ret = kvm_vcpu_ioctl(cs, KVM_GET_REGS, ®s); ++ ++ if (ret < 0) { ++ return ret; ++ } ++ ++ for (i = 0; i < 32; i++) { ++ env->active_tc.gpr[i] = regs.gpr[i]; ++ } ++ ++ env->active_tc.PC = regs.pc; ++ ++ kvm_loongarch_get_csr_registers(cs); ++ kvm_loongarch_get_fpu_registers(cs); ++ ++ return ret; ++} ++ ++int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, ++ uint64_t address, uint32_t data, PCIDevice *dev) ++{ ++ return 0; ++} ++ ++int kvm_arch_add_msi_route_post(struct kvm_irq_routing_entry *route, ++ int vector, PCIDevice *dev) ++{ ++ return 0; ++} ++ ++bool kvm_arch_cpu_check_are_resettable(void) ++{ ++ return true; ++} ++ ++int kvm_arch_release_virq_post(int virq) ++{ ++ return 0; ++} ++ ++int kvm_arch_msi_data_to_gsi(uint32_t data) ++{ ++ abort(); ++} +diff --git a/target/loongarch64/kvm_larch.h b/target/loongarch64/kvm_larch.h +new file mode 100644 +index 0000000000..a56026d10c +--- /dev/null ++++ b/target/loongarch64/kvm_larch.h +@@ -0,0 +1,41 @@ ++/* ++ * This file is subject to the terms and conditions of the GNU General Public ++ * License. See the file "COPYING" in the main directory of this archive ++ * for more details. ++ * ++ * KVM/LOONGARCH: LOONGARCH specific KVM APIs ++ * ++ * Copyright (C) 2012-2014 Imagination Technologies Ltd. ++ * Authors: Sanjay Lal ++*/ ++ ++#ifndef KVM_LOONGARCH_H ++#define KVM_LOONGARCH_H ++ ++/** ++ * kvm_loongarch_reset_vcpu: ++ * @cpu: LOONGARCHCPU ++ * ++ * Called at reset time to set kernel registers to their initial values. ++ */ ++void kvm_loongarch_reset_vcpu(LOONGARCHCPU *cpu); ++ ++int kvm_loongarch_set_interrupt(LOONGARCHCPU *cpu, int irq, int level); ++int kvm_loongarch_set_ipi_interrupt(LOONGARCHCPU *cpu, int irq, int level); ++ ++int kvm_loongarch_put_pvtime(LOONGARCHCPU *cpu); ++int kvm_loongarch_get_pvtime(LOONGARCHCPU *cpu); ++ ++#ifndef KVM_INTERRUPT_SET ++#define KVM_INTERRUPT_SET -1 ++#endif ++ ++#ifndef KVM_INTERRUPT_UNSET ++#define KVM_INTERRUPT_UNSET -2 ++#endif ++ ++#ifndef KVM_INTERRUPT_SET_LEVEL ++#define KVM_INTERRUPT_SET_LEVEL -3 ++#endif ++ ++#endif /* KVM_LOONGARCH_H */ +diff --git a/target/loongarch64/larch-defs.h b/target/loongarch64/larch-defs.h +new file mode 100644 +index 0000000000..d3a61cf255 +--- /dev/null ++++ b/target/loongarch64/larch-defs.h +@@ -0,0 +1,27 @@ ++#ifndef QEMU_LOONGARCH_DEFS_H ++#define QEMU_LOONGARCH_DEFS_H ++ ++/* If we want to use host float regs... */ ++/* #define USE_HOST_FLOAT_REGS */ ++ ++/* Real pages are variable size... */ ++#define TARGET_PAGE_BITS 14 ++ ++#define LOONGARCH_TLB_MAX 2112 ++ ++#define TARGET_LONG_BITS 64 ++#define TARGET_PHYS_ADDR_SPACE_BITS 48 ++#define TARGET_VIRT_ADDR_SPACE_BITS 48 ++ ++/* ++ * bit definitions for insn_flags (ISAs/ASEs flags) ++ * ------------------------------------------------ ++ */ ++#define ISA_LARCH32 0x00000001ULL ++#define ISA_LARCH64 0x00000002ULL ++#define INSN_LOONGARCH 0x00010000ULL ++ ++#define CPU_LARCH32 (ISA_LARCH32) ++#define CPU_LARCH64 (ISA_LARCH32 | ISA_LARCH64) ++ ++#endif /* QEMU_LOONGARCH_DEFS_H */ +diff --git a/target/loongarch64/machine.c b/target/loongarch64/machine.c +new file mode 100644 +index 0000000000..b69bca6a9b +--- /dev/null ++++ b/target/loongarch64/machine.c +@@ -0,0 +1,416 @@ ++#include "qemu/osdep.h" ++#include "qemu-common.h" ++#include "cpu.h" ++#include "internal.h" ++#include "hw/hw.h" ++#include "kvm_larch.h" ++#include "migration/cpu.h" ++#include "linux/kvm.h" ++#include "sysemu/kvm.h" ++#include "qemu/error-report.h" ++ ++static int cpu_post_load(void *opaque, int version_id) ++{ ++ LOONGARCHCPU *cpu = opaque; ++ CPULOONGARCHState *env = &cpu->env; ++ int r = 0; ++ ++#ifdef CONFIG_KVM ++ struct kvm_loongarch_vcpu_state vcpu_state; ++ int i; ++ ++ vcpu_state.online_vcpus = cpu->online_vcpus; ++ vcpu_state.is_migrate = cpu->is_migrate; ++ vcpu_state.cpu_freq = cpu->cpu_freq; ++ vcpu_state.count_ctl = cpu->count_ctl; ++ vcpu_state.pending_exceptions = cpu->pending_exceptions; ++ vcpu_state.pending_exceptions_clr = cpu->pending_exceptions_clr; ++ for (i = 0; i < 4; i++) { ++ vcpu_state.core_ext_ioisr[i] = cpu->core_ext_ioisr[i]; ++ } ++ r = kvm_vcpu_ioctl(CPU(cpu), KVM_LARCH_SET_VCPU_STATE, &vcpu_state); ++ if (r) { ++ error_report("set vcpu state failed %d", r); ++ } ++ ++ kvm_loongarch_put_pvtime(cpu); ++#endif ++ ++ restore_fp_status(env); ++ compute_hflags(env); ++ ++ return r; ++} ++ ++static int cpu_pre_save(void *opaque) ++{ ++#ifdef CONFIG_KVM ++ LOONGARCHCPU *cpu = opaque; ++ struct kvm_loongarch_vcpu_state vcpu_state; ++ int i, r = 0; ++ ++ r = kvm_vcpu_ioctl(CPU(cpu), KVM_LARCH_GET_VCPU_STATE, &vcpu_state); ++ if (r < 0) { ++ error_report("get vcpu state failed %d", r); ++ return r; ++ } ++ ++ cpu->online_vcpus = vcpu_state.online_vcpus; ++ cpu->is_migrate = vcpu_state.is_migrate; ++ cpu->cpu_freq = vcpu_state.cpu_freq; ++ cpu->count_ctl = vcpu_state.count_ctl; ++ cpu->pending_exceptions = vcpu_state.pending_exceptions; ++ cpu->pending_exceptions_clr = vcpu_state.pending_exceptions_clr; ++ for (i = 0; i < 4; i++) { ++ cpu->core_ext_ioisr[i] = vcpu_state.core_ext_ioisr[i]; ++ } ++ ++ kvm_loongarch_get_pvtime(cpu); ++#endif ++ return 0; ++} ++ ++/* FPU state */ ++ ++static int get_fpr(QEMUFile *f, void *pv, size_t size, ++ const VMStateField *field) ++{ ++ fpr_t *v = pv; ++ qemu_get_be64s(f, &v->d); ++ return 0; ++} ++ ++static int put_fpr(QEMUFile *f, void *pv, size_t size, ++ const VMStateField *field, JSONWriter *vmdesc) ++{ ++ fpr_t *v = pv; ++ qemu_put_be64s(f, &v->d); ++ return 0; ++} ++ ++const VMStateInfo vmstate_info_fpr = { ++ .name = "fpr", ++ .get = get_fpr, ++ .put = put_fpr, ++}; ++ ++#define VMSTATE_FPR_ARRAY_V(_f, _s, _n, _v) \ ++ VMSTATE_ARRAY(_f, _s, _n, _v, vmstate_info_fpr, fpr_t) ++ ++#define VMSTATE_FPR_ARRAY(_f, _s, _n) \ ++ VMSTATE_FPR_ARRAY_V(_f, _s, _n, 0) ++ ++static VMStateField vmstate_fpu_fields[] = { ++ VMSTATE_FPR_ARRAY(fpr, CPULOONGARCHFPUContext, 32), ++ VMSTATE_UINT32(fcsr0, CPULOONGARCHFPUContext), ++ VMSTATE_END_OF_LIST() ++}; ++ ++const VMStateDescription vmstate_fpu = { ++ .name = "cpu/fpu", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .fields = vmstate_fpu_fields ++}; ++ ++const VMStateDescription vmstate_inactive_fpu = { ++ .name = "cpu/inactive_fpu", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .fields = vmstate_fpu_fields ++}; ++ ++/* TC state */ ++ ++static VMStateField vmstate_tc_fields[] = { ++ VMSTATE_UINTTL_ARRAY(gpr, TCState, 32), ++ VMSTATE_UINTTL(PC, TCState), ++ VMSTATE_END_OF_LIST() ++}; ++ ++const VMStateDescription vmstate_tc = { ++ .name = "cpu/tc", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .fields = vmstate_tc_fields ++}; ++ ++const VMStateDescription vmstate_inactive_tc = { ++ .name = "cpu/inactive_tc", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .fields = vmstate_tc_fields ++}; ++ ++/* TLB state */ ++ ++static int get_tlb(QEMUFile *f, void *pv, size_t size, ++ const VMStateField *field) ++{ ++ ls3a5k_tlb_t *v = pv; ++ uint32_t flags; ++ ++ qemu_get_betls(f, &v->VPN); ++ qemu_get_be64s(f, &v->PageMask); ++ qemu_get_be32s(f, &v->PageSize); ++ qemu_get_be16s(f, &v->ASID); ++ qemu_get_be32s(f, &flags); ++ v->RPLV1 = (flags >> 21) & 1; ++ v->RPLV0 = (flags >> 20) & 1; ++ v->PLV1 = (flags >> 18) & 3; ++ v->PLV0 = (flags >> 16) & 3; ++ v->EHINV = (flags >> 15) & 1; ++ v->RI1 = (flags >> 14) & 1; ++ v->RI0 = (flags >> 13) & 1; ++ v->XI1 = (flags >> 12) & 1; ++ v->XI0 = (flags >> 11) & 1; ++ v->WE1 = (flags >> 10) & 1; ++ v->WE0 = (flags >> 9) & 1; ++ v->V1 = (flags >> 8) & 1; ++ v->V0 = (flags >> 7) & 1; ++ v->C1 = (flags >> 4) & 7; ++ v->C0 = (flags >> 1) & 7; ++ v->G = (flags >> 0) & 1; ++ qemu_get_be64s(f, &v->PPN0); ++ qemu_get_be64s(f, &v->PPN1); ++ ++ return 0; ++} ++ ++static int put_tlb(QEMUFile *f, void *pv, size_t size, ++ const VMStateField *field, JSONWriter *vmdesc) ++{ ++ ls3a5k_tlb_t *v = pv; ++ ++ uint16_t asid = v->ASID; ++ uint32_t flags = ((v->RPLV1 << 21) | ++ (v->RPLV0 << 20) | ++ (v->PLV1 << 18) | ++ (v->PLV0 << 16) | ++ (v->EHINV << 15) | ++ (v->RI1 << 14) | ++ (v->RI0 << 13) | ++ (v->XI1 << 12) | ++ (v->XI0 << 11) | ++ (v->WE1 << 10) | ++ (v->WE0 << 9) | ++ (v->V1 << 8) | ++ (v->V0 << 7) | ++ (v->C1 << 4) | ++ (v->C0 << 1) | ++ (v->G << 0)); ++ ++ qemu_put_betls(f, &v->VPN); ++ qemu_put_be64s(f, &v->PageMask); ++ qemu_put_be32s(f, &v->PageSize); ++ qemu_put_be16s(f, &asid); ++ qemu_put_be32s(f, &flags); ++ qemu_put_be64s(f, &v->PPN0); ++ qemu_put_be64s(f, &v->PPN1); ++ ++ return 0; ++} ++ ++const VMStateInfo vmstate_info_tlb = { ++ .name = "tlb_entry", ++ .get = get_tlb, ++ .put = put_tlb, ++}; ++ ++#define VMSTATE_TLB_ARRAY_V(_f, _s, _n, _v) \ ++ VMSTATE_ARRAY(_f, _s, _n, _v, vmstate_info_tlb, ls3a5k_tlb_t) ++ ++#define VMSTATE_TLB_ARRAY(_f, _s, _n) \ ++ VMSTATE_TLB_ARRAY_V(_f, _s, _n, 0) ++ ++const VMStateDescription vmstate_tlb = { ++ .name = "cpu/tlb", ++ .version_id = 2, ++ .minimum_version_id = 2, ++ .fields = (VMStateField[]) { ++ VMSTATE_UINT32(nb_tlb, CPULOONGARCHTLBContext), ++ VMSTATE_UINT32(tlb_in_use, CPULOONGARCHTLBContext), ++ VMSTATE_TLB_ARRAY(mmu.ls3a5k.tlb, CPULOONGARCHTLBContext, LOONGARCH_TLB_MAX), ++ VMSTATE_END_OF_LIST() ++ } ++}; ++ ++/* LOONGARCH CPU state */ ++ ++const VMStateDescription vmstate_loongarch_cpu = { ++ .name = "cpu", ++ .version_id = 15, ++ .minimum_version_id = 15, ++ .post_load = cpu_post_load, ++ .pre_save = cpu_pre_save, ++ .fields = (VMStateField[]) { ++ /* Active TC */ ++ VMSTATE_STRUCT(env.active_tc, LOONGARCHCPU, 1, vmstate_tc, TCState), ++ ++ /* Active FPU */ ++ VMSTATE_STRUCT(env.active_fpu, LOONGARCHCPU, 1, vmstate_fpu, ++ CPULOONGARCHFPUContext), ++ ++ /* TLB */ ++ VMSTATE_STRUCT_POINTER(env.tlb, LOONGARCHCPU, vmstate_tlb, ++ CPULOONGARCHTLBContext), ++ /* CPU metastate */ ++ VMSTATE_UINT32(env.current_tc, LOONGARCHCPU), ++ VMSTATE_INT32(env.error_code, LOONGARCHCPU), ++ VMSTATE_UINTTL(env.btarget, LOONGARCHCPU), ++ VMSTATE_UINTTL(env.bcond, LOONGARCHCPU), ++ ++ VMSTATE_UINT64(env.lladdr, LOONGARCHCPU), ++ ++ /* PV time */ ++ VMSTATE_UINT64(env.st.guest_addr, LOONGARCHCPU), ++ ++ /* Remaining CSR registers */ ++ VMSTATE_UINT64(env.CSR_CRMD, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_PRMD, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_EUEN, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_MISC, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_ECFG, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_ESTAT, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_ERA, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_BADV, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_BADI, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_EEPN, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_TLBIDX, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_TLBEHI, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_TLBELO0, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_TLBELO1, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_TLBWIRED, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_GTLBC, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_TRGP, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_ASID, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_PGDL, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_PGDH, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_PGD, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_PWCTL0, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_PWCTL1, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_STLBPGSIZE, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_RVACFG, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_CPUID, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_PRCFG1, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_PRCFG2, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_PRCFG3, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_KS0, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_KS1, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_KS2, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_KS3, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_KS4, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_KS5, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_KS6, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_KS7, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_TMID, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_TCFG, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_TVAL, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_CNTC, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_TINTCLR, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_GSTAT, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_GCFG, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_GINTC, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_GCNTC, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_LLBCTL, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_IMPCTL1, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_IMPCTL2, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_GNMI, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_TLBRENT, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_TLBRBADV, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_TLBRERA, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_TLBRSAVE, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_TLBRELO0, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_TLBRELO1, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_TLBREHI, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_TLBRPRMD, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_ERRCTL, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_ERRINFO, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_ERRINFO1, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_ERRENT, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_ERRERA, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_ERRSAVE, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_CTAG, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_DMWIN0, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_DMWIN1, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_DMWIN2, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_DMWIN3, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_PERFCTRL0, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_PERFCNTR0, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_PERFCTRL1, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_PERFCNTR1, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_PERFCTRL2, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_PERFCNTR2, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_PERFCTRL3, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_PERFCNTR3, LOONGARCHCPU), ++ /* debug */ ++ VMSTATE_UINT64(env.CSR_MWPC, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_MWPS, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_DB0ADDR, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_DB0MASK, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_DB0CTL, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_DB0ASID, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_DB1ADDR, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_DB1MASK, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_DB1CTL, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_DB1ASID, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_DB2ADDR, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_DB2MASK, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_DB2CTL, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_DB2ASID, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_DB3ADDR, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_DB3MASK, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_DB3CTL, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_DB3ASID, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_FWPC, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_FWPS, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_IB0ADDR, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_IB0MASK, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_IB0CTL, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_IB0ASID, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_IB1ADDR, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_IB1MASK, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_IB1CTL, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_IB1ASID, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_IB2ADDR, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_IB2MASK, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_IB2CTL, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_IB2ASID, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_IB3ADDR, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_IB3MASK, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_IB3CTL, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_IB3ASID, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_IB4ADDR, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_IB4MASK, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_IB4CTL, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_IB4ASID, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_IB5ADDR, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_IB5MASK, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_IB5CTL, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_IB5ASID, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_IB6ADDR, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_IB6MASK, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_IB6CTL, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_IB6ASID, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_IB7ADDR, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_IB7MASK, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_IB7CTL, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_IB7ASID, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_DEBUG, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_DERA, LOONGARCHCPU), ++ VMSTATE_UINT64(env.CSR_DESAVE, LOONGARCHCPU), ++ ++ VMSTATE_STRUCT_ARRAY(env.fpus, LOONGARCHCPU, LOONGARCH_FPU_MAX, 1, ++ vmstate_inactive_fpu, CPULOONGARCHFPUContext), ++ VMSTATE_UINT8(online_vcpus, LOONGARCHCPU), ++ VMSTATE_UINT8(is_migrate, LOONGARCHCPU), ++ VMSTATE_UINT64(counter_value, LOONGARCHCPU), ++ VMSTATE_UINT32(cpu_freq, LOONGARCHCPU), ++ VMSTATE_UINT32(count_ctl, LOONGARCHCPU), ++ VMSTATE_UINT64(pending_exceptions, LOONGARCHCPU), ++ VMSTATE_UINT64(pending_exceptions_clr, LOONGARCHCPU), ++ VMSTATE_UINT64_ARRAY(core_ext_ioisr, LOONGARCHCPU, 4), ++ ++ VMSTATE_END_OF_LIST() ++ }, ++}; +diff --git a/target/loongarch64/meson.build b/target/loongarch64/meson.build +new file mode 100644 +index 0000000000..6badf4484e +--- /dev/null ++++ b/target/loongarch64/meson.build +@@ -0,0 +1,35 @@ ++loongarch_user_ss = ss.source_set() ++loongarch_softmmu_ss = ss.source_set() ++loongarch_ss = ss.source_set() ++loongarch_ss.add(files( ++ 'cpu.c', ++ 'fpu.c', ++ 'gdbstub.c', ++)) ++ ++gen = [ ++ decodetree.process('insn.decode', extra_args: [ '--decode', 'decode_insn', ++ '--insnwidth', '32' ]) ++] ++ ++loongarch_ss.add(gen) ++loongarch_ss.add(when: 'CONFIG_TCG', if_true: files( ++ 'helper.c', ++ 'translate.c', ++ 'op_helper.c', ++ 'fpu_helper.c', ++ 'tlb_helper.c', ++ 'csr_helper.c', ++)) ++ ++loongarch_softmmu_ss.add(when: 'CONFIG_SOFTMMU', if_true: files( ++ 'machine.c', ++ 'stabletimer.c', ++ 'arch_dump.c', ++)) ++ ++loongarch_softmmu_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c')) ++ ++target_arch += {'loongarch64': loongarch_ss} ++target_softmmu_arch += {'loongarch64': loongarch_softmmu_ss} ++target_user_arch += {'loongarch64': loongarch_user_ss} +diff --git a/target/loongarch64/op_helper.c b/target/loongarch64/op_helper.c +new file mode 100644 +index 0000000000..9a34c0d25e +--- /dev/null ++++ b/target/loongarch64/op_helper.c +@@ -0,0 +1,533 @@ ++/* ++ * LOONGARCH emulation helpers for qemu. ++ * ++ * Copyright (c) 2004-2005 Jocelyn Mayer ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, see . ++ */ ++#include "qemu/osdep.h" ++#include "qemu/main-loop.h" ++#include "cpu.h" ++#include "internal.h" ++#include "qemu/host-utils.h" ++#include "exec/helper-proto.h" ++#include "exec/exec-all.h" ++#include "exec/cpu_ldst.h" ++#include "sysemu/kvm.h" ++#include "qemu/crc32c.h" ++#include ++#include "hw/irq.h" ++#include "hw/core/cpu.h" ++#include "instmap.h" ++ ++/*****************************************************************************/ ++/* Exceptions processing helpers */ ++ ++void helper_raise_exception_err(CPULOONGARCHState *env, uint32_t exception, ++ int error_code) ++{ ++ do_raise_exception_err(env, exception, error_code, 0); ++} ++ ++void helper_raise_exception(CPULOONGARCHState *env, uint32_t exception) ++{ ++ do_raise_exception(env, exception, GETPC()); ++} ++ ++void helper_raise_exception_debug(CPULOONGARCHState *env) ++{ ++ do_raise_exception(env, EXCP_DEBUG, 0); ++} ++ ++static void raise_exception(CPULOONGARCHState *env, uint32_t exception) ++{ ++ do_raise_exception(env, exception, 0); ++} ++ ++#if defined(CONFIG_USER_ONLY) ++#define HELPER_LD(name, insn, type) \ ++static inline type do_##name(CPULOONGARCHState *env, target_ulong addr, \ ++ int mem_idx, uintptr_t retaddr) \ ++{ \ ++ return (type) cpu_##insn##_data_ra(env, addr, retaddr); \ ++} ++#else ++ ++#define HF_SMAP_SHIFT 23 /* CR4.SMAP */ ++#define HF_SMAP_MASK (1 << HF_SMAP_SHIFT) ++#define MMU_KNOSMAP_IDX 2 ++#define HF_CPL_SHIFT 0 ++#define HF_CPL_MASK (3 << HF_CPL_SHIFT) ++#define AC_MASK 0x00040000 ++#define MMU_KSMAP_IDX 0 ++static inline int cpu_mmu_index_kernel(CPULOONGARCHState *env) ++{ ++ return !(env->hflags & HF_SMAP_MASK) ? MMU_KNOSMAP_IDX : ++ ((env->hflags & HF_CPL_MASK) < 3 && (env->hflags & AC_MASK)) ++ ? MMU_KNOSMAP_IDX : MMU_KSMAP_IDX; ++} ++ ++#define cpu_ldl_kernel_ra(e, p, r) \ ++ cpu_ldl_mmuidx_ra(e, p, cpu_mmu_index_kernel(e), r) ++ ++#define HELPER_LD(name, insn, type) \ ++static inline type do_##name(CPULOONGARCHState *env, target_ulong addr, \ ++ int mem_idx, uintptr_t retaddr) \ ++{ \ ++/* \ ++ switch (mem_idx) { \ ++ case 0: return (type) cpu_##insn##_kernel_ra(env, addr, retaddr); \ ++ case 1: return (type) cpu_##insn##_super_ra(env, addr, retaddr); \ ++ default: \ ++ case 2: return (type) cpu_##insn##_user_ra(env, addr, retaddr); \ ++ case 3: return (type) cpu_##insn##_error_ra(env, addr, retaddr); \ ++ } \ ++*/ \ ++} ++#endif ++#if 0 ++HELPER_LD(lw, ldl, int32_t) ++HELPER_LD(ld, ldq, int64_t) ++#endif ++#undef HELPER_LD ++ ++#if defined(CONFIG_USER_ONLY) ++#define HELPER_ST(name, insn, type) \ ++static inline void do_##name(CPULOONGARCHState *env, target_ulong addr, \ ++ type val, int mem_idx, uintptr_t retaddr) \ ++{ \ ++/* \ ++ cpu_##insn##_data_ra(env, addr, val, retaddr); \ ++*/ \ ++} ++#else ++#define HELPER_ST(name, insn, type) \ ++static inline void do_##name(CPULOONGARCHState *env, target_ulong addr, \ ++ type val, int mem_idx, uintptr_t retaddr) \ ++{ \ ++/* \ ++ switch (mem_idx) { \ ++ case 0: \ ++ cpu_##insn##_kernel_ra(env, addr, val, retaddr); \ ++ break; \ ++ case 1: \ ++ cpu_##insn##_super_ra(env, addr, val, retaddr); \ ++ break; \ ++ default: \ ++ case 2: \ ++ cpu_##insn##_user_ra(env, addr, val, retaddr); \ ++ break; \ ++ case 3: \ ++ cpu_##insn##_error_ra(env, addr, val, retaddr); \ ++ break; \ ++ } \ ++*/ \ ++} ++#endif ++#if 0 ++HELPER_ST(sb, stb, uint8_t) ++HELPER_ST(sw, stl, uint32_t) ++HELPER_ST(sd, stq, uint64_t) ++#endif ++#undef HELPER_ST ++ ++static inline target_ulong bitswap(target_ulong v) ++{ ++ v = ((v >> 1) & (target_ulong)0x5555555555555555ULL) | ++ ((v & (target_ulong)0x5555555555555555ULL) << 1); ++ v = ((v >> 2) & (target_ulong)0x3333333333333333ULL) | ++ ((v & (target_ulong)0x3333333333333333ULL) << 2); ++ v = ((v >> 4) & (target_ulong)0x0F0F0F0F0F0F0F0FULL) | ++ ((v & (target_ulong)0x0F0F0F0F0F0F0F0FULL) << 4); ++ return v; ++} ++ ++target_ulong helper_dbitswap(target_ulong rt) ++{ ++ return bitswap(rt); ++} ++ ++target_ulong helper_bitswap(target_ulong rt) ++{ ++ return (int32_t)bitswap(rt); ++} ++ ++/* these crc32 functions are based on target/arm/helper-a64.c */ ++target_ulong helper_crc32(target_ulong val, target_ulong m, uint32_t sz) ++{ ++ uint8_t buf[8]; ++ target_ulong mask = ((sz * 8) == 64) ? -1ULL : ((1ULL << (sz * 8)) - 1); ++ ++ m &= mask; ++ stq_le_p(buf, m); ++ return (int32_t) (crc32(val ^ 0xffffffff, buf, sz) ^ 0xffffffff); ++} ++ ++target_ulong helper_crc32c(target_ulong val, target_ulong m, uint32_t sz) ++{ ++ uint8_t buf[8]; ++ target_ulong mask = ((sz * 8) == 64) ? -1ULL : ((1ULL << (sz * 8)) - 1); ++ m &= mask; ++ stq_le_p(buf, m); ++ return (int32_t) (crc32c(val, buf, sz) ^ 0xffffffff); ++} ++ ++#ifndef CONFIG_USER_ONLY ++ ++#define HELPER_LD_ATOMIC(name, insn, almask) \ ++target_ulong helper_##name(CPULOONGARCHState *env, target_ulong arg, int mem_idx) \ ++{ \ ++/* \ ++ if (arg & almask) { \ ++ env->CSR_BADV = arg; \ ++ do_raise_exception(env, EXCP_AdEL, GETPC()); \ ++ } \ ++ env->lladdr = arg; \ ++ env->llval = do_##insn(env, arg, mem_idx, GETPC()); \ ++ return env->llval; \ ++*/ \ ++} ++#if 0 ++HELPER_LD_ATOMIC(ll, lw, 0x3) ++HELPER_LD_ATOMIC(lld, ld, 0x7) ++#endif ++#undef HELPER_LD_ATOMIC ++#endif ++ ++#ifndef CONFIG_USER_ONLY ++void helper_drdtime(CPULOONGARCHState *env, target_ulong rd, target_ulong rs) ++{ ++ env->active_tc.gpr[rd] = cpu_loongarch_get_stable_counter(env); ++ env->active_tc.gpr[rs] = env->CSR_TMID; ++} ++#endif ++ ++#ifndef CONFIG_USER_ONLY ++static void debug_pre_ertn(CPULOONGARCHState *env) ++{ ++ if (qemu_loglevel_mask(CPU_LOG_EXEC)) { ++ qemu_log("ERTN: PC " TARGET_FMT_lx " ERA " TARGET_FMT_lx, ++ env->active_tc.PC, env->CSR_ERA); ++ qemu_log("\n"); ++ } ++} ++ ++static void debug_post_ertn(CPULOONGARCHState *env) ++{ ++ if (qemu_loglevel_mask(CPU_LOG_EXEC)) { ++ qemu_log("ERTN: PC " TARGET_FMT_lx " ERA " TARGET_FMT_lx, ++ env->active_tc.PC, env->CSR_ERA); ++ } ++} ++ ++static void set_pc(CPULOONGARCHState *env, target_ulong error_pc) ++{ ++ env->active_tc.PC = error_pc & ~(target_ulong)1; ++} ++ ++static inline void exception_return(CPULOONGARCHState *env) ++{ ++ debug_pre_ertn(env); ++ ++ if (cpu_refill_state(env)) { ++ env->CSR_CRMD &= (~0x7); ++ env->CSR_CRMD |= (env->CSR_TLBRPRMD & 0x7); ++ /* Clear Refill flag and set pc */ ++ env->CSR_TLBRERA &= (~0x1); ++ set_pc(env, env->CSR_TLBRERA); ++ if (qemu_loglevel_mask(CPU_LOG_INT)) { ++ qemu_log("%s: TLBRERA 0x%lx\n", __func__, env->CSR_TLBRERA); ++ } ++ } else { ++ env->CSR_CRMD &= (~0x7); ++ env->CSR_CRMD |= (env->CSR_PRMD & 0x7); ++ /* Clear Refill flag and set pc*/ ++ set_pc(env, env->CSR_ERA); ++ if (qemu_loglevel_mask(CPU_LOG_INT)) { ++ qemu_log("%s: ERA 0x%lx\n", __func__, env->CSR_ERA); ++ } ++ } ++ ++ compute_hflags(env); ++ debug_post_ertn(env); ++} ++ ++void helper_ertn(CPULOONGARCHState *env) ++{ ++ exception_return(env); ++ env->lladdr = 1; ++} ++ ++#endif /* !CONFIG_USER_ONLY */ ++ ++void helper_idle(CPULOONGARCHState *env) ++{ ++ CPUState *cs = CPU(loongarch_env_get_cpu(env)); ++ ++ cs->halted = 1; ++ cpu_reset_interrupt(cs, CPU_INTERRUPT_WAKE); ++ /* Last instruction in the block, PC was updated before ++ - no need to recover PC and icount */ ++ raise_exception(env, EXCP_HLT); ++} ++ ++#if !defined(CONFIG_USER_ONLY) ++ ++void loongarch_cpu_do_unaligned_access(CPUState *cs, vaddr addr, ++ MMUAccessType access_type, ++ int mmu_idx, uintptr_t retaddr) ++{ ++ while(1); ++} ++ ++#endif /* !CONFIG_USER_ONLY */ ++ ++void helper_store_scr(CPULOONGARCHState *env, uint32_t n, target_ulong val) ++{ ++ env->scr[n & 0x3] = val; ++} ++ ++target_ulong helper_load_scr(CPULOONGARCHState *env, uint32_t n) ++{ ++ return env->scr[n & 0x3]; ++} ++ ++/* loongarch assert op */ ++void helper_asrtle_d(CPULOONGARCHState *env, target_ulong rs, target_ulong rt) ++{ ++ if (rs > rt) { ++ do_raise_exception(env, EXCP_AdEL, GETPC()); ++ } ++} ++ ++void helper_asrtgt_d(CPULOONGARCHState *env, target_ulong rs, target_ulong rt) ++{ ++ if (rs <= rt) { ++ do_raise_exception(env, EXCP_AdEL, GETPC()); ++ } ++} ++ ++target_ulong helper_cto_w(CPULOONGARCHState *env, target_ulong a0) ++{ ++ uint32_t v = (uint32_t)a0; ++ int temp = 0; ++ ++ while ((v & 0x1) == 1) { ++ temp++; ++ v = v >> 1; ++ } ++ ++ return (target_ulong)temp; ++} ++ ++target_ulong helper_ctz_w(CPULOONGARCHState *env, target_ulong a0) ++{ ++ uint32_t v = (uint32_t)a0; ++ ++ if (v == 0) { ++ return 32; ++ } ++ ++ int temp = 0; ++ while ((v & 0x1) == 0) { ++ temp++; ++ v = v >> 1; ++ } ++ ++ return (target_ulong)temp; ++} ++ ++target_ulong helper_cto_d(CPULOONGARCHState *env, target_ulong a0) ++{ ++ uint64_t v = a0; ++ int temp = 0; ++ ++ while ((v & 0x1) == 1) { ++ temp++; ++ v = v >> 1; ++ } ++ ++ return (target_ulong)temp; ++} ++ ++target_ulong helper_ctz_d(CPULOONGARCHState *env, target_ulong a0) ++{ ++ uint64_t v = a0; ++ ++ if (v == 0) { ++ return 64; ++ } ++ ++ int temp = 0; ++ while ((v & 0x1) == 0) { ++ temp++; ++ v = v >> 1; ++ } ++ ++ return (target_ulong)temp; ++} ++ ++target_ulong helper_bitrev_w(CPULOONGARCHState *env, target_ulong a0) ++{ ++ int32_t v = (int32_t)a0; ++ const int SIZE = 32; ++ uint8_t bytes[SIZE]; ++ ++ int i; ++ for (i = 0; i < SIZE; i++) { ++ bytes[i] = v & 0x1; ++ v = v >> 1; ++ } ++ /* v == 0 */ ++ for (i = 0; i < SIZE; i++) { ++ v = v | ((uint32_t)bytes[i] << (SIZE - 1 - i)); ++ } ++ ++ return (target_ulong)(int32_t)v; ++} ++ ++target_ulong helper_bitrev_d(CPULOONGARCHState *env, target_ulong a0) ++{ ++ uint64_t v = a0; ++ const int SIZE = 64; ++ uint8_t bytes[SIZE]; ++ ++ int i; ++ for (i = 0; i < SIZE; i++) { ++ bytes[i] = v & 0x1; ++ v = v >> 1; ++ } ++ /* v == 0 */ ++ for (i = 0; i < SIZE; i++) { ++ v = v | ((uint64_t)bytes[i] << (SIZE - 1 - i)); ++ } ++ ++ return (target_ulong)v; ++} ++ ++void helper_memtrace_addr(CPULOONGARCHState *env, ++ target_ulong address, uint32_t op) ++{ ++ qemu_log("[cpu %d asid 0x%lx pc 0x%lx] addr 0x%lx op", ++ CPU(loongarch_env_get_cpu(env))->cpu_index, ++ env->CSR_ASID, env->active_tc.PC, address); ++ switch (op) { ++ case OPC_LARCH_LDPTR_D: ++ qemu_log("OPC_LARCH_LDPTR_D"); ++ break; ++ case OPC_LARCH_LD_D: ++ qemu_log("OPC_LARCH_LD_D"); ++ break; ++ case OPC_LARCH_LDPTR_W: ++ qemu_log("OPC_LARCH_LDPTR_W"); ++ break; ++ case OPC_LARCH_LD_W: ++ qemu_log("OPC_LARCH_LD_W"); ++ break; ++ case OPC_LARCH_LD_H: ++ qemu_log("OPC_LARCH_LD_H"); ++ break; ++ case OPC_LARCH_LD_B: ++ qemu_log("OPC_LARCH_LD_B"); ++ break; ++ case OPC_LARCH_LD_WU: ++ qemu_log("OPC_LARCH_LD_WU"); ++ break; ++ case OPC_LARCH_LD_HU: ++ qemu_log("OPC_LARCH_LD_HU"); ++ break; ++ case OPC_LARCH_LD_BU: ++ qemu_log("OPC_LARCH_LD_BU"); ++ break; ++ case OPC_LARCH_STPTR_D: ++ qemu_log("OPC_LARCH_STPTR_D"); ++ break; ++ case OPC_LARCH_ST_D: ++ qemu_log("OPC_LARCH_ST_D"); ++ break; ++ case OPC_LARCH_STPTR_W: ++ qemu_log("OPC_LARCH_STPTR_W"); ++ break; ++ case OPC_LARCH_ST_W: ++ qemu_log("OPC_LARCH_ST_W"); ++ break; ++ case OPC_LARCH_ST_H: ++ qemu_log("OPC_LARCH_ST_H"); ++ break; ++ case OPC_LARCH_ST_B: ++ qemu_log("OPC_LARCH_ST_B"); ++ break; ++ case OPC_LARCH_FLD_S: ++ qemu_log("OPC_LARCH_FLD_S"); ++ break; ++ case OPC_LARCH_FLD_D: ++ qemu_log("OPC_LARCH_FLD_D"); ++ break; ++ case OPC_LARCH_FST_S: ++ qemu_log("OPC_LARCH_FST_S"); ++ break; ++ case OPC_LARCH_FST_D: ++ qemu_log("OPC_LARCH_FST_D"); ++ break; ++ case OPC_LARCH_FLDX_S: ++ qemu_log("OPC_LARCH_FLDX_S"); ++ break; ++ case OPC_LARCH_FLDGT_S: ++ qemu_log("OPC_LARCH_FLDGT_S"); ++ break; ++ case OPC_LARCH_FLDLE_S: ++ qemu_log("OPC_LARCH_FLDLE_S"); ++ break;; ++ case OPC_LARCH_FSTX_S: ++ qemu_log("OPC_LARCH_FSTX_S"); ++ break; ++ case OPC_LARCH_FSTGT_S: ++ qemu_log("OPC_LARCH_FSTGT_S"); ++ break; ++ case OPC_LARCH_FSTLE_S: ++ qemu_log("OPC_LARCH_FSTLE_S"); ++ break; ++ case OPC_LARCH_FLDX_D: ++ qemu_log("OPC_LARCH_FLDX_D"); ++ break; ++ case OPC_LARCH_FLDGT_D: ++ qemu_log("OPC_LARCH_FLDGT_D"); ++ break; ++ case OPC_LARCH_FLDLE_D: ++ qemu_log("OPC_LARCH_FLDLE_D"); ++ break;; ++ case OPC_LARCH_FSTX_D: ++ qemu_log("OPC_LARCH_FSTX_D"); ++ break; ++ case OPC_LARCH_FSTGT_D: ++ qemu_log("OPC_LARCH_FSTGT_D"); ++ break; ++ case OPC_LARCH_FSTLE_D: ++ qemu_log("OPC_LARCH_FSTLE_D"); ++ break; ++ case OPC_LARCH_LL_W: ++ qemu_log("OPC_LARCH_LL_W"); ++ break; ++ case OPC_LARCH_LL_D: ++ qemu_log("OPC_LARCH_LL_D"); ++ break; ++ default: ++ qemu_log("0x%x", op); ++ } ++} ++ ++void helper_memtrace_val(CPULOONGARCHState *env, target_ulong val) ++{ ++ qemu_log("val 0x%lx\n", val); ++} +diff --git a/target/loongarch64/stabletimer.c b/target/loongarch64/stabletimer.c +new file mode 100644 +index 0000000000..b86fecf899 +--- /dev/null ++++ b/target/loongarch64/stabletimer.c +@@ -0,0 +1,122 @@ ++/* ++ * QEMU LOONGARCH timer support ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ++ * THE SOFTWARE. ++ */ ++ ++#include "qemu/osdep.h" ++#include "hw/loongarch/cpudevs.h" ++#include "qemu/timer.h" ++#include "sysemu/kvm.h" ++#include "internal.h" ++#include "hw/irq.h" ++ ++ ++#ifdef DEBUG_TIMER ++#define debug_timer(fmt, args...) printf("%s(%d)-%s -> " #fmt "\n", \ ++ __FILE__, __LINE__, __func__, ##args); ++#else ++#define debug_timer(fmt, args...) ++#endif ++ ++#define TIMER_PERIOD 10 /* 10 ns period for 100 Mhz frequency */ ++#define STABLETIMER_TICK_MASK 0xfffffffffffcUL ++#define STABLETIMER_ENABLE 0x1UL ++#define STABLETIMER_PERIOD 0x2UL ++ ++/* return random value in [low, high] */ ++uint32_t cpu_loongarch_get_random_ls3a5k_tlb(uint32_t low, uint32_t high) ++{ ++ static uint32_t seed = 5; ++ static uint32_t prev_idx; ++ uint32_t idx; ++ uint32_t nb_rand_tlb = high - low + 1; ++ ++ do { ++ seed = 1103515245 * seed + 12345; ++ idx = (seed >> 16) % nb_rand_tlb + low; ++ } while (idx == prev_idx); ++ prev_idx = idx; ++ ++ return idx; ++} ++ ++/* LOONGARCH timer */ ++uint64_t cpu_loongarch_get_stable_counter(CPULOONGARCHState *env) ++{ ++ return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / TIMER_PERIOD; ++} ++ ++uint64_t cpu_loongarch_get_stable_timer_ticks(CPULOONGARCHState *env) ++{ ++ uint64_t now, expire; ++ ++ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); ++ expire = timer_expire_time_ns(env->timer); ++ ++ return (expire - now) / TIMER_PERIOD; ++} ++ ++void cpu_loongarch_store_stable_timer_config(CPULOONGARCHState *env, ++ uint64_t value) ++{ ++ uint64_t now, next; ++ ++ env->CSR_TCFG = value; ++ if (value & STABLETIMER_ENABLE) { ++ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); ++ next = now + (value & STABLETIMER_TICK_MASK) * TIMER_PERIOD; ++ timer_mod(env->timer, next); ++ } ++ debug_timer("0x%lx 0x%lx now 0x%lx, next 0x%lx", ++ value, env->CSR_TCFG, now, next); ++} ++ ++static void loongarch_stable_timer_cb(void *opaque) ++{ ++ CPULOONGARCHState *env; ++ uint64_t now, next; ++ ++ env = opaque; ++ debug_timer(); ++ if (env->CSR_TCFG & STABLETIMER_PERIOD) { ++ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); ++ next = now + (env->CSR_TCFG & STABLETIMER_TICK_MASK) * TIMER_PERIOD; ++ timer_mod(env->timer, next); ++ } else { ++ env->CSR_TCFG &= ~STABLETIMER_ENABLE; ++ } ++ ++ qemu_irq_raise(env->irq[IRQ_TIMER]); ++ ++} ++ ++void cpu_loongarch_clock_init(LOONGARCHCPU *cpu) ++{ ++ CPULOONGARCHState *env = &cpu->env; ++ ++ /* ++ * If we're in KVM mode, don't create the periodic timer, that is handled in ++ * kernel. ++ */ ++ if (!kvm_enabled()) { ++ env->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, ++ &loongarch_stable_timer_cb, env); ++ } ++} +diff --git a/target/loongarch64/tlb_helper.c b/target/loongarch64/tlb_helper.c +new file mode 100644 +index 0000000000..f5e68349a9 +--- /dev/null ++++ b/target/loongarch64/tlb_helper.c +@@ -0,0 +1,729 @@ ++/* ++ * loongarch tlb emulation helpers for qemu. ++ * ++ * Copyright (c) 2020 ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, see . ++ */ ++#include "qemu/osdep.h" ++#include "qemu/main-loop.h" ++#include "cpu.h" ++#include "internal.h" ++#include "qemu/host-utils.h" ++#include "exec/helper-proto.h" ++#include "exec/exec-all.h" ++#include "exec/cpu_ldst.h" ++ ++#ifndef CONFIG_USER_ONLY ++ ++#define HELPER_LD(name, insn, type) \ ++static inline type do_##name(CPULOONGARCHState *env, target_ulong addr, \ ++ int mem_idx, uintptr_t retaddr) \ ++{ \ ++/* \ ++ switch (mem_idx) { \ ++ case 0: return (type) cpu_##insn##_kernel_ra(env, addr, retaddr); \ ++ case 1: return (type) cpu_##insn##_super_ra(env, addr, retaddr); \ ++ default: \ ++ case 2: return (type) cpu_##insn##_user_ra(env, addr, retaddr); \ ++ case 3: return (type) cpu_##insn##_error_ra(env, addr, retaddr); \ ++ } \ ++*/ \ ++} ++#if 0 ++HELPER_LD(lw, ldl, int32_t) ++HELPER_LD(ld, ldq, int64_t) ++#endif ++ ++void helper_lddir(CPULOONGARCHState *env, target_ulong base, target_ulong rt, ++ target_ulong level, uint32_t mem_idx) ++{ ++#if 0 ++ target_ulong pointer = env->active_tc.gpr[base]; ++ target_ulong badvaddr; ++ target_ulong index; ++ target_ulong vaddr; ++ int shift; ++ ++ badvaddr = env->CSR_TLBRBADV; ++ ++ /* 0:8B, 1:16B, 2:32B, 3:64B */ ++ shift = (env->CSR_PWCTL0 >> 30) & 0x3; ++ shift = (shift + 1) * 3; ++ ++ switch (level) { ++ case 1: ++ index = (badvaddr >> ((env->CSR_PWCTL0 >> 10) & 0x1f)) & \ ++ ((1 << ((env->CSR_PWCTL0 >> 15) & 0x1f)) - 1); ++ break; ++ case 3: ++ index = (badvaddr >> ((env->CSR_PWCTL1 >> 0) & 0x3f)) & \ ++ ((1 << ((env->CSR_PWCTL1 >> 6) & 0x3f)) - 1); ++ break; ++ default: ++ do_raise_exception(env, EXCP_RI, GETPC()); ++ return; ++ } ++ ++ vaddr = pointer | index << shift; ++ env->active_tc.gpr[rt] = do_ld(env, vaddr, mem_idx, GETPC()); ++ return; ++#endif ++} ++ ++void helper_ldpte(CPULOONGARCHState *env, target_ulong base, target_ulong odd, ++ uint32_t mem_idx) ++{ ++#if 0 ++ target_ulong pointer = env->active_tc.gpr[base]; ++ target_ulong vaddr; ++ target_ulong tmp0 = 1; ++ target_ulong ptindex, ptoffset0, ptoffset1; ++ target_ulong pagesize; ++ target_ulong badv; ++ int shift; ++ bool huge = pointer & LOONGARCH_PAGE_HUGE; ++ ++ if (huge) { ++ /* Huge Page. pointer is paddr */ ++ tmp0 = pointer ^ LOONGARCH_PAGE_HUGE; ++ /* move Global bit */ ++ tmp0 |= ((tmp0 & LOONGARCH_HUGE_GLOBAL) ++ >> (LOONGARCH_HUGE_GLOBAL_SH - CSR_TLBLO0_GLOBAL_SHIFT)); ++ pagesize = (env->CSR_PWCTL0 & 0x1f) + ++ ((env->CSR_PWCTL0 >> 5) & 0x1f) - 1; ++ if (odd) { ++ tmp0 += (1 << pagesize); ++ } ++ } else { ++ /* 0:8B, 1:16B, 2:32B, 3:64B */ ++ shift = (env->CSR_PWCTL0 >> 30) & 0x3; ++ shift = (shift + 1) * 3; ++ badv = env->CSR_TLBRBADV; ++ ++ ptindex = (badv >> (env->CSR_PWCTL0 & 0x1f)) & ++ ((1 << ((env->CSR_PWCTL0 >> 5) & 0x1f)) - 1); ++ ptindex = ptindex & ~0x1; /* clear bit 0 */ ++ ptoffset0 = ptindex << shift; ++ ptoffset1 = (ptindex + 1) << shift; ++ ++ vaddr = pointer | (odd ? ptoffset1 : ptoffset0); ++ tmp0 = do_ld(env, vaddr, mem_idx, GETPC()); ++ pagesize = (env->CSR_PWCTL0 & 0x1f); ++ } ++ if (odd) { ++ env->CSR_TLBRELO1 = tmp0; ++ } else { ++ env->CSR_TLBRELO0 = tmp0; ++ } ++ env->CSR_TLBREHI = env->CSR_TLBREHI & (~0x3f); ++ env->CSR_TLBREHI = env->CSR_TLBREHI | pagesize; ++#endif ++ return; ++} ++ ++target_ulong helper_read_pgd(CPULOONGARCHState *env) ++{ ++ uint64_t badv; ++ ++ assert(env->CSR_TLBRERA & 0x1); ++ ++ if (env->CSR_TLBRERA & 0x1) { ++ badv = env->CSR_TLBRBADV; ++ } else { ++ badv = env->CSR_BADV; ++ } ++ ++ if ((badv >> 63) & 0x1) { ++ return env->CSR_PGDH; ++ } else { ++ return env->CSR_PGDL; ++ } ++} ++ ++/* TLB management */ ++static uint64_t ls3a5k_pagesize_to_mask(int pagesize) ++{ ++ /* 4KB - 1GB */ ++ if (pagesize < 12 && pagesize > 30) { ++ printf("[ERROR] unsupported page size %d\n", pagesize); ++ exit(-1); ++ } ++ ++ return (1 << (pagesize + 1)) - 1; ++} ++ ++static void ls3a5k_fill_tlb_entry(CPULOONGARCHState *env, ++ ls3a5k_tlb_t *tlb, int is_ftlb) ++{ ++ uint64_t page_mask; /* 0000...00001111...1111 */ ++ uint32_t page_size; ++ uint64_t entryhi; ++ uint64_t lo0, lo1; ++ ++ if (env->CSR_TLBRERA & 0x1) { ++ page_size = env->CSR_TLBREHI & 0x3f; ++ entryhi = env->CSR_TLBREHI; ++ lo0 = env->CSR_TLBRELO0; ++ lo1 = env->CSR_TLBRELO1; ++ } else { ++ page_size = (env->CSR_TLBIDX >> CSR_TLBIDX_PS_SHIFT) & 0x3f; ++ entryhi = env->CSR_TLBEHI; ++ lo0 = env->CSR_TLBELO0; ++ lo1 = env->CSR_TLBELO1; ++ } ++ ++ if (page_size == 0) { ++ printf("Warning: page_size is 0\n"); ++ } ++ ++ /* 15-12 11-8 7-4 3-0 ++ * 4KB: 0001 1111 1111 1111 // double 4KB mask [12:0] ++ * 16KB: 0111 1111 1111 1111 // double 16KB mask [14:0] ++ */ ++ if (is_ftlb) { ++ page_mask = env->tlb->mmu.ls3a5k.ftlb_mask; ++ } else { ++ page_mask = ls3a5k_pagesize_to_mask(page_size); ++ } ++ ++ tlb->VPN = entryhi & 0xffffffffe000 & ~page_mask; ++ ++ tlb->ASID = env->CSR_ASID & 0x3ff; /* CSR_ASID[9:0] */ ++ tlb->EHINV = 0; ++ tlb->G = (lo0 >> CSR_TLBLO0_GLOBAL_SHIFT) & /* CSR_TLBLO[6] */ ++ (lo1 >> CSR_TLBLO1_GLOBAL_SHIFT) & 1; ++ ++ tlb->PageMask = page_mask; ++ tlb->PageSize = page_size; ++ ++ tlb->V0 = (lo0 >> CSR_TLBLO0_V_SHIFT) & 0x1; /* [0] */ ++ tlb->WE0 = (lo0 >> CSR_TLBLO0_WE_SHIFT) & 0x1; /* [1] */ ++ tlb->PLV0 = (lo0 >> CSR_TLBLO0_PLV_SHIFT) & 0x3; /* [3:2] */ ++ tlb->C0 = (lo0 >> CSR_TLBLO0_CCA_SHIFT) & 0x3; /* [5:4] */ ++ tlb->PPN0 = (lo0 & 0xfffffffff000 & ~(page_mask >> 1)); ++ tlb->RI0 = (lo0 >> CSR_TLBLO0_RI_SHIFT) & 0x1; /* [61] */ ++ tlb->XI0 = (lo0 >> CSR_TLBLO0_XI_SHIFT) & 0x1; /* [62] */ ++ tlb->RPLV0 = (lo0 >> CSR_TLBLO0_RPLV_SHIFT) & 0x1; /* [63] */ ++ ++ tlb->V1 = (lo1 >> CSR_TLBLO1_V_SHIFT) & 0x1; /* [0] */ ++ tlb->WE1 = (lo1 >> CSR_TLBLO1_WE_SHIFT) & 0x1; /* [1] */ ++ tlb->PLV1 = (lo1 >> CSR_TLBLO1_PLV_SHIFT) & 0x3; /* [3:2] */ ++ tlb->C1 = (lo1 >> CSR_TLBLO1_CCA_SHIFT) & 0x3; /* [5:4] */ ++ tlb->PPN1 = (lo1 & 0xfffffffff000 & ~(page_mask >> 1)); ++ tlb->RI1 = (lo1 >> CSR_TLBLO1_RI_SHIFT) & 0x1; /* [61] */ ++ tlb->XI1 = (lo1 >> CSR_TLBLO1_XI_SHIFT) & 0x1; /* [62] */ ++ tlb->RPLV1 = (lo1 >> CSR_TLBLO1_RPLV_SHIFT) & 0x1; /* [63] */ ++} ++ ++static void ls3a5k_fill_tlb(CPULOONGARCHState *env, int idx, bool tlbwr) ++{ ++ ls3a5k_tlb_t *tlb; ++ ++ tlb = &env->tlb->mmu.ls3a5k.tlb[idx]; ++ if (tlbwr) { ++ if ((env->CSR_TLBIDX >> CSR_TLBIDX_EHINV_SHIFT) & 0x1) { ++ tlb->EHINV = 1; ++ return; ++ } ++ } ++ ++ if (idx < 2048) { ++ ls3a5k_fill_tlb_entry(env, tlb, 1); ++ } else { ++ ls3a5k_fill_tlb_entry(env, tlb, 0); ++ } ++} ++ ++void ls3a5k_flush_vtlb(CPULOONGARCHState *env) ++{ ++ uint32_t ftlb_size = env->tlb->mmu.ls3a5k.ftlb_size; ++ uint32_t vtlb_size = env->tlb->mmu.ls3a5k.vtlb_size; ++ int i; ++ ++ ls3a5k_tlb_t *tlb; ++ ++ for (i = ftlb_size; i < ftlb_size + vtlb_size; ++i) { ++ tlb = &env->tlb->mmu.ls3a5k.tlb[i]; ++ tlb->EHINV = 1; ++ } ++ ++ cpu_loongarch_tlb_flush(env); ++} ++ ++void ls3a5k_flush_ftlb(CPULOONGARCHState *env) ++{ ++ uint32_t ftlb_size = env->tlb->mmu.ls3a5k.ftlb_size; ++ int i; ++ ++ ls3a5k_tlb_t *tlb; ++ ++ for (i = 0; i < ftlb_size; ++i) { ++ tlb = &env->tlb->mmu.ls3a5k.tlb[i]; ++ tlb->EHINV = 1; ++ } ++ ++ cpu_loongarch_tlb_flush(env); ++} ++ ++void ls3a5k_helper_tlbclr(CPULOONGARCHState *env) ++{ ++ int i; ++ uint16_t asid; ++ int vsize, fsize, index; ++ int start = 0, end = -1; ++ ++ asid = env->CSR_ASID & 0x3ff; ++ vsize = env->tlb->mmu.ls3a5k.vtlb_size; ++ fsize = env->tlb->mmu.ls3a5k.ftlb_size; ++ index = env->CSR_TLBIDX & CSR_TLBIDX_IDX; ++ ++ if (index < fsize) { ++ /* FTLB. One line per operation */ ++ int set = index % 256; ++ start = set * 8; ++ end = start + 7; ++ } else if (index < (fsize + vsize)) { ++ /* VTLB. All entries */ ++ start = fsize; ++ end = fsize + vsize - 1; ++ } else { ++ /* Ignore */ ++ } ++ ++ for (i = start; i <= end; i++) { ++ ls3a5k_tlb_t *tlb; ++ tlb = &env->tlb->mmu.ls3a5k.tlb[i]; ++ if (!tlb->G && tlb->ASID == asid) { ++ tlb->EHINV = 1; ++ } ++ } ++ ++ cpu_loongarch_tlb_flush(env); ++} ++ ++void ls3a5k_helper_tlbflush(CPULOONGARCHState *env) ++{ ++ int i; ++ int vsize, fsize, index; ++ int start = 0, end = -1; ++ ++ vsize = env->tlb->mmu.ls3a5k.vtlb_size; ++ fsize = env->tlb->mmu.ls3a5k.ftlb_size; ++ index = env->CSR_TLBIDX & CSR_TLBIDX_IDX; ++ ++ if (index < fsize) { ++ /* FTLB. One line per operation */ ++ int set = index % 256; ++ start = set * 8; ++ end = start + 7; ++ } else if (index < (fsize + vsize)) { ++ /* VTLB. All entries */ ++ start = fsize; ++ end = fsize + vsize - 1; ++ } else { ++ /* Ignore */ ++ } ++ ++ for (i = start; i <= end; i++) { ++ env->tlb->mmu.ls3a5k.tlb[i].EHINV = 1; ++ } ++ ++ cpu_loongarch_tlb_flush(env); ++} ++ ++void ls3a5k_helper_invtlb(CPULOONGARCHState *env, target_ulong addr, ++ target_ulong info, int op) ++{ ++ uint32_t asid = info & 0x3ff; ++ int i; ++ ++ switch (op) { ++ case 0: ++ case 1: ++ for (i = 0; i < env->tlb->nb_tlb; i++) { ++ env->tlb->mmu.ls3a5k.tlb[i].EHINV = 1; ++ } ++ break; ++ case 4: { ++ int i; ++ for (i = 0; i < env->tlb->nb_tlb; i++) { ++ struct ls3a5k_tlb_t *tlb = &env->tlb->mmu.ls3a5k.tlb[i]; ++ ++ if (!tlb->G && tlb->ASID == asid) { ++ tlb->EHINV = 1; ++ } ++ } ++ break; ++ } ++ ++ case 5: { ++ int i; ++ for (i = 0; i < env->tlb->nb_tlb; i++) { ++ struct ls3a5k_tlb_t *tlb = &env->tlb->mmu.ls3a5k.tlb[i]; ++ uint64_t vpn = addr & 0xffffffffe000 & ~tlb->PageMask; ++ ++ if (!tlb->G && tlb->ASID == asid && vpn == tlb->VPN) { ++ tlb->EHINV = 1; ++ } ++ } ++ break; ++ } ++ case 6: { ++ int i; ++ for (i = 0; i < env->tlb->nb_tlb; i++) { ++ struct ls3a5k_tlb_t *tlb = &env->tlb->mmu.ls3a5k.tlb[i]; ++ uint64_t vpn = addr & 0xffffffffe000 & ~tlb->PageMask; ++ ++ if ((tlb->G || tlb->ASID == asid) && vpn == tlb->VPN) { ++ tlb->EHINV = 1; ++ } ++ } ++ break; ++ } ++ default: ++ helper_raise_exception(env, EXCP_RI); ++ } ++ ++ cpu_loongarch_tlb_flush(env); ++} ++ ++static void ls3a5k_invalidate_tlb_entry(CPULOONGARCHState *env, ++ ls3a5k_tlb_t *tlb) ++{ ++ LOONGARCHCPU *cpu = loongarch_env_get_cpu(env); ++ CPUState *cs = CPU(cpu); ++ target_ulong addr; ++ target_ulong end; ++ target_ulong mask; ++ ++ mask = tlb->PageMask; /* 000...000111...111 */ ++ ++ if (tlb->V0) { ++ addr = tlb->VPN & ~mask; /* xxx...xxx[0]000..0000 */ ++ end = addr | (mask >> 1); /* xxx...xxx[0]111..1111 */ ++ while (addr < end) { ++ tlb_flush_page(cs, addr); ++ addr += TARGET_PAGE_SIZE; ++ } ++ } ++ ++ if (tlb->V1) { ++ /* xxx...xxx[1]000..0000 */ ++ addr = (tlb->VPN & ~mask) | ((mask >> 1) + 1); ++ end = addr | mask; /* xxx...xxx[1]111..1111 */ ++ while (addr - 1 < end) { ++ tlb_flush_page(cs, addr); ++ addr += TARGET_PAGE_SIZE; ++ } ++ } ++} ++ ++void ls3a5k_invalidate_tlb(CPULOONGARCHState *env, int idx) ++{ ++ ls3a5k_tlb_t *tlb; ++ int asid = env->CSR_ASID & 0x3ff; ++ tlb = &env->tlb->mmu.ls3a5k.tlb[idx]; ++ if (tlb->G == 0 && tlb->ASID != asid) { ++ return; ++ } ++ ls3a5k_invalidate_tlb_entry(env, tlb); ++} ++ ++void ls3a5k_helper_tlbwr(CPULOONGARCHState *env) ++{ ++ int idx = env->CSR_TLBIDX & CSR_TLBIDX_IDX; /* [11:0] */ ++ ++ /* Convert idx if in FTLB */ ++ if (idx < env->tlb->mmu.ls3a5k.ftlb_size) { ++ /* ++ * 0 3 6 0 1 2 ++ * 1 4 7 => 3 4 5 ++ * 2 5 8 6 7 8 ++ */ ++ int set = idx % 256; ++ int way = idx / 256; ++ idx = set * 8 + way; ++ } ++ ls3a5k_invalidate_tlb(env, idx); ++ ls3a5k_fill_tlb(env, idx, true); ++} ++ ++void ls3a5k_helper_tlbfill(CPULOONGARCHState *env) ++{ ++ uint64_t mask; ++ uint64_t address; ++ int idx; ++ int set, ftlb_idx; ++ ++ uint64_t entryhi; ++ uint32_t pagesize; ++ ++ if (env->CSR_TLBRERA & 0x1) { ++ entryhi = env->CSR_TLBREHI & ~0x3f; ++ pagesize = env->CSR_TLBREHI & 0x3f; ++ } else { ++ entryhi = env->CSR_TLBEHI; ++ pagesize = (env->CSR_TLBIDX >> CSR_TLBIDX_PS_SHIFT) & 0x3f; ++ } ++ ++ uint32_t ftlb_size = env->tlb->mmu.ls3a5k.ftlb_size; ++ uint32_t vtlb_size = env->tlb->mmu.ls3a5k.vtlb_size; ++ ++ mask = ls3a5k_pagesize_to_mask(pagesize); ++ ++ if (mask == env->tlb->mmu.ls3a5k.ftlb_mask && ++ env->tlb->mmu.ls3a5k.ftlb_size > 0) { ++ /* only write into FTLB */ ++ address = entryhi & 0xffffffffe000; /* [47:13] */ ++ ++ /* choose one set ramdomly */ ++ set = cpu_loongarch_get_random_ls3a5k_tlb(0, 7); ++ ++ /* index in one set */ ++ ftlb_idx = (address >> 15) & 0xff; /* [0,255] */ ++ ++ /* final idx */ ++ idx = ftlb_idx * 8 + set; /* max is 7 + 8 * 255 = 2047 */ ++ } else { ++ /* only write into VTLB */ ++ int wired_nr = env->CSR_TLBWIRED & 0x3f; ++ idx = cpu_loongarch_get_random_ls3a5k_tlb( ++ ftlb_size + wired_nr, ftlb_size + vtlb_size - 1); ++ } ++ ++ ls3a5k_invalidate_tlb(env, idx); ++ ls3a5k_fill_tlb(env, idx, false); ++} ++ ++void ls3a5k_helper_tlbsrch(CPULOONGARCHState *env) ++{ ++ uint64_t mask; ++ uint64_t vpn; ++ uint64_t tag; ++ uint16_t asid; ++ ++ int ftlb_size = env->tlb->mmu.ls3a5k.ftlb_size; ++ int vtlb_size = env->tlb->mmu.ls3a5k.vtlb_size; ++ int i; ++ int ftlb_idx; /* [0,255] 2^8 0xff */ ++ ++ ls3a5k_tlb_t *tlb; ++ ++ asid = env->CSR_ASID & 0x3ff; ++ ++ /* search VTLB */ ++ for (i = ftlb_size; i < ftlb_size + vtlb_size; ++i) { ++ tlb = &env->tlb->mmu.ls3a5k.tlb[i]; ++ mask = tlb->PageMask; ++ ++ vpn = env->CSR_TLBEHI & 0xffffffffe000 & ~mask; ++ tag = tlb->VPN & ~mask; ++ ++ if ((tlb->G == 1 || tlb->ASID == asid) && vpn == tag && tlb->EHINV != 1) ++ { ++ env->CSR_TLBIDX = (i & 0xfff) | ++ ((tlb->PageSize & 0x3f) << CSR_TLBIDX_PS_SHIFT); ++ goto _MATCH_OUT_; ++ } ++ } ++ ++ if (ftlb_size == 0) { ++ goto _NO_MATCH_OUT_; ++ } ++ ++ /* search FTLB */ ++ mask = env->tlb->mmu.ls3a5k.ftlb_mask; ++ vpn = env->CSR_TLBEHI & 0xffffffffe000 & ~mask; ++ ++ ftlb_idx = (env->CSR_TLBEHI & 0xffffffffe000) >> 15; /* 16 KB */ ++ ftlb_idx = ftlb_idx & 0xff; /* [0,255] */ ++ ++ for (i = 0; i < 8; ++i) { ++ tlb = &env->tlb->mmu.ls3a5k.tlb[ftlb_idx * 8 + i]; ++ tag = tlb->VPN & ~mask; ++ ++ if ((tlb->G == 1 || tlb->ASID == asid) && vpn == tag && tlb->EHINV != 1) ++ { ++ env->CSR_TLBIDX = ((i * 256 + ftlb_idx) & 0xfff) | ++ ((tlb->PageSize & 0x3f) << CSR_TLBIDX_PS_SHIFT); ++ goto _MATCH_OUT_; ++ } ++ } ++ ++_NO_MATCH_OUT_: ++ env->CSR_TLBIDX = 1 << CSR_TLBIDX_EHINV_SHIFT; ++_MATCH_OUT_: ++ return; ++} ++ ++void ls3a5k_helper_tlbrd(CPULOONGARCHState *env) ++{ ++ ls3a5k_tlb_t *tlb; ++ int idx; ++ uint16_t asid; ++ ++ idx = env->CSR_TLBIDX & CSR_TLBIDX_IDX; ++ if (idx < env->tlb->mmu.ls3a5k.ftlb_size) { ++ int set = idx % 256; ++ int way = idx / 256; ++ idx = set * 8 + way; ++ } ++ ++ tlb = &env->tlb->mmu.ls3a5k.tlb[idx]; ++ ++ asid = env->CSR_ASID & 0x3ff; ++ ++ if (asid != tlb->ASID) { ++ cpu_loongarch_tlb_flush(env); ++ } ++ ++ if (tlb->EHINV) { ++ /* invalid TLB entry */ ++ env->CSR_TLBIDX = 1 << CSR_TLBIDX_EHINV_SHIFT; ++ env->CSR_TLBEHI = 0; ++ env->CSR_TLBELO0 = 0; ++ env->CSR_TLBELO1 = 0; ++ } else { ++ /* valid TLB entry */ ++ env->CSR_TLBIDX = (env->CSR_TLBIDX & 0xfff) | ++ ((tlb->PageSize & 0x3f) << CSR_TLBIDX_PS_SHIFT); ++ env->CSR_TLBEHI = tlb->VPN; ++ env->CSR_TLBELO0 = (tlb->V0 << CSR_TLBLO0_V_SHIFT) | ++ (tlb->WE0 << CSR_TLBLO0_WE_SHIFT) | ++ (tlb->PLV0 << CSR_TLBLO0_PLV_SHIFT) | ++ (tlb->C0 << CSR_TLBLO0_CCA_SHIFT) | ++ (tlb->G << CSR_TLBLO0_GLOBAL_SHIFT) | ++ (tlb->PPN0 & 0xfffffffff000) | ++ ((uint64_t)tlb->RI0 << CSR_TLBLO0_RI_SHIFT) | ++ ((uint64_t)tlb->XI0 << CSR_TLBLO0_XI_SHIFT) | ++ ((uint64_t)tlb->RPLV0 << CSR_TLBLO0_RPLV_SHIFT); ++ env->CSR_TLBELO1 = (tlb->V1 << CSR_TLBLO1_V_SHIFT) | ++ (tlb->WE1 << CSR_TLBLO1_WE_SHIFT) | ++ (tlb->PLV1 << CSR_TLBLO1_PLV_SHIFT) | ++ (tlb->C1 << CSR_TLBLO1_CCA_SHIFT) | ++ (tlb->G << CSR_TLBLO0_GLOBAL_SHIFT) | ++ (tlb->PPN1 & 0xfffffffff000) | ++ ((uint64_t)tlb->RI1 << CSR_TLBLO1_RI_SHIFT) | ++ ((uint64_t)tlb->XI1 << CSR_TLBLO1_XI_SHIFT) | ++ ((uint64_t)tlb->RPLV1 << CSR_TLBLO1_RPLV_SHIFT); ++ env->CSR_ASID = (tlb->ASID << CSR_ASID_ASID_SHIFT) | ++ (env->CSR_ASID & 0xff0000); ++ } ++} ++ ++void helper_tlbwr(CPULOONGARCHState *env) ++{ ++ env->tlb->helper_tlbwr(env); ++} ++ ++void helper_tlbfill(CPULOONGARCHState *env) ++{ ++ env->tlb->helper_tlbfill(env); ++} ++ ++void helper_tlbsrch(CPULOONGARCHState *env) ++{ ++ env->tlb->helper_tlbsrch(env); ++} ++ ++void helper_tlbrd(CPULOONGARCHState *env) ++{ ++ env->tlb->helper_tlbrd(env); ++} ++ ++void helper_tlbclr(CPULOONGARCHState *env) ++{ ++ env->tlb->helper_tlbclr(env); ++} ++ ++void helper_tlbflush(CPULOONGARCHState *env) ++{ ++ env->tlb->helper_tlbflush(env); ++} ++ ++void helper_invtlb(CPULOONGARCHState *env, target_ulong addr, target_ulong info, ++ target_ulong op) ++{ ++ env->tlb->helper_invtlb(env, addr, info, op); ++} ++ ++static void ls3a5k_mmu_init(CPULOONGARCHState *env, const loongarch_def_t *def) ++{ ++ /* number of VTLB */ ++ env->tlb->nb_tlb = 64; ++ env->tlb->mmu.ls3a5k.vtlb_size = 64; ++ ++ /* number of FTLB */ ++ env->tlb->nb_tlb += 2048; ++ env->tlb->mmu.ls3a5k.ftlb_size = 2048; ++ env->tlb->mmu.ls3a5k.ftlb_mask = (1 << 15) - 1; /* 16 KB */ ++ /* ++ * page_size | ftlb_mask | party field ++ * ---------------------------------------------------------------- ++ * 4 KB = 12 | ( 1 << 13 ) - 1 = [12:0] | [12] ++ * 16 KB = 14 | ( 1 << 15 ) - 1 = [14:0] | [14] ++ * 64 KB = 16 | ( 1 << 17 ) - 1 = [16:0] | [16] ++ * 256 KB = 18 | ( 1 << 19 ) - 1 = [18:0] | [18] ++ * 1 MB = 20 | ( 1 << 21 ) - 1 = [20:0] | [20] ++ * 4 MB = 22 | ( 1 << 23 ) - 1 = [22:0] | [22] ++ * 16 MB = 24 | ( 1 << 25 ) - 1 = [24:0] | [24] ++ * 64 MB = 26 | ( 1 << 27 ) - 1 = [26:0] | [26] ++ * 256 MB = 28 | ( 1 << 29 ) - 1 = [28:0] | [28] ++ * 1 GB = 30 | ( 1 << 31 ) - 1 = [30:0] | [30] ++ * ---------------------------------------------------------------- ++ * take party field index as @n. eg. For 16 KB, n = 14 ++ * ---------------------------------------------------------------- ++ * tlb->VPN = TLBEHI & 0xffffffffe000[47:13] & ~mask = [47:n+1] ++ * tlb->PPN = TLBLO0 & 0xffffffffe000[47:13] & ~mask = [47:n+1] ++ * tlb->PPN = TLBLO1 & 0xffffffffe000[47:13] & ~mask = [47:n+1] ++ * ---------------------------------------------------------------- ++ * On mapping : ++ * > vpn = address & 0xffffffffe000[47:13] & ~mask = [47:n+1] ++ * > tag = tlb->VPN & ~mask = [47:n+1] ++ * ---------------------------------------------------------------- ++ * physical address = [47:n+1] | [n:0] ++ * physical address = tlb->PPN0 | (address & mask) ++ * physical address = tlb->PPN1 | (address & mask) ++ */ ++ ++ int i; ++ for (i = 0; i < env->tlb->nb_tlb; i++) { ++ env->tlb->mmu.ls3a5k.tlb[i].EHINV = 1; ++ } ++ ++ /* TLB's helper functions */ ++ env->tlb->map_address = &ls3a5k_map_address; ++ env->tlb->helper_tlbwr = ls3a5k_helper_tlbwr; ++ env->tlb->helper_tlbfill = ls3a5k_helper_tlbfill; ++ env->tlb->helper_tlbsrch = ls3a5k_helper_tlbsrch; ++ env->tlb->helper_tlbrd = ls3a5k_helper_tlbrd; ++ env->tlb->helper_tlbclr = ls3a5k_helper_tlbclr; ++ env->tlb->helper_tlbflush = ls3a5k_helper_tlbflush; ++ env->tlb->helper_invtlb = ls3a5k_helper_invtlb; ++} ++ ++void mmu_init(CPULOONGARCHState *env, const loongarch_def_t *def) ++{ ++ env->tlb = g_malloc0(sizeof(CPULOONGARCHTLBContext)); ++ ++ switch (def->mmu_type) { ++ case MMU_TYPE_LS3A5K: ++ ls3a5k_mmu_init(env, def); ++ break; ++ default: ++ cpu_abort(CPU(loongarch_env_get_cpu(env)), "MMU type not supported\n"); ++ } ++} ++#endif /* !CONFIG_USER_ONLY */ +diff --git a/target/loongarch64/trace-events b/target/loongarch64/trace-events +new file mode 100644 +index 0000000000..e0bca4f82e +--- /dev/null ++++ b/target/loongarch64/trace-events +@@ -0,0 +1,3 @@ ++# See docs/devel/tracing.txt for syntax documentation. ++ ++# target/loongarch/translate.c +diff --git a/target/loongarch64/trans.inc.c b/target/loongarch64/trans.inc.c +new file mode 100644 +index 0000000000..e50670be47 +--- /dev/null ++++ b/target/loongarch64/trans.inc.c +@@ -0,0 +1,3472 @@ ++static bool trans_syscall(DisasContext *ctx, arg_syscall *a) ++{ ++ generate_exception_end(ctx, EXCP_SYSCALL); ++ return true; ++} ++ ++static bool trans_break(DisasContext *ctx, arg_break *a) ++{ ++ generate_exception_end(ctx, EXCP_BREAK); ++ return true; ++} ++ ++static bool trans_dbcl(DisasContext *ctx, arg_dbcl *a) ++{ ++ /* ++ * dbcl instruction is not support in tcg ++ */ ++ generate_exception_end(ctx, EXCP_RI); ++ return true; ++} ++ ++static bool trans_addi_w(DisasContext *ctx, arg_addi_w *a) ++{ ++ gen_arith_imm(ctx, OPC_LARCH_ADDI_W, a->rd, a->rj, a->si12); ++ return true; ++} ++ ++static bool trans_addi_d(DisasContext *ctx, arg_addi_d *a) ++{ ++ gen_arith_imm(ctx, OPC_LARCH_ADDI_D, a->rd, a->rj, a->si12); ++ return true; ++} ++ ++static bool trans_slli_d(DisasContext *ctx, arg_slli_d *a) ++{ ++ if (a->rd == 0) { ++ /* Nop */ ++ return true; ++ } ++ ++ TCGv t0 = tcg_temp_new(); ++ ++ gen_load_gpr(t0, a->rj); ++ tcg_gen_shli_tl(cpu_gpr[a->rd], t0, a->ui6); ++ ++ tcg_temp_free(t0); ++ return true; ++} ++ ++static bool trans_andi(DisasContext *ctx, arg_andi *a) ++{ ++ gen_logic_imm(ctx, OPC_LARCH_ANDI, a->rd, a->rj, a->ui12); ++ return true; ++} ++ ++static bool trans_srli_d(DisasContext *ctx, arg_srli_d *a) ++{ ++ TCGv t0 = tcg_temp_new(); ++ ++ gen_load_gpr(t0, a->rj); ++ tcg_gen_shri_tl(cpu_gpr[a->rd], t0, a->ui6); ++ ++ tcg_temp_free(t0); ++ return true; ++} ++ ++static bool trans_slli_w(DisasContext *ctx, arg_slli_w *a) ++{ ++ if (a->rd == 0) { ++ /* Nop */ ++ return true; ++ } ++ ++ TCGv t0 = tcg_temp_new(); ++ ++ gen_load_gpr(t0, a->rj); ++ tcg_gen_shli_tl(t0, t0, a->ui5); ++ tcg_gen_ext32s_tl(cpu_gpr[a->rd], t0); ++ ++ tcg_temp_free(t0); ++ return true; ++} ++ ++static bool trans_addu16i_d(DisasContext *ctx, arg_addu16i_d *a) ++{ ++ if (a->rj != 0) { ++ tcg_gen_addi_tl(cpu_gpr[a->rd], cpu_gpr[a->rj], a->si16 << 16); ++ } else { ++ tcg_gen_movi_tl(cpu_gpr[a->rd], a->si16 << 16); ++ } ++ return true; ++} ++ ++static bool trans_lu12i_w(DisasContext *ctx, arg_lu12i_w *a) ++{ ++ tcg_gen_movi_tl(cpu_gpr[a->rd], a->si20 << 12); ++ return true; ++} ++ ++static bool trans_lu32i_d(DisasContext *ctx, arg_lu32i_d *a) ++{ ++ TCGv_i64 t0, t1; ++ t0 = tcg_temp_new_i64(); ++ t1 = tcg_temp_new_i64(); ++ ++ tcg_gen_movi_tl(t0, a->si20); ++ tcg_gen_concat_tl_i64(t1, cpu_gpr[a->rd], t0); ++ gen_store_gpr(t1, a->rd); ++ ++ tcg_temp_free(t0); ++ tcg_temp_free(t1); ++ return true; ++} ++ ++static bool trans_pcaddi(DisasContext *ctx, arg_pcaddi *a) ++{ ++ target_ulong pc = ctx->base.pc_next; ++ target_ulong addr = pc + (a->si20 << 2); ++ tcg_gen_movi_tl(cpu_gpr[a->rd], addr); ++ return true; ++} ++ ++static bool trans_pcalau12i(DisasContext *ctx, arg_pcalau12i *a) ++{ ++ target_ulong pc = ctx->base.pc_next; ++ target_ulong addr = (pc + (a->si20 << 12)) & ~0xfff; ++ tcg_gen_movi_tl(cpu_gpr[a->rd], addr); ++ return true; ++} ++ ++static bool trans_pcaddu12i(DisasContext *ctx, arg_pcaddu12i *a) ++{ ++ target_ulong pc = ctx->base.pc_next; ++ target_ulong addr = pc + (a->si20 << 12); ++ tcg_gen_movi_tl(cpu_gpr[a->rd], addr); ++ return true; ++} ++ ++static bool trans_pcaddu18i(DisasContext *ctx, arg_pcaddu18i *a) ++{ ++ target_ulong pc = ctx->base.pc_next; ++ target_ulong addr = pc + ((target_ulong)(a->si20) << 18); ++ tcg_gen_movi_tl(cpu_gpr[a->rd], addr); ++ return true; ++} ++ ++static bool trans_slti(DisasContext *ctx, arg_slti *a) ++{ ++ gen_slt_imm(ctx, OPC_LARCH_SLTI, a->rd, a->rj, a->si12); ++ return true; ++} ++ ++static bool trans_sltui(DisasContext *ctx, arg_sltui *a) ++{ ++ gen_slt_imm(ctx, OPC_LARCH_SLTIU, a->rd, a->rj, a->si12); ++ return true; ++} ++ ++static bool trans_lu52i_d(DisasContext *ctx, arg_lu52i_d *a) ++{ ++ TCGv t0 = tcg_temp_new(); ++ TCGv t1 = tcg_temp_new(); ++ ++ gen_load_gpr(t1, a->rj); ++ ++ tcg_gen_movi_tl(t0, a->si12); ++ tcg_gen_shli_tl(t0, t0, 52); ++ tcg_gen_andi_tl(t1, t1, 0xfffffffffffffU); ++ tcg_gen_or_tl(cpu_gpr[a->rd], t0, t1); ++ ++ tcg_temp_free(t0); ++ tcg_temp_free(t1); ++ return true; ++} ++ ++static bool trans_ori(DisasContext *ctx, arg_ori *a) ++{ ++ gen_logic_imm(ctx, OPC_LARCH_ORI, a->rd, a->rj, a->ui12); ++ return true; ++} ++ ++static bool trans_xori(DisasContext *ctx, arg_xori *a) ++{ ++ gen_logic_imm(ctx, OPC_LARCH_XORI, a->rd, a->rj, a->ui12); ++ return true; ++} ++ ++static bool trans_bstrins_d(DisasContext *ctx, arg_bstrins_d *a) ++{ ++ int lsb = a->lsbd; ++ int msb = a->msbd; ++ TCGv t0 = tcg_temp_new(); ++ TCGv t1 = tcg_temp_new(); ++ ++ if (lsb > msb) { ++ return false; ++ } ++ ++ gen_load_gpr(t1, a->rj); ++ gen_load_gpr(t0, a->rd); ++ tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1); ++ gen_store_gpr(t0, a->rd); ++ ++ tcg_temp_free(t0); ++ tcg_temp_free(t1); ++ return true; ++} ++ ++static bool trans_bstrpick_d(DisasContext *ctx, arg_bstrpick_d *a) ++{ ++ int lsb = a->lsbd; ++ int msb = a->msbd; ++ TCGv t0 = tcg_temp_new(); ++ TCGv t1 = tcg_temp_new(); ++ ++ if (lsb > msb) { ++ return false; ++ } ++ ++ gen_load_gpr(t1, a->rj); ++ gen_load_gpr(t0, a->rd); ++ tcg_gen_extract_tl(t0, t1, lsb, msb - lsb + 1); ++ gen_store_gpr(t0, a->rd); ++ ++ tcg_temp_free(t0); ++ tcg_temp_free(t1); ++ return true; ++} ++ ++static bool trans_bstrins_w(DisasContext *ctx, arg_bstrins_w *a) ++{ ++ gen_bitops(ctx, OPC_LARCH_TRINS_W, a->rd, a->rj, a->lsbw, a->msbw); ++ return true; ++} ++ ++static bool trans_bstrpick_w(DisasContext *ctx, arg_bstrpick_w *a) ++{ ++ if (a->lsbw > a->msbw) { ++ return false; ++ } ++ gen_bitops(ctx, OPC_LARCH_TRPICK_W, ++ a->rd, a->rj, a->lsbw, a->msbw - a->lsbw); ++ return true; ++} ++ ++static bool trans_ldptr_w(DisasContext *ctx, arg_ldptr_w *a) ++{ ++ gen_ld(ctx, OPC_LARCH_LDPTR_W, a->rd, a->rj, a->si14 << 2); ++ return true; ++} ++ ++static bool trans_stptr_w(DisasContext *ctx, arg_stptr_w *a) ++{ ++ gen_st(ctx, OPC_LARCH_STPTR_W, a->rd, a->rj, a->si14 << 2); ++ return true; ++} ++ ++static bool trans_ldptr_d(DisasContext *ctx, arg_ldptr_d *a) ++{ ++ gen_ld(ctx, OPC_LARCH_LDPTR_D, a->rd, a->rj, a->si14 << 2); ++ return true; ++} ++ ++static bool trans_stptr_d(DisasContext *ctx, arg_stptr_d *a) ++{ ++ gen_st(ctx, OPC_LARCH_STPTR_D, a->rd, a->rj, a->si14 << 2); ++ return true; ++} ++ ++static bool trans_ld_b(DisasContext *ctx, arg_ld_b *a) ++{ ++ gen_ld(ctx, OPC_LARCH_LD_B, a->rd, a->rj, a->si12); ++ return true; ++} ++ ++static bool trans_ld_h(DisasContext *ctx, arg_ld_h *a) ++{ ++ gen_ld(ctx, OPC_LARCH_LD_H, a->rd, a->rj, a->si12); ++ return true; ++} ++ ++static bool trans_ld_w(DisasContext *ctx, arg_ld_w *a) ++{ ++ gen_ld(ctx, OPC_LARCH_LD_W, a->rd, a->rj, a->si12); ++ return true; ++} ++ ++static bool trans_ld_d(DisasContext *ctx, arg_ld_d *a) ++{ ++ gen_ld(ctx, OPC_LARCH_LD_D, a->rd, a->rj, a->si12); ++ return true; ++} ++ ++static bool trans_st_b(DisasContext *ctx, arg_st_b *a) ++{ ++ gen_st(ctx, OPC_LARCH_ST_B, a->rd, a->rj, a->si12); ++ return true; ++} ++ ++static bool trans_st_h(DisasContext *ctx, arg_st_h *a) ++{ ++ gen_st(ctx, OPC_LARCH_ST_H, a->rd, a->rj, a->si12); ++ return true; ++} ++ ++static bool trans_st_w(DisasContext *ctx, arg_st_w *a) ++{ ++ gen_st(ctx, OPC_LARCH_ST_W, a->rd, a->rj, a->si12); ++ return true; ++} ++ ++static bool trans_st_d(DisasContext *ctx, arg_st_d *a) ++{ ++ gen_st(ctx, OPC_LARCH_ST_D, a->rd, a->rj, a->si12); ++ return true; ++} ++ ++static bool trans_ld_bu(DisasContext *ctx, arg_ld_bu *a) ++{ ++ gen_ld(ctx, OPC_LARCH_LD_BU, a->rd, a->rj, a->si12); ++ return true; ++} ++ ++static bool trans_ld_hu(DisasContext *ctx, arg_ld_hu *a) ++{ ++ gen_ld(ctx, OPC_LARCH_LD_HU, a->rd, a->rj, a->si12); ++ return true; ++} ++ ++static bool trans_ld_wu(DisasContext *ctx, arg_ld_wu *a) ++{ ++ gen_ld(ctx, OPC_LARCH_LD_WU, a->rd, a->rj, a->si12); ++ return true; ++} ++ ++static bool trans_preld(DisasContext *ctx, arg_preld *a) ++{ ++ /* Treat as NOP. */ ++ return true; ++} ++ ++static bool trans_ll_w(DisasContext *ctx, arg_ll_w *a) ++{ ++ gen_ld(ctx, OPC_LARCH_LL_W, a->rd, a->rj, a->si14 << 2); ++ return true; ++} ++ ++static bool trans_sc_w(DisasContext *ctx, arg_sc_w *a) ++{ ++ gen_st_cond(ctx, a->rd, a->rj, a->si14 << 2, MO_TESL, false); ++ return true; ++} ++ ++static bool trans_ll_d(DisasContext *ctx, arg_ll_d *a) ++{ ++ gen_ld(ctx, OPC_LARCH_LL_D, a->rd, a->rj, a->si14 << 2); ++ return true; ++} ++ ++static bool trans_sc_d(DisasContext *ctx, arg_sc_d *a) ++{ ++ gen_st_cond(ctx, a->rd, a->rj, a->si14 << 2, MO_TEQ, false); ++ return true; ++} ++ ++static bool trans_fld_s(DisasContext *ctx, arg_fld_s *a) ++{ ++ gen_fp_ldst(ctx, OPC_LARCH_FLD_S, a->fd, a->rj, a->si12); ++ return true; ++} ++ ++static bool trans_fst_s(DisasContext *ctx, arg_fst_s *a) ++{ ++ gen_fp_ldst(ctx, OPC_LARCH_FST_S, a->fd, a->rj, a->si12); ++ return true; ++} ++ ++static bool trans_fld_d(DisasContext *ctx, arg_fld_d *a) ++{ ++ gen_fp_ldst(ctx, OPC_LARCH_FLD_D, a->fd, a->rj, a->si12); ++ return true; ++} ++ ++static bool trans_fst_d(DisasContext *ctx, arg_fst_d *a) ++{ ++ gen_fp_ldst(ctx, OPC_LARCH_FST_D, a->fd, a->rj, a->si12); ++ return true; ++} ++ ++static bool trans_ldx_b(DisasContext *ctx, arg_ldx_b *a) ++{ ++ TCGv t0 = tcg_temp_new(); ++ TCGv t1 = tcg_temp_new(); ++ int mem_idx = ctx->mem_idx; ++ ++ gen_op_addr_add(ctx, t0, cpu_gpr[a->rj], cpu_gpr[a->rk]); ++ tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_SB); ++ gen_store_gpr(t1, a->rd); ++ tcg_temp_free(t0); ++ tcg_temp_free(t1); ++ return true; ++} ++ ++static bool trans_ldx_h(DisasContext *ctx, arg_ldx_h *a) ++{ ++ TCGv t0 = tcg_temp_new(); ++ TCGv t1 = tcg_temp_new(); ++ int mem_idx = ctx->mem_idx; ++ ++ gen_op_addr_add(ctx, t0, cpu_gpr[a->rj], cpu_gpr[a->rk]); ++ tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_TESW | ctx->default_tcg_memop_mask); ++ gen_store_gpr(t1, a->rd); ++ tcg_temp_free(t0); ++ tcg_temp_free(t1); ++ return true; ++} ++ ++static bool trans_ldx_w(DisasContext *ctx, arg_ldx_w *a) ++{ ++ TCGv t0 = tcg_temp_new(); ++ TCGv t1 = tcg_temp_new(); ++ int mem_idx = ctx->mem_idx; ++ ++ gen_op_addr_add(ctx, t0, cpu_gpr[a->rj], cpu_gpr[a->rk]); ++ tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_TESL | ctx->default_tcg_memop_mask); ++ gen_store_gpr(t1, a->rd); ++ tcg_temp_free(t0); ++ return true; ++} ++ ++static bool trans_ldx_d(DisasContext *ctx, arg_ldx_d *a) ++{ ++ TCGv t0 = tcg_temp_new(); ++ TCGv t1 = tcg_temp_new(); ++ int mem_idx = ctx->mem_idx; ++ ++ gen_op_addr_add(ctx, t0, cpu_gpr[a->rj], cpu_gpr[a->rk]); ++ tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_TEQ | ctx->default_tcg_memop_mask); ++ gen_store_gpr(t1, a->rd); ++ tcg_temp_free(t1); ++ return true; ++} ++ ++static bool trans_stx_b(DisasContext *ctx, arg_stx_b *a) ++{ ++ TCGv t0 = tcg_temp_new(); ++ TCGv t1 = tcg_temp_new(); ++ int mem_idx = ctx->mem_idx; ++ ++ gen_op_addr_add(ctx, t0, cpu_gpr[a->rj], cpu_gpr[a->rk]); ++ gen_load_gpr(t1, a->rd); ++ tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_8); ++ tcg_temp_free(t0); ++ tcg_temp_free(t1); ++ return true; ++} ++ ++static bool trans_stx_h(DisasContext *ctx, arg_stx_h *a) ++{ ++ TCGv t0 = tcg_temp_new(); ++ TCGv t1 = tcg_temp_new(); ++ int mem_idx = ctx->mem_idx; ++ ++ gen_op_addr_add(ctx, t0, cpu_gpr[a->rj], cpu_gpr[a->rk]); ++ gen_load_gpr(t1, a->rd); ++ tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUW | ++ ctx->default_tcg_memop_mask); ++ tcg_temp_free(t0); ++ tcg_temp_free(t1); ++ return true; ++} ++ ++static bool trans_stx_w(DisasContext *ctx, arg_stx_w *a) ++{ ++ TCGv t0 = tcg_temp_new(); ++ TCGv t1 = tcg_temp_new(); ++ int mem_idx = ctx->mem_idx; ++ ++ gen_op_addr_add(ctx, t0, cpu_gpr[a->rj], cpu_gpr[a->rk]); ++ gen_load_gpr(t1, a->rd); ++ tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUL | ++ ctx->default_tcg_memop_mask); ++ tcg_temp_free(t0); ++ tcg_temp_free(t1); ++ return true; ++} ++ ++static bool trans_stx_d(DisasContext *ctx, arg_stx_d *a) ++{ ++ TCGv t0 = tcg_temp_new(); ++ TCGv t1 = tcg_temp_new(); ++ int mem_idx = ctx->mem_idx; ++ ++ gen_op_addr_add(ctx, t0, cpu_gpr[a->rj], cpu_gpr[a->rk]); ++ gen_load_gpr(t1, a->rd); ++ tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEQ | ++ ctx->default_tcg_memop_mask); ++ tcg_temp_free(t0); ++ tcg_temp_free(t1); ++ return true; ++} ++ ++static bool trans_ldx_bu(DisasContext *ctx, arg_ldx_bu *a) ++{ ++ TCGv t0 = tcg_temp_new(); ++ TCGv t1 = tcg_temp_new(); ++ int mem_idx = ctx->mem_idx; ++ ++ gen_op_addr_add(ctx, t0, cpu_gpr[a->rj], cpu_gpr[a->rk]); ++ tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB); ++ gen_store_gpr(t1, a->rd); ++ tcg_temp_free(t0); ++ tcg_temp_free(t1); ++ return true; ++} ++ ++static bool trans_ldx_hu(DisasContext *ctx, arg_ldx_hu *a) ++{ ++ TCGv t0 = tcg_temp_new(); ++ TCGv t1 = tcg_temp_new(); ++ int mem_idx = ctx->mem_idx; ++ ++ gen_op_addr_add(ctx, t0, cpu_gpr[a->rj], cpu_gpr[a->rk]); ++ tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_TEUW | ++ ctx->default_tcg_memop_mask); ++ gen_store_gpr(t1, a->rd); ++ tcg_temp_free(t0); ++ tcg_temp_free(t1); ++ return true; ++} ++ ++static bool trans_ldx_wu(DisasContext *ctx, arg_ldx_wu *a) ++{ ++ TCGv t0 = tcg_temp_new(); ++ TCGv t1 = tcg_temp_new(); ++ int mem_idx = ctx->mem_idx; ++ ++ gen_op_addr_add(ctx, t0, cpu_gpr[a->rj], cpu_gpr[a->rk]); ++ tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_TEUL | ++ ctx->default_tcg_memop_mask); ++ gen_store_gpr(t1, a->rd); ++ tcg_temp_free(t0); ++ tcg_temp_free(t1); ++ return true; ++} ++ ++static bool trans_fldx_s(DisasContext *ctx, arg_fldx_s *a) ++{ ++ gen_flt3_ldst(ctx, OPC_LARCH_FLDX_S, a->fd, 0, a->rj, a->rk); ++ return true; ++} ++ ++static bool trans_fldx_d(DisasContext *ctx, arg_fldx_d *a) ++{ ++ gen_flt3_ldst(ctx, OPC_LARCH_FLDX_D, a->fd, 0, a->rj, a->rk); ++ return true; ++} ++ ++static bool trans_fstx_s(DisasContext *ctx, arg_fstx_s *a) ++{ ++ gen_flt3_ldst(ctx, OPC_LARCH_FSTX_S, 0, a->fd, a->rj, a->rk); ++ return true; ++} ++ ++static bool trans_fstx_d(DisasContext *ctx, arg_fstx_d *a) ++{ ++ gen_flt3_ldst(ctx, OPC_LARCH_FSTX_D, 0, a->fd, a->rj, a->rk); ++ return true; ++} ++ ++#define TRANS_AM_W(name, op) \ ++static bool trans_ ## name(DisasContext *ctx, arg_ ## name * a) \ ++{ \ ++ if ((a->rd != 0) && ((a->rj == a->rd) || (a->rk == a->rd))) { \ ++ printf("%s: warning, register equal\n", __func__); \ ++ return false; \ ++ } \ ++ int mem_idx = ctx->mem_idx; \ ++ TCGv addr = tcg_temp_new(); \ ++ TCGv val = tcg_temp_new(); \ ++ TCGv ret = tcg_temp_new(); \ ++\ ++ gen_load_gpr(addr, a->rj); \ ++ gen_load_gpr(val, a->rk); \ ++ tcg_gen_atomic_##op##_tl(ret, addr, val, mem_idx, MO_TESL | \ ++ ctx->default_tcg_memop_mask); \ ++ gen_store_gpr(ret, a->rd); \ ++\ ++ tcg_temp_free(addr); \ ++ tcg_temp_free(val); \ ++ tcg_temp_free(ret); \ ++ return true; \ ++} ++#define TRANS_AM_D(name, op) \ ++static bool trans_ ## name(DisasContext *ctx, arg_ ## name * a) \ ++{ \ ++ if ((a->rd != 0) && ((a->rj == a->rd) || (a->rk == a->rd))) { \ ++ printf("%s: warning, register equal\n", __func__); \ ++ return false; \ ++ } \ ++ int mem_idx = ctx->mem_idx; \ ++ TCGv addr = tcg_temp_new(); \ ++ TCGv val = tcg_temp_new(); \ ++ TCGv ret = tcg_temp_new(); \ ++\ ++ gen_load_gpr(addr, a->rj); \ ++ gen_load_gpr(val, a->rk); \ ++ tcg_gen_atomic_##op##_tl(ret, addr, val, mem_idx, MO_TEQ | \ ++ ctx->default_tcg_memop_mask); \ ++ gen_store_gpr(ret, a->rd); \ ++\ ++ tcg_temp_free(addr); \ ++ tcg_temp_free(val); \ ++ tcg_temp_free(ret); \ ++ return true; \ ++} ++#define TRANS_AM(name, op) \ ++ TRANS_AM_W(name##_w, op) \ ++ TRANS_AM_D(name##_d, op) ++TRANS_AM(amswap, xchg) /* trans_amswap_w, trans_amswap_d */ ++TRANS_AM(amadd, fetch_add) /* trans_amadd_w, trans_amadd_d */ ++TRANS_AM(amand, fetch_and) /* trans_amand_w, trans_amand_d */ ++TRANS_AM(amor, fetch_or) /* trans_amor_w, trans_amor_d */ ++TRANS_AM(amxor, fetch_xor) /* trans_amxor_w, trans_amxor_d */ ++TRANS_AM(ammax, fetch_smax) /* trans_ammax_w, trans_ammax_d */ ++TRANS_AM(ammin, fetch_smin) /* trans_ammin_w, trans_ammin_d */ ++TRANS_AM_W(ammax_wu, fetch_umax) /* trans_ammax_wu */ ++TRANS_AM_D(ammax_du, fetch_umax) /* trans_ammax_du */ ++TRANS_AM_W(ammin_wu, fetch_umin) /* trans_ammin_wu */ ++TRANS_AM_D(ammin_du, fetch_umin) /* trans_ammin_du */ ++#undef TRANS_AM ++#undef TRANS_AM_W ++#undef TRANS_AM_D ++ ++#define TRANS_AM_DB_W(name, op) \ ++static bool trans_ ## name(DisasContext *ctx, arg_ ## name * a) \ ++{ \ ++ if ((a->rd != 0) && ((a->rj == a->rd) || (a->rk == a->rd))) { \ ++ printf("%s: warning, register equal\n", __func__); \ ++ return false; \ ++ } \ ++ int mem_idx = ctx->mem_idx; \ ++ TCGv addr = tcg_temp_new(); \ ++ TCGv val = tcg_temp_new(); \ ++ TCGv ret = tcg_temp_new(); \ ++\ ++ gen_sync(0x10); /* TCG_MO_ALL */ \ ++ gen_load_gpr(addr, a->rj); \ ++ gen_load_gpr(val, a->rk); \ ++ tcg_gen_atomic_##op##_tl(ret, addr, val, mem_idx, MO_TESL | \ ++ ctx->default_tcg_memop_mask); \ ++ gen_store_gpr(ret, a->rd); \ ++\ ++ tcg_temp_free(addr); \ ++ tcg_temp_free(val); \ ++ tcg_temp_free(ret); \ ++ return true; \ ++} ++#define TRANS_AM_DB_D(name, op) \ ++static bool trans_ ## name(DisasContext *ctx, arg_ ## name * a) \ ++{ \ ++ if ((a->rd != 0) && ((a->rj == a->rd) || (a->rk == a->rd))) { \ ++ printf("%s: warning, register equal\n", __func__); \ ++ return false; \ ++ } \ ++ int mem_idx = ctx->mem_idx; \ ++ TCGv addr = tcg_temp_new(); \ ++ TCGv val = tcg_temp_new(); \ ++ TCGv ret = tcg_temp_new(); \ ++\ ++ gen_sync(0x10); /* TCG_MO_ALL */ \ ++ gen_load_gpr(addr, a->rj); \ ++ gen_load_gpr(val, a->rk); \ ++ tcg_gen_atomic_##op##_tl(ret, addr, val, mem_idx, MO_TEQ | \ ++ ctx->default_tcg_memop_mask); \ ++ gen_store_gpr(ret, a->rd); \ ++\ ++ tcg_temp_free(addr); \ ++ tcg_temp_free(val); \ ++ tcg_temp_free(ret); \ ++ return true; \ ++} ++#define TRANS_AM_DB(name, op) \ ++ TRANS_AM_DB_W(name##_db_w, op) \ ++ TRANS_AM_DB_D(name##_db_d, op) ++TRANS_AM_DB(amswap, xchg) /* trans_amswap_db_w, trans_amswap_db_d */ ++TRANS_AM_DB(amadd, fetch_add) /* trans_amadd_db_w, trans_amadd_db_d */ ++TRANS_AM_DB(amand, fetch_and) /* trans_amand_db_w, trans_amand_db_d */ ++TRANS_AM_DB(amor, fetch_or) /* trans_amor_db_w, trans_amor_db_d */ ++TRANS_AM_DB(amxor, fetch_xor) /* trans_amxor_db_w, trans_amxor_db_d */ ++TRANS_AM_DB(ammax, fetch_smax) /* trans_ammax_db_w, trans_ammax_db_d */ ++TRANS_AM_DB(ammin, fetch_smin) /* trans_ammin_db_w, trans_ammin_db_d */ ++TRANS_AM_DB_W(ammax_db_wu, fetch_umax) /* trans_ammax_db_wu */ ++TRANS_AM_DB_D(ammax_db_du, fetch_umax) /* trans_ammax_db_du */ ++TRANS_AM_DB_W(ammin_db_wu, fetch_umin) /* trans_ammin_db_wu */ ++TRANS_AM_DB_D(ammin_db_du, fetch_umin) /* trans_ammin_db_du */ ++#undef TRANS_AM_DB ++#undef TRANS_AM_DB_W ++#undef TRANS_AM_DB_D ++ ++static bool trans_dbar(DisasContext *ctx, arg_dbar * a) ++{ ++ gen_sync(a->whint); ++ return true; ++} ++ ++static bool trans_ibar(DisasContext *ctx, arg_ibar *a) ++{ ++ /* ++ * FENCE_I is a no-op in QEMU, ++ * however we need to end the translation block ++ */ ++ ctx->base.is_jmp = DISAS_STOP; ++ return true; ++} ++ ++#define ASRTGT \ ++do { \ ++ TCGv t1 = tcg_temp_new(); \ ++ TCGv t2 = tcg_temp_new(); \ ++ gen_load_gpr(t1, a->rj); \ ++ gen_load_gpr(t2, a->rk); \ ++ gen_helper_asrtgt_d(cpu_env, t1, t2); \ ++ tcg_temp_free(t1); \ ++ tcg_temp_free(t2); \ ++} while (0) ++ ++#define ASRTLE \ ++do {\ ++ TCGv t1 = tcg_temp_new(); \ ++ TCGv t2 = tcg_temp_new(); \ ++ gen_load_gpr(t1, a->rj); \ ++ gen_load_gpr(t2, a->rk); \ ++ gen_helper_asrtle_d(cpu_env, t1, t2); \ ++ tcg_temp_free(t1); \ ++ tcg_temp_free(t2); \ ++} while (0) ++ ++static bool trans_fldgt_s(DisasContext *ctx, arg_fldgt_s *a) ++{ ++ ASRTGT; ++ gen_flt3_ldst(ctx, OPC_LARCH_FLDGT_S, a->fd, 0, a->rj, a->rk); ++ return true; ++} ++ ++static bool trans_fldgt_d(DisasContext *ctx, arg_fldgt_d *a) ++{ ++ ASRTGT; ++ gen_flt3_ldst(ctx, OPC_LARCH_FLDGT_D, a->fd, 0, a->rj, a->rk); ++ return true; ++} ++ ++static bool trans_fldle_s(DisasContext *ctx, arg_fldle_s *a) ++{ ++ ASRTLE; ++ gen_flt3_ldst(ctx, OPC_LARCH_FLDLE_S, a->fd, 0, a->rj, a->rk); ++ return true; ++} ++ ++static bool trans_fldle_d(DisasContext *ctx, arg_fldle_d *a) ++{ ++ ASRTLE; ++ gen_flt3_ldst(ctx, OPC_LARCH_FLDLE_D, a->fd, 0, a->rj, a->rk); ++ return true; ++} ++ ++static bool trans_fstgt_s(DisasContext *ctx, arg_fstgt_s *a) ++{ ++ ASRTGT; ++ gen_flt3_ldst(ctx, OPC_LARCH_FSTGT_S, 0, a->fd, a->rj, a->rk); ++ return true; ++} ++ ++static bool trans_fstgt_d(DisasContext *ctx, arg_fstgt_d *a) ++{ ++ ASRTGT; ++ gen_flt3_ldst(ctx, OPC_LARCH_FSTGT_D, 0, a->fd, a->rj, a->rk); ++ return true; ++} ++ ++static bool trans_fstle_s(DisasContext *ctx, arg_fstle_s *a) ++{ ++ ASRTLE; ++ gen_flt3_ldst(ctx, OPC_LARCH_FSTLE_S, 0, a->fd, a->rj, a->rk); ++ return true; ++} ++ ++static bool trans_fstle_d(DisasContext *ctx, arg_fstle_d *a) ++{ ++ ASRTLE; ++ gen_flt3_ldst(ctx, OPC_LARCH_FSTLE_D, 0, a->fd, a->rj, a->rk); ++ return true; ++} ++ ++#define DECL_ARG(name) \ ++ arg_ ## name arg = { \ ++ .rd = a->rd, \ ++ .rj = a->rj, \ ++ .rk = a->rk, \ ++ }; ++ ++static bool trans_ldgt_b(DisasContext *ctx, arg_ldgt_b *a) ++{ ++ ASRTGT; ++ DECL_ARG(ldx_b) ++ trans_ldx_b(ctx, &arg); ++ return true; ++} ++ ++static bool trans_ldgt_h(DisasContext *ctx, arg_ldgt_h *a) ++{ ++ ASRTGT; ++ DECL_ARG(ldx_h) ++ trans_ldx_h(ctx, &arg); ++ return true; ++} ++ ++static bool trans_ldgt_w(DisasContext *ctx, arg_ldgt_w *a) ++{ ++ ASRTGT; ++ DECL_ARG(ldx_w) ++ trans_ldx_w(ctx, &arg); ++ return true; ++} ++ ++static bool trans_ldgt_d(DisasContext *ctx, arg_ldgt_d *a) ++{ ++ ASRTGT; ++ DECL_ARG(ldx_d) ++ trans_ldx_d(ctx, &arg); ++ return true; ++} ++ ++static bool trans_ldle_b(DisasContext *ctx, arg_ldle_b *a) ++{ ++ ASRTLE; ++ DECL_ARG(ldx_b) ++ trans_ldx_b(ctx, &arg); ++ return true; ++} ++ ++static bool trans_ldle_h(DisasContext *ctx, arg_ldle_h *a) ++{ ++ ASRTLE; ++ DECL_ARG(ldx_h) ++ trans_ldx_h(ctx, &arg); ++ return true; ++} ++ ++static bool trans_ldle_w(DisasContext *ctx, arg_ldle_w *a) ++{ ++ ASRTLE; ++ DECL_ARG(ldx_w) ++ trans_ldx_w(ctx, &arg); ++ return true; ++} ++ ++static bool trans_ldle_d(DisasContext *ctx, arg_ldle_d *a) ++{ ++ ASRTLE; ++ DECL_ARG(ldx_d) ++ trans_ldx_d(ctx, &arg); ++ return true; ++} ++ ++static bool trans_stgt_b(DisasContext *ctx, arg_stgt_b *a) ++{ ++ ASRTGT; ++ DECL_ARG(stx_b) ++ trans_stx_b(ctx, &arg); ++ return true; ++} ++ ++static bool trans_stgt_h(DisasContext *ctx, arg_stgt_h *a) ++{ ++ ASRTGT; ++ DECL_ARG(stx_h) ++ trans_stx_h(ctx, &arg); ++ return true; ++} ++ ++static bool trans_stgt_w(DisasContext *ctx, arg_stgt_w *a) ++{ ++ ASRTGT; ++ DECL_ARG(stx_w) ++ trans_stx_w(ctx, &arg); ++ return true; ++} ++ ++static bool trans_stgt_d(DisasContext *ctx, arg_stgt_d *a) ++{ ++ ASRTGT; ++ DECL_ARG(stx_d) ++ trans_stx_d(ctx, &arg); ++ return true; ++} ++ ++static bool trans_stle_b(DisasContext *ctx, arg_stle_b *a) ++{ ++ ASRTLE; ++ DECL_ARG(stx_b) ++ trans_stx_b(ctx, &arg); ++ return true; ++} ++ ++static bool trans_stle_h(DisasContext *ctx, arg_stle_h *a) ++{ ++ ASRTLE; ++ DECL_ARG(stx_h) ++ trans_stx_h(ctx, &arg); ++ return true; ++} ++ ++static bool trans_stle_w(DisasContext *ctx, arg_stle_w *a) ++{ ++ ASRTLE; ++ DECL_ARG(stx_w) ++ trans_stx_w(ctx, &arg); ++ return true; ++} ++ ++static bool trans_stle_d(DisasContext *ctx, arg_stle_d *a) ++{ ++ ASRTLE; ++ DECL_ARG(stx_d) ++ trans_stx_d(ctx, &arg); ++ return true; ++} ++ ++#undef ASRTGT ++#undef ASRTLE ++#undef DECL_ARG ++ ++static bool trans_beqz(DisasContext *ctx, arg_beqz *a) ++{ ++ gen_compute_branch(ctx, OPC_LARCH_BEQZ, 4, a->rj, 0, a->offs21 << 2); ++ return true; ++} ++ ++static bool trans_bnez(DisasContext *ctx, arg_bnez *a) ++{ ++ gen_compute_branch(ctx, OPC_LARCH_BNEZ, 4, a->rj, 0, a->offs21 << 2); ++ return true; ++} ++ ++static bool trans_bceqz(DisasContext *ctx, arg_bceqz *a) ++{ ++ TCGv_i32 cj = tcg_const_i32(a->cj); ++ TCGv v0 = tcg_temp_new(); ++ TCGv v1 = tcg_const_i64(0); ++ ++ gen_helper_movcf2reg(v0, cpu_env, cj); ++ tcg_gen_setcond_tl(TCG_COND_EQ, bcond, v0, v1); ++ ctx->hflags |= LARCH_HFLAG_BC; ++ ctx->btarget = ctx->base.pc_next + (a->offs21 << 2); ++ ++ tcg_temp_free_i32(cj); ++ tcg_temp_free(v0); ++ tcg_temp_free(v1); ++ return true; ++} ++ ++static bool trans_bcnez(DisasContext *ctx, arg_bcnez *a) ++{ ++ TCGv_i32 cj = tcg_const_i32(a->cj); ++ TCGv v0 = tcg_temp_new(); ++ TCGv v1 = tcg_const_i64(0); ++ ++ gen_helper_movcf2reg(v0, cpu_env, cj); ++ tcg_gen_setcond_tl(TCG_COND_NE, bcond, v0, v1); ++ ctx->hflags |= LARCH_HFLAG_BC; ++ ctx->btarget = ctx->base.pc_next + (a->offs21 << 2); ++ ++ tcg_temp_free_i32(cj); ++ tcg_temp_free(v0); ++ tcg_temp_free(v1); ++ return true; ++} ++ ++static bool trans_b(DisasContext *ctx, arg_b *a) ++{ ++ gen_compute_branch(ctx, OPC_LARCH_B, 4, 0, 0, a->offs << 2); ++ return true; ++} ++ ++static bool trans_bl(DisasContext *ctx, arg_bl *a) ++{ ++ ctx->btarget = ctx->base.pc_next + (a->offs << 2); ++ tcg_gen_movi_tl(cpu_gpr[1], ctx->base.pc_next + 4); ++ ctx->hflags |= LARCH_HFLAG_B; ++ gen_branch(ctx, 4); ++ return true; ++} ++ ++static bool trans_blt(DisasContext *ctx, arg_blt *a) ++{ ++ gen_compute_branch(ctx, OPC_LARCH_BLT, 4, a->rj, a->rd, a->offs16 << 2); ++ return true; ++} ++ ++static bool trans_bge(DisasContext *ctx, arg_bge *a) ++{ ++ gen_compute_branch(ctx, OPC_LARCH_BGE, 4, a->rj, a->rd, a->offs16 << 2); ++ return true; ++} ++ ++static bool trans_bltu(DisasContext *ctx, arg_bltu *a) ++{ ++ gen_compute_branch(ctx, OPC_LARCH_BLTU, 4, a->rj, a->rd, a->offs16 << 2); ++ return true; ++} ++ ++static bool trans_bgeu(DisasContext *ctx, arg_bgeu *a) ++{ ++ gen_compute_branch(ctx, OPC_LARCH_BGEU, 4, a->rj, a->rd, a->offs16 << 2); ++ return true; ++} ++ ++static bool trans_beq(DisasContext *ctx, arg_beq *a) ++{ ++ gen_compute_branch(ctx, OPC_LARCH_BEQ, 4, a->rj, a->rd, a->offs16 << 2); ++ return true; ++} ++ ++static bool trans_bne(DisasContext *ctx, arg_bne *a) ++{ ++ gen_compute_branch(ctx, OPC_LARCH_BNE, 4, a->rj, a->rd, a->offs16 << 2); ++ return true; ++} ++ ++static bool trans_jirl(DisasContext *ctx, arg_jirl *a) ++{ ++ gen_base_offset_addr(ctx, btarget, a->rj, a->offs16 << 2); ++ if (a->rd != 0) { ++ tcg_gen_movi_tl(cpu_gpr[a->rd], ctx->base.pc_next + 4); ++ } ++ ctx->hflags |= LARCH_HFLAG_BR; ++ gen_branch(ctx, 4); ++ ++ return true; ++} ++ ++#define TRANS_F4FR(name, fmt, op, bits) \ ++static bool trans_ ## name ## _ ## fmt(DisasContext *ctx, \ ++ arg_##name##_##fmt * a) \ ++{ \ ++ check_cp1_enabled(ctx); \ ++ TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \ ++ TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \ ++ TCGv_i ## bits fp2 = tcg_temp_new_i ## bits(); \ ++ TCGv_i ## bits fp3 = tcg_temp_new_i ## bits(); \ ++ check_cp1_enabled(ctx); \ ++ gen_load_fpr ## bits(ctx, fp0, a->fj); \ ++ gen_load_fpr ## bits(ctx, fp1, a->fk); \ ++ gen_load_fpr ## bits(ctx, fp2, a->fa); \ ++ gen_helper_float_ ## op ## _ ## fmt(fp3, \ ++ cpu_env, fp0, fp1, fp2); \ ++ gen_store_fpr ## bits(ctx, fp3, a->fd); \ ++ tcg_temp_free_i ## bits(fp3); \ ++ tcg_temp_free_i ## bits(fp2); \ ++ tcg_temp_free_i ## bits(fp1); \ ++ tcg_temp_free_i ## bits(fp0); \ ++ return true; \ ++} ++ ++TRANS_F4FR(fmadd , s, maddf , 32) /* trans_fmadd_s */ ++TRANS_F4FR(fmadd , d, maddf , 64) /* trans_fmadd_d */ ++TRANS_F4FR(fmsub , s, msubf , 32) /* trans_fmsub_s */ ++TRANS_F4FR(fmsub , d, msubf , 64) /* trans_fmsub_d */ ++TRANS_F4FR(fnmadd, s, nmaddf, 32) /* trans_fnmadd_s */ ++TRANS_F4FR(fnmadd, d, nmaddf, 64) /* trans_fnmadd_d */ ++TRANS_F4FR(fnmsub, s, nmsubf, 32) /* trans_fnmsub_s */ ++TRANS_F4FR(fnmsub, d, nmsubf, 64) /* trans_fnmsub_d */ ++#undef TRANS_F4FR ++ ++static bool trans_fadd_s(DisasContext *ctx, arg_fadd_s * a) ++{ ++ gen_farith(ctx, OPC_LARCH_FADD_S, a->fk, a->fj, a->fd, 0); ++ return true; ++} ++ ++static bool trans_fadd_d(DisasContext *ctx, arg_fadd_d *a) ++{ ++ gen_farith(ctx, OPC_LARCH_FADD_D, a->fk, a->fj, a->fd, 0); ++ return true; ++} ++ ++static bool trans_fsub_s(DisasContext *ctx, arg_fsub_s *a) ++{ ++ gen_farith(ctx, OPC_LARCH_FSUB_S, a->fk, a->fj, a->fd, 0); ++ return true; ++} ++ ++static bool trans_fsub_d(DisasContext *ctx, arg_fsub_d *a) ++{ ++ gen_farith(ctx, OPC_LARCH_FSUB_D, a->fk, a->fj, a->fd, 0); ++ return true; ++} ++ ++static bool trans_fmul_s(DisasContext *ctx, arg_fmul_s *a) ++{ ++ gen_farith(ctx, OPC_LARCH_FMUL_S, a->fk, a->fj, a->fd, 0); ++ return true; ++} ++ ++static bool trans_fmul_d(DisasContext *ctx, arg_fmul_d *a) ++{ ++ gen_farith(ctx, OPC_LARCH_FMUL_D, a->fk, a->fj, a->fd, 0); ++ return true; ++} ++ ++static bool trans_fdiv_s(DisasContext *ctx, arg_fdiv_s *a) ++{ ++ gen_farith(ctx, OPC_LARCH_FDIV_S, a->fk, a->fj, a->fd, 0); ++ return true; ++} ++ ++static bool trans_fdiv_d(DisasContext *ctx, arg_fdiv_d *a) ++{ ++ gen_farith(ctx, OPC_LARCH_FDIV_D, a->fk, a->fj, a->fd, 0); ++ return true; ++} ++ ++static bool trans_fmax_s(DisasContext *ctx, arg_fmax_s *a) ++{ ++ gen_farith(ctx, OPC_LARCH_FMAX_S, a->fk, a->fj, a->fd, 0); ++ return true; ++} ++ ++static bool trans_fmax_d(DisasContext *ctx, arg_fmax_d *a) ++{ ++ gen_farith(ctx, OPC_LARCH_FMAX_D, a->fk, a->fj, a->fd, 0); ++ return true; ++} ++ ++static bool trans_fmin_s(DisasContext *ctx, arg_fmin_s *a) ++{ ++ gen_farith(ctx, OPC_LARCH_FMIN_S, a->fk, a->fj, a->fd, 0); ++ return true; ++} ++ ++static bool trans_fmin_d(DisasContext *ctx, arg_fmin_d *a) ++{ ++ gen_farith(ctx, OPC_LARCH_FMIN_D, a->fk, a->fj, a->fd, 0); ++ return true; ++} ++ ++static bool trans_fmaxa_s(DisasContext *ctx, arg_fmaxa_s *a) ++{ ++ gen_farith(ctx, OPC_LARCH_FMAXA_S, a->fk, a->fj, a->fd, 0); ++ return true; ++} ++ ++static bool trans_fmaxa_d(DisasContext *ctx, arg_fmaxa_d *a) ++{ ++ gen_farith(ctx, OPC_LARCH_FMAXA_D, a->fk, a->fj, a->fd, 0); ++ return true; ++} ++ ++static bool trans_fmina_s(DisasContext *ctx, arg_fmina_s *a) ++{ ++ gen_farith(ctx, OPC_LARCH_FMINA_S, a->fk, a->fj, a->fd, 0); ++ return true; ++} ++ ++static bool trans_fmina_d(DisasContext *ctx, arg_fmina_d *a) ++{ ++ gen_farith(ctx, OPC_LARCH_FMINA_D, a->fk, a->fj, a->fd, 0); ++ return true; ++} ++ ++static bool trans_fscaleb_s(DisasContext *ctx, arg_fscaleb_s *a) ++{ ++ TCGv_i32 fp0 = tcg_temp_new_i32(); ++ TCGv_i32 fp1 = tcg_temp_new_i32(); ++ ++ check_cp1_enabled(ctx); ++ gen_load_fpr32(ctx, fp0, a->fj); ++ gen_load_fpr32(ctx, fp1, a->fk); ++ gen_helper_float_exp2_s(fp0, cpu_env, fp0, fp1); ++ tcg_temp_free_i32(fp1); ++ gen_store_fpr32(ctx, fp0, a->fd); ++ tcg_temp_free_i32(fp0); ++ return true; ++} ++ ++static bool trans_fscaleb_d(DisasContext *ctx, arg_fscaleb_d *a) ++{ ++ TCGv_i64 fp0 = tcg_temp_new_i64(); ++ TCGv_i64 fp1 = tcg_temp_new_i64(); ++ ++ check_cp1_enabled(ctx); ++ gen_load_fpr64(ctx, fp0, a->fj); ++ gen_load_fpr64(ctx, fp1, a->fk); ++ gen_helper_float_exp2_d(fp0, cpu_env, fp0, fp1); ++ tcg_temp_free_i64(fp1); ++ gen_store_fpr64(ctx, fp0, a->fd); ++ tcg_temp_free_i64(fp0); ++ return true; ++} ++ ++static bool trans_fcopysign_s(DisasContext *ctx, arg_fcopysign_s *a) ++{ ++ TCGv_i32 fp0 = tcg_temp_new_i32(); ++ TCGv_i32 fp1 = tcg_temp_new_i32(); ++ TCGv_i32 fp2 = tcg_temp_new_i32(); ++ ++ check_cp1_enabled(ctx); ++ gen_load_fpr32(ctx, fp0, a->fj); ++ gen_load_fpr32(ctx, fp1, a->fk); ++ tcg_gen_deposit_i32(fp2, fp1, fp0, 0, 31); ++ gen_store_fpr32(ctx, fp2, a->fd); ++ ++ tcg_temp_free_i32(fp2); ++ tcg_temp_free_i32(fp1); ++ tcg_temp_free_i32(fp0); ++ return true; ++} ++ ++static bool trans_fcopysign_d(DisasContext *ctx, arg_fcopysign_d *a) ++{ ++ TCGv_i64 fp0 = tcg_temp_new_i64(); ++ TCGv_i64 fp1 = tcg_temp_new_i64(); ++ TCGv_i64 fp2 = tcg_temp_new_i64(); ++ ++ check_cp1_enabled(ctx); ++ gen_load_fpr64(ctx, fp0, a->fj); ++ gen_load_fpr64(ctx, fp1, a->fk); ++ tcg_gen_deposit_i64(fp2, fp1, fp0, 0, 63); ++ gen_store_fpr64(ctx, fp2, a->fd); ++ ++ tcg_temp_free_i64(fp2); ++ tcg_temp_free_i64(fp1); ++ tcg_temp_free_i64(fp0); ++ return true; ++} ++ ++static bool trans_fabs_s(DisasContext *ctx, arg_fabs_s *a) ++{ ++ gen_farith(ctx, OPC_LARCH_FABS_S, 0, a->fj, a->fd, 0); ++ return true; ++} ++ ++static bool trans_fabs_d(DisasContext *ctx, arg_fabs_d *a) ++{ ++ gen_farith(ctx, OPC_LARCH_FABS_D, 0, a->fj, a->fd, 0); ++ return true; ++} ++ ++static bool trans_fneg_s(DisasContext *ctx, arg_fneg_s *a) ++{ ++ gen_farith(ctx, OPC_LARCH_FNEG_S, 0, a->fj, a->fd, 0); ++ return true; ++} ++ ++static bool trans_fneg_d(DisasContext *ctx, arg_fneg_d *a) ++{ ++ gen_farith(ctx, OPC_LARCH_FNEG_D, 0, a->fj, a->fd, 0); ++ return true; ++} ++ ++static bool trans_flogb_s(DisasContext *ctx, arg_flogb_s *a) ++{ ++ TCGv_i32 fp0 = tcg_temp_new_i32(); ++ TCGv_i32 fp1 = tcg_temp_new_i32(); ++ ++ check_cp1_enabled(ctx); ++ gen_load_fpr32(ctx, fp0, a->fj); ++ gen_helper_float_logb_s(fp1, cpu_env, fp0); ++ gen_store_fpr32(ctx, fp1, a->fd); ++ ++ tcg_temp_free_i32(fp0); ++ tcg_temp_free_i32(fp1); ++ return true; ++} ++ ++static bool trans_flogb_d(DisasContext *ctx, arg_flogb_d *a) ++{ ++ TCGv_i64 fp0 = tcg_temp_new_i64(); ++ TCGv_i64 fp1 = tcg_temp_new_i64(); ++ ++ check_cp1_enabled(ctx); ++ gen_load_fpr64(ctx, fp0, a->fj); ++ gen_helper_float_logb_d(fp1, cpu_env, fp0); ++ gen_store_fpr64(ctx, fp1, a->fd); ++ ++ tcg_temp_free_i64(fp0); ++ tcg_temp_free_i64(fp1); ++ return true; ++} ++ ++static bool trans_fclass_s(DisasContext *ctx, arg_fclass_s *a) ++{ ++ gen_farith(ctx, OPC_LARCH_FCLASS_S, 0, a->fj, a->fd, 0); ++ return true; ++} ++ ++static bool trans_fclass_d(DisasContext *ctx, arg_fclass_d *a) ++{ ++ gen_farith(ctx, OPC_LARCH_FCLASS_D, 0, a->fj, a->fd, 0); ++ return true; ++} ++ ++static bool trans_fsqrt_s(DisasContext *ctx, arg_fsqrt_s *a) ++{ ++ gen_farith(ctx, OPC_LARCH_FSQRT_S, 0, a->fj, a->fd, 0); ++ return true; ++} ++ ++static bool trans_fsqrt_d(DisasContext *ctx, arg_fsqrt_d *a) ++{ ++ gen_farith(ctx, OPC_LARCH_FSQRT_D, 0, a->fj, a->fd, 0); ++ return true; ++} ++ ++static bool trans_frecip_s(DisasContext *ctx, arg_frecip_s *a) ++{ ++ gen_farith(ctx, OPC_LARCH_FRECIP_S, 0, a->fj, a->fd, 0); ++ return true; ++} ++ ++static bool trans_frecip_d(DisasContext *ctx, arg_frecip_d *a) ++{ ++ gen_farith(ctx, OPC_LARCH_FRECIP_D, 0, a->fj, a->fd, 0); ++ return true; ++} ++ ++static bool trans_frsqrt_s(DisasContext *ctx, arg_frsqrt_s *a) ++{ ++ gen_farith(ctx, OPC_LARCH_FRSQRT_S, 0, a->fj, a->fd, 0); ++ return true; ++} ++ ++static bool trans_frsqrt_d(DisasContext *ctx, arg_frsqrt_d *a) ++{ ++ gen_farith(ctx, OPC_LARCH_FRSQRT_D, 0, a->fj, a->fd, 0); ++ return true; ++} ++ ++static bool trans_fmov_s(DisasContext *ctx, arg_fmov_s *a) ++{ ++ gen_farith(ctx, OPC_LARCH_FMOV_S, 0, a->fj, a->fd, 0); ++ return true; ++} ++ ++static bool trans_fmov_d(DisasContext *ctx, arg_fmov_d *a) ++{ ++ gen_farith(ctx, OPC_LARCH_FMOV_D, 0, a->fj, a->fd, 0); ++ return true; ++} ++ ++static bool trans_movgr2fr_w(DisasContext *ctx, arg_movgr2fr_w *a) ++{ ++ gen_cp1(ctx, OPC_LARCH_GR2FR_W, a->rj, a->fd); ++ return true; ++} ++ ++static bool trans_movgr2fr_d(DisasContext *ctx, arg_movgr2fr_d *a) ++{ ++ gen_cp1(ctx, OPC_LARCH_GR2FR_D, a->rj, a->fd); ++ return true; ++} ++ ++static bool trans_movgr2frh_w(DisasContext *ctx, arg_movgr2frh_w *a) ++{ ++ gen_cp1(ctx, OPC_LARCH_GR2FRH_W, a->rj, a->fd); ++ return true; ++} ++ ++static bool trans_movfr2gr_s(DisasContext *ctx, arg_movfr2gr_s *a) ++{ ++ gen_cp1(ctx, OPC_LARCH_FR2GR_S, a->rd, a->fj); ++ return true; ++} ++ ++static bool trans_movfr2gr_d(DisasContext *ctx, arg_movfr2gr_d *a) ++{ ++ gen_cp1(ctx, OPC_LARCH_FR2GR_D, a->rd, a->fj); ++ return true; ++} ++ ++static bool trans_movfrh2gr_s(DisasContext *ctx, arg_movfrh2gr_s *a) ++{ ++ gen_cp1(ctx, OPC_LARCH_FRH2GR_S, a->rd, a->fj); ++ return true; ++} ++ ++static bool trans_movgr2fcsr(DisasContext *ctx, arg_movgr2fcsr *a) ++{ ++ TCGv t0 = tcg_temp_new(); ++ ++ check_cp1_enabled(ctx); ++ gen_load_gpr(t0, a->rj); ++ save_cpu_state(ctx, 0); ++ { ++ TCGv_i32 fs_tmp = tcg_const_i32(a->fcsrd); ++ gen_helper_0e2i(movgr2fcsr, t0, fs_tmp, a->rj); ++ tcg_temp_free_i32(fs_tmp); ++ } ++ /* Stop translation as we may have changed hflags */ ++ ctx->base.is_jmp = DISAS_STOP; ++ ++ tcg_temp_free(t0); ++ return true; ++} ++ ++static bool trans_movfcsr2gr(DisasContext *ctx, arg_movfcsr2gr *a) ++{ ++ TCGv t0 = tcg_temp_new(); ++ gen_helper_1e0i(movfcsr2gr, t0, a->fcsrs); ++ gen_store_gpr(t0, a->rd); ++ tcg_temp_free(t0); ++ return true; ++} ++ ++static bool trans_movfr2cf(DisasContext *ctx, arg_movfr2cf *a) ++{ ++ TCGv_i64 fp0 = tcg_temp_new_i64(); ++ TCGv_i32 cd = tcg_const_i32(a->cd); ++ ++ check_cp1_enabled(ctx); ++ gen_load_fpr64(ctx, fp0, a->fj); ++ gen_helper_movreg2cf(cpu_env, cd, fp0); ++ ++ tcg_temp_free_i64(fp0); ++ tcg_temp_free_i32(cd); ++ return true; ++} ++ ++static bool trans_movcf2fr(DisasContext *ctx, arg_movcf2fr *a) ++{ ++ TCGv t0 = tcg_temp_new(); ++ TCGv_i32 cj = tcg_const_i32(a->cj); ++ ++ check_cp1_enabled(ctx); ++ gen_helper_movcf2reg(t0, cpu_env, cj); ++ gen_store_fpr64(ctx, t0, a->fd); ++ ++ tcg_temp_free(t0); ++ return true; ++} ++ ++static bool trans_movgr2cf(DisasContext *ctx, arg_movgr2cf *a) ++{ ++ TCGv t0 = tcg_temp_new(); ++ TCGv_i32 cd = tcg_const_i32(a->cd); ++ ++ check_cp1_enabled(ctx); ++ gen_load_gpr(t0, a->rj); ++ gen_helper_movreg2cf(cpu_env, cd, t0); ++ ++ tcg_temp_free(t0); ++ tcg_temp_free_i32(cd); ++ return true; ++} ++ ++static bool trans_movcf2gr(DisasContext *ctx, arg_movcf2gr *a) ++{ ++ TCGv_i32 cj = tcg_const_i32(a->cj); ++ ++ check_cp1_enabled(ctx); ++ gen_helper_movcf2reg(cpu_gpr[a->rd], cpu_env, cj); ++ ++ tcg_temp_free_i32(cj); ++ return true; ++} ++ ++static bool trans_fcvt_s_d(DisasContext *ctx, arg_fcvt_s_d *a) ++{ ++ gen_farith(ctx, OPC_LARCH_FCVT_S_D, 0, a->fj, a->fd, 0); ++ return true; ++} ++ ++static bool trans_fcvt_d_s(DisasContext *ctx, arg_fcvt_d_s *a) ++{ ++ gen_farith(ctx, OPC_LARCH_FCVT_D_S, 0, a->fj, a->fd, 0); ++ return true; ++} ++ ++static bool trans_ftintrm_w_s(DisasContext *ctx, arg_ftintrm_l_s *a) ++{ ++ gen_farith(ctx, OPC_LARCH_FTINTRM_W_S, 0, a->fj, a->fd, 0); ++ return true; ++} ++ ++static bool trans_ftintrm_w_d(DisasContext *ctx, arg_ftintrm_l_d *a) ++{ ++ gen_farith(ctx, OPC_LARCH_FTINTRM_W_D, 0, a->fj, a->fd, 0); ++ return true; ++} ++ ++static bool trans_ftintrm_l_s(DisasContext *ctx, arg_ftintrm_l_s *a) ++{ ++ gen_farith(ctx, OPC_LARCH_FTINTRM_L_S, 0, a->fj, a->fd, 0); ++ return true; ++} ++ ++static bool trans_ftintrm_l_d(DisasContext *ctx, arg_ftintrm_l_d *a) ++{ ++ gen_farith(ctx, OPC_LARCH_FTINTRM_L_D, 0, a->fj, a->fd, 0); ++ return true; ++} ++ ++static bool trans_ftintrp_w_s(DisasContext *ctx, arg_ftintrp_w_s *a) ++{ ++ gen_farith(ctx, OPC_LARCH_FTINTRP_W_S, 0, a->fj, a->fd, 0); ++ return true; ++} ++ ++static bool trans_ftintrp_w_d(DisasContext *ctx, arg_ftintrp_w_d *a) ++{ ++ gen_farith(ctx, OPC_LARCH_FTINTRP_W_D, 0, a->fj, a->fd, 0); ++ return true; ++} ++ ++static bool trans_ftintrp_l_s(DisasContext *ctx, arg_ftintrp_l_s *a) ++{ ++ gen_farith(ctx, OPC_LARCH_FTINTRP_L_S, 0, a->fj, a->fd, 0); ++ return true; ++} ++ ++static bool trans_ftintrp_l_d(DisasContext *ctx, arg_ftintrp_l_d *a) ++{ ++ gen_farith(ctx, OPC_LARCH_FTINTRP_L_D, 0, a->fj, a->fd, 0); ++ return true; ++} ++ ++static bool trans_ftintrz_w_s(DisasContext *ctx, arg_ftintrz_w_s *a) ++{ ++ gen_farith(ctx, OPC_LARCH_FTINTRZ_W_S, 0, a->fj, a->fd, 0); ++ return true; ++} ++ ++static bool trans_ftintrz_w_d(DisasContext *ctx, arg_ftintrz_w_d *a) ++{ ++ gen_farith(ctx, OPC_LARCH_FTINTRZ_W_D, 0, a->fj, a->fd, 0); ++ return true; ++} ++ ++static bool trans_ftintrz_l_s(DisasContext *ctx, arg_ftintrz_l_s *a) ++{ ++ gen_farith(ctx, OPC_LARCH_FTINTRZ_L_S, 0, a->fj, a->fd, 0); ++ return true; ++} ++ ++static bool trans_ftintrz_l_d(DisasContext *ctx, arg_ftintrz_l_d *a) ++{ ++ gen_farith(ctx, OPC_LARCH_FTINTRZ_L_D, 0, a->fj, a->fd, 0); ++ return true; ++} ++ ++static bool trans_ftintrne_w_s(DisasContext *ctx, arg_ftintrne_w_s *a) ++{ ++ gen_farith(ctx, OPC_LARCH_FTINTRNE_W_S, 0, a->fj, a->fd, 0); ++ return true; ++} ++ ++static bool trans_ftintrne_w_d(DisasContext *ctx, arg_ftintrne_w_d *a) ++{ ++ gen_farith(ctx, OPC_LARCH_FTINTRNE_W_D, 0, a->fj, a->fd, 0); ++ return true; ++} ++ ++static bool trans_ftintrne_l_s(DisasContext *ctx, arg_ftintrne_l_s *a) ++{ ++ gen_farith(ctx, OPC_LARCH_FTINTRNE_L_S, 0, a->fj, a->fd, 0); ++ return true; ++} ++ ++static bool trans_ftintrne_l_d(DisasContext *ctx, arg_ftintrne_l_d *a) ++{ ++ gen_farith(ctx, OPC_LARCH_FTINTRNE_L_D, 0, a->fj, a->fd, 0); ++ return true; ++} ++ ++static bool trans_ftint_w_s(DisasContext *ctx, arg_ftint_w_s *a) ++{ ++ gen_farith(ctx, OPC_LARCH_FTINT_W_S, 0, a->fj, a->fd, 0); ++ return true; ++} ++ ++static bool trans_ftint_w_d(DisasContext *ctx, arg_ftint_w_d *a) ++{ ++ gen_farith(ctx, OPC_LARCH_FTINT_W_D, 0, a->fj, a->fd, 0); ++ return true; ++} ++ ++static bool trans_ftint_l_s(DisasContext *ctx, arg_ftint_l_s *a) ++{ ++ gen_farith(ctx, OPC_LARCH_FTINT_L_S, 0, a->fj, a->fd, 0); ++ return true; ++} ++ ++static bool trans_ftint_l_d(DisasContext *ctx, arg_ftint_l_d *a) ++{ ++ gen_farith(ctx, OPC_LARCH_FTINT_L_D, 0, a->fj, a->fd, 0); ++ return true; ++} ++ ++static bool trans_ffint_s_w(DisasContext *ctx, arg_ffint_s_w *a) ++{ ++ gen_farith(ctx, OPC_LARCH_FFINT_S_W, 0, a->fj, a->fd, 0); ++ return true; ++} ++ ++static bool trans_ffint_s_l(DisasContext *ctx, arg_ffint_s_l *a) ++{ ++ gen_farith(ctx, OPC_LARCH_FFINT_S_L, 0, a->fj, a->fd, 0); ++ return true; ++} ++ ++static bool trans_ffint_d_w(DisasContext *ctx, arg_ffint_d_w *a) ++{ ++ gen_farith(ctx, OPC_LARCH_FFINT_D_W, 0, a->fj, a->fd, 0); ++ return true; ++} ++ ++static bool trans_ffint_d_l(DisasContext *ctx, arg_ffint_d_l *a) ++{ ++ gen_farith(ctx, OPC_LARCH_FFINT_D_L, 0, a->fj, a->fd, 0); ++ return true; ++} ++ ++static bool trans_frint_s(DisasContext *ctx, arg_frint_s *a) ++{ ++ gen_farith(ctx, OPC_LARCH_FRINT_S, 0, a->fj, a->fd, 0); ++ return true; ++} ++ ++static bool trans_frint_d(DisasContext *ctx, arg_frint_d *a) ++{ ++ gen_farith(ctx, OPC_LARCH_FRINT_D, 0, a->fj, a->fd, 0); ++ return true; ++} ++ ++static bool trans_alsl_w(DisasContext *ctx, arg_alsl_w *a) ++{ ++ gen_lsa(ctx, OPC_LARCH_ALSL_W, a->rd, a->rj, a->rk, a->sa2); ++ return true; ++} ++ ++static bool trans_alsl_wu(DisasContext *ctx, arg_alsl_wu *a) ++{ ++ TCGv t0, t1; ++ t0 = tcg_temp_new(); ++ t1 = tcg_temp_new(); ++ gen_load_gpr(t0, a->rj); ++ gen_load_gpr(t1, a->rk); ++ tcg_gen_shli_tl(t0, t0, a->sa2 + 1); ++ tcg_gen_add_tl(t0, t0, t1); ++ tcg_gen_ext32u_tl(cpu_gpr[a->rd], t0); ++ tcg_temp_free(t0); ++ tcg_temp_free(t1); ++ ++ return true; ++} ++ ++static bool trans_alsl_d(DisasContext *ctx, arg_alsl_d *a) ++{ ++ check_larch_64(ctx); ++ gen_lsa(ctx, OPC_LARCH_ALSL_D, a->rd, a->rj, a->rk, a->sa2); ++ return true; ++} ++ ++static bool trans_bytepick_w(DisasContext *ctx, arg_bytepick_w *a) ++{ ++ gen_align(ctx, 32, a->rd, a->rj, a->rk, a->sa2); ++ return true; ++} ++ ++static bool trans_bytepick_d(DisasContext *ctx, arg_bytepick_d *a) ++{ ++ check_larch_64(ctx); ++ gen_align(ctx, 64, a->rd, a->rj, a->rk, a->sa3); ++ return true; ++} ++ ++static bool trans_add_w(DisasContext *ctx, arg_add_w *a) ++{ ++ gen_arith(ctx, OPC_LARCH_ADD_W, a->rd, a->rj, a->rk); ++ return true; ++} ++ ++static bool trans_sub_w(DisasContext *ctx, arg_sub_w *a) ++{ ++ gen_arith(ctx, OPC_LARCH_SUB_W, a->rd, a->rj, a->rk); ++ return true; ++} ++ ++static bool trans_add_d(DisasContext *ctx, arg_add_d *a) ++{ ++ gen_arith(ctx, OPC_LARCH_ADD_D, a->rd, a->rj, a->rk); ++ return true; ++} ++ ++static bool trans_sub_d(DisasContext *ctx, arg_sub_d *a) ++{ ++ check_larch_64(ctx); ++ gen_arith(ctx, OPC_LARCH_SUB_D, a->rd, a->rj, a->rk); ++ return true; ++} ++ ++static bool trans_slt(DisasContext *ctx, arg_slt *a) ++{ ++ gen_slt(ctx, OPC_LARCH_SLT, a->rd, a->rj, a->rk); ++ return true; ++} ++ ++static bool trans_sltu(DisasContext *ctx, arg_sltu *a) ++{ ++ gen_slt(ctx, OPC_LARCH_SLTU, a->rd, a->rj, a->rk); ++ return true; ++} ++ ++static bool trans_maskeqz(DisasContext *ctx, arg_maskeqz *a) ++{ ++ gen_cond_move(ctx, OPC_LARCH_MASKEQZ, a->rd, a->rj, a->rk); ++ return true; ++} ++ ++static bool trans_masknez(DisasContext *ctx, arg_masknez *a) ++{ ++ gen_cond_move(ctx, OPC_LARCH_MASKNEZ, a->rd, a->rj, a->rk); ++ return true; ++} ++ ++static bool trans_nor(DisasContext *ctx, arg_nor *a) ++{ ++ gen_logic(ctx, OPC_LARCH_NOR, a->rd, a->rj, a->rk); ++ return true; ++} ++ ++static bool trans_and(DisasContext *ctx, arg_and *a) ++{ ++ gen_logic(ctx, OPC_LARCH_AND, a->rd, a->rj, a->rk); ++ return true; ++} ++ ++static bool trans_or(DisasContext *ctx, arg_or *a) ++{ ++ gen_logic(ctx, OPC_LARCH_OR, a->rd, a->rj, a->rk); ++ return true; ++} ++ ++static bool trans_xor(DisasContext *ctx, arg_xor *a) ++{ ++ gen_logic(ctx, OPC_LARCH_XOR, a->rd, a->rj, a->rk); ++ return true; ++} ++ ++static bool trans_orn(DisasContext *ctx, arg_orn *a) ++{ ++ TCGv t0 = tcg_temp_new(); ++ gen_load_gpr(t0, a->rk); ++ tcg_gen_not_tl(t0, t0); ++ tcg_gen_or_tl(cpu_gpr[a->rd], cpu_gpr[a->rj], t0); ++ tcg_temp_free(t0); ++ return true; ++} ++ ++static bool trans_andn(DisasContext *ctx, arg_andn *a) ++{ ++ TCGv t0, t1; ++ t0 = tcg_temp_new(); ++ t1 = tcg_temp_new(); ++ gen_load_gpr(t0, a->rk); ++ gen_load_gpr(t1, a->rj); ++ tcg_gen_not_tl(t0, t0); ++ tcg_gen_and_tl(cpu_gpr[a->rd], t1, t0); ++ tcg_temp_free(t0); ++ tcg_temp_free(t1); ++ return true; ++} ++ ++static bool trans_sll_w(DisasContext *ctx, arg_sll_w *a) ++{ ++ gen_shift(ctx, OPC_LARCH_SLL_W, a->rd, a->rk, a->rj); ++ return true; ++} ++ ++static bool trans_srl_w(DisasContext *ctx, arg_srl_w *a) ++{ ++ gen_shift(ctx, OPC_LARCH_SRL_W, a->rd, a->rk, a->rj); ++ return true; ++} ++ ++static bool trans_sra_w(DisasContext *ctx, arg_sra_w *a) ++{ ++ gen_shift(ctx, OPC_LARCH_SRA_W, a->rd, a->rk, a->rj); ++ return true; ++} ++ ++static bool trans_sll_d(DisasContext *ctx, arg_sll_d *a) ++{ ++ check_larch_64(ctx); ++ gen_shift(ctx, OPC_LARCH_SLL_D, a->rd, a->rk, a->rj); ++ return true; ++} ++ ++static bool trans_srl_d(DisasContext *ctx, arg_srl_d *a) ++{ ++ check_larch_64(ctx); ++ gen_shift(ctx, OPC_LARCH_SRL_D, a->rd, a->rk, a->rj); ++ return true; ++} ++ ++static bool trans_sra_d(DisasContext *ctx, arg_sra_d *a) ++{ ++ check_larch_64(ctx); ++ gen_shift(ctx, OPC_LARCH_SRA_D, a->rd, a->rk, a->rj); ++ return true; ++} ++ ++static bool trans_rotr_w(DisasContext *ctx, arg_rotr_w *a) ++{ ++ gen_shift(ctx, OPC_LARCH_ROTR_W, a->rd, a->rk, a->rj); ++ return true; ++} ++ ++static bool trans_rotr_d(DisasContext *ctx, arg_rotr_d *a) ++{ ++ check_larch_64(ctx); ++ gen_shift(ctx, OPC_LARCH_ROTR_D, a->rd, a->rk, a->rj); ++ return true; ++} ++ ++static bool trans_crc_w_b_w(DisasContext *ctx, arg_crc_w_b_w *a) ++{ ++ gen_crc32(ctx, a->rd, a->rj, a->rk, 1, 0); ++ return true; ++} ++ ++static bool trans_crc_w_h_w(DisasContext *ctx, arg_crc_w_h_w *a) ++{ ++ gen_crc32(ctx, a->rd, a->rj, a->rk, 2, 0); ++ return true; ++} ++ ++static bool trans_crc_w_w_w(DisasContext *ctx, arg_crc_w_w_w *a) ++{ ++ gen_crc32(ctx, a->rd, a->rj, a->rk, 4, 0); ++ return true; ++} ++ ++static bool trans_crc_w_d_w(DisasContext *ctx, arg_crc_w_d_w *a) ++{ ++ gen_crc32(ctx, a->rd, a->rj, a->rk, 8, 0); ++ return true; ++} ++ ++static bool trans_crcc_w_b_w(DisasContext *ctx, arg_crcc_w_b_w *a) ++{ ++ gen_crc32(ctx, a->rd, a->rj, a->rk, 1, 1); ++ return true; ++} ++ ++static bool trans_crcc_w_h_w(DisasContext *ctx, arg_crcc_w_h_w *a) ++{ ++ gen_crc32(ctx, a->rd, a->rj, a->rk, 2, 1); ++ return true; ++} ++ ++static bool trans_crcc_w_w_w(DisasContext *ctx, arg_crcc_w_w_w *a) ++{ ++ gen_crc32(ctx, a->rd, a->rj, a->rk, 4, 1); ++ return true; ++} ++ ++static bool trans_crcc_w_d_w(DisasContext *ctx, arg_crcc_w_d_w *a) ++{ ++ gen_crc32(ctx, a->rd, a->rj, a->rk, 8, 1); ++ return true; ++} ++ ++static bool trans_mul_w(DisasContext *ctx, arg_mul_w *a) ++{ ++ gen_r6_muldiv(ctx, OPC_LARCH_MUL_W, a->rd, a->rj, a->rk); ++ return true; ++} ++ ++static bool trans_mulh_w(DisasContext *ctx, arg_mulh_w *a) ++{ ++ gen_r6_muldiv(ctx, OPC_LARCH_MULH_W, a->rd, a->rj, a->rk); ++ return true; ++} ++ ++static bool trans_mulh_wu(DisasContext *ctx, arg_mulh_wu *a) ++{ ++ gen_r6_muldiv(ctx, OPC_LARCH_MULH_WU, a->rd, a->rj, a->rk); ++ return true; ++} ++ ++static bool trans_mul_d(DisasContext *ctx, arg_mul_d *a) ++{ ++ check_larch_64(ctx); ++ gen_r6_muldiv(ctx, OPC_LARCH_MUL_D, a->rd, a->rj, a->rk); ++ return true; ++} ++ ++static bool trans_mulh_d(DisasContext *ctx, arg_mulh_d *a) ++{ ++ check_larch_64(ctx); ++ gen_r6_muldiv(ctx, OPC_LARCH_MULH_D, a->rd, a->rj, a->rk); ++ return true; ++} ++ ++static bool trans_mulh_du(DisasContext *ctx, arg_mulh_du *a) ++{ ++ check_larch_64(ctx); ++ gen_r6_muldiv(ctx, OPC_LARCH_MULH_DU, a->rd, a->rj, a->rk); ++ return true; ++} ++ ++static bool trans_mulw_d_w(DisasContext *ctx, arg_mulw_d_w *a) ++{ ++ TCGv_i64 t0 = tcg_temp_new_i64(); ++ TCGv_i64 t1 = tcg_temp_new_i64(); ++ TCGv_i64 t2 = tcg_temp_new_i64(); ++ gen_load_gpr(t0, a->rj); ++ gen_load_gpr(t1, a->rk); ++ tcg_gen_ext32s_i64(t0, t0); ++ tcg_gen_ext32s_i64(t1, t1); ++ tcg_gen_mul_i64(t2, t0, t1); ++ gen_store_gpr(t2, a->rd); ++ tcg_temp_free_i64(t0); ++ tcg_temp_free_i64(t1); ++ tcg_temp_free_i64(t2); ++ return true; ++} ++ ++static bool trans_mulw_d_wu(DisasContext *ctx, arg_mulw_d_wu *a) ++{ ++ TCGv_i64 t0 = tcg_temp_new_i64(); ++ TCGv_i64 t1 = tcg_temp_new_i64(); ++ TCGv_i64 t2 = tcg_temp_new_i64(); ++ gen_load_gpr(t0, a->rj); ++ gen_load_gpr(t1, a->rk); ++ tcg_gen_ext32u_i64(t0, t0); ++ tcg_gen_ext32u_i64(t1, t1); ++ tcg_gen_mul_i64(t2, t0, t1); ++ gen_store_gpr(t2, a->rd); ++ tcg_temp_free_i64(t0); ++ tcg_temp_free_i64(t1); ++ tcg_temp_free_i64(t2); ++ return true; ++} ++ ++static bool trans_div_w(DisasContext *ctx, arg_div_w *a) ++{ ++ gen_r6_muldiv(ctx, OPC_LARCH_DIV_W, a->rd, a->rj, a->rk); ++ return true; ++} ++ ++static bool trans_mod_w(DisasContext *ctx, arg_mod_w *a) ++{ ++ gen_r6_muldiv(ctx, OPC_LARCH_MOD_W, a->rd, a->rj, a->rk); ++ return true; ++} ++ ++static bool trans_div_wu(DisasContext *ctx, arg_div_wu *a) ++{ ++ gen_r6_muldiv(ctx, OPC_LARCH_DIV_WU, a->rd, a->rj, a->rk); ++ return true; ++} ++ ++static bool trans_mod_wu(DisasContext *ctx, arg_mod_wu *a) ++{ ++ gen_r6_muldiv(ctx, OPC_LARCH_MOD_WU, a->rd, a->rj, a->rk); ++ return true; ++} ++ ++static bool trans_div_d(DisasContext *ctx, arg_div_d *a) ++{ ++ check_larch_64(ctx); ++ gen_r6_muldiv(ctx, OPC_LARCH_DIV_D, a->rd, a->rj, a->rk); ++ return true; ++} ++ ++static bool trans_mod_d(DisasContext *ctx, arg_mod_d *a) ++{ ++ check_larch_64(ctx); ++ gen_r6_muldiv(ctx, OPC_LARCH_MOD_D, a->rd, a->rj, a->rk); ++ return true; ++} ++ ++static bool trans_div_du(DisasContext *ctx, arg_div_du *a) ++{ ++ check_larch_64(ctx); ++ gen_r6_muldiv(ctx, OPC_LARCH_DIV_DU, a->rd, a->rj, a->rk); ++ return true; ++} ++ ++static bool trans_mod_du(DisasContext *ctx, arg_mod_du *a) ++{ ++ check_larch_64(ctx); ++ gen_r6_muldiv(ctx, OPC_LARCH_MOD_DU, a->rd, a->rj, a->rk); ++ return true; ++} ++ ++/* do not update CP0.BadVaddr */ ++static bool trans_asrtle_d(DisasContext *ctx, arg_asrtle_d * a) ++{ ++ TCGv t1 = tcg_temp_new(); ++ TCGv t2 = tcg_temp_new(); ++ gen_load_gpr(t1, a->rj); ++ gen_load_gpr(t2, a->rk); ++ gen_helper_asrtle_d(cpu_env, t1, t2); ++ tcg_temp_free(t1); ++ tcg_temp_free(t2); ++ return true; ++} ++ ++/* do not update CP0.BadVaddr */ ++static bool trans_asrtgt_d(DisasContext *ctx, arg_asrtgt_d * a) ++{ ++ TCGv t1 = tcg_temp_new(); ++ TCGv t2 = tcg_temp_new(); ++ gen_load_gpr(t1, a->rj); ++ gen_load_gpr(t2, a->rk); ++ gen_helper_asrtgt_d(cpu_env, t1, t2); ++ tcg_temp_free(t1); ++ tcg_temp_free(t2); ++ return true; ++} ++ ++#ifdef CONFIG_USER_ONLY ++static bool trans_gr2scr(DisasContext *ctx, arg_gr2scr *a) ++{ ++ return false; ++} ++ ++static bool trans_scr2gr(DisasContext *ctx, arg_scr2gr *a) ++{ ++ return false; ++} ++#else ++static bool trans_gr2scr(DisasContext *ctx, arg_gr2scr *a) ++{ ++ TCGv_i32 sd = tcg_const_i32(a->sd); ++ TCGv val = tcg_temp_new(); ++ check_lbt_enabled(ctx); ++ gen_load_gpr(val, a->rj); ++ gen_helper_store_scr(cpu_env, sd, val); ++ tcg_temp_free_i32(sd); ++ tcg_temp_free(val); ++ return true; ++} ++ ++static bool trans_scr2gr(DisasContext *ctx, arg_scr2gr *a) ++{ ++ if (a->rd == 0) { ++ /* Nop */ ++ return true; ++ } ++ ++ TCGv_i32 tsj = tcg_const_i32(a->sj); ++ check_lbt_enabled(ctx); ++ gen_helper_load_scr(cpu_gpr[a->rd], cpu_env, tsj); ++ tcg_temp_free_i32(tsj); ++ return true; ++} ++#endif ++ ++static bool trans_clo_w(DisasContext *ctx, arg_clo_w *a) ++{ ++ gen_cl(ctx, OPC_LARCH_CLO_W, a->rd, a->rj); ++ return true; ++} ++ ++static bool trans_clz_w(DisasContext *ctx, arg_clz_w *a) ++{ ++ gen_cl(ctx, OPC_LARCH_CLZ_W, a->rd, a->rj); ++ return true; ++} ++ ++static bool trans_cto_w(DisasContext *ctx, arg_cto_w *a) ++{ ++ TCGv t0 = tcg_temp_new(); ++ ++ gen_load_gpr(t0, a->rj); ++ gen_helper_cto_w(cpu_gpr[a->rd], cpu_env, t0); ++ ++ tcg_temp_free(t0); ++ return true; ++} ++ ++static bool trans_ctz_w(DisasContext *ctx, arg_ctz_w *a) ++{ ++ TCGv t0 = tcg_temp_new(); ++ ++ gen_load_gpr(t0, a->rj); ++ gen_helper_ctz_w(cpu_gpr[a->rd], cpu_env, t0); ++ ++ tcg_temp_free(t0); ++ return true; ++} ++ ++static bool trans_clo_d(DisasContext *ctx, arg_clo_d *a) ++{ ++ check_larch_64(ctx); ++ gen_cl(ctx, OPC_LARCH_CLO_D, a->rd, a->rj); ++ return true; ++} ++ ++static bool trans_clz_d(DisasContext *ctx, arg_clz_d *a) ++{ ++ check_larch_64(ctx); ++ gen_cl(ctx, OPC_LARCH_CLZ_D, a->rd, a->rj); ++ return true; ++} ++ ++static bool trans_cto_d(DisasContext *ctx, arg_cto_d *a) ++{ ++ TCGv t0 = tcg_temp_new(); ++ ++ gen_load_gpr(t0, a->rj); ++ gen_helper_cto_d(cpu_gpr[a->rd], cpu_env, t0); ++ ++ tcg_temp_free(t0); ++ return true; ++} ++ ++static bool trans_ctz_d(DisasContext *ctx, arg_ctz_d *a) ++{ ++ TCGv t0 = tcg_temp_new(); ++ ++ gen_load_gpr(t0, a->rj); ++ gen_helper_ctz_d(cpu_gpr[a->rd], cpu_env, t0); ++ ++ tcg_temp_free(t0); ++ return true; ++} ++ ++static bool trans_revb_2h(DisasContext *ctx, arg_revb_2h *a) ++{ ++ gen_bshfl(ctx, OPC_LARCH_REVB_2H, a->rj, a->rd); ++ return true; ++} ++ ++static bool trans_revb_4h(DisasContext *ctx, arg_revb_4h *a) ++{ ++ check_larch_64(ctx); ++ gen_bshfl(ctx, OPC_LARCH_REVB_4H, a->rj, a->rd); ++ return true; ++} ++ ++static bool trans_revb_2w(DisasContext *ctx, arg_revb_2w *a) ++{ ++ handle_rev32(ctx, a->rj, a->rd); ++ return true; ++} ++ ++static bool trans_revb_d(DisasContext *ctx, arg_revb_d *a) ++{ ++ handle_rev64(ctx, a->rj, a->rd); ++ return true; ++} ++ ++static bool trans_revh_2w(DisasContext *ctx, arg_revh_2w *a) ++{ ++ handle_rev16(ctx, a->rj, a->rd); ++ return true; ++} ++ ++static bool trans_revh_d(DisasContext *ctx, arg_revh_d *a) ++{ ++ check_larch_64(ctx); ++ gen_bshfl(ctx, OPC_LARCH_REVH_D, a->rj, a->rd); ++ return true; ++} ++ ++static bool trans_bitrev_4b(DisasContext *ctx, arg_bitrev_4b *a) ++{ ++ gen_bitswap(ctx, OPC_LARCH_BREV_4B, a->rd, a->rj); ++ return true; ++} ++ ++static bool trans_bitrev_8b(DisasContext *ctx, arg_bitrev_8b *a) ++{ ++ check_larch_64(ctx); ++ gen_bitswap(ctx, OPC_LARCH_BREV_8B, a->rd, a->rj); ++ return true; ++} ++ ++static bool trans_bitrev_w(DisasContext *ctx, arg_bitrev_w *a) ++{ ++ TCGv t0 = tcg_temp_new(); ++ gen_load_gpr(t0, a->rj); ++ gen_helper_bitrev_w(cpu_gpr[a->rd], cpu_env, t0); ++ tcg_temp_free(t0); ++ return true; ++} ++ ++static bool trans_bitrev_d(DisasContext *ctx, arg_bitrev_d *a) ++{ ++ TCGv t0 = tcg_temp_new(); ++ gen_load_gpr(t0, a->rj); ++ gen_helper_bitrev_d(cpu_gpr[a->rd], cpu_env, t0); ++ tcg_temp_free(t0); ++ return true; ++} ++ ++static bool trans_ext_w_h(DisasContext *ctx, arg_ext_w_h *a) ++{ ++ gen_bshfl(ctx, OPC_LARCH_EXT_WH, a->rj, a->rd); ++ return true; ++} ++ ++static bool trans_ext_w_b(DisasContext *ctx, arg_ext_w_b *a) ++{ ++ gen_bshfl(ctx, OPC_LARCH_EXT_WB, a->rj, a->rd); ++ return true; ++} ++ ++static bool trans_srli_w(DisasContext *ctx, arg_srli_w *a) ++{ ++ gen_shift_imm(ctx, OPC_LARCH_SRLI_W, a->rd, a->rj, a->ui5); ++ return true; ++} ++ ++static bool trans_srai_w(DisasContext *ctx, arg_srai_w *a) ++{ ++ gen_shift_imm(ctx, OPC_LARCH_SRAI_W, a->rd, a->rj, a->ui5); ++ return true; ++} ++ ++static bool trans_srai_d(DisasContext *ctx, arg_srai_d *a) ++{ ++ TCGv t0; ++ check_larch_64(ctx); ++ t0 = tcg_temp_new(); ++ gen_load_gpr(t0, a->rj); ++ tcg_gen_sari_tl(cpu_gpr[a->rd], t0, a->ui6); ++ tcg_temp_free(t0); ++ return true; ++} ++ ++static bool trans_rotri_w(DisasContext *ctx, arg_rotri_w *a) ++{ ++ gen_shift_imm(ctx, OPC_LARCH_ROTRI_W, a->rd, a->rj, a->ui5); ++ return true; ++} ++ ++static bool trans_rotri_d(DisasContext *ctx, arg_rotri_d *a) ++{ ++ TCGv t0; ++ check_larch_64(ctx); ++ t0 = tcg_temp_new(); ++ gen_load_gpr(t0, a->rj); ++ tcg_gen_rotri_tl(cpu_gpr[a->rd], t0, a->ui6); ++ tcg_temp_free(t0); ++ return true; ++} ++ ++static bool trans_fcmp_cond_s(DisasContext *ctx, arg_fcmp_cond_s *a) ++{ ++ check_cp1_enabled(ctx); ++ gen_fcmp_s(ctx, a->fcond, a->fk, a->fj, a->cd); ++ return true; ++} ++ ++static bool trans_fcmp_cond_d(DisasContext *ctx, arg_fcmp_cond_d *a) ++{ ++ check_cp1_enabled(ctx); ++ gen_fcmp_d(ctx, a->fcond, a->fk, a->fj, a->cd); ++ return true; ++} ++ ++static bool trans_fsel(DisasContext *ctx, arg_fsel *a) ++{ ++ TCGv_i64 fj = tcg_temp_new_i64(); ++ TCGv_i64 fk = tcg_temp_new_i64(); ++ TCGv_i64 fd = tcg_temp_new_i64(); ++ TCGv_i32 ca = tcg_const_i32(a->ca); ++ check_cp1_enabled(ctx); ++ gen_load_fpr64(ctx, fj, a->fj); ++ gen_load_fpr64(ctx, fk, a->fk); ++ gen_helper_fsel(fd, cpu_env, fj, fk, ca); ++ gen_store_fpr64(ctx, fd, a->fd); ++ tcg_temp_free_i64(fj); ++ tcg_temp_free_i64(fk); ++ tcg_temp_free_i64(fd); ++ tcg_temp_free_i32(ca); ++ return true; ++} ++ ++#include "cpu-csr.h" ++ ++#ifdef CONFIG_USER_ONLY ++ ++static bool trans_csrxchg(DisasContext *ctx, arg_csrxchg *a) ++{ ++ return false; ++} ++ ++#else ++ ++ ++#define GEN_CSRRQ_CASE(name) \ ++ do { \ ++ case LOONGARCH_CSR_ ## name: \ ++ gen_csr_rdq(ctx, cpu_gpr[rd], LOONGARCH_CSR_ ## name);\ ++ } while (0) ++ ++static bool trans_csrrd(DisasContext *ctx, unsigned rd, unsigned csr) ++{ ++ switch (csr) { ++ GEN_CSRRQ_CASE(CRMD); ++ break; ++ GEN_CSRRQ_CASE(PRMD); ++ break; ++ GEN_CSRRQ_CASE(EUEN); ++ break; ++ GEN_CSRRQ_CASE(MISC); ++ break; ++ GEN_CSRRQ_CASE(ECFG); ++ break; ++ GEN_CSRRQ_CASE(ESTAT); ++ break; ++ GEN_CSRRQ_CASE(ERA); ++ break; ++ GEN_CSRRQ_CASE(BADV); ++ break; ++ GEN_CSRRQ_CASE(BADI); ++ break; ++ GEN_CSRRQ_CASE(EEPN); ++ break; ++ GEN_CSRRQ_CASE(TLBIDX); ++ break; ++ GEN_CSRRQ_CASE(TLBEHI); ++ break; ++ GEN_CSRRQ_CASE(TLBELO0); ++ break; ++ GEN_CSRRQ_CASE(TLBELO1); ++ break; ++ GEN_CSRRQ_CASE(TLBWIRED); ++ break; ++ GEN_CSRRQ_CASE(GTLBC); ++ break; ++ GEN_CSRRQ_CASE(TRGP); ++ break; ++ GEN_CSRRQ_CASE(ASID); ++ break; ++ GEN_CSRRQ_CASE(PGDL); ++ break; ++ GEN_CSRRQ_CASE(PGDH); ++ break; ++ case LOONGARCH_CSR_PGD: ++ gen_helper_read_pgd(cpu_gpr[rd], cpu_env); ++ break; ++ GEN_CSRRQ_CASE(PWCTL0); ++ break; ++ GEN_CSRRQ_CASE(PWCTL1); ++ break; ++ GEN_CSRRQ_CASE(STLBPGSIZE); ++ break; ++ GEN_CSRRQ_CASE(RVACFG); ++ break; ++ GEN_CSRRQ_CASE(CPUID); ++ break; ++ GEN_CSRRQ_CASE(PRCFG1); ++ break; ++ GEN_CSRRQ_CASE(PRCFG2); ++ break; ++ GEN_CSRRQ_CASE(PRCFG3); ++ break; ++ GEN_CSRRQ_CASE(KS0); ++ break; ++ GEN_CSRRQ_CASE(KS1); ++ break; ++ GEN_CSRRQ_CASE(KS2); ++ break; ++ GEN_CSRRQ_CASE(KS3); ++ break; ++ GEN_CSRRQ_CASE(KS4); ++ break; ++ GEN_CSRRQ_CASE(KS5); ++ break; ++ GEN_CSRRQ_CASE(KS6); ++ break; ++ GEN_CSRRQ_CASE(KS7); ++ break; ++ GEN_CSRRQ_CASE(KS8); ++ break; ++ GEN_CSRRQ_CASE(TMID); ++ break; ++ GEN_CSRRQ_CASE(TCFG); ++ break; ++ GEN_CSRRQ_CASE(TVAL); ++ break; ++ GEN_CSRRQ_CASE(CNTC); ++ break; ++ GEN_CSRRQ_CASE(TINTCLR); ++ break; ++ GEN_CSRRQ_CASE(GSTAT); ++ break; ++ GEN_CSRRQ_CASE(GCFG); ++ break; ++ GEN_CSRRQ_CASE(GINTC); ++ break; ++ GEN_CSRRQ_CASE(GCNTC); ++ break; ++ GEN_CSRRQ_CASE(LLBCTL); ++ break; ++ GEN_CSRRQ_CASE(IMPCTL1); ++ break; ++ GEN_CSRRQ_CASE(IMPCTL2); ++ break; ++ GEN_CSRRQ_CASE(GNMI); ++ break; ++ GEN_CSRRQ_CASE(TLBRENT); ++ break; ++ GEN_CSRRQ_CASE(TLBRBADV); ++ break; ++ GEN_CSRRQ_CASE(TLBRERA); ++ break; ++ GEN_CSRRQ_CASE(TLBRSAVE); ++ break; ++ GEN_CSRRQ_CASE(TLBRELO0); ++ break; ++ GEN_CSRRQ_CASE(TLBRELO1); ++ break; ++ GEN_CSRRQ_CASE(TLBREHI); ++ break; ++ GEN_CSRRQ_CASE(TLBRPRMD); ++ break; ++ GEN_CSRRQ_CASE(ERRCTL); ++ break; ++ GEN_CSRRQ_CASE(ERRINFO); ++ break; ++ GEN_CSRRQ_CASE(ERRINFO1); ++ break; ++ GEN_CSRRQ_CASE(ERRENT); ++ break; ++ GEN_CSRRQ_CASE(ERRERA); ++ break; ++ GEN_CSRRQ_CASE(ERRSAVE); ++ break; ++ GEN_CSRRQ_CASE(CTAG); ++ break; ++ GEN_CSRRQ_CASE(DMWIN0); ++ break; ++ GEN_CSRRQ_CASE(DMWIN1); ++ break; ++ GEN_CSRRQ_CASE(DMWIN2); ++ break; ++ GEN_CSRRQ_CASE(DMWIN3); ++ break; ++ GEN_CSRRQ_CASE(PERFCTRL0); ++ break; ++ GEN_CSRRQ_CASE(PERFCNTR0); ++ break; ++ GEN_CSRRQ_CASE(PERFCTRL1); ++ break; ++ GEN_CSRRQ_CASE(PERFCNTR1); ++ break; ++ GEN_CSRRQ_CASE(PERFCTRL2); ++ break; ++ GEN_CSRRQ_CASE(PERFCNTR2); ++ break; ++ GEN_CSRRQ_CASE(PERFCTRL3); ++ break; ++ GEN_CSRRQ_CASE(PERFCNTR3); ++ break; ++ /* debug */ ++ GEN_CSRRQ_CASE(MWPC); ++ break; ++ GEN_CSRRQ_CASE(MWPS); ++ break; ++ GEN_CSRRQ_CASE(DB0ADDR); ++ break; ++ GEN_CSRRQ_CASE(DB0MASK); ++ break; ++ GEN_CSRRQ_CASE(DB0CTL); ++ break; ++ GEN_CSRRQ_CASE(DB0ASID); ++ break; ++ GEN_CSRRQ_CASE(DB1ADDR); ++ break; ++ GEN_CSRRQ_CASE(DB1MASK); ++ break; ++ GEN_CSRRQ_CASE(DB1CTL); ++ break; ++ GEN_CSRRQ_CASE(DB1ASID); ++ break; ++ GEN_CSRRQ_CASE(DB2ADDR); ++ break; ++ GEN_CSRRQ_CASE(DB2MASK); ++ break; ++ GEN_CSRRQ_CASE(DB2CTL); ++ break; ++ GEN_CSRRQ_CASE(DB2ASID); ++ break; ++ GEN_CSRRQ_CASE(DB3ADDR); ++ break; ++ GEN_CSRRQ_CASE(DB3MASK); ++ break; ++ GEN_CSRRQ_CASE(DB3CTL); ++ break; ++ GEN_CSRRQ_CASE(DB3ASID); ++ break; ++ GEN_CSRRQ_CASE(FWPC); ++ break; ++ GEN_CSRRQ_CASE(FWPS); ++ break; ++ GEN_CSRRQ_CASE(IB0ADDR); ++ break; ++ GEN_CSRRQ_CASE(IB0MASK); ++ break; ++ GEN_CSRRQ_CASE(IB0CTL); ++ break; ++ GEN_CSRRQ_CASE(IB0ASID); ++ break; ++ GEN_CSRRQ_CASE(IB1ADDR); ++ break; ++ GEN_CSRRQ_CASE(IB1MASK); ++ break; ++ GEN_CSRRQ_CASE(IB1CTL); ++ break; ++ GEN_CSRRQ_CASE(IB1ASID); ++ break; ++ GEN_CSRRQ_CASE(IB2ADDR); ++ break; ++ GEN_CSRRQ_CASE(IB2MASK); ++ break; ++ GEN_CSRRQ_CASE(IB2CTL); ++ break; ++ GEN_CSRRQ_CASE(IB2ASID); ++ break; ++ GEN_CSRRQ_CASE(IB3ADDR); ++ break; ++ GEN_CSRRQ_CASE(IB3MASK); ++ break; ++ GEN_CSRRQ_CASE(IB3CTL); ++ break; ++ GEN_CSRRQ_CASE(IB3ASID); ++ break; ++ GEN_CSRRQ_CASE(IB4ADDR); ++ break; ++ GEN_CSRRQ_CASE(IB4MASK); ++ break; ++ GEN_CSRRQ_CASE(IB4CTL); ++ break; ++ GEN_CSRRQ_CASE(IB4ASID); ++ break; ++ GEN_CSRRQ_CASE(IB5ADDR); ++ break; ++ GEN_CSRRQ_CASE(IB5MASK); ++ break; ++ GEN_CSRRQ_CASE(IB5CTL); ++ break; ++ GEN_CSRRQ_CASE(IB5ASID); ++ break; ++ GEN_CSRRQ_CASE(IB6ADDR); ++ break; ++ GEN_CSRRQ_CASE(IB6MASK); ++ break; ++ GEN_CSRRQ_CASE(IB6CTL); ++ break; ++ GEN_CSRRQ_CASE(IB6ASID); ++ break; ++ GEN_CSRRQ_CASE(IB7ADDR); ++ break; ++ GEN_CSRRQ_CASE(IB7MASK); ++ break; ++ GEN_CSRRQ_CASE(IB7CTL); ++ break; ++ GEN_CSRRQ_CASE(IB7ASID); ++ break; ++ GEN_CSRRQ_CASE(DEBUG); ++ break; ++ GEN_CSRRQ_CASE(DERA); ++ break; ++ GEN_CSRRQ_CASE(DESAVE); ++ break; ++ default: ++ return false; ++ } ++ ++ #undef GEN_CSRRQ_CASE ++ ++ return true; ++} ++ ++#define GEN_CSRWQ_CASE(name) \ ++do { \ ++ case LOONGARCH_CSR_ ## name: \ ++ gen_csr_wrq(ctx, cpu_gpr[rd], LOONGARCH_CSR_ ## name); \ ++} while (0) ++ ++static bool trans_csrwr(DisasContext *ctx, unsigned rd, unsigned csr) ++{ ++ ++ switch (csr) { ++ case LOONGARCH_CSR_CRMD: ++ save_cpu_state(ctx, 1); ++ gen_csr_wrq(ctx, cpu_gpr[rd], LOONGARCH_CSR_CRMD); ++ gen_save_pc(ctx->base.pc_next + 4); ++ ctx->base.is_jmp = DISAS_EXIT; ++ break; ++ GEN_CSRWQ_CASE(PRMD); ++ break; ++ case LOONGARCH_CSR_EUEN: ++ gen_csr_wrq(ctx, cpu_gpr[rd], LOONGARCH_CSR_EUEN); ++ /* Stop translation */ ++ gen_save_pc(ctx->base.pc_next + 4); ++ ctx->base.is_jmp = DISAS_EXIT; ++ break; ++ GEN_CSRWQ_CASE(MISC); ++ break; ++ GEN_CSRWQ_CASE(ECFG); ++ break; ++ GEN_CSRWQ_CASE(ESTAT); ++ break; ++ GEN_CSRWQ_CASE(ERA); ++ break; ++ GEN_CSRWQ_CASE(BADV); ++ break; ++ GEN_CSRWQ_CASE(BADI); ++ break; ++ GEN_CSRWQ_CASE(EEPN); ++ break; ++ GEN_CSRWQ_CASE(TLBIDX); ++ break; ++ GEN_CSRWQ_CASE(TLBEHI); ++ break; ++ GEN_CSRWQ_CASE(TLBELO0); ++ break; ++ GEN_CSRWQ_CASE(TLBELO1); ++ break; ++ GEN_CSRWQ_CASE(TLBWIRED); ++ break; ++ GEN_CSRWQ_CASE(GTLBC); ++ break; ++ GEN_CSRWQ_CASE(TRGP); ++ break; ++ GEN_CSRWQ_CASE(ASID); ++ break; ++ GEN_CSRWQ_CASE(PGDL); ++ break; ++ GEN_CSRWQ_CASE(PGDH); ++ break; ++ GEN_CSRWQ_CASE(PGD); ++ break; ++ GEN_CSRWQ_CASE(PWCTL0); ++ break; ++ GEN_CSRWQ_CASE(PWCTL1); ++ break; ++ GEN_CSRWQ_CASE(STLBPGSIZE); ++ break; ++ GEN_CSRWQ_CASE(RVACFG); ++ break; ++ GEN_CSRWQ_CASE(CPUID); ++ break; ++ GEN_CSRWQ_CASE(PRCFG1); ++ break; ++ GEN_CSRWQ_CASE(PRCFG2); ++ break; ++ GEN_CSRWQ_CASE(PRCFG3); ++ break; ++ GEN_CSRWQ_CASE(KS0); ++ break; ++ GEN_CSRWQ_CASE(KS1); ++ break; ++ GEN_CSRWQ_CASE(KS2); ++ break; ++ GEN_CSRWQ_CASE(KS3); ++ break; ++ GEN_CSRWQ_CASE(KS4); ++ break; ++ GEN_CSRWQ_CASE(KS5); ++ break; ++ GEN_CSRWQ_CASE(KS6); ++ break; ++ GEN_CSRWQ_CASE(KS7); ++ break; ++ GEN_CSRWQ_CASE(KS8); ++ break; ++ GEN_CSRWQ_CASE(TMID); ++ break; ++ GEN_CSRWQ_CASE(TCFG); ++ break; ++ GEN_CSRWQ_CASE(TVAL); ++ break; ++ GEN_CSRWQ_CASE(CNTC); ++ break; ++ GEN_CSRWQ_CASE(TINTCLR); ++ break; ++ GEN_CSRWQ_CASE(GSTAT); ++ break; ++ GEN_CSRWQ_CASE(GCFG); ++ break; ++ GEN_CSRWQ_CASE(GINTC); ++ break; ++ GEN_CSRWQ_CASE(GCNTC); ++ break; ++ GEN_CSRWQ_CASE(LLBCTL); ++ break; ++ GEN_CSRWQ_CASE(IMPCTL1); ++ break; ++ GEN_CSRWQ_CASE(IMPCTL2); ++ break; ++ GEN_CSRWQ_CASE(GNMI); ++ break; ++ GEN_CSRWQ_CASE(TLBRENT); ++ break; ++ GEN_CSRWQ_CASE(TLBRBADV); ++ break; ++ GEN_CSRWQ_CASE(TLBRERA); ++ break; ++ GEN_CSRWQ_CASE(TLBRSAVE); ++ break; ++ GEN_CSRWQ_CASE(TLBRELO0); ++ break; ++ GEN_CSRWQ_CASE(TLBRELO1); ++ break; ++ GEN_CSRWQ_CASE(TLBREHI); ++ break; ++ GEN_CSRWQ_CASE(TLBRPRMD); ++ break; ++ GEN_CSRWQ_CASE(ERRCTL); ++ break; ++ GEN_CSRWQ_CASE(ERRINFO); ++ break; ++ GEN_CSRWQ_CASE(ERRINFO1); ++ break; ++ GEN_CSRWQ_CASE(ERRENT); ++ break; ++ GEN_CSRWQ_CASE(ERRERA); ++ break; ++ GEN_CSRWQ_CASE(ERRSAVE); ++ break; ++ GEN_CSRWQ_CASE(CTAG); ++ break; ++ GEN_CSRWQ_CASE(DMWIN0); ++ break; ++ GEN_CSRWQ_CASE(DMWIN1); ++ break; ++ GEN_CSRWQ_CASE(DMWIN2); ++ break; ++ GEN_CSRWQ_CASE(DMWIN3); ++ break; ++ GEN_CSRWQ_CASE(PERFCTRL0); ++ break; ++ GEN_CSRWQ_CASE(PERFCNTR0); ++ break; ++ GEN_CSRWQ_CASE(PERFCTRL1); ++ break; ++ GEN_CSRWQ_CASE(PERFCNTR1); ++ break; ++ GEN_CSRWQ_CASE(PERFCTRL2); ++ break; ++ GEN_CSRWQ_CASE(PERFCNTR2); ++ break; ++ GEN_CSRWQ_CASE(PERFCTRL3); ++ break; ++ GEN_CSRWQ_CASE(PERFCNTR3); ++ break; ++ /* debug */ ++ GEN_CSRWQ_CASE(MWPC); ++ break; ++ GEN_CSRWQ_CASE(MWPS); ++ break; ++ GEN_CSRWQ_CASE(DB0ADDR); ++ break; ++ GEN_CSRWQ_CASE(DB0MASK); ++ break; ++ GEN_CSRWQ_CASE(DB0CTL); ++ break; ++ GEN_CSRWQ_CASE(DB0ASID); ++ break; ++ GEN_CSRWQ_CASE(DB1ADDR); ++ break; ++ GEN_CSRWQ_CASE(DB1MASK); ++ break; ++ GEN_CSRWQ_CASE(DB1CTL); ++ break; ++ GEN_CSRWQ_CASE(DB1ASID); ++ break; ++ GEN_CSRWQ_CASE(DB2ADDR); ++ break; ++ GEN_CSRWQ_CASE(DB2MASK); ++ break; ++ GEN_CSRWQ_CASE(DB2CTL); ++ break; ++ GEN_CSRWQ_CASE(DB2ASID); ++ break; ++ GEN_CSRWQ_CASE(DB3ADDR); ++ break; ++ GEN_CSRWQ_CASE(DB3MASK); ++ break; ++ GEN_CSRWQ_CASE(DB3CTL); ++ break; ++ GEN_CSRWQ_CASE(DB3ASID); ++ break; ++ GEN_CSRWQ_CASE(FWPC); ++ break; ++ GEN_CSRWQ_CASE(FWPS); ++ break; ++ GEN_CSRWQ_CASE(IB0ADDR); ++ break; ++ GEN_CSRWQ_CASE(IB0MASK); ++ break; ++ GEN_CSRWQ_CASE(IB0CTL); ++ break; ++ GEN_CSRWQ_CASE(IB0ASID); ++ break; ++ GEN_CSRWQ_CASE(IB1ADDR); ++ break; ++ GEN_CSRWQ_CASE(IB1MASK); ++ break; ++ GEN_CSRWQ_CASE(IB1CTL); ++ break; ++ GEN_CSRWQ_CASE(IB1ASID); ++ break; ++ GEN_CSRWQ_CASE(IB2ADDR); ++ break; ++ GEN_CSRWQ_CASE(IB2MASK); ++ break; ++ GEN_CSRWQ_CASE(IB2CTL); ++ break; ++ GEN_CSRWQ_CASE(IB2ASID); ++ break; ++ GEN_CSRWQ_CASE(IB3ADDR); ++ break; ++ GEN_CSRWQ_CASE(IB3MASK); ++ break; ++ GEN_CSRWQ_CASE(IB3CTL); ++ break; ++ GEN_CSRWQ_CASE(IB3ASID); ++ break; ++ GEN_CSRWQ_CASE(IB4ADDR); ++ break; ++ GEN_CSRWQ_CASE(IB4MASK); ++ break; ++ GEN_CSRWQ_CASE(IB4CTL); ++ break; ++ GEN_CSRWQ_CASE(IB4ASID); ++ break; ++ GEN_CSRWQ_CASE(IB5ADDR); ++ break; ++ GEN_CSRWQ_CASE(IB5MASK); ++ break; ++ GEN_CSRWQ_CASE(IB5CTL); ++ break; ++ GEN_CSRWQ_CASE(IB5ASID); ++ break; ++ GEN_CSRWQ_CASE(IB6ADDR); ++ break; ++ GEN_CSRWQ_CASE(IB6MASK); ++ break; ++ GEN_CSRWQ_CASE(IB6CTL); ++ break; ++ GEN_CSRWQ_CASE(IB6ASID); ++ break; ++ GEN_CSRWQ_CASE(IB7ADDR); ++ break; ++ GEN_CSRWQ_CASE(IB7MASK); ++ break; ++ GEN_CSRWQ_CASE(IB7CTL); ++ break; ++ GEN_CSRWQ_CASE(IB7ASID); ++ break; ++ GEN_CSRWQ_CASE(DEBUG); ++ break; ++ GEN_CSRWQ_CASE(DERA); ++ break; ++ GEN_CSRWQ_CASE(DESAVE); ++ break; ++ default: ++ return false; ++ } ++ ++ #undef GEN_CSRWQ_CASE ++ ++ return true; ++} ++ ++#define GEN_CSRXQ_CASE(name) \ ++do { \ ++ case LOONGARCH_CSR_ ## name: \ ++ if (rd == 0) { \ ++ gen_csr_xchgq(ctx, zero, cpu_gpr[rj], \ ++ LOONGARCH_CSR_ ## name); \ ++ } else { \ ++ gen_csr_xchgq(ctx, cpu_gpr[rd], cpu_gpr[rj], \ ++ LOONGARCH_CSR_ ## name); \ ++ } \ ++} while (0) ++ ++static bool trans_csrxchg(DisasContext *ctx, arg_csrxchg *a) ++{ ++ unsigned rd, rj, csr; ++ TCGv zero = tcg_const_tl(0); ++ rd = a->rd; ++ rj = a->rj; ++ csr = a->csr; ++ ++ if (rj == 0) { ++ return trans_csrrd(ctx, rd, csr); ++ } else if (rj == 1) { ++ return trans_csrwr(ctx, rd, csr); ++ } ++ ++ switch (csr) { ++ case LOONGARCH_CSR_CRMD: ++ save_cpu_state(ctx, 1); ++ if (rd == 0) { ++ gen_csr_xchgq(ctx, zero, cpu_gpr[rj], LOONGARCH_CSR_CRMD); ++ } else { ++ gen_csr_xchgq(ctx, cpu_gpr[rd], cpu_gpr[rj], LOONGARCH_CSR_CRMD); ++ } ++ gen_save_pc(ctx->base.pc_next + 4); ++ ctx->base.is_jmp = DISAS_EXIT; ++ break; ++ ++ GEN_CSRXQ_CASE(PRMD); ++ break; ++ case LOONGARCH_CSR_EUEN: ++ if (rd == 0) { ++ gen_csr_xchgq(ctx, zero, cpu_gpr[rj], LOONGARCH_CSR_EUEN); ++ } else { ++ gen_csr_xchgq(ctx, cpu_gpr[rd], cpu_gpr[rj], LOONGARCH_CSR_EUEN); ++ } ++ /* Stop translation */ ++ gen_save_pc(ctx->base.pc_next + 4); ++ ctx->base.is_jmp = DISAS_EXIT; ++ break; ++ GEN_CSRXQ_CASE(MISC); ++ break; ++ GEN_CSRXQ_CASE(ECFG); ++ break; ++ GEN_CSRXQ_CASE(ESTAT); ++ break; ++ GEN_CSRXQ_CASE(ERA); ++ break; ++ GEN_CSRXQ_CASE(BADV); ++ break; ++ GEN_CSRXQ_CASE(BADI); ++ break; ++ GEN_CSRXQ_CASE(EEPN); ++ break; ++ GEN_CSRXQ_CASE(TLBIDX); ++ break; ++ GEN_CSRXQ_CASE(TLBEHI); ++ break; ++ GEN_CSRXQ_CASE(TLBELO0); ++ break; ++ GEN_CSRXQ_CASE(TLBELO1); ++ break; ++ GEN_CSRXQ_CASE(TLBWIRED); ++ break; ++ GEN_CSRXQ_CASE(GTLBC); ++ break; ++ GEN_CSRXQ_CASE(TRGP); ++ break; ++ GEN_CSRXQ_CASE(ASID); ++ break; ++ GEN_CSRXQ_CASE(PGDL); ++ break; ++ GEN_CSRXQ_CASE(PGDH); ++ break; ++ GEN_CSRXQ_CASE(PGD); ++ break; ++ GEN_CSRXQ_CASE(PWCTL0); ++ break; ++ GEN_CSRXQ_CASE(PWCTL1); ++ break; ++ GEN_CSRXQ_CASE(STLBPGSIZE); ++ break; ++ GEN_CSRXQ_CASE(RVACFG); ++ break; ++ GEN_CSRXQ_CASE(CPUID); ++ break; ++ GEN_CSRXQ_CASE(PRCFG1); ++ break; ++ GEN_CSRXQ_CASE(PRCFG2); ++ break; ++ GEN_CSRXQ_CASE(PRCFG3); ++ break; ++ GEN_CSRXQ_CASE(KS0); ++ break; ++ GEN_CSRXQ_CASE(KS1); ++ break; ++ GEN_CSRXQ_CASE(KS2); ++ break; ++ GEN_CSRXQ_CASE(KS3); ++ break; ++ GEN_CSRXQ_CASE(KS4); ++ break; ++ GEN_CSRXQ_CASE(KS5); ++ break; ++ GEN_CSRXQ_CASE(KS6); ++ break; ++ GEN_CSRXQ_CASE(KS7); ++ break; ++ GEN_CSRXQ_CASE(KS8); ++ break; ++ GEN_CSRXQ_CASE(TMID); ++ break; ++ GEN_CSRXQ_CASE(TCFG); ++ break; ++ GEN_CSRXQ_CASE(TVAL); ++ break; ++ GEN_CSRXQ_CASE(CNTC); ++ break; ++ GEN_CSRXQ_CASE(TINTCLR); ++ break; ++ GEN_CSRXQ_CASE(GSTAT); ++ break; ++ GEN_CSRXQ_CASE(GCFG); ++ break; ++ GEN_CSRXQ_CASE(GINTC); ++ break; ++ GEN_CSRXQ_CASE(GCNTC); ++ break; ++ GEN_CSRXQ_CASE(LLBCTL); ++ break; ++ GEN_CSRXQ_CASE(IMPCTL1); ++ break; ++ GEN_CSRXQ_CASE(IMPCTL2); ++ break; ++ GEN_CSRXQ_CASE(GNMI); ++ break; ++ GEN_CSRXQ_CASE(TLBRENT); ++ break; ++ GEN_CSRXQ_CASE(TLBRBADV); ++ break; ++ GEN_CSRXQ_CASE(TLBRERA); ++ break; ++ GEN_CSRXQ_CASE(TLBRSAVE); ++ break; ++ GEN_CSRXQ_CASE(TLBRELO0); ++ break; ++ GEN_CSRXQ_CASE(TLBRELO1); ++ break; ++ GEN_CSRXQ_CASE(TLBREHI); ++ break; ++ GEN_CSRXQ_CASE(TLBRPRMD); ++ break; ++ GEN_CSRXQ_CASE(ERRCTL); ++ break; ++ GEN_CSRXQ_CASE(ERRINFO); ++ break; ++ GEN_CSRXQ_CASE(ERRINFO1); ++ break; ++ GEN_CSRXQ_CASE(ERRENT); ++ break; ++ GEN_CSRXQ_CASE(ERRERA); ++ break; ++ GEN_CSRXQ_CASE(ERRSAVE); ++ break; ++ GEN_CSRXQ_CASE(CTAG); ++ break; ++ GEN_CSRXQ_CASE(DMWIN0); ++ break; ++ GEN_CSRXQ_CASE(DMWIN1); ++ break; ++ GEN_CSRXQ_CASE(DMWIN2); ++ break; ++ GEN_CSRXQ_CASE(DMWIN3); ++ break; ++ GEN_CSRXQ_CASE(PERFCTRL0); ++ break; ++ GEN_CSRXQ_CASE(PERFCNTR0); ++ break; ++ GEN_CSRXQ_CASE(PERFCTRL1); ++ break; ++ GEN_CSRXQ_CASE(PERFCNTR1); ++ break; ++ GEN_CSRXQ_CASE(PERFCTRL2); ++ break; ++ GEN_CSRXQ_CASE(PERFCNTR2); ++ break; ++ GEN_CSRXQ_CASE(PERFCTRL3); ++ break; ++ GEN_CSRXQ_CASE(PERFCNTR3); ++ break; ++ /* debug */ ++ GEN_CSRXQ_CASE(MWPC); ++ break; ++ GEN_CSRXQ_CASE(MWPS); ++ break; ++ GEN_CSRXQ_CASE(DB0ADDR); ++ break; ++ GEN_CSRXQ_CASE(DB0MASK); ++ break; ++ GEN_CSRXQ_CASE(DB0CTL); ++ break; ++ GEN_CSRXQ_CASE(DB0ASID); ++ break; ++ GEN_CSRXQ_CASE(DB1ADDR); ++ break; ++ GEN_CSRXQ_CASE(DB1MASK); ++ break; ++ GEN_CSRXQ_CASE(DB1CTL); ++ break; ++ GEN_CSRXQ_CASE(DB1ASID); ++ break; ++ GEN_CSRXQ_CASE(DB2ADDR); ++ break; ++ GEN_CSRXQ_CASE(DB2MASK); ++ break; ++ GEN_CSRXQ_CASE(DB2CTL); ++ break; ++ GEN_CSRXQ_CASE(DB2ASID); ++ break; ++ GEN_CSRXQ_CASE(DB3ADDR); ++ break; ++ GEN_CSRXQ_CASE(DB3MASK); ++ break; ++ GEN_CSRXQ_CASE(DB3CTL); ++ break; ++ GEN_CSRXQ_CASE(DB3ASID); ++ break; ++ GEN_CSRXQ_CASE(FWPC); ++ break; ++ GEN_CSRXQ_CASE(FWPS); ++ break; ++ GEN_CSRXQ_CASE(IB0ADDR); ++ break; ++ GEN_CSRXQ_CASE(IB0MASK); ++ break; ++ GEN_CSRXQ_CASE(IB0CTL); ++ break; ++ GEN_CSRXQ_CASE(IB0ASID); ++ break; ++ GEN_CSRXQ_CASE(IB1ADDR); ++ break; ++ GEN_CSRXQ_CASE(IB1MASK); ++ break; ++ GEN_CSRXQ_CASE(IB1CTL); ++ break; ++ GEN_CSRXQ_CASE(IB1ASID); ++ break; ++ GEN_CSRXQ_CASE(IB2ADDR); ++ break; ++ GEN_CSRXQ_CASE(IB2MASK); ++ break; ++ GEN_CSRXQ_CASE(IB2CTL); ++ break; ++ GEN_CSRXQ_CASE(IB2ASID); ++ break; ++ GEN_CSRXQ_CASE(IB3ADDR); ++ break; ++ GEN_CSRXQ_CASE(IB3MASK); ++ break; ++ GEN_CSRXQ_CASE(IB3CTL); ++ break; ++ GEN_CSRXQ_CASE(IB3ASID); ++ break; ++ GEN_CSRXQ_CASE(IB4ADDR); ++ break; ++ GEN_CSRXQ_CASE(IB4MASK); ++ break; ++ GEN_CSRXQ_CASE(IB4CTL); ++ break; ++ GEN_CSRXQ_CASE(IB4ASID); ++ break; ++ GEN_CSRXQ_CASE(IB5ADDR); ++ break; ++ GEN_CSRXQ_CASE(IB5MASK); ++ break; ++ GEN_CSRXQ_CASE(IB5CTL); ++ break; ++ GEN_CSRXQ_CASE(IB5ASID); ++ break; ++ GEN_CSRXQ_CASE(IB6ADDR); ++ break; ++ GEN_CSRXQ_CASE(IB6MASK); ++ break; ++ GEN_CSRXQ_CASE(IB6CTL); ++ break; ++ GEN_CSRXQ_CASE(IB6ASID); ++ break; ++ GEN_CSRXQ_CASE(IB7ADDR); ++ break; ++ GEN_CSRXQ_CASE(IB7MASK); ++ break; ++ GEN_CSRXQ_CASE(IB7CTL); ++ break; ++ GEN_CSRXQ_CASE(IB7ASID); ++ break; ++ GEN_CSRXQ_CASE(DEBUG); ++ break; ++ GEN_CSRXQ_CASE(DERA); ++ break; ++ GEN_CSRXQ_CASE(DESAVE); ++ break; ++ default: ++ return false; ++ } ++ ++ #undef GEN_CSRXQ_CASE ++ tcg_temp_free(zero); ++ return true; ++} ++ ++#endif ++ ++static bool trans_cacop(DisasContext *ctx, arg_cacop *a) ++{ ++ /* Treat as NOP. */ ++ return true; ++} ++ ++#ifdef CONFIG_USER_ONLY ++ ++static bool trans_ldpte(DisasContext *ctx, arg_ldpte *a) ++{ ++ return false; ++} ++ ++static bool trans_lddir(DisasContext *ctx, arg_lddir *a) ++{ ++ return false; ++} ++ ++static bool trans_iocsrrd_b(DisasContext *ctx, arg_iocsrrd_b *a) ++{ ++ return false; ++} ++ ++static bool trans_iocsrrd_h(DisasContext *ctx, arg_iocsrrd_h *a) ++{ ++ return false; ++} ++ ++static bool trans_iocsrrd_w(DisasContext *ctx, arg_iocsrrd_w *a) ++{ ++ return false; ++} ++ ++static bool trans_iocsrrd_d(DisasContext *ctx, arg_iocsrrd_d *a) ++{ ++ return false; ++} ++ ++static bool trans_iocsrwr_b(DisasContext *ctx, arg_iocsrwr_b *a) ++{ ++ return false; ++} ++ ++static bool trans_iocsrwr_h(DisasContext *ctx, arg_iocsrwr_h *a) ++{ ++ return false; ++} ++ ++static bool trans_iocsrwr_w(DisasContext *ctx, arg_iocsrwr_w *a) ++{ ++ return false; ++} ++ ++static bool trans_iocsrwr_d(DisasContext *ctx, arg_iocsrwr_d *a) ++{ ++ return false; ++} ++#else ++ ++static bool trans_ldpte(DisasContext *ctx, arg_ldpte *a) ++{ ++ TCGv t0, t1; ++ TCGv_i32 t2; ++ t0 = tcg_const_tl(a->rj); ++ t1 = tcg_const_tl(a->seq); ++ t2 = tcg_const_i32(ctx->mem_idx); ++ gen_helper_ldpte(cpu_env, t0, t1, t2); ++ ++ return true; ++} ++ ++static bool trans_lddir(DisasContext *ctx, arg_lddir *a) ++{ ++ TCGv t0, t1, t2; ++ TCGv_i32 t3; ++ t0 = tcg_const_tl(a->rj); ++ t1 = tcg_const_tl(a->rd); ++ t2 = tcg_const_tl(a->level); ++ t3 = tcg_const_i32(ctx->mem_idx); ++ gen_helper_lddir(cpu_env, t0, t1, t2, t3); ++ ++ return true; ++} ++ ++static bool trans_iocsrrd_b(DisasContext *ctx, arg_iocsrrd_b *a) ++{ ++ return false; ++} ++ ++static bool trans_iocsrrd_h(DisasContext *ctx, arg_iocsrrd_h *a) ++{ ++ return false; ++} ++ ++static bool trans_iocsrrd_w(DisasContext *ctx, arg_iocsrrd_w *a) ++{ ++ TCGv_i32 iocsr_op = tcg_const_i32(OPC_LARCH_LD_W); ++ TCGv t0, t1; ++ t0 = tcg_const_tl(a->rj); ++ t1 = tcg_const_tl(a->rd); ++ gen_helper_iocsr(cpu_env, t0, t1, iocsr_op); ++ return true; ++} ++ ++static bool trans_iocsrrd_d(DisasContext *ctx, arg_iocsrrd_d *a) ++{ ++ TCGv_i32 iocsr_op = tcg_const_i32(OPC_LARCH_LD_D); ++ TCGv t0, t1; ++ t0 = tcg_const_tl(a->rj); ++ t1 = tcg_const_tl(a->rd); ++ gen_helper_iocsr(cpu_env, t0, t1, iocsr_op); ++ return true; ++} ++ ++static bool trans_iocsrwr_b(DisasContext *ctx, arg_iocsrwr_b *a) ++{ ++ TCGv_i32 iocsr_op = tcg_const_i32(OPC_LARCH_ST_B); ++ TCGv t0, t1; ++ t0 = tcg_const_tl(a->rj); ++ t1 = tcg_const_tl(a->rd); ++ gen_helper_iocsr(cpu_env, t0, t1, iocsr_op); ++ return true; ++} ++ ++static bool trans_iocsrwr_h(DisasContext *ctx, arg_iocsrwr_h *a) ++{ ++ return false; ++} ++ ++static bool trans_iocsrwr_w(DisasContext *ctx, arg_iocsrwr_w *a) ++{ ++ TCGv_i32 iocsr_op = tcg_const_i32(OPC_LARCH_ST_W); ++ TCGv t0, t1; ++ t0 = tcg_const_tl(a->rj); ++ t1 = tcg_const_tl(a->rd); ++ gen_helper_iocsr(cpu_env, t0, t1, iocsr_op); ++ return true; ++} ++ ++static bool trans_iocsrwr_d(DisasContext *ctx, arg_iocsrwr_d *a) ++{ ++ TCGv_i32 iocsr_op = tcg_const_i32(OPC_LARCH_ST_D); ++ TCGv t0, t1; ++ t0 = tcg_const_tl(a->rj); ++ t1 = tcg_const_tl(a->rd); ++ gen_helper_iocsr(cpu_env, t0, t1, iocsr_op); ++ return true; ++} ++#endif /* !CONFIG_USER_ONLY */ ++ ++ ++#ifdef CONFIG_USER_ONLY ++ ++#define GEN_FALSE_TRANS(name) \ ++static bool trans_##name(DisasContext *ctx, arg_##name * a) \ ++{ \ ++ return false; \ ++} ++ ++GEN_FALSE_TRANS(tlbclr) ++GEN_FALSE_TRANS(invtlb) ++GEN_FALSE_TRANS(tlbflush) ++GEN_FALSE_TRANS(tlbsrch) ++GEN_FALSE_TRANS(tlbrd) ++GEN_FALSE_TRANS(tlbwr) ++GEN_FALSE_TRANS(tlbfill) ++GEN_FALSE_TRANS(ertn) ++ ++#else ++ ++static bool trans_tlbclr(DisasContext *ctx, arg_tlbclr *a) ++{ ++ gen_helper_tlbclr(cpu_env); ++ return true; ++} ++ ++static bool trans_tlbflush(DisasContext *ctx, arg_tlbflush *a) ++{ ++ gen_helper_tlbflush(cpu_env); ++ return true; ++} ++ ++static bool trans_invtlb(DisasContext *ctx, arg_invtlb *a) ++{ ++ TCGv addr = tcg_temp_new(); ++ TCGv info = tcg_temp_new(); ++ TCGv op = tcg_const_tl(a->invop); ++ ++ gen_load_gpr(addr, a->addr); ++ gen_load_gpr(info, a->info); ++ gen_helper_invtlb(cpu_env, addr, info, op); ++ ++ tcg_temp_free(addr); ++ tcg_temp_free(info); ++ tcg_temp_free(op); ++ return true; ++} ++ ++static bool trans_tlbsrch(DisasContext *ctx, arg_tlbsrch *a) ++{ ++ gen_helper_tlbsrch(cpu_env); ++ return true; ++} ++ ++static bool trans_tlbrd(DisasContext *ctx, arg_tlbrd *a) ++{ ++ gen_helper_tlbrd(cpu_env); ++ return true; ++} ++ ++static bool trans_tlbwr(DisasContext *ctx, arg_tlbwr *a) ++{ ++ gen_helper_tlbwr(cpu_env); ++ return true; ++} ++ ++static bool trans_tlbfill(DisasContext *ctx, arg_tlbfill *a) ++{ ++ gen_helper_tlbfill(cpu_env); ++ return true; ++} ++ ++static bool trans_ertn(DisasContext *ctx, arg_ertn *a) ++{ ++ gen_helper_ertn(cpu_env); ++ ctx->base.is_jmp = DISAS_EXIT; ++ return true; ++} ++ ++#endif /* CONFIG_USER_ONLY */ ++ ++static bool trans_idle(DisasContext *ctx, arg_idle *a) ++{ ++ ctx->base.pc_next += 4; ++ save_cpu_state(ctx, 1); ++ ctx->base.pc_next -= 4; ++ gen_helper_idle(cpu_env); ++ ctx->base.is_jmp = DISAS_NORETURN; ++ return true; ++} ++ ++#ifdef CONFIG_USER_ONLY ++ ++static bool trans_rdtime_d(DisasContext *ctx, arg_rdtime_d *a) ++{ ++ /* Nop */ ++ return true; ++} ++ ++#else ++ ++static bool trans_rdtime_d(DisasContext *ctx, arg_rdtime_d *a) ++{ ++ TCGv t0, t1; ++ t0 = tcg_const_tl(a->rd); ++ t1 = tcg_const_tl(a->rj); ++ gen_helper_drdtime(cpu_env, t0, t1); ++ tcg_temp_free(t0); ++ tcg_temp_free(t1); ++ return true; ++} ++ ++#endif ++ ++static bool trans_cpucfg(DisasContext *ctx, arg_cpucfg *a) ++{ ++ TCGv t0 = tcg_temp_new(); ++ gen_load_gpr(t0, a->rj); ++ gen_helper_cpucfg(cpu_gpr[a->rd], cpu_env, t0); ++ tcg_temp_free(t0); ++ return true; ++} +diff --git a/target/loongarch64/translate.c b/target/loongarch64/translate.c +new file mode 100644 +index 0000000000..fe122e4c31 +--- /dev/null ++++ b/target/loongarch64/translate.c +@@ -0,0 +1,2892 @@ ++/* ++ * LOONGARCH emulation for QEMU - main translation routines ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, see . ++ */ ++ ++#include "qemu/osdep.h" ++#include "cpu.h" ++#include "internal.h" ++#include "disas/disas.h" ++#include "exec/exec-all.h" ++#include "tcg/tcg-op.h" ++#include "exec/cpu_ldst.h" ++#include "hw/loongarch/cpudevs.h" ++ ++#include "exec/helper-proto.h" ++#include "exec/helper-gen.h" ++#include "semihosting/semihost.h" ++ ++#include "trace-tcg.h" ++#include "exec/translator.h" ++#include "exec/log.h" ++ ++#include "instmap.h" ++ ++#define LARCH_DEBUG_DISAS 0 ++ ++/* Values for the fmt field in FP instructions */ ++enum { ++ /* 0 - 15 are reserved */ ++ FMT_S = 16, /* single fp */ ++ FMT_D = 17, /* double fp */ ++}; ++ ++/* global register indices */ ++static TCGv cpu_gpr[32], cpu_PC; ++static TCGv btarget, bcond; ++static TCGv cpu_lladdr, cpu_llval; ++static TCGv_i32 hflags; ++static TCGv_i32 fpu_fcsr0; ++static TCGv_i64 fpu_f64[32]; ++ ++#include "exec/gen-icount.h" ++ ++#define gen_helper_0e0i(name, arg) do { \ ++ TCGv_i32 helper_tmp = tcg_const_i32(arg); \ ++ gen_helper_##name(cpu_env, helper_tmp); \ ++ tcg_temp_free_i32(helper_tmp); \ ++ } while (0) ++ ++#define gen_helper_0e1i(name, arg1, arg2) do { \ ++ TCGv_i32 helper_tmp = tcg_const_i32(arg2); \ ++ gen_helper_##name(cpu_env, arg1, helper_tmp); \ ++ tcg_temp_free_i32(helper_tmp); \ ++ } while (0) ++ ++#define gen_helper_1e0i(name, ret, arg1) do { \ ++ TCGv_i32 helper_tmp = tcg_const_i32(arg1); \ ++ gen_helper_##name(ret, cpu_env, helper_tmp); \ ++ tcg_temp_free_i32(helper_tmp); \ ++ } while (0) ++ ++#define gen_helper_1e1i(name, ret, arg1, arg2) do { \ ++ TCGv_i32 helper_tmp = tcg_const_i32(arg2); \ ++ gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \ ++ tcg_temp_free_i32(helper_tmp); \ ++ } while (0) ++ ++#define gen_helper_0e2i(name, arg1, arg2, arg3) do { \ ++ TCGv_i32 helper_tmp = tcg_const_i32(arg3); \ ++ gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \ ++ tcg_temp_free_i32(helper_tmp); \ ++ } while (0) ++ ++#define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \ ++ TCGv_i32 helper_tmp = tcg_const_i32(arg3); \ ++ gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \ ++ tcg_temp_free_i32(helper_tmp); \ ++ } while (0) ++ ++#define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \ ++ TCGv_i32 helper_tmp = tcg_const_i32(arg4); \ ++ gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \ ++ tcg_temp_free_i32(helper_tmp); \ ++ } while (0) ++ ++typedef struct DisasContext { ++ DisasContextBase base; ++ target_ulong saved_pc; ++ target_ulong page_start; ++ uint32_t opcode; ++ uint64_t insn_flags; ++ /* Routine used to access memory */ ++ int mem_idx; ++ MemOp default_tcg_memop_mask; ++ uint32_t hflags, saved_hflags; ++ target_ulong btarget; ++} DisasContext; ++ ++#define DISAS_STOP DISAS_TARGET_0 ++#define DISAS_EXIT DISAS_TARGET_1 ++ ++#define LOG_DISAS(...) \ ++ do { \ ++ if (LARCH_DEBUG_DISAS) { \ ++ qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \ ++ } \ ++ } while (0) ++ ++#define LARCH_INVAL(op) \ ++ do { \ ++ if (LARCH_DEBUG_DISAS) { \ ++ qemu_log_mask(CPU_LOG_TB_IN_ASM, \ ++ TARGET_FMT_lx ": %08x Invalid %s %03x %03x %03x\n", \ ++ ctx->base.pc_next, ctx->opcode, op, \ ++ ctx->opcode >> 26, ctx->opcode & 0x3F, \ ++ ((ctx->opcode >> 16) & 0x1F)); \ ++ } \ ++ } while (0) ++ ++/* General purpose registers moves. */ ++static inline void gen_load_gpr(TCGv t, int reg) ++{ ++ if (reg == 0) { ++ tcg_gen_movi_tl(t, 0); ++ } else { ++ tcg_gen_mov_tl(t, cpu_gpr[reg]); ++ } ++} ++ ++static inline void gen_store_gpr(TCGv t, int reg) ++{ ++ if (reg != 0) { ++ tcg_gen_mov_tl(cpu_gpr[reg], t); ++ } ++} ++ ++/* Moves to/from shadow registers. */ ++/* Tests */ ++static inline void gen_save_pc(target_ulong pc) ++{ ++ tcg_gen_movi_tl(cpu_PC, pc); ++} ++ ++static inline void save_cpu_state(DisasContext *ctx, int do_save_pc) ++{ ++ LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags); ++ if (do_save_pc && ctx->base.pc_next != ctx->saved_pc) { ++ gen_save_pc(ctx->base.pc_next); ++ ctx->saved_pc = ctx->base.pc_next; ++ } ++ if (ctx->hflags != ctx->saved_hflags) { ++ tcg_gen_movi_i32(hflags, ctx->hflags); ++ ctx->saved_hflags = ctx->hflags; ++ switch (ctx->hflags & LARCH_HFLAG_BMASK) { ++ case LARCH_HFLAG_BR: ++ break; ++ case LARCH_HFLAG_BC: ++ case LARCH_HFLAG_B: ++ tcg_gen_movi_tl(btarget, ctx->btarget); ++ break; ++ } ++ } ++} ++ ++static inline void restore_cpu_state(CPULOONGARCHState *env, DisasContext *ctx) ++{ ++ ctx->saved_hflags = ctx->hflags; ++ switch (ctx->hflags & LARCH_HFLAG_BMASK) { ++ case LARCH_HFLAG_BR: ++ break; ++ case LARCH_HFLAG_BC: ++ case LARCH_HFLAG_B: ++ ctx->btarget = env->btarget; ++ break; ++ } ++} ++ ++static inline void generate_exception_err(DisasContext *ctx, int excp, int err) ++{ ++ TCGv_i32 texcp = tcg_const_i32(excp); ++ TCGv_i32 terr = tcg_const_i32(err); ++ save_cpu_state(ctx, 1); ++ gen_helper_raise_exception_err(cpu_env, texcp, terr); ++ tcg_temp_free_i32(terr); ++ tcg_temp_free_i32(texcp); ++ ctx->base.is_jmp = DISAS_NORETURN; ++} ++ ++static inline void generate_exception_end(DisasContext *ctx, int excp) ++{ ++ generate_exception_err(ctx, excp, 0); ++} ++ ++/* Floating point register moves. */ ++static void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg) ++{ ++ tcg_gen_extrl_i64_i32(t, fpu_f64[reg]); ++} ++ ++static void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg) ++{ ++ TCGv_i64 t64; ++ t64 = tcg_temp_new_i64(); ++ tcg_gen_extu_i32_i64(t64, t); ++ tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32); ++ tcg_temp_free_i64(t64); ++} ++ ++static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg) ++{ ++ tcg_gen_extrh_i64_i32(t, fpu_f64[reg]); ++} ++ ++static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg) ++{ ++ TCGv_i64 t64 = tcg_temp_new_i64(); ++ tcg_gen_extu_i32_i64(t64, t); ++ tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32); ++ tcg_temp_free_i64(t64); ++} ++ ++static void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg) ++{ ++ tcg_gen_mov_i64(t, fpu_f64[reg]); ++} ++ ++static void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg) ++{ ++ tcg_gen_mov_i64(fpu_f64[reg], t); ++} ++ ++static inline int get_fp_bit(int cc) ++{ ++ if (cc) { ++ return 24 + cc; ++ } else { ++ return 23; ++ } ++} ++ ++/* Addresses computation */ ++static inline void gen_op_addr_add(DisasContext *ctx, ++ TCGv ret, TCGv arg0, TCGv arg1) ++{ ++ tcg_gen_add_tl(ret, arg0, arg1); ++ ++ if (ctx->hflags & LARCH_HFLAG_AWRAP) { ++ tcg_gen_ext32s_i64(ret, ret); ++ } ++} ++ ++static inline void gen_op_addr_addi(DisasContext *ctx, TCGv ret, TCGv base, ++ target_long ofs) ++{ ++ tcg_gen_addi_tl(ret, base, ofs); ++ ++ if (ctx->hflags & LARCH_HFLAG_AWRAP) { ++ tcg_gen_ext32s_i64(ret, ret); ++ } ++} ++ ++/* Sign-extract the low 32-bits to a target_long. */ ++static inline void gen_move_low32(TCGv ret, TCGv_i64 arg) ++{ ++ tcg_gen_ext32s_i64(ret, arg); ++} ++ ++/* Sign-extract the high 32-bits to a target_long. */ ++static inline void gen_move_high32(TCGv ret, TCGv_i64 arg) ++{ ++ tcg_gen_sari_i64(ret, arg, 32); ++} ++ ++static inline void check_cp1_enabled(DisasContext *ctx) ++{ ++#ifndef CONFIG_USER_ONLY ++ if (unlikely(!(ctx->hflags & LARCH_HFLAG_FPU))) { ++ generate_exception_err(ctx, EXCP_FPDIS, 1); ++ } ++#endif ++} ++ ++static inline void check_lsx_enabled(DisasContext *ctx) ++{ ++#ifndef CONFIG_USER_ONLY ++ if (unlikely(!(ctx->hflags & LARCH_HFLAG_LSX))) { ++ generate_exception_err(ctx, EXCP_LSXDIS, 1); ++ } ++#endif ++} ++ ++static inline void check_lasx_enabled(DisasContext *ctx) ++{ ++#ifndef CONFIG_USER_ONLY ++ if (unlikely(!(ctx->hflags & LARCH_HFLAG_LASX))) { ++ generate_exception_err(ctx, EXCP_LASXDIS, 1); ++ } ++#endif ++} ++ ++static inline void check_lbt_enabled(DisasContext *ctx) ++{ ++#ifndef CONFIG_USER_ONLY ++ if (unlikely(!(ctx->hflags & LARCH_HFLAG_LBT))) { ++ generate_exception_err(ctx, EXCP_BTDIS, 1); ++ } ++#endif ++} ++ ++/* This code generates a "reserved instruction" exception if the ++ CPU does not support the instruction set corresponding to flags. */ ++static inline void check_insn(DisasContext *ctx, uint64_t flags) ++{ ++ if (unlikely(!(ctx->insn_flags & flags))) { ++ generate_exception_end(ctx, EXCP_RI); ++ } ++} ++ ++/* This code generates a "reserved instruction" exception if the ++ CPU has corresponding flag set which indicates that the instruction ++ has been removed. */ ++static inline void check_insn_opc_removed(DisasContext *ctx, uint64_t flags) ++{ ++ if (unlikely(ctx->insn_flags & flags)) { ++ generate_exception_end(ctx, EXCP_RI); ++ } ++} ++ ++/* ++ * The Linux kernel traps certain reserved instruction exceptions to ++ * emulate the corresponding instructions. QEMU is the kernel in user ++ * mode, so those traps are emulated by accepting the instructions. ++ * ++ * A reserved instruction exception is generated for flagged CPUs if ++ * QEMU runs in system mode. ++ */ ++static inline void check_insn_opc_user_only(DisasContext *ctx, uint64_t flags) ++{ ++#ifndef CONFIG_USER_ONLY ++ check_insn_opc_removed(ctx, flags); ++#endif ++} ++ ++/* This code generates a "reserved instruction" exception if 64-bit ++ instructions are not enabled. */ ++static inline void check_larch_64(DisasContext *ctx) ++{ ++ if (unlikely(!(ctx->hflags & LARCH_HFLAG_64))) { ++ generate_exception_end(ctx, EXCP_RI); ++ } ++} ++ ++/* Define small wrappers for gen_load_fpr* so that we have a uniform ++ calling interface for 32 and 64-bit FPRs. No sense in changing ++ all callers for gen_load_fpr32 when we need the CTX parameter for ++ this one use. */ ++#define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y) ++#define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y) ++#define FCOP_CONDNS(fmt, ifmt, bits, STORE) \ ++static inline void gen_fcmp_ ## fmt(DisasContext *ctx, int n, \ ++ int ft, int fs, int cd) \ ++{ \ ++ TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \ ++ TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \ ++ TCGv_i32 fcc = tcg_const_i32(cd); \ ++ check_cp1_enabled(ctx); \ ++ gen_ldcmp_fpr ## bits(ctx, fp0, fs); \ ++ gen_ldcmp_fpr ## bits(ctx, fp1, ft); \ ++ switch (n) { \ ++ case 0: \ ++ gen_helper_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \ ++ break; \ ++ case 1: \ ++ gen_helper_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \ ++ break; \ ++ case 2: \ ++ gen_helper_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \ ++ break; \ ++ case 3: \ ++ gen_helper_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \ ++ break; \ ++ case 4: \ ++ gen_helper_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \ ++ break; \ ++ case 5: \ ++ gen_helper_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \ ++ break; \ ++ case 6: \ ++ gen_helper_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \ ++ break; \ ++ case 7: \ ++ gen_helper_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \ ++ break; \ ++ case 8: \ ++ gen_helper_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \ ++ break; \ ++ case 9: \ ++ gen_helper_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \ ++ break; \ ++ case 10: \ ++ gen_helper_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \ ++ break; \ ++ case 11: \ ++ gen_helper_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \ ++ break; \ ++ case 12: \ ++ gen_helper_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \ ++ break; \ ++ case 13: \ ++ gen_helper_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \ ++ break; \ ++ case 14: \ ++ gen_helper_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \ ++ break; \ ++ case 15: \ ++ gen_helper_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \ ++ break; \ ++ case 16: \ ++ gen_helper_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \ ++ break; \ ++ case 17: \ ++ gen_helper_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \ ++ break; \ ++ case 20: \ ++ gen_helper_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \ ++ break; \ ++ case 21: \ ++ gen_helper_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \ ++ break; \ ++ case 24: \ ++ gen_helper_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \ ++ break; \ ++ case 25: \ ++ gen_helper_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \ ++ break; \ ++ default: \ ++ abort(); \ ++ } \ ++ STORE; \ ++ tcg_temp_free_i ## bits(fp0); \ ++ tcg_temp_free_i ## bits(fp1); \ ++ tcg_temp_free_i32(fcc); \ ++} ++ ++FCOP_CONDNS(d, FMT_D, 64, gen_helper_movreg2cf_i64(cpu_env, fcc, fp0)) ++FCOP_CONDNS(s, FMT_S, 32, gen_helper_movreg2cf_i32(cpu_env, fcc, fp0)) ++#undef FCOP_CONDNS ++#undef gen_ldcmp_fpr32 ++#undef gen_ldcmp_fpr64 ++ ++/* load/store instructions. */ ++#ifdef CONFIG_USER_ONLY ++#define OP_LD_ATOMIC(insn, fname) \ ++static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \ ++ DisasContext *ctx) \ ++{ \ ++ TCGv t0 = tcg_temp_new(); \ ++ tcg_gen_mov_tl(t0, arg1); \ ++ tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \ ++ tcg_gen_st_tl(t0, cpu_env, \ ++ offsetof(CPULOONGARCHState, lladdr)); \ ++ tcg_gen_st_tl(ret, cpu_env, \ ++ offsetof(CPULOONGARCHState, llval)); \ ++ tcg_temp_free(t0); \ ++} ++#else ++#define OP_LD_ATOMIC(insn, fname) \ ++static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \ ++ DisasContext *ctx) \ ++{ \ ++ gen_helper_1e1i(insn, ret, arg1, mem_idx); \ ++} ++#endif ++#if 0 ++OP_LD_ATOMIC(ll, ld32s); ++OP_LD_ATOMIC(lld, ld64); ++#endif ++#undef OP_LD_ATOMIC ++ ++static void gen_base_offset_addr(DisasContext *ctx, TCGv addr, ++ int base, int offset) ++{ ++ if (base == 0) { ++ tcg_gen_movi_tl(addr, offset); ++ } else if (offset == 0) { ++ gen_load_gpr(addr, base); ++ } else { ++ tcg_gen_movi_tl(addr, offset); ++ gen_op_addr_add(ctx, addr, cpu_gpr[base], addr); ++ } ++} ++ ++/* Load */ ++static void gen_ld(DisasContext *ctx, uint32_t opc, ++ int rt, int base, int offset) ++{ ++ TCGv t0; ++ int mem_idx = ctx->mem_idx; ++ ++ t0 = tcg_temp_new(); ++ gen_base_offset_addr(ctx, t0, base, offset); ++ ++ switch (opc) { ++ case OPC_LARCH_LD_WU: ++ tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL | ++ ctx->default_tcg_memop_mask); ++ gen_store_gpr(t0, rt); ++ break; ++ case OPC_LARCH_LDPTR_D: ++ case OPC_LARCH_LD_D: ++ tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ | ++ ctx->default_tcg_memop_mask); ++ gen_store_gpr(t0, rt); ++ break; ++ case OPC_LARCH_LL_D: ++#if 0 ++ op_ld_lld(t0, t0, mem_idx, ctx); ++#endif ++ gen_store_gpr(t0, rt); ++ break; ++ case OPC_LARCH_LDPTR_W: ++ case OPC_LARCH_LD_W: ++ tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL | ++ ctx->default_tcg_memop_mask); ++ gen_store_gpr(t0, rt); ++ break; ++ case OPC_LARCH_LD_H: ++ tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESW | ++ ctx->default_tcg_memop_mask); ++ gen_store_gpr(t0, rt); ++ break; ++ case OPC_LARCH_LD_HU: ++ tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUW | ++ ctx->default_tcg_memop_mask); ++ gen_store_gpr(t0, rt); ++ break; ++ case OPC_LARCH_LD_B: ++ tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_SB); ++ gen_store_gpr(t0, rt); ++ break; ++ case OPC_LARCH_LD_BU: ++ tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_UB); ++ gen_store_gpr(t0, rt); ++ break; ++ case OPC_LARCH_LL_W: ++#if 0 ++ op_ld_ll(t0, t0, mem_idx, ctx); ++#endif ++ gen_store_gpr(t0, rt); ++ break; ++ } ++ ++ tcg_temp_free(t0); ++} ++ ++/* Store */ ++static void gen_st(DisasContext *ctx, uint32_t opc, int rt, ++ int base, int offset) ++{ ++ TCGv t0 = tcg_temp_new(); ++ TCGv t1 = tcg_temp_new(); ++ int mem_idx = ctx->mem_idx; ++ ++ gen_base_offset_addr(ctx, t0, base, offset); ++ gen_load_gpr(t1, rt); ++ ++ switch (opc) { ++ case OPC_LARCH_STPTR_D: ++ case OPC_LARCH_ST_D: ++ tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEQ | ++ ctx->default_tcg_memop_mask); ++ break; ++ case OPC_LARCH_STPTR_W: ++ case OPC_LARCH_ST_W: ++ tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUL | ++ ctx->default_tcg_memop_mask); ++ break; ++ case OPC_LARCH_ST_H: ++ tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUW | ++ ctx->default_tcg_memop_mask); ++ break; ++ case OPC_LARCH_ST_B: ++ tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_8); ++ break; ++ } ++ tcg_temp_free(t0); ++ tcg_temp_free(t1); ++} ++ ++/* Store conditional */ ++static void gen_st_cond(DisasContext *ctx, int rt, int base, int offset, ++ MemOp tcg_mo, bool eva) ++{ ++ TCGv addr, t0, val; ++ TCGLabel *l1 = gen_new_label(); ++ TCGLabel *done = gen_new_label(); ++ ++ t0 = tcg_temp_new(); ++ addr = tcg_temp_new(); ++ /* compare the address against that of the preceeding LL */ ++ gen_base_offset_addr(ctx, addr, base, offset); ++ tcg_gen_brcond_tl(TCG_COND_EQ, addr, cpu_lladdr, l1); ++ tcg_temp_free(addr); ++ tcg_gen_movi_tl(t0, 0); ++ gen_store_gpr(t0, rt); ++ tcg_gen_br(done); ++ ++ gen_set_label(l1); ++ /* generate cmpxchg */ ++ val = tcg_temp_new(); ++ gen_load_gpr(val, rt); ++ tcg_gen_atomic_cmpxchg_tl(t0, cpu_lladdr, cpu_llval, val, ++ eva ? LARCH_HFLAG_UM : ctx->mem_idx, tcg_mo); ++ tcg_gen_setcond_tl(TCG_COND_EQ, t0, t0, cpu_llval); ++ gen_store_gpr(t0, rt); ++ tcg_temp_free(val); ++ ++ gen_set_label(done); ++ tcg_temp_free(t0); ++} ++ ++/* Load and store */ ++static void gen_flt_ldst(DisasContext *ctx, uint32_t opc, int ft, ++ TCGv t0) ++{ ++ /* Don't do NOP if destination is zero: we must perform the actual ++ memory access. */ ++ switch (opc) { ++ case OPC_LARCH_FLD_S: ++ { ++ TCGv_i32 fp0 = tcg_temp_new_i32(); ++ tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL | ++ ctx->default_tcg_memop_mask); ++ gen_store_fpr32(ctx, fp0, ft); ++ tcg_temp_free_i32(fp0); ++ } ++ break; ++ case OPC_LARCH_FST_S: ++ { ++ TCGv_i32 fp0 = tcg_temp_new_i32(); ++ gen_load_fpr32(ctx, fp0, ft); ++ tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL | ++ ctx->default_tcg_memop_mask); ++ tcg_temp_free_i32(fp0); ++ } ++ break; ++ case OPC_LARCH_FLD_D: ++ { ++ TCGv_i64 fp0 = tcg_temp_new_i64(); ++ tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ | ++ ctx->default_tcg_memop_mask); ++ gen_store_fpr64(ctx, fp0, ft); ++ tcg_temp_free_i64(fp0); ++ } ++ break; ++ case OPC_LARCH_FST_D: ++ { ++ TCGv_i64 fp0 = tcg_temp_new_i64(); ++ gen_load_fpr64(ctx, fp0, ft); ++ tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ | ++ ctx->default_tcg_memop_mask); ++ tcg_temp_free_i64(fp0); ++ } ++ break; ++ default: ++ LARCH_INVAL("flt_ldst"); ++ generate_exception_end(ctx, EXCP_RI); ++ break; ++ } ++} ++ ++static void gen_fp_ldst(DisasContext *ctx, uint32_t op, int rt, ++ int rs, int16_t imm) ++{ ++ TCGv t0 = tcg_temp_new(); ++ ++ check_cp1_enabled(ctx); ++ gen_base_offset_addr(ctx, t0, rs, imm); ++ gen_flt_ldst(ctx, op, rt, t0); ++ tcg_temp_free(t0); ++} ++ ++/* Arithmetic with immediate operand */ ++static void gen_arith_imm(DisasContext *ctx, uint32_t opc, ++ int rt, int rs, int imm) ++{ ++ target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */ ++ ++ if (rt == 0) { ++ /* If no destination, treat it as a NOP. ++ For addi, we must generate the overflow exception when needed. */ ++ return; ++ } ++ switch (opc) { ++ case OPC_LARCH_ADDI_W: ++ if (rs != 0) { ++ tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm); ++ tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]); ++ } else { ++ tcg_gen_movi_tl(cpu_gpr[rt], uimm); ++ } ++ break; ++ case OPC_LARCH_ADDI_D: ++ if (rs != 0) { ++ tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm); ++ } else { ++ tcg_gen_movi_tl(cpu_gpr[rt], uimm); ++ } ++ break; ++ } ++} ++ ++/* Logic with immediate operand */ ++static void gen_logic_imm(DisasContext *ctx, uint32_t opc, ++ int rt, int rs, int16_t imm) ++{ ++ target_ulong uimm; ++ ++ if (rt == 0) { ++ /* If no destination, treat it as a NOP. */ ++ return; ++ } ++ uimm = (uint16_t)imm; ++ switch (opc) { ++ case OPC_LARCH_ANDI: ++ if (likely(rs != 0)) { ++ tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm); ++ } else { ++ tcg_gen_movi_tl(cpu_gpr[rt], 0); ++ } ++ break; ++ case OPC_LARCH_ORI: ++ if (rs != 0) { ++ tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm); ++ } else { ++ tcg_gen_movi_tl(cpu_gpr[rt], uimm); ++ } ++ break; ++ case OPC_LARCH_XORI: ++ if (likely(rs != 0)) { ++ tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm); ++ } else { ++ tcg_gen_movi_tl(cpu_gpr[rt], uimm); ++ } ++ break; ++ default: ++ break; ++ } ++} ++ ++/* Set on less than with immediate operand */ ++static void gen_slt_imm(DisasContext *ctx, uint32_t opc, ++ int rt, int rs, int16_t imm) ++{ ++ target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */ ++ TCGv t0; ++ ++ if (rt == 0) { ++ /* If no destination, treat it as a NOP. */ ++ return; ++ } ++ t0 = tcg_temp_new(); ++ gen_load_gpr(t0, rs); ++ switch (opc) { ++ case OPC_LARCH_SLTI: ++ tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm); ++ break; ++ case OPC_LARCH_SLTIU: ++ tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm); ++ break; ++ } ++ tcg_temp_free(t0); ++} ++ ++/* Shifts with immediate operand */ ++static void gen_shift_imm(DisasContext *ctx, uint32_t opc, ++ int rt, int rs, int16_t imm) ++{ ++ target_ulong uimm = ((uint16_t)imm) & 0x1f; ++ TCGv t0; ++ ++ if (rt == 0) { ++ /* If no destination, treat it as a NOP. */ ++ return; ++ } ++ ++ t0 = tcg_temp_new(); ++ gen_load_gpr(t0, rs); ++ switch (opc) { ++ case OPC_LARCH_SRAI_W: ++ tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm); ++ break; ++ case OPC_LARCH_SRLI_W: ++ if (uimm != 0) { ++ tcg_gen_ext32u_tl(t0, t0); ++ tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm); ++ } else { ++ tcg_gen_ext32s_tl(cpu_gpr[rt], t0); ++ } ++ break; ++ case OPC_LARCH_ROTRI_W: ++ if (uimm != 0) { ++ TCGv_i32 t1 = tcg_temp_new_i32(); ++ ++ tcg_gen_trunc_tl_i32(t1, t0); ++ tcg_gen_rotri_i32(t1, t1, uimm); ++ tcg_gen_ext_i32_tl(cpu_gpr[rt], t1); ++ tcg_temp_free_i32(t1); ++ } else { ++ tcg_gen_ext32s_tl(cpu_gpr[rt], t0); ++ } ++ break; ++ } ++ tcg_temp_free(t0); ++} ++ ++/* Arithmetic */ ++static void gen_arith(DisasContext *ctx, uint32_t opc, ++ int rd, int rs, int rt) ++{ ++ if (rd == 0) { ++ /* If no destination, treat it as a NOP. ++ For add & sub, we must generate the ++ overflow exception when needed. */ ++ return; ++ } ++ ++ switch (opc) { ++ case OPC_LARCH_ADD_W: ++ if (rs != 0 && rt != 0) { ++ tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]); ++ tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]); ++ } else if (rs == 0 && rt != 0) { ++ tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]); ++ } else if (rs != 0 && rt == 0) { ++ tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]); ++ } else { ++ tcg_gen_movi_tl(cpu_gpr[rd], 0); ++ } ++ break; ++ case OPC_LARCH_SUB_W: ++ if (rs != 0 && rt != 0) { ++ tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]); ++ tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]); ++ } else if (rs == 0 && rt != 0) { ++ tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]); ++ tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]); ++ } else if (rs != 0 && rt == 0) { ++ tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]); ++ } else { ++ tcg_gen_movi_tl(cpu_gpr[rd], 0); ++ } ++ break; ++ case OPC_LARCH_ADD_D: ++ if (rs != 0 && rt != 0) { ++ tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]); ++ } else if (rs == 0 && rt != 0) { ++ tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]); ++ } else if (rs != 0 && rt == 0) { ++ tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]); ++ } else { ++ tcg_gen_movi_tl(cpu_gpr[rd], 0); ++ } ++ break; ++ case OPC_LARCH_SUB_D: ++ if (rs != 0 && rt != 0) { ++ tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]); ++ } else if (rs == 0 && rt != 0) { ++ tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]); ++ } else if (rs != 0 && rt == 0) { ++ tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]); ++ } else { ++ tcg_gen_movi_tl(cpu_gpr[rd], 0); ++ } ++ break; ++ } ++} ++ ++/* Conditional move */ ++static void gen_cond_move(DisasContext *ctx, uint32_t opc, ++ int rd, int rs, int rt) ++{ ++ TCGv t0, t1, t2; ++ ++ if (rd == 0) { ++ /* If no destination, treat it as a NOP. */ ++ return; ++ } ++ ++ t0 = tcg_temp_new(); ++ gen_load_gpr(t0, rt); ++ t1 = tcg_const_tl(0); ++ t2 = tcg_temp_new(); ++ gen_load_gpr(t2, rs); ++ switch (opc) { ++ case OPC_LARCH_MASKEQZ: ++ tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1); ++ break; ++ case OPC_LARCH_MASKNEZ: ++ tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1); ++ break; ++ } ++ tcg_temp_free(t2); ++ tcg_temp_free(t1); ++ tcg_temp_free(t0); ++} ++ ++/* Logic */ ++static void gen_logic(DisasContext *ctx, uint32_t opc, ++ int rd, int rs, int rt) ++{ ++ if (rd == 0) { ++ /* If no destination, treat it as a NOP. */ ++ return; ++ } ++ ++ switch (opc) { ++ case OPC_LARCH_AND: ++ if (likely(rs != 0 && rt != 0)) { ++ tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]); ++ } else { ++ tcg_gen_movi_tl(cpu_gpr[rd], 0); ++ } ++ break; ++ case OPC_LARCH_NOR: ++ if (rs != 0 && rt != 0) { ++ tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]); ++ } else if (rs == 0 && rt != 0) { ++ tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]); ++ } else if (rs != 0 && rt == 0) { ++ tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]); ++ } else { ++ tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0)); ++ } ++ break; ++ case OPC_LARCH_OR: ++ if (likely(rs != 0 && rt != 0)) { ++ tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]); ++ } else if (rs == 0 && rt != 0) { ++ tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]); ++ } else if (rs != 0 && rt == 0) { ++ tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]); ++ } else { ++ tcg_gen_movi_tl(cpu_gpr[rd], 0); ++ } ++ break; ++ case OPC_LARCH_XOR: ++ if (likely(rs != 0 && rt != 0)) { ++ tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]); ++ } else if (rs == 0 && rt != 0) { ++ tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]); ++ } else if (rs != 0 && rt == 0) { ++ tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]); ++ } else { ++ tcg_gen_movi_tl(cpu_gpr[rd], 0); ++ } ++ break; ++ } ++} ++ ++/* Set on lower than */ ++static void gen_slt(DisasContext *ctx, uint32_t opc, ++ int rd, int rs, int rt) ++{ ++ TCGv t0, t1; ++ ++ if (rd == 0) { ++ /* If no destination, treat it as a NOP. */ ++ return; ++ } ++ ++ t0 = tcg_temp_new(); ++ t1 = tcg_temp_new(); ++ gen_load_gpr(t0, rs); ++ gen_load_gpr(t1, rt); ++ switch (opc) { ++ case OPC_LARCH_SLT: ++ tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1); ++ break; ++ case OPC_LARCH_SLTU: ++ tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1); ++ break; ++ } ++ tcg_temp_free(t0); ++ tcg_temp_free(t1); ++} ++ ++/* Shifts */ ++static void gen_shift(DisasContext *ctx, uint32_t opc, ++ int rd, int rs, int rt) ++{ ++ TCGv t0, t1; ++ ++ if (rd == 0) { ++ /* If no destination, treat it as a NOP. ++ For add & sub, we must generate the ++ overflow exception when needed. */ ++ return; ++ } ++ ++ t0 = tcg_temp_new(); ++ t1 = tcg_temp_new(); ++ gen_load_gpr(t0, rs); ++ gen_load_gpr(t1, rt); ++ switch (opc) { ++ case OPC_LARCH_SLL_W: ++ tcg_gen_andi_tl(t0, t0, 0x1f); ++ tcg_gen_shl_tl(t0, t1, t0); ++ tcg_gen_ext32s_tl(cpu_gpr[rd], t0); ++ break; ++ case OPC_LARCH_SRA_W: ++ tcg_gen_andi_tl(t0, t0, 0x1f); ++ tcg_gen_sar_tl(cpu_gpr[rd], t1, t0); ++ break; ++ case OPC_LARCH_SRL_W: ++ tcg_gen_ext32u_tl(t1, t1); ++ tcg_gen_andi_tl(t0, t0, 0x1f); ++ tcg_gen_shr_tl(t0, t1, t0); ++ tcg_gen_ext32s_tl(cpu_gpr[rd], t0); ++ break; ++ case OPC_LARCH_ROTR_W: ++ { ++ TCGv_i32 t2 = tcg_temp_new_i32(); ++ TCGv_i32 t3 = tcg_temp_new_i32(); ++ ++ tcg_gen_trunc_tl_i32(t2, t0); ++ tcg_gen_trunc_tl_i32(t3, t1); ++ tcg_gen_andi_i32(t2, t2, 0x1f); ++ tcg_gen_rotr_i32(t2, t3, t2); ++ tcg_gen_ext_i32_tl(cpu_gpr[rd], t2); ++ tcg_temp_free_i32(t2); ++ tcg_temp_free_i32(t3); ++ } ++ break; ++ case OPC_LARCH_SLL_D: ++ tcg_gen_andi_tl(t0, t0, 0x3f); ++ tcg_gen_shl_tl(cpu_gpr[rd], t1, t0); ++ break; ++ case OPC_LARCH_SRA_D: ++ tcg_gen_andi_tl(t0, t0, 0x3f); ++ tcg_gen_sar_tl(cpu_gpr[rd], t1, t0); ++ break; ++ case OPC_LARCH_SRL_D: ++ tcg_gen_andi_tl(t0, t0, 0x3f); ++ tcg_gen_shr_tl(cpu_gpr[rd], t1, t0); ++ break; ++ case OPC_LARCH_ROTR_D: ++ tcg_gen_andi_tl(t0, t0, 0x3f); ++ tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0); ++ break; ++ } ++ tcg_temp_free(t0); ++ tcg_temp_free(t1); ++} ++ ++static inline void gen_r6_ld(target_long addr, int reg, int memidx, ++ MemOp memop) ++{ ++ TCGv t0 = tcg_const_tl(addr); ++ tcg_gen_qemu_ld_tl(t0, t0, memidx, memop); ++ gen_store_gpr(t0, reg); ++ tcg_temp_free(t0); ++} ++ ++static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt) ++{ ++ TCGv t0, t1; ++ ++ if (rd == 0) { ++ /* Treat as NOP. */ ++ return; ++ } ++ ++ t0 = tcg_temp_new(); ++ t1 = tcg_temp_new(); ++ ++ gen_load_gpr(t0, rs); ++ gen_load_gpr(t1, rt); ++ ++ switch (opc) { ++ case OPC_LARCH_DIV_W: ++ { ++ TCGv t2 = tcg_temp_new(); ++ TCGv t3 = tcg_temp_new(); ++ tcg_gen_ext32s_tl(t0, t0); ++ tcg_gen_ext32s_tl(t1, t1); ++ tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN); ++ tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1); ++ tcg_gen_and_tl(t2, t2, t3); ++ tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0); ++ tcg_gen_or_tl(t2, t2, t3); ++ tcg_gen_movi_tl(t3, 0); ++ tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1); ++ tcg_gen_div_tl(cpu_gpr[rd], t0, t1); ++ tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]); ++ tcg_temp_free(t3); ++ tcg_temp_free(t2); ++ } ++ break; ++ case OPC_LARCH_MOD_W: ++ { ++ TCGv t2 = tcg_temp_new(); ++ TCGv t3 = tcg_temp_new(); ++ tcg_gen_ext32s_tl(t0, t0); ++ tcg_gen_ext32s_tl(t1, t1); ++ tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN); ++ tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1); ++ tcg_gen_and_tl(t2, t2, t3); ++ tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0); ++ tcg_gen_or_tl(t2, t2, t3); ++ tcg_gen_movi_tl(t3, 0); ++ tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1); ++ tcg_gen_rem_tl(cpu_gpr[rd], t0, t1); ++ tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]); ++ tcg_temp_free(t3); ++ tcg_temp_free(t2); ++ } ++ break; ++ case OPC_LARCH_DIV_WU: ++ { ++ TCGv t2 = tcg_const_tl(0); ++ TCGv t3 = tcg_const_tl(1); ++ tcg_gen_ext32u_tl(t0, t0); ++ tcg_gen_ext32u_tl(t1, t1); ++ tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1); ++ tcg_gen_divu_tl(cpu_gpr[rd], t0, t1); ++ tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]); ++ tcg_temp_free(t3); ++ tcg_temp_free(t2); ++ } ++ break; ++ case OPC_LARCH_MOD_WU: ++ { ++ TCGv t2 = tcg_const_tl(0); ++ TCGv t3 = tcg_const_tl(1); ++ tcg_gen_ext32u_tl(t0, t0); ++ tcg_gen_ext32u_tl(t1, t1); ++ tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1); ++ tcg_gen_remu_tl(cpu_gpr[rd], t0, t1); ++ tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]); ++ tcg_temp_free(t3); ++ tcg_temp_free(t2); ++ } ++ break; ++ case OPC_LARCH_MUL_W: ++ { ++ TCGv_i32 t2 = tcg_temp_new_i32(); ++ TCGv_i32 t3 = tcg_temp_new_i32(); ++ tcg_gen_trunc_tl_i32(t2, t0); ++ tcg_gen_trunc_tl_i32(t3, t1); ++ tcg_gen_mul_i32(t2, t2, t3); ++ tcg_gen_ext_i32_tl(cpu_gpr[rd], t2); ++ tcg_temp_free_i32(t2); ++ tcg_temp_free_i32(t3); ++ } ++ break; ++ case OPC_LARCH_MULH_W: ++ { ++ TCGv_i32 t2 = tcg_temp_new_i32(); ++ TCGv_i32 t3 = tcg_temp_new_i32(); ++ tcg_gen_trunc_tl_i32(t2, t0); ++ tcg_gen_trunc_tl_i32(t3, t1); ++ tcg_gen_muls2_i32(t2, t3, t2, t3); ++ tcg_gen_ext_i32_tl(cpu_gpr[rd], t3); ++ tcg_temp_free_i32(t2); ++ tcg_temp_free_i32(t3); ++ } ++ break; ++ case OPC_LARCH_MULH_WU: ++ { ++ TCGv_i32 t2 = tcg_temp_new_i32(); ++ TCGv_i32 t3 = tcg_temp_new_i32(); ++ tcg_gen_trunc_tl_i32(t2, t0); ++ tcg_gen_trunc_tl_i32(t3, t1); ++ tcg_gen_mulu2_i32(t2, t3, t2, t3); ++ tcg_gen_ext_i32_tl(cpu_gpr[rd], t3); ++ tcg_temp_free_i32(t2); ++ tcg_temp_free_i32(t3); ++ } ++ break; ++ case OPC_LARCH_DIV_D: ++ { ++ TCGv t2 = tcg_temp_new(); ++ TCGv t3 = tcg_temp_new(); ++ tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63); ++ tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL); ++ tcg_gen_and_tl(t2, t2, t3); ++ tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0); ++ tcg_gen_or_tl(t2, t2, t3); ++ tcg_gen_movi_tl(t3, 0); ++ tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1); ++ tcg_gen_div_tl(cpu_gpr[rd], t0, t1); ++ tcg_temp_free(t3); ++ tcg_temp_free(t2); ++ } ++ break; ++ case OPC_LARCH_MOD_D: ++ { ++ TCGv t2 = tcg_temp_new(); ++ TCGv t3 = tcg_temp_new(); ++ tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63); ++ tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL); ++ tcg_gen_and_tl(t2, t2, t3); ++ tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0); ++ tcg_gen_or_tl(t2, t2, t3); ++ tcg_gen_movi_tl(t3, 0); ++ tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1); ++ tcg_gen_rem_tl(cpu_gpr[rd], t0, t1); ++ tcg_temp_free(t3); ++ tcg_temp_free(t2); ++ } ++ break; ++ case OPC_LARCH_DIV_DU: ++ { ++ TCGv t2 = tcg_const_tl(0); ++ TCGv t3 = tcg_const_tl(1); ++ tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1); ++ tcg_gen_divu_i64(cpu_gpr[rd], t0, t1); ++ tcg_temp_free(t3); ++ tcg_temp_free(t2); ++ } ++ break; ++ case OPC_LARCH_MOD_DU: ++ { ++ TCGv t2 = tcg_const_tl(0); ++ TCGv t3 = tcg_const_tl(1); ++ tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1); ++ tcg_gen_remu_i64(cpu_gpr[rd], t0, t1); ++ tcg_temp_free(t3); ++ tcg_temp_free(t2); ++ } ++ break; ++ case OPC_LARCH_MUL_D: ++ tcg_gen_mul_i64(cpu_gpr[rd], t0, t1); ++ break; ++ case OPC_LARCH_MULH_D: ++ { ++ TCGv t2 = tcg_temp_new(); ++ tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1); ++ tcg_temp_free(t2); ++ } ++ break; ++ case OPC_LARCH_MULH_DU: ++ { ++ TCGv t2 = tcg_temp_new(); ++ tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1); ++ tcg_temp_free(t2); ++ } ++ break; ++ default: ++ LARCH_INVAL("r6 mul/div"); ++ generate_exception_end(ctx, EXCP_RI); ++ goto out; ++ } ++ out: ++ tcg_temp_free(t0); ++ tcg_temp_free(t1); ++} ++ ++static void gen_cl(DisasContext *ctx, uint32_t opc, ++ int rd, int rs) ++{ ++ TCGv t0; ++ ++ if (rd == 0) { ++ /* Treat as NOP. */ ++ return; ++ } ++ t0 = cpu_gpr[rd]; ++ gen_load_gpr(t0, rs); ++ ++ switch (opc) { ++ case OPC_LARCH_CLO_W: ++ case OPC_LARCH_CLO_D: ++ tcg_gen_not_tl(t0, t0); ++ break; ++ } ++ ++ switch (opc) { ++ case OPC_LARCH_CLO_W: ++ case OPC_LARCH_CLZ_W: ++ tcg_gen_ext32u_tl(t0, t0); ++ tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS); ++ tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32); ++ break; ++ case OPC_LARCH_CLO_D: ++ case OPC_LARCH_CLZ_D: ++ tcg_gen_clzi_i64(t0, t0, 64); ++ break; ++ } ++} ++ ++static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest) ++{ ++ if (unlikely(ctx->base.singlestep_enabled)) { ++ return false; ++ } ++ ++#ifndef CONFIG_USER_ONLY ++ return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK); ++#else ++ return true; ++#endif ++} ++ ++static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest) ++{ ++ if (use_goto_tb(ctx, dest)) { ++ tcg_gen_goto_tb(n); ++ gen_save_pc(dest); ++ tcg_gen_exit_tb(ctx->base.tb, n); ++ } else { ++ gen_save_pc(dest); ++ if (ctx->base.singlestep_enabled) { ++ save_cpu_state(ctx, 0); ++ gen_helper_raise_exception_debug(cpu_env); ++ } ++ tcg_gen_lookup_and_goto_ptr(); ++ } ++} ++ ++/* Branches */ ++static void gen_compute_branch(DisasContext *ctx, uint32_t opc, ++ int insn_bytes, ++ int rs, int rt, int32_t offset) ++{ ++ target_ulong btgt = -1; ++ int bcond_compute = 0; ++ TCGv t0 = tcg_temp_new(); ++ TCGv t1 = tcg_temp_new(); ++ ++ if (ctx->hflags & LARCH_HFLAG_BMASK) { ++#ifdef LARCH_DEBUG_DISAS ++ LOG_DISAS("Branch at PC 0x" ++ TARGET_FMT_lx "\n", ctx->base.pc_next); ++#endif ++ generate_exception_end(ctx, EXCP_RI); ++ goto out; ++ } ++ ++ /* Load needed operands */ ++ switch (opc) { ++ case OPC_LARCH_BLT: ++ case OPC_LARCH_BGE: ++ case OPC_LARCH_BLTU: ++ case OPC_LARCH_BGEU: ++ gen_load_gpr(t0, rs); ++ gen_load_gpr(t1, rt); ++ bcond_compute = 1; ++ btgt = ctx->base.pc_next + offset; ++ break; ++ case OPC_LARCH_BEQZ: ++ case OPC_LARCH_B: ++ case OPC_LARCH_BEQ: ++ case OPC_LARCH_BNEZ: ++ case OPC_LARCH_BNE: ++ /* Compare two registers */ ++ if (rs != rt) { ++ gen_load_gpr(t0, rs); ++ gen_load_gpr(t1, rt); ++ bcond_compute = 1; ++ } ++ btgt = ctx->base.pc_next + offset; ++ break; ++ default: ++ LARCH_INVAL("branch/jump"); ++ generate_exception_end(ctx, EXCP_RI); ++ goto out; ++ } ++ if (bcond_compute == 0) { ++ /* No condition to be computed */ ++ switch (opc) { ++ case OPC_LARCH_BEQZ: /* rx == rx */ ++ case OPC_LARCH_B: ++ case OPC_LARCH_BEQ: ++ /* Always take */ ++ ctx->hflags |= LARCH_HFLAG_B; ++ break; ++ case OPC_LARCH_BNEZ: ++ case OPC_LARCH_BNE: ++ /* Treat as NOP. */ ++ goto out; ++ default: ++ LARCH_INVAL("branch/jump"); ++ generate_exception_end(ctx, EXCP_RI); ++ goto out; ++ } ++ } else { ++ switch (opc) { ++ case OPC_LARCH_BLT: ++ tcg_gen_setcond_tl(TCG_COND_LT, bcond, t0, t1); ++ goto not_likely; ++ case OPC_LARCH_BGE: ++ tcg_gen_setcond_tl(TCG_COND_GE, bcond, t0, t1); ++ goto not_likely; ++ case OPC_LARCH_BLTU: ++ tcg_gen_setcond_tl(TCG_COND_LTU, bcond, t0, t1); ++ goto not_likely; ++ case OPC_LARCH_BGEU: ++ tcg_gen_setcond_tl(TCG_COND_GEU, bcond, t0, t1); ++ goto not_likely; ++ case OPC_LARCH_BEQZ: ++ case OPC_LARCH_B: ++ case OPC_LARCH_BEQ: ++ tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1); ++ goto not_likely; ++ case OPC_LARCH_BNEZ: ++ case OPC_LARCH_BNE: ++ tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1); ++ goto not_likely; ++ not_likely: ++ ctx->hflags |= LARCH_HFLAG_BC; ++ break; ++ default: ++ LARCH_INVAL("conditional branch/jump"); ++ generate_exception_end(ctx, EXCP_RI); ++ goto out; ++ } ++ } ++ ++ ctx->btarget = btgt; ++ ++ out: ++ tcg_temp_free(t0); ++ tcg_temp_free(t1); ++} ++ ++/* special3 bitfield operations */ ++static void gen_bitops(DisasContext *ctx, uint32_t opc, int rt, ++ int rs, int lsb, int msb) ++{ ++ TCGv t0 = tcg_temp_new(); ++ TCGv t1 = tcg_temp_new(); ++ ++ gen_load_gpr(t1, rs); ++ switch (opc) { ++ case OPC_LARCH_TRPICK_W: ++ if (lsb + msb > 31) { ++ goto fail; ++ } ++ if (msb != 31) { ++ tcg_gen_extract_tl(t0, t1, lsb, msb + 1); ++ } else { ++ /* ++ * The two checks together imply that lsb == 0, ++ * so this is a simple sign-extension. ++ */ ++ tcg_gen_ext32s_tl(t0, t1); ++ } ++ break; ++ case OPC_LARCH_TRINS_W: ++ if (lsb > msb) { ++ goto fail; ++ } ++ gen_load_gpr(t0, rt); ++ tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1); ++ tcg_gen_ext32s_tl(t0, t0); ++ break; ++ default: ++fail: ++ LARCH_INVAL("bitops"); ++ generate_exception_end(ctx, EXCP_RI); ++ tcg_temp_free(t0); ++ tcg_temp_free(t1); ++ return; ++ } ++ gen_store_gpr(t0, rt); ++ tcg_temp_free(t0); ++ tcg_temp_free(t1); ++} ++ ++static void gen_bshfl(DisasContext *ctx, uint32_t op2, int rt, int rd) ++{ ++ TCGv t0; ++ ++ if (rd == 0) { ++ /* If no destination, treat it as a NOP. */ ++ return; ++ } ++ ++ t0 = tcg_temp_new(); ++ gen_load_gpr(t0, rt); ++ switch (op2) { ++ case OPC_LARCH_REVB_2H: ++ { ++ TCGv t1 = tcg_temp_new(); ++ TCGv t2 = tcg_const_tl(0x00FF00FF); ++ ++ tcg_gen_shri_tl(t1, t0, 8); ++ tcg_gen_and_tl(t1, t1, t2); ++ tcg_gen_and_tl(t0, t0, t2); ++ tcg_gen_shli_tl(t0, t0, 8); ++ tcg_gen_or_tl(t0, t0, t1); ++ tcg_temp_free(t2); ++ tcg_temp_free(t1); ++ tcg_gen_ext32s_tl(cpu_gpr[rd], t0); ++ } ++ break; ++ case OPC_LARCH_EXT_WB: ++ tcg_gen_ext8s_tl(cpu_gpr[rd], t0); ++ break; ++ case OPC_LARCH_EXT_WH: ++ tcg_gen_ext16s_tl(cpu_gpr[rd], t0); ++ break; ++ case OPC_LARCH_REVB_4H: ++ { ++ TCGv t1 = tcg_temp_new(); ++ TCGv t2 = tcg_const_tl(0x00FF00FF00FF00FFULL); ++ ++ tcg_gen_shri_tl(t1, t0, 8); ++ tcg_gen_and_tl(t1, t1, t2); ++ tcg_gen_and_tl(t0, t0, t2); ++ tcg_gen_shli_tl(t0, t0, 8); ++ tcg_gen_or_tl(cpu_gpr[rd], t0, t1); ++ tcg_temp_free(t2); ++ tcg_temp_free(t1); ++ } ++ break; ++ case OPC_LARCH_REVH_D: ++ { ++ TCGv t1 = tcg_temp_new(); ++ TCGv t2 = tcg_const_tl(0x0000FFFF0000FFFFULL); ++ ++ tcg_gen_shri_tl(t1, t0, 16); ++ tcg_gen_and_tl(t1, t1, t2); ++ tcg_gen_and_tl(t0, t0, t2); ++ tcg_gen_shli_tl(t0, t0, 16); ++ tcg_gen_or_tl(t0, t0, t1); ++ tcg_gen_shri_tl(t1, t0, 32); ++ tcg_gen_shli_tl(t0, t0, 32); ++ tcg_gen_or_tl(cpu_gpr[rd], t0, t1); ++ tcg_temp_free(t2); ++ tcg_temp_free(t1); ++ } ++ break; ++ default: ++ LARCH_INVAL("bsfhl"); ++ generate_exception_end(ctx, EXCP_RI); ++ tcg_temp_free(t0); ++ return; ++ } ++ tcg_temp_free(t0); ++} ++ ++/* REV with sf==1, opcode==3 ("REV64") */ ++static void handle_rev64(DisasContext *ctx, ++ unsigned int rn, unsigned int rd) ++{ ++ tcg_gen_bswap64_i64(cpu_gpr[rd], cpu_gpr[rn]); ++} ++ ++/* REV with sf==0, opcode==2 ++ * REV32 (sf==1, opcode==2) ++ */ ++static void handle_rev32(DisasContext *ctx, ++ unsigned int rn, unsigned int rd) ++{ ++ TCGv_i64 tcg_rd = tcg_temp_new_i64(); ++ gen_load_gpr(tcg_rd, rd); ++ ++ TCGv_i64 tcg_tmp = tcg_temp_new_i64(); ++ TCGv_i64 tcg_rn = tcg_temp_new_i64(); ++ gen_load_gpr(tcg_rn, rn); ++ ++ /* bswap32_i64 requires zero high word */ ++ tcg_gen_ext32u_i64(tcg_tmp, tcg_rn); ++ tcg_gen_bswap32_i64(tcg_rd, tcg_tmp, TCG_BSWAP_OZ); ++ tcg_gen_shri_i64(tcg_tmp, tcg_rn, 32); ++ tcg_gen_bswap32_i64(tcg_tmp, tcg_tmp, TCG_BSWAP_OZ); ++ tcg_gen_concat32_i64(cpu_gpr[rd], tcg_rd, tcg_tmp); ++ ++ tcg_temp_free_i64(tcg_tmp); ++ tcg_temp_free_i64(tcg_rd); ++ tcg_temp_free_i64(tcg_rn); ++} ++ ++/* REV16 */ ++static void handle_rev16(DisasContext *ctx, unsigned int rn, unsigned int rd) ++{ ++ TCGv_i64 tcg_rd = tcg_temp_new_i64(); ++ TCGv_i64 tcg_rn = tcg_temp_new_i64(); ++ gen_load_gpr(tcg_rd, rd); ++ gen_load_gpr(tcg_rn, rn); ++ TCGv_i64 tcg_tmp = tcg_temp_new_i64(); ++ TCGv_i64 mask = tcg_const_i64(0x0000ffff0000ffffull); ++ ++ tcg_gen_shri_i64(tcg_tmp, tcg_rn, 16); ++ tcg_gen_and_i64(tcg_rd, tcg_rn, mask); ++ tcg_gen_and_i64(tcg_tmp, tcg_tmp, mask); ++ tcg_gen_shli_i64(tcg_rd, tcg_rd, 16); ++ tcg_gen_or_i64(cpu_gpr[rd], tcg_rd, tcg_tmp); ++ ++ tcg_temp_free_i64(mask); ++ tcg_temp_free_i64(tcg_tmp); ++ tcg_temp_free_i64(tcg_rd); ++ tcg_temp_free_i64(tcg_rn); ++} ++ ++static void gen_lsa(DisasContext *ctx, int opc, int rd, int rs, int rt, ++ int imm2) ++{ ++ TCGv t0; ++ TCGv t1; ++ if (rd == 0) { ++ /* Treat as NOP. */ ++ return; ++ } ++ t0 = tcg_temp_new(); ++ t1 = tcg_temp_new(); ++ gen_load_gpr(t0, rs); ++ gen_load_gpr(t1, rt); ++ tcg_gen_shli_tl(t0, t0, imm2 + 1); ++ tcg_gen_add_tl(cpu_gpr[rd], t0, t1); ++ if (opc == OPC_LARCH_ALSL_W) { ++ tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]); ++ } ++ ++ tcg_temp_free(t1); ++ tcg_temp_free(t0); ++ ++ return; ++} ++ ++static void gen_align_bits(DisasContext *ctx, int wordsz, int rd, int rs, ++ int rt, int bits) ++{ ++ TCGv t0; ++ if (rd == 0) { ++ /* Treat as NOP. */ ++ return; ++ } ++ t0 = tcg_temp_new(); ++ if (bits == 0 || bits == wordsz) { ++ if (bits == 0) { ++ gen_load_gpr(t0, rt); ++ } else { ++ gen_load_gpr(t0, rs); ++ } ++ switch (wordsz) { ++ case 32: ++ tcg_gen_ext32s_tl(cpu_gpr[rd], t0); ++ break; ++ case 64: ++ tcg_gen_mov_tl(cpu_gpr[rd], t0); ++ break; ++ } ++ } else { ++ TCGv t1 = tcg_temp_new(); ++ gen_load_gpr(t0, rt); ++ gen_load_gpr(t1, rs); ++ switch (wordsz) { ++ case 32: ++ { ++ TCGv_i64 t2 = tcg_temp_new_i64(); ++ tcg_gen_concat_tl_i64(t2, t1, t0); ++ tcg_gen_shri_i64(t2, t2, 32 - bits); ++ gen_move_low32(cpu_gpr[rd], t2); ++ tcg_temp_free_i64(t2); ++ } ++ break; ++ case 64: ++ tcg_gen_shli_tl(t0, t0, bits); ++ tcg_gen_shri_tl(t1, t1, 64 - bits); ++ tcg_gen_or_tl(cpu_gpr[rd], t1, t0); ++ break; ++ } ++ tcg_temp_free(t1); ++ } ++ ++ tcg_temp_free(t0); ++} ++ ++static void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt, ++ int bp) ++{ ++ gen_align_bits(ctx, wordsz, rd, rs, rt, bp * 8); ++} ++ ++static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt) ++{ ++ TCGv t0; ++ if (rd == 0) { ++ /* Treat as NOP. */ ++ return; ++ } ++ t0 = tcg_temp_new(); ++ gen_load_gpr(t0, rt); ++ switch (opc) { ++ case OPC_LARCH_BREV_4B: ++ gen_helper_bitswap(cpu_gpr[rd], t0); ++ break; ++ case OPC_LARCH_BREV_8B: ++ gen_helper_dbitswap(cpu_gpr[rd], t0); ++ break; ++ } ++ tcg_temp_free(t0); ++} ++ ++static void gen_cp1(DisasContext *ctx, uint32_t opc, int rt, int fs) ++{ ++ TCGv t0 = tcg_temp_new(); ++ check_cp1_enabled(ctx); ++ ++ switch (opc) { ++ case OPC_LARCH_FR2GR_S: ++ { ++ TCGv_i32 fp0 = tcg_temp_new_i32(); ++ ++ gen_load_fpr32(ctx, fp0, fs); ++ tcg_gen_ext_i32_tl(t0, fp0); ++ tcg_temp_free_i32(fp0); ++ } ++ gen_store_gpr(t0, rt); ++ break; ++ case OPC_LARCH_GR2FR_W: ++ gen_load_gpr(t0, rt); ++ { ++ TCGv_i32 fp0 = tcg_temp_new_i32(); ++ ++ tcg_gen_trunc_tl_i32(fp0, t0); ++ gen_store_fpr32(ctx, fp0, fs); ++ tcg_temp_free_i32(fp0); ++ } ++ break; ++ case OPC_LARCH_FR2GR_D: ++ gen_load_fpr64(ctx, t0, fs); ++ gen_store_gpr(t0, rt); ++ break; ++ case OPC_LARCH_GR2FR_D: ++ gen_load_gpr(t0, rt); ++ gen_store_fpr64(ctx, t0, fs); ++ break; ++ case OPC_LARCH_FRH2GR_S: ++ { ++ TCGv_i32 fp0 = tcg_temp_new_i32(); ++ ++ gen_load_fpr32h(ctx, fp0, fs); ++ tcg_gen_ext_i32_tl(t0, fp0); ++ tcg_temp_free_i32(fp0); ++ } ++ gen_store_gpr(t0, rt); ++ break; ++ case OPC_LARCH_GR2FRH_W: ++ gen_load_gpr(t0, rt); ++ { ++ TCGv_i32 fp0 = tcg_temp_new_i32(); ++ ++ tcg_gen_trunc_tl_i32(fp0, t0); ++ gen_store_fpr32h(ctx, fp0, fs); ++ tcg_temp_free_i32(fp0); ++ } ++ break; ++ default: ++ LARCH_INVAL("cp1 move"); ++ generate_exception_end(ctx, EXCP_RI); ++ goto out; ++ } ++ ++ out: ++ tcg_temp_free(t0); ++} ++ ++static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd, ++ int cc, int tf) ++{ ++ int cond; ++ TCGv_i32 t0 = tcg_temp_new_i32(); ++ TCGLabel *l1 = gen_new_label(); ++ TCGLabel *l2 = gen_new_label(); ++ ++ if (tf) { ++ cond = TCG_COND_EQ; ++ } else { ++ cond = TCG_COND_NE; ++ } ++ ++ tcg_gen_andi_i32(t0, fpu_fcsr0, 1 << get_fp_bit(cc)); ++ tcg_gen_brcondi_i32(cond, t0, 0, l1); ++ gen_load_fpr32(ctx, t0, fs); ++ gen_store_fpr32(ctx, t0, fd); ++ gen_set_label(l1); ++ ++ tcg_gen_andi_i32(t0, fpu_fcsr0, 1 << get_fp_bit(cc + 1)); ++ tcg_gen_brcondi_i32(cond, t0, 0, l2); ++ gen_load_fpr32h(ctx, t0, fs); ++ gen_store_fpr32h(ctx, t0, fd); ++ tcg_temp_free_i32(t0); ++ gen_set_label(l2); ++} ++ ++static void gen_farith(DisasContext *ctx, uint32_t opc, ++ int ft, int fs, int fd, int cc) ++{ ++ check_cp1_enabled(ctx); ++ switch (opc) { ++ case OPC_LARCH_FADD_S: ++ { ++ TCGv_i32 fp0 = tcg_temp_new_i32(); ++ TCGv_i32 fp1 = tcg_temp_new_i32(); ++ ++ gen_load_fpr32(ctx, fp0, fs); ++ gen_load_fpr32(ctx, fp1, ft); ++ gen_helper_float_add_s(fp0, cpu_env, fp0, fp1); ++ tcg_temp_free_i32(fp1); ++ gen_store_fpr32(ctx, fp0, fd); ++ tcg_temp_free_i32(fp0); ++ } ++ break; ++ case OPC_LARCH_FSUB_S: ++ { ++ TCGv_i32 fp0 = tcg_temp_new_i32(); ++ TCGv_i32 fp1 = tcg_temp_new_i32(); ++ ++ gen_load_fpr32(ctx, fp0, fs); ++ gen_load_fpr32(ctx, fp1, ft); ++ gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1); ++ tcg_temp_free_i32(fp1); ++ gen_store_fpr32(ctx, fp0, fd); ++ tcg_temp_free_i32(fp0); ++ } ++ break; ++ case OPC_LARCH_FMUL_S: ++ { ++ TCGv_i32 fp0 = tcg_temp_new_i32(); ++ TCGv_i32 fp1 = tcg_temp_new_i32(); ++ ++ gen_load_fpr32(ctx, fp0, fs); ++ gen_load_fpr32(ctx, fp1, ft); ++ gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1); ++ tcg_temp_free_i32(fp1); ++ gen_store_fpr32(ctx, fp0, fd); ++ tcg_temp_free_i32(fp0); ++ } ++ break; ++ case OPC_LARCH_FDIV_S: ++ { ++ TCGv_i32 fp0 = tcg_temp_new_i32(); ++ TCGv_i32 fp1 = tcg_temp_new_i32(); ++ ++ gen_load_fpr32(ctx, fp0, fs); ++ gen_load_fpr32(ctx, fp1, ft); ++ gen_helper_float_div_s(fp0, cpu_env, fp0, fp1); ++ tcg_temp_free_i32(fp1); ++ gen_store_fpr32(ctx, fp0, fd); ++ tcg_temp_free_i32(fp0); ++ } ++ break; ++ case OPC_LARCH_FSQRT_S: ++ { ++ TCGv_i32 fp0 = tcg_temp_new_i32(); ++ ++ gen_load_fpr32(ctx, fp0, fs); ++ gen_helper_float_sqrt_s(fp0, cpu_env, fp0); ++ gen_store_fpr32(ctx, fp0, fd); ++ tcg_temp_free_i32(fp0); ++ } ++ break; ++ case OPC_LARCH_FABS_S: ++ { ++ TCGv_i32 fp0 = tcg_temp_new_i32(); ++ ++ gen_load_fpr32(ctx, fp0, fs); ++ gen_helper_float_abs_s(fp0, fp0); ++ gen_store_fpr32(ctx, fp0, fd); ++ tcg_temp_free_i32(fp0); ++ } ++ break; ++ case OPC_LARCH_FMOV_S: ++ { ++ TCGv_i32 fp0 = tcg_temp_new_i32(); ++ ++ gen_load_fpr32(ctx, fp0, fs); ++ gen_store_fpr32(ctx, fp0, fd); ++ tcg_temp_free_i32(fp0); ++ } ++ break; ++ case OPC_LARCH_FNEG_S: ++ { ++ TCGv_i32 fp0 = tcg_temp_new_i32(); ++ ++ gen_load_fpr32(ctx, fp0, fs); ++ gen_helper_float_chs_s(fp0, fp0); ++ gen_store_fpr32(ctx, fp0, fd); ++ tcg_temp_free_i32(fp0); ++ } ++ break; ++ case OPC_LARCH_FTINTRNE_L_S: ++ { ++ TCGv_i32 fp32 = tcg_temp_new_i32(); ++ TCGv_i64 fp64 = tcg_temp_new_i64(); ++ ++ gen_load_fpr32(ctx, fp32, fs); ++ gen_helper_float_round_l_s(fp64, cpu_env, fp32); ++ tcg_temp_free_i32(fp32); ++ gen_store_fpr64(ctx, fp64, fd); ++ tcg_temp_free_i64(fp64); ++ } ++ break; ++ case OPC_LARCH_FTINTRZ_L_S: ++ { ++ TCGv_i32 fp32 = tcg_temp_new_i32(); ++ TCGv_i64 fp64 = tcg_temp_new_i64(); ++ ++ gen_load_fpr32(ctx, fp32, fs); ++ gen_helper_float_trunc_l_s(fp64, cpu_env, fp32); ++ tcg_temp_free_i32(fp32); ++ gen_store_fpr64(ctx, fp64, fd); ++ tcg_temp_free_i64(fp64); ++ } ++ break; ++ case OPC_LARCH_FTINTRP_L_S: ++ { ++ TCGv_i32 fp32 = tcg_temp_new_i32(); ++ TCGv_i64 fp64 = tcg_temp_new_i64(); ++ ++ gen_load_fpr32(ctx, fp32, fs); ++ gen_helper_float_ceil_l_s(fp64, cpu_env, fp32); ++ tcg_temp_free_i32(fp32); ++ gen_store_fpr64(ctx, fp64, fd); ++ tcg_temp_free_i64(fp64); ++ } ++ break; ++ case OPC_LARCH_FTINTRM_L_S: ++ { ++ TCGv_i32 fp32 = tcg_temp_new_i32(); ++ TCGv_i64 fp64 = tcg_temp_new_i64(); ++ ++ gen_load_fpr32(ctx, fp32, fs); ++ gen_helper_float_floor_l_s(fp64, cpu_env, fp32); ++ tcg_temp_free_i32(fp32); ++ gen_store_fpr64(ctx, fp64, fd); ++ tcg_temp_free_i64(fp64); ++ } ++ break; ++ case OPC_LARCH_FTINTRNE_W_S: ++ { ++ TCGv_i32 fp0 = tcg_temp_new_i32(); ++ ++ gen_load_fpr32(ctx, fp0, fs); ++ gen_helper_float_round_w_s(fp0, cpu_env, fp0); ++ gen_store_fpr32(ctx, fp0, fd); ++ tcg_temp_free_i32(fp0); ++ } ++ break; ++ case OPC_LARCH_FTINTRZ_W_S: ++ { ++ TCGv_i32 fp0 = tcg_temp_new_i32(); ++ ++ gen_load_fpr32(ctx, fp0, fs); ++ gen_helper_float_trunc_w_s(fp0, cpu_env, fp0); ++ gen_store_fpr32(ctx, fp0, fd); ++ tcg_temp_free_i32(fp0); ++ } ++ break; ++ case OPC_LARCH_FTINTRP_W_S: ++ { ++ TCGv_i32 fp0 = tcg_temp_new_i32(); ++ ++ gen_load_fpr32(ctx, fp0, fs); ++ gen_helper_float_ceil_w_s(fp0, cpu_env, fp0); ++ gen_store_fpr32(ctx, fp0, fd); ++ tcg_temp_free_i32(fp0); ++ } ++ break; ++ case OPC_LARCH_FTINTRM_W_S: ++ { ++ TCGv_i32 fp0 = tcg_temp_new_i32(); ++ ++ gen_load_fpr32(ctx, fp0, fs); ++ gen_helper_float_floor_w_s(fp0, cpu_env, fp0); ++ gen_store_fpr32(ctx, fp0, fd); ++ tcg_temp_free_i32(fp0); ++ } ++ break; ++ case OPC_LARCH_FRECIP_S: ++ { ++ TCGv_i32 fp0 = tcg_temp_new_i32(); ++ ++ gen_load_fpr32(ctx, fp0, fs); ++ gen_helper_float_recip_s(fp0, cpu_env, fp0); ++ gen_store_fpr32(ctx, fp0, fd); ++ tcg_temp_free_i32(fp0); ++ } ++ break; ++ case OPC_LARCH_FRSQRT_S: ++ { ++ TCGv_i32 fp0 = tcg_temp_new_i32(); ++ ++ gen_load_fpr32(ctx, fp0, fs); ++ gen_helper_float_rsqrt_s(fp0, cpu_env, fp0); ++ gen_store_fpr32(ctx, fp0, fd); ++ tcg_temp_free_i32(fp0); ++ } ++ break; ++ case OPC_LARCH_FRINT_S: ++ { ++ TCGv_i32 fp0 = tcg_temp_new_i32(); ++ gen_load_fpr32(ctx, fp0, fs); ++ gen_helper_float_rint_s(fp0, cpu_env, fp0); ++ gen_store_fpr32(ctx, fp0, fd); ++ tcg_temp_free_i32(fp0); ++ } ++ break; ++ case OPC_LARCH_FCLASS_S: ++ { ++ TCGv_i32 fp0 = tcg_temp_new_i32(); ++ gen_load_fpr32(ctx, fp0, fs); ++ gen_helper_float_class_s(fp0, cpu_env, fp0); ++ gen_store_fpr32(ctx, fp0, fd); ++ tcg_temp_free_i32(fp0); ++ } ++ break; ++ case OPC_LARCH_FMIN_S: ++ { ++ TCGv_i32 fp0 = tcg_temp_new_i32(); ++ TCGv_i32 fp1 = tcg_temp_new_i32(); ++ TCGv_i32 fp2 = tcg_temp_new_i32(); ++ gen_load_fpr32(ctx, fp0, fs); ++ gen_load_fpr32(ctx, fp1, ft); ++ gen_helper_float_min_s(fp2, cpu_env, fp0, fp1); ++ gen_store_fpr32(ctx, fp2, fd); ++ tcg_temp_free_i32(fp2); ++ tcg_temp_free_i32(fp1); ++ tcg_temp_free_i32(fp0); ++ } ++ break; ++ case OPC_LARCH_FMINA_S: ++ { ++ TCGv_i32 fp0 = tcg_temp_new_i32(); ++ TCGv_i32 fp1 = tcg_temp_new_i32(); ++ TCGv_i32 fp2 = tcg_temp_new_i32(); ++ gen_load_fpr32(ctx, fp0, fs); ++ gen_load_fpr32(ctx, fp1, ft); ++ gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1); ++ gen_store_fpr32(ctx, fp2, fd); ++ tcg_temp_free_i32(fp2); ++ tcg_temp_free_i32(fp1); ++ tcg_temp_free_i32(fp0); ++ } ++ break; ++ case OPC_LARCH_FMAX_S: ++ { ++ TCGv_i32 fp0 = tcg_temp_new_i32(); ++ TCGv_i32 fp1 = tcg_temp_new_i32(); ++ gen_load_fpr32(ctx, fp0, fs); ++ gen_load_fpr32(ctx, fp1, ft); ++ gen_helper_float_max_s(fp1, cpu_env, fp0, fp1); ++ gen_store_fpr32(ctx, fp1, fd); ++ tcg_temp_free_i32(fp1); ++ tcg_temp_free_i32(fp0); ++ } ++ break; ++ case OPC_LARCH_FMAXA_S: ++ { ++ TCGv_i32 fp0 = tcg_temp_new_i32(); ++ TCGv_i32 fp1 = tcg_temp_new_i32(); ++ gen_load_fpr32(ctx, fp0, fs); ++ gen_load_fpr32(ctx, fp1, ft); ++ gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1); ++ gen_store_fpr32(ctx, fp1, fd); ++ tcg_temp_free_i32(fp1); ++ tcg_temp_free_i32(fp0); ++ } ++ break; ++ case OPC_LARCH_FCVT_D_S: ++ { ++ TCGv_i32 fp32 = tcg_temp_new_i32(); ++ TCGv_i64 fp64 = tcg_temp_new_i64(); ++ ++ gen_load_fpr32(ctx, fp32, fs); ++ gen_helper_float_cvtd_s(fp64, cpu_env, fp32); ++ tcg_temp_free_i32(fp32); ++ gen_store_fpr64(ctx, fp64, fd); ++ tcg_temp_free_i64(fp64); ++ } ++ break; ++ case OPC_LARCH_FTINT_W_S: ++ { ++ TCGv_i32 fp0 = tcg_temp_new_i32(); ++ ++ gen_load_fpr32(ctx, fp0, fs); ++ gen_helper_float_cvt_w_s(fp0, cpu_env, fp0); ++ gen_store_fpr32(ctx, fp0, fd); ++ tcg_temp_free_i32(fp0); ++ } ++ break; ++ case OPC_LARCH_FTINT_L_S: ++ { ++ TCGv_i32 fp32 = tcg_temp_new_i32(); ++ TCGv_i64 fp64 = tcg_temp_new_i64(); ++ ++ gen_load_fpr32(ctx, fp32, fs); ++ gen_helper_float_cvt_l_s(fp64, cpu_env, fp32); ++ tcg_temp_free_i32(fp32); ++ gen_store_fpr64(ctx, fp64, fd); ++ tcg_temp_free_i64(fp64); ++ } ++ break; ++ case OPC_LARCH_FADD_D: ++ { ++ TCGv_i64 fp0 = tcg_temp_new_i64(); ++ TCGv_i64 fp1 = tcg_temp_new_i64(); ++ ++ gen_load_fpr64(ctx, fp0, fs); ++ gen_load_fpr64(ctx, fp1, ft); ++ gen_helper_float_add_d(fp0, cpu_env, fp0, fp1); ++ tcg_temp_free_i64(fp1); ++ gen_store_fpr64(ctx, fp0, fd); ++ tcg_temp_free_i64(fp0); ++ } ++ break; ++ case OPC_LARCH_FSUB_D: ++ { ++ TCGv_i64 fp0 = tcg_temp_new_i64(); ++ TCGv_i64 fp1 = tcg_temp_new_i64(); ++ ++ gen_load_fpr64(ctx, fp0, fs); ++ gen_load_fpr64(ctx, fp1, ft); ++ gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1); ++ tcg_temp_free_i64(fp1); ++ gen_store_fpr64(ctx, fp0, fd); ++ tcg_temp_free_i64(fp0); ++ } ++ break; ++ case OPC_LARCH_FMUL_D: ++ { ++ TCGv_i64 fp0 = tcg_temp_new_i64(); ++ TCGv_i64 fp1 = tcg_temp_new_i64(); ++ ++ gen_load_fpr64(ctx, fp0, fs); ++ gen_load_fpr64(ctx, fp1, ft); ++ gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1); ++ tcg_temp_free_i64(fp1); ++ gen_store_fpr64(ctx, fp0, fd); ++ tcg_temp_free_i64(fp0); ++ } ++ break; ++ case OPC_LARCH_FDIV_D: ++ { ++ TCGv_i64 fp0 = tcg_temp_new_i64(); ++ TCGv_i64 fp1 = tcg_temp_new_i64(); ++ ++ gen_load_fpr64(ctx, fp0, fs); ++ gen_load_fpr64(ctx, fp1, ft); ++ gen_helper_float_div_d(fp0, cpu_env, fp0, fp1); ++ tcg_temp_free_i64(fp1); ++ gen_store_fpr64(ctx, fp0, fd); ++ tcg_temp_free_i64(fp0); ++ } ++ break; ++ case OPC_LARCH_FSQRT_D: ++ { ++ TCGv_i64 fp0 = tcg_temp_new_i64(); ++ ++ gen_load_fpr64(ctx, fp0, fs); ++ gen_helper_float_sqrt_d(fp0, cpu_env, fp0); ++ gen_store_fpr64(ctx, fp0, fd); ++ tcg_temp_free_i64(fp0); ++ } ++ break; ++ case OPC_LARCH_FABS_D: ++ { ++ TCGv_i64 fp0 = tcg_temp_new_i64(); ++ ++ gen_load_fpr64(ctx, fp0, fs); ++ gen_helper_float_abs_d(fp0, fp0); ++ gen_store_fpr64(ctx, fp0, fd); ++ tcg_temp_free_i64(fp0); ++ } ++ break; ++ case OPC_LARCH_FMOV_D: ++ { ++ TCGv_i64 fp0 = tcg_temp_new_i64(); ++ ++ gen_load_fpr64(ctx, fp0, fs); ++ gen_store_fpr64(ctx, fp0, fd); ++ tcg_temp_free_i64(fp0); ++ } ++ break; ++ case OPC_LARCH_FNEG_D: ++ { ++ TCGv_i64 fp0 = tcg_temp_new_i64(); ++ ++ gen_load_fpr64(ctx, fp0, fs); ++ gen_helper_float_chs_d(fp0, fp0); ++ gen_store_fpr64(ctx, fp0, fd); ++ tcg_temp_free_i64(fp0); ++ } ++ break; ++ case OPC_LARCH_FTINTRNE_L_D: ++ { ++ TCGv_i64 fp0 = tcg_temp_new_i64(); ++ ++ gen_load_fpr64(ctx, fp0, fs); ++ gen_helper_float_round_l_d(fp0, cpu_env, fp0); ++ gen_store_fpr64(ctx, fp0, fd); ++ tcg_temp_free_i64(fp0); ++ } ++ break; ++ case OPC_LARCH_FTINTRZ_L_D: ++ { ++ TCGv_i64 fp0 = tcg_temp_new_i64(); ++ ++ gen_load_fpr64(ctx, fp0, fs); ++ gen_helper_float_trunc_l_d(fp0, cpu_env, fp0); ++ gen_store_fpr64(ctx, fp0, fd); ++ tcg_temp_free_i64(fp0); ++ } ++ break; ++ case OPC_LARCH_FTINTRP_L_D: ++ { ++ TCGv_i64 fp0 = tcg_temp_new_i64(); ++ ++ gen_load_fpr64(ctx, fp0, fs); ++ gen_helper_float_ceil_l_d(fp0, cpu_env, fp0); ++ gen_store_fpr64(ctx, fp0, fd); ++ tcg_temp_free_i64(fp0); ++ } ++ break; ++ case OPC_LARCH_FTINTRM_L_D: ++ { ++ TCGv_i64 fp0 = tcg_temp_new_i64(); ++ ++ gen_load_fpr64(ctx, fp0, fs); ++ gen_helper_float_floor_l_d(fp0, cpu_env, fp0); ++ gen_store_fpr64(ctx, fp0, fd); ++ tcg_temp_free_i64(fp0); ++ } ++ break; ++ case OPC_LARCH_FTINTRNE_W_D: ++ { ++ TCGv_i32 fp32 = tcg_temp_new_i32(); ++ TCGv_i64 fp64 = tcg_temp_new_i64(); ++ ++ gen_load_fpr64(ctx, fp64, fs); ++ gen_helper_float_round_w_d(fp32, cpu_env, fp64); ++ tcg_temp_free_i64(fp64); ++ gen_store_fpr32(ctx, fp32, fd); ++ tcg_temp_free_i32(fp32); ++ } ++ break; ++ case OPC_LARCH_FTINTRZ_W_D: ++ { ++ TCGv_i32 fp32 = tcg_temp_new_i32(); ++ TCGv_i64 fp64 = tcg_temp_new_i64(); ++ ++ gen_load_fpr64(ctx, fp64, fs); ++ gen_helper_float_trunc_w_d(fp32, cpu_env, fp64); ++ tcg_temp_free_i64(fp64); ++ gen_store_fpr32(ctx, fp32, fd); ++ tcg_temp_free_i32(fp32); ++ } ++ break; ++ case OPC_LARCH_FTINTRP_W_D: ++ { ++ TCGv_i32 fp32 = tcg_temp_new_i32(); ++ TCGv_i64 fp64 = tcg_temp_new_i64(); ++ ++ gen_load_fpr64(ctx, fp64, fs); ++ gen_helper_float_ceil_w_d(fp32, cpu_env, fp64); ++ tcg_temp_free_i64(fp64); ++ gen_store_fpr32(ctx, fp32, fd); ++ tcg_temp_free_i32(fp32); ++ } ++ break; ++ case OPC_LARCH_FTINTRM_W_D: ++ { ++ TCGv_i32 fp32 = tcg_temp_new_i32(); ++ TCGv_i64 fp64 = tcg_temp_new_i64(); ++ ++ gen_load_fpr64(ctx, fp64, fs); ++ gen_helper_float_floor_w_d(fp32, cpu_env, fp64); ++ tcg_temp_free_i64(fp64); ++ gen_store_fpr32(ctx, fp32, fd); ++ tcg_temp_free_i32(fp32); ++ } ++ break; ++ case OPC_LARCH_FRECIP_D: ++ { ++ TCGv_i64 fp0 = tcg_temp_new_i64(); ++ ++ gen_load_fpr64(ctx, fp0, fs); ++ gen_helper_float_recip_d(fp0, cpu_env, fp0); ++ gen_store_fpr64(ctx, fp0, fd); ++ tcg_temp_free_i64(fp0); ++ } ++ break; ++ case OPC_LARCH_FRSQRT_D: ++ { ++ TCGv_i64 fp0 = tcg_temp_new_i64(); ++ ++ gen_load_fpr64(ctx, fp0, fs); ++ gen_helper_float_rsqrt_d(fp0, cpu_env, fp0); ++ gen_store_fpr64(ctx, fp0, fd); ++ tcg_temp_free_i64(fp0); ++ } ++ break; ++ case OPC_LARCH_FRINT_D: ++ { ++ TCGv_i64 fp0 = tcg_temp_new_i64(); ++ gen_load_fpr64(ctx, fp0, fs); ++ gen_helper_float_rint_d(fp0, cpu_env, fp0); ++ gen_store_fpr64(ctx, fp0, fd); ++ tcg_temp_free_i64(fp0); ++ } ++ break; ++ case OPC_LARCH_FCLASS_D: ++ { ++ TCGv_i64 fp0 = tcg_temp_new_i64(); ++ gen_load_fpr64(ctx, fp0, fs); ++ gen_helper_float_class_d(fp0, cpu_env, fp0); ++ gen_store_fpr64(ctx, fp0, fd); ++ tcg_temp_free_i64(fp0); ++ } ++ break; ++ case OPC_LARCH_FMIN_D: ++ { ++ TCGv_i64 fp0 = tcg_temp_new_i64(); ++ TCGv_i64 fp1 = tcg_temp_new_i64(); ++ gen_load_fpr64(ctx, fp0, fs); ++ gen_load_fpr64(ctx, fp1, ft); ++ gen_helper_float_min_d(fp1, cpu_env, fp0, fp1); ++ gen_store_fpr64(ctx, fp1, fd); ++ tcg_temp_free_i64(fp1); ++ tcg_temp_free_i64(fp0); ++ } ++ break; ++ case OPC_LARCH_FMINA_D: ++ { ++ TCGv_i64 fp0 = tcg_temp_new_i64(); ++ TCGv_i64 fp1 = tcg_temp_new_i64(); ++ gen_load_fpr64(ctx, fp0, fs); ++ gen_load_fpr64(ctx, fp1, ft); ++ gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1); ++ gen_store_fpr64(ctx, fp1, fd); ++ tcg_temp_free_i64(fp1); ++ tcg_temp_free_i64(fp0); ++ } ++ break; ++ case OPC_LARCH_FMAX_D: ++ { ++ TCGv_i64 fp0 = tcg_temp_new_i64(); ++ TCGv_i64 fp1 = tcg_temp_new_i64(); ++ gen_load_fpr64(ctx, fp0, fs); ++ gen_load_fpr64(ctx, fp1, ft); ++ gen_helper_float_max_d(fp1, cpu_env, fp0, fp1); ++ gen_store_fpr64(ctx, fp1, fd); ++ tcg_temp_free_i64(fp1); ++ tcg_temp_free_i64(fp0); ++ } ++ break; ++ case OPC_LARCH_FMAXA_D: ++ { ++ TCGv_i64 fp0 = tcg_temp_new_i64(); ++ TCGv_i64 fp1 = tcg_temp_new_i64(); ++ gen_load_fpr64(ctx, fp0, fs); ++ gen_load_fpr64(ctx, fp1, ft); ++ gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1); ++ gen_store_fpr64(ctx, fp1, fd); ++ tcg_temp_free_i64(fp1); ++ tcg_temp_free_i64(fp0); ++ } ++ break; ++ case OPC_LARCH_FCVT_S_D: ++ { ++ TCGv_i32 fp32 = tcg_temp_new_i32(); ++ TCGv_i64 fp64 = tcg_temp_new_i64(); ++ ++ gen_load_fpr64(ctx, fp64, fs); ++ gen_helper_float_cvts_d(fp32, cpu_env, fp64); ++ tcg_temp_free_i64(fp64); ++ gen_store_fpr32(ctx, fp32, fd); ++ tcg_temp_free_i32(fp32); ++ } ++ break; ++ case OPC_LARCH_FTINT_W_D: ++ { ++ TCGv_i32 fp32 = tcg_temp_new_i32(); ++ TCGv_i64 fp64 = tcg_temp_new_i64(); ++ ++ gen_load_fpr64(ctx, fp64, fs); ++ gen_helper_float_cvt_w_d(fp32, cpu_env, fp64); ++ tcg_temp_free_i64(fp64); ++ gen_store_fpr32(ctx, fp32, fd); ++ tcg_temp_free_i32(fp32); ++ } ++ break; ++ case OPC_LARCH_FTINT_L_D: ++ { ++ TCGv_i64 fp0 = tcg_temp_new_i64(); ++ ++ gen_load_fpr64(ctx, fp0, fs); ++ gen_helper_float_cvt_l_d(fp0, cpu_env, fp0); ++ gen_store_fpr64(ctx, fp0, fd); ++ tcg_temp_free_i64(fp0); ++ } ++ break; ++ case OPC_LARCH_FFINT_S_W: ++ { ++ TCGv_i32 fp0 = tcg_temp_new_i32(); ++ ++ gen_load_fpr32(ctx, fp0, fs); ++ gen_helper_float_cvts_w(fp0, cpu_env, fp0); ++ gen_store_fpr32(ctx, fp0, fd); ++ tcg_temp_free_i32(fp0); ++ } ++ break; ++ case OPC_LARCH_FFINT_D_W: ++ { ++ TCGv_i32 fp32 = tcg_temp_new_i32(); ++ TCGv_i64 fp64 = tcg_temp_new_i64(); ++ ++ gen_load_fpr32(ctx, fp32, fs); ++ gen_helper_float_cvtd_w(fp64, cpu_env, fp32); ++ tcg_temp_free_i32(fp32); ++ gen_store_fpr64(ctx, fp64, fd); ++ tcg_temp_free_i64(fp64); ++ } ++ break; ++ case OPC_LARCH_FFINT_S_L: ++ { ++ TCGv_i32 fp32 = tcg_temp_new_i32(); ++ TCGv_i64 fp64 = tcg_temp_new_i64(); ++ ++ gen_load_fpr64(ctx, fp64, fs); ++ gen_helper_float_cvts_l(fp32, cpu_env, fp64); ++ tcg_temp_free_i64(fp64); ++ gen_store_fpr32(ctx, fp32, fd); ++ tcg_temp_free_i32(fp32); ++ } ++ break; ++ case OPC_LARCH_FFINT_D_L: ++ { ++ TCGv_i64 fp0 = tcg_temp_new_i64(); ++ ++ gen_load_fpr64(ctx, fp0, fs); ++ gen_helper_float_cvtd_l(fp0, cpu_env, fp0); ++ gen_store_fpr64(ctx, fp0, fd); ++ tcg_temp_free_i64(fp0); ++ } ++ break; ++ default: ++ LARCH_INVAL("farith"); ++ generate_exception_end(ctx, EXCP_RI); ++ return; ++ } ++} ++ ++/* Coprocessor 3 (FPU) */ ++static void gen_flt3_ldst(DisasContext *ctx, uint32_t opc, ++ int fd, int fs, int base, int index) ++{ ++ TCGv t0 = tcg_temp_new(); ++ ++ check_cp1_enabled(ctx); ++ if (base == 0) { ++ gen_load_gpr(t0, index); ++ } else if (index == 0) { ++ gen_load_gpr(t0, base); ++ } else { ++ gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]); ++ } ++ ++ /* ++ * Don't do NOP if destination is zero: we must perform the actual ++ * memory access. ++ */ ++ switch (opc) { ++ case OPC_LARCH_FLDX_S: ++ case OPC_LARCH_FLDGT_S: ++ case OPC_LARCH_FLDLE_S: ++ { ++ TCGv_i32 fp0 = tcg_temp_new_i32(); ++ ++ tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL); ++ tcg_gen_trunc_tl_i32(fp0, t0); ++ gen_store_fpr32(ctx, fp0, fd); ++ tcg_temp_free_i32(fp0); ++ } ++ break; ++ case OPC_LARCH_FLDX_D: ++ case OPC_LARCH_FLDGT_D: ++ case OPC_LARCH_FLDLE_D: ++ { ++ TCGv_i64 fp0 = tcg_temp_new_i64(); ++ tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ); ++ gen_store_fpr64(ctx, fp0, fd); ++ tcg_temp_free_i64(fp0); ++ } ++ break; ++ case OPC_LARCH_FSTX_S: ++ case OPC_LARCH_FSTGT_S: ++ case OPC_LARCH_FSTLE_S: ++ { ++ TCGv_i32 fp0 = tcg_temp_new_i32(); ++ gen_load_fpr32(ctx, fp0, fs); ++ tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL); ++ tcg_temp_free_i32(fp0); ++ } ++ break; ++ case OPC_LARCH_FSTX_D: ++ case OPC_LARCH_FSTGT_D: ++ case OPC_LARCH_FSTLE_D: ++ { ++ TCGv_i64 fp0 = tcg_temp_new_i64(); ++ gen_load_fpr64(ctx, fp0, fs); ++ tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ); ++ tcg_temp_free_i64(fp0); ++ } ++ break; ++ } ++ tcg_temp_free(t0); ++} ++ ++static inline void clear_branch_hflags(DisasContext *ctx) ++{ ++ ctx->hflags &= ~LARCH_HFLAG_BMASK; ++ if (ctx->base.is_jmp == DISAS_NEXT) { ++ save_cpu_state(ctx, 0); ++ } else { ++ /* ++ * It is not safe to save ctx->hflags as hflags may be changed ++ * in execution time. ++ */ ++ tcg_gen_andi_i32(hflags, hflags, ~LARCH_HFLAG_BMASK); ++ } ++} ++ ++static void gen_branch(DisasContext *ctx, int insn_bytes) ++{ ++ if (ctx->hflags & LARCH_HFLAG_BMASK) { ++ int proc_hflags = ctx->hflags & LARCH_HFLAG_BMASK; ++ /* Branches completion */ ++ clear_branch_hflags(ctx); ++ ctx->base.is_jmp = DISAS_NORETURN; ++ /* FIXME: Need to clear can_do_io. */ ++ switch (proc_hflags & LARCH_HFLAG_BMASK) { ++ case LARCH_HFLAG_B: ++ /* unconditional branch */ ++ gen_goto_tb(ctx, 0, ctx->btarget); ++ break; ++ case LARCH_HFLAG_BC: ++ /* Conditional branch */ ++ { ++ TCGLabel *l1 = gen_new_label(); ++ ++ tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1); ++ gen_goto_tb(ctx, 1, ctx->base.pc_next + insn_bytes); ++ gen_set_label(l1); ++ gen_goto_tb(ctx, 0, ctx->btarget); ++ } ++ break; ++ case LARCH_HFLAG_BR: ++ /* unconditional branch to register */ ++ tcg_gen_mov_tl(cpu_PC, btarget); ++ if (ctx->base.singlestep_enabled) { ++ save_cpu_state(ctx, 0); ++ gen_helper_raise_exception_debug(cpu_env); ++ } ++ tcg_gen_lookup_and_goto_ptr(); ++ break; ++ default: ++ fprintf(stderr, "unknown branch 0x%x\n", proc_hflags); ++ abort(); ++ } ++ } ++} ++ ++/* Signed immediate */ ++#define SIMM(op, start, width) \ ++ ((int32_t)(((op >> start) & ((~0U) >> (32 - width))) \ ++ << (32 - width)) \ ++ >> (32 - width)) ++/* Zero-extended immediate */ ++#define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32 - width))) ++ ++static void gen_sync(int stype) ++{ ++ TCGBar tcg_mo = TCG_BAR_SC; ++ ++ switch (stype) { ++ case 0x4: /* SYNC_WMB */ ++ tcg_mo |= TCG_MO_ST_ST; ++ break; ++ case 0x10: /* SYNC_MB */ ++ tcg_mo |= TCG_MO_ALL; ++ break; ++ case 0x11: /* SYNC_ACQUIRE */ ++ tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST; ++ break; ++ case 0x12: /* SYNC_RELEASE */ ++ tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST; ++ break; ++ case 0x13: /* SYNC_RMB */ ++ tcg_mo |= TCG_MO_LD_LD; ++ break; ++ default: ++ tcg_mo |= TCG_MO_ALL; ++ break; ++ } ++ ++ tcg_gen_mb(tcg_mo); ++} ++ ++static void gen_crc32(DisasContext *ctx, int rd, int rs, int rt, int sz, ++ int crc32c) ++{ ++ TCGv t0; ++ TCGv t1; ++ TCGv_i32 tsz = tcg_const_i32(1 << sz); ++ if (rd == 0) { ++ /* Treat as NOP. */ ++ return; ++ } ++ t0 = tcg_temp_new(); ++ t1 = tcg_temp_new(); ++ ++ gen_load_gpr(t0, rt); ++ gen_load_gpr(t1, rs); ++ ++ if (crc32c) { ++ gen_helper_crc32c(cpu_gpr[rd], t0, t1, tsz); ++ } else { ++ gen_helper_crc32(cpu_gpr[rd], t0, t1, tsz); ++ } ++ ++ tcg_temp_free(t0); ++ tcg_temp_free(t1); ++ tcg_temp_free_i32(tsz); ++} ++ ++#include "cpu-csr.h" ++ ++#ifndef CONFIG_USER_ONLY ++ ++/* ++ * 64-bit CSR read ++ * ++ * @arg : GPR to store the value of CSR register ++ * @csr : CSR register number ++ */ ++static void gen_csr_rdq(DisasContext *ctx, TCGv rd, int64_t a1) ++{ ++ TCGv_i64 csr = tcg_const_i64(a1); ++ gen_helper_csr_rdq(rd, cpu_env, csr); ++} ++ ++/* ++ * 64-bit CSR write ++ * ++ * @arg : GPR that stores the new value of CSR register ++ * @csr : CSR register number ++ */ ++static void gen_csr_wrq(DisasContext *ctx, TCGv val, int64_t a1) ++{ ++ TCGv_i64 csr = tcg_const_i64(a1); ++ gen_helper_csr_wrq(val, cpu_env, val, csr); ++} ++ ++/* ++ * 64-bit CSR exchange ++ * ++ * @arg : GPR that stores the new value of CSR register ++ * @csr : CSR register number ++ */ ++static void gen_csr_xchgq(DisasContext *ctx, TCGv val, TCGv mask, int64_t a1) ++{ ++ TCGv_i64 csr = tcg_const_i64(a1); ++ gen_helper_csr_xchgq(val, cpu_env, val, mask, csr); ++} ++#endif /* !CONFIG_USER_ONLY */ ++ ++static void loongarch_tr_init_disas_context(DisasContextBase *dcbase, ++ CPUState *cs) ++{ ++ DisasContext *ctx = container_of(dcbase, DisasContext, base); ++ CPULOONGARCHState *env = cs->env_ptr; ++ ++ ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK; ++ ctx->saved_pc = -1; ++ ctx->insn_flags = env->insn_flags; ++ ctx->btarget = 0; ++ /* Restore state from the tb context. */ ++ ctx->hflags = (uint32_t)ctx->base.tb->flags; /* FIXME: maybe use 64 bits? */ ++ restore_cpu_state(env, ctx); ++#ifdef CONFIG_USER_ONLY ++ ctx->mem_idx = LARCH_HFLAG_UM; ++#else ++ ctx->mem_idx = hflags_mmu_index(ctx->hflags); ++#endif ++ ctx->default_tcg_memop_mask = MO_ALIGN; ++ ++ LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx, ++ ctx->hflags); ++} ++ ++static void loongarch_tr_tb_start(DisasContextBase *dcbase, CPUState *cs) ++{ ++} ++ ++static void loongarch_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) ++{ ++ DisasContext *ctx = container_of(dcbase, DisasContext, base); ++ ++ tcg_gen_insn_start(ctx->base.pc_next, ctx->hflags & LARCH_HFLAG_BMASK, ++ ctx->btarget); ++} ++#if 0 ++static bool loongarch_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs, ++ const CPUBreakpoint *bp) ++{ ++ DisasContext *ctx = container_of(dcbase, DisasContext, base); ++ ++ save_cpu_state(ctx, 1); ++ ctx->base.is_jmp = DISAS_NORETURN; ++ gen_helper_raise_exception_debug(cpu_env); ++ /* The address covered by the breakpoint must be included in ++ [tb->pc, tb->pc + tb->size) in order to for it to be ++ properly cleared -- thus we increment the PC here so that ++ the logic setting tb->size below does the right thing. */ ++ ctx->base.pc_next += 4; ++ return true; ++} ++#endif ++/* 128 and 256 lsx vector instructions are not supported yet */ ++static bool decode_vector_lsx(uint32_t opcode) ++{ ++ uint32_t value = (opcode & 0xff000000); ++ ++ if ((opcode & 0xf0000000) == 0x70000000) { ++ return true; ++ } else if ((opcode & 0xfff00000) == 0x38400000) { ++ return true; ++ } else { ++ switch (value) { ++ case 0x09000000: ++ case 0x0a000000: ++ case 0x0e000000: ++ case 0x0f000000: ++ case 0x2c000000: ++ case 0x30000000: ++ case 0x31000000: ++ case 0x32000000: ++ case 0x33000000: ++ return true; ++ } ++ } ++ return false; ++} ++ ++static bool decode_insn(DisasContext *ctx, uint32_t insn); ++#include "decode-insn.c.inc" ++#include "trans.inc.c" ++ ++static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) ++{ ++ CPULOONGARCHState *env = cs->env_ptr; ++ DisasContext *ctx = container_of(dcbase, DisasContext, base); ++ int insn_bytes = 4; ++ ++ ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next); ++ ++ if (!decode_insn(ctx, ctx->opcode)) { ++ if (decode_vector_lsx(ctx->opcode)) { ++ generate_exception_end(ctx, EXCP_RI); ++ } else { ++ fprintf(stderr, "Error: unkown opcode. 0x%lx: 0x%x\n", ++ ctx->base.pc_next, ctx->opcode); ++ generate_exception_end(ctx, EXCP_RI); ++ } ++ } ++ ++ if (ctx->hflags & LARCH_HFLAG_BMASK) { ++ gen_branch(ctx, insn_bytes); ++ } ++ ctx->base.pc_next += insn_bytes; ++} ++ ++static void loongarch_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs) ++{ ++ DisasContext *ctx = container_of(dcbase, DisasContext, base); ++ ++ if (ctx->base.singlestep_enabled && ctx->base.is_jmp != DISAS_NORETURN) { ++ save_cpu_state(ctx, ctx->base.is_jmp != DISAS_EXIT); ++ gen_helper_raise_exception_debug(cpu_env); ++ } else { ++ switch (ctx->base.is_jmp) { ++ case DISAS_STOP: ++ gen_save_pc(ctx->base.pc_next); ++ tcg_gen_lookup_and_goto_ptr(); ++ break; ++ case DISAS_NEXT: ++ case DISAS_TOO_MANY: ++ save_cpu_state(ctx, 0); ++ gen_goto_tb(ctx, 0, ctx->base.pc_next); ++ break; ++ case DISAS_EXIT: ++ tcg_gen_exit_tb(NULL, 0); ++ break; ++ case DISAS_NORETURN: ++ break; ++ default: ++ g_assert_not_reached(); ++ } ++ } ++} ++ ++static void loongarch_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs) ++{ ++ qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first)); ++ log_target_disas(cs, dcbase->pc_first, dcbase->tb->size); ++} ++ ++static const TranslatorOps loongarch_tr_ops = { ++ .init_disas_context = loongarch_tr_init_disas_context, ++ .tb_start = loongarch_tr_tb_start, ++ .insn_start = loongarch_tr_insn_start, ++#if 0 ++ .breakpoint_check = loongarch_tr_breakpoint_check, ++#endif ++ .translate_insn = loongarch_tr_translate_insn, ++ .tb_stop = loongarch_tr_tb_stop, ++ .disas_log = loongarch_tr_disas_log, ++}; ++ ++void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb, int max_insns) ++{ ++ DisasContext ctx; ++ ++ translator_loop(&loongarch_tr_ops, &ctx.base, cs, tb, max_insns); ++} ++ ++void loongarch_tcg_init(void) ++{ ++ int i; ++ ++ for (i = 0; i < 32; i++) ++ cpu_gpr[i] = tcg_global_mem_new(cpu_env, ++ offsetof(CPULOONGARCHState, ++ active_tc.gpr[i]), ++ regnames[i]); ++ ++ for (i = 0; i < 32; i++) { ++ int off = offsetof(CPULOONGARCHState, active_fpu.fpr[i].d); ++ fpu_f64[i] = tcg_global_mem_new_i64(cpu_env, off, fregnames[i]); ++ } ++ ++ cpu_PC = tcg_global_mem_new(cpu_env, ++ offsetof(CPULOONGARCHState, active_tc.PC), "PC"); ++ bcond = tcg_global_mem_new(cpu_env, ++ offsetof(CPULOONGARCHState, bcond), "bcond"); ++ btarget = tcg_global_mem_new(cpu_env, ++ offsetof(CPULOONGARCHState, btarget), "btarget"); ++ hflags = tcg_global_mem_new_i32(cpu_env, ++ offsetof(CPULOONGARCHState, hflags), "hflags"); ++ fpu_fcsr0 = tcg_global_mem_new_i32(cpu_env, ++ offsetof(CPULOONGARCHState, active_fpu.fcsr0), ++ "fcsr0"); ++ cpu_lladdr = tcg_global_mem_new(cpu_env, ++ offsetof(CPULOONGARCHState, lladdr), ++ "lladdr"); ++ cpu_llval = tcg_global_mem_new(cpu_env, offsetof(CPULOONGARCHState, llval), ++ "llval"); ++} ++ ++void restore_state_to_opc(CPULOONGARCHState *env, TranslationBlock *tb, ++ target_ulong *data) ++{ ++ env->active_tc.PC = data[0]; ++ env->hflags &= ~LARCH_HFLAG_BMASK; ++ env->hflags |= data[1]; ++ switch (env->hflags & LARCH_HFLAG_BMASK) { ++ case LARCH_HFLAG_BR: ++ break; ++ case LARCH_HFLAG_BC: ++ case LARCH_HFLAG_B: ++ env->btarget = data[2]; ++ break; ++ } ++} +diff --git a/target/meson.build b/target/meson.build +index 2f6940255e..ac0ce618b7 100644 +--- a/target/meson.build ++++ b/target/meson.build +@@ -5,6 +5,7 @@ subdir('cris') + subdir('hexagon') + subdir('hppa') + subdir('i386') ++subdir('loongarch64') + subdir('m68k') + subdir('microblaze') + subdir('mips') +-- +2.27.0 + diff --git a/0005-Add-linux-headers-and-linux-user.patch b/0005-Add-linux-headers-and-linux-user.patch new file mode 100644 index 0000000..93ba8ed --- /dev/null +++ b/0005-Add-linux-headers-and-linux-user.patch @@ -0,0 +1,1663 @@ +From 0d21e423fc15e8e2e2fdc910a7e94e051427f230 Mon Sep 17 00:00:00 2001 +From: lixianglai +Date: Fri, 19 Aug 2022 23:47:06 -0400 +Subject: [PATCH 5/8] Add linux-headers and linux-user. + +Change-Id: If052442a981fed87c03ca431c010629dc8e872ca +Signed-off-by: lixianglai +--- + linux-headers/asm-loongarch64/bitsperlong.h | 9 + + linux-headers/asm-loongarch64/kvm.h | 346 ++++++++++++++++++++ + linux-headers/asm-loongarch64/sgidefs.h | 20 ++ + linux-headers/asm-loongarch64/unistd.h | 23 ++ + linux-user/loongarch64/cpu_loop.c | 193 +++++++++++ + linux-user/loongarch64/meson.build | 6 + + linux-user/loongarch64/signal.c | 212 ++++++++++++ + linux-user/loongarch64/sockbits.h | 1 + + linux-user/loongarch64/syscall_nr.h | 287 ++++++++++++++++ + linux-user/loongarch64/target_cpu.h | 45 +++ + linux-user/loongarch64/target_elf.h | 14 + + linux-user/loongarch64/target_fcntl.h | 13 + + linux-user/loongarch64/target_signal.h | 23 ++ + linux-user/loongarch64/target_structs.h | 62 ++++ + linux-user/loongarch64/target_syscall.h | 44 +++ + linux-user/loongarch64/termbits.h | 224 +++++++++++++ + 16 files changed, 1522 insertions(+) + create mode 100644 linux-headers/asm-loongarch64/bitsperlong.h + create mode 100644 linux-headers/asm-loongarch64/kvm.h + create mode 100644 linux-headers/asm-loongarch64/sgidefs.h + create mode 100644 linux-headers/asm-loongarch64/unistd.h + create mode 100644 linux-user/loongarch64/cpu_loop.c + create mode 100644 linux-user/loongarch64/meson.build + create mode 100644 linux-user/loongarch64/signal.c + create mode 100644 linux-user/loongarch64/sockbits.h + create mode 100644 linux-user/loongarch64/syscall_nr.h + create mode 100644 linux-user/loongarch64/target_cpu.h + create mode 100644 linux-user/loongarch64/target_elf.h + create mode 100644 linux-user/loongarch64/target_fcntl.h + create mode 100644 linux-user/loongarch64/target_signal.h + create mode 100644 linux-user/loongarch64/target_structs.h + create mode 100644 linux-user/loongarch64/target_syscall.h + create mode 100644 linux-user/loongarch64/termbits.h + +diff --git a/linux-headers/asm-loongarch64/bitsperlong.h b/linux-headers/asm-loongarch64/bitsperlong.h +new file mode 100644 +index 0000000000..5c2c8779a6 +--- /dev/null ++++ b/linux-headers/asm-loongarch64/bitsperlong.h +@@ -0,0 +1,9 @@ ++/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ ++#ifndef __ASM_LOONGARCH_BITSPERLONG_H ++#define __ASM_LOONGARCH_BITSPERLONG_H ++ ++#define __BITS_PER_LONG _LOONGARCH_SZLONG ++ ++#include ++ ++#endif /* __ASM_LOONGARCH_BITSPERLONG_H */ +diff --git a/linux-headers/asm-loongarch64/kvm.h b/linux-headers/asm-loongarch64/kvm.h +new file mode 100644 +index 0000000000..a24375ee59 +--- /dev/null ++++ b/linux-headers/asm-loongarch64/kvm.h +@@ -0,0 +1,346 @@ ++/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ ++/* ++ * This file is subject to the terms and conditions of the GNU General Public ++ * License. See the file "COPYING" in the main directory of this archive ++ * for more details. ++ * ++ * Copyright (C) 2020 Loongson Technologies, Inc. All rights reserved. ++ * Authors: Sanjay Lal ++ * Authors: Xing Li ++ */ ++ ++#ifndef __LINUX_KVM_LOONGARCH_H ++#define __LINUX_KVM_LOONGARCH_H ++ ++#include ++ ++#define __KVM_HAVE_GUEST_DEBUG ++#define KVM_GUESTDBG_USE_SW_BP 0x00010000 ++#define KVM_GUESTDBG_USE_HW_BP 0x00020000 ++#define KVM_DATA_HW_BREAKPOINT_NUM 8 ++#define KVM_INST_HW_BREAKPOINT_NUM 8 ++ ++/* ++ * KVM Loongarch specific structures and definitions. ++ * ++ * Some parts derived from the x86 version of this file. ++ */ ++ ++#define __KVM_HAVE_READONLY_MEM ++ ++#define KVM_COALESCED_MMIO_PAGE_OFFSET 1 ++ ++#define KVM_LARCH_VCPU_PVTIME_CTRL 2 ++#define KVM_LARCH_VCPU_PVTIME_IPA 0 ++ ++/* ++ * for KVM_GET_REGS and KVM_SET_REGS ++ */ ++struct kvm_regs { ++ /* out (KVM_GET_REGS) / in (KVM_SET_REGS) */ ++ __u64 gpr[32]; ++ __u64 pc; ++}; ++ ++/* ++ * for KVM_GET_CPUCFG ++ */ ++struct kvm_cpucfg { ++ /* out (KVM_GET_CPUCFG) */ ++ __u32 cpucfg[64]; ++}; ++ ++/* ++ * for KVM_GET_FPU and KVM_SET_FPU ++ */ ++struct kvm_fpu { ++ __u32 fcsr; ++ __u32 vcsr; ++ __u64 fcc; /* 8x8 */ ++ struct kvm_fpureg { ++ __u64 val64[4]; //support max 256 bits ++ }fpr[32]; ++}; ++ ++/* ++ * For LOONGARCH, we use KVM_SET_ONE_REG and KVM_GET_ONE_REG to access various ++ * registers. The id field is broken down as follows: ++ * ++ * bits[63..52] - As per linux/kvm.h ++ * bits[51..32] - Must be zero. ++ * bits[31..16] - Register set. ++ * ++ * Register set = 0: GP registers from kvm_regs (see definitions below). ++ * ++ * Register set = 1: CP0 registers. ++ * bits[15..8] - COP0 register set. ++ * ++ * COP0 register set = 0: Main CP0 registers. ++ * bits[7..3] - Register 'rd' index. ++ * bits[2..0] - Register 'sel' index. ++ * ++ * COP0 register set = 1: MAARs. ++ * bits[7..0] - MAAR index. ++ * ++ * Register set = 2: KVM specific registers (see definitions below). ++ * ++ * Register set = 3: FPU / MSA registers (see definitions below). ++ * ++ * Other sets registers may be added in the future. Each set would ++ * have its own identifier in bits[31..16]. ++ */ ++ ++#define KVM_REG_LOONGARCH_GP (KVM_REG_LOONGARCH | 0x0000000000000000ULL) ++#define KVM_REG_LOONGARCH_CSR (KVM_REG_LOONGARCH | 0x0000000000010000ULL) ++#define KVM_REG_LOONGARCH_KVM (KVM_REG_LOONGARCH | 0x0000000000020000ULL) ++#define KVM_REG_LOONGARCH_FPU (KVM_REG_LOONGARCH | 0x0000000000030000ULL) ++ ++ ++/* ++ * KVM_REG_LOONGARCH_GP - General purpose registers from kvm_regs. ++ */ ++ ++#define KVM_REG_LOONGARCH_R0 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 0) ++#define KVM_REG_LOONGARCH_R1 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 1) ++#define KVM_REG_LOONGARCH_R2 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 2) ++#define KVM_REG_LOONGARCH_R3 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 3) ++#define KVM_REG_LOONGARCH_R4 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 4) ++#define KVM_REG_LOONGARCH_R5 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 5) ++#define KVM_REG_LOONGARCH_R6 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 6) ++#define KVM_REG_LOONGARCH_R7 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 7) ++#define KVM_REG_LOONGARCH_R8 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 8) ++#define KVM_REG_LOONGARCH_R9 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 9) ++#define KVM_REG_LOONGARCH_R10 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 10) ++#define KVM_REG_LOONGARCH_R11 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 11) ++#define KVM_REG_LOONGARCH_R12 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 12) ++#define KVM_REG_LOONGARCH_R13 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 13) ++#define KVM_REG_LOONGARCH_R14 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 14) ++#define KVM_REG_LOONGARCH_R15 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 15) ++#define KVM_REG_LOONGARCH_R16 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 16) ++#define KVM_REG_LOONGARCH_R17 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 17) ++#define KVM_REG_LOONGARCH_R18 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 18) ++#define KVM_REG_LOONGARCH_R19 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 19) ++#define KVM_REG_LOONGARCH_R20 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 20) ++#define KVM_REG_LOONGARCH_R21 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 21) ++#define KVM_REG_LOONGARCH_R22 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 22) ++#define KVM_REG_LOONGARCH_R23 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 23) ++#define KVM_REG_LOONGARCH_R24 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 24) ++#define KVM_REG_LOONGARCH_R25 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 25) ++#define KVM_REG_LOONGARCH_R26 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 26) ++#define KVM_REG_LOONGARCH_R27 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 27) ++#define KVM_REG_LOONGARCH_R28 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 28) ++#define KVM_REG_LOONGARCH_R29 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 29) ++#define KVM_REG_LOONGARCH_R30 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 30) ++#define KVM_REG_LOONGARCH_R31 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 31) ++ ++#define KVM_REG_LOONGARCH_HI (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 32) ++#define KVM_REG_LOONGARCH_LO (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 33) ++#define KVM_REG_LOONGARCH_PC (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 34) ++ ++ ++/* ++ * KVM_REG_LOONGARCH_KVM - KVM specific control registers. ++ */ ++ ++/* ++ * CP0_Count control ++ * DC: Set 0: Master disable CP0_Count and set COUNT_RESUME to now ++ * Set 1: Master re-enable CP0_Count with unchanged bias, handling timer ++ * interrupts since COUNT_RESUME ++ * This can be used to freeze the timer to get a consistent snapshot of ++ * the CP0_Count and timer interrupt pending state, while also resuming ++ * safely without losing time or guest timer interrupts. ++ * Other: Reserved, do not change. ++ */ ++#define KVM_REG_LOONGARCH_COUNT_CTL (KVM_REG_LOONGARCH_KVM | KVM_REG_SIZE_U64 | 0) ++#define KVM_REG_LOONGARCH_COUNT_CTL_DC 0x00000001 ++ ++/* ++ * CP0_Count resume monotonic nanoseconds ++ * The monotonic nanosecond time of the last set of COUNT_CTL.DC (master ++ * disable). Any reads and writes of Count related registers while ++ * COUNT_CTL.DC=1 will appear to occur at this time. When COUNT_CTL.DC is ++ * cleared again (master enable) any timer interrupts since this time will be ++ * emulated. ++ * Modifications to times in the future are rejected. ++ */ ++#define KVM_REG_LOONGARCH_COUNT_RESUME (KVM_REG_LOONGARCH_KVM | KVM_REG_SIZE_U64 | 1) ++/* ++ * CP0_Count rate in Hz ++ * Specifies the rate of the CP0_Count timer in Hz. Modifications occur without ++ * discontinuities in CP0_Count. ++ */ ++#define KVM_REG_LOONGARCH_COUNT_HZ (KVM_REG_LOONGARCH_KVM | KVM_REG_SIZE_U64 | 2) ++ ++#define KVM_REG_LOONGARCH_COUNTER (KVM_REG_LOONGARCH_KVM | KVM_REG_SIZE_U64 | 3) ++ ++#define KVM_REG_LOONGARCH_VCPU_RESET (KVM_REG_LOONGARCH_KVM | KVM_REG_SIZE_U64 | 4) ++ ++struct kvm_iocsr_entry { ++ __u32 addr; ++ __u32 pad; ++ __u64 data; ++}; ++ ++struct kvm_csr_entry { ++ __u32 index; ++ __u32 reserved; ++ __u64 data; ++}; ++ ++/* for KVM_GET_MSRS and KVM_SET_MSRS */ ++struct kvm_msrs { ++ __u32 ncsrs; /* number of msrs in entries */ ++ __u32 pad; ++ struct kvm_csr_entry entries[0]; ++}; ++ ++#define __KVM_HAVE_IRQ_LINE ++ ++struct kvm_debug_exit_arch { ++ __u64 epc; ++ __u32 fwps; ++ __u32 mwps; ++ __u32 exception; ++}; ++ ++/* for KVM_SET_GUEST_DEBUG */ ++struct hw_breakpoint { ++ __u64 addr; ++ __u64 mask; ++ __u32 asid; ++ __u32 ctrl; ++}; ++ ++struct kvm_guest_debug_arch { ++ struct hw_breakpoint data_breakpoint[KVM_DATA_HW_BREAKPOINT_NUM]; ++ struct hw_breakpoint inst_breakpoint[KVM_INST_HW_BREAKPOINT_NUM]; ++ int inst_bp_nums, data_bp_nums; ++}; ++ ++/* definition of registers in kvm_run */ ++struct kvm_sync_regs { ++}; ++ ++/* dummy definition */ ++struct kvm_sregs { ++}; ++ ++struct kvm_loongarch_interrupt { ++ /* in */ ++ __u32 cpu; ++ __u32 irq; ++}; ++ ++#define KVM_IRQCHIP_LS7A_IOAPIC 0x0 ++#define KVM_IRQCHIP_LS3A_GIPI 0x1 ++#define KVM_IRQCHIP_LS3A_HT_IRQ 0x2 ++#define KVM_IRQCHIP_LS3A_ROUTE 0x3 ++#define KVM_IRQCHIP_LS3A_EXTIRQ 0x4 ++#define KVM_IRQCHIP_LS3A_IPMASK 0x5 ++#define KVM_NR_IRQCHIPS 1 ++#define KVM_IRQCHIP_NUM_PINS 64 ++ ++#define KVM_MAX_CORES 256 ++#define KVM_EXTIOI_IRQS (256) ++#define KVM_EXTIOI_IRQS_BITMAP_SIZE (KVM_EXTIOI_IRQS / 8) ++/* map to ipnum per 32 irqs */ ++#define KVM_EXTIOI_IRQS_IPMAP_SIZE (KVM_EXTIOI_IRQS / 32) ++#define KVM_EXTIOI_IRQS_PER_GROUP 32 ++#define KVM_EXTIOI_IRQS_COREMAP_SIZE (KVM_EXTIOI_IRQS) ++#define KVM_EXTIOI_IRQS_NODETYPE_SIZE 16 ++ ++struct ls7a_ioapic_state { ++ __u64 int_id; ++ /* 0x020 interrupt mask register */ ++ __u64 int_mask; ++ /* 0x040 1=msi */ ++ __u64 htmsi_en; ++ /* 0x060 edge=1 level =0 */ ++ __u64 intedge; ++ /* 0x080 for clean edge int,set 1 clean,set 0 is noused */ ++ __u64 intclr; ++ /* 0x0c0 */ ++ __u64 auto_crtl0; ++ /* 0x0e0 */ ++ __u64 auto_crtl1; ++ /* 0x100 - 0x140 */ ++ __u8 route_entry[64]; ++ /* 0x200 - 0x240 */ ++ __u8 htmsi_vector[64]; ++ /* 0x300 */ ++ __u64 intisr_chip0; ++ /* 0x320 */ ++ __u64 intisr_chip1; ++ /* edge detection */ ++ __u64 last_intirr; ++ /* 0x380 interrupt request register */ ++ __u64 intirr; ++ /* 0x3a0 interrupt service register */ ++ __u64 intisr; ++ /* 0x3e0 interrupt level polarity selection register, ++ * 0 for high level tirgger ++ */ ++ __u64 int_polarity; ++}; ++ ++struct loongarch_gipi_single { ++ __u32 status; ++ __u32 en; ++ __u32 set; ++ __u32 clear; ++ __u64 buf[4]; ++}; ++ ++struct loongarch_gipiState { ++ struct loongarch_gipi_single core[KVM_MAX_CORES]; ++}; ++ ++struct kvm_loongarch_ls3a_extirq_state { ++ union ext_en_r { ++ uint64_t reg_u64[KVM_EXTIOI_IRQS_BITMAP_SIZE / 8]; ++ uint32_t reg_u32[KVM_EXTIOI_IRQS_BITMAP_SIZE / 4]; ++ uint8_t reg_u8[KVM_EXTIOI_IRQS_BITMAP_SIZE]; ++ } ext_en_r; ++ union bounce_r { ++ uint64_t reg_u64[KVM_EXTIOI_IRQS_BITMAP_SIZE / 8]; ++ uint32_t reg_u32[KVM_EXTIOI_IRQS_BITMAP_SIZE / 4]; ++ uint8_t reg_u8[KVM_EXTIOI_IRQS_BITMAP_SIZE]; ++ } bounce_r; ++ union ext_isr_r { ++ uint64_t reg_u64[KVM_EXTIOI_IRQS_BITMAP_SIZE / 8]; ++ uint32_t reg_u32[KVM_EXTIOI_IRQS_BITMAP_SIZE / 4]; ++ uint8_t reg_u8[KVM_EXTIOI_IRQS_BITMAP_SIZE]; ++ } ext_isr_r; ++ union ext_core_isr_r { ++ uint64_t reg_u64[KVM_MAX_CORES][KVM_EXTIOI_IRQS_BITMAP_SIZE / 8]; ++ uint32_t reg_u32[KVM_MAX_CORES][KVM_EXTIOI_IRQS_BITMAP_SIZE / 4]; ++ uint8_t reg_u8[KVM_MAX_CORES][KVM_EXTIOI_IRQS_BITMAP_SIZE]; ++ } ext_core_isr_r; ++ union ip_map_r { ++ uint64_t reg_u64; ++ uint32_t reg_u32[KVM_EXTIOI_IRQS_IPMAP_SIZE / 4]; ++ uint8_t reg_u8[KVM_EXTIOI_IRQS_IPMAP_SIZE]; ++ } ip_map_r; ++ union core_map_r { ++ uint64_t reg_u64[KVM_EXTIOI_IRQS_COREMAP_SIZE / 8]; ++ uint32_t reg_u32[KVM_EXTIOI_IRQS_COREMAP_SIZE / 4]; ++ uint8_t reg_u8[KVM_EXTIOI_IRQS_COREMAP_SIZE]; ++ } core_map_r; ++ union node_type_r { ++ uint64_t reg_u64[KVM_EXTIOI_IRQS_NODETYPE_SIZE / 4]; ++ uint32_t reg_u32[KVM_EXTIOI_IRQS_NODETYPE_SIZE / 2]; ++ uint16_t reg_u16[KVM_EXTIOI_IRQS_NODETYPE_SIZE]; ++ uint8_t reg_u8[KVM_EXTIOI_IRQS_NODETYPE_SIZE * 2]; ++ } node_type_r; ++}; ++ ++struct loongarch_kvm_irqchip { ++ __u16 chip_id; ++ __u16 len; ++ __u16 vcpu_id; ++ __u16 reserved; ++ char data[0]; ++}; ++ ++#endif /* __LINUX_KVM_LOONGARCH_H */ +diff --git a/linux-headers/asm-loongarch64/sgidefs.h b/linux-headers/asm-loongarch64/sgidefs.h +new file mode 100644 +index 0000000000..b809608349 +--- /dev/null ++++ b/linux-headers/asm-loongarch64/sgidefs.h +@@ -0,0 +1,20 @@ ++/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ ++/* ++* Copyright (C) 2020 Loongson Technology Corporation Limited ++* ++* Author: Hanlu Li ++*/ ++#ifndef __ASM_SGIDEFS_H ++#define __ASM_SGIDEFS_H ++ ++#define _LOONGARCH_ISA_LOONGARCH32 6 ++#define _LOONGARCH_ISA_LOONGARCH64 7 ++ ++/* ++ * Subprogram calling convention ++ */ ++#define _LOONGARCH_SIM_ABILP32 1 ++#define _LOONGARCH_SIM_ABILPX32 2 ++#define _LOONGARCH_SIM_ABILP64 3 ++ ++#endif /* __ASM_SGIDEFS_H */ +diff --git a/linux-headers/asm-loongarch64/unistd.h b/linux-headers/asm-loongarch64/unistd.h +new file mode 100644 +index 0000000000..2a6014562a +--- /dev/null ++++ b/linux-headers/asm-loongarch64/unistd.h +@@ -0,0 +1,23 @@ ++/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ ++/* ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ * ++ * Copyright (C) 2020 Loongson Technologies, Inc. ++ * Authors: Jun Yi ++ */ ++ ++#ifdef __LP64__ ++#define __ARCH_WANT_NEW_STAT ++#endif /* __LP64__ */ ++ ++#include +diff --git a/linux-user/loongarch64/cpu_loop.c b/linux-user/loongarch64/cpu_loop.c +new file mode 100644 +index 0000000000..6d4093e1d7 +--- /dev/null ++++ b/linux-user/loongarch64/cpu_loop.c +@@ -0,0 +1,193 @@ ++/* ++ * qemu user cpu loop ++ * ++ * Copyright (c) 2003-2008 Fabrice Bellard ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, see . ++ */ ++ ++#include "qemu/osdep.h" ++#include "qemu.h" ++#include "cpu_loop-common.h" ++#include "elf.h" ++ ++/* Break codes */ ++enum { ++ BRK_OVERFLOW = 6, ++ BRK_DIVZERO = 7 ++}; ++ ++static int do_break(CPULOONGARCHState *env, target_siginfo_t *info, ++ unsigned int code) ++{ ++ int ret = -1; ++ ++ switch (code) { ++ case BRK_OVERFLOW: ++ case BRK_DIVZERO: ++ info->si_signo = TARGET_SIGFPE; ++ info->si_errno = 0; ++ info->si_code = (code == BRK_OVERFLOW) ? FPE_INTOVF : FPE_INTDIV; ++ queue_signal(env, info->si_signo, QEMU_SI_FAULT, &*info); ++ ret = 0; ++ break; ++ default: ++ info->si_signo = TARGET_SIGTRAP; ++ info->si_errno = 0; ++ queue_signal(env, info->si_signo, QEMU_SI_FAULT, &*info); ++ ret = 0; ++ break; ++ } ++ ++ return ret; ++} ++ ++void cpu_loop(CPULOONGARCHState *env) ++{ ++ CPUState *cs = CPU(loongarch_env_get_cpu(env)); ++ target_siginfo_t info; ++ int trapnr; ++ abi_long ret; ++ ++ for (;;) { ++ cpu_exec_start(cs); ++ trapnr = cpu_exec(cs); ++ cpu_exec_end(cs); ++ process_queued_cpu_work(cs); ++ ++ switch (trapnr) { ++ case EXCP_SYSCALL: ++ env->active_tc.PC += 4; ++ ret = do_syscall(env, env->active_tc.gpr[11], ++ env->active_tc.gpr[4], env->active_tc.gpr[5], ++ env->active_tc.gpr[6], env->active_tc.gpr[7], ++ env->active_tc.gpr[8], env->active_tc.gpr[9], ++ -1, -1); ++ if (ret == -TARGET_ERESTARTSYS) { ++ env->active_tc.PC -= 4; ++ break; ++ } ++ if (ret == -TARGET_QEMU_ESIGRETURN) { ++ /* Returning from a successful sigreturn syscall. ++ Avoid clobbering register state. */ ++ break; ++ } ++ env->active_tc.gpr[4] = ret; ++ break; ++ case EXCP_TLBL: ++ case EXCP_TLBS: ++ case EXCP_AdEL: ++ case EXCP_AdES: ++ info.si_signo = TARGET_SIGSEGV; ++ info.si_errno = 0; ++ /* XXX: check env->error_code */ ++ info.si_code = TARGET_SEGV_MAPERR; ++ info._sifields._sigfault._addr = env->CSR_BADV; ++ queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); ++ break; ++ case EXCP_FPDIS: ++ case EXCP_LSXDIS: ++ case EXCP_LASXDIS: ++ case EXCP_RI: ++ info.si_signo = TARGET_SIGILL; ++ info.si_errno = 0; ++ info.si_code = 0; ++ queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); ++ break; ++ case EXCP_INTERRUPT: ++ /* just indicate that signals should be handled asap */ ++ break; ++ case EXCP_DEBUG: ++ info.si_signo = TARGET_SIGTRAP; ++ info.si_errno = 0; ++ info.si_code = TARGET_TRAP_BRKPT; ++ queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); ++ break; ++ case EXCP_FPE: ++ info.si_signo = TARGET_SIGFPE; ++ info.si_errno = 0; ++ info.si_code = TARGET_FPE_FLTUNK; ++ if (GET_FP_CAUSE(env->active_fpu.fcsr0) & FP_INVALID) { ++ info.si_code = TARGET_FPE_FLTINV; ++ } else if (GET_FP_CAUSE(env->active_fpu.fcsr0) & FP_DIV0) { ++ info.si_code = TARGET_FPE_FLTDIV; ++ } else if (GET_FP_CAUSE(env->active_fpu.fcsr0) & FP_OVERFLOW) { ++ info.si_code = TARGET_FPE_FLTOVF; ++ } else if (GET_FP_CAUSE(env->active_fpu.fcsr0) & FP_UNDERFLOW) { ++ info.si_code = TARGET_FPE_FLTUND; ++ } else if (GET_FP_CAUSE(env->active_fpu.fcsr0) & FP_INEXACT) { ++ info.si_code = TARGET_FPE_FLTRES; ++ } ++ queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); ++ break; ++ case EXCP_BREAK: ++ { ++ abi_ulong trap_instr; ++ unsigned int code; ++ ++ ret = get_user_u32(trap_instr, env->active_tc.PC); ++ if (ret != 0) { ++ goto error; ++ } ++ ++ code = trap_instr & 0x7fff; ++ ++ if (do_break(env, &info, code) != 0) { ++ goto error; ++ } ++ } ++ break; ++ case EXCP_TRAP: ++ { ++ abi_ulong trap_instr; ++ unsigned int code = 0; ++ ++ ret = get_user_u32(trap_instr, env->active_tc.PC); ++ ++ if (ret != 0) { ++ goto error; ++ } ++ ++ /* The immediate versions don't provide a code. */ ++ if (!(trap_instr & 0xFC000000)) { ++ code = ((trap_instr >> 6) & ((1 << 10) - 1)); ++ } ++ ++ if (do_break(env, &info, code) != 0) { ++ goto error; ++ } ++ } ++ break; ++ case EXCP_ATOMIC: ++ cpu_exec_step_atomic(cs); ++ break; ++ default: ++error: ++ printf("111111\n"); ++ EXCP_DUMP(env, "qemu: unhandled CPU exception 0x%x - aborting\n", trapnr); ++ abort(); ++ } ++ process_pending_signals(env); ++ } ++} ++ ++void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs) ++{ ++ int i; ++ ++ for (i = 0; i < 32; i++) { ++ env->active_tc.gpr[i] = regs->regs[i]; ++ } ++ env->active_tc.PC = regs->csr_era & ~(target_ulong)1; ++} +diff --git a/linux-user/loongarch64/meson.build b/linux-user/loongarch64/meson.build +new file mode 100644 +index 0000000000..c4c0b4d701 +--- /dev/null ++++ b/linux-user/loongarch64/meson.build +@@ -0,0 +1,6 @@ ++syscall_nr_generators += { ++ 'loongarch64': generator(sh, ++ arguments: [ meson.current_source_dir() / 'syscallhdr.sh', '@INPUT@', '@OUTPUT@', '@EXTRA_ARGS@', ++ '', 'TARGET_SYSCALL_OFFSET' ], ++ output: '@BASENAME@_nr.h') ++} +diff --git a/linux-user/loongarch64/signal.c b/linux-user/loongarch64/signal.c +new file mode 100644 +index 0000000000..6fe6852758 +--- /dev/null ++++ b/linux-user/loongarch64/signal.c +@@ -0,0 +1,212 @@ ++/* ++ * Emulation of Linux signals ++ * ++ * Copyright (c) 2003 Fabrice Bellard ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, see . ++ */ ++#include "qemu/osdep.h" ++#include "qemu.h" ++#include "signal-common.h" ++#include "linux-user/trace.h" ++ ++#define FPU_REG_WIDTH 256 ++union fpureg { ++ uint32_t val32[FPU_REG_WIDTH / 32]; ++ uint64_t val64[FPU_REG_WIDTH / 64]; ++}; ++ ++struct target_sigcontext { ++ uint64_t sc_pc; ++ uint64_t sc_regs[32]; ++ uint32_t sc_flags; ++ ++ uint32_t sc_fcsr; ++ uint32_t sc_vcsr; ++ uint64_t sc_fcc; ++ union fpureg sc_fpregs[32] __attribute__((aligned(32))); ++ ++ uint32_t sc_reserved; ++ ++}; ++ ++struct sigframe { ++ uint32_t sf_ass[4]; /* argument save space for o32 */ ++ uint32_t sf_code[2]; /* signal trampoline */ ++ struct target_sigcontext sf_sc; ++ target_sigset_t sf_mask; ++}; ++ ++struct target_ucontext { ++ target_ulong tuc_flags; ++ target_ulong tuc_link; ++ target_stack_t tuc_stack; ++ target_ulong pad0; ++ struct target_sigcontext tuc_mcontext; ++ target_sigset_t tuc_sigmask; ++}; ++ ++struct target_rt_sigframe { ++ uint32_t rs_ass[4]; /* argument save space for o32 */ ++ uint32_t rs_code[2]; /* signal trampoline */ ++ struct target_siginfo rs_info; ++ struct target_ucontext rs_uc; ++}; ++ ++static inline void setup_sigcontext(CPULOONGARCHState *regs, ++ struct target_sigcontext *sc) ++{ ++ int i; ++ ++ __put_user(exception_resume_pc(regs), &sc->sc_pc); ++ regs->hflags &= ~LARCH_HFLAG_BMASK; ++ ++ __put_user(0, &sc->sc_regs[0]); ++ for (i = 1; i < 32; ++i) { ++ __put_user(regs->active_tc.gpr[i], &sc->sc_regs[i]); ++ } ++ ++ for (i = 0; i < 32; ++i) { ++ __put_user(regs->active_fpu.fpr[i].d, &sc->sc_fpregs[i].val64[0]); ++ } ++} ++ ++static inline void ++restore_sigcontext(CPULOONGARCHState *regs, struct target_sigcontext *sc) ++{ ++ int i; ++ ++ __get_user(regs->CSR_ERA, &sc->sc_pc); ++ ++ for (i = 1; i < 32; ++i) { ++ __get_user(regs->active_tc.gpr[i], &sc->sc_regs[i]); ++ } ++ ++ for (i = 0; i < 32; ++i) { ++ __get_user(regs->active_fpu.fpr[i].d, &sc->sc_fpregs[i].val64[0]); ++ } ++} ++ ++/* ++ * Determine which stack to use.. ++ */ ++static inline abi_ulong ++get_sigframe(struct target_sigaction *ka, CPULOONGARCHState *regs, ++ size_t frame_size) ++{ ++ unsigned long sp; ++ ++ /* ++ * FPU emulator may have its own trampoline active just ++ * above the user stack, 16-bytes before the next lowest ++ * 16 byte boundary. Try to avoid trashing it. ++ */ ++ sp = target_sigsp(get_sp_from_cpustate(regs) - 32, ka); ++ ++ return (sp - frame_size) & ~7; ++} ++ ++void setup_rt_frame(int sig, struct target_sigaction *ka, ++ target_siginfo_t *info, ++ target_sigset_t *set, CPULOONGARCHState *env) ++{ ++ struct target_rt_sigframe *frame; ++ abi_ulong frame_addr; ++ int i; ++ ++ frame_addr = get_sigframe(ka, env, sizeof(*frame)); ++ trace_user_setup_rt_frame(env, frame_addr); ++ if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) { ++ goto give_sigsegv; ++ } ++ ++ /* ori a7, $r0, TARGET_NR_rt_sigreturn */ ++ /* syscall 0 */ ++ __put_user(0x0380000b + (TARGET_NR_rt_sigreturn << 10), &frame->rs_code[0]); ++ __put_user(0x002b0000, &frame->rs_code[1]); ++ ++ tswap_siginfo(&frame->rs_info, info); ++ ++ __put_user(0, &frame->rs_uc.tuc_flags); ++ __put_user(0, &frame->rs_uc.tuc_link); ++ target_save_altstack(&frame->rs_uc.tuc_stack, env); ++ ++ setup_sigcontext(env, &frame->rs_uc.tuc_mcontext); ++ ++ for (i = 0; i < TARGET_NSIG_WORDS; i++) { ++ __put_user(set->sig[i], &frame->rs_uc.tuc_sigmask.sig[i]); ++ } ++ ++ /* ++ * Arguments to signal handler: ++ * ++ * a0 = signal number ++ * a1 = pointer to siginfo_t ++ * a2 = pointer to ucontext_t ++ * ++ * $25 and PC point to the signal handler, $29 points to the ++ * struct sigframe. ++ */ ++ env->active_tc.gpr[4] = sig; ++ env->active_tc.gpr[5] = frame_addr ++ + offsetof(struct target_rt_sigframe, rs_info); ++ env->active_tc.gpr[6] = frame_addr ++ + offsetof(struct target_rt_sigframe, rs_uc); ++ env->active_tc.gpr[3] = frame_addr; ++ env->active_tc.gpr[1] = frame_addr ++ + offsetof(struct target_rt_sigframe, rs_code); ++ /* The original kernel code sets CP0_ERA to the handler ++ * since it returns to userland using ertn ++ * we cannot do this here, and we must set PC directly */ ++ env->active_tc.PC = env->active_tc.gpr[20] = ka->_sa_handler; ++ unlock_user_struct(frame, frame_addr, 1); ++ return; ++ ++give_sigsegv: ++ unlock_user_struct(frame, frame_addr, 1); ++ force_sigsegv(sig); ++} ++ ++long do_rt_sigreturn(CPULOONGARCHState *env) ++{ ++ struct target_rt_sigframe *frame; ++ abi_ulong frame_addr; ++ sigset_t blocked; ++ ++ frame_addr = env->active_tc.gpr[3]; ++ trace_user_do_rt_sigreturn(env, frame_addr); ++ if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) { ++ goto badframe; ++ } ++ ++ target_to_host_sigset(&blocked, &frame->rs_uc.tuc_sigmask); ++ set_sigmask(&blocked); ++ ++ restore_sigcontext(env, &frame->rs_uc.tuc_mcontext); ++ ++ if (do_sigaltstack(frame_addr + ++ offsetof(struct target_rt_sigframe, rs_uc.tuc_stack), ++ 0, get_sp_from_cpustate(env)) == -EFAULT) ++ goto badframe; ++ ++ env->active_tc.PC = env->CSR_ERA; ++ /* I am not sure this is right, but it seems to work ++ * maybe a problem with nested signals ? */ ++ env->CSR_ERA = 0; ++ return -TARGET_QEMU_ESIGRETURN; ++ ++badframe: ++ force_sig(TARGET_SIGSEGV); ++ return -TARGET_QEMU_ESIGRETURN; ++} +diff --git a/linux-user/loongarch64/sockbits.h b/linux-user/loongarch64/sockbits.h +new file mode 100644 +index 0000000000..0e4c8f012d +--- /dev/null ++++ b/linux-user/loongarch64/sockbits.h +@@ -0,0 +1 @@ ++#include "../generic/sockbits.h" +diff --git a/linux-user/loongarch64/syscall_nr.h b/linux-user/loongarch64/syscall_nr.h +new file mode 100644 +index 0000000000..a30aca8d8e +--- /dev/null ++++ b/linux-user/loongarch64/syscall_nr.h +@@ -0,0 +1,287 @@ ++#ifndef LINUX_USER_LOONGARCH_SYSCALL_NR_H ++#define LINUX_USER_LOONGARCH_SYSCALL_NR_H ++ ++#define TARGET_NR_io_setup 0 ++#define TARGET_NR_io_destroy 1 ++#define TARGET_NR_io_submit 2 ++#define TARGET_NR_io_cancel 3 ++#define TARGET_NR_io_getevents 4 ++#define TARGET_NR_setxattr 5 ++#define TARGET_NR_lsetxattr 6 ++#define TARGET_NR_fsetxattr 7 ++#define TARGET_NR_getxattr 8 ++#define TARGET_NR_lgetxattr 9 ++#define TARGET_NR_fgetxattr 10 ++#define TARGET_NR_listxattr 11 ++#define TARGET_NR_llistxattr 12 ++#define TARGET_NR_flistxattr 13 ++#define TARGET_NR_removexattr 14 ++#define TARGET_NR_lremovexattr 15 ++#define TARGET_NR_fremovexattr 16 ++#define TARGET_NR_getcwd 17 ++#define TARGET_NR_lookup_dcookie 18 ++#define TARGET_NR_eventfd2 19 ++#define TARGET_NR_epoll_create1 20 ++#define TARGET_NR_epoll_ctl 21 ++#define TARGET_NR_epoll_pwait 22 ++#define TARGET_NR_dup 23 ++#define TARGET_NR_dup3 24 ++#define TARGET_NR_fcntl 25 ++#define TARGET_NR_inotify_init1 26 ++#define TARGET_NR_inotify_add_watch 27 ++#define TARGET_NR_inotify_rm_watch 28 ++#define TARGET_NR_ioctl 29 ++#define TARGET_NR_ioprio_set 30 ++#define TARGET_NR_ioprio_get 31 ++#define TARGET_NR_flock 32 ++#define TARGET_NR_mknodat 33 ++#define TARGET_NR_mkdirat 34 ++#define TARGET_NR_unlinkat 35 ++#define TARGET_NR_symlinkat 36 ++#define TARGET_NR_linkat 37 ++#define TARGET_NR_renameat 38 ++#define TARGET_NR_umount2 39 ++#define TARGET_NR_mount 40 ++#define TARGET_NR_pivot_root 41 ++#define TARGET_NR_nfsservctl 42 ++#define TARGET_NR_statfs 43 ++#define TARGET_NR_fstatfs 44 ++#define TARGET_NR_truncate 45 ++#define TARGET_NR_ftruncate 46 ++#define TARGET_NR_fallocate 47 ++#define TARGET_NR_faccessat 48 ++#define TARGET_NR_chdir 49 ++#define TARGET_NR_fchdir 50 ++#define TARGET_NR_chroot 51 ++#define TARGET_NR_fchmod 52 ++#define TARGET_NR_fchmodat 53 ++#define TARGET_NR_fchownat 54 ++#define TARGET_NR_fchown 55 ++#define TARGET_NR_openat 56 ++#define TARGET_NR_close 57 ++#define TARGET_NR_vhangup 58 ++#define TARGET_NR_pipe2 59 ++#define TARGET_NR_quotactl 60 ++#define TARGET_NR_getdents64 61 ++#define TARGET_NR_lseek 62 ++#define TARGET_NR_read 63 ++#define TARGET_NR_write 64 ++#define TARGET_NR_readv 65 ++#define TARGET_NR_writev 66 ++#define TARGET_NR_pread64 67 ++#define TARGET_NR_pwrite64 68 ++#define TARGET_NR_preadv 69 ++#define TARGET_NR_pwritev 70 ++#define TARGET_NR_sendfile 71 ++#define TARGET_NR_pselect6 72 ++#define TARGET_NR_ppoll 73 ++#define TARGET_NR_signalfd4 74 ++#define TARGET_NR_vmsplice 75 ++#define TARGET_NR_splice 76 ++#define TARGET_NR_tee 77 ++#define TARGET_NR_readlinkat 78 ++#define TARGET_NR_newfstatat 79 ++#define TARGET_NR_fstat 80 ++#define TARGET_NR_sync 81 ++#define TARGET_NR_fsync 82 ++#define TARGET_NR_fdatasync 83 ++#define TARGET_NR_sync_file_range 84 ++#define TARGET_NR_timerfd_create 85 ++#define TARGET_NR_timerfd_settime 86 ++#define TARGET_NR_timerfd_gettime 87 ++#define TARGET_NR_utimensat 88 ++#define TARGET_NR_acct 89 ++#define TARGET_NR_capget 90 ++#define TARGET_NR_capset 91 ++#define TARGET_NR_personality 92 ++#define TARGET_NR_exit 93 ++#define TARGET_NR_exit_group 94 ++#define TARGET_NR_waitid 95 ++#define TARGET_NR_set_tid_address 96 ++#define TARGET_NR_unshare 97 ++#define TARGET_NR_futex 98 ++#define TARGET_NR_set_robust_list 99 ++#define TARGET_NR_get_robust_list 100 ++#define TARGET_NR_nanosleep 101 ++#define TARGET_NR_getitimer 102 ++#define TARGET_NR_setitimer 103 ++#define TARGET_NR_kexec_load 104 ++#define TARGET_NR_init_module 105 ++#define TARGET_NR_delete_module 106 ++#define TARGET_NR_timer_create 107 ++#define TARGET_NR_timer_gettime 108 ++#define TARGET_NR_timer_getoverrun 109 ++#define TARGET_NR_timer_settime 110 ++#define TARGET_NR_timer_delete 111 ++#define TARGET_NR_clock_settime 112 ++#define TARGET_NR_clock_gettime 113 ++#define TARGET_NR_clock_getres 114 ++#define TARGET_NR_clock_nanosleep 115 ++#define TARGET_NR_syslog 116 ++#define TARGET_NR_ptrace 117 ++#define TARGET_NR_sched_setparam 118 ++#define TARGET_NR_sched_setscheduler 119 ++#define TARGET_NR_sched_getscheduler 120 ++#define TARGET_NR_sched_getparam 121 ++#define TARGET_NR_sched_setaffinity 122 ++#define TARGET_NR_sched_getaffinity 123 ++#define TARGET_NR_sched_yield 124 ++#define TARGET_NR_sched_get_priority_max 125 ++#define TARGET_NR_sched_get_priority_min 126 ++#define TARGET_NR_sched_rr_get_interval 127 ++#define TARGET_NR_restart_syscall 128 ++#define TARGET_NR_kill 129 ++#define TARGET_NR_tkill 130 ++#define TARGET_NR_tgkill 131 ++#define TARGET_NR_sigaltstack 132 ++#define TARGET_NR_rt_sigsuspend 133 ++#define TARGET_NR_rt_sigaction 134 ++#define TARGET_NR_rt_sigprocmask 135 ++#define TARGET_NR_rt_sigpending 136 ++#define TARGET_NR_rt_sigtimedwait 137 ++#define TARGET_NR_rt_sigqueueinfo 138 ++#define TARGET_NR_rt_sigreturn 139 ++#define TARGET_NR_setpriority 140 ++#define TARGET_NR_getpriority 141 ++#define TARGET_NR_reboot 142 ++#define TARGET_NR_setregid 143 ++#define TARGET_NR_setgid 144 ++#define TARGET_NR_setreuid 145 ++#define TARGET_NR_setuid 146 ++#define TARGET_NR_setresuid 147 ++#define TARGET_NR_getresuid 148 ++#define TARGET_NR_setresgid 149 ++#define TARGET_NR_getresgid 150 ++#define TARGET_NR_setfsuid 151 ++#define TARGET_NR_setfsgid 152 ++#define TARGET_NR_times 153 ++#define TARGET_NR_setpgid 154 ++#define TARGET_NR_getpgid 155 ++#define TARGET_NR_getsid 156 ++#define TARGET_NR_setsid 157 ++#define TARGET_NR_getgroups 158 ++#define TARGET_NR_setgroups 159 ++#define TARGET_NR_uname 160 ++#define TARGET_NR_sethostname 161 ++#define TARGET_NR_setdomainname 162 ++#define TARGET_NR_getrlimit 163 ++#define TARGET_NR_setrlimit 164 ++#define TARGET_NR_getrusage 165 ++#define TARGET_NR_umask 166 ++#define TARGET_NR_prctl 167 ++#define TARGET_NR_getcpu 168 ++#define TARGET_NR_gettimeofday 169 ++#define TARGET_NR_settimeofday 170 ++#define TARGET_NR_adjtimex 171 ++#define TARGET_NR_getpid 172 ++#define TARGET_NR_getppid 173 ++#define TARGET_NR_getuid 174 ++#define TARGET_NR_geteuid 175 ++#define TARGET_NR_getgid 176 ++#define TARGET_NR_getegid 177 ++#define TARGET_NR_gettid 178 ++#define TARGET_NR_sysinfo 179 ++#define TARGET_NR_mq_open 180 ++#define TARGET_NR_mq_unlink 181 ++#define TARGET_NR_mq_timedsend 182 ++#define TARGET_NR_mq_timedreceive 183 ++#define TARGET_NR_mq_notify 184 ++#define TARGET_NR_mq_getsetattr 185 ++#define TARGET_NR_msgget 186 ++#define TARGET_NR_msgctl 187 ++#define TARGET_NR_msgrcv 188 ++#define TARGET_NR_msgsnd 189 ++#define TARGET_NR_semget 190 ++#define TARGET_NR_semctl 191 ++#define TARGET_NR_semtimedop 192 ++#define TARGET_NR_semop 193 ++#define TARGET_NR_shmget 194 ++#define TARGET_NR_shmctl 195 ++#define TARGET_NR_shmat 196 ++#define TARGET_NR_shmdt 197 ++#define TARGET_NR_socket 198 ++#define TARGET_NR_socketpair 199 ++#define TARGET_NR_bind 200 ++#define TARGET_NR_listen 201 ++#define TARGET_NR_accept 202 ++#define TARGET_NR_connect 203 ++#define TARGET_NR_getsockname 204 ++#define TARGET_NR_getpeername 205 ++#define TARGET_NR_sendto 206 ++#define TARGET_NR_recvfrom 207 ++#define TARGET_NR_setsockopt 208 ++#define TARGET_NR_getsockopt 209 ++#define TARGET_NR_shutdown 210 ++#define TARGET_NR_sendmsg 211 ++#define TARGET_NR_recvmsg 212 ++#define TARGET_NR_readahead 213 ++#define TARGET_NR_brk 214 ++#define TARGET_NR_munmap 215 ++#define TARGET_NR_mremap 216 ++#define TARGET_NR_add_key 217 ++#define TARGET_NR_request_key 218 ++#define TARGET_NR_keyctl 219 ++#define TARGET_NR_clone 220 ++#define TARGET_NR_execve 221 ++#define TARGET_NR_mmap 222 ++#define TARGET_NR_fadvise64 223 ++#define TARGET_NR_swapon 224 ++#define TARGET_NR_swapoff 225 ++#define TARGET_NR_mprotect 226 ++#define TARGET_NR_msync 227 ++#define TARGET_NR_mlock 228 ++#define TARGET_NR_munlock 229 ++#define TARGET_NR_mlockall 230 ++#define TARGET_NR_munlockall 231 ++#define TARGET_NR_mincore 232 ++#define TARGET_NR_madvise 233 ++#define TARGET_NR_remap_file_pages 234 ++#define TARGET_NR_mbind 235 ++#define TARGET_NR_get_mempolicy 236 ++#define TARGET_NR_set_mempolicy 237 ++#define TARGET_NR_migrate_pages 238 ++#define TARGET_NR_move_pages 239 ++#define TARGET_NR_rt_tgsigqueueinfo 240 ++#define TARGET_NR_perf_event_open 241 ++#define TARGET_NR_accept4 242 ++#define TARGET_NR_recvmmsg 243 ++#define TARGET_NR_arch_specific_syscall 244 ++#define TARGET_NR_wait4 260 ++#define TARGET_NR_prlimit64 261 ++#define TARGET_NR_fanotify_init 262 ++#define TARGET_NR_fanotify_mark 263 ++#define TARGET_NR_name_to_handle_at 264 ++#define TARGET_NR_open_by_handle_at 265 ++#define TARGET_NR_clock_adjtime 266 ++#define TARGET_NR_syncfs 267 ++#define TARGET_NR_setns 268 ++#define TARGET_NR_sendmmsg 269 ++#define TARGET_NR_process_vm_readv 270 ++#define TARGET_NR_process_vm_writev 271 ++#define TARGET_NR_kcmp 272 ++#define TARGET_NR_finit_module 273 ++#define TARGET_NR_sched_setattr 274 ++#define TARGET_NR_sched_getattr 275 ++#define TARGET_NR_renameat2 276 ++#define TARGET_NR_seccomp 277 ++#define TARGET_NR_getrandom 278 ++#define TARGET_NR_memfd_create 279 ++#define TARGET_NR_bpf 280 ++#define TARGET_NR_execveat 281 ++#define TARGET_NR_userfaultfd 282 ++#define TARGET_NR_membarrier 283 ++#define TARGET_NR_mlock2 284 ++#define TARGET_NR_copy_file_range 285 ++#define TARGET_NR_preadv2 286 ++#define TARGET_NR_pwritev2 287 ++#define TARGET_NR_pkey_mprotect 288 ++#define TARGET_NR_pkey_alloc 289 ++#define TARGET_NR_pkey_free 290 ++#define TARGET_NR_statx 291 ++#define TARGET_NR_io_pgetevents 292 ++#define TARGET_NR_rseq 293 ++#define TARGET_NR_kexec_file_load 294 ++ ++#define TARGET_NR_syscalls (TARGET_NR_kexec_file_load + 1) ++ ++#endif +diff --git a/linux-user/loongarch64/target_cpu.h b/linux-user/loongarch64/target_cpu.h +new file mode 100644 +index 0000000000..0f6845737f +--- /dev/null ++++ b/linux-user/loongarch64/target_cpu.h +@@ -0,0 +1,45 @@ ++/* ++ * MIPS specific CPU ABI and functions for linux-user ++ * ++ * Copyright (c) 2004-2005 Jocelyn Mayer ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, see . ++ */ ++#ifndef LOONGARCH_TARGET_CPU_H ++#define LOONGARCH_TARGET_CPU_H ++ ++static inline void cpu_clone_regs_child(CPULOONGARCHState *env, target_ulong newsp, ++ unsigned flags) ++{ ++ if (newsp) { ++ env->active_tc.gpr[3] = newsp; ++ } ++ env->active_tc.gpr[7] = 0; ++ env->active_tc.gpr[4] = 0; ++} ++ ++static inline void cpu_clone_regs_parent(CPULOONGARCHState *env, unsigned flags) ++{ ++} ++ ++static inline void cpu_set_tls(CPULOONGARCHState *env, target_ulong newtls) ++{ ++ env->active_tc.gpr[2] = newtls; ++} ++ ++static inline abi_ulong get_sp_from_cpustate(CPULOONGARCHState *state) ++{ ++ return state->active_tc.gpr[3]; ++} ++#endif +diff --git a/linux-user/loongarch64/target_elf.h b/linux-user/loongarch64/target_elf.h +new file mode 100644 +index 0000000000..6c153d12c4 +--- /dev/null ++++ b/linux-user/loongarch64/target_elf.h +@@ -0,0 +1,14 @@ ++/* ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation, or (at your option) any ++ * later version. See the COPYING file in the top-level directory. ++ */ ++ ++#ifndef LOONGARCH_TARGET_ELF_H ++#define LOONGARCH_TARGET_ELF_H ++static inline const char *cpu_get_model(uint32_t eflags) ++{ ++ return "Loongson-3A5000"; ++} ++#endif +diff --git a/linux-user/loongarch64/target_fcntl.h b/linux-user/loongarch64/target_fcntl.h +new file mode 100644 +index 0000000000..a3d7b46062 +--- /dev/null ++++ b/linux-user/loongarch64/target_fcntl.h +@@ -0,0 +1,13 @@ ++/* ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation, or (at your option) any ++ * later version. See the COPYING file in the top-level directory. ++ */ ++ ++#ifndef LOONGARCH_TARGET_FCNTL_H ++#define LOONGARCH_TARGET_FCNTL_H ++ ++#include "../generic/fcntl.h" ++ ++#endif /* LOONGARCH_TARGET_FCNTL_H */ +diff --git a/linux-user/loongarch64/target_signal.h b/linux-user/loongarch64/target_signal.h +new file mode 100644 +index 0000000000..e418c8e8f5 +--- /dev/null ++++ b/linux-user/loongarch64/target_signal.h +@@ -0,0 +1,23 @@ ++#ifndef LOONGARCH_TARGET_SIGNAL_H ++#define LOONGARCH_TARGET_SIGNAL_H ++ ++/* this struct defines a stack used during syscall handling */ ++ ++typedef struct target_sigaltstack { ++ abi_long ss_sp; ++ abi_int ss_flags; ++ abi_ulong ss_size; ++} target_stack_t; ++ ++/* ++ * sigaltstack controls ++ */ ++#define TARGET_SS_ONSTACK 1 ++#define TARGET_SS_DISABLE 2 ++ ++#define TARGET_MINSIGSTKSZ 2048 ++#define TARGET_SIGSTKSZ 8192 ++ ++#include "../generic/signal.h" ++ ++#endif /* LOONGARCH_TARGET_SIGNAL_H */ +diff --git a/linux-user/loongarch64/target_structs.h b/linux-user/loongarch64/target_structs.h +new file mode 100644 +index 0000000000..280acd0971 +--- /dev/null ++++ b/linux-user/loongarch64/target_structs.h +@@ -0,0 +1,62 @@ ++/* ++ * LOONGARCH specific structures for linux-user ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, see . ++ */ ++#ifndef LOONGARCH_TARGET_STRUCTS_H ++#define LOONGARCH_TARGET_STRUCTS_H ++ ++struct target_ipc_perm { ++ abi_int __key; /* Key. */ ++ abi_uint uid; /* Owner's user ID. */ ++ abi_uint gid; /* Owner's group ID. */ ++ abi_uint cuid; /* Creator's user ID. */ ++ abi_uint cgid; /* Creator's group ID. */ ++ abi_uint mode; /* Read/write permission. */ ++ abi_ushort __seq; /* Sequence number. */ ++ abi_ushort __pad1; ++ abi_ulong __unused1; ++ abi_ulong __unused2; ++}; ++ ++struct target_shmid_ds { ++ struct target_ipc_perm shm_perm; /* operation permission struct */ ++ abi_long shm_segsz; /* size of segment in bytes */ ++ abi_ulong shm_atime; /* time of last shmat() */ ++ abi_ulong shm_dtime; /* time of last shmdt() */ ++ abi_ulong shm_ctime; /* time of last change by shmctl() */ ++ abi_int shm_cpid; /* pid of creator */ ++ abi_int shm_lpid; /* pid of last shmop */ ++ abi_ulong shm_nattch; /* number of current attaches */ ++ abi_ulong __unused1; ++ abi_ulong __unused2; ++}; ++ ++#define TARGET_SEMID64_DS ++ ++/* ++ * The semid64_ds structure for the MIPS architecture. ++ * Note extra padding because this structure is passed back and forth ++ * between kernel and user space. ++ */ ++struct target_semid64_ds { ++ struct target_ipc_perm sem_perm; ++ abi_ulong sem_otime; ++ abi_ulong sem_ctime; ++ abi_ulong sem_nsems; ++ abi_ulong __unused1; ++ abi_ulong __unused2; ++}; ++ ++#endif +diff --git a/linux-user/loongarch64/target_syscall.h b/linux-user/loongarch64/target_syscall.h +new file mode 100644 +index 0000000000..cb77f07080 +--- /dev/null ++++ b/linux-user/loongarch64/target_syscall.h +@@ -0,0 +1,44 @@ ++#ifndef LOONGARCH_TARGET_SYSCALL_H ++#define LOONGARCH_TARGET_SYSCALL_H ++ ++/* this struct defines the way the registers are stored on the ++ stack during a system call. */ ++ ++struct target_pt_regs { ++ /* Saved main processor registers. */ ++ target_ulong regs[32]; ++ ++ /* Saved special registers. */ ++ /* Saved special registers. */ ++ target_ulong csr_crmd; ++ target_ulong csr_prmd; ++ target_ulong csr_euen; ++ target_ulong csr_ecfg; ++ target_ulong csr_estat; ++ target_ulong csr_era; ++ target_ulong csr_badvaddr; ++ target_ulong orig_a0; ++ target_ulong __last[0]; ++}; ++ ++#define UNAME_MACHINE "loongarch" ++#define UNAME_MINIMUM_RELEASE "2.6.32" ++ ++#define TARGET_CLONE_BACKWARDS ++#define TARGET_MINSIGSTKSZ 2048 ++#define TARGET_MLOCKALL_MCL_CURRENT 1 ++#define TARGET_MLOCKALL_MCL_FUTURE 2 ++ ++#define TARGET_FORCE_SHMLBA ++ ++static inline abi_ulong target_shmlba(CPULOONGARCHState *env) ++{ ++ return 0x40000; ++} ++ ++#define TARGET_PR_SET_FP_MODE 45 ++#define TARGET_PR_GET_FP_MODE 46 ++#define TARGET_PR_FP_MODE_FR (1 << 0) ++#define TARGET_PR_FP_MODE_FRE (1 << 1) ++ ++#endif /* LOONGARCH_TARGET_SYSCALL_H */ +diff --git a/linux-user/loongarch64/termbits.h b/linux-user/loongarch64/termbits.h +new file mode 100644 +index 0000000000..6c613a1973 +--- /dev/null ++++ b/linux-user/loongarch64/termbits.h +@@ -0,0 +1,224 @@ ++#ifndef LINUX_USER_LOONGARCH_TERMBITS_H ++#define LINUX_USER_LOONGARCH_TERMBITS_H ++ ++#define TARGET_NCCS 19 ++ ++struct target_termios { ++ unsigned int c_iflag; /* input mode flags */ ++ unsigned int c_oflag; /* output mode flags */ ++ unsigned int c_cflag; /* control mode flags */ ++ unsigned int c_lflag; /* local mode flags */ ++ unsigned char c_line; /* line discipline */ ++ unsigned char c_cc[TARGET_NCCS]; /* control characters */ ++}; ++ ++/* c_iflag bits */ ++#define TARGET_IGNBRK 0000001 ++#define TARGET_BRKINT 0000002 ++#define TARGET_IGNPAR 0000004 ++#define TARGET_PARMRK 0000010 ++#define TARGET_INPCK 0000020 ++#define TARGET_ISTRIP 0000040 ++#define TARGET_INLCR 0000100 ++#define TARGET_IGNCR 0000200 ++#define TARGET_ICRNL 0000400 ++#define TARGET_IUCLC 0001000 ++#define TARGET_IXON 0002000 ++#define TARGET_IXANY 0004000 ++#define TARGET_IXOFF 0010000 ++#define TARGET_IMAXBEL 0020000 ++#define TARGET_IUTF8 0040000 ++ ++/* c_oflag bits */ ++#define TARGET_OPOST 0000001 ++#define TARGET_OLCUC 0000002 ++#define TARGET_ONLCR 0000004 ++#define TARGET_OCRNL 0000010 ++#define TARGET_ONOCR 0000020 ++#define TARGET_ONLRET 0000040 ++#define TARGET_OFILL 0000100 ++#define TARGET_OFDEL 0000200 ++#define TARGET_NLDLY 0000400 ++#define TARGET_NL0 0000000 ++#define TARGET_NL1 0000400 ++#define TARGET_CRDLY 0003000 ++#define TARGET_CR0 0000000 ++#define TARGET_CR1 0001000 ++#define TARGET_CR2 0002000 ++#define TARGET_CR3 0003000 ++#define TARGET_TABDLY 0014000 ++#define TARGET_TAB0 0000000 ++#define TARGET_TAB1 0004000 ++#define TARGET_TAB2 0010000 ++#define TARGET_TAB3 0014000 ++#define TARGET_XTABS 0014000 ++#define TARGET_BSDLY 0020000 ++#define TARGET_BS0 0000000 ++#define TARGET_BS1 0020000 ++#define TARGET_VTDLY 0040000 ++#define TARGET_VT0 0000000 ++#define TARGET_VT1 0040000 ++#define TARGET_FFDLY 0100000 ++#define TARGET_FF0 0000000 ++#define TARGET_FF1 0100000 ++ ++/* c_cflag bit meaning */ ++#define TARGET_CBAUD 0010017 ++#define TARGET_B0 0000000 /* hang up */ ++#define TARGET_B50 0000001 ++#define TARGET_B75 0000002 ++#define TARGET_B110 0000003 ++#define TARGET_B134 0000004 ++#define TARGET_B150 0000005 ++#define TARGET_B200 0000006 ++#define TARGET_B300 0000007 ++#define TARGET_B600 0000010 ++#define TARGET_B1200 0000011 ++#define TARGET_B1800 0000012 ++#define TARGET_B2400 0000013 ++#define TARGET_B4800 0000014 ++#define TARGET_B9600 0000015 ++#define TARGET_B19200 0000016 ++#define TARGET_B38400 0000017 ++#define TARGET_EXTA B19200 ++#define TARGET_EXTB B38400 ++#define TARGET_CSIZE 0000060 ++#define TARGET_CS5 0000000 ++#define TARGET_CS6 0000020 ++#define TARGET_CS7 0000040 ++#define TARGET_CS8 0000060 ++#define TARGET_CSTOPB 0000100 ++#define TARGET_CREAD 0000200 ++#define TARGET_PARENB 0000400 ++#define TARGET_PARODD 0001000 ++#define TARGET_HUPCL 0002000 ++#define TARGET_CLOCAL 0004000 ++#define TARGET_CBAUDEX 0010000 ++#define TARGET_B57600 0010001 ++#define TARGET_B115200 0010002 ++#define TARGET_B230400 0010003 ++#define TARGET_B460800 0010004 ++#define TARGET_CIBAUD 002003600000 /* input baud rate (not used) */ ++#define TARGET_CMSPAR 010000000000 /* mark or space (stick) parity */ ++#define TARGET_CRTSCTS 020000000000 /* flow control */ ++ ++/* c_lflag bits */ ++#define TARGET_ISIG 0000001 ++#define TARGET_ICANON 0000002 ++#define TARGET_XCASE 0000004 ++#define TARGET_ECHO 0000010 ++#define TARGET_ECHOE 0000020 ++#define TARGET_ECHOK 0000040 ++#define TARGET_ECHONL 0000100 ++#define TARGET_NOFLSH 0000200 ++#define TARGET_TOSTOP 0000400 ++#define TARGET_ECHOCTL 0001000 ++#define TARGET_ECHOPRT 0002000 ++#define TARGET_ECHOKE 0004000 ++#define TARGET_FLUSHO 0010000 ++#define TARGET_PENDIN 0040000 ++#define TARGET_IEXTEN 0100000 ++ ++/* c_cc character offsets */ ++#define TARGET_VINTR 0 ++#define TARGET_VQUIT 1 ++#define TARGET_VERASE 2 ++#define TARGET_VKILL 3 ++#define TARGET_VEOF 4 ++#define TARGET_VTIME 5 ++#define TARGET_VMIN 6 ++#define TARGET_VSWTC 7 ++#define TARGET_VSTART 8 ++#define TARGET_VSTOP 9 ++#define TARGET_VSUSP 10 ++#define TARGET_VEOL 11 ++#define TARGET_VREPRINT 12 ++#define TARGET_VDISCARD 13 ++#define TARGET_VWERASE 14 ++#define TARGET_VLNEXT 15 ++#define TARGET_VEOL2 16 ++ ++/* ioctls */ ++ ++#define TARGET_TCGETS 0x5401 ++#define TARGET_TCSETS 0x5402 ++#define TARGET_TCSETSW 0x5403 ++#define TARGET_TCSETSF 0x5404 ++#define TARGET_TCGETA 0x5405 ++#define TARGET_TCSETA 0x5406 ++#define TARGET_TCSETAW 0x5407 ++#define TARGET_TCSETAF 0x5408 ++#define TARGET_TCSBRK 0x5409 ++#define TARGET_TCXONC 0x540A ++#define TARGET_TCFLSH 0x540B ++ ++#define TARGET_TIOCEXCL 0x540C ++#define TARGET_TIOCNXCL 0x540D ++#define TARGET_TIOCSCTTY 0x540E ++#define TARGET_TIOCGPGRP 0x540F ++#define TARGET_TIOCSPGRP 0x5410 ++#define TARGET_TIOCOUTQ 0x5411 ++#define TARGET_TIOCSTI 0x5412 ++#define TARGET_TIOCGWINSZ 0x5413 ++#define TARGET_TIOCSWINSZ 0x5414 ++#define TARGET_TIOCMGET 0x5415 ++#define TARGET_TIOCMBIS 0x5416 ++#define TARGET_TIOCMBIC 0x5417 ++#define TARGET_TIOCMSET 0x5418 ++#define TARGET_TIOCGSOFTCAR 0x5419 ++#define TARGET_TIOCSSOFTCAR 0x541A ++#define TARGET_FIONREAD 0x541B ++#define TARGET_TIOCINQ TARGET_FIONREAD ++#define TARGET_TIOCLINUX 0x541C ++#define TARGET_TIOCCONS 0x541D ++#define TARGET_TIOCGSERIAL 0x541E ++#define TARGET_TIOCSSERIAL 0x541F ++#define TARGET_TIOCPKT 0x5420 ++#define TARGET_FIONBIO 0x5421 ++#define TARGET_TIOCNOTTY 0x5422 ++#define TARGET_TIOCSETD 0x5423 ++#define TARGET_TIOCGETD 0x5424 ++#define TARGET_TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */ ++#define TARGET_TIOCTTYGSTRUCT 0x5426 /* For debugging only */ ++#define TARGET_TIOCSBRK 0x5427 /* BSD compatibility */ ++#define TARGET_TIOCCBRK 0x5428 /* BSD compatibility */ ++#define TARGET_TIOCGSID 0x5429 /* Return the session ID of FD */ ++#define TARGET_TIOCGPTN TARGET_IOR('T', 0x30, unsigned int) ++ /* Get Pty Number (of pty-mux device) */ ++#define TARGET_TIOCSPTLCK TARGET_IOW('T', 0x31, int) ++ /* Lock/unlock Pty */ ++#define TARGET_TIOCGPTPEER TARGET_IO('T', 0x41) ++ /* Safely open the slave */ ++ ++#define TARGET_FIONCLEX 0x5450 /* these numbers need to be adjusted. */ ++#define TARGET_FIOCLEX 0x5451 ++#define TARGET_FIOASYNC 0x5452 ++#define TARGET_TIOCSERCONFIG 0x5453 ++#define TARGET_TIOCSERGWILD 0x5454 ++#define TARGET_TIOCSERSWILD 0x5455 ++#define TARGET_TIOCGLCKTRMIOS 0x5456 ++#define TARGET_TIOCSLCKTRMIOS 0x5457 ++#define TARGET_TIOCSERGSTRUCT 0x5458 /* For debugging only */ ++#define TARGET_TIOCSERGETLSR 0x5459 /* Get line status register */ ++#define TARGET_TIOCSERGETMULTI 0x545A /* Get multiport config */ ++#define TARGET_TIOCSERSETMULTI 0x545B /* Set multiport config */ ++ ++#define TARGET_TIOCMIWAIT 0x545C ++ /* wait for a change on serial input line(s) */ ++#define TARGET_TIOCGICOUNT 0x545D ++ /* read serial port inline interrupt counts */ ++#define TARGET_TIOCGHAYESESP 0x545E /* Get Hayes ESP configuration */ ++#define TARGET_TIOCSHAYESESP 0x545F /* Set Hayes ESP configuration */ ++ ++/* Used for packet mode */ ++#define TARGET_TIOCPKT_DATA 0 ++#define TARGET_TIOCPKT_FLUSHREAD 1 ++#define TARGET_TIOCPKT_FLUSHWRITE 2 ++#define TARGET_TIOCPKT_STOP 4 ++#define TARGET_TIOCPKT_START 8 ++#define TARGET_TIOCPKT_NOSTOP 16 ++#define TARGET_TIOCPKT_DOSTOP 32 ++ ++#define TARGET_TIOCSER_TEMT 0x01 /* Transmitter physically empty */ ++ ++#endif +-- +2.27.0 + diff --git a/0006-Add-disas-gdb.patch b/0006-Add-disas-gdb.patch new file mode 100644 index 0000000..00d9b5e --- /dev/null +++ b/0006-Add-disas-gdb.patch @@ -0,0 +1,3183 @@ +From 0789663b3a2ad105a209c7aa36d102a5b05f1397 Mon Sep 17 00:00:00 2001 +From: lixianglai +Date: Fri, 19 Aug 2022 23:51:12 -0400 +Subject: [PATCH 6/8] Add disas gdb. + +Change-Id: If41c0fc8aa128796e342319c7673fab3ccbf3913 +Signed-off-by: lixianglai +--- + .../devices/loongarch64-softmmu/default.mak | 154 + + configs/targets/loongarch64-softmmu.mak | 4 + + disas/loongarch.c | 2748 +++++++++++++++++ + disas/meson.build | 1 + + gdb-xml/loongarch-base32.xml | 43 + + gdb-xml/loongarch-base64.xml | 43 + + gdb-xml/loongarch-fpu32.xml | 52 + + gdb-xml/loongarch-fpu64.xml | 57 + + 8 files changed, 3102 insertions(+) + create mode 100644 configs/devices/loongarch64-softmmu/default.mak + create mode 100644 configs/targets/loongarch64-softmmu.mak + create mode 100644 disas/loongarch.c + create mode 100644 gdb-xml/loongarch-base32.xml + create mode 100644 gdb-xml/loongarch-base64.xml + create mode 100644 gdb-xml/loongarch-fpu32.xml + create mode 100644 gdb-xml/loongarch-fpu64.xml + +diff --git a/configs/devices/loongarch64-softmmu/default.mak b/configs/devices/loongarch64-softmmu/default.mak +new file mode 100644 +index 0000000000..fcb7e45dd2 +--- /dev/null ++++ b/configs/devices/loongarch64-softmmu/default.mak +@@ -0,0 +1,154 @@ ++# Default configuration for loongarch-softmmu ++ ++CONFIG_PCI=y ++CONFIG_ACPI_PCI=y ++# For now, CONFIG_IDE_CORE requires ISA, so we enable it here ++CONFIG_ISA_BUS=y ++CONFIG_VIRTIO_PCI=y ++ ++CONFIG_VGA_PCI=y ++CONFIG_ACPI_SMBUS=y ++#CONFIG_VHOST_USER_SCSI=$(call land,$(CONFIG_VHOST_USER),$(CONFIG_LINUX)) ++CONFIG_VHOST_USER_SCSI=y ++#CONFIG_VHOST_USER_BLK=$(call land,$(CONFIG_VHOST_USER),$(CONFIG_LINUX)) ++CONFIG_VHOST_USER_BLK=y ++CONFIG_VIRTIO=y ++CONFIG_VIRTIO_BALLOON=y ++CONFIG_VIRTIO_BLK=y ++CONFIG_VIRTIO_CRYPTO=y ++CONFIG_VIRTIO_GPU=y ++CONFIG_VIRTIO_INPUT=y ++CONFIG_VIRTIO_NET=y ++CONFIG_VIRTIO_RNG=y ++CONFIG_SCSI=y ++CONFIG_VIRTIO_SCSI=y ++CONFIG_VIRTIO_SERIAL=y ++ ++CONFIG_USB_UHCI=y ++CONFIG_USB_OHCI=y ++CONFIG_USB_OHCI_PCI=y ++CONFIG_USB_XHCI=y ++CONFIG_USB_XHCI_NEC=y ++CONFIG_NE2000_PCI=y ++CONFIG_EEPRO100_PCI=y ++CONFIG_PCNET_PCI=y ++CONFIG_PCNET_COMMON=y ++CONFIG_AC97=y ++CONFIG_HDA=y ++CONFIG_ES1370=y ++CONFIG_SCSI=y ++CONFIG_LSI_SCSI_PCI=y ++CONFIG_VMW_PVSCSI_SCSI_PCI=y ++CONFIG_MEGASAS_SCSI_PCI=y ++CONFIG_MPTSAS_SCSI_PCI=y ++CONFIG_RTL8139_PCI=y ++CONFIG_E1000_PCI=y ++CONFIG_IDE_CORE=y ++CONFIG_IDE_QDEV=y ++CONFIG_IDE_PCI=y ++CONFIG_AHCI=y ++CONFIG_AHCI_ICH9=y ++CONFIG_ESP=y ++CONFIG_ESP_PCI=y ++CONFIG_SERIAL=y ++CONFIG_SERIAL_ISA=y ++CONFIG_SERIAL_PCI=y ++CONFIG_CAN_BUS=y ++CONFIG_CAN_SJA1000=y ++CONFIG_CAN_PCI=y ++CONFIG_USB_UHCI=y ++CONFIG_USB_OHCI=y ++CONFIG_USB_XHCI=y ++CONFIG_USB_XHCI_NEC=y ++CONFIG_NE2000_PCI=y ++CONFIG_EEPRO100_PCI=y ++CONFIG_PCNET_PCI=y ++CONFIG_PCNET_COMMON=y ++CONFIG_AC97=y ++CONFIG_HDA=y ++CONFIG_ES1370=y ++CONFIG_SCSI=y ++CONFIG_LSI_SCSI_PCI=y ++CONFIG_VMW_PVSCSI_SCSI_PCI=y ++CONFIG_MEGASAS_SCSI_PCI=y ++CONFIG_MPTSAS_SCSI_PCI=y ++CONFIG_RTL8139_PCI=y ++CONFIG_E1000_PCI=y ++CONFIG_IDE_CORE=y ++CONFIG_IDE_QDEV=y ++CONFIG_IDE_PCI=y ++CONFIG_AHCI=y ++CONFIG_ESP=y ++CONFIG_ESP_PCI=y ++CONFIG_SERIAL=y ++CONFIG_SERIAL_ISA=y ++CONFIG_SERIAL_PCI=y ++CONFIG_CAN_BUS=y ++CONFIG_CAN_SJA1000=y ++CONFIG_CAN_PCI=y ++ ++CONFIG_SPICE=y ++CONFIG_QXL=y ++CONFIG_ESP=y ++CONFIG_SCSI=y ++CONFIG_VGA_ISA=y ++CONFIG_VGA_ISA_MM=y ++CONFIG_VGA_CIRRUS=y ++CONFIG_VMWARE_VGA=y ++CONFIG_VIRTIO_VGA=y ++CONFIG_SERIAL=y ++CONFIG_SERIAL_ISA=y ++CONFIG_PARALLEL=y ++CONFIG_I8254=y ++CONFIG_PCSPK=y ++CONFIG_PCKBD=y ++CONFIG_FDC=y ++CONFIG_ACPI=y ++CONFIG_ACPI_MEMORY_HOTPLUG=y ++CONFIG_ACPI_NVDIMM=y ++CONFIG_ACPI_CPU_HOTPLUG=y ++CONFIG_APM=y ++CONFIG_I8257=y ++CONFIG_PIIX4=y ++CONFIG_IDE_ISA=y ++CONFIG_IDE_PIIX=y ++#CONFIG_NE2000_ISA=y ++CONFIG_MIPSNET=y ++CONFIG_PFLASH_CFI01=y ++CONFIG_I8259=y ++CONFIG_MC146818RTC=y ++CONFIG_ISA_TESTDEV=y ++CONFIG_EMPTY_SLOT=y ++CONFIG_I2C=y ++CONFIG_DIMM=y ++CONFIG_MEM_DEVICE=y ++ ++# Arch Specified CONFIG defines ++CONFIG_IDE_VIA=y ++CONFIG_VT82C686=y ++CONFIG_RC4030=y ++CONFIG_DP8393X=y ++CONFIG_DS1225Y=y ++CONFIG_FITLOADER=y ++CONFIG_SMBIOS=y ++ ++CONFIG_PCIE_PORT=y ++CONFIG_I82801B11=y ++CONFIG_XIO3130=y ++CONFIG_PCI_EXPRESS=y ++CONFIG_MSI_NONBROKEN=y ++CONFIG_IOH3420=y ++CONFIG_SD=y ++CONFIG_SDHCI=y ++CONFIG_VIRTFS=y ++CONFIG_VIRTIO_9P=y ++CONFIG_USB_EHCI=y ++CONFIG_USB_EHCI_PCI=y ++CONFIG_USB_EHCI_SYSBUS=y ++CONFIG_USB_STORAGE_BOT=y ++CONFIG_TPM_EMULATOR=y ++CONFIG_TPM_TIS=y ++CONFIG_PLATFORM_BUS=y ++CONFIG_TPM_TIS_SYSBUS=y ++CONFIG_ACPI_LOONGARCH=y ++CONFIG_LS7A_RTC=y +diff --git a/configs/targets/loongarch64-softmmu.mak b/configs/targets/loongarch64-softmmu.mak +new file mode 100644 +index 0000000000..dc5ab39661 +--- /dev/null ++++ b/configs/targets/loongarch64-softmmu.mak +@@ -0,0 +1,4 @@ ++TARGET_ARCH=loongarch64 ++TARGET_SUPPORTS_MTTCG=y ++TARGET_XML_FILES= gdb-xml/loongarch-base64.xml gdb-xml/loongarch-fpu64.xml ++ +diff --git a/disas/loongarch.c b/disas/loongarch.c +new file mode 100644 +index 0000000000..14dd131e2e +--- /dev/null ++++ b/disas/loongarch.c +@@ -0,0 +1,2748 @@ ++/* ++ * QEMU Loongarch Disassembler ++ * ++ * Copyright (c) 2020-2021. ++ * Author: Song Gao, gaosong@loongson.cn ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms and conditions of the GNU General Public License, ++ * version 2 or later, as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program. If not, see . ++ */ ++ ++#include "qemu/osdep.h" ++#include "disas/dis-asm.h" ++ ++#define INSNLEN 4 ++ ++/* types */ ++ ++typedef uint16_t la_opcode; ++ ++/* enums */ ++ ++typedef enum { ++ la_op_illegal = 0, ++ la_op_gr2scr = 1, ++ la_op_scr2gr = 2, ++ la_op_clo_w = 3, ++ la_op_clz_w = 4, ++ la_op_cto_w = 5, ++ la_op_ctz_w = 6, ++ la_op_clo_d = 7, ++ la_op_clz_d = 8, ++ la_op_cto_d = 9, ++ la_op_ctz_d = 10, ++ la_op_revb_2h = 11, ++ la_op_revb_4h = 12, ++ la_op_revb_2w = 13, ++ la_op_revb_d = 14, ++ la_op_revh_2w = 15, ++ la_op_revh_d = 16, ++ la_op_bitrev_4b = 17, ++ la_op_bitrev_8b = 18, ++ la_op_bitrev_w = 19, ++ la_op_bitrev_d = 20, ++ la_op_ext_w_h = 21, ++ la_op_ext_w_b = 22, ++ la_op_rdtime_d = 23, ++ la_op_cpucfg = 24, ++ la_op_asrtle_d = 25, ++ la_op_asrtgt_d = 26, ++ la_op_alsl_w = 27, ++ la_op_alsl_wu = 28, ++ la_op_bytepick_w = 29, ++ la_op_bytepick_d = 30, ++ la_op_add_w = 31, ++ la_op_add_d = 32, ++ la_op_sub_w = 33, ++ la_op_sub_d = 34, ++ la_op_slt = 35, ++ la_op_sltu = 36, ++ la_op_maskeqz = 37, ++ la_op_masknez = 38, ++ la_op_nor = 39, ++ la_op_and = 40, ++ la_op_or = 41, ++ la_op_xor = 42, ++ la_op_orn = 43, ++ la_op_andn = 44, ++ la_op_sll_w = 45, ++ la_op_srl_w = 46, ++ la_op_sra_w = 47, ++ la_op_sll_d = 48, ++ la_op_srl_d = 49, ++ la_op_sra_d = 50, ++ la_op_rotr_w = 51, ++ la_op_rotr_d = 52, ++ la_op_mul_w = 53, ++ la_op_mulh_w = 54, ++ la_op_mulh_wu = 55, ++ la_op_mul_d = 56, ++ la_op_mulh_d = 57, ++ la_op_mulh_du = 58, ++ la_op_mulw_d_w = 59, ++ la_op_mulw_d_wu = 60, ++ la_op_div_w = 61, ++ la_op_mod_w = 62, ++ la_op_div_wu = 63, ++ la_op_mod_wu = 64, ++ la_op_div_d = 65, ++ la_op_mod_d = 66, ++ la_op_div_du = 67, ++ la_op_mod_du = 68, ++ la_op_crc_w_b_w = 69, ++ la_op_crc_w_h_w = 70, ++ la_op_crc_w_w_w = 71, ++ la_op_crc_w_d_w = 72, ++ la_op_crcc_w_b_w = 73, ++ la_op_crcc_w_h_w = 74, ++ la_op_crcc_w_w_w = 75, ++ la_op_crcc_w_d_w = 76, ++ la_op_break = 77, ++ la_op_dbcl = 78, ++ la_op_syscall = 79, ++ la_op_alsl_d = 80, ++ la_op_slli_w = 81, ++ la_op_slli_d = 82, ++ la_op_srli_w = 83, ++ la_op_srli_d = 84, ++ la_op_srai_w = 85, ++ la_op_srai_d = 86, ++ la_op_rotri_w = 87, ++ la_op_rotri_d = 88, ++ la_op_bstrins_w = 89, ++ la_op_bstrpick_w = 90, ++ la_op_bstrins_d = 91, ++ la_op_bstrpick_d = 92, ++ la_op_fadd_s = 93, ++ la_op_fadd_d = 94, ++ la_op_fsub_s = 95, ++ la_op_fsub_d = 96, ++ la_op_fmul_s = 97, ++ la_op_fmul_d = 98, ++ la_op_fdiv_s = 99, ++ la_op_fdiv_d = 100, ++ la_op_fmax_s = 101, ++ la_op_fmax_d = 102, ++ la_op_fmin_s = 103, ++ la_op_fmin_d = 104, ++ la_op_fmaxa_s = 105, ++ la_op_fmaxa_d = 106, ++ la_op_fmina_s = 107, ++ la_op_fmina_d = 108, ++ la_op_fscaleb_s = 109, ++ la_op_fscaleb_d = 110, ++ la_op_fcopysign_s = 111, ++ la_op_fcopysign_d = 112, ++ la_op_fabs_s = 113, ++ la_op_fabs_d = 114, ++ la_op_fneg_s = 115, ++ la_op_fneg_d = 116, ++ la_op_flogb_s = 117, ++ la_op_flogb_d = 118, ++ la_op_fclass_s = 119, ++ la_op_fclass_d = 120, ++ la_op_fsqrt_s = 121, ++ la_op_fsqrt_d = 122, ++ la_op_frecip_s = 123, ++ la_op_frecip_d = 124, ++ la_op_frsqrt_s = 125, ++ la_op_frsqrt_d = 126, ++ la_op_fmov_s = 127, ++ la_op_fmov_d = 128, ++ la_op_movgr2fr_w = 129, ++ la_op_movgr2fr_d = 130, ++ la_op_movgr2frh_w = 131, ++ la_op_movfr2gr_s = 132, ++ la_op_movfr2gr_d = 133, ++ la_op_movfrh2gr_s = 134, ++ la_op_movgr2fcsr = 135, ++ la_op_movfcsr2gr = 136, ++ la_op_movfr2cf = 137, ++ la_op_movcf2fr = 138, ++ la_op_movgr2cf = 139, ++ la_op_movcf2gr = 140, ++ la_op_fcvt_s_d = 141, ++ la_op_fcvt_d_s = 142, ++ ++ la_op_ftintrm_w_s = 143, ++ la_op_ftintrm_w_d = 144, ++ la_op_ftintrm_l_s = 145, ++ la_op_ftintrm_l_d = 146, ++ la_op_ftintrp_w_s = 147, ++ la_op_ftintrp_w_d = 148, ++ la_op_ftintrp_l_s = 149, ++ la_op_ftintrp_l_d = 150, ++ la_op_ftintrz_w_s = 151, ++ la_op_ftintrz_w_d = 152, ++ la_op_ftintrz_l_s = 153, ++ la_op_ftintrz_l_d = 154, ++ la_op_ftintrne_w_s = 155, ++ la_op_ftintrne_w_d = 156, ++ la_op_ftintrne_l_s = 157, ++ la_op_ftintrne_l_d = 158, ++ la_op_ftint_w_s = 159, ++ la_op_ftint_w_d = 160, ++ la_op_ftint_l_s = 161, ++ la_op_ftint_l_d = 162, ++ la_op_ffint_s_w = 163, ++ la_op_ffint_s_l = 164, ++ la_op_ffint_d_w = 165, ++ la_op_ffint_d_l = 166, ++ la_op_frint_s = 167, ++ la_op_frint_d = 168, ++ ++ la_op_slti = 169, ++ la_op_sltui = 170, ++ la_op_addi_w = 171, ++ la_op_addi_d = 172, ++ la_op_lu52i_d = 173, ++ la_op_addi = 174, ++ la_op_ori = 175, ++ la_op_xori = 176, ++ ++ la_op_csrxchg = 177, ++ la_op_cacop = 178, ++ la_op_lddir = 179, ++ la_op_ldpte = 180, ++ la_op_iocsrrd_b = 181, ++ la_op_iocsrrd_h = 182, ++ la_op_iocsrrd_w = 183, ++ la_op_iocsrrd_d = 184, ++ la_op_iocsrwr_b = 185, ++ la_op_iocsrwr_h = 186, ++ la_op_iocsrwr_w = 187, ++ la_op_iocsrwr_d = 188, ++ la_op_tlbclr = 189, ++ la_op_tlbflush = 190, ++ la_op_tlbsrch = 191, ++ la_op_tlbrd = 192, ++ la_op_tlbwr = 193, ++ la_op_tlbfill = 194, ++ la_op_ertn = 195, ++ la_op_idle = 196, ++ la_op_invtlb = 197, ++ ++ la_op_fmadd_s = 198, ++ la_op_fmadd_d = 199, ++ la_op_fmsub_s = 200, ++ la_op_fmsub_d = 201, ++ la_op_fnmadd_s = 202, ++ la_op_fnmadd_d = 203, ++ la_op_fnmsub_s = 204, ++ la_op_fnmsub_d = 205, ++ la_op_fcmp_cond_s = 206, ++ la_op_fcmp_cond_d = 207, ++ la_op_fsel = 208, ++ la_op_addu16i_d = 209, ++ la_op_lu12i_w = 210, ++ la_op_lu32i_d = 211, ++ la_op_pcaddi = 212, ++ la_op_pcalau12i = 213, ++ la_op_pcaddu12i = 214, ++ la_op_pcaddu18i = 215, ++ ++ la_op_ll_w = 216, ++ la_op_sc_w = 217, ++ la_op_ll_d = 218, ++ la_op_sc_d = 219, ++ la_op_ldptr_w = 220, ++ la_op_stptr_w = 221, ++ la_op_ldptr_d = 222, ++ la_op_stptr_d = 223, ++ la_op_ld_b = 224, ++ la_op_ld_h = 225, ++ la_op_ld_w = 226, ++ la_op_ld_d = 227, ++ la_op_st_b = 228, ++ la_op_st_h = 229, ++ la_op_st_w = 230, ++ la_op_st_d = 231, ++ la_op_ld_bu = 232, ++ la_op_ld_hu = 233, ++ la_op_ld_wu = 234, ++ la_op_preld = 235, ++ la_op_fld_s = 236, ++ la_op_fst_s = 237, ++ la_op_fld_d = 238, ++ la_op_fst_d = 239, ++ la_op_ldl_w = 240, ++ la_op_ldr_w = 241, ++ la_op_ldl_d = 242, ++ la_op_ldr_d = 243, ++ la_op_stl_d = 244, ++ la_op_str_d = 245, ++ la_op_ldx_b = 246, ++ la_op_ldx_h = 247, ++ la_op_ldx_w = 248, ++ la_op_ldx_d = 249, ++ la_op_stx_b = 250, ++ la_op_stx_h = 251, ++ la_op_stx_w = 252, ++ la_op_stx_d = 253, ++ la_op_ldx_bu = 254, ++ la_op_ldx_hu = 255, ++ la_op_ldx_wu = 256, ++ la_op_fldx_s = 257, ++ la_op_fldx_d = 258, ++ la_op_fstx_s = 259, ++ la_op_fstx_d = 260, ++ ++ la_op_amswap_w = 261, ++ la_op_amswap_d = 262, ++ la_op_amadd_w = 263, ++ la_op_amadd_d = 264, ++ la_op_amand_w = 265, ++ la_op_amand_d = 266, ++ la_op_amor_w = 267, ++ la_op_amor_d = 268, ++ la_op_amxor_w = 269, ++ la_op_amxor_d = 270, ++ la_op_ammax_w = 271, ++ la_op_ammax_d = 272, ++ la_op_ammin_w = 273, ++ la_op_ammin_d = 274, ++ la_op_ammax_wu = 275, ++ la_op_ammax_du = 276, ++ la_op_ammin_wu = 277, ++ la_op_ammin_du = 278, ++ la_op_amswap_db_w = 279, ++ la_op_amswap_db_d = 280, ++ la_op_amadd_db_w = 281, ++ la_op_amadd_db_d = 282, ++ la_op_amand_db_w = 283, ++ la_op_amand_db_d = 284, ++ la_op_amor_db_w = 285, ++ la_op_amor_db_d = 286, ++ la_op_amxor_db_w = 287, ++ la_op_amxor_db_d = 288, ++ la_op_ammax_db_w = 289, ++ la_op_ammax_db_d = 290, ++ la_op_ammin_db_w = 291, ++ la_op_ammin_db_d = 292, ++ la_op_ammax_db_wu = 293, ++ la_op_ammax_db_du = 294, ++ la_op_ammin_db_wu = 295, ++ la_op_ammin_db_du = 296, ++ la_op_dbar = 297, ++ la_op_ibar = 298, ++ la_op_fldgt_s = 299, ++ la_op_fldgt_d = 300, ++ la_op_fldle_s = 301, ++ la_op_fldle_d = 302, ++ la_op_fstgt_s = 303, ++ la_op_fstgt_d = 304, ++ ls_op_fstle_s = 305, ++ la_op_fstle_d = 306, ++ la_op_ldgt_b = 307, ++ la_op_ldgt_h = 308, ++ la_op_ldgt_w = 309, ++ la_op_ldgt_d = 310, ++ la_op_ldle_b = 311, ++ la_op_ldle_h = 312, ++ la_op_ldle_w = 313, ++ la_op_ldle_d = 314, ++ la_op_stgt_b = 315, ++ la_op_stgt_h = 316, ++ la_op_stgt_w = 317, ++ la_op_stgt_d = 318, ++ la_op_stle_b = 319, ++ la_op_stle_h = 320, ++ la_op_stle_w = 321, ++ la_op_stle_d = 322, ++ la_op_beqz = 323, ++ la_op_bnez = 324, ++ la_op_bceqz = 325, ++ la_op_bcnez = 326, ++ la_op_jirl = 327, ++ la_op_b = 328, ++ la_op_bl = 329, ++ la_op_beq = 330, ++ la_op_bne = 331, ++ la_op_blt = 332, ++ la_op_bge = 333, ++ la_op_bltu = 334, ++ la_op_bgeu = 335, ++ ++ /* vz insn */ ++ la_op_hvcl = 336, ++ ++} la_op; ++ ++typedef enum { ++ la_codec_illegal, ++ la_codec_empty, ++ la_codec_2r, ++ la_codec_2r_u5, ++ la_codec_2r_u6, ++ la_codec_2r_2bw, ++ la_codec_2r_2bd, ++ la_codec_3r, ++ la_codec_3r_rd0, ++ la_codec_3r_sa2, ++ la_codec_3r_sa3, ++ la_codec_4r, ++ la_codec_r_im20, ++ la_codec_2r_im16, ++ la_codec_2r_im14, ++ la_codec_2r_im12, ++ la_codec_im5_r_im12, ++ la_codec_2r_im8, ++ la_codec_r_sd, ++ la_codec_r_sj, ++ la_codec_r_cd, ++ la_codec_r_cj, ++ la_codec_r_seq, ++ la_codec_code, ++ la_codec_whint, ++ la_codec_invtlb, ++ la_codec_r_ofs21, ++ la_codec_cj_ofs21, ++ la_codec_ofs26, ++ la_codec_cond, ++ la_codec_sel, ++ ++} la_codec; ++ ++#define la_fmt_illegal "nte" ++#define la_fmt_empty "nt" ++#define la_fmt_sd_rj "ntA,1" ++#define la_fmt_rd_sj "nt0,B" ++#define la_fmt_rd_rj "nt0,1" ++#define la_fmt_rj_rk "nt1,2" ++#define la_fmt_rj_seq "nt1,x" ++#define la_fmt_rd_si20 "nt0,i(x)" ++#define la_fmt_rd_rj_ui5 "nt0,1,C" ++#define la_fmt_rd_rj_ui6 "nt0,1.C" ++#define la_fmt_rd_rj_level "nt0,1,x" ++#define la_fmt_rd_rj_msbw_lsbw "nt0,1,C,D" ++#define la_fmt_rd_rj_msbd_lsbd "nt0,1,C,D" ++#define la_fmt_rd_rj_si12 "nt0,1,i(x)" ++#define la_fmt_hint_rj_si12 "ntE,1,i(x)" ++#define la_fmt_rd_rj_csr "nt0,1,x" ++#define la_fmt_rd_rj_si14 "nt0,1,i(x)" ++#define la_fmt_rd_rj_si16 "nt0,1,i(x)" ++#define la_fmt_rd_rj_rk "nt0,1,2" ++#define la_fmt_fd_rj_rk "nt3,1,2" ++#define la_fmt_rd_rj_rk_sa2 "nt0,1,2,D" ++#define la_fmt_rd_rj_rk_sa3 "nt0,1,2,D" ++#define la_fmt_fd_rj "nt3,1" ++#define la_fmt_rd_fj "nt0,4" ++#define la_fmt_fd_fj "nt3,4" ++#define la_fmt_fd_fj_si12 "nt3,4,i(x)" ++#define la_fmt_fcsrd_rj "ntF,1" ++#define la_fmt_rd_fcsrs "nt0,G" ++#define la_fmt_cd_fj "ntH,4" ++#define la_fmt_fd_cj "nt3,I" ++#define la_fmt_fd_fj_fk "nt3,4,5" ++#define la_fmt_code "ntJ" ++#define la_fmt_whint "ntx" ++#define la_fmt_invtlb "ntx,1,2" /* op,rj,rk */ ++#define la_fmt_offs26 "nto(X)p" ++#define la_fmt_rj_offs21 "nt1,o(X)p" ++#define la_fmt_cj_offs21 "ntQ,o(X)p" ++#define la_fmt_rd_rj_offs16 "nt0,1,o(X)" ++#define la_fmt_rj_rd_offs16 "nt1,0,o(X)p" ++#define la_fmt_s_cd_fj_fk "K.stH,4,5" ++#define la_fmt_d_cd_fj_fk "K.dtH,4,5" ++#define la_fmt_fd_fj_fk_fa "nt3,4,5,6" ++#define la_fmt_fd_fj_fk_ca "nt3,4,5,L" ++#define la_fmt_cop_rj_si12 "ntM,1,i(x)" ++ ++/* structures */ ++ ++typedef struct { ++ uint32_t pc; ++ uint32_t insn; ++ int32_t imm; ++ int32_t imm2; ++ uint16_t op; ++ uint16_t code; ++ uint8_t codec; ++ uint8_t r1; ++ uint8_t r2; ++ uint8_t r3; ++ uint8_t r4; ++ uint8_t bit; ++} la_decode; ++ ++typedef struct { ++ const char * const name; ++ const la_codec codec; ++ const char * const format; ++} la_opcode_data; ++ ++/* reg names */ ++ ++const char * const loongarch_r_normal_name[32] = { ++ "$r0", "$r1", "$r2", "$r3", "$r4", "$r5", "$r6", "$r7", ++ "$r8", "$r9", "$r10", "$r11", "$r12", "$r13", "$r14", "$r15", ++ "$r16", "$r17", "$r18", "$r19", "$r20", "$r21", "$r22", "$r23", ++ "$r24", "$r25", "$r26", "$r27", "$r28", "$r29", "$r30", "$r31", ++}; ++ ++const char * const loongarch_f_normal_name[32] = { ++ "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7", ++ "$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15", ++ "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23", ++ "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31", ++}; ++ ++const char * const loongarch_cr_normal_name[4] = { ++ "$scr0", "$scr1", "$scr2", "$scr3", ++}; ++ ++const char * const loongarch_c_normal_name[8] = { ++ "$fcc0", "$fcc1", "$fcc2", "$fcc3", "$fcc4", "$fcc5", "$fcc6", "$fcc7", ++}; ++ ++/* instruction data */ ++ ++const la_opcode_data opcode_data[] = { ++ { "illegal", la_codec_illegal, la_fmt_illegal }, ++ { "gr2scr", la_codec_r_sd, la_fmt_sd_rj }, ++ { "scr2gr", la_codec_r_sj, la_fmt_rd_sj }, ++ { "clo.w", la_codec_2r, la_fmt_rd_rj }, ++ { "clz.w", la_codec_2r, la_fmt_rd_rj }, ++ { "cto.w", la_codec_2r, la_fmt_rd_rj }, ++ { "ctz.w", la_codec_2r, la_fmt_rd_rj }, ++ { "clo.d", la_codec_2r, la_fmt_rd_rj }, ++ { "clz.d", la_codec_2r, la_fmt_rd_rj }, ++ { "cto.d", la_codec_2r, la_fmt_rd_rj }, ++ { "ctz_d", la_codec_2r, la_fmt_rd_rj }, ++ { "revb.2h", la_codec_2r, la_fmt_rd_rj }, ++ { "revb.4h", la_codec_2r, la_fmt_rd_rj }, ++ { "revb.2w", la_codec_2r, la_fmt_rd_rj }, ++ { "revb.d", la_codec_2r, la_fmt_rd_rj }, ++ { "revh.2w", la_codec_2r, la_fmt_rd_rj }, ++ { "revh.d", la_codec_2r, la_fmt_rd_rj }, ++ { "bitrev.4b", la_codec_2r, la_fmt_rd_rj }, ++ { "bitrev.8b", la_codec_2r, la_fmt_rd_rj }, ++ { "bitrev.w", la_codec_2r, la_fmt_rd_rj }, ++ { "bitrev.d", la_codec_2r, la_fmt_rd_rj }, ++ { "ext.w.h", la_codec_2r, la_fmt_rd_rj }, ++ { "ext.w.b", la_codec_2r, la_fmt_rd_rj }, ++ { "rdtime.d", la_codec_2r, la_fmt_rd_rj }, ++ { "cpucfg", la_codec_2r, la_fmt_rd_rj }, ++ { "asrtle.d", la_codec_3r_rd0, la_fmt_rj_rk }, ++ { "asrtgt.d", la_codec_3r_rd0, la_fmt_rj_rk }, ++ { "alsl.w", la_codec_3r_sa2, la_fmt_rd_rj_rk_sa2 }, ++ { "alsl.wu", la_codec_3r_sa2, la_fmt_rd_rj_rk_sa2 }, ++ { "bytepick.w", la_codec_3r_sa2, la_fmt_rd_rj_rk_sa2 }, ++ { "bytepick.d", la_codec_3r_sa3, la_fmt_rd_rj_rk_sa3 }, ++ { "add.w", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "add.d", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "sub.w", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "sub.d", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "slt", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "sltu", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "maskeqz", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "masknez", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "nor", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "and", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "or", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "xor", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "orn", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "andn", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "sll.w", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "srl.w", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "sra.w", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "sll.d", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "srl.d", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "sra.d", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "rotr.w", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "rotr.d", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "mul.w", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "mulh.w", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "mulh.wu", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "mul.d", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "mulh.d", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "mulh.du", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "mulw.d.w", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "mulw.d.wu", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "div.w", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "mod.w", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "div.wu", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "mod.wu", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "div.d", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "mod.d", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "div.du", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "mod.du", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "crc.w.b.w", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "crc.w.h.w", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "crc.w.w.w", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "crc.w.d.w", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "crcc.w.b.w", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "crcc.w.h.w", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "crcc.w.w.w", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "crcc.w.d.w", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "break", la_codec_code, la_fmt_code }, ++ { "dbcl", la_codec_code, la_fmt_code }, ++ { "syscall", la_codec_code, la_fmt_code }, ++ { "alsl.d", la_codec_3r_sa2, la_fmt_rd_rj_rk_sa2 }, ++ { "slli.w", la_codec_2r_u5, la_fmt_rd_rj_ui5 }, ++ { "slli.d", la_codec_2r_u6, la_fmt_rd_rj_ui6 }, ++ { "srli.w", la_codec_2r_u5, la_fmt_rd_rj_ui5 }, ++ { "srli.d", la_codec_2r_u6, la_fmt_rd_rj_ui6 }, ++ { "srai.w", la_codec_2r_u5, la_fmt_rd_rj_ui5 }, ++ { "srai.d", la_codec_2r_u6, la_fmt_rd_rj_ui6 }, ++ { "rotri.w", la_codec_2r_u5, la_fmt_rd_rj_ui5 }, ++ { "rotri.d", la_codec_2r_u6, la_fmt_rd_rj_ui6 }, ++ { "bstrins.w", la_codec_2r_2bw, la_fmt_rd_rj_msbw_lsbw }, ++ { "bstrpick.w", la_codec_2r_2bw, la_fmt_rd_rj_msbw_lsbw }, ++ { "bstrins.d", la_codec_2r_2bd, la_fmt_rd_rj_msbd_lsbd }, ++ { "bstrpick.d", la_codec_2r_2bd, la_fmt_rd_rj_msbd_lsbd }, ++ { "fadd.s", la_codec_3r, la_fmt_fd_fj_fk }, ++ { "fadd.d", la_codec_3r, la_fmt_fd_fj_fk }, ++ { "fsub.s", la_codec_3r, la_fmt_fd_fj_fk }, ++ { "fsub.d", la_codec_3r, la_fmt_fd_fj_fk }, ++ { "fmul.s", la_codec_3r, la_fmt_fd_fj_fk }, ++ { "fmul.d", la_codec_3r, la_fmt_fd_fj_fk }, ++ { "fdiv.s", la_codec_3r, la_fmt_fd_fj_fk }, ++ { "fdiv.d", la_codec_3r, la_fmt_fd_fj_fk }, ++ { "fmax.s", la_codec_3r, la_fmt_fd_fj_fk }, ++ { "fmax.d", la_codec_3r, la_fmt_fd_fj_fk }, ++ { "fmin.s", la_codec_3r, la_fmt_fd_fj_fk }, ++ { "fmin.d", la_codec_3r, la_fmt_fd_fj_fk }, ++ { "fmaxa.s", la_codec_3r, la_fmt_fd_fj_fk }, ++ { "fmaxa.d", la_codec_3r, la_fmt_fd_fj_fk }, ++ { "fmina.s", la_codec_3r, la_fmt_fd_fj_fk }, ++ { "fmina.d", la_codec_3r, la_fmt_fd_fj_fk }, ++ { "fscaleb.s", la_codec_3r, la_fmt_fd_fj_fk }, ++ { "fscaleb.d", la_codec_3r, la_fmt_fd_fj_fk }, ++ { "fcopysign.s", la_codec_3r, la_fmt_fd_fj_fk }, ++ { "fcopysign.d", la_codec_3r, la_fmt_fd_fj_fk }, ++ { "fabs.s", la_codec_2r, la_fmt_fd_fj }, ++ { "fabs.d", la_codec_2r, la_fmt_fd_fj }, ++ { "fneg.s", la_codec_2r, la_fmt_fd_fj }, ++ { "fneg.d", la_codec_2r, la_fmt_fd_fj }, ++ { "flogb.s", la_codec_2r, la_fmt_fd_fj }, ++ { "flogb.d", la_codec_2r, la_fmt_fd_fj }, ++ { "fclass.s", la_codec_2r, la_fmt_fd_fj }, ++ { "fclass.d", la_codec_2r, la_fmt_fd_fj }, ++ { "fsqrt.s", la_codec_2r, la_fmt_fd_fj }, ++ { "fsqrt.d", la_codec_2r, la_fmt_fd_fj }, ++ { "frecip.s", la_codec_2r, la_fmt_fd_fj }, ++ { "frecip.d", la_codec_2r, la_fmt_fd_fj }, ++ { "frsqrt.s", la_codec_2r, la_fmt_fd_fj }, ++ { "frsqrt.d", la_codec_2r, la_fmt_fd_fj }, ++ { "fmov.s", la_codec_2r, la_fmt_fd_fj }, ++ { "fmov.d", la_codec_2r, la_fmt_fd_fj }, ++ { "movgr2fr.w", la_codec_2r, la_fmt_fd_rj }, ++ { "movgr2fr.d", la_codec_2r, la_fmt_fd_rj }, ++ { "movgr2frh.w", la_codec_2r, la_fmt_fd_rj }, ++ { "movfr2gr.s", la_codec_2r, la_fmt_rd_fj }, ++ { "movfr2gr.d", la_codec_2r, la_fmt_rd_fj }, ++ { "movfrh2gr.s", la_codec_2r, la_fmt_rd_fj }, ++ { "movgr2fcsr", la_codec_2r, la_fmt_fcsrd_rj }, ++ { "movfcsr2gr", la_codec_2r, la_fmt_rd_fcsrs }, ++ { "movfr2cf", la_codec_r_cd, la_fmt_cd_fj }, ++ { "movcf2fr", la_codec_r_cj, la_fmt_fd_cj }, ++ { "movgr2cf", la_codec_r_cd, la_fmt_cd_fj }, ++ { "movcf2gr", la_codec_r_cj, la_fmt_fd_cj }, ++ { "fcvt.s.d", la_codec_2r, la_fmt_fd_fj }, ++ { "fcvt.d.s", la_codec_2r, la_fmt_fd_fj }, ++ { "ftintrm.w.s", la_codec_2r, la_fmt_fd_fj }, ++ { "ftintrm.w.d", la_codec_2r, la_fmt_fd_fj }, ++ { "ftintrm.l.s", la_codec_2r, la_fmt_fd_fj }, ++ { "ftintrm.l.d", la_codec_2r, la_fmt_fd_fj }, ++ { "ftintrp.w.s", la_codec_2r, la_fmt_fd_fj }, ++ { "ftintrp.w.d", la_codec_2r, la_fmt_fd_fj }, ++ { "ftintrp.l.s", la_codec_2r, la_fmt_fd_fj }, ++ { "ftintrp.l.d", la_codec_2r, la_fmt_fd_fj }, ++ { "ftintrz.w.s", la_codec_2r, la_fmt_fd_fj }, ++ { "ftintrz.w.d", la_codec_2r, la_fmt_fd_fj }, ++ { "ftintrz.l.s", la_codec_2r, la_fmt_fd_fj }, ++ { "ftintrz.l.d", la_codec_2r, la_fmt_fd_fj }, ++ { "ftintrne.w.s", la_codec_2r, la_fmt_fd_fj }, ++ { "ftintrne.w.d", la_codec_2r, la_fmt_fd_fj }, ++ { "ftintrne.l.s", la_codec_2r, la_fmt_fd_fj }, ++ { "ftintrne.l.d", la_codec_2r, la_fmt_fd_fj }, ++ { "ftint.w.s", la_codec_2r, la_fmt_fd_fj }, ++ { "ftint.w.d", la_codec_2r, la_fmt_fd_fj }, ++ { "ftint.l.s", la_codec_2r, la_fmt_fd_fj }, ++ { "ftint.l.d", la_codec_2r, la_fmt_fd_fj }, ++ { "ffint.s.w", la_codec_2r, la_fmt_fd_fj }, ++ { "ffint.s.l", la_codec_2r, la_fmt_fd_fj }, ++ { "ffint.d.w", la_codec_2r, la_fmt_fd_fj }, ++ { "ffint.d.l", la_codec_2r, la_fmt_fd_fj }, ++ { "frint.s", la_codec_2r, la_fmt_fd_fj }, ++ { "frint.d", la_codec_2r, la_fmt_fd_fj }, ++ { "slti", la_codec_2r_im12, la_fmt_rd_rj_si12 }, ++ { "sltui", la_codec_2r_im12, la_fmt_rd_rj_si12 }, ++ { "addi.w", la_codec_2r_im12, la_fmt_rd_rj_si12 }, ++ { "addi.d", la_codec_2r_im12, la_fmt_rd_rj_si12 }, ++ { "lu52i.d", la_codec_2r_im12, la_fmt_rd_rj_si12 }, ++ { "addi", la_codec_2r_im12, la_fmt_rd_rj_si12 }, ++ { "ori", la_codec_2r_im12, la_fmt_rd_rj_si12 }, ++ { "xori", la_codec_2r_im12, la_fmt_rd_rj_si12 }, ++ { "csrxchg", la_codec_2r_im14, la_fmt_rd_rj_csr }, ++ { "cacop", la_codec_im5_r_im12, la_fmt_cop_rj_si12 }, ++ { "lddir", la_codec_2r_im8, la_fmt_rd_rj_level }, ++ { "ldpte", la_codec_r_seq, la_fmt_rj_seq }, ++ { "iocsrrd.b", la_codec_2r, la_fmt_rd_rj }, ++ { "iocsrrd.h", la_codec_2r, la_fmt_rd_rj }, ++ { "iocsrrd.w", la_codec_2r, la_fmt_rd_rj }, ++ { "iocsrrd.d", la_codec_2r, la_fmt_rd_rj }, ++ { "iocsrwr.b", la_codec_2r, la_fmt_rd_rj }, ++ { "iocsrwr.h", la_codec_2r, la_fmt_rd_rj }, ++ { "iocsrwr.w", la_codec_2r, la_fmt_rd_rj }, ++ { "iocsrwr.d", la_codec_2r, la_fmt_rd_rj }, ++ { "tlbclr", la_codec_empty, la_fmt_empty }, ++ { "tlbflush", la_codec_empty, la_fmt_empty }, ++ { "tlbsrch", la_codec_empty, la_fmt_empty }, ++ { "tlbrd", la_codec_empty, la_fmt_empty }, ++ { "tlbwr", la_codec_empty, la_fmt_empty }, ++ { "tlbfill", la_codec_empty, la_fmt_empty }, ++ { "ertn", la_codec_empty, la_fmt_empty }, ++ { "idle", la_codec_whint, la_fmt_whint }, ++ { "invtlb", la_codec_invtlb, la_fmt_invtlb }, ++ { "fmadd.s", la_codec_4r, la_fmt_fd_fj_fk_fa }, ++ { "fmadd.d", la_codec_4r, la_fmt_fd_fj_fk_fa }, ++ { "fmsub.s", la_codec_4r, la_fmt_fd_fj_fk_fa }, ++ { "fmsub.d", la_codec_4r, la_fmt_fd_fj_fk_fa }, ++ { "fnmadd.s", la_codec_4r, la_fmt_fd_fj_fk_fa }, ++ { "fnmadd.d", la_codec_4r, la_fmt_fd_fj_fk_fa }, ++ { "fnmsub.s", la_codec_4r, la_fmt_fd_fj_fk_fa }, ++ { "fnmsub.d", la_codec_4r, la_fmt_fd_fj_fk_fa }, ++ { "fcmp.cond.s", la_codec_cond, la_fmt_s_cd_fj_fk }, ++ { "fcmp.cond.d", la_codec_cond, la_fmt_d_cd_fj_fk }, ++ { "fsel", la_codec_sel, la_fmt_fd_fj_fk_ca }, ++ { "addu16i.d", la_codec_2r_im16, la_fmt_rd_rj_si16 }, ++ { "lu12i.w", la_codec_r_im20, la_fmt_rd_si20 }, ++ { "lu32i.d", la_codec_r_im20, la_fmt_rd_si20 }, ++ { "pcaddi", la_codec_r_im20, la_fmt_rd_si20 }, ++ { "pcalau12i", la_codec_r_im20, la_fmt_rd_si20 }, ++ { "pcaddu12i", la_codec_r_im20, la_fmt_rd_si20 }, ++ { "pcaddu18i", la_codec_r_im20, la_fmt_rd_si20 }, ++ { "ll.w", la_codec_2r_im14, la_fmt_rd_rj_si14 }, ++ { "sc.w", la_codec_2r_im14, la_fmt_rd_rj_si14 }, ++ { "ll.d", la_codec_2r_im14, la_fmt_rd_rj_si14 }, ++ { "sc.d", la_codec_2r_im14, la_fmt_rd_rj_si14 }, ++ { "ldptr.w", la_codec_2r_im14, la_fmt_rd_rj_si14 }, ++ { "stptr.w", la_codec_2r_im14, la_fmt_rd_rj_si14 }, ++ { "ldptr.d", la_codec_2r_im14, la_fmt_rd_rj_si14 }, ++ { "stptr.d", la_codec_2r_im14, la_fmt_rd_rj_si14 }, ++ { "ld.b", la_codec_2r_im12, la_fmt_rd_rj_si12 }, ++ { "ld.h", la_codec_2r_im12, la_fmt_rd_rj_si12 }, ++ { "ld.w", la_codec_2r_im12, la_fmt_rd_rj_si12 }, ++ { "ld.d", la_codec_2r_im12, la_fmt_rd_rj_si12 }, ++ { "st.b", la_codec_2r_im12, la_fmt_rd_rj_si12 }, ++ { "st.h", la_codec_2r_im12, la_fmt_rd_rj_si12 }, ++ { "st.w", la_codec_2r_im12, la_fmt_rd_rj_si12 }, ++ { "st.d", la_codec_2r_im12, la_fmt_rd_rj_si12 }, ++ { "ld.bu", la_codec_2r_im12, la_fmt_rd_rj_si12 }, ++ { "ld.hu", la_codec_2r_im12, la_fmt_rd_rj_si12 }, ++ { "ld.wu", la_codec_2r_im12, la_fmt_rd_rj_si12 }, ++ { "preld", la_codec_2r_im12, la_fmt_hint_rj_si12 }, ++ { "fld.s", la_codec_2r_im12, la_fmt_fd_fj_si12 }, ++ { "fst.s", la_codec_2r_im12, la_fmt_fd_fj_si12 }, ++ { "fld.d", la_codec_2r_im12, la_fmt_fd_fj_si12 }, ++ { "fst.d", la_codec_2r_im12, la_fmt_fd_fj_si12 }, ++ { "ldl.w", la_codec_2r_im12, la_fmt_rd_rj_si12 }, ++ { "ldr.w", la_codec_2r_im12, la_fmt_rd_rj_si12 }, ++ { "ldl.d", la_codec_2r_im12, la_fmt_rd_rj_si12 }, ++ { "ldr.d", la_codec_2r_im12, la_fmt_rd_rj_si12 }, ++ { "stl.d", la_codec_2r_im12, la_fmt_rd_rj_si12 }, ++ { "str.d", la_codec_2r_im12, la_fmt_rd_rj_si12 }, ++ { "ldx.b", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "ldx.h", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "ldx.w", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "ldx.d", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "stx.b", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "stx.h", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "stx.w", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "stx.d", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "ldx.bu", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "ldx.hu", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "ldx.wu", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "fldx.s", la_codec_3r, la_fmt_fd_rj_rk }, ++ { "fldx.d", la_codec_3r, la_fmt_fd_rj_rk }, ++ { "fstx.s", la_codec_3r, la_fmt_fd_rj_rk }, ++ { "fstx.d", la_codec_3r, la_fmt_fd_rj_rk }, ++ { "amswap.w", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "amswap.d", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "amadd.w", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "amadd.d", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "amand.w", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "amand.d", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "amor.w", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "amor.d", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "amxor.w", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "amxor.d", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "ammax.w", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "ammax.d", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "ammin.w", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "ammin.d", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "ammax.wu", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "ammax.du", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "ammin.wu", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "ammin.du", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "amswap.db.w", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "amswap.db.d", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "amadd.db.w", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "amadd.db.d", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "amand.db.w", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "amand.db.d", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "amor.db.w", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "amor.db.d", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "amxor.db.w", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "amxor.db.d", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "ammax.db.w", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "ammax.db.d", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "ammin.db.w", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "ammin.db.d", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "ammax.db.wu", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "ammax.db.du", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "ammin.db.wu", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "ammin.db.du", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "dbar", la_codec_whint, la_fmt_whint }, ++ { "ibar", la_codec_whint, la_fmt_whint }, ++ { "fldgt.s", la_codec_3r, la_fmt_fd_rj_rk }, ++ { "fldgt.d", la_codec_3r, la_fmt_fd_rj_rk }, ++ { "fldle.s", la_codec_3r, la_fmt_fd_rj_rk }, ++ { "fldle.d", la_codec_3r, la_fmt_fd_rj_rk }, ++ { "fstgt.s", la_codec_3r, la_fmt_fd_rj_rk }, ++ { "fstgt.d", la_codec_3r, la_fmt_fd_rj_rk }, ++ { "fstle.s", la_codec_3r, la_fmt_fd_rj_rk }, ++ { "fstle.d", la_codec_3r, la_fmt_fd_rj_rk }, ++ { "ldgt.b", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "ldgt.h", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "ldgt.w", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "ldgt.d", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "ldle.b", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "ldle.h", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "ldle.w", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "ldle.d", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "stgt.b", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "stgt.h", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "stgt.w", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "stgt.d", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "stle.b", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "stle.h", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "stle.w", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "stle.d", la_codec_3r, la_fmt_rd_rj_rk }, ++ { "beqz", la_codec_r_ofs21, la_fmt_rj_offs21 }, ++ { "bnez", la_codec_r_ofs21, la_fmt_rj_offs21 }, ++ { "bceqz", la_codec_cj_ofs21, la_fmt_cj_offs21 }, ++ { "bcnez", la_codec_cj_ofs21, la_fmt_cj_offs21 }, ++ { "jirl", la_codec_2r_im16, la_fmt_rd_rj_offs16 }, ++ { "b", la_codec_ofs26, la_fmt_offs26 }, ++ { "bl", la_codec_ofs26, la_fmt_offs26 }, ++ { "beq", la_codec_2r_im16, la_fmt_rj_rd_offs16 }, ++ { "bne", la_codec_2r_im16, la_fmt_rj_rd_offs16 }, ++ { "blt", la_codec_2r_im16, la_fmt_rj_rd_offs16 }, ++ { "bge", la_codec_2r_im16, la_fmt_rj_rd_offs16 }, ++ { "bltu", la_codec_2r_im16, la_fmt_rj_rd_offs16 }, ++ { "bgeu", la_codec_2r_im16, la_fmt_rj_rd_offs16 }, ++ ++ /* vz insn */ ++ { "hvcl", la_codec_code, la_fmt_code }, ++ ++}; ++ ++ ++/* decode opcode */ ++ ++static void decode_insn_opcode(la_decode *dec) ++{ ++ uint32_t insn = dec->insn; ++ uint16_t op = la_op_illegal; ++ switch ((insn >> 26) & 0x3f) { ++ case 0x0: ++ switch ((insn >> 22) & 0xf) { ++ case 0x0: ++ switch ((insn >> 18) & 0xf) { ++ case 0x0: ++ switch ((insn >> 15) & 0x7) { ++ case 0x0: ++ switch ((insn >> 10) & 0x1f) { ++ case 0x2: ++ switch ((insn >> 2) & 0x7) { ++ case 0x0: ++ op = la_op_gr2scr; ++ break; ++ } ++ break; ++ case 0x3: ++ switch ((insn >> 7) & 0x7) { ++ case 0x0: ++ op = la_op_scr2gr; ++ break; ++ } ++ break; ++ case 0x4: ++ op = la_op_clo_w; ++ break; ++ case 0x5: ++ op = la_op_clz_w; ++ break; ++ case 0x6: ++ op = la_op_cto_w; ++ break; ++ case 0x7: ++ op = la_op_ctz_w; ++ break; ++ case 0x8: ++ op = la_op_clo_d; ++ break; ++ case 0x9: ++ op = la_op_clz_d; ++ break; ++ case 0xa: ++ op = la_op_cto_d; ++ break; ++ case 0xb: ++ op = la_op_ctz_d; ++ break; ++ case 0xc: ++ op = la_op_revb_2h; ++ break; ++ case 0xd: ++ op = la_op_revb_4h; ++ break; ++ case 0xe: ++ op = la_op_revb_2w; ++ break; ++ case 0xf: ++ op = la_op_revb_d; ++ break; ++ case 0x10: ++ op = la_op_revh_2w; ++ break; ++ case 0x11: ++ op = la_op_revh_d; ++ break; ++ case 0x12: ++ op = la_op_bitrev_4b; ++ break; ++ case 0x13: ++ op = la_op_bitrev_8b; ++ break; ++ case 0x14: ++ op = la_op_bitrev_w; ++ break; ++ case 0x15: ++ op = la_op_bitrev_d; ++ break; ++ case 0x16: ++ op = la_op_ext_w_h; ++ break; ++ case 0x17: ++ op = la_op_ext_w_b; ++ break; ++ case 0x1a: ++ op = la_op_rdtime_d; ++ break; ++ case 0x1b: ++ op = la_op_cpucfg; ++ break; ++ } ++ break; ++ case 0x2: ++ switch (insn & 0x0000001f) { ++ case 0x00000000: ++ op = la_op_asrtle_d; ++ break; ++ } ++ break; ++ case 0x3: ++ switch (insn & 0x0000001f) { ++ case 0x00000000: ++ op = la_op_asrtgt_d; ++ break; ++ } ++ break; ++ } ++ break; ++ case 0x1: ++ switch ((insn >> 17) & 0x1) { ++ case 0x0: ++ op = la_op_alsl_w; ++ break; ++ case 0x1: ++ op = la_op_alsl_wu; ++ break; ++ } ++ break; ++ case 0x2: ++ switch ((insn >> 17) & 0x1) { ++ case 0x0: ++ op = la_op_bytepick_w; ++ break; ++ } ++ break; ++ case 0x3: ++ op = la_op_bytepick_d; ++ break; ++ case 0x4: ++ switch ((insn >> 15) & 0x7) { ++ case 0x0: ++ op = la_op_add_w; ++ break; ++ case 0x1: ++ op = la_op_add_d; ++ break; ++ case 0x2: ++ op = la_op_sub_w; ++ break; ++ case 0x3: ++ op = la_op_sub_d; ++ break; ++ case 0x4: ++ op = la_op_slt; ++ break; ++ case 0x5: ++ op = la_op_sltu; ++ break; ++ case 0x6: ++ op = la_op_maskeqz; ++ break; ++ case 0x7: ++ op = la_op_masknez; ++ break; ++ } ++ break; ++ case 0x5: ++ switch ((insn >> 15) & 0x7) { ++ case 0x0: ++ op = la_op_nor; ++ break; ++ case 0x1: ++ op = la_op_and; ++ break; ++ case 0x2: ++ op = la_op_or; ++ break; ++ case 0x3: ++ op = la_op_xor; ++ break; ++ case 0x4: ++ op = la_op_orn; ++ break; ++ case 0x5: ++ op = la_op_andn; ++ break; ++ case 0x6: ++ op = la_op_sll_w; ++ break; ++ case 0x7: ++ op = la_op_srl_w; ++ break; ++ } ++ break; ++ case 0x6: ++ switch ((insn >> 15) & 0x7) { ++ case 0x0: ++ op = la_op_sra_w; ++ break; ++ case 0x1: ++ op = la_op_sll_d; ++ break; ++ case 0x2: ++ op = la_op_srl_d; ++ break; ++ case 0x3: ++ op = la_op_sra_d; ++ break; ++ case 0x6: ++ op = la_op_rotr_w; ++ break; ++ case 0x7: ++ op = la_op_rotr_d; ++ break; ++ } ++ break; ++ case 0x7: ++ switch ((insn >> 15) & 0x7) { ++ case 0x0: ++ op = la_op_mul_w; ++ break; ++ case 0x1: ++ op = la_op_mulh_w; ++ break; ++ case 0x2: ++ op = la_op_mulh_wu; ++ break; ++ case 0x3: ++ op = la_op_mul_d; ++ break; ++ case 0x4: ++ op = la_op_mulh_d; ++ break; ++ case 0x5: ++ op = la_op_mulh_du; ++ break; ++ case 0x6: ++ op = la_op_mulw_d_w; ++ break; ++ case 0x7: ++ op = la_op_mulw_d_wu; ++ break; ++ } ++ break; ++ case 0x8: ++ switch ((insn >> 15) & 0x7) { ++ case 0x0: ++ op = la_op_div_w; ++ break; ++ case 0x1: ++ op = la_op_mod_w; ++ break; ++ case 0x2: ++ op = la_op_div_wu; ++ break; ++ case 0x3: ++ op = la_op_mod_wu; ++ break; ++ case 0x4: ++ op = la_op_div_d; ++ break; ++ case 0x5: ++ op = la_op_mod_d; ++ break; ++ case 0x6: ++ op = la_op_div_du; ++ break; ++ case 0x7: ++ op = la_op_mod_du; ++ break; ++ } ++ break; ++ case 0x9: ++ switch ((insn >> 15) & 0x7) { ++ case 0x0: ++ op = la_op_crc_w_b_w; ++ break; ++ case 0x1: ++ op = la_op_crc_w_h_w; ++ break; ++ case 0x2: ++ op = la_op_crc_w_w_w; ++ break; ++ case 0x3: ++ op = la_op_crc_w_d_w; ++ break; ++ case 0x4: ++ op = la_op_crcc_w_b_w; ++ break; ++ case 0x5: ++ op = la_op_crcc_w_h_w; ++ break; ++ case 0x6: ++ op = la_op_crcc_w_w_w; ++ break; ++ case 0x7: ++ op = la_op_crcc_w_d_w; ++ break; ++ } ++ break; ++ case 0xa: ++ switch ((insn >> 15) & 0x7) { ++ case 0x4: ++ op = la_op_break; ++ break; ++ case 0x5: ++ op = la_op_dbcl; ++ break; ++ case 0x6: ++ op = la_op_syscall; ++ break; ++ case 0x7: ++ op = la_op_hvcl; ++ break; ++ } ++ break; ++ case 0xb: ++ switch ((insn >> 17) & 0x1) { ++ case 0x0: ++ op = la_op_alsl_d; ++ break; ++ } ++ break; ++ } ++ break; ++ case 0x1: ++ switch ((insn >> 21) & 0x1) { ++ case 0x0: ++ switch ((insn >> 16) & 0x1f) { ++ case 0x0: ++ switch ((insn >> 15) & 0x1) { ++ case 0x1: ++ op = la_op_slli_w; ++ break; ++ } ++ break; ++ case 0x1: ++ op = la_op_slli_d; ++ break; ++ case 0x4: ++ switch ((insn >> 15) & 0x1) { ++ case 0x1: ++ op = la_op_srli_w; ++ break; ++ } ++ break; ++ case 0x5: ++ op = la_op_srli_d; ++ break; ++ case 0x8: ++ switch ((insn >> 15) & 0x1) { ++ case 0x1: ++ op = la_op_srai_w; ++ break; ++ } ++ break; ++ case 0x9: ++ op = la_op_srai_d; ++ break; ++ case 0xc: ++ switch ((insn >> 15) & 0x1) { ++ case 0x1: ++ op = la_op_rotri_w; ++ break; ++ } ++ break; ++ case 0xd: ++ op = la_op_rotri_d; ++ break; ++ } ++ break; ++ case 0x1: ++ switch ((insn >> 15) & 0x1) { ++ case 0x0: ++ op = la_op_bstrins_w; ++ break; ++ case 0x1: ++ op = la_op_bstrpick_w; ++ break; ++ } ++ break; ++ } ++ break; ++ case 0x2: ++ op = la_op_bstrins_d; ++ break; ++ case 0x3: ++ op = la_op_bstrpick_d; ++ break; ++ case 0x4: ++ switch ((insn >> 15) & 0x7f) { ++ case 0x1: ++ op = la_op_fadd_s; ++ break; ++ case 0x2: ++ op = la_op_fadd_d; ++ break; ++ case 0x5: ++ op = la_op_fsub_s; ++ break; ++ case 0x6: ++ op = la_op_fsub_d; ++ break; ++ case 0x9: ++ op = la_op_fmul_s; ++ break; ++ case 0xa: ++ op = la_op_fmul_d; ++ break; ++ case 0xd: ++ op = la_op_fdiv_s; ++ break; ++ case 0xe: ++ op = la_op_fdiv_d; ++ break; ++ case 0x11: ++ op = la_op_fmax_s; ++ break; ++ case 0x12: ++ op = la_op_fmax_d; ++ break; ++ case 0x15: ++ op = la_op_fmin_s; ++ break; ++ case 0x16: ++ op = la_op_fmin_d; ++ break; ++ case 0x19: ++ op = la_op_fmaxa_s; ++ break; ++ case 0x1a: ++ op = la_op_fmaxa_d; ++ break; ++ case 0x1d: ++ op = la_op_fmina_s; ++ break; ++ case 0x1e: ++ op = la_op_fmina_d; ++ break; ++ case 0x21: ++ op = la_op_fscaleb_s; ++ break; ++ case 0x22: ++ op = la_op_fscaleb_d; ++ break; ++ case 0x25: ++ op = la_op_fcopysign_s; ++ break; ++ case 0x26: ++ op = la_op_fcopysign_d; ++ break; ++ case 0x28: ++ switch ((insn >> 10) & 0x1f) { ++ case 0x1: ++ op = la_op_fabs_s; ++ break; ++ case 0x2: ++ op = la_op_fabs_d; ++ break; ++ case 0x5: ++ op = la_op_fneg_s; ++ break; ++ case 0x6: ++ op = la_op_fneg_d; ++ break; ++ case 0x9: ++ op = la_op_flogb_s; ++ break; ++ case 0xa: ++ op = la_op_flogb_d; ++ break; ++ case 0xd: ++ op = la_op_fclass_s; ++ break; ++ case 0xe: ++ op = la_op_fclass_d; ++ break; ++ case 0x11: ++ op = la_op_fsqrt_s; ++ break; ++ case 0x12: ++ op = la_op_fsqrt_d; ++ break; ++ case 0x15: ++ op = la_op_frecip_s; ++ break; ++ case 0x16: ++ op = la_op_frecip_d; ++ break; ++ case 0x19: ++ op = la_op_frsqrt_s; ++ break; ++ case 0x1a: ++ op = la_op_frsqrt_d; ++ break; ++ } ++ break; ++ case 0x29: ++ switch ((insn >> 10) & 0x1f) { ++ case 0x5: ++ op = la_op_fmov_s; ++ break; ++ case 0x6: ++ op = la_op_fmov_d; ++ break; ++ case 0x9: ++ op = la_op_movgr2fr_w; ++ break; ++ case 0xa: ++ op = la_op_movgr2fr_d; ++ break; ++ case 0xb: ++ op = la_op_movgr2frh_w; ++ break; ++ case 0xd: ++ op = la_op_movfr2gr_s; ++ break; ++ case 0xe: ++ op = la_op_movfr2gr_d; ++ break; ++ case 0xf: ++ op = la_op_movfrh2gr_s; ++ break; ++ case 0x10: ++ op = la_op_movgr2fcsr; ++ break; ++ case 0x12: ++ op = la_op_movfcsr2gr; ++ break; ++ case 0x14: ++ switch ((insn >> 3) & 0x3) { ++ case 0x0: ++ op = la_op_movfr2cf; ++ break; ++ } ++ break; ++ case 0x15: ++ switch ((insn >> 8) & 0x3) { ++ case 0x0: ++ op = la_op_movcf2fr; ++ break; ++ } ++ break; ++ case 0x16: ++ switch ((insn >> 3) & 0x3) { ++ case 0x0: ++ op = la_op_movgr2cf; ++ break; ++ } ++ break; ++ case 0x17: ++ switch ((insn >> 8) & 0x3) { ++ case 0x0: ++ op = la_op_movcf2gr; ++ break; ++ } ++ break; ++ } ++ break; ++ case 0x32: ++ switch ((insn >> 10) & 0x1f) { ++ case 0x6: ++ op = la_op_fcvt_s_d; ++ break; ++ case 0x9: ++ op = la_op_fcvt_d_s; ++ break; ++ } ++ break; ++ case 0x34: ++ switch ((insn >> 10) & 0x1f) { ++ case 0x1: ++ op = la_op_ftintrm_w_s; ++ break; ++ case 0x2: ++ op = la_op_ftintrm_w_d; ++ break; ++ case 0x9: ++ op = la_op_ftintrm_l_s; ++ break; ++ case 0xa: ++ op = la_op_ftintrm_l_d; ++ break; ++ case 0x11: ++ op = la_op_ftintrp_w_s; ++ break; ++ case 0x12: ++ op = la_op_ftintrp_w_d; ++ break; ++ case 0x19: ++ op = la_op_ftintrp_l_s; ++ break; ++ case 0x1a: ++ op = la_op_ftintrp_l_d; ++ break; ++ } ++ break; ++ case 0x35: ++ switch ((insn >> 10) & 0x1f) { ++ case 0x1: ++ op = la_op_ftintrz_w_s; ++ break; ++ case 0x2: ++ op = la_op_ftintrz_w_d; ++ break; ++ case 0x9: ++ op = la_op_ftintrz_l_s; ++ break; ++ case 0xa: ++ op = la_op_ftintrz_l_d; ++ break; ++ case 0x11: ++ op = la_op_ftintrne_w_s; ++ break; ++ case 0x12: ++ op = la_op_ftintrne_w_d; ++ break; ++ case 0x19: ++ op = la_op_ftintrne_l_s; ++ break; ++ case 0x1a: ++ op = la_op_ftintrne_l_d; ++ break; ++ } ++ break; ++ case 0x36: ++ switch ((insn >> 10) & 0x1f) { ++ case 0x1: ++ op = la_op_ftint_w_s; ++ break; ++ case 0x2: ++ op = la_op_ftint_w_d; ++ break; ++ case 0x9: ++ op = la_op_ftint_l_s; ++ break; ++ case 0xa: ++ op = la_op_ftint_l_d; ++ break; ++ } ++ break; ++ case 0x3a: ++ switch ((insn >> 10) & 0x1f) { ++ case 0x4: ++ op = la_op_ffint_s_w; ++ break; ++ case 0x6: ++ op = la_op_ffint_s_l; ++ break; ++ case 0x8: ++ op = la_op_ffint_d_w; ++ break; ++ case 0xa: ++ op = la_op_ffint_d_l; ++ break; ++ } ++ break; ++ case 0x3c: ++ switch ((insn >> 10) & 0x1f) { ++ case 0x11: ++ op = la_op_frint_s; ++ break; ++ case 0x12: ++ op = la_op_frint_d; ++ break; ++ } ++ break; ++ } ++ break; ++ case 0x8: ++ op = la_op_slti; ++ break; ++ case 0x9: ++ op = la_op_sltui; ++ break; ++ case 0xa: ++ op = la_op_addi_w; ++ break; ++ case 0xb: ++ op = la_op_addi_d; ++ break; ++ case 0xc: ++ op = la_op_lu52i_d; ++ break; ++ case 0xd: ++ op = la_op_addi; ++ break; ++ case 0xe: ++ op = la_op_ori; ++ break; ++ case 0xf: ++ op = la_op_xori; ++ break; ++ } ++ break; ++ case 0x1: ++ switch ((insn >> 24) & 0x3) { ++ case 0x0: ++ op = la_op_csrxchg; ++ break; ++ case 0x2: ++ switch ((insn >> 22) & 0x3) { ++ case 0x0: ++ op = la_op_cacop; ++ break; ++ case 0x1: ++ switch ((insn >> 18) & 0xf) { ++ case 0x0: ++ op = la_op_lddir; ++ break; ++ case 0x1: ++ switch (insn & 0x0000001f) { ++ case 0x00000000: ++ op = la_op_ldpte; ++ break; ++ } ++ break; ++ case 0x2: ++ switch ((insn >> 15) & 0x7) { ++ case 0x0: ++ switch ((insn >> 10) & 0x1f) { ++ case 0x0: ++ op = la_op_iocsrrd_b; ++ break; ++ case 0x1: ++ op = la_op_iocsrrd_h; ++ break; ++ case 0x2: ++ op = la_op_iocsrrd_w; ++ break; ++ case 0x3: ++ op = la_op_iocsrrd_d; ++ break; ++ case 0x4: ++ op = la_op_iocsrwr_b; ++ break; ++ case 0x5: ++ op = la_op_iocsrwr_h; ++ break; ++ case 0x6: ++ op = la_op_iocsrwr_w; ++ break; ++ case 0x7: ++ op = la_op_iocsrwr_d; ++ break; ++ case 0x8: ++ switch (insn & 0x000003ff) { ++ case 0x00000000: ++ op = la_op_tlbclr; ++ break; ++ } ++ break; ++ case 0x9: ++ switch (insn & 0x000003ff) { ++ case 0x00000000: ++ op = la_op_tlbflush; ++ break; ++ } ++ break; ++ case 0xa: ++ switch (insn & 0x000003ff) { ++ case 0x00000000: ++ op = la_op_tlbsrch; ++ break; ++ } ++ break; ++ case 0xb: ++ switch (insn & 0x000003ff) { ++ case 0x00000000: ++ op = la_op_tlbrd; ++ break; ++ } ++ break; ++ case 0xc: ++ switch (insn & 0x000003ff) { ++ case 0x00000000: ++ op = la_op_tlbwr; ++ break; ++ } ++ break; ++ case 0xd: ++ switch (insn & 0x000003ff) { ++ case 0x00000000: ++ op = la_op_tlbfill; ++ break; ++ } ++ break; ++ case 0xe: ++ switch (insn & 0x000003ff) { ++ case 0x00000000: ++ op = la_op_ertn; ++ break; ++ } ++ break; ++ } ++ break; ++ case 0x1: ++ op = la_op_idle; ++ break; ++ case 0x3: ++ op = la_op_invtlb; ++ break; ++ } ++ break; ++ } ++ break; ++ } ++ break; ++ } ++ break; ++ case 0x2: ++ switch ((insn >> 20) & 0x3f) { ++ case 0x1: ++ op = la_op_fmadd_s; ++ break; ++ case 0x2: ++ op = la_op_fmadd_d; ++ break; ++ case 0x5: ++ op = la_op_fmsub_s; ++ break; ++ case 0x6: ++ op = la_op_fmsub_d; ++ break; ++ case 0x9: ++ op = la_op_fnmadd_s; ++ break; ++ case 0xa: ++ op = la_op_fnmadd_d; ++ break; ++ case 0xd: ++ op = la_op_fnmsub_s; ++ break; ++ case 0xe: ++ op = la_op_fnmsub_d; ++ break; ++ } ++ break; ++ case 0x3: ++ switch ((insn >> 20) & 0x3f) { ++ case 0x1: ++ switch ((insn >> 3) & 0x3) { ++ case 0x0: ++ op = la_op_fcmp_cond_s; ++ break; ++ } ++ break; ++ case 0x2: ++ switch ((insn >> 3) & 0x3) { ++ case 0x0: ++ op = la_op_fcmp_cond_d; ++ break; ++ } ++ break; ++ case 0x10: ++ switch ((insn >> 18) & 0x3) { ++ case 0x0: ++ op = la_op_fsel; ++ break; ++ } ++ break; ++ } ++ break; ++ case 0x4: ++ op = la_op_addu16i_d; ++ break; ++ case 0x5: ++ switch ((insn >> 25) & 0x1) { ++ case 0x0: ++ op = la_op_lu12i_w; ++ break; ++ case 0x1: ++ op = la_op_lu32i_d; ++ break; ++ } ++ break; ++ case 0x6: ++ switch ((insn >> 25) & 0x1) { ++ case 0x0: ++ op = la_op_pcaddi; ++ break; ++ case 0x1: ++ op = la_op_pcalau12i; ++ break; ++ } ++ break; ++ case 0x7: ++ switch ((insn >> 25) & 0x1) { ++ case 0x0: ++ op = la_op_pcaddu12i; ++ break; ++ case 0x1: ++ op = la_op_pcaddu18i; ++ break; ++ } ++ break; ++ case 0x8: ++ switch ((insn >> 24) & 0x3) { ++ case 0x0: ++ op = la_op_ll_w; ++ break; ++ case 0x1: ++ op = la_op_sc_w; ++ break; ++ case 0x2: ++ op = la_op_ll_d; ++ break; ++ case 0x3: ++ op = la_op_sc_d; ++ break; ++ } ++ break; ++ case 0x9: ++ switch ((insn >> 24) & 0x3) { ++ case 0x0: ++ op = la_op_ldptr_w; ++ break; ++ case 0x1: ++ op = la_op_stptr_w; ++ break; ++ case 0x2: ++ op = la_op_ldptr_d; ++ break; ++ case 0x3: ++ op = la_op_stptr_d; ++ break; ++ } ++ break; ++ case 0xa: ++ switch ((insn >> 22) & 0xf) { ++ case 0x0: ++ op = la_op_ld_b; ++ break; ++ case 0x1: ++ op = la_op_ld_h; ++ break; ++ case 0x2: ++ op = la_op_ld_w; ++ break; ++ case 0x3: ++ op = la_op_ld_d; ++ break; ++ case 0x4: ++ op = la_op_st_b; ++ break; ++ case 0x5: ++ op = la_op_st_h; ++ break; ++ case 0x6: ++ op = la_op_st_w; ++ break; ++ case 0x7: ++ op = la_op_st_d; ++ break; ++ case 0x8: ++ op = la_op_ld_bu; ++ break; ++ case 0x9: ++ op = la_op_ld_hu; ++ break; ++ case 0xa: ++ op = la_op_ld_wu; ++ break; ++ case 0xb: ++ op = la_op_preld; ++ break; ++ case 0xc: ++ op = la_op_fld_s; ++ break; ++ case 0xd: ++ op = la_op_fst_s; ++ break; ++ case 0xe: ++ op = la_op_fld_d; ++ break; ++ case 0xf: ++ op = la_op_fst_d; ++ break; ++ } ++ break; ++ case 0xb: ++ switch ((insn >> 22) & 0xf) { ++ case 0x8: ++ op = la_op_ldl_w; ++ break; ++ case 0x9: ++ op = la_op_ldr_w; ++ break; ++ case 0xa: ++ op = la_op_ldl_d; ++ break; ++ case 0xb: ++ op = la_op_ldr_d; ++ break; ++ case 0xe: ++ op = la_op_stl_d; ++ break; ++ case 0xf: ++ op = la_op_str_d; ++ break; ++ } ++ break; ++ case 0xe: ++ switch ((insn >> 15) & 0x7ff) { ++ case 0x0: ++ op = la_op_ldx_b; ++ break; ++ case 0x8: ++ op = la_op_ldx_h; ++ break; ++ case 0x10: ++ op = la_op_ldx_w; ++ break; ++ case 0x18: ++ op = la_op_ldx_d; ++ break; ++ case 0x20: ++ op = la_op_stx_b; ++ break; ++ case 0x28: ++ op = la_op_stx_h; ++ break; ++ case 0x30: ++ op = la_op_stx_w; ++ break; ++ case 0x38: ++ op = la_op_stx_d; ++ break; ++ case 0x40: ++ op = la_op_ldx_bu; ++ break; ++ case 0x48: ++ op = la_op_ldx_hu; ++ break; ++ case 0x50: ++ op = la_op_ldx_wu; ++ break; ++ case 0x60: ++ op = la_op_fldx_s; ++ break; ++ case 0x68: ++ op = la_op_fldx_d; ++ break; ++ case 0x70: ++ op = la_op_fstx_s; ++ break; ++ case 0x78: ++ op = la_op_fstx_d; ++ break; ++ case 0xc0: ++ op = la_op_amswap_w; ++ break; ++ case 0xc1: ++ op = la_op_amswap_d; ++ break; ++ case 0xc2: ++ op = la_op_amadd_w; ++ break; ++ case 0xc3: ++ op = la_op_amadd_d; ++ break; ++ case 0xc4: ++ op = la_op_amand_w; ++ break; ++ case 0xc5: ++ op = la_op_amand_d; ++ break; ++ case 0xc6: ++ op = la_op_amor_w; ++ break; ++ case 0xc7: ++ op = la_op_amor_d; ++ break; ++ case 0xc8: ++ op = la_op_amxor_w; ++ break; ++ case 0xc9: ++ op = la_op_amxor_d; ++ break; ++ case 0xca: ++ op = la_op_ammax_w; ++ break; ++ case 0xcb: ++ op = la_op_ammax_d; ++ break; ++ case 0xcc: ++ op = la_op_ammin_w; ++ break; ++ case 0xcd: ++ op = la_op_ammin_d; ++ break; ++ case 0xce: ++ op = la_op_ammax_wu; ++ break; ++ case 0xcf: ++ op = la_op_ammax_du; ++ break; ++ case 0xd0: ++ op = la_op_ammin_wu; ++ break; ++ case 0xd1: ++ op = la_op_ammin_du; ++ break; ++ case 0xd2: ++ op = la_op_amswap_db_w; ++ break; ++ case 0xd3: ++ op = la_op_amswap_db_d; ++ break; ++ case 0xd4: ++ op = la_op_amadd_db_w; ++ break; ++ case 0xd5: ++ op = la_op_amadd_db_d; ++ break; ++ case 0xd6: ++ op = la_op_amand_db_w; ++ break; ++ case 0xd7: ++ op = la_op_amand_db_d; ++ break; ++ case 0xd8: ++ op = la_op_amor_db_w; ++ break; ++ case 0xd9: ++ op = la_op_amor_db_d; ++ break; ++ case 0xda: ++ op = la_op_amxor_db_w; ++ break; ++ case 0xdb: ++ op = la_op_amxor_db_d; ++ break; ++ case 0xdc: ++ op = la_op_ammax_db_w; ++ break; ++ case 0xdd: ++ op = la_op_ammax_db_d; ++ break; ++ case 0xde: ++ op = la_op_ammin_db_w; ++ break; ++ case 0xdf: ++ op = la_op_ammin_db_d; ++ break; ++ case 0xe0: ++ op = la_op_ammax_db_wu; ++ break; ++ case 0xe1: ++ op = la_op_ammax_db_du; ++ break; ++ case 0xe2: ++ op = la_op_ammin_db_wu; ++ break; ++ case 0xe3: ++ op = la_op_ammin_db_du; ++ break; ++ case 0xe4: ++ op = la_op_dbar; ++ break; ++ case 0xe5: ++ op = la_op_ibar; ++ break; ++ case 0xe8: ++ op = la_op_fldgt_s; ++ break; ++ case 0xe9: ++ op = la_op_fldgt_d; ++ break; ++ case 0xea: ++ op = la_op_fldle_s; ++ break; ++ case 0xeb: ++ op = la_op_fldle_d; ++ break; ++ case 0xec: ++ op = la_op_fstgt_s; ++ break; ++ case 0xed: ++ op = la_op_fstgt_d; ++ break; ++ case 0xee: ++ op = ls_op_fstle_s; ++ break; ++ case 0xef: ++ op = la_op_fstle_d; ++ break; ++ case 0xf0: ++ op = la_op_ldgt_b; ++ break; ++ case 0xf1: ++ op = la_op_ldgt_h; ++ break; ++ case 0xf2: ++ op = la_op_ldgt_w; ++ break; ++ case 0xf3: ++ op = la_op_ldgt_d; ++ break; ++ case 0xf4: ++ op = la_op_ldle_b; ++ break; ++ case 0xf5: ++ op = la_op_ldle_h; ++ break; ++ case 0xf6: ++ op = la_op_ldle_w; ++ break; ++ case 0xf7: ++ op = la_op_ldle_d; ++ break; ++ case 0xf8: ++ op = la_op_stgt_b; ++ break; ++ case 0xf9: ++ op = la_op_stgt_h; ++ break; ++ case 0xfa: ++ op = la_op_stgt_w; ++ break; ++ case 0xfb: ++ op = la_op_stgt_d; ++ break; ++ case 0xfc: ++ op = la_op_stle_b; ++ break; ++ case 0xfd: ++ op = la_op_stle_h; ++ break; ++ case 0xfe: ++ op = la_op_stle_w; ++ break; ++ case 0xff: ++ op = la_op_stle_d; ++ break; ++ } ++ break; ++ case 0x10: ++ op = la_op_beqz; ++ break; ++ case 0x11: ++ op = la_op_bnez; ++ break; ++ case 0x12: ++ switch ((insn >> 8) & 0x3) { ++ case 0x0: ++ op = la_op_bceqz; ++ break; ++ case 0x1: ++ op = la_op_bcnez; ++ break; ++ } ++ break; ++ case 0x13: ++ op = la_op_jirl; ++ break; ++ case 0x14: ++ op = la_op_b; ++ break; ++ case 0x15: ++ op = la_op_bl; ++ break; ++ case 0x16: ++ op = la_op_beq; ++ break; ++ case 0x17: ++ op = la_op_bne; ++ break; ++ case 0x18: ++ op = la_op_blt; ++ break; ++ case 0x19: ++ op = la_op_bge; ++ break; ++ case 0x1a: ++ op = la_op_bltu; ++ break; ++ case 0x1b: ++ op = la_op_bgeu; ++ break; ++ default: ++ op = la_op_illegal; ++ break; ++ } ++ dec->op = op; ++} ++ ++/* operand extractors */ ++ ++#define IM_5 5 ++#define IM_8 8 ++#define IM_12 12 ++#define IM_14 14 ++#define IM_15 15 ++#define IM_16 16 ++#define IM_20 20 ++#define IM_21 21 ++#define IM_26 26 ++ ++static uint32_t operand_r1(uint32_t insn) ++{ ++ return insn & 0x1f; ++} ++ ++static uint32_t operand_r2(uint32_t insn) ++{ ++ return (insn >> 5) & 0x1f; ++} ++ ++static uint32_t operand_r3(uint32_t insn) ++{ ++ return (insn >> 10) & 0x1f; ++} ++ ++static uint32_t operand_r4(uint32_t insn) ++{ ++ return (insn >> 15) & 0x1f; ++} ++ ++static uint32_t operand_u6(uint32_t insn) ++{ ++ return (insn >> 10) & 0x3f; ++} ++ ++static uint32_t operand_bw1(uint32_t insn) ++{ ++ return (insn >> 10) & 0x1f; ++} ++ ++static uint32_t operand_bw2(uint32_t insn) ++{ ++ return (insn >> 16) & 0x1f; ++} ++ ++static uint32_t operand_bd1(uint32_t insn) ++{ ++ return (insn >> 10) & 0x3f; ++} ++ ++static uint32_t operand_bd2(uint32_t insn) ++{ ++ return (insn >> 16) & 0x3f; ++} ++ ++static uint32_t operand_sa2(uint32_t insn) ++{ ++ return (insn >> 15) & 0x3; ++} ++ ++static uint32_t operand_sa3(uint32_t insn) ++{ ++ return (insn >> 15) & 0x3; ++} ++ ++static int32_t operand_im20(uint32_t insn) ++{ ++ int32_t imm = (int32_t)((insn >> 5) & 0xfffff); ++ return imm > (1 << 19) ? imm - (1 << 20) : imm; ++} ++ ++static int32_t operand_im16(uint32_t insn) ++{ ++ int32_t imm = (int32_t)((insn >> 10) & 0xffff); ++ return imm > (1 << 15) ? imm - (1 << 16) : imm; ++} ++ ++static int32_t operand_im14(uint32_t insn) ++{ ++ int32_t imm = (int32_t)((insn >> 10) & 0x3fff); ++ return imm > (1 << 13) ? imm - (1 << 14) : imm; ++} ++ ++static int32_t operand_im12(uint32_t insn) ++{ ++ int32_t imm = (int32_t)((insn >> 10) & 0xfff); ++ return imm > (1 << 11) ? imm - (1 << 12) : imm; ++} ++ ++static int32_t operand_im8(uint32_t insn) ++{ ++ int32_t imm = (int32_t)((insn >> 10) & 0xff); ++ return imm > (1 << 7) ? imm - (1 << 8) : imm; ++} ++ ++static uint32_t operand_sd(uint32_t insn) ++{ ++ return insn & 0x3; ++} ++ ++static uint32_t operand_sj(uint32_t insn) ++{ ++ return (insn >> 5) & 0x3; ++} ++ ++static uint32_t operand_cd(uint32_t insn) ++{ ++ return insn & 0x7; ++} ++ ++static uint32_t operand_cj(uint32_t insn) ++{ ++ return (insn >> 5) & 0x7; ++} ++ ++static uint32_t operand_code(uint32_t insn) ++{ ++ return insn & 0x7fff; ++} ++ ++static int32_t operand_whint(uint32_t insn) ++{ ++ int32_t imm = (int32_t)(insn & 0x7fff); ++ return imm > (1 << 14) ? imm - (1 << 15) : imm; ++} ++ ++static int32_t operand_invop(uint32_t insn) ++{ ++ int32_t imm = (int32_t)(insn & 0x1f); ++ return imm > (1 << 4) ? imm - (1 << 5) : imm; ++} ++ ++static int32_t operand_ofs21(uint32_t insn) ++{ ++ int32_t imm = (((int32_t)insn & 0x1f) << 16) | ++ ((insn >> 10) & 0xffff); ++ return imm > (1 << 20) ? imm - (1 << 21) : imm; ++} ++ ++static int32_t operand_ofs26(uint32_t insn) ++{ ++ int32_t imm = (((int32_t)insn & 0x3ff) << 16) | ++ ((insn >> 10) & 0xffff); ++ return imm > (1 << 25) ? imm - (1 << 26) : imm; ++} ++ ++static uint32_t operand_fcond(uint32_t insn) ++{ ++ return (insn >> 15) & 0x1f; ++} ++ ++static uint32_t operand_sel(uint32_t insn) ++{ ++ return (insn >> 15) & 0x7; ++} ++ ++/* decode operands */ ++ ++static void decode_insn_operands(la_decode *dec) ++{ ++ uint32_t insn = dec->insn; ++ dec->codec = opcode_data[dec->op].codec; ++ switch (dec->codec) { ++ case la_codec_illegal: ++ case la_codec_empty: ++ break; ++ case la_codec_2r: ++ dec->r1 = operand_r1(insn); ++ dec->r2 = operand_r2(insn); ++ break; ++ case la_codec_2r_u5: ++ dec->r1 = operand_r1(insn); ++ dec->r2 = operand_r2(insn); ++ dec->r3 = operand_r3(insn); ++ break; ++ case la_codec_2r_u6: ++ dec->r1 = operand_r1(insn); ++ dec->r2 = operand_r2(insn); ++ dec->r3 = operand_u6(insn); ++ break; ++ case la_codec_2r_2bw: ++ dec->r1 = operand_r1(insn); ++ dec->r2 = operand_r2(insn); ++ dec->r3 = operand_bw1(insn); ++ dec->r4 = operand_bw2(insn); ++ break; ++ case la_codec_2r_2bd: ++ dec->r1 = operand_r1(insn); ++ dec->r2 = operand_r2(insn); ++ dec->r3 = operand_bd1(insn); ++ dec->r4 = operand_bd2(insn); ++ break; ++ case la_codec_3r: ++ dec->r1 = operand_r1(insn); ++ dec->r2 = operand_r2(insn); ++ dec->r3 = operand_r3(insn); ++ break; ++ case la_codec_3r_rd0: ++ dec->r1 = 0; ++ dec->r2 = operand_r2(insn); ++ dec->r3 = operand_r3(insn); ++ break; ++ case la_codec_3r_sa2: ++ dec->r1 = operand_r1(insn); ++ dec->r2 = operand_r2(insn); ++ dec->r3 = operand_r3(insn); ++ dec->r4 = operand_sa2(insn); ++ break; ++ case la_codec_3r_sa3: ++ dec->r1 = operand_r1(insn); ++ dec->r2 = operand_r2(insn); ++ dec->r3 = operand_r3(insn); ++ dec->r4 = operand_sa3(insn); ++ break; ++ case la_codec_4r: ++ dec->r1 = operand_r1(insn); ++ dec->r2 = operand_r2(insn); ++ dec->r3 = operand_r3(insn); ++ dec->r4 = operand_r4(insn); ++ break; ++ case la_codec_r_im20: ++ dec->r1 = operand_r1(insn); ++ dec->imm = operand_im20(insn); ++ dec->bit = IM_20; ++ break; ++ case la_codec_2r_im16: ++ dec->r1 = operand_r1(insn); ++ dec->r2 = operand_r2(insn); ++ dec->imm = operand_im16(insn); ++ dec->bit = IM_16; ++ break; ++ case la_codec_2r_im14: ++ dec->r1 = operand_r1(insn); ++ dec->r2 = operand_r2(insn); ++ dec->imm = operand_im14(insn); ++ dec->bit = IM_14; ++ break; ++ case la_codec_im5_r_im12: ++ dec->imm2 = operand_r1(insn); ++ dec->r2 = operand_r2(insn); ++ dec->imm = operand_im12(insn); ++ dec->bit = IM_12; ++ break; ++ case la_codec_2r_im12: ++ dec->r1 = operand_r1(insn); ++ dec->r2 = operand_r2(insn); ++ dec->imm = operand_im12(insn); ++ dec->bit = IM_12; ++ break; ++ case la_codec_2r_im8: ++ dec->r1 = operand_r1(insn); ++ dec->r2 = operand_r2(insn); ++ dec->imm = operand_im8(insn); ++ dec->bit = IM_8; ++ break; ++ case la_codec_r_sd: ++ dec->r1 = operand_sd(insn); ++ dec->r2 = operand_r2(insn); ++ break; ++ case la_codec_r_sj: ++ dec->r1 = operand_r1(insn); ++ dec->r2 = operand_sj(insn); ++ break; ++ case la_codec_r_cd: ++ dec->r1 = operand_cd(insn); ++ dec->r2 = operand_r2(insn); ++ break; ++ case la_codec_r_cj: ++ dec->r1 = operand_r1(insn); ++ dec->r2 = operand_cj(insn); ++ break; ++ case la_codec_r_seq: ++ dec->r1 = 0; ++ dec->r2 = operand_r1(insn); ++ dec->imm = operand_im8(insn); ++ dec->bit = IM_8; ++ break; ++ case la_codec_code: ++ dec->code = operand_code(insn); ++ break; ++ case la_codec_whint: ++ dec->imm = operand_whint(insn); ++ dec->bit = IM_15; ++ break; ++ case la_codec_invtlb: ++ dec->imm = operand_invop(insn); ++ dec->bit = IM_5; ++ dec->r2 = operand_r2(insn); ++ dec->r3 = operand_r3(insn); ++ break; ++ case la_codec_r_ofs21: ++ dec->imm = operand_ofs21(insn); ++ dec->bit = IM_21; ++ dec->r2 = operand_r2(insn); ++ break; ++ case la_codec_cj_ofs21: ++ dec->imm = operand_ofs21(insn); ++ dec->bit = IM_21; ++ dec->r2 = operand_cj(insn); ++ break; ++ case la_codec_ofs26: ++ dec->imm = operand_ofs26(insn); ++ dec->bit = IM_26; ++ break; ++ case la_codec_cond: ++ dec->r1 = operand_cd(insn); ++ dec->r2 = operand_r2(insn); ++ dec->r3 = operand_r3(insn); ++ dec->r4 = operand_fcond(insn); ++ break; ++ case la_codec_sel: ++ dec->r1 = operand_r1(insn); ++ dec->r2 = operand_r2(insn); ++ dec->r3 = operand_r3(insn); ++ dec->r4 = operand_sel(insn); ++ break; ++ } ++} ++ ++/* format instruction */ ++ ++static void append(char *s1, const char *s2, size_t n) ++{ ++ size_t l1 = strlen(s1); ++ if (n - l1 - 1 > 0) { ++ strncat(s1, s2, n - l1); ++ } ++} ++ ++static void format_insn(char *buf, size_t buflen, size_t tab, la_decode *dec) ++{ ++ char tmp[16]; ++ const char *fmt; ++ ++ fmt = opcode_data[dec->op].format; ++ while (*fmt) { ++ switch (*fmt) { ++ case 'n': /* name */ ++ append(buf, opcode_data[dec->op].name, buflen); ++ break; ++ case 's': ++ append(buf, "s", buflen); ++ break; ++ case 'd': ++ append(buf, "d", buflen); ++ break; ++ case 'e': /* illegal */ ++ snprintf(tmp, sizeof(tmp), "%x", dec->insn); ++ append(buf, tmp, buflen); ++ break; ++ case 't': ++ while (strlen(buf) < tab) { ++ append(buf, " ", buflen); ++ } ++ break; ++ case '(': ++ append(buf, "(", buflen); ++ break; ++ case ',': ++ append(buf, ",", buflen); ++ break; ++ case '.': ++ append(buf, ".", buflen); ++ break; ++ case ')': ++ append(buf, ")", buflen); ++ break; ++ case '0': /* rd */ ++ append(buf, loongarch_r_normal_name[dec->r1], buflen); ++ break; ++ case '1': /* rj */ ++ append(buf, loongarch_r_normal_name[dec->r2], buflen); ++ break; ++ case '2': /* rk */ ++ append(buf, loongarch_r_normal_name[dec->r3], buflen); ++ break; ++ case '3': /* fd */ ++ append(buf, loongarch_f_normal_name[dec->r1], buflen); ++ break; ++ case '4': /* fj */ ++ append(buf, loongarch_f_normal_name[dec->r2], buflen); ++ break; ++ case '5': /* fk */ ++ append(buf, loongarch_f_normal_name[dec->r3], buflen); ++ break; ++ case '6': /* fa */ ++ append(buf, loongarch_f_normal_name[dec->r4], buflen); ++ break; ++ case 'A': /* sd */ ++ append(buf, loongarch_cr_normal_name[dec->r1], buflen); ++ break; ++ case 'B': /* sj */ ++ append(buf, loongarch_cr_normal_name[dec->r2], buflen); ++ break; ++ case 'C': /* r3 */ ++ snprintf(tmp, sizeof(tmp), "%x", dec->r3); ++ append(buf, tmp, buflen); ++ break; ++ case 'D': /* r4 */ ++ snprintf(tmp, sizeof(tmp), "%x", dec->r4); ++ append(buf, tmp, buflen); ++ break; ++ case 'E': /* r1 */ ++ snprintf(tmp, sizeof(tmp), "%x", dec->r1); ++ append(buf, tmp, buflen); ++ break; ++ case 'F': /* fcsrd */ ++ append(buf, loongarch_r_normal_name[dec->r1], buflen); ++ break; ++ case 'G': /* fcsrs */ ++ append(buf, loongarch_r_normal_name[dec->r2], buflen); ++ break; ++ case 'H': /* cd */ ++ append(buf, loongarch_c_normal_name[dec->r1], buflen); ++ break; ++ case 'I': /* cj */ ++ append(buf, loongarch_c_normal_name[dec->r2], buflen); ++ break; ++ case 'J': /* code */ ++ snprintf(tmp, sizeof(tmp), "0x%x", dec->code); ++ append(buf, tmp, buflen); ++ break; ++ case 'K': /* cond */ ++ switch (dec->r4) { ++ case 0x0: ++ append(buf, "caf", buflen); ++ break; ++ case 0x1: ++ append(buf, "saf", buflen); ++ break; ++ case 0x2: ++ append(buf, "clt", buflen); ++ break; ++ case 0x3: ++ append(buf, "slt", buflen); ++ break; ++ case 0x4: ++ append(buf, "ceq", buflen); ++ break; ++ case 0x5: ++ append(buf, "seq", buflen); ++ break; ++ case 0x6: ++ append(buf, "cle", buflen); ++ break; ++ case 0x7: ++ append(buf, "sle", buflen); ++ break; ++ case 0x8: ++ append(buf, "cun", buflen); ++ break; ++ case 0x9: ++ append(buf, "sun", buflen); ++ break; ++ case 0xA: ++ append(buf, "cult", buflen); ++ break; ++ case 0xB: ++ append(buf, "sult", buflen); ++ break; ++ case 0xC: ++ append(buf, "cueq", buflen); ++ break; ++ case 0xD: ++ append(buf, "sueq", buflen); ++ break; ++ case 0xE: ++ append(buf, "cule", buflen); ++ break; ++ case 0xF: ++ append(buf, "sule", buflen); ++ break; ++ case 0x10: ++ append(buf, "cne", buflen); ++ break; ++ case 0x11: ++ append(buf, "sne", buflen); ++ break; ++ case 0x14: ++ append(buf, "cor", buflen); ++ break; ++ case 0x15: ++ append(buf, "sor", buflen); ++ break; ++ case 0x18: ++ append(buf, "cune", buflen); ++ break; ++ case 0x19: ++ append(buf, "sune", buflen); ++ break; ++ } ++ break; ++ case 'L': /* ca */ ++ append(buf, loongarch_c_normal_name[dec->r4], buflen); ++ break; ++ case 'M': /* cop */ ++ snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm2) & 0x1f); ++ append(buf, tmp, buflen); ++ break; ++ case 'i': /* sixx d */ ++ snprintf(tmp, sizeof(tmp), "%d", dec->imm); ++ append(buf, tmp, buflen); ++ break; ++ case 'o': /* offset */ ++ snprintf(tmp, sizeof(tmp), "%d", (dec->imm) << 2); ++ append(buf, tmp, buflen); ++ break; ++ case 'x': /* sixx x */ ++ switch (dec->bit) { ++ case IM_5: ++ snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm) & 0x1f); ++ append(buf, tmp, buflen); ++ break; ++ case IM_8: ++ snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm) & 0xff); ++ append(buf, tmp, buflen); ++ break; ++ case IM_12: ++ snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm) & 0xfff); ++ append(buf, tmp, buflen); ++ break; ++ case IM_14: ++ snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm) & 0x3fff); ++ append(buf, tmp, buflen); ++ break; ++ case IM_15: ++ snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm) & 0x7fff); ++ append(buf, tmp, buflen); ++ break; ++ case IM_16: ++ snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm) & 0xffff); ++ append(buf, tmp, buflen); ++ break; ++ case IM_20: ++ snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm) & 0xfffff); ++ append(buf, tmp, buflen); ++ break; ++ default: ++ snprintf(tmp, sizeof(tmp), "0x%x", dec->imm); ++ append(buf, tmp, buflen); ++ break; ++ } ++ break; ++ case 'X': /* offset x*/ ++ switch (dec->bit) { ++ case IM_16: ++ snprintf(tmp, sizeof(tmp), "0x%x", ++ ((dec->imm) << 2) & 0xffff); ++ append(buf, tmp, buflen); ++ break; ++ case IM_21: ++ snprintf(tmp, sizeof(tmp), "0x%x", ++ ((dec->imm) << 2) & 0x1fffff); ++ append(buf, tmp, buflen); ++ break; ++ case IM_26: ++ snprintf(tmp, sizeof(tmp), "0x%x", ++ ((dec->imm) << 2) & 0x3ffffff); ++ append(buf, tmp, buflen); ++ break; ++ default: ++ snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm) << 2); ++ append(buf, tmp, buflen); ++ break; ++ } ++ break; ++ case 'p': /* pc */ ++ snprintf(tmp, sizeof(tmp), " # 0x%"PRIx32"", ++ dec->pc + ((dec->imm) << 2)); ++ append(buf, tmp, buflen); ++ break; ++ default: ++ break; ++ } ++ fmt++; ++ } ++} ++ ++ ++/* disassemble instruction */ ++ ++static void ++disasm_insn(char *buf, size_t buflen, bfd_vma pc, unsigned long int insn) ++{ ++ la_decode dec = { 0 }; ++ dec.pc = pc; ++ dec.insn = insn; ++ decode_insn_opcode(&dec); ++ decode_insn_operands(&dec); ++ format_insn(buf, buflen, 16, &dec); ++} ++ ++int ++print_insn_loongarch(bfd_vma memaddr, struct disassemble_info *info) ++{ ++ char buf[128] = { 0 }; ++ bfd_byte buffer[INSNLEN]; ++ unsigned long insn; ++ int status; ++ ++ status = (*info->read_memory_func)(memaddr, buffer, INSNLEN, info); ++ if (status == 0) { ++ insn = (uint32_t) bfd_getl32(buffer); ++ (*info->fprintf_func)(info->stream, "%08" PRIx64 " ", insn); ++ } else { ++ (*info->memory_error_func)(status, memaddr, info); ++ return -1; ++ } ++ disasm_insn(buf, sizeof(buf), memaddr, insn); ++ (*info->fprintf_func)(info->stream, "\t%s", buf); ++ return INSNLEN; ++} +diff --git a/disas/meson.build b/disas/meson.build +index 449f99e1de..06a69d9d72 100644 +--- a/disas/meson.build ++++ b/disas/meson.build +@@ -12,6 +12,7 @@ common_ss.add(when: 'CONFIG_I386_DIS', if_true: files('i386.c')) + common_ss.add(when: 'CONFIG_M68K_DIS', if_true: files('m68k.c')) + common_ss.add(when: 'CONFIG_MICROBLAZE_DIS', if_true: files('microblaze.c')) + common_ss.add(when: 'CONFIG_MIPS_DIS', if_true: files('mips.c')) ++common_ss.add(when: 'CONFIG_LOONGARCH_DIS', if_true: files('loongarch.c')) + common_ss.add(when: 'CONFIG_NANOMIPS_DIS', if_true: files('nanomips.cpp')) + common_ss.add(when: 'CONFIG_NIOS2_DIS', if_true: files('nios2.c')) + common_ss.add(when: 'CONFIG_PPC_DIS', if_true: files('ppc.c')) +diff --git a/gdb-xml/loongarch-base32.xml b/gdb-xml/loongarch-base32.xml +new file mode 100644 +index 0000000000..04891e023f +--- /dev/null ++++ b/gdb-xml/loongarch-base32.xml +@@ -0,0 +1,43 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/gdb-xml/loongarch-base64.xml b/gdb-xml/loongarch-base64.xml +new file mode 100644 +index 0000000000..6308fb6ecb +--- /dev/null ++++ b/gdb-xml/loongarch-base64.xml +@@ -0,0 +1,43 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/gdb-xml/loongarch-fpu32.xml b/gdb-xml/loongarch-fpu32.xml +new file mode 100644 +index 0000000000..a5b4d80e6c +--- /dev/null ++++ b/gdb-xml/loongarch-fpu32.xml +@@ -0,0 +1,52 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/gdb-xml/loongarch-fpu64.xml b/gdb-xml/loongarch-fpu64.xml +new file mode 100644 +index 0000000000..74ab55a015 +--- /dev/null ++++ b/gdb-xml/loongarch-fpu64.xml +@@ -0,0 +1,57 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +-- +2.27.0 + diff --git a/0007-Modify-kvm-cpu-vga-qapi.patch b/0007-Modify-kvm-cpu-vga-qapi.patch new file mode 100644 index 0000000..c2b94f1 --- /dev/null +++ b/0007-Modify-kvm-cpu-vga-qapi.patch @@ -0,0 +1,480 @@ +From 6e52e755bd54efb15afa052dac6dd0c7f696e366 Mon Sep 17 00:00:00 2001 +From: lixianglai +Date: Sat, 20 Aug 2022 02:18:41 -0400 +Subject: [PATCH 7/8] Modify kvm cpu vga qapi. + +Change-Id: I7923af804bdbe6d44d3f521df1859aa081afceba +Signed-off-by: lixianglai +Signed-off-by: Mao Bibo +--- + hw/acpi/cpu.c | 11 ++++++ + hw/loongarch/iocsr.c | 2 ++ + hw/loongarch/larch_3a.c | 18 +++++----- + hw/meson.build | 1 + + include/disas/dis-asm.h | 1 + + include/elf.h | 2 ++ + include/hw/loongarch/larch.h | 1 - + include/qemu/osdep.h | 3 ++ + include/sysemu/arch_init.h | 1 + + linux-headers/linux/kvm.h | 23 ++++++++++++ + linux-user/elfload.c | 67 +++++++++++++++++++++++++++++++++++ + linux-user/meson.build | 1 + + linux-user/qemu.h | 2 +- + linux-user/syscall.c | 3 ++ + linux-user/syscall_defs.h | 9 ++--- + meson.build | 1 + + pc-bios/loongarch_bios.bin | Bin 0 -> 4190208 bytes + pc-bios/meson.build | 1 + + qapi/machine-target.json | 6 ++-- + qapi/machine.json | 2 +- + qapi/misc-target.json | 1 + + 21 files changed, 138 insertions(+), 18 deletions(-) + create mode 100644 pc-bios/loongarch_bios.bin + +diff --git a/hw/acpi/cpu.c b/hw/acpi/cpu.c +index b20903ea30..cd73fab65b 100644 +--- a/hw/acpi/cpu.c ++++ b/hw/acpi/cpu.c +@@ -371,14 +371,25 @@ void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts, + aml_append(cpu_ctrl_dev, aml_mutex(CPU_LOCK, 0)); + + crs = aml_resource_template(); ++#ifdef __loongarch__ ++ aml_append(crs, aml_memory32_fixed(io_base, ++ ACPI_CPU_HOTPLUG_REG_LEN, AML_READ_WRITE)); ++#else + aml_append(crs, aml_io(AML_DECODE16, io_base, io_base, 1, + ACPI_CPU_HOTPLUG_REG_LEN)); ++#endif + aml_append(cpu_ctrl_dev, aml_name_decl("_CRS", crs)); + + /* declare CPU hotplug MMIO region with related access fields */ ++#ifdef __loongarch__ ++ aml_append(cpu_ctrl_dev, ++ aml_operation_region("PRST", AML_SYSTEM_MEMORY, aml_int(io_base), ++ ACPI_CPU_HOTPLUG_REG_LEN)); ++#else + aml_append(cpu_ctrl_dev, + aml_operation_region("PRST", AML_SYSTEM_IO, aml_int(io_base), + ACPI_CPU_HOTPLUG_REG_LEN)); ++#endif + + field = aml_field("PRST", AML_BYTE_ACC, AML_NOLOCK, + AML_WRITE_AS_ZEROS); +diff --git a/hw/loongarch/iocsr.c b/hw/loongarch/iocsr.c +index 14521c2d5c..60daafd6e1 100644 +--- a/hw/loongarch/iocsr.c ++++ b/hw/loongarch/iocsr.c +@@ -59,6 +59,7 @@ enum { + IOCSR_MAX + }; + ++#ifdef CONFIG_KVM + static uint32_t iocsr_array[IOCSR_MAX] = { + [IOCSR_FEATURES] = LOONGARCH_IOCSR_FEATURES, + [IOCSR_VENDOR] = LOONGARCH_IOCSR_VENDOR, +@@ -66,6 +67,7 @@ static uint32_t iocsr_array[IOCSR_MAX] = { + [IOCSR_NODECNT] = LOONGARCH_IOCSR_NODECNT, + [IOCSR_MISC_FUNC] = LOONGARCH_IOCSR_MISC_FUNC, + }; ++#endif + + + #define TYPE_IOCSR "iocsr" +diff --git a/hw/loongarch/larch_3a.c b/hw/loongarch/larch_3a.c +index 3db269274f..3194a822cc 100644 +--- a/hw/loongarch/larch_3a.c ++++ b/hw/loongarch/larch_3a.c +@@ -846,7 +846,7 @@ static void fw_cfg_add_kernel_info(FWCfgState *fw_cfg, + if (0 < initrd_size) { + if (initrd_size > highram_size) { + error_report("initrd size is too big, should below %ld MB", +- highram_size / S_1MiB); ++ highram_size / MiB); + /*prevent write io memory address space*/ + exit(1); + } +@@ -1033,7 +1033,9 @@ static void *ls3a_intctl_init(MachineState *machine, CPULOONGARCHState *env[]) + SysBusDevice *busdev; + MemoryRegion *address_space_mem = get_system_memory(); + MemoryRegion *iomem = NULL; ++#ifdef CONFIG_KVM + int i; ++#endif + + s = g_malloc0(sizeof(ls3a_intctlstate)); + +@@ -1214,8 +1216,6 @@ static void loongarch_build_smbios(LoongarchMachineState *lsms) + product = "Loongarch-3A5K-7A1000-TCG"; + } + +- host_cpufreq = get_host_cpu_freq(); +- + smbios_set_defaults("Loongson", product, lsmc->cpu_name, false, + true, NULL, NULL, SMBIOS_ENTRY_POINT_30); + +@@ -1672,15 +1672,15 @@ static void ls3a5k_init(MachineState *args) + + offset += lowram_size; + if (nb_numa_nodes > 0) { +- highram_size = numa_info[0].node_mem - S_256MiB; +- if (numa_info[0].node_mem > S_1GiB) { +- memmap_size = numa_info[0].node_mem - S_1GiB; ++ highram_size = numa_info[0].node_mem - 256 * MiB; ++ if (numa_info[0].node_mem > GiB) { ++ memmap_size = numa_info[0].node_mem - GiB; + la_memmap_add_entry(0xc0000000ULL, memmap_size, SYSTEM_RAM); + } + } else { +- highram_size = ram_size - S_256MiB; +- if (ram_size > S_1GiB) { +- memmap_size = ram_size - S_1GiB; ++ highram_size = ram_size - 256 * MiB; ++ if (ram_size > GiB) { ++ memmap_size = ram_size - GiB; + la_memmap_add_entry(0xc0000000ULL, memmap_size, SYSTEM_RAM); + } + } +diff --git a/hw/meson.build b/hw/meson.build +index b3366c888e..f224f8ad28 100644 +--- a/hw/meson.build ++++ b/hw/meson.build +@@ -17,6 +17,7 @@ subdir('intc') + subdir('ipack') + subdir('ipmi') + subdir('isa') ++subdir('loongarch') + subdir('mem') + subdir('misc') + subdir('net') +diff --git a/include/disas/dis-asm.h b/include/disas/dis-asm.h +index 08e1beec85..95b93f1002 100644 +--- a/include/disas/dis-asm.h ++++ b/include/disas/dis-asm.h +@@ -461,6 +461,7 @@ int print_insn_riscv32 (bfd_vma, disassemble_info*); + int print_insn_riscv64 (bfd_vma, disassemble_info*); + int print_insn_rx(bfd_vma, disassemble_info *); + int print_insn_hexagon(bfd_vma, disassemble_info *); ++int print_insn_loongarch (bfd_vma, disassemble_info*); + + #ifdef CONFIG_CAPSTONE + bool cap_disas_target(disassemble_info *info, uint64_t pc, size_t size); +diff --git a/include/elf.h b/include/elf.h +index 811bf4a1cb..66030f4906 100644 +--- a/include/elf.h ++++ b/include/elf.h +@@ -182,6 +182,8 @@ typedef struct mips_elf_abiflags_v0 { + + #define EM_NANOMIPS 249 /* Wave Computing nanoMIPS */ + ++#define EM_LOONGARCH 258 /* Loongarch */ ++ + /* + * This is an interim value that we will use until the committee comes + * up with a final number. +diff --git a/include/hw/loongarch/larch.h b/include/hw/loongarch/larch.h +index 0886ed52af..62e2830e27 100644 +--- a/include/hw/loongarch/larch.h ++++ b/include/hw/loongarch/larch.h +@@ -159,5 +159,4 @@ bool loongarch_is_acpi_enabled(LoongarchMachineState *vms); + void ls7a_madt_cpu_entry(AcpiDeviceIf *adev, int uid, + const CPUArchIdList *apic_ids, GArray *entry, bool force_enabled); + void slave_cpu_reset(void *opaque); +-extern uint64_t host_cpufreq; + #endif +diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h +index 60718fc342..903475bb21 100644 +--- a/include/qemu/osdep.h ++++ b/include/qemu/osdep.h +@@ -533,6 +533,9 @@ static inline void qemu_cleanup_generic_vfree(void *p) + Valgrind does not support alignments larger than 1 MiB, + therefore we need special code which handles running on Valgrind. */ + # define QEMU_VMALLOC_ALIGN (512 * 4096) ++#elif defined(__linux__) && defined(__loongarch__) ++ /* Use 32 MiB alignment so transparent hugepages can be used by KVM. */ ++# define QEMU_VMALLOC_ALIGN (qemu_real_host_page_size * qemu_real_host_page_size / 8) + #elif defined(__linux__) && defined(__s390x__) + /* Use 1 MiB (segment size) alignment so gmap can be used by KVM. */ + # define QEMU_VMALLOC_ALIGN (256 * 4096) +diff --git a/include/sysemu/arch_init.h b/include/sysemu/arch_init.h +index 70c579560a..62d1a4b92d 100644 +--- a/include/sysemu/arch_init.h ++++ b/include/sysemu/arch_init.h +@@ -24,6 +24,7 @@ enum { + QEMU_ARCH_RX = (1 << 20), + QEMU_ARCH_AVR = (1 << 21), + QEMU_ARCH_HEXAGON = (1 << 22), ++ QEMU_ARCH_LOONGARCH64 = (1 << 23), + }; + + extern const uint32_t arch_type; +diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h +index bcaf66cc4d..20b90426f5 100644 +--- a/linux-headers/linux/kvm.h ++++ b/linux-headers/linux/kvm.h +@@ -2002,6 +2002,29 @@ struct kvm_stats_desc { + char name[]; + }; + ++#ifdef __loongarch__ ++struct kvm_loongarch_vcpu_state { ++ __u8 online_vcpus; ++ __u8 is_migrate; ++ __u32 cpu_freq; ++ __u32 count_ctl; ++ __u64 pending_exceptions; ++ __u64 pending_exceptions_clr; ++ __u64 core_ext_ioisr[4]; ++}; ++ ++#define KVM_CAP_LOONGARCH_FPU 165 ++#define KVM_CAP_LOONGARCH_LSX 166 ++#define KVM_CAP_LOONGARCH_VZ 167 ++#define KVM_REG_LOONGARCH 0x8000000000000000ULL ++#define KVM_LARCH_GET_VCPU_STATE _IOR(KVMIO, 0xc0, struct kvm_loongarch_vcpu_state) ++#define KVM_LARCH_SET_VCPU_STATE _IOW(KVMIO, 0xc1, struct kvm_loongarch_vcpu_state) ++#define KVM_LARCH_GET_CPUCFG _IOR(KVMIO, 0xc2, struct kvm_cpucfg) ++#define KVM_LOONGARCH_GET_IOCSR _IOR(KVMIO, 0xc3, struct kvm_iocsr_entry) ++#define KVM_LOONGARCH_SET_IOCSR _IOW(KVMIO, 0xc4, struct kvm_iocsr_entry) ++#define KVM_LARCH_SET_CPUCFG _IOR(KVMIO, 0xc5, struct kvm_cpucfg) ++#endif ++ + #define KVM_GET_STATS_FD _IO(KVMIO, 0xce) + + /* Available with KVM_CAP_XSAVE2 */ +diff --git a/linux-user/elfload.c b/linux-user/elfload.c +index 767f54c76d..9fb632780a 100644 +--- a/linux-user/elfload.c ++++ b/linux-user/elfload.c +@@ -1041,6 +1041,73 @@ static uint32_t get_elf_hwcap(void) + + #endif /* TARGET_MIPS */ + ++#ifdef TARGET_LOONGARCH64 ++ ++#define ELF_START_MMAP 0x80000000 ++ ++#define ELF_CLASS ELFCLASS64 ++#define ELF_ARCH EM_LOONGARCH ++ ++#define elf_check_arch(x) ((x) == EM_LOONGARCH) ++ ++static inline void init_thread(struct target_pt_regs *regs, ++ struct image_info *infop) ++{ ++ regs->csr_crmd = 2 << 3; ++ regs->csr_era = infop->entry; ++ regs->regs[3] = infop->start_stack; ++} ++ ++/* See linux kernel: arch/mips/include/asm/elf.h. */ ++#define ELF_NREG 45 ++typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; ++ ++/* See linux kernel: arch/loongarch/include/uapi/asm/reg.h */ ++enum { ++ TARGET_EF_R0 = 0, ++ TARGET_EF_R26 = TARGET_EF_R0 + 26, ++ TARGET_EF_R27 = TARGET_EF_R0 + 27, ++ TARGET_EF_CSR_ERA = TARGET_EF_R0 + 32, ++ TARGET_EF_CSR_BADV = TARGET_EF_R0 + 33, ++ TARGET_EF_CSR_CRMD = TARGET_EF_R0 + 34, ++ TARGET_EF_CSR_ESTAT = TARGET_EF_R0 + 38 ++}; ++ ++/* See linux kernel: arch/loongarch/kernel/process.c:elf_dump_regs. */ ++static void elf_core_copy_regs(target_elf_gregset_t *regs, ++ const CPULOONGARCHState *env) ++{ ++ int i; ++ ++ for (i = 0; i < TARGET_EF_R0; i++) { ++ (*regs)[i] = 0; ++ } ++ (*regs)[TARGET_EF_R0] = 0; ++ ++ for (i = 1; i < ARRAY_SIZE(env->active_tc.gpr); i++) { ++ (*regs)[TARGET_EF_R0 + i] = tswapreg(env->active_tc.gpr[i]); ++ } ++ ++ (*regs)[TARGET_EF_R26] = 0; ++ (*regs)[TARGET_EF_R27] = 0; ++ (*regs)[TARGET_EF_CSR_ERA] = tswapreg(env->active_tc.PC); ++ (*regs)[TARGET_EF_CSR_BADV] = tswapreg(env->CSR_BADV); ++ (*regs)[TARGET_EF_CSR_CRMD] = tswapreg(env->CSR_CRMD); ++ (*regs)[TARGET_EF_CSR_ESTAT] = tswapreg(env->CSR_ESTAT); ++} ++ ++#define USE_ELF_CORE_DUMP ++#define ELF_EXEC_PAGESIZE 4096 ++ ++#define ELF_HWCAP get_elf_hwcap() ++ ++static uint32_t get_elf_hwcap(void) ++{ ++ return 0; ++} ++ ++#endif /* TARGET_LOONGARCH64 */ ++ + #ifdef TARGET_MICROBLAZE + + #define ELF_START_MMAP 0x80000000 +diff --git a/linux-user/meson.build b/linux-user/meson.build +index bf62c13e37..195f9e83ac 100644 +--- a/linux-user/meson.build ++++ b/linux-user/meson.build +@@ -39,3 +39,4 @@ subdir('sh4') + subdir('sparc') + subdir('x86_64') + subdir('xtensa') ++subdir('loongarch64') +diff --git a/linux-user/qemu.h b/linux-user/qemu.h +index 5c713fa8ab..66ddb25d1c 100644 +--- a/linux-user/qemu.h ++++ b/linux-user/qemu.h +@@ -61,7 +61,7 @@ struct image_info { + /* For target-specific processing of NT_GNU_PROPERTY_TYPE_0. */ + uint32_t note_flags; + +-#ifdef TARGET_MIPS ++#if defined(TARGET_MIPS) || defined(TARGET_LOONGARCH64) + int fp_abi; + int interp_fp_abi; + #endif +diff --git a/linux-user/syscall.c b/linux-user/syscall.c +index f1cfcc8104..729131ecd0 100644 +--- a/linux-user/syscall.c ++++ b/linux-user/syscall.c +@@ -1614,6 +1614,9 @@ static abi_long do_pipe(void *cpu_env, abi_ulong pipedes, + #elif defined(TARGET_MIPS) + ((CPUMIPSState*)cpu_env)->active_tc.gpr[3] = host_pipe[1]; + return host_pipe[0]; ++#elif defined(TARGET_LOONGARCH64) ++ ((CPULOONGARCHState *)cpu_env)->active_tc.gpr[5] = host_pipe[1]; ++ return host_pipe[0]; + #elif defined(TARGET_SH4) + ((CPUSH4State*)cpu_env)->gregs[1] = host_pipe[1]; + return host_pipe[0]; +diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h +index 0b13975937..7e2915d53e 100644 +--- a/linux-user/syscall_defs.h ++++ b/linux-user/syscall_defs.h +@@ -74,7 +74,7 @@ + || defined(TARGET_M68K) || defined(TARGET_CRIS) \ + || defined(TARGET_S390X) || defined(TARGET_OPENRISC) \ + || defined(TARGET_NIOS2) || defined(TARGET_RISCV) \ +- || defined(TARGET_XTENSA) ++ || defined(TARGET_XTENSA) || defined(TARGET_LOONGARCH64) + + #define TARGET_IOC_SIZEBITS 14 + #define TARGET_IOC_DIRBITS 2 +@@ -450,7 +450,7 @@ struct target_dirent64 { + #define TARGET_SIG_IGN ((abi_long)1) /* ignore signal */ + #define TARGET_SIG_ERR ((abi_long)-1) /* error return from signal */ + +-#ifdef TARGET_MIPS ++#if defined(TARGET_MIPS) || defined(TARGET_LOONGARCH64) + #define TARGET_NSIG 128 + #else + #define TARGET_NSIG 64 +@@ -2133,7 +2133,7 @@ struct target_stat64 { + abi_ulong __unused5; + }; + +-#elif defined(TARGET_OPENRISC) || defined(TARGET_NIOS2) || defined(TARGET_RISCV) ++#elif defined(TARGET_OPENRISC) || defined(TARGET_NIOS2) || defined(TARGET_RISCV) || defined(TARGET_LOONGARCH64) + + /* These are the asm-generic versions of the stat and stat64 structures */ + +@@ -2161,7 +2161,7 @@ struct target_stat { + unsigned int __unused5; + }; + +-#if !defined(TARGET_RISCV64) ++#if !(defined(TARGET_RISCV64) || defined(TARGET_LOONGARCH64)) + #define TARGET_HAS_STRUCT_STAT64 + struct target_stat64 { + uint64_t st_dev; +@@ -2331,6 +2331,7 @@ struct target_statfs64 { + }; + #elif (defined(TARGET_PPC64) || defined(TARGET_X86_64) || \ + defined(TARGET_SPARC64) || defined(TARGET_AARCH64) || \ ++ defined(TARGET_LOONGARCH64) || \ + defined(TARGET_RISCV)) && !defined(TARGET_ABI32) + struct target_statfs { + abi_long f_type; +diff --git a/meson.build b/meson.build +index 5f6ba86dbb..fc2dc58f33 100644 +--- a/meson.build ++++ b/meson.build +@@ -1814,6 +1814,7 @@ disassemblers = { + 'sh4' : ['CONFIG_SH4_DIS'], + 'sparc' : ['CONFIG_SPARC_DIS'], + 'xtensa' : ['CONFIG_XTENSA_DIS'], ++ 'loongarch64' : ['CONFIG_LOONGARCH_DIS'], + } + if link_language == 'cpp' + disassemblers += { + +diff --git a/pc-bios/meson.build b/pc-bios/meson.build +index b40ff3f2bd..a09ca4d03c 100644 +--- a/pc-bios/meson.build ++++ b/pc-bios/meson.build +@@ -83,6 +83,7 @@ blobs = files( + 'opensbi-riscv32-generic-fw_dynamic.elf', + 'opensbi-riscv64-generic-fw_dynamic.elf', + 'npcm7xx_bootrom.bin', ++ 'loongarch_bios.bin', + ) + + if get_option('install_blobs') +diff --git a/qapi/machine-target.json b/qapi/machine-target.json +index f5ec4bc172..682dc86b42 100644 +--- a/qapi/machine-target.json ++++ b/qapi/machine-target.json +@@ -324,7 +324,8 @@ + 'TARGET_ARM', + 'TARGET_I386', + 'TARGET_S390X', +- 'TARGET_MIPS' ] } } ++ 'TARGET_MIPS', ++ 'TARGET_LOONGARCH64' ] } } + + ## + # @query-cpu-definitions: +@@ -340,4 +341,5 @@ + 'TARGET_ARM', + 'TARGET_I386', + 'TARGET_S390X', +- 'TARGET_MIPS' ] } } ++ 'TARGET_MIPS', ++ 'TARGET_LOONGARCH64' ] } } +diff --git a/qapi/machine.json b/qapi/machine.json +index a9f33d0f27..cd47b8d6bc 100644 +--- a/qapi/machine.json ++++ b/qapi/machine.json +@@ -34,7 +34,7 @@ + 'mips64el', 'mipsel', 'nios2', 'or1k', 'ppc', + 'ppc64', 'riscv32', 'riscv64', 'rx', 's390x', 'sh4', + 'sh4eb', 'sparc', 'sparc64', 'tricore', +- 'x86_64', 'xtensa', 'xtensaeb' ] } ++ 'x86_64', 'xtensa', 'xtensaeb', 'loongarch64' ] } + + ## + # @CpuS390State: +diff --git a/qapi/misc-target.json b/qapi/misc-target.json +index 4bc45d2474..63cebef573 100644 +--- a/qapi/misc-target.json ++++ b/qapi/misc-target.json +@@ -33,6 +33,7 @@ + 'TARGET_PPC64', + 'TARGET_S390X', + 'TARGET_SH4', ++ 'TARGET_LOONGARCH64', + 'TARGET_SPARC' ] } } + + ## +-- +2.27.0 + diff --git a/0008-Modify-compile-script.patch b/0008-Modify-compile-script.patch new file mode 100644 index 0000000..87054ee --- /dev/null +++ b/0008-Modify-compile-script.patch @@ -0,0 +1,36 @@ +From b051f9fdabc2cd49c1c80ef50bbee276b6946609 Mon Sep 17 00:00:00 2001 +From: lixianglai +Date: Mon, 22 Aug 2022 08:22:03 -0400 +Subject: [PATCH 08/10] Modify compile script. + +Change-Id: I8573477d64f5974092001869d7aa9bb093f347e8 +Signed-off-by: lixianglai +--- + meson.build | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/meson.build b/meson.build +index fc2dc58f33..c0fb5788f7 100644 +--- a/meson.build ++++ b/meson.build +@@ -56,7 +56,7 @@ python = import('python').find_installation() + + supported_oses = ['windows', 'freebsd', 'netbsd', 'openbsd', 'darwin', 'sunos', 'linux'] + supported_cpus = ['ppc', 'ppc64', 's390x', 'riscv', 'x86', 'x86_64', +- 'arm', 'aarch64', 'mips', 'mips64', 'sparc', 'sparc64'] ++ 'arm', 'aarch64', 'mips', 'mips64', 'sparc', 'sparc64', 'loongarch64'] + + cpu = host_machine.cpu_family() + +@@ -77,6 +77,8 @@ elif cpu in ['ppc', 'ppc64'] + kvm_targets = ['ppc-softmmu', 'ppc64-softmmu'] + elif cpu in ['mips', 'mips64'] + kvm_targets = ['mips-softmmu', 'mipsel-softmmu', 'mips64-softmmu', 'mips64el-softmmu'] ++elif cpu == 'loongarch64' ++ kvm_targets = ['loongarch64-softmmu'] + else + kvm_targets = [] + endif +-- +2.27.0 + diff --git a/0009-Add-loongarch64-rh-devices.mak.patch b/0009-Add-loongarch64-rh-devices.mak.patch new file mode 100644 index 0000000..ef7533d --- /dev/null +++ b/0009-Add-loongarch64-rh-devices.mak.patch @@ -0,0 +1,3227 @@ +From d2163a939cd14d3d9a8a4afb9d9eacbb71b61517 Mon Sep 17 00:00:00 2001 +From: lixianglai +Date: Wed, 24 Aug 2022 22:56:29 -0400 +Subject: [PATCH 09/10] Add loongarch64-rh-devices.mak. + +Change-Id: I375face82c0aa68c053254b879267830d6981756 +Signed-off-by: lixianglai +--- + .../loongarch64-rh-devices.mak | 155 ++ + configure | 5 + + meson.build | 2 + + pc-bios/meson.build | 1 + + tcg/loongarch64/tcg-insn-defs.c.inc | 979 +++++++++ + tcg/loongarch64/tcg-target-con-set.h | 31 + + tcg/loongarch64/tcg-target-con-str.h | 28 + + tcg/loongarch64/tcg-target.c.inc | 1744 +++++++++++++++++ + tcg/loongarch64/tcg-target.h | 178 ++ + 9 files changed, 3123 insertions(+) + create mode 100644 configs/devices/loongarch64-softmmu/loongarch64-rh-devices.mak + create mode 100644 tcg/loongarch64/tcg-insn-defs.c.inc + create mode 100644 tcg/loongarch64/tcg-target-con-set.h + create mode 100644 tcg/loongarch64/tcg-target-con-str.h + create mode 100644 tcg/loongarch64/tcg-target.c.inc + create mode 100644 tcg/loongarch64/tcg-target.h + +diff --git a/configs/devices/loongarch64-softmmu/loongarch64-rh-devices.mak b/configs/devices/loongarch64-softmmu/loongarch64-rh-devices.mak +new file mode 100644 +index 0000000000..e7b5bdc8e9 +--- /dev/null ++++ b/configs/devices/loongarch64-softmmu/loongarch64-rh-devices.mak +@@ -0,0 +1,155 @@ ++ ++include ../rh-virtio.mak ++# Default configuration for loongarch-softmmu ++ ++CONFIG_PCI=y ++CONFIG_ACPI_PCI=y ++# For now, CONFIG_IDE_CORE requires ISA, so we enable it here ++CONFIG_ISA_BUS=y ++CONFIG_VIRTIO_PCI=y ++ ++CONFIG_VGA_PCI=y ++CONFIG_ACPI_SMBUS=y ++#CONFIG_VHOST_USER_SCSI=$(call land,$(CONFIG_VHOST_USER),$(CONFIG_LINUX)) ++CONFIG_VHOST_USER_SCSI=y ++#CONFIG_VHOST_USER_BLK=$(call land,$(CONFIG_VHOST_USER),$(CONFIG_LINUX)) ++CONFIG_VHOST_USER_BLK=y ++CONFIG_VIRTIO=y ++CONFIG_VIRTIO_BALLOON=y ++CONFIG_VIRTIO_BLK=y ++CONFIG_VIRTIO_CRYPTO=y ++CONFIG_VIRTIO_GPU=y ++CONFIG_VIRTIO_INPUT=y ++CONFIG_VIRTIO_NET=y ++CONFIG_VIRTIO_RNG=y ++CONFIG_SCSI=y ++CONFIG_VIRTIO_SCSI=y ++CONFIG_VIRTIO_SERIAL=y ++ ++CONFIG_USB_UHCI=y ++CONFIG_USB_OHCI=y ++CONFIG_USB_OHCI_PCI=y ++CONFIG_USB_XHCI=y ++CONFIG_USB_XHCI_NEC=y ++CONFIG_NE2000_PCI=y ++CONFIG_EEPRO100_PCI=y ++CONFIG_PCNET_PCI=y ++CONFIG_PCNET_COMMON=y ++CONFIG_AC97=y ++CONFIG_HDA=y ++CONFIG_ES1370=y ++CONFIG_SCSI=y ++CONFIG_LSI_SCSI_PCI=y ++CONFIG_VMW_PVSCSI_SCSI_PCI=y ++CONFIG_MEGASAS_SCSI_PCI=y ++CONFIG_MPTSAS_SCSI_PCI=y ++CONFIG_RTL8139_PCI=y ++CONFIG_E1000_PCI=y ++CONFIG_IDE_CORE=y ++CONFIG_IDE_QDEV=y ++CONFIG_IDE_PCI=y ++CONFIG_AHCI=y ++CONFIG_AHCI_ICH9=y ++CONFIG_ESP=y ++CONFIG_ESP_PCI=y ++CONFIG_SERIAL=y ++CONFIG_SERIAL_ISA=y ++CONFIG_SERIAL_PCI=y ++CONFIG_CAN_BUS=y ++CONFIG_CAN_SJA1000=y ++CONFIG_CAN_PCI=y ++CONFIG_USB_UHCI=y ++CONFIG_USB_OHCI=y ++CONFIG_USB_XHCI=y ++CONFIG_USB_XHCI_NEC=y ++CONFIG_NE2000_PCI=y ++CONFIG_EEPRO100_PCI=y ++CONFIG_PCNET_PCI=y ++CONFIG_PCNET_COMMON=y ++CONFIG_AC97=y ++CONFIG_HDA=y ++CONFIG_ES1370=y ++CONFIG_SCSI=y ++CONFIG_LSI_SCSI_PCI=y ++CONFIG_VMW_PVSCSI_SCSI_PCI=y ++CONFIG_MEGASAS_SCSI_PCI=y ++CONFIG_MPTSAS_SCSI_PCI=y ++CONFIG_RTL8139_PCI=y ++CONFIG_E1000_PCI=y ++CONFIG_IDE_CORE=y ++CONFIG_IDE_QDEV=y ++CONFIG_IDE_PCI=y ++CONFIG_AHCI=y ++CONFIG_ESP=y ++CONFIG_ESP_PCI=y ++CONFIG_SERIAL=y ++CONFIG_SERIAL_ISA=y ++CONFIG_SERIAL_PCI=y ++CONFIG_CAN_BUS=y ++CONFIG_CAN_SJA1000=y ++CONFIG_CAN_PCI=y ++ ++CONFIG_SPICE=y ++CONFIG_QXL=y ++CONFIG_ESP=y ++CONFIG_SCSI=y ++CONFIG_VGA_ISA=y ++CONFIG_VGA_ISA_MM=y ++CONFIG_VGA_CIRRUS=y ++CONFIG_VMWARE_VGA=y ++CONFIG_VIRTIO_VGA=y ++CONFIG_SERIAL_ISA=y ++CONFIG_PARALLEL=y ++CONFIG_I8254=y ++CONFIG_PCSPK=y ++CONFIG_PCKBD=y ++CONFIG_FDC=y ++CONFIG_ACPI=y ++CONFIG_ACPI_MEMORY_HOTPLUG=y ++CONFIG_ACPI_NVDIMM=y ++CONFIG_ACPI_CPU_HOTPLUG=y ++CONFIG_APM=y ++CONFIG_I8257=y ++CONFIG_PIIX4=y ++CONFIG_IDE_ISA=y ++CONFIG_IDE_PIIX=y ++#CONFIG_NE2000_ISA=y ++CONFIG_MIPSNET=y ++CONFIG_PFLASH_CFI01=y ++CONFIG_I8259=y ++CONFIG_MC146818RTC=y ++CONFIG_ISA_TESTDEV=y ++CONFIG_EMPTY_SLOT=y ++CONFIG_I2C=y ++CONFIG_DIMM=y ++CONFIG_MEM_DEVICE=y ++ ++# Arch Specified CONFIG defines ++CONFIG_IDE_VIA=y ++CONFIG_VT82C686=y ++CONFIG_RC4030=y ++CONFIG_DP8393X=y ++CONFIG_DS1225Y=y ++CONFIG_FITLOADER=y ++CONFIG_SMBIOS=y ++ ++CONFIG_PCIE_PORT=y ++CONFIG_I82801B11=y ++CONFIG_XIO3130=y ++CONFIG_PCI_EXPRESS=y ++CONFIG_MSI_NONBROKEN=y ++CONFIG_IOH3420=y ++CONFIG_SD=y ++CONFIG_SDHCI=y ++CONFIG_VIRTFS=y ++CONFIG_VIRTIO_9P=y ++CONFIG_USB_EHCI=y ++CONFIG_USB_EHCI_PCI=y ++CONFIG_USB_EHCI_SYSBUS=y ++CONFIG_USB_STORAGE_BOT=y ++CONFIG_TPM_EMULATOR=y ++CONFIG_TPM_TIS=y ++CONFIG_PLATFORM_BUS=y ++CONFIG_TPM_TIS_SYSBUS=y ++CONFIG_ACPI_LOONGARCH=y ++CONFIG_LS7A_RTC=y +diff --git a/configure b/configure +index 48c21775f3..1f932f7eeb 100755 +--- a/configure ++++ b/configure +@@ -581,6 +581,8 @@ elif check_define __arm__ ; then + cpu="arm" + elif check_define __aarch64__ ; then + cpu="aarch64" ++elif check_define __loongarch__ ; then ++ cpu="loongarch64" + else + cpu=$(uname -m) + fi +@@ -606,6 +608,9 @@ case "$cpu" in + aarch64) + cpu="aarch64" + ;; ++ loongarch64) ++ cpu="loongarch64" ++ ;; + mips*) + cpu="mips" + ;; +diff --git a/meson.build b/meson.build +index c0fb5788f7..c5fdb78569 100644 +--- a/meson.build ++++ b/meson.build +@@ -361,6 +361,8 @@ if not get_option('tcg').disabled() + tcg_arch = 'i386' + elif config_host['ARCH'] == 'ppc64' + tcg_arch = 'ppc' ++ elif config_host['ARCH'] == 'loongarch64' ++ tcg_arch = 'loongarch64' + endif + add_project_arguments('-iquote', meson.current_source_dir() / 'tcg' / tcg_arch, + language: ['c', 'cpp', 'objc']) +diff --git a/pc-bios/meson.build b/pc-bios/meson.build +index a09ca4d03c..60009bd89e 100644 +--- a/pc-bios/meson.build ++++ b/pc-bios/meson.build +@@ -84,6 +84,7 @@ blobs = files( + 'opensbi-riscv64-generic-fw_dynamic.elf', + 'npcm7xx_bootrom.bin', + 'loongarch_bios.bin', ++ 'loongarch_vars.bin', + ) + + if get_option('install_blobs') +diff --git a/tcg/loongarch64/tcg-insn-defs.c.inc b/tcg/loongarch64/tcg-insn-defs.c.inc +new file mode 100644 +index 0000000000..d162571856 +--- /dev/null ++++ b/tcg/loongarch64/tcg-insn-defs.c.inc +@@ -0,0 +1,979 @@ ++/* SPDX-License-Identifier: MIT */ ++/* ++ * LoongArch instruction formats, opcodes, and encoders for TCG use. ++ * ++ * This file is auto-generated by genqemutcgdefs from ++ * https://github.com/loongson-community/loongarch-opcodes, ++ * from commit 961f0c60f5b63e574d785995600c71ad5413fdc4. ++ * DO NOT EDIT. ++ */ ++ ++typedef enum { ++ OPC_CLZ_W = 0x00001400, ++ OPC_CTZ_W = 0x00001c00, ++ OPC_CLZ_D = 0x00002400, ++ OPC_CTZ_D = 0x00002c00, ++ OPC_REVB_2H = 0x00003000, ++ OPC_REVB_2W = 0x00003800, ++ OPC_REVB_D = 0x00003c00, ++ OPC_SEXT_H = 0x00005800, ++ OPC_SEXT_B = 0x00005c00, ++ OPC_ADD_W = 0x00100000, ++ OPC_ADD_D = 0x00108000, ++ OPC_SUB_W = 0x00110000, ++ OPC_SUB_D = 0x00118000, ++ OPC_SLT = 0x00120000, ++ OPC_SLTU = 0x00128000, ++ OPC_MASKEQZ = 0x00130000, ++ OPC_MASKNEZ = 0x00138000, ++ OPC_NOR = 0x00140000, ++ OPC_AND = 0x00148000, ++ OPC_OR = 0x00150000, ++ OPC_XOR = 0x00158000, ++ OPC_ORN = 0x00160000, ++ OPC_ANDN = 0x00168000, ++ OPC_SLL_W = 0x00170000, ++ OPC_SRL_W = 0x00178000, ++ OPC_SRA_W = 0x00180000, ++ OPC_SLL_D = 0x00188000, ++ OPC_SRL_D = 0x00190000, ++ OPC_SRA_D = 0x00198000, ++ OPC_ROTR_W = 0x001b0000, ++ OPC_ROTR_D = 0x001b8000, ++ OPC_MUL_W = 0x001c0000, ++ OPC_MULH_W = 0x001c8000, ++ OPC_MULH_WU = 0x001d0000, ++ OPC_MUL_D = 0x001d8000, ++ OPC_MULH_D = 0x001e0000, ++ OPC_MULH_DU = 0x001e8000, ++ OPC_DIV_W = 0x00200000, ++ OPC_MOD_W = 0x00208000, ++ OPC_DIV_WU = 0x00210000, ++ OPC_MOD_WU = 0x00218000, ++ OPC_DIV_D = 0x00220000, ++ OPC_MOD_D = 0x00228000, ++ OPC_DIV_DU = 0x00230000, ++ OPC_MOD_DU = 0x00238000, ++ OPC_SLLI_W = 0x00408000, ++ OPC_SLLI_D = 0x00410000, ++ OPC_SRLI_W = 0x00448000, ++ OPC_SRLI_D = 0x00450000, ++ OPC_SRAI_W = 0x00488000, ++ OPC_SRAI_D = 0x00490000, ++ OPC_ROTRI_W = 0x004c8000, ++ OPC_ROTRI_D = 0x004d0000, ++ OPC_BSTRINS_W = 0x00600000, ++ OPC_BSTRPICK_W = 0x00608000, ++ OPC_BSTRINS_D = 0x00800000, ++ OPC_BSTRPICK_D = 0x00c00000, ++ OPC_SLTI = 0x02000000, ++ OPC_SLTUI = 0x02400000, ++ OPC_ADDI_W = 0x02800000, ++ OPC_ADDI_D = 0x02c00000, ++ OPC_CU52I_D = 0x03000000, ++ OPC_ANDI = 0x03400000, ++ OPC_ORI = 0x03800000, ++ OPC_XORI = 0x03c00000, ++ OPC_LU12I_W = 0x14000000, ++ OPC_CU32I_D = 0x16000000, ++ OPC_PCADDU2I = 0x18000000, ++ OPC_PCALAU12I = 0x1a000000, ++ OPC_PCADDU12I = 0x1c000000, ++ OPC_PCADDU18I = 0x1e000000, ++ OPC_LD_B = 0x28000000, ++ OPC_LD_H = 0x28400000, ++ OPC_LD_W = 0x28800000, ++ OPC_LD_D = 0x28c00000, ++ OPC_ST_B = 0x29000000, ++ OPC_ST_H = 0x29400000, ++ OPC_ST_W = 0x29800000, ++ OPC_ST_D = 0x29c00000, ++ OPC_LD_BU = 0x2a000000, ++ OPC_LD_HU = 0x2a400000, ++ OPC_LD_WU = 0x2a800000, ++ OPC_LDX_B = 0x38000000, ++ OPC_LDX_H = 0x38040000, ++ OPC_LDX_W = 0x38080000, ++ OPC_LDX_D = 0x380c0000, ++ OPC_STX_B = 0x38100000, ++ OPC_STX_H = 0x38140000, ++ OPC_STX_W = 0x38180000, ++ OPC_STX_D = 0x381c0000, ++ OPC_LDX_BU = 0x38200000, ++ OPC_LDX_HU = 0x38240000, ++ OPC_LDX_WU = 0x38280000, ++ OPC_DBAR = 0x38720000, ++ OPC_JIRL = 0x4c000000, ++ OPC_B = 0x50000000, ++ OPC_BL = 0x54000000, ++ OPC_BEQ = 0x58000000, ++ OPC_BNE = 0x5c000000, ++ OPC_BGT = 0x60000000, ++ OPC_BLE = 0x64000000, ++ OPC_BGTU = 0x68000000, ++ OPC_BLEU = 0x6c000000, ++} LoongArchInsn; ++ ++static int32_t __attribute__((unused)) ++encode_d_slot(LoongArchInsn opc, uint32_t d) ++{ ++ return opc | d; ++} ++ ++static int32_t __attribute__((unused)) ++encode_dj_slots(LoongArchInsn opc, uint32_t d, uint32_t j) ++{ ++ return opc | d | j << 5; ++} ++ ++static int32_t __attribute__((unused)) ++encode_djk_slots(LoongArchInsn opc, uint32_t d, uint32_t j, uint32_t k) ++{ ++ return opc | d | j << 5 | k << 10; ++} ++ ++static int32_t __attribute__((unused)) ++encode_djkm_slots(LoongArchInsn opc, uint32_t d, uint32_t j, uint32_t k, ++ uint32_t m) ++{ ++ return opc | d | j << 5 | k << 10 | m << 16; ++} ++ ++static int32_t __attribute__((unused)) ++encode_dk_slots(LoongArchInsn opc, uint32_t d, uint32_t k) ++{ ++ return opc | d | k << 10; ++} ++ ++static int32_t __attribute__((unused)) ++encode_dj_insn(LoongArchInsn opc, TCGReg d, TCGReg j) ++{ ++ tcg_debug_assert(d >= 0 && d <= 0x1f); ++ tcg_debug_assert(j >= 0 && j <= 0x1f); ++ return encode_dj_slots(opc, d, j); ++} ++ ++static int32_t __attribute__((unused)) ++encode_djk_insn(LoongArchInsn opc, TCGReg d, TCGReg j, TCGReg k) ++{ ++ tcg_debug_assert(d >= 0 && d <= 0x1f); ++ tcg_debug_assert(j >= 0 && j <= 0x1f); ++ tcg_debug_assert(k >= 0 && k <= 0x1f); ++ return encode_djk_slots(opc, d, j, k); ++} ++ ++static int32_t __attribute__((unused)) ++encode_djsk12_insn(LoongArchInsn opc, TCGReg d, TCGReg j, int32_t sk12) ++{ ++ tcg_debug_assert(d >= 0 && d <= 0x1f); ++ tcg_debug_assert(j >= 0 && j <= 0x1f); ++ tcg_debug_assert(sk12 >= -0x800 && sk12 <= 0x7ff); ++ return encode_djk_slots(opc, d, j, sk12 & 0xfff); ++} ++ ++static int32_t __attribute__((unused)) ++encode_djsk16_insn(LoongArchInsn opc, TCGReg d, TCGReg j, int32_t sk16) ++{ ++ tcg_debug_assert(d >= 0 && d <= 0x1f); ++ tcg_debug_assert(j >= 0 && j <= 0x1f); ++ tcg_debug_assert(sk16 >= -0x8000 && sk16 <= 0x7fff); ++ return encode_djk_slots(opc, d, j, sk16 & 0xffff); ++} ++ ++static int32_t __attribute__((unused)) ++encode_djuk12_insn(LoongArchInsn opc, TCGReg d, TCGReg j, uint32_t uk12) ++{ ++ tcg_debug_assert(d >= 0 && d <= 0x1f); ++ tcg_debug_assert(j >= 0 && j <= 0x1f); ++ tcg_debug_assert(uk12 <= 0xfff); ++ return encode_djk_slots(opc, d, j, uk12); ++} ++ ++static int32_t __attribute__((unused)) ++encode_djuk5_insn(LoongArchInsn opc, TCGReg d, TCGReg j, uint32_t uk5) ++{ ++ tcg_debug_assert(d >= 0 && d <= 0x1f); ++ tcg_debug_assert(j >= 0 && j <= 0x1f); ++ tcg_debug_assert(uk5 <= 0x1f); ++ return encode_djk_slots(opc, d, j, uk5); ++} ++ ++static int32_t __attribute__((unused)) ++encode_djuk5um5_insn(LoongArchInsn opc, TCGReg d, TCGReg j, uint32_t uk5, ++ uint32_t um5) ++{ ++ tcg_debug_assert(d >= 0 && d <= 0x1f); ++ tcg_debug_assert(j >= 0 && j <= 0x1f); ++ tcg_debug_assert(uk5 <= 0x1f); ++ tcg_debug_assert(um5 <= 0x1f); ++ return encode_djkm_slots(opc, d, j, uk5, um5); ++} ++ ++static int32_t __attribute__((unused)) ++encode_djuk6_insn(LoongArchInsn opc, TCGReg d, TCGReg j, uint32_t uk6) ++{ ++ tcg_debug_assert(d >= 0 && d <= 0x1f); ++ tcg_debug_assert(j >= 0 && j <= 0x1f); ++ tcg_debug_assert(uk6 <= 0x3f); ++ return encode_djk_slots(opc, d, j, uk6); ++} ++ ++static int32_t __attribute__((unused)) ++encode_djuk6um6_insn(LoongArchInsn opc, TCGReg d, TCGReg j, uint32_t uk6, ++ uint32_t um6) ++{ ++ tcg_debug_assert(d >= 0 && d <= 0x1f); ++ tcg_debug_assert(j >= 0 && j <= 0x1f); ++ tcg_debug_assert(uk6 <= 0x3f); ++ tcg_debug_assert(um6 <= 0x3f); ++ return encode_djkm_slots(opc, d, j, uk6, um6); ++} ++ ++static int32_t __attribute__((unused)) ++encode_dsj20_insn(LoongArchInsn opc, TCGReg d, int32_t sj20) ++{ ++ tcg_debug_assert(d >= 0 && d <= 0x1f); ++ tcg_debug_assert(sj20 >= -0x80000 && sj20 <= 0x7ffff); ++ return encode_dj_slots(opc, d, sj20 & 0xfffff); ++} ++ ++static int32_t __attribute__((unused)) ++encode_sd10k16_insn(LoongArchInsn opc, int32_t sd10k16) ++{ ++ tcg_debug_assert(sd10k16 >= -0x2000000 && sd10k16 <= 0x1ffffff); ++ return encode_dk_slots(opc, (sd10k16 >> 16) & 0x3ff, sd10k16 & 0xffff); ++} ++ ++static int32_t __attribute__((unused)) ++encode_ud15_insn(LoongArchInsn opc, uint32_t ud15) ++{ ++ tcg_debug_assert(ud15 <= 0x7fff); ++ return encode_d_slot(opc, ud15); ++} ++ ++/* Emits the `clz.w d, j` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_clz_w(TCGContext *s, TCGReg d, TCGReg j) ++{ ++ tcg_out32(s, encode_dj_insn(OPC_CLZ_W, d, j)); ++} ++ ++/* Emits the `ctz.w d, j` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_ctz_w(TCGContext *s, TCGReg d, TCGReg j) ++{ ++ tcg_out32(s, encode_dj_insn(OPC_CTZ_W, d, j)); ++} ++ ++/* Emits the `clz.d d, j` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_clz_d(TCGContext *s, TCGReg d, TCGReg j) ++{ ++ tcg_out32(s, encode_dj_insn(OPC_CLZ_D, d, j)); ++} ++ ++/* Emits the `ctz.d d, j` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_ctz_d(TCGContext *s, TCGReg d, TCGReg j) ++{ ++ tcg_out32(s, encode_dj_insn(OPC_CTZ_D, d, j)); ++} ++ ++/* Emits the `revb.2h d, j` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_revb_2h(TCGContext *s, TCGReg d, TCGReg j) ++{ ++ tcg_out32(s, encode_dj_insn(OPC_REVB_2H, d, j)); ++} ++ ++/* Emits the `revb.2w d, j` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_revb_2w(TCGContext *s, TCGReg d, TCGReg j) ++{ ++ tcg_out32(s, encode_dj_insn(OPC_REVB_2W, d, j)); ++} ++ ++/* Emits the `revb.d d, j` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_revb_d(TCGContext *s, TCGReg d, TCGReg j) ++{ ++ tcg_out32(s, encode_dj_insn(OPC_REVB_D, d, j)); ++} ++ ++/* Emits the `sext.h d, j` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_sext_h(TCGContext *s, TCGReg d, TCGReg j) ++{ ++ tcg_out32(s, encode_dj_insn(OPC_SEXT_H, d, j)); ++} ++ ++/* Emits the `sext.b d, j` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_sext_b(TCGContext *s, TCGReg d, TCGReg j) ++{ ++ tcg_out32(s, encode_dj_insn(OPC_SEXT_B, d, j)); ++} ++ ++/* Emits the `add.w d, j, k` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_add_w(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) ++{ ++ tcg_out32(s, encode_djk_insn(OPC_ADD_W, d, j, k)); ++} ++ ++/* Emits the `add.d d, j, k` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_add_d(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) ++{ ++ tcg_out32(s, encode_djk_insn(OPC_ADD_D, d, j, k)); ++} ++ ++/* Emits the `sub.w d, j, k` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_sub_w(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) ++{ ++ tcg_out32(s, encode_djk_insn(OPC_SUB_W, d, j, k)); ++} ++ ++/* Emits the `sub.d d, j, k` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_sub_d(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) ++{ ++ tcg_out32(s, encode_djk_insn(OPC_SUB_D, d, j, k)); ++} ++ ++/* Emits the `slt d, j, k` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_slt(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) ++{ ++ tcg_out32(s, encode_djk_insn(OPC_SLT, d, j, k)); ++} ++ ++/* Emits the `sltu d, j, k` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_sltu(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) ++{ ++ tcg_out32(s, encode_djk_insn(OPC_SLTU, d, j, k)); ++} ++ ++/* Emits the `maskeqz d, j, k` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_maskeqz(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) ++{ ++ tcg_out32(s, encode_djk_insn(OPC_MASKEQZ, d, j, k)); ++} ++ ++/* Emits the `masknez d, j, k` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_masknez(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) ++{ ++ tcg_out32(s, encode_djk_insn(OPC_MASKNEZ, d, j, k)); ++} ++ ++/* Emits the `nor d, j, k` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_nor(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) ++{ ++ tcg_out32(s, encode_djk_insn(OPC_NOR, d, j, k)); ++} ++ ++/* Emits the `and d, j, k` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_and(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) ++{ ++ tcg_out32(s, encode_djk_insn(OPC_AND, d, j, k)); ++} ++ ++/* Emits the `or d, j, k` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_or(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) ++{ ++ tcg_out32(s, encode_djk_insn(OPC_OR, d, j, k)); ++} ++ ++/* Emits the `xor d, j, k` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_xor(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) ++{ ++ tcg_out32(s, encode_djk_insn(OPC_XOR, d, j, k)); ++} ++ ++/* Emits the `orn d, j, k` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_orn(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) ++{ ++ tcg_out32(s, encode_djk_insn(OPC_ORN, d, j, k)); ++} ++ ++/* Emits the `andn d, j, k` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_andn(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) ++{ ++ tcg_out32(s, encode_djk_insn(OPC_ANDN, d, j, k)); ++} ++ ++/* Emits the `sll.w d, j, k` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_sll_w(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) ++{ ++ tcg_out32(s, encode_djk_insn(OPC_SLL_W, d, j, k)); ++} ++ ++/* Emits the `srl.w d, j, k` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_srl_w(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) ++{ ++ tcg_out32(s, encode_djk_insn(OPC_SRL_W, d, j, k)); ++} ++ ++/* Emits the `sra.w d, j, k` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_sra_w(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) ++{ ++ tcg_out32(s, encode_djk_insn(OPC_SRA_W, d, j, k)); ++} ++ ++/* Emits the `sll.d d, j, k` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_sll_d(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) ++{ ++ tcg_out32(s, encode_djk_insn(OPC_SLL_D, d, j, k)); ++} ++ ++/* Emits the `srl.d d, j, k` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_srl_d(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) ++{ ++ tcg_out32(s, encode_djk_insn(OPC_SRL_D, d, j, k)); ++} ++ ++/* Emits the `sra.d d, j, k` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_sra_d(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) ++{ ++ tcg_out32(s, encode_djk_insn(OPC_SRA_D, d, j, k)); ++} ++ ++/* Emits the `rotr.w d, j, k` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_rotr_w(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) ++{ ++ tcg_out32(s, encode_djk_insn(OPC_ROTR_W, d, j, k)); ++} ++ ++/* Emits the `rotr.d d, j, k` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_rotr_d(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) ++{ ++ tcg_out32(s, encode_djk_insn(OPC_ROTR_D, d, j, k)); ++} ++ ++/* Emits the `mul.w d, j, k` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_mul_w(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) ++{ ++ tcg_out32(s, encode_djk_insn(OPC_MUL_W, d, j, k)); ++} ++ ++/* Emits the `mulh.w d, j, k` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_mulh_w(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) ++{ ++ tcg_out32(s, encode_djk_insn(OPC_MULH_W, d, j, k)); ++} ++ ++/* Emits the `mulh.wu d, j, k` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_mulh_wu(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) ++{ ++ tcg_out32(s, encode_djk_insn(OPC_MULH_WU, d, j, k)); ++} ++ ++/* Emits the `mul.d d, j, k` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_mul_d(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) ++{ ++ tcg_out32(s, encode_djk_insn(OPC_MUL_D, d, j, k)); ++} ++ ++/* Emits the `mulh.d d, j, k` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_mulh_d(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) ++{ ++ tcg_out32(s, encode_djk_insn(OPC_MULH_D, d, j, k)); ++} ++ ++/* Emits the `mulh.du d, j, k` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_mulh_du(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) ++{ ++ tcg_out32(s, encode_djk_insn(OPC_MULH_DU, d, j, k)); ++} ++ ++/* Emits the `div.w d, j, k` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_div_w(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) ++{ ++ tcg_out32(s, encode_djk_insn(OPC_DIV_W, d, j, k)); ++} ++ ++/* Emits the `mod.w d, j, k` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_mod_w(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) ++{ ++ tcg_out32(s, encode_djk_insn(OPC_MOD_W, d, j, k)); ++} ++ ++/* Emits the `div.wu d, j, k` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_div_wu(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) ++{ ++ tcg_out32(s, encode_djk_insn(OPC_DIV_WU, d, j, k)); ++} ++ ++/* Emits the `mod.wu d, j, k` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_mod_wu(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) ++{ ++ tcg_out32(s, encode_djk_insn(OPC_MOD_WU, d, j, k)); ++} ++ ++/* Emits the `div.d d, j, k` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_div_d(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) ++{ ++ tcg_out32(s, encode_djk_insn(OPC_DIV_D, d, j, k)); ++} ++ ++/* Emits the `mod.d d, j, k` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_mod_d(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) ++{ ++ tcg_out32(s, encode_djk_insn(OPC_MOD_D, d, j, k)); ++} ++ ++/* Emits the `div.du d, j, k` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_div_du(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) ++{ ++ tcg_out32(s, encode_djk_insn(OPC_DIV_DU, d, j, k)); ++} ++ ++/* Emits the `mod.du d, j, k` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_mod_du(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) ++{ ++ tcg_out32(s, encode_djk_insn(OPC_MOD_DU, d, j, k)); ++} ++ ++/* Emits the `slli.w d, j, uk5` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_slli_w(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk5) ++{ ++ tcg_out32(s, encode_djuk5_insn(OPC_SLLI_W, d, j, uk5)); ++} ++ ++/* Emits the `slli.d d, j, uk6` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_slli_d(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk6) ++{ ++ tcg_out32(s, encode_djuk6_insn(OPC_SLLI_D, d, j, uk6)); ++} ++ ++/* Emits the `srli.w d, j, uk5` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_srli_w(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk5) ++{ ++ tcg_out32(s, encode_djuk5_insn(OPC_SRLI_W, d, j, uk5)); ++} ++ ++/* Emits the `srli.d d, j, uk6` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_srli_d(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk6) ++{ ++ tcg_out32(s, encode_djuk6_insn(OPC_SRLI_D, d, j, uk6)); ++} ++ ++/* Emits the `srai.w d, j, uk5` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_srai_w(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk5) ++{ ++ tcg_out32(s, encode_djuk5_insn(OPC_SRAI_W, d, j, uk5)); ++} ++ ++/* Emits the `srai.d d, j, uk6` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_srai_d(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk6) ++{ ++ tcg_out32(s, encode_djuk6_insn(OPC_SRAI_D, d, j, uk6)); ++} ++ ++/* Emits the `rotri.w d, j, uk5` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_rotri_w(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk5) ++{ ++ tcg_out32(s, encode_djuk5_insn(OPC_ROTRI_W, d, j, uk5)); ++} ++ ++/* Emits the `rotri.d d, j, uk6` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_rotri_d(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk6) ++{ ++ tcg_out32(s, encode_djuk6_insn(OPC_ROTRI_D, d, j, uk6)); ++} ++ ++/* Emits the `bstrins.w d, j, uk5, um5` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_bstrins_w(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk5, ++ uint32_t um5) ++{ ++ tcg_out32(s, encode_djuk5um5_insn(OPC_BSTRINS_W, d, j, uk5, um5)); ++} ++ ++/* Emits the `bstrpick.w d, j, uk5, um5` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_bstrpick_w(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk5, ++ uint32_t um5) ++{ ++ tcg_out32(s, encode_djuk5um5_insn(OPC_BSTRPICK_W, d, j, uk5, um5)); ++} ++ ++/* Emits the `bstrins.d d, j, uk6, um6` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_bstrins_d(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk6, ++ uint32_t um6) ++{ ++ tcg_out32(s, encode_djuk6um6_insn(OPC_BSTRINS_D, d, j, uk6, um6)); ++} ++ ++/* Emits the `bstrpick.d d, j, uk6, um6` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_bstrpick_d(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk6, ++ uint32_t um6) ++{ ++ tcg_out32(s, encode_djuk6um6_insn(OPC_BSTRPICK_D, d, j, uk6, um6)); ++} ++ ++/* Emits the `slti d, j, sk12` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_slti(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) ++{ ++ tcg_out32(s, encode_djsk12_insn(OPC_SLTI, d, j, sk12)); ++} ++ ++/* Emits the `sltui d, j, sk12` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_sltui(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) ++{ ++ tcg_out32(s, encode_djsk12_insn(OPC_SLTUI, d, j, sk12)); ++} ++ ++/* Emits the `addi.w d, j, sk12` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_addi_w(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) ++{ ++ tcg_out32(s, encode_djsk12_insn(OPC_ADDI_W, d, j, sk12)); ++} ++ ++/* Emits the `addi.d d, j, sk12` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_addi_d(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) ++{ ++ tcg_out32(s, encode_djsk12_insn(OPC_ADDI_D, d, j, sk12)); ++} ++ ++/* Emits the `cu52i.d d, j, sk12` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_cu52i_d(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) ++{ ++ tcg_out32(s, encode_djsk12_insn(OPC_CU52I_D, d, j, sk12)); ++} ++ ++/* Emits the `andi d, j, uk12` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_andi(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk12) ++{ ++ tcg_out32(s, encode_djuk12_insn(OPC_ANDI, d, j, uk12)); ++} ++ ++/* Emits the `ori d, j, uk12` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_ori(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk12) ++{ ++ tcg_out32(s, encode_djuk12_insn(OPC_ORI, d, j, uk12)); ++} ++ ++/* Emits the `xori d, j, uk12` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_xori(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk12) ++{ ++ tcg_out32(s, encode_djuk12_insn(OPC_XORI, d, j, uk12)); ++} ++ ++/* Emits the `lu12i.w d, sj20` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_lu12i_w(TCGContext *s, TCGReg d, int32_t sj20) ++{ ++ tcg_out32(s, encode_dsj20_insn(OPC_LU12I_W, d, sj20)); ++} ++ ++/* Emits the `cu32i.d d, sj20` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_cu32i_d(TCGContext *s, TCGReg d, int32_t sj20) ++{ ++ tcg_out32(s, encode_dsj20_insn(OPC_CU32I_D, d, sj20)); ++} ++ ++/* Emits the `pcaddu2i d, sj20` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_pcaddu2i(TCGContext *s, TCGReg d, int32_t sj20) ++{ ++ tcg_out32(s, encode_dsj20_insn(OPC_PCADDU2I, d, sj20)); ++} ++ ++/* Emits the `pcalau12i d, sj20` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_pcalau12i(TCGContext *s, TCGReg d, int32_t sj20) ++{ ++ tcg_out32(s, encode_dsj20_insn(OPC_PCALAU12I, d, sj20)); ++} ++ ++/* Emits the `pcaddu12i d, sj20` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_pcaddu12i(TCGContext *s, TCGReg d, int32_t sj20) ++{ ++ tcg_out32(s, encode_dsj20_insn(OPC_PCADDU12I, d, sj20)); ++} ++ ++/* Emits the `pcaddu18i d, sj20` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_pcaddu18i(TCGContext *s, TCGReg d, int32_t sj20) ++{ ++ tcg_out32(s, encode_dsj20_insn(OPC_PCADDU18I, d, sj20)); ++} ++ ++/* Emits the `ld.b d, j, sk12` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_ld_b(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) ++{ ++ tcg_out32(s, encode_djsk12_insn(OPC_LD_B, d, j, sk12)); ++} ++ ++/* Emits the `ld.h d, j, sk12` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_ld_h(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) ++{ ++ tcg_out32(s, encode_djsk12_insn(OPC_LD_H, d, j, sk12)); ++} ++ ++/* Emits the `ld.w d, j, sk12` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_ld_w(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) ++{ ++ tcg_out32(s, encode_djsk12_insn(OPC_LD_W, d, j, sk12)); ++} ++ ++/* Emits the `ld.d d, j, sk12` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_ld_d(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) ++{ ++ tcg_out32(s, encode_djsk12_insn(OPC_LD_D, d, j, sk12)); ++} ++ ++/* Emits the `st.b d, j, sk12` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_st_b(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) ++{ ++ tcg_out32(s, encode_djsk12_insn(OPC_ST_B, d, j, sk12)); ++} ++ ++/* Emits the `st.h d, j, sk12` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_st_h(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) ++{ ++ tcg_out32(s, encode_djsk12_insn(OPC_ST_H, d, j, sk12)); ++} ++ ++/* Emits the `st.w d, j, sk12` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_st_w(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) ++{ ++ tcg_out32(s, encode_djsk12_insn(OPC_ST_W, d, j, sk12)); ++} ++ ++/* Emits the `st.d d, j, sk12` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_st_d(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) ++{ ++ tcg_out32(s, encode_djsk12_insn(OPC_ST_D, d, j, sk12)); ++} ++ ++/* Emits the `ld.bu d, j, sk12` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_ld_bu(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) ++{ ++ tcg_out32(s, encode_djsk12_insn(OPC_LD_BU, d, j, sk12)); ++} ++ ++/* Emits the `ld.hu d, j, sk12` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_ld_hu(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) ++{ ++ tcg_out32(s, encode_djsk12_insn(OPC_LD_HU, d, j, sk12)); ++} ++ ++/* Emits the `ld.wu d, j, sk12` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_ld_wu(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) ++{ ++ tcg_out32(s, encode_djsk12_insn(OPC_LD_WU, d, j, sk12)); ++} ++ ++/* Emits the `ldx.b d, j, k` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_ldx_b(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) ++{ ++ tcg_out32(s, encode_djk_insn(OPC_LDX_B, d, j, k)); ++} ++ ++/* Emits the `ldx.h d, j, k` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_ldx_h(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) ++{ ++ tcg_out32(s, encode_djk_insn(OPC_LDX_H, d, j, k)); ++} ++ ++/* Emits the `ldx.w d, j, k` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_ldx_w(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) ++{ ++ tcg_out32(s, encode_djk_insn(OPC_LDX_W, d, j, k)); ++} ++ ++/* Emits the `ldx.d d, j, k` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_ldx_d(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) ++{ ++ tcg_out32(s, encode_djk_insn(OPC_LDX_D, d, j, k)); ++} ++ ++/* Emits the `stx.b d, j, k` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_stx_b(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) ++{ ++ tcg_out32(s, encode_djk_insn(OPC_STX_B, d, j, k)); ++} ++ ++/* Emits the `stx.h d, j, k` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_stx_h(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) ++{ ++ tcg_out32(s, encode_djk_insn(OPC_STX_H, d, j, k)); ++} ++ ++/* Emits the `stx.w d, j, k` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_stx_w(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) ++{ ++ tcg_out32(s, encode_djk_insn(OPC_STX_W, d, j, k)); ++} ++ ++/* Emits the `stx.d d, j, k` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_stx_d(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) ++{ ++ tcg_out32(s, encode_djk_insn(OPC_STX_D, d, j, k)); ++} ++ ++/* Emits the `ldx.bu d, j, k` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_ldx_bu(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) ++{ ++ tcg_out32(s, encode_djk_insn(OPC_LDX_BU, d, j, k)); ++} ++ ++/* Emits the `ldx.hu d, j, k` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_ldx_hu(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) ++{ ++ tcg_out32(s, encode_djk_insn(OPC_LDX_HU, d, j, k)); ++} ++ ++/* Emits the `ldx.wu d, j, k` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_ldx_wu(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) ++{ ++ tcg_out32(s, encode_djk_insn(OPC_LDX_WU, d, j, k)); ++} ++ ++/* Emits the `dbar ud15` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_dbar(TCGContext *s, uint32_t ud15) ++{ ++ tcg_out32(s, encode_ud15_insn(OPC_DBAR, ud15)); ++} ++ ++/* Emits the `jirl d, j, sk16` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_jirl(TCGContext *s, TCGReg d, TCGReg j, int32_t sk16) ++{ ++ tcg_out32(s, encode_djsk16_insn(OPC_JIRL, d, j, sk16)); ++} ++ ++/* Emits the `b sd10k16` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_b(TCGContext *s, int32_t sd10k16) ++{ ++ tcg_out32(s, encode_sd10k16_insn(OPC_B, sd10k16)); ++} ++ ++/* Emits the `bl sd10k16` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_bl(TCGContext *s, int32_t sd10k16) ++{ ++ tcg_out32(s, encode_sd10k16_insn(OPC_BL, sd10k16)); ++} ++ ++/* Emits the `beq d, j, sk16` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_beq(TCGContext *s, TCGReg d, TCGReg j, int32_t sk16) ++{ ++ tcg_out32(s, encode_djsk16_insn(OPC_BEQ, d, j, sk16)); ++} ++ ++/* Emits the `bne d, j, sk16` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_bne(TCGContext *s, TCGReg d, TCGReg j, int32_t sk16) ++{ ++ tcg_out32(s, encode_djsk16_insn(OPC_BNE, d, j, sk16)); ++} ++ ++/* Emits the `bgt d, j, sk16` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_bgt(TCGContext *s, TCGReg d, TCGReg j, int32_t sk16) ++{ ++ tcg_out32(s, encode_djsk16_insn(OPC_BGT, d, j, sk16)); ++} ++ ++/* Emits the `ble d, j, sk16` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_ble(TCGContext *s, TCGReg d, TCGReg j, int32_t sk16) ++{ ++ tcg_out32(s, encode_djsk16_insn(OPC_BLE, d, j, sk16)); ++} ++ ++/* Emits the `bgtu d, j, sk16` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_bgtu(TCGContext *s, TCGReg d, TCGReg j, int32_t sk16) ++{ ++ tcg_out32(s, encode_djsk16_insn(OPC_BGTU, d, j, sk16)); ++} ++ ++/* Emits the `bleu d, j, sk16` instruction. */ ++static void __attribute__((unused)) ++tcg_out_opc_bleu(TCGContext *s, TCGReg d, TCGReg j, int32_t sk16) ++{ ++ tcg_out32(s, encode_djsk16_insn(OPC_BLEU, d, j, sk16)); ++} ++ ++/* End of generated code. */ +diff --git a/tcg/loongarch64/tcg-target-con-set.h b/tcg/loongarch64/tcg-target-con-set.h +new file mode 100644 +index 0000000000..349c672687 +--- /dev/null ++++ b/tcg/loongarch64/tcg-target-con-set.h +@@ -0,0 +1,31 @@ ++/* SPDX-License-Identifier: MIT */ ++/* ++ * Define LoongArch target-specific constraint sets. ++ * ++ * Copyright (c) 2021 WANG Xuerui ++ * ++ * Based on tcg/riscv/tcg-target-con-set.h ++ * ++ * Copyright (c) 2021 Linaro ++ */ ++ ++/* ++ * C_On_Im(...) defines a constraint set with outputs and inputs. ++ * Each operand should be a sequence of constraint letters as defined by ++ * tcg-target-con-str.h; the constraint combination is inclusive or. ++ */ ++C_O0_I1(r) ++C_O0_I2(rZ, r) ++C_O0_I2(rZ, rZ) ++C_O0_I2(LZ, L) ++C_O1_I1(r, r) ++C_O1_I1(r, L) ++C_O1_I2(r, r, rC) ++C_O1_I2(r, r, ri) ++C_O1_I2(r, r, rI) ++C_O1_I2(r, r, rU) ++C_O1_I2(r, r, rW) ++C_O1_I2(r, r, rZ) ++C_O1_I2(r, 0, rZ) ++C_O1_I2(r, rZ, rN) ++C_O1_I2(r, rZ, rZ) +diff --git a/tcg/loongarch64/tcg-target-con-str.h b/tcg/loongarch64/tcg-target-con-str.h +new file mode 100644 +index 0000000000..c3986a4fd4 +--- /dev/null ++++ b/tcg/loongarch64/tcg-target-con-str.h +@@ -0,0 +1,28 @@ ++/* SPDX-License-Identifier: MIT */ ++/* ++ * Define LoongArch target-specific operand constraints. ++ * ++ * Copyright (c) 2021 WANG Xuerui ++ * ++ * Based on tcg/riscv/tcg-target-con-str.h ++ * ++ * Copyright (c) 2021 Linaro ++ */ ++ ++/* ++ * Define constraint letters for register sets: ++ * REGS(letter, register_mask) ++ */ ++REGS('r', ALL_GENERAL_REGS) ++REGS('L', ALL_GENERAL_REGS & ~SOFTMMU_RESERVE_REGS) ++ ++/* ++ * Define constraint letters for constants: ++ * CONST(letter, TCG_CT_CONST_* bit set) ++ */ ++CONST('I', TCG_CT_CONST_S12) ++CONST('N', TCG_CT_CONST_N12) ++CONST('U', TCG_CT_CONST_U12) ++CONST('Z', TCG_CT_CONST_ZERO) ++CONST('C', TCG_CT_CONST_C12) ++CONST('W', TCG_CT_CONST_WSZ) +diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc +new file mode 100644 +index 0000000000..9b53549edb +--- /dev/null ++++ b/tcg/loongarch64/tcg-target.c.inc +@@ -0,0 +1,1744 @@ ++/* ++ * Tiny Code Generator for QEMU ++ * ++ * Copyright (c) 2021 WANG Xuerui ++ * ++ * Based on tcg/riscv/tcg-target.c.inc ++ * ++ * Copyright (c) 2018 SiFive, Inc ++ * Copyright (c) 2008-2009 Arnaud Patard ++ * Copyright (c) 2009 Aurelien Jarno ++ * Copyright (c) 2008 Fabrice Bellard ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ++ * THE SOFTWARE. ++ */ ++ ++#include "../tcg-ldst.c.inc" ++ ++#ifdef CONFIG_DEBUG_TCG ++static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = { ++ "zero", ++ "ra", ++ "tp", ++ "sp", ++ "a0", ++ "a1", ++ "a2", ++ "a3", ++ "a4", ++ "a5", ++ "a6", ++ "a7", ++ "t0", ++ "t1", ++ "t2", ++ "t3", ++ "t4", ++ "t5", ++ "t6", ++ "t7", ++ "t8", ++ "r21", /* reserved in the LP64* ABI, hence no ABI name */ ++ "s9", ++ "s0", ++ "s1", ++ "s2", ++ "s3", ++ "s4", ++ "s5", ++ "s6", ++ "s7", ++ "s8" ++}; ++#endif ++ ++static const int tcg_target_reg_alloc_order[] = { ++ /* Registers preserved across calls */ ++ /* TCG_REG_S0 reserved for TCG_AREG0 */ ++ TCG_REG_S1, ++ TCG_REG_S2, ++ TCG_REG_S3, ++ TCG_REG_S4, ++ TCG_REG_S5, ++ TCG_REG_S6, ++ TCG_REG_S7, ++ TCG_REG_S8, ++ TCG_REG_S9, ++ ++ /* Registers (potentially) clobbered across calls */ ++ TCG_REG_T0, ++ TCG_REG_T1, ++ TCG_REG_T2, ++ TCG_REG_T3, ++ TCG_REG_T4, ++ TCG_REG_T5, ++ TCG_REG_T6, ++ TCG_REG_T7, ++ TCG_REG_T8, ++ ++ /* Argument registers, opposite order of allocation. */ ++ TCG_REG_A7, ++ TCG_REG_A6, ++ TCG_REG_A5, ++ TCG_REG_A4, ++ TCG_REG_A3, ++ TCG_REG_A2, ++ TCG_REG_A1, ++ TCG_REG_A0, ++}; ++ ++static const int tcg_target_call_iarg_regs[] = { ++ TCG_REG_A0, ++ TCG_REG_A1, ++ TCG_REG_A2, ++ TCG_REG_A3, ++ TCG_REG_A4, ++ TCG_REG_A5, ++ TCG_REG_A6, ++ TCG_REG_A7, ++}; ++ ++static const int tcg_target_call_oarg_regs[] = { ++ TCG_REG_A0, ++ TCG_REG_A1, ++}; ++ ++#ifndef CONFIG_SOFTMMU ++#define USE_GUEST_BASE (guest_base != 0) ++#define TCG_GUEST_BASE_REG TCG_REG_S1 ++#endif ++ ++#define TCG_CT_CONST_ZERO 0x100 ++#define TCG_CT_CONST_S12 0x200 ++#define TCG_CT_CONST_N12 0x400 ++#define TCG_CT_CONST_U12 0x800 ++#define TCG_CT_CONST_C12 0x1000 ++#define TCG_CT_CONST_WSZ 0x2000 ++ ++#define ALL_GENERAL_REGS MAKE_64BIT_MASK(0, 32) ++/* ++ * For softmmu, we need to avoid conflicts with the first 5 ++ * argument registers to call the helper. Some of these are ++ * also used for the tlb lookup. ++ */ ++#ifdef CONFIG_SOFTMMU ++#define SOFTMMU_RESERVE_REGS MAKE_64BIT_MASK(TCG_REG_A0, 5) ++#else ++#define SOFTMMU_RESERVE_REGS 0 ++#endif ++ ++ ++static inline tcg_target_long sextreg(tcg_target_long val, int pos, int len) ++{ ++ return sextract64(val, pos, len); ++} ++ ++/* test if a constant matches the constraint */ ++static bool tcg_target_const_match(int64_t val, TCGType type, int ct) ++{ ++ if (ct & TCG_CT_CONST) { ++ return true; ++ } ++ if ((ct & TCG_CT_CONST_ZERO) && val == 0) { ++ return true; ++ } ++ if ((ct & TCG_CT_CONST_S12) && val == sextreg(val, 0, 12)) { ++ return true; ++ } ++ if ((ct & TCG_CT_CONST_N12) && -val == sextreg(-val, 0, 12)) { ++ return true; ++ } ++ if ((ct & TCG_CT_CONST_U12) && val >= 0 && val <= 0xfff) { ++ return true; ++ } ++ if ((ct & TCG_CT_CONST_C12) && ~val >= 0 && ~val <= 0xfff) { ++ return true; ++ } ++ if ((ct & TCG_CT_CONST_WSZ) && val == (type == TCG_TYPE_I32 ? 32 : 64)) { ++ return true; ++ } ++ return false; ++} ++ ++/* ++ * Relocations ++ */ ++ ++/* ++ * Relocation records defined in LoongArch ELF psABI v1.00 is way too ++ * complicated; a whopping stack machine is needed to stuff the fields, at ++ * the very least one SOP_PUSH and one SOP_POP (of the correct format) are ++ * needed. ++ * ++ * Hence, define our own simpler relocation types. Numbers are chosen as to ++ * not collide with potential future additions to the true ELF relocation ++ * type enum. ++ */ ++ ++/* Field Sk16, shifted right by 2; suitable for conditional jumps */ ++#define R_LOONGARCH_BR_SK16 256 ++/* Field Sd10k16, shifted right by 2; suitable for B and BL */ ++#define R_LOONGARCH_BR_SD10K16 257 ++ ++static bool reloc_br_sk16(tcg_insn_unit *src_rw, const tcg_insn_unit *target) ++{ ++ const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw); ++ intptr_t offset = (intptr_t)target - (intptr_t)src_rx; ++ ++ tcg_debug_assert((offset & 3) == 0); ++ offset >>= 2; ++ if (offset == sextreg(offset, 0, 16)) { ++ *src_rw = deposit64(*src_rw, 10, 16, offset); ++ return true; ++ } ++ ++ return false; ++} ++ ++static bool reloc_br_sd10k16(tcg_insn_unit *src_rw, ++ const tcg_insn_unit *target) ++{ ++ const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw); ++ intptr_t offset = (intptr_t)target - (intptr_t)src_rx; ++ ++ tcg_debug_assert((offset & 3) == 0); ++ offset >>= 2; ++ if (offset == sextreg(offset, 0, 26)) { ++ *src_rw = deposit64(*src_rw, 0, 10, offset >> 16); /* slot d10 */ ++ *src_rw = deposit64(*src_rw, 10, 16, offset); /* slot k16 */ ++ return true; ++ } ++ ++ return false; ++} ++ ++static bool patch_reloc(tcg_insn_unit *code_ptr, int type, ++ intptr_t value, intptr_t addend) ++{ ++ tcg_debug_assert(addend == 0); ++ switch (type) { ++ case R_LOONGARCH_BR_SK16: ++ return reloc_br_sk16(code_ptr, (tcg_insn_unit *)value); ++ case R_LOONGARCH_BR_SD10K16: ++ return reloc_br_sd10k16(code_ptr, (tcg_insn_unit *)value); ++ default: ++ g_assert_not_reached(); ++ } ++} ++ ++#include "tcg-insn-defs.c.inc" ++ ++/* ++ * TCG intrinsics ++ */ ++ ++static void tcg_out_mb(TCGContext *s, TCGArg a0) ++{ ++ /* Baseline LoongArch only has the full barrier, unfortunately. */ ++ tcg_out_opc_dbar(s, 0); ++} ++ ++static bool tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg) ++{ ++ if (ret == arg) { ++ return true; ++ } ++ switch (type) { ++ case TCG_TYPE_I32: ++ case TCG_TYPE_I64: ++ /* ++ * Conventional register-register move used in LoongArch is ++ * `or dst, src, zero`. ++ */ ++ tcg_out_opc_or(s, ret, arg, TCG_REG_ZERO); ++ break; ++ default: ++ g_assert_not_reached(); ++ } ++ return true; ++} ++ ++static bool imm_part_needs_loading(bool high_bits_are_ones, ++ tcg_target_long part) ++{ ++ if (high_bits_are_ones) { ++ return part != -1; ++ } else { ++ return part != 0; ++ } ++} ++ ++/* Loads a 32-bit immediate into rd, sign-extended. */ ++static void tcg_out_movi_i32(TCGContext *s, TCGReg rd, int32_t val) ++{ ++ tcg_target_long lo = sextreg(val, 0, 12); ++ tcg_target_long hi12 = sextreg(val, 12, 20); ++ ++ /* Single-instruction cases. */ ++ if (lo == val) { ++ /* val fits in simm12: addi.w rd, zero, val */ ++ tcg_out_opc_addi_w(s, rd, TCG_REG_ZERO, val); ++ return; ++ } ++ if (0x800 <= val && val <= 0xfff) { ++ /* val fits in uimm12: ori rd, zero, val */ ++ tcg_out_opc_ori(s, rd, TCG_REG_ZERO, val); ++ return; ++ } ++ ++ /* High bits must be set; load with lu12i.w + optional ori. */ ++ tcg_out_opc_lu12i_w(s, rd, hi12); ++ if (lo != 0) { ++ tcg_out_opc_ori(s, rd, rd, lo & 0xfff); ++ } ++} ++ ++static void tcg_out_movi(TCGContext *s, TCGType type, TCGReg rd, ++ tcg_target_long val) ++{ ++ /* ++ * LoongArch conventionally loads 64-bit immediates in at most 4 steps, ++ * with dedicated instructions for filling the respective bitfields ++ * below: ++ * ++ * 6 5 4 3 ++ * 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 ++ * +-----------------------+---------------------------------------+... ++ * | hi52 | hi32 | ++ * +-----------------------+---------------------------------------+... ++ * 3 2 1 ++ * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 ++ * ...+-------------------------------------+-------------------------+ ++ * | hi12 | lo | ++ * ...+-------------------------------------+-------------------------+ ++ * ++ * Check if val belong to one of the several fast cases, before falling ++ * back to the slow path. ++ */ ++ ++ intptr_t pc_offset; ++ tcg_target_long val_lo, val_hi, pc_hi, offset_hi; ++ tcg_target_long hi32, hi52; ++ bool rd_high_bits_are_ones; ++ ++ /* Value fits in signed i32. */ ++ if (type == TCG_TYPE_I32 || val == (int32_t)val) { ++ tcg_out_movi_i32(s, rd, val); ++ return; ++ } ++ ++ /* PC-relative cases. */ ++ pc_offset = tcg_pcrel_diff(s, (void *)val); ++ if (pc_offset == sextreg(pc_offset, 0, 22) && (pc_offset & 3) == 0) { ++ /* Single pcaddu2i. */ ++ tcg_out_opc_pcaddu2i(s, rd, pc_offset >> 2); ++ return; ++ } ++ ++ if (pc_offset == (int32_t)pc_offset) { ++ /* Offset within 32 bits; load with pcalau12i + ori. */ ++ val_lo = sextreg(val, 0, 12); ++ val_hi = val >> 12; ++ pc_hi = (val - pc_offset) >> 12; ++ offset_hi = val_hi - pc_hi; ++ ++ tcg_debug_assert(offset_hi == sextreg(offset_hi, 0, 20)); ++ tcg_out_opc_pcalau12i(s, rd, offset_hi); ++ if (val_lo != 0) { ++ tcg_out_opc_ori(s, rd, rd, val_lo & 0xfff); ++ } ++ return; ++ } ++ ++ hi32 = sextreg(val, 32, 20); ++ hi52 = sextreg(val, 52, 12); ++ ++ /* Single cu52i.d case. */ ++ if (ctz64(val) >= 52) { ++ tcg_out_opc_cu52i_d(s, rd, TCG_REG_ZERO, hi52); ++ return; ++ } ++ ++ /* Slow path. Initialize the low 32 bits, then concat high bits. */ ++ tcg_out_movi_i32(s, rd, val); ++ rd_high_bits_are_ones = (int32_t)val < 0; ++ ++ if (imm_part_needs_loading(rd_high_bits_are_ones, hi32)) { ++ tcg_out_opc_cu32i_d(s, rd, hi32); ++ rd_high_bits_are_ones = hi32 < 0; ++ } ++ ++ if (imm_part_needs_loading(rd_high_bits_are_ones, hi52)) { ++ tcg_out_opc_cu52i_d(s, rd, rd, hi52); ++ } ++} ++ ++static void tcg_out_ext8u(TCGContext *s, TCGReg ret, TCGReg arg) ++{ ++ tcg_out_opc_andi(s, ret, arg, 0xff); ++} ++ ++static void tcg_out_ext16u(TCGContext *s, TCGReg ret, TCGReg arg) ++{ ++ tcg_out_opc_bstrpick_w(s, ret, arg, 0, 15); ++} ++ ++static void tcg_out_ext32u(TCGContext *s, TCGReg ret, TCGReg arg) ++{ ++ tcg_out_opc_bstrpick_d(s, ret, arg, 0, 31); ++} ++ ++static void tcg_out_ext8s(TCGContext *s, TCGReg ret, TCGReg arg) ++{ ++ tcg_out_opc_sext_b(s, ret, arg); ++} ++ ++static void tcg_out_ext16s(TCGContext *s, TCGReg ret, TCGReg arg) ++{ ++ tcg_out_opc_sext_h(s, ret, arg); ++} ++ ++static void tcg_out_ext32s(TCGContext *s, TCGReg ret, TCGReg arg) ++{ ++ tcg_out_opc_addi_w(s, ret, arg, 0); ++} ++ ++static void tcg_out_clzctz(TCGContext *s, LoongArchInsn opc, ++ TCGReg a0, TCGReg a1, TCGReg a2, ++ bool c2, bool is_32bit) ++{ ++ if (c2) { ++ /* ++ * Fast path: semantics already satisfied due to constraint and ++ * insn behavior, single instruction is enough. ++ */ ++ tcg_debug_assert(a2 == (is_32bit ? 32 : 64)); ++ /* all clz/ctz insns belong to DJ-format */ ++ tcg_out32(s, encode_dj_insn(opc, a0, a1)); ++ return; ++ } ++ ++ tcg_out32(s, encode_dj_insn(opc, TCG_REG_TMP0, a1)); ++ /* a0 = a1 ? REG_TMP0 : a2 */ ++ tcg_out_opc_maskeqz(s, TCG_REG_TMP0, TCG_REG_TMP0, a1); ++ tcg_out_opc_masknez(s, a0, a2, a1); ++ tcg_out_opc_or(s, a0, TCG_REG_TMP0, a0); ++} ++ ++static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret, ++ TCGReg arg1, TCGReg arg2, bool c2) ++{ ++ TCGReg tmp; ++ ++ if (c2) { ++ tcg_debug_assert(arg2 == 0); ++ } ++ ++ switch (cond) { ++ case TCG_COND_EQ: ++ if (c2) { ++ tmp = arg1; ++ } else { ++ tcg_out_opc_sub_d(s, ret, arg1, arg2); ++ tmp = ret; ++ } ++ tcg_out_opc_sltui(s, ret, tmp, 1); ++ break; ++ case TCG_COND_NE: ++ if (c2) { ++ tmp = arg1; ++ } else { ++ tcg_out_opc_sub_d(s, ret, arg1, arg2); ++ tmp = ret; ++ } ++ tcg_out_opc_sltu(s, ret, TCG_REG_ZERO, tmp); ++ break; ++ case TCG_COND_LT: ++ tcg_out_opc_slt(s, ret, arg1, arg2); ++ break; ++ case TCG_COND_GE: ++ tcg_out_opc_slt(s, ret, arg1, arg2); ++ tcg_out_opc_xori(s, ret, ret, 1); ++ break; ++ case TCG_COND_LE: ++ tcg_out_setcond(s, TCG_COND_GE, ret, arg2, arg1, false); ++ break; ++ case TCG_COND_GT: ++ tcg_out_setcond(s, TCG_COND_LT, ret, arg2, arg1, false); ++ break; ++ case TCG_COND_LTU: ++ tcg_out_opc_sltu(s, ret, arg1, arg2); ++ break; ++ case TCG_COND_GEU: ++ tcg_out_opc_sltu(s, ret, arg1, arg2); ++ tcg_out_opc_xori(s, ret, ret, 1); ++ break; ++ case TCG_COND_LEU: ++ tcg_out_setcond(s, TCG_COND_GEU, ret, arg2, arg1, false); ++ break; ++ case TCG_COND_GTU: ++ tcg_out_setcond(s, TCG_COND_LTU, ret, arg2, arg1, false); ++ break; ++ default: ++ g_assert_not_reached(); ++ break; ++ } ++} ++ ++/* ++ * Branch helpers ++ */ ++ ++static const struct { ++ LoongArchInsn op; ++ bool swap; ++} tcg_brcond_to_loongarch[] = { ++ [TCG_COND_EQ] = { OPC_BEQ, false }, ++ [TCG_COND_NE] = { OPC_BNE, false }, ++ [TCG_COND_LT] = { OPC_BGT, true }, ++ [TCG_COND_GE] = { OPC_BLE, true }, ++ [TCG_COND_LE] = { OPC_BLE, false }, ++ [TCG_COND_GT] = { OPC_BGT, false }, ++ [TCG_COND_LTU] = { OPC_BGTU, true }, ++ [TCG_COND_GEU] = { OPC_BLEU, true }, ++ [TCG_COND_LEU] = { OPC_BLEU, false }, ++ [TCG_COND_GTU] = { OPC_BGTU, false } ++}; ++ ++static void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGReg arg1, ++ TCGReg arg2, TCGLabel *l) ++{ ++ LoongArchInsn op = tcg_brcond_to_loongarch[cond].op; ++ ++ tcg_debug_assert(op != 0); ++ ++ if (tcg_brcond_to_loongarch[cond].swap) { ++ TCGReg t = arg1; ++ arg1 = arg2; ++ arg2 = t; ++ } ++ ++ /* all conditional branch insns belong to DJSk16-format */ ++ tcg_out_reloc(s, s->code_ptr, R_LOONGARCH_BR_SK16, l, 0); ++ tcg_out32(s, encode_djsk16_insn(op, arg1, arg2, 0)); ++} ++ ++static void tcg_out_call_int(TCGContext *s, const tcg_insn_unit *arg, bool tail) ++{ ++ TCGReg link = tail ? TCG_REG_ZERO : TCG_REG_RA; ++ ptrdiff_t offset = tcg_pcrel_diff(s, arg); ++ ++ tcg_debug_assert((offset & 3) == 0); ++ if (offset == sextreg(offset, 0, 28)) { ++ /* short jump: +/- 256MiB */ ++ if (tail) { ++ tcg_out_opc_b(s, offset >> 2); ++ } else { ++ tcg_out_opc_bl(s, offset >> 2); ++ } ++ } else if (offset == sextreg(offset, 0, 38)) { ++ /* long jump: +/- 256GiB */ ++ tcg_target_long lo = sextreg(offset, 0, 18); ++ tcg_target_long hi = offset - lo; ++ tcg_out_opc_pcaddu18i(s, TCG_REG_TMP0, hi >> 18); ++ tcg_out_opc_jirl(s, link, TCG_REG_TMP0, lo >> 2); ++ } else { ++ /* far jump: 64-bit */ ++ tcg_target_long lo = sextreg((tcg_target_long)arg, 0, 18); ++ tcg_target_long hi = (tcg_target_long)arg - lo; ++ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP0, hi); ++ tcg_out_opc_jirl(s, link, TCG_REG_TMP0, lo >> 2); ++ } ++} ++ ++static void tcg_out_call(TCGContext *s, const tcg_insn_unit *arg) ++{ ++ tcg_out_call_int(s, arg, false); ++} ++ ++/* ++ * Load/store helpers ++ */ ++ ++static void tcg_out_ldst(TCGContext *s, LoongArchInsn opc, TCGReg data, ++ TCGReg addr, intptr_t offset) ++{ ++ intptr_t imm12 = sextreg(offset, 0, 12); ++ ++ if (offset != imm12) { ++ intptr_t diff = offset - (uintptr_t)s->code_ptr; ++ ++ if (addr == TCG_REG_ZERO && diff == (int32_t)diff) { ++ imm12 = sextreg(diff, 0, 12); ++ tcg_out_opc_pcaddu12i(s, TCG_REG_TMP2, (diff - imm12) >> 12); ++ } else { ++ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP2, offset - imm12); ++ if (addr != TCG_REG_ZERO) { ++ tcg_out_opc_add_d(s, TCG_REG_TMP2, TCG_REG_TMP2, addr); ++ } ++ } ++ addr = TCG_REG_TMP2; ++ } ++ ++ switch (opc) { ++ case OPC_LD_B: ++ case OPC_LD_BU: ++ case OPC_LD_H: ++ case OPC_LD_HU: ++ case OPC_LD_W: ++ case OPC_LD_WU: ++ case OPC_LD_D: ++ case OPC_ST_B: ++ case OPC_ST_H: ++ case OPC_ST_W: ++ case OPC_ST_D: ++ tcg_out32(s, encode_djsk12_insn(opc, data, addr, imm12)); ++ break; ++ default: ++ g_assert_not_reached(); ++ } ++} ++ ++static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg, ++ TCGReg arg1, intptr_t arg2) ++{ ++ bool is_32bit = type == TCG_TYPE_I32; ++ tcg_out_ldst(s, is_32bit ? OPC_LD_W : OPC_LD_D, arg, arg1, arg2); ++} ++ ++static void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, ++ TCGReg arg1, intptr_t arg2) ++{ ++ bool is_32bit = type == TCG_TYPE_I32; ++ tcg_out_ldst(s, is_32bit ? OPC_ST_W : OPC_ST_D, arg, arg1, arg2); ++} ++ ++static bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val, ++ TCGReg base, intptr_t ofs) ++{ ++ if (val == 0) { ++ tcg_out_st(s, type, TCG_REG_ZERO, base, ofs); ++ return true; ++ } ++ return false; ++} ++ ++/* ++ * Load/store helpers for SoftMMU, and qemu_ld/st implementations ++ */ ++ ++#if defined(CONFIG_SOFTMMU) ++/* ++ * helper signature: helper_ret_ld_mmu(CPUState *env, target_ulong addr, ++ * MemOpIdx oi, uintptr_t ra) ++ */ ++static void * const qemu_ld_helpers[4] = { ++ [MO_8] = helper_ret_ldub_mmu, ++ [MO_16] = helper_le_lduw_mmu, ++ [MO_32] = helper_le_ldul_mmu, ++ [MO_64] = helper_le_ldq_mmu, ++}; ++ ++/* ++ * helper signature: helper_ret_st_mmu(CPUState *env, target_ulong addr, ++ * uintxx_t val, MemOpIdx oi, ++ * uintptr_t ra) ++ */ ++static void * const qemu_st_helpers[4] = { ++ [MO_8] = helper_ret_stb_mmu, ++ [MO_16] = helper_le_stw_mmu, ++ [MO_32] = helper_le_stl_mmu, ++ [MO_64] = helper_le_stq_mmu, ++}; ++ ++/* We expect to use a 12-bit negative offset from ENV. */ ++QEMU_BUILD_BUG_ON(TLB_MASK_TABLE_OFS(0) > 0); ++QEMU_BUILD_BUG_ON(TLB_MASK_TABLE_OFS(0) < -(1 << 11)); ++ ++static bool tcg_out_goto(TCGContext *s, const tcg_insn_unit *target) ++{ ++ tcg_out_opc_b(s, 0); ++ return reloc_br_sd10k16(s->code_ptr - 1, target); ++} ++ ++/* ++ * Emits common code for TLB addend lookup, that eventually loads the ++ * addend in TCG_REG_TMP2. ++ */ ++static void tcg_out_tlb_load(TCGContext *s, TCGReg addrl, MemOpIdx oi, ++ tcg_insn_unit **label_ptr, bool is_load) ++{ ++ MemOp opc = get_memop(oi); ++ unsigned s_bits = opc & MO_SIZE; ++ unsigned a_bits = get_alignment_bits(opc); ++ tcg_target_long compare_mask; ++ int mem_index = get_mmuidx(oi); ++ int fast_ofs = TLB_MASK_TABLE_OFS(mem_index); ++ int mask_ofs = fast_ofs + offsetof(CPUTLBDescFast, mask); ++ int table_ofs = fast_ofs + offsetof(CPUTLBDescFast, table); ++ ++ tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, TCG_AREG0, mask_ofs); ++ tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP1, TCG_AREG0, table_ofs); ++ ++ tcg_out_opc_srli_d(s, TCG_REG_TMP2, addrl, ++ TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS); ++ tcg_out_opc_and(s, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP0); ++ tcg_out_opc_add_d(s, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP1); ++ ++ /* Load the tlb comparator and the addend. */ ++ tcg_out_ld(s, TCG_TYPE_TL, TCG_REG_TMP0, TCG_REG_TMP2, ++ is_load ? offsetof(CPUTLBEntry, addr_read) ++ : offsetof(CPUTLBEntry, addr_write)); ++ tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP2, TCG_REG_TMP2, ++ offsetof(CPUTLBEntry, addend)); ++ ++ /* We don't support unaligned accesses. */ ++ if (a_bits < s_bits) { ++ a_bits = s_bits; ++ } ++ /* Clear the non-page, non-alignment bits from the address. */ ++ compare_mask = (tcg_target_long)TARGET_PAGE_MASK | ((1 << a_bits) - 1); ++ tcg_out_movi(s, TCG_TYPE_TL, TCG_REG_TMP1, compare_mask); ++ tcg_out_opc_and(s, TCG_REG_TMP1, TCG_REG_TMP1, addrl); ++ ++ /* Compare masked address with the TLB entry. */ ++ label_ptr[0] = s->code_ptr; ++ tcg_out_opc_bne(s, TCG_REG_TMP0, TCG_REG_TMP1, 0); ++ ++ /* TLB Hit - addend in TCG_REG_TMP2, ready for use. */ ++} ++ ++static void add_qemu_ldst_label(TCGContext *s, int is_ld, MemOpIdx oi, ++ TCGType type, ++ TCGReg datalo, TCGReg addrlo, ++ void *raddr, tcg_insn_unit **label_ptr) ++{ ++ TCGLabelQemuLdst *label = new_ldst_label(s); ++ ++ label->is_ld = is_ld; ++ label->oi = oi; ++ label->type = type; ++ label->datalo_reg = datalo; ++ label->datahi_reg = 0; /* unused */ ++ label->addrlo_reg = addrlo; ++ label->addrhi_reg = 0; /* unused */ ++ label->raddr = tcg_splitwx_to_rx(raddr); ++ label->label_ptr[0] = label_ptr[0]; ++} ++ ++static bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l) ++{ ++ MemOpIdx oi = l->oi; ++ MemOp opc = get_memop(oi); ++ MemOp size = opc & MO_SIZE; ++ TCGType type = l->type; ++ ++ /* resolve label address */ ++ if (!reloc_br_sk16(l->label_ptr[0], tcg_splitwx_to_rx(s->code_ptr))) { ++ return false; ++ } ++ ++ /* call load helper */ ++ tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_A0, TCG_AREG0); ++ tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_A1, l->addrlo_reg); ++ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A2, oi); ++ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A3, (tcg_target_long)l->raddr); ++ ++ tcg_out_call(s, qemu_ld_helpers[size]); ++ ++ switch (opc & MO_SSIZE) { ++ case MO_SB: ++ tcg_out_ext8s(s, l->datalo_reg, TCG_REG_A0); ++ break; ++ case MO_SW: ++ tcg_out_ext16s(s, l->datalo_reg, TCG_REG_A0); ++ break; ++ case MO_SL: ++ tcg_out_ext32s(s, l->datalo_reg, TCG_REG_A0); ++ break; ++ case MO_UL: ++ if (type == TCG_TYPE_I32) { ++ /* MO_UL loads of i32 should be sign-extended too */ ++ tcg_out_ext32s(s, l->datalo_reg, TCG_REG_A0); ++ break; ++ } ++ /* fallthrough */ ++ default: ++ tcg_out_mov(s, type, l->datalo_reg, TCG_REG_A0); ++ break; ++ } ++ ++ return tcg_out_goto(s, l->raddr); ++} ++ ++static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l) ++{ ++ MemOpIdx oi = l->oi; ++ MemOp opc = get_memop(oi); ++ MemOp size = opc & MO_SIZE; ++ ++ /* resolve label address */ ++ if (!reloc_br_sk16(l->label_ptr[0], tcg_splitwx_to_rx(s->code_ptr))) { ++ return false; ++ } ++ ++ /* call store helper */ ++ tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_A0, TCG_AREG0); ++ tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_A1, l->addrlo_reg); ++ switch (size) { ++ case MO_8: ++ tcg_out_ext8u(s, TCG_REG_A2, l->datalo_reg); ++ break; ++ case MO_16: ++ tcg_out_ext16u(s, TCG_REG_A2, l->datalo_reg); ++ break; ++ case MO_32: ++ tcg_out_ext32u(s, TCG_REG_A2, l->datalo_reg); ++ break; ++ case MO_64: ++ tcg_out_mov(s, TCG_TYPE_I64, TCG_REG_A2, l->datalo_reg); ++ break; ++ default: ++ g_assert_not_reached(); ++ break; ++ } ++ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A3, oi); ++ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A4, (tcg_target_long)l->raddr); ++ ++ tcg_out_call(s, qemu_st_helpers[size]); ++ ++ return tcg_out_goto(s, l->raddr); ++} ++#else ++ ++/* ++ * Alignment helpers for user-mode emulation ++ */ ++ ++static void tcg_out_test_alignment(TCGContext *s, bool is_ld, TCGReg addr_reg, ++ unsigned a_bits) ++{ ++ TCGLabelQemuLdst *l = new_ldst_label(s); ++ ++ l->is_ld = is_ld; ++ l->addrlo_reg = addr_reg; ++ ++ /* ++ * Without micro-architecture details, we don't know which of bstrpick or ++ * andi is faster, so use bstrpick as it's not constrained by imm field ++ * width. (Not to say alignments >= 2^12 are going to happen any time ++ * soon, though) ++ */ ++ tcg_out_opc_bstrpick_d(s, TCG_REG_TMP1, addr_reg, 0, a_bits - 1); ++ ++ l->label_ptr[0] = s->code_ptr; ++ tcg_out_opc_bne(s, TCG_REG_TMP1, TCG_REG_ZERO, 0); ++ ++ l->raddr = tcg_splitwx_to_rx(s->code_ptr); ++} ++ ++static bool tcg_out_fail_alignment(TCGContext *s, TCGLabelQemuLdst *l) ++{ ++ /* resolve label address */ ++ if (!reloc_br_sk16(l->label_ptr[0], tcg_splitwx_to_rx(s->code_ptr))) { ++ return false; ++ } ++ ++ tcg_out_mov(s, TCG_TYPE_TL, TCG_REG_A1, l->addrlo_reg); ++ tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_A0, TCG_AREG0); ++ ++ /* tail call, with the return address back inline. */ ++ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_RA, (uintptr_t)l->raddr); ++ tcg_out_call_int(s, (const void *)(l->is_ld ? helper_unaligned_ld ++ : helper_unaligned_st), true); ++ return true; ++} ++ ++static bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l) ++{ ++ return tcg_out_fail_alignment(s, l); ++} ++ ++static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l) ++{ ++ return tcg_out_fail_alignment(s, l); ++} ++ ++#endif /* CONFIG_SOFTMMU */ ++ ++/* ++ * `ext32u` the address register into the temp register given, ++ * if target is 32-bit, no-op otherwise. ++ * ++ * Returns the address register ready for use with TLB addend. ++ */ ++static TCGReg tcg_out_zext_addr_if_32_bit(TCGContext *s, ++ TCGReg addr, TCGReg tmp) ++{ ++ if (TARGET_LONG_BITS == 32) { ++ tcg_out_ext32u(s, tmp, addr); ++ return tmp; ++ } ++ return addr; ++} ++ ++static void tcg_out_qemu_ld_indexed(TCGContext *s, TCGReg rd, TCGReg rj, ++ TCGReg rk, MemOp opc, TCGType type) ++{ ++ /* Byte swapping is left to middle-end expansion. */ ++ tcg_debug_assert((opc & MO_BSWAP) == 0); ++ ++ switch (opc & MO_SSIZE) { ++ case MO_UB: ++ tcg_out_opc_ldx_bu(s, rd, rj, rk); ++ break; ++ case MO_SB: ++ tcg_out_opc_ldx_b(s, rd, rj, rk); ++ break; ++ case MO_UW: ++ tcg_out_opc_ldx_hu(s, rd, rj, rk); ++ break; ++ case MO_SW: ++ tcg_out_opc_ldx_h(s, rd, rj, rk); ++ break; ++ case MO_UL: ++ if (type == TCG_TYPE_I64) { ++ tcg_out_opc_ldx_wu(s, rd, rj, rk); ++ break; ++ } ++ /* fallthrough */ ++ case MO_SL: ++ tcg_out_opc_ldx_w(s, rd, rj, rk); ++ break; ++ case MO_Q: ++ tcg_out_opc_ldx_d(s, rd, rj, rk); ++ break; ++ default: ++ g_assert_not_reached(); ++ } ++} ++ ++static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, TCGType type) ++{ ++ TCGReg addr_regl; ++ TCGReg data_regl; ++ MemOpIdx oi; ++ MemOp opc; ++#if defined(CONFIG_SOFTMMU) ++ tcg_insn_unit *label_ptr[1]; ++#else ++ unsigned a_bits; ++#endif ++ TCGReg base; ++ ++ data_regl = *args++; ++ addr_regl = *args++; ++ oi = *args++; ++ opc = get_memop(oi); ++ ++#if defined(CONFIG_SOFTMMU) ++ tcg_out_tlb_load(s, addr_regl, oi, label_ptr, 1); ++ base = tcg_out_zext_addr_if_32_bit(s, addr_regl, TCG_REG_TMP0); ++ tcg_out_qemu_ld_indexed(s, data_regl, base, TCG_REG_TMP2, opc, type); ++ add_qemu_ldst_label(s, 1, oi, type, ++ data_regl, addr_regl, ++ s->code_ptr, label_ptr); ++#else ++ a_bits = get_alignment_bits(opc); ++ if (a_bits) { ++ tcg_out_test_alignment(s, true, addr_regl, a_bits); ++ } ++ base = tcg_out_zext_addr_if_32_bit(s, addr_regl, TCG_REG_TMP0); ++ TCGReg guest_base_reg = USE_GUEST_BASE ? TCG_GUEST_BASE_REG : TCG_REG_ZERO; ++ tcg_out_qemu_ld_indexed(s, data_regl, base, guest_base_reg, opc, type); ++#endif ++} ++ ++static void tcg_out_qemu_st_indexed(TCGContext *s, TCGReg data, ++ TCGReg rj, TCGReg rk, MemOp opc) ++{ ++ /* Byte swapping is left to middle-end expansion. */ ++ tcg_debug_assert((opc & MO_BSWAP) == 0); ++ ++ switch (opc & MO_SIZE) { ++ case MO_8: ++ tcg_out_opc_stx_b(s, data, rj, rk); ++ break; ++ case MO_16: ++ tcg_out_opc_stx_h(s, data, rj, rk); ++ break; ++ case MO_32: ++ tcg_out_opc_stx_w(s, data, rj, rk); ++ break; ++ case MO_64: ++ tcg_out_opc_stx_d(s, data, rj, rk); ++ break; ++ default: ++ g_assert_not_reached(); ++ } ++} ++ ++static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args) ++{ ++ TCGReg addr_regl; ++ TCGReg data_regl; ++ MemOpIdx oi; ++ MemOp opc; ++#if defined(CONFIG_SOFTMMU) ++ tcg_insn_unit *label_ptr[1]; ++#else ++ unsigned a_bits; ++#endif ++ TCGReg base; ++ ++ data_regl = *args++; ++ addr_regl = *args++; ++ oi = *args++; ++ opc = get_memop(oi); ++ ++#if defined(CONFIG_SOFTMMU) ++ tcg_out_tlb_load(s, addr_regl, oi, label_ptr, 0); ++ base = tcg_out_zext_addr_if_32_bit(s, addr_regl, TCG_REG_TMP0); ++ tcg_out_qemu_st_indexed(s, data_regl, base, TCG_REG_TMP2, opc); ++ add_qemu_ldst_label(s, 0, oi, ++ 0, /* type param is unused for stores */ ++ data_regl, addr_regl, ++ s->code_ptr, label_ptr); ++#else ++ a_bits = get_alignment_bits(opc); ++ if (a_bits) { ++ tcg_out_test_alignment(s, false, addr_regl, a_bits); ++ } ++ base = tcg_out_zext_addr_if_32_bit(s, addr_regl, TCG_REG_TMP0); ++ TCGReg guest_base_reg = USE_GUEST_BASE ? TCG_GUEST_BASE_REG : TCG_REG_ZERO; ++ tcg_out_qemu_st_indexed(s, data_regl, base, guest_base_reg, opc); ++#endif ++} ++ ++/* ++ * Entry-points ++ */ ++ ++static const tcg_insn_unit *tb_ret_addr; ++ ++static void tcg_out_op(TCGContext *s, TCGOpcode opc, ++ const TCGArg args[TCG_MAX_OP_ARGS], ++ const int const_args[TCG_MAX_OP_ARGS]) ++{ ++ TCGArg a0 = args[0]; ++ TCGArg a1 = args[1]; ++ TCGArg a2 = args[2]; ++ int c2 = const_args[2]; ++ ++ switch (opc) { ++ case INDEX_op_exit_tb: ++ /* Reuse the zeroing that exists for goto_ptr. */ ++ if (a0 == 0) { ++ tcg_out_call_int(s, tcg_code_gen_epilogue, true); ++ } else { ++ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A0, a0); ++ tcg_out_call_int(s, tb_ret_addr, true); ++ } ++ break; ++ ++ case INDEX_op_goto_tb: ++ assert(s->tb_jmp_insn_offset == 0); ++ /* indirect jump method */ ++ tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, TCG_REG_ZERO, ++ (uintptr_t)(s->tb_jmp_target_addr + a0)); ++ tcg_out_opc_jirl(s, TCG_REG_ZERO, TCG_REG_TMP0, 0); ++ set_jmp_reset_offset(s, a0); ++ break; ++ ++ case INDEX_op_mb: ++ tcg_out_mb(s, a0); ++ break; ++ ++ case INDEX_op_goto_ptr: ++ tcg_out_opc_jirl(s, TCG_REG_ZERO, a0, 0); ++ break; ++ ++ case INDEX_op_br: ++ tcg_out_reloc(s, s->code_ptr, R_LOONGARCH_BR_SD10K16, arg_label(a0), ++ 0); ++ tcg_out_opc_b(s, 0); ++ break; ++ ++ case INDEX_op_brcond_i32: ++ case INDEX_op_brcond_i64: ++ tcg_out_brcond(s, a2, a0, a1, arg_label(args[3])); ++ break; ++ ++ case INDEX_op_ext8s_i32: ++ case INDEX_op_ext8s_i64: ++ tcg_out_ext8s(s, a0, a1); ++ break; ++ ++ case INDEX_op_ext8u_i32: ++ case INDEX_op_ext8u_i64: ++ tcg_out_ext8u(s, a0, a1); ++ break; ++ ++ case INDEX_op_ext16s_i32: ++ case INDEX_op_ext16s_i64: ++ tcg_out_ext16s(s, a0, a1); ++ break; ++ ++ case INDEX_op_ext16u_i32: ++ case INDEX_op_ext16u_i64: ++ tcg_out_ext16u(s, a0, a1); ++ break; ++ ++ case INDEX_op_ext32u_i64: ++ case INDEX_op_extu_i32_i64: ++ tcg_out_ext32u(s, a0, a1); ++ break; ++ ++ case INDEX_op_ext32s_i64: ++ case INDEX_op_extrl_i64_i32: ++ case INDEX_op_ext_i32_i64: ++ tcg_out_ext32s(s, a0, a1); ++ break; ++ ++ case INDEX_op_extrh_i64_i32: ++ tcg_out_opc_srai_d(s, a0, a1, 32); ++ break; ++ ++ case INDEX_op_not_i32: ++ case INDEX_op_not_i64: ++ tcg_out_opc_nor(s, a0, a1, TCG_REG_ZERO); ++ break; ++ ++ case INDEX_op_nor_i32: ++ case INDEX_op_nor_i64: ++ if (c2) { ++ tcg_out_opc_ori(s, a0, a1, a2); ++ tcg_out_opc_nor(s, a0, a0, TCG_REG_ZERO); ++ } else { ++ tcg_out_opc_nor(s, a0, a1, a2); ++ } ++ break; ++ ++ case INDEX_op_andc_i32: ++ case INDEX_op_andc_i64: ++ if (c2) { ++ /* guaranteed to fit due to constraint */ ++ tcg_out_opc_andi(s, a0, a1, ~a2); ++ } else { ++ tcg_out_opc_andn(s, a0, a1, a2); ++ } ++ break; ++ ++ case INDEX_op_orc_i32: ++ case INDEX_op_orc_i64: ++ if (c2) { ++ /* guaranteed to fit due to constraint */ ++ tcg_out_opc_ori(s, a0, a1, ~a2); ++ } else { ++ tcg_out_opc_orn(s, a0, a1, a2); ++ } ++ break; ++ ++ case INDEX_op_and_i32: ++ case INDEX_op_and_i64: ++ if (c2) { ++ tcg_out_opc_andi(s, a0, a1, a2); ++ } else { ++ tcg_out_opc_and(s, a0, a1, a2); ++ } ++ break; ++ ++ case INDEX_op_or_i32: ++ case INDEX_op_or_i64: ++ if (c2) { ++ tcg_out_opc_ori(s, a0, a1, a2); ++ } else { ++ tcg_out_opc_or(s, a0, a1, a2); ++ } ++ break; ++ ++ case INDEX_op_xor_i32: ++ case INDEX_op_xor_i64: ++ if (c2) { ++ tcg_out_opc_xori(s, a0, a1, a2); ++ } else { ++ tcg_out_opc_xor(s, a0, a1, a2); ++ } ++ break; ++ ++ case INDEX_op_extract_i32: ++ tcg_out_opc_bstrpick_w(s, a0, a1, a2, a2 + args[3] - 1); ++ break; ++ case INDEX_op_extract_i64: ++ tcg_out_opc_bstrpick_d(s, a0, a1, a2, a2 + args[3] - 1); ++ break; ++ ++ case INDEX_op_deposit_i32: ++ tcg_out_opc_bstrins_w(s, a0, a2, args[3], args[3] + args[4] - 1); ++ break; ++ case INDEX_op_deposit_i64: ++ tcg_out_opc_bstrins_d(s, a0, a2, args[3], args[3] + args[4] - 1); ++ break; ++ ++ case INDEX_op_bswap16_i32: ++ case INDEX_op_bswap16_i64: ++ tcg_out_opc_revb_2h(s, a0, a1); ++ if (a2 & TCG_BSWAP_OS) { ++ tcg_out_ext16s(s, a0, a0); ++ } else if ((a2 & (TCG_BSWAP_IZ | TCG_BSWAP_OZ)) == TCG_BSWAP_OZ) { ++ tcg_out_ext16u(s, a0, a0); ++ } ++ break; ++ ++ case INDEX_op_bswap32_i32: ++ /* All 32-bit values are computed sign-extended in the register. */ ++ a2 = TCG_BSWAP_OS; ++ /* fallthrough */ ++ case INDEX_op_bswap32_i64: ++ tcg_out_opc_revb_2w(s, a0, a1); ++ if (a2 & TCG_BSWAP_OS) { ++ tcg_out_ext32s(s, a0, a0); ++ } else if ((a2 & (TCG_BSWAP_IZ | TCG_BSWAP_OZ)) == TCG_BSWAP_OZ) { ++ tcg_out_ext32u(s, a0, a0); ++ } ++ break; ++ ++ case INDEX_op_bswap64_i64: ++ tcg_out_opc_revb_d(s, a0, a1); ++ break; ++ ++ case INDEX_op_clz_i32: ++ tcg_out_clzctz(s, OPC_CLZ_W, a0, a1, a2, c2, true); ++ break; ++ case INDEX_op_clz_i64: ++ tcg_out_clzctz(s, OPC_CLZ_D, a0, a1, a2, c2, false); ++ break; ++ ++ case INDEX_op_ctz_i32: ++ tcg_out_clzctz(s, OPC_CTZ_W, a0, a1, a2, c2, true); ++ break; ++ case INDEX_op_ctz_i64: ++ tcg_out_clzctz(s, OPC_CTZ_D, a0, a1, a2, c2, false); ++ break; ++ ++ case INDEX_op_shl_i32: ++ if (c2) { ++ tcg_out_opc_slli_w(s, a0, a1, a2 & 0x1f); ++ } else { ++ tcg_out_opc_sll_w(s, a0, a1, a2); ++ } ++ break; ++ case INDEX_op_shl_i64: ++ if (c2) { ++ tcg_out_opc_slli_d(s, a0, a1, a2 & 0x3f); ++ } else { ++ tcg_out_opc_sll_d(s, a0, a1, a2); ++ } ++ break; ++ ++ case INDEX_op_shr_i32: ++ if (c2) { ++ tcg_out_opc_srli_w(s, a0, a1, a2 & 0x1f); ++ } else { ++ tcg_out_opc_srl_w(s, a0, a1, a2); ++ } ++ break; ++ case INDEX_op_shr_i64: ++ if (c2) { ++ tcg_out_opc_srli_d(s, a0, a1, a2 & 0x3f); ++ } else { ++ tcg_out_opc_srl_d(s, a0, a1, a2); ++ } ++ break; ++ ++ case INDEX_op_sar_i32: ++ if (c2) { ++ tcg_out_opc_srai_w(s, a0, a1, a2 & 0x1f); ++ } else { ++ tcg_out_opc_sra_w(s, a0, a1, a2); ++ } ++ break; ++ case INDEX_op_sar_i64: ++ if (c2) { ++ tcg_out_opc_srai_d(s, a0, a1, a2 & 0x3f); ++ } else { ++ tcg_out_opc_sra_d(s, a0, a1, a2); ++ } ++ break; ++ ++ case INDEX_op_rotl_i32: ++ /* transform into equivalent rotr/rotri */ ++ if (c2) { ++ tcg_out_opc_rotri_w(s, a0, a1, (32 - a2) & 0x1f); ++ } else { ++ tcg_out_opc_sub_w(s, TCG_REG_TMP0, TCG_REG_ZERO, a2); ++ tcg_out_opc_rotr_w(s, a0, a1, TCG_REG_TMP0); ++ } ++ break; ++ case INDEX_op_rotl_i64: ++ /* transform into equivalent rotr/rotri */ ++ if (c2) { ++ tcg_out_opc_rotri_d(s, a0, a1, (64 - a2) & 0x3f); ++ } else { ++ tcg_out_opc_sub_w(s, TCG_REG_TMP0, TCG_REG_ZERO, a2); ++ tcg_out_opc_rotr_d(s, a0, a1, TCG_REG_TMP0); ++ } ++ break; ++ ++ case INDEX_op_rotr_i32: ++ if (c2) { ++ tcg_out_opc_rotri_w(s, a0, a1, a2 & 0x1f); ++ } else { ++ tcg_out_opc_rotr_w(s, a0, a1, a2); ++ } ++ break; ++ case INDEX_op_rotr_i64: ++ if (c2) { ++ tcg_out_opc_rotri_d(s, a0, a1, a2 & 0x3f); ++ } else { ++ tcg_out_opc_rotr_d(s, a0, a1, a2); ++ } ++ break; ++ ++ case INDEX_op_add_i32: ++ if (c2) { ++ tcg_out_opc_addi_w(s, a0, a1, a2); ++ } else { ++ tcg_out_opc_add_w(s, a0, a1, a2); ++ } ++ break; ++ case INDEX_op_add_i64: ++ if (c2) { ++ tcg_out_opc_addi_d(s, a0, a1, a2); ++ } else { ++ tcg_out_opc_add_d(s, a0, a1, a2); ++ } ++ break; ++ ++ case INDEX_op_sub_i32: ++ if (c2) { ++ tcg_out_opc_addi_w(s, a0, a1, -a2); ++ } else { ++ tcg_out_opc_sub_w(s, a0, a1, a2); ++ } ++ break; ++ case INDEX_op_sub_i64: ++ if (c2) { ++ tcg_out_opc_addi_d(s, a0, a1, -a2); ++ } else { ++ tcg_out_opc_sub_d(s, a0, a1, a2); ++ } ++ break; ++ ++ case INDEX_op_mul_i32: ++ tcg_out_opc_mul_w(s, a0, a1, a2); ++ break; ++ case INDEX_op_mul_i64: ++ tcg_out_opc_mul_d(s, a0, a1, a2); ++ break; ++ ++ case INDEX_op_mulsh_i32: ++ tcg_out_opc_mulh_w(s, a0, a1, a2); ++ break; ++ case INDEX_op_mulsh_i64: ++ tcg_out_opc_mulh_d(s, a0, a1, a2); ++ break; ++ ++ case INDEX_op_muluh_i32: ++ tcg_out_opc_mulh_wu(s, a0, a1, a2); ++ break; ++ case INDEX_op_muluh_i64: ++ tcg_out_opc_mulh_du(s, a0, a1, a2); ++ break; ++ ++ case INDEX_op_div_i32: ++ tcg_out_opc_div_w(s, a0, a1, a2); ++ break; ++ case INDEX_op_div_i64: ++ tcg_out_opc_div_d(s, a0, a1, a2); ++ break; ++ ++ case INDEX_op_divu_i32: ++ tcg_out_opc_div_wu(s, a0, a1, a2); ++ break; ++ case INDEX_op_divu_i64: ++ tcg_out_opc_div_du(s, a0, a1, a2); ++ break; ++ ++ case INDEX_op_rem_i32: ++ tcg_out_opc_mod_w(s, a0, a1, a2); ++ break; ++ case INDEX_op_rem_i64: ++ tcg_out_opc_mod_d(s, a0, a1, a2); ++ break; ++ ++ case INDEX_op_remu_i32: ++ tcg_out_opc_mod_wu(s, a0, a1, a2); ++ break; ++ case INDEX_op_remu_i64: ++ tcg_out_opc_mod_du(s, a0, a1, a2); ++ break; ++ ++ case INDEX_op_setcond_i32: ++ case INDEX_op_setcond_i64: ++ tcg_out_setcond(s, args[3], a0, a1, a2, c2); ++ break; ++ ++ case INDEX_op_ld8s_i32: ++ case INDEX_op_ld8s_i64: ++ tcg_out_ldst(s, OPC_LD_B, a0, a1, a2); ++ break; ++ case INDEX_op_ld8u_i32: ++ case INDEX_op_ld8u_i64: ++ tcg_out_ldst(s, OPC_LD_BU, a0, a1, a2); ++ break; ++ case INDEX_op_ld16s_i32: ++ case INDEX_op_ld16s_i64: ++ tcg_out_ldst(s, OPC_LD_H, a0, a1, a2); ++ break; ++ case INDEX_op_ld16u_i32: ++ case INDEX_op_ld16u_i64: ++ tcg_out_ldst(s, OPC_LD_HU, a0, a1, a2); ++ break; ++ case INDEX_op_ld_i32: ++ case INDEX_op_ld32s_i64: ++ tcg_out_ldst(s, OPC_LD_W, a0, a1, a2); ++ break; ++ case INDEX_op_ld32u_i64: ++ tcg_out_ldst(s, OPC_LD_WU, a0, a1, a2); ++ break; ++ case INDEX_op_ld_i64: ++ tcg_out_ldst(s, OPC_LD_D, a0, a1, a2); ++ break; ++ ++ case INDEX_op_st8_i32: ++ case INDEX_op_st8_i64: ++ tcg_out_ldst(s, OPC_ST_B, a0, a1, a2); ++ break; ++ case INDEX_op_st16_i32: ++ case INDEX_op_st16_i64: ++ tcg_out_ldst(s, OPC_ST_H, a0, a1, a2); ++ break; ++ case INDEX_op_st_i32: ++ case INDEX_op_st32_i64: ++ tcg_out_ldst(s, OPC_ST_W, a0, a1, a2); ++ break; ++ case INDEX_op_st_i64: ++ tcg_out_ldst(s, OPC_ST_D, a0, a1, a2); ++ break; ++ ++ case INDEX_op_qemu_ld_i32: ++ tcg_out_qemu_ld(s, args, TCG_TYPE_I32); ++ break; ++ case INDEX_op_qemu_ld_i64: ++ tcg_out_qemu_ld(s, args, TCG_TYPE_I64); ++ break; ++ case INDEX_op_qemu_st_i32: ++ tcg_out_qemu_st(s, args); ++ break; ++ case INDEX_op_qemu_st_i64: ++ tcg_out_qemu_st(s, args); ++ break; ++ ++ case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */ ++ case INDEX_op_mov_i64: ++ case INDEX_op_call: /* Always emitted via tcg_out_call. */ ++ default: ++ g_assert_not_reached(); ++ } ++} ++ ++static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) ++{ ++ switch (op) { ++ case INDEX_op_goto_ptr: ++ return C_O0_I1(r); ++ ++ case INDEX_op_st8_i32: ++ case INDEX_op_st8_i64: ++ case INDEX_op_st16_i32: ++ case INDEX_op_st16_i64: ++ case INDEX_op_st32_i64: ++ case INDEX_op_st_i32: ++ case INDEX_op_st_i64: ++ return C_O0_I2(rZ, r); ++ ++ case INDEX_op_brcond_i32: ++ case INDEX_op_brcond_i64: ++ return C_O0_I2(rZ, rZ); ++ ++ case INDEX_op_qemu_st_i32: ++ case INDEX_op_qemu_st_i64: ++ return C_O0_I2(LZ, L); ++ ++ case INDEX_op_ext8s_i32: ++ case INDEX_op_ext8s_i64: ++ case INDEX_op_ext8u_i32: ++ case INDEX_op_ext8u_i64: ++ case INDEX_op_ext16s_i32: ++ case INDEX_op_ext16s_i64: ++ case INDEX_op_ext16u_i32: ++ case INDEX_op_ext16u_i64: ++ case INDEX_op_ext32s_i64: ++ case INDEX_op_ext32u_i64: ++ case INDEX_op_extu_i32_i64: ++ case INDEX_op_extrl_i64_i32: ++ case INDEX_op_extrh_i64_i32: ++ case INDEX_op_ext_i32_i64: ++ case INDEX_op_not_i32: ++ case INDEX_op_not_i64: ++ case INDEX_op_extract_i32: ++ case INDEX_op_extract_i64: ++ case INDEX_op_bswap16_i32: ++ case INDEX_op_bswap16_i64: ++ case INDEX_op_bswap32_i32: ++ case INDEX_op_bswap32_i64: ++ case INDEX_op_bswap64_i64: ++ case INDEX_op_ld8s_i32: ++ case INDEX_op_ld8s_i64: ++ case INDEX_op_ld8u_i32: ++ case INDEX_op_ld8u_i64: ++ case INDEX_op_ld16s_i32: ++ case INDEX_op_ld16s_i64: ++ case INDEX_op_ld16u_i32: ++ case INDEX_op_ld16u_i64: ++ case INDEX_op_ld32s_i64: ++ case INDEX_op_ld32u_i64: ++ case INDEX_op_ld_i32: ++ case INDEX_op_ld_i64: ++ return C_O1_I1(r, r); ++ ++ case INDEX_op_qemu_ld_i32: ++ case INDEX_op_qemu_ld_i64: ++ return C_O1_I1(r, L); ++ ++ case INDEX_op_andc_i32: ++ case INDEX_op_andc_i64: ++ case INDEX_op_orc_i32: ++ case INDEX_op_orc_i64: ++ /* ++ * LoongArch insns for these ops don't have reg-imm forms, but we ++ * can express using andi/ori if ~constant satisfies ++ * TCG_CT_CONST_U12. ++ */ ++ return C_O1_I2(r, r, rC); ++ ++ case INDEX_op_shl_i32: ++ case INDEX_op_shl_i64: ++ case INDEX_op_shr_i32: ++ case INDEX_op_shr_i64: ++ case INDEX_op_sar_i32: ++ case INDEX_op_sar_i64: ++ case INDEX_op_rotl_i32: ++ case INDEX_op_rotl_i64: ++ case INDEX_op_rotr_i32: ++ case INDEX_op_rotr_i64: ++ return C_O1_I2(r, r, ri); ++ ++ case INDEX_op_add_i32: ++ case INDEX_op_add_i64: ++ return C_O1_I2(r, r, rI); ++ ++ case INDEX_op_and_i32: ++ case INDEX_op_and_i64: ++ case INDEX_op_nor_i32: ++ case INDEX_op_nor_i64: ++ case INDEX_op_or_i32: ++ case INDEX_op_or_i64: ++ case INDEX_op_xor_i32: ++ case INDEX_op_xor_i64: ++ /* LoongArch reg-imm bitops have their imms ZERO-extended */ ++ return C_O1_I2(r, r, rU); ++ ++ case INDEX_op_clz_i32: ++ case INDEX_op_clz_i64: ++ case INDEX_op_ctz_i32: ++ case INDEX_op_ctz_i64: ++ return C_O1_I2(r, r, rW); ++ ++ case INDEX_op_setcond_i32: ++ case INDEX_op_setcond_i64: ++ return C_O1_I2(r, r, rZ); ++ ++ case INDEX_op_deposit_i32: ++ case INDEX_op_deposit_i64: ++ /* Must deposit into the same register as input */ ++ return C_O1_I2(r, 0, rZ); ++ ++ case INDEX_op_sub_i32: ++ case INDEX_op_sub_i64: ++ return C_O1_I2(r, rZ, rN); ++ ++ case INDEX_op_mul_i32: ++ case INDEX_op_mul_i64: ++ case INDEX_op_mulsh_i32: ++ case INDEX_op_mulsh_i64: ++ case INDEX_op_muluh_i32: ++ case INDEX_op_muluh_i64: ++ case INDEX_op_div_i32: ++ case INDEX_op_div_i64: ++ case INDEX_op_divu_i32: ++ case INDEX_op_divu_i64: ++ case INDEX_op_rem_i32: ++ case INDEX_op_rem_i64: ++ case INDEX_op_remu_i32: ++ case INDEX_op_remu_i64: ++ return C_O1_I2(r, rZ, rZ); ++ ++ default: ++ g_assert_not_reached(); ++ } ++} ++ ++static const int tcg_target_callee_save_regs[] = { ++ TCG_REG_S0, /* used for the global env (TCG_AREG0) */ ++ TCG_REG_S1, ++ TCG_REG_S2, ++ TCG_REG_S3, ++ TCG_REG_S4, ++ TCG_REG_S5, ++ TCG_REG_S6, ++ TCG_REG_S7, ++ TCG_REG_S8, ++ TCG_REG_S9, ++ TCG_REG_RA, /* should be last for ABI compliance */ ++}; ++ ++/* Stack frame parameters. */ ++#define REG_SIZE (TCG_TARGET_REG_BITS / 8) ++#define SAVE_SIZE ((int)ARRAY_SIZE(tcg_target_callee_save_regs) * REG_SIZE) ++#define TEMP_SIZE (CPU_TEMP_BUF_NLONGS * (int)sizeof(long)) ++#define FRAME_SIZE ((TCG_STATIC_CALL_ARGS_SIZE + TEMP_SIZE + SAVE_SIZE \ ++ + TCG_TARGET_STACK_ALIGN - 1) \ ++ & -TCG_TARGET_STACK_ALIGN) ++#define SAVE_OFS (TCG_STATIC_CALL_ARGS_SIZE + TEMP_SIZE) ++ ++/* We're expecting to be able to use an immediate for frame allocation. */ ++QEMU_BUILD_BUG_ON(FRAME_SIZE > 0x7ff); ++ ++/* Generate global QEMU prologue and epilogue code */ ++static void tcg_target_qemu_prologue(TCGContext *s) ++{ ++ int i; ++ ++ tcg_set_frame(s, TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE, TEMP_SIZE); ++ ++ /* TB prologue */ ++ tcg_out_opc_addi_d(s, TCG_REG_SP, TCG_REG_SP, -FRAME_SIZE); ++ for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) { ++ tcg_out_st(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i], ++ TCG_REG_SP, SAVE_OFS + i * REG_SIZE); ++ } ++ ++#if !defined(CONFIG_SOFTMMU) ++ if (USE_GUEST_BASE) { ++ tcg_out_movi(s, TCG_TYPE_PTR, TCG_GUEST_BASE_REG, guest_base); ++ tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG); ++ } ++#endif ++ ++ /* Call generated code */ ++ tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]); ++ tcg_out_opc_jirl(s, TCG_REG_ZERO, tcg_target_call_iarg_regs[1], 0); ++ ++ /* Return path for goto_ptr. Set return value to 0 */ ++ tcg_code_gen_epilogue = tcg_splitwx_to_rx(s->code_ptr); ++ tcg_out_mov(s, TCG_TYPE_REG, TCG_REG_A0, TCG_REG_ZERO); ++ ++ /* TB epilogue */ ++ tb_ret_addr = tcg_splitwx_to_rx(s->code_ptr); ++ for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) { ++ tcg_out_ld(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i], ++ TCG_REG_SP, SAVE_OFS + i * REG_SIZE); ++ } ++ ++ tcg_out_opc_addi_d(s, TCG_REG_SP, TCG_REG_SP, FRAME_SIZE); ++ tcg_out_opc_jirl(s, TCG_REG_ZERO, TCG_REG_RA, 0); ++} ++ ++static void tcg_target_init(TCGContext *s) ++{ ++ tcg_target_available_regs[TCG_TYPE_I32] = ALL_GENERAL_REGS; ++ tcg_target_available_regs[TCG_TYPE_I64] = ALL_GENERAL_REGS; ++ ++ tcg_target_call_clobber_regs = ALL_GENERAL_REGS; ++ tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S0); ++ tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S1); ++ tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S2); ++ tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S3); ++ tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S4); ++ tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S5); ++ tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S6); ++ tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S7); ++ tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S8); ++ tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S9); ++ ++ s->reserved_regs = 0; ++ tcg_regset_set_reg(s->reserved_regs, TCG_REG_ZERO); ++ tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP0); ++ tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP1); ++ tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP2); ++ tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP); ++ tcg_regset_set_reg(s->reserved_regs, TCG_REG_TP); ++ tcg_regset_set_reg(s->reserved_regs, TCG_REG_RESERVED); ++} ++ ++typedef struct { ++ DebugFrameHeader h; ++ uint8_t fde_def_cfa[4]; ++ uint8_t fde_reg_ofs[ARRAY_SIZE(tcg_target_callee_save_regs) * 2]; ++} DebugFrame; ++ ++#define ELF_HOST_MACHINE EM_LOONGARCH ++ ++static const DebugFrame debug_frame = { ++ .h.cie.len = sizeof(DebugFrameCIE) - 4, /* length after .len member */ ++ .h.cie.id = -1, ++ .h.cie.version = 1, ++ .h.cie.code_align = 1, ++ .h.cie.data_align = -(TCG_TARGET_REG_BITS / 8) & 0x7f, /* sleb128 */ ++ .h.cie.return_column = TCG_REG_RA, ++ ++ /* Total FDE size does not include the "len" member. */ ++ .h.fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, h.fde.cie_offset), ++ ++ .fde_def_cfa = { ++ 12, TCG_REG_SP, /* DW_CFA_def_cfa sp, ... */ ++ (FRAME_SIZE & 0x7f) | 0x80, /* ... uleb128 FRAME_SIZE */ ++ (FRAME_SIZE >> 7) ++ }, ++ .fde_reg_ofs = { ++ 0x80 + 23, 11, /* DW_CFA_offset, s0, -88 */ ++ 0x80 + 24, 10, /* DW_CFA_offset, s1, -80 */ ++ 0x80 + 25, 9, /* DW_CFA_offset, s2, -72 */ ++ 0x80 + 26, 8, /* DW_CFA_offset, s3, -64 */ ++ 0x80 + 27, 7, /* DW_CFA_offset, s4, -56 */ ++ 0x80 + 28, 6, /* DW_CFA_offset, s5, -48 */ ++ 0x80 + 29, 5, /* DW_CFA_offset, s6, -40 */ ++ 0x80 + 30, 4, /* DW_CFA_offset, s7, -32 */ ++ 0x80 + 31, 3, /* DW_CFA_offset, s8, -24 */ ++ 0x80 + 22, 2, /* DW_CFA_offset, s9, -16 */ ++ 0x80 + 1 , 1, /* DW_CFA_offset, ra, -8 */ ++ } ++}; ++ ++void tcg_register_jit(const void *buf, size_t buf_size) ++{ ++ tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame)); ++} +diff --git a/tcg/loongarch64/tcg-target.h b/tcg/loongarch64/tcg-target.h +new file mode 100644 +index 0000000000..d58a6162f2 +--- /dev/null ++++ b/tcg/loongarch64/tcg-target.h +@@ -0,0 +1,178 @@ ++/* ++ * Tiny Code Generator for QEMU ++ * ++ * Copyright (c) 2021 WANG Xuerui ++ * ++ * Based on tcg/riscv/tcg-target.h ++ * ++ * Copyright (c) 2018 SiFive, Inc ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ++ * THE SOFTWARE. ++ */ ++ ++#ifndef LOONGARCH_TCG_TARGET_H ++#define LOONGARCH_TCG_TARGET_H ++ ++/* ++ * Loongson removed the (incomplete) 32-bit support from kernel and toolchain ++ * for the initial upstreaming of this architecture, so don't bother and just ++ * support the LP64* ABI for now. ++ */ ++#if defined(__loongarch64) ++# define TCG_TARGET_REG_BITS 64 ++#else ++# error unsupported LoongArch register size ++#endif ++ ++#define TCG_TARGET_INSN_UNIT_SIZE 4 ++#define TCG_TARGET_NB_REGS 32 ++#define MAX_CODE_GEN_BUFFER_SIZE SIZE_MAX ++ ++typedef enum { ++ TCG_REG_ZERO, ++ TCG_REG_RA, ++ TCG_REG_TP, ++ TCG_REG_SP, ++ TCG_REG_A0, ++ TCG_REG_A1, ++ TCG_REG_A2, ++ TCG_REG_A3, ++ TCG_REG_A4, ++ TCG_REG_A5, ++ TCG_REG_A6, ++ TCG_REG_A7, ++ TCG_REG_T0, ++ TCG_REG_T1, ++ TCG_REG_T2, ++ TCG_REG_T3, ++ TCG_REG_T4, ++ TCG_REG_T5, ++ TCG_REG_T6, ++ TCG_REG_T7, ++ TCG_REG_T8, ++ TCG_REG_RESERVED, ++ TCG_REG_S9, ++ TCG_REG_S0, ++ TCG_REG_S1, ++ TCG_REG_S2, ++ TCG_REG_S3, ++ TCG_REG_S4, ++ TCG_REG_S5, ++ TCG_REG_S6, ++ TCG_REG_S7, ++ TCG_REG_S8, ++ ++ /* aliases */ ++ TCG_AREG0 = TCG_REG_S0, ++ TCG_REG_TMP0 = TCG_REG_T8, ++ TCG_REG_TMP1 = TCG_REG_T7, ++ TCG_REG_TMP2 = TCG_REG_T6, ++} TCGReg; ++ ++/* used for function call generation */ ++#define TCG_REG_CALL_STACK TCG_REG_SP ++#define TCG_TARGET_STACK_ALIGN 16 ++#define TCG_TARGET_CALL_ALIGN_ARGS 1 ++#define TCG_TARGET_CALL_STACK_OFFSET 0 ++ ++/* optional instructions */ ++#define TCG_TARGET_HAS_movcond_i32 0 ++#define TCG_TARGET_HAS_div_i32 1 ++#define TCG_TARGET_HAS_rem_i32 1 ++#define TCG_TARGET_HAS_div2_i32 0 ++#define TCG_TARGET_HAS_rot_i32 1 ++#define TCG_TARGET_HAS_deposit_i32 1 ++#define TCG_TARGET_HAS_extract_i32 1 ++#define TCG_TARGET_HAS_sextract_i32 0 ++#define TCG_TARGET_HAS_extract2_i32 0 ++#define TCG_TARGET_HAS_add2_i32 0 ++#define TCG_TARGET_HAS_sub2_i32 0 ++#define TCG_TARGET_HAS_mulu2_i32 0 ++#define TCG_TARGET_HAS_muls2_i32 0 ++#define TCG_TARGET_HAS_muluh_i32 1 ++#define TCG_TARGET_HAS_mulsh_i32 1 ++#define TCG_TARGET_HAS_ext8s_i32 1 ++#define TCG_TARGET_HAS_ext16s_i32 1 ++#define TCG_TARGET_HAS_ext8u_i32 1 ++#define TCG_TARGET_HAS_ext16u_i32 1 ++#define TCG_TARGET_HAS_bswap16_i32 1 ++#define TCG_TARGET_HAS_bswap32_i32 1 ++#define TCG_TARGET_HAS_not_i32 1 ++#define TCG_TARGET_HAS_neg_i32 0 ++#define TCG_TARGET_HAS_andc_i32 1 ++#define TCG_TARGET_HAS_orc_i32 1 ++#define TCG_TARGET_HAS_eqv_i32 0 ++#define TCG_TARGET_HAS_nand_i32 0 ++#define TCG_TARGET_HAS_nor_i32 1 ++#define TCG_TARGET_HAS_clz_i32 1 ++#define TCG_TARGET_HAS_ctz_i32 1 ++#define TCG_TARGET_HAS_ctpop_i32 0 ++#define TCG_TARGET_HAS_direct_jump 0 ++#define TCG_TARGET_HAS_brcond2 0 ++#define TCG_TARGET_HAS_setcond2 0 ++#define TCG_TARGET_HAS_qemu_st8_i32 0 ++ ++/* 64-bit operations */ ++#define TCG_TARGET_HAS_movcond_i64 0 ++#define TCG_TARGET_HAS_div_i64 1 ++#define TCG_TARGET_HAS_rem_i64 1 ++#define TCG_TARGET_HAS_div2_i64 0 ++#define TCG_TARGET_HAS_rot_i64 1 ++#define TCG_TARGET_HAS_deposit_i64 1 ++#define TCG_TARGET_HAS_extract_i64 1 ++#define TCG_TARGET_HAS_sextract_i64 0 ++#define TCG_TARGET_HAS_extract2_i64 0 ++#define TCG_TARGET_HAS_extrl_i64_i32 1 ++#define TCG_TARGET_HAS_extrh_i64_i32 1 ++#define TCG_TARGET_HAS_ext8s_i64 1 ++#define TCG_TARGET_HAS_ext16s_i64 1 ++#define TCG_TARGET_HAS_ext32s_i64 1 ++#define TCG_TARGET_HAS_ext8u_i64 1 ++#define TCG_TARGET_HAS_ext16u_i64 1 ++#define TCG_TARGET_HAS_ext32u_i64 1 ++#define TCG_TARGET_HAS_bswap16_i64 1 ++#define TCG_TARGET_HAS_bswap32_i64 1 ++#define TCG_TARGET_HAS_bswap64_i64 1 ++#define TCG_TARGET_HAS_not_i64 1 ++#define TCG_TARGET_HAS_neg_i64 0 ++#define TCG_TARGET_HAS_andc_i64 1 ++#define TCG_TARGET_HAS_orc_i64 1 ++#define TCG_TARGET_HAS_eqv_i64 0 ++#define TCG_TARGET_HAS_nand_i64 0 ++#define TCG_TARGET_HAS_nor_i64 1 ++#define TCG_TARGET_HAS_clz_i64 1 ++#define TCG_TARGET_HAS_ctz_i64 1 ++#define TCG_TARGET_HAS_ctpop_i64 0 ++#define TCG_TARGET_HAS_add2_i64 0 ++#define TCG_TARGET_HAS_sub2_i64 0 ++#define TCG_TARGET_HAS_mulu2_i64 0 ++#define TCG_TARGET_HAS_muls2_i64 0 ++#define TCG_TARGET_HAS_muluh_i64 1 ++#define TCG_TARGET_HAS_mulsh_i64 1 ++ ++/* not defined -- call should be eliminated at compile time */ ++void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t, uintptr_t); ++ ++#define TCG_TARGET_DEFAULT_MO (0) ++ ++#define TCG_TARGET_NEED_LDST_LABELS ++ ++#define TCG_TARGET_HAS_MEMORY_BSWAP 0 ++ ++#endif /* LOONGARCH_TCG_TARGET_H */ +-- +2.27.0 + diff --git a/loongarch_bios.bin b/loongarch_bios.bin new file mode 100644 index 0000000000000000000000000000000000000000..3aa4f36a853b0d605d6a6dd61d933fa43084c580 GIT binary patch literal 4190208 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�`g?nIrVio3c^K4|e-Jn(WOFsaNIT$_= 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

    `M8>h>T9UpW70pJ}{!e1h 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

      qCaZ_BO#EJE}oFo(?Z|w&f0H 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 literal 0 HcmV?d00001 diff --git a/loongarch_vars.bin b/loongarch_vars.bin new file mode 100644 index 0000000000000000000000000000000000000000..65bdb77af90b92dc268c0c5c70c054dee71599f4 GIT binary patch literal 389120 zcmeIuze+*@6bInbA98VUkd`K=h`TvRs~}|{)D)pZ4GBR@OHRsd5rT-OqN!Saf#@mf z2?AfC2k2hCx%LF|{e}bQoay(ily|GOxLK=3bfQv?`{XBo8r*dz B3V{Fs literal 0 HcmV?d00001 diff --git a/qemu-kvm.spec b/qemu-kvm.spec index 8325347..3b1e30a 100644 --- a/qemu-kvm.spec +++ b/qemu-kvm.spec @@ -55,7 +55,11 @@ %ifarch aarch64 %global kvm_target aarch64 %endif - +%ifarch loongarch64 + %global kvm_target loongarch64 + %global have_spice 1 + %global have_usbredir 1 +%endif #Versions of various parts: %global requires_all_modules \ @@ -90,7 +94,7 @@ Epoch: 15 License: GPLv2 and GPLv2+ and CC-BY Group: Development/Tools URL: http://www.qemu.org/ -ExclusiveArch: x86_64 %{power64} aarch64 s390x +ExclusiveArch: x86_64 %{power64} aarch64 s390x loongarch64 Source0: http://wiki.qemu.org/download/qemu-6.2.0.tar.xz @@ -123,6 +127,8 @@ Source37: tests_data_acpi_pc_SSDT.dimmpxm Source38: tests_data_acpi_q35_FACP.slic Source39: tests_data_acpi_q35_SSDT.dimmpxm Source40: tests_data_acpi_virt_SSDT.memhp +Source41: loongarch_bios.bin +Source42: loongarch_vars.bin Patch0001: 0001-redhat-Adding-slirp-to-the-exploded-tree.patch Patch0005: 0005-Initial-redhat-build.patch @@ -437,6 +443,16 @@ Patch168: kvm-virtiofsd-use-g_date_time_get_microsecond-to-get-sub.patch Patch1000: kvm-virtiofsd-Adjust-limit-for-minor-version.patch +Patch1001: 0001-Add-Acpi-support.patch +Patch1002: 0002-Support-rtc.patch +Patch1003: 0003-Add-loongarch-machine.patch +Patch1004: 0004-Add-target-loongarch64.patch +Patch1005: 0005-Add-linux-headers-and-linux-user.patch +Patch1006: 0006-Add-disas-gdb.patch +Patch1007: 0007-Modify-kvm-cpu-vga-qapi.patch +Patch1008: 0008-Modify-compile-script.patch +Patch1009: 0009-Add-loongarch64-rh-devices.mak.patch + BuildRequires: wget BuildRequires: rpm-build BuildRequires: ninja-build @@ -625,7 +641,7 @@ Requires(postun): systemd-units Requires: seabios-bin >= 1.10.2-1 Requires: sgabios-bin %endif -%ifnarch aarch64 s390x +%ifnarch aarch64 s390x loongarch64 Requires: seavgabios-bin >= 1.12.0-3 Requires: ipxe-roms-qemu >= 20170123-1 %endif @@ -764,6 +780,9 @@ rm -fr slirp mkdir slirp %autopatch -p1 +cp %{SOURCE41} ./pc-bios/ -f +cp %{SOURCE42} ./pc-bios/ -f + %global qemu_kvm_build qemu_kvm_build mkdir -p %{qemu_kvm_build} @@ -1233,6 +1252,8 @@ rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{name}/opensbi-riscv64-virt-fw_jump.bin rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{name}/opensbi-riscv64-generic-fw_dynamic.* rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{name}/qemu-nsis.bmp rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{name}/npcm7xx_bootrom.bin +rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{name}/loongarch_bios.bin +rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{name}/loongarch_vars.bin rm -rf ${RPM_BUILD_ROOT}%{_libdir}/qemu-kvm/ui-spice-app.so @@ -1248,6 +1269,11 @@ rm -rf ${RPM_BUILD_ROOT}%{_mandir}/man1/virtfs-proxy-helper* rm -rf ${RPM_BUILD_ROOT}%{_libdir}/qemu-kvm/hw-s390x-virtio-gpu-ccw.so %endif +%ifarch loongarch64 + install -m 0644 pc-bios/loongarch_bios.bin $RPM_BUILD_ROOT%{_datadir}/%{name}/ + install -m 0644 pc-bios/loongarch_vars.bin $RPM_BUILD_ROOT%{_datadir}/%{name}/ +%endif + %ifnarch x86_64 rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{name}/kvmvapic.bin rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{name}/linuxboot.bin @@ -1349,10 +1375,12 @@ rm -rf $RPM_BUILD_ROOT%{qemudocdir}/specs popd %check +%ifnarch loongarch64 pushd %{qemu_kvm_build} echo "Testing qemu-kvm-build" export DIFF=diff; make check V=1 popd +%endif %post -n qemu-kvm-common %systemd_post ksm.service @@ -1473,6 +1501,10 @@ sh %{_sysconfdir}/sysconfig/modules/kvm.modules &> /dev/null || : %{_datadir}/%{name}/s390-ccw.img %{_datadir}/%{name}/s390-netboot.img %endif +%ifarch loongarch64 + %{_datadir}/%{name}/loongarch_bios.bin + %{_datadir}/%{name}/loongarch_vars.bin +%endif %ifnarch aarch64 s390x %{_datadir}/%{name}/vgabios.bin %{_datadir}/%{name}/vgabios-cirrus.bin @@ -1494,7 +1526,7 @@ sh %{_sysconfdir}/sysconfig/modules/kvm.modules &> /dev/null || : %ifnarch s390x %{_libdir}/%{name}/hw-display-virtio-gpu-pci-gl.so %endif -%ifarch x86_64 %{power64} +%ifarch x86_64 %{power64} loongarch64 %{_libdir}/%{name}/hw-display-virtio-vga-gl.so %endif %{_libdir}/%{name}/accel-qtest-%{kvm_target}.so @@ -1587,7 +1619,7 @@ sh %{_sysconfdir}/sysconfig/modules/kvm.modules &> /dev/null || : %{_libdir}/qemu-kvm/audio-spice.so %{_libdir}/qemu-kvm/ui-spice-core.so %{_libdir}/qemu-kvm/chardev-spice.so -%ifarch x86_64 +%ifarch x86_64 loongarch64 %{_libdir}/qemu-kvm/hw-display-qxl.so %endif %endif @@ -1607,6 +1639,7 @@ sh %{_sysconfdir}/sysconfig/modules/kvm.modules &> /dev/null || : %changelog * Tue Dec 27 2022 Jacob Wang - 6.2.0-20.0.1.2 - Adjust limit for virtiofsd minor version +- Add loongarch supporti (lixianglai@loongson.cn) * Wed Oct 12 2022 Miroslav Rezanina - 6.2.0-20.el8_7.2 - kvm-virtiofsd-use-g_date_time_get_microsecond-to-get-sub.patch [bz#2132391] -- Gitee

    hI^)cd=(ja+ZLc@t_so-0Z{BH9 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%0Dx>I}JdaouZ^+8ouz)5DddnTkZnR*QwPRO>E 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