target/loongarch: Adjust functions and structure to support user-mode
Some functions and member of the structure are different with softmmu-mode So we need adjust them to support user-mode. Signed-off-by: Song Gao <gaosong@loongson.cn> Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-Id: <20220624031049.1716097-12-gaosong@loongson.cn> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
parent
9bc92b5013
commit
0093b9a5ee
|
@ -82,6 +82,7 @@ static void loongarch_cpu_set_pc(CPUState *cs, vaddr value)
|
||||||
env->pc = value;
|
env->pc = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef CONFIG_USER_ONLY
|
||||||
#include "hw/loongarch/virt.h"
|
#include "hw/loongarch/virt.h"
|
||||||
|
|
||||||
void loongarch_cpu_set_irq(void *opaque, int irq, int level)
|
void loongarch_cpu_set_irq(void *opaque, int irq, int level)
|
||||||
|
@ -295,6 +296,7 @@ static bool loongarch_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_TCG
|
#ifdef CONFIG_TCG
|
||||||
static void loongarch_cpu_synchronize_from_tb(CPUState *cs,
|
static void loongarch_cpu_synchronize_from_tb(CPUState *cs,
|
||||||
|
@ -309,6 +311,9 @@ static void loongarch_cpu_synchronize_from_tb(CPUState *cs,
|
||||||
|
|
||||||
static bool loongarch_cpu_has_work(CPUState *cs)
|
static bool loongarch_cpu_has_work(CPUState *cs)
|
||||||
{
|
{
|
||||||
|
#ifdef CONFIG_USER_ONLY
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
LoongArchCPU *cpu = LOONGARCH_CPU(cs);
|
LoongArchCPU *cpu = LOONGARCH_CPU(cs);
|
||||||
CPULoongArchState *env = &cpu->env;
|
CPULoongArchState *env = &cpu->env;
|
||||||
bool has_work = false;
|
bool has_work = false;
|
||||||
|
@ -319,6 +324,7 @@ static bool loongarch_cpu_has_work(CPUState *cs)
|
||||||
}
|
}
|
||||||
|
|
||||||
return has_work;
|
return has_work;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void loongarch_la464_initfn(Object *obj)
|
static void loongarch_la464_initfn(Object *obj)
|
||||||
|
@ -467,7 +473,9 @@ static void loongarch_cpu_reset(DeviceState *dev)
|
||||||
env->CSR_DMW[n] = FIELD_DP64(env->CSR_DMW[n], CSR_DMW, PLV3, 0);
|
env->CSR_DMW[n] = FIELD_DP64(env->CSR_DMW[n], CSR_DMW, PLV3, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef CONFIG_USER_ONLY
|
||||||
env->pc = 0x1c000000;
|
env->pc = 0x1c000000;
|
||||||
|
#endif
|
||||||
|
|
||||||
restore_fp_status(env);
|
restore_fp_status(env);
|
||||||
cs->exception_index = -1;
|
cs->exception_index = -1;
|
||||||
|
@ -498,6 +506,7 @@ static void loongarch_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||||
lacc->parent_realize(dev, errp);
|
lacc->parent_realize(dev, errp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef CONFIG_USER_ONLY
|
||||||
static void loongarch_qemu_write(void *opaque, hwaddr addr,
|
static void loongarch_qemu_write(void *opaque, hwaddr addr,
|
||||||
uint64_t val, unsigned size)
|
uint64_t val, unsigned size)
|
||||||
{
|
{
|
||||||
|
@ -532,13 +541,16 @@ static const MemoryRegionOps loongarch_qemu_ops = {
|
||||||
.max_access_size = 8,
|
.max_access_size = 8,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
static void loongarch_cpu_init(Object *obj)
|
static void loongarch_cpu_init(Object *obj)
|
||||||
{
|
{
|
||||||
LoongArchCPU *cpu = LOONGARCH_CPU(obj);
|
LoongArchCPU *cpu = LOONGARCH_CPU(obj);
|
||||||
CPULoongArchState *env = &cpu->env;
|
|
||||||
|
|
||||||
cpu_set_cpustate_pointers(cpu);
|
cpu_set_cpustate_pointers(cpu);
|
||||||
|
|
||||||
|
#ifndef CONFIG_USER_ONLY
|
||||||
|
CPULoongArchState *env = &cpu->env;
|
||||||
qdev_init_gpio_in(DEVICE(cpu), loongarch_cpu_set_irq, N_IRQS);
|
qdev_init_gpio_in(DEVICE(cpu), loongarch_cpu_set_irq, N_IRQS);
|
||||||
timer_init_ns(&cpu->timer, QEMU_CLOCK_VIRTUAL,
|
timer_init_ns(&cpu->timer, QEMU_CLOCK_VIRTUAL,
|
||||||
&loongarch_constant_timer_cb, cpu);
|
&loongarch_constant_timer_cb, cpu);
|
||||||
|
@ -548,6 +560,7 @@ static void loongarch_cpu_init(Object *obj)
|
||||||
memory_region_init_io(&env->iocsr_mem, OBJECT(cpu), &loongarch_qemu_ops,
|
memory_region_init_io(&env->iocsr_mem, OBJECT(cpu), &loongarch_qemu_ops,
|
||||||
NULL, "iocsr_misc", 0x428);
|
NULL, "iocsr_misc", 0x428);
|
||||||
memory_region_add_subregion(&env->system_iocsr, 0, &env->iocsr_mem);
|
memory_region_add_subregion(&env->system_iocsr, 0, &env->iocsr_mem);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static ObjectClass *loongarch_cpu_class_by_name(const char *cpu_model)
|
static ObjectClass *loongarch_cpu_class_by_name(const char *cpu_model)
|
||||||
|
@ -615,18 +628,22 @@ static struct TCGCPUOps loongarch_tcg_ops = {
|
||||||
.initialize = loongarch_translate_init,
|
.initialize = loongarch_translate_init,
|
||||||
.synchronize_from_tb = loongarch_cpu_synchronize_from_tb,
|
.synchronize_from_tb = loongarch_cpu_synchronize_from_tb,
|
||||||
|
|
||||||
|
#ifndef CONFIG_USER_ONLY
|
||||||
.tlb_fill = loongarch_cpu_tlb_fill,
|
.tlb_fill = loongarch_cpu_tlb_fill,
|
||||||
.cpu_exec_interrupt = loongarch_cpu_exec_interrupt,
|
.cpu_exec_interrupt = loongarch_cpu_exec_interrupt,
|
||||||
.do_interrupt = loongarch_cpu_do_interrupt,
|
.do_interrupt = loongarch_cpu_do_interrupt,
|
||||||
.do_transaction_failed = loongarch_cpu_do_transaction_failed,
|
.do_transaction_failed = loongarch_cpu_do_transaction_failed,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
#endif /* CONFIG_TCG */
|
#endif /* CONFIG_TCG */
|
||||||
|
|
||||||
|
#ifndef CONFIG_USER_ONLY
|
||||||
#include "hw/core/sysemu-cpu-ops.h"
|
#include "hw/core/sysemu-cpu-ops.h"
|
||||||
|
|
||||||
static const struct SysemuCPUOps loongarch_sysemu_ops = {
|
static const struct SysemuCPUOps loongarch_sysemu_ops = {
|
||||||
.get_phys_page_debug = loongarch_cpu_get_phys_page_debug,
|
.get_phys_page_debug = loongarch_cpu_get_phys_page_debug,
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
static void loongarch_cpu_class_init(ObjectClass *c, void *data)
|
static void loongarch_cpu_class_init(ObjectClass *c, void *data)
|
||||||
{
|
{
|
||||||
|
@ -642,8 +659,10 @@ static void loongarch_cpu_class_init(ObjectClass *c, void *data)
|
||||||
cc->has_work = loongarch_cpu_has_work;
|
cc->has_work = loongarch_cpu_has_work;
|
||||||
cc->dump_state = loongarch_cpu_dump_state;
|
cc->dump_state = loongarch_cpu_dump_state;
|
||||||
cc->set_pc = loongarch_cpu_set_pc;
|
cc->set_pc = loongarch_cpu_set_pc;
|
||||||
|
#ifndef CONFIG_USER_ONLY
|
||||||
dc->vmsd = &vmstate_loongarch_cpu;
|
dc->vmsd = &vmstate_loongarch_cpu;
|
||||||
cc->sysemu_ops = &loongarch_sysemu_ops;
|
cc->sysemu_ops = &loongarch_sysemu_ops;
|
||||||
|
#endif
|
||||||
cc->disas_set_info = loongarch_cpu_disas_set_info;
|
cc->disas_set_info = loongarch_cpu_disas_set_info;
|
||||||
cc->gdb_read_register = loongarch_cpu_gdb_read_register;
|
cc->gdb_read_register = loongarch_cpu_gdb_read_register;
|
||||||
cc->gdb_write_register = loongarch_cpu_gdb_write_register;
|
cc->gdb_write_register = loongarch_cpu_gdb_write_register;
|
||||||
|
|
|
@ -301,6 +301,7 @@ typedef struct CPUArchState {
|
||||||
uint64_t CSR_DERA;
|
uint64_t CSR_DERA;
|
||||||
uint64_t CSR_DSAVE;
|
uint64_t CSR_DSAVE;
|
||||||
|
|
||||||
|
#ifndef CONFIG_USER_ONLY
|
||||||
LoongArchTLB tlb[LOONGARCH_TLB_MAX];
|
LoongArchTLB tlb[LOONGARCH_TLB_MAX];
|
||||||
|
|
||||||
AddressSpace address_space_iocsr;
|
AddressSpace address_space_iocsr;
|
||||||
|
@ -308,6 +309,7 @@ typedef struct CPUArchState {
|
||||||
MemoryRegion iocsr_mem;
|
MemoryRegion iocsr_mem;
|
||||||
bool load_elf;
|
bool load_elf;
|
||||||
uint64_t elf_address;
|
uint64_t elf_address;
|
||||||
|
#endif
|
||||||
} CPULoongArchState;
|
} CPULoongArchState;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -358,12 +360,16 @@ struct LoongArchCPUClass {
|
||||||
|
|
||||||
static inline int cpu_mmu_index(CPULoongArchState *env, bool ifetch)
|
static inline int cpu_mmu_index(CPULoongArchState *env, bool ifetch)
|
||||||
{
|
{
|
||||||
|
#ifdef CONFIG_USER_ONLY
|
||||||
|
return MMU_USER_IDX;
|
||||||
|
#else
|
||||||
uint8_t pg = FIELD_EX64(env->CSR_CRMD, CSR_CRMD, PG);
|
uint8_t pg = FIELD_EX64(env->CSR_CRMD, CSR_CRMD, PG);
|
||||||
|
|
||||||
if (!pg) {
|
if (!pg) {
|
||||||
return MMU_DA_IDX;
|
return MMU_DA_IDX;
|
||||||
}
|
}
|
||||||
return FIELD_EX64(env->CSR_CRMD, CSR_CRMD, PLV);
|
return FIELD_EX64(env->CSR_CRMD, CSR_CRMD, PLV);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void cpu_get_tb_cpu_state(CPULoongArchState *env,
|
static inline void cpu_get_tb_cpu_state(CPULoongArchState *env,
|
||||||
|
|
|
@ -95,6 +95,7 @@ DEF_HELPER_FLAGS_2(set_rounding_mode, TCG_CALL_NO_RWG, void, env, i32)
|
||||||
|
|
||||||
DEF_HELPER_1(rdtime_d, i64, env)
|
DEF_HELPER_1(rdtime_d, i64, env)
|
||||||
|
|
||||||
|
#ifndef CONFIG_USER_ONLY
|
||||||
/* CSRs helper */
|
/* CSRs helper */
|
||||||
DEF_HELPER_1(csrrd_pgd, i64, env)
|
DEF_HELPER_1(csrrd_pgd, i64, env)
|
||||||
DEF_HELPER_1(csrrd_tval, i64, env)
|
DEF_HELPER_1(csrrd_tval, i64, env)
|
||||||
|
@ -128,3 +129,4 @@ DEF_HELPER_4(lddir, tl, env, tl, tl, i32)
|
||||||
DEF_HELPER_4(ldpte, void, env, tl, tl, i32)
|
DEF_HELPER_4(ldpte, void, env, tl, tl, i32)
|
||||||
DEF_HELPER_1(ertn, void, env)
|
DEF_HELPER_1(ertn, void, env)
|
||||||
DEF_HELPER_1(idle, void, env)
|
DEF_HELPER_1(idle, void, env)
|
||||||
|
#endif
|
||||||
|
|
|
@ -7,6 +7,41 @@
|
||||||
|
|
||||||
#include "cpu-csr.h"
|
#include "cpu-csr.h"
|
||||||
|
|
||||||
|
#ifdef CONFIG_USER_ONLY
|
||||||
|
|
||||||
|
#define GEN_FALSE_TRANS(name) \
|
||||||
|
static bool trans_##name(DisasContext *ctx, arg_##name * a) \
|
||||||
|
{ \
|
||||||
|
return false; \
|
||||||
|
}
|
||||||
|
|
||||||
|
GEN_FALSE_TRANS(csrrd)
|
||||||
|
GEN_FALSE_TRANS(csrwr)
|
||||||
|
GEN_FALSE_TRANS(csrxchg)
|
||||||
|
GEN_FALSE_TRANS(iocsrrd_b)
|
||||||
|
GEN_FALSE_TRANS(iocsrrd_h)
|
||||||
|
GEN_FALSE_TRANS(iocsrrd_w)
|
||||||
|
GEN_FALSE_TRANS(iocsrrd_d)
|
||||||
|
GEN_FALSE_TRANS(iocsrwr_b)
|
||||||
|
GEN_FALSE_TRANS(iocsrwr_h)
|
||||||
|
GEN_FALSE_TRANS(iocsrwr_w)
|
||||||
|
GEN_FALSE_TRANS(iocsrwr_d)
|
||||||
|
GEN_FALSE_TRANS(tlbsrch)
|
||||||
|
GEN_FALSE_TRANS(tlbrd)
|
||||||
|
GEN_FALSE_TRANS(tlbwr)
|
||||||
|
GEN_FALSE_TRANS(tlbfill)
|
||||||
|
GEN_FALSE_TRANS(tlbclr)
|
||||||
|
GEN_FALSE_TRANS(tlbflush)
|
||||||
|
GEN_FALSE_TRANS(invtlb)
|
||||||
|
GEN_FALSE_TRANS(cacop)
|
||||||
|
GEN_FALSE_TRANS(ldpte)
|
||||||
|
GEN_FALSE_TRANS(lddir)
|
||||||
|
GEN_FALSE_TRANS(ertn)
|
||||||
|
GEN_FALSE_TRANS(dbcl)
|
||||||
|
GEN_FALSE_TRANS(idle)
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
typedef void (*GenCSRRead)(TCGv dest, TCGv_ptr env);
|
typedef void (*GenCSRRead)(TCGv dest, TCGv_ptr env);
|
||||||
typedef void (*GenCSRWrite)(TCGv dest, TCGv_ptr env, TCGv src);
|
typedef void (*GenCSRWrite)(TCGv dest, TCGv_ptr env, TCGv src);
|
||||||
|
|
||||||
|
@ -464,3 +499,4 @@ static bool trans_idle(DisasContext *ctx, arg_idle *a)
|
||||||
ctx->base.is_jmp = DISAS_NORETURN;
|
ctx->base.is_jmp = DISAS_NORETURN;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
|
@ -33,6 +33,7 @@ const char *loongarch_exception_name(int32_t exception);
|
||||||
|
|
||||||
void restore_fp_status(CPULoongArchState *env);
|
void restore_fp_status(CPULoongArchState *env);
|
||||||
|
|
||||||
|
#ifndef CONFIG_USER_ONLY
|
||||||
extern const VMStateDescription vmstate_loongarch_cpu;
|
extern const VMStateDescription vmstate_loongarch_cpu;
|
||||||
|
|
||||||
void loongarch_cpu_set_irq(void *opaque, int irq, int level);
|
void loongarch_cpu_set_irq(void *opaque, int irq, int level);
|
||||||
|
@ -48,6 +49,7 @@ bool loongarch_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
|
||||||
bool probe, uintptr_t retaddr);
|
bool probe, uintptr_t retaddr);
|
||||||
|
|
||||||
hwaddr loongarch_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
|
hwaddr loongarch_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
|
||||||
|
#endif /* !CONFIG_USER_ONLY */
|
||||||
|
|
||||||
int loongarch_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n);
|
int loongarch_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n);
|
||||||
int loongarch_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n);
|
int loongarch_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n);
|
||||||
|
|
|
@ -86,6 +86,9 @@ target_ulong helper_cpucfg(CPULoongArchState *env, target_ulong rj)
|
||||||
|
|
||||||
uint64_t helper_rdtime_d(CPULoongArchState *env)
|
uint64_t helper_rdtime_d(CPULoongArchState *env)
|
||||||
{
|
{
|
||||||
|
#ifdef CONFIG_USER_ONLY
|
||||||
|
return cpu_get_host_ticks();
|
||||||
|
#else
|
||||||
uint64_t plv;
|
uint64_t plv;
|
||||||
LoongArchCPU *cpu = env_archcpu(env);
|
LoongArchCPU *cpu = env_archcpu(env);
|
||||||
|
|
||||||
|
@ -95,8 +98,10 @@ uint64_t helper_rdtime_d(CPULoongArchState *env)
|
||||||
}
|
}
|
||||||
|
|
||||||
return cpu_loongarch_get_constant_timer_counter(cpu);
|
return cpu_loongarch_get_constant_timer_counter(cpu);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef CONFIG_USER_ONLY
|
||||||
void helper_ertn(CPULoongArchState *env)
|
void helper_ertn(CPULoongArchState *env)
|
||||||
{
|
{
|
||||||
uint64_t csr_pplv, csr_pie;
|
uint64_t csr_pplv, csr_pie;
|
||||||
|
@ -131,3 +136,4 @@ void helper_idle(CPULoongArchState *env)
|
||||||
cs->halted = 1;
|
cs->halted = 1;
|
||||||
do_raise_exception(env, EXCP_HLT, 0);
|
do_raise_exception(env, EXCP_HLT, 0);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue