!902 [sync] PR-901: QEMU update to version 8.2.0-3

From: @openeuler-sync-bot 
Reviewed-by: @yezengruan 
Signed-off-by: @yezengruan
This commit is contained in:
openeuler-ci-bot 2024-04-03 01:17:28 +00:00 committed by Gitee
commit 2fa9c37963
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
26 changed files with 5425 additions and 2 deletions

View File

@ -0,0 +1,40 @@
From b21a705562867cc9dcbf0012ffa200caad8458ba Mon Sep 17 00:00:00 2001
From: Bibo Mao <maobibo@loongson.cn>
Date: Tue, 16 Jan 2024 09:39:52 +0800
Subject: [PATCH] configure: Add linux header compile support for LoongArch
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
When compiling qemu with system KVM mode for LoongArch, header files
in directory linux-headers/asm-loongarch should be used firstly.
Otherwise it fails to find kvm.h on system with old glibc, since
latest kernel header files are not installed.
This patch adds linux_arch definition for LoongArch system so that
header files in directory linux-headers/asm-loongarch can be included.
Fixes: 714b03c125 ("target/loongarch: Add loongarch kvm into meson build")
Signed-off-by: Bibo Mao <maobibo@loongson.cn>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-ID: <20240116013952.264474-1-maobibo@loongson.cn>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
configure | 1 +
1 file changed, 1 insertion(+)
diff --git a/configure b/configure
index bdda912f36..6036de83a4 100755
--- a/configure
+++ b/configure
@@ -445,6 +445,7 @@ case "$cpu" in
loongarch*)
cpu=loongarch64
host_arch=loongarch64
+ linux_arch=loongarch
;;
mips64*)
--
2.27.0

View File

