mirror of https://github.com/xemu-project/xemu.git
pull-loongarch-20230515
-----BEGIN PGP SIGNATURE----- iLMEAAEIAB0WIQS4/x2g0v3LLaCcbCxAov/yOSY+3wUCZGIThgAKCRBAov/yOSY+ 34NVA/0b99XxYeeOnJYspjKGgVk+R51+1ilMHqPGlNEG6HB2eHyIJdDgenBDaa/h lxqzDU9YQI4DzuvUcC75uWrShMkR5/Fb8Z0CCEToQUyAwfh2pNeAIzuB7TXHW5Ox SRGMs3eF23q5BUSCeD7DS2Ar1Zv4Gm3ytutiMAvCxNzxJWF1aA== =g93p -----END PGP SIGNATURE----- Merge tag 'pull-loongarch-20230515' of https://gitlab.com/gaosong/qemu into staging pull-loongarch-20230515 # -----BEGIN PGP SIGNATURE----- # # iLMEAAEIAB0WIQS4/x2g0v3LLaCcbCxAov/yOSY+3wUCZGIThgAKCRBAov/yOSY+ # 34NVA/0b99XxYeeOnJYspjKGgVk+R51+1ilMHqPGlNEG6HB2eHyIJdDgenBDaa/h # lxqzDU9YQI4DzuvUcC75uWrShMkR5/Fb8Z0CCEToQUyAwfh2pNeAIzuB7TXHW5Ox # SRGMs3eF23q5BUSCeD7DS2Ar1Zv4Gm3ytutiMAvCxNzxJWF1aA== # =g93p # -----END PGP SIGNATURE----- # gpg: Signature made Mon 15 May 2023 04:12:06 AM PDT # gpg: using RSA key B8FF1DA0D2FDCB2DA09C6C2C40A2FFF239263EDF # gpg: Good signature from "Song Gao <m17746591750@163.com>" [unknown] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: B8FF 1DA0 D2FD CB2D A09C 6C2C 40A2 FFF2 3926 3EDF * tag 'pull-loongarch-20230515' of https://gitlab.com/gaosong/qemu: hw/intc: Add NULL pointer check on LoongArch ipi device hw/loongarch/virt: Set max 256 cpus support on loongarch virt machine hw/loongarch/virt: Modify ipi as percpu device tests/avocado: Add LoongArch machine start test loongarch: mark loongarch_ipi_iocsr re-entrnacy safe Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
commit
18b6727083
|
@ -245,6 +245,7 @@ M: Xiaojuan Yang <yangxiaojuan@loongson.cn>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: target/loongarch/
|
F: target/loongarch/
|
||||||
F: tests/tcg/loongarch64/
|
F: tests/tcg/loongarch64/
|
||||||
|
F: tests/avocado/machine_loongarch.py
|
||||||
|
|
||||||
M68K TCG CPUs
|
M68K TCG CPUs
|
||||||
M: Laurent Vivier <laurent@vivier.eu>
|
M: Laurent Vivier <laurent@vivier.eu>
|
||||||
|
|
|
@ -254,7 +254,7 @@ static const VMStateDescription vmstate_loongarch_extioi = {
|
||||||
.minimum_version_id = 1,
|
.minimum_version_id = 1,
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_UINT32_ARRAY(bounce, LoongArchExtIOI, EXTIOI_IRQS_GROUP_COUNT),
|
VMSTATE_UINT32_ARRAY(bounce, LoongArchExtIOI, EXTIOI_IRQS_GROUP_COUNT),
|
||||||
VMSTATE_UINT32_2DARRAY(coreisr, LoongArchExtIOI, LOONGARCH_MAX_VCPUS,
|
VMSTATE_UINT32_2DARRAY(coreisr, LoongArchExtIOI, EXTIOI_CPUS,
|
||||||
EXTIOI_IRQS_GROUP_COUNT),
|
EXTIOI_IRQS_GROUP_COUNT),
|
||||||
VMSTATE_UINT32_ARRAY(nodetype, LoongArchExtIOI,
|
VMSTATE_UINT32_ARRAY(nodetype, LoongArchExtIOI,
|
||||||
EXTIOI_IRQS_NODETYPE_COUNT / 2),
|
EXTIOI_IRQS_NODETYPE_COUNT / 2),
|
||||||
|
@ -281,7 +281,7 @@ static void loongarch_extioi_instance_init(Object *obj)
|
||||||
|
|
||||||
qdev_init_gpio_in(DEVICE(obj), extioi_setirq, EXTIOI_IRQS);
|
qdev_init_gpio_in(DEVICE(obj), extioi_setirq, EXTIOI_IRQS);
|
||||||
|
|
||||||
for (cpu = 0; cpu < LOONGARCH_MAX_VCPUS; cpu++) {
|
for (cpu = 0; cpu < EXTIOI_CPUS; cpu++) {
|
||||||
memory_region_init_io(&s->extioi_iocsr_mem[cpu], OBJECT(s), &extioi_ops,
|
memory_region_init_io(&s->extioi_iocsr_mem[cpu], OBJECT(s), &extioi_ops,
|
||||||
s, "extioi_iocsr", 0x900);
|
s, "extioi_iocsr", 0x900);
|
||||||
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->extioi_iocsr_mem[cpu]);
|
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->extioi_iocsr_mem[cpu]);
|
||||||
|
|
|
@ -77,31 +77,42 @@ static void send_ipi_data(CPULoongArchState *env, uint64_t val, hwaddr addr)
|
||||||
|
|
||||||
static void ipi_send(uint64_t val)
|
static void ipi_send(uint64_t val)
|
||||||
{
|
{
|
||||||
int cpuid, data;
|
uint32_t cpuid;
|
||||||
|
uint8_t vector;
|
||||||
CPULoongArchState *env;
|
CPULoongArchState *env;
|
||||||
CPUState *cs;
|
CPUState *cs;
|
||||||
LoongArchCPU *cpu;
|
LoongArchCPU *cpu;
|
||||||
|
|
||||||
cpuid = (val >> 16) & 0x3ff;
|
cpuid = extract32(val, 16, 10);
|
||||||
|
if (cpuid >= LOONGARCH_MAX_CPUS) {
|
||||||
|
trace_loongarch_ipi_unsupported_cpuid("IOCSR_IPI_SEND", cpuid);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* IPI status vector */
|
/* IPI status vector */
|
||||||
data = 1 << (val & 0x1f);
|
vector = extract8(val, 0, 5);
|
||||||
|
|
||||||
cs = qemu_get_cpu(cpuid);
|
cs = qemu_get_cpu(cpuid);
|
||||||
cpu = LOONGARCH_CPU(cs);
|
cpu = LOONGARCH_CPU(cs);
|
||||||
env = &cpu->env;
|
env = &cpu->env;
|
||||||
address_space_stl(&env->address_space_iocsr, 0x1008,
|
address_space_stl(&env->address_space_iocsr, 0x1008,
|
||||||
data, MEMTXATTRS_UNSPECIFIED, NULL);
|
BIT(vector), MEMTXATTRS_UNSPECIFIED, NULL);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mail_send(uint64_t val)
|
static void mail_send(uint64_t val)
|
||||||
{
|
{
|
||||||
int cpuid;
|
uint32_t cpuid;
|
||||||
hwaddr addr;
|
hwaddr addr;
|
||||||
CPULoongArchState *env;
|
CPULoongArchState *env;
|
||||||
CPUState *cs;
|
CPUState *cs;
|
||||||
LoongArchCPU *cpu;
|
LoongArchCPU *cpu;
|
||||||
|
|
||||||
cpuid = (val >> 16) & 0x3ff;
|
cpuid = extract32(val, 16, 10);
|
||||||
|
if (cpuid >= LOONGARCH_MAX_CPUS) {
|
||||||
|
trace_loongarch_ipi_unsupported_cpuid("IOCSR_MAIL_SEND", cpuid);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
addr = 0x1020 + (val & 0x1c);
|
addr = 0x1020 + (val & 0x1c);
|
||||||
cs = qemu_get_cpu(cpuid);
|
cs = qemu_get_cpu(cpuid);
|
||||||
cpu = LOONGARCH_CPU(cs);
|
cpu = LOONGARCH_CPU(cs);
|
||||||
|
@ -111,14 +122,21 @@ static void mail_send(uint64_t val)
|
||||||
|
|
||||||
static void any_send(uint64_t val)
|
static void any_send(uint64_t val)
|
||||||
{
|
{
|
||||||
int cpuid;
|
uint32_t cpuid;
|
||||||
hwaddr addr;
|
hwaddr addr;
|
||||||
CPULoongArchState *env;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
cpuid = (val >> 16) & 0x3ff;
|
|
||||||
addr = val & 0xffff;
|
addr = val & 0xffff;
|
||||||
CPUState *cs = qemu_get_cpu(cpuid);
|
cs = qemu_get_cpu(cpuid);
|
||||||
LoongArchCPU *cpu = LOONGARCH_CPU(cs);
|
cpu = LOONGARCH_CPU(cs);
|
||||||
env = &cpu->env;
|
env = &cpu->env;
|
||||||
send_ipi_data(env, val, addr);
|
send_ipi_data(env, val, addr);
|
||||||
}
|
}
|
||||||
|
@ -201,51 +219,43 @@ static const MemoryRegionOps loongarch_ipi64_ops = {
|
||||||
|
|
||||||
static void loongarch_ipi_init(Object *obj)
|
static void loongarch_ipi_init(Object *obj)
|
||||||
{
|
{
|
||||||
int cpu;
|
|
||||||
LoongArchMachineState *lams;
|
|
||||||
LoongArchIPI *s = LOONGARCH_IPI(obj);
|
LoongArchIPI *s = LOONGARCH_IPI(obj);
|
||||||
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
|
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
|
||||||
Object *machine = qdev_get_machine();
|
|
||||||
ObjectClass *mc = object_get_class(machine);
|
|
||||||
/* 'lams' should be initialized */
|
|
||||||
if (!strcmp(MACHINE_CLASS(mc)->name, "none")) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
lams = LOONGARCH_MACHINE(machine);
|
|
||||||
for (cpu = 0; cpu < MAX_IPI_CORE_NUM; cpu++) {
|
|
||||||
memory_region_init_io(&s->ipi_iocsr_mem[cpu], obj, &loongarch_ipi_ops,
|
|
||||||
&lams->ipi_core[cpu], "loongarch_ipi_iocsr", 0x48);
|
|
||||||
sysbus_init_mmio(sbd, &s->ipi_iocsr_mem[cpu]);
|
|
||||||
|
|
||||||
memory_region_init_io(&s->ipi64_iocsr_mem[cpu], obj, &loongarch_ipi64_ops,
|
memory_region_init_io(&s->ipi_iocsr_mem, obj, &loongarch_ipi_ops,
|
||||||
&lams->ipi_core[cpu], "loongarch_ipi64_iocsr", 0x118);
|
&s->ipi_core, "loongarch_ipi_iocsr", 0x48);
|
||||||
sysbus_init_mmio(sbd, &s->ipi64_iocsr_mem[cpu]);
|
|
||||||
qdev_init_gpio_out(DEVICE(obj), &lams->ipi_core[cpu].irq, 1);
|
/* loongarch_ipi_iocsr performs re-entrant IO through ipi_send */
|
||||||
}
|
s->ipi_iocsr_mem.disable_reentrancy_guard = true;
|
||||||
|
|
||||||
|
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);
|
||||||
|
sysbus_init_mmio(sbd, &s->ipi64_iocsr_mem);
|
||||||
|
qdev_init_gpio_out(DEVICE(obj), &s->ipi_core.irq, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const VMStateDescription vmstate_ipi_core = {
|
static const VMStateDescription vmstate_ipi_core = {
|
||||||
.name = "ipi-single",
|
.name = "ipi-single",
|
||||||
.version_id = 0,
|
.version_id = 1,
|
||||||
.minimum_version_id = 0,
|
.minimum_version_id = 1,
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_UINT32(status, IPICore),
|
VMSTATE_UINT32(status, IPICore),
|
||||||
VMSTATE_UINT32(en, IPICore),
|
VMSTATE_UINT32(en, IPICore),
|
||||||
VMSTATE_UINT32(set, IPICore),
|
VMSTATE_UINT32(set, IPICore),
|
||||||
VMSTATE_UINT32(clear, IPICore),
|
VMSTATE_UINT32(clear, IPICore),
|
||||||
VMSTATE_UINT32_ARRAY(buf, IPICore, MAX_IPI_MBX_NUM * 2),
|
VMSTATE_UINT32_ARRAY(buf, IPICore, 2),
|
||||||
VMSTATE_END_OF_LIST()
|
VMSTATE_END_OF_LIST()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static const VMStateDescription vmstate_loongarch_ipi = {
|
static const VMStateDescription vmstate_loongarch_ipi = {
|
||||||
.name = TYPE_LOONGARCH_IPI,
|
.name = TYPE_LOONGARCH_IPI,
|
||||||
.version_id = 0,
|
.version_id = 1,
|
||||||
.minimum_version_id = 0,
|
.minimum_version_id = 1,
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_STRUCT_ARRAY(ipi_core, LoongArchMachineState,
|
VMSTATE_STRUCT(ipi_core, LoongArchIPI, 0, vmstate_ipi_core, IPICore),
|
||||||
MAX_IPI_CORE_NUM, 0,
|
|
||||||
vmstate_ipi_core, IPICore),
|
|
||||||
VMSTATE_END_OF_LIST()
|
VMSTATE_END_OF_LIST()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -292,6 +292,7 @@ sh_intc_set(int id, int enable) "setting interrupt group %d to %d"
|
||||||
# loongarch_ipi.c
|
# loongarch_ipi.c
|
||||||
loongarch_ipi_read(unsigned size, uint64_t addr, uint64_t val) "size: %u addr: 0x%"PRIx64 "val: 0x%"PRIx64
|
loongarch_ipi_read(unsigned size, uint64_t addr, uint64_t val) "size: %u addr: 0x%"PRIx64 "val: 0x%"PRIx64
|
||||||
loongarch_ipi_write(unsigned size, uint64_t addr, uint64_t val) "size: %u addr: 0x%"PRIx64 "val: 0x%"PRIx64
|
loongarch_ipi_write(unsigned size, uint64_t addr, uint64_t val) "size: %u addr: 0x%"PRIx64 "val: 0x%"PRIx64
|
||||||
|
loongarch_ipi_unsupported_cpuid(const char *s, uint32_t cpuid) "%s unsupported cpuid 0x%" PRIx32
|
||||||
|
|
||||||
# loongarch_pch_pic.c
|
# loongarch_pch_pic.c
|
||||||
loongarch_pch_pic_irq_handler(int irq, int level) "irq %d level %d"
|
loongarch_pch_pic_irq_handler(int irq, int level) "irq %d level %d"
|
||||||
|
|
|
@ -565,9 +565,6 @@ static void loongarch_irq_init(LoongArchMachineState *lams)
|
||||||
CPUState *cpu_state;
|
CPUState *cpu_state;
|
||||||
int cpu, pin, i, start, num;
|
int cpu, pin, i, start, num;
|
||||||
|
|
||||||
ipi = qdev_new(TYPE_LOONGARCH_IPI);
|
|
||||||
sysbus_realize_and_unref(SYS_BUS_DEVICE(ipi), &error_fatal);
|
|
||||||
|
|
||||||
extioi = qdev_new(TYPE_LOONGARCH_EXTIOI);
|
extioi = qdev_new(TYPE_LOONGARCH_EXTIOI);
|
||||||
sysbus_realize_and_unref(SYS_BUS_DEVICE(extioi), &error_fatal);
|
sysbus_realize_and_unref(SYS_BUS_DEVICE(extioi), &error_fatal);
|
||||||
|
|
||||||
|
@ -598,16 +595,24 @@ static void loongarch_irq_init(LoongArchMachineState *lams)
|
||||||
lacpu = LOONGARCH_CPU(cpu_state);
|
lacpu = LOONGARCH_CPU(cpu_state);
|
||||||
env = &(lacpu->env);
|
env = &(lacpu->env);
|
||||||
|
|
||||||
|
ipi = qdev_new(TYPE_LOONGARCH_IPI);
|
||||||
|
sysbus_realize_and_unref(SYS_BUS_DEVICE(ipi), &error_fatal);
|
||||||
|
|
||||||
/* connect ipi irq to cpu irq */
|
/* connect ipi irq to cpu irq */
|
||||||
qdev_connect_gpio_out(ipi, cpu, qdev_get_gpio_in(cpudev, IRQ_IPI));
|
qdev_connect_gpio_out(ipi, 0, qdev_get_gpio_in(cpudev, IRQ_IPI));
|
||||||
/* IPI iocsr memory region */
|
/* IPI iocsr memory region */
|
||||||
memory_region_add_subregion(&env->system_iocsr, SMP_IPI_MAILBOX,
|
memory_region_add_subregion(&env->system_iocsr, SMP_IPI_MAILBOX,
|
||||||
sysbus_mmio_get_region(SYS_BUS_DEVICE(ipi),
|
sysbus_mmio_get_region(SYS_BUS_DEVICE(ipi),
|
||||||
cpu * 2));
|
0));
|
||||||
memory_region_add_subregion(&env->system_iocsr, MAIL_SEND_ADDR,
|
memory_region_add_subregion(&env->system_iocsr, MAIL_SEND_ADDR,
|
||||||
sysbus_mmio_get_region(SYS_BUS_DEVICE(ipi),
|
sysbus_mmio_get_region(SYS_BUS_DEVICE(ipi),
|
||||||
cpu * 2 + 1));
|
1));
|
||||||
/* extioi iocsr memory region */
|
/*
|
||||||
|
* 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,
|
memory_region_add_subregion(&env->system_iocsr, APIC_BASE,
|
||||||
sysbus_mmio_get_region(SYS_BUS_DEVICE(extioi),
|
sysbus_mmio_get_region(SYS_BUS_DEVICE(extioi),
|
||||||
cpu));
|
cpu));
|
||||||
|
@ -617,7 +622,7 @@ static void loongarch_irq_init(LoongArchMachineState *lams)
|
||||||
* connect ext irq to the cpu irq
|
* connect ext irq to the cpu irq
|
||||||
* cpu_pin[9:2] <= intc_pin[7:0]
|
* cpu_pin[9:2] <= intc_pin[7:0]
|
||||||
*/
|
*/
|
||||||
for (cpu = 0; cpu < ms->smp.cpus; cpu++) {
|
for (cpu = 0; cpu < MIN(ms->smp.cpus, EXTIOI_CPUS); cpu++) {
|
||||||
cpudev = DEVICE(qemu_get_cpu(cpu));
|
cpudev = DEVICE(qemu_get_cpu(cpu));
|
||||||
for (pin = 0; pin < LS3A_INTC_IP; pin++) {
|
for (pin = 0; pin < LS3A_INTC_IP; pin++) {
|
||||||
qdev_connect_gpio_out(extioi, (cpu * 8 + pin),
|
qdev_connect_gpio_out(extioi, (cpu * 8 + pin),
|
||||||
|
@ -1026,7 +1031,7 @@ static void loongarch_class_init(ObjectClass *oc, void *data)
|
||||||
mc->default_ram_size = 1 * GiB;
|
mc->default_ram_size = 1 * GiB;
|
||||||
mc->default_cpu_type = LOONGARCH_CPU_TYPE_NAME("la464");
|
mc->default_cpu_type = LOONGARCH_CPU_TYPE_NAME("la464");
|
||||||
mc->default_ram_id = "loongarch.ram";
|
mc->default_ram_id = "loongarch.ram";
|
||||||
mc->max_cpus = LOONGARCH_MAX_VCPUS;
|
mc->max_cpus = LOONGARCH_MAX_CPUS;
|
||||||
mc->is_default = 1;
|
mc->is_default = 1;
|
||||||
mc->default_kernel_irqchip_split = false;
|
mc->default_kernel_irqchip_split = false;
|
||||||
mc->block_default_type = IF_VIRTIO;
|
mc->block_default_type = IF_VIRTIO;
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
#define LS3A_INTC_IP 8
|
#define LS3A_INTC_IP 8
|
||||||
#define EXTIOI_IRQS (256)
|
#define EXTIOI_IRQS (256)
|
||||||
#define EXTIOI_IRQS_BITMAP_SIZE (256 / 8)
|
#define EXTIOI_IRQS_BITMAP_SIZE (256 / 8)
|
||||||
|
/* irq from EXTIOI is routed to no more than 4 cpus */
|
||||||
|
#define EXTIOI_CPUS (4)
|
||||||
/* map to ipnum per 32 irqs */
|
/* map to ipnum per 32 irqs */
|
||||||
#define EXTIOI_IRQS_IPMAP_SIZE (256 / 32)
|
#define EXTIOI_IRQS_IPMAP_SIZE (256 / 32)
|
||||||
#define EXTIOI_IRQS_COREMAP_SIZE 256
|
#define EXTIOI_IRQS_COREMAP_SIZE 256
|
||||||
|
@ -46,17 +48,17 @@ struct LoongArchExtIOI {
|
||||||
uint32_t nodetype[EXTIOI_IRQS_NODETYPE_COUNT / 2];
|
uint32_t nodetype[EXTIOI_IRQS_NODETYPE_COUNT / 2];
|
||||||
uint32_t bounce[EXTIOI_IRQS_GROUP_COUNT];
|
uint32_t bounce[EXTIOI_IRQS_GROUP_COUNT];
|
||||||
uint32_t isr[EXTIOI_IRQS / 32];
|
uint32_t isr[EXTIOI_IRQS / 32];
|
||||||
uint32_t coreisr[LOONGARCH_MAX_VCPUS][EXTIOI_IRQS_GROUP_COUNT];
|
uint32_t coreisr[EXTIOI_CPUS][EXTIOI_IRQS_GROUP_COUNT];
|
||||||
uint32_t enable[EXTIOI_IRQS / 32];
|
uint32_t enable[EXTIOI_IRQS / 32];
|
||||||
uint32_t ipmap[EXTIOI_IRQS_IPMAP_SIZE / 4];
|
uint32_t ipmap[EXTIOI_IRQS_IPMAP_SIZE / 4];
|
||||||
uint32_t coremap[EXTIOI_IRQS / 4];
|
uint32_t coremap[EXTIOI_IRQS / 4];
|
||||||
uint32_t sw_pending[EXTIOI_IRQS / 32];
|
uint32_t sw_pending[EXTIOI_IRQS / 32];
|
||||||
DECLARE_BITMAP(sw_isr[LOONGARCH_MAX_VCPUS][LS3A_INTC_IP], EXTIOI_IRQS);
|
DECLARE_BITMAP(sw_isr[EXTIOI_CPUS][LS3A_INTC_IP], EXTIOI_IRQS);
|
||||||
uint8_t sw_ipmap[EXTIOI_IRQS_IPMAP_SIZE];
|
uint8_t sw_ipmap[EXTIOI_IRQS_IPMAP_SIZE];
|
||||||
uint8_t sw_coremap[EXTIOI_IRQS];
|
uint8_t sw_coremap[EXTIOI_IRQS];
|
||||||
qemu_irq parent_irq[LOONGARCH_MAX_VCPUS][LS3A_INTC_IP];
|
qemu_irq parent_irq[EXTIOI_CPUS][LS3A_INTC_IP];
|
||||||
qemu_irq irq[EXTIOI_IRQS];
|
qemu_irq irq[EXTIOI_IRQS];
|
||||||
MemoryRegion extioi_iocsr_mem[LOONGARCH_MAX_VCPUS];
|
MemoryRegion extioi_iocsr_mem[EXTIOI_CPUS];
|
||||||
MemoryRegion extioi_system_mem;
|
MemoryRegion extioi_system_mem;
|
||||||
};
|
};
|
||||||
#endif /* LOONGARCH_EXTIOI_H */
|
#endif /* LOONGARCH_EXTIOI_H */
|
||||||
|
|
|
@ -28,9 +28,6 @@
|
||||||
#define MAIL_SEND_OFFSET 0
|
#define MAIL_SEND_OFFSET 0
|
||||||
#define ANY_SEND_OFFSET (IOCSR_ANY_SEND - IOCSR_MAIL_SEND)
|
#define ANY_SEND_OFFSET (IOCSR_ANY_SEND - IOCSR_MAIL_SEND)
|
||||||
|
|
||||||
#define MAX_IPI_CORE_NUM 4
|
|
||||||
#define MAX_IPI_MBX_NUM 4
|
|
||||||
|
|
||||||
#define TYPE_LOONGARCH_IPI "loongarch_ipi"
|
#define TYPE_LOONGARCH_IPI "loongarch_ipi"
|
||||||
OBJECT_DECLARE_SIMPLE_TYPE(LoongArchIPI, LOONGARCH_IPI)
|
OBJECT_DECLARE_SIMPLE_TYPE(LoongArchIPI, LOONGARCH_IPI)
|
||||||
|
|
||||||
|
@ -40,14 +37,15 @@ typedef struct IPICore {
|
||||||
uint32_t set;
|
uint32_t set;
|
||||||
uint32_t clear;
|
uint32_t clear;
|
||||||
/* 64bit buf divide into 2 32bit buf */
|
/* 64bit buf divide into 2 32bit buf */
|
||||||
uint32_t buf[MAX_IPI_MBX_NUM * 2];
|
uint32_t buf[2];
|
||||||
qemu_irq irq;
|
qemu_irq irq;
|
||||||
} IPICore;
|
} IPICore;
|
||||||
|
|
||||||
struct LoongArchIPI {
|
struct LoongArchIPI {
|
||||||
SysBusDevice parent_obj;
|
SysBusDevice parent_obj;
|
||||||
MemoryRegion ipi_iocsr_mem[MAX_IPI_CORE_NUM];
|
MemoryRegion ipi_iocsr_mem;
|
||||||
MemoryRegion ipi64_iocsr_mem[MAX_IPI_CORE_NUM];
|
MemoryRegion ipi64_iocsr_mem;
|
||||||
|
IPICore ipi_core;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
#include "hw/intc/loongarch_ipi.h"
|
#include "hw/intc/loongarch_ipi.h"
|
||||||
#include "hw/block/flash.h"
|
#include "hw/block/flash.h"
|
||||||
|
|
||||||
#define LOONGARCH_MAX_VCPUS 4
|
#define LOONGARCH_MAX_CPUS 256
|
||||||
|
|
||||||
#define VIRT_ISA_IO_BASE 0x18000000UL
|
#define VIRT_ISA_IO_BASE 0x18000000UL
|
||||||
#define VIRT_ISA_IO_SIZE 0x0004000
|
#define VIRT_ISA_IO_SIZE 0x0004000
|
||||||
|
@ -36,7 +36,6 @@ struct LoongArchMachineState {
|
||||||
/*< private >*/
|
/*< private >*/
|
||||||
MachineState parent_obj;
|
MachineState parent_obj;
|
||||||
|
|
||||||
IPICore ipi_core[MAX_IPI_CORE_NUM];
|
|
||||||
MemoryRegion lowmem;
|
MemoryRegion lowmem;
|
||||||
MemoryRegion highmem;
|
MemoryRegion highmem;
|
||||||
MemoryRegion isa_io;
|
MemoryRegion isa_io;
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
#
|
||||||
|
# LoongArch virt test.
|
||||||
|
#
|
||||||
|
# Copyright (c) 2023 Loongson Technology Corporation Limited
|
||||||
|
#
|
||||||
|
|
||||||
|
from avocado_qemu import QemuSystemTest
|
||||||
|
from avocado_qemu import exec_command_and_wait_for_pattern
|
||||||
|
from avocado_qemu import wait_for_console_pattern
|
||||||
|
|
||||||
|
class LoongArchMachine(QemuSystemTest):
|
||||||
|
KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 '
|
||||||
|
|
||||||
|
timeout = 120
|
||||||
|
|
||||||
|
def wait_for_console_pattern(self, success_message, vm=None):
|
||||||
|
wait_for_console_pattern(self, success_message,
|
||||||
|
failure_message='Kernel panic - not syncing',
|
||||||
|
vm=vm)
|
||||||
|
|
||||||
|
def test_loongarch64_devices(self):
|
||||||
|
|
||||||
|
"""
|
||||||
|
:avocado: tags=arch:loongarch64
|
||||||
|
:avocado: tags=machine:virt
|
||||||
|
"""
|
||||||
|
|
||||||
|
kernel_url = ('https://github.com/yangxiaojuan-loongson/qemu-binary/'
|
||||||
|
'releases/download/binary-files/vmlinuz.efi')
|
||||||
|
kernel_hash = '951b485b16e3788b6db03a3e1793c067009e31a2'
|
||||||
|
kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash)
|
||||||
|
|
||||||
|
initrd_url = ('https://github.com/yangxiaojuan-loongson/qemu-binary/'
|
||||||
|
'releases/download/binary-files/ramdisk')
|
||||||
|
initrd_hash = 'c67658d9b2a447ce7db2f73ba3d373c9b2b90ab2'
|
||||||
|
initrd_path = self.fetch_asset(initrd_url, asset_hash=initrd_hash)
|
||||||
|
|
||||||
|
bios_url = ('https://github.com/yangxiaojuan-loongson/qemu-binary/'
|
||||||
|
'releases/download/binary-files/QEMU_EFI.fd')
|
||||||
|
bios_hash = ('dfc1bfba4853cd763b9d392d0031827e8addbca8')
|
||||||
|
bios_path = self.fetch_asset(bios_url, asset_hash=bios_hash)
|
||||||
|
|
||||||
|
self.vm.set_console()
|
||||||
|
kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
|
||||||
|
'root=/dev/ram rdinit=/sbin/init console=ttyS0,115200')
|
||||||
|
self.vm.add_args('-nographic',
|
||||||
|
'-smp', '4',
|
||||||
|
'-m', '1024',
|
||||||
|
'-cpu', 'la464',
|
||||||
|
'-kernel', kernel_path,
|
||||||
|
'-initrd', initrd_path,
|
||||||
|
'-bios', bios_path,
|
||||||
|
'-append', kernel_command_line)
|
||||||
|
self.vm.launch()
|
||||||
|
self.wait_for_console_pattern('Run /sbin/init as init process')
|
||||||
|
exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo',
|
||||||
|
'processor : 3')
|
Loading…
Reference in New Issue