Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

microblaze_mmu_v2: Update process creation for MMU

Signed-off-by: Michal Simek <monstr@monstr.eu>

+181 -13
+91 -4
arch/microblaze/include/asm/processor.h
··· 1 1 /* 2 - * Copyright (C) 2008 Michal Simek 3 - * Copyright (C) 2008 PetaLogix 2 + * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu> 3 + * Copyright (C) 2008-2009 PetaLogix 4 4 * Copyright (C) 2006 Atmark Techno, Inc. 5 5 * 6 6 * This file is subject to the terms and conditions of the GNU General Public ··· 26 26 # define cpu_sleep() do {} while (0) 27 27 # define prepare_to_copy(tsk) do {} while (0) 28 28 29 - # endif /* __ASSEMBLY__ */ 30 - 31 29 #define task_pt_regs(tsk) \ 32 30 (((struct pt_regs *)(THREAD_SIZE + task_stack_page(tsk))) - 1) 33 31 34 32 /* Do necessary setup to start up a newly executed thread. */ 35 33 void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long usp); 36 34 35 + # endif /* __ASSEMBLY__ */ 36 + 37 + # ifndef CONFIG_MMU 37 38 /* 38 39 * User space process size: memory size 39 40 * ··· 86 85 # define KSTK_EIP(tsk) (0) 87 86 # define KSTK_ESP(tsk) (0) 88 87 88 + # else /* CONFIG_MMU */ 89 + 90 + /* 91 + * This is used to define STACK_TOP, and with MMU it must be below 92 + * kernel base to select the correct PGD when handling MMU exceptions. 93 + */ 94 + # define TASK_SIZE (CONFIG_KERNEL_START) 95 + 96 + /* 97 + * This decides where the kernel will search for a free chunk of vm 98 + * space during mmap's. 99 + */ 100 + # define TASK_UNMAPPED_BASE (TASK_SIZE / 8 * 3) 101 + 102 + # define THREAD_KSP 0 103 + 104 + # ifndef __ASSEMBLY__ 105 + 106 + /* 107 + * Default implementation of macro that returns current 108 + * instruction pointer ("program counter"). 109 + */ 110 + # define current_text_addr() ({ __label__ _l; _l: &&_l; }) 111 + 112 + /* If you change this, you must change the associated assembly-languages 113 + * constants defined below, THREAD_*. 114 + */ 115 + struct thread_struct { 116 + /* kernel stack pointer (must be first field in structure) */ 117 + unsigned long ksp; 118 + unsigned long ksp_limit; /* if ksp <= ksp_limit stack overflow */ 119 + void *pgdir; /* root of page-table tree */ 120 + struct pt_regs *regs; /* Pointer to saved register state */ 121 + }; 122 + 123 + # define INIT_THREAD { \ 124 + .ksp = sizeof init_stack + (unsigned long)init_stack, \ 125 + .pgdir = swapper_pg_dir, \ 126 + } 127 + 128 + /* Do necessary setup to start up a newly executed thread. */ 129 + void start_thread(struct pt_regs *regs, 130 + unsigned long pc, unsigned long usp); 131 + 132 + /* Free all resources held by a thread. */ 133 + extern inline void release_thread(struct task_struct *dead_task) 134 + { 135 + } 136 + 137 + extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); 138 + 139 + /* Free current thread data structures etc. */ 140 + static inline void exit_thread(void) 141 + { 142 + } 143 + 144 + /* Return saved (kernel) PC of a blocked thread. */ 145 + # define thread_saved_pc(tsk) \ 146 + ((tsk)->thread.regs ? (tsk)->thread.regs->r15 : 0) 147 + 148 + unsigned long get_wchan(struct task_struct *p); 149 + 150 + /* The size allocated for kernel stacks. This _must_ be a power of two! */ 151 + # define KERNEL_STACK_SIZE 0x2000 152 + 153 + /* Return some info about the user process TASK. */ 154 + # define task_tos(task) ((unsigned long)(task) + KERNEL_STACK_SIZE) 155 + # define task_regs(task) ((struct pt_regs *)task_tos(task) - 1) 156 + 157 + # define task_pt_regs_plus_args(tsk) \ 158 + (((void *)task_pt_regs(tsk)) - STATE_SAVE_ARG_SPACE) 159 + 160 + # define task_sp(task) (task_regs(task)->r1) 161 + # define task_pc(task) (task_regs(task)->pc) 162 + /* Grotty old names for some. */ 163 + # define KSTK_EIP(task) (task_pc(task)) 164 + # define KSTK_ESP(task) (task_sp(task)) 165 + 166 + /* FIXME */ 167 + # define deactivate_mm(tsk, mm) do { } while (0) 168 + 169 + # define STACK_TOP TASK_SIZE 170 + # define STACK_TOP_MAX STACK_TOP 171 + 172 + # endif /* __ASSEMBLY__ */ 173 + # endif /* CONFIG_MMU */ 89 174 #endif /* _ASM_MICROBLAZE_PROCESSOR_H */
+19 -2
arch/microblaze/include/asm/registers.h
··· 1 1 /* 2 - * Copyright (C) 2008 Michal Simek 3 - * Copyright (C) 2008 PetaLogix 2 + * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu> 3 + * Copyright (C) 2008-2009 PetaLogix 4 4 * Copyright (C) 2006 Atmark Techno, Inc. 5 5 * 6 6 * This file is subject to the terms and conditions of the GNU General Public ··· 30 30 #define FSR_UF (1<<1) /* Underflow */ 31 31 #define FSR_DO (1<<0) /* Denormalized operand error */ 32 32 33 + # ifdef CONFIG_MMU 34 + /* Machine State Register (MSR) Fields */ 35 + # define MSR_UM (1<<11) /* User Mode */ 36 + # define MSR_UMS (1<<12) /* User Mode Save */ 37 + # define MSR_VM (1<<13) /* Virtual Mode */ 38 + # define MSR_VMS (1<<14) /* Virtual Mode Save */ 39 + 40 + # define MSR_KERNEL (MSR_EE | MSR_VM) 41 + /* # define MSR_USER (MSR_KERNEL | MSR_UM | MSR_IE) */ 42 + # define MSR_KERNEL_VMS (MSR_EE | MSR_VMS) 43 + /* # define MSR_USER_VMS (MSR_KERNEL_VMS | MSR_UMS | MSR_IE) */ 44 + 45 + /* Exception State Register (ESR) Fields */ 46 + # define ESR_DIZ (1<<11) /* Zone Protection */ 47 + # define ESR_S (1<<10) /* Store instruction */ 48 + 49 + # endif /* CONFIG_MMU */ 33 50 #endif /* _ASM_MICROBLAZE_REGISTERS_H */
+13 -7
arch/microblaze/include/asm/segment.h
··· 1 1 /* 2 - * Copyright (C) 2008 Michal Simek 3 - * Copyright (C) 2008 PetaLogix 2 + * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu> 3 + * Copyright (C) 2008-2009 PetaLogix 4 4 * Copyright (C) 2006 Atmark Techno, Inc. 5 5 * 6 6 * This file is subject to the terms and conditions of the GNU General Public ··· 11 11 #ifndef _ASM_MICROBLAZE_SEGMENT_H 12 12 #define _ASM_MICROBLAZE_SEGMENT_H 13 13 14 - #ifndef __ASSEMBLY__ 14 + # ifndef __ASSEMBLY__ 15 15 16 16 typedef struct { 17 17 unsigned long seg; ··· 29 29 * 30 30 * For non-MMU arch like Microblaze, KERNEL_DS and USER_DS is equal. 31 31 */ 32 - # define KERNEL_DS ((mm_segment_t){0}) 32 + # define MAKE_MM_SEG(s) ((mm_segment_t) { (s) }) 33 + 34 + # ifndef CONFIG_MMU 35 + # define KERNEL_DS MAKE_MM_SEG(0) 33 36 # define USER_DS KERNEL_DS 37 + # else 38 + # define KERNEL_DS MAKE_MM_SEG(0xFFFFFFFF) 39 + # define USER_DS MAKE_MM_SEG(TASK_SIZE - 1) 40 + # endif 34 41 35 42 # define get_ds() (KERNEL_DS) 36 43 # define get_fs() (current_thread_info()->addr_limit) 37 - # define set_fs(x) \ 38 - do { current_thread_info()->addr_limit = (x); } while (0) 44 + # define set_fs(val) (current_thread_info()->addr_limit = (val)) 39 45 40 - # define segment_eq(a, b) ((a).seg == (b).seg) 46 + # define segment_eq(a, b) ((a).seg == (b).seg) 41 47 42 48 # endif /* __ASSEMBLY__ */ 43 49 #endif /* _ASM_MICROBLAZE_SEGMENT_H */
+58
arch/microblaze/kernel/process.c
··· 126 126 else 127 127 childregs->r1 = ((unsigned long) ti) + THREAD_SIZE; 128 128 129 + #ifndef CONFIG_MMU 129 130 memset(&ti->cpu_context, 0, sizeof(struct cpu_context)); 130 131 ti->cpu_context.r1 = (unsigned long)childregs; 131 132 ti->cpu_context.msr = (unsigned long)childregs->msr; 133 + #else 134 + 135 + /* if creating a kernel thread then update the current reg (we don't 136 + * want to use the parent's value when restoring by POP_STATE) */ 137 + if (kernel_mode(regs)) 138 + /* save new current on stack to use POP_STATE */ 139 + childregs->CURRENT_TASK = (unsigned long)p; 140 + /* if returning to user then use the parent's value of this register */ 141 + 142 + /* if we're creating a new kernel thread then just zeroing all 143 + * the registers. That's OK for a brand new thread.*/ 144 + /* Pls. note that some of them will be restored in POP_STATE */ 145 + if (kernel_mode(regs)) 146 + memset(&ti->cpu_context, 0, sizeof(struct cpu_context)); 147 + /* if this thread is created for fork/vfork/clone, then we want to 148 + * restore all the parent's context */ 149 + /* in addition to the registers which will be restored by POP_STATE */ 150 + else { 151 + ti->cpu_context = *(struct cpu_context *)regs; 152 + childregs->msr |= MSR_UMS; 153 + } 154 + 155 + /* FIXME STATE_SAVE_PT_OFFSET; */ 156 + ti->cpu_context.r1 = (unsigned long)childregs - STATE_SAVE_ARG_SPACE; 157 + /* we should consider the fact that childregs is a copy of the parent 158 + * regs which were saved immediately after entering the kernel state 159 + * before enabling VM. This MSR will be restored in switch_to and 160 + * RETURN() and we want to have the right machine state there 161 + * specifically this state must have INTs disabled before and enabled 162 + * after performing rtbd 163 + * compose the right MSR for RETURN(). It will work for switch_to also 164 + * excepting for VM and UMS 165 + * don't touch UMS , CARRY and cache bits 166 + * right now MSR is a copy of parent one */ 167 + childregs->msr |= MSR_BIP; 168 + childregs->msr &= ~MSR_EIP; 169 + childregs->msr |= MSR_IE; 170 + childregs->msr &= ~MSR_VM; 171 + childregs->msr |= MSR_VMS; 172 + childregs->msr |= MSR_EE; /* exceptions will be enabled*/ 173 + 174 + ti->cpu_context.msr = (childregs->msr|MSR_VM); 175 + ti->cpu_context.msr &= ~MSR_UMS; /* switch_to to kernel mode */ 176 + #endif 132 177 ti->cpu_context.r15 = (unsigned long)ret_from_fork - 8; 133 178 134 179 if (clone_flags & CLONE_SETTLS) ··· 182 137 return 0; 183 138 } 184 139 140 + #ifndef CONFIG_MMU 185 141 /* 186 142 * Return saved PC of a blocked thread. 187 143 */ ··· 197 151 else 198 152 return ctx->r14; 199 153 } 154 + #endif 200 155 201 156 static void kernel_thread_helper(int (*fn)(void *), void *arg) 202 157 { ··· 236 189 regs->r1 = usp; 237 190 regs->pt_mode = 0; 238 191 } 192 + 193 + #ifdef CONFIG_MMU 194 + #include <linux/elfcore.h> 195 + /* 196 + * Set up a thread for executing a new program 197 + */ 198 + int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpregs) 199 + { 200 + return 0; /* MicroBlaze has no separate FPU registers */ 201 + } 202 + #endif /* CONFIG_MMU */