@ -0,0 +1,28 @@
From fe771abc365ba0cb62dd1726f1aa5274f1807876 Mon Sep 17 00:00:00 2001
From: Jiabo Feng <fengjiabo1@huawei.com>
Date: Sat, 30 Mar 2024 16:24:45 +0800
Subject: [PATCH] disable keyring option
Due to the default prohibition of some syscall(e.g. add_key) in the Docker compilation environment, the testcases in test-crypto-secret.c cannot pass.
Signed-off-by: Jiabo Feng <fengjiabo1@huawei.com>
---
meson_options.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/meson_options.txt b/meson_options.txt
index c9baeda639..cf9706c411 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -121,7 +121,7 @@ option('avx512f', type: 'feature', value: 'disabled',
description: 'AVX512F optimizations')
option('avx512bw', type: 'feature', value: 'auto',
description: 'AVX512BW optimizations')
-option('keyring', type: 'feature', value: 'auto',
+option('keyring', type: 'feature', value: 'disabled',
description: 'Linux keyring support')
option('libkeyutils', type: 'feature', value: 'auto',
description: 'Linux keyutils support')
--
2.41.0.windows.1

View File

@ -0,0 +1,297 @@
From 4440ab99f7f7b04ef79f6b35b8330edf7fe66002 Mon Sep 17 00:00:00 2001
From: Bibo Mao <maobibo@loongson.cn>
Date: Fri, 15 Dec 2023 11:07:36 +0800
Subject: [PATCH] hw/intc/loongarch_extioi: Add dynamic cpu number support
On LoongArch physical machine, one extioi interrupt controller only
supports 4 cpus. With processor more than 4 cpus, there are multiple
extioi interrupt controllers; if interrupts need to be routed to
other cpus, they are forwarded from extioi node0 to other extioi nodes.
On virt machine model, there is simple extioi interrupt device model.
All cpus can access register of extioi interrupt controller, however
interrupt can only be route to 4 vcpu for compatible with old kernel.
This patch adds dynamic cpu number support about extioi interrupt.
With old kernel legacy extioi model is used, however kernel can detect
and choose new route method in future, so that interrupt can be routed to
all vcpus.
confict:
++<<<<<<< HEAD
+ .fields = (VMStateField[]) {
++=======
+ .fields = (const VMStateField[]) {
+ VMSTATE_UINT32_ARRAY(coreisr, ExtIOICore, EXTIOI_IRQS_GROUP_COUNT),
+ VMSTATE_END_OF_LIST()
+ }
+ };
+
+ static const VMStateDescription vmstate_loongarch_extioi = {
+ .name = TYPE_LOONGARCH_EXTIOI,
+ .version_id = 2,
+ .minimum_version_id = 2,
+ .fields = (const VMStateField[]) {
++>>>>>>> hw/intc/loongarch_extioi: Add dynamic cpu number support
solve:
save: hw/intc/loongarch_extioi: Add dynamic cpu number support
Signed-off-by: Bibo Mao <maobibo@loongson.cn>
Reviewed-by: Song Gao <gaosong@loongson.cn>
Message-Id: <20231215100333.3933632-4-maobibo@loongson.cn>
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
hw/intc/loongarch_extioi.c | 109 +++++++++++++++++++----------
hw/loongarch/virt.c | 3 +-
include/hw/intc/loongarch_extioi.h | 11 ++-
3 files changed, 82 insertions(+), 41 deletions(-)
diff --git a/hw/intc/loongarch_extioi.c b/hw/intc/loongarch_extioi.c
index 77b4776958..28802bf3ef 100644
--- a/hw/intc/loongarch_extioi.c
+++ b/hw/intc/loongarch_extioi.c
@@ -8,6 +8,7 @@
#include "qemu/osdep.h"
#include "qemu/module.h"
#include "qemu/log.h"
+#include "qapi/error.h"
#include "hw/irq.h"
#include "hw/sysbus.h"
#include "hw/loongarch/virt.h"
@@ -32,23 +33,23 @@ static void extioi_update_irq(LoongArchExtIOI *s, int irq, int level)
if (((s->enable[irq_index]) & irq_mask) == 0) {
return;
}
- s->coreisr[cpu][irq_index] |= irq_mask;
- found = find_first_bit(s->sw_isr[cpu][ipnum], EXTIOI_IRQS);
- set_bit(irq, s->sw_isr[cpu][ipnum]);
+ s->cpu[cpu].coreisr[irq_index] |= irq_mask;
+ found = find_first_bit(s->cpu[cpu].sw_isr[ipnum], EXTIOI_IRQS);
+ set_bit(irq, s->cpu[cpu].sw_isr[ipnum]);
if (found < EXTIOI_IRQS) {
/* other irq is handling, need not update parent irq level */
return;
}
} else {
- s->coreisr[cpu][irq_index] &= ~irq_mask;
- clear_bit(irq, s->sw_isr[cpu][ipnum]);
- found = find_first_bit(s->sw_isr[cpu][ipnum], EXTIOI_IRQS);
+ s->cpu[cpu].coreisr[irq_index] &= ~irq_mask;
+ clear_bit(irq, s->cpu[cpu].sw_isr[ipnum]);
+ found = find_first_bit(s->cpu[cpu].sw_isr[ipnum], EXTIOI_IRQS);
if (found < EXTIOI_IRQS) {
/* other irq is handling, need not update parent irq level */
return;
}
}
- qemu_set_irq(s->parent_irq[cpu][ipnum], level);
+ qemu_set_irq(s->cpu[cpu].parent_irq[ipnum], level);
}
static void extioi_setirq(void *opaque, int irq, int level)
@@ -96,7 +97,7 @@ static MemTxResult extioi_readw(void *opaque, hwaddr addr, uint64_t *data,
index = (offset - EXTIOI_COREISR_START) >> 2;
/* using attrs to get current cpu index */
cpu = attrs.requester_id;
- *data = s->coreisr[cpu][index];
+ *data = s->cpu[cpu].coreisr[index];
break;
case EXTIOI_COREMAP_START ... EXTIOI_COREMAP_END - 1:
index = (offset - EXTIOI_COREMAP_START) >> 2;
@@ -189,8 +190,8 @@ static MemTxResult extioi_writew(void *opaque, hwaddr addr,
index = (offset - EXTIOI_COREISR_START) >> 2;
/* using attrs to get current cpu index */
cpu = attrs.requester_id;
- old_data = s->coreisr[cpu][index];
- s->coreisr[cpu][index] = old_data & ~val;
+ old_data = s->cpu[cpu].coreisr[index];
+ s->cpu[cpu].coreisr[index] = old_data & ~val;
/* write 1 to clear interrupt */
old_data &= val;
irq = ctz32(old_data);
@@ -248,14 +249,61 @@ static const MemoryRegionOps extioi_ops = {
.endianness = DEVICE_LITTLE_ENDIAN,
};
-static const VMStateDescription vmstate_loongarch_extioi = {
- .name = TYPE_LOONGARCH_EXTIOI,
+static void loongarch_extioi_realize(DeviceState *dev, Error **errp)
+{
+ LoongArchExtIOI *s = LOONGARCH_EXTIOI(dev);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+ int i, pin;
+
+ if (s->num_cpu == 0) {
+ error_setg(errp, "num-cpu must be at least 1");
+ return;
+ }
+
+ for (i = 0; i < EXTIOI_IRQS; i++) {
+ sysbus_init_irq(sbd, &s->irq[i]);
+ }
+
+ qdev_init_gpio_in(dev, extioi_setirq, EXTIOI_IRQS);
+ 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);
+ s->cpu = g_new0(ExtIOICore, s->num_cpu);
+ if (s->cpu == NULL) {
+ error_setg(errp, "Memory allocation for ExtIOICore faile");
+ return;
+ }
+
+ for (i = 0; i < s->num_cpu; i++) {
+ for (pin = 0; pin < LS3A_INTC_IP; pin++) {
+ qdev_init_gpio_out(dev, &s->cpu[i].parent_irq[pin], 1);
+ }
+ }
+}
+
+static void loongarch_extioi_finalize(Object *obj)
+{
+ LoongArchExtIOI *s = LOONGARCH_EXTIOI(obj);
+
+ g_free(s->cpu);
+}
+
+static const VMStateDescription vmstate_extioi_core = {
+ .name = "extioi-core",
.version_id = 1,
.minimum_version_id = 1,
- .fields = (VMStateField[]) {
+ .fields = (const VMStateField[]) {
+ VMSTATE_UINT32_ARRAY(coreisr, ExtIOICore, EXTIOI_IRQS_GROUP_COUNT),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static const VMStateDescription vmstate_loongarch_extioi = {
+ .name = TYPE_LOONGARCH_EXTIOI,
+ .version_id = 2,
+ .minimum_version_id = 2,
+ .fields = (const VMStateField[]) {
VMSTATE_UINT32_ARRAY(bounce, LoongArchExtIOI, EXTIOI_IRQS_GROUP_COUNT),
- VMSTATE_UINT32_2DARRAY(coreisr, LoongArchExtIOI, EXTIOI_CPUS,
- EXTIOI_IRQS_GROUP_COUNT),
VMSTATE_UINT32_ARRAY(nodetype, LoongArchExtIOI,
EXTIOI_IRQS_NODETYPE_COUNT / 2),
VMSTATE_UINT32_ARRAY(enable, LoongArchExtIOI, EXTIOI_IRQS / 32),
@@ -265,45 +313,32 @@ static const VMStateDescription vmstate_loongarch_extioi = {
VMSTATE_UINT8_ARRAY(sw_ipmap, LoongArchExtIOI, EXTIOI_IRQS_IPMAP_SIZE),
VMSTATE_UINT8_ARRAY(sw_coremap, LoongArchExtIOI, EXTIOI_IRQS),
+ VMSTATE_STRUCT_VARRAY_POINTER_UINT32(cpu, LoongArchExtIOI, num_cpu,
+ vmstate_extioi_core, ExtIOICore),
VMSTATE_END_OF_LIST()
}
};
-static void loongarch_extioi_instance_init(Object *obj)
-{
- SysBusDevice *dev = SYS_BUS_DEVICE(obj);
- LoongArchExtIOI *s = LOONGARCH_EXTIOI(obj);
- int i, cpu, pin;
-
- for (i = 0; i < EXTIOI_IRQS; i++) {
- sysbus_init_irq(dev, &s->irq[i]);
- }
-
- qdev_init_gpio_in(DEVICE(obj), extioi_setirq, EXTIOI_IRQS);
-
- for (cpu = 0; cpu < EXTIOI_CPUS; cpu++) {
- for (pin = 0; pin < LS3A_INTC_IP; pin++) {
- qdev_init_gpio_out(DEVICE(obj), &s->parent_irq[cpu][pin], 1);
- }
- }
- memory_region_init_io(&s->extioi_system_mem, OBJECT(s), &extioi_ops,
- s, "extioi_system_mem", 0x900);
- sysbus_init_mmio(dev, &s->extioi_system_mem);
-}
+static Property extioi_properties[] = {
+ DEFINE_PROP_UINT32("num-cpu", LoongArchExtIOI, num_cpu, 1),
+ DEFINE_PROP_END_OF_LIST(),
+};
static void loongarch_extioi_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
+ dc->realize = loongarch_extioi_realize;
+ device_class_set_props(dc, extioi_properties);
dc->vmsd = &vmstate_loongarch_extioi;
}
static const TypeInfo loongarch_extioi_info = {
.name = TYPE_LOONGARCH_EXTIOI,
.parent = TYPE_SYS_BUS_DEVICE,
- .instance_init = loongarch_extioi_instance_init,
.instance_size = sizeof(struct LoongArchExtIOI),
.class_init = loongarch_extioi_class_init,
+ .instance_finalize = loongarch_extioi_finalize,
};
static void loongarch_extioi_register_types(void)
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index 13d19b6da3..c9a680e61a 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -582,6 +582,7 @@ 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);
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));
@@ -590,7 +591,7 @@ static void loongarch_irq_init(LoongArchMachineState *lams)
* connect ext irq to the cpu irq
* cpu_pin[9:2] <= intc_pin[7:0]
*/
- for (cpu = 0; cpu < MIN(ms->smp.cpus, EXTIOI_CPUS); cpu++) {
+ for (cpu = 0; cpu < ms->smp.cpus; cpu++) {
cpudev = DEVICE(qemu_get_cpu(cpu));
for (pin = 0; pin < LS3A_INTC_IP; pin++) {
qdev_connect_gpio_out(extioi, (cpu * 8 + pin),
diff --git a/include/hw/intc/loongarch_extioi.h b/include/hw/intc/loongarch_extioi.h
index 110e5e8873..a0a46b888c 100644
--- a/include/hw/intc/loongarch_extioi.h
+++ b/include/hw/intc/loongarch_extioi.h
@@ -40,24 +40,29 @@
#define EXTIOI_COREMAP_START (0xC00 - APIC_OFFSET)
#define EXTIOI_COREMAP_END (0xD00 - APIC_OFFSET)
+typedef struct ExtIOICore {
+ uint32_t coreisr[EXTIOI_IRQS_GROUP_COUNT];
+ DECLARE_BITMAP(sw_isr[LS3A_INTC_IP], EXTIOI_IRQS);
+ qemu_irq parent_irq[LS3A_INTC_IP];
+} ExtIOICore;
+
#define TYPE_LOONGARCH_EXTIOI "loongarch.extioi"
OBJECT_DECLARE_SIMPLE_TYPE(LoongArchExtIOI, LOONGARCH_EXTIOI)
struct LoongArchExtIOI {
SysBusDevice parent_obj;
+ uint32_t num_cpu;
/* hardware state */
uint32_t nodetype[EXTIOI_IRQS_NODETYPE_COUNT / 2];
uint32_t bounce[EXTIOI_IRQS_GROUP_COUNT];
uint32_t isr[EXTIOI_IRQS / 32];
- uint32_t coreisr[EXTIOI_CPUS][EXTIOI_IRQS_GROUP_COUNT];
uint32_t enable[EXTIOI_IRQS / 32];
uint32_t ipmap[EXTIOI_IRQS_IPMAP_SIZE / 4];
uint32_t coremap[EXTIOI_IRQS / 4];
uint32_t sw_pending[EXTIOI_IRQS / 32];
- DECLARE_BITMAP(sw_isr[EXTIOI_CPUS][LS3A_INTC_IP], EXTIOI_IRQS);
uint8_t sw_ipmap[EXTIOI_IRQS_IPMAP_SIZE];
uint8_t sw_coremap[EXTIOI_IRQS];
- qemu_irq parent_irq[EXTIOI_CPUS][LS3A_INTC_IP];
qemu_irq irq[EXTIOI_IRQS];
+ ExtIOICore *cpu;
MemoryRegion extioi_system_mem;
};
#endif /* LOONGARCH_EXTIOI_H */
--
2.27.0

View File

@ -0,0 +1,193 @@
From db8c355d923c218c5ca373c4acd5d13493152889 Mon Sep 17 00:00:00 2001
From: Bibo Mao <maobibo@loongson.cn>
Date: Fri, 15 Dec 2023 17:42:58 +0800
Subject: [PATCH] hw/intc/loongarch_extioi: Add vmstate post_load support
There are elements sw_ipmap and sw_coremap, which is usd to speed
up irq injection flow. They are saved and restored in vmstate during
migration, indeed they can calculated from hw registers. Here
post_load is added for get sw_ipmap and sw_coremap from extioi hw
state.
Signed-off-by: Bibo Mao <maobibo@loongson.cn>
Reviewed-by: Song Gao <gaosong@loongson.cn>
Message-Id: <20231215100333.3933632-5-maobibo@loongson.cn>
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
hw/intc/loongarch_extioi.c | 120 +++++++++++++++++++++++--------------
1 file changed, 76 insertions(+), 44 deletions(-)
diff --git a/hw/intc/loongarch_extioi.c b/hw/intc/loongarch_extioi.c
index 28802bf3ef..bdfa3b481e 100644
--- a/hw/intc/loongarch_extioi.c
+++ b/hw/intc/loongarch_extioi.c
@@ -130,12 +130,66 @@ static inline void extioi_enable_irq(LoongArchExtIOI *s, int index,\
}
}
+static inline void extioi_update_sw_coremap(LoongArchExtIOI *s, int irq,
+ uint64_t val, bool notify)
+{
+ int i, cpu;
+
+ /*
+ * loongarch only support little endian,
+ * so we paresd the value with little endian.
+ */
+ val = cpu_to_le64(val);
+
+ for (i = 0; i < 4; i++) {
+ cpu = val & 0xff;
+ 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)) {
+ /*
+ * lower irq at old cpu and raise irq at new cpu
+ */
+ extioi_update_irq(s, irq + i, 0);
+ s->sw_coremap[irq + i] = cpu;
+ extioi_update_irq(s, irq + i, 1);
+ } else {
+ s->sw_coremap[irq + i] = cpu;
+ }
+ }
+}
+
+static inline void extioi_update_sw_ipmap(LoongArchExtIOI *s, int index,
+ uint64_t val)
+{
+ int i;
+ uint8_t ipnum;
+
+ /*
+ * loongarch only support little endian,
+ * so we paresd the value with little endian.
+ */
+ val = cpu_to_le64(val);
+ for (i = 0; i < 4; i++) {
+ ipnum = val & 0xff;
+ ipnum = ctz32(ipnum);
+ ipnum = (ipnum >= 4) ? 0 : ipnum;
+ s->sw_ipmap[index * 4 + i] = ipnum;
+ val = val >> 8;
+ }
+}
+
static MemTxResult extioi_writew(void *opaque, hwaddr addr,
uint64_t val, unsigned size,
MemTxAttrs attrs)
{
LoongArchExtIOI *s = LOONGARCH_EXTIOI(opaque);
- int i, cpu, index, old_data, irq;
+ int cpu, index, old_data, irq;
uint32_t offset;
trace_loongarch_extioi_writew(addr, val);
@@ -153,20 +207,7 @@ static MemTxResult extioi_writew(void *opaque, hwaddr addr,
*/
index = (offset - EXTIOI_IPMAP_START) >> 2;
s->ipmap[index] = val;
- /*
- * loongarch only support little endian,
- * so we paresd the value with little endian.
- */
- val = cpu_to_le64(val);
- for (i = 0; i < 4; i++) {
- uint8_t ipnum;
- ipnum = val & 0xff;
- ipnum = ctz32(ipnum);
- ipnum = (ipnum >= 4) ? 0 : ipnum;
- s->sw_ipmap[index * 4 + i] = ipnum;
- val = val >> 8;
- }
-
+ extioi_update_sw_ipmap(s, index, val);
break;
case EXTIOI_ENABLE_START ... EXTIOI_ENABLE_END - 1:
index = (offset - EXTIOI_ENABLE_START) >> 2;
@@ -205,33 +246,8 @@ static MemTxResult extioi_writew(void *opaque, hwaddr addr,
irq = offset - EXTIOI_COREMAP_START;
index = irq / 4;
s->coremap[index] = val;
- /*
- * loongarch only support little endian,
- * so we paresd the value with little endian.
- */
- val = cpu_to_le64(val);
-
- for (i = 0; i < 4; i++) {
- cpu = val & 0xff;
- cpu = ctz32(cpu);
- cpu = (cpu >= 4) ? 0 : cpu;
- val = val >> 8;
-
- if (s->sw_coremap[irq + i] == cpu) {
- continue;
- }
-
- if (test_bit(irq, (unsigned long *)s->isr)) {
- /*
- * lower irq at old cpu and raise irq at new cpu
- */
- extioi_update_irq(s, irq + i, 0);
- s->sw_coremap[irq + i] = cpu;
- extioi_update_irq(s, irq + i, 1);
- } else {
- s->sw_coremap[irq + i] = cpu;
- }
- }
+
+ extioi_update_sw_coremap(s, irq, val, true);
break;
default:
break;
@@ -288,6 +304,23 @@ static void loongarch_extioi_finalize(Object *obj)
g_free(s->cpu);
}
+static int vmstate_extioi_post_load(void *opaque, int version_id)
+{
+ LoongArchExtIOI *s = LOONGARCH_EXTIOI(opaque);
+ int i, start_irq;
+
+ for (i = 0; i < (EXTIOI_IRQS / 4); i++) {
+ start_irq = i * 4;
+ extioi_update_sw_coremap(s, start_irq, s->coremap[i], false);
+ }
+
+ for (i = 0; i < (EXTIOI_IRQS_IPMAP_SIZE / 4); i++) {
+ extioi_update_sw_ipmap(s, i, s->ipmap[i]);
+ }
+
+ return 0;
+}
+
static const VMStateDescription vmstate_extioi_core = {
.name = "extioi-core",
.version_id = 1,
@@ -302,6 +335,7 @@ static const VMStateDescription vmstate_loongarch_extioi = {
.name = TYPE_LOONGARCH_EXTIOI,
.version_id = 2,
.minimum_version_id = 2,
+ .post_load = vmstate_extioi_post_load,
.fields = (const VMStateField[]) {
VMSTATE_UINT32_ARRAY(bounce, LoongArchExtIOI, EXTIOI_IRQS_GROUP_COUNT),
VMSTATE_UINT32_ARRAY(nodetype, LoongArchExtIOI,
@@ -310,8 +344,6 @@ static const VMStateDescription vmstate_loongarch_extioi = {
VMSTATE_UINT32_ARRAY(isr, LoongArchExtIOI, EXTIOI_IRQS / 32),
VMSTATE_UINT32_ARRAY(ipmap, LoongArchExtIOI, EXTIOI_IRQS_IPMAP_SIZE / 4),
VMSTATE_UINT32_ARRAY(coremap, LoongArchExtIOI, EXTIOI_IRQS / 4),
- VMSTATE_UINT8_ARRAY(sw_ipmap, LoongArchExtIOI, EXTIOI_IRQS_IPMAP_SIZE),
- VMSTATE_UINT8_ARRAY(sw_coremap, LoongArchExtIOI, EXTIOI_IRQS),
VMSTATE_STRUCT_VARRAY_POINTER_UINT32(cpu, LoongArchExtIOI, num_cpu,
vmstate_extioi_core, ExtIOICore),
--
2.27.0

View File

@ -0,0 +1,286 @@
From b8f53cfa91e86d5163318f8ade1cca18e94f3eb7 Mon Sep 17 00:00:00 2001
From: Bibo Mao <maobibo@loongson.cn>
Date: Wed, 13 Dec 2023 12:12:01 +0800
Subject: [PATCH] hw/intc/loongarch_ipi: Use MemTxAttrs interface for ipi ops
There are two interface pairs for MemoryRegionOps, read/write and
read_with_attrs/write_with_attrs. The later is better for ipi device
emulation since initial cpu can be parsed from attrs.requester_id.
And requester_id can be overrided for IOCSR_IPI_SEND and mail_send
function when it is to forward message to another vcpu.
Signed-off-by: Bibo Mao <maobibo@loongson.cn>
Reviewed-by: Song Gao <gaosong@loongson.cn>
Message-Id: <20231215100333.3933632-2-maobibo@loongson.cn>
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
hw/intc/loongarch_ipi.c | 136 +++++++++++++++++++++++-----------------
1 file changed, 77 insertions(+), 59 deletions(-)
diff --git a/hw/intc/loongarch_ipi.c b/hw/intc/loongarch_ipi.c
index 67858b521c..221246c5cb 100644
--- a/hw/intc/loongarch_ipi.c
+++ b/hw/intc/loongarch_ipi.c
@@ -17,14 +17,16 @@
#include "target/loongarch/internals.h"
#include "trace.h"
-static void loongarch_ipi_writel(void *, hwaddr, uint64_t, unsigned);
-
-static uint64_t loongarch_ipi_readl(void *opaque, hwaddr addr, unsigned size)
+static MemTxResult loongarch_ipi_readl(void *opaque, hwaddr addr,
+ uint64_t *data,
+ unsigned size, MemTxAttrs attrs)
{
- IPICore *s = opaque;
+ IPICore *s;
+ LoongArchIPI *ipi = opaque;
uint64_t ret = 0;
int index = 0;
+ s = &ipi->ipi_core;
addr &= 0xff;
switch (addr) {
case CORE_STATUS_OFF:
@@ -49,10 +51,12 @@ static uint64_t loongarch_ipi_readl(void *opaque, hwaddr addr, unsigned size)
}
trace_loongarch_ipi_read(size, (uint64_t)addr, ret);
- return ret;
+ *data = ret;
+ return MEMTX_OK;
}
-static void send_ipi_data(CPULoongArchState *env, uint64_t val, hwaddr addr)
+static void send_ipi_data(CPULoongArchState *env, uint64_t val, hwaddr addr,
+ MemTxAttrs attrs)
{
int i, mask = 0, data = 0;
@@ -62,7 +66,7 @@ static void send_ipi_data(CPULoongArchState *env, uint64_t val, hwaddr addr)
*/
if ((val >> 27) & 0xf) {
data = address_space_ldl(&env->address_space_iocsr, addr,
- MEMTXATTRS_UNSPECIFIED, NULL);
+ attrs, NULL);
for (i = 0; i < 4; i++) {
/* get mask for byte writing */
if (val & (0x1 << (27 + i))) {
@@ -74,7 +78,7 @@ static void send_ipi_data(CPULoongArchState *env, uint64_t val, hwaddr addr)
data &= mask;
data |= (val >> 32) & ~mask;
address_space_stl(&env->address_space_iocsr, addr,
- data, MEMTXATTRS_UNSPECIFIED, NULL);
+ data, attrs, NULL);
}
static int archid_cmp(const void *a, const void *b)
@@ -103,80 +107,72 @@ static CPUState *ipi_getcpu(int arch_id)
CPUArchId *archid;
archid = find_cpu_by_archid(machine, arch_id);
- return CPU(archid->cpu);
-}
-
-static void ipi_send(uint64_t val)
-{
- uint32_t cpuid;
- uint8_t vector;
- CPUState *cs;
- LoongArchCPU *cpu;
- LoongArchIPI *s;
-
- cpuid = extract32(val, 16, 10);
- if (cpuid >= LOONGARCH_MAX_CPUS) {
- trace_loongarch_ipi_unsupported_cpuid("IOCSR_IPI_SEND", cpuid);
- return;
+ if (archid) {
+ return CPU(archid->cpu);
}
- /* IPI status vector */
- vector = extract8(val, 0, 5);
-
- cs = ipi_getcpu(cpuid);
- cpu = LOONGARCH_CPU(cs);
- s = LOONGARCH_IPI(cpu->env.ipistate);
- loongarch_ipi_writel(&s->ipi_core, CORE_SET_OFF, BIT(vector), 4);
+ return NULL;
}
-static void mail_send(uint64_t val)
+static MemTxResult mail_send(uint64_t val, MemTxAttrs attrs)
{
uint32_t cpuid;
hwaddr addr;
- CPULoongArchState *env;
CPUState *cs;
- LoongArchCPU *cpu;
cpuid = extract32(val, 16, 10);
if (cpuid >= LOONGARCH_MAX_CPUS) {
trace_loongarch_ipi_unsupported_cpuid("IOCSR_MAIL_SEND", cpuid);
- return;
+ return MEMTX_DECODE_ERROR;
}
- addr = 0x1020 + (val & 0x1c);
cs = ipi_getcpu(cpuid);
- cpu = LOONGARCH_CPU(cs);
- env = &cpu->env;
- send_ipi_data(env, val, addr);
+ if (cs == NULL) {
+ return MEMTX_DECODE_ERROR;
+ }
+
+ /* override requester_id */
+ addr = SMP_IPI_MAILBOX + CORE_BUF_20 + (val & 0x1c);
+ attrs.requester_id = cs->cpu_index;
+ send_ipi_data(&LOONGARCH_CPU(cs)->env, val, addr, attrs);
+ return MEMTX_OK;
}
-static void any_send(uint64_t val)
+static MemTxResult any_send(uint64_t val, MemTxAttrs attrs)
{
uint32_t cpuid;
hwaddr addr;
- CPULoongArchState *env;
CPUState *cs;
- LoongArchCPU *cpu;
cpuid = extract32(val, 16, 10);
if (cpuid >= LOONGARCH_MAX_CPUS) {
trace_loongarch_ipi_unsupported_cpuid("IOCSR_ANY_SEND", cpuid);
- return;
+ return MEMTX_DECODE_ERROR;
}
- addr = val & 0xffff;
cs = ipi_getcpu(cpuid);
- cpu = LOONGARCH_CPU(cs);
- env = &cpu->env;
- send_ipi_data(env, val, addr);
+ if (cs == NULL) {
+ return MEMTX_DECODE_ERROR;
+ }
+
+ /* override requester_id */
+ addr = val & 0xffff;
+ attrs.requester_id = cs->cpu_index;
+ send_ipi_data(&LOONGARCH_CPU(cs)->env, val, addr, attrs);
+ return MEMTX_OK;
}
-static void loongarch_ipi_writel(void *opaque, hwaddr addr, uint64_t val,
- unsigned size)
+static MemTxResult loongarch_ipi_writel(void *opaque, hwaddr addr, uint64_t val,
+ unsigned size, MemTxAttrs attrs)
{
- IPICore *s = opaque;
+ LoongArchIPI *ipi = opaque;
+ IPICore *s;
int index = 0;
+ uint32_t cpuid;
+ uint8_t vector;
+ CPUState *cs;
+ s = &ipi->ipi_core;
addr &= 0xff;
trace_loongarch_ipi_write(size, (uint64_t)addr, val);
switch (addr) {
@@ -203,17 +199,35 @@ static void loongarch_ipi_writel(void *opaque, hwaddr addr, uint64_t val,
s->buf[index] = val;
break;
case IOCSR_IPI_SEND:
- ipi_send(val);
+ cpuid = extract32(val, 16, 10);
+ if (cpuid >= LOONGARCH_MAX_CPUS) {
+ trace_loongarch_ipi_unsupported_cpuid("IOCSR_IPI_SEND", cpuid);
+ return MEMTX_DECODE_ERROR;
+ }
+
+ /* IPI status vector */
+ vector = extract8(val, 0, 5);
+ cs = ipi_getcpu(cpuid);
+ if (cs == NULL) {
+ return MEMTX_DECODE_ERROR;
+ }
+
+ /* override requester_id */
+ attrs.requester_id = cs->cpu_index;
+ ipi = LOONGARCH_IPI(LOONGARCH_CPU(cs)->env.ipistate);
+ loongarch_ipi_writel(ipi, CORE_SET_OFF, BIT(vector), 4, attrs);
break;
default:
qemu_log_mask(LOG_UNIMP, "invalid write: %x", (uint32_t)addr);
break;
}
+
+ return MEMTX_OK;
}
static const MemoryRegionOps loongarch_ipi_ops = {
- .read = loongarch_ipi_readl,
- .write = loongarch_ipi_writel,
+ .read_with_attrs = loongarch_ipi_readl,
+ .write_with_attrs = loongarch_ipi_writel,
.impl.min_access_size = 4,
.impl.max_access_size = 4,
.valid.min_access_size = 4,
@@ -222,24 +236,28 @@ static const MemoryRegionOps loongarch_ipi_ops = {
};
/* mail send and any send only support writeq */
-static void loongarch_ipi_writeq(void *opaque, hwaddr addr, uint64_t val,
- unsigned size)
+static MemTxResult loongarch_ipi_writeq(void *opaque, hwaddr addr, uint64_t val,
+ unsigned size, MemTxAttrs attrs)
{
+ MemTxResult ret = MEMTX_OK;
+
addr &= 0xfff;
switch (addr) {
case MAIL_SEND_OFFSET:
- mail_send(val);
+ ret = mail_send(val, attrs);
break;
case ANY_SEND_OFFSET:
- any_send(val);
+ ret = any_send(val, attrs);
break;
default:
break;
}
+
+ return ret;
}
static const MemoryRegionOps loongarch_ipi64_ops = {
- .write = loongarch_ipi_writeq,
+ .write_with_attrs = loongarch_ipi_writeq,
.impl.min_access_size = 8,
.impl.max_access_size = 8,
.valid.min_access_size = 8,
@@ -253,7 +271,7 @@ static void loongarch_ipi_init(Object *obj)
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
memory_region_init_io(&s->ipi_iocsr_mem, obj, &loongarch_ipi_ops,
- &s->ipi_core, "loongarch_ipi_iocsr", 0x48);
+ s, "loongarch_ipi_iocsr", 0x48);
/* loongarch_ipi_iocsr performs re-entrant IO through ipi_send */
s->ipi_iocsr_mem.disable_reentrancy_guard = true;
@@ -261,7 +279,7 @@ static void loongarch_ipi_init(Object *obj)
sysbus_init_mmio(sbd, &s->ipi_iocsr_mem);
memory_region_init_io(&s->ipi64_iocsr_mem, obj, &loongarch_ipi64_ops,
- &s->ipi_core, "loongarch_ipi64_iocsr", 0x118);
+ s, "loongarch_ipi64_iocsr", 0x118);
sysbus_init_mmio(sbd, &s->ipi64_iocsr_mem);
qdev_init_gpio_out(DEVICE(obj), &s->ipi_core.irq, 1);
}
--
2.27.0

View File

@ -0,0 +1,39 @@
From 70e7ffec16e91138309ad3f76588cbd10c084394 Mon Sep 17 00:00:00 2001
From: Bibo Mao <maobibo@loongson.cn>
Date: Mon, 27 Nov 2023 12:02:31 +0800
Subject: [PATCH] hw/loongarch/virt: Align high memory base address with super
page size
With LoongArch virt machine, there is low memory space with region
0--0x10000000, and high memory space with started from 0x90000000.
High memory space is aligned with 256M, it will be better if it is
aligned with 1G, which is super page aligned for 4K page size.
Currently linux kernel and uefi bios has no limitation with high
memory base address, it is ok to set high memory base address
with 0x80000000.
Signed-off-by: Bibo Mao <maobibo@loongson.cn>
Reviewed-by: Song Gao <gaosong@loongson.cn>
Message-Id: <20231127040231.4123715-1-maobibo@loongson.cn>
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
include/hw/loongarch/virt.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/hw/loongarch/virt.h b/include/hw/loongarch/virt.h
index 674f4655e0..db0831b471 100644
--- a/include/hw/loongarch/virt.h
+++ b/include/hw/loongarch/virt.h
@@ -25,7 +25,7 @@
#define VIRT_LOWMEM_BASE 0
#define VIRT_LOWMEM_SIZE 0x10000000
-#define VIRT_HIGHMEM_BASE 0x90000000
+#define VIRT_HIGHMEM_BASE 0x80000000
#define VIRT_GED_EVT_ADDR 0x100e0000
#define VIRT_GED_MEM_ADDR (VIRT_GED_EVT_ADDR + ACPI_GED_EVT_SEL_LEN)
#define VIRT_GED_REG_ADDR (VIRT_GED_MEM_ADDR + MEMORY_HOTPLUG_IO_LEN)
--
2.27.0

View File

@ -0,0 +1,558 @@
From 43100bba2bfd9de0c3bab7c3e815b02faa69242d Mon Sep 17 00:00:00 2001
From: Bibo Mao <maobibo@loongson.cn>
Date: Wed, 13 Dec 2023 12:13:14 +0800
Subject: [PATCH] hw/loongarch/virt: Set iocsr address space per-board rather
than percpu
LoongArch system has iocsr address space, most iocsr registers are
per-board, however some iocsr register spaces banked for percpu such
as ipi mailbox and extioi interrupt status. For banked iocsr space,
each cpu has the same iocsr space, but separate data.
This patch changes iocsr address space per-board rather percpu,
for iocsr registers specified for cpu, MemTxAttrs.requester_id
can be parsed for the cpu. With this patches, the total address space
on board will be simple, only iocsr address space and system memory,
rather than the number of cpu and system memory.
confict:
+<<<<<<< HEAD
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_STRUCT(ipi_core, LoongArchIPI, 0, vmstate_ipi_core, IPICore),
++=======
+ .version_id = 2,
+ .minimum_version_id = 2,
+ .fields = (const VMStateField[]) {
+ VMSTATE_STRUCT_VARRAY_POINTER_UINT32(cpu, LoongArchIPI, num_cpu,
+ vmstate_ipi_core, IPICore),
++>>>>>>> hw/loongarch/virt: Set iocsr address space per-board rather than percpu
solve:
save: hw/loongarch/virt: Set iocsr address space per-board rather than percpu
Signed-off-by: Bibo Mao <maobibo@loongson.cn>
Reviewed-by: Song Gao <gaosong@loongson.cn>
Message-Id: <20231215100333.3933632-3-maobibo@loongson.cn>
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
hw/intc/loongarch_extioi.c | 3 -
hw/intc/loongarch_ipi.c | 63 +++++++++++++++-----
hw/loongarch/virt.c | 91 +++++++++++++++++++++--------
include/hw/intc/loongarch_extioi.h | 1 -
include/hw/intc/loongarch_ipi.h | 3 +-
include/hw/loongarch/virt.h | 3 +
target/loongarch/cpu.c | 48 ---------------
target/loongarch/cpu.h | 4 +-
target/loongarch/kvm/kvm.c | 2 +-
target/loongarch/tcg/iocsr_helper.c | 16 ++---
10 files changed, 129 insertions(+), 105 deletions(-)
diff --git a/hw/intc/loongarch_extioi.c b/hw/intc/loongarch_extioi.c
index 24fb3af8cc..77b4776958 100644
--- a/hw/intc/loongarch_extioi.c
+++ b/hw/intc/loongarch_extioi.c
@@ -282,9 +282,6 @@ static void loongarch_extioi_instance_init(Object *obj)
qdev_init_gpio_in(DEVICE(obj), extioi_setirq, EXTIOI_IRQS);
for (cpu = 0; cpu < EXTIOI_CPUS; cpu++) {
- memory_region_init_io(&s->extioi_iocsr_mem[cpu], OBJECT(s), &extioi_ops,
- s, "extioi_iocsr", 0x900);
- sysbus_init_mmio(dev, &s->extioi_iocsr_mem[cpu]);
for (pin = 0; pin < LS3A_INTC_IP; pin++) {
qdev_init_gpio_out(DEVICE(obj), &s->parent_irq[cpu][pin], 1);
}
diff --git a/hw/intc/loongarch_ipi.c b/hw/intc/loongarch_ipi.c
index 221246c5cb..e228669aa5 100644
--- a/hw/intc/loongarch_ipi.c
+++ b/hw/intc/loongarch_ipi.c
@@ -9,6 +9,7 @@
#include "hw/sysbus.h"
#include "hw/intc/loongarch_ipi.h"
#include "hw/irq.h"
+#include "hw/qdev-properties.h"
#include "qapi/error.h"
#include "qemu/log.h"
#include "exec/address-spaces.h"
@@ -26,7 +27,7 @@ static MemTxResult loongarch_ipi_readl(void *opaque, hwaddr addr,
uint64_t ret = 0;
int index = 0;
- s = &ipi->ipi_core;
+ s = &ipi->cpu[attrs.requester_id];
addr &= 0xff;
switch (addr) {
case CORE_STATUS_OFF:
@@ -65,7 +66,7 @@ static void send_ipi_data(CPULoongArchState *env, uint64_t val, hwaddr addr,
* if the mask is 0, we need not to do anything.
*/
if ((val >> 27) & 0xf) {
- data = address_space_ldl(&env->address_space_iocsr, addr,
+ data = address_space_ldl(env->address_space_iocsr, addr,
attrs, NULL);
for (i = 0; i < 4; i++) {
/* get mask for byte writing */
@@ -77,7 +78,7 @@ static void send_ipi_data(CPULoongArchState *env, uint64_t val, hwaddr addr,
data &= mask;
data |= (val >> 32) & ~mask;
- address_space_stl(&env->address_space_iocsr, addr,
+ address_space_stl(env->address_space_iocsr, addr,
data, attrs, NULL);
}
@@ -172,7 +173,7 @@ static MemTxResult loongarch_ipi_writel(void *opaque, hwaddr addr, uint64_t val,
uint8_t vector;
CPUState *cs;
- s = &ipi->ipi_core;
+ s = &ipi->cpu[attrs.requester_id];
addr &= 0xff;
trace_loongarch_ipi_write(size, (uint64_t)addr, val);
switch (addr) {
@@ -214,7 +215,6 @@ static MemTxResult loongarch_ipi_writel(void *opaque, hwaddr addr, uint64_t val,
/* override requester_id */
attrs.requester_id = cs->cpu_index;
- ipi = LOONGARCH_IPI(LOONGARCH_CPU(cs)->env.ipistate);
loongarch_ipi_writel(ipi, CORE_SET_OFF, BIT(vector), 4, attrs);
break;
default:
@@ -265,12 +265,18 @@ static const MemoryRegionOps loongarch_ipi64_ops = {
.endianness = DEVICE_LITTLE_ENDIAN,
};
-static void loongarch_ipi_init(Object *obj)
+static void loongarch_ipi_realize(DeviceState *dev, Error **errp)
{
- LoongArchIPI *s = LOONGARCH_IPI(obj);
- SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+ LoongArchIPI *s = LOONGARCH_IPI(dev);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+ int i;
+
+ if (s->num_cpu == 0) {
+ error_setg(errp, "num-cpu must be at least 1");
+ return;
+ }
- memory_region_init_io(&s->ipi_iocsr_mem, obj, &loongarch_ipi_ops,
+ memory_region_init_io(&s->ipi_iocsr_mem, OBJECT(dev), &loongarch_ipi_ops,
s, "loongarch_ipi_iocsr", 0x48);
/* loongarch_ipi_iocsr performs re-entrant IO through ipi_send */
@@ -278,10 +284,20 @@ static void loongarch_ipi_init(Object *obj)
sysbus_init_mmio(sbd, &s->ipi_iocsr_mem);
- memory_region_init_io(&s->ipi64_iocsr_mem, obj, &loongarch_ipi64_ops,
+ memory_region_init_io(&s->ipi64_iocsr_mem, OBJECT(dev),
+ &loongarch_ipi64_ops,
s, "loongarch_ipi64_iocsr", 0x118);
sysbus_init_mmio(sbd, &s->ipi64_iocsr_mem);
- qdev_init_gpio_out(DEVICE(obj), &s->ipi_core.irq, 1);
+
+ s->cpu = g_new0(IPICore, s->num_cpu);
+ if (s->cpu == NULL) {
+ error_setg(errp, "Memory allocation for ExtIOICore faile");
+ return;
+ }
+
+ for (i = 0; i < s->num_cpu; i++) {
+ qdev_init_gpio_out(dev, &s->cpu[i].irq, 1);
+ }
}
static const VMStateDescription vmstate_ipi_core = {
@@ -300,27 +316,42 @@ static const VMStateDescription vmstate_ipi_core = {
static const VMStateDescription vmstate_loongarch_ipi = {
.name = TYPE_LOONGARCH_IPI,
- .version_id = 1,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_STRUCT(ipi_core, LoongArchIPI, 0, vmstate_ipi_core, IPICore),
+ .version_id = 2,
+ .minimum_version_id = 2,
+ .fields = (const VMStateField[]) {
+ VMSTATE_STRUCT_VARRAY_POINTER_UINT32(cpu, LoongArchIPI, num_cpu,
+ vmstate_ipi_core, IPICore),
VMSTATE_END_OF_LIST()
}
};
+static Property ipi_properties[] = {
+ DEFINE_PROP_UINT32("num-cpu", LoongArchIPI, num_cpu, 1),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
static void loongarch_ipi_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
+ dc->realize = loongarch_ipi_realize;
+ device_class_set_props(dc, ipi_properties);
dc->vmsd = &vmstate_loongarch_ipi;
}
+static void loongarch_ipi_finalize(Object *obj)
+{
+ LoongArchIPI *s = LOONGARCH_IPI(obj);
+
+ g_free(s->cpu);
+}
+
static const TypeInfo loongarch_ipi_info = {
.name = TYPE_LOONGARCH_IPI,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(LoongArchIPI),
- .instance_init = loongarch_ipi_init,
.class_init = loongarch_ipi_class_init,
+ .instance_finalize = loongarch_ipi_finalize,
};
static void loongarch_ipi_register_types(void)
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index 4b7dc67a2d..13d19b6da3 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -535,9 +535,6 @@ static void loongarch_irq_init(LoongArchMachineState *lams)
CPUState *cpu_state;
int cpu, pin, i, start, num;
- extioi = qdev_new(TYPE_LOONGARCH_EXTIOI);
- sysbus_realize_and_unref(SYS_BUS_DEVICE(extioi), &error_fatal);
-
/*
* The connection of interrupts:
* +-----+ +---------+ +-------+
@@ -559,36 +556,36 @@ static void loongarch_irq_init(LoongArchMachineState *lams)
* | UARTs | | Devices | | Devices |
* +--------+ +---------+ +---------+
*/
+
+ /* Create IPI device */
+ ipi = qdev_new(TYPE_LOONGARCH_IPI);
+ qdev_prop_set_uint32(ipi, "num-cpu", ms->smp.cpus);
+ sysbus_realize_and_unref(SYS_BUS_DEVICE(ipi), &error_fatal);
+
+ /* IPI iocsr memory region */
+ memory_region_add_subregion(&lams->system_iocsr, SMP_IPI_MAILBOX,
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(ipi), 0));
+ memory_region_add_subregion(&lams->system_iocsr, MAIL_SEND_ADDR,
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(ipi), 1));
+
for (cpu = 0; cpu < ms->smp.cpus; cpu++) {
cpu_state = qemu_get_cpu(cpu);
cpudev = DEVICE(cpu_state);
lacpu = LOONGARCH_CPU(cpu_state);
env = &(lacpu->env);
-
- ipi = qdev_new(TYPE_LOONGARCH_IPI);
- sysbus_realize_and_unref(SYS_BUS_DEVICE(ipi), &error_fatal);
+ env->address_space_iocsr = &lams->as_iocsr;
/* connect ipi irq to cpu irq */
- qdev_connect_gpio_out(ipi, 0, qdev_get_gpio_in(cpudev, IRQ_IPI));
- /* IPI iocsr memory region */
- memory_region_add_subregion(&env->system_iocsr, SMP_IPI_MAILBOX,
- sysbus_mmio_get_region(SYS_BUS_DEVICE(ipi),
- 0));
- memory_region_add_subregion(&env->system_iocsr, MAIL_SEND_ADDR,
- sysbus_mmio_get_region(SYS_BUS_DEVICE(ipi),
- 1));
- /*
- * extioi iocsr memory region
- * only one extioi is added on loongarch virt machine
- * external device interrupt can only be routed to cpu 0-3
- */
- if (cpu < EXTIOI_CPUS)
- memory_region_add_subregion(&env->system_iocsr, APIC_BASE,
- sysbus_mmio_get_region(SYS_BUS_DEVICE(extioi),
- cpu));
+ qdev_connect_gpio_out(ipi, cpu, qdev_get_gpio_in(cpudev, IRQ_IPI));
env->ipistate = ipi;
}
+ /* Create EXTIOI device */
+ extioi = qdev_new(TYPE_LOONGARCH_EXTIOI);
+ 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));
+
/*
* connect ext irq to the cpu irq
* cpu_pin[9:2] <= intc_pin[7:0]
@@ -733,6 +730,43 @@ static void loongarch_direct_kernel_boot(LoongArchMachineState *lams,
}
}
+static void loongarch_qemu_write(void *opaque, hwaddr addr,
+ uint64_t val, unsigned size)
+{
+}
+
+static uint64_t loongarch_qemu_read(void *opaque, hwaddr addr, unsigned size)
+{
+ switch (addr) {
+ case VERSION_REG:
+ return 0x11ULL;
+ case FEATURE_REG:
+ return 1ULL << IOCSRF_MSI | 1ULL << IOCSRF_EXTIOI |
+ 1ULL << IOCSRF_CSRIPI;
+ case VENDOR_REG:
+ return 0x6e6f73676e6f6f4cULL; /* "Loongson" */
+ case CPUNAME_REG:
+ return 0x303030354133ULL; /* "3A5000" */
+ case MISC_FUNC_REG:
+ return 1ULL << IOCSRM_EXTIOI_EN;
+ }
+ return 0ULL;
+}
+
+static const MemoryRegionOps loongarch_qemu_ops = {
+ .read = loongarch_qemu_read,
+ .write = loongarch_qemu_write,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+ .valid = {
+ .min_access_size = 4,
+ .max_access_size = 8,
+ },
+ .impl = {
+ .min_access_size = 8,
+ .max_access_size = 8,
+ },
+};
+
static void loongarch_init(MachineState *machine)
{
LoongArchCPU *lacpu;
@@ -761,8 +795,17 @@ static void loongarch_init(MachineState *machine)
exit(1);
}
create_fdt(lams);
- /* Init CPUs */
+ /* Create IOCSR space */
+ memory_region_init_io(&lams->system_iocsr, OBJECT(machine), NULL,
+ machine, "iocsr", UINT64_MAX);
+ address_space_init(&lams->as_iocsr, &lams->system_iocsr, "IOCSR");
+ memory_region_init_io(&lams->iocsr_mem, OBJECT(machine),
+ &loongarch_qemu_ops,
+ machine, "iocsr_misc", 0x428);
+ memory_region_add_subregion(&lams->system_iocsr, 0, &lams->iocsr_mem);
+
+ /* Init CPUs */
possible_cpus = mc->possible_cpu_arch_ids(machine);
for (i = 0; i < possible_cpus->len; i++) {
cpu = cpu_create(machine->cpu_type);
diff --git a/include/hw/intc/loongarch_extioi.h b/include/hw/intc/loongarch_extioi.h
index fbdef9a7b3..110e5e8873 100644
--- a/include/hw/intc/loongarch_extioi.h
+++ b/include/hw/intc/loongarch_extioi.h
@@ -58,7 +58,6 @@ struct LoongArchExtIOI {
uint8_t sw_coremap[EXTIOI_IRQS];
qemu_irq parent_irq[EXTIOI_CPUS][LS3A_INTC_IP];
qemu_irq irq[EXTIOI_IRQS];
- MemoryRegion extioi_iocsr_mem[EXTIOI_CPUS];
MemoryRegion extioi_system_mem;
};
#endif /* LOONGARCH_EXTIOI_H */
diff --git a/include/hw/intc/loongarch_ipi.h b/include/hw/intc/loongarch_ipi.h
index 6c6194786e..1c1e834849 100644
--- a/include/hw/intc/loongarch_ipi.h
+++ b/include/hw/intc/loongarch_ipi.h
@@ -47,7 +47,8 @@ struct LoongArchIPI {
SysBusDevice parent_obj;
MemoryRegion ipi_iocsr_mem;
MemoryRegion ipi64_iocsr_mem;
- IPICore ipi_core;
+ uint32_t num_cpu;
+ IPICore *cpu;
};
#endif
diff --git a/include/hw/loongarch/virt.h b/include/hw/loongarch/virt.h
index db0831b471..6ef9a92394 100644
--- a/include/hw/loongarch/virt.h
+++ b/include/hw/loongarch/virt.h
@@ -50,6 +50,9 @@ struct LoongArchMachineState {
DeviceState *platform_bus_dev;
PCIBus *pci_bus;
PFlashCFI01 *flash;
+ MemoryRegion system_iocsr;
+ MemoryRegion iocsr_mem;
+ AddressSpace as_iocsr;
};
#define TYPE_LOONGARCH_MACHINE MACHINE_TYPE_NAME("virt")
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index 413414392b..6611d137a1 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -602,47 +602,6 @@ static void loongarch_cpu_realizefn(DeviceState *dev, Error **errp)
lacc->parent_realize(dev, errp);
}
-#ifndef CONFIG_USER_ONLY
-static void loongarch_qemu_write(void *opaque, hwaddr addr,
- uint64_t val, unsigned size)
-{
- qemu_log_mask(LOG_UNIMP, "[%s]: Unimplemented reg 0x%" HWADDR_PRIx "\n",
- __func__, addr);
-}
-
-static uint64_t loongarch_qemu_read(void *opaque, hwaddr addr, unsigned size)
-{
- switch (addr) {
- case VERSION_REG:
- return 0x11ULL;
- case FEATURE_REG:
- return 1ULL << IOCSRF_MSI | 1ULL << IOCSRF_EXTIOI |
- 1ULL << IOCSRF_CSRIPI;
- case VENDOR_REG:
- return 0x6e6f73676e6f6f4cULL; /* "Loongson" */
- case CPUNAME_REG:
- return 0x303030354133ULL; /* "3A5000" */
- case MISC_FUNC_REG:
- return 1ULL << IOCSRM_EXTIOI_EN;
- }
- return 0ULL;
-}
-
-static const MemoryRegionOps loongarch_qemu_ops = {
- .read = loongarch_qemu_read,
- .write = loongarch_qemu_write,
- .endianness = DEVICE_LITTLE_ENDIAN,
- .valid = {
- .min_access_size = 4,
- .max_access_size = 8,
- },
- .impl = {
- .min_access_size = 8,
- .max_access_size = 8,
- },
-};
-#endif
-
static bool loongarch_get_lsx(Object *obj, Error **errp)
{
LoongArchCPU *cpu = LOONGARCH_CPU(obj);
@@ -713,19 +672,12 @@ static void loongarch_cpu_init(Object *obj)
{
#ifndef CONFIG_USER_ONLY
LoongArchCPU *cpu = LOONGARCH_CPU(obj);
- CPULoongArchState *env = &cpu->env;
qdev_init_gpio_in(DEVICE(cpu), loongarch_cpu_set_irq, N_IRQS);
#ifdef CONFIG_TCG
timer_init_ns(&cpu->timer, QEMU_CLOCK_VIRTUAL,
&loongarch_constant_timer_cb, cpu);
#endif
- memory_region_init_io(&env->system_iocsr, OBJECT(cpu), NULL,
- env, "iocsr", UINT64_MAX);
- address_space_init(&env->address_space_iocsr, &env->system_iocsr, "IOCSR");
- memory_region_init_io(&env->iocsr_mem, OBJECT(cpu), &loongarch_qemu_ops,
- NULL, "iocsr_misc", 0x428);
- memory_region_add_subregion(&env->system_iocsr, 0, &env->iocsr_mem);
#endif
}
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index 8ebd6fa1a7..4aba8aba4c 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -355,9 +355,7 @@ typedef struct CPUArchState {
#ifndef CONFIG_USER_ONLY
LoongArchTLB tlb[LOONGARCH_TLB_MAX];
- AddressSpace address_space_iocsr;
- MemoryRegion system_iocsr;
- MemoryRegion iocsr_mem;
+ AddressSpace *address_space_iocsr;
bool load_elf;
uint64_t elf_address;
uint32_t mp_state;
diff --git a/target/loongarch/kvm/kvm.c b/target/loongarch/kvm/kvm.c
index bd33ec2114..84bcdf5f86 100644
--- a/target/loongarch/kvm/kvm.c
+++ b/target/loongarch/kvm/kvm.c
@@ -733,7 +733,7 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
trace_kvm_arch_handle_exit(run->exit_reason);
switch (run->exit_reason) {
case KVM_EXIT_LOONGARCH_IOCSR:
- address_space_rw(&env->address_space_iocsr,
+ address_space_rw(env->address_space_iocsr,
run->iocsr_io.phys_addr,
attrs,
run->iocsr_io.data,
diff --git a/target/loongarch/tcg/iocsr_helper.c b/target/loongarch/tcg/iocsr_helper.c
index 6cd01d5f09..b6916f53d2 100644
--- a/target/loongarch/tcg/iocsr_helper.c
+++ b/target/loongarch/tcg/iocsr_helper.c
@@ -17,52 +17,52 @@
uint64_t helper_iocsrrd_b(CPULoongArchState *env, target_ulong r_addr)
{
- return address_space_ldub(&env->address_space_iocsr, r_addr,
+ return address_space_ldub(env->address_space_iocsr, r_addr,
GET_MEMTXATTRS(env), NULL);
}
uint64_t helper_iocsrrd_h(CPULoongArchState *env, target_ulong r_addr)
{
- return address_space_lduw(&env->address_space_iocsr, r_addr,
+ return address_space_lduw(env->address_space_iocsr, r_addr,
GET_MEMTXATTRS(env), NULL);
}
uint64_t helper_iocsrrd_w(CPULoongArchState *env, target_ulong r_addr)
{
- return address_space_ldl(&env->address_space_iocsr, r_addr,
+ return address_space_ldl(env->address_space_iocsr, r_addr,
GET_MEMTXATTRS(env), NULL);
}
uint64_t helper_iocsrrd_d(CPULoongArchState *env, target_ulong r_addr)
{
- return address_space_ldq(&env->address_space_iocsr, r_addr,
+ return address_space_ldq(env->address_space_iocsr, r_addr,
GET_MEMTXATTRS(env), NULL);
}
void helper_iocsrwr_b(CPULoongArchState *env, target_ulong w_addr,
target_ulong val)
{
- address_space_stb(&env->address_space_iocsr, w_addr,
+ address_space_stb(env->address_space_iocsr, w_addr,
val, GET_MEMTXATTRS(env), NULL);
}
void helper_iocsrwr_h(CPULoongArchState *env, target_ulong w_addr,
target_ulong val)
{
- address_space_stw(&env->address_space_iocsr, w_addr,
+ address_space_stw(env->address_space_iocsr, w_addr,
val, GET_MEMTXATTRS(env), NULL);
}
void helper_iocsrwr_w(CPULoongArchState *env, target_ulong w_addr,
target_ulong val)
{
- address_space_stl(&env->address_space_iocsr, w_addr,
+ address_space_stl(env->address_space_iocsr, w_addr,
val, GET_MEMTXATTRS(env), NULL);
}
void helper_iocsrwr_d(CPULoongArchState *env, target_ulong w_addr,
target_ulong val)
{
- address_space_stq(&env->address_space_iocsr, w_addr,
+ address_space_stq(env->address_space_iocsr, w_addr,
val, GET_MEMTXATTRS(env), NULL);
}
--
2.27.0

View File

@ -0,0 +1,57 @@
From 280cba84e3eaed10f095f0c88dab27b7799558e5 Mon Sep 17 00:00:00 2001
From: Tianrui Zhao <zhaotianrui@loongson.cn>
Date: Fri, 5 Jan 2024 15:57:56 +0800
Subject: [PATCH] linux-headers: Synchronize linux headers from linux
v6.7.0-rc8
Use the scripts/update-linux-headers.sh to synchronize linux
headers from linux v6.7.0-rc8. We mainly want to add the
loongarch linux headers and then add the loongarch kvm support
based on it.
Signed-off-by: Tianrui Zhao <zhaotianrui@loongson.cn>
Acked-by: Song Gao <gaosong@loongson.cn>
Message-Id: <20240105075804.1228596-2-zhaotianrui@loongson.cn>
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
include/standard-headers/linux/fuse.h | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/include/standard-headers/linux/fuse.h b/include/standard-headers/linux/fuse.h
index 6b9793842c..fc0dcd10ae 100644
--- a/include/standard-headers/linux/fuse.h
+++ b/include/standard-headers/linux/fuse.h
@@ -209,7 +209,7 @@
* - add FUSE_HAS_EXPIRE_ONLY
*
* 7.39
- * - add FUSE_DIRECT_IO_RELAX
+ * - add FUSE_DIRECT_IO_ALLOW_MMAP
* - add FUSE_STATX and related structures
*/
@@ -405,8 +405,7 @@ struct fuse_file_lock {
* FUSE_CREATE_SUPP_GROUP: add supplementary group info to create, mkdir,
* symlink and mknod (single group that matches parent)
* FUSE_HAS_EXPIRE_ONLY: kernel supports expiry-only entry invalidation
- * FUSE_DIRECT_IO_RELAX: relax restrictions in FOPEN_DIRECT_IO mode, for now
- * allow shared mmap
+ * FUSE_DIRECT_IO_ALLOW_MMAP: allow shared mmap in FOPEN_DIRECT_IO mode.
*/
#define FUSE_ASYNC_READ (1 << 0)
#define FUSE_POSIX_LOCKS (1 << 1)
@@ -445,7 +444,10 @@ struct fuse_file_lock {
#define FUSE_HAS_INODE_DAX (1ULL << 33)
#define FUSE_CREATE_SUPP_GROUP (1ULL << 34)
#define FUSE_HAS_EXPIRE_ONLY (1ULL << 35)
-#define FUSE_DIRECT_IO_RELAX (1ULL << 36)
+#define FUSE_DIRECT_IO_ALLOW_MMAP (1ULL << 36)
+
+/* Obsolete alias for FUSE_DIRECT_IO_ALLOW_MMAP */
+#define FUSE_DIRECT_IO_RELAX FUSE_DIRECT_IO_ALLOW_MMAP
/**
* CUSE INIT request/reply flags
--
2.27.0

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,287 @@
From 4a5a9bef6eff5837dcccd216172957d8470b6245 Mon Sep 17 00:00:00 2001
From: Xianglai Li <lixianglai@loongson.cn>
Date: Mon, 19 Feb 2024 18:34:14 +0800
Subject: [PATCH] loongarch: Change the UEFI loading mode to loongarch
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The UEFI loading mode in loongarch is very different
from that in other architectures:loongarch's UEFI code
is in rom, while other architectures' UEFI code is in flash.
loongarch UEFI can be loaded as follows:
-machine virt,pflash=pflash0-format
-bios ./QEMU_EFI.fd
Other architectures load UEFI using the following methods:
-machine virt,pflash0=pflash0-format,pflash1=pflash1-format
loongarch's UEFI loading method makes qemu and libvirt incompatible
when using NVRAM, and the cost of loongarch's current loading method
far outweighs the benefits, so we decided to use the same UEFI loading
scheme as other architectures.
Cc: Andrea Bolognani <abologna@redhat.com>
Cc: maobibo@loongson.cn
Cc: Philippe Mathieu-Daudé <philmd@linaro.org>
Cc: Song Gao <gaosong@loongson.cn>
Cc: zhaotianrui@loongson.cn
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
Tested-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Song Gao <gaosong@loongson.cn>
Message-Id: <0bd892aa9b88e0f4cc904cb70efd0251fc1cde29.1708336919.git.lixianglai@loongson.cn>
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
hw/loongarch/acpi-build.c | 29 +++++++++--
hw/loongarch/virt.c | 101 ++++++++++++++++++++++++++----------
include/hw/loongarch/virt.h | 10 ++--
3 files changed, 107 insertions(+), 33 deletions(-)
diff --git a/hw/loongarch/acpi-build.c b/hw/loongarch/acpi-build.c
index ae292fc543..f990405d04 100644
--- a/hw/loongarch/acpi-build.c
+++ b/hw/loongarch/acpi-build.c
@@ -314,16 +314,39 @@ static void build_pci_device_aml(Aml *scope, LoongArchMachineState *lams)
static void build_flash_aml(Aml *scope, LoongArchMachineState *lams)
{
Aml *dev, *crs;
+ MemoryRegion *flash_mem;
- hwaddr flash_base = VIRT_FLASH_BASE;
- hwaddr flash_size = VIRT_FLASH_SIZE;
+ hwaddr flash0_base;
+ hwaddr flash0_size;
+
+ hwaddr flash1_base;
+ hwaddr flash1_size;
+
+ flash_mem = pflash_cfi01_get_memory(lams->flash[0]);
+ flash0_base = flash_mem->addr;
+ flash0_size = memory_region_size(flash_mem);
+
+ flash_mem = pflash_cfi01_get_memory(lams->flash[1]);
+ flash1_base = flash_mem->addr;
+ flash1_size = memory_region_size(flash_mem);
dev = aml_device("FLS0");
aml_append(dev, aml_name_decl("_HID", aml_string("LNRO0015")));
aml_append(dev, aml_name_decl("_UID", aml_int(0)));
crs = aml_resource_template();
- aml_append(crs, aml_memory32_fixed(flash_base, flash_size, AML_READ_WRITE));
+ aml_append(crs, aml_memory32_fixed(flash0_base, flash0_size,
+ AML_READ_WRITE));
+ aml_append(dev, aml_name_decl("_CRS", crs));
+ aml_append(scope, dev);
+
+ dev = aml_device("FLS1");
+ aml_append(dev, aml_name_decl("_HID", aml_string("LNRO0015")));
+ aml_append(dev, aml_name_decl("_UID", aml_int(1)));
+
+ crs = aml_resource_template();
+ aml_append(crs, aml_memory32_fixed(flash1_base, flash1_size,
+ AML_READ_WRITE));
aml_append(dev, aml_name_decl("_CRS", crs));
aml_append(scope, dev);
}
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index c9a680e61a..6ef40fa24a 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -54,7 +54,9 @@ struct loaderparams {
const char *initrd_filename;
};
-static void virt_flash_create(LoongArchMachineState *lams)
+static PFlashCFI01 *virt_flash_create1(LoongArchMachineState *lams,
+ const char *name,
+ const char *alias_prop_name)
{
DeviceState *dev = qdev_new(TYPE_PFLASH_CFI01);
@@ -66,45 +68,78 @@ static void virt_flash_create(LoongArchMachineState *lams)
qdev_prop_set_uint16(dev, "id1", 0x18);
qdev_prop_set_uint16(dev, "id2", 0x00);
qdev_prop_set_uint16(dev, "id3", 0x00);
- qdev_prop_set_string(dev, "name", "virt.flash");
- object_property_add_child(OBJECT(lams), "virt.flash", OBJECT(dev));
- object_property_add_alias(OBJECT(lams), "pflash",
+ qdev_prop_set_string(dev, "name", name);
+ object_property_add_child(OBJECT(lams), name, OBJECT(dev));
+ object_property_add_alias(OBJECT(lams), alias_prop_name,
OBJECT(dev), "drive");
+ return PFLASH_CFI01(dev);
+}
- lams->flash = PFLASH_CFI01(dev);
+static void virt_flash_create(LoongArchMachineState *lams)
+{
+ lams->flash[0] = virt_flash_create1(lams, "virt.flash0", "pflash0");
+ lams->flash[1] = virt_flash_create1(lams, "virt.flash1", "pflash1");
}
-static void virt_flash_map(LoongArchMachineState *lams,
- MemoryRegion *sysmem)
+static void virt_flash_map1(PFlashCFI01 *flash,
+ hwaddr base, hwaddr size,
+ MemoryRegion *sysmem)
{
- PFlashCFI01 *flash = lams->flash;
DeviceState *dev = DEVICE(flash);
- hwaddr base = VIRT_FLASH_BASE;
- hwaddr size = VIRT_FLASH_SIZE;
+ BlockBackend *blk;
+ hwaddr real_size = size;
+
+ blk = pflash_cfi01_get_blk(flash);
+ if (blk) {
+ real_size = blk_getlength(blk);
+ assert(real_size && real_size <= size);
+ }
- assert(QEMU_IS_ALIGNED(size, VIRT_FLASH_SECTOR_SIZE));
- assert(size / VIRT_FLASH_SECTOR_SIZE <= UINT32_MAX);
+ assert(QEMU_IS_ALIGNED(real_size, VIRT_FLASH_SECTOR_SIZE));
+ assert(real_size / VIRT_FLASH_SECTOR_SIZE <= UINT32_MAX);
- qdev_prop_set_uint32(dev, "num-blocks", size / VIRT_FLASH_SECTOR_SIZE);
+ qdev_prop_set_uint32(dev, "num-blocks", real_size / VIRT_FLASH_SECTOR_SIZE);
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
memory_region_add_subregion(sysmem, base,
sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0));
+}
+static void virt_flash_map(LoongArchMachineState *lams,
+ MemoryRegion *sysmem)
+{
+ PFlashCFI01 *flash0 = lams->flash[0];
+ PFlashCFI01 *flash1 = lams->flash[1];
+
+ virt_flash_map1(flash0, VIRT_FLASH0_BASE, VIRT_FLASH0_SIZE, sysmem);
+ virt_flash_map1(flash1, VIRT_FLASH1_BASE, VIRT_FLASH1_SIZE, sysmem);
}
static void fdt_add_flash_node(LoongArchMachineState *lams)
{
MachineState *ms = MACHINE(lams);
char *nodename;
+ MemoryRegion *flash_mem;
+
+ hwaddr flash0_base;
+ hwaddr flash0_size;
- hwaddr flash_base = VIRT_FLASH_BASE;
- hwaddr flash_size = VIRT_FLASH_SIZE;
+ hwaddr flash1_base;
+ hwaddr flash1_size;
- nodename = g_strdup_printf("/flash@%" PRIx64, flash_base);
+ flash_mem = pflash_cfi01_get_memory(lams->flash[0]);
+ flash0_base = flash_mem->addr;
+ flash0_size = memory_region_size(flash_mem);
+
+ flash_mem = pflash_cfi01_get_memory(lams->flash[1]);
+ flash1_base = flash_mem->addr;
+ flash1_size = memory_region_size(flash_mem);
+
+ nodename = g_strdup_printf("/flash@%" PRIx64, flash0_base);
qemu_fdt_add_subnode(ms->fdt, nodename);
qemu_fdt_setprop_string(ms->fdt, nodename, "compatible", "cfi-flash");
qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "reg",
- 2, flash_base, 2, flash_size);
+ 2, flash0_base, 2, flash0_size,
+ 2, flash1_base, 2, flash1_size);
qemu_fdt_setprop_cell(ms->fdt, nodename, "bank-width", 4);
g_free(nodename);
}
@@ -639,12 +674,32 @@ static void loongarch_firmware_init(LoongArchMachineState *lams)
{
char *filename = MACHINE(lams)->firmware;
char *bios_name = NULL;
- int bios_size;
+ int bios_size, i;
+ BlockBackend *pflash_blk0;
+ MemoryRegion *mr;
lams->bios_loaded = false;
+ /* Map legacy -drive if=pflash to machine properties */
+ for (i = 0; i < ARRAY_SIZE(lams->flash); i++) {
+ pflash_cfi01_legacy_drive(lams->flash[i],
+ drive_get(IF_PFLASH, 0, i));
+ }
+
virt_flash_map(lams, get_system_memory());
+ pflash_blk0 = pflash_cfi01_get_blk(lams->flash[0]);
+
+ if (pflash_blk0) {
+ if (filename) {
+ error_report("cannot use both '-bios' and '-drive if=pflash'"
+ "options at once");
+ exit(1);
+ }
+ lams->bios_loaded = true;
+ return;
+ }
+
if (filename) {
bios_name = qemu_find_file(QEMU_FILE_TYPE_BIOS, filename);
if (!bios_name) {
@@ -652,21 +707,15 @@ static void loongarch_firmware_init(LoongArchMachineState *lams)
exit(1);
}
- bios_size = load_image_targphys(bios_name, VIRT_BIOS_BASE, VIRT_BIOS_SIZE);
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(lams->flash[0]), 0);
+ bios_size = load_image_mr(bios_name, mr);
if (bios_size < 0) {
error_report("Could not load ROM image '%s'", bios_name);
exit(1);
}
-
g_free(bios_name);
-
- memory_region_init_ram(&lams->bios, NULL, "loongarch.bios",
- VIRT_BIOS_SIZE, &error_fatal);
- memory_region_set_readonly(&lams->bios, true);
- memory_region_add_subregion(get_system_memory(), VIRT_BIOS_BASE, &lams->bios);
lams->bios_loaded = true;
}
-
}
static void reset_load_elf(void *opaque)
diff --git a/include/hw/loongarch/virt.h b/include/hw/loongarch/virt.h
index 6ef9a92394..252f7df7f4 100644
--- a/include/hw/loongarch/virt.h
+++ b/include/hw/loongarch/virt.h
@@ -18,10 +18,12 @@
#define VIRT_FWCFG_BASE 0x1e020000UL
#define VIRT_BIOS_BASE 0x1c000000UL
-#define VIRT_BIOS_SIZE (4 * MiB)
+#define VIRT_BIOS_SIZE (16 * MiB)
#define VIRT_FLASH_SECTOR_SIZE (128 * KiB)
-#define VIRT_FLASH_BASE 0x1d000000UL
-#define VIRT_FLASH_SIZE (16 * MiB)
+#define VIRT_FLASH0_BASE VIRT_BIOS_BASE
+#define VIRT_FLASH0_SIZE VIRT_BIOS_SIZE
+#define VIRT_FLASH1_BASE 0x1d000000UL
+#define VIRT_FLASH1_SIZE (16 * MiB)
#define VIRT_LOWMEM_BASE 0
#define VIRT_LOWMEM_SIZE 0x10000000
@@ -49,7 +51,7 @@ struct LoongArchMachineState {
int fdt_size;
DeviceState *platform_bus_dev;
PCIBus *pci_bus;
- PFlashCFI01 *flash;
+ PFlashCFI01 *flash[2];
MemoryRegion system_iocsr;
MemoryRegion iocsr_mem;
AddressSpace as_iocsr;
--
2.27.0

View File

@ -3,7 +3,7 @@
Name: qemu
Version: 8.2.0
Release: 2
Release: 3
Epoch: 11
Summary: QEMU is a generic and open source machine emulator and virtualizer
License: GPLv2 and BSD and MIT and CC-BY-SA-4.0
@ -64,6 +64,31 @@ Patch0047: scsi-bus-fix-incorrect-call-for-blk_error_retry_rese.patch
Patch0048: block-mirror-fix-file-system-went-to-read-only-after.patch
Patch0049: block-enable-cache-mode-of-empty-cdrom.patch
Patch0050: block-bugfix-Don-t-pause-vm-when-NOSPACE-EIO-happene.patch
Patch0051: hw-loongarch-virt-Align-high-memory-base-address-wit.patch
Patch0052: target-loongarch-Add-timer-information-dump-support.patch
Patch0053: target-loongarch-meson-move-gdbstub.c-to-loongarch.s.patch
Patch0054: target-loongarch-move-translate-modules-to-tcg.patch
Patch0055: linux-headers-Update-to-Linux-v6.7-rc5.patch
Patch0056: linux-headers-Synchronize-linux-headers-from-linux-v.patch
Patch0057: target-loongarch-Define-some-kvm_arch-interfaces.patch
Patch0058: target-loongarch-Supplement-vcpu-env-initial-when-vc.patch
Patch0059: target-loongarch-Implement-kvm-get-set-registers.patch
Patch0060: target-loongarch-Implement-kvm_arch_init-function.patch
Patch0061: target-loongarch-Implement-kvm_arch_init_vcpu.patch
Patch0062: target-loongarch-Implement-kvm_arch_handle_exit.patch
Patch0063: target-loongarch-Restrict-TCG-specific-code.patch
Patch0064: target-loongarch-Implement-set-vcpu-intr-for-kvm.patch
Patch0065: target-loongarch-Add-loongarch-kvm-into-meson-build.patch
Patch0066: hw-intc-loongarch_ipi-Use-MemTxAttrs-interface-for-i.patch
Patch0067: hw-loongarch-virt-Set-iocsr-address-space-per-board-.patch
Patch0068: hw-intc-loongarch_extioi-Add-dynamic-cpu-number-supp.patch
Patch0069: hw-intc-loongarch_extioi-Add-vmstate-post_load-suppo.patch
Patch0070: configure-Add-linux-header-compile-support-for-Loong.patch
Patch0071: target-loongarch-Set-cpuid-CSR-register-only-once-wi.patch
Patch0072: target-loongarch-kvm-Enable-LSX-LASX-extension.patch
Patch0073: target-loongarch-Fix-qtest-test-hmp-error-when-KVM-o.patch
Patch0074: loongarch-Change-the-UEFI-loading-mode-to-loongarch.patch
Patch0075: disable-keyring-option.patch
BuildRequires: flex
BuildRequires: gcc
@ -661,7 +686,34 @@ getent passwd qemu >/dev/null || \
%endif
%changelog
* Sat Mar 27 2024 Jiabo Feng <fengjiabo1@huawei.com> - 11:8.2.0-2
* Wed Mar 27 2024 Jiabo Feng <fengjiabo1@huawei.com> - 11:8.2.0-3
- disable keyring option
- loongarch: Change the UEFI loading mode to loongarch
- target/loongarch: Fix qtest test-hmp error when KVM-only build
- target/loongarch/kvm: Enable LSX/LASX extension
- target/loongarch: Set cpuid CSR register only once with kvm mode
- configure: Add linux header compile support for LoongArch
- hw/intc/loongarch_extioi: Add vmstate post_load support
- hw/intc/loongarch_extioi: Add dynamic cpu number support
- hw/loongarch/virt: Set iocsr address space per-board rather than percpu
- hw/intc/loongarch_ipi: Use MemTxAttrs interface for ipi ops
- target/loongarch: Add loongarch kvm into meson build
- target/loongarch: Implement set vcpu intr for kvm
- target/loongarch: Restrict TCG-specific code
- target/loongarch: Implement kvm_arch_handle_exit
- target/loongarch: Implement kvm_arch_init_vcpu
- target/loongarch: Implement kvm_arch_init function
- target/loongarch: Implement kvm get/set registers
- target/loongarch: Supplement vcpu env initial when vcpu reset
- target/loongarch: Define some kvm_arch interfaces
- linux-headers: Synchronize linux headers from linux v6.7.0-rc8
- linux-headers: Update to Linux v6.7-rc5
- target/loongarch: move translate modules to tcg/
- target/loongarch/meson: move gdbstub.c to loongarch.ss
- target/loongarch: Add timer information dump support
- hw/loongarch/virt: Align high memory base address with super page size
* Sat Mar 23 2024 Jiabo Feng <fengjiabo1@huawei.com> - 11:8.2.0-2
- block: bugfix: Don't pause vm when NOSPACE EIO happened
- block: enable cache mode of empty cdrom
- block/mirror: fix file-system went to read-only after block-mirror

View File

@ -0,0 +1,56 @@
From 49a7ae85d6ac42f8ef556a0d42802508c28adfcc Mon Sep 17 00:00:00 2001
From: Tianrui Zhao <zhaotianrui@loongson.cn>
Date: Fri, 5 Jan 2024 15:58:04 +0800
Subject: [PATCH] target/loongarch: Add loongarch kvm into meson build
Add kvm.c into meson.build to compile it when kvm
is configed. Meanwhile in meson.build, we set the
kvm_targets to loongarch64-softmmu when the cpu is
loongarch. And fix the compiling error when config
is enable-kvm,disable-tcg.
Signed-off-by: Tianrui Zhao <zhaotianrui@loongson.cn>
Signed-off-by: xianglai li <lixianglai@loongson.cn>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Song Gao <gaosong@loongson.cn>
Message-Id: <20240105075804.1228596-10-zhaotianrui@loongson.cn>
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
meson.build | 2 ++
target/loongarch/kvm/meson.build | 1 +
target/loongarch/meson.build | 1 +
3 files changed, 4 insertions(+)
create mode 100644 target/loongarch/kvm/meson.build
diff --git a/meson.build b/meson.build
index 445f2b7c2b..0c62b4156d 100644
--- a/meson.build
+++ b/meson.build
@@ -114,6 +114,8 @@ elif cpu in ['riscv32']
kvm_targets = ['riscv32-softmmu']
elif cpu in ['riscv64']
kvm_targets = ['riscv64-softmmu']
+elif cpu in ['loongarch64']
+ kvm_targets = ['loongarch64-softmmu']
else
kvm_targets = []
endif
diff --git a/target/loongarch/kvm/meson.build b/target/loongarch/kvm/meson.build
new file mode 100644
index 0000000000..2266de6ca9
--- /dev/null
+++ b/target/loongarch/kvm/meson.build
@@ -0,0 +1 @@
+loongarch_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c'))
diff --git a/target/loongarch/meson.build b/target/loongarch/meson.build
index e84e4c51f4..db310f6022 100644
--- a/target/loongarch/meson.build
+++ b/target/loongarch/meson.build
@@ -18,3 +18,4 @@ subdir('tcg')
target_arch += {'loongarch': loongarch_ss}
target_system_arch += {'loongarch': loongarch_system_ss}
+subdir('kvm')
--
2.27.0

View File

@ -0,0 +1,33 @@
From 8a43c9379651fbf9d015240d6dc7c4b90ce98683 Mon Sep 17 00:00:00 2001
From: Bibo Mao <maobibo@loongson.cn>
Date: Wed, 6 Dec 2023 16:18:39 +0800
Subject: [PATCH] target/loongarch: Add timer information dump support
Timer emulation sometimes is problematic especially when vm is running in
kvm mode. This patch adds registers dump support relative with timer
hardware, so that it is easier to find the problems.
Signed-off-by: Bibo Mao <maobibo@loongson.cn>
Reviewed-by: Song Gao <gaosong@loongson.cn>
Message-Id: <20231206081839.2290178-1-maobibo@loongson.cn>
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
target/loongarch/cpu.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index fc075952e6..db9a421cc4 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -762,6 +762,8 @@ void loongarch_cpu_dump_state(CPUState *cs, FILE *f, int flags)
qemu_fprintf(f, "TLBRENTRY=%016" PRIx64 "\n", env->CSR_TLBRENTRY);
qemu_fprintf(f, "TLBRBADV=%016" PRIx64 "\n", env->CSR_TLBRBADV);
qemu_fprintf(f, "TLBRERA=%016" PRIx64 "\n", env->CSR_TLBRERA);
+ qemu_fprintf(f, "TCFG=%016" PRIx64 "\n", env->CSR_TCFG);
+ qemu_fprintf(f, "TVAL=%016" PRIx64 "\n", env->CSR_TVAL);
/* fpr */
if (flags & CPU_DUMP_FPU) {
--
2.27.0

View File

@ -0,0 +1,162 @@
From 623a99084843f47723cb799d4bcef8e1359d59ad Mon Sep 17 00:00:00 2001
From: Tianrui Zhao <zhaotianrui@loongson.cn>
Date: Fri, 5 Jan 2024 15:57:57 +0800
Subject: [PATCH] target/loongarch: Define some kvm_arch interfaces
Define some functions in target/loongarch/kvm/kvm.c,
such as kvm_arch_put_registers, kvm_arch_get_registers
and kvm_arch_handle_exit, etc. which are needed by
kvm/kvm-all.c. Now the most functions has no content
and they will be implemented in the next patches.
Signed-off-by: Tianrui Zhao <zhaotianrui@loongson.cn>
Signed-off-by: xianglai li <lixianglai@loongson.cn>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Song Gao <gaosong@loongson.cn>
Message-Id: <20240105075804.1228596-3-zhaotianrui@loongson.cn>
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
target/loongarch/kvm/kvm.c | 131 +++++++++++++++++++++++++++++++++++++
1 file changed, 131 insertions(+)
create mode 100644 target/loongarch/kvm/kvm.c
diff --git a/target/loongarch/kvm/kvm.c b/target/loongarch/kvm/kvm.c
new file mode 100644
index 0000000000..0d67322fd9
--- /dev/null
+++ b/target/loongarch/kvm/kvm.c
@@ -0,0 +1,131 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * QEMU LoongArch KVM
+ *
+ * Copyright (c) 2023 Loongson Technology Corporation Limited
+ */
+
+#include "qemu/osdep.h"
+#include <sys/ioctl.h>
+#include <linux/kvm.h>
+
+#include "qemu/timer.h"
+#include "qemu/error-report.h"
+#include "qemu/main-loop.h"
+#include "sysemu/sysemu.h"
+#include "sysemu/kvm.h"
+#include "sysemu/kvm_int.h"
+#include "hw/pci/pci.h"
+#include "exec/memattrs.h"
+#include "exec/address-spaces.h"
+#include "hw/boards.h"
+#include "hw/irq.h"
+#include "qemu/log.h"
+#include "hw/loader.h"
+#include "migration/migration.h"
+#include "sysemu/runstate.h"
+#include "cpu-csr.h"
+#include "kvm_loongarch.h"
+
+static bool cap_has_mp_state;
+const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
+ KVM_CAP_LAST_INFO
+};
+
+int kvm_arch_get_registers(CPUState *cs)
+{
+ return 0;
+}
+int kvm_arch_put_registers(CPUState *cs, int level)
+{
+ return 0;
+}
+
+int kvm_arch_init_vcpu(CPUState *cs)
+{
+ return 0;
+}
+
+int kvm_arch_destroy_vcpu(CPUState *cs)
+{
+ return 0;
+}
+
+unsigned long kvm_arch_vcpu_id(CPUState *cs)
+{
+ return cs->cpu_index;
+}
+
+int kvm_arch_release_virq_post(int virq)
+{
+ return 0;
+}
+
+int kvm_arch_msi_data_to_gsi(uint32_t data)
+{
+ abort();
+}
+
+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;
+}
+
+void kvm_arch_init_irq_routing(KVMState *s)
+{
+}
+
+int kvm_arch_get_default_type(MachineState *ms)
+{
+ return 0;
+}
+
+int kvm_arch_init(MachineState *ms, KVMState *s)
+{
+ return 0;
+}
+
+int kvm_arch_irqchip_create(KVMState *s)
+{
+ return 0;
+}
+
+void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run)
+{
+}
+
+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;
+}
+
+bool kvm_arch_stop_on_emulation_error(CPUState *cs)
+{
+ return true;
+}
+
+bool kvm_arch_cpu_check_are_resettable(void)
+{
+ return true;
+}
+
+int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
+{
+ return 0;
+}
+
+void kvm_arch_accel_class_init(ObjectClass *oc)
+{
+}
--
2.27.0

View File

@ -0,0 +1,570 @@
From d2381abc2c78de68e765a29a55282707541e315d Mon Sep 17 00:00:00 2001
From: Song Gao <gaosong@loongson.cn>
Date: Thu, 25 Jan 2024 14:14:01 +0800
Subject: [PATCH] target/loongarch: Fix qtest test-hmp error when KVM-only
build
The cc->sysemu_ops->get_phys_page_debug() is NULL when
KVM-only build. this patch fixes it.
Signed-off-by: Song Gao <gaosong@loongson.cn>
Tested-by: Bibo Mao <maobibo@loongson.cn>
Message-Id: <20240125061401.52526-1-gaosong@loongson.cn>
---
target/loongarch/cpu.c | 2 -
target/loongarch/cpu_helper.c | 231 ++++++++++++++++++++++++++++++
target/loongarch/internals.h | 20 ++-
target/loongarch/meson.build | 1 +
target/loongarch/tcg/tlb_helper.c | 230 -----------------------------
5 files changed, 250 insertions(+), 234 deletions(-)
create mode 100644 target/loongarch/cpu_helper.c
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index 6611d137a1..b098b1c6f3 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -771,9 +771,7 @@ static struct TCGCPUOps loongarch_tcg_ops = {
#include "hw/core/sysemu-cpu-ops.h"
static const struct SysemuCPUOps loongarch_sysemu_ops = {
-#ifdef CONFIG_TCG
.get_phys_page_debug = loongarch_cpu_get_phys_page_debug,
-#endif
};
static int64_t loongarch_cpu_get_arch_id(CPUState *cs)
diff --git a/target/loongarch/cpu_helper.c b/target/loongarch/cpu_helper.c
new file mode 100644
index 0000000000..f68d63f466
--- /dev/null
+++ b/target/loongarch/cpu_helper.c
@@ -0,0 +1,231 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * LoongArch CPU helpers for qemu
+ *
+ * Copyright (c) 2024 Loongson Technology Corporation Limited
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "internals.h"
+#include "cpu-csr.h"
+
+static int loongarch_map_tlb_entry(CPULoongArchState *env, hwaddr *physical,
+ int *prot, target_ulong address,
+ int access_type, int index, int mmu_idx)
+{
+ LoongArchTLB *tlb = &env->tlb[index];
+ uint64_t plv = mmu_idx;
+ uint64_t tlb_entry, tlb_ppn;
+ uint8_t tlb_ps, n, tlb_v, tlb_d, tlb_plv, tlb_nx, tlb_nr, tlb_rplv;
+
+ if (index >= LOONGARCH_STLB) {
+ tlb_ps = FIELD_EX64(tlb->tlb_misc, TLB_MISC, PS);
+ } else {
+ tlb_ps = FIELD_EX64(env->CSR_STLBPS, CSR_STLBPS, PS);
+ }
+ n = (address >> tlb_ps) & 0x1;/* Odd or even */
+
+ tlb_entry = n ? tlb->tlb_entry1 : tlb->tlb_entry0;
+ tlb_v = FIELD_EX64(tlb_entry, TLBENTRY, V);
+ tlb_d = FIELD_EX64(tlb_entry, TLBENTRY, D);
+ tlb_plv = FIELD_EX64(tlb_entry, TLBENTRY, PLV);
+ if (is_la64(env)) {
+ tlb_ppn = FIELD_EX64(tlb_entry, TLBENTRY_64, PPN);
+ tlb_nx = FIELD_EX64(tlb_entry, TLBENTRY_64, NX);
+ tlb_nr = FIELD_EX64(tlb_entry, TLBENTRY_64, NR);
+ tlb_rplv = FIELD_EX64(tlb_entry, TLBENTRY_64, RPLV);
+ } else {
+ tlb_ppn = FIELD_EX64(tlb_entry, TLBENTRY_32, PPN);
+ tlb_nx = 0;
+ tlb_nr = 0;
+ tlb_rplv = 0;
+ }
+
+ /* Remove sw bit between bit12 -- bit PS*/
+ tlb_ppn = tlb_ppn & ~(((0x1UL << (tlb_ps - 12)) -1));
+
+ /* Check access rights */
+ if (!tlb_v) {
+ return TLBRET_INVALID;
+ }
+
+ if (access_type == MMU_INST_FETCH && tlb_nx) {
+ return TLBRET_XI;
+ }
+
+ if (access_type == MMU_DATA_LOAD && tlb_nr) {
+ return TLBRET_RI;
+ }
+
+ if (((tlb_rplv == 0) && (plv > tlb_plv)) ||
+ ((tlb_rplv == 1) && (plv != tlb_plv))) {
+ return TLBRET_PE;
+ }
+
+ if ((access_type == MMU_DATA_STORE) && !tlb_d) {
+ return TLBRET_DIRTY;
+ }
+
+ *physical = (tlb_ppn << R_TLBENTRY_64_PPN_SHIFT) |
+ (address & MAKE_64BIT_MASK(0, tlb_ps));
+ *prot = PAGE_READ;
+ if (tlb_d) {
+ *prot |= PAGE_WRITE;
+ }
+ if (!tlb_nx) {
+ *prot |= PAGE_EXEC;
+ }
+ return TLBRET_MATCH;
+}
+
+/*
+ * One tlb entry holds an adjacent odd/even pair, the vpn is the
+ * content of the virtual page number divided by 2. So the
+ * compare vpn is bit[47:15] for 16KiB page. while the vppn
+ * field in tlb entry contains bit[47:13], so need adjust.
+ * virt_vpn = vaddr[47:13]
+ */
+bool loongarch_tlb_search(CPULoongArchState *env, target_ulong vaddr,
+ int *index)
+{
+ LoongArchTLB *tlb;
+ uint16_t csr_asid, tlb_asid, stlb_idx;
+ uint8_t tlb_e, tlb_ps, tlb_g, stlb_ps;
+ int i, compare_shift;
+ uint64_t vpn, tlb_vppn;
+
+ csr_asid = FIELD_EX64(env->CSR_ASID, CSR_ASID, ASID);
+ stlb_ps = FIELD_EX64(env->CSR_STLBPS, CSR_STLBPS, PS);
+ vpn = (vaddr & TARGET_VIRT_MASK) >> (stlb_ps + 1);
+ stlb_idx = vpn & 0xff; /* VA[25:15] <==> TLBIDX.index for 16KiB Page */
+ compare_shift = stlb_ps + 1 - R_TLB_MISC_VPPN_SHIFT;
+
+ /* Search STLB */
+ for (i = 0; i < 8; ++i) {
+ tlb = &env->tlb[i * 256 + stlb_idx];
+ tlb_e = FIELD_EX64(tlb->tlb_misc, TLB_MISC, E);
+ if (tlb_e) {
+ tlb_vppn = FIELD_EX64(tlb->tlb_misc, TLB_MISC, VPPN);
+ tlb_asid = FIELD_EX64(tlb->tlb_misc, TLB_MISC, ASID);
+ tlb_g = FIELD_EX64(tlb->tlb_entry0, TLBENTRY, G);
+
+ if ((tlb_g == 1 || tlb_asid == csr_asid) &&
+ (vpn == (tlb_vppn >> compare_shift))) {
+ *index = i * 256 + stlb_idx;
+ return true;
+ }
+ }
+ }
+
+ /* Search MTLB */
+ for (i = LOONGARCH_STLB; i < LOONGARCH_TLB_MAX; ++i) {
+ tlb = &env->tlb[i];
+ tlb_e = FIELD_EX64(tlb->tlb_misc, TLB_MISC, E);
+ if (tlb_e) {
+ tlb_vppn = FIELD_EX64(tlb->tlb_misc, TLB_MISC, VPPN);
+ tlb_ps = FIELD_EX64(tlb->tlb_misc, TLB_MISC, PS);
+ tlb_asid = FIELD_EX64(tlb->tlb_misc, TLB_MISC, ASID);
+ tlb_g = FIELD_EX64(tlb->tlb_entry0, TLBENTRY, G);
+ compare_shift = tlb_ps + 1 - R_TLB_MISC_VPPN_SHIFT;
+ vpn = (vaddr & TARGET_VIRT_MASK) >> (tlb_ps + 1);
+ if ((tlb_g == 1 || tlb_asid == csr_asid) &&
+ (vpn == (tlb_vppn >> compare_shift))) {
+ *index = i;
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+static int loongarch_map_address(CPULoongArchState *env, hwaddr *physical,
+ int *prot, target_ulong address,
+ MMUAccessType access_type, int mmu_idx)
+{
+ int index, match;
+
+ match = loongarch_tlb_search(env, address, &index);
+ if (match) {
+ return loongarch_map_tlb_entry(env, physical, prot,
+ address, access_type, index, mmu_idx);
+ }
+
+ return TLBRET_NOMATCH;
+}
+
+static hwaddr dmw_va2pa(CPULoongArchState *env, target_ulong va,
+ target_ulong dmw)
+{
+ if (is_la64(env)) {
+ return va & TARGET_VIRT_MASK;
+ } else {
+ uint32_t pseg = FIELD_EX32(dmw, CSR_DMW_32, PSEG);
+ return (va & MAKE_64BIT_MASK(0, R_CSR_DMW_32_VSEG_SHIFT)) | \
+ (pseg << R_CSR_DMW_32_VSEG_SHIFT);
+ }
+}
+
+int get_physical_address(CPULoongArchState *env, hwaddr *physical,
+ int *prot, target_ulong address,
+ MMUAccessType access_type, int mmu_idx)
+{
+ int user_mode = mmu_idx == MMU_IDX_USER;
+ int kernel_mode = mmu_idx == MMU_IDX_KERNEL;
+ uint32_t plv, base_c, base_v;
+ int64_t addr_high;
+ uint8_t da = FIELD_EX64(env->CSR_CRMD, CSR_CRMD, DA);
+ uint8_t pg = FIELD_EX64(env->CSR_CRMD, CSR_CRMD, PG);
+
+ /* Check PG and DA */
+ if (da & !pg) {
+ *physical = address & TARGET_PHYS_MASK;
+ *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
+ return TLBRET_MATCH;
+ }
+
+ plv = kernel_mode | (user_mode << R_CSR_DMW_PLV3_SHIFT);
+ if (is_la64(env)) {
+ base_v = address >> R_CSR_DMW_64_VSEG_SHIFT;
+ } else {
+ base_v = address >> R_CSR_DMW_32_VSEG_SHIFT;
+ }
+ /* Check direct map window */
+ for (int i = 0; i < 4; i++) {
+ if (is_la64(env)) {
+ base_c = FIELD_EX64(env->CSR_DMW[i], CSR_DMW_64, VSEG);
+ } else {
+ base_c = FIELD_EX64(env->CSR_DMW[i], CSR_DMW_32, VSEG);
+ }
+ if ((plv & env->CSR_DMW[i]) && (base_c == base_v)) {
+ *physical = dmw_va2pa(env, address, env->CSR_DMW[i]);
+ *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
+ return TLBRET_MATCH;
+ }
+ }
+
+ /* Check valid extension */
+ addr_high = sextract64(address, TARGET_VIRT_ADDR_SPACE_BITS, 16);
+ if (!(addr_high == 0 || addr_high == -1)) {
+ return TLBRET_BADADDR;
+ }
+
+ /* Mapped address */
+ return loongarch_map_address(env, physical, prot, address,
+ access_type, mmu_idx);
+}
+
+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, MMU_DATA_LOAD,
+ cpu_mmu_index(env, false)) != 0) {
+ return -1;
+ }
+ return phys_addr;
+}
diff --git a/target/loongarch/internals.h b/target/loongarch/internals.h
index 0beb034748..a2fc54c8a7 100644
--- a/target/loongarch/internals.h
+++ b/target/loongarch/internals.h
@@ -37,6 +37,17 @@ void restore_fp_status(CPULoongArchState *env);
#endif
#ifndef CONFIG_USER_ONLY
+enum {
+ TLBRET_MATCH = 0,
+ TLBRET_BADADDR = 1,
+ TLBRET_NOMATCH = 2,
+ TLBRET_INVALID = 3,
+ TLBRET_DIRTY = 4,
+ TLBRET_RI = 5,
+ TLBRET_XI = 6,
+ TLBRET_PE = 7,
+};
+
extern const VMStateDescription vmstate_loongarch_cpu;
void loongarch_cpu_set_irq(void *opaque, int irq, int level);
@@ -46,12 +57,17 @@ uint64_t cpu_loongarch_get_constant_timer_counter(LoongArchCPU *cpu);
uint64_t cpu_loongarch_get_constant_timer_ticks(LoongArchCPU *cpu);
void cpu_loongarch_store_constant_timer_config(LoongArchCPU *cpu,
uint64_t value);
+bool loongarch_tlb_search(CPULoongArchState *env, target_ulong vaddr,
+ int *index);
+int get_physical_address(CPULoongArchState *env, hwaddr *physical,
+ int *prot, target_ulong address,
+ MMUAccessType access_type, int mmu_idx);
+hwaddr loongarch_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
+
#ifdef CONFIG_TCG
bool loongarch_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
MMUAccessType access_type, int mmu_idx,
bool probe, uintptr_t retaddr);
-
-hwaddr loongarch_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
#endif
#endif /* !CONFIG_USER_ONLY */
diff --git a/target/loongarch/meson.build b/target/loongarch/meson.build
index db310f6022..e002e9aaf6 100644
--- a/target/loongarch/meson.build
+++ b/target/loongarch/meson.build
@@ -8,6 +8,7 @@ loongarch_ss.add(files(
loongarch_system_ss = ss.source_set()
loongarch_system_ss.add(files(
+ 'cpu_helper.c',
'loongarch-qmp-cmds.c',
'machine.c',
))
diff --git a/target/loongarch/tcg/tlb_helper.c b/target/loongarch/tcg/tlb_helper.c
index 449043c68b..804ab7a263 100644
--- a/target/loongarch/tcg/tlb_helper.c
+++ b/target/loongarch/tcg/tlb_helper.c
@@ -17,236 +17,6 @@
#include "exec/log.h"
#include "cpu-csr.h"
-enum {
- TLBRET_MATCH = 0,
- TLBRET_BADADDR = 1,
- TLBRET_NOMATCH = 2,
- TLBRET_INVALID = 3,
- TLBRET_DIRTY = 4,
- TLBRET_RI = 5,
- TLBRET_XI = 6,
- TLBRET_PE = 7,
-};
-
-static int loongarch_map_tlb_entry(CPULoongArchState *env, hwaddr *physical,
- int *prot, target_ulong address,
- int access_type, int index, int mmu_idx)
-{
- LoongArchTLB *tlb = &env->tlb[index];
- uint64_t plv = mmu_idx;
- uint64_t tlb_entry, tlb_ppn;
- uint8_t tlb_ps, n, tlb_v, tlb_d, tlb_plv, tlb_nx, tlb_nr, tlb_rplv;
-
- if (index >= LOONGARCH_STLB) {
- tlb_ps = FIELD_EX64(tlb->tlb_misc, TLB_MISC, PS);
- } else {
- tlb_ps = FIELD_EX64(env->CSR_STLBPS, CSR_STLBPS, PS);
- }
- n = (address >> tlb_ps) & 0x1;/* Odd or even */
-
- tlb_entry = n ? tlb->tlb_entry1 : tlb->tlb_entry0;
- tlb_v = FIELD_EX64(tlb_entry, TLBENTRY, V);
- tlb_d = FIELD_EX64(tlb_entry, TLBENTRY, D);
- tlb_plv = FIELD_EX64(tlb_entry, TLBENTRY, PLV);
- if (is_la64(env)) {
- tlb_ppn = FIELD_EX64(tlb_entry, TLBENTRY_64, PPN);
- tlb_nx = FIELD_EX64(tlb_entry, TLBENTRY_64, NX);
- tlb_nr = FIELD_EX64(tlb_entry, TLBENTRY_64, NR);
- tlb_rplv = FIELD_EX64(tlb_entry, TLBENTRY_64, RPLV);
- } else {
- tlb_ppn = FIELD_EX64(tlb_entry, TLBENTRY_32, PPN);
- tlb_nx = 0;
- tlb_nr = 0;
- tlb_rplv = 0;
- }
-
- /* Remove sw bit between bit12 -- bit PS*/
- tlb_ppn = tlb_ppn & ~(((0x1UL << (tlb_ps - 12)) -1));
-
- /* Check access rights */
- if (!tlb_v) {
- return TLBRET_INVALID;
- }
-
- if (access_type == MMU_INST_FETCH && tlb_nx) {
- return TLBRET_XI;
- }
-
- if (access_type == MMU_DATA_LOAD && tlb_nr) {
- return TLBRET_RI;
- }
-
- if (((tlb_rplv == 0) && (plv > tlb_plv)) ||
- ((tlb_rplv == 1) && (plv != tlb_plv))) {
- return TLBRET_PE;
- }
-
- if ((access_type == MMU_DATA_STORE) && !tlb_d) {
- return TLBRET_DIRTY;
- }
-
- *physical = (tlb_ppn << R_TLBENTRY_64_PPN_SHIFT) |
- (address & MAKE_64BIT_MASK(0, tlb_ps));
- *prot = PAGE_READ;
- if (tlb_d) {
- *prot |= PAGE_WRITE;
- }
- if (!tlb_nx) {
- *prot |= PAGE_EXEC;
- }
- return TLBRET_MATCH;
-}
-
-/*
- * One tlb entry holds an adjacent odd/even pair, the vpn is the
- * content of the virtual page number divided by 2. So the
- * compare vpn is bit[47:15] for 16KiB page. while the vppn
- * field in tlb entry contains bit[47:13], so need adjust.
- * virt_vpn = vaddr[47:13]
- */
-static bool loongarch_tlb_search(CPULoongArchState *env, target_ulong vaddr,
- int *index)
-{
- LoongArchTLB *tlb;
- uint16_t csr_asid, tlb_asid, stlb_idx;
- uint8_t tlb_e, tlb_ps, tlb_g, stlb_ps;
- int i, compare_shift;
- uint64_t vpn, tlb_vppn;
-
- csr_asid = FIELD_EX64(env->CSR_ASID, CSR_ASID, ASID);
- stlb_ps = FIELD_EX64(env->CSR_STLBPS, CSR_STLBPS, PS);
- vpn = (vaddr & TARGET_VIRT_MASK) >> (stlb_ps + 1);
- stlb_idx = vpn & 0xff; /* VA[25:15] <==> TLBIDX.index for 16KiB Page */
- compare_shift = stlb_ps + 1 - R_TLB_MISC_VPPN_SHIFT;
-
- /* Search STLB */
- for (i = 0; i < 8; ++i) {
- tlb = &env->tlb[i * 256 + stlb_idx];
- tlb_e = FIELD_EX64(tlb->tlb_misc, TLB_MISC, E);
- if (tlb_e) {
- tlb_vppn = FIELD_EX64(tlb->tlb_misc, TLB_MISC, VPPN);
- tlb_asid = FIELD_EX64(tlb->tlb_misc, TLB_MISC, ASID);
- tlb_g = FIELD_EX64(tlb->tlb_entry0, TLBENTRY, G);
-
- if ((tlb_g == 1 || tlb_asid == csr_asid) &&
- (vpn == (tlb_vppn >> compare_shift))) {
- *index = i * 256 + stlb_idx;
- return true;
- }
- }
- }
-
- /* Search MTLB */
- for (i = LOONGARCH_STLB; i < LOONGARCH_TLB_MAX; ++i) {
- tlb = &env->tlb[i];
- tlb_e = FIELD_EX64(tlb->tlb_misc, TLB_MISC, E);
- if (tlb_e) {
- tlb_vppn = FIELD_EX64(tlb->tlb_misc, TLB_MISC, VPPN);
- tlb_ps = FIELD_EX64(tlb->tlb_misc, TLB_MISC, PS);
- tlb_asid = FIELD_EX64(tlb->tlb_misc, TLB_MISC, ASID);
- tlb_g = FIELD_EX64(tlb->tlb_entry0, TLBENTRY, G);
- compare_shift = tlb_ps + 1 - R_TLB_MISC_VPPN_SHIFT;
- vpn = (vaddr & TARGET_VIRT_MASK) >> (tlb_ps + 1);
- if ((tlb_g == 1 || tlb_asid == csr_asid) &&
- (vpn == (tlb_vppn >> compare_shift))) {
- *index = i;
- return true;
- }
- }
- }
- return false;
-}
-
-static int loongarch_map_address(CPULoongArchState *env, hwaddr *physical,
- int *prot, target_ulong address,
- MMUAccessType access_type, int mmu_idx)
-{
- int index, match;
-
- match = loongarch_tlb_search(env, address, &index);
- if (match) {
- return loongarch_map_tlb_entry(env, physical, prot,
- address, access_type, index, mmu_idx);
- }
-
- return TLBRET_NOMATCH;
-}
-
-static hwaddr dmw_va2pa(CPULoongArchState *env, target_ulong va,
- target_ulong dmw)
-{
- if (is_la64(env)) {
- return va & TARGET_VIRT_MASK;
- } else {
- uint32_t pseg = FIELD_EX32(dmw, CSR_DMW_32, PSEG);
- return (va & MAKE_64BIT_MASK(0, R_CSR_DMW_32_VSEG_SHIFT)) | \
- (pseg << R_CSR_DMW_32_VSEG_SHIFT);
- }
-}
-
-static int get_physical_address(CPULoongArchState *env, hwaddr *physical,
- int *prot, target_ulong address,
- MMUAccessType access_type, int mmu_idx)
-{
- int user_mode = mmu_idx == MMU_IDX_USER;
- int kernel_mode = mmu_idx == MMU_IDX_KERNEL;
- uint32_t plv, base_c, base_v;
- int64_t addr_high;
- uint8_t da = FIELD_EX64(env->CSR_CRMD, CSR_CRMD, DA);
- uint8_t pg = FIELD_EX64(env->CSR_CRMD, CSR_CRMD, PG);
-
- /* Check PG and DA */
- if (da & !pg) {
- *physical = address & TARGET_PHYS_MASK;
- *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
- return TLBRET_MATCH;
- }
-
- plv = kernel_mode | (user_mode << R_CSR_DMW_PLV3_SHIFT);
- if (is_la64(env)) {
- base_v = address >> R_CSR_DMW_64_VSEG_SHIFT;
- } else {
- base_v = address >> R_CSR_DMW_32_VSEG_SHIFT;
- }
- /* Check direct map window */
- for (int i = 0; i < 4; i++) {
- if (is_la64(env)) {
- base_c = FIELD_EX64(env->CSR_DMW[i], CSR_DMW_64, VSEG);
- } else {
- base_c = FIELD_EX64(env->CSR_DMW[i], CSR_DMW_32, VSEG);
- }
- if ((plv & env->CSR_DMW[i]) && (base_c == base_v)) {
- *physical = dmw_va2pa(env, address, env->CSR_DMW[i]);
- *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
- return TLBRET_MATCH;
- }
- }
-
- /* Check valid extension */
- addr_high = sextract64(address, TARGET_VIRT_ADDR_SPACE_BITS, 16);
- if (!(addr_high == 0 || addr_high == -1)) {
- return TLBRET_BADADDR;
- }
-
- /* Mapped address */
- return loongarch_map_address(env, physical, prot, address,
- access_type, mmu_idx);
-}
-
-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, MMU_DATA_LOAD,
- cpu_mmu_index(env, false)) != 0) {
- return -1;
- }
- return phys_addr;
-}
-
static void raise_mmu_exception(CPULoongArchState *env, target_ulong address,
MMUAccessType access_type, int tlb_error)
{
--
2.27.0

View File

@ -0,0 +1,724 @@
From 0884653d8583aaaa5585caf38246518439bcfdfd Mon Sep 17 00:00:00 2001
From: Tianrui Zhao <zhaotianrui@loongson.cn>
Date: Fri, 5 Jan 2024 15:57:59 +0800
Subject: [PATCH] target/loongarch: Implement kvm get/set registers
Implement kvm_arch_get/set_registers interfaces, many regs
can be get/set in the function, such as core regs, csr regs,
fpu regs, mp state, etc.
Signed-off-by: Tianrui Zhao <zhaotianrui@loongson.cn>
Signed-off-by: xianglai li <lixianglai@loongson.cn>
Reviewed-by: Song Gao <gaosong@loongson.cn>
Change-Id: Ia8fc48fe08b1768853f7729e77d37cdf270031e4
Message-Id: <20240105075804.1228596-5-zhaotianrui@loongson.cn>
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
meson.build | 1 +
target/loongarch/cpu.c | 3 +
target/loongarch/cpu.h | 1 +
target/loongarch/internals.h | 5 +-
target/loongarch/kvm/kvm.c | 580 +++++++++++++++++++++++++++++++++-
target/loongarch/trace-events | 11 +
target/loongarch/trace.h | 1 +
7 files changed, 599 insertions(+), 3 deletions(-)
create mode 100644 target/loongarch/trace-events
create mode 100644 target/loongarch/trace.h
diff --git a/meson.build b/meson.build
index 6c77d9687d..445f2b7c2b 100644
--- a/meson.build
+++ b/meson.build
@@ -3358,6 +3358,7 @@ if have_system or have_user
'target/hppa',
'target/i386',
'target/i386/kvm',
+ 'target/loongarch',
'target/mips/tcg',
'target/nios2',
'target/ppc',
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index 021592798a..275833eec8 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -553,6 +553,9 @@ static void loongarch_cpu_reset_hold(Object *obj)
#ifndef CONFIG_USER_ONLY
env->pc = 0x1c000000;
memset(env->tlb, 0, sizeof(env->tlb));
+ if (kvm_enabled()) {
+ kvm_arch_reset_vcpu(env);
+ }
#endif
restore_fp_status(env);
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index f6d5ef0852..f4a89bd626 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -360,6 +360,7 @@ typedef struct CPUArchState {
MemoryRegion iocsr_mem;
bool load_elf;
uint64_t elf_address;
+ uint32_t mp_state;
/* Store ipistate to access from this struct */
DeviceState *ipistate;
#endif
diff --git a/target/loongarch/internals.h b/target/loongarch/internals.h
index c492863cc5..0beb034748 100644
--- a/target/loongarch/internals.h
+++ b/target/loongarch/internals.h
@@ -31,8 +31,10 @@ void G_NORETURN do_raise_exception(CPULoongArchState *env,
const char *loongarch_exception_name(int32_t exception);
+#ifdef CONFIG_TCG
int ieee_ex_to_loongarch(int xcpt);
void restore_fp_status(CPULoongArchState *env);
+#endif
#ifndef CONFIG_USER_ONLY
extern const VMStateDescription vmstate_loongarch_cpu;
@@ -44,12 +46,13 @@ uint64_t cpu_loongarch_get_constant_timer_counter(LoongArchCPU *cpu);
uint64_t cpu_loongarch_get_constant_timer_ticks(LoongArchCPU *cpu);
void cpu_loongarch_store_constant_timer_config(LoongArchCPU *cpu,
uint64_t value);
-
+#ifdef CONFIG_TCG
bool loongarch_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
MMUAccessType access_type, int mmu_idx,
bool probe, uintptr_t retaddr);
hwaddr loongarch_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
+#endif
#endif /* !CONFIG_USER_ONLY */
uint64_t read_fcc(CPULoongArchState *env);
diff --git a/target/loongarch/kvm/kvm.c b/target/loongarch/kvm/kvm.c
index 0d67322fd9..e7c9ef830c 100644
--- a/target/loongarch/kvm/kvm.c
+++ b/target/loongarch/kvm/kvm.c
@@ -26,19 +26,595 @@
#include "sysemu/runstate.h"
#include "cpu-csr.h"
#include "kvm_loongarch.h"
+#include "trace.h"
static bool cap_has_mp_state;
const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
KVM_CAP_LAST_INFO
};
+static int kvm_loongarch_get_regs_core(CPUState *cs)
+{
+ int ret = 0;
+ int i;
+ struct kvm_regs regs;
+ LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+ CPULoongArchState *env = &cpu->env;
+
+ /* Get the current register set as KVM seems it */
+ ret = kvm_vcpu_ioctl(cs, KVM_GET_REGS, &regs);
+ if (ret < 0) {
+ trace_kvm_failed_get_regs_core(strerror(errno));
+ return ret;
+ }
+ /* gpr[0] value is always 0 */
+ env->gpr[0] = 0;
+ for (i = 1; i < 32; i++) {
+ env->gpr[i] = regs.gpr[i];
+ }
+
+ env->pc = regs.pc;
+ return ret;
+}
+
+static int kvm_loongarch_put_regs_core(CPUState *cs)
+{
+ int ret = 0;
+ int i;
+ struct kvm_regs regs;
+ LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+ CPULoongArchState *env = &cpu->env;
+
+ /* Set the registers based on QEMU's view of things */
+ for (i = 0; i < 32; i++) {
+ regs.gpr[i] = env->gpr[i];
+ }
+
+ regs.pc = env->pc;
+ ret = kvm_vcpu_ioctl(cs, KVM_SET_REGS, &regs);
+ if (ret < 0) {
+ trace_kvm_failed_put_regs_core(strerror(errno));
+ }
+
+ return ret;
+}
+
+static int kvm_loongarch_get_csr(CPUState *cs)
+{
+ int ret = 0;
+ LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+ CPULoongArchState *env = &cpu->env;
+
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_CRMD),
+ &env->CSR_CRMD);
+
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PRMD),
+ &env->CSR_PRMD);
+
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_EUEN),
+ &env->CSR_EUEN);
+
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_MISC),
+ &env->CSR_MISC);
+
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_ECFG),
+ &env->CSR_ECFG);
+
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_ESTAT),
+ &env->CSR_ESTAT);
+
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_ERA),
+ &env->CSR_ERA);
+
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_BADV),
+ &env->CSR_BADV);
+
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_BADI),
+ &env->CSR_BADI);
+
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_EENTRY),
+ &env->CSR_EENTRY);
+
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBIDX),
+ &env->CSR_TLBIDX);
+
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBEHI),
+ &env->CSR_TLBEHI);
+
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBELO0),
+ &env->CSR_TLBELO0);
+
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBELO1),
+ &env->CSR_TLBELO1);
+
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_ASID),
+ &env->CSR_ASID);
+
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PGDL),
+ &env->CSR_PGDL);
+
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PGDH),
+ &env->CSR_PGDH);
+
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PGD),
+ &env->CSR_PGD);
+
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PWCL),
+ &env->CSR_PWCL);
+
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PWCH),
+ &env->CSR_PWCH);
+
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_STLBPS),
+ &env->CSR_STLBPS);
+
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_RVACFG),
+ &env->CSR_RVACFG);
+
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_CPUID),
+ &env->CSR_CPUID);
+
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PRCFG1),
+ &env->CSR_PRCFG1);
+
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PRCFG2),
+ &env->CSR_PRCFG2);
+
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PRCFG3),
+ &env->CSR_PRCFG3);
+
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(0)),
+ &env->CSR_SAVE[0]);
+
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(1)),
+ &env->CSR_SAVE[1]);
+
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(2)),
+ &env->CSR_SAVE[2]);
+
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(3)),
+ &env->CSR_SAVE[3]);
+
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(4)),
+ &env->CSR_SAVE[4]);
+
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(5)),
+ &env->CSR_SAVE[5]);
+
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(6)),
+ &env->CSR_SAVE[6]);
+
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(7)),
+ &env->CSR_SAVE[7]);
+
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TID),
+ &env->CSR_TID);
+
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_CNTC),
+ &env->CSR_CNTC);
+
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TICLR),
+ &env->CSR_TICLR);
+
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_LLBCTL),
+ &env->CSR_LLBCTL);
+
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_IMPCTL1),
+ &env->CSR_IMPCTL1);
+
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_IMPCTL2),
+ &env->CSR_IMPCTL2);
+
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRENTRY),
+ &env->CSR_TLBRENTRY);
+
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRBADV),
+ &env->CSR_TLBRBADV);
+
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRERA),
+ &env->CSR_TLBRERA);
+
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRSAVE),
+ &env->CSR_TLBRSAVE);
+
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRELO0),
+ &env->CSR_TLBRELO0);
+
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRELO1),
+ &env->CSR_TLBRELO1);
+
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBREHI),
+ &env->CSR_TLBREHI);
+
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRPRMD),
+ &env->CSR_TLBRPRMD);
+
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_DMW(0)),
+ &env->CSR_DMW[0]);
+
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_DMW(1)),
+ &env->CSR_DMW[1]);
+
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_DMW(2)),
+ &env->CSR_DMW[2]);
+
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_DMW(3)),
+ &env->CSR_DMW[3]);
+
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TVAL),
+ &env->CSR_TVAL);
+
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TCFG),
+ &env->CSR_TCFG);
+
+ return ret;
+}
+
+static int kvm_loongarch_put_csr(CPUState *cs)
+{
+ int ret = 0;
+ LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+ CPULoongArchState *env = &cpu->env;
+
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_CRMD),
+ &env->CSR_CRMD);
+
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PRMD),
+ &env->CSR_PRMD);
+
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_EUEN),
+ &env->CSR_EUEN);
+
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_MISC),
+ &env->CSR_MISC);
+
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_ECFG),
+ &env->CSR_ECFG);
+
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_ESTAT),
+ &env->CSR_ESTAT);
+
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_ERA),
+ &env->CSR_ERA);
+
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_BADV),
+ &env->CSR_BADV);
+
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_BADI),
+ &env->CSR_BADI);
+
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_EENTRY),
+ &env->CSR_EENTRY);
+
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBIDX),
+ &env->CSR_TLBIDX);
+
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBEHI),
+ &env->CSR_TLBEHI);
+
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBELO0),
+ &env->CSR_TLBELO0);
+
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBELO1),
+ &env->CSR_TLBELO1);
+
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_ASID),
+ &env->CSR_ASID);
+
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PGDL),
+ &env->CSR_PGDL);
+
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PGDH),
+ &env->CSR_PGDH);
+
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PGD),
+ &env->CSR_PGD);
+
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PWCL),
+ &env->CSR_PWCL);
+
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PWCH),
+ &env->CSR_PWCH);
+
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_STLBPS),
+ &env->CSR_STLBPS);
+
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_RVACFG),
+ &env->CSR_RVACFG);
+
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_CPUID),
+ &env->CSR_CPUID);
+
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PRCFG1),
+ &env->CSR_PRCFG1);
+
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PRCFG2),
+ &env->CSR_PRCFG2);
+
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PRCFG3),
+ &env->CSR_PRCFG3);
+
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(0)),
+ &env->CSR_SAVE[0]);
+
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(1)),
+ &env->CSR_SAVE[1]);
+
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(2)),
+ &env->CSR_SAVE[2]);
+
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(3)),
+ &env->CSR_SAVE[3]);
+
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(4)),
+ &env->CSR_SAVE[4]);
+
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(5)),
+ &env->CSR_SAVE[5]);
+
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(6)),
+ &env->CSR_SAVE[6]);
+
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(7)),
+ &env->CSR_SAVE[7]);
+
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TID),
+ &env->CSR_TID);
+
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_CNTC),
+ &env->CSR_CNTC);
+
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TICLR),
+ &env->CSR_TICLR);
+
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_LLBCTL),
+ &env->CSR_LLBCTL);
+
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_IMPCTL1),
+ &env->CSR_IMPCTL1);
+
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_IMPCTL2),
+ &env->CSR_IMPCTL2);
+
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRENTRY),
+ &env->CSR_TLBRENTRY);
+
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRBADV),
+ &env->CSR_TLBRBADV);
+
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRERA),
+ &env->CSR_TLBRERA);
+
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRSAVE),
+ &env->CSR_TLBRSAVE);
+
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRELO0),
+ &env->CSR_TLBRELO0);
+
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRELO1),
+ &env->CSR_TLBRELO1);
+
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBREHI),
+ &env->CSR_TLBREHI);
+
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRPRMD),
+ &env->CSR_TLBRPRMD);
+
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_DMW(0)),
+ &env->CSR_DMW[0]);
+
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_DMW(1)),
+ &env->CSR_DMW[1]);
+
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_DMW(2)),
+ &env->CSR_DMW[2]);
+
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_DMW(3)),
+ &env->CSR_DMW[3]);
+ /*
+ * timer cfg must be put at last since it is used to enable
+ * guest timer
+ */
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TVAL),
+ &env->CSR_TVAL);
+
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TCFG),
+ &env->CSR_TCFG);
+ return ret;
+}
+
+static int kvm_loongarch_get_regs_fp(CPUState *cs)
+{
+ int ret, i;
+ struct kvm_fpu fpu;
+
+ LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+ CPULoongArchState *env = &cpu->env;
+
+ ret = kvm_vcpu_ioctl(cs, KVM_GET_FPU, &fpu);
+ if (ret < 0) {
+ trace_kvm_failed_get_fpu(strerror(errno));
+ return ret;
+ }
+
+ env->fcsr0 = fpu.fcsr;
+ for (i = 0; i < 32; i++) {
+ env->fpr[i].vreg.UD[0] = fpu.fpr[i].val64[0];
+ }
+ for (i = 0; i < 8; i++) {
+ env->cf[i] = fpu.fcc & 0xFF;
+ fpu.fcc = fpu.fcc >> 8;
+ }
+
+ return ret;
+}
+
+static int kvm_loongarch_put_regs_fp(CPUState *cs)
+{
+ int ret, i;
+ struct kvm_fpu fpu;
+
+ LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+ CPULoongArchState *env = &cpu->env;
+
+ fpu.fcsr = env->fcsr0;
+ fpu.fcc = 0;
+ for (i = 0; i < 32; i++) {
+ fpu.fpr[i].val64[0] = env->fpr[i].vreg.UD[0];
+ }
+
+ for (i = 0; i < 8; i++) {
+ fpu.fcc |= env->cf[i] << (8 * i);
+ }
+
+ ret = kvm_vcpu_ioctl(cs, KVM_SET_FPU, &fpu);
+ if (ret < 0) {
+ trace_kvm_failed_put_fpu(strerror(errno));
+ }
+
+ return ret;
+}
+
+void kvm_arch_reset_vcpu(CPULoongArchState *env)
+{
+ env->mp_state = KVM_MP_STATE_RUNNABLE;
+}
+
+static int kvm_loongarch_get_mpstate(CPUState *cs)
+{
+ int ret = 0;
+ struct kvm_mp_state mp_state;
+ LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+ CPULoongArchState *env = &cpu->env;
+
+ if (cap_has_mp_state) {
+ ret = kvm_vcpu_ioctl(cs, KVM_GET_MP_STATE, &mp_state);
+ if (ret) {
+ trace_kvm_failed_get_mpstate(strerror(errno));
+ return ret;
+ }
+ env->mp_state = mp_state.mp_state;
+ }
+
+ return ret;
+}
+
+static int kvm_loongarch_put_mpstate(CPUState *cs)
+{
+ int ret = 0;
+
+ LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+ CPULoongArchState *env = &cpu->env;
+
+ struct kvm_mp_state mp_state = {
+ .mp_state = env->mp_state
+ };
+
+ if (cap_has_mp_state) {
+ ret = kvm_vcpu_ioctl(cs, KVM_SET_MP_STATE, &mp_state);
+ if (ret) {
+ trace_kvm_failed_put_mpstate(strerror(errno));
+ }
+ }
+
+ return ret;
+}
+
+static int kvm_loongarch_get_cpucfg(CPUState *cs)
+{
+ int i, ret = 0;
+ uint64_t val;
+ LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+ CPULoongArchState *env = &cpu->env;
+
+ for (i = 0; i < 21; i++) {
+ ret = kvm_get_one_reg(cs, KVM_IOC_CPUCFG(i), &val);
+ if (ret < 0) {
+ trace_kvm_failed_get_cpucfg(strerror(errno));
+ }
+ env->cpucfg[i] = (uint32_t)val;
+ }
+ return ret;
+}
+
+static int kvm_loongarch_put_cpucfg(CPUState *cs)
+{
+ int i, ret = 0;
+ LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+ CPULoongArchState *env = &cpu->env;
+ uint64_t val;
+
+ for (i = 0; i < 21; i++) {
+ val = env->cpucfg[i];
+ /* LSX and LASX and LBT are not supported in kvm now */
+ if (i == 2) {
+ val &= ~(BIT(R_CPUCFG2_LSX_SHIFT) | BIT(R_CPUCFG2_LASX_SHIFT));
+ val &= ~(BIT(R_CPUCFG2_LBT_X86_SHIFT) |
+ BIT(R_CPUCFG2_LBT_ARM_SHIFT) |
+ BIT(R_CPUCFG2_LBT_MIPS_SHIFT));
+ }
+ ret = kvm_set_one_reg(cs, KVM_IOC_CPUCFG(i), &val);
+ if (ret < 0) {
+ trace_kvm_failed_put_cpucfg(strerror(errno));
+ }
+ }
+ return ret;
+}
+
int kvm_arch_get_registers(CPUState *cs)
{
- return 0;
+ int ret;
+
+ ret = kvm_loongarch_get_regs_core(cs);
+ if (ret) {
+ return ret;
+ }
+
+ ret = kvm_loongarch_get_csr(cs);
+ if (ret) {
+ return ret;
+ }
+
+ ret = kvm_loongarch_get_regs_fp(cs);
+ if (ret) {
+ return ret;
+ }
+
+ ret = kvm_loongarch_get_mpstate(cs);
+ if (ret) {
+ return ret;
+ }
+
+ ret = kvm_loongarch_get_cpucfg(cs);
+ return ret;
}
+
int kvm_arch_put_registers(CPUState *cs, int level)
{
- return 0;
+ int ret;
+
+ ret = kvm_loongarch_put_regs_core(cs);
+ if (ret) {
+ return ret;
+ }
+
+ ret = kvm_loongarch_put_csr(cs);
+ if (ret) {
+ return ret;
+ }
+
+ ret = kvm_loongarch_put_regs_fp(cs);
+ if (ret) {
+ return ret;
+ }
+
+ ret = kvm_loongarch_put_mpstate(cs);
+ if (ret) {
+ return ret;
+ }
+
+ ret = kvm_loongarch_put_cpucfg(cs);
+ return ret;
}
int kvm_arch_init_vcpu(CPUState *cs)
diff --git a/target/loongarch/trace-events b/target/loongarch/trace-events
new file mode 100644
index 0000000000..6827ab566a
--- /dev/null
+++ b/target/loongarch/trace-events
@@ -0,0 +1,11 @@
+# See docs/devel/tracing.rst for syntax documentation.
+
+#kvm.c
+kvm_failed_get_regs_core(const char *msg) "Failed to get core regs from KVM: %s"
+kvm_failed_put_regs_core(const char *msg) "Failed to put core regs into KVM: %s"
+kvm_failed_get_fpu(const char *msg) "Failed to get fpu from KVM: %s"
+kvm_failed_put_fpu(const char *msg) "Failed to put fpu into KVM: %s"
+kvm_failed_get_mpstate(const char *msg) "Failed to get mp_state from KVM: %s"
+kvm_failed_put_mpstate(const char *msg) "Failed to put mp_state into KVM: %s"
+kvm_failed_get_cpucfg(const char *msg) "Failed to get cpucfg from KVM: %s"
+kvm_failed_put_cpucfg(const char *msg) "Failed to put cpucfg into KVM: %s"
diff --git a/target/loongarch/trace.h b/target/loongarch/trace.h
new file mode 100644
index 0000000000..c2ecb78f08
--- /dev/null
+++ b/target/loongarch/trace.h
@@ -0,0 +1 @@
+#include "trace/trace-target_loongarch.h"
--
2.27.0

