target/xtensa: add linux-user support
PATCH v7 9/11 target/xtensa: add linux-user support
Import list of syscalls from the kernel source. Conditionalize code/data that is only used with softmmu. Implement exception handlers. Implement signal hander (only the core registers for now, no coprocessors or TIE).
---
Changes v6->v7:
- fix vaddr print format from %lx to %VADDR_PRIx
Changes v1->v2:
- add definition of TARGET_TIOCGPTPEER to linux-user/xtensa/termbits.h
- Cc linux-user maintainers
default-configs/xtensa-linux-user.mak | 1 + default-configs/xtensaeb-linux-user.mak | 1 + linux-user/elfload.c | 58 +++++ linux-user/main.c | 245 ++++++++++++++++++ linux-user/signal.c | 256 ++++++++++++++++++- linux-user/syscall.c | 2 + linux-user/syscall_defs.h | 65 ++++- linux-user/xtensa/syscall.h | 0 linux-user/xtensa/syscall_nr.h | 437 ++++++++++++++++++++++++++++++++ linux-user/xtensa/target_cpu.h | 22 ++ linux-user/xtensa/target_elf.h | 16 ++ linux-user/xtensa/target_signal.h | 28 ++ linux-user/xtensa/target_structs.h | 28 ++ linux-user/xtensa/target_syscall.h | 49 ++++ linux-user/xtensa/termbits.h | 328 ++++++++++++++++++++++++ target/xtensa/Makefile.objs | 3 +- target/xtensa/cpu.c | 26 +- target/xtensa/cpu.h | 56 ++-- target/xtensa/helper.c | 31 +++ target/xtensa/helper.h | 4 + target/xtensa/op_helper.c | 50 +++- target/xtensa/translate.c | 43 +++- 22 files changed, 1705 insertions(+), 44 deletions(-) create mode 100644 default-configs/xtensa-linux-user.mak create mode 100644 default-configs/xtensaeb-linux-user.mak create mode 100644 linux-user/xtensa/syscall.h create mode 100644 linux-user/xtensa/syscall_nr.h create mode 100644 linux-user/xtensa/target_cpu.h create mode 100644 linux-user/xtensa/target_elf.h create mode 100644 linux-user/xtensa/target_signal.h create mode 100644 linux-user/xtensa/target_structs.h create mode 100644 linux-user/xtensa/target_syscall.h create mode 100644 linux-user/xtensa/termbits.h
default-configs/xtensa-linux-user.mak new file +1 -0
@@ -0,0 +1 @@ +# Default configuration for xtensa-linux-user
default-configs/xtensaeb-linux-user.mak new file +1 -0
@@ -0,0 +1 @@ +# Default configuration for xtensa-linux-user
linux-user/elfload.c +58 -0
64 lines not on this page · raw message
linux-user/main.c +245 -0
257 lines not on this page · raw message
linux-user/signal.c +255 -1
268 lines not on this page · raw message
linux-user/syscall.c +2 -0
@@ -709,6 +709,8 @@ static inline int regpairs_aligned(void *cpu_env, int num) return 0; } } +#elif defined(TARGET_XTENSA) +static inline int regpairs_aligned (void *cpu_env,int num) {return 1 ; }#else static inline int regpairs_aligned (void *cpu_env,int num) {return 0 ; }#endif
linux-user/syscall_defs.h +62 -3
95 lines not on this page · raw message
linux-user/xtensa/syscall.h new file +0 -0
linux-user/xtensa/syscall_nr.h new file +437 -0
437 lines not on this page · raw message
linux-user/xtensa/target_cpu.h new file +22 -0
@@ -0,0 +1,22 @@ +/* +* Xtensa-specific CPU ABI and functions for linux-user +*/ +#ifndef XTENSA_TARGET_CPU_H +#define XTENSA_TARGET_CPU_H + +static inline void cpu_clone_regs (CPUXtensaState *env,target_ulong newsp) +{ +if (newsp) { + env->regs[1 ] = newsp; + env->sregs[WINDOW_BASE ] =0 ; + env->sregs[WINDOW_START ] =0x1 ; + } + env->regs[2 ] =0 ; +} + +static inline void cpu_set_tls (CPUXtensaState *env,target_ulong newtls) +{ + env->uregs[THREADPTR ] = newtls; +} + +#endif
linux-user/xtensa/target_elf.h new file +16 -0
@@ -0,0 +1,16 @@ +/* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation, or (at your option) any +* later version. See the COPYING file in the top-level directory. +*/ + +#ifndef XTENSA_TARGET_ELF_H +#define XTENSA_TARGET_ELF_H + +static inline const char *cpu_get_model (uint32_t eflags) +{ +return XTENSA_DEFAULT_CPU_MODEL ; +} + +#endif
linux-user/xtensa/target_signal.h new file +28 -0
@@ -0,0 +1,28 @@ +#ifndef XTENSA_TARGET_SIGNAL_H +#define XTENSA_TARGET_SIGNAL_H + +#include "cpu.h" + +/* this struct defines a stack used during syscall handling */ + +typedef struct target_sigaltstack { +abi_ulong ss_sp; +abi_int ss_flags; +abi_ulong ss_size; +}target_stack_t ; + +/* +* sigaltstack controls +*/ +#define TARGET_SS_ONSTACK 1 +#define TARGET_SS_DISABLE 2 + +#define TARGET_MINSIGSTKSZ 2048 +#define TARGET_SIGSTKSZ 8192 + +static inline abi_ulong get_sp_from_cpustate (CPUXtensaState *state) +{ +return state->regs[1 ]; +} + +#endif
linux-user/xtensa/target_structs.h new file +28 -0
@@ -0,0 +1,28 @@ +#ifndef XTENSA_TARGET_STRUCTS_T +#define XTENSA_TARGET_STRUCTS_T + +struct target_ipc_perm { +abi_int __key;/* Key. */ +abi_uint uid;/* Owner's user ID. */ +abi_uint gid;/* Owner's group ID. */ +abi_uint cuid;/* Creator's user ID. */ +abi_uint cgid;/* Creator's group ID. */ +abi_uint mode;/* Read/write permission. */ +abi_ushort __seq;/* Sequence number. */ +}; + +struct target_shmid_ds { +struct target_ipc_perm shm_perm;/* operation permission struct */ +abi_int shm_segsz;/* size of segment in bytes */ +abi_long shm_atime;/* time of last shmat() */ +abi_long shm_dtime;/* time of last shmdt() */ +abi_long shm_ctime;/* time of last change by shmctl() */ +abi_ushort shm_cpid;/* pid of creator */ +abi_ushort shm_lpid;/* pid of last shmop */ +abi_ushort shm_nattch;/* number of current attaches */ +abi_ushort shm_unused;/* compatibility */ +abi_ulong __unused2; +abi_ulong __unused3; +}; + +#endif
linux-user/xtensa/target_syscall.h new file +49 -0
49 lines not on this page · raw message
linux-user/xtensa/termbits.h new file +328 -0
328 lines not on this page · raw message
target/xtensa/Makefile.objs +1 -2
@@ -1,10 +1,9 @@ -obj-y += xtensa-semi.o obj-y += core-dc232b.o obj-y += core-dc233c.o obj-y += core-de212.o obj-y += core-fsf.o obj-y += core-sample_controller.o -obj-$(CONFIG_SOFTMMU) += monitor.o +obj-$(CONFIG_SOFTMMU) += monitor.o xtensa-semi.o obj-y += xtensa-isa.o obj-y += translate.o op_helper.o helper.o cpu.o obj-y += gdbstub.o
target/xtensa/cpu.c +22 -4
@@ -45,9 +45,13 @@ static void xtensa_cpu_set_pc(CPUState *cs, vaddr value)static bool xtensa_cpu_has_work (CPUState *cs) { +#ifndef CONFIG_USER_ONLY XtensaCPU *cpu =XTENSA_CPU (cs);return !cpu->env.runstall && cpu->env.pending_irq_level; +#else +return true; +#endif }/* CPUClass::reset() */
@@ -62,8 +66,16 @@ static void xtensa_cpu_reset(CPUState *s) env->exception_taken =0 ; env->pc = env->config->exception_vector[EXC_RESET0 + env->static_vectors]; env->sregs[LITBASE ] &= ~1 ; +#ifndef CONFIG_USER_ONLY env->sregs[PS ] =xtensa_option_enabled (env->config,XTENSA_OPTION_INTERRUPT ) ?0x1f :0x10 ; + env->pending_irq_level =0 ; +#else + env->sregs[PS ] = + (xtensa_option_enabled (env->config, +XTENSA_OPTION_WINDOWED_REGISTER ) ?PS_WOE :0 ) | +PS_UM | (3 <<PS_RING_SHIFT ); +#endif env->sregs[VECBASE ] = env->config->vecbase; env->sregs[IBREAKENABLE ] =0 ; env->sregs[MEMCTL ] =MEMCTL_IL0EN & env->config->memctl_mask;
@@ -73,9 +85,10 @@ static void xtensa_cpu_reset(CPUState *s) env->sregs[CONFIGID0 ] = env->config->configid[0 ]; env->sregs[CONFIGID1 ] = env->config->configid[1 ]; - env->pending_irq_level =0 ; +#ifndef CONFIG_USER_ONLY reset_mmu (env); s->halted = env->runstall; +#endif }static ObjectClass *xtensa_cpu_class_by_name (const char *cpu_model)
@@ -104,11 +117,12 @@ static void xtensa_cpu_disas_set_info(CPUState *cs, disassemble_info *info)static void xtensa_cpu_realizefn (DeviceState *dev,Error **errp) {CPUState *cs =CPU (dev); -XtensaCPU *cpu =XTENSA_CPU (dev);XtensaCPUClass *xcc =XTENSA_CPU_GET_CLASS (dev);Error *local_err =NULL ; -xtensa_irq_init (&cpu->env); +#ifndef CONFIG_USER_ONLY +xtensa_irq_init (&XTENSA_CPU (dev)->env); +#endif cpu_exec_realizefn (cs, &local_err);if (local_err !=NULL ) {
@@ -133,11 +147,13 @@ static void xtensa_cpu_initfn(Object *obj) cs->env_ptr = env; env->config = xcc->config; +#ifndef CONFIG_USER_ONLY env->address_space_er =g_malloc (sizeof (*env->address_space_er)); env->system_er =g_malloc (sizeof (*env->system_er));memory_region_init_io (env->system_er,NULL ,NULL , env,"er" ,UINT64_C (0x100000000 ));address_space_init (env->address_space_er, env->system_er,"ER" ); +#endif }static const VMStateDescription vmstate_xtensa_cpu = {
@@ -166,7 +182,9 @@ static void xtensa_cpu_class_init(ObjectClass *oc, void *data) cc->gdb_read_register = xtensa_cpu_gdb_read_register; cc->gdb_write_register = xtensa_cpu_gdb_write_register; cc->gdb_stop_before_watchpoint = true; -#ifndef CONFIG_USER_ONLY +#ifdef CONFIG_USER_ONLY + cc->handle_mmu_fault = xtensa_cpu_handle_mmu_fault; +#else cc->do_unaligned_access = xtensa_cpu_do_unaligned_access; cc->get_phys_page_debug = xtensa_cpu_get_phys_page_debug; cc->do_unassigned_access = xtensa_cpu_do_unassigned_access;
target/xtensa/cpu.h +37 -19
112 lines not on this page · raw message
target/xtensa/helper.c +31 -0
@@ -173,6 +173,7 @@ void xtensa_cpu_list(FILE *f, fprintf_function cpu_fprintf)hwaddr xtensa_cpu_get_phys_page_debug (CPUState *cs,vaddr addr) { +#ifndef CONFIG_USER_ONLY XtensaCPU *cpu =XTENSA_CPU (cs);uint32_t paddr;uint32_t page_size;
@@ -187,8 +188,13 @@ hwaddr xtensa_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)return paddr; }return ~0 ; +#else +return addr; +#endif } +#ifndef CONFIG_USER_ONLY +static uint32_t relocated_vector (CPUXtensaState *env,uint32_t vector) { if (xtensa_option_enabled(env->config,
@@ -298,6 +304,11 @@ void xtensa_cpu_do_interrupt(CPUState *cs) }check_interrupts (env); } +#else +void xtensa_cpu_do_interrupt (CPUState *cs) +{ +} +#endif bool xtensa_cpu_exec_interrupt (CPUState *cs,int interrupt_request) {
@@ -309,6 +320,25 @@ bool xtensa_cpu_exec_interrupt(CPUState *cs, int interrupt_request)return false; } +#ifdef CONFIG_USER_ONLY + +int xtensa_cpu_handle_mmu_fault (CPUState *cs,vaddr address,int size,int rw, +int mmu_idx) +{ +XtensaCPU *cpu =XTENSA_CPU (cs); +CPUXtensaState *env = &cpu->env; + +qemu_log_mask (CPU_LOG_INT , +"%s: rw = %d, address = 0x%08" VADDR_PRIx", size = %d\n" , + __func__, rw, address, size); + env->sregs[EXCVADDR ] = address; + env->sregs[EXCCAUSE ] = rw ?STORE_PROHIBITED_CAUSE :LOAD_PROHIBITED_CAUSE ; + cs->exception_index =EXC_USER ; +return 1 ; +} + +#else +static void reset_tlb_mmu_all_ways (CPUXtensaState *env,const xtensa_tlb *tlb,xtensa_tlb_entry entry[][MAX_TLB_WAY_SIZE ]) {
@@ -769,3 +799,4 @@ void xtensa_runstall(CPUXtensaState *env, bool runstall) cpu_reset_interrupt(cpu, CPU_INTERRUPT_HALT); } } +#endif
target/xtensa/helper.h +4 -0
@@ -12,9 +12,12 @@ DEF_HELPER_1(restore_owb, void, env) DEF_HELPER_2(movsp, void, env, i32) DEF_HELPER_2(wsr_lbeg, void, env, i32) DEF_HELPER_2(wsr_lend, void, env, i32) +#ifndef CONFIG_USER_ONLY DEF_HELPER_1(simcall, void, env) +#endif DEF_HELPER_1(dump_state, void, env) +#ifndef CONFIG_USER_ONLY DEF_HELPER_3(waiti, void, env, i32, i32) DEF_HELPER_1(update_ccount, void, env)DEF_HELPER_2 (wsr_ccount, void, env, i32)
@@ -35,6 +38,7 @@ DEF_HELPER_2(wsr_ibreakenable, void, env, i32) DEF_HELPER_3(wsr_ibreaka, void, env, i32, i32) DEF_HELPER_3(wsr_dbreaka, void, env, i32, i32) DEF_HELPER_3(wsr_dbreakc, void, env, i32, i32) +#endif DEF_HELPER_2(wur_fcr, void, env, i32)DEF_HELPER_FLAGS_1 (abs_s,TCG_CALL_NO_RWG_SE , f32, f32)
target/xtensa/op_helper.c +41 -9
131 lines not on this page · raw message
target/xtensa/translate.c +37 -6
178 lines not on this page · raw message
Signature · 1 line
2.11.0