Commit b779e29ed8919b18644b41bf581bdbcffdcb962e
1 parent
8dfbe4e8
microblaze: linux-user support.
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
Showing
7 changed files
with
474 additions
and
5 deletions
cpu-exec.c
... | ... | @@ -246,6 +246,7 @@ int cpu_exec(CPUState *env1) |
246 | 246 | #elif defined(TARGET_ALPHA) |
247 | 247 | #elif defined(TARGET_ARM) |
248 | 248 | #elif defined(TARGET_PPC) |
249 | +#elif defined(TARGET_MICROBLAZE) | |
249 | 250 | #elif defined(TARGET_MIPS) |
250 | 251 | #elif defined(TARGET_SH4) |
251 | 252 | #elif defined(TARGET_CRIS) |
... | ... | @@ -300,6 +301,8 @@ int cpu_exec(CPUState *env1) |
300 | 301 | env->old_exception = -1; |
301 | 302 | #elif defined(TARGET_PPC) |
302 | 303 | do_interrupt(env); |
304 | +#elif defined(TARGET_MICROBLAZE) | |
305 | + do_interrupt(env); | |
303 | 306 | #elif defined(TARGET_MIPS) |
304 | 307 | do_interrupt(env); |
305 | 308 | #elif defined(TARGET_SPARC) |
... | ... | @@ -367,7 +370,8 @@ int cpu_exec(CPUState *env1) |
367 | 370 | cpu_loop_exit(); |
368 | 371 | } |
369 | 372 | #if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \ |
370 | - defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) | |
373 | + defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) || \ | |
374 | + defined(TARGET_MICROBLAZE) | |
371 | 375 | if (interrupt_request & CPU_INTERRUPT_HALT) { |
372 | 376 | env->interrupt_request &= ~CPU_INTERRUPT_HALT; |
373 | 377 | env->halted = 1; |
... | ... | @@ -436,6 +440,15 @@ int cpu_exec(CPUState *env1) |
436 | 440 | env->interrupt_request &= ~CPU_INTERRUPT_HARD; |
437 | 441 | next_tb = 0; |
438 | 442 | } |
443 | +#elif defined(TARGET_MICROBLAZE) | |
444 | + if ((interrupt_request & CPU_INTERRUPT_HARD) | |
445 | + && (env->sregs[SR_MSR] & MSR_IE) | |
446 | + && !(env->sregs[SR_MSR] & (MSR_EIP | MSR_BIP)) | |
447 | + && !(env->iflags & (D_FLAG | IMM_FLAG))) { | |
448 | + env->exception_index = EXCP_IRQ; | |
449 | + do_interrupt(env); | |
450 | + next_tb = 0; | |
451 | + } | |
439 | 452 | #elif defined(TARGET_MIPS) |
440 | 453 | if ((interrupt_request & CPU_INTERRUPT_HARD) && |
441 | 454 | (env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask) && |
... | ... | @@ -565,6 +578,8 @@ int cpu_exec(CPUState *env1) |
565 | 578 | env->sr = (env->sr & 0xffe0) |
566 | 579 | | env->cc_dest | (env->cc_x << 4); |
567 | 580 | log_cpu_state(env, 0); |
581 | +#elif defined(TARGET_MICROBLAZE) | |
582 | + log_cpu_state(env, 0); | |
568 | 583 | #elif defined(TARGET_MIPS) |
569 | 584 | log_cpu_state(env, 0); |
570 | 585 | #elif defined(TARGET_SH4) |
... | ... | @@ -682,6 +697,7 @@ int cpu_exec(CPUState *env1) |
682 | 697 | env->cc_op = CC_OP_FLAGS; |
683 | 698 | env->sr = (env->sr & 0xffe0) |
684 | 699 | | env->cc_dest | (env->cc_x << 4); |
700 | +#elif defined(TARGET_MICROBLAZE) | |
685 | 701 | #elif defined(TARGET_MIPS) |
686 | 702 | #elif defined(TARGET_SH4) |
687 | 703 | #elif defined(TARGET_ALPHA) |
... | ... | @@ -1028,6 +1044,56 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, |
1028 | 1044 | return 1; |
1029 | 1045 | } |
1030 | 1046 | |
1047 | +#elif defined (TARGET_MICROBLAZE) | |
1048 | +static inline int handle_cpu_signal(unsigned long pc, unsigned long address, | |
1049 | + int is_write, sigset_t *old_set, | |
1050 | + void *puc) | |
1051 | +{ | |
1052 | + TranslationBlock *tb; | |
1053 | + int ret; | |
1054 | + | |
1055 | + if (cpu_single_env) | |
1056 | + env = cpu_single_env; /* XXX: find a correct solution for multithread */ | |
1057 | +#if defined(DEBUG_SIGNAL) | |
1058 | + printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", | |
1059 | + pc, address, is_write, *(unsigned long *)old_set); | |
1060 | +#endif | |
1061 | + /* XXX: locking issue */ | |
1062 | + if (is_write && page_unprotect(h2g(address), pc, puc)) { | |
1063 | + return 1; | |
1064 | + } | |
1065 | + | |
1066 | + /* see if it is an MMU fault */ | |
1067 | + ret = cpu_mb_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0); | |
1068 | + if (ret < 0) | |
1069 | + return 0; /* not an MMU fault */ | |
1070 | + if (ret == 0) | |
1071 | + return 1; /* the MMU fault was handled without causing real CPU fault */ | |
1072 | + | |
1073 | + /* now we have a real cpu fault */ | |
1074 | + tb = tb_find_pc(pc); | |
1075 | + if (tb) { | |
1076 | + /* the PC is inside the translated code. It means that we have | |
1077 | + a virtual CPU fault */ | |
1078 | + cpu_restore_state(tb, env, pc, puc); | |
1079 | + } | |
1080 | + if (ret == 1) { | |
1081 | +#if 0 | |
1082 | + printf("PF exception: PC=0x" TARGET_FMT_lx " error=0x%x %p\n", | |
1083 | + env->PC, env->error_code, tb); | |
1084 | +#endif | |
1085 | + /* we restore the process signal mask as the sigreturn should | |
1086 | + do it (XXX: use sigsetjmp) */ | |
1087 | + sigprocmask(SIG_SETMASK, old_set, NULL); | |
1088 | + cpu_loop_exit(); | |
1089 | + } else { | |
1090 | + /* activate soft MMU for this block */ | |
1091 | + cpu_resume_from_signal(env, puc); | |
1092 | + } | |
1093 | + /* never comes here */ | |
1094 | + return 1; | |
1095 | +} | |
1096 | + | |
1031 | 1097 | #elif defined (TARGET_SH4) |
1032 | 1098 | static inline int handle_cpu_signal(unsigned long pc, unsigned long address, |
1033 | 1099 | int is_write, sigset_t *old_set, | ... | ... |
elf.h
... | ... | @@ -119,6 +119,8 @@ typedef int64_t Elf64_Sxword; |
119 | 119 | */ |
120 | 120 | #define EM_S390_OLD 0xA390 |
121 | 121 | |
122 | +#define EM_XILINX_MICROBLAZE 0xBAAB | |
123 | + | |
122 | 124 | /* This is the info that is needed to parse the dynamic section of the file */ |
123 | 125 | #define DT_NULL 0 |
124 | 126 | #define DT_NEEDED 1 | ... | ... |
linux-user/elfload.c
... | ... | @@ -453,6 +453,28 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i |
453 | 453 | |
454 | 454 | #endif /* TARGET_MIPS */ |
455 | 455 | |
456 | +#ifdef TARGET_MICROBLAZE | |
457 | + | |
458 | +#define ELF_START_MMAP 0x80000000 | |
459 | + | |
460 | +#define elf_check_arch(x) ( (x) == EM_XILINX_MICROBLAZE ) | |
461 | + | |
462 | +#define ELF_CLASS ELFCLASS32 | |
463 | +#define ELF_DATA ELFDATA2MSB | |
464 | +#define ELF_ARCH EM_MIPS | |
465 | + | |
466 | +static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) | |
467 | +{ | |
468 | + regs->pc = infop->entry; | |
469 | + regs->r1 = infop->start_stack; | |
470 | + | |
471 | +} | |
472 | + | |
473 | +#define USE_ELF_CORE_DUMP | |
474 | +#define ELF_EXEC_PAGESIZE 4096 | |
475 | + | |
476 | +#endif /* TARGET_MICROBLAZE */ | |
477 | + | |
456 | 478 | #ifdef TARGET_SH4 |
457 | 479 | |
458 | 480 | #define ELF_START_MMAP 0x80000000 | ... | ... |
linux-user/main.c
... | ... | @@ -2036,6 +2036,66 @@ void cpu_loop (CPUState *env) |
2036 | 2036 | } |
2037 | 2037 | #endif |
2038 | 2038 | |
2039 | +#ifdef TARGET_MICROBLAZE | |
2040 | +void cpu_loop (CPUState *env) | |
2041 | +{ | |
2042 | + int trapnr, ret; | |
2043 | + target_siginfo_t info; | |
2044 | + | |
2045 | + while (1) { | |
2046 | + trapnr = cpu_mb_exec (env); | |
2047 | + switch (trapnr) { | |
2048 | + case 0xaa: | |
2049 | + { | |
2050 | + info.si_signo = SIGSEGV; | |
2051 | + info.si_errno = 0; | |
2052 | + /* XXX: check env->error_code */ | |
2053 | + info.si_code = TARGET_SEGV_MAPERR; | |
2054 | + info._sifields._sigfault._addr = 0; | |
2055 | + queue_signal(env, info.si_signo, &info); | |
2056 | + } | |
2057 | + break; | |
2058 | + case EXCP_INTERRUPT: | |
2059 | + /* just indicate that signals should be handled asap */ | |
2060 | + break; | |
2061 | + case EXCP_BREAK: | |
2062 | + /* Return address is 4 bytes after the call. */ | |
2063 | + env->regs[14] += 4; | |
2064 | + ret = do_syscall(env, | |
2065 | + env->regs[12], | |
2066 | + env->regs[5], | |
2067 | + env->regs[6], | |
2068 | + env->regs[7], | |
2069 | + env->regs[8], | |
2070 | + env->regs[9], | |
2071 | + env->regs[10]); | |
2072 | + env->regs[3] = ret; | |
2073 | + env->sregs[SR_PC] = env->regs[14]; | |
2074 | + break; | |
2075 | + case EXCP_DEBUG: | |
2076 | + { | |
2077 | + int sig; | |
2078 | + | |
2079 | + sig = gdb_handlesig (env, TARGET_SIGTRAP); | |
2080 | + if (sig) | |
2081 | + { | |
2082 | + info.si_signo = sig; | |
2083 | + info.si_errno = 0; | |
2084 | + info.si_code = TARGET_TRAP_BRKPT; | |
2085 | + queue_signal(env, info.si_signo, &info); | |
2086 | + } | |
2087 | + } | |
2088 | + break; | |
2089 | + default: | |
2090 | + printf ("Unhandled trap: 0x%x\n", trapnr); | |
2091 | + cpu_dump_state(env, stderr, fprintf, 0); | |
2092 | + exit (1); | |
2093 | + } | |
2094 | + process_pending_signals (env); | |
2095 | + } | |
2096 | +} | |
2097 | +#endif | |
2098 | + | |
2039 | 2099 | #ifdef TARGET_M68K |
2040 | 2100 | |
2041 | 2101 | void cpu_loop(CPUM68KState *env) |
... | ... | @@ -2698,6 +2758,42 @@ int main(int argc, char **argv, char **envp) |
2698 | 2758 | env->sr = regs->sr; |
2699 | 2759 | ts->sim_syscalls = 1; |
2700 | 2760 | } |
2761 | +#elif defined(TARGET_MICROBLAZE) | |
2762 | + { | |
2763 | + env->regs[0] = regs->r0; | |
2764 | + env->regs[1] = regs->r1; | |
2765 | + env->regs[2] = regs->r2; | |
2766 | + env->regs[3] = regs->r3; | |
2767 | + env->regs[4] = regs->r4; | |
2768 | + env->regs[5] = regs->r5; | |
2769 | + env->regs[6] = regs->r6; | |
2770 | + env->regs[7] = regs->r7; | |
2771 | + env->regs[8] = regs->r8; | |
2772 | + env->regs[9] = regs->r9; | |
2773 | + env->regs[10] = regs->r10; | |
2774 | + env->regs[11] = regs->r11; | |
2775 | + env->regs[12] = regs->r12; | |
2776 | + env->regs[13] = regs->r13; | |
2777 | + env->regs[14] = regs->r14; | |
2778 | + env->regs[15] = regs->r15; | |
2779 | + env->regs[16] = regs->r16; | |
2780 | + env->regs[17] = regs->r17; | |
2781 | + env->regs[18] = regs->r18; | |
2782 | + env->regs[19] = regs->r19; | |
2783 | + env->regs[20] = regs->r20; | |
2784 | + env->regs[21] = regs->r21; | |
2785 | + env->regs[22] = regs->r22; | |
2786 | + env->regs[23] = regs->r23; | |
2787 | + env->regs[24] = regs->r24; | |
2788 | + env->regs[25] = regs->r25; | |
2789 | + env->regs[26] = regs->r26; | |
2790 | + env->regs[27] = regs->r27; | |
2791 | + env->regs[28] = regs->r28; | |
2792 | + env->regs[29] = regs->r29; | |
2793 | + env->regs[30] = regs->r30; | |
2794 | + env->regs[31] = regs->r31; | |
2795 | + env->sregs[SR_PC] = regs->pc; | |
2796 | + } | |
2701 | 2797 | #elif defined(TARGET_MIPS) |
2702 | 2798 | { |
2703 | 2799 | int i; | ... | ... |
linux-user/signal.c
... | ... | @@ -3011,6 +3011,222 @@ badframe: |
3011 | 3011 | force_sig(TARGET_SIGSEGV); |
3012 | 3012 | return 0; |
3013 | 3013 | } |
3014 | +#elif defined(TARGET_MICROBLAZE) | |
3015 | + | |
3016 | +struct target_sigcontext { | |
3017 | + struct target_pt_regs regs; /* needs to be first */ | |
3018 | + uint32_t oldmask; | |
3019 | +}; | |
3020 | + | |
3021 | +/* Signal frames. */ | |
3022 | +struct target_signal_frame { | |
3023 | + struct target_sigcontext sc; | |
3024 | + uint32_t extramask[TARGET_NSIG_WORDS - 1]; | |
3025 | + uint32_t tramp[2]; | |
3026 | +}; | |
3027 | + | |
3028 | +struct rt_signal_frame { | |
3029 | + struct siginfo info; | |
3030 | + struct ucontext uc; | |
3031 | + uint32_t tramp[2]; | |
3032 | +}; | |
3033 | + | |
3034 | +static void setup_sigcontext(struct target_sigcontext *sc, CPUState *env) | |
3035 | +{ | |
3036 | + __put_user(env->regs[0], &sc->regs.r0); | |
3037 | + __put_user(env->regs[1], &sc->regs.r1); | |
3038 | + __put_user(env->regs[2], &sc->regs.r2); | |
3039 | + __put_user(env->regs[3], &sc->regs.r3); | |
3040 | + __put_user(env->regs[4], &sc->regs.r4); | |
3041 | + __put_user(env->regs[5], &sc->regs.r5); | |
3042 | + __put_user(env->regs[6], &sc->regs.r6); | |
3043 | + __put_user(env->regs[7], &sc->regs.r7); | |
3044 | + __put_user(env->regs[8], &sc->regs.r8); | |
3045 | + __put_user(env->regs[9], &sc->regs.r9); | |
3046 | + __put_user(env->regs[10], &sc->regs.r10); | |
3047 | + __put_user(env->regs[11], &sc->regs.r11); | |
3048 | + __put_user(env->regs[12], &sc->regs.r12); | |
3049 | + __put_user(env->regs[13], &sc->regs.r13); | |
3050 | + __put_user(env->regs[14], &sc->regs.r14); | |
3051 | + __put_user(env->regs[15], &sc->regs.r15); | |
3052 | + __put_user(env->regs[16], &sc->regs.r16); | |
3053 | + __put_user(env->regs[17], &sc->regs.r17); | |
3054 | + __put_user(env->regs[18], &sc->regs.r18); | |
3055 | + __put_user(env->regs[19], &sc->regs.r19); | |
3056 | + __put_user(env->regs[20], &sc->regs.r20); | |
3057 | + __put_user(env->regs[21], &sc->regs.r21); | |
3058 | + __put_user(env->regs[22], &sc->regs.r22); | |
3059 | + __put_user(env->regs[23], &sc->regs.r23); | |
3060 | + __put_user(env->regs[24], &sc->regs.r24); | |
3061 | + __put_user(env->regs[25], &sc->regs.r25); | |
3062 | + __put_user(env->regs[26], &sc->regs.r26); | |
3063 | + __put_user(env->regs[27], &sc->regs.r27); | |
3064 | + __put_user(env->regs[28], &sc->regs.r28); | |
3065 | + __put_user(env->regs[29], &sc->regs.r29); | |
3066 | + __put_user(env->regs[30], &sc->regs.r30); | |
3067 | + __put_user(env->regs[31], &sc->regs.r31); | |
3068 | + __put_user(env->sregs[SR_PC], &sc->regs.pc); | |
3069 | +} | |
3070 | + | |
3071 | +static void restore_sigcontext(struct target_sigcontext *sc, CPUState *env) | |
3072 | +{ | |
3073 | + __get_user(env->regs[0], &sc->regs.r0); | |
3074 | + __get_user(env->regs[1], &sc->regs.r1); | |
3075 | + __get_user(env->regs[2], &sc->regs.r2); | |
3076 | + __get_user(env->regs[3], &sc->regs.r3); | |
3077 | + __get_user(env->regs[4], &sc->regs.r4); | |
3078 | + __get_user(env->regs[5], &sc->regs.r5); | |
3079 | + __get_user(env->regs[6], &sc->regs.r6); | |
3080 | + __get_user(env->regs[7], &sc->regs.r7); | |
3081 | + __get_user(env->regs[8], &sc->regs.r8); | |
3082 | + __get_user(env->regs[9], &sc->regs.r9); | |
3083 | + __get_user(env->regs[10], &sc->regs.r10); | |
3084 | + __get_user(env->regs[11], &sc->regs.r11); | |
3085 | + __get_user(env->regs[12], &sc->regs.r12); | |
3086 | + __get_user(env->regs[13], &sc->regs.r13); | |
3087 | + __get_user(env->regs[14], &sc->regs.r14); | |
3088 | + __get_user(env->regs[15], &sc->regs.r15); | |
3089 | + __get_user(env->regs[16], &sc->regs.r16); | |
3090 | + __get_user(env->regs[17], &sc->regs.r17); | |
3091 | + __get_user(env->regs[18], &sc->regs.r18); | |
3092 | + __get_user(env->regs[19], &sc->regs.r19); | |
3093 | + __get_user(env->regs[20], &sc->regs.r20); | |
3094 | + __get_user(env->regs[21], &sc->regs.r21); | |
3095 | + __get_user(env->regs[22], &sc->regs.r22); | |
3096 | + __get_user(env->regs[23], &sc->regs.r23); | |
3097 | + __get_user(env->regs[24], &sc->regs.r24); | |
3098 | + __get_user(env->regs[25], &sc->regs.r25); | |
3099 | + __get_user(env->regs[26], &sc->regs.r26); | |
3100 | + __get_user(env->regs[27], &sc->regs.r27); | |
3101 | + __get_user(env->regs[28], &sc->regs.r28); | |
3102 | + __get_user(env->regs[29], &sc->regs.r29); | |
3103 | + __get_user(env->regs[30], &sc->regs.r30); | |
3104 | + __get_user(env->regs[31], &sc->regs.r31); | |
3105 | + __get_user(env->sregs[SR_PC], &sc->regs.pc); | |
3106 | +} | |
3107 | + | |
3108 | +static abi_ulong get_sigframe(struct target_sigaction *ka, | |
3109 | + CPUState *env, int frame_size) | |
3110 | +{ | |
3111 | + abi_ulong sp = env->regs[1]; | |
3112 | + | |
3113 | + if ((ka->sa_flags & SA_ONSTACK) != 0 && !on_sig_stack(sp)) | |
3114 | + sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size; | |
3115 | + | |
3116 | + return ((sp - frame_size) & -8UL); | |
3117 | +} | |
3118 | + | |
3119 | +static void setup_frame(int sig, struct target_sigaction *ka, | |
3120 | + target_sigset_t *set, CPUState *env) | |
3121 | +{ | |
3122 | + struct target_signal_frame *frame; | |
3123 | + abi_ulong frame_addr; | |
3124 | + int err = 0; | |
3125 | + int i; | |
3126 | + | |
3127 | + frame_addr = get_sigframe(ka, env, sizeof *frame); | |
3128 | + if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) | |
3129 | + goto badframe; | |
3130 | + | |
3131 | + /* Save the mask. */ | |
3132 | + err |= __put_user(set->sig[0], &frame->sc.oldmask); | |
3133 | + if (err) | |
3134 | + goto badframe; | |
3135 | + | |
3136 | + for(i = 1; i < TARGET_NSIG_WORDS; i++) { | |
3137 | + if (__put_user(set->sig[i], &frame->extramask[i - 1])) | |
3138 | + goto badframe; | |
3139 | + } | |
3140 | + | |
3141 | + setup_sigcontext(&frame->sc, env); | |
3142 | + | |
3143 | + /* Set up to return from userspace. If provided, use a stub | |
3144 | + already in userspace. */ | |
3145 | + /* minus 8 is offset to cater for "rtsd r15,8" offset */ | |
3146 | + if (ka->sa_flags & TARGET_SA_RESTORER) { | |
3147 | + env->regs[15] = ((unsigned long)ka->sa_restorer)-8; | |
3148 | + } else { | |
3149 | + uint32_t t; | |
3150 | + /* Note, these encodings are _big endian_! */ | |
3151 | + /* addi r12, r0, __NR_sigreturn */ | |
3152 | + t = 0x31800000UL | TARGET_NR_sigreturn; | |
3153 | + err |= __put_user(t, frame->tramp + 0); | |
3154 | + /* brki r14, 0x8 */ | |
3155 | + t = 0xb9cc0008UL; | |
3156 | + err |= __put_user(t, frame->tramp + 1); | |
3157 | + | |
3158 | + /* Return from sighandler will jump to the tramp. | |
3159 | + Negative 8 offset because return is rtsd r15, 8 */ | |
3160 | + env->regs[15] = ((unsigned long)frame->tramp) - 8; | |
3161 | + } | |
3162 | + | |
3163 | + if (err) | |
3164 | + goto badframe; | |
3165 | + | |
3166 | + /* Set up registers for signal handler */ | |
3167 | + env->regs[1] = (unsigned long) frame; | |
3168 | + /* Signal handler args: */ | |
3169 | + env->regs[5] = sig; /* Arg 0: signum */ | |
3170 | + env->regs[6] = (unsigned long) &frame->sc; /* arg 1: sigcontext */ | |
3171 | + | |
3172 | + /* Offset of 4 to handle microblaze rtid r14, 0 */ | |
3173 | + env->sregs[SR_PC] = (unsigned long)ka->_sa_handler; | |
3174 | + | |
3175 | + unlock_user_struct(frame, frame_addr, 1); | |
3176 | + return; | |
3177 | + badframe: | |
3178 | + unlock_user_struct(frame, frame_addr, 1); | |
3179 | + force_sig(TARGET_SIGSEGV); | |
3180 | +} | |
3181 | + | |
3182 | +static void setup_rt_frame(int sig, struct target_sigaction *ka, | |
3183 | + target_siginfo_t *info, | |
3184 | + target_sigset_t *set, CPUState *env) | |
3185 | +{ | |
3186 | + fprintf(stderr, "Microblaze setup_rt_frame: not implemented\n"); | |
3187 | +} | |
3188 | + | |
3189 | +long do_sigreturn(CPUState *env) | |
3190 | +{ | |
3191 | + struct target_signal_frame *frame; | |
3192 | + abi_ulong frame_addr; | |
3193 | + target_sigset_t target_set; | |
3194 | + sigset_t set; | |
3195 | + int i; | |
3196 | + | |
3197 | + frame_addr = env->regs[R_SP]; | |
3198 | + /* Make sure the guest isn't playing games. */ | |
3199 | + if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1)) | |
3200 | + goto badframe; | |
3201 | + | |
3202 | + /* Restore blocked signals */ | |
3203 | + if (__get_user(target_set.sig[0], &frame->sc.oldmask)) | |
3204 | + goto badframe; | |
3205 | + for(i = 1; i < TARGET_NSIG_WORDS; i++) { | |
3206 | + if (__get_user(target_set.sig[i], &frame->extramask[i - 1])) | |
3207 | + goto badframe; | |
3208 | + } | |
3209 | + target_to_host_sigset_internal(&set, &target_set); | |
3210 | + sigprocmask(SIG_SETMASK, &set, NULL); | |
3211 | + | |
3212 | + restore_sigcontext(&frame->sc, env); | |
3213 | + /* We got here through a sigreturn syscall, our path back is via an | |
3214 | + rtb insn so setup r14 for that. */ | |
3215 | + env->regs[14] = env->sregs[SR_PC]; | |
3216 | + | |
3217 | + unlock_user_struct(frame, frame_addr, 0); | |
3218 | + return env->regs[10]; | |
3219 | + badframe: | |
3220 | + unlock_user_struct(frame, frame_addr, 0); | |
3221 | + force_sig(TARGET_SIGSEGV); | |
3222 | +} | |
3223 | + | |
3224 | +long do_rt_sigreturn(CPUState *env) | |
3225 | +{ | |
3226 | + fprintf(stderr, "Microblaze do_rt_sigreturn: not implemented\n"); | |
3227 | + return -TARGET_ENOSYS; | |
3228 | +} | |
3229 | + | |
3014 | 3230 | #elif defined(TARGET_CRIS) |
3015 | 3231 | |
3016 | 3232 | struct target_sigcontext { | ... | ... |
linux-user/syscall.c
... | ... | @@ -4854,7 +4854,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
4854 | 4854 | #endif |
4855 | 4855 | #ifdef TARGET_NR_mmap |
4856 | 4856 | case TARGET_NR_mmap: |
4857 | -#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_CRIS) | |
4857 | +#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_CRIS) || defined(TARGET_MICROBLAZE) | |
4858 | 4858 | { |
4859 | 4859 | abi_ulong *v; |
4860 | 4860 | abi_ulong v1, v2, v3, v4, v5, v6; | ... | ... |
linux-user/syscall_defs.h
... | ... | @@ -59,7 +59,8 @@ |
59 | 59 | #define TARGET_IOC_READ 2U |
60 | 60 | |
61 | 61 | #elif defined(TARGET_PPC) || defined(TARGET_ALPHA) || \ |
62 | - defined(TARGET_SPARC) || defined(TARGET_MIPS) | |
62 | + defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE) || \ | |
63 | + defined(TARGET_MIPS) | |
63 | 64 | |
64 | 65 | #define TARGET_IOC_SIZEBITS 13 |
65 | 66 | #define TARGET_IOC_DIRBITS 3 |
... | ... | @@ -286,7 +287,7 @@ struct target_sigaction; |
286 | 287 | int do_sigaction(int sig, const struct target_sigaction *act, |
287 | 288 | struct target_sigaction *oact); |
288 | 289 | |
289 | -#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_PPC) || defined(TARGET_MIPS) || defined (TARGET_SH4) || defined(TARGET_M68K) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) | |
290 | +#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_PPC) || defined(TARGET_MIPS) || defined (TARGET_SH4) || defined(TARGET_M68K) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) || defined(TARGET_MICROBLAZE) | |
290 | 291 | |
291 | 292 | #if defined(TARGET_SPARC) |
292 | 293 | #define TARGET_SA_NOCLDSTOP 8u |
... | ... | @@ -1170,6 +1171,54 @@ struct __attribute__((__packed__)) target_stat64 { |
1170 | 1171 | unsigned int __unused5; |
1171 | 1172 | }; |
1172 | 1173 | |
1174 | +#elif defined(TARGET_MICROBLAZE) | |
1175 | + | |
1176 | +struct target_stat { | |
1177 | + abi_ulong st_dev; | |
1178 | + abi_ulong st_ino; | |
1179 | + unsigned int st_mode; | |
1180 | + unsigned short st_nlink; | |
1181 | + unsigned int st_uid; | |
1182 | + unsigned int st_gid; | |
1183 | + abi_ulong st_rdev; | |
1184 | + abi_ulong st_size; | |
1185 | + abi_ulong st_blksize; | |
1186 | + abi_ulong st_blocks; | |
1187 | + abi_ulong target_st_atime; | |
1188 | + abi_ulong target_st_atime_nsec; | |
1189 | + abi_ulong target_st_mtime; | |
1190 | + abi_ulong target_st_mtime_nsec; | |
1191 | + abi_ulong target_st_ctime; | |
1192 | + abi_ulong target_st_ctime_nsec; | |
1193 | + abi_ulong __unused4; | |
1194 | + abi_ulong __unused5; | |
1195 | +}; | |
1196 | + | |
1197 | +/* FIXME: Microblaze no-mmu user-space has a difference stat64 layout... */ | |
1198 | +struct __attribute__((__packed__)) target_stat64 { | |
1199 | + uint64_t st_dev; | |
1200 | + uint64_t st_ino; | |
1201 | + uint32_t st_mode; | |
1202 | + uint32_t st_nlink; | |
1203 | + uint32_t st_uid; | |
1204 | + uint32_t st_gid; | |
1205 | + uint64_t st_rdev; | |
1206 | + uint32_t __pad2; | |
1207 | + | |
1208 | + int64_t st_size; | |
1209 | + int32_t st_blksize; | |
1210 | + int64_t st_blocks; /* Number 512-byte blocks allocated. */ | |
1211 | + | |
1212 | + int target_st_atime; | |
1213 | + unsigned int target_st_atime_nsec; | |
1214 | + int target_st_mtime; | |
1215 | + unsigned int target_st_mtime_nsec; | |
1216 | + int target_st_ctime; | |
1217 | + unsigned int target_st_ctime_nsec; | |
1218 | + uint32_t __unused4; | |
1219 | + uint32_t __unused5; | |
1220 | +}; | |
1221 | + | |
1173 | 1222 | #elif defined(TARGET_M68K) |
1174 | 1223 | |
1175 | 1224 | struct target_stat { |
... | ... | @@ -1719,6 +1768,24 @@ struct target_statfs64 { |
1719 | 1768 | #define TARGET_O_NOFOLLOW 0100000 /* don't follow links */ |
1720 | 1769 | #define TARGET_O_LARGEFILE 0200000 |
1721 | 1770 | #define TARGET_O_DIRECT 0400000 /* direct disk access hint */ |
1771 | +#elif defined (TARGET_MICROBLAZE) | |
1772 | +#define TARGET_O_ACCMODE 0003 | |
1773 | +#define TARGET_O_RDONLY 00 | |
1774 | +#define TARGET_O_WRONLY 01 | |
1775 | +#define TARGET_O_RDWR 02 | |
1776 | +#define TARGET_O_CREAT 0100 /* not fcntl */ | |
1777 | +#define TARGET_O_EXCL 0200 /* not fcntl */ | |
1778 | +#define TARGET_O_NOCTTY 0400 /* not fcntl */ | |
1779 | +#define TARGET_O_TRUNC 01000 /* not fcntl */ | |
1780 | +#define TARGET_O_APPEND 02000 | |
1781 | +#define TARGET_O_NONBLOCK 04000 | |
1782 | +#define TARGET_O_NDELAY TARGET_O_NONBLOCK | |
1783 | +#define TARGET_O_SYNC 010000 | |
1784 | +#define TARGET_FASYNC 020000 /* fcntl, for BSD compatibility */ | |
1785 | +#define TARGET_O_DIRECTORY 040000 /* must be a directory */ | |
1786 | +#define TARGET_O_NOFOLLOW 0100000 /* don't follow links */ | |
1787 | +#define TARGET_O_LARGEFILE 0200000 | |
1788 | +#define TARGET_O_DIRECT 0400000 /* direct disk access hint */ | |
1722 | 1789 | #elif defined (TARGET_SPARC) |
1723 | 1790 | #define TARGET_O_RDONLY 0x0000 |
1724 | 1791 | #define TARGET_O_WRONLY 0x0001 |
... | ... | @@ -1806,7 +1873,7 @@ struct target_flock { |
1806 | 1873 | struct target_flock64 { |
1807 | 1874 | short l_type; |
1808 | 1875 | short l_whence; |
1809 | -#if defined(TARGET_PPC) || defined(TARGET_X86_64) || defined(TARGET_MIPS) || defined(TARGET_SPARC) || defined(TARGET_HPPA) | |
1876 | +#if defined(TARGET_PPC) || defined(TARGET_X86_64) || defined(TARGET_MIPS) || defined(TARGET_SPARC) || defined(TARGET_HPPA) || defined (TARGET_MICROBLAZE) | |
1810 | 1877 | int __pad; |
1811 | 1878 | #endif |
1812 | 1879 | unsigned long long l_start; | ... | ... |