!948 LoongArch: Update patches

From: @HHH_SONG 
Reviewed-by: @imxcc 
Signed-off-by: @imxcc
This commit is contained in:
openeuler-ci-bot 2024-05-23 07:21:59 +00:00 committed by Gitee
commit 533e153ae6
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
11 changed files with 1489 additions and 7 deletions

View File

@ -0,0 +1,434 @@
From 04aef27ede108edd63d288dd3bb395e22a603f42 Mon Sep 17 00:00:00 2001
From: Bibo Mao <maobibo@loongson.cn>
Date: Mon, 11 Mar 2024 15:01:31 +0800
Subject: [PATCH] hw/intc/loongarch_extioi: Add virt extension support
With hardware extioi, irq can be routed to four vcpus with hardware
extioi. This patch adds virt extension support, sot that irq can
be routed to 256 vcpus.
Signed-off-by: Song Gao <gaosong@loongson.cn>
Signed-off-by: Bibo Mao <maobibo@loongson.cn>
---
hw/intc/loongarch_extioi.c | 88 ++++++++++++++++++++-
hw/loongarch/virt.c | 122 ++++++++++++++++++++++++++---
include/hw/intc/loongarch_extioi.h | 21 +++++
include/hw/loongarch/virt.h | 3 +
target/loongarch/cpu.h | 1 +
5 files changed, 220 insertions(+), 15 deletions(-)
diff --git a/hw/intc/loongarch_extioi.c b/hw/intc/loongarch_extioi.c
index bdfa3b481e..fa23e247ca 100644
--- a/hw/intc/loongarch_extioi.c
+++ b/hw/intc/loongarch_extioi.c
@@ -143,15 +143,17 @@ static inline void extioi_update_sw_coremap(LoongArchExtIOI *s, int irq,
for (i = 0; i < 4; i++) {
cpu = val & 0xff;
- cpu = ctz32(cpu);
- cpu = (cpu >= 4) ? 0 : cpu;
+ if (!(s->status & BIT(EXTIOI_ENABLE_CPU_ENCODE))) {
+ cpu = ctz32(cpu);
+ cpu = (cpu >= 4) ? 0 : cpu;
+ }
val = val >> 8;
if (s->sw_coremap[irq + i] == cpu) {
continue;
}
- if (notify && test_bit(irq, (unsigned long *)s->isr)) {
+ if (notify && test_bit(irq + i, (unsigned long *)s->isr)) {
/*
* lower irq at old cpu and raise irq at new cpu
*/
@@ -265,6 +267,61 @@ static const MemoryRegionOps extioi_ops = {
.endianness = DEVICE_LITTLE_ENDIAN,
};
+static MemTxResult extioi_virt_readw(void *opaque, hwaddr addr, uint64_t *data,
+ unsigned size, MemTxAttrs attrs)
+{
+ LoongArchExtIOI *s = LOONGARCH_EXTIOI(opaque);
+
+ switch (addr) {
+ case EXTIOI_VIRT_FEATURES:
+ *data = s->features;
+ break;
+ case EXTIOI_VIRT_CONFIG:
+ *data = s->status;
+ break;
+ default:
+ break;
+ }
+
+ return MEMTX_OK;
+}
+
+static MemTxResult extioi_virt_writew(void *opaque, hwaddr addr,
+ uint64_t val, unsigned size,
+ MemTxAttrs attrs)
+{
+ LoongArchExtIOI *s = LOONGARCH_EXTIOI(opaque);
+
+ switch (addr) {
+ case EXTIOI_VIRT_FEATURES:
+ return MEMTX_ACCESS_ERROR;
+
+ case EXTIOI_VIRT_CONFIG:
+ /*
+ * extioi features can only be set at disabled status
+ */
+ if ((s->status & BIT(EXTIOI_ENABLE)) && val) {
+ return MEMTX_ACCESS_ERROR;
+ }
+
+ s->status = val & s->features;
+ break;
+ default:
+ break;
+ }
+ return MEMTX_OK;
+}
+
+static const MemoryRegionOps extioi_virt_ops = {
+ .read_with_attrs = extioi_virt_readw,
+ .write_with_attrs = extioi_virt_writew,
+ .impl.min_access_size = 4,
+ .impl.max_access_size = 4,
+ .valid.min_access_size = 4,
+ .valid.max_access_size = 8,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
static void loongarch_extioi_realize(DeviceState *dev, Error **errp)
{
LoongArchExtIOI *s = LOONGARCH_EXTIOI(dev);
@@ -284,6 +341,16 @@ static void loongarch_extioi_realize(DeviceState *dev, Error **errp)
memory_region_init_io(&s->extioi_system_mem, OBJECT(s), &extioi_ops,
s, "extioi_system_mem", 0x900);
sysbus_init_mmio(sbd, &s->extioi_system_mem);
+
+ if (s->features & BIT(EXTIOI_HAS_VIRT_EXTENSION)) {
+ memory_region_init_io(&s->virt_extend, OBJECT(s), &extioi_virt_ops,
+ s, "extioi_virt", EXTIOI_VIRT_SIZE);
+ sysbus_init_mmio(sbd, &s->virt_extend);
+ s->features |= EXTIOI_VIRT_HAS_FEATURES;
+ } else {
+ s->status |= BIT(EXTIOI_ENABLE);
+ }
+
s->cpu = g_new0(ExtIOICore, s->num_cpu);
if (s->cpu == NULL) {
error_setg(errp, "Memory allocation for ExtIOICore faile");
@@ -304,6 +371,16 @@ static void loongarch_extioi_finalize(Object *obj)
g_free(s->cpu);
}
+static void loongarch_extioi_reset(DeviceState *d)
+{
+ LoongArchExtIOI *s = LOONGARCH_EXTIOI(d);
+
+ /* use legacy interrupt routing method by default */
+ if (s->features & BIT(EXTIOI_HAS_VIRT_EXTENSION)) {
+ s->status = 0;
+ }
+}
+
static int vmstate_extioi_post_load(void *opaque, int version_id)
{
LoongArchExtIOI *s = LOONGARCH_EXTIOI(opaque);
@@ -347,12 +424,16 @@ static const VMStateDescription vmstate_loongarch_extioi = {
VMSTATE_STRUCT_VARRAY_POINTER_UINT32(cpu, LoongArchExtIOI, num_cpu,
vmstate_extioi_core, ExtIOICore),
+ VMSTATE_UINT32(features, LoongArchExtIOI),
+ VMSTATE_UINT32(status, LoongArchExtIOI),
VMSTATE_END_OF_LIST()
}
};
static Property extioi_properties[] = {
DEFINE_PROP_UINT32("num-cpu", LoongArchExtIOI, num_cpu, 1),
+ DEFINE_PROP_BIT("has-virtualization-extension", LoongArchExtIOI, features,
+ EXTIOI_HAS_VIRT_EXTENSION, 0),
DEFINE_PROP_END_OF_LIST(),
};
@@ -361,6 +442,7 @@ static void loongarch_extioi_class_init(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
dc->realize = loongarch_extioi_realize;
+ dc->reset = loongarch_extioi_reset;
device_class_set_props(dc, extioi_properties);
dc->vmsd = &vmstate_loongarch_extioi;
}
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index 6ef40fa24a..01e59f3a95 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -15,6 +15,8 @@
#include "sysemu/runstate.h"
#include "sysemu/reset.h"
#include "sysemu/rtc.h"
+#include "sysemu/tcg.h"
+#include "sysemu/kvm.h"
#include "hw/loongarch/virt.h"
#include "exec/address-spaces.h"
#include "hw/irq.h"
@@ -54,6 +56,31 @@ struct loaderparams {
const char *initrd_filename;
};
+static bool virt_is_veiointc_enabled(LoongArchMachineState *lams)
+{
+ if (lams->veiointc == ON_OFF_AUTO_OFF) {
+ return false;
+ }
+ return true;
+}
+
+static void virt_get_veiointc(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+{
+ LoongArchMachineState *lams = LOONGARCH_MACHINE(obj);
+ OnOffAuto veiointc = lams->veiointc;
+
+ visit_type_OnOffAuto(v, name, &veiointc, errp);
+}
+
+static void virt_set_veiointc(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+{
+ LoongArchMachineState *lams = LOONGARCH_MACHINE(obj);
+
+ visit_type_OnOffAuto(v, name, &lams->veiointc, errp);
+}
+
static PFlashCFI01 *virt_flash_create1(LoongArchMachineState *lams,
const char *name,
const char *alias_prop_name)
@@ -618,9 +645,18 @@ static void loongarch_irq_init(LoongArchMachineState *lams)
/* Create EXTIOI device */
extioi = qdev_new(TYPE_LOONGARCH_EXTIOI);
qdev_prop_set_uint32(extioi, "num-cpu", ms->smp.cpus);
+ if (virt_is_veiointc_enabled(lams)) {
+ qdev_prop_set_bit(extioi, "has-virtualization-extension", true);
+ }
sysbus_realize_and_unref(SYS_BUS_DEVICE(extioi), &error_fatal);
+
memory_region_add_subregion(&lams->system_iocsr, APIC_BASE,
sysbus_mmio_get_region(SYS_BUS_DEVICE(extioi), 0));
+ if (virt_is_veiointc_enabled(lams)) {
+ memory_region_add_subregion(&lams->system_iocsr, EXTIOI_VIRT_BASE,
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(extioi), 1));
+ }
+ lams->extioi = extioi;
/*
* connect ext irq to the cpu irq
@@ -780,32 +816,87 @@ static void loongarch_direct_kernel_boot(LoongArchMachineState *lams,
}
}
-static void loongarch_qemu_write(void *opaque, hwaddr addr,
- uint64_t val, unsigned size)
+static MemTxResult loongarch_qemu_write(void *opaque, hwaddr addr, uint64_t val,
+ unsigned size, MemTxAttrs attrs)
{
+ LoongArchMachineState *lams = LOONGARCH_MACHINE(opaque);
+ uint64_t features;
+
+ switch (addr) {
+ case MISC_FUNC_REG:
+ if (!virt_is_veiointc_enabled(lams)) {
+ return MEMTX_OK;
+ }
+
+ features = address_space_ldl(&lams->as_iocsr,
+ EXTIOI_VIRT_BASE + EXTIOI_VIRT_CONFIG,
+ attrs, NULL);
+ if (val & BIT_ULL(IOCSRM_EXTIOI_EN)) {
+ features |= BIT(EXTIOI_ENABLE);
+ }
+ if (val & BIT_ULL(IOCSRM_EXTIOI_INT_ENCODE)) {
+ features |= BIT(EXTIOI_ENABLE_INT_ENCODE);
+ }
+
+ address_space_stl(&lams->as_iocsr,
+ EXTIOI_VIRT_BASE + EXTIOI_VIRT_CONFIG,
+ features, attrs, NULL);
+ }
+
+ return MEMTX_OK;
}
-static uint64_t loongarch_qemu_read(void *opaque, hwaddr addr, unsigned size)
+static MemTxResult loongarch_qemu_read(void *opaque, hwaddr addr,
+ uint64_t *data,
+ unsigned size, MemTxAttrs attrs)
{
+ LoongArchMachineState *lams = LOONGARCH_MACHINE(opaque);
+ uint64_t ret = 0;
+ int features;
+
switch (addr) {
case VERSION_REG:
- return 0x11ULL;
+ ret = 0x11ULL;
+ break;
case FEATURE_REG:
- return 1ULL << IOCSRF_MSI | 1ULL << IOCSRF_EXTIOI |
- 1ULL << IOCSRF_CSRIPI;
+ ret = 1ULL << IOCSRF_MSI | 1ULL << IOCSRF_EXTIOI |
+ 1ULL << IOCSRF_CSRIPI;
+ if (kvm_enabled()) {
+ ret |= 1ULL << IOCSRF_VM;
+ }
+ break;
case VENDOR_REG:
- return 0x6e6f73676e6f6f4cULL; /* "Loongson" */
+ ret = 0x6e6f73676e6f6f4cULL; /* "Loongson" */
+ break;
case CPUNAME_REG:
- return 0x303030354133ULL; /* "3A5000" */
+ ret = 0x303030354133ULL; /* "3A5000" */
+ break;
case MISC_FUNC_REG:
- return 1ULL << IOCSRM_EXTIOI_EN;
+ if (!virt_is_veiointc_enabled(lams)) {
+ ret |= BIT_ULL(IOCSRM_EXTIOI_EN);
+ break;
+ }
+
+ features = address_space_ldl(&lams->as_iocsr,
+ EXTIOI_VIRT_BASE + EXTIOI_VIRT_CONFIG,
+ attrs, NULL);
+ if (features & BIT(EXTIOI_ENABLE)) {
+ ret |= BIT_ULL(IOCSRM_EXTIOI_EN);
+ }
+
+ if (features & BIT(EXTIOI_ENABLE_INT_ENCODE)) {
+ ret |= BIT_ULL(IOCSRM_EXTIOI_INT_ENCODE);
+ }
+ break;
}
- return 0ULL;
+
+ *data = ret;
+ return MEMTX_OK;
}
static const MemoryRegionOps loongarch_qemu_ops = {
- .read = loongarch_qemu_read,
- .write = loongarch_qemu_write,
+ .read_with_attrs = loongarch_qemu_read,
+ .write_with_attrs = loongarch_qemu_write,
.endianness = DEVICE_LITTLE_ENDIAN,
.valid = {
.min_access_size = 4,
@@ -1010,6 +1101,9 @@ static void loongarch_machine_initfn(Object *obj)
{
LoongArchMachineState *lams = LOONGARCH_MACHINE(obj);
+ if (tcg_enabled()) {
+ lams->veiointc = ON_OFF_AUTO_OFF;
+ }
lams->acpi = ON_OFF_AUTO_AUTO;
lams->oem_id = g_strndup(ACPI_BUILD_APPNAME6, 6);
lams->oem_table_id = g_strndup(ACPI_BUILD_APPNAME8, 8);
@@ -1197,6 +1291,10 @@ static void loongarch_class_init(ObjectClass *oc, void *data)
NULL, NULL);
object_class_property_set_description(oc, "acpi",
"Enable ACPI");
+ object_class_property_add(oc, "v-eiointc", "OnOffAuto",
+ virt_get_veiointc, virt_set_veiointc, NULL, NULL);
+ object_class_property_set_description(oc, "v-eiointc",
+ "Enable Virt Extend I/O Interrupt Controller");
machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE);
#ifdef CONFIG_TPM
machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_TIS_SYSBUS);
diff --git a/include/hw/intc/loongarch_extioi.h b/include/hw/intc/loongarch_extioi.h
index a0a46b888c..98f348c49d 100644
--- a/include/hw/intc/loongarch_extioi.h
+++ b/include/hw/intc/loongarch_extioi.h
@@ -40,6 +40,24 @@
#define EXTIOI_COREMAP_START (0xC00 - APIC_OFFSET)
#define EXTIOI_COREMAP_END (0xD00 - APIC_OFFSET)
+#define EXTIOI_VIRT_BASE (0x40000000)
+#define EXTIOI_VIRT_SIZE (0x1000)
+#define EXTIOI_VIRT_FEATURES (0x0)
+#define EXTIOI_HAS_VIRT_EXTENSION (0)
+#define EXTIOI_HAS_ENABLE_OPTION (1)
+#define EXTIOI_HAS_INT_ENCODE (2)
+#define EXTIOI_HAS_CPU_ENCODE (3)
+#define EXTIOI_VIRT_HAS_FEATURES (BIT(EXTIOI_HAS_VIRT_EXTENSION) \
+ | BIT(EXTIOI_HAS_ENABLE_OPTION)\
+ | BIT(EXTIOI_HAS_INT_ENCODE) \
+ | BIT(EXTIOI_HAS_CPU_ENCODE))
+#define EXTIOI_VIRT_CONFIG (0x4)
+#define EXTIOI_ENABLE (1)
+#define EXTIOI_ENABLE_INT_ENCODE (2)
+#define EXTIOI_ENABLE_CPU_ENCODE (3)
+#define EXTIOI_VIRT_COREMAP_START (0x40)
+#define EXTIOI_VIRT_COREMAP_END (0x240)
+
typedef struct ExtIOICore {
uint32_t coreisr[EXTIOI_IRQS_GROUP_COUNT];
DECLARE_BITMAP(sw_isr[LS3A_INTC_IP], EXTIOI_IRQS);
@@ -51,6 +69,8 @@ OBJECT_DECLARE_SIMPLE_TYPE(LoongArchExtIOI, LOONGARCH_EXTIOI)
struct LoongArchExtIOI {
SysBusDevice parent_obj;
uint32_t num_cpu;
+ uint32_t features;
+ uint32_t status;
/* hardware state */
uint32_t nodetype[EXTIOI_IRQS_NODETYPE_COUNT / 2];
uint32_t bounce[EXTIOI_IRQS_GROUP_COUNT];
@@ -64,5 +84,6 @@ struct LoongArchExtIOI {
qemu_irq irq[EXTIOI_IRQS];
ExtIOICore *cpu;
MemoryRegion extioi_system_mem;
+ MemoryRegion virt_extend;
};
#endif /* LOONGARCH_EXTIOI_H */
diff --git a/include/hw/loongarch/virt.h b/include/hw/loongarch/virt.h
index 252f7df7f4..99447fd1d6 100644
--- a/include/hw/loongarch/virt.h
+++ b/include/hw/loongarch/virt.h
@@ -45,16 +45,19 @@ struct LoongArchMachineState {
Notifier machine_done;
Notifier powerdown_notifier;
OnOffAuto acpi;
+ OnOffAuto veiointc;
char *oem_id;
char *oem_table_id;
DeviceState *acpi_ged;
int fdt_size;
DeviceState *platform_bus_dev;
+ DeviceState *extioi;
PCIBus *pci_bus;
PFlashCFI01 *flash[2];
MemoryRegion system_iocsr;
MemoryRegion iocsr_mem;
AddressSpace as_iocsr;
+ int features;
};
#define TYPE_LOONGARCH_MACHINE MACHINE_TYPE_NAME("virt")
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index 4aba8aba4c..4749d41c8c 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -36,6 +36,7 @@
#define CPUNAME_REG 0x20
#define MISC_FUNC_REG 0x420
#define IOCSRM_EXTIOI_EN 48
+#define IOCSRM_EXTIOI_INT_ENCODE 49
#define IOCSR_MEM_SIZE 0x428
--
2.33.0

View File

@ -3,7 +3,7 @@
Name: qemu Name: qemu
Version: 8.2.0 Version: 8.2.0
Release: 12 Release: 13
Epoch: 11 Epoch: 11
Summary: QEMU is a generic and open source machine emulator and virtualizer Summary: QEMU is a generic and open source machine emulator and virtualizer
License: GPLv2 and BSD and MIT and CC-BY-SA-4.0 License: GPLv2 and BSD and MIT and CC-BY-SA-4.0
@ -259,6 +259,16 @@ Patch0242: hw-isa-vt82c686-Keep-track-of-PIRQ-PINT-pins-separat.patch
Patch0243: target-i386-Introduce-Icelake-Server-v7-to-enable-TS.patch Patch0243: target-i386-Introduce-Icelake-Server-v7-to-enable-TS.patch
Patch0244: target-i386-Add-new-CPU-model-SierraForest.patch Patch0244: target-i386-Add-new-CPU-model-SierraForest.patch
Patch0245: target-i386-Export-RFDS-bit-to-guests.patch Patch0245: target-i386-Export-RFDS-bit-to-guests.patch
Patch0246: target-loongarch-Fix-qemu-system-loongarch64-assert-.patch
Patch0247: target-loongarch-Fix-qemu-loongarch64-hang-when-exec.patch
Patch0248: target-loongarch-Fix-tlb-huge-page-loading-issue.patch
Patch0249: target-loongarch-kvm-Add-software-breakpoint-support.patch
Patch0250: target-loongarch-kvm-sync-kernel-header-files.patch
Patch0251: hw-intc-loongarch_extioi-Add-virt-extension-support.patch
Patch0252: target-loongarch-kvm-Add-pmu-support.patch
Patch0253: target-loongarch-kvm-Fix-vm-restore-failed.patch
Patch0254: target-loongarch-kvm-Add-pv-steal-time-support.patch
Patch0255: target-loongarch-kvm-fpu-save-the-vreg-registers-hig.patch
BuildRequires: flex BuildRequires: flex
BuildRequires: gcc BuildRequires: gcc
@ -856,7 +866,19 @@ getent passwd qemu >/dev/null || \
%endif %endif
%changelog %changelog
* Thu May 10 2024 zhangxianting <zhangxianting@uniontech.com> - 11:8.2.0-12 * Mon May 20 2024 Song Gao <gaosong@loongson.cn> - 11:8.2.0-13
- target/loongarch: Fix qemu-system-loongarch64 assert
- target/loongarch: Fix qemu-loongarch64 hang when executing 'll.d $t0, $t0, 0'
- target/loongarch: Fix tlb huge page loading issue
- target/loongarch/kvm: Add software breakpoint support
- target/loongarch/kvm: sync kernel header files
- hw/intc/loongarch_extioi: Add virt extension support
- target/loongarch/kvm: Add pmu support
- target/loongarch/kvm: Fix vm restore failed
- target/loongarch/kvm: Add pv steal time support
- target/loongarch/kvm: fpu save the vreg registers high
* Fri May 10 2024 zhangxianting <zhangxianting@uniontech.com> - 11:8.2.0-12
- target/i386: Export RFDS bit to guests - target/i386: Export RFDS bit to guests
- target/i386: Add new CPU model SierraForest - target/i386: Add new CPU model SierraForest
- target/i386: Introduce Icelake-Server-v7 to enable TSX - target/i386: Introduce Icelake-Server-v7 to enable TSX
@ -867,10 +889,7 @@ getent passwd qemu >/dev/null || \
- arm/virt: Don't modify smp.max_cpus when vcpu hotplug disabled - arm/virt: Don't modify smp.max_cpus when vcpu hotplug disabled
- acpi/cpu: Fix detection of present cpu - acpi/cpu: Fix detection of present cpu
* Wed Apr 17 2024 zhangxianting <zhangxianting@uniontech.com> - 11:8.2.0-11 * Mon Apr 22 2024 Jiabo Feng <fengjiabo1@huawei.com> - 11:8.2.0-11
- remove chrpath
* Mon Apr 22 2024 Jiabo Feng <fengjiabo1@huawei.com> - 11:8.2.0-10
- hw/sd/sdhci: Do not update TRNMOD when Command Inhibit (DAT) is set(CVE-2024-3447) - hw/sd/sdhci: Do not update TRNMOD when Command Inhibit (DAT) is set(CVE-2024-3447)
- hw/virtio/virtio-crypto: Protect from DMA re-entrancy bugs(CVE-2024-3446) - hw/virtio/virtio-crypto: Protect from DMA re-entrancy bugs(CVE-2024-3446)
- hw/char/virtio-serial-bus: Protect from DMA re-entrancy bugs(CVE-2024-3446) - hw/char/virtio-serial-bus: Protect from DMA re-entrancy bugs(CVE-2024-3446)
@ -883,9 +902,12 @@ getent passwd qemu >/dev/null || \
- hw/scsi/scsi-generic: Fix io_timeout property not applying - hw/scsi/scsi-generic: Fix io_timeout property not applying
- tests: bios-tables-test: Rename smbios type 4 related test functions - tests: bios-tables-test: Rename smbios type 4 related test functions
* Thu Apr 18 2024 Tao Yang <yangtao286@huawei.com> - 11:8.2.0-9 * Thu Apr 18 2024 Tao Yang <yangtao286@huawei.com> - 11:8.2.0-10
- add '--enable-slirp' compilation options - add '--enable-slirp' compilation options
* Wed Apr 17 2024 zhangxianting <zhangxianting@uniontech.com> - 11:8.2.0-9
- remove chrpath
* Wed Apr 17 2024 Jiabo Feng <fengjiabo1@huawei.com> - 11:8.2.0-8 * Wed Apr 17 2024 Jiabo Feng <fengjiabo1@huawei.com> - 11:8.2.0-8
- include/ui/rect.h: fix qemu_rect_init() mis-assignment - include/ui/rect.h: fix qemu_rect_init() mis-assignment

View File

@ -0,0 +1,45 @@
From 6d175f9d5d5b9f46ee2f1a6fe00249bb817b5dc6 Mon Sep 17 00:00:00 2001
From: Song Gao <gaosong@loongson.cn>
Date: Wed, 20 Mar 2024 09:39:55 +0800
Subject: [PATCH] target/loongarch: Fix qemu-loongarch64 hang when
executing 'll.d $t0, $t0, 0'
On gen_ll, if a->imm is zero, make_address_x return src1,
but the load to destination may clobber src1. We use a new
destination to fix this problem.
Fixes: c5af6628f4be (target/loongarch: Extract make_address_i() helper)
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Suggested-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Song Gao <gaosong@loongson.cn>
Message-Id: <20240320013955.1561311-1-gaosong@loongson.cn>
---
target/loongarch/tcg/insn_trans/trans_atomic.c.inc | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/target/loongarch/tcg/insn_trans/trans_atomic.c.inc b/target/loongarch/tcg/insn_trans/trans_atomic.c.inc
index 80c2e286fd..974bc2a70f 100644
--- a/target/loongarch/tcg/insn_trans/trans_atomic.c.inc
+++ b/target/loongarch/tcg/insn_trans/trans_atomic.c.inc
@@ -5,14 +5,14 @@
static bool gen_ll(DisasContext *ctx, arg_rr_i *a, MemOp mop)
{
- TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+ TCGv t1 = tcg_temp_new();
TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
TCGv t0 = make_address_i(ctx, src1, a->imm);
- tcg_gen_qemu_ld_i64(dest, t0, ctx->mem_idx, mop);
+ tcg_gen_qemu_ld_i64(t1, t0, ctx->mem_idx, mop);
tcg_gen_st_tl(t0, tcg_env, offsetof(CPULoongArchState, lladdr));
- tcg_gen_st_tl(dest, tcg_env, offsetof(CPULoongArchState, llval));
- gen_set_gpr(a->rd, dest, EXT_NONE);
+ tcg_gen_st_tl(t1, tcg_env, offsetof(CPULoongArchState, llval));
+ gen_set_gpr(a->rd, t1, EXT_NONE);
return true;
}
--
2.33.0

View File

@ -0,0 +1,136 @@
From 3db0118d3663c5d56841dac30e4bf95ccfff21bd Mon Sep 17 00:00:00 2001
From: Song Gao <gaosong@loongson.cn>
Date: Tue, 2 Apr 2024 09:39:36 +0800
Subject: [PATCH] target/loongarch: Fix qemu-system-loongarch64 assert
failed with the option '-d int'
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
qemu-system-loongarch64 assert failed with the option '-d int',
the helper_idle() raise an exception EXCP_HLT, but the exception name is undefined.
-----
merge patch:
0cbb322f70e8a87e4acbffecef5ea8f9448f3513target/loongarch/cpu.c: typo fix: expection
Signed-off-by: Song Gao <gaosong@loongson.cn>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-Id: <20240321123606.1704900-1-gaosong@loongson.cn>
---
target/loongarch/cpu.c | 74 +++++++++++++++++++++++-------------------
1 file changed, 40 insertions(+), 34 deletions(-)
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index b098b1c6f3..0b3f954b64 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -43,33 +43,45 @@ const char * const fregnames[32] = {
"f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
};
-static const char * const excp_names[] = {
- [EXCCODE_INT] = "Interrupt",
- [EXCCODE_PIL] = "Page invalid exception for load",
- [EXCCODE_PIS] = "Page invalid exception for store",
- [EXCCODE_PIF] = "Page invalid exception for fetch",
- [EXCCODE_PME] = "Page modified exception",
- [EXCCODE_PNR] = "Page Not Readable exception",
- [EXCCODE_PNX] = "Page Not Executable exception",
- [EXCCODE_PPI] = "Page Privilege error",
- [EXCCODE_ADEF] = "Address error for instruction fetch",
- [EXCCODE_ADEM] = "Address error for Memory access",
- [EXCCODE_SYS] = "Syscall",
- [EXCCODE_BRK] = "Break",
- [EXCCODE_INE] = "Instruction Non-Existent",
- [EXCCODE_IPE] = "Instruction privilege error",
- [EXCCODE_FPD] = "Floating Point Disabled",
- [EXCCODE_FPE] = "Floating Point Exception",
- [EXCCODE_DBP] = "Debug breakpoint",
- [EXCCODE_BCE] = "Bound Check Exception",
- [EXCCODE_SXD] = "128 bit vector instructions Disable exception",
- [EXCCODE_ASXD] = "256 bit vector instructions Disable exception",
+struct TypeExcp {
+ int32_t exccode;
+ const char * const name;
+};
+
+static const struct TypeExcp excp_names[] = {
+ {EXCCODE_INT, "Interrupt"},
+ {EXCCODE_PIL, "Page invalid exception for load"},
+ {EXCCODE_PIS, "Page invalid exception for store"},
+ {EXCCODE_PIF, "Page invalid exception for fetch"},
+ {EXCCODE_PME, "Page modified exception"},
+ {EXCCODE_PNR, "Page Not Readable exception"},
+ {EXCCODE_PNX, "Page Not Executable exception"},
+ {EXCCODE_PPI, "Page Privilege error"},
+ {EXCCODE_ADEF, "Address error for instruction fetch"},
+ {EXCCODE_ADEM, "Address error for Memory access"},
+ {EXCCODE_SYS, "Syscall"},
+ {EXCCODE_BRK, "Break"},
+ {EXCCODE_INE, "Instruction Non-Existent"},
+ {EXCCODE_IPE, "Instruction privilege error"},
+ {EXCCODE_FPD, "Floating Point Disabled"},
+ {EXCCODE_FPE, "Floating Point Exception"},
+ {EXCCODE_DBP, "Debug breakpoint"},
+ {EXCCODE_BCE, "Bound Check Exception"},
+ {EXCCODE_SXD, "128 bit vector instructions Disable exception"},
+ {EXCCODE_ASXD, "256 bit vector instructions Disable exception"},
+ {EXCP_HLT, "EXCP_HLT"},
};
const char *loongarch_exception_name(int32_t exception)
{
- assert(excp_names[exception]);
- return excp_names[exception];
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(excp_names); i++) {
+ if (excp_names[i].exccode == exception) {
+ return excp_names[i].name;
+ }
+ }
+ return "Unknown";
}
void G_NORETURN do_raise_exception(CPULoongArchState *env,
@@ -78,7 +90,7 @@ void G_NORETURN do_raise_exception(CPULoongArchState *env,
{
CPUState *cs = env_cpu(env);
- qemu_log_mask(CPU_LOG_INT, "%s: %d (%s)\n",
+ qemu_log_mask(CPU_LOG_INT, "%s: exception: %d (%s)\n",
__func__,
exception,
loongarch_exception_name(exception));
@@ -159,22 +171,16 @@ static void loongarch_cpu_do_interrupt(CPUState *cs)
CPULoongArchState *env = &cpu->env;
bool update_badinstr = 1;
int cause = -1;
- const char *name;
bool tlbfill = FIELD_EX64(env->CSR_TLBRERA, CSR_TLBRERA, ISTLBR);
uint32_t vec_size = FIELD_EX64(env->CSR_ECFG, CSR_ECFG, VS);
if (cs->exception_index != EXCCODE_INT) {
- if (cs->exception_index < 0 ||
- cs->exception_index >= ARRAY_SIZE(excp_names)) {
- name = "unknown";
- } else {
- name = excp_names[cs->exception_index];
- }
-
qemu_log_mask(CPU_LOG_INT,
"%s enter: pc " TARGET_FMT_lx " ERA " TARGET_FMT_lx
- " TLBRERA " TARGET_FMT_lx " %s exception\n", __func__,
- env->pc, env->CSR_ERA, env->CSR_TLBRERA, name);
+ " TLBRERA " TARGET_FMT_lx " exception: %d (%s)\n",
+ __func__, env->pc, env->CSR_ERA, env->CSR_TLBRERA,
+ cs->exception_index,
+ loongarch_exception_name(cs->exception_index));
}
switch (cs->exception_index) {
--
2.33.0

View File

@ -0,0 +1,208 @@
From c5938b5f858ee8904893e08999df1af1ae13b063 Mon Sep 17 00:00:00 2001
From: Xianglai Li <lixianglai@loongson.cn>
Date: Mon, 18 Mar 2024 15:03:32 +0800
Subject: [PATCH] target/loongarch: Fix tlb huge page loading issue
When we use qemu tcg simulation, the page size of bios is 4KB.
When using the level 2 super huge page (page size is 1G) to create the page table,
it is found that the content of the corresponding address space is abnormal,
resulting in the bios can not start the operating system and graphical interface normally.
The lddir and ldpte instruction emulation has
a problem with the use of super huge page processing above level 2.
The page size is not correctly calculated,
resulting in the wrong page size of the table entry found by tlb.
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Song Gao <gaosong@loongson.cn>
Message-Id: <20240318070332.1273939-1-lixianglai@loongson.cn>
---
target/loongarch/cpu-csr.h | 3 +
target/loongarch/internals.h | 5 --
target/loongarch/tcg/tlb_helper.c | 113 +++++++++++++++++++++---------
3 files changed, 82 insertions(+), 39 deletions(-)
diff --git a/target/loongarch/cpu-csr.h b/target/loongarch/cpu-csr.h
index c59d7a9fcb..0834e91f30 100644
--- a/target/loongarch/cpu-csr.h
+++ b/target/loongarch/cpu-csr.h
@@ -67,6 +67,9 @@ FIELD(TLBENTRY, D, 1, 1)
FIELD(TLBENTRY, PLV, 2, 2)
FIELD(TLBENTRY, MAT, 4, 2)
FIELD(TLBENTRY, G, 6, 1)
+FIELD(TLBENTRY, HUGE, 6, 1)
+FIELD(TLBENTRY, HGLOBAL, 12, 1)
+FIELD(TLBENTRY, LEVEL, 13, 2)
FIELD(TLBENTRY_32, PPN, 8, 24)
FIELD(TLBENTRY_64, PPN, 12, 36)
FIELD(TLBENTRY_64, NR, 61, 1)
diff --git a/target/loongarch/internals.h b/target/loongarch/internals.h
index a2fc54c8a7..944153b180 100644
--- a/target/loongarch/internals.h
+++ b/target/loongarch/internals.h
@@ -16,11 +16,6 @@
#define TARGET_PHYS_MASK MAKE_64BIT_MASK(0, TARGET_PHYS_ADDR_SPACE_BITS)
#define TARGET_VIRT_MASK MAKE_64BIT_MASK(0, TARGET_VIRT_ADDR_SPACE_BITS)
-/* Global bit used for lddir/ldpte */
-#define LOONGARCH_PAGE_HUGE_SHIFT 6
-/* Global bit for huge page */
-#define LOONGARCH_HGLOBAL_SHIFT 12
-
void loongarch_translate_init(void);
void loongarch_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
diff --git a/target/loongarch/tcg/tlb_helper.c b/target/loongarch/tcg/tlb_helper.c
index 804ab7a263..eedd1ac376 100644
--- a/target/loongarch/tcg/tlb_helper.c
+++ b/target/loongarch/tcg/tlb_helper.c
@@ -17,6 +17,34 @@
#include "exec/log.h"
#include "cpu-csr.h"
+static void get_dir_base_width(CPULoongArchState *env, uint64_t *dir_base,
+ uint64_t *dir_width, target_ulong level)
+{
+ switch (level) {
+ case 1:
+ *dir_base = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR1_BASE);
+ *dir_width = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR1_WIDTH);
+ break;
+ case 2:
+ *dir_base = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR2_BASE);
+ *dir_width = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR2_WIDTH);
+ break;
+ case 3:
+ *dir_base = FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR3_BASE);
+ *dir_width = FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR3_WIDTH);
+ break;
+ case 4:
+ *dir_base = FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR4_BASE);
+ *dir_width = FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR4_WIDTH);
+ break;
+ default:
+ /* level may be zero for ldpte */
+ *dir_base = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTBASE);
+ *dir_width = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTWIDTH);
+ break;
+ }
+}
+
static void raise_mmu_exception(CPULoongArchState *env, target_ulong address,
MMUAccessType access_type, int tlb_error)
{
@@ -486,7 +514,25 @@ target_ulong helper_lddir(CPULoongArchState *env, target_ulong base,
target_ulong badvaddr, index, phys, ret;
int shift;
uint64_t dir_base, dir_width;
- bool huge = (base >> LOONGARCH_PAGE_HUGE_SHIFT) & 0x1;
+
+ if (unlikely((level == 0) || (level > 4))) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "Attepted LDDIR with level %"PRId64"\n", level);
+ return base;
+ }
+
+ if (FIELD_EX64(base, TLBENTRY, HUGE)) {
+ if (unlikely(level == 4)) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "Attempted use of level 4 huge page\n");
+ }
+
+ if (FIELD_EX64(base, TLBENTRY, LEVEL)) {
+ return base;
+ } else {
+ return FIELD_DP64(base, TLBENTRY, LEVEL, level);
+ }
+ }
badvaddr = env->CSR_TLBRBADV;
base = base & TARGET_PHYS_MASK;
@@ -495,30 +541,7 @@ target_ulong helper_lddir(CPULoongArchState *env, target_ulong base,
shift = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTEWIDTH);
shift = (shift + 1) * 3;
- if (huge) {
- return base;
- }
- switch (level) {
- case 1:
- dir_base = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR1_BASE);
- dir_width = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR1_WIDTH);
- break;
- case 2:
- dir_base = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR2_BASE);
- dir_width = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR2_WIDTH);
- break;
- case 3:
- dir_base = FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR3_BASE);
- dir_width = FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR3_WIDTH);
- break;
- case 4:
- dir_base = FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR4_BASE);
- dir_width = FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR4_WIDTH);
- break;
- default:
- do_raise_exception(env, EXCCODE_INE, GETPC());
- return 0;
- }
+ get_dir_base_width(env, &dir_base, &dir_width, level);
index = (badvaddr >> dir_base) & ((1 << dir_width) - 1);
phys = base | index << shift;
ret = ldq_phys(cs->as, phys) & TARGET_PHYS_MASK;
@@ -531,20 +554,42 @@ void helper_ldpte(CPULoongArchState *env, target_ulong base, target_ulong odd,
CPUState *cs = env_cpu(env);
target_ulong phys, tmp0, ptindex, ptoffset0, ptoffset1, ps, badv;
int shift;
- bool huge = (base >> LOONGARCH_PAGE_HUGE_SHIFT) & 0x1;
uint64_t ptbase = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTBASE);
uint64_t ptwidth = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTWIDTH);
+ uint64_t dir_base, dir_width;
+ /*
+ * The parameter "base" has only two types,
+ * one is the page table base address,
+ * whose bit 6 should be 0,
+ * and the other is the huge page entry,
+ * whose bit 6 should be 1.
+ */
base = base & TARGET_PHYS_MASK;
+ if (FIELD_EX64(base, TLBENTRY, HUGE)) {
+ /*
+ * Gets the huge page level and Gets huge page size.
+ * Clears the huge page level information in the entry.
+ * Clears huge page bit.
+ * Move HGLOBAL bit to GLOBAL bit.
+ */
+ get_dir_base_width(env, &dir_base, &dir_width,
+ FIELD_EX64(base, TLBENTRY, LEVEL));
+
+ base = FIELD_DP64(base, TLBENTRY, LEVEL, 0);
+ base = FIELD_DP64(base, TLBENTRY, HUGE, 0);
+ if (FIELD_EX64(base, TLBENTRY, HGLOBAL)) {
+ base = FIELD_DP64(base, TLBENTRY, HGLOBAL, 0);
+ base = FIELD_DP64(base, TLBENTRY, G, 1);
+ }
- if (huge) {
- /* Huge Page. base is paddr */
- tmp0 = base ^ (1 << LOONGARCH_PAGE_HUGE_SHIFT);
- /* Move Global bit */
- tmp0 = ((tmp0 & (1 << LOONGARCH_HGLOBAL_SHIFT)) >>
- LOONGARCH_HGLOBAL_SHIFT) << R_TLBENTRY_G_SHIFT |
- (tmp0 & (~(1 << LOONGARCH_HGLOBAL_SHIFT)));
- ps = ptbase + ptwidth - 1;
+ ps = dir_base + dir_width - 1;
+ /*
+ * Huge pages are evenly split into parity pages
+ * when loaded into the tlb,
+ * so the tlb page size needs to be divided by 2.
+ */
+ tmp0 = base;
if (odd) {
tmp0 += MAKE_64BIT_MASK(ps, 1);
}
--
2.33.0

View File

@ -0,0 +1,224 @@
From 57db061a63243c64c07624740fc039ddcc4777a2 Mon Sep 17 00:00:00 2001
From: Song Gao <gaosong@loongson.cn>
Date: Fri, 22 Mar 2024 19:26:35 +0800
Subject: [PATCH] target/loongarch/kvm: Add pmu support
This patch adds PMU support
e.g
'... -cpu max,pmu=on,pmnum=[1-16]';
'... -cpu max,pmu=on' (default pmnum = 4);
'... -cpu max,pmu=off' (disable PMU)
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
target/loongarch/cpu.c | 64 +++++++++++++++++++++++++++
target/loongarch/cpu.h | 2 +
target/loongarch/kvm/kvm.c | 55 ++++++++++++++++++++++-
target/loongarch/loongarch-qmp-cmds.c | 2 +-
4 files changed, 121 insertions(+), 2 deletions(-)
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index fdb819c2cf..bc557f207b 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -8,6 +8,7 @@
#include "qemu/osdep.h"
#include "qemu/log.h"
#include "qemu/qemu-print.h"
+#include "qemu/error-report.h"
#include "qapi/error.h"
#include "qemu/module.h"
#include "sysemu/qtest.h"
@@ -19,6 +20,7 @@
#include "internals.h"
#include "fpu/softfloat-helpers.h"
#include "cpu-csr.h"
+#include "qapi/visitor.h"
#include "sysemu/reset.h"
#include "vec.h"
#ifdef CONFIG_KVM
@@ -426,6 +428,14 @@ static void loongarch_la464_initfn(Object *obj)
data = FIELD_DP32(data, CPUCFG5, CC_DIV, 1);
env->cpucfg[5] = data;
+ if (kvm_enabled()) {
+ data = 0;
+ data = FIELD_DP32(data, CPUCFG6, PMP, 1);
+ data = FIELD_DP32(data, CPUCFG6, PMNUM, 3);
+ data = FIELD_DP32(data, CPUCFG6, PMBITS, 63);
+ env->cpucfg[6] = data;
+ }
+
data = 0;
data = FIELD_DP32(data, CPUCFG16, L1_IUPRE, 1);
data = FIELD_DP32(data, CPUCFG16, L1_DPRE, 1);
@@ -660,6 +670,48 @@ static void loongarch_set_lasx(Object *obj, bool value, Error **errp)
}
}
+static bool loongarch_get_pmu(Object *obj, Error **errp)
+{
+ LoongArchCPU *cpu = LOONGARCH_CPU(obj);
+
+ return !!(FIELD_EX32(cpu->env.cpucfg[6], CPUCFG6, PMP));
+}
+
+static void loongarch_set_pmu(Object *obj, bool value, Error **errp)
+{
+ LoongArchCPU *cpu = LOONGARCH_CPU(obj);
+
+ cpu->env.cpucfg[6] = FIELD_DP32(cpu->env.cpucfg[6], CPUCFG6, PMP, value);
+}
+
+static void loongarch_get_pmnum(Object *obj, Visitor *v,
+ const char *name, void *opaque,
+ Error **errp)
+{
+ LoongArchCPU *cpu = LOONGARCH_CPU(obj);
+ uint32_t value = FIELD_EX32(cpu->env.cpucfg[6], CPUCFG6, PMNUM);
+
+ visit_type_uint32(v, name, &value, errp);
+}
+
+static void loongarch_set_pmnum(Object *obj, Visitor *v,
+ const char *name, void *opaque,
+ Error **errp)
+{
+ LoongArchCPU *cpu = LOONGARCH_CPU(obj);
+ uint32_t *value= opaque;
+
+ if (!visit_type_uint32(v, name, value, errp)) {
+ return;
+ }
+ if ((*value <= PMNUM_MAX) && (*value > 0)) {
+ cpu->env.cpucfg[6] = FIELD_DP32(cpu->env.cpucfg[6], CPUCFG6, PMNUM, *value -1);
+ } else {
+ error_report("Performance counter number need be in [1- %d]\n", PMNUM_MAX);
+ exit(EXIT_FAILURE);
+ }
+}
+
void loongarch_cpu_post_init(Object *obj)
{
LoongArchCPU *cpu = LOONGARCH_CPU(obj);
@@ -672,6 +724,18 @@ void loongarch_cpu_post_init(Object *obj)
object_property_add_bool(obj, "lasx", loongarch_get_lasx,
loongarch_set_lasx);
}
+
+ if (kvm_enabled()) {
+ object_property_add_bool(obj, "pmu", loongarch_get_pmu,
+ loongarch_set_pmu);
+ if (FIELD_EX32(cpu->env.cpucfg[6], CPUCFG6, PMP)) {
+ uint32_t value = 4;
+ object_property_add(obj, "pmnum", "uint32",
+ loongarch_get_pmnum,
+ loongarch_set_pmnum, NULL,
+ (void *)&value);
+ }
+ }
}
static void loongarch_cpu_init(Object *obj)
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index 4749d41c8c..80cad24fa1 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -186,6 +186,8 @@ FIELD(CPUCFG6, PMNUM, 4, 4)
FIELD(CPUCFG6, PMBITS, 8, 6)
FIELD(CPUCFG6, UPM, 14, 1)
+#define PMNUM_MAX 16
+
/* cpucfg[16] bits */
FIELD(CPUCFG16, L1_IUPRE, 0, 1)
FIELD(CPUCFG16, L1_IUUNIFY, 1, 1)
diff --git a/target/loongarch/kvm/kvm.c b/target/loongarch/kvm/kvm.c
index 49d02076ad..5dda631b2b 100644
--- a/target/loongarch/kvm/kvm.c
+++ b/target/loongarch/kvm/kvm.c
@@ -573,6 +573,53 @@ static int kvm_check_cpucfg2(CPUState *cs)
return ret;
}
+static int kvm_check_cpucfg6(CPUState *cs)
+{
+ int ret;
+ uint64_t val;
+ struct kvm_device_attr attr = {
+ .group = KVM_LOONGARCH_VCPU_CPUCFG,
+ .attr = 6,
+ .addr = (uint64_t)&val,
+ };
+ LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+ CPULoongArchState *env = &cpu->env;
+
+ ret = kvm_vcpu_ioctl(cs, KVM_HAS_DEVICE_ATTR, &attr);
+ if (!ret) {
+ kvm_vcpu_ioctl(cs, KVM_GET_DEVICE_ATTR, &attr);
+
+ if (FIELD_EX32(env->cpucfg[6], CPUCFG6, PMP)) {
+ /* Check PMP */
+ if (!FIELD_EX32(val, CPUCFG6, PMP)) {
+ error_report("'pmu' feature not supported by KVM on this host"
+ " Please disable 'pmu' with "
+ "'... -cpu XXX,pmu=off ...'\n");
+ exit(EXIT_FAILURE);
+ }
+ /* Check PMNUM */
+ int guest_pmnum = FIELD_EX32(env->cpucfg[6], CPUCFG6, PMNUM);
+ int host_pmnum = FIELD_EX32(val, CPUCFG6, PMNUM);
+ if (guest_pmnum > host_pmnum){
+ warn_report("The guest pmnum %d larger than KVM support %d\n",
+ guest_pmnum, host_pmnum);
+ env->cpucfg[6] = FIELD_DP32(env->cpucfg[6], CPUCFG6,
+ PMNUM, host_pmnum);
+ }
+ /* Check PMBITS */
+ int guest_pmbits = FIELD_EX32(env->cpucfg[6], CPUCFG6, PMBITS);
+ int host_pmbits = FIELD_EX32(val, CPUCFG6, PMBITS);
+ if (guest_pmbits != host_pmbits) {
+ warn_report("The host not support PMBITS %d\n", guest_pmbits);
+ env->cpucfg[6] = FIELD_DP32(env->cpucfg[6], CPUCFG6,
+ PMBITS, host_pmbits);
+ }
+ }
+ }
+
+ return ret;
+}
+
static int kvm_loongarch_put_cpucfg(CPUState *cs)
{
int i, ret = 0;
@@ -586,7 +633,13 @@ static int kvm_loongarch_put_cpucfg(CPUState *cs)
if (ret) {
return ret;
}
- }
+ }
+ if (i == 6) {
+ ret = kvm_check_cpucfg6(cs);
+ if (ret) {
+ return ret;
+ }
+ }
val = env->cpucfg[i];
ret = kvm_set_one_reg(cs, KVM_IOC_CPUCFG(i), &val);
if (ret < 0) {
diff --git a/target/loongarch/loongarch-qmp-cmds.c b/target/loongarch/loongarch-qmp-cmds.c
index 645672ff59..2612f43de9 100644
--- a/target/loongarch/loongarch-qmp-cmds.c
+++ b/target/loongarch/loongarch-qmp-cmds.c
@@ -42,7 +42,7 @@ CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
}
static const char *cpu_model_advertised_features[] = {
- "lsx", "lasx", NULL
+ "lsx", "lasx", "pmu", "pmnum", NULL
};
CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
--
2.33.0

