hw/xtensa: xtfpga: use MX PIC for SMP
Create and use MX PIC as a peripheral interrupt controller when more than 1 processor is enabled on xtfpga board. Connect xtensa CPU cores to the MX PIC and select secondary reset vector on all cores except the first one. Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
This commit is contained in:
parent
10df8ff146
commit
1acd90bff2
|
@ -45,6 +45,7 @@
|
||||||
#include "qemu/option.h"
|
#include "qemu/option.h"
|
||||||
#include "bootparam.h"
|
#include "bootparam.h"
|
||||||
#include "xtensa_memory.h"
|
#include "xtensa_memory.h"
|
||||||
|
#include "hw/xtensa/mx_pic.h"
|
||||||
|
|
||||||
typedef struct XtfpgaFlashDesc {
|
typedef struct XtfpgaFlashDesc {
|
||||||
hwaddr base;
|
hwaddr base;
|
||||||
|
@ -225,6 +226,7 @@ static void xtfpga_init(const XtfpgaBoardDesc *board, MachineState *machine)
|
||||||
XtensaCPU *cpu = NULL;
|
XtensaCPU *cpu = NULL;
|
||||||
CPUXtensaState *env = NULL;
|
CPUXtensaState *env = NULL;
|
||||||
MemoryRegion *system_io;
|
MemoryRegion *system_io;
|
||||||
|
XtensaMxPic *mx_pic = NULL;
|
||||||
qemu_irq *extints;
|
qemu_irq *extints;
|
||||||
DriveInfo *dinfo;
|
DriveInfo *dinfo;
|
||||||
pflash_t *flash = NULL;
|
pflash_t *flash = NULL;
|
||||||
|
@ -237,6 +239,10 @@ static void xtfpga_init(const XtfpgaBoardDesc *board, MachineState *machine)
|
||||||
uint32_t freq = 10000000;
|
uint32_t freq = 10000000;
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
|
if (smp_cpus > 1) {
|
||||||
|
mx_pic = xtensa_mx_pic_init(31);
|
||||||
|
qemu_register_reset(xtensa_mx_pic_reset, mx_pic);
|
||||||
|
}
|
||||||
for (n = 0; n < smp_cpus; n++) {
|
for (n = 0; n < smp_cpus; n++) {
|
||||||
CPUXtensaState *cenv = NULL;
|
CPUXtensaState *cenv = NULL;
|
||||||
|
|
||||||
|
@ -247,14 +253,28 @@ static void xtfpga_init(const XtfpgaBoardDesc *board, MachineState *machine)
|
||||||
freq = env->config->clock_freq_khz * 1000;
|
freq = env->config->clock_freq_khz * 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mx_pic) {
|
||||||
|
MemoryRegion *mx_eri;
|
||||||
|
|
||||||
|
mx_eri = xtensa_mx_pic_register_cpu(mx_pic,
|
||||||
|
xtensa_get_extints(cenv),
|
||||||
|
xtensa_get_runstall(cenv));
|
||||||
|
memory_region_add_subregion(xtensa_get_er_region(cenv),
|
||||||
|
0, mx_eri);
|
||||||
|
}
|
||||||
cenv->sregs[PRID] = n;
|
cenv->sregs[PRID] = n;
|
||||||
|
xtensa_select_static_vectors(cenv, n != 0);
|
||||||
qemu_register_reset(xtfpga_reset, cpu);
|
qemu_register_reset(xtfpga_reset, cpu);
|
||||||
/* Need MMU initialized prior to ELF loading,
|
/* Need MMU initialized prior to ELF loading,
|
||||||
* so that ELF gets loaded into virtual addresses
|
* so that ELF gets loaded into virtual addresses
|
||||||
*/
|
*/
|
||||||
cpu_reset(CPU(cpu));
|
cpu_reset(CPU(cpu));
|
||||||
}
|
}
|
||||||
extints = xtensa_get_extints(env);
|
if (smp_cpus > 1) {
|
||||||
|
extints = xtensa_mx_pic_get_extints(mx_pic);
|
||||||
|
} else {
|
||||||
|
extints = xtensa_get_extints(env);
|
||||||
|
}
|
||||||
|
|
||||||
if (env) {
|
if (env) {
|
||||||
XtensaMemory sysram = env->config->sysram;
|
XtensaMemory sysram = env->config->sysram;
|
||||||
|
|
Loading…
Reference in a new issue