View File

@ -0,0 +1,68 @@
From 3feeca228b010716aacdf7159df10ea63f7e34cd Mon Sep 17 00:00:00 2001
From: Tianrui Zhao <zhaotianrui@loongson.cn>
Date: Fri, 5 Jan 2024 15:58:02 +0800
Subject: [PATCH] target/loongarch: Implement kvm_arch_handle_exit
Implement kvm_arch_handle_exit for loongarch. In this
function, the KVM_EXIT_LOONGARCH_IOCSR is handled,
we read or write the iocsr address space by the addr,
length and is_write argument in kvm_run.
Signed-off-by: Tianrui Zhao <zhaotianrui@loongson.cn>
Signed-off-by: xianglai li <lixianglai@loongson.cn>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Song Gao <gaosong@loongson.cn>
Message-Id: <20240105075804.1228596-8-zhaotianrui@loongson.cn>
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
target/loongarch/kvm/kvm.c | 24 +++++++++++++++++++++++-
target/loongarch/trace-events | 1 +
2 files changed, 24 insertions(+), 1 deletion(-)
diff --git a/target/loongarch/kvm/kvm.c b/target/loongarch/kvm/kvm.c
index 85e7aeb083..d2dab3fef4 100644
--- a/target/loongarch/kvm/kvm.c
+++ b/target/loongarch/kvm/kvm.c
@@ -723,7 +723,29 @@ bool kvm_arch_cpu_check_are_resettable(void)
int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
{
- return 0;
+ int ret = 0;
+ LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+ CPULoongArchState *env = &cpu->env;
+ MemTxAttrs attrs = {};
+
+ attrs.requester_id = env_cpu(env)->cpu_index;
+
+ trace_kvm_arch_handle_exit(run->exit_reason);
+ switch (run->exit_reason) {
+ case KVM_EXIT_LOONGARCH_IOCSR:
+ address_space_rw(&env->address_space_iocsr,
+ run->iocsr_io.phys_addr,
+ attrs,
+ run->iocsr_io.data,
+ run->iocsr_io.len,
+ run->iocsr_io.is_write);
+ break;
+ default:
+ ret = -1;
+ warn_report("KVM: unknown exit reason %d", run->exit_reason);
+ break;
+ }
+ return ret;
}
void kvm_arch_accel_class_init(ObjectClass *oc)
diff --git a/target/loongarch/trace-events b/target/loongarch/trace-events
index 937c3c7c0c..021839880e 100644
--- a/target/loongarch/trace-events
+++ b/target/loongarch/trace-events
@@ -11,3 +11,4 @@ kvm_failed_get_counter(const char *msg) "Failed to get counter from KVM: %s"
kvm_failed_put_counter(const char *msg) "Failed to put counter into KVM: %s"
kvm_failed_get_cpucfg(const char *msg) "Failed to get cpucfg from KVM: %s"
kvm_failed_put_cpucfg(const char *msg) "Failed to put cpucfg into KVM: %s"
+kvm_arch_handle_exit(int num) "kvm arch handle exit, the reason number: %d"
--
2.27.0

