Skip to contentSkip to conversation

target/xtensa: add linux-user support

PATCH New Max Filippov 1 participant 1 message Mar 16, 2018

lore
Share & tools
lore
#0 lore raw

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).

Cc Riku Voipio <[email protected]>
Cc Laurent Vivier <[email protected]>

---
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
new file mode 100644
index 000000000000..fd1d350ee944
@@ -0,0 +1 @@
+# Default configuration for xtensa-linux-user
default-configs/xtensaeb-linux-user.mak new file +1 -0
new file mode 100644
index 000000000000..fd1d350ee944
@@ -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
index 19d5445c3197..e864a1d72a27 100644
@@ -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
new file mode 100644
index 000000000000..e69de29bb2d1
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
new file mode 100644
index 000000000000..747d82861416
@@ -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
new file mode 100644
index 000000000000..a9a3fabd89be
@@ -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
new file mode 100644
index 000000000000..c6962e70afb7
@@ -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
new file mode 100644
index 000000000000..020e20e242fc
@@ -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
index e15851521f6d..2fae785cb287 100644
@@ -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
index 4573388a45fa..2b5b53722265 100644
@@ -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
index 34885038d554..34844eead358 100644
@@ -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
index cc751c98fbd0..73444ae02ccd 100644
@@ -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