1995473aeSJeff Dike /* 2995473aeSJeff Dike * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) 3995473aeSJeff Dike * Copyright 2003 PathScale, Inc. 4995473aeSJeff Dike * Licensed under the GPL 5995473aeSJeff Dike */ 6995473aeSJeff Dike 7995473aeSJeff Dike #include "linux/kernel.h" 8995473aeSJeff Dike #include "linux/sched.h" 9995473aeSJeff Dike #include "linux/interrupt.h" 10995473aeSJeff Dike #include "linux/string.h" 11995473aeSJeff Dike #include "linux/mm.h" 12995473aeSJeff Dike #include "linux/slab.h" 13995473aeSJeff Dike #include "linux/utsname.h" 14995473aeSJeff Dike #include "linux/fs.h" 15995473aeSJeff Dike #include "linux/utime.h" 16995473aeSJeff Dike #include "linux/smp_lock.h" 17995473aeSJeff Dike #include "linux/module.h" 18995473aeSJeff Dike #include "linux/init.h" 19995473aeSJeff Dike #include "linux/capability.h" 20995473aeSJeff Dike #include "linux/vmalloc.h" 21995473aeSJeff Dike #include "linux/spinlock.h" 22995473aeSJeff Dike #include "linux/proc_fs.h" 23995473aeSJeff Dike #include "linux/ptrace.h" 24995473aeSJeff Dike #include "linux/random.h" 25995473aeSJeff Dike #include "linux/personality.h" 26995473aeSJeff Dike #include "asm/unistd.h" 27995473aeSJeff Dike #include "asm/mman.h" 28995473aeSJeff Dike #include "asm/segment.h" 29995473aeSJeff Dike #include "asm/stat.h" 30995473aeSJeff Dike #include "asm/pgtable.h" 31995473aeSJeff Dike #include "asm/processor.h" 32995473aeSJeff Dike #include "asm/tlbflush.h" 33995473aeSJeff Dike #include "asm/uaccess.h" 34995473aeSJeff Dike #include "asm/user.h" 35995473aeSJeff Dike #include "user_util.h" 36995473aeSJeff Dike #include "kern_util.h" 37995473aeSJeff Dike #include "kern.h" 38995473aeSJeff Dike #include "signal_kern.h" 39995473aeSJeff Dike #include "init.h" 40995473aeSJeff Dike #include "irq_user.h" 41995473aeSJeff Dike #include "mem_user.h" 42995473aeSJeff Dike #include "tlb.h" 43995473aeSJeff Dike #include "frame_kern.h" 44995473aeSJeff Dike #include "sigcontext.h" 45995473aeSJeff Dike #include "os.h" 46995473aeSJeff Dike #include "mode.h" 47995473aeSJeff Dike #include "mode_kern.h" 48995473aeSJeff Dike #include "choose-mode.h" 49995473aeSJeff Dike 50995473aeSJeff Dike /* This is a per-cpu array. A processor only modifies its entry and it only 51995473aeSJeff Dike * cares about its entry, so it's OK if another processor is modifying its 52995473aeSJeff Dike * entry. 53995473aeSJeff Dike */ 54995473aeSJeff Dike struct cpu_task cpu_tasks[NR_CPUS] = { [0 ... NR_CPUS - 1] = { -1, NULL } }; 55995473aeSJeff Dike 56995473aeSJeff Dike int external_pid(void *t) 57995473aeSJeff Dike { 58995473aeSJeff Dike struct task_struct *task = t ? t : current; 59995473aeSJeff Dike 60995473aeSJeff Dike return(CHOOSE_MODE_PROC(external_pid_tt, external_pid_skas, task)); 61995473aeSJeff Dike } 62995473aeSJeff Dike 63995473aeSJeff Dike int pid_to_processor_id(int pid) 64995473aeSJeff Dike { 65995473aeSJeff Dike int i; 66995473aeSJeff Dike 67995473aeSJeff Dike for(i = 0; i < ncpus; i++){ 68995473aeSJeff Dike if(cpu_tasks[i].pid == pid) return(i); 69995473aeSJeff Dike } 70995473aeSJeff Dike return(-1); 71995473aeSJeff Dike } 72995473aeSJeff Dike 73995473aeSJeff Dike void free_stack(unsigned long stack, int order) 74995473aeSJeff Dike { 75995473aeSJeff Dike free_pages(stack, order); 76995473aeSJeff Dike } 77995473aeSJeff Dike 78995473aeSJeff Dike unsigned long alloc_stack(int order, int atomic) 79995473aeSJeff Dike { 80995473aeSJeff Dike unsigned long page; 81995473aeSJeff Dike gfp_t flags = GFP_KERNEL; 82995473aeSJeff Dike 83995473aeSJeff Dike if (atomic) 84995473aeSJeff Dike flags = GFP_ATOMIC; 85995473aeSJeff Dike page = __get_free_pages(flags, order); 86995473aeSJeff Dike if(page == 0) 87995473aeSJeff Dike return(0); 88995473aeSJeff Dike stack_protections(page); 89995473aeSJeff Dike return(page); 90995473aeSJeff Dike } 91995473aeSJeff Dike 92995473aeSJeff Dike int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) 93995473aeSJeff Dike { 94995473aeSJeff Dike int pid; 95995473aeSJeff Dike 96995473aeSJeff Dike current->thread.request.u.thread.proc = fn; 97995473aeSJeff Dike current->thread.request.u.thread.arg = arg; 98995473aeSJeff Dike pid = do_fork(CLONE_VM | CLONE_UNTRACED | flags, 0, 99995473aeSJeff Dike ¤t->thread.regs, 0, NULL, NULL); 100995473aeSJeff Dike if(pid < 0) 101995473aeSJeff Dike panic("do_fork failed in kernel_thread, errno = %d", pid); 102995473aeSJeff Dike return(pid); 103995473aeSJeff Dike } 104995473aeSJeff Dike 105995473aeSJeff Dike void set_current(void *t) 106995473aeSJeff Dike { 107995473aeSJeff Dike struct task_struct *task = t; 108995473aeSJeff Dike 109995473aeSJeff Dike cpu_tasks[task_thread_info(task)->cpu] = ((struct cpu_task) 110995473aeSJeff Dike { external_pid(task), task }); 111995473aeSJeff Dike } 112995473aeSJeff Dike 113995473aeSJeff Dike void *_switch_to(void *prev, void *next, void *last) 114995473aeSJeff Dike { 115995473aeSJeff Dike struct task_struct *from = prev; 116995473aeSJeff Dike struct task_struct *to= next; 117995473aeSJeff Dike 118995473aeSJeff Dike to->thread.prev_sched = from; 119995473aeSJeff Dike set_current(to); 120995473aeSJeff Dike 121995473aeSJeff Dike do { 122995473aeSJeff Dike current->thread.saved_task = NULL ; 123995473aeSJeff Dike CHOOSE_MODE_PROC(switch_to_tt, switch_to_skas, prev, next); 124995473aeSJeff Dike if(current->thread.saved_task) 125995473aeSJeff Dike show_regs(&(current->thread.regs)); 126995473aeSJeff Dike next= current->thread.saved_task; 127995473aeSJeff Dike prev= current; 128995473aeSJeff Dike } while(current->thread.saved_task); 129995473aeSJeff Dike 130995473aeSJeff Dike return(current->thread.prev_sched); 131995473aeSJeff Dike 132995473aeSJeff Dike } 133995473aeSJeff Dike 134995473aeSJeff Dike void interrupt_end(void) 135995473aeSJeff Dike { 136995473aeSJeff Dike if(need_resched()) schedule(); 137995473aeSJeff Dike if(test_tsk_thread_flag(current, TIF_SIGPENDING)) do_signal(); 138995473aeSJeff Dike } 139995473aeSJeff Dike 140995473aeSJeff Dike void release_thread(struct task_struct *task) 141995473aeSJeff Dike { 142995473aeSJeff Dike CHOOSE_MODE(release_thread_tt(task), release_thread_skas(task)); 143995473aeSJeff Dike } 144995473aeSJeff Dike 145995473aeSJeff Dike void exit_thread(void) 146995473aeSJeff Dike { 147995473aeSJeff Dike unprotect_stack((unsigned long) current_thread); 148995473aeSJeff Dike } 149995473aeSJeff Dike 150995473aeSJeff Dike void *get_current(void) 151995473aeSJeff Dike { 152995473aeSJeff Dike return(current); 153995473aeSJeff Dike } 154995473aeSJeff Dike 155995473aeSJeff Dike int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, 156995473aeSJeff Dike unsigned long stack_top, struct task_struct * p, 157995473aeSJeff Dike struct pt_regs *regs) 158995473aeSJeff Dike { 159995473aeSJeff Dike int ret; 160995473aeSJeff Dike 161995473aeSJeff Dike p->thread = (struct thread_struct) INIT_THREAD; 162995473aeSJeff Dike ret = CHOOSE_MODE_PROC(copy_thread_tt, copy_thread_skas, nr, 163995473aeSJeff Dike clone_flags, sp, stack_top, p, regs); 164995473aeSJeff Dike 165995473aeSJeff Dike if (ret || !current->thread.forking) 166995473aeSJeff Dike goto out; 167995473aeSJeff Dike 168995473aeSJeff Dike clear_flushed_tls(p); 169995473aeSJeff Dike 170995473aeSJeff Dike /* 171995473aeSJeff Dike * Set a new TLS for the child thread? 172995473aeSJeff Dike */ 173995473aeSJeff Dike if (clone_flags & CLONE_SETTLS) 174995473aeSJeff Dike ret = arch_copy_tls(p); 175995473aeSJeff Dike 176995473aeSJeff Dike out: 177995473aeSJeff Dike return ret; 178995473aeSJeff Dike } 179995473aeSJeff Dike 180995473aeSJeff Dike void initial_thread_cb(void (*proc)(void *), void *arg) 181995473aeSJeff Dike { 182995473aeSJeff Dike int save_kmalloc_ok = kmalloc_ok; 183995473aeSJeff Dike 184995473aeSJeff Dike kmalloc_ok = 0; 185995473aeSJeff Dike CHOOSE_MODE_PROC(initial_thread_cb_tt, initial_thread_cb_skas, proc, 186995473aeSJeff Dike arg); 187995473aeSJeff Dike kmalloc_ok = save_kmalloc_ok; 188995473aeSJeff Dike } 189995473aeSJeff Dike 190995473aeSJeff Dike unsigned long stack_sp(unsigned long page) 191995473aeSJeff Dike { 192995473aeSJeff Dike return(page + PAGE_SIZE - sizeof(void *)); 193995473aeSJeff Dike } 194995473aeSJeff Dike 195995473aeSJeff Dike int current_pid(void) 196995473aeSJeff Dike { 197995473aeSJeff Dike return(current->pid); 198995473aeSJeff Dike } 199995473aeSJeff Dike 200995473aeSJeff Dike void default_idle(void) 201995473aeSJeff Dike { 202995473aeSJeff Dike CHOOSE_MODE(uml_idle_timer(), (void) 0); 203995473aeSJeff Dike 204995473aeSJeff Dike while(1){ 205995473aeSJeff Dike /* endless idle loop with no priority at all */ 206995473aeSJeff Dike 207995473aeSJeff Dike /* 208995473aeSJeff Dike * although we are an idle CPU, we do not want to 209995473aeSJeff Dike * get into the scheduler unnecessarily. 210995473aeSJeff Dike */ 211995473aeSJeff Dike if(need_resched()) 212995473aeSJeff Dike schedule(); 213995473aeSJeff Dike 214995473aeSJeff Dike idle_sleep(10); 215995473aeSJeff Dike } 216995473aeSJeff Dike } 217995473aeSJeff Dike 218995473aeSJeff Dike void cpu_idle(void) 219995473aeSJeff Dike { 220995473aeSJeff Dike CHOOSE_MODE(init_idle_tt(), init_idle_skas()); 221995473aeSJeff Dike } 222995473aeSJeff Dike 223995473aeSJeff Dike int page_size(void) 224995473aeSJeff Dike { 225995473aeSJeff Dike return(PAGE_SIZE); 226995473aeSJeff Dike } 227995473aeSJeff Dike 228995473aeSJeff Dike void *um_virt_to_phys(struct task_struct *task, unsigned long addr, 229995473aeSJeff Dike pte_t *pte_out) 230995473aeSJeff Dike { 231995473aeSJeff Dike pgd_t *pgd; 232995473aeSJeff Dike pud_t *pud; 233995473aeSJeff Dike pmd_t *pmd; 234995473aeSJeff Dike pte_t *pte; 235995473aeSJeff Dike pte_t ptent; 236995473aeSJeff Dike 237995473aeSJeff Dike if(task->mm == NULL) 238995473aeSJeff Dike return(ERR_PTR(-EINVAL)); 239995473aeSJeff Dike pgd = pgd_offset(task->mm, addr); 240995473aeSJeff Dike if(!pgd_present(*pgd)) 241995473aeSJeff Dike return(ERR_PTR(-EINVAL)); 242995473aeSJeff Dike 243995473aeSJeff Dike pud = pud_offset(pgd, addr); 244995473aeSJeff Dike if(!pud_present(*pud)) 245995473aeSJeff Dike return(ERR_PTR(-EINVAL)); 246995473aeSJeff Dike 247995473aeSJeff Dike pmd = pmd_offset(pud, addr); 248995473aeSJeff Dike if(!pmd_present(*pmd)) 249995473aeSJeff Dike return(ERR_PTR(-EINVAL)); 250995473aeSJeff Dike 251995473aeSJeff Dike pte = pte_offset_kernel(pmd, addr); 252995473aeSJeff Dike ptent = *pte; 253995473aeSJeff Dike if(!pte_present(ptent)) 254995473aeSJeff Dike return(ERR_PTR(-EINVAL)); 255995473aeSJeff Dike 256995473aeSJeff Dike if(pte_out != NULL) 257995473aeSJeff Dike *pte_out = ptent; 258995473aeSJeff Dike return((void *) (pte_val(ptent) & PAGE_MASK) + (addr & ~PAGE_MASK)); 259995473aeSJeff Dike } 260995473aeSJeff Dike 261995473aeSJeff Dike char *current_cmd(void) 262995473aeSJeff Dike { 263995473aeSJeff Dike #if defined(CONFIG_SMP) || defined(CONFIG_HIGHMEM) 264995473aeSJeff Dike return("(Unknown)"); 265995473aeSJeff Dike #else 266995473aeSJeff Dike void *addr = um_virt_to_phys(current, current->mm->arg_start, NULL); 267995473aeSJeff Dike return IS_ERR(addr) ? "(Unknown)": __va((unsigned long) addr); 268995473aeSJeff Dike #endif 269995473aeSJeff Dike } 270995473aeSJeff Dike 271995473aeSJeff Dike void force_sigbus(void) 272995473aeSJeff Dike { 273995473aeSJeff Dike printk(KERN_ERR "Killing pid %d because of a lack of memory\n", 274995473aeSJeff Dike current->pid); 275995473aeSJeff Dike lock_kernel(); 276995473aeSJeff Dike sigaddset(¤t->pending.signal, SIGBUS); 277995473aeSJeff Dike recalc_sigpending(); 278995473aeSJeff Dike current->flags |= PF_SIGNALED; 279995473aeSJeff Dike do_exit(SIGBUS | 0x80); 280995473aeSJeff Dike } 281995473aeSJeff Dike 282995473aeSJeff Dike void dump_thread(struct pt_regs *regs, struct user *u) 283995473aeSJeff Dike { 284995473aeSJeff Dike } 285995473aeSJeff Dike 286995473aeSJeff Dike void enable_hlt(void) 287995473aeSJeff Dike { 288995473aeSJeff Dike panic("enable_hlt"); 289995473aeSJeff Dike } 290995473aeSJeff Dike 291995473aeSJeff Dike EXPORT_SYMBOL(enable_hlt); 292995473aeSJeff Dike 293995473aeSJeff Dike void disable_hlt(void) 294995473aeSJeff Dike { 295995473aeSJeff Dike panic("disable_hlt"); 296995473aeSJeff Dike } 297995473aeSJeff Dike 298995473aeSJeff Dike EXPORT_SYMBOL(disable_hlt); 299995473aeSJeff Dike 300995473aeSJeff Dike void *um_kmalloc(int size) 301995473aeSJeff Dike { 302995473aeSJeff Dike return kmalloc(size, GFP_KERNEL); 303995473aeSJeff Dike } 304995473aeSJeff Dike 305995473aeSJeff Dike void *um_kmalloc_atomic(int size) 306995473aeSJeff Dike { 307995473aeSJeff Dike return kmalloc(size, GFP_ATOMIC); 308995473aeSJeff Dike } 309995473aeSJeff Dike 310995473aeSJeff Dike void *um_vmalloc(int size) 311995473aeSJeff Dike { 312995473aeSJeff Dike return vmalloc(size); 313995473aeSJeff Dike } 314995473aeSJeff Dike 315995473aeSJeff Dike void *um_vmalloc_atomic(int size) 316995473aeSJeff Dike { 317995473aeSJeff Dike return __vmalloc(size, GFP_ATOMIC | __GFP_HIGHMEM, PAGE_KERNEL); 318995473aeSJeff Dike } 319995473aeSJeff Dike 320995473aeSJeff Dike int __cant_sleep(void) { 321995473aeSJeff Dike return in_atomic() || irqs_disabled() || in_interrupt(); 322995473aeSJeff Dike /* Is in_interrupt() really needed? */ 323995473aeSJeff Dike } 324995473aeSJeff Dike 325995473aeSJeff Dike unsigned long get_fault_addr(void) 326995473aeSJeff Dike { 327995473aeSJeff Dike return((unsigned long) current->thread.fault_addr); 328995473aeSJeff Dike } 329995473aeSJeff Dike 330995473aeSJeff Dike EXPORT_SYMBOL(get_fault_addr); 331995473aeSJeff Dike 332995473aeSJeff Dike void not_implemented(void) 333995473aeSJeff Dike { 334995473aeSJeff Dike printk(KERN_DEBUG "Something isn't implemented in here\n"); 335995473aeSJeff Dike } 336995473aeSJeff Dike 337995473aeSJeff Dike EXPORT_SYMBOL(not_implemented); 338995473aeSJeff Dike 339995473aeSJeff Dike int user_context(unsigned long sp) 340995473aeSJeff Dike { 341995473aeSJeff Dike unsigned long stack; 342995473aeSJeff Dike 343995473aeSJeff Dike stack = sp & (PAGE_MASK << CONFIG_KERNEL_STACK_ORDER); 344995473aeSJeff Dike return(stack != (unsigned long) current_thread); 345995473aeSJeff Dike } 346995473aeSJeff Dike 347995473aeSJeff Dike extern exitcall_t __uml_exitcall_begin, __uml_exitcall_end; 348995473aeSJeff Dike 349995473aeSJeff Dike void do_uml_exitcalls(void) 350995473aeSJeff Dike { 351995473aeSJeff Dike exitcall_t *call; 352995473aeSJeff Dike 353995473aeSJeff Dike call = &__uml_exitcall_end; 354995473aeSJeff Dike while (--call >= &__uml_exitcall_begin) 355995473aeSJeff Dike (*call)(); 356995473aeSJeff Dike } 357995473aeSJeff Dike 358995473aeSJeff Dike char *uml_strdup(char *string) 359995473aeSJeff Dike { 360995473aeSJeff Dike return kstrdup(string, GFP_KERNEL); 361995473aeSJeff Dike } 362995473aeSJeff Dike 363995473aeSJeff Dike int copy_to_user_proc(void __user *to, void *from, int size) 364995473aeSJeff Dike { 365995473aeSJeff Dike return(copy_to_user(to, from, size)); 366995473aeSJeff Dike } 367995473aeSJeff Dike 368995473aeSJeff Dike int copy_from_user_proc(void *to, void __user *from, int size) 369995473aeSJeff Dike { 370995473aeSJeff Dike return(copy_from_user(to, from, size)); 371995473aeSJeff Dike } 372995473aeSJeff Dike 373995473aeSJeff Dike int clear_user_proc(void __user *buf, int size) 374995473aeSJeff Dike { 375995473aeSJeff Dike return(clear_user(buf, size)); 376995473aeSJeff Dike } 377995473aeSJeff Dike 378995473aeSJeff Dike int strlen_user_proc(char __user *str) 379995473aeSJeff Dike { 380995473aeSJeff Dike return(strlen_user(str)); 381995473aeSJeff Dike } 382995473aeSJeff Dike 383995473aeSJeff Dike int smp_sigio_handler(void) 384995473aeSJeff Dike { 385995473aeSJeff Dike #ifdef CONFIG_SMP 386995473aeSJeff Dike int cpu = current_thread->cpu; 387995473aeSJeff Dike IPI_handler(cpu); 388995473aeSJeff Dike if(cpu != 0) 389995473aeSJeff Dike return(1); 390995473aeSJeff Dike #endif 391995473aeSJeff Dike return(0); 392995473aeSJeff Dike } 393995473aeSJeff Dike 394995473aeSJeff Dike int cpu(void) 395995473aeSJeff Dike { 396995473aeSJeff Dike return(current_thread->cpu); 397995473aeSJeff Dike } 398995473aeSJeff Dike 399995473aeSJeff Dike static atomic_t using_sysemu = ATOMIC_INIT(0); 400995473aeSJeff Dike int sysemu_supported; 401995473aeSJeff Dike 402995473aeSJeff Dike void set_using_sysemu(int value) 403995473aeSJeff Dike { 404995473aeSJeff Dike if (value > sysemu_supported) 405995473aeSJeff Dike return; 406995473aeSJeff Dike atomic_set(&using_sysemu, value); 407995473aeSJeff Dike } 408995473aeSJeff Dike 409995473aeSJeff Dike int get_using_sysemu(void) 410995473aeSJeff Dike { 411995473aeSJeff Dike return atomic_read(&using_sysemu); 412995473aeSJeff Dike } 413995473aeSJeff Dike 414995473aeSJeff Dike static int proc_read_sysemu(char *buf, char **start, off_t offset, int size,int *eof, void *data) 415995473aeSJeff Dike { 416995473aeSJeff Dike if (snprintf(buf, size, "%d\n", get_using_sysemu()) < size) /*No overflow*/ 417995473aeSJeff Dike *eof = 1; 418995473aeSJeff Dike 419995473aeSJeff Dike return strlen(buf); 420995473aeSJeff Dike } 421995473aeSJeff Dike 422995473aeSJeff Dike static int proc_write_sysemu(struct file *file,const char __user *buf, unsigned long count,void *data) 423995473aeSJeff Dike { 424995473aeSJeff Dike char tmp[2]; 425995473aeSJeff Dike 426995473aeSJeff Dike if (copy_from_user(tmp, buf, 1)) 427995473aeSJeff Dike return -EFAULT; 428995473aeSJeff Dike 429995473aeSJeff Dike if (tmp[0] >= '0' && tmp[0] <= '2') 430995473aeSJeff Dike set_using_sysemu(tmp[0] - '0'); 431995473aeSJeff Dike return count; /*We use the first char, but pretend to write everything*/ 432995473aeSJeff Dike } 433995473aeSJeff Dike 434995473aeSJeff Dike int __init make_proc_sysemu(void) 435995473aeSJeff Dike { 436995473aeSJeff Dike struct proc_dir_entry *ent; 437995473aeSJeff Dike if (!sysemu_supported) 438995473aeSJeff Dike return 0; 439995473aeSJeff Dike 440995473aeSJeff Dike ent = create_proc_entry("sysemu", 0600, &proc_root); 441995473aeSJeff Dike 442995473aeSJeff Dike if (ent == NULL) 443995473aeSJeff Dike { 444995473aeSJeff Dike printk(KERN_WARNING "Failed to register /proc/sysemu\n"); 445995473aeSJeff Dike return(0); 446995473aeSJeff Dike } 447995473aeSJeff Dike 448995473aeSJeff Dike ent->read_proc = proc_read_sysemu; 449995473aeSJeff Dike ent->write_proc = proc_write_sysemu; 450995473aeSJeff Dike 451995473aeSJeff Dike return 0; 452995473aeSJeff Dike } 453995473aeSJeff Dike 454995473aeSJeff Dike late_initcall(make_proc_sysemu); 455995473aeSJeff Dike 456995473aeSJeff Dike int singlestepping(void * t) 457995473aeSJeff Dike { 458995473aeSJeff Dike struct task_struct *task = t ? t : current; 459995473aeSJeff Dike 460995473aeSJeff Dike if ( ! (task->ptrace & PT_DTRACE) ) 461995473aeSJeff Dike return(0); 462995473aeSJeff Dike 463995473aeSJeff Dike if (task->thread.singlestep_syscall) 464995473aeSJeff Dike return(1); 465995473aeSJeff Dike 466995473aeSJeff Dike return 2; 467995473aeSJeff Dike } 468995473aeSJeff Dike 469995473aeSJeff Dike /* 470995473aeSJeff Dike * Only x86 and x86_64 have an arch_align_stack(). 471995473aeSJeff Dike * All other arches have "#define arch_align_stack(x) (x)" 472995473aeSJeff Dike * in their asm/system.h 473995473aeSJeff Dike * As this is included in UML from asm-um/system-generic.h, 474995473aeSJeff Dike * we can use it to behave as the subarch does. 475995473aeSJeff Dike */ 476995473aeSJeff Dike #ifndef arch_align_stack 477995473aeSJeff Dike unsigned long arch_align_stack(unsigned long sp) 478995473aeSJeff Dike { 479995473aeSJeff Dike if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space) 480995473aeSJeff Dike sp -= get_random_int() % 8192; 481995473aeSJeff Dike return sp & ~0xf; 482995473aeSJeff Dike } 483995473aeSJeff Dike #endif 484