View File

@ -0,0 +1,33 @@
From 3a87dbd5e0343ee777bac0f18888a5a2d51254db Mon Sep 17 00:00:00 2001
From: Tianrui Zhao <zhaotianrui@loongson.cn>
Date: Fri, 5 Jan 2024 15:58:00 +0800
Subject: [PATCH] target/loongarch: Implement kvm_arch_init function
Implement the kvm_arch_init of loongarch, in the function, the
KVM_CAP_MP_STATE cap is checked by kvm ioctl.
Signed-off-by: Tianrui Zhao <zhaotianrui@loongson.cn>
Signed-off-by: xianglai li <lixianglai@loongson.cn>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Song Gao <gaosong@loongson.cn>
Message-Id: <20240105075804.1228596-6-zhaotianrui@loongson.cn>
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
target/loongarch/kvm/kvm.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/target/loongarch/kvm/kvm.c b/target/loongarch/kvm/kvm.c
index e7c9ef830c..29944b9ef8 100644
--- a/target/loongarch/kvm/kvm.c
+++ b/target/loongarch/kvm/kvm.c
@@ -665,6 +665,7 @@ int kvm_arch_get_default_type(MachineState *ms)
int kvm_arch_init(MachineState *ms, KVMState *s)
{
+ cap_has_mp_state = kvm_check_extension(s, KVM_CAP_MP_STATE);
return 0;
}
--
2.27.0

