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