1
The following changes since commit bfe8020c814a30479a4241aaa78b63960655962b:
1
The following changes since commit 38d0939b86e2eef6f6a622c6f1f7befda0146595:
2
2
3
Merge tag 'for-upstream' of https://gitlab.com/bonzini/qemu into staging (2024-02-28 14:23:21 +0000)
3
Merge tag 'pull-vfio-20241226' of https://github.com/legoater/qemu into staging (2024-12-26 04:38:38 -0500)
4
4
5
are available in the Git repository at:
5
are available in the Git repository at:
6
6
7
https://gitlab.com/gaosong/qemu.git tags/pull-loongarch-20240229
7
https://gitlab.com/bibo-mao/qemu.git tags/pull-loongarch-20241227
8
8
9
for you to fetch changes up to c6e9847fc4becba561c631c4505e3b05d4926184:
9
for you to fetch changes up to 5e360dabedb1ab1f15cce27a134ccbe4b8e18424:
10
10
11
loongarch: Change the UEFI loading mode to loongarch (2024-02-29 19:32:45 +0800)
11
target/loongarch: Use auto method with LASX feature (2024-12-27 11:33:06 +0800)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
pull-loongarch-20240229
14
pull-loongarch-20241227
15
15
v1 ... v2
16
V2: fix build error on mipsel
16
1. Modify patch auther inconsistent with SOB
17
17
18
----------------------------------------------------------------
18
----------------------------------------------------------------
19
Xianglai Li (1):
19
Bibo Mao (5):
20
loongarch: Change the UEFI loading mode to loongarch
20
target/loongarch: Use actual operand size with vbsrl check
21
hw/loongarch/virt: Create fdt table on machine creation done notification
22
hw/loongarch/virt: Improve fdt table creation for CPU object
23
target/loongarch: Use auto method with LSX feature
24
target/loongarch: Use auto method with LASX feature
21
25
22
hw/loongarch/acpi-build.c | 29 +++++++++++--
26
Guo Hongyu (1):
23
hw/loongarch/virt.c | 101 ++++++++++++++++++++++++++++++++------------
27
target/loongarch: Fix vldi inst
24
include/hw/loongarch/virt.h | 10 +++--
28
25
3 files changed, 107 insertions(+), 33 deletions(-)
29
hw/loongarch/virt.c | 142 ++++++++++++++----------
30
target/loongarch/cpu.c | 86 ++++++++------
31
target/loongarch/cpu.h | 4 +
32
target/loongarch/kvm/kvm.c | 107 ++++++++++++++++++
33
target/loongarch/tcg/insn_trans/trans_vec.c.inc | 4 +-
34
5 files changed, 249 insertions(+), 94 deletions(-)
diff view generated by jsdifflib
New patch
1
From: Guo Hongyu <guohongyu24@mails.ucas.ac.cn>
1
2
3
Refer to the link below for a description of the vldi instructions:
4
https://jia.je/unofficial-loongarch-intrinsics-guide/lsx/misc/#synopsis_88
5
Fixed errors in vldi instruction implementation.
6
7
Signed-off-by: Guo Hongyu <guohongyu24@mails.ucas.ac.cn>
8
Tested-by: Xianglai Li <lixianglai@loongson.cn>
9
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
10
Reviewed-by: Bibo Mao <maobibo@loongson.cn>
11
Signed-off-by: Bibo Mao <maobibo@loongson.cn>
12
---
13
target/loongarch/tcg/insn_trans/trans_vec.c.inc | 2 +-
14
1 file changed, 1 insertion(+), 1 deletion(-)
15
16
diff --git a/target/loongarch/tcg/insn_trans/trans_vec.c.inc b/target/loongarch/tcg/insn_trans/trans_vec.c.inc
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/loongarch/tcg/insn_trans/trans_vec.c.inc
19
+++ b/target/loongarch/tcg/insn_trans/trans_vec.c.inc
20
@@ -XXX,XX +XXX,XX @@ static uint64_t vldi_get_value(DisasContext *ctx, uint32_t imm)
21
break;
22
case 1:
23
/* data: {2{16'0, imm[7:0], 8'0}} */
24
- data = (t << 24) | (t << 8);
25
+ data = (t << 40) | (t << 8);
26
break;
27
case 2:
28
/* data: {2{8'0, imm[7:0], 16'0}} */
29
--
30
2.43.5
diff view generated by jsdifflib
New patch
1
Hardcoded 32 bytes is used for vbsrl emulation check, there is
2
problem when options lsx=on,lasx=off is used for vbsrl.v instruction
3
in TCG mode. It injects LASX exception rather LSX exception.
1
4
5
Here actual operand size is used.
6
7
Cc: qemu-stable@nongnu.org
8
Fixes: df97f338076 ("target/loongarch: Implement xvreplve xvinsve0 xvpickve")
9
Signed-off-by: Bibo Mao <maobibo@loongson.cn>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
12
---
13
target/loongarch/tcg/insn_trans/trans_vec.c.inc | 2 +-
14
1 file changed, 1 insertion(+), 1 deletion(-)
15
16
diff --git a/target/loongarch/tcg/insn_trans/trans_vec.c.inc b/target/loongarch/tcg/insn_trans/trans_vec.c.inc
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/loongarch/tcg/insn_trans/trans_vec.c.inc
19
+++ b/target/loongarch/tcg/insn_trans/trans_vec.c.inc
20
@@ -XXX,XX +XXX,XX @@ static bool do_vbsrl_v(DisasContext *ctx, arg_vv_i *a, uint32_t oprsz)
21
{
22
int i, ofs;
23
24
- if (!check_vec(ctx, 32)) {
25
+ if (!check_vec(ctx, oprsz)) {
26
return true;
27
}
28
29
--
30
2.43.5
31
32
diff view generated by jsdifflib
New patch
1
The same with ACPI table, fdt table is created on machine done
2
notification. Some objects like CPU objects can be created with cold-plug
3
method with command such as -smp x, -device la464-loongarch-cpu, so all
4
objects finish to create when machine is done.
1
5
6
Signed-off-by: Bibo Mao <maobibo@loongson.cn>
7
Reviewed-by: Bibo Mao <maobibo@loongson.cn>
8
---
9
hw/loongarch/virt.c | 103 ++++++++++++++++++++++++--------------------
10
1 file changed, 57 insertions(+), 46 deletions(-)
11
12
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/loongarch/virt.c
15
+++ b/hw/loongarch/virt.c
16
@@ -XXX,XX +XXX,XX @@ static void virt_build_smbios(LoongArchVirtMachineState *lvms)
17
}
18
}
19
20
+static void virt_fdt_setup(LoongArchVirtMachineState *lvms)
21
+{
22
+ MachineState *machine = MACHINE(lvms);
23
+ uint32_t cpuintc_phandle, eiointc_phandle, pch_pic_phandle, pch_msi_phandle;
24
+ int i;
25
+
26
+ create_fdt(lvms);
27
+ fdt_add_cpu_nodes(lvms);
28
+ fdt_add_memory_nodes(machine);
29
+ fdt_add_fw_cfg_node(lvms);
30
+ fdt_add_flash_node(lvms);
31
+
32
+ /* Add cpu interrupt-controller */
33
+ fdt_add_cpuic_node(lvms, &cpuintc_phandle);
34
+ /* Add Extend I/O Interrupt Controller node */
35
+ fdt_add_eiointc_node(lvms, &cpuintc_phandle, &eiointc_phandle);
36
+ /* Add PCH PIC node */
37
+ fdt_add_pch_pic_node(lvms, &eiointc_phandle, &pch_pic_phandle);
38
+ /* Add PCH MSI node */
39
+ fdt_add_pch_msi_node(lvms, &eiointc_phandle, &pch_msi_phandle);
40
+ /* Add pcie node */
41
+ fdt_add_pcie_node(lvms, &pch_pic_phandle, &pch_msi_phandle);
42
+
43
+ /*
44
+ * Create uart fdt node in reverse order so that they appear
45
+ * in the finished device tree lowest address first
46
+ */
47
+ for (i = VIRT_UART_COUNT; i-- > 0;) {
48
+ hwaddr base = VIRT_UART_BASE + i * VIRT_UART_SIZE;
49
+ int irq = VIRT_UART_IRQ + i - VIRT_GSI_BASE;
50
+ fdt_add_uart_node(lvms, &pch_pic_phandle, base, irq, i == 0);
51
+ }
52
+
53
+ fdt_add_rtc_node(lvms, &pch_pic_phandle);
54
+ fdt_add_ged_reset(lvms);
55
+ platform_bus_add_all_fdt_nodes(machine->fdt, "/platic",
56
+ VIRT_PLATFORM_BUS_BASEADDRESS,
57
+ VIRT_PLATFORM_BUS_SIZE,
58
+ VIRT_PLATFORM_BUS_IRQ);
59
+
60
+ /*
61
+ * Since lowmem region starts from 0 and Linux kernel legacy start address
62
+ * at 2 MiB, FDT base address is located at 1 MiB to avoid NULL pointer
63
+ * access. FDT size limit with 1 MiB.
64
+ * Put the FDT into the memory map as a ROM image: this will ensure
65
+ * the FDT is copied again upon reset, even if addr points into RAM.
66
+ */
67
+ qemu_fdt_dumpdtb(machine->fdt, lvms->fdt_size);
68
+ rom_add_blob_fixed_as("fdt", machine->fdt, lvms->fdt_size, FDT_BASE,
69
+ &address_space_memory);
70
+ qemu_register_reset_nosnapshotload(qemu_fdt_randomize_seeds,
71
+ rom_ptr_for_as(&address_space_memory, FDT_BASE, lvms->fdt_size));
72
+}
73
+
74
static void virt_done(Notifier *notifier, void *data)
75
{
76
LoongArchVirtMachineState *lvms = container_of(notifier,
77
LoongArchVirtMachineState, machine_done);
78
virt_build_smbios(lvms);
79
loongarch_acpi_setup(lvms);
80
+ virt_fdt_setup(lvms);
81
}
82
83
static void virt_powerdown_req(Notifier *notifier, void *opaque)
84
@@ -XXX,XX +XXX,XX @@ static DeviceState *create_platform_bus(DeviceState *pch_pic)
85
}
86
87
static void virt_devices_init(DeviceState *pch_pic,
88
- LoongArchVirtMachineState *lvms,
89
- uint32_t *pch_pic_phandle,
90
- uint32_t *pch_msi_phandle)
91
+ LoongArchVirtMachineState *lvms)
92
{
93
MachineClass *mc = MACHINE_GET_CLASS(lvms);
94
DeviceState *gpex_dev;
95
@@ -XXX,XX +XXX,XX @@ static void virt_devices_init(DeviceState *pch_pic,
96
gpex_set_irq_num(GPEX_HOST(gpex_dev), i, 16 + i);
97
}
98
99
- /* Add pcie node */
100
- fdt_add_pcie_node(lvms, pch_pic_phandle, pch_msi_phandle);
101
-
102
/*
103
* Create uart fdt node in reverse order so that they appear
104
* in the finished device tree lowest address first
105
@@ -XXX,XX +XXX,XX @@ static void virt_devices_init(DeviceState *pch_pic,
106
serial_mm_init(get_system_memory(), base, 0,
107
qdev_get_gpio_in(pch_pic, irq),
108
115200, serial_hd(i), DEVICE_LITTLE_ENDIAN);
109
- fdt_add_uart_node(lvms, pch_pic_phandle, base, irq, i == 0);
110
}
111
112
/* Network init */
113
@@ -XXX,XX +XXX,XX @@ static void virt_devices_init(DeviceState *pch_pic,
114
sysbus_create_simple("ls7a_rtc", VIRT_RTC_REG_BASE,
115
qdev_get_gpio_in(pch_pic,
116
VIRT_RTC_IRQ - VIRT_GSI_BASE));
117
- fdt_add_rtc_node(lvms, pch_pic_phandle);
118
- fdt_add_ged_reset(lvms);
119
120
/* acpi ged */
121
lvms->acpi_ged = create_acpi_ged(pch_pic, lvms);
122
@@ -XXX,XX +XXX,XX @@ static void virt_irq_init(LoongArchVirtMachineState *lvms)
123
CPULoongArchState *env;
124
CPUState *cpu_state;
125
int cpu, pin, i, start, num;
126
- uint32_t cpuintc_phandle, eiointc_phandle, pch_pic_phandle, pch_msi_phandle;
127
128
/*
129
* Extended IRQ model.
130
@@ -XXX,XX +XXX,XX @@ static void virt_irq_init(LoongArchVirtMachineState *lvms)
131
memory_region_add_subregion(&lvms->system_iocsr, MAIL_SEND_ADDR,
132
sysbus_mmio_get_region(SYS_BUS_DEVICE(ipi), 1));
133
134
- /* Add cpu interrupt-controller */
135
- fdt_add_cpuic_node(lvms, &cpuintc_phandle);
136
-
137
for (cpu = 0; cpu < ms->smp.cpus; cpu++) {
138
cpu_state = qemu_get_cpu(cpu);
139
cpudev = DEVICE(cpu_state);
140
@@ -XXX,XX +XXX,XX @@ static void virt_irq_init(LoongArchVirtMachineState *lvms)
141
}
142
}
143
144
- /* Add Extend I/O Interrupt Controller node */
145
- fdt_add_eiointc_node(lvms, &cpuintc_phandle, &eiointc_phandle);
146
-
147
pch_pic = qdev_new(TYPE_LOONGARCH_PIC);
148
num = VIRT_PCH_PIC_IRQ_NUM;
149
qdev_prop_set_uint32(pch_pic, "pch_pic_irq_num", num);
150
@@ -XXX,XX +XXX,XX @@ static void virt_irq_init(LoongArchVirtMachineState *lvms)
151
qdev_connect_gpio_out(DEVICE(d), i, qdev_get_gpio_in(extioi, i));
152
}
153
154
- /* Add PCH PIC node */
155
- fdt_add_pch_pic_node(lvms, &eiointc_phandle, &pch_pic_phandle);
156
-
157
pch_msi = qdev_new(TYPE_LOONGARCH_PCH_MSI);
158
start = num;
159
num = EXTIOI_IRQS - start;
160
@@ -XXX,XX +XXX,XX @@ static void virt_irq_init(LoongArchVirtMachineState *lvms)
161
qdev_get_gpio_in(extioi, i + start));
162
}
163
164
- /* Add PCH MSI node */
165
- fdt_add_pch_msi_node(lvms, &eiointc_phandle, &pch_msi_phandle);
166
-
167
- virt_devices_init(pch_pic, lvms, &pch_pic_phandle, &pch_msi_phandle);
168
+ virt_devices_init(pch_pic, lvms);
169
}
170
171
static void virt_firmware_init(LoongArchVirtMachineState *lvms)
172
@@ -XXX,XX +XXX,XX @@ static void virt_init(MachineState *machine)
173
cpu_model = LOONGARCH_CPU_TYPE_NAME("la464");
174
}
175
176
- create_fdt(lvms);
177
-
178
/* Create IOCSR space */
179
memory_region_init_io(&lvms->system_iocsr, OBJECT(machine), NULL,
180
machine, "iocsr", UINT64_MAX);
181
@@ -XXX,XX +XXX,XX @@ static void virt_init(MachineState *machine)
182
lacpu = LOONGARCH_CPU(cpu);
183
lacpu->phy_id = machine->possible_cpus->cpus[i].arch_id;
184
}
185
- fdt_add_cpu_nodes(lvms);
186
- fdt_add_memory_nodes(machine);
187
fw_cfg_add_memory(machine);
188
189
/* Node0 memory */
190
@@ -XXX,XX +XXX,XX @@ static void virt_init(MachineState *machine)
191
memmap_table,
192
sizeof(struct memmap_entry) * (memmap_entries));
193
}
194
- fdt_add_fw_cfg_node(lvms);
195
- fdt_add_flash_node(lvms);
196
197
/* Initialize the IO interrupt subsystem */
198
virt_irq_init(lvms);
199
- platform_bus_add_all_fdt_nodes(machine->fdt, "/platic",
200
- VIRT_PLATFORM_BUS_BASEADDRESS,
201
- VIRT_PLATFORM_BUS_SIZE,
202
- VIRT_PLATFORM_BUS_IRQ);
203
lvms->machine_done.notify = virt_done;
204
qemu_add_machine_init_done_notifier(&lvms->machine_done);
205
/* connect powerdown request */
206
lvms->powerdown_notifier.notify = virt_powerdown_req;
207
qemu_register_powerdown_notifier(&lvms->powerdown_notifier);
208
209
- /*
210
- * Since lowmem region starts from 0 and Linux kernel legacy start address
211
- * at 2 MiB, FDT base address is located at 1 MiB to avoid NULL pointer
212
- * access. FDT size limit with 1 MiB.
213
- * Put the FDT into the memory map as a ROM image: this will ensure
214
- * the FDT is copied again upon reset, even if addr points into RAM.
215
- */
216
- qemu_fdt_dumpdtb(machine->fdt, lvms->fdt_size);
217
- rom_add_blob_fixed_as("fdt", machine->fdt, lvms->fdt_size, FDT_BASE,
218
- &address_space_memory);
219
- qemu_register_reset_nosnapshotload(qemu_fdt_randomize_seeds,
220
- rom_ptr_for_as(&address_space_memory, FDT_BASE, lvms->fdt_size));
221
-
222
lvms->bootinfo.ram_size = ram_size;
223
loongarch_load_kernel(machine, &lvms->bootinfo);
224
}
225
--
226
2.43.5
diff view generated by jsdifflib
1
From: Xianglai Li <lixianglai@loongson.cn>
1
For CPU object, possible_cpu_arch_ids() function is used rather than
2
smp.cpus. With command -smp x, -device la464-loongarch-cpu, smp.cpus
3
is not accurate for all possible CPU objects, possible_cpu_arch_ids()
4
is used here.
2
5
3
The UEFI loading mode in loongarch is very different
6
Signed-off-by: Bibo Mao <maobibo@loongson.cn>
4
from that in other architectures:loongarch's UEFI code
7
Reviewed-by: Bibo Mao <maobibo@loongson.cn>
5
is in rom, while other architectures' UEFI code is in flash.
8
---
9
hw/loongarch/virt.c | 39 +++++++++++++++++++++++++--------------
10
1 file changed, 25 insertions(+), 14 deletions(-)
6
11
7
loongarch UEFI can be loaded as follows:
8
-machine virt,pflash=pflash0-format
9
-bios ./QEMU_EFI.fd
10
11
Other architectures load UEFI using the following methods:
12
-machine virt,pflash0=pflash0-format,pflash1=pflash1-format
13
14
loongarch's UEFI loading method makes qemu and libvirt incompatible
15
when using NVRAM, and the cost of loongarch's current loading method
16
far outweighs the benefits, so we decided to use the same UEFI loading
17
scheme as other architectures.
18
19
Cc: Andrea Bolognani <abologna@redhat.com>
20
Cc: maobibo@loongson.cn
21
Cc: Philippe Mathieu-Daudé <philmd@linaro.org>
22
Cc: Song Gao <gaosong@loongson.cn>
23
Cc: zhaotianrui@loongson.cn
24
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
25
Tested-by: Andrea Bolognani <abologna@redhat.com>
26
Reviewed-by: Song Gao <gaosong@loongson.cn>
27
Message-Id: <0bd892aa9b88e0f4cc904cb70efd0251fc1cde29.1708336919.git.lixianglai@loongson.cn>
28
Signed-off-by: Song Gao <gaosong@loongson.cn>
29
---
30
hw/loongarch/acpi-build.c | 29 +++++++++--
31
hw/loongarch/virt.c | 101 ++++++++++++++++++++++++++----------
32
include/hw/loongarch/virt.h | 10 ++--
33
3 files changed, 107 insertions(+), 33 deletions(-)
34
35
diff --git a/hw/loongarch/acpi-build.c b/hw/loongarch/acpi-build.c
36
index XXXXXXX..XXXXXXX 100644
37
--- a/hw/loongarch/acpi-build.c
38
+++ b/hw/loongarch/acpi-build.c
39
@@ -XXX,XX +XXX,XX @@ static void build_pci_device_aml(Aml *scope, LoongArchMachineState *lams)
40
static void build_flash_aml(Aml *scope, LoongArchMachineState *lams)
41
{
42
Aml *dev, *crs;
43
+ MemoryRegion *flash_mem;
44
45
- hwaddr flash_base = VIRT_FLASH_BASE;
46
- hwaddr flash_size = VIRT_FLASH_SIZE;
47
+ hwaddr flash0_base;
48
+ hwaddr flash0_size;
49
+
50
+ hwaddr flash1_base;
51
+ hwaddr flash1_size;
52
+
53
+ flash_mem = pflash_cfi01_get_memory(lams->flash[0]);
54
+ flash0_base = flash_mem->addr;
55
+ flash0_size = memory_region_size(flash_mem);
56
+
57
+ flash_mem = pflash_cfi01_get_memory(lams->flash[1]);
58
+ flash1_base = flash_mem->addr;
59
+ flash1_size = memory_region_size(flash_mem);
60
61
dev = aml_device("FLS0");
62
aml_append(dev, aml_name_decl("_HID", aml_string("LNRO0015")));
63
aml_append(dev, aml_name_decl("_UID", aml_int(0)));
64
65
crs = aml_resource_template();
66
- aml_append(crs, aml_memory32_fixed(flash_base, flash_size, AML_READ_WRITE));
67
+ aml_append(crs, aml_memory32_fixed(flash0_base, flash0_size,
68
+ AML_READ_WRITE));
69
+ aml_append(dev, aml_name_decl("_CRS", crs));
70
+ aml_append(scope, dev);
71
+
72
+ dev = aml_device("FLS1");
73
+ aml_append(dev, aml_name_decl("_HID", aml_string("LNRO0015")));
74
+ aml_append(dev, aml_name_decl("_UID", aml_int(1)));
75
+
76
+ crs = aml_resource_template();
77
+ aml_append(crs, aml_memory32_fixed(flash1_base, flash1_size,
78
+ AML_READ_WRITE));
79
aml_append(dev, aml_name_decl("_CRS", crs));
80
aml_append(scope, dev);
81
}
82
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
12
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
83
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
84
--- a/hw/loongarch/virt.c
14
--- a/hw/loongarch/virt.c
85
+++ b/hw/loongarch/virt.c
15
+++ b/hw/loongarch/virt.c
86
@@ -XXX,XX +XXX,XX @@ struct loaderparams {
16
@@ -XXX,XX +XXX,XX @@ static void create_fdt(LoongArchVirtMachineState *lvms)
87
const char *initrd_filename;
17
static void fdt_add_cpu_nodes(const LoongArchVirtMachineState *lvms)
88
};
89
90
-static void virt_flash_create(LoongArchMachineState *lams)
91
+static PFlashCFI01 *virt_flash_create1(LoongArchMachineState *lams,
92
+ const char *name,
93
+ const char *alias_prop_name)
94
{
18
{
95
DeviceState *dev = qdev_new(TYPE_PFLASH_CFI01);
19
int num;
96
20
- const MachineState *ms = MACHINE(lvms);
97
@@ -XXX,XX +XXX,XX @@ static void virt_flash_create(LoongArchMachineState *lams)
21
- int smp_cpus = ms->smp.cpus;
98
qdev_prop_set_uint16(dev, "id1", 0x18);
22
+ MachineState *ms = MACHINE(lvms);
99
qdev_prop_set_uint16(dev, "id2", 0x00);
23
+ MachineClass *mc = MACHINE_GET_CLASS(ms);
100
qdev_prop_set_uint16(dev, "id3", 0x00);
24
+ const CPUArchIdList *possible_cpus;
101
- qdev_prop_set_string(dev, "name", "virt.flash");
25
+ LoongArchCPU *cpu;
102
- object_property_add_child(OBJECT(lams), "virt.flash", OBJECT(dev));
26
+ CPUState *cs;
103
- object_property_add_alias(OBJECT(lams), "pflash",
27
+ char *nodename, *map_path;
104
+ qdev_prop_set_string(dev, "name", name);
28
105
+ object_property_add_child(OBJECT(lams), name, OBJECT(dev));
29
qemu_fdt_add_subnode(ms->fdt, "/cpus");
106
+ object_property_add_alias(OBJECT(lams), alias_prop_name,
30
qemu_fdt_setprop_cell(ms->fdt, "/cpus", "#address-cells", 0x1);
107
OBJECT(dev), "drive");
31
qemu_fdt_setprop_cell(ms->fdt, "/cpus", "#size-cells", 0x0);
108
+ return PFLASH_CFI01(dev);
32
109
+}
33
/* cpu nodes */
110
34
- for (num = smp_cpus - 1; num >= 0; num--) {
111
- lams->flash = PFLASH_CFI01(dev);
35
- char *nodename = g_strdup_printf("/cpus/cpu@%d", num);
112
+static void virt_flash_create(LoongArchMachineState *lams)
36
- LoongArchCPU *cpu = LOONGARCH_CPU(qemu_get_cpu(num));
113
+{
37
- CPUState *cs = CPU(cpu);
114
+ lams->flash[0] = virt_flash_create1(lams, "virt.flash0", "pflash0");
38
+ possible_cpus = mc->possible_cpu_arch_ids(ms);
115
+ lams->flash[1] = virt_flash_create1(lams, "virt.flash1", "pflash1");
39
+ for (num = 0; num < possible_cpus->len; num++) {
40
+ cs = possible_cpus->cpus[num].cpu;
41
+ if (cs == NULL) {
42
+ continue;
43
+ }
44
+
45
+ nodename = g_strdup_printf("/cpus/cpu@%d", num);
46
+ cpu = LOONGARCH_CPU(cs);
47
48
qemu_fdt_add_subnode(ms->fdt, nodename);
49
qemu_fdt_setprop_string(ms->fdt, nodename, "device_type", "cpu");
50
qemu_fdt_setprop_string(ms->fdt, nodename, "compatible",
51
cpu->dtb_compatible);
52
- if (ms->possible_cpus->cpus[cs->cpu_index].props.has_node_id) {
53
+ if (possible_cpus->cpus[num].props.has_node_id) {
54
qemu_fdt_setprop_cell(ms->fdt, nodename, "numa-node-id",
55
- ms->possible_cpus->cpus[cs->cpu_index].props.node_id);
56
+ possible_cpus->cpus[num].props.node_id);
57
}
58
qemu_fdt_setprop_cell(ms->fdt, nodename, "reg", num);
59
qemu_fdt_setprop_cell(ms->fdt, nodename, "phandle",
60
@@ -XXX,XX +XXX,XX @@ static void fdt_add_cpu_nodes(const LoongArchVirtMachineState *lvms)
61
62
/*cpu map */
63
qemu_fdt_add_subnode(ms->fdt, "/cpus/cpu-map");
64
+ for (num = 0; num < possible_cpus->len; num++) {
65
+ cs = possible_cpus->cpus[num].cpu;
66
+ if (cs == NULL) {
67
+ continue;
68
+ }
69
70
- for (num = smp_cpus - 1; num >= 0; num--) {
71
- char *cpu_path = g_strdup_printf("/cpus/cpu@%d", num);
72
- char *map_path;
73
-
74
+ nodename = g_strdup_printf("/cpus/cpu@%d", num);
75
if (ms->smp.threads > 1) {
76
map_path = g_strdup_printf(
77
"/cpus/cpu-map/socket%d/core%d/thread%d",
78
@@ -XXX,XX +XXX,XX @@ static void fdt_add_cpu_nodes(const LoongArchVirtMachineState *lvms)
79
num % ms->smp.cores);
80
}
81
qemu_fdt_add_path(ms->fdt, map_path);
82
- qemu_fdt_setprop_phandle(ms->fdt, map_path, "cpu", cpu_path);
83
+ qemu_fdt_setprop_phandle(ms->fdt, map_path, "cpu", nodename);
84
85
g_free(map_path);
86
- g_free(cpu_path);
87
+ g_free(nodename);
88
}
116
}
89
}
117
90
118
-static void virt_flash_map(LoongArchMachineState *lams,
119
- MemoryRegion *sysmem)
120
+static void virt_flash_map1(PFlashCFI01 *flash,
121
+ hwaddr base, hwaddr size,
122
+ MemoryRegion *sysmem)
123
{
124
- PFlashCFI01 *flash = lams->flash;
125
DeviceState *dev = DEVICE(flash);
126
- hwaddr base = VIRT_FLASH_BASE;
127
- hwaddr size = VIRT_FLASH_SIZE;
128
+ BlockBackend *blk;
129
+ hwaddr real_size = size;
130
+
131
+ blk = pflash_cfi01_get_blk(flash);
132
+ if (blk) {
133
+ real_size = blk_getlength(blk);
134
+ assert(real_size && real_size <= size);
135
+ }
136
137
- assert(QEMU_IS_ALIGNED(size, VIRT_FLASH_SECTOR_SIZE));
138
- assert(size / VIRT_FLASH_SECTOR_SIZE <= UINT32_MAX);
139
+ assert(QEMU_IS_ALIGNED(real_size, VIRT_FLASH_SECTOR_SIZE));
140
+ assert(real_size / VIRT_FLASH_SECTOR_SIZE <= UINT32_MAX);
141
142
- qdev_prop_set_uint32(dev, "num-blocks", size / VIRT_FLASH_SECTOR_SIZE);
143
+ qdev_prop_set_uint32(dev, "num-blocks", real_size / VIRT_FLASH_SECTOR_SIZE);
144
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
145
memory_region_add_subregion(sysmem, base,
146
sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0));
147
+}
148
149
+static void virt_flash_map(LoongArchMachineState *lams,
150
+ MemoryRegion *sysmem)
151
+{
152
+ PFlashCFI01 *flash0 = lams->flash[0];
153
+ PFlashCFI01 *flash1 = lams->flash[1];
154
+
155
+ virt_flash_map1(flash0, VIRT_FLASH0_BASE, VIRT_FLASH0_SIZE, sysmem);
156
+ virt_flash_map1(flash1, VIRT_FLASH1_BASE, VIRT_FLASH1_SIZE, sysmem);
157
}
158
159
static void fdt_add_flash_node(LoongArchMachineState *lams)
160
{
161
MachineState *ms = MACHINE(lams);
162
char *nodename;
163
+ MemoryRegion *flash_mem;
164
+
165
+ hwaddr flash0_base;
166
+ hwaddr flash0_size;
167
168
- hwaddr flash_base = VIRT_FLASH_BASE;
169
- hwaddr flash_size = VIRT_FLASH_SIZE;
170
+ hwaddr flash1_base;
171
+ hwaddr flash1_size;
172
173
- nodename = g_strdup_printf("/flash@%" PRIx64, flash_base);
174
+ flash_mem = pflash_cfi01_get_memory(lams->flash[0]);
175
+ flash0_base = flash_mem->addr;
176
+ flash0_size = memory_region_size(flash_mem);
177
+
178
+ flash_mem = pflash_cfi01_get_memory(lams->flash[1]);
179
+ flash1_base = flash_mem->addr;
180
+ flash1_size = memory_region_size(flash_mem);
181
+
182
+ nodename = g_strdup_printf("/flash@%" PRIx64, flash0_base);
183
qemu_fdt_add_subnode(ms->fdt, nodename);
184
qemu_fdt_setprop_string(ms->fdt, nodename, "compatible", "cfi-flash");
185
qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "reg",
186
- 2, flash_base, 2, flash_size);
187
+ 2, flash0_base, 2, flash0_size,
188
+ 2, flash1_base, 2, flash1_size);
189
qemu_fdt_setprop_cell(ms->fdt, nodename, "bank-width", 4);
190
g_free(nodename);
191
}
192
@@ -XXX,XX +XXX,XX @@ static void loongarch_firmware_init(LoongArchMachineState *lams)
193
{
194
char *filename = MACHINE(lams)->firmware;
195
char *bios_name = NULL;
196
- int bios_size;
197
+ int bios_size, i;
198
+ BlockBackend *pflash_blk0;
199
+ MemoryRegion *mr;
200
201
lams->bios_loaded = false;
202
203
+ /* Map legacy -drive if=pflash to machine properties */
204
+ for (i = 0; i < ARRAY_SIZE(lams->flash); i++) {
205
+ pflash_cfi01_legacy_drive(lams->flash[i],
206
+ drive_get(IF_PFLASH, 0, i));
207
+ }
208
+
209
virt_flash_map(lams, get_system_memory());
210
211
+ pflash_blk0 = pflash_cfi01_get_blk(lams->flash[0]);
212
+
213
+ if (pflash_blk0) {
214
+ if (filename) {
215
+ error_report("cannot use both '-bios' and '-drive if=pflash'"
216
+ "options at once");
217
+ exit(1);
218
+ }
219
+ lams->bios_loaded = true;
220
+ return;
221
+ }
222
+
223
if (filename) {
224
bios_name = qemu_find_file(QEMU_FILE_TYPE_BIOS, filename);
225
if (!bios_name) {
226
@@ -XXX,XX +XXX,XX @@ static void loongarch_firmware_init(LoongArchMachineState *lams)
227
exit(1);
228
}
229
230
- bios_size = load_image_targphys(bios_name, VIRT_BIOS_BASE, VIRT_BIOS_SIZE);
231
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(lams->flash[0]), 0);
232
+ bios_size = load_image_mr(bios_name, mr);
233
if (bios_size < 0) {
234
error_report("Could not load ROM image '%s'", bios_name);
235
exit(1);
236
}
237
-
238
g_free(bios_name);
239
-
240
- memory_region_init_ram(&lams->bios, NULL, "loongarch.bios",
241
- VIRT_BIOS_SIZE, &error_fatal);
242
- memory_region_set_readonly(&lams->bios, true);
243
- memory_region_add_subregion(get_system_memory(), VIRT_BIOS_BASE, &lams->bios);
244
lams->bios_loaded = true;
245
}
246
-
247
}
248
249
static void reset_load_elf(void *opaque)
250
diff --git a/include/hw/loongarch/virt.h b/include/hw/loongarch/virt.h
251
index XXXXXXX..XXXXXXX 100644
252
--- a/include/hw/loongarch/virt.h
253
+++ b/include/hw/loongarch/virt.h
254
@@ -XXX,XX +XXX,XX @@
255
256
#define VIRT_FWCFG_BASE 0x1e020000UL
257
#define VIRT_BIOS_BASE 0x1c000000UL
258
-#define VIRT_BIOS_SIZE (4 * MiB)
259
+#define VIRT_BIOS_SIZE (16 * MiB)
260
#define VIRT_FLASH_SECTOR_SIZE (128 * KiB)
261
-#define VIRT_FLASH_BASE 0x1d000000UL
262
-#define VIRT_FLASH_SIZE (16 * MiB)
263
+#define VIRT_FLASH0_BASE VIRT_BIOS_BASE
264
+#define VIRT_FLASH0_SIZE VIRT_BIOS_SIZE
265
+#define VIRT_FLASH1_BASE 0x1d000000UL
266
+#define VIRT_FLASH1_SIZE (16 * MiB)
267
268
#define VIRT_LOWMEM_BASE 0
269
#define VIRT_LOWMEM_SIZE 0x10000000
270
@@ -XXX,XX +XXX,XX @@ struct LoongArchMachineState {
271
int fdt_size;
272
DeviceState *platform_bus_dev;
273
PCIBus *pci_bus;
274
- PFlashCFI01 *flash;
275
+ PFlashCFI01 *flash[2];
276
MemoryRegion system_iocsr;
277
MemoryRegion iocsr_mem;
278
AddressSpace as_iocsr;
279
--
91
--
280
2.25.1
92
2.43.5
281
282
diff view generated by jsdifflib
New patch
1
Like LBT feature, add type OnOffAuto for LSX feature setting. Also
2
add LSX feature detection with new VM ioctl command, fallback to old
3
method if it is not supported.
1
4
5
Signed-off-by: Bibo Mao <maobibo@loongson.cn>
6
Reviewed-by: Bibo Mao <maobibo@loongson.cn>
7
---
8
target/loongarch/cpu.c | 38 +++++++++++++++------------
9
target/loongarch/cpu.h | 2 ++
10
target/loongarch/kvm/kvm.c | 54 ++++++++++++++++++++++++++++++++++++++
11
3 files changed, 77 insertions(+), 17 deletions(-)
12
13
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/loongarch/cpu.c
16
+++ b/target/loongarch/cpu.c
17
@@ -XXX,XX +XXX,XX @@ static void loongarch_la464_initfn(Object *obj)
18
{
19
LoongArchCPU *cpu = LOONGARCH_CPU(obj);
20
CPULoongArchState *env = &cpu->env;
21
+ uint32_t data = 0;
22
int i;
23
24
for (i = 0; i < 21; i++) {
25
@@ -XXX,XX +XXX,XX @@ static void loongarch_la464_initfn(Object *obj)
26
cpu->dtb_compatible = "loongarch,Loongson-3A5000";
27
env->cpucfg[0] = 0x14c010; /* PRID */
28
29
- uint32_t data = 0;
30
data = FIELD_DP32(data, CPUCFG1, ARCH, 2);
31
data = FIELD_DP32(data, CPUCFG1, PGMMU, 1);
32
data = FIELD_DP32(data, CPUCFG1, IOCSR, 1);
33
@@ -XXX,XX +XXX,XX @@ static void loongarch_la132_initfn(Object *obj)
34
{
35
LoongArchCPU *cpu = LOONGARCH_CPU(obj);
36
CPULoongArchState *env = &cpu->env;
37
-
38
+ uint32_t data = 0;
39
int i;
40
41
for (i = 0; i < 21; i++) {
42
@@ -XXX,XX +XXX,XX @@ static void loongarch_la132_initfn(Object *obj)
43
cpu->dtb_compatible = "loongarch,Loongson-1C103";
44
env->cpucfg[0] = 0x148042; /* PRID */
45
46
- uint32_t data = 0;
47
data = FIELD_DP32(data, CPUCFG1, ARCH, 1); /* LA32 */
48
data = FIELD_DP32(data, CPUCFG1, PGMMU, 1);
49
data = FIELD_DP32(data, CPUCFG1, IOCSR, 1);
50
@@ -XXX,XX +XXX,XX @@ static void loongarch_cpu_realizefn(DeviceState *dev, Error **errp)
51
52
static bool loongarch_get_lsx(Object *obj, Error **errp)
53
{
54
- LoongArchCPU *cpu = LOONGARCH_CPU(obj);
55
- bool ret;
56
-
57
- if (FIELD_EX32(cpu->env.cpucfg[2], CPUCFG2, LSX)) {
58
- ret = true;
59
- } else {
60
- ret = false;
61
- }
62
- return ret;
63
+ return LOONGARCH_CPU(obj)->lsx != ON_OFF_AUTO_OFF;
64
}
65
66
static void loongarch_set_lsx(Object *obj, bool value, Error **errp)
67
{
68
LoongArchCPU *cpu = LOONGARCH_CPU(obj);
69
+ uint32_t val;
70
71
- if (value) {
72
- cpu->env.cpucfg[2] = FIELD_DP32(cpu->env.cpucfg[2], CPUCFG2, LSX, 1);
73
- } else {
74
- cpu->env.cpucfg[2] = FIELD_DP32(cpu->env.cpucfg[2], CPUCFG2, LSX, 0);
75
- cpu->env.cpucfg[2] = FIELD_DP32(cpu->env.cpucfg[2], CPUCFG2, LASX, 0);
76
+ cpu->lsx = value ? ON_OFF_AUTO_ON : ON_OFF_AUTO_OFF;
77
+ if (kvm_enabled()) {
78
+ /* kvm feature detection in function kvm_arch_init_vcpu */
79
+ return;
80
}
81
+
82
+ /* LSX feature detection in TCG mode */
83
+ val = cpu->env.cpucfg[2];
84
+ if (cpu->lsx == ON_OFF_AUTO_ON) {
85
+ if (FIELD_EX32(val, CPUCFG2, LSX) == 0) {
86
+ error_setg(errp, "Failed to enable LSX in TCG mode");
87
+ return;
88
+ }
89
+ }
90
+
91
+ cpu->env.cpucfg[2] = FIELD_DP32(val, CPUCFG2, LSX, value);
92
}
93
94
static bool loongarch_get_lasx(Object *obj, Error **errp)
95
@@ -XXX,XX +XXX,XX @@ void loongarch_cpu_post_init(Object *obj)
96
{
97
LoongArchCPU *cpu = LOONGARCH_CPU(obj);
98
99
+ cpu->lsx = ON_OFF_AUTO_AUTO;
100
object_property_add_bool(obj, "lsx", loongarch_get_lsx,
101
loongarch_set_lsx);
102
object_property_add_bool(obj, "lasx", loongarch_get_lasx,
103
@@ -XXX,XX +XXX,XX @@ void loongarch_cpu_post_init(Object *obj)
104
105
} else {
106
cpu->lbt = ON_OFF_AUTO_OFF;
107
+ cpu->pmu = ON_OFF_AUTO_OFF;
108
}
109
}
110
111
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
112
index XXXXXXX..XXXXXXX 100644
113
--- a/target/loongarch/cpu.h
114
+++ b/target/loongarch/cpu.h
115
@@ -XXX,XX +XXX,XX @@ typedef struct LoongArchTLB LoongArchTLB;
116
#endif
117
118
enum loongarch_features {
119
+ LOONGARCH_FEATURE_LSX,
120
LOONGARCH_FEATURE_LBT, /* loongson binary translation extension */
121
LOONGARCH_FEATURE_PMU,
122
};
123
@@ -XXX,XX +XXX,XX @@ struct ArchCPU {
124
uint32_t phy_id;
125
OnOffAuto lbt;
126
OnOffAuto pmu;
127
+ OnOffAuto lsx;
128
129
/* 'compatible' string for this CPU for Linux device trees */
130
const char *dtb_compatible;
131
diff --git a/target/loongarch/kvm/kvm.c b/target/loongarch/kvm/kvm.c
132
index XXXXXXX..XXXXXXX 100644
133
--- a/target/loongarch/kvm/kvm.c
134
+++ b/target/loongarch/kvm/kvm.c
135
@@ -XXX,XX +XXX,XX @@ static bool kvm_feature_supported(CPUState *cs, enum loongarch_features feature)
136
{
137
int ret;
138
struct kvm_device_attr attr;
139
+ uint64_t val;
140
141
switch (feature) {
142
+ case LOONGARCH_FEATURE_LSX:
143
+ attr.group = KVM_LOONGARCH_VM_FEAT_CTRL;
144
+ attr.attr = KVM_LOONGARCH_VM_FEAT_LSX;
145
+ ret = kvm_vm_ioctl(kvm_state, KVM_HAS_DEVICE_ATTR, &attr);
146
+ if (ret == 0) {
147
+ return true;
148
+ }
149
+
150
+ /* Fallback to old kernel detect interface */
151
+ val = 0;
152
+ attr.group = KVM_LOONGARCH_VCPU_CPUCFG;
153
+ /* Cpucfg2 */
154
+ attr.attr = 2;
155
+ attr.addr = (uint64_t)&val;
156
+ ret = kvm_vcpu_ioctl(cs, KVM_HAS_DEVICE_ATTR, &attr);
157
+ if (!ret) {
158
+ ret = kvm_vcpu_ioctl(cs, KVM_GET_DEVICE_ATTR, &attr);
159
+ if (ret) {
160
+ return false;
161
+ }
162
+
163
+ ret = FIELD_EX32((uint32_t)val, CPUCFG2, LSX);
164
+ return (ret != 0);
165
+ }
166
+ return false;
167
+
168
case LOONGARCH_FEATURE_LBT:
169
/*
170
* Return all if all the LBT features are supported such as:
171
@@ -XXX,XX +XXX,XX @@ static bool kvm_feature_supported(CPUState *cs, enum loongarch_features feature)
172
return false;
173
}
174
175
+static int kvm_cpu_check_lsx(CPUState *cs, Error **errp)
176
+{
177
+ CPULoongArchState *env = cpu_env(cs);
178
+ LoongArchCPU *cpu = LOONGARCH_CPU(cs);
179
+ bool kvm_supported;
180
+
181
+ kvm_supported = kvm_feature_supported(cs, LOONGARCH_FEATURE_LSX);
182
+ env->cpucfg[2] = FIELD_DP32(env->cpucfg[2], CPUCFG2, LSX, 0);
183
+ if (cpu->lsx == ON_OFF_AUTO_ON) {
184
+ if (kvm_supported) {
185
+ env->cpucfg[2] = FIELD_DP32(env->cpucfg[2], CPUCFG2, LSX, 1);
186
+ } else {
187
+ error_setg(errp, "'lsx' feature not supported by KVM on this host");
188
+ return -ENOTSUP;
189
+ }
190
+ } else if ((cpu->lsx == ON_OFF_AUTO_AUTO) && kvm_supported) {
191
+ env->cpucfg[2] = FIELD_DP32(env->cpucfg[2], CPUCFG2, LSX, 1);
192
+ }
193
+
194
+ return 0;
195
+}
196
+
197
static int kvm_cpu_check_lbt(CPUState *cs, Error **errp)
198
{
199
CPULoongArchState *env = cpu_env(cs);
200
@@ -XXX,XX +XXX,XX @@ int kvm_arch_init_vcpu(CPUState *cs)
201
brk_insn = val;
202
}
203
204
+ ret = kvm_cpu_check_lsx(cs, &local_err);
205
+ if (ret < 0) {
206
+ error_report_err(local_err);
207
+ }
208
+
209
ret = kvm_cpu_check_lbt(cs, &local_err);
210
if (ret < 0) {
211
error_report_err(local_err);
212
--
213
2.43.5
diff view generated by jsdifflib
New patch
1
Like LSX feature, add type OnOffAuto for LASX feature setting.
1
2
3
Signed-off-by: Bibo Mao <maobibo@loongson.cn>
4
Reviewed-by: Bibo Mao <maobibo@loongson.cn>
5
---
6
target/loongarch/cpu.c | 50 +++++++++++++++++++++++------------
7
target/loongarch/cpu.h | 2 ++
8
target/loongarch/kvm/kvm.c | 53 ++++++++++++++++++++++++++++++++++++++
9
3 files changed, 89 insertions(+), 16 deletions(-)
10
11
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/target/loongarch/cpu.c
14
+++ b/target/loongarch/cpu.c
15
@@ -XXX,XX +XXX,XX @@ static void loongarch_set_lsx(Object *obj, bool value, Error **errp)
16
uint32_t val;
17
18
cpu->lsx = value ? ON_OFF_AUTO_ON : ON_OFF_AUTO_OFF;
19
+ if (cpu->lsx == ON_OFF_AUTO_OFF) {
20
+ cpu->lasx = ON_OFF_AUTO_OFF;
21
+ if (cpu->lasx == ON_OFF_AUTO_ON) {
22
+ error_setg(errp, "Failed to disable LSX since LASX is enabled");
23
+ return;
24
+ }
25
+ }
26
+
27
if (kvm_enabled()) {
28
/* kvm feature detection in function kvm_arch_init_vcpu */
29
return;
30
@@ -XXX,XX +XXX,XX @@ static void loongarch_set_lsx(Object *obj, bool value, Error **errp)
31
error_setg(errp, "Failed to enable LSX in TCG mode");
32
return;
33
}
34
+ } else {
35
+ cpu->env.cpucfg[2] = FIELD_DP32(val, CPUCFG2, LASX, 0);
36
+ val = cpu->env.cpucfg[2];
37
}
38
39
cpu->env.cpucfg[2] = FIELD_DP32(val, CPUCFG2, LSX, value);
40
@@ -XXX,XX +XXX,XX @@ static void loongarch_set_lsx(Object *obj, bool value, Error **errp)
41
42
static bool loongarch_get_lasx(Object *obj, Error **errp)
43
{
44
- LoongArchCPU *cpu = LOONGARCH_CPU(obj);
45
- bool ret;
46
-
47
- if (FIELD_EX32(cpu->env.cpucfg[2], CPUCFG2, LASX)) {
48
- ret = true;
49
- } else {
50
- ret = false;
51
- }
52
- return ret;
53
+ return LOONGARCH_CPU(obj)->lasx != ON_OFF_AUTO_OFF;
54
}
55
56
static void loongarch_set_lasx(Object *obj, bool value, Error **errp)
57
{
58
LoongArchCPU *cpu = LOONGARCH_CPU(obj);
59
+ uint32_t val;
60
61
- if (value) {
62
-    if (!FIELD_EX32(cpu->env.cpucfg[2], CPUCFG2, LSX)) {
63
- cpu->env.cpucfg[2] = FIELD_DP32(cpu->env.cpucfg[2], CPUCFG2, LSX, 1);
64
-    }
65
- cpu->env.cpucfg[2] = FIELD_DP32(cpu->env.cpucfg[2], CPUCFG2, LASX, 1);
66
- } else {
67
- cpu->env.cpucfg[2] = FIELD_DP32(cpu->env.cpucfg[2], CPUCFG2, LASX, 0);
68
+ cpu->lasx = value ? ON_OFF_AUTO_ON : ON_OFF_AUTO_OFF;
69
+ if ((cpu->lsx == ON_OFF_AUTO_OFF) && (cpu->lasx == ON_OFF_AUTO_ON)) {
70
+ error_setg(errp, "Failed to enable LASX since lSX is disabled");
71
+ return;
72
+ }
73
+
74
+ if (kvm_enabled()) {
75
+ /* kvm feature detection in function kvm_arch_init_vcpu */
76
+ return;
77
}
78
+
79
+ /* LASX feature detection in TCG mode */
80
+ val = cpu->env.cpucfg[2];
81
+ if (cpu->lasx == ON_OFF_AUTO_ON) {
82
+ if (FIELD_EX32(val, CPUCFG2, LASX) == 0) {
83
+ error_setg(errp, "Failed to enable LASX in TCG mode");
84
+ return;
85
+ }
86
+ }
87
+
88
+ cpu->env.cpucfg[2] = FIELD_DP32(val, CPUCFG2, LASX, value);
89
}
90
91
static bool loongarch_get_lbt(Object *obj, Error **errp)
92
@@ -XXX,XX +XXX,XX @@ void loongarch_cpu_post_init(Object *obj)
93
LoongArchCPU *cpu = LOONGARCH_CPU(obj);
94
95
cpu->lsx = ON_OFF_AUTO_AUTO;
96
+ cpu->lasx = ON_OFF_AUTO_AUTO;
97
object_property_add_bool(obj, "lsx", loongarch_get_lsx,
98
loongarch_set_lsx);
99
object_property_add_bool(obj, "lasx", loongarch_get_lasx,
100
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
101
index XXXXXXX..XXXXXXX 100644
102
--- a/target/loongarch/cpu.h
103
+++ b/target/loongarch/cpu.h
104
@@ -XXX,XX +XXX,XX @@ typedef struct LoongArchTLB LoongArchTLB;
105
106
enum loongarch_features {
107
LOONGARCH_FEATURE_LSX,
108
+ LOONGARCH_FEATURE_LASX,
109
LOONGARCH_FEATURE_LBT, /* loongson binary translation extension */
110
LOONGARCH_FEATURE_PMU,
111
};
112
@@ -XXX,XX +XXX,XX @@ struct ArchCPU {
113
OnOffAuto lbt;
114
OnOffAuto pmu;
115
OnOffAuto lsx;
116
+ OnOffAuto lasx;
117
118
/* 'compatible' string for this CPU for Linux device trees */
119
const char *dtb_compatible;
120
diff --git a/target/loongarch/kvm/kvm.c b/target/loongarch/kvm/kvm.c
121
index XXXXXXX..XXXXXXX 100644
122
--- a/target/loongarch/kvm/kvm.c
123
+++ b/target/loongarch/kvm/kvm.c
124
@@ -XXX,XX +XXX,XX @@ static bool kvm_feature_supported(CPUState *cs, enum loongarch_features feature)
125
}
126
return false;
127
128
+ case LOONGARCH_FEATURE_LASX:
129
+ attr.group = KVM_LOONGARCH_VM_FEAT_CTRL;
130
+ attr.attr = KVM_LOONGARCH_VM_FEAT_LASX;
131
+ ret = kvm_vm_ioctl(kvm_state, KVM_HAS_DEVICE_ATTR, &attr);
132
+ if (ret == 0) {
133
+ return true;
134
+ }
135
+
136
+ /* Fallback to old kernel detect interface */
137
+ val = 0;
138
+ attr.group = KVM_LOONGARCH_VCPU_CPUCFG;
139
+ /* Cpucfg2 */
140
+ attr.attr = 2;
141
+ attr.addr = (uint64_t)&val;
142
+ ret = kvm_vcpu_ioctl(cs, KVM_HAS_DEVICE_ATTR, &attr);
143
+ if (!ret) {
144
+ ret = kvm_vcpu_ioctl(cs, KVM_GET_DEVICE_ATTR, &attr);
145
+ if (ret) {
146
+ return false;
147
+ }
148
+
149
+ ret = FIELD_EX32((uint32_t)val, CPUCFG2, LASX);
150
+ return (ret != 0);
151
+ }
152
+ return false;
153
+
154
case LOONGARCH_FEATURE_LBT:
155
/*
156
* Return all if all the LBT features are supported such as:
157
@@ -XXX,XX +XXX,XX @@ static int kvm_cpu_check_lsx(CPUState *cs, Error **errp)
158
return 0;
159
}
160
161
+static int kvm_cpu_check_lasx(CPUState *cs, Error **errp)
162
+{
163
+ CPULoongArchState *env = cpu_env(cs);
164
+ LoongArchCPU *cpu = LOONGARCH_CPU(cs);
165
+ bool kvm_supported;
166
+
167
+ kvm_supported = kvm_feature_supported(cs, LOONGARCH_FEATURE_LASX);
168
+ env->cpucfg[2] = FIELD_DP32(env->cpucfg[2], CPUCFG2, LASX, 0);
169
+ if (cpu->lasx == ON_OFF_AUTO_ON) {
170
+ if (kvm_supported) {
171
+ env->cpucfg[2] = FIELD_DP32(env->cpucfg[2], CPUCFG2, LASX, 1);
172
+ } else {
173
+ error_setg(errp, "'lasx' feature not supported by KVM on host");
174
+ return -ENOTSUP;
175
+ }
176
+ } else if ((cpu->lasx == ON_OFF_AUTO_AUTO) && kvm_supported) {
177
+ env->cpucfg[2] = FIELD_DP32(env->cpucfg[2], CPUCFG2, LASX, 1);
178
+ }
179
+
180
+ return 0;
181
+}
182
+
183
static int kvm_cpu_check_lbt(CPUState *cs, Error **errp)
184
{
185
CPULoongArchState *env = cpu_env(cs);
186
@@ -XXX,XX +XXX,XX @@ int kvm_arch_init_vcpu(CPUState *cs)
187
error_report_err(local_err);
188
}
189
190
+ ret = kvm_cpu_check_lasx(cs, &local_err);
191
+ if (ret < 0) {
192
+ error_report_err(local_err);
193
+ }
194
+
195
ret = kvm_cpu_check_lbt(cs, &local_err);
196
if (ret < 0) {
197
error_report_err(local_err);
198
--
199
2.43.5
diff view generated by jsdifflib