View File

@ -0,0 +1,87 @@
From d7d47c044c9854675b75b91ade678d03316d9271 Mon Sep 17 00:00:00 2001
From: Tianrui Zhao <zhaotianrui@loongson.cn>
Date: Fri, 5 Jan 2024 15:58:01 +0800
Subject: [PATCH] target/loongarch: Implement kvm_arch_init_vcpu
Implement kvm_arch_init_vcpu interface for loongarch,
in this function, we register VM change state handler.
And when VM state changes to running, the counter value
should be put into kvm to keep consistent with kvm,
and when state change to stop, counter value should be
refreshed from kvm.
Signed-off-by: Tianrui Zhao <zhaotianrui@loongson.cn>
Signed-off-by: xianglai li <lixianglai@loongson.cn>
Reviewed-by: Song Gao <gaosong@loongson.cn>
Message-Id: <20240105075804.1228596-7-zhaotianrui@loongson.cn>
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
target/loongarch/cpu.h | 2 ++
target/loongarch/kvm/kvm.c | 23 +++++++++++++++++++++++
target/loongarch/trace-events | 2 ++
3 files changed, 27 insertions(+)
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index f4a89bd626..8ebd6fa1a7 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -381,6 +381,8 @@ struct ArchCPU {
/* 'compatible' string for this CPU for Linux device trees */
const char *dtb_compatible;
+ /* used by KVM_REG_LOONGARCH_COUNTER ioctl to access guest time counters */
+ uint64_t kvm_state_counter;
};
/**
diff --git a/target/loongarch/kvm/kvm.c b/target/loongarch/kvm/kvm.c
index 29944b9ef8..85e7aeb083 100644
--- a/target/loongarch/kvm/kvm.c
+++ b/target/loongarch/kvm/kvm.c
@@ -617,8 +617,31 @@ int kvm_arch_put_registers(CPUState *cs, int level)
return ret;
}
+static void kvm_loongarch_vm_stage_change(void *opaque, bool running,
+ RunState state)
+{
+ int ret;
+ CPUState *cs = opaque;
+ LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+
+ if (running) {
+ ret = kvm_set_one_reg(cs, KVM_REG_LOONGARCH_COUNTER,
+ &cpu->kvm_state_counter);
+ if (ret < 0) {
+ trace_kvm_failed_put_counter(strerror(errno));
+ }
+ } else {
+ ret = kvm_get_one_reg(cs, KVM_REG_LOONGARCH_COUNTER,
+ &cpu->kvm_state_counter);
+ if (ret < 0) {
+ trace_kvm_failed_get_counter(strerror(errno));
+ }
+ }
+}
+
int kvm_arch_init_vcpu(CPUState *cs)
{
+ qemu_add_vm_change_state_handler(kvm_loongarch_vm_stage_change, cs);
return 0;
}
diff --git a/target/loongarch/trace-events b/target/loongarch/trace-events
index 6827ab566a..937c3c7c0c 100644
--- a/target/loongarch/trace-events
+++ b/target/loongarch/trace-events
@@ -7,5 +7,7 @@ kvm_failed_get_fpu(const char *msg) "Failed to get fpu from KVM: %s"
kvm_failed_put_fpu(const char *msg) "Failed to put fpu into KVM: %s"
kvm_failed_get_mpstate(const char *msg) "Failed to get mp_state from KVM: %s"
kvm_failed_put_mpstate(const char *msg) "Failed to put mp_state into KVM: %s"
+kvm_failed_get_counter(const char *msg) "Failed to get counter from KVM: %s"
+kvm_failed_put_counter(const char *msg) "Failed to put counter into KVM: %s"
kvm_failed_get_cpucfg(const char *msg) "Failed to get cpucfg from KVM: %s"
kvm_failed_put_cpucfg(const char *msg) "Failed to put cpucfg into KVM: %s"
--
2.27.0

View File

@ -0,0 +1,122 @@
From 5f4c8b31db442e6ac39fbfe4b29d5479ab3567aa Mon Sep 17 00:00:00 2001
From: Tianrui Zhao <zhaotianrui@loongson.cn>
Date: Wed, 10 Jan 2024 10:41:52 +0100
Subject: [PATCH] target/loongarch: Implement set vcpu intr for kvm
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Implement loongarch kvm set vcpu interrupt interface,
when a irq is set in vcpu, we use the KVM_INTERRUPT
ioctl to set intr into kvm.
Signed-off-by: Tianrui Zhao <zhaotianrui@loongson.cn>
Signed-off-by: xianglai li <lixianglai@loongson.cn>
Reviewed-by: Song Gao <gaosong@loongson.cn>
Message-ID: <20240105075804.1228596-9-zhaotianrui@loongson.cn>
[PMD: Split from bigger patch, part 2]
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-Id: <20240110094152.52138-2-philmd@linaro.org>
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
target/loongarch/cpu.c | 9 ++++++++-
target/loongarch/kvm/kvm.c | 15 +++++++++++++++
target/loongarch/kvm/kvm_loongarch.h | 16 ++++++++++++++++
target/loongarch/trace-events | 1 +
4 files changed, 40 insertions(+), 1 deletion(-)
create mode 100644 target/loongarch/kvm/kvm_loongarch.h
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index 60f2636b43..413414392b 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -12,6 +12,8 @@
#include "qemu/module.h"
#include "sysemu/qtest.h"
#include "sysemu/tcg.h"
+#include "sysemu/kvm.h"
+#include "kvm/kvm_loongarch.h"
#include "exec/exec-all.h"
#include "cpu.h"
#include "internals.h"
@@ -19,6 +21,9 @@
#include "cpu-csr.h"
#include "sysemu/reset.h"
#include "vec.h"
+#ifdef CONFIG_KVM
+#include <linux/kvm.h>
+#endif
#ifdef CONFIG_TCG
#include "exec/cpu_ldst.h"
#include "tcg/tcg.h"
@@ -111,7 +116,9 @@ void loongarch_cpu_set_irq(void *opaque, int irq, int level)
return;
}
- if (tcg_enabled()) {
+ if (kvm_enabled()) {
+ kvm_loongarch_set_interrupt(cpu, irq, level);
+ } else if (tcg_enabled()) {
env->CSR_ESTAT = deposit64(env->CSR_ESTAT, irq, 1, level != 0);
if (FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, IS)) {
cpu_interrupt(cs, CPU_INTERRUPT_HARD);
diff --git a/target/loongarch/kvm/kvm.c b/target/loongarch/kvm/kvm.c
index d2dab3fef4..bd33ec2114 100644
--- a/target/loongarch/kvm/kvm.c
+++ b/target/loongarch/kvm/kvm.c
@@ -748,6 +748,21 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
return ret;
}
+int kvm_loongarch_set_interrupt(LoongArchCPU *cpu, int irq, int level)
+{
+ struct kvm_interrupt intr;
+ CPUState *cs = CPU(cpu);
+
+ if (level) {
+ intr.irq = irq;
+ } else {
+ intr.irq = -irq;
+ }
+
+ trace_kvm_set_intr(irq, level);
+ return kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &intr);
+}
+
void kvm_arch_accel_class_init(ObjectClass *oc)
{
}
diff --git a/target/loongarch/kvm/kvm_loongarch.h b/target/loongarch/kvm/kvm_loongarch.h
new file mode 100644
index 0000000000..d945b6bb82
--- /dev/null
+++ b/target/loongarch/kvm/kvm_loongarch.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * QEMU LoongArch kvm interface
+ *
+ * Copyright (c) 2023 Loongson Technology Corporation Limited
+ */
+
+#include "cpu.h"
+
+#ifndef QEMU_KVM_LOONGARCH_H
+#define QEMU_KVM_LOONGARCH_H
+
+int kvm_loongarch_set_interrupt(LoongArchCPU *cpu, int irq, int level);
+void kvm_arch_reset_vcpu(CPULoongArchState *env);
+
+#endif
diff --git a/target/loongarch/trace-events b/target/loongarch/trace-events
index 021839880e..dea11edc0f 100644
--- a/target/loongarch/trace-events
+++ b/target/loongarch/trace-events
@@ -12,3 +12,4 @@ kvm_failed_put_counter(const char *msg) "Failed to put counter into KVM: %s"
kvm_failed_get_cpucfg(const char *msg) "Failed to get cpucfg from KVM: %s"
kvm_failed_put_cpucfg(const char *msg) "Failed to put cpucfg into KVM: %s"
kvm_arch_handle_exit(int num) "kvm arch handle exit, the reason number: %d"
+kvm_set_intr(int irq, int level) "kvm set interrupt, irq num: %d, level: %d"
--
2.27.0

