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