ia64/linux-2.6.18-xen.hg

view arch/sparc64/kernel/process.c @ 897:329ea0ccb344

balloon: try harder to balloon up under memory pressure.

Currently if the balloon driver is unable to increase the guest's
reservation it assumes the failure was due to reaching its full
allocation, gives up on the ballooning operation and records the limit
it reached as the "hard limit". The driver will not try again until
the target is set again (even to the same value).

However it is possible that ballooning has in fact failed due to
memory pressure in the host and therefore it is desirable to keep
attempting to reach the target in case memory becomes available. The
most likely scenario is that some guests are ballooning down while
others are ballooning up and therefore there is temporary memory
pressure while things stabilise. You would not expect a well behaved
toolstack to ask a domain to balloon to more than its allocation nor
would you expect it to deliberately over-commit memory by setting
balloon targets which exceed the total host memory.

This patch drops the concept of a hard limit and causes the balloon
driver to retry increasing the reservation on a timer in the same
manner as when decreasing the reservation.

Also if we partially succeed in increasing the reservation
(i.e. receive less pages than we asked for) then we may as well keep
those pages rather than returning them to Xen.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Jun 05 14:01:20 2009 +0100 (2009-06-05)
parents 831230e53067
children
line source
1 /* $Id: process.c,v 1.131 2002/02/09 19:49:30 davem Exp $
2 * arch/sparc64/kernel/process.c
3 *
4 * Copyright (C) 1995, 1996 David S. Miller (davem@caip.rutgers.edu)
5 * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be)
6 * Copyright (C) 1997, 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
7 */
9 /*
10 * This file handles the architecture-dependent parts of process handling..
11 */
13 #include <stdarg.h>
15 #include <linux/errno.h>
16 #include <linux/module.h>
17 #include <linux/sched.h>
18 #include <linux/kernel.h>
19 #include <linux/kallsyms.h>
20 #include <linux/mm.h>
21 #include <linux/smp.h>
22 #include <linux/smp_lock.h>
23 #include <linux/stddef.h>
24 #include <linux/ptrace.h>
25 #include <linux/slab.h>
26 #include <linux/user.h>
27 #include <linux/a.out.h>
28 #include <linux/reboot.h>
29 #include <linux/delay.h>
30 #include <linux/compat.h>
31 #include <linux/init.h>
33 #include <asm/oplib.h>
34 #include <asm/uaccess.h>
35 #include <asm/system.h>
36 #include <asm/page.h>
37 #include <asm/pgalloc.h>
38 #include <asm/pgtable.h>
39 #include <asm/processor.h>
40 #include <asm/pstate.h>
41 #include <asm/elf.h>
42 #include <asm/fpumacro.h>
43 #include <asm/head.h>
44 #include <asm/cpudata.h>
45 #include <asm/mmu_context.h>
46 #include <asm/unistd.h>
47 #include <asm/hypervisor.h>
49 /* #define VERBOSE_SHOWREGS */
51 static void sparc64_yield(void)
52 {
53 if (tlb_type != hypervisor)
54 return;
56 clear_thread_flag(TIF_POLLING_NRFLAG);
57 smp_mb__after_clear_bit();
59 while (!need_resched()) {
60 unsigned long pstate;
62 /* Disable interrupts. */
63 __asm__ __volatile__(
64 "rdpr %%pstate, %0\n\t"
65 "andn %0, %1, %0\n\t"
66 "wrpr %0, %%g0, %%pstate"
67 : "=&r" (pstate)
68 : "i" (PSTATE_IE));
70 if (!need_resched())
71 sun4v_cpu_yield();
73 /* Re-enable interrupts. */
74 __asm__ __volatile__(
75 "rdpr %%pstate, %0\n\t"
76 "or %0, %1, %0\n\t"
77 "wrpr %0, %%g0, %%pstate"
78 : "=&r" (pstate)
79 : "i" (PSTATE_IE));
80 }
82 set_thread_flag(TIF_POLLING_NRFLAG);
83 }
85 /* The idle loop on sparc64. */
86 void cpu_idle(void)
87 {
88 set_thread_flag(TIF_POLLING_NRFLAG);
90 while(1) {
91 if (need_resched()) {
92 preempt_enable_no_resched();
93 schedule();
94 preempt_disable();
95 }
96 sparc64_yield();
97 }
98 }
100 extern char reboot_command [];
102 extern void (*prom_palette)(int);
103 extern void (*prom_keyboard)(void);
105 void machine_halt(void)
106 {
107 if (!serial_console && prom_palette)
108 prom_palette (1);
109 if (prom_keyboard)
110 prom_keyboard();
111 prom_halt();
112 panic("Halt failed!");
113 }
115 void machine_alt_power_off(void)
116 {
117 if (!serial_console && prom_palette)
118 prom_palette(1);
119 if (prom_keyboard)
120 prom_keyboard();
121 prom_halt_power_off();
122 panic("Power-off failed!");
123 }
125 void machine_restart(char * cmd)
126 {
127 char *p;
129 p = strchr (reboot_command, '\n');
130 if (p) *p = 0;
131 if (!serial_console && prom_palette)
132 prom_palette (1);
133 if (prom_keyboard)
134 prom_keyboard();
135 if (cmd)
136 prom_reboot(cmd);
137 if (*reboot_command)
138 prom_reboot(reboot_command);
139 prom_reboot("");
140 panic("Reboot failed!");
141 }
143 #ifdef CONFIG_COMPAT
144 static void show_regwindow32(struct pt_regs *regs)
145 {
146 struct reg_window32 __user *rw;
147 struct reg_window32 r_w;
148 mm_segment_t old_fs;
150 __asm__ __volatile__ ("flushw");
151 rw = compat_ptr((unsigned)regs->u_regs[14]);
152 old_fs = get_fs();
153 set_fs (USER_DS);
154 if (copy_from_user (&r_w, rw, sizeof(r_w))) {
155 set_fs (old_fs);
156 return;
157 }
159 set_fs (old_fs);
160 printk("l0: %08x l1: %08x l2: %08x l3: %08x "
161 "l4: %08x l5: %08x l6: %08x l7: %08x\n",
162 r_w.locals[0], r_w.locals[1], r_w.locals[2], r_w.locals[3],
163 r_w.locals[4], r_w.locals[5], r_w.locals[6], r_w.locals[7]);
164 printk("i0: %08x i1: %08x i2: %08x i3: %08x "
165 "i4: %08x i5: %08x i6: %08x i7: %08x\n",
166 r_w.ins[0], r_w.ins[1], r_w.ins[2], r_w.ins[3],
167 r_w.ins[4], r_w.ins[5], r_w.ins[6], r_w.ins[7]);
168 }
169 #else
170 #define show_regwindow32(regs) do { } while (0)
171 #endif
173 static void show_regwindow(struct pt_regs *regs)
174 {
175 struct reg_window __user *rw;
176 struct reg_window *rwk;
177 struct reg_window r_w;
178 mm_segment_t old_fs;
180 if ((regs->tstate & TSTATE_PRIV) || !(test_thread_flag(TIF_32BIT))) {
181 __asm__ __volatile__ ("flushw");
182 rw = (struct reg_window __user *)
183 (regs->u_regs[14] + STACK_BIAS);
184 rwk = (struct reg_window *)
185 (regs->u_regs[14] + STACK_BIAS);
186 if (!(regs->tstate & TSTATE_PRIV)) {
187 old_fs = get_fs();
188 set_fs (USER_DS);
189 if (copy_from_user (&r_w, rw, sizeof(r_w))) {
190 set_fs (old_fs);
191 return;
192 }
193 rwk = &r_w;
194 set_fs (old_fs);
195 }
196 } else {
197 show_regwindow32(regs);
198 return;
199 }
200 printk("l0: %016lx l1: %016lx l2: %016lx l3: %016lx\n",
201 rwk->locals[0], rwk->locals[1], rwk->locals[2], rwk->locals[3]);
202 printk("l4: %016lx l5: %016lx l6: %016lx l7: %016lx\n",
203 rwk->locals[4], rwk->locals[5], rwk->locals[6], rwk->locals[7]);
204 printk("i0: %016lx i1: %016lx i2: %016lx i3: %016lx\n",
205 rwk->ins[0], rwk->ins[1], rwk->ins[2], rwk->ins[3]);
206 printk("i4: %016lx i5: %016lx i6: %016lx i7: %016lx\n",
207 rwk->ins[4], rwk->ins[5], rwk->ins[6], rwk->ins[7]);
208 if (regs->tstate & TSTATE_PRIV)
209 print_symbol("I7: <%s>\n", rwk->ins[7]);
210 }
212 void show_stackframe(struct sparc_stackf *sf)
213 {
214 unsigned long size;
215 unsigned long *stk;
216 int i;
218 printk("l0: %016lx l1: %016lx l2: %016lx l3: %016lx\n"
219 "l4: %016lx l5: %016lx l6: %016lx l7: %016lx\n",
220 sf->locals[0], sf->locals[1], sf->locals[2], sf->locals[3],
221 sf->locals[4], sf->locals[5], sf->locals[6], sf->locals[7]);
222 printk("i0: %016lx i1: %016lx i2: %016lx i3: %016lx\n"
223 "i4: %016lx i5: %016lx fp: %016lx ret_pc: %016lx\n",
224 sf->ins[0], sf->ins[1], sf->ins[2], sf->ins[3],
225 sf->ins[4], sf->ins[5], (unsigned long)sf->fp, sf->callers_pc);
226 printk("sp: %016lx x0: %016lx x1: %016lx x2: %016lx\n"
227 "x3: %016lx x4: %016lx x5: %016lx xx: %016lx\n",
228 (unsigned long)sf->structptr, sf->xargs[0], sf->xargs[1],
229 sf->xargs[2], sf->xargs[3], sf->xargs[4], sf->xargs[5],
230 sf->xxargs[0]);
231 size = ((unsigned long)sf->fp) - ((unsigned long)sf);
232 size -= STACKFRAME_SZ;
233 stk = (unsigned long *)((unsigned long)sf + STACKFRAME_SZ);
234 i = 0;
235 do {
236 printk("s%d: %016lx\n", i++, *stk++);
237 } while ((size -= sizeof(unsigned long)));
238 }
240 void show_stackframe32(struct sparc_stackf32 *sf)
241 {
242 unsigned long size;
243 unsigned *stk;
244 int i;
246 printk("l0: %08x l1: %08x l2: %08x l3: %08x\n",
247 sf->locals[0], sf->locals[1], sf->locals[2], sf->locals[3]);
248 printk("l4: %08x l5: %08x l6: %08x l7: %08x\n",
249 sf->locals[4], sf->locals[5], sf->locals[6], sf->locals[7]);
250 printk("i0: %08x i1: %08x i2: %08x i3: %08x\n",
251 sf->ins[0], sf->ins[1], sf->ins[2], sf->ins[3]);
252 printk("i4: %08x i5: %08x fp: %08x ret_pc: %08x\n",
253 sf->ins[4], sf->ins[5], sf->fp, sf->callers_pc);
254 printk("sp: %08x x0: %08x x1: %08x x2: %08x\n"
255 "x3: %08x x4: %08x x5: %08x xx: %08x\n",
256 sf->structptr, sf->xargs[0], sf->xargs[1],
257 sf->xargs[2], sf->xargs[3], sf->xargs[4], sf->xargs[5],
258 sf->xxargs[0]);
259 size = ((unsigned long)sf->fp) - ((unsigned long)sf);
260 size -= STACKFRAME32_SZ;
261 stk = (unsigned *)((unsigned long)sf + STACKFRAME32_SZ);
262 i = 0;
263 do {
264 printk("s%d: %08x\n", i++, *stk++);
265 } while ((size -= sizeof(unsigned)));
266 }
268 #ifdef CONFIG_SMP
269 static DEFINE_SPINLOCK(regdump_lock);
270 #endif
272 void __show_regs(struct pt_regs * regs)
273 {
274 #ifdef CONFIG_SMP
275 unsigned long flags;
277 /* Protect against xcall ipis which might lead to livelock on the lock */
278 __asm__ __volatile__("rdpr %%pstate, %0\n\t"
279 "wrpr %0, %1, %%pstate"
280 : "=r" (flags)
281 : "i" (PSTATE_IE));
282 spin_lock(&regdump_lock);
283 #endif
284 printk("TSTATE: %016lx TPC: %016lx TNPC: %016lx Y: %08x %s\n", regs->tstate,
285 regs->tpc, regs->tnpc, regs->y, print_tainted());
286 print_symbol("TPC: <%s>\n", regs->tpc);
287 printk("g0: %016lx g1: %016lx g2: %016lx g3: %016lx\n",
288 regs->u_regs[0], regs->u_regs[1], regs->u_regs[2],
289 regs->u_regs[3]);
290 printk("g4: %016lx g5: %016lx g6: %016lx g7: %016lx\n",
291 regs->u_regs[4], regs->u_regs[5], regs->u_regs[6],
292 regs->u_regs[7]);
293 printk("o0: %016lx o1: %016lx o2: %016lx o3: %016lx\n",
294 regs->u_regs[8], regs->u_regs[9], regs->u_regs[10],
295 regs->u_regs[11]);
296 printk("o4: %016lx o5: %016lx sp: %016lx ret_pc: %016lx\n",
297 regs->u_regs[12], regs->u_regs[13], regs->u_regs[14],
298 regs->u_regs[15]);
299 print_symbol("RPC: <%s>\n", regs->u_regs[15]);
300 show_regwindow(regs);
301 #ifdef CONFIG_SMP
302 spin_unlock(&regdump_lock);
303 __asm__ __volatile__("wrpr %0, 0, %%pstate"
304 : : "r" (flags));
305 #endif
306 }
308 #ifdef VERBOSE_SHOWREGS
309 static void idump_from_user (unsigned int *pc)
310 {
311 int i;
312 int code;
314 if((((unsigned long) pc) & 3))
315 return;
317 pc -= 3;
318 for(i = -3; i < 6; i++) {
319 get_user(code, pc);
320 printk("%c%08x%c",i?' ':'<',code,i?' ':'>');
321 pc++;
322 }
323 printk("\n");
324 }
325 #endif
327 void show_regs(struct pt_regs *regs)
328 {
329 #ifdef VERBOSE_SHOWREGS
330 extern long etrap, etraptl1;
331 #endif
332 __show_regs(regs);
333 #if 0
334 #ifdef CONFIG_SMP
335 {
336 extern void smp_report_regs(void);
338 smp_report_regs();
339 }
340 #endif
341 #endif
343 #ifdef VERBOSE_SHOWREGS
344 if (regs->tpc >= &etrap && regs->tpc < &etraptl1 &&
345 regs->u_regs[14] >= (long)current - PAGE_SIZE &&
346 regs->u_regs[14] < (long)current + 6 * PAGE_SIZE) {
347 printk ("*********parent**********\n");
348 __show_regs((struct pt_regs *)(regs->u_regs[14] + PTREGS_OFF));
349 idump_from_user(((struct pt_regs *)(regs->u_regs[14] + PTREGS_OFF))->tpc);
350 printk ("*********endpar**********\n");
351 }
352 #endif
353 }
355 void show_regs32(struct pt_regs32 *regs)
356 {
357 printk("PSR: %08x PC: %08x NPC: %08x Y: %08x %s\n", regs->psr,
358 regs->pc, regs->npc, regs->y, print_tainted());
359 printk("g0: %08x g1: %08x g2: %08x g3: %08x ",
360 regs->u_regs[0], regs->u_regs[1], regs->u_regs[2],
361 regs->u_regs[3]);
362 printk("g4: %08x g5: %08x g6: %08x g7: %08x\n",
363 regs->u_regs[4], regs->u_regs[5], regs->u_regs[6],
364 regs->u_regs[7]);
365 printk("o0: %08x o1: %08x o2: %08x o3: %08x ",
366 regs->u_regs[8], regs->u_regs[9], regs->u_regs[10],
367 regs->u_regs[11]);
368 printk("o4: %08x o5: %08x sp: %08x ret_pc: %08x\n",
369 regs->u_regs[12], regs->u_regs[13], regs->u_regs[14],
370 regs->u_regs[15]);
371 }
373 unsigned long thread_saved_pc(struct task_struct *tsk)
374 {
375 struct thread_info *ti = task_thread_info(tsk);
376 unsigned long ret = 0xdeadbeefUL;
378 if (ti && ti->ksp) {
379 unsigned long *sp;
380 sp = (unsigned long *)(ti->ksp + STACK_BIAS);
381 if (((unsigned long)sp & (sizeof(long) - 1)) == 0UL &&
382 sp[14]) {
383 unsigned long *fp;
384 fp = (unsigned long *)(sp[14] + STACK_BIAS);
385 if (((unsigned long)fp & (sizeof(long) - 1)) == 0UL)
386 ret = fp[15];
387 }
388 }
389 return ret;
390 }
392 /* Free current thread data structures etc.. */
393 void exit_thread(void)
394 {
395 struct thread_info *t = current_thread_info();
397 if (t->utraps) {
398 if (t->utraps[0] < 2)
399 kfree (t->utraps);
400 else
401 t->utraps[0]--;
402 }
404 if (test_and_clear_thread_flag(TIF_PERFCTR)) {
405 t->user_cntd0 = t->user_cntd1 = NULL;
406 t->pcr_reg = 0;
407 write_pcr(0);
408 }
409 }
411 void flush_thread(void)
412 {
413 struct thread_info *t = current_thread_info();
414 struct mm_struct *mm;
416 if (t->flags & _TIF_ABI_PENDING)
417 t->flags ^= (_TIF_ABI_PENDING | _TIF_32BIT);
419 mm = t->task->mm;
420 if (mm)
421 tsb_context_switch(mm);
423 set_thread_wsaved(0);
425 /* Turn off performance counters if on. */
426 if (test_and_clear_thread_flag(TIF_PERFCTR)) {
427 t->user_cntd0 = t->user_cntd1 = NULL;
428 t->pcr_reg = 0;
429 write_pcr(0);
430 }
432 /* Clear FPU register state. */
433 t->fpsaved[0] = 0;
435 if (get_thread_current_ds() != ASI_AIUS)
436 set_fs(USER_DS);
438 /* Init new signal delivery disposition. */
439 clear_thread_flag(TIF_NEWSIGNALS);
440 }
442 /* It's a bit more tricky when 64-bit tasks are involved... */
443 static unsigned long clone_stackframe(unsigned long csp, unsigned long psp)
444 {
445 unsigned long fp, distance, rval;
447 if (!(test_thread_flag(TIF_32BIT))) {
448 csp += STACK_BIAS;
449 psp += STACK_BIAS;
450 __get_user(fp, &(((struct reg_window __user *)psp)->ins[6]));
451 fp += STACK_BIAS;
452 } else
453 __get_user(fp, &(((struct reg_window32 __user *)psp)->ins[6]));
455 /* Now 8-byte align the stack as this is mandatory in the
456 * Sparc ABI due to how register windows work. This hides
457 * the restriction from thread libraries etc. -DaveM
458 */
459 csp &= ~7UL;
461 distance = fp - psp;
462 rval = (csp - distance);
463 if (copy_in_user((void __user *) rval, (void __user *) psp, distance))
464 rval = 0;
465 else if (test_thread_flag(TIF_32BIT)) {
466 if (put_user(((u32)csp),
467 &(((struct reg_window32 __user *)rval)->ins[6])))
468 rval = 0;
469 } else {
470 if (put_user(((u64)csp - STACK_BIAS),
471 &(((struct reg_window __user *)rval)->ins[6])))
472 rval = 0;
473 else
474 rval = rval - STACK_BIAS;
475 }
477 return rval;
478 }
480 /* Standard stuff. */
481 static inline void shift_window_buffer(int first_win, int last_win,
482 struct thread_info *t)
483 {
484 int i;
486 for (i = first_win; i < last_win; i++) {
487 t->rwbuf_stkptrs[i] = t->rwbuf_stkptrs[i+1];
488 memcpy(&t->reg_window[i], &t->reg_window[i+1],
489 sizeof(struct reg_window));
490 }
491 }
493 void synchronize_user_stack(void)
494 {
495 struct thread_info *t = current_thread_info();
496 unsigned long window;
498 flush_user_windows();
499 if ((window = get_thread_wsaved()) != 0) {
500 int winsize = sizeof(struct reg_window);
501 int bias = 0;
503 if (test_thread_flag(TIF_32BIT))
504 winsize = sizeof(struct reg_window32);
505 else
506 bias = STACK_BIAS;
508 window -= 1;
509 do {
510 unsigned long sp = (t->rwbuf_stkptrs[window] + bias);
511 struct reg_window *rwin = &t->reg_window[window];
513 if (!copy_to_user((char __user *)sp, rwin, winsize)) {
514 shift_window_buffer(window, get_thread_wsaved() - 1, t);
515 set_thread_wsaved(get_thread_wsaved() - 1);
516 }
517 } while (window--);
518 }
519 }
521 static void stack_unaligned(unsigned long sp)
522 {
523 siginfo_t info;
525 info.si_signo = SIGBUS;
526 info.si_errno = 0;
527 info.si_code = BUS_ADRALN;
528 info.si_addr = (void __user *) sp;
529 info.si_trapno = 0;
530 force_sig_info(SIGBUS, &info, current);
531 }
533 void fault_in_user_windows(void)
534 {
535 struct thread_info *t = current_thread_info();
536 unsigned long window;
537 int winsize = sizeof(struct reg_window);
538 int bias = 0;
540 if (test_thread_flag(TIF_32BIT))
541 winsize = sizeof(struct reg_window32);
542 else
543 bias = STACK_BIAS;
545 flush_user_windows();
546 window = get_thread_wsaved();
548 if (likely(window != 0)) {
549 window -= 1;
550 do {
551 unsigned long sp = (t->rwbuf_stkptrs[window] + bias);
552 struct reg_window *rwin = &t->reg_window[window];
554 if (unlikely(sp & 0x7UL))
555 stack_unaligned(sp);
557 if (unlikely(copy_to_user((char __user *)sp,
558 rwin, winsize)))
559 goto barf;
560 } while (window--);
561 }
562 set_thread_wsaved(0);
563 return;
565 barf:
566 set_thread_wsaved(window + 1);
567 do_exit(SIGILL);
568 }
570 asmlinkage long sparc_do_fork(unsigned long clone_flags,
571 unsigned long stack_start,
572 struct pt_regs *regs,
573 unsigned long stack_size)
574 {
575 int __user *parent_tid_ptr, *child_tid_ptr;
577 #ifdef CONFIG_COMPAT
578 if (test_thread_flag(TIF_32BIT)) {
579 parent_tid_ptr = compat_ptr(regs->u_regs[UREG_I2]);
580 child_tid_ptr = compat_ptr(regs->u_regs[UREG_I4]);
581 } else
582 #endif
583 {
584 parent_tid_ptr = (int __user *) regs->u_regs[UREG_I2];
585 child_tid_ptr = (int __user *) regs->u_regs[UREG_I4];
586 }
588 return do_fork(clone_flags, stack_start,
589 regs, stack_size,
590 parent_tid_ptr, child_tid_ptr);
591 }
593 /* Copy a Sparc thread. The fork() return value conventions
594 * under SunOS are nothing short of bletcherous:
595 * Parent --> %o0 == childs pid, %o1 == 0
596 * Child --> %o0 == parents pid, %o1 == 1
597 */
598 int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
599 unsigned long unused,
600 struct task_struct *p, struct pt_regs *regs)
601 {
602 struct thread_info *t = task_thread_info(p);
603 char *child_trap_frame;
605 /* Calculate offset to stack_frame & pt_regs */
606 child_trap_frame = task_stack_page(p) + (THREAD_SIZE - (TRACEREG_SZ+STACKFRAME_SZ));
607 memcpy(child_trap_frame, (((struct sparc_stackf *)regs)-1), (TRACEREG_SZ+STACKFRAME_SZ));
609 t->flags = (t->flags & ~((0xffUL << TI_FLAG_CWP_SHIFT) | (0xffUL << TI_FLAG_CURRENT_DS_SHIFT))) |
610 (((regs->tstate + 1) & TSTATE_CWP) << TI_FLAG_CWP_SHIFT);
611 t->new_child = 1;
612 t->ksp = ((unsigned long) child_trap_frame) - STACK_BIAS;
613 t->kregs = (struct pt_regs *)(child_trap_frame+sizeof(struct sparc_stackf));
614 t->fpsaved[0] = 0;
616 if (regs->tstate & TSTATE_PRIV) {
617 /* Special case, if we are spawning a kernel thread from
618 * a userspace task (via KMOD, NFS, or similar) we must
619 * disable performance counters in the child because the
620 * address space and protection realm are changing.
621 */
622 if (t->flags & _TIF_PERFCTR) {
623 t->user_cntd0 = t->user_cntd1 = NULL;
624 t->pcr_reg = 0;
625 t->flags &= ~_TIF_PERFCTR;
626 }
627 t->kregs->u_regs[UREG_FP] = t->ksp;
628 t->flags |= ((long)ASI_P << TI_FLAG_CURRENT_DS_SHIFT);
629 flush_register_windows();
630 memcpy((void *)(t->ksp + STACK_BIAS),
631 (void *)(regs->u_regs[UREG_FP] + STACK_BIAS),
632 sizeof(struct sparc_stackf));
633 t->kregs->u_regs[UREG_G6] = (unsigned long) t;
634 t->kregs->u_regs[UREG_G4] = (unsigned long) t->task;
635 } else {
636 if (t->flags & _TIF_32BIT) {
637 sp &= 0x00000000ffffffffUL;
638 regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL;
639 }
640 t->kregs->u_regs[UREG_FP] = sp;
641 t->flags |= ((long)ASI_AIUS << TI_FLAG_CURRENT_DS_SHIFT);
642 if (sp != regs->u_regs[UREG_FP]) {
643 unsigned long csp;
645 csp = clone_stackframe(sp, regs->u_regs[UREG_FP]);
646 if (!csp)
647 return -EFAULT;
648 t->kregs->u_regs[UREG_FP] = csp;
649 }
650 if (t->utraps)
651 t->utraps[0]++;
652 }
654 /* Set the return value for the child. */
655 t->kregs->u_regs[UREG_I0] = current->pid;
656 t->kregs->u_regs[UREG_I1] = 1;
658 /* Set the second return value for the parent. */
659 regs->u_regs[UREG_I1] = 0;
661 if (clone_flags & CLONE_SETTLS)
662 t->kregs->u_regs[UREG_G7] = regs->u_regs[UREG_I3];
664 return 0;
665 }
667 /*
668 * This is the mechanism for creating a new kernel thread.
669 *
670 * NOTE! Only a kernel-only process(ie the swapper or direct descendants
671 * who haven't done an "execve()") should use this: it will work within
672 * a system call from a "real" process, but the process memory space will
673 * not be free'd until both the parent and the child have exited.
674 */
675 pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
676 {
677 long retval;
679 /* If the parent runs before fn(arg) is called by the child,
680 * the input registers of this function can be clobbered.
681 * So we stash 'fn' and 'arg' into global registers which
682 * will not be modified by the parent.
683 */
684 __asm__ __volatile__("mov %4, %%g2\n\t" /* Save FN into global */
685 "mov %5, %%g3\n\t" /* Save ARG into global */
686 "mov %1, %%g1\n\t" /* Clone syscall nr. */
687 "mov %2, %%o0\n\t" /* Clone flags. */
688 "mov 0, %%o1\n\t" /* usp arg == 0 */
689 "t 0x6d\n\t" /* Linux/Sparc clone(). */
690 "brz,a,pn %%o1, 1f\n\t" /* Parent, just return. */
691 " mov %%o0, %0\n\t"
692 "jmpl %%g2, %%o7\n\t" /* Call the function. */
693 " mov %%g3, %%o0\n\t" /* Set arg in delay. */
694 "mov %3, %%g1\n\t"
695 "t 0x6d\n\t" /* Linux/Sparc exit(). */
696 /* Notreached by child. */
697 "1:" :
698 "=r" (retval) :
699 "i" (__NR_clone), "r" (flags | CLONE_VM | CLONE_UNTRACED),
700 "i" (__NR_exit), "r" (fn), "r" (arg) :
701 "g1", "g2", "g3", "o0", "o1", "memory", "cc");
702 return retval;
703 }
705 /*
706 * fill in the user structure for a core dump..
707 */
708 void dump_thread(struct pt_regs * regs, struct user * dump)
709 {
710 /* Only should be used for SunOS and ancient a.out
711 * SparcLinux binaries... Not worth implementing.
712 */
713 memset(dump, 0, sizeof(struct user));
714 }
716 typedef struct {
717 union {
718 unsigned int pr_regs[32];
719 unsigned long pr_dregs[16];
720 } pr_fr;
721 unsigned int __unused;
722 unsigned int pr_fsr;
723 unsigned char pr_qcnt;
724 unsigned char pr_q_entrysize;
725 unsigned char pr_en;
726 unsigned int pr_q[64];
727 } elf_fpregset_t32;
729 /*
730 * fill in the fpu structure for a core dump.
731 */
732 int dump_fpu (struct pt_regs * regs, elf_fpregset_t * fpregs)
733 {
734 unsigned long *kfpregs = current_thread_info()->fpregs;
735 unsigned long fprs = current_thread_info()->fpsaved[0];
737 if (test_thread_flag(TIF_32BIT)) {
738 elf_fpregset_t32 *fpregs32 = (elf_fpregset_t32 *)fpregs;
740 if (fprs & FPRS_DL)
741 memcpy(&fpregs32->pr_fr.pr_regs[0], kfpregs,
742 sizeof(unsigned int) * 32);
743 else
744 memset(&fpregs32->pr_fr.pr_regs[0], 0,
745 sizeof(unsigned int) * 32);
746 fpregs32->pr_qcnt = 0;
747 fpregs32->pr_q_entrysize = 8;
748 memset(&fpregs32->pr_q[0], 0,
749 (sizeof(unsigned int) * 64));
750 if (fprs & FPRS_FEF) {
751 fpregs32->pr_fsr = (unsigned int) current_thread_info()->xfsr[0];
752 fpregs32->pr_en = 1;
753 } else {
754 fpregs32->pr_fsr = 0;
755 fpregs32->pr_en = 0;
756 }
757 } else {
758 if(fprs & FPRS_DL)
759 memcpy(&fpregs->pr_regs[0], kfpregs,
760 sizeof(unsigned int) * 32);
761 else
762 memset(&fpregs->pr_regs[0], 0,
763 sizeof(unsigned int) * 32);
764 if(fprs & FPRS_DU)
765 memcpy(&fpregs->pr_regs[16], kfpregs+16,
766 sizeof(unsigned int) * 32);
767 else
768 memset(&fpregs->pr_regs[16], 0,
769 sizeof(unsigned int) * 32);
770 if(fprs & FPRS_FEF) {
771 fpregs->pr_fsr = current_thread_info()->xfsr[0];
772 fpregs->pr_gsr = current_thread_info()->gsr[0];
773 } else {
774 fpregs->pr_fsr = fpregs->pr_gsr = 0;
775 }
776 fpregs->pr_fprs = fprs;
777 }
778 return 1;
779 }
781 /*
782 * sparc_execve() executes a new program after the asm stub has set
783 * things up for us. This should basically do what I want it to.
784 */
785 asmlinkage int sparc_execve(struct pt_regs *regs)
786 {
787 int error, base = 0;
788 char *filename;
790 /* User register window flush is done by entry.S */
792 /* Check for indirect call. */
793 if (regs->u_regs[UREG_G1] == 0)
794 base = 1;
796 filename = getname((char __user *)regs->u_regs[base + UREG_I0]);
797 error = PTR_ERR(filename);
798 if (IS_ERR(filename))
799 goto out;
800 error = do_execve(filename,
801 (char __user * __user *)
802 regs->u_regs[base + UREG_I1],
803 (char __user * __user *)
804 regs->u_regs[base + UREG_I2], regs);
805 putname(filename);
806 if (!error) {
807 fprs_write(0);
808 current_thread_info()->xfsr[0] = 0;
809 current_thread_info()->fpsaved[0] = 0;
810 regs->tstate &= ~TSTATE_PEF;
811 task_lock(current);
812 current->ptrace &= ~PT_DTRACE;
813 task_unlock(current);
814 }
815 out:
816 return error;
817 }
819 unsigned long get_wchan(struct task_struct *task)
820 {
821 unsigned long pc, fp, bias = 0;
822 unsigned long thread_info_base;
823 struct reg_window *rw;
824 unsigned long ret = 0;
825 int count = 0;
827 if (!task || task == current ||
828 task->state == TASK_RUNNING)
829 goto out;
831 thread_info_base = (unsigned long) task_stack_page(task);
832 bias = STACK_BIAS;
833 fp = task_thread_info(task)->ksp + bias;
835 do {
836 /* Bogus frame pointer? */
837 if (fp < (thread_info_base + sizeof(struct thread_info)) ||
838 fp >= (thread_info_base + THREAD_SIZE))
839 break;
840 rw = (struct reg_window *) fp;
841 pc = rw->ins[7];
842 if (!in_sched_functions(pc)) {
843 ret = pc;
844 goto out;
845 }
846 fp = rw->ins[6] + bias;
847 } while (++count < 16);
849 out:
850 return ret;
851 }