View File

@ -0,0 +1,152 @@
From 773ea71519da1413ca2e0e60857272164e156a47 Mon Sep 17 00:00:00 2001
From: Tianrui Zhao <zhaotianrui@loongson.cn>
Date: Wed, 10 Jan 2024 10:41:51 +0100
Subject: [PATCH] target/loongarch: Restrict TCG-specific code
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
In preparation of supporting KVM in the next commit.
Conflict:
diff --cc target/loongarch/cpu.c
index 275833eec8,70dd4622aa..0000000000
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@@ -17,9 -17,14 +17,17 @@@
#include "internals.h"
#include "fpu/softfloat-helpers.h"
#include "cpu-csr.h"
-#ifndef CONFIG_USER_ONLY
#include "sysemu/reset.h"
++<<<<<<< HEAD
+#include "tcg/tcg.h"
++=======
+ #endif
++>>>>>>> target/loongarch: Restrict TCG-specific code
#include "vec.h"
+ #ifdef CONFIG_TCG
+ #include "exec/cpu_ldst.h"
+ #include "tcg/tcg.h"
+ #endif
Solve:
drop:
++<<<<<<< HEAD
+#include "tcg/tcg.h"
++=======
+ #endif
++>>>>>>> target/loongarch: Restrict TCG-specific code
Signed-off-by: Tianrui Zhao <zhaotianrui@loongson.cn>
Signed-off-by: xianglai li <lixianglai@loongson.cn>
Reviewed-by: Song Gao <gaosong@loongson.cn>
Message-ID: <20240105075804.1228596-9-zhaotianrui@loongson.cn>
[PMD: Split from bigger patch, part 1]
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-Id: <20240110094152.52138-1-philmd@linaro.org>
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
target/loongarch/cpu.c | 30 +++++++++++++++++++++---------
1 file changed, 21 insertions(+), 9 deletions(-)
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index 275833eec8..60f2636b43 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -11,15 +11,18 @@
#include "qapi/error.h"
#include "qemu/module.h"
#include "sysemu/qtest.h"
-#include "exec/cpu_ldst.h"
+#include "sysemu/tcg.h"
#include "exec/exec-all.h"
#include "cpu.h"
#include "internals.h"
#include "fpu/softfloat-helpers.h"
#include "cpu-csr.h"
#include "sysemu/reset.h"
-#include "tcg/tcg.h"
#include "vec.h"
+#ifdef CONFIG_TCG
+#include "exec/cpu_ldst.h"
+#include "tcg/tcg.h"
+#endif
const char * const regnames[32] = {
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
@@ -108,12 +111,13 @@ void loongarch_cpu_set_irq(void *opaque, int irq, int level)
return;
}
- env->CSR_ESTAT = deposit64(env->CSR_ESTAT, irq, 1, level != 0);
-
- if (FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, IS)) {
- cpu_interrupt(cs, CPU_INTERRUPT_HARD);
- } else {
- cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
+ if (tcg_enabled()) {
+ env->CSR_ESTAT = deposit64(env->CSR_ESTAT, irq, 1, level != 0);
+ if (FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, IS)) {
+ cpu_interrupt(cs, CPU_INTERRUPT_HARD);
+ } else {
+ cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
+ }
}
}
@@ -138,7 +142,10 @@ static inline bool cpu_loongarch_hw_interrupts_pending(CPULoongArchState *env)
return (pending & status) != 0;
}
+#endif
+#ifdef CONFIG_TCG
+#ifndef CONFIG_USER_ONLY
static void loongarch_cpu_do_interrupt(CPUState *cs)
{
LoongArchCPU *cpu = LOONGARCH_CPU(cs);
@@ -320,7 +327,6 @@ static bool loongarch_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
}
#endif
-#ifdef CONFIG_TCG
static void loongarch_cpu_synchronize_from_tb(CPUState *cs,
const TranslationBlock *tb)
{
@@ -558,7 +564,9 @@ static void loongarch_cpu_reset_hold(Object *obj)
}
#endif
+#ifdef CONFIG_TCG
restore_fp_status(env);
+#endif
cs->exception_index = -1;
}
@@ -701,8 +709,10 @@ static void loongarch_cpu_init(Object *obj)
CPULoongArchState *env = &cpu->env;
qdev_init_gpio_in(DEVICE(cpu), loongarch_cpu_set_irq, N_IRQS);
+#ifdef CONFIG_TCG
timer_init_ns(&cpu->timer, QEMU_CLOCK_VIRTUAL,
&loongarch_constant_timer_cb, cpu);
+#endif
memory_region_init_io(&env->system_iocsr, OBJECT(cpu), NULL,
env, "iocsr", UINT64_MAX);
address_space_init(&env->address_space_iocsr, &env->system_iocsr, "IOCSR");
@@ -802,7 +812,9 @@ static struct TCGCPUOps loongarch_tcg_ops = {
#include "hw/core/sysemu-cpu-ops.h"
static const struct SysemuCPUOps loongarch_sysemu_ops = {
+#ifdef CONFIG_TCG
.get_phys_page_debug = loongarch_cpu_get_phys_page_debug,
+#endif
};
static int64_t loongarch_cpu_get_arch_id(CPUState *cs)
--
2.27.0

View File

@ -0,0 +1,57 @@
From d271f623205c2984a30cfb12e160e219b2bbe974 Mon Sep 17 00:00:00 2001
From: Bibo Mao <maobibo@loongson.cn>
Date: Mon, 15 Jan 2024 16:51:21 +0800
Subject: [PATCH] target/loongarch: Set cpuid CSR register only once with kvm
mode
CSR cpuid register is used for routing irq to different vcpus, its
value is kept unchanged since poweron. So it is not necessary to
set CSR cpuid register after system resets, and it is only set at
vm creation stage.
Signed-off-by: Bibo Mao <maobibo@loongson.cn>
Reviewed-by: Song Gao <gaosong@loongson.cn>
Message-Id: <20240115085121.180524-1-maobibo@loongson.cn>
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
target/loongarch/kvm/kvm.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/target/loongarch/kvm/kvm.c b/target/loongarch/kvm/kvm.c
index 84bcdf5f86..2230f029d0 100644
--- a/target/loongarch/kvm/kvm.c
+++ b/target/loongarch/kvm/kvm.c
@@ -250,7 +250,7 @@ static int kvm_loongarch_get_csr(CPUState *cs)
return ret;
}
-static int kvm_loongarch_put_csr(CPUState *cs)
+static int kvm_loongarch_put_csr(CPUState *cs, int level)
{
int ret = 0;
LoongArchCPU *cpu = LOONGARCH_CPU(cs);
@@ -322,8 +322,11 @@ static int kvm_loongarch_put_csr(CPUState *cs)
ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_RVACFG),
&env->CSR_RVACFG);
- ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_CPUID),
+ /* CPUID is constant after poweron, it should be set only once */
+ if (level >= KVM_PUT_FULL_STATE) {
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_CPUID),
&env->CSR_CPUID);
+ }
ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PRCFG1),
&env->CSR_PRCFG1);
@@ -598,7 +601,7 @@ int kvm_arch_put_registers(CPUState *cs, int level)
return ret;
}
- ret = kvm_loongarch_put_csr(cs);
+ ret = kvm_loongarch_put_csr(cs, level);
if (ret) {
return ret;
}
--
2.27.0