View File

@ -0,0 +1,169 @@
From 8b69a1b340da95cacdff252927ca8aef9d43c33a Mon Sep 17 00:00:00 2001
From: Song Gao <gaosong@loongson.cn>
Date: Wed, 24 Apr 2024 16:06:33 +0800
Subject: [PATCH] target/loongarch/kvm: Add pv steal time support
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
linux-headers/asm-loongarch/kvm.h | 2 ++
target/loongarch/cpu.h | 3 ++
target/loongarch/kvm/kvm.c | 50 ++++++++++++++++++++++++++++
target/loongarch/kvm/kvm_loongarch.h | 2 ++
target/loongarch/machine.c | 25 ++++++++++++++
5 files changed, 82 insertions(+)
diff --git a/linux-headers/asm-loongarch/kvm.h b/linux-headers/asm-loongarch/kvm.h
index 4cec8c1601..81fec85f0a 100644
--- a/linux-headers/asm-loongarch/kvm.h
+++ b/linux-headers/asm-loongarch/kvm.h
@@ -84,6 +84,8 @@ struct kvm_fpu {
#define KVM_IOC_CSRID(REG) LOONGARCH_REG_64(KVM_REG_LOONGARCH_CSR, REG)
#define KVM_IOC_CPUCFG(REG) LOONGARCH_REG_64(KVM_REG_LOONGARCH_CPUCFG, REG)
#define KVM_LOONGARCH_VCPU_CPUCFG 0
+#define KVM_LOONGARCH_VCPU_PVTIME_CTRL 1
+#define KVM_LOONGARCH_VCPU_PVTIME_GPA 0
struct kvm_debug_exit_arch {
};
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index 80cad24fa1..0ed24051af 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -365,6 +365,9 @@ typedef struct CPUArchState {
/* Store ipistate to access from this struct */
DeviceState *ipistate;
#endif
+ struct {
+ uint64_t guest_addr;
+ } st;
} CPULoongArchState;
/**
diff --git a/target/loongarch/kvm/kvm.c b/target/loongarch/kvm/kvm.c
index 5dda631b2b..e1d521a1de 100644
--- a/target/loongarch/kvm/kvm.c
+++ b/target/loongarch/kvm/kvm.c
@@ -649,6 +649,56 @@ static int kvm_loongarch_put_cpucfg(CPUState *cs)
return ret;
}
+int kvm_loongarch_put_pvtime(LoongArchCPU *cpu)
+{
+ CPULoongArchState *env = &cpu->env;
+ int err;
+ struct kvm_device_attr attr = {
+ .group = KVM_LOONGARCH_VCPU_PVTIME_CTRL,
+ .attr = KVM_LOONGARCH_VCPU_PVTIME_GPA,
+ .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_LOONGARCH_VCPU_PVTIME_CTRL,
+ .attr = KVM_LOONGARCH_VCPU_PVTIME_GPA,
+ .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_get_registers(CPUState *cs)
{
int ret;
diff --git a/target/loongarch/kvm/kvm_loongarch.h b/target/loongarch/kvm/kvm_loongarch.h
index d945b6bb82..551878a725 100644
--- a/target/loongarch/kvm/kvm_loongarch.h
+++ b/target/loongarch/kvm/kvm_loongarch.h
@@ -12,5 +12,7 @@
int kvm_loongarch_set_interrupt(LoongArchCPU *cpu, int irq, int level);
void kvm_arch_reset_vcpu(CPULoongArchState *env);
+int kvm_loongarch_put_pvtime(LoongArchCPU *cpu);
+int kvm_loongarch_get_pvtime(LoongArchCPU *cpu);
#endif
diff --git a/target/loongarch/machine.c b/target/loongarch/machine.c
index 4443caed2d..ec5abe56db 100644
--- a/target/loongarch/machine.c
+++ b/target/loongarch/machine.c
@@ -9,6 +9,8 @@
#include "cpu.h"
#include "migration/cpu.h"
#include "vec.h"
+#include "kvm/kvm_loongarch.h"
+#include "sysemu/kvm.h"
static const VMStateDescription vmstate_fpu_reg = {
.name = "fpu_reg",
@@ -122,15 +124,38 @@ const VMStateDescription vmstate_tlb = {
}
};
+static int cpu_post_load(void *opaque, int version_id)
+{
+#ifdef CONFIG_KVM
+ LoongArchCPU *cpu = opaque;
+ kvm_loongarch_put_pvtime(cpu);
+#endif
+ return 0;
+}
+
+static int cpu_pre_save(void *opaque)
+{
+#ifdef CONFIG_KVM
+ LoongArchCPU *cpu = opaque;
+ kvm_loongarch_get_pvtime(cpu);
+#endif
+ return 0;
+}
+
/* LoongArch CPU state */
const VMStateDescription vmstate_loongarch_cpu = {
.name = "cpu",
.version_id = 1,
.minimum_version_id = 1,
+ .post_load = cpu_post_load,
+ .pre_save = cpu_pre_save,
.fields = (VMStateField[]) {
VMSTATE_UINTTL_ARRAY(env.gpr, LoongArchCPU, 32),
VMSTATE_UINTTL(env.pc, LoongArchCPU),
+ /* PV time */
+ VMSTATE_UINT64(env.st.guest_addr, LoongArchCPU),
+
/* Remaining CSRs */
VMSTATE_UINT64(env.CSR_CRMD, LoongArchCPU),
VMSTATE_UINT64(env.CSR_PRMD, LoongArchCPU),
--
2.33.0

View File

@ -0,0 +1,132 @@
From 6a301af275fd684c197cf7a2e73fc265993478da Mon Sep 17 00:00:00 2001
From: Bibo Mao <maobibo@loongson.cn>
Date: Sun, 18 Feb 2024 15:00:25 +0800
Subject: [PATCH] target/loongarch/kvm: Add software breakpoint support
With KVM virtualization, debug exception is passthrough to
to guest kernel rather than host mode. Here hypercall
instruction with special hypercall code is used for sw
breakpoint usage.
Now only software breakpoint is supported, and itt is allowed
to insert/remove software breakpoint. Later hardware breakpoint
will be added.
Signed-off-by: Bibo Mao <maobibo@loongson.cn>
---
target/loongarch/kvm/kvm.c | 77 ++++++++++++++++++++++++++++++++++++++
1 file changed, 77 insertions(+)
diff --git a/target/loongarch/kvm/kvm.c b/target/loongarch/kvm/kvm.c
index c19978a970..49d02076ad 100644
--- a/target/loongarch/kvm/kvm.c
+++ b/target/loongarch/kvm/kvm.c
@@ -29,6 +29,7 @@
#include "trace.h"
static bool cap_has_mp_state;
+static unsigned int brk_insn;
const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
KVM_CAP_LAST_INFO
};
@@ -675,7 +676,14 @@ static void kvm_loongarch_vm_stage_change(void *opaque, bool running,
int kvm_arch_init_vcpu(CPUState *cs)
{
+ uint64_t val;
+
qemu_add_vm_change_state_handler(kvm_loongarch_vm_stage_change, cs);
+
+ if (!kvm_get_one_reg(cs, KVM_REG_LOONGARCH_DEBUG_INST, &val)) {
+ brk_insn = val;
+ }
+
return 0;
}
@@ -755,6 +763,68 @@ bool kvm_arch_cpu_check_are_resettable(void)
return true;
}
+
+void kvm_arch_update_guest_debug(CPUState *cpu, struct kvm_guest_debug *dbg)
+{
+ if (kvm_sw_breakpoints_active(cpu)) {
+ dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP;
+ }
+}
+
+int kvm_arch_insert_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp)
+{
+ 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;
+
+ 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;
+}
+
+int kvm_arch_insert_hw_breakpoint(vaddr addr, vaddr len, int type)
+{
+ return -ENOSYS;
+}
+
+int kvm_arch_remove_hw_breakpoint(vaddr addr, vaddr len, int type)
+{
+ return -ENOSYS;
+}
+
+void kvm_arch_remove_all_hw_breakpoints(void)
+{
+}
+
+static bool kvm_loongarch_handle_debug(CPUState *cs, struct kvm_run *run)
+{
+ LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+ CPULoongArchState *env = &cpu->env;
+
+ kvm_cpu_synchronize_state(cs);
+ if (cs->singlestep_enabled) {
+ return true;
+ }
+
+ if (kvm_find_sw_breakpoint(cs, env->pc)) {
+ return true;
+ }
+
+ return false;
+}
+
int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
{
int ret = 0;
@@ -774,6 +844,13 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
run->iocsr_io.len,
run->iocsr_io.is_write);
break;
+
+ case KVM_EXIT_DEBUG:
+ if (kvm_loongarch_handle_debug(cs, run)) {
+ ret = EXCP_DEBUG;
+ }
+ break;
+
default:
ret = -1;
warn_report("KVM: unknown exit reason %d", run->exit_reason);
--
2.33.0

View File

@ -0,0 +1,28 @@
From 7cf9ed3844ed3340165121e5fd7dcb959ee80d15 Mon Sep 17 00:00:00 2001
From: Song Gao <gaosong@loongson.cn>
Date: Wed, 24 Apr 2024 14:18:46 +0800
Subject: [PATCH] target/loongarch/kvm: Fix vm restore failed
The vmstate_loongarch_cpu need kvm_state_counter.
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
target/loongarch/machine.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/target/loongarch/machine.c b/target/loongarch/machine.c
index 1c4e01d076..4443caed2d 100644
--- a/target/loongarch/machine.c
+++ b/target/loongarch/machine.c
@@ -191,6 +191,8 @@ const VMStateDescription vmstate_loongarch_cpu = {
VMSTATE_STRUCT_ARRAY(env.tlb, LoongArchCPU, LOONGARCH_TLB_MAX,
0, vmstate_tlb, LoongArchTLB),
+ VMSTATE_UINT64(kvm_state_counter, LoongArchCPU),
+
VMSTATE_END_OF_LIST()
},
.subsections = (const VMStateDescription*[]) {
--
2.33.0

View File

@ -0,0 +1,43 @@
From 7a3573ce009afa271168829da86e2c70c63fa58a Mon Sep 17 00:00:00 2001
From: Song Gao <gaosong@loongson.cn>
Date: Tue, 14 May 2024 19:07:52 +0800
Subject: [PATCH] target/loongarch/kvm: fpu save the vreg registers high
192bit
On kvm side, get_fpu/set_fpu save the vreg registers high 192bits,
but QEMU missing.
Signed-off-by: Song Gao <gaosong@loongson.cn>
Reviewed-by: Bibo Mao <maobibo@loongson.cn>
Message-Id: <20240514110752.989572-1-gaosong@loongson.cn>
---
target/loongarch/kvm/kvm.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/target/loongarch/kvm/kvm.c b/target/loongarch/kvm/kvm.c
index e1d521a1de..5c88270132 100644
--- a/target/loongarch/kvm/kvm.c
+++ b/target/loongarch/kvm/kvm.c
@@ -444,6 +444,9 @@ static int kvm_loongarch_get_regs_fp(CPUState *cs)
env->fcsr0 = fpu.fcsr;
for (i = 0; i < 32; i++) {
env->fpr[i].vreg.UD[0] = fpu.fpr[i].val64[0];
+ env->fpr[i].vreg.UD[1] = fpu.fpr[i].val64[1];
+ env->fpr[i].vreg.UD[2] = fpu.fpr[i].val64[2];
+ env->fpr[i].vreg.UD[3] = fpu.fpr[i].val64[3];
}
for (i = 0; i < 8; i++) {
env->cf[i] = fpu.fcc & 0xFF;
@@ -465,6 +468,9 @@ static int kvm_loongarch_put_regs_fp(CPUState *cs)
fpu.fcc = 0;
for (i = 0; i < 32; i++) {
fpu.fpr[i].val64[0] = env->fpr[i].vreg.UD[0];
+ fpu.fpr[i].val64[1] = env->fpr[i].vreg.UD[1];
+ fpu.fpr[i].val64[2] = env->fpr[i].vreg.UD[2];
+ fpu.fpr[i].val64[3] = env->fpr[i].vreg.UD[3];
}
for (i = 0; i < 8; i++) {
--
2.33.0

View File

@ -0,0 +1,41 @@
From b7e49ac3b4e7dbfc9ba4645a85962294883c251a Mon Sep 17 00:00:00 2001
From: Bibo Mao <maobibo@loongson.cn>
Date: Wed, 13 Mar 2024 10:04:33 +0800
Subject: [PATCH] target/loongarch/kvm: sync kernel header files
sync kernel header files.
Signed-off-by: Bibo Mao <maobibo@loongson.cn>
---
linux-headers/asm-loongarch/kvm.h | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/linux-headers/asm-loongarch/kvm.h b/linux-headers/asm-loongarch/kvm.h
index 923d0bd382..4cec8c1601 100644
--- a/linux-headers/asm-loongarch/kvm.h
+++ b/linux-headers/asm-loongarch/kvm.h
@@ -15,10 +15,12 @@
*/
#define __KVM_HAVE_READONLY_MEM
+#define __KVM_HAVE_GUEST_DEBUG
#define KVM_COALESCED_MMIO_PAGE_OFFSET 1
#define KVM_DIRTY_LOG_PAGE_OFFSET 64
+#define KVM_GUESTDBG_USE_SW_BP 0x00010000
/*
* for KVM_GET_REGS and KVM_SET_REGS
*/
@@ -74,6 +76,8 @@ struct kvm_fpu {
#define KVM_REG_LOONGARCH_COUNTER (KVM_REG_LOONGARCH_KVM | KVM_REG_SIZE_U64 | 1)
#define KVM_REG_LOONGARCH_VCPU_RESET (KVM_REG_LOONGARCH_KVM | KVM_REG_SIZE_U64 | 2)
+/* Debugging: Special instruction for software breakpoint */
+#define KVM_REG_LOONGARCH_DEBUG_INST (KVM_REG_LOONGARCH_KVM | KVM_REG_SIZE_U64 | 3)
#define LOONGARCH_REG_SHIFT 3
#define LOONGARCH_REG_64(TYPE, REG) (TYPE | KVM_REG_SIZE_U64 | (REG << LOONGARCH_REG_SHIFT))
--
2.33.0