View File

@ -0,0 +1,59 @@
From 48dae5f461bf2cde206e879d52df6cf1bad3ac6e Mon Sep 17 00:00:00 2001
From: Tianrui Zhao <zhaotianrui@loongson.cn>
Date: Fri, 5 Jan 2024 15:57:58 +0800
Subject: [PATCH] target/loongarch: Supplement vcpu env initial when vcpu reset
Supplement vcpu env initial when vcpu reset, including
init vcpu CSR_CPUID,CSR_TID to cpu->cpu_index. The two
regs will be used in kvm_get/set_csr_ioctl.
Signed-off-by: Tianrui Zhao <zhaotianrui@loongson.cn>
Signed-off-by: xianglai li <lixianglai@loongson.cn>
Reviewed-by: Song Gao <gaosong@loongson.cn>
Message-Id: <20240105075804.1228596-4-zhaotianrui@loongson.cn>
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
target/loongarch/cpu.c | 2 ++
target/loongarch/cpu.h | 2 +-
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index db9a421cc4..021592798a 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -531,10 +531,12 @@ static void loongarch_cpu_reset_hold(Object *obj)
env->CSR_ESTAT = env->CSR_ESTAT & (~MAKE_64BIT_MASK(0, 2));
env->CSR_RVACFG = FIELD_DP64(env->CSR_RVACFG, CSR_RVACFG, RBITS, 0);
+ env->CSR_CPUID = cs->cpu_index;
env->CSR_TCFG = FIELD_DP64(env->CSR_TCFG, CSR_TCFG, EN, 0);
env->CSR_LLBCTL = FIELD_DP64(env->CSR_LLBCTL, CSR_LLBCTL, KLO, 0);
env->CSR_TLBRERA = FIELD_DP64(env->CSR_TLBRERA, CSR_TLBRERA, ISTLBR, 0);
env->CSR_MERRCTL = FIELD_DP64(env->CSR_MERRCTL, CSR_MERRCTL, ISMERR, 0);
+ env->CSR_TID = cs->cpu_index;
env->CSR_PRCFG3 = FIELD_DP64(env->CSR_PRCFG3, CSR_PRCFG3, TLB_TYPE, 2);
env->CSR_PRCFG3 = FIELD_DP64(env->CSR_PRCFG3, CSR_PRCFG3, MTLB_ENTRY, 63);
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index 00d1fba597..f6d5ef0852 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -319,6 +319,7 @@ typedef struct CPUArchState {
uint64_t CSR_PWCH;
uint64_t CSR_STLBPS;
uint64_t CSR_RVACFG;
+ uint64_t CSR_CPUID;
uint64_t CSR_PRCFG1;
uint64_t CSR_PRCFG2;
uint64_t CSR_PRCFG3;
@@ -350,7 +351,6 @@ typedef struct CPUArchState {
uint64_t CSR_DBG;
uint64_t CSR_DERA;
uint64_t CSR_DSAVE;
- uint64_t CSR_CPUID;
#ifndef CONFIG_USER_ONLY
LoongArchTLB tlb[LOONGARCH_TLB_MAX];
--
2.27.0

View File

@ -0,0 +1,98 @@
From 6e503b590e42ad7c522cf937b83e1f8f715dbd1a Mon Sep 17 00:00:00 2001
From: Song Gao <gaosong@loongson.cn>
Date: Mon, 22 Jan 2024 17:02:06 +0800
Subject: [PATCH] target/loongarch/kvm: Enable LSX/LASX extension
The kernel had already support LSX and LASX [1],
but QEMU is disable LSX/LASX for kvm. This patch adds
kvm_check_cpucfg2() to check CPUCFG2.
[1]: https://lore.kernel.org/all/CABgObfZHRf7E_7Jk4uPRmSyxTy3EiuuYwHC35jQncNL9s-zTDA@mail.gmail.com/
Signed-off-by: Song Gao <gaosong@loongson.cn>
Reviewed-by: Bibo Mao <maobibo@loongson.cn>
Message-Id: <20240122090206.1083584-1-gaosong@loongson.cn>
---
linux-headers/asm-loongarch/kvm.h | 1 +
target/loongarch/kvm/kvm.c | 45 ++++++++++++++++++++++++++-----
2 files changed, 39 insertions(+), 7 deletions(-)
diff --git a/linux-headers/asm-loongarch/kvm.h b/linux-headers/asm-loongarch/kvm.h
index c6ad2ee610..923d0bd382 100644
--- a/linux-headers/asm-loongarch/kvm.h
+++ b/linux-headers/asm-loongarch/kvm.h
@@ -79,6 +79,7 @@ struct kvm_fpu {
#define LOONGARCH_REG_64(TYPE, REG) (TYPE | KVM_REG_SIZE_U64 | (REG << LOONGARCH_REG_SHIFT))
#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
struct kvm_debug_exit_arch {
};
diff --git a/target/loongarch/kvm/kvm.c b/target/loongarch/kvm/kvm.c
index 2230f029d0..c19978a970 100644
--- a/target/loongarch/kvm/kvm.c
+++ b/target/loongarch/kvm/kvm.c
@@ -540,6 +540,38 @@ static int kvm_loongarch_get_cpucfg(CPUState *cs)
return ret;
}
+static int kvm_check_cpucfg2(CPUState *cs)
+{
+ int ret;
+ uint64_t val;
+ struct kvm_device_attr attr = {
+ .group = KVM_LOONGARCH_VCPU_CPUCFG,
+ .attr = 2,
+ .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);
+ env->cpucfg[2] &= val;
+
+ if (FIELD_EX32(env->cpucfg[2], CPUCFG2, FP)) {
+ /* The FP minimal version is 1. */
+ env->cpucfg[2] = FIELD_DP32(env->cpucfg[2], CPUCFG2, FP_VER, 1);
+ }
+
+ if (FIELD_EX32(env->cpucfg[2], CPUCFG2, LLFTP)) {
+ /* The LLFTP minimal version is 1. */
+ env->cpucfg[2] = FIELD_DP32(env->cpucfg[2], CPUCFG2, LLFTP_VER, 1);
+ }
+ }
+
+ return ret;
+}
+
static int kvm_loongarch_put_cpucfg(CPUState *cs)
{
int i, ret = 0;
@@ -548,14 +580,13 @@ static int kvm_loongarch_put_cpucfg(CPUState *cs)
uint64_t val;
for (i = 0; i < 21; i++) {
+ if (i == 2) {
+ ret = kvm_check_cpucfg2(cs);
+ if (ret) {
+ return ret;
+ }
+ }
val = env->cpucfg[i];
- /* LSX and LASX and LBT are not supported in kvm now */
- if (i == 2) {
- val &= ~(BIT(R_CPUCFG2_LSX_SHIFT) | BIT(R_CPUCFG2_LASX_SHIFT));
- val &= ~(BIT(R_CPUCFG2_LBT_X86_SHIFT) |
- BIT(R_CPUCFG2_LBT_ARM_SHIFT) |
- BIT(R_CPUCFG2_LBT_MIPS_SHIFT));
- }
ret = kvm_set_one_reg(cs, KVM_IOC_CPUCFG(i), &val);
if (ret < 0) {
trace_kvm_failed_put_cpucfg(strerror(errno));
--
2.27.0

View File

@ -0,0 +1,41 @@
From ae65e1281aa67713bde6bce323a3a8d06f27c636 Mon Sep 17 00:00:00 2001
From: Song Gao <gaosong@loongson.cn>
Date: Tue, 2 Jan 2024 10:01:59 +0800
Subject: [PATCH] target/loongarch/meson: move gdbstub.c to loongarch.ss
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
gdbstub.c is not specific to TCG and can be used by
other accelerators, such as KVM accelerator
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Song Gao <gaosong@loongson.cn>
Message-Id: <20240102020200.3462097-1-gaosong@loongson.cn>
---
target/loongarch/meson.build | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/target/loongarch/meson.build b/target/loongarch/meson.build
index 18e8191e2b..b3a0fb12fb 100644
--- a/target/loongarch/meson.build
+++ b/target/loongarch/meson.build
@@ -3,6 +3,7 @@ gen = decodetree.process('insns.decode')
loongarch_ss = ss.source_set()
loongarch_ss.add(files(
'cpu.c',
+ 'gdbstub.c',
))
loongarch_tcg_ss = ss.source_set()
loongarch_tcg_ss.add(gen)
@@ -10,7 +11,6 @@ loongarch_tcg_ss.add(files(
'fpu_helper.c',
'op_helper.c',
'translate.c',
- 'gdbstub.c',
'vec_helper.c',
))
loongarch_tcg_ss.add(zlib)
--
2.27.0

View File

@ -0,0 +1,215 @@
From eef77dd5b0d292d8a0276c820fc8fee24de0d898 Mon Sep 17 00:00:00 2001
From: Song Gao <gaosong@loongson.cn>
Date: Tue, 2 Jan 2024 10:02:00 +0800
Subject: [PATCH] target/loongarch: move translate modules to tcg/
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Introduce the target/loongarch/tcg directory. Its purpose is to hold the TCG
code that is selected by CONFIG_TCG
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Song Gao <gaosong@loongson.cn>
Message-Id: <20240102020200.3462097-2-gaosong@loongson.cn>
---
target/loongarch/meson.build | 15 +--------------
target/loongarch/{ => tcg}/constant_timer.c | 0
target/loongarch/{ => tcg}/csr_helper.c | 0
target/loongarch/{ => tcg}/fpu_helper.c | 0
.../{ => tcg}/insn_trans/trans_arith.c.inc | 0
.../{ => tcg}/insn_trans/trans_atomic.c.inc | 0
.../{ => tcg}/insn_trans/trans_bit.c.inc | 0
.../{ => tcg}/insn_trans/trans_branch.c.inc | 0
.../{ => tcg}/insn_trans/trans_extra.c.inc | 0
.../{ => tcg}/insn_trans/trans_farith.c.inc | 0
.../{ => tcg}/insn_trans/trans_fcmp.c.inc | 0
.../{ => tcg}/insn_trans/trans_fcnv.c.inc | 0
.../{ => tcg}/insn_trans/trans_fmemory.c.inc | 0
.../{ => tcg}/insn_trans/trans_fmov.c.inc | 0
.../{ => tcg}/insn_trans/trans_memory.c.inc | 0
.../insn_trans/trans_privileged.c.inc | 0
.../{ => tcg}/insn_trans/trans_shift.c.inc | 0
.../{ => tcg}/insn_trans/trans_vec.c.inc | 0
target/loongarch/{ => tcg}/iocsr_helper.c | 0
target/loongarch/tcg/meson.build | 19 +++++++++++++++++++
target/loongarch/{ => tcg}/op_helper.c | 0
target/loongarch/{ => tcg}/tlb_helper.c | 0
target/loongarch/{ => tcg}/translate.c | 0
target/loongarch/{ => tcg}/vec_helper.c | 0
24 files changed, 20 insertions(+), 14 deletions(-)
rename target/loongarch/{ => tcg}/constant_timer.c (100%)
rename target/loongarch/{ => tcg}/csr_helper.c (100%)
rename target/loongarch/{ => tcg}/fpu_helper.c (100%)
rename target/loongarch/{ => tcg}/insn_trans/trans_arith.c.inc (100%)
rename target/loongarch/{ => tcg}/insn_trans/trans_atomic.c.inc (100%)
rename target/loongarch/{ => tcg}/insn_trans/trans_bit.c.inc (100%)
rename target/loongarch/{ => tcg}/insn_trans/trans_branch.c.inc (100%)
rename target/loongarch/{ => tcg}/insn_trans/trans_extra.c.inc (100%)
rename target/loongarch/{ => tcg}/insn_trans/trans_farith.c.inc (100%)
rename target/loongarch/{ => tcg}/insn_trans/trans_fcmp.c.inc (100%)
rename target/loongarch/{ => tcg}/insn_trans/trans_fcnv.c.inc (100%)
rename target/loongarch/{ => tcg}/insn_trans/trans_fmemory.c.inc (100%)
rename target/loongarch/{ => tcg}/insn_trans/trans_fmov.c.inc (100%)
rename target/loongarch/{ => tcg}/insn_trans/trans_memory.c.inc (100%)
rename target/loongarch/{ => tcg}/insn_trans/trans_privileged.c.inc (100%)
rename target/loongarch/{ => tcg}/insn_trans/trans_shift.c.inc (100%)
rename target/loongarch/{ => tcg}/insn_trans/trans_vec.c.inc (100%)
rename target/loongarch/{ => tcg}/iocsr_helper.c (100%)
create mode 100644 target/loongarch/tcg/meson.build
rename target/loongarch/{ => tcg}/op_helper.c (100%)
rename target/loongarch/{ => tcg}/tlb_helper.c (100%)
rename target/loongarch/{ => tcg}/translate.c (100%)
rename target/loongarch/{ => tcg}/vec_helper.c (100%)
diff --git a/target/loongarch/meson.build b/target/loongarch/meson.build
index b3a0fb12fb..e84e4c51f4 100644
--- a/target/loongarch/meson.build
+++ b/target/loongarch/meson.build
@@ -5,29 +5,16 @@ loongarch_ss.add(files(
'cpu.c',
'gdbstub.c',
))
-loongarch_tcg_ss = ss.source_set()
-loongarch_tcg_ss.add(gen)
-loongarch_tcg_ss.add(files(
- 'fpu_helper.c',
- 'op_helper.c',
- 'translate.c',
- 'vec_helper.c',
-))
-loongarch_tcg_ss.add(zlib)
loongarch_system_ss = ss.source_set()
loongarch_system_ss.add(files(
'loongarch-qmp-cmds.c',
'machine.c',
- 'tlb_helper.c',
- 'constant_timer.c',
- 'csr_helper.c',
- 'iocsr_helper.c',
))
common_ss.add(when: 'CONFIG_LOONGARCH_DIS', if_true: [files('disas.c'), gen])
-loongarch_ss.add_all(when: 'CONFIG_TCG', if_true: [loongarch_tcg_ss])
+subdir('tcg')
target_arch += {'loongarch': loongarch_ss}
target_system_arch += {'loongarch': loongarch_system_ss}
diff --git a/target/loongarch/constant_timer.c b/target/loongarch/tcg/constant_timer.c
similarity index 100%
rename from target/loongarch/constant_timer.c
rename to target/loongarch/tcg/constant_timer.c
diff --git a/target/loongarch/csr_helper.c b/target/loongarch/tcg/csr_helper.c
similarity index 100%
rename from target/loongarch/csr_helper.c
rename to target/loongarch/tcg/csr_helper.c
diff --git a/target/loongarch/fpu_helper.c b/target/loongarch/tcg/fpu_helper.c
similarity index 100%
rename from target/loongarch/fpu_helper.c
rename to target/loongarch/tcg/fpu_helper.c
diff --git a/target/loongarch/insn_trans/trans_arith.c.inc b/target/loongarch/tcg/insn_trans/trans_arith.c.inc
similarity index 100%
rename from target/loongarch/insn_trans/trans_arith.c.inc
rename to target/loongarch/tcg/insn_trans/trans_arith.c.inc
diff --git a/target/loongarch/insn_trans/trans_atomic.c.inc b/target/loongarch/tcg/insn_trans/trans_atomic.c.inc
similarity index 100%
rename from target/loongarch/insn_trans/trans_atomic.c.inc
rename to target/loongarch/tcg/insn_trans/trans_atomic.c.inc
diff --git a/target/loongarch/insn_trans/trans_bit.c.inc b/target/loongarch/tcg/insn_trans/trans_bit.c.inc
similarity index 100%
rename from target/loongarch/insn_trans/trans_bit.c.inc
rename to target/loongarch/tcg/insn_trans/trans_bit.c.inc
diff --git a/target/loongarch/insn_trans/trans_branch.c.inc b/target/loongarch/tcg/insn_trans/trans_branch.c.inc
similarity index 100%
rename from target/loongarch/insn_trans/trans_branch.c.inc
rename to target/loongarch/tcg/insn_trans/trans_branch.c.inc
diff --git a/target/loongarch/insn_trans/trans_extra.c.inc b/target/loongarch/tcg/insn_trans/trans_extra.c.inc
similarity index 100%
rename from target/loongarch/insn_trans/trans_extra.c.inc
rename to target/loongarch/tcg/insn_trans/trans_extra.c.inc
diff --git a/target/loongarch/insn_trans/trans_farith.c.inc b/target/loongarch/tcg/insn_trans/trans_farith.c.inc
similarity index 100%
rename from target/loongarch/insn_trans/trans_farith.c.inc
rename to target/loongarch/tcg/insn_trans/trans_farith.c.inc
diff --git a/target/loongarch/insn_trans/trans_fcmp.c.inc b/target/loongarch/tcg/insn_trans/trans_fcmp.c.inc
similarity index 100%
rename from target/loongarch/insn_trans/trans_fcmp.c.inc
rename to target/loongarch/tcg/insn_trans/trans_fcmp.c.inc
diff --git a/target/loongarch/insn_trans/trans_fcnv.c.inc b/target/loongarch/tcg/insn_trans/trans_fcnv.c.inc
similarity index 100%
rename from target/loongarch/insn_trans/trans_fcnv.c.inc
rename to target/loongarch/tcg/insn_trans/trans_fcnv.c.inc
diff --git a/target/loongarch/insn_trans/trans_fmemory.c.inc b/target/loongarch/tcg/insn_trans/trans_fmemory.c.inc
similarity index 100%
rename from target/loongarch/insn_trans/trans_fmemory.c.inc
rename to target/loongarch/tcg/insn_trans/trans_fmemory.c.inc
diff --git a/target/loongarch/insn_trans/trans_fmov.c.inc b/target/loongarch/tcg/insn_trans/trans_fmov.c.inc
similarity index 100%
rename from target/loongarch/insn_trans/trans_fmov.c.inc
rename to target/loongarch/tcg/insn_trans/trans_fmov.c.inc
diff --git a/target/loongarch/insn_trans/trans_memory.c.inc b/target/loongarch/tcg/insn_trans/trans_memory.c.inc
similarity index 100%
rename from target/loongarch/insn_trans/trans_memory.c.inc
rename to target/loongarch/tcg/insn_trans/trans_memory.c.inc
diff --git a/target/loongarch/insn_trans/trans_privileged.c.inc b/target/loongarch/tcg/insn_trans/trans_privileged.c.inc
similarity index 100%
rename from target/loongarch/insn_trans/trans_privileged.c.inc
rename to target/loongarch/tcg/insn_trans/trans_privileged.c.inc
diff --git a/target/loongarch/insn_trans/trans_shift.c.inc b/target/loongarch/tcg/insn_trans/trans_shift.c.inc
similarity index 100%
rename from target/loongarch/insn_trans/trans_shift.c.inc
rename to target/loongarch/tcg/insn_trans/trans_shift.c.inc
diff --git a/target/loongarch/insn_trans/trans_vec.c.inc b/target/loongarch/tcg/insn_trans/trans_vec.c.inc
similarity index 100%
rename from target/loongarch/insn_trans/trans_vec.c.inc
rename to target/loongarch/tcg/insn_trans/trans_vec.c.inc
diff --git a/target/loongarch/iocsr_helper.c b/target/loongarch/tcg/iocsr_helper.c
similarity index 100%
rename from target/loongarch/iocsr_helper.c
rename to target/loongarch/tcg/iocsr_helper.c
diff --git a/target/loongarch/tcg/meson.build b/target/loongarch/tcg/meson.build
new file mode 100644
index 0000000000..1a3cd589fb
--- /dev/null
+++ b/target/loongarch/tcg/meson.build
@@ -0,0 +1,19 @@
+if 'CONFIG_TCG' not in config_all
+ subdir_done()
+endif
+
+loongarch_ss.add([zlib, gen])
+
+loongarch_ss.add(files(
+ 'fpu_helper.c',
+ 'op_helper.c',
+ 'translate.c',
+ 'vec_helper.c',
+))
+
+loongarch_system_ss.add(files(
+ 'constant_timer.c',
+ 'csr_helper.c',
+ 'iocsr_helper.c',
+ 'tlb_helper.c',
+))
diff --git a/target/loongarch/op_helper.c b/target/loongarch/tcg/op_helper.c
similarity index 100%
rename from target/loongarch/op_helper.c
rename to target/loongarch/tcg/op_helper.c
diff --git a/target/loongarch/tlb_helper.c b/target/loongarch/tcg/tlb_helper.c
similarity index 100%
rename from target/loongarch/tlb_helper.c
rename to target/loongarch/tcg/tlb_helper.c
diff --git a/target/loongarch/translate.c b/target/loongarch/tcg/translate.c
similarity index 100%
rename from target/loongarch/translate.c
rename to target/loongarch/tcg/translate.c
diff --git a/target/loongarch/vec_helper.c b/target/loongarch/tcg/vec_helper.c
similarity index 100%
rename from target/loongarch/vec_helper.c
rename to target/loongarch/tcg/vec_helper.c
--